2 * @file sn9c20x-bridge.c
6 * @brief Common functions and data for the Sonix SN9C20x webcam bridge chips.
8 * @note Copyright (C) Dave Neuer
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/delay.h>
28 #include <linux/errno.h>
29 #include <linux/string.h>
31 #include "sn9c20x-bridge.h"
33 int sn9c20x_set_camera_control(struct usb_sn9c20x
*dev
,
34 __u32 control
, __u32 value
)
38 case V4L2_CID_CONTRAST
:
39 if (dev
->camera
.set_contrast
) {
40 dev
->vsettings
.contrast
= value
;
41 ret
= dev
->camera
.set_contrast(dev
);
44 case V4L2_CID_BRIGHTNESS
:
45 if (dev
->camera
.set_brightness
) {
46 dev
->vsettings
.brightness
= value
;
47 ret
= dev
->camera
.set_brightness(dev
);
51 if (dev
->camera
.set_gamma
) {
52 dev
->vsettings
.gamma
= value
;
53 ret
= dev
->camera
.set_gamma(dev
);
56 case V4L2_CID_SATURATION
:
57 if (dev
->camera
.set_saturation
) {
58 dev
->vsettings
.colour
= value
;
59 ret
= dev
->camera
.set_saturation(dev
);
62 case V4L2_CID_SHARPNESS
:
63 if (dev
->camera
.set_sharpness
) {
64 dev
->vsettings
.sharpness
= value
;
65 ret
= dev
->camera
.set_sharpness(dev
);
68 case V4L2_CID_RED_BALANCE
:
69 if (dev
->camera
.set_red_gain
) {
70 dev
->vsettings
.red_gain
= value
& 0x7f;
71 ret
= dev
->camera
.set_red_gain(dev
);
74 case V4L2_CID_BLUE_BALANCE
:
75 if (dev
->camera
.set_blue_gain
) {
76 dev
->vsettings
.blue_gain
= value
& 0x7f;
77 ret
= dev
->camera
.set_blue_gain(dev
);
81 if (dev
->camera
.set_hvflip
) {
82 dev
->vsettings
.hflip
= value
;
83 ret
= dev
->camera
.set_hvflip(dev
);
87 if (dev
->camera
.set_hvflip
) {
88 dev
->vsettings
.vflip
= value
;
89 ret
= dev
->camera
.set_hvflip(dev
);
92 case V4L2_CID_AUTOGAIN
:
93 if (dev
->camera
.set_auto_gain
) {
94 dev
->vsettings
.auto_gain
= value
;
95 ret
= dev
->camera
.set_auto_gain(dev
);
98 case V4L2_CID_EXPOSURE
:
99 if (dev
->camera
.set_exposure
) {
100 dev
->vsettings
.exposure
= value
;
101 ret
= dev
->camera
.set_exposure(dev
);
105 if (dev
->camera
.set_gain
) {
106 dev
->vsettings
.gain
= value
;
107 ret
= dev
->camera
.set_gain(dev
);
110 case V4L2_CID_AUTO_WHITE_BALANCE
:
111 if (dev
->camera
.set_auto_whitebalance
) {
112 dev
->vsettings
.auto_whitebalance
= value
;
113 ret
= dev
->camera
.set_auto_whitebalance(dev
);
116 case V4L2_CID_EXPOSURE_AUTO
:
117 dev
->vsettings
.auto_exposure
= value
;
119 if (dev
->camera
.set_auto_exposure
)
120 ret
= dev
->camera
.set_auto_exposure(dev
);
127 * @brief Switch Video stream on and off
129 * @param dev Pointer to device structure
130 * @param enable On or off
132 * @author Brian Johnson
134 * @return 0 or negative error code
137 int sn9c20x_enable_video(struct usb_sn9c20x
*dev
, int enable
)
142 ret
= usb_sn9c20x_control_read(dev
, 0x1061, &value
, 1);
148 ret
= usb_sn9c20x_control_write(dev
, 0x1061, &value
, 1);
151 ret
= usb_sn9c20x_control_write(dev
, 0x1061, &value
, 1);
154 sn9c20x_set_LEDs(dev
, enable
);
160 * @brief Switch LEDs on and off
162 * @param dev Pointer to device structure
163 * @param enable On or off
165 * @author Josua Grawitter
167 * @return 0 or negative error code
170 int sn9c20x_set_LEDs(struct usb_sn9c20x
*dev
, int enable
)
175 int sensor
= dev
->camera
.sensor
;
225 ret
= usb_sn9c20x_control_write(dev
, 0x1006, led
, 2);
231 * @brief Initializes Micro-Controller's I2C interface
235 * @param dev Pointer to the device
237 * @return Zero (success) or negative (USB-error value)
240 int sn9c20x_i2c_initialize(struct usb_sn9c20x
*dev
)
245 dev
->camera
.i2c_flags
= SN9C20X_I2C_2WIRE
;
247 buf
[0] = dev
->camera
.i2c_flags
;
248 buf
[1] = dev
->camera
.address
;
256 /* Initialize I2C registers to avoid getting no ACK at first I2C operation: */
257 /* Get green diagonal bands w/o this dummy write, Bridge does not know sensor address ? */
258 ret
= usb_sn9c20x_control_write(dev
, 0x10c0, buf
, 9);
266 * @brief Wait until the I2C slave is ready for the next operation
268 * @param dev Pointer to the device
272 * @return Zero for success or a negative error value
275 int sn9c20x_i2c_ack_wait(struct usb_sn9c20x
*dev
, bool highspeed
, bool *slave_error
)
279 int delay
= highspeed
? 100 : 400;
281 for (i
= 0; i
< 5; i
++) {
282 ret
= usb_sn9c20x_control_read(dev
, 0x10c0, &readbuf
, 1);
286 else if (readbuf
& SN9C20X_I2C_ERROR
) {
288 /* probably should come up w/ an error value and
289 * return it via the error return */
291 } else if (readbuf
& SN9C20X_I2C_READY
)
300 * @brief Read up to 5 bytes of data from an I2C slave
302 * @param dev Pointer to the device
303 * @param nbytes Number of bytes to read
304 * @param address The address of the register on the slave to read
305 * @param result A pointer to the location at which the result should be stored
307 * @return Zero for success or a negative error value
310 int sn9c20x_read_i2c_data(struct usb_sn9c20x
*dev
, __u8 nbytes
,
311 __u8 address
, __u8
*result
)
316 if (!dev
|| nbytes
> 4)
319 /* first, we must do a dummy write of just the address */
320 ret
= sn9c20x_write_i2c_data(dev
, 0, address
, NULL
);
325 /* now we issue the same command but with the read bit set
326 * and no slave register address */
327 dev
->camera
.i2c_flags
|= SN9C20X_I2C_READ
;
328 ret
= sn9c20x_write_i2c_data(dev
, nbytes
- 1, 0, row
);
329 dev
->camera
.i2c_flags
&= ~SN9C20X_I2C_READ
;
333 /* finally, ask the bridge for the data */
334 ret
= usb_sn9c20x_control_read(dev
, 0x10c2, row
, 5);
338 UDIA_DEBUG("I2C read: %02x %02x %02x %02x %02x %02x\n",
339 address
, row
[0], row
[1], row
[2], row
[3], row
[4]);
341 for (i
= 0, j
= 5 - nbytes
; i
< nbytes
; i
++, j
++)
348 * @brief Read up to 4 bytes of data from an I2C slave an return them as 16bit values
350 * @param dev Pointer to the device
351 * @param datalen Number of 16bit values to read
352 * @param address The address of the register on the slave to read
353 * @param result A pointer to the location at which the result should be stored
355 * @return Zero for success or a negative error value
358 int sn9c20x_read_i2c_data16(struct usb_sn9c20x
*dev
, __u8 datalen
,
359 __u8 address
, __u16
*result
)
367 ret
= sn9c20x_read_i2c_data(dev
, 2*datalen
, address
, result8
);
368 for (k
= 0; k
< datalen
; k
++)
369 result
[k
] = (result8
[k
*2] << 8) | result8
[k
*2+1];
373 static const char *wasread
= "read from";
374 static const char *waswrite
= "write to";
377 * @brief Write up to 5 bytes of data to an I2C slave
379 * @param dev Pointer to the device
380 * @param nbytes The number of bytes of data
381 * @param address The address of the register on the slave to write
382 * @param data An array containing the data to write
383 * @param last_byte The byte to be sent as last byte of control sequence
385 * @return Zero for success or a negative error value
388 int sn9c20x_write_i2c_data_ext(struct usb_sn9c20x
*dev
, __u8 nbytes
,
389 __u8 address
, const __u8 data
[nbytes
], __u8 last_byte
)
393 bool slave_error
= 0;
395 if (!dev
|| (nbytes
> 0 && !data
) || nbytes
> 4)
398 /* from the point of view of the bridge, the length
399 * includes the address */
400 row
[0] = dev
->camera
.i2c_flags
| ((nbytes
+ 1) << 4);
401 row
[1] = dev
->camera
.address
;
405 for (i
= 0; i
< 4; i
++)
406 row
[i
+ 3] = i
< nbytes
? data
[i
] : 0;
408 UDIA_DEBUG("I2C %s %02x: %02x %02x %02x %02x %02x %02x %02x %02x\n",
409 (dev
->camera
.i2c_flags
& SN9C20X_I2C_READ
? wasread
: waswrite
),
410 address
, row
[0], row
[1], row
[2], row
[3], row
[4], row
[5], row
[6],
413 ret
= usb_sn9c20x_control_write(dev
, 0x10c0, row
, 8);
415 ret
= sn9c20x_i2c_ack_wait(dev
,
416 dev
->camera
.i2c_flags
& SN9C20X_I2C_400KHZ
,
420 UDIA_ERROR("I2C slave 0x%02x returned error during %s address 0x%02x\n",
421 dev
->camera
.address
, (dev
->camera
.i2c_flags
&
422 SN9C20X_I2C_READ
? wasread
: waswrite
), address
);
424 /* there should be no interference with USB errors */
429 UDIA_ERROR("No ack from I2C slave 0x%02x for %s address 0x%02x\n",
430 dev
->camera
.address
, (dev
->camera
.i2c_flags
&
431 SN9C20X_I2C_READ
? wasread
: waswrite
), address
);
439 * @brief Write up to 2 16bit values als single bytes to an I2C slave
441 * @param dev Pointer to the device
442 * @param datalen The number of 16bit data values to write
443 * @param address The address of the register on the slave to write
444 * @param data An array containing the data to write
446 * @return Zero for success or a negative error value
449 int sn9c20x_write_i2c_data16(struct usb_sn9c20x
*dev
, __u8 datalen
,
450 __u8 address
, const __u16 data
[datalen
])
458 for (k
= 0; k
< datalen
; k
++) {
459 data8
[k
*2] = data
[k
] >> 8;
460 data8
[k
*2+1] = data
[k
] & 0xff;
462 ret
= sn9c20x_write_i2c_data(dev
, 2*datalen
, address
, data8
);
466 int sn9c20x_write_i2c_array(struct usb_sn9c20x
*dev
,
467 struct sn9c20x_i2c_regs
*regs
, int bits16
)
474 if (regs
[i
].address
== 0xff)
477 value16
= regs
[i
].value
;
478 ret
= sn9c20x_write_i2c_data16(dev
, 1,
479 regs
[i
].address
, &value16
);
481 value8
= (__u8
)regs
[i
].value
;
482 ret
= sn9c20x_write_i2c_data(dev
, 1,
483 regs
[i
].address
, &value8
);
492 * @brief Set contrast inside sn9c20x chip
496 * @param dev Pointer to the device
498 * @return Zero (success) or negative (USB-error value)
501 int sn9c20x_set_contrast(struct usb_sn9c20x
*dev
)
503 /* from 0x26 to 0x4b */
504 __u8 brightness_contrast
[21] = {0x16, 0x0, 0x2b, 0x0, 0x8, 0x0, 0xf6, 0x0f,
505 0xd2, 0x0f, 0x38, 0x0, 0x34, 0x0, 0xcf, 0x0f,
506 0xfd, 0x0f, 0x0, 0x0, 0x0};
507 __u8 contrast_val
= (dev
->vsettings
.contrast
) * 0x25 / 0x100;
508 __u8 brightness_val
= dev
->vsettings
.brightness
;
510 brightness_val
-= 0x80;
511 brightness_contrast
[18] = brightness_val
;
513 contrast_val
+= 0x26;
514 brightness_contrast
[2] = contrast_val
;
515 brightness_contrast
[0] = 0x13 + (brightness_contrast
[2] - 0x26) * 0x13 / 0x25;
516 brightness_contrast
[4] = 0x7 + (brightness_contrast
[2] - 0x26) * 0x7 / 0x25;
518 return usb_sn9c20x_control_write(dev
, 0x10e1, brightness_contrast
, 21);
522 * @brief Set brightness inside sn9c20x chip
526 * @param dev Pointer to the device
528 * @return Zero (success) or negative (USB-error value)
530 * Wrapper for sn9c20x_set_contrast
533 int sn9c20x_set_brightness(struct usb_sn9c20x
*dev
)
535 return sn9c20x_set_contrast(dev
);
539 * @brief Set gamma inside sn9c20x chip
543 * @param dev Pointer to the device
545 * @return Zero (success) or negative (USB-error value)
548 int sn9c20x_set_gamma(struct usb_sn9c20x
*dev
)
550 int value
= (dev
->vsettings
.gamma
) * 0xb8 / 0x100;
553 __u8 gamma_val
[17] = {0x0a, 0x13, 0x25, 0x37, 0x45, 0x55, 0x65, 0x74,
554 0x83, 0x92, 0xa1, 0xb0, 0xbf, 0xce, 0xdf, 0xea, 0xf5};
557 gamma_val
[1] = 0x13 + (value
* (0xcb - 0x13) / 0xb8);
558 gamma_val
[2] = 0x25 + (value
* (0xee - 0x25) / 0xb8);
559 gamma_val
[3] = 0x37 + (value
* (0xfa - 0x37) / 0xb8);
560 gamma_val
[4] = 0x45 + (value
* (0xfc - 0x45) / 0xb8);
561 gamma_val
[5] = 0x55 + (value
* (0xfb - 0x55) / 0xb8);
562 gamma_val
[6] = 0x65 + (value
* (0xfc - 0x65) / 0xb8);
563 gamma_val
[7] = 0x74 + (value
* (0xfd - 0x74) / 0xb8);
564 gamma_val
[8] = 0x83 + (value
* (0xfe - 0x83) / 0xb8);
565 gamma_val
[9] = 0x92 + (value
* (0xfc - 0x92) / 0xb8);
566 gamma_val
[10] = 0xa1 + (value
* (0xfc - 0xa1) / 0xb8);
567 gamma_val
[11] = 0xb0 + (value
* (0xfc - 0xb0) / 0xb8);
568 gamma_val
[12] = 0xbf + (value
* (0xfb - 0xbf) / 0xb8);
569 gamma_val
[13] = 0xce + (value
* (0xfb - 0xce) / 0xb8);
570 gamma_val
[14] = 0xdf + (value
* (0xfd - 0xdf) / 0xb8);
571 gamma_val
[15] = 0xea + (value
* (0xf9 - 0xea) / 0xb8);
572 gamma_val
[16] = 0xf5;
574 r
= usb_sn9c20x_control_write(dev
, 0x1190, gamma_val
, 17);
580 * @brief Set saturation inside sn9c20x chip
584 * @param dev Pointer to the device
586 * @return Zero (success) or negative (USB-error value)
589 int sn9c20x_set_saturation(struct usb_sn9c20x
*dev
)
595 __u16 saturation
[10][2] = {
608 /* __u16 saturation[10][2] = {
622 for( i
= 0; i
< 10; i
++) {
623 reg
= saturation
[i
][0];
624 value
= saturation
[i
][1]*(dev
->vsettings
.colour
/0xff);
625 ret
= usb_sn9c20x_control_write(dev
, reg
, &value
, 1);
626 UDIA_DEBUG("Saturation - Reg:0x%X Value:0x%X\n", reg
, value
);
637 * @brief Set sharpness inside sn9c20x chip
641 * @param dev Pointer to the device
643 * @return Zero (success) or negative (USB-error value)
646 int sn9c20x_set_sharpness(struct usb_sn9c20x
*dev
)
651 ret
= usb_sn9c20x_control_read(dev
, SN9C20X_SHARPNESS
, val
, 1);
654 val
[0] = (val
[0] & 0xc0) | (dev
->vsettings
.sharpness
& 0x3f);
655 ret
= usb_sn9c20x_control_write(dev
, SN9C20X_SHARPNESS
, val
, 1);
663 * @brief Set red gain inside sn9c20x chip
665 * @author Brian Johnson
667 * @param dev Pointer to the device
669 * @return Zero (success) or negative (USB-error value)
672 int sn9c20x_set_red_gain(struct usb_sn9c20x
*dev
)
677 val
= dev
->vsettings
.red_gain
;
678 ret
= usb_sn9c20x_control_write(dev
, SN9C20X_RED_GAIN
, &val
, 1);
686 * @brief Set blue gain inside sn9c20x chip
688 * @author Brian Johnson
690 * @param dev Pointer to the device
692 * @return Zero (success) or negative (USB-error value)
695 int sn9c20x_set_blue_gain(struct usb_sn9c20x
*dev
)
700 val
= dev
->vsettings
.blue_gain
;
701 ret
= usb_sn9c20x_control_write(dev
, SN9C20X_BLUE_GAIN
, &val
, 1);
710 * @brief Calculate closest resolution to input from application
712 * @author Brian Johnson
714 * @param dev Pointer to the device structure
715 * @param width Requested width of video stream
716 * @param height Requested height of video stream
718 * @retval width Closest possible width of video stream
719 * @retval height Closest possible height of video stream
721 * @return Number of the
724 int sn9c20x_get_closest_resolution(struct usb_sn9c20x
*dev
,
725 int *width
, int *height
)
729 for (i
= SN9C20X_N_MODES
- 1; i
>= 0; i
--) {
730 if (*width
>= sn9c20x_modes
[i
].width
731 && *height
>= sn9c20x_modes
[i
].height
)
735 *width
= sn9c20x_modes
[i
].width
;
736 *height
= sn9c20x_modes
[i
].height
;
742 * @brief Set resolution inside sn9c20x chip
744 * @author Brian Johnson
746 * @param dev Pointer to the device
748 * @param height Height
753 int sn9c20x_set_resolution(struct usb_sn9c20x
*dev
,
754 int width
, int height
)
760 struct sn9c20x_video_mode
*mode
;
762 ret
= sn9c20x_get_closest_resolution(dev
, &width
, &height
);
764 mode
= &sn9c20x_modes
[ret
];
766 dev
->vsettings
.format
.width
= mode
->width
;
767 dev
->vsettings
.format
.height
= mode
->height
;
770 clrwindow
[1] = mode
->width
>> 2;
772 clrwindow
[3] = mode
->height
>> 1;
773 clrwindow
[4] = ((mode
->width
>> 10) & 0x01) |
774 ((mode
->height
>> 8) & 0x06);
778 window
[0] = (mode
->window
[0] + dev
->camera
.hstart
) & 0xff;
779 window
[1] = (mode
->window
[0] + dev
->camera
.hstart
) >> 8;
780 window
[2] = (mode
->window
[1] + dev
->camera
.vstart
) & 0xff;
781 window
[3] = (mode
->window
[1] + dev
->camera
.vstart
) >> 8;
782 window
[4] = mode
->window
[2] >> 4;
783 window
[5] = mode
->window
[3] >> 3;
785 usb_sn9c20x_control_write(dev
, 0x10fb, clrwindow
, 5);
786 usb_sn9c20x_control_write(dev
, 0x1180, window
, 6);
787 usb_sn9c20x_control_write(dev
, SN9C20X_SCALE
, &scale
, 1);
789 UDIA_DEBUG("Set mode [%dx%d]\n", mode
->width
, mode
->height
);
795 int sn9c20x_set_format(struct usb_sn9c20x
*dev
, __u32 format
)
799 for (i
= 0; i
< SN9C20X_N_FMTS
; i
++) {
800 if (sn9c20x_fmts
[i
].pix_fmt
== format
) {
801 dev
->vsettings
.format
.bytesperline
=
802 dev
->vsettings
.format
.width
*
803 sn9c20x_fmts
[i
].depth
/ 8;
804 dev
->vsettings
.format
.sizeimage
=
805 dev
->vsettings
.format
.height
*
806 dev
->vsettings
.format
.bytesperline
;
807 dev
->vsettings
.format
.pixelformat
= format
;
808 dev
->vsettings
.format
.colorspace
= V4L2_COLORSPACE_SRGB
;
809 dev
->vsettings
.format
.priv
= 0;
810 sn9c20x_fmts
[i
].set_format(dev
);
818 void sn9c20x_set_raw(struct usb_sn9c20x
*dev
)
822 usb_sn9c20x_control_write(dev
, 0x10e0, &value
, 1);
823 UDIA_INFO("Using raw output format\n");
826 void sn9c20x_set_jpeg(struct usb_sn9c20x
*dev
)
830 usb_sn9c20x_control_write(dev
, 0x10e0, &value
, 1);
831 UDIA_INFO("Using jpeg output format\n");
834 void sn9c20x_set_yuv420(struct usb_sn9c20x
*dev
)
838 usb_sn9c20x_control_write(dev
, 0x10e0, &value
, 1);
839 UDIA_INFO("Using yuv420 output format\n");
842 void sn9c20x_set_yuv422(struct usb_sn9c20x
*dev
)
846 usb_sn9c20x_control_write(dev
, 0x10e0, &value
, 1);
847 UDIA_INFO("Using yuv422 output format\n");
851 * @brief This function initializes the SN9C20x bridge,
852 * these are the bare minimum writes that must be done for
853 * the bridge to work correctly.
857 * @param dev Pointer to the device
859 * @return Zero for success or error value
862 int sn9c20x_initialize(struct usb_sn9c20x
*dev
)
930 0x0d, 0x08, 0x08, 0x0d, 0x08, 0x08, 0x0d, 0x0d,
931 0x0d, 0x0d, 0x11, 0x0d, 0x0d, 0x11, 0x15, 0x21,
932 0x15, 0x15, 0x11, 0x11, 0x15, 0x2a, 0x1d, 0x1d,
933 0x19, 0x21, 0x32, 0x2a, 0x32, 0x32, 0x2e, 0x2a,
934 0x2e, 0x2e, 0x36, 0x3a, 0x4b, 0x43, 0x36, 0x3a,
935 0x47, 0x3a, 0x2e, 0x2e, 0x43, 0x5c, 0x43, 0x47,
936 0x4f, 0x54, 0x58, 0x58, 0x58, 0x32, 0x3f, 0x60,
937 0x64, 0x5c, 0x54, 0x64, 0x4b, 0x54, 0x58, 0x54
941 0x0d, 0x11, 0x11, 0x15, 0x11, 0x15, 0x26, 0x15,
942 0x15, 0x26, 0x54, 0x36, 0x2e, 0x36, 0x54, 0x54,
943 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
944 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
945 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
946 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
947 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
948 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54
951 for (i
= 0; i
< ARRAY_SIZE(regs
); i
++) {
954 ret
= usb_sn9c20x_control_write(dev
, reg
, &value
, 1);
956 UDIA_INFO("Bridge Init Error (%d). line %d\n", ret
, i
);
961 ret
= usb_sn9c20x_control_write(dev
, 0x1100, qtable1
, 64);
965 ret
= usb_sn9c20x_control_write(dev
, 0x1140, qtable2
, 64);
969 dev
->camera
.set_contrast
= sn9c20x_set_contrast
;
970 dev
->camera
.set_brightness
= sn9c20x_set_brightness
;
971 dev
->camera
.set_gamma
= sn9c20x_set_gamma
;
972 dev
->camera
.set_saturation
= sn9c20x_set_saturation
;
973 dev
->camera
.set_sharpness
= sn9c20x_set_sharpness
;
974 dev
->camera
.set_red_gain
= sn9c20x_set_red_gain
;
975 dev
->camera
.set_blue_gain
= sn9c20x_set_blue_gain
;
977 ret
= sn9c20x_i2c_initialize(dev
);
981 ret
= sn9c20x_initialize_sensor(dev
);
985 UDIA_ERROR("Device Init failed (%d)!\n", ret
);