aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Risolia <luca.risolia@studio.unibo.it>2007-03-26 15:12:04 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-04-27 14:45:08 -0400
commitf423b9a86a6dd3d2bc08d78f4d21525a14c40a6b (patch)
treecac9dcd72bd298478559cdae7061b1a942cb4b0f
parent9ab7e323af9f9efad3e20a14faa4d947adfac381 (diff)
V4L/DVB (5474): SN9C1xx driver updates
@ Don't assume that SOF headers can't cross packets boundaries @ Fix compression quality selection + Add support for MI-0360 image sensor * Documentation updates @ Fix sysfs @ MI0343 rewritten * HV7131R color fixes and add new ABLC control * Rename the archive from "sn9c102" to "sn9c1xx" * fix typos * better support for TAS5110D @ fix OV7630 wrong colors @ Don't return an error if no input buffers are enqueued yet on VIDIOC_STREAMON * Add informations about colorspaces * More appropriate error codes in case of failure of some system calls * More precise hardware detection * Add more informations about supported hardware in the documentation + More supported devices + Add support for HV7131R image sensor Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--Documentation/video4linux/sn9c102.txt64
-rw-r--r--MAINTAINERS2
-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.c199
-rw-r--r--drivers/media/video/sn9c102/sn9c102_devtable.h14
-rw-r--r--drivers/media/video/sn9c102/sn9c102_hv7131d.c7
-rw-r--r--drivers/media/video/sn9c102/sn9c102_hv7131r.c458
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mi0343.c111
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mi0360.c353
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7630.c63
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7660.c3
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas106b.c5
-rw-r--r--drivers/media/video/sn9c102/sn9c102_pas202bcb.c15
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5110c1b.c6
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5110d.c121
-rw-r--r--drivers/media/video/sn9c102/sn9c102_tas5130d1b.c5
17 files changed, 1223 insertions, 237 deletions
diff --git a/Documentation/video4linux/sn9c102.txt b/Documentation/video4linux/sn9c102.txt
index 2913da3d0878..5fe0ad7dfc20 100644
--- a/Documentation/video4linux/sn9c102.txt
+++ b/Documentation/video4linux/sn9c102.txt
@@ -25,7 +25,7 @@ Index
25 25
261. Copyright 261. Copyright
27============ 27============
28Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> 28Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
29 29
30 30
312. Disclaimer 312. Disclaimer
@@ -216,10 +216,10 @@ Description: Debugging information level, from 0 to 3:
216 1 = critical errors 216 1 = critical errors
217 2 = significant informations 217 2 = significant informations
218 3 = more verbose messages 218 3 = more verbose messages
219 Level 3 is useful for testing only, when only one device 219 Level 3 is useful for testing only. It also shows some more
220 is used. It also shows some more informations about the 220 informations about the hardware being detected.
221 hardware being detected. This parameter can be changed at 221 This parameter can be changed at runtime thanks to the /sys
222 runtime thanks to the /sys filesystem interface. 222 filesystem interface.
223Default: 2 223Default: 2
224------------------------------------------------------------------------------- 224-------------------------------------------------------------------------------
225 225
@@ -235,7 +235,7 @@ created in the /sys/class/video4linux/videoX directory. You can set the green
235channel's gain by writing the desired value to it. The value may range from 0 235channel's gain by writing the desired value to it. The value may range from 0
236to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103, 236to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103,
237SN9C105 and SN9C120 bridges. 237SN9C105 and SN9C120 bridges.
238Similarly, only for the SN9C103, SN9C105 and SN9120 controllers, blue and red 238Similarly, only for the SN9C103, SN9C105 and SN9C120 controllers, blue and red
239gain control files are available in the same directory, for which accepted 239gain control files are available in the same directory, for which accepted
240values may range from 0 to 127. 240values may range from 0 to 127.
241 241
@@ -402,38 +402,49 @@ Vendor ID Product ID
4020x0c45 0x60bc 4020x0c45 0x60bc
4030x0c45 0x60be 4030x0c45 0x60be
4040x0c45 0x60c0 4040x0c45 0x60c0
4050x0c45 0x60c2
4050x0c45 0x60c8 4060x0c45 0x60c8
4060x0c45 0x60cc 4070x0c45 0x60cc
4070x0c45 0x60ea 4080x0c45 0x60ea
4080x0c45 0x60ec 4090x0c45 0x60ec
4100x0c45 0x60ef
4090x0c45 0x60fa 4110x0c45 0x60fa
4100x0c45 0x60fb 4120x0c45 0x60fb
4110x0c45 0x60fc 4130x0c45 0x60fc
4120x0c45 0x60fe 4140x0c45 0x60fe
4150x0c45 0x6102
4160x0c45 0x6108
4170x0c45 0x610f
4130x0c45 0x6130 4180x0c45 0x6130
4190x0c45 0x6138
4140x0c45 0x613a 4200x0c45 0x613a
4150x0c45 0x613b 4210x0c45 0x613b
4160x0c45 0x613c 4220x0c45 0x613c
4170x0c45 0x613e 4230x0c45 0x613e
418 424
419The list above does not imply that all those devices work with this driver: up 425The list above does not imply that all those devices work with this driver: up
420until now only the ones that assemble the following image sensors are 426until now only the ones that assemble the following pairs of SN9C1xx bridges
421supported; kernel messages will always tell you whether this is the case (see 427and image sensors are supported; kernel messages will always tell you whether
422"Module loading" paragraph): 428this is the case (see "Module loading" paragraph):
423 429
424Model Manufacturer 430Image sensor / SN9C1xx bridge | SN9C10[12] SN9C103 SN9C105 SN9C120
425----- ------------ 431-------------------------------------------------------------------------------
426HV7131D Hynix Semiconductor, Inc. 432HV7131D Hynix Semiconductor | Yes No No No
427MI-0343 Micron Technology, Inc. 433HV7131R Hynix Semiconductor | No Yes Yes Yes
428OV7630 OmniVision Technologies, Inc. 434MI-0343 Micron Technology | Yes No No No
429OV7660 OmniVision Technologies, Inc. 435MI-0360 Micron Technology | No Yes No No
430PAS106B PixArt Imaging, Inc. 436OV7630 OmniVision Technologies | Yes Yes No No
431PAS202BCA PixArt Imaging, Inc. 437OV7660 OmniVision Technologies | No No Yes Yes
432PAS202BCB PixArt Imaging, Inc. 438PAS106B PixArt Imaging | Yes No No No
433TAS5110C1B Taiwan Advanced Sensor Corporation 439PAS202B PixArt Imaging | Yes Yes No No
434TAS5130D1B Taiwan Advanced Sensor Corporation 440TAS5110C1B Taiwan Advanced Sensor | Yes No No No
435 441TAS5110D Taiwan Advanced Sensor | Yes No No No
436Some of the available control settings of each image sensor are supported 442TAS5130D1B Taiwan Advanced Sensor | Yes No No No
443
444"Yes" means that the pair is supported by the driver, while "No" means that the
445pair does not exist or is not supported by the driver.
446
447Only some of the available control settings of each image sensor are supported
437through the V4L2 interface. 448through the V4L2 interface.
438 449
439Donations of new models for further testing and support would be much 450Donations of new models for further testing and support would be much
@@ -482,8 +493,8 @@ The SN9C1xx PC Camera Controllers can send images in two possible video
482formats over the USB: either native "Sequential RGB Bayer" or compressed. 493formats over the USB: either native "Sequential RGB Bayer" or compressed.
483The compression is used to achieve high frame rates. With regard to the 494The compression is used to achieve high frame rates. With regard to the
484SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding 495SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding
485algorithm described below, while the SN9C105 and SN9C120 the compression is 496algorithm described below, while with regard to the SN9C105 and SN9C120 the
486based on the JPEG standard. 497compression is based on the JPEG standard.
487The current video format may be selected or queried from the user application 498The current video format may be selected or queried from the user application
488by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2 499by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2
489API specifications. 500API specifications.
@@ -573,4 +584,5 @@ order):
573- Mizuno Takafumi for the donation of a webcam; 584- Mizuno Takafumi for the donation of a webcam;
574- an "anonymous" donator (who didn't want his name to be revealed) for the 585- an "anonymous" donator (who didn't want his name to be revealed) for the
575 donation of a webcam. 586 donation of a webcam.
576- an anonymous donator for the donation of four webcams. 587- an anonymous donator for the donation of four webcams and two boards with ten
588 image sensors.
diff --git a/MAINTAINERS b/MAINTAINERS
index 8a2f2fd5403e..415011c9d84e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3606,7 +3606,7 @@ L: linux-usb-devel@lists.sourceforge.net
3606W: http://www.connecttech.com 3606W: http://www.connecttech.com
3607S: Supported 3607S: Supported
3608 3608
3609USB SN9C10x DRIVER 3609USB SN9C1xx DRIVER
3610P: Luca Risolia 3610P: Luca Risolia
3611M: luca.risolia@studio.unibo.it 3611M: luca.risolia@studio.unibo.it
3612L: linux-usb-devel@lists.sourceforge.net 3612L: linux-usb-devel@lists.sourceforge.net
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..f09caf2b6e75 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
@@ -485,18 +486,43 @@ static size_t sn9c102_sof_length(struct sn9c102_device* cam)
485static void* 486static void*
486sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) 487sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
487{ 488{
488 char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; 489 const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
489 size_t soflen = 0, i; 490 const char *m = mem;
491 size_t soflen = 0, i, j;
490 492
491 soflen = sn9c102_sof_length(cam); 493 soflen = sn9c102_sof_length(cam);
492 494
493 for (i = 0; (len >= soflen) && (i <= len - soflen); i++) 495 for (i = 0; i < len; i++) {
494 if (!memcmp(mem + i, sof_header, sizeof(sof_header))) { 496 size_t b;
495 memcpy(cam->sof_header, mem + i, 497
496 sizeof(sn9c102_sof_header_t)); 498 /* Read the variable part of the header */
497 /* Skip the header */ 499 if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
498 return mem + i + soflen; 500 cam->sof.header[cam->sof.bytesread] = *(m+i);
501 if (++cam->sof.bytesread == soflen) {
502 cam->sof.bytesread = 0;
503 return mem + i;
504 }
505 continue;
506 }
507
508 /* Search for the SOF marker (fixed part) in the header */
509 for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
510 if (unlikely(i+j) == len)
511 return NULL;
512 if (*(m+i+j) == marker[cam->sof.bytesread]) {
513 cam->sof.header[cam->sof.bytesread] = *(m+i+j);
514 if (++cam->sof.bytesread == sizeof(marker)) {
515 PDBGG("Bytes to analyze: %zd. SOF "
516 "starts at byte #%zd", len, i);
517 i += j+1;
518 break;
519 }
520 } else {
521 cam->sof.bytesread = 0;
522 break;
499 } 523 }
524 }
525 }
500 526
501 return NULL; 527 return NULL;
502} 528}
@@ -513,10 +539,16 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
513 }; 539 };
514 size_t i, j; 540 size_t i, j;
515 541
542 /* The EOF header does not exist in compressed data */
516 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || 543 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
517 cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) 544 cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
518 return NULL; /* EOF header does not exist in compressed data */ 545 return NULL;
519 546
547 /*
548 The EOF header might cross the packet boundary, but this is not a
549 problem, since the end of a frame is determined by checking its size
550 in the first place.
551 */
520 for (i = 0; (len >= 4) && (i <= len - 4); i++) 552 for (i = 0; (len >= 4) && (i <= len - 4); i++)
521 for (j = 0; j < ARRAY_SIZE(eof_header); j++) 553 for (j = 0; j < ARRAY_SIZE(eof_header); j++)
522 if (!memcmp(mem + i, eof_header[j], 4)) 554 if (!memcmp(mem + i, eof_header[j], 4))
@@ -639,6 +671,7 @@ static void sn9c102_urb_complete(struct urb *urb)
639 cam->stream = STREAM_OFF; 671 cam->stream = STREAM_OFF;
640 if ((*f)) 672 if ((*f))
641 (*f)->state = F_QUEUED; 673 (*f)->state = F_QUEUED;
674 cam->sof.bytesread = 0;
642 DBG(3, "Stream interrupted by application"); 675 DBG(3, "Stream interrupted by application");
643 wake_up(&cam->wait_stream); 676 wake_up(&cam->wait_stream);
644 } 677 }
@@ -676,6 +709,7 @@ static void sn9c102_urb_complete(struct urb *urb)
676 if (status) { 709 if (status) {
677 DBG(3, "Error in isochronous frame"); 710 DBG(3, "Error in isochronous frame");
678 (*f)->state = F_ERROR; 711 (*f)->state = F_ERROR;
712 cam->sof.bytesread = 0;
679 continue; 713 continue;
680 } 714 }
681 715
@@ -692,13 +726,13 @@ end_of_frame:
692 if (eof) 726 if (eof)
693 img = (eof > pos) ? eof - pos - 1 : 0; 727 img = (eof > pos) ? eof - pos - 1 : 0;
694 728
695 if ((*f)->buf.bytesused+img > imagesize) { 729 if ((*f)->buf.bytesused + img > imagesize) {
696 u32 b; 730 u32 b;
697 b = (*f)->buf.bytesused + img - 731 b = (*f)->buf.bytesused + img -
698 imagesize; 732 imagesize;
699 img = imagesize - (*f)->buf.bytesused; 733 img = imagesize - (*f)->buf.bytesused;
700 DBG(3, "Expected EOF not found: " 734 PDBGG("Expected EOF not found: video "
701 "video frame cut"); 735 "frame cut");
702 if (eof) 736 if (eof)
703 DBG(3, "Exceeded limit: +%u " 737 DBG(3, "Exceeded limit: +%u "
704 "bytes", (unsigned)(b)); 738 "bytes", (unsigned)(b));
@@ -719,11 +753,6 @@ end_of_frame:
719 V4L2_PIX_FMT_JPEG) && eof)) { 753 V4L2_PIX_FMT_JPEG) && eof)) {
720 u32 b; 754 u32 b;
721 755
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; 756 b = (*f)->buf.bytesused;
728 (*f)->state = F_DONE; 757 (*f)->state = F_DONE;
729 (*f)->buf.sequence= ++cam->frame_count; 758 (*f)->buf.sequence= ++cam->frame_count;
@@ -741,7 +770,7 @@ end_of_frame:
741 spin_unlock(&cam->queue_lock); 770 spin_unlock(&cam->queue_lock);
742 771
743 memcpy(cam->sysfs.frame_header, 772 memcpy(cam->sysfs.frame_header,
744 cam->sof_header, soflen); 773 cam->sof.header, soflen);
745 774
746 DBG(3, "Video frame captured: %lu " 775 DBG(3, "Video frame captured: %lu "
747 "bytes", (unsigned long)(b)); 776 "bytes", (unsigned long)(b));
@@ -791,7 +820,13 @@ start_of_frame:
791 V4L2_PIX_FMT_SN9C10X || 820 V4L2_PIX_FMT_SN9C10X ||
792 cam->sensor.pix_format.pixelformat == 821 cam->sensor.pix_format.pixelformat ==
793 V4L2_PIX_FMT_JPEG) { 822 V4L2_PIX_FMT_JPEG) {
794 eof = sof - soflen; 823 if (sof - pos >= soflen) {
824 eof = sof - soflen;
825 } else { /* remove header */
826 eof = pos;
827 (*f)->buf.bytesused -=
828 (soflen - (sof - pos));
829 }
795 goto end_of_frame; 830 goto end_of_frame;
796 } else { 831 } else {
797 DBG(3, "SOF before expected EOF after " 832 DBG(3, "SOF before expected EOF after "
@@ -878,6 +913,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
878 } 913 }
879 914
880 cam->frame_current = NULL; 915 cam->frame_current = NULL;
916 cam->sof.bytesread = 0;
881 917
882 for (i = 0; i < SN9C102_URBS; i++) { 918 for (i = 0; i < SN9C102_URBS; i++) {
883 err = usb_submit_urb(cam->urb[i], GFP_KERNEL); 919 err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
@@ -959,9 +995,9 @@ static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)
959 995
960 if (len < 6) { 996 if (len < 6) {
961 strncpy(str, buff, len); 997 strncpy(str, buff, len);
962 str[len+1] = '\0'; 998 str[len] = '\0';
963 } else { 999 } else {
964 strncpy(str, buff, 4); 1000 strncpy(str, buff, 6);
965 str[6] = '\0'; 1001 str[6] = '\0';
966 } 1002 }
967 1003
@@ -1062,7 +1098,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
1062 1098
1063 count = sprintf(buf, "%d\n", val); 1099 count = sprintf(buf, "%d\n", val);
1064 1100
1065 DBG(3, "Read bytes: %zd", count); 1101 DBG(3, "Read bytes: %zd, value: %d", count, val);
1066 1102
1067 mutex_unlock(&sn9c102_sysfs_lock); 1103 mutex_unlock(&sn9c102_sysfs_lock);
1068 1104
@@ -1197,7 +1233,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
1197 1233
1198 count = sprintf(buf, "%d\n", val); 1234 count = sprintf(buf, "%d\n", val);
1199 1235
1200 DBG(3, "Read bytes: %zd", count); 1236 DBG(3, "Read bytes: %zd, value: %d", count, val);
1201 1237
1202 mutex_unlock(&sn9c102_sysfs_lock); 1238 mutex_unlock(&sn9c102_sysfs_lock);
1203 1239
@@ -1477,10 +1513,10 @@ sn9c102_set_compression(struct sn9c102_device* cam,
1477 case BRIDGE_SN9C101: 1513 case BRIDGE_SN9C101:
1478 case BRIDGE_SN9C102: 1514 case BRIDGE_SN9C102:
1479 case BRIDGE_SN9C103: 1515 case BRIDGE_SN9C103:
1480 if (compression->quality == 0) 1516 if (compression->quality == 0)
1481 err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 1517 err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
1482 0x17); 1518 0x17);
1483 else if (compression->quality == 1) 1519 else if (compression->quality == 1)
1484 err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 1520 err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
1485 0x17); 1521 0x17);
1486 break; 1522 break;
@@ -1489,10 +1525,10 @@ sn9c102_set_compression(struct sn9c102_device* cam,
1489 if (compression->quality == 0) { 1525 if (compression->quality == 0) {
1490 for (i = 0; i <= 63; i++) { 1526 for (i = 0; i <= 63; i++) {
1491 err += sn9c102_write_reg(cam, 1527 err += sn9c102_write_reg(cam,
1492 SN9C102_Y_QTABLE0[i], 1528 SN9C102_Y_QTABLE1[i],
1493 0x100 + i); 1529 0x100 + i);
1494 err += sn9c102_write_reg(cam, 1530 err += sn9c102_write_reg(cam,
1495 SN9C102_UV_QTABLE0[i], 1531 SN9C102_UV_QTABLE1[i],
1496 0x140 + i); 1532 0x140 + i);
1497 } 1533 }
1498 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf, 1534 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
@@ -1597,9 +1633,13 @@ static int sn9c102_init(struct sn9c102_device* cam)
1597 if (cam->bridge == BRIDGE_SN9C101 || 1633 if (cam->bridge == BRIDGE_SN9C101 ||
1598 cam->bridge == BRIDGE_SN9C102 || 1634 cam->bridge == BRIDGE_SN9C102 ||
1599 cam->bridge == BRIDGE_SN9C103) { 1635 cam->bridge == BRIDGE_SN9C103) {
1636 if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
1637 s->pix_format.pixelformat= V4L2_PIX_FMT_SBGGR8;
1600 cam->compression.quality = cam->reg[0x17] & 0x01 ? 1638 cam->compression.quality = cam->reg[0x17] & 0x01 ?
1601 0 : 1; 1639 0 : 1;
1602 } else { 1640 } else {
1641 if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
1642 s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
1603 cam->compression.quality = cam->reg[0x18] & 0x40 ? 1643 cam->compression.quality = cam->reg[0x18] & 0x40 ?
1604 0 : 1; 1644 0 : 1;
1605 err += sn9c102_set_compression(cam, &cam->compression); 1645 err += sn9c102_set_compression(cam, &cam->compression);
@@ -1805,7 +1845,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 " 1845 DBG(3, "Close and open the device again to choose "
1806 "the read method"); 1846 "the read method");
1807 mutex_unlock(&cam->fileop_mutex); 1847 mutex_unlock(&cam->fileop_mutex);
1808 return -EINVAL; 1848 return -EBUSY;
1809 } 1849 }
1810 1850
1811 if (cam->io == IO_NONE) { 1851 if (cam->io == IO_NONE) {
@@ -1845,16 +1885,16 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
1845 return err; 1885 return err;
1846 } 1886 }
1847 } else { 1887 } else {
1848 timeout = wait_event_interruptible_timeout 1888 timeout = wait_event_interruptible_timeout
1849 ( cam->wait_frame, 1889 ( cam->wait_frame,
1850 (!list_empty(&cam->outqueue)) || 1890 (!list_empty(&cam->outqueue)) ||
1851 (cam->state & DEV_DISCONNECTED) || 1891 (cam->state & DEV_DISCONNECTED) ||
1852 (cam->state & DEV_MISCONFIGURED), 1892 (cam->state & DEV_MISCONFIGURED),
1853 cam->module_param.frame_timeout * 1893 cam->module_param.frame_timeout *
1854 1000 * msecs_to_jiffies(1) ); 1894 1000 * msecs_to_jiffies(1) );
1855 if (timeout < 0) { 1895 if (timeout < 0) {
1856 mutex_unlock(&cam->fileop_mutex); 1896 mutex_unlock(&cam->fileop_mutex);
1857 return timeout; 1897 return timeout;
1858 } else if (timeout == 0 && 1898 } else if (timeout == 0 &&
1859 !(cam->state & DEV_DISCONNECTED)) { 1899 !(cam->state & DEV_DISCONNECTED)) {
1860 DBG(1, "Video frame timeout elapsed"); 1900 DBG(1, "Video frame timeout elapsed");
@@ -2001,7 +2041,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
2001 return -EIO; 2041 return -EIO;
2002 } 2042 }
2003 2043
2004 if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || 2044 if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
2045 mutex_unlock(&cam->fileop_mutex);
2046 return -EACCES;
2047 }
2048
2049 if (cam->io != IO_MMAP ||
2005 size != PAGE_ALIGN(cam->frame[0].buf.length)) { 2050 size != PAGE_ALIGN(cam->frame[0].buf.length)) {
2006 mutex_unlock(&cam->fileop_mutex); 2051 mutex_unlock(&cam->fileop_mutex);
2007 return -EINVAL; 2052 return -EINVAL;
@@ -2267,7 +2312,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
2267 if (cam->frame[i].vma_use_count) { 2312 if (cam->frame[i].vma_use_count) {
2268 DBG(3, "VIDIOC_S_CROP failed. " 2313 DBG(3, "VIDIOC_S_CROP failed. "
2269 "Unmap the buffers first."); 2314 "Unmap the buffers first.");
2270 return -EINVAL; 2315 return -EBUSY;
2271 } 2316 }
2272 2317
2273 /* Preserve R,G or B origin */ 2318 /* Preserve R,G or B origin */
@@ -2410,8 +2455,8 @@ sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
2410 case BRIDGE_SN9C101: 2455 case BRIDGE_SN9C101:
2411 case BRIDGE_SN9C102: 2456 case BRIDGE_SN9C102:
2412 case BRIDGE_SN9C103: 2457 case BRIDGE_SN9C103:
2413 strcpy(fmtd.description, "compressed"); 2458 strcpy(fmtd.description, "compressed");
2414 fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; 2459 fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
2415 break; 2460 break;
2416 case BRIDGE_SN9C105: 2461 case BRIDGE_SN9C105:
2417 case BRIDGE_SN9C120: 2462 case BRIDGE_SN9C120:
@@ -2445,8 +2490,10 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
2445 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 2490 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2446 return -EINVAL; 2491 return -EINVAL;
2447 2492
2448 pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X || 2493 pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
2449 pfmt->pixelformat==V4L2_PIX_FMT_JPEG) 2494 V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
2495 pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
2496 pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
2450 ? 0 : (pfmt->width * pfmt->priv) / 8; 2497 ? 0 : (pfmt->width * pfmt->priv) / 8;
2451 pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); 2498 pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
2452 pfmt->field = V4L2_FIELD_NONE; 2499 pfmt->field = V4L2_FIELD_NONE;
@@ -2521,9 +2568,9 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
2521 case BRIDGE_SN9C101: 2568 case BRIDGE_SN9C101:
2522 case BRIDGE_SN9C102: 2569 case BRIDGE_SN9C102:
2523 case BRIDGE_SN9C103: 2570 case BRIDGE_SN9C103:
2524 if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && 2571 if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
2525 pix->pixelformat != V4L2_PIX_FMT_SBGGR8) 2572 pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
2526 pix->pixelformat = pfmt->pixelformat; 2573 pix->pixelformat = pfmt->pixelformat;
2527 break; 2574 break;
2528 case BRIDGE_SN9C105: 2575 case BRIDGE_SN9C105:
2529 case BRIDGE_SN9C120: 2576 case BRIDGE_SN9C120:
@@ -2533,7 +2580,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
2533 break; 2580 break;
2534 } 2581 }
2535 pix->priv = pfmt->priv; /* bpp */ 2582 pix->priv = pfmt->priv; /* bpp */
2536 pix->colorspace = pfmt->colorspace; 2583 pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
2584 V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
2537 pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || 2585 pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
2538 pix->pixelformat == V4L2_PIX_FMT_JPEG) 2586 pix->pixelformat == V4L2_PIX_FMT_JPEG)
2539 ? 0 : (pix->width * pix->priv) / 8; 2587 ? 0 : (pix->width * pix->priv) / 8;
@@ -2551,7 +2599,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
2551 if (cam->frame[i].vma_use_count) { 2599 if (cam->frame[i].vma_use_count) {
2552 DBG(3, "VIDIOC_S_FMT failed. Unmap the " 2600 DBG(3, "VIDIOC_S_FMT failed. Unmap the "
2553 "buffers first."); 2601 "buffers first.");
2554 return -EINVAL; 2602 return -EBUSY;
2555 } 2603 }
2556 2604
2557 if (cam->stream == STREAM_ON) 2605 if (cam->stream == STREAM_ON)
@@ -2666,14 +2714,14 @@ sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
2666 if (cam->io == IO_READ) { 2714 if (cam->io == IO_READ) {
2667 DBG(3, "Close and open the device again to choose the mmap " 2715 DBG(3, "Close and open the device again to choose the mmap "
2668 "I/O method"); 2716 "I/O method");
2669 return -EINVAL; 2717 return -EBUSY;
2670 } 2718 }
2671 2719
2672 for (i = 0; i < cam->nbuffers; i++) 2720 for (i = 0; i < cam->nbuffers; i++)
2673 if (cam->frame[i].vma_use_count) { 2721 if (cam->frame[i].vma_use_count) {
2674 DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are " 2722 DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
2675 "still mapped."); 2723 "still mapped.");
2676 return -EINVAL; 2724 return -EBUSY;
2677 } 2725 }
2678 2726
2679 if (cam->stream == STREAM_ON) 2727 if (cam->stream == STREAM_ON)
@@ -2785,15 +2833,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
2785 if (err) 2833 if (err)
2786 return err; 2834 return err;
2787 } else { 2835 } else {
2788 timeout = wait_event_interruptible_timeout 2836 timeout = wait_event_interruptible_timeout
2789 ( cam->wait_frame, 2837 ( cam->wait_frame,
2790 (!list_empty(&cam->outqueue)) || 2838 (!list_empty(&cam->outqueue)) ||
2791 (cam->state & DEV_DISCONNECTED) || 2839 (cam->state & DEV_DISCONNECTED) ||
2792 (cam->state & DEV_MISCONFIGURED), 2840 (cam->state & DEV_MISCONFIGURED),
2793 cam->module_param.frame_timeout * 2841 cam->module_param.frame_timeout *
2794 1000 * msecs_to_jiffies(1) ); 2842 1000 * msecs_to_jiffies(1) );
2795 if (timeout < 0) 2843 if (timeout < 0)
2796 return timeout; 2844 return timeout;
2797 else if (timeout == 0 && 2845 else if (timeout == 0 &&
2798 !(cam->state & DEV_DISCONNECTED)) { 2846 !(cam->state & DEV_DISCONNECTED)) {
2799 DBG(1, "Video frame timeout elapsed"); 2847 DBG(1, "Video frame timeout elapsed");
@@ -2837,9 +2885,6 @@ sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
2837 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) 2885 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
2838 return -EINVAL; 2886 return -EINVAL;
2839 2887
2840 if (list_empty(&cam->inqueue))
2841 return -EINVAL;
2842
2843 cam->stream = STREAM_ON; 2888 cam->stream = STREAM_ON;
2844 2889
2845 DBG(3, "Stream on"); 2890 DBG(3, "Stream on");
@@ -3166,8 +3211,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3166 3211
3167 r = sn9c102_read_reg(cam, 0x00); 3212 r = sn9c102_read_reg(cam, 0x00);
3168 if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) { 3213 if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
3169 DBG(1, "Sorry, this is not a SN9C1xx based camera " 3214 DBG(1, "Sorry, this is not a SN9C1xx-based camera "
3170 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3215 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3171 err = -ENODEV; 3216 err = -ENODEV;
3172 goto fail; 3217 goto fail;
3173 } 3218 }
@@ -3177,19 +3222,19 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3177 case BRIDGE_SN9C101: 3222 case BRIDGE_SN9C101:
3178 case BRIDGE_SN9C102: 3223 case BRIDGE_SN9C102:
3179 DBG(2, "SN9C10[12] PC Camera Controller detected " 3224 DBG(2, "SN9C10[12] PC Camera Controller detected "
3180 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3225 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3181 break; 3226 break;
3182 case BRIDGE_SN9C103: 3227 case BRIDGE_SN9C103:
3183 DBG(2, "SN9C103 PC Camera Controller detected " 3228 DBG(2, "SN9C103 PC Camera Controller detected "
3184 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3229 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3185 break; 3230 break;
3186 case BRIDGE_SN9C105: 3231 case BRIDGE_SN9C105:
3187 DBG(2, "SN9C105 PC Camera Controller detected " 3232 DBG(2, "SN9C105 PC Camera Controller detected "
3188 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3233 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3189 break; 3234 break;
3190 case BRIDGE_SN9C120: 3235 case BRIDGE_SN9C120:
3191 DBG(2, "SN9C120 PC Camera Controller detected " 3236 DBG(2, "SN9C120 PC Camera Controller detected "
3192 "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3237 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3193 break; 3238 break;
3194 } 3239 }
3195 3240
@@ -3260,6 +3305,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3260 "device controlling. Error #%d", err); 3305 "device controlling. Error #%d", err);
3261#else 3306#else
3262 DBG(2, "Optional device control through 'sysfs' interface disabled"); 3307 DBG(2, "Optional device control through 'sysfs' interface disabled");
3308 DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
3309 "configuration option to enable it.");
3263#endif 3310#endif
3264 3311
3265 usb_set_intfdata(intf, cam); 3312 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..9b2e2d68c739 100644
--- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
@@ -22,9 +22,6 @@
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 = 0;
@@ -153,7 +150,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam,
153static struct sn9c102_sensor hv7131d = { 150static struct sn9c102_sensor hv7131d = {
154 .name = "HV7131D", 151 .name = "HV7131D",
155 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 152 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
156 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 153 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
157 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 154 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
158 .frequency = SN9C102_I2C_100KHZ, 155 .frequency = SN9C102_I2C_100KHZ,
159 .interface = SN9C102_I2C_2WIRES, 156 .interface = SN9C102_I2C_2WIRES,
@@ -263,7 +260,7 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
263 if (r0 < 0 || r1 < 0) 260 if (r0 < 0 || r1 < 0)
264 return -EIO; 261 return -EIO;
265 262
266 if (r0 != 0x00 && r1 != 0x04) 263 if (r0 != 0x00 || r1 != 0x04)
267 return -ENODEV; 264 return -ENODEV;
268 265
269 sn9c102_attach_sensor(cam, &hv7131d); 266 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..c4a3e3991e88
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_hv7131r.c
@@ -0,0 +1,458 @@
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_reg(cam, 0x00, 0x03);
32 err += sn9c102_write_reg(cam, 0x1a, 0x04);
33 err += sn9c102_write_reg(cam, 0x20, 0x05);
34 err += sn9c102_write_reg(cam, 0x20, 0x06);
35 err += sn9c102_write_reg(cam, 0x03, 0x10);
36 err += sn9c102_write_reg(cam, 0x00, 0x14);
37 err += sn9c102_write_reg(cam, 0x60, 0x17);
38 err += sn9c102_write_reg(cam, 0x0a, 0x18);
39 err += sn9c102_write_reg(cam, 0xf0, 0x19);
40 err += sn9c102_write_reg(cam, 0x1d, 0x1a);
41 err += sn9c102_write_reg(cam, 0x10, 0x1b);
42 err += sn9c102_write_reg(cam, 0x02, 0x1c);
43 err += sn9c102_write_reg(cam, 0x03, 0x1d);
44 err += sn9c102_write_reg(cam, 0x0f, 0x1e);
45 err += sn9c102_write_reg(cam, 0x0c, 0x1f);
46 err += sn9c102_write_reg(cam, 0x00, 0x20);
47 err += sn9c102_write_reg(cam, 0x10, 0x21);
48 err += sn9c102_write_reg(cam, 0x20, 0x22);
49 err += sn9c102_write_reg(cam, 0x30, 0x23);
50 err += sn9c102_write_reg(cam, 0x40, 0x24);
51 err += sn9c102_write_reg(cam, 0x50, 0x25);
52 err += sn9c102_write_reg(cam, 0x60, 0x26);
53 err += sn9c102_write_reg(cam, 0x70, 0x27);
54 err += sn9c102_write_reg(cam, 0x80, 0x28);
55 err += sn9c102_write_reg(cam, 0x90, 0x29);
56 err += sn9c102_write_reg(cam, 0xa0, 0x2a);
57 err += sn9c102_write_reg(cam, 0xb0, 0x2b);
58 err += sn9c102_write_reg(cam, 0xc0, 0x2c);
59 err += sn9c102_write_reg(cam, 0xd0, 0x2d);
60 err += sn9c102_write_reg(cam, 0xe0, 0x2e);
61 err += sn9c102_write_reg(cam, 0xf0, 0x2f);
62 err += sn9c102_write_reg(cam, 0xff, 0x30);
63 break;
64 case BRIDGE_SN9C105:
65 case BRIDGE_SN9C120:
66 err += sn9c102_write_reg(cam, 0x44, 0x01);
67 err += sn9c102_write_reg(cam, 0x40, 0x02);
68 err += sn9c102_write_reg(cam, 0x00, 0x03);
69 err += sn9c102_write_reg(cam, 0x1a, 0x04);
70 err += sn9c102_write_reg(cam, 0x44, 0x05);
71 err += sn9c102_write_reg(cam, 0x3e, 0x06);
72 err += sn9c102_write_reg(cam, 0x1a, 0x07);
73 err += sn9c102_write_reg(cam, 0x03, 0x10);
74 err += sn9c102_write_reg(cam, 0x08, 0x14);
75 err += sn9c102_write_reg(cam, 0xa3, 0x17);
76 err += sn9c102_write_reg(cam, 0x4b, 0x18);
77 err += sn9c102_write_reg(cam, 0x00, 0x19);
78 err += sn9c102_write_reg(cam, 0x1d, 0x1a);
79 err += sn9c102_write_reg(cam, 0x10, 0x1b);
80 err += sn9c102_write_reg(cam, 0x02, 0x1c);
81 err += sn9c102_write_reg(cam, 0x03, 0x1d);
82 err += sn9c102_write_reg(cam, 0x0f, 0x1e);
83 err += sn9c102_write_reg(cam, 0x0c, 0x1f);
84 err += sn9c102_write_reg(cam, 0x00, 0x20);
85 err += sn9c102_write_reg(cam, 0x29, 0x21);
86 err += sn9c102_write_reg(cam, 0x40, 0x22);
87 err += sn9c102_write_reg(cam, 0x54, 0x23);
88 err += sn9c102_write_reg(cam, 0x66, 0x24);
89 err += sn9c102_write_reg(cam, 0x76, 0x25);
90 err += sn9c102_write_reg(cam, 0x85, 0x26);
91 err += sn9c102_write_reg(cam, 0x94, 0x27);
92 err += sn9c102_write_reg(cam, 0xa1, 0x28);
93 err += sn9c102_write_reg(cam, 0xae, 0x29);
94 err += sn9c102_write_reg(cam, 0xbb, 0x2a);
95 err += sn9c102_write_reg(cam, 0xc7, 0x2b);
96 err += sn9c102_write_reg(cam, 0xd3, 0x2c);
97 err += sn9c102_write_reg(cam, 0xde, 0x2d);
98 err += sn9c102_write_reg(cam, 0xea, 0x2e);
99 err += sn9c102_write_reg(cam, 0xf4, 0x2f);
100 err += sn9c102_write_reg(cam, 0xff, 0x30);
101 err += sn9c102_write_reg(cam, 0x00, 0x3F);
102 err += sn9c102_write_reg(cam, 0xC7, 0x40);
103 err += sn9c102_write_reg(cam, 0x01, 0x41);
104 err += sn9c102_write_reg(cam, 0x44, 0x42);
105 err += sn9c102_write_reg(cam, 0x00, 0x43);
106 err += sn9c102_write_reg(cam, 0x44, 0x44);
107 err += sn9c102_write_reg(cam, 0x00, 0x45);
108 err += sn9c102_write_reg(cam, 0x44, 0x46);
109 err += sn9c102_write_reg(cam, 0x00, 0x47);
110 err += sn9c102_write_reg(cam, 0xC7, 0x48);
111 err += sn9c102_write_reg(cam, 0x01, 0x49);
112 err += sn9c102_write_reg(cam, 0xC7, 0x4A);
113 err += sn9c102_write_reg(cam, 0x01, 0x4B);
114 err += sn9c102_write_reg(cam, 0xC7, 0x4C);
115 err += sn9c102_write_reg(cam, 0x01, 0x4D);
116 err += sn9c102_write_reg(cam, 0x44, 0x4E);
117 err += sn9c102_write_reg(cam, 0x00, 0x4F);
118 err += sn9c102_write_reg(cam, 0x44, 0x50);
119 err += sn9c102_write_reg(cam, 0x00, 0x51);
120 err += sn9c102_write_reg(cam, 0x44, 0x52);
121 err += sn9c102_write_reg(cam, 0x00, 0x53);
122 err += sn9c102_write_reg(cam, 0xC7, 0x54);
123 err += sn9c102_write_reg(cam, 0x01, 0x55);
124 err += sn9c102_write_reg(cam, 0xC7, 0x56);
125 err += sn9c102_write_reg(cam, 0x01, 0x57);
126 err += sn9c102_write_reg(cam, 0xC7, 0x58);
127 err += sn9c102_write_reg(cam, 0x01, 0x59);
128 err += sn9c102_write_reg(cam, 0x44, 0x5A);
129 err += sn9c102_write_reg(cam, 0x00, 0x5B);
130 err += sn9c102_write_reg(cam, 0x44, 0x5C);
131 err += sn9c102_write_reg(cam, 0x00, 0x5D);
132 err += sn9c102_write_reg(cam, 0x44, 0x5E);
133 err += sn9c102_write_reg(cam, 0x00, 0x5F);
134 err += sn9c102_write_reg(cam, 0xC7, 0x60);
135 err += sn9c102_write_reg(cam, 0x01, 0x61);
136 err += sn9c102_write_reg(cam, 0xC7, 0x62);
137 err += sn9c102_write_reg(cam, 0x01, 0x63);
138 err += sn9c102_write_reg(cam, 0xC7, 0x64);
139 err += sn9c102_write_reg(cam, 0x01, 0x65);
140 err += sn9c102_write_reg(cam, 0x44, 0x66);
141 err += sn9c102_write_reg(cam, 0x00, 0x67);
142 err += sn9c102_write_reg(cam, 0x44, 0x68);
143 err += sn9c102_write_reg(cam, 0x00, 0x69);
144 err += sn9c102_write_reg(cam, 0x44, 0x6A);
145 err += sn9c102_write_reg(cam, 0x00, 0x6B);
146 err += sn9c102_write_reg(cam, 0xC7, 0x6C);
147 err += sn9c102_write_reg(cam, 0x01, 0x6D);
148 err += sn9c102_write_reg(cam, 0xC7, 0x6E);
149 err += sn9c102_write_reg(cam, 0x01, 0x6F);
150 err += sn9c102_write_reg(cam, 0xC7, 0x70);
151 err += sn9c102_write_reg(cam, 0x01, 0x71);
152 err += sn9c102_write_reg(cam, 0x44, 0x72);
153 err += sn9c102_write_reg(cam, 0x00, 0x73);
154 err += sn9c102_write_reg(cam, 0x44, 0x74);
155 err += sn9c102_write_reg(cam, 0x00, 0x75);
156 err += sn9c102_write_reg(cam, 0x44, 0x76);
157 err += sn9c102_write_reg(cam, 0x00, 0x77);
158 err += sn9c102_write_reg(cam, 0xC7, 0x78);
159 err += sn9c102_write_reg(cam, 0x01, 0x79);
160 err += sn9c102_write_reg(cam, 0xC7, 0x7A);
161 err += sn9c102_write_reg(cam, 0x01, 0x7B);
162 err += sn9c102_write_reg(cam, 0xC7, 0x7C);
163 err += sn9c102_write_reg(cam, 0x01, 0x7D);
164 err += sn9c102_write_reg(cam, 0x44, 0x7E);
165 err += sn9c102_write_reg(cam, 0x00, 0x7F);
166 err += sn9c102_write_reg(cam, 0x14, 0x84);
167 err += sn9c102_write_reg(cam, 0x00, 0x85);
168 err += sn9c102_write_reg(cam, 0x27, 0x86);
169 err += sn9c102_write_reg(cam, 0x00, 0x87);
170 err += sn9c102_write_reg(cam, 0x07, 0x88);
171 err += sn9c102_write_reg(cam, 0x00, 0x89);
172 err += sn9c102_write_reg(cam, 0xEC, 0x8A);
173 err += sn9c102_write_reg(cam, 0x0f, 0x8B);
174 err += sn9c102_write_reg(cam, 0xD8, 0x8C);
175 err += sn9c102_write_reg(cam, 0x0f, 0x8D);
176 err += sn9c102_write_reg(cam, 0x3D, 0x8E);
177 err += sn9c102_write_reg(cam, 0x00, 0x8F);
178 err += sn9c102_write_reg(cam, 0x3D, 0x90);
179 err += sn9c102_write_reg(cam, 0x00, 0x91);
180 err += sn9c102_write_reg(cam, 0xCD, 0x92);
181 err += sn9c102_write_reg(cam, 0x0f, 0x93);
182 err += sn9c102_write_reg(cam, 0xf7, 0x94);
183 err += sn9c102_write_reg(cam, 0x0f, 0x95);
184 err += sn9c102_write_reg(cam, 0x0C, 0x96);
185 err += sn9c102_write_reg(cam, 0x00, 0x97);
186 err += sn9c102_write_reg(cam, 0x00, 0x98);
187 err += sn9c102_write_reg(cam, 0x66, 0x99);
188 err += sn9c102_write_reg(cam, 0x05, 0x9A);
189 err += sn9c102_write_reg(cam, 0x00, 0x9B);
190 err += sn9c102_write_reg(cam, 0x04, 0x9C);
191 err += sn9c102_write_reg(cam, 0x00, 0x9D);
192 err += sn9c102_write_reg(cam, 0x08, 0x9E);
193 err += sn9c102_write_reg(cam, 0x00, 0x9F);
194 err += sn9c102_write_reg(cam, 0x2D, 0xC0);
195 err += sn9c102_write_reg(cam, 0x2D, 0xC1);
196 err += sn9c102_write_reg(cam, 0x3A, 0xC2);
197 err += sn9c102_write_reg(cam, 0x05, 0xC3);
198 err += sn9c102_write_reg(cam, 0x04, 0xC4);
199 err += sn9c102_write_reg(cam, 0x3F, 0xC5);
200 err += sn9c102_write_reg(cam, 0x00, 0xC6);
201 err += sn9c102_write_reg(cam, 0x00, 0xC7);
202 err += sn9c102_write_reg(cam, 0x50, 0xC8);
203 err += sn9c102_write_reg(cam, 0x3C, 0xC9);
204 err += sn9c102_write_reg(cam, 0x28, 0xCA);
205 err += sn9c102_write_reg(cam, 0xD8, 0xCB);
206 err += sn9c102_write_reg(cam, 0x14, 0xCC);
207 err += sn9c102_write_reg(cam, 0xEC, 0xCD);
208 err += sn9c102_write_reg(cam, 0x32, 0xCE);
209 err += sn9c102_write_reg(cam, 0xDD, 0xCF);
210 err += sn9c102_write_reg(cam, 0x32, 0xD0);
211 err += sn9c102_write_reg(cam, 0xDD, 0xD1);
212 err += sn9c102_write_reg(cam, 0x6A, 0xD2);
213 err += sn9c102_write_reg(cam, 0x50, 0xD3);
214 err += sn9c102_write_reg(cam, 0x00, 0xD4);
215 err += sn9c102_write_reg(cam, 0x00, 0xD5);
216 err += sn9c102_write_reg(cam, 0x00, 0xD6);
217 break;
218 default:
219 break;
220 }
221
222 err += sn9c102_i2c_write(cam, 0x20, 0x00);
223 err += sn9c102_i2c_write(cam, 0x21, 0xd6);
224 err += sn9c102_i2c_write(cam, 0x25, 0x06);
225
226 return err;
227}
228
229
230static int hv7131r_get_ctrl(struct sn9c102_device* cam,
231 struct v4l2_control* ctrl)
232{
233 switch (ctrl->id) {
234 case V4L2_CID_GAIN:
235 if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
236 return -EIO;
237 return 0;
238 case V4L2_CID_RED_BALANCE:
239 if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
240 return -EIO;
241 ctrl->value = ctrl->value & 0x3f;
242 return 0;
243 case V4L2_CID_BLUE_BALANCE:
244 if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
245 return -EIO;
246 ctrl->value = ctrl->value & 0x3f;
247 return 0;
248 case SN9C102_V4L2_CID_GREEN_BALANCE:
249 if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
250 return -EIO;
251 ctrl->value = ctrl->value & 0x3f;
252 return 0;
253 case V4L2_CID_BLACK_LEVEL:
254 if ((ctrl->value = sn9c102_i2c_read(cam, 0x01)) < 0)
255 return -EIO;
256 ctrl->value = (ctrl->value & 0x08) ? 1 : 0;
257 return 0;
258 default:
259 return -EINVAL;
260 }
261}
262
263
264static int hv7131r_set_ctrl(struct sn9c102_device* cam,
265 const struct v4l2_control* ctrl)
266{
267 int err = 0;
268
269 switch (ctrl->id) {
270 case V4L2_CID_GAIN:
271 err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
272 break;
273 case V4L2_CID_RED_BALANCE:
274 err += sn9c102_i2c_write(cam, 0x31, ctrl->value);
275 break;
276 case V4L2_CID_BLUE_BALANCE:
277 err += sn9c102_i2c_write(cam, 0x33, ctrl->value);
278 break;
279 case SN9C102_V4L2_CID_GREEN_BALANCE:
280 err += sn9c102_i2c_write(cam, 0x32, ctrl->value);
281 break;
282 case V4L2_CID_BLACK_LEVEL:
283 {
284 int r = sn9c102_i2c_read(cam, 0x01);
285 if (r < 0)
286 return -EIO;
287 err += sn9c102_i2c_write(cam, 0x01,
288 (ctrl->value<<3) | (r&0xf7));
289 }
290 break;
291 default:
292 return -EINVAL;
293 }
294
295 return err ? -EIO : 0;
296}
297
298
299static int hv7131r_set_crop(struct sn9c102_device* cam,
300 const struct v4l2_rect* rect)
301{
302 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
303 int err = 0;
304 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
305 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
306
307 err += sn9c102_write_reg(cam, h_start, 0x12);
308 err += sn9c102_write_reg(cam, v_start, 0x13);
309
310 return err;
311}
312
313
314static int hv7131r_set_pix_format(struct sn9c102_device* cam,
315 const struct v4l2_pix_format* pix)
316{
317 int err = 0;
318
319 switch (sn9c102_get_bridge(cam)) {
320 case BRIDGE_SN9C103:
321 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
322 err += sn9c102_write_reg(cam, 0xa0, 0x19);
323 err += sn9c102_i2c_write(cam, 0x01, 0x04);
324 } else {
325 err += sn9c102_write_reg(cam, 0x30, 0x19);
326 err += sn9c102_i2c_write(cam, 0x01, 0x04);
327 }
328 break;
329 case BRIDGE_SN9C105:
330 case BRIDGE_SN9C120:
331 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
332 err += sn9c102_write_reg(cam, 0xa5, 0x17);
333 err += sn9c102_i2c_write(cam, 0x01, 0x24);
334 } else {
335 err += sn9c102_write_reg(cam, 0xa3, 0x17);
336 err += sn9c102_i2c_write(cam, 0x01, 0x04);
337 }
338 break;
339 default:
340 break;
341 }
342
343 return err;
344}
345
346
347static struct sn9c102_sensor hv7131r = {
348 .name = "HV7131R",
349 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
350 .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
351 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
352 .frequency = SN9C102_I2C_100KHZ,
353 .interface = SN9C102_I2C_2WIRES,
354 .i2c_slave_id = 0x11,
355 .init = &hv7131r_init,
356 .qctrl = {
357 {
358 .id = V4L2_CID_GAIN,
359 .type = V4L2_CTRL_TYPE_INTEGER,
360 .name = "global gain",
361 .minimum = 0x00,
362 .maximum = 0xff,
363 .step = 0x01,
364 .default_value = 0x40,
365 .flags = 0,
366 },
367 {
368 .id = V4L2_CID_RED_BALANCE,
369 .type = V4L2_CTRL_TYPE_INTEGER,
370 .name = "red balance",
371 .minimum = 0x00,
372 .maximum = 0x3f,
373 .step = 0x01,
374 .default_value = 0x08,
375 .flags = 0,
376 },
377 {
378 .id = V4L2_CID_BLUE_BALANCE,
379 .type = V4L2_CTRL_TYPE_INTEGER,
380 .name = "blue balance",
381 .minimum = 0x00,
382 .maximum = 0x3f,
383 .step = 0x01,
384 .default_value = 0x1a,
385 .flags = 0,
386 },
387 {
388 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
389 .type = V4L2_CTRL_TYPE_INTEGER,
390 .name = "green balance",
391 .minimum = 0x00,
392 .maximum = 0x3f,
393 .step = 0x01,
394 .default_value = 0x2f,
395 .flags = 0,
396 },
397 {
398 .id = V4L2_CID_BLACK_LEVEL,
399 .type = V4L2_CTRL_TYPE_BOOLEAN,
400 .name = "auto black level compensation",
401 .minimum = 0x00,
402 .maximum = 0x01,
403 .step = 0x01,
404 .default_value = 0x00,
405 .flags = 0,
406 },
407 },
408 .get_ctrl = &hv7131r_get_ctrl,
409 .set_ctrl = &hv7131r_set_ctrl,
410 .cropcap = {
411 .bounds = {
412 .left = 0,
413 .top = 0,
414 .width = 640,
415 .height = 480,
416 },
417 .defrect = {
418 .left = 0,
419 .top = 0,
420 .width = 640,
421 .height = 480,
422 },
423 },
424 .set_crop = &hv7131r_set_crop,
425 .pix_format = {
426 .width = 640,
427 .height = 480,
428 .pixelformat = V4L2_PIX_FMT_SBGGR8,
429 .priv = 8,
430 },
431 .set_pix_format = &hv7131r_set_pix_format
432};
433
434
435int sn9c102_probe_hv7131r(struct sn9c102_device* cam)
436{
437 int devid, err = 0;
438
439 err += sn9c102_write_reg(cam, 0x09, 0x01);
440 err += sn9c102_write_reg(cam, 0x44, 0x02);
441 err += sn9c102_write_reg(cam, 0x34, 0x01);
442 err += sn9c102_write_reg(cam, 0x20, 0x17);
443 err += sn9c102_write_reg(cam, 0x34, 0x01);
444 err += sn9c102_write_reg(cam, 0x46, 0x01);
445 if (err)
446 return -EIO;
447
448 devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
449 if (devid < 0)
450 return -EIO;
451
452 if (devid != 0x02)
453 return -ENODEV;
454
455 sn9c102_attach_sensor(cam, &hv7131r);
456
457 return 0;
458}
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c
index a33d1bc10f90..441156d61106 100644
--- a/drivers/media/video/sn9c102/sn9c102_mi0343.c
+++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c
@@ -22,12 +22,9 @@
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_reg(cam, 0x00, 0x10);
@@ -38,20 +35,20 @@ static int mi0343_init(struct sn9c102_device* cam)
38 err += sn9c102_write_reg(cam, 0x07, 0x18); 35 err += sn9c102_write_reg(cam, 0x07, 0x18);
39 err += sn9c102_write_reg(cam, 0xa0, 0x19); 36 err += sn9c102_write_reg(cam, 0xa0, 0x19);
40 37
41 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 38 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
42 0x0d, 0x00, 0x01, 0, 0); 39 0x00, 0x01, 0, 0);
43 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 40 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
44 0x0d, 0x00, 0x00, 0, 0); 41 0x00, 0x00, 0, 0);
45 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 42 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
46 0x03, 0x01, 0xe1, 0, 0); 43 0x01, 0xe1, 0, 0);
47 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 44 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
48 0x04, 0x02, 0x81, 0, 0); 45 0x02, 0x81, 0, 0);
49 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 46 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
50 0x05, 0x00, 0x17, 0, 0); 47 0x00, 0x17, 0, 0);
51 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 48 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
52 0x06, 0x00, 0x11, 0, 0); 49 0x00, 0x11, 0, 0);
53 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id, 50 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
54 0x62, 0x04, 0x9a, 0, 0); 51 0x04, 0x9a, 0, 0);
55 52
56 return err; 53 return err;
57} 54}
@@ -60,43 +57,46 @@ static int mi0343_init(struct sn9c102_device* cam)
60static int mi0343_get_ctrl(struct sn9c102_device* cam, 57static int mi0343_get_ctrl(struct sn9c102_device* cam,
61 struct v4l2_control* ctrl) 58 struct v4l2_control* ctrl)
62{ 59{
60 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
61 u8 data[5+1];
62
63 switch (ctrl->id) { 63 switch (ctrl->id) {
64 case V4L2_CID_EXPOSURE: 64 case V4L2_CID_EXPOSURE:
65 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 65 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
66 0x09, 2+1, mi0343_i2c_data) < 0) 66 2+1, data) < 0)
67 return -EIO; 67 return -EIO;
68 ctrl->value = mi0343_i2c_data[2]; 68 ctrl->value = data[2];
69 return 0; 69 return 0;
70 case V4L2_CID_GAIN: 70 case V4L2_CID_GAIN:
71 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 71 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
72 0x35, 2+1, mi0343_i2c_data) < 0) 72 2+1, data) < 0)
73 return -EIO; 73 return -EIO;
74 break; 74 break;
75 case V4L2_CID_HFLIP: 75 case V4L2_CID_HFLIP:
76 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 76 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
77 0x20, 2+1, mi0343_i2c_data) < 0) 77 2+1, data) < 0)
78 return -EIO; 78 return -EIO;
79 ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0; 79 ctrl->value = data[3] & 0x20 ? 1 : 0;
80 return 0; 80 return 0;
81 case V4L2_CID_VFLIP: 81 case V4L2_CID_VFLIP:
82 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 82 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
83 0x20, 2+1, mi0343_i2c_data) < 0) 83 2+1, data) < 0)
84 return -EIO; 84 return -EIO;
85 ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0; 85 ctrl->value = data[3] & 0x80 ? 1 : 0;
86 return 0; 86 return 0;
87 case V4L2_CID_RED_BALANCE: 87 case V4L2_CID_RED_BALANCE:
88 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 88 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
89 0x2d, 2+1, mi0343_i2c_data) < 0) 89 2+1, data) < 0)
90 return -EIO; 90 return -EIO;
91 break; 91 break;
92 case V4L2_CID_BLUE_BALANCE: 92 case V4L2_CID_BLUE_BALANCE:
93 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 93 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
94 0x2c, 2+1, mi0343_i2c_data) < 0) 94 2+1, data) < 0)
95 return -EIO; 95 return -EIO;
96 break; 96 break;
97 case SN9C102_V4L2_CID_GREEN_BALANCE: 97 case SN9C102_V4L2_CID_GREEN_BALANCE:
98 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 98 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
99 0x2e, 2+1, mi0343_i2c_data) < 0) 99 2+1, data) < 0)
100 return -EIO; 100 return -EIO;
101 break; 101 break;
102 default: 102 default:
@@ -108,7 +108,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
108 case V4L2_CID_RED_BALANCE: 108 case V4L2_CID_RED_BALANCE:
109 case V4L2_CID_BLUE_BALANCE: 109 case V4L2_CID_BLUE_BALANCE:
110 case SN9C102_V4L2_CID_GREEN_BALANCE: 110 case SN9C102_V4L2_CID_GREEN_BALANCE:
111 ctrl->value = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8); 111 ctrl->value = data[3] | (data[2] << 8);
112 if (ctrl->value >= 0x10 && ctrl->value <= 0x3f) 112 if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
113 ctrl->value -= 0x10; 113 ctrl->value -= 0x10;
114 else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f) 114 else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
@@ -124,6 +124,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
124static int mi0343_set_ctrl(struct sn9c102_device* cam, 124static int mi0343_set_ctrl(struct sn9c102_device* cam,
125 const struct v4l2_control* ctrl) 125 const struct v4l2_control* ctrl)
126{ 126{
127 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
127 u16 reg = 0; 128 u16 reg = 0;
128 int err = 0; 129 int err = 0;
129 130
@@ -143,50 +144,42 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam,
143 144
144 switch (ctrl->id) { 145 switch (ctrl->id) {
145 case V4L2_CID_EXPOSURE: 146 case V4L2_CID_EXPOSURE:
146 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 147 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
147 mi0343.i2c_slave_id,
148 0x09, ctrl->value, 0x00, 148 0x09, ctrl->value, 0x00,
149 0, 0); 149 0, 0);
150 break; 150 break;
151 case V4L2_CID_GAIN: 151 case V4L2_CID_GAIN:
152 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 152 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
153 mi0343.i2c_slave_id,
154 0x35, reg >> 8, reg & 0xff, 153 0x35, reg >> 8, reg & 0xff,
155 0, 0); 154 0, 0);
156 break; 155 break;
157 case V4L2_CID_HFLIP: 156 case V4L2_CID_HFLIP:
158 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 157 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
159 mi0343.i2c_slave_id,
160 0x20, ctrl->value ? 0x40:0x00, 158 0x20, ctrl->value ? 0x40:0x00,
161 ctrl->value ? 0x20:0x00, 159 ctrl->value ? 0x20:0x00,
162 0, 0); 160 0, 0);
163 break; 161 break;
164 case V4L2_CID_VFLIP: 162 case V4L2_CID_VFLIP:
165 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 163 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
166 mi0343.i2c_slave_id,
167 0x20, ctrl->value ? 0x80:0x00, 164 0x20, ctrl->value ? 0x80:0x00,
168 ctrl->value ? 0x80:0x00, 165 ctrl->value ? 0x80:0x00,
169 0, 0); 166 0, 0);
170 break; 167 break;
171 case V4L2_CID_RED_BALANCE: 168 case V4L2_CID_RED_BALANCE:
172 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 169 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
173 mi0343.i2c_slave_id,
174 0x2d, reg >> 8, reg & 0xff, 170 0x2d, reg >> 8, reg & 0xff,
175 0, 0); 171 0, 0);
176 break; 172 break;
177 case V4L2_CID_BLUE_BALANCE: 173 case V4L2_CID_BLUE_BALANCE:
178 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 174 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
179 mi0343.i2c_slave_id,
180 0x2c, reg >> 8, reg & 0xff, 175 0x2c, reg >> 8, reg & 0xff,
181 0, 0); 176 0, 0);
182 break; 177 break;
183 case SN9C102_V4L2_CID_GREEN_BALANCE: 178 case SN9C102_V4L2_CID_GREEN_BALANCE:
184 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 179 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
185 mi0343.i2c_slave_id,
186 0x2b, reg >> 8, reg & 0xff, 180 0x2b, reg >> 8, reg & 0xff,
187 0, 0); 181 0, 0);
188 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 182 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
189 mi0343.i2c_slave_id,
190 0x2e, reg >> 8, reg & 0xff, 183 0x2e, reg >> 8, reg & 0xff,
191 0, 0); 184 0, 0);
192 break; 185 break;
@@ -216,16 +209,15 @@ static int mi0343_set_crop(struct sn9c102_device* cam,
216static int mi0343_set_pix_format(struct sn9c102_device* cam, 209static int mi0343_set_pix_format(struct sn9c102_device* cam,
217 const struct v4l2_pix_format* pix) 210 const struct v4l2_pix_format* pix)
218{ 211{
212 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
219 int err = 0; 213 int err = 0;
220 214
221 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { 215 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
222 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 216 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
223 mi0343.i2c_slave_id,
224 0x0a, 0x00, 0x03, 0, 0); 217 0x0a, 0x00, 0x03, 0, 0);
225 err += sn9c102_write_reg(cam, 0x20, 0x19); 218 err += sn9c102_write_reg(cam, 0x20, 0x19);
226 } else { 219 } else {
227 err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, 220 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
228 mi0343.i2c_slave_id,
229 0x0a, 0x00, 0x05, 0, 0); 221 0x0a, 0x00, 0x05, 0, 0);
230 err += sn9c102_write_reg(cam, 0xa0, 0x19); 222 err += sn9c102_write_reg(cam, 0xa0, 0x19);
231 } 223 }
@@ -237,7 +229,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam,
237static struct sn9c102_sensor mi0343 = { 229static struct sn9c102_sensor mi0343 = {
238 .name = "MI-0343", 230 .name = "MI-0343",
239 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 231 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
240 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 232 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
241 .frequency = SN9C102_I2C_100KHZ, 233 .frequency = SN9C102_I2C_100KHZ,
242 .interface = SN9C102_I2C_2WIRES, 234 .interface = SN9C102_I2C_2WIRES,
243 .i2c_slave_id = 0x5d, 235 .i2c_slave_id = 0x5d,
@@ -343,6 +335,7 @@ static struct sn9c102_sensor mi0343 = {
343 335
344int sn9c102_probe_mi0343(struct sn9c102_device* cam) 336int sn9c102_probe_mi0343(struct sn9c102_device* cam)
345{ 337{
338 u8 data[5+1];
346 int err = 0; 339 int err = 0;
347 340
348 err += sn9c102_write_reg(cam, 0x01, 0x01); 341 err += sn9c102_write_reg(cam, 0x01, 0x01);
@@ -352,10 +345,10 @@ int sn9c102_probe_mi0343(struct sn9c102_device* cam)
352 return -EIO; 345 return -EIO;
353 346
354 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, 347 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
355 2, mi0343_i2c_data) < 0) 348 2, data) < 0)
356 return -EIO; 349 return -EIO;
357 350
358 if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3) 351 if (data[4] != 0x32 || data[3] != 0xe3)
359 return -ENODEV; 352 return -ENODEV;
360 353
361 sn9c102_attach_sensor(cam, &mi0343); 354 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..7154dd0534ff
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_mi0360.c
@@ -0,0 +1,353 @@
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_reg(cam, 0x00, 0x10);
31 err += sn9c102_write_reg(cam, 0x00, 0x11);
32 err += sn9c102_write_reg(cam, 0x0a, 0x14);
33 err += sn9c102_write_reg(cam, 0x40, 0x01);
34 err += sn9c102_write_reg(cam, 0x20, 0x17);
35 err += sn9c102_write_reg(cam, 0x07, 0x18);
36 err += sn9c102_write_reg(cam, 0xa0, 0x19);
37 err += sn9c102_write_reg(cam, 0x02, 0x1c);
38 err += sn9c102_write_reg(cam, 0x03, 0x1d);
39 err += sn9c102_write_reg(cam, 0x0f, 0x1e);
40 err += sn9c102_write_reg(cam, 0x0c, 0x1f);
41 err += sn9c102_write_reg(cam, 0x00, 0x20);
42 err += sn9c102_write_reg(cam, 0x10, 0x21);
43 err += sn9c102_write_reg(cam, 0x20, 0x22);
44 err += sn9c102_write_reg(cam, 0x30, 0x23);
45 err += sn9c102_write_reg(cam, 0x40, 0x24);
46 err += sn9c102_write_reg(cam, 0x50, 0x25);
47 err += sn9c102_write_reg(cam, 0x60, 0x26);
48 err += sn9c102_write_reg(cam, 0x70, 0x27);
49 err += sn9c102_write_reg(cam, 0x80, 0x28);
50 err += sn9c102_write_reg(cam, 0x90, 0x29);
51 err += sn9c102_write_reg(cam, 0xa0, 0x2a);
52 err += sn9c102_write_reg(cam, 0xb0, 0x2b);
53 err += sn9c102_write_reg(cam, 0xc0, 0x2c);
54 err += sn9c102_write_reg(cam, 0xd0, 0x2d);
55 err += sn9c102_write_reg(cam, 0xe0, 0x2e);
56 err += sn9c102_write_reg(cam, 0xf0, 0x2f);
57 err += sn9c102_write_reg(cam, 0xff, 0x30);
58
59 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
60 0x00, 0x01, 0, 0);
61 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
62 0x00, 0x00, 0, 0);
63 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
64 0x01, 0xe1, 0, 0);
65 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
66 0x02, 0x81, 0, 0);
67 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
68 0x00, 0x17, 0, 0);
69 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
70 0x00, 0x11, 0, 0);
71 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
72 0x04, 0x9a, 0, 0);
73
74 return err;
75}
76
77
78static int mi0360_get_ctrl(struct sn9c102_device* cam,
79 struct v4l2_control* ctrl)
80{
81 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
82 u8 data[5+1];
83
84 switch (ctrl->id) {
85 case V4L2_CID_EXPOSURE:
86 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
87 2+1, data) < 0)
88 return -EIO;
89 ctrl->value = data[2];
90 return 0;
91 case V4L2_CID_GAIN:
92 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
93 2+1, data) < 0)
94 return -EIO;
95 ctrl->value = data[3];
96 return 0;
97 case V4L2_CID_RED_BALANCE:
98 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
99 2+1, data) < 0)
100 return -EIO;
101 ctrl->value = data[3];
102 return 0;
103 case V4L2_CID_BLUE_BALANCE:
104 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
105 2+1, data) < 0)
106 return -EIO;
107 ctrl->value = data[3];
108 return 0;
109 case SN9C102_V4L2_CID_GREEN_BALANCE:
110 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
111 2+1, data) < 0)
112 return -EIO;
113 ctrl->value = data[3];
114 return 0;
115 case V4L2_CID_HFLIP:
116 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
117 2+1, data) < 0)
118 return -EIO;
119 ctrl->value = data[3] & 0x20 ? 1 : 0;
120 return 0;
121 case V4L2_CID_VFLIP:
122 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
123 2+1, data) < 0)
124 return -EIO;
125 ctrl->value = data[3] & 0x80 ? 1 : 0;
126 return 0;
127 default:
128 return -EINVAL;
129 }
130
131 return 0;
132}
133
134
135static int mi0360_set_ctrl(struct sn9c102_device* cam,
136 const struct v4l2_control* ctrl)
137{
138 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
139 int err = 0;
140
141 switch (ctrl->id) {
142 case V4L2_CID_EXPOSURE:
143 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
144 0x09, ctrl->value, 0x00,
145 0, 0);
146 break;
147 case V4L2_CID_GAIN:
148 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
149 0x35, 0x03, ctrl->value,
150 0, 0);
151 break;
152 case V4L2_CID_RED_BALANCE:
153 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
154 0x2c, 0x03, ctrl->value,
155 0, 0);
156 break;
157 case V4L2_CID_BLUE_BALANCE:
158 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
159 0x2d, 0x03, ctrl->value,
160 0, 0);
161 break;
162 case SN9C102_V4L2_CID_GREEN_BALANCE:
163 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
164 0x2b, 0x03, ctrl->value,
165 0, 0);
166 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
167 0x2e, 0x03, ctrl->value,
168 0, 0);
169 break;
170 case V4L2_CID_HFLIP:
171 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
172 0x20, ctrl->value ? 0x40:0x00,
173 ctrl->value ? 0x20:0x00,
174 0, 0);
175 break;
176 case V4L2_CID_VFLIP:
177 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
178 0x20, ctrl->value ? 0x80:0x00,
179 ctrl->value ? 0x80:0x00,
180 0, 0);
181 break;
182 default:
183 return -EINVAL;
184 }
185
186 return err ? -EIO : 0;
187}
188
189
190static int mi0360_set_crop(struct sn9c102_device* cam,
191 const struct v4l2_rect* rect)
192{
193 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
194 int err = 0;
195 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
196 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
197
198 err += sn9c102_write_reg(cam, h_start, 0x12);
199 err += sn9c102_write_reg(cam, v_start, 0x13);
200
201 return err;
202}
203
204
205static int mi0360_set_pix_format(struct sn9c102_device* cam,
206 const struct v4l2_pix_format* pix)
207{
208 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
209 int err = 0;
210
211 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
212 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
213 0x0a, 0x00, 0x02, 0, 0);
214 err += sn9c102_write_reg(cam, 0x20, 0x19);
215 } else {
216 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
217 0x0a, 0x00, 0x05, 0, 0);
218 err += sn9c102_write_reg(cam, 0x60, 0x19);
219 }
220
221 return err;
222}
223
224
225static struct sn9c102_sensor mi0360 = {
226 .name = "MI-0360",
227 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
228 .supported_bridge = BRIDGE_SN9C103,
229 .frequency = SN9C102_I2C_100KHZ,
230 .interface = SN9C102_I2C_2WIRES,
231 .i2c_slave_id = 0x5d,
232 .init = &mi0360_init,
233 .qctrl = {
234 {
235 .id = V4L2_CID_EXPOSURE,
236 .type = V4L2_CTRL_TYPE_INTEGER,
237 .name = "exposure",
238 .minimum = 0x00,
239 .maximum = 0x0f,
240 .step = 0x01,
241 .default_value = 0x05,
242 .flags = 0,
243 },
244 {
245 .id = V4L2_CID_GAIN,
246 .type = V4L2_CTRL_TYPE_INTEGER,
247 .name = "global gain",
248 .minimum = 0x00,
249 .maximum = 0x7f,
250 .step = 0x01,
251 .default_value = 0x25,
252 .flags = 0,
253 },
254 {
255 .id = V4L2_CID_HFLIP,
256 .type = V4L2_CTRL_TYPE_BOOLEAN,
257 .name = "horizontal mirror",
258 .minimum = 0,
259 .maximum = 1,
260 .step = 1,
261 .default_value = 0,
262 .flags = 0,
263 },
264 {
265 .id = V4L2_CID_VFLIP,
266 .type = V4L2_CTRL_TYPE_BOOLEAN,
267 .name = "vertical mirror",
268 .minimum = 0,
269 .maximum = 1,
270 .step = 1,
271 .default_value = 0,
272 .flags = 0,
273 },
274 {
275 .id = V4L2_CID_BLUE_BALANCE,
276 .type = V4L2_CTRL_TYPE_INTEGER,
277 .name = "blue balance",
278 .minimum = 0x00,
279 .maximum = 0x7f,
280 .step = 0x01,
281 .default_value = 0x0f,
282 .flags = 0,
283 },
284 {
285 .id = V4L2_CID_RED_BALANCE,
286 .type = V4L2_CTRL_TYPE_INTEGER,
287 .name = "red balance",
288 .minimum = 0x00,
289 .maximum = 0x7f,
290 .step = 0x01,
291 .default_value = 0x32,
292 .flags = 0,
293 },
294 {
295 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
296 .type = V4L2_CTRL_TYPE_INTEGER,
297 .name = "green balance",
298 .minimum = 0x00,
299 .maximum = 0x7f,
300 .step = 0x01,
301 .default_value = 0x25,
302 .flags = 0,
303 },
304 },
305 .get_ctrl = &mi0360_get_ctrl,
306 .set_ctrl = &mi0360_set_ctrl,
307 .cropcap = {
308 .bounds = {
309 .left = 0,
310 .top = 0,
311 .width = 640,
312 .height = 480,
313 },
314 .defrect = {
315 .left = 0,
316 .top = 0,
317 .width = 640,
318 .height = 480,
319 },
320 },
321 .set_crop = &mi0360_set_crop,
322 .pix_format = {
323 .width = 640,
324 .height = 480,
325 .pixelformat = V4L2_PIX_FMT_SBGGR8,
326 .priv = 8,
327 },
328 .set_pix_format = &mi0360_set_pix_format
329};
330
331
332int sn9c102_probe_mi0360(struct sn9c102_device* cam)
333{
334 u8 data[5+1];
335 int err = 0;
336
337 err += sn9c102_write_reg(cam, 0x01, 0x01);
338 err += sn9c102_write_reg(cam, 0x00, 0x01);
339 err += sn9c102_write_reg(cam, 0x28, 0x17);
340 if (err)
341 return -EIO;
342
343 if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
344 2+1, data) < 0)
345 return -EIO;
346
347 if (data[2] != 0x82 || data[3] != 0x43)
348 return -ENODEV;
349
350 sn9c102_attach_sensor(cam, &mi0360);
351
352 return 0;
353}
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
index 7df09ff38e63..ad9fb2ca2735 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,21 @@ 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_reg(cam, 0x00, 0x14);
36 err += sn9c102_write_reg(cam, 0x60, 0x17); 33 err += sn9c102_write_reg(cam, 0x60, 0x17);
37 err += sn9c102_write_reg(cam, 0x0f, 0x18); 34 err += sn9c102_write_reg(cam, 0x0f, 0x18);
38 err += sn9c102_write_reg(cam, 0x50, 0x19); 35 err += sn9c102_write_reg(cam, 0x50, 0x19);
39 36
40 err += sn9c102_i2c_write(cam, 0x12, 0x8d); 37 err += sn9c102_i2c_write(cam, 0x12, 0x8d);
41 err += sn9c102_i2c_write(cam, 0x12, 0x0d); 38 err += sn9c102_i2c_write(cam, 0x12, 0x0d);
42 err += sn9c102_i2c_write(cam, 0x11, 0x00); 39 err += sn9c102_i2c_write(cam, 0x11, 0x00);
43 err += sn9c102_i2c_write(cam, 0x15, 0x34); 40 err += sn9c102_i2c_write(cam, 0x15, 0x35);
44 err += sn9c102_i2c_write(cam, 0x16, 0x03); 41 err += sn9c102_i2c_write(cam, 0x16, 0x03);
45 err += sn9c102_i2c_write(cam, 0x17, 0x1c); 42 err += sn9c102_i2c_write(cam, 0x17, 0x1c);
46 err += sn9c102_i2c_write(cam, 0x18, 0xbd); 43 err += sn9c102_i2c_write(cam, 0x18, 0xbd);
47 err += sn9c102_i2c_write(cam, 0x19, 0x06); 44 err += sn9c102_i2c_write(cam, 0x19, 0x06);
48 err += sn9c102_i2c_write(cam, 0x1a, 0xf6); 45 err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
49 err += sn9c102_i2c_write(cam, 0x1b, 0x04); 46 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
50 err += sn9c102_i2c_write(cam, 0x20, 0x44); 47 err += sn9c102_i2c_write(cam, 0x20, 0x44);
51 err += sn9c102_i2c_write(cam, 0x23, 0xee); 48 err += sn9c102_i2c_write(cam, 0x23, 0xee);
52 err += sn9c102_i2c_write(cam, 0x26, 0xa0); 49 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
@@ -108,23 +105,23 @@ static int ov7630_init(struct sn9c102_device* cam)
108 err += sn9c102_i2c_write(cam, 0x11, 0x01); 105 err += sn9c102_i2c_write(cam, 0x11, 0x01);
109 err += sn9c102_i2c_write(cam, 0x1b, 0x04); 106 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
110 err += sn9c102_i2c_write(cam, 0x20, 0x44); 107 err += sn9c102_i2c_write(cam, 0x20, 0x44);
111 err += sn9c102_i2c_write(cam, 0x23, 0xee); 108 err += sn9c102_i2c_write(cam, 0x23, 0xee);
112 err += sn9c102_i2c_write(cam, 0x26, 0xa0); 109 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
113 err += sn9c102_i2c_write(cam, 0x27, 0x9a); 110 err += sn9c102_i2c_write(cam, 0x27, 0x9a);
114 err += sn9c102_i2c_write(cam, 0x28, 0x20); 111 err += sn9c102_i2c_write(cam, 0x28, 0x20);
115 err += sn9c102_i2c_write(cam, 0x29, 0x30); 112 err += sn9c102_i2c_write(cam, 0x29, 0x30);
116 err += sn9c102_i2c_write(cam, 0x2f, 0x3d); 113 err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
117 err += sn9c102_i2c_write(cam, 0x30, 0x24); 114 err += sn9c102_i2c_write(cam, 0x30, 0x24);
118 err += sn9c102_i2c_write(cam, 0x32, 0x86); 115 err += sn9c102_i2c_write(cam, 0x32, 0x86);
119 err += sn9c102_i2c_write(cam, 0x60, 0xa9); 116 err += sn9c102_i2c_write(cam, 0x60, 0xa9);
120 err += sn9c102_i2c_write(cam, 0x61, 0x42); 117 err += sn9c102_i2c_write(cam, 0x61, 0x42);
121 err += sn9c102_i2c_write(cam, 0x65, 0x00); 118 err += sn9c102_i2c_write(cam, 0x65, 0x00);
122 err += sn9c102_i2c_write(cam, 0x69, 0x38); 119 err += sn9c102_i2c_write(cam, 0x69, 0x38);
123 err += sn9c102_i2c_write(cam, 0x6f, 0x88); 120 err += sn9c102_i2c_write(cam, 0x6f, 0x88);
124 err += sn9c102_i2c_write(cam, 0x70, 0x0b); 121 err += sn9c102_i2c_write(cam, 0x70, 0x0b);
125 err += sn9c102_i2c_write(cam, 0x71, 0x00); 122 err += sn9c102_i2c_write(cam, 0x71, 0x00);
126 err += sn9c102_i2c_write(cam, 0x74, 0x21); 123 err += sn9c102_i2c_write(cam, 0x74, 0x21);
127 err += sn9c102_i2c_write(cam, 0x7d, 0xf7); 124 err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
128 break; 125 break;
129 default: 126 default:
130 break; 127 break;
@@ -428,9 +425,9 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
428 switch (sn9c102_get_bridge(cam)) { 425 switch (sn9c102_get_bridge(cam)) {
429 case BRIDGE_SN9C101: 426 case BRIDGE_SN9C101:
430 case BRIDGE_SN9C102: 427 case BRIDGE_SN9C102:
431 err += sn9c102_write_reg(cam, 0x01, 0x01); 428 err += sn9c102_write_reg(cam, 0x01, 0x01);
432 err += sn9c102_write_reg(cam, 0x00, 0x01); 429 err += sn9c102_write_reg(cam, 0x00, 0x01);
433 err += sn9c102_write_reg(cam, 0x28, 0x17); 430 err += sn9c102_write_reg(cam, 0x28, 0x17);
434 break; 431 break;
435 case BRIDGE_SN9C103: /* do _not_ change anything! */ 432 case BRIDGE_SN9C103: /* do _not_ change anything! */
436 err += sn9c102_write_reg(cam, 0x09, 0x01); 433 err += sn9c102_write_reg(cam, 0x09, 0x01);
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c
index d670c24d4435..eef90ff3d474 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7660.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c
@@ -22,9 +22,6 @@
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;
diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c
index 8d79a5fae5de..a67057210cab 100644
--- a/drivers/media/video/sn9c102/sn9c102_pas106b.c
+++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c
@@ -23,9 +23,6 @@
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;
@@ -172,7 +169,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam,
172static struct sn9c102_sensor pas106b = { 169static struct sn9c102_sensor pas106b = {
173 .name = "PAS106B", 170 .name = "PAS106B",
174 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 171 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
175 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 172 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
176 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 173 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
177 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, 174 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
178 .interface = SN9C102_I2C_2WIRES, 175 .interface = SN9C102_I2C_2WIRES,
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
index 7894f01b56e8..4447d7cb1e92 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,12 +35,12 @@ 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_reg(cam, 0x00, 0x10);
42 err += sn9c102_write_reg(cam, 0x00, 0x11); 39 err += sn9c102_write_reg(cam, 0x00, 0x11);
43 err += sn9c102_write_reg(cam, 0x00, 0x14); 40 err += sn9c102_write_reg(cam, 0x00, 0x14);
44 err += sn9c102_write_reg(cam, 0x20, 0x17); 41 err += sn9c102_write_reg(cam, 0x20, 0x17);
45 err += sn9c102_write_reg(cam, 0x30, 0x19); 42 err += sn9c102_write_reg(cam, 0x30, 0x19);
46 err += sn9c102_write_reg(cam, 0x09, 0x18); 43 err += sn9c102_write_reg(cam, 0x09, 0x18);
47 break; 44 break;
48 case BRIDGE_SN9C103: 45 case BRIDGE_SN9C103:
49 err += sn9c102_write_reg(cam, 0x00, 0x02); 46 err += sn9c102_write_reg(cam, 0x00, 0x02);
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
index 90023ad63adc..a265767e5f31 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
@@ -22,9 +22,6 @@
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;
@@ -98,7 +95,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
98static struct sn9c102_sensor tas5110c1b = { 95static struct sn9c102_sensor tas5110c1b = {
99 .name = "TAS5110C1B", 96 .name = "TAS5110C1B",
100 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 97 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
101 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 98 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
102 .sysfs_ops = SN9C102_I2C_WRITE, 99 .sysfs_ops = SN9C102_I2C_WRITE,
103 .frequency = SN9C102_I2C_100KHZ, 100 .frequency = SN9C102_I2C_100KHZ,
104 .interface = SN9C102_I2C_3WIRES, 101 .interface = SN9C102_I2C_3WIRES,
@@ -146,7 +143,6 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
146 const struct usb_device_id tas5110c1b_id_table[] = { 143 const struct usb_device_id tas5110c1b_id_table[] = {
147 { USB_DEVICE(0x0c45, 0x6001), }, 144 { USB_DEVICE(0x0c45, 0x6001), },
148 { USB_DEVICE(0x0c45, 0x6005), }, 145 { USB_DEVICE(0x0c45, 0x6005), },
149 { USB_DEVICE(0x0c45, 0x6007), },
150 { USB_DEVICE(0x0c45, 0x60ab), }, 146 { USB_DEVICE(0x0c45, 0x60ab), },
151 { } 147 { }
152 }; 148 };
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c
new file mode 100644
index 000000000000..4681cfa1bf57
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_tas5110d.c
@@ -0,0 +1,121 @@
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 = 0;
28
29 err += sn9c102_write_reg(cam, 0x01, 0x01);
30 err += sn9c102_write_reg(cam, 0x04, 0x01);
31 err += sn9c102_write_reg(cam, 0x0a, 0x14);
32 err += sn9c102_write_reg(cam, 0x60, 0x17);
33 err += sn9c102_write_reg(cam, 0x06, 0x18);
34 err += sn9c102_write_reg(cam, 0xfb, 0x19);
35
36 err += sn9c102_i2c_write(cam, 0x9a, 0xca);
37
38 return err;
39}
40
41
42static int tas5110d_set_crop(struct sn9c102_device* cam,
43 const struct v4l2_rect* rect)
44{
45 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
46 int err = 0;
47 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
48 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
49
50 err += sn9c102_write_reg(cam, h_start, 0x12);
51 err += sn9c102_write_reg(cam, v_start, 0x13);
52
53 err += sn9c102_write_reg(cam, 0x14, 0x1a);
54 err += sn9c102_write_reg(cam, 0x0a, 0x1b);
55
56 return err;
57}
58
59
60static int tas5110d_set_pix_format(struct sn9c102_device* cam,
61 const struct v4l2_pix_format* pix)
62{
63 int err = 0;
64
65 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
66 err += sn9c102_write_reg(cam, 0x3b, 0x19);
67 else
68 err += sn9c102_write_reg(cam, 0xfb, 0x19);
69
70 return err;
71}
72
73
74static struct sn9c102_sensor tas5110d = {
75 .name = "TAS5110D",
76 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
77 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
78 .sysfs_ops = SN9C102_I2C_WRITE,
79 .frequency = SN9C102_I2C_100KHZ,
80 .interface = SN9C102_I2C_2WIRES,
81 .i2c_slave_id = 0x61,
82 .init = &tas5110d_init,
83 .cropcap = {
84 .bounds = {
85 .left = 0,
86 .top = 0,
87 .width = 352,
88 .height = 288,
89 },
90 .defrect = {
91 .left = 0,
92 .top = 0,
93 .width = 352,
94 .height = 288,
95 },
96 },
97 .set_crop = &tas5110d_set_crop,
98 .pix_format = {
99 .width = 352,
100 .height = 288,
101 .pixelformat = V4L2_PIX_FMT_SBGGR8,
102 .priv = 8,
103 },
104 .set_pix_format = &tas5110d_set_pix_format
105};
106
107
108int sn9c102_probe_tas5110d(struct sn9c102_device* cam)
109{
110 const struct usb_device_id tas5110d_id_table[] = {
111 { USB_DEVICE(0x0c45, 0x6007), },
112 { }
113 };
114
115 if (!sn9c102_match_id(cam, tas5110d_id_table))
116 return -ENODEV;
117
118 sn9c102_attach_sensor(cam, &tas5110d);
119
120 return 0;
121}
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
index cb1b318bc1ff..a7f711396152 100644
--- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
+++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
@@ -22,9 +22,6 @@
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 = 0;
@@ -99,7 +96,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
99static struct sn9c102_sensor tas5130d1b = { 96static struct sn9c102_sensor tas5130d1b = {
100 .name = "TAS5130D1B", 97 .name = "TAS5130D1B",
101 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 98 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
102 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 99 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
103 .sysfs_ops = SN9C102_I2C_WRITE, 100 .sysfs_ops = SN9C102_I2C_WRITE,
104 .frequency = SN9C102_I2C_100KHZ, 101 .frequency = SN9C102_I2C_100KHZ,
105 .interface = SN9C102_I2C_3WIRES, 102 .interface = SN9C102_I2C_3WIRES,