1 |
/* |
2 |
* drivers/media/video/ov3640.c |
3 |
* |
4 |
* ov3640 sensor driver |
5 |
* |
6 |
* |
7 |
* Copyright (C) 2008 Texas Instruments. |
8 |
* |
9 |
* Leverage ov3640.c |
10 |
* |
11 |
* This file is licensed under the terms of the GNU General Public License |
12 |
* version 2. This program is licensed "as is" without any warranty of any |
13 |
* kind, whether express or implied. |
14 |
*/ |
15 |
|
16 |
#include |
17 |
#include |
18 |
#include |
19 |
#include "ov3640.h" |
20 |
#include "omap34xxcam.h" |
21 |
#include "isp/isp.h" |
22 |
#include "isp/ispcsi2.h" |
23 |
|
24 |
#define OV3640_DRIVER_NAME "ov3640" |
25 |
#define MOD_NAME "OV3640: " |
26 |
|
27 |
#define I2C_M_WR 0 |
28 |
|
29 |
/** |
30 |
* struct ov3640_sensor - main structure for storage of sensor information |
31 |
* @pdata: access functions and data for platform level information |
32 |
* @v4l2_int_device: V4L2 device structure structure |
33 |
* @i2c_client: iic client device structure |
34 |
* @pix: V4L2 pixel format information structure |
35 |
* @timeperframe: time per frame expressed as V4L fraction |
36 |
* @isize: base image size |
37 |
* @ver: ov3640 chip version |
38 |
* @width: configured width |
39 |
* @height: configuredheight |
40 |
* @vsize: vertical size for the image |
41 |
* @hsize: horizontal size for the image |
42 |
* @crop_rect: crop rectangle specifying the left,top and width and height |
43 |
*/ |
44 |
struct ov3640_sensor {
|
45 |
const struct ov3640_platform_data *pdata;
|
46 |
struct v4l2_int_device *v4l2_int_device;
|
47 |
struct i2c_client *i2c_client;
|
48 |
struct v4l2_pix_format pix;
|
49 |
struct v4l2_fract timeperframe;
|
50 |
int isize;
|
51 |
int ver;
|
52 |
int fps;
|
53 |
unsigned long width;
|
54 |
unsigned long height;
|
55 |
unsigned long vsize;
|
56 |
unsigned long hsize;
|
57 |
struct v4l2_rect crop_rect;
|
58 |
int state;
|
59 |
}; |
60 |
|
61 |
static struct ov3640_sensor ov3640;
|
62 |
static struct i2c_driver ov3640sensor_i2c_driver;
|
63 |
static unsigned long xclk_current = OV3640_XCLK_MIN;
|
64 |
|
65 |
/* List of image formats supported by OV3640 sensor */ |
66 |
const static struct v4l2_fmtdesc ov3640_formats[] = {
|
67 |
#if OV3640_RAW_MODE |
68 |
{
|
69 |
.description = "RAW10",
|
70 |
.pixelformat = V4L2_PIX_FMT_SGRBG10,
|
71 |
},
|
72 |
#else |
73 |
{
|
74 |
/* Note: V4L2 defines RGB565 as:
|
75 |
* |
76 |
* Byte 0 Byte 1 |
77 |
* g2 g1 g0 r4 r3 r2 r1 r0 b4 b3 b2 b1 b0 g5 g4 g3 |
78 |
* |
79 |
* We interpret RGB565 as: |
80 |
* |
81 |
* Byte 0 Byte 1 |
82 |
* g2 g1 g0 b4 b3 b2 b1 b0 r4 r3 r2 r1 r0 g5 g4 g3 |
83 |
*/ |
84 |
.description = "RGB565, le",
|
85 |
.pixelformat = V4L2_PIX_FMT_RGB565,
|
86 |
},
|
87 |
{
|
88 |
/* Note: V4L2 defines RGB565X as:
|
89 |
* |
90 |
* Byte 0 Byte 1 |
91 |
* b4 b3 b2 b1 b0 g5 g4 g3 g2 g1 g0 r4 r3 r2 r1 r0 |
92 |
* |
93 |
* We interpret RGB565X as: |
94 |
* |
95 |
* Byte 0 Byte 1 |
96 |
* r4 r3 r2 r1 r0 g5 g4 g3 g2 g1 g0 b4 b3 b2 b1 b0 |
97 |
*/ |
98 |
.description = "RGB565, be",
|
99 |
.pixelformat = V4L2_PIX_FMT_RGB565X,
|
100 |
},
|
101 |
{
|
102 |
.description = "YUYV (YUV 4:2:2), packed",
|
103 |
.pixelformat = V4L2_PIX_FMT_YUYV,
|
104 |
},
|
105 |
{
|
106 |
.description = "UYVY, packed",
|
107 |
.pixelformat = V4L2_PIX_FMT_UYVY,
|
108 |
},
|
109 |
{
|
110 |
/* Note: V4L2 defines RGB555 as:
|
111 |
* |
112 |
* Byte 0 Byte 1 |
113 |
* g2 g1 g0 r4 r3 r2 r1 r0 x b4 b3 b2 b1 b0 g4 g3 |
114 |
* |
115 |
* We interpret RGB555 as: |
116 |
* |
117 |
* Byte 0 Byte 1 |
118 |
* g2 g1 g0 b4 b3 b2 b1 b0 x r4 r3 r2 r1 r0 g4 g3 |
119 |
*/ |
120 |
.description = "RGB555, le",
|
121 |
.pixelformat = V4L2_PIX_FMT_RGB555,
|
122 |
},
|
123 |
{
|
124 |
/* Note: V4L2 defines RGB555X as:
|
125 |
* |
126 |
* Byte 0 Byte 1 |
127 |
* x b4 b3 b2 b1 b0 g4 g3 g2 g1 g0 r4 r3 r2 r1 r0 |
128 |
* |
129 |
* We interpret RGB555X as: |
130 |
* |
131 |
* Byte 0 Byte 1 |
132 |
* x r4 r3 r2 r1 r0 g4 g3 g2 g1 g0 b4 b3 b2 b1 b0 |
133 |
*/ |
134 |
.description = "RGB555, be",
|
135 |
.pixelformat = V4L2_PIX_FMT_RGB555X,
|
136 |
},
|
137 |
#endif |
138 |
};
|
139 |
|
140 |
#define NUM_CAPTURE_FORMATS (sizeof(ov3640_formats) / sizeof(ov3640_formats[0])) |
141 |
|
142 |
/* register initialization tables for ov3640 */ |
143 |
#define OV3640_REG_TERM 0xFFFF /* terminating list entry for reg */
|
144 |
#define OV3640_VAL_TERM 0xFF /* terminating list entry for val */
|
145 |
|
146 |
const static struct ov3640_reg ov3640_out_xga[] = {
|
147 |
{OV3640_ISP_XOUT_H, 0x04}, /* ISP_XOUT */
|
148 |
{OV3640_ISP_XOUT_L, 0x00}, /* ISP_XOUT */
|
149 |
{OV3640_ISP_YOUT_H, 0x03}, /* ISP_YOUT */
|
150 |
{OV3640_ISP_YOUT_L, 0x00}, /* ISP_YOUT */
|
151 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
152 |
}; |
153 |
|
154 |
const static struct ov3640_reg ov3640_out_qxga[] = {
|
155 |
{OV3640_ISP_XOUT_H, 0x08}, /* ISP_XOUT */
|
156 |
{OV3640_ISP_XOUT_L, 0x00}, /* ISP_XOUT */
|
157 |
{OV3640_ISP_YOUT_H, 0x06}, /* ISP_YOUT */
|
158 |
{OV3640_ISP_YOUT_L, 0x00}, /* ISP_YOUT */
|
159 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
160 |
}; |
161 |
|
162 |
/* Brightness Settings - 7 levels */ |
163 |
const static struct ov3640_reg brightness[7][5] = {
|
164 |
{
|
165 |
{OV3640_SDE_CTRL, 0x04},
|
166 |
{OV3640_SGNSET, 0x09},
|
167 |
{OV3640_YBRIGHT, 0x30},
|
168 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
169 |
},
|
170 |
{
|
171 |
{OV3640_SDE_CTRL, 0x04},
|
172 |
{OV3640_SGNSET, 0x09},
|
173 |
{OV3640_YBRIGHT, 0x20},
|
174 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
175 |
},
|
176 |
{
|
177 |
{OV3640_SDE_CTRL, 0x04},
|
178 |
{OV3640_SGNSET, 0x09},
|
179 |
{OV3640_YBRIGHT, 0x10},
|
180 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
181 |
},
|
182 |
{
|
183 |
{OV3640_SDE_CTRL, 0x04},
|
184 |
{OV3640_SGNSET, 0x01},
|
185 |
{OV3640_YBRIGHT, 0x00},
|
186 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
187 |
},
|
188 |
{
|
189 |
{OV3640_SDE_CTRL, 0x04},
|
190 |
{OV3640_SGNSET, 0x01},
|
191 |
{OV3640_YBRIGHT, 0x10},
|
192 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
193 |
},
|
194 |
{
|
195 |
{OV3640_SDE_CTRL, 0x04},
|
196 |
{OV3640_SGNSET, 0x01},
|
197 |
{OV3640_YBRIGHT, 0x20},
|
198 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
199 |
},
|
200 |
{
|
201 |
{OV3640_SDE_CTRL, 0x04},
|
202 |
{OV3640_SGNSET, 0x01},
|
203 |
{OV3640_YBRIGHT, 0x30},
|
204 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
205 |
},
|
206 |
}; |
207 |
|
208 |
/* Contrast Settings - 7 levels */ |
209 |
const static struct ov3640_reg contrast[7][5] = {
|
210 |
{
|
211 |
{OV3640_SDE_CTRL, 0x04},
|
212 |
{OV3640_YOFFSET, 0x14},
|
213 |
{OV3640_YGAIN, 0x14},
|
214 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
215 |
},
|
216 |
{
|
217 |
{OV3640_SDE_CTRL, 0x04},
|
218 |
{OV3640_YOFFSET, 0x18},
|
219 |
{OV3640_YGAIN, 0x18},
|
220 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
221 |
},
|
222 |
{
|
223 |
{OV3640_SDE_CTRL, 0x04},
|
224 |
{OV3640_YOFFSET, 0x1c},
|
225 |
{OV3640_YGAIN, 0x1c},
|
226 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
227 |
},
|
228 |
{
|
229 |
{OV3640_SDE_CTRL, 0x04},
|
230 |
{OV3640_YOFFSET, 0x20},
|
231 |
{OV3640_YGAIN, 0x20},
|
232 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
233 |
},
|
234 |
{
|
235 |
{OV3640_SDE_CTRL, 0x04},
|
236 |
{OV3640_YOFFSET, 0x24},
|
237 |
{OV3640_YGAIN, 0x24},
|
238 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
239 |
},
|
240 |
{
|
241 |
{OV3640_SDE_CTRL, 0x04},
|
242 |
{OV3640_YOFFSET, 0x28},
|
243 |
{OV3640_YGAIN, 0x28},
|
244 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
245 |
},
|
246 |
{
|
247 |
{OV3640_SDE_CTRL, 0x04},
|
248 |
{OV3640_YOFFSET, 0x2c},
|
249 |
{OV3640_YGAIN, 0x2c},
|
250 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
251 |
},
|
252 |
}; |
253 |
|
254 |
/* Color Settings - 3 colors */ |
255 |
const static struct ov3640_reg colors[3][5] = {
|
256 |
{
|
257 |
{OV3640_SDE_CTRL, 0x00},
|
258 |
{OV3640_UREG, 0x80},
|
259 |
{OV3640_VREG, 0x80},
|
260 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
261 |
},
|
262 |
{
|
263 |
{OV3640_SDE_CTRL, 0x18},
|
264 |
{OV3640_UREG, 0x40},
|
265 |
{OV3640_VREG, 0xa6},
|
266 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
267 |
},
|
268 |
{
|
269 |
{OV3640_SDE_CTRL, 0x18},
|
270 |
{OV3640_UREG, 0x80},
|
271 |
{OV3640_VREG, 0x80},
|
272 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
273 |
},
|
274 |
}; |
275 |
|
276 |
/* Average Based Algorithm - Based on target Luminance */ |
277 |
const static struct ov3640_reg exposure_avg[11][5] = {
|
278 |
/* -1.7EV */
|
279 |
{
|
280 |
{OV3640_HISTO7, 0x00},
|
281 |
{OV3640_WPT_HISH, 0x10},
|
282 |
{OV3640_BPT_HISL, 0x08},
|
283 |
{OV3640_VPT, 0x21},
|
284 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
285 |
},
|
286 |
/* -1.3EV */
|
287 |
{
|
288 |
{OV3640_HISTO7, 0x00},
|
289 |
{OV3640_WPT_HISH, 0x18},
|
290 |
{OV3640_BPT_HISL, 0x10},
|
291 |
{OV3640_VPT, 0x31},
|
292 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
293 |
},
|
294 |
/* -1.0EV */
|
295 |
{
|
296 |
{OV3640_HISTO7, 0x00},
|
297 |
{OV3640_WPT_HISH, 0x20},
|
298 |
{OV3640_BPT_HISL, 0x18},
|
299 |
{OV3640_VPT, 0x41},
|
300 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
301 |
},
|
302 |
/* -0.7EV */
|
303 |
{
|
304 |
{OV3640_HISTO7, 0x00},
|
305 |
{OV3640_WPT_HISH, 0x28},
|
306 |
{OV3640_BPT_HISL, 0x20},
|
307 |
{OV3640_VPT, 0x51},
|
308 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
309 |
},
|
310 |
/* -0.3EV */
|
311 |
{
|
312 |
{OV3640_HISTO7, 0x00},
|
313 |
{OV3640_WPT_HISH, 0x30},
|
314 |
{OV3640_BPT_HISL, 0x28},
|
315 |
{OV3640_VPT, 0x61},
|
316 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
317 |
},
|
318 |
/* default */
|
319 |
{
|
320 |
{OV3640_HISTO7, 0x00},
|
321 |
{OV3640_WPT_HISH, 0x38},
|
322 |
{OV3640_BPT_HISL, 0x30},
|
323 |
{OV3640_VPT, 0x61},
|
324 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
325 |
},
|
326 |
/* 0.3EV */
|
327 |
{
|
328 |
{OV3640_HISTO7, 0x00},
|
329 |
{OV3640_WPT_HISH, 0x40},
|
330 |
{OV3640_BPT_HISL, 0x38},
|
331 |
{OV3640_VPT, 0x71},
|
332 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
333 |
},
|
334 |
/* 0.7EV */
|
335 |
{
|
336 |
{OV3640_HISTO7, 0x00},
|
337 |
{OV3640_WPT_HISH, 0x48},
|
338 |
{OV3640_BPT_HISL, 0x40},
|
339 |
{OV3640_VPT, 0x81},
|
340 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
341 |
},
|
342 |
/* 1.0EV */
|
343 |
{
|
344 |
{OV3640_HISTO7, 0x00},
|
345 |
{OV3640_WPT_HISH, 0x50},
|
346 |
{OV3640_BPT_HISL, 0x48},
|
347 |
{OV3640_VPT, 0x91},
|
348 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
349 |
},
|
350 |
/* 1.3EV */
|
351 |
{
|
352 |
{OV3640_HISTO7, 0x00},
|
353 |
{OV3640_WPT_HISH, 0x58},
|
354 |
{OV3640_BPT_HISL, 0x50},
|
355 |
{OV3640_VPT, 0x91},
|
356 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
357 |
},
|
358 |
/* 1.7EV */
|
359 |
{
|
360 |
{OV3640_HISTO7, 0x00},
|
361 |
{OV3640_WPT_HISH, 0x60},
|
362 |
{OV3640_BPT_HISL, 0x58},
|
363 |
{OV3640_VPT, 0xa1},
|
364 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
365 |
},
|
366 |
}; |
367 |
|
368 |
/* Histogram Based Algorithm - Based on histogram and probability */ |
369 |
const static struct ov3640_reg exposure_hist[11][5] = {
|
370 |
/* -1.7EV */
|
371 |
{
|
372 |
{OV3640_HISTO7, 0x80},
|
373 |
{OV3640_WPT_HISH, 0x58},
|
374 |
{OV3640_BPT_HISL, 0x38},
|
375 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
376 |
},
|
377 |
/* -1.3EV */
|
378 |
{
|
379 |
{OV3640_HISTO7, 0x80},
|
380 |
{OV3640_WPT_HISH, 0x60},
|
381 |
{OV3640_BPT_HISL, 0x40},
|
382 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
383 |
},
|
384 |
/* -1.0EV */
|
385 |
{
|
386 |
{OV3640_HISTO7, 0x80},
|
387 |
{OV3640_WPT_HISH, 0x68},
|
388 |
{OV3640_BPT_HISL, 0x48},
|
389 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
390 |
},
|
391 |
/* -0.7EV */
|
392 |
{
|
393 |
{OV3640_HISTO7, 0x80},
|
394 |
{OV3640_WPT_HISH, 0x70},
|
395 |
{OV3640_BPT_HISL, 0x50},
|
396 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
397 |
},
|
398 |
/* -0.3EV */
|
399 |
{
|
400 |
{OV3640_HISTO7, 0x80},
|
401 |
{OV3640_WPT_HISH, 0x78},
|
402 |
{OV3640_BPT_HISL, 0x58},
|
403 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
404 |
},
|
405 |
/* default */
|
406 |
{
|
407 |
{OV3640_HISTO7, 0x80},
|
408 |
{OV3640_WPT_HISH, 0x80},
|
409 |
{OV3640_BPT_HISL, 0x60},
|
410 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
411 |
},
|
412 |
/* 0.3EV */
|
413 |
{
|
414 |
{OV3640_HISTO7, 0x80},
|
415 |
{OV3640_WPT_HISH, 0x88},
|
416 |
{OV3640_BPT_HISL, 0x68},
|
417 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
418 |
},
|
419 |
/* 0.7EV */
|
420 |
{
|
421 |
{OV3640_HISTO7, 0x80},
|
422 |
{OV3640_WPT_HISH, 0x90},
|
423 |
{OV3640_BPT_HISL, 0x70},
|
424 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
425 |
},
|
426 |
/* 1.0EV */
|
427 |
{
|
428 |
{OV3640_HISTO7, 0x80},
|
429 |
{OV3640_WPT_HISH, 0x98},
|
430 |
{OV3640_BPT_HISL, 0x78},
|
431 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
432 |
},
|
433 |
/* 1.3EV */
|
434 |
{
|
435 |
{OV3640_HISTO7, 0x80},
|
436 |
{OV3640_WPT_HISH, 0xa0},
|
437 |
{OV3640_BPT_HISL, 0x80},
|
438 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
439 |
},
|
440 |
/* 1.7EV */
|
441 |
{
|
442 |
{OV3640_HISTO7, 0x80},
|
443 |
{OV3640_WPT_HISH, 0xa8},
|
444 |
{OV3640_BPT_HISL, 0x88},
|
445 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
446 |
},
|
447 |
}; |
448 |
|
449 |
/* ov3640 register configuration for combinations of pixel format and |
450 |
* image size |
451 |
*/ |
452 |
|
453 |
const static struct ov3640_reg qxga_yuv[] = {
|
454 |
{OV3640_SC_CTRL0, 0x02},
|
455 |
{OV3640_DSP_CTRL_4, 0xFC},
|
456 |
{OV3640_FMT_MUX_CTRL0, 0x00},
|
457 |
{OV3640_FMT_CTRL00, 0x00},
|
458 |
{OV3640_OUT_CTRL01, OV3640_OUT_CTRL01_MIPIBIT8},
|
459 |
{OV3640_VTS_H, 0x06},
|
460 |
{OV3640_VTS_L, 0x20},
|
461 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
462 |
}; |
463 |
|
464 |
const static struct ov3640_reg qxga_565[] = {
|
465 |
{OV3640_SC_CTRL0, 0x02},
|
466 |
{OV3640_DSP_CTRL_4, 0xFC},
|
467 |
{OV3640_FMT_MUX_CTRL0, 0x01},
|
468 |
{OV3640_FMT_CTRL00, 0x11},
|
469 |
{OV3640_OUT_CTRL01, OV3640_OUT_CTRL01_MIPIBIT8},
|
470 |
{OV3640_VTS_H, 0x06},
|
471 |
{OV3640_VTS_L, 0x20},
|
472 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
473 |
}; |
474 |
|
475 |
const static struct ov3640_reg qxga_555[] = {
|
476 |
{OV3640_SC_CTRL0, 0x02},
|
477 |
{OV3640_DSP_CTRL_4, 0xFC},
|
478 |
{OV3640_FMT_MUX_CTRL0, 0x01},
|
479 |
{OV3640_FMT_CTRL00, 0x13},
|
480 |
{OV3640_OUT_CTRL01, OV3640_OUT_CTRL01_MIPIBIT8},
|
481 |
{OV3640_VTS_H, 0x06},
|
482 |
{OV3640_VTS_L, 0x20},
|
483 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
484 |
}; |
485 |
|
486 |
const static struct ov3640_reg qxga_raw10[] = {
|
487 |
{OV3640_SC_CTRL0, 0x22},
|
488 |
{OV3640_DSP_CTRL_4, 0x01},
|
489 |
{OV3640_FMT_MUX_CTRL0, 0x04},
|
490 |
{OV3640_FMT_CTRL00, 0x18},
|
491 |
{OV3640_OUT_CTRL01, 0x00},
|
492 |
{OV3640_VTS_H, 0x06},
|
493 |
{OV3640_VTS_L, 0x20},
|
494 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
495 |
}; |
496 |
|
497 |
const static struct ov3640_reg xga_yuv[] = {
|
498 |
{OV3640_SC_CTRL0, 0x02},
|
499 |
{OV3640_DSP_CTRL_4, 0xFC},
|
500 |
{OV3640_FMT_MUX_CTRL0, 0x00},
|
501 |
{OV3640_FMT_CTRL00, 0x00},
|
502 |
{OV3640_OUT_CTRL01, OV3640_OUT_CTRL01_MIPIBIT8},
|
503 |
{OV3640_VTS_H, 0x03},
|
504 |
{OV3640_VTS_L, 0x10},
|
505 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
506 |
}; |
507 |
|
508 |
const static struct ov3640_reg xga_565[] = {
|
509 |
{OV3640_SC_CTRL0, 0x02},
|
510 |
{OV3640_DSP_CTRL_4, 0xFC},
|
511 |
{OV3640_FMT_MUX_CTRL0, 0x01},
|
512 |
{OV3640_FMT_CTRL00, 0x11},
|
513 |
{OV3640_OUT_CTRL01, OV3640_OUT_CTRL01_MIPIBIT8},
|
514 |
{OV3640_VTS_H, 0x03},
|
515 |
{OV3640_VTS_L, 0x10},
|
516 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
517 |
}; |
518 |
|
519 |
const static struct ov3640_reg xga_555[] = {
|
520 |
{OV3640_SC_CTRL0, 0x02},
|
521 |
{OV3640_DSP_CTRL_4, 0xFC},
|
522 |
{OV3640_FMT_MUX_CTRL0, 0x01},
|
523 |
{OV3640_FMT_CTRL00, 0x13},
|
524 |
{OV3640_OUT_CTRL01, OV3640_OUT_CTRL01_MIPIBIT8},
|
525 |
{OV3640_VTS_H, 0x03},
|
526 |
{OV3640_VTS_L, 0x10},
|
527 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
528 |
}; |
529 |
|
530 |
const static struct ov3640_reg xga_raw10[] = {
|
531 |
{OV3640_SC_CTRL0, 0x22},
|
532 |
{OV3640_DSP_CTRL_4, 0x01},
|
533 |
{OV3640_FMT_MUX_CTRL0, 0x04},
|
534 |
{OV3640_FMT_CTRL00, 0x18},
|
535 |
{OV3640_OUT_CTRL01, 0x00},
|
536 |
{OV3640_VTS_H, 0x03},
|
537 |
{OV3640_VTS_L, 0x10},
|
538 |
{OV3640_REG_TERM, OV3640_VAL_TERM}
|
539 |
}; |
540 |
|
541 |
const static struct ov3640_reg |
542 |
*ov3640_reg_init[OV_NUM_PIXEL_FORMATS][OV_NUM_IMAGE_SIZES] = {
|
543 |
{xga_yuv, qxga_yuv},
|
544 |
{xga_565, qxga_565},
|
545 |
{xga_555, qxga_555},
|
546 |
{xga_raw10, qxga_raw10}
|
547 |
}; |
548 |
|
549 |
/* |
550 |
* struct vcontrol - Video controls |
551 |
* @v4l2_queryctrl: V4L2 VIDIOC_QUERYCTRL ioctl structure |
552 |
* @current_value: current value of this control |
553 |
*/ |
554 |
static struct vcontrol {
|
555 |
struct v4l2_queryctrl qc;
|
556 |
int current_value;
|
557 |
} video_control[] = {
|
558 |
#if (OV3640_RAW_MODE == 0) |
559 |
{
|
560 |
{
|
561 |
.id = V4L2_CID_BRIGHTNESS,
|
562 |
.type = V4L2_CTRL_TYPE_INTEGER,
|
563 |
.name = "Brightness",
|
564 |
.minimum = OV3640_MIN_BRIGHT,
|
565 |
.maximum = OV3640_MAX_BRIGHT,
|
566 |
.step = OV3640_BRIGHT_STEP,
|
567 |
.default_value = OV3640_DEF_BRIGHT,
|
568 |
},
|
569 |
.current_value = OV3640_DEF_BRIGHT,
|
570 |
},
|
571 |
{
|
572 |
{
|
573 |
.id = V4L2_CID_CONTRAST,
|
574 |
.type = V4L2_CTRL_TYPE_INTEGER,
|
575 |
.name = "Contrast",
|
576 |
.minimum = OV3640_MIN_CONTRAST,
|
577 |
.maximum = OV3640_MAX_CONTRAST,
|
578 |
.step = OV3640_CONTRAST_STEP,
|
579 |
.default_value = OV3640_DEF_CONTRAST,
|
580 |
},
|
581 |
.current_value = OV3640_DEF_CONTRAST,
|
582 |
},
|
583 |
{
|
584 |
{
|
585 |
.id = V4L2_CID_PRIVATE_BASE,
|
586 |
.type = V4L2_CTRL_TYPE_INTEGER,
|
587 |
.name = "Color Effects",
|
588 |
.minimum = OV3640_MIN_COLOR,
|
589 |
.maximum = OV3640_MAX_COLOR,
|
590 |
.step = OV3640_COLOR_STEP,
|
591 |
.default_value = OV3640_DEF_COLOR,
|
592 |
},
|
593 |
.current_value = OV3640_DEF_COLOR,
|
594 |
}
|
595 |
#endif |
596 |
};
|
597 |
|
598 |
/* |
599 |
* find_vctrl - Finds the requested ID in the video control structure array |
600 |
* @id: ID of control to search the video control array. |
601 |
* |
602 |
* Returns the index of the requested ID from the control structure array |
603 |
*/ |
604 |
static int find_vctrl(int id)
|
605 |
{ |
606 |
int i = 0;
|
607 |
|
608 |
if (id < V4L2_CID_BASE)
|
609 |
return -EDOM;
|
610 |
|
611 |
for (i = (ARRAY_SIZE(video_control) - 1); i >= 0; i--)
|
612 |
if (video_control[i].qc.id == id)
|
613 |
break;
|
614 |
if (i < 0)
|
615 |
i = -EINVAL;
|
616 |
return i;
|
617 |
} |
618 |
|
619 |
/* |
620 |
* Read a value from a register in ov3640 sensor device. |
621 |
* The value is returned in 'val'. |
622 |
* Returns zero if successful, or non-zero otherwise. |
623 |
*/ |
624 |
static int ov3640_read_reg(struct i2c_client *client, u16 data_length, u16 reg,
|
625 |
u32 *val)
|
626 |
{ |
627 |
int err = 0;
|
628 |
struct i2c_msg msg[1];
|
629 |
unsigned char data[4];
|
630 |
|
631 |
if (!client->adapter)
|
632 |
return -ENODEV;
|
633 |
|
634 |
msg->addr = client->addr;
|
635 |
msg->flags = I2C_M_WR;
|
636 |
msg->len = 2;
|
637 |
msg->buf = data;
|
638 |
|
639 |
/* High byte goes out first */
|
640 |
data[0] = (u8) (reg >> 8);
|
641 |
data[1] = (u8) (reg & 0xff);
|
642 |
|
643 |
err = i2c_transfer(client->adapter, msg, 1);
|
644 |
if (err >= 0) {
|
645 |
mdelay(3);
|
646 |
msg->flags = I2C_M_RD;
|
647 |
msg->len = data_length;
|
648 |
err = i2c_transfer(client->adapter, msg, 1);
|
649 |
}
|
650 |
if (err >= 0) {
|
651 |
*val = 0;
|
652 |
/* High byte comes first */
|
653 |
if (data_length == 1)
|
654 |
*val = data[0];
|
655 |
else if (data_length == 2)
|
656 |
*val = data[1] + (data[0] << 8);
|
657 |
else
|
658 |
*val = data[3] + (data[2] << 8) +
|
659 |
(data[1] << 16) + (data[0] << 24);
|
660 |
return 0;
|
661 |
}
|
662 |
dev_err(&client->dev, "read from offset 0x%x error %d", reg, err);
|
663 |
return err;
|
664 |
} |
665 |
|
666 |
/* Write a value to a register in ov3640 sensor device. |
667 |
* @client: i2c driver client structure. |
668 |
* @reg: Address of the register to read value from. |
669 |
* @val: Value to be written to a specific register. |
670 |
* Returns zero if successful, or non-zero otherwise. |
671 |
*/ |
672 |
static int ov3640_write_reg(struct i2c_client *client, u16 reg, u8 val)
|
673 |
{ |
674 |
int err = 0;
|
675 |
struct i2c_msg msg[1];
|
676 |
unsigned char data[3];
|
677 |
int retries = 0;
|
678 |
|
679 |
if (!client->adapter)
|
680 |
return -ENODEV;
|
681 |
retry: |
682 |
msg->addr = client->addr;
|
683 |
msg->flags = I2C_M_WR;
|
684 |
msg->len = 3;
|
685 |
msg->buf = data;
|
686 |
|
687 |
/* high byte goes out first */
|
688 |
data[0] = (u8) (reg >> 8);
|
689 |
data[1] = (u8) (reg & 0xff);
|
690 |
data[2] = val;
|
691 |
|
692 |
err = i2c_transfer(client->adapter, msg, 1);
|
693 |
udelay(50);
|
694 |
|
695 |
if (err >= 0)
|
696 |
return 0;
|
697 |
|
698 |
if (retries <= 5) {
|
699 |
dev_dbg(&client->dev, "Retrying I2C... %d", retries);
|
700 |
retries++;
|
701 |
set_current_state(TASK_UNINTERRUPTIBLE);
|
702 |
schedule_timeout(msecs_to_jiffies(20));
|
703 |
goto retry;
|
704 |
}
|
705 |
|
706 |
return err;
|
707 |
} |
708 |
|
709 |
/* |
710 |
* Initialize a list of ov3640 registers. |
711 |
* The list of registers is terminated by the pair of values |
712 |
* {OV3640_REG_TERM, OV3640_VAL_TERM}. |
713 |
* @client: i2c driver client structure. |
714 |
* @reglist[]: List of address of the registers to write data. |
715 |
* Returns zero if successful, or non-zero otherwise. |
716 |
*/ |
717 |
static int ov3640_write_regs(struct i2c_client *client,
|
718 |
const struct ov3640_reg reglist[])
|
719 |
{ |
720 |
int err = 0;
|
721 |
const struct ov3640_reg *next = reglist;
|
722 |
|
723 |
while (!((next->reg == OV3640_REG_TERM)
|
724 |
&& (next->val == OV3640_VAL_TERM))) {
|
725 |
err = ov3640_write_reg(client, next->reg, next->val);
|
726 |
udelay(100);
|
727 |
if (err)
|
728 |
return err;
|
729 |
next++;
|
730 |
}
|
731 |
return 0;
|
732 |
} |
733 |
|
734 |
/* Find the best match for a requested image capture size. The best match |
735 |
* is chosen as the nearest match that has the same number or fewer pixels |
736 |
* as the requested size, or the smallest image size if the requested size |
737 |
* has fewer pixels than the smallest image. |
738 |
*/ |
739 |
static enum image_size_ov |
740 |
ov3640_find_size(unsigned int width, unsigned int height)
|
741 |
{ |
742 |
if ((width > ov3640_sizes[XGA].width) ||
|
743 |
(height > ov3640_sizes[XGA].height))
|
744 |
return QXGA;
|
745 |
return XGA;
|
746 |
} |
747 |
|
748 |
/* |
749 |
* Set CSI2 Virtual ID. |
750 |
*/ |
751 |
static int ov3640_set_virtual_id(struct i2c_client *client, u32 id)
|
752 |
{ |
753 |
return ov3640_write_reg(client, OV3640_MIPI_CTRL0C, (0x3 & id) << 6 |
|
754 |
0x02);
|
755 |
} |
756 |
|
757 |
|
758 |
/* |
759 |
* Calculates the MIPIClk. |
760 |
* 1) Calculate fclk |
761 |
* fclk = (64 - OV3640_PLL_1[5:0]) * N * Bit8Div * MCLK / M |
762 |
* where N = 1/1.5/2/3 for OV3640_PLL_2[7:6]=0~3 |
763 |
* M = 1/1.5/2/3 for OV3640_PLL_2[1:0]=0~3 |
764 |
* Bit8Div = 1/1/4/5 for OV3640_PLL_2[5:4] |
765 |
* 2) Calculate MIPIClk |
766 |
* MIPIClk = fclk / ScaleDiv / MIPIDiv |
767 |
* = fclk * (1/ScaleDiv) / MIPIDiv |
768 |
* where 1/ScaleDiv = 0x3010[3:0]*2 |
769 |
* MIPIDiv = 0x3010[5] + 1 |
770 |
* NOTE: |
771 |
* - The lookup table 'lut1' has been multiplied by 2 so all its values |
772 |
* are integers. Since both N & M use the same table, and they are |
773 |
* used as a ratio then the factor of 2 is already take into account. |
774 |
* i.e. 2N/2M = N/M |
775 |
*/ |
776 |
static u32 ov3640_calc_mipiclk(struct v4l2_int_device *s)
|
777 |
{ |
778 |
struct ov3640_sensor *sensor = s->priv;
|
779 |
struct i2c_client *client = sensor->i2c_client;
|
780 |
u32 rxpll, val, n, m, bit8div;
|
781 |
u32 sdiv_inv, mipidiv;
|
782 |
u32 fclk, mipiclk, mclk = 24000000;
|
783 |
u8 lut1[4] = {2, 3, 4, 6};
|
784 |
u8 lut2[4] = {1, 1, 4, 5};
|
785 |
|
786 |
/* Calculate fclk */
|
787 |
ov3640_read_reg(client, 1, OV3640_PLL_1, &val);
|
788 |
rxpll = val & 0x3F;
|
789 |
|
790 |
ov3640_read_reg(client, 1, OV3640_PLL_2, &val);
|
791 |
n = lut1[(val >> 6) & 0x3];
|
792 |
m = lut1[val & 0x3];
|
793 |
bit8div = lut2[(val >> 4) & 0x3];
|
794 |
fclk = (64 - rxpll) * n * bit8div * mclk / m;
|
795 |
|
796 |
ov3640_read_reg(client, 1, OV3640_PLL_3, &val);
|
797 |
mipidiv = ((val >> 5) & 1) + 1;
|
798 |
sdiv_inv = (val & 0xF) * 2;
|
799 |
|
800 |
if ((val & 0xF) >= 1)
|
801 |
mipiclk = fclk / sdiv_inv / mipidiv;
|
802 |
else
|
803 |
mipiclk = fclk / mipidiv;
|
804 |
dev_dbg(&client->dev, "mipiclk=%u fclk=%u val&0xF=%u sdiv_inv=%u "
|
805 |
"mipidiv=%u\n",
|
806 |
mipiclk, fclk, val&0xF,
|
807 |
sdiv_inv, mipidiv);
|
808 |
return mipiclk;
|
809 |
} |
810 |
|
811 |
/** |
812 |
* ov3640_set_framerate |
813 |
**/ |
814 |
static int ov3640_set_framerate(struct i2c_client *client,
|
815 |
struct v4l2_fract *fper,
|
816 |
enum image_size_ov isize)
|
817 |
{ |
818 |
u32 tempfps1, tempfps2;
|
819 |
u8 clkval;
|
820 |
/* |
821 |
u32 origvts, newvts, templineperiod; |
822 |
u32 origvts_h, origvts_l, newvts_h, newvts_l; |
823 |
*/ |
824 |
int err = 0;
|
825 |
|
826 |
/* FIXME: QXGA framerate setting forced to 15 FPS */
|
827 |
if (isize == QXGA) {
|
828 |
err = ov3640_write_reg(client, OV3640_PLL_1, 0x32);
|
829 |
err = ov3640_write_reg(client, OV3640_PLL_2, 0x21);
|
830 |
err = ov3640_write_reg(client, OV3640_PLL_3, 0x21);
|
831 |
err = ov3640_write_reg(client, OV3640_CLK, 0x01);
|
832 |
err = ov3640_write_reg(client, 0x304c, 0x81);
|
833 |
return err;
|
834 |
}
|
835 |
|
836 |
tempfps1 = fper->denominator * 10000;
|
837 |
tempfps1 /= fper->numerator;
|
838 |
tempfps2 = fper->denominator / fper->numerator;
|
839 |
if ((tempfps1 % 10000) != 0)
|
840 |
tempfps2++;
|
841 |
clkval = (u8)((30 / tempfps2) - 1);
|
842 |
|
843 |
err = ov3640_write_reg(client, OV3640_CLK, clkval);
|
844 |
/* RxPLL = 50d = 32h */
|
845 |
err = ov3640_write_reg(client, OV3640_PLL_1, 0x32);
|
846 |
/* RxPLL = 50d = 32h */
|
847 |
err = ov3640_write_reg(client, OV3640_PLL_2,
|
848 |
OV3640_PLL_2_BIT8DIV_4 |
|
849 |
OV3640_PLL_2_INDIV_1_5);
|
850 |
/*
|
851 |
* NOTE: Sergio's Fix for MIPI CLK timings, not suggested by OV |
852 |
*/ |
853 |
err = ov3640_write_reg(client, OV3640_PLL_3, 0x21 +
|
854 |
(clkval & 0xF));
|
855 |
/* Setting DVP divisor value */
|
856 |
err = ov3640_write_reg(client, 0x304c, 0x82);
|
857 |
/* FIXME: Time adjustment to add granularity to the available fps */ |
858 |
/* |
859 |
ov3640_read_reg(client, 1, OV3640_VTS_H, &origvts_h); |
860 |
ov3640_read_reg(client, 1, OV3640_VTS_L, &origvts_l); |
861 |
origvts = (u32)((origvts_h << 8) + origvts_l); |
862 |
templineperiod = 1000000 / (tempfps2 * origvts); |
863 |
newvts = 1000000 / (tempfps2 * templineperiod); |
864 |
newvts_h = (u8)((newvts & 0xFF00) >> 8); |
865 |
newvts_l = (u8)(newvts & 0xFF); |
866 |
err = ov3640_write_reg(client, OV3640_VTS_H, newvts_h); |
867 |
err = ov3640_write_reg(client, OV3640_VTS_L, newvts_l); |
868 |
*/ |
869 |
return err;
|
870 |
} |
871 |
|
872 |
/* |
873 |
* Configure the ov3640 for a specified image size, pixel format, and frame |
874 |
* period. xclk is the frequency (in Hz) of the xclk input to the OV3640. |
875 |
* fper is the frame period (in seconds) expressed as a fraction. |
876 |
* Returns zero if successful, or non-zero otherwise. |
877 |
* The actual frame period is returned in fper. |
878 |
*/ |
879 |
static int ov3640_configure(struct v4l2_int_device *s)
|
880 |
{ |
881 |
struct ov3640_sensor *sensor = s->priv;
|
882 |
struct v4l2_pix_format *pix = &sensor->pix;
|
883 |
struct i2c_client *client = sensor->i2c_client;
|
884 |
enum image_size_ov isize = XGA;
|
885 |
unsigned char hsize_l = 0, hsize_h = 0;
|
886 |
unsigned char vsize_l = 0, vsize_h = 0;
|
887 |
int vsize = 0, hsize = 0, height_l = 0, height_h = 0, width_l = 0;
|
888 |
int width_h = 0, ratio = 0, err = 0;
|
889 |
u32 mipiclk;
|
890 |
enum pixel_format_ov pfmt = YUV;
|
891 |
u32 min_hs_zero_nui, min_hs_zero, min_hs_zero_total;
|
892 |
u32 min_hs_prepare_nui, min_hs_prepare, min_hs_prepare_total;
|
893 |
u32 max_hs_prepare_nui, max_hs_prepare, max_hs_prepare_total;
|
894 |
u32 ubound_hs_settle, lbound_hs_settle;
|
895 |
u32 val;
|
896 |
|
897 |
switch (pix->pixelformat) {
|
898 |
|
899 |
case V4L2_PIX_FMT_RGB565: |
900 |
case V4L2_PIX_FMT_RGB565X: |
901 |
pfmt = RGB565;
|
902 |
break;
|
903 |
|
904 |
case V4L2_PIX_FMT_RGB555: |
905 |
case V4L2_PIX_FMT_RGB555X: |
906 |
pfmt = RGB555;
|
907 |
break;
|
908 |
|
909 |
case V4L2_PIX_FMT_SGRBG10: |
910 |
pfmt = RAW10;
|
911 |
break;
|
912 |
|
913 |
case V4L2_PIX_FMT_YUYV: |
914 |
case V4L2_PIX_FMT_UYVY: |
915 |
default:
|
916 |
pfmt = YUV;
|
917 |
}
|
918 |
|
919 |
/* Set receivers virtual channel before sensor setup starts.
|
920 |
* Only set the sensors virtual channel after all other setup |
921 |
* for the sensor is complete. |
922 |
*/ |
923 |
isp_csi2_ctx_config_virtual_id(0, OV3640_CSI2_VIRTUAL_ID);
|
924 |
isp_csi2_ctx_update(0, false);
|
925 |
|
926 |
if (ov3640_find_size(pix->width, pix->height) == XGA)
|
927 |
isize = XGA;
|
928 |
else
|
929 |
isize = QXGA;
|
930 |
|
931 |
/* Reset */
|
932 |
ov3640_write_reg(client, OV3640_SYS, 0x80);
|
933 |
mdelay(5);
|
934 |
|
935 |
/* Common registers */
|
936 |
err = ov3640_write_regs(client, ov3640_common[isize]);
|
937 |
|
938 |
/* Configure image size and pixel format */
|
939 |
err = ov3640_write_regs(client, ov3640_reg_init[pfmt][isize]);
|
940 |
|
941 |
/* Setting of frame rate (OV suggested way) */
|
942 |
err = ov3640_set_framerate(client, &sensor->timeperframe, isize);
|
943 |
#ifdef CONFIG_VIDEO_OV3640_CSI2 |
944 |
/* Set CSI2 common register settings */
|
945 |
err = ov3640_write_regs(client, ov3640_common_csi2);
|
946 |
#endif |
947 |
|
948 |
sensor->isize = isize;
|
949 |
|
950 |
/* Scale image if needed*/
|
951 |
if (((pix->width == ov3640_sizes[QXGA].width) &&
|
952 |
(pix->height == ov3640_sizes[QXGA].height) && (isize == QXGA))
|
953 |
|| ((pix->width == ov3640_sizes[XGA].width) &&
|
954 |
(pix->height == ov3640_sizes[XGA].height) &&
|
955 |
(isize == XGA)) || (pfmt == RAW10)) {
|
956 |
|
957 |
/* if the image size correspond to one of the base image sizes
|
958 |
then we don't need to scale the image */ |
959 |
sensor->hsize = pix->width;
|
960 |
sensor->vsize = pix->height;
|
961 |
|
962 |
if (isize == XGA)
|
963 |
ov3640_write_regs(client, ov3640_out_xga);
|
964 |
else
|
965 |
ov3640_write_regs(client, ov3640_out_qxga);
|
966 |
|
967 |
} else {
|
968 |
/* Default Ver and Hor sizes for QXGA and XGA*/
|
969 |
if (isize == QXGA) {
|
970 |
vsize = 0x600;/* 0x60c; */
|
971 |
hsize = 0x800;/* 0x818; */
|
972 |
} else {
|
973 |
vsize = 0x304;
|
974 |
hsize = 0x40c;
|
975 |
}
|
976 |
/* Scaling */
|
977 |
/* Adjust V and H sizes for image sizes not derived form VGA*/
|
978 |
ratio = (pix->width * 1000) / pix->height;
|
979 |
|
980 |
if (((vsize * ratio + 500) / 1000) > hsize)
|
981 |
vsize = (hsize * 1000) / ratio ;
|
982 |
|
983 |
else
|
984 |
hsize = (vsize * ratio + 500) / 1000;
|
985 |
|
986 |
/* We need even numbers */
|
987 |
if (vsize & 1)
|
988 |
vsize--;
|
989 |
if (hsize & 1)
|
990 |
hsize--;
|
991 |
|
992 |
/* Adjusting numbers to set registers correctly */
|
993 |
hsize_l = (0xFF & hsize);
|
994 |
hsize_h = (0xF00 & hsize) >> 8;
|
995 |
vsize_l = (0xFF & vsize);
|
996 |
vsize_h = (0x700 & vsize) >> 4;
|
997 |
|
998 |
/* According to Software app notes we have to add 0x08 and 0x04
|
999 |
* in order to scale correctly |
1000 |
*/ |
1001 |
width_l = (0xFF & pix->width) + 0x08;
|
1002 |
width_h = (0xF00 & pix->width) >> 8;
|
1003 |
height_l = (0xFF & pix->height) + 0x04;
|
1004 |
height_h = (0x700 & pix->height) >> 4;
|
1005 |
|
1006 |
err = ov3640_write_reg(client, OV3640_SIZE_IN_MISC,
|
1007 |
(vsize_h | hsize_h));
|
1008 |
err = ov3640_write_reg(client, OV3640_HSIZE_IN_L, hsize_l);
|
1009 |
err = ov3640_write_reg(client, OV3640_VSIZE_IN_L, vsize_l);
|
1010 |
err = ov3640_write_reg(client, OV3640_SIZE_OUT_MISC,
|
1011 |
(height_h | width_h));
|
1012 |
err = ov3640_write_reg(client, OV3640_HSIZE_OUT_L, width_l);
|
1013 |
err = ov3640_write_reg(client, OV3640_VSIZE_OUT_L, height_l);
|
1014 |
err = ov3640_write_reg(client, OV3640_ISP_PAD_CTR2, 0x42);
|
1015 |
err = ov3640_write_reg(client, OV3640_ISP_XOUT_H, width_h);
|
1016 |
err = ov3640_write_reg(client, OV3640_ISP_XOUT_L,
|
1017 |
(width_l - 0x08));
|
1018 |
err = ov3640_write_reg(client, OV3640_ISP_YOUT_H,
|
1019 |
(height_h >> 4));
|
1020 |
err = ov3640_write_reg(client, OV3640_ISP_YOUT_L,
|
1021 |
(height_l - 0x04));
|
1022 |
|
1023 |
sensor->hsize = hsize;
|
1024 |
sensor->vsize = vsize;
|
1025 |
|
1026 |
dev_dbg(&client->dev, "HSIZE_IN =%i VSIZE_IN =%i\n", hsize,
|
1027 |
vsize);
|
1028 |
dev_dbg(&client->dev, "HSIZE_OUT=%u VSIZE_OUT=%u\n",
|
1029 |
(pix->width + 8),
|
1030 |
(pix->height + 4));
|
1031 |
dev_dbg(&client->dev, "ISP_XOUT =%u ISP_YOUT =%u\n",
|
1032 |
pix->width,
|
1033 |
pix->height);
|
1034 |
}
|
1035 |
|
1036 |
/* Setup the ISP VP based on image format */
|
1037 |
if (pix->pixelformat == V4L2_PIX_FMT_SGRBG10) {
|
1038 |
isp_configure_interface_bridge(0x00);
|
1039 |
isp_csi2_ctrl_config_vp_out_ctrl(2);
|
1040 |
isp_csi2_ctrl_update(false);
|
1041 |
} else {
|
1042 |
isp_configure_interface_bridge(0x03);
|
1043 |
isp_csi2_ctrl_config_vp_out_ctrl(1);
|
1044 |
isp_csi2_ctrl_update(false);
|
1045 |
}
|
1046 |
|
1047 |
/* Store image size */
|
1048 |
sensor->width = pix->width;
|
1049 |
sensor->height = pix->height;
|
1050 |
|
1051 |
sensor->crop_rect.left = 0;
|
1052 |
sensor->crop_rect.width = pix->width;
|
1053 |
sensor->crop_rect.top = 0;
|
1054 |
sensor->crop_rect.height = pix->height;
|
1055 |
|
1056 |
#ifdef CONFIG_VIDEO_OV3640_CSI2 |
1057 |
mipiclk = ov3640_calc_mipiclk(s);
|
1058 |
|
1059 |
/* Calculate Valid bounds for High speed settle timing in UIs */
|
1060 |
ov3640_read_reg(client, 1, OV3640_MIPI_CTRL22, &val);
|
1061 |
min_hs_zero_nui = ((val & OV3640_MIPI_CTRL22_MIN_HS_ZERO_NUI_MASK) >>
|
1062 |
OV3640_MIPI_CTRL22_MIN_HS_ZERO_NUI_SHIFT);
|
1063 |
min_hs_zero = ((val & OV3640_MIPI_CTRL22_MIN_HS_ZERO_H_MASK) << 8);
|
1064 |
ov3640_read_reg(client, 1, OV3640_MIPI_CTRL23, &val);
|
1065 |
min_hs_zero |= (val & OV3640_MIPI_CTRL23_MIN_HS_ZERO_L_MASK);
|
1066 |
min_hs_zero_total = ((min_hs_zero_nui * 1000000 * 1000) / mipiclk) +
|
1067 |
min_hs_zero;
|
1068 |
|
1069 |
ov3640_read_reg(client, 1, OV3640_MIPI_CTRL32, &val);
|
1070 |
min_hs_prepare_nui = ((val &
|
1071 |
OV3640_MIPI_CTRL32_MIN_HS_PREPARE_NUI_MASK) >>
|
1072 |
OV3640_MIPI_CTRL32_MIN_HS_PREPARE_NUI_SHIFT);
|
1073 |
min_hs_prepare = ((val &
|
1074 |
OV3640_MIPI_CTRL32_MIN_HS_PREPARE_H_MASK) << 8);
|
1075 |
ov3640_read_reg(client, 1, OV3640_MIPI_CTRL33, &val);
|
1076 |
min_hs_prepare |= (val & OV3640_MIPI_CTRL33_MIN_HS_PREPARE_L_MASK);
|
1077 |
min_hs_prepare_total = ((min_hs_prepare_nui * 1000000 * 1000) /
|
1078 |
mipiclk) + min_hs_prepare;
|
1079 |
|
1080 |
ov3640_read_reg(client, 1, OV3640_MIPI_CTRL34, &val);
|
1081 |
max_hs_prepare_nui = ((val &
|
1082 |
OV3640_MIPI_CTRL34_MAX_HS_PREPARE_NUI_MASK) >>
|
1083 |
OV3640_MIPI_CTRL34_MAX_HS_PREPARE_NUI_SHIFT);
|
1084 |
max_hs_prepare = ((val &
|
1085 |
OV3640_MIPI_CTRL34_MAX_HS_PREPARE_H_MASK) << 8);
|
1086 |
ov3640_read_reg(client, 1, OV3640_MIPI_CTRL35, &val);
|
1087 |
max_hs_prepare |= (val & OV3640_MIPI_CTRL35_MAX_HS_PREPARE_L_MASK);
|
1088 |
max_hs_prepare_total = ((max_hs_prepare_nui * 1000000 * 1000) /
|
1089 |
mipiclk) + max_hs_prepare;
|
1090 |
|
1091 |
ubound_hs_settle = ((min_hs_zero_total + min_hs_prepare_total) *
|
1092 |
((mipiclk >> 1) / 1000000)) / 1000;
|
1093 |
lbound_hs_settle = (max_hs_prepare_total * ((mipiclk >> 1) /
|
1094 |
1000000)) / 1000;
|
1095 |
|
1096 |
/* Send settings to ISP-CSI2 Receiver PHY */
|
1097 |
isp_csi2_calc_phy_cfg0(mipiclk, lbound_hs_settle, ubound_hs_settle);
|
1098 |
|
1099 |
/* Set sensors virtual channel*/
|
1100 |
ov3640_set_virtual_id(client, OV3640_CSI2_VIRTUAL_ID);
|
1101 |
#endif |
1102 |
return err;
|
1103 |
} |
1104 |
|
1105 |
|
1106 |
/* Detect if an ov3640 is present, returns a negative error number if no |
1107 |
* device is detected, or pidl as version number if a device is detected. |
1108 |
*/ |
1109 |
static int ov3640_detect(struct i2c_client *client)
|
1110 |
{ |
1111 |
u32 pidh, pidl;
|
1112 |
|
1113 |
if (!client)
|
1114 |
return -ENODEV;
|
1115 |
|
1116 |
if (ov3640_read_reg(client, 1, OV3640_PIDH, &pidh))
|
1117 |
return -ENODEV;
|
1118 |
|
1119 |
if (ov3640_read_reg(client, 1, OV3640_PIDL, &pidl))
|
1120 |
return -ENODEV;
|
1121 |
|
1122 |
if ((pidh == OV3640_PIDH_MAGIC) && ((pidl == OV3640_PIDL_MAGIC1) ||
|
1123 |
(pidl == OV3640_PIDL_MAGIC2))) {
|
1124 |
dev_dbg(&client->dev, "Detect success (%02X,%02X)\n", pidh,
|
1125 |
pidl);
|
1126 |
return pidl;
|
1127 |
}
|
1128 |
|
1129 |
return -ENODEV;
|
1130 |
} |
1131 |
|
1132 |
/* To get the cropping capabilities of ov3640 sensor |
1133 |
* Returns zero if successful, or non-zero otherwise. |
1134 |
*/ |
1135 |
static int ioctl_cropcap(struct v4l2_int_device *s,
|
1136 |
struct v4l2_cropcap *cropcap)
|
1137 |
{ |
1138 |
struct ov3640_sensor *sensor = s->priv;
|
1139 |
|
1140 |
cropcap->bounds.top = 0;
|
1141 |
cropcap->bounds.left = 0;
|
1142 |
cropcap->bounds.width = sensor->width;
|
1143 |
cropcap->bounds.height = sensor->height;
|
1144 |
cropcap->defrect = cropcap->bounds;
|
1145 |
cropcap->pixelaspect.numerator = 1;
|
1146 |
cropcap->pixelaspect.denominator = 1;
|
1147 |
return 0;
|
1148 |
} |
1149 |
|
1150 |
/* To get the current crop window for of ov3640 sensor |
1151 |
* Returns zero if successful, or non-zero otherwise. |
1152 |
*/ |
1153 |
static int ioctl_g_crop(struct v4l2_int_device *s, struct v4l2_crop *crop)
|
1154 |
{ |
1155 |
struct ov3640_sensor *sensor = s->priv;
|
1156 |
|
1157 |
crop->c = sensor->crop_rect;
|
1158 |
return 0;
|
1159 |
} |
1160 |
|
1161 |
/* To set the crop window for of ov3640 sensor |
1162 |
* Returns zero if successful, or non-zero otherwise. |
1163 |
*/ |
1164 |
static int ioctl_s_crop(struct v4l2_int_device *s, struct v4l2_crop *crop)
|
1165 |
{ |
1166 |
struct ov3640_sensor *sensor = s->priv;
|
1167 |
/* FIXME: Temporary workaround for avoiding Zoom setting */
|
1168 |
/* struct i2c_client *client = sensor->i2c_client; */
|
1169 |
struct v4l2_rect *cur_rect;
|
1170 |
unsigned long *cur_width, *cur_height;
|
1171 |
int hstart, vstart, hsize, vsize, hsize_l, vsize_l, hsize_h, vsize_h;
|
1172 |
int hratio, vratio, zoomfactor, err = 0;
|
1173 |
|
1174 |
cur_rect = &sensor->crop_rect;
|
1175 |
cur_width = &sensor->width;
|
1176 |
cur_height = &sensor->height;
|
1177 |
|
1178 |
if ((crop->c.left == cur_rect->left) &&
|
1179 |
(crop->c.width == cur_rect->width) &&
|
1180 |
(crop->c.top == cur_rect->top) &&
|
1181 |
(crop->c.height == cur_rect->height))
|
1182 |
return 0;
|
1183 |
|
1184 |
/* out of range? then return the current crop rectangle */
|
1185 |
if ((crop->c.left + crop->c.width) > sensor->width ||
|
1186 |
(crop->c.top + crop->c.height) > sensor->height) {
|
1187 |
crop->c = *cur_rect;
|
1188 |
return 0;
|
1189 |
}
|
1190 |
|
1191 |
if (sensor->isize == QXGA)
|
1192 |
zoomfactor = 1;
|
1193 |
else
|
1194 |
zoomfactor = 2;
|
1195 |
|
1196 |
hratio = (sensor->hsize * 1000) / sensor->width;
|
1197 |
vratio = (sensor->vsize * 1000) / sensor->height;
|
1198 |
hstart = (((crop->c.left * hratio + 500) / 1000) * zoomfactor) + 0x11d;
|
1199 |
vstart = (((crop->c.top * vratio + 500) / 1000) + 0x0a);
|
1200 |
hsize = (crop->c.width * hratio + 500) / 1000;
|
1201 |
vsize = (crop->c.height * vratio + 500) / 1000;
|
1202 |
|
1203 |
if (vsize & 1)
|
1204 |
vsize--;
|
1205 |
if (hsize & 1)
|
1206 |
hsize--;
|
1207 |
|
1208 |
/* Adjusting numbers to set register correctly */
|
1209 |
hsize_l = (0xFF & hsize);
|
1210 |
hsize_h = (0xF00 & hsize) >> 8;
|
1211 |
vsize_l = (0xFF & vsize);
|
1212 |
vsize_h = (0x700 & vsize) >> 4;
|
1213 |
|
1214 |
if ((sensor->height > vsize) || (sensor->width > hsize))
|
1215 |
return -EINVAL;
|
1216 |
|
1217 |
hsize = hsize * zoomfactor;
|
1218 |
/* |
1219 |
err = ov3640_write_reg(client, OV3640_DSP_CTRL_2, 0xEF); |
1220 |
err = ov3640_write_reg(client, OV3640_SIZE_IN_MISC, (vsize_h | |
1221 |
hsize_h)); |
1222 |
err = ov3640_write_reg(client, OV3640_HSIZE_IN_L, hsize_l); |
1223 |
err = ov3640_write_reg(client, OV3640_VSIZE_IN_L, vsize_l); |
1224 |
err = ov3640_write_reg(client, OV3640_HS_H, (hstart >> 8) & 0xFF); |
1225 |
err = ov3640_write_reg(client, OV3640_HS_L, hstart & 0xFF); |
1226 |
err = ov3640_write_reg(client, OV3640_VS_H, (vstart >> 8) & 0xFF); |
1227 |
err = ov3640_write_reg(client, OV3640_VS_L, vstart & 0xFF); |
1228 |
err = ov3640_write_reg(client, OV3640_HW_H, ((hsize) >> 8) & 0xFF); |
1229 |
err = ov3640_write_reg(client, OV3640_HW_L, hsize & 0xFF); |
1230 |
err = ov3640_write_reg(client, OV3640_VH_H, ((vsize) >> 8) & 0xFF); |
1231 |
err = ov3640_write_reg(client, OV3640_VH_L, vsize & 0xFF); |
1232 |
*/ |
1233 |
if (err)
|
1234 |
return err;
|
1235 |
|
1236 |
/* save back */
|
1237 |
*cur_rect = crop->c;
|
1238 |
|
1239 |
/* Setting crop too fast can cause frame out-of-sync. */
|
1240 |
|
1241 |
set_current_state(TASK_UNINTERRUPTIBLE);
|
1242 |
schedule_timeout(msecs_to_jiffies(20));
|
1243 |
return 0;
|
1244 |
} |
1245 |
|
1246 |
|
1247 |
/* |
1248 |
* ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl |
1249 |
* @s: pointer to standard V4L2 device structure |
1250 |
* @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure |
1251 |
* |
1252 |
* If the requested control is supported, returns the control information |
1253 |
* from the video_control[] array. Otherwise, returns -EINVAL if the |
1254 |
* control is not supported. |
1255 |
*/ |
1256 |
static int ioctl_queryctrl(struct v4l2_int_device *s,
|
1257 |
struct v4l2_queryctrl *qc)
|
1258 |
{ |
1259 |
int i;
|
1260 |
|
1261 |
i = find_vctrl(qc->id);
|
1262 |
if (i == -EINVAL)
|
1263 |
qc->flags = V4L2_CTRL_FLAG_DISABLED;
|
1264 |
|
1265 |
if (i < 0)
|
1266 |
return -EINVAL;
|
1267 |
|
1268 |
*qc = video_control[i].qc;
|
1269 |
return 0;
|
1270 |
} |
1271 |
|
1272 |
/* |
1273 |
* ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl |
1274 |
* @s: pointer to standard V4L2 device structure |
1275 |
* @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure |
1276 |
* |
1277 |
* If the requested control is supported, returns the control's current |
1278 |
* value from the video_control[] array. Otherwise, returns -EINVAL |
1279 |
* if the control is not supported. |
1280 |
*/ |
1281 |
|
1282 |
static int ioctl_g_ctrl(struct v4l2_int_device *s,
|
1283 |
struct v4l2_control *vc)
|
1284 |
{ |
1285 |
struct vcontrol *lvc;
|
1286 |
int i;
|
1287 |
|
1288 |
i = find_vctrl(vc->id);
|
1289 |
if (i < 0)
|
1290 |
return -EINVAL;
|
1291 |
lvc = &video_control[i];
|
1292 |
|
1293 |
switch (vc->id) {
|
1294 |
case V4L2_CID_BRIGHTNESS: |
1295 |
vc->value = lvc->current_value;
|
1296 |
break;
|
1297 |
case V4L2_CID_CONTRAST: |
1298 |
vc->value = lvc->current_value;
|
1299 |
break;
|
1300 |
case V4L2_CID_PRIVATE_BASE: |
1301 |
vc->value = lvc->current_value;
|
1302 |
break;
|
1303 |
}
|
1304 |
return 0;
|
1305 |
} |
1306 |
|
1307 |
/* |
1308 |
* ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl |
1309 |
* @s: pointer to standard V4L2 device structure |
1310 |
* @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure |
1311 |
* |
1312 |
* If the requested control is supported, sets the control's current |
1313 |
* value in HW (and updates the video_control[] array). Otherwise, |
1314 |
* returns -EINVAL if the control is not supported. |
1315 |
*/ |
1316 |
static int ioctl_s_ctrl(struct v4l2_int_device *s,
|
1317 |
struct v4l2_control *vc)
|
1318 |
{ |
1319 |
int retval = -EINVAL;
|
1320 |
int i;
|
1321 |
struct ov3640_sensor *sensor = s->priv;
|
1322 |
struct i2c_client *client = sensor->i2c_client;
|
1323 |
struct vcontrol *lvc;
|
1324 |
|
1325 |
i = find_vctrl(vc->id);
|
1326 |
if (i < 0)
|
1327 |
return -EINVAL;
|
1328 |
|
1329 |
lvc = &video_control[i];
|
1330 |
|
1331 |
switch (vc->id) {
|
1332 |
case V4L2_CID_BRIGHTNESS: |
1333 |
if (vc->value >= 0 && vc->value <= 6) {
|
1334 |
retval = ov3640_write_regs(client,
|
1335 |
brightness[vc->value]);
|
1336 |
} else {
|
1337 |
dev_err(&client->dev, "BRIGHTNESS LEVEL NOT SUPPORTED");
|
1338 |
return -EINVAL;
|
1339 |
}
|
1340 |
break;
|
1341 |
case V4L2_CID_CONTRAST: |
1342 |
if (vc->value >= 0 && vc->value <= 6)
|
1343 |
retval = ov3640_write_regs(client, contrast[vc->value]);
|
1344 |
else {
|
1345 |
dev_err(&client->dev, "CONTRAST LEVEL NOT SUPPORTED");
|
1346 |
return -EINVAL;
|
1347 |
}
|
1348 |
break;
|
1349 |
case V4L2_CID_PRIVATE_BASE: |
1350 |
if (vc->value >= 0 && vc->value <= 2)
|
1351 |
retval = ov3640_write_regs(client, colors[vc->value]);
|
1352 |
else {
|
1353 |
dev_err(&client->dev, "COLOR LEVEL NOT SUPPORTED");
|
1354 |
return -EINVAL;
|
1355 |
}
|
1356 |
break;
|
1357 |
}
|
1358 |
if (!retval)
|
1359 |
lvc->current_value = vc->value;
|
1360 |
return retval;
|
1361 |
} |
1362 |
|
1363 |
/* |
1364 |
* ioctl_enum_fmt_cap - Implement the CAPTURE buffer VIDIOC_ENUM_FMT ioctl |
1365 |
* @s: pointer to standard V4L2 device structure |
1366 |
* @fmt: standard V4L2 VIDIOC_ENUM_FMT ioctl structure |
1367 |
* |
1368 |
* Implement the VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type. |
1369 |
*/ |
1370 |
static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
|
1371 |
struct v4l2_fmtdesc *fmt)
|
1372 |
{ |
1373 |
int index = fmt->index;
|
1374 |
enum v4l2_buf_type type = fmt->type;
|
1375 |
|
1376 |
memset(fmt, 0, sizeof(*fmt));
|
1377 |
fmt->index = index;
|
1378 |
fmt->type = type;
|
1379 |
|
1380 |
switch (fmt->type) {
|
1381 |
case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
1382 |
if (index >= NUM_CAPTURE_FORMATS)
|
1383 |
return -EINVAL;
|
1384 |
break;
|
1385 |
default:
|
1386 |
return -EINVAL;
|
1387 |
}
|
1388 |
|
1389 |
fmt->flags = ov3640_formats[index].flags;
|
1390 |
strlcpy(fmt->description, ov3640_formats[index].description,
|
1391 |
sizeof(fmt->description));
|
1392 |
fmt->pixelformat = ov3640_formats[index].pixelformat;
|
1393 |
|
1394 |
return 0;
|
1395 |
} |
1396 |
|
1397 |
|
1398 |
/* |
1399 |
* ioctl_try_fmt_cap - Implement the CAPTURE buffer VIDIOC_TRY_FMT ioctl |
1400 |
* @s: pointer to standard V4L2 device structure |
1401 |
* @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure |
1402 |
* |
1403 |
* Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This |
1404 |
* ioctl is used to negotiate the image capture size and pixel format |
1405 |
* without actually making it take effect. |
1406 |
*/ |
1407 |
|
1408 |
static int ioctl_try_fmt_cap(struct v4l2_int_device *s,
|
1409 |
struct v4l2_format *f)
|
1410 |
{ |
1411 |
int ifmt;
|
1412 |
enum image_size_ov isize;
|
1413 |
struct v4l2_pix_format *pix = &f->fmt.pix;
|
1414 |
|
1415 |
if (pix->width > ov3640_sizes[QXGA].width)
|
1416 |
pix->width = ov3640_sizes[QXGA].width;
|
1417 |
if (pix->height > ov3640_sizes[QXGA].height)
|
1418 |
pix->height = ov3640_sizes[QXGA].height;
|
1419 |
|
1420 |
isize = ov3640_find_size(pix->width, pix->height);
|
1421 |
pix->width = ov3640_sizes[isize].width;
|
1422 |
pix->height = ov3640_sizes[isize].height;
|
1423 |
|
1424 |
for (ifmt = 0; ifmt < NUM_CAPTURE_FORMATS; ifmt++) {
|
1425 |
if (pix->pixelformat == ov3640_formats[ifmt].pixelformat)
|
1426 |
break;
|
1427 |
}
|
1428 |
if (ifmt == NUM_CAPTURE_FORMATS)
|
1429 |
ifmt = 0;
|
1430 |
pix->pixelformat = ov3640_formats[ifmt].pixelformat;
|
1431 |
pix->field = V4L2_FIELD_NONE;
|
1432 |
pix->bytesperline = pix->width*2;
|
1433 |
pix->sizeimage = pix->bytesperline*pix->height;
|
1434 |
pix->priv = 0;
|
1435 |
switch (pix->pixelformat) {
|
1436 |
case V4L2_PIX_FMT_YUYV: |
1437 |
case V4L2_PIX_FMT_UYVY: |
1438 |
default:
|
1439 |
pix->colorspace = V4L2_COLORSPACE_JPEG;
|
1440 |
break;
|
1441 |
case V4L2_PIX_FMT_SGRBG10: |
1442 |
case V4L2_PIX_FMT_RGB565: |
1443 |
case V4L2_PIX_FMT_RGB565X: |
1444 |
case V4L2_PIX_FMT_RGB555: |
1445 |
case V4L2_PIX_FMT_RGB555X: |
1446 |
pix->colorspace = V4L2_COLORSPACE_SRGB;
|
1447 |
break;
|
1448 |
}
|
1449 |
return 0;
|
1450 |
} |
1451 |
|
1452 |
|
1453 |
/* |
1454 |
* ioctl_s_fmt_cap - V4L2 sensor interface handler for VIDIOC_S_FMT ioctl |
1455 |
* @s: pointer to standard V4L2 device structure |
1456 |
* @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure |
1457 |
* |
1458 |
* If the requested format is supported, configures the HW to use that |
1459 |
* format, returns error code if format not supported or HW can't be |
1460 |
* correctly configured. |
1461 |
*/ |
1462 |
static int ioctl_s_fmt_cap(struct v4l2_int_device *s,
|
1463 |
struct v4l2_format *f)
|
1464 |
{ |
1465 |
struct ov3640_sensor *sensor = s->priv;
|
1466 |
struct v4l2_pix_format *pix = &f->fmt.pix;
|
1467 |
int rval;
|
1468 |
|
1469 |
rval = ioctl_try_fmt_cap(s, f);
|
1470 |
if (rval)
|
1471 |
return rval;
|
1472 |
|
1473 |
sensor->pix = *pix;
|
1474 |
|
1475 |
return 0;
|
1476 |
} |
1477 |
|
1478 |
/* |
1479 |
* ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap |
1480 |
* @s: pointer to standard V4L2 device structure |
1481 |
* @f: pointer to standard V4L2 v4l2_format structure |
1482 |
* |
1483 |
* Returns the sensor's current pixel format in the v4l2_format |
1484 |
* parameter. |
1485 |
*/ |
1486 |
static int ioctl_g_fmt_cap(struct v4l2_int_device *s,
|
1487 |
struct v4l2_format *f)
|
1488 |
{ |
1489 |
struct ov3640_sensor *sensor = s->priv;
|
1490 |
f->fmt.pix = sensor->pix;
|
1491 |
|
1492 |
return 0;
|
1493 |
} |
1494 |
|
1495 |
/* |
1496 |
* ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl |
1497 |
* @s: pointer to standard V4L2 device structure |
1498 |
* @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure |
1499 |
* |
1500 |
* Returns the sensor's video CAPTURE parameters. |
1501 |
*/ |
1502 |
static int ioctl_g_parm(struct v4l2_int_device *s,
|
1503 |
struct v4l2_streamparm *a)
|
1504 |
{ |
1505 |
struct ov3640_sensor *sensor = s->priv;
|
1506 |
struct v4l2_captureparm *cparm = &a->parm.capture;
|
1507 |
|
1508 |
if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
1509 |
return -EINVAL;
|
1510 |
|
1511 |
memset(a, 0, sizeof(*a));
|
1512 |
a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
1513 |
|
1514 |
cparm->capability = V4L2_CAP_TIMEPERFRAME;
|
1515 |
cparm->timeperframe = sensor->timeperframe;
|
1516 |
|
1517 |
return 0;
|
1518 |
} |
1519 |
|
1520 |
/* |
1521 |
* ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl |
1522 |
* @s: pointer to standard V4L2 device structure |
1523 |
* @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure |
1524 |
* |
1525 |
* Configures the sensor to use the input parameters, if possible. If |
1526 |
* not possible, reverts to the old parameters and returns the |
1527 |
* appropriate error code. |
1528 |
*/ |
1529 |
static int ioctl_s_parm(struct v4l2_int_device *s,
|
1530 |
struct v4l2_streamparm *a)
|
1531 |
{ |
1532 |
int rval = 0;
|
1533 |
struct ov3640_sensor *sensor = s->priv;
|
1534 |
struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
|
1535 |
struct v4l2_fract timeperframe_old;
|
1536 |
int desired_fps;
|
1537 |
timeperframe_old = sensor->timeperframe;
|
1538 |
sensor->timeperframe = *timeperframe;
|
1539 |
|
1540 |
desired_fps = timeperframe->denominator / timeperframe->numerator;
|
1541 |
if ((desired_fps < OV3640_MIN_FPS) || (desired_fps > OV3640_MAX_FPS))
|
1542 |
rval = -EINVAL;
|
1543 |
|
1544 |
if (rval)
|
1545 |
sensor->timeperframe = timeperframe_old;
|
1546 |
else
|
1547 |
*timeperframe = sensor->timeperframe;
|
1548 |
|
1549 |
return rval;
|
1550 |
} |
1551 |
|
1552 |
/* |
1553 |
* ioctl_g_priv - V4L2 sensor interface handler for vidioc_int_g_priv_num |
1554 |
* @s: pointer to standard V4L2 device structure |
1555 |
* @p: void pointer to hold sensor's private data address |
1556 |
* |
1557 |
* Returns device's (sensor's) private data area address in p parameter |
1558 |
*/ |
1559 |
static int ioctl_g_priv(struct v4l2_int_device *s, void *p)
|
1560 |
{ |
1561 |
struct ov3640_sensor *sensor = s->priv;
|
1562 |
|
1563 |
return sensor->pdata->priv_data_set(p);
|
1564 |
} |
1565 |
|
1566 |
/* |
1567 |
* ioctl_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num |
1568 |
* @s: pointer to standard V4L2 device structure |
1569 |
* @on: power state to which device is to be set |
1570 |
* |
1571 |
* Sets devices power state to requrested state, if possible. |
1572 |
*/ |
1573 |
static int ioctl_s_power(struct v4l2_int_device *s, enum v4l2_power on)
|
1574 |
{ |
1575 |
struct ov3640_sensor *sensor = s->priv;
|
1576 |
struct i2c_client *c = sensor->i2c_client;
|
1577 |
struct omap34xxcam_hw_config hw_config;
|
1578 |
static enum v4l2_power prev_on = V4L2_POWER_OFF;
|
1579 |
int rval;
|
1580 |
|
1581 |
rval = ioctl_g_priv(s, &hw_config);
|
1582 |
if (rval) {
|
1583 |
dev_err(&c->dev, "Unable to get hw params\n");
|
1584 |
return rval;
|
1585 |
}
|
1586 |
|
1587 |
rval = sensor->pdata->power_set(on);
|
1588 |
if (rval < 0) {
|
1589 |
dev_err(&c->dev, "Unable to set the power state: "
|
1590 |
OV3640_DRIVER_NAME " sensor\n");
|
1591 |
isp_set_xclk(0, OV3640_USE_XCLKB);
|
1592 |
return rval;
|
1593 |
}
|
1594 |
|
1595 |
if (on == V4L2_POWER_ON)
|
1596 |
isp_set_xclk(xclk_current, OV3640_USE_XCLKB);
|
1597 |
else
|
1598 |
isp_set_xclk(0, OV3640_USE_XCLKB);
|
1599 |
|
1600 |
if ((prev_on == V4L2_POWER_STANDBY) && (on == V4L2_POWER_ON) &&
|
1601 |
(sensor->state == SENSOR_DETECTED))
|
1602 |
ov3640_configure(s);
|
1603 |
|
1604 |
if ((on == V4L2_POWER_ON) && (sensor->state == SENSOR_NOT_DETECTED)) {
|
1605 |
rval = ov3640_detect(c);
|
1606 |
if (rval < 0) {
|
1607 |
dev_err(&c->dev, "Unable to detect "
|
1608 |
OV3640_DRIVER_NAME " sensor\n");
|
1609 |
sensor->state = SENSOR_NOT_DETECTED;
|
1610 |
return rval;
|
1611 |
}
|
1612 |
sensor->state = SENSOR_DETECTED;
|
1613 |
sensor->ver = rval;
|
1614 |
pr_info(OV3640_DRIVER_NAME " Chip version 0x%02x detected\n",
|
1615 |
sensor->ver);
|
1616 |
}
|
1617 |
prev_on = on;
|
1618 |
return 0;
|
1619 |
} |
1620 |
|
1621 |
/* |
1622 |
* ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT |
1623 |
* @s: pointer to standard V4L2 device structure |
1624 |
* |
1625 |
* Initialize the sensor device (call ov3640_configure()) |
1626 |
*/ |
1627 |
static int ioctl_init(struct v4l2_int_device *s)
|
1628 |
{ |
1629 |
return 0;
|
1630 |
} |
1631 |
|
1632 |
/** |
1633 |
* ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num |
1634 |
* @s: pointer to standard V4L2 device structure |
1635 |
* |
1636 |
* Delinitialise the dev. at slave detach. The complement of ioctl_dev_init. |
1637 |
*/ |
1638 |
static int ioctl_dev_exit(struct v4l2_int_device *s)
|
1639 |
{ |
1640 |
return 0;
|
1641 |
} |
1642 |
|
1643 |
/** |
1644 |
* ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num |
1645 |
* @s: pointer to standard V4L2 device structure |
1646 |
* |
1647 |
* Initialise the device when slave attaches to the master. Returns 0 if |
1648 |
* ov3640 device could be found, otherwise returns appropriate error. |
1649 |
*/ |
1650 |
static int ioctl_dev_init(struct v4l2_int_device *s)
|
1651 |
{ |
1652 |
struct ov3640_sensor *sensor = s->priv;
|
1653 |
struct i2c_client *c = sensor->i2c_client;
|
1654 |
int err;
|
1655 |
|
1656 |
err = ov3640_detect(c);
|
1657 |
if (err < 0) {
|
1658 |
dev_err(&c->dev, "Unable to detect " OV3640_DRIVER_NAME |
1659 |
" sensor\n");
|
1660 |
return err;
|
1661 |
}
|
1662 |
|
1663 |
sensor->ver = err;
|
1664 |
pr_info(OV3640_DRIVER_NAME " chip version 0x%02x detected\n",
|
1665 |
sensor->ver);
|
1666 |
|
1667 |
return 0;
|
1668 |
} |
1669 |
|
1670 |
/** |
1671 |
* ioctl_enum_framesizes - V4L2 sensor if handler for vidioc_int_enum_framesizes |
1672 |
* @s: pointer to standard V4L2 device structure |
1673 |
* @frms: pointer to standard V4L2 framesizes enumeration structure |
1674 |
* |
1675 |
* Returns possible framesizes depending on choosen pixel format |
1676 |
**/ |
1677 |
static int ioctl_enum_framesizes(struct v4l2_int_device *s,
|
1678 |
struct v4l2_frmsizeenum *frms)
|
1679 |
{ |
1680 |
int ifmt;
|
1681 |
|
1682 |
for (ifmt = 0; ifmt < NUM_CAPTURE_FORMATS; ifmt++) {
|
1683 |
if (frms->pixel_format == ov3640_formats[ifmt].pixelformat)
|
1684 |
break;
|
1685 |
}
|
1686 |
/* Is requested pixelformat not found on sensor? */
|
1687 |
if (ifmt == NUM_CAPTURE_FORMATS)
|
1688 |
return -EINVAL;
|
1689 |
|
1690 |
/* Do we already reached all discrete framesizes? */
|
1691 |
if (frms->index >= 2)
|
1692 |
return -EINVAL;
|
1693 |
|
1694 |
frms->type = V4L2_FRMSIZE_TYPE_DISCRETE;
|
1695 |
frms->discrete.width = ov3640_sizes[frms->index].width;
|
1696 |
frms->discrete.height = ov3640_sizes[frms->index].height;
|
1697 |
|
1698 |
return 0;
|
1699 |
} |
1700 |
|
1701 |
const struct v4l2_fract ov3640_frameintervals[] = {
|
1702 |
{ .numerator = 2, .denominator = 15 },
|
1703 |
{ .numerator = 1, .denominator = 15 },
|
1704 |
{ .numerator = 1, .denominator = 30 },
|
1705 |
}; |
1706 |
|
1707 |
static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
|
1708 |
struct v4l2_frmivalenum *frmi)
|
1709 |
{ |
1710 |
int ifmt;
|
1711 |
|
1712 |
for (ifmt = 0; ifmt < NUM_CAPTURE_FORMATS; ifmt++) {
|
1713 |
if (frmi->pixel_format == ov3640_formats[ifmt].pixelformat)
|
1714 |
break;
|
1715 |
}
|
1716 |
/* Is requested pixelformat not found on sensor? */
|
1717 |
if (ifmt == NUM_CAPTURE_FORMATS)
|
1718 |
return -EINVAL;
|
1719 |
|
1720 |
/* Do we already reached all discrete framesizes? */
|
1721 |
|
1722 |
if ((frmi->width == ov3640_sizes[1].width) &&
|
1723 |
(frmi->height == ov3640_sizes[1].height)) {
|
1724 |
/* FIXME: The only frameinterval supported by QXGA capture is
|
1725 |
* 2/15 fps |
1726 |
*/ |
1727 |
if (frmi->index != 0)
|
1728 |
return -EINVAL;
|
1729 |
} else {
|
1730 |
if (frmi->index >= 3)
|
1731 |
return -EINVAL;
|
1732 |
}
|
1733 |
|
1734 |
frmi->type = V4L2_FRMIVAL_TYPE_DISCRETE;
|
1735 |
frmi->discrete.numerator =
|
1736 |
ov3640_frameintervals[frmi->index].numerator;
|
1737 |
frmi->discrete.denominator =
|
1738 |
ov3640_frameintervals[frmi->index].denominator;
|
1739 |
|
1740 |
return 0;
|
1741 |
} |
1742 |
|
1743 |
static struct v4l2_int_ioctl_desc ov3640_ioctl_desc[] = {
|
1744 |
{vidioc_int_enum_framesizes_num,
|
1745 |
(v4l2_int_ioctl_func *)ioctl_enum_framesizes},
|
1746 |
{vidioc_int_enum_frameintervals_num,
|
1747 |
(v4l2_int_ioctl_func *)ioctl_enum_frameintervals},
|
1748 |
{vidioc_int_dev_init_num,
|
1749 |
(v4l2_int_ioctl_func *)ioctl_dev_init},
|
1750 |
{vidioc_int_dev_exit_num,
|
1751 |
(v4l2_int_ioctl_func *)ioctl_dev_exit},
|
1752 |
{vidioc_int_s_power_num,
|
1753 |
(v4l2_int_ioctl_func *)ioctl_s_power},
|
1754 |
{vidioc_int_g_priv_num,
|
1755 |
(v4l2_int_ioctl_func *)ioctl_g_priv},
|
1756 |
{vidioc_int_init_num,
|
1757 |
(v4l2_int_ioctl_func *)ioctl_init},
|
1758 |
{vidioc_int_enum_fmt_cap_num,
|
1759 |
(v4l2_int_ioctl_func *)ioctl_enum_fmt_cap},
|
1760 |
{vidioc_int_try_fmt_cap_num,
|
1761 |
(v4l2_int_ioctl_func *)ioctl_try_fmt_cap},
|
1762 |
{vidioc_int_g_fmt_cap_num,
|
1763 |
(v4l2_int_ioctl_func *)ioctl_g_fmt_cap},
|
1764 |
{vidioc_int_s_fmt_cap_num,
|
1765 |
(v4l2_int_ioctl_func *)ioctl_s_fmt_cap},
|
1766 |
{vidioc_int_g_parm_num,
|
1767 |
(v4l2_int_ioctl_func *)ioctl_g_parm},
|
1768 |
{vidioc_int_s_parm_num,
|
1769 |
(v4l2_int_ioctl_func *)ioctl_s_parm},
|
1770 |
{vidioc_int_queryctrl_num,
|
1771 |
(v4l2_int_ioctl_func *)ioctl_queryctrl},
|
1772 |
{vidioc_int_g_ctrl_num,
|
1773 |
(v4l2_int_ioctl_func *)ioctl_g_ctrl},
|
1774 |
{vidioc_int_s_ctrl_num,
|
1775 |
(v4l2_int_ioctl_func *)ioctl_s_ctrl},
|
1776 |
{ vidioc_int_g_crop_num,
|
1777 |
(v4l2_int_ioctl_func *)ioctl_g_crop},
|
1778 |
{vidioc_int_s_crop_num,
|
1779 |
(v4l2_int_ioctl_func *)ioctl_s_crop},
|
1780 |
{ vidioc_int_cropcap_num,
|
1781 |
(v4l2_int_ioctl_func *)ioctl_cropcap},
|
1782 |
}; |
1783 |
|
1784 |
static struct v4l2_int_slave ov3640_slave = {
|
1785 |
.ioctls = ov3640_ioctl_desc,
|
1786 |
.num_ioctls = ARRAY_SIZE(ov3640_ioctl_desc),
|
1787 |
}; |
1788 |
|
1789 |
static struct v4l2_int_device ov3640_int_device = {
|
1790 |
.module = THIS_MODULE,
|
1791 |
.name = OV3640_DRIVER_NAME,
|
1792 |
.priv = &ov3640,
|
1793 |
.type = v4l2_int_type_slave,
|
1794 |
.u = {
|
1795 |
.slave = &ov3640_slave,
|
1796 |
},
|
1797 |
}; |
1798 |
|
1799 |
/* |
1800 |
* ov3640_probe - sensor driver i2c probe handler |
1801 |
* @client: i2c driver client device structure |
1802 |
* |
1803 |
* Register sensor as an i2c client device and V4L2 |
1804 |
* device. |
1805 |
*/ |
1806 |
static int __init |
1807 |
ov3640_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
1808 |
{ |
1809 |
struct ov3640_sensor *sensor = &ov3640;
|
1810 |
int err;
|
1811 |
|
1812 |
if (i2c_get_clientdata(client))
|
1813 |
return -EBUSY;
|
1814 |
|
1815 |
sensor->pdata = client->dev.platform_data;
|
1816 |
|
1817 |
if (!sensor->pdata || !sensor->pdata->default_regs) {
|
1818 |
dev_err(&client->dev, "No platform data?\n");
|
1819 |
return -ENODEV;
|
1820 |
}
|
1821 |
|
1822 |
sensor->v4l2_int_device = &ov3640_int_device;
|
1823 |
sensor->i2c_client = client;
|
1824 |
|
1825 |
i2c_set_clientdata(client, sensor);
|
1826 |
|
1827 |
/* Make the default capture format XGA RGB565 */
|
1828 |
sensor->pix.width = ov3640_sizes[XGA].width;
|
1829 |
sensor->pix.height = ov3640_sizes[XGA].height;
|
1830 |
sensor->pix.pixelformat = V4L2_PIX_FMT_RGB565;
|
1831 |
|
1832 |
err = v4l2_int_device_register(sensor->v4l2_int_device);
|
1833 |
if (err)
|
1834 |
i2c_set_clientdata(client, NULL);
|
1835 |
|
1836 |
return 0;
|
1837 |
} |
1838 |
|
1839 |
/* |
1840 |
* ov3640_remove - sensor driver i2c remove handler |
1841 |
* @client: i2c driver client device structure |
1842 |
* |
1843 |
* Unregister sensor as an i2c client device and V4L2 |
1844 |
* device. Complement of ov3640_probe(). |
1845 |
*/ |
1846 |
static int __exit |
1847 |
ov3640_remove(struct i2c_client *client)
|
1848 |
{ |
1849 |
struct ov3640_sensor *sensor = i2c_get_clientdata(client);
|
1850 |
|
1851 |
if (!client->adapter)
|
1852 |
return -ENODEV; /* our client isn't attached */
|
1853 |
|
1854 |
v4l2_int_device_unregister(sensor->v4l2_int_device);
|
1855 |
i2c_set_clientdata(client, NULL);
|
1856 |
|
1857 |
return 0;
|
1858 |
} |
1859 |
|
1860 |
static const struct i2c_device_id ov3640_id[] = {
|
1861 |
{ OV3640_DRIVER_NAME, 0 },
|
1862 |
{ },
|
1863 |
}; |
1864 |
MODULE_DEVICE_TABLE(i2c, ov3640_id);
|
1865 |
|
1866 |
static struct i2c_driver ov3640sensor_i2c_driver = {
|
1867 |
.driver = {
|
1868 |
.name = OV3640_DRIVER_NAME,
|
1869 |
.owner = THIS_MODULE,
|
1870 |
},
|
1871 |
.probe = ov3640_probe,
|
1872 |
.remove = __exit_p(ov3640_remove),
|
1873 |
.id_table = ov3640_id,
|
1874 |
}; |
1875 |
|
1876 |
static struct ov3640_sensor ov3640 = {
|
1877 |
.timeperframe = {
|
1878 |
.numerator = 1,
|
1879 |
.denominator = 15,
|
1880 |
},
|
1881 |
.state = SENSOR_NOT_DETECTED,
|
1882 |
}; |
1883 |
|
1884 |
/* |
1885 |
* ov3640sensor_init - sensor driver module_init handler |
1886 |
* |
1887 |
* Registers driver as an i2c client driver. Returns 0 on success, |
1888 |
* error code otherwise. |
1889 |
*/ |
1890 |
static int __init ov3640sensor_init(void)
|
1891 |
{ |
1892 |
int err;
|
1893 |
|
1894 |
err = i2c_add_driver(&ov3640sensor_i2c_driver);
|
1895 |
if (err) {
|
1896 |
printk(KERN_ERR "Failed to register" OV3640_DRIVER_NAME ".\n");
|
1897 |
return err;
|
1898 |
}
|
1899 |
return 0;
|
1900 |
} |
1901 |
late_initcall(ov3640sensor_init);
|
1902 |
|
1903 |
/* |
1904 |
* ov3640sensor_cleanup - sensor driver module_exit handler |
1905 |
* |
1906 |
* Unregisters/deletes driver as an i2c client driver. |
1907 |
* Complement of ov3640sensor_init. |
1908 |
*/ |
1909 |
static void __exit ov3640sensor_cleanup(void)
|
1910 |
{ |
1911 |
i2c_del_driver(&ov3640sensor_i2c_driver);
|
1912 |
} |
1913 |
module_exit(ov3640sensor_cleanup);
|
1914 |
|
1915 |
MODULE_LICENSE("GPL");
|
1916 |
MODULE_DESCRIPTION("OV3640 camera sensor driver");
|
1917 |
|
1918 |
|