diff options
author | Luca Risolia <luca.risolia@studio.unibo.it> | 2007-06-13 13:37:50 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-07-18 13:24:07 -0400 |
commit | 3770be34199ace8c497ce454cebd7d63347dc4c3 (patch) | |
tree | 4c9c3adef124a1400234a730a7ebca63c8ab63e3 | |
parent | a6e2b40cb430e1e3a22fbb56807edebf71bf6188 (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>
-rw-r--r-- | Documentation/video4linux/sn9c102.txt | 3 | ||||
-rw-r--r-- | drivers/media/video/sn9c102/sn9c102.h | 9 | ||||
-rw-r--r-- | drivers/media/video/sn9c102/sn9c102_core.c | 173 | ||||
-rw-r--r-- | drivers/media/video/sn9c102/sn9c102_ov7630.c | 214 | ||||
-rw-r--r-- | drivers/media/video/sn9c102/sn9c102_ov7660.c | 88 |
5 files changed, 358 insertions, 129 deletions
diff --git a/Documentation/video4linux/sn9c102.txt b/Documentation/video4linux/sn9c102.txt index 279717c96f63..1ffad19ce891 100644 --- a/Documentation/video4linux/sn9c102.txt +++ b/Documentation/video4linux/sn9c102.txt | |||
@@ -436,7 +436,7 @@ HV7131D Hynix Semiconductor | Yes No No No | |||
436 | HV7131R Hynix Semiconductor | No Yes Yes Yes | 436 | HV7131R Hynix Semiconductor | No Yes Yes Yes |
437 | MI-0343 Micron Technology | Yes No No No | 437 | MI-0343 Micron Technology | Yes No No No |
438 | MI-0360 Micron Technology | No Yes Yes Yes | 438 | MI-0360 Micron Technology | No Yes Yes Yes |
439 | OV7630 OmniVision Technologies | Yes Yes No No | 439 | OV7630 OmniVision Technologies | Yes Yes Yes Yes |
440 | OV7660 OmniVision Technologies | No No Yes Yes | 440 | OV7660 OmniVision Technologies | No No Yes Yes |
441 | PAS106B PixArt Imaging | Yes No No No | 441 | PAS106B PixArt Imaging | Yes No No No |
442 | PAS202B PixArt Imaging | Yes Yes No No | 442 | PAS202B PixArt Imaging | Yes Yes No No |
@@ -583,6 +583,7 @@ order): | |||
583 | - Bertrik Sikken, who reverse-engineered and documented the Huffman compression | 583 | - Bertrik Sikken, who reverse-engineered and documented the Huffman compression |
584 | algorithm used in the SN9C101, SN9C102 and SN9C103 controllers and | 584 | algorithm used in the SN9C101, SN9C102 and SN9C103 controllers and |
585 | implemented the first decoder; | 585 | implemented the first decoder; |
586 | - Ronny Standke for the donation of a webcam; | ||
586 | - Mizuno Takafumi for the donation of a webcam; | 587 | - Mizuno Takafumi for the donation of a webcam; |
587 | - an "anonymous" donator (who didn't want his name to be revealed) for the | 588 | - an "anonymous" donator (who didn't want his name to be revealed) for the |
588 | donation of a webcam. | 589 | donation of a webcam. |
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 | ||
96 | static DEFINE_MUTEX(sn9c102_sysfs_lock); | 97 | static DEFINE_MUTEX(sn9c102_sysfs_lock); |
97 | static DECLARE_RWSEM(sn9c102_disconnect); | 98 | static DECLARE_RWSEM(sn9c102_dev_lock); |
98 | 99 | ||
99 | struct sn9c102_device { | 100 | struct 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); | |||
64 | static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; | 64 | static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1}; |
65 | module_param_array(video_nr, short, NULL, 0444); | 65 | module_param_array(video_nr, short, NULL, 0444); |
66 | MODULE_PARM_DESC(video_nr, | 66 | MODULE_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}; |
80 | module_param_array(force_munmap, bool, NULL, 0444); | 81 | module_param_array(force_munmap, bool, NULL, 0444); |
81 | MODULE_PARM_DESC(force_munmap, | 82 | MODULE_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}; |
94 | module_param_array(frame_timeout, uint, NULL, 0644); | 96 | module_param_array(frame_timeout, uint, NULL, 0644); |
95 | MODULE_PARM_DESC(frame_timeout, | 97 | MODULE_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, | |||
103 | static unsigned short debug = SN9C102_DEBUG_LEVEL; | 106 | static unsigned short debug = SN9C102_DEBUG_LEVEL; |
104 | module_param(debug, ushort, 0644); | 107 | module_param(debug, ushort, 0644); |
105 | MODULE_PARM_DESC(debug, | 108 | MODULE_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 | ||
1710 | static void sn9c102_release_resources(struct sn9c102_device* cam) | 1716 | static 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 | ||
1725 | static int sn9c102_open(struct inode* inode, struct file* filp) | 1736 | static 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 | ||
1791 | out: | 1837 | out: |
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 | ||
1798 | static int sn9c102_release(struct inode* inode, struct file* filp) | 1847 | static 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 | ||
3337 | static void sn9c102_usb_disconnect(struct usb_interface* intf) | 3379 | static 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) | |||
115 | static int ov7630_get_ctrl(struct sn9c102_device* cam, | 254 | static 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, | |||
177 | static int ov7630_set_ctrl(struct sn9c102_device* cam, | 324 | static 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, | |||
254 | static const struct sn9c102_sensor ov7630 = { | 439 | static 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); |