Commit f423b9a8 authored by Luca Risolia's avatar Luca Risolia Committed by Mauro Carvalho Chehab

V4L/DVB (5474): SN9C1xx driver updates

@ Don't assume that SOF headers can't cross packets boundaries
@ Fix compression quality selection
+ Add support for MI-0360 image sensor
* Documentation updates
@ Fix sysfs
@ MI0343 rewritten
* HV7131R color fixes and add new ABLC control
* Rename the archive from "sn9c102" to "sn9c1xx"
* fix typos
* better support for TAS5110D
@ fix OV7630 wrong colors
@ Don't return an error if no input buffers are enqueued yet on VIDIOC_STREAMON
* Add informations about colorspaces
* More appropriate error codes in case of failure of some system calls
* More precise hardware detection
* Add more informations about supported hardware in the documentation
+ More supported devices
+ Add support for HV7131R image sensor
Signed-off-by: default avatarLuca Risolia <luca.risolia@studio.unibo.it>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 9ab7e323
...@@ -25,7 +25,7 @@ Index ...@@ -25,7 +25,7 @@ Index
1. Copyright 1. Copyright
============ ============
Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
2. Disclaimer 2. Disclaimer
...@@ -216,10 +216,10 @@ Description: Debugging information level, from 0 to 3: ...@@ -216,10 +216,10 @@ Description: Debugging information level, from 0 to 3:
1 = critical errors 1 = critical errors
2 = significant informations 2 = significant informations
3 = more verbose messages 3 = more verbose messages
Level 3 is useful for testing only, when only one device Level 3 is useful for testing only. It also shows some more
is used. It also shows some more informations about the informations about the hardware being detected.
hardware being detected. This parameter can be changed at This parameter can be changed at runtime thanks to the /sys
runtime thanks to the /sys filesystem interface. filesystem interface.
Default: 2 Default: 2
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
...@@ -235,7 +235,7 @@ created in the /sys/class/video4linux/videoX directory. You can set the green ...@@ -235,7 +235,7 @@ created in the /sys/class/video4linux/videoX directory. You can set the green
channel's gain by writing the desired value to it. The value may range from 0 channel's gain by writing the desired value to it. The value may range from 0
to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103, to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103,
SN9C105 and SN9C120 bridges. SN9C105 and SN9C120 bridges.
Similarly, only for the SN9C103, SN9C105 and SN9120 controllers, blue and red Similarly, only for the SN9C103, SN9C105 and SN9C120 controllers, blue and red
gain control files are available in the same directory, for which accepted gain control files are available in the same directory, for which accepted
values may range from 0 to 127. values may range from 0 to 127.
...@@ -402,38 +402,49 @@ Vendor ID Product ID ...@@ -402,38 +402,49 @@ Vendor ID Product ID
0x0c45 0x60bc 0x0c45 0x60bc
0x0c45 0x60be 0x0c45 0x60be
0x0c45 0x60c0 0x0c45 0x60c0
0x0c45 0x60c2
0x0c45 0x60c8 0x0c45 0x60c8
0x0c45 0x60cc 0x0c45 0x60cc
0x0c45 0x60ea 0x0c45 0x60ea
0x0c45 0x60ec 0x0c45 0x60ec
0x0c45 0x60ef
0x0c45 0x60fa 0x0c45 0x60fa
0x0c45 0x60fb 0x0c45 0x60fb
0x0c45 0x60fc 0x0c45 0x60fc
0x0c45 0x60fe 0x0c45 0x60fe
0x0c45 0x6102
0x0c45 0x6108
0x0c45 0x610f
0x0c45 0x6130 0x0c45 0x6130
0x0c45 0x6138
0x0c45 0x613a 0x0c45 0x613a
0x0c45 0x613b 0x0c45 0x613b
0x0c45 0x613c 0x0c45 0x613c
0x0c45 0x613e 0x0c45 0x613e
The list above does not imply that all those devices work with this driver: up The list above does not imply that all those devices work with this driver: up
until now only the ones that assemble the following image sensors are until now only the ones that assemble the following pairs of SN9C1xx bridges
supported; kernel messages will always tell you whether this is the case (see and image sensors are supported; kernel messages will always tell you whether
"Module loading" paragraph): this is the case (see "Module loading" paragraph):
Model Manufacturer Image sensor / SN9C1xx bridge | SN9C10[12] SN9C103 SN9C105 SN9C120
----- ------------ -------------------------------------------------------------------------------
HV7131D Hynix Semiconductor, Inc. HV7131D Hynix Semiconductor | Yes No No No
MI-0343 Micron Technology, Inc. HV7131R Hynix Semiconductor | No Yes Yes Yes
OV7630 OmniVision Technologies, Inc. MI-0343 Micron Technology | Yes No No No
OV7660 OmniVision Technologies, Inc. MI-0360 Micron Technology | No Yes No No
PAS106B PixArt Imaging, Inc. OV7630 OmniVision Technologies | Yes Yes No No
PAS202BCA PixArt Imaging, Inc. OV7660 OmniVision Technologies | No No Yes Yes
PAS202BCB PixArt Imaging, Inc. PAS106B PixArt Imaging | Yes No No No
TAS5110C1B Taiwan Advanced Sensor Corporation PAS202B PixArt Imaging | Yes Yes No No
TAS5130D1B Taiwan Advanced Sensor Corporation TAS5110C1B Taiwan Advanced Sensor | Yes No No No
TAS5110D Taiwan Advanced Sensor | Yes No No No
Some of the available control settings of each image sensor are supported TAS5130D1B Taiwan Advanced Sensor | Yes No No No
"Yes" means that the pair is supported by the driver, while "No" means that the
pair does not exist or is not supported by the driver.
Only some of the available control settings of each image sensor are supported
through the V4L2 interface. through the V4L2 interface.
Donations of new models for further testing and support would be much Donations of new models for further testing and support would be much
...@@ -482,8 +493,8 @@ The SN9C1xx PC Camera Controllers can send images in two possible video ...@@ -482,8 +493,8 @@ The SN9C1xx PC Camera Controllers can send images in two possible video
formats over the USB: either native "Sequential RGB Bayer" or compressed. formats over the USB: either native "Sequential RGB Bayer" or compressed.
The compression is used to achieve high frame rates. With regard to the The compression is used to achieve high frame rates. With regard to the
SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding
algorithm described below, while the SN9C105 and SN9C120 the compression is algorithm described below, while with regard to the SN9C105 and SN9C120 the
based on the JPEG standard. compression is based on the JPEG standard.
The current video format may be selected or queried from the user application The current video format may be selected or queried from the user application
by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2 by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2
API specifications. API specifications.
...@@ -573,4 +584,5 @@ order): ...@@ -573,4 +584,5 @@ order):
- Mizuno Takafumi for the donation of a webcam; - Mizuno Takafumi for the donation of a webcam;
- an "anonymous" donator (who didn't want his name to be revealed) for the - an "anonymous" donator (who didn't want his name to be revealed) for the
donation of a webcam. donation of a webcam.
- an anonymous donator for the donation of four webcams. - an anonymous donator for the donation of four webcams and two boards with ten
image sensors.
...@@ -3606,7 +3606,7 @@ L: linux-usb-devel@lists.sourceforge.net ...@@ -3606,7 +3606,7 @@ L: linux-usb-devel@lists.sourceforge.net
W: http://www.connecttech.com W: http://www.connecttech.com
S: Supported S: Supported
USB SN9C10x DRIVER USB SN9C1xx DRIVER
P: Luca Risolia P: Luca Risolia
M: luca.risolia@studio.unibo.it M: luca.risolia@studio.unibo.it
L: linux-usb-devel@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net
......
sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ sn9c102-objs := sn9c102_core.o \
sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \ sn9c102_hv7131d.o \
sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ sn9c102_hv7131r.o \
sn9c102_mi0343.o \
sn9c102_mi0360.o \
sn9c102_ov7630.o \
sn9c102_ov7660.o \
sn9c102_pas106b.o \
sn9c102_pas202bcb.o \
sn9c102_tas5110c1b.o \
sn9c102_tas5110d.o \
sn9c102_tas5130d1b.o sn9c102_tas5130d1b.o
obj-$(CONFIG_USB_SN9C102) += sn9c102.o obj-$(CONFIG_USB_SN9C102) += sn9c102.o
...@@ -78,8 +78,13 @@ enum sn9c102_stream_state { ...@@ -78,8 +78,13 @@ enum sn9c102_stream_state {
typedef char sn9c102_sof_header_t[62]; typedef char sn9c102_sof_header_t[62];
struct sn9c102_sof_t {
sn9c102_sof_header_t header;
u16 bytesread;
};
struct sn9c102_sysfs_attr { struct sn9c102_sysfs_attr {
u8 reg, i2c_reg; u16 reg, i2c_reg;
sn9c102_sof_header_t frame_header; sn9c102_sof_header_t frame_header;
}; };
...@@ -112,7 +117,7 @@ struct sn9c102_device { ...@@ -112,7 +117,7 @@ struct sn9c102_device {
struct v4l2_jpegcompression compression; struct v4l2_jpegcompression compression;
struct sn9c102_sysfs_attr sysfs; struct sn9c102_sysfs_attr sysfs;
sn9c102_sof_header_t sof_header; struct sn9c102_sof_t sof;
u16 reg[384]; u16 reg[384];
struct sn9c102_module_param module_param; struct sn9c102_module_param module_param;
...@@ -182,8 +187,8 @@ do { \ ...@@ -182,8 +187,8 @@ do { \
if ((level) == 1 || (level) == 2) \ if ((level) == 1 || (level) == 2) \
pr_info("sn9c102: " fmt "\n", ## args); \ pr_info("sn9c102: " fmt "\n", ## args); \
else if ((level) == 3) \ else if ((level) == 3) \
pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \ pr_debug("sn9c102: [%s:%d] " fmt "\n", \
__LINE__ , ## args); \ __FUNCTION__, __LINE__ , ## args); \
} \ } \
} while (0) } while (0)
#else #else
...@@ -194,8 +199,8 @@ do { \ ...@@ -194,8 +199,8 @@ do { \
#undef PDBG #undef PDBG
#define PDBG(fmt, args...) \ #define PDBG(fmt, args...) \
dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
__FUNCTION__, __LINE__ , ## args) __LINE__ , ## args)
#undef PDBGG #undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
......
This diff is collapsed.
...@@ -89,16 +89,22 @@ static const struct usb_device_id sn9c102_id_table[] = { ...@@ -89,16 +89,22 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
/* SN9C120 */ /* SN9C120 */
{ SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
...@@ -114,12 +120,15 @@ static const struct usb_device_id sn9c102_id_table[] = { ...@@ -114,12 +120,15 @@ static const struct usb_device_id sn9c102_id_table[] = {
Functions must return 0 on success, the appropriate error otherwise. Functions must return 0 on success, the appropriate error otherwise.
*/ */
extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
extern int sn9c102_probe_hv7131r(struct sn9c102_device* cam);
extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
extern int sn9c102_probe_mi0360(struct sn9c102_device* cam);
extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
extern int sn9c102_probe_ov7660(struct sn9c102_device* cam); extern int sn9c102_probe_ov7660(struct sn9c102_device* cam);
extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam);
extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
/* /*
...@@ -128,13 +137,16 @@ extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); ...@@ -128,13 +137,16 @@ extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
the order of the list below, from top to bottom. the order of the list below, from top to bottom.
*/ */
static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
&sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
&sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
&sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
&sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
&sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
&sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
&sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
&sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
&sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
&sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
NULL, NULL,
}; };
......
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h" #include "sn9c102_sensor.h"
static struct sn9c102_sensor hv7131d;
static int hv7131d_init(struct sn9c102_device* cam) static int hv7131d_init(struct sn9c102_device* cam)
{ {
int err = 0; int err = 0;
...@@ -153,7 +150,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam, ...@@ -153,7 +150,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor hv7131d = { static struct sn9c102_sensor hv7131d = {
.name = "HV7131D", .name = "HV7131D",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_100KHZ, .frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES, .interface = SN9C102_I2C_2WIRES,
...@@ -263,7 +260,7 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam) ...@@ -263,7 +260,7 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
if (r0 < 0 || r1 < 0) if (r0 < 0 || r1 < 0)
return -EIO; return -EIO;
if (r0 != 0x00 && r1 != 0x04) if (r0 != 0x00 || r1 != 0x04)
return -ENODEV; return -ENODEV;
sn9c102_attach_sensor(cam, &hv7131d); sn9c102_attach_sensor(cam, &hv7131d);
......
This diff is collapsed.
...@@ -22,12 +22,9 @@ ...@@ -22,12 +22,9 @@
#include "sn9c102_sensor.h" #include "sn9c102_sensor.h"
static struct sn9c102_sensor mi0343;
static u8 mi0343_i2c_data[5+1];
static int mi0343_init(struct sn9c102_device* cam) static int mi0343_init(struct sn9c102_device* cam)
{ {
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
int err = 0; int err = 0;
err += sn9c102_write_reg(cam, 0x00, 0x10); err += sn9c102_write_reg(cam, 0x00, 0x10);
...@@ -38,20 +35,20 @@ static int mi0343_init(struct sn9c102_device* cam) ...@@ -38,20 +35,20 @@ static int mi0343_init(struct sn9c102_device* cam)
err += sn9c102_write_reg(cam, 0x07, 0x18); err += sn9c102_write_reg(cam, 0x07, 0x18);
err += sn9c102_write_reg(cam, 0xa0, 0x19); err += sn9c102_write_reg(cam, 0xa0, 0x19);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
0x0d, 0x00, 0x01, 0, 0); 0x00, 0x01, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
0x0d, 0x00, 0x00, 0, 0); 0x00, 0x00, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
0x03, 0x01, 0xe1, 0, 0); 0x01, 0xe1, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
0x04, 0x02, 0x81, 0, 0); 0x02, 0x81, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
0x05, 0x00, 0x17, 0, 0); 0x00, 0x17, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
0x06, 0x00, 0x11, 0, 0); 0x00, 0x11, 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
0x62, 0x04, 0x9a, 0, 0); 0x04, 0x9a, 0, 0);
return err; return err;
} }
...@@ -60,43 +57,46 @@ static int mi0343_init(struct sn9c102_device* cam) ...@@ -60,43 +57,46 @@ static int mi0343_init(struct sn9c102_device* cam)
static int mi0343_get_ctrl(struct sn9c102_device* cam, static int mi0343_get_ctrl(struct sn9c102_device* cam,
struct v4l2_control* ctrl) struct v4l2_control* ctrl)
{ {
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
u8 data[5+1];
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_EXPOSURE: case V4L2_CID_EXPOSURE:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
0x09, 2+1, mi0343_i2c_data) < 0) 2+1, data) < 0)
return -EIO; return -EIO;
ctrl->value = mi0343_i2c_data[2]; ctrl->value = data[2];
return 0; return 0;
case V4L2_CID_GAIN: case V4L2_CID_GAIN:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
0x35, 2+1, mi0343_i2c_data) < 0) 2+1, data) < 0)
return -EIO; return -EIO;
break; break;
case V4L2_CID_HFLIP: case V4L2_CID_HFLIP:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
0x20, 2+1, mi0343_i2c_data) < 0) 2+1, data) < 0)
return -EIO; return -EIO;
ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0; ctrl->value = data[3] & 0x20 ? 1 : 0;
return 0; return 0;
case V4L2_CID_VFLIP: case V4L2_CID_VFLIP:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
0x20, 2+1, mi0343_i2c_data) < 0) 2+1, data) < 0)
return -EIO; return -EIO;
ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0; ctrl->value = data[3] & 0x80 ? 1 : 0;
return 0; return 0;
case V4L2_CID_RED_BALANCE: case V4L2_CID_RED_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
0x2d, 2+1, mi0343_i2c_data) < 0) 2+1, data) < 0)
return -EIO; return -EIO;
break; break;
case V4L2_CID_BLUE_BALANCE: case V4L2_CID_BLUE_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
0x2c, 2+1, mi0343_i2c_data) < 0) 2+1, data) < 0)
return -EIO; return -EIO;
break; break;
case SN9C102_V4L2_CID_GREEN_BALANCE: case SN9C102_V4L2_CID_GREEN_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
0x2e, 2+1, mi0343_i2c_data) < 0) 2+1, data) < 0)
return -EIO; return -EIO;
break; break;
default: default:
...@@ -108,7 +108,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, ...@@ -108,7 +108,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
case V4L2_CID_RED_BALANCE: case V4L2_CID_RED_BALANCE:
case V4L2_CID_BLUE_BALANCE: case V4L2_CID_BLUE_BALANCE:
case SN9C102_V4L2_CID_GREEN_BALANCE: case SN9C102_V4L2_CID_GREEN_BALANCE:
ctrl->value = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8); ctrl->value = data[3] | (data[2] << 8);
if (ctrl->value >= 0x10 && ctrl->value <= 0x3f) if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
ctrl->value -= 0x10; ctrl->value -= 0x10;
else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f) else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
...@@ -124,6 +124,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, ...@@ -124,6 +124,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
static int mi0343_set_ctrl(struct sn9c102_device* cam, static int mi0343_set_ctrl(struct sn9c102_device* cam,
const struct v4l2_control* ctrl) const struct v4l2_control* ctrl)
{ {
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
u16 reg = 0; u16 reg = 0;
int err = 0; int err = 0;
...@@ -143,50 +144,42 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam, ...@@ -143,50 +144,42 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam,
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_EXPOSURE: case V4L2_CID_EXPOSURE:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
mi0343.i2c_slave_id,
0x09, ctrl->value, 0x00, 0x09, ctrl->value, 0x00,
0, 0); 0, 0);
break; break;
case V4L2_CID_GAIN: case V4L2_CID_GAIN:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
mi0343.i2c_slave_id,
0x35, reg >> 8, reg & 0xff, 0x35, reg >> 8, reg & 0xff,
0, 0); 0, 0);
break; break;
case V4L2_CID_HFLIP: case V4L2_CID_HFLIP:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
mi0343.i2c_slave_id,
0x20, ctrl->value ? 0x40:0x00, 0x20, ctrl->value ? 0x40:0x00,
ctrl->value ? 0x20:0x00, ctrl->value ? 0x20:0x00,
0, 0); 0, 0);
break; break;
case V4L2_CID_VFLIP: case V4L2_CID_VFLIP:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
mi0343.i2c_slave_id,
0x20, ctrl->value ? 0x80:0x00, 0x20, ctrl->value ? 0x80:0x00,
ctrl->value ? 0x80:0x00, ctrl->value ? 0x80:0x00,
0, 0); 0, 0);
break; break;
case V4L2_CID_RED_BALANCE: case V4L2_CID_RED_BALANCE:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
mi0343.i2c_slave_id,
0x2d, reg >> 8, reg & 0xff, 0x2d, reg >> 8, reg & 0xff,
0, 0); 0, 0);
break; break;
case V4L2_CID_BLUE_BALANCE: case V4L2_CID_BLUE_BALANCE:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
mi0343.i2c_slave_id,
0x2c, reg >> 8, reg & 0xff, 0x2c, reg >> 8, reg & 0xff,
0, 0); 0, 0);
break; break;
case SN9C102_V4L2_CID_GREEN_BALANCE: case SN9C102_V4L2_CID_GREEN_BALANCE:
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
mi0343.i2c_slave_id,
0x2b, reg >> 8, reg & 0xff, 0x2b, reg >> 8, reg & 0xff,
0, 0); 0, 0);
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
mi0343.i2c_slave_id,
0x2e, reg >> 8, reg & 0xff, 0x2e, reg >> 8, reg & 0xff,
0, 0); 0, 0);
break; break;
...@@ -216,16 +209,15 @@ static int mi0343_set_crop(struct sn9c102_device* cam, ...@@ -216,16 +209,15 @@ static int mi0343_set_crop(struct sn9c102_device* cam,
static int mi0343_set_pix_format(struct sn9c102_device* cam, static int mi0343_set_pix_format(struct sn9c102_device* cam,
const struct v4l2_pix_format* pix) const struct v4l2_pix_format* pix)
{ {
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
int err = 0; int err = 0;
if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
mi0343.i2c_slave_id,
0x0a, 0x00, 0x03, 0, 0); 0x0a, 0x00, 0x03, 0, 0);
err += sn9c102_write_reg(cam, 0x20, 0x19); err += sn9c102_write_reg(cam, 0x20, 0x19);
} else { } else {
err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
mi0343.i2c_slave_id,
0x0a, 0x00, 0x05, 0, 0); 0x0a, 0x00, 0x05, 0, 0);
err += sn9c102_write_reg(cam, 0xa0, 0x19); err += sn9c102_write_reg(cam, 0xa0, 0x19);
} }
...@@ -237,7 +229,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam, ...@@ -237,7 +229,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor mi0343 = { static struct sn9c102_sensor mi0343 = {
.name = "MI-0343", .name = "MI-0343",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.frequency = SN9C102_I2C_100KHZ, .frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES, .interface = SN9C102_I2C_2WIRES,
.i2c_slave_id = 0x5d, .i2c_slave_id = 0x5d,
...@@ -343,6 +335,7 @@ static struct sn9c102_sensor mi0343 = { ...@@ -343,6 +335,7 @@ static struct sn9c102_sensor mi0343 = {
int sn9c102_probe_mi0343(struct sn9c102_device* cam) int sn9c102_probe_mi0343(struct sn9c102_device* cam)
{ {
u8 data[5+1];
int err = 0; int err = 0;
err += sn9c102_write_reg(cam, 0x01, 0x01); err += sn9c102_write_reg(cam, 0x01, 0x01);
...@@ -352,10 +345,10 @@ int sn9c102_probe_mi0343(struct sn9c102_device* cam) ...@@ -352,10 +345,10 @@ int sn9c102_probe_mi0343(struct sn9c102_device* cam)
return -EIO; return -EIO;
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
2, mi0343_i2c_data) < 0) 2, data) < 0)
return -EIO; return -EIO;
if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3) if (data[4] != 0x32 || data[3] != 0xe3)
return -ENODEV; return -ENODEV;
sn9c102_attach_sensor(cam, &mi0343); sn9c102_attach_sensor(cam, &mi0343);
......
This diff is collapsed.
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h" #include "sn9c102_sensor.h"
static struct sn9c102_sensor ov7630;
static int ov7630_init(struct sn9c102_device* cam) static int ov7630_init(struct sn9c102_device* cam)
{ {
int err = 0; int err = 0;
...@@ -40,7 +37,7 @@ static int ov7630_init(struct sn9c102_device* cam) ...@@ -40,7 +37,7 @@ static int ov7630_init(struct sn9c102_device* cam)
err += sn9c102_i2c_write(cam, 0x12, 0x8d); err += sn9c102_i2c_write(cam, 0x12, 0x8d);
err += sn9c102_i2c_write(cam, 0x12, 0x0d); err += sn9c102_i2c_write(cam, 0x12, 0x0d);
err += sn9c102_i2c_write(cam, 0x11, 0x00); err += sn9c102_i2c_write(cam, 0x11, 0x00);
err += sn9c102_i2c_write(cam, 0x15, 0x34); err += sn9c102_i2c_write(cam, 0x15, 0x35);
err += sn9c102_i2c_write(cam, 0x16, 0x03); err += sn9c102_i2c_write(cam, 0x16, 0x03);
err += sn9c102_i2c_write(cam, 0x17, 0x1c); err += sn9c102_i2c_write(cam, 0x17, 0x1c);
err += sn9c102_i2c_write(cam, 0x18, 0xbd); err += sn9c102_i2c_write(cam, 0x18, 0xbd);
......
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h" #include "sn9c102_sensor.h"
static struct sn9c102_sensor ov7660;
static int ov7660_init(struct sn9c102_device* cam) static int ov7660_init(struct sn9c102_device* cam)
{ {
int err = 0; int err = 0;
......
...@@ -23,9 +23,6 @@ ...@@ -23,9 +23,6 @@
#include "sn9c102_sensor.h" #include "sn9c102_sensor.h"
static struct sn9c102_sensor pas106b;
static int pas106b_init(struct sn9c102_device* cam) static int pas106b_init(struct sn9c102_device* cam)
{ {
int err = 0; int err = 0;
...@@ -172,7 +169,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam, ...@@ -172,7 +169,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor pas106b = { static struct sn9c102_sensor pas106b = {
.name = "PAS106B", .name = "PAS106B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES, .interface = SN9C102_I2C_2WIRES,
......
...@@ -28,9 +28,6 @@ ...@@ -28,9 +28,6 @@
#include "sn9c102_sensor.h" #include "sn9c102_sensor.h"
static struct sn9c102_sensor pas202bcb;
static int pas202bcb_init(struct sn9c102_device* cam) static int pas202bcb_init(struct sn9c102_device* cam)
{ {
int err = 0; int err = 0;
......
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h" #include "sn9c102_sensor.h"
static struct sn9c102_sensor tas5110c1b;
static int tas5110c1b_init(struct sn9c102_device* cam) static int tas5110c1b_init(struct sn9c102_device* cam)
{ {
int err = 0; int err = 0;
...@@ -98,7 +95,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam, ...@@ -98,7 +95,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor tas5110c1b = { static struct sn9c102_sensor tas5110c1b = {
.name = "TAS5110C1B", .name = "TAS5110C1B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.sysfs_ops = SN9C102_I2C_WRITE, .sysfs_ops = SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_100KHZ, .frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_3WIRES, .interface = SN9C102_I2C_3WIRES,
...@@ -146,7 +143,6 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) ...@@ -146,7 +143,6 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
const struct usb_device_id tas5110c1b_id_table[] = { const struct usb_device_id tas5110c1b_id_table[] = {
{ USB_DEVICE(0x0c45, 0x6001), }, { USB_DEVICE(0x0c45, 0x6001), },
{ USB_DEVICE(0x0c45, 0x6005), }, { USB_DEVICE(0x0c45, 0x6005), },
{ USB_DEVICE(0x0c45, 0x6007), },
{ USB_DEVICE(0x0c45, 0x60ab), }, { USB_DEVICE(0x0c45, 0x60ab), },
{ } { }
}; };
......
/***************************************************************************
* Plug-in for TAS5110D image sensor connected to the SN9C1xx PC Camera *
* Controllers *
* *
* Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
***************************************************************************/
#include "sn9c102_sensor.h"
static int tas5110d_init(struct sn9c102_device* cam)
{
int err = 0;
err += sn9c102_write_reg(cam, 0x01, 0x01);
err += sn9c102_write_reg(cam, 0x04, 0x01);
err += sn9c102_write_reg(cam, 0x0a, 0x14);
err += sn9c102_write_reg(cam, 0x60, 0x17);
err += sn9c102_write_reg(cam, 0x06, 0x18);
err += sn9c102_write_reg(cam, 0xfb, 0x19);
err += sn9c102_i2c_write(cam, 0x9a, 0xca);
return err;
}
static int tas5110d_set_crop(struct sn9c102_device* cam,
const struct v4l2_rect* rect)
{
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
int err = 0;
u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
err += sn9c102_write_reg(cam, h_start, 0x12);
err += sn9c102_write_reg(cam, v_start, 0x13);
err += sn9c102_write_reg(cam, 0x14, 0x1a);
err += sn9c102_write_reg(cam, 0x0a, 0x1b);
return err;
}
static int tas5110d_set_pix_format(struct sn9c102_device* cam,
const struct v4l2_pix_format* pix)
{
int err = 0;
if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
err += sn9c102_write_reg(cam, 0x3b, 0x19);
else
err += sn9c102_write_reg(cam, 0xfb, 0x19);
return err;
}
static struct sn9c102_sensor tas5110d = {
.name = "TAS5110D",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.sysfs_ops = SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
.i2c_slave_id = 0x61,
.init = &tas5110d_init,
.cropcap = {
.bounds = {
.left = 0,
.top = 0,
.width = 352,
.height = 288,
},
.defrect = {
.left = 0,
.top = 0,
.width = 352,
.height = 288,
},
},
.set_crop = &tas5110d_set_crop,
.pix_format = {
.width = 352,
.height = 288,
.pixelformat = V4L2_PIX_FMT_SBGGR8,
.priv = 8,
},
.set_pix_format = &tas5110d_set_pix_format
};
int sn9c102_probe_tas5110d(struct sn9c102_device* cam)
{
const struct usb_device_id tas5110d_id_table[] = {
{ USB_DEVICE(0x0c45, 0x6007), },
{ }
};
if (!sn9c102_match_id(cam, tas5110d_id_table))
return -ENODEV;
sn9c102_attach_sensor(cam, &tas5110d);
return 0;
}
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h" #include "sn9c102_sensor.h"
static struct sn9c102_sensor tas5130d1b;
static int tas5130d1b_init(struct sn9c102_device* cam) static int tas5130d1b_init(struct sn9c102_device* cam)
{ {
int err = 0; int err = 0;
...@@ -99,7 +96,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam, ...@@ -99,7 +96,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor tas5130d1b = { static struct sn9c102_sensor tas5130d1b = {
.name = "TAS5130D1B", .name = "TAS5130D1B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.sysfs_ops = SN9C102_I2C_WRITE, .sysfs_ops = SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_100KHZ, .frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_3WIRES, .interface = SN9C102_I2C_3WIRES,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment