aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS9
-rw-r--r--drivers/staging/media/Kconfig2
-rw-r--r--drivers/staging/media/Makefile1
-rw-r--r--drivers/staging/media/sn9c102/Kconfig17
-rw-r--r--drivers/staging/media/sn9c102/Makefile15
-rw-r--r--drivers/staging/media/sn9c102/sn9c102.h214
-rw-r--r--drivers/staging/media/sn9c102/sn9c102.txt592
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_config.h86
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_core.c3465
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_devtable.h145
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_hv7131d.c269
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_hv7131r.c369
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_mi0343.c352
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_mi0360.c453
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_mt9v111.c260
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_ov7630.c634
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_ov7660.c546
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_pas106b.c308
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_pas202bcb.c340
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_sensor.h307
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c154
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_tas5110d.c119
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c165
23 files changed, 0 insertions, 8822 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 134483f206e4..50f81349a16a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9499,15 +9499,6 @@ L: netdev@vger.kernel.org
9499S: Maintained 9499S: Maintained
9500F: drivers/net/usb/smsc95xx.* 9500F: drivers/net/usb/smsc95xx.*
9501 9501
9502USB SN9C1xx DRIVER
9503M: Luca Risolia <luca.risolia@studio.unibo.it>
9504L: linux-usb@vger.kernel.org
9505L: linux-media@vger.kernel.org
9506T: git git://linuxtv.org/media_tree.git
9507W: http://www.linux-projects.org
9508S: Maintained
9509F: drivers/staging/media/sn9c102/
9510
9511USB SUBSYSTEM 9502USB SUBSYSTEM
9512M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> 9503M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
9513L: linux-usb@vger.kernel.org 9504L: linux-usb@vger.kernel.org
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index a9f2e63a7c9c..cd2af3769f7f 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -35,8 +35,6 @@ source "drivers/staging/media/msi3101/Kconfig"
35 35
36source "drivers/staging/media/omap24xx/Kconfig" 36source "drivers/staging/media/omap24xx/Kconfig"
37 37
38source "drivers/staging/media/sn9c102/Kconfig"
39
40source "drivers/staging/media/solo6x10/Kconfig" 38source "drivers/staging/media/solo6x10/Kconfig"
41 39
42source "drivers/staging/media/omap4iss/Kconfig" 40source "drivers/staging/media/omap4iss/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 8e2c5d272162..2766a3e9e053 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_VIDEO_GO7007) += go7007/
8obj-$(CONFIG_USB_MSI3101) += msi3101/ 8obj-$(CONFIG_USB_MSI3101) += msi3101/
9obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ 9obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
10obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ 10obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
11obj-$(CONFIG_USB_SN9C102) += sn9c102/
12obj-$(CONFIG_VIDEO_OMAP2) += omap24xx/ 11obj-$(CONFIG_VIDEO_OMAP2) += omap24xx/
13obj-$(CONFIG_VIDEO_TCM825X) += omap24xx/ 12obj-$(CONFIG_VIDEO_TCM825X) += omap24xx/
14obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832u_sdr/ 13obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832u_sdr/
diff --git a/drivers/staging/media/sn9c102/Kconfig b/drivers/staging/media/sn9c102/Kconfig
deleted file mode 100644
index c9aba59258d9..000000000000
--- a/drivers/staging/media/sn9c102/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
1config USB_SN9C102
2 tristate "USB SN9C1xx PC Camera Controller support (DEPRECATED)"
3 depends on VIDEO_V4L2 && MEDIA_USB_SUPPORT
4 ---help---
5 This driver is DEPRECATED, please use the gspca sonixb and
6 sonixj modules instead.
7
8 Say Y here if you want support for cameras based on SONiX SN9C101,
9 SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
10
11 See <file:drivers/staging/media/sn9c102/sn9c102.txt> for more info.
12
13 If you have webcams that are only supported by this driver and not by
14 the gspca driver, then contact the linux-media mailinglist.
15
16 To compile this driver as a module, choose M here: the
17 module will be called sn9c102.
diff --git a/drivers/staging/media/sn9c102/Makefile b/drivers/staging/media/sn9c102/Makefile
deleted file mode 100644
index 7ecd5a90c7c9..000000000000
--- a/drivers/staging/media/sn9c102/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
1sn9c102-objs := sn9c102_core.o \
2 sn9c102_hv7131d.o \
3 sn9c102_hv7131r.o \
4 sn9c102_mi0343.o \
5 sn9c102_mi0360.o \
6 sn9c102_mt9v111.o \
7 sn9c102_ov7630.o \
8 sn9c102_ov7660.o \
9 sn9c102_pas106b.o \
10 sn9c102_pas202bcb.o \
11 sn9c102_tas5110c1b.o \
12 sn9c102_tas5110d.o \
13 sn9c102_tas5130d1b.o
14
15obj-$(CONFIG_USB_SN9C102) += sn9c102.o
diff --git a/drivers/staging/media/sn9c102/sn9c102.h b/drivers/staging/media/sn9c102/sn9c102.h
deleted file mode 100644
index 37ca7225fcf7..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102.h
+++ /dev/null
@@ -1,214 +0,0 @@
1/***************************************************************************
2 * V4L2 driver for SN9C1xx PC Camera Controllers *
3 * *
4 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 ***************************************************************************/
20
21#ifndef _SN9C102_H_
22#define _SN9C102_H_
23
24#include <linux/usb.h>
25#include <linux/videodev2.h>
26#include <media/v4l2-common.h>
27#include <media/v4l2-ioctl.h>
28#include <media/v4l2-device.h>
29#include <linux/device.h>
30#include <linux/list.h>
31#include <linux/spinlock.h>
32#include <linux/time.h>
33#include <linux/wait.h>
34#include <linux/types.h>
35#include <linux/param.h>
36#include <linux/rwsem.h>
37#include <linux/mutex.h>
38#include <linux/string.h>
39#include <linux/stddef.h>
40#include <linux/kref.h>
41
42#include "sn9c102_config.h"
43#include "sn9c102_sensor.h"
44#include "sn9c102_devtable.h"
45
46
47enum sn9c102_frame_state {
48 F_UNUSED,
49 F_QUEUED,
50 F_GRABBING,
51 F_DONE,
52 F_ERROR,
53};
54
55struct sn9c102_frame_t {
56 void *bufmem;
57 struct v4l2_buffer buf;
58 enum sn9c102_frame_state state;
59 struct list_head frame;
60 unsigned long vma_use_count;
61};
62
63enum sn9c102_dev_state {
64 DEV_INITIALIZED = 0x01,
65 DEV_DISCONNECTED = 0x02,
66 DEV_MISCONFIGURED = 0x04,
67};
68
69enum sn9c102_io_method {
70 IO_NONE,
71 IO_READ,
72 IO_MMAP,
73};
74
75enum sn9c102_stream_state {
76 STREAM_OFF,
77 STREAM_INTERRUPT,
78 STREAM_ON,
79};
80
81typedef char sn9c102_sof_header_t[62];
82
83struct sn9c102_sof_t {
84 sn9c102_sof_header_t header;
85 u16 bytesread;
86};
87
88struct sn9c102_sysfs_attr {
89 u16 reg, i2c_reg;
90 sn9c102_sof_header_t frame_header;
91};
92
93struct sn9c102_module_param {
94 u8 force_munmap;
95 u16 frame_timeout;
96};
97
98static DEFINE_MUTEX(sn9c102_sysfs_lock);
99static DECLARE_RWSEM(sn9c102_dev_lock);
100
101struct sn9c102_device {
102 struct video_device *v4ldev;
103
104 struct v4l2_device v4l2_dev;
105
106 enum sn9c102_bridge bridge;
107 struct sn9c102_sensor sensor;
108
109 struct usb_device *usbdev;
110 struct urb *urb[SN9C102_URBS];
111 void *transfer_buffer[SN9C102_URBS];
112 u8 *control_buffer;
113
114 struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES];
115 struct list_head inqueue, outqueue;
116 u32 frame_count, nbuffers, nreadbuffers;
117
118 enum sn9c102_io_method io;
119 enum sn9c102_stream_state stream;
120
121 struct v4l2_jpegcompression compression;
122
123 struct sn9c102_sysfs_attr sysfs;
124 struct sn9c102_sof_t sof;
125 u16 reg[384];
126
127 struct sn9c102_module_param module_param;
128
129 struct kref kref;
130 enum sn9c102_dev_state state;
131 u8 users;
132
133 struct completion probe;
134 struct mutex open_mutex, fileop_mutex;
135 spinlock_t queue_lock;
136 wait_queue_head_t wait_open, wait_frame, wait_stream;
137};
138
139/*****************************************************************************/
140
141struct sn9c102_device*
142sn9c102_match_id(struct sn9c102_device *cam, const struct usb_device_id *id)
143{
144 return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
145}
146
147
148void
149sn9c102_attach_sensor(struct sn9c102_device *cam,
150 const struct sn9c102_sensor *sensor)
151{
152 memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
153}
154
155
156enum sn9c102_bridge
157sn9c102_get_bridge(struct sn9c102_device *cam)
158{
159 return cam->bridge;
160}
161
162
163struct sn9c102_sensor *sn9c102_get_sensor(struct sn9c102_device *cam)
164{
165 return &cam->sensor;
166}
167
168/*****************************************************************************/
169
170#undef DBG
171#undef KDBG
172#ifdef SN9C102_DEBUG
173# define DBG(level, fmt, args...) \
174do { \
175 if (debug >= (level)) { \
176 if ((level) == 1) \
177 dev_err(&cam->usbdev->dev, fmt "\n", ## args); \
178 else if ((level) == 2) \
179 dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
180 else if ((level) >= 3) \
181 dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
182 __func__, __LINE__ , ## args); \
183 } \
184} while (0)
185# define V4LDBG(level, name, cmd) \
186do { \
187 if (debug >= (level)) \
188 v4l_printk_ioctl(name, cmd); \
189} while (0)
190# define KDBG(level, fmt, args...) \
191do { \
192 if (debug >= (level)) { \
193 if ((level) == 1 || (level) == 2) \
194 pr_info("sn9c102: " fmt "\n", ## args); \
195 else if ((level) == 3) \
196 pr_debug("sn9c102: [%s:%d] " fmt "\n", \
197 __func__, __LINE__ , ## args); \
198 } \
199} while (0)
200#else
201# define DBG(level, fmt, args...) do { ; } while (0)
202# define V4LDBG(level, name, cmd) do { ; } while (0)
203# define KDBG(level, fmt, args...) do { ; } while (0)
204#endif
205
206#undef PDBG
207#define PDBG(fmt, args...) \
208dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \
209 __LINE__ , ## args)
210
211#undef PDBGG
212#define PDBGG(fmt, args...) do { ; } while (0) /* placeholder */
213
214#endif /* _SN9C102_H_ */
diff --git a/drivers/staging/media/sn9c102/sn9c102.txt b/drivers/staging/media/sn9c102/sn9c102.txt
deleted file mode 100644
index b4f67040403a..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102.txt
+++ /dev/null
@@ -1,592 +0,0 @@
1
2 SN9C1xx PC Camera Controllers
3 Driver for Linux
4 =============================
5
6 - Documentation -
7
8
9Index
10=====
111. Copyright
122. Disclaimer
133. License
144. Overview and features
155. Module dependencies
166. Module loading
177. Module parameters
188. Optional device control through "sysfs"
199. Supported devices
2010. Notes for V4L2 application developers
2111. Video frame formats
2212. Contact information
2313. Credits
24
25
261. Copyright
27============
28Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
29
30
312. Disclaimer
32=============
33SONiX is a trademark of SONiX Technology Company Limited, inc.
34This software is not sponsored or developed by SONiX.
35
36
373. License
38==========
39This program is free software; you can redistribute it and/or modify
40it under the terms of the GNU General Public License as published by
41the Free Software Foundation; either version 2 of the License, or
42(at your option) any later version.
43
44This program is distributed in the hope that it will be useful,
45but WITHOUT ANY WARRANTY; without even the implied warranty of
46MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47GNU General Public License for more details.
48
49You should have received a copy of the GNU General Public License
50along with this program; if not, write to the Free Software
51Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
52
53
544. Overview and features
55========================
56This driver attempts to support the video interface of the devices assembling
57the SONiX SN9C101, SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers
58("SN9C1xx" from now on).
59
60The driver relies on the Video4Linux2 and USB core modules. It has been
61designed to run properly on SMP systems as well.
62
63The latest version of the SN9C1xx driver can be found at the following URL:
64http://www.linux-projects.org/
65
66Some of the features of the driver are:
67
68- full compliance with the Video4Linux2 API (see also "Notes for V4L2
69 application developers" paragraph);
70- available mmap or read/poll methods for video streaming through isochronous
71 data transfers;
72- automatic detection of image sensor;
73- support for built-in microphone interface;
74- support for any window resolutions and optional panning within the maximum
75 pixel area of image sensor;
76- image downscaling with arbitrary scaling factors from 1, 2 and 4 in both
77 directions (see "Notes for V4L2 application developers" paragraph);
78- two different video formats for uncompressed or compressed data in low or
79 high compression quality (see also "Notes for V4L2 application developers"
80 and "Video frame formats" paragraphs);
81- full support for the capabilities of many of the possible image sensors that
82 can be connected to the SN9C1xx bridges, including, for instance, red, green,
83 blue and global gain adjustments and exposure (see "Supported devices"
84 paragraph for details);
85- use of default color settings for sunlight conditions;
86- dynamic I/O interface for both SN9C1xx and image sensor control and
87 monitoring (see "Optional device control through 'sysfs'" paragraph);
88- dynamic driver control thanks to various module parameters (see "Module
89 parameters" paragraph);
90- up to 64 cameras can be handled at the same time; they can be connected and
91 disconnected from the host many times without turning off the computer, if
92 the system supports hotplugging;
93- no known bugs.
94
95
965. Module dependencies
97======================
98For it to work properly, the driver needs kernel support for Video4Linux and
99USB.
100
101The following options of the kernel configuration file must be enabled and
102corresponding modules must be compiled:
103
104 # Multimedia devices
105 #
106 CONFIG_VIDEO_DEV=m
107
108To enable advanced debugging functionality on the device through /sysfs:
109
110 # Multimedia devices
111 #
112 CONFIG_VIDEO_ADV_DEBUG=y
113
114 # USB support
115 #
116 CONFIG_USB=m
117
118In addition, depending on the hardware being used, the modules below are
119necessary:
120
121 # USB Host Controller Drivers
122 #
123 CONFIG_USB_EHCI_HCD=m
124 CONFIG_USB_UHCI_HCD=m
125 CONFIG_USB_OHCI_HCD=m
126
127The SN9C103, SN9c105 and SN9C120 controllers also provide a built-in microphone
128interface. It is supported by the USB Audio driver thanks to the ALSA API:
129
130 # Sound
131 #
132 CONFIG_SOUND=y
133
134 # Advanced Linux Sound Architecture
135 #
136 CONFIG_SND=m
137
138 # USB devices
139 #
140 CONFIG_SND_USB_AUDIO=m
141
142And finally:
143
144 # USB Multimedia devices
145 #
146 CONFIG_USB_SN9C102=m
147
148
1496. Module loading
150=================
151To use the driver, it is necessary to load the "sn9c102" module into memory
152after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
153"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
154"uhci-hcd" or "ohci-hcd".
155
156Loading can be done as shown below:
157
158 [root@localhost home]# modprobe sn9c102
159
160Note that the module is called "sn9c102" for historic reasons, although it
161does not just support the SN9C102.
162
163At this point all the devices supported by the driver and connected to the USB
164ports should be recognized. You can invoke "dmesg" to analyze kernel messages
165and verify that the loading process has gone well:
166
167 [user@localhost home]$ dmesg
168
169or, to isolate all the kernel messages generated by the driver:
170
171 [user@localhost home]$ dmesg | grep sn9c102
172
173
1747. Module parameters
175====================
176Module parameters are listed below:
177-------------------------------------------------------------------------------
178Name: video_nr
179Type: short array (min = 0, max = 64)
180Syntax: <-1|n[,...]>
181Description: Specify V4L2 minor mode number:
182 -1 = use next available
183 n = use minor number n
184 You can specify up to 64 cameras this way.
185 For example:
186 video_nr=-1,2,-1 would assign minor number 2 to the second
187 recognized camera and use auto for the first one and for every
188 other camera.
189Default: -1
190-------------------------------------------------------------------------------
191Name: force_munmap
192Type: bool array (min = 0, max = 64)
193Syntax: <0|1[,...]>
194Description: Force the application to unmap previously mapped buffer memory
195 before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
196 all the applications support this feature. This parameter is
197 specific for each detected camera.
198 0 = do not force memory unmapping
199 1 = force memory unmapping (save memory)
200Default: 0
201-------------------------------------------------------------------------------
202Name: frame_timeout
203Type: uint array (min = 0, max = 64)
204Syntax: <0|n[,...]>
205Description: Timeout for a video frame in seconds before returning an I/O
206 error; 0 for infinity. This parameter is specific for each
207 detected camera and can be changed at runtime thanks to the
208 /sys filesystem interface.
209Default: 2
210-------------------------------------------------------------------------------
211Name: debug
212Type: ushort
213Syntax: <n>
214Description: Debugging information level, from 0 to 3:
215 0 = none (use carefully)
216 1 = critical errors
217 2 = significant information
218 3 = more verbose messages
219 Level 3 is useful for testing only. It also shows some more
220 information about the hardware being detected.
221 This parameter can be changed at runtime thanks to the /sys
222 filesystem interface.
223Default: 2
224-------------------------------------------------------------------------------
225
226
2278. Optional device control through "sysfs" [1]
228==========================================
229If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
230it is possible to read and write both the SN9C1xx and the image sensor
231registers by using the "sysfs" filesystem interface.
232
233Every time a supported device is recognized, a write-only file named "green" is
234created 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
236to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103,
237SN9C105 and SN9C120 bridges.
238Similarly, only for the SN9C103, SN9C105 and SN9C120 controllers, blue and red
239gain control files are available in the same directory, for which accepted
240values may range from 0 to 127.
241
242There are other four entries in the directory above for each registered camera:
243"reg", "val", "i2c_reg" and "i2c_val". The first two files control the
244SN9C1xx bridge, while the other two control the sensor chip. "reg" and
245"i2c_reg" hold the values of the current register index where the following
246reading/writing operations are addressed at through "val" and "i2c_val". Their
247use is not intended for end-users. Note that "i2c_reg" and "i2c_val" will not
248be created if the sensor does not actually support the standard I2C protocol or
249its registers are not 8-bit long. Also, remember that you must be logged in as
250root before writing to them.
251
252As an example, suppose we were to want to read the value contained in the
253register number 1 of the sensor register table - which is usually the product
254identifier - of the camera registered as "/dev/video0":
255
256 [root@localhost #] cd /sys/class/video4linux/video0
257 [root@localhost #] echo 1 > i2c_reg
258 [root@localhost #] cat i2c_val
259
260Note that "cat" will fail if sensor registers cannot be read.
261
262Now let's set the green gain's register of the SN9C101 or SN9C102 chips to 2:
263
264 [root@localhost #] echo 0x11 > reg
265 [root@localhost #] echo 2 > val
266
267Note that the SN9C1xx always returns 0 when some of its registers are read.
268To avoid race conditions, all the I/O accesses to the above files are
269serialized.
270The sysfs interface also provides the "frame_header" entry, which exports the
271frame header of the most recent requested and captured video frame. The header
272is always 18-bytes long and is appended to every video frame by the SN9C1xx
273controllers. As an example, this additional information can be used by the user
274application for implementing auto-exposure features via software.
275
276The following table describes the frame header exported by the SN9C101 and
277SN9C102:
278
279Byte # Value or bits Description
280------ ------------- -----------
2810x00 0xFF Frame synchronisation pattern
2820x01 0xFF Frame synchronisation pattern
2830x02 0x00 Frame synchronisation pattern
2840x03 0xC4 Frame synchronisation pattern
2850x04 0xC4 Frame synchronisation pattern
2860x05 0x96 Frame synchronisation pattern
2870x06 [3:0] Read channel gain control = (1+R_GAIN/8)
288 [7:4] Blue channel gain control = (1+B_GAIN/8)
2890x07 [ 0 ] Compression mode. 0=No compression, 1=Compression enabled
290 [2:1] Maximum scale factor for compression
291 [ 3 ] 1 = USB fifo(2K bytes) is full
292 [ 4 ] 1 = Digital gain is finish
293 [ 5 ] 1 = Exposure is finish
294 [7:6] Frame index
2950x08 [7:0] Y sum inside Auto-Exposure area (low-byte)
2960x09 [7:0] Y sum inside Auto-Exposure area (high-byte)
297 where Y sum = (R/4 + 5G/16 + B/8) / 32
2980x0A [7:0] Y sum outside Auto-Exposure area (low-byte)
2990x0B [7:0] Y sum outside Auto-Exposure area (high-byte)
300 where Y sum = (R/4 + 5G/16 + B/8) / 128
3010x0C 0xXX Not used
3020x0D 0xXX Not used
3030x0E 0xXX Not used
3040x0F 0xXX Not used
3050x10 0xXX Not used
3060x11 0xXX Not used
307
308The following table describes the frame header exported by the SN9C103:
309
310Byte # Value or bits Description
311------ ------------- -----------
3120x00 0xFF Frame synchronisation pattern
3130x01 0xFF Frame synchronisation pattern
3140x02 0x00 Frame synchronisation pattern
3150x03 0xC4 Frame synchronisation pattern
3160x04 0xC4 Frame synchronisation pattern
3170x05 0x96 Frame synchronisation pattern
3180x06 [6:0] Read channel gain control = (1/2+R_GAIN/64)
3190x07 [6:0] Blue channel gain control = (1/2+B_GAIN/64)
320 [7:4]
3210x08 [ 0 ] Compression mode. 0=No compression, 1=Compression enabled
322 [2:1] Maximum scale factor for compression
323 [ 3 ] 1 = USB fifo(2K bytes) is full
324 [ 4 ] 1 = Digital gain is finish
325 [ 5 ] 1 = Exposure is finish
326 [7:6] Frame index
3270x09 [7:0] Y sum inside Auto-Exposure area (low-byte)
3280x0A [7:0] Y sum inside Auto-Exposure area (high-byte)
329 where Y sum = (R/4 + 5G/16 + B/8) / 32
3300x0B [7:0] Y sum outside Auto-Exposure area (low-byte)
3310x0C [7:0] Y sum outside Auto-Exposure area (high-byte)
332 where Y sum = (R/4 + 5G/16 + B/8) / 128
3330x0D [1:0] Audio frame number
334 [ 2 ] 1 = Audio is recording
3350x0E [7:0] Audio summation (low-byte)
3360x0F [7:0] Audio summation (high-byte)
3370x10 [7:0] Audio sample count
3380x11 [7:0] Audio peak data in audio frame
339
340The AE area (sx, sy, ex, ey) in the active window can be set by programming the
341registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C1xx controllers, where one unit
342corresponds to 32 pixels.
343
344[1] The frame headers exported by the SN9C105 and SN9C120 are not described.
345
346
3479. Supported devices
348====================
349None of the names of the companies as well as their products will be mentioned
350here. They have never collaborated with the author, so no advertising.
351
352From the point of view of a driver, what unambiguously identify a device are
353its vendor and product USB identifiers. Below is a list of known identifiers of
354devices assembling the SN9C1xx PC camera controllers:
355
356Vendor ID Product ID
357--------- ----------
3580x0458 0x7025
3590x045e 0x00f5
3600x045e 0x00f7
3610x0471 0x0327
3620x0471 0x0328
3630x0c45 0x6001
3640x0c45 0x6005
3650x0c45 0x6007
3660x0c45 0x6009
3670x0c45 0x600d
3680x0c45 0x6011
3690x0c45 0x6019
3700x0c45 0x6024
3710x0c45 0x6025
3720x0c45 0x6028
3730x0c45 0x6029
3740x0c45 0x602a
3750x0c45 0x602b
3760x0c45 0x602c
3770x0c45 0x602d
3780x0c45 0x602e
3790x0c45 0x6030
3800x0c45 0x603f
3810x0c45 0x6080
3820x0c45 0x6082
3830x0c45 0x6083
3840x0c45 0x6088
3850x0c45 0x608a
3860x0c45 0x608b
3870x0c45 0x608c
3880x0c45 0x608e
3890x0c45 0x608f
3900x0c45 0x60a0
3910x0c45 0x60a2
3920x0c45 0x60a3
3930x0c45 0x60a8
3940x0c45 0x60aa
3950x0c45 0x60ab
3960x0c45 0x60ac
3970x0c45 0x60ae
3980x0c45 0x60af
3990x0c45 0x60b0
4000x0c45 0x60b2
4010x0c45 0x60b3
4020x0c45 0x60b8
4030x0c45 0x60ba
4040x0c45 0x60bb
4050x0c45 0x60bc
4060x0c45 0x60be
4070x0c45 0x60c0
4080x0c45 0x60c2
4090x0c45 0x60c8
4100x0c45 0x60cc
4110x0c45 0x60ea
4120x0c45 0x60ec
4130x0c45 0x60ef
4140x0c45 0x60fa
4150x0c45 0x60fb
4160x0c45 0x60fc
4170x0c45 0x60fe
4180x0c45 0x6102
4190x0c45 0x6108
4200x0c45 0x610f
4210x0c45 0x6130
4220x0c45 0x6138
4230x0c45 0x613a
4240x0c45 0x613b
4250x0c45 0x613c
4260x0c45 0x613e
427
428The list above does not imply that all those devices work with this driver: up
429until now only the ones that assemble the following pairs of SN9C1xx bridges
430and image sensors are supported; kernel messages will always tell you whether
431this is the case (see "Module loading" paragraph):
432
433Image sensor / SN9C1xx bridge | SN9C10[12] SN9C103 SN9C105 SN9C120
434-------------------------------------------------------------------------------
435HV7131D Hynix Semiconductor | Yes No No No
436HV7131R Hynix Semiconductor | No Yes Yes Yes
437MI-0343 Micron Technology | Yes No No No
438MI-0360 Micron Technology | No Yes Yes Yes
439OV7630 OmniVision Technologies | Yes Yes Yes Yes
440OV7660 OmniVision Technologies | No No Yes Yes
441PAS106B PixArt Imaging | Yes No No No
442PAS202B PixArt Imaging | Yes Yes No No
443TAS5110C1B Taiwan Advanced Sensor | Yes No No No
444TAS5110D Taiwan Advanced Sensor | Yes No No No
445TAS5130D1B Taiwan Advanced Sensor | Yes No No No
446
447"Yes" means that the pair is supported by the driver, while "No" means that the
448pair does not exist or is not supported by the driver.
449
450Only some of the available control settings of each image sensor are supported
451through the V4L2 interface.
452
453Donations of new models for further testing and support would be much
454appreciated. Non-available hardware will not be supported by the author of this
455driver.
456
457
45810. Notes for V4L2 application developers
459=========================================
460This driver follows the V4L2 API specifications. In particular, it enforces two
461rules:
462
463- exactly one I/O method, either "mmap" or "read", is associated with each
464file descriptor. Once it is selected, the application must close and reopen the
465device to switch to the other I/O method;
466
467- although it is not mandatory, previously mapped buffer memory should always
468be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's.
469The same number of buffers as before will be allocated again to match the size
470of the new video frames, so you have to map the buffers again before any I/O
471attempts on them.
472
473Consistently with the hardware limits, this driver also supports image
474downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions.
475However, the V4L2 API specifications don't correctly define how the scaling
476factor can be chosen arbitrarily by the "negotiation" of the "source" and
477"target" rectangles. To work around this flaw, we have added the convention
478that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
479scaling factor is restored to 1.
480
481This driver supports two different video formats: the first one is the "8-bit
482Sequential Bayer" format and can be used to obtain uncompressed video data
483from the device through the current I/O method, while the second one provides
484either "raw" compressed video data (without frame headers not related to the
485compressed data) or standard JPEG (with frame headers). The compression quality
486may vary from 0 to 1 and can be selected or queried thanks to the
487VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum flexibility,
488both the default active video format and the default compression quality
489depend on how the image sensor being used is initialized.
490
491
49211. Video frame formats [1]
493=======================
494The SN9C1xx PC Camera Controllers can send images in two possible video
495formats over the USB: either native "Sequential RGB Bayer" or compressed.
496The compression is used to achieve high frame rates. With regard to the
497SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding
498algorithm described below, while with regard to the SN9C105 and SN9C120 the
499compression is based on the JPEG standard.
500The current video format may be selected or queried from the user application
501by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2
502API specifications.
503
504The name "Sequential Bayer" indicates the organization of the red, green and
505blue pixels in one video frame. Each pixel is associated with a 8-bit long
506value and is disposed in memory according to the pattern shown below:
507
508B[0] G[1] B[2] G[3] ... B[m-2] G[m-1]
509G[m] R[m+1] G[m+2] R[m+2] ... G[2m-2] R[2m-1]
510...
511... B[(n-1)(m-2)] G[(n-1)(m-1)]
512... G[n(m-2)] R[n(m-1)]
513
514The above matrix also represents the sequential or progressive read-out mode of
515the (n, m) Bayer color filter array used in many CCD or CMOS image sensors.
516
517The Huffman compressed video frame consists of a bitstream that encodes for
518every R, G, or B pixel the difference between the value of the pixel itself and
519some reference pixel value. Pixels are organised in the Bayer pattern and the
520Bayer sub-pixels are tracked individually and alternatingly. For example, in
521the first line values for the B and G1 pixels are alternatingly encoded, while
522in the second line values for the G2 and R pixels are alternatingly encoded.
523
524The pixel reference value is calculated as follows:
525- the 4 top left pixels are encoded in raw uncompressed 8-bit format;
526- the value in the top two rows is the value of the pixel left of the current
527 pixel;
528- the value in the left column is the value of the pixel above the current
529 pixel;
530- for all other pixels, the reference value is the average of the value of the
531 pixel on the left and the value of the pixel above the current pixel;
532- there is one code in the bitstream that specifies the value of a pixel
533 directly (in 4-bit resolution);
534- pixel values need to be clamped inside the range [0..255] for proper
535 decoding.
536
537The algorithm purely describes the conversion from compressed Bayer code used
538in the SN9C101, SN9C102 and SN9C103 chips to uncompressed Bayer. Additional
539steps are required to convert this to a color image (i.e. a color interpolation
540algorithm).
541
542The following Huffman codes have been found:
5430: +0 (relative to reference pixel value)
544100: +4
545101: -4?
5461110xxxx: set absolute value to xxxx.0000
5471101: +11
5481111: -11
54911001: +20
550110000: -20
551110001: ??? - these codes are apparently not used
552
553[1] The Huffman compression algorithm has been reverse-engineered and
554 documented by Bertrik Sikken.
555
556
55712. Contact information
558=======================
559The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
560
561GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is
562'FCE635A4'; the public 1024-bit key should be available at any keyserver;
563the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'.
564
565
56613. Credits
567===========
568Many thanks to following persons for their contribute (listed in alphabetical
569order):
570
571- David Anderson for the donation of a webcam;
572- Luca Capello for the donation of a webcam;
573- Philippe Coval for having helped testing the PAS202BCA image sensor;
574- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
575 donation of a webcam;
576- Dennis Heitmann for the donation of a webcam;
577- Jon Hollstrom for the donation of a webcam;
578- Nick McGill for the donation of a webcam;
579- Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB
580 image sensor;
581- Stefano Mozzi, who donated 45 EU;
582- Andrew Pearce for the donation of a webcam;
583- John Pullan for the donation of a webcam;
584- Bertrik Sikken, who reverse-engineered and documented the Huffman compression
585 algorithm used in the SN9C101, SN9C102 and SN9C103 controllers and
586 implemented the first decoder;
587- Ronny Standke for the donation of a webcam;
588- Mizuno Takafumi for the donation of a webcam;
589- an "anonymous" donator (who didn't want his name to be revealed) for the
590 donation of a webcam.
591- an anonymous donator for the donation of four webcams and two boards with ten
592 image sensors.
diff --git a/drivers/staging/media/sn9c102/sn9c102_config.h b/drivers/staging/media/sn9c102/sn9c102_config.h
deleted file mode 100644
index 0f4e0378b071..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_config.h
+++ /dev/null
@@ -1,86 +0,0 @@
1/***************************************************************************
2 * Global parameters for the V4L2 driver for SN9C1xx PC Camera Controllers *
3 * *
4 * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 ***************************************************************************/
20
21#ifndef _SN9C102_CONFIG_H_
22#define _SN9C102_CONFIG_H_
23
24#include <linux/types.h>
25#include <linux/jiffies.h>
26
27#define SN9C102_DEBUG
28#define SN9C102_DEBUG_LEVEL 2
29#define SN9C102_MAX_DEVICES 64
30#define SN9C102_PRESERVE_IMGSCALE 0
31#define SN9C102_FORCE_MUNMAP 0
32#define SN9C102_MAX_FRAMES 32
33#define SN9C102_URBS 2
34#define SN9C102_ISO_PACKETS 7
35#define SN9C102_ALTERNATE_SETTING 8
36#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
37#define SN9C102_CTRL_TIMEOUT 300
38#define SN9C102_FRAME_TIMEOUT 0
39
40/*****************************************************************************/
41
42static const u8 SN9C102_Y_QTABLE0[64] = {
43 8, 5, 5, 8, 12, 20, 25, 30,
44 6, 6, 7, 9, 13, 29, 30, 27,
45 7, 6, 8, 12, 20, 28, 34, 28,
46 7, 8, 11, 14, 25, 43, 40, 31,
47 9, 11, 18, 28, 34, 54, 51, 38,
48 12, 17, 27, 32, 40, 52, 56, 46,
49 24, 32, 39, 43, 51, 60, 60, 50,
50 36, 46, 47, 49, 56, 50, 51, 49
51};
52
53static const u8 SN9C102_UV_QTABLE0[64] = {
54 8, 9, 12, 23, 49, 49, 49, 49,
55 9, 10, 13, 33, 49, 49, 49, 49,
56 12, 13, 28, 49, 49, 49, 49, 49,
57 23, 33, 49, 49, 49, 49, 49, 49,
58 49, 49, 49, 49, 49, 49, 49, 49,
59 49, 49, 49, 49, 49, 49, 49, 49,
60 49, 49, 49, 49, 49, 49, 49, 49,
61 49, 49, 49, 49, 49, 49, 49, 49
62};
63
64static const u8 SN9C102_Y_QTABLE1[64] = {
65 16, 11, 10, 16, 24, 40, 51, 61,
66 12, 12, 14, 19, 26, 58, 60, 55,
67 14, 13, 16, 24, 40, 57, 69, 56,
68 14, 17, 22, 29, 51, 87, 80, 62,
69 18, 22, 37, 56, 68, 109, 103, 77,
70 24, 35, 55, 64, 81, 104, 113, 92,
71 49, 64, 78, 87, 103, 121, 120, 101,
72 72, 92, 95, 98, 112, 100, 103, 99
73};
74
75static const u8 SN9C102_UV_QTABLE1[64] = {
76 17, 18, 24, 47, 99, 99, 99, 99,
77 18, 21, 26, 66, 99, 99, 99, 99,
78 24, 26, 56, 99, 99, 99, 99, 99,
79 47, 66, 99, 99, 99, 99, 99, 99,
80 99, 99, 99, 99, 99, 99, 99, 99,
81 99, 99, 99, 99, 99, 99, 99, 99,
82 99, 99, 99, 99, 99, 99, 99, 99,
83 99, 99, 99, 99, 99, 99, 99, 99
84};
85
86#endif /* _SN9C102_CONFIG_H_ */
diff --git a/drivers/staging/media/sn9c102/sn9c102_core.c b/drivers/staging/media/sn9c102/sn9c102_core.c
deleted file mode 100644
index 98b30579b0ac..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_core.c
+++ /dev/null
@@ -1,3465 +0,0 @@
1/***************************************************************************
2 * V4L2 driver for SN9C1xx PC Camera Controllers *
3 * *
4 * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 ***************************************************************************/
20
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/kernel.h>
24#include <linux/param.h>
25#include <linux/errno.h>
26#include <linux/slab.h>
27#include <linux/device.h>
28#include <linux/fs.h>
29#include <linux/delay.h>
30#include <linux/compiler.h>
31#include <linux/ioctl.h>
32#include <linux/poll.h>
33#include <linux/stat.h>
34#include <linux/mm.h>
35#include <linux/vmalloc.h>
36#include <linux/version.h>
37#include <linux/page-flags.h>
38#include <asm/byteorder.h>
39#include <asm/page.h>
40#include <asm/uaccess.h>
41
42#include "sn9c102.h"
43
44/*****************************************************************************/
45
46#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers"
47#define SN9C102_MODULE_ALIAS "sn9c1xx"
48#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
49#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
50#define SN9C102_MODULE_LICENSE "GPL"
51#define SN9C102_MODULE_VERSION "1:1.48"
52
53/*****************************************************************************/
54
55MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
56
57MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
58MODULE_DESCRIPTION(SN9C102_MODULE_NAME);
59MODULE_ALIAS(SN9C102_MODULE_ALIAS);
60MODULE_VERSION(SN9C102_MODULE_VERSION);
61MODULE_LICENSE(SN9C102_MODULE_LICENSE);
62
63static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
64module_param_array(video_nr, short, NULL, 0444);
65MODULE_PARM_DESC(video_nr,
66 " <-1|n[,...]>"
67 "\nSpecify V4L2 minor mode number."
68 "\n-1 = use next available (default)"
69 "\n n = use minor number n (integer >= 0)"
70 "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
71 " cameras this way."
72 "\nFor example:"
73 "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
74 "\nthe second camera and use auto for the first"
75 "\none and for every other camera."
76 "\n");
77
78static bool force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
79 SN9C102_FORCE_MUNMAP};
80module_param_array(force_munmap, bool, NULL, 0444);
81MODULE_PARM_DESC(force_munmap,
82 " <0|1[,...]>"
83 "\nForce the application to unmap previously"
84 "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
85 "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
86 "\nthis feature. This parameter is specific for each"
87 "\ndetected camera."
88 "\n0 = do not force memory unmapping"
89 "\n1 = force memory unmapping (save memory)"
90 "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
91 "\n");
92
93static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
94 SN9C102_FRAME_TIMEOUT};
95module_param_array(frame_timeout, uint, NULL, 0644);
96MODULE_PARM_DESC(frame_timeout,
97 " <0|n[,...]>"
98 "\nTimeout for a video frame in seconds before"
99 "\nreturning an I/O error; 0 for infinity."
100 "\nThis parameter is specific for each detected camera."
101 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
102 "\n");
103
104#ifdef SN9C102_DEBUG
105static unsigned short debug = SN9C102_DEBUG_LEVEL;
106module_param(debug, ushort, 0644);
107MODULE_PARM_DESC(debug,
108 " <n>"
109 "\nDebugging information level, from 0 to 3:"
110 "\n0 = none (use carefully)"
111 "\n1 = critical errors"
112 "\n2 = significant informations"
113 "\n3 = more verbose messages"
114 "\nLevel 3 is useful for testing only."
115 "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
116 "\n");
117#endif
118
119/*
120 Add the probe entries to this table. Be sure to add the entry in the right
121 place, since, on failure, the next probing routine is called according to
122 the order of the list below, from top to bottom.
123*/
124static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = {
125 &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
126 &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
127 &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
128 &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
129 &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
130 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
131 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
132 &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
133 &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
134 &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
135 &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
136 &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
137};
138
139/*****************************************************************************/
140
141static u32
142sn9c102_request_buffers(struct sn9c102_device *cam, u32 count,
143 enum sn9c102_io_method io)
144{
145 struct v4l2_pix_format *p = &(cam->sensor.pix_format);
146 struct v4l2_rect *r = &(cam->sensor.cropcap.bounds);
147 size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
148 (p->width * p->height * p->priv) / 8 :
149 (r->width * r->height * p->priv) / 8;
150 void *buff = NULL;
151 u32 i;
152
153 if (count > SN9C102_MAX_FRAMES)
154 count = SN9C102_MAX_FRAMES;
155
156 if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120)
157 imagesize += 589 + 2; /* length of JPEG header + EOI marker */
158
159 cam->nbuffers = count;
160 while (cam->nbuffers > 0) {
161 buff = vmalloc_32_user(cam->nbuffers * PAGE_ALIGN(imagesize));
162 if (buff)
163 break;
164 cam->nbuffers--;
165 }
166
167 for (i = 0; i < cam->nbuffers; i++) {
168 cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize);
169 cam->frame[i].buf.index = i;
170 cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize);
171 cam->frame[i].buf.length = imagesize;
172 cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
173 cam->frame[i].buf.sequence = 0;
174 cam->frame[i].buf.field = V4L2_FIELD_NONE;
175 cam->frame[i].buf.memory = V4L2_MEMORY_MMAP;
176 cam->frame[i].buf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
177 }
178
179 return cam->nbuffers;
180}
181
182
183static void sn9c102_release_buffers(struct sn9c102_device *cam)
184{
185 if (cam->nbuffers) {
186 vfree(cam->frame[0].bufmem);
187 cam->nbuffers = 0;
188 }
189 cam->frame_current = NULL;
190}
191
192
193static void sn9c102_empty_framequeues(struct sn9c102_device *cam)
194{
195 u32 i;
196
197 INIT_LIST_HEAD(&cam->inqueue);
198 INIT_LIST_HEAD(&cam->outqueue);
199
200 for (i = 0; i < SN9C102_MAX_FRAMES; i++) {
201 cam->frame[i].state = F_UNUSED;
202 cam->frame[i].buf.bytesused = 0;
203 }
204}
205
206
207static void sn9c102_requeue_outqueue(struct sn9c102_device *cam)
208{
209 struct sn9c102_frame_t *i;
210
211 list_for_each_entry(i, &cam->outqueue, frame) {
212 i->state = F_QUEUED;
213 list_add(&i->frame, &cam->inqueue);
214 }
215
216 INIT_LIST_HEAD(&cam->outqueue);
217}
218
219
220static void sn9c102_queue_unusedframes(struct sn9c102_device *cam)
221{
222 unsigned long lock_flags;
223 u32 i;
224
225 for (i = 0; i < cam->nbuffers; i++)
226 if (cam->frame[i].state == F_UNUSED) {
227 cam->frame[i].state = F_QUEUED;
228 spin_lock_irqsave(&cam->queue_lock, lock_flags);
229 list_add_tail(&cam->frame[i].frame, &cam->inqueue);
230 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
231 }
232}
233
234/*****************************************************************************/
235
236/*
237 Write a sequence of count value/register pairs. Returns -1 after the first
238 failed write, or 0 for no errors.
239*/
240int sn9c102_write_regs(struct sn9c102_device *cam, const u8 valreg[][2],
241 int count)
242{
243 struct usb_device *udev = cam->usbdev;
244 u8 *buff = cam->control_buffer;
245 int i, res;
246
247 for (i = 0; i < count; i++) {
248 u8 index = valreg[i][1];
249
250 /*
251 index is a u8, so it must be <256 and can't be out of range.
252 If we put in a check anyway, gcc annoys us with a warning
253 hat our check is useless. People get all uppity when they
254 see warnings in the kernel compile.
255 */
256
257 *buff = valreg[i][0];
258
259 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08,
260 0x41, index, 0, buff, 1,
261 SN9C102_CTRL_TIMEOUT);
262
263 if (res < 0) {
264 DBG(3, "Failed to write a register (value 0x%02X, "
265 "index 0x%02X, error %d)", *buff, index, res);
266 return -1;
267 }
268
269 cam->reg[index] = *buff;
270 }
271
272 return 0;
273}
274
275
276int sn9c102_write_reg(struct sn9c102_device *cam, u8 value, u16 index)
277{
278 struct usb_device *udev = cam->usbdev;
279 u8 *buff = cam->control_buffer;
280 int res;
281
282 if (index >= ARRAY_SIZE(cam->reg))
283 return -1;
284
285 *buff = value;
286
287 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
288 index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
289 if (res < 0) {
290 DBG(3, "Failed to write a register (value 0x%02X, index "
291 "0x%02X, error %d)", value, index, res);
292 return -1;
293 }
294
295 cam->reg[index] = value;
296
297 return 0;
298}
299
300
301/* NOTE: with the SN9C10[123] reading some registers always returns 0 */
302int sn9c102_read_reg(struct sn9c102_device *cam, u16 index)
303{
304 struct usb_device *udev = cam->usbdev;
305 u8 *buff = cam->control_buffer;
306 int res;
307
308 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
309 index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
310 if (res < 0)
311 DBG(3, "Failed to read a register (index 0x%02X, error %d)",
312 index, res);
313
314 return (res >= 0) ? (int)(*buff) : -1;
315}
316
317
318int sn9c102_pread_reg(struct sn9c102_device *cam, u16 index)
319{
320 if (index >= ARRAY_SIZE(cam->reg))
321 return -1;
322
323 return cam->reg[index];
324}
325
326
327static int
328sn9c102_i2c_wait(struct sn9c102_device *cam,
329 const struct sn9c102_sensor *sensor)
330{
331 int i, r;
332
333 for (i = 1; i <= 5; i++) {
334 r = sn9c102_read_reg(cam, 0x08);
335 if (r < 0)
336 return -EIO;
337 if (r & 0x04)
338 return 0;
339 if (sensor->frequency & SN9C102_I2C_400KHZ)
340 udelay(5*16);
341 else
342 udelay(16*16);
343 }
344 return -EBUSY;
345}
346
347
348static int
349sn9c102_i2c_detect_read_error(struct sn9c102_device *cam,
350 const struct sn9c102_sensor *sensor)
351{
352 int r , err = 0;
353
354 r = sn9c102_read_reg(cam, 0x08);
355 if (r < 0)
356 err += r;
357
358 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
359 if (!(r & 0x08))
360 err += -1;
361 } else {
362 if (r & 0x08)
363 err += -1;
364 }
365
366 return err ? -EIO : 0;
367}
368
369
370static int
371sn9c102_i2c_detect_write_error(struct sn9c102_device *cam,
372 const struct sn9c102_sensor *sensor)
373{
374 int r;
375
376 r = sn9c102_read_reg(cam, 0x08);
377 return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0;
378}
379
380
381int
382sn9c102_i2c_try_raw_read(struct sn9c102_device *cam,
383 const struct sn9c102_sensor *sensor, u8 data0,
384 u8 data1, u8 n, u8 buffer[])
385{
386 struct usb_device *udev = cam->usbdev;
387 u8 *data = cam->control_buffer;
388 int i = 0, err = 0, res;
389
390 /* Write cycle */
391 data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
392 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
393 data[1] = data0; /* I2C slave id */
394 data[2] = data1; /* address */
395 data[7] = 0x10;
396 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
397 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
398 if (res < 0)
399 err += res;
400
401 err += sn9c102_i2c_wait(cam, sensor);
402
403 /* Read cycle - n bytes */
404 data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
405 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
406 (n << 4) | 0x02;
407 data[1] = data0;
408 data[7] = 0x10;
409 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
410 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
411 if (res < 0)
412 err += res;
413
414 err += sn9c102_i2c_wait(cam, sensor);
415
416 /* The first read byte will be placed in data[4] */
417 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
418 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
419 if (res < 0)
420 err += res;
421
422 err += sn9c102_i2c_detect_read_error(cam, sensor);
423
424 PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1,
425 data[4]);
426
427 if (err) {
428 DBG(3, "I2C read failed for %s image sensor", sensor->name);
429 return -1;
430 }
431
432 if (buffer)
433 for (i = 0; i < n && i < 5; i++)
434 buffer[n-i-1] = data[4-i];
435
436 return (int)data[4];
437}
438
439
440int
441sn9c102_i2c_try_raw_write(struct sn9c102_device *cam,
442 const struct sn9c102_sensor *sensor, u8 n, u8 data0,
443 u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
444{
445 struct usb_device *udev = cam->usbdev;
446 u8 *data = cam->control_buffer;
447 int err = 0, res;
448
449 /* Write cycle. It usually is address + value */
450 data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
451 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
452 | ((n - 1) << 4);
453 data[1] = data0;
454 data[2] = data1;
455 data[3] = data2;
456 data[4] = data3;
457 data[5] = data4;
458 data[6] = data5;
459 data[7] = 0x17;
460 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
461 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
462 if (res < 0)
463 err += res;
464
465 err += sn9c102_i2c_wait(cam, sensor);
466 err += sn9c102_i2c_detect_write_error(cam, sensor);
467
468 if (err)
469 DBG(3, "I2C write failed for %s image sensor", sensor->name);
470
471 PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, "
472 "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X",
473 n, data0, data1, data2, data3, data4, data5);
474
475 return err ? -1 : 0;
476}
477
478
479int
480sn9c102_i2c_try_read(struct sn9c102_device *cam,
481 const struct sn9c102_sensor *sensor, u8 address)
482{
483 return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
484 address, 1, NULL);
485}
486
487
488static int sn9c102_i2c_try_write(struct sn9c102_device *cam,
489 const struct sn9c102_sensor *sensor,
490 u8 address, u8 value)
491{
492 return sn9c102_i2c_try_raw_write(cam, sensor, 3,
493 sensor->i2c_slave_id, address,
494 value, 0, 0, 0);
495}
496
497
498int sn9c102_i2c_read(struct sn9c102_device *cam, u8 address)
499{
500 return sn9c102_i2c_try_read(cam, &cam->sensor, address);
501}
502
503
504int sn9c102_i2c_write(struct sn9c102_device *cam, u8 address, u8 value)
505{
506 return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);
507}
508
509/*****************************************************************************/
510
511static size_t sn9c102_sof_length(struct sn9c102_device *cam)
512{
513 switch (cam->bridge) {
514 case BRIDGE_SN9C101:
515 case BRIDGE_SN9C102:
516 return 12;
517 case BRIDGE_SN9C103:
518 return 18;
519 case BRIDGE_SN9C105:
520 case BRIDGE_SN9C120:
521 return 62;
522 }
523
524 return 0;
525}
526
527
528static void*
529sn9c102_find_sof_header(struct sn9c102_device *cam, void *mem, size_t len)
530{
531 static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
532 const char *m = mem;
533 size_t soflen = 0, i, j;
534
535 soflen = sn9c102_sof_length(cam);
536
537 for (i = 0; i < len; i++) {
538 size_t b;
539
540 /* Read the variable part of the header */
541 if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
542 cam->sof.header[cam->sof.bytesread] = *(m+i);
543 if (++cam->sof.bytesread == soflen) {
544 cam->sof.bytesread = 0;
545 return mem + i;
546 }
547 continue;
548 }
549
550 /* Search for the SOF marker (fixed part) in the header */
551 for (j = 0, b = cam->sof.bytesread; j+b < sizeof(marker); j++) {
552 if (unlikely(i+j == len))
553 return NULL;
554 if (*(m+i+j) == marker[cam->sof.bytesread]) {
555 cam->sof.header[cam->sof.bytesread] = *(m+i+j);
556 if (++cam->sof.bytesread == sizeof(marker)) {
557 PDBGG("Bytes to analyze: %zd. SOF "
558 "starts at byte #%zd", len, i);
559 i += j+1;
560 break;
561 }
562 } else {
563 cam->sof.bytesread = 0;
564 break;
565 }
566 }
567 }
568
569 return NULL;
570}
571
572
573static void*
574sn9c102_find_eof_header(struct sn9c102_device *cam, void *mem, size_t len)
575{
576 static const u8 eof_header[4][4] = {
577 {0x00, 0x00, 0x00, 0x00},
578 {0x40, 0x00, 0x00, 0x00},
579 {0x80, 0x00, 0x00, 0x00},
580 {0xc0, 0x00, 0x00, 0x00},
581 };
582 size_t i, j;
583
584 /* The EOF header does not exist in compressed data */
585 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
586 cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
587 return NULL;
588
589 /*
590 The EOF header might cross the packet boundary, but this is not a
591 problem, since the end of a frame is determined by checking its size
592 in the first place.
593 */
594 for (i = 0; (len >= 4) && (i <= len - 4); i++)
595 for (j = 0; j < ARRAY_SIZE(eof_header); j++)
596 if (!memcmp(mem + i, eof_header[j], 4))
597 return mem + i;
598
599 return NULL;
600}
601
602
603static void
604sn9c102_write_jpegheader(struct sn9c102_device *cam, struct sn9c102_frame_t *f)
605{
606 static const u8 jpeg_header[589] = {
607 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
608 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
609 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
610 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16,
611 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16,
612 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29,
613 0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29,
614 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
615 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28,
616 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
617 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
618 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
619 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
620 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2,
621 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
623 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01,
624 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
625 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
626 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00,
627 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
628 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
629 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
630 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
631 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
632 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
633 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
634 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
635 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
636 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
637 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
638 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
639 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
640 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
641 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
642 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
643 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
644 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
645 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
646 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
647 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
648 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
649 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
650 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19,
651 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
652 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
653 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
654 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
655 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
656 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
657 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
658 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
659 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
660 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
661 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
662 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11,
663 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02,
664 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03,
665 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
666 };
667 u8 *pos = f->bufmem;
668
669 memcpy(pos, jpeg_header, sizeof(jpeg_header));
670 *(pos + 6) = 0x00;
671 *(pos + 7 + 64) = 0x01;
672 if (cam->compression.quality == 0) {
673 memcpy(pos + 7, SN9C102_Y_QTABLE0, 64);
674 memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64);
675 } else if (cam->compression.quality == 1) {
676 memcpy(pos + 7, SN9C102_Y_QTABLE1, 64);
677 memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64);
678 }
679 *(pos + 564) = cam->sensor.pix_format.width & 0xFF;
680 *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF;
681 *(pos + 562) = cam->sensor.pix_format.height & 0xFF;
682 *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF;
683 *(pos + 567) = 0x21;
684
685 f->buf.bytesused += sizeof(jpeg_header);
686}
687
688
689static void sn9c102_urb_complete(struct urb *urb)
690{
691 struct sn9c102_device *cam = urb->context;
692 struct sn9c102_frame_t **f;
693 size_t imagesize, soflen;
694 u8 i;
695 int err = 0;
696
697 if (urb->status == -ENOENT)
698 return;
699
700 f = &cam->frame_current;
701
702 if (cam->stream == STREAM_INTERRUPT) {
703 cam->stream = STREAM_OFF;
704 if ((*f))
705 (*f)->state = F_QUEUED;
706 cam->sof.bytesread = 0;
707 DBG(3, "Stream interrupted by application");
708 wake_up(&cam->wait_stream);
709 }
710
711 if (cam->state & DEV_DISCONNECTED)
712 return;
713
714 if (cam->state & DEV_MISCONFIGURED) {
715 wake_up_interruptible(&cam->wait_frame);
716 return;
717 }
718
719 if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
720 goto resubmit_urb;
721
722 if (!(*f))
723 (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
724 frame);
725
726 imagesize = (cam->sensor.pix_format.width *
727 cam->sensor.pix_format.height *
728 cam->sensor.pix_format.priv) / 8;
729 if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
730 imagesize += 589; /* length of jpeg header */
731 soflen = sn9c102_sof_length(cam);
732
733 for (i = 0; i < urb->number_of_packets; i++) {
734 unsigned int img, len, status;
735 void *pos, *sof, *eof;
736
737 len = urb->iso_frame_desc[i].actual_length;
738 status = urb->iso_frame_desc[i].status;
739 pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
740
741 if (status) {
742 DBG(3, "Error in isochronous frame");
743 (*f)->state = F_ERROR;
744 cam->sof.bytesread = 0;
745 continue;
746 }
747
748 PDBGG("Isochrnous frame: length %u, #%u i", len, i);
749
750redo:
751 sof = sn9c102_find_sof_header(cam, pos, len);
752 if (likely(!sof)) {
753 eof = sn9c102_find_eof_header(cam, pos, len);
754 if ((*f)->state == F_GRABBING) {
755end_of_frame:
756 img = len;
757
758 if (eof)
759 img = (eof > pos) ? eof - pos - 1 : 0;
760
761 if ((*f)->buf.bytesused + img > imagesize) {
762 u32 b;
763 b = (*f)->buf.bytesused + img -
764 imagesize;
765 img = imagesize - (*f)->buf.bytesused;
766 PDBGG("Expected EOF not found: video "
767 "frame cut");
768 if (eof)
769 DBG(3, "Exceeded limit: +%u "
770 "bytes", (unsigned)(b));
771 }
772
773 memcpy((*f)->bufmem + (*f)->buf.bytesused, pos,
774 img);
775
776 if ((*f)->buf.bytesused == 0)
777 v4l2_get_timestamp(
778 &(*f)->buf.timestamp);
779
780 (*f)->buf.bytesused += img;
781
782 if ((*f)->buf.bytesused == imagesize ||
783 ((cam->sensor.pix_format.pixelformat ==
784 V4L2_PIX_FMT_SN9C10X ||
785 cam->sensor.pix_format.pixelformat ==
786 V4L2_PIX_FMT_JPEG) && eof)) {
787 u32 b;
788
789 b = (*f)->buf.bytesused;
790 (*f)->state = F_DONE;
791 (*f)->buf.sequence = ++cam->frame_count;
792
793 spin_lock(&cam->queue_lock);
794 list_move_tail(&(*f)->frame,
795 &cam->outqueue);
796 if (!list_empty(&cam->inqueue))
797 (*f) = list_entry(
798 cam->inqueue.next,
799 struct sn9c102_frame_t,
800 frame);
801 else
802 (*f) = NULL;
803 spin_unlock(&cam->queue_lock);
804
805 memcpy(cam->sysfs.frame_header,
806 cam->sof.header, soflen);
807
808 DBG(3, "Video frame captured: %lu "
809 "bytes", (unsigned long)(b));
810
811 if (!(*f))
812 goto resubmit_urb;
813
814 } else if (eof) {
815 (*f)->state = F_ERROR;
816 DBG(3, "Not expected EOF after %lu "
817 "bytes of image data",
818 (unsigned long)
819 ((*f)->buf.bytesused));
820 }
821
822 if (sof) /* (1) */
823 goto start_of_frame;
824
825 } else if (eof) {
826 DBG(3, "EOF without SOF");
827 continue;
828
829 } else {
830 PDBGG("Ignoring pointless isochronous frame");
831 continue;
832 }
833
834 } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) {
835start_of_frame:
836 (*f)->state = F_GRABBING;
837 (*f)->buf.bytesused = 0;
838 len -= (sof - pos);
839 pos = sof;
840 if (cam->sensor.pix_format.pixelformat ==
841 V4L2_PIX_FMT_JPEG)
842 sn9c102_write_jpegheader(cam, (*f));
843 DBG(3, "SOF detected: new video frame");
844 if (len)
845 goto redo;
846
847 } else if ((*f)->state == F_GRABBING) {
848 eof = sn9c102_find_eof_header(cam, pos, len);
849 if (eof && eof < sof)
850 goto end_of_frame; /* (1) */
851 else {
852 if (cam->sensor.pix_format.pixelformat ==
853 V4L2_PIX_FMT_SN9C10X ||
854 cam->sensor.pix_format.pixelformat ==
855 V4L2_PIX_FMT_JPEG) {
856 if (sof - pos >= soflen) {
857 eof = sof - soflen;
858 } else { /* remove header */
859 eof = pos;
860 (*f)->buf.bytesused -=
861 (soflen - (sof - pos));
862 }
863 goto end_of_frame;
864 } else {
865 DBG(3, "SOF before expected EOF after "
866 "%lu bytes of image data",
867 (unsigned long)
868 ((*f)->buf.bytesused));
869 goto start_of_frame;
870 }
871 }
872 }
873 }
874
875resubmit_urb:
876 urb->dev = cam->usbdev;
877 err = usb_submit_urb(urb, GFP_ATOMIC);
878 if (err < 0 && err != -EPERM) {
879 cam->state |= DEV_MISCONFIGURED;
880 DBG(1, "usb_submit_urb() failed");
881 }
882
883 wake_up_interruptible(&cam->wait_frame);
884}
885
886
887static int sn9c102_start_transfer(struct sn9c102_device *cam)
888{
889 struct usb_device *udev = cam->usbdev;
890 struct urb *urb;
891 struct usb_host_interface *altsetting = usb_altnum_to_altsetting(
892 usb_ifnum_to_if(udev, 0),
893 SN9C102_ALTERNATE_SETTING);
894 const unsigned int psz = le16_to_cpu(altsetting->
895 endpoint[0].desc.wMaxPacketSize);
896 s8 i, j;
897 int err = 0;
898
899 for (i = 0; i < SN9C102_URBS; i++) {
900 cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
901 GFP_KERNEL);
902 if (!cam->transfer_buffer[i]) {
903 err = -ENOMEM;
904 DBG(1, "Not enough memory");
905 goto free_buffers;
906 }
907 }
908
909 for (i = 0; i < SN9C102_URBS; i++) {
910 urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL);
911 cam->urb[i] = urb;
912 if (!urb) {
913 err = -ENOMEM;
914 DBG(1, "usb_alloc_urb() failed");
915 goto free_urbs;
916 }
917 urb->dev = udev;
918 urb->context = cam;
919 urb->pipe = usb_rcvisocpipe(udev, 1);
920 urb->transfer_flags = URB_ISO_ASAP;
921 urb->number_of_packets = SN9C102_ISO_PACKETS;
922 urb->complete = sn9c102_urb_complete;
923 urb->transfer_buffer = cam->transfer_buffer[i];
924 urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS;
925 urb->interval = 1;
926 for (j = 0; j < SN9C102_ISO_PACKETS; j++) {
927 urb->iso_frame_desc[j].offset = psz * j;
928 urb->iso_frame_desc[j].length = psz;
929 }
930 }
931
932 /* Enable video */
933 if (!(cam->reg[0x01] & 0x04)) {
934 err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01);
935 if (err) {
936 err = -EIO;
937 DBG(1, "I/O hardware error");
938 goto free_urbs;
939 }
940 }
941
942 err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING);
943 if (err) {
944 DBG(1, "usb_set_interface() failed");
945 goto free_urbs;
946 }
947
948 cam->frame_current = NULL;
949 cam->sof.bytesread = 0;
950
951 for (i = 0; i < SN9C102_URBS; i++) {
952 err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
953 if (err) {
954 for (j = i-1; j >= 0; j--)
955 usb_kill_urb(cam->urb[j]);
956 DBG(1, "usb_submit_urb() failed, error %d", err);
957 goto free_urbs;
958 }
959 }
960
961 return 0;
962
963free_urbs:
964 for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
965 usb_free_urb(cam->urb[i]);
966
967free_buffers:
968 for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++)
969 kfree(cam->transfer_buffer[i]);
970
971 return err;
972}
973
974
975static int sn9c102_stop_transfer(struct sn9c102_device *cam)
976{
977 struct usb_device *udev = cam->usbdev;
978 s8 i;
979 int err = 0;
980
981 if (cam->state & DEV_DISCONNECTED)
982 return 0;
983
984 for (i = SN9C102_URBS-1; i >= 0; i--) {
985 usb_kill_urb(cam->urb[i]);
986 usb_free_urb(cam->urb[i]);
987 kfree(cam->transfer_buffer[i]);
988 }
989
990 err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
991 if (err)
992 DBG(3, "usb_set_interface() failed");
993
994 return err;
995}
996
997
998static int sn9c102_stream_interrupt(struct sn9c102_device *cam)
999{
1000 cam->stream = STREAM_INTERRUPT;
1001 wait_event_timeout(cam->wait_stream,
1002 (cam->stream == STREAM_OFF) ||
1003 (cam->state & DEV_DISCONNECTED),
1004 SN9C102_URB_TIMEOUT);
1005 if (cam->state & DEV_DISCONNECTED)
1006 return -ENODEV;
1007 else if (cam->stream != STREAM_OFF) {
1008 cam->state |= DEV_MISCONFIGURED;
1009 DBG(1, "URB timeout reached. The camera is misconfigured. "
1010 "To use it, close and open %s again.",
1011 video_device_node_name(cam->v4ldev));
1012 return -EIO;
1013 }
1014
1015 return 0;
1016}
1017
1018/*****************************************************************************/
1019
1020#ifdef CONFIG_VIDEO_ADV_DEBUG
1021static u16 sn9c102_strtou16(const char *buff, size_t len, ssize_t *count)
1022{
1023 char str[7];
1024 char *endp;
1025 unsigned long val;
1026
1027 if (len < 6) {
1028 strncpy(str, buff, len);
1029 str[len] = '\0';
1030 } else {
1031 strncpy(str, buff, 6);
1032 str[6] = '\0';
1033 }
1034
1035 val = simple_strtoul(str, &endp, 0);
1036
1037 *count = 0;
1038 if (val <= 0xffff)
1039 *count = (ssize_t)(endp - str);
1040 if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
1041 *count += 1;
1042
1043 return (u16)val;
1044}
1045
1046/*
1047 NOTE 1: being inside one of the following methods implies that the v4l
1048 device exists for sure (see kobjects and reference counters)
1049 NOTE 2: buffers are PAGE_SIZE long
1050*/
1051
1052static ssize_t sn9c102_show_reg(struct device *cd,
1053 struct device_attribute *attr, char *buf)
1054{
1055 struct sn9c102_device *cam;
1056 ssize_t count;
1057
1058 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1059 return -ERESTARTSYS;
1060
1061 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
1062 if (!cam) {
1063 mutex_unlock(&sn9c102_sysfs_lock);
1064 return -ENODEV;
1065 }
1066
1067 count = sprintf(buf, "%u\n", cam->sysfs.reg);
1068
1069 mutex_unlock(&sn9c102_sysfs_lock);
1070
1071 return count;
1072}
1073
1074
1075static ssize_t
1076sn9c102_store_reg(struct device *cd, struct device_attribute *attr,
1077 const char *buf, size_t len)
1078{
1079 struct sn9c102_device *cam;
1080 u16 index;
1081 ssize_t count;
1082
1083 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1084 return -ERESTARTSYS;
1085
1086 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
1087 if (!cam) {
1088 mutex_unlock(&sn9c102_sysfs_lock);
1089 return -ENODEV;
1090 }
1091
1092 index = sn9c102_strtou16(buf, len, &count);
1093 if (index >= ARRAY_SIZE(cam->reg) || !count) {
1094 mutex_unlock(&sn9c102_sysfs_lock);
1095 return -EINVAL;
1096 }
1097
1098 cam->sysfs.reg = index;
1099
1100 DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg);
1101 DBG(3, "Written bytes: %zd", count);
1102
1103 mutex_unlock(&sn9c102_sysfs_lock);
1104
1105 return count;
1106}
1107
1108
1109static ssize_t sn9c102_show_val(struct device *cd,
1110 struct device_attribute *attr, char *buf)
1111{
1112 struct sn9c102_device *cam;
1113 ssize_t count;
1114 int val;
1115
1116 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1117 return -ERESTARTSYS;
1118
1119 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
1120 if (!cam) {
1121 mutex_unlock(&sn9c102_sysfs_lock);
1122 return -ENODEV;
1123 }
1124
1125 val = sn9c102_read_reg(cam, cam->sysfs.reg);
1126 if (val < 0) {
1127 mutex_unlock(&sn9c102_sysfs_lock);
1128 return -EIO;
1129 }
1130
1131 count = sprintf(buf, "%d\n", val);
1132
1133 DBG(3, "Read bytes: %zd, value: %d", count, val);
1134
1135 mutex_unlock(&sn9c102_sysfs_lock);
1136
1137 return count;
1138}
1139
1140
1141static ssize_t
1142sn9c102_store_val(struct device *cd, struct device_attribute *attr,
1143 const char *buf, size_t len)
1144{
1145 struct sn9c102_device *cam;
1146 u16 value;
1147 ssize_t count;
1148 int err;
1149
1150 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1151 return -ERESTARTSYS;
1152
1153 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
1154 if (!cam) {
1155 mutex_unlock(&sn9c102_sysfs_lock);
1156 return -ENODEV;
1157 }
1158
1159 value = sn9c102_strtou16(buf, len, &count);
1160 if (!count) {
1161 mutex_unlock(&sn9c102_sysfs_lock);
1162 return -EINVAL;
1163 }
1164
1165 err = sn9c102_write_reg(cam, value, cam->sysfs.reg);
1166 if (err) {
1167 mutex_unlock(&sn9c102_sysfs_lock);
1168 return -EIO;
1169 }
1170
1171 DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X",
1172 cam->sysfs.reg, value);
1173 DBG(3, "Written bytes: %zd", count);
1174
1175 mutex_unlock(&sn9c102_sysfs_lock);
1176
1177 return count;
1178}
1179
1180
1181static ssize_t sn9c102_show_i2c_reg(struct device *cd,
1182 struct device_attribute *attr, char *buf)
1183{
1184 struct sn9c102_device *cam;
1185 ssize_t count;
1186
1187 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1188 return -ERESTARTSYS;
1189
1190 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
1191 if (!cam) {
1192 mutex_unlock(&sn9c102_sysfs_lock);
1193 return -ENODEV;
1194 }
1195
1196 count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
1197
1198 DBG(3, "Read bytes: %zd", count);
1199
1200 mutex_unlock(&sn9c102_sysfs_lock);
1201
1202 return count;
1203}
1204
1205
1206static ssize_t
1207sn9c102_store_i2c_reg(struct device *cd, struct device_attribute *attr,
1208 const char *buf, size_t len)
1209{
1210 struct sn9c102_device *cam;
1211 u16 index;
1212 ssize_t count;
1213
1214 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1215 return -ERESTARTSYS;
1216
1217 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
1218 if (!cam) {
1219 mutex_unlock(&sn9c102_sysfs_lock);
1220 return -ENODEV;
1221 }
1222
1223 index = sn9c102_strtou16(buf, len, &count);
1224 if (!count) {
1225 mutex_unlock(&sn9c102_sysfs_lock);
1226 return -EINVAL;
1227 }
1228
1229 cam->sysfs.i2c_reg = index;
1230
1231 DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
1232 DBG(3, "Written bytes: %zd", count);
1233
1234 mutex_unlock(&sn9c102_sysfs_lock);
1235
1236 return count;
1237}
1238
1239
1240static ssize_t sn9c102_show_i2c_val(struct device *cd,
1241 struct device_attribute *attr, char *buf)
1242{
1243 struct sn9c102_device *cam;
1244 ssize_t count;
1245 int val;
1246
1247 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1248 return -ERESTARTSYS;
1249
1250 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
1251 if (!cam) {
1252 mutex_unlock(&sn9c102_sysfs_lock);
1253 return -ENODEV;
1254 }
1255
1256 if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) {
1257 mutex_unlock(&sn9c102_sysfs_lock);
1258 return -ENOSYS;
1259 }
1260
1261 val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg);
1262 if (val < 0) {
1263 mutex_unlock(&sn9c102_sysfs_lock);
1264 return -EIO;
1265 }
1266
1267 count = sprintf(buf, "%d\n", val);
1268
1269 DBG(3, "Read bytes: %zd, value: %d", count, val);
1270
1271 mutex_unlock(&sn9c102_sysfs_lock);
1272
1273 return count;
1274}
1275
1276
1277static ssize_t
1278sn9c102_store_i2c_val(struct device *cd, struct device_attribute *attr,
1279 const char *buf, size_t len)
1280{
1281 struct sn9c102_device *cam;
1282 u16 value;
1283 ssize_t count;
1284 int err;
1285
1286 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1287 return -ERESTARTSYS;
1288
1289 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
1290 if (!cam) {
1291 mutex_unlock(&sn9c102_sysfs_lock);
1292 return -ENODEV;
1293 }
1294
1295 if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) {
1296 mutex_unlock(&sn9c102_sysfs_lock);
1297 return -ENOSYS;
1298 }
1299
1300 value = sn9c102_strtou16(buf, len, &count);
1301 if (!count) {
1302 mutex_unlock(&sn9c102_sysfs_lock);
1303 return -EINVAL;
1304 }
1305
1306 err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value);
1307 if (err) {
1308 mutex_unlock(&sn9c102_sysfs_lock);
1309 return -EIO;
1310 }
1311
1312 DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
1313 cam->sysfs.i2c_reg, value);
1314 DBG(3, "Written bytes: %zd", count);
1315
1316 mutex_unlock(&sn9c102_sysfs_lock);
1317
1318 return count;
1319}
1320
1321
1322static ssize_t
1323sn9c102_store_green(struct device *cd, struct device_attribute *attr,
1324 const char *buf, size_t len)
1325{
1326 struct sn9c102_device *cam;
1327 enum sn9c102_bridge bridge;
1328 ssize_t res = 0;
1329 u16 value;
1330 ssize_t count;
1331
1332 if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
1333 return -ERESTARTSYS;
1334
1335 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
1336 if (!cam) {
1337 mutex_unlock(&sn9c102_sysfs_lock);
1338 return -ENODEV;
1339 }
1340
1341 bridge = cam->bridge;
1342
1343 mutex_unlock(&sn9c102_sysfs_lock);
1344
1345 value = sn9c102_strtou16(buf, len, &count);
1346 if (!count)
1347 return -EINVAL;
1348
1349 switch (bridge) {
1350 case BRIDGE_SN9C101:
1351 case BRIDGE_SN9C102:
1352 if (value > 0x0f)
1353 return -EINVAL;
1354 res = sn9c102_store_reg(cd, attr, "0x11", 4);
1355 if (res >= 0)
1356 res = sn9c102_store_val(cd, attr, buf, len);
1357 break;
1358 case BRIDGE_SN9C103:
1359 case BRIDGE_SN9C105:
1360 case BRIDGE_SN9C120:
1361 if (value > 0x7f)
1362 return -EINVAL;
1363 res = sn9c102_store_reg(cd, attr, "0x07", 4);
1364 if (res >= 0)
1365 res = sn9c102_store_val(cd, attr, buf, len);
1366 break;
1367 }
1368
1369 return res;
1370}
1371
1372
1373static ssize_t
1374sn9c102_store_blue(struct device *cd, struct device_attribute *attr,
1375 const char *buf, size_t len)
1376{
1377 ssize_t res = 0;
1378 u16 value;
1379 ssize_t count;
1380
1381 value = sn9c102_strtou16(buf, len, &count);
1382 if (!count || value > 0x7f)
1383 return -EINVAL;
1384
1385 res = sn9c102_store_reg(cd, attr, "0x06", 4);
1386 if (res >= 0)
1387 res = sn9c102_store_val(cd, attr, buf, len);
1388
1389 return res;
1390}
1391
1392
1393static ssize_t
1394sn9c102_store_red(struct device *cd, struct device_attribute *attr,
1395 const char *buf, size_t len)
1396{
1397 ssize_t res = 0;
1398 u16 value;
1399 ssize_t count;
1400
1401 value = sn9c102_strtou16(buf, len, &count);
1402 if (!count || value > 0x7f)
1403 return -EINVAL;
1404 res = sn9c102_store_reg(cd, attr, "0x05", 4);
1405 if (res >= 0)
1406 res = sn9c102_store_val(cd, attr, buf, len);
1407
1408 return res;
1409}
1410
1411
1412static ssize_t sn9c102_show_frame_header(struct device *cd,
1413 struct device_attribute *attr,
1414 char *buf)
1415{
1416 struct sn9c102_device *cam;
1417 ssize_t count;
1418
1419 cam = video_get_drvdata(container_of(cd, struct video_device, dev));
1420 if (!cam)
1421 return -ENODEV;
1422
1423 count = sizeof(cam->sysfs.frame_header);
1424 memcpy(buf, cam->sysfs.frame_header, count);
1425
1426 DBG(3, "Frame header, read bytes: %zd", count);
1427
1428 return count;
1429}
1430
1431
1432static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg);
1433static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val);
1434static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
1435 sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
1436static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
1437 sn9c102_show_i2c_val, sn9c102_store_i2c_val);
1438static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green);
1439static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue);
1440static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red);
1441static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
1442
1443
1444static int sn9c102_create_sysfs(struct sn9c102_device *cam)
1445{
1446 struct device *dev = &(cam->v4ldev->dev);
1447 int err = 0;
1448
1449 err = device_create_file(dev, &dev_attr_reg);
1450 if (err)
1451 goto err_out;
1452 err = device_create_file(dev, &dev_attr_val);
1453 if (err)
1454 goto err_reg;
1455 err = device_create_file(dev, &dev_attr_frame_header);
1456 if (err)
1457 goto err_val;
1458
1459 if (cam->sensor.sysfs_ops) {
1460 err = device_create_file(dev, &dev_attr_i2c_reg);
1461 if (err)
1462 goto err_frame_header;
1463 err = device_create_file(dev, &dev_attr_i2c_val);
1464 if (err)
1465 goto err_i2c_reg;
1466 }
1467
1468 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
1469 err = device_create_file(dev, &dev_attr_green);
1470 if (err)
1471 goto err_i2c_val;
1472 } else {
1473 err = device_create_file(dev, &dev_attr_blue);
1474 if (err)
1475 goto err_i2c_val;
1476 err = device_create_file(dev, &dev_attr_red);
1477 if (err)
1478 goto err_blue;
1479 }
1480
1481 return 0;
1482
1483err_blue:
1484 device_remove_file(dev, &dev_attr_blue);
1485err_i2c_val:
1486 if (cam->sensor.sysfs_ops)
1487 device_remove_file(dev, &dev_attr_i2c_val);
1488err_i2c_reg:
1489 if (cam->sensor.sysfs_ops)
1490 device_remove_file(dev, &dev_attr_i2c_reg);
1491err_frame_header:
1492 device_remove_file(dev, &dev_attr_frame_header);
1493err_val:
1494 device_remove_file(dev, &dev_attr_val);
1495err_reg:
1496 device_remove_file(dev, &dev_attr_reg);
1497err_out:
1498 return err;
1499}
1500#endif /* CONFIG_VIDEO_ADV_DEBUG */
1501
1502/*****************************************************************************/
1503
1504static int
1505sn9c102_set_pix_format(struct sn9c102_device *cam, struct v4l2_pix_format *pix)
1506{
1507 int err = 0;
1508
1509 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
1510 pix->pixelformat == V4L2_PIX_FMT_JPEG) {
1511 switch (cam->bridge) {
1512 case BRIDGE_SN9C101:
1513 case BRIDGE_SN9C102:
1514 case BRIDGE_SN9C103:
1515 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
1516 0x18);
1517 break;
1518 case BRIDGE_SN9C105:
1519 case BRIDGE_SN9C120:
1520 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
1521 0x18);
1522 break;
1523 }
1524 } else {
1525 switch (cam->bridge) {
1526 case BRIDGE_SN9C101:
1527 case BRIDGE_SN9C102:
1528 case BRIDGE_SN9C103:
1529 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
1530 0x18);
1531 break;
1532 case BRIDGE_SN9C105:
1533 case BRIDGE_SN9C120:
1534 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
1535 0x18);
1536 break;
1537 }
1538 }
1539
1540 return err ? -EIO : 0;
1541}
1542
1543
1544static int
1545sn9c102_set_compression(struct sn9c102_device *cam,
1546 struct v4l2_jpegcompression *compression)
1547{
1548 int i, err = 0;
1549
1550 switch (cam->bridge) {
1551 case BRIDGE_SN9C101:
1552 case BRIDGE_SN9C102:
1553 case BRIDGE_SN9C103:
1554 if (compression->quality == 0)
1555 err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
1556 0x17);
1557 else if (compression->quality == 1)
1558 err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
1559 0x17);
1560 break;
1561 case BRIDGE_SN9C105:
1562 case BRIDGE_SN9C120:
1563 if (compression->quality == 0) {
1564 for (i = 0; i <= 63; i++) {
1565 err += sn9c102_write_reg(cam,
1566 SN9C102_Y_QTABLE1[i],
1567 0x100 + i);
1568 err += sn9c102_write_reg(cam,
1569 SN9C102_UV_QTABLE1[i],
1570 0x140 + i);
1571 }
1572 err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
1573 0x18);
1574 } else if (compression->quality == 1) {
1575 for (i = 0; i <= 63; i++) {
1576 err += sn9c102_write_reg(cam,
1577 SN9C102_Y_QTABLE1[i],
1578 0x100 + i);
1579 err += sn9c102_write_reg(cam,
1580 SN9C102_UV_QTABLE1[i],
1581 0x140 + i);
1582 }
1583 err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40,
1584 0x18);
1585 }
1586 break;
1587 }
1588
1589 return err ? -EIO : 0;
1590}
1591
1592
1593static int sn9c102_set_scale(struct sn9c102_device *cam, u8 scale)
1594{
1595 u8 r = 0;
1596 int err = 0;
1597
1598 if (scale == 1)
1599 r = cam->reg[0x18] & 0xcf;
1600 else if (scale == 2) {
1601 r = cam->reg[0x18] & 0xcf;
1602 r |= 0x10;
1603 } else if (scale == 4)
1604 r = cam->reg[0x18] | 0x20;
1605
1606 err += sn9c102_write_reg(cam, r, 0x18);
1607 if (err)
1608 return -EIO;
1609
1610 PDBGG("Scaling factor: %u", scale);
1611
1612 return 0;
1613}
1614
1615
1616static int sn9c102_set_crop(struct sn9c102_device *cam, struct v4l2_rect *rect)
1617{
1618 struct sn9c102_sensor *s = &cam->sensor;
1619 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),
1620 v_start = (u8)(rect->top - s->cropcap.bounds.top),
1621 h_size = (u8)(rect->width / 16),
1622 v_size = (u8)(rect->height / 16);
1623 int err = 0;
1624
1625 err += sn9c102_write_reg(cam, h_start, 0x12);
1626 err += sn9c102_write_reg(cam, v_start, 0x13);
1627 err += sn9c102_write_reg(cam, h_size, 0x15);
1628 err += sn9c102_write_reg(cam, v_size, 0x16);
1629 if (err)
1630 return -EIO;
1631
1632 PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
1633 "%u %u %u %u", h_start, v_start, h_size, v_size);
1634
1635 return 0;
1636}
1637
1638
1639static int sn9c102_init(struct sn9c102_device *cam)
1640{
1641 struct sn9c102_sensor *s = &cam->sensor;
1642 struct v4l2_control ctrl;
1643 struct v4l2_queryctrl *qctrl;
1644 struct v4l2_rect *rect;
1645 u8 i = 0;
1646 int err = 0;
1647
1648 if (!(cam->state & DEV_INITIALIZED)) {
1649 mutex_init(&cam->open_mutex);
1650 init_waitqueue_head(&cam->wait_open);
1651 qctrl = s->qctrl;
1652 rect = &(s->cropcap.defrect);
1653 } else { /* use current values */
1654 qctrl = s->_qctrl;
1655 rect = &(s->_rect);
1656 }
1657
1658 err += sn9c102_set_scale(cam, rect->width / s->pix_format.width);
1659 err += sn9c102_set_crop(cam, rect);
1660 if (err)
1661 return err;
1662
1663 if (s->init) {
1664 err = s->init(cam);
1665 if (err) {
1666 DBG(3, "Sensor initialization failed");
1667 return err;
1668 }
1669 }
1670
1671 if (!(cam->state & DEV_INITIALIZED))
1672 if (cam->bridge == BRIDGE_SN9C101 ||
1673 cam->bridge == BRIDGE_SN9C102 ||
1674 cam->bridge == BRIDGE_SN9C103) {
1675 if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
1676 s->pix_format.pixelformat = V4L2_PIX_FMT_SBGGR8;
1677 cam->compression.quality = cam->reg[0x17] & 0x01 ?
1678 0 : 1;
1679 } else {
1680 if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
1681 s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
1682 cam->compression.quality = cam->reg[0x18] & 0x40 ?
1683 0 : 1;
1684 err += sn9c102_set_compression(cam, &cam->compression);
1685 }
1686 else
1687 err += sn9c102_set_compression(cam, &cam->compression);
1688 err += sn9c102_set_pix_format(cam, &s->pix_format);
1689 if (s->set_pix_format)
1690 err += s->set_pix_format(cam, &s->pix_format);
1691 if (err)
1692 return err;
1693
1694 if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
1695 s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
1696 DBG(3, "Compressed video format is active, quality %d",
1697 cam->compression.quality);
1698 else
1699 DBG(3, "Uncompressed video format is active");
1700
1701 if (s->set_crop) {
1702 err = s->set_crop(cam, rect);
1703 if (err) {
1704 DBG(3, "set_crop() failed");
1705 return err;
1706 }
1707 }
1708
1709 if (s->set_ctrl) {
1710 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
1711 if (s->qctrl[i].id != 0 &&
1712 !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
1713 ctrl.id = s->qctrl[i].id;
1714 ctrl.value = qctrl[i].default_value;
1715 err = s->set_ctrl(cam, &ctrl);
1716 if (err) {
1717 DBG(3, "Set %s control failed",
1718 s->qctrl[i].name);
1719 return err;
1720 }
1721 DBG(3, "Image sensor supports '%s' control",
1722 s->qctrl[i].name);
1723 }
1724 }
1725
1726 if (!(cam->state & DEV_INITIALIZED)) {
1727 mutex_init(&cam->fileop_mutex);
1728 spin_lock_init(&cam->queue_lock);
1729 init_waitqueue_head(&cam->wait_frame);
1730 init_waitqueue_head(&cam->wait_stream);
1731 cam->nreadbuffers = 2;
1732 memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
1733 memcpy(&(s->_rect), &(s->cropcap.defrect),
1734 sizeof(struct v4l2_rect));
1735 cam->state |= DEV_INITIALIZED;
1736 }
1737
1738 DBG(2, "Initialization succeeded");
1739 return 0;
1740}
1741
1742/*****************************************************************************/
1743
1744static void sn9c102_release_resources(struct kref *kref)
1745{
1746 struct sn9c102_device *cam;
1747
1748 mutex_lock(&sn9c102_sysfs_lock);
1749
1750 cam = container_of(kref, struct sn9c102_device, kref);
1751
1752 DBG(2, "V4L2 device %s deregistered",
1753 video_device_node_name(cam->v4ldev));
1754 video_set_drvdata(cam->v4ldev, NULL);
1755 video_unregister_device(cam->v4ldev);
1756 v4l2_device_unregister(&cam->v4l2_dev);
1757 usb_put_dev(cam->usbdev);
1758 kfree(cam->control_buffer);
1759 kfree(cam);
1760
1761 mutex_unlock(&sn9c102_sysfs_lock);
1762
1763}
1764
1765
1766static int sn9c102_open(struct file *filp)
1767{
1768 struct sn9c102_device *cam;
1769 int err = 0;
1770
1771 /*
1772 A read_trylock() in open() is the only safe way to prevent race
1773 conditions with disconnect(), one close() and multiple (not
1774 necessarily simultaneous) attempts to open(). For example, it
1775 prevents from waiting for a second access, while the device
1776 structure is being deallocated, after a possible disconnect() and
1777 during a following close() holding the write lock: given that, after
1778 this deallocation, no access will be possible anymore, using the
1779 non-trylock version would have let open() gain the access to the
1780 device structure improperly.
1781 For this reason the lock must also not be per-device.
1782 */
1783 if (!down_read_trylock(&sn9c102_dev_lock))
1784 return -ERESTARTSYS;
1785
1786 cam = video_drvdata(filp);
1787
1788 if (wait_for_completion_interruptible(&cam->probe)) {
1789 up_read(&sn9c102_dev_lock);
1790 return -ERESTARTSYS;
1791 }
1792
1793 kref_get(&cam->kref);
1794
1795 /*
1796 Make sure to isolate all the simultaneous opens.
1797 */
1798 if (mutex_lock_interruptible(&cam->open_mutex)) {
1799 kref_put(&cam->kref, sn9c102_release_resources);
1800 up_read(&sn9c102_dev_lock);
1801 return -ERESTARTSYS;
1802 }
1803
1804 if (cam->state & DEV_DISCONNECTED) {
1805 DBG(1, "Device not present");
1806 err = -ENODEV;
1807 goto out;
1808 }
1809
1810 if (cam->users) {
1811 DBG(2, "Device %s is already in use",
1812 video_device_node_name(cam->v4ldev));
1813 DBG(3, "Simultaneous opens are not supported");
1814 /*
1815 open() must follow the open flags and should block
1816 eventually while the device is in use.
1817 */
1818 if ((filp->f_flags & O_NONBLOCK) ||
1819 (filp->f_flags & O_NDELAY)) {
1820 err = -EWOULDBLOCK;
1821 goto out;
1822 }
1823 DBG(2, "A blocking open() has been requested. Wait for the "
1824 "device to be released...");
1825 up_read(&sn9c102_dev_lock);
1826 /*
1827 We will not release the "open_mutex" lock, so that only one
1828 process can be in the wait queue below. This way the process
1829 will be sleeping while holding the lock, without losing its
1830 priority after any wake_up().
1831 */
1832 err = wait_event_interruptible_exclusive(cam->wait_open,
1833 (cam->state & DEV_DISCONNECTED)
1834 || !cam->users);
1835 down_read(&sn9c102_dev_lock);
1836 if (err)
1837 goto out;
1838 if (cam->state & DEV_DISCONNECTED) {
1839 err = -ENODEV;
1840 goto out;
1841 }
1842 }
1843
1844 if (cam->state & DEV_MISCONFIGURED) {
1845 err = sn9c102_init(cam);
1846 if (err) {
1847 DBG(1, "Initialization failed again. "
1848 "I will retry on next open().");
1849 goto out;
1850 }
1851 cam->state &= ~DEV_MISCONFIGURED;
1852 }
1853
1854 err = sn9c102_start_transfer(cam);
1855 if (err)
1856 goto out;
1857
1858 filp->private_data = cam;
1859 cam->users++;
1860 cam->io = IO_NONE;
1861 cam->stream = STREAM_OFF;
1862 cam->nbuffers = 0;
1863 cam->frame_count = 0;
1864 sn9c102_empty_framequeues(cam);
1865
1866 DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev));
1867
1868out:
1869 mutex_unlock(&cam->open_mutex);
1870 if (err)
1871 kref_put(&cam->kref, sn9c102_release_resources);
1872
1873 up_read(&sn9c102_dev_lock);
1874 return err;
1875}
1876
1877
1878static int sn9c102_release(struct file *filp)
1879{
1880 struct sn9c102_device *cam;
1881
1882 down_write(&sn9c102_dev_lock);
1883
1884 cam = video_drvdata(filp);
1885
1886 sn9c102_stop_transfer(cam);
1887 sn9c102_release_buffers(cam);
1888 cam->users--;
1889 wake_up_interruptible_nr(&cam->wait_open, 1);
1890
1891 DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev));
1892
1893 kref_put(&cam->kref, sn9c102_release_resources);
1894
1895 up_write(&sn9c102_dev_lock);
1896
1897 return 0;
1898}
1899
1900
1901static ssize_t
1902sn9c102_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
1903{
1904 struct sn9c102_device *cam = video_drvdata(filp);
1905 struct sn9c102_frame_t *f, *i;
1906 unsigned long lock_flags;
1907 long timeout;
1908 int err = 0;
1909
1910 if (mutex_lock_interruptible(&cam->fileop_mutex))
1911 return -ERESTARTSYS;
1912
1913 if (cam->state & DEV_DISCONNECTED) {
1914 DBG(1, "Device not present");
1915 mutex_unlock(&cam->fileop_mutex);
1916 return -ENODEV;
1917 }
1918
1919 if (cam->state & DEV_MISCONFIGURED) {
1920 DBG(1, "The camera is misconfigured. Close and open it "
1921 "again.");
1922 mutex_unlock(&cam->fileop_mutex);
1923 return -EIO;
1924 }
1925
1926 if (cam->io == IO_MMAP) {
1927 DBG(3, "Close and open the device again to choose "
1928 "the read method");
1929 mutex_unlock(&cam->fileop_mutex);
1930 return -EBUSY;
1931 }
1932
1933 if (cam->io == IO_NONE) {
1934 if (!sn9c102_request_buffers(cam, cam->nreadbuffers, IO_READ)) {
1935 DBG(1, "read() failed, not enough memory");
1936 mutex_unlock(&cam->fileop_mutex);
1937 return -ENOMEM;
1938 }
1939 cam->io = IO_READ;
1940 cam->stream = STREAM_ON;
1941 }
1942
1943 if (list_empty(&cam->inqueue)) {
1944 if (!list_empty(&cam->outqueue))
1945 sn9c102_empty_framequeues(cam);
1946 sn9c102_queue_unusedframes(cam);
1947 }
1948
1949 if (!count) {
1950 mutex_unlock(&cam->fileop_mutex);
1951 return 0;
1952 }
1953
1954 if (list_empty(&cam->outqueue)) {
1955 if (filp->f_flags & O_NONBLOCK) {
1956 mutex_unlock(&cam->fileop_mutex);
1957 return -EAGAIN;
1958 }
1959 if (!cam->module_param.frame_timeout) {
1960 err = wait_event_interruptible
1961 (cam->wait_frame,
1962 (!list_empty(&cam->outqueue)) ||
1963 (cam->state & DEV_DISCONNECTED) ||
1964 (cam->state & DEV_MISCONFIGURED));
1965 if (err) {
1966 mutex_unlock(&cam->fileop_mutex);
1967 return err;
1968 }
1969 } else {
1970 timeout = wait_event_interruptible_timeout
1971 (cam->wait_frame,
1972 (!list_empty(&cam->outqueue)) ||
1973 (cam->state & DEV_DISCONNECTED) ||
1974 (cam->state & DEV_MISCONFIGURED),
1975 msecs_to_jiffies(
1976 cam->module_param.frame_timeout * 1000
1977 )
1978 );
1979 if (timeout < 0) {
1980 mutex_unlock(&cam->fileop_mutex);
1981 return timeout;
1982 } else if (timeout == 0 &&
1983 !(cam->state & DEV_DISCONNECTED)) {
1984 DBG(1, "Video frame timeout elapsed");
1985 mutex_unlock(&cam->fileop_mutex);
1986 return -EIO;
1987 }
1988 }
1989 if (cam->state & DEV_DISCONNECTED) {
1990 mutex_unlock(&cam->fileop_mutex);
1991 return -ENODEV;
1992 }
1993 if (cam->state & DEV_MISCONFIGURED) {
1994 mutex_unlock(&cam->fileop_mutex);
1995 return -EIO;
1996 }
1997 }
1998
1999 f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
2000
2001 if (count > f->buf.bytesused)
2002 count = f->buf.bytesused;
2003
2004 if (copy_to_user(buf, f->bufmem, count)) {
2005 err = -EFAULT;
2006 goto exit;
2007 }
2008 *f_pos += count;
2009
2010exit:
2011 spin_lock_irqsave(&cam->queue_lock, lock_flags);
2012 list_for_each_entry(i, &cam->outqueue, frame)
2013 i->state = F_UNUSED;
2014 INIT_LIST_HEAD(&cam->outqueue);
2015 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
2016
2017 sn9c102_queue_unusedframes(cam);
2018
2019 PDBGG("Frame #%lu, bytes read: %zu",
2020 (unsigned long)f->buf.index, count);
2021
2022 mutex_unlock(&cam->fileop_mutex);
2023
2024 return count;
2025}
2026
2027
2028static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
2029{
2030 struct sn9c102_device *cam = video_drvdata(filp);
2031 struct sn9c102_frame_t *f;
2032 unsigned long lock_flags;
2033 unsigned int mask = 0;
2034
2035 if (mutex_lock_interruptible(&cam->fileop_mutex))
2036 return POLLERR;
2037
2038 if (cam->state & DEV_DISCONNECTED) {
2039 DBG(1, "Device not present");
2040 goto error;
2041 }
2042
2043 if (cam->state & DEV_MISCONFIGURED) {
2044 DBG(1, "The camera is misconfigured. Close and open it "
2045 "again.");
2046 goto error;
2047 }
2048
2049 if (cam->io == IO_NONE) {
2050 if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
2051 IO_READ)) {
2052 DBG(1, "poll() failed, not enough memory");
2053 goto error;
2054 }
2055 cam->io = IO_READ;
2056 cam->stream = STREAM_ON;
2057 }
2058
2059 if (cam->io == IO_READ) {
2060 spin_lock_irqsave(&cam->queue_lock, lock_flags);
2061 list_for_each_entry(f, &cam->outqueue, frame)
2062 f->state = F_UNUSED;
2063 INIT_LIST_HEAD(&cam->outqueue);
2064 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
2065 sn9c102_queue_unusedframes(cam);
2066 }
2067
2068 poll_wait(filp, &cam->wait_frame, wait);
2069
2070 if (!list_empty(&cam->outqueue))
2071 mask |= POLLIN | POLLRDNORM;
2072
2073 mutex_unlock(&cam->fileop_mutex);
2074
2075 return mask;
2076
2077error:
2078 mutex_unlock(&cam->fileop_mutex);
2079 return POLLERR;
2080}
2081
2082
2083static void sn9c102_vm_open(struct vm_area_struct *vma)
2084{
2085 struct sn9c102_frame_t *f = vma->vm_private_data;
2086 f->vma_use_count++;
2087}
2088
2089
2090static void sn9c102_vm_close(struct vm_area_struct *vma)
2091{
2092 /* NOTE: buffers are not freed here */
2093 struct sn9c102_frame_t *f = vma->vm_private_data;
2094 f->vma_use_count--;
2095}
2096
2097
2098static const struct vm_operations_struct sn9c102_vm_ops = {
2099 .open = sn9c102_vm_open,
2100 .close = sn9c102_vm_close,
2101};
2102
2103
2104static int sn9c102_mmap(struct file *filp, struct vm_area_struct *vma)
2105{
2106 struct sn9c102_device *cam = video_drvdata(filp);
2107 unsigned long size = vma->vm_end - vma->vm_start,
2108 start = vma->vm_start;
2109 void *pos;
2110 u32 i;
2111
2112 if (mutex_lock_interruptible(&cam->fileop_mutex))
2113 return -ERESTARTSYS;
2114
2115 if (cam->state & DEV_DISCONNECTED) {
2116 DBG(1, "Device not present");
2117 mutex_unlock(&cam->fileop_mutex);
2118 return -ENODEV;
2119 }
2120
2121 if (cam->state & DEV_MISCONFIGURED) {
2122 DBG(1, "The camera is misconfigured. Close and open it "
2123 "again.");
2124 mutex_unlock(&cam->fileop_mutex);
2125 return -EIO;
2126 }
2127
2128 if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
2129 mutex_unlock(&cam->fileop_mutex);
2130 return -EACCES;
2131 }
2132
2133 if (cam->io != IO_MMAP ||
2134 size != PAGE_ALIGN(cam->frame[0].buf.length)) {
2135 mutex_unlock(&cam->fileop_mutex);
2136 return -EINVAL;
2137 }
2138
2139 for (i = 0; i < cam->nbuffers; i++) {
2140 if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)
2141 break;
2142 }
2143 if (i == cam->nbuffers) {
2144 mutex_unlock(&cam->fileop_mutex);
2145 return -EINVAL;
2146 }
2147
2148 vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
2149
2150 pos = cam->frame[i].bufmem;
2151 while (size > 0) { /* size is page-aligned */
2152 if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
2153 mutex_unlock(&cam->fileop_mutex);
2154 return -EAGAIN;
2155 }
2156 start += PAGE_SIZE;
2157 pos += PAGE_SIZE;
2158 size -= PAGE_SIZE;
2159 }
2160
2161 vma->vm_ops = &sn9c102_vm_ops;
2162 vma->vm_private_data = &cam->frame[i];
2163 sn9c102_vm_open(vma);
2164
2165 mutex_unlock(&cam->fileop_mutex);
2166
2167 return 0;
2168}
2169
2170/*****************************************************************************/
2171
2172static int
2173sn9c102_vidioc_querycap(struct sn9c102_device *cam, void __user *arg)
2174{
2175 struct v4l2_capability cap = {
2176 .driver = "sn9c102",
2177 .version = LINUX_VERSION_CODE,
2178 .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
2179 V4L2_CAP_STREAMING,
2180 };
2181
2182 strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
2183 if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
2184 strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev),
2185 sizeof(cap.bus_info));
2186
2187 if (copy_to_user(arg, &cap, sizeof(cap)))
2188 return -EFAULT;
2189
2190 return 0;
2191}
2192
2193
2194static int
2195sn9c102_vidioc_enuminput(struct sn9c102_device *cam, void __user *arg)
2196{
2197 struct v4l2_input i;
2198
2199 if (copy_from_user(&i, arg, sizeof(i)))
2200 return -EFAULT;
2201
2202 if (i.index)
2203 return -EINVAL;
2204
2205 memset(&i, 0, sizeof(i));
2206 strcpy(i.name, "Camera");
2207 i.type = V4L2_INPUT_TYPE_CAMERA;
2208 i.capabilities = V4L2_IN_CAP_STD;
2209
2210 if (copy_to_user(arg, &i, sizeof(i)))
2211 return -EFAULT;
2212
2213 return 0;
2214}
2215
2216
2217static int
2218sn9c102_vidioc_g_input(struct sn9c102_device *cam, void __user *arg)
2219{
2220 int index = 0;
2221
2222 if (copy_to_user(arg, &index, sizeof(index)))
2223 return -EFAULT;
2224
2225 return 0;
2226}
2227
2228
2229static int
2230sn9c102_vidioc_s_input(struct sn9c102_device *cam, void __user *arg)
2231{
2232 int index;
2233
2234 if (copy_from_user(&index, arg, sizeof(index)))
2235 return -EFAULT;
2236
2237 if (index != 0)
2238 return -EINVAL;
2239
2240 return 0;
2241}
2242
2243
2244static int
2245sn9c102_vidioc_query_ctrl(struct sn9c102_device *cam, void __user *arg)
2246{
2247 struct sn9c102_sensor *s = &cam->sensor;
2248 struct v4l2_queryctrl qc;
2249 u8 i;
2250
2251 if (copy_from_user(&qc, arg, sizeof(qc)))
2252 return -EFAULT;
2253
2254 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
2255 if (qc.id && qc.id == s->qctrl[i].id) {
2256 memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
2257 if (copy_to_user(arg, &qc, sizeof(qc)))
2258 return -EFAULT;
2259 return 0;
2260 }
2261
2262 return -EINVAL;
2263}
2264
2265
2266static int
2267sn9c102_vidioc_g_ctrl(struct sn9c102_device *cam, void __user *arg)
2268{
2269 struct sn9c102_sensor *s = &cam->sensor;
2270 struct v4l2_control ctrl;
2271 int err = 0;
2272 u8 i;
2273
2274 if (!s->get_ctrl && !s->set_ctrl)
2275 return -EINVAL;
2276
2277 if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
2278 return -EFAULT;
2279
2280 if (!s->get_ctrl) {
2281 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
2282 if (ctrl.id && ctrl.id == s->qctrl[i].id) {
2283 ctrl.value = s->_qctrl[i].default_value;
2284 goto exit;
2285 }
2286 return -EINVAL;
2287 } else
2288 err = s->get_ctrl(cam, &ctrl);
2289
2290exit:
2291 if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
2292 return -EFAULT;
2293
2294 PDBGG("VIDIOC_G_CTRL: id %lu, value %lu",
2295 (unsigned long)ctrl.id, (unsigned long)ctrl.value);
2296
2297 return err;
2298}
2299
2300
2301static int
2302sn9c102_vidioc_s_ctrl(struct sn9c102_device *cam, void __user *arg)
2303{
2304 struct sn9c102_sensor *s = &cam->sensor;
2305 struct v4l2_control ctrl;
2306 u8 i;
2307 int err = 0;
2308
2309 if (!s->set_ctrl)
2310 return -EINVAL;
2311
2312 if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
2313 return -EFAULT;
2314
2315 for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) {
2316 if (ctrl.id == s->qctrl[i].id) {
2317 if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
2318 return -EINVAL;
2319 if (ctrl.value < s->qctrl[i].minimum ||
2320 ctrl.value > s->qctrl[i].maximum)
2321 return -ERANGE;
2322 ctrl.value -= ctrl.value % s->qctrl[i].step;
2323 break;
2324 }
2325 }
2326 if (i == ARRAY_SIZE(s->qctrl))
2327 return -EINVAL;
2328 err = s->set_ctrl(cam, &ctrl);
2329 if (err)
2330 return err;
2331
2332 s->_qctrl[i].default_value = ctrl.value;
2333
2334 PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
2335 (unsigned long)ctrl.id, (unsigned long)ctrl.value);
2336
2337 return 0;
2338}
2339
2340
2341static int
2342sn9c102_vidioc_cropcap(struct sn9c102_device *cam, void __user *arg)
2343{
2344 struct v4l2_cropcap *cc = &(cam->sensor.cropcap);
2345
2346 cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2347 cc->pixelaspect.numerator = 1;
2348 cc->pixelaspect.denominator = 1;
2349
2350 if (copy_to_user(arg, cc, sizeof(*cc)))
2351 return -EFAULT;
2352
2353 return 0;
2354}
2355
2356
2357static int
2358sn9c102_vidioc_g_crop(struct sn9c102_device *cam, void __user *arg)
2359{
2360 struct sn9c102_sensor *s = &cam->sensor;
2361 struct v4l2_crop crop = {
2362 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
2363 };
2364
2365 memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
2366
2367 if (copy_to_user(arg, &crop, sizeof(crop)))
2368 return -EFAULT;
2369
2370 return 0;
2371}
2372
2373
2374static int
2375sn9c102_vidioc_s_crop(struct sn9c102_device *cam, void __user *arg)
2376{
2377 struct sn9c102_sensor *s = &cam->sensor;
2378 struct v4l2_crop crop;
2379 struct v4l2_rect *rect;
2380 struct v4l2_rect *bounds = &(s->cropcap.bounds);
2381 struct v4l2_pix_format *pix_format = &(s->pix_format);
2382 u8 scale;
2383 const enum sn9c102_stream_state stream = cam->stream;
2384 const u32 nbuffers = cam->nbuffers;
2385 u32 i;
2386 int err = 0;
2387
2388 if (copy_from_user(&crop, arg, sizeof(crop)))
2389 return -EFAULT;
2390
2391 rect = &(crop.c);
2392
2393 if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2394 return -EINVAL;
2395
2396 if (cam->module_param.force_munmap)
2397 for (i = 0; i < cam->nbuffers; i++)
2398 if (cam->frame[i].vma_use_count) {
2399 DBG(3, "VIDIOC_S_CROP failed. "
2400 "Unmap the buffers first.");
2401 return -EBUSY;
2402 }
2403
2404 /* Preserve R,G or B origin */
2405 rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
2406 rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
2407
2408 if (rect->width < 16)
2409 rect->width = 16;
2410 if (rect->height < 16)
2411 rect->height = 16;
2412 if (rect->width > bounds->width)
2413 rect->width = bounds->width;
2414 if (rect->height > bounds->height)
2415 rect->height = bounds->height;
2416 if (rect->left < bounds->left)
2417 rect->left = bounds->left;
2418 if (rect->top < bounds->top)
2419 rect->top = bounds->top;
2420 if (rect->left + rect->width > bounds->left + bounds->width)
2421 rect->left = bounds->left+bounds->width - rect->width;
2422 if (rect->top + rect->height > bounds->top + bounds->height)
2423 rect->top = bounds->top+bounds->height - rect->height;
2424
2425 rect->width &= ~15L;
2426 rect->height &= ~15L;
2427
2428 if (SN9C102_PRESERVE_IMGSCALE) {
2429 /* Calculate the actual scaling factor */
2430 u32 a, b;
2431 a = rect->width * rect->height;
2432 b = pix_format->width * pix_format->height;
2433 scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
2434 } else
2435 scale = 1;
2436
2437 if (cam->stream == STREAM_ON) {
2438 err = sn9c102_stream_interrupt(cam);
2439 if (err)
2440 return err;
2441 }
2442
2443 if (copy_to_user(arg, &crop, sizeof(crop))) {
2444 cam->stream = stream;
2445 return -EFAULT;
2446 }
2447
2448 if (cam->module_param.force_munmap || cam->io == IO_READ)
2449 sn9c102_release_buffers(cam);
2450
2451 err = sn9c102_set_crop(cam, rect);
2452 if (s->set_crop)
2453 err += s->set_crop(cam, rect);
2454 err += sn9c102_set_scale(cam, scale);
2455
2456 if (err) { /* atomic, no rollback in ioctl() */
2457 cam->state |= DEV_MISCONFIGURED;
2458 DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
2459 "use the camera, close and open %s again.",
2460 video_device_node_name(cam->v4ldev));
2461 return -EIO;
2462 }
2463
2464 s->pix_format.width = rect->width/scale;
2465 s->pix_format.height = rect->height/scale;
2466 memcpy(&(s->_rect), rect, sizeof(*rect));
2467
2468 if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
2469 nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
2470 cam->state |= DEV_MISCONFIGURED;
2471 DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
2472 "use the camera, close and open %s again.",
2473 video_device_node_name(cam->v4ldev));
2474 return -ENOMEM;
2475 }
2476
2477 if (cam->io == IO_READ)
2478 sn9c102_empty_framequeues(cam);
2479 else if (cam->module_param.force_munmap)
2480 sn9c102_requeue_outqueue(cam);
2481
2482 cam->stream = stream;
2483
2484 return 0;
2485}
2486
2487
2488static int
2489sn9c102_vidioc_enum_framesizes(struct sn9c102_device *cam, void __user *arg)
2490{
2491 struct v4l2_frmsizeenum frmsize;
2492
2493 if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
2494 return -EFAULT;
2495
2496 if (frmsize.index != 0)
2497 return -EINVAL;
2498
2499 switch (cam->bridge) {
2500 case BRIDGE_SN9C101:
2501 case BRIDGE_SN9C102:
2502 case BRIDGE_SN9C103:
2503 if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
2504 frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
2505 return -EINVAL;
2506 break;
2507 case BRIDGE_SN9C105:
2508 case BRIDGE_SN9C120:
2509 if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
2510 frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
2511 return -EINVAL;
2512 break;
2513 }
2514
2515 frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
2516 frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
2517 frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
2518 frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
2519 frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
2520 memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
2521
2522 if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
2523 return -EFAULT;
2524
2525 return 0;
2526}
2527
2528
2529static int
2530sn9c102_vidioc_enum_fmt(struct sn9c102_device *cam, void __user *arg)
2531{
2532 struct v4l2_fmtdesc fmtd;
2533
2534 if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
2535 return -EFAULT;
2536
2537 if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2538 return -EINVAL;
2539
2540 if (fmtd.index == 0) {
2541 strcpy(fmtd.description, "bayer rgb");
2542 fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
2543 } else if (fmtd.index == 1) {
2544 switch (cam->bridge) {
2545 case BRIDGE_SN9C101:
2546 case BRIDGE_SN9C102:
2547 case BRIDGE_SN9C103:
2548 strcpy(fmtd.description, "compressed");
2549 fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
2550 break;
2551 case BRIDGE_SN9C105:
2552 case BRIDGE_SN9C120:
2553 strcpy(fmtd.description, "JPEG");
2554 fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
2555 break;
2556 }
2557 fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
2558 } else
2559 return -EINVAL;
2560
2561 fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2562 memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
2563
2564 if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
2565 return -EFAULT;
2566
2567 return 0;
2568}
2569
2570
2571static int
2572sn9c102_vidioc_g_fmt(struct sn9c102_device *cam, void __user *arg)
2573{
2574 struct v4l2_format format;
2575 struct v4l2_pix_format *pfmt = &(cam->sensor.pix_format);
2576
2577 if (copy_from_user(&format, arg, sizeof(format)))
2578 return -EFAULT;
2579
2580 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2581 return -EINVAL;
2582
2583 pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
2584 V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
2585 pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
2586 pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
2587 ? 0 : (pfmt->width * pfmt->priv) / 8;
2588 pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
2589 pfmt->field = V4L2_FIELD_NONE;
2590 memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
2591
2592 if (copy_to_user(arg, &format, sizeof(format)))
2593 return -EFAULT;
2594
2595 return 0;
2596}
2597
2598
2599static int
2600sn9c102_vidioc_try_s_fmt(struct sn9c102_device *cam, unsigned int cmd,
2601 void __user *arg)
2602{
2603 struct sn9c102_sensor *s = &cam->sensor;
2604 struct v4l2_format format;
2605 struct v4l2_pix_format *pix;
2606 struct v4l2_pix_format *pfmt = &(s->pix_format);
2607 struct v4l2_rect *bounds = &(s->cropcap.bounds);
2608 struct v4l2_rect rect;
2609 u8 scale;
2610 const enum sn9c102_stream_state stream = cam->stream;
2611 const u32 nbuffers = cam->nbuffers;
2612 u32 i;
2613 int err = 0;
2614
2615 if (copy_from_user(&format, arg, sizeof(format)))
2616 return -EFAULT;
2617
2618 pix = &(format.fmt.pix);
2619
2620 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2621 return -EINVAL;
2622
2623 memcpy(&rect, &(s->_rect), sizeof(rect));
2624
2625 { /* calculate the actual scaling factor */
2626 u32 a, b;
2627 a = rect.width * rect.height;
2628 b = pix->width * pix->height;
2629 scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
2630 }
2631
2632 rect.width = scale * pix->width;
2633 rect.height = scale * pix->height;
2634
2635 if (rect.width < 16)
2636 rect.width = 16;
2637 if (rect.height < 16)
2638 rect.height = 16;
2639 if (rect.width > bounds->left + bounds->width - rect.left)
2640 rect.width = bounds->left + bounds->width - rect.left;
2641 if (rect.height > bounds->top + bounds->height - rect.top)
2642 rect.height = bounds->top + bounds->height - rect.top;
2643
2644 rect.width &= ~15L;
2645 rect.height &= ~15L;
2646
2647 { /* adjust the scaling factor */
2648 u32 a, b;
2649 a = rect.width * rect.height;
2650 b = pix->width * pix->height;
2651 scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
2652 }
2653
2654 pix->width = rect.width / scale;
2655 pix->height = rect.height / scale;
2656
2657 switch (cam->bridge) {
2658 case BRIDGE_SN9C101:
2659 case BRIDGE_SN9C102:
2660 case BRIDGE_SN9C103:
2661 if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
2662 pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
2663 pix->pixelformat = pfmt->pixelformat;
2664 break;
2665 case BRIDGE_SN9C105:
2666 case BRIDGE_SN9C120:
2667 if (pix->pixelformat != V4L2_PIX_FMT_JPEG &&
2668 pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
2669 pix->pixelformat = pfmt->pixelformat;
2670 break;
2671 }
2672 pix->priv = pfmt->priv; /* bpp */
2673 pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
2674 V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
2675 pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
2676 pix->pixelformat == V4L2_PIX_FMT_JPEG)
2677 ? 0 : (pix->width * pix->priv) / 8;
2678 pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
2679 pix->field = V4L2_FIELD_NONE;
2680
2681 if (cmd == VIDIOC_TRY_FMT) {
2682 if (copy_to_user(arg, &format, sizeof(format)))
2683 return -EFAULT;
2684 return 0;
2685 }
2686
2687 if (cam->module_param.force_munmap)
2688 for (i = 0; i < cam->nbuffers; i++)
2689 if (cam->frame[i].vma_use_count) {
2690 DBG(3, "VIDIOC_S_FMT failed. Unmap the "
2691 "buffers first.");
2692 return -EBUSY;
2693 }
2694
2695 if (cam->stream == STREAM_ON) {
2696 err = sn9c102_stream_interrupt(cam);
2697 if (err)
2698 return err;
2699 }
2700
2701 if (copy_to_user(arg, &format, sizeof(format))) {
2702 cam->stream = stream;
2703 return -EFAULT;
2704 }
2705
2706 if (cam->module_param.force_munmap || cam->io == IO_READ)
2707 sn9c102_release_buffers(cam);
2708
2709 err += sn9c102_set_pix_format(cam, pix);
2710 err += sn9c102_set_crop(cam, &rect);
2711 if (s->set_pix_format)
2712 err += s->set_pix_format(cam, pix);
2713 if (s->set_crop)
2714 err += s->set_crop(cam, &rect);
2715 err += sn9c102_set_scale(cam, scale);
2716
2717 if (err) { /* atomic, no rollback in ioctl() */
2718 cam->state |= DEV_MISCONFIGURED;
2719 DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
2720 "use the camera, close and open %s again.",
2721 video_device_node_name(cam->v4ldev));
2722 return -EIO;
2723 }
2724
2725 memcpy(pfmt, pix, sizeof(*pix));
2726 memcpy(&(s->_rect), &rect, sizeof(rect));
2727
2728 if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
2729 nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
2730 cam->state |= DEV_MISCONFIGURED;
2731 DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
2732 "use the camera, close and open %s again.",
2733 video_device_node_name(cam->v4ldev));
2734 return -ENOMEM;
2735 }
2736
2737 if (cam->io == IO_READ)
2738 sn9c102_empty_framequeues(cam);
2739 else if (cam->module_param.force_munmap)
2740 sn9c102_requeue_outqueue(cam);
2741
2742 cam->stream = stream;
2743
2744 return 0;
2745}
2746
2747
2748static int
2749sn9c102_vidioc_g_jpegcomp(struct sn9c102_device *cam, void __user *arg)
2750{
2751 if (copy_to_user(arg, &cam->compression, sizeof(cam->compression)))
2752 return -EFAULT;
2753
2754 return 0;
2755}
2756
2757
2758static int
2759sn9c102_vidioc_s_jpegcomp(struct sn9c102_device *cam, void __user *arg)
2760{
2761 struct v4l2_jpegcompression jc;
2762 const enum sn9c102_stream_state stream = cam->stream;
2763 int err = 0;
2764
2765 if (copy_from_user(&jc, arg, sizeof(jc)))
2766 return -EFAULT;
2767
2768 if (jc.quality != 0 && jc.quality != 1)
2769 return -EINVAL;
2770
2771 if (cam->stream == STREAM_ON) {
2772 err = sn9c102_stream_interrupt(cam);
2773 if (err)
2774 return err;
2775 }
2776
2777 err += sn9c102_set_compression(cam, &jc);
2778 if (err) { /* atomic, no rollback in ioctl() */
2779 cam->state |= DEV_MISCONFIGURED;
2780 DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. "
2781 "To use the camera, close and open %s again.",
2782 video_device_node_name(cam->v4ldev));
2783 return -EIO;
2784 }
2785
2786 cam->compression.quality = jc.quality;
2787
2788 cam->stream = stream;
2789
2790 return 0;
2791}
2792
2793
2794static int
2795sn9c102_vidioc_reqbufs(struct sn9c102_device *cam, void __user *arg)
2796{
2797 struct v4l2_requestbuffers rb;
2798 u32 i;
2799 int err;
2800
2801 if (copy_from_user(&rb, arg, sizeof(rb)))
2802 return -EFAULT;
2803
2804 if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2805 rb.memory != V4L2_MEMORY_MMAP)
2806 return -EINVAL;
2807
2808 if (cam->io == IO_READ) {
2809 DBG(3, "Close and open the device again to choose the mmap "
2810 "I/O method");
2811 return -EBUSY;
2812 }
2813
2814 for (i = 0; i < cam->nbuffers; i++)
2815 if (cam->frame[i].vma_use_count) {
2816 DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
2817 "still mapped.");
2818 return -EBUSY;
2819 }
2820
2821 if (cam->stream == STREAM_ON) {
2822 err = sn9c102_stream_interrupt(cam);
2823 if (err)
2824 return err;
2825 }
2826
2827 sn9c102_empty_framequeues(cam);
2828
2829 sn9c102_release_buffers(cam);
2830 if (rb.count)
2831 rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP);
2832
2833 if (copy_to_user(arg, &rb, sizeof(rb))) {
2834 sn9c102_release_buffers(cam);
2835 cam->io = IO_NONE;
2836 return -EFAULT;
2837 }
2838
2839 cam->io = rb.count ? IO_MMAP : IO_NONE;
2840
2841 return 0;
2842}
2843
2844
2845static int
2846sn9c102_vidioc_querybuf(struct sn9c102_device *cam, void __user *arg)
2847{
2848 struct v4l2_buffer b;
2849
2850 if (copy_from_user(&b, arg, sizeof(b)))
2851 return -EFAULT;
2852
2853 if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2854 b.index >= cam->nbuffers || cam->io != IO_MMAP)
2855 return -EINVAL;
2856
2857 b = cam->frame[b.index].buf;
2858
2859 if (cam->frame[b.index].vma_use_count)
2860 b.flags |= V4L2_BUF_FLAG_MAPPED;
2861
2862 if (cam->frame[b.index].state == F_DONE)
2863 b.flags |= V4L2_BUF_FLAG_DONE;
2864 else if (cam->frame[b.index].state != F_UNUSED)
2865 b.flags |= V4L2_BUF_FLAG_QUEUED;
2866
2867 if (copy_to_user(arg, &b, sizeof(b)))
2868 return -EFAULT;
2869
2870 return 0;
2871}
2872
2873
2874static int
2875sn9c102_vidioc_qbuf(struct sn9c102_device *cam, void __user *arg)
2876{
2877 struct v4l2_buffer b;
2878 unsigned long lock_flags;
2879
2880 if (copy_from_user(&b, arg, sizeof(b)))
2881 return -EFAULT;
2882
2883 if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
2884 b.index >= cam->nbuffers || cam->io != IO_MMAP)
2885 return -EINVAL;
2886
2887 if (cam->frame[b.index].state != F_UNUSED)
2888 return -EINVAL;
2889
2890 cam->frame[b.index].state = F_QUEUED;
2891
2892 spin_lock_irqsave(&cam->queue_lock, lock_flags);
2893 list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
2894 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
2895
2896 PDBGG("Frame #%lu queued", (unsigned long)b.index);
2897
2898 return 0;
2899}
2900
2901
2902static int
2903sn9c102_vidioc_dqbuf(struct sn9c102_device *cam, struct file *filp,
2904 void __user *arg)
2905{
2906 struct v4l2_buffer b;
2907 struct sn9c102_frame_t *f;
2908 unsigned long lock_flags;
2909 long timeout;
2910 int err = 0;
2911
2912 if (copy_from_user(&b, arg, sizeof(b)))
2913 return -EFAULT;
2914
2915 if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
2916 return -EINVAL;
2917
2918 if (list_empty(&cam->outqueue)) {
2919 if (cam->stream == STREAM_OFF)
2920 return -EINVAL;
2921 if (filp->f_flags & O_NONBLOCK)
2922 return -EAGAIN;
2923 if (!cam->module_param.frame_timeout) {
2924 err = wait_event_interruptible
2925 (cam->wait_frame,
2926 (!list_empty(&cam->outqueue)) ||
2927 (cam->state & DEV_DISCONNECTED) ||
2928 (cam->state & DEV_MISCONFIGURED));
2929 if (err)
2930 return err;
2931 } else {
2932 timeout = wait_event_interruptible_timeout
2933 (cam->wait_frame,
2934 (!list_empty(&cam->outqueue)) ||
2935 (cam->state & DEV_DISCONNECTED) ||
2936 (cam->state & DEV_MISCONFIGURED),
2937 cam->module_param.frame_timeout *
2938 1000 * msecs_to_jiffies(1));
2939 if (timeout < 0)
2940 return timeout;
2941 else if (timeout == 0 &&
2942 !(cam->state & DEV_DISCONNECTED)) {
2943 DBG(1, "Video frame timeout elapsed");
2944 return -EIO;
2945 }
2946 }
2947 if (cam->state & DEV_DISCONNECTED)
2948 return -ENODEV;
2949 if (cam->state & DEV_MISCONFIGURED)
2950 return -EIO;
2951 }
2952
2953 spin_lock_irqsave(&cam->queue_lock, lock_flags);
2954 f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame);
2955 list_del(cam->outqueue.next);
2956 spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
2957
2958 f->state = F_UNUSED;
2959
2960 b = f->buf;
2961 if (f->vma_use_count)
2962 b.flags |= V4L2_BUF_FLAG_MAPPED;
2963
2964 if (copy_to_user(arg, &b, sizeof(b)))
2965 return -EFAULT;
2966
2967 PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
2968
2969 return 0;
2970}
2971
2972
2973static int
2974sn9c102_vidioc_streamon(struct sn9c102_device *cam, void __user *arg)
2975{
2976 int type;
2977
2978 if (copy_from_user(&type, arg, sizeof(type)))
2979 return -EFAULT;
2980
2981 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
2982 return -EINVAL;
2983
2984 cam->stream = STREAM_ON;
2985
2986 DBG(3, "Stream on");
2987
2988 return 0;
2989}
2990
2991
2992static int
2993sn9c102_vidioc_streamoff(struct sn9c102_device *cam, void __user *arg)
2994{
2995 int type, err;
2996
2997 if (copy_from_user(&type, arg, sizeof(type)))
2998 return -EFAULT;
2999
3000 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
3001 return -EINVAL;
3002
3003 if (cam->stream == STREAM_ON) {
3004 err = sn9c102_stream_interrupt(cam);
3005 if (err)
3006 return err;
3007 }
3008
3009 sn9c102_empty_framequeues(cam);
3010
3011 DBG(3, "Stream off");
3012
3013 return 0;
3014}
3015
3016
3017static int
3018sn9c102_vidioc_g_parm(struct sn9c102_device *cam, void __user *arg)
3019{
3020 struct v4l2_streamparm sp;
3021
3022 if (copy_from_user(&sp, arg, sizeof(sp)))
3023 return -EFAULT;
3024
3025 if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
3026 return -EINVAL;
3027
3028 sp.parm.capture.extendedmode = 0;
3029 sp.parm.capture.readbuffers = cam->nreadbuffers;
3030
3031 if (copy_to_user(arg, &sp, sizeof(sp)))
3032 return -EFAULT;
3033
3034 return 0;
3035}
3036
3037
3038static int
3039sn9c102_vidioc_s_parm(struct sn9c102_device *cam, void __user *arg)
3040{
3041 struct v4l2_streamparm sp;
3042
3043 if (copy_from_user(&sp, arg, sizeof(sp)))
3044 return -EFAULT;
3045
3046 if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
3047 return -EINVAL;
3048
3049 sp.parm.capture.extendedmode = 0;
3050
3051 if (sp.parm.capture.readbuffers == 0)
3052 sp.parm.capture.readbuffers = cam->nreadbuffers;
3053
3054 if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
3055 sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
3056
3057 if (copy_to_user(arg, &sp, sizeof(sp)))
3058 return -EFAULT;
3059
3060 cam->nreadbuffers = sp.parm.capture.readbuffers;
3061
3062 return 0;
3063}
3064
3065
3066static int
3067sn9c102_vidioc_enumaudio(struct sn9c102_device *cam, void __user *arg)
3068{
3069 struct v4l2_audio audio;
3070
3071 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
3072 return -EINVAL;
3073
3074 if (copy_from_user(&audio, arg, sizeof(audio)))
3075 return -EFAULT;
3076
3077 if (audio.index != 0)
3078 return -EINVAL;
3079
3080 strcpy(audio.name, "Microphone");
3081 audio.capability = 0;
3082 audio.mode = 0;
3083
3084 if (copy_to_user(arg, &audio, sizeof(audio)))
3085 return -EFAULT;
3086
3087 return 0;
3088}
3089
3090
3091static int
3092sn9c102_vidioc_g_audio(struct sn9c102_device *cam, void __user *arg)
3093{
3094 struct v4l2_audio audio;
3095
3096 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
3097 return -EINVAL;
3098
3099 if (copy_from_user(&audio, arg, sizeof(audio)))
3100 return -EFAULT;
3101
3102 memset(&audio, 0, sizeof(audio));
3103 strcpy(audio.name, "Microphone");
3104
3105 if (copy_to_user(arg, &audio, sizeof(audio)))
3106 return -EFAULT;
3107
3108 return 0;
3109}
3110
3111
3112static int
3113sn9c102_vidioc_s_audio(struct sn9c102_device *cam, void __user *arg)
3114{
3115 struct v4l2_audio audio;
3116
3117 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
3118 return -EINVAL;
3119
3120 if (copy_from_user(&audio, arg, sizeof(audio)))
3121 return -EFAULT;
3122
3123 if (audio.index != 0)
3124 return -EINVAL;
3125
3126 return 0;
3127}
3128
3129
3130static long sn9c102_ioctl_v4l2(struct file *filp,
3131 unsigned int cmd, void __user *arg)
3132{
3133 struct sn9c102_device *cam = video_drvdata(filp);
3134
3135 switch (cmd) {
3136
3137 case VIDIOC_QUERYCAP:
3138 return sn9c102_vidioc_querycap(cam, arg);
3139
3140 case VIDIOC_ENUMINPUT:
3141 return sn9c102_vidioc_enuminput(cam, arg);
3142
3143 case VIDIOC_G_INPUT:
3144 return sn9c102_vidioc_g_input(cam, arg);
3145
3146 case VIDIOC_S_INPUT:
3147 return sn9c102_vidioc_s_input(cam, arg);
3148
3149 case VIDIOC_QUERYCTRL:
3150 return sn9c102_vidioc_query_ctrl(cam, arg);
3151
3152 case VIDIOC_G_CTRL:
3153 return sn9c102_vidioc_g_ctrl(cam, arg);
3154
3155 case VIDIOC_S_CTRL:
3156 return sn9c102_vidioc_s_ctrl(cam, arg);
3157
3158 case VIDIOC_CROPCAP:
3159 return sn9c102_vidioc_cropcap(cam, arg);
3160
3161 case VIDIOC_G_CROP:
3162 return sn9c102_vidioc_g_crop(cam, arg);
3163
3164 case VIDIOC_S_CROP:
3165 return sn9c102_vidioc_s_crop(cam, arg);
3166
3167 case VIDIOC_ENUM_FRAMESIZES:
3168 return sn9c102_vidioc_enum_framesizes(cam, arg);
3169
3170 case VIDIOC_ENUM_FMT:
3171 return sn9c102_vidioc_enum_fmt(cam, arg);
3172
3173 case VIDIOC_G_FMT:
3174 return sn9c102_vidioc_g_fmt(cam, arg);
3175
3176 case VIDIOC_TRY_FMT:
3177 case VIDIOC_S_FMT:
3178 return sn9c102_vidioc_try_s_fmt(cam, cmd, arg);
3179
3180 case VIDIOC_G_JPEGCOMP:
3181 return sn9c102_vidioc_g_jpegcomp(cam, arg);
3182
3183 case VIDIOC_S_JPEGCOMP:
3184 return sn9c102_vidioc_s_jpegcomp(cam, arg);
3185
3186 case VIDIOC_REQBUFS:
3187 return sn9c102_vidioc_reqbufs(cam, arg);
3188
3189 case VIDIOC_QUERYBUF:
3190 return sn9c102_vidioc_querybuf(cam, arg);
3191
3192 case VIDIOC_QBUF:
3193 return sn9c102_vidioc_qbuf(cam, arg);
3194
3195 case VIDIOC_DQBUF:
3196 return sn9c102_vidioc_dqbuf(cam, filp, arg);
3197
3198 case VIDIOC_STREAMON:
3199 return sn9c102_vidioc_streamon(cam, arg);
3200
3201 case VIDIOC_STREAMOFF:
3202 return sn9c102_vidioc_streamoff(cam, arg);
3203
3204 case VIDIOC_G_PARM:
3205 return sn9c102_vidioc_g_parm(cam, arg);
3206
3207 case VIDIOC_S_PARM:
3208 return sn9c102_vidioc_s_parm(cam, arg);
3209
3210 case VIDIOC_ENUMAUDIO:
3211 return sn9c102_vidioc_enumaudio(cam, arg);
3212
3213 case VIDIOC_G_AUDIO:
3214 return sn9c102_vidioc_g_audio(cam, arg);
3215
3216 case VIDIOC_S_AUDIO:
3217 return sn9c102_vidioc_s_audio(cam, arg);
3218
3219 default:
3220 return -ENOTTY;
3221
3222 }
3223}
3224
3225
3226static long sn9c102_ioctl(struct file *filp,
3227 unsigned int cmd, unsigned long arg)
3228{
3229 struct sn9c102_device *cam = video_drvdata(filp);
3230 int err = 0;
3231
3232 if (mutex_lock_interruptible(&cam->fileop_mutex))
3233 return -ERESTARTSYS;
3234
3235 if (cam->state & DEV_DISCONNECTED) {
3236 DBG(1, "Device not present");
3237 mutex_unlock(&cam->fileop_mutex);
3238 return -ENODEV;
3239 }
3240
3241 if (cam->state & DEV_MISCONFIGURED) {
3242 DBG(1, "The camera is misconfigured. Close and open it "
3243 "again.");
3244 mutex_unlock(&cam->fileop_mutex);
3245 return -EIO;
3246 }
3247
3248 V4LDBG(3, "sn9c102", cmd);
3249
3250 err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg);
3251
3252 mutex_unlock(&cam->fileop_mutex);
3253
3254 return err;
3255}
3256
3257/*****************************************************************************/
3258
3259static const struct v4l2_file_operations sn9c102_fops = {
3260 .owner = THIS_MODULE,
3261 .open = sn9c102_open,
3262 .release = sn9c102_release,
3263 .unlocked_ioctl = sn9c102_ioctl,
3264 .read = sn9c102_read,
3265 .poll = sn9c102_poll,
3266 .mmap = sn9c102_mmap,
3267};
3268
3269/*****************************************************************************/
3270
3271/* It exists a single interface only. We do not need to validate anything. */
3272static int
3273sn9c102_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
3274{
3275 struct usb_device *udev = interface_to_usbdev(intf);
3276 struct sn9c102_device *cam;
3277 static unsigned int dev_nr;
3278 unsigned int i;
3279 int err = 0, r;
3280
3281 cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL);
3282 if (!cam)
3283 return -ENOMEM;
3284
3285 cam->usbdev = udev;
3286
3287 /* register v4l2_device early so it can be used for printks */
3288 if (v4l2_device_register(&intf->dev, &cam->v4l2_dev)) {
3289 dev_err(&intf->dev, "v4l2_device_register failed\n");
3290 err = -ENOMEM;
3291 goto fail;
3292 }
3293
3294 cam->control_buffer = kzalloc(8, GFP_KERNEL);
3295 if (!cam->control_buffer) {
3296 DBG(1, "kzalloc() failed");
3297 err = -ENOMEM;
3298 goto fail;
3299 }
3300
3301 cam->v4ldev = video_device_alloc();
3302 if (!cam->v4ldev) {
3303 DBG(1, "video_device_alloc() failed");
3304 err = -ENOMEM;
3305 goto fail;
3306 }
3307
3308 r = sn9c102_read_reg(cam, 0x00);
3309 if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
3310 DBG(1, "Sorry, this is not a SN9C1xx-based camera "
3311 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3312 err = -ENODEV;
3313 goto fail;
3314 }
3315
3316 cam->bridge = id->driver_info;
3317 switch (cam->bridge) {
3318 case BRIDGE_SN9C101:
3319 case BRIDGE_SN9C102:
3320 DBG(2, "SN9C10[12] PC Camera Controller detected "
3321 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3322 break;
3323 case BRIDGE_SN9C103:
3324 DBG(2, "SN9C103 PC Camera Controller detected "
3325 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3326 break;
3327 case BRIDGE_SN9C105:
3328 DBG(2, "SN9C105 PC Camera Controller detected "
3329 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3330 break;
3331 case BRIDGE_SN9C120:
3332 DBG(2, "SN9C120 PC Camera Controller detected "
3333 "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
3334 break;
3335 }
3336
3337 for (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) {
3338 err = sn9c102_sensor_table[i](cam);
3339 if (!err)
3340 break;
3341 }
3342
3343 if (!err) {
3344 DBG(2, "%s image sensor detected", cam->sensor.name);
3345 DBG(3, "Support for %s maintained by %s",
3346 cam->sensor.name, cam->sensor.maintainer);
3347 } else {
3348 DBG(1, "No supported image sensor detected for this bridge");
3349 err = -ENODEV;
3350 goto fail;
3351 }
3352
3353 if (!(cam->bridge & cam->sensor.supported_bridge)) {
3354 DBG(1, "Bridge not supported");
3355 err = -ENODEV;
3356 goto fail;
3357 }
3358
3359 if (sn9c102_init(cam)) {
3360 DBG(1, "Initialization failed. I will retry on open().");
3361 cam->state |= DEV_MISCONFIGURED;
3362 }
3363
3364 strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
3365 cam->v4ldev->fops = &sn9c102_fops;
3366 cam->v4ldev->release = video_device_release;
3367 cam->v4ldev->v4l2_dev = &cam->v4l2_dev;
3368
3369 init_completion(&cam->probe);
3370
3371 err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
3372 video_nr[dev_nr]);
3373 if (err) {
3374 DBG(1, "V4L2 device registration failed");
3375 if (err == -ENFILE && video_nr[dev_nr] == -1)
3376 DBG(1, "Free /dev/videoX node not found");
3377 video_nr[dev_nr] = -1;
3378 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
3379 complete_all(&cam->probe);
3380 goto fail;
3381 }
3382
3383 DBG(2, "V4L2 device registered as %s",
3384 video_device_node_name(cam->v4ldev));
3385
3386 video_set_drvdata(cam->v4ldev, cam);
3387 cam->module_param.force_munmap = force_munmap[dev_nr];
3388 cam->module_param.frame_timeout = frame_timeout[dev_nr];
3389
3390 dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
3391
3392#ifdef CONFIG_VIDEO_ADV_DEBUG
3393 err = sn9c102_create_sysfs(cam);
3394 if (!err)
3395 DBG(2, "Optional device control through 'sysfs' "
3396 "interface ready");
3397 else
3398 DBG(2, "Failed to create optional 'sysfs' interface for "
3399 "device controlling. Error #%d", err);
3400#else
3401 DBG(2, "Optional device control through 'sysfs' interface disabled");
3402 DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
3403 "configuration option to enable it.");
3404#endif
3405
3406 usb_set_intfdata(intf, cam);
3407 kref_init(&cam->kref);
3408 usb_get_dev(cam->usbdev);
3409
3410 complete_all(&cam->probe);
3411
3412 return 0;
3413
3414fail:
3415 if (cam) {
3416 kfree(cam->control_buffer);
3417 if (cam->v4ldev)
3418 video_device_release(cam->v4ldev);
3419 v4l2_device_unregister(&cam->v4l2_dev);
3420 kfree(cam);
3421 }
3422 return err;
3423}
3424
3425
3426static void sn9c102_usb_disconnect(struct usb_interface *intf)
3427{
3428 struct sn9c102_device *cam;
3429
3430 down_write(&sn9c102_dev_lock);
3431
3432 cam = usb_get_intfdata(intf);
3433
3434 DBG(2, "Disconnecting %s...", cam->v4ldev->name);
3435
3436 if (cam->users) {
3437 DBG(2, "Device %s is open! Deregistration and memory "
3438 "deallocation are deferred.",
3439 video_device_node_name(cam->v4ldev));
3440 cam->state |= DEV_MISCONFIGURED;
3441 sn9c102_stop_transfer(cam);
3442 cam->state |= DEV_DISCONNECTED;
3443 wake_up_interruptible(&cam->wait_frame);
3444 wake_up(&cam->wait_stream);
3445 } else
3446 cam->state |= DEV_DISCONNECTED;
3447
3448 wake_up_interruptible_all(&cam->wait_open);
3449
3450 v4l2_device_disconnect(&cam->v4l2_dev);
3451
3452 kref_put(&cam->kref, sn9c102_release_resources);
3453
3454 up_write(&sn9c102_dev_lock);
3455}
3456
3457
3458static struct usb_driver sn9c102_usb_driver = {
3459 .name = "sn9c102",
3460 .id_table = sn9c102_id_table,
3461 .probe = sn9c102_usb_probe,
3462 .disconnect = sn9c102_usb_disconnect,
3463};
3464
3465module_usb_driver(sn9c102_usb_driver);
diff --git a/drivers/staging/media/sn9c102/sn9c102_devtable.h b/drivers/staging/media/sn9c102/sn9c102_devtable.h
deleted file mode 100644
index b187a8a304eb..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_devtable.h
+++ /dev/null
@@ -1,145 +0,0 @@
1/***************************************************************************
2 * Table of device identifiers of the SN9C1xx PC Camera Controllers *
3 * *
4 * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 ***************************************************************************/
20
21#ifndef _SN9C102_DEVTABLE_H_
22#define _SN9C102_DEVTABLE_H_
23
24#include <linux/usb.h>
25
26struct sn9c102_device;
27
28/*
29 Each SN9C1xx camera has proper PID/VID identifiers.
30 SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to
31 handle the video class interface.
32*/
33#define SN9C102_USB_DEVICE(vend, prod, bridge) \
34 .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
35 USB_DEVICE_ID_MATCH_INT_CLASS, \
36 .idVendor = (vend), \
37 .idProduct = (prod), \
38 .bInterfaceClass = 0xff, \
39 .driver_info = (bridge)
40
41static const struct usb_device_id sn9c102_id_table[] = {
42 /* SN9C101 and SN9C102 */
43#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
44 { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
45 { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
46 { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
47 { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
48 { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
49/* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */
50 { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
51 { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
52 { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
53 { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
54 { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
55 { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
56#endif
57 { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, /* not in sonixb */
58#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
59 { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
60/* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
61 { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
62#endif
63 { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* not in sonixb */
64 /* SN9C103 */
65/* { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, non existent ? */
66 { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, /* not in sonixb */
67#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
68/* { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */
69/* { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, non existent ? */
70/* { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, non existent ? */
71/* { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, non existent ? */
72 { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
73/* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */
74 { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
75/* { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, non existent ? */
76/* { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, non existent ? */
77/* { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, non existent ? */
78/* { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */
79/* { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */
80/* { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5110, non existent */
81/* { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, non existent ? */
82/* { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, non existent ? */
83 { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
84 { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
85/* { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, non existent ? */
86/* { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, non existent ? */
87/* { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, non existent ? */
88/* { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, non existent ? */
89/* { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, non existent ? */
90/* { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, non existent ? */
91/* { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, non existent ? */
92#endif
93 /* SN9C105 */
94#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE
95 { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
96 { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
97 { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
98 { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
99 { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
100/* { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, PO1030 */
101/* { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, OM6801 */
102/* { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, HV7131GP */
103/* { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, non existent ? */
104/* { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, MO4000 */
105/* { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, ICM105C */
106/* { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, OV7648 */
107 { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
108 { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
109 { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
110 /* SN9C120 */
111 { SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), },
112/* { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, po2030 */
113/* { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, om6801 */
114/* { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, S5K53BEB */
115 { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
116/* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */
117 { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
118 { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
119 { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
120 { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
121#endif
122 { }
123};
124
125/*
126 Probing functions: on success, you must attach the sensor to the camera
127 by calling sn9c102_attach_sensor().
128 To enable the I2C communication, you might need to perform a really basic
129 initialization of the SN9C1XX chip.
130 Functions must return 0 on success, the appropriate error otherwise.
131*/
132extern int sn9c102_probe_hv7131d(struct sn9c102_device *cam);
133extern int sn9c102_probe_hv7131r(struct sn9c102_device *cam);
134extern int sn9c102_probe_mi0343(struct sn9c102_device *cam);
135extern int sn9c102_probe_mi0360(struct sn9c102_device *cam);
136extern int sn9c102_probe_mt9v111(struct sn9c102_device *cam);
137extern int sn9c102_probe_ov7630(struct sn9c102_device *cam);
138extern int sn9c102_probe_ov7660(struct sn9c102_device *cam);
139extern int sn9c102_probe_pas106b(struct sn9c102_device *cam);
140extern int sn9c102_probe_pas202bcb(struct sn9c102_device *cam);
141extern int sn9c102_probe_tas5110c1b(struct sn9c102_device *cam);
142extern int sn9c102_probe_tas5110d(struct sn9c102_device *cam);
143extern int sn9c102_probe_tas5130d1b(struct sn9c102_device *cam);
144
145#endif /* _SN9C102_DEVTABLE_H_ */
diff --git a/drivers/staging/media/sn9c102/sn9c102_hv7131d.c b/drivers/staging/media/sn9c102/sn9c102_hv7131d.c
deleted file mode 100644
index f1d94f0190c6..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_hv7131d.c
+++ /dev/null
@@ -1,269 +0,0 @@
1/***************************************************************************
2 * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004-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#include "sn9c102_devtable.h"
24
25
26static int hv7131d_init(struct sn9c102_device *cam)
27{
28 int err;
29
30 err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
31 {0x00, 0x14}, {0x60, 0x17},
32 {0x0e, 0x18}, {0xf2, 0x19});
33
34 err += sn9c102_i2c_write(cam, 0x01, 0x04);
35 err += sn9c102_i2c_write(cam, 0x02, 0x00);
36 err += sn9c102_i2c_write(cam, 0x28, 0x00);
37
38 return err;
39}
40
41
42static int hv7131d_get_ctrl(struct sn9c102_device *cam,
43 struct v4l2_control *ctrl)
44{
45 switch (ctrl->id) {
46 case V4L2_CID_EXPOSURE:
47 {
48 int r1 = sn9c102_i2c_read(cam, 0x26),
49 r2 = sn9c102_i2c_read(cam, 0x27);
50 if (r1 < 0 || r2 < 0)
51 return -EIO;
52 ctrl->value = (r1 << 8) | (r2 & 0xff);
53 }
54 return 0;
55 case V4L2_CID_RED_BALANCE:
56 ctrl->value = sn9c102_i2c_read(cam, 0x31);
57 if (ctrl->value < 0)
58 return -EIO;
59 ctrl->value = 0x3f - (ctrl->value & 0x3f);
60 return 0;
61 case V4L2_CID_BLUE_BALANCE:
62 ctrl->value = sn9c102_i2c_read(cam, 0x33);
63 if (ctrl->value < 0)
64 return -EIO;
65 ctrl->value = 0x3f - (ctrl->value & 0x3f);
66 return 0;
67 case SN9C102_V4L2_CID_GREEN_BALANCE:
68 ctrl->value = sn9c102_i2c_read(cam, 0x32);
69 if (ctrl->value < 0)
70 return -EIO;
71 ctrl->value = 0x3f - (ctrl->value & 0x3f);
72 return 0;
73 case SN9C102_V4L2_CID_RESET_LEVEL:
74 ctrl->value = sn9c102_i2c_read(cam, 0x30);
75 if (ctrl->value < 0)
76 return -EIO;
77 ctrl->value &= 0x3f;
78 return 0;
79 case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
80 ctrl->value = sn9c102_i2c_read(cam, 0x34);
81 if (ctrl->value < 0)
82 return -EIO;
83 ctrl->value &= 0x07;
84 return 0;
85 default:
86 return -EINVAL;
87 }
88}
89
90
91static int hv7131d_set_ctrl(struct sn9c102_device *cam,
92 const struct v4l2_control *ctrl)
93{
94 int err = 0;
95
96 switch (ctrl->id) {
97 case V4L2_CID_EXPOSURE:
98 err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8);
99 err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff);
100 break;
101 case V4L2_CID_RED_BALANCE:
102 err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value);
103 break;
104 case V4L2_CID_BLUE_BALANCE:
105 err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value);
106 break;
107 case SN9C102_V4L2_CID_GREEN_BALANCE:
108 err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value);
109 break;
110 case SN9C102_V4L2_CID_RESET_LEVEL:
111 err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
112 break;
113 case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
114 err += sn9c102_i2c_write(cam, 0x34, ctrl->value);
115 break;
116 default:
117 return -EINVAL;
118 }
119
120 return err ? -EIO : 0;
121}
122
123
124static int hv7131d_set_crop(struct sn9c102_device *cam,
125 const struct v4l2_rect *rect)
126{
127 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
128 int err = 0;
129 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
130 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
131
132 err += sn9c102_write_reg(cam, h_start, 0x12);
133 err += sn9c102_write_reg(cam, v_start, 0x13);
134
135 return err;
136}
137
138
139static int hv7131d_set_pix_format(struct sn9c102_device *cam,
140 const struct v4l2_pix_format *pix)
141{
142 int err = 0;
143
144 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
145 err += sn9c102_write_reg(cam, 0x42, 0x19);
146 else
147 err += sn9c102_write_reg(cam, 0xf2, 0x19);
148
149 return err;
150}
151
152
153static const struct sn9c102_sensor hv7131d = {
154 .name = "HV7131D",
155 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
156 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
157 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
158 .frequency = SN9C102_I2C_100KHZ,
159 .interface = SN9C102_I2C_2WIRES,
160 .i2c_slave_id = 0x11,
161 .init = &hv7131d_init,
162 .qctrl = {
163 {
164 .id = V4L2_CID_EXPOSURE,
165 .type = V4L2_CTRL_TYPE_INTEGER,
166 .name = "exposure",
167 .minimum = 0x0250,
168 .maximum = 0xffff,
169 .step = 0x0001,
170 .default_value = 0x0250,
171 .flags = 0,
172 },
173 {
174 .id = V4L2_CID_RED_BALANCE,
175 .type = V4L2_CTRL_TYPE_INTEGER,
176 .name = "red balance",
177 .minimum = 0x00,
178 .maximum = 0x3f,
179 .step = 0x01,
180 .default_value = 0x00,
181 .flags = 0,
182 },
183 {
184 .id = V4L2_CID_BLUE_BALANCE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "blue balance",
187 .minimum = 0x00,
188 .maximum = 0x3f,
189 .step = 0x01,
190 .default_value = 0x20,
191 .flags = 0,
192 },
193 {
194 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
195 .type = V4L2_CTRL_TYPE_INTEGER,
196 .name = "green balance",
197 .minimum = 0x00,
198 .maximum = 0x3f,
199 .step = 0x01,
200 .default_value = 0x1e,
201 .flags = 0,
202 },
203 {
204 .id = SN9C102_V4L2_CID_RESET_LEVEL,
205 .type = V4L2_CTRL_TYPE_INTEGER,
206 .name = "reset level",
207 .minimum = 0x19,
208 .maximum = 0x3f,
209 .step = 0x01,
210 .default_value = 0x30,
211 .flags = 0,
212 },
213 {
214 .id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE,
215 .type = V4L2_CTRL_TYPE_INTEGER,
216 .name = "pixel bias voltage",
217 .minimum = 0x00,
218 .maximum = 0x07,
219 .step = 0x01,
220 .default_value = 0x02,
221 .flags = 0,
222 },
223 },
224 .get_ctrl = &hv7131d_get_ctrl,
225 .set_ctrl = &hv7131d_set_ctrl,
226 .cropcap = {
227 .bounds = {
228 .left = 0,
229 .top = 0,
230 .width = 640,
231 .height = 480,
232 },
233 .defrect = {
234 .left = 0,
235 .top = 0,
236 .width = 640,
237 .height = 480,
238 },
239 },
240 .set_crop = &hv7131d_set_crop,
241 .pix_format = {
242 .width = 640,
243 .height = 480,
244 .pixelformat = V4L2_PIX_FMT_SBGGR8,
245 .priv = 8,
246 },
247 .set_pix_format = &hv7131d_set_pix_format
248};
249
250
251int sn9c102_probe_hv7131d(struct sn9c102_device *cam)
252{
253 int r0 = 0, r1 = 0, err;
254
255 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
256 {0x28, 0x17});
257
258 r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
259 r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
260 if (err || r0 < 0 || r1 < 0)
261 return -EIO;
262
263 if ((r0 != 0x00 && r0 != 0x01) || r1 != 0x04)
264 return -ENODEV;
265
266 sn9c102_attach_sensor(cam, &hv7131d);
267
268 return 0;
269}
diff --git a/drivers/staging/media/sn9c102/sn9c102_hv7131r.c b/drivers/staging/media/sn9c102/sn9c102_hv7131r.c
deleted file mode 100644
index 51b24e000e88..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_hv7131r.c
+++ /dev/null
@@ -1,369 +0,0 @@
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#include "sn9c102_devtable.h"
24
25
26static int hv7131r_init(struct sn9c102_device *cam)
27{
28 int err = 0;
29
30 switch (sn9c102_get_bridge(cam)) {
31 case BRIDGE_SN9C103:
32 err = sn9c102_write_const_regs(cam, {0x00, 0x03}, {0x1a, 0x04},
33 {0x20, 0x05}, {0x20, 0x06},
34 {0x03, 0x10}, {0x00, 0x14},
35 {0x60, 0x17}, {0x0a, 0x18},
36 {0xf0, 0x19}, {0x1d, 0x1a},
37 {0x10, 0x1b}, {0x02, 0x1c},
38 {0x03, 0x1d}, {0x0f, 0x1e},
39 {0x0c, 0x1f}, {0x00, 0x20},
40 {0x10, 0x21}, {0x20, 0x22},
41 {0x30, 0x23}, {0x40, 0x24},
42 {0x50, 0x25}, {0x60, 0x26},
43 {0x70, 0x27}, {0x80, 0x28},
44 {0x90, 0x29}, {0xa0, 0x2a},
45 {0xb0, 0x2b}, {0xc0, 0x2c},
46 {0xd0, 0x2d}, {0xe0, 0x2e},
47 {0xf0, 0x2f}, {0xff, 0x30});
48 break;
49 case BRIDGE_SN9C105:
50 case BRIDGE_SN9C120:
51 err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
52 {0x00, 0x03}, {0x1a, 0x04},
53 {0x44, 0x05}, {0x3e, 0x06},
54 {0x1a, 0x07}, {0x03, 0x10},
55 {0x08, 0x14}, {0xa3, 0x17},
56 {0x4b, 0x18}, {0x00, 0x19},
57 {0x1d, 0x1a}, {0x10, 0x1b},
58 {0x02, 0x1c}, {0x03, 0x1d},
59 {0x0f, 0x1e}, {0x0c, 0x1f},
60 {0x00, 0x20}, {0x29, 0x21},
61 {0x40, 0x22}, {0x54, 0x23},
62 {0x66, 0x24}, {0x76, 0x25},
63 {0x85, 0x26}, {0x94, 0x27},
64 {0xa1, 0x28}, {0xae, 0x29},
65 {0xbb, 0x2a}, {0xc7, 0x2b},
66 {0xd3, 0x2c}, {0xde, 0x2d},
67 {0xea, 0x2e}, {0xf4, 0x2f},
68 {0xff, 0x30}, {0x00, 0x3F},
69 {0xC7, 0x40}, {0x01, 0x41},
70 {0x44, 0x42}, {0x00, 0x43},
71 {0x44, 0x44}, {0x00, 0x45},
72 {0x44, 0x46}, {0x00, 0x47},
73 {0xC7, 0x48}, {0x01, 0x49},
74 {0xC7, 0x4A}, {0x01, 0x4B},
75 {0xC7, 0x4C}, {0x01, 0x4D},
76 {0x44, 0x4E}, {0x00, 0x4F},
77 {0x44, 0x50}, {0x00, 0x51},
78 {0x44, 0x52}, {0x00, 0x53},
79 {0xC7, 0x54}, {0x01, 0x55},
80 {0xC7, 0x56}, {0x01, 0x57},
81 {0xC7, 0x58}, {0x01, 0x59},
82 {0x44, 0x5A}, {0x00, 0x5B},
83 {0x44, 0x5C}, {0x00, 0x5D},
84 {0x44, 0x5E}, {0x00, 0x5F},
85 {0xC7, 0x60}, {0x01, 0x61},
86 {0xC7, 0x62}, {0x01, 0x63},
87 {0xC7, 0x64}, {0x01, 0x65},
88 {0x44, 0x66}, {0x00, 0x67},
89 {0x44, 0x68}, {0x00, 0x69},
90 {0x44, 0x6A}, {0x00, 0x6B},
91 {0xC7, 0x6C}, {0x01, 0x6D},
92 {0xC7, 0x6E}, {0x01, 0x6F},
93 {0xC7, 0x70}, {0x01, 0x71},
94 {0x44, 0x72}, {0x00, 0x73},
95 {0x44, 0x74}, {0x00, 0x75},
96 {0x44, 0x76}, {0x00, 0x77},
97 {0xC7, 0x78}, {0x01, 0x79},
98 {0xC7, 0x7A}, {0x01, 0x7B},
99 {0xC7, 0x7C}, {0x01, 0x7D},
100 {0x44, 0x7E}, {0x00, 0x7F},
101 {0x14, 0x84}, {0x00, 0x85},
102 {0x27, 0x86}, {0x00, 0x87},
103 {0x07, 0x88}, {0x00, 0x89},
104 {0xEC, 0x8A}, {0x0f, 0x8B},
105 {0xD8, 0x8C}, {0x0f, 0x8D},
106 {0x3D, 0x8E}, {0x00, 0x8F},
107 {0x3D, 0x90}, {0x00, 0x91},
108 {0xCD, 0x92}, {0x0f, 0x93},
109 {0xf7, 0x94}, {0x0f, 0x95},
110 {0x0C, 0x96}, {0x00, 0x97},
111 {0x00, 0x98}, {0x66, 0x99},
112 {0x05, 0x9A}, {0x00, 0x9B},
113 {0x04, 0x9C}, {0x00, 0x9D},
114 {0x08, 0x9E}, {0x00, 0x9F},
115 {0x2D, 0xC0}, {0x2D, 0xC1},
116 {0x3A, 0xC2}, {0x05, 0xC3},
117 {0x04, 0xC4}, {0x3F, 0xC5},
118 {0x00, 0xC6}, {0x00, 0xC7},
119 {0x50, 0xC8}, {0x3C, 0xC9},
120 {0x28, 0xCA}, {0xD8, 0xCB},
121 {0x14, 0xCC}, {0xEC, 0xCD},
122 {0x32, 0xCE}, {0xDD, 0xCF},
123 {0x32, 0xD0}, {0xDD, 0xD1},
124 {0x6A, 0xD2}, {0x50, 0xD3},
125 {0x00, 0xD4}, {0x00, 0xD5},
126 {0x00, 0xD6});
127 break;
128 default:
129 break;
130 }
131
132 err += sn9c102_i2c_write(cam, 0x20, 0x00);
133 err += sn9c102_i2c_write(cam, 0x21, 0xd6);
134 err += sn9c102_i2c_write(cam, 0x25, 0x06);
135
136 return err;
137}
138
139
140static int hv7131r_get_ctrl(struct sn9c102_device *cam,
141 struct v4l2_control *ctrl)
142{
143 switch (ctrl->id) {
144 case V4L2_CID_GAIN:
145 ctrl->value = sn9c102_i2c_read(cam, 0x30);
146 if (ctrl->value < 0)
147 return -EIO;
148 return 0;
149 case V4L2_CID_RED_BALANCE:
150 ctrl->value = sn9c102_i2c_read(cam, 0x31);
151 if (ctrl->value < 0)
152 return -EIO;
153 ctrl->value = ctrl->value & 0x3f;
154 return 0;
155 case V4L2_CID_BLUE_BALANCE:
156 ctrl->value = sn9c102_i2c_read(cam, 0x33);
157 if (ctrl->value < 0)
158 return -EIO;
159 ctrl->value = ctrl->value & 0x3f;
160 return 0;
161 case SN9C102_V4L2_CID_GREEN_BALANCE:
162 ctrl->value = sn9c102_i2c_read(cam, 0x32);
163 if (ctrl->value < 0)
164 return -EIO;
165 ctrl->value = ctrl->value & 0x3f;
166 return 0;
167 case V4L2_CID_BLACK_LEVEL:
168 ctrl->value = sn9c102_i2c_read(cam, 0x01);
169 if (ctrl->value < 0)
170 return -EIO;
171 ctrl->value = (ctrl->value & 0x08) ? 1 : 0;
172 return 0;
173 default:
174 return -EINVAL;
175 }
176}
177
178
179static int hv7131r_set_ctrl(struct sn9c102_device *cam,
180 const struct v4l2_control *ctrl)
181{
182 int err = 0;
183
184 switch (ctrl->id) {
185 case V4L2_CID_GAIN:
186 err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
187 break;
188 case V4L2_CID_RED_BALANCE:
189 err += sn9c102_i2c_write(cam, 0x31, ctrl->value);
190 break;
191 case V4L2_CID_BLUE_BALANCE:
192 err += sn9c102_i2c_write(cam, 0x33, ctrl->value);
193 break;
194 case SN9C102_V4L2_CID_GREEN_BALANCE:
195 err += sn9c102_i2c_write(cam, 0x32, ctrl->value);
196 break;
197 case V4L2_CID_BLACK_LEVEL:
198 {
199 int r = sn9c102_i2c_read(cam, 0x01);
200
201 if (r < 0)
202 return -EIO;
203 err += sn9c102_i2c_write(cam, 0x01,
204 (ctrl->value<<3) | (r&0xf7));
205 }
206 break;
207 default:
208 return -EINVAL;
209 }
210
211 return err ? -EIO : 0;
212}
213
214
215static int hv7131r_set_crop(struct sn9c102_device *cam,
216 const struct v4l2_rect *rect)
217{
218 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
219 int err = 0;
220 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
221 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
222
223 err += sn9c102_write_reg(cam, h_start, 0x12);
224 err += sn9c102_write_reg(cam, v_start, 0x13);
225
226 return err;
227}
228
229
230static int hv7131r_set_pix_format(struct sn9c102_device *cam,
231 const struct v4l2_pix_format *pix)
232{
233 int err = 0;
234
235 switch (sn9c102_get_bridge(cam)) {
236 case BRIDGE_SN9C103:
237 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
238 err += sn9c102_write_reg(cam, 0xa0, 0x19);
239 err += sn9c102_i2c_write(cam, 0x01, 0x04);
240 } else {
241 err += sn9c102_write_reg(cam, 0x30, 0x19);
242 err += sn9c102_i2c_write(cam, 0x01, 0x04);
243 }
244 break;
245 case BRIDGE_SN9C105:
246 case BRIDGE_SN9C120:
247 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
248 err += sn9c102_write_reg(cam, 0xa5, 0x17);
249 err += sn9c102_i2c_write(cam, 0x01, 0x24);
250 } else {
251 err += sn9c102_write_reg(cam, 0xa3, 0x17);
252 err += sn9c102_i2c_write(cam, 0x01, 0x04);
253 }
254 break;
255 default:
256 break;
257 }
258
259 return err;
260}
261
262
263static const struct sn9c102_sensor hv7131r = {
264 .name = "HV7131R",
265 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
266 .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
267 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
268 .frequency = SN9C102_I2C_100KHZ,
269 .interface = SN9C102_I2C_2WIRES,
270 .i2c_slave_id = 0x11,
271 .init = &hv7131r_init,
272 .qctrl = {
273 {
274 .id = V4L2_CID_GAIN,
275 .type = V4L2_CTRL_TYPE_INTEGER,
276 .name = "global gain",
277 .minimum = 0x00,
278 .maximum = 0xff,
279 .step = 0x01,
280 .default_value = 0x40,
281 .flags = 0,
282 },
283 {
284 .id = V4L2_CID_RED_BALANCE,
285 .type = V4L2_CTRL_TYPE_INTEGER,
286 .name = "red balance",
287 .minimum = 0x00,
288 .maximum = 0x3f,
289 .step = 0x01,
290 .default_value = 0x08,
291 .flags = 0,
292 },
293 {
294 .id = V4L2_CID_BLUE_BALANCE,
295 .type = V4L2_CTRL_TYPE_INTEGER,
296 .name = "blue balance",
297 .minimum = 0x00,
298 .maximum = 0x3f,
299 .step = 0x01,
300 .default_value = 0x1a,
301 .flags = 0,
302 },
303 {
304 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
305 .type = V4L2_CTRL_TYPE_INTEGER,
306 .name = "green balance",
307 .minimum = 0x00,
308 .maximum = 0x3f,
309 .step = 0x01,
310 .default_value = 0x2f,
311 .flags = 0,
312 },
313 {
314 .id = V4L2_CID_BLACK_LEVEL,
315 .type = V4L2_CTRL_TYPE_BOOLEAN,
316 .name = "auto black level compensation",
317 .minimum = 0x00,
318 .maximum = 0x01,
319 .step = 0x01,
320 .default_value = 0x00,
321 .flags = 0,
322 },
323 },
324 .get_ctrl = &hv7131r_get_ctrl,
325 .set_ctrl = &hv7131r_set_ctrl,
326 .cropcap = {
327 .bounds = {
328 .left = 0,
329 .top = 0,
330 .width = 640,
331 .height = 480,
332 },
333 .defrect = {
334 .left = 0,
335 .top = 0,
336 .width = 640,
337 .height = 480,
338 },
339 },
340 .set_crop = &hv7131r_set_crop,
341 .pix_format = {
342 .width = 640,
343 .height = 480,
344 .pixelformat = V4L2_PIX_FMT_SBGGR8,
345 .priv = 8,
346 },
347 .set_pix_format = &hv7131r_set_pix_format
348};
349
350
351int sn9c102_probe_hv7131r(struct sn9c102_device *cam)
352{
353 int devid, err;
354
355 err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x02},
356 {0x34, 0x01}, {0x20, 0x17},
357 {0x34, 0x01}, {0x46, 0x01});
358
359 devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
360 if (err || devid < 0)
361 return -EIO;
362
363 if (devid != 0x02)
364 return -ENODEV;
365
366 sn9c102_attach_sensor(cam, &hv7131r);
367
368 return 0;
369}
diff --git a/drivers/staging/media/sn9c102/sn9c102_mi0343.c b/drivers/staging/media/sn9c102/sn9c102_mi0343.c
deleted file mode 100644
index b20fdb6541d3..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_mi0343.c
+++ /dev/null
@@ -1,352 +0,0 @@
1/***************************************************************************
2 * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004-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#include "sn9c102_devtable.h"
24
25
26static int mi0343_init(struct sn9c102_device *cam)
27{
28 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
29 int err = 0;
30
31 err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
32 {0x0a, 0x14}, {0x40, 0x01},
33 {0x20, 0x17}, {0x07, 0x18},
34 {0xa0, 0x19});
35
36 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
37 0x00, 0x01, 0, 0);
38 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
39 0x00, 0x00, 0, 0);
40 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
41 0x01, 0xe1, 0, 0);
42 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
43 0x02, 0x81, 0, 0);
44 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
45 0x00, 0x17, 0, 0);
46 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
47 0x00, 0x11, 0, 0);
48 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
49 0x04, 0x9a, 0, 0);
50
51 return err;
52}
53
54
55static int mi0343_get_ctrl(struct sn9c102_device *cam,
56 struct v4l2_control *ctrl)
57{
58 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
59 u8 data[2];
60
61 switch (ctrl->id) {
62 case V4L2_CID_EXPOSURE:
63 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
64 data) < 0)
65 return -EIO;
66 ctrl->value = data[0];
67 return 0;
68 case V4L2_CID_GAIN:
69 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
70 data) < 0)
71 return -EIO;
72 break;
73 case V4L2_CID_HFLIP:
74 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
75 data) < 0)
76 return -EIO;
77 ctrl->value = data[1] & 0x20 ? 1 : 0;
78 return 0;
79 case V4L2_CID_VFLIP:
80 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
81 data) < 0)
82 return -EIO;
83 ctrl->value = data[1] & 0x80 ? 1 : 0;
84 return 0;
85 case V4L2_CID_RED_BALANCE:
86 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
87 data) < 0)
88 return -EIO;
89 break;
90 case V4L2_CID_BLUE_BALANCE:
91 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
92 data) < 0)
93 return -EIO;
94 break;
95 case SN9C102_V4L2_CID_GREEN_BALANCE:
96 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
97 data) < 0)
98 return -EIO;
99 break;
100 default:
101 return -EINVAL;
102 }
103
104 switch (ctrl->id) {
105 case V4L2_CID_GAIN:
106 case V4L2_CID_RED_BALANCE:
107 case V4L2_CID_BLUE_BALANCE:
108 case SN9C102_V4L2_CID_GREEN_BALANCE:
109 ctrl->value = data[1] | (data[0] << 8);
110 if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
111 ctrl->value -= 0x10;
112 else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
113 ctrl->value -= 0x60;
114 else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff)
115 ctrl->value -= 0xe0;
116 }
117
118 return 0;
119}
120
121
122static int mi0343_set_ctrl(struct sn9c102_device *cam,
123 const struct v4l2_control *ctrl)
124{
125 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
126 u16 reg = 0;
127 int err = 0;
128
129 switch (ctrl->id) {
130 case V4L2_CID_GAIN:
131 case V4L2_CID_RED_BALANCE:
132 case V4L2_CID_BLUE_BALANCE:
133 case SN9C102_V4L2_CID_GREEN_BALANCE:
134 if (ctrl->value <= (0x3f-0x10))
135 reg = 0x10 + ctrl->value;
136 else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60)))
137 reg = 0x60 + (ctrl->value - (0x3f-0x10));
138 else
139 reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60));
140 break;
141 }
142
143 switch (ctrl->id) {
144 case V4L2_CID_EXPOSURE:
145 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
146 0x09, ctrl->value, 0x00,
147 0, 0);
148 break;
149 case V4L2_CID_GAIN:
150 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
151 0x35, reg >> 8, reg & 0xff,
152 0, 0);
153 break;
154 case V4L2_CID_HFLIP:
155 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
156 0x20, ctrl->value ? 0x40:0x00,
157 ctrl->value ? 0x20:0x00,
158 0, 0);
159 break;
160 case V4L2_CID_VFLIP:
161 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
162 0x20, ctrl->value ? 0x80:0x00,
163 ctrl->value ? 0x80:0x00,
164 0, 0);
165 break;
166 case V4L2_CID_RED_BALANCE:
167 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
168 0x2d, reg >> 8, reg & 0xff,
169 0, 0);
170 break;
171 case V4L2_CID_BLUE_BALANCE:
172 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
173 0x2c, reg >> 8, reg & 0xff,
174 0, 0);
175 break;
176 case SN9C102_V4L2_CID_GREEN_BALANCE:
177 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
178 0x2b, reg >> 8, reg & 0xff,
179 0, 0);
180 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
181 0x2e, reg >> 8, reg & 0xff,
182 0, 0);
183 break;
184 default:
185 return -EINVAL;
186 }
187
188 return err ? -EIO : 0;
189}
190
191
192static int mi0343_set_crop(struct sn9c102_device *cam,
193 const struct v4l2_rect *rect)
194{
195 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
196 int err = 0;
197 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
198 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
199
200 err += sn9c102_write_reg(cam, h_start, 0x12);
201 err += sn9c102_write_reg(cam, v_start, 0x13);
202
203 return err;
204}
205
206
207static int mi0343_set_pix_format(struct sn9c102_device *cam,
208 const struct v4l2_pix_format *pix)
209{
210 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
211 int err = 0;
212
213 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
214 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
215 0x0a, 0x00, 0x03, 0, 0);
216 err += sn9c102_write_reg(cam, 0x20, 0x19);
217 } else {
218 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
219 0x0a, 0x00, 0x05, 0, 0);
220 err += sn9c102_write_reg(cam, 0xa0, 0x19);
221 }
222
223 return err;
224}
225
226
227static const struct sn9c102_sensor mi0343 = {
228 .name = "MI-0343",
229 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
230 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
231 .frequency = SN9C102_I2C_100KHZ,
232 .interface = SN9C102_I2C_2WIRES,
233 .i2c_slave_id = 0x5d,
234 .init = &mi0343_init,
235 .qctrl = {
236 {
237 .id = V4L2_CID_EXPOSURE,
238 .type = V4L2_CTRL_TYPE_INTEGER,
239 .name = "exposure",
240 .minimum = 0x00,
241 .maximum = 0x0f,
242 .step = 0x01,
243 .default_value = 0x06,
244 .flags = 0,
245 },
246 {
247 .id = V4L2_CID_GAIN,
248 .type = V4L2_CTRL_TYPE_INTEGER,
249 .name = "global gain",
250 .minimum = 0x00,
251 .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/
252 .step = 0x01,
253 .default_value = 0x00,
254 .flags = 0,
255 },
256 {
257 .id = V4L2_CID_HFLIP,
258 .type = V4L2_CTRL_TYPE_BOOLEAN,
259 .name = "horizontal mirror",
260 .minimum = 0,
261 .maximum = 1,
262 .step = 1,
263 .default_value = 0,
264 .flags = 0,
265 },
266 {
267 .id = V4L2_CID_VFLIP,
268 .type = V4L2_CTRL_TYPE_BOOLEAN,
269 .name = "vertical mirror",
270 .minimum = 0,
271 .maximum = 1,
272 .step = 1,
273 .default_value = 0,
274 .flags = 0,
275 },
276 {
277 .id = V4L2_CID_RED_BALANCE,
278 .type = V4L2_CTRL_TYPE_INTEGER,
279 .name = "red balance",
280 .minimum = 0x00,
281 .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
282 .step = 0x01,
283 .default_value = 0x00,
284 .flags = 0,
285 },
286 {
287 .id = V4L2_CID_BLUE_BALANCE,
288 .type = V4L2_CTRL_TYPE_INTEGER,
289 .name = "blue balance",
290 .minimum = 0x00,
291 .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
292 .step = 0x01,
293 .default_value = 0x00,
294 .flags = 0,
295 },
296 {
297 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
298 .type = V4L2_CTRL_TYPE_INTEGER,
299 .name = "green balance",
300 .minimum = 0x00,
301 .maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)),
302 .step = 0x01,
303 .default_value = 0x00,
304 .flags = 0,
305 },
306 },
307 .get_ctrl = &mi0343_get_ctrl,
308 .set_ctrl = &mi0343_set_ctrl,
309 .cropcap = {
310 .bounds = {
311 .left = 0,
312 .top = 0,
313 .width = 640,
314 .height = 480,
315 },
316 .defrect = {
317 .left = 0,
318 .top = 0,
319 .width = 640,
320 .height = 480,
321 },
322 },
323 .set_crop = &mi0343_set_crop,
324 .pix_format = {
325 .width = 640,
326 .height = 480,
327 .pixelformat = V4L2_PIX_FMT_SBGGR8,
328 .priv = 8,
329 },
330 .set_pix_format = &mi0343_set_pix_format
331};
332
333
334int sn9c102_probe_mi0343(struct sn9c102_device *cam)
335{
336 u8 data[2];
337
338 if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
339 {0x28, 0x17}))
340 return -EIO;
341
342 if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
343 2, data) < 0)
344 return -EIO;
345
346 if (data[1] != 0x42 || data[0] != 0xe3)
347 return -ENODEV;
348
349 sn9c102_attach_sensor(cam, &mi0343);
350
351 return 0;
352}
diff --git a/drivers/staging/media/sn9c102/sn9c102_mi0360.c b/drivers/staging/media/sn9c102/sn9c102_mi0360.c
deleted file mode 100644
index 5f21d1b43e32..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_mi0360.c
+++ /dev/null
@@ -1,453 +0,0 @@
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#include "sn9c102_devtable.h"
24
25
26static int mi0360_init(struct sn9c102_device *cam)
27{
28 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
29 int err = 0;
30
31 switch (sn9c102_get_bridge(cam)) {
32 case BRIDGE_SN9C103:
33 err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
34 {0x0a, 0x14}, {0x40, 0x01},
35 {0x20, 0x17}, {0x07, 0x18},
36 {0xa0, 0x19}, {0x02, 0x1c},
37 {0x03, 0x1d}, {0x0f, 0x1e},
38 {0x0c, 0x1f}, {0x00, 0x20},
39 {0x10, 0x21}, {0x20, 0x22},
40 {0x30, 0x23}, {0x40, 0x24},
41 {0x50, 0x25}, {0x60, 0x26},
42 {0x70, 0x27}, {0x80, 0x28},
43 {0x90, 0x29}, {0xa0, 0x2a},
44 {0xb0, 0x2b}, {0xc0, 0x2c},
45 {0xd0, 0x2d}, {0xe0, 0x2e},
46 {0xf0, 0x2f}, {0xff, 0x30});
47 break;
48 case BRIDGE_SN9C105:
49 case BRIDGE_SN9C120:
50 err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
51 {0x00, 0x03}, {0x1a, 0x04},
52 {0x50, 0x05}, {0x20, 0x06},
53 {0x10, 0x07}, {0x03, 0x10},
54 {0x08, 0x14}, {0xa2, 0x17},
55 {0x47, 0x18}, {0x00, 0x19},
56 {0x1d, 0x1a}, {0x10, 0x1b},
57 {0x02, 0x1c}, {0x03, 0x1d},
58 {0x0f, 0x1e}, {0x0c, 0x1f},
59 {0x00, 0x20}, {0x29, 0x21},
60 {0x40, 0x22}, {0x54, 0x23},
61 {0x66, 0x24}, {0x76, 0x25},
62 {0x85, 0x26}, {0x94, 0x27},
63 {0xa1, 0x28}, {0xae, 0x29},
64 {0xbb, 0x2a}, {0xc7, 0x2b},
65 {0xd3, 0x2c}, {0xde, 0x2d},
66 {0xea, 0x2e}, {0xf4, 0x2f},
67 {0xff, 0x30}, {0x00, 0x3F},
68 {0xC7, 0x40}, {0x01, 0x41},
69 {0x44, 0x42}, {0x00, 0x43},
70 {0x44, 0x44}, {0x00, 0x45},
71 {0x44, 0x46}, {0x00, 0x47},
72 {0xC7, 0x48}, {0x01, 0x49},
73 {0xC7, 0x4A}, {0x01, 0x4B},
74 {0xC7, 0x4C}, {0x01, 0x4D},
75 {0x44, 0x4E}, {0x00, 0x4F},
76 {0x44, 0x50}, {0x00, 0x51},
77 {0x44, 0x52}, {0x00, 0x53},
78 {0xC7, 0x54}, {0x01, 0x55},
79 {0xC7, 0x56}, {0x01, 0x57},
80 {0xC7, 0x58}, {0x01, 0x59},
81 {0x44, 0x5A}, {0x00, 0x5B},
82 {0x44, 0x5C}, {0x00, 0x5D},
83 {0x44, 0x5E}, {0x00, 0x5F},
84 {0xC7, 0x60}, {0x01, 0x61},
85 {0xC7, 0x62}, {0x01, 0x63},
86 {0xC7, 0x64}, {0x01, 0x65},
87 {0x44, 0x66}, {0x00, 0x67},
88 {0x44, 0x68}, {0x00, 0x69},
89 {0x44, 0x6A}, {0x00, 0x6B},
90 {0xC7, 0x6C}, {0x01, 0x6D},
91 {0xC7, 0x6E}, {0x01, 0x6F},
92 {0xC7, 0x70}, {0x01, 0x71},
93 {0x44, 0x72}, {0x00, 0x73},
94 {0x44, 0x74}, {0x00, 0x75},
95 {0x44, 0x76}, {0x00, 0x77},
96 {0xC7, 0x78}, {0x01, 0x79},
97 {0xC7, 0x7A}, {0x01, 0x7B},
98 {0xC7, 0x7C}, {0x01, 0x7D},
99 {0x44, 0x7E}, {0x00, 0x7F},
100 {0x14, 0x84}, {0x00, 0x85},
101 {0x27, 0x86}, {0x00, 0x87},
102 {0x07, 0x88}, {0x00, 0x89},
103 {0xEC, 0x8A}, {0x0f, 0x8B},
104 {0xD8, 0x8C}, {0x0f, 0x8D},
105 {0x3D, 0x8E}, {0x00, 0x8F},
106 {0x3D, 0x90}, {0x00, 0x91},
107 {0xCD, 0x92}, {0x0f, 0x93},
108 {0xf7, 0x94}, {0x0f, 0x95},
109 {0x0C, 0x96}, {0x00, 0x97},
110 {0x00, 0x98}, {0x66, 0x99},
111 {0x05, 0x9A}, {0x00, 0x9B},
112 {0x04, 0x9C}, {0x00, 0x9D},
113 {0x08, 0x9E}, {0x00, 0x9F},
114 {0x2D, 0xC0}, {0x2D, 0xC1},
115 {0x3A, 0xC2}, {0x05, 0xC3},
116 {0x04, 0xC4}, {0x3F, 0xC5},
117 {0x00, 0xC6}, {0x00, 0xC7},
118 {0x50, 0xC8}, {0x3C, 0xC9},
119 {0x28, 0xCA}, {0xD8, 0xCB},
120 {0x14, 0xCC}, {0xEC, 0xCD},
121 {0x32, 0xCE}, {0xDD, 0xCF},
122 {0x32, 0xD0}, {0xDD, 0xD1},
123 {0x6A, 0xD2}, {0x50, 0xD3},
124 {0x00, 0xD4}, {0x00, 0xD5},
125 {0x00, 0xD6});
126 break;
127 default:
128 break;
129 }
130
131 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
132 0x00, 0x01, 0, 0);
133 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
134 0x00, 0x00, 0, 0);
135 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
136 0x01, 0xe1, 0, 0);
137 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
138 0x02, 0x81, 0, 0);
139 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
140 0x00, 0x17, 0, 0);
141 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
142 0x00, 0x11, 0, 0);
143 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
144 0x04, 0x9a, 0, 0);
145
146 return err;
147}
148
149
150static int mi0360_get_ctrl(struct sn9c102_device *cam,
151 struct v4l2_control *ctrl)
152{
153 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
154 u8 data[2];
155
156 switch (ctrl->id) {
157 case V4L2_CID_EXPOSURE:
158 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
159 data) < 0)
160 return -EIO;
161 ctrl->value = data[0];
162 return 0;
163 case V4L2_CID_GAIN:
164 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
165 data) < 0)
166 return -EIO;
167 ctrl->value = data[1];
168 return 0;
169 case V4L2_CID_RED_BALANCE:
170 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
171 data) < 0)
172 return -EIO;
173 ctrl->value = data[1];
174 return 0;
175 case V4L2_CID_BLUE_BALANCE:
176 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
177 data) < 0)
178 return -EIO;
179 ctrl->value = data[1];
180 return 0;
181 case SN9C102_V4L2_CID_GREEN_BALANCE:
182 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
183 data) < 0)
184 return -EIO;
185 ctrl->value = data[1];
186 return 0;
187 case V4L2_CID_HFLIP:
188 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
189 data) < 0)
190 return -EIO;
191 ctrl->value = data[1] & 0x20 ? 1 : 0;
192 return 0;
193 case V4L2_CID_VFLIP:
194 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
195 data) < 0)
196 return -EIO;
197 ctrl->value = data[1] & 0x80 ? 1 : 0;
198 return 0;
199 default:
200 return -EINVAL;
201 }
202
203 return 0;
204}
205
206
207static int mi0360_set_ctrl(struct sn9c102_device *cam,
208 const struct v4l2_control *ctrl)
209{
210 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
211 int err = 0;
212
213 switch (ctrl->id) {
214 case V4L2_CID_EXPOSURE:
215 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
216 0x09, ctrl->value, 0x00,
217 0, 0);
218 break;
219 case V4L2_CID_GAIN:
220 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
221 0x35, 0x03, ctrl->value,
222 0, 0);
223 break;
224 case V4L2_CID_RED_BALANCE:
225 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
226 0x2c, 0x03, ctrl->value,
227 0, 0);
228 break;
229 case V4L2_CID_BLUE_BALANCE:
230 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
231 0x2d, 0x03, ctrl->value,
232 0, 0);
233 break;
234 case SN9C102_V4L2_CID_GREEN_BALANCE:
235 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
236 0x2b, 0x03, ctrl->value,
237 0, 0);
238 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
239 0x2e, 0x03, ctrl->value,
240 0, 0);
241 break;
242 case V4L2_CID_HFLIP:
243 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
244 0x20, ctrl->value ? 0x40:0x00,
245 ctrl->value ? 0x20:0x00,
246 0, 0);
247 break;
248 case V4L2_CID_VFLIP:
249 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
250 0x20, ctrl->value ? 0x80:0x00,
251 ctrl->value ? 0x80:0x00,
252 0, 0);
253 break;
254 default:
255 return -EINVAL;
256 }
257
258 return err ? -EIO : 0;
259}
260
261
262static int mi0360_set_crop(struct sn9c102_device *cam,
263 const struct v4l2_rect *rect)
264{
265 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
266 int err = 0;
267 u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
268
269 switch (sn9c102_get_bridge(cam)) {
270 case BRIDGE_SN9C103:
271 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0;
272 break;
273 case BRIDGE_SN9C105:
274 case BRIDGE_SN9C120:
275 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
276 break;
277 default:
278 break;
279 }
280
281 err += sn9c102_write_reg(cam, h_start, 0x12);
282 err += sn9c102_write_reg(cam, v_start, 0x13);
283
284 return err;
285}
286
287
288static int mi0360_set_pix_format(struct sn9c102_device *cam,
289 const struct v4l2_pix_format *pix)
290{
291 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
292 int err = 0;
293
294 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
295 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
296 0x0a, 0x00, 0x05, 0, 0);
297 err += sn9c102_write_reg(cam, 0x60, 0x19);
298 if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
299 sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
300 err += sn9c102_write_reg(cam, 0xa6, 0x17);
301 } else {
302 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
303 0x0a, 0x00, 0x02, 0, 0);
304 err += sn9c102_write_reg(cam, 0x20, 0x19);
305 if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
306 sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
307 err += sn9c102_write_reg(cam, 0xa2, 0x17);
308 }
309
310 return err;
311}
312
313
314static const struct sn9c102_sensor mi0360 = {
315 .name = "MI-0360",
316 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
317 .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
318 .frequency = SN9C102_I2C_100KHZ,
319 .interface = SN9C102_I2C_2WIRES,
320 .i2c_slave_id = 0x5d,
321 .init = &mi0360_init,
322 .qctrl = {
323 {
324 .id = V4L2_CID_EXPOSURE,
325 .type = V4L2_CTRL_TYPE_INTEGER,
326 .name = "exposure",
327 .minimum = 0x00,
328 .maximum = 0x0f,
329 .step = 0x01,
330 .default_value = 0x05,
331 .flags = 0,
332 },
333 {
334 .id = V4L2_CID_GAIN,
335 .type = V4L2_CTRL_TYPE_INTEGER,
336 .name = "global gain",
337 .minimum = 0x00,
338 .maximum = 0x7f,
339 .step = 0x01,
340 .default_value = 0x25,
341 .flags = 0,
342 },
343 {
344 .id = V4L2_CID_HFLIP,
345 .type = V4L2_CTRL_TYPE_BOOLEAN,
346 .name = "horizontal mirror",
347 .minimum = 0,
348 .maximum = 1,
349 .step = 1,
350 .default_value = 0,
351 .flags = 0,
352 },
353 {
354 .id = V4L2_CID_VFLIP,
355 .type = V4L2_CTRL_TYPE_BOOLEAN,
356 .name = "vertical mirror",
357 .minimum = 0,
358 .maximum = 1,
359 .step = 1,
360 .default_value = 0,
361 .flags = 0,
362 },
363 {
364 .id = V4L2_CID_BLUE_BALANCE,
365 .type = V4L2_CTRL_TYPE_INTEGER,
366 .name = "blue balance",
367 .minimum = 0x00,
368 .maximum = 0x7f,
369 .step = 0x01,
370 .default_value = 0x0f,
371 .flags = 0,
372 },
373 {
374 .id = V4L2_CID_RED_BALANCE,
375 .type = V4L2_CTRL_TYPE_INTEGER,
376 .name = "red balance",
377 .minimum = 0x00,
378 .maximum = 0x7f,
379 .step = 0x01,
380 .default_value = 0x32,
381 .flags = 0,
382 },
383 {
384 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
385 .type = V4L2_CTRL_TYPE_INTEGER,
386 .name = "green balance",
387 .minimum = 0x00,
388 .maximum = 0x7f,
389 .step = 0x01,
390 .default_value = 0x25,
391 .flags = 0,
392 },
393 },
394 .get_ctrl = &mi0360_get_ctrl,
395 .set_ctrl = &mi0360_set_ctrl,
396 .cropcap = {
397 .bounds = {
398 .left = 0,
399 .top = 0,
400 .width = 640,
401 .height = 480,
402 },
403 .defrect = {
404 .left = 0,
405 .top = 0,
406 .width = 640,
407 .height = 480,
408 },
409 },
410 .set_crop = &mi0360_set_crop,
411 .pix_format = {
412 .width = 640,
413 .height = 480,
414 .pixelformat = V4L2_PIX_FMT_SBGGR8,
415 .priv = 8,
416 },
417 .set_pix_format = &mi0360_set_pix_format
418};
419
420
421int sn9c102_probe_mi0360(struct sn9c102_device *cam)
422{
423
424 u8 data[2];
425
426 switch (sn9c102_get_bridge(cam)) {
427 case BRIDGE_SN9C103:
428 if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
429 {0x28, 0x17}))
430 return -EIO;
431 break;
432 case BRIDGE_SN9C105:
433 case BRIDGE_SN9C120:
434 if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
435 {0x01, 0x01}, {0x00, 0x01},
436 {0x28, 0x17}))
437 return -EIO;
438 break;
439 default:
440 break;
441 }
442
443 if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
444 2, data) < 0)
445 return -EIO;
446
447 if (data[0] != 0x82 || data[1] != 0x43)
448 return -ENODEV;
449
450 sn9c102_attach_sensor(cam, &mi0360);
451
452 return 0;
453}
diff --git a/drivers/staging/media/sn9c102/sn9c102_mt9v111.c b/drivers/staging/media/sn9c102/sn9c102_mt9v111.c
deleted file mode 100644
index 95986eb492e4..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_mt9v111.c
+++ /dev/null
@@ -1,260 +0,0 @@
1/***************************************************************************
2 * Plug-in for MT9V111 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#include "sn9c102_devtable.h"
24
25
26static int mt9v111_init(struct sn9c102_device *cam)
27{
28 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
29 int err = 0;
30
31 err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
32 {0x00, 0x03}, {0x1a, 0x04},
33 {0x1f, 0x05}, {0x20, 0x06},
34 {0x1f, 0x07}, {0x81, 0x08},
35 {0x5c, 0x09}, {0x00, 0x0a},
36 {0x00, 0x0b}, {0x00, 0x0c},
37 {0x00, 0x0d}, {0x00, 0x0e},
38 {0x00, 0x0f}, {0x03, 0x10},
39 {0x00, 0x11}, {0x00, 0x12},
40 {0x02, 0x13}, {0x14, 0x14},
41 {0x28, 0x15}, {0x1e, 0x16},
42 {0xe2, 0x17}, {0x06, 0x18},
43 {0x00, 0x19}, {0x00, 0x1a},
44 {0x00, 0x1b}, {0x08, 0x20},
45 {0x39, 0x21}, {0x51, 0x22},
46 {0x63, 0x23}, {0x73, 0x24},
47 {0x82, 0x25}, {0x8f, 0x26},
48 {0x9b, 0x27}, {0xa7, 0x28},
49 {0xb1, 0x29}, {0xbc, 0x2a},
50 {0xc6, 0x2b}, {0xcf, 0x2c},
51 {0xd8, 0x2d}, {0xe1, 0x2e},
52 {0xea, 0x2f}, {0xf2, 0x30},
53 {0x13, 0x84}, {0x00, 0x85},
54 {0x25, 0x86}, {0x00, 0x87},
55 {0x07, 0x88}, {0x00, 0x89},
56 {0xee, 0x8a}, {0x0f, 0x8b},
57 {0xe5, 0x8c}, {0x0f, 0x8d},
58 {0x2e, 0x8e}, {0x00, 0x8f},
59 {0x30, 0x90}, {0x00, 0x91},
60 {0xd4, 0x92}, {0x0f, 0x93},
61 {0xfc, 0x94}, {0x0f, 0x95},
62 {0x14, 0x96}, {0x00, 0x97},
63 {0x00, 0x98}, {0x60, 0x99},
64 {0x07, 0x9a}, {0x40, 0x9b},
65 {0x20, 0x9c}, {0x00, 0x9d},
66 {0x00, 0x9e}, {0x00, 0x9f},
67 {0x2d, 0xc0}, {0x2d, 0xc1},
68 {0x3a, 0xc2}, {0x05, 0xc3},
69 {0x04, 0xc4}, {0x3f, 0xc5},
70 {0x00, 0xc6}, {0x00, 0xc7},
71 {0x50, 0xc8}, {0x3c, 0xc9},
72 {0x28, 0xca}, {0xd8, 0xcb},
73 {0x14, 0xcc}, {0xec, 0xcd},
74 {0x32, 0xce}, {0xdd, 0xcf},
75 {0x2d, 0xd0}, {0xdd, 0xd1},
76 {0x6a, 0xd2}, {0x50, 0xd3},
77 {0x60, 0xd4}, {0x00, 0xd5},
78 {0x00, 0xd6});
79
80 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
81 0x00, 0x01, 0, 0);
82 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
83 0x00, 0x01, 0, 0);
84 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
85 0x00, 0x00, 0, 0);
86 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
87 0x04, 0x80, 0, 0);
88 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
89 0x00, 0x04, 0, 0);
90 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
91 0x00, 0x08, 0, 0);
92 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x02,
93 0x00, 0x16, 0, 0);
94 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
95 0x01, 0xe7, 0, 0);
96 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
97 0x02, 0x87, 0, 0);
98 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
99 0x00, 0x40, 0, 0);
100 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
101 0x00, 0x09, 0, 0);
102 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x07,
103 0x30, 0x02, 0, 0);
104 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0c,
105 0x00, 0x00, 0, 0);
106 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x12,
107 0x00, 0xb0, 0, 0);
108 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x13,
109 0x00, 0x7c, 0, 0);
110 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x1e,
111 0x00, 0x00, 0, 0);
112 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
113 0x00, 0x00, 0, 0);
114 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
115 0x00, 0x00, 0, 0);
116 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
117 0x00, 0x04, 0, 0);
118
119 return err;
120}
121
122static int mt9v111_get_ctrl(struct sn9c102_device *cam,
123 struct v4l2_control *ctrl)
124{
125 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
126 u8 data[2];
127 int err = 0;
128
129 switch (ctrl->id) {
130 case V4L2_CID_VFLIP:
131 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
132 data) < 0)
133 return -EIO;
134 ctrl->value = data[1] & 0x80 ? 1 : 0;
135 return 0;
136 default:
137 return -EINVAL;
138 }
139
140 return err ? -EIO : 0;
141}
142
143static int mt9v111_set_ctrl(struct sn9c102_device *cam,
144 const struct v4l2_control *ctrl)
145{
146 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
147 int err = 0;
148
149 switch (ctrl->id) {
150 case V4L2_CID_VFLIP:
151 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
152 0x20,
153 ctrl->value ? 0x80 : 0x00,
154 ctrl->value ? 0x80 : 0x00, 0,
155 0);
156 break;
157 default:
158 return -EINVAL;
159 }
160
161 return err ? -EIO : 0;
162}
163
164static int mt9v111_set_crop(struct sn9c102_device *cam,
165 const struct v4l2_rect *rect)
166{
167 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
168 int err = 0;
169 u8 v_start = (u8) (rect->top - s->cropcap.bounds.top) + 2;
170
171 err += sn9c102_write_reg(cam, v_start, 0x13);
172
173 return err;
174}
175
176static int mt9v111_set_pix_format(struct sn9c102_device *cam,
177 const struct v4l2_pix_format *pix)
178{
179 int err = 0;
180
181 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
182 err += sn9c102_write_reg(cam, 0xb4, 0x17);
183 } else {
184 err += sn9c102_write_reg(cam, 0xe2, 0x17);
185 }
186
187 return err;
188}
189
190
191static const struct sn9c102_sensor mt9v111 = {
192 .name = "MT9V111",
193 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
194 .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
195 .frequency = SN9C102_I2C_100KHZ,
196 .interface = SN9C102_I2C_2WIRES,
197 .i2c_slave_id = 0x5c,
198 .init = &mt9v111_init,
199 .qctrl = {
200 {
201 .id = V4L2_CID_VFLIP,
202 .type = V4L2_CTRL_TYPE_BOOLEAN,
203 .name = "vertical mirror",
204 .minimum = 0,
205 .maximum = 1,
206 .step = 1,
207 .default_value = 0,
208 .flags = 0,
209 },
210 },
211 .get_ctrl = &mt9v111_get_ctrl,
212 .set_ctrl = &mt9v111_set_ctrl,
213 .cropcap = {
214 .bounds = {
215 .left = 0,
216 .top = 0,
217 .width = 640,
218 .height = 480,
219 },
220 .defrect = {
221 .left = 0,
222 .top = 0,
223 .width = 640,
224 .height = 480,
225 },
226 },
227 .set_crop = &mt9v111_set_crop,
228 .pix_format = {
229 .width = 640,
230 .height = 480,
231 .pixelformat = V4L2_PIX_FMT_SBGGR8,
232 .priv = 8,
233 },
234 .set_pix_format = &mt9v111_set_pix_format
235};
236
237
238int sn9c102_probe_mt9v111(struct sn9c102_device *cam)
239{
240 u8 data[2];
241 int err = 0;
242
243 err += sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
244 {0x29, 0x01}, {0x42, 0x17},
245 {0x62, 0x17}, {0x08, 0x01});
246 err += sn9c102_i2c_try_raw_write(cam, &mt9v111, 4,
247 mt9v111.i2c_slave_id, 0x01, 0x00,
248 0x04, 0, 0);
249 if (err || sn9c102_i2c_try_raw_read(cam, &mt9v111,
250 mt9v111.i2c_slave_id, 0x36, 2,
251 data) < 0)
252 return -EIO;
253
254 if (data[0] != 0x82 || data[1] != 0x3a)
255 return -ENODEV;
256
257 sn9c102_attach_sensor(cam, &mt9v111);
258
259 return 0;
260}
diff --git a/drivers/staging/media/sn9c102/sn9c102_ov7630.c b/drivers/staging/media/sn9c102/sn9c102_ov7630.c
deleted file mode 100644
index 9ec304dc4705..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_ov7630.c
+++ /dev/null
@@ -1,634 +0,0 @@
1/***************************************************************************
2 * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2006-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#include "sn9c102_devtable.h"
24
25
26static int ov7630_init(struct sn9c102_device *cam)
27{
28 int err = 0;
29
30 switch (sn9c102_get_bridge(cam)) {
31 case BRIDGE_SN9C101:
32 case BRIDGE_SN9C102:
33 err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17},
34 {0x0f, 0x18}, {0x50, 0x19});
35
36 err += sn9c102_i2c_write(cam, 0x12, 0x8d);
37 err += sn9c102_i2c_write(cam, 0x12, 0x0d);
38 err += sn9c102_i2c_write(cam, 0x11, 0x00);
39 err += sn9c102_i2c_write(cam, 0x15, 0x35);
40 err += sn9c102_i2c_write(cam, 0x16, 0x03);
41 err += sn9c102_i2c_write(cam, 0x17, 0x1c);
42 err += sn9c102_i2c_write(cam, 0x18, 0xbd);
43 err += sn9c102_i2c_write(cam, 0x19, 0x06);
44 err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
45 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
46 err += sn9c102_i2c_write(cam, 0x20, 0x44);
47 err += sn9c102_i2c_write(cam, 0x23, 0xee);
48 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
49 err += sn9c102_i2c_write(cam, 0x27, 0x9a);
50 err += sn9c102_i2c_write(cam, 0x28, 0x20);
51 err += sn9c102_i2c_write(cam, 0x29, 0x30);
52 err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
53 err += sn9c102_i2c_write(cam, 0x30, 0x24);
54 err += sn9c102_i2c_write(cam, 0x32, 0x86);
55 err += sn9c102_i2c_write(cam, 0x60, 0xa9);
56 err += sn9c102_i2c_write(cam, 0x61, 0x42);
57 err += sn9c102_i2c_write(cam, 0x65, 0x00);
58 err += sn9c102_i2c_write(cam, 0x69, 0x38);
59 err += sn9c102_i2c_write(cam, 0x6f, 0x88);
60 err += sn9c102_i2c_write(cam, 0x70, 0x0b);
61 err += sn9c102_i2c_write(cam, 0x71, 0x00);
62 err += sn9c102_i2c_write(cam, 0x74, 0x21);
63 err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
64 break;
65 case BRIDGE_SN9C103:
66 err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
67 {0x1a, 0x04}, {0x20, 0x05},
68 {0x20, 0x06}, {0x20, 0x07},
69 {0x03, 0x10}, {0x0a, 0x14},
70 {0x60, 0x17}, {0x0f, 0x18},
71 {0x50, 0x19}, {0x1d, 0x1a},
72 {0x10, 0x1b}, {0x02, 0x1c},
73 {0x03, 0x1d}, {0x0f, 0x1e},
74 {0x0c, 0x1f}, {0x00, 0x20},
75 {0x10, 0x21}, {0x20, 0x22},
76 {0x30, 0x23}, {0x40, 0x24},
77 {0x50, 0x25}, {0x60, 0x26},
78 {0x70, 0x27}, {0x80, 0x28},
79 {0x90, 0x29}, {0xa0, 0x2a},
80 {0xb0, 0x2b}, {0xc0, 0x2c},
81 {0xd0, 0x2d}, {0xe0, 0x2e},
82 {0xf0, 0x2f}, {0xff, 0x30});
83
84 err += sn9c102_i2c_write(cam, 0x12, 0x8d);
85 err += sn9c102_i2c_write(cam, 0x12, 0x0d);
86 err += sn9c102_i2c_write(cam, 0x15, 0x34);
87 err += sn9c102_i2c_write(cam, 0x11, 0x01);
88 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
89 err += sn9c102_i2c_write(cam, 0x20, 0x44);
90 err += sn9c102_i2c_write(cam, 0x23, 0xee);
91 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
92 err += sn9c102_i2c_write(cam, 0x27, 0x9a);
93 err += sn9c102_i2c_write(cam, 0x28, 0x20);
94 err += sn9c102_i2c_write(cam, 0x29, 0x30);
95 err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
96 err += sn9c102_i2c_write(cam, 0x30, 0x24);
97 err += sn9c102_i2c_write(cam, 0x32, 0x86);
98 err += sn9c102_i2c_write(cam, 0x60, 0xa9);
99 err += sn9c102_i2c_write(cam, 0x61, 0x42);
100 err += sn9c102_i2c_write(cam, 0x65, 0x00);
101 err += sn9c102_i2c_write(cam, 0x69, 0x38);
102 err += sn9c102_i2c_write(cam, 0x6f, 0x88);
103 err += sn9c102_i2c_write(cam, 0x70, 0x0b);
104 err += sn9c102_i2c_write(cam, 0x71, 0x00);
105 err += sn9c102_i2c_write(cam, 0x74, 0x21);
106 err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
107 break;
108 case BRIDGE_SN9C105:
109 case BRIDGE_SN9C120:
110 err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
111 {0x1a, 0x04}, {0x03, 0x10},
112 {0x0a, 0x14}, {0xe2, 0x17},
113 {0x0b, 0x18}, {0x00, 0x19},
114 {0x1d, 0x1a}, {0x10, 0x1b},
115 {0x02, 0x1c}, {0x03, 0x1d},
116 {0x0f, 0x1e}, {0x0c, 0x1f},
117 {0x00, 0x20}, {0x24, 0x21},
118 {0x3b, 0x22}, {0x47, 0x23},
119 {0x60, 0x24}, {0x71, 0x25},
120 {0x80, 0x26}, {0x8f, 0x27},
121 {0x9d, 0x28}, {0xaa, 0x29},
122 {0xb8, 0x2a}, {0xc4, 0x2b},
123 {0xd1, 0x2c}, {0xdd, 0x2d},
124 {0xe8, 0x2e}, {0xf4, 0x2f},
125 {0xff, 0x30}, {0x00, 0x3f},
126 {0xc7, 0x40}, {0x01, 0x41},
127 {0x44, 0x42}, {0x00, 0x43},
128 {0x44, 0x44}, {0x00, 0x45},
129 {0x44, 0x46}, {0x00, 0x47},
130 {0xc7, 0x48}, {0x01, 0x49},
131 {0xc7, 0x4a}, {0x01, 0x4b},
132 {0xc7, 0x4c}, {0x01, 0x4d},
133 {0x44, 0x4e}, {0x00, 0x4f},
134 {0x44, 0x50}, {0x00, 0x51},
135 {0x44, 0x52}, {0x00, 0x53},
136 {0xc7, 0x54}, {0x01, 0x55},
137 {0xc7, 0x56}, {0x01, 0x57},
138 {0xc7, 0x58}, {0x01, 0x59},
139 {0x44, 0x5a}, {0x00, 0x5b},
140 {0x44, 0x5c}, {0x00, 0x5d},
141 {0x44, 0x5e}, {0x00, 0x5f},
142 {0xc7, 0x60}, {0x01, 0x61},
143 {0xc7, 0x62}, {0x01, 0x63},
144 {0xc7, 0x64}, {0x01, 0x65},
145 {0x44, 0x66}, {0x00, 0x67},
146 {0x44, 0x68}, {0x00, 0x69},
147 {0x44, 0x6a}, {0x00, 0x6b},
148 {0xc7, 0x6c}, {0x01, 0x6d},
149 {0xc7, 0x6e}, {0x01, 0x6f},
150 {0xc7, 0x70}, {0x01, 0x71},
151 {0x44, 0x72}, {0x00, 0x73},
152 {0x44, 0x74}, {0x00, 0x75},
153 {0x44, 0x76}, {0x00, 0x77},
154 {0xc7, 0x78}, {0x01, 0x79},
155 {0xc7, 0x7a}, {0x01, 0x7b},
156 {0xc7, 0x7c}, {0x01, 0x7d},
157 {0x44, 0x7e}, {0x00, 0x7f},
158 {0x17, 0x84}, {0x00, 0x85},
159 {0x2e, 0x86}, {0x00, 0x87},
160 {0x09, 0x88}, {0x00, 0x89},
161 {0xe8, 0x8a}, {0x0f, 0x8b},
162 {0xda, 0x8c}, {0x0f, 0x8d},
163 {0x40, 0x8e}, {0x00, 0x8f},
164 {0x37, 0x90}, {0x00, 0x91},
165 {0xcf, 0x92}, {0x0f, 0x93},
166 {0xfa, 0x94}, {0x0f, 0x95},
167 {0x00, 0x96}, {0x00, 0x97},
168 {0x00, 0x98}, {0x66, 0x99},
169 {0x00, 0x9a}, {0x40, 0x9b},
170 {0x20, 0x9c}, {0x00, 0x9d},
171 {0x00, 0x9e}, {0x00, 0x9f},
172 {0x2d, 0xc0}, {0x2d, 0xc1},
173 {0x3a, 0xc2}, {0x00, 0xc3},
174 {0x04, 0xc4}, {0x3f, 0xc5},
175 {0x00, 0xc6}, {0x00, 0xc7},
176 {0x50, 0xc8}, {0x3c, 0xc9},
177 {0x28, 0xca}, {0xd8, 0xcb},
178 {0x14, 0xcc}, {0xec, 0xcd},
179 {0x32, 0xce}, {0xdd, 0xcf},
180 {0x32, 0xd0}, {0xdd, 0xd1},
181 {0x6a, 0xd2}, {0x50, 0xd3},
182 {0x60, 0xd4}, {0x00, 0xd5},
183 {0x00, 0xd6});
184
185 err += sn9c102_i2c_write(cam, 0x12, 0x80);
186 err += sn9c102_i2c_write(cam, 0x12, 0x48);
187 err += sn9c102_i2c_write(cam, 0x01, 0x80);
188 err += sn9c102_i2c_write(cam, 0x02, 0x80);
189 err += sn9c102_i2c_write(cam, 0x03, 0x80);
190 err += sn9c102_i2c_write(cam, 0x04, 0x10);
191 err += sn9c102_i2c_write(cam, 0x05, 0x20);
192 err += sn9c102_i2c_write(cam, 0x06, 0x80);
193 err += sn9c102_i2c_write(cam, 0x11, 0x00);
194 err += sn9c102_i2c_write(cam, 0x0c, 0x20);
195 err += sn9c102_i2c_write(cam, 0x0d, 0x20);
196 err += sn9c102_i2c_write(cam, 0x15, 0x80);
197 err += sn9c102_i2c_write(cam, 0x16, 0x03);
198 err += sn9c102_i2c_write(cam, 0x17, 0x1b);
199 err += sn9c102_i2c_write(cam, 0x18, 0xbd);
200 err += sn9c102_i2c_write(cam, 0x19, 0x05);
201 err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
202 err += sn9c102_i2c_write(cam, 0x1b, 0x04);
203 err += sn9c102_i2c_write(cam, 0x21, 0x1b);
204 err += sn9c102_i2c_write(cam, 0x22, 0x00);
205 err += sn9c102_i2c_write(cam, 0x23, 0xde);
206 err += sn9c102_i2c_write(cam, 0x24, 0x10);
207 err += sn9c102_i2c_write(cam, 0x25, 0x8a);
208 err += sn9c102_i2c_write(cam, 0x26, 0xa0);
209 err += sn9c102_i2c_write(cam, 0x27, 0xca);
210 err += sn9c102_i2c_write(cam, 0x28, 0xa2);
211 err += sn9c102_i2c_write(cam, 0x29, 0x74);
212 err += sn9c102_i2c_write(cam, 0x2a, 0x88);
213 err += sn9c102_i2c_write(cam, 0x2b, 0x34);
214 err += sn9c102_i2c_write(cam, 0x2c, 0x88);
215 err += sn9c102_i2c_write(cam, 0x2e, 0x00);
216 err += sn9c102_i2c_write(cam, 0x2f, 0x00);
217 err += sn9c102_i2c_write(cam, 0x30, 0x00);
218 err += sn9c102_i2c_write(cam, 0x32, 0xc2);
219 err += sn9c102_i2c_write(cam, 0x33, 0x08);
220 err += sn9c102_i2c_write(cam, 0x4c, 0x40);
221 err += sn9c102_i2c_write(cam, 0x4d, 0xf3);
222 err += sn9c102_i2c_write(cam, 0x60, 0x05);
223 err += sn9c102_i2c_write(cam, 0x61, 0x40);
224 err += sn9c102_i2c_write(cam, 0x62, 0x12);
225 err += sn9c102_i2c_write(cam, 0x63, 0x57);
226 err += sn9c102_i2c_write(cam, 0x64, 0x73);
227 err += sn9c102_i2c_write(cam, 0x65, 0x00);
228 err += sn9c102_i2c_write(cam, 0x66, 0x55);
229 err += sn9c102_i2c_write(cam, 0x67, 0x01);
230 err += sn9c102_i2c_write(cam, 0x68, 0xac);
231 err += sn9c102_i2c_write(cam, 0x69, 0x38);
232 err += sn9c102_i2c_write(cam, 0x6f, 0x1f);
233 err += sn9c102_i2c_write(cam, 0x70, 0x01);
234 err += sn9c102_i2c_write(cam, 0x71, 0x00);
235 err += sn9c102_i2c_write(cam, 0x72, 0x10);
236 err += sn9c102_i2c_write(cam, 0x73, 0x50);
237 err += sn9c102_i2c_write(cam, 0x74, 0x20);
238 err += sn9c102_i2c_write(cam, 0x76, 0x01);
239 err += sn9c102_i2c_write(cam, 0x77, 0xf3);
240 err += sn9c102_i2c_write(cam, 0x78, 0x90);
241 err += sn9c102_i2c_write(cam, 0x79, 0x98);
242 err += sn9c102_i2c_write(cam, 0x7a, 0x98);
243 err += sn9c102_i2c_write(cam, 0x7b, 0x00);
244 err += sn9c102_i2c_write(cam, 0x7c, 0x38);
245 err += sn9c102_i2c_write(cam, 0x7d, 0xff);
246 break;
247 default:
248 break;
249 }
250
251 return err;
252}
253
254
255static int ov7630_get_ctrl(struct sn9c102_device *cam,
256 struct v4l2_control *ctrl)
257{
258 enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
259 int err = 0;
260
261 switch (ctrl->id) {
262 case V4L2_CID_EXPOSURE:
263 ctrl->value = sn9c102_i2c_read(cam, 0x10);
264 if (ctrl->value < 0)
265 return -EIO;
266 break;
267 case V4L2_CID_RED_BALANCE:
268 if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
269 ctrl->value = sn9c102_pread_reg(cam, 0x05);
270 else
271 ctrl->value = sn9c102_pread_reg(cam, 0x07);
272 break;
273 case V4L2_CID_BLUE_BALANCE:
274 ctrl->value = sn9c102_pread_reg(cam, 0x06);
275 break;
276 case SN9C102_V4L2_CID_GREEN_BALANCE:
277 if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
278 ctrl->value = sn9c102_pread_reg(cam, 0x07);
279 else
280 ctrl->value = sn9c102_pread_reg(cam, 0x05);
281 break;
282 break;
283 case V4L2_CID_GAIN:
284 ctrl->value = sn9c102_i2c_read(cam, 0x00);
285 if (ctrl->value < 0)
286 return -EIO;
287 ctrl->value &= 0x3f;
288 break;
289 case V4L2_CID_DO_WHITE_BALANCE:
290 ctrl->value = sn9c102_i2c_read(cam, 0x0c);
291 if (ctrl->value < 0)
292 return -EIO;
293 ctrl->value &= 0x3f;
294 break;
295 case V4L2_CID_WHITENESS:
296 ctrl->value = sn9c102_i2c_read(cam, 0x0d);
297 if (ctrl->value < 0)
298 return -EIO;
299 ctrl->value &= 0x3f;
300 break;
301 case V4L2_CID_AUTOGAIN:
302 ctrl->value = sn9c102_i2c_read(cam, 0x13);
303 if (ctrl->value < 0)
304 return -EIO;
305 ctrl->value &= 0x01;
306 break;
307 case V4L2_CID_VFLIP:
308 ctrl->value = sn9c102_i2c_read(cam, 0x75);
309 if (ctrl->value < 0)
310 return -EIO;
311 ctrl->value = (ctrl->value & 0x80) ? 1 : 0;
312 break;
313 case SN9C102_V4L2_CID_GAMMA:
314 ctrl->value = sn9c102_i2c_read(cam, 0x14);
315 if (ctrl->value < 0)
316 return -EIO;
317 ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
318 break;
319 case SN9C102_V4L2_CID_BAND_FILTER:
320 ctrl->value = sn9c102_i2c_read(cam, 0x2d);
321 if (ctrl->value < 0)
322 return -EIO;
323 ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
324 break;
325 default:
326 return -EINVAL;
327 }
328
329 return err ? -EIO : 0;
330}
331
332
333static int ov7630_set_ctrl(struct sn9c102_device *cam,
334 const struct v4l2_control *ctrl)
335{
336 enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
337 int err = 0;
338
339 switch (ctrl->id) {
340 case V4L2_CID_EXPOSURE:
341 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
342 break;
343 case V4L2_CID_RED_BALANCE:
344 if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
345 err += sn9c102_write_reg(cam, ctrl->value, 0x05);
346 else
347 err += sn9c102_write_reg(cam, ctrl->value, 0x07);
348 break;
349 case V4L2_CID_BLUE_BALANCE:
350 err += sn9c102_write_reg(cam, ctrl->value, 0x06);
351 break;
352 case SN9C102_V4L2_CID_GREEN_BALANCE:
353 if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
354 err += sn9c102_write_reg(cam, ctrl->value, 0x07);
355 else
356 err += sn9c102_write_reg(cam, ctrl->value, 0x05);
357 break;
358 case V4L2_CID_GAIN:
359 err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
360 break;
361 case V4L2_CID_DO_WHITE_BALANCE:
362 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
363 break;
364 case V4L2_CID_WHITENESS:
365 err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
366 break;
367 case V4L2_CID_AUTOGAIN:
368 err += sn9c102_i2c_write(cam, 0x13, ctrl->value |
369 (ctrl->value << 1));
370 break;
371 case V4L2_CID_VFLIP:
372 err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
373 break;
374 case SN9C102_V4L2_CID_GAMMA:
375 err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2);
376 break;
377 case SN9C102_V4L2_CID_BAND_FILTER:
378 err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
379 break;
380 default:
381 return -EINVAL;
382 }
383
384 return err ? -EIO : 0;
385}
386
387
388static int ov7630_set_crop(struct sn9c102_device *cam,
389 const struct v4l2_rect *rect)
390{
391 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
392 int err = 0;
393 u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
394
395 switch (sn9c102_get_bridge(cam)) {
396 case BRIDGE_SN9C101:
397 case BRIDGE_SN9C102:
398 case BRIDGE_SN9C103:
399 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
400 break;
401 case BRIDGE_SN9C105:
402 case BRIDGE_SN9C120:
403 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
404 break;
405 default:
406 break;
407 }
408
409 err += sn9c102_write_reg(cam, h_start, 0x12);
410 err += sn9c102_write_reg(cam, v_start, 0x13);
411
412 return err;
413}
414
415
416static int ov7630_set_pix_format(struct sn9c102_device *cam,
417 const struct v4l2_pix_format *pix)
418{
419 int err = 0;
420
421 switch (sn9c102_get_bridge(cam)) {
422 case BRIDGE_SN9C101:
423 case BRIDGE_SN9C102:
424 case BRIDGE_SN9C103:
425 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8)
426 err += sn9c102_write_reg(cam, 0x50, 0x19);
427 else
428 err += sn9c102_write_reg(cam, 0x20, 0x19);
429 break;
430 case BRIDGE_SN9C105:
431 case BRIDGE_SN9C120:
432 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
433 err += sn9c102_write_reg(cam, 0xe5, 0x17);
434 err += sn9c102_i2c_write(cam, 0x11, 0x04);
435 } else {
436 err += sn9c102_write_reg(cam, 0xe2, 0x17);
437 err += sn9c102_i2c_write(cam, 0x11, 0x02);
438 }
439 break;
440 default:
441 break;
442 }
443
444 return err;
445}
446
447
448static const struct sn9c102_sensor ov7630 = {
449 .name = "OV7630",
450 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
451 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103 |
452 BRIDGE_SN9C105 | BRIDGE_SN9C120,
453 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
454 .frequency = SN9C102_I2C_100KHZ,
455 .interface = SN9C102_I2C_2WIRES,
456 .i2c_slave_id = 0x21,
457 .init = &ov7630_init,
458 .qctrl = {
459 {
460 .id = V4L2_CID_GAIN,
461 .type = V4L2_CTRL_TYPE_INTEGER,
462 .name = "global gain",
463 .minimum = 0x00,
464 .maximum = 0x3f,
465 .step = 0x01,
466 .default_value = 0x14,
467 .flags = 0,
468 },
469 {
470 .id = V4L2_CID_EXPOSURE,
471 .type = V4L2_CTRL_TYPE_INTEGER,
472 .name = "exposure",
473 .minimum = 0x00,
474 .maximum = 0xff,
475 .step = 0x01,
476 .default_value = 0x60,
477 .flags = 0,
478 },
479 {
480 .id = V4L2_CID_WHITENESS,
481 .type = V4L2_CTRL_TYPE_INTEGER,
482 .name = "white balance background: red",
483 .minimum = 0x00,
484 .maximum = 0x3f,
485 .step = 0x01,
486 .default_value = 0x20,
487 .flags = 0,
488 },
489 {
490 .id = V4L2_CID_DO_WHITE_BALANCE,
491 .type = V4L2_CTRL_TYPE_INTEGER,
492 .name = "white balance background: blue",
493 .minimum = 0x00,
494 .maximum = 0x3f,
495 .step = 0x01,
496 .default_value = 0x20,
497 .flags = 0,
498 },
499 {
500 .id = V4L2_CID_RED_BALANCE,
501 .type = V4L2_CTRL_TYPE_INTEGER,
502 .name = "red balance",
503 .minimum = 0x00,
504 .maximum = 0x7f,
505 .step = 0x01,
506 .default_value = 0x20,
507 .flags = 0,
508 },
509 {
510 .id = V4L2_CID_BLUE_BALANCE,
511 .type = V4L2_CTRL_TYPE_INTEGER,
512 .name = "blue balance",
513 .minimum = 0x00,
514 .maximum = 0x7f,
515 .step = 0x01,
516 .default_value = 0x20,
517 .flags = 0,
518 },
519 {
520 .id = V4L2_CID_AUTOGAIN,
521 .type = V4L2_CTRL_TYPE_BOOLEAN,
522 .name = "auto adjust",
523 .minimum = 0x00,
524 .maximum = 0x01,
525 .step = 0x01,
526 .default_value = 0x00,
527 .flags = 0,
528 },
529 {
530 .id = V4L2_CID_VFLIP,
531 .type = V4L2_CTRL_TYPE_BOOLEAN,
532 .name = "vertical flip",
533 .minimum = 0x00,
534 .maximum = 0x01,
535 .step = 0x01,
536 .default_value = 0x01,
537 .flags = 0,
538 },
539 {
540 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
541 .type = V4L2_CTRL_TYPE_INTEGER,
542 .name = "green balance",
543 .minimum = 0x00,
544 .maximum = 0x7f,
545 .step = 0x01,
546 .default_value = 0x20,
547 .flags = 0,
548 },
549 {
550 .id = SN9C102_V4L2_CID_BAND_FILTER,
551 .type = V4L2_CTRL_TYPE_BOOLEAN,
552 .name = "band filter",
553 .minimum = 0x00,
554 .maximum = 0x01,
555 .step = 0x01,
556 .default_value = 0x00,
557 .flags = 0,
558 },
559 {
560 .id = SN9C102_V4L2_CID_GAMMA,
561 .type = V4L2_CTRL_TYPE_BOOLEAN,
562 .name = "rgb gamma",
563 .minimum = 0x00,
564 .maximum = 0x01,
565 .step = 0x01,
566 .default_value = 0x00,
567 .flags = 0,
568 },
569 },
570 .get_ctrl = &ov7630_get_ctrl,
571 .set_ctrl = &ov7630_set_ctrl,
572 .cropcap = {
573 .bounds = {
574 .left = 0,
575 .top = 0,
576 .width = 640,
577 .height = 480,
578 },
579 .defrect = {
580 .left = 0,
581 .top = 0,
582 .width = 640,
583 .height = 480,
584 },
585 },
586 .set_crop = &ov7630_set_crop,
587 .pix_format = {
588 .width = 640,
589 .height = 480,
590 .pixelformat = V4L2_PIX_FMT_SN9C10X,
591 .priv = 8,
592 },
593 .set_pix_format = &ov7630_set_pix_format
594};
595
596
597int sn9c102_probe_ov7630(struct sn9c102_device *cam)
598{
599 int pid, ver, err = 0;
600
601 switch (sn9c102_get_bridge(cam)) {
602 case BRIDGE_SN9C101:
603 case BRIDGE_SN9C102:
604 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
605 {0x28, 0x17});
606 break;
607 case BRIDGE_SN9C103: /* do _not_ change anything! */
608 err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01},
609 {0x28, 0x17}, {0x44, 0x02});
610 pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
611 if (err || pid < 0) /* try a different initialization */
612 err += sn9c102_write_const_regs(cam, {0x01, 0x01},
613 {0x00, 0x01});
614 break;
615 case BRIDGE_SN9C105:
616 case BRIDGE_SN9C120:
617 err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
618 {0x29, 0x01}, {0x74, 0x02},
619 {0x0e, 0x01}, {0x44, 0x01});
620 break;
621 default:
622 break;
623 }
624
625 pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
626 ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b);
627 if (err || pid < 0 || ver < 0)
628 return -EIO;
629 if (pid != 0x76 || ver != 0x31)
630 return -ENODEV;
631 sn9c102_attach_sensor(cam, &ov7630);
632
633 return 0;
634}
diff --git a/drivers/staging/media/sn9c102/sn9c102_ov7660.c b/drivers/staging/media/sn9c102/sn9c102_ov7660.c
deleted file mode 100644
index ac07805d122e..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_ov7660.c
+++ /dev/null
@@ -1,546 +0,0 @@
1/***************************************************************************
2 * Plug-in for OV7660 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#include "sn9c102_devtable.h"
24
25
26static int ov7660_init(struct sn9c102_device *cam)
27{
28 int err = 0;
29
30 err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
31 {0x1a, 0x04}, {0x03, 0x10},
32 {0x08, 0x14}, {0x20, 0x17},
33 {0x8b, 0x18}, {0x00, 0x19},
34 {0x1d, 0x1a}, {0x10, 0x1b},
35 {0x02, 0x1c}, {0x03, 0x1d},
36 {0x0f, 0x1e}, {0x0c, 0x1f},
37 {0x00, 0x20}, {0x29, 0x21},
38 {0x40, 0x22}, {0x54, 0x23},
39 {0x66, 0x24}, {0x76, 0x25},
40 {0x85, 0x26}, {0x94, 0x27},
41 {0xa1, 0x28}, {0xae, 0x29},
42 {0xbb, 0x2a}, {0xc7, 0x2b},
43 {0xd3, 0x2c}, {0xde, 0x2d},
44 {0xea, 0x2e}, {0xf4, 0x2f},
45 {0xff, 0x30}, {0x00, 0x3f},
46 {0xc7, 0x40}, {0x01, 0x41},
47 {0x44, 0x42}, {0x00, 0x43},
48 {0x44, 0x44}, {0x00, 0x45},
49 {0x44, 0x46}, {0x00, 0x47},
50 {0xc7, 0x48}, {0x01, 0x49},
51 {0xc7, 0x4a}, {0x01, 0x4b},
52 {0xc7, 0x4c}, {0x01, 0x4d},
53 {0x44, 0x4e}, {0x00, 0x4f},
54 {0x44, 0x50}, {0x00, 0x51},
55 {0x44, 0x52}, {0x00, 0x53},
56 {0xc7, 0x54}, {0x01, 0x55},
57 {0xc7, 0x56}, {0x01, 0x57},
58 {0xc7, 0x58}, {0x01, 0x59},
59 {0x44, 0x5a}, {0x00, 0x5b},
60 {0x44, 0x5c}, {0x00, 0x5d},
61 {0x44, 0x5e}, {0x00, 0x5f},
62 {0xc7, 0x60}, {0x01, 0x61},
63 {0xc7, 0x62}, {0x01, 0x63},
64 {0xc7, 0x64}, {0x01, 0x65},
65 {0x44, 0x66}, {0x00, 0x67},
66 {0x44, 0x68}, {0x00, 0x69},
67 {0x44, 0x6a}, {0x00, 0x6b},
68 {0xc7, 0x6c}, {0x01, 0x6d},
69 {0xc7, 0x6e}, {0x01, 0x6f},
70 {0xc7, 0x70}, {0x01, 0x71},
71 {0x44, 0x72}, {0x00, 0x73},
72 {0x44, 0x74}, {0x00, 0x75},
73 {0x44, 0x76}, {0x00, 0x77},
74 {0xc7, 0x78}, {0x01, 0x79},
75 {0xc7, 0x7a}, {0x01, 0x7b},
76 {0xc7, 0x7c}, {0x01, 0x7d},
77 {0x44, 0x7e}, {0x00, 0x7f},
78 {0x14, 0x84}, {0x00, 0x85},
79 {0x27, 0x86}, {0x00, 0x87},
80 {0x07, 0x88}, {0x00, 0x89},
81 {0xec, 0x8a}, {0x0f, 0x8b},
82 {0xd8, 0x8c}, {0x0f, 0x8d},
83 {0x3d, 0x8e}, {0x00, 0x8f},
84 {0x3d, 0x90}, {0x00, 0x91},
85 {0xcd, 0x92}, {0x0f, 0x93},
86 {0xf7, 0x94}, {0x0f, 0x95},
87 {0x0c, 0x96}, {0x00, 0x97},
88 {0x00, 0x98}, {0x66, 0x99},
89 {0x05, 0x9a}, {0x00, 0x9b},
90 {0x04, 0x9c}, {0x00, 0x9d},
91 {0x08, 0x9e}, {0x00, 0x9f},
92 {0x2d, 0xc0}, {0x2d, 0xc1},
93 {0x3a, 0xc2}, {0x05, 0xc3},
94 {0x04, 0xc4}, {0x3f, 0xc5},
95 {0x00, 0xc6}, {0x00, 0xc7},
96 {0x50, 0xc8}, {0x3C, 0xc9},
97 {0x28, 0xca}, {0xd8, 0xcb},
98 {0x14, 0xcc}, {0xec, 0xcd},
99 {0x32, 0xce}, {0xdd, 0xcf},
100 {0x32, 0xd0}, {0xdd, 0xd1},
101 {0x6a, 0xd2}, {0x50, 0xd3},
102 {0x00, 0xd4}, {0x00, 0xd5},
103 {0x00, 0xd6});
104
105 err += sn9c102_i2c_write(cam, 0x12, 0x80);
106 err += sn9c102_i2c_write(cam, 0x11, 0x09);
107 err += sn9c102_i2c_write(cam, 0x00, 0x0A);
108 err += sn9c102_i2c_write(cam, 0x01, 0x80);
109 err += sn9c102_i2c_write(cam, 0x02, 0x80);
110 err += sn9c102_i2c_write(cam, 0x03, 0x00);
111 err += sn9c102_i2c_write(cam, 0x04, 0x00);
112 err += sn9c102_i2c_write(cam, 0x05, 0x08);
113 err += sn9c102_i2c_write(cam, 0x06, 0x0B);
114 err += sn9c102_i2c_write(cam, 0x07, 0x00);
115 err += sn9c102_i2c_write(cam, 0x08, 0x1C);
116 err += sn9c102_i2c_write(cam, 0x09, 0x01);
117 err += sn9c102_i2c_write(cam, 0x0A, 0x76);
118 err += sn9c102_i2c_write(cam, 0x0B, 0x60);
119 err += sn9c102_i2c_write(cam, 0x0C, 0x00);
120 err += sn9c102_i2c_write(cam, 0x0D, 0x08);
121 err += sn9c102_i2c_write(cam, 0x0E, 0x04);
122 err += sn9c102_i2c_write(cam, 0x0F, 0x6F);
123 err += sn9c102_i2c_write(cam, 0x10, 0x20);
124 err += sn9c102_i2c_write(cam, 0x11, 0x03);
125 err += sn9c102_i2c_write(cam, 0x12, 0x05);
126 err += sn9c102_i2c_write(cam, 0x13, 0xC7);
127 err += sn9c102_i2c_write(cam, 0x14, 0x2C);
128 err += sn9c102_i2c_write(cam, 0x15, 0x00);
129 err += sn9c102_i2c_write(cam, 0x16, 0x02);
130 err += sn9c102_i2c_write(cam, 0x17, 0x10);
131 err += sn9c102_i2c_write(cam, 0x18, 0x60);
132 err += sn9c102_i2c_write(cam, 0x19, 0x02);
133 err += sn9c102_i2c_write(cam, 0x1A, 0x7B);
134 err += sn9c102_i2c_write(cam, 0x1B, 0x02);
135 err += sn9c102_i2c_write(cam, 0x1C, 0x7F);
136 err += sn9c102_i2c_write(cam, 0x1D, 0xA2);
137 err += sn9c102_i2c_write(cam, 0x1E, 0x01);
138 err += sn9c102_i2c_write(cam, 0x1F, 0x0E);
139 err += sn9c102_i2c_write(cam, 0x20, 0x05);
140 err += sn9c102_i2c_write(cam, 0x21, 0x05);
141 err += sn9c102_i2c_write(cam, 0x22, 0x05);
142 err += sn9c102_i2c_write(cam, 0x23, 0x05);
143 err += sn9c102_i2c_write(cam, 0x24, 0x68);
144 err += sn9c102_i2c_write(cam, 0x25, 0x58);
145 err += sn9c102_i2c_write(cam, 0x26, 0xD4);
146 err += sn9c102_i2c_write(cam, 0x27, 0x80);
147 err += sn9c102_i2c_write(cam, 0x28, 0x80);
148 err += sn9c102_i2c_write(cam, 0x29, 0x30);
149 err += sn9c102_i2c_write(cam, 0x2A, 0x00);
150 err += sn9c102_i2c_write(cam, 0x2B, 0x00);
151 err += sn9c102_i2c_write(cam, 0x2C, 0x80);
152 err += sn9c102_i2c_write(cam, 0x2D, 0x00);
153 err += sn9c102_i2c_write(cam, 0x2E, 0x00);
154 err += sn9c102_i2c_write(cam, 0x2F, 0x0E);
155 err += sn9c102_i2c_write(cam, 0x30, 0x08);
156 err += sn9c102_i2c_write(cam, 0x31, 0x30);
157 err += sn9c102_i2c_write(cam, 0x32, 0xB4);
158 err += sn9c102_i2c_write(cam, 0x33, 0x00);
159 err += sn9c102_i2c_write(cam, 0x34, 0x07);
160 err += sn9c102_i2c_write(cam, 0x35, 0x84);
161 err += sn9c102_i2c_write(cam, 0x36, 0x00);
162 err += sn9c102_i2c_write(cam, 0x37, 0x0C);
163 err += sn9c102_i2c_write(cam, 0x38, 0x02);
164 err += sn9c102_i2c_write(cam, 0x39, 0x43);
165 err += sn9c102_i2c_write(cam, 0x3A, 0x00);
166 err += sn9c102_i2c_write(cam, 0x3B, 0x0A);
167 err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
168 err += sn9c102_i2c_write(cam, 0x3D, 0x99);
169 err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
170 err += sn9c102_i2c_write(cam, 0x3F, 0x41);
171 err += sn9c102_i2c_write(cam, 0x40, 0xC1);
172 err += sn9c102_i2c_write(cam, 0x41, 0x22);
173 err += sn9c102_i2c_write(cam, 0x42, 0x08);
174 err += sn9c102_i2c_write(cam, 0x43, 0xF0);
175 err += sn9c102_i2c_write(cam, 0x44, 0x10);
176 err += sn9c102_i2c_write(cam, 0x45, 0x78);
177 err += sn9c102_i2c_write(cam, 0x46, 0xA8);
178 err += sn9c102_i2c_write(cam, 0x47, 0x60);
179 err += sn9c102_i2c_write(cam, 0x48, 0x80);
180 err += sn9c102_i2c_write(cam, 0x49, 0x00);
181 err += sn9c102_i2c_write(cam, 0x4A, 0x00);
182 err += sn9c102_i2c_write(cam, 0x4B, 0x00);
183 err += sn9c102_i2c_write(cam, 0x4C, 0x00);
184 err += sn9c102_i2c_write(cam, 0x4D, 0x00);
185 err += sn9c102_i2c_write(cam, 0x4E, 0x00);
186 err += sn9c102_i2c_write(cam, 0x4F, 0x46);
187 err += sn9c102_i2c_write(cam, 0x50, 0x36);
188 err += sn9c102_i2c_write(cam, 0x51, 0x0F);
189 err += sn9c102_i2c_write(cam, 0x52, 0x17);
190 err += sn9c102_i2c_write(cam, 0x53, 0x7F);
191 err += sn9c102_i2c_write(cam, 0x54, 0x96);
192 err += sn9c102_i2c_write(cam, 0x55, 0x40);
193 err += sn9c102_i2c_write(cam, 0x56, 0x40);
194 err += sn9c102_i2c_write(cam, 0x57, 0x40);
195 err += sn9c102_i2c_write(cam, 0x58, 0x0F);
196 err += sn9c102_i2c_write(cam, 0x59, 0xBA);
197 err += sn9c102_i2c_write(cam, 0x5A, 0x9A);
198 err += sn9c102_i2c_write(cam, 0x5B, 0x22);
199 err += sn9c102_i2c_write(cam, 0x5C, 0xB9);
200 err += sn9c102_i2c_write(cam, 0x5D, 0x9B);
201 err += sn9c102_i2c_write(cam, 0x5E, 0x10);
202 err += sn9c102_i2c_write(cam, 0x5F, 0xF0);
203 err += sn9c102_i2c_write(cam, 0x60, 0x05);
204 err += sn9c102_i2c_write(cam, 0x61, 0x60);
205 err += sn9c102_i2c_write(cam, 0x62, 0x00);
206 err += sn9c102_i2c_write(cam, 0x63, 0x00);
207 err += sn9c102_i2c_write(cam, 0x64, 0x50);
208 err += sn9c102_i2c_write(cam, 0x65, 0x30);
209 err += sn9c102_i2c_write(cam, 0x66, 0x00);
210 err += sn9c102_i2c_write(cam, 0x67, 0x80);
211 err += sn9c102_i2c_write(cam, 0x68, 0x7A);
212 err += sn9c102_i2c_write(cam, 0x69, 0x90);
213 err += sn9c102_i2c_write(cam, 0x6A, 0x80);
214 err += sn9c102_i2c_write(cam, 0x6B, 0x0A);
215 err += sn9c102_i2c_write(cam, 0x6C, 0x30);
216 err += sn9c102_i2c_write(cam, 0x6D, 0x48);
217 err += sn9c102_i2c_write(cam, 0x6E, 0x80);
218 err += sn9c102_i2c_write(cam, 0x6F, 0x74);
219 err += sn9c102_i2c_write(cam, 0x70, 0x64);
220 err += sn9c102_i2c_write(cam, 0x71, 0x60);
221 err += sn9c102_i2c_write(cam, 0x72, 0x5C);
222 err += sn9c102_i2c_write(cam, 0x73, 0x58);
223 err += sn9c102_i2c_write(cam, 0x74, 0x54);
224 err += sn9c102_i2c_write(cam, 0x75, 0x4C);
225 err += sn9c102_i2c_write(cam, 0x76, 0x40);
226 err += sn9c102_i2c_write(cam, 0x77, 0x38);
227 err += sn9c102_i2c_write(cam, 0x78, 0x34);
228 err += sn9c102_i2c_write(cam, 0x79, 0x30);
229 err += sn9c102_i2c_write(cam, 0x7A, 0x2F);
230 err += sn9c102_i2c_write(cam, 0x7B, 0x2B);
231 err += sn9c102_i2c_write(cam, 0x7C, 0x03);
232 err += sn9c102_i2c_write(cam, 0x7D, 0x07);
233 err += sn9c102_i2c_write(cam, 0x7E, 0x17);
234 err += sn9c102_i2c_write(cam, 0x7F, 0x34);
235 err += sn9c102_i2c_write(cam, 0x80, 0x41);
236 err += sn9c102_i2c_write(cam, 0x81, 0x4D);
237 err += sn9c102_i2c_write(cam, 0x82, 0x58);
238 err += sn9c102_i2c_write(cam, 0x83, 0x63);
239 err += sn9c102_i2c_write(cam, 0x84, 0x6E);
240 err += sn9c102_i2c_write(cam, 0x85, 0x77);
241 err += sn9c102_i2c_write(cam, 0x86, 0x87);
242 err += sn9c102_i2c_write(cam, 0x87, 0x95);
243 err += sn9c102_i2c_write(cam, 0x88, 0xAF);
244 err += sn9c102_i2c_write(cam, 0x89, 0xC7);
245 err += sn9c102_i2c_write(cam, 0x8A, 0xDF);
246 err += sn9c102_i2c_write(cam, 0x8B, 0x99);
247 err += sn9c102_i2c_write(cam, 0x8C, 0x99);
248 err += sn9c102_i2c_write(cam, 0x8D, 0xCF);
249 err += sn9c102_i2c_write(cam, 0x8E, 0x20);
250 err += sn9c102_i2c_write(cam, 0x8F, 0x26);
251 err += sn9c102_i2c_write(cam, 0x90, 0x10);
252 err += sn9c102_i2c_write(cam, 0x91, 0x0C);
253 err += sn9c102_i2c_write(cam, 0x92, 0x25);
254 err += sn9c102_i2c_write(cam, 0x93, 0x00);
255 err += sn9c102_i2c_write(cam, 0x94, 0x50);
256 err += sn9c102_i2c_write(cam, 0x95, 0x50);
257 err += sn9c102_i2c_write(cam, 0x96, 0x00);
258 err += sn9c102_i2c_write(cam, 0x97, 0x01);
259 err += sn9c102_i2c_write(cam, 0x98, 0x10);
260 err += sn9c102_i2c_write(cam, 0x99, 0x40);
261 err += sn9c102_i2c_write(cam, 0x9A, 0x40);
262 err += sn9c102_i2c_write(cam, 0x9B, 0x20);
263 err += sn9c102_i2c_write(cam, 0x9C, 0x00);
264 err += sn9c102_i2c_write(cam, 0x9D, 0x99);
265 err += sn9c102_i2c_write(cam, 0x9E, 0x7F);
266 err += sn9c102_i2c_write(cam, 0x9F, 0x00);
267 err += sn9c102_i2c_write(cam, 0xA0, 0x00);
268 err += sn9c102_i2c_write(cam, 0xA1, 0x00);
269
270 return err;
271}
272
273
274static int ov7660_get_ctrl(struct sn9c102_device *cam,
275 struct v4l2_control *ctrl)
276{
277 int err = 0;
278
279 switch (ctrl->id) {
280 case V4L2_CID_EXPOSURE:
281 ctrl->value = sn9c102_i2c_read(cam, 0x10);
282 if (ctrl->value < 0)
283 return -EIO;
284 break;
285 case V4L2_CID_DO_WHITE_BALANCE:
286 ctrl->value = sn9c102_read_reg(cam, 0x02);
287 if (ctrl->value < 0)
288 return -EIO;
289 ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
290 break;
291 case V4L2_CID_RED_BALANCE:
292 ctrl->value = sn9c102_read_reg(cam, 0x05);
293 if (ctrl->value < 0)
294 return -EIO;
295 ctrl->value &= 0x7f;
296 break;
297 case V4L2_CID_BLUE_BALANCE:
298 ctrl->value = sn9c102_read_reg(cam, 0x06);
299 if (ctrl->value < 0)
300 return -EIO;
301 ctrl->value &= 0x7f;
302 break;
303 case SN9C102_V4L2_CID_GREEN_BALANCE:
304 ctrl->value = sn9c102_read_reg(cam, 0x07);
305 if (ctrl->value < 0)
306 return -EIO;
307 ctrl->value &= 0x7f;
308 break;
309 case SN9C102_V4L2_CID_BAND_FILTER:
310 ctrl->value = sn9c102_i2c_read(cam, 0x3b);
311 if (ctrl->value < 0)
312 return -EIO;
313 ctrl->value &= 0x08;
314 break;
315 case V4L2_CID_GAIN:
316 ctrl->value = sn9c102_i2c_read(cam, 0x00);
317 if (ctrl->value < 0)
318 return -EIO;
319 ctrl->value &= 0x1f;
320 break;
321 case V4L2_CID_AUTOGAIN:
322 ctrl->value = sn9c102_i2c_read(cam, 0x13);
323 if (ctrl->value < 0)
324 return -EIO;
325 ctrl->value &= 0x01;
326 break;
327 default:
328 return -EINVAL;
329 }
330
331 return err ? -EIO : 0;
332}
333
334
335static int ov7660_set_ctrl(struct sn9c102_device *cam,
336 const struct v4l2_control *ctrl)
337{
338 int err = 0;
339
340 switch (ctrl->id) {
341 case V4L2_CID_EXPOSURE:
342 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
343 break;
344 case V4L2_CID_DO_WHITE_BALANCE:
345 err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02);
346 break;
347 case V4L2_CID_RED_BALANCE:
348 err += sn9c102_write_reg(cam, ctrl->value, 0x05);
349 break;
350 case V4L2_CID_BLUE_BALANCE:
351 err += sn9c102_write_reg(cam, ctrl->value, 0x06);
352 break;
353 case SN9C102_V4L2_CID_GREEN_BALANCE:
354 err += sn9c102_write_reg(cam, ctrl->value, 0x07);
355 break;
356 case SN9C102_V4L2_CID_BAND_FILTER:
357 err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b);
358 break;
359 case V4L2_CID_GAIN:
360 err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value);
361 break;
362 case V4L2_CID_AUTOGAIN:
363 err += sn9c102_i2c_write(cam, 0x13, 0xc0 |
364 (ctrl->value * 0x07));
365 break;
366 default:
367 return -EINVAL;
368 }
369
370 return err ? -EIO : 0;
371}
372
373
374static int ov7660_set_crop(struct sn9c102_device *cam,
375 const struct v4l2_rect *rect)
376{
377 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
378 int err = 0;
379 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
380 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
381
382 err += sn9c102_write_reg(cam, h_start, 0x12);
383 err += sn9c102_write_reg(cam, v_start, 0x13);
384
385 return err;
386}
387
388
389static int ov7660_set_pix_format(struct sn9c102_device *cam,
390 const struct v4l2_pix_format *pix)
391{
392 int r0, err = 0;
393
394 r0 = sn9c102_pread_reg(cam, 0x01);
395
396 if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
397 err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
398 err += sn9c102_write_reg(cam, 0xa2, 0x17);
399 err += sn9c102_i2c_write(cam, 0x11, 0x00);
400 } else {
401 err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
402 err += sn9c102_write_reg(cam, 0xa2, 0x17);
403 err += sn9c102_i2c_write(cam, 0x11, 0x0d);
404 }
405
406 return err;
407}
408
409
410static const struct sn9c102_sensor ov7660 = {
411 .name = "OV7660",
412 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
413 .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
414 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
415 .frequency = SN9C102_I2C_100KHZ,
416 .interface = SN9C102_I2C_2WIRES,
417 .i2c_slave_id = 0x21,
418 .init = &ov7660_init,
419 .qctrl = {
420 {
421 .id = V4L2_CID_GAIN,
422 .type = V4L2_CTRL_TYPE_INTEGER,
423 .name = "global gain",
424 .minimum = 0x00,
425 .maximum = 0x1f,
426 .step = 0x01,
427 .default_value = 0x09,
428 .flags = 0,
429 },
430 {
431 .id = V4L2_CID_EXPOSURE,
432 .type = V4L2_CTRL_TYPE_INTEGER,
433 .name = "exposure",
434 .minimum = 0x00,
435 .maximum = 0xff,
436 .step = 0x01,
437 .default_value = 0x27,
438 .flags = 0,
439 },
440 {
441 .id = V4L2_CID_DO_WHITE_BALANCE,
442 .type = V4L2_CTRL_TYPE_BOOLEAN,
443 .name = "night mode",
444 .minimum = 0x00,
445 .maximum = 0x01,
446 .step = 0x01,
447 .default_value = 0x00,
448 .flags = 0,
449 },
450 {
451 .id = V4L2_CID_RED_BALANCE,
452 .type = V4L2_CTRL_TYPE_INTEGER,
453 .name = "red balance",
454 .minimum = 0x00,
455 .maximum = 0x7f,
456 .step = 0x01,
457 .default_value = 0x14,
458 .flags = 0,
459 },
460 {
461 .id = V4L2_CID_BLUE_BALANCE,
462 .type = V4L2_CTRL_TYPE_INTEGER,
463 .name = "blue balance",
464 .minimum = 0x00,
465 .maximum = 0x7f,
466 .step = 0x01,
467 .default_value = 0x14,
468 .flags = 0,
469 },
470 {
471 .id = V4L2_CID_AUTOGAIN,
472 .type = V4L2_CTRL_TYPE_BOOLEAN,
473 .name = "auto adjust",
474 .minimum = 0x00,
475 .maximum = 0x01,
476 .step = 0x01,
477 .default_value = 0x01,
478 .flags = 0,
479 },
480 {
481 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
482 .type = V4L2_CTRL_TYPE_INTEGER,
483 .name = "green balance",
484 .minimum = 0x00,
485 .maximum = 0x7f,
486 .step = 0x01,
487 .default_value = 0x14,
488 .flags = 0,
489 },
490 {
491 .id = SN9C102_V4L2_CID_BAND_FILTER,
492 .type = V4L2_CTRL_TYPE_BOOLEAN,
493 .name = "band filter",
494 .minimum = 0x00,
495 .maximum = 0x01,
496 .step = 0x01,
497 .default_value = 0x00,
498 .flags = 0,
499 },
500 },
501 .get_ctrl = &ov7660_get_ctrl,
502 .set_ctrl = &ov7660_set_ctrl,
503 .cropcap = {
504 .bounds = {
505 .left = 0,
506 .top = 0,
507 .width = 640,
508 .height = 480,
509 },
510 .defrect = {
511 .left = 0,
512 .top = 0,
513 .width = 640,
514 .height = 480,
515 },
516 },
517 .set_crop = &ov7660_set_crop,
518 .pix_format = {
519 .width = 640,
520 .height = 480,
521 .pixelformat = V4L2_PIX_FMT_JPEG,
522 .priv = 8,
523 },
524 .set_pix_format = &ov7660_set_pix_format
525};
526
527
528int sn9c102_probe_ov7660(struct sn9c102_device *cam)
529{
530 int pid, ver, err;
531
532 err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
533 {0x01, 0x01}, {0x00, 0x01},
534 {0x28, 0x17});
535
536 pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
537 ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b);
538 if (err || pid < 0 || ver < 0)
539 return -EIO;
540 if (pid != 0x76 || ver != 0x60)
541 return -ENODEV;
542
543 sn9c102_attach_sensor(cam, &ov7660);
544
545 return 0;
546}
diff --git a/drivers/staging/media/sn9c102/sn9c102_pas106b.c b/drivers/staging/media/sn9c102/sn9c102_pas106b.c
deleted file mode 100644
index 895931ecac48..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_pas106b.c
+++ /dev/null
@@ -1,308 +0,0 @@
1/***************************************************************************
2 * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004-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 <linux/delay.h>
23#include "sn9c102_sensor.h"
24#include "sn9c102_devtable.h"
25
26
27static int pas106b_init(struct sn9c102_device *cam)
28{
29 int err = 0;
30
31 err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
32 {0x00, 0x14}, {0x20, 0x17},
33 {0x20, 0x19}, {0x09, 0x18});
34
35 err += sn9c102_i2c_write(cam, 0x02, 0x0c);
36 err += sn9c102_i2c_write(cam, 0x05, 0x5a);
37 err += sn9c102_i2c_write(cam, 0x06, 0x88);
38 err += sn9c102_i2c_write(cam, 0x07, 0x80);
39 err += sn9c102_i2c_write(cam, 0x10, 0x06);
40 err += sn9c102_i2c_write(cam, 0x11, 0x06);
41 err += sn9c102_i2c_write(cam, 0x12, 0x00);
42 err += sn9c102_i2c_write(cam, 0x14, 0x02);
43 err += sn9c102_i2c_write(cam, 0x13, 0x01);
44
45 msleep(400);
46
47 return err;
48}
49
50
51static int pas106b_get_ctrl(struct sn9c102_device *cam,
52 struct v4l2_control *ctrl)
53{
54 switch (ctrl->id) {
55 case V4L2_CID_EXPOSURE:
56 {
57 int r1 = sn9c102_i2c_read(cam, 0x03),
58 r2 = sn9c102_i2c_read(cam, 0x04);
59 if (r1 < 0 || r2 < 0)
60 return -EIO;
61 ctrl->value = (r1 << 4) | (r2 & 0x0f);
62 }
63 return 0;
64 case V4L2_CID_RED_BALANCE:
65 ctrl->value = sn9c102_i2c_read(cam, 0x0c);
66 if (ctrl->value < 0)
67 return -EIO;
68 ctrl->value &= 0x1f;
69 return 0;
70 case V4L2_CID_BLUE_BALANCE:
71 ctrl->value = sn9c102_i2c_read(cam, 0x09);
72 if (ctrl->value < 0)
73 return -EIO;
74 ctrl->value &= 0x1f;
75 return 0;
76 case V4L2_CID_GAIN:
77 ctrl->value = sn9c102_i2c_read(cam, 0x0e);
78 if (ctrl->value < 0)
79 return -EIO;
80 ctrl->value &= 0x1f;
81 return 0;
82 case V4L2_CID_CONTRAST:
83 ctrl->value = sn9c102_i2c_read(cam, 0x0f);
84 if (ctrl->value < 0)
85 return -EIO;
86 ctrl->value &= 0x07;
87 return 0;
88 case SN9C102_V4L2_CID_GREEN_BALANCE:
89 ctrl->value = sn9c102_i2c_read(cam, 0x0a);
90 if (ctrl->value < 0)
91 return -EIO;
92 ctrl->value = (ctrl->value & 0x1f) << 1;
93 return 0;
94 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
95 ctrl->value = sn9c102_i2c_read(cam, 0x08);
96 if (ctrl->value < 0)
97 return -EIO;
98 ctrl->value &= 0xf8;
99 return 0;
100 default:
101 return -EINVAL;
102 }
103}
104
105
106static int pas106b_set_ctrl(struct sn9c102_device *cam,
107 const struct v4l2_control *ctrl)
108{
109 int err = 0;
110
111 switch (ctrl->id) {
112 case V4L2_CID_EXPOSURE:
113 err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4);
114 err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f);
115 break;
116 case V4L2_CID_RED_BALANCE:
117 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
118 break;
119 case V4L2_CID_BLUE_BALANCE:
120 err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
121 break;
122 case V4L2_CID_GAIN:
123 err += sn9c102_i2c_write(cam, 0x0e, ctrl->value);
124 break;
125 case V4L2_CID_CONTRAST:
126 err += sn9c102_i2c_write(cam, 0x0f, ctrl->value);
127 break;
128 case SN9C102_V4L2_CID_GREEN_BALANCE:
129 err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1);
130 err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1);
131 break;
132 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
133 err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3);
134 break;
135 default:
136 return -EINVAL;
137 }
138 err += sn9c102_i2c_write(cam, 0x13, 0x01);
139
140 return err ? -EIO : 0;
141}
142
143
144static int pas106b_set_crop(struct sn9c102_device *cam,
145 const struct v4l2_rect *rect)
146{
147 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
148 int err = 0;
149 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
150 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
151
152 err += sn9c102_write_reg(cam, h_start, 0x12);
153 err += sn9c102_write_reg(cam, v_start, 0x13);
154
155 return err;
156}
157
158
159static int pas106b_set_pix_format(struct sn9c102_device *cam,
160 const struct v4l2_pix_format *pix)
161{
162 int err = 0;
163
164 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
165 err += sn9c102_write_reg(cam, 0x2c, 0x17);
166 else
167 err += sn9c102_write_reg(cam, 0x20, 0x17);
168
169 return err;
170}
171
172
173static const struct sn9c102_sensor pas106b = {
174 .name = "PAS106B",
175 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
176 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
177 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
178 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
179 .interface = SN9C102_I2C_2WIRES,
180 .i2c_slave_id = 0x40,
181 .init = &pas106b_init,
182 .qctrl = {
183 {
184 .id = V4L2_CID_EXPOSURE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "exposure",
187 .minimum = 0x125,
188 .maximum = 0xfff,
189 .step = 0x001,
190 .default_value = 0x140,
191 .flags = 0,
192 },
193 {
194 .id = V4L2_CID_GAIN,
195 .type = V4L2_CTRL_TYPE_INTEGER,
196 .name = "global gain",
197 .minimum = 0x00,
198 .maximum = 0x1f,
199 .step = 0x01,
200 .default_value = 0x0d,
201 .flags = 0,
202 },
203 {
204 .id = V4L2_CID_CONTRAST,
205 .type = V4L2_CTRL_TYPE_INTEGER,
206 .name = "contrast",
207 .minimum = 0x00,
208 .maximum = 0x07,
209 .step = 0x01,
210 .default_value = 0x00, /* 0x00~0x03 have same effect */
211 .flags = 0,
212 },
213 {
214 .id = V4L2_CID_RED_BALANCE,
215 .type = V4L2_CTRL_TYPE_INTEGER,
216 .name = "red balance",
217 .minimum = 0x00,
218 .maximum = 0x1f,
219 .step = 0x01,
220 .default_value = 0x04,
221 .flags = 0,
222 },
223 {
224 .id = V4L2_CID_BLUE_BALANCE,
225 .type = V4L2_CTRL_TYPE_INTEGER,
226 .name = "blue balance",
227 .minimum = 0x00,
228 .maximum = 0x1f,
229 .step = 0x01,
230 .default_value = 0x06,
231 .flags = 0,
232 },
233 {
234 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
235 .type = V4L2_CTRL_TYPE_INTEGER,
236 .name = "green balance",
237 .minimum = 0x00,
238 .maximum = 0x3e,
239 .step = 0x02,
240 .default_value = 0x02,
241 .flags = 0,
242 },
243 {
244 .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
245 .type = V4L2_CTRL_TYPE_INTEGER,
246 .name = "DAC magnitude",
247 .minimum = 0x00,
248 .maximum = 0x1f,
249 .step = 0x01,
250 .default_value = 0x01,
251 .flags = 0,
252 },
253 },
254 .get_ctrl = &pas106b_get_ctrl,
255 .set_ctrl = &pas106b_set_ctrl,
256 .cropcap = {
257 .bounds = {
258 .left = 0,
259 .top = 0,
260 .width = 352,
261 .height = 288,
262 },
263 .defrect = {
264 .left = 0,
265 .top = 0,
266 .width = 352,
267 .height = 288,
268 },
269 },
270 .set_crop = &pas106b_set_crop,
271 .pix_format = {
272 .width = 352,
273 .height = 288,
274 .pixelformat = V4L2_PIX_FMT_SBGGR8,
275 .priv = 8, /* we use this field as 'bits per pixel' */
276 },
277 .set_pix_format = &pas106b_set_pix_format
278};
279
280
281int sn9c102_probe_pas106b(struct sn9c102_device *cam)
282{
283 int r0 = 0, r1 = 0;
284 unsigned int pid = 0;
285
286 /*
287 Minimal initialization to enable the I2C communication
288 NOTE: do NOT change the values!
289 */
290 if (sn9c102_write_const_regs(cam,
291 {0x01, 0x01}, /* sensor power down */
292 {0x00, 0x01}, /* sensor power on */
293 {0x28, 0x17})) /* sensor clock at 24 MHz */
294 return -EIO;
295
296 r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00);
297 r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01);
298 if (r0 < 0 || r1 < 0)
299 return -EIO;
300
301 pid = (r0 << 11) | ((r1 & 0xf0) >> 4);
302 if (pid != 0x007)
303 return -ENODEV;
304
305 sn9c102_attach_sensor(cam, &pas106b);
306
307 return 0;
308}
diff --git a/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c b/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c
deleted file mode 100644
index f9e31ae2ad9f..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c
+++ /dev/null
@@ -1,340 +0,0 @@
1/***************************************************************************
2 * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio *
6 * <medaglia@undl.org.br> *
7 * *
8 * Support for SN9C103, DAC Magnitude, exposure and green gain controls *
9 * added by Luca Risolia <luca.risolia@studio.unibo.it> *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the Free Software *
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
24 ***************************************************************************/
25
26#include <linux/delay.h>
27#include "sn9c102_sensor.h"
28#include "sn9c102_devtable.h"
29
30
31static int pas202bcb_init(struct sn9c102_device *cam)
32{
33 int err = 0;
34
35 switch (sn9c102_get_bridge(cam)) {
36 case BRIDGE_SN9C101:
37 case BRIDGE_SN9C102:
38 err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
39 {0x00, 0x14}, {0x20, 0x17},
40 {0x30, 0x19}, {0x09, 0x18});
41 break;
42 case BRIDGE_SN9C103:
43 err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
44 {0x1a, 0x04}, {0x20, 0x05},
45 {0x20, 0x06}, {0x20, 0x07},
46 {0x00, 0x10}, {0x00, 0x11},
47 {0x00, 0x14}, {0x20, 0x17},
48 {0x30, 0x19}, {0x09, 0x18},
49 {0x02, 0x1c}, {0x03, 0x1d},
50 {0x0f, 0x1e}, {0x0c, 0x1f},
51 {0x00, 0x20}, {0x10, 0x21},
52 {0x20, 0x22}, {0x30, 0x23},
53 {0x40, 0x24}, {0x50, 0x25},
54 {0x60, 0x26}, {0x70, 0x27},
55 {0x80, 0x28}, {0x90, 0x29},
56 {0xa0, 0x2a}, {0xb0, 0x2b},
57 {0xc0, 0x2c}, {0xd0, 0x2d},
58 {0xe0, 0x2e}, {0xf0, 0x2f},
59 {0xff, 0x30});
60 break;
61 default:
62 break;
63 }
64
65 err += sn9c102_i2c_write(cam, 0x02, 0x14);
66 err += sn9c102_i2c_write(cam, 0x03, 0x40);
67 err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
68 err += sn9c102_i2c_write(cam, 0x0e, 0x01);
69 err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
70 err += sn9c102_i2c_write(cam, 0x10, 0x08);
71 err += sn9c102_i2c_write(cam, 0x13, 0x63);
72 err += sn9c102_i2c_write(cam, 0x15, 0x70);
73 err += sn9c102_i2c_write(cam, 0x11, 0x01);
74
75 msleep(400);
76
77 return err;
78}
79
80
81static int pas202bcb_get_ctrl(struct sn9c102_device *cam,
82 struct v4l2_control *ctrl)
83{
84 switch (ctrl->id) {
85 case V4L2_CID_EXPOSURE:
86 {
87 int r1 = sn9c102_i2c_read(cam, 0x04),
88 r2 = sn9c102_i2c_read(cam, 0x05);
89 if (r1 < 0 || r2 < 0)
90 return -EIO;
91 ctrl->value = (r1 << 6) | (r2 & 0x3f);
92 }
93 return 0;
94 case V4L2_CID_RED_BALANCE:
95 ctrl->value = sn9c102_i2c_read(cam, 0x09);
96 if (ctrl->value < 0)
97 return -EIO;
98 ctrl->value &= 0x0f;
99 return 0;
100 case V4L2_CID_BLUE_BALANCE:
101 ctrl->value = sn9c102_i2c_read(cam, 0x07);
102 if (ctrl->value < 0)
103 return -EIO;
104 ctrl->value &= 0x0f;
105 return 0;
106 case V4L2_CID_GAIN:
107 ctrl->value = sn9c102_i2c_read(cam, 0x10);
108 if (ctrl->value < 0)
109 return -EIO;
110 ctrl->value &= 0x1f;
111 return 0;
112 case SN9C102_V4L2_CID_GREEN_BALANCE:
113 ctrl->value = sn9c102_i2c_read(cam, 0x08);
114 if (ctrl->value < 0)
115 return -EIO;
116 ctrl->value &= 0x0f;
117 return 0;
118 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
119 ctrl->value = sn9c102_i2c_read(cam, 0x0c);
120 if (ctrl->value < 0)
121 return -EIO;
122 return 0;
123 default:
124 return -EINVAL;
125 }
126}
127
128
129static int pas202bcb_set_pix_format(struct sn9c102_device *cam,
130 const struct v4l2_pix_format *pix)
131{
132 int err = 0;
133
134 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
135 err += sn9c102_write_reg(cam, 0x28, 0x17);
136 else
137 err += sn9c102_write_reg(cam, 0x20, 0x17);
138
139 return err;
140}
141
142
143static int pas202bcb_set_ctrl(struct sn9c102_device *cam,
144 const struct v4l2_control *ctrl)
145{
146 int err = 0;
147
148 switch (ctrl->id) {
149 case V4L2_CID_EXPOSURE:
150 err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
151 err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
152 break;
153 case V4L2_CID_RED_BALANCE:
154 err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
155 break;
156 case V4L2_CID_BLUE_BALANCE:
157 err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
158 break;
159 case V4L2_CID_GAIN:
160 err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
161 break;
162 case SN9C102_V4L2_CID_GREEN_BALANCE:
163 err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
164 break;
165 case SN9C102_V4L2_CID_DAC_MAGNITUDE:
166 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
167 break;
168 default:
169 return -EINVAL;
170 }
171 err += sn9c102_i2c_write(cam, 0x11, 0x01);
172
173 return err ? -EIO : 0;
174}
175
176
177static int pas202bcb_set_crop(struct sn9c102_device *cam,
178 const struct v4l2_rect *rect)
179{
180 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
181 int err = 0;
182 u8 h_start = 0,
183 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
184
185 switch (sn9c102_get_bridge(cam)) {
186 case BRIDGE_SN9C101:
187 case BRIDGE_SN9C102:
188 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
189 break;
190 case BRIDGE_SN9C103:
191 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3;
192 break;
193 default:
194 break;
195 }
196
197 err += sn9c102_write_reg(cam, h_start, 0x12);
198 err += sn9c102_write_reg(cam, v_start, 0x13);
199
200 return err;
201}
202
203
204static const struct sn9c102_sensor pas202bcb = {
205 .name = "PAS202BCB",
206 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
207 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
208 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
209 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
210 .interface = SN9C102_I2C_2WIRES,
211 .i2c_slave_id = 0x40,
212 .init = &pas202bcb_init,
213 .qctrl = {
214 {
215 .id = V4L2_CID_EXPOSURE,
216 .type = V4L2_CTRL_TYPE_INTEGER,
217 .name = "exposure",
218 .minimum = 0x01e5,
219 .maximum = 0x3fff,
220 .step = 0x0001,
221 .default_value = 0x01e5,
222 .flags = 0,
223 },
224 {
225 .id = V4L2_CID_GAIN,
226 .type = V4L2_CTRL_TYPE_INTEGER,
227 .name = "global gain",
228 .minimum = 0x00,
229 .maximum = 0x1f,
230 .step = 0x01,
231 .default_value = 0x0b,
232 .flags = 0,
233 },
234 {
235 .id = V4L2_CID_RED_BALANCE,
236 .type = V4L2_CTRL_TYPE_INTEGER,
237 .name = "red balance",
238 .minimum = 0x00,
239 .maximum = 0x0f,
240 .step = 0x01,
241 .default_value = 0x00,
242 .flags = 0,
243 },
244 {
245 .id = V4L2_CID_BLUE_BALANCE,
246 .type = V4L2_CTRL_TYPE_INTEGER,
247 .name = "blue balance",
248 .minimum = 0x00,
249 .maximum = 0x0f,
250 .step = 0x01,
251 .default_value = 0x05,
252 .flags = 0,
253 },
254 {
255 .id = SN9C102_V4L2_CID_GREEN_BALANCE,
256 .type = V4L2_CTRL_TYPE_INTEGER,
257 .name = "green balance",
258 .minimum = 0x00,
259 .maximum = 0x0f,
260 .step = 0x01,
261 .default_value = 0x00,
262 .flags = 0,
263 },
264 {
265 .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
266 .type = V4L2_CTRL_TYPE_INTEGER,
267 .name = "DAC magnitude",
268 .minimum = 0x00,
269 .maximum = 0xff,
270 .step = 0x01,
271 .default_value = 0x04,
272 .flags = 0,
273 },
274 },
275 .get_ctrl = &pas202bcb_get_ctrl,
276 .set_ctrl = &pas202bcb_set_ctrl,
277 .cropcap = {
278 .bounds = {
279 .left = 0,
280 .top = 0,
281 .width = 640,
282 .height = 480,
283 },
284 .defrect = {
285 .left = 0,
286 .top = 0,
287 .width = 640,
288 .height = 480,
289 },
290 },
291 .set_crop = &pas202bcb_set_crop,
292 .pix_format = {
293 .width = 640,
294 .height = 480,
295 .pixelformat = V4L2_PIX_FMT_SBGGR8,
296 .priv = 8,
297 },
298 .set_pix_format = &pas202bcb_set_pix_format
299};
300
301
302int sn9c102_probe_pas202bcb(struct sn9c102_device *cam)
303{
304 int r0 = 0, r1 = 0, err = 0;
305 unsigned int pid = 0;
306
307 /*
308 * Minimal initialization to enable the I2C communication
309 * NOTE: do NOT change the values!
310 */
311 switch (sn9c102_get_bridge(cam)) {
312 case BRIDGE_SN9C101:
313 case BRIDGE_SN9C102:
314 err = sn9c102_write_const_regs(cam,
315 {0x01, 0x01}, /* power down */
316 {0x40, 0x01}, /* power on */
317 {0x28, 0x17});/* clock 24 MHz */
318 break;
319 case BRIDGE_SN9C103: /* do _not_ change anything! */
320 err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01},
321 {0x44, 0x02}, {0x29, 0x17});
322 break;
323 default:
324 break;
325 }
326
327 r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
328 r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
329
330 if (err || r0 < 0 || r1 < 0)
331 return -EIO;
332
333 pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
334 if (pid != 0x017)
335 return -ENODEV;
336
337 sn9c102_attach_sensor(cam, &pas202bcb);
338
339 return 0;
340}
diff --git a/drivers/staging/media/sn9c102/sn9c102_sensor.h b/drivers/staging/media/sn9c102/sn9c102_sensor.h
deleted file mode 100644
index 9f59c815d48b..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_sensor.h
+++ /dev/null
@@ -1,307 +0,0 @@
1/***************************************************************************
2 * API for image sensors connected to the SN9C1xx PC Camera Controllers *
3 * *
4 * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 ***************************************************************************/
20
21#ifndef _SN9C102_SENSOR_H_
22#define _SN9C102_SENSOR_H_
23
24#include <linux/usb.h>
25#include <linux/videodev2.h>
26#include <linux/device.h>
27#include <linux/stddef.h>
28#include <linux/errno.h>
29#include <asm/types.h>
30
31struct sn9c102_device;
32struct sn9c102_sensor;
33
34/*****************************************************************************/
35
36/*
37 OVERVIEW.
38 This is a small interface that allows you to add support for any CCD/CMOS
39 image sensors connected to the SN9C1XX bridges. The entire API is documented
40 below. In the most general case, to support a sensor there are three steps
41 you have to follow:
42 1) define the main "sn9c102_sensor" structure by setting the basic fields;
43 2) write a probing function to be called by the core module when the USB
44 camera is recognized, then add both the USB ids and the name of that
45 function to the two corresponding tables in sn9c102_devtable.h;
46 3) implement the methods that you want/need (and fill the rest of the main
47 structure accordingly).
48 "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
49 NOT need to touch the source code of the core module for the things to work
50 properly, unless you find bugs or flaws in it. Finally, do not forget to
51 read the V4L2 API for completeness.
52*/
53
54/*****************************************************************************/
55
56enum sn9c102_bridge {
57 BRIDGE_SN9C101 = 0x01,
58 BRIDGE_SN9C102 = 0x02,
59 BRIDGE_SN9C103 = 0x04,
60 BRIDGE_SN9C105 = 0x08,
61 BRIDGE_SN9C120 = 0x10,
62};
63
64/* Return the bridge name */
65enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device *cam);
66
67/* Return a pointer the sensor struct attached to the camera */
68struct sn9c102_sensor *sn9c102_get_sensor(struct sn9c102_device *cam);
69
70/* Identify a device */
71extern struct sn9c102_device*
72sn9c102_match_id(struct sn9c102_device *cam, const struct usb_device_id *id);
73
74/* Attach a probed sensor to the camera. */
75extern void
76sn9c102_attach_sensor(struct sn9c102_device *cam,
77 const struct sn9c102_sensor *sensor);
78
79/*
80 Read/write routines: they always return -1 on error, 0 or the read value
81 otherwise. NOTE that a real read operation is not supported by the SN9C1XX
82 chip for some of its registers. To work around this problem, a pseudo-read
83 call is provided instead: it returns the last successfully written value
84 on the register (0 if it has never been written), the usual -1 on error.
85*/
86
87/* The "try" I2C I/O versions are used when probing the sensor */
88extern int sn9c102_i2c_try_read(struct sn9c102_device*,
89 const struct sn9c102_sensor*, u8 address);
90
91/*
92 These must be used if and only if the sensor doesn't implement the standard
93 I2C protocol. There are a number of good reasons why you must use the
94 single-byte versions of these functions: do not abuse. The first function
95 writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX
96 chip. The second one programs the registers 0x09 and 0x10 with data0 and
97 data1, and places the n bytes read from the sensor register table in the
98 buffer pointed by 'buffer'. Both the functions return -1 on error; the write
99 version returns 0 on success, while the read version returns the first read
100 byte.
101*/
102extern int sn9c102_i2c_try_raw_write(struct sn9c102_device *cam,
103 const struct sn9c102_sensor *sensor, u8 n,
104 u8 data0, u8 data1, u8 data2, u8 data3,
105 u8 data4, u8 data5);
106extern int sn9c102_i2c_try_raw_read(struct sn9c102_device *cam,
107 const struct sn9c102_sensor *sensor,
108 u8 data0, u8 data1, u8 n, u8 buffer[]);
109
110/* To be used after the sensor struct has been attached to the camera struct */
111extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
112extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
113
114/* I/O on registers in the bridge. Could be used by the sensor methods too */
115extern int sn9c102_read_reg(struct sn9c102_device*, u16 index);
116extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
117extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
118extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
119 int count);
120/*
121 Write multiple registers with constant values. For example:
122 sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
123 Register addresses must be < 256.
124*/
125#define sn9c102_write_const_regs(sn9c102_device, data...) \
126 ({ static const u8 _valreg[][2] = {data}; \
127 sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); })
128
129/*****************************************************************************/
130
131enum sn9c102_i2c_sysfs_ops {
132 SN9C102_I2C_READ = 0x01,
133 SN9C102_I2C_WRITE = 0x02,
134};
135
136enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */
137 SN9C102_I2C_100KHZ = 0x01,
138 SN9C102_I2C_400KHZ = 0x02,
139};
140
141enum sn9c102_i2c_interface {
142 SN9C102_I2C_2WIRES,
143 SN9C102_I2C_3WIRES,
144};
145
146#define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
147
148struct sn9c102_sensor {
149 char name[32], /* sensor name */
150 maintainer[64]; /* name of the maintainer <email> */
151
152 enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */
153
154 /* Supported operations through the 'sysfs' interface */
155 enum sn9c102_i2c_sysfs_ops sysfs_ops;
156
157 /*
158 These sensor capabilities must be provided if the SN9C1XX controller
159 needs to communicate through the sensor serial interface by using
160 at least one of the i2c functions available.
161 */
162 enum sn9c102_i2c_frequency frequency;
163 enum sn9c102_i2c_interface interface;
164
165 /*
166 This identifier must be provided if the image sensor implements
167 the standard I2C protocol.
168 */
169 u8 i2c_slave_id; /* reg. 0x09 */
170
171 /*
172 NOTE: Where not noted,most of the functions below are not mandatory.
173 Set to null if you do not implement them. If implemented,
174 they must return 0 on success, the proper error otherwise.
175 */
176
177 int (*init)(struct sn9c102_device *cam);
178 /*
179 This function will be called after the sensor has been attached.
180 It should be used to initialize the sensor only, but may also
181 configure part of the SN9C1XX chip if necessary. You don't need to
182 setup picture settings like brightness, contrast, etc.. here, if
183 the corresponding controls are implemented (see below), since
184 they are adjusted in the core driver by calling the set_ctrl()
185 method after init(), where the arguments are the default values
186 specified in the v4l2_queryctrl list of supported controls;
187 Same suggestions apply for other settings, _if_ the corresponding
188 methods are present; if not, the initialization must configure the
189 sensor according to the default configuration structures below.
190 */
191
192 struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS];
193 /*
194 Optional list of default controls, defined as indicated in the
195 V4L2 API. Menu type controls are not handled by this interface.
196 */
197
198 int (*get_ctrl)(struct sn9c102_device *cam, struct v4l2_control *ctrl);
199 int (*set_ctrl)(struct sn9c102_device *cam,
200 const struct v4l2_control *ctrl);
201 /*
202 You must implement at least the set_ctrl method if you have defined
203 the list above. The returned value must follow the V4L2
204 specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER
205 are not supported by this driver, so do not implement them. Also,
206 you don't have to check whether the passed values are out of bounds,
207 given that this is done by the core module.
208 */
209
210 struct v4l2_cropcap cropcap;
211 /*
212 Think the image sensor as a grid of R,G,B monochromatic pixels
213 disposed according to a particular Bayer pattern, which describes
214 the complete array of pixels, from (0,0) to (xmax, ymax). We will
215 use this coordinate system from now on. It is assumed the sensor
216 chip can be programmed to capture/transmit a subsection of that
217 array of pixels: we will call this subsection "active window".
218 It is not always true that the largest achievable active window can
219 cover the whole array of pixels. The V4L2 API defines another
220 area called "source rectangle", which, in turn, is a subrectangle of
221 the active window. The SN9C1XX chip is always programmed to read the
222 source rectangle.
223 The bounds of both the active window and the source rectangle are
224 specified in the cropcap substructures 'bounds' and 'defrect'.
225 By default, the source rectangle should cover the largest possible
226 area. Again, it is not always true that the largest source rectangle
227 can cover the entire active window, although it is a rare case for
228 the hardware we have. The bounds of the source rectangle _must_ be
229 multiple of 16 and must use the same coordinate system as indicated
230 before; their centers shall align initially.
231 If necessary, the sensor chip must be initialized during init() to
232 set the bounds of the active sensor window; however, by default, it
233 usually covers the largest achievable area (maxwidth x maxheight)
234 of pixels, so no particular initialization is needed, if you have
235 defined the correct default bounds in the structures.
236 See the V4L2 API for further details.
237 NOTE: once you have defined the bounds of the active window
238 (struct cropcap.bounds) you must not change them.anymore.
239 Only 'bounds' and 'defrect' fields are mandatory, other fields
240 will be ignored.
241 */
242
243 int (*set_crop)(struct sn9c102_device *cam,
244 const struct v4l2_rect *rect);
245 /*
246 To be called on VIDIOC_C_SETCROP. The core module always calls a
247 default routine which configures the appropriate SN9C1XX regs (also
248 scaling), but you may need to override/adjust specific stuff.
249 'rect' contains width and height values that are multiple of 16: in
250 case you override the default function, you always have to program
251 the chip to match those values; on error return the corresponding
252 error code without rolling back.
253 NOTE: in case, you must program the SN9C1XX chip to get rid of
254 blank pixels or blank lines at the _start_ of each line or
255 frame after each HSYNC or VSYNC, so that the image starts with
256 real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
257 V_SIZE you don't have to care about blank pixels or blank
258 lines at the end of each line or frame).
259 */
260
261 struct v4l2_pix_format pix_format;
262 /*
263 What you have to define here are: 1) initial 'width' and 'height' of
264 the target rectangle 2) the initial 'pixelformat', which can be
265 either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video)
266 or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate
267 the number of bits per pixel for uncompressed video, 8 or 9 (despite
268 the current value of 'pixelformat').
269 NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
270 of cropcap.defrect.width and cropcap.defrect.height. I
271 suggest 1/1.
272 NOTE 2: The initial compression quality is defined by the first bit
273 of reg 0x17 during the initialization of the image sensor.
274 NOTE 3: as said above, you have to program the SN9C1XX chip to get
275 rid of any blank pixels, so that the output of the sensor
276 matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
277 */
278
279 int (*set_pix_format)(struct sn9c102_device *cam,
280 const struct v4l2_pix_format *pix);
281 /*
282 To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to
283 SN9C10X pixel format or viceversa. On error return the corresponding
284 error code without rolling back.
285 */
286
287 /*
288 Do NOT write to the data below, it's READ ONLY. It is used by the
289 core module to store successfully updated values of the above
290 settings, for rollbacks..etc..in case of errors during atomic I/O
291 */
292 struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS];
293 struct v4l2_rect _rect;
294};
295
296/*****************************************************************************/
297
298/* Private ioctl's for control settings supported by some image sensors */
299#define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0)
300#define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1)
301#define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2)
302#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3)
303#define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4)
304#define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5)
305#define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6)
306
307#endif /* _SN9C102_SENSOR_H_ */
diff --git a/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c b/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c
deleted file mode 100644
index 6a00b626d347..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c
+++ /dev/null
@@ -1,154 +0,0 @@
1/***************************************************************************
2 * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004-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#include "sn9c102_devtable.h"
24
25
26static int tas5110c1b_init(struct sn9c102_device *cam)
27{
28 int err = 0;
29
30 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x44, 0x01},
31 {0x00, 0x10}, {0x00, 0x11},
32 {0x0a, 0x14}, {0x60, 0x17},
33 {0x06, 0x18}, {0xfb, 0x19});
34
35 err += sn9c102_i2c_write(cam, 0xc0, 0x80);
36
37 return err;
38}
39
40
41static int tas5110c1b_set_ctrl(struct sn9c102_device *cam,
42 const struct v4l2_control *ctrl)
43{
44 int err = 0;
45
46 switch (ctrl->id) {
47 case V4L2_CID_GAIN:
48 err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
49 break;
50 default:
51 return -EINVAL;
52 }
53
54 return err ? -EIO : 0;
55}
56
57
58static int tas5110c1b_set_crop(struct sn9c102_device *cam,
59 const struct v4l2_rect *rect)
60{
61 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
62 int err = 0;
63 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
64 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
65
66 err += sn9c102_write_reg(cam, h_start, 0x12);
67 err += sn9c102_write_reg(cam, v_start, 0x13);
68
69 /* Don't change ! */
70 err += sn9c102_write_reg(cam, 0x14, 0x1a);
71 err += sn9c102_write_reg(cam, 0x0a, 0x1b);
72 err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
73
74 return err;
75}
76
77
78static int tas5110c1b_set_pix_format(struct sn9c102_device *cam,
79 const struct v4l2_pix_format *pix)
80{
81 int err = 0;
82
83 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
84 err += sn9c102_write_reg(cam, 0x2b, 0x19);
85 else
86 err += sn9c102_write_reg(cam, 0xfb, 0x19);
87
88 return err;
89}
90
91
92static const struct sn9c102_sensor tas5110c1b = {
93 .name = "TAS5110C1B",
94 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
95 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
96 .sysfs_ops = SN9C102_I2C_WRITE,
97 .frequency = SN9C102_I2C_100KHZ,
98 .interface = SN9C102_I2C_3WIRES,
99 .init = &tas5110c1b_init,
100 .qctrl = {
101 {
102 .id = V4L2_CID_GAIN,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "global gain",
105 .minimum = 0x00,
106 .maximum = 0xf6,
107 .step = 0x01,
108 .default_value = 0x40,
109 .flags = 0,
110 },
111 },
112 .set_ctrl = &tas5110c1b_set_ctrl,
113 .cropcap = {
114 .bounds = {
115 .left = 0,
116 .top = 0,
117 .width = 352,
118 .height = 288,
119 },
120 .defrect = {
121 .left = 0,
122 .top = 0,
123 .width = 352,
124 .height = 288,
125 },
126 },
127 .set_crop = &tas5110c1b_set_crop,
128 .pix_format = {
129 .width = 352,
130 .height = 288,
131 .pixelformat = V4L2_PIX_FMT_SBGGR8,
132 .priv = 8,
133 },
134 .set_pix_format = &tas5110c1b_set_pix_format
135};
136
137
138int sn9c102_probe_tas5110c1b(struct sn9c102_device *cam)
139{
140 const struct usb_device_id tas5110c1b_id_table[] = {
141 { USB_DEVICE(0x0c45, 0x6001), },
142 { USB_DEVICE(0x0c45, 0x6005), },
143 { USB_DEVICE(0x0c45, 0x60ab), },
144 { }
145 };
146
147 /* Sensor detection is based on USB pid/vid */
148 if (!sn9c102_match_id(cam, tas5110c1b_id_table))
149 return -ENODEV;
150
151 sn9c102_attach_sensor(cam, &tas5110c1b);
152
153 return 0;
154}
diff --git a/drivers/staging/media/sn9c102/sn9c102_tas5110d.c b/drivers/staging/media/sn9c102/sn9c102_tas5110d.c
deleted file mode 100644
index eefbf8670c3e..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_tas5110d.c
+++ /dev/null
@@ -1,119 +0,0 @@
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#include "sn9c102_devtable.h"
24
25
26static int tas5110d_init(struct sn9c102_device *cam)
27{
28 int err;
29
30 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x04, 0x01},
31 {0x0a, 0x14}, {0x60, 0x17},
32 {0x06, 0x18}, {0xfb, 0x19});
33
34 err += sn9c102_i2c_write(cam, 0x9a, 0xca);
35
36 return err;
37}
38
39
40static int tas5110d_set_crop(struct sn9c102_device *cam,
41 const struct v4l2_rect *rect)
42{
43 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
44 int err = 0;
45 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
46 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
47
48 err += sn9c102_write_reg(cam, h_start, 0x12);
49 err += sn9c102_write_reg(cam, v_start, 0x13);
50
51 err += sn9c102_write_reg(cam, 0x14, 0x1a);
52 err += sn9c102_write_reg(cam, 0x0a, 0x1b);
53
54 return err;
55}
56
57
58static int tas5110d_set_pix_format(struct sn9c102_device *cam,
59 const struct v4l2_pix_format *pix)
60{
61 int err = 0;
62
63 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
64 err += sn9c102_write_reg(cam, 0x3b, 0x19);
65 else
66 err += sn9c102_write_reg(cam, 0xfb, 0x19);
67
68 return err;
69}
70
71
72static const struct sn9c102_sensor tas5110d = {
73 .name = "TAS5110D",
74 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
75 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
76 .sysfs_ops = SN9C102_I2C_WRITE,
77 .frequency = SN9C102_I2C_100KHZ,
78 .interface = SN9C102_I2C_2WIRES,
79 .i2c_slave_id = 0x61,
80 .init = &tas5110d_init,
81 .cropcap = {
82 .bounds = {
83 .left = 0,
84 .top = 0,
85 .width = 352,
86 .height = 288,
87 },
88 .defrect = {
89 .left = 0,
90 .top = 0,
91 .width = 352,
92 .height = 288,
93 },
94 },
95 .set_crop = &tas5110d_set_crop,
96 .pix_format = {
97 .width = 352,
98 .height = 288,
99 .pixelformat = V4L2_PIX_FMT_SBGGR8,
100 .priv = 8,
101 },
102 .set_pix_format = &tas5110d_set_pix_format
103};
104
105
106int sn9c102_probe_tas5110d(struct sn9c102_device *cam)
107{
108 const struct usb_device_id tas5110d_id_table[] = {
109 { USB_DEVICE(0x0c45, 0x6007), },
110 { }
111 };
112
113 if (!sn9c102_match_id(cam, tas5110d_id_table))
114 return -ENODEV;
115
116 sn9c102_attach_sensor(cam, &tas5110d);
117
118 return 0;
119}
diff --git a/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c b/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c
deleted file mode 100644
index 725de857de45..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c
+++ /dev/null
@@ -1,165 +0,0 @@
1/***************************************************************************
2 * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera *
3 * Controllers *
4 * *
5 * Copyright (C) 2004-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#include "sn9c102_devtable.h"
24
25
26static int tas5130d1b_init(struct sn9c102_device *cam)
27{
28 int err;
29
30 err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x20, 0x17},
31 {0x04, 0x01}, {0x01, 0x10},
32 {0x00, 0x11}, {0x00, 0x14},
33 {0x60, 0x17}, {0x07, 0x18});
34
35 return err;
36}
37
38
39static int tas5130d1b_set_ctrl(struct sn9c102_device *cam,
40 const struct v4l2_control *ctrl)
41{
42 int err = 0;
43
44 switch (ctrl->id) {
45 case V4L2_CID_GAIN:
46 err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
47 break;
48 case V4L2_CID_EXPOSURE:
49 err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value);
50 break;
51 default:
52 return -EINVAL;
53 }
54
55 return err ? -EIO : 0;
56}
57
58
59static int tas5130d1b_set_crop(struct sn9c102_device *cam,
60 const struct v4l2_rect *rect)
61{
62 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
63 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
64 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
65 int err = 0;
66
67 err += sn9c102_write_reg(cam, h_start, 0x12);
68 err += sn9c102_write_reg(cam, v_start, 0x13);
69
70 /* Do NOT change! */
71 err += sn9c102_write_reg(cam, 0x1f, 0x1a);
72 err += sn9c102_write_reg(cam, 0x1a, 0x1b);
73 err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
74
75 return err;
76}
77
78
79static int tas5130d1b_set_pix_format(struct sn9c102_device *cam,
80 const struct v4l2_pix_format *pix)
81{
82 int err = 0;
83
84 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
85 err += sn9c102_write_reg(cam, 0x63, 0x19);
86 else
87 err += sn9c102_write_reg(cam, 0xf3, 0x19);
88
89 return err;
90}
91
92
93static const struct sn9c102_sensor tas5130d1b = {
94 .name = "TAS5130D1B",
95 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
96 .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
97 .sysfs_ops = SN9C102_I2C_WRITE,
98 .frequency = SN9C102_I2C_100KHZ,
99 .interface = SN9C102_I2C_3WIRES,
100 .init = &tas5130d1b_init,
101 .qctrl = {
102 {
103 .id = V4L2_CID_GAIN,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "global gain",
106 .minimum = 0x00,
107 .maximum = 0xf6,
108 .step = 0x02,
109 .default_value = 0x00,
110 .flags = 0,
111 },
112 {
113 .id = V4L2_CID_EXPOSURE,
114 .type = V4L2_CTRL_TYPE_INTEGER,
115 .name = "exposure",
116 .minimum = 0x00,
117 .maximum = 0x47,
118 .step = 0x01,
119 .default_value = 0x00,
120 .flags = 0,
121 },
122 },
123 .set_ctrl = &tas5130d1b_set_ctrl,
124 .cropcap = {
125 .bounds = {
126 .left = 0,
127 .top = 0,
128 .width = 640,
129 .height = 480,
130 },
131 .defrect = {
132 .left = 0,
133 .top = 0,
134 .width = 640,
135 .height = 480,
136 },
137 },
138 .set_crop = &tas5130d1b_set_crop,
139 .pix_format = {
140 .width = 640,
141 .height = 480,
142 .pixelformat = V4L2_PIX_FMT_SBGGR8,
143 .priv = 8,
144 },
145 .set_pix_format = &tas5130d1b_set_pix_format
146};
147
148
149int sn9c102_probe_tas5130d1b(struct sn9c102_device *cam)
150{
151 const struct usb_device_id tas5130d1b_id_table[] = {
152 { USB_DEVICE(0x0c45, 0x6024), },
153 { USB_DEVICE(0x0c45, 0x6025), },
154 { USB_DEVICE(0x0c45, 0x60aa), },
155 { }
156 };
157
158 /* Sensor detection is based on USB pid/vid */
159 if (!sn9c102_match_id(cam, tas5130d1b_id_table))
160 return -ENODEV;
161
162 sn9c102_attach_sensor(cam, &tas5130d1b);
163
164 return 0;
165}