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

V4L/DVB (5585): SN9C1xx driver updates

* Default color improvements to the OV7660
@ Fix sn9c102_write_reg()
@ Fix sn9c102_i2c_try_raw_read()
@ Fix MI-0343
+ Add support for pair MI0360+SN9C120
+ Add more USB ids
Signed-off-by: default avatarLuca Risolia <luca.risolia@studio.unibo.it>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent b3785596
......@@ -355,6 +355,9 @@ devices assembling the SN9C1xx PC camera controllers:
Vendor ID Product ID
--------- ----------
0x0458 0x7025
0x045e 0x00f5
0x045e 0x00f7
0x0471 0x0327
0x0471 0x0328
0x0c45 0x6001
......@@ -432,7 +435,7 @@ Image sensor / SN9C1xx bridge | SN9C10[12] SN9C103 SN9C105 SN9C120
HV7131D Hynix Semiconductor | Yes No No No
HV7131R Hynix Semiconductor | No Yes Yes Yes
MI-0343 Micron Technology | Yes No No No
MI-0360 Micron Technology | No Yes No No
MI-0360 Micron Technology | No Yes Yes Yes
OV7630 OmniVision Technologies | Yes Yes No No
OV7660 OmniVision Technologies | No No Yes Yes
PAS106B PixArt Imaging | Yes No No No
......@@ -478,13 +481,12 @@ scaling factor is restored to 1.
This driver supports two different video formats: the first one is the "8-bit
Sequential Bayer" format and can be used to obtain uncompressed video data
from the device through the current I/O method, while the second one provides
"raw" compressed video data (without frame headers not related to the
compressed data). The compression quality may vary from 0 to 1 and can be
selected or queried thanks to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2
ioctl's. For maximum flexibility, both the default active video format and the
default compression quality depend on how the image sensor being used is
initialized (as described in the documentation of the API for the image sensors
supplied by this driver).
either "raw" compressed video data (without frame headers not related to the
compressed data) or standard JPEG (with frame headers). The compression quality
may vary from 0 to 1 and can be selected or queried thanks to the
VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum flexibility,
both the default active video format and the default compression quality
depend on how the image sensor being used is initialized.
11. Video frame formats [1]
......
......@@ -141,7 +141,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
void
sn9c102_attach_sensor(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor)
const struct sn9c102_sensor* sensor)
{
memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
}
......
......@@ -48,8 +48,8 @@
#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define SN9C102_MODULE_LICENSE "GPL"
#define SN9C102_MODULE_VERSION "1:1.39"
#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 39)
#define SN9C102_MODULE_VERSION "1:1.44"
#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 44)
/*****************************************************************************/
......@@ -209,38 +209,41 @@ static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
}
/*****************************************************************************/
/*
* Write a sequence of count value/register pairs. Returns -1 after the
* first failed write, or 0 for no errors.
*/
Write a sequence of count value/register pairs. Returns -1 after the first
failed write, or 0 for no errors.
*/
int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2],
int count)
{
struct usb_device* udev = cam->usbdev;
u8* value = cam->control_buffer; /* Needed for DMA'able memory */
u8* buff = cam->control_buffer;
int i, res;
for (i = 0; i < count; i++) {
u8 index = valreg[i][1];
/*
* index is a u8, so it must be <256 and can't be out of range.
* If we put in a check anyway, gcc annoys us with a warning
* that our check is useless. People get all uppity when they
* see warnings in the kernel compile.
*/
*value = valreg[i][0];
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0x08, 0x41, index, 0,
value, 1, SN9C102_CTRL_TIMEOUT);
index is a u8, so it must be <256 and can't be out of range.
If we put in a check anyway, gcc annoys us with a warning
hat our check is useless. People get all uppity when they
see warnings in the kernel compile.
*/
*buff = valreg[i][0];
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08,
0x41, index, 0, buff, 1,
SN9C102_CTRL_TIMEOUT);
if (res < 0) {
DBG(3, "Failed to write a register (value 0x%02X, "
"index 0x%02X, error %d)", *value, index, res);
"index 0x%02X, error %d)", *buff, index, res);
return -1;
}
cam->reg[index] = *value;
cam->reg[index] = *buff;
}
return 0;
......@@ -272,8 +275,8 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
}
/* NOTE: reading some registers always returns 0 */
static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
/* NOTE: with the SN9C10[123] reading some registers always returns 0 */
int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
{
struct usb_device* udev = cam->usbdev;
u8* buff = cam->control_buffer;
......@@ -299,7 +302,8 @@ int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index)
static int
sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor)
sn9c102_i2c_wait(struct sn9c102_device* cam,
const struct sn9c102_sensor* sensor)
{
int i, r;
......@@ -320,7 +324,7 @@ sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor)
static int
sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor)
const struct sn9c102_sensor* sensor)
{
int r , err = 0;
......@@ -342,7 +346,7 @@ sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
static int
sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor)
const struct sn9c102_sensor* sensor)
{
int r;
r = sn9c102_read_reg(cam, 0x08);
......@@ -352,12 +356,12 @@ sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
int
sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor, u8 data0, u8 data1,
u8 n, u8 buffer[])
const struct sn9c102_sensor* sensor, u8 data0,
u8 data1, u8 n, u8 buffer[])
{
struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer;
int err = 0, res;
int i = 0, err = 0, res;
/* Write cycle */
data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
......@@ -402,7 +406,8 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
}
if (buffer)
memcpy(buffer, data, sizeof(buffer));
for (i = 0; i < n && i < 5; i++)
buffer[n-i-1] = data[4-i];
return (int)data[4];
}
......@@ -410,7 +415,7 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
int
sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor, u8 n, u8 data0,
const struct sn9c102_sensor* sensor, u8 n, u8 data0,
u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
{
struct usb_device* udev = cam->usbdev;
......@@ -449,7 +454,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
int
sn9c102_i2c_try_read(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor, u8 address)
const struct sn9c102_sensor* sensor, u8 address)
{
return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
address, 1, NULL);
......@@ -458,7 +463,7 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
int
sn9c102_i2c_try_write(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor, u8 address, u8 value)
const struct sn9c102_sensor* sensor, u8 address, u8 value)
{
return sn9c102_i2c_try_raw_write(cam, sensor, 3,
sensor->i2c_slave_id, address,
......@@ -657,16 +662,6 @@ sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
}
static void
sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
{
static const u8 eoi_marker[2] = {0xff, 0xd9};
memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker));
f->buf.bytesused += sizeof(eoi_marker);
}
static void sn9c102_urb_complete(struct urb *urb)
{
struct sn9c102_device* cam = urb->context;
......@@ -3181,14 +3176,14 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
static const struct file_operations sn9c102_fops = {
.owner = THIS_MODULE,
.open = sn9c102_open,
.open = sn9c102_open,
.release = sn9c102_release,
.ioctl = sn9c102_ioctl,
.ioctl = sn9c102_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.read = sn9c102_read,
.poll = sn9c102_poll,
.mmap = sn9c102_mmap,
.llseek = no_llseek,
.read = sn9c102_read,
.poll = sn9c102_poll,
.mmap = sn9c102_mmap,
.llseek = no_llseek,
};
/*****************************************************************************/
......@@ -3251,7 +3246,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
break;
}
for (i = 0; sn9c102_sensor_table[i]; i++) {
for (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) {
err = sn9c102_sensor_table[i](cam);
if (!err)
break;
......@@ -3262,7 +3257,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
DBG(3, "Support for %s maintained by %s",
cam->sensor.name, cam->sensor.maintainer);
} else {
DBG(1, "No supported image sensor detected");
DBG(1, "No supported image sensor detected for this bridge");
err = -ENODEV;
goto fail;
}
......
......@@ -86,6 +86,8 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), },
/* SN9C105 */
{ SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
......@@ -100,6 +102,7 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
/* SN9C120 */
{ SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), },
......@@ -148,7 +151,6 @@ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
&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 */
NULL,
};
#endif /* _SN9C102_DEVTABLE_H_ */
......@@ -144,7 +144,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam,
}
static struct sn9c102_sensor hv7131d = {
static const struct sn9c102_sensor hv7131d = {
.name = "HV7131D",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
......@@ -248,12 +248,10 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
{0x28, 0x17});
if (err)
return -EIO;
r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
if (r0 < 0 || r1 < 0)
if (err || r0 < 0 || r1 < 0)
return -EIO;
if (r0 != 0x00 || r1 != 0x04)
......
......@@ -44,7 +44,6 @@ static int hv7131r_init(struct sn9c102_device* cam)
{0xb0, 0x2b}, {0xc0, 0x2c},
{0xd0, 0x2d}, {0xe0, 0x2e},
{0xf0, 0x2f}, {0xff, 0x30});
break;
case BRIDGE_SN9C105:
case BRIDGE_SN9C120:
......@@ -254,7 +253,7 @@ static int hv7131r_set_pix_format(struct sn9c102_device* cam,
}
static struct sn9c102_sensor hv7131r = {
static const struct sn9c102_sensor hv7131r = {
.name = "HV7131R",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
......@@ -350,11 +349,8 @@ int sn9c102_probe_hv7131r(struct sn9c102_device* cam)
{0x34, 0x01}, {0x20, 0x17},
{0x34, 0x01}, {0x46, 0x01});
if (err)
return -EIO;
devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
if (devid < 0)
if (err || devid < 0)
return -EIO;
if (devid != 0x02)
......
......@@ -55,45 +55,45 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
struct v4l2_control* ctrl)
{
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
u8 data[5+1];
u8 data[2];
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
data) < 0)
return -EIO;
ctrl->value = data[2];
ctrl->value = data[0];
return 0;
case V4L2_CID_GAIN:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
data) < 0)
return -EIO;
break;
case V4L2_CID_HFLIP:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
data) < 0)
return -EIO;
ctrl->value = data[3] & 0x20 ? 1 : 0;
ctrl->value = data[1] & 0x20 ? 1 : 0;
return 0;
case V4L2_CID_VFLIP:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
data) < 0)
return -EIO;
ctrl->value = data[3] & 0x80 ? 1 : 0;
ctrl->value = data[1] & 0x80 ? 1 : 0;
return 0;
case V4L2_CID_RED_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
data) < 0)
return -EIO;
break;
case V4L2_CID_BLUE_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
data) < 0)
return -EIO;
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
data) < 0)
return -EIO;
break;
default:
......@@ -105,7 +105,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
case V4L2_CID_RED_BALANCE:
case V4L2_CID_BLUE_BALANCE:
case SN9C102_V4L2_CID_GREEN_BALANCE:
ctrl->value = data[3] | (data[2] << 8);
ctrl->value = data[1] | (data[0] << 8);
if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
ctrl->value -= 0x10;
else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
......@@ -223,7 +223,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam,
}
static struct sn9c102_sensor mi0343 = {
static const struct sn9c102_sensor mi0343 = {
.name = "MI-0343",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
......@@ -332,20 +332,17 @@ static struct sn9c102_sensor mi0343 = {
int sn9c102_probe_mi0343(struct sn9c102_device* cam)
{
u8 data[5+1];
int err = 0;
err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
{0x28, 0x17});
u8 data[2];
if (err)
if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
{0x28, 0x17}))
return -EIO;
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
2, data) < 0)
return -EIO;
if (data[4] != 0x32 || data[3] != 0xe3)
if (data[1] != 0x42 || data[0] != 0xe3)
return -ENODEV;
sn9c102_attach_sensor(cam, &mi0343);
......
......@@ -27,20 +27,105 @@ static int mi0360_init(struct sn9c102_device* cam)
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
int err = 0;
err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
{0x0a, 0x14}, {0x40, 0x01},
{0x20, 0x17}, {0x07, 0x18},
{0xa0, 0x19}, {0x02, 0x1c},
{0x03, 0x1d}, {0x0f, 0x1e},
{0x0c, 0x1f}, {0x00, 0x20},
{0x10, 0x21}, {0x20, 0x22},
{0x30, 0x23}, {0x40, 0x24},
{0x50, 0x25}, {0x60, 0x26},
{0x70, 0x27}, {0x80, 0x28},
{0x90, 0x29}, {0xa0, 0x2a},
{0xb0, 0x2b}, {0xc0, 0x2c},
{0xd0, 0x2d}, {0xe0, 0x2e},
{0xf0, 0x2f}, {0xff, 0x30});
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C103:
err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
{0x0a, 0x14}, {0x40, 0x01},
{0x20, 0x17}, {0x07, 0x18},
{0xa0, 0x19}, {0x02, 0x1c},
{0x03, 0x1d}, {0x0f, 0x1e},
{0x0c, 0x1f}, {0x00, 0x20},
{0x10, 0x21}, {0x20, 0x22},
{0x30, 0x23}, {0x40, 0x24},
{0x50, 0x25}, {0x60, 0x26},
{0x70, 0x27}, {0x80, 0x28},
{0x90, 0x29}, {0xa0, 0x2a},
{0xb0, 0x2b}, {0xc0, 0x2c},
{0xd0, 0x2d}, {0xe0, 0x2e},
{0xf0, 0x2f}, {0xff, 0x30});
break;
case BRIDGE_SN9C105:
case BRIDGE_SN9C120:
err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
{0x00, 0x03}, {0x1a, 0x04},
{0x50, 0x05}, {0x20, 0x06},
{0x10, 0x07}, {0x03, 0x10},
{0x08, 0x14}, {0xa2, 0x17},
{0x47, 0x18}, {0x00, 0x19},
{0x1d, 0x1a}, {0x10, 0x1b},
{0x02, 0x1c}, {0x03, 0x1d},
{0x0f, 0x1e}, {0x0c, 0x1f},
{0x00, 0x20}, {0x29, 0x21},
{0x40, 0x22}, {0x54, 0x23},
{0x66, 0x24}, {0x76, 0x25},
{0x85, 0x26}, {0x94, 0x27},
{0xa1, 0x28}, {0xae, 0x29},
{0xbb, 0x2a}, {0xc7, 0x2b},
{0xd3, 0x2c}, {0xde, 0x2d},
{0xea, 0x2e}, {0xf4, 0x2f},
{0xff, 0x30}, {0x00, 0x3F},
{0xC7, 0x40}, {0x01, 0x41},
{0x44, 0x42}, {0x00, 0x43},
{0x44, 0x44}, {0x00, 0x45},
{0x44, 0x46}, {0x00, 0x47},
{0xC7, 0x48}, {0x01, 0x49},
{0xC7, 0x4A}, {0x01, 0x4B},
{0xC7, 0x4C}, {0x01, 0x4D},
{0x44, 0x4E}, {0x00, 0x4F},
{0x44, 0x50}, {0x00, 0x51},
{0x44, 0x52}, {0x00, 0x53},
{0xC7, 0x54}, {0x01, 0x55},
{0xC7, 0x56}, {0x01, 0x57},
{0xC7, 0x58}, {0x01, 0x59},
{0x44, 0x5A}, {0x00, 0x5B},
{0x44, 0x5C}, {0x00, 0x5D},
{0x44, 0x5E}, {0x00, 0x5F},
{0xC7, 0x60}, {0x01, 0x61},
{0xC7, 0x62}, {0x01, 0x63},
{0xC7, 0x64}, {0x01, 0x65},
{0x44, 0x66}, {0x00, 0x67},
{0x44, 0x68}, {0x00, 0x69},
{0x44, 0x6A}, {0x00, 0x6B},
{0xC7, 0x6C}, {0x01, 0x6D},
{0xC7, 0x6E}, {0x01, 0x6F},
{0xC7, 0x70}, {0x01, 0x71},
{0x44, 0x72}, {0x00, 0x73},
{0x44, 0x74}, {0x00, 0x75},
{0x44, 0x76}, {0x00, 0x77},
{0xC7, 0x78}, {0x01, 0x79},
{0xC7, 0x7A}, {0x01, 0x7B},
{0xC7, 0x7C}, {0x01, 0x7D},
{0x44, 0x7E}, {0x00, 0x7F},
{0x14, 0x84}, {0x00, 0x85},
{0x27, 0x86}, {0x00, 0x87},
{0x07, 0x88}, {0x00, 0x89},
{0xEC, 0x8A}, {0x0f, 0x8B},
{0xD8, 0x8C}, {0x0f, 0x8D},
{0x3D, 0x8E}, {0x00, 0x8F},
{0x3D, 0x90}, {0x00, 0x91},
{0xCD, 0x92}, {0x0f, 0x93},
{0xf7, 0x94}, {0x0f, 0x95},
{0x0C, 0x96}, {0x00, 0x97},
{0x00, 0x98}, {0x66, 0x99},
{0x05, 0x9A}, {0x00, 0x9B},
{0x04, 0x9C}, {0x00, 0x9D},
{0x08, 0x9E}, {0x00, 0x9F},
{0x2D, 0xC0}, {0x2D, 0xC1},
{0x3A, 0xC2}, {0x05, 0xC3},
{0x04, 0xC4}, {0x3F, 0xC5},
{0x00, 0xC6}, {0x00, 0xC7},
{0x50, 0xC8}, {0x3C, 0xC9},
{0x28, 0xCA}, {0xD8, 0xCB},
{0x14, 0xCC}, {0xEC, 0xCD},
{0x32, 0xCE}, {0xDD, 0xCF},
{0x32, 0xD0}, {0xDD, 0xD1},
{0x6A, 0xD2}, {0x50, 0xD3},
{0x00, 0xD4}, {0x00, 0xD5},
{0x00, 0xD6});
break;
default:
break;
}
err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
0x00, 0x01, 0, 0);
......@@ -65,50 +150,50 @@ static int mi0360_get_ctrl(struct sn9c102_device* cam,
struct v4l2_control* ctrl)
{
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
u8 data[5+1];
u8 data[2];
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
data) < 0)
return -EIO;
ctrl->value = data[2];
ctrl->value = data[0];
return 0;
case V4L2_CID_GAIN:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
data) < 0)
return -EIO;
ctrl->value = data[3];
ctrl->value = data[1];
return 0;
case V4L2_CID_RED_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
data) < 0)
return -EIO;
ctrl->value = data[3];
ctrl->value = data[1];
return 0;
case V4L2_CID_BLUE_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
data) < 0)
return -EIO;
ctrl->value = data[3];
ctrl->value = data[1];
return 0;
case SN9C102_V4L2_CID_GREEN_BALANCE:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
data) < 0)
return -EIO;
ctrl->value = data[3];
ctrl->value = data[1];
return 0;
case V4L2_CID_HFLIP:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
data) < 0)
return -EIO;
ctrl->value = data[3] & 0x20 ? 1 : 0;
ctrl->value = data[1] & 0x20 ? 1 : 0;
return 0;
case V4L2_CID_VFLIP:
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
2+1, data) < 0)
if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
data) < 0)
return -EIO;
ctrl->value = data[3] & 0x80 ? 1 : 0;
ctrl->value = data[1] & 0x80 ? 1 : 0;
return 0;
default:
return -EINVAL;
......@@ -178,8 +263,19 @@ static int mi0360_set_crop(struct sn9c102_device* cam,
{
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
int err = 0;
u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C103:
h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0;
break;
case BRIDGE_SN9C105:
case BRIDGE_SN9C120:
h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
break;
default:
break;
}
err += sn9c102_write_reg(cam, h_start, 0x12);
err += sn9c102_write_reg(cam, v_start, 0x13);
......@@ -194,24 +290,30 @@ static int mi0360_set_pix_format(struct sn9c102_device* cam,
struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
int err = 0;
if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x0a, 0x00, 0x02, 0, 0);
err += sn9c102_write_reg(cam, 0x20, 0x19);
} else {
if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x0a, 0x00, 0x05, 0, 0);
err += sn9c102_write_reg(cam, 0x60, 0x19);
if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
err += sn9c102_write_reg(cam, 0xa6, 0x17);
} else {
err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x0a, 0x00, 0x02, 0, 0);
err += sn9c102_write_reg(cam, 0x20, 0x19);
if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
err += sn9c102_write_reg(cam, 0xa2, 0x17);
}
return err;
}
static struct sn9c102_sensor mi0360 = {
static const struct sn9c102_sensor mi0360 = {
.name = "MI-0360",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C103,
.supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
.i2c_slave_id = 0x5d,
......@@ -317,19 +419,31 @@ static struct sn9c102_sensor mi0360 = {
int sn9c102_probe_mi0360(struct sn9c102_device* cam)
{
u8 data[5+1];
int err;
err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
{0x28, 0x17});
if (err)
return -EIO;
u8 data[2];
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C103:
if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
{0x28, 0x17}))
return -EIO;
break;
case BRIDGE_SN9C105:
case BRIDGE_SN9C120:
if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
{0x01, 0x01}, {0x00, 0x01},
{0x28, 0x17}))
return -EIO;
break;
default:
break;
}
if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
2+1, data) < 0)
2, data) < 0)
return -EIO;
if (data[2] != 0x82 || data[3] != 0x43)
if (data[0] != 0x82 || data[1] != 0x43)
return -ENODEV;
sn9c102_attach_sensor(cam, &mi0360);
......
......@@ -29,9 +29,8 @@ static int ov7630_init(struct sn9c102_device* cam)
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
err = sn9c102_write_const_regs(cam, {0x00, 0x14},
{0x60, 0x17}, {0x0f, 0x18},
{0x50, 0x19});
err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17},
{0x0f, 0x18}, {0x50, 0x19});
err += sn9c102_i2c_write(cam, 0x12, 0x8d);
err += sn9c102_i2c_write(cam, 0x12, 0x0d);
......@@ -61,7 +60,6 @@ static int ov7630_init(struct sn9c102_device* cam)
err += sn9c102_i2c_write(cam, 0x71, 0x00);
err += sn9c102_i2c_write(cam, 0x74, 0x21);
err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
break;
case BRIDGE_SN9C103:
err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
......@@ -253,7 +251,7 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam,
}
static struct sn9c102_sensor ov7630 = {
static const struct sn9c102_sensor ov7630 = {
.name = "OV7630",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
......@@ -408,19 +406,16 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
err = sn9c102_write_const_regs(cam, {0x01, 0x01},
{0x00, 0x01}, {0x28, 0x17});
err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
{0x28, 0x17});
break;
case BRIDGE_SN9C103: /* do _not_ change anything! */
err = sn9c102_write_const_regs(cam, {0x09, 0x01},
{0x42, 0x01}, {0x28, 0x17},
{0x44, 0x02});
err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01},
{0x28, 0x17}, {0x44, 0x02});
pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
if (err || pid < 0) { /* try a different initialization */
err = sn9c102_write_reg(cam, 0x01, 0x01);
err += sn9c102_write_reg(cam, 0x00, 0x01);
}
if (err || pid < 0) /* try a different initialization */
err += sn9c102_write_const_regs(cam, {0x01, 0x01},
{0x00, 0x01});
break;
default:
break;
......
......@@ -104,8 +104,8 @@ static int ov7660_init(struct sn9c102_device* cam)
err += sn9c102_i2c_write(cam, 0x12, 0x80);
err += sn9c102_i2c_write(cam, 0x11, 0x09);
err += sn9c102_i2c_write(cam, 0x00, 0x0A);
err += sn9c102_i2c_write(cam, 0x01, 0x78);
err += sn9c102_i2c_write(cam, 0x02, 0x90);
err += sn9c102_i2c_write(cam, 0x01, 0x80);
err += sn9c102_i2c_write(cam, 0x02, 0x80);
err += sn9c102_i2c_write(cam, 0x03, 0x00);
err += sn9c102_i2c_write(cam, 0x04, 0x00);
err += sn9c102_i2c_write(cam, 0x05, 0x08);
......@@ -122,7 +122,7 @@ static int ov7660_init(struct sn9c102_device* cam)
err += sn9c102_i2c_write(cam, 0x10, 0x20);
err += sn9c102_i2c_write(cam, 0x11, 0x03);
err += sn9c102_i2c_write(cam, 0x12, 0x05);
err += sn9c102_i2c_write(cam, 0x13, 0xF8);
err += sn9c102_i2c_write(cam, 0x13, 0xC7);
err += sn9c102_i2c_write(cam, 0x14, 0x2C);
err += sn9c102_i2c_write(cam, 0x15, 0x00);
err += sn9c102_i2c_write(cam, 0x16, 0x02);
......@@ -162,7 +162,7 @@ static int ov7660_init(struct sn9c102_device* cam)
err += sn9c102_i2c_write(cam, 0x38, 0x02);
err += sn9c102_i2c_write(cam, 0x39, 0x43);
err += sn9c102_i2c_write(cam, 0x3A, 0x00);
err += sn9c102_i2c_write(cam, 0x3B, 0x02);
err += sn9c102_i2c_write(cam, 0x3B, 0x0A);
err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
err += sn9c102_i2c_write(cam, 0x3D, 0x99);
err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
......@@ -281,25 +281,34 @@ static int ov7660_get_ctrl(struct sn9c102_device* cam,
return -EIO;
break;
case V4L2_CID_DO_WHITE_BALANCE:
ctrl->value = sn9c102_pread_reg(cam, 0x02);
if ((ctrl->value = sn9c102_read_reg(cam, 0x02)) < 0)
return -EIO;
ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
break;
case V4L2_CID_RED_BALANCE:
ctrl->value = sn9c102_pread_reg(cam, 0x05);
if ((ctrl->value = sn9c102_read_reg(cam, 0x05)) < 0)
return -EIO;
ctrl->value &= 0x7f;
break;
case V4L2_CID_BLUE_BALANCE:
ctrl->value = sn9c102_pread_reg(cam, 0x06);
if ((ctrl->value = sn9c102_read_reg(cam, 0x06)) < 0)
return -EIO;
ctrl->value &= 0x7f;
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
ctrl->value = sn9c102_pread_reg(cam, 0x07);
if ((ctrl->value = sn9c102_read_reg(cam, 0x07)) < 0)
return -EIO;
ctrl->value &= 0x7f;
break;
case SN9C102_V4L2_CID_BAND_FILTER:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x3b)) < 0)
return -EIO;
ctrl->value &= 0x08;
break;
case V4L2_CID_GAIN:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
return -EIO;
ctrl->value &= 0x7f;
ctrl->value &= 0x1f;
break;
case V4L2_CID_AUTOGAIN:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
......@@ -335,12 +344,15 @@ static int ov7660_set_ctrl(struct sn9c102_device* cam,
case SN9C102_V4L2_CID_GREEN_BALANCE:
err += sn9c102_write_reg(cam, ctrl->value, 0x07);
break;
case SN9C102_V4L2_CID_BAND_FILTER:
err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b);
break;
case V4L2_CID_GAIN:
err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value);
break;
case V4L2_CID_AUTOGAIN:
err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value |
(ctrl->value << 1));
err += sn9c102_i2c_write(cam, 0x13, 0xc0 |
(ctrl->value * 0x07));
break;
default:
return -EINVAL;
......@@ -386,7 +398,7 @@ static int ov7660_set_pix_format(struct sn9c102_device* cam,
}
static struct sn9c102_sensor ov7660 = {
static const struct sn9c102_sensor ov7660 = {
.name = "OV7660",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
......@@ -401,9 +413,9 @@ static struct sn9c102_sensor ov7660 = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "global gain",
.minimum = 0x00,
.maximum = 0x7f,
.maximum = 0x1f,
.step = 0x01,
.default_value = 0x0a,
.default_value = 0x09,
.flags = 0,
},
{
......@@ -413,7 +425,7 @@ static struct sn9c102_sensor ov7660 = {
.minimum = 0x00,
.maximum = 0xff,
.step = 0x01,
.default_value = 0x50,
.default_value = 0x27,
.flags = 0,
},
{
......@@ -433,7 +445,7 @@ static struct sn9c102_sensor ov7660 = {
.minimum = 0x00,
.maximum = 0x7f,
.step = 0x01,
.default_value = 0x1f,
.default_value = 0x14,
.flags = 0,
},
{
......@@ -443,7 +455,7 @@ static struct sn9c102_sensor ov7660 = {
.minimum = 0x00,
.maximum = 0x7f,
.step = 0x01,
.default_value = 0x1e,
.default_value = 0x14,
.flags = 0,
},
{
......@@ -453,7 +465,7 @@ static struct sn9c102_sensor ov7660 = {
.minimum = 0x00,
.maximum = 0x01,
.step = 0x01,
.default_value = 0x00,
.default_value = 0x01,
.flags = 0,
},
{
......@@ -463,7 +475,17 @@ static struct sn9c102_sensor ov7660 = {
.minimum = 0x00,
.maximum = 0x7f,
.step = 0x01,
.default_value = 0x20,
.default_value = 0x14,
.flags = 0,
},
{
.id = SN9C102_V4L2_CID_BAND_FILTER,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "band filter",
.minimum = 0x00,
.maximum = 0x01,
.step = 0x01,
.default_value = 0x00,
.flags = 0,
},
},
......@@ -508,6 +530,7 @@ int sn9c102_probe_ov7660(struct sn9c102_device* cam)
return -EIO;
if (pid != 0x76 || ver != 0x60)
return -ENODEV;
sn9c102_attach_sensor(cam, &ov7660);
return 0;
......
......@@ -163,7 +163,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam,
}
static struct sn9c102_sensor pas106b = {
static const struct sn9c102_sensor pas106b = {
.name = "PAS106B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
......@@ -273,23 +273,21 @@ static struct sn9c102_sensor pas106b = {
int sn9c102_probe_pas106b(struct sn9c102_device* cam)
{
int r0 = 0, r1 = 0, err;
int r0 = 0, r1 = 0;
unsigned int pid = 0;
/*
Minimal initialization to enable the I2C communication
NOTE: do NOT change the values!
*/
err = sn9c102_write_const_regs(cam,
{0x01, 0x01}, /* sensor power down */
{0x00, 0x01}, /* sensor power on */
{0x28, 0x17});/* sensor clock 24 MHz */
if (err)
if (sn9c102_write_const_regs(cam,
{0x01, 0x01}, /* sensor power down */
{0x00, 0x01}, /* sensor power on */
{0x28, 0x17})) /* sensor clock at 24 MHz */
return -EIO;
r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00);
r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01);
if (r0 < 0 || r1 < 0)
return -EIO;
......
......@@ -35,29 +35,28 @@ static int pas202bcb_init(struct sn9c102_device* cam)
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
err = sn9c102_write_const_regs(cam, {0x00, 0x10},
{0x00, 0x11}, {0x00, 0x14},
{0x20, 0x17}, {0x30, 0x19},
{0x09, 0x18});
err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
{0x00, 0x14}, {0x20, 0x17},
{0x30, 0x19}, {0x09, 0x18});
break;
case BRIDGE_SN9C103:
err = sn9c102_write_const_regs(cam, {0x00, 0x02},
{0x00, 0x03}, {0x1a, 0x04},
{0x20, 0x05}, {0x20, 0x06},
{0x20, 0x07}, {0x00, 0x10},
{0x00, 0x11}, {0x00, 0x14},
{0x20, 0x17}, {0x30, 0x19},
{0x09, 0x18}, {0x02, 0x1c},
{0x03, 0x1d}, {0x0f, 0x1e},
{0x0c, 0x1f}, {0x00, 0x20},
{0x10, 0x21}, {0x20, 0x22},
{0x30, 0x23}, {0x40, 0x24},
{0x50, 0x25}, {0x60, 0x26},
{0x70, 0x27}, {0x80, 0x28},
{0x90, 0x29}, {0xa0, 0x2a},
{0xb0, 0x2b}, {0xc0, 0x2c},
{0xd0, 0x2d}, {0xe0, 0x2e},
{0xf0, 0x2f}, {0xff, 0x30});
err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
{0x1a, 0x04}, {0x20, 0x05},
{0x20, 0x06}, {0x20, 0x07},
{0x00, 0x10}, {0x00, 0x11},
{0x00, 0x14}, {0x20, 0x17},
{0x30, 0x19}, {0x09, 0x18},
{0x02, 0x1c}, {0x03, 0x1d},
{0x0f, 0x1e}, {0x0c, 0x1f},
{0x00, 0x20}, {0x10, 0x21},
{0x20, 0x22}, {0x30, 0x23},
{0x40, 0x24}, {0x50, 0x25},
{0x60, 0x26}, {0x70, 0x27},
{0x80, 0x28}, {0x90, 0x29},
{0xa0, 0x2a}, {0xb0, 0x2b},
{0xc0, 0x2c}, {0xd0, 0x2d},
{0xe0, 0x2e}, {0xf0, 0x2f},
{0xff, 0x30});
break;
default:
break;
......@@ -197,7 +196,7 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam,
}
static struct sn9c102_sensor pas202bcb = {
static const struct sn9c102_sensor pas202bcb = {
.name = "PAS202BCB",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
......@@ -313,9 +312,8 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
{0x28, 0x17});/* clock 24 MHz */
break;
case BRIDGE_SN9C103: /* do _not_ change anything! */
err = sn9c102_write_const_regs(cam, {0x09, 0x01},
{0x44, 0x01}, {0x44, 0x02},
{0x29, 0x17});
err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01},
{0x44, 0x02}, {0x29, 0x17});
break;
default:
break;
......
......@@ -22,7 +22,7 @@
#define _SN9C102_SENSOR_H_
#include <linux/usb.h>
#include <linux/videodev.h>
#include <linux/videodev2.h>
#include <linux/device.h>
#include <linux/stddef.h>
#include <linux/errno.h>
......@@ -74,7 +74,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
/* Attach a probed sensor to the camera. */
extern void
sn9c102_attach_sensor(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor);
const struct sn9c102_sensor* sensor);
/*
Read/write routines: they always return -1 on error, 0 or the read value
......@@ -85,10 +85,11 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
*/
/* The "try" I2C I/O versions are used when probing the sensor */
extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
u8 address, u8 value);
extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
u8 address);
extern int sn9c102_i2c_try_write(struct sn9c102_device*,
const struct sn9c102_sensor*, u8 address,
u8 value);
extern int sn9c102_i2c_try_read(struct sn9c102_device*,
const struct sn9c102_sensor*, u8 address);
/*
These must be used if and only if the sensor doesn't implement the standard
......@@ -102,29 +103,31 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
byte.
*/
extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor, u8 n,
const struct sn9c102_sensor* sensor, u8 n,
u8 data0, u8 data1, u8 data2, u8 data3,
u8 data4, u8 data5);
extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor, u8 data0,
u8 data1, u8 n, u8 buffer[]);
const struct sn9c102_sensor* sensor,
u8 data0, u8 data1, u8 n, u8 buffer[]);
/* To be used after the sensor struct has been attached to the camera struct */
extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
/* I/O on registers in the bridge. Could be used by the sensor methods too */
extern int sn9c102_read_reg(struct sn9c102_device*, u16 index);
extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
int count);
/*
* Write multiple registers with constant values. For example:
* sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
*/
#define sn9c102_write_const_regs(device, data...) \
({ const static u8 _data[][2] = {data}; \
sn9c102_write_regs(device, _data, ARRAY_SIZE(_data)); })
Write multiple registers with constant values. For example:
sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
Register adresses must be < 256.
*/
#define sn9c102_write_const_regs(sn9c102_device, data...) \
({ const static u8 _valreg[][2] = {data}; \
sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); })
/*****************************************************************************/
......
......@@ -88,7 +88,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
}
static struct sn9c102_sensor tas5110c1b = {
static const struct sn9c102_sensor tas5110c1b = {
.name = "TAS5110C1B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
......
......@@ -68,7 +68,7 @@ static int tas5110d_set_pix_format(struct sn9c102_device* cam,
}
static struct sn9c102_sensor tas5110d = {
static const struct sn9c102_sensor tas5110d = {
.name = "TAS5110D",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
......
......@@ -89,7 +89,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
}
static struct sn9c102_sensor tas5130d1b = {
static const struct sn9c102_sensor tas5130d1b = {
.name = "TAS5130D1B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
......
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