aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/video4linux/sn9c102.txt1
-rw-r--r--drivers/media/video/sn9c102/Makefile1
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c4
-rw-r--r--drivers/media/video/sn9c102/sn9c102_devtable.h2
-rw-r--r--drivers/media/video/sn9c102/sn9c102_mt9v111.c259
5 files changed, 265 insertions, 2 deletions
diff --git a/Documentation/video4linux/sn9c102.txt b/Documentation/video4linux/sn9c102.txt
index 1ffad19ce891..b26f5195af51 100644
--- a/Documentation/video4linux/sn9c102.txt
+++ b/Documentation/video4linux/sn9c102.txt
@@ -568,6 +568,7 @@ the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'.
568Many thanks to following persons for their contribute (listed in alphabetical 568Many thanks to following persons for their contribute (listed in alphabetical
569order): 569order):
570 570
571- David Anderson for the donation of a webcam;
571- Luca Capello for the donation of a webcam; 572- Luca Capello for the donation of a webcam;
572- Philippe Coval for having helped testing the PAS202BCA image sensor; 573- Philippe Coval for having helped testing the PAS202BCA image sensor;
573- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the 574- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile
index a56d16f69c71..7ecd5a90c7c9 100644
--- a/drivers/media/video/sn9c102/Makefile
+++ b/drivers/media/video/sn9c102/Makefile
@@ -3,6 +3,7 @@ sn9c102-objs := sn9c102_core.o \
3 sn9c102_hv7131r.o \ 3 sn9c102_hv7131r.o \
4 sn9c102_mi0343.o \ 4 sn9c102_mi0343.o \
5 sn9c102_mi0360.o \ 5 sn9c102_mi0360.o \
6 sn9c102_mt9v111.o \
6 sn9c102_ov7630.o \ 7 sn9c102_ov7630.o \
7 sn9c102_ov7660.o \ 8 sn9c102_ov7660.o \
8 sn9c102_pas106b.o \ 9 sn9c102_pas106b.o \
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 511847912c48..c40ba3adab21 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -47,7 +47,7 @@
47#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia" 47#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
48#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" 48#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
49#define SN9C102_MODULE_LICENSE "GPL" 49#define SN9C102_MODULE_LICENSE "GPL"
50#define SN9C102_MODULE_VERSION "1:1.47" 50#define SN9C102_MODULE_VERSION "1:1.47pre49"
51#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 47) 51#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 47)
52 52
53/*****************************************************************************/ 53/*****************************************************************************/
@@ -3322,7 +3322,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3322 cam->v4ldev->fops = &sn9c102_fops; 3322 cam->v4ldev->fops = &sn9c102_fops;
3323 cam->v4ldev->minor = video_nr[dev_nr]; 3323 cam->v4ldev->minor = video_nr[dev_nr];
3324 cam->v4ldev->release = video_device_release; 3324 cam->v4ldev->release = video_device_release;
3325 video_set_drvdata(cam->v4ldev, cam);
3326 3325
3327 init_completion(&cam->probe); 3326 init_completion(&cam->probe);
3328 3327
@@ -3340,6 +3339,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3340 3339
3341 DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); 3340 DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
3342 3341
3342 video_set_drvdata(cam->v4ldev, cam);
3343 cam->module_param.force_munmap = force_munmap[dev_nr]; 3343 cam->module_param.force_munmap = force_munmap[dev_nr];
3344 cam->module_param.frame_timeout = frame_timeout[dev_nr]; 3344 cam->module_param.frame_timeout = frame_timeout[dev_nr];
3345 3345
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
index 916054faf9be..35223e0d7e49 100644
--- a/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -126,6 +126,7 @@ extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
126extern int sn9c102_probe_hv7131r(struct sn9c102_device* cam); 126extern int sn9c102_probe_hv7131r(struct sn9c102_device* cam);
127extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); 127extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
128extern int sn9c102_probe_mi0360(struct sn9c102_device* cam); 128extern int sn9c102_probe_mi0360(struct sn9c102_device* cam);
129extern int sn9c102_probe_mt9v111(struct sn9c102_device *cam);
129extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); 130extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
130extern int sn9c102_probe_ov7660(struct sn9c102_device* cam); 131extern int sn9c102_probe_ov7660(struct sn9c102_device* cam);
131extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); 132extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
@@ -144,6 +145,7 @@ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
144 &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ 145 &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
145 &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ 146 &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
146 &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ 147 &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
148 &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
147 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ 149 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
148 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ 150 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
149 &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ 151 &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
diff --git a/drivers/media/video/sn9c102/sn9c102_mt9v111.c b/drivers/media/video/sn9c102/sn9c102_mt9v111.c
new file mode 100644
index 000000000000..3b98ac3bbc38
--- /dev/null
+++ b/drivers/media/video/sn9c102/sn9c102_mt9v111.c
@@ -0,0 +1,259 @@
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
24
25static int mt9v111_init(struct sn9c102_device *cam)
26{
27 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
28 int err = 0;
29
30 err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
31 {0x00, 0x03}, {0x1a, 0x04},
32 {0x1f, 0x05}, {0x20, 0x06},
33 {0x1f, 0x07}, {0x81, 0x08},
34 {0x5c, 0x09}, {0x00, 0x0a},
35 {0x00, 0x0b}, {0x00, 0x0c},
36 {0x00, 0x0d}, {0x00, 0x0e},
37 {0x00, 0x0f}, {0x03, 0x10},
38 {0x00, 0x11}, {0x00, 0x12},
39 {0x02, 0x13}, {0x14, 0x14},
40 {0x28, 0x15}, {0x1e, 0x16},
41 {0xe2, 0x17}, {0x06, 0x18},
42 {0x00, 0x19}, {0x00, 0x1a},
43 {0x00, 0x1b}, {0x08, 0x20},
44 {0x39, 0x21}, {0x51, 0x22},
45 {0x63, 0x23}, {0x73, 0x24},
46 {0x82, 0x25}, {0x8f, 0x26},
47 {0x9b, 0x27}, {0xa7, 0x28},
48 {0xb1, 0x29}, {0xbc, 0x2a},
49 {0xc6, 0x2b}, {0xcf, 0x2c},
50 {0xd8, 0x2d}, {0xe1, 0x2e},
51 {0xea, 0x2f}, {0xf2, 0x30},
52 {0x13, 0x84}, {0x00, 0x85},
53 {0x25, 0x86}, {0x00, 0x87},
54 {0x07, 0x88}, {0x00, 0x89},
55 {0xee, 0x8a}, {0x0f, 0x8b},
56 {0xe5, 0x8c}, {0x0f, 0x8d},
57 {0x2e, 0x8e}, {0x00, 0x8f},
58 {0x30, 0x90}, {0x00, 0x91},
59 {0xd4, 0x92}, {0x0f, 0x93},
60 {0xfc, 0x94}, {0x0f, 0x95},
61 {0x14, 0x96}, {0x00, 0x97},
62 {0x00, 0x98}, {0x60, 0x99},
63 {0x07, 0x9a}, {0x40, 0x9b},
64 {0x20, 0x9c}, {0x00, 0x9d},
65 {0x00, 0x9e}, {0x00, 0x9f},
66 {0x2d, 0xc0}, {0x2d, 0xc1},
67 {0x3a, 0xc2}, {0x05, 0xc3},
68 {0x04, 0xc4}, {0x3f, 0xc5},
69 {0x00, 0xc6}, {0x00, 0xc7},
70 {0x50, 0xc8}, {0x3c, 0xc9},
71 {0x28, 0xca}, {0xd8, 0xcb},
72 {0x14, 0xcc}, {0xec, 0xcd},
73 {0x32, 0xce}, {0xdd, 0xcf},
74 {0x2d, 0xd0}, {0xdd, 0xd1},
75 {0x6a, 0xd2}, {0x50, 0xd3},
76 {0x60, 0xd4}, {0x00, 0xd5},
77 {0x00, 0xd6});
78
79 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
80 0x00, 0x01, 0, 0);
81 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
82 0x00, 0x01, 0, 0);
83 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
84 0x00, 0x00, 0, 0);
85 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
86 0x04, 0x80, 0, 0);
87 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
88 0x00, 0x04, 0, 0);
89 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
90 0x00, 0x08, 0, 0);
91 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x02,
92 0x00, 0x16, 0, 0);
93 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
94 0x01, 0xe7, 0, 0);
95 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
96 0x02, 0x87, 0, 0);
97 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
98 0x00, 0x40, 0, 0);
99 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
100 0x00, 0x09, 0, 0);
101 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x07,
102 0x30, 0x02, 0, 0);
103 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0c,
104 0x00, 0x00, 0, 0);
105 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x12,
106 0x00, 0xb0, 0, 0);
107 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x13,
108 0x00, 0x7c, 0, 0);
109 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x1e,
110 0x00, 0x00, 0, 0);
111 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
112 0x00, 0x00, 0, 0);
113 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
114 0x00, 0x00, 0, 0);
115 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
116 0x00, 0x04, 0, 0);
117
118 return err;
119}
120
121static int mt9v111_get_ctrl(struct sn9c102_device *cam,
122 struct v4l2_control *ctrl)
123{
124 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
125 u8 data[2];
126 int err = 0;
127
128 switch (ctrl->id) {
129 case V4L2_CID_VFLIP:
130 if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
131 data) < 0)
132 return -EIO;
133 ctrl->value = data[1] & 0x80 ? 1 : 0;
134 return 0;
135 default:
136 return -EINVAL;
137 }
138
139 return err ? -EIO : 0;
140}
141
142static int mt9v111_set_ctrl(struct sn9c102_device *cam,
143 const struct v4l2_control *ctrl)
144{
145 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
146 int err = 0;
147
148 switch (ctrl->id) {
149 case V4L2_CID_VFLIP:
150 err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
151 0x20,
152 ctrl->value ? 0x80 : 0x00,
153 ctrl->value ? 0x80 : 0x00, 0,
154 0);
155 break;
156 default:
157 return -EINVAL;
158 }
159
160 return err ? -EIO : 0;
161}
162
163static int mt9v111_set_crop(struct sn9c102_device *cam,
164 const struct v4l2_rect *rect)
165{
166 struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
167 int err = 0;
168 u8 v_start = (u8) (rect->top - s->cropcap.bounds.top) + 2;
169
170 err += sn9c102_write_reg(cam, v_start, 0x13);
171
172 return err;
173}
174
175static int mt9v111_set_pix_format(struct sn9c102_device *cam,
176 const struct v4l2_pix_format *pix)
177{
178 int err = 0;
179
180 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
181 err += sn9c102_write_reg(cam, 0xb4, 0x17);
182 } else {
183 err += sn9c102_write_reg(cam, 0xe2, 0x17);
184 }
185
186 return err;
187}
188
189
190static const struct sn9c102_sensor mt9v111 = {
191 .name = "MT9V111",
192 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
193 .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
194 .frequency = SN9C102_I2C_100KHZ,
195 .interface = SN9C102_I2C_2WIRES,
196 .i2c_slave_id = 0x5c,
197 .init = &mt9v111_init,
198 .qctrl = {
199 {
200 .id = V4L2_CID_VFLIP,
201 .type = V4L2_CTRL_TYPE_BOOLEAN,
202 .name = "vertical mirror",
203 .minimum = 0,
204 .maximum = 1,
205 .step = 1,
206 .default_value = 0,
207 .flags = 0,
208 },
209 },
210 .get_ctrl = &mt9v111_get_ctrl,
211 .set_ctrl = &mt9v111_set_ctrl,
212 .cropcap = {
213 .bounds = {
214 .left = 0,
215 .top = 0,
216 .width = 640,
217 .height = 480,
218 },
219 .defrect = {
220 .left = 0,
221 .top = 0,
222 .width = 640,
223 .height = 480,
224 },
225 },
226 .set_crop = &mt9v111_set_crop,
227 .pix_format = {
228 .width = 640,
229 .height = 480,
230 .pixelformat = V4L2_PIX_FMT_SBGGR8,
231 .priv = 8,
232 },
233 .set_pix_format = &mt9v111_set_pix_format
234};
235
236
237int sn9c102_probe_mt9v111(struct sn9c102_device *cam)
238{
239 u8 data[2];
240 int err = 0;
241
242 err += sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
243 {0x29, 0x01}, {0x42, 0x17},
244 {0x62, 0x17}, {0x08, 0x01});
245 err += sn9c102_i2c_try_raw_write(cam, &mt9v111, 4,
246 mt9v111.i2c_slave_id, 0x01, 0x00,
247 0x04, 0, 0);
248 if (err || sn9c102_i2c_try_raw_read(cam, &mt9v111,
249 mt9v111.i2c_slave_id, 0x36, 2,
250 data) < 0)
251 return -EIO;
252
253 if (data[0] != 0x82 || data[1] != 0x3a)
254 return -ENODEV;
255
256 sn9c102_attach_sensor(cam, &mt9v111);
257
258 return 0;
259}