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

[media] gscpa_ov534_9: Add support for ov3610 sensor

Dear Hans de Goede, I have Ubuntu (raring) and recently bought digital
microscope eyepiece Lomo MD300. It is the same device as Future Optics MVV3000.
Unfortunately it does not work out of box. Moreover drivers refused to work
under Windows 7 as well leaving me only with Win Xp working system. I have had
no choice but to examine what happened in USB bus and attempt to reproduce the
sequence. So, i have download the source(3.8.0-30 kernel) and made required
changes to driver to make my hardware work.
I submit my changed files to you as maintainer of the driver so you can
integrade my changes into main stream. Thanx. Hopefully my Ubuntu will work
with my hardware out of box.
Sincerely yours Vladik Aranov

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>

authored by

Vladik Aranov and committed by
Mauro Carvalho Chehab
15807765 de0fc463

+333 -1
+333 -1
drivers/media/usb/gspca/ov534_9.c
··· 59 59 SENSOR_OV965x, /* ov9657 */ 60 60 SENSOR_OV971x, /* ov9712 */ 61 61 SENSOR_OV562x, /* ov5621 */ 62 + SENSOR_OV361x, /* ov3610 */ 62 63 NSENSORS 63 64 }; 64 65 ··· 105 104 .sizeimage = 2592 * 1680, 106 105 .colorspace = V4L2_COLORSPACE_SRGB 107 106 } 107 + }; 108 + 109 + enum ov361x { 110 + ov361x_2048 = 0, 111 + ov361x_1600, 112 + ov361x_1024, 113 + ov361x_640, 114 + ov361x_320, 115 + ov361x_160, 116 + ov361x_last 117 + }; 118 + 119 + static const struct v4l2_pix_format ov361x_mode[] = { 120 + {0x800, 0x600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 121 + .bytesperline = 0x800, 122 + .sizeimage = 0x800 * 0x600, 123 + .colorspace = V4L2_COLORSPACE_SRGB}, 124 + {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 125 + .bytesperline = 1600, 126 + .sizeimage = 1600 * 1200, 127 + .colorspace = V4L2_COLORSPACE_SRGB}, 128 + {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 129 + .bytesperline = 768, 130 + .sizeimage = 1024 * 768, 131 + .colorspace = V4L2_COLORSPACE_SRGB}, 132 + {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 133 + .bytesperline = 640, 134 + .sizeimage = 640 * 480, 135 + .colorspace = V4L2_COLORSPACE_SRGB}, 136 + {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 137 + .bytesperline = 320, 138 + .sizeimage = 320 * 240, 139 + .colorspace = V4L2_COLORSPACE_SRGB}, 140 + {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 141 + .bytesperline = 160, 142 + .sizeimage = 160 * 120, 143 + .colorspace = V4L2_COLORSPACE_SRGB} 144 + }; 145 + 146 + static const u8 ov361x_start_2048[][2] = { 147 + {0x12, 0x80}, 148 + {0x13, 0xcf}, 149 + {0x14, 0x40}, 150 + {0x15, 0x00}, 151 + {0x01, 0x80}, 152 + {0x02, 0x80}, 153 + {0x04, 0x70}, 154 + {0x0d, 0x40}, 155 + {0x0f, 0x47}, 156 + {0x11, 0x81}, 157 + {0x32, 0x36}, 158 + {0x33, 0x0c}, 159 + {0x34, 0x00}, 160 + {0x35, 0x90}, 161 + {0x12, 0x00}, 162 + {0x17, 0x10}, 163 + {0x18, 0x90}, 164 + {0x19, 0x00}, 165 + {0x1a, 0xc0}, 166 + }; 167 + static const u8 ov361x_bridge_start_2048[][2] = { 168 + {0xf1, 0x60}, 169 + {0x88, 0x00}, 170 + {0x89, 0x08}, 171 + {0x8a, 0x00}, 172 + {0x8b, 0x06}, 173 + {0x8c, 0x01}, 174 + {0x8d, 0x10}, 175 + {0x1c, 0x00}, 176 + {0x1d, 0x48}, 177 + {0x1d, 0x00}, 178 + {0x1d, 0xff}, 179 + {0x1c, 0x0a}, 180 + {0x1d, 0x2e}, 181 + {0x1d, 0x1e}, 182 + }; 183 + 184 + static const u8 ov361x_start_1600[][2] = { 185 + {0x12, 0x80}, 186 + {0x13, 0xcf}, 187 + {0x14, 0x40}, 188 + {0x15, 0x00}, 189 + {0x01, 0x80}, 190 + {0x02, 0x80}, 191 + {0x04, 0x70}, 192 + {0x0d, 0x40}, 193 + {0x0f, 0x47}, 194 + {0x11, 0x81}, 195 + {0x32, 0x36}, 196 + {0x33, 0x0C}, 197 + {0x34, 0x00}, 198 + {0x35, 0x90}, 199 + {0x12, 0x00}, 200 + {0x17, 0x10}, 201 + {0x18, 0x90}, 202 + {0x19, 0x00}, 203 + {0x1a, 0xc0}, 204 + }; 205 + static const u8 ov361x_bridge_start_1600[][2] = { 206 + {0xf1, 0x60}, /* Hsize[7:0] */ 207 + {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */ 208 + {0x89, 0x08}, /* Vsize[7:0] */ 209 + {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */ 210 + {0x8b, 0x06}, /* for Iso */ 211 + {0x8c, 0x01}, /* RAW input */ 212 + {0x8d, 0x10}, 213 + {0x1c, 0x00}, /* RAW output, Iso transfer */ 214 + {0x1d, 0x48}, 215 + {0x1d, 0x00}, 216 + {0x1d, 0xff}, 217 + {0x1c, 0x0a}, /* turn off JPEG, Iso mode */ 218 + {0x1d, 0x2e}, /* for Iso */ 219 + {0x1d, 0x1e}, 220 + }; 221 + 222 + static const u8 ov361x_start_1024[][2] = { 223 + {0x12, 0x80}, 224 + {0x13, 0xcf}, 225 + {0x14, 0x40}, 226 + {0x15, 0x00}, 227 + {0x01, 0x80}, 228 + {0x02, 0x80}, 229 + {0x04, 0x70}, 230 + {0x0d, 0x40}, 231 + {0x0f, 0x47}, 232 + {0x11, 0x81}, 233 + {0x32, 0x36}, 234 + {0x33, 0x0C}, 235 + {0x34, 0x00}, 236 + {0x35, 0x90}, 237 + {0x12, 0x40}, 238 + {0x17, 0x1f}, 239 + {0x18, 0x5f}, 240 + {0x19, 0x00}, 241 + {0x1a, 0x68}, 242 + }; 243 + static const u8 ov361x_bridge_start_1024[][2] = { 244 + {0xf1, 0x60}, /* Hsize[7:0] */ 245 + {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */ 246 + {0x89, 0x04}, /* Vsize[7:0] */ 247 + {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */ 248 + {0x8b, 0x03}, /* for Iso */ 249 + {0x8c, 0x01}, /* RAW input */ 250 + {0x8d, 0x10}, 251 + {0x1c, 0x00}, /* RAW output, Iso transfer */ 252 + {0x1d, 0x48}, 253 + {0x1d, 0x00}, 254 + {0x1d, 0xff}, 255 + {0x1c, 0x0a}, /* turn off JPEG, Iso mode */ 256 + {0x1d, 0x2e}, /* for Iso */ 257 + {0x1d, 0x1e}, 258 + }; 259 + 260 + static const u8 ov361x_start_640[][2] = { 261 + {0x12, 0x80}, 262 + {0x13, 0xcf}, 263 + {0x14, 0x40}, 264 + {0x15, 0x00}, 265 + {0x01, 0x80}, 266 + {0x02, 0x80}, 267 + {0x04, 0x70}, 268 + {0x0d, 0x40}, 269 + {0x0f, 0x47}, 270 + {0x11, 0x81}, 271 + {0x32, 0x36}, 272 + {0x33, 0x0C}, 273 + {0x34, 0x00}, 274 + {0x35, 0x90}, 275 + {0x12, 0x40}, 276 + {0x17, 0x1f}, 277 + {0x18, 0x5f}, 278 + {0x19, 0x00}, 279 + {0x1a, 0x68}, 280 + }; 281 + 282 + static const u8 ov361x_bridge_start_640[][2] = { 283 + {0xf1, 0x60}, /* Hsize[7:0]*/ 284 + {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */ 285 + {0x89, 0x04}, /* Vsize[7:0] */ 286 + {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */ 287 + {0x8b, 0x03}, /* for Iso */ 288 + {0x8c, 0x01}, /* RAW input */ 289 + {0x8d, 0x10}, 290 + {0x1c, 0x00}, /* RAW output, Iso transfer */ 291 + {0x1d, 0x48}, 292 + {0x1d, 0x00}, 293 + {0x1d, 0xff}, 294 + {0x1c, 0x0a}, /* turn off JPEG, Iso mode */ 295 + {0x1d, 0x2e}, /* for Iso */ 296 + {0x1d, 0x1e}, 297 + }; 298 + 299 + static const u8 ov361x_start_320[][2] = { 300 + {0x12, 0x80}, 301 + {0x13, 0xcf}, 302 + {0x14, 0x40}, 303 + {0x15, 0x00}, 304 + {0x01, 0x80}, 305 + {0x02, 0x80}, 306 + {0x04, 0x70}, 307 + {0x0d, 0x40}, 308 + {0x0f, 0x47}, 309 + {0x11, 0x81}, 310 + {0x32, 0x36}, 311 + {0x33, 0x0C}, 312 + {0x34, 0x00}, 313 + {0x35, 0x90}, 314 + {0x12, 0x40}, 315 + {0x17, 0x1f}, 316 + {0x18, 0x5f}, 317 + {0x19, 0x00}, 318 + {0x1a, 0x68}, 319 + }; 320 + 321 + static const u8 ov361x_bridge_start_320[][2] = { 322 + {0xf1, 0x60}, /* Hsize[7:0] */ 323 + {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */ 324 + {0x89, 0x04}, /* Vsize[7:0] */ 325 + {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */ 326 + {0x8b, 0x03}, /* for Iso */ 327 + {0x8c, 0x01}, /* RAW input */ 328 + {0x8d, 0x10}, 329 + {0x1c, 0x00}, /* RAW output, Iso transfer; */ 330 + {0x1d, 0x48}, 331 + {0x1d, 0x00}, 332 + {0x1d, 0xff}, 333 + {0x1c, 0x0a}, /* turn off JPEG, Iso mode */ 334 + {0x1d, 0x2e}, /* for Iso */ 335 + {0x1d, 0x1e}, 336 + }; 337 + 338 + static const u8 ov361x_start_160[][2] = { 339 + {0x12, 0x80}, 340 + {0x13, 0xcf}, 341 + {0x14, 0x40}, 342 + {0x15, 0x00}, 343 + {0x01, 0x80}, 344 + {0x02, 0x80}, 345 + {0x04, 0x70}, 346 + {0x0d, 0x40}, 347 + {0x0f, 0x47}, 348 + {0x11, 0x81}, 349 + {0x32, 0x36}, 350 + {0x33, 0x0C}, 351 + {0x34, 0x00}, 352 + {0x35, 0x90}, 353 + {0x12, 0x40}, 354 + {0x17, 0x1f}, 355 + {0x18, 0x5f}, 356 + {0x19, 0x00}, 357 + {0x1a, 0x68}, 358 + }; 359 + 360 + static const u8 ov361x_bridge_start_160[][2] = { 361 + {0xf1, 0x60}, /* Hsize[7:0] */ 362 + {0x88, 0x00}, /* Hsize[15:8] Write Only, can't read */ 363 + {0x89, 0x04}, /* Vsize[7:0] */ 364 + {0x8a, 0x00}, /* Vsize[15:8] Write Only, can't read */ 365 + {0x8b, 0x03}, /* for Iso */ 366 + {0x8c, 0x01}, /* RAW input */ 367 + {0x8d, 0x10}, 368 + {0x1c, 0x00}, /* RAW output, Iso transfer */ 369 + {0x1d, 0x48}, 370 + {0x1d, 0x00}, 371 + {0x1d, 0xff}, 372 + {0x1c, 0x0a}, /* turn off JPEG, Iso mode */ 373 + {0x1d, 0x2e}, /* for Iso */ 374 + {0x1d, 0x1e}, 108 375 }; 109 376 110 377 static const u8 bridge_init[][2] = { ··· 1167 898 int i; 1168 899 1169 900 for (i = 0; i < 5; i++) { 1170 - msleep(10); 901 + msleep(20); 1171 902 data = reg_r(gspca_dev, OV534_REG_STATUS); 1172 903 1173 904 switch (data) { ··· 1490 1221 sccb_w_array(gspca_dev, ov562x_init_2, 1491 1222 ARRAY_SIZE(ov562x_init_2)); 1492 1223 reg_w(gspca_dev, 0xe0, 0x00); 1224 + } else if ((sensor_id & 0xfff0) == 0x3610) { 1225 + sd->sensor = SENSOR_OV361x; 1226 + gspca_dev->cam.cam_mode = ov361x_mode; 1227 + gspca_dev->cam.nmodes = ARRAY_SIZE(ov361x_mode); 1228 + reg_w(gspca_dev, 0xe7, 0x3a); 1229 + reg_w(gspca_dev, 0xf1, 0x60); 1230 + sccb_write(gspca_dev, 0x12, 0x80); 1493 1231 } else { 1494 1232 pr_err("Unknown sensor %04x", sensor_id); 1495 1233 return -EINVAL; 1496 1234 } 1235 + 1236 + return gspca_dev->usb_err; 1237 + } 1238 + 1239 + static int sd_start_ov361x(struct gspca_dev *gspca_dev) 1240 + { 1241 + sccb_write(gspca_dev, 0x12, 0x80); 1242 + msleep(20); 1243 + switch (gspca_dev->curr_mode % (ov361x_last)) { 1244 + case ov361x_2048: 1245 + reg_w_array(gspca_dev, ov361x_bridge_start_2048, 1246 + ARRAY_SIZE(ov361x_bridge_start_2048)); 1247 + sccb_w_array(gspca_dev, ov361x_start_2048, 1248 + ARRAY_SIZE(ov361x_start_2048)); 1249 + break; 1250 + case ov361x_1600: 1251 + reg_w_array(gspca_dev, ov361x_bridge_start_1600, 1252 + ARRAY_SIZE(ov361x_bridge_start_1600)); 1253 + sccb_w_array(gspca_dev, ov361x_start_1600, 1254 + ARRAY_SIZE(ov361x_start_1600)); 1255 + break; 1256 + case ov361x_1024: 1257 + reg_w_array(gspca_dev, ov361x_bridge_start_1024, 1258 + ARRAY_SIZE(ov361x_bridge_start_1024)); 1259 + sccb_w_array(gspca_dev, ov361x_start_1024, 1260 + ARRAY_SIZE(ov361x_start_1024)); 1261 + break; 1262 + case ov361x_640: 1263 + reg_w_array(gspca_dev, ov361x_bridge_start_640, 1264 + ARRAY_SIZE(ov361x_bridge_start_640)); 1265 + sccb_w_array(gspca_dev, ov361x_start_640, 1266 + ARRAY_SIZE(ov361x_start_640)); 1267 + break; 1268 + case ov361x_320: 1269 + reg_w_array(gspca_dev, ov361x_bridge_start_320, 1270 + ARRAY_SIZE(ov361x_bridge_start_320)); 1271 + sccb_w_array(gspca_dev, ov361x_start_320, 1272 + ARRAY_SIZE(ov361x_start_320)); 1273 + break; 1274 + case ov361x_160: 1275 + reg_w_array(gspca_dev, ov361x_bridge_start_160, 1276 + ARRAY_SIZE(ov361x_bridge_start_160)); 1277 + sccb_w_array(gspca_dev, ov361x_start_160, 1278 + ARRAY_SIZE(ov361x_start_160)); 1279 + break; 1280 + } 1281 + reg_w(gspca_dev, 0xe0, 0x00); /* start transfer */ 1497 1282 1498 1283 return gspca_dev->usb_err; 1499 1284 } ··· 1560 1237 return gspca_dev->usb_err; 1561 1238 if (sd->sensor == SENSOR_OV562x) 1562 1239 return gspca_dev->usb_err; 1240 + if (sd->sensor == SENSOR_OV361x) 1241 + return sd_start_ov361x(gspca_dev); 1563 1242 1564 1243 switch (gspca_dev->curr_mode) { 1565 1244 case QVGA_MODE: /* 320x240 */ ··· 1615 1290 1616 1291 static void sd_stopN(struct gspca_dev *gspca_dev) 1617 1292 { 1293 + if (((struct sd *)gspca_dev)->sensor == SENSOR_OV361x) { 1294 + reg_w(gspca_dev, 0xe0, 0x01); /* stop transfer */ 1295 + /* reg_w(gspca_dev, 0x31, 0x09); */ 1296 + return; 1297 + } 1618 1298 reg_w(gspca_dev, 0xe0, 0x01); 1619 1299 set_led(gspca_dev, 0); 1620 1300 reg_w(gspca_dev, 0xe0, 0x00); ··· 1754 1424 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 1755 1425 1756 1426 if (sd->sensor == SENSOR_OV971x) 1427 + return 0; 1428 + if (sd->sensor == SENSOR_OV361x) 1757 1429 return 0; 1758 1430 gspca_dev->vdev.ctrl_handler = hdl; 1759 1431 v4l2_ctrl_handler_init(hdl, 7);