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>
33 #include "omnivision.h"
36 static struct sensor_info sensors
[] = {
41 .initialize
= ov_initialize
,
44 .set_hvflip
= ov965x_set_hvflip
,
45 .set_exposure
= ov965x_set_exposure
,
46 .set_auto_gain
= ov_set_autogain
,
47 .flip_detect
= ov965x_flip_detect
,
53 .initialize
= ov_initialize
,
54 .set_auto_exposure
= ov_set_autoexposure
,
55 .set_auto_gain
= ov_set_autogain
,
63 .initialize
= ov_initialize
,
64 .set_exposure
= soi968_set_exposure
,
65 .set_auto_exposure
= ov_set_autoexposure
,
66 .set_auto_gain
= ov_set_autogain
,
74 .initialize
= ov_initialize
,
75 .set_exposure
= ov7660_set_exposure
,
76 .set_auto_exposure
= ov_set_autoexposure
,
77 .set_auto_gain
= ov_set_autogain
,
85 .initialize
= ov_initialize
,
86 .set_auto_exposure
= ov_set_autoexposure
,
87 .set_auto_gain
= ov_set_autogain
,
88 .flip_detect
= ov7670_flip_detect
,
96 .initialize
= micron_initialize
,
97 .set_hvflip
= mt9v111_set_hvflip
,
98 .set_exposure
= mt9v111_set_exposure
,
99 .set_auto_exposure
= mt9v111_set_autoexposure
,
104 .id
= MT9M111_SENSOR
,
107 .initialize
= micron_initialize
,
108 .set_yuv422
= mt9m111_set_yuv422
,
109 .set_bayer
= mt9m111_set_raw
,
114 .id
= MT9V011_SENSOR
,
117 .initialize
= micron_initialize
,
118 .set_hvflip
= mt9v011_set_hvflip
,
119 .set_exposure
= mt9v011_set_exposure
,
124 .id
= MT9M001_SENSOR
,
127 .initialize
= micron_initialize
,
133 static __u16 known_cams
[][2] = {
134 {0x6240, MT9M001_SENSOR
},
135 {0x6242, MT9M111_SENSOR
},
136 {0x6248, OV9655_SENSOR
},
137 {0x624e, SOI968_SENSOR
},
138 {0x624f, OV9650_SENSOR
},
139 {0x6253, OV9650_SENSOR
},
140 {0x6260, OV7670_SENSOR
},
141 {0x627b, OV7660_SENSOR
},
142 {0x627f, OV9650_SENSOR
},
143 {0x6288, OV9655_SENSOR
},
144 {0x628e, SOI968_SENSOR
},
145 {0x62a0, OV7670_SENSOR
},
146 {0x62b3, OV9655_SENSOR
},
147 {0x62bb, OV7660_SENSOR
},
148 /* The following PIDs have VIDs different from 0x0c45. */
149 {0x00f4, OV9650_SENSOR
},
150 {0x013d, OV7660_SENSOR
},
153 int dev_microdia_assign_sensor(struct usb_microdia
*dev
)
156 __u16 pid
= le16_to_cpu(dev
->udev
->descriptor
.idProduct
);
158 for (i
= 0; i
< ARRAY_SIZE(known_cams
); i
++) {
159 if (pid
== known_cams
[i
][0]) {
160 for (j
= 0; j
< ARRAY_SIZE(sensors
); j
++) {
161 if (known_cams
[i
][1] == sensors
[j
].id
) {
162 dev
->camera
.sensor
= &(sensors
[j
]);
169 if ((pid
== 0x6270) || (pid
== 0x62b0)) {
170 ret
= micron_probe(dev
);
171 for (j
= 0; j
< ARRAY_SIZE(sensors
); j
++) {
172 if (ret
== sensors
[j
].id
) {
173 dev
->camera
.sensor
= &(sensors
[j
]);
179 UDIA_ERROR("Could not assign sensor: "
180 "Please report to microdia@googlegroups.com .\n");
185 int dev_microdia_initialize_sensor(struct usb_microdia
*dev
)
188 if (dev
&& dev
->camera
.sensor
->initialize
)
189 ret
= dev
->camera
.sensor
->initialize(dev
);
193 static struct microdia_video_format default_fmts
[] = {
195 .pix_fmt
= V4L2_PIX_FMT_SBGGR8
,
196 .desc
= "Bayer 8bit (BGGR)",
199 {160, 120, SN9C20X_1_4_SCALE
,
202 {320, 240, SN9C20X_1_2_SCALE
,
205 {640, 480, SN9C20X_NO_SCALE
,
209 .set_format
= sn9c20x_set_raw
212 .pix_fmt
= V4L2_PIX_FMT_JPEG
,
213 .desc
= "JPEG (YUV 4:2:2)",
216 {160, 120, SN9C20X_1_4_SCALE
,
219 {320, 240, SN9C20X_1_2_SCALE
,
222 {640, 480, SN9C20X_NO_SCALE
,
226 .set_format
= sn9c20x_set_jpeg
229 .pix_fmt
= V4L2_PIX_FMT_YUYV
,
230 .desc
= "YUV 4:2:2 (YUYV)",
233 {160, 120, SN9C20X_1_4_SCALE
,
236 {320, 240, SN9C20X_1_2_SCALE
,
239 {640, 480, SN9C20X_NO_SCALE
,
247 int dev_microdia_assign_fmts(struct usb_microdia
*dev
)
251 dev
->camera
.fmts
= default_fmts
;
252 dev
->camera
.nfmts
= ARRAY_SIZE(default_fmts
);
254 for (i
= 0; i
< ARRAY_SIZE(default_fmts
); i
++) {
255 if ((dev
->camera
.sensor
->set_yuv422
!= NULL
) &&
256 (dev
->camera
.fmts
[i
].pix_fmt
== V4L2_PIX_FMT_YUYV
))
257 dev
->camera
.fmts
[i
].set_format
=
258 dev
->camera
.sensor
->set_yuv422
;
259 if ((dev
->camera
.sensor
->set_bayer
!= NULL
) &&
260 (dev
->camera
.fmts
[i
].pix_fmt
== V4L2_PIX_FMT_SBGGR8
))
261 dev
->camera
.fmts
[i
].set_format
=
262 dev
->camera
.sensor
->set_bayer
;
263 for (j
= 0; j
< N_MODES
; j
++) {
264 dev
->camera
.fmts
[i
].modes
[j
].hw_window
[0] =
265 dev
->camera
.sensor
->hstart
;
266 dev
->camera
.fmts
[i
].modes
[j
].hw_window
[1] =
267 dev
->camera
.sensor
->vstart
;
275 * @brief Wrapper function for camera-setting functions
277 * @param dev Pointer to device structure
281 int dev_microdia_camera_settings(struct usb_microdia
*dev
)
283 dev_microdia_camera_set_contrast(dev
);
284 dev_microdia_camera_set_brightness(dev
);
285 dev_microdia_camera_set_gamma(dev
);
286 dev_microdia_camera_set_exposure(dev
);
287 dev_microdia_camera_set_hvflip(dev
);
288 dev_microdia_camera_set_sharpness(dev
);
289 dev_microdia_camera_set_rgb_gain(dev
);
290 dev_microdia_camera_set_auto_exposure(dev
);
291 dev_microdia_camera_set_auto_gain(dev
);
292 dev_microdia_camera_set_auto_whitebalance(dev
);
297 * @brief Wrapper function for device-specific contrast functions
299 * @param dev Pointer to device structure
301 * @returns 0 or negative error value
304 int dev_microdia_camera_set_contrast(struct usb_microdia
*dev
)
307 if (dev
&& dev
->camera
.set_contrast
)
308 ret
= dev
->camera
.set_contrast(dev
);
313 * @brief Wrapper function for device-specific brightness functions
315 * @param dev Pointer to device structure
317 * @returns 0 or negative error value
320 int dev_microdia_camera_set_brightness(struct usb_microdia
*dev
)
323 if (dev
&& dev
->camera
.set_brightness
)
324 ret
= dev
->camera
.set_brightness(dev
);
329 * @brief Wrapper function for device-specific gamma functions
331 * @param dev Pointer to device structure
333 * @returns 0 or negative error value
336 int dev_microdia_camera_set_gamma(struct usb_microdia
*dev
)
339 if (dev
&& dev
->camera
.set_gamma
)
340 ret
= dev
->camera
.set_gamma(dev
);
345 * @brief Wrapper function for device-specific exposure functions
347 * @param dev Pointer to device structure
349 * @returns 0 or negative error value
352 int dev_microdia_camera_set_exposure(struct usb_microdia
*dev
)
354 if (dev
&& dev
->camera
.sensor
->set_exposure
!= NULL
)
355 return dev
->camera
.sensor
->set_exposure(dev
);
361 * @brief Wrapper function for device-specific hvflip functions
363 * @param dev Pointer to device structure
365 * @returns 0 or negative error value
368 int dev_microdia_camera_set_hvflip(struct usb_microdia
*dev
)
371 if (dev
&& dev
->camera
.sensor
->set_hvflip
)
372 ret
= dev
->camera
.sensor
->set_hvflip(dev
);
378 * @brief Wrapper function for device-specific sharpness functions
380 * @param dev Pointer to device structure
382 * @returns 0 or negative error value
385 int dev_microdia_camera_set_sharpness(struct usb_microdia
*dev
)
388 if (dev
&& dev
->camera
.set_sharpness
)
389 ret
= dev
->camera
.set_sharpness(dev
);
395 * @brief Wrapper function for device-specific rgb-gain functions
397 * @param dev Pointer to device structure
399 * @returns 0 or negative error value
402 int dev_microdia_camera_set_rgb_gain(struct usb_microdia
*dev
)
405 if (dev
&& dev
->camera
.set_rgb_gain
)
406 ret
= dev
->camera
.set_rgb_gain(dev
);
412 * @brief Wrapper function for device-specific auto-exposure functions
414 * @param dev Pointer to device structure
416 * @returns 0 or negative error value
419 int dev_microdia_camera_set_auto_exposure(struct usb_microdia
*dev
)
422 if (dev
&& dev
->camera
.sensor
->set_auto_exposure
)
423 ret
= dev
->camera
.sensor
->set_auto_exposure(dev
);
429 * @brief Wrapper function for device-specific auto-gain functions
431 * @param dev Pointer to device structure
433 * @returns 0 or negative error value
436 int dev_microdia_camera_set_auto_gain(struct usb_microdia
*dev
)
439 if (dev
&& dev
->camera
.sensor
->set_auto_gain
)
440 ret
= dev
->camera
.sensor
->set_auto_gain(dev
);
446 * @brief Wrapper function for device-specific auto-whitebalance functions
448 * @param dev Pointer to device structure
450 * @returns 0 or negative error value
453 int dev_microdia_camera_set_auto_whitebalance(struct usb_microdia
*dev
)
456 if (dev
&& dev
->camera
.sensor
->set_auto_whitebalance
)
457 ret
= dev
->camera
.sensor
->set_auto_whitebalance(dev
);
463 * @brief Wrapper function for device-specific initialization functions
465 * @param dev Pointer to device structure
468 * @returns 0 or negative error value
471 int dev_microdia_initialize_device(struct usb_microdia
*dev
, __u32 flags
)
473 switch (flags
>> 16) {
474 case (SN9C20X_BRIDGE
>> 16):
475 UDIA_INFO("Detected SN9C20X Bridge\n");
476 return sn9c20x_initialize(dev
);
478 UDIA_INFO("Unsupported bridge\n");
484 * @brief Wrapper function for for enable video stream for specific bridge
486 * @param dev Pointer to device structure
487 * @param enable Contains the wanted state
492 int dev_microdia_enable_video(struct usb_microdia
*dev
, int enable
)
495 if (dev
&& dev
->camera
.enable_video
)
496 ret
= dev
->camera
.enable_video(dev
, enable
);