aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/sn9c102
diff options
context:
space:
mode:
authorLuca Risolia <luca.risolia@studio.unibo.it>2007-06-13 13:37:50 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-07-18 13:24:07 -0400
commit3770be34199ace8c497ce454cebd7d63347dc4c3 (patch)
tree4c9c3adef124a1400234a730a7ebca63c8ab63e3 /drivers/media/video/sn9c102
parenta6e2b40cb430e1e3a22fbb56807edebf71bf6188 (diff)
V4L/DVB (5765): SN9C1xx driver updates
- Add support for pair OV7630+SN9C120 - Better and safe locking mechanism of the device structure on open(), close() and disconnect() - Use kref for handling device deallocation - Generic cleanups Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/sn9c102')
-rw-r--r--drivers/media/video/sn9c102/sn9c102.h9
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c173
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7630.c214
-rw-r--r--drivers/media/video/sn9c102/sn9c102_ov7660.c88
4 files changed, 356 insertions, 128 deletions
diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
index 11fcb49f5b99..2e3c3de793a7 100644
--- a/drivers/media/video/sn9c102/sn9c102.h
+++ b/drivers/media/video/sn9c102/sn9c102.h
@@ -36,6 +36,7 @@
36#include <linux/mutex.h> 36#include <linux/mutex.h>
37#include <linux/string.h> 37#include <linux/string.h>
38#include <linux/stddef.h> 38#include <linux/stddef.h>
39#include <linux/kref.h>
39 40
40#include "sn9c102_config.h" 41#include "sn9c102_config.h"
41#include "sn9c102_sensor.h" 42#include "sn9c102_sensor.h"
@@ -94,7 +95,7 @@ struct sn9c102_module_param {
94}; 95};
95 96
96static DEFINE_MUTEX(sn9c102_sysfs_lock); 97static DEFINE_MUTEX(sn9c102_sysfs_lock);
97static DECLARE_RWSEM(sn9c102_disconnect); 98static DECLARE_RWSEM(sn9c102_dev_lock);
98 99
99struct sn9c102_device { 100struct sn9c102_device {
100 struct video_device* v4ldev; 101 struct video_device* v4ldev;
@@ -122,12 +123,14 @@ struct sn9c102_device {
122 123
123 struct sn9c102_module_param module_param; 124 struct sn9c102_module_param module_param;
124 125
126 struct kref kref;
125 enum sn9c102_dev_state state; 127 enum sn9c102_dev_state state;
126 u8 users; 128 u8 users;
127 129
128 struct mutex dev_mutex, fileop_mutex; 130 struct completion probe;
131 struct mutex open_mutex, fileop_mutex;
129 spinlock_t queue_lock; 132 spinlock_t queue_lock;
130 wait_queue_head_t open, wait_frame, wait_stream; 133 wait_queue_head_t wait_open, wait_frame, wait_stream;
131}; 134};
132 135
133/*****************************************************************************/ 136/*****************************************************************************/
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 74a204f8ebc8..36d8a455e0ec 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -48,8 +48,8 @@
48#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia" 48#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
49#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" 49#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
50#define SN9C102_MODULE_LICENSE "GPL" 50#define SN9C102_MODULE_LICENSE "GPL"
51#define SN9C102_MODULE_VERSION "1:1.44" 51#define SN9C102_MODULE_VERSION "1:1.47"
52#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 44) 52#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 47)
53 53
54/*****************************************************************************/ 54/*****************************************************************************/
55 55
@@ -64,9 +64,10 @@ MODULE_LICENSE(SN9C102_MODULE_LICENSE);
64static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; 64static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
65module_param_array(video_nr, short, NULL, 0444); 65module_param_array(video_nr, short, NULL, 0444);
66MODULE_PARM_DESC(video_nr, 66MODULE_PARM_DESC(video_nr,
67 "\n<-1|n[,...]> Specify V4L2 minor mode number." 67 " <-1|n[,...]>"
68 "\n -1 = use next available (default)" 68 "\nSpecify V4L2 minor mode number."
69 "\n n = use minor number n (integer >= 0)" 69 "\n-1 = use next available (default)"
70 "\n n = use minor number n (integer >= 0)"
70 "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES) 71 "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
71 " cameras this way." 72 " cameras this way."
72 "\nFor example:" 73 "\nFor example:"
@@ -79,13 +80,14 @@ static short force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
79 SN9C102_FORCE_MUNMAP}; 80 SN9C102_FORCE_MUNMAP};
80module_param_array(force_munmap, bool, NULL, 0444); 81module_param_array(force_munmap, bool, NULL, 0444);
81MODULE_PARM_DESC(force_munmap, 82MODULE_PARM_DESC(force_munmap,
82 "\n<0|1[,...]> Force the application to unmap previously" 83 " <0|1[,...]>"
84 "\nForce the application to unmap previously"
83 "\nmapped buffer memory before calling any VIDIOC_S_CROP or" 85 "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
84 "\nVIDIOC_S_FMT ioctl's. Not all the applications support" 86 "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
85 "\nthis feature. This parameter is specific for each" 87 "\nthis feature. This parameter is specific for each"
86 "\ndetected camera." 88 "\ndetected camera."
87 "\n 0 = do not force memory unmapping" 89 "\n0 = do not force memory unmapping"
88 "\n 1 = force memory unmapping (save memory)" 90 "\n1 = force memory unmapping (save memory)"
89 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." 91 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
90 "\n"); 92 "\n");
91 93
@@ -93,7 +95,8 @@ static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
93 SN9C102_FRAME_TIMEOUT}; 95 SN9C102_FRAME_TIMEOUT};
94module_param_array(frame_timeout, uint, NULL, 0644); 96module_param_array(frame_timeout, uint, NULL, 0644);
95MODULE_PARM_DESC(frame_timeout, 97MODULE_PARM_DESC(frame_timeout,
96 "\n<0|n[,...]> Timeout for a video frame in seconds before" 98 " <0|n[,...]>"
99 "\nTimeout for a video frame in seconds before"
97 "\nreturning an I/O error; 0 for infinity." 100 "\nreturning an I/O error; 0 for infinity."
98 "\nThis parameter is specific for each detected camera." 101 "\nThis parameter is specific for each detected camera."
99 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." 102 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
@@ -103,7 +106,8 @@ MODULE_PARM_DESC(frame_timeout,
103static unsigned short debug = SN9C102_DEBUG_LEVEL; 106static unsigned short debug = SN9C102_DEBUG_LEVEL;
104module_param(debug, ushort, 0644); 107module_param(debug, ushort, 0644);
105MODULE_PARM_DESC(debug, 108MODULE_PARM_DESC(debug,
106 "\n<n> Debugging information level, from 0 to 3:" 109 " <n>"
110 "\nDebugging information level, from 0 to 3:"
107 "\n0 = none (use carefully)" 111 "\n0 = none (use carefully)"
108 "\n1 = critical errors" 112 "\n1 = critical errors"
109 "\n2 = significant informations" 113 "\n2 = significant informations"
@@ -1616,7 +1620,8 @@ static int sn9c102_init(struct sn9c102_device* cam)
1616 int err = 0; 1620 int err = 0;
1617 1621
1618 if (!(cam->state & DEV_INITIALIZED)) { 1622 if (!(cam->state & DEV_INITIALIZED)) {
1619 init_waitqueue_head(&cam->open); 1623 mutex_init(&cam->open_mutex);
1624 init_waitqueue_head(&cam->wait_open);
1620 qctrl = s->qctrl; 1625 qctrl = s->qctrl;
1621 rect = &(s->cropcap.defrect); 1626 rect = &(s->cropcap.defrect);
1622 } else { /* use current values */ 1627 } else { /* use current values */
@@ -1706,21 +1711,27 @@ static int sn9c102_init(struct sn9c102_device* cam)
1706 return 0; 1711 return 0;
1707} 1712}
1708 1713
1714/*****************************************************************************/
1709 1715
1710static void sn9c102_release_resources(struct sn9c102_device* cam) 1716static void sn9c102_release_resources(struct kref *kref)
1711{ 1717{
1718 struct sn9c102_device *cam;
1719
1712 mutex_lock(&sn9c102_sysfs_lock); 1720 mutex_lock(&sn9c102_sysfs_lock);
1713 1721
1722 cam = container_of(kref, struct sn9c102_device, kref);
1723
1714 DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); 1724 DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);
1715 video_set_drvdata(cam->v4ldev, NULL); 1725 video_set_drvdata(cam->v4ldev, NULL);
1716 video_unregister_device(cam->v4ldev); 1726 video_unregister_device(cam->v4ldev);
1727 usb_put_dev(cam->usbdev);
1728 kfree(cam->control_buffer);
1729 kfree(cam);
1717 1730
1718 mutex_unlock(&sn9c102_sysfs_lock); 1731 mutex_unlock(&sn9c102_sysfs_lock);
1719 1732
1720 kfree(cam->control_buffer);
1721} 1733}
1722 1734
1723/*****************************************************************************/
1724 1735
1725static int sn9c102_open(struct inode* inode, struct file* filp) 1736static int sn9c102_open(struct inode* inode, struct file* filp)
1726{ 1737{
@@ -1728,43 +1739,78 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
1728 int err = 0; 1739 int err = 0;
1729 1740
1730 /* 1741 /*
1731 This is the only safe way to prevent race conditions with 1742 A read_trylock() in open() is the only safe way to prevent race
1732 disconnect 1743 conditions with disconnect(), one close() and multiple (not
1744 necessarily simultaneous) attempts to open(). For example, it
1745 prevents from waiting for a second access, while the device
1746 structure is being deallocated, after a possible disconnect() and
1747 during a following close() holding the write lock: given that, after
1748 this deallocation, no access will be possible anymore, using the
1749 non-trylock version would have let open() gain the access to the
1750 device structure improperly.
1751 For this reason the lock must also not be per-device.
1733 */ 1752 */
1734 if (!down_read_trylock(&sn9c102_disconnect)) 1753 if (!down_read_trylock(&sn9c102_dev_lock))
1735 return -ERESTARTSYS; 1754 return -ERESTARTSYS;
1736 1755
1737 cam = video_get_drvdata(video_devdata(filp)); 1756 cam = video_get_drvdata(video_devdata(filp));
1738 1757
1739 if (mutex_lock_interruptible(&cam->dev_mutex)) { 1758 if (wait_for_completion_interruptible(&cam->probe)) {
1740 up_read(&sn9c102_disconnect); 1759 up_read(&sn9c102_dev_lock);
1760 return -ERESTARTSYS;
1761 }
1762
1763 kref_get(&cam->kref);
1764
1765 /*
1766 Make sure to isolate all the simultaneous opens.
1767 */
1768 if (mutex_lock_interruptible(&cam->open_mutex)) {
1769 kref_put(&cam->kref, sn9c102_release_resources);
1770 up_read(&sn9c102_dev_lock);
1741 return -ERESTARTSYS; 1771 return -ERESTARTSYS;
1742 } 1772 }
1743 1773
1774 if (cam->state & DEV_DISCONNECTED) {
1775 DBG(1, "Device not present");
1776 err = -ENODEV;
1777 goto out;
1778 }
1779
1744 if (cam->users) { 1780 if (cam->users) {
1745 DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); 1781 DBG(2, "Device /dev/video%d is already in use",
1782 cam->v4ldev->minor);
1746 DBG(3, "Simultaneous opens are not supported"); 1783 DBG(3, "Simultaneous opens are not supported");
1784 /*
1785 open() must follow the open flags and should block
1786 eventually while the device is in use.
1787 */
1747 if ((filp->f_flags & O_NONBLOCK) || 1788 if ((filp->f_flags & O_NONBLOCK) ||
1748 (filp->f_flags & O_NDELAY)) { 1789 (filp->f_flags & O_NDELAY)) {
1749 err = -EWOULDBLOCK; 1790 err = -EWOULDBLOCK;
1750 goto out; 1791 goto out;
1751 } 1792 }
1752 mutex_unlock(&cam->dev_mutex); 1793 DBG(2, "A blocking open() has been requested. Wait for the "
1753 err = wait_event_interruptible_exclusive(cam->open, 1794 "device to be released...");
1754 cam->state & DEV_DISCONNECTED 1795 up_read(&sn9c102_dev_lock);
1796 /*
1797 We will not release the "open_mutex" lock, so that only one
1798 process can be in the wait queue below. This way the process
1799 will be sleeping while holding the lock, without loosing its
1800 priority after any wake_up().
1801 */
1802 err = wait_event_interruptible_exclusive(cam->wait_open,
1803 (cam->state & DEV_DISCONNECTED)
1755 || !cam->users); 1804 || !cam->users);
1756 if (err) { 1805 down_read(&sn9c102_dev_lock);
1757 up_read(&sn9c102_disconnect); 1806 if (err)
1758 return err; 1807 goto out;
1759 }
1760 if (cam->state & DEV_DISCONNECTED) { 1808 if (cam->state & DEV_DISCONNECTED) {
1761 up_read(&sn9c102_disconnect); 1809 err = -ENODEV;
1762 return -ENODEV; 1810 goto out;
1763 } 1811 }
1764 mutex_lock(&cam->dev_mutex);
1765 } 1812 }
1766 1813
1767
1768 if (cam->state & DEV_MISCONFIGURED) { 1814 if (cam->state & DEV_MISCONFIGURED) {
1769 err = sn9c102_init(cam); 1815 err = sn9c102_init(cam);
1770 if (err) { 1816 if (err) {
@@ -1789,36 +1835,33 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
1789 DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); 1835 DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);
1790 1836
1791out: 1837out:
1792 mutex_unlock(&cam->dev_mutex); 1838 mutex_unlock(&cam->open_mutex);
1793 up_read(&sn9c102_disconnect); 1839 if (err)
1840 kref_put(&cam->kref, sn9c102_release_resources);
1841
1842 up_read(&sn9c102_dev_lock);
1794 return err; 1843 return err;
1795} 1844}
1796 1845
1797 1846
1798static int sn9c102_release(struct inode* inode, struct file* filp) 1847static int sn9c102_release(struct inode* inode, struct file* filp)
1799{ 1848{
1800 struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); 1849 struct sn9c102_device* cam;
1801 1850
1802 mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ 1851 down_write(&sn9c102_dev_lock);
1803 1852
1804 sn9c102_stop_transfer(cam); 1853 cam = video_get_drvdata(video_devdata(filp));
1805 1854
1855 sn9c102_stop_transfer(cam);
1806 sn9c102_release_buffers(cam); 1856 sn9c102_release_buffers(cam);
1807
1808 if (cam->state & DEV_DISCONNECTED) {
1809 sn9c102_release_resources(cam);
1810 usb_put_dev(cam->usbdev);
1811 mutex_unlock(&cam->dev_mutex);
1812 kfree(cam);
1813 return 0;
1814 }
1815
1816 cam->users--; 1857 cam->users--;
1817 wake_up_interruptible_nr(&cam->open, 1); 1858 wake_up_interruptible_nr(&cam->wait_open, 1);
1818 1859
1819 DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); 1860 DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);
1820 1861
1821 mutex_unlock(&cam->dev_mutex); 1862 kref_put(&cam->kref, sn9c102_release_resources);
1863
1864 up_write(&sn9c102_dev_lock);
1822 1865
1823 return 0; 1866 return 0;
1824} 1867}
@@ -2085,7 +2128,6 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
2085 2128
2086 vma->vm_ops = &sn9c102_vm_ops; 2129 vma->vm_ops = &sn9c102_vm_ops;
2087 vma->vm_private_data = &cam->frame[i]; 2130 vma->vm_private_data = &cam->frame[i];
2088
2089 sn9c102_vm_open(vma); 2131 sn9c102_vm_open(vma);
2090 2132
2091 mutex_unlock(&cam->fileop_mutex); 2133 mutex_unlock(&cam->fileop_mutex);
@@ -3215,8 +3257,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3215 goto fail; 3257 goto fail;
3216 } 3258 }
3217 3259
3218 mutex_init(&cam->dev_mutex);
3219
3220 r = sn9c102_read_reg(cam, 0x00); 3260 r = sn9c102_read_reg(cam, 0x00);
3221 if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) { 3261 if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
3222 DBG(1, "Sorry, this is not a SN9C1xx-based camera " 3262 DBG(1, "Sorry, this is not a SN9C1xx-based camera "
@@ -3282,7 +3322,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3282 cam->v4ldev->release = video_device_release; 3322 cam->v4ldev->release = video_device_release;
3283 video_set_drvdata(cam->v4ldev, cam); 3323 video_set_drvdata(cam->v4ldev, cam);
3284 3324
3285 mutex_lock(&cam->dev_mutex); 3325 init_completion(&cam->probe);
3286 3326
3287 err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, 3327 err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
3288 video_nr[dev_nr]); 3328 video_nr[dev_nr]);
@@ -3292,7 +3332,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3292 DBG(1, "Free /dev/videoX node not found"); 3332 DBG(1, "Free /dev/videoX node not found");
3293 video_nr[dev_nr] = -1; 3333 video_nr[dev_nr] = -1;
3294 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; 3334 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
3295 mutex_unlock(&cam->dev_mutex); 3335 complete_all(&cam->probe);
3296 goto fail; 3336 goto fail;
3297 } 3337 }
3298 3338
@@ -3318,8 +3358,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3318#endif 3358#endif
3319 3359
3320 usb_set_intfdata(intf, cam); 3360 usb_set_intfdata(intf, cam);
3361 kref_init(&cam->kref);
3362 usb_get_dev(cam->usbdev);
3321 3363
3322 mutex_unlock(&cam->dev_mutex); 3364 complete_all(&cam->probe);
3323 3365
3324 return 0; 3366 return 0;
3325 3367
@@ -3336,40 +3378,31 @@ fail:
3336 3378
3337static void sn9c102_usb_disconnect(struct usb_interface* intf) 3379static void sn9c102_usb_disconnect(struct usb_interface* intf)
3338{ 3380{
3339 struct sn9c102_device* cam = usb_get_intfdata(intf); 3381 struct sn9c102_device* cam;
3340
3341 if (!cam)
3342 return;
3343 3382
3344 down_write(&sn9c102_disconnect); 3383 down_write(&sn9c102_dev_lock);
3345 3384
3346 mutex_lock(&cam->dev_mutex); 3385 cam = usb_get_intfdata(intf);
3347 3386
3348 DBG(2, "Disconnecting %s...", cam->v4ldev->name); 3387 DBG(2, "Disconnecting %s...", cam->v4ldev->name);
3349 3388
3350 wake_up_interruptible_all(&cam->open);
3351
3352 if (cam->users) { 3389 if (cam->users) {
3353 DBG(2, "Device /dev/video%d is open! Deregistration and " 3390 DBG(2, "Device /dev/video%d is open! Deregistration and "
3354 "memory deallocation are deferred on close.", 3391 "memory deallocation are deferred.",
3355 cam->v4ldev->minor); 3392 cam->v4ldev->minor);
3356 cam->state |= DEV_MISCONFIGURED; 3393 cam->state |= DEV_MISCONFIGURED;
3357 sn9c102_stop_transfer(cam); 3394 sn9c102_stop_transfer(cam);
3358 cam->state |= DEV_DISCONNECTED; 3395 cam->state |= DEV_DISCONNECTED;
3359 wake_up_interruptible(&cam->wait_frame); 3396 wake_up_interruptible(&cam->wait_frame);
3360 wake_up(&cam->wait_stream); 3397 wake_up(&cam->wait_stream);
3361 usb_get_dev(cam->usbdev); 3398 } else
3362 } else {
3363 cam->state |= DEV_DISCONNECTED; 3399 cam->state |= DEV_DISCONNECTED;
3364 sn9c102_release_resources(cam);
3365 }
3366 3400
3367 mutex_unlock(&cam->dev_mutex); 3401 wake_up_interruptible_all(&cam->wait_open);
3368 3402
3369 if (!cam->users) 3403 kref_put(&cam->kref, sn9c102_release_resources);
3370 kfree(cam);
3371 3404
3372 up_write(&sn9c102_disconnect); 3405 up_write(&sn9c102_dev_lock);
3373} 3406}
3374 3407
3375 3408
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
index e6832347894f..e4856fd77982 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7630.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c
@@ -104,6 +104,145 @@ static int ov7630_init(struct sn9c102_device* cam)
104 err += sn9c102_i2c_write(cam, 0x74, 0x21); 104 err += sn9c102_i2c_write(cam, 0x74, 0x21);
105 err += sn9c102_i2c_write(cam, 0x7d, 0xf7); 105 err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
106 break; 106 break;
107 case BRIDGE_SN9C105:
108 case BRIDGE_SN9C120:
109 err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
110 {0x1a, 0x04}, {0x03, 0x10},
111 {0x0a, 0x14}, {0xe2, 0x17},
112 {0x0b, 0x18}, {0x00, 0x19},
113 {0x1d, 0x1a}, {0x10, 0x1b},
114 {0x02, 0x1c}, {0x03, 0x1d},
115 {0x0f, 0x1e}, {0x0c, 0x1f},
116 {0x00, 0x20}, {0x24, 0x21},
117 {0x3b, 0x22}, {0x47, 0x23},
118 {0x60, 0x24}, {0x71, 0x25},
119 {0x80, 0x26}, {0x8f, 0x27},
120 {0x9d, 0x28}, {0xaa, 0x29},
121 {0xb8, 0x2a}, {0xc4, 0x2b},
122 {0xd1, 0x2c}, {0xdd, 0x2d},
123 {0xe8, 0x2e}, {0xf4, 0x2f},
124 {0xff, 0x30}, {0x00, 0x3f},
125 {0xc7, 0x40}, {0x01, 0x41},
126 {0x44, 0x42}, {0x00, 0x43},
127 {0x44, 0x44}, {0x00, 0x45},
128 {0x44, 0x46}, {0x00, 0x47},
129 {0xc7, 0x48}, {0x01, 0x49},
130 {0xc7, 0x4a}, {0x01, 0x4b},
131 {0xc7, 0x4c}, {0x01, 0x4d},
132 {0x44, 0x4e}, {0x00, 0x4f},
133 {0x44, 0x50}, {0x00, 0x51},
134 {0x44, 0x52}, {0x00, 0x53},
135 {0xc7, 0x54}, {0x01, 0x55},
136 {0xc7, 0x56}, {0x01, 0x57},
137 {0xc7, 0x58}, {0x01, 0x59},
138 {0x44, 0x5a}, {0x00, 0x5b},
139 {0x44, 0x5c}, {0x00, 0x5d},
140 {0x44, 0x5e}, {0x00, 0x5f},
141 {0xc7, 0x60}, {0x01, 0x61},
142 {0xc7, 0x62}, {0x01, 0x63},
143 {0xc7, 0x64}, {0x01, 0x65},
144 {0x44, 0x66}, {0x00, 0x67},
145 {0x44, 0x68}, {0x00, 0x69},
146 {0x44, 0x6a}, {0x00, 0x6b},
147 {0xc7, 0x6c}, {0x01, 0x6d},
148 {0xc7, 0x6e}, {0x01, 0x6f},
149 {0xc7, 0x70}, {0x01, 0x71},
150 {0x44, 0x72}, {0x00, 0x73},
151 {0x44, 0x74}, {0x00, 0x75},
152 {0x44, 0x76}, {0x00, 0x77},
153 {0xc7, 0x78}, {0x01, 0x79},
154 {0xc7, 0x7a}, {0x01, 0x7b},
155 {0xc7, 0x7c}, {0x01, 0x7d},
156 {0x44, 0x7e}, {0x00, 0x7f},
157 {0x17, 0x84}, {0x00, 0x85},
158 {0x2e, 0x86}, {0x00, 0x87},
159 {0x09, 0x88}, {0x00, 0x89},
160 {0xe8, 0x8a}, {0x0f, 0x8b},
161 {0xda, 0x8c}, {0x0f, 0x8d},
162 {0x40, 0x8e}, {0x00, 0x8f},
163 {0x37, 0x90}, {0x00, 0x91},
164 {0xcf, 0x92}, {0x0f, 0x93},
165 {0xfa, 0x94}, {0x0f, 0x95},
166 {0x00, 0x96}, {0x00, 0x97},
167 {0x00, 0x98}, {0x66, 0x99},
168 {0x00, 0x9a}, {0x40, 0x9b},
169 {0x20, 0x9c}, {0x00, 0x9d},
170 {0x00, 0x9e}, {0x00, 0x9f},
171 {0x2d, 0xc0}, {0x2d, 0xc1},
172 {0x3a, 0xc2}, {0x00, 0xc3},
173 {0x04, 0xc4}, {0x3f, 0xc5},
174 {0x00, 0xc6}, {0x00, 0xc7},
175 {0x50, 0xc8}, {0x3c, 0xc9},
176 {0x28, 0xca}, {0xd8, 0xcb},
177 {0x14, 0xcc}, {0xec, 0xcd},
178 {0x32, 0xce}, {0xdd, 0xcf},
179 {0x32, 0xd0}, {0xdd, 0xd1},
180 {0x6a, 0xd2}, {0x50, 0xd3},
181 {0x60, 0xd4}, {0x00, 0xd5},
182 {0x00, 0xd6});
183
184 err += sn9c102_i2c_write(cam, 0x12, 0x80);
185 err += sn9c102_i2c_write(cam, 0x12, 0x48);
186 err += sn9c102_i2c_write(cam, 0x01, 0x80);
187 err += sn9c102_i2c_write(cam, 0x02, 0x80);
188 err += sn9c102_i2c_write(cam, 0x03, 0x80);
189 err += sn9c102_i2c_write(cam, 0x04, 0x10);
190 err += sn9c102_i2c_write(cam, 0x05, 0x20);
191 err += sn9c102_i2c_write(cam, 0x06, 0x80);
192 err += sn9c102_i2c_write(cam, 0x11, 0x00);
193 err += sn9c102_i2c_write(cam, 0x0c, 0x20);
194 err += sn9c102_i2c_write(cam, 0x0d, 0x20);
195 err += sn9c102_i2c_write(cam, 0x15, 0x80);
196 err += sn9c102_i2c_write(cam, 0x16, 0x03);
197 err += sn9c102_i2c_write(cam, 0x17, 0x1b);
198 err += sn9c102_i2c_write(cam, 0x18, 0xbd);
199 err += sn9c102_i2c_write(cam, 0x19, 0x05);
200 err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
201 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
202 err += sn9c102_i2c_write(cam, 0x21, 0x1b);
203 err += sn9c102_i2c_write(cam, 0x22, 0x00);
204 err += sn9c102_i2c_write(cam, 0x23, 0xde);
205 err += sn9c102_i2c_write(cam, 0x24, 0x10);
206 err += sn9c102_i2c_write(cam, 0x25, 0x8a);
207 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
208 err += sn9c102_i2c_write(cam, 0x27, 0xca);
209 err += sn9c102_i2c_write(cam, 0x28, 0xa2);
210 err += sn9c102_i2c_write(cam, 0x29, 0x74);
211 err += sn9c102_i2c_write(cam, 0x2a, 0x88);
212 err += sn9c102_i2c_write(cam, 0x2b, 0x34);
213 err += sn9c102_i2c_write(cam, 0x2c, 0x88);
214 err += sn9c102_i2c_write(cam, 0x2e, 0x00);
215 err += sn9c102_i2c_write(cam, 0x2f, 0x00);
216 err += sn9c102_i2c_write(cam, 0x30, 0x00);
217 err += sn9c102_i2c_write(cam, 0x32, 0xc2);
218 err += sn9c102_i2c_write(cam, 0x33, 0x08);
219 err += sn9c102_i2c_write(cam, 0x4c, 0x40);
220 err += sn9c102_i2c_write(cam, 0x4d, 0xf3);
221 err += sn9c102_i2c_write(cam, 0x60, 0x05);
222 err += sn9c102_i2c_write(cam, 0x61, 0x40);
223 err += sn9c102_i2c_write(cam, 0x62, 0x12);
224 err += sn9c102_i2c_write(cam, 0x63, 0x57);
225 err += sn9c102_i2c_write(cam, 0x64, 0x73);
226 err += sn9c102_i2c_write(cam, 0x65, 0x00);
227 err += sn9c102_i2c_write(cam, 0x66, 0x55);
228 err += sn9c102_i2c_write(cam, 0x67, 0x01);
229 err += sn9c102_i2c_write(cam, 0x68, 0xac);
230 err += sn9c102_i2c_write(cam, 0x69, 0x38);
231 err += sn9c102_i2c_write(cam, 0x6f, 0x1f);
232 err += sn9c102_i2c_write(cam, 0x70, 0x01);
233 err += sn9c102_i2c_write(cam, 0x71, 0x00);
234 err += sn9c102_i2c_write(cam, 0x72, 0x10);
235 err += sn9c102_i2c_write(cam, 0x73, 0x50);
236 err += sn9c102_i2c_write(cam, 0x74, 0x20);
237 err += sn9c102_i2c_write(cam, 0x76, 0x01);
238 err += sn9c102_i2c_write(cam, 0x77, 0xf3);
239 err += sn9c102_i2c_write(cam, 0x78, 0x90);
240 err += sn9c102_i2c_write(cam, 0x79, 0x98);
241 err += sn9c102_i2c_write(cam, 0x7a, 0x98);
242 err += sn9c102_i2c_write(cam, 0x7b, 0x00);
243 err += sn9c102_i2c_write(cam, 0x7c, 0x38);
244 err += sn9c102_i2c_write(cam, 0x7d, 0xff);
245 break;
107 default: 246 default:
108 break; 247 break;
109 } 248 }
@@ -115,6 +254,7 @@ static int ov7630_init(struct sn9c102_device* cam)
115static int ov7630_get_ctrl(struct sn9c102_device* cam, 254static int ov7630_get_ctrl(struct sn9c102_device* cam,
116 struct v4l2_control* ctrl) 255 struct v4l2_control* ctrl)
117{ 256{
257 enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
118 int err = 0; 258 int err = 0;
119 259
120 switch (ctrl->id) { 260 switch (ctrl->id) {
@@ -123,13 +263,20 @@ static int ov7630_get_ctrl(struct sn9c102_device* cam,
123 return -EIO; 263 return -EIO;
124 break; 264 break;
125 case V4L2_CID_RED_BALANCE: 265 case V4L2_CID_RED_BALANCE:
126 ctrl->value = sn9c102_pread_reg(cam, 0x07); 266 if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
267 ctrl->value = sn9c102_pread_reg(cam, 0x05);
268 else
269 ctrl->value = sn9c102_pread_reg(cam, 0x07);
127 break; 270 break;
128 case V4L2_CID_BLUE_BALANCE: 271 case V4L2_CID_BLUE_BALANCE:
129 ctrl->value = sn9c102_pread_reg(cam, 0x06); 272 ctrl->value = sn9c102_pread_reg(cam, 0x06);
130 break; 273 break;
131 case SN9C102_V4L2_CID_GREEN_BALANCE: 274 case SN9C102_V4L2_CID_GREEN_BALANCE:
132 ctrl->value = sn9c102_pread_reg(cam, 0x05); 275 if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
276 ctrl->value = sn9c102_pread_reg(cam, 0x07);
277 else
278 ctrl->value = sn9c102_pread_reg(cam, 0x05);
279 break;
133 break; 280 break;
134 case V4L2_CID_GAIN: 281 case V4L2_CID_GAIN:
135 if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0) 282 if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
@@ -177,6 +324,7 @@ static int ov7630_get_ctrl(struct sn9c102_device* cam,
177static int ov7630_set_ctrl(struct sn9c102_device* cam, 324static int ov7630_set_ctrl(struct sn9c102_device* cam,
178 const struct v4l2_control* ctrl) 325 const struct v4l2_control* ctrl)
179{ 326{
327 enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
180 int err = 0; 328 int err = 0;
181 329
182 switch (ctrl->id) { 330 switch (ctrl->id) {
@@ -184,13 +332,19 @@ static int ov7630_set_ctrl(struct sn9c102_device* cam,
184 err += sn9c102_i2c_write(cam, 0x10, ctrl->value); 332 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
185 break; 333 break;
186 case V4L2_CID_RED_BALANCE: 334 case V4L2_CID_RED_BALANCE:
187 err += sn9c102_write_reg(cam, ctrl->value, 0x07); 335 if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
336 err += sn9c102_write_reg(cam, ctrl->value, 0x05);
337 else
338 err += sn9c102_write_reg(cam, ctrl->value, 0x07);
188 break; 339 break;
189 case V4L2_CID_BLUE_BALANCE: 340 case V4L2_CID_BLUE_BALANCE:
190 err += sn9c102_write_reg(cam, ctrl->value, 0x06); 341 err += sn9c102_write_reg(cam, ctrl->value, 0x06);
191 break; 342 break;
192 case SN9C102_V4L2_CID_GREEN_BALANCE: 343 case SN9C102_V4L2_CID_GREEN_BALANCE:
193 err += sn9c102_write_reg(cam, ctrl->value, 0x05); 344 if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
345 err += sn9c102_write_reg(cam, ctrl->value, 0x07);
346 else
347 err += sn9c102_write_reg(cam, ctrl->value, 0x05);
194 break; 348 break;
195 case V4L2_CID_GAIN: 349 case V4L2_CID_GAIN:
196 err += sn9c102_i2c_write(cam, 0x00, ctrl->value); 350 err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
@@ -227,8 +381,21 @@ static int ov7630_set_crop(struct sn9c102_device* cam,
227{ 381{
228 struct sn9c102_sensor* s = sn9c102_get_sensor(cam); 382 struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
229 int err = 0; 383 int err = 0;
230 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1, 384 u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
231 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; 385
386 switch (sn9c102_get_bridge(cam)) {
387 case BRIDGE_SN9C101:
388 case BRIDGE_SN9C102:
389 case BRIDGE_SN9C103:
390 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
391 break;
392 case BRIDGE_SN9C105:
393 case BRIDGE_SN9C120:
394 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
395 break;
396 default:
397 break;
398 }
232 399
233 err += sn9c102_write_reg(cam, h_start, 0x12); 400 err += sn9c102_write_reg(cam, h_start, 0x12);
234 err += sn9c102_write_reg(cam, v_start, 0x13); 401 err += sn9c102_write_reg(cam, v_start, 0x13);
@@ -242,10 +409,28 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam,
242{ 409{
243 int err = 0; 410 int err = 0;
244 411
245 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) 412 switch (sn9c102_get_bridge(cam)) {
246 err += sn9c102_write_reg(cam, 0x20, 0x19); 413 case BRIDGE_SN9C101:
247 else 414 case BRIDGE_SN9C102:
248 err += sn9c102_write_reg(cam, 0x50, 0x19); 415 case BRIDGE_SN9C103:
416 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8)
417 err += sn9c102_write_reg(cam, 0x50, 0x19);
418 else
419 err += sn9c102_write_reg(cam, 0x20, 0x19);
420 break;
421 case BRIDGE_SN9C105:
422 case BRIDGE_SN9C120:
423 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
424 err += sn9c102_write_reg(cam, 0xe5, 0x17);
425 err += sn9c102_i2c_write(cam, 0x11, 0x04);
426 } else {
427 err += sn9c102_write_reg(cam, 0xe2, 0x17);
428 err += sn9c102_i2c_write(cam, 0x11, 0x02);
429 }
430 break;
431 default:
432 break;
433 }
249 434
250 return err; 435 return err;
251} 436}
@@ -254,7 +439,8 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam,
254static const struct sn9c102_sensor ov7630 = { 439static const struct sn9c102_sensor ov7630 = {
255 .name = "OV7630", 440 .name = "OV7630",
256 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 441 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
257 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 442 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103 |
443 BRIDGE_SN9C105 | BRIDGE_SN9C120,
258 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 444 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
259 .frequency = SN9C102_I2C_100KHZ, 445 .frequency = SN9C102_I2C_100KHZ,
260 .interface = SN9C102_I2C_2WIRES, 446 .interface = SN9C102_I2C_2WIRES,
@@ -417,6 +603,12 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
417 err += sn9c102_write_const_regs(cam, {0x01, 0x01}, 603 err += sn9c102_write_const_regs(cam, {0x01, 0x01},
418 {0x00, 0x01}); 604 {0x00, 0x01});
419 break; 605 break;
606 case BRIDGE_SN9C105:
607 case BRIDGE_SN9C120:
608 err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
609 {0x29, 0x01}, {0x74, 0x02},
610 {0x0e, 0x01}, {0x44, 0x01});
611 break;
420 default: 612 default:
421 break; 613 break;
422 } 614 }
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c
index 4b6474048a72..8aae416ba8ec 100644
--- a/drivers/media/video/sn9c102/sn9c102_ov7660.c
+++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c
@@ -41,65 +41,65 @@ static int ov7660_init(struct sn9c102_device* cam)
41 {0xbb, 0x2a}, {0xc7, 0x2b}, 41 {0xbb, 0x2a}, {0xc7, 0x2b},
42 {0xd3, 0x2c}, {0xde, 0x2d}, 42 {0xd3, 0x2c}, {0xde, 0x2d},
43 {0xea, 0x2e}, {0xf4, 0x2f}, 43 {0xea, 0x2e}, {0xf4, 0x2f},
44 {0xff, 0x30}, {0x00, 0x3F}, 44 {0xff, 0x30}, {0x00, 0x3f},
45 {0xC7, 0x40}, {0x01, 0x41}, 45 {0xc7, 0x40}, {0x01, 0x41},
46 {0x44, 0x42}, {0x00, 0x43}, 46 {0x44, 0x42}, {0x00, 0x43},
47 {0x44, 0x44}, {0x00, 0x45}, 47 {0x44, 0x44}, {0x00, 0x45},
48 {0x44, 0x46}, {0x00, 0x47}, 48 {0x44, 0x46}, {0x00, 0x47},
49 {0xC7, 0x48}, {0x01, 0x49}, 49 {0xc7, 0x48}, {0x01, 0x49},
50 {0xC7, 0x4A}, {0x01, 0x4B}, 50 {0xc7, 0x4a}, {0x01, 0x4b},
51 {0xC7, 0x4C}, {0x01, 0x4D}, 51 {0xc7, 0x4c}, {0x01, 0x4d},
52 {0x44, 0x4E}, {0x00, 0x4F}, 52 {0x44, 0x4e}, {0x00, 0x4f},
53 {0x44, 0x50}, {0x00, 0x51}, 53 {0x44, 0x50}, {0x00, 0x51},
54 {0x44, 0x52}, {0x00, 0x53}, 54 {0x44, 0x52}, {0x00, 0x53},
55 {0xC7, 0x54}, {0x01, 0x55}, 55 {0xc7, 0x54}, {0x01, 0x55},
56 {0xC7, 0x56}, {0x01, 0x57}, 56 {0xc7, 0x56}, {0x01, 0x57},
57 {0xC7, 0x58}, {0x01, 0x59}, 57 {0xc7, 0x58}, {0x01, 0x59},
58 {0x44, 0x5A}, {0x00, 0x5B}, 58 {0x44, 0x5a}, {0x00, 0x5b},
59 {0x44, 0x5C}, {0x00, 0x5D}, 59 {0x44, 0x5c}, {0x00, 0x5d},
60 {0x44, 0x5E}, {0x00, 0x5F}, 60 {0x44, 0x5e}, {0x00, 0x5f},
61 {0xC7, 0x60}, {0x01, 0x61}, 61 {0xc7, 0x60}, {0x01, 0x61},
62 {0xC7, 0x62}, {0x01, 0x63}, 62 {0xc7, 0x62}, {0x01, 0x63},
63 {0xC7, 0x64}, {0x01, 0x65}, 63 {0xc7, 0x64}, {0x01, 0x65},
64 {0x44, 0x66}, {0x00, 0x67}, 64 {0x44, 0x66}, {0x00, 0x67},
65 {0x44, 0x68}, {0x00, 0x69}, 65 {0x44, 0x68}, {0x00, 0x69},
66 {0x44, 0x6A}, {0x00, 0x6B}, 66 {0x44, 0x6a}, {0x00, 0x6b},
67 {0xC7, 0x6C}, {0x01, 0x6D}, 67 {0xc7, 0x6c}, {0x01, 0x6d},
68 {0xC7, 0x6E}, {0x01, 0x6F}, 68 {0xc7, 0x6e}, {0x01, 0x6f},
69 {0xC7, 0x70}, {0x01, 0x71}, 69 {0xc7, 0x70}, {0x01, 0x71},
70 {0x44, 0x72}, {0x00, 0x73}, 70 {0x44, 0x72}, {0x00, 0x73},
71 {0x44, 0x74}, {0x00, 0x75}, 71 {0x44, 0x74}, {0x00, 0x75},
72 {0x44, 0x76}, {0x00, 0x77}, 72 {0x44, 0x76}, {0x00, 0x77},
73 {0xC7, 0x78}, {0x01, 0x79}, 73 {0xc7, 0x78}, {0x01, 0x79},
74 {0xC7, 0x7A}, {0x01, 0x7B}, 74 {0xc7, 0x7a}, {0x01, 0x7b},
75 {0xC7, 0x7C}, {0x01, 0x7D}, 75 {0xc7, 0x7c}, {0x01, 0x7d},
76 {0x44, 0x7E}, {0x00, 0x7F}, 76 {0x44, 0x7e}, {0x00, 0x7f},
77 {0x14, 0x84}, {0x00, 0x85}, 77 {0x14, 0x84}, {0x00, 0x85},
78 {0x27, 0x86}, {0x00, 0x87}, 78 {0x27, 0x86}, {0x00, 0x87},
79 {0x07, 0x88}, {0x00, 0x89}, 79 {0x07, 0x88}, {0x00, 0x89},
80 {0xEC, 0x8A}, {0x0f, 0x8B}, 80 {0xec, 0x8a}, {0x0f, 0x8b},
81 {0xD8, 0x8C}, {0x0f, 0x8D}, 81 {0xd8, 0x8c}, {0x0f, 0x8d},
82 {0x3D, 0x8E}, {0x00, 0x8F}, 82 {0x3d, 0x8e}, {0x00, 0x8f},
83 {0x3D, 0x90}, {0x00, 0x91}, 83 {0x3d, 0x90}, {0x00, 0x91},
84 {0xCD, 0x92}, {0x0f, 0x93}, 84 {0xcd, 0x92}, {0x0f, 0x93},
85 {0xf7, 0x94}, {0x0f, 0x95}, 85 {0xf7, 0x94}, {0x0f, 0x95},
86 {0x0C, 0x96}, {0x00, 0x97}, 86 {0x0c, 0x96}, {0x00, 0x97},
87 {0x00, 0x98}, {0x66, 0x99}, 87 {0x00, 0x98}, {0x66, 0x99},
88 {0x05, 0x9A}, {0x00, 0x9B}, 88 {0x05, 0x9a}, {0x00, 0x9b},
89 {0x04, 0x9C}, {0x00, 0x9D}, 89 {0x04, 0x9c}, {0x00, 0x9d},
90 {0x08, 0x9E}, {0x00, 0x9F}, 90 {0x08, 0x9e}, {0x00, 0x9f},
91 {0x2D, 0xC0}, {0x2D, 0xC1}, 91 {0x2d, 0xc0}, {0x2d, 0xc1},
92 {0x3A, 0xC2}, {0x05, 0xC3}, 92 {0x3a, 0xc2}, {0x05, 0xc3},
93 {0x04, 0xC4}, {0x3F, 0xC5}, 93 {0x04, 0xc4}, {0x3f, 0xc5},
94 {0x00, 0xC6}, {0x00, 0xC7}, 94 {0x00, 0xc6}, {0x00, 0xc7},
95 {0x50, 0xC8}, {0x3C, 0xC9}, 95 {0x50, 0xc8}, {0x3C, 0xc9},
96 {0x28, 0xCA}, {0xD8, 0xCB}, 96 {0x28, 0xca}, {0xd8, 0xcb},
97 {0x14, 0xCC}, {0xEC, 0xCD}, 97 {0x14, 0xcc}, {0xec, 0xcd},
98 {0x32, 0xCE}, {0xDD, 0xCF}, 98 {0x32, 0xce}, {0xdd, 0xcf},
99 {0x32, 0xD0}, {0xDD, 0xD1}, 99 {0x32, 0xd0}, {0xdd, 0xd1},
100 {0x6A, 0xD2}, {0x50, 0xD3}, 100 {0x6a, 0xd2}, {0x50, 0xd3},
101 {0x00, 0xD4}, {0x00, 0xD5}, 101 {0x00, 0xd4}, {0x00, 0xd5},
102 {0x00, 0xD6}); 102 {0x00, 0xd6});
103 103
104 err += sn9c102_i2c_write(cam, 0x12, 0x80); 104 err += sn9c102_i2c_write(cam, 0x12, 0x80);
105 err += sn9c102_i2c_write(cam, 0x11, 0x09); 105 err += sn9c102_i2c_write(cam, 0x11, 0x09);