3 * @author Nicolas VIVIEN
6 * @brief Device specific functions
8 * @note Copyright (C) Nicolas VIVIEN
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <linux/errno.h>
28 #include <linux/string.h>
32 #include "sn9c20x-bridge.h"
33 #include "omnivision.h"
36 int (*sn_probes
[])(struct usb_sn9c20x
*dev
) = {
41 struct sn9c20x_video_mode sn9c20x_modes
[SN9C20X_N_MODES
] = {
45 .scale
= SN9C20X_1_4_SCALE
,
46 .window
= {65, 48, 1024, 768}
51 .scale
= SN9C20X_1_4_SCALE
,
52 .window
= {0, 0, 640, 480}
57 .scale
= SN9C20X_1_2_SCALE
,
58 .window
= {145, 96, 704, 576}
63 .scale
= SN9C20X_1_2_SCALE
,
64 .window
= {0, 0, 640, 480}
69 .scale
= SN9C20X_NO_SCALE
,
70 .window
= {145, 96, 704, 576}
75 .scale
= SN9C20X_NO_SCALE
,
76 .window
= {0, 0, 640, 480}
80 struct sn9c20x_video_format sn9c20x_fmts
[SN9C20X_N_FMTS
] = {
82 .pix_fmt
= V4L2_PIX_FMT_SBGGR8
,
83 .desc
= "Bayer 8bit (BGGR)",
85 .set_format
= sn9c20x_set_raw
,
88 .pix_fmt
= V4L2_PIX_FMT_YUV420
,
89 .desc
= "I420 (YUV 4:2:0)",
91 .set_format
= sn9c20x_set_yuv420
,
94 .pix_fmt
= V4L2_PIX_FMT_YUYV
,
95 .desc
= "YUYV (YUV 4:2:0)",
97 .set_format
= sn9c20x_set_yuv422
,
100 .pix_fmt
= V4L2_PIX_FMT_JPEG
,
101 .desc
= "JPEG (YUV 4:2:2)",
103 .set_format
= sn9c20x_set_jpeg
,
107 int sn9c20x_initialize_sensor(struct usb_sn9c20x
*dev
)
112 dev
->camera
.min_yavg
= 30;
113 dev
->camera
.max_yavg
= 60;
114 dev
->camera
.min_stable_yavg
= 32;
115 dev
->camera
.max_stable_yavg
= 58;
117 /* Probe sensor first if sensor set to probe*/
118 if (dev
->camera
.sensor
== PROBE_SENSOR
) {
119 for (i
= 0; i
< ARRAY_SIZE(sn_probes
); i
++) {
120 ret
= sn_probes
[i
](dev
);
123 dev
->camera
.sensor
= ret
;
127 switch (dev
->camera
.sensor
) {
129 sn9c20x_write_i2c_array(dev
, soi968_init
, 0);
130 dev
->camera
.set_exposure
= soi968_set_exposure
;
131 dev
->camera
.set_auto_exposure
= ov_set_autoexposure
;
132 dev
->camera
.set_auto_gain
= ov_set_autogain
;
133 dev
->camera
.button_detect
= soi968_button_detect
;
134 dev
->camera
.hstart
= 60;
135 dev
->camera
.vstart
= 11;
136 UDIA_INFO("Detected SOI968 Sensor.\n");
139 sn9c20x_write_i2c_array(dev
, ov9650_init
, 0);
140 dev
->camera
.hstart
= 1;
141 dev
->camera
.vstart
= 7;
142 dev
->camera
.set_hvflip
= ov965x_set_hvflip
;
143 dev
->camera
.set_exposure
= ov965x_set_exposure
;
144 dev
->camera
.set_auto_gain
= ov_set_autogain
;
145 dev
->camera
.flip_detect
= ov965x_flip_detect
;
146 dev
->camera
.get_yavg
= ov965x_get_yavg
;
147 UDIA_INFO("Detected OV9650 Sensor.\n");
150 sn9c20x_write_i2c_array(dev
, ov9655_init
, 0);
151 dev
->camera
.set_auto_exposure
= ov_set_autoexposure
;
152 dev
->camera
.set_auto_gain
= ov_set_autogain
;
153 dev
->camera
.hstart
= 0;
154 dev
->camera
.vstart
= 7;
155 UDIA_INFO("Detected OV9655 Sensor.\n");
158 sn9c20x_write_i2c_array(dev
, ov7670_init
, 0);
159 dev
->camera
.set_auto_exposure
= ov_set_autoexposure
;
160 dev
->camera
.set_exposure
= ov7660_set_exposure
;
161 dev
->camera
.set_auto_gain
= ov_set_autogain
;
162 dev
->camera
.flip_detect
= ov7670_flip_detect
;
163 dev
->camera
.hstart
= 0;
164 dev
->camera
.vstart
= 1;
165 UDIA_INFO("Detected OV7670 Sensor.\n");
168 sn9c20x_write_i2c_array(dev
, ov7660_init
, 0);
169 dev
->camera
.set_exposure
= ov7660_set_exposure
;
170 dev
->camera
.set_auto_gain
= ov_set_autogain
;
171 dev
->camera
.hstart
= 1;
172 dev
->camera
.vstart
= 1;
173 dev
->camera
.get_yavg
= ov965x_get_yavg
;
174 UDIA_INFO("Detected OV7660 Sensor.\n");
177 sn9c20x_write_i2c_array(dev
, mt9v111_init
, 1);
178 dev
->camera
.set_hvflip
= mt9v111_set_hvflip
;
179 dev
->camera
.set_exposure
= mt9v111_set_exposure
;
180 dev
->camera
.set_auto_exposure
= mt9v111_set_autoexposure
;
181 dev
->camera
.hstart
= 2;
182 dev
->camera
.vstart
= 2;
183 UDIA_INFO("Detected MT9V111 Sensor.\n");
186 sn9c20x_write_i2c_array(dev
, mt9m111_init
, 1);
187 dev
->camera
.hstart
= 6;
188 dev
->camera
.vstart
= 2;
189 UDIA_INFO("Detected MT9M111 Sensor.\n");
192 sn9c20x_write_i2c_array(dev
, mt9v011_init
, 1);
193 dev
->camera
.set_hvflip
= mt9v011_set_hvflip
;
194 dev
->camera
.set_exposure
= mt9v011_set_exposure
;
195 dev
->camera
.hstart
= 2;
196 dev
->camera
.vstart
= 2;
197 UDIA_INFO("Detected MT9V011 Sensor.\n");
200 sn9c20x_write_i2c_array(dev
, mt9m001_init
, 1);
201 dev
->camera
.hstart
= 2;
202 dev
->camera
.vstart
= 2;
203 UDIA_INFO("Detected MT9M001 Sensor.\n");
206 dev
->camera
.i2c_flags
|= SN9C20X_I2C_400KHZ
;
207 sn9c20x_write_i2c_array(dev
, hv7131r_init
, 0);
208 dev
->camera
.set_hvflip
= hv7131r_set_hvflip
;
209 dev
->camera
.set_gain
= hv7131r_set_gain
;
210 dev
->camera
.set_exposure
= hv7131r_set_exposure
;
211 dev
->camera
.hstart
= 0;
212 dev
->camera
.vstart
= 1;
213 UDIA_INFO("Detected HV7131R Sensor.\n");
217 UDIA_INFO("Unsupported sensor.\n");
224 * @brief Wrapper function to detect hardware states
226 * @param dev Pointer to device structure
230 int dev_sn9c20x_call_constantly(struct usb_sn9c20x
*dev
)
233 /* Know to be broken, temporarely disabled */
234 /*dev_sn9c20x_flip_detection(dev);*/
235 dev_sn9c20x_button_detection(dev
);
236 if (!dev
->camera
.set_auto_exposure
&&
237 dev
->camera
.get_yavg
&&
238 dev
->vsettings
.auto_exposure
== V4L2_EXPOSURE_AUTO
) {
239 dev_sn9c20x_perform_soft_ae(dev
);
246 * @brief Wrapper function to detect a flipped sensor
248 * @param dev Pointer to device structure
250 * @returns 0 or negative error value
253 int dev_sn9c20x_flip_detection(struct usb_sn9c20x
*dev
)
256 if (dev
&& dev
->camera
.flip_detect
)
257 ret
= dev
->camera
.flip_detect(dev
);
262 * @brief Wrapper function to detect a pushed button
264 * @param dev Pointer to device structure
266 * @returns 0 or negative error value
269 int dev_sn9c20x_button_detection(struct usb_sn9c20x
*dev
)
272 if (dev
&& dev
->camera
.button_detect
)
273 ret
= dev
->camera
.button_detect(dev
);
278 * @brief Perform software autoexposure
282 * @returns 0 or negative error value
284 * @author Vasily Khoruzhick
286 int dev_sn9c20x_perform_soft_ae(struct usb_sn9c20x
*dev
)
289 static int old_yavg
= -1, old_exp
= -1;
290 int koef
= 100, new_exp
, i
;
294 if (!dev
->camera
.set_exposure
)
296 if (!dev
->camera
.get_yavg
)
299 /* Trying to get average value of Y */
300 while ((yavg
== -1) && (i
--))
301 yavg
= dev
->camera
.get_yavg(dev
);
304 /* Can't get YAVG - we have nothing to do */
308 /* Image is too dark */
309 if (yavg
< dev
->camera
.min_yavg
) {
310 /* yavg can't be 0 - in that way new_exp == infinity */
313 if (old_yavg
!= -1) {
314 /* Previous correction was made to make image darker,
315 * but we made it too dark. Calculating our error
316 * and taking it into account.
317 * Usually error is 0.7 - 2, so we multiply it by 100
319 if (old_yavg
> dev
->camera
.max_yavg
)
320 koef
= 100 * dev
->camera
.
321 min_stable_yavg
/ yavg
;
326 /* Calculating new exposure value. We assuming that
327 * exposure linearly depends on YAVG, but we taking
328 * our calculated error into account */
329 new_exp
= (dev
->camera
.min_stable_yavg
330 * dev
->vsettings
.exposure
* 100) / (yavg
* koef
);
332 /* Exposure can't be more than 0xff or less than 0x1 */
338 old_exp
= dev
->vsettings
.exposure
;
341 /* Applying new exposure */
342 dev
->vsettings
.exposure
= new_exp
;
343 dev
->camera
.set_exposure(dev
);
346 /* Image is too bright */
347 else if (yavg
> dev
->camera
.max_yavg
) {
348 /* yavg can't be 0 - in that way new_exp == infinity */
351 if (old_yavg
!= -1) {
353 /* Previous correction was made to make image brighter,
354 * but we made it too bright. Calculating our error
355 * and taking it into account.
356 * Usually error is 0.7 - 2, so we multiply it by 100
358 if (old_yavg
< dev
->camera
.min_yavg
)
359 koef
= 100 * yavg
/ dev
->camera
.
365 /* Calculating new exposure value. We assuming that
366 * exposure linearly depends on YAVG, but we taking
367 * our calculated error into account */
368 new_exp
= (koef
* dev
->camera
.max_stable_yavg
369 * dev
->vsettings
.exposure
) / (yavg
* 100);
371 /* Exposure can't be more than 0xff or less than 0x1 */
377 old_exp
= dev
->vsettings
.exposure
;
380 /* Applying new exposure */
381 dev
->vsettings
.exposure
= new_exp
;
382 dev
->camera
.set_exposure(dev
);