V4L/DVB (8157): gspca: all subdrivers
- remaning subdrivers added - remove the decoding helper and some specific frame decodings Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
d43fa32fec
commit
6a7eba24e4
|
@ -1,4 +1,4 @@
|
|||
Here the list of the known working cameras with gspca.
|
||||
List of the webcams know by gspca.
|
||||
|
||||
The modules are:
|
||||
gspca_main main driver
|
||||
|
@ -6,203 +6,50 @@ The modules are:
|
|||
|
||||
xxxx vend:prod
|
||||
----
|
||||
conex 0572:0041 Creative Notebook cx11646
|
||||
etoms 102c:6151 Qcam Sangha CIF
|
||||
etoms 102c:6251 Qcam xxxxxx VGA
|
||||
mars 093a:050f Mars-Semi Pc-Camera
|
||||
ov519 041e:4052 Creative Live! VISTA IM
|
||||
ov519 041e:405f Creative Live! VISTA VF0330
|
||||
ov519 041e:4060 Creative Live! VISTA VF0350
|
||||
ov519 041e:4061 Creative Live! VISTA VF0400
|
||||
ov519 041e:4064 Creative Live! VISTA VF0420
|
||||
ov519 041e:4068 Creative Live! VISTA VF0470
|
||||
ov519 045e:028c Micro$oft xbox cam
|
||||
ov519 054c:0154 Sonny toy4
|
||||
ov519 054c:0155 Sonny toy5
|
||||
ov519 05a9:0519 OmniVision
|
||||
ov519 05a9:4519 OmniVision
|
||||
ov519 05a9:8519 OmniVision
|
||||
ov519 05a9:0530 OmniVision
|
||||
pac207 041e:4028 Creative Webcam Vista Plus
|
||||
pac207 093a:2460 PAC207 Qtec Webcam 100
|
||||
pac207 093a:2463 Philips spc200nc pac207
|
||||
pac207 093a:2464 Labtec Webcam 1200
|
||||
pac207 093a:2468 PAC207
|
||||
pac207 093a:2470 Genius GF112
|
||||
pac207 093a:2471 PAC207 Genius VideoCam ge111
|
||||
pac207 093a:2472 PAC207 Genius VideoCam ge110
|
||||
pac7311 093a:2600 PAC7311 Typhoon
|
||||
pac7311 093a:2601 PAC7311 Phillips SPC610NC
|
||||
pac7311 093a:2603 PAC7312
|
||||
pac7311 093a:2608 PAC7311 Trust WB-3300p
|
||||
pac7311 093a:260e PAC7311 Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
|
||||
pac7311 093a:260f PAC7311 SnakeCam
|
||||
sonixb 0c45:6001 Genius VideoCAM NB
|
||||
sonixb 0c45:6005 Sweex Tas5110
|
||||
sonixb 0c45:6007 Sonix sn9c101 + Tas5110D
|
||||
sonixb 0c45:6009 spcaCam@120
|
||||
sonixb 0c45:600d spcaCam@120
|
||||
sonixb 0c45:6011 MAX Webcam (Microdia - OV6650 - SN9C101G)
|
||||
sonixb 0c45:6019 Generic Sonix OV7630
|
||||
sonixb 0c45:6024 Generic Sonix Tas5130c
|
||||
sonixb 0c45:6025 Xcam Shanga
|
||||
sonixb 0c45:6028 Sonix Btc Pc380
|
||||
sonixb 0c45:6029 spcaCam@150
|
||||
sonixb 0c45:602c Generic Sonix OV7630
|
||||
sonixb 0c45:602d LIC-200 LG
|
||||
sonixb 0c45:602e Genius VideoCam Messenger
|
||||
sonixj 0458:7025 Genius Eye 311Q
|
||||
sonixj 045e:00f5 MicroSoft VX3000
|
||||
sonixj 045e:00f7 MicroSoft VX1000
|
||||
sonixj 0471:0327 Philips SPC 600 NC
|
||||
sonixj 0471:0328 Philips SPC 700 NC
|
||||
sonixj 0471:0330 Philips SPC 710NC
|
||||
sonixj 0c45:6040 Speed NVC 350K
|
||||
sonixj 0c45:607c Sonix sn9c102p Hv7131R
|
||||
sonixj 0c45:60c0 Sangha Sn535
|
||||
sonixj 0c45:60ec SN9C105+MO4000
|
||||
sonixj 0c45:60fb Surfer NoName
|
||||
sonixj 0c45:60fc LG-LIC300
|
||||
sonixj 0c45:612a Avant Camera
|
||||
sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix
|
||||
sonixj 0c45:6130 Sonix Pccam
|
||||
sonixj 0c45:6138 Sn9c120 Mo4000
|
||||
sonixj 0c45:613b Surfer SN-206
|
||||
sonixj 0c45:613c Sonix Pccam168
|
||||
spca500 040a:0300 Kodak EZ200
|
||||
spca500 041e:400a Creative PC-CAM 300
|
||||
spca500 046d:0890 Logitech QuickCam traveler
|
||||
spca500 046d:0900 Logitech Inc. ClickSmart 310
|
||||
spca500 046d:0901 Logitech Inc. ClickSmart 510
|
||||
spca500 04a5:300c Benq DC1016
|
||||
spca500 04fc:7333 PalmPixDC85
|
||||
spca500 055f:c200 Mustek Gsmart 300
|
||||
spca500 055f:c220 Gsmart Mini
|
||||
spca500 06bd:0404 Agfa CL20
|
||||
spca500 06be:0800 Optimedia
|
||||
spca500 084d:0003 D-Link DSC-350
|
||||
spca500 08ca:0103 Aiptek PocketDV
|
||||
spca500 2899:012c Toptro Industrial
|
||||
spca500 8086:0630 Intel Pocket PC Camera
|
||||
spca501 040a:0002 Kodak DVC-325
|
||||
spca501 0497:c001 Smile International
|
||||
spca501 0506:00df 3Com HomeConnect Lite
|
||||
spca501 0733:0401 Intel Create and Share
|
||||
spca501 0733:0402 ViewQuest M318B
|
||||
spca501 1776:501c Arowana 300K CMOS Camera
|
||||
spca501 0000:0000 MystFromOri Unknow Camera
|
||||
spca505 041e:401d Creative Webcam NX ULTRA
|
||||
spca505 0733:0430 Intel PC Camera Pro
|
||||
spca506 06e1:a190 ADS Instant VCD
|
||||
spca506 0734:043b 3DeMon USB Capture aka
|
||||
spca506 99fa:8988 Grandtec V.cap
|
||||
spca506 99fa:8988 Grandtec V.cap
|
||||
spca508 041e:4018 Creative Webcam Vista (PD1100)
|
||||
spca508 0461:0815 Micro Innovation IC200
|
||||
spca508 0733:0110 ViewQuest VQ110
|
||||
spca508 0af9:0010 Hama USB Sightcam 100
|
||||
spca508 0af9:0011 Hama USB Sightcam 100
|
||||
spca508 8086:0110 Intel Easy PC Camera
|
||||
spca561 041e:401a Creative Webcam Vista (PD1100)
|
||||
spca561 041e:403b Creative Webcam Vista (VF0010)
|
||||
spca561 0458:7004 Genius VideoCAM Express V2
|
||||
spca561 046d:0928 Logitech QC Express Etch2
|
||||
spca561 046d:0929 Labtec Webcam Elch2
|
||||
spca561 046d:092a Logitech QC for Notebook
|
||||
spca561 046d:092b Labtec Webcam Plus
|
||||
spca561 046d:092c Logitech QC chat Elch2
|
||||
spca561 046d:092d Logitech QC Elch2
|
||||
spca561 046d:092e Logitech QC Elch2
|
||||
spca561 046d:092f Logitech QC Elch2
|
||||
spca561 04fc:0561 Flexcam 100
|
||||
spca561 060b:a001 Maxell Compact Pc PM3
|
||||
spca561 10fd:7e50 FlyCam Usb 100
|
||||
spca561 abcd:cdee Petcam
|
||||
stk014 05e1:0893 Syntek DV4000
|
||||
spca501 040a:0002 Kodak DVC-325
|
||||
spca500 040a:0300 Kodak EZ200
|
||||
zc3xx 041e:041e Creative WebCam Live!
|
||||
spca500 041e:400a Creative PC-CAM 300
|
||||
sunplus 041e:400b Creative PC-CAM 600
|
||||
sunplus 041e:4012 PC-Cam350
|
||||
sunplus 041e:4013 Creative Pccam750
|
||||
sunplus 0458:7006 Genius Dsc 1.3 Smart
|
||||
sunplus 046d:0905 Logitech ClickSmart 820
|
||||
sunplus 046d:0960 Logitech ClickSmart 420
|
||||
sunplus 0471:0322 Philips DMVC1300K
|
||||
sunplus 04a5:3003 Benq DC 1300
|
||||
sunplus 04a5:3008 Benq DC 1500
|
||||
sunplus 04a5:300a Benq DC3410
|
||||
sunplus 04f1:1001 JVC GC A50
|
||||
sunplus 04fc:500c Sunplus CA500C
|
||||
sunplus 04fc:504a Aiptek Mini PenCam 1.3
|
||||
sunplus 04fc:504b Maxell MaxPocket LE 1.3
|
||||
sunplus 04fc:5330 Digitrex 2110
|
||||
sunplus 04fc:5360 Sunplus Generic
|
||||
sunplus 04fc:ffff Pure DigitalDakota
|
||||
sunplus 052b:1513 Megapix V4
|
||||
sunplus 0546:3155 Polaroid PDC3070
|
||||
sunplus 0546:3191 Polaroid Ion 80
|
||||
sunplus 0546:3273 Polaroid PDC2030
|
||||
sunplus 055f:c211 Kowa Bs888e Microcamera
|
||||
sunplus 055f:c230 Mustek Digicam 330K
|
||||
sunplus 055f:c232 Mustek MDC3500
|
||||
sunplus 055f:c360 Mustek DV4000 Mpeg4
|
||||
sunplus 055f:c420 Mustek gSmart Mini 2
|
||||
sunplus 055f:c430 Mustek Gsmart LCD 2
|
||||
sunplus 055f:c440 Mustek DV 3000
|
||||
sunplus 055f:c520 Mustek gSmart Mini 3
|
||||
sunplus 055f:c530 Mustek Gsmart LCD 3
|
||||
sunplus 055f:c540 Gsmart D30
|
||||
sunplus 055f:c630 Mustek MDC4000
|
||||
sunplus 055f:c650 Mustek MDC5500Z
|
||||
sunplus 05da:1018 Digital Dream Enigma 1.3
|
||||
sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom
|
||||
sunplus 0733:1311 Digital Dream Epsilon 1.3
|
||||
sunplus 0733:1314 Mercury 2.1MEG Deluxe Classic Cam
|
||||
sunplus 0733:2211 Jenoptik jdc 21 LCD
|
||||
sunplus 0733:2221 Mercury Digital Pro 3.1p
|
||||
sunplus 0733:3261 Concord 3045 spca536a
|
||||
sunplus 0733:3281 Cyberpix S550V
|
||||
sunplus 08ca:0104 Aiptek PocketDVII 1.3
|
||||
sunplus 08ca:0106 Aiptek Pocket DV3100+
|
||||
sunplus 08ca:2008 Aiptek Mini PenCam 2 M
|
||||
sunplus 08ca:2010 Aiptek PocketCam 3M
|
||||
sunplus 08ca:2016 Aiptek PocketCam 2 Mega
|
||||
sunplus 08ca:2018 Aiptek Pencam SD 2M
|
||||
sunplus 08ca:2020 Aiptek Slim 3000F
|
||||
sunplus 08ca:2022 Aiptek Slim 3200
|
||||
sunplus 08ca:2024 Aiptek DV3500 Mpeg4
|
||||
sunplus 08ca:2028 Aiptek PocketCam4M
|
||||
sunplus 08ca:2040 Aiptek PocketDV4100M
|
||||
sunplus 08ca:2042 Aiptek PocketDV5100
|
||||
sunplus 08ca:2060 Aiptek PocketDV5300
|
||||
sunplus 0d64:0303 Sunplus FashionCam DXG
|
||||
tv8532 046d:0920 QC Express
|
||||
tv8532 046d:0921 Labtec Webcam
|
||||
tv8532 0545:808b Veo Stingray
|
||||
tv8532 0545:8333 Veo Stingray
|
||||
tv8532 0923:010f ICM532 cams
|
||||
vc032x 046d:0892 Logitech Orbicam
|
||||
vc032x 046d:0896 Logitech Orbicam
|
||||
vc032x 0ac8:0321 Vimicro generic vc0321
|
||||
vc032x 0ac8:0323 Vimicro Vc0323
|
||||
vc032x 0ac8:0328 A4Tech PK-130MG
|
||||
vc032x 0ac8:c001 Sony embedded vimicro
|
||||
vc032x 0ac8:c002 Sony embedded vimicro
|
||||
vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC
|
||||
zc3xx 041e:041e Creative WebCam Live!
|
||||
zc3xx 041e:4017 Creative Webcam Mobile PD1090
|
||||
spca508 041e:4018 Creative Webcam Vista (PD1100)
|
||||
spca561 041e:401a Creative Webcam Vista (PD1100)
|
||||
zc3xx 041e:401c Creative NX
|
||||
spca505 041e:401d Creative Webcam NX ULTRA
|
||||
zc3xx 041e:401e Creative Nx Pro
|
||||
zc3xx 041e:401f Creative Webcam Notebook PD1171
|
||||
pac207 041e:4028 Creative Webcam Vista Plus
|
||||
zc3xx 041e:4029 Creative WebCam Vista Pro
|
||||
zc3xx 041e:4034 Creative Instant P0620
|
||||
zc3xx 041e:4035 Creative Instant P0620D
|
||||
zc3xx 041e:4036 Creative Live !
|
||||
zc3xx 041e:403a Creative Nx Pro 2
|
||||
spca561 041e:403b Creative Webcam Vista (VF0010)
|
||||
zc3xx 041e:4051 Creative Live!Cam Notebook Pro (VF0250)
|
||||
ov519 041e:4052 Creative Live! VISTA IM
|
||||
zc3xx 041e:4053 Creative Live!Cam Video IM
|
||||
ov519 041e:405f Creative Live! VISTA VF0330
|
||||
ov519 041e:4060 Creative Live! VISTA VF0350
|
||||
ov519 041e:4061 Creative Live! VISTA VF0400
|
||||
ov519 041e:4064 Creative Live! VISTA VF0420
|
||||
ov519 041e:4068 Creative Live! VISTA VF0470
|
||||
spca561 0458:7004 Genius VideoCAM Express V2
|
||||
sunplus 0458:7006 Genius Dsc 1.3 Smart
|
||||
zc3xx 0458:7007 Genius VideoCam V2
|
||||
zc3xx 0458:700c Genius VideoCam V3
|
||||
zc3xx 0458:700f Genius VideoCam Web V2
|
||||
sonixj 0458:7025 Genius Eye 311Q
|
||||
sonixj 045e:00f5 MicroSoft VX3000
|
||||
sonixj 045e:00f7 MicroSoft VX1000
|
||||
ov519 045e:028c Micro$oft xbox cam
|
||||
spca508 0461:0815 Micro Innovation IC200
|
||||
zc3xx 0461:0a00 MicroInnovation WebCam320
|
||||
spca500 046d:0890 Logitech QuickCam traveler
|
||||
vc032x 046d:0892 Logitech Orbicam
|
||||
vc032x 046d:0896 Logitech Orbicam
|
||||
zc3xx 046d:08a0 Logitech QC IM
|
||||
zc3xx 046d:08a1 Logitech QC IM 0x08A1 +sound
|
||||
zc3xx 046d:08a2 Labtec Webcam Pro
|
||||
|
@ -221,18 +68,173 @@ zc3xx 046d:08d9 Logitech QuickCam IM/Connect
|
|||
zc3xx 046d:08d8 Logitech Notebook Deluxe
|
||||
zc3xx 046d:08da Logitech QuickCam Messenger
|
||||
zc3xx 046d:08dd Logitech QuickCam for Notebooks
|
||||
spca500 046d:0900 Logitech Inc. ClickSmart 310
|
||||
spca500 046d:0901 Logitech Inc. ClickSmart 510
|
||||
sunplus 046d:0905 Logitech ClickSmart 820
|
||||
tv8532 046d:0920 QC Express
|
||||
tv8532 046d:0921 Labtec Webcam
|
||||
spca561 046d:0928 Logitech QC Express Etch2
|
||||
spca561 046d:0929 Labtec Webcam Elch2
|
||||
spca561 046d:092a Logitech QC for Notebook
|
||||
spca561 046d:092b Labtec Webcam Plus
|
||||
spca561 046d:092c Logitech QC chat Elch2
|
||||
spca561 046d:092d Logitech QC Elch2
|
||||
spca561 046d:092e Logitech QC Elch2
|
||||
spca561 046d:092f Logitech QC Elch2
|
||||
sunplus 046d:0960 Logitech ClickSmart 420
|
||||
sunplus 0471:0322 Philips DMVC1300K
|
||||
zc3xx 0471:0325 Philips SPC 200 NC
|
||||
zc3xx 0471:0326 Philips SPC 300 NC
|
||||
sonixj 0471:0327 Philips SPC 600 NC
|
||||
sonixj 0471:0328 Philips SPC 700 NC
|
||||
zc3xx 0471:032d Philips spc210nc
|
||||
zc3xx 0471:032e Philips spc315nc
|
||||
sonixj 0471:0330 Philips SPC 710NC
|
||||
spca501 0497:c001 Smile International
|
||||
sunplus 04a5:3003 Benq DC 1300
|
||||
sunplus 04a5:3008 Benq DC 1500
|
||||
sunplus 04a5:300a Benq DC3410
|
||||
spca500 04a5:300c Benq DC1016
|
||||
sunplus 04f1:1001 JVC GC A50
|
||||
spca561 04fc:0561 Flexcam 100
|
||||
sunplus 04fc:500c Sunplus CA500C
|
||||
sunplus 04fc:504a Aiptek Mini PenCam 1.3
|
||||
sunplus 04fc:504b Maxell MaxPocket LE 1.3
|
||||
sunplus 04fc:5330 Digitrex 2110
|
||||
sunplus 04fc:5360 Sunplus Generic
|
||||
spca500 04fc:7333 PalmPixDC85
|
||||
sunplus 04fc:ffff Pure DigitalDakota
|
||||
spca501 0506:00df 3Com HomeConnect Lite
|
||||
sunplus 052b:1513 Megapix V4
|
||||
tv8532 0545:808b Veo Stingray
|
||||
tv8532 0545:8333 Veo Stingray
|
||||
sunplus 0546:3155 Polaroid PDC3070
|
||||
sunplus 0546:3191 Polaroid Ion 80
|
||||
sunplus 0546:3273 Polaroid PDC2030
|
||||
ov519 054c:0154 Sonny toy4
|
||||
ov519 054c:0155 Sonny toy5
|
||||
zc3xx 055f:c005 Mustek Wcam300A
|
||||
spca500 055f:c200 Mustek Gsmart 300
|
||||
sunplus 055f:c211 Kowa Bs888e Microcamera
|
||||
spca500 055f:c220 Gsmart Mini
|
||||
sunplus 055f:c230 Mustek Digicam 330K
|
||||
sunplus 055f:c232 Mustek MDC3500
|
||||
sunplus 055f:c360 Mustek DV4000 Mpeg4
|
||||
sunplus 055f:c420 Mustek gSmart Mini 2
|
||||
sunplus 055f:c430 Mustek Gsmart LCD 2
|
||||
sunplus 055f:c440 Mustek DV 3000
|
||||
sunplus 055f:c520 Mustek gSmart Mini 3
|
||||
sunplus 055f:c530 Mustek Gsmart LCD 3
|
||||
sunplus 055f:c540 Gsmart D30
|
||||
sunplus 055f:c630 Mustek MDC4000
|
||||
sunplus 055f:c650 Mustek MDC5500Z
|
||||
zc3xx 055f:d003 Mustek WCam300A
|
||||
zc3xx 055f:d004 Mustek WCam300 AN
|
||||
conex 0572:0041 Creative Notebook cx11646
|
||||
ov519 05a9:0519 OmniVision
|
||||
ov519 05a9:0530 OmniVision
|
||||
ov519 05a9:4519 OmniVision
|
||||
ov519 05a9:8519 OmniVision
|
||||
sunplus 05da:1018 Digital Dream Enigma 1.3
|
||||
stk014 05e1:0893 Syntek DV4000
|
||||
spca561 060b:a001 Maxell Compact Pc PM3
|
||||
zc3xx 0698:2003 CTX M730V built in
|
||||
spca500 06bd:0404 Agfa CL20
|
||||
spca500 06be:0800 Optimedia
|
||||
sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom
|
||||
spca506 06e1:a190 ADS Instant VCD
|
||||
spca508 0733:0110 ViewQuest VQ110
|
||||
spca501 0733:0401 Intel Create and Share
|
||||
spca501 0733:0402 ViewQuest M318B
|
||||
spca505 0733:0430 Intel PC Camera Pro
|
||||
sunplus 0733:1311 Digital Dream Epsilon 1.3
|
||||
sunplus 0733:1314 Mercury 2.1MEG Deluxe Classic Cam
|
||||
sunplus 0733:2211 Jenoptik jdc 21 LCD
|
||||
sunplus 0733:2221 Mercury Digital Pro 3.1p
|
||||
sunplus 0733:3261 Concord 3045 spca536a
|
||||
sunplus 0733:3281 Cyberpix S550V
|
||||
spca506 0734:043b 3DeMon USB Capture aka
|
||||
spca500 084d:0003 D-Link DSC-350
|
||||
spca500 08ca:0103 Aiptek PocketDV
|
||||
sunplus 08ca:0104 Aiptek PocketDVII 1.3
|
||||
sunplus 08ca:0106 Aiptek Pocket DV3100+
|
||||
sunplus 08ca:2008 Aiptek Mini PenCam 2 M
|
||||
sunplus 08ca:2010 Aiptek PocketCam 3M
|
||||
sunplus 08ca:2016 Aiptek PocketCam 2 Mega
|
||||
sunplus 08ca:2018 Aiptek Pencam SD 2M
|
||||
sunplus 08ca:2020 Aiptek Slim 3000F
|
||||
sunplus 08ca:2022 Aiptek Slim 3200
|
||||
sunplus 08ca:2024 Aiptek DV3500 Mpeg4
|
||||
sunplus 08ca:2028 Aiptek PocketCam4M
|
||||
sunplus 08ca:2040 Aiptek PocketDV4100M
|
||||
sunplus 08ca:2042 Aiptek PocketDV5100
|
||||
sunplus 08ca:2060 Aiptek PocketDV5300
|
||||
tv8532 0923:010f ICM532 cams
|
||||
mars 093a:050f Mars-Semi Pc-Camera
|
||||
pac207 093a:2460 PAC207 Qtec Webcam 100
|
||||
pac207 093a:2463 Philips spc200nc pac207
|
||||
pac207 093a:2464 Labtec Webcam 1200
|
||||
pac207 093a:2468 PAC207
|
||||
pac207 093a:2470 Genius GF112
|
||||
pac207 093a:2471 PAC207 Genius VideoCam ge111
|
||||
pac207 093a:2472 PAC207 Genius VideoCam ge110
|
||||
pac7311 093a:2600 PAC7311 Typhoon
|
||||
pac7311 093a:2601 PAC7311 Phillips SPC610NC
|
||||
pac7311 093a:2603 PAC7312
|
||||
pac7311 093a:2608 PAC7311 Trust WB-3300p
|
||||
pac7311 093a:260e PAC7311 Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
|
||||
pac7311 093a:260f PAC7311 SnakeCam
|
||||
pac7311 093a:2621 PAC731x
|
||||
zc3xx 0ac8:0302 Z-star Vimicro zc0302
|
||||
vc032x 0ac8:0321 Vimicro generic vc0321
|
||||
vc032x 0ac8:0323 Vimicro Vc0323
|
||||
vc032x 0ac8:0328 A4Tech PK-130MG
|
||||
zc3xx 0ac8:301b Z-Star zc301b
|
||||
zc3xx 0ac8:303b Vimicro 0x303b
|
||||
zc3xx 0ac8:305b Z-star Vimicro zc0305b
|
||||
zc3xx 0ac8:307b Ldlc VC302+Ov7620
|
||||
vc032x 0ac8:c001 Sony embedded vimicro
|
||||
vc032x 0ac8:c002 Sony embedded vimicro
|
||||
spca508 0af9:0010 Hama USB Sightcam 100
|
||||
spca508 0af9:0011 Hama USB Sightcam 100
|
||||
sonixb 0c45:6001 Genius VideoCAM NB
|
||||
sonixb 0c45:6005 Sweex Tas5110
|
||||
sonixb 0c45:6007 Sonix sn9c101 + Tas5110D
|
||||
sonixb 0c45:6009 spcaCam@120
|
||||
sonixb 0c45:600d spcaCam@120
|
||||
sonixb 0c45:6011 MAX Webcam (Microdia - OV6650 - SN9C101G)
|
||||
sonixb 0c45:6019 Generic Sonix OV7630
|
||||
sonixb 0c45:6024 Generic Sonix Tas5130c
|
||||
sonixb 0c45:6025 Xcam Shanga
|
||||
sonixb 0c45:6028 Sonix Btc Pc380
|
||||
sonixb 0c45:6029 spcaCam@150
|
||||
sonixb 0c45:602c Generic Sonix OV7630
|
||||
sonixb 0c45:602d LIC-200 LG
|
||||
sonixb 0c45:602e Genius VideoCam Messenger
|
||||
sonixj 0c45:6040 Speed NVC 350K
|
||||
sonixj 0c45:607c Sonix sn9c102p Hv7131R
|
||||
sonixj 0c45:60c0 Sangha Sn535
|
||||
sonixj 0c45:60ec SN9C105+MO4000
|
||||
sonixj 0c45:60fb Surfer NoName
|
||||
sonixj 0c45:60fc LG-LIC300
|
||||
sonixj 0c45:612a Avant Camera
|
||||
sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix
|
||||
sonixj 0c45:6130 Sonix Pccam
|
||||
sonixj 0c45:6138 Sn9c120 Mo4000
|
||||
sonixj 0c45:613b Surfer SN-206
|
||||
sonixj 0c45:613c Sonix Pccam168
|
||||
sunplus 0d64:0303 Sunplus FashionCam DXG
|
||||
etoms 102c:6151 Qcam Sangha CIF
|
||||
etoms 102c:6251 Qcam xxxxxx VGA
|
||||
zc3xx 10fd:0128 Typhoon Webshot II USB 300k 0x0128
|
||||
spca561 10fd:7e50 FlyCam Usb 100
|
||||
zc3xx 10fd:8050 Typhoon Webshot II USB 300k
|
||||
spca501 1776:501c Arowana 300K CMOS Camera
|
||||
t613 17a1:0128 T613/TAS5130A
|
||||
vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC
|
||||
pac207 2001:f115 D-Link DSB-C120
|
||||
spca500 2899:012c Toptro Industrial
|
||||
spca508 8086:0110 Intel Easy PC Camera
|
||||
spca500 8086:0630 Intel Pocket PC Camera
|
||||
spca506 99fa:8988 Grandtec V.cap
|
||||
spca561 abcd:cdee Petcam
|
||||
|
|
|
@ -117,6 +117,7 @@ obj-$(CONFIG_USB_SN9C102) += sn9c102/
|
|||
obj-$(CONFIG_USB_ET61X251) += et61x251/
|
||||
obj-$(CONFIG_USB_PWC) += pwc/
|
||||
obj-$(CONFIG_USB_ZC0301) += zc0301/
|
||||
obj-$(CONFIG_USB_GSPCA) += gspca/
|
||||
|
||||
obj-$(CONFIG_USB_IBMCAM) += usbvideo/
|
||||
obj-$(CONFIG_USB_KONICAWC) += usbvideo/
|
||||
|
|
|
@ -2,7 +2,7 @@ config USB_GSPCA
|
|||
tristate "USB GSPCA driver"
|
||||
depends on VIDEO_V4L2
|
||||
---help---
|
||||
Say Y here if you want support for various USB cameras.
|
||||
Say Y here if you want support for various USB webcams.
|
||||
|
||||
See <file:Documentation/video4linux/gspca.txt> for more info.
|
||||
|
||||
|
|
|
@ -1,7 +1,29 @@
|
|||
obj-$(CONFIG_GSPCA) += gspca_main.o \
|
||||
gspca_pac207.o gspca_stk014.o gspca_zc3xx.o
|
||||
obj-$(CONFIG_USB_GSPCA) += gspca_main.o \
|
||||
gspca_conex.o gspca_etoms.o gspca_mars.o \
|
||||
gspca_ov519.o gspca_pac207.o gspca_pac7311.o \
|
||||
gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \
|
||||
gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \
|
||||
gspca_sunplus.o gspca_stk014.o gspca_t613.o gspca_tv8532.o \
|
||||
gspca_vc032x.o gspca_zc3xx.o
|
||||
|
||||
gspca_main-objs := gspca.o
|
||||
gspca_conex-objs := conex.o
|
||||
gspca_etoms-objs := etoms.o
|
||||
gspca_mars-objs := mars.o
|
||||
gspca_ov519-objs := ov519.o
|
||||
gspca_pac207-objs := pac207.o
|
||||
gspca_pac7311-objs := pac7311.o
|
||||
gspca_sonixb-objs := sonixb.o
|
||||
gspca_sonixj-objs := sonixj.o
|
||||
gspca_spca500-objs := spca500.o
|
||||
gspca_spca501-objs := spca501.o
|
||||
gspca_spca505-objs := spca505.o
|
||||
gspca_spca506-objs := spca506.o
|
||||
gspca_spca508-objs := spca508.o
|
||||
gspca_spca561-objs := spca561.o
|
||||
gspca_stk014-objs := stk014.o
|
||||
gspca_sunplus-objs := sunplus.o
|
||||
gspca_t613-objs := t613.o
|
||||
gspca_tv8532-objs := tv8532.o
|
||||
gspca_vc032x-objs := vc032x.o
|
||||
gspca_zc3xx-objs := zc3xx.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -35,24 +35,24 @@
|
|||
|
||||
#include "gspca.h"
|
||||
|
||||
/* option */
|
||||
#define GSPCA_HLP 0
|
||||
#undef CONFIG_VIDEO_V4L1_COMPAT
|
||||
|
||||
/* global values */
|
||||
#define DEF_NURBS 2 /* default number of URBs (mmap) */
|
||||
#define USR_NURBS 5 /* default number of URBs (userptr) */
|
||||
|
||||
MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
|
||||
MODULE_DESCRIPTION("GSPCA USB Camera Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 2, 15)
|
||||
static const char version[] = "0.2.15";
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
|
||||
static const char version[] = "2.1.0";
|
||||
|
||||
static int video_nr = -1;
|
||||
|
||||
static int comp_fac = 30; /* Buffer size ratio when compressed in % */
|
||||
|
||||
#ifdef GSPCA_DEBUG
|
||||
#ifdef VIDEO_ADV_DEBUG
|
||||
int gspca_debug = D_ERR | D_PROBE;
|
||||
EXPORT_SYMBOL(gspca_debug);
|
||||
|
||||
|
@ -81,224 +81,7 @@ static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
|
|||
#define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */
|
||||
#define GSPCA_MEMORY_READ 7
|
||||
|
||||
#ifndef GSPCA_HLP
|
||||
#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
|
||||
#else
|
||||
#define GSPCA_BUF_FLAG_DECODE 0x1000 /* internal buffer flag */
|
||||
#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE \
|
||||
| GSPCA_BUF_FLAG_DECODE)
|
||||
|
||||
static int autostart = 4;
|
||||
module_param(autostart, int, 0644);
|
||||
MODULE_PARM_DESC(autostart,
|
||||
"Automatically start the helper process");
|
||||
|
||||
/* try to start the helper process */
|
||||
static void start_hlp(void)
|
||||
{
|
||||
int ret;
|
||||
static char *argv[] = {"gspca_hlp", NULL};
|
||||
static char *env[] = {NULL};
|
||||
|
||||
if (autostart <= 0) {
|
||||
if (autostart < 0)
|
||||
PDEBUG(D_ERR|D_PROBE, "Too many helper restart");
|
||||
return;
|
||||
}
|
||||
autostart--;
|
||||
if (autostart == 0)
|
||||
autostart = -1;
|
||||
ret = call_usermodehelper("/sbin/gspca_hlp", argv, env,
|
||||
UMH_WAIT_EXEC);
|
||||
if (ret != 0)
|
||||
PDEBUG(D_ERR|D_PROBE,
|
||||
"/sbin/gspca_hlp start failed %d", ret);
|
||||
}
|
||||
|
||||
/* /dev/gspca_hlp stuff */
|
||||
#include <linux/miscdevice.h>
|
||||
#include "gspca_hlp.h"
|
||||
|
||||
/* !! possible decodings defined in decoder.c */
|
||||
static __u32 bayer_to_tb[] = {
|
||||
V4L2_PIX_FMT_SBGGR8,
|
||||
V4L2_PIX_FMT_YUYV,
|
||||
V4L2_PIX_FMT_YUV420,
|
||||
V4L2_PIX_FMT_RGB24,
|
||||
V4L2_PIX_FMT_BGR24,
|
||||
V4L2_PIX_FMT_RGB565,
|
||||
};
|
||||
static __u32 jpeg_to_tb[] = {
|
||||
V4L2_PIX_FMT_JPEG,
|
||||
V4L2_PIX_FMT_YUYV,
|
||||
V4L2_PIX_FMT_YUV420,
|
||||
V4L2_PIX_FMT_RGB24,
|
||||
V4L2_PIX_FMT_BGR24,
|
||||
V4L2_PIX_FMT_RGB565,
|
||||
};
|
||||
|
||||
/* /dev/gspca_hlp device */
|
||||
struct hlp_dev {
|
||||
struct gspca_dev *gspca_dev; /* associated device */
|
||||
struct gspca_frame *frame; /* frame being decoded */
|
||||
__u32 pixfmt; /* webcam pixel format */
|
||||
atomic_t nevent; /* nb of frames ready to decode */
|
||||
wait_queue_head_t wq; /* wait queue */
|
||||
char fr_d; /* next frame to decode */
|
||||
} *hlp;
|
||||
|
||||
static int hlp_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct hlp_dev *hlp_dev;
|
||||
|
||||
PDEBUG(D_CONF, "hlp open");
|
||||
if (hlp != 0)
|
||||
return -EBUSY;
|
||||
hlp_dev = kzalloc(sizeof *hlp_dev, GFP_KERNEL);
|
||||
if (hlp_dev == NULL) {
|
||||
err("couldn't kzalloc hlp struct");
|
||||
return -EIO;
|
||||
}
|
||||
init_waitqueue_head(&hlp_dev->wq);
|
||||
file->private_data = hlp_dev;
|
||||
hlp = hlp_dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hlp_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct gspca_dev *gspca_dev;
|
||||
int mode;
|
||||
|
||||
PDEBUG(D_CONF, "hlp close");
|
||||
file->private_data = NULL;
|
||||
|
||||
/* stop decoding */
|
||||
gspca_dev = hlp->gspca_dev;
|
||||
if (gspca_dev != 0) {
|
||||
mode = gspca_dev->curr_mode;
|
||||
gspca_dev->pixfmt = gspca_dev->cam.cam_mode[mode].pixfmt;
|
||||
}
|
||||
|
||||
/* destroy the helper structure */
|
||||
kfree(hlp);
|
||||
hlp = 0;
|
||||
|
||||
/* try to restart the helper process */
|
||||
start_hlp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t hlp_read(struct file *file, char __user *buf,
|
||||
size_t cnt, loff_t *ppos)
|
||||
{
|
||||
struct hlp_dev *hlp_dev = file->private_data;
|
||||
struct gspca_dev *gspca_dev;
|
||||
struct gspca_frame *frame;
|
||||
struct gspca_hlp_read_hd head;
|
||||
int i, j, len, ret;
|
||||
|
||||
PDEBUG(D_FRAM, "hlp read (%d)", cnt);
|
||||
|
||||
/* check / wait till a frame is ready */
|
||||
for (;;) {
|
||||
gspca_dev = hlp_dev->gspca_dev;
|
||||
if (gspca_dev != 0 && gspca_dev->streaming) {
|
||||
i = hlp_dev->fr_d; /* frame to decode */
|
||||
j = gspca_dev->fr_queue[i];
|
||||
frame = &gspca_dev->frame[j];
|
||||
if (frame->v4l2_buf.flags & GSPCA_BUF_FLAG_DECODE)
|
||||
break;
|
||||
}
|
||||
ret = wait_event_interruptible(hlp_dev->wq,
|
||||
atomic_read(&hlp_dev->nevent) > 0);
|
||||
if (ret < 0) { /* helper process is killed */
|
||||
autostart = 0; /* don't restart it */
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
atomic_dec(&hlp_dev->nevent);
|
||||
hlp_dev->fr_d = (i + 1) % gspca_dev->nframes;
|
||||
PDEBUG(D_FRAM, "hlp read q:%d i:%d d:%d o:%d",
|
||||
gspca_dev->fr_q,
|
||||
gspca_dev->fr_i,
|
||||
hlp_dev->fr_d,
|
||||
gspca_dev->fr_o);
|
||||
|
||||
hlp_dev->frame = frame; /* memorize the current frame */
|
||||
len = frame->v4l2_buf.bytesused;
|
||||
if (cnt < sizeof head - sizeof head.data + len)
|
||||
/*fixme: special errno?*/
|
||||
return -EINVAL;
|
||||
head.pixfmt_out = gspca_dev->pixfmt;
|
||||
head.pixfmt_in = hlp_dev->pixfmt;
|
||||
head.width = gspca_dev->width;
|
||||
head.height = gspca_dev->height;
|
||||
copy_to_user(buf, &head, sizeof head);
|
||||
copy_to_user(buf + sizeof head - sizeof head.data,
|
||||
frame->data, len);
|
||||
return sizeof head - sizeof head.data + len;
|
||||
}
|
||||
|
||||
static ssize_t hlp_write(struct file *file,
|
||||
const char __user *buf,
|
||||
size_t cnt, loff_t *ppos)
|
||||
{
|
||||
struct hlp_dev *hlp_dev = file->private_data;
|
||||
struct gspca_dev *gspca_dev;
|
||||
struct gspca_frame *frame;
|
||||
|
||||
PDEBUG(D_FRAM, "hlp write (%d)", cnt);
|
||||
gspca_dev = hlp_dev->gspca_dev;
|
||||
if (gspca_dev == 0)
|
||||
return cnt;
|
||||
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
|
||||
return -ERESTARTSYS;
|
||||
if (!gspca_dev->streaming)
|
||||
goto out;
|
||||
frame = hlp_dev->frame;
|
||||
hlp_dev->frame = 0;
|
||||
if (frame == 0)
|
||||
goto out;
|
||||
if (cnt > frame->v4l2_buf.length) {
|
||||
PDEBUG(D_ERR|D_FRAM, "bad frame size %d - %d",
|
||||
cnt, frame->v4l2_buf.length);
|
||||
cnt = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
copy_from_user(frame->data, buf, cnt);
|
||||
frame->v4l2_buf.bytesused = cnt;
|
||||
frame->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_QUEUED
|
||||
| GSPCA_BUF_FLAG_DECODE);
|
||||
frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
|
||||
mutex_unlock(&gspca_dev->queue_lock);
|
||||
atomic_inc(&gspca_dev->nevent);
|
||||
wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
|
||||
PDEBUG(D_FRAM, "hlp write q:%d i:%d d:%d o:%d",
|
||||
gspca_dev->fr_q,
|
||||
gspca_dev->fr_i,
|
||||
hlp_dev->fr_d,
|
||||
gspca_dev->fr_o);
|
||||
return cnt;
|
||||
out:
|
||||
mutex_unlock(&gspca_dev->queue_lock);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static struct file_operations hlp_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = hlp_open,
|
||||
.release = hlp_close,
|
||||
.read = hlp_read,
|
||||
.write = hlp_write,
|
||||
.llseek = no_llseek
|
||||
};
|
||||
static struct miscdevice hlp_device = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "gspca_hlp",
|
||||
.fops = &hlp_fops,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* VMA operations.
|
||||
|
@ -331,10 +114,14 @@ static void fill_frame(struct gspca_dev *gspca_dev,
|
|||
struct urb *urb)
|
||||
{
|
||||
struct gspca_frame *frame;
|
||||
unsigned char *data; /* address of data in the iso message */
|
||||
__u8 *data; /* address of data in the iso message */
|
||||
int i, j, len, st;
|
||||
cam_pkt_op pkt_scan;
|
||||
|
||||
if (urb->status != 0) {
|
||||
PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
|
||||
return; /* disconnection ? */
|
||||
}
|
||||
pkt_scan = gspca_dev->sd_desc->pkt_scan;
|
||||
for (i = 0; i < urb->number_of_packets; i++) {
|
||||
|
||||
|
@ -350,20 +137,21 @@ static void fill_frame(struct gspca_dev *gspca_dev,
|
|||
|
||||
/* check the packet status and length */
|
||||
len = urb->iso_frame_desc[i].actual_length;
|
||||
if (len == 0)
|
||||
continue;
|
||||
st = urb->iso_frame_desc[i].status;
|
||||
if (st) {
|
||||
PDEBUG(D_ERR, "ISOC data error: [%d] len=%d, status=%d",
|
||||
PDEBUG(D_ERR,
|
||||
"ISOC data error: [%d] len=%d, status=%d",
|
||||
i, len, st);
|
||||
gspca_dev->last_packet_type = DISCARD_PACKET;
|
||||
continue;
|
||||
}
|
||||
if (len == 0)
|
||||
continue;
|
||||
|
||||
/* let the packet be analyzed by the subdriver */
|
||||
PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
|
||||
i, urb->iso_frame_desc[i].offset, len);
|
||||
data = (unsigned char *) urb->transfer_buffer
|
||||
data = (__u8 *) urb->transfer_buffer
|
||||
+ urb->iso_frame_desc[i].offset;
|
||||
pkt_scan(gspca_dev, frame, data, len);
|
||||
}
|
||||
|
@ -390,7 +178,8 @@ static void fill_frame(struct gspca_dev *gspca_dev,
|
|||
* buffers are in user space (userptr). The frame detection
|
||||
* and copy is done by the application.
|
||||
*/
|
||||
static void isoc_irq_mmap(struct urb *urb)
|
||||
static void isoc_irq_mmap(struct urb *urb
|
||||
)
|
||||
{
|
||||
struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
|
||||
|
||||
|
@ -400,7 +189,8 @@ static void isoc_irq_mmap(struct urb *urb)
|
|||
fill_frame(gspca_dev, urb);
|
||||
}
|
||||
|
||||
static void isoc_irq_user(struct urb *urb)
|
||||
static void isoc_irq_user(struct urb *urb
|
||||
)
|
||||
{
|
||||
struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
|
||||
int i;
|
||||
|
@ -459,7 +249,7 @@ static void isoc_transfer(struct gspca_dev *gspca_dev)
|
|||
struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
|
||||
int packet_type,
|
||||
struct gspca_frame *frame,
|
||||
unsigned char *data,
|
||||
__u8 *data,
|
||||
int len)
|
||||
{
|
||||
int i, j;
|
||||
|
@ -503,23 +293,10 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
|
|||
/* if last packet, wake the application and advance in the queue */
|
||||
if (packet_type == LAST_PACKET) {
|
||||
frame->v4l2_buf.bytesused = frame->data_end - frame->data;
|
||||
#ifndef GSPCA_HLP
|
||||
frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
|
||||
frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
|
||||
atomic_inc(&gspca_dev->nevent);
|
||||
wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
|
||||
#else /*GSPCA_HLP*/
|
||||
if (hlp != 0 && hlp->gspca_dev == gspca_dev) {
|
||||
frame->v4l2_buf.flags |= GSPCA_BUF_FLAG_DECODE;
|
||||
atomic_inc(&hlp->nevent);
|
||||
wake_up_interruptible(&hlp->wq);
|
||||
} else {
|
||||
frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
|
||||
frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
|
||||
atomic_inc(&gspca_dev->nevent);
|
||||
wake_up_interruptible(&gspca_dev->wq); /* new frame */
|
||||
}
|
||||
#endif /*GSPCA_HLP*/
|
||||
i = (gspca_dev->fr_i + 1) % gspca_dev->nframes;
|
||||
gspca_dev->fr_i = i;
|
||||
PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d",
|
||||
|
@ -581,13 +358,13 @@ static void rvfree(void *mem, unsigned long size)
|
|||
static __u32 get_v4l2_depth(__u32 pixfmt)
|
||||
{
|
||||
switch (pixfmt) {
|
||||
case V4L2_PIX_FMT_BGR32:
|
||||
/* case V4L2_PIX_FMT_BGR32:
|
||||
case V4L2_PIX_FMT_RGB32:
|
||||
return 32;
|
||||
return 32; */
|
||||
case V4L2_PIX_FMT_RGB24: /* 'RGB3' */
|
||||
case V4L2_PIX_FMT_BGR24:
|
||||
return 24;
|
||||
case V4L2_PIX_FMT_RGB565: /* 'RGBP' */
|
||||
/* case V4L2_PIX_FMT_RGB565: * 'RGBP' */
|
||||
case V4L2_PIX_FMT_YUYV: /* 'YUYV' packed 4.2.2 */
|
||||
case V4L2_PIX_FMT_YYUV: /* 'YYUV' */
|
||||
return 16;
|
||||
|
@ -596,6 +373,9 @@ static __u32 get_v4l2_depth(__u32 pixfmt)
|
|||
case V4L2_PIX_FMT_MJPEG:
|
||||
case V4L2_PIX_FMT_JPEG:
|
||||
case V4L2_PIX_FMT_SBGGR8: /* 'BA81' Bayer */
|
||||
case V4L2_PIX_FMT_SN9C10X: /* 'S910' SN9C10x compression */
|
||||
case V4L2_PIX_FMT_SPCA501: /* 'S501' YUYV per line */
|
||||
case V4L2_PIX_FMT_SPCA561: /* 'S561' compressed BGGR bayer */
|
||||
return 8;
|
||||
}
|
||||
PDEBUG(D_ERR|D_CONF, "Unknown pixel format %c%c%c%c",
|
||||
|
@ -603,7 +383,7 @@ static __u32 get_v4l2_depth(__u32 pixfmt)
|
|||
(pixfmt >> 8) & 0xff,
|
||||
(pixfmt >> 16) & 0xff,
|
||||
pixfmt >> 24);
|
||||
return -EINVAL;
|
||||
return 24;
|
||||
}
|
||||
|
||||
static int gspca_get_buff_size(struct gspca_dev *gspca_dev)
|
||||
|
@ -632,7 +412,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
|
|||
count = GSPCA_MAX_FRAMES;
|
||||
/* if compressed (JPEG), reduce the buffer size */
|
||||
if (gspca_is_compressed(gspca_dev->pixfmt))
|
||||
frsz = (frsz * comp_fac) / 100 + 600; /* plus JPEG header */
|
||||
frsz = (frsz * comp_fac) / 100 + 600; /* (+ JPEG header sz) */
|
||||
frsz = PAGE_ALIGN(frsz);
|
||||
PDEBUG(D_STREAM, "new fr_sz: %d", frsz);
|
||||
gspca_dev->frsz = frsz;
|
||||
|
@ -660,17 +440,6 @@ static int frame_alloc(struct gspca_dev *gspca_dev,
|
|||
}
|
||||
}
|
||||
gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
|
||||
#ifdef GSPCA_HLP
|
||||
{
|
||||
struct hlp_dev *hlp_dev;
|
||||
|
||||
hlp_dev = hlp;
|
||||
if (hlp != 0 && hlp_dev->gspca_dev == gspca_dev) {
|
||||
hlp_dev->fr_d = 0;
|
||||
atomic_set(&hlp_dev->nevent, 0);
|
||||
}
|
||||
}
|
||||
#endif /*GSPCA_HLP*/
|
||||
gspca_dev->last_packet_type = DISCARD_PACKET;
|
||||
gspca_dev->sequence = 0;
|
||||
atomic_set(&gspca_dev->nevent, 0);
|
||||
|
@ -752,13 +521,14 @@ struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
|
|||
int i, ret;
|
||||
|
||||
intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
|
||||
ep = NULL;
|
||||
i = gspca_dev->alt; /* previous alt setting */
|
||||
while (--i > 0) { /* alt 0 is unusable */
|
||||
ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr);
|
||||
if (ep)
|
||||
break;
|
||||
}
|
||||
if (i <= 0) {
|
||||
if (ep == NULL) {
|
||||
err("no ISOC endpoint found");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -796,11 +566,14 @@ static int create_urbs(struct gspca_dev *gspca_dev,
|
|||
"isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
|
||||
/*fixme:change for userptr*/
|
||||
/*fixme:don't submit all URBs when userptr*/
|
||||
gspca_dev->nurbs = nurbs = DEF_NURBS;
|
||||
if (gspca_dev->memory == V4L2_MEMORY_MMAP)
|
||||
if (gspca_dev->memory == V4L2_MEMORY_MMAP) {
|
||||
usb_complete = isoc_irq_mmap;
|
||||
else
|
||||
nurbs = DEF_NURBS;
|
||||
} else {
|
||||
usb_complete = isoc_irq_user;
|
||||
nurbs = USR_NURBS;
|
||||
}
|
||||
gspca_dev->nurbs = nurbs;
|
||||
for (n = 0; n < nurbs; n++) {
|
||||
urb = usb_alloc_urb(npkt, GFP_KERNEL);
|
||||
if (!urb) {
|
||||
|
@ -904,16 +677,6 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
|
|||
{
|
||||
gspca_dev->streaming = 0;
|
||||
atomic_set(&gspca_dev->nevent, 0);
|
||||
#ifdef GSPCA_HLP
|
||||
{
|
||||
struct hlp_dev *hlp_dev;
|
||||
|
||||
hlp_dev = hlp;
|
||||
if (hlp_dev != 0
|
||||
&& hlp_dev->gspca_dev == gspca_dev)
|
||||
atomic_set(&hlp_dev->nevent, 0);
|
||||
}
|
||||
#endif
|
||||
if (gspca_dev->present) {
|
||||
gspca_dev->sd_desc->stopN(gspca_dev);
|
||||
destroy_urbs(gspca_dev);
|
||||
|
@ -979,15 +742,11 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv,
|
|||
struct v4l2_fmtdesc *fmtdesc)
|
||||
{
|
||||
struct gspca_dev *gspca_dev = priv;
|
||||
int i;
|
||||
#ifndef GSPCA_HLP
|
||||
int j, index;
|
||||
int i, j, index;
|
||||
__u32 fmt_tb[8];
|
||||
#endif
|
||||
|
||||
PDEBUG(D_CONF, "enum fmt cap");
|
||||
|
||||
#ifndef GSPCA_HLP
|
||||
/* give an index to each format */
|
||||
index = 0;
|
||||
j = 0;
|
||||
|
@ -1013,36 +772,6 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv,
|
|||
fmtdesc->pixelformat = fmt_tb[index];
|
||||
if (gspca_is_compressed(fmt_tb[index]))
|
||||
fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
|
||||
#else /*GSPCA_HLP*/
|
||||
/* !! code tied to the decoding functions in decoder.c */
|
||||
i = gspca_dev->cam.nmodes - 1;
|
||||
if (fmtdesc->index == 0) { /* (assume one format per subdriver) */
|
||||
fmtdesc->pixelformat = gspca_dev->cam.cam_mode[i].pixfmt;
|
||||
if (gspca_is_compressed(fmtdesc->pixelformat))
|
||||
fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
|
||||
} else {
|
||||
if (hlp == 0
|
||||
|| (hlp->gspca_dev != 0
|
||||
&& hlp->gspca_dev != gspca_dev))
|
||||
return -EINVAL;
|
||||
switch (gspca_dev->cam.cam_mode[i].pixfmt) {
|
||||
case V4L2_PIX_FMT_JPEG:
|
||||
if (fmtdesc->index >= sizeof jpeg_to_tb
|
||||
/ sizeof jpeg_to_tb[0])
|
||||
return -EINVAL;
|
||||
fmtdesc->pixelformat = jpeg_to_tb[fmtdesc->index];
|
||||
break;
|
||||
case V4L2_PIX_FMT_SBGGR8:
|
||||
if (fmtdesc->index >= sizeof bayer_to_tb
|
||||
/ sizeof bayer_to_tb[0])
|
||||
return -EINVAL;
|
||||
fmtdesc->pixelformat = bayer_to_tb[fmtdesc->index];
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#endif /*GSPCA_HLP*/
|
||||
fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
|
||||
fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
|
||||
|
@ -1057,25 +786,12 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
|
|||
{
|
||||
struct gspca_dev *gspca_dev = priv;
|
||||
|
||||
#ifdef GSPCA_HLP
|
||||
int i;
|
||||
|
||||
/* if the pixel format is not the one of the device and
|
||||
* if the helper is inactive or busy, restore */
|
||||
i = gspca_dev->curr_mode;
|
||||
if (gspca_dev->pixfmt != gspca_dev->cam.cam_mode[i].pixfmt) {
|
||||
struct hlp_dev *hlp_dev;
|
||||
|
||||
hlp_dev = hlp;
|
||||
if (hlp_dev == 0 || hlp_dev->gspca_dev != gspca_dev)
|
||||
gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixfmt;
|
||||
}
|
||||
#endif /*GSPCA_HLP*/
|
||||
|
||||
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
return -EINVAL;
|
||||
fmt->fmt.pix.width = gspca_dev->width;
|
||||
fmt->fmt.pix.height = gspca_dev->height;
|
||||
fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
|
||||
#ifdef GSPCA_DEBUG
|
||||
#ifdef VIDEO_ADV_DEBUG
|
||||
if (gspca_debug & D_CONF) {
|
||||
PDEBUG_MODE("get fmt cap",
|
||||
fmt->fmt.pix.pixelformat,
|
||||
|
@ -1099,13 +815,15 @@ static int try_fmt_cap(struct gspca_dev *gspca_dev,
|
|||
{
|
||||
int w, h, mode, mode2, frsz;
|
||||
|
||||
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
return -EINVAL;
|
||||
w = fmt->fmt.pix.width;
|
||||
h = fmt->fmt.pix.height;
|
||||
|
||||
/* (luvcview problem) */
|
||||
if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
|
||||
fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
|
||||
#ifdef GSPCA_DEBUG
|
||||
#ifdef VIDEO_ADV_DEBUG
|
||||
if (gspca_debug & D_CONF)
|
||||
PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
|
||||
#endif
|
||||
|
@ -1121,44 +839,11 @@ static int try_fmt_cap(struct gspca_dev *gspca_dev,
|
|||
if (mode2 >= 0) {
|
||||
mode = mode2;
|
||||
} else {
|
||||
__u32 pixfmt;
|
||||
|
||||
pixfmt = gspca_dev->cam.cam_mode[mode].pixfmt;
|
||||
#ifndef GSPCA_HLP
|
||||
|
||||
/* no chance, return this mode */
|
||||
fmt->fmt.pix.pixelformat = pixfmt;
|
||||
#else /*GSPCA_HLP*/
|
||||
if (hlp != 0
|
||||
&& (hlp->gspca_dev == 0
|
||||
|| hlp->gspca_dev == gspca_dev)
|
||||
/* decoding works for JPEG and Bayer only */
|
||||
&& (pixfmt == V4L2_PIX_FMT_JPEG
|
||||
|| pixfmt == V4L2_PIX_FMT_SBGGR8)) {
|
||||
switch (fmt->fmt.pix.pixelformat) {
|
||||
case V4L2_PIX_FMT_YUYV: /* 'YUYV' */
|
||||
case V4L2_PIX_FMT_BGR24: /* 'BGR3' */
|
||||
case V4L2_PIX_FMT_RGB24: /* 'RGB3' */
|
||||
case V4L2_PIX_FMT_YUV420: /* 'YU12' */
|
||||
case V4L2_PIX_FMT_RGB565: /* 'RGBP' */
|
||||
break;
|
||||
default: {
|
||||
/* return any of the supported fmt's */
|
||||
__u8 u;
|
||||
|
||||
u = get_jiffies_64();
|
||||
u %= sizeof bayer_to_tb
|
||||
/ sizeof bayer_to_tb[0] - 1;
|
||||
fmt->fmt.pix.pixelformat =
|
||||
bayer_to_tb[u + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt->fmt.pix.pixelformat = pixfmt;
|
||||
}
|
||||
#endif /*GSPCA_HLP*/
|
||||
#ifdef GSPCA_DEBUG
|
||||
fmt->fmt.pix.pixelformat =
|
||||
gspca_dev->cam.cam_mode[mode].pixfmt;
|
||||
#ifdef VIDEO_ADV_DEBUG
|
||||
if (gspca_debug & D_CONF) {
|
||||
PDEBUG_MODE("new format",
|
||||
fmt->fmt.pix.pixelformat,
|
||||
|
@ -1198,7 +883,17 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
|
|||
struct gspca_dev *gspca_dev = priv;
|
||||
int ret;
|
||||
|
||||
#ifdef GSPCA_DEBUG
|
||||
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||
/* if v4l1 got JPEG */
|
||||
if (fmt->fmt.pix.pixelformat == 0
|
||||
&& gspca_dev->streaming) {
|
||||
fmt->fmt.pix.width = gspca_dev->width;
|
||||
fmt->fmt.pix.height = gspca_dev->height;
|
||||
fmt->fmt.pix.pixelformat = gspca_dev->pixfmt;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef VIDEO_ADV_DEBUG
|
||||
if (gspca_debug & D_CONF) {
|
||||
PDEBUG_MODE("set fmt cap",
|
||||
fmt->fmt.pix.pixelformat,
|
||||
|
@ -1218,14 +913,8 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
|
|||
goto out;
|
||||
}
|
||||
|
||||
#ifndef GSPCA_HLP
|
||||
if (ret == gspca_dev->curr_mode)
|
||||
goto out; /* same mode */
|
||||
#else /*GSPCA_HLP*/
|
||||
if (ret == gspca_dev->curr_mode
|
||||
&& gspca_dev->pixfmt == fmt->fmt.pix.pixelformat)
|
||||
goto out; /* same mode */
|
||||
#endif /*GSPCA_HLP*/
|
||||
|
||||
if (gspca_dev->streaming) {
|
||||
ret = -EBUSY;
|
||||
|
@ -1236,26 +925,6 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
|
|||
gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
|
||||
gspca_dev->curr_mode = ret;
|
||||
|
||||
#ifdef GSPCA_HLP
|
||||
/* if frame decoding is required */
|
||||
if (gspca_dev->pixfmt != gspca_dev->cam.cam_mode[ret].pixfmt) {
|
||||
struct hlp_dev *hlp_dev;
|
||||
|
||||
hlp_dev = hlp;
|
||||
if (hlp_dev == 0
|
||||
|| (hlp_dev->gspca_dev != 0
|
||||
&& hlp_dev->gspca_dev != gspca_dev)) { /* helper busy */
|
||||
fmt->fmt.pix.pixelformat =
|
||||
gspca_dev->pixfmt =
|
||||
gspca_dev->cam.cam_mode[ret].pixfmt;
|
||||
} else { /* helper active */
|
||||
hlp_dev->gspca_dev = gspca_dev;
|
||||
hlp_dev->pixfmt = gspca_dev->cam.cam_mode[ret].pixfmt;
|
||||
hlp_dev->fr_d = gspca_dev->fr_i;
|
||||
}
|
||||
} else if (hlp != 0 && hlp->gspca_dev == gspca_dev)
|
||||
hlp->gspca_dev = 0;
|
||||
#endif /*GSPCA_HLP*/
|
||||
ret = 0;
|
||||
out:
|
||||
mutex_unlock(&gspca_dev->queue_lock);
|
||||
|
@ -1294,7 +963,7 @@ static int dev_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
gspca_dev->users++;
|
||||
file->private_data = gspca_dev;
|
||||
#ifdef GSPCA_DEBUG
|
||||
#ifdef VIDEO_ADV_DEBUG
|
||||
/* activate the v4l2 debug */
|
||||
if (gspca_debug & D_V4L2)
|
||||
gspca_dev->vdev.debug |= 3;
|
||||
|
@ -1329,22 +998,6 @@ static int dev_close(struct inode *inode, struct file *file)
|
|||
frame_free(gspca_dev);
|
||||
gspca_dev->capt_file = 0;
|
||||
gspca_dev->memory = GSPCA_MEMORY_NO;
|
||||
#ifdef GSPCA_HLP
|
||||
{
|
||||
struct hlp_dev *hlp_dev;
|
||||
int mode;
|
||||
|
||||
hlp_dev = hlp;
|
||||
if (hlp_dev != 0
|
||||
&& hlp_dev->gspca_dev == gspca_dev) {
|
||||
hlp_dev->gspca_dev = 0;
|
||||
hlp_dev->frame = 0;
|
||||
mode = gspca_dev->curr_mode;
|
||||
gspca_dev->pixfmt =
|
||||
gspca_dev->cam.cam_mode[mode].pixfmt;
|
||||
}
|
||||
}
|
||||
#endif /*GSPCA_HLP*/
|
||||
}
|
||||
file->private_data = NULL;
|
||||
mutex_unlock(&gspca_dev->queue_lock);
|
||||
|
@ -1370,23 +1023,38 @@ static int vidioc_querycap(struct file *file, void *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* the use of V4L2_CTRL_FLAG_NEXT_CTRL asks for the controls to be sorted */
|
||||
static int vidioc_queryctrl(struct file *file, void *priv,
|
||||
struct v4l2_queryctrl *q_ctrl)
|
||||
{
|
||||
struct gspca_dev *gspca_dev = priv;
|
||||
int i;
|
||||
u32 id;
|
||||
|
||||
PDEBUG(D_CONF, "queryctrl");
|
||||
id = q_ctrl->id;
|
||||
if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
|
||||
id &= V4L2_CTRL_ID_MASK;
|
||||
id++;
|
||||
for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
|
||||
if (id >= gspca_dev->sd_desc->ctrls[i].qctrl.id) {
|
||||
memcpy(q_ctrl,
|
||||
&gspca_dev->sd_desc->ctrls[i].qctrl,
|
||||
sizeof *q_ctrl);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
|
||||
if (q_ctrl->id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
|
||||
if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
|
||||
memcpy(q_ctrl,
|
||||
&gspca_dev->sd_desc->ctrls[i].qctrl,
|
||||
sizeof *q_ctrl);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (q_ctrl->id >= V4L2_CID_BASE
|
||||
&& q_ctrl->id <= V4L2_CID_LASTP1) {
|
||||
if (id >= V4L2_CID_BASE
|
||||
&& id <= V4L2_CID_LASTP1) {
|
||||
q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1489,13 +1157,8 @@ static int vidioc_reqbufs(struct file *file, void *priv,
|
|||
return -EINVAL;
|
||||
switch (rb->memory) {
|
||||
case V4L2_MEMORY_MMAP:
|
||||
break;
|
||||
case V4L2_MEMORY_USERPTR:
|
||||
#ifdef GSPCA_HLP
|
||||
if (hlp == 0 || hlp->gspca_dev != gspca_dev)
|
||||
break;
|
||||
#endif
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1578,7 +1241,7 @@ static int vidioc_streamon(struct file *file, void *priv,
|
|||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
#ifdef GSPCA_DEBUG
|
||||
#ifdef VIDEO_ADV_DEBUG
|
||||
if (gspca_debug & D_STREAM) {
|
||||
PDEBUG_MODE("stream on OK",
|
||||
gspca_dev->pixfmt,
|
||||
|
@ -1657,7 +1320,7 @@ static int vidioc_g_parm(struct file *filp, void *priv,
|
|||
{
|
||||
struct gspca_dev *gspca_dev = priv;
|
||||
|
||||
memset(parm, 0, sizeof parm);
|
||||
memset(parm, 0, sizeof *parm);
|
||||
parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
parm->parm.capture.readbuffers = gspca_dev->nbufread;
|
||||
return 0;
|
||||
|
@ -1677,6 +1340,12 @@ static int vidioc_s_parm(struct file *filp, void *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_std(struct file *filp, void *priv,
|
||||
v4l2_std_id *parm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||
static int vidiocgmbuf(struct file *file, void *priv,
|
||||
struct video_mbuf *mbuf)
|
||||
|
@ -1686,29 +1355,32 @@ static int vidiocgmbuf(struct file *file, void *priv,
|
|||
|
||||
PDEBUG(D_STREAM, "cgmbuf");
|
||||
if (gspca_dev->nframes == 0) {
|
||||
struct v4l2_requestbuffers rb;
|
||||
int ret;
|
||||
__u32 pixfmt;
|
||||
short width, height;
|
||||
|
||||
/* as the final format is not yet defined, allocate
|
||||
buffers with the max size */
|
||||
pixfmt = gspca_dev->pixfmt;
|
||||
width = gspca_dev->width;
|
||||
height = gspca_dev->height;
|
||||
gspca_dev->pixfmt = V4L2_PIX_FMT_BGR32;
|
||||
gspca_dev->width = 640;
|
||||
gspca_dev->height = 480;
|
||||
memset(&rb, 0, sizeof rb);
|
||||
rb.count = 4;
|
||||
rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
rb.memory = V4L2_MEMORY_MMAP;
|
||||
ret = vidioc_reqbufs(file, priv, &rb);
|
||||
gspca_dev->pixfmt = pixfmt;
|
||||
gspca_dev->width = width;
|
||||
gspca_dev->height = height;
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
{
|
||||
struct v4l2_format fmt;
|
||||
|
||||
memset(&fmt, 0, sizeof fmt);
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
i = gspca_dev->cam.nmodes - 1; /* highest mode */
|
||||
fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width;
|
||||
fmt.fmt.pix.height = gspca_dev->cam.cam_mode[i].height;
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
|
||||
ret = vidioc_s_fmt_cap(file, priv, &fmt);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
{
|
||||
struct v4l2_requestbuffers rb;
|
||||
|
||||
memset(&rb, 0, sizeof rb);
|
||||
rb.count = 4;
|
||||
rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
rb.memory = V4L2_MEMORY_MMAP;
|
||||
ret = vidioc_reqbufs(file, priv, &rb);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
mbuf->frames = gspca_dev->nframes;
|
||||
mbuf->size = gspca_dev->frsz * gspca_dev->nframes;
|
||||
|
@ -1951,7 +1623,7 @@ static int vidioc_qbuf(struct file *file, void *priv,
|
|||
|
||||
if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
|
||||
frame->data = frame->data_end =
|
||||
(unsigned char *) v4l2_buf->m.userptr;
|
||||
(__u8 *) v4l2_buf->m.userptr;
|
||||
frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
|
||||
frame->v4l2_buf.length = v4l2_buf->length;
|
||||
}
|
||||
|
@ -2154,6 +1826,9 @@ static struct file_operations dev_fops = {
|
|||
.read = dev_read,
|
||||
.mmap = dev_mmap,
|
||||
.ioctl = video_ioctl2,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = v4l_compat_ioctl32,
|
||||
#endif
|
||||
.llseek = no_llseek,
|
||||
.poll = dev_poll,
|
||||
};
|
||||
|
@ -2186,6 +1861,7 @@ static struct video_device gspca_template = {
|
|||
.vidioc_s_jpegcomp = vidioc_s_jpegcomp,
|
||||
.vidioc_g_parm = vidioc_g_parm,
|
||||
.vidioc_s_parm = vidioc_s_parm,
|
||||
.vidioc_s_std = vidioc_s_std,
|
||||
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||
.vidiocgmbuf = vidiocgmbuf,
|
||||
#endif
|
||||
|
@ -2207,12 +1883,8 @@ int gspca_dev_probe(struct usb_interface *intf,
|
|||
struct gspca_dev *gspca_dev;
|
||||
struct usb_device *dev = interface_to_usbdev(intf);
|
||||
int ret;
|
||||
__u16 vendor;
|
||||
__u16 product;
|
||||
|
||||
vendor = id->idVendor;
|
||||
product = id->idProduct;
|
||||
PDEBUG(D_PROBE, "probing %04x:%04x", vendor, product);
|
||||
PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
|
||||
|
||||
/* we don't handle multi-config cameras */
|
||||
if (dev->descriptor.bNumConfigurations != 1)
|
||||
|
@ -2309,35 +1981,24 @@ EXPORT_SYMBOL(gspca_disconnect);
|
|||
/* -- module insert / remove -- */
|
||||
static int __init gspca_init(void)
|
||||
{
|
||||
#ifdef GSPCA_HLP
|
||||
int ret;
|
||||
|
||||
/* create /dev/gspca_hlp */
|
||||
ret = misc_register(&hlp_device);
|
||||
if (ret < 0)
|
||||
err("misc_register err %d", ret);
|
||||
start_hlp(); /* try to start the helper process */
|
||||
#endif
|
||||
info("main v%s registered", version);
|
||||
return 0;
|
||||
}
|
||||
static void __exit gspca_exit(void)
|
||||
{
|
||||
#ifdef GSPCA_HLP
|
||||
misc_deregister(&hlp_device);
|
||||
#endif
|
||||
info("main deregistered");
|
||||
}
|
||||
|
||||
module_init(gspca_init);
|
||||
module_exit(gspca_exit);
|
||||
|
||||
#ifdef VIDEO_ADV_DEBUG
|
||||
module_param_named(debug, gspca_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug,
|
||||
"Debug (bit) 0x01:error 0x02:probe 0x04:config"
|
||||
" 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout"
|
||||
" 0x0100: v4l2");
|
||||
|
||||
#endif
|
||||
module_param(comp_fac, int, 0644);
|
||||
MODULE_PARM_DESC(comp_fac,
|
||||
"Buffer size ratio when compressed in percent");
|
||||
|
|
|
@ -9,7 +9,26 @@
|
|||
#include <media/v4l2-common.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#ifdef GSPCA_DEBUG
|
||||
/* values in 2.6.27 */
|
||||
#ifndef V4L2_PIX_FMT_SPCA501
|
||||
#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S', '5', '0', '1')
|
||||
#endif
|
||||
#ifndef V4L2_PIX_FMT_SPCA561
|
||||
#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1')
|
||||
#endif
|
||||
|
||||
/* values in 2.6.26 */
|
||||
#ifndef V4L2_CID_POWER_LINE_FREQUENCY
|
||||
#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24)
|
||||
#endif
|
||||
#ifndef V4L2_CID_WHITE_BALANCE_TEMPERATURE
|
||||
#define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE + 26)
|
||||
#endif
|
||||
#ifndef V4L2_CID_SHARPNESS
|
||||
#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27)
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_ADV_DEBUG
|
||||
/* GSPCA our debug messages */
|
||||
extern int gspca_debug;
|
||||
#define PDEBUG(level, fmt, args...) \
|
||||
|
@ -47,7 +66,7 @@ extern int gspca_debug;
|
|||
|
||||
#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
|
||||
/* ISOC transfers */
|
||||
#define MAX_NURBS 32 /* max number of URBs (read & userptr) */
|
||||
#define MAX_NURBS 16 /* max number of URBs */
|
||||
#define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */
|
||||
#define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */
|
||||
|
||||
|
@ -79,7 +98,7 @@ typedef int (*cam_qmnu_op) (struct gspca_dev *,
|
|||
struct v4l2_querymenu *);
|
||||
typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame,
|
||||
unsigned char *data,
|
||||
__u8 *data,
|
||||
int len);
|
||||
|
||||
struct ctrl {
|
||||
|
@ -116,8 +135,8 @@ struct sd_desc {
|
|||
#define LAST_PACKET 3
|
||||
|
||||
struct gspca_frame {
|
||||
unsigned char *data; /* frame buffer */
|
||||
unsigned char *data_end; /* end of frame while filling */
|
||||
__u8 *data; /* frame buffer */
|
||||
__u8 *data_end; /* end of frame while filling */
|
||||
int vma_use_count;
|
||||
struct v4l2_buffer v4l2_buf;
|
||||
};
|
||||
|
@ -135,7 +154,7 @@ struct gspca_dev {
|
|||
|
||||
__u8 *frbuf; /* buffer for nframes */
|
||||
struct gspca_frame frame[GSPCA_MAX_FRAMES];
|
||||
unsigned int frsz; /* frame size */
|
||||
__u32 frsz; /* frame size */
|
||||
char nframes; /* number of frames */
|
||||
char fr_i; /* frame being filled */
|
||||
char fr_q; /* next frame to queue */
|
||||
|
@ -145,10 +164,10 @@ struct gspca_dev {
|
|||
|
||||
__u8 iface; /* USB interface number */
|
||||
__u8 alt; /* USB alternate setting */
|
||||
unsigned char curr_mode; /* current camera mode */
|
||||
__u8 curr_mode; /* current camera mode */
|
||||
__u32 pixfmt; /* current mode parameters */
|
||||
short width;
|
||||
short height;
|
||||
__u16 width;
|
||||
__u16 height;
|
||||
|
||||
atomic_t nevent; /* number of frames done */
|
||||
wait_queue_head_t wq; /* wait queue */
|
||||
|
@ -176,6 +195,6 @@ void gspca_disconnect(struct usb_interface *intf);
|
|||
struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
|
||||
int packet_type,
|
||||
struct gspca_frame *frame,
|
||||
unsigned char *data,
|
||||
__u8 *data,
|
||||
int len);
|
||||
#endif /* GSPCAV2_H */
|
||||
|
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* Mars-Semi MR97311A library
|
||||
* Copyright (C) 2005 <bradlch@hotmail.com>
|
||||
*
|
||||
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define MODULE_NAME "mars"
|
||||
|
||||
#include "gspca.h"
|
||||
#include "jpeg.h"
|
||||
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
|
||||
static const char version[] = "2.1.0";
|
||||
|
||||
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
|
||||
MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* specific webcam descriptor */
|
||||
struct sd {
|
||||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||||
|
||||
char qindex;
|
||||
};
|
||||
|
||||
/* V4L2 controls supported by the driver */
|
||||
static struct ctrl sd_ctrls[] = {
|
||||
};
|
||||
|
||||
static struct cam_mode vga_mode[] = {
|
||||
{V4L2_PIX_FMT_JPEG, 320, 240, 2},
|
||||
{V4L2_PIX_FMT_JPEG, 640, 480, 1},
|
||||
};
|
||||
|
||||
/* MI Register table //elvis */
|
||||
enum {
|
||||
REG_HW_MI_0,
|
||||
REG_HW_MI_1,
|
||||
REG_HW_MI_2,
|
||||
REG_HW_MI_3,
|
||||
REG_HW_MI_4,
|
||||
REG_HW_MI_5,
|
||||
REG_HW_MI_6,
|
||||
REG_HW_MI_7,
|
||||
REG_HW_MI_9 = 0x09,
|
||||
REG_HW_MI_B = 0x0B,
|
||||
REG_HW_MI_C,
|
||||
REG_HW_MI_D,
|
||||
REG_HW_MI_1E = 0x1E,
|
||||
REG_HW_MI_20 = 0x20,
|
||||
REG_HW_MI_2B = 0x2B,
|
||||
REG_HW_MI_2C,
|
||||
REG_HW_MI_2D,
|
||||
REG_HW_MI_2E,
|
||||
REG_HW_MI_35 = 0x35,
|
||||
REG_HW_MI_5F = 0x5f,
|
||||
REG_HW_MI_60,
|
||||
REG_HW_MI_61,
|
||||
REG_HW_MI_62,
|
||||
REG_HW_MI_63,
|
||||
REG_HW_MI_64,
|
||||
REG_HW_MI_F1 = 0xf1,
|
||||
ATTR_TOTAL_MI_REG = 242
|
||||
};
|
||||
|
||||
static int pcam_reg_write(struct usb_device *dev,
|
||||
__u16 index, unsigned char *value, int length)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = usb_control_msg(dev,
|
||||
usb_sndbulkpipe(dev, 4),
|
||||
0x12,
|
||||
/* ?? 0xc8 = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_??? !? */
|
||||
0xc8,
|
||||
0, /* value */
|
||||
index, value, length, 500);
|
||||
PDEBUG(D_USBO, "reg write: 0x%02X , result = 0x%x", index, rc);
|
||||
|
||||
if (rc < 0)
|
||||
PDEBUG(D_ERR, "reg write: error %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void MISensor_BulkWrite(struct usb_device *dev, unsigned short *pch,
|
||||
char Address)
|
||||
{
|
||||
int result;
|
||||
unsigned char data[6];
|
||||
|
||||
data[0] = 0x1f;
|
||||
data[1] = 0;
|
||||
data[2] = Address;
|
||||
data[3] = *pch >> 8; /* high byte */
|
||||
data[4] = *pch; /* low byte */
|
||||
data[5] = 0;
|
||||
|
||||
result = usb_control_msg(dev,
|
||||
usb_sndbulkpipe(dev, 4),
|
||||
0x12,
|
||||
/* ?? 0xc8 = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_??? !? */
|
||||
0xc8,
|
||||
0, /* value */
|
||||
Address, /* index */
|
||||
data, 5, 500);
|
||||
PDEBUG(D_USBO, "bulk write 0x%02x = 0x%04x", Address, *pch);
|
||||
|
||||
if (result < 0)
|
||||
PDEBUG(D_ERR, "reg write: error %d", result);
|
||||
}
|
||||
|
||||
/* this function is called at probe time */
|
||||
static int sd_config(struct gspca_dev *gspca_dev,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct cam *cam;
|
||||
|
||||
cam = &gspca_dev->cam;
|
||||
cam->dev_name = (char *) id->driver_info;
|
||||
cam->epaddr = 0x01;
|
||||
cam->cam_mode = vga_mode;
|
||||
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
|
||||
sd->qindex = 1; /* set the quantization table */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this function is called at open time */
|
||||
static int sd_open(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sd_start(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
int err_code;
|
||||
__u8 data[12];
|
||||
__u16 MI_buf[242];
|
||||
int h_size, v_size;
|
||||
int intpipe;
|
||||
/* struct usb_device *dev = pcam->dev; */
|
||||
memset(data, 0, sizeof data);
|
||||
memset(MI_buf, 0, sizeof MI_buf);
|
||||
|
||||
PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface);
|
||||
if (usb_set_interface(dev, gspca_dev->iface, 8) < 0) {
|
||||
PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error");
|
||||
return;
|
||||
}
|
||||
|
||||
data[0] = 0x01; /* address */
|
||||
data[1] = 0x01;
|
||||
|
||||
err_code = pcam_reg_write(dev, data[0], data, 0x02);
|
||||
if (err_code < 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
Initialize the MR97113 chip register
|
||||
*/
|
||||
data[0] = 0x00; /* address */
|
||||
data[1] = 0x0c | 0x01; /* reg 0 */
|
||||
data[2] = 0x01; /* reg 1 */
|
||||
h_size = gspca_dev->width;
|
||||
v_size = gspca_dev->height;
|
||||
data[3] = h_size / 8; /* h_size , reg 2 */
|
||||
data[4] = v_size / 8; /* v_size , reg 3 */
|
||||
data[5] = 0x30; /* reg 4, MI, PAS5101 :
|
||||
* 0x30 for 24mhz , 0x28 for 12mhz */
|
||||
data[6] = 4; /* reg 5, H start */
|
||||
data[7] = 0xc0; /* reg 6, gamma 1.5 */
|
||||
data[8] = 3; /* reg 7, V start */
|
||||
/* if(h_size == 320 ) */
|
||||
/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */
|
||||
/* else */
|
||||
data[9] = 0x52; /* reg 8, 24MHz, no scale down */
|
||||
data[10] = 0x5d; /* reg 9, I2C device address
|
||||
* [for PAS5101 (0x40)] [for MI (0x5d)] */
|
||||
|
||||
err_code = pcam_reg_write(dev, data[0], data, 0x0b);
|
||||
if (err_code < 0)
|
||||
return;
|
||||
|
||||
data[0] = 0x23; /* address */
|
||||
data[1] = 0x09; /* reg 35, append frame header */
|
||||
|
||||
err_code = pcam_reg_write(dev, data[0], data, 0x02);
|
||||
if (err_code < 0) {
|
||||
PDEBUG(D_ERR, "Register write failed");
|
||||
return;
|
||||
}
|
||||
|
||||
data[0] = 0x3C; /* address */
|
||||
/* if (pcam->width == 1280) */
|
||||
/* data[1] = 200; * reg 60, pc-cam frame size
|
||||
* (unit: 4KB) 800KB */
|
||||
/* else */
|
||||
data[1] = 50; /* 50 reg 60, pc-cam frame size
|
||||
* (unit: 4KB) 200KB */
|
||||
err_code = pcam_reg_write(dev, data[0], data, 0x02);
|
||||
if (err_code < 0)
|
||||
return;
|
||||
|
||||
if (0) { /* fixed dark-gain */
|
||||
data[1] = 0; /* reg 94, Y Gain (1.75) */
|
||||
data[2] = 0; /* reg 95, UV Gain (1.75) */
|
||||
data[3] = 0x3f; /* reg 96, Y Gain/UV Gain/disable auto dark-gain */
|
||||
data[4] = 0; /* reg 97, set fixed dark level */
|
||||
data[5] = 0; /* reg 98, don't care */
|
||||
} else { /* auto dark-gain */
|
||||
data[1] = 0; /* reg 94, Y Gain (auto) */
|
||||
data[2] = 0; /* reg 95, UV Gain (1.75) */
|
||||
data[3] = 0x78; /* reg 96, Y Gain/UV Gain/disable auto dark-gain */
|
||||
switch (gspca_dev->width) {
|
||||
/* case 1280: */
|
||||
/* data[4] = 154;
|
||||
* reg 97, %3 shadow point (unit: 256 pixel) */
|
||||
/* data[5] = 51;
|
||||
* reg 98, %1 highlight point
|
||||
* (uint: 256 pixel) */
|
||||
/* break; */
|
||||
default:
|
||||
/* case 640: */
|
||||
data[4] = 36; /* reg 97, %3 shadow point
|
||||
* (unit: 256 pixel) */
|
||||
data[5] = 12; /* reg 98, %1 highlight point
|
||||
* (uint: 256 pixel) */
|
||||
break;
|
||||
case 320:
|
||||
data[4] = 9; /* reg 97, %3 shadow point
|
||||
* (unit: 256 pixel) */
|
||||
data[5] = 3; /* reg 98, %1 highlight point
|
||||
* (uint: 256 pixel) */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* auto dark-gain */
|
||||
data[0] = 0x5e; /* address */
|
||||
|
||||
err_code = pcam_reg_write(dev, data[0], data, 0x06);
|
||||
if (err_code < 0)
|
||||
return;
|
||||
|
||||
data[0] = 0x67;
|
||||
data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */
|
||||
err_code = pcam_reg_write(dev, data[0], data, 0x02);
|
||||
if (err_code < 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* initialize the value of MI sensor...
|
||||
*/
|
||||
MI_buf[REG_HW_MI_1] = 0x000a;
|
||||
MI_buf[REG_HW_MI_2] = 0x000c;
|
||||
MI_buf[REG_HW_MI_3] = 0x0405;
|
||||
MI_buf[REG_HW_MI_4] = 0x0507;
|
||||
/* mi_Attr_Reg_[REG_HW_MI_5] = 0x01ff;//13 */
|
||||
MI_buf[REG_HW_MI_5] = 0x0013; /* 13 */
|
||||
MI_buf[REG_HW_MI_6] = 0x001f; /* vertical blanking */
|
||||
/* mi_Attr_Reg_[REG_HW_MI_6] = 0x0400; // vertical blanking */
|
||||
MI_buf[REG_HW_MI_7] = 0x0002;
|
||||
/* mi_Attr_Reg_[REG_HW_MI_9] = 0x015f; */
|
||||
/* mi_Attr_Reg_[REG_HW_MI_9] = 0x030f; */
|
||||
MI_buf[REG_HW_MI_9] = 0x0374;
|
||||
MI_buf[REG_HW_MI_B] = 0x0000;
|
||||
MI_buf[REG_HW_MI_C] = 0x0000;
|
||||
MI_buf[REG_HW_MI_D] = 0x0000;
|
||||
MI_buf[REG_HW_MI_1E] = 0x8000;
|
||||
/* mi_Attr_Reg_[REG_HW_MI_20] = 0x1104; */
|
||||
MI_buf[REG_HW_MI_20] = 0x1104; /* 0x111c; */
|
||||
MI_buf[REG_HW_MI_2B] = 0x0008;
|
||||
/* mi_Attr_Reg_[REG_HW_MI_2C] = 0x000f; */
|
||||
MI_buf[REG_HW_MI_2C] = 0x001f; /* lita suggest */
|
||||
MI_buf[REG_HW_MI_2D] = 0x0008;
|
||||
MI_buf[REG_HW_MI_2E] = 0x0008;
|
||||
MI_buf[REG_HW_MI_35] = 0x0051;
|
||||
MI_buf[REG_HW_MI_5F] = 0x0904; /* fail to write */
|
||||
MI_buf[REG_HW_MI_60] = 0x0000;
|
||||
MI_buf[REG_HW_MI_61] = 0x0000;
|
||||
MI_buf[REG_HW_MI_62] = 0x0498;
|
||||
MI_buf[REG_HW_MI_63] = 0x0000;
|
||||
MI_buf[REG_HW_MI_64] = 0x0000;
|
||||
MI_buf[REG_HW_MI_F1] = 0x0001;
|
||||
/* changing while setting up the different value of dx/dy */
|
||||
|
||||
if (gspca_dev->width != 1280) {
|
||||
MI_buf[0x01] = 0x010a;
|
||||
MI_buf[0x02] = 0x014c;
|
||||
MI_buf[0x03] = 0x01e5;
|
||||
MI_buf[0x04] = 0x0287;
|
||||
}
|
||||
MI_buf[0x20] = 0x1104;
|
||||
|
||||
MISensor_BulkWrite(dev, MI_buf + 1, 1);
|
||||
MISensor_BulkWrite(dev, MI_buf + 2, 2);
|
||||
MISensor_BulkWrite(dev, MI_buf + 3, 3);
|
||||
MISensor_BulkWrite(dev, MI_buf + 4, 4);
|
||||
MISensor_BulkWrite(dev, MI_buf + 5, 5);
|
||||
MISensor_BulkWrite(dev, MI_buf + 6, 6);
|
||||
MISensor_BulkWrite(dev, MI_buf + 7, 7);
|
||||
MISensor_BulkWrite(dev, MI_buf + 9, 9);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x0b, 0x0b);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x0c, 0x0c);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x0d, 0x0d);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x1e, 0x1e);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x20, 0x20);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x2b, 0x2b);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x2c, 0x2c);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x2d, 0x2d);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x2e, 0x2e);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x35, 0x35);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x5f, 0x5f);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x60, 0x60);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x61, 0x61);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x62, 0x62);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x63, 0x63);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0x64, 0x64);
|
||||
MISensor_BulkWrite(dev, MI_buf + 0xf1, 0xf1);
|
||||
|
||||
intpipe = usb_sndintpipe(dev, 0);
|
||||
err_code = usb_clear_halt(dev, intpipe);
|
||||
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x4d; /* ISOC transfering enable... */
|
||||
pcam_reg_write(dev, data[0], data, 0x02);
|
||||
}
|
||||
|
||||
static void sd_stopN(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
int result;
|
||||
__u8 data[2];
|
||||
|
||||
data[0] = 1;
|
||||
data[1] = 0;
|
||||
result = pcam_reg_write(gspca_dev->dev, data[0], data, 2);
|
||||
if (result < 0)
|
||||
PDEBUG(D_ERR, "Camera Stop failed");
|
||||
}
|
||||
|
||||
static void sd_stop0(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void sd_close(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame, /* target */
|
||||
unsigned char *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int p;
|
||||
|
||||
if (len < 6) {
|
||||
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
|
||||
return;
|
||||
}
|
||||
for (p = 0; p < len - 6; p++) {
|
||||
if (data[0 + p] == 0xff
|
||||
&& data[1 + p] == 0xff
|
||||
&& data[2 + p] == 0x00
|
||||
&& data[3 + p] == 0xff
|
||||
&& data[4 + p] == 0x96) {
|
||||
if (data[5 + p] == 0x64
|
||||
|| data[5 + p] == 0x65
|
||||
|| data[5 + p] == 0x66
|
||||
|| data[5 + p] == 0x67) {
|
||||
PDEBUG(D_PACK, "sof offset: %d leng: %d",
|
||||
p, len);
|
||||
frame = gspca_frame_add(gspca_dev, LAST_PACKET,
|
||||
frame, data, 0);
|
||||
|
||||
/* put the JPEG header */
|
||||
jpeg_put_header(gspca_dev, frame,
|
||||
sd->qindex, 0x21);
|
||||
data += 16;
|
||||
len -= 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
|
||||
}
|
||||
|
||||
/* sub-driver description */
|
||||
static struct sd_desc sd_desc = {
|
||||
.name = MODULE_NAME,
|
||||
.ctrls = sd_ctrls,
|
||||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||||
.config = sd_config,
|
||||
.open = sd_open,
|
||||
.start = sd_start,
|
||||
.stopN = sd_stopN,
|
||||
.stop0 = sd_stop0,
|
||||
.close = sd_close,
|
||||
.pkt_scan = sd_pkt_scan,
|
||||
};
|
||||
|
||||
/* -- module initialisation -- */
|
||||
#define DVNM(name) .driver_info = (kernel_ulong_t) name
|
||||
static __devinitdata struct usb_device_id device_table[] = {
|
||||
{USB_DEVICE(0x093a, 0x050f), DVNM("Mars-Semi Pc-Camera")},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, device_table);
|
||||
|
||||
/* -- device connect -- */
|
||||
static int sd_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
|
||||
THIS_MODULE);
|
||||
}
|
||||
|
||||
static struct usb_driver sd_driver = {
|
||||
.name = MODULE_NAME,
|
||||
.id_table = device_table,
|
||||
.probe = sd_probe,
|
||||
.disconnect = gspca_disconnect,
|
||||
};
|
||||
|
||||
/* -- module insert / remove -- */
|
||||
static int __init sd_mod_init(void)
|
||||
{
|
||||
if (usb_register(&sd_driver) < 0)
|
||||
return -1;
|
||||
PDEBUG(D_PROBE, "v%s registered", version);
|
||||
return 0;
|
||||
}
|
||||
static void __exit sd_mod_exit(void)
|
||||
{
|
||||
usb_deregister(&sd_driver);
|
||||
PDEBUG(D_PROBE, "deregistered");
|
||||
}
|
||||
|
||||
module_init(sd_mod_init);
|
||||
module_exit(sd_mod_exit);
|
File diff suppressed because it is too large
Load Diff
|
@ -27,8 +27,8 @@
|
|||
|
||||
#include "gspca.h"
|
||||
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 2, 15)
|
||||
static const char version[] = "0.2.15";
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
|
||||
static const char version[] = "2.1.0";
|
||||
|
||||
MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
|
||||
MODULE_DESCRIPTION("Pixart PAC207");
|
||||
|
@ -297,7 +297,6 @@ static int sd_open(struct gspca_dev *gspca_dev)
|
|||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->autogain = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -338,7 +337,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
|
|||
|
||||
pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
|
||||
pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
|
||||
udelay(1000); /* taken from gspca */
|
||||
msleep(10);
|
||||
pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
|
||||
|
||||
sd->sof_read = 0;
|
||||
|
@ -743,8 +742,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
|||
PDEBUG(D_STREAM, "Incomplete frame");
|
||||
}
|
||||
pac207_decode_frame_init(gspca_dev);
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL,
|
||||
0);
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
|
||||
len -= sof - data;
|
||||
data = sof;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,754 @@
|
|||
/*
|
||||
* Pixart PAC7311 library
|
||||
* Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
|
||||
*
|
||||
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define MODULE_NAME "pac7311"
|
||||
|
||||
#include "gspca.h"
|
||||
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
|
||||
static const char version[] = "2.1.0";
|
||||
|
||||
MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
|
||||
MODULE_DESCRIPTION("Pixart PAC7311");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* specific webcam descriptor */
|
||||
struct sd {
|
||||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||||
|
||||
int avg_lum;
|
||||
|
||||
unsigned char brightness;
|
||||
#define BRIGHTNESS_MAX 0x20
|
||||
unsigned char contrast;
|
||||
unsigned char colors;
|
||||
unsigned char autogain;
|
||||
|
||||
char ffseq;
|
||||
signed char ag_cnt;
|
||||
#define AG_CNT_START 13
|
||||
};
|
||||
|
||||
/* V4L2 controls supported by the driver */
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
|
||||
static struct ctrl sd_ctrls[] = {
|
||||
#define SD_BRIGHTNESS 0
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_BRIGHTNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Brightness",
|
||||
.minimum = 0,
|
||||
.maximum = BRIGHTNESS_MAX,
|
||||
.step = 1,
|
||||
.default_value = 0x10,
|
||||
},
|
||||
.set = sd_setbrightness,
|
||||
.get = sd_getbrightness,
|
||||
},
|
||||
#define SD_CONTRAST 1
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_CONTRAST,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Contrast",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 127,
|
||||
},
|
||||
.set = sd_setcontrast,
|
||||
.get = sd_getcontrast,
|
||||
},
|
||||
#define SD_COLOR 2
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_SATURATION,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Color",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 127,
|
||||
},
|
||||
.set = sd_setcolors,
|
||||
.get = sd_getcolors,
|
||||
},
|
||||
#define SD_AUTOGAIN 3
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_AUTOGAIN,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "Auto Gain",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
},
|
||||
.set = sd_setautogain,
|
||||
.get = sd_getautogain,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_mode vga_mode[] = {
|
||||
{V4L2_PIX_FMT_JPEG, 160, 120, 2},
|
||||
{V4L2_PIX_FMT_JPEG, 320, 240, 1},
|
||||
{V4L2_PIX_FMT_JPEG, 640, 480, 0},
|
||||
};
|
||||
|
||||
#define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */
|
||||
|
||||
const unsigned char pac7311_jpeg_header[] = {
|
||||
0xff, 0xd8,
|
||||
0xff, 0xe0, 0x00, 0x03, 0x20,
|
||||
0xff, 0xc0, 0x00, 0x11, 0x08,
|
||||
0x01, 0xe0, /* 12: height */
|
||||
0x02, 0x80, /* 14: width */
|
||||
0x03, /* 16 */
|
||||
0x01, 0x21, 0x00,
|
||||
0x02, 0x11, 0x01,
|
||||
0x03, 0x11, 0x01,
|
||||
0xff, 0xdb, 0x00, 0x84,
|
||||
0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
|
||||
0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
|
||||
0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
|
||||
0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
|
||||
0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
|
||||
0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
|
||||
0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
|
||||
0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
|
||||
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
|
||||
0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
|
||||
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
|
||||
0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
|
||||
0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
|
||||
0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
|
||||
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
|
||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
|
||||
0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
|
||||
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
|
||||
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
|
||||
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
|
||||
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
|
||||
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
|
||||
0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
|
||||
0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
||||
0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
|
||||
0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
|
||||
0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
|
||||
0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
|
||||
0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
|
||||
0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
|
||||
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
|
||||
0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
|
||||
0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
|
||||
0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
|
||||
0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
|
||||
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
|
||||
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
|
||||
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
|
||||
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
|
||||
0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
|
||||
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
|
||||
0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
|
||||
0x11, 0x00, 0x3f, 0x00
|
||||
};
|
||||
|
||||
static void reg_w(struct usb_device *dev,
|
||||
__u16 req,
|
||||
__u16 value,
|
||||
__u16 index,
|
||||
__u8 *buffer, __u16 length)
|
||||
{
|
||||
usb_control_msg(dev,
|
||||
usb_sndctrlpipe(dev, 0),
|
||||
req,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
value, index, buffer, length,
|
||||
500);
|
||||
}
|
||||
|
||||
static void pac7311_reg_read(struct usb_device *dev, __u16 index,
|
||||
__u8 *buffer)
|
||||
{
|
||||
usb_control_msg(dev,
|
||||
usb_rcvctrlpipe(dev, 0),
|
||||
0, /* request */
|
||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0, /* value */
|
||||
index, buffer, 1,
|
||||
500);
|
||||
}
|
||||
|
||||
static void pac7311_reg_write(struct usb_device *dev,
|
||||
__u16 index,
|
||||
__u8 value)
|
||||
{
|
||||
__u8 buf;
|
||||
|
||||
buf = value;
|
||||
reg_w(dev, 0x00, value, index, &buf, 1);
|
||||
}
|
||||
|
||||
/* this function is called at probe time */
|
||||
static int sd_config(struct gspca_dev *gspca_dev,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
struct cam *cam;
|
||||
|
||||
PDEBUG(D_CONF, "Find Sensor PAC7311");
|
||||
pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
|
||||
pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
|
||||
pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
|
||||
pac7311_reg_write(dev, 0xff, 0x04);
|
||||
pac7311_reg_write(dev, 0x27, 0x80);
|
||||
pac7311_reg_write(dev, 0x28, 0xca);
|
||||
pac7311_reg_write(dev, 0x29, 0x53);
|
||||
pac7311_reg_write(dev, 0x2a, 0x0e);
|
||||
pac7311_reg_write(dev, 0xff, 0x01);
|
||||
pac7311_reg_write(dev, 0x3e, 0x20);
|
||||
|
||||
cam = &gspca_dev->cam;
|
||||
cam->dev_name = (char *) id->driver_info;
|
||||
cam->epaddr = 0x05;
|
||||
cam->cam_mode = vga_mode;
|
||||
cam->nmodes = ARRAY_SIZE(vga_mode);
|
||||
|
||||
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
|
||||
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
|
||||
sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
|
||||
sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setbrightness(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int brightness;
|
||||
|
||||
/*jfm: inverted?*/
|
||||
brightness = BRIGHTNESS_MAX - sd->brightness;
|
||||
pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
|
||||
/* pac7311_reg_write(gspca_dev->dev, 0x0e, 0x00); */
|
||||
pac7311_reg_write(gspca_dev->dev, 0x0f, brightness);
|
||||
/* load registers to sensor (Bit 0, auto clear) */
|
||||
pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
|
||||
PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
|
||||
}
|
||||
|
||||
static void setcontrast(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
|
||||
pac7311_reg_write(gspca_dev->dev, 0x80, sd->contrast);
|
||||
/* load registers to sensor (Bit 0, auto clear) */
|
||||
pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
|
||||
PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
|
||||
}
|
||||
|
||||
static void setcolors(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
|
||||
pac7311_reg_write(gspca_dev->dev, 0x10, sd->colors);
|
||||
/* load registers to sensor (Bit 0, auto clear) */
|
||||
pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
|
||||
PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
|
||||
}
|
||||
|
||||
/* this function is called at open time */
|
||||
static int sd_open(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
pac7311_reg_write(gspca_dev->dev, 0x78, 0x00); /* Turn on LED */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sd_start(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
pac7311_reg_write(dev, 0xff, 0x01);
|
||||
reg_w(dev, 0x01, 0, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
|
||||
reg_w(dev, 0x01, 0, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
|
||||
reg_w(dev, 0x01, 0, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
|
||||
reg_w(dev, 0x01, 0, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
|
||||
reg_w(dev, 0x01, 0, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
|
||||
reg_w(dev, 0x01, 0, 0x002a, "\x00\x00\x00", 3);
|
||||
reg_w(dev, 0x01, 0, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
|
||||
reg_w(dev, 0x01, 0, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
|
||||
reg_w(dev, 0x01, 0, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
|
||||
reg_w(dev, 0x01, 0, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
|
||||
reg_w(dev, 0x01, 0, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
|
||||
reg_w(dev, 0x01, 0, 0x0066, "\xd0\xff", 2);
|
||||
reg_w(dev, 0x01, 0, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
|
||||
reg_w(dev, 0x01, 0, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
|
||||
reg_w(dev, 0x01, 0, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
|
||||
reg_w(dev, 0x01, 0, 0x008f, "\x18\x20", 2);
|
||||
reg_w(dev, 0x01, 0, 0x0096, "\x01\x08\x04", 3);
|
||||
reg_w(dev, 0x01, 0, 0x00a0, "\x44\x44\x44\x04", 4);
|
||||
reg_w(dev, 0x01, 0, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
|
||||
reg_w(dev, 0x01, 0, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
|
||||
|
||||
pac7311_reg_write(dev, 0xff, 0x04);
|
||||
pac7311_reg_write(dev, 0x02, 0x04);
|
||||
pac7311_reg_write(dev, 0x03, 0x54);
|
||||
pac7311_reg_write(dev, 0x04, 0x07);
|
||||
pac7311_reg_write(dev, 0x05, 0x2b);
|
||||
pac7311_reg_write(dev, 0x06, 0x09);
|
||||
pac7311_reg_write(dev, 0x07, 0x0f);
|
||||
pac7311_reg_write(dev, 0x08, 0x09);
|
||||
pac7311_reg_write(dev, 0x09, 0x00);
|
||||
pac7311_reg_write(dev, 0x0c, 0x07);
|
||||
pac7311_reg_write(dev, 0x0d, 0x00);
|
||||
pac7311_reg_write(dev, 0x0e, 0x00);
|
||||
pac7311_reg_write(dev, 0x0f, 0x62);
|
||||
pac7311_reg_write(dev, 0x10, 0x08);
|
||||
pac7311_reg_write(dev, 0x12, 0x07);
|
||||
pac7311_reg_write(dev, 0x13, 0x00);
|
||||
pac7311_reg_write(dev, 0x14, 0x00);
|
||||
pac7311_reg_write(dev, 0x15, 0x00);
|
||||
pac7311_reg_write(dev, 0x16, 0x00);
|
||||
pac7311_reg_write(dev, 0x17, 0x00);
|
||||
pac7311_reg_write(dev, 0x18, 0x00);
|
||||
pac7311_reg_write(dev, 0x19, 0x00);
|
||||
pac7311_reg_write(dev, 0x1a, 0x00);
|
||||
pac7311_reg_write(dev, 0x1b, 0x03);
|
||||
pac7311_reg_write(dev, 0x1c, 0xa0);
|
||||
pac7311_reg_write(dev, 0x1d, 0x01);
|
||||
pac7311_reg_write(dev, 0x1e, 0xf4);
|
||||
pac7311_reg_write(dev, 0x21, 0x00);
|
||||
pac7311_reg_write(dev, 0x22, 0x08);
|
||||
pac7311_reg_write(dev, 0x24, 0x03);
|
||||
pac7311_reg_write(dev, 0x26, 0x00);
|
||||
pac7311_reg_write(dev, 0x27, 0x01);
|
||||
pac7311_reg_write(dev, 0x28, 0xca);
|
||||
pac7311_reg_write(dev, 0x29, 0x10);
|
||||
pac7311_reg_write(dev, 0x2a, 0x06);
|
||||
pac7311_reg_write(dev, 0x2b, 0x78);
|
||||
pac7311_reg_write(dev, 0x2c, 0x00);
|
||||
pac7311_reg_write(dev, 0x2d, 0x00);
|
||||
pac7311_reg_write(dev, 0x2e, 0x00);
|
||||
pac7311_reg_write(dev, 0x2f, 0x00);
|
||||
pac7311_reg_write(dev, 0x30, 0x23);
|
||||
pac7311_reg_write(dev, 0x31, 0x28);
|
||||
pac7311_reg_write(dev, 0x32, 0x04);
|
||||
pac7311_reg_write(dev, 0x33, 0x11);
|
||||
pac7311_reg_write(dev, 0x34, 0x00);
|
||||
pac7311_reg_write(dev, 0x35, 0x00);
|
||||
pac7311_reg_write(dev, 0x11, 0x01);
|
||||
setcontrast(gspca_dev);
|
||||
setbrightness(gspca_dev);
|
||||
setcolors(gspca_dev);
|
||||
|
||||
/* set correct resolution */
|
||||
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
|
||||
case 2: /* 160x120 */
|
||||
pac7311_reg_write(dev, 0xff, 0x04);
|
||||
pac7311_reg_write(dev, 0x02, 0x03);
|
||||
pac7311_reg_write(dev, 0xff, 0x01);
|
||||
pac7311_reg_write(dev, 0x08, 0x09);
|
||||
pac7311_reg_write(dev, 0x17, 0x20);
|
||||
pac7311_reg_write(dev, 0x1b, 0x00);
|
||||
/* pac7311_reg_write(dev, 0x80, 0x69); */
|
||||
pac7311_reg_write(dev, 0x87, 0x10);
|
||||
break;
|
||||
case 1: /* 320x240 */
|
||||
pac7311_reg_write(dev, 0xff, 0x04);
|
||||
pac7311_reg_write(dev, 0x02, 0x03);
|
||||
pac7311_reg_write(dev, 0xff, 0x01);
|
||||
pac7311_reg_write(dev, 0x08, 0x09);
|
||||
pac7311_reg_write(dev, 0x17, 0x30);
|
||||
/* pac7311_reg_write(dev, 0x80, 0x3f); */
|
||||
pac7311_reg_write(dev, 0x87, 0x11);
|
||||
break;
|
||||
case 0: /* 640x480 */
|
||||
pac7311_reg_write(dev, 0xff, 0x04);
|
||||
pac7311_reg_write(dev, 0x02, 0x03);
|
||||
pac7311_reg_write(dev, 0xff, 0x01);
|
||||
pac7311_reg_write(dev, 0x08, 0x08);
|
||||
pac7311_reg_write(dev, 0x17, 0x00);
|
||||
/* pac7311_reg_write(dev, 0x80, 0x1c); */
|
||||
pac7311_reg_write(dev, 0x87, 0x12);
|
||||
break;
|
||||
}
|
||||
|
||||
/* start stream */
|
||||
pac7311_reg_write(dev, 0xff, 0x01);
|
||||
pac7311_reg_write(dev, 0x78, 0x04);
|
||||
pac7311_reg_write(dev, 0x78, 0x05);
|
||||
|
||||
if (sd->autogain) {
|
||||
sd->ag_cnt = AG_CNT_START;
|
||||
sd->avg_lum = 0;
|
||||
} else {
|
||||
sd->ag_cnt = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void sd_stopN(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
|
||||
pac7311_reg_write(dev, 0xff, 0x04);
|
||||
pac7311_reg_write(dev, 0x27, 0x80);
|
||||
pac7311_reg_write(dev, 0x28, 0xca);
|
||||
pac7311_reg_write(dev, 0x29, 0x53);
|
||||
pac7311_reg_write(dev, 0x2a, 0x0e);
|
||||
pac7311_reg_write(dev, 0xff, 0x01);
|
||||
pac7311_reg_write(dev, 0x3e, 0x20);
|
||||
pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
|
||||
pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
|
||||
pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
|
||||
}
|
||||
|
||||
static void sd_stop0(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
/* this function is called at close time */
|
||||
static void sd_close(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
|
||||
pac7311_reg_write(dev, 0xff, 0x04);
|
||||
pac7311_reg_write(dev, 0x27, 0x80);
|
||||
pac7311_reg_write(dev, 0x28, 0xca);
|
||||
pac7311_reg_write(dev, 0x29, 0x53);
|
||||
pac7311_reg_write(dev, 0x2a, 0x0e);
|
||||
pac7311_reg_write(dev, 0xff, 0x01);
|
||||
pac7311_reg_write(dev, 0x3e, 0x20);
|
||||
pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
|
||||
pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
|
||||
pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
|
||||
}
|
||||
|
||||
static void setautogain(struct gspca_dev *gspca_dev, int luma)
|
||||
{
|
||||
int luma_mean = 128;
|
||||
int luma_delta = 20;
|
||||
__u8 spring = 5;
|
||||
__u8 Pxclk;
|
||||
int Gbright;
|
||||
|
||||
pac7311_reg_read(gspca_dev->dev, 0x02, &Pxclk);
|
||||
Gbright = Pxclk;
|
||||
PDEBUG(D_FRAM, "luma mean %d", luma);
|
||||
if (luma < luma_mean - luma_delta ||
|
||||
luma > luma_mean + luma_delta) {
|
||||
Gbright += (luma_mean - luma) >> spring;
|
||||
if (Gbright > 0x1a)
|
||||
Gbright = 0x1a;
|
||||
else if (Gbright < 4)
|
||||
Gbright = 4;
|
||||
PDEBUG(D_FRAM, "gbright %d", Gbright);
|
||||
pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
|
||||
pac7311_reg_write(gspca_dev->dev, 0x0f, Gbright);
|
||||
/* load registers to sensor (Bit 0, auto clear) */
|
||||
pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
|
||||
}
|
||||
}
|
||||
|
||||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame, /* target */
|
||||
unsigned char *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
unsigned char tmpbuf[4];
|
||||
int i, p, ffseq;
|
||||
|
||||
/* if (len < 5) { */
|
||||
if (len < 6) {
|
||||
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
|
||||
return;
|
||||
}
|
||||
|
||||
ffseq = sd->ffseq;
|
||||
|
||||
for (p = 0; p < len - 6; p++) {
|
||||
if ((data[0 + p] == 0xff)
|
||||
&& (data[1 + p] == 0xff)
|
||||
&& (data[2 + p] == 0x00)
|
||||
&& (data[3 + p] == 0xff)
|
||||
&& (data[4 + p] == 0x96)) {
|
||||
|
||||
/* start of frame */
|
||||
if (sd->ag_cnt >= 0 && p > 28) {
|
||||
sd->avg_lum += data[p - 23];
|
||||
if (--sd->ag_cnt < 0) {
|
||||
sd->ag_cnt = AG_CNT_START;
|
||||
setautogain(gspca_dev,
|
||||
sd->avg_lum / AG_CNT_START);
|
||||
sd->avg_lum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy the end of data to the current frame */
|
||||
frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
|
||||
data, p);
|
||||
|
||||
/* put the JPEG header in the new frame */
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
|
||||
(unsigned char *) pac7311_jpeg_header,
|
||||
12);
|
||||
tmpbuf[0] = gspca_dev->height >> 8;
|
||||
tmpbuf[1] = gspca_dev->height & 0xff;
|
||||
tmpbuf[2] = gspca_dev->width >> 8;
|
||||
tmpbuf[3] = gspca_dev->width & 0xff;
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame,
|
||||
tmpbuf, 4);
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame,
|
||||
(unsigned char *) &pac7311_jpeg_header[16],
|
||||
PAC7311_JPEG_HEADER_SIZE - 16);
|
||||
|
||||
data += p + 7;
|
||||
len -= p + 7;
|
||||
ffseq = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* remove the 'ff ff ff xx' sequences */
|
||||
switch (ffseq) {
|
||||
case 3:
|
||||
data += 1;
|
||||
len -= 1;
|
||||
break;
|
||||
case 2:
|
||||
if (data[0] == 0xff) {
|
||||
data += 2;
|
||||
len -= 2;
|
||||
frame->data_end -= 2;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (data[0] == 0xff
|
||||
&& data[1] == 0xff) {
|
||||
data += 3;
|
||||
len -= 3;
|
||||
frame->data_end -= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < len - 4; i++) {
|
||||
if (data[i] == 0xff
|
||||
&& data[i + 1] == 0xff
|
||||
&& data[i + 2] == 0xff) {
|
||||
memmove(&data[i], &data[i + 4], len - i - 4);
|
||||
len -= 4;
|
||||
}
|
||||
}
|
||||
ffseq = 0;
|
||||
if (data[len - 4] == 0xff) {
|
||||
if (data[len - 3] == 0xff
|
||||
&& data[len - 2] == 0xff) {
|
||||
len -= 4;
|
||||
}
|
||||
} else if (data[len - 3] == 0xff) {
|
||||
if (data[len - 2] == 0xff
|
||||
&& data[len - 1] == 0xff)
|
||||
ffseq = 3;
|
||||
} else if (data[len - 2] == 0xff) {
|
||||
if (data[len - 1] == 0xff)
|
||||
ffseq = 2;
|
||||
} else if (data[len - 1] == 0xff)
|
||||
ffseq = 1;
|
||||
sd->ffseq = ffseq;
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
|
||||
}
|
||||
|
||||
static void getbrightness(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
/* __u8 brightness = 0;
|
||||
|
||||
pac7311_reg_read(gspca_dev->dev, 0x0008, &brightness);
|
||||
spca50x->brightness = brightness;
|
||||
return spca50x->brightness; */
|
||||
/* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->brightness = val;
|
||||
if (gspca_dev->streaming)
|
||||
setbrightness(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
getbrightness(gspca_dev);
|
||||
*val = sd->brightness;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->contrast = val;
|
||||
if (gspca_dev->streaming)
|
||||
setcontrast(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
/* getcontrast(gspca_dev); */
|
||||
*val = sd->contrast;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->colors = val;
|
||||
if (gspca_dev->streaming)
|
||||
setcolors(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
/* getcolors(gspca_dev); */
|
||||
*val = sd->colors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->autogain = val;
|
||||
if (val) {
|
||||
sd->ag_cnt = AG_CNT_START;
|
||||
sd->avg_lum = 0;
|
||||
} else {
|
||||
sd->ag_cnt = -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
*val = sd->autogain;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sub-driver description */
|
||||
static struct sd_desc sd_desc = {
|
||||
.name = MODULE_NAME,
|
||||
.ctrls = sd_ctrls,
|
||||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||||
.config = sd_config,
|
||||
.open = sd_open,
|
||||
.start = sd_start,
|
||||
.stopN = sd_stopN,
|
||||
.stop0 = sd_stop0,
|
||||
.close = sd_close,
|
||||
.pkt_scan = sd_pkt_scan,
|
||||
};
|
||||
|
||||
/* -- module initialisation -- */
|
||||
#define DVNM(name) .driver_info = (kernel_ulong_t) name
|
||||
static __devinitdata struct usb_device_id device_table[] = {
|
||||
{USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
|
||||
{USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
|
||||
{USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
|
||||
{USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
|
||||
{USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350")},
|
||||
{USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
|
||||
{USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, device_table);
|
||||
|
||||
/* -- device connect -- */
|
||||
static int sd_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
|
||||
THIS_MODULE);
|
||||
}
|
||||
|
||||
static struct usb_driver sd_driver = {
|
||||
.name = MODULE_NAME,
|
||||
.id_table = device_table,
|
||||
.probe = sd_probe,
|
||||
.disconnect = gspca_disconnect,
|
||||
};
|
||||
|
||||
/* -- module insert / remove -- */
|
||||
static int __init sd_mod_init(void)
|
||||
{
|
||||
if (usb_register(&sd_driver) < 0)
|
||||
return -1;
|
||||
PDEBUG(D_PROBE, "v%s registered", version);
|
||||
return 0;
|
||||
}
|
||||
static void __exit sd_mod_exit(void)
|
||||
{
|
||||
usb_deregister(&sd_driver);
|
||||
PDEBUG(D_PROBE, "deregistered");
|
||||
}
|
||||
|
||||
module_init(sd_mod_init);
|
||||
module_exit(sd_mod_exit);
|
|
@ -0,0 +1,879 @@
|
|||
/*
|
||||
* sonix sn9c102 (bayer) library
|
||||
* Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
|
||||
* Add Pas106 Stefano Mozzi (C) 2004
|
||||
*
|
||||
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define MODULE_NAME "sonixb"
|
||||
|
||||
#include "gspca.h"
|
||||
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
|
||||
static const char version[] = "2.1.0";
|
||||
|
||||
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
|
||||
MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* specific webcam descriptor */
|
||||
struct sd {
|
||||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||||
|
||||
unsigned char brightness;
|
||||
unsigned char contrast;
|
||||
|
||||
char sensor; /* Type of image sensor chip */
|
||||
#define SENSOR_HV7131R 0
|
||||
#define SENSOR_OV6650 1
|
||||
#define SENSOR_OV7630 2
|
||||
#define SENSOR_OV7630_3 3
|
||||
#define SENSOR_PAS106 4
|
||||
#define SENSOR_PAS202 5
|
||||
#define SENSOR_TAS5110 6
|
||||
#define SENSOR_TAS5130CXX 7
|
||||
};
|
||||
|
||||
#define COMP2 0x8f
|
||||
#define COMP 0xc7 /* 0x87 //0x07 */
|
||||
#define COMP1 0xc9 /* 0x89 //0x09 */
|
||||
|
||||
#define MCK_INIT 0x63
|
||||
#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
|
||||
|
||||
#define SYS_CLK 0x04
|
||||
|
||||
/* V4L2 controls supported by the driver */
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
|
||||
static struct ctrl sd_ctrls[] = {
|
||||
#define SD_BRIGHTNESS 0
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_BRIGHTNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Brightness",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 127,
|
||||
},
|
||||
.set = sd_setbrightness,
|
||||
.get = sd_getbrightness,
|
||||
},
|
||||
#define SD_CONTRAST 1
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_CONTRAST,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Contrast",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 127,
|
||||
},
|
||||
.set = sd_setcontrast,
|
||||
.get = sd_getcontrast,
|
||||
},
|
||||
};
|
||||
|
||||
/* fixme: should have V4L2_PIX_FMT_SN9C10X */
|
||||
static struct cam_mode vga_mode[] = {
|
||||
{V4L2_PIX_FMT_SN9C10X, 160, 120, 2},
|
||||
{V4L2_PIX_FMT_SN9C10X, 320, 240, 1},
|
||||
{V4L2_PIX_FMT_SN9C10X, 640, 480, 0},
|
||||
};
|
||||
static struct cam_mode sif_mode[] = {
|
||||
{V4L2_PIX_FMT_SN9C10X, 176, 144, 1},
|
||||
{V4L2_PIX_FMT_SN9C10X, 352, 288, 0},
|
||||
};
|
||||
|
||||
static const __u8 probe_ov7630[] = {0x08, 0x44};
|
||||
|
||||
static const __u8 initHv7131[] = {
|
||||
0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
|
||||
0x28, 0x1e, 0x60, 0x8a, 0x20,
|
||||
0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
|
||||
};
|
||||
static const __u8 hv7131_sensor_init[][8] = {
|
||||
{0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
|
||||
{0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
|
||||
{0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
|
||||
{0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
|
||||
{0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
|
||||
};
|
||||
static const __u8 initOv6650[] = {
|
||||
0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
|
||||
0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
|
||||
};
|
||||
static const __u8 ov6650_sensor_init[][8] =
|
||||
{
|
||||
/* Bright, contrast, etc are set througth SCBB interface.
|
||||
* AVCAP on win2 do not send any data on this controls. */
|
||||
/* Anyway, some registers appears to alter bright and constrat */
|
||||
{0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
|
||||
{0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
|
||||
{0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
|
||||
/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
|
||||
* THIS SET GREEN SCREEN
|
||||
* (pixels could be innverted in decode kind of "brg",
|
||||
* but blue wont be there. Avoid this data ... */
|
||||
{0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
|
||||
{0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
|
||||
{0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
|
||||
{0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10},
|
||||
{0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
|
||||
{0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
|
||||
{0xa0, 0x60, 0x10, 0x5d, 0x99, 0x04, 0x94, 0x16},
|
||||
{0xa0, 0x60, 0x2d, 0x0a, 0x99, 0x04, 0x94, 0x16},
|
||||
{0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
|
||||
{0xa0, 0x60, 0x33, 0x40, 0x99, 0x04, 0x94, 0x16},
|
||||
{0xa0, 0x60, 0x11, 0xc0, 0x99, 0x04, 0x94, 0x16},
|
||||
{0xa0, 0x60, 0x00, 0x16, 0x99, 0x04, 0x94, 0x15}, /* bright / Lumino */
|
||||
{0xa0, 0x60, 0x2b, 0xab, 0x99, 0x04, 0x94, 0x15},
|
||||
/* ?flicker o brillo */
|
||||
{0xa0, 0x60, 0x2d, 0x2a, 0x99, 0x04, 0x94, 0x15},
|
||||
{0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
|
||||
{0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
|
||||
{0xa0, 0x60, 0x33, 0x00, 0x99, 0x04, 0x94, 0x16},
|
||||
{0xa0, 0x60, 0x10, 0x57, 0x99, 0x04, 0x94, 0x16},
|
||||
{0xa0, 0x60, 0x2d, 0x2b, 0x99, 0x04, 0x94, 0x16},
|
||||
{0xa0, 0x60, 0x32, 0x00, 0x99, 0x04, 0x94, 0x16},
|
||||
/* Low Light (Enabled: 0x32 0x1 | Disabled: 0x32 0x00) */
|
||||
{0xa0, 0x60, 0x33, 0x29, 0x99, 0x04, 0x94, 0x16},
|
||||
/* Low Ligth (Enabled: 0x33 0x13 | Disabled: 0x33 0x29) */
|
||||
/* {0xa0, 0x60, 0x11, 0xc1, 0x99, 0x04, 0x94, 0x16}, */
|
||||
{0xa0, 0x60, 0x00, 0x17, 0x99, 0x04, 0x94, 0x15}, /* clip? r */
|
||||
{0xa0, 0x60, 0x00, 0x18, 0x99, 0x04, 0x94, 0x15}, /* clip? r */
|
||||
};
|
||||
static const __u8 initOv7630[] = {
|
||||
0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
|
||||
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
|
||||
0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
|
||||
0x28, 0x1e, /* H & V sizes r15 .. r16 */
|
||||
0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
|
||||
0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
|
||||
};
|
||||
static const __u8 initOv7630_3[] = {
|
||||
0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
|
||||
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
|
||||
0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
|
||||
0x28, 0x1e, /* H & V sizes r15 .. r16 */
|
||||
0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
|
||||
0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
|
||||
};
|
||||
static const __u8 ov7630_sensor_init_com[][8] = {
|
||||
{0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
|
||||
{0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
|
||||
/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
|
||||
{0xd0, 0x21, 0x12, 0x78, 0x00, 0x80, 0x34, 0x10}, /* jfm */
|
||||
{0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
|
||||
{0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
|
||||
{0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
|
||||
{0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
|
||||
{0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
|
||||
{0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
|
||||
{0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
|
||||
/* {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10}, jfm */
|
||||
{0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, /* jfm */
|
||||
{0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
|
||||
{0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
|
||||
{0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
|
||||
{0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
|
||||
{0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
|
||||
{0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
|
||||
};
|
||||
static const __u8 ov7630_sensor_init[][8] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
|
||||
{0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
|
||||
{0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
|
||||
{0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
|
||||
{0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
|
||||
};
|
||||
static const __u8 ov7630_sensor_init_3[][8] = {
|
||||
{0xa0, 0x21, 0x10, 0x36, 0xbd, 0x06, 0xf6, 0x16}, /* exposure */
|
||||
{0xa0, 0x21, 0x76, 0x03, 0xbd, 0x06, 0xf6, 0x16},
|
||||
{0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x16},
|
||||
{0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
|
||||
/* {0xb0, 0x21, 0x2a, 0xc0, 0x3c, 0x06, 0xf6, 0x1d},
|
||||
* a0 1c,a0 1f,c0 3c frame rate ?line interval from ov6630 */
|
||||
/* {0xb0, 0x21, 0x2a, 0xa0, 0x1f, 0x06, 0xf6, 0x1d}, * from win */
|
||||
{0xb0, 0x21, 0x2a, 0xa0, 0x1c, 0x06, 0xf6, 0x1d},
|
||||
};
|
||||
|
||||
static const __u8 initPas106[] = {
|
||||
0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
|
||||
0x16, 0x12, 0x28, COMP1, MCK_INIT1,
|
||||
0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
|
||||
};
|
||||
/* compression 0x86 mckinit1 0x2b */
|
||||
static const __u8 pas106_data[][2] = {
|
||||
{0x02, 0x04}, /* Pixel Clock Divider 6 */
|
||||
{0x03, 0x13}, /* Frame Time MSB */
|
||||
/* {0x03, 0x12}, * Frame Time MSB */
|
||||
{0x04, 0x06}, /* Frame Time LSB */
|
||||
/* {0x04, 0x05}, * Frame Time LSB */
|
||||
{0x05, 0x65}, /* Shutter Time Line Offset */
|
||||
/* {0x05, 0x6d}, * Shutter Time Line Offset */
|
||||
/* {0x06, 0xb1}, * Shutter Time Pixel Offset */
|
||||
{0x06, 0xcd}, /* Shutter Time Pixel Offset */
|
||||
{0x07, 0xc1}, /* Black Level Subtract Sign */
|
||||
/* {0x07, 0x00}, * Black Level Subtract Sign */
|
||||
{0x08, 0x06}, /* Black Level Subtract Level */
|
||||
{0x08, 0x06}, /* Black Level Subtract Level */
|
||||
/* {0x08, 0x01}, * Black Level Subtract Level */
|
||||
{0x09, 0x05}, /* Color Gain B Pixel 5 a */
|
||||
{0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
|
||||
{0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
|
||||
{0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
|
||||
{0x0d, 0x00}, /* Color GainH Pixel */
|
||||
{0x0e, 0x0e}, /* Global Gain */
|
||||
{0x0f, 0x00}, /* Contrast */
|
||||
{0x10, 0x06}, /* H&V synchro polarity */
|
||||
{0x11, 0x06}, /* ?default */
|
||||
{0x12, 0x06}, /* DAC scale */
|
||||
{0x14, 0x02}, /* ?default */
|
||||
{0x13, 0x01}, /* Validate Settings */
|
||||
};
|
||||
static const __u8 initPas202[] = {
|
||||
0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
|
||||
0x28, 0x1e, 0x28, 0x89, 0x30,
|
||||
0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
|
||||
};
|
||||
static const __u8 pas202_sensor_init[][8] = {
|
||||
{0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
|
||||
{0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
|
||||
{0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
|
||||
{0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
|
||||
{0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
|
||||
{0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
|
||||
{0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
|
||||
{0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
|
||||
{0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
|
||||
{0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
|
||||
{0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
|
||||
{0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
|
||||
|
||||
{0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
|
||||
{0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
|
||||
{0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
|
||||
{0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
|
||||
{0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
|
||||
{0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
|
||||
{0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
|
||||
{0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
|
||||
};
|
||||
|
||||
static const __u8 initTas5110[] = {
|
||||
0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
|
||||
0x16, 0x12, 0x60, 0x86, 0x2b,
|
||||
0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
|
||||
};
|
||||
static const __u8 tas5110_sensor_init[][8] = {
|
||||
{0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
|
||||
{0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
|
||||
{0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
|
||||
};
|
||||
|
||||
static const __u8 initTas5130[] = {
|
||||
0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
|
||||
0x28, 0x1e, 0x60, COMP, MCK_INIT,
|
||||
0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
|
||||
};
|
||||
static const __u8 tas5130_sensor_init[][8] = {
|
||||
/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
|
||||
* shutter 0x47 short exposure? */
|
||||
{0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
|
||||
/* shutter 0x01 long exposure */
|
||||
{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
|
||||
};
|
||||
|
||||
static void reg_r(struct usb_device *dev,
|
||||
__u16 value, __u8 *buffer)
|
||||
{
|
||||
usb_control_msg(dev,
|
||||
usb_rcvctrlpipe(dev, 0),
|
||||
0, /* request */
|
||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||
value,
|
||||
0, /* index */
|
||||
buffer, 1,
|
||||
500);
|
||||
}
|
||||
|
||||
static void reg_w(struct usb_device *dev,
|
||||
__u16 value,
|
||||
const __u8 *buffer,
|
||||
__u16 len)
|
||||
{
|
||||
usb_control_msg(dev,
|
||||
usb_sndctrlpipe(dev, 0),
|
||||
0x08, /* request */
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||
value,
|
||||
0, /* index */
|
||||
(__u8 *) buffer, len,
|
||||
500);
|
||||
}
|
||||
|
||||
static int i2c_w(struct usb_device *dev, const __u8 *buffer)
|
||||
{
|
||||
int retry = 60;
|
||||
__u8 ByteReceive;
|
||||
|
||||
/* is i2c ready */
|
||||
reg_w(dev, 0x08, buffer, 8);
|
||||
while (retry--) {
|
||||
msleep(10);
|
||||
reg_r(dev, 0x08, &ByteReceive);
|
||||
if (ByteReceive == 4)
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void i2c_w_vector(struct usb_device *dev,
|
||||
const __u8 buffer[][8], int len)
|
||||
{
|
||||
for (;;) {
|
||||
reg_w(dev, 0x08, *buffer, 8);
|
||||
len -= 8;
|
||||
if (len <= 0)
|
||||
break;
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
static void setbrightness(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
__u8 value;
|
||||
|
||||
switch (sd->sensor) {
|
||||
case SENSOR_OV6650: {
|
||||
__u8 i2cOV6650[] =
|
||||
{0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
|
||||
|
||||
i2cOV6650[3] = sd->brightness;
|
||||
if (i2c_w(gspca_dev->dev, i2cOV6650) < 0)
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
case SENSOR_OV7630: {
|
||||
__u8 i2cOV[] =
|
||||
{0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
|
||||
|
||||
/* change reg 0x06 */
|
||||
i2cOV[3] = sd->brightness;
|
||||
if (i2c_w(gspca_dev->dev, i2cOV) < 0)
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
case SENSOR_PAS106: {
|
||||
__u8 i2c1[] =
|
||||
{0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
|
||||
|
||||
i2c1[3] = sd->brightness >> 3;
|
||||
i2c1[2] = 0x0e;
|
||||
if (i2c_w(gspca_dev->dev, i2c1) < 0)
|
||||
goto err;
|
||||
i2c1[3] = 0x01;
|
||||
i2c1[2] = 0x13;
|
||||
if (i2c_w(gspca_dev->dev, i2c1) < 0)
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
case SENSOR_PAS202: {
|
||||
/* __u8 i2cpexpo1[] =
|
||||
{0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
|
||||
__u8 i2cpexpo[] =
|
||||
{0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
|
||||
__u8 i2cp202[] =
|
||||
{0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
|
||||
static __u8 i2cpdoit[] =
|
||||
{0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
|
||||
|
||||
/* change reg 0x10 */
|
||||
i2cpexpo[4] = 0xff - sd->brightness;
|
||||
/* if(i2c_w(gspca_dev->dev,i2cpexpo1) < 0)
|
||||
goto err; */
|
||||
/* if(i2c_w(gspca_dev->dev,i2cpdoit) < 0)
|
||||
goto err; */
|
||||
if (i2c_w(gspca_dev->dev, i2cpexpo) < 0)
|
||||
goto err;
|
||||
if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
|
||||
goto err;
|
||||
i2cp202[3] = sd->brightness >> 3;
|
||||
if (i2c_w(gspca_dev->dev, i2cp202) < 0)
|
||||
goto err;
|
||||
if (i2c_w(gspca_dev->dev, i2cpdoit) < 0)
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
case SENSOR_TAS5130CXX:
|
||||
case SENSOR_TAS5110: {
|
||||
__u8 i2c[] =
|
||||
{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
|
||||
|
||||
value = 0xff - sd->brightness;
|
||||
i2c[4] = value;
|
||||
PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
|
||||
if (i2c_w(gspca_dev->dev, i2c) < 0)
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
err:
|
||||
PDEBUG(D_ERR, "i2c error brightness");
|
||||
}
|
||||
static void setcontrast(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
__u8 gain;
|
||||
__u8 rgb_value;
|
||||
|
||||
gain = sd->contrast >> 4;
|
||||
/* red and blue gain */
|
||||
rgb_value = gain << 4 | gain;
|
||||
reg_w(gspca_dev->dev, 0x10, &rgb_value, 1);
|
||||
/* green gain */
|
||||
rgb_value = gain;
|
||||
reg_w(gspca_dev->dev, 0x11, &rgb_value, 1);
|
||||
}
|
||||
|
||||
/* this function is called at probe time */
|
||||
static int sd_config(struct gspca_dev *gspca_dev,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct cam *cam;
|
||||
/* __u16 vendor; */
|
||||
__u16 product;
|
||||
int sif = 0;
|
||||
|
||||
/* vendor = id->idVendor; */
|
||||
product = id->idProduct;
|
||||
/* switch (vendor) { */
|
||||
/* case 0x0c45: * Sonix */
|
||||
switch (product) {
|
||||
case 0x6001: /* SN9C102 */
|
||||
case 0x6005: /* SN9C101 */
|
||||
case 0x6007: /* SN9C101 */
|
||||
sd->sensor = SENSOR_TAS5110;
|
||||
sif = 1;
|
||||
break;
|
||||
case 0x6009: /* SN9C101 */
|
||||
case 0x600d: /* SN9C101 */
|
||||
case 0x6029: /* SN9C101 */
|
||||
sd->sensor = SENSOR_PAS106;
|
||||
sif = 1;
|
||||
break;
|
||||
case 0x6011: /* SN9C101 - SN9C101G */
|
||||
sd->sensor = SENSOR_OV6650;
|
||||
sif = 1;
|
||||
break;
|
||||
case 0x6019: /* SN9C101 */
|
||||
case 0x602c: /* SN9C102 */
|
||||
case 0x602e: /* SN9C102 */
|
||||
sd->sensor = SENSOR_OV7630;
|
||||
break;
|
||||
case 0x60b0: /* SN9C103 */
|
||||
sd->sensor = SENSOR_OV7630_3;
|
||||
break;
|
||||
case 0x6024: /* SN9C102 */
|
||||
case 0x6025: /* SN9C102 */
|
||||
sd->sensor = SENSOR_TAS5130CXX;
|
||||
break;
|
||||
case 0x6028: /* SN9C102 */
|
||||
sd->sensor = SENSOR_PAS202;
|
||||
break;
|
||||
case 0x602d: /* SN9C102 */
|
||||
sd->sensor = SENSOR_HV7131R;
|
||||
break;
|
||||
case 0x60af: /* SN9C103 */
|
||||
sd->sensor = SENSOR_PAS202;
|
||||
break;
|
||||
}
|
||||
/* break; */
|
||||
/* } */
|
||||
|
||||
cam = &gspca_dev->cam;
|
||||
cam->dev_name = (char *) id->driver_info;
|
||||
cam->epaddr = 0x01;
|
||||
if (!sif) {
|
||||
cam->cam_mode = vga_mode;
|
||||
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
|
||||
} else {
|
||||
cam->cam_mode = sif_mode;
|
||||
cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
|
||||
}
|
||||
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
|
||||
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
|
||||
if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
|
||||
reg_w(gspca_dev->dev, 0x01, probe_ov7630, sizeof probe_ov7630);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this function is called at open time */
|
||||
static int sd_open(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
__u8 ByteReceive;
|
||||
|
||||
reg_r(gspca_dev->dev, 0x00, &ByteReceive);
|
||||
if (ByteReceive != 0x10)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pas106_i2cinit(struct usb_device *dev)
|
||||
{
|
||||
int i;
|
||||
const __u8 *data;
|
||||
__u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
|
||||
|
||||
i = ARRAY_SIZE(pas106_data);
|
||||
data = pas106_data[0];
|
||||
while (--i >= 0) {
|
||||
memcpy(&i2c1[2], data, 2);
|
||||
/* copy 2 bytes from the template */
|
||||
if (i2c_w(dev, i2c1) < 0)
|
||||
PDEBUG(D_ERR, "i2c error pas106");
|
||||
data += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- start the camera -- */
|
||||
static void sd_start(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
int mode, l;
|
||||
const __u8 *sn9c10x;
|
||||
__u8 reg01, reg17;
|
||||
__u8 reg17_19[3];
|
||||
|
||||
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
|
||||
switch (sd->sensor) {
|
||||
case SENSOR_HV7131R:
|
||||
sn9c10x = initHv7131;
|
||||
reg17_19[0] = 0x60;
|
||||
reg17_19[1] = (mode << 4) | 0x8a;
|
||||
reg17_19[2] = 0x20;
|
||||
break;
|
||||
case SENSOR_OV6650:
|
||||
sn9c10x = initOv6650;
|
||||
reg17_19[0] = 0x68;
|
||||
reg17_19[1] = (mode << 4) | 0x8b;
|
||||
reg17_19[2] = 0x20;
|
||||
break;
|
||||
case SENSOR_OV7630:
|
||||
sn9c10x = initOv7630;
|
||||
reg17_19[0] = 0x68;
|
||||
reg17_19[1] = (mode << 4) | COMP2;
|
||||
reg17_19[2] = MCK_INIT1;
|
||||
break;
|
||||
case SENSOR_OV7630_3:
|
||||
sn9c10x = initOv7630_3;
|
||||
reg17_19[0] = 0x68;
|
||||
reg17_19[1] = (mode << 4) | COMP2;
|
||||
reg17_19[2] = MCK_INIT1;
|
||||
break;
|
||||
case SENSOR_PAS106:
|
||||
sn9c10x = initPas106;
|
||||
reg17_19[0] = 0x24; /* 0x28 */
|
||||
reg17_19[1] = (mode << 4) | COMP1;
|
||||
reg17_19[2] = MCK_INIT1;
|
||||
break;
|
||||
case SENSOR_PAS202:
|
||||
sn9c10x = initPas202;
|
||||
reg17_19[0] = mode ? 0x24 : 0x20;
|
||||
reg17_19[1] = (mode << 4) | 0x89;
|
||||
reg17_19[2] = 0x20;
|
||||
break;
|
||||
case SENSOR_TAS5110:
|
||||
sn9c10x = initTas5110;
|
||||
reg17_19[0] = 0x60;
|
||||
reg17_19[1] = (mode << 4) | 0x86;
|
||||
reg17_19[2] = 0x2b; /* 0xf3; */
|
||||
break;
|
||||
default:
|
||||
/* case SENSOR_TAS5130CXX: */
|
||||
sn9c10x = initTas5130;
|
||||
reg17_19[0] = 0x60;
|
||||
reg17_19[1] = (mode << 4) | COMP;
|
||||
reg17_19[2] = mode ? 0x23 : 0x43;
|
||||
break;
|
||||
}
|
||||
switch (sd->sensor) {
|
||||
case SENSOR_OV7630:
|
||||
reg01 = 0x06;
|
||||
reg17 = 0x29;
|
||||
l = 0x10;
|
||||
break;
|
||||
case SENSOR_OV7630_3:
|
||||
reg01 = 0x44;
|
||||
reg17 = 0x68;
|
||||
l = 0x10;
|
||||
break;
|
||||
default:
|
||||
reg01 = sn9c10x[0];
|
||||
reg17 = sn9c10x[0x17 - 1];
|
||||
l = 0x1f;
|
||||
break;
|
||||
}
|
||||
|
||||
/* reg 0x01 bit 2 video transfert on */
|
||||
reg_w(dev, 0x01, ®01, 1);
|
||||
/* reg 0x17 SensorClk enable inv Clk 0x60 */
|
||||
reg_w(dev, 0x17, ®17, 1);
|
||||
/*fixme: for ov7630 102
|
||||
reg_w(dev, 0x01, {0x06, sn9c10x[1]}, 2); */
|
||||
/* Set the registers from the template */
|
||||
reg_w(dev, 0x01, sn9c10x, l);
|
||||
switch (sd->sensor) {
|
||||
case SENSOR_HV7131R:
|
||||
i2c_w_vector(dev, hv7131_sensor_init,
|
||||
sizeof hv7131_sensor_init);
|
||||
break;
|
||||
case SENSOR_OV6650:
|
||||
i2c_w_vector(dev, ov6650_sensor_init,
|
||||
sizeof ov6650_sensor_init);
|
||||
break;
|
||||
case SENSOR_OV7630:
|
||||
i2c_w_vector(dev, ov7630_sensor_init_com,
|
||||
sizeof ov7630_sensor_init_com);
|
||||
msleep(200);
|
||||
i2c_w_vector(dev, ov7630_sensor_init,
|
||||
sizeof ov7630_sensor_init);
|
||||
break;
|
||||
case SENSOR_OV7630_3:
|
||||
i2c_w_vector(dev, ov7630_sensor_init_com,
|
||||
sizeof ov7630_sensor_init_com);
|
||||
msleep(200);
|
||||
i2c_w_vector(dev, ov7630_sensor_init_3,
|
||||
sizeof ov7630_sensor_init_3);
|
||||
break;
|
||||
case SENSOR_PAS106:
|
||||
pas106_i2cinit(dev);
|
||||
break;
|
||||
case SENSOR_PAS202:
|
||||
i2c_w_vector(dev, pas202_sensor_init,
|
||||
sizeof pas202_sensor_init);
|
||||
break;
|
||||
case SENSOR_TAS5110:
|
||||
i2c_w_vector(dev, tas5110_sensor_init,
|
||||
sizeof tas5110_sensor_init);
|
||||
break;
|
||||
default:
|
||||
/* case SENSOR_TAS5130CXX: */
|
||||
i2c_w_vector(dev, tas5130_sensor_init,
|
||||
sizeof tas5130_sensor_init);
|
||||
break;
|
||||
}
|
||||
/* H_size V_size 0x28, 0x1e maybe 640x480 */
|
||||
reg_w(dev, 0x15, &sn9c10x[0x15 - 1], 2);
|
||||
/* compression register */
|
||||
reg_w(dev, 0x18, ®17_19[1], 1);
|
||||
/* H_start */ /*fixme: not ov7630*/
|
||||
reg_w(dev, 0x12, &sn9c10x[0x12 - 1], 1);
|
||||
/* V_START */ /*fixme: not ov7630*/
|
||||
reg_w(dev, 0x13, &sn9c10x[0x13 - 1], 1);
|
||||
/* reset 0x17 SensorClk enable inv Clk 0x60 */
|
||||
/*fixme: ov7630 [17]=68 8f (+20 if 102)*/
|
||||
reg_w(dev, 0x17, ®17_19[0], 1);
|
||||
/*MCKSIZE ->3 */ /*fixme: not ov7630*/
|
||||
reg_w(dev, 0x19, ®17_19[2], 1);
|
||||
/* AE_STRX AE_STRY AE_ENDX AE_ENDY */
|
||||
reg_w(dev, 0x1c, &sn9c10x[0x1c - 1], 4);
|
||||
/* Enable video transfert */
|
||||
reg_w(dev, 0x01, &sn9c10x[0], 1);
|
||||
/* Compression */
|
||||
reg_w(dev, 0x18, ®17_19[1], 2);
|
||||
msleep(20);
|
||||
|
||||
setcontrast(gspca_dev);
|
||||
setbrightness(gspca_dev);
|
||||
}
|
||||
|
||||
static void sd_stopN(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
__u8 ByteSend = 0;
|
||||
|
||||
ByteSend = 0x09; /* 0X00 */
|
||||
reg_w(gspca_dev->dev, 0x01, &ByteSend, 1);
|
||||
}
|
||||
|
||||
static void sd_stop0(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void sd_close(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame, /* target */
|
||||
unsigned char *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
{
|
||||
int p;
|
||||
|
||||
if (len > 6 && len < 24) {
|
||||
for (p = 0; p < len - 6; p++) {
|
||||
if (data[0 + p] == 0xff
|
||||
&& data[1 + p] == 0xff
|
||||
&& data[2 + p] == 0x00
|
||||
&& data[3 + p] == 0xc4
|
||||
&& data[4 + p] == 0xc4
|
||||
&& data[5 + p] == 0x96) { /* start of frame */
|
||||
frame = gspca_frame_add(gspca_dev,
|
||||
LAST_PACKET,
|
||||
frame,
|
||||
data, 0);
|
||||
data += 12;
|
||||
len -= 12;
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET,
|
||||
frame, data, len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET,
|
||||
frame, data, len);
|
||||
}
|
||||
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->brightness = val;
|
||||
if (gspca_dev->streaming)
|
||||
setbrightness(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
*val = sd->brightness;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->contrast = val;
|
||||
if (gspca_dev->streaming)
|
||||
setcontrast(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
*val = sd->contrast;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sub-driver description */
|
||||
static struct sd_desc sd_desc = {
|
||||
.name = MODULE_NAME,
|
||||
.ctrls = sd_ctrls,
|
||||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||||
.config = sd_config,
|
||||
.open = sd_open,
|
||||
.start = sd_start,
|
||||
.stopN = sd_stopN,
|
||||
.stop0 = sd_stop0,
|
||||
.close = sd_close,
|
||||
.pkt_scan = sd_pkt_scan,
|
||||
};
|
||||
|
||||
/* -- module initialisation -- */
|
||||
#define DVNM(name) .driver_info = (kernel_ulong_t) name
|
||||
static __devinitdata struct usb_device_id device_table[] = {
|
||||
{USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
|
||||
{USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
|
||||
{USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
|
||||
{USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
|
||||
{USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
|
||||
{USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia-OV6650-SN9C101G")},
|
||||
{USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
|
||||
{USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
|
||||
{USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
|
||||
{USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
|
||||
{USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
|
||||
{USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
|
||||
{USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
|
||||
{USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
|
||||
{USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
|
||||
{USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, device_table);
|
||||
|
||||
/* -- device connect -- */
|
||||
static int sd_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
|
||||
THIS_MODULE);
|
||||
}
|
||||
|
||||
static struct usb_driver sd_driver = {
|
||||
.name = MODULE_NAME,
|
||||
.id_table = device_table,
|
||||
.probe = sd_probe,
|
||||
.disconnect = gspca_disconnect,
|
||||
};
|
||||
|
||||
/* -- module insert / remove -- */
|
||||
static int __init sd_mod_init(void)
|
||||
{
|
||||
if (usb_register(&sd_driver) < 0)
|
||||
return -1;
|
||||
PDEBUG(D_PROBE, "v%s registered", version);
|
||||
return 0;
|
||||
}
|
||||
static void __exit sd_mod_exit(void)
|
||||
{
|
||||
usb_deregister(&sd_driver);
|
||||
PDEBUG(D_PROBE, "deregistered");
|
||||
}
|
||||
|
||||
module_init(sd_mod_init);
|
||||
module_exit(sd_mod_exit);
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,933 @@
|
|||
/*
|
||||
* SPCA505 chip based cameras initialization data
|
||||
*
|
||||
* V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#define MODULE_NAME "spca505"
|
||||
|
||||
#include "gspca.h"
|
||||
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
|
||||
static const char version[] = "2.1.0";
|
||||
|
||||
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
|
||||
MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* specific webcam descriptor */
|
||||
struct sd {
|
||||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||||
|
||||
int buflen;
|
||||
unsigned char tmpbuf[640 * 480 * 3 / 2]; /* YYUV per line */
|
||||
unsigned char tmpbuf2[640 * 480 * 2]; /* YUYV */
|
||||
|
||||
unsigned char brightness;
|
||||
|
||||
char subtype;
|
||||
#define IntelPCCameraPro 0
|
||||
#define Nxultra 1
|
||||
};
|
||||
|
||||
/* V4L2 controls supported by the driver */
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
|
||||
static struct ctrl sd_ctrls[] = {
|
||||
#define SD_BRIGHTNESS 0
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_BRIGHTNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Brightness",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = 127,
|
||||
},
|
||||
.set = sd_setbrightness,
|
||||
.get = sd_getbrightness,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_mode vga_mode[] = {
|
||||
{V4L2_PIX_FMT_YUYV, 160, 120, 5},
|
||||
{V4L2_PIX_FMT_YUYV, 176, 144, 4},
|
||||
{V4L2_PIX_FMT_YUYV, 320, 240, 2},
|
||||
{V4L2_PIX_FMT_YUYV, 352, 288, 1},
|
||||
{V4L2_PIX_FMT_YUYV, 640, 480, 0},
|
||||
};
|
||||
|
||||
#define SPCA50X_OFFSET_DATA 10
|
||||
|
||||
#define SPCA50X_REG_USB 0x02 /* spca505 501 */
|
||||
|
||||
#define SPCA50X_USB_CTRL 0x00 /* spca505 */
|
||||
#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
|
||||
#define SPCA50X_REG_GLOBAL 0x03 /* spca505 */
|
||||
#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
|
||||
#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
|
||||
|
||||
#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
|
||||
#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
|
||||
#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */
|
||||
|
||||
/*
|
||||
* Data to initialize a SPCA505. Common to the CCD and external modes
|
||||
*/
|
||||
static __u16 spca505_init_data[][3] = {
|
||||
/* line bmRequest,value,index */
|
||||
/* 1819 */
|
||||
{SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
|
||||
/* Sensor reset */
|
||||
/* 1822 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
|
||||
/* 1825 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
|
||||
/* Block USB reset */
|
||||
/* 1828 */ {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL,
|
||||
SPCA50X_GLOBAL_MISC0},
|
||||
|
||||
/* 1831 */ {0x5, 0x01, 0x10},
|
||||
/* Maybe power down some stuff */
|
||||
/* 1834 */ {0x5, 0x0f, 0x11},
|
||||
|
||||
/* Setup internal CCD ? */
|
||||
/* 1837 */ {0x6, 0x10, 0x08},
|
||||
/* 1840 */ {0x6, 0x00, 0x09},
|
||||
/* 1843 */ {0x6, 0x00, 0x0a},
|
||||
/* 1846 */ {0x6, 0x00, 0x0b},
|
||||
/* 1849 */ {0x6, 0x10, 0x0c},
|
||||
/* 1852 */ {0x6, 0x00, 0x0d},
|
||||
/* 1855 */ {0x6, 0x00, 0x0e},
|
||||
/* 1858 */ {0x6, 0x00, 0x0f},
|
||||
/* 1861 */ {0x6, 0x10, 0x10},
|
||||
/* 1864 */ {0x6, 0x02, 0x11},
|
||||
/* 1867 */ {0x6, 0x00, 0x12},
|
||||
/* 1870 */ {0x6, 0x04, 0x13},
|
||||
/* 1873 */ {0x6, 0x02, 0x14},
|
||||
/* 1876 */ {0x6, 0x8a, 0x51},
|
||||
/* 1879 */ {0x6, 0x40, 0x52},
|
||||
/* 1882 */ {0x6, 0xb6, 0x53},
|
||||
/* 1885 */ {0x6, 0x3d, 0x54},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Data to initialize the camera using the internal CCD
|
||||
*/
|
||||
static __u16 spca505_open_data_ccd[][3] = {
|
||||
/* line bmRequest,value,index */
|
||||
/* Internal CCD data set */
|
||||
/* 1891 */ {0x3, 0x04, 0x01},
|
||||
/* This could be a reset */
|
||||
/* 1894 */ {0x3, 0x00, 0x01},
|
||||
|
||||
/* Setup compression and image registers. 0x6 and 0x7 seem to be
|
||||
related to H&V hold, and are resolution mode specific */
|
||||
/* 1897 */ {0x4, 0x10, 0x01},
|
||||
/* DIFF(0x50), was (0x10) */
|
||||
/* 1900 */ {0x4, 0x00, 0x04},
|
||||
/* 1903 */ {0x4, 0x00, 0x05},
|
||||
/* 1906 */ {0x4, 0x20, 0x06},
|
||||
/* 1909 */ {0x4, 0x20, 0x07},
|
||||
|
||||
/* 1912 */ {0x8, 0x0a, 0x00},
|
||||
/* DIFF (0x4a), was (0xa) */
|
||||
|
||||
/* 1915 */ {0x5, 0x00, 0x10},
|
||||
/* 1918 */ {0x5, 0x00, 0x11},
|
||||
/* 1921 */ {0x5, 0x00, 0x00},
|
||||
/* DIFF not written */
|
||||
/* 1924 */ {0x5, 0x00, 0x01},
|
||||
/* DIFF not written */
|
||||
/* 1927 */ {0x5, 0x00, 0x02},
|
||||
/* DIFF not written */
|
||||
/* 1930 */ {0x5, 0x00, 0x03},
|
||||
/* DIFF not written */
|
||||
/* 1933 */ {0x5, 0x00, 0x04},
|
||||
/* DIFF not written */
|
||||
/* 1936 */ {0x5, 0x80, 0x05},
|
||||
/* DIFF not written */
|
||||
/* 1939 */ {0x5, 0xe0, 0x06},
|
||||
/* DIFF not written */
|
||||
/* 1942 */ {0x5, 0x20, 0x07},
|
||||
/* DIFF not written */
|
||||
/* 1945 */ {0x5, 0xa0, 0x08},
|
||||
/* DIFF not written */
|
||||
/* 1948 */ {0x5, 0x0, 0x12},
|
||||
/* DIFF not written */
|
||||
/* 1951 */ {0x5, 0x02, 0x0f},
|
||||
/* DIFF not written */
|
||||
/* 1954 */ {0x5, 0x10, 0x46},
|
||||
/* DIFF not written */
|
||||
/* 1957 */ {0x5, 0x8, 0x4a},
|
||||
/* DIFF not written */
|
||||
|
||||
/* 1960 */ {0x3, 0x08, 0x03},
|
||||
/* DIFF (0x3,0x28,0x3) */
|
||||
/* 1963 */ {0x3, 0x08, 0x01},
|
||||
/* 1966 */ {0x3, 0x0c, 0x03},
|
||||
/* DIFF not written */
|
||||
/* 1969 */ {0x3, 0x21, 0x00},
|
||||
/* DIFF (0x39) */
|
||||
|
||||
/* Extra block copied from init to hopefully ensure CCD is in a sane state */
|
||||
/* 1837 */ {0x6, 0x10, 0x08},
|
||||
/* 1840 */ {0x6, 0x00, 0x09},
|
||||
/* 1843 */ {0x6, 0x00, 0x0a},
|
||||
/* 1846 */ {0x6, 0x00, 0x0b},
|
||||
/* 1849 */ {0x6, 0x10, 0x0c},
|
||||
/* 1852 */ {0x6, 0x00, 0x0d},
|
||||
/* 1855 */ {0x6, 0x00, 0x0e},
|
||||
/* 1858 */ {0x6, 0x00, 0x0f},
|
||||
/* 1861 */ {0x6, 0x10, 0x10},
|
||||
/* 1864 */ {0x6, 0x02, 0x11},
|
||||
/* 1867 */ {0x6, 0x00, 0x12},
|
||||
/* 1870 */ {0x6, 0x04, 0x13},
|
||||
/* 1873 */ {0x6, 0x02, 0x14},
|
||||
/* 1876 */ {0x6, 0x8a, 0x51},
|
||||
/* 1879 */ {0x6, 0x40, 0x52},
|
||||
/* 1882 */ {0x6, 0xb6, 0x53},
|
||||
/* 1885 */ {0x6, 0x3d, 0x54},
|
||||
/* End of extra block */
|
||||
|
||||
/* 1972 */ {0x6, 0x3f, 0x1},
|
||||
/* Block skipped */
|
||||
/* 1975 */ {0x6, 0x10, 0x02},
|
||||
/* 1978 */ {0x6, 0x64, 0x07},
|
||||
/* 1981 */ {0x6, 0x10, 0x08},
|
||||
/* 1984 */ {0x6, 0x00, 0x09},
|
||||
/* 1987 */ {0x6, 0x00, 0x0a},
|
||||
/* 1990 */ {0x6, 0x00, 0x0b},
|
||||
/* 1993 */ {0x6, 0x10, 0x0c},
|
||||
/* 1996 */ {0x6, 0x00, 0x0d},
|
||||
/* 1999 */ {0x6, 0x00, 0x0e},
|
||||
/* 2002 */ {0x6, 0x00, 0x0f},
|
||||
/* 2005 */ {0x6, 0x10, 0x10},
|
||||
/* 2008 */ {0x6, 0x02, 0x11},
|
||||
/* 2011 */ {0x6, 0x00, 0x12},
|
||||
/* 2014 */ {0x6, 0x04, 0x13},
|
||||
/* 2017 */ {0x6, 0x02, 0x14},
|
||||
/* 2020 */ {0x6, 0x8a, 0x51},
|
||||
/* 2023 */ {0x6, 0x40, 0x52},
|
||||
/* 2026 */ {0x6, 0xb6, 0x53},
|
||||
/* 2029 */ {0x6, 0x3d, 0x54},
|
||||
/* 2032 */ {0x6, 0x60, 0x57},
|
||||
/* 2035 */ {0x6, 0x20, 0x58},
|
||||
/* 2038 */ {0x6, 0x15, 0x59},
|
||||
/* 2041 */ {0x6, 0x05, 0x5a},
|
||||
|
||||
/* 2044 */ {0x5, 0x01, 0xc0},
|
||||
/* 2047 */ {0x5, 0x10, 0xcb},
|
||||
/* 2050 */ {0x5, 0x80, 0xc1},
|
||||
/* */
|
||||
/* 2053 */ {0x5, 0x0, 0xc2},
|
||||
/* 4 was 0 */
|
||||
/* 2056 */ {0x5, 0x00, 0xca},
|
||||
/* 2059 */ {0x5, 0x80, 0xc1},
|
||||
/* */
|
||||
/* 2062 */ {0x5, 0x04, 0xc2},
|
||||
/* 2065 */ {0x5, 0x00, 0xca},
|
||||
/* 2068 */ {0x5, 0x0, 0xc1},
|
||||
/* */
|
||||
/* 2071 */ {0x5, 0x00, 0xc2},
|
||||
/* 2074 */ {0x5, 0x00, 0xca},
|
||||
/* 2077 */ {0x5, 0x40, 0xc1},
|
||||
/* */
|
||||
/* 2080 */ {0x5, 0x17, 0xc2},
|
||||
/* 2083 */ {0x5, 0x00, 0xca},
|
||||
/* 2086 */ {0x5, 0x80, 0xc1},
|
||||
/* */
|
||||
/* 2089 */ {0x5, 0x06, 0xc2},
|
||||
/* 2092 */ {0x5, 0x00, 0xca},
|
||||
/* 2095 */ {0x5, 0x80, 0xc1},
|
||||
/* */
|
||||
/* 2098 */ {0x5, 0x04, 0xc2},
|
||||
/* 2101 */ {0x5, 0x00, 0xca},
|
||||
|
||||
/* 2104 */ {0x3, 0x4c, 0x3},
|
||||
/* 2107 */ {0x3, 0x18, 0x1},
|
||||
|
||||
/* 2110 */ {0x6, 0x70, 0x51},
|
||||
/* 2113 */ {0x6, 0xbe, 0x53},
|
||||
/* 2116 */ {0x6, 0x71, 0x57},
|
||||
/* 2119 */ {0x6, 0x20, 0x58},
|
||||
/* 2122 */ {0x6, 0x05, 0x59},
|
||||
/* 2125 */ {0x6, 0x15, 0x5a},
|
||||
|
||||
/* 2128 */ {0x4, 0x00, 0x08},
|
||||
/* Compress = OFF (0x1 to turn on) */
|
||||
/* 2131 */ {0x4, 0x12, 0x09},
|
||||
/* 2134 */ {0x4, 0x21, 0x0a},
|
||||
/* 2137 */ {0x4, 0x10, 0x0b},
|
||||
/* 2140 */ {0x4, 0x21, 0x0c},
|
||||
/* 2143 */ {0x4, 0x05, 0x00},
|
||||
/* was 5 (Image Type ? ) */
|
||||
/* 2146 */ {0x4, 0x00, 0x01},
|
||||
|
||||
/* 2149 */ {0x6, 0x3f, 0x01},
|
||||
|
||||
/* 2152 */ {0x4, 0x00, 0x04},
|
||||
/* 2155 */ {0x4, 0x00, 0x05},
|
||||
/* 2158 */ {0x4, 0x40, 0x06},
|
||||
/* 2161 */ {0x4, 0x40, 0x07},
|
||||
|
||||
/* 2164 */ {0x6, 0x1c, 0x17},
|
||||
/* 2167 */ {0x6, 0xe2, 0x19},
|
||||
/* 2170 */ {0x6, 0x1c, 0x1b},
|
||||
/* 2173 */ {0x6, 0xe2, 0x1d},
|
||||
/* 2176 */ {0x6, 0xaa, 0x1f},
|
||||
/* 2179 */ {0x6, 0x70, 0x20},
|
||||
|
||||
/* 2182 */ {0x5, 0x01, 0x10},
|
||||
/* 2185 */ {0x5, 0x00, 0x11},
|
||||
/* 2188 */ {0x5, 0x01, 0x00},
|
||||
/* 2191 */ {0x5, 0x05, 0x01},
|
||||
/* 2194 */ {0x5, 0x00, 0xc1},
|
||||
/* */
|
||||
/* 2197 */ {0x5, 0x00, 0xc2},
|
||||
/* 2200 */ {0x5, 0x00, 0xca},
|
||||
|
||||
/* 2203 */ {0x6, 0x70, 0x51},
|
||||
/* 2206 */ {0x6, 0xbe, 0x53},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
|
||||
* SPCA505b chip based cameras initialization data
|
||||
*
|
||||
*/
|
||||
/* jfm */
|
||||
#define initial_brightness 0x7f /* 0x0(white)-0xff(black) */
|
||||
/* #define initial_brightness 0x0 //0x0(white)-0xff(black) */
|
||||
/*
|
||||
* Data to initialize a SPCA505. Common to the CCD and external modes
|
||||
*/
|
||||
static __u16 spca505b_init_data[][3] = {
|
||||
/* start */
|
||||
{0x02, 0x00, 0x00}, /* init */
|
||||
{0x02, 0x00, 0x01},
|
||||
{0x02, 0x00, 0x02},
|
||||
{0x02, 0x00, 0x03},
|
||||
{0x02, 0x00, 0x04},
|
||||
{0x02, 0x00, 0x05},
|
||||
{0x02, 0x00, 0x06},
|
||||
{0x02, 0x00, 0x07},
|
||||
{0x02, 0x00, 0x08},
|
||||
{0x02, 0x00, 0x09},
|
||||
{0x03, 0x00, 0x00},
|
||||
{0x03, 0x00, 0x01},
|
||||
{0x03, 0x00, 0x02},
|
||||
{0x03, 0x00, 0x03},
|
||||
{0x03, 0x00, 0x04},
|
||||
{0x03, 0x00, 0x05},
|
||||
{0x03, 0x00, 0x06},
|
||||
{0x04, 0x00, 0x00},
|
||||
{0x04, 0x00, 0x02},
|
||||
{0x04, 0x00, 0x04},
|
||||
{0x04, 0x00, 0x05},
|
||||
{0x04, 0x00, 0x06},
|
||||
{0x04, 0x00, 0x07},
|
||||
{0x04, 0x00, 0x08},
|
||||
{0x04, 0x00, 0x09},
|
||||
{0x04, 0x00, 0x0a},
|
||||
{0x04, 0x00, 0x0b},
|
||||
{0x04, 0x00, 0x0c},
|
||||
{0x07, 0x00, 0x00},
|
||||
{0x07, 0x00, 0x03},
|
||||
{0x08, 0x00, 0x00},
|
||||
{0x08, 0x00, 0x01},
|
||||
{0x08, 0x00, 0x02},
|
||||
{0x00, 0x01, 0x00},
|
||||
{0x00, 0x01, 0x01},
|
||||
{0x00, 0x01, 0x34},
|
||||
{0x00, 0x01, 0x35},
|
||||
{0x06, 0x18, 0x08},
|
||||
{0x06, 0xfc, 0x09},
|
||||
{0x06, 0xfc, 0x0a},
|
||||
{0x06, 0xfc, 0x0b},
|
||||
{0x06, 0x18, 0x0c},
|
||||
{0x06, 0xfc, 0x0d},
|
||||
{0x06, 0xfc, 0x0e},
|
||||
{0x06, 0xfc, 0x0f},
|
||||
{0x06, 0x18, 0x10},
|
||||
{0x06, 0xfe, 0x12},
|
||||
{0x06, 0x00, 0x11},
|
||||
{0x06, 0x00, 0x14},
|
||||
{0x06, 0x00, 0x13},
|
||||
{0x06, 0x28, 0x51},
|
||||
{0x06, 0xff, 0x53},
|
||||
{0x02, 0x00, 0x08},
|
||||
|
||||
{0x03, 0x00, 0x03},
|
||||
{0x03, 0x10, 0x03},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Data to initialize the camera using the internal CCD
|
||||
*/
|
||||
static __u16 spca505b_open_data_ccd[][3] = {
|
||||
|
||||
/* {0x02,0x00,0x00}, */
|
||||
{0x03, 0x04, 0x01}, /* rst */
|
||||
{0x03, 0x00, 0x01},
|
||||
{0x03, 0x00, 0x00},
|
||||
{0x03, 0x21, 0x00},
|
||||
{0x03, 0x00, 0x04},
|
||||
{0x03, 0x00, 0x03},
|
||||
{0x03, 0x18, 0x03},
|
||||
{0x03, 0x08, 0x01},
|
||||
{0x03, 0x1c, 0x03},
|
||||
{0x03, 0x5c, 0x03},
|
||||
{0x03, 0x5c, 0x03},
|
||||
{0x03, 0x18, 0x01},
|
||||
|
||||
/* same as 505 */
|
||||
{0x04, 0x10, 0x01},
|
||||
{0x04, 0x00, 0x04},
|
||||
{0x04, 0x00, 0x05},
|
||||
{0x04, 0x20, 0x06},
|
||||
{0x04, 0x20, 0x07},
|
||||
|
||||
{0x08, 0x0a, 0x00},
|
||||
|
||||
{0x05, 0x00, 0x10},
|
||||
{0x05, 0x00, 0x11},
|
||||
{0x05, 0x00, 0x12},
|
||||
{0x05, 0x6f, 0x00},
|
||||
{0x05, initial_brightness >> 6, 0x00},
|
||||
{0x05, initial_brightness << 2, 0x01},
|
||||
{0x05, 0x00, 0x02},
|
||||
{0x05, 0x01, 0x03},
|
||||
{0x05, 0x00, 0x04},
|
||||
{0x05, 0x03, 0x05},
|
||||
{0x05, 0xe0, 0x06},
|
||||
{0x05, 0x20, 0x07},
|
||||
{0x05, 0xa0, 0x08},
|
||||
{0x05, 0x00, 0x12},
|
||||
{0x05, 0x02, 0x0f},
|
||||
{0x05, 128, 0x14}, /* max exposure off (0=on) */
|
||||
{0x05, 0x01, 0xb0},
|
||||
{0x05, 0x01, 0xbf},
|
||||
{0x03, 0x02, 0x06},
|
||||
{0x05, 0x10, 0x46},
|
||||
{0x05, 0x08, 0x4a},
|
||||
|
||||
{0x06, 0x00, 0x01},
|
||||
{0x06, 0x10, 0x02},
|
||||
{0x06, 0x64, 0x07},
|
||||
{0x06, 0x18, 0x08},
|
||||
{0x06, 0xfc, 0x09},
|
||||
{0x06, 0xfc, 0x0a},
|
||||
{0x06, 0xfc, 0x0b},
|
||||
{0x04, 0x00, 0x01},
|
||||
{0x06, 0x18, 0x0c},
|
||||
{0x06, 0xfc, 0x0d},
|
||||
{0x06, 0xfc, 0x0e},
|
||||
{0x06, 0xfc, 0x0f},
|
||||
{0x06, 0x11, 0x10}, /* contrast */
|
||||
{0x06, 0x00, 0x11},
|
||||
{0x06, 0xfe, 0x12},
|
||||
{0x06, 0x00, 0x13},
|
||||
{0x06, 0x00, 0x14},
|
||||
{0x06, 0x9d, 0x51},
|
||||
{0x06, 0x40, 0x52},
|
||||
{0x06, 0x7c, 0x53},
|
||||
{0x06, 0x40, 0x54},
|
||||
{0x06, 0x02, 0x57},
|
||||
{0x06, 0x03, 0x58},
|
||||
{0x06, 0x15, 0x59},
|
||||
{0x06, 0x05, 0x5a},
|
||||
{0x06, 0x03, 0x56},
|
||||
{0x06, 0x02, 0x3f},
|
||||
{0x06, 0x00, 0x40},
|
||||
{0x06, 0x39, 0x41},
|
||||
{0x06, 0x69, 0x42},
|
||||
{0x06, 0x87, 0x43},
|
||||
{0x06, 0x9e, 0x44},
|
||||
{0x06, 0xb1, 0x45},
|
||||
{0x06, 0xbf, 0x46},
|
||||
{0x06, 0xcc, 0x47},
|
||||
{0x06, 0xd5, 0x48},
|
||||
{0x06, 0xdd, 0x49},
|
||||
{0x06, 0xe3, 0x4a},
|
||||
{0x06, 0xe8, 0x4b},
|
||||
{0x06, 0xed, 0x4c},
|
||||
{0x06, 0xf2, 0x4d},
|
||||
{0x06, 0xf7, 0x4e},
|
||||
{0x06, 0xfc, 0x4f},
|
||||
{0x06, 0xff, 0x50},
|
||||
|
||||
{0x05, 0x01, 0xc0},
|
||||
{0x05, 0x10, 0xcb},
|
||||
{0x05, 0x40, 0xc1},
|
||||
{0x05, 0x04, 0xc2},
|
||||
{0x05, 0x00, 0xca},
|
||||
{0x05, 0x40, 0xc1},
|
||||
{0x05, 0x09, 0xc2},
|
||||
{0x05, 0x00, 0xca},
|
||||
{0x05, 0xc0, 0xc1},
|
||||
{0x05, 0x09, 0xc2},
|
||||
{0x05, 0x00, 0xca},
|
||||
{0x05, 0x40, 0xc1},
|
||||
{0x05, 0x59, 0xc2},
|
||||
{0x05, 0x00, 0xca},
|
||||
{0x04, 0x00, 0x01},
|
||||
{0x05, 0x80, 0xc1},
|
||||
{0x05, 0xec, 0xc2},
|
||||
{0x05, 0x0, 0xca},
|
||||
|
||||
{0x06, 0x02, 0x57},
|
||||
{0x06, 0x01, 0x58},
|
||||
{0x06, 0x15, 0x59},
|
||||
{0x06, 0x0a, 0x5a},
|
||||
{0x06, 0x01, 0x57},
|
||||
{0x06, 0x8a, 0x03},
|
||||
{0x06, 0x0a, 0x6c},
|
||||
{0x06, 0x30, 0x01},
|
||||
{0x06, 0x20, 0x02},
|
||||
{0x06, 0x00, 0x03},
|
||||
|
||||
{0x05, 0x8c, 0x25},
|
||||
|
||||
{0x06, 0x4d, 0x51}, /* maybe saturation (4d) */
|
||||
{0x06, 0x84, 0x53}, /* making green (84) */
|
||||
{0x06, 0x00, 0x57}, /* sharpness (1) */
|
||||
{0x06, 0x18, 0x08},
|
||||
{0x06, 0xfc, 0x09},
|
||||
{0x06, 0xfc, 0x0a},
|
||||
{0x06, 0xfc, 0x0b},
|
||||
{0x06, 0x18, 0x0c}, /* maybe hue (18) */
|
||||
{0x06, 0xfc, 0x0d},
|
||||
{0x06, 0xfc, 0x0e},
|
||||
{0x06, 0xfc, 0x0f},
|
||||
{0x06, 0x18, 0x10}, /* maybe contrast (18) */
|
||||
|
||||
{0x05, 0x01, 0x02},
|
||||
|
||||
{0x04, 0x00, 0x08}, /* compression */
|
||||
{0x04, 0x12, 0x09},
|
||||
{0x04, 0x21, 0x0a},
|
||||
{0x04, 0x10, 0x0b},
|
||||
{0x04, 0x21, 0x0c},
|
||||
{0x04, 0x1d, 0x00}, /* imagetype (1d) */
|
||||
{0x04, 0x41, 0x01}, /* hardware snapcontrol */
|
||||
|
||||
{0x04, 0x00, 0x04},
|
||||
{0x04, 0x00, 0x05},
|
||||
{0x04, 0x10, 0x06},
|
||||
{0x04, 0x10, 0x07},
|
||||
{0x04, 0x40, 0x06},
|
||||
{0x04, 0x40, 0x07},
|
||||
{0x04, 0x00, 0x04},
|
||||
{0x04, 0x00, 0x05},
|
||||
|
||||
{0x06, 0x1c, 0x17},
|
||||
{0x06, 0xe2, 0x19},
|
||||
{0x06, 0x1c, 0x1b},
|
||||
{0x06, 0xe2, 0x1d},
|
||||
{0x06, 0x5f, 0x1f},
|
||||
{0x06, 0x32, 0x20},
|
||||
|
||||
{0x05, initial_brightness >> 6, 0x00},
|
||||
{0x05, initial_brightness << 2, 0x01},
|
||||
{0x05, 0x06, 0xc1},
|
||||
{0x05, 0x58, 0xc2},
|
||||
{0x05, 0x0, 0xca},
|
||||
{0x05, 0x0, 0x11},
|
||||
{}
|
||||
};
|
||||
|
||||
static int reg_write(struct usb_device *dev,
|
||||
__u16 reg, __u16 index, __u16 value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = usb_control_msg(dev,
|
||||
usb_sndctrlpipe(dev, 0),
|
||||
reg,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
value, index, NULL, 0, 500);
|
||||
PDEBUG(D_PACK, "reg write: 0x%02x,0x%02x:0x%02x, 0x%x",
|
||||
reg, index, value, ret);
|
||||
if (ret < 0)
|
||||
PDEBUG(D_ERR, "reg write: error %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* returns: negative is error, pos or zero is data */
|
||||
static int reg_read(struct usb_device *dev,
|
||||
__u16 reg, /* bRequest */
|
||||
__u16 index, /* wIndex */
|
||||
__u16 length) /* wLength (1 or 2 only) */
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[4];
|
||||
|
||||
buf[1] = 0;
|
||||
ret = usb_control_msg(dev,
|
||||
usb_rcvctrlpipe(dev, 0),
|
||||
reg,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
(__u16) 0, /* value */
|
||||
(__u16) index,
|
||||
buf,
|
||||
length,
|
||||
500); /* timeout */
|
||||
if (ret < 0) {
|
||||
PDEBUG(D_ERR, "reg_read err %d", ret);
|
||||
return -1;
|
||||
}
|
||||
return (buf[1] << 8) + buf[0];
|
||||
}
|
||||
|
||||
static int write_vector(struct gspca_dev *gspca_dev,
|
||||
__u16 data[][3])
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
int ret, i = 0;
|
||||
|
||||
while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
|
||||
ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
|
||||
if (ret < 0) {
|
||||
PDEBUG(D_ERR,
|
||||
"Register write failed for 0x%x,0x%x,0x%x",
|
||||
data[i][0], data[i][1], data[i][2]);
|
||||
return ret;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this function is called at probe time */
|
||||
static int sd_config(struct gspca_dev *gspca_dev,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct cam *cam;
|
||||
__u16 vendor;
|
||||
__u16 product;
|
||||
|
||||
vendor = id->idVendor;
|
||||
product = id->idProduct;
|
||||
switch (vendor) {
|
||||
case 0x041e: /* Creative cameras */
|
||||
/* switch (product) { */
|
||||
/* case 0x401d: * here505b */
|
||||
sd->subtype = Nxultra;
|
||||
/* break; */
|
||||
/* } */
|
||||
break;
|
||||
case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
|
||||
/* switch (product) { */
|
||||
/* case 0x0430: */
|
||||
/* fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
|
||||
sd->subtype = IntelPCCameraPro;
|
||||
/* break; */
|
||||
/* } */
|
||||
break;
|
||||
}
|
||||
|
||||
cam = &gspca_dev->cam;
|
||||
cam->dev_name = (char *) id->driver_info;
|
||||
cam->epaddr = 0x01;
|
||||
cam->cam_mode = vga_mode;
|
||||
if (sd->subtype != IntelPCCameraPro)
|
||||
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
|
||||
else /* no 640x480 for IntelPCCameraPro */
|
||||
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0] - 1;
|
||||
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
|
||||
|
||||
if (sd->subtype == Nxultra) {
|
||||
if (write_vector(gspca_dev, spca505b_init_data))
|
||||
return -EIO;
|
||||
} else {
|
||||
if (write_vector(gspca_dev, spca505_init_data))
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this function is called at open time */
|
||||
static int sd_open(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int ret;
|
||||
|
||||
PDEBUG(D_STREAM, "Initializing SPCA505");
|
||||
if (sd->subtype == Nxultra)
|
||||
write_vector(gspca_dev, spca505b_open_data_ccd);
|
||||
else
|
||||
write_vector(gspca_dev, spca505_open_data_ccd);
|
||||
ret = reg_read(gspca_dev->dev, 6, 0x16, 2);
|
||||
|
||||
if (ret < 0) {
|
||||
PDEBUG(D_ERR|D_STREAM,
|
||||
"register read failed for after vector read err = %d",
|
||||
ret);
|
||||
return -EIO;
|
||||
}
|
||||
PDEBUG(D_STREAM,
|
||||
"After vector read returns : 0x%x should be 0x0101",
|
||||
ret & 0xffff);
|
||||
|
||||
ret = reg_write(gspca_dev->dev, 6, 0x16, 0x0a);
|
||||
if (ret < 0) {
|
||||
PDEBUG(D_ERR, "register write failed for (6,0xa,0x16) err=%d",
|
||||
ret);
|
||||
return -EIO;
|
||||
}
|
||||
reg_write(gspca_dev->dev, 5, 0xc2, 18);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sd_start(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
int ret;
|
||||
|
||||
/* necessary because without it we can see stream
|
||||
* only once after loading module */
|
||||
/* stopping usb registers Tomasz change */
|
||||
reg_write(dev, 0x02, 0x0, 0x0);
|
||||
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
|
||||
case 0:
|
||||
reg_write(dev, 0x04, 0x00, 0x00);
|
||||
reg_write(dev, 0x04, 0x06, 0x10);
|
||||
reg_write(dev, 0x04, 0x07, 0x10);
|
||||
break;
|
||||
case 1:
|
||||
reg_write(dev, 0x04, 0x00, 0x01);
|
||||
reg_write(dev, 0x04, 0x06, 0x1a);
|
||||
reg_write(dev, 0x04, 0x07, 0x1a);
|
||||
break;
|
||||
case 2:
|
||||
reg_write(dev, 0x04, 0x00, 0x02);
|
||||
reg_write(dev, 0x04, 0x06, 0x1c);
|
||||
reg_write(dev, 0x04, 0x07, 0x1d);
|
||||
break;
|
||||
case 4:
|
||||
reg_write(dev, 0x04, 0x00, 0x04);
|
||||
reg_write(dev, 0x04, 0x06, 0x34);
|
||||
reg_write(dev, 0x04, 0x07, 0x34);
|
||||
break;
|
||||
default:
|
||||
/* case 5: */
|
||||
reg_write(dev, 0x04, 0x00, 0x05);
|
||||
reg_write(dev, 0x04, 0x06, 0x40);
|
||||
reg_write(dev, 0x04, 0x07, 0x40);
|
||||
break;
|
||||
}
|
||||
/* Enable ISO packet machine - should we do this here or in ISOC init ? */
|
||||
ret = reg_write(dev, SPCA50X_REG_USB,
|
||||
SPCA50X_USB_CTRL,
|
||||
SPCA50X_CUSB_ENABLE);
|
||||
|
||||
/* reg_write(dev, 0x5, 0x0, 0x0); */
|
||||
/* reg_write(dev, 0x5, 0x0, 0x1); */
|
||||
/* reg_write(dev, 0x5, 0x11, 0x2); */
|
||||
}
|
||||
|
||||
static void sd_stopN(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
/* Disable ISO packet machine */
|
||||
reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
|
||||
}
|
||||
|
||||
static void sd_stop0(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
/* this function is called at close time */
|
||||
static void sd_close(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
/* This maybe reset or power control */
|
||||
reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
|
||||
reg_write(gspca_dev->dev, 0x03, 0x01, 0x0);
|
||||
reg_write(gspca_dev->dev, 0x03, 0x00, 0x1);
|
||||
reg_write(gspca_dev->dev, 0x05, 0x10, 0x1);
|
||||
reg_write(gspca_dev->dev, 0x05, 0x11, 0xf);
|
||||
}
|
||||
|
||||
/* convert YYUV per line to YUYV (YUV 4:2:2) */
|
||||
static void yyuv_decode(unsigned char *out,
|
||||
unsigned char *in,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
unsigned char *Ui, *Vi, *yi, *yi1;
|
||||
unsigned char *out1;
|
||||
int i, j;
|
||||
|
||||
yi = in;
|
||||
for (i = height / 2; --i >= 0; ) {
|
||||
out1 = out + width * 2; /* next line */
|
||||
yi1 = yi + width;
|
||||
Ui = yi1 + width;
|
||||
Vi = Ui + width / 2;
|
||||
for (j = width / 2; --j >= 0; ) {
|
||||
*out++ = 128 + *yi++;
|
||||
*out++ = 128 + *Ui;
|
||||
*out++ = 128 + *yi++;
|
||||
*out++ = 128 + *Vi;
|
||||
|
||||
*out1++ = 128 + *yi1++;
|
||||
*out1++ = 128 + *Ui++;
|
||||
*out1++ = 128 + *yi1++;
|
||||
*out1++ = 128 + *Vi++;
|
||||
}
|
||||
yi += width * 2;
|
||||
out = out1;
|
||||
}
|
||||
}
|
||||
|
||||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame, /* target */
|
||||
unsigned char *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
switch (data[0]) {
|
||||
case 0: /* start of frame */
|
||||
if (gspca_dev->last_packet_type == FIRST_PACKET) {
|
||||
yyuv_decode(sd->tmpbuf2, sd->tmpbuf,
|
||||
gspca_dev->width,
|
||||
gspca_dev->height);
|
||||
frame = gspca_frame_add(gspca_dev,
|
||||
LAST_PACKET,
|
||||
frame,
|
||||
sd->tmpbuf2,
|
||||
gspca_dev->width
|
||||
* gspca_dev->height
|
||||
* 2);
|
||||
}
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
|
||||
data, 0);
|
||||
data += SPCA50X_OFFSET_DATA;
|
||||
len -= SPCA50X_OFFSET_DATA;
|
||||
if (len > 0)
|
||||
memcpy(sd->tmpbuf, data, len);
|
||||
else
|
||||
len = 0;
|
||||
sd->buflen = len;
|
||||
return;
|
||||
case 0xff: /* drop */
|
||||
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
|
||||
return;
|
||||
}
|
||||
data += 1;
|
||||
len -= 1;
|
||||
memcpy(&sd->tmpbuf[sd->buflen], data, len);
|
||||
sd->buflen += len;
|
||||
}
|
||||
|
||||
static void setbrightness(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
__u8 brightness = sd->brightness;
|
||||
reg_write(gspca_dev->dev, 5, 0x00, (255 - brightness) >> 6);
|
||||
reg_write(gspca_dev->dev, 5, 0x01, (255 - brightness) << 2);
|
||||
|
||||
}
|
||||
static void getbrightness(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->brightness = 255
|
||||
- ((reg_read(gspca_dev->dev, 5, 0x01, 1) >> 2)
|
||||
+ (reg_read(gspca_dev->dev, 5, 0x0, 1) << 6));
|
||||
}
|
||||
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->brightness = val;
|
||||
if (gspca_dev->streaming)
|
||||
setbrightness(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
getbrightness(gspca_dev);
|
||||
*val = sd->brightness;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sub-driver description */
|
||||
static struct sd_desc sd_desc = {
|
||||
.name = MODULE_NAME,
|
||||
.ctrls = sd_ctrls,
|
||||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||||
.config = sd_config,
|
||||
.open = sd_open,
|
||||
.start = sd_start,
|
||||
.stopN = sd_stopN,
|
||||
.stop0 = sd_stop0,
|
||||
.close = sd_close,
|
||||
.pkt_scan = sd_pkt_scan,
|
||||
};
|
||||
|
||||
/* -- module initialisation -- */
|
||||
#define DVNM(name) .driver_info = (kernel_ulong_t) name
|
||||
static __devinitdata struct usb_device_id device_table[] = {
|
||||
{USB_DEVICE(0x041e, 0x401d), DVNM("Creative Webcam NX ULTRA")},
|
||||
{USB_DEVICE(0x0733, 0x0430), DVNM("Intel PC Camera Pro")},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, device_table);
|
||||
|
||||
/* -- device connect -- */
|
||||
static int sd_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return gspca_dev_probe(intf, id, &sd_desc, sizeof (struct sd),
|
||||
THIS_MODULE);
|
||||
}
|
||||
|
||||
static struct usb_driver sd_driver = {
|
||||
.name = MODULE_NAME,
|
||||
.id_table = device_table,
|
||||
.probe = sd_probe,
|
||||
.disconnect = gspca_disconnect,
|
||||
};
|
||||
|
||||
/* -- module insert / remove -- */
|
||||
static int __init sd_mod_init(void)
|
||||
{
|
||||
if (usb_register(&sd_driver) < 0)
|
||||
return -1;
|
||||
PDEBUG(D_PROBE, "v%s registered", version);
|
||||
return 0;
|
||||
}
|
||||
static void __exit sd_mod_exit(void)
|
||||
{
|
||||
usb_deregister(&sd_driver);
|
||||
PDEBUG(D_PROBE, "deregistered");
|
||||
}
|
||||
|
||||
module_init(sd_mod_init);
|
||||
module_exit(sd_mod_exit);
|
|
@ -0,0 +1,830 @@
|
|||
/*
|
||||
* SPCA506 chip based cameras function
|
||||
* M Xhaard 15/04/2004 based on different work Mark Taylor and others
|
||||
* and my own snoopy file on a pv-321c donate by a german compagny
|
||||
* "Firma Frank Gmbh" from Saarbruecken
|
||||
*
|
||||
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define MODULE_NAME "spca506"
|
||||
|
||||
#include "gspca.h"
|
||||
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
|
||||
static const char version[] = "2.1.0";
|
||||
|
||||
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
|
||||
MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* specific webcam descriptor */
|
||||
struct sd {
|
||||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||||
|
||||
int buflen;
|
||||
unsigned char tmpbuf[640 * 480 * 3]; /* YYUV per line */
|
||||
unsigned char tmpbuf2[640 * 480 * 2]; /* YUYV */
|
||||
|
||||
unsigned char brightness;
|
||||
unsigned char contrast;
|
||||
unsigned char colors;
|
||||
unsigned char hue;
|
||||
char norme;
|
||||
char channel;
|
||||
};
|
||||
|
||||
/* V4L2 controls supported by the driver */
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
|
||||
static struct ctrl sd_ctrls[] = {
|
||||
#define SD_BRIGHTNESS 0
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_BRIGHTNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Brightness",
|
||||
.minimum = 0,
|
||||
.maximum = 0xff,
|
||||
.step = 1,
|
||||
.default_value = 0x80,
|
||||
},
|
||||
.set = sd_setbrightness,
|
||||
.get = sd_getbrightness,
|
||||
},
|
||||
#define SD_CONTRAST 1
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_CONTRAST,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Contrast",
|
||||
.minimum = 0,
|
||||
.maximum = 0xff,
|
||||
.step = 1,
|
||||
.default_value = 0x47,
|
||||
},
|
||||
.set = sd_setcontrast,
|
||||
.get = sd_getcontrast,
|
||||
},
|
||||
#define SD_COLOR 2
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_SATURATION,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Saturation",
|
||||
.minimum = 0,
|
||||
.maximum = 0xff,
|
||||
.step = 1,
|
||||
.default_value = 0x40,
|
||||
},
|
||||
.set = sd_setcolors,
|
||||
.get = sd_getcolors,
|
||||
},
|
||||
#define SD_HUE 3
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_HUE,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Hue",
|
||||
.minimum = 0,
|
||||
.maximum = 0xff,
|
||||
.step = 1,
|
||||
.default_value = 0,
|
||||
},
|
||||
.set = sd_sethue,
|
||||
.get = sd_gethue,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_mode vga_mode[] = {
|
||||
{V4L2_PIX_FMT_YUYV, 160, 120, 5},
|
||||
{V4L2_PIX_FMT_YUYV, 176, 144, 4},
|
||||
{V4L2_PIX_FMT_YUYV, 320, 240, 2},
|
||||
{V4L2_PIX_FMT_YUYV, 352, 288, 1},
|
||||
{V4L2_PIX_FMT_YUYV, 640, 480, 0},
|
||||
};
|
||||
|
||||
#define SPCA50X_OFFSET_DATA 10
|
||||
|
||||
#define SAA7113_bright 0x0a /* defaults 0x80 */
|
||||
#define SAA7113_contrast 0x0b /* defaults 0x47 */
|
||||
#define SAA7113_saturation 0x0c /* defaults 0x40 */
|
||||
#define SAA7113_hue 0x0d /* defaults 0x00 */
|
||||
#define SAA7113_I2C_BASE_WRITE 0x4a
|
||||
|
||||
static void reg_r(struct usb_device *dev,
|
||||
__u16 req,
|
||||
__u16 index,
|
||||
__u8 *buffer, __u16 length)
|
||||
{
|
||||
usb_control_msg(dev,
|
||||
usb_rcvctrlpipe(dev, 0),
|
||||
req,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0, /* value */
|
||||
index, buffer, length,
|
||||
500);
|
||||
}
|
||||
|
||||
static void reg_w(struct usb_device *dev,
|
||||
__u16 req,
|
||||
__u16 value,
|
||||
__u16 index)
|
||||
{
|
||||
usb_control_msg(dev,
|
||||
usb_sndctrlpipe(dev, 0),
|
||||
req,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
value, index,
|
||||
NULL, 0, 500);
|
||||
}
|
||||
|
||||
static void spca506_Initi2c(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
|
||||
}
|
||||
|
||||
static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,
|
||||
__u16 reg)
|
||||
{
|
||||
int retry = 60;
|
||||
unsigned char Data[2];
|
||||
|
||||
reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
|
||||
reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);
|
||||
while (retry--) {
|
||||
reg_r(gspca_dev->dev, 0x07, 0x0003, Data, 2);
|
||||
if ((Data[0] | Data[1]) == 0x00)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int spca506_ReadI2c(struct gspca_dev *gspca_dev, __u16 reg)
|
||||
{
|
||||
int retry = 60;
|
||||
unsigned char Data[2];
|
||||
unsigned char value;
|
||||
|
||||
reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
|
||||
reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
|
||||
reg_w(gspca_dev->dev, 0x07, 0x01, 0x0002);
|
||||
while (--retry) {
|
||||
reg_r(gspca_dev->dev, 0x07, 0x0003, Data, 2);
|
||||
if ((Data[0] | Data[1]) == 0x00)
|
||||
break;
|
||||
}
|
||||
if (retry == 0)
|
||||
return -1;
|
||||
reg_r(gspca_dev->dev, 0x07, 0x0000, &value, 1);
|
||||
return value;
|
||||
}
|
||||
|
||||
static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,
|
||||
__u16 norme,
|
||||
__u16 channel)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
/* fixme: check if channel == 0..3 and 6..9 (8 values) */
|
||||
__u8 setbit0 = 0x00;
|
||||
__u8 setbit1 = 0x00;
|
||||
__u8 videomask = 0x00;
|
||||
|
||||
PDEBUG(D_STREAM, "** Open Set Norme **");
|
||||
spca506_Initi2c(gspca_dev);
|
||||
/* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */
|
||||
/* Composite channel bit1 -> 1 S-video bit 1 -> 0 */
|
||||
/* and exclude SAA7113 reserved channel set default 0 otherwise */
|
||||
if (norme & V4L2_STD_NTSC)
|
||||
setbit0 = 0x01;
|
||||
if (channel == 4 || channel == 5 || channel > 9)
|
||||
channel = 0;
|
||||
if (channel < 4)
|
||||
setbit1 = 0x02;
|
||||
videomask = (0x48 | setbit0 | setbit1);
|
||||
reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);
|
||||
spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);
|
||||
|
||||
if (norme & V4L2_STD_NTSC)
|
||||
spca506_WriteI2c(gspca_dev, 0x33, 0x0e);
|
||||
/* Chrominance Control NTSC N */
|
||||
else if (norme & V4L2_STD_SECAM)
|
||||
spca506_WriteI2c(gspca_dev, 0x53, 0x0e);
|
||||
/* Chrominance Control SECAM */
|
||||
else
|
||||
spca506_WriteI2c(gspca_dev, 0x03, 0x0e);
|
||||
/* Chrominance Control PAL BGHIV */
|
||||
|
||||
sd->norme = norme;
|
||||
sd->channel = channel;
|
||||
PDEBUG(D_STREAM, "Set Video Byte to 0x%2x", videomask);
|
||||
PDEBUG(D_STREAM, "Set Norme: %08x Channel %d", norme, channel);
|
||||
}
|
||||
|
||||
static void spca506_GetNormeInput(struct gspca_dev *gspca_dev,
|
||||
__u16 *norme, __u16 *channel)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
/* Read the register is not so good value change so
|
||||
we use your own copy in spca50x struct */
|
||||
*norme = sd->norme;
|
||||
*channel = sd->channel;
|
||||
PDEBUG(D_STREAM, "Get Norme: %d Channel %d", *norme, *channel);
|
||||
}
|
||||
|
||||
static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,
|
||||
__u16 xmult, __u16 ymult)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
|
||||
PDEBUG(D_STREAM, "** SetSize **");
|
||||
reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);
|
||||
/* Soft snap 0x40 Hard 0x41 */
|
||||
reg_w(dev, 0x04, 0x41, 0x0001);
|
||||
reg_w(dev, 0x04, 0x00, 0x0002);
|
||||
/* reserved */
|
||||
reg_w(dev, 0x04, 0x00, 0x0003);
|
||||
|
||||
/* reserved */
|
||||
reg_w(dev, 0x04, 0x00, 0x0004);
|
||||
/* reserved */
|
||||
reg_w(dev, 0x04, 0x01, 0x0005);
|
||||
/* reserced */
|
||||
reg_w(dev, 0x04, xmult, 0x0006);
|
||||
/* reserved */
|
||||
reg_w(dev, 0x04, ymult, 0x0007);
|
||||
/* compression 1 */
|
||||
reg_w(dev, 0x04, 0x00, 0x0008);
|
||||
/* T=64 -> 2 */
|
||||
reg_w(dev, 0x04, 0x00, 0x0009);
|
||||
/* threshold2D */
|
||||
reg_w(dev, 0x04, 0x21, 0x000a);
|
||||
/* quantization */
|
||||
reg_w(dev, 0x04, 0x00, 0x000b);
|
||||
}
|
||||
|
||||
/* this function is called at probe time */
|
||||
static int sd_config(struct gspca_dev *gspca_dev,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct cam *cam;
|
||||
|
||||
cam = &gspca_dev->cam;
|
||||
cam->dev_name = (char *) id->driver_info;
|
||||
cam->epaddr = 0x01;
|
||||
cam->cam_mode = vga_mode;
|
||||
cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
|
||||
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
|
||||
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
|
||||
sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
|
||||
sd->hue = sd_ctrls[SD_HUE].qctrl.default_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this function is called at open time */
|
||||
static int sd_open(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
|
||||
reg_w(dev, 0x03, 0x00, 0x0004);
|
||||
reg_w(dev, 0x03, 0xFF, 0x0003);
|
||||
reg_w(dev, 0x03, 0x00, 0x0000);
|
||||
reg_w(dev, 0x03, 0x1c, 0x0001);
|
||||
reg_w(dev, 0x03, 0x18, 0x0001);
|
||||
/* Init on PAL and composite input0 */
|
||||
spca506_SetNormeInput(gspca_dev, 0, 0);
|
||||
reg_w(dev, 0x03, 0x1c, 0x0001);
|
||||
reg_w(dev, 0x03, 0x18, 0x0001);
|
||||
reg_w(dev, 0x05, 0x00, 0x0000);
|
||||
reg_w(dev, 0x05, 0xef, 0x0001);
|
||||
reg_w(dev, 0x05, 0x00, 0x00c1);
|
||||
reg_w(dev, 0x05, 0x00, 0x00c2);
|
||||
reg_w(dev, 0x06, 0x18, 0x0002);
|
||||
reg_w(dev, 0x06, 0xf5, 0x0011);
|
||||
reg_w(dev, 0x06, 0x02, 0x0012);
|
||||
reg_w(dev, 0x06, 0xfb, 0x0013);
|
||||
reg_w(dev, 0x06, 0x00, 0x0014);
|
||||
reg_w(dev, 0x06, 0xa4, 0x0051);
|
||||
reg_w(dev, 0x06, 0x40, 0x0052);
|
||||
reg_w(dev, 0x06, 0x71, 0x0053);
|
||||
reg_w(dev, 0x06, 0x40, 0x0054);
|
||||
/************************************************/
|
||||
reg_w(dev, 0x03, 0x00, 0x0004);
|
||||
reg_w(dev, 0x03, 0x00, 0x0003);
|
||||
reg_w(dev, 0x03, 0x00, 0x0004);
|
||||
reg_w(dev, 0x03, 0xFF, 0x0003);
|
||||
reg_w(dev, 0x02, 0x00, 0x0000);
|
||||
reg_w(dev, 0x03, 0x60, 0x0000);
|
||||
reg_w(dev, 0x03, 0x18, 0x0001);
|
||||
/* for a better reading mx :) */
|
||||
/*sdca506_WriteI2c(value,register) */
|
||||
spca506_Initi2c(gspca_dev);
|
||||
spca506_WriteI2c(gspca_dev, 0x08, 0x01);
|
||||
spca506_WriteI2c(gspca_dev, 0xc0, 0x02);
|
||||
/* input composite video */
|
||||
spca506_WriteI2c(gspca_dev, 0x33, 0x03);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x04);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x05);
|
||||
spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
|
||||
spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
|
||||
spca506_WriteI2c(gspca_dev, 0x98, 0x08);
|
||||
spca506_WriteI2c(gspca_dev, 0x03, 0x09);
|
||||
spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
|
||||
spca506_WriteI2c(gspca_dev, 0x47, 0x0b);
|
||||
spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
|
||||
spca506_WriteI2c(gspca_dev, 0x03, 0x0e); /* Chroma Pal adjust */
|
||||
spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x10);
|
||||
spca506_WriteI2c(gspca_dev, 0x0c, 0x11);
|
||||
spca506_WriteI2c(gspca_dev, 0xb8, 0x12);
|
||||
spca506_WriteI2c(gspca_dev, 0x01, 0x13);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x14);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x15);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x16);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x17);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x18);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x19);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
|
||||
spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
|
||||
spca506_WriteI2c(gspca_dev, 0x02, 0x40);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x41);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x42);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x43);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x44);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x45);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x46);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x47);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x48);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x49);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x50);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x51);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x52);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x53);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x54);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x55);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x56);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x57);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x58);
|
||||
spca506_WriteI2c(gspca_dev, 0x54, 0x59);
|
||||
spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
|
||||
spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x60);
|
||||
spca506_WriteI2c(gspca_dev, 0x05, 0x61);
|
||||
spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
|
||||
PDEBUG(D_STREAM, "** Close Init *");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sd_start(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
__u16 norme;
|
||||
__u16 channel;
|
||||
__u8 Data[2];
|
||||
|
||||
/**************************************/
|
||||
reg_w(dev, 0x03, 0x00, 0x0004);
|
||||
reg_w(dev, 0x03, 0x00, 0x0003);
|
||||
reg_w(dev, 0x03, 0x00, 0x0004);
|
||||
reg_w(dev, 0x03, 0xFF, 0x0003);
|
||||
reg_w(dev, 0x02, 0x00, 0x0000);
|
||||
reg_w(dev, 0x03, 0x60, 0x0000);
|
||||
reg_w(dev, 0x03, 0x18, 0x0001);
|
||||
|
||||
/*sdca506_WriteI2c(value,register) */
|
||||
spca506_Initi2c(gspca_dev);
|
||||
spca506_WriteI2c(gspca_dev, 0x08, 0x01); /* Increment Delay */
|
||||
/* spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */
|
||||
spca506_WriteI2c(gspca_dev, 0x33, 0x03);
|
||||
/* Analog Input Control 2 */
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x04);
|
||||
/* Analog Input Control 3 */
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x05);
|
||||
/* Analog Input Control 4 */
|
||||
spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
|
||||
/* Horizontal Sync Start 0xe9-0x0d */
|
||||
spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
|
||||
/* Horizontal Sync Stop 0x0d-0xf0 */
|
||||
|
||||
spca506_WriteI2c(gspca_dev, 0x98, 0x08); /* Sync Control */
|
||||
/* Defaults value */
|
||||
spca506_WriteI2c(gspca_dev, 0x03, 0x09); /* Luminance Control */
|
||||
spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
|
||||
/* Luminance Brightness */
|
||||
spca506_WriteI2c(gspca_dev, 0x47, 0x0b); /* Luminance Contrast */
|
||||
spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
|
||||
/* Chrominance Saturation */
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
|
||||
/* Chrominance Hue Control */
|
||||
spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
|
||||
/* Chrominance Gain Control */
|
||||
/**************************************/
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x10);
|
||||
/* Format/Delay Control */
|
||||
spca506_WriteI2c(gspca_dev, 0x0c, 0x11); /* Output Control 1 */
|
||||
spca506_WriteI2c(gspca_dev, 0xb8, 0x12); /* Output Control 2 */
|
||||
spca506_WriteI2c(gspca_dev, 0x01, 0x13); /* Output Control 3 */
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x14); /* reserved */
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x15); /* VGATE START */
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x16); /* VGATE STOP */
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x17); /* VGATE Control (MSB) */
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x18);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x19);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
|
||||
spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
|
||||
spca506_WriteI2c(gspca_dev, 0x02, 0x40);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x41);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x42);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x43);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x44);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x45);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x46);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x47);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x48);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x49);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x50);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x51);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x52);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x53);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x54);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x55);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x56);
|
||||
spca506_WriteI2c(gspca_dev, 0xff, 0x57);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x58);
|
||||
spca506_WriteI2c(gspca_dev, 0x54, 0x59);
|
||||
spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
|
||||
spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
|
||||
spca506_WriteI2c(gspca_dev, 0x00, 0x60);
|
||||
spca506_WriteI2c(gspca_dev, 0x05, 0x61);
|
||||
spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
|
||||
/**************************************/
|
||||
reg_w(dev, 0x05, 0x00, 0x0003);
|
||||
reg_w(dev, 0x05, 0x00, 0x0004);
|
||||
reg_w(dev, 0x03, 0x10, 0x0001);
|
||||
reg_w(dev, 0x03, 0x78, 0x0000);
|
||||
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
|
||||
case 0:
|
||||
spca506_Setsize(gspca_dev, 0, 0x10, 0x10);
|
||||
break;
|
||||
case 1:
|
||||
spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);
|
||||
break;
|
||||
case 2:
|
||||
spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);
|
||||
break;
|
||||
case 4:
|
||||
spca506_Setsize(gspca_dev, 4, 0x34, 0x34);
|
||||
break;
|
||||
default:
|
||||
/* case 5: */
|
||||
spca506_Setsize(gspca_dev, 5, 0x40, 0x40);
|
||||
break;
|
||||
}
|
||||
|
||||
/* compress setting and size */
|
||||
/* set i2c luma */
|
||||
reg_w(dev, 0x02, 0x01, 0x0000);
|
||||
reg_w(dev, 0x03, 0x12, 0x000);
|
||||
reg_r(dev, 0x04, 0x0001, Data, 2);
|
||||
PDEBUG(D_STREAM, "webcam started");
|
||||
spca506_GetNormeInput(gspca_dev, &norme, &channel);
|
||||
spca506_SetNormeInput(gspca_dev, norme, channel);
|
||||
}
|
||||
|
||||
static void sd_stopN(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
|
||||
reg_w(dev, 0x02, 0x00, 0x0000);
|
||||
reg_w(dev, 0x03, 0x00, 0x0004);
|
||||
reg_w(dev, 0x03, 0x00, 0x0003);
|
||||
}
|
||||
|
||||
static void sd_stop0(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void sd_close(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
/* convert YYUV per line to YUYV (YUV 4:2:2) */
|
||||
static void yyuv_decode(unsigned char *out,
|
||||
unsigned char *in,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
unsigned char *Ui, *Vi, *yi, *yi1;
|
||||
unsigned char *out1;
|
||||
int i, j;
|
||||
|
||||
yi = in;
|
||||
for (i = height / 2; --i >= 0; ) {
|
||||
out1 = out + width * 2; /* next line */
|
||||
yi1 = yi + width;
|
||||
Ui = yi1 + width;
|
||||
Vi = Ui + width / 2;
|
||||
for (j = width / 2; --j >= 0; ) {
|
||||
*out++ = 128 + *yi++;
|
||||
*out++ = 128 + *Ui;
|
||||
*out++ = 128 + *yi++;
|
||||
*out++ = 128 + *Vi;
|
||||
|
||||
*out1++ = 128 + *yi1++;
|
||||
*out1++ = 128 + *Ui++;
|
||||
*out1++ = 128 + *yi1++;
|
||||
*out1++ = 128 + *Vi++;
|
||||
}
|
||||
yi += width * 2;
|
||||
out = out1;
|
||||
}
|
||||
}
|
||||
|
||||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame, /* target */
|
||||
unsigned char *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
switch (data[0]) {
|
||||
case 0: /* start of frame */
|
||||
if (gspca_dev->last_packet_type == FIRST_PACKET) {
|
||||
yyuv_decode(sd->tmpbuf2, sd->tmpbuf,
|
||||
gspca_dev->width,
|
||||
gspca_dev->height);
|
||||
frame = gspca_frame_add(gspca_dev,
|
||||
LAST_PACKET,
|
||||
frame,
|
||||
sd->tmpbuf2,
|
||||
gspca_dev->width
|
||||
* gspca_dev->height
|
||||
* 2);
|
||||
}
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
|
||||
data, 0);
|
||||
data += SPCA50X_OFFSET_DATA;
|
||||
len -= SPCA50X_OFFSET_DATA;
|
||||
if (len > 0)
|
||||
memcpy(sd->tmpbuf, data, len);
|
||||
else
|
||||
len = 0;
|
||||
sd->buflen = len;
|
||||
return;
|
||||
case 0xff: /* drop */
|
||||
/* gspca_dev->last_packet_type = DISCARD_PACKET; */
|
||||
return;
|
||||
}
|
||||
data += 1;
|
||||
len -= 1;
|
||||
memcpy(&sd->tmpbuf[sd->buflen], data, len);
|
||||
sd->buflen += len;
|
||||
}
|
||||
|
||||
static void setbrightness(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
spca506_Initi2c(gspca_dev);
|
||||
spca506_WriteI2c(gspca_dev, sd->brightness, SAA7113_bright);
|
||||
spca506_WriteI2c(gspca_dev, 0x01, 0x09);
|
||||
}
|
||||
|
||||
static void getbrightness(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->brightness = spca506_ReadI2c(gspca_dev, SAA7113_bright);
|
||||
}
|
||||
|
||||
static void setcontrast(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
spca506_Initi2c(gspca_dev);
|
||||
spca506_WriteI2c(gspca_dev, sd->contrast, SAA7113_contrast);
|
||||
spca506_WriteI2c(gspca_dev, 0x01, 0x09);
|
||||
}
|
||||
|
||||
static void getcontrast(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->contrast = spca506_ReadI2c(gspca_dev, SAA7113_contrast);
|
||||
}
|
||||
|
||||
static void setcolors(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
spca506_Initi2c(gspca_dev);
|
||||
spca506_WriteI2c(gspca_dev, sd->colors, SAA7113_saturation);
|
||||
spca506_WriteI2c(gspca_dev, 0x01, 0x09);
|
||||
}
|
||||
|
||||
static void getcolors(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->colors = spca506_ReadI2c(gspca_dev, SAA7113_saturation);
|
||||
}
|
||||
|
||||
static void sethue(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
spca506_Initi2c(gspca_dev);
|
||||
spca506_WriteI2c(gspca_dev, sd->hue, SAA7113_hue);
|
||||
spca506_WriteI2c(gspca_dev, 0x01, 0x09);
|
||||
}
|
||||
|
||||
static void gethue(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->hue = spca506_ReadI2c(gspca_dev, SAA7113_hue);
|
||||
}
|
||||
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->brightness = val;
|
||||
if (gspca_dev->streaming)
|
||||
setbrightness(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
getbrightness(gspca_dev);
|
||||
*val = sd->brightness;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->contrast = val;
|
||||
if (gspca_dev->streaming)
|
||||
setcontrast(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
getcontrast(gspca_dev);
|
||||
*val = sd->contrast;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->colors = val;
|
||||
if (gspca_dev->streaming)
|
||||
setcolors(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
getcolors(gspca_dev);
|
||||
*val = sd->colors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->hue = val;
|
||||
if (gspca_dev->streaming)
|
||||
sethue(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
gethue(gspca_dev);
|
||||
*val = sd->hue;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sub-driver description */
|
||||
static struct sd_desc sd_desc = {
|
||||
.name = MODULE_NAME,
|
||||
.ctrls = sd_ctrls,
|
||||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||||
.config = sd_config,
|
||||
.open = sd_open,
|
||||
.start = sd_start,
|
||||
.stopN = sd_stopN,
|
||||
.stop0 = sd_stop0,
|
||||
.close = sd_close,
|
||||
.pkt_scan = sd_pkt_scan,
|
||||
};
|
||||
|
||||
/* -- module initialisation -- */
|
||||
#define DVNM(name) .driver_info = (kernel_ulong_t) name
|
||||
static __devinitdata struct usb_device_id device_table[] = {
|
||||
{USB_DEVICE(0x06e1, 0xa190), DVNM("ADS Instant VCD")},
|
||||
/* {USB_DEVICE(0x0733, 0x0430), DVNM("UsbGrabber PV321c")}, */
|
||||
{USB_DEVICE(0x0734, 0x043b), DVNM("3DeMon USB Capture aka")},
|
||||
{USB_DEVICE(0x99fa, 0x8988), DVNM("Grandtec V.cap")},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, device_table);
|
||||
|
||||
/* -- device connect -- */
|
||||
static int sd_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
|
||||
THIS_MODULE);
|
||||
}
|
||||
|
||||
static struct usb_driver sd_driver = {
|
||||
.name = MODULE_NAME,
|
||||
.id_table = device_table,
|
||||
.probe = sd_probe,
|
||||
.disconnect = gspca_disconnect,
|
||||
};
|
||||
|
||||
/* -- module insert / remove -- */
|
||||
static int __init sd_mod_init(void)
|
||||
{
|
||||
if (usb_register(&sd_driver) < 0)
|
||||
return -1;
|
||||
PDEBUG(D_PROBE, "v%s registered", version);
|
||||
return 0;
|
||||
}
|
||||
static void __exit sd_mod_exit(void)
|
||||
{
|
||||
usb_deregister(&sd_driver);
|
||||
PDEBUG(D_PROBE, "deregistered");
|
||||
}
|
||||
|
||||
module_init(sd_mod_init);
|
||||
module_exit(sd_mod_exit);
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -23,8 +23,8 @@
|
|||
#include "gspca.h"
|
||||
#include "jpeg.h"
|
||||
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 2, 7)
|
||||
static const char version[] = "0.2.7";
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
|
||||
static const char version[] = "2.1.0";
|
||||
|
||||
MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
|
||||
MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
|
||||
|
@ -37,10 +37,10 @@ struct sd {
|
|||
unsigned char brightness;
|
||||
unsigned char contrast;
|
||||
unsigned char colors;
|
||||
unsigned char lightfreq;
|
||||
};
|
||||
|
||||
/* global parameters */
|
||||
static int lightfreq = 50;
|
||||
static int sd_quant = 7; /* <= 4 KO - 7: good (enough!) */
|
||||
|
||||
/* V4L2 controls supported by the driver */
|
||||
|
@ -50,6 +50,8 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
|
|||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
|
||||
static struct ctrl sd_ctrls[] = {
|
||||
#define SD_BRIGHTNESS 0
|
||||
|
@ -94,6 +96,20 @@ static struct ctrl sd_ctrls[] = {
|
|||
.set = sd_setcolors,
|
||||
.get = sd_getcolors,
|
||||
},
|
||||
#define SD_FREQ 3
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_POWER_LINE_FREQUENCY,
|
||||
.type = V4L2_CTRL_TYPE_MENU,
|
||||
.name = "Light frequency filter",
|
||||
.minimum = 1,
|
||||
.maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
|
||||
.step = 1,
|
||||
.default_value = 1,
|
||||
},
|
||||
.set = sd_setfreq,
|
||||
.get = sd_getfreq,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_mode vga_mode[] = {
|
||||
|
@ -102,11 +118,11 @@ static struct cam_mode vga_mode[] = {
|
|||
};
|
||||
|
||||
/* -- read a register -- */
|
||||
static int reg_read(struct gspca_dev *gspca_dev,
|
||||
static int reg_r(struct gspca_dev *gspca_dev,
|
||||
__u16 index, __u8 *buf)
|
||||
{
|
||||
int ret;
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
int ret;
|
||||
|
||||
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
0x00,
|
||||
|
@ -116,12 +132,12 @@ static int reg_read(struct gspca_dev *gspca_dev,
|
|||
buf, 1,
|
||||
500);
|
||||
if (ret < 0)
|
||||
PDEBUG(D_ERR, "reg_read err %d", ret);
|
||||
PDEBUG(D_ERR, "reg_r err %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -- write a register -- */
|
||||
static int reg_write(struct gspca_dev *gspca_dev,
|
||||
static int reg_w(struct gspca_dev *gspca_dev,
|
||||
__u16 index, __u16 value)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
|
@ -136,7 +152,7 @@ static int reg_write(struct gspca_dev *gspca_dev,
|
|||
0,
|
||||
500);
|
||||
if (ret < 0)
|
||||
PDEBUG(D_ERR, "reg_write err %d", ret);
|
||||
PDEBUG(D_ERR, "reg_w err %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -149,15 +165,15 @@ static int rcv_val(struct gspca_dev *gspca_dev,
|
|||
int alen, ret;
|
||||
unsigned char bulk_buf[4];
|
||||
|
||||
reg_write(gspca_dev, 0x634, (ads >> 16) & 0xff);
|
||||
reg_write(gspca_dev, 0x635, (ads >> 8) & 0xff);
|
||||
reg_write(gspca_dev, 0x636, ads & 0xff);
|
||||
reg_write(gspca_dev, 0x637, 0);
|
||||
reg_write(gspca_dev, 0x638, len & 0xff);
|
||||
reg_write(gspca_dev, 0x639, len >> 8);
|
||||
reg_write(gspca_dev, 0x63a, 0);
|
||||
reg_write(gspca_dev, 0x63b, 0);
|
||||
reg_write(gspca_dev, 0x630, 5);
|
||||
reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
|
||||
reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
|
||||
reg_w(gspca_dev, 0x636, ads & 0xff);
|
||||
reg_w(gspca_dev, 0x637, 0);
|
||||
reg_w(gspca_dev, 0x638, len & 0xff);
|
||||
reg_w(gspca_dev, 0x639, len >> 8);
|
||||
reg_w(gspca_dev, 0x63a, 0);
|
||||
reg_w(gspca_dev, 0x63b, 0);
|
||||
reg_w(gspca_dev, 0x630, 5);
|
||||
if (len > sizeof bulk_buf)
|
||||
return -1;
|
||||
ret = usb_bulk_msg(dev,
|
||||
|
@ -180,26 +196,26 @@ static int snd_val(struct gspca_dev *gspca_dev,
|
|||
unsigned char bulk_buf[4];
|
||||
|
||||
if (ads == 0x003f08) {
|
||||
ret = reg_read(gspca_dev, 0x0704, &value);
|
||||
ret = reg_r(gspca_dev, 0x0704, &value);
|
||||
if (ret < 0)
|
||||
goto ko;
|
||||
ret = reg_read(gspca_dev, 0x0705, &seq);
|
||||
ret = reg_r(gspca_dev, 0x0705, &seq);
|
||||
if (ret < 0)
|
||||
goto ko;
|
||||
ret = reg_read(gspca_dev, 0x0650, &value);
|
||||
ret = reg_r(gspca_dev, 0x0650, &value);
|
||||
if (ret < 0)
|
||||
goto ko;
|
||||
reg_write(gspca_dev, 0x654, seq);
|
||||
reg_w(gspca_dev, 0x654, seq);
|
||||
} else
|
||||
reg_write(gspca_dev, 0x654, (ads >> 16) & 0xff);
|
||||
reg_write(gspca_dev, 0x655, (ads >> 8) & 0xff);
|
||||
reg_write(gspca_dev, 0x656, ads & 0xff);
|
||||
reg_write(gspca_dev, 0x657, 0);
|
||||
reg_write(gspca_dev, 0x658, 0x04); /* size */
|
||||
reg_write(gspca_dev, 0x659, 0);
|
||||
reg_write(gspca_dev, 0x65a, 0);
|
||||
reg_write(gspca_dev, 0x65b, 0);
|
||||
reg_write(gspca_dev, 0x650, 5);
|
||||
reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
|
||||
reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
|
||||
reg_w(gspca_dev, 0x656, ads & 0xff);
|
||||
reg_w(gspca_dev, 0x657, 0);
|
||||
reg_w(gspca_dev, 0x658, 0x04); /* size */
|
||||
reg_w(gspca_dev, 0x659, 0);
|
||||
reg_w(gspca_dev, 0x65a, 0);
|
||||
reg_w(gspca_dev, 0x65b, 0);
|
||||
reg_w(gspca_dev, 0x650, 5);
|
||||
bulk_buf[0] = (val >> 24) & 0xff;
|
||||
bulk_buf[1] = (val >> 16) & 0xff;
|
||||
bulk_buf[2] = (val >> 8) & 0xff;
|
||||
|
@ -215,7 +231,7 @@ static int snd_val(struct gspca_dev *gspca_dev,
|
|||
if (ads == 0x003f08) {
|
||||
seq += 4;
|
||||
seq &= 0x3f;
|
||||
reg_write(gspca_dev, 0x705, seq);
|
||||
reg_w(gspca_dev, 0x705, seq);
|
||||
}
|
||||
return ret;
|
||||
ko:
|
||||
|
@ -235,7 +251,6 @@ static void setbrightness(struct gspca_dev *gspca_dev)
|
|||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int parval;
|
||||
|
||||
PDEBUG(D_CONF, "brightness: %d", sd->brightness);
|
||||
parval = 0x06000000 /* whiteness */
|
||||
+ (sd->brightness << 16);
|
||||
set_par(gspca_dev, parval);
|
||||
|
@ -246,7 +261,6 @@ static void setcontrast(struct gspca_dev *gspca_dev)
|
|||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int parval;
|
||||
|
||||
PDEBUG(D_CONF, "contrast: %d", sd->contrast);
|
||||
parval = 0x07000000 /* contrast */
|
||||
+ (sd->contrast << 16);
|
||||
set_par(gspca_dev, parval);
|
||||
|
@ -257,13 +271,20 @@ static void setcolors(struct gspca_dev *gspca_dev)
|
|||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int parval;
|
||||
|
||||
PDEBUG(D_CONF, "saturation: %d",
|
||||
sd->colors);
|
||||
parval = 0x08000000 /* saturation */
|
||||
+ (sd->colors << 16);
|
||||
set_par(gspca_dev, parval);
|
||||
}
|
||||
|
||||
static void setfreq(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
set_par(gspca_dev, sd->lightfreq == 1
|
||||
? 0x33640000 /* 50 Hz */
|
||||
: 0x33780000); /* 60 Hz */
|
||||
}
|
||||
|
||||
/* this function is called at probe time */
|
||||
static int sd_config(struct gspca_dev *gspca_dev,
|
||||
const struct usb_device_id *id)
|
||||
|
@ -278,6 +299,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
|||
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
|
||||
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
|
||||
sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
|
||||
sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -289,7 +311,7 @@ static int sd_open(struct gspca_dev *gspca_dev)
|
|||
|
||||
/* check if the device responds */
|
||||
usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
|
||||
ret = reg_read(gspca_dev, 0x0740, &value);
|
||||
ret = reg_r(gspca_dev, 0x0740, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (value != 0xff) {
|
||||
|
@ -320,21 +342,24 @@ static void sd_start(struct gspca_dev *gspca_dev)
|
|||
ret = usb_set_interface(gspca_dev->dev,
|
||||
gspca_dev->iface,
|
||||
gspca_dev->alt);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
PDEBUG(D_ERR|D_STREAM, "set intf %d %d failed",
|
||||
gspca_dev->iface, gspca_dev->alt);
|
||||
goto out;
|
||||
ret = reg_read(gspca_dev, 0x0630, &dum);
|
||||
}
|
||||
ret = reg_r(gspca_dev, 0x0630, &dum);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
rcv_val(gspca_dev, 0x000020, 4); /* << (value ff ff ff ff) */
|
||||
ret = reg_read(gspca_dev, 0x0650, &dum);
|
||||
ret = reg_r(gspca_dev, 0x0650, &dum);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
snd_val(gspca_dev, 0x000020, 0xffffffff);
|
||||
reg_write(gspca_dev, 0x0620, 0);
|
||||
reg_write(gspca_dev, 0x0630, 0);
|
||||
reg_write(gspca_dev, 0x0640, 0);
|
||||
reg_write(gspca_dev, 0x0650, 0);
|
||||
reg_write(gspca_dev, 0x0660, 0);
|
||||
reg_w(gspca_dev, 0x0620, 0);
|
||||
reg_w(gspca_dev, 0x0630, 0);
|
||||
reg_w(gspca_dev, 0x0640, 0);
|
||||
reg_w(gspca_dev, 0x0650, 0);
|
||||
reg_w(gspca_dev, 0x0660, 0);
|
||||
setbrightness(gspca_dev); /* whiteness */
|
||||
setcontrast(gspca_dev); /* contrast */
|
||||
setcolors(gspca_dev); /* saturation */
|
||||
|
@ -342,9 +367,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
|
|||
set_par(gspca_dev, 0x0a800000); /* Green ? */
|
||||
set_par(gspca_dev, 0x0b800000); /* Blue ? */
|
||||
set_par(gspca_dev, 0x0d030000); /* Gamma ? */
|
||||
set_par(gspca_dev, lightfreq == 60
|
||||
? 0x33780000 /* 60 Hz */
|
||||
: 0x33640000); /* 50 Hz */
|
||||
setfreq(gspca_dev); /* light frequency */
|
||||
|
||||
/* start the video flow */
|
||||
set_par(gspca_dev, 0x01000000);
|
||||
|
@ -363,15 +386,15 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
|
|||
set_par(gspca_dev, 0x02000000);
|
||||
set_par(gspca_dev, 0x02000000);
|
||||
usb_set_interface(dev, gspca_dev->iface, 1);
|
||||
reg_read(gspca_dev, 0x0630, &value);
|
||||
reg_r(gspca_dev, 0x0630, &value);
|
||||
rcv_val(gspca_dev, 0x000020, 4); /* << (value ff ff ff ff) */
|
||||
reg_read(gspca_dev, 0x0650, &value);
|
||||
reg_r(gspca_dev, 0x0650, &value);
|
||||
snd_val(gspca_dev, 0x000020, 0xffffffff);
|
||||
reg_write(gspca_dev, 0x0620, 0);
|
||||
reg_write(gspca_dev, 0x0630, 0);
|
||||
reg_write(gspca_dev, 0x0640, 0);
|
||||
reg_write(gspca_dev, 0x0650, 0);
|
||||
reg_write(gspca_dev, 0x0660, 0);
|
||||
reg_w(gspca_dev, 0x0620, 0);
|
||||
reg_w(gspca_dev, 0x0630, 0);
|
||||
reg_w(gspca_dev, 0x0640, 0);
|
||||
reg_w(gspca_dev, 0x0650, 0);
|
||||
reg_w(gspca_dev, 0x0660, 0);
|
||||
PDEBUG(D_STREAM, "camera stopped");
|
||||
}
|
||||
|
||||
|
@ -470,6 +493,42 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->lightfreq = val;
|
||||
if (gspca_dev->streaming)
|
||||
setfreq(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
*val = sd->lightfreq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_querymenu(struct gspca_dev *gspca_dev,
|
||||
struct v4l2_querymenu *menu)
|
||||
{
|
||||
switch (menu->id) {
|
||||
case V4L2_CID_POWER_LINE_FREQUENCY:
|
||||
switch (menu->index) {
|
||||
case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
|
||||
strcpy(menu->name, "50 Hz");
|
||||
return 0;
|
||||
case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
|
||||
strcpy(menu->name, "60 Hz");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* sub-driver description */
|
||||
static struct sd_desc sd_desc = {
|
||||
.name = MODULE_NAME,
|
||||
|
@ -482,6 +541,7 @@ static struct sd_desc sd_desc = {
|
|||
.stop0 = sd_stop0,
|
||||
.close = sd_close,
|
||||
.pkt_scan = sd_pkt_scan,
|
||||
.querymenu = sd_querymenu,
|
||||
};
|
||||
|
||||
/* -- module initialisation -- */
|
||||
|
@ -524,7 +584,5 @@ static void __exit sd_mod_exit(void)
|
|||
module_init(sd_mod_init);
|
||||
module_exit(sd_mod_exit);
|
||||
|
||||
module_param(lightfreq, int, 0644);
|
||||
MODULE_PARM_DESC(lightfreq, "Light frequency 50 or 60 Hz");
|
||||
module_param_named(quant, sd_quant, int, 0644);
|
||||
MODULE_PARM_DESC(quant, "Quantization index (0..8)");
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,709 @@
|
|||
/*
|
||||
* Quickcam cameras initialization data
|
||||
*
|
||||
* V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#define MODULE_NAME "tv8532"
|
||||
|
||||
#include "gspca.h"
|
||||
|
||||
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 0)
|
||||
static const char version[] = "2.1.0";
|
||||
|
||||
MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
|
||||
MODULE_DESCRIPTION("TV8532 USB Camera Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* specific webcam descriptor */
|
||||
struct sd {
|
||||
struct gspca_dev gspca_dev; /* !! must be the first item */
|
||||
|
||||
int buflen; /* current length of tmpbuf */
|
||||
__u8 tmpbuf[352 * 288 + 10 * 288]; /* no protection... */
|
||||
__u8 tmpbuf2[352 * 288]; /* no protection... */
|
||||
|
||||
unsigned short brightness;
|
||||
unsigned short contrast;
|
||||
|
||||
char packet;
|
||||
char synchro;
|
||||
};
|
||||
|
||||
/* V4L2 controls supported by the driver */
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
|
||||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
|
||||
|
||||
static struct ctrl sd_ctrls[] = {
|
||||
#define SD_BRIGHTNESS 0
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_BRIGHTNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Brightness",
|
||||
.minimum = 1,
|
||||
.maximum = 0x2ff,
|
||||
.step = 1,
|
||||
.default_value = 0x18f,
|
||||
},
|
||||
.set = sd_setbrightness,
|
||||
.get = sd_getbrightness,
|
||||
},
|
||||
#define SD_CONTRAST 1
|
||||
{
|
||||
{
|
||||
.id = V4L2_CID_CONTRAST,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Contrast",
|
||||
.minimum = 0,
|
||||
.maximum = 0xffff,
|
||||
.step = 1,
|
||||
.default_value = 0x7fff,
|
||||
},
|
||||
.set = sd_setcontrast,
|
||||
.get = sd_getcontrast,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cam_mode sif_mode[] = {
|
||||
{V4L2_PIX_FMT_SBGGR8, 176, 144, 1},
|
||||
{V4L2_PIX_FMT_SBGGR8, 352, 288, 0},
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialization data: this is the first set-up data written to the
|
||||
* device (before the open data).
|
||||
*/
|
||||
#define TESTCLK 0x10 /* reg 0x2c -> 0x12 //10 */
|
||||
#define TESTCOMP 0x90 /* reg 0x28 -> 0x80 */
|
||||
#define TESTLINE 0x81 /* reg 0x29 -> 0x81 */
|
||||
#define QCIFLINE 0x41 /* reg 0x29 -> 0x81 */
|
||||
#define TESTPTL 0x14 /* reg 0x2D -> 0x14 */
|
||||
#define TESTPTH 0x01 /* reg 0x2E -> 0x01 */
|
||||
#define TESTPTBL 0x12 /* reg 0x2F -> 0x0a */
|
||||
#define TESTPTBH 0x01 /* reg 0x30 -> 0x01 */
|
||||
#define ADWIDTHL 0xe8 /* reg 0x0c -> 0xe8 */
|
||||
#define ADWIDTHH 0x03 /* reg 0x0d -> 0x03 */
|
||||
#define ADHEIGHL 0x90 /* reg 0x0e -> 0x91 //93 */
|
||||
#define ADHEIGHH 0x01 /* reg 0x0f -> 0x01 */
|
||||
#define EXPOL 0x8f /* reg 0x1c -> 0x8f */
|
||||
#define EXPOH 0x01 /* reg 0x1d -> 0x01 */
|
||||
#define ADCBEGINL 0x44 /* reg 0x10 -> 0x46 //47 */
|
||||
#define ADCBEGINH 0x00 /* reg 0x11 -> 0x00 */
|
||||
#define ADRBEGINL 0x0a /* reg 0x14 -> 0x0b //0x0c */
|
||||
#define ADRBEGINH 0x00 /* reg 0x15 -> 0x00 */
|
||||
#define TV8532_CMD_UPDATE 0x84
|
||||
|
||||
#define TV8532_EEprom_Add 0x03
|
||||
#define TV8532_EEprom_DataL 0x04
|
||||
#define TV8532_EEprom_DataM 0x05
|
||||
#define TV8532_EEprom_DataH 0x06
|
||||
#define TV8532_EEprom_TableLength 0x07
|
||||
#define TV8532_EEprom_Write 0x08
|
||||
#define TV8532_PART_CTRL 0x00
|
||||
#define TV8532_CTRL 0x01
|
||||
#define TV8532_CMD_EEprom_Open 0x30
|
||||
#define TV8532_CMD_EEprom_Close 0x29
|
||||
#define TV8532_UDP_UPDATE 0x31
|
||||
#define TV8532_GPIO 0x39
|
||||
#define TV8532_GPIO_OE 0x3B
|
||||
#define TV8532_REQ_RegWrite 0x02
|
||||
#define TV8532_REQ_RegRead 0x03
|
||||
|
||||
#define TV8532_ADWIDTH_L 0x0C
|
||||
#define TV8532_ADWIDTH_H 0x0D
|
||||
#define TV8532_ADHEIGHT_L 0x0E
|
||||
#define TV8532_ADHEIGHT_H 0x0F
|
||||
#define TV8532_EXPOSURE 0x1C
|
||||
#define TV8532_QUANT_COMP 0x28
|
||||
#define TV8532_MODE_PACKET 0x29
|
||||
#define TV8532_SETCLK 0x2C
|
||||
#define TV8532_POINT_L 0x2D
|
||||
#define TV8532_POINT_H 0x2E
|
||||
#define TV8532_POINTB_L 0x2F
|
||||
#define TV8532_POINTB_H 0x30
|
||||
#define TV8532_BUDGET_L 0x2A
|
||||
#define TV8532_BUDGET_H 0x2B
|
||||
#define TV8532_VID_L 0x34
|
||||
#define TV8532_VID_H 0x35
|
||||
#define TV8532_PID_L 0x36
|
||||
#define TV8532_PID_H 0x37
|
||||
#define TV8532_DeviceID 0x83
|
||||
#define TV8532_AD_SLOPE 0x91
|
||||
#define TV8532_AD_BITCTRL 0x94
|
||||
#define TV8532_AD_COLBEGIN_L 0x10
|
||||
#define TV8532_AD_COLBEGIN_H 0x11
|
||||
#define TV8532_AD_ROWBEGIN_L 0x14
|
||||
#define TV8532_AD_ROWBEGIN_H 0x15
|
||||
|
||||
static __u32 tv_8532_eeprom_data[] = {
|
||||
/* add dataL dataM dataH */
|
||||
0x00010001, 0x01018011, 0x02050014, 0x0305001c,
|
||||
0x040d001e, 0x0505001f, 0x06050519, 0x0705011b,
|
||||
0x0805091e, 0x090d892e, 0x0a05892f, 0x0b050dd9,
|
||||
0x0c0509f1, 0
|
||||
};
|
||||
|
||||
static void reg_r(struct usb_device *dev,
|
||||
__u16 index, __u8 *buffer)
|
||||
{
|
||||
usb_control_msg(dev,
|
||||
usb_rcvctrlpipe(dev, 0),
|
||||
TV8532_REQ_RegRead,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0, /* value */
|
||||
index, buffer, sizeof(__u8),
|
||||
500);
|
||||
}
|
||||
|
||||
static void reg_w(struct usb_device *dev,
|
||||
__u16 index, __u8 *buffer, __u16 length)
|
||||
{
|
||||
usb_control_msg(dev,
|
||||
usb_sndctrlpipe(dev, 0),
|
||||
TV8532_REQ_RegWrite,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0, /* value */
|
||||
index, buffer, length, 500);
|
||||
}
|
||||
|
||||
static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
int i = 0;
|
||||
__u8 reg, data0, data1, data2, datacmd;
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
|
||||
datacmd = 0xb0;;
|
||||
reg_w(dev, TV8532_GPIO, &datacmd, 1);
|
||||
datacmd = TV8532_CMD_EEprom_Open;
|
||||
reg_w(dev, TV8532_CTRL, &datacmd,
|
||||
1);
|
||||
/* msleep(1); */
|
||||
while (tv_8532_eeprom_data[i]) {
|
||||
reg = (tv_8532_eeprom_data[i] & 0xff000000) >> 24;
|
||||
reg_w(dev, TV8532_EEprom_Add, ®, 1);
|
||||
/* msleep(1); */
|
||||
data0 = (tv_8532_eeprom_data[i] & 0x000000ff);
|
||||
reg_w(dev, TV8532_EEprom_DataL, &data0, 1);
|
||||
/* msleep(1); */
|
||||
data1 = (tv_8532_eeprom_data[i] & 0x0000FF00) >> 8;
|
||||
reg_w(dev, TV8532_EEprom_DataM, &data1, 1);
|
||||
/* msleep(1); */
|
||||
data2 = (tv_8532_eeprom_data[i] & 0x00FF0000) >> 16;
|
||||
reg_w(dev, TV8532_EEprom_DataH, &data2, 1);
|
||||
/* msleep(1); */
|
||||
datacmd = 0;
|
||||
reg_w(dev, TV8532_EEprom_Write, &datacmd, 1);
|
||||
/* msleep(10); */
|
||||
i++;
|
||||
}
|
||||
datacmd = i;
|
||||
reg_w(dev, TV8532_EEprom_TableLength, &datacmd, 1);
|
||||
/* msleep(1); */
|
||||
datacmd = TV8532_CMD_EEprom_Close;
|
||||
reg_w(dev, TV8532_CTRL, &datacmd, 1);
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
/* this function is called at probe time */
|
||||
static int sd_config(struct gspca_dev *gspca_dev,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct cam *cam;
|
||||
|
||||
tv_8532WriteEEprom(gspca_dev);
|
||||
|
||||
cam = &gspca_dev->cam;
|
||||
cam->dev_name = (char *) id->driver_info;
|
||||
cam->epaddr = 1;
|
||||
cam->cam_mode = sif_mode;
|
||||
cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
|
||||
|
||||
sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
|
||||
sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
__u8 data = 0;
|
||||
/* __u16 vid, pid; */
|
||||
|
||||
reg_r(dev, 0x0001, &data);
|
||||
PDEBUG(D_USBI, "register 0x01-> %x", data);
|
||||
reg_r(dev, 0x0002, &data);
|
||||
PDEBUG(D_USBI, "register 0x02-> %x", data);
|
||||
reg_r(dev, TV8532_ADWIDTH_L, &data);
|
||||
reg_r(dev, TV8532_ADWIDTH_H, &data);
|
||||
reg_r(dev, TV8532_QUANT_COMP, &data);
|
||||
reg_r(dev, TV8532_MODE_PACKET, &data);
|
||||
reg_r(dev, TV8532_SETCLK, &data);
|
||||
reg_r(dev, TV8532_POINT_L, &data);
|
||||
reg_r(dev, TV8532_POINT_H, &data);
|
||||
reg_r(dev, TV8532_POINTB_L, &data);
|
||||
reg_r(dev, TV8532_POINTB_H, &data);
|
||||
reg_r(dev, TV8532_BUDGET_L, &data);
|
||||
reg_r(dev, TV8532_BUDGET_H, &data);
|
||||
reg_r(dev, TV8532_VID_L, &data);
|
||||
reg_r(dev, TV8532_VID_H, &data);
|
||||
reg_r(dev, TV8532_PID_L, &data);
|
||||
reg_r(dev, TV8532_PID_H, &data);
|
||||
reg_r(dev, TV8532_DeviceID, &data);
|
||||
reg_r(dev, TV8532_AD_COLBEGIN_L, &data);
|
||||
reg_r(dev, TV8532_AD_COLBEGIN_H, &data);
|
||||
reg_r(dev, TV8532_AD_ROWBEGIN_L, &data);
|
||||
reg_r(dev, TV8532_AD_ROWBEGIN_H, &data);
|
||||
}
|
||||
|
||||
static void tv_8532_setReg(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
__u8 data = 0;
|
||||
__u8 value[2] = { 0, 0 };
|
||||
|
||||
data = ADCBEGINL;
|
||||
reg_w(dev, TV8532_AD_COLBEGIN_L, &data, 1); /* 0x10 */
|
||||
data = ADCBEGINH; /* also digital gain */
|
||||
reg_w(dev, TV8532_AD_COLBEGIN_H, &data, 1);
|
||||
data = TV8532_CMD_UPDATE;
|
||||
reg_w(dev, TV8532_PART_CTRL, &data, 1); /* 0x00<-0x84 */
|
||||
|
||||
data = 0x0a;
|
||||
reg_w(dev, TV8532_GPIO_OE, &data, 1);
|
||||
/******************************************************/
|
||||
data = ADHEIGHL;
|
||||
reg_w(dev, TV8532_ADHEIGHT_L, &data, 1); /* 0e */
|
||||
data = ADHEIGHH;
|
||||
reg_w(dev, TV8532_ADHEIGHT_H, &data, 1); /* 0f */
|
||||
value[0] = EXPOL;
|
||||
value[1] = EXPOH; /* 350d 0x014c; */
|
||||
reg_w(dev, TV8532_EXPOSURE, value, 2); /* 1c */
|
||||
data = ADCBEGINL;
|
||||
reg_w(dev, TV8532_AD_COLBEGIN_L, &data, 1); /* 0x10 */
|
||||
data = ADCBEGINH; /* also digital gain */
|
||||
reg_w(dev, TV8532_AD_COLBEGIN_H, &data, 1);
|
||||
data = ADRBEGINL;
|
||||
reg_w(dev, TV8532_AD_ROWBEGIN_L, &data, 1); /* 0x14 */
|
||||
|
||||
data = 0x00;
|
||||
reg_w(dev, TV8532_AD_SLOPE, &data, 1); /* 0x91 */
|
||||
data = 0x02;
|
||||
reg_w(dev, TV8532_AD_BITCTRL, &data, 1); /* 0x94 */
|
||||
|
||||
|
||||
data = TV8532_CMD_EEprom_Close;
|
||||
reg_w(dev, TV8532_CTRL, &data, 1); /* 0x01 */
|
||||
|
||||
data = 0x00;
|
||||
reg_w(dev, TV8532_AD_SLOPE, &data, 1); /* 0x91 */
|
||||
data = TV8532_CMD_UPDATE;
|
||||
reg_w(dev, TV8532_PART_CTRL, &data, 1); /* 0x00<-0x84 */
|
||||
}
|
||||
|
||||
static void tv_8532_PollReg(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
__u8 data = 0;
|
||||
int i;
|
||||
|
||||
/* strange polling from tgc */
|
||||
for (i = 0; i < 10; i++) {
|
||||
data = TESTCLK; /* 0x48; //0x08; */
|
||||
reg_w(dev, TV8532_SETCLK, &data, 1); /* 0x2c */
|
||||
data = TV8532_CMD_UPDATE;
|
||||
reg_w(dev, TV8532_PART_CTRL, &data, 1);
|
||||
data = 0x01;
|
||||
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
|
||||
}
|
||||
}
|
||||
|
||||
/* this function is called at open time */
|
||||
static int sd_open(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
__u8 data = 0;
|
||||
__u8 dataStart = 0;
|
||||
__u8 value[2] = { 0, 0 };
|
||||
|
||||
data = 0x32;
|
||||
reg_w(dev, TV8532_AD_SLOPE, &data, 1);
|
||||
data = 0;
|
||||
reg_w(dev, TV8532_AD_BITCTRL, &data, 1);
|
||||
tv_8532ReadRegisters(gspca_dev);
|
||||
data = 0x0b;
|
||||
reg_w(dev, TV8532_GPIO_OE, &data, 1);
|
||||
value[0] = ADHEIGHL;
|
||||
value[1] = ADHEIGHH; /* 401d 0x0169; */
|
||||
reg_w(dev, TV8532_ADHEIGHT_L, value, 2); /* 0e */
|
||||
value[0] = EXPOL;
|
||||
value[1] = EXPOH; /* 350d 0x014c; */
|
||||
reg_w(dev, TV8532_EXPOSURE, value, 2); /* 1c */
|
||||
data = ADWIDTHL; /* 0x20; */
|
||||
reg_w(dev, TV8532_ADWIDTH_L, &data, 1); /* 0x0c */
|
||||
data = ADWIDTHH;
|
||||
reg_w(dev, TV8532_ADWIDTH_H, &data, 1); /* 0x0d */
|
||||
|
||||
/*******************************************************************/
|
||||
data = TESTCOMP; /* 0x72 compressed mode */
|
||||
reg_w(dev, TV8532_QUANT_COMP, &data, 1); /* 0x28 */
|
||||
data = TESTLINE; /* 0x84; // CIF | 4 packet */
|
||||
reg_w(dev, TV8532_MODE_PACKET, &data, 1); /* 0x29 */
|
||||
|
||||
/************************************************/
|
||||
data = TESTCLK; /* 0x48; //0x08; */
|
||||
reg_w(dev, TV8532_SETCLK, &data, 1); /* 0x2c */
|
||||
data = TESTPTL; /* 0x38; */
|
||||
reg_w(dev, TV8532_POINT_L, &data, 1); /* 0x2d */
|
||||
data = TESTPTH; /* 0x04; */
|
||||
reg_w(dev, TV8532_POINT_H, &data, 1); /* 0x2e */
|
||||
dataStart = TESTPTBL; /* 0x04; */
|
||||
reg_w(dev, TV8532_POINTB_L, &dataStart, 1); /* 0x2f */
|
||||
data = TESTPTBH; /* 0x04; */
|
||||
reg_w(dev, TV8532_POINTB_H, &data, 1); /* 0x30 */
|
||||
data = TV8532_CMD_UPDATE;
|
||||
reg_w(dev, TV8532_PART_CTRL, &data, 1); /* 0x00<-0x84 */
|
||||
/*************************************************/
|
||||
data = 0x01;
|
||||
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
|
||||
msleep(200);
|
||||
data = 0x00;
|
||||
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
|
||||
/*************************************************/
|
||||
tv_8532_setReg(gspca_dev);
|
||||
/*************************************************/
|
||||
data = 0x0b;
|
||||
reg_w(dev, TV8532_GPIO_OE, &data,
|
||||
1);
|
||||
/*************************************************/
|
||||
tv_8532_setReg(gspca_dev);
|
||||
/*************************************************/
|
||||
tv_8532_PollReg(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setbrightness(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
__u8 value[2];
|
||||
__u8 data;
|
||||
int brightness = sd->brightness;
|
||||
|
||||
value[1] = (brightness >> 8) & 0xff;
|
||||
value[0] = (brightness) & 0xff;
|
||||
reg_w(gspca_dev->dev, TV8532_EXPOSURE, value, 2); /* 1c */
|
||||
data = TV8532_CMD_UPDATE;
|
||||
reg_w(gspca_dev->dev, TV8532_PART_CTRL, &data, 1);
|
||||
}
|
||||
|
||||
/* -- start the camera -- */
|
||||
static void sd_start(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
__u8 data = 0;
|
||||
__u8 dataStart = 0;
|
||||
__u8 value[2];
|
||||
|
||||
data = 0x32;
|
||||
reg_w(dev, TV8532_AD_SLOPE, &data, 1);
|
||||
data = 0;
|
||||
reg_w(dev, TV8532_AD_BITCTRL, &data, 1);
|
||||
tv_8532ReadRegisters(gspca_dev);
|
||||
data = 0x0b;
|
||||
reg_w(dev, TV8532_GPIO_OE, &data, 1);
|
||||
value[0] = ADHEIGHL;
|
||||
value[1] = ADHEIGHH; /* 401d 0x0169; */
|
||||
reg_w(dev, TV8532_ADHEIGHT_L, value, 2); /* 0e */
|
||||
/* value[0] = EXPOL; value[1] =EXPOH; * 350d 0x014c; */
|
||||
/* reg_w(dev,TV8532_REQ_RegWrite,0,TV8532_EXPOSURE,value,2); * 1c */
|
||||
setbrightness(gspca_dev);
|
||||
|
||||
data = ADWIDTHL; /* 0x20; */
|
||||
reg_w(dev, TV8532_ADWIDTH_L, &data, 1); /* 0x0c */
|
||||
data = ADWIDTHH;
|
||||
reg_w(dev, TV8532_ADWIDTH_H, &data, 1); /* 0x0d */
|
||||
|
||||
/************************************************/
|
||||
data = TESTCOMP; /* 0x72 compressed mode */
|
||||
reg_w(dev, TV8532_QUANT_COMP, &data, 1); /* 0x28 */
|
||||
if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
|
||||
/* 176x144 */
|
||||
data = QCIFLINE; /* 0x84; // CIF | 4 packet */
|
||||
reg_w(dev, TV8532_MODE_PACKET, &data, 1); /* 0x29 */
|
||||
} else {
|
||||
/* 352x288 */
|
||||
data = TESTLINE; /* 0x84; // CIF | 4 packet */
|
||||
reg_w(dev, TV8532_MODE_PACKET, &data, 1); /* 0x29 */
|
||||
}
|
||||
/************************************************/
|
||||
data = TESTCLK; /* 0x48; //0x08; */
|
||||
reg_w(dev, TV8532_SETCLK, &data, 1); /* 0x2c */
|
||||
data = TESTPTL; /* 0x38; */
|
||||
reg_w(dev, TV8532_POINT_L, &data, 1); /* 0x2d */
|
||||
data = TESTPTH; /* 0x04; */
|
||||
reg_w(dev, TV8532_POINT_H, &data, 1); /* 0x2e */
|
||||
dataStart = TESTPTBL; /* 0x04; */
|
||||
reg_w(dev, TV8532_POINTB_L, &dataStart, 1); /* 0x2f */
|
||||
data = TESTPTBH; /* 0x04; */
|
||||
reg_w(dev, TV8532_POINTB_H, &data, 1); /* 0x30 */
|
||||
data = TV8532_CMD_UPDATE;
|
||||
reg_w(dev, TV8532_PART_CTRL, &data, 1); /* 0x00<-0x84 */
|
||||
/************************************************/
|
||||
data = 0x01;
|
||||
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
|
||||
msleep(200);
|
||||
data = 0x00;
|
||||
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
|
||||
/************************************************/
|
||||
tv_8532_setReg(gspca_dev);
|
||||
/************************************************/
|
||||
data = 0x0b;
|
||||
reg_w(dev, TV8532_GPIO_OE, &data, 1);
|
||||
/************************************************/
|
||||
tv_8532_setReg(gspca_dev);
|
||||
/************************************************/
|
||||
tv_8532_PollReg(gspca_dev);
|
||||
data = 0x00;
|
||||
reg_w(dev, TV8532_UDP_UPDATE, &data, 1); /* 0x31 */
|
||||
}
|
||||
|
||||
static void sd_stopN(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct usb_device *dev = gspca_dev->dev;
|
||||
__u8 data;
|
||||
|
||||
data = 0x0b;
|
||||
reg_w(dev, TV8532_GPIO_OE, &data, 1);
|
||||
}
|
||||
|
||||
static void sd_stop0(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void sd_close(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void tv8532_preprocess(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
/* we should received a whole frame with header and EOL marker
|
||||
* in gspca_dev->tmpbuf and return a GBRG pattern in gspca_dev->tmpbuf2
|
||||
* sequence 2bytes header the Alternate pixels bayer GB 4 bytes
|
||||
* Alternate pixels bayer RG 4 bytes EOL */
|
||||
int width = gspca_dev->width;
|
||||
int height = gspca_dev->height;
|
||||
unsigned char *dst = sd->tmpbuf2;
|
||||
unsigned char *data = sd->tmpbuf;
|
||||
int i;
|
||||
|
||||
/* precompute where is the good bayer line */
|
||||
if (((data[3] + data[width + 7]) >> 1)
|
||||
+ (data[4] >> 2)
|
||||
+ (data[width + 6] >> 1) >= ((data[2] + data[width + 6]) >> 1)
|
||||
+ (data[3] >> 2)
|
||||
+ (data[width + 5] >> 1))
|
||||
data += 3;
|
||||
else
|
||||
data += 2;
|
||||
for (i = 0; i < height / 2; i++) {
|
||||
memcpy(dst, data, width);
|
||||
data += width + 3;
|
||||
dst += width;
|
||||
memcpy(dst, data, width);
|
||||
data += width + 7;
|
||||
dst += width;
|
||||
}
|
||||
}
|
||||
|
||||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
struct gspca_frame *frame, /* target */
|
||||
__u8 *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
if (data[0] != 0x80) {
|
||||
sd->packet++;
|
||||
if (sd->buflen + len > sizeof sd->tmpbuf) {
|
||||
if (gspca_dev->last_packet_type != DISCARD_PACKET) {
|
||||
PDEBUG(D_PACK, "buffer overflow");
|
||||
gspca_dev->last_packet_type = DISCARD_PACKET;
|
||||
}
|
||||
return;
|
||||
}
|
||||
memcpy(&sd->tmpbuf[sd->buflen], data, len);
|
||||
sd->buflen += len;
|
||||
return;
|
||||
}
|
||||
|
||||
/* here we detect 0x80 */
|
||||
/* counter is limited so we need few header for a frame :) */
|
||||
|
||||
/* header 0x80 0x80 0x80 0x80 0x80 */
|
||||
/* packet 00 63 127 145 00 */
|
||||
/* sof 0 1 1 0 0 */
|
||||
|
||||
/* update sequence */
|
||||
if (sd->packet == 63 || sd->packet == 127)
|
||||
sd->synchro = 1;
|
||||
|
||||
/* is there a frame start ? */
|
||||
if (sd->packet >= (gspca_dev->height >> 1) - 1) {
|
||||
PDEBUG(D_PACK, "SOF > %d packet %d", sd->synchro,
|
||||
sd->packet);
|
||||
if (!sd->synchro) { /* start of frame */
|
||||
if (gspca_dev->last_packet_type == FIRST_PACKET) {
|
||||
tv8532_preprocess(gspca_dev);
|
||||
frame = gspca_frame_add(gspca_dev,
|
||||
LAST_PACKET,
|
||||
frame, sd->tmpbuf2,
|
||||
gspca_dev->width *
|
||||
gspca_dev->width);
|
||||
}
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET,
|
||||
frame, data, 0);
|
||||
memcpy(sd->tmpbuf, data, len);
|
||||
sd->buflen = len;
|
||||
sd->packet = 0;
|
||||
return;
|
||||
}
|
||||
if (gspca_dev->last_packet_type != DISCARD_PACKET) {
|
||||
PDEBUG(D_PACK,
|
||||
"Warning wrong TV8532 frame detection %d",
|
||||
sd->packet);
|
||||
gspca_dev->last_packet_type = DISCARD_PACKET;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sd->synchro) {
|
||||
/* Drop packet frame corrupt */
|
||||
PDEBUG(D_PACK, "DROP SOF %d packet %d",
|
||||
sd->synchro, sd->packet);
|
||||
sd->packet = 0;
|
||||
gspca_dev->last_packet_type = DISCARD_PACKET;
|
||||
return;
|
||||
}
|
||||
sd->synchro = 1;
|
||||
sd->packet++;
|
||||
memcpy(&sd->tmpbuf[sd->buflen], data, len);
|
||||
sd->buflen += len;
|
||||
}
|
||||
|
||||
static void setcontrast(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->brightness = val;
|
||||
if (gspca_dev->streaming)
|
||||
setbrightness(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
*val = sd->brightness;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
sd->contrast = val;
|
||||
if (gspca_dev->streaming)
|
||||
setcontrast(gspca_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
|
||||
*val = sd->contrast;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sub-driver description */
|
||||
static struct sd_desc sd_desc = {
|
||||
.name = MODULE_NAME,
|
||||
.ctrls = sd_ctrls,
|
||||
.nctrls = ARRAY_SIZE(sd_ctrls),
|
||||
.config = sd_config,
|
||||
.open = sd_open,
|
||||
.start = sd_start,
|
||||
.stopN = sd_stopN,
|
||||
.stop0 = sd_stop0,
|
||||
.close = sd_close,
|
||||
.pkt_scan = sd_pkt_scan,
|
||||
};
|
||||
|
||||
/* -- module initialisation -- */
|
||||
#define DVNM(name) .driver_info = (kernel_ulong_t) name
|
||||
static __devinitdata struct usb_device_id device_table[] = {
|
||||
{USB_DEVICE(0x046d, 0x0920), DVNM("QC Express")},
|
||||
{USB_DEVICE(0x046d, 0x0921), DVNM("Labtec Webcam")},
|
||||
{USB_DEVICE(0x0545, 0x808b), DVNM("Veo Stingray")},
|
||||
{USB_DEVICE(0x0545, 0x8333), DVNM("Veo Stingray")},
|
||||
{USB_DEVICE(0x0923, 0x010f), DVNM("ICM532 cams")},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, device_table);
|
||||
|
||||
/* -- device connect -- */
|
||||
static int sd_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
|
||||
THIS_MODULE);
|
||||
}
|
||||
|
||||
static struct usb_driver sd_driver = {
|
||||
.name = MODULE_NAME,
|
||||
.id_table = device_table,
|
||||
.probe = sd_probe,
|
||||
.disconnect = gspca_disconnect,
|
||||
};
|
||||
|
||||
/* -- module insert / remove -- */
|
||||
static int __init sd_mod_init(void)
|
||||
{
|
||||
if (usb_register(&sd_driver) < 0)
|
||||
return -1;
|
||||
PDEBUG(D_PROBE, "v%s registered", version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit sd_mod_exit(void)
|
||||
{
|
||||
usb_deregister(&sd_driver);
|
||||
PDEBUG(D_PROBE, "deregistered");
|
||||
}
|
||||
|
||||
module_init(sd_mod_init);
|
||||
module_exit(sd_mod_exit);
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -324,6 +324,8 @@ struct v4l2_pix_format
|
|||
#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') /* pwc older webcam */
|
||||
#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') /* pwc newer webcam */
|
||||
#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */
|
||||
#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S','5','0','1') /* YUYV per line */
|
||||
#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S','5','6','1') /* compressed BGGR bayer */
|
||||
|
||||
/*
|
||||
* F O R M A T E N U M E R A T I O N
|
||||
|
|
Loading…
Reference in New Issue