Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
17988 views
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 <[email protected]>
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
29
#include "stv06xx_st6422.h"
30
31
/* controls */
32
enum e_ctrl {
33
BRIGHTNESS,
34
CONTRAST,
35
GAIN,
36
EXPOSURE,
37
NCTRLS /* number of controls */
38
};
39
40
/* sensor settings */
41
struct st6422_settings {
42
struct gspca_ctrl ctrls[NCTRLS];
43
};
44
45
static struct v4l2_pix_format st6422_mode[] = {
46
/* Note we actually get 124 lines of data, of which we skip the 4st
47
4 as they are garbage */
48
{
49
162,
50
120,
51
V4L2_PIX_FMT_SGRBG8,
52
V4L2_FIELD_NONE,
53
.sizeimage = 162 * 120,
54
.bytesperline = 162,
55
.colorspace = V4L2_COLORSPACE_SRGB,
56
.priv = 1
57
},
58
/* Note we actually get 248 lines of data, of which we skip the 4st
59
4 as they are garbage, and we tell the app it only gets the
60
first 240 of the 244 lines it actually gets, so that it ignores
61
the last 4. */
62
{
63
324,
64
240,
65
V4L2_PIX_FMT_SGRBG8,
66
V4L2_FIELD_NONE,
67
.sizeimage = 324 * 244,
68
.bytesperline = 324,
69
.colorspace = V4L2_COLORSPACE_SRGB,
70
.priv = 0
71
},
72
};
73
74
/* V4L2 controls supported by the driver */
75
static void st6422_set_brightness(struct gspca_dev *gspca_dev);
76
static void st6422_set_contrast(struct gspca_dev *gspca_dev);
77
static void st6422_set_gain(struct gspca_dev *gspca_dev);
78
static void st6422_set_exposure(struct gspca_dev *gspca_dev);
79
80
static const struct ctrl st6422_ctrl[NCTRLS] = {
81
[BRIGHTNESS] = {
82
{
83
.id = V4L2_CID_BRIGHTNESS,
84
.type = V4L2_CTRL_TYPE_INTEGER,
85
.name = "Brightness",
86
.minimum = 0,
87
.maximum = 31,
88
.step = 1,
89
.default_value = 3
90
},
91
.set_control = st6422_set_brightness
92
},
93
[CONTRAST] = {
94
{
95
.id = V4L2_CID_CONTRAST,
96
.type = V4L2_CTRL_TYPE_INTEGER,
97
.name = "Contrast",
98
.minimum = 0,
99
.maximum = 15,
100
.step = 1,
101
.default_value = 11
102
},
103
.set_control = st6422_set_contrast
104
},
105
[GAIN] = {
106
{
107
.id = V4L2_CID_GAIN,
108
.type = V4L2_CTRL_TYPE_INTEGER,
109
.name = "Gain",
110
.minimum = 0,
111
.maximum = 255,
112
.step = 1,
113
.default_value = 64
114
},
115
.set_control = st6422_set_gain
116
},
117
[EXPOSURE] = {
118
{
119
.id = V4L2_CID_EXPOSURE,
120
.type = V4L2_CTRL_TYPE_INTEGER,
121
.name = "Exposure",
122
.minimum = 0,
123
#define EXPOSURE_MAX 1023
124
.maximum = EXPOSURE_MAX,
125
.step = 1,
126
.default_value = 256
127
},
128
.set_control = st6422_set_exposure
129
},
130
};
131
132
static int st6422_probe(struct sd *sd)
133
{
134
struct st6422_settings *sensor_settings;
135
136
if (sd->bridge != BRIDGE_ST6422)
137
return -ENODEV;
138
139
info("st6422 sensor detected");
140
141
sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
142
if (!sensor_settings)
143
return -ENOMEM;
144
145
sd->gspca_dev.cam.cam_mode = st6422_mode;
146
sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
147
sd->gspca_dev.cam.ctrls = sensor_settings->ctrls;
148
sd->desc.ctrls = st6422_ctrl;
149
sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
150
sd->sensor_priv = sensor_settings;
151
152
return 0;
153
}
154
155
static int st6422_init(struct sd *sd)
156
{
157
int err = 0, i;
158
159
const u16 st6422_bridge_init[][2] = {
160
{ STV_ISO_ENABLE, 0x00 }, /* disable capture */
161
{ 0x1436, 0x00 },
162
{ 0x1432, 0x03 }, /* 0x00-0x1F brightness */
163
{ 0x143a, 0xf9 }, /* 0x00-0x0F contrast */
164
{ 0x0509, 0x38 }, /* R */
165
{ 0x050a, 0x38 }, /* G */
166
{ 0x050b, 0x38 }, /* B */
167
{ 0x050c, 0x2a },
168
{ 0x050d, 0x01 },
169
170
171
{ 0x1431, 0x00 }, /* 0x00-0x07 ??? */
172
{ 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */
173
{ 0x1438, 0x18 }, /* 640x480 */
174
/* 18 bayes */
175
/* 10 compressed? */
176
177
{ 0x1439, 0x00 },
178
/* anti-noise? 0xa2 gives a perfect image */
179
180
{ 0x143b, 0x05 },
181
{ 0x143c, 0x00 }, /* 0x00-0x01 - ??? */
182
183
184
/* shutter time 0x0000-0x03FF */
185
/* low value give good picures on moving objects (but requires much light) */
186
/* high value gives good picures in darkness (but tends to be overexposed) */
187
{ 0x143e, 0x01 },
188
{ 0x143d, 0x00 },
189
190
{ 0x1442, 0xe2 },
191
/* write: 1x1x xxxx */
192
/* read: 1x1x xxxx */
193
/* bit 5 == button pressed and hold if 0 */
194
/* write 0xe2,0xea */
195
196
/* 0x144a */
197
/* 0x00 init */
198
/* bit 7 == button has been pressed, but not handled */
199
200
/* interrupt */
201
/* if(urb->iso_frame_desc[i].status == 0x80) { */
202
/* if(urb->iso_frame_desc[i].status == 0x88) { */
203
204
{ 0x1500, 0xd0 },
205
{ 0x1500, 0xd0 },
206
{ 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */
207
208
{ 0x1501, 0xaf },
209
/* high val-> light area gets darker */
210
/* low val -> light area gets lighter */
211
{ 0x1502, 0xc2 },
212
/* high val-> light area gets darker */
213
/* low val -> light area gets lighter */
214
{ 0x1503, 0x45 },
215
/* high val-> light area gets darker */
216
/* low val -> light area gets lighter */
217
{ 0x1505, 0x02 },
218
/* 2 : 324x248 80352 bytes */
219
/* 7 : 248x162 40176 bytes */
220
/* c+f: 162*124 20088 bytes */
221
222
{ 0x150e, 0x8e },
223
{ 0x150f, 0x37 },
224
{ 0x15c0, 0x00 },
225
{ 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */
226
227
228
{ 0x143f, 0x01 }, /* commit settings */
229
230
};
231
232
for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
233
err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
234
st6422_bridge_init[i][1]);
235
}
236
237
return err;
238
}
239
240
static void st6422_disconnect(struct sd *sd)
241
{
242
sd->sensor = NULL;
243
kfree(sd->sensor_priv);
244
}
245
246
static int setbrightness(struct sd *sd)
247
{
248
struct st6422_settings *sensor_settings = sd->sensor_priv;
249
250
/* val goes from 0 -> 31 */
251
return stv06xx_write_bridge(sd, 0x1432,
252
sensor_settings->ctrls[BRIGHTNESS].val);
253
}
254
255
static int setcontrast(struct sd *sd)
256
{
257
struct st6422_settings *sensor_settings = sd->sensor_priv;
258
259
/* Val goes from 0 -> 15 */
260
return stv06xx_write_bridge(sd, 0x143a,
261
sensor_settings->ctrls[CONTRAST].val | 0xf0);
262
}
263
264
static int setgain(struct sd *sd)
265
{
266
struct st6422_settings *sensor_settings = sd->sensor_priv;
267
u8 gain;
268
int err;
269
270
gain = sensor_settings->ctrls[GAIN].val;
271
272
/* Set red, green, blue, gain */
273
err = stv06xx_write_bridge(sd, 0x0509, gain);
274
if (err < 0)
275
return err;
276
277
err = stv06xx_write_bridge(sd, 0x050a, gain);
278
if (err < 0)
279
return err;
280
281
err = stv06xx_write_bridge(sd, 0x050b, gain);
282
if (err < 0)
283
return err;
284
285
/* 2 mystery writes */
286
err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
287
if (err < 0)
288
return err;
289
290
return stv06xx_write_bridge(sd, 0x050d, 0x01);
291
}
292
293
static int setexposure(struct sd *sd)
294
{
295
struct st6422_settings *sensor_settings = sd->sensor_priv;
296
u16 expo;
297
int err;
298
299
expo = sensor_settings->ctrls[EXPOSURE].val;
300
err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
301
if (err < 0)
302
return err;
303
304
return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
305
}
306
307
static int st6422_start(struct sd *sd)
308
{
309
int err;
310
struct cam *cam = &sd->gspca_dev.cam;
311
312
if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
313
err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
314
else
315
err = stv06xx_write_bridge(sd, 0x1505, 0x02);
316
if (err < 0)
317
return err;
318
319
err = setbrightness(sd);
320
if (err < 0)
321
return err;
322
323
err = setcontrast(sd);
324
if (err < 0)
325
return err;
326
327
err = setexposure(sd);
328
if (err < 0)
329
return err;
330
331
err = setgain(sd);
332
if (err < 0)
333
return err;
334
335
/* commit settings */
336
err = stv06xx_write_bridge(sd, 0x143f, 0x01);
337
return (err < 0) ? err : 0;
338
}
339
340
static int st6422_stop(struct sd *sd)
341
{
342
PDEBUG(D_STREAM, "Halting stream");
343
344
return 0;
345
}
346
347
static void st6422_set_brightness(struct gspca_dev *gspca_dev)
348
{
349
int err;
350
struct sd *sd = (struct sd *) gspca_dev;
351
352
err = setbrightness(sd);
353
354
/* commit settings */
355
if (err >= 0)
356
err = stv06xx_write_bridge(sd, 0x143f, 0x01);
357
358
gspca_dev->usb_err = err;
359
}
360
361
static void st6422_set_contrast(struct gspca_dev *gspca_dev)
362
{
363
int err;
364
struct sd *sd = (struct sd *) gspca_dev;
365
366
err = setcontrast(sd);
367
368
/* commit settings */
369
if (err >= 0)
370
err = stv06xx_write_bridge(sd, 0x143f, 0x01);
371
372
gspca_dev->usb_err = err;
373
}
374
375
static void st6422_set_gain(struct gspca_dev *gspca_dev)
376
{
377
int err;
378
struct sd *sd = (struct sd *) gspca_dev;
379
380
err = setgain(sd);
381
382
/* commit settings */
383
if (err >= 0)
384
err = stv06xx_write_bridge(sd, 0x143f, 0x01);
385
386
gspca_dev->usb_err = err;
387
}
388
389
static void st6422_set_exposure(struct gspca_dev *gspca_dev)
390
{
391
int err;
392
struct sd *sd = (struct sd *) gspca_dev;
393
394
err = setexposure(sd);
395
396
/* commit settings */
397
if (err >= 0)
398
err = stv06xx_write_bridge(sd, 0x143f, 0x01);
399
400
gspca_dev->usb_err = err;
401
}
402
403