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

V4L/DVB (5062): SN9C102 driver updates

- Add support for SN9C105 and SN9C120
- Add some more USB device identifiers
- Add support for OV7660
- Implement audio ioctl's and VIDIOC_ENUM_FRAMESIZES
- Add preliminary support for 0x0c45/0x6007
- Documentation updates
- Generic improvements
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
f327ebbd 19790db0

+1905 -841
+149 -91
Documentation/video4linux/sn9c102.txt
··· 1 1 2 - SN9C10x PC Camera Controllers 2 + SN9C1xx PC Camera Controllers 3 3 Driver for Linux 4 4 ============================= 5 5 ··· 53 53 54 54 4. Overview and features 55 55 ======================== 56 - This driver attempts to support the video interface of the devices mounting the 57 - SONiX SN9C101, SN9C102 and SN9C103 PC Camera Controllers. 58 - 59 - It's worth to note that SONiX has never collaborated with the author during the 60 - development of this project, despite several requests for enough detailed 61 - specifications of the register tables, compression engine and video data format 62 - of the above chips. Nevertheless, these informations are no longer necessary, 63 - because all the aspects related to these chips are known and have been 64 - described in detail in this documentation. 56 + This driver attempts to support the video interface of the devices assembling 57 + the SONiX SN9C101, SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers 58 + ("SN9C1xx" from now on). 65 59 66 60 The driver relies on the Video4Linux2 and USB core modules. It has been 67 61 designed to run properly on SMP systems as well. 68 62 69 - The latest version of the SN9C10x driver can be found at the following URL: 63 + The latest version of the SN9C1xx driver can be found at the following URL: 70 64 http://www.linux-projects.org/ 71 65 72 66 Some of the features of the driver are: ··· 79 85 high compression quality (see also "Notes for V4L2 application developers" 80 86 and "Video frame formats" paragraphs); 81 87 - full support for the capabilities of many of the possible image sensors that 82 - can be connected to the SN9C10x bridges, including, for instance, red, green, 88 + can be connected to the SN9C1xx bridges, including, for instance, red, green, 83 89 blue and global gain adjustments and exposure (see "Supported devices" 84 90 paragraph for details); 85 91 - use of default color settings for sunlight conditions; 86 - - dynamic I/O interface for both SN9C10x and image sensor control and 92 + - dynamic I/O interface for both SN9C1xx and image sensor control and 87 93 monitoring (see "Optional device control through 'sysfs'" paragraph); 88 94 - dynamic driver control thanks to various module parameters (see "Module 89 95 parameters" paragraph); ··· 124 130 CONFIG_USB_UHCI_HCD=m 125 131 CONFIG_USB_OHCI_HCD=m 126 132 127 - The SN9C103 controller also provides a built-in microphone interface. It is 128 - supported by the USB Audio driver thanks to the ALSA API: 133 + The SN9C103, SN9c105 and SN9C120 controllers also provide a built-in microphone 134 + interface. It is supported by the USB Audio driver thanks to the ALSA API: 129 135 130 136 # Sound 131 137 # ··· 149 155 6. Module loading 150 156 ================= 151 157 To use the driver, it is necessary to load the "sn9c102" module into memory 152 - after every other module required: "videodev", "usbcore" and, depending on 153 - the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd". 158 + after every other module required: "videodev", "v4l2_common", "compat_ioctl32", 159 + "usbcore" and, depending on the USB host controller you have, "ehci-hcd", 160 + "uhci-hcd" or "ohci-hcd". 154 161 155 162 Loading can be done as shown below: 156 163 157 164 [root@localhost home]# modprobe sn9c102 158 165 159 - At this point the devices should be recognized. You can invoke "dmesg" to 160 - analyze kernel messages and verify that the loading process has gone well: 166 + Note that the module is called "sn9c102" for historic reasons, althought it 167 + does not just support the SN9C102. 168 + 169 + At this point all the devices supported by the driver and connected to the USB 170 + ports should be recognized. You can invoke "dmesg" to analyze kernel messages 171 + and verify that the loading process has gone well: 161 172 162 173 [user@localhost home]$ dmesg 174 + 175 + or, to isolate all the kernel messages generated by the driver: 176 + 177 + [user@localhost home]$ dmesg | grep sn9c102 163 178 164 179 165 180 7. Module parameters ··· 201 198 ------------------------------------------------------------------------------- 202 199 Name: frame_timeout 203 200 Type: uint array (min = 0, max = 64) 204 - Syntax: <n[,...]> 205 - Description: Timeout for a video frame in seconds. This parameter is 206 - specific for each detected camera. This parameter can be 207 - changed at runtime thanks to the /sys filesystem interface. 201 + Syntax: <0|n[,...]> 202 + Description: Timeout for a video frame in seconds before returning an I/O 203 + error; 0 for infinity. This parameter is specific for each 204 + detected camera and can be changed at runtime thanks to the 205 + /sys filesystem interface. 208 206 Default: 2 209 207 ------------------------------------------------------------------------------- 210 208 Name: debug ··· 227 223 8. Optional device control through "sysfs" [1] 228 224 ========================================== 229 225 If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled, 230 - it is possible to read and write both the SN9C10x and the image sensor 226 + it is possible to read and write both the SN9C1xx and the image sensor 231 227 registers by using the "sysfs" filesystem interface. 232 228 233 229 Every time a supported device is recognized, a write-only file named "green" is 234 230 created in the /sys/class/video4linux/videoX directory. You can set the green 235 231 channel's gain by writing the desired value to it. The value may range from 0 236 - to 15 for SN9C101 or SN9C102 bridges, from 0 to 127 for SN9C103 bridges. 237 - Similarly, only for SN9C103 controllers, blue and red gain control files are 238 - available in the same directory, for which accepted values may range from 0 to 239 - 127. 232 + to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103, 233 + SN9C105 and SN9C120 bridges. 234 + Similarly, only for the SN9C103, SN9C105 and SN9120 controllers, blue and red 235 + gain control files are available in the same directory, for which accepted 236 + values may range from 0 to 127. 240 237 241 238 There are other four entries in the directory above for each registered camera: 242 239 "reg", "val", "i2c_reg" and "i2c_val". The first two files control the 243 - SN9C10x bridge, while the other two control the sensor chip. "reg" and 240 + SN9C1xx bridge, while the other two control the sensor chip. "reg" and 244 241 "i2c_reg" hold the values of the current register index where the following 245 242 reading/writing operations are addressed at through "val" and "i2c_val". Their 246 243 use is not intended for end-users. Note that "i2c_reg" and "i2c_val" will not ··· 264 259 [root@localhost #] echo 0x11 > reg 265 260 [root@localhost #] echo 2 > val 266 261 267 - Note that the SN9C10x always returns 0 when some of its registers are read. 262 + Note that the SN9C1xx always returns 0 when some of its registers are read. 268 263 To avoid race conditions, all the I/O accesses to the above files are 269 264 serialized. 270 - 271 265 The sysfs interface also provides the "frame_header" entry, which exports the 272 266 frame header of the most recent requested and captured video frame. The header 273 - is always 18-bytes long and is appended to every video frame by the SN9C10x 267 + is always 18-bytes long and is appended to every video frame by the SN9C1xx 274 268 controllers. As an example, this additional information can be used by the user 275 269 application for implementing auto-exposure features via software. 276 270 277 - The following table describes the frame header: 271 + The following table describes the frame header exported by the SN9C101 and 272 + SN9C102: 278 273 279 - Byte # Value Description 280 - ------ ----- ----------- 281 - 0x00 0xFF Frame synchronisation pattern. 282 - 0x01 0xFF Frame synchronisation pattern. 283 - 0x02 0x00 Frame synchronisation pattern. 284 - 0x03 0xC4 Frame synchronisation pattern. 285 - 0x04 0xC4 Frame synchronisation pattern. 286 - 0x05 0x96 Frame synchronisation pattern. 287 - 0x06 0xXX Unknown meaning. The exact value depends on the chip; 288 - possible values are 0x00, 0x01 and 0x20. 289 - 0x07 0xXX Variable value, whose bits are ff00uzzc, where ff is a 290 - frame counter, u is unknown, zz is a size indicator 291 - (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for 292 - "compression enabled" (1 = yes, 0 = no). 293 - 0x08 0xXX Brightness sum inside Auto-Exposure area (low-byte). 294 - 0x09 0xXX Brightness sum inside Auto-Exposure area (high-byte). 295 - For a pure white image, this number will be equal to 500 296 - times the area of the specified AE area. For images 297 - that are not pure white, the value scales down according 298 - to relative whiteness. 299 - 0x0A 0xXX Brightness sum outside Auto-Exposure area (low-byte). 300 - 0x0B 0xXX Brightness sum outside Auto-Exposure area (high-byte). 301 - For a pure white image, this number will be equal to 125 302 - times the area outside of the specified AE area. For 303 - images that are not pure white, the value scales down 304 - according to relative whiteness. 305 - according to relative whiteness. 274 + Byte # Value or bits Description 275 + ------ ------------- ----------- 276 + 0x00 0xFF Frame synchronisation pattern 277 + 0x01 0xFF Frame synchronisation pattern 278 + 0x02 0x00 Frame synchronisation pattern 279 + 0x03 0xC4 Frame synchronisation pattern 280 + 0x04 0xC4 Frame synchronisation pattern 281 + 0x05 0x96 Frame synchronisation pattern 282 + 0x06 [3:0] Read channel gain control = (1+R_GAIN/8) 283 + [7:4] Blue channel gain control = (1+B_GAIN/8) 284 + 0x07 [ 0 ] Compression mode. 0=No compression, 1=Compression enabled 285 + [2:1] Maximum scale factor for compression 286 + [ 3 ] 1 = USB fifo(2K bytes) is full 287 + [ 4 ] 1 = Digital gain is finish 288 + [ 5 ] 1 = Exposure is finish 289 + [7:6] Frame index 290 + 0x08 [7:0] Y sum inside Auto-Exposure area (low-byte) 291 + 0x09 [7:0] Y sum inside Auto-Exposure area (high-byte) 292 + where Y sum = (R/4 + 5G/16 + B/8) / 32 293 + 0x0A [7:0] Y sum outside Auto-Exposure area (low-byte) 294 + 0x0B [7:0] Y sum outside Auto-Exposure area (high-byte) 295 + where Y sum = (R/4 + 5G/16 + B/8) / 128 296 + 0x0C 0xXX Not used 297 + 0x0D 0xXX Not used 298 + 0x0E 0xXX Not used 299 + 0x0F 0xXX Not used 300 + 0x10 0xXX Not used 301 + 0x11 0xXX Not used 306 302 307 - The following bytes are used by the SN9C103 bridge only: 303 + The following table describes the frame header exported by the SN9C103: 308 304 309 - 0x0C 0xXX Unknown meaning 310 - 0x0D 0xXX Unknown meaning 311 - 0x0E 0xXX Unknown meaning 312 - 0x0F 0xXX Unknown meaning 313 - 0x10 0xXX Unknown meaning 314 - 0x11 0xXX Unknown meaning 305 + Byte # Value or bits Description 306 + ------ ------------- ----------- 307 + 0x00 0xFF Frame synchronisation pattern 308 + 0x01 0xFF Frame synchronisation pattern 309 + 0x02 0x00 Frame synchronisation pattern 310 + 0x03 0xC4 Frame synchronisation pattern 311 + 0x04 0xC4 Frame synchronisation pattern 312 + 0x05 0x96 Frame synchronisation pattern 313 + 0x06 [6:0] Read channel gain control = (1/2+R_GAIN/64) 314 + 0x07 [6:0] Blue channel gain control = (1/2+B_GAIN/64) 315 + [7:4] 316 + 0x08 [ 0 ] Compression mode. 0=No compression, 1=Compression enabled 317 + [2:1] Maximum scale factor for compression 318 + [ 3 ] 1 = USB fifo(2K bytes) is full 319 + [ 4 ] 1 = Digital gain is finish 320 + [ 5 ] 1 = Exposure is finish 321 + [7:6] Frame index 322 + 0x09 [7:0] Y sum inside Auto-Exposure area (low-byte) 323 + 0x0A [7:0] Y sum inside Auto-Exposure area (high-byte) 324 + where Y sum = (R/4 + 5G/16 + B/8) / 32 325 + 0x0B [7:0] Y sum outside Auto-Exposure area (low-byte) 326 + 0x0C [7:0] Y sum outside Auto-Exposure area (high-byte) 327 + where Y sum = (R/4 + 5G/16 + B/8) / 128 328 + 0x0D [1:0] Audio frame number 329 + [ 2 ] 1 = Audio is recording 330 + 0x0E [7:0] Audio summation (low-byte) 331 + 0x0F [7:0] Audio summation (high-byte) 332 + 0x10 [7:0] Audio sample count 333 + 0x11 [7:0] Audio peak data in audio frame 315 334 316 335 The AE area (sx, sy, ex, ey) in the active window can be set by programming the 317 - registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C10x controllers, where one unit 336 + registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C1xx controllers, where one unit 318 337 corresponds to 32 pixels. 319 338 320 - [1] Part of the meaning of the frame header has been documented by Bertrik 321 - Sikken. 339 + [1] The frame headers exported by the SN9C105 and SN9C120 are not described. 322 340 323 341 324 342 9. Supported devices ··· 351 323 352 324 From the point of view of a driver, what unambiguously identify a device are 353 325 its vendor and product USB identifiers. Below is a list of known identifiers of 354 - devices mounting the SN9C10x PC camera controllers: 326 + devices assembling the SN9C1xx PC camera controllers: 355 327 356 328 Vendor ID Product ID 357 329 --------- ---------- 330 + 0x0471 0x0327 331 + 0x0471 0x0328 358 332 0x0c45 0x6001 359 333 0x0c45 0x6005 360 334 0x0c45 0x6007 361 335 0x0c45 0x6009 362 336 0x0c45 0x600d 337 + 0x0c45 0x6011 338 + 0x0c45 0x6019 363 339 0x0c45 0x6024 364 340 0x0c45 0x6025 365 341 0x0c45 0x6028 ··· 374 342 0x0c45 0x602d 375 343 0x0c45 0x602e 376 344 0x0c45 0x6030 345 + 0x0c45 0x603f 377 346 0x0c45 0x6080 378 347 0x0c45 0x6082 379 348 0x0c45 0x6083 ··· 401 368 0x0c45 0x60bb 402 369 0x0c45 0x60bc 403 370 0x0c45 0x60be 371 + 0x0c45 0x60c0 372 + 0x0c45 0x60c8 373 + 0x0c45 0x60cc 374 + 0x0c45 0x60ea 375 + 0x0c45 0x60ec 376 + 0x0c45 0x60fa 377 + 0x0c45 0x60fb 378 + 0x0c45 0x60fc 379 + 0x0c45 0x60fe 380 + 0x0c45 0x6130 381 + 0x0c45 0x613a 382 + 0x0c45 0x613b 383 + 0x0c45 0x613c 384 + 0x0c45 0x613e 404 385 405 386 The list above does not imply that all those devices work with this driver: up 406 - until now only the ones that mount the following image sensors are supported; 407 - kernel messages will always tell you whether this is the case: 387 + until now only the ones that assemble the following image sensors are 388 + supported; kernel messages will always tell you whether this is the case (see 389 + "Module loading" paragraph): 408 390 409 391 Model Manufacturer 410 392 ----- ------------ 411 393 HV7131D Hynix Semiconductor, Inc. 412 394 MI-0343 Micron Technology, Inc. 413 395 OV7630 OmniVision Technologies, Inc. 396 + OV7660 OmniVision Technologies, Inc. 414 397 PAS106B PixArt Imaging, Inc. 415 398 PAS202BCA PixArt Imaging, Inc. 416 399 PAS202BCB PixArt Imaging, Inc. 417 400 TAS5110C1B Taiwan Advanced Sensor Corporation 418 401 TAS5130D1B Taiwan Advanced Sensor Corporation 419 402 420 - All the available control settings of each image sensor are supported through 421 - the V4L2 interface. 403 + Some of the available control settings of each image sensor are supported 404 + through the V4L2 interface. 422 405 423 406 Donations of new models for further testing and support would be much 424 407 appreciated. Non-available hardware will not be supported by the author of this ··· 478 429 479 430 11. Video frame formats [1] 480 431 ======================= 481 - The SN9C10x PC Camera Controllers can send images in two possible video 482 - formats over the USB: either native "Sequential RGB Bayer" or Huffman 483 - compressed. The latter is used to achieve high frame rates. The current video 484 - format may be selected or queried from the user application by calling the 485 - VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2 API 486 - specifications. 432 + The SN9C1xx PC Camera Controllers can send images in two possible video 433 + formats over the USB: either native "Sequential RGB Bayer" or compressed. 434 + The compression is used to achieve high frame rates. With regard to the 435 + SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding 436 + algorithm described below, while the SN9C105 and SN9C120 the compression is 437 + based on the JPEG standard. 438 + The current video format may be selected or queried from the user application 439 + by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2 440 + API specifications. 487 441 488 442 The name "Sequential Bayer" indicates the organization of the red, green and 489 443 blue pixels in one video frame. Each pixel is associated with a 8-bit long ··· 499 447 ... G[n(m-2)] R[n(m-1)] 500 448 501 449 The above matrix also represents the sequential or progressive read-out mode of 502 - the (n, m) Bayer color filter array used in many CCD/CMOS image sensors. 450 + the (n, m) Bayer color filter array used in many CCD or CMOS image sensors. 503 451 504 - One compressed video frame consists of a bitstream that encodes for every R, G, 505 - or B pixel the difference between the value of the pixel itself and some 506 - reference pixel value. Pixels are organised in the Bayer pattern and the Bayer 507 - sub-pixels are tracked individually and alternatingly. For example, in the 508 - first line values for the B and G1 pixels are alternatingly encoded, while in 509 - the second line values for the G2 and R pixels are alternatingly encoded. 452 + The Huffman compressed video frame consists of a bitstream that encodes for 453 + every R, G, or B pixel the difference between the value of the pixel itself and 454 + some reference pixel value. Pixels are organised in the Bayer pattern and the 455 + Bayer sub-pixels are tracked individually and alternatingly. For example, in 456 + the first line values for the B and G1 pixels are alternatingly encoded, while 457 + in the second line values for the G2 and R pixels are alternatingly encoded. 510 458 511 459 The pixel reference value is calculated as follows: 512 460 - the 4 top left pixels are encoded in raw uncompressed 8-bit format; ··· 522 470 decoding. 523 471 524 472 The algorithm purely describes the conversion from compressed Bayer code used 525 - in the SN9C10x chips to uncompressed Bayer. Additional steps are required to 526 - convert this to a color image (i.e. a color interpolation algorithm). 473 + in the SN9C101, SN9C102 and SN9C103 chips to uncompressed Bayer. Additional 474 + steps are required to convert this to a color image (i.e. a color interpolation 475 + algorithm). 527 476 528 477 The following Huffman codes have been found: 529 478 0: +0 (relative to reference pixel value) ··· 559 506 - Philippe Coval for having helped testing the PAS202BCA image sensor; 560 507 - Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the 561 508 donation of a webcam; 509 + - Dennis Heitmann for the donation of a webcam; 562 510 - Jon Hollstrom for the donation of a webcam; 511 + - Nick McGill for the donation of a webcam; 563 512 - Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB 564 513 image sensor; 565 514 - Stefano Mozzi, who donated 45 EU; 566 515 - Andrew Pearce for the donation of a webcam; 516 + - John Pullan for the donation of a webcam; 567 517 - Bertrik Sikken, who reverse-engineered and documented the Huffman compression 568 - algorithm used in the SN9C10x controllers and implemented the first decoder; 518 + algorithm used in the SN9C101, SN9C102 and SN9C103 controllers and 519 + implemented the first decoder; 569 520 - Mizuno Takafumi for the donation of a webcam; 570 521 - an "anonymous" donator (who didn't want his name to be revealed) for the 571 522 donation of a webcam. 523 + - an anonymous donator for the donation of four webcams.
+2 -2
drivers/media/video/sn9c102/Kconfig
··· 1 1 config USB_SN9C102 2 - tristate "USB SN9C10x PC Camera Controller support" 2 + tristate "USB SN9C1xx PC Camera Controller support" 3 3 depends on USB && VIDEO_V4L1 4 4 ---help--- 5 5 Say Y here if you want support for cameras based on SONiX SN9C101, 6 - SN9C102 or SN9C103 PC Camera Controllers. 6 + SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. 7 7 8 8 See <file:Documentation/video4linux/sn9c102.txt> for more info. 9 9
+1 -1
drivers/media/video/sn9c102/Makefile
··· 1 1 sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ 2 - sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \ 2 + sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \ 3 3 sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ 4 4 sn9c102_tas5130d1b.o 5 5
+21 -36
drivers/media/video/sn9c102/sn9c102.h
··· 1 1 /*************************************************************************** 2 - * V4L2 driver for SN9C10x PC Camera Controllers * 2 + * V4L2 driver for SN9C1xx PC Camera Controllers * 3 3 * * 4 4 * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 5 * * ··· 37 37 #include <linux/string.h> 38 38 #include <linux/stddef.h> 39 39 40 + #include "sn9c102_config.h" 40 41 #include "sn9c102_sensor.h" 42 + #include "sn9c102_devtable.h" 41 43 42 - /*****************************************************************************/ 43 - 44 - #define SN9C102_DEBUG 45 - #define SN9C102_DEBUG_LEVEL 2 46 - #define SN9C102_MAX_DEVICES 64 47 - #define SN9C102_PRESERVE_IMGSCALE 0 48 - #define SN9C102_FORCE_MUNMAP 0 49 - #define SN9C102_MAX_FRAMES 32 50 - #define SN9C102_URBS 2 51 - #define SN9C102_ISO_PACKETS 7 52 - #define SN9C102_ALTERNATE_SETTING 8 53 - #define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS) 54 - #define SN9C102_CTRL_TIMEOUT 300 55 - #define SN9C102_FRAME_TIMEOUT 2 56 - 57 - /*****************************************************************************/ 58 - 59 - enum sn9c102_bridge { 60 - BRIDGE_SN9C101 = 0x01, 61 - BRIDGE_SN9C102 = 0x02, 62 - BRIDGE_SN9C103 = 0x04, 63 - }; 64 - 65 - SN9C102_ID_TABLE 66 - SN9C102_SENSOR_TABLE 67 44 68 45 enum sn9c102_frame_state { 69 46 F_UNUSED, ··· 76 99 STREAM_ON, 77 100 }; 78 101 79 - typedef char sn9c103_sof_header_t[18]; 80 - typedef char sn9c102_sof_header_t[12]; 81 - typedef char sn9c102_eof_header_t[4]; 102 + typedef char sn9c102_sof_header_t[62]; 82 103 83 104 struct sn9c102_sysfs_attr { 84 105 u8 reg, i2c_reg; 85 - sn9c103_sof_header_t frame_header; 106 + sn9c102_sof_header_t frame_header; 86 107 }; 87 108 88 109 struct sn9c102_module_param { ··· 112 137 struct v4l2_jpegcompression compression; 113 138 114 139 struct sn9c102_sysfs_attr sysfs; 115 - sn9c103_sof_header_t sof_header; 116 - u16 reg[63]; 140 + sn9c102_sof_header_t sof_header; 141 + u16 reg[384]; 117 142 118 143 struct sn9c102_module_param module_param; 119 144 ··· 130 155 struct sn9c102_device* 131 156 sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) 132 157 { 133 - if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) 134 - return cam; 135 - 136 - return NULL; 158 + return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; 137 159 } 138 160 139 161 ··· 139 167 struct sn9c102_sensor* sensor) 140 168 { 141 169 memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); 170 + } 171 + 172 + 173 + enum sn9c102_bridge 174 + sn9c102_get_bridge(struct sn9c102_device* cam) 175 + { 176 + return cam->bridge; 177 + } 178 + 179 + 180 + struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam) 181 + { 182 + return &cam->sensor; 142 183 } 143 184 144 185 /*****************************************************************************/
+86
drivers/media/video/sn9c102/sn9c102_config.h
··· 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 + 42 + static 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 + 53 + static 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 + 64 + static 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 + 75 + static 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_ */
+559 -160
drivers/media/video/sn9c102/sn9c102_core.c
··· 1 1 /*************************************************************************** 2 - * V4L2 driver for SN9C10x PC Camera Controllers * 2 + * V4L2 driver for SN9C1xx PC Camera Controllers * 3 3 * * 4 - * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 4 + * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 5 * * 6 6 * This program is free software; you can redistribute it and/or modify * 7 7 * it under the terms of the GNU General Public License as published by * ··· 43 43 44 44 /*****************************************************************************/ 45 45 46 - #define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers" 46 + #define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers" 47 47 #define SN9C102_MODULE_AUTHOR "(C) 2004-2006 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.27" 51 - #define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 27) 50 + #define SN9C102_MODULE_VERSION "1:1.34" 51 + #define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 34) 52 52 53 53 /*****************************************************************************/ 54 54 ··· 91 91 SN9C102_FRAME_TIMEOUT}; 92 92 module_param_array(frame_timeout, uint, NULL, 0644); 93 93 MODULE_PARM_DESC(frame_timeout, 94 - "\n<n[,...]> Timeout for a video frame in seconds." 94 + "\n<0|n[,...]> Timeout for a video frame in seconds before" 95 + "\nreturning an I/O error; 0 for infinity." 95 96 "\nThis parameter is specific for each detected camera." 96 97 "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." 97 98 "\n"); ··· 114 113 115 114 /*****************************************************************************/ 116 115 117 - static sn9c102_sof_header_t sn9c102_sof_header[] = { 118 - {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00}, 119 - {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01}, 120 - }; 121 - 122 - static sn9c103_sof_header_t sn9c103_sof_header[] = { 123 - {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x20}, 124 - }; 125 - 126 - static sn9c102_eof_header_t sn9c102_eof_header[] = { 127 - {0x00, 0x00, 0x00, 0x00}, 128 - {0x40, 0x00, 0x00, 0x00}, 129 - {0x80, 0x00, 0x00, 0x00}, 130 - {0xc0, 0x00, 0x00, 0x00}, 131 - }; 132 - 133 - /*****************************************************************************/ 134 - 135 116 static u32 136 117 sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, 137 118 enum sn9c102_io_method io) 138 119 { 139 120 struct v4l2_pix_format* p = &(cam->sensor.pix_format); 140 121 struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); 141 - const size_t imagesize = cam->module_param.force_munmap || 142 - io == IO_READ ? 122 + size_t imagesize = cam->module_param.force_munmap || io == IO_READ ? 143 123 (p->width * p->height * p->priv) / 8 : 144 124 (r->width * r->height * p->priv) / 8; 145 125 void* buff = NULL; ··· 129 147 if (count > SN9C102_MAX_FRAMES) 130 148 count = SN9C102_MAX_FRAMES; 131 149 150 + if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120) 151 + imagesize += 589 + 2; /* length of JPEG header + EOI marker */ 152 + 132 153 cam->nbuffers = count; 133 154 while (cam->nbuffers > 0) { 134 - if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) 155 + if ((buff = vmalloc_32_user(cam->nbuffers * 156 + PAGE_ALIGN(imagesize)))) 135 157 break; 136 158 cam->nbuffers--; 137 159 } ··· 308 322 sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, 309 323 struct sn9c102_sensor* sensor) 310 324 { 311 - int r; 325 + int r , err = 0; 326 + 312 327 r = sn9c102_read_reg(cam, 0x08); 313 - return (r < 0 || (r >= 0 && !(r & 0x08))) ? -EIO : 0; 328 + if (r < 0) 329 + err += r; 330 + 331 + if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { 332 + if (!(r & 0x08)) 333 + err += -1; 334 + } else { 335 + if (r & 0x08) 336 + err += -1; 337 + } 338 + 339 + return err ? -EIO : 0; 314 340 } 315 341 316 342 ··· 413 415 data[4] = data3; 414 416 data[5] = data4; 415 417 data[6] = data5; 416 - data[7] = 0x14; 418 + data[7] = 0x17; 417 419 res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, 418 420 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT); 419 421 if (res < 0) ··· 465 467 466 468 /*****************************************************************************/ 467 469 468 - static void* 469 - sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) 470 + static size_t sn9c102_sof_length(struct sn9c102_device* cam) 470 471 { 471 - size_t soflen = 0, i; 472 - u8 j, n = 0; 473 - 474 472 switch (cam->bridge) { 475 473 case BRIDGE_SN9C101: 476 474 case BRIDGE_SN9C102: 477 - soflen = sizeof(sn9c102_sof_header_t); 478 - n = sizeof(sn9c102_sof_header) / soflen; 479 - break; 475 + return 12; 480 476 case BRIDGE_SN9C103: 481 - soflen = sizeof(sn9c103_sof_header_t); 482 - n = sizeof(sn9c103_sof_header) / soflen; 477 + return 18; 478 + case BRIDGE_SN9C105: 479 + case BRIDGE_SN9C120: 480 + return 62; 483 481 } 484 482 483 + return 0; 484 + } 485 + 486 + 487 + static void* 488 + sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len) 489 + { 490 + char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; 491 + size_t soflen = 0, i; 492 + 493 + soflen = sn9c102_sof_length(cam); 494 + 485 495 for (i = 0; (len >= soflen) && (i <= len - soflen); i++) 486 - for (j = 0; j < n; j++) 487 - /* The invariable part of the header is 6 bytes long */ 488 - if ((cam->bridge != BRIDGE_SN9C103 && 489 - !memcmp(mem + i, sn9c102_sof_header[j], 6)) || 490 - (cam->bridge == BRIDGE_SN9C103 && 491 - !memcmp(mem + i, sn9c103_sof_header[j], 6))) { 492 - memcpy(cam->sof_header, mem + i, soflen); 496 + if (!memcmp(mem + i, sof_header, sizeof(sof_header))) { 497 + memcpy(cam->sof_header, mem + i, 498 + sizeof(sn9c102_sof_header_t)); 493 499 /* Skip the header */ 494 500 return mem + i + soflen; 495 501 } ··· 505 503 static void* 506 504 sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len) 507 505 { 508 - size_t eoflen = sizeof(sn9c102_eof_header_t), i; 509 - unsigned j, n = sizeof(sn9c102_eof_header) / eoflen; 506 + char eof_header[4][4] = { 507 + {0x00, 0x00, 0x00, 0x00}, 508 + {0x40, 0x00, 0x00, 0x00}, 509 + {0x80, 0x00, 0x00, 0x00}, 510 + {0xc0, 0x00, 0x00, 0x00}, 511 + }; 512 + size_t i, j; 510 513 511 - if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) 514 + if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || 515 + cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) 512 516 return NULL; /* EOF header does not exist in compressed data */ 513 517 514 - for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++) 515 - for (j = 0; j < n; j++) 516 - if (!memcmp(mem + i, sn9c102_eof_header[j], eoflen)) 518 + for (i = 0; (len >= 4) && (i <= len - 4); i++) 519 + for (j = 0; j < ARRAY_SIZE(eof_header); j++) 520 + if (!memcmp(mem + i, eof_header[j], 4)) 517 521 return mem + i; 518 522 519 523 return NULL; 524 + } 525 + 526 + 527 + static void 528 + sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f) 529 + { 530 + static u8 jpeg_header[589] = { 531 + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05, 532 + 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06, 533 + 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e, 534 + 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16, 535 + 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16, 536 + 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29, 537 + 0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29, 538 + 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a, 539 + 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28, 540 + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 541 + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 542 + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 543 + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 544 + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2, 545 + 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 546 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 547 + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 548 + 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 549 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 550 + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 551 + 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 552 + 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, 553 + 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 554 + 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 555 + 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 556 + 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 557 + 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 558 + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 559 + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 560 + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 561 + 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 562 + 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 563 + 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 564 + 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 565 + 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 566 + 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 567 + 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 568 + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02, 569 + 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 570 + 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 571 + 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 572 + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 573 + 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 574 + 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 575 + 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 576 + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 577 + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 578 + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 579 + 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 580 + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 581 + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 582 + 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 583 + 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 584 + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 585 + 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 586 + 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11, 587 + 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 588 + 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 589 + 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 590 + }; 591 + u8 *pos = f->bufmem; 592 + 593 + memcpy(pos, jpeg_header, sizeof(jpeg_header)); 594 + *(pos + 6) = 0x00; 595 + *(pos + 7 + 64) = 0x01; 596 + if (cam->compression.quality == 0) { 597 + memcpy(pos + 7, SN9C102_Y_QTABLE0, 64); 598 + memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64); 599 + } else if (cam->compression.quality == 1) { 600 + memcpy(pos + 7, SN9C102_Y_QTABLE1, 64); 601 + memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64); 602 + } 603 + *(pos + 564) = cam->sensor.pix_format.width & 0xFF; 604 + *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF; 605 + *(pos + 562) = cam->sensor.pix_format.height & 0xFF; 606 + *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF; 607 + *(pos + 567) = 0x21; 608 + 609 + f->buf.bytesused += sizeof(jpeg_header); 610 + } 611 + 612 + 613 + static void 614 + sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f) 615 + { 616 + static const u8 eoi_marker[2] = {0xff, 0xd9}; 617 + 618 + memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker)); 619 + f->buf.bytesused += sizeof(eoi_marker); 520 620 } 521 621 522 622 ··· 639 535 cam->stream = STREAM_OFF; 640 536 if ((*f)) 641 537 (*f)->state = F_QUEUED; 642 - DBG(3, "Stream interrupted"); 538 + DBG(3, "Stream interrupted by application"); 643 539 wake_up(&cam->wait_stream); 644 540 } 645 541 ··· 661 557 imagesize = (cam->sensor.pix_format.width * 662 558 cam->sensor.pix_format.height * 663 559 cam->sensor.pix_format.priv) / 8; 664 - 665 - soflen = (cam->bridge) == BRIDGE_SN9C103 ? 666 - sizeof(sn9c103_sof_header_t) : 667 - sizeof(sn9c102_sof_header_t); 560 + if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG) 561 + imagesize += 589; /* length of jpeg header */ 562 + soflen = sn9c102_sof_length(cam); 668 563 669 564 for (i = 0; i < urb->number_of_packets; i++) { 670 565 unsigned int img, len, status; ··· 713 610 (*f)->buf.bytesused += img; 714 611 715 612 if ((*f)->buf.bytesused == imagesize || 716 - (cam->sensor.pix_format.pixelformat == 717 - V4L2_PIX_FMT_SN9C10X && eof)) { 613 + ((cam->sensor.pix_format.pixelformat == 614 + V4L2_PIX_FMT_SN9C10X || 615 + cam->sensor.pix_format.pixelformat == 616 + V4L2_PIX_FMT_JPEG) && eof)) { 718 617 u32 b; 618 + 619 + if (cam->sensor.pix_format.pixelformat 620 + == V4L2_PIX_FMT_JPEG) 621 + sn9c102_write_eoimarker(cam, 622 + (*f)); 623 + 719 624 b = (*f)->buf.bytesused; 720 625 (*f)->state = F_DONE; 721 626 (*f)->buf.sequence= ++cam->frame_count; 627 + 722 628 spin_lock(&cam->queue_lock); 723 629 list_move_tail(&(*f)->frame, 724 630 &cam->outqueue); ··· 739 627 else 740 628 (*f) = NULL; 741 629 spin_unlock(&cam->queue_lock); 630 + 742 631 memcpy(cam->sysfs.frame_header, 743 632 cam->sof_header, soflen); 633 + 744 634 DBG(3, "Video frame captured: %lu " 745 635 "bytes", (unsigned long)(b)); 746 636 ··· 775 661 (*f)->buf.bytesused = 0; 776 662 len -= (sof - pos); 777 663 pos = sof; 664 + if (cam->sensor.pix_format.pixelformat == 665 + V4L2_PIX_FMT_JPEG) 666 + sn9c102_write_jpegheader(cam, (*f)); 778 667 DBG(3, "SOF detected: new video frame"); 779 668 if (len) 780 669 goto redo; ··· 788 671 goto end_of_frame; /* (1) */ 789 672 else { 790 673 if (cam->sensor.pix_format.pixelformat == 791 - V4L2_PIX_FMT_SN9C10X) { 674 + V4L2_PIX_FMT_SN9C10X || 675 + cam->sensor.pix_format.pixelformat == 676 + V4L2_PIX_FMT_JPEG) { 792 677 eof = sof - soflen; 793 678 goto end_of_frame; 794 679 } else { ··· 820 701 { 821 702 struct usb_device *udev = cam->usbdev; 822 703 struct urb* urb; 823 - const unsigned int sn9c102_wMaxPacketSize[] = {0, 128, 256, 384, 512, 824 - 680, 800, 900, 1023}; 825 - const unsigned int sn9c103_wMaxPacketSize[] = {0, 128, 256, 384, 512, 826 - 680, 800, 900, 1003}; 827 - const unsigned int psz = (cam->bridge == BRIDGE_SN9C103) ? 828 - sn9c103_wMaxPacketSize[SN9C102_ALTERNATE_SETTING] : 829 - sn9c102_wMaxPacketSize[SN9C102_ALTERNATE_SETTING]; 704 + struct usb_host_interface* altsetting = usb_altnum_to_altsetting( 705 + usb_ifnum_to_if(udev, 0), 706 + SN9C102_ALTERNATE_SETTING); 707 + const unsigned int psz = le16_to_cpu(altsetting-> 708 + endpoint[0].desc.wMaxPacketSize); 830 709 s8 i, j; 831 710 int err = 0; 832 711 ··· 892 775 return 0; 893 776 894 777 free_urbs: 895 - for (i = 0; i < SN9C102_URBS; i++) 778 + for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++) 896 779 usb_free_urb(cam->urb[i]); 897 780 898 781 free_buffers: ··· 951 834 /*****************************************************************************/ 952 835 953 836 #ifdef CONFIG_VIDEO_ADV_DEBUG 954 - static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) 837 + static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count) 955 838 { 956 - char str[5]; 839 + char str[7]; 957 840 char* endp; 958 841 unsigned long val; 959 842 960 - if (len < 4) { 843 + if (len < 6) { 961 844 strncpy(str, buff, len); 962 845 str[len+1] = '\0'; 963 846 } else { 964 847 strncpy(str, buff, 4); 965 - str[4] = '\0'; 848 + str[6] = '\0'; 966 849 } 967 850 968 851 val = simple_strtoul(str, &endp, 0); 969 852 970 853 *count = 0; 971 - if (val <= 0xff) 854 + if (val <= 0xffff) 972 855 *count = (ssize_t)(endp - str); 973 856 if ((*count) && (len == *count+1) && (buff[*count] == '\n')) 974 857 *count += 1; 975 858 976 - return (u8)val; 859 + return (u16)val; 977 860 } 978 861 979 862 /* ··· 990 873 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 991 874 return -ERESTARTSYS; 992 875 993 - cam = video_get_drvdata(to_video_device(cd)); 876 + cam = video_get_drvdata(container_of(cd, struct video_device, 877 + class_dev)); 994 878 if (!cam) { 995 879 mutex_unlock(&sn9c102_sysfs_lock); 996 880 return -ENODEV; ··· 1009 891 sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len) 1010 892 { 1011 893 struct sn9c102_device* cam; 1012 - u8 index; 894 + u16 index; 1013 895 ssize_t count; 1014 896 1015 897 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1016 898 return -ERESTARTSYS; 1017 899 1018 - cam = video_get_drvdata(to_video_device(cd)); 900 + cam = video_get_drvdata(container_of(cd, struct video_device, 901 + class_dev)); 1019 902 if (!cam) { 1020 903 mutex_unlock(&sn9c102_sysfs_lock); 1021 904 return -ENODEV; 1022 905 } 1023 906 1024 - index = sn9c102_strtou8(buf, len, &count); 1025 - if (index > 0x1f || !count) { 907 + index = sn9c102_strtou16(buf, len, &count); 908 + if (index >= ARRAY_SIZE(cam->reg) || !count) { 1026 909 mutex_unlock(&sn9c102_sysfs_lock); 1027 910 return -EINVAL; 1028 911 } 1029 912 1030 913 cam->sysfs.reg = index; 1031 914 1032 - DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg); 915 + DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg); 1033 916 DBG(3, "Written bytes: %zd", count); 1034 917 1035 918 mutex_unlock(&sn9c102_sysfs_lock); ··· 1048 929 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1049 930 return -ERESTARTSYS; 1050 931 1051 - cam = video_get_drvdata(to_video_device(cd)); 932 + cam = video_get_drvdata(container_of(cd, struct video_device, 933 + class_dev)); 1052 934 if (!cam) { 1053 935 mutex_unlock(&sn9c102_sysfs_lock); 1054 936 return -ENODEV; ··· 1074 954 sn9c102_store_val(struct class_device* cd, const char* buf, size_t len) 1075 955 { 1076 956 struct sn9c102_device* cam; 1077 - u8 value; 957 + u16 value; 1078 958 ssize_t count; 1079 959 int err; 1080 960 1081 961 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1082 962 return -ERESTARTSYS; 1083 963 1084 - cam = video_get_drvdata(to_video_device(cd)); 964 + cam = video_get_drvdata(container_of(cd, struct video_device, 965 + class_dev)); 1085 966 if (!cam) { 1086 967 mutex_unlock(&sn9c102_sysfs_lock); 1087 968 return -ENODEV; 1088 969 } 1089 970 1090 - value = sn9c102_strtou8(buf, len, &count); 971 + value = sn9c102_strtou16(buf, len, &count); 1091 972 if (!count) { 1092 973 mutex_unlock(&sn9c102_sysfs_lock); 1093 974 return -EINVAL; ··· 1100 979 return -EIO; 1101 980 } 1102 981 1103 - DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X", 982 + DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X", 1104 983 cam->sysfs.reg, value); 1105 984 DBG(3, "Written bytes: %zd", count); 1106 985 ··· 1118 997 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1119 998 return -ERESTARTSYS; 1120 999 1121 - cam = video_get_drvdata(to_video_device(cd)); 1000 + cam = video_get_drvdata(container_of(cd, struct video_device, 1001 + class_dev)); 1122 1002 if (!cam) { 1123 1003 mutex_unlock(&sn9c102_sysfs_lock); 1124 1004 return -ENODEV; ··· 1139 1017 sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len) 1140 1018 { 1141 1019 struct sn9c102_device* cam; 1142 - u8 index; 1020 + u16 index; 1143 1021 ssize_t count; 1144 1022 1145 1023 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1146 1024 return -ERESTARTSYS; 1147 1025 1148 - cam = video_get_drvdata(to_video_device(cd)); 1026 + cam = video_get_drvdata(container_of(cd, struct video_device, 1027 + class_dev)); 1149 1028 if (!cam) { 1150 1029 mutex_unlock(&sn9c102_sysfs_lock); 1151 1030 return -ENODEV; 1152 1031 } 1153 1032 1154 - index = sn9c102_strtou8(buf, len, &count); 1033 + index = sn9c102_strtou16(buf, len, &count); 1155 1034 if (!count) { 1156 1035 mutex_unlock(&sn9c102_sysfs_lock); 1157 1036 return -EINVAL; ··· 1178 1055 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1179 1056 return -ERESTARTSYS; 1180 1057 1181 - cam = video_get_drvdata(to_video_device(cd)); 1058 + cam = video_get_drvdata(container_of(cd, struct video_device, 1059 + class_dev)); 1182 1060 if (!cam) { 1183 1061 mutex_unlock(&sn9c102_sysfs_lock); 1184 1062 return -ENODEV; ··· 1209 1085 sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len) 1210 1086 { 1211 1087 struct sn9c102_device* cam; 1212 - u8 value; 1088 + u16 value; 1213 1089 ssize_t count; 1214 1090 int err; 1215 1091 1216 1092 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1217 1093 return -ERESTARTSYS; 1218 1094 1219 - cam = video_get_drvdata(to_video_device(cd)); 1095 + cam = video_get_drvdata(container_of(cd, struct video_device, 1096 + class_dev)); 1220 1097 if (!cam) { 1221 1098 mutex_unlock(&sn9c102_sysfs_lock); 1222 1099 return -ENODEV; ··· 1228 1103 return -ENOSYS; 1229 1104 } 1230 1105 1231 - value = sn9c102_strtou8(buf, len, &count); 1106 + value = sn9c102_strtou16(buf, len, &count); 1232 1107 if (!count) { 1233 1108 mutex_unlock(&sn9c102_sysfs_lock); 1234 1109 return -EINVAL; ··· 1256 1131 struct sn9c102_device* cam; 1257 1132 enum sn9c102_bridge bridge; 1258 1133 ssize_t res = 0; 1259 - u8 value; 1134 + u16 value; 1260 1135 ssize_t count; 1261 1136 1262 1137 if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) 1263 1138 return -ERESTARTSYS; 1264 1139 1265 - cam = video_get_drvdata(to_video_device(cd)); 1140 + cam = video_get_drvdata(container_of(cd, struct video_device, 1141 + class_dev)); 1266 1142 if (!cam) { 1267 1143 mutex_unlock(&sn9c102_sysfs_lock); 1268 1144 return -ENODEV; ··· 1273 1147 1274 1148 mutex_unlock(&sn9c102_sysfs_lock); 1275 1149 1276 - value = sn9c102_strtou8(buf, len, &count); 1150 + value = sn9c102_strtou16(buf, len, &count); 1277 1151 if (!count) 1278 1152 return -EINVAL; 1279 1153 ··· 1286 1160 res = sn9c102_store_val(cd, buf, len); 1287 1161 break; 1288 1162 case BRIDGE_SN9C103: 1163 + case BRIDGE_SN9C105: 1164 + case BRIDGE_SN9C120: 1289 1165 if (value > 0x7f) 1290 1166 return -EINVAL; 1291 - if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0) 1167 + if ((res = sn9c102_store_reg(cd, "0x07", 4)) >= 0) 1292 1168 res = sn9c102_store_val(cd, buf, len); 1293 1169 break; 1294 1170 } ··· 1303 1175 sn9c102_store_blue(struct class_device* cd, const char* buf, size_t len) 1304 1176 { 1305 1177 ssize_t res = 0; 1306 - u8 value; 1178 + u16 value; 1307 1179 ssize_t count; 1308 1180 1309 - value = sn9c102_strtou8(buf, len, &count); 1181 + value = sn9c102_strtou16(buf, len, &count); 1310 1182 if (!count || value > 0x7f) 1311 1183 return -EINVAL; 1312 1184 ··· 1321 1193 sn9c102_store_red(struct class_device* cd, const char* buf, size_t len) 1322 1194 { 1323 1195 ssize_t res = 0; 1324 - u8 value; 1196 + u16 value; 1325 1197 ssize_t count; 1326 1198 1327 - value = sn9c102_strtou8(buf, len, &count); 1199 + value = sn9c102_strtou16(buf, len, &count); 1328 1200 if (!count || value > 0x7f) 1329 1201 return -EINVAL; 1330 1202 ··· 1340 1212 struct sn9c102_device* cam; 1341 1213 ssize_t count; 1342 1214 1343 - cam = video_get_drvdata(to_video_device(cd)); 1215 + cam = video_get_drvdata(container_of(cd, struct video_device, 1216 + class_dev)); 1344 1217 if (!cam) 1345 1218 return -ENODEV; 1346 1219 ··· 1372 1243 static int sn9c102_create_sysfs(struct sn9c102_device* cam) 1373 1244 { 1374 1245 struct video_device *v4ldev = cam->v4ldev; 1375 - int rc; 1246 + int err = 0; 1376 1247 1377 - rc = video_device_create_file(v4ldev, &class_device_attr_reg); 1378 - if (rc) goto err; 1379 - rc = video_device_create_file(v4ldev, &class_device_attr_val); 1380 - if (rc) goto err_reg; 1381 - rc = video_device_create_file(v4ldev, &class_device_attr_frame_header); 1382 - if (rc) goto err_val; 1248 + if ((err = video_device_create_file(v4ldev, &class_device_attr_reg))) 1249 + goto err_out; 1250 + if ((err = video_device_create_file(v4ldev, &class_device_attr_val))) 1251 + goto err_reg; 1252 + if ((err = video_device_create_file(v4ldev, 1253 + &class_device_attr_frame_header))) 1254 + goto err_val; 1383 1255 1384 1256 if (cam->sensor.sysfs_ops) { 1385 - rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg); 1386 - if (rc) goto err_frhead; 1387 - rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val); 1388 - if (rc) goto err_i2c_reg; 1257 + if ((err = video_device_create_file(v4ldev, 1258 + &class_device_attr_i2c_reg))) 1259 + goto err_frame_header; 1260 + if ((err = video_device_create_file(v4ldev, 1261 + &class_device_attr_i2c_val))) 1262 + goto err_i2c_reg; 1389 1263 } 1390 1264 1391 1265 if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { 1392 - rc = video_device_create_file(v4ldev, &class_device_attr_green); 1393 - if (rc) goto err_i2c_val; 1394 - } else if (cam->bridge == BRIDGE_SN9C103) { 1395 - rc = video_device_create_file(v4ldev, &class_device_attr_blue); 1396 - if (rc) goto err_i2c_val; 1397 - rc = video_device_create_file(v4ldev, &class_device_attr_red); 1398 - if (rc) goto err_blue; 1266 + if ((err = video_device_create_file(v4ldev, 1267 + &class_device_attr_green))) 1268 + goto err_i2c_val; 1269 + } else { 1270 + if ((err = video_device_create_file(v4ldev, 1271 + &class_device_attr_blue))) 1272 + goto err_i2c_val; 1273 + if ((err = video_device_create_file(v4ldev, 1274 + &class_device_attr_red))) 1275 + goto err_blue; 1399 1276 } 1400 1277 1401 1278 return 0; ··· 1414 1279 err_i2c_reg: 1415 1280 if (cam->sensor.sysfs_ops) 1416 1281 video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); 1417 - err_frhead: 1282 + err_frame_header: 1418 1283 video_device_remove_file(v4ldev, &class_device_attr_frame_header); 1419 1284 err_val: 1420 1285 video_device_remove_file(v4ldev, &class_device_attr_val); 1421 1286 err_reg: 1422 1287 video_device_remove_file(v4ldev, &class_device_attr_reg); 1423 - err: 1424 - return rc; 1288 + err_out: 1289 + return err; 1425 1290 } 1426 1291 #endif /* CONFIG_VIDEO_ADV_DEBUG */ 1427 1292 ··· 1432 1297 { 1433 1298 int err = 0; 1434 1299 1435 - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) 1436 - err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18); 1437 - else 1438 - err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18); 1300 + if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || 1301 + pix->pixelformat == V4L2_PIX_FMT_JPEG) { 1302 + switch (cam->bridge) { 1303 + case BRIDGE_SN9C101: 1304 + case BRIDGE_SN9C102: 1305 + case BRIDGE_SN9C103: 1306 + err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 1307 + 0x18); 1308 + break; 1309 + case BRIDGE_SN9C105: 1310 + case BRIDGE_SN9C120: 1311 + err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 1312 + 0x18); 1313 + break; 1314 + } 1315 + } else { 1316 + switch (cam->bridge) { 1317 + case BRIDGE_SN9C101: 1318 + case BRIDGE_SN9C102: 1319 + case BRIDGE_SN9C103: 1320 + err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 1321 + 0x18); 1322 + break; 1323 + case BRIDGE_SN9C105: 1324 + case BRIDGE_SN9C120: 1325 + err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 1326 + 0x18); 1327 + break; 1328 + } 1329 + } 1439 1330 1440 1331 return err ? -EIO : 0; 1441 1332 } ··· 1471 1310 sn9c102_set_compression(struct sn9c102_device* cam, 1472 1311 struct v4l2_jpegcompression* compression) 1473 1312 { 1474 - int err = 0; 1313 + int i, err = 0; 1475 1314 1315 + switch (cam->bridge) { 1316 + case BRIDGE_SN9C101: 1317 + case BRIDGE_SN9C102: 1318 + case BRIDGE_SN9C103: 1476 1319 if (compression->quality == 0) 1477 - err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17); 1320 + err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 1321 + 0x17); 1478 1322 else if (compression->quality == 1) 1479 - err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17); 1323 + err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 1324 + 0x17); 1325 + break; 1326 + case BRIDGE_SN9C105: 1327 + case BRIDGE_SN9C120: 1328 + if (compression->quality == 0) { 1329 + for (i = 0; i <= 63; i++) { 1330 + err += sn9c102_write_reg(cam, 1331 + SN9C102_Y_QTABLE0[i], 1332 + 0x100 + i); 1333 + err += sn9c102_write_reg(cam, 1334 + SN9C102_UV_QTABLE0[i], 1335 + 0x140 + i); 1336 + } 1337 + err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf, 1338 + 0x18); 1339 + } else if (compression->quality == 1) { 1340 + for (i = 0; i <= 63; i++) { 1341 + err += sn9c102_write_reg(cam, 1342 + SN9C102_Y_QTABLE1[i], 1343 + 0x100 + i); 1344 + err += sn9c102_write_reg(cam, 1345 + SN9C102_UV_QTABLE1[i], 1346 + 0x140 + i); 1347 + } 1348 + err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40, 1349 + 0x18); 1350 + } 1351 + break; 1352 + } 1480 1353 1481 1354 return err ? -EIO : 0; 1482 1355 } ··· 1594 1399 } 1595 1400 1596 1401 if (!(cam->state & DEV_INITIALIZED)) 1597 - cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1; 1402 + if (cam->bridge == BRIDGE_SN9C101 || 1403 + cam->bridge == BRIDGE_SN9C102 || 1404 + cam->bridge == BRIDGE_SN9C103) { 1405 + cam->compression.quality = cam->reg[0x17] & 0x01 ? 1406 + 0 : 1; 1407 + } else { 1408 + cam->compression.quality = cam->reg[0x18] & 0x40 ? 1409 + 0 : 1; 1410 + err += sn9c102_set_compression(cam, &cam->compression); 1411 + } 1598 1412 else 1599 1413 err += sn9c102_set_compression(cam, &cam->compression); 1600 1414 err += sn9c102_set_pix_format(cam, &s->pix_format); ··· 1612 1408 if (err) 1613 1409 return err; 1614 1410 1615 - if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) 1411 + if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X || 1412 + s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG) 1616 1413 DBG(3, "Compressed video format is active, quality %d", 1617 1414 cam->compression.quality); 1618 1415 else ··· 1695 1490 1696 1491 if (cam->users) { 1697 1492 DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); 1493 + DBG(3, "Simultaneous opens are not supported"); 1698 1494 if ((filp->f_flags & O_NONBLOCK) || 1699 1495 (filp->f_flags & O_NDELAY)) { 1700 1496 err = -EWOULDBLOCK; ··· 1834 1628 mutex_unlock(&cam->fileop_mutex); 1835 1629 return -EAGAIN; 1836 1630 } 1631 + if (!cam->module_param.frame_timeout) { 1632 + err = wait_event_interruptible 1633 + ( cam->wait_frame, 1634 + (!list_empty(&cam->outqueue)) || 1635 + (cam->state & DEV_DISCONNECTED) || 1636 + (cam->state & DEV_MISCONFIGURED) ); 1637 + if (err) { 1638 + mutex_unlock(&cam->fileop_mutex); 1639 + return err; 1640 + } 1641 + } else { 1837 1642 timeout = wait_event_interruptible_timeout 1838 1643 ( cam->wait_frame, 1839 1644 (!list_empty(&cam->outqueue)) || ··· 1855 1638 if (timeout < 0) { 1856 1639 mutex_unlock(&cam->fileop_mutex); 1857 1640 return timeout; 1641 + } else if (timeout == 0 && 1642 + !(cam->state & DEV_DISCONNECTED)) { 1643 + DBG(1, "Video frame timeout elapsed"); 1644 + mutex_unlock(&cam->fileop_mutex); 1645 + return -EIO; 1646 + } 1858 1647 } 1859 1648 if (cam->state & DEV_DISCONNECTED) { 1860 1649 mutex_unlock(&cam->fileop_mutex); 1861 1650 return -ENODEV; 1862 1651 } 1863 - if (!timeout || (cam->state & DEV_MISCONFIGURED)) { 1652 + if (cam->state & DEV_MISCONFIGURED) { 1864 1653 mutex_unlock(&cam->fileop_mutex); 1865 1654 return -EIO; 1866 1655 } ··· 2163 1940 if (copy_to_user(arg, &ctrl, sizeof(ctrl))) 2164 1941 return -EFAULT; 2165 1942 1943 + PDBGG("VIDIOC_G_CTRL: id %lu, value %lu", 1944 + (unsigned long)ctrl.id, (unsigned long)ctrl.value); 1945 + 2166 1946 return err; 2167 1947 } 2168 1948 ··· 2353 2127 2354 2128 2355 2129 static int 2130 + sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg) 2131 + { 2132 + struct v4l2_frmsizeenum frmsize; 2133 + 2134 + if (copy_from_user(&frmsize, arg, sizeof(frmsize))) 2135 + return -EFAULT; 2136 + 2137 + if (frmsize.index != 0) 2138 + return -EINVAL; 2139 + 2140 + switch (cam->bridge) { 2141 + case BRIDGE_SN9C101: 2142 + case BRIDGE_SN9C102: 2143 + case BRIDGE_SN9C103: 2144 + if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X && 2145 + frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8) 2146 + return -EINVAL; 2147 + case BRIDGE_SN9C105: 2148 + case BRIDGE_SN9C120: 2149 + if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG && 2150 + frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8) 2151 + return -EINVAL; 2152 + } 2153 + 2154 + frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE; 2155 + frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16; 2156 + frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16; 2157 + frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width; 2158 + frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height; 2159 + memset(&frmsize.reserved, 0, sizeof(frmsize.reserved)); 2160 + 2161 + if (copy_to_user(arg, &frmsize, sizeof(frmsize))) 2162 + return -EFAULT; 2163 + 2164 + return 0; 2165 + } 2166 + 2167 + 2168 + static int 2356 2169 sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg) 2357 2170 { 2358 2171 struct v4l2_fmtdesc fmtd; ··· 2399 2134 if (copy_from_user(&fmtd, arg, sizeof(fmtd))) 2400 2135 return -EFAULT; 2401 2136 2137 + if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 2138 + return -EINVAL; 2139 + 2402 2140 if (fmtd.index == 0) { 2403 2141 strcpy(fmtd.description, "bayer rgb"); 2404 2142 fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; 2405 2143 } else if (fmtd.index == 1) { 2144 + switch (cam->bridge) { 2145 + case BRIDGE_SN9C101: 2146 + case BRIDGE_SN9C102: 2147 + case BRIDGE_SN9C103: 2406 2148 strcpy(fmtd.description, "compressed"); 2407 2149 fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X; 2150 + break; 2151 + case BRIDGE_SN9C105: 2152 + case BRIDGE_SN9C120: 2153 + strcpy(fmtd.description, "JPEG"); 2154 + fmtd.pixelformat = V4L2_PIX_FMT_JPEG; 2155 + break; 2156 + } 2408 2157 fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; 2409 2158 } else 2410 2159 return -EINVAL; ··· 2445 2166 if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 2446 2167 return -EINVAL; 2447 2168 2448 - pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X) 2169 + pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X || 2170 + pfmt->pixelformat==V4L2_PIX_FMT_JPEG) 2449 2171 ? 0 : (pfmt->width * pfmt->priv) / 8; 2450 2172 pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); 2451 2173 pfmt->field = V4L2_FIELD_NONE; ··· 2517 2237 pix->width = rect.width / scale; 2518 2238 pix->height = rect.height / scale; 2519 2239 2240 + switch (cam->bridge) { 2241 + case BRIDGE_SN9C101: 2242 + case BRIDGE_SN9C102: 2243 + case BRIDGE_SN9C103: 2520 2244 if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X && 2521 2245 pix->pixelformat != V4L2_PIX_FMT_SBGGR8) 2522 2246 pix->pixelformat = pfmt->pixelformat; 2247 + break; 2248 + case BRIDGE_SN9C105: 2249 + case BRIDGE_SN9C120: 2250 + if (pix->pixelformat != V4L2_PIX_FMT_JPEG && 2251 + pix->pixelformat != V4L2_PIX_FMT_SBGGR8) 2252 + pix->pixelformat = pfmt->pixelformat; 2253 + break; 2254 + } 2523 2255 pix->priv = pfmt->priv; /* bpp */ 2524 2256 pix->colorspace = pfmt->colorspace; 2525 - pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) 2257 + pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || 2258 + pix->pixelformat == V4L2_PIX_FMT_JPEG) 2526 2259 ? 0 : (pix->width * pix->priv) / 8; 2527 2260 pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); 2528 2261 pix->field = V4L2_FIELD_NONE; ··· 2608 2315 static int 2609 2316 sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg) 2610 2317 { 2611 - if (copy_to_user(arg, &cam->compression, 2612 - sizeof(cam->compression))) 2318 + if (copy_to_user(arg, &cam->compression, sizeof(cam->compression))) 2613 2319 return -EFAULT; 2614 2320 2615 2321 return 0; ··· 2763 2471 struct sn9c102_frame_t *f; 2764 2472 unsigned long lock_flags; 2765 2473 long timeout; 2474 + int err = 0; 2766 2475 2767 2476 if (copy_from_user(&b, arg, sizeof(b))) 2768 2477 return -EFAULT; ··· 2776 2483 return -EINVAL; 2777 2484 if (filp->f_flags & O_NONBLOCK) 2778 2485 return -EAGAIN; 2486 + if (!cam->module_param.frame_timeout) { 2487 + err = wait_event_interruptible 2488 + ( cam->wait_frame, 2489 + (!list_empty(&cam->outqueue)) || 2490 + (cam->state & DEV_DISCONNECTED) || 2491 + (cam->state & DEV_MISCONFIGURED) ); 2492 + if (err) 2493 + return err; 2494 + } else { 2779 2495 timeout = wait_event_interruptible_timeout 2780 2496 ( cam->wait_frame, 2781 2497 (!list_empty(&cam->outqueue)) || ··· 2794 2492 1000 * msecs_to_jiffies(1) ); 2795 2493 if (timeout < 0) 2796 2494 return timeout; 2495 + else if (timeout == 0 && 2496 + !(cam->state & DEV_DISCONNECTED)) { 2497 + DBG(1, "Video frame timeout elapsed"); 2498 + return -EIO; 2499 + } 2500 + } 2797 2501 if (cam->state & DEV_DISCONNECTED) 2798 2502 return -ENODEV; 2799 - if (!timeout || (cam->state & DEV_MISCONFIGURED)) 2503 + if (cam->state & DEV_MISCONFIGURED) 2800 2504 return -EIO; 2801 2505 } 2802 2506 ··· 2920 2612 } 2921 2613 2922 2614 2615 + static int 2616 + sn9c102_vidioc_enumaudio(struct sn9c102_device* cam, void __user * arg) 2617 + { 2618 + struct v4l2_audio audio; 2619 + 2620 + if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) 2621 + return -EINVAL; 2622 + 2623 + if (copy_from_user(&audio, arg, sizeof(audio))) 2624 + return -EFAULT; 2625 + 2626 + if (audio.index != 0) 2627 + return -EINVAL; 2628 + 2629 + strcpy(audio.name, "Microphone"); 2630 + audio.capability = 0; 2631 + audio.mode = 0; 2632 + 2633 + if (copy_to_user(arg, &audio, sizeof(audio))) 2634 + return -EFAULT; 2635 + 2636 + return 0; 2637 + } 2638 + 2639 + 2640 + static int 2641 + sn9c102_vidioc_g_audio(struct sn9c102_device* cam, void __user * arg) 2642 + { 2643 + struct v4l2_audio audio; 2644 + 2645 + if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) 2646 + return -EINVAL; 2647 + 2648 + if (copy_from_user(&audio, arg, sizeof(audio))) 2649 + return -EFAULT; 2650 + 2651 + memset(&audio, 0, sizeof(audio)); 2652 + strcpy(audio.name, "Microphone"); 2653 + 2654 + if (copy_to_user(arg, &audio, sizeof(audio))) 2655 + return -EFAULT; 2656 + 2657 + return 0; 2658 + } 2659 + 2660 + 2661 + static int 2662 + sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg) 2663 + { 2664 + struct v4l2_audio audio; 2665 + 2666 + if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) 2667 + return -EINVAL; 2668 + 2669 + if (copy_from_user(&audio, arg, sizeof(audio))) 2670 + return -EFAULT; 2671 + 2672 + if (audio.index != 0) 2673 + return -EINVAL; 2674 + 2675 + return 0; 2676 + } 2677 + 2678 + 2923 2679 static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, 2924 2680 unsigned int cmd, void __user * arg) 2925 2681 { ··· 3020 2648 3021 2649 case VIDIOC_S_CROP: 3022 2650 return sn9c102_vidioc_s_crop(cam, arg); 2651 + 2652 + case VIDIOC_ENUM_FRAMESIZES: 2653 + return sn9c102_vidioc_enum_framesizes(cam, arg); 3023 2654 3024 2655 case VIDIOC_ENUM_FMT: 3025 2656 return sn9c102_vidioc_enum_fmt(cam, arg); ··· 3064 2689 case VIDIOC_S_PARM: 3065 2690 return sn9c102_vidioc_s_parm(cam, arg); 3066 2691 2692 + case VIDIOC_ENUMAUDIO: 2693 + return sn9c102_vidioc_enumaudio(cam, arg); 2694 + 2695 + case VIDIOC_G_AUDIO: 2696 + return sn9c102_vidioc_g_audio(cam, arg); 2697 + 2698 + case VIDIOC_S_AUDIO: 2699 + return sn9c102_vidioc_s_audio(cam, arg); 2700 + 3067 2701 case VIDIOC_G_STD: 3068 2702 case VIDIOC_S_STD: 3069 2703 case VIDIOC_QUERYSTD: 3070 2704 case VIDIOC_ENUMSTD: 3071 2705 case VIDIOC_QUERYMENU: 2706 + case VIDIOC_ENUM_FRAMEINTERVALS: 3072 2707 return -EINVAL; 3073 2708 3074 2709 default: ··· 3126 2741 .open = sn9c102_open, 3127 2742 .release = sn9c102_release, 3128 2743 .ioctl = sn9c102_ioctl, 2744 + .compat_ioctl = v4l_compat_ioctl32, 3129 2745 .read = sn9c102_read, 3130 2746 .poll = sn9c102_poll, 3131 2747 .mmap = sn9c102_mmap, ··· 3151 2765 cam->usbdev = udev; 3152 2766 3153 2767 if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { 3154 - DBG(1, "kmalloc() failed"); 2768 + DBG(1, "kzalloc() failed"); 3155 2769 err = -ENOMEM; 3156 2770 goto fail; 3157 2771 } ··· 3165 2779 mutex_init(&cam->dev_mutex); 3166 2780 3167 2781 r = sn9c102_read_reg(cam, 0x00); 3168 - if (r < 0 || r != 0x10) { 3169 - DBG(1, "Sorry, this is not a SN9C10x based camera " 3170 - "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); 2782 + if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) { 2783 + DBG(1, "Sorry, this is not a SN9C1xx based camera " 2784 + "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3171 2785 err = -ENODEV; 3172 2786 goto fail; 3173 2787 } 3174 2788 3175 - cam->bridge = (id->idProduct & 0xffc0) == 0x6080 ? 3176 - BRIDGE_SN9C103 : BRIDGE_SN9C102; 2789 + cam->bridge = id->driver_info; 3177 2790 switch (cam->bridge) { 3178 2791 case BRIDGE_SN9C101: 3179 2792 case BRIDGE_SN9C102: 3180 2793 DBG(2, "SN9C10[12] PC Camera Controller detected " 3181 - "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); 2794 + "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3182 2795 break; 3183 2796 case BRIDGE_SN9C103: 3184 2797 DBG(2, "SN9C103 PC Camera Controller detected " 3185 - "(vid/pid 0x%04X/0x%04X)", id->idVendor, id->idProduct); 2798 + "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 2799 + break; 2800 + case BRIDGE_SN9C105: 2801 + DBG(2, "SN9C105 PC Camera Controller detected " 2802 + "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 2803 + break; 2804 + case BRIDGE_SN9C120: 2805 + DBG(2, "SN9C120 PC Camera Controller detected " 2806 + "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); 3186 2807 break; 3187 2808 } 3188 2809 ··· 3209 2816 goto fail; 3210 2817 } 3211 2818 2819 + if (!(cam->bridge & cam->sensor.supported_bridge)) { 2820 + DBG(1, "Bridge not supported"); 2821 + err = -ENODEV; 2822 + goto fail; 2823 + } 2824 + 3212 2825 if (sn9c102_init(cam)) { 3213 2826 DBG(1, "Initialization failed. I will retry on open()."); 3214 2827 cam->state |= DEV_MISCONFIGURED; 3215 2828 } 3216 2829 3217 - strcpy(cam->v4ldev->name, "SN9C10x PC Camera"); 2830 + strcpy(cam->v4ldev->name, "SN9C1xx PC Camera"); 3218 2831 cam->v4ldev->owner = THIS_MODULE; 3219 2832 cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; 3220 2833 cam->v4ldev->hardware = 0; ··· 3237 2838 DBG(1, "V4L2 device registration failed"); 3238 2839 if (err == -ENFILE && video_nr[dev_nr] == -1) 3239 2840 DBG(1, "Free /dev/videoX node not found"); 3240 - goto fail2; 2841 + video_nr[dev_nr] = -1; 2842 + dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; 2843 + mutex_unlock(&cam->dev_mutex); 2844 + goto fail; 3241 2845 } 3242 2846 3243 2847 DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); ··· 3252 2850 3253 2851 #ifdef CONFIG_VIDEO_ADV_DEBUG 3254 2852 err = sn9c102_create_sysfs(cam); 3255 - if (err) 3256 - goto fail3; 3257 - DBG(2, "Optional device control through 'sysfs' interface ready"); 2853 + if (!err) 2854 + DBG(2, "Optional device control through 'sysfs' " 2855 + "interface ready"); 2856 + else 2857 + DBG(2, "Failed to create optional 'sysfs' interface for " 2858 + "device controlling. Error #%d", err); 2859 + #else 2860 + DBG(2, "Optional device control through 'sysfs' interface disabled"); 3258 2861 #endif 3259 2862 3260 2863 usb_set_intfdata(intf, cam); ··· 3268 2861 3269 2862 return 0; 3270 2863 3271 - #ifdef CONFIG_VIDEO_ADV_DEBUG 3272 - fail3: 3273 - video_unregister_device(cam->v4ldev); 3274 - #endif 3275 - fail2: 3276 - video_nr[dev_nr] = -1; 3277 - dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; 3278 - mutex_unlock(&cam->dev_mutex); 3279 2864 fail: 3280 2865 if (cam) { 3281 2866 kfree(cam->control_buffer);
+142
drivers/media/video/sn9c102/sn9c102_devtable.h
··· 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 + 26 + struct 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 + 41 + static const struct usb_device_id sn9c102_id_table[] = { 42 + /* SN9C101 and SN9C102 */ 43 + { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), }, 44 + { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, 45 + { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, 46 + { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, 47 + { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, 48 + { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, 49 + { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, 50 + { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, 51 + { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, 52 + { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, 53 + { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, 54 + { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, 55 + { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, 56 + { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, 57 + { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, 58 + { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, 59 + { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, 60 + { SN9C102_USB_DEVICE(0x0c45, 0x603f, BRIDGE_SN9C102), }, 61 + /* SN9C103 */ 62 + { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, 63 + { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, 64 + { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, 65 + { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, 66 + { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, 67 + { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, 68 + { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), }, 69 + { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, 70 + { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), }, 71 + { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, 72 + { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, 73 + { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, 74 + { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, 75 + { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, 76 + { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, 77 + { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, 78 + { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, 79 + { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), }, 80 + { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), }, 81 + { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, 82 + { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, 83 + { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, 84 + { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, 85 + { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, 86 + { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, 87 + { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, 88 + /* SN9C105 */ 89 + { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, 90 + { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, 91 + { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, 92 + { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, 93 + { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, 94 + { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, 95 + { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, 96 + { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, 97 + { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), }, 98 + { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), }, 99 + { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), }, 100 + /* SN9C120 */ 101 + { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, 102 + { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, 103 + { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, 104 + { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, 105 + { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, 106 + { } 107 + }; 108 + 109 + /* 110 + Probing functions: on success, you must attach the sensor to the camera 111 + by calling sn9c102_attach_sensor(). 112 + To enable the I2C communication, you might need to perform a really basic 113 + initialization of the SN9C1XX chip. 114 + Functions must return 0 on success, the appropriate error otherwise. 115 + */ 116 + extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); 117 + extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); 118 + extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); 119 + extern int sn9c102_probe_ov7660(struct sn9c102_device* cam); 120 + extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); 121 + extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); 122 + extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); 123 + extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); 124 + 125 + /* 126 + Add the above entries to this table. Be sure to add the entry in the right 127 + place, since, on failure, the next probing routine is called according to 128 + the order of the list below, from top to bottom. 129 + */ 130 + static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { 131 + &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ 132 + &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ 133 + &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ 134 + &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ 135 + &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ 136 + &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ 137 + &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ 138 + &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ 139 + NULL, 140 + }; 141 + 142 + #endif /* _SN9C102_DEVTABLE_H_ */
+4 -3
drivers/media/video/sn9c102/sn9c102_hv7131d.c
··· 1 1 /*************************************************************************** 2 - * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera * 2 + * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera * 3 3 * Controllers * 4 4 * * 5 - * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 + * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * 6 6 * * 7 7 * This program is free software; you can redistribute it and/or modify * 8 8 * it under the terms of the GNU General Public License as published by * ··· 124 124 static int hv7131d_set_crop(struct sn9c102_device* cam, 125 125 const struct v4l2_rect* rect) 126 126 { 127 - struct sn9c102_sensor* s = &hv7131d; 127 + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); 128 128 int err = 0; 129 129 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2, 130 130 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; ··· 153 153 static struct sn9c102_sensor hv7131d = { 154 154 .name = "HV7131D", 155 155 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 156 + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 156 157 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 157 158 .frequency = SN9C102_I2C_100KHZ, 158 159 .interface = SN9C102_I2C_2WIRES,
+4 -3
drivers/media/video/sn9c102/sn9c102_mi0343.c
··· 1 1 /*************************************************************************** 2 - * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera * 2 + * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera * 3 3 * Controllers * 4 4 * * 5 - * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 + * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * 6 6 * * 7 7 * This program is free software; you can redistribute it and/or modify * 8 8 * it under the terms of the GNU General Public License as published by * ··· 201 201 static int mi0343_set_crop(struct sn9c102_device* cam, 202 202 const struct v4l2_rect* rect) 203 203 { 204 - struct sn9c102_sensor* s = &mi0343; 204 + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); 205 205 int err = 0; 206 206 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, 207 207 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2; ··· 237 237 static struct sn9c102_sensor mi0343 = { 238 238 .name = "MI-0343", 239 239 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 240 + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 240 241 .frequency = SN9C102_I2C_100KHZ, 241 242 .interface = SN9C102_I2C_2WIRES, 242 243 .i2c_slave_id = 0x5d,
+211 -153
drivers/media/video/sn9c102/sn9c102_ov7630.c
··· 1 1 /*************************************************************************** 2 - * Plug-in for OV7630 image sensor connected to the SN9C10x PC Camera * 2 + * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera * 3 3 * Controllers * 4 4 * * 5 - * Copyright (C) 2005-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 + * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * 6 6 * * 7 7 * This program is free software; you can redistribute it and/or modify * 8 8 * it under the terms of the GNU General Public License as published by * ··· 29 29 { 30 30 int err = 0; 31 31 32 + switch (sn9c102_get_bridge(cam)) { 33 + case BRIDGE_SN9C101: 34 + case BRIDGE_SN9C102: 32 35 err += sn9c102_write_reg(cam, 0x00, 0x14); 33 36 err += sn9c102_write_reg(cam, 0x60, 0x17); 34 37 err += sn9c102_write_reg(cam, 0x0f, 0x18); 35 38 err += sn9c102_write_reg(cam, 0x50, 0x19); 36 39 37 - err += sn9c102_i2c_write(cam, 0x12, 0x80); 38 - err += sn9c102_i2c_write(cam, 0x11, 0x01); 40 + err += sn9c102_i2c_write(cam, 0x12, 0x8d); 41 + err += sn9c102_i2c_write(cam, 0x12, 0x0d); 42 + err += sn9c102_i2c_write(cam, 0x11, 0x00); 39 43 err += sn9c102_i2c_write(cam, 0x15, 0x34); 40 44 err += sn9c102_i2c_write(cam, 0x16, 0x03); 41 45 err += sn9c102_i2c_write(cam, 0x17, 0x1c); ··· 47 43 err += sn9c102_i2c_write(cam, 0x19, 0x06); 48 44 err += sn9c102_i2c_write(cam, 0x1a, 0xf6); 49 45 err += sn9c102_i2c_write(cam, 0x1b, 0x04); 50 - err += sn9c102_i2c_write(cam, 0x20, 0xf6); 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_reg(cam, 0x00, 0x02); 67 + err += sn9c102_write_reg(cam, 0x00, 0x03); 68 + err += sn9c102_write_reg(cam, 0x1a, 0x04); 69 + err += sn9c102_write_reg(cam, 0x20, 0x05); 70 + err += sn9c102_write_reg(cam, 0x20, 0x06); 71 + err += sn9c102_write_reg(cam, 0x20, 0x07); 72 + err += sn9c102_write_reg(cam, 0x03, 0x10); 73 + err += sn9c102_write_reg(cam, 0x0a, 0x14); 74 + err += sn9c102_write_reg(cam, 0x60, 0x17); 75 + err += sn9c102_write_reg(cam, 0x0f, 0x18); 76 + err += sn9c102_write_reg(cam, 0x50, 0x19); 77 + err += sn9c102_write_reg(cam, 0x1d, 0x1a); 78 + err += sn9c102_write_reg(cam, 0x10, 0x1b); 79 + err += sn9c102_write_reg(cam, 0x02, 0x1c); 80 + err += sn9c102_write_reg(cam, 0x03, 0x1d); 81 + err += sn9c102_write_reg(cam, 0x0f, 0x1e); 82 + err += sn9c102_write_reg(cam, 0x0c, 0x1f); 83 + err += sn9c102_write_reg(cam, 0x00, 0x20); 84 + err += sn9c102_write_reg(cam, 0x10, 0x21); 85 + err += sn9c102_write_reg(cam, 0x20, 0x22); 86 + err += sn9c102_write_reg(cam, 0x30, 0x23); 87 + err += sn9c102_write_reg(cam, 0x40, 0x24); 88 + err += sn9c102_write_reg(cam, 0x50, 0x25); 89 + err += sn9c102_write_reg(cam, 0x60, 0x26); 90 + err += sn9c102_write_reg(cam, 0x70, 0x27); 91 + err += sn9c102_write_reg(cam, 0x80, 0x28); 92 + err += sn9c102_write_reg(cam, 0x90, 0x29); 93 + err += sn9c102_write_reg(cam, 0xa0, 0x2a); 94 + err += sn9c102_write_reg(cam, 0xb0, 0x2b); 95 + err += sn9c102_write_reg(cam, 0xc0, 0x2c); 96 + err += sn9c102_write_reg(cam, 0xd0, 0x2d); 97 + err += sn9c102_write_reg(cam, 0xe0, 0x2e); 98 + err += sn9c102_write_reg(cam, 0xf0, 0x2f); 99 + err += sn9c102_write_reg(cam, 0xff, 0x30); 100 + 101 + err += sn9c102_i2c_write(cam, 0x12, 0x8d); 102 + err += sn9c102_i2c_write(cam, 0x12, 0x0d); 103 + err += sn9c102_i2c_write(cam, 0x15, 0x34); 104 + err += sn9c102_i2c_write(cam, 0x11, 0x01); 105 + err += sn9c102_i2c_write(cam, 0x1b, 0x04); 106 + err += sn9c102_i2c_write(cam, 0x20, 0x44); 51 107 err += sn9c102_i2c_write(cam, 0x23, 0xee); 52 108 err += sn9c102_i2c_write(cam, 0x26, 0xa0); 53 109 err += sn9c102_i2c_write(cam, 0x27, 0x9a); 54 - err += sn9c102_i2c_write(cam, 0x28, 0xa0); 110 + err += sn9c102_i2c_write(cam, 0x28, 0x20); 55 111 err += sn9c102_i2c_write(cam, 0x29, 0x30); 56 - err += sn9c102_i2c_write(cam, 0x2a, 0xa0); 57 - err += sn9c102_i2c_write(cam, 0x2b, 0x1f); 58 112 err += sn9c102_i2c_write(cam, 0x2f, 0x3d); 59 113 err += sn9c102_i2c_write(cam, 0x30, 0x24); 60 114 err += sn9c102_i2c_write(cam, 0x32, 0x86); ··· 125 63 err += sn9c102_i2c_write(cam, 0x71, 0x00); 126 64 err += sn9c102_i2c_write(cam, 0x74, 0x21); 127 65 err += sn9c102_i2c_write(cam, 0x7d, 0xf7); 66 + break; 67 + default: 68 + break; 69 + } 128 70 129 71 return err; 72 + } 73 + 74 + 75 + static int ov7630_get_ctrl(struct sn9c102_device* cam, 76 + struct v4l2_control* ctrl) 77 + { 78 + int err = 0; 79 + 80 + switch (ctrl->id) { 81 + case V4L2_CID_EXPOSURE: 82 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0) 83 + return -EIO; 84 + break; 85 + case V4L2_CID_RED_BALANCE: 86 + ctrl->value = sn9c102_pread_reg(cam, 0x07); 87 + break; 88 + case V4L2_CID_BLUE_BALANCE: 89 + ctrl->value = sn9c102_pread_reg(cam, 0x06); 90 + break; 91 + case SN9C102_V4L2_CID_GREEN_BALANCE: 92 + ctrl->value = sn9c102_pread_reg(cam, 0x05); 93 + break; 94 + case V4L2_CID_GAIN: 95 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0) 96 + return -EIO; 97 + ctrl->value &= 0x3f; 98 + break; 99 + case V4L2_CID_DO_WHITE_BALANCE: 100 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0) 101 + return -EIO; 102 + ctrl->value &= 0x3f; 103 + break; 104 + case V4L2_CID_WHITENESS: 105 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0) 106 + return -EIO; 107 + ctrl->value &= 0x3f; 108 + break; 109 + case V4L2_CID_AUTOGAIN: 110 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0) 111 + return -EIO; 112 + ctrl->value &= 0x01; 113 + break; 114 + case V4L2_CID_VFLIP: 115 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x75)) < 0) 116 + return -EIO; 117 + ctrl->value = (ctrl->value & 0x80) ? 1 : 0; 118 + break; 119 + case SN9C102_V4L2_CID_GAMMA: 120 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x14)) < 0) 121 + return -EIO; 122 + ctrl->value = (ctrl->value & 0x02) ? 1 : 0; 123 + break; 124 + case SN9C102_V4L2_CID_BAND_FILTER: 125 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x2d)) < 0) 126 + return -EIO; 127 + ctrl->value = (ctrl->value & 0x02) ? 1 : 0; 128 + break; 129 + default: 130 + return -EINVAL; 131 + } 132 + 133 + return err ? -EIO : 0; 130 134 } 131 135 132 136 ··· 203 75 204 76 switch (ctrl->id) { 205 77 case V4L2_CID_EXPOSURE: 206 - err += sn9c102_i2c_write(cam, 0x10, ctrl->value >> 2); 207 - err += sn9c102_i2c_write(cam, 0x76, ctrl->value & 0x03); 78 + err += sn9c102_i2c_write(cam, 0x10, ctrl->value); 208 79 break; 209 80 case V4L2_CID_RED_BALANCE: 210 - err += sn9c102_i2c_write(cam, 0x02, ctrl->value); 81 + err += sn9c102_write_reg(cam, ctrl->value, 0x07); 211 82 break; 212 83 case V4L2_CID_BLUE_BALANCE: 213 - err += sn9c102_i2c_write(cam, 0x01, ctrl->value); 84 + err += sn9c102_write_reg(cam, ctrl->value, 0x06); 85 + break; 86 + case SN9C102_V4L2_CID_GREEN_BALANCE: 87 + err += sn9c102_write_reg(cam, ctrl->value, 0x05); 214 88 break; 215 89 case V4L2_CID_GAIN: 216 90 err += sn9c102_i2c_write(cam, 0x00, ctrl->value); 217 - break; 218 - case V4L2_CID_CONTRAST: 219 - err += ctrl->value ? sn9c102_i2c_write(cam, 0x05, 220 - (ctrl->value-1) | 0x20) 221 - : sn9c102_i2c_write(cam, 0x05, 0x00); 222 - break; 223 - case V4L2_CID_BRIGHTNESS: 224 - err += sn9c102_i2c_write(cam, 0x06, ctrl->value); 225 - break; 226 - case V4L2_CID_SATURATION: 227 - err += sn9c102_i2c_write(cam, 0x03, ctrl->value << 4); 228 - break; 229 - case V4L2_CID_HUE: 230 - err += ctrl->value ? sn9c102_i2c_write(cam, 0x04, 231 - (ctrl->value-1) | 0x20) 232 - : sn9c102_i2c_write(cam, 0x04, 0x00); 233 91 break; 234 92 case V4L2_CID_DO_WHITE_BALANCE: 235 93 err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); ··· 223 109 case V4L2_CID_WHITENESS: 224 110 err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); 225 111 break; 226 - case V4L2_CID_AUTO_WHITE_BALANCE: 227 - err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78); 228 - break; 229 112 case V4L2_CID_AUTOGAIN: 230 - err += sn9c102_i2c_write(cam, 0x13, ctrl->value); 113 + err += sn9c102_i2c_write(cam, 0x13, ctrl->value | 114 + (ctrl->value << 1)); 231 115 break; 232 116 case V4L2_CID_VFLIP: 233 117 err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7)); 234 118 break; 235 - case V4L2_CID_BLACK_LEVEL: 236 - err += sn9c102_i2c_write(cam, 0x25, ctrl->value); 237 - break; 238 - case SN9C102_V4L2_CID_BRIGHT_LEVEL: 239 - err += sn9c102_i2c_write(cam, 0x24, ctrl->value); 240 - break; 241 119 case SN9C102_V4L2_CID_GAMMA: 242 - err += sn9c102_i2c_write(cam, 0x14, (ctrl->value << 2) | 0x80); 120 + err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2); 243 121 break; 244 122 case SN9C102_V4L2_CID_BAND_FILTER: 245 123 err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2); ··· 247 141 static int ov7630_set_crop(struct sn9c102_device* cam, 248 142 const struct v4l2_rect* rect) 249 143 { 250 - struct sn9c102_sensor* s = &ov7630; 144 + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); 251 145 int err = 0; 252 - u8 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; 146 + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1, 147 + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; 253 148 149 + err += sn9c102_write_reg(cam, h_start, 0x12); 254 150 err += sn9c102_write_reg(cam, v_start, 0x13); 255 151 256 152 return err; ··· 276 168 static struct sn9c102_sensor ov7630 = { 277 169 .name = "OV7630", 278 170 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 279 - .sysfs_ops = SN9C102_I2C_WRITE, 171 + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 172 + .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 280 173 .frequency = SN9C102_I2C_100KHZ, 281 174 .interface = SN9C102_I2C_2WIRES, 282 175 .i2c_slave_id = 0x21, ··· 294 185 .flags = 0, 295 186 }, 296 187 { 297 - .id = V4L2_CID_HUE, 298 - .type = V4L2_CTRL_TYPE_INTEGER, 299 - .name = "hue", 300 - .minimum = 0x00, 301 - .maximum = 0x1f+1, 302 - .step = 0x01, 303 - .default_value = 0x00, 304 - .flags = 0, 305 - }, 306 - { 307 - .id = V4L2_CID_SATURATION, 308 - .type = V4L2_CTRL_TYPE_INTEGER, 309 - .name = "saturation", 310 - .minimum = 0x00, 311 - .maximum = 0x0f, 312 - .step = 0x01, 313 - .default_value = 0x08, 314 - .flags = 0, 315 - }, 316 - { 317 - .id = V4L2_CID_CONTRAST, 318 - .type = V4L2_CTRL_TYPE_INTEGER, 319 - .name = "contrast", 320 - .minimum = 0x00, 321 - .maximum = 0x1f+1, 322 - .step = 0x01, 323 - .default_value = 0x00, 324 - .flags = 0, 325 - }, 326 - { 327 188 .id = V4L2_CID_EXPOSURE, 328 189 .type = V4L2_CTRL_TYPE_INTEGER, 329 190 .name = "exposure", 330 - .minimum = 0x000, 331 - .maximum = 0x3ff, 332 - .step = 0x001, 333 - .default_value = 0x83<<2, 334 - .flags = 0, 335 - }, 336 - { 337 - .id = V4L2_CID_RED_BALANCE, 338 - .type = V4L2_CTRL_TYPE_INTEGER, 339 - .name = "red balance", 340 191 .minimum = 0x00, 341 192 .maximum = 0xff, 342 193 .step = 0x01, 343 - .default_value = 0x3a, 344 - .flags = 0, 345 - }, 346 - { 347 - .id = V4L2_CID_BLUE_BALANCE, 348 - .type = V4L2_CTRL_TYPE_INTEGER, 349 - .name = "blue balance", 350 - .minimum = 0x00, 351 - .maximum = 0xff, 352 - .step = 0x01, 353 - .default_value = 0x77, 354 - .flags = 0, 355 - }, 356 - { 357 - .id = V4L2_CID_BRIGHTNESS, 358 - .type = V4L2_CTRL_TYPE_INTEGER, 359 - .name = "brightness", 360 - .minimum = 0x00, 361 - .maximum = 0xff, 362 - .step = 0x01, 363 - .default_value = 0xa0, 364 - .flags = 0, 365 - }, 366 - { 367 - .id = V4L2_CID_DO_WHITE_BALANCE, 368 - .type = V4L2_CTRL_TYPE_INTEGER, 369 - .name = "white balance background: blue", 370 - .minimum = 0x00, 371 - .maximum = 0x3f, 372 - .step = 0x01, 373 - .default_value = 0x20, 194 + .default_value = 0x60, 374 195 .flags = 0, 375 196 }, 376 197 { ··· 314 275 .flags = 0, 315 276 }, 316 277 { 317 - .id = V4L2_CID_AUTO_WHITE_BALANCE, 318 - .type = V4L2_CTRL_TYPE_BOOLEAN, 319 - .name = "auto white balance", 278 + .id = V4L2_CID_DO_WHITE_BALANCE, 279 + .type = V4L2_CTRL_TYPE_INTEGER, 280 + .name = "white balance background: blue", 320 281 .minimum = 0x00, 321 - .maximum = 0x01, 282 + .maximum = 0x3f, 322 283 .step = 0x01, 323 - .default_value = 0x01, 284 + .default_value = 0x20, 285 + .flags = 0, 286 + }, 287 + { 288 + .id = V4L2_CID_RED_BALANCE, 289 + .type = V4L2_CTRL_TYPE_INTEGER, 290 + .name = "red balance", 291 + .minimum = 0x00, 292 + .maximum = 0x7f, 293 + .step = 0x01, 294 + .default_value = 0x20, 295 + .flags = 0, 296 + }, 297 + { 298 + .id = V4L2_CID_BLUE_BALANCE, 299 + .type = V4L2_CTRL_TYPE_INTEGER, 300 + .name = "blue balance", 301 + .minimum = 0x00, 302 + .maximum = 0x7f, 303 + .step = 0x01, 304 + .default_value = 0x20, 324 305 .flags = 0, 325 306 }, 326 307 { 327 308 .id = V4L2_CID_AUTOGAIN, 328 - .type = V4L2_CTRL_TYPE_INTEGER, 329 - .name = "gain & exposure mode", 309 + .type = V4L2_CTRL_TYPE_BOOLEAN, 310 + .name = "auto adjust", 330 311 .minimum = 0x00, 331 - .maximum = 0x03, 312 + .maximum = 0x01, 332 313 .step = 0x01, 333 314 .default_value = 0x00, 334 315 .flags = 0, ··· 364 305 .flags = 0, 365 306 }, 366 307 { 367 - .id = V4L2_CID_BLACK_LEVEL, 308 + .id = SN9C102_V4L2_CID_GREEN_BALANCE, 368 309 .type = V4L2_CTRL_TYPE_INTEGER, 369 - .name = "black pixel ratio", 370 - .minimum = 0x01, 371 - .maximum = 0x9a, 310 + .name = "green balance", 311 + .minimum = 0x00, 312 + .maximum = 0x7f, 372 313 .step = 0x01, 373 - .default_value = 0x8a, 374 - .flags = 0, 375 - }, 376 - { 377 - .id = SN9C102_V4L2_CID_BRIGHT_LEVEL, 378 - .type = V4L2_CTRL_TYPE_INTEGER, 379 - .name = "bright pixel ratio", 380 - .minimum = 0x01, 381 - .maximum = 0x9a, 382 - .step = 0x01, 383 - .default_value = 0x10, 314 + .default_value = 0x20, 384 315 .flags = 0, 385 316 }, 386 317 { ··· 394 345 .flags = 0, 395 346 }, 396 347 }, 348 + .get_ctrl = &ov7630_get_ctrl, 397 349 .set_ctrl = &ov7630_set_ctrl, 398 350 .cropcap = { 399 351 .bounds = { ··· 414 364 .pix_format = { 415 365 .width = 640, 416 366 .height = 480, 417 - .pixelformat = V4L2_PIX_FMT_SBGGR8, 367 + .pixelformat = V4L2_PIX_FMT_SN9C10X, 418 368 .priv = 8, 419 369 }, 420 370 .set_pix_format = &ov7630_set_pix_format ··· 423 373 424 374 int sn9c102_probe_ov7630(struct sn9c102_device* cam) 425 375 { 426 - const struct usb_device_id ov7630_id_table[] = { 427 - { USB_DEVICE(0x0c45, 0x602c), }, 428 - { USB_DEVICE(0x0c45, 0x602d), }, 429 - { USB_DEVICE(0x0c45, 0x608f), }, 430 - { USB_DEVICE(0x0c45, 0x60b0), }, 431 - { } 432 - }; 433 - int err = 0; 376 + int pid, ver, err = 0; 434 377 435 - if (!sn9c102_match_id(cam, ov7630_id_table)) 436 - return -ENODEV; 437 - 378 + switch (sn9c102_get_bridge(cam)) { 379 + case BRIDGE_SN9C101: 380 + case BRIDGE_SN9C102: 438 381 err += sn9c102_write_reg(cam, 0x01, 0x01); 439 382 err += sn9c102_write_reg(cam, 0x00, 0x01); 440 383 err += sn9c102_write_reg(cam, 0x28, 0x17); 441 - if (err) 384 + break; 385 + case BRIDGE_SN9C103: /* do _not_ change anything! */ 386 + err += sn9c102_write_reg(cam, 0x09, 0x01); 387 + err += sn9c102_write_reg(cam, 0x42, 0x01); 388 + err += sn9c102_write_reg(cam, 0x28, 0x17); 389 + err += sn9c102_write_reg(cam, 0x44, 0x02); 390 + pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); 391 + if (err || pid < 0) { /* try a different initialization */ 392 + err = sn9c102_write_reg(cam, 0x01, 0x01); 393 + err += sn9c102_write_reg(cam, 0x00, 0x01); 394 + } 395 + break; 396 + default: 397 + break; 398 + } 399 + 400 + pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); 401 + ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b); 402 + if (err || pid < 0 || ver < 0) 442 403 return -EIO; 443 - 444 - err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0); 445 - if (err) 404 + if (pid != 0x76 || ver != 0x31) 446 405 return -ENODEV; 447 - 448 406 sn9c102_attach_sensor(cam, &ov7630); 449 407 450 408 return 0;
+592
drivers/media/video/sn9c102/sn9c102_ov7660.c
··· 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 + 24 + 25 + static struct sn9c102_sensor ov7660; 26 + 27 + 28 + static int ov7660_init(struct sn9c102_device* cam) 29 + { 30 + int err = 0; 31 + 32 + err += sn9c102_write_reg(cam, 0x40, 0x02); 33 + err += sn9c102_write_reg(cam, 0x00, 0x03); 34 + err += sn9c102_write_reg(cam, 0x1a, 0x04); 35 + err += sn9c102_write_reg(cam, 0x03, 0x10); 36 + err += sn9c102_write_reg(cam, 0x08, 0x14); 37 + err += sn9c102_write_reg(cam, 0x20, 0x17); 38 + err += sn9c102_write_reg(cam, 0x8b, 0x18); 39 + err += sn9c102_write_reg(cam, 0x00, 0x19); 40 + err += sn9c102_write_reg(cam, 0x1d, 0x1a); 41 + err += sn9c102_write_reg(cam, 0x10, 0x1b); 42 + err += sn9c102_write_reg(cam, 0x02, 0x1c); 43 + err += sn9c102_write_reg(cam, 0x03, 0x1d); 44 + err += sn9c102_write_reg(cam, 0x0f, 0x1e); 45 + err += sn9c102_write_reg(cam, 0x0c, 0x1f); 46 + err += sn9c102_write_reg(cam, 0x00, 0x20); 47 + err += sn9c102_write_reg(cam, 0x29, 0x21); 48 + err += sn9c102_write_reg(cam, 0x40, 0x22); 49 + err += sn9c102_write_reg(cam, 0x54, 0x23); 50 + err += sn9c102_write_reg(cam, 0x66, 0x24); 51 + err += sn9c102_write_reg(cam, 0x76, 0x25); 52 + err += sn9c102_write_reg(cam, 0x85, 0x26); 53 + err += sn9c102_write_reg(cam, 0x94, 0x27); 54 + err += sn9c102_write_reg(cam, 0xa1, 0x28); 55 + err += sn9c102_write_reg(cam, 0xae, 0x29); 56 + err += sn9c102_write_reg(cam, 0xbb, 0x2a); 57 + err += sn9c102_write_reg(cam, 0xc7, 0x2b); 58 + err += sn9c102_write_reg(cam, 0xd3, 0x2c); 59 + err += sn9c102_write_reg(cam, 0xde, 0x2d); 60 + err += sn9c102_write_reg(cam, 0xea, 0x2e); 61 + err += sn9c102_write_reg(cam, 0xf4, 0x2f); 62 + err += sn9c102_write_reg(cam, 0xff, 0x30); 63 + err += sn9c102_write_reg(cam, 0x00, 0x3F); 64 + err += sn9c102_write_reg(cam, 0xC7, 0x40); 65 + err += sn9c102_write_reg(cam, 0x01, 0x41); 66 + err += sn9c102_write_reg(cam, 0x44, 0x42); 67 + err += sn9c102_write_reg(cam, 0x00, 0x43); 68 + err += sn9c102_write_reg(cam, 0x44, 0x44); 69 + err += sn9c102_write_reg(cam, 0x00, 0x45); 70 + err += sn9c102_write_reg(cam, 0x44, 0x46); 71 + err += sn9c102_write_reg(cam, 0x00, 0x47); 72 + err += sn9c102_write_reg(cam, 0xC7, 0x48); 73 + err += sn9c102_write_reg(cam, 0x01, 0x49); 74 + err += sn9c102_write_reg(cam, 0xC7, 0x4A); 75 + err += sn9c102_write_reg(cam, 0x01, 0x4B); 76 + err += sn9c102_write_reg(cam, 0xC7, 0x4C); 77 + err += sn9c102_write_reg(cam, 0x01, 0x4D); 78 + err += sn9c102_write_reg(cam, 0x44, 0x4E); 79 + err += sn9c102_write_reg(cam, 0x00, 0x4F); 80 + err += sn9c102_write_reg(cam, 0x44, 0x50); 81 + err += sn9c102_write_reg(cam, 0x00, 0x51); 82 + err += sn9c102_write_reg(cam, 0x44, 0x52); 83 + err += sn9c102_write_reg(cam, 0x00, 0x53); 84 + err += sn9c102_write_reg(cam, 0xC7, 0x54); 85 + err += sn9c102_write_reg(cam, 0x01, 0x55); 86 + err += sn9c102_write_reg(cam, 0xC7, 0x56); 87 + err += sn9c102_write_reg(cam, 0x01, 0x57); 88 + err += sn9c102_write_reg(cam, 0xC7, 0x58); 89 + err += sn9c102_write_reg(cam, 0x01, 0x59); 90 + err += sn9c102_write_reg(cam, 0x44, 0x5A); 91 + err += sn9c102_write_reg(cam, 0x00, 0x5B); 92 + err += sn9c102_write_reg(cam, 0x44, 0x5C); 93 + err += sn9c102_write_reg(cam, 0x00, 0x5D); 94 + err += sn9c102_write_reg(cam, 0x44, 0x5E); 95 + err += sn9c102_write_reg(cam, 0x00, 0x5F); 96 + err += sn9c102_write_reg(cam, 0xC7, 0x60); 97 + err += sn9c102_write_reg(cam, 0x01, 0x61); 98 + err += sn9c102_write_reg(cam, 0xC7, 0x62); 99 + err += sn9c102_write_reg(cam, 0x01, 0x63); 100 + err += sn9c102_write_reg(cam, 0xC7, 0x64); 101 + err += sn9c102_write_reg(cam, 0x01, 0x65); 102 + err += sn9c102_write_reg(cam, 0x44, 0x66); 103 + err += sn9c102_write_reg(cam, 0x00, 0x67); 104 + err += sn9c102_write_reg(cam, 0x44, 0x68); 105 + err += sn9c102_write_reg(cam, 0x00, 0x69); 106 + err += sn9c102_write_reg(cam, 0x44, 0x6A); 107 + err += sn9c102_write_reg(cam, 0x00, 0x6B); 108 + err += sn9c102_write_reg(cam, 0xC7, 0x6C); 109 + err += sn9c102_write_reg(cam, 0x01, 0x6D); 110 + err += sn9c102_write_reg(cam, 0xC7, 0x6E); 111 + err += sn9c102_write_reg(cam, 0x01, 0x6F); 112 + err += sn9c102_write_reg(cam, 0xC7, 0x70); 113 + err += sn9c102_write_reg(cam, 0x01, 0x71); 114 + err += sn9c102_write_reg(cam, 0x44, 0x72); 115 + err += sn9c102_write_reg(cam, 0x00, 0x73); 116 + err += sn9c102_write_reg(cam, 0x44, 0x74); 117 + err += sn9c102_write_reg(cam, 0x00, 0x75); 118 + err += sn9c102_write_reg(cam, 0x44, 0x76); 119 + err += sn9c102_write_reg(cam, 0x00, 0x77); 120 + err += sn9c102_write_reg(cam, 0xC7, 0x78); 121 + err += sn9c102_write_reg(cam, 0x01, 0x79); 122 + err += sn9c102_write_reg(cam, 0xC7, 0x7A); 123 + err += sn9c102_write_reg(cam, 0x01, 0x7B); 124 + err += sn9c102_write_reg(cam, 0xC7, 0x7C); 125 + err += sn9c102_write_reg(cam, 0x01, 0x7D); 126 + err += sn9c102_write_reg(cam, 0x44, 0x7E); 127 + err += sn9c102_write_reg(cam, 0x00, 0x7F); 128 + err += sn9c102_write_reg(cam, 0x14, 0x84); 129 + err += sn9c102_write_reg(cam, 0x00, 0x85); 130 + err += sn9c102_write_reg(cam, 0x27, 0x86); 131 + err += sn9c102_write_reg(cam, 0x00, 0x87); 132 + err += sn9c102_write_reg(cam, 0x07, 0x88); 133 + err += sn9c102_write_reg(cam, 0x00, 0x89); 134 + err += sn9c102_write_reg(cam, 0xEC, 0x8A); 135 + err += sn9c102_write_reg(cam, 0x0f, 0x8B); 136 + err += sn9c102_write_reg(cam, 0xD8, 0x8C); 137 + err += sn9c102_write_reg(cam, 0x0f, 0x8D); 138 + err += sn9c102_write_reg(cam, 0x3D, 0x8E); 139 + err += sn9c102_write_reg(cam, 0x00, 0x8F); 140 + err += sn9c102_write_reg(cam, 0x3D, 0x90); 141 + err += sn9c102_write_reg(cam, 0x00, 0x91); 142 + err += sn9c102_write_reg(cam, 0xCD, 0x92); 143 + err += sn9c102_write_reg(cam, 0x0f, 0x93); 144 + err += sn9c102_write_reg(cam, 0xf7, 0x94); 145 + err += sn9c102_write_reg(cam, 0x0f, 0x95); 146 + err += sn9c102_write_reg(cam, 0x0C, 0x96); 147 + err += sn9c102_write_reg(cam, 0x00, 0x97); 148 + err += sn9c102_write_reg(cam, 0x00, 0x98); 149 + err += sn9c102_write_reg(cam, 0x66, 0x99); 150 + err += sn9c102_write_reg(cam, 0x05, 0x9A); 151 + err += sn9c102_write_reg(cam, 0x00, 0x9B); 152 + err += sn9c102_write_reg(cam, 0x04, 0x9C); 153 + err += sn9c102_write_reg(cam, 0x00, 0x9D); 154 + err += sn9c102_write_reg(cam, 0x08, 0x9E); 155 + err += sn9c102_write_reg(cam, 0x00, 0x9F); 156 + err += sn9c102_write_reg(cam, 0x2D, 0xC0); 157 + err += sn9c102_write_reg(cam, 0x2D, 0xC1); 158 + err += sn9c102_write_reg(cam, 0x3A, 0xC2); 159 + err += sn9c102_write_reg(cam, 0x05, 0xC3); 160 + err += sn9c102_write_reg(cam, 0x04, 0xC4); 161 + err += sn9c102_write_reg(cam, 0x3F, 0xC5); 162 + err += sn9c102_write_reg(cam, 0x00, 0xC6); 163 + err += sn9c102_write_reg(cam, 0x00, 0xC7); 164 + err += sn9c102_write_reg(cam, 0x50, 0xC8); 165 + err += sn9c102_write_reg(cam, 0x3C, 0xC9); 166 + err += sn9c102_write_reg(cam, 0x28, 0xCA); 167 + err += sn9c102_write_reg(cam, 0xD8, 0xCB); 168 + err += sn9c102_write_reg(cam, 0x14, 0xCC); 169 + err += sn9c102_write_reg(cam, 0xEC, 0xCD); 170 + err += sn9c102_write_reg(cam, 0x32, 0xCE); 171 + err += sn9c102_write_reg(cam, 0xDD, 0xCF); 172 + err += sn9c102_write_reg(cam, 0x32, 0xD0); 173 + err += sn9c102_write_reg(cam, 0xDD, 0xD1); 174 + err += sn9c102_write_reg(cam, 0x6A, 0xD2); 175 + err += sn9c102_write_reg(cam, 0x50, 0xD3); 176 + err += sn9c102_write_reg(cam, 0x00, 0xD4); 177 + err += sn9c102_write_reg(cam, 0x00, 0xD5); 178 + err += sn9c102_write_reg(cam, 0x00, 0xD6); 179 + 180 + err += sn9c102_i2c_write(cam, 0x12, 0x80); 181 + err += sn9c102_i2c_write(cam, 0x11, 0x09); 182 + err += sn9c102_i2c_write(cam, 0x00, 0x0A); 183 + err += sn9c102_i2c_write(cam, 0x01, 0x78); 184 + err += sn9c102_i2c_write(cam, 0x02, 0x90); 185 + err += sn9c102_i2c_write(cam, 0x03, 0x00); 186 + err += sn9c102_i2c_write(cam, 0x04, 0x00); 187 + err += sn9c102_i2c_write(cam, 0x05, 0x08); 188 + err += sn9c102_i2c_write(cam, 0x06, 0x0B); 189 + err += sn9c102_i2c_write(cam, 0x07, 0x00); 190 + err += sn9c102_i2c_write(cam, 0x08, 0x1C); 191 + err += sn9c102_i2c_write(cam, 0x09, 0x01); 192 + err += sn9c102_i2c_write(cam, 0x0A, 0x76); 193 + err += sn9c102_i2c_write(cam, 0x0B, 0x60); 194 + err += sn9c102_i2c_write(cam, 0x0C, 0x00); 195 + err += sn9c102_i2c_write(cam, 0x0D, 0x08); 196 + err += sn9c102_i2c_write(cam, 0x0E, 0x04); 197 + err += sn9c102_i2c_write(cam, 0x0F, 0x6F); 198 + err += sn9c102_i2c_write(cam, 0x10, 0x20); 199 + err += sn9c102_i2c_write(cam, 0x11, 0x03); 200 + err += sn9c102_i2c_write(cam, 0x12, 0x05); 201 + err += sn9c102_i2c_write(cam, 0x13, 0xF8); 202 + err += sn9c102_i2c_write(cam, 0x14, 0x2C); 203 + err += sn9c102_i2c_write(cam, 0x15, 0x00); 204 + err += sn9c102_i2c_write(cam, 0x16, 0x02); 205 + err += sn9c102_i2c_write(cam, 0x17, 0x10); 206 + err += sn9c102_i2c_write(cam, 0x18, 0x60); 207 + err += sn9c102_i2c_write(cam, 0x19, 0x02); 208 + err += sn9c102_i2c_write(cam, 0x1A, 0x7B); 209 + err += sn9c102_i2c_write(cam, 0x1B, 0x02); 210 + err += sn9c102_i2c_write(cam, 0x1C, 0x7F); 211 + err += sn9c102_i2c_write(cam, 0x1D, 0xA2); 212 + err += sn9c102_i2c_write(cam, 0x1E, 0x01); 213 + err += sn9c102_i2c_write(cam, 0x1F, 0x0E); 214 + err += sn9c102_i2c_write(cam, 0x20, 0x05); 215 + err += sn9c102_i2c_write(cam, 0x21, 0x05); 216 + err += sn9c102_i2c_write(cam, 0x22, 0x05); 217 + err += sn9c102_i2c_write(cam, 0x23, 0x05); 218 + err += sn9c102_i2c_write(cam, 0x24, 0x68); 219 + err += sn9c102_i2c_write(cam, 0x25, 0x58); 220 + err += sn9c102_i2c_write(cam, 0x26, 0xD4); 221 + err += sn9c102_i2c_write(cam, 0x27, 0x80); 222 + err += sn9c102_i2c_write(cam, 0x28, 0x80); 223 + err += sn9c102_i2c_write(cam, 0x29, 0x30); 224 + err += sn9c102_i2c_write(cam, 0x2A, 0x00); 225 + err += sn9c102_i2c_write(cam, 0x2B, 0x00); 226 + err += sn9c102_i2c_write(cam, 0x2C, 0x80); 227 + err += sn9c102_i2c_write(cam, 0x2D, 0x00); 228 + err += sn9c102_i2c_write(cam, 0x2E, 0x00); 229 + err += sn9c102_i2c_write(cam, 0x2F, 0x0E); 230 + err += sn9c102_i2c_write(cam, 0x30, 0x08); 231 + err += sn9c102_i2c_write(cam, 0x31, 0x30); 232 + err += sn9c102_i2c_write(cam, 0x32, 0xB4); 233 + err += sn9c102_i2c_write(cam, 0x33, 0x00); 234 + err += sn9c102_i2c_write(cam, 0x34, 0x07); 235 + err += sn9c102_i2c_write(cam, 0x35, 0x84); 236 + err += sn9c102_i2c_write(cam, 0x36, 0x00); 237 + err += sn9c102_i2c_write(cam, 0x37, 0x0C); 238 + err += sn9c102_i2c_write(cam, 0x38, 0x02); 239 + err += sn9c102_i2c_write(cam, 0x39, 0x43); 240 + err += sn9c102_i2c_write(cam, 0x3A, 0x00); 241 + err += sn9c102_i2c_write(cam, 0x3B, 0x02); 242 + err += sn9c102_i2c_write(cam, 0x3C, 0x6C); 243 + err += sn9c102_i2c_write(cam, 0x3D, 0x99); 244 + err += sn9c102_i2c_write(cam, 0x3E, 0x0E); 245 + err += sn9c102_i2c_write(cam, 0x3F, 0x41); 246 + err += sn9c102_i2c_write(cam, 0x40, 0xC1); 247 + err += sn9c102_i2c_write(cam, 0x41, 0x22); 248 + err += sn9c102_i2c_write(cam, 0x42, 0x08); 249 + err += sn9c102_i2c_write(cam, 0x43, 0xF0); 250 + err += sn9c102_i2c_write(cam, 0x44, 0x10); 251 + err += sn9c102_i2c_write(cam, 0x45, 0x78); 252 + err += sn9c102_i2c_write(cam, 0x46, 0xA8); 253 + err += sn9c102_i2c_write(cam, 0x47, 0x60); 254 + err += sn9c102_i2c_write(cam, 0x48, 0x80); 255 + err += sn9c102_i2c_write(cam, 0x49, 0x00); 256 + err += sn9c102_i2c_write(cam, 0x4A, 0x00); 257 + err += sn9c102_i2c_write(cam, 0x4B, 0x00); 258 + err += sn9c102_i2c_write(cam, 0x4C, 0x00); 259 + err += sn9c102_i2c_write(cam, 0x4D, 0x00); 260 + err += sn9c102_i2c_write(cam, 0x4E, 0x00); 261 + err += sn9c102_i2c_write(cam, 0x4F, 0x46); 262 + err += sn9c102_i2c_write(cam, 0x50, 0x36); 263 + err += sn9c102_i2c_write(cam, 0x51, 0x0F); 264 + err += sn9c102_i2c_write(cam, 0x52, 0x17); 265 + err += sn9c102_i2c_write(cam, 0x53, 0x7F); 266 + err += sn9c102_i2c_write(cam, 0x54, 0x96); 267 + err += sn9c102_i2c_write(cam, 0x55, 0x40); 268 + err += sn9c102_i2c_write(cam, 0x56, 0x40); 269 + err += sn9c102_i2c_write(cam, 0x57, 0x40); 270 + err += sn9c102_i2c_write(cam, 0x58, 0x0F); 271 + err += sn9c102_i2c_write(cam, 0x59, 0xBA); 272 + err += sn9c102_i2c_write(cam, 0x5A, 0x9A); 273 + err += sn9c102_i2c_write(cam, 0x5B, 0x22); 274 + err += sn9c102_i2c_write(cam, 0x5C, 0xB9); 275 + err += sn9c102_i2c_write(cam, 0x5D, 0x9B); 276 + err += sn9c102_i2c_write(cam, 0x5E, 0x10); 277 + err += sn9c102_i2c_write(cam, 0x5F, 0xF0); 278 + err += sn9c102_i2c_write(cam, 0x60, 0x05); 279 + err += sn9c102_i2c_write(cam, 0x61, 0x60); 280 + err += sn9c102_i2c_write(cam, 0x62, 0x00); 281 + err += sn9c102_i2c_write(cam, 0x63, 0x00); 282 + err += sn9c102_i2c_write(cam, 0x64, 0x50); 283 + err += sn9c102_i2c_write(cam, 0x65, 0x30); 284 + err += sn9c102_i2c_write(cam, 0x66, 0x00); 285 + err += sn9c102_i2c_write(cam, 0x67, 0x80); 286 + err += sn9c102_i2c_write(cam, 0x68, 0x7A); 287 + err += sn9c102_i2c_write(cam, 0x69, 0x90); 288 + err += sn9c102_i2c_write(cam, 0x6A, 0x80); 289 + err += sn9c102_i2c_write(cam, 0x6B, 0x0A); 290 + err += sn9c102_i2c_write(cam, 0x6C, 0x30); 291 + err += sn9c102_i2c_write(cam, 0x6D, 0x48); 292 + err += sn9c102_i2c_write(cam, 0x6E, 0x80); 293 + err += sn9c102_i2c_write(cam, 0x6F, 0x74); 294 + err += sn9c102_i2c_write(cam, 0x70, 0x64); 295 + err += sn9c102_i2c_write(cam, 0x71, 0x60); 296 + err += sn9c102_i2c_write(cam, 0x72, 0x5C); 297 + err += sn9c102_i2c_write(cam, 0x73, 0x58); 298 + err += sn9c102_i2c_write(cam, 0x74, 0x54); 299 + err += sn9c102_i2c_write(cam, 0x75, 0x4C); 300 + err += sn9c102_i2c_write(cam, 0x76, 0x40); 301 + err += sn9c102_i2c_write(cam, 0x77, 0x38); 302 + err += sn9c102_i2c_write(cam, 0x78, 0x34); 303 + err += sn9c102_i2c_write(cam, 0x79, 0x30); 304 + err += sn9c102_i2c_write(cam, 0x7A, 0x2F); 305 + err += sn9c102_i2c_write(cam, 0x7B, 0x2B); 306 + err += sn9c102_i2c_write(cam, 0x7C, 0x03); 307 + err += sn9c102_i2c_write(cam, 0x7D, 0x07); 308 + err += sn9c102_i2c_write(cam, 0x7E, 0x17); 309 + err += sn9c102_i2c_write(cam, 0x7F, 0x34); 310 + err += sn9c102_i2c_write(cam, 0x80, 0x41); 311 + err += sn9c102_i2c_write(cam, 0x81, 0x4D); 312 + err += sn9c102_i2c_write(cam, 0x82, 0x58); 313 + err += sn9c102_i2c_write(cam, 0x83, 0x63); 314 + err += sn9c102_i2c_write(cam, 0x84, 0x6E); 315 + err += sn9c102_i2c_write(cam, 0x85, 0x77); 316 + err += sn9c102_i2c_write(cam, 0x86, 0x87); 317 + err += sn9c102_i2c_write(cam, 0x87, 0x95); 318 + err += sn9c102_i2c_write(cam, 0x88, 0xAF); 319 + err += sn9c102_i2c_write(cam, 0x89, 0xC7); 320 + err += sn9c102_i2c_write(cam, 0x8A, 0xDF); 321 + err += sn9c102_i2c_write(cam, 0x8B, 0x99); 322 + err += sn9c102_i2c_write(cam, 0x8C, 0x99); 323 + err += sn9c102_i2c_write(cam, 0x8D, 0xCF); 324 + err += sn9c102_i2c_write(cam, 0x8E, 0x20); 325 + err += sn9c102_i2c_write(cam, 0x8F, 0x26); 326 + err += sn9c102_i2c_write(cam, 0x90, 0x10); 327 + err += sn9c102_i2c_write(cam, 0x91, 0x0C); 328 + err += sn9c102_i2c_write(cam, 0x92, 0x25); 329 + err += sn9c102_i2c_write(cam, 0x93, 0x00); 330 + err += sn9c102_i2c_write(cam, 0x94, 0x50); 331 + err += sn9c102_i2c_write(cam, 0x95, 0x50); 332 + err += sn9c102_i2c_write(cam, 0x96, 0x00); 333 + err += sn9c102_i2c_write(cam, 0x97, 0x01); 334 + err += sn9c102_i2c_write(cam, 0x98, 0x10); 335 + err += sn9c102_i2c_write(cam, 0x99, 0x40); 336 + err += sn9c102_i2c_write(cam, 0x9A, 0x40); 337 + err += sn9c102_i2c_write(cam, 0x9B, 0x20); 338 + err += sn9c102_i2c_write(cam, 0x9C, 0x00); 339 + err += sn9c102_i2c_write(cam, 0x9D, 0x99); 340 + err += sn9c102_i2c_write(cam, 0x9E, 0x7F); 341 + err += sn9c102_i2c_write(cam, 0x9F, 0x00); 342 + err += sn9c102_i2c_write(cam, 0xA0, 0x00); 343 + err += sn9c102_i2c_write(cam, 0xA1, 0x00); 344 + 345 + return err; 346 + } 347 + 348 + 349 + static int ov7660_get_ctrl(struct sn9c102_device* cam, 350 + struct v4l2_control* ctrl) 351 + { 352 + int err = 0; 353 + 354 + switch (ctrl->id) { 355 + case V4L2_CID_EXPOSURE: 356 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0) 357 + return -EIO; 358 + break; 359 + case V4L2_CID_DO_WHITE_BALANCE: 360 + ctrl->value = sn9c102_pread_reg(cam, 0x02); 361 + ctrl->value = (ctrl->value & 0x04) ? 1 : 0; 362 + break; 363 + case V4L2_CID_RED_BALANCE: 364 + ctrl->value = sn9c102_pread_reg(cam, 0x05); 365 + ctrl->value &= 0x7f; 366 + break; 367 + case V4L2_CID_BLUE_BALANCE: 368 + ctrl->value = sn9c102_pread_reg(cam, 0x06); 369 + ctrl->value &= 0x7f; 370 + break; 371 + case SN9C102_V4L2_CID_GREEN_BALANCE: 372 + ctrl->value = sn9c102_pread_reg(cam, 0x07); 373 + ctrl->value &= 0x7f; 374 + break; 375 + case V4L2_CID_GAIN: 376 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0) 377 + return -EIO; 378 + ctrl->value &= 0x7f; 379 + break; 380 + case V4L2_CID_AUTOGAIN: 381 + if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0) 382 + return -EIO; 383 + ctrl->value &= 0x01; 384 + break; 385 + default: 386 + return -EINVAL; 387 + } 388 + 389 + return err ? -EIO : 0; 390 + } 391 + 392 + 393 + static int ov7660_set_ctrl(struct sn9c102_device* cam, 394 + const struct v4l2_control* ctrl) 395 + { 396 + int err = 0; 397 + 398 + switch (ctrl->id) { 399 + case V4L2_CID_EXPOSURE: 400 + err += sn9c102_i2c_write(cam, 0x10, ctrl->value); 401 + break; 402 + case V4L2_CID_DO_WHITE_BALANCE: 403 + err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02); 404 + break; 405 + case V4L2_CID_RED_BALANCE: 406 + err += sn9c102_write_reg(cam, ctrl->value, 0x05); 407 + break; 408 + case V4L2_CID_BLUE_BALANCE: 409 + err += sn9c102_write_reg(cam, ctrl->value, 0x06); 410 + break; 411 + case SN9C102_V4L2_CID_GREEN_BALANCE: 412 + err += sn9c102_write_reg(cam, ctrl->value, 0x07); 413 + break; 414 + case V4L2_CID_GAIN: 415 + err += sn9c102_i2c_write(cam, 0x00, ctrl->value); 416 + break; 417 + case V4L2_CID_AUTOGAIN: 418 + err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value | 419 + (ctrl->value << 1)); 420 + break; 421 + default: 422 + return -EINVAL; 423 + } 424 + 425 + return err ? -EIO : 0; 426 + } 427 + 428 + 429 + static int ov7660_set_crop(struct sn9c102_device* cam, 430 + const struct v4l2_rect* rect) 431 + { 432 + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); 433 + int err = 0; 434 + u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1, 435 + v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; 436 + 437 + err += sn9c102_write_reg(cam, h_start, 0x12); 438 + err += sn9c102_write_reg(cam, v_start, 0x13); 439 + 440 + return err; 441 + } 442 + 443 + 444 + static int ov7660_set_pix_format(struct sn9c102_device* cam, 445 + const struct v4l2_pix_format* pix) 446 + { 447 + int r0, err = 0; 448 + 449 + r0 = sn9c102_pread_reg(cam, 0x01); 450 + 451 + if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { 452 + err += sn9c102_write_reg(cam, r0 | 0x40, 0x01); 453 + err += sn9c102_write_reg(cam, 0xa2, 0x17); 454 + err += sn9c102_i2c_write(cam, 0x11, 0x00); 455 + } else { 456 + err += sn9c102_write_reg(cam, r0 | 0x40, 0x01); 457 + err += sn9c102_write_reg(cam, 0xa2, 0x17); 458 + err += sn9c102_i2c_write(cam, 0x11, 0x0d); 459 + } 460 + 461 + return err; 462 + } 463 + 464 + 465 + static struct sn9c102_sensor ov7660 = { 466 + .name = "OV7660", 467 + .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 468 + .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120, 469 + .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 470 + .frequency = SN9C102_I2C_100KHZ, 471 + .interface = SN9C102_I2C_2WIRES, 472 + .i2c_slave_id = 0x21, 473 + .init = &ov7660_init, 474 + .qctrl = { 475 + { 476 + .id = V4L2_CID_GAIN, 477 + .type = V4L2_CTRL_TYPE_INTEGER, 478 + .name = "global gain", 479 + .minimum = 0x00, 480 + .maximum = 0x7f, 481 + .step = 0x01, 482 + .default_value = 0x0a, 483 + .flags = 0, 484 + }, 485 + { 486 + .id = V4L2_CID_EXPOSURE, 487 + .type = V4L2_CTRL_TYPE_INTEGER, 488 + .name = "exposure", 489 + .minimum = 0x00, 490 + .maximum = 0xff, 491 + .step = 0x01, 492 + .default_value = 0x50, 493 + .flags = 0, 494 + }, 495 + { 496 + .id = V4L2_CID_DO_WHITE_BALANCE, 497 + .type = V4L2_CTRL_TYPE_BOOLEAN, 498 + .name = "night mode", 499 + .minimum = 0x00, 500 + .maximum = 0x01, 501 + .step = 0x01, 502 + .default_value = 0x00, 503 + .flags = 0, 504 + }, 505 + { 506 + .id = V4L2_CID_RED_BALANCE, 507 + .type = V4L2_CTRL_TYPE_INTEGER, 508 + .name = "red balance", 509 + .minimum = 0x00, 510 + .maximum = 0x7f, 511 + .step = 0x01, 512 + .default_value = 0x1f, 513 + .flags = 0, 514 + }, 515 + { 516 + .id = V4L2_CID_BLUE_BALANCE, 517 + .type = V4L2_CTRL_TYPE_INTEGER, 518 + .name = "blue balance", 519 + .minimum = 0x00, 520 + .maximum = 0x7f, 521 + .step = 0x01, 522 + .default_value = 0x1e, 523 + .flags = 0, 524 + }, 525 + { 526 + .id = V4L2_CID_AUTOGAIN, 527 + .type = V4L2_CTRL_TYPE_BOOLEAN, 528 + .name = "auto adjust", 529 + .minimum = 0x00, 530 + .maximum = 0x01, 531 + .step = 0x01, 532 + .default_value = 0x00, 533 + .flags = 0, 534 + }, 535 + { 536 + .id = SN9C102_V4L2_CID_GREEN_BALANCE, 537 + .type = V4L2_CTRL_TYPE_INTEGER, 538 + .name = "green balance", 539 + .minimum = 0x00, 540 + .maximum = 0x7f, 541 + .step = 0x01, 542 + .default_value = 0x20, 543 + .flags = 0, 544 + }, 545 + }, 546 + .get_ctrl = &ov7660_get_ctrl, 547 + .set_ctrl = &ov7660_set_ctrl, 548 + .cropcap = { 549 + .bounds = { 550 + .left = 0, 551 + .top = 0, 552 + .width = 640, 553 + .height = 480, 554 + }, 555 + .defrect = { 556 + .left = 0, 557 + .top = 0, 558 + .width = 640, 559 + .height = 480, 560 + }, 561 + }, 562 + .set_crop = &ov7660_set_crop, 563 + .pix_format = { 564 + .width = 640, 565 + .height = 480, 566 + .pixelformat = V4L2_PIX_FMT_JPEG, 567 + .priv = 8, 568 + }, 569 + .set_pix_format = &ov7660_set_pix_format 570 + }; 571 + 572 + 573 + int sn9c102_probe_ov7660(struct sn9c102_device* cam) 574 + { 575 + int pid, ver, err = 0; 576 + 577 + err += sn9c102_write_reg(cam, 0x01, 0xf1); 578 + err += sn9c102_write_reg(cam, 0x00, 0xf1); 579 + err += sn9c102_write_reg(cam, 0x01, 0x01); 580 + err += sn9c102_write_reg(cam, 0x00, 0x01); 581 + err += sn9c102_write_reg(cam, 0x28, 0x17); 582 + 583 + pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a); 584 + ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b); 585 + if (err || pid < 0 || ver < 0) 586 + return -EIO; 587 + if (pid != 0x76 || ver != 0x60) 588 + return -ENODEV; 589 + sn9c102_attach_sensor(cam, &ov7660); 590 + 591 + return 0; 592 + }
+4 -3
drivers/media/video/sn9c102/sn9c102_pas106b.c
··· 1 1 /*************************************************************************** 2 - * Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera * 2 + * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera * 3 3 * Controllers * 4 4 * * 5 - * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 + * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * 6 6 * * 7 7 * This program is free software; you can redistribute it and/or modify * 8 8 * it under the terms of the GNU General Public License as published by * ··· 143 143 static int pas106b_set_crop(struct sn9c102_device* cam, 144 144 const struct v4l2_rect* rect) 145 145 { 146 - struct sn9c102_sensor* s = &pas106b; 146 + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); 147 147 int err = 0; 148 148 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, 149 149 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; ··· 172 172 static struct sn9c102_sensor pas106b = { 173 173 .name = "PAS106B", 174 174 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 175 + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 175 176 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 176 177 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, 177 178 .interface = SN9C102_I2C_2WIRES,
-238
drivers/media/video/sn9c102/sn9c102_pas202bca.c
··· 1 - /*************************************************************************** 2 - * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera * 3 - * Controllers * 4 - * * 5 - * Copyright (C) 2006 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 - 25 - 26 - static struct sn9c102_sensor pas202bca; 27 - 28 - 29 - static int pas202bca_init(struct sn9c102_device* cam) 30 - { 31 - int err = 0; 32 - 33 - err += sn9c102_write_reg(cam, 0x00, 0x10); 34 - err += sn9c102_write_reg(cam, 0x00, 0x11); 35 - err += sn9c102_write_reg(cam, 0x00, 0x14); 36 - err += sn9c102_write_reg(cam, 0x20, 0x17); 37 - err += sn9c102_write_reg(cam, 0x30, 0x19); 38 - err += sn9c102_write_reg(cam, 0x09, 0x18); 39 - 40 - err += sn9c102_i2c_write(cam, 0x02, 0x14); 41 - err += sn9c102_i2c_write(cam, 0x03, 0x40); 42 - err += sn9c102_i2c_write(cam, 0x0d, 0x2c); 43 - err += sn9c102_i2c_write(cam, 0x0e, 0x01); 44 - err += sn9c102_i2c_write(cam, 0x0f, 0xa9); 45 - err += sn9c102_i2c_write(cam, 0x10, 0x08); 46 - err += sn9c102_i2c_write(cam, 0x13, 0x63); 47 - err += sn9c102_i2c_write(cam, 0x15, 0x70); 48 - err += sn9c102_i2c_write(cam, 0x11, 0x01); 49 - 50 - msleep(400); 51 - 52 - return err; 53 - } 54 - 55 - 56 - static int pas202bca_set_pix_format(struct sn9c102_device* cam, 57 - const struct v4l2_pix_format* pix) 58 - { 59 - int err = 0; 60 - 61 - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) 62 - err += sn9c102_write_reg(cam, 0x24, 0x17); 63 - else 64 - err += sn9c102_write_reg(cam, 0x20, 0x17); 65 - 66 - return err; 67 - } 68 - 69 - 70 - static int pas202bca_set_ctrl(struct sn9c102_device* cam, 71 - const struct v4l2_control* ctrl) 72 - { 73 - int err = 0; 74 - 75 - switch (ctrl->id) { 76 - case V4L2_CID_EXPOSURE: 77 - err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); 78 - err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); 79 - break; 80 - case V4L2_CID_RED_BALANCE: 81 - err += sn9c102_i2c_write(cam, 0x09, ctrl->value); 82 - break; 83 - case V4L2_CID_BLUE_BALANCE: 84 - err += sn9c102_i2c_write(cam, 0x07, ctrl->value); 85 - break; 86 - case V4L2_CID_GAIN: 87 - err += sn9c102_i2c_write(cam, 0x10, ctrl->value); 88 - break; 89 - case SN9C102_V4L2_CID_GREEN_BALANCE: 90 - err += sn9c102_i2c_write(cam, 0x08, ctrl->value); 91 - break; 92 - case SN9C102_V4L2_CID_DAC_MAGNITUDE: 93 - err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); 94 - break; 95 - default: 96 - return -EINVAL; 97 - } 98 - err += sn9c102_i2c_write(cam, 0x11, 0x01); 99 - 100 - return err ? -EIO : 0; 101 - } 102 - 103 - 104 - static int pas202bca_set_crop(struct sn9c102_device* cam, 105 - const struct v4l2_rect* rect) 106 - { 107 - struct sn9c102_sensor* s = &pas202bca; 108 - int err = 0; 109 - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3, 110 - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; 111 - 112 - err += sn9c102_write_reg(cam, h_start, 0x12); 113 - err += sn9c102_write_reg(cam, v_start, 0x13); 114 - 115 - return err; 116 - } 117 - 118 - 119 - static struct sn9c102_sensor pas202bca = { 120 - .name = "PAS202BCA", 121 - .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 122 - .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 123 - .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, 124 - .interface = SN9C102_I2C_2WIRES, 125 - .i2c_slave_id = 0x40, 126 - .init = &pas202bca_init, 127 - .qctrl = { 128 - { 129 - .id = V4L2_CID_EXPOSURE, 130 - .type = V4L2_CTRL_TYPE_INTEGER, 131 - .name = "exposure", 132 - .minimum = 0x01e5, 133 - .maximum = 0x3fff, 134 - .step = 0x0001, 135 - .default_value = 0x01e5, 136 - .flags = 0, 137 - }, 138 - { 139 - .id = V4L2_CID_GAIN, 140 - .type = V4L2_CTRL_TYPE_INTEGER, 141 - .name = "global gain", 142 - .minimum = 0x00, 143 - .maximum = 0x1f, 144 - .step = 0x01, 145 - .default_value = 0x0c, 146 - .flags = 0, 147 - }, 148 - { 149 - .id = V4L2_CID_RED_BALANCE, 150 - .type = V4L2_CTRL_TYPE_INTEGER, 151 - .name = "red balance", 152 - .minimum = 0x00, 153 - .maximum = 0x0f, 154 - .step = 0x01, 155 - .default_value = 0x01, 156 - .flags = 0, 157 - }, 158 - { 159 - .id = V4L2_CID_BLUE_BALANCE, 160 - .type = V4L2_CTRL_TYPE_INTEGER, 161 - .name = "blue balance", 162 - .minimum = 0x00, 163 - .maximum = 0x0f, 164 - .step = 0x01, 165 - .default_value = 0x05, 166 - .flags = 0, 167 - }, 168 - { 169 - .id = SN9C102_V4L2_CID_GREEN_BALANCE, 170 - .type = V4L2_CTRL_TYPE_INTEGER, 171 - .name = "green balance", 172 - .minimum = 0x00, 173 - .maximum = 0x0f, 174 - .step = 0x01, 175 - .default_value = 0x00, 176 - .flags = 0, 177 - }, 178 - { 179 - .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, 180 - .type = V4L2_CTRL_TYPE_INTEGER, 181 - .name = "DAC magnitude", 182 - .minimum = 0x00, 183 - .maximum = 0xff, 184 - .step = 0x01, 185 - .default_value = 0x04, 186 - .flags = 0, 187 - }, 188 - }, 189 - .set_ctrl = &pas202bca_set_ctrl, 190 - .cropcap = { 191 - .bounds = { 192 - .left = 0, 193 - .top = 0, 194 - .width = 640, 195 - .height = 480, 196 - }, 197 - .defrect = { 198 - .left = 0, 199 - .top = 0, 200 - .width = 640, 201 - .height = 480, 202 - }, 203 - }, 204 - .set_crop = &pas202bca_set_crop, 205 - .pix_format = { 206 - .width = 640, 207 - .height = 480, 208 - .pixelformat = V4L2_PIX_FMT_SBGGR8, 209 - .priv = 8, 210 - }, 211 - .set_pix_format = &pas202bca_set_pix_format 212 - }; 213 - 214 - 215 - int sn9c102_probe_pas202bca(struct sn9c102_device* cam) 216 - { 217 - const struct usb_device_id pas202bca_id_table[] = { 218 - { USB_DEVICE(0x0c45, 0x60af), }, 219 - { } 220 - }; 221 - int err = 0; 222 - 223 - if (!sn9c102_match_id(cam,pas202bca_id_table)) 224 - return -ENODEV; 225 - 226 - err += sn9c102_write_reg(cam, 0x01, 0x01); 227 - err += sn9c102_write_reg(cam, 0x40, 0x01); 228 - err += sn9c102_write_reg(cam, 0x28, 0x17); 229 - if (err) 230 - return -EIO; 231 - 232 - if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */ 233 - return -ENODEV; 234 - 235 - sn9c102_attach_sensor(cam, &pas202bca); 236 - 237 - return 0; 238 - }
+81 -16
drivers/media/video/sn9c102/sn9c102_pas202bcb.c
··· 1 1 /*************************************************************************** 2 - * Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera * 2 + * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera * 3 3 * Controllers * 4 4 * * 5 5 * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio * 6 6 * <medaglia@undl.org.br> * 7 7 * http://cadu.homelinux.com:8080/ * 8 8 * * 9 - * DAC Magnitude, exposure and green gain controls added by * 10 - * Luca Risolia <luca.risolia@studio.unibo.it> * 9 + * Support for SN9C103, DAC Magnitude, exposure and green gain controls * 10 + * added by Luca Risolia <luca.risolia@studio.unibo.it> * 11 11 * * 12 12 * This program is free software; you can redistribute it and/or modify * 13 13 * it under the terms of the GNU General Public License as published by * ··· 35 35 { 36 36 int err = 0; 37 37 38 + switch (sn9c102_get_bridge(cam)) { 39 + case BRIDGE_SN9C101: 40 + case BRIDGE_SN9C102: 38 41 err += sn9c102_write_reg(cam, 0x00, 0x10); 39 42 err += sn9c102_write_reg(cam, 0x00, 0x11); 40 43 err += sn9c102_write_reg(cam, 0x00, 0x14); 41 44 err += sn9c102_write_reg(cam, 0x20, 0x17); 42 45 err += sn9c102_write_reg(cam, 0x30, 0x19); 43 46 err += sn9c102_write_reg(cam, 0x09, 0x18); 47 + break; 48 + case BRIDGE_SN9C103: 49 + err += sn9c102_write_reg(cam, 0x00, 0x02); 50 + err += sn9c102_write_reg(cam, 0x00, 0x03); 51 + err += sn9c102_write_reg(cam, 0x1a, 0x04); 52 + err += sn9c102_write_reg(cam, 0x20, 0x05); 53 + err += sn9c102_write_reg(cam, 0x20, 0x06); 54 + err += sn9c102_write_reg(cam, 0x20, 0x07); 55 + err += sn9c102_write_reg(cam, 0x00, 0x10); 56 + err += sn9c102_write_reg(cam, 0x00, 0x11); 57 + err += sn9c102_write_reg(cam, 0x00, 0x14); 58 + err += sn9c102_write_reg(cam, 0x20, 0x17); 59 + err += sn9c102_write_reg(cam, 0x30, 0x19); 60 + err += sn9c102_write_reg(cam, 0x09, 0x18); 61 + err += sn9c102_write_reg(cam, 0x02, 0x1c); 62 + err += sn9c102_write_reg(cam, 0x03, 0x1d); 63 + err += sn9c102_write_reg(cam, 0x0f, 0x1e); 64 + err += sn9c102_write_reg(cam, 0x0c, 0x1f); 65 + err += sn9c102_write_reg(cam, 0x00, 0x20); 66 + err += sn9c102_write_reg(cam, 0x10, 0x21); 67 + err += sn9c102_write_reg(cam, 0x20, 0x22); 68 + err += sn9c102_write_reg(cam, 0x30, 0x23); 69 + err += sn9c102_write_reg(cam, 0x40, 0x24); 70 + err += sn9c102_write_reg(cam, 0x50, 0x25); 71 + err += sn9c102_write_reg(cam, 0x60, 0x26); 72 + err += sn9c102_write_reg(cam, 0x70, 0x27); 73 + err += sn9c102_write_reg(cam, 0x80, 0x28); 74 + err += sn9c102_write_reg(cam, 0x90, 0x29); 75 + err += sn9c102_write_reg(cam, 0xa0, 0x2a); 76 + err += sn9c102_write_reg(cam, 0xb0, 0x2b); 77 + err += sn9c102_write_reg(cam, 0xc0, 0x2c); 78 + err += sn9c102_write_reg(cam, 0xd0, 0x2d); 79 + err += sn9c102_write_reg(cam, 0xe0, 0x2e); 80 + err += sn9c102_write_reg(cam, 0xf0, 0x2f); 81 + err += sn9c102_write_reg(cam, 0xff, 0x30); 82 + break; 83 + default: 84 + break; 85 + } 44 86 45 87 err += sn9c102_i2c_write(cam, 0x02, 0x14); 46 88 err += sn9c102_i2c_write(cam, 0x03, 0x40); ··· 149 107 int err = 0; 150 108 151 109 if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) 152 - err += sn9c102_write_reg(cam, 0x24, 0x17); 110 + err += sn9c102_write_reg(cam, 0x28, 0x17); 153 111 else 154 112 err += sn9c102_write_reg(cam, 0x20, 0x17); 155 113 ··· 194 152 static int pas202bcb_set_crop(struct sn9c102_device* cam, 195 153 const struct v4l2_rect* rect) 196 154 { 197 - struct sn9c102_sensor* s = &pas202bcb; 155 + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); 198 156 int err = 0; 199 - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4, 157 + u8 h_start = 0, 200 158 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; 159 + 160 + switch (sn9c102_get_bridge(cam)) { 161 + case BRIDGE_SN9C101: 162 + case BRIDGE_SN9C102: 163 + h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4; 164 + break; 165 + case BRIDGE_SN9C103: 166 + h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3; 167 + break; 168 + default: 169 + break; 170 + } 201 171 202 172 err += sn9c102_write_reg(cam, h_start, 0x12); 203 173 err += sn9c102_write_reg(cam, v_start, 0x13); ··· 220 166 221 167 static struct sn9c102_sensor pas202bcb = { 222 168 .name = "PAS202BCB", 223 - .maintainer = "Carlos Eduardo Medaglia Dyonisio " 224 - "<medaglia@undl.org.br>", 169 + .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 170 + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 225 171 .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, 226 172 .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, 227 173 .interface = SN9C102_I2C_2WIRES, ··· 245 191 .minimum = 0x00, 246 192 .maximum = 0x1f, 247 193 .step = 0x01, 248 - .default_value = 0x0c, 194 + .default_value = 0x0b, 249 195 .flags = 0, 250 196 }, 251 197 { ··· 255 201 .minimum = 0x00, 256 202 .maximum = 0x0f, 257 203 .step = 0x01, 258 - .default_value = 0x01, 204 + .default_value = 0x00, 259 205 .flags = 0, 260 206 }, 261 207 { ··· 325 271 * Minimal initialization to enable the I2C communication 326 272 * NOTE: do NOT change the values! 327 273 */ 328 - err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */ 329 - err += sn9c102_write_reg(cam, 0x40, 0x01); /* sensor power on */ 330 - err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */ 331 - if (err) 332 - return -EIO; 274 + switch (sn9c102_get_bridge(cam)) { 275 + case BRIDGE_SN9C101: 276 + case BRIDGE_SN9C102: 277 + err += sn9c102_write_reg(cam, 0x01, 0x01); /* power down */ 278 + err += sn9c102_write_reg(cam, 0x40, 0x01); /* power on */ 279 + err += sn9c102_write_reg(cam, 0x28, 0x17); /* clock 24 MHz */ 280 + break; 281 + case BRIDGE_SN9C103: /* do _not_ change anything! */ 282 + err += sn9c102_write_reg(cam, 0x09, 0x01); 283 + err += sn9c102_write_reg(cam, 0x44, 0x01); 284 + err += sn9c102_write_reg(cam, 0x44, 0x02); 285 + err += sn9c102_write_reg(cam, 0x29, 0x17); 286 + break; 287 + default: 288 + break; 289 + } 333 290 334 291 r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00); 335 292 r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01); 336 293 337 - if (r0 < 0 || r1 < 0) 294 + if (err || r0 < 0 || r1 < 0) 338 295 return -EIO; 339 296 340 297 pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
+39 -129
drivers/media/video/sn9c102/sn9c102_sensor.h
··· 1 1 /*************************************************************************** 2 - * API for image sensors connected to the SN9C10x PC Camera Controllers * 2 + * API for image sensors connected to the SN9C1xx PC Camera Controllers * 3 3 * * 4 - * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 4 + * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 5 * * 6 6 * This program is free software; you can redistribute it and/or modify * 7 7 * it under the terms of the GNU General Public License as published by * ··· 36 36 /* 37 37 OVERVIEW. 38 38 This is a small interface that allows you to add support for any CCD/CMOS 39 - image sensors connected to the SN9C10X bridges. The entire API is documented 39 + image sensors connected to the SN9C1XX bridges. The entire API is documented 40 40 below. In the most general case, to support a sensor there are three steps 41 41 you have to follow: 42 42 1) define the main "sn9c102_sensor" structure by setting the basic fields; 43 43 2) write a probing function to be called by the core module when the USB 44 44 camera is recognized, then add both the USB ids and the name of that 45 - function to the two corresponding tables SENSOR_TABLE and ID_TABLE (see 46 - below); 45 + function to the two corresponding tables in sn9c102_devtable.h; 47 46 3) implement the methods that you want/need (and fill the rest of the main 48 47 structure accordingly). 49 48 "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do ··· 53 54 54 55 /*****************************************************************************/ 55 56 56 - /* 57 - Probing functions: on success, you must attach the sensor to the camera 58 - by calling sn9c102_attach_sensor() provided below. 59 - To enable the I2C communication, you might need to perform a really basic 60 - initialization of the SN9C10X chip by using the write function declared 61 - ahead. 62 - Functions must return 0 on success, the appropriate error otherwise. 63 - */ 64 - extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam); 65 - extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); 66 - extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); 67 - extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); 68 - extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam); 69 - extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); 70 - extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); 71 - extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); 72 - 73 - /* 74 - Add the above entries to this table. Be sure to add the entry in the right 75 - place, since, on failure, the next probing routine is called according to 76 - the order of the list below, from top to bottom. 77 - */ 78 - #define SN9C102_SENSOR_TABLE \ 79 - static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \ 80 - &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ \ 81 - &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \ 82 - &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \ 83 - &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \ 84 - &sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \ 85 - &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \ 86 - &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \ 87 - &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \ 88 - NULL, \ 57 + enum sn9c102_bridge { 58 + BRIDGE_SN9C101 = 0x01, 59 + BRIDGE_SN9C102 = 0x02, 60 + BRIDGE_SN9C103 = 0x04, 61 + BRIDGE_SN9C105 = 0x08, 62 + BRIDGE_SN9C120 = 0x10, 89 63 }; 90 64 91 - /* Device identification */ 65 + /* Return the bridge name */ 66 + enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device* cam); 67 + 68 + /* Return a pointer the sensor struct attached to the camera */ 69 + struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam); 70 + 71 + /* Identify a device */ 92 72 extern struct sn9c102_device* 93 73 sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); 94 74 ··· 77 99 struct sn9c102_sensor* sensor); 78 100 79 101 /* 80 - Each SN9C10x camera has proper PID/VID identifiers. 81 - SN9C103 supports multiple interfaces, but we only handle the video class 82 - interface. 83 - */ 84 - #define SN9C102_USB_DEVICE(vend, prod, intclass) \ 85 - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ 86 - USB_DEVICE_ID_MATCH_INT_CLASS, \ 87 - .idVendor = (vend), \ 88 - .idProduct = (prod), \ 89 - .bInterfaceClass = (intclass) 90 - 91 - #define SN9C102_ID_TABLE \ 92 - static const struct usb_device_id sn9c102_id_table[] = { \ 93 - { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \ 94 - { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \ 95 - { USB_DEVICE(0x0c45, 0x6007), }, \ 96 - { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \ 97 - { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \ 98 - { USB_DEVICE(0x0c45, 0x6024), }, \ 99 - { USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */ \ 100 - { USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */ \ 101 - { USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \ 102 - { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */ \ 103 - { USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \ 104 - { USB_DEVICE(0x0c45, 0x602c), }, /* OV7630 */ \ 105 - { USB_DEVICE(0x0c45, 0x602d), }, \ 106 - { USB_DEVICE(0x0c45, 0x602e), }, /* OV7630 */ \ 107 - { USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \ 108 - { SN9C102_USB_DEVICE(0x0c45, 0x6080, 0xff), }, \ 109 - { SN9C102_USB_DEVICE(0x0c45, 0x6082, 0xff), }, /* MI0343 & MI0360 */ \ 110 - { SN9C102_USB_DEVICE(0x0c45, 0x6083, 0xff), }, /* HV7131[D|E1] */ \ 111 - { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \ 112 - { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \ 113 - { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \ 114 - { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */ \ 115 - { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \ 116 - { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \ 117 - { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \ 118 - { SN9C102_USB_DEVICE(0x0c45, 0x60a2, 0xff), }, \ 119 - { SN9C102_USB_DEVICE(0x0c45, 0x60a3, 0xff), }, \ 120 - { SN9C102_USB_DEVICE(0x0c45, 0x60a8, 0xff), }, /* PAS106B */ \ 121 - { SN9C102_USB_DEVICE(0x0c45, 0x60aa, 0xff), }, /* TAS5130D1B */ \ 122 - { SN9C102_USB_DEVICE(0x0c45, 0x60ab, 0xff), }, /* TAS5110C1B */ \ 123 - { SN9C102_USB_DEVICE(0x0c45, 0x60ac, 0xff), }, \ 124 - { SN9C102_USB_DEVICE(0x0c45, 0x60ae, 0xff), }, \ 125 - { SN9C102_USB_DEVICE(0x0c45, 0x60af, 0xff), }, /* PAS202BCB */ \ 126 - { SN9C102_USB_DEVICE(0x0c45, 0x60b0, 0xff), }, /* OV7630 (?) */ \ 127 - { SN9C102_USB_DEVICE(0x0c45, 0x60b2, 0xff), }, \ 128 - { SN9C102_USB_DEVICE(0x0c45, 0x60b3, 0xff), }, \ 129 - { SN9C102_USB_DEVICE(0x0c45, 0x60b8, 0xff), }, \ 130 - { SN9C102_USB_DEVICE(0x0c45, 0x60ba, 0xff), }, \ 131 - { SN9C102_USB_DEVICE(0x0c45, 0x60bb, 0xff), }, \ 132 - { SN9C102_USB_DEVICE(0x0c45, 0x60bc, 0xff), }, \ 133 - { SN9C102_USB_DEVICE(0x0c45, 0x60be, 0xff), }, \ 134 - { } \ 135 - }; 136 - 137 - /*****************************************************************************/ 138 - 139 - /* 140 102 Read/write routines: they always return -1 on error, 0 or the read value 141 - otherwise. NOTE that a real read operation is not supported by the SN9C10X 103 + otherwise. NOTE that a real read operation is not supported by the SN9C1XX 142 104 chip for some of its registers. To work around this problem, a pseudo-read 143 105 call is provided instead: it returns the last successfully written value 144 106 on the register (0 if it has never been written), the usual -1 on error. ··· 94 176 These must be used if and only if the sensor doesn't implement the standard 95 177 I2C protocol. There are a number of good reasons why you must use the 96 178 single-byte versions of these functions: do not abuse. The first function 97 - writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X 179 + writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX 98 180 chip. The second one programs the registers 0x09 and 0x10 with data0 and 99 181 data1, and places the n bytes read from the sensor register table in the 100 182 buffer pointed by 'buffer'. Both the functions return -1 on error; the write ··· 118 200 extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); 119 201 extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); 120 202 121 - /* 122 - NOTE: there are no exported debugging functions. To uniform the output you 123 - must use the dev_info()/dev_warn()/dev_err() macros defined in device.h, 124 - already included here, the argument being the struct device '&usbdev->dev' 125 - of the sensor structure. Do NOT use these macros before the sensor is 126 - attached or the kernel will crash! However, you should not need to notify 127 - the user about common errors or other messages, since this is done by the 128 - master module. 129 - */ 130 - 131 203 /*****************************************************************************/ 132 204 133 205 enum sn9c102_i2c_sysfs_ops { ··· 135 227 SN9C102_I2C_3WIRES, 136 228 }; 137 229 138 - #define SN9C102_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 230 + #define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10) 139 231 140 232 struct sn9c102_sensor { 141 233 char name[32], /* sensor name */ 142 234 maintainer[64]; /* name of the mantainer <email> */ 143 235 236 + enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */ 237 + 144 238 /* Supported operations through the 'sysfs' interface */ 145 239 enum sn9c102_i2c_sysfs_ops sysfs_ops; 146 240 147 241 /* 148 - These sensor capabilities must be provided if the SN9C10X controller 242 + These sensor capabilities must be provided if the SN9C1XX controller 149 243 needs to communicate through the sensor serial interface by using 150 244 at least one of the i2c functions available. 151 245 */ ··· 170 260 /* 171 261 This function will be called after the sensor has been attached. 172 262 It should be used to initialize the sensor only, but may also 173 - configure part of the SN9C10X chip if necessary. You don't need to 263 + configure part of the SN9C1XX chip if necessary. You don't need to 174 264 setup picture settings like brightness, contrast, etc.. here, if 175 265 the corrisponding controls are implemented (see below), since 176 266 they are adjusted in the core driver by calling the set_ctrl() ··· 210 300 It is not always true that the largest achievable active window can 211 301 cover the whole array of pixels. The V4L2 API defines another 212 302 area called "source rectangle", which, in turn, is a subrectangle of 213 - the active window. The SN9C10X chip is always programmed to read the 303 + the active window. The SN9C1XX chip is always programmed to read the 214 304 source rectangle. 215 305 The bounds of both the active window and the source rectangle are 216 306 specified in the cropcap substructures 'bounds' and 'defrect'. ··· 236 326 const struct v4l2_rect* rect); 237 327 /* 238 328 To be called on VIDIOC_C_SETCROP. The core module always calls a 239 - default routine which configures the appropriate SN9C10X regs (also 329 + default routine which configures the appropriate SN9C1XX regs (also 240 330 scaling), but you may need to override/adjust specific stuff. 241 331 'rect' contains width and height values that are multiple of 16: in 242 332 case you override the default function, you always have to program 243 333 the chip to match those values; on error return the corresponding 244 334 error code without rolling back. 245 - NOTE: in case, you must program the SN9C10X chip to get rid of 335 + NOTE: in case, you must program the SN9C1XX chip to get rid of 246 336 blank pixels or blank lines at the _start_ of each line or 247 337 frame after each HSYNC or VSYNC, so that the image starts with 248 338 real RGB data (see regs 0x12, 0x13) (having set H_SIZE and, ··· 254 344 /* 255 345 What you have to define here are: 1) initial 'width' and 'height' of 256 346 the target rectangle 2) the initial 'pixelformat', which can be 257 - either V4L2_PIX_FMT_SN9C10X (for compressed video) or 258 - V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the 259 - number of bits per pixel for uncompressed video, 8 or 9 (despite the 260 - current value of 'pixelformat'). 347 + either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video) 348 + or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate 349 + the number of bits per pixel for uncompressed video, 8 or 9 (despite 350 + the current value of 'pixelformat'). 261 351 NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4 262 352 of cropcap.defrect.width and cropcap.defrect.height. I 263 353 suggest 1/1. 264 354 NOTE 2: The initial compression quality is defined by the first bit 265 355 of reg 0x17 during the initialization of the image sensor. 266 - NOTE 3: as said above, you have to program the SN9C10X chip to get 356 + NOTE 3: as said above, you have to program the SN9C1XX chip to get 267 357 rid of any blank pixels, so that the output of the sensor 268 358 matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). 269 359 */ ··· 288 378 /*****************************************************************************/ 289 379 290 380 /* Private ioctl's for control settings supported by some image sensors */ 291 - #define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE 292 - #define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 293 - #define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2 294 - #define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3 295 - #define SN9C102_V4L2_CID_GAMMA V4L2_CID_PRIVATE_BASE + 4 296 - #define SN9C102_V4L2_CID_BAND_FILTER V4L2_CID_PRIVATE_BASE + 5 297 - #define SN9C102_V4L2_CID_BRIGHT_LEVEL V4L2_CID_PRIVATE_BASE + 6 381 + #define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0) 382 + #define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1) 383 + #define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2) 384 + #define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3) 385 + #define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4) 386 + #define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5) 387 + #define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6) 298 388 299 389 #endif /* _SN9C102_SENSOR_H_ */
+5 -3
drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
··· 1 1 /*************************************************************************** 2 - * Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera * 2 + * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera * 3 3 * Controllers * 4 4 * * 5 - * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 + * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * 6 6 * * 7 7 * This program is free software; you can redistribute it and/or modify * 8 8 * it under the terms of the GNU General Public License as published by * ··· 64 64 static int tas5110c1b_set_crop(struct sn9c102_device* cam, 65 65 const struct v4l2_rect* rect) 66 66 { 67 - struct sn9c102_sensor* s = &tas5110c1b; 67 + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); 68 68 int err = 0; 69 69 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69, 70 70 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9; ··· 98 98 static struct sn9c102_sensor tas5110c1b = { 99 99 .name = "TAS5110C1B", 100 100 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 101 + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 101 102 .sysfs_ops = SN9C102_I2C_WRITE, 102 103 .frequency = SN9C102_I2C_100KHZ, 103 104 .interface = SN9C102_I2C_3WIRES, ··· 146 145 const struct usb_device_id tas5110c1b_id_table[] = { 147 146 { USB_DEVICE(0x0c45, 0x6001), }, 148 147 { USB_DEVICE(0x0c45, 0x6005), }, 148 + { USB_DEVICE(0x0c45, 0x6007), }, 149 149 { USB_DEVICE(0x0c45, 0x60ab), }, 150 150 { } 151 151 };
+5 -3
drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
··· 1 1 /*************************************************************************** 2 - * Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera * 2 + * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera * 3 3 * Controllers * 4 4 * * 5 - * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> * 5 + * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * 6 6 * * 7 7 * This program is free software; you can redistribute it and/or modify * 8 8 * it under the terms of the GNU General Public License as published by * ··· 65 65 static int tas5130d1b_set_crop(struct sn9c102_device* cam, 66 66 const struct v4l2_rect* rect) 67 67 { 68 - struct sn9c102_sensor* s = &tas5130d1b; 68 + struct sn9c102_sensor* s = sn9c102_get_sensor(cam); 69 69 u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104, 70 70 v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12; 71 71 int err = 0; ··· 99 99 static struct sn9c102_sensor tas5130d1b = { 100 100 .name = "TAS5130D1B", 101 101 .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", 102 + .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, 102 103 .sysfs_ops = SN9C102_I2C_WRITE, 103 104 .frequency = SN9C102_I2C_100KHZ, 104 105 .interface = SN9C102_I2C_3WIRES, ··· 155 154 int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) 156 155 { 157 156 const struct usb_device_id tas5130d1b_id_table[] = { 157 + { USB_DEVICE(0x0c45, 0x6024), }, 158 158 { USB_DEVICE(0x0c45, 0x6025), }, 159 159 { USB_DEVICE(0x0c45, 0x60aa), }, 160 160 { }