aboutsummaryrefslogtreecommitdiffstats
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 1a7ccb666ab0..19204f5686e1 100644
--- a/drivers/media/video/sn9c102/Kconfig
+++ b/drivers/media/video/sn9c102/Kconfig
@@ -1,6 +1,6 @@
1config USB_SN9C102 1config USB_SN9C102
2 tristate "USB SN9C1xx PC Camera Controller support" 2 tristate "USB SN9C1xx PC Camera Controller support"
3 depends on USB && VIDEO_V4L1 3 depends on USB && VIDEO_V4L2
4 ---help--- 4 ---help---
5 Say Y here if you want support for cameras based on SONiX SN9C101, 5 Say Y here if you want support for cameras based on SONiX SN9C101,
6 SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. 6 SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile
index 30e3dfe537fe..a56d16f69c71 100644
--- a/drivers/media/video/sn9c102/Makefile
+++ b/drivers/media/video/sn9c102/Makefile
@@ -1,7 +1,14 @@
1sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ 1sn9c102-objs := sn9c102_core.o \
2 sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \ 2 sn9c102_hv7131d.o \
3 sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ 3 sn9c102_hv7131r.o \
4 sn9c102_tas5130d1b.o 4 sn9c102_mi0343.o \
5 sn9c102_mi0360.o \
6 sn9c102_ov7630.o \
7 sn9c102_ov7660.o \
8 sn9c102_pas106b.o \
9 sn9c102_pas202bcb.o \
10 sn9c102_tas5110c1b.o \
11 sn9c102_tas5110d.o \
12 sn9c102_tas5130d1b.o
5 13
6obj-$(CONFIG_USB_SN9C102) += sn9c102.o 14obj-$(CONFIG_USB_SN9C102) += sn9c102.o
7
diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
index 5428f34e7c5b..680e74634527 100644
--- a/drivers/media/video/sn9c102/sn9c102.h
+++ b/drivers/media/video/sn9c102/sn9c102.h
@@ -78,8 +78,13 @@ enum sn9c102_stream_state {
78 78
79typedef char sn9c102_sof_header_t[62]; 79typedef char sn9c102_sof_header_t[62];
80 80
81struct sn9c102_sof_t {
82 sn9c102_sof_header_t header;
83 u16 bytesread;
84};
85
81struct sn9c102_sysfs_attr { 86struct sn9c102_sysfs_attr {
82 u8 reg, i2c_reg; 87 u16 reg, i2c_reg;
83 sn9c102_sof_header_t frame_header; 88 sn9c102_sof_header_t frame_header;
84}; 89};
85 90
@@ -112,7 +117,7 @@ struct sn9c102_device {
112 struct v4l2_jpegcompression compression; 117 struct v4l2_jpegcompression compression;
113 118
114 struct sn9c102_sysfs_attr sysfs; 119 struct sn9c102_sysfs_attr sysfs;
115 sn9c102_sof_header_t sof_header; 120 struct sn9c102_sof_t sof;
116 u16 reg[384]; 121 u16 reg[384];
117 122
118 struct sn9c102_module_param module_param; 123 struct sn9c102_module_param module_param;
@@ -182,8 +187,8 @@ do { \
182 if ((level) == 1 || (level) == 2) \ 187 if ((level) == 1 || (level) == 2) \
183 pr_info("sn9c102: " fmt "\n", ## args); \ 188 pr_info("sn9c102: " fmt "\n", ## args); \
184 else if ((level) == 3) \ 189 else if ((level) == 3) \
185 pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \ 190 pr_debug("sn9c102: [%s:%d] " fmt "\n", \
186 __LINE__ , ## args); \ 191 __FUNCTION__, __LINE__ , ## args); \
187 } \ 192 } \
188} while (0) 193} while (0)
189#else 194#else
@@ -194,8 +199,8 @@ do { \
194 199
195#undef PDBG 200#undef PDBG
196#define PDBG(fmt, args...) \ 201#define PDBG(fmt, args...) \
197dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ 202dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
198 __FUNCTION__, __LINE__ , ## args) 203 __LINE__ , ## args)
199 204
200#undef PDBGG 205#undef PDBGG
201#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ 206#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 d0e2b40a7725..89f83354de3b 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -44,11 +44,12 @@
44/*****************************************************************************/ 44/*****************************************************************************/
45 45
46#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers" 46#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers"
47#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" 47#define SN9C102_MODULE_ALIAS "sn9c1xx"
48#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
48#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" 49#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
49#define SN9C102_MODULE_LICENSE "GPL" 50#define SN9C102_MODULE_LICENSE "GPL"
50#define SN9C102_MODULE_VERSION "1:1.34" 51#define SN9C102_MODULE_VERSION "1:1.39"
51#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 34) 52#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 39)
52 53
53/*****************************************************************************/ 54/*****************************************************************************/
54 55
@@ -56,6 +57,7 @@ MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
56 57
57MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL); 58MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
58MODULE_DESCRIPTION(SN9C102_MODULE_NAME); 59MODULE_DESCRIPTION(SN9C102_MODULE_NAME);
60MODULE_ALIAS(SN9C102_MODULE_ALIAS);
59MODULE_VERSION(SN9C102_MODULE_VERSION); 61MODULE_VERSION(SN9C102_MODULE_VERSION);
60MODULE_LICENSE(SN9C102_MODULE_LICENSE); 62MODULE_LICENSE(SN9C102_MODULE_LICENSE);
61 63
@@ -106,8 +108,7 @@ MODULE_PARM_DESC(debug,
106 "\n1 = critical errors" 108 "\n1 = critical errors"
107 "\n2 = significant informations" 109 "\n2 = significant informations"
108 "\n3 = more verbose messages" 110 "\n3 = more verbose messages"
109 "\nLevel 3 is useful for testing only, when only " 111 "\nLevel 3 is useful for testing only."
110 "one device is used."
111 "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"." 112 "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
112 "\n"); 113 "\n");
113#endif 114#endif
@@ -121,8 +122,8 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
121 struct v4l2_pix_format* p = &(cam->sensor.pix_format); 122 struct v4l2_pix_format* p = &(cam->sensor.pix_format);
122 struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); 123 struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
123 size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? 124 size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
124 (p->width * p->height * p->priv) / 8 : 125 (p->width * p->height * p->priv) / 8 :
125 (r->width * r->height * p->priv) / 8; 126 (r->width * r->height * p->priv) / 8;
126 void* buff = NULL; 127 void* buff = NULL;
127 u32 i; 128 u32 i;
128 129
@@ -208,27 +209,40 @@ static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
208} 209}
209 210
210/*****************************************************************************/ 211/*****************************************************************************/
211 212/*
212int sn9c102_write_regs(struct sn9c102_device* cam, u8* buff, u16 index) 213 * Write a sequence of count value/register pairs. Returns -1 after the
214 * first failed write, or 0 for no errors.
215 */
216int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2],
217 int count)
213{ 218{
214 struct usb_device* udev = cam->usbdev; 219 struct usb_device* udev = cam->usbdev;
220 u8* value = cam->control_buffer; /* Needed for DMA'able memory */
215 int i, res; 221 int i, res;
216 222
217 if (index + sizeof(buff) >= ARRAY_SIZE(cam->reg)) 223 for (i = 0; i < count; i++) {
218 return -1; 224 u8 index = valreg[i][1];
225
226 /*
227 * index is a u8, so it must be <256 and can't be out of range.
228 * If we put in a check anyway, gcc annoys us with a warning
229 * that our check is useless. People get all uppity when they
230 * see warnings in the kernel compile.
231 */
232
233 *value = valreg[i][0];
234 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
235 0x08, 0x41, index, 0,
236 value, 1, SN9C102_CTRL_TIMEOUT);
237 if (res < 0) {
238 DBG(3, "Failed to write a register (value 0x%02X, "
239 "index 0x%02X, error %d)", *value, index, res);
240 return -1;
241 }
219 242
220 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, 243 cam->reg[index] = *value;
221 index, 0, buff, sizeof(buff),
222 SN9C102_CTRL_TIMEOUT*sizeof(buff));
223 if (res < 0) {
224 DBG(3, "Failed to write registers (index 0x%02X, error %d)",
225 index, res);
226 return -1;
227 } 244 }
228 245
229 for (i = 0; i < sizeof(buff); i++)
230 cam->reg[index+i] = buff[i];
231
232 return 0; 246 return 0;
233} 247}
234 248
@@ -485,18 +499,43 @@ static size_t sn9c102_sof_length(struct sn9c102_device* cam)
485static void* 499static void*
486sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) 500sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
487{ 501{
488 char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; 502 static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
489 size_t soflen = 0, i; 503 const char *m = mem;
504 size_t soflen = 0, i, j;
490 505
491 soflen = sn9c102_sof_length(cam); 506 soflen = sn9c102_sof_length(cam);
492 507
493 for (i = 0; (len >= soflen) && (i <= len - soflen); i++) 508 for (i = 0; i < len; i++) {
494 if (!memcmp(mem + i, sof_header, sizeof(sof_header))) { 509 size_t b;
495 memcpy(cam->sof_header, mem + i, 510
496 sizeof(sn9c102_sof_header_t)); 511 /* Read the variable part of the header */
497 /* Skip the header */ 512 if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
498 return mem + i + soflen; 513 cam->sof.header[cam->sof.bytesread] = *(m+i);
514 if (++cam->sof.bytesread == soflen) {
515 cam->sof.bytesread = 0;
516 return mem + i;
517 }
518 continue;
519 }
520
521 /* Search for the SOF marker (fixed part) in the header */
522 for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
523 if (unlikely(i+j) == len)
524 return NULL;
525 if (*(m+i+j) == marker[cam->sof.bytesread]) {
526 cam->sof.header[cam->sof.bytesread] = *(m+i+j);
527 if (++cam->sof.bytesread == sizeof(marker)) {
528 PDBGG("Bytes to analyze: %zd. SOF "
529 "starts at byte #%zd", len, i);
530 i += j+1;
531 break;
532 }
533 } else {
534 cam->sof.bytesread = 0;
535 break;
499 } 536 }
537 }
538 }
500 539
501 return NULL; 540 return NULL;
502} 541}
@@ -505,7 +544,7 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
505static void* 544static void*
506sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) 545sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
507{ 546{
508 char eof_header[4][4] = { 547 static const u8 eof_header[4][4] = {
509 {0x00, 0x00, 0x00, 0x00}, 548 {0x00, 0x00, 0x00, 0x00},
510 {0x40, 0x00, 0x00, 0x00}, 549 {0x40, 0x00, 0x00, 0x00},
511 {0x80, 0x00, 0x00, 0x00}, 550 {0x80, 0x00, 0x00, 0x00},
@@ -513,10 +552,16 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
513 }; 552 };
514 size_t i, j; 553 size_t i, j;
515 554
555 /* The EOF header does not exist in compressed data */
516 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || 556 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
517 cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) 557 cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
518 return NULL; /* EOF header does not exist in compressed data */ 558 return NULL;
519 559
560 /*
561 The EOF header might cross the packet boundary, but this is not a
562 problem, since the end of a frame is determined by checking its size
563 in the first place.
564 */
520 for (i = 0; (len >= 4) && (i <= len - 4); i++) 565 for (i = 0; (len >= 4) && (i <= len - 4); i++)
521 for (j = 0; j < ARRAY_SIZE(eof_header); j++) 566 for (j = 0; j < ARRAY_SIZE(eof_header); j++)
522 if (!memcmp(mem + i, eof_header[j], 4)) 567 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)
529static void 574static void
530sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f) 575sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
531{ 576{
532 static u8 jpeg_header[589] = { 577 static const u8 jpeg_header[589] = {
533 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05, 578 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
534 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06, 579 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
535 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e, 580 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
@@ -639,6 +684,7 @@ static void sn9c102_urb_complete(struct urb *urb)
639 cam->stream = STREAM_OFF; 684 cam->stream = STREAM_OFF;
640 if ((*f)) 685 if ((*f))
641 (*f)->state = F_QUEUED; 686 (*f)->state = F_QUEUED;
687 cam->sof.bytesread = 0;
642 DBG(3, "Stream interrupted by application"); 688 DBG(3, "Stream interrupted by application");
643 wake_up(&cam->wait_stream); 689 wake_up(&cam->wait_stream);
644 } 690 }
@@ -676,6 +722,7 @@ static void sn9c102_urb_complete(struct urb *urb)
676 if (status) { 722 if (status) {
677 DBG(3, "Error in isochronous frame"); 723 DBG(3, "Error in isochronous frame");
678 (*f)->state = F_ERROR; 724 (*f)->state = F_ERROR;
725 cam->sof.bytesread = 0;
679 continue; 726 continue;
680 } 727 }
681 728
@@ -692,13 +739,13 @@ end_of_frame:
692 if (eof) 739 if (eof)
693 img = (eof > pos) ? eof - pos - 1 : 0; 740 img = (eof > pos) ? eof - pos - 1 : 0;
694 741
695 if ((*f)->buf.bytesused+img > imagesize) { 742 if ((*f)->buf.bytesused + img > imagesize) {
696 u32 b; 743 u32 b;
697 b = (*f)->buf.bytesused + img - 744 b = (*f)->buf.bytesused + img -
698 imagesize; 745 imagesize;
699 img = imagesize - (*f)->buf.bytesused; 746 img = imagesize - (*f)->buf.bytesused;
700 DBG(3, "Expected EOF not found: " 747 PDBGG("Expected EOF not found: video "
701 "video frame cut"); 748 "frame cut");
702 if (eof) 749 if (eof)
703 DBG(3, "Exceeded limit: +%u " 750 DBG(3, "Exceeded limit: +%u "
704 "bytes", (unsigned)(b)); 751 "bytes", (unsigned)(b));
@@ -719,11 +766,6 @@ end_of_frame:
719 V4L2_PIX_FMT_JPEG) && eof)) { 766 V4L2_PIX_FMT_JPEG) && eof)) {
720 u32 b; 767 u32 b;
721 768
722 if (cam->sensor.pix_format.pixelformat
723 == V4L2_PIX_FMT_JPEG)
724 sn9c102_write_eoimarker(cam,
725 (*f));
726
727 b = (*f)->buf.bytesused; 769 b = (*f)->buf.bytesused;
728 (*f)->state = F_DONE; 770 (*f)->state = F_DONE;
729 (*f)->buf.sequence= ++cam->frame_count; 771 (*f)->buf.sequence= ++cam->frame_count;
@@ -741,7 +783,7 @@ end_of_frame:
741 spin_unlock(&cam->queue_lock); 783 spin_unlock(&cam->queue_lock);
742 784
743 memcpy(cam->sysfs.frame_header, 785 memcpy(cam->sysfs.frame_header,
744 cam->sof_header, soflen); 786 cam->sof.header, soflen);
745 787
746 DBG(3, "Video frame captured: %lu " 788 DBG(3, "Video frame captured: %lu "
747 "bytes", (unsigned long)(b)); 789 "bytes", (unsigned long)(b));
@@ -791,7 +833,13 @@ start_of_frame:
791 V4L2_PIX_FMT_SN9C10X || 833 V4L2_PIX_FMT_SN9C10X ||
792 cam->sensor.pix_format.pixelformat == 834 cam->sensor.pix_format.pixelformat ==
793 V4L2_PIX_FMT_JPEG) { 835 V4L2_PIX_FMT_JPEG) {
794 eof = sof - soflen; 836 if (sof - pos >= soflen) {
837 eof = sof - soflen;
838 } else { /* remove header */
839 eof = pos;
840 (*f)->buf.bytesused -=
841 (soflen - (sof - pos));
842 }
795 goto end_of_frame; 843 goto end_of_frame;
796 } else { 844 } else {
797 DBG(3, "SOF before expected EOF after " 845 DBG(3, "SOF before expected EOF after "
@@ -878,6 +926,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
878 } 926 }
879 927
880 cam->frame_current = NULL; 928 cam->frame_current = NULL;
929 cam->sof.bytesread = 0;
881 930
882 for (i = 0; i < SN9C102_URBS; i++) { 931 for (i = 0; i < SN9C102_URBS; i++) {
883 err = usb_submit_urb(cam->urb[i], GFP_KERNEL); 932 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)
959 1008
960 if (len < 6) { 1009 if (len < 6) {
961 strncpy(str, buff, len); 1010 strncpy(str, buff, len);
962 str[len+1] = '\0'; 1011 str[len] = '\0';
963 } else { 1012 } else {
964 strncpy(str, buff, 4); 1013 strncpy(str, buff, 6);
965 str[6] = '\0'; 1014 str[6] = '\0';
966 } 1015 }
967 1016
@@ -1062,7 +1111,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
1062 1111
1063 count = sprintf(buf, "%d\n", val); 1112 count = sprintf(buf, "%d\n", val);
1064 1113
1065 DBG(3, "Read bytes: %zd", count); 1114 DBG(3, "Read bytes: %zd, value: %d", count, val);
1066 1115
1067 mutex_unlock(&sn9c102_sysfs_lock); 1116 mutex_unlock(&sn9c102_sysfs_lock);
1068 1117
@@ -1197,7 +1246,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
1197 1246
1198 count = sprintf(buf, "%d\n", val); 1247 count = sprintf(buf, "%d\n", val);
1199 1248
1200 DBG(3, "Read bytes: %zd", count); 1249 DBG(3, "Read bytes: %zd, value: %d", count, val);
1201 1250
1202 mutex_unlock(&sn9c102_sysfs_lock); 1251 mutex_unlock(&sn9c102_sysfs_lock);
1203 1252
@@ -1371,35 +1420,35 @@ static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,
1371 1420
1372static int sn9c102_create_sysfs(struct sn9c102_device* cam) 1421static int sn9c102_create_sysfs(struct sn9c102_device* cam)
1373{ 1422{
1374 struct video_device *v4ldev = cam->v4ldev; 1423 struct class_device *classdev = &(cam->v4ldev->class_dev);
1375 int err = 0; 1424 int err = 0;
1376 1425
1377 if ((err = video_device_create_file(v4ldev, &class_device_attr_reg))) 1426 if ((err = class_device_create_file(classdev, &class_device_attr_reg)))
1378 goto err_out; 1427 goto err_out;
1379 if ((err = video_device_create_file(v4ldev, &class_device_attr_val))) 1428 if ((err = class_device_create_file(classdev, &class_device_attr_val)))
1380 goto err_reg; 1429 goto err_reg;
1381 if ((err = video_device_create_file(v4ldev, 1430 if ((err = class_device_create_file(classdev,
1382 &class_device_attr_frame_header))) 1431 &class_device_attr_frame_header)))
1383 goto err_val; 1432 goto err_val;
1384 1433
1385 if (cam->sensor.sysfs_ops) { 1434 if (cam->sensor.sysfs_ops) {
1386 if ((err = video_device_create_file(v4ldev, 1435 if ((err = class_device_create_file(classdev,
1387 &class_device_attr_i2c_reg))) 1436 &class_device_attr_i2c_reg)))
1388 goto err_frame_header; 1437 goto err_frame_header;
1389 if ((err = video_device_create_file(v4ldev, 1438 if ((err = class_device_create_file(classdev,
1390 &class_device_attr_i2c_val))) 1439 &class_device_attr_i2c_val)))
1391 goto err_i2c_reg; 1440 goto err_i2c_reg;
1392 } 1441 }
1393 1442
1394 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { 1443 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
1395 if ((err = video_device_create_file(v4ldev, 1444 if ((err = class_device_create_file(classdev,
1396 &class_device_attr_green))) 1445 &class_device_attr_green)))
1397 goto err_i2c_val; 1446 goto err_i2c_val;
1398 } else { 1447 } else {
1399 if ((err = video_device_create_file(v4ldev, 1448 if ((err = class_device_create_file(classdev,
1400 &class_device_attr_blue))) 1449 &class_device_attr_blue)))
1401 goto err_i2c_val; 1450 goto err_i2c_val;
1402 if ((err = video_device_create_file(v4ldev, 1451 if ((err = class_device_create_file(classdev,
1403 &class_device_attr_red))) 1452 &class_device_attr_red)))
1404 goto err_blue; 1453 goto err_blue;
1405 } 1454 }
@@ -1407,19 +1456,19 @@ static int sn9c102_create_sysfs(struct sn9c102_device* cam)
1407 return 0; 1456 return 0;
1408 1457
1409err_blue: 1458err_blue:
1410 video_device_remove_file(v4ldev, &class_device_attr_blue); 1459 class_device_remove_file(classdev, &class_device_attr_blue);
1411err_i2c_val: 1460err_i2c_val:
1412 if (cam->sensor.sysfs_ops) 1461 if (cam->sensor.sysfs_ops)
1413 video_device_remove_file(v4ldev, &class_device_attr_i2c_val); 1462 class_device_remove_file(classdev, &class_device_attr_i2c_val);
1414err_i2c_reg: 1463err_i2c_reg:
1415 if (cam->sensor.sysfs_ops) 1464 if (cam->sensor.sysfs_ops)
1416 video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); 1465 class_device_remove_file(classdev, &class_device_attr_i2c_reg);
1417err_frame_header: 1466err_frame_header:
1418 video_device_remove_file(v4ldev, &class_device_attr_frame_header); 1467 class_device_remove_file(classdev, &class_device_attr_frame_header);
1419err_val: 1468err_val:
1420 video_device_remove_file(v4ldev, &class_device_attr_val); 1469 class_device_remove_file(classdev, &class_device_attr_val);
1421err_reg: 1470err_reg:
1422 video_device_remove_file(v4ldev, &class_device_attr_reg); 1471 class_device_remove_file(classdev, &class_device_attr_reg);
1423err_out: 1472err_out:
1424 return err; 1473 return err;
1425} 1474}
@@ -1477,10 +1526,10 @@ sn9c102_set_compression(struct sn9c102_device* cam,
1477 case BRIDGE_SN9C101: 1526 case BRIDGE_SN9C101:
1478 case BRIDGE_SN9C102: 1527 case BRIDGE_SN9C102:
1479 case BRIDGE_SN9C103: 1528 case BRIDGE_SN9C103:
1480 if (compression->quality == 0) 1529 if (compression->quality == 0)
1481 err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 1530 err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
1482 0x17); 1531 0x17);
1483 else if (compression->quality == 1) 1532 else if (compression->quality == 1)
1484 err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 1533 err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
1485 0x17); 1534 0x17);
1486 break; 1535 break;
@@ -1489,10 +1538,10 @@ sn9c102_set_compression(struct sn9c102_device* cam,
1489 if (compression->quality == 0) { 1538 if (compression->quality == 0) {
1490 for (i = 0; i <= 63; i++) { 1539 for (i = 0; i <= 63; i++) {
1491 err += sn9c102_write_reg(cam, 1540 err += sn9c102_write_reg(cam,
1492 SN9C102_Y_QTABLE0[i], 1541 SN9C102_Y_QTABLE1[i],
1493 0x100 + i); 1542 0x100 + i);
1494 err += sn9c102_write_reg(cam, 1543 err += sn9c102_write_reg(cam,
1495 SN9C102_UV_QTABLE0[i], 1544 SN9C102_UV_QTABLE1[i],
1496 0x140 + i); 1545 0x140 + i);
1497 } 1546 }
1498 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf, 1547 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
@@ -1597,9 +1646,13 @@ static int sn9c102_init(struct sn9c102_device* cam)
1597 if (cam->bridge == BRIDGE_SN9C101 || 1646 if (cam->bridge == BRIDGE_SN9C101 ||
1598 cam->bridge == BRIDGE_SN9C102 || 1647 cam->bridge == BRIDGE_SN9C102 ||
1599 cam->bridge == BRIDGE_SN9C103) { 1648 cam->bridge == BRIDGE_SN9C103) {
1649 if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
1650 s->pix_format.pixelformat= V4L2_PIX_FMT_SBGGR8;
1600 cam->compression.quality = cam->reg[0x17] & 0x01 ? 1651 cam->compression.quality = cam->reg[0x17] & 0x01 ?
1601 0 : 1; 1652 0 : 1;
1602 } else { 1653 } else {
1654 if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
1655 s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
1603 cam->compression.quality = cam->reg[0x18] & 0x40 ? 1656 cam->compression.quality = cam->reg[0x18] & 0x40 ?
1604 0 : 1; 1657 0 : 1;
1605 err += sn9c102_set_compression(cam, &cam->compression); 1658 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)
1805 DBG(3, "Close and open the device again to choose " 1858 DBG(3, "Close and open the device again to choose "
1806 "the read method"); 1859 "the read method");
1807 mutex_unlock(&cam->fileop_mutex); 1860 mutex_unlock(&cam->fileop_mutex);
1808 return -EINVAL; 1861 return -EBUSY;
1809 } 1862 }
1810 1863
1811 if (cam->io == IO_NONE) { 1864 if (cam->io == IO_NONE) {
@@ -1845,16 +1898,16 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
1845 return err; 1898 return err;
1846 } 1899 }
1847 } else { 1900 } else {
1848 timeout = wait_event_interruptible_timeout 1901 timeout = wait_event_interruptible_timeout
1849 ( cam->wait_frame, 1902 ( cam->wait_frame,
1850 (!list_empty(&cam->outqueue)) || 1903 (!list_empty(&cam->outqueue)) ||
1851 (cam->state & DEV_DISCONNECTED) || 1904 (cam->state & DEV_DISCONNECTED) ||
1852 (cam->state & DEV_MISCONFIGURED), 1905 (cam->state & DEV_MISCONFIGURED),
1853 cam->module_param.frame_timeout * 1906 cam->module_param.frame_timeout *
1854 1000 * msecs_to_jiffies(1) ); 1907 1000 * msecs_to_jiffies(1) );
1855 if (timeout < 0) { 1908 if (timeout < 0) {
1856 mutex_unlock(&cam->fileop_mutex); 1909 mutex_unlock(&cam->fileop_mutex);
1857 return timeout; 1910 return timeout;
1858 } else if (timeout == 0 && 1911 } else if (timeout == 0 &&
1859 !(cam->state & DEV_DISCONNECTED)) { 1912 !(cam->state & DEV_DISCONNECTED)) {
1860 DBG(1, "Video frame timeout elapsed"); 1913 DBG(1, "Video frame timeout elapsed");
@@ -2001,7 +2054,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
2001 return -EIO; 2054 return -EIO;
2002 } 2055 }
2003 2056
2004 if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || 2057 if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
2058 mutex_unlock(&cam->fileop_mutex);
2059 return -EACCES;
2060 }
2061
2062 if (cam->io != IO_MMAP ||
2005 size != PAGE_ALIGN(cam->frame[0].buf.length)) { 2063 size != PAGE_ALIGN(cam->frame[0].buf.length)) {
2006 mutex_unlock(&cam->fileop_mutex); 2064 mutex_unlock(&cam->fileop_mutex);
2007 return -EINVAL; 2065 return -EINVAL;
@@ -2267,7 +2325,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
2267 if (cam->frame[i].vma_use_count) { 2325 if (cam->frame[i].vma_use_count) {
2268 DBG(3, "VIDIOC_S_CROP failed. " 2326 DBG(3, "VIDIOC_S_CROP failed. "
2269 "Unmap the buffers first."); 2327 "Unmap the buffers first.");
2270 return -EINVAL; 2328 return -EBUSY;
2271 } 2329 }
2272 2330
2273 /* Preserve R,G or B origin */ 2331 /* Preserve R,G or B origin */
@@ -2410,8 +2468,8 @@ sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
2410 case BRIDGE_SN9C101: 2468 case BRIDGE_SN9C101:
2411 case BRIDGE_SN9C102: 2469 case BRIDGE_SN9C102:
2412 case BRIDGE_SN9C103: 2470 case BRIDGE_SN9C103:
2413 strcpy(fmtd.description, "compressed"); 2471 strcpy(fmtd.description, "compressed");
2414 fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; 2472 fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
2415 break; 2473 break;
2416 case BRIDGE_SN9C105: 2474 case BRIDGE_SN9C105:
2417 case BRIDGE_SN9C120: 2475 case BRIDGE_SN9C120:
@@ -2445,8 +2503,10 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
2445 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 2503 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2446 return -EINVAL; 2504 return -EINVAL;
2447 2505
2448 pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X || 2506 pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
2449 pfmt->pixelformat==V4L2_PIX_FMT_JPEG) 2507 V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
2508 pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
2509 pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
2450 ? 0 : (pfmt->width * pfmt->priv) / 8; 2510 ? 0 : (pfmt->width * pfmt->priv) / 8;
2451 pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); 2511 pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
2452 pfmt->field = V4L2_FIELD_NONE; 2512 pfmt->field = V4L2_FIELD_NONE;
@@ -2521,9 +2581,9 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
2521 case BRIDGE_SN9C101: 2581 case BRIDGE_SN9C101:
2522 case BRIDGE_SN9C102: 2582 case BRIDGE_SN9C102:
2523 case BRIDGE_SN9C103: 2583 case BRIDGE_SN9C103:
2524 if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && 2584 if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
2525 pix->pixelformat != V4L2_PIX_FMT_SBGGR8) 2585 pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
2526 pix->pixelformat = pfmt->pixelformat; 2586 pix->pixelformat = pfmt->pixelformat;
2527 break; 2587 break;
2528 case BRIDGE_SN9C105: 2588 case BRIDGE_SN9C105:
2529 case BRIDGE_SN9C120: 2589 case BRIDGE_SN9C120:
@@ -2533,7 +2593,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
2533 break; 2593 break;
2534 } 2594 }
2535 pix->priv = pfmt->priv; /* bpp */ 2595 pix->priv = pfmt->priv; /* bpp */
2536 pix->colorspace = pfmt->colorspace; 2596 pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
2597 V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
2537 pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || 2598 pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
2538 pix->pixelformat == V4L2_PIX_FMT_JPEG) 2599 pix->pixelformat == V4L2_PIX_FMT_JPEG)
2539 ? 0 : (pix->width * pix->priv) / 8; 2600 ? 0 : (pix->width * pix->priv) / 8;
@@ -2551,7 +2612,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
2551 if (cam->frame[i].vma_use_count) { 2612 if (cam->frame[i].vma_use_count) {
2552 DBG(3, "VIDIOC_S_FMT failed. Unmap the " 2613 DBG(3, "VIDIOC_S_FMT failed. Unmap the "
2553 "buffers first."); 2614 "buffers first.");
2554 return -EINVAL; 2615 return -EBUSY;
2555 } 2616 }
2556 2617
2557 if (cam->stream == STREAM_ON) 2618 if (cam->stream == STREAM_ON)
@@ -2666,14 +2727,14 @@ sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
2666 if (cam->io == IO_READ) { 2727 if (cam->io == IO_READ) {
2667 DBG(3, "Close and open the device again to choose the mmap " 2728 DBG(3, "Close and open the device again to choose the mmap "
2668 "I/O method"); 2729 "I/O method");
2669 return -EINVAL; 2730 return -EBUSY;
2670 } 2731 }
2671 2732
2672 for (i = 0; i < cam->nbuffers; i++) 2733 for (i = 0; i < cam->nbuffers; i++)
2673 if (cam->frame[i].vma_use_count) { 2734 if (cam->frame[i].vma_use_count) {
2674 DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are " 2735 DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
2675 "still mapped."); 2736 "still mapped.");
2676 return -EINVAL; 2737 return -EBUSY;
2677 } 2738 }
2678 2739
2679 if (cam->stream == STREAM_ON) 2740 if (cam->stream == STREAM_ON)
@@ -2785,15 +2846,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
2785 if (err) 2846 if (err)
2786 return err; 2847 return err;
2787 } else { 2848 } else {
2788 timeout = wait_event_interruptible_timeout 2849 timeout = wait_event_interruptible_timeout
2789 ( cam->wait_frame, 2850 ( cam->wait_frame,
2790 (!list_empty(&cam->outqueue)) || 2851 (!list_empty(&cam->outqueue)) ||
2791 (cam->state & DEV_DISCONNECTED) || 2852 (cam->state & DEV_DISCONNECTED) ||
2792 (cam->state & DEV_MISCONFIGURED), 2853 (cam->state & DEV_MISCONFIGURED),
2793 cam->module_param.frame_timeout * 2854 cam->module_param.frame_timeout *
2794 1000 * msecs_to_jiffies(1) ); 2855 1000 * msecs_to_jiffies(1) );
2795 if (timeout < 0) 2856 if (timeout < 0)
2796 return timeout; 2857 return timeout;
2797 else if (timeout == 0 && 2858 else if (timeout == 0 &&
2798 !(cam->state & DEV_DISCONNECTED)) { 2859 !(cam->state & DEV_DISCONNECTED)) {
2799 DBG(1, "Video frame timeout elapsed"); 2860 DBG(1, "Video frame timeout elapsed");
@@ -2837,9 +2898,6 @@ sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
2837 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) 2898 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
2838 return -EINVAL; 2899 return -EINVAL;
2839 2900
2840 if (list_empty(&cam->inqueue))
2841 return -EINVAL;
2842
2843 cam->stream = STREAM_ON; 2901 cam->stream = STREAM_ON;
2844 2902
2845 DBG(3, "Stream on"); 2903 DBG(3, "Stream on");
@@ -3166,8 +3224,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3166 3224
3167 r = sn9c102_read_reg(cam, 0x00); 3225 r = sn9c102_read_reg(cam, 0x00);
3168 if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) { 3226 if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
3169 DBG(1, "Sorry, this is not a SN9C1xx based camera " 3227 DBG(1, "Sorry, this is not a SN9C1xx-based camera "
3170 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3228 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3171 err = -ENODEV; 3229 err = -ENODEV;
3172 goto fail; 3230 goto fail;
3173 } 3231 }
@@ -3177,19 +3235,19 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3177 case BRIDGE_SN9C101: 3235 case BRIDGE_SN9C101:
3178 case BRIDGE_SN9C102: 3236 case BRIDGE_SN9C102:
3179 DBG(2, "SN9C10[12] PC Camera Controller detected " 3237 DBG(2, "SN9C10[12] PC Camera Controller detected "
3180 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3238 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3181 break; 3239 break;
3182 case BRIDGE_SN9C103: 3240 case BRIDGE_SN9C103:
3183 DBG(2, "SN9C103 PC Camera Controller detected " 3241 DBG(2, "SN9C103 PC Camera Controller detected "
3184 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3242 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3185 break; 3243 break;
3186 case BRIDGE_SN9C105: 3244 case BRIDGE_SN9C105:
3187 DBG(2, "SN9C105 PC Camera Controller detected " 3245 DBG(2, "SN9C105 PC Camera Controller detected "
3188 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3246 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3189 break; 3247 break;
3190 case BRIDGE_SN9C120: 3248 case BRIDGE_SN9C120:
3191 DBG(2, "SN9C120 PC Camera Controller detected " 3249 DBG(2, "SN9C120 PC Camera Controller detected "
3192 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3250 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3193 break; 3251 break;
3194 } 3252 }
3195 3253
@@ -3260,6 +3318,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3260 "device controlling. Error #%d", err); 3318 "device controlling. Error #%d", err);
3261#else 3319#else
3262 DBG(2, "Optional device control through 'sysfs' interface disabled"); 3320 DBG(2, "Optional device control through 'sysfs' interface disabled");
3321 DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
3322 "configuration option to enable it.");
3263#endif 3323#endif
3264 3324
3265 usb_set_intfdata(intf, cam); 3325 usb_set_intfdata(intf, cam);
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
index 3a682eca6c65..f49bd8c5b86e 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[] = {
89 { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, 89 { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
90 { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, 90 { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
91 { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, 91 { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
92 { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), },
92 { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, 93 { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), },
93 { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, 94 { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), },
94 { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, 95 { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), },
95 { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, 96 { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), },
97 { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), },
96 { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, 98 { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), },
97 { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), }, 99 { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
98 { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), }, 100 { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
99 { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), }, 101 { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
100 /* SN9C120 */ 102 /* SN9C120 */
103 { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), },
104 { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), },
105 { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), },
101 { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, 106 { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
107 { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), },
102 { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, 108 { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
103 { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, 109 { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
104 { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, 110 { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
@@ -114,12 +120,15 @@ static const struct usb_device_id sn9c102_id_table[] = {
114 Functions must return 0 on success, the appropriate error otherwise. 120 Functions must return 0 on success, the appropriate error otherwise.
115*/ 121*/
116extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); 122extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
123extern int sn9c102_probe_hv7131r(struct sn9c102_device* cam);
117extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); 124extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
125extern int sn9c102_probe_mi0360(struct sn9c102_device* cam);
118extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); 126extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
119extern int sn9c102_probe_ov7660(struct sn9c102_device* cam); 127extern int sn9c102_probe_ov7660(struct sn9c102_device* cam);
120extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); 128extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
121extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); 129extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
122extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); 130extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
131extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam);
123extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); 132extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
124 133
125/* 134/*
@@ -128,13 +137,16 @@ extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
128 the order of the list below, from top to bottom. 137 the order of the list below, from top to bottom.
129*/ 138*/
130static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { 139static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
140 &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
141 &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
131 &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ 142 &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
143 &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
132 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ 144 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
133 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ 145 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
134 &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
135 &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ 146 &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
136 &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ 147 &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
137 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ 148 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
149 &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
138 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ 150 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
139 NULL, 151 NULL,
140}; 152};
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
index 7ae368f60d89..28a861aed044 100644
--- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
@@ -22,19 +22,13 @@
22#include "sn9c102_sensor.h" 22#include "sn9c102_sensor.h"
23 23
24 24
25static struct sn9c102_sensor hv7131d;
26
27
28static int hv7131d_init(struct sn9c102_device* cam) 25static int hv7131d_init(struct sn9c102_device* cam)
29{ 26{
30 int err = 0; 27 int err;
31 28
32 err += sn9c102_write_reg(cam, 0x00, 0x10); 29 err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
33 err += sn9c102_write_reg(cam, 0x00, 0x11); 30 {0x00, 0x14}, {0x60, 0x17},
34 err += sn9c102_write_reg(cam, 0x00, 0x14); 31 {0x0e, 0x18}, {0xf2, 0x19});
35 err += sn9c102_write_reg(cam, 0x60, 0x17);
36 err += sn9c102_write_reg(cam, 0x0e, 0x18);
37 err += sn9c102_write_reg(cam, 0xf2, 0x19);
38 32
39 err += sn9c102_i2c_write(cam, 0x01, 0x04); 33 err += sn9c102_i2c_write(cam, 0x01, 0x04);
40 err += sn9c102_i2c_write(cam, 0x02, 0x00); 34 err += sn9c102_i2c_write(cam, 0x02, 0x00);
@@ -153,7 +147,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam,
153static struct sn9c102_sensor hv7131d = { 147static struct sn9c102_sensor hv7131d = {
154 .name = "HV7131D", 148 .name = "HV7131D",
155 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 149 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
156 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 150 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
157 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 151 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
158 .frequency = SN9C102_I2C_100KHZ, 152 .frequency = SN9C102_I2C_100KHZ,
159 .interface = SN9C102_I2C_2WIRES, 153 .interface = SN9C102_I2C_2WIRES,
@@ -250,11 +244,10 @@ static struct sn9c102_sensor hv7131d = {
250 244
251int sn9c102_probe_hv7131d(struct sn9c102_device* cam) 245int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
252{ 246{
253 int r0 = 0, r1 = 0, err = 0; 247 int r0 = 0, r1 = 0, err;
254 248
255 err += sn9c102_write_reg(cam, 0x01, 0x01); 249 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
256 err += sn9c102_write_reg(cam, 0x00, 0x01); 250 {0x28, 0x17});
257 err += sn9c102_write_reg(cam, 0x28, 0x17);
258 if (err) 251 if (err)
259 return -EIO; 252 return -EIO;
260 253
@@ -263,7 +256,7 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
263 if (r0 < 0 || r1 < 0) 256 if (r0 < 0 || r1 < 0)
264 return -EIO; 257 return -EIO;
265 258
266 if (r0 != 0x00 && r1 != 0x04) 259 if (r0 != 0x00 || r1 != 0x04)
267 return -ENODEV; 260 return -ENODEV;
268 261
269 sn9c102_attach_sensor(cam, &hv7131d); 262 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 000000000000..5a495baa5f95
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131r.c
@@ -0,0 +1,366 @@
1/***************************************************************************
2 * Plug-in for HV7131R image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include "sn9c102_sensor.h"
23
24
25static int hv7131r_init(struct sn9c102_device* cam)
26{
27 int err = 0;
28
29 switch (sn9c102_get_bridge(cam)) {
30 case BRIDGE_SN9C103:
31 err = sn9c102_write_const_regs(cam, {0x00, 0x03}, {0x1a, 0x04},
32 {0x20, 0x05}, {0x20, 0x06},
33 {0x03, 0x10}, {0x00, 0x14},
34 {0x60, 0x17}, {0x0a, 0x18},
35 {0xf0, 0x19}, {0x1d, 0x1a},
36 {0x10, 0x1b}, {0x02, 0x1c},
37 {0x03, 0x1d}, {0x0f, 0x1e},
38 {0x0c, 0x1f}, {0x00, 0x20},
39 {0x10, 0x21}, {0x20, 0x22},
40 {0x30, 0x23}, {0x40, 0x24},
41 {0x50, 0x25}, {0x60, 0x26},
42 {0x70, 0x27}, {0x80, 0x28},
43 {0x90, 0x29}, {0xa0, 0x2a},
44 {0xb0, 0x2b}, {0xc0, 0x2c},
45 {0xd0, 0x2d}, {0xe0, 0x2e},
46 {0xf0, 0x2f}, {0xff, 0x30});
47
48 break;
49 case BRIDGE_SN9C105:
50 case BRIDGE_SN9C120:
51 err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
52 {0x00, 0x03}, {0x1a, 0x04},
53 {0x44, 0x05}, {0x3e, 0x06},
54 {0x1a, 0x07}, {0x03, 0x10},
55 {0x08, 0x14}, {0xa3, 0x17},
56 {0x4b, 0x18}, {0x00, 0x19},
57 {0x1d, 0x1a}, {0x10, 0x1b},
58 {0x02, 0x1c}, {0x03, 0x1d},
59 {0x0f, 0x1e}, {0x0c, 0x1f},
60 {0x00, 0x20}, {0x29, 0x21},
61 {0x40, 0x22}, {0x54, 0x23},
62 {0x66, 0x24}, {0x76, 0x25},
63 {0x85, 0x26}, {0x94, 0x27},
64 {0xa1, 0x28}, {0xae, 0x29},
65 {0xbb, 0x2a}, {0xc7, 0x2b},
66 {0xd3, 0x2c}, {0xde, 0x2d},
67 {0xea, 0x2e}, {0xf4, 0x2f},
68 {0xff, 0x30}, {0x00, 0x3F},
69 {0xC7, 0x40}, {0x01, 0x41},
70 {0x44, 0x42}, {0x00, 0x43},
71 {0x44, 0x44}, {0x00, 0x45},
72 {0x44, 0x46}, {0x00, 0x47},
73 {0xC7, 0x48}, {0x01, 0x49},
74 {0xC7, 0x4A}, {0x01, 0x4B},
75 {0xC7, 0x4C}, {0x01, 0x4D},
76 {0x44, 0x4E}, {0x00, 0x4F},
77 {0x44, 0x50}, {0x00, 0x51},
78 {0x44, 0x52}, {0x00, 0x53},
79 {0xC7, 0x54}, {0x01, 0x55},
80 {0xC7, 0x56}, {0x01, 0x57},
81 {0xC7, 0x58}, {0x01, 0x59},
82 {0x44, 0x5A}, {0x00, 0x5B},
83 {0x44, 0x5C}, {0x00, 0x5D},
84 {0x44, 0x5E}, {0x00, 0x5F},
85 {0xC7, 0x60}, {0x01, 0x61},
86 {0xC7, 0x62}, {0x01, 0x63},
87 {0xC7, 0x64}, {0x01, 0x65},
88 {0x44, 0x66}, {0x00, 0x67},
89 {0x44, 0x68}, {0x00, 0x69},
90 {0x44, 0x6A}, {0x00, 0x6B},
91 {0xC7, 0x6C}, {0x01, 0x6D},
92 {0xC7, 0x6E}, {0x01, 0x6F},
93 {0xC7, 0x70}, {0x01, 0x71},
94 {0x44, 0x72}, {0x00, 0x73},
95 {0x44, 0x74}, {0x00, 0x75},
96 {0x44, 0x76}, {0x00, 0x77},
97 {0xC7, 0x78}, {0x01, 0x79},
98 {0xC7, 0x7A}, {0x01, 0x7B},
99 {0xC7, 0x7C}, {0x01, 0x7D},
100 {0x44, 0x7E}, {0x00, 0x7F},
101 {0x14, 0x84}, {0x00, 0x85},
102 {0x27, 0x86}, {0x00, 0x87},
103 {0x07, 0x88}, {0x00, 0x89},
104 {0xEC, 0x8A}, {0x0f, 0x8B},
105 {0xD8, 0x8C}, {0x0f, 0x8D},
106 {0x3D, 0x8E}, {0x00, 0x8F},
107 {0x3D, 0x90}, {0x00, 0x91},
108 {0xCD, 0x92}, {0x0f, 0x93},
109 {0xf7, 0x94}, {0x0f, 0x95},
110 {0x0C, 0x96}, {0x00, 0x97},
111 {0x00, 0x98}, {0x66, 0x99},
112 {0x05, 0x9A}, {0x00, 0x9B},
113 {0x04, 0x9C}, {0x00, 0x9D},
114 {0x08, 0x9E}, {0x00, 0x9F},
115 {0x2D, 0xC0}, {0x2D, 0xC1},
116 {0x3A, 0xC2}, {0x05, 0xC3},
117 {0x04, 0xC4}, {0x3F, 0xC5},
118 {0x00, 0xC6}, {0x00, 0xC7},
119 {0x50, 0xC8}, {0x3C, 0xC9},
120 {0x28, 0xCA}, {0xD8, 0xCB},
121 {0x14, 0xCC}, {0xEC, 0xCD},
122 {0x32, 0xCE}, {0xDD, 0xCF},
123 {0x32, 0xD0}, {0xDD, 0xD1},
124 {0x6A, 0xD2}, {0x50, 0xD3},
125 {0x00, 0xD4}, {0x00, 0xD5},
126 {0x00, 0xD6});
127 break;
128 default:
129 break;
130 }
131
132 err += sn9c102_i2c_write(cam, 0x20, 0x00);
133 err += sn9c102_i2c_write(cam, 0x21, 0xd6);
134 err += sn9c102_i2c_write(cam, 0x25, 0x06);
135
136 return err;
137}
138
139
140static int hv7131r_get_ctrl(struct sn9c102_device* cam,
141 struct v4l2_control* ctrl)
142{
143 switch (ctrl->id) {
144 case V4L2_CID_GAIN:
145 if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
146 return -EIO;
147 return 0;
148 case V4L2_CID_RED_BALANCE:
149 if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
150 return -EIO;
151 ctrl->value = ctrl->value & 0x3f;
152 return 0;
153 case V4L2_CID_BLUE_BALANCE:
154 if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
155 return -EIO;
156 ctrl->value = ctrl->value & 0x3f;
157 return 0;
158 case SN9C102_V4L2_CID_GREEN_BALANCE:
159 if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
160 return -EIO;
161 ctrl->value = ctrl->value & 0x3f;
162 return 0;
163 case V4L2_CID_BLACK_LEVEL:
164 if ((ctrl->value = sn9c102_i2c_read(cam, 0x01)) < 0)
165 return -EIO;
166 ctrl->value = (ctrl->value & 0x08) ? 1 : 0;
167 return 0;
168 default:
169 return -EINVAL;
170 }
171}
172
173
174static int hv7131r_set_ctrl(struct sn9c102_device* cam,
175 const struct v4l2_control* ctrl)
176{
177 int err = 0;
178
179 switch (ctrl->id) {
180 case V4L2_CID_GAIN:
181 err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
182 break;
183 case V4L2_CID_RED_BALANCE:
184 err += sn9c102_i2c_write(cam, 0x31, ctrl->value);
185 break;
186 case V4L2_CID_BLUE_BALANCE:
187 err += sn9c102_i2c_write(cam, 0x33, ctrl->value);
188 break;
189 case SN9C102_V4L2_CID_GREEN_BALANCE:
190 err += sn9c102_i2c_write(cam, 0x32, ctrl->value);
191 break;
192 case V4L2_CID_BLACK_LEVEL:
193 {
194 int r = sn9c102_i2c_read(cam, 0x01);
195 if (r < 0)
196 return -EIO;
197 err += sn9c102_i2c_write(cam, 0x01,
198 (ctrl->value<<3) | (r&0xf7));
199 }
200 break;
201 default:
202 return -EINVAL;
203 }
204
205 return err ? -EIO : 0;
206}
207
208
209static int hv7131r_set_crop(struct sn9c102_device* cam,
210 const struct v4l2_rect* rect)
211{
212 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
213 int err = 0;
214 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
215 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
216
217 err += sn9c102_write_reg(cam, h_start, 0x12);
218 err += sn9c102_write_reg(cam, v_start, 0x13);
219
220 return err;
221}
222
223
224static int hv7131r_set_pix_format(struct sn9c102_device* cam,
225 const struct v4l2_pix_format* pix)
226{
227 int err = 0;
228
229 switch (sn9c102_get_bridge(cam)) {
230 case BRIDGE_SN9C103:
231 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
232 err += sn9c102_write_reg(cam, 0xa0, 0x19);
233 err += sn9c102_i2c_write(cam, 0x01, 0x04);
234 } else {
235 err += sn9c102_write_reg(cam, 0x30, 0x19);
236 err += sn9c102_i2c_write(cam, 0x01, 0x04);
237 }
238 break;
239 case BRIDGE_SN9C105:
240 case BRIDGE_SN9C120:
241 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
242 err += sn9c102_write_reg(cam, 0xa5, 0x17);
243 err += sn9c102_i2c_write(cam, 0x01, 0x24);
244 } else {
245 err += sn9c102_write_reg(cam, 0xa3, 0x17);
246 err += sn9c102_i2c_write(cam, 0x01, 0x04);
247 }
248 break;
249 default:
250 break;
251 }
252
253 return err;
254}
255
256
257static struct sn9c102_sensor hv7131r = {
258 .name = "HV7131R",
259 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
260 .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
261 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
262 .frequency = SN9C102_I2C_100KHZ,
263 .interface = SN9C102_I2C_2WIRES,
264 .i2c_slave_id = 0x11,
265 .init = &hv7131r_init,
266 .qctrl = {
267 {
268 .id = V4L2_CID_GAIN,
269 .type = V4L2_CTRL_TYPE_INTEGER,
270 .name = "global gain",
271 .minimum = 0x00,
272 .maximum = 0xff,
273 .step = 0x01,
274 .default_value = 0x40,
275 .flags = 0,
276 },
277 {
278 .id = V4L2_CID_RED_BALANCE,
279 .type = V4L2_CTRL_TYPE_INTEGER,
280 .name = "red balance",
281 .minimum = 0x00,
282 .maximum = 0x3f,
283 .step = 0x01,
284 .default_value = 0x08,
285 .flags = 0,
286 },
287 {
288 .id = V4L2_CID_BLUE_BALANCE,
289 .type = V4L2_CTRL_TYPE_INTEGER,
290 .name = "blue balance",
291 .minimum = 0x00,
292 .maximum = 0x3f,
293 .step = 0x01,
294 .default_value = 0x1a,
295 .flags = 0,
296 },
297 {
298 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
299 .type = V4L2_CTRL_TYPE_INTEGER,
300 .name = "green balance",
301 .minimum = 0x00,
302 .maximum = 0x3f,
303 .step = 0x01,
304 .default_value = 0x2f,
305 .flags = 0,
306 },
307 {
308 .id = V4L2_CID_BLACK_LEVEL,
309 .type = V4L2_CTRL_TYPE_BOOLEAN,
310 .name = "auto black level compensation",
311 .minimum = 0x00,
312 .maximum = 0x01,
313 .step = 0x01,
314 .default_value = 0x00,
315 .flags = 0,
316 },
317 },
318 .get_ctrl = &hv7131r_get_ctrl,
319 .set_ctrl = &hv7131r_set_ctrl,
320 .cropcap = {
321 .bounds = {
322 .left = 0,
323 .top = 0,
324 .width = 640,
325 .height = 480,
326 },
327 .defrect = {
328 .left = 0,
329 .top = 0,
330 .width = 640,
331 .height = 480,
332 },
333 },
334 .set_crop = &hv7131r_set_crop,
335 .pix_format = {
336 .width = 640,
337 .height = 480,
338 .pixelformat = V4L2_PIX_FMT_SBGGR8,
339 .priv = 8,
340 },
341 .set_pix_format = &hv7131r_set_pix_format
342};
343
344
345int sn9c102_probe_hv7131r(struct sn9c102_device* cam)
346{
347 int devid, err;
348
349 err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x02},
350 {0x34, 0x01}, {0x20, 0x17},
351 {0x34, 0x01}, {0x46, 0x01});
352
353 if (err)
354 return -EIO;
355
356 devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
357 if (devid < 0)
358 return -EIO;
359
360 if (devid != 0x02)
361 return -ENODEV;
362
363 sn9c102_attach_sensor(cam, &hv7131r);
364
365 return 0;
366}
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c
index a33d1bc10f90..9200845d011b 100644
--- a/drivers/media/video/sn9c102/sn9c102_mi0343.c
+++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c
@@ -22,36 +22,30 @@
22#include "sn9c102_sensor.h" 22#include "sn9c102_sensor.h"
23 23
24 24
25static struct sn9c102_sensor mi0343;
26static u8 mi0343_i2c_data[5+1];
27
28
29static int mi0343_init(struct sn9c102_device* cam) 25static int mi0343_init(struct sn9c102_device* cam)
30{ 26{
27 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
31 int err = 0; 28 int err = 0;
32 29
33 err += sn9c102_write_reg(cam, 0x00, 0x10); 30 err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
34 err += sn9c102_write_reg(cam, 0x00, 0x11); 31 {0x0a, 0x14}, {0x40, 0x01},
35 err += sn9c102_write_reg(cam, 0x0a, 0x14); 32 {0x20, 0x17}, {0x07, 0x18},
36 err += sn9c102_write_reg(cam, 0x40, 0x01); 33 {0xa0, 0x19});
37 err += sn9c102_write_reg(cam, 0x20, 0x17); 34
38 err += sn9c102_write_reg(cam, 0x07, 0x18); 35 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
39 err += sn9c102_write_reg(cam, 0xa0, 0x19); 36 0x00, 0x01, 0, 0);
40 37 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
41 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 38 0x00, 0x00, 0, 0);
42 0x0d, 0x00, 0x01, 0, 0); 39 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
43 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 40 0x01, 0xe1, 0, 0);
44 0x0d, 0x00, 0x00, 0, 0); 41 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
45 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 42 0x02, 0x81, 0, 0);
46 0x03, 0x01, 0xe1, 0, 0); 43 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
47 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 44 0x00, 0x17, 0, 0);
48 0x04, 0x02, 0x81, 0, 0); 45 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
49 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 46 0x00, 0x11, 0, 0);
50 0x05, 0x00, 0x17, 0, 0); 47 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
51 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 48 0x04, 0x9a, 0, 0);
52 0x06, 0x00, 0x11, 0, 0);
53 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
54 0x62, 0x04, 0x9a, 0, 0);
55 49
56 return err; 50 return err;
57} 51}
@@ -60,43 +54,46 @@ static int mi0343_init(struct sn9c102_device* cam)
60static int mi0343_get_ctrl(struct sn9c102_device* cam, 54static int mi0343_get_ctrl(struct sn9c102_device* cam,
61 struct v4l2_control* ctrl) 55 struct v4l2_control* ctrl)
62{ 56{
57 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
58 u8 data[5+1];
59
63 switch (ctrl->id) { 60 switch (ctrl->id) {
64 case V4L2_CID_EXPOSURE: 61 case V4L2_CID_EXPOSURE:
65 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 62 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
66 0x09, 2+1, mi0343_i2c_data) < 0) 63 2+1, data) < 0)
67 return -EIO; 64 return -EIO;
68 ctrl->value = mi0343_i2c_data[2]; 65 ctrl->value = data[2];
69 return 0; 66 return 0;
70 case V4L2_CID_GAIN: 67 case V4L2_CID_GAIN:
71 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 68 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
72 0x35, 2+1, mi0343_i2c_data) < 0) 69 2+1, data) < 0)
73 return -EIO; 70 return -EIO;
74 break; 71 break;
75 case V4L2_CID_HFLIP: 72 case V4L2_CID_HFLIP:
76 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 73 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
77 0x20, 2+1, mi0343_i2c_data) < 0) 74 2+1, data) < 0)
78 return -EIO; 75 return -EIO;
79 ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0; 76 ctrl->value = data[3] & 0x20 ? 1 : 0;
80 return 0; 77 return 0;
81 case V4L2_CID_VFLIP: 78 case V4L2_CID_VFLIP:
82 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 79 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
83 0x20, 2+1, mi0343_i2c_data) < 0) 80 2+1, data) < 0)
84 return -EIO; 81 return -EIO;
85 ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0; 82 ctrl->value = data[3] & 0x80 ? 1 : 0;
86 return 0; 83 return 0;
87 case V4L2_CID_RED_BALANCE: 84 case V4L2_CID_RED_BALANCE:
88 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 85 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
89 0x2d, 2+1, mi0343_i2c_data) < 0) 86 2+1, data) < 0)
90 return -EIO; 87 return -EIO;
91 break; 88 break;
92 case V4L2_CID_BLUE_BALANCE: 89 case V4L2_CID_BLUE_BALANCE:
93 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 90 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
94 0x2c, 2+1, mi0343_i2c_data) < 0) 91 2+1, data) < 0)
95 return -EIO; 92 return -EIO;
96 break; 93 break;
97 case SN9C102_V4L2_CID_GREEN_BALANCE: 94 case SN9C102_V4L2_CID_GREEN_BALANCE:
98 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 95 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
99 0x2e, 2+1, mi0343_i2c_data) < 0) 96 2+1, data) < 0)
100 return -EIO; 97 return -EIO;
101 break; 98 break;
102 default: 99 default:
@@ -108,7 +105,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
108 case V4L2_CID_RED_BALANCE: 105 case V4L2_CID_RED_BALANCE:
109 case V4L2_CID_BLUE_BALANCE: 106 case V4L2_CID_BLUE_BALANCE:
110 case SN9C102_V4L2_CID_GREEN_BALANCE: 107 case SN9C102_V4L2_CID_GREEN_BALANCE:
111 ctrl->value = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8); 108 ctrl->value = data[3] | (data[2] << 8);
112 if (ctrl->value >= 0x10 && ctrl->value <= 0x3f) 109 if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
113 ctrl->value -= 0x10; 110 ctrl->value -= 0x10;
114 else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f) 111 else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
@@ -124,6 +121,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
124static int mi0343_set_ctrl(struct sn9c102_device* cam, 121static int mi0343_set_ctrl(struct sn9c102_device* cam,
125 const struct v4l2_control* ctrl) 122 const struct v4l2_control* ctrl)
126{ 123{
124 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
127 u16 reg = 0; 125 u16 reg = 0;
128 int err = 0; 126 int err = 0;
129 127
@@ -143,50 +141,42 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam,
143 141
144 switch (ctrl->id) { 142 switch (ctrl->id) {
145 case V4L2_CID_EXPOSURE: 143 case V4L2_CID_EXPOSURE:
146 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 144 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
147 mi0343.i2c_slave_id,
148 0x09, ctrl->value, 0x00, 145 0x09, ctrl->value, 0x00,
149 0, 0); 146 0, 0);
150 break; 147 break;
151 case V4L2_CID_GAIN: 148 case V4L2_CID_GAIN:
152 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 149 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
153 mi0343.i2c_slave_id,
154 0x35, reg >> 8, reg & 0xff, 150 0x35, reg >> 8, reg & 0xff,
155 0, 0); 151 0, 0);
156 break; 152 break;
157 case V4L2_CID_HFLIP: 153 case V4L2_CID_HFLIP:
158 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 154 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
159 mi0343.i2c_slave_id,
160 0x20, ctrl->value ? 0x40:0x00, 155 0x20, ctrl->value ? 0x40:0x00,
161 ctrl->value ? 0x20:0x00, 156 ctrl->value ? 0x20:0x00,
162 0, 0); 157 0, 0);
163 break; 158 break;
164 case V4L2_CID_VFLIP: 159 case V4L2_CID_VFLIP:
165 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 160 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
166 mi0343.i2c_slave_id,
167 0x20, ctrl->value ? 0x80:0x00, 161 0x20, ctrl->value ? 0x80:0x00,
168 ctrl->value ? 0x80:0x00, 162 ctrl->value ? 0x80:0x00,
169 0, 0); 163 0, 0);
170 break; 164 break;
171 case V4L2_CID_RED_BALANCE: 165 case V4L2_CID_RED_BALANCE:
172 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 166 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
173 mi0343.i2c_slave_id,
174 0x2d, reg >> 8, reg & 0xff, 167 0x2d, reg >> 8, reg & 0xff,
175 0, 0); 168 0, 0);
176 break; 169 break;
177 case V4L2_CID_BLUE_BALANCE: 170 case V4L2_CID_BLUE_BALANCE:
178 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 171 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
179 mi0343.i2c_slave_id,
180 0x2c, reg >> 8, reg & 0xff, 172 0x2c, reg >> 8, reg & 0xff,
181 0, 0); 173 0, 0);
182 break; 174 break;
183 case SN9C102_V4L2_CID_GREEN_BALANCE: 175 case SN9C102_V4L2_CID_GREEN_BALANCE:
184 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 176 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
185 mi0343.i2c_slave_id,
186 0x2b, reg >> 8, reg & 0xff, 177 0x2b, reg >> 8, reg & 0xff,
187 0, 0); 178 0, 0);
188 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 179 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
189 mi0343.i2c_slave_id,
190 0x2e, reg >> 8, reg & 0xff, 180 0x2e, reg >> 8, reg & 0xff,
191 0, 0); 181 0, 0);
192 break; 182 break;
@@ -216,16 +206,15 @@ static int mi0343_set_crop(struct sn9c102_device* cam,
216static int mi0343_set_pix_format(struct sn9c102_device* cam, 206static int mi0343_set_pix_format(struct sn9c102_device* cam,
217 const struct v4l2_pix_format* pix) 207 const struct v4l2_pix_format* pix)
218{ 208{
209 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
219 int err = 0; 210 int err = 0;
220 211
221 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { 212 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
222 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 213 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
223 mi0343.i2c_slave_id,
224 0x0a, 0x00, 0x03, 0, 0); 214 0x0a, 0x00, 0x03, 0, 0);
225 err += sn9c102_write_reg(cam, 0x20, 0x19); 215 err += sn9c102_write_reg(cam, 0x20, 0x19);
226 } else { 216 } else {
227 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 217 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
228 mi0343.i2c_slave_id,
229 0x0a, 0x00, 0x05, 0, 0); 218 0x0a, 0x00, 0x05, 0, 0);
230 err += sn9c102_write_reg(cam, 0xa0, 0x19); 219 err += sn9c102_write_reg(cam, 0xa0, 0x19);
231 } 220 }
@@ -237,7 +226,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam,
237static struct sn9c102_sensor mi0343 = { 226static struct sn9c102_sensor mi0343 = {
238 .name = "MI-0343", 227 .name = "MI-0343",
239 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 228 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
240 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 229 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
241 .frequency = SN9C102_I2C_100KHZ, 230 .frequency = SN9C102_I2C_100KHZ,
242 .interface = SN9C102_I2C_2WIRES, 231 .interface = SN9C102_I2C_2WIRES,
243 .i2c_slave_id = 0x5d, 232 .i2c_slave_id = 0x5d,
@@ -343,19 +332,20 @@ static struct sn9c102_sensor mi0343 = {
343 332
344int sn9c102_probe_mi0343(struct sn9c102_device* cam) 333int sn9c102_probe_mi0343(struct sn9c102_device* cam)
345{ 334{
335 u8 data[5+1];
346 int err = 0; 336 int err = 0;
347 337
348 err += sn9c102_write_reg(cam, 0x01, 0x01); 338 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
349 err += sn9c102_write_reg(cam, 0x00, 0x01); 339 {0x28, 0x17});
350 err += sn9c102_write_reg(cam, 0x28, 0x17); 340
351 if (err) 341 if (err)
352 return -EIO; 342 return -EIO;
353 343
354 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, 344 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
355 2, mi0343_i2c_data) < 0) 345 2, data) < 0)
356 return -EIO; 346 return -EIO;
357 347
358 if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3) 348 if (data[4] != 0x32 || data[3] != 0xe3)
359 return -ENODEV; 349 return -ENODEV;
360 350
361 sn9c102_attach_sensor(cam, &mi0343); 351 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 000000000000..64698acb0b15
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_mi0360.c
@@ -0,0 +1,338 @@
1/***************************************************************************
2 * Plug-in for MI-0360 image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include "sn9c102_sensor.h"
23
24
25static int mi0360_init(struct sn9c102_device* cam)
26{
27 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
28 int err = 0;
29
30 err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
31 {0x0a, 0x14}, {0x40, 0x01},
32 {0x20, 0x17}, {0x07, 0x18},
33 {0xa0, 0x19}, {0x02, 0x1c},
34 {0x03, 0x1d}, {0x0f, 0x1e},
35 {0x0c, 0x1f}, {0x00, 0x20},
36 {0x10, 0x21}, {0x20, 0x22},
37 {0x30, 0x23}, {0x40, 0x24},
38 {0x50, 0x25}, {0x60, 0x26},
39 {0x70, 0x27}, {0x80, 0x28},
40 {0x90, 0x29}, {0xa0, 0x2a},
41 {0xb0, 0x2b}, {0xc0, 0x2c},
42 {0xd0, 0x2d}, {0xe0, 0x2e},
43 {0xf0, 0x2f}, {0xff, 0x30});
44
45 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
46 0x00, 0x01, 0, 0);
47 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
48 0x00, 0x00, 0, 0);
49 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
50 0x01, 0xe1, 0, 0);
51 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
52 0x02, 0x81, 0, 0);
53 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
54 0x00, 0x17, 0, 0);
55 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
56 0x00, 0x11, 0, 0);
57 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
58 0x04, 0x9a, 0, 0);
59
60 return err;
61}
62
63
64static int mi0360_get_ctrl(struct sn9c102_device* cam,
65 struct v4l2_control* ctrl)
66{
67 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
68 u8 data[5+1];
69
70 switch (ctrl->id) {
71 case V4L2_CID_EXPOSURE:
72 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
73 2+1, data) < 0)
74 return -EIO;
75 ctrl->value = data[2];
76 return 0;
77 case V4L2_CID_GAIN:
78 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
79 2+1, data) < 0)
80 return -EIO;
81 ctrl->value = data[3];
82 return 0;
83 case V4L2_CID_RED_BALANCE:
84 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
85 2+1, data) < 0)
86 return -EIO;
87 ctrl->value = data[3];
88 return 0;
89 case V4L2_CID_BLUE_BALANCE:
90 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
91 2+1, data) < 0)
92 return -EIO;
93 ctrl->value = data[3];
94 return 0;
95 case SN9C102_V4L2_CID_GREEN_BALANCE:
96 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
97 2+1, data) < 0)
98 return -EIO;
99 ctrl->value = data[3];
100 return 0;
101 case V4L2_CID_HFLIP:
102 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
103 2+1, data) < 0)
104 return -EIO;
105 ctrl->value = data[3] & 0x20 ? 1 : 0;
106 return 0;
107 case V4L2_CID_VFLIP:
108 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
109 2+1, data) < 0)
110 return -EIO;
111 ctrl->value = data[3] & 0x80 ? 1 : 0;
112 return 0;
113 default:
114 return -EINVAL;
115 }
116
117 return 0;
118}
119
120
121static int mi0360_set_ctrl(struct sn9c102_device* cam,
122 const struct v4l2_control* ctrl)
123{
124 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
125 int err = 0;
126
127 switch (ctrl->id) {
128 case V4L2_CID_EXPOSURE:
129 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
130 0x09, ctrl->value, 0x00,
131 0, 0);
132 break;
133 case V4L2_CID_GAIN:
134 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
135 0x35, 0x03, ctrl->value,
136 0, 0);
137 break;
138 case V4L2_CID_RED_BALANCE:
139 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
140 0x2c, 0x03, ctrl->value,
141 0, 0);
142 break;
143 case V4L2_CID_BLUE_BALANCE:
144 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
145 0x2d, 0x03, ctrl->value,
146 0, 0);
147 break;
148 case SN9C102_V4L2_CID_GREEN_BALANCE:
149 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
150 0x2b, 0x03, ctrl->value,
151 0, 0);
152 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
153 0x2e, 0x03, ctrl->value,
154 0, 0);
155 break;
156 case V4L2_CID_HFLIP:
157 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
158 0x20, ctrl->value ? 0x40:0x00,
159 ctrl->value ? 0x20:0x00,
160 0, 0);
161 break;
162 case V4L2_CID_VFLIP:
163 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
164 0x20, ctrl->value ? 0x80:0x00,
165 ctrl->value ? 0x80:0x00,
166 0, 0);
167 break;
168 default:
169 return -EINVAL;
170 }
171
172 return err ? -EIO : 0;
173}
174
175
176static int mi0360_set_crop(struct sn9c102_device* cam,
177 const struct v4l2_rect* rect)
178{
179 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
180 int err = 0;
181 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
182 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
183
184 err += sn9c102_write_reg(cam, h_start, 0x12);
185 err += sn9c102_write_reg(cam, v_start, 0x13);
186
187 return err;
188}
189
190
191static int mi0360_set_pix_format(struct sn9c102_device* cam,
192 const struct v4l2_pix_format* pix)
193{
194 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
195 int err = 0;
196
197 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
198 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
199 0x0a, 0x00, 0x02, 0, 0);
200 err += sn9c102_write_reg(cam, 0x20, 0x19);
201 } else {
202 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
203 0x0a, 0x00, 0x05, 0, 0);
204 err += sn9c102_write_reg(cam, 0x60, 0x19);
205 }
206
207 return err;
208}
209
210
211static struct sn9c102_sensor mi0360 = {
212 .name = "MI-0360",
213 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
214 .supported_bridge = BRIDGE_SN9C103,
215 .frequency = SN9C102_I2C_100KHZ,
216 .interface = SN9C102_I2C_2WIRES,
217 .i2c_slave_id = 0x5d,
218 .init = &mi0360_init,
219 .qctrl = {
220 {
221 .id = V4L2_CID_EXPOSURE,
222 .type = V4L2_CTRL_TYPE_INTEGER,
223 .name = "exposure",
224 .minimum = 0x00,
225 .maximum = 0x0f,
226 .step = 0x01,
227 .default_value = 0x05,
228 .flags = 0,
229 },
230 {
231 .id = V4L2_CID_GAIN,
232 .type = V4L2_CTRL_TYPE_INTEGER,
233 .name = "global gain",
234 .minimum = 0x00,
235 .maximum = 0x7f,
236 .step = 0x01,
237 .default_value = 0x25,
238 .flags = 0,
239 },
240 {
241 .id = V4L2_CID_HFLIP,
242 .type = V4L2_CTRL_TYPE_BOOLEAN,
243 .name = "horizontal mirror",
244 .minimum = 0,
245 .maximum = 1,
246 .step = 1,
247 .default_value = 0,
248 .flags = 0,
249 },
250 {
251 .id = V4L2_CID_VFLIP,
252 .type = V4L2_CTRL_TYPE_BOOLEAN,
253 .name = "vertical mirror",
254 .minimum = 0,
255 .maximum = 1,
256 .step = 1,
257 .default_value = 0,
258 .flags = 0,
259 },
260 {
261 .id = V4L2_CID_BLUE_BALANCE,
262 .type = V4L2_CTRL_TYPE_INTEGER,
263 .name = "blue balance",
264 .minimum = 0x00,
265 .maximum = 0x7f,
266 .step = 0x01,
267 .default_value = 0x0f,
268 .flags = 0,
269 },
270 {
271 .id = V4L2_CID_RED_BALANCE,
272 .type = V4L2_CTRL_TYPE_INTEGER,
273 .name = "red balance",
274 .minimum = 0x00,
275 .maximum = 0x7f,
276 .step = 0x01,
277 .default_value = 0x32,
278 .flags = 0,
279 },
280 {
281 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
282 .type = V4L2_CTRL_TYPE_INTEGER,
283 .name = "green balance",
284 .minimum = 0x00,
285 .maximum = 0x7f,
286 .step = 0x01,
287 .default_value = 0x25,
288 .flags = 0,
289 },
290 },
291 .get_ctrl = &mi0360_get_ctrl,
292 .set_ctrl = &mi0360_set_ctrl,
293 .cropcap = {
294 .bounds = {
295 .left = 0,
296 .top = 0,
297 .width = 640,
298 .height = 480,
299 },
300 .defrect = {
301 .left = 0,
302 .top = 0,
303 .width = 640,
304 .height = 480,
305 },
306 },
307 .set_crop = &mi0360_set_crop,
308 .pix_format = {
309 .width = 640,
310 .height = 480,
311 .pixelformat = V4L2_PIX_FMT_SBGGR8,
312 .priv = 8,
313 },
314 .set_pix_format = &mi0360_set_pix_format
315};
316
317
318int sn9c102_probe_mi0360(struct sn9c102_device* cam)
319{
320 u8 data[5+1];
321 int err;
322
323 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
324 {0x28, 0x17});
325 if (err)
326 return -EIO;
327
328 if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
329 2+1, data) < 0)
330 return -EIO;
331
332 if (data[2] != 0x82 || data[3] != 0x43)
333 return -ENODEV;
334
335 sn9c102_attach_sensor(cam, &mi0360);
336
337 return 0;
338}
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
index 7df09ff38e63..31b6080b0615 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7630.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c
@@ -22,9 +22,6 @@
22#include "sn9c102_sensor.h" 22#include "sn9c102_sensor.h"
23 23
24 24
25static struct sn9c102_sensor ov7630;
26
27
28static int ov7630_init(struct sn9c102_device* cam) 25static int ov7630_init(struct sn9c102_device* cam)
29{ 26{
30 int err = 0; 27 int err = 0;
@@ -32,21 +29,20 @@ static int ov7630_init(struct sn9c102_device* cam)
32 switch (sn9c102_get_bridge(cam)) { 29 switch (sn9c102_get_bridge(cam)) {
33 case BRIDGE_SN9C101: 30 case BRIDGE_SN9C101:
34 case BRIDGE_SN9C102: 31 case BRIDGE_SN9C102:
35 err += sn9c102_write_reg(cam, 0x00, 0x14); 32 err = sn9c102_write_const_regs(cam, {0x00, 0x14},
36 err += sn9c102_write_reg(cam, 0x60, 0x17); 33 {0x60, 0x17}, {0x0f, 0x18},
37 err += sn9c102_write_reg(cam, 0x0f, 0x18); 34 {0x50, 0x19});
38 err += sn9c102_write_reg(cam, 0x50, 0x19);
39 35
40 err += sn9c102_i2c_write(cam, 0x12, 0x8d); 36 err += sn9c102_i2c_write(cam, 0x12, 0x8d);
41 err += sn9c102_i2c_write(cam, 0x12, 0x0d); 37 err += sn9c102_i2c_write(cam, 0x12, 0x0d);
42 err += sn9c102_i2c_write(cam, 0x11, 0x00); 38 err += sn9c102_i2c_write(cam, 0x11, 0x00);
43 err += sn9c102_i2c_write(cam, 0x15, 0x34); 39 err += sn9c102_i2c_write(cam, 0x15, 0x35);
44 err += sn9c102_i2c_write(cam, 0x16, 0x03); 40 err += sn9c102_i2c_write(cam, 0x16, 0x03);
45 err += sn9c102_i2c_write(cam, 0x17, 0x1c); 41 err += sn9c102_i2c_write(cam, 0x17, 0x1c);
46 err += sn9c102_i2c_write(cam, 0x18, 0xbd); 42 err += sn9c102_i2c_write(cam, 0x18, 0xbd);
47 err += sn9c102_i2c_write(cam, 0x19, 0x06); 43 err += sn9c102_i2c_write(cam, 0x19, 0x06);
48 err += sn9c102_i2c_write(cam, 0x1a, 0xf6); 44 err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
49 err += sn9c102_i2c_write(cam, 0x1b, 0x04); 45 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
50 err += sn9c102_i2c_write(cam, 0x20, 0x44); 46 err += sn9c102_i2c_write(cam, 0x20, 0x44);
51 err += sn9c102_i2c_write(cam, 0x23, 0xee); 47 err += sn9c102_i2c_write(cam, 0x23, 0xee);
52 err += sn9c102_i2c_write(cam, 0x26, 0xa0); 48 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
@@ -65,42 +61,26 @@ static int ov7630_init(struct sn9c102_device* cam)
65 err += sn9c102_i2c_write(cam, 0x71, 0x00); 61 err += sn9c102_i2c_write(cam, 0x71, 0x00);
66 err += sn9c102_i2c_write(cam, 0x74, 0x21); 62 err += sn9c102_i2c_write(cam, 0x74, 0x21);
67 err += sn9c102_i2c_write(cam, 0x7d, 0xf7); 63 err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
64
68 break; 65 break;
69 case BRIDGE_SN9C103: 66 case BRIDGE_SN9C103:
70 err += sn9c102_write_reg(cam, 0x00, 0x02); 67 err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
71 err += sn9c102_write_reg(cam, 0x00, 0x03); 68 {0x1a, 0x04}, {0x20, 0x05},
72 err += sn9c102_write_reg(cam, 0x1a, 0x04); 69 {0x20, 0x06}, {0x20, 0x07},
73 err += sn9c102_write_reg(cam, 0x20, 0x05); 70 {0x03, 0x10}, {0x0a, 0x14},
74 err += sn9c102_write_reg(cam, 0x20, 0x06); 71 {0x60, 0x17}, {0x0f, 0x18},
75 err += sn9c102_write_reg(cam, 0x20, 0x07); 72 {0x50, 0x19}, {0x1d, 0x1a},
76 err += sn9c102_write_reg(cam, 0x03, 0x10); 73 {0x10, 0x1b}, {0x02, 0x1c},
77 err += sn9c102_write_reg(cam, 0x0a, 0x14); 74 {0x03, 0x1d}, {0x0f, 0x1e},
78 err += sn9c102_write_reg(cam, 0x60, 0x17); 75 {0x0c, 0x1f}, {0x00, 0x20},
79 err += sn9c102_write_reg(cam, 0x0f, 0x18); 76 {0x10, 0x21}, {0x20, 0x22},
80 err += sn9c102_write_reg(cam, 0x50, 0x19); 77 {0x30, 0x23}, {0x40, 0x24},
81 err += sn9c102_write_reg(cam, 0x1d, 0x1a); 78 {0x50, 0x25}, {0x60, 0x26},
82 err += sn9c102_write_reg(cam, 0x10, 0x1b); 79 {0x70, 0x27}, {0x80, 0x28},
83 err += sn9c102_write_reg(cam, 0x02, 0x1c); 80 {0x90, 0x29}, {0xa0, 0x2a},
84 err += sn9c102_write_reg(cam, 0x03, 0x1d); 81 {0xb0, 0x2b}, {0xc0, 0x2c},
85 err += sn9c102_write_reg(cam, 0x0f, 0x1e); 82 {0xd0, 0x2d}, {0xe0, 0x2e},
86 err += sn9c102_write_reg(cam, 0x0c, 0x1f); 83 {0xf0, 0x2f}, {0xff, 0x30});
87 err += sn9c102_write_reg(cam, 0x00, 0x20);
88 err += sn9c102_write_reg(cam, 0x10, 0x21);
89 err += sn9c102_write_reg(cam, 0x20, 0x22);
90 err += sn9c102_write_reg(cam, 0x30, 0x23);
91 err += sn9c102_write_reg(cam, 0x40, 0x24);
92 err += sn9c102_write_reg(cam, 0x50, 0x25);
93 err += sn9c102_write_reg(cam, 0x60, 0x26);
94 err += sn9c102_write_reg(cam, 0x70, 0x27);
95 err += sn9c102_write_reg(cam, 0x80, 0x28);
96 err += sn9c102_write_reg(cam, 0x90, 0x29);
97 err += sn9c102_write_reg(cam, 0xa0, 0x2a);
98 err += sn9c102_write_reg(cam, 0xb0, 0x2b);
99 err += sn9c102_write_reg(cam, 0xc0, 0x2c);
100 err += sn9c102_write_reg(cam, 0xd0, 0x2d);
101 err += sn9c102_write_reg(cam, 0xe0, 0x2e);
102 err += sn9c102_write_reg(cam, 0xf0, 0x2f);
103 err += sn9c102_write_reg(cam, 0xff, 0x30);
104 84
105 err += sn9c102_i2c_write(cam, 0x12, 0x8d); 85 err += sn9c102_i2c_write(cam, 0x12, 0x8d);
106 err += sn9c102_i2c_write(cam, 0x12, 0x0d); 86 err += sn9c102_i2c_write(cam, 0x12, 0x0d);
@@ -108,23 +88,23 @@ static int ov7630_init(struct sn9c102_device* cam)
108 err += sn9c102_i2c_write(cam, 0x11, 0x01); 88 err += sn9c102_i2c_write(cam, 0x11, 0x01);
109 err += sn9c102_i2c_write(cam, 0x1b, 0x04); 89 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
110 err += sn9c102_i2c_write(cam, 0x20, 0x44); 90 err += sn9c102_i2c_write(cam, 0x20, 0x44);
111 err += sn9c102_i2c_write(cam, 0x23, 0xee); 91 err += sn9c102_i2c_write(cam, 0x23, 0xee);
112 err += sn9c102_i2c_write(cam, 0x26, 0xa0); 92 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
113 err += sn9c102_i2c_write(cam, 0x27, 0x9a); 93 err += sn9c102_i2c_write(cam, 0x27, 0x9a);
114 err += sn9c102_i2c_write(cam, 0x28, 0x20); 94 err += sn9c102_i2c_write(cam, 0x28, 0x20);
115 err += sn9c102_i2c_write(cam, 0x29, 0x30); 95 err += sn9c102_i2c_write(cam, 0x29, 0x30);
116 err += sn9c102_i2c_write(cam, 0x2f, 0x3d); 96 err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
117 err += sn9c102_i2c_write(cam, 0x30, 0x24); 97 err += sn9c102_i2c_write(cam, 0x30, 0x24);
118 err += sn9c102_i2c_write(cam, 0x32, 0x86); 98 err += sn9c102_i2c_write(cam, 0x32, 0x86);
119 err += sn9c102_i2c_write(cam, 0x60, 0xa9); 99 err += sn9c102_i2c_write(cam, 0x60, 0xa9);
120 err += sn9c102_i2c_write(cam, 0x61, 0x42); 100 err += sn9c102_i2c_write(cam, 0x61, 0x42);
121 err += sn9c102_i2c_write(cam, 0x65, 0x00); 101 err += sn9c102_i2c_write(cam, 0x65, 0x00);
122 err += sn9c102_i2c_write(cam, 0x69, 0x38); 102 err += sn9c102_i2c_write(cam, 0x69, 0x38);
123 err += sn9c102_i2c_write(cam, 0x6f, 0x88); 103 err += sn9c102_i2c_write(cam, 0x6f, 0x88);
124 err += sn9c102_i2c_write(cam, 0x70, 0x0b); 104 err += sn9c102_i2c_write(cam, 0x70, 0x0b);
125 err += sn9c102_i2c_write(cam, 0x71, 0x00); 105 err += sn9c102_i2c_write(cam, 0x71, 0x00);
126 err += sn9c102_i2c_write(cam, 0x74, 0x21); 106 err += sn9c102_i2c_write(cam, 0x74, 0x21);
127 err += sn9c102_i2c_write(cam, 0x7d, 0xf7); 107 err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
128 break; 108 break;
129 default: 109 default:
130 break; 110 break;
@@ -428,15 +408,14 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
428 switch (sn9c102_get_bridge(cam)) { 408 switch (sn9c102_get_bridge(cam)) {
429 case BRIDGE_SN9C101: 409 case BRIDGE_SN9C101:
430 case BRIDGE_SN9C102: 410 case BRIDGE_SN9C102:
431 err += sn9c102_write_reg(cam, 0x01, 0x01); 411 err = sn9c102_write_const_regs(cam, {0x01, 0x01},
432 err += sn9c102_write_reg(cam, 0x00, 0x01); 412 {0x00, 0x01}, {0x28, 0x17});
433 err += sn9c102_write_reg(cam, 0x28, 0x17); 413
434 break; 414 break;
435 case BRIDGE_SN9C103: /* do _not_ change anything! */ 415 case BRIDGE_SN9C103: /* do _not_ change anything! */
436 err += sn9c102_write_reg(cam, 0x09, 0x01); 416 err = sn9c102_write_const_regs(cam, {0x09, 0x01},
437 err += sn9c102_write_reg(cam, 0x42, 0x01); 417 {0x42, 0x01}, {0x28, 0x17},
438 err += sn9c102_write_reg(cam, 0x28, 0x17); 418 {0x44, 0x02});
439 err += sn9c102_write_reg(cam, 0x44, 0x02);
440 pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); 419 pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
441 if (err || pid < 0) { /* try a different initialization */ 420 if (err || pid < 0) { /* try a different initialization */
442 err = sn9c102_write_reg(cam, 0x01, 0x01); 421 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 d670c24d4435..c898e948fe8d 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7660.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c
@@ -22,160 +22,84 @@
22#include "sn9c102_sensor.h" 22#include "sn9c102_sensor.h"
23 23
24 24
25static struct sn9c102_sensor ov7660;
26
27
28static int ov7660_init(struct sn9c102_device* cam) 25static int ov7660_init(struct sn9c102_device* cam)
29{ 26{
30 int err = 0; 27 int err = 0;
31 28
32 err += sn9c102_write_reg(cam, 0x40, 0x02); 29 err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
33 err += sn9c102_write_reg(cam, 0x00, 0x03); 30 {0x1a, 0x04}, {0x03, 0x10},
34 err += sn9c102_write_reg(cam, 0x1a, 0x04); 31 {0x08, 0x14}, {0x20, 0x17},
35 err += sn9c102_write_reg(cam, 0x03, 0x10); 32 {0x8b, 0x18}, {0x00, 0x19},
36 err += sn9c102_write_reg(cam, 0x08, 0x14); 33 {0x1d, 0x1a}, {0x10, 0x1b},
37 err += sn9c102_write_reg(cam, 0x20, 0x17); 34 {0x02, 0x1c}, {0x03, 0x1d},
38 err += sn9c102_write_reg(cam, 0x8b, 0x18); 35 {0x0f, 0x1e}, {0x0c, 0x1f},
39 err += sn9c102_write_reg(cam, 0x00, 0x19); 36 {0x00, 0x20}, {0x29, 0x21},
40 err += sn9c102_write_reg(cam, 0x1d, 0x1a); 37 {0x40, 0x22}, {0x54, 0x23},
41 err += sn9c102_write_reg(cam, 0x10, 0x1b); 38 {0x66, 0x24}, {0x76, 0x25},
42 err += sn9c102_write_reg(cam, 0x02, 0x1c); 39 {0x85, 0x26}, {0x94, 0x27},
43 err += sn9c102_write_reg(cam, 0x03, 0x1d); 40 {0xa1, 0x28}, {0xae, 0x29},
44 err += sn9c102_write_reg(cam, 0x0f, 0x1e); 41 {0xbb, 0x2a}, {0xc7, 0x2b},
45 err += sn9c102_write_reg(cam, 0x0c, 0x1f); 42 {0xd3, 0x2c}, {0xde, 0x2d},
46 err += sn9c102_write_reg(cam, 0x00, 0x20); 43 {0xea, 0x2e}, {0xf4, 0x2f},
47 err += sn9c102_write_reg(cam, 0x29, 0x21); 44 {0xff, 0x30}, {0x00, 0x3F},
48 err += sn9c102_write_reg(cam, 0x40, 0x22); 45 {0xC7, 0x40}, {0x01, 0x41},
49 err += sn9c102_write_reg(cam, 0x54, 0x23); 46 {0x44, 0x42}, {0x00, 0x43},
50 err += sn9c102_write_reg(cam, 0x66, 0x24); 47 {0x44, 0x44}, {0x00, 0x45},
51 err += sn9c102_write_reg(cam, 0x76, 0x25); 48 {0x44, 0x46}, {0x00, 0x47},
52 err += sn9c102_write_reg(cam, 0x85, 0x26); 49 {0xC7, 0x48}, {0x01, 0x49},
53 err += sn9c102_write_reg(cam, 0x94, 0x27); 50 {0xC7, 0x4A}, {0x01, 0x4B},
54 err += sn9c102_write_reg(cam, 0xa1, 0x28); 51 {0xC7, 0x4C}, {0x01, 0x4D},
55 err += sn9c102_write_reg(cam, 0xae, 0x29); 52 {0x44, 0x4E}, {0x00, 0x4F},
56 err += sn9c102_write_reg(cam, 0xbb, 0x2a); 53 {0x44, 0x50}, {0x00, 0x51},
57 err += sn9c102_write_reg(cam, 0xc7, 0x2b); 54 {0x44, 0x52}, {0x00, 0x53},
58 err += sn9c102_write_reg(cam, 0xd3, 0x2c); 55 {0xC7, 0x54}, {0x01, 0x55},
59 err += sn9c102_write_reg(cam, 0xde, 0x2d); 56 {0xC7, 0x56}, {0x01, 0x57},
60 err += sn9c102_write_reg(cam, 0xea, 0x2e); 57 {0xC7, 0x58}, {0x01, 0x59},
61 err += sn9c102_write_reg(cam, 0xf4, 0x2f); 58 {0x44, 0x5A}, {0x00, 0x5B},
62 err += sn9c102_write_reg(cam, 0xff, 0x30); 59 {0x44, 0x5C}, {0x00, 0x5D},
63 err += sn9c102_write_reg(cam, 0x00, 0x3F); 60 {0x44, 0x5E}, {0x00, 0x5F},
64 err += sn9c102_write_reg(cam, 0xC7, 0x40); 61 {0xC7, 0x60}, {0x01, 0x61},
65 err += sn9c102_write_reg(cam, 0x01, 0x41); 62 {0xC7, 0x62}, {0x01, 0x63},
66 err += sn9c102_write_reg(cam, 0x44, 0x42); 63 {0xC7, 0x64}, {0x01, 0x65},
67 err += sn9c102_write_reg(cam, 0x00, 0x43); 64 {0x44, 0x66}, {0x00, 0x67},
68 err += sn9c102_write_reg(cam, 0x44, 0x44); 65 {0x44, 0x68}, {0x00, 0x69},
69 err += sn9c102_write_reg(cam, 0x00, 0x45); 66 {0x44, 0x6A}, {0x00, 0x6B},
70 err += sn9c102_write_reg(cam, 0x44, 0x46); 67 {0xC7, 0x6C}, {0x01, 0x6D},
71 err += sn9c102_write_reg(cam, 0x00, 0x47); 68 {0xC7, 0x6E}, {0x01, 0x6F},
72 err += sn9c102_write_reg(cam, 0xC7, 0x48); 69 {0xC7, 0x70}, {0x01, 0x71},
73 err += sn9c102_write_reg(cam, 0x01, 0x49); 70 {0x44, 0x72}, {0x00, 0x73},
74 err += sn9c102_write_reg(cam, 0xC7, 0x4A); 71 {0x44, 0x74}, {0x00, 0x75},
75 err += sn9c102_write_reg(cam, 0x01, 0x4B); 72 {0x44, 0x76}, {0x00, 0x77},
76 err += sn9c102_write_reg(cam, 0xC7, 0x4C); 73 {0xC7, 0x78}, {0x01, 0x79},
77 err += sn9c102_write_reg(cam, 0x01, 0x4D); 74 {0xC7, 0x7A}, {0x01, 0x7B},
78 err += sn9c102_write_reg(cam, 0x44, 0x4E); 75 {0xC7, 0x7C}, {0x01, 0x7D},
79 err += sn9c102_write_reg(cam, 0x00, 0x4F); 76 {0x44, 0x7E}, {0x00, 0x7F},
80 err += sn9c102_write_reg(cam, 0x44, 0x50); 77 {0x14, 0x84}, {0x00, 0x85},
81 err += sn9c102_write_reg(cam, 0x00, 0x51); 78 {0x27, 0x86}, {0x00, 0x87},
82 err += sn9c102_write_reg(cam, 0x44, 0x52); 79 {0x07, 0x88}, {0x00, 0x89},
83 err += sn9c102_write_reg(cam, 0x00, 0x53); 80 {0xEC, 0x8A}, {0x0f, 0x8B},
84 err += sn9c102_write_reg(cam, 0xC7, 0x54); 81 {0xD8, 0x8C}, {0x0f, 0x8D},
85 err += sn9c102_write_reg(cam, 0x01, 0x55); 82 {0x3D, 0x8E}, {0x00, 0x8F},
86 err += sn9c102_write_reg(cam, 0xC7, 0x56); 83 {0x3D, 0x90}, {0x00, 0x91},
87 err += sn9c102_write_reg(cam, 0x01, 0x57); 84 {0xCD, 0x92}, {0x0f, 0x93},
88 err += sn9c102_write_reg(cam, 0xC7, 0x58); 85 {0xf7, 0x94}, {0x0f, 0x95},
89 err += sn9c102_write_reg(cam, 0x01, 0x59); 86 {0x0C, 0x96}, {0x00, 0x97},
90 err += sn9c102_write_reg(cam, 0x44, 0x5A); 87 {0x00, 0x98}, {0x66, 0x99},
91 err += sn9c102_write_reg(cam, 0x00, 0x5B); 88 {0x05, 0x9A}, {0x00, 0x9B},
92 err += sn9c102_write_reg(cam, 0x44, 0x5C); 89 {0x04, 0x9C}, {0x00, 0x9D},
93 err += sn9c102_write_reg(cam, 0x00, 0x5D); 90 {0x08, 0x9E}, {0x00, 0x9F},
94 err += sn9c102_write_reg(cam, 0x44, 0x5E); 91 {0x2D, 0xC0}, {0x2D, 0xC1},
95 err += sn9c102_write_reg(cam, 0x00, 0x5F); 92 {0x3A, 0xC2}, {0x05, 0xC3},
96 err += sn9c102_write_reg(cam, 0xC7, 0x60); 93 {0x04, 0xC4}, {0x3F, 0xC5},
97 err += sn9c102_write_reg(cam, 0x01, 0x61); 94 {0x00, 0xC6}, {0x00, 0xC7},
98 err += sn9c102_write_reg(cam, 0xC7, 0x62); 95 {0x50, 0xC8}, {0x3C, 0xC9},
99 err += sn9c102_write_reg(cam, 0x01, 0x63); 96 {0x28, 0xCA}, {0xD8, 0xCB},
100 err += sn9c102_write_reg(cam, 0xC7, 0x64); 97 {0x14, 0xCC}, {0xEC, 0xCD},
101 err += sn9c102_write_reg(cam, 0x01, 0x65); 98 {0x32, 0xCE}, {0xDD, 0xCF},
102 err += sn9c102_write_reg(cam, 0x44, 0x66); 99 {0x32, 0xD0}, {0xDD, 0xD1},
103 err += sn9c102_write_reg(cam, 0x00, 0x67); 100 {0x6A, 0xD2}, {0x50, 0xD3},
104 err += sn9c102_write_reg(cam, 0x44, 0x68); 101 {0x00, 0xD4}, {0x00, 0xD5},
105 err += sn9c102_write_reg(cam, 0x00, 0x69); 102 {0x00, 0xD6});
106 err += sn9c102_write_reg(cam, 0x44, 0x6A);
107 err += sn9c102_write_reg(cam, 0x00, 0x6B);
108 err += sn9c102_write_reg(cam, 0xC7, 0x6C);
109 err += sn9c102_write_reg(cam, 0x01, 0x6D);
110 err += sn9c102_write_reg(cam, 0xC7, 0x6E);
111 err += sn9c102_write_reg(cam, 0x01, 0x6F);
112 err += sn9c102_write_reg(cam, 0xC7, 0x70);
113 err += sn9c102_write_reg(cam, 0x01, 0x71);
114 err += sn9c102_write_reg(cam, 0x44, 0x72);
115 err += sn9c102_write_reg(cam, 0x00, 0x73);
116 err += sn9c102_write_reg(cam, 0x44, 0x74);
117 err += sn9c102_write_reg(cam, 0x00, 0x75);
118 err += sn9c102_write_reg(cam, 0x44, 0x76);
119 err += sn9c102_write_reg(cam, 0x00, 0x77);
120 err += sn9c102_write_reg(cam, 0xC7, 0x78);
121 err += sn9c102_write_reg(cam, 0x01, 0x79);
122 err += sn9c102_write_reg(cam, 0xC7, 0x7A);
123 err += sn9c102_write_reg(cam, 0x01, 0x7B);
124 err += sn9c102_write_reg(cam, 0xC7, 0x7C);
125 err += sn9c102_write_reg(cam, 0x01, 0x7D);
126 err += sn9c102_write_reg(cam, 0x44, 0x7E);
127 err += sn9c102_write_reg(cam, 0x00, 0x7F);
128 err += sn9c102_write_reg(cam, 0x14, 0x84);
129 err += sn9c102_write_reg(cam, 0x00, 0x85);
130 err += sn9c102_write_reg(cam, 0x27, 0x86);
131 err += sn9c102_write_reg(cam, 0x00, 0x87);
132 err += sn9c102_write_reg(cam, 0x07, 0x88);
133 err += sn9c102_write_reg(cam, 0x00, 0x89);
134 err += sn9c102_write_reg(cam, 0xEC, 0x8A);
135 err += sn9c102_write_reg(cam, 0x0f, 0x8B);
136 err += sn9c102_write_reg(cam, 0xD8, 0x8C);
137 err += sn9c102_write_reg(cam, 0x0f, 0x8D);
138 err += sn9c102_write_reg(cam, 0x3D, 0x8E);
139 err += sn9c102_write_reg(cam, 0x00, 0x8F);
140 err += sn9c102_write_reg(cam, 0x3D, 0x90);
141 err += sn9c102_write_reg(cam, 0x00, 0x91);
142 err += sn9c102_write_reg(cam, 0xCD, 0x92);
143 err += sn9c102_write_reg(cam, 0x0f, 0x93);
144 err += sn9c102_write_reg(cam, 0xf7, 0x94);
145 err += sn9c102_write_reg(cam, 0x0f, 0x95);
146 err += sn9c102_write_reg(cam, 0x0C, 0x96);
147 err += sn9c102_write_reg(cam, 0x00, 0x97);
148 err += sn9c102_write_reg(cam, 0x00, 0x98);
149 err += sn9c102_write_reg(cam, 0x66, 0x99);
150 err += sn9c102_write_reg(cam, 0x05, 0x9A);
151 err += sn9c102_write_reg(cam, 0x00, 0x9B);
152 err += sn9c102_write_reg(cam, 0x04, 0x9C);
153 err += sn9c102_write_reg(cam, 0x00, 0x9D);
154 err += sn9c102_write_reg(cam, 0x08, 0x9E);
155 err += sn9c102_write_reg(cam, 0x00, 0x9F);
156 err += sn9c102_write_reg(cam, 0x2D, 0xC0);
157 err += sn9c102_write_reg(cam, 0x2D, 0xC1);
158 err += sn9c102_write_reg(cam, 0x3A, 0xC2);
159 err += sn9c102_write_reg(cam, 0x05, 0xC3);
160 err += sn9c102_write_reg(cam, 0x04, 0xC4);
161 err += sn9c102_write_reg(cam, 0x3F, 0xC5);
162 err += sn9c102_write_reg(cam, 0x00, 0xC6);
163 err += sn9c102_write_reg(cam, 0x00, 0xC7);
164 err += sn9c102_write_reg(cam, 0x50, 0xC8);
165 err += sn9c102_write_reg(cam, 0x3C, 0xC9);
166 err += sn9c102_write_reg(cam, 0x28, 0xCA);
167 err += sn9c102_write_reg(cam, 0xD8, 0xCB);
168 err += sn9c102_write_reg(cam, 0x14, 0xCC);
169 err += sn9c102_write_reg(cam, 0xEC, 0xCD);
170 err += sn9c102_write_reg(cam, 0x32, 0xCE);
171 err += sn9c102_write_reg(cam, 0xDD, 0xCF);
172 err += sn9c102_write_reg(cam, 0x32, 0xD0);
173 err += sn9c102_write_reg(cam, 0xDD, 0xD1);
174 err += sn9c102_write_reg(cam, 0x6A, 0xD2);
175 err += sn9c102_write_reg(cam, 0x50, 0xD3);
176 err += sn9c102_write_reg(cam, 0x00, 0xD4);
177 err += sn9c102_write_reg(cam, 0x00, 0xD5);
178 err += sn9c102_write_reg(cam, 0x00, 0xD6);
179 103
180 err += sn9c102_i2c_write(cam, 0x12, 0x80); 104 err += sn9c102_i2c_write(cam, 0x12, 0x80);
181 err += sn9c102_i2c_write(cam, 0x11, 0x09); 105 err += sn9c102_i2c_write(cam, 0x11, 0x09);
@@ -572,13 +496,11 @@ static struct sn9c102_sensor ov7660 = {
572 496
573int sn9c102_probe_ov7660(struct sn9c102_device* cam) 497int sn9c102_probe_ov7660(struct sn9c102_device* cam)
574{ 498{
575 int pid, ver, err = 0; 499 int pid, ver, err;
576 500
577 err += sn9c102_write_reg(cam, 0x01, 0xf1); 501 err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
578 err += sn9c102_write_reg(cam, 0x00, 0xf1); 502 {0x01, 0x01}, {0x00, 0x01},
579 err += sn9c102_write_reg(cam, 0x01, 0x01); 503 {0x28, 0x17});
580 err += sn9c102_write_reg(cam, 0x00, 0x01);
581 err += sn9c102_write_reg(cam, 0x28, 0x17);
582 504
583 pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a); 505 pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
584 ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b); 506 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 8d79a5fae5de..67151964801f 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas106b.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c
@@ -23,19 +23,13 @@
23#include "sn9c102_sensor.h" 23#include "sn9c102_sensor.h"
24 24
25 25
26static struct sn9c102_sensor pas106b;
27
28
29static int pas106b_init(struct sn9c102_device* cam) 26static int pas106b_init(struct sn9c102_device* cam)
30{ 27{
31 int err = 0; 28 int err = 0;
32 29
33 err += sn9c102_write_reg(cam, 0x00, 0x10); 30 err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
34 err += sn9c102_write_reg(cam, 0x00, 0x11); 31 {0x00, 0x14}, {0x20, 0x17},
35 err += sn9c102_write_reg(cam, 0x00, 0x14); 32 {0x20, 0x19}, {0x09, 0x18});
36 err += sn9c102_write_reg(cam, 0x20, 0x17);
37 err += sn9c102_write_reg(cam, 0x20, 0x19);
38 err += sn9c102_write_reg(cam, 0x09, 0x18);
39 33
40 err += sn9c102_i2c_write(cam, 0x02, 0x0c); 34 err += sn9c102_i2c_write(cam, 0x02, 0x0c);
41 err += sn9c102_i2c_write(cam, 0x05, 0x5a); 35 err += sn9c102_i2c_write(cam, 0x05, 0x5a);
@@ -172,7 +166,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam,
172static struct sn9c102_sensor pas106b = { 166static struct sn9c102_sensor pas106b = {
173 .name = "PAS106B", 167 .name = "PAS106B",
174 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 168 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
175 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 169 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
176 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 170 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
177 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, 171 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
178 .interface = SN9C102_I2C_2WIRES, 172 .interface = SN9C102_I2C_2WIRES,
@@ -279,16 +273,17 @@ static struct sn9c102_sensor pas106b = {
279 273
280int sn9c102_probe_pas106b(struct sn9c102_device* cam) 274int sn9c102_probe_pas106b(struct sn9c102_device* cam)
281{ 275{
282 int r0 = 0, r1 = 0, err = 0; 276 int r0 = 0, r1 = 0, err;
283 unsigned int pid = 0; 277 unsigned int pid = 0;
284 278
285 /* 279 /*
286 Minimal initialization to enable the I2C communication 280 Minimal initialization to enable the I2C communication
287 NOTE: do NOT change the values! 281 NOTE: do NOT change the values!
288 */ 282 */
289 err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ 283 err = sn9c102_write_const_regs(cam,
290 err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */ 284 {0x01, 0x01}, /* sensor power down */
291 err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ 285 {0x00, 0x01}, /* sensor power on */
286 {0x28, 0x17});/* sensor clock 24 MHz */
292 if (err) 287 if (err)
293 return -EIO; 288 return -EIO;
294 289
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
index 7894f01b56e8..c1b8d6b63b47 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
@@ -28,9 +28,6 @@
28#include "sn9c102_sensor.h" 28#include "sn9c102_sensor.h"
29 29
30 30
31static struct sn9c102_sensor pas202bcb;
32
33
34static int pas202bcb_init(struct sn9c102_device* cam) 31static int pas202bcb_init(struct sn9c102_device* cam)
35{ 32{
36 int err = 0; 33 int err = 0;
@@ -38,47 +35,29 @@ static int pas202bcb_init(struct sn9c102_device* cam)
38 switch (sn9c102_get_bridge(cam)) { 35 switch (sn9c102_get_bridge(cam)) {
39 case BRIDGE_SN9C101: 36 case BRIDGE_SN9C101:
40 case BRIDGE_SN9C102: 37 case BRIDGE_SN9C102:
41 err += sn9c102_write_reg(cam, 0x00, 0x10); 38 err = sn9c102_write_const_regs(cam, {0x00, 0x10},
42 err += sn9c102_write_reg(cam, 0x00, 0x11); 39 {0x00, 0x11}, {0x00, 0x14},
43 err += sn9c102_write_reg(cam, 0x00, 0x14); 40 {0x20, 0x17}, {0x30, 0x19},
44 err += sn9c102_write_reg(cam, 0x20, 0x17); 41 {0x09, 0x18});
45 err += sn9c102_write_reg(cam, 0x30, 0x19);
46 err += sn9c102_write_reg(cam, 0x09, 0x18);
47 break; 42 break;
48 case BRIDGE_SN9C103: 43 case BRIDGE_SN9C103:
49 err += sn9c102_write_reg(cam, 0x00, 0x02); 44 err = sn9c102_write_const_regs(cam, {0x00, 0x02},
50 err += sn9c102_write_reg(cam, 0x00, 0x03); 45 {0x00, 0x03}, {0x1a, 0x04},
51 err += sn9c102_write_reg(cam, 0x1a, 0x04); 46 {0x20, 0x05}, {0x20, 0x06},
52 err += sn9c102_write_reg(cam, 0x20, 0x05); 47 {0x20, 0x07}, {0x00, 0x10},
53 err += sn9c102_write_reg(cam, 0x20, 0x06); 48 {0x00, 0x11}, {0x00, 0x14},
54 err += sn9c102_write_reg(cam, 0x20, 0x07); 49 {0x20, 0x17}, {0x30, 0x19},
55 err += sn9c102_write_reg(cam, 0x00, 0x10); 50 {0x09, 0x18}, {0x02, 0x1c},
56 err += sn9c102_write_reg(cam, 0x00, 0x11); 51 {0x03, 0x1d}, {0x0f, 0x1e},
57 err += sn9c102_write_reg(cam, 0x00, 0x14); 52 {0x0c, 0x1f}, {0x00, 0x20},
58 err += sn9c102_write_reg(cam, 0x20, 0x17); 53 {0x10, 0x21}, {0x20, 0x22},
59 err += sn9c102_write_reg(cam, 0x30, 0x19); 54 {0x30, 0x23}, {0x40, 0x24},
60 err += sn9c102_write_reg(cam, 0x09, 0x18); 55 {0x50, 0x25}, {0x60, 0x26},
61 err += sn9c102_write_reg(cam, 0x02, 0x1c); 56 {0x70, 0x27}, {0x80, 0x28},
62 err += sn9c102_write_reg(cam, 0x03, 0x1d); 57 {0x90, 0x29}, {0xa0, 0x2a},
63 err += sn9c102_write_reg(cam, 0x0f, 0x1e); 58 {0xb0, 0x2b}, {0xc0, 0x2c},
64 err += sn9c102_write_reg(cam, 0x0c, 0x1f); 59 {0xd0, 0x2d}, {0xe0, 0x2e},
65 err += sn9c102_write_reg(cam, 0x00, 0x20); 60 {0xf0, 0x2f}, {0xff, 0x30});
66 err += sn9c102_write_reg(cam, 0x10, 0x21);
67 err += sn9c102_write_reg(cam, 0x20, 0x22);
68 err += sn9c102_write_reg(cam, 0x30, 0x23);
69 err += sn9c102_write_reg(cam, 0x40, 0x24);
70 err += sn9c102_write_reg(cam, 0x50, 0x25);
71 err += sn9c102_write_reg(cam, 0x60, 0x26);
72 err += sn9c102_write_reg(cam, 0x70, 0x27);
73 err += sn9c102_write_reg(cam, 0x80, 0x28);
74 err += sn9c102_write_reg(cam, 0x90, 0x29);
75 err += sn9c102_write_reg(cam, 0xa0, 0x2a);
76 err += sn9c102_write_reg(cam, 0xb0, 0x2b);
77 err += sn9c102_write_reg(cam, 0xc0, 0x2c);
78 err += sn9c102_write_reg(cam, 0xd0, 0x2d);
79 err += sn9c102_write_reg(cam, 0xe0, 0x2e);
80 err += sn9c102_write_reg(cam, 0xf0, 0x2f);
81 err += sn9c102_write_reg(cam, 0xff, 0x30);
82 break; 61 break;
83 default: 62 default:
84 break; 63 break;
@@ -328,15 +307,15 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
328 switch (sn9c102_get_bridge(cam)) { 307 switch (sn9c102_get_bridge(cam)) {
329 case BRIDGE_SN9C101: 308 case BRIDGE_SN9C101:
330 case BRIDGE_SN9C102: 309 case BRIDGE_SN9C102:
331 err += sn9c102_write_reg(cam, 0x01, 0x01); /* power down */ 310 err = sn9c102_write_const_regs(cam,
332 err += sn9c102_write_reg(cam, 0x40, 0x01); /* power on */ 311 {0x01, 0x01}, /* power down */
333 err += sn9c102_write_reg(cam, 0x28, 0x17); /* clock 24 MHz */ 312 {0x40, 0x01}, /* power on */
313 {0x28, 0x17});/* clock 24 MHz */
334 break; 314 break;
335 case BRIDGE_SN9C103: /* do _not_ change anything! */ 315 case BRIDGE_SN9C103: /* do _not_ change anything! */
336 err += sn9c102_write_reg(cam, 0x09, 0x01); 316 err = sn9c102_write_const_regs(cam, {0x09, 0x01},
337 err += sn9c102_write_reg(cam, 0x44, 0x01); 317 {0x44, 0x01}, {0x44, 0x02},
338 err += sn9c102_write_reg(cam, 0x44, 0x02); 318 {0x29, 0x17});
339 err += sn9c102_write_reg(cam, 0x29, 0x17);
340 break; 319 break;
341 default: 320 default:
342 break; 321 break;
diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h
index 05f2942639c3..1bbf64c897a2 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);
114extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address); 114extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
115 115
116/* I/O on registers in the bridge. Could be used by the sensor methods too */ 116/* I/O on registers in the bridge. Could be used by the sensor methods too */
117extern int sn9c102_write_regs(struct sn9c102_device*, u8* buff, u16 index);
118extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
119extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); 117extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
118extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
119extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
120 int count);
121/*
122 * Write multiple registers with constant values. For example:
123 * sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
124 */
125#define sn9c102_write_const_regs(device, data...) \
126 ({ const static u8 _data[][2] = {data}; \
127 sn9c102_write_regs(device, _data, ARRAY_SIZE(_data)); })
120 128
121/*****************************************************************************/ 129/*****************************************************************************/
122 130
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
index 90023ad63adc..0e7ec8662c70 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
@@ -22,21 +22,14 @@
22#include "sn9c102_sensor.h" 22#include "sn9c102_sensor.h"
23 23
24 24
25static struct sn9c102_sensor tas5110c1b;
26
27
28static int tas5110c1b_init(struct sn9c102_device* cam) 25static int tas5110c1b_init(struct sn9c102_device* cam)
29{ 26{
30 int err = 0; 27 int err = 0;
31 28
32 err += sn9c102_write_reg(cam, 0x01, 0x01); 29 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x44, 0x01},
33 err += sn9c102_write_reg(cam, 0x44, 0x01); 30 {0x00, 0x10}, {0x00, 0x11},
34 err += sn9c102_write_reg(cam, 0x00, 0x10); 31 {0x0a, 0x14}, {0x60, 0x17},
35 err += sn9c102_write_reg(cam, 0x00, 0x11); 32 {0x06, 0x18}, {0xfb, 0x19});
36 err += sn9c102_write_reg(cam, 0x0a, 0x14);
37 err += sn9c102_write_reg(cam, 0x60, 0x17);
38 err += sn9c102_write_reg(cam, 0x06, 0x18);
39 err += sn9c102_write_reg(cam, 0xfb, 0x19);
40 33
41 err += sn9c102_i2c_write(cam, 0xc0, 0x80); 34 err += sn9c102_i2c_write(cam, 0xc0, 0x80);
42 35
@@ -98,7 +91,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
98static struct sn9c102_sensor tas5110c1b = { 91static struct sn9c102_sensor tas5110c1b = {
99 .name = "TAS5110C1B", 92 .name = "TAS5110C1B",
100 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 93 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
101 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 94 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
102 .sysfs_ops = SN9C102_I2C_WRITE, 95 .sysfs_ops = SN9C102_I2C_WRITE,
103 .frequency = SN9C102_I2C_100KHZ, 96 .frequency = SN9C102_I2C_100KHZ,
104 .interface = SN9C102_I2C_3WIRES, 97 .interface = SN9C102_I2C_3WIRES,
@@ -146,7 +139,6 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
146 const struct usb_device_id tas5110c1b_id_table[] = { 139 const struct usb_device_id tas5110c1b_id_table[] = {
147 { USB_DEVICE(0x0c45, 0x6001), }, 140 { USB_DEVICE(0x0c45, 0x6001), },
148 { USB_DEVICE(0x0c45, 0x6005), }, 141 { USB_DEVICE(0x0c45, 0x6005), },
149 { USB_DEVICE(0x0c45, 0x6007), },
150 { USB_DEVICE(0x0c45, 0x60ab), }, 142 { USB_DEVICE(0x0c45, 0x60ab), },
151 { } 143 { }
152 }; 144 };
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c
new file mode 100644
index 000000000000..83a39e8b5e71
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110d.c
@@ -0,0 +1,118 @@
1/***************************************************************************
2 * Plug-in for TAS5110D image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20 ***************************************************************************/
21
22#include "sn9c102_sensor.h"
23
24
25static int tas5110d_init(struct sn9c102_device* cam)
26{
27 int err;
28
29 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x04, 0x01},
30 {0x0a, 0x14}, {0x60, 0x17},
31 {0x06, 0x18}, {0xfb, 0x19});
32
33 err += sn9c102_i2c_write(cam, 0x9a, 0xca);
34
35 return err;
36}
37
38
39static int tas5110d_set_crop(struct sn9c102_device* cam,
40 const struct v4l2_rect* rect)
41{
42 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
43 int err = 0;
44 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
45 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
46
47 err += sn9c102_write_reg(cam, h_start, 0x12);
48 err += sn9c102_write_reg(cam, v_start, 0x13);
49
50 err += sn9c102_write_reg(cam, 0x14, 0x1a);
51 err += sn9c102_write_reg(cam, 0x0a, 0x1b);
52
53 return err;
54}
55
56
57static int tas5110d_set_pix_format(struct sn9c102_device* cam,
58 const struct v4l2_pix_format* pix)
59{
60 int err = 0;
61
62 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
63 err += sn9c102_write_reg(cam, 0x3b, 0x19);
64 else
65 err += sn9c102_write_reg(cam, 0xfb, 0x19);
66
67 return err;
68}
69
70
71static struct sn9c102_sensor tas5110d = {
72 .name = "TAS5110D",
73 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
74 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
75 .sysfs_ops = SN9C102_I2C_WRITE,
76 .frequency = SN9C102_I2C_100KHZ,
77 .interface = SN9C102_I2C_2WIRES,
78 .i2c_slave_id = 0x61,
79 .init = &tas5110d_init,
80 .cropcap = {
81 .bounds = {
82 .left = 0,
83 .top = 0,
84 .width = 352,
85 .height = 288,
86 },
87 .defrect = {
88 .left = 0,
89 .top = 0,
90 .width = 352,
91 .height = 288,
92 },
93 },
94 .set_crop = &tas5110d_set_crop,
95 .pix_format = {
96 .width = 352,
97 .height = 288,
98 .pixelformat = V4L2_PIX_FMT_SBGGR8,
99 .priv = 8,
100 },
101 .set_pix_format = &tas5110d_set_pix_format
102};
103
104
105int sn9c102_probe_tas5110d(struct sn9c102_device* cam)
106{
107 const struct usb_device_id tas5110d_id_table[] = {
108 { USB_DEVICE(0x0c45, 0x6007), },
109 { }
110 };
111
112 if (!sn9c102_match_id(cam, tas5110d_id_table))
113 return -ENODEV;
114
115 sn9c102_attach_sensor(cam, &tas5110d);
116
117 return 0;
118}
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
index cb1b318bc1ff..50406503fc40 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
@@ -22,21 +22,14 @@
22#include "sn9c102_sensor.h" 22#include "sn9c102_sensor.h"
23 23
24 24
25static struct sn9c102_sensor tas5130d1b;
26
27
28static int tas5130d1b_init(struct sn9c102_device* cam) 25static int tas5130d1b_init(struct sn9c102_device* cam)
29{ 26{
30 int err = 0; 27 int err;
31 28
32 err += sn9c102_write_reg(cam, 0x01, 0x01); 29 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x20, 0x17},
33 err += sn9c102_write_reg(cam, 0x20, 0x17); 30 {0x04, 0x01}, {0x01, 0x10},
34 err += sn9c102_write_reg(cam, 0x04, 0x01); 31 {0x00, 0x11}, {0x00, 0x14},
35 err += sn9c102_write_reg(cam, 0x01, 0x10); 32 {0x60, 0x17}, {0x07, 0x18});
36 err += sn9c102_write_reg(cam, 0x00, 0x11);
37 err += sn9c102_write_reg(cam, 0x00, 0x14);
38 err += sn9c102_write_reg(cam, 0x60, 0x17);
39 err += sn9c102_write_reg(cam, 0x07, 0x18);
40 33
41 return err; 34 return err;
42} 35}
@@ -99,7 +92,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
99static struct sn9c102_sensor tas5130d1b = { 92static struct sn9c102_sensor tas5130d1b = {
100 .name = "TAS5130D1B", 93 .name = "TAS5130D1B",
101 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 94 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
102 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 95 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
103 .sysfs_ops = SN9C102_I2C_WRITE, 96 .sysfs_ops = SN9C102_I2C_WRITE,
104 .frequency = SN9C102_I2C_100KHZ, 97 .frequency = SN9C102_I2C_100KHZ,
105 .interface = SN9C102_I2C_3WIRES, 98 .interface = SN9C102_I2C_3WIRES,