aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/video/sn9c102
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/sn9c102')
-rw-r--r--drivers/media/video/sn9c102/Kconfig2
-rw-r--r--drivers/media/video/sn9c102/Makefile17
-rw-r--r--drivers/media/video/sn9c102/sn9c102.h17
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c274
-rw-r--r--drivers/media/video/sn9c102/sn9c102_devtable.h14
-rw-r--r--drivers/media/video/sn9c102/sn9c102_hv7131d.c25
-rw-r--r--drivers/media/video/sn9c102/sn9c102_hv7131r.c366
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mi0343.c130
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mi0360.c338
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7630.c121
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7660.c234
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas106b.c23
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas202bcb.c77
-rw-r--r--drivers/media/video/sn9c102/sn9c102_sensor.h12
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5110c1b.c18
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5110d.c118
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5130d1b.c19
17 files changed, 1281 insertions, 524 deletions
diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig
index 1a7ccb666ab..19204f5686e 100644
--- a/drivers/media/video/sn9c102/Kconfig
+++ b/drivers/media/video/sn9c102/Kconfig
@@ -1,6 +1,6 @@
config USB_SN9C102
tristate "USB SN9C1xx PC Camera Controller support"
- depends on USB && VIDEO_V4L1
+ depends on USB && VIDEO_V4L2
---help---
Say Y here if you want support for cameras based on SONiX SN9C101,
SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile
index 30e3dfe537f..a56d16f69c7 100644
--- a/drivers/media/video/sn9c102/Makefile
+++ b/drivers/media/video/sn9c102/Makefile
@@ -1,7 +1,14 @@
-sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
- sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \
- sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
- sn9c102_tas5130d1b.o
+sn9c102-objs := sn9c102_core.o \
+ sn9c102_hv7131d.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
obj-$(CONFIG_USB_SN9C102) += sn9c102.o
-
diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
index 5428f34e7c5..680e7463452 100644
--- a/drivers/media/video/sn9c102/sn9c102.h
+++ b/drivers/media/video/sn9c102/sn9c102.h
@@ -78,8 +78,13 @@ enum sn9c102_stream_state {
typedef char sn9c102_sof_header_t[62];
+struct sn9c102_sof_t {
+ sn9c102_sof_header_t header;
+ u16 bytesread;
+};
+
struct sn9c102_sysfs_attr {
- u8 reg, i2c_reg;
+ u16 reg, i2c_reg;
sn9c102_sof_header_t frame_header;
};
@@ -112,7 +117,7 @@ struct sn9c102_device {
struct v4l2_jpegcompression compression;
struct sn9c102_sysfs_attr sysfs;
- sn9c102_sof_header_t sof_header;
+ struct sn9c102_sof_t sof;
u16 reg[384];
struct sn9c102_module_param module_param;
@@ -182,8 +187,8 @@ do { \
if ((level) == 1 || (level) == 2) \
pr_info("sn9c102: " fmt "\n", ## args); \
else if ((level) == 3) \
- pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \
- __LINE__ , ## args); \
+ pr_debug("sn9c102: [%s:%d] " fmt "\n", \
+ __FUNCTION__, __LINE__ , ## args); \
} \
} while (0)
#else
@@ -194,8 +199,8 @@ do { \
#undef PDBG
#define PDBG(fmt, args...) \
-dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args)
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
+ __LINE__ , ## args)
#undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index d0e2b40a772..89f83354de3 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -44,11 +44,12 @@
/*****************************************************************************/
#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers"
-#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia"
+#define SN9C102_MODULE_ALIAS "sn9c1xx"
+#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.34"
-#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 34)
+#define SN9C102_MODULE_VERSION "1:1.39"
+#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 39)
/*****************************************************************************/
@@ -56,6 +57,7 @@ MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
MODULE_DESCRIPTION(SN9C102_MODULE_NAME);
+MODULE_ALIAS(SN9C102_MODULE_ALIAS);
MODULE_VERSION(SN9C102_MODULE_VERSION);
MODULE_LICENSE(SN9C102_MODULE_LICENSE);
@@ -106,8 +108,7 @@ MODULE_PARM_DESC(debug,
"\n1 = critical errors"
"\n2 = significant informations"
"\n3 = more verbose messages"
- "\nLevel 3 is useful for testing only, when only "
- "one device is used."
+ "\nLevel 3 is useful for testing only."
"\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
"\n");
#endif
@@ -121,8 +122,8 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
struct v4l2_pix_format* p = &(cam->sensor.pix_format);
struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
- (p->width * p->height * p->priv) / 8 :
- (r->width * r->height * p->priv) / 8;
+ (p->width * p->height * p->priv) / 8 :
+ (r->width * r->height * p->priv) / 8;
void* buff = NULL;
u32 i;
@@ -208,27 +209,40 @@ static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
}
/*****************************************************************************/
-
-int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index)
+/*
+ * 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 */
int i, res;
- if (index + sizeof(buff) >= ARRAY_SIZE(cam->reg))
- return -1;
+ 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);
+ if (res < 0) {
+ DBG(3, "Failed to write a register (value 0x%02X, "
+ "index 0x%02X, error %d)", *value, index, res);
+ return -1;
+ }
- res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
- index, 0, buff, sizeof(buff),
- SN9C102_CTRL_TIMEOUT*sizeof(buff));
- if (res < 0) {
- DBG(3, "Failed to write registers (index 0x%02X, error %d)",
- index, res);
- return -1;
+ cam->reg[index] = *value;
}
- for (i = 0; i < sizeof(buff); i++)
- cam->reg[index+i] = buff[i];
-
return 0;
}
@@ -485,18 +499,43 @@ static size_t sn9c102_sof_length(struct sn9c102_device* cam)
static void*
sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
{
- char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
- size_t soflen = 0, i;
+ static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
+ const char *m = mem;
+ size_t soflen = 0, i, j;
soflen = sn9c102_sof_length(cam);
- for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
- if (!memcmp(mem + i, sof_header, sizeof(sof_header))) {
- memcpy(cam->sof_header, mem + i,
- sizeof(sn9c102_sof_header_t));
- /* Skip the header */
- return mem + i + soflen;
+ for (i = 0; i < len; i++) {
+ size_t b;
+
+ /* Read the variable part of the header */
+ if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
+ cam->sof.header[cam->sof.bytesread] = *(m+i);
+ if (++cam->sof.bytesread == soflen) {
+ cam->sof.bytesread = 0;
+ return mem + i;
+ }
+ continue;
+ }
+
+ /* Search for the SOF marker (fixed part) in the header */
+ for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
+ if (unlikely(i+j) == len)
+ return NULL;
+ if (*(m+i+j) == marker[cam->sof.bytesread]) {
+ cam->sof.header[cam->sof.bytesread] = *(m+i+j);
+ if (++cam->sof.bytesread == sizeof(marker)) {
+ PDBGG("Bytes to analyze: %zd. SOF "
+ "starts at byte #%zd", len, i);
+ i += j+1;
+ break;
+ }
+ } else {
+ cam->sof.bytesread = 0;
+ break;
}
+ }
+ }
return NULL;
}
@@ -505,7 +544,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
static void*
sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
{
- char eof_header[4][4] = {
+ static const u8 eof_header[4][4] = {
{0x00, 0x00, 0x00, 0x00},
{0x40, 0x00, 0x00, 0x00},
{0x80, 0x00, 0x00, 0x00},
@@ -513,10 +552,16 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
};
size_t i, j;
+ /* The EOF header does not exist in compressed data */
if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
- return NULL; /* EOF header does not exist in compressed data */
+ return NULL;
+ /*
+ The EOF header might cross the packet boundary, but this is not a
+ problem, since the end of a frame is determined by checking its size
+ in the first place.
+ */
for (i = 0; (len >= 4) && (i <= len - 4); i++)
for (j = 0; j < ARRAY_SIZE(eof_header); j++)
if (!memcmp(mem + i, eof_header[j], 4))
@@ -529,7 +574,7 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
static void
sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
{
- static u8 jpeg_header[589] = {
+ static const u8 jpeg_header[589] = {
0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
@@ -639,6 +684,7 @@ static void sn9c102_urb_complete(struct urb *urb)
cam->stream = STREAM_OFF;
if ((*f))
(*f)->state = F_QUEUED;
+ cam->sof.bytesread = 0;
DBG(3, "Stream interrupted by application");
wake_up(&cam->wait_stream);
}
@@ -676,6 +722,7 @@ static void sn9c102_urb_complete(struct urb *urb)
if (status) {
DBG(3, "Error in isochronous frame");
(*f)->state = F_ERROR;
+ cam->sof.bytesread = 0;
continue;
}
@@ -692,13 +739,13 @@ end_of_frame:
if (eof)
img = (eof > pos) ? eof - pos - 1 : 0;
- if ((*f)->buf.bytesused+img > imagesize) {
+ if ((*f)->buf.bytesused + img > imagesize) {
u32 b;
b = (*f)->buf.bytesused + img -
imagesize;
img = imagesize - (*f)->buf.bytesused;
- DBG(3, "Expected EOF not found: "
- "video frame cut");
+ PDBGG("Expected EOF not found: video "
+ "frame cut");
if (eof)
DBG(3, "Exceeded limit: +%u "
"bytes", (unsigned)(b));
@@ -719,11 +766,6 @@ end_of_frame:
V4L2_PIX_FMT_JPEG) && eof)) {
u32 b;
- if (cam->sensor.pix_format.pixelformat
- == V4L2_PIX_FMT_JPEG)
- sn9c102_write_eoimarker(cam,
- (*f));
-
b = (*f)->buf.bytesused;
(*f)->state = F_DONE;
(*f)->buf.sequence= ++cam->frame_count;
@@ -741,7 +783,7 @@ end_of_frame:
spin_unlock(&cam->queue_lock);
memcpy(cam->sysfs.frame_header,
- cam->sof_header, soflen);
+ cam->sof.header, soflen);
DBG(3, "Video frame captured: %lu "
"bytes", (unsigned long)(b));
@@ -791,7 +833,13 @@ start_of_frame:
V4L2_PIX_FMT_SN9C10X ||
cam->sensor.pix_format.pixelformat ==
V4L2_PIX_FMT_JPEG) {
- eof = sof - soflen;
+ if (sof - pos >= soflen) {
+ eof = sof - soflen;
+ } else { /* remove header */
+ eof = pos;
+ (*f)->buf.bytesused -=
+ (soflen - (sof - pos));
+ }
goto end_of_frame;
} else {
DBG(3, "SOF before expected EOF after "
@@ -878,6 +926,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
}
cam->frame_current = NULL;
+ cam->sof.bytesread = 0;
for (i = 0; i < SN9C102_URBS; i++) {
err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
@@ -959,9 +1008,9 @@ static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)
if (len < 6) {
strncpy(str, buff, len);
- str[len+1] = '\0';
+ str[len] = '\0';
} else {
- strncpy(str, buff, 4);
+ strncpy(str, buff, 6);
str[6] = '\0';
}
@@ -1062,7 +1111,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
count = sprintf(buf, "%d\n", val);
- DBG(3, "Read bytes: %zd", count);
+ DBG(3, "Read bytes: %zd, value: %d", count, val);
mutex_unlock(&sn9c102_sysfs_lock);
@@ -1197,7 +1246,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
count = sprintf(buf, "%d\n", val);
- DBG(3, "Read bytes: %zd", count);
+ DBG(3, "Read bytes: %zd, value: %d", count, val);
mutex_unlock(&sn9c102_sysfs_lock);
@@ -1371,35 +1420,35 @@ static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,
static int sn9c102_create_sysfs(struct sn9c102_device* cam)
{
- struct video_device *v4ldev = cam->v4ldev;
+ struct class_device *classdev = &(cam->v4ldev->class_dev);
int err = 0;
- if ((err = video_device_create_file(v4ldev, &class_device_attr_reg)))
+ if ((err = class_device_create_file(classdev, &class_device_attr_reg)))
goto err_out;
- if ((err = video_device_create_file(v4ldev, &class_device_attr_val)))
+ if ((err = class_device_create_file(classdev, &class_device_attr_val)))
goto err_reg;
- if ((err = video_device_create_file(v4ldev,
+ if ((err = class_device_create_file(classdev,
&class_device_attr_frame_header)))
goto err_val;
if (cam->sensor.sysfs_ops) {
- if ((err = video_device_create_file(v4ldev,
+ if ((err = class_device_create_file(classdev,
&class_device_attr_i2c_reg)))
goto err_frame_header;
- if ((err = video_device_create_file(v4ldev,
+ if ((err = class_device_create_file(classdev,
&class_device_attr_i2c_val)))
goto err_i2c_reg;
}
if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
- if ((err = video_device_create_file(v4ldev,
+ if ((err = class_device_create_file(classdev,
&class_device_attr_green)))
goto err_i2c_val;
} else {
- if ((err = video_device_create_file(v4ldev,
+ if ((err = class_device_create_file(classdev,
&class_device_attr_blue)))
goto err_i2c_val;
- if ((err = video_device_create_file(v4ldev,
+ if ((err = class_device_create_file(classdev,
&class_device_attr_red)))
goto err_blue;
}
@@ -1407,19 +1456,19 @@ static int sn9c102_create_sysfs(struct sn9c102_device* cam)
return 0;
err_blue:
- video_device_remove_file(v4ldev, &class_device_attr_blue);
+ class_device_remove_file(classdev, &class_device_attr_blue);
err_i2c_val:
if (cam->sensor.sysfs_ops)
- video_device_remove_file(v4ldev, &class_device_attr_i2c_val);
+ class_device_remove_file(classdev, &class_device_attr_i2c_val);
err_i2c_reg:
if (cam->sensor.sysfs_ops)
- video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
+ class_device_remove_file(classdev, &class_device_attr_i2c_reg);
err_frame_header:
- video_device_remove_file(v4ldev, &class_device_attr_frame_header);
+ class_device_remove_file(classdev, &class_device_attr_frame_header);
err_val:
- video_device_remove_file(v4ldev, &class_device_attr_val);
+ class_device_remove_file(classdev, &class_device_attr_val);
err_reg:
- video_device_remove_file(v4ldev, &class_device_attr_reg);
+ class_device_remove_file(classdev, &class_device_attr_reg);
err_out:
return err;
}
@@ -1477,10 +1526,10 @@ sn9c102_set_compression(struct sn9c102_device* cam,
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
case BRIDGE_SN9C103:
- if (compression->quality == 0)
+ if (compression->quality == 0)
err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
0x17);
- else if (compression->quality == 1)
+ else if (compression->quality == 1)
err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
0x17);
break;
@@ -1489,10 +1538,10 @@ sn9c102_set_compression(struct sn9c102_device* cam,
if (compression->quality == 0) {
for (i = 0; i <= 63; i++) {
err += sn9c102_write_reg(cam,
- SN9C102_Y_QTABLE0[i],
+ SN9C102_Y_QTABLE1[i],
0x100 + i);
err += sn9c102_write_reg(cam,
- SN9C102_UV_QTABLE0[i],
+ SN9C102_UV_QTABLE1[i],
0x140 + i);
}
err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
@@ -1597,9 +1646,13 @@ static int sn9c102_init(struct sn9c102_device* cam)
if (cam->bridge == BRIDGE_SN9C101 ||
cam->bridge == BRIDGE_SN9C102 ||
cam->bridge == BRIDGE_SN9C103) {
+ if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
+ s->pix_format.pixelformat= V4L2_PIX_FMT_SBGGR8;
cam->compression.quality = cam->reg[0x17] & 0x01 ?
0 : 1;
} else {
+ if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
+ s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
cam->compression.quality = cam->reg[0x18] & 0x40 ?
0 : 1;
err += sn9c102_set_compression(cam, &cam->compression);
@@ -1805,7 +1858,7 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
DBG(3, "Close and open the device again to choose "
"the read method");
mutex_unlock(&cam->fileop_mutex);
- return -EINVAL;
+ return -EBUSY;
}
if (cam->io == IO_NONE) {
@@ -1845,16 +1898,16 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
return err;
}
} else {
- timeout = wait_event_interruptible_timeout
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1) );
- if (timeout < 0) {
- mutex_unlock(&cam->fileop_mutex);
- return timeout;
+ timeout = wait_event_interruptible_timeout
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+ cam->module_param.frame_timeout *
+ 1000 * msecs_to_jiffies(1) );
+ if (timeout < 0) {
+ mutex_unlock(&cam->fileop_mutex);
+ return timeout;
} else if (timeout == 0 &&
!(cam->state & DEV_DISCONNECTED)) {
DBG(1, "Video frame timeout elapsed");
@@ -2001,7 +2054,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
return -EIO;
}
- if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
+ if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
+ mutex_unlock(&cam->fileop_mutex);
+ return -EACCES;
+ }
+
+ if (cam->io != IO_MMAP ||
size != PAGE_ALIGN(cam->frame[0].buf.length)) {
mutex_unlock(&cam->fileop_mutex);
return -EINVAL;
@@ -2267,7 +2325,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_S_CROP failed. "
"Unmap the buffers first.");
- return -EINVAL;
+ return -EBUSY;
}
/* Preserve R,G or B origin */
@@ -2410,8 +2468,8 @@ sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
case BRIDGE_SN9C103:
- strcpy(fmtd.description, "compressed");
- fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
+ strcpy(fmtd.description, "compressed");
+ fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
break;
case BRIDGE_SN9C105:
case BRIDGE_SN9C120:
@@ -2445,8 +2503,10 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X ||
- pfmt->pixelformat==V4L2_PIX_FMT_JPEG)
+ pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
+ V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
+ pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
+ pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
? 0 : (pfmt->width * pfmt->priv) / 8;
pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
pfmt->field = V4L2_FIELD_NONE;
@@ -2521,9 +2581,9 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
case BRIDGE_SN9C103:
- if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
- pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
- pix->pixelformat = pfmt->pixelformat;
+ if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
+ pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
+ pix->pixelformat = pfmt->pixelformat;
break;
case BRIDGE_SN9C105:
case BRIDGE_SN9C120:
@@ -2533,7 +2593,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
break;
}
pix->priv = pfmt->priv; /* bpp */
- pix->colorspace = pfmt->colorspace;
+ pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
+ V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
pix->pixelformat == V4L2_PIX_FMT_JPEG)
? 0 : (pix->width * pix->priv) / 8;
@@ -2551,7 +2612,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_S_FMT failed. Unmap the "
"buffers first.");
- return -EINVAL;
+ return -EBUSY;
}
if (cam->stream == STREAM_ON)
@@ -2666,14 +2727,14 @@ sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
if (cam->io == IO_READ) {
DBG(3, "Close and open the device again to choose the mmap "
"I/O method");
- return -EINVAL;
+ return -EBUSY;
}
for (i = 0; i < cam->nbuffers; i++)
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
"still mapped.");
- return -EINVAL;
+ return -EBUSY;
}
if (cam->stream == STREAM_ON)
@@ -2785,15 +2846,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
if (err)
return err;
} else {
- timeout = wait_event_interruptible_timeout
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1) );
- if (timeout < 0)
- return timeout;
+ timeout = wait_event_interruptible_timeout
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+ cam->module_param.frame_timeout *
+ 1000 * msecs_to_jiffies(1) );
+ if (timeout < 0)
+ return timeout;
else if (timeout == 0 &&
!(cam->state & DEV_DISCONNECTED)) {
DBG(1, "Video frame timeout elapsed");
@@ -2837,9 +2898,6 @@ sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
return -EINVAL;
- if (list_empty(&cam->inqueue))
- return -EINVAL;
-
cam->stream = STREAM_ON;
DBG(3, "Stream on");
@@ -3166,8 +3224,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
r = sn9c102_read_reg(cam, 0x00);
if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
- DBG(1, "Sorry, this is not a SN9C1xx based camera "
- "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ DBG(1, "Sorry, this is not a SN9C1xx-based camera "
+ "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
err = -ENODEV;
goto fail;
}
@@ -3177,19 +3235,19 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
DBG(2, "SN9C10[12] PC Camera Controller detected "
- "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
break;
case BRIDGE_SN9C103:
DBG(2, "SN9C103 PC Camera Controller detected "
- "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
break;
case BRIDGE_SN9C105:
DBG(2, "SN9C105 PC Camera Controller detected "
- "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
break;
case BRIDGE_SN9C120:
DBG(2, "SN9C120 PC Camera Controller detected "
- "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
break;
}
@@ -3260,6 +3318,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
"device controlling. Error #%d", err);
#else
DBG(2, "Optional device control through 'sysfs' interface disabled");
+ DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
+ "configuration option to enable it.");
#endif
usb_set_intfdata(intf, cam);
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
index 3a682eca6c6..f49bd8c5b86 100644
--- a/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -89,16 +89,22 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0471, 0x0328, 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, 0x60cc, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60ea, 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, 0x60fb, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
/* 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, 0x6138, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
@@ -114,12 +120,15 @@ static const struct usb_device_id sn9c102_id_table[] = {
Functions must return 0 on success, the appropriate error otherwise.
*/
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_mi0360(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_pas106b(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_tas5110d(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);
the order of the list below, from top to bottom.
*/
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_mi0360, /* 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_hv7131d, /* 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_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,
};
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
index 7ae368f60d8..28a861aed04 100644
--- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
@@ -22,19 +22,13 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor hv7131d;
-
-
static int hv7131d_init(struct sn9c102_device* cam)
{
- int err = 0;
+ int err;
- err += sn9c102_write_reg(cam, 0x00, 0x10);
- err += sn9c102_write_reg(cam, 0x00, 0x11);
- err += sn9c102_write_reg(cam, 0x00, 0x14);
- err += sn9c102_write_reg(cam, 0x60, 0x17);
- err += sn9c102_write_reg(cam, 0x0e, 0x18);
- err += sn9c102_write_reg(cam, 0xf2, 0x19);
+ err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
+ {0x00, 0x14}, {0x60, 0x17},
+ {0x0e, 0x18}, {0xf2, 0x19});
err += sn9c102_i2c_write(cam, 0x01, 0x04);
err += sn9c102_i2c_write(cam, 0x02, 0x00);
@@ -153,7 +147,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor hv7131d = {
.name = "HV7131D",
.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,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
@@ -250,11 +244,10 @@ static struct sn9c102_sensor hv7131d = {
int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
{
- int r0 = 0, r1 = 0, err = 0;
+ int r0 = 0, r1 = 0, err;
- err += sn9c102_write_reg(cam, 0x01, 0x01);
- err += sn9c102_write_reg(cam, 0x00, 0x01);
- err += sn9c102_write_reg(cam, 0x28, 0x17);
+ err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
+ {0x28, 0x17});
if (err)
return -EIO;
@@ -263,7 +256,7 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
if (r0 < 0 || r1 < 0)
return -EIO;
- if (r0 != 0x00 && r1 != 0x04)
+ if (r0 != 0x00 || r1 != 0x04)
return -ENODEV;
sn9c102_attach_sensor(cam, &hv7131d);
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/video/sn9c102/sn9c102_hv7131r.c
new file mode 100644
index 00000000000..5a495baa5f9
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131r.c
@@ -0,0 +1,366 @@
+/***************************************************************************
+ * Plug-in for HV7131R 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 hv7131r_init(struct sn9c102_device* cam)
+{
+ int err = 0;
+
+ switch (sn9c102_get_bridge(cam)) {
+ case BRIDGE_SN9C103:
+ err = sn9c102_write_const_regs(cam, {0x00, 0x03}, {0x1a, 0x04},
+ {0x20, 0x05}, {0x20, 0x06},
+ {0x03, 0x10}, {0x00, 0x14},
+ {0x60, 0x17}, {0x0a, 0x18},
+ {0xf0, 0x19}, {0x1d, 0x1a},
+ {0x10, 0x1b}, {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},
+ {0x44, 0x05}, {0x3e, 0x06},
+ {0x1a, 0x07}, {0x03, 0x10},
+ {0x08, 0x14}, {0xa3, 0x17},
+ {0x4b, 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_write(cam, 0x20, 0x00);
+ err += sn9c102_i2c_write(cam, 0x21, 0xd6);
+ err += sn9c102_i2c_write(cam, 0x25, 0x06);
+
+ return err;
+}
+
+
+static int hv7131r_get_ctrl(struct sn9c102_device* cam,
+ struct v4l2_control* ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
+ return -EIO;
+ return 0;
+ case V4L2_CID_RED_BALANCE:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
+ return -EIO;
+ ctrl->value = ctrl->value & 0x3f;
+ return 0;
+ case V4L2_CID_BLUE_BALANCE:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
+ return -EIO;
+ ctrl->value = ctrl->value & 0x3f;
+ return 0;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
+ return -EIO;
+ ctrl->value = ctrl->value & 0x3f;
+ return 0;
+ case V4L2_CID_BLACK_LEVEL:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x01)) < 0)
+ return -EIO;
+ ctrl->value = (ctrl->value & 0x08) ? 1 : 0;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+
+static int hv7131r_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
+{
+ int err = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
+ break;
+ case V4L2_CID_RED_BALANCE:
+ err += sn9c102_i2c_write(cam, 0x31, ctrl->value);
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ err += sn9c102_i2c_write(cam, 0x33, ctrl->value);
+ break;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ err += sn9c102_i2c_write(cam, 0x32, ctrl->value);
+ break;
+ case V4L2_CID_BLACK_LEVEL:
+ {
+ int r = sn9c102_i2c_read(cam, 0x01);
+ if (r < 0)
+ return -EIO;
+ err += sn9c102_i2c_write(cam, 0x01,
+ (ctrl->value<<3) | (r&0xf7));
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return err ? -EIO : 0;
+}
+
+
+static int hv7131r_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) + 1,
+ v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+ err += sn9c102_write_reg(cam, h_start, 0x12);
+ err += sn9c102_write_reg(cam, v_start, 0x13);
+
+ return err;
+}
+
+
+static int hv7131r_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ int err = 0;
+
+ switch (sn9c102_get_bridge(cam)) {
+ case BRIDGE_SN9C103:
+ if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
+ err += sn9c102_write_reg(cam, 0xa0, 0x19);
+ err += sn9c102_i2c_write(cam, 0x01, 0x04);
+ } else {
+ err += sn9c102_write_reg(cam, 0x30, 0x19);
+ err += sn9c102_i2c_write(cam, 0x01, 0x04);
+ }
+ break;
+ case BRIDGE_SN9C105:
+ case BRIDGE_SN9C120:
+ if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
+ err += sn9c102_write_reg(cam, 0xa5, 0x17);
+ err += sn9c102_i2c_write(cam, 0x01, 0x24);
+ } else {
+ err += sn9c102_write_reg(cam, 0xa3, 0x17);
+ err += sn9c102_i2c_write(cam, 0x01, 0x04);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+
+
+static struct sn9c102_sensor hv7131r = {
+ .name = "HV7131R",
+ .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+ .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
+ .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+ .frequency = SN9C102_I2C_100KHZ,
+ .interface = SN9C102_I2C_2WIRES,
+ .i2c_slave_id = 0x11,
+ .init = &hv7131r_init,
+ .qctrl = {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "global gain",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x01,
+ .default_value = 0x40,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "red balance",
+ .minimum = 0x00,
+ .maximum = 0x3f,
+ .step = 0x01,
+ .default_value = 0x08,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "blue balance",
+ .minimum = 0x00,
+ .maximum = 0x3f,
+ .step = 0x01,
+ .default_value = 0x1a,
+ .flags = 0,
+ },
+ {
+ .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "green balance",
+ .minimum = 0x00,
+ .maximum = 0x3f,
+ .step = 0x01,
+ .default_value = 0x2f,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_BLACK_LEVEL,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "auto black level compensation",
+ .minimum = 0x00,
+ .maximum = 0x01,
+ .step = 0x01,
+ .default_value = 0x00,
+ .flags = 0,
+ },
+ },
+ .get_ctrl = &hv7131r_get_ctrl,
+ .set_ctrl = &hv7131r_set_ctrl,
+ .cropcap = {
+ .bounds = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ .defrect = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ },
+ .set_crop = &hv7131r_set_crop,
+ .pix_format = {
+ .width = 640,
+ .height = 480,
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .priv = 8,
+ },
+ .set_pix_format = &hv7131r_set_pix_format
+};
+
+
+int sn9c102_probe_hv7131r(struct sn9c102_device* cam)
+{
+ int devid, err;
+
+ err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x02},
+ {0x34, 0x01}, {0x20, 0x17},
+ {0x34, 0x01}, {0x46, 0x01});
+
+ if (err)
+ return -EIO;
+
+ devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
+ if (devid < 0)
+ return -EIO;
+
+ if (devid != 0x02)
+ return -ENODEV;
+
+ sn9c102_attach_sensor(cam, &hv7131r);
+
+ return 0;
+}
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c
index a33d1bc10f9..9200845d011 100644
--- a/drivers/media/video/sn9c102/sn9c102_mi0343.c
+++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c
@@ -22,36 +22,30 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor mi0343;
-static u8 mi0343_i2c_data[5+1];
-
-
static int mi0343_init(struct sn9c102_device* cam)
{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
int err = 0;
- err += sn9c102_write_reg(cam, 0x00, 0x10);
- err += sn9c102_write_reg(cam, 0x00, 0x11);
- err += sn9c102_write_reg(cam, 0x0a, 0x14);
- err += sn9c102_write_reg(cam, 0x40, 0x01);
- err += sn9c102_write_reg(cam, 0x20, 0x17);
- err += sn9c102_write_reg(cam, 0x07, 0x18);
- err += sn9c102_write_reg(cam, 0xa0, 0x19);
-
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x0d, 0x00, 0x01, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x0d, 0x00, 0x00, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x03, 0x01, 0xe1, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x04, 0x02, 0x81, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x05, 0x00, 0x17, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x06, 0x00, 0x11, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x62, 0x04, 0x9a, 0, 0);
+ err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
+ {0x0a, 0x14}, {0x40, 0x01},
+ {0x20, 0x17}, {0x07, 0x18},
+ {0xa0, 0x19});
+
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+ 0x00, 0x01, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+ 0x00, 0x00, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
+ 0x01, 0xe1, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
+ 0x02, 0x81, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
+ 0x00, 0x17, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
+ 0x00, 0x11, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
+ 0x04, 0x9a, 0, 0);
return err;
}
@@ -60,43 +54,46 @@ static int mi0343_init(struct sn9c102_device* cam)
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];
+
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x09, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
+ 2+1, data) < 0)
return -EIO;
- ctrl->value = mi0343_i2c_data[2];
+ ctrl->value = data[2];
return 0;
case V4L2_CID_GAIN:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x35, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
+ 2+1, data) < 0)
return -EIO;
break;
case V4L2_CID_HFLIP:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x20, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
+ 2+1, data) < 0)
return -EIO;
- ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0;
+ ctrl->value = data[3] & 0x20 ? 1 : 0;
return 0;
case V4L2_CID_VFLIP:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x20, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
+ 2+1, data) < 0)
return -EIO;
- ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0;
+ ctrl->value = data[3] & 0x80 ? 1 : 0;
return 0;
case V4L2_CID_RED_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x2d, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
+ 2+1, data) < 0)
return -EIO;
break;
case V4L2_CID_BLUE_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x2c, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
+ 2+1, data) < 0)
return -EIO;
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x2e, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
+ 2+1, data) < 0)
return -EIO;
break;
default:
@@ -108,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 = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8);
+ ctrl->value = data[3] | (data[2] << 8);
if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
ctrl->value -= 0x10;
else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
@@ -124,6 +121,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
static int mi0343_set_ctrl(struct sn9c102_device* cam,
const struct v4l2_control* ctrl)
{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
u16 reg = 0;
int err = 0;
@@ -143,50 +141,42 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam,
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
- 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,
0x09, ctrl->value, 0x00,
0, 0);
break;
case V4L2_CID_GAIN:
- 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,
0x35, reg >> 8, reg & 0xff,
0, 0);
break;
case V4L2_CID_HFLIP:
- 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,
0x20, ctrl->value ? 0x40:0x00,
ctrl->value ? 0x20:0x00,
0, 0);
break;
case V4L2_CID_VFLIP:
- 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,
0x20, ctrl->value ? 0x80:0x00,
ctrl->value ? 0x80:0x00,
0, 0);
break;
case V4L2_CID_RED_BALANCE:
- 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,
0x2d, reg >> 8, reg & 0xff,
0, 0);
break;
case V4L2_CID_BLUE_BALANCE:
- 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,
0x2c, reg >> 8, reg & 0xff,
0, 0);
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
- 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,
0x2b, reg >> 8, reg & 0xff,
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,
0x2e, reg >> 8, reg & 0xff,
0, 0);
break;
@@ -216,16 +206,15 @@ static int mi0343_set_crop(struct sn9c102_device* cam,
static int mi0343_set_pix_format(struct sn9c102_device* cam,
const struct v4l2_pix_format* pix)
{
+ 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, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x0a, 0x00, 0x03, 0, 0);
err += sn9c102_write_reg(cam, 0x20, 0x19);
} else {
- 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,
0x0a, 0x00, 0x05, 0, 0);
err += sn9c102_write_reg(cam, 0xa0, 0x19);
}
@@ -237,7 +226,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor mi0343 = {
.name = "MI-0343",
.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,
.interface = SN9C102_I2C_2WIRES,
.i2c_slave_id = 0x5d,
@@ -343,19 +332,20 @@ static struct sn9c102_sensor mi0343 = {
int sn9c102_probe_mi0343(struct sn9c102_device* cam)
{
+ u8 data[5+1];
int err = 0;
- err += sn9c102_write_reg(cam, 0x01, 0x01);
- err += sn9c102_write_reg(cam, 0x00, 0x01);
- err += sn9c102_write_reg(cam, 0x28, 0x17);
+ err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
+ {0x28, 0x17});
+
if (err)
return -EIO;
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
- 2, mi0343_i2c_data) < 0)
+ 2, data) < 0)
return -EIO;
- if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3)
+ if (data[4] != 0x32 || data[3] != 0xe3)
return -ENODEV;
sn9c102_attach_sensor(cam, &mi0343);
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/video/sn9c102/sn9c102_mi0360.c
new file mode 100644
index 00000000000..64698acb0b1
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_mi0360.c
@@ -0,0 +1,338 @@
+/***************************************************************************
+ * Plug-in for MI-0360 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 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});
+
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+ 0x00, 0x01, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+ 0x00, 0x00, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
+ 0x01, 0xe1, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
+ 0x02, 0x81, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
+ 0x00, 0x17, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
+ 0x00, 0x11, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
+ 0x04, 0x9a, 0, 0);
+
+ return err;
+}
+
+
+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];
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[2];
+ return 0;
+ case V4L2_CID_GAIN:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[3];
+ return 0;
+ case V4L2_CID_RED_BALANCE:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[3];
+ return 0;
+ case V4L2_CID_BLUE_BALANCE:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[3];
+ 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)
+ return -EIO;
+ ctrl->value = data[3];
+ return 0;
+ case V4L2_CID_HFLIP:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[3] & 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)
+ return -EIO;
+ ctrl->value = data[3] & 0x80 ? 1 : 0;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static int mi0360_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
+{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+ int err = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x09, ctrl->value, 0x00,
+ 0, 0);
+ break;
+ case V4L2_CID_GAIN:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x35, 0x03, ctrl->value,
+ 0, 0);
+ break;
+ case V4L2_CID_RED_BALANCE:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x2c, 0x03, ctrl->value,
+ 0, 0);
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x2d, 0x03, ctrl->value,
+ 0, 0);
+ break;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x2b, 0x03, ctrl->value,
+ 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x2e, 0x03, ctrl->value,
+ 0, 0);
+ break;
+ case V4L2_CID_HFLIP:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x20, ctrl->value ? 0x40:0x00,
+ ctrl->value ? 0x20:0x00,
+ 0, 0);
+ break;
+ case V4L2_CID_VFLIP:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x20, ctrl->value ? 0x80:0x00,
+ ctrl->value ? 0x80:0x00,
+ 0, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return err ? -EIO : 0;
+}
+
+
+static int mi0360_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) + 0,
+ v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+ err += sn9c102_write_reg(cam, h_start, 0x12);
+ err += sn9c102_write_reg(cam, v_start, 0x13);
+
+ return err;
+}
+
+
+static int mi0360_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ 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 {
+ 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);
+ }
+
+ return err;
+}
+
+
+static struct sn9c102_sensor mi0360 = {
+ .name = "MI-0360",
+ .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+ .supported_bridge = BRIDGE_SN9C103,
+ .frequency = SN9C102_I2C_100KHZ,
+ .interface = SN9C102_I2C_2WIRES,
+ .i2c_slave_id = 0x5d,
+ .init = &mi0360_init,
+ .qctrl = {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "exposure",
+ .minimum = 0x00,
+ .maximum = 0x0f,
+ .step = 0x01,
+ .default_value = 0x05,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "global gain",
+ .minimum = 0x00,
+ .maximum = 0x7f,
+ .step = 0x01,
+ .default_value = 0x25,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "horizontal mirror",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "vertical mirror",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "blue balance",
+ .minimum = 0x00,
+ .maximum = 0x7f,
+ .step = 0x01,
+ .default_value = 0x0f,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "red balance",
+ .minimum = 0x00,
+ .maximum = 0x7f,
+ .step = 0x01,
+ .default_value = 0x32,
+ .flags = 0,
+ },
+ {
+ .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "green balance",
+ .minimum = 0x00,
+ .maximum = 0x7f,
+ .step = 0x01,
+ .default_value = 0x25,
+ .flags = 0,
+ },
+ },
+ .get_ctrl = &mi0360_get_ctrl,
+ .set_ctrl = &mi0360_set_ctrl,
+ .cropcap = {
+ .bounds = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ .defrect = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ },
+ .set_crop = &mi0360_set_crop,
+ .pix_format = {
+ .width = 640,
+ .height = 480,
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .priv = 8,
+ },
+ .set_pix_format = &mi0360_set_pix_format
+};
+
+
+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;
+
+ if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
+ 2+1, data) < 0)
+ return -EIO;
+
+ if (data[2] != 0x82 || data[3] != 0x43)
+ return -ENODEV;
+
+ sn9c102_attach_sensor(cam, &mi0360);
+
+ return 0;
+}
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
index 7df09ff38e6..31b6080b061 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7630.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c
@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor ov7630;
-
-
static int ov7630_init(struct sn9c102_device* cam)
{
int err = 0;
@@ -32,21 +29,20 @@ static int ov7630_init(struct sn9c102_device* cam)
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
- err += sn9c102_write_reg(cam, 0x00, 0x14);
- err += sn9c102_write_reg(cam, 0x60, 0x17);
- err += sn9c102_write_reg(cam, 0x0f, 0x18);
- err += sn9c102_write_reg(cam, 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);
err += sn9c102_i2c_write(cam, 0x11, 0x00);
- err += sn9c102_i2c_write(cam, 0x15, 0x34);
- err += sn9c102_i2c_write(cam, 0x16, 0x03);
- err += sn9c102_i2c_write(cam, 0x17, 0x1c);
- err += sn9c102_i2c_write(cam, 0x18, 0xbd);
- err += sn9c102_i2c_write(cam, 0x19, 0x06);
- err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
- err += sn9c102_i2c_write(cam, 0x1b, 0x04);
+ err += sn9c102_i2c_write(cam, 0x15, 0x35);
+ err += sn9c102_i2c_write(cam, 0x16, 0x03);
+ err += sn9c102_i2c_write(cam, 0x17, 0x1c);
+ err += sn9c102_i2c_write(cam, 0x18, 0xbd);
+ err += sn9c102_i2c_write(cam, 0x19, 0x06);
+ err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
+ err += sn9c102_i2c_write(cam, 0x1b, 0x04);
err += sn9c102_i2c_write(cam, 0x20, 0x44);
err += sn9c102_i2c_write(cam, 0x23, 0xee);
err += sn9c102_i2c_write(cam, 0x26, 0xa0);
@@ -65,42 +61,26 @@ 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_reg(cam, 0x00, 0x02);
- err += sn9c102_write_reg(cam, 0x00, 0x03);
- err += sn9c102_write_reg(cam, 0x1a, 0x04);
- err += sn9c102_write_reg(cam, 0x20, 0x05);
- err += sn9c102_write_reg(cam, 0x20, 0x06);
- err += sn9c102_write_reg(cam, 0x20, 0x07);
- err += sn9c102_write_reg(cam, 0x03, 0x10);
- err += sn9c102_write_reg(cam, 0x0a, 0x14);
- err += sn9c102_write_reg(cam, 0x60, 0x17);
- err += sn9c102_write_reg(cam, 0x0f, 0x18);
- err += sn9c102_write_reg(cam, 0x50, 0x19);
- err += sn9c102_write_reg(cam, 0x1d, 0x1a);
- err += sn9c102_write_reg(cam, 0x10, 0x1b);
- err += sn9c102_write_reg(cam, 0x02, 0x1c);
- err += sn9c102_write_reg(cam, 0x03, 0x1d);
- err += sn9c102_write_reg(cam, 0x0f, 0x1e);
- err += sn9c102_write_reg(cam, 0x0c, 0x1f);
- err += sn9c102_write_reg(cam, 0x00, 0x20);
- err += sn9c102_write_reg(cam, 0x10, 0x21);
- err += sn9c102_write_reg(cam, 0x20, 0x22);
- err += sn9c102_write_reg(cam, 0x30, 0x23);
- err += sn9c102_write_reg(cam, 0x40, 0x24);
- err += sn9c102_write_reg(cam, 0x50, 0x25);
- err += sn9c102_write_reg(cam, 0x60, 0x26);
- err += sn9c102_write_reg(cam, 0x70, 0x27);
- err += sn9c102_write_reg(cam, 0x80, 0x28);
- err += sn9c102_write_reg(cam, 0x90, 0x29);
- err += sn9c102_write_reg(cam, 0xa0, 0x2a);
- err += sn9c102_write_reg(cam, 0xb0, 0x2b);
- err += sn9c102_write_reg(cam, 0xc0, 0x2c);
- err += sn9c102_write_reg(cam, 0xd0, 0x2d);
- err += sn9c102_write_reg(cam, 0xe0, 0x2e);
- err += sn9c102_write_reg(cam, 0xf0, 0x2f);
- err += sn9c102_write_reg(cam, 0xff, 0x30);
+ err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
+ {0x1a, 0x04}, {0x20, 0x05},
+ {0x20, 0x06}, {0x20, 0x07},
+ {0x03, 0x10}, {0x0a, 0x14},
+ {0x60, 0x17}, {0x0f, 0x18},
+ {0x50, 0x19}, {0x1d, 0x1a},
+ {0x10, 0x1b}, {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_i2c_write(cam, 0x12, 0x8d);
err += sn9c102_i2c_write(cam, 0x12, 0x0d);
@@ -108,23 +88,23 @@ static int ov7630_init(struct sn9c102_device* cam)
err += sn9c102_i2c_write(cam, 0x11, 0x01);
err += sn9c102_i2c_write(cam, 0x1b, 0x04);
err += sn9c102_i2c_write(cam, 0x20, 0x44);
- err += sn9c102_i2c_write(cam, 0x23, 0xee);
- err += sn9c102_i2c_write(cam, 0x26, 0xa0);
- err += sn9c102_i2c_write(cam, 0x27, 0x9a);
+ err += sn9c102_i2c_write(cam, 0x23, 0xee);
+ err += sn9c102_i2c_write(cam, 0x26, 0xa0);
+ err += sn9c102_i2c_write(cam, 0x27, 0x9a);
err += sn9c102_i2c_write(cam, 0x28, 0x20);
- err += sn9c102_i2c_write(cam, 0x29, 0x30);
- err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
- err += sn9c102_i2c_write(cam, 0x30, 0x24);
- err += sn9c102_i2c_write(cam, 0x32, 0x86);
- err += sn9c102_i2c_write(cam, 0x60, 0xa9);
- err += sn9c102_i2c_write(cam, 0x61, 0x42);
- err += sn9c102_i2c_write(cam, 0x65, 0x00);
- err += sn9c102_i2c_write(cam, 0x69, 0x38);
- err += sn9c102_i2c_write(cam, 0x6f, 0x88);
- err += sn9c102_i2c_write(cam, 0x70, 0x0b);
- err += sn9c102_i2c_write(cam, 0x71, 0x00);
- err += sn9c102_i2c_write(cam, 0x74, 0x21);
- err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
+ err += sn9c102_i2c_write(cam, 0x29, 0x30);
+ err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
+ err += sn9c102_i2c_write(cam, 0x30, 0x24);
+ err += sn9c102_i2c_write(cam, 0x32, 0x86);
+ err += sn9c102_i2c_write(cam, 0x60, 0xa9);
+ err += sn9c102_i2c_write(cam, 0x61, 0x42);
+ err += sn9c102_i2c_write(cam, 0x65, 0x00);
+ err += sn9c102_i2c_write(cam, 0x69, 0x38);
+ err += sn9c102_i2c_write(cam, 0x6f, 0x88);
+ err += sn9c102_i2c_write(cam, 0x70, 0x0b);
+ err += sn9c102_i2c_write(cam, 0x71, 0x00);
+ err += sn9c102_i2c_write(cam, 0x74, 0x21);
+ err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
break;
default:
break;
@@ -428,15 +408,14 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
- err += sn9c102_write_reg(cam, 0x01, 0x01);
- err += sn9c102_write_reg(cam, 0x00, 0x01);
- err += sn9c102_write_reg(cam, 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_reg(cam, 0x09, 0x01);
- err += sn9c102_write_reg(cam, 0x42, 0x01);
- err += sn9c102_write_reg(cam, 0x28, 0x17);
- err += sn9c102_write_reg(cam, 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);
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c
index d670c24d443..c898e948fe8 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7660.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c
@@ -22,160 +22,84 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor ov7660;
-
-
static int ov7660_init(struct sn9c102_device* cam)
{
int err = 0;
- err += sn9c102_write_reg(cam, 0x40, 0x02);
- err += sn9c102_write_reg(cam, 0x00, 0x03);
- err += sn9c102_write_reg(cam, 0x1a, 0x04);
- err += sn9c102_write_reg(cam, 0x03, 0x10);
- err += sn9c102_write_reg(cam, 0x08, 0x14);
- err += sn9c102_write_reg(cam, 0x20, 0x17);
- err += sn9c102_write_reg(cam, 0x8b, 0x18);
- err += sn9c102_write_reg(cam, 0x00, 0x19);
- err += sn9c102_write_reg(cam, 0x1d, 0x1a);
- err += sn9c102_write_reg(cam, 0x10, 0x1b);
- err += sn9c102_write_reg(cam, 0x02, 0x1c);
- err += sn9c102_write_reg(cam, 0x03, 0x1d);
- err += sn9c102_write_reg(cam, 0x0f, 0x1e);
- err += sn9c102_write_reg(cam, 0x0c, 0x1f);
- err += sn9c102_write_reg(cam, 0x00, 0x20);
- err += sn9c102_write_reg(cam, 0x29, 0x21);
- err += sn9c102_write_reg(cam, 0x40, 0x22);
- err += sn9c102_write_reg(cam, 0x54, 0x23);
- err += sn9c102_write_reg(cam, 0x66, 0x24);
- err += sn9c102_write_reg(cam, 0x76, 0x25);
- err += sn9c102_write_reg(cam, 0x85, 0x26);
- err += sn9c102_write_reg(cam, 0x94, 0x27);
- err += sn9c102_write_reg(cam, 0xa1, 0x28);
- err += sn9c102_write_reg(cam, 0xae, 0x29);
- err += sn9c102_write_reg(cam, 0xbb, 0x2a);
- err += sn9c102_write_reg(cam, 0xc7, 0x2b);
- err += sn9c102_write_reg(cam, 0xd3, 0x2c);
- err += sn9c102_write_reg(cam, 0xde, 0x2d);
- err += sn9c102_write_reg(cam, 0xea, 0x2e);
- err += sn9c102_write_reg(cam, 0xf4, 0x2f);
- err += sn9c102_write_reg(cam, 0xff, 0x30);
- err += sn9c102_write_reg(cam, 0x00, 0x3F);
- err += sn9c102_write_reg(cam, 0xC7, 0x40);
- err += sn9c102_write_reg(cam, 0x01, 0x41);
- err += sn9c102_write_reg(cam, 0x44, 0x42);
- err += sn9c102_write_reg(cam, 0x00, 0x43);
- err += sn9c102_write_reg(cam, 0x44, 0x44);
- err += sn9c102_write_reg(cam, 0x00, 0x45);
- err += sn9c102_write_reg(cam, 0x44, 0x46);
- err += sn9c102_write_reg(cam, 0x00, 0x47);
- err += sn9c102_write_reg(cam, 0xC7, 0x48);
- err += sn9c102_write_reg(cam, 0x01, 0x49);
- err += sn9c102_write_reg(cam, 0xC7, 0x4A);
- err += sn9c102_write_reg(cam, 0x01, 0x4B);
- err += sn9c102_write_reg(cam, 0xC7, 0x4C);
- err += sn9c102_write_reg(cam, 0x01, 0x4D);
- err += sn9c102_write_reg(cam, 0x44, 0x4E);
- err += sn9c102_write_reg(cam, 0x00, 0x4F);
- err += sn9c102_write_reg(cam, 0x44, 0x50);
- err += sn9c102_write_reg(cam, 0x00, 0x51);
- err += sn9c102_write_reg(cam, 0x44, 0x52);
- err += sn9c102_write_reg(cam, 0x00, 0x53);
- err += sn9c102_write_reg(cam, 0xC7, 0x54);
- err += sn9c102_write_reg(cam, 0x01, 0x55);
- err += sn9c102_write_reg(cam, 0xC7, 0x56);
- err += sn9c102_write_reg(cam, 0x01, 0x57);
- err += sn9c102_write_reg(cam, 0xC7, 0x58);
- err += sn9c102_write_reg(cam, 0x01, 0x59);
- err += sn9c102_write_reg(cam, 0x44, 0x5A);
- err += sn9c102_write_reg(cam, 0x00, 0x5B);
- err += sn9c102_write_reg(cam, 0x44, 0x5C);
- err += sn9c102_write_reg(cam, 0x00, 0x5D);
- err += sn9c102_write_reg(cam, 0x44, 0x5E);
- err += sn9c102_write_reg(cam, 0x00, 0x5F);
- err += sn9c102_write_reg(cam, 0xC7, 0x60);
- err += sn9c102_write_reg(cam, 0x01, 0x61);
- err += sn9c102_write_reg(cam, 0xC7, 0x62);
- err += sn9c102_write_reg(cam, 0x01, 0x63);
- err += sn9c102_write_reg(cam, 0xC7, 0x64);
- err += sn9c102_write_reg(cam, 0x01, 0x65);
- err += sn9c102_write_reg(cam, 0x44, 0x66);
- err += sn9c102_write_reg(cam, 0x00, 0x67);
- err += sn9c102_write_reg(cam, 0x44, 0x68);
- err += sn9c102_write_reg(cam, 0x00, 0x69);
- err += sn9c102_write_reg(cam, 0x44, 0x6A);
- err += sn9c102_write_reg(cam, 0x00, 0x6B);
- err += sn9c102_write_reg(cam, 0xC7, 0x6C);
- err += sn9c102_write_reg(cam, 0x01, 0x6D);
- err += sn9c102_write_reg(cam, 0xC7, 0x6E);
- err += sn9c102_write_reg(cam, 0x01, 0x6F);
- err += sn9c102_write_reg(cam, 0xC7, 0x70);
- err += sn9c102_write_reg(cam, 0x01, 0x71);
- err += sn9c102_write_reg(cam, 0x44, 0x72);
- err += sn9c102_write_reg(cam, 0x00, 0x73);
- err += sn9c102_write_reg(cam, 0x44, 0x74);
- err += sn9c102_write_reg(cam, 0x00, 0x75);
- err += sn9c102_write_reg(cam, 0x44, 0x76);
- err += sn9c102_write_reg(cam, 0x00, 0x77);
- err += sn9c102_write_reg(cam, 0xC7, 0x78);
- err += sn9c102_write_reg(cam, 0x01, 0x79);
- err += sn9c102_write_reg(cam, 0xC7, 0x7A);
- err += sn9c102_write_reg(cam, 0x01, 0x7B);
- err += sn9c102_write_reg(cam, 0xC7, 0x7C);
- err += sn9c102_write_reg(cam, 0x01, 0x7D);
- err += sn9c102_write_reg(cam, 0x44, 0x7E);
- err += sn9c102_write_reg(cam, 0x00, 0x7F);
- err += sn9c102_write_reg(cam, 0x14, 0x84);
- err += sn9c102_write_reg(cam, 0x00, 0x85);
- err += sn9c102_write_reg(cam, 0x27, 0x86);
- err += sn9c102_write_reg(cam, 0x00, 0x87);
- err += sn9c102_write_reg(cam, 0x07, 0x88);
- err += sn9c102_write_reg(cam, 0x00, 0x89);
- err += sn9c102_write_reg(cam, 0xEC, 0x8A);
- err += sn9c102_write_reg(cam, 0x0f, 0x8B);
- err += sn9c102_write_reg(cam, 0xD8, 0x8C);
- err += sn9c102_write_reg(cam, 0x0f, 0x8D);
- err += sn9c102_write_reg(cam, 0x3D, 0x8E);
- err += sn9c102_write_reg(cam, 0x00, 0x8F);
- err += sn9c102_write_reg(cam, 0x3D, 0x90);
- err += sn9c102_write_reg(cam, 0x00, 0x91);
- err += sn9c102_write_reg(cam, 0xCD, 0x92);
- err += sn9c102_write_reg(cam, 0x0f, 0x93);
- err += sn9c102_write_reg(cam, 0xf7, 0x94);
- err += sn9c102_write_reg(cam, 0x0f, 0x95);
- err += sn9c102_write_reg(cam, 0x0C, 0x96);
- err += sn9c102_write_reg(cam, 0x00, 0x97);
- err += sn9c102_write_reg(cam, 0x00, 0x98);
- err += sn9c102_write_reg(cam, 0x66, 0x99);
- err += sn9c102_write_reg(cam, 0x05, 0x9A);
- err += sn9c102_write_reg(cam, 0x00, 0x9B);
- err += sn9c102_write_reg(cam, 0x04, 0x9C);
- err += sn9c102_write_reg(cam, 0x00, 0x9D);
- err += sn9c102_write_reg(cam, 0x08, 0x9E);
- err += sn9c102_write_reg(cam, 0x00, 0x9F);
- err += sn9c102_write_reg(cam, 0x2D, 0xC0);
- err += sn9c102_write_reg(cam, 0x2D, 0xC1);
- err += sn9c102_write_reg(cam, 0x3A, 0xC2);
- err += sn9c102_write_reg(cam, 0x05, 0xC3);
- err += sn9c102_write_reg(cam, 0x04, 0xC4);
- err += sn9c102_write_reg(cam, 0x3F, 0xC5);
- err += sn9c102_write_reg(cam, 0x00, 0xC6);
- err += sn9c102_write_reg(cam, 0x00, 0xC7);
- err += sn9c102_write_reg(cam, 0x50, 0xC8);
- err += sn9c102_write_reg(cam, 0x3C, 0xC9);
- err += sn9c102_write_reg(cam, 0x28, 0xCA);
- err += sn9c102_write_reg(cam, 0xD8, 0xCB);
- err += sn9c102_write_reg(cam, 0x14, 0xCC);
- err += sn9c102_write_reg(cam, 0xEC, 0xCD);
- err += sn9c102_write_reg(cam, 0x32, 0xCE);
- err += sn9c102_write_reg(cam, 0xDD, 0xCF);
- err += sn9c102_write_reg(cam, 0x32, 0xD0);
- err += sn9c102_write_reg(cam, 0xDD, 0xD1);
- err += sn9c102_write_reg(cam, 0x6A, 0xD2);
- err += sn9c102_write_reg(cam, 0x50, 0xD3);
- err += sn9c102_write_reg(cam, 0x00, 0xD4);
- err += sn9c102_write_reg(cam, 0x00, 0xD5);
- err += sn9c102_write_reg(cam, 0x00, 0xD6);
+ err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
+ {0x1a, 0x04}, {0x03, 0x10},
+ {0x08, 0x14}, {0x20, 0x17},
+ {0x8b, 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});
err += sn9c102_i2c_write(cam, 0x12, 0x80);
err += sn9c102_i2c_write(cam, 0x11, 0x09);
@@ -572,13 +496,11 @@ static struct sn9c102_sensor ov7660 = {
int sn9c102_probe_ov7660(struct sn9c102_device* cam)
{
- int pid, ver, err = 0;
+ int pid, ver, err;
- err += sn9c102_write_reg(cam, 0x01, 0xf1);
- err += sn9c102_write_reg(cam, 0x00, 0xf1);
- err += sn9c102_write_reg(cam, 0x01, 0x01);
- err += sn9c102_write_reg(cam, 0x00, 0x01);
- err += sn9c102_write_reg(cam, 0x28, 0x17);
+ err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
+ {0x01, 0x01}, {0x00, 0x01},
+ {0x28, 0x17});
pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b);
diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c
index 8d79a5fae5d..67151964801 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas106b.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c
@@ -23,19 +23,13 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor pas106b;
-
-
static int pas106b_init(struct sn9c102_device* cam)
{
int err = 0;
- err += sn9c102_write_reg(cam, 0x00, 0x10);
- err += sn9c102_write_reg(cam, 0x00, 0x11);
- err += sn9c102_write_reg(cam, 0x00, 0x14);
- err += sn9c102_write_reg(cam, 0x20, 0x17);
- err += sn9c102_write_reg(cam, 0x20, 0x19);
- err += sn9c102_write_reg(cam, 0x09, 0x18);
+ err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
+ {0x00, 0x14}, {0x20, 0x17},
+ {0x20, 0x19}, {0x09, 0x18});
err += sn9c102_i2c_write(cam, 0x02, 0x0c);
err += sn9c102_i2c_write(cam, 0x05, 0x5a);
@@ -172,7 +166,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor pas106b = {
.name = "PAS106B",
.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,
.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
@@ -279,16 +273,17 @@ static struct sn9c102_sensor pas106b = {
int sn9c102_probe_pas106b(struct sn9c102_device* cam)
{
- int r0 = 0, r1 = 0, err = 0;
+ int r0 = 0, r1 = 0, err;
unsigned int pid = 0;
/*
Minimal initialization to enable the I2C communication
NOTE: do NOT change the values!
*/
- err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
- err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */
- err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
+ err = sn9c102_write_const_regs(cam,
+ {0x01, 0x01}, /* sensor power down */
+ {0x00, 0x01}, /* sensor power on */
+ {0x28, 0x17});/* sensor clock 24 MHz */
if (err)
return -EIO;
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
index 7894f01b56e..c1b8d6b63b4 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
@@ -28,9 +28,6 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor pas202bcb;
-
-
static int pas202bcb_init(struct sn9c102_device* cam)
{
int err = 0;
@@ -38,47 +35,29 @@ static int pas202bcb_init(struct sn9c102_device* cam)
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
- err += sn9c102_write_reg(cam, 0x00, 0x10);
- err += sn9c102_write_reg(cam, 0x00, 0x11);
- err += sn9c102_write_reg(cam, 0x00, 0x14);
- err += sn9c102_write_reg(cam, 0x20, 0x17);
- err += sn9c102_write_reg(cam, 0x30, 0x19);
- err += sn9c102_write_reg(cam, 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_reg(cam, 0x00, 0x02);
- err += sn9c102_write_reg(cam, 0x00, 0x03);
- err += sn9c102_write_reg(cam, 0x1a, 0x04);
- err += sn9c102_write_reg(cam, 0x20, 0x05);
- err += sn9c102_write_reg(cam, 0x20, 0x06);
- err += sn9c102_write_reg(cam, 0x20, 0x07);
- err += sn9c102_write_reg(cam, 0x00, 0x10);
- err += sn9c102_write_reg(cam, 0x00, 0x11);
- err += sn9c102_write_reg(cam, 0x00, 0x14);
- err += sn9c102_write_reg(cam, 0x20, 0x17);
- err += sn9c102_write_reg(cam, 0x30, 0x19);
- err += sn9c102_write_reg(cam, 0x09, 0x18);
- err += sn9c102_write_reg(cam, 0x02, 0x1c);
- err += sn9c102_write_reg(cam, 0x03, 0x1d);
- err += sn9c102_write_reg(cam, 0x0f, 0x1e);
- err += sn9c102_write_reg(cam, 0x0c, 0x1f);
- err += sn9c102_write_reg(cam, 0x00, 0x20);
- err += sn9c102_write_reg(cam, 0x10, 0x21);
- err += sn9c102_write_reg(cam, 0x20, 0x22);
- err += sn9c102_write_reg(cam, 0x30, 0x23);
- err += sn9c102_write_reg(cam, 0x40, 0x24);
- err += sn9c102_write_reg(cam, 0x50, 0x25);
- err += sn9c102_write_reg(cam, 0x60, 0x26);
- err += sn9c102_write_reg(cam, 0x70, 0x27);
- err += sn9c102_write_reg(cam, 0x80, 0x28);
- err += sn9c102_write_reg(cam, 0x90, 0x29);
- err += sn9c102_write_reg(cam, 0xa0, 0x2a);
- err += sn9c102_write_reg(cam, 0xb0, 0x2b);
- err += sn9c102_write_reg(cam, 0xc0, 0x2c);
- err += sn9c102_write_reg(cam, 0xd0, 0x2d);
- err += sn9c102_write_reg(cam, 0xe0, 0x2e);
- err += sn9c102_write_reg(cam, 0xf0, 0x2f);
- err += sn9c102_write_reg(cam, 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;
@@ -328,15 +307,15 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
- err += sn9c102_write_reg(cam, 0x01, 0x01); /* power down */
- err += sn9c102_write_reg(cam, 0x40, 0x01); /* power on */
- err += sn9c102_write_reg(cam, 0x28, 0x17); /* clock 24 MHz */
+ err = sn9c102_write_const_regs(cam,
+ {0x01, 0x01}, /* power down */
+ {0x40, 0x01}, /* power on */
+ {0x28, 0x17});/* clock 24 MHz */
break;
case BRIDGE_SN9C103: /* do _not_ change anything! */
- err += sn9c102_write_reg(cam, 0x09, 0x01);
- err += sn9c102_write_reg(cam, 0x44, 0x01);
- err += sn9c102_write_reg(cam, 0x44, 0x02);
- err += sn9c102_write_reg(cam, 0x29, 0x17);
+ err = sn9c102_write_const_regs(cam, {0x09, 0x01},
+ {0x44, 0x01}, {0x44, 0x02},
+ {0x29, 0x17});
break;
default:
break;
diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h
index 05f2942639c..1bbf64c897a 100644
--- a/drivers/media/video/sn9c102/sn9c102_sensor.h
+++ b/drivers/media/video/sn9c102/sn9c102_sensor.h
@@ -114,9 +114,17 @@ 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_write_regs(struct sn9c102_device*, u8* buff, u16 index);
-extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, 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)); })
/*****************************************************************************/
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
index 90023ad63ad..0e7ec8662c7 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
@@ -22,21 +22,14 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor tas5110c1b;
-
-
static int tas5110c1b_init(struct sn9c102_device* cam)
{
int err = 0;
- err += sn9c102_write_reg(cam, 0x01, 0x01);
- err += sn9c102_write_reg(cam, 0x44, 0x01);
- err += sn9c102_write_reg(cam, 0x00, 0x10);
- err += sn9c102_write_reg(cam, 0x00, 0x11);
- 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_write_const_regs(cam, {0x01, 0x01}, {0x44, 0x01},
+ {0x00, 0x10}, {0x00, 0x11},
+ {0x0a, 0x14}, {0x60, 0x17},
+ {0x06, 0x18}, {0xfb, 0x19});
err += sn9c102_i2c_write(cam, 0xc0, 0x80);
@@ -98,7 +91,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor tas5110c1b = {
.name = "TAS5110C1B",
.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,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_3WIRES,
@@ -146,7 +139,6 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
const struct usb_device_id tas5110c1b_id_table[] = {
{ USB_DEVICE(0x0c45, 0x6001), },
{ USB_DEVICE(0x0c45, 0x6005), },
- { USB_DEVICE(0x0c45, 0x6007), },
{ USB_DEVICE(0x0c45, 0x60ab), },
{ }
};
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c
new file mode 100644
index 00000000000..83a39e8b5e7
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110d.c
@@ -0,0 +1,118 @@
+/***************************************************************************
+ * 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;
+
+ err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x04, 0x01},
+ {0x0a, 0x14}, {0x60, 0x17},
+ {0x06, 0x18}, {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;
+}
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
index cb1b318bc1f..50406503fc4 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
@@ -22,21 +22,14 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor tas5130d1b;
-
-
static int tas5130d1b_init(struct sn9c102_device* cam)
{
- int err = 0;
+ int err;
- err += sn9c102_write_reg(cam, 0x01, 0x01);
- err += sn9c102_write_reg(cam, 0x20, 0x17);
- err += sn9c102_write_reg(cam, 0x04, 0x01);
- err += sn9c102_write_reg(cam, 0x01, 0x10);
- err += sn9c102_write_reg(cam, 0x00, 0x11);
- err += sn9c102_write_reg(cam, 0x00, 0x14);
- err += sn9c102_write_reg(cam, 0x60, 0x17);
- err += sn9c102_write_reg(cam, 0x07, 0x18);
+ err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x20, 0x17},
+ {0x04, 0x01}, {0x01, 0x10},
+ {0x00, 0x11}, {0x00, 0x14},
+ {0x60, 0x17}, {0x07, 0x18});
return err;
}
@@ -99,7 +92,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor tas5130d1b = {
.name = "TAS5130D1B",
.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,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_3WIRES,