Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (6591): Adds support for MT9V111 on sn9c102

Adds a new image sensor to the sn9c102 driver.

Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>

authored by

Luca Risolia and committed by
Mauro Carvalho Chehab
ddef2dcc 542794be

+265 -2
+1
Documentation/video4linux/sn9c102.txt
··· 568 568 Many thanks to following persons for their contribute (listed in alphabetical 569 569 order): 570 570 571 + - David Anderson for the donation of a webcam; 571 572 - Luca Capello for the donation of a webcam; 572 573 - Philippe Coval for having helped testing the PAS202BCA image sensor; 573 574 - Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
+1
drivers/media/video/sn9c102/Makefile
··· 3 3 sn9c102_hv7131r.o \ 4 4 sn9c102_mi0343.o \ 5 5 sn9c102_mi0360.o \ 6 + sn9c102_mt9v111.o \ 6 7 sn9c102_ov7630.o \ 7 8 sn9c102_ov7660.o \ 8 9 sn9c102_pas106b.o \
+2 -2
drivers/media/video/sn9c102/sn9c102_core.c
··· 47 47 #define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia" 48 48 #define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" 49 49 #define SN9C102_MODULE_LICENSE "GPL" 50 - #define SN9C102_MODULE_VERSION "1:1.47" 50 + #define SN9C102_MODULE_VERSION "1:1.47pre49" 51 51 #define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 47) 52 52 53 53 /*****************************************************************************/ ··· 3322 3322 cam->v4ldev->fops = &sn9c102_fops; 3323 3323 cam->v4ldev->minor = video_nr[dev_nr]; 3324 3324 cam->v4ldev->release = video_device_release; 3325 - video_set_drvdata(cam->v4ldev, cam); 3326 3325 3327 3326 init_completion(&cam->probe); 3328 3327 ··· 3339 3340 3340 3341 DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); 3341 3342 3343 + video_set_drvdata(cam->v4ldev, cam); 3342 3344 cam->module_param.force_munmap = force_munmap[dev_nr]; 3343 3345 cam->module_param.frame_timeout = frame_timeout[dev_nr]; 3344 3346
+2
drivers/media/video/sn9c102/sn9c102_devtable.h
··· 126 126 extern int sn9c102_probe_hv7131r(struct sn9c102_device* cam); 127 127 extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); 128 128 extern int sn9c102_probe_mi0360(struct sn9c102_device* cam); 129 + extern int sn9c102_probe_mt9v111(struct sn9c102_device *cam); 129 130 extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); 130 131 extern int sn9c102_probe_ov7660(struct sn9c102_device* cam); 131 132 extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); ··· 145 144 &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ 146 145 &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ 147 146 &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ 147 + &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */ 148 148 &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ 149 149 &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ 150 150 &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
+259
drivers/media/video/sn9c102/sn9c102_mt9v111.c
··· 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 + 25 + static 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 + 121 + static 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 + 142 + static 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 + 163 + static 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 + 175 + static 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 + 190 + static 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 + 237 + int 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 + }