diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 17:03:59 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 17:03:59 -0400 |
| commit | cf2fa66055d718ae13e62451bb546505f63906a2 (patch) | |
| tree | e206d3f04e74a34e9aa88d21af6c26eea21d4121 | |
| parent | 4501a466f28788485604ee42641d7a5fe7258d16 (diff) | |
| parent | 57f51dbc45f65f7ee1e8c8f77200bb8000e3e271 (diff) | |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (313 commits)
V4L/DVB (9186): Added support for Prof 7300 DVB-S/S2 cards
V4L/DVB (9185): S2API: Ensure we have a reasonable ROLLOFF default
V4L/DVB (9184): cx24116: Change the default SNR units back to percentage by default.
V4L/DVB (9183): S2API: Return error of the caller provides 0 commands.
V4L/DVB (9182): S2API: Added support for DTV_HIERARCHY
V4L/DVB (9181): S2API: Add support fot DTV_GUARD_INTERVAL and DTV_TRANSMISSION_MODE
V4L/DVB (9180): S2API: Added support for DTV_CODE_RATE_HP/LP
V4L/DVB (9179): S2API: frontend.h cleanup
V4L/DVB (9178): cx24116: Add module parameter to return SNR as ESNO.
V4L/DVB (9177): S2API: Change _8PSK / _16APSK to PSK_8 and APSK_16
V4L/DVB (9176): Add support for DvbWorld USB cards with STV0288 demodulator.
V4L/DVB (9175): Remove NULL pointer in stb6000 driver.
V4L/DVB (9174): Allow custom inittab for ST STV0288 demodulator.
V4L/DVB (9173): S2API: Remove the hardcoded command limit during validation
V4L/DVB (9172): S2API: Bugfix related to DVB-S / DVB-S2 tuning for the legacy API.
V4L/DVB (9171): S2API: Stop an OOPS if illegal commands are dumped in S2API.
V4L/DVB (9170): cx24116: Sanity checking to data input via S2API to the cx24116 demod.
V4L/DVB (9169): uvcvideo: Support two new Bison Electronics webcams.
V4L/DVB (9168): Add support for MSI TV@nywhere Plus remote
V4L/DVB: v4l2-dev: remove duplicated #include
...
377 files changed, 29913 insertions, 6866 deletions
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index f32efb6fb12c..60ba66836038 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv | |||
| @@ -150,3 +150,4 @@ | |||
| 150 | 149 -> Typhoon TV-Tuner PCI (50684) | 150 | 149 -> Typhoon TV-Tuner PCI (50684) |
| 151 | 150 -> Geovision GV-600 [008a:763c] | 151 | 150 -> Geovision GV-600 [008a:763c] |
| 152 | 151 -> Kozumi KTV-01C | 152 | 151 -> Kozumi KTV-01C |
| 153 | 152 -> Encore ENL TV-FM-2 [1000:1801] | ||
diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index f0e613ba55b8..64823ccacd69 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 | |||
| @@ -9,3 +9,5 @@ | |||
| 9 | 8 -> Hauppauge WinTV-HVR1700 [0070:8101] | 9 | 8 -> Hauppauge WinTV-HVR1700 [0070:8101] |
| 10 | 9 -> Hauppauge WinTV-HVR1400 [0070:8010] | 10 | 9 -> Hauppauge WinTV-HVR1400 [0070:8010] |
| 11 | 10 -> DViCO FusionHDTV7 Dual Express [18ac:d618] | 11 | 10 -> DViCO FusionHDTV7 Dual Express [18ac:d618] |
| 12 | 11 -> DViCO FusionHDTV DVB-T Dual Express [18ac:db78] | ||
| 13 | 12 -> Leadtek Winfast PxDVR3200 H [107d:6681] | ||
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 7cf5685d3645..a5227e308f4a 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 | |||
| @@ -66,3 +66,11 @@ | |||
| 66 | 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] | 66 | 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] |
| 67 | 66 -> Prolink Pixelview MPEG 8000GT [1554:4935] | 67 | 66 -> Prolink Pixelview MPEG 8000GT [1554:4935] |
| 68 | 67 -> Kworld PlusTV HD PCI 120 (ATSC 120) [17de:08c1] | 68 | 67 -> Kworld PlusTV HD PCI 120 (ATSC 120) [17de:08c1] |
| 69 | 68 -> Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid [0070:6900,0070:6904,0070:6902] | ||
| 70 | 69 -> Hauppauge WinTV-HVR4000(Lite) DVB-S/S2 [0070:6905,0070:6906] | ||
| 71 | 70 -> TeVii S460 DVB-S/S2 [d460:9022] | ||
| 72 | 71 -> Omicom SS4 DVB-S/S2 PCI [A044:2011] | ||
| 73 | 72 -> TBS 8920 DVB-S/S2 [8920:8888] | ||
| 74 | 73 -> TeVii S420 DVB-S [d420:9022] | ||
| 75 | 74 -> Prolink Pixelview Global Extreme [1554:4976] | ||
| 76 | 75 -> PROF 7300 DVB-S/S2 [B033:3033] | ||
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 53449cb99b17..187cc48d0924 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] | 1 | 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] |
| 2 | 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883] | 2 | 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2820,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883] |
| 3 | 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] | 3 | 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] |
| 4 | 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] | 4 | 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] |
| 5 | 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] | 5 | 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] |
| @@ -12,7 +12,7 @@ | |||
| 12 | 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] | 12 | 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] |
| 13 | 12 -> Kworld PVR TV 2800 RF (em2820/em2840) | 13 | 12 -> Kworld PVR TV 2800 RF (em2820/em2840) |
| 14 | 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] | 14 | 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] |
| 15 | 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) | 15 | 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) [eb1a:2821] |
| 16 | 15 -> V-Gear PocketTV (em2800) | 16 | 15 -> V-Gear PocketTV (em2800) |
| 17 | 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b,2040:651f] | 17 | 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b,2040:651f] |
| 18 | 17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227] | 18 | 17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227] |
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 39868af9cf9f..dc67eef38ff9 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 | |||
| @@ -76,7 +76,7 @@ | |||
| 76 | 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] | 76 | 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] |
| 77 | 76 -> SKNet MonsterTV Mobile [1131:4ee9] | 77 | 76 -> SKNet MonsterTV Mobile [1131:4ee9] |
| 78 | 77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e] | 78 | 77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e] |
| 79 | 78 -> ASUSTeK P7131 Dual [1043:4862,1043:4857] | 79 | 78 -> ASUSTeK P7131 Dual [1043:4862] |
| 80 | 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) | 80 | 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) |
| 81 | 80 -> ASUS Digimatrix TV [1043:0210] | 81 | 80 -> ASUS Digimatrix TV [1043:0210] |
| 82 | 81 -> Philips Tiger reference design [1131:2018] | 82 | 81 -> Philips Tiger reference design [1131:2018] |
| @@ -145,3 +145,9 @@ | |||
| 145 | 144 -> Beholder BeholdTV M6 Extra [5ace:6193] | 145 | 144 -> Beholder BeholdTV M6 Extra [5ace:6193] |
| 146 | 145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636] | 146 | 145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636] |
| 147 | 146 -> ASUSTeK P7131 Analog | 147 | 146 -> ASUSTeK P7131 Analog |
| 148 | 147 -> Asus Tiger 3in1 [1043:4878] | ||
| 149 | 148 -> Encore ENLTV-FM v5.3 [1a7f:2008] | ||
| 150 | 149 -> Avermedia PCI pure analog (M135A) [1461:f11d] | ||
| 151 | 150 -> Zogis Real Angel 220 | ||
| 152 | 151 -> ADS Tech Instant HDTV [1421:0380] | ||
| 153 | 152 -> Asus Tiger Rev:1.00 [1043:4857] | ||
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 0e2394695bb8..30bbdda68d03 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner | |||
| @@ -74,3 +74,4 @@ tuner=72 - Thomson FE6600 | |||
| 74 | tuner=73 - Samsung TCPG 6121P30A | 74 | tuner=73 - Samsung TCPG 6121P30A |
| 75 | tuner=75 - Philips TEA5761 FM Radio | 75 | tuner=75 - Philips TEA5761 FM Radio |
| 76 | tuner=76 - Xceive 5000 tuner | 76 | tuner=76 - Xceive 5000 tuner |
| 77 | tuner=77 - TCL tuner MF02GIP-5N-E | ||
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 9a3e4d797fa8..004818fab040 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt | |||
| @@ -7,6 +7,7 @@ The modules are: | |||
| 7 | xxxx vend:prod | 7 | xxxx vend:prod |
| 8 | ---- | 8 | ---- |
| 9 | spca501 0000:0000 MystFromOri Unknow Camera | 9 | spca501 0000:0000 MystFromOri Unknow Camera |
| 10 | m5602 0402:5602 ALi Video Camera Controller | ||
| 10 | spca501 040a:0002 Kodak DVC-325 | 11 | spca501 040a:0002 Kodak DVC-325 |
| 11 | spca500 040a:0300 Kodak EZ200 | 12 | spca500 040a:0300 Kodak EZ200 |
| 12 | zc3xx 041e:041e Creative WebCam Live! | 13 | zc3xx 041e:041e Creative WebCam Live! |
| @@ -42,6 +43,7 @@ zc3xx 0458:7007 Genius VideoCam V2 | |||
| 42 | zc3xx 0458:700c Genius VideoCam V3 | 43 | zc3xx 0458:700c Genius VideoCam V3 |
| 43 | zc3xx 0458:700f Genius VideoCam Web V2 | 44 | zc3xx 0458:700f Genius VideoCam Web V2 |
| 44 | sonixj 0458:7025 Genius Eye 311Q | 45 | sonixj 0458:7025 Genius Eye 311Q |
| 46 | sonixj 0458:702e Genius Slim 310 NB | ||
| 45 | sonixj 045e:00f5 MicroSoft VX3000 | 47 | sonixj 045e:00f5 MicroSoft VX3000 |
| 46 | sonixj 045e:00f7 MicroSoft VX1000 | 48 | sonixj 045e:00f7 MicroSoft VX1000 |
| 47 | ov519 045e:028c Micro$oft xbox cam | 49 | ov519 045e:028c Micro$oft xbox cam |
| @@ -81,7 +83,7 @@ spca561 046d:092b Labtec Webcam Plus | |||
| 81 | spca561 046d:092c Logitech QC chat Elch2 | 83 | spca561 046d:092c Logitech QC chat Elch2 |
| 82 | spca561 046d:092d Logitech QC Elch2 | 84 | spca561 046d:092d Logitech QC Elch2 |
| 83 | spca561 046d:092e Logitech QC Elch2 | 85 | spca561 046d:092e Logitech QC Elch2 |
| 84 | spca561 046d:092f Logitech QC Elch2 | 86 | spca561 046d:092f Logitech QuickCam Express Plus |
| 85 | sunplus 046d:0960 Logitech ClickSmart 420 | 87 | sunplus 046d:0960 Logitech ClickSmart 420 |
| 86 | sunplus 0471:0322 Philips DMVC1300K | 88 | sunplus 0471:0322 Philips DMVC1300K |
| 87 | zc3xx 0471:0325 Philips SPC 200 NC | 89 | zc3xx 0471:0325 Philips SPC 200 NC |
| @@ -96,6 +98,29 @@ sunplus 04a5:3003 Benq DC 1300 | |||
| 96 | sunplus 04a5:3008 Benq DC 1500 | 98 | sunplus 04a5:3008 Benq DC 1500 |
| 97 | sunplus 04a5:300a Benq DC 3410 | 99 | sunplus 04a5:300a Benq DC 3410 |
| 98 | spca500 04a5:300c Benq DC 1016 | 100 | spca500 04a5:300c Benq DC 1016 |
| 101 | finepix 04cb:0104 Fujifilm FinePix 4800 | ||
| 102 | finepix 04cb:0109 Fujifilm FinePix A202 | ||
| 103 | finepix 04cb:010b Fujifilm FinePix A203 | ||
| 104 | finepix 04cb:010f Fujifilm FinePix A204 | ||
| 105 | finepix 04cb:0111 Fujifilm FinePix A205 | ||
| 106 | finepix 04cb:0113 Fujifilm FinePix A210 | ||
| 107 | finepix 04cb:0115 Fujifilm FinePix A303 | ||
| 108 | finepix 04cb:0117 Fujifilm FinePix A310 | ||
| 109 | finepix 04cb:0119 Fujifilm FinePix F401 | ||
| 110 | finepix 04cb:011b Fujifilm FinePix F402 | ||
| 111 | finepix 04cb:011d Fujifilm FinePix F410 | ||
| 112 | finepix 04cb:0121 Fujifilm FinePix F601 | ||
| 113 | finepix 04cb:0123 Fujifilm FinePix F700 | ||
| 114 | finepix 04cb:0125 Fujifilm FinePix M603 | ||
| 115 | finepix 04cb:0127 Fujifilm FinePix S300 | ||
| 116 | finepix 04cb:0129 Fujifilm FinePix S304 | ||
| 117 | finepix 04cb:012b Fujifilm FinePix S500 | ||
| 118 | finepix 04cb:012d Fujifilm FinePix S602 | ||
| 119 | finepix 04cb:012f Fujifilm FinePix S700 | ||
| 120 | finepix 04cb:0131 Fujifilm FinePix unknown model | ||
| 121 | finepix 04cb:013b Fujifilm FinePix unknown model | ||
| 122 | finepix 04cb:013d Fujifilm FinePix unknown model | ||
| 123 | finepix 04cb:013f Fujifilm FinePix F420 | ||
| 99 | sunplus 04f1:1001 JVC GC A50 | 124 | sunplus 04f1:1001 JVC GC A50 |
| 100 | spca561 04fc:0561 Flexcam 100 | 125 | spca561 04fc:0561 Flexcam 100 |
| 101 | sunplus 04fc:500c Sunplus CA500C | 126 | sunplus 04fc:500c Sunplus CA500C |
| @@ -181,6 +206,7 @@ pac207 093a:2468 PAC207 | |||
| 181 | pac207 093a:2470 Genius GF112 | 206 | pac207 093a:2470 Genius GF112 |
| 182 | pac207 093a:2471 Genius VideoCam ge111 | 207 | pac207 093a:2471 Genius VideoCam ge111 |
| 183 | pac207 093a:2472 Genius VideoCam ge110 | 208 | pac207 093a:2472 Genius VideoCam ge110 |
| 209 | pac207 093a:2476 Genius e-Messenger 112 | ||
| 184 | pac7311 093a:2600 PAC7311 Typhoon | 210 | pac7311 093a:2600 PAC7311 Typhoon |
| 185 | pac7311 093a:2601 Philips SPC 610 NC | 211 | pac7311 093a:2601 Philips SPC 610 NC |
| 186 | pac7311 093a:2603 PAC7312 | 212 | pac7311 093a:2603 PAC7312 |
diff --git a/Documentation/video4linux/m5602.txt b/Documentation/video4linux/m5602.txt new file mode 100644 index 000000000000..4450ab13f37b --- /dev/null +++ b/Documentation/video4linux/m5602.txt | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | This document describes the ALi m5602 bridge connected | ||
| 2 | to the following supported sensors: | ||
| 3 | OmniVision OV9650, | ||
| 4 | Samsung s5k83a, | ||
| 5 | Samsung s5k4aa, | ||
| 6 | Micron mt9m111, | ||
| 7 | Pixel plus PO1030 | ||
| 8 | |||
| 9 | This driver mimics the windows drivers, which have a braindead implementation sending bayer-encoded frames at VGA resolution. | ||
| 10 | In a perfect world we should be able to reprogram the m5602 and the connected sensor in hardware instead, supporting a range of resolutions and pixelformats | ||
| 11 | |||
| 12 | Anyway, have fun and please report any bugs to m560x-driver-devel@lists.sourceforge.net | ||
diff --git a/Documentation/video4linux/soc-camera.txt b/Documentation/video4linux/soc-camera.txt new file mode 100644 index 000000000000..178ef3c5e579 --- /dev/null +++ b/Documentation/video4linux/soc-camera.txt | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | Soc-Camera Subsystem | ||
| 2 | ==================== | ||
| 3 | |||
| 4 | Terminology | ||
| 5 | ----------- | ||
| 6 | |||
| 7 | The following terms are used in this document: | ||
| 8 | - camera / camera device / camera sensor - a video-camera sensor chip, capable | ||
| 9 | of connecting to a variety of systems and interfaces, typically uses i2c for | ||
| 10 | control and configuration, and a parallel or a serial bus for data. | ||
| 11 | - camera host - an interface, to which a camera is connected. Typically a | ||
| 12 | specialised interface, present on many SoCs, e.g., PXA27x and PXA3xx, SuperH, | ||
| 13 | AVR32, i.MX27, i.MX31. | ||
| 14 | - camera host bus - a connection between a camera host and a camera. Can be | ||
| 15 | parallel or serial, consists of data and control lines, e.g., clock, vertical | ||
| 16 | and horizontal synchronization signals. | ||
| 17 | |||
| 18 | Purpose of the soc-camera subsystem | ||
| 19 | ----------------------------------- | ||
| 20 | |||
| 21 | The soc-camera subsystem provides a unified API between camera host drivers and | ||
| 22 | camera sensor drivers. It implements a V4L2 interface to the user, currently | ||
| 23 | only the mmap method is supported. | ||
| 24 | |||
| 25 | This subsystem has been written to connect drivers for System-on-Chip (SoC) | ||
| 26 | video capture interfaces with drivers for CMOS camera sensor chips to enable | ||
| 27 | the reuse of sensor drivers with various hosts. The subsystem has been designed | ||
| 28 | to support multiple camera host interfaces and multiple cameras per interface, | ||
| 29 | although most applications have only one camera sensor. | ||
| 30 | |||
| 31 | Existing drivers | ||
| 32 | ---------------- | ||
| 33 | |||
| 34 | As of 2.6.27-rc4 there are two host drivers in the mainline: pxa_camera.c for | ||
| 35 | PXA27x SoCs and sh_mobile_ceu_camera.c for SuperH SoCs, and four sensor drivers: | ||
| 36 | mt9m001.c, mt9m111.c, mt9v022.c and a generic soc_camera_platform.c driver. This | ||
| 37 | list is not supposed to be updated, look for more examples in your tree. | ||
| 38 | |||
| 39 | Camera host API | ||
| 40 | --------------- | ||
| 41 | |||
| 42 | A host camera driver is registered using the | ||
| 43 | |||
| 44 | soc_camera_host_register(struct soc_camera_host *); | ||
| 45 | |||
| 46 | function. The host object can be initialized as follows: | ||
| 47 | |||
| 48 | static struct soc_camera_host pxa_soc_camera_host = { | ||
| 49 | .drv_name = PXA_CAM_DRV_NAME, | ||
| 50 | .ops = &pxa_soc_camera_host_ops, | ||
| 51 | }; | ||
| 52 | |||
| 53 | All camera host methods are passed in a struct soc_camera_host_ops: | ||
| 54 | |||
| 55 | static struct soc_camera_host_ops pxa_soc_camera_host_ops = { | ||
| 56 | .owner = THIS_MODULE, | ||
| 57 | .add = pxa_camera_add_device, | ||
| 58 | .remove = pxa_camera_remove_device, | ||
| 59 | .suspend = pxa_camera_suspend, | ||
| 60 | .resume = pxa_camera_resume, | ||
| 61 | .set_fmt_cap = pxa_camera_set_fmt_cap, | ||
| 62 | .try_fmt_cap = pxa_camera_try_fmt_cap, | ||
| 63 | .init_videobuf = pxa_camera_init_videobuf, | ||
| 64 | .reqbufs = pxa_camera_reqbufs, | ||
| 65 | .poll = pxa_camera_poll, | ||
| 66 | .querycap = pxa_camera_querycap, | ||
| 67 | .try_bus_param = pxa_camera_try_bus_param, | ||
| 68 | .set_bus_param = pxa_camera_set_bus_param, | ||
| 69 | }; | ||
| 70 | |||
| 71 | .add and .remove methods are called when a sensor is attached to or detached | ||
| 72 | from the host, apart from performing host-internal tasks they shall also call | ||
| 73 | sensor driver's .init and .release methods respectively. .suspend and .resume | ||
| 74 | methods implement host's power-management functionality and its their | ||
| 75 | responsibility to call respective sensor's methods. .try_bus_param and | ||
| 76 | .set_bus_param are used to negotiate physical connection parameters between the | ||
| 77 | host and the sensor. .init_videobuf is called by soc-camera core when a | ||
| 78 | video-device is opened, further video-buffer management is implemented completely | ||
| 79 | by the specific camera host driver. The rest of the methods are called from | ||
| 80 | respective V4L2 operations. | ||
| 81 | |||
| 82 | Camera API | ||
| 83 | ---------- | ||
| 84 | |||
| 85 | Sensor drivers can use struct soc_camera_link, typically provided by the | ||
| 86 | platform, and used to specify to which camera host bus the sensor is connected, | ||
| 87 | and arbitrarily provide platform .power and .reset methods for the camera. | ||
| 88 | soc_camera_device_register() and soc_camera_device_unregister() functions are | ||
| 89 | used to add a sensor driver to or remove one from the system. The registration | ||
| 90 | function takes a pointer to struct soc_camera_device as the only parameter. | ||
| 91 | This struct can be initialized as follows: | ||
| 92 | |||
| 93 | /* link to driver operations */ | ||
| 94 | icd->ops = &mt9m001_ops; | ||
| 95 | /* link to the underlying physical (e.g., i2c) device */ | ||
| 96 | icd->control = &client->dev; | ||
| 97 | /* window geometry */ | ||
| 98 | icd->x_min = 20; | ||
| 99 | icd->y_min = 12; | ||
| 100 | icd->x_current = 20; | ||
| 101 | icd->y_current = 12; | ||
| 102 | icd->width_min = 48; | ||
| 103 | icd->width_max = 1280; | ||
| 104 | icd->height_min = 32; | ||
| 105 | icd->height_max = 1024; | ||
| 106 | icd->y_skip_top = 1; | ||
| 107 | /* camera bus ID, typically obtained from platform data */ | ||
| 108 | icd->iface = icl->bus_id; | ||
| 109 | |||
| 110 | struct soc_camera_ops provides .probe and .remove methods, which are called by | ||
| 111 | the soc-camera core, when a camera is matched against or removed from a camera | ||
| 112 | host bus, .init, .release, .suspend, and .resume are called from the camera host | ||
| 113 | driver as discussed above. Other members of this struct provide respective V4L2 | ||
| 114 | functionality. | ||
| 115 | |||
| 116 | struct soc_camera_device also links to an array of struct soc_camera_data_format, | ||
| 117 | listing pixel formats, supported by the camera. | ||
| 118 | |||
| 119 | -- | ||
| 120 | Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
diff --git a/arch/arm/mach-pxa/include/mach/camera.h b/arch/arm/mach-pxa/include/mach/camera.h index 39516ced8b1f..31abe6d514b8 100644 --- a/arch/arm/mach-pxa/include/mach/camera.h +++ b/arch/arm/mach-pxa/include/mach/camera.h | |||
| @@ -36,8 +36,6 @@ | |||
| 36 | 36 | ||
| 37 | struct pxacamera_platform_data { | 37 | struct pxacamera_platform_data { |
| 38 | int (*init)(struct device *); | 38 | int (*init)(struct device *); |
| 39 | int (*power)(struct device *, int); | ||
| 40 | int (*reset)(struct device *, int); | ||
| 41 | 39 | ||
| 42 | unsigned long flags; | 40 | unsigned long flags; |
| 43 | unsigned long mclk_10khz; | 41 | unsigned long mclk_10khz; |
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 8fa91f846d59..4952aeb5dd80 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c | |||
| @@ -103,6 +103,56 @@ IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = { | |||
| 103 | 103 | ||
| 104 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); | 104 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); |
| 105 | 105 | ||
| 106 | /* Mauro Carvalho Chehab <mchehab@infradead.org> */ | ||
| 107 | IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = { | ||
| 108 | [0x00] = KEY_POWER2, | ||
| 109 | [0x2e] = KEY_DOT, /* '.' */ | ||
| 110 | [0x01] = KEY_MODE, /* TV/FM */ | ||
| 111 | |||
| 112 | [0x05] = KEY_1, | ||
| 113 | [0x06] = KEY_2, | ||
| 114 | [0x07] = KEY_3, | ||
| 115 | [0x09] = KEY_4, | ||
| 116 | [0x0a] = KEY_5, | ||
| 117 | [0x0b] = KEY_6, | ||
| 118 | [0x0d] = KEY_7, | ||
| 119 | [0x0e] = KEY_8, | ||
| 120 | [0x0f] = KEY_9, | ||
| 121 | [0x11] = KEY_0, | ||
| 122 | |||
| 123 | [0x13] = KEY_RIGHT, /* -> */ | ||
| 124 | [0x12] = KEY_LEFT, /* <- */ | ||
| 125 | |||
| 126 | [0x17] = KEY_SLEEP, /* Capturar Imagem */ | ||
| 127 | [0x10] = KEY_SHUFFLE, /* Amostra */ | ||
| 128 | |||
| 129 | /* FIXME: The keys bellow aren't ok */ | ||
| 130 | |||
| 131 | [0x43] = KEY_CHANNELUP, | ||
| 132 | [0x42] = KEY_CHANNELDOWN, | ||
| 133 | [0x1f] = KEY_VOLUMEUP, | ||
| 134 | [0x1e] = KEY_VOLUMEDOWN, | ||
| 135 | [0x0c] = KEY_ENTER, | ||
| 136 | |||
| 137 | [0x14] = KEY_MUTE, | ||
| 138 | [0x08] = KEY_AUDIO, | ||
| 139 | |||
| 140 | [0x03] = KEY_TEXT, | ||
| 141 | [0x04] = KEY_EPG, | ||
| 142 | [0x2b] = KEY_TV2, /* TV2 */ | ||
| 143 | |||
| 144 | [0x1d] = KEY_RED, | ||
| 145 | [0x1c] = KEY_YELLOW, | ||
| 146 | [0x41] = KEY_GREEN, | ||
| 147 | [0x40] = KEY_BLUE, | ||
| 148 | |||
| 149 | [0x1a] = KEY_PLAYPAUSE, | ||
| 150 | [0x19] = KEY_RECORD, | ||
| 151 | [0x18] = KEY_PLAY, | ||
| 152 | [0x1b] = KEY_STOP, | ||
| 153 | }; | ||
| 154 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a); | ||
| 155 | |||
| 106 | /* Attila Kondoros <attila.kondoros@chello.hu> */ | 156 | /* Attila Kondoros <attila.kondoros@chello.hu> */ |
| 107 | IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { | 157 | IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { |
| 108 | 158 | ||
| @@ -467,7 +517,8 @@ EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); | |||
| 467 | 517 | ||
| 468 | /* ---------------------------------------------------------------------- */ | 518 | /* ---------------------------------------------------------------------- */ |
| 469 | 519 | ||
| 470 | /* MSI TV@nywhere remote */ | 520 | /* MSI TV@nywhere MASTER remote */ |
| 521 | |||
| 471 | IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { | 522 | IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { |
| 472 | /* Keys 0 to 9 */ | 523 | /* Keys 0 to 9 */ |
| 473 | [ 0x00 ] = KEY_0, | 524 | [ 0x00 ] = KEY_0, |
| @@ -501,6 +552,95 @@ EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere); | |||
| 501 | 552 | ||
| 502 | /* ---------------------------------------------------------------------- */ | 553 | /* ---------------------------------------------------------------------- */ |
| 503 | 554 | ||
| 555 | /* | ||
| 556 | Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card | ||
| 557 | is marked "KS003". The controller is I2C at address 0x30, but does not seem | ||
| 558 | to respond to probes until a read is performed from a valid device. | ||
| 559 | I don't know why... | ||
| 560 | |||
| 561 | Note: This remote may be of similar or identical design to the | ||
| 562 | Pixelview remote (?). The raw codes and duplicate button codes | ||
| 563 | appear to be the same. | ||
| 564 | |||
| 565 | Henry Wong <henry@stuffedcow.net> | ||
| 566 | Some changes to formatting and keycodes by Mark Schultz <n9xmj@yahoo.com> | ||
| 567 | |||
| 568 | */ | ||
| 569 | |||
| 570 | IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = { | ||
| 571 | |||
| 572 | /* ---- Remote Button Layout ---- | ||
| 573 | |||
| 574 | POWER SOURCE SCAN MUTE | ||
| 575 | TV/FM 1 2 3 | ||
| 576 | |> 4 5 6 | ||
| 577 | <| 7 8 9 | ||
| 578 | ^^UP 0 + RECALL | ||
| 579 | vvDN RECORD STOP PLAY | ||
| 580 | |||
| 581 | MINIMIZE ZOOM | ||
| 582 | |||
| 583 | CH+ | ||
| 584 | VOL- VOL+ | ||
| 585 | CH- | ||
| 586 | |||
| 587 | SNAPSHOT MTS | ||
| 588 | |||
| 589 | << FUNC >> RESET | ||
| 590 | */ | ||
| 591 | |||
| 592 | [0x01] = KEY_KP1, /* 1 */ | ||
| 593 | [0x0b] = KEY_KP2, /* 2 */ | ||
| 594 | [0x1b] = KEY_KP3, /* 3 */ | ||
| 595 | [0x05] = KEY_KP4, /* 4 */ | ||
| 596 | [0x09] = KEY_KP5, /* 5 */ | ||
| 597 | [0x15] = KEY_KP6, /* 6 */ | ||
| 598 | [0x06] = KEY_KP7, /* 7 */ | ||
| 599 | [0x0a] = KEY_KP8, /* 8 */ | ||
| 600 | [0x12] = KEY_KP9, /* 9 */ | ||
| 601 | [0x02] = KEY_KP0, /* 0 */ | ||
| 602 | [0x10] = KEY_KPPLUS, /* + */ | ||
| 603 | [0x13] = KEY_AGAIN, /* Recall */ | ||
| 604 | |||
| 605 | [0x1e] = KEY_POWER, /* Power */ | ||
| 606 | [0x07] = KEY_TUNER, /* Source */ | ||
| 607 | [0x1c] = KEY_SEARCH, /* Scan */ | ||
| 608 | [0x18] = KEY_MUTE, /* Mute */ | ||
| 609 | |||
| 610 | [0x03] = KEY_RADIO, /* TV/FM */ | ||
| 611 | /* The next four keys are duplicates that appear to send the | ||
| 612 | same IR code as Ch+, Ch-, >>, and << . The raw code assigned | ||
| 613 | to them is the actual code + 0x20 - they will never be | ||
| 614 | detected as such unless some way is discovered to distinguish | ||
| 615 | these buttons from those that have the same code. */ | ||
| 616 | [0x3f] = KEY_RIGHT, /* |> and Ch+ */ | ||
| 617 | [0x37] = KEY_LEFT, /* <| and Ch- */ | ||
| 618 | [0x2c] = KEY_UP, /* ^^Up and >> */ | ||
| 619 | [0x24] = KEY_DOWN, /* vvDn and << */ | ||
| 620 | |||
| 621 | [0x00] = KEY_RECORD, /* Record */ | ||
| 622 | [0x08] = KEY_STOP, /* Stop */ | ||
| 623 | [0x11] = KEY_PLAY, /* Play */ | ||
| 624 | |||
| 625 | [0x0f] = KEY_CLOSE, /* Minimize */ | ||
| 626 | [0x19] = KEY_ZOOM, /* Zoom */ | ||
| 627 | [0x1a] = KEY_SHUFFLE, /* Snapshot */ | ||
| 628 | [0x0d] = KEY_LANGUAGE, /* MTS */ | ||
| 629 | |||
| 630 | [0x14] = KEY_VOLUMEDOWN, /* Vol- */ | ||
| 631 | [0x16] = KEY_VOLUMEUP, /* Vol+ */ | ||
| 632 | [0x17] = KEY_CHANNELDOWN, /* Ch- */ | ||
| 633 | [0x1f] = KEY_CHANNELUP, /* Ch+ */ | ||
| 634 | |||
| 635 | [0x04] = KEY_REWIND, /* << */ | ||
| 636 | [0x0e] = KEY_MENU, /* Function */ | ||
| 637 | [0x0c] = KEY_FASTFORWARD, /* >> */ | ||
| 638 | [0x1d] = KEY_RESTART, /* Reset */ | ||
| 639 | }; | ||
| 640 | EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus); | ||
| 641 | |||
| 642 | /* ---------------------------------------------------------------------- */ | ||
| 643 | |||
| 504 | /* Cinergy 1400 DVB-T */ | 644 | /* Cinergy 1400 DVB-T */ |
| 505 | IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { | 645 | IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { |
| 506 | [ 0x01 ] = KEY_POWER, | 646 | [ 0x01 ] = KEY_POWER, |
| @@ -1792,12 +1932,61 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { | |||
| 1792 | [ 0x41 ] = KEY_GREEN, /* AP2 */ | 1932 | [ 0x41 ] = KEY_GREEN, /* AP2 */ |
| 1793 | [ 0x47 ] = KEY_YELLOW, /* AP3 */ | 1933 | [ 0x47 ] = KEY_YELLOW, /* AP3 */ |
| 1794 | [ 0x57 ] = KEY_BLUE, /* AP4 */ | 1934 | [ 0x57 ] = KEY_BLUE, /* AP4 */ |
| 1795 | |||
| 1796 | |||
| 1797 | }; | 1935 | }; |
| 1798 | |||
| 1799 | EXPORT_SYMBOL_GPL(ir_codes_encore_enltv); | 1936 | EXPORT_SYMBOL_GPL(ir_codes_encore_enltv); |
| 1800 | 1937 | ||
| 1938 | /* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton | ||
| 1939 | Mauro Carvalho Chehab <mchehab@infradead.org> */ | ||
| 1940 | IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE] = { | ||
| 1941 | [0x4c] = KEY_POWER2, | ||
| 1942 | [0x4a] = KEY_TUNER, | ||
| 1943 | [0x40] = KEY_1, | ||
| 1944 | [0x60] = KEY_2, | ||
| 1945 | [0x50] = KEY_3, | ||
| 1946 | [0x70] = KEY_4, | ||
| 1947 | [0x48] = KEY_5, | ||
| 1948 | [0x68] = KEY_6, | ||
| 1949 | [0x58] = KEY_7, | ||
| 1950 | [0x78] = KEY_8, | ||
| 1951 | [0x44] = KEY_9, | ||
| 1952 | [0x54] = KEY_0, | ||
| 1953 | |||
| 1954 | [0x64] = KEY_LAST, /* +100 */ | ||
| 1955 | [0x4e] = KEY_AGAIN, /* Recall */ | ||
| 1956 | |||
| 1957 | [0x6c] = KEY_SWITCHVIDEOMODE, /* Video Source */ | ||
| 1958 | [0x5e] = KEY_MENU, | ||
| 1959 | [0x56] = KEY_SCREEN, | ||
| 1960 | [0x7a] = KEY_SETUP, | ||
| 1961 | |||
| 1962 | [0x46] = KEY_MUTE, | ||
| 1963 | [0x5c] = KEY_MODE, /* Stereo */ | ||
| 1964 | [0x74] = KEY_INFO, | ||
| 1965 | [0x7c] = KEY_CLEAR, | ||
| 1966 | |||
| 1967 | [0x55] = KEY_UP, | ||
| 1968 | [0x49] = KEY_DOWN, | ||
| 1969 | [0x7e] = KEY_LEFT, | ||
| 1970 | [0x59] = KEY_RIGHT, | ||
| 1971 | [0x6a] = KEY_ENTER, | ||
| 1972 | |||
| 1973 | [0x42] = KEY_VOLUMEUP, | ||
| 1974 | [0x62] = KEY_VOLUMEDOWN, | ||
| 1975 | [0x52] = KEY_CHANNELUP, | ||
| 1976 | [0x72] = KEY_CHANNELDOWN, | ||
| 1977 | |||
| 1978 | [0x41] = KEY_RECORD, | ||
| 1979 | [0x51] = KEY_SHUFFLE, /* Snapshot */ | ||
| 1980 | [0x75] = KEY_TIME, /* Timeshift */ | ||
| 1981 | [0x71] = KEY_TV2, /* PIP */ | ||
| 1982 | |||
| 1983 | [0x45] = KEY_REWIND, | ||
| 1984 | [0x6f] = KEY_PAUSE, | ||
| 1985 | [0x7d] = KEY_FORWARD, | ||
| 1986 | [0x79] = KEY_STOP, | ||
| 1987 | }; | ||
| 1988 | EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2); | ||
| 1989 | |||
| 1801 | /* for the Technotrend 1500 bundled remotes (grey and black): */ | 1990 | /* for the Technotrend 1500 bundled remotes (grey and black): */ |
| 1802 | IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { | 1991 | IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { |
| 1803 | [ 0x01 ] = KEY_POWER, | 1992 | [ 0x01 ] = KEY_POWER, |
| @@ -2239,3 +2428,86 @@ IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = { | |||
| 2239 | [0x2a] = KEY_MENU, | 2428 | [0x2a] = KEY_MENU, |
| 2240 | }; | 2429 | }; |
| 2241 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d); | 2430 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d); |
| 2431 | |||
| 2432 | /* Encore ENLTV-FM v5.3 | ||
| 2433 | Mauro Carvalho Chehab <mchehab@infradead.org> | ||
| 2434 | */ | ||
| 2435 | IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = { | ||
| 2436 | [0x10] = KEY_POWER2, | ||
| 2437 | [0x06] = KEY_MUTE, | ||
| 2438 | |||
| 2439 | [0x09] = KEY_1, | ||
| 2440 | [0x1d] = KEY_2, | ||
| 2441 | [0x1f] = KEY_3, | ||
| 2442 | [0x19] = KEY_4, | ||
| 2443 | [0x1b] = KEY_5, | ||
| 2444 | [0x11] = KEY_6, | ||
| 2445 | [0x17] = KEY_7, | ||
| 2446 | [0x12] = KEY_8, | ||
| 2447 | [0x16] = KEY_9, | ||
| 2448 | [0x48] = KEY_0, | ||
| 2449 | |||
| 2450 | [0x04] = KEY_LIST, /* -/-- */ | ||
| 2451 | [0x40] = KEY_LAST, /* recall */ | ||
| 2452 | |||
| 2453 | [0x02] = KEY_MODE, /* TV/AV */ | ||
| 2454 | [0x05] = KEY_SHUFFLE, /* SNAPSHOT */ | ||
| 2455 | |||
| 2456 | [0x4c] = KEY_CHANNELUP, /* UP */ | ||
| 2457 | [0x00] = KEY_CHANNELDOWN, /* DOWN */ | ||
| 2458 | [0x0d] = KEY_VOLUMEUP, /* RIGHT */ | ||
| 2459 | [0x15] = KEY_VOLUMEDOWN, /* LEFT */ | ||
| 2460 | [0x49] = KEY_ENTER, /* OK */ | ||
| 2461 | |||
| 2462 | [0x54] = KEY_RECORD, | ||
| 2463 | [0x4d] = KEY_PLAY, /* pause */ | ||
| 2464 | |||
| 2465 | [0x1e] = KEY_UP, /* video setting */ | ||
| 2466 | [0x0e] = KEY_RIGHT, /* <- */ | ||
| 2467 | [0x1a] = KEY_LEFT, /* -> */ | ||
| 2468 | |||
| 2469 | [0x0a] = KEY_DOWN, /* video default */ | ||
| 2470 | [0x0c] = KEY_ZOOM, /* hide pannel */ | ||
| 2471 | [0x47] = KEY_SLEEP, /* shutdown */ | ||
| 2472 | }; | ||
| 2473 | EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53); | ||
| 2474 | |||
| 2475 | /* Zogis Real Audio 220 - 32 keys IR */ | ||
| 2476 | IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = { | ||
| 2477 | [0x1c] = KEY_RADIO, | ||
| 2478 | [0x12] = KEY_POWER2, | ||
| 2479 | |||
| 2480 | [0x01] = KEY_1, | ||
| 2481 | [0x02] = KEY_2, | ||
| 2482 | [0x03] = KEY_3, | ||
| 2483 | [0x04] = KEY_4, | ||
| 2484 | [0x05] = KEY_5, | ||
| 2485 | [0x06] = KEY_6, | ||
| 2486 | [0x07] = KEY_7, | ||
| 2487 | [0x08] = KEY_8, | ||
| 2488 | [0x09] = KEY_9, | ||
| 2489 | [0x00] = KEY_0, | ||
| 2490 | |||
| 2491 | [0x0c] = KEY_VOLUMEUP, | ||
| 2492 | [0x18] = KEY_VOLUMEDOWN, | ||
| 2493 | [0x0b] = KEY_CHANNELUP, | ||
| 2494 | [0x15] = KEY_CHANNELDOWN, | ||
| 2495 | [0x16] = KEY_ENTER, | ||
| 2496 | |||
| 2497 | [0x11] = KEY_LIST, /* Source */ | ||
| 2498 | [0x0d] = KEY_AUDIO, /* stereo */ | ||
| 2499 | |||
| 2500 | [0x0f] = KEY_PREVIOUS, /* Prev */ | ||
| 2501 | [0x1b] = KEY_PAUSE, /* Timeshift */ | ||
| 2502 | [0x1a] = KEY_NEXT, /* Next */ | ||
| 2503 | |||
| 2504 | [0x0e] = KEY_STOP, | ||
| 2505 | [0x1f] = KEY_PLAY, | ||
| 2506 | [0x1e] = KEY_PLAYPAUSE, /* Pause */ | ||
| 2507 | |||
| 2508 | [0x1d] = KEY_RECORD, | ||
| 2509 | [0x13] = KEY_MUTE, | ||
| 2510 | [0x19] = KEY_SHUFFLE, /* Snapshot */ | ||
| 2511 | |||
| 2512 | }; | ||
| 2513 | EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys); | ||
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index d01965e96927..d599d360da3f 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c | |||
| @@ -234,7 +234,7 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt) | |||
| 234 | int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) | 234 | int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) |
| 235 | { | 235 | { |
| 236 | __le32 *cpu; | 236 | __le32 *cpu; |
| 237 | dma_addr_t dma_addr; | 237 | dma_addr_t dma_addr = 0; |
| 238 | 238 | ||
| 239 | cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr); | 239 | cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr); |
| 240 | if (NULL == cpu) { | 240 | if (NULL == cpu) { |
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index cf6a817d5059..5b34c134aa25 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c | |||
| @@ -533,7 +533,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, | |||
| 533 | memcpy(vfd, &device_template, sizeof(struct video_device)); | 533 | memcpy(vfd, &device_template, sizeof(struct video_device)); |
| 534 | strlcpy(vfd->name, name, sizeof(vfd->name)); | 534 | strlcpy(vfd->name, name, sizeof(vfd->name)); |
| 535 | vfd->release = video_device_release; | 535 | vfd->release = video_device_release; |
| 536 | vfd->priv = dev; | 536 | video_set_drvdata(vfd, dev); |
| 537 | 537 | ||
| 538 | // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); | 538 | // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); |
| 539 | if (video_register_device(vfd, type, -1) < 0) { | 539 | if (video_register_device(vfd, type, -1) < 0) { |
diff --git a/drivers/media/common/tuners/mt2060.c b/drivers/media/common/tuners/mt2060.c index 1305b0e63ce5..12206d75dd4e 100644 --- a/drivers/media/common/tuners/mt2060.c +++ b/drivers/media/common/tuners/mt2060.c | |||
| @@ -170,6 +170,9 @@ static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame | |||
| 170 | b[0] = REG_LO1B1; | 170 | b[0] = REG_LO1B1; |
| 171 | b[1] = 0xFF; | 171 | b[1] = 0xFF; |
| 172 | 172 | ||
| 173 | if (fe->ops.i2c_gate_ctrl) | ||
| 174 | fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ | ||
| 175 | |||
| 173 | mt2060_writeregs(priv,b,2); | 176 | mt2060_writeregs(priv,b,2); |
| 174 | 177 | ||
| 175 | freq = params->frequency / 1000; // Hz -> kHz | 178 | freq = params->frequency / 1000; // Hz -> kHz |
| @@ -233,6 +236,9 @@ static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame | |||
| 233 | i++; | 236 | i++; |
| 234 | } while (i<10); | 237 | } while (i<10); |
| 235 | 238 | ||
| 239 | if (fe->ops.i2c_gate_ctrl) | ||
| 240 | fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ | ||
| 241 | |||
| 236 | return ret; | 242 | return ret; |
| 237 | } | 243 | } |
| 238 | 244 | ||
| @@ -296,13 +302,35 @@ static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | |||
| 296 | static int mt2060_init(struct dvb_frontend *fe) | 302 | static int mt2060_init(struct dvb_frontend *fe) |
| 297 | { | 303 | { |
| 298 | struct mt2060_priv *priv = fe->tuner_priv; | 304 | struct mt2060_priv *priv = fe->tuner_priv; |
| 299 | return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x33); | 305 | int ret; |
| 306 | |||
| 307 | if (fe->ops.i2c_gate_ctrl) | ||
| 308 | fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ | ||
| 309 | |||
| 310 | ret = mt2060_writereg(priv, REG_VGAG, | ||
| 311 | (priv->cfg->clock_out << 6) | 0x33); | ||
| 312 | |||
| 313 | if (fe->ops.i2c_gate_ctrl) | ||
| 314 | fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ | ||
| 315 | |||
| 316 | return ret; | ||
| 300 | } | 317 | } |
| 301 | 318 | ||
| 302 | static int mt2060_sleep(struct dvb_frontend *fe) | 319 | static int mt2060_sleep(struct dvb_frontend *fe) |
| 303 | { | 320 | { |
| 304 | struct mt2060_priv *priv = fe->tuner_priv; | 321 | struct mt2060_priv *priv = fe->tuner_priv; |
| 305 | return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30); | 322 | int ret; |
| 323 | |||
| 324 | if (fe->ops.i2c_gate_ctrl) | ||
| 325 | fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ | ||
| 326 | |||
| 327 | ret = mt2060_writereg(priv, REG_VGAG, | ||
| 328 | (priv->cfg->clock_out << 6) | 0x30); | ||
| 329 | |||
| 330 | if (fe->ops.i2c_gate_ctrl) | ||
| 331 | fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ | ||
| 332 | |||
| 333 | return ret; | ||
| 306 | } | 334 | } |
| 307 | 335 | ||
| 308 | static int mt2060_release(struct dvb_frontend *fe) | 336 | static int mt2060_release(struct dvb_frontend *fe) |
| @@ -344,6 +372,9 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter | |||
| 344 | priv->i2c = i2c; | 372 | priv->i2c = i2c; |
| 345 | priv->if1_freq = if1; | 373 | priv->if1_freq = if1; |
| 346 | 374 | ||
| 375 | if (fe->ops.i2c_gate_ctrl) | ||
| 376 | fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ | ||
| 377 | |||
| 347 | if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) { | 378 | if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) { |
| 348 | kfree(priv); | 379 | kfree(priv); |
| 349 | return NULL; | 380 | return NULL; |
| @@ -360,6 +391,9 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter | |||
| 360 | 391 | ||
| 361 | mt2060_calibrate(priv); | 392 | mt2060_calibrate(priv); |
| 362 | 393 | ||
| 394 | if (fe->ops.i2c_gate_ctrl) | ||
| 395 | fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ | ||
| 396 | |||
| 363 | return fe; | 397 | return fe; |
| 364 | } | 398 | } |
| 365 | EXPORT_SYMBOL(mt2060_attach); | 399 | EXPORT_SYMBOL(mt2060_attach); |
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c index cb25e43502fe..64379f2bf237 100644 --- a/drivers/media/common/tuners/mxl5007t.c +++ b/drivers/media/common/tuners/mxl5007t.c | |||
| @@ -979,7 +979,6 @@ struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe, | |||
| 979 | switch (instance) { | 979 | switch (instance) { |
| 980 | case 0: | 980 | case 0: |
| 981 | goto fail; | 981 | goto fail; |
| 982 | break; | ||
| 983 | case 1: | 982 | case 1: |
| 984 | /* new tuner instance */ | 983 | /* new tuner instance */ |
| 985 | state->config = cfg; | 984 | state->config = cfg; |
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 93063c6fbbf6..1b48b5d0bf1e 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c | |||
| @@ -1155,7 +1155,6 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, | |||
| 1155 | switch (instance) { | 1155 | switch (instance) { |
| 1156 | case 0: | 1156 | case 0: |
| 1157 | goto fail; | 1157 | goto fail; |
| 1158 | break; | ||
| 1159 | case 1: | 1158 | case 1: |
| 1160 | /* new tuner instance */ | 1159 | /* new tuner instance */ |
| 1161 | priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; | 1160 | priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; |
diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c index 8555d9cf9051..4a74f65e759a 100644 --- a/drivers/media/common/tuners/tda827x.c +++ b/drivers/media/common/tuners/tda827x.c | |||
| @@ -447,17 +447,19 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, | |||
| 447 | else | 447 | else |
| 448 | arg = 0; | 448 | arg = 0; |
| 449 | } | 449 | } |
| 450 | if (priv->cfg->tuner_callback) | 450 | if (fe->callback) |
| 451 | priv->cfg->tuner_callback(priv->i2c_adap->algo_data, | 451 | fe->callback(priv->i2c_adap->algo_data, |
| 452 | gp_func, arg); | 452 | DVB_FRONTEND_COMPONENT_TUNER, |
| 453 | gp_func, arg); | ||
| 453 | buf[1] = high ? 0 : 1; | 454 | buf[1] = high ? 0 : 1; |
| 454 | if (priv->cfg->config == 2) | 455 | if (priv->cfg->config == 2) |
| 455 | buf[1] = high ? 1 : 0; | 456 | buf[1] = high ? 1 : 0; |
| 456 | i2c_transfer(priv->i2c_adap, &msg, 1); | 457 | i2c_transfer(priv->i2c_adap, &msg, 1); |
| 457 | break; | 458 | break; |
| 458 | case 3: /* switch with GPIO of saa713x */ | 459 | case 3: /* switch with GPIO of saa713x */ |
| 459 | if (priv->cfg->tuner_callback) | 460 | if (fe->callback) |
| 460 | priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high); | 461 | fe->callback(priv->i2c_adap->algo_data, |
| 462 | DVB_FRONTEND_COMPONENT_TUNER, 0, high); | ||
| 461 | break; | 463 | break; |
| 462 | } | 464 | } |
| 463 | } | 465 | } |
diff --git a/drivers/media/common/tuners/tda827x.h b/drivers/media/common/tuners/tda827x.h index 7850a9a1dc8f..7d72ce0a0c2d 100644 --- a/drivers/media/common/tuners/tda827x.h +++ b/drivers/media/common/tuners/tda827x.h | |||
| @@ -36,7 +36,6 @@ struct tda827x_config | |||
| 36 | /* interface to tda829x driver */ | 36 | /* interface to tda829x driver */ |
| 37 | unsigned int config; | 37 | unsigned int config; |
| 38 | int switch_addr; | 38 | int switch_addr; |
| 39 | int (*tuner_callback) (void *dev, int command, int arg); | ||
| 40 | 39 | ||
| 41 | void (*agcf)(struct dvb_frontend *fe); | 40 | void (*agcf)(struct dvb_frontend *fe); |
| 42 | }; | 41 | }; |
diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index 91204d3f282d..c112bdd4e0f0 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c | |||
| @@ -672,10 +672,8 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, | |||
| 672 | priv->i2c_props.addr = i2c_addr; | 672 | priv->i2c_props.addr = i2c_addr; |
| 673 | priv->i2c_props.adap = i2c_adap; | 673 | priv->i2c_props.adap = i2c_adap; |
| 674 | priv->i2c_props.name = "tda829x"; | 674 | priv->i2c_props.name = "tda829x"; |
| 675 | if (cfg) { | 675 | if (cfg) |
| 676 | priv->cfg.config = cfg->lna_cfg; | 676 | priv->cfg.config = cfg->lna_cfg; |
| 677 | priv->cfg.tuner_callback = cfg->tuner_callback; | ||
| 678 | } | ||
| 679 | 677 | ||
| 680 | if (tda8290_probe(&priv->i2c_props) == 0) { | 678 | if (tda8290_probe(&priv->i2c_props) == 0) { |
| 681 | priv->ver = TDA8290; | 679 | priv->ver = TDA8290; |
diff --git a/drivers/media/common/tuners/tda8290.h b/drivers/media/common/tuners/tda8290.h index aa074f3f0c07..7e288b26fcc3 100644 --- a/drivers/media/common/tuners/tda8290.h +++ b/drivers/media/common/tuners/tda8290.h | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | 22 | ||
| 23 | struct tda829x_config { | 23 | struct tda829x_config { |
| 24 | unsigned int lna_cfg; | 24 | unsigned int lna_cfg; |
| 25 | int (*tuner_callback) (void *dev, int command, int arg); | ||
| 26 | 25 | ||
| 27 | unsigned int probe_tuner:1; | 26 | unsigned int probe_tuner:1; |
| 28 | #define TDA829X_PROBE_TUNER 0 | 27 | #define TDA829X_PROBE_TUNER 0 |
diff --git a/drivers/media/common/tuners/tda9887.c b/drivers/media/common/tuners/tda9887.c index 72abf0b73486..ff1788cc5d48 100644 --- a/drivers/media/common/tuners/tda9887.c +++ b/drivers/media/common/tuners/tda9887.c | |||
| @@ -686,7 +686,6 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, | |||
| 686 | case 0: | 686 | case 0: |
| 687 | mutex_unlock(&tda9887_list_mutex); | 687 | mutex_unlock(&tda9887_list_mutex); |
| 688 | return NULL; | 688 | return NULL; |
| 689 | break; | ||
| 690 | case 1: | 689 | case 1: |
| 691 | fe->analog_demod_priv = priv; | 690 | fe->analog_demod_priv = priv; |
| 692 | priv->mode = T_STANDBY; | 691 | priv->mode = T_STANDBY; |
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c index aa773a658a2a..2a1aac1cc755 100644 --- a/drivers/media/common/tuners/tuner-simple.c +++ b/drivers/media/common/tuners/tuner-simple.c | |||
| @@ -142,6 +142,7 @@ static inline int tuner_stereo(const int type, const int status) | |||
| 142 | case TUNER_PHILIPS_FM1236_MK3: | 142 | case TUNER_PHILIPS_FM1236_MK3: |
| 143 | case TUNER_PHILIPS_FM1256_IH3: | 143 | case TUNER_PHILIPS_FM1256_IH3: |
| 144 | case TUNER_LG_NTSC_TAPE: | 144 | case TUNER_LG_NTSC_TAPE: |
| 145 | case TUNER_TCL_MF02GIP_5N: | ||
| 145 | return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); | 146 | return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); |
| 146 | default: | 147 | default: |
| 147 | return status & TUNER_STEREO; | 148 | return status & TUNER_STEREO; |
| @@ -494,6 +495,7 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) | |||
| 494 | case TUNER_PHILIPS_FMD1216ME_MK3: | 495 | case TUNER_PHILIPS_FMD1216ME_MK3: |
| 495 | case TUNER_LG_NTSC_TAPE: | 496 | case TUNER_LG_NTSC_TAPE: |
| 496 | case TUNER_PHILIPS_FM1256_IH3: | 497 | case TUNER_PHILIPS_FM1256_IH3: |
| 498 | case TUNER_TCL_MF02GIP_5N: | ||
| 497 | buffer[3] = 0x19; | 499 | buffer[3] = 0x19; |
| 498 | break; | 500 | break; |
| 499 | case TUNER_TNF_5335MF: | 501 | case TUNER_TNF_5335MF: |
| @@ -1038,7 +1040,6 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, | |||
| 1038 | case 0: | 1040 | case 0: |
| 1039 | mutex_unlock(&tuner_simple_list_mutex); | 1041 | mutex_unlock(&tuner_simple_list_mutex); |
| 1040 | return NULL; | 1042 | return NULL; |
| 1041 | break; | ||
| 1042 | case 1: | 1043 | case 1: |
| 1043 | fe->tuner_priv = priv; | 1044 | fe->tuner_priv = priv; |
| 1044 | 1045 | ||
diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c index 10dddca8b5d1..04961a1f44be 100644 --- a/drivers/media/common/tuners/tuner-types.c +++ b/drivers/media/common/tuners/tuner-types.c | |||
| @@ -1216,6 +1216,23 @@ static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = { | |||
| 1216 | }, | 1216 | }, |
| 1217 | }; | 1217 | }; |
| 1218 | 1218 | ||
| 1219 | /* ------------ TUNER_TCL_MF02GIP-5N-E - TCL MF02GIP-5N ------------ */ | ||
| 1220 | |||
| 1221 | static struct tuner_range tuner_tcl_mf02gip_5n_ntsc_ranges[] = { | ||
| 1222 | { 16 * 172.00 /*MHz*/, 0x8e, 0x01, }, | ||
| 1223 | { 16 * 448.00 /*MHz*/, 0x8e, 0x02, }, | ||
| 1224 | { 16 * 999.99 , 0x8e, 0x04, }, | ||
| 1225 | }; | ||
| 1226 | |||
| 1227 | static struct tuner_params tuner_tcl_mf02gip_5n_params[] = { | ||
| 1228 | { | ||
| 1229 | .type = TUNER_PARAM_TYPE_NTSC, | ||
| 1230 | .ranges = tuner_tcl_mf02gip_5n_ntsc_ranges, | ||
| 1231 | .count = ARRAY_SIZE(tuner_tcl_mf02gip_5n_ntsc_ranges), | ||
| 1232 | .cb_first_if_lower_freq = 1, | ||
| 1233 | }, | ||
| 1234 | }; | ||
| 1235 | |||
| 1219 | /* --------------------------------------------------------------------- */ | 1236 | /* --------------------------------------------------------------------- */ |
| 1220 | 1237 | ||
| 1221 | struct tunertype tuners[] = { | 1238 | struct tunertype tuners[] = { |
| @@ -1641,6 +1658,11 @@ struct tunertype tuners[] = { | |||
| 1641 | .name = "Xceive 5000 tuner", | 1658 | .name = "Xceive 5000 tuner", |
| 1642 | /* see xc5000.c for details */ | 1659 | /* see xc5000.c for details */ |
| 1643 | }, | 1660 | }, |
| 1661 | [TUNER_TCL_MF02GIP_5N] = { /* TCL tuner MF02GIP-5N-E */ | ||
| 1662 | .name = "TCL tuner MF02GIP-5N-E", | ||
| 1663 | .params = tuner_tcl_mf02gip_5n_params, | ||
| 1664 | .count = ARRAY_SIZE(tuner_tcl_mf02gip_5n_params), | ||
| 1665 | }, | ||
| 1644 | }; | 1666 | }; |
| 1645 | EXPORT_SYMBOL(tuners); | 1667 | EXPORT_SYMBOL(tuners); |
| 1646 | 1668 | ||
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index 4dd1d2421cc5..b65e6803e6c6 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c | |||
| @@ -71,9 +71,6 @@ struct firmware_properties { | |||
| 71 | struct xc2028_data { | 71 | struct xc2028_data { |
| 72 | struct list_head hybrid_tuner_instance_list; | 72 | struct list_head hybrid_tuner_instance_list; |
| 73 | struct tuner_i2c_props i2c_props; | 73 | struct tuner_i2c_props i2c_props; |
| 74 | int (*tuner_callback) (void *dev, | ||
| 75 | int command, int arg); | ||
| 76 | void *video_dev; | ||
| 77 | __u32 frequency; | 74 | __u32 frequency; |
| 78 | 75 | ||
| 79 | struct firmware_description *firm; | 76 | struct firmware_description *firm; |
| @@ -492,6 +489,23 @@ ret: | |||
| 492 | return i; | 489 | return i; |
| 493 | } | 490 | } |
| 494 | 491 | ||
| 492 | static inline int do_tuner_callback(struct dvb_frontend *fe, int cmd, int arg) | ||
| 493 | { | ||
| 494 | struct xc2028_data *priv = fe->tuner_priv; | ||
| 495 | |||
| 496 | /* analog side (tuner-core) uses i2c_adap->algo_data. | ||
| 497 | * digital side is not guaranteed to have algo_data defined. | ||
| 498 | * | ||
| 499 | * digital side will always have fe->dvb defined. | ||
| 500 | * analog side (tuner-core) doesn't (yet) define fe->dvb. | ||
| 501 | */ | ||
| 502 | |||
| 503 | return (!fe->callback) ? -EINVAL : | ||
| 504 | fe->callback(((fe->dvb) && (fe->dvb->priv)) ? | ||
| 505 | fe->dvb->priv : priv->i2c_props.adap->algo_data, | ||
| 506 | DVB_FRONTEND_COMPONENT_TUNER, cmd, arg); | ||
| 507 | } | ||
| 508 | |||
| 495 | static int load_firmware(struct dvb_frontend *fe, unsigned int type, | 509 | static int load_firmware(struct dvb_frontend *fe, unsigned int type, |
| 496 | v4l2_std_id *id) | 510 | v4l2_std_id *id) |
| 497 | { | 511 | { |
| @@ -530,8 +544,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, | |||
| 530 | 544 | ||
| 531 | if (!size) { | 545 | if (!size) { |
| 532 | /* Special callback command received */ | 546 | /* Special callback command received */ |
| 533 | rc = priv->tuner_callback(priv->video_dev, | 547 | rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0); |
| 534 | XC2028_TUNER_RESET, 0); | ||
| 535 | if (rc < 0) { | 548 | if (rc < 0) { |
| 536 | tuner_err("Error at RESET code %d\n", | 549 | tuner_err("Error at RESET code %d\n", |
| 537 | (*p) & 0x7f); | 550 | (*p) & 0x7f); |
| @@ -542,8 +555,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, | |||
| 542 | if (size >= 0xff00) { | 555 | if (size >= 0xff00) { |
| 543 | switch (size) { | 556 | switch (size) { |
| 544 | case 0xff00: | 557 | case 0xff00: |
| 545 | rc = priv->tuner_callback(priv->video_dev, | 558 | rc = do_tuner_callback(fe, XC2028_RESET_CLK, 0); |
| 546 | XC2028_RESET_CLK, 0); | ||
| 547 | if (rc < 0) { | 559 | if (rc < 0) { |
| 548 | tuner_err("Error at RESET code %d\n", | 560 | tuner_err("Error at RESET code %d\n", |
| 549 | (*p) & 0x7f); | 561 | (*p) & 0x7f); |
| @@ -715,8 +727,7 @@ retry: | |||
| 715 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); | 727 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); |
| 716 | 728 | ||
| 717 | /* Reset is needed before loading firmware */ | 729 | /* Reset is needed before loading firmware */ |
| 718 | rc = priv->tuner_callback(priv->video_dev, | 730 | rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0); |
| 719 | XC2028_TUNER_RESET, 0); | ||
| 720 | if (rc < 0) | 731 | if (rc < 0) |
| 721 | goto fail; | 732 | goto fail; |
| 722 | 733 | ||
| @@ -933,7 +944,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | |||
| 933 | The reset CLK is needed only with tm6000. | 944 | The reset CLK is needed only with tm6000. |
| 934 | Driver should work fine even if this fails. | 945 | Driver should work fine even if this fails. |
| 935 | */ | 946 | */ |
| 936 | priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1); | 947 | do_tuner_callback(fe, XC2028_RESET_CLK, 1); |
| 937 | 948 | ||
| 938 | msleep(10); | 949 | msleep(10); |
| 939 | 950 | ||
| @@ -1002,11 +1013,6 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
| 1002 | 1013 | ||
| 1003 | tuner_dbg("%s called\n", __func__); | 1014 | tuner_dbg("%s called\n", __func__); |
| 1004 | 1015 | ||
| 1005 | if (priv->ctrl.d2633) | ||
| 1006 | type |= D2633; | ||
| 1007 | else | ||
| 1008 | type |= D2620; | ||
| 1009 | |||
| 1010 | switch(fe->ops.info.type) { | 1016 | switch(fe->ops.info.type) { |
| 1011 | case FE_OFDM: | 1017 | case FE_OFDM: |
| 1012 | bw = p->u.ofdm.bandwidth; | 1018 | bw = p->u.ofdm.bandwidth; |
| @@ -1021,10 +1027,8 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
| 1021 | break; | 1027 | break; |
| 1022 | case FE_ATSC: | 1028 | case FE_ATSC: |
| 1023 | bw = BANDWIDTH_6_MHZ; | 1029 | bw = BANDWIDTH_6_MHZ; |
| 1024 | /* The only ATSC firmware (at least on v2.7) is D2633, | 1030 | /* The only ATSC firmware (at least on v2.7) is D2633 */ |
| 1025 | so overrides ctrl->d2633 */ | 1031 | type |= ATSC | D2633; |
| 1026 | type |= ATSC| D2633; | ||
| 1027 | type &= ~D2620; | ||
| 1028 | break; | 1032 | break; |
| 1029 | /* DVB-S is not supported */ | 1033 | /* DVB-S is not supported */ |
| 1030 | default: | 1034 | default: |
| @@ -1057,6 +1061,28 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
| 1057 | tuner_err("error: bandwidth not supported.\n"); | 1061 | tuner_err("error: bandwidth not supported.\n"); |
| 1058 | }; | 1062 | }; |
| 1059 | 1063 | ||
| 1064 | /* | ||
| 1065 | Selects between D2633 or D2620 firmware. | ||
| 1066 | It doesn't make sense for ATSC, since it should be D2633 on all cases | ||
| 1067 | */ | ||
| 1068 | if (fe->ops.info.type != FE_ATSC) { | ||
| 1069 | switch (priv->ctrl.type) { | ||
| 1070 | case XC2028_D2633: | ||
| 1071 | type |= D2633; | ||
| 1072 | break; | ||
| 1073 | case XC2028_D2620: | ||
| 1074 | type |= D2620; | ||
| 1075 | break; | ||
| 1076 | case XC2028_AUTO: | ||
| 1077 | default: | ||
| 1078 | /* Zarlink seems to need D2633 */ | ||
| 1079 | if (priv->ctrl.demod == XC3028_FE_ZARLINK456) | ||
| 1080 | type |= D2633; | ||
| 1081 | else | ||
| 1082 | type |= D2620; | ||
| 1083 | } | ||
| 1084 | } | ||
| 1085 | |||
| 1060 | /* All S-code tables need a 200kHz shift */ | 1086 | /* All S-code tables need a 200kHz shift */ |
| 1061 | if (priv->ctrl.demod) | 1087 | if (priv->ctrl.demod) |
| 1062 | demod = priv->ctrl.demod + 200; | 1088 | demod = priv->ctrl.demod + 200; |
| @@ -1177,20 +1203,10 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe, | |||
| 1177 | break; | 1203 | break; |
| 1178 | case 1: | 1204 | case 1: |
| 1179 | /* new tuner instance */ | 1205 | /* new tuner instance */ |
| 1180 | priv->tuner_callback = cfg->callback; | ||
| 1181 | priv->ctrl.max_len = 13; | 1206 | priv->ctrl.max_len = 13; |
| 1182 | 1207 | ||
| 1183 | mutex_init(&priv->lock); | 1208 | mutex_init(&priv->lock); |
| 1184 | 1209 | ||
| 1185 | /* analog side (tuner-core) uses i2c_adap->algo_data. | ||
| 1186 | * digital side is not guaranteed to have algo_data defined. | ||
| 1187 | * | ||
| 1188 | * digital side will always have fe->dvb defined. | ||
| 1189 | * analog side (tuner-core) doesn't (yet) define fe->dvb. | ||
| 1190 | */ | ||
| 1191 | priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ? | ||
| 1192 | fe->dvb->priv : cfg->i2c_adap->algo_data; | ||
| 1193 | |||
| 1194 | fe->tuner_priv = priv; | 1210 | fe->tuner_priv = priv; |
| 1195 | break; | 1211 | break; |
| 1196 | case 2: | 1212 | case 2: |
diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h index 2c5b6282b569..19de7928a74e 100644 --- a/drivers/media/common/tuners/tuner-xc2028.h +++ b/drivers/media/common/tuners/tuner-xc2028.h | |||
| @@ -24,24 +24,28 @@ | |||
| 24 | #define XC3028_FE_ZARLINK456 4560 | 24 | #define XC3028_FE_ZARLINK456 4560 |
| 25 | #define XC3028_FE_CHINA 5200 | 25 | #define XC3028_FE_CHINA 5200 |
| 26 | 26 | ||
| 27 | enum firmware_type { | ||
| 28 | XC2028_AUTO = 0, /* By default, auto-detects */ | ||
| 29 | XC2028_D2633, | ||
| 30 | XC2028_D2620, | ||
| 31 | }; | ||
| 32 | |||
| 27 | struct xc2028_ctrl { | 33 | struct xc2028_ctrl { |
| 28 | char *fname; | 34 | char *fname; |
| 29 | int max_len; | 35 | int max_len; |
| 30 | unsigned int scode_table; | 36 | unsigned int scode_table; |
| 31 | unsigned int mts :1; | 37 | unsigned int mts :1; |
| 32 | unsigned int d2633 :1; | ||
| 33 | unsigned int input1:1; | 38 | unsigned int input1:1; |
| 34 | unsigned int vhfbw7:1; | 39 | unsigned int vhfbw7:1; |
| 35 | unsigned int uhfbw8:1; | 40 | unsigned int uhfbw8:1; |
| 36 | unsigned int demod; | 41 | unsigned int demod; |
| 42 | enum firmware_type type:2; | ||
| 37 | }; | 43 | }; |
| 38 | 44 | ||
| 39 | struct xc2028_config { | 45 | struct xc2028_config { |
| 40 | struct i2c_adapter *i2c_adap; | 46 | struct i2c_adapter *i2c_adap; |
| 41 | u8 i2c_addr; | 47 | u8 i2c_addr; |
| 42 | void *video_dev; | ||
| 43 | struct xc2028_ctrl *ctrl; | 48 | struct xc2028_ctrl *ctrl; |
| 44 | int (*callback) (void *dev, int command, int arg); | ||
| 45 | }; | 49 | }; |
| 46 | 50 | ||
| 47 | /* xc2028 commands for callback */ | 51 | /* xc2028 commands for callback */ |
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index dcddfa803a75..f9c2bb917f54 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include "dvb_frontend.h" | 30 | #include "dvb_frontend.h" |
| 31 | 31 | ||
| 32 | #include "xc5000.h" | 32 | #include "xc5000.h" |
| 33 | #include "xc5000_priv.h" | 33 | #include "tuner-i2c.h" |
| 34 | 34 | ||
| 35 | static int debug; | 35 | static int debug; |
| 36 | module_param(debug, int, 0644); | 36 | module_param(debug, int, 0644); |
| @@ -40,12 +40,26 @@ static int xc5000_load_fw_on_attach; | |||
| 40 | module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644); | 40 | module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644); |
| 41 | MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization."); | 41 | MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization."); |
| 42 | 42 | ||
| 43 | static DEFINE_MUTEX(xc5000_list_mutex); | ||
| 44 | static LIST_HEAD(hybrid_tuner_instance_list); | ||
| 45 | |||
| 43 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 46 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
| 44 | printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) | 47 | printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) |
| 45 | 48 | ||
| 46 | #define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw" | 49 | #define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw" |
| 47 | #define XC5000_DEFAULT_FIRMWARE_SIZE 12332 | 50 | #define XC5000_DEFAULT_FIRMWARE_SIZE 12332 |
| 48 | 51 | ||
| 52 | struct xc5000_priv { | ||
| 53 | struct tuner_i2c_props i2c_props; | ||
| 54 | struct list_head hybrid_tuner_instance_list; | ||
| 55 | |||
| 56 | u32 if_khz; | ||
| 57 | u32 freq_hz; | ||
| 58 | u32 bandwidth; | ||
| 59 | u8 video_standard; | ||
| 60 | u8 rf_mode; | ||
| 61 | }; | ||
| 62 | |||
| 49 | /* Misc Defines */ | 63 | /* Misc Defines */ |
| 50 | #define MAX_TV_STANDARD 23 | 64 | #define MAX_TV_STANDARD 23 |
| 51 | #define XC_MAX_I2C_WRITE_LENGTH 64 | 65 | #define XC_MAX_I2C_WRITE_LENGTH 64 |
| @@ -216,9 +230,12 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) | |||
| 216 | 230 | ||
| 217 | dprintk(1, "%s()\n", __func__); | 231 | dprintk(1, "%s()\n", __func__); |
| 218 | 232 | ||
| 219 | if (priv->cfg->tuner_callback) { | 233 | if (fe->callback) { |
| 220 | ret = priv->cfg->tuner_callback(priv->devptr, | 234 | ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ? |
| 221 | XC5000_TUNER_RESET, 0); | 235 | fe->dvb->priv : |
| 236 | priv->i2c_props.adap->algo_data, | ||
| 237 | DVB_FRONTEND_COMPONENT_TUNER, | ||
| 238 | XC5000_TUNER_RESET, 0); | ||
| 222 | if (ret) | 239 | if (ret) |
| 223 | printk(KERN_ERR "xc5000: reset failed\n"); | 240 | printk(KERN_ERR "xc5000: reset failed\n"); |
| 224 | } else | 241 | } else |
| @@ -509,13 +526,13 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) | |||
| 509 | u8 buf[2] = { reg >> 8, reg & 0xff }; | 526 | u8 buf[2] = { reg >> 8, reg & 0xff }; |
| 510 | u8 bval[2] = { 0, 0 }; | 527 | u8 bval[2] = { 0, 0 }; |
| 511 | struct i2c_msg msg[2] = { | 528 | struct i2c_msg msg[2] = { |
| 512 | { .addr = priv->cfg->i2c_address, | 529 | { .addr = priv->i2c_props.addr, |
| 513 | .flags = 0, .buf = &buf[0], .len = 2 }, | 530 | .flags = 0, .buf = &buf[0], .len = 2 }, |
| 514 | { .addr = priv->cfg->i2c_address, | 531 | { .addr = priv->i2c_props.addr, |
| 515 | .flags = I2C_M_RD, .buf = &bval[0], .len = 2 }, | 532 | .flags = I2C_M_RD, .buf = &bval[0], .len = 2 }, |
| 516 | }; | 533 | }; |
| 517 | 534 | ||
| 518 | if (i2c_transfer(priv->i2c, msg, 2) != 2) { | 535 | if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) { |
| 519 | printk(KERN_WARNING "xc5000: I2C read failed\n"); | 536 | printk(KERN_WARNING "xc5000: I2C read failed\n"); |
| 520 | return -EREMOTEIO; | 537 | return -EREMOTEIO; |
| 521 | } | 538 | } |
| @@ -526,10 +543,10 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) | |||
| 526 | 543 | ||
| 527 | static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) | 544 | static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) |
| 528 | { | 545 | { |
| 529 | struct i2c_msg msg = { .addr = priv->cfg->i2c_address, | 546 | struct i2c_msg msg = { .addr = priv->i2c_props.addr, |
| 530 | .flags = 0, .buf = buf, .len = len }; | 547 | .flags = 0, .buf = buf, .len = len }; |
| 531 | 548 | ||
| 532 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | 549 | if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { |
| 533 | printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", | 550 | printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", |
| 534 | (int)len); | 551 | (int)len); |
| 535 | return -EREMOTEIO; | 552 | return -EREMOTEIO; |
| @@ -539,10 +556,10 @@ static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len) | |||
| 539 | 556 | ||
| 540 | static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len) | 557 | static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len) |
| 541 | { | 558 | { |
| 542 | struct i2c_msg msg = { .addr = priv->cfg->i2c_address, | 559 | struct i2c_msg msg = { .addr = priv->i2c_props.addr, |
| 543 | .flags = I2C_M_RD, .buf = buf, .len = len }; | 560 | .flags = I2C_M_RD, .buf = buf, .len = len }; |
| 544 | 561 | ||
| 545 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | 562 | if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { |
| 546 | printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len); | 563 | printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len); |
| 547 | return -EREMOTEIO; | 564 | return -EREMOTEIO; |
| 548 | } | 565 | } |
| @@ -559,7 +576,7 @@ static int xc5000_fwupload(struct dvb_frontend* fe) | |||
| 559 | printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", | 576 | printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", |
| 560 | XC5000_DEFAULT_FIRMWARE); | 577 | XC5000_DEFAULT_FIRMWARE); |
| 561 | 578 | ||
| 562 | ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev); | 579 | ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c_props.adap->dev); |
| 563 | if (ret) { | 580 | if (ret) { |
| 564 | printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); | 581 | printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); |
| 565 | ret = XC_RESULT_RESET_FAILURE; | 582 | ret = XC_RESULT_RESET_FAILURE; |
| @@ -675,10 +692,10 @@ static int xc5000_set_params(struct dvb_frontend *fe, | |||
| 675 | return -EREMOTEIO; | 692 | return -EREMOTEIO; |
| 676 | } | 693 | } |
| 677 | 694 | ||
| 678 | ret = xc_set_IF_frequency(priv, priv->cfg->if_khz); | 695 | ret = xc_set_IF_frequency(priv, priv->if_khz); |
| 679 | if (ret != XC_RESULT_SUCCESS) { | 696 | if (ret != XC_RESULT_SUCCESS) { |
| 680 | printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n", | 697 | printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n", |
| 681 | priv->cfg->if_khz); | 698 | priv->if_khz); |
| 682 | return -EIO; | 699 | return -EIO; |
| 683 | } | 700 | } |
| 684 | 701 | ||
| @@ -897,9 +914,19 @@ static int xc5000_init(struct dvb_frontend *fe) | |||
| 897 | 914 | ||
| 898 | static int xc5000_release(struct dvb_frontend *fe) | 915 | static int xc5000_release(struct dvb_frontend *fe) |
| 899 | { | 916 | { |
| 917 | struct xc5000_priv *priv = fe->tuner_priv; | ||
| 918 | |||
| 900 | dprintk(1, "%s()\n", __func__); | 919 | dprintk(1, "%s()\n", __func__); |
| 901 | kfree(fe->tuner_priv); | 920 | |
| 921 | mutex_lock(&xc5000_list_mutex); | ||
| 922 | |||
| 923 | if (priv) | ||
| 924 | hybrid_tuner_release_state(priv); | ||
| 925 | |||
| 926 | mutex_unlock(&xc5000_list_mutex); | ||
| 927 | |||
| 902 | fe->tuner_priv = NULL; | 928 | fe->tuner_priv = NULL; |
| 929 | |||
| 903 | return 0; | 930 | return 0; |
| 904 | } | 931 | } |
| 905 | 932 | ||
| @@ -924,29 +951,43 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = { | |||
| 924 | 951 | ||
| 925 | struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, | 952 | struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, |
| 926 | struct i2c_adapter *i2c, | 953 | struct i2c_adapter *i2c, |
| 927 | struct xc5000_config *cfg, void *devptr) | 954 | struct xc5000_config *cfg) |
| 928 | { | 955 | { |
| 929 | struct xc5000_priv *priv = NULL; | 956 | struct xc5000_priv *priv = NULL; |
| 957 | int instance; | ||
| 930 | u16 id = 0; | 958 | u16 id = 0; |
| 931 | 959 | ||
| 932 | dprintk(1, "%s()\n", __func__); | 960 | dprintk(1, "%s(%d-%04x)\n", __func__, |
| 961 | i2c ? i2c_adapter_id(i2c) : -1, | ||
| 962 | cfg ? cfg->i2c_address : -1); | ||
| 933 | 963 | ||
| 934 | priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL); | 964 | mutex_lock(&xc5000_list_mutex); |
| 935 | if (priv == NULL) | ||
| 936 | return NULL; | ||
| 937 | 965 | ||
| 938 | priv->cfg = cfg; | 966 | instance = hybrid_tuner_request_state(struct xc5000_priv, priv, |
| 939 | priv->bandwidth = BANDWIDTH_6_MHZ; | 967 | hybrid_tuner_instance_list, |
| 940 | priv->i2c = i2c; | 968 | i2c, cfg->i2c_address, "xc5000"); |
| 941 | priv->devptr = devptr; | 969 | switch (instance) { |
| 970 | case 0: | ||
| 971 | goto fail; | ||
| 972 | break; | ||
| 973 | case 1: | ||
| 974 | /* new tuner instance */ | ||
| 975 | priv->bandwidth = BANDWIDTH_6_MHZ; | ||
| 976 | priv->if_khz = cfg->if_khz; | ||
| 977 | |||
| 978 | fe->tuner_priv = priv; | ||
| 979 | break; | ||
| 980 | default: | ||
| 981 | /* existing tuner instance */ | ||
| 982 | fe->tuner_priv = priv; | ||
| 983 | break; | ||
| 984 | } | ||
| 942 | 985 | ||
| 943 | /* Check if firmware has been loaded. It is possible that another | 986 | /* Check if firmware has been loaded. It is possible that another |
| 944 | instance of the driver has loaded the firmware. | 987 | instance of the driver has loaded the firmware. |
| 945 | */ | 988 | */ |
| 946 | if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) { | 989 | if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) |
| 947 | kfree(priv); | 990 | goto fail; |
| 948 | return NULL; | ||
| 949 | } | ||
| 950 | 991 | ||
| 951 | switch(id) { | 992 | switch(id) { |
| 952 | case XC_PRODUCT_ID_FW_LOADED: | 993 | case XC_PRODUCT_ID_FW_LOADED: |
| @@ -967,19 +1008,23 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, | |||
| 967 | printk(KERN_ERR | 1008 | printk(KERN_ERR |
| 968 | "xc5000: Device not found at addr 0x%02x (0x%x)\n", | 1009 | "xc5000: Device not found at addr 0x%02x (0x%x)\n", |
| 969 | cfg->i2c_address, id); | 1010 | cfg->i2c_address, id); |
| 970 | kfree(priv); | 1011 | goto fail; |
| 971 | return NULL; | ||
| 972 | } | 1012 | } |
| 973 | 1013 | ||
| 1014 | mutex_unlock(&xc5000_list_mutex); | ||
| 1015 | |||
| 974 | memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops, | 1016 | memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops, |
| 975 | sizeof(struct dvb_tuner_ops)); | 1017 | sizeof(struct dvb_tuner_ops)); |
| 976 | 1018 | ||
| 977 | fe->tuner_priv = priv; | ||
| 978 | |||
| 979 | if (xc5000_load_fw_on_attach) | 1019 | if (xc5000_load_fw_on_attach) |
| 980 | xc5000_init(fe); | 1020 | xc5000_init(fe); |
| 981 | 1021 | ||
| 982 | return fe; | 1022 | return fe; |
| 1023 | fail: | ||
| 1024 | mutex_unlock(&xc5000_list_mutex); | ||
| 1025 | |||
| 1026 | xc5000_release(fe); | ||
| 1027 | return NULL; | ||
| 983 | } | 1028 | } |
| 984 | EXPORT_SYMBOL(xc5000_attach); | 1029 | EXPORT_SYMBOL(xc5000_attach); |
| 985 | 1030 | ||
diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h index 5389f740945a..cf1a558e0e7f 100644 --- a/drivers/media/common/tuners/xc5000.h +++ b/drivers/media/common/tuners/xc5000.h | |||
| @@ -30,8 +30,6 @@ struct i2c_adapter; | |||
| 30 | struct xc5000_config { | 30 | struct xc5000_config { |
| 31 | u8 i2c_address; | 31 | u8 i2c_address; |
| 32 | u32 if_khz; | 32 | u32 if_khz; |
| 33 | |||
| 34 | int (*tuner_callback) (void *priv, int command, int arg); | ||
| 35 | }; | 33 | }; |
| 36 | 34 | ||
| 37 | /* xc5000 callback command */ | 35 | /* xc5000 callback command */ |
| @@ -49,13 +47,11 @@ struct xc5000_config { | |||
| 49 | (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE)) | 47 | (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE)) |
| 50 | extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, | 48 | extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, |
| 51 | struct i2c_adapter *i2c, | 49 | struct i2c_adapter *i2c, |
| 52 | struct xc5000_config *cfg, | 50 | struct xc5000_config *cfg); |
| 53 | void *devptr); | ||
| 54 | #else | 51 | #else |
| 55 | static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, | 52 | static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, |
| 56 | struct i2c_adapter *i2c, | 53 | struct i2c_adapter *i2c, |
| 57 | struct xc5000_config *cfg, | 54 | struct xc5000_config *cfg) |
| 58 | void *devptr) | ||
| 59 | { | 55 | { |
| 60 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 56 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
| 61 | return NULL; | 57 | return NULL; |
diff --git a/drivers/media/common/tuners/xc5000_priv.h b/drivers/media/common/tuners/xc5000_priv.h deleted file mode 100644 index b2a0074c99c9..000000000000 --- a/drivers/media/common/tuners/xc5000_priv.h +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Xceive XC5000 "QAM/8VSB single chip tuner" | ||
| 3 | * | ||
| 4 | * Copyright (c) 2007 Steven Toth <stoth@linuxtv.org> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef XC5000_PRIV_H | ||
| 23 | #define XC5000_PRIV_H | ||
| 24 | |||
| 25 | struct xc5000_priv { | ||
| 26 | struct xc5000_config *cfg; | ||
| 27 | struct i2c_adapter *i2c; | ||
| 28 | |||
| 29 | u32 freq_hz; | ||
| 30 | u32 bandwidth; | ||
| 31 | u8 video_standard; | ||
| 32 | u8 rf_mode; | ||
| 33 | |||
| 34 | void *devptr; | ||
| 35 | }; | ||
| 36 | |||
| 37 | #endif | ||
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 8bc1445bd33b..0bcd852576d6 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig | |||
| @@ -20,7 +20,6 @@ comment "Supported USB Adapters" | |||
| 20 | source "drivers/media/dvb/dvb-usb/Kconfig" | 20 | source "drivers/media/dvb/dvb-usb/Kconfig" |
| 21 | source "drivers/media/dvb/ttusb-budget/Kconfig" | 21 | source "drivers/media/dvb/ttusb-budget/Kconfig" |
| 22 | source "drivers/media/dvb/ttusb-dec/Kconfig" | 22 | source "drivers/media/dvb/ttusb-dec/Kconfig" |
| 23 | source "drivers/media/dvb/cinergyT2/Kconfig" | ||
| 24 | source "drivers/media/dvb/siano/Kconfig" | 23 | source "drivers/media/dvb/siano/Kconfig" |
| 25 | 24 | ||
| 26 | comment "Supported FlexCopII (B2C2) Adapters" | 25 | comment "Supported FlexCopII (B2C2) Adapters" |
| @@ -35,6 +34,10 @@ comment "Supported Pluto2 Adapters" | |||
| 35 | depends on DVB_CORE && PCI && I2C | 34 | depends on DVB_CORE && PCI && I2C |
| 36 | source "drivers/media/dvb/pluto2/Kconfig" | 35 | source "drivers/media/dvb/pluto2/Kconfig" |
| 37 | 36 | ||
| 37 | comment "Supported SDMC DM1105 Adapters" | ||
| 38 | depends on DVB_CORE && PCI && I2C | ||
| 39 | source "drivers/media/dvb/dm1105/Kconfig" | ||
| 40 | |||
| 38 | comment "Supported DVB Frontends" | 41 | comment "Supported DVB Frontends" |
| 39 | depends on DVB_CORE | 42 | depends on DVB_CORE |
| 40 | source "drivers/media/dvb/frontends/Kconfig" | 43 | source "drivers/media/dvb/frontends/Kconfig" |
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index d6ba4d195201..f91e9eb15e52 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile | |||
| @@ -2,4 +2,4 @@ | |||
| 2 | # Makefile for the kernel multimedia device drivers. | 2 | # Makefile for the kernel multimedia device drivers. |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/ | 5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ |
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c index a91ed28f03a4..26f0011a5078 100644 --- a/drivers/media/dvb/b2c2/flexcop-dma.c +++ b/drivers/media/dvb/b2c2/flexcop-dma.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size) | 10 | int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size) |
| 11 | { | 11 | { |
| 12 | u8 *tcpu; | 12 | u8 *tcpu; |
| 13 | dma_addr_t tdma; | 13 | dma_addr_t tdma = 0; |
| 14 | 14 | ||
| 15 | if (size % 2) { | 15 | if (size % 2) { |
| 16 | err("dma buffersize has to be even."); | 16 | err("dma buffersize has to be even."); |
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 6afbfbbef0ce..48762a2b9e42 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c | |||
| @@ -702,7 +702,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) | |||
| 702 | } | 702 | } |
| 703 | 703 | ||
| 704 | if (card->fe == NULL) | 704 | if (card->fe == NULL) |
| 705 | printk("dvb-bt8xx: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", | 705 | printk("dvb-bt8xx: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", |
| 706 | card->bt->dev->vendor, | 706 | card->bt->dev->vendor, |
| 707 | card->bt->dev->device, | 707 | card->bt->dev->device, |
| 708 | card->bt->dev->subsystem_vendor, | 708 | card->bt->dev->subsystem_vendor, |
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig deleted file mode 100644 index c03513b2ccae..000000000000 --- a/drivers/media/dvb/cinergyT2/Kconfig +++ /dev/null | |||
| @@ -1,85 +0,0 @@ | |||
| 1 | config DVB_CINERGYT2 | ||
| 2 | tristate "Terratec CinergyT2/qanu USB2 DVB-T receiver" | ||
| 3 | depends on DVB_CORE && USB && INPUT | ||
| 4 | help | ||
| 5 | Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers | ||
| 6 | |||
| 7 | Say Y if you own such a device and want to use it. | ||
| 8 | |||
| 9 | |||
| 10 | config DVB_CINERGYT2_TUNING | ||
| 11 | bool "sophisticated fine-tuning for CinergyT2 cards" | ||
| 12 | depends on DVB_CINERGYT2 | ||
| 13 | help | ||
| 14 | Here you can fine-tune some parameters of the CinergyT2 driver. | ||
| 15 | |||
| 16 | Normally you don't need to touch this, but in exotic setups you | ||
| 17 | may fine-tune your setup and adjust e.g. DMA buffer sizes for | ||
| 18 | a particular application. | ||
| 19 | |||
| 20 | |||
| 21 | config DVB_CINERGYT2_STREAM_URB_COUNT | ||
| 22 | int "Number of queued USB Request Blocks for Highspeed Stream Transfers" | ||
| 23 | depends on DVB_CINERGYT2_TUNING | ||
| 24 | default "32" | ||
| 25 | help | ||
| 26 | USB Request Blocks for Highspeed Stream transfers are scheduled in | ||
| 27 | a queue for the Host Controller. | ||
| 28 | |||
| 29 | Usually the default value is a safe choice. | ||
| 30 | |||
| 31 | You may increase this number if you are using this device in a | ||
| 32 | Server Environment with many high-traffic USB Highspeed devices | ||
| 33 | sharing the same USB bus. | ||
| 34 | |||
| 35 | |||
| 36 | config DVB_CINERGYT2_STREAM_BUF_SIZE | ||
| 37 | int "Size of URB Stream Buffers for Highspeed Transfers" | ||
| 38 | depends on DVB_CINERGYT2_TUNING | ||
| 39 | default "512" | ||
| 40 | help | ||
| 41 | Should be a multiple of native buffer size of 512 bytes. | ||
| 42 | Default value is a safe choice. | ||
| 43 | |||
| 44 | You may increase this number if you are using this device in a | ||
| 45 | Server Environment with many high-traffic USB Highspeed devices | ||
| 46 | sharing the same USB bus. | ||
| 47 | |||
| 48 | |||
| 49 | config DVB_CINERGYT2_QUERY_INTERVAL | ||
| 50 | int "Status update interval [milliseconds]" | ||
| 51 | depends on DVB_CINERGYT2_TUNING | ||
| 52 | default "250" | ||
| 53 | help | ||
| 54 | This is the interval for status readouts from the demodulator. | ||
| 55 | You may try lower values if you need more responsive signal quality | ||
| 56 | measurements. | ||
| 57 | |||
| 58 | Please keep in mind that these updates cause traffic on the tuner | ||
| 59 | control bus and thus may or may not affect reception sensitivity. | ||
| 60 | |||
| 61 | The default value should be a safe choice for common applications. | ||
| 62 | |||
| 63 | |||
| 64 | config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE | ||
| 65 | bool "Register the onboard IR Remote Control Receiver as Input Device" | ||
| 66 | depends on DVB_CINERGYT2_TUNING | ||
| 67 | default y | ||
| 68 | help | ||
| 69 | Enable this option if you want to use the onboard Infrared Remote | ||
| 70 | Control Receiver as Linux-Input device. | ||
| 71 | |||
| 72 | Right now only the keycode table for the default Remote Control | ||
| 73 | delivered with the device is supported, please see the driver | ||
| 74 | source code to find out how to add support for other controls. | ||
| 75 | |||
| 76 | |||
| 77 | config DVB_CINERGYT2_RC_QUERY_INTERVAL | ||
| 78 | int "Infrared Remote Controller update interval [milliseconds]" | ||
| 79 | depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE | ||
| 80 | default "50" | ||
| 81 | help | ||
| 82 | If you have a very fast-repeating remote control you can try lower | ||
| 83 | values, for normal consumer receivers the default value should be | ||
| 84 | a safe choice. | ||
| 85 | |||
diff --git a/drivers/media/dvb/cinergyT2/Makefile b/drivers/media/dvb/cinergyT2/Makefile deleted file mode 100644 index d762d8cb0cf1..000000000000 --- a/drivers/media/dvb/cinergyT2/Makefile +++ /dev/null | |||
| @@ -1,3 +0,0 @@ | |||
| 1 | obj-$(CONFIG_DVB_CINERGYT2) += cinergyT2.o | ||
| 2 | |||
| 3 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ | ||
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c deleted file mode 100644 index a824f3719f81..000000000000 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ /dev/null | |||
| @@ -1,1105 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * TerraTec Cinergy T²/qanu USB2 DVB-T adapter. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and | ||
| 5 | * Holger Waechtler <holger@qanu.de> | ||
| 6 | * | ||
| 7 | * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 22 | * | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include <linux/usb.h> | ||
| 29 | #include <linux/input.h> | ||
| 30 | #include <linux/dvb/frontend.h> | ||
| 31 | #include <linux/mutex.h> | ||
| 32 | #include <linux/mm.h> | ||
| 33 | #include <asm/io.h> | ||
| 34 | |||
| 35 | #include "dmxdev.h" | ||
| 36 | #include "dvb_demux.h" | ||
| 37 | #include "dvb_net.h" | ||
| 38 | |||
| 39 | #ifdef CONFIG_DVB_CINERGYT2_TUNING | ||
| 40 | #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT) | ||
| 41 | #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE) | ||
| 42 | #define QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_QUERY_INTERVAL) | ||
| 43 | #ifdef CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE | ||
| 44 | #define RC_QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL) | ||
| 45 | #define ENABLE_RC (1) | ||
| 46 | #endif | ||
| 47 | #else | ||
| 48 | #define STREAM_URB_COUNT (32) | ||
| 49 | #define STREAM_BUF_SIZE (512) /* bytes */ | ||
| 50 | #define ENABLE_RC (1) | ||
| 51 | #define RC_QUERY_INTERVAL (50) /* milliseconds */ | ||
| 52 | #define QUERY_INTERVAL (333) /* milliseconds */ | ||
| 53 | #endif | ||
| 54 | |||
| 55 | #define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver" | ||
| 56 | |||
| 57 | static int debug; | ||
| 58 | module_param_named(debug, debug, int, 0644); | ||
| 59 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
| 60 | |||
| 61 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 62 | |||
| 63 | #define dprintk(level, args...) \ | ||
| 64 | do { \ | ||
| 65 | if ((debug & level)) { \ | ||
| 66 | printk("%s: %s(): ", KBUILD_MODNAME, \ | ||
| 67 | __func__); \ | ||
| 68 | printk(args); } \ | ||
| 69 | } while (0) | ||
| 70 | |||
| 71 | enum cinergyt2_ep1_cmd { | ||
| 72 | CINERGYT2_EP1_PID_TABLE_RESET = 0x01, | ||
| 73 | CINERGYT2_EP1_PID_SETUP = 0x02, | ||
| 74 | CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03, | ||
| 75 | CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04, | ||
| 76 | CINERGYT2_EP1_GET_TUNER_STATUS = 0x05, | ||
| 77 | CINERGYT2_EP1_START_SCAN = 0x06, | ||
| 78 | CINERGYT2_EP1_CONTINUE_SCAN = 0x07, | ||
| 79 | CINERGYT2_EP1_GET_RC_EVENTS = 0x08, | ||
| 80 | CINERGYT2_EP1_SLEEP_MODE = 0x09 | ||
| 81 | }; | ||
| 82 | |||
| 83 | struct dvbt_set_parameters_msg { | ||
| 84 | uint8_t cmd; | ||
| 85 | __le32 freq; | ||
| 86 | uint8_t bandwidth; | ||
| 87 | __le16 tps; | ||
| 88 | uint8_t flags; | ||
| 89 | } __attribute__((packed)); | ||
| 90 | |||
| 91 | struct dvbt_get_status_msg { | ||
| 92 | __le32 freq; | ||
| 93 | uint8_t bandwidth; | ||
| 94 | __le16 tps; | ||
| 95 | uint8_t flags; | ||
| 96 | __le16 gain; | ||
| 97 | uint8_t snr; | ||
| 98 | __le32 viterbi_error_rate; | ||
| 99 | __le32 rs_error_rate; | ||
| 100 | __le32 uncorrected_block_count; | ||
| 101 | uint8_t lock_bits; | ||
| 102 | uint8_t prev_lock_bits; | ||
| 103 | } __attribute__((packed)); | ||
| 104 | |||
| 105 | static struct dvb_frontend_info cinergyt2_fe_info = { | ||
| 106 | .name = DRIVER_NAME, | ||
| 107 | .type = FE_OFDM, | ||
| 108 | .frequency_min = 174000000, | ||
| 109 | .frequency_max = 862000000, | ||
| 110 | .frequency_stepsize = 166667, | ||
| 111 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | | ||
| 112 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | | ||
| 113 | FE_CAN_FEC_AUTO | | ||
| 114 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
| 115 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | | ||
| 116 | FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS | ||
| 117 | }; | ||
| 118 | |||
| 119 | struct cinergyt2 { | ||
| 120 | struct dvb_demux demux; | ||
| 121 | struct usb_device *udev; | ||
| 122 | struct mutex sem; | ||
| 123 | struct mutex wq_sem; | ||
| 124 | struct dvb_adapter adapter; | ||
| 125 | struct dvb_device *fedev; | ||
| 126 | struct dmxdev dmxdev; | ||
| 127 | struct dvb_net dvbnet; | ||
| 128 | |||
| 129 | int streaming; | ||
| 130 | int sleeping; | ||
| 131 | |||
| 132 | struct dvbt_set_parameters_msg param; | ||
| 133 | struct dvbt_get_status_msg status; | ||
| 134 | struct delayed_work query_work; | ||
| 135 | |||
| 136 | wait_queue_head_t poll_wq; | ||
| 137 | int pending_fe_events; | ||
| 138 | int disconnect_pending; | ||
| 139 | unsigned int uncorrected_block_count; | ||
| 140 | atomic_t inuse; | ||
| 141 | |||
| 142 | void *streambuf; | ||
| 143 | dma_addr_t streambuf_dmahandle; | ||
| 144 | struct urb *stream_urb [STREAM_URB_COUNT]; | ||
| 145 | |||
| 146 | #ifdef ENABLE_RC | ||
| 147 | struct input_dev *rc_input_dev; | ||
| 148 | char phys[64]; | ||
| 149 | struct delayed_work rc_query_work; | ||
| 150 | int rc_input_event; | ||
| 151 | __le32 rc_last_code; | ||
| 152 | unsigned long last_event_jiffies; | ||
| 153 | #endif | ||
| 154 | }; | ||
| 155 | |||
| 156 | enum { | ||
| 157 | CINERGYT2_RC_EVENT_TYPE_NONE = 0x00, | ||
| 158 | CINERGYT2_RC_EVENT_TYPE_NEC = 0x01, | ||
| 159 | CINERGYT2_RC_EVENT_TYPE_RC5 = 0x02 | ||
| 160 | }; | ||
| 161 | |||
| 162 | struct cinergyt2_rc_event { | ||
| 163 | char type; | ||
| 164 | __le32 value; | ||
| 165 | } __attribute__((packed)); | ||
| 166 | |||
| 167 | static const uint32_t rc_keys[] = { | ||
| 168 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER, | ||
| 169 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1, | ||
| 170 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2, | ||
| 171 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfb04eb04, KEY_3, | ||
| 172 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfa05eb04, KEY_4, | ||
| 173 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf906eb04, KEY_5, | ||
| 174 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf807eb04, KEY_6, | ||
| 175 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf708eb04, KEY_7, | ||
| 176 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf609eb04, KEY_8, | ||
| 177 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf50aeb04, KEY_9, | ||
| 178 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf30ceb04, KEY_0, | ||
| 179 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf40beb04, KEY_VIDEO, | ||
| 180 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf20deb04, KEY_REFRESH, | ||
| 181 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf10eeb04, KEY_SELECT, | ||
| 182 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xf00feb04, KEY_EPG, | ||
| 183 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xef10eb04, KEY_UP, | ||
| 184 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xeb14eb04, KEY_DOWN, | ||
| 185 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xee11eb04, KEY_LEFT, | ||
| 186 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xec13eb04, KEY_RIGHT, | ||
| 187 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xed12eb04, KEY_OK, | ||
| 188 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xea15eb04, KEY_TEXT, | ||
| 189 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe916eb04, KEY_INFO, | ||
| 190 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe817eb04, KEY_RED, | ||
| 191 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe718eb04, KEY_GREEN, | ||
| 192 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe619eb04, KEY_YELLOW, | ||
| 193 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe51aeb04, KEY_BLUE, | ||
| 194 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe31ceb04, KEY_VOLUMEUP, | ||
| 195 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe11eeb04, KEY_VOLUMEDOWN, | ||
| 196 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe21deb04, KEY_MUTE, | ||
| 197 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe41beb04, KEY_CHANNELUP, | ||
| 198 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xe01feb04, KEY_CHANNELDOWN, | ||
| 199 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xbf40eb04, KEY_PAUSE, | ||
| 200 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xb34ceb04, KEY_PLAY, | ||
| 201 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xa758eb04, KEY_RECORD, | ||
| 202 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xab54eb04, KEY_PREVIOUS, | ||
| 203 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xb748eb04, KEY_STOP, | ||
| 204 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xa35ceb04, KEY_NEXT | ||
| 205 | }; | ||
| 206 | |||
| 207 | static int cinergyt2_command (struct cinergyt2 *cinergyt2, | ||
| 208 | char *send_buf, int send_buf_len, | ||
| 209 | char *recv_buf, int recv_buf_len) | ||
| 210 | { | ||
| 211 | int actual_len; | ||
| 212 | char dummy; | ||
| 213 | int ret; | ||
| 214 | |||
| 215 | ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1), | ||
| 216 | send_buf, send_buf_len, &actual_len, 1000); | ||
| 217 | |||
| 218 | if (ret) | ||
| 219 | dprintk(1, "usb_bulk_msg (send) failed, err %i\n", ret); | ||
| 220 | |||
| 221 | if (!recv_buf) | ||
| 222 | recv_buf = &dummy; | ||
| 223 | |||
| 224 | ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1), | ||
| 225 | recv_buf, recv_buf_len, &actual_len, 1000); | ||
| 226 | |||
| 227 | if (ret) | ||
| 228 | dprintk(1, "usb_bulk_msg (read) failed, err %i\n", ret); | ||
| 229 | |||
| 230 | return ret ? ret : actual_len; | ||
| 231 | } | ||
| 232 | |||
| 233 | static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable) | ||
| 234 | { | ||
| 235 | char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; | ||
| 236 | cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); | ||
| 237 | } | ||
| 238 | |||
| 239 | static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep) | ||
| 240 | { | ||
| 241 | char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 }; | ||
| 242 | cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0); | ||
| 243 | cinergyt2->sleeping = sleep; | ||
| 244 | } | ||
| 245 | |||
| 246 | static void cinergyt2_stream_irq (struct urb *urb); | ||
| 247 | |||
| 248 | static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb) | ||
| 249 | { | ||
| 250 | int err; | ||
| 251 | |||
| 252 | usb_fill_bulk_urb(urb, | ||
| 253 | cinergyt2->udev, | ||
| 254 | usb_rcvbulkpipe(cinergyt2->udev, 0x2), | ||
| 255 | urb->transfer_buffer, | ||
| 256 | STREAM_BUF_SIZE, | ||
| 257 | cinergyt2_stream_irq, | ||
| 258 | cinergyt2); | ||
| 259 | |||
| 260 | if ((err = usb_submit_urb(urb, GFP_ATOMIC))) | ||
| 261 | dprintk(1, "urb submission failed (err = %i)!\n", err); | ||
| 262 | |||
| 263 | return err; | ||
| 264 | } | ||
| 265 | |||
| 266 | static void cinergyt2_stream_irq (struct urb *urb) | ||
| 267 | { | ||
| 268 | struct cinergyt2 *cinergyt2 = urb->context; | ||
| 269 | |||
| 270 | if (urb->actual_length > 0) | ||
| 271 | dvb_dmx_swfilter(&cinergyt2->demux, | ||
| 272 | urb->transfer_buffer, urb->actual_length); | ||
| 273 | |||
| 274 | if (cinergyt2->streaming) | ||
| 275 | cinergyt2_submit_stream_urb(cinergyt2, urb); | ||
| 276 | } | ||
| 277 | |||
| 278 | static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2) | ||
| 279 | { | ||
| 280 | int i; | ||
| 281 | |||
| 282 | for (i=0; i<STREAM_URB_COUNT; i++) | ||
| 283 | usb_free_urb(cinergyt2->stream_urb[i]); | ||
| 284 | |||
| 285 | usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, | ||
| 286 | cinergyt2->streambuf, cinergyt2->streambuf_dmahandle); | ||
| 287 | } | ||
| 288 | |||
| 289 | static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2) | ||
| 290 | { | ||
| 291 | int i; | ||
| 292 | |||
| 293 | cinergyt2->streambuf = usb_buffer_alloc(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, | ||
| 294 | GFP_KERNEL, &cinergyt2->streambuf_dmahandle); | ||
| 295 | if (!cinergyt2->streambuf) { | ||
| 296 | dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n"); | ||
| 297 | return -ENOMEM; | ||
| 298 | } | ||
| 299 | |||
| 300 | memset(cinergyt2->streambuf, 0, STREAM_URB_COUNT*STREAM_BUF_SIZE); | ||
| 301 | |||
| 302 | for (i=0; i<STREAM_URB_COUNT; i++) { | ||
| 303 | struct urb *urb; | ||
| 304 | |||
| 305 | if (!(urb = usb_alloc_urb(0, GFP_ATOMIC))) { | ||
| 306 | dprintk(1, "failed to alloc consistent stream urbs, bailing out!\n"); | ||
| 307 | cinergyt2_free_stream_urbs(cinergyt2); | ||
| 308 | return -ENOMEM; | ||
| 309 | } | ||
| 310 | |||
| 311 | urb->transfer_buffer = cinergyt2->streambuf + i * STREAM_BUF_SIZE; | ||
| 312 | urb->transfer_buffer_length = STREAM_BUF_SIZE; | ||
| 313 | |||
| 314 | cinergyt2->stream_urb[i] = urb; | ||
| 315 | } | ||
| 316 | |||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 320 | static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2) | ||
| 321 | { | ||
| 322 | int i; | ||
| 323 | |||
| 324 | cinergyt2_control_stream_transfer(cinergyt2, 0); | ||
| 325 | |||
| 326 | for (i=0; i<STREAM_URB_COUNT; i++) | ||
| 327 | usb_kill_urb(cinergyt2->stream_urb[i]); | ||
| 328 | } | ||
| 329 | |||
| 330 | static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2) | ||
| 331 | { | ||
| 332 | int i, err; | ||
| 333 | |||
| 334 | for (i=0; i<STREAM_URB_COUNT; i++) { | ||
| 335 | if ((err = cinergyt2_submit_stream_urb(cinergyt2, cinergyt2->stream_urb[i]))) { | ||
| 336 | cinergyt2_stop_stream_xfer(cinergyt2); | ||
| 337 | dprintk(1, "failed urb submission (%i: err = %i)!\n", i, err); | ||
| 338 | return err; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | |||
| 342 | cinergyt2_control_stream_transfer(cinergyt2, 1); | ||
| 343 | return 0; | ||
| 344 | } | ||
| 345 | |||
| 346 | static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
| 347 | { | ||
| 348 | struct dvb_demux *demux = dvbdmxfeed->demux; | ||
| 349 | struct cinergyt2 *cinergyt2 = demux->priv; | ||
| 350 | |||
| 351 | if (cinergyt2->disconnect_pending) | ||
| 352 | return -EAGAIN; | ||
| 353 | if (mutex_lock_interruptible(&cinergyt2->sem)) | ||
| 354 | return -ERESTARTSYS; | ||
| 355 | |||
| 356 | if (cinergyt2->streaming == 0) | ||
| 357 | cinergyt2_start_stream_xfer(cinergyt2); | ||
| 358 | |||
| 359 | cinergyt2->streaming++; | ||
| 360 | mutex_unlock(&cinergyt2->sem); | ||
| 361 | return 0; | ||
| 362 | } | ||
| 363 | |||
| 364 | static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
| 365 | { | ||
| 366 | struct dvb_demux *demux = dvbdmxfeed->demux; | ||
| 367 | struct cinergyt2 *cinergyt2 = demux->priv; | ||
| 368 | |||
| 369 | if (cinergyt2->disconnect_pending) | ||
| 370 | return -EAGAIN; | ||
| 371 | if (mutex_lock_interruptible(&cinergyt2->sem)) | ||
| 372 | return -ERESTARTSYS; | ||
| 373 | |||
| 374 | if (--cinergyt2->streaming == 0) | ||
| 375 | cinergyt2_stop_stream_xfer(cinergyt2); | ||
| 376 | |||
| 377 | mutex_unlock(&cinergyt2->sem); | ||
| 378 | return 0; | ||
| 379 | } | ||
| 380 | |||
| 381 | /** | ||
| 382 | * convert linux-dvb frontend parameter set into TPS. | ||
| 383 | * See ETSI ETS-300744, section 4.6.2, table 9 for details. | ||
| 384 | * | ||
| 385 | * This function is probably reusable and may better get placed in a support | ||
| 386 | * library. | ||
| 387 | * | ||
| 388 | * We replace errornous fields by default TPS fields (the ones with value 0). | ||
| 389 | */ | ||
| 390 | static uint16_t compute_tps (struct dvb_frontend_parameters *p) | ||
| 391 | { | ||
| 392 | struct dvb_ofdm_parameters *op = &p->u.ofdm; | ||
| 393 | uint16_t tps = 0; | ||
| 394 | |||
| 395 | switch (op->code_rate_HP) { | ||
| 396 | case FEC_2_3: | ||
| 397 | tps |= (1 << 7); | ||
| 398 | break; | ||
| 399 | case FEC_3_4: | ||
| 400 | tps |= (2 << 7); | ||
| 401 | break; | ||
| 402 | case FEC_5_6: | ||
| 403 | tps |= (3 << 7); | ||
| 404 | break; | ||
| 405 | case FEC_7_8: | ||
| 406 | tps |= (4 << 7); | ||
| 407 | break; | ||
| 408 | case FEC_1_2: | ||
| 409 | case FEC_AUTO: | ||
| 410 | default: | ||
| 411 | /* tps |= (0 << 7) */; | ||
| 412 | } | ||
| 413 | |||
| 414 | switch (op->code_rate_LP) { | ||
| 415 | case FEC_2_3: | ||
| 416 | tps |= (1 << 4); | ||
| 417 | break; | ||
| 418 | case FEC_3_4: | ||
| 419 | tps |= (2 << 4); | ||
| 420 | break; | ||
| 421 | case FEC_5_6: | ||
| 422 | tps |= (3 << 4); | ||
| 423 | break; | ||
| 424 | case FEC_7_8: | ||
| 425 | tps |= (4 << 4); | ||
| 426 | break; | ||
| 427 | case FEC_1_2: | ||
| 428 | case FEC_AUTO: | ||
| 429 | default: | ||
| 430 | /* tps |= (0 << 4) */; | ||
| 431 | } | ||
| 432 | |||
| 433 | switch (op->constellation) { | ||
| 434 | case QAM_16: | ||
| 435 | tps |= (1 << 13); | ||
| 436 | break; | ||
| 437 | case QAM_64: | ||
| 438 | tps |= (2 << 13); | ||
| 439 | break; | ||
| 440 | case QPSK: | ||
| 441 | default: | ||
| 442 | /* tps |= (0 << 13) */; | ||
| 443 | } | ||
| 444 | |||
| 445 | switch (op->transmission_mode) { | ||
| 446 | case TRANSMISSION_MODE_8K: | ||
| 447 | tps |= (1 << 0); | ||
| 448 | break; | ||
| 449 | case TRANSMISSION_MODE_2K: | ||
| 450 | default: | ||
| 451 | /* tps |= (0 << 0) */; | ||
| 452 | } | ||
| 453 | |||
| 454 | switch (op->guard_interval) { | ||
| 455 | case GUARD_INTERVAL_1_16: | ||
| 456 | tps |= (1 << 2); | ||
| 457 | break; | ||
| 458 | case GUARD_INTERVAL_1_8: | ||
| 459 | tps |= (2 << 2); | ||
| 460 | break; | ||
| 461 | case GUARD_INTERVAL_1_4: | ||
| 462 | tps |= (3 << 2); | ||
| 463 | break; | ||
| 464 | case GUARD_INTERVAL_1_32: | ||
| 465 | default: | ||
| 466 | /* tps |= (0 << 2) */; | ||
| 467 | } | ||
| 468 | |||
| 469 | switch (op->hierarchy_information) { | ||
| 470 | case HIERARCHY_1: | ||
| 471 | tps |= (1 << 10); | ||
| 472 | break; | ||
| 473 | case HIERARCHY_2: | ||
| 474 | tps |= (2 << 10); | ||
| 475 | break; | ||
| 476 | case HIERARCHY_4: | ||
| 477 | tps |= (3 << 10); | ||
| 478 | break; | ||
| 479 | case HIERARCHY_NONE: | ||
| 480 | default: | ||
| 481 | /* tps |= (0 << 10) */; | ||
| 482 | } | ||
| 483 | |||
| 484 | return tps; | ||
| 485 | } | ||
| 486 | |||
| 487 | static int cinergyt2_open (struct inode *inode, struct file *file) | ||
| 488 | { | ||
| 489 | struct dvb_device *dvbdev = file->private_data; | ||
| 490 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | ||
| 491 | int err = -EAGAIN; | ||
| 492 | |||
| 493 | if (cinergyt2->disconnect_pending) | ||
| 494 | goto out; | ||
| 495 | err = mutex_lock_interruptible(&cinergyt2->wq_sem); | ||
| 496 | if (err) | ||
| 497 | goto out; | ||
| 498 | |||
| 499 | err = mutex_lock_interruptible(&cinergyt2->sem); | ||
| 500 | if (err) | ||
| 501 | goto out_unlock1; | ||
| 502 | |||
| 503 | if ((err = dvb_generic_open(inode, file))) | ||
| 504 | goto out_unlock2; | ||
| 505 | |||
| 506 | if ((file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
| 507 | cinergyt2_sleep(cinergyt2, 0); | ||
| 508 | schedule_delayed_work(&cinergyt2->query_work, HZ/2); | ||
| 509 | } | ||
| 510 | |||
| 511 | atomic_inc(&cinergyt2->inuse); | ||
| 512 | |||
| 513 | out_unlock2: | ||
| 514 | mutex_unlock(&cinergyt2->sem); | ||
| 515 | out_unlock1: | ||
| 516 | mutex_unlock(&cinergyt2->wq_sem); | ||
| 517 | out: | ||
| 518 | return err; | ||
| 519 | } | ||
| 520 | |||
| 521 | static void cinergyt2_unregister(struct cinergyt2 *cinergyt2) | ||
| 522 | { | ||
| 523 | dvb_net_release(&cinergyt2->dvbnet); | ||
| 524 | dvb_dmxdev_release(&cinergyt2->dmxdev); | ||
| 525 | dvb_dmx_release(&cinergyt2->demux); | ||
| 526 | dvb_unregister_device(cinergyt2->fedev); | ||
| 527 | dvb_unregister_adapter(&cinergyt2->adapter); | ||
| 528 | |||
| 529 | cinergyt2_free_stream_urbs(cinergyt2); | ||
| 530 | kfree(cinergyt2); | ||
| 531 | } | ||
| 532 | |||
| 533 | static int cinergyt2_release (struct inode *inode, struct file *file) | ||
| 534 | { | ||
| 535 | struct dvb_device *dvbdev = file->private_data; | ||
| 536 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | ||
| 537 | |||
| 538 | mutex_lock(&cinergyt2->wq_sem); | ||
| 539 | |||
| 540 | if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { | ||
| 541 | cancel_rearming_delayed_work(&cinergyt2->query_work); | ||
| 542 | |||
| 543 | mutex_lock(&cinergyt2->sem); | ||
| 544 | cinergyt2_sleep(cinergyt2, 1); | ||
| 545 | mutex_unlock(&cinergyt2->sem); | ||
| 546 | } | ||
| 547 | |||
| 548 | mutex_unlock(&cinergyt2->wq_sem); | ||
| 549 | |||
| 550 | if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) { | ||
| 551 | warn("delayed unregister in release"); | ||
| 552 | cinergyt2_unregister(cinergyt2); | ||
| 553 | } | ||
| 554 | |||
| 555 | return dvb_generic_release(inode, file); | ||
| 556 | } | ||
| 557 | |||
| 558 | static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct *wait) | ||
| 559 | { | ||
| 560 | struct dvb_device *dvbdev = file->private_data; | ||
| 561 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | ||
| 562 | unsigned int mask = 0; | ||
| 563 | |||
| 564 | if (cinergyt2->disconnect_pending) | ||
| 565 | return -EAGAIN; | ||
| 566 | if (mutex_lock_interruptible(&cinergyt2->sem)) | ||
| 567 | return -ERESTARTSYS; | ||
| 568 | |||
| 569 | poll_wait(file, &cinergyt2->poll_wq, wait); | ||
| 570 | |||
| 571 | if (cinergyt2->pending_fe_events != 0) | ||
| 572 | mask |= (POLLIN | POLLRDNORM | POLLPRI); | ||
| 573 | |||
| 574 | mutex_unlock(&cinergyt2->sem); | ||
| 575 | |||
| 576 | return mask; | ||
| 577 | } | ||
| 578 | |||
| 579 | |||
| 580 | static int cinergyt2_ioctl (struct inode *inode, struct file *file, | ||
| 581 | unsigned cmd, unsigned long arg) | ||
| 582 | { | ||
| 583 | struct dvb_device *dvbdev = file->private_data; | ||
| 584 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | ||
| 585 | struct dvbt_get_status_msg *stat = &cinergyt2->status; | ||
| 586 | fe_status_t status = 0; | ||
| 587 | |||
| 588 | switch (cmd) { | ||
| 589 | case FE_GET_INFO: | ||
| 590 | return copy_to_user((void __user*) arg, &cinergyt2_fe_info, | ||
| 591 | sizeof(struct dvb_frontend_info)); | ||
| 592 | |||
| 593 | case FE_READ_STATUS: | ||
| 594 | if (0xffff - le16_to_cpu(stat->gain) > 30) | ||
| 595 | status |= FE_HAS_SIGNAL; | ||
| 596 | if (stat->lock_bits & (1 << 6)) | ||
| 597 | status |= FE_HAS_LOCK; | ||
| 598 | if (stat->lock_bits & (1 << 5)) | ||
| 599 | status |= FE_HAS_SYNC; | ||
| 600 | if (stat->lock_bits & (1 << 4)) | ||
| 601 | status |= FE_HAS_CARRIER; | ||
| 602 | if (stat->lock_bits & (1 << 1)) | ||
| 603 | status |= FE_HAS_VITERBI; | ||
| 604 | |||
| 605 | return copy_to_user((void __user*) arg, &status, sizeof(status)); | ||
| 606 | |||
| 607 | case FE_READ_BER: | ||
| 608 | return put_user(le32_to_cpu(stat->viterbi_error_rate), | ||
| 609 | (__u32 __user *) arg); | ||
| 610 | |||
| 611 | case FE_READ_SIGNAL_STRENGTH: | ||
| 612 | return put_user(0xffff - le16_to_cpu(stat->gain), | ||
| 613 | (__u16 __user *) arg); | ||
| 614 | |||
| 615 | case FE_READ_SNR: | ||
| 616 | return put_user((stat->snr << 8) | stat->snr, | ||
| 617 | (__u16 __user *) arg); | ||
| 618 | |||
| 619 | case FE_READ_UNCORRECTED_BLOCKS: | ||
| 620 | { | ||
| 621 | uint32_t unc_count; | ||
| 622 | |||
| 623 | if (mutex_lock_interruptible(&cinergyt2->sem)) | ||
| 624 | return -ERESTARTSYS; | ||
| 625 | unc_count = cinergyt2->uncorrected_block_count; | ||
| 626 | cinergyt2->uncorrected_block_count = 0; | ||
| 627 | mutex_unlock(&cinergyt2->sem); | ||
| 628 | |||
| 629 | /* UNC are already converted to host byte order... */ | ||
| 630 | return put_user(unc_count,(__u32 __user *) arg); | ||
| 631 | } | ||
| 632 | case FE_SET_FRONTEND: | ||
| 633 | { | ||
| 634 | struct dvbt_set_parameters_msg *param = &cinergyt2->param; | ||
| 635 | struct dvb_frontend_parameters p; | ||
| 636 | int err; | ||
| 637 | |||
| 638 | if ((file->f_flags & O_ACCMODE) == O_RDONLY) | ||
| 639 | return -EPERM; | ||
| 640 | |||
| 641 | if (copy_from_user(&p, (void __user*) arg, sizeof(p))) | ||
| 642 | return -EFAULT; | ||
| 643 | |||
| 644 | if (cinergyt2->disconnect_pending) | ||
| 645 | return -EAGAIN; | ||
| 646 | if (mutex_lock_interruptible(&cinergyt2->sem)) | ||
| 647 | return -ERESTARTSYS; | ||
| 648 | |||
| 649 | param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; | ||
| 650 | param->tps = cpu_to_le16(compute_tps(&p)); | ||
| 651 | param->freq = cpu_to_le32(p.frequency / 1000); | ||
| 652 | param->bandwidth = 8 - p.u.ofdm.bandwidth - BANDWIDTH_8_MHZ; | ||
| 653 | |||
| 654 | stat->lock_bits = 0; | ||
| 655 | cinergyt2->pending_fe_events++; | ||
| 656 | wake_up_interruptible(&cinergyt2->poll_wq); | ||
| 657 | |||
| 658 | err = cinergyt2_command(cinergyt2, | ||
| 659 | (char *) param, sizeof(*param), | ||
| 660 | NULL, 0); | ||
| 661 | |||
| 662 | mutex_unlock(&cinergyt2->sem); | ||
| 663 | |||
| 664 | return (err < 0) ? err : 0; | ||
| 665 | } | ||
| 666 | |||
| 667 | case FE_GET_FRONTEND: | ||
| 668 | /** | ||
| 669 | * trivial to implement (see struct dvbt_get_status_msg). | ||
| 670 | * equivalent to FE_READ ioctls, but needs | ||
| 671 | * TPS -> linux-dvb parameter set conversion. Feel free | ||
| 672 | * to implement this and send us a patch if you need this | ||
| 673 | * functionality. | ||
| 674 | */ | ||
| 675 | break; | ||
| 676 | |||
| 677 | case FE_GET_EVENT: | ||
| 678 | { | ||
| 679 | /** | ||
| 680 | * for now we only fill the status field. the parameters | ||
| 681 | * are trivial to fill as soon FE_GET_FRONTEND is done. | ||
| 682 | */ | ||
| 683 | struct dvb_frontend_event __user *e = (void __user *) arg; | ||
| 684 | if (cinergyt2->pending_fe_events == 0) { | ||
| 685 | if (file->f_flags & O_NONBLOCK) | ||
| 686 | return -EWOULDBLOCK; | ||
| 687 | wait_event_interruptible(cinergyt2->poll_wq, | ||
| 688 | cinergyt2->pending_fe_events > 0); | ||
| 689 | } | ||
| 690 | cinergyt2->pending_fe_events = 0; | ||
| 691 | return cinergyt2_ioctl(inode, file, FE_READ_STATUS, | ||
| 692 | (unsigned long) &e->status); | ||
| 693 | } | ||
| 694 | |||
| 695 | default: | ||
| 696 | ; | ||
| 697 | } | ||
| 698 | |||
| 699 | return -EINVAL; | ||
| 700 | } | ||
| 701 | |||
| 702 | static int cinergyt2_mmap(struct file *file, struct vm_area_struct *vma) | ||
| 703 | { | ||
| 704 | struct dvb_device *dvbdev = file->private_data; | ||
| 705 | struct cinergyt2 *cinergyt2 = dvbdev->priv; | ||
| 706 | int ret = 0; | ||
| 707 | |||
| 708 | lock_kernel(); | ||
| 709 | |||
| 710 | if (vma->vm_flags & (VM_WRITE | VM_EXEC)) { | ||
| 711 | ret = -EPERM; | ||
| 712 | goto bailout; | ||
| 713 | } | ||
| 714 | |||
| 715 | if (vma->vm_end > vma->vm_start + STREAM_URB_COUNT * STREAM_BUF_SIZE) { | ||
| 716 | ret = -EINVAL; | ||
| 717 | goto bailout; | ||
| 718 | } | ||
| 719 | |||
| 720 | vma->vm_flags |= (VM_IO | VM_DONTCOPY); | ||
| 721 | vma->vm_file = file; | ||
| 722 | |||
| 723 | ret = remap_pfn_range(vma, vma->vm_start, | ||
| 724 | virt_to_phys(cinergyt2->streambuf) >> PAGE_SHIFT, | ||
| 725 | vma->vm_end - vma->vm_start, | ||
| 726 | vma->vm_page_prot) ? -EAGAIN : 0; | ||
| 727 | bailout: | ||
| 728 | unlock_kernel(); | ||
| 729 | return ret; | ||
| 730 | } | ||
| 731 | |||
| 732 | static struct file_operations cinergyt2_fops = { | ||
| 733 | .owner = THIS_MODULE, | ||
| 734 | .ioctl = cinergyt2_ioctl, | ||
| 735 | .poll = cinergyt2_poll, | ||
| 736 | .open = cinergyt2_open, | ||
| 737 | .release = cinergyt2_release, | ||
| 738 | .mmap = cinergyt2_mmap | ||
| 739 | }; | ||
| 740 | |||
| 741 | static struct dvb_device cinergyt2_fe_template = { | ||
| 742 | .users = ~0, | ||
| 743 | .writers = 1, | ||
| 744 | .readers = (~0)-1, | ||
| 745 | .fops = &cinergyt2_fops | ||
| 746 | }; | ||
| 747 | |||
| 748 | #ifdef ENABLE_RC | ||
| 749 | |||
| 750 | static void cinergyt2_query_rc (struct work_struct *work) | ||
| 751 | { | ||
| 752 | struct cinergyt2 *cinergyt2 = | ||
| 753 | container_of(work, struct cinergyt2, rc_query_work.work); | ||
| 754 | char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS }; | ||
| 755 | struct cinergyt2_rc_event rc_events[12]; | ||
| 756 | int n, len, i; | ||
| 757 | |||
| 758 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | ||
| 759 | return; | ||
| 760 | |||
| 761 | len = cinergyt2_command(cinergyt2, buf, sizeof(buf), | ||
| 762 | (char *) rc_events, sizeof(rc_events)); | ||
| 763 | if (len < 0) | ||
| 764 | goto out; | ||
| 765 | if (len == 0) { | ||
| 766 | if (time_after(jiffies, cinergyt2->last_event_jiffies + | ||
| 767 | msecs_to_jiffies(150))) { | ||
| 768 | /* stop key repeat */ | ||
| 769 | if (cinergyt2->rc_input_event != KEY_MAX) { | ||
| 770 | dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); | ||
| 771 | input_report_key(cinergyt2->rc_input_dev, | ||
| 772 | cinergyt2->rc_input_event, 0); | ||
| 773 | input_sync(cinergyt2->rc_input_dev); | ||
| 774 | cinergyt2->rc_input_event = KEY_MAX; | ||
| 775 | } | ||
| 776 | cinergyt2->rc_last_code = cpu_to_le32(~0); | ||
| 777 | } | ||
| 778 | goto out; | ||
| 779 | } | ||
| 780 | cinergyt2->last_event_jiffies = jiffies; | ||
| 781 | |||
| 782 | for (n = 0; n < (len / sizeof(rc_events[0])); n++) { | ||
| 783 | dprintk(1, "rc_events[%d].value = %x, type=%x\n", | ||
| 784 | n, le32_to_cpu(rc_events[n].value), rc_events[n].type); | ||
| 785 | |||
| 786 | if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC && | ||
| 787 | rc_events[n].value == cpu_to_le32(~0)) { | ||
| 788 | /* keyrepeat bit -> just repeat last rc_input_event */ | ||
| 789 | } else { | ||
| 790 | cinergyt2->rc_input_event = KEY_MAX; | ||
| 791 | for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) { | ||
| 792 | if (rc_keys[i + 0] == rc_events[n].type && | ||
| 793 | rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) { | ||
| 794 | cinergyt2->rc_input_event = rc_keys[i + 2]; | ||
| 795 | break; | ||
| 796 | } | ||
| 797 | } | ||
| 798 | } | ||
| 799 | |||
| 800 | if (cinergyt2->rc_input_event != KEY_MAX) { | ||
| 801 | if (rc_events[n].value == cinergyt2->rc_last_code && | ||
| 802 | cinergyt2->rc_last_code != cpu_to_le32(~0)) { | ||
| 803 | /* emit a key-up so the double event is recognized */ | ||
| 804 | dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event); | ||
| 805 | input_report_key(cinergyt2->rc_input_dev, | ||
| 806 | cinergyt2->rc_input_event, 0); | ||
| 807 | } | ||
| 808 | dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); | ||
| 809 | input_report_key(cinergyt2->rc_input_dev, | ||
| 810 | cinergyt2->rc_input_event, 1); | ||
| 811 | input_sync(cinergyt2->rc_input_dev); | ||
| 812 | cinergyt2->rc_last_code = rc_events[n].value; | ||
| 813 | } | ||
| 814 | } | ||
| 815 | |||
| 816 | out: | ||
| 817 | schedule_delayed_work(&cinergyt2->rc_query_work, | ||
| 818 | msecs_to_jiffies(RC_QUERY_INTERVAL)); | ||
| 819 | |||
| 820 | mutex_unlock(&cinergyt2->sem); | ||
| 821 | } | ||
| 822 | |||
| 823 | static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) | ||
| 824 | { | ||
| 825 | struct input_dev *input_dev; | ||
| 826 | int i; | ||
| 827 | int err; | ||
| 828 | |||
| 829 | input_dev = input_allocate_device(); | ||
| 830 | if (!input_dev) | ||
| 831 | return -ENOMEM; | ||
| 832 | |||
| 833 | usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys)); | ||
| 834 | strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys)); | ||
| 835 | cinergyt2->rc_input_event = KEY_MAX; | ||
| 836 | cinergyt2->rc_last_code = cpu_to_le32(~0); | ||
| 837 | INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc); | ||
| 838 | |||
| 839 | input_dev->name = DRIVER_NAME " remote control"; | ||
| 840 | input_dev->phys = cinergyt2->phys; | ||
| 841 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
| 842 | for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) | ||
| 843 | set_bit(rc_keys[i + 2], input_dev->keybit); | ||
| 844 | input_dev->keycodesize = 0; | ||
| 845 | input_dev->keycodemax = 0; | ||
| 846 | input_dev->id.bustype = BUS_USB; | ||
| 847 | input_dev->id.vendor = le16_to_cpu(cinergyt2->udev->descriptor.idVendor); | ||
| 848 | input_dev->id.product = le16_to_cpu(cinergyt2->udev->descriptor.idProduct); | ||
| 849 | input_dev->id.version = 1; | ||
| 850 | input_dev->dev.parent = &cinergyt2->udev->dev; | ||
| 851 | |||
| 852 | err = input_register_device(input_dev); | ||
| 853 | if (err) { | ||
| 854 | input_free_device(input_dev); | ||
| 855 | return err; | ||
| 856 | } | ||
| 857 | |||
| 858 | cinergyt2->rc_input_dev = input_dev; | ||
| 859 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); | ||
| 860 | |||
| 861 | return 0; | ||
| 862 | } | ||
| 863 | |||
| 864 | static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) | ||
| 865 | { | ||
| 866 | cancel_rearming_delayed_work(&cinergyt2->rc_query_work); | ||
| 867 | input_unregister_device(cinergyt2->rc_input_dev); | ||
| 868 | } | ||
| 869 | |||
| 870 | static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) | ||
| 871 | { | ||
| 872 | cancel_rearming_delayed_work(&cinergyt2->rc_query_work); | ||
| 873 | } | ||
| 874 | |||
| 875 | static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) | ||
| 876 | { | ||
| 877 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); | ||
| 878 | } | ||
| 879 | |||
| 880 | #else | ||
| 881 | |||
| 882 | static inline int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { return 0; } | ||
| 883 | static inline void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { } | ||
| 884 | static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) { } | ||
| 885 | static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { } | ||
| 886 | |||
| 887 | #endif /* ENABLE_RC */ | ||
| 888 | |||
| 889 | static void cinergyt2_query (struct work_struct *work) | ||
| 890 | { | ||
| 891 | struct cinergyt2 *cinergyt2 = | ||
| 892 | container_of(work, struct cinergyt2, query_work.work); | ||
| 893 | char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 894 | struct dvbt_get_status_msg *s = &cinergyt2->status; | ||
| 895 | uint8_t lock_bits; | ||
| 896 | |||
| 897 | if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem)) | ||
| 898 | return; | ||
| 899 | |||
| 900 | lock_bits = s->lock_bits; | ||
| 901 | |||
| 902 | cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s)); | ||
| 903 | |||
| 904 | cinergyt2->uncorrected_block_count += | ||
| 905 | le32_to_cpu(s->uncorrected_block_count); | ||
| 906 | |||
| 907 | if (lock_bits != s->lock_bits) { | ||
| 908 | wake_up_interruptible(&cinergyt2->poll_wq); | ||
| 909 | cinergyt2->pending_fe_events++; | ||
| 910 | } | ||
| 911 | |||
| 912 | schedule_delayed_work(&cinergyt2->query_work, | ||
| 913 | msecs_to_jiffies(QUERY_INTERVAL)); | ||
| 914 | |||
| 915 | mutex_unlock(&cinergyt2->sem); | ||
| 916 | } | ||
| 917 | |||
| 918 | static int cinergyt2_probe (struct usb_interface *intf, | ||
| 919 | const struct usb_device_id *id) | ||
| 920 | { | ||
| 921 | struct cinergyt2 *cinergyt2; | ||
| 922 | int err; | ||
| 923 | |||
| 924 | if (!(cinergyt2 = kzalloc (sizeof(struct cinergyt2), GFP_KERNEL))) { | ||
| 925 | dprintk(1, "out of memory?!?\n"); | ||
| 926 | return -ENOMEM; | ||
| 927 | } | ||
| 928 | |||
| 929 | usb_set_intfdata (intf, (void *) cinergyt2); | ||
| 930 | |||
| 931 | mutex_init(&cinergyt2->sem); | ||
| 932 | mutex_init(&cinergyt2->wq_sem); | ||
| 933 | init_waitqueue_head (&cinergyt2->poll_wq); | ||
| 934 | INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query); | ||
| 935 | |||
| 936 | cinergyt2->udev = interface_to_usbdev(intf); | ||
| 937 | cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; | ||
| 938 | |||
| 939 | if (cinergyt2_alloc_stream_urbs (cinergyt2) < 0) { | ||
| 940 | dprintk(1, "unable to allocate stream urbs\n"); | ||
| 941 | kfree(cinergyt2); | ||
| 942 | return -ENOMEM; | ||
| 943 | } | ||
| 944 | |||
| 945 | err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, | ||
| 946 | THIS_MODULE, &cinergyt2->udev->dev, | ||
| 947 | adapter_nr); | ||
| 948 | if (err < 0) { | ||
| 949 | kfree(cinergyt2); | ||
| 950 | return err; | ||
| 951 | } | ||
| 952 | |||
| 953 | cinergyt2->demux.priv = cinergyt2; | ||
| 954 | cinergyt2->demux.filternum = 256; | ||
| 955 | cinergyt2->demux.feednum = 256; | ||
| 956 | cinergyt2->demux.start_feed = cinergyt2_start_feed; | ||
| 957 | cinergyt2->demux.stop_feed = cinergyt2_stop_feed; | ||
| 958 | cinergyt2->demux.dmx.capabilities = DMX_TS_FILTERING | | ||
| 959 | DMX_SECTION_FILTERING | | ||
| 960 | DMX_MEMORY_BASED_FILTERING; | ||
| 961 | |||
| 962 | if ((err = dvb_dmx_init(&cinergyt2->demux)) < 0) { | ||
| 963 | dprintk(1, "dvb_dmx_init() failed (err = %d)\n", err); | ||
| 964 | goto bailout; | ||
| 965 | } | ||
| 966 | |||
| 967 | cinergyt2->dmxdev.filternum = cinergyt2->demux.filternum; | ||
| 968 | cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx; | ||
| 969 | cinergyt2->dmxdev.capabilities = 0; | ||
| 970 | |||
| 971 | if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, &cinergyt2->adapter)) < 0) { | ||
| 972 | dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err); | ||
| 973 | goto bailout; | ||
| 974 | } | ||
| 975 | |||
| 976 | if (dvb_net_init(&cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx)) | ||
| 977 | dprintk(1, "dvb_net_init() failed!\n"); | ||
| 978 | |||
| 979 | dvb_register_device(&cinergyt2->adapter, &cinergyt2->fedev, | ||
| 980 | &cinergyt2_fe_template, cinergyt2, | ||
| 981 | DVB_DEVICE_FRONTEND); | ||
| 982 | |||
| 983 | err = cinergyt2_register_rc(cinergyt2); | ||
| 984 | if (err) | ||
| 985 | goto bailout; | ||
| 986 | |||
| 987 | return 0; | ||
| 988 | |||
| 989 | bailout: | ||
| 990 | dvb_net_release(&cinergyt2->dvbnet); | ||
| 991 | dvb_dmxdev_release(&cinergyt2->dmxdev); | ||
| 992 | dvb_dmx_release(&cinergyt2->demux); | ||
| 993 | dvb_unregister_adapter(&cinergyt2->adapter); | ||
| 994 | cinergyt2_free_stream_urbs(cinergyt2); | ||
| 995 | kfree(cinergyt2); | ||
| 996 | return -ENOMEM; | ||
| 997 | } | ||
| 998 | |||
| 999 | static void cinergyt2_disconnect (struct usb_interface *intf) | ||
| 1000 | { | ||
| 1001 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); | ||
| 1002 | |||
| 1003 | cinergyt2_unregister_rc(cinergyt2); | ||
| 1004 | cancel_rearming_delayed_work(&cinergyt2->query_work); | ||
| 1005 | wake_up_interruptible(&cinergyt2->poll_wq); | ||
| 1006 | |||
| 1007 | cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx); | ||
| 1008 | cinergyt2->disconnect_pending = 1; | ||
| 1009 | |||
| 1010 | if (!atomic_read(&cinergyt2->inuse)) | ||
| 1011 | cinergyt2_unregister(cinergyt2); | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state) | ||
| 1015 | { | ||
| 1016 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); | ||
| 1017 | |||
| 1018 | if (cinergyt2->disconnect_pending) | ||
| 1019 | return -EAGAIN; | ||
| 1020 | if (mutex_lock_interruptible(&cinergyt2->wq_sem)) | ||
| 1021 | return -ERESTARTSYS; | ||
| 1022 | |||
| 1023 | cinergyt2_suspend_rc(cinergyt2); | ||
| 1024 | cancel_rearming_delayed_work(&cinergyt2->query_work); | ||
| 1025 | |||
| 1026 | mutex_lock(&cinergyt2->sem); | ||
| 1027 | if (cinergyt2->streaming) | ||
| 1028 | cinergyt2_stop_stream_xfer(cinergyt2); | ||
| 1029 | cinergyt2_sleep(cinergyt2, 1); | ||
| 1030 | mutex_unlock(&cinergyt2->sem); | ||
| 1031 | |||
| 1032 | mutex_unlock(&cinergyt2->wq_sem); | ||
| 1033 | |||
| 1034 | return 0; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | static int cinergyt2_resume (struct usb_interface *intf) | ||
| 1038 | { | ||
| 1039 | struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf); | ||
| 1040 | struct dvbt_set_parameters_msg *param = &cinergyt2->param; | ||
| 1041 | int err = -EAGAIN; | ||
| 1042 | |||
| 1043 | if (cinergyt2->disconnect_pending) | ||
| 1044 | goto out; | ||
| 1045 | err = mutex_lock_interruptible(&cinergyt2->wq_sem); | ||
| 1046 | if (err) | ||
| 1047 | goto out; | ||
| 1048 | |||
| 1049 | err = mutex_lock_interruptible(&cinergyt2->sem); | ||
| 1050 | if (err) | ||
| 1051 | goto out_unlock1; | ||
| 1052 | |||
| 1053 | if (!cinergyt2->sleeping) { | ||
| 1054 | cinergyt2_sleep(cinergyt2, 0); | ||
| 1055 | cinergyt2_command(cinergyt2, (char *) param, sizeof(*param), NULL, 0); | ||
| 1056 | if (cinergyt2->streaming) | ||
| 1057 | cinergyt2_start_stream_xfer(cinergyt2); | ||
| 1058 | schedule_delayed_work(&cinergyt2->query_work, HZ/2); | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | cinergyt2_resume_rc(cinergyt2); | ||
| 1062 | |||
| 1063 | mutex_unlock(&cinergyt2->sem); | ||
| 1064 | out_unlock1: | ||
| 1065 | mutex_unlock(&cinergyt2->wq_sem); | ||
| 1066 | out: | ||
| 1067 | return err; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | static const struct usb_device_id cinergyt2_table [] __devinitdata = { | ||
| 1071 | { USB_DEVICE(0x0ccd, 0x0038) }, | ||
| 1072 | { 0 } | ||
| 1073 | }; | ||
| 1074 | |||
| 1075 | MODULE_DEVICE_TABLE(usb, cinergyt2_table); | ||
| 1076 | |||
| 1077 | static struct usb_driver cinergyt2_driver = { | ||
| 1078 | .name = "cinergyT2", | ||
| 1079 | .probe = cinergyt2_probe, | ||
| 1080 | .disconnect = cinergyt2_disconnect, | ||
| 1081 | .suspend = cinergyt2_suspend, | ||
| 1082 | .resume = cinergyt2_resume, | ||
| 1083 | .id_table = cinergyt2_table | ||
| 1084 | }; | ||
| 1085 | |||
| 1086 | static int __init cinergyt2_init (void) | ||
| 1087 | { | ||
| 1088 | int err; | ||
| 1089 | |||
| 1090 | if ((err = usb_register(&cinergyt2_driver)) < 0) | ||
| 1091 | dprintk(1, "usb_register() failed! (err %i)\n", err); | ||
| 1092 | |||
| 1093 | return err; | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | static void __exit cinergyt2_exit (void) | ||
| 1097 | { | ||
| 1098 | usb_deregister(&cinergyt2_driver); | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | module_init (cinergyt2_init); | ||
| 1102 | module_exit (cinergyt2_exit); | ||
| 1103 | |||
| 1104 | MODULE_LICENSE("GPL"); | ||
| 1105 | MODULE_AUTHOR("Holger Waechtler, Daniel Mack"); | ||
diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig new file mode 100644 index 000000000000..1332301ef3ae --- /dev/null +++ b/drivers/media/dvb/dm1105/Kconfig | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | config DVB_DM1105 | ||
| 2 | tristate "SDMC DM1105 based PCI cards" | ||
| 3 | depends on DVB_CORE && PCI && I2C | ||
| 4 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 5 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
| 6 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | ||
| 7 | select DVB_STB6000 if !DVB_FE_CUSTOMISE | ||
| 8 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | ||
| 9 | select DVB_SI21XX if !DVB_FE_CUSTOMISE | ||
| 10 | help | ||
| 11 | Support for cards based on the SDMC DM1105 PCI chip like | ||
| 12 | DvbWorld 2002 | ||
| 13 | |||
| 14 | Since these cards have no MPEG decoder onboard, they transmit | ||
| 15 | only compressed MPEG data over the PCI bus, so you need | ||
| 16 | an external software decoder to watch TV on your computer. | ||
| 17 | |||
| 18 | Say Y or M if you own such a device and want to use it. | ||
diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile new file mode 100644 index 000000000000..8ac28b0546af --- /dev/null +++ b/drivers/media/dvb/dm1105/Makefile | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | obj-$(CONFIG_DVB_DM1105) += dm1105.o | ||
| 2 | |||
| 3 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends | ||
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c new file mode 100644 index 000000000000..f7321448b4b1 --- /dev/null +++ b/drivers/media/dvb/dm1105/dm1105.c | |||
| @@ -0,0 +1,911 @@ | |||
| 1 | /* | ||
| 2 | * dm1105.c - driver for DVB cards based on SDMC DM1105 PCI chip | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/version.h> | ||
| 23 | #include <linux/i2c.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/proc_fs.h> | ||
| 28 | #include <linux/pci.h> | ||
| 29 | #include <linux/dma-mapping.h> | ||
| 30 | #include <linux/input.h> | ||
| 31 | #include <media/ir-common.h> | ||
| 32 | |||
| 33 | #include "demux.h" | ||
| 34 | #include "dmxdev.h" | ||
| 35 | #include "dvb_demux.h" | ||
| 36 | #include "dvb_frontend.h" | ||
| 37 | #include "dvb_net.h" | ||
| 38 | #include "dvbdev.h" | ||
| 39 | #include "dvb-pll.h" | ||
| 40 | |||
| 41 | #include "stv0299.h" | ||
| 42 | #include "stv0288.h" | ||
| 43 | #include "stb6000.h" | ||
| 44 | #include "si21xx.h" | ||
| 45 | #include "cx24116.h" | ||
| 46 | #include "z0194a.h" | ||
| 47 | |||
| 48 | /* ----------------------------------------------- */ | ||
| 49 | /* | ||
| 50 | * PCI ID's | ||
| 51 | */ | ||
| 52 | #ifndef PCI_VENDOR_ID_TRIGEM | ||
| 53 | #define PCI_VENDOR_ID_TRIGEM 0x109f | ||
| 54 | #endif | ||
| 55 | #ifndef PCI_DEVICE_ID_DM1105 | ||
| 56 | #define PCI_DEVICE_ID_DM1105 0x036f | ||
| 57 | #endif | ||
| 58 | #ifndef PCI_DEVICE_ID_DW2002 | ||
| 59 | #define PCI_DEVICE_ID_DW2002 0x2002 | ||
| 60 | #endif | ||
| 61 | #ifndef PCI_DEVICE_ID_DW2004 | ||
| 62 | #define PCI_DEVICE_ID_DW2004 0x2004 | ||
| 63 | #endif | ||
| 64 | /* ----------------------------------------------- */ | ||
| 65 | /* sdmc dm1105 registers */ | ||
| 66 | |||
| 67 | /* TS Control */ | ||
| 68 | #define DM1105_TSCTR 0x00 | ||
| 69 | #define DM1105_DTALENTH 0x04 | ||
| 70 | |||
| 71 | /* GPIO Interface */ | ||
| 72 | #define DM1105_GPIOVAL 0x08 | ||
| 73 | #define DM1105_GPIOCTR 0x0c | ||
| 74 | |||
| 75 | /* PID serial number */ | ||
| 76 | #define DM1105_PIDN 0x10 | ||
| 77 | |||
| 78 | /* Odd-even secret key select */ | ||
| 79 | #define DM1105_CWSEL 0x14 | ||
| 80 | |||
| 81 | /* Host Command Interface */ | ||
| 82 | #define DM1105_HOST_CTR 0x18 | ||
| 83 | #define DM1105_HOST_AD 0x1c | ||
| 84 | |||
| 85 | /* PCI Interface */ | ||
| 86 | #define DM1105_CR 0x30 | ||
| 87 | #define DM1105_RST 0x34 | ||
| 88 | #define DM1105_STADR 0x38 | ||
| 89 | #define DM1105_RLEN 0x3c | ||
| 90 | #define DM1105_WRP 0x40 | ||
| 91 | #define DM1105_INTCNT 0x44 | ||
| 92 | #define DM1105_INTMAK 0x48 | ||
| 93 | #define DM1105_INTSTS 0x4c | ||
| 94 | |||
| 95 | /* CW Value */ | ||
| 96 | #define DM1105_ODD 0x50 | ||
| 97 | #define DM1105_EVEN 0x58 | ||
| 98 | |||
| 99 | /* PID Value */ | ||
| 100 | #define DM1105_PID 0x60 | ||
| 101 | |||
| 102 | /* IR Control */ | ||
| 103 | #define DM1105_IRCTR 0x64 | ||
| 104 | #define DM1105_IRMODE 0x68 | ||
| 105 | #define DM1105_SYSTEMCODE 0x6c | ||
| 106 | #define DM1105_IRCODE 0x70 | ||
| 107 | |||
| 108 | /* Unknown Values */ | ||
| 109 | #define DM1105_ENCRYPT 0x74 | ||
| 110 | #define DM1105_VER 0x7c | ||
| 111 | |||
| 112 | /* I2C Interface */ | ||
| 113 | #define DM1105_I2CCTR 0x80 | ||
| 114 | #define DM1105_I2CSTS 0x81 | ||
| 115 | #define DM1105_I2CDAT 0x82 | ||
| 116 | #define DM1105_I2C_RA 0x83 | ||
| 117 | /* ----------------------------------------------- */ | ||
| 118 | /* Interrupt Mask Bits */ | ||
| 119 | |||
| 120 | #define INTMAK_TSIRQM 0x01 | ||
| 121 | #define INTMAK_HIRQM 0x04 | ||
| 122 | #define INTMAK_IRM 0x08 | ||
| 123 | #define INTMAK_ALLMASK (INTMAK_TSIRQM | \ | ||
| 124 | INTMAK_HIRQM | \ | ||
| 125 | INTMAK_IRM) | ||
| 126 | #define INTMAK_NONEMASK 0x00 | ||
| 127 | |||
| 128 | /* Interrupt Status Bits */ | ||
| 129 | #define INTSTS_TSIRQ 0x01 | ||
| 130 | #define INTSTS_HIRQ 0x04 | ||
| 131 | #define INTSTS_IR 0x08 | ||
| 132 | |||
| 133 | /* IR Control Bits */ | ||
| 134 | #define DM1105_IR_EN 0x01 | ||
| 135 | #define DM1105_SYS_CHK 0x02 | ||
| 136 | #define DM1105_REP_FLG 0x08 | ||
| 137 | |||
| 138 | /* EEPROM addr */ | ||
| 139 | #define IIC_24C01_addr 0xa0 | ||
| 140 | /* Max board count */ | ||
| 141 | #define DM1105_MAX 0x04 | ||
| 142 | |||
| 143 | #define DRIVER_NAME "dm1105" | ||
| 144 | |||
| 145 | #define DM1105_DMA_PACKETS 47 | ||
| 146 | #define DM1105_DMA_PACKET_LENGTH (128*4) | ||
| 147 | #define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS) | ||
| 148 | |||
| 149 | /* GPIO's for LNB power control */ | ||
| 150 | #define DM1105_LNB_MASK 0x00000000 | ||
| 151 | #define DM1105_LNB_13V 0x00010100 | ||
| 152 | #define DM1105_LNB_18V 0x00000100 | ||
| 153 | |||
| 154 | static int ir_debug; | ||
| 155 | module_param(ir_debug, int, 0644); | ||
| 156 | MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); | ||
| 157 | |||
| 158 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 159 | |||
| 160 | static u16 ir_codes_dm1105_nec[128] = { | ||
| 161 | [0x0a] = KEY_Q, /*power*/ | ||
| 162 | [0x0c] = KEY_M, /*mute*/ | ||
| 163 | [0x11] = KEY_1, | ||
| 164 | [0x12] = KEY_2, | ||
| 165 | [0x13] = KEY_3, | ||
| 166 | [0x14] = KEY_4, | ||
| 167 | [0x15] = KEY_5, | ||
| 168 | [0x16] = KEY_6, | ||
| 169 | [0x17] = KEY_7, | ||
| 170 | [0x18] = KEY_8, | ||
| 171 | [0x19] = KEY_9, | ||
| 172 | [0x10] = KEY_0, | ||
| 173 | [0x1c] = KEY_PAGEUP, /*ch+*/ | ||
| 174 | [0x0f] = KEY_PAGEDOWN, /*ch-*/ | ||
| 175 | [0x1a] = KEY_O, /*vol+*/ | ||
| 176 | [0x0e] = KEY_Z, /*vol-*/ | ||
| 177 | [0x04] = KEY_R, /*rec*/ | ||
| 178 | [0x09] = KEY_D, /*fav*/ | ||
| 179 | [0x08] = KEY_BACKSPACE, /*rewind*/ | ||
| 180 | [0x07] = KEY_A, /*fast*/ | ||
| 181 | [0x0b] = KEY_P, /*pause*/ | ||
| 182 | [0x02] = KEY_ESC, /*cancel*/ | ||
| 183 | [0x03] = KEY_G, /*tab*/ | ||
| 184 | [0x00] = KEY_UP, /*up*/ | ||
| 185 | [0x1f] = KEY_ENTER, /*ok*/ | ||
| 186 | [0x01] = KEY_DOWN, /*down*/ | ||
| 187 | [0x05] = KEY_C, /*cap*/ | ||
| 188 | [0x06] = KEY_S, /*stop*/ | ||
| 189 | [0x40] = KEY_F, /*full*/ | ||
| 190 | [0x1e] = KEY_W, /*tvmode*/ | ||
| 191 | [0x1b] = KEY_B, /*recall*/ | ||
| 192 | }; | ||
| 193 | |||
| 194 | /* infrared remote control */ | ||
| 195 | struct infrared { | ||
| 196 | u16 key_map[128]; | ||
| 197 | struct input_dev *input_dev; | ||
| 198 | char input_phys[32]; | ||
| 199 | struct tasklet_struct ir_tasklet; | ||
| 200 | u32 ir_command; | ||
| 201 | }; | ||
| 202 | |||
| 203 | struct dm1105dvb { | ||
| 204 | /* pci */ | ||
| 205 | struct pci_dev *pdev; | ||
| 206 | u8 __iomem *io_mem; | ||
| 207 | |||
| 208 | /* ir */ | ||
| 209 | struct infrared ir; | ||
| 210 | |||
| 211 | /* dvb */ | ||
| 212 | struct dmx_frontend hw_frontend; | ||
| 213 | struct dmx_frontend mem_frontend; | ||
| 214 | struct dmxdev dmxdev; | ||
| 215 | struct dvb_adapter dvb_adapter; | ||
| 216 | struct dvb_demux demux; | ||
| 217 | struct dvb_frontend *fe; | ||
| 218 | struct dvb_net dvbnet; | ||
| 219 | unsigned int full_ts_users; | ||
| 220 | |||
| 221 | /* i2c */ | ||
| 222 | struct i2c_adapter i2c_adap; | ||
| 223 | |||
| 224 | /* dma */ | ||
| 225 | dma_addr_t dma_addr; | ||
| 226 | unsigned char *ts_buf; | ||
| 227 | u32 wrp; | ||
| 228 | u32 buffer_size; | ||
| 229 | unsigned int PacketErrorCount; | ||
| 230 | unsigned int dmarst; | ||
| 231 | spinlock_t lock; | ||
| 232 | |||
| 233 | }; | ||
| 234 | |||
| 235 | #define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg])) | ||
| 236 | |||
| 237 | static struct dm1105dvb *dm1105dvb_local; | ||
| 238 | |||
| 239 | static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, | ||
| 240 | struct i2c_msg *msgs, int num) | ||
| 241 | { | ||
| 242 | struct dm1105dvb *dm1105dvb ; | ||
| 243 | |||
| 244 | int addr, rc, i, j, k, len, byte, data; | ||
| 245 | u8 status; | ||
| 246 | |||
| 247 | dm1105dvb = i2c_adap->algo_data; | ||
| 248 | for (i = 0; i < num; i++) { | ||
| 249 | outb(0x00, dm_io_mem(DM1105_I2CCTR)); | ||
| 250 | if (msgs[i].flags & I2C_M_RD) { | ||
| 251 | /* read bytes */ | ||
| 252 | addr = msgs[i].addr << 1; | ||
| 253 | addr |= 1; | ||
| 254 | outb(addr, dm_io_mem(DM1105_I2CDAT)); | ||
| 255 | for (byte = 0; byte < msgs[i].len; byte++) | ||
| 256 | outb(0, dm_io_mem(DM1105_I2CDAT + byte + 1)); | ||
| 257 | |||
| 258 | outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR)); | ||
| 259 | for (j = 0; j < 55; j++) { | ||
| 260 | mdelay(10); | ||
| 261 | status = inb(dm_io_mem(DM1105_I2CSTS)); | ||
| 262 | if ((status & 0xc0) == 0x40) | ||
| 263 | break; | ||
| 264 | } | ||
| 265 | if (j >= 55) | ||
| 266 | return -1; | ||
| 267 | |||
| 268 | for (byte = 0; byte < msgs[i].len; byte++) { | ||
| 269 | rc = inb(dm_io_mem(DM1105_I2CDAT + byte + 1)); | ||
| 270 | if (rc < 0) | ||
| 271 | goto err; | ||
| 272 | msgs[i].buf[byte] = rc; | ||
| 273 | } | ||
| 274 | } else { | ||
| 275 | if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) { | ||
| 276 | /* prepaired for cx24116 firmware */ | ||
| 277 | /* Write in small blocks */ | ||
| 278 | len = msgs[i].len - 1; | ||
| 279 | k = 1; | ||
| 280 | do { | ||
| 281 | outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT)); | ||
| 282 | outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1)); | ||
| 283 | for (byte = 0; byte < (len > 48 ? 48 : len); byte++) { | ||
| 284 | data = msgs[i].buf[k+byte]; | ||
| 285 | outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2)); | ||
| 286 | } | ||
| 287 | outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR)); | ||
| 288 | for (j = 0; j < 25; j++) { | ||
| 289 | mdelay(10); | ||
| 290 | status = inb(dm_io_mem(DM1105_I2CSTS)); | ||
| 291 | if ((status & 0xc0) == 0x40) | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | |||
| 295 | if (j >= 25) | ||
| 296 | return -1; | ||
| 297 | |||
| 298 | k += 48; | ||
| 299 | len -= 48; | ||
| 300 | } while (len > 0); | ||
| 301 | } else { | ||
| 302 | /* write bytes */ | ||
| 303 | outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT)); | ||
| 304 | for (byte = 0; byte < msgs[i].len; byte++) { | ||
| 305 | data = msgs[i].buf[byte]; | ||
| 306 | outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1)); | ||
| 307 | } | ||
| 308 | outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR)); | ||
| 309 | for (j = 0; j < 25; j++) { | ||
| 310 | mdelay(10); | ||
| 311 | status = inb(dm_io_mem(DM1105_I2CSTS)); | ||
| 312 | if ((status & 0xc0) == 0x40) | ||
| 313 | break; | ||
| 314 | } | ||
| 315 | |||
| 316 | if (j >= 25) | ||
| 317 | return -1; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | } | ||
| 321 | return num; | ||
| 322 | err: | ||
| 323 | return rc; | ||
| 324 | } | ||
| 325 | |||
| 326 | static u32 functionality(struct i2c_adapter *adap) | ||
| 327 | { | ||
| 328 | return I2C_FUNC_I2C; | ||
| 329 | } | ||
| 330 | |||
| 331 | static struct i2c_algorithm dm1105_algo = { | ||
| 332 | .master_xfer = dm1105_i2c_xfer, | ||
| 333 | .functionality = functionality, | ||
| 334 | }; | ||
| 335 | |||
| 336 | static inline struct dm1105dvb *feed_to_dm1105dvb(struct dvb_demux_feed *feed) | ||
| 337 | { | ||
| 338 | return container_of(feed->demux, struct dm1105dvb, demux); | ||
| 339 | } | ||
| 340 | |||
| 341 | static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe) | ||
| 342 | { | ||
| 343 | return container_of(fe->dvb, struct dm1105dvb, dvb_adapter); | ||
| 344 | } | ||
| 345 | |||
| 346 | static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
| 347 | { | ||
| 348 | struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe); | ||
| 349 | |||
| 350 | if (voltage == SEC_VOLTAGE_18) { | ||
| 351 | outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR)); | ||
| 352 | outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL)); | ||
| 353 | } else { | ||
| 354 | /*LNB ON-13V by default!*/ | ||
| 355 | outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR)); | ||
| 356 | outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL)); | ||
| 357 | } | ||
| 358 | |||
| 359 | return 0; | ||
| 360 | } | ||
| 361 | |||
| 362 | static void dm1105dvb_set_dma_addr(struct dm1105dvb *dm1105dvb) | ||
| 363 | { | ||
| 364 | outl(cpu_to_le32(dm1105dvb->dma_addr), dm_io_mem(DM1105_STADR)); | ||
| 365 | } | ||
| 366 | |||
| 367 | static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb) | ||
| 368 | { | ||
| 369 | dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr); | ||
| 370 | |||
| 371 | return pci_dma_mapping_error(dm1105dvb->pdev, dm1105dvb->dma_addr); | ||
| 372 | } | ||
| 373 | |||
| 374 | static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb) | ||
| 375 | { | ||
| 376 | pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr); | ||
| 377 | } | ||
| 378 | |||
| 379 | static void __devinit dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb) | ||
| 380 | { | ||
| 381 | outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK)); | ||
| 382 | outb(1, dm_io_mem(DM1105_CR)); | ||
| 383 | } | ||
| 384 | |||
| 385 | static void dm1105dvb_disable_irqs(struct dm1105dvb *dm1105dvb) | ||
| 386 | { | ||
| 387 | outb(INTMAK_IRM, dm_io_mem(DM1105_INTMAK)); | ||
| 388 | outb(0, dm_io_mem(DM1105_CR)); | ||
| 389 | } | ||
| 390 | |||
| 391 | static int dm1105dvb_start_feed(struct dvb_demux_feed *f) | ||
| 392 | { | ||
| 393 | struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f); | ||
| 394 | |||
| 395 | if (dm1105dvb->full_ts_users++ == 0) | ||
| 396 | dm1105dvb_enable_irqs(dm1105dvb); | ||
| 397 | |||
| 398 | return 0; | ||
| 399 | } | ||
| 400 | |||
| 401 | static int dm1105dvb_stop_feed(struct dvb_demux_feed *f) | ||
| 402 | { | ||
| 403 | struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f); | ||
| 404 | |||
| 405 | if (--dm1105dvb->full_ts_users == 0) | ||
| 406 | dm1105dvb_disable_irqs(dm1105dvb); | ||
| 407 | |||
| 408 | return 0; | ||
| 409 | } | ||
| 410 | |||
| 411 | /* ir tasklet */ | ||
| 412 | static void dm1105_emit_key(unsigned long parm) | ||
| 413 | { | ||
| 414 | struct infrared *ir = (struct infrared *) parm; | ||
| 415 | u32 ircom = ir->ir_command; | ||
| 416 | u8 data; | ||
| 417 | u16 keycode; | ||
| 418 | |||
| 419 | data = (ircom >> 8) & 0x7f; | ||
| 420 | |||
| 421 | input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data); | ||
| 422 | input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); | ||
| 423 | keycode = ir->key_map[data]; | ||
| 424 | |||
| 425 | if (!keycode) | ||
| 426 | return; | ||
| 427 | |||
| 428 | input_event(ir->input_dev, EV_KEY, keycode, 1); | ||
| 429 | input_sync(ir->input_dev); | ||
| 430 | input_event(ir->input_dev, EV_KEY, keycode, 0); | ||
| 431 | input_sync(ir->input_dev); | ||
| 432 | |||
| 433 | } | ||
| 434 | |||
| 435 | static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) | ||
| 436 | { | ||
| 437 | struct dm1105dvb *dm1105dvb = dev_id; | ||
| 438 | unsigned int piece; | ||
| 439 | unsigned int nbpackets; | ||
| 440 | u32 command; | ||
| 441 | u32 nextwrp; | ||
| 442 | u32 oldwrp; | ||
| 443 | |||
| 444 | /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */ | ||
| 445 | unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS)); | ||
| 446 | outb(intsts, dm_io_mem(DM1105_INTSTS)); | ||
| 447 | |||
| 448 | switch (intsts) { | ||
| 449 | case INTSTS_TSIRQ: | ||
| 450 | case (INTSTS_TSIRQ | INTSTS_IR): | ||
| 451 | nextwrp = inl(dm_io_mem(DM1105_WRP)) - | ||
| 452 | inl(dm_io_mem(DM1105_STADR)) ; | ||
| 453 | oldwrp = dm1105dvb->wrp; | ||
| 454 | spin_lock(&dm1105dvb->lock); | ||
| 455 | if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) && | ||
| 456 | (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) && | ||
| 457 | (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) { | ||
| 458 | dm1105dvb->PacketErrorCount++; | ||
| 459 | /* bad packet found */ | ||
| 460 | if ((dm1105dvb->PacketErrorCount >= 2) && | ||
| 461 | (dm1105dvb->dmarst == 0)) { | ||
| 462 | outb(1, dm_io_mem(DM1105_RST)); | ||
| 463 | dm1105dvb->wrp = 0; | ||
| 464 | dm1105dvb->PacketErrorCount = 0; | ||
| 465 | dm1105dvb->dmarst = 0; | ||
| 466 | spin_unlock(&dm1105dvb->lock); | ||
| 467 | return IRQ_HANDLED; | ||
| 468 | } | ||
| 469 | } | ||
| 470 | if (nextwrp < oldwrp) { | ||
| 471 | piece = dm1105dvb->buffer_size - oldwrp; | ||
| 472 | memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp); | ||
| 473 | nbpackets = (piece + nextwrp)/188; | ||
| 474 | } else { | ||
| 475 | nbpackets = (nextwrp - oldwrp)/188; | ||
| 476 | } | ||
| 477 | dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], nbpackets); | ||
| 478 | dm1105dvb->wrp = nextwrp; | ||
| 479 | spin_unlock(&dm1105dvb->lock); | ||
| 480 | break; | ||
| 481 | case INTSTS_IR: | ||
| 482 | command = inl(dm_io_mem(DM1105_IRCODE)); | ||
| 483 | if (ir_debug) | ||
| 484 | printk("dm1105: received byte 0x%04x\n", command); | ||
| 485 | |||
| 486 | dm1105dvb->ir.ir_command = command; | ||
| 487 | tasklet_schedule(&dm1105dvb->ir.ir_tasklet); | ||
| 488 | break; | ||
| 489 | } | ||
| 490 | return IRQ_HANDLED; | ||
| 491 | |||
| 492 | |||
| 493 | } | ||
| 494 | |||
| 495 | /* register with input layer */ | ||
| 496 | static void input_register_keys(struct infrared *ir) | ||
| 497 | { | ||
| 498 | int i; | ||
| 499 | |||
| 500 | memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); | ||
| 501 | |||
| 502 | for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) | ||
| 503 | set_bit(ir->key_map[i], ir->input_dev->keybit); | ||
| 504 | |||
| 505 | ir->input_dev->keycode = ir->key_map; | ||
| 506 | ir->input_dev->keycodesize = sizeof(ir->key_map[0]); | ||
| 507 | ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); | ||
| 508 | } | ||
| 509 | |||
| 510 | int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) | ||
| 511 | { | ||
| 512 | struct input_dev *input_dev; | ||
| 513 | int err; | ||
| 514 | |||
| 515 | dm1105dvb_local = dm1105; | ||
| 516 | |||
| 517 | input_dev = input_allocate_device(); | ||
| 518 | if (!input_dev) | ||
| 519 | return -ENOMEM; | ||
| 520 | |||
| 521 | dm1105->ir.input_dev = input_dev; | ||
| 522 | snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), | ||
| 523 | "pci-%s/ir0", pci_name(dm1105->pdev)); | ||
| 524 | |||
| 525 | input_dev->evbit[0] = BIT(EV_KEY); | ||
| 526 | input_dev->name = "DVB on-card IR receiver"; | ||
| 527 | |||
| 528 | input_dev->phys = dm1105->ir.input_phys; | ||
| 529 | input_dev->id.bustype = BUS_PCI; | ||
| 530 | input_dev->id.version = 2; | ||
| 531 | if (dm1105->pdev->subsystem_vendor) { | ||
| 532 | input_dev->id.vendor = dm1105->pdev->subsystem_vendor; | ||
| 533 | input_dev->id.product = dm1105->pdev->subsystem_device; | ||
| 534 | } else { | ||
| 535 | input_dev->id.vendor = dm1105->pdev->vendor; | ||
| 536 | input_dev->id.product = dm1105->pdev->device; | ||
| 537 | } | ||
| 538 | input_dev->dev.parent = &dm1105->pdev->dev; | ||
| 539 | /* initial keymap */ | ||
| 540 | memcpy(dm1105->ir.key_map, ir_codes_dm1105_nec, sizeof dm1105->ir.key_map); | ||
| 541 | input_register_keys(&dm1105->ir); | ||
| 542 | err = input_register_device(input_dev); | ||
| 543 | if (err) { | ||
| 544 | input_free_device(input_dev); | ||
| 545 | return err; | ||
| 546 | } | ||
| 547 | |||
| 548 | tasklet_init(&dm1105->ir.ir_tasklet, dm1105_emit_key, (unsigned long) &dm1105->ir); | ||
| 549 | |||
| 550 | return 0; | ||
| 551 | } | ||
| 552 | |||
| 553 | |||
| 554 | void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) | ||
| 555 | { | ||
| 556 | tasklet_kill(&dm1105->ir.ir_tasklet); | ||
| 557 | input_unregister_device(dm1105->ir.input_dev); | ||
| 558 | |||
| 559 | } | ||
| 560 | |||
| 561 | static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb) | ||
| 562 | { | ||
| 563 | dm1105dvb_disable_irqs(dm1105dvb); | ||
| 564 | |||
| 565 | outb(0, dm_io_mem(DM1105_HOST_CTR)); | ||
| 566 | |||
| 567 | /*DATALEN 188,*/ | ||
| 568 | outb(188, dm_io_mem(DM1105_DTALENTH)); | ||
| 569 | /*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/ | ||
| 570 | outw(0xc10a, dm_io_mem(DM1105_TSCTR)); | ||
| 571 | |||
| 572 | /* map DMA and set address */ | ||
| 573 | dm1105dvb_dma_map(dm1105dvb); | ||
| 574 | dm1105dvb_set_dma_addr(dm1105dvb); | ||
| 575 | /* big buffer */ | ||
| 576 | outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN)); | ||
| 577 | outb(47, dm_io_mem(DM1105_INTCNT)); | ||
| 578 | |||
| 579 | /* IR NEC mode enable */ | ||
| 580 | outb((DM1105_IR_EN | DM1105_SYS_CHK), dm_io_mem(DM1105_IRCTR)); | ||
| 581 | outb(0, dm_io_mem(DM1105_IRMODE)); | ||
| 582 | outw(0, dm_io_mem(DM1105_SYSTEMCODE)); | ||
| 583 | |||
| 584 | return 0; | ||
| 585 | } | ||
| 586 | |||
| 587 | static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb) | ||
| 588 | { | ||
| 589 | dm1105dvb_disable_irqs(dm1105dvb); | ||
| 590 | |||
| 591 | /* IR disable */ | ||
| 592 | outb(0, dm_io_mem(DM1105_IRCTR)); | ||
| 593 | outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK)); | ||
| 594 | |||
| 595 | dm1105dvb_dma_unmap(dm1105dvb); | ||
| 596 | } | ||
| 597 | |||
| 598 | static struct stv0288_config earda_config = { | ||
| 599 | .demod_address = 0x68, | ||
| 600 | .min_delay_ms = 100, | ||
| 601 | }; | ||
| 602 | |||
| 603 | static struct si21xx_config serit_config = { | ||
| 604 | .demod_address = 0x68, | ||
| 605 | .min_delay_ms = 100, | ||
| 606 | |||
| 607 | }; | ||
| 608 | |||
| 609 | static struct cx24116_config serit_sp2633_config = { | ||
| 610 | .demod_address = 0x55, | ||
| 611 | }; | ||
| 612 | |||
| 613 | static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) | ||
| 614 | { | ||
| 615 | int ret; | ||
| 616 | |||
| 617 | switch (dm1105dvb->pdev->subsystem_device) { | ||
| 618 | case PCI_DEVICE_ID_DW2002: | ||
| 619 | dm1105dvb->fe = dvb_attach( | ||
| 620 | stv0299_attach, &sharp_z0194a_config, | ||
| 621 | &dm1105dvb->i2c_adap); | ||
| 622 | |||
| 623 | if (dm1105dvb->fe) { | ||
| 624 | dm1105dvb->fe->ops.set_voltage = | ||
| 625 | dm1105dvb_set_voltage; | ||
| 626 | dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60, | ||
| 627 | &dm1105dvb->i2c_adap, DVB_PLL_OPERA1); | ||
| 628 | } | ||
| 629 | |||
| 630 | if (!dm1105dvb->fe) { | ||
| 631 | dm1105dvb->fe = dvb_attach( | ||
| 632 | stv0288_attach, &earda_config, | ||
| 633 | &dm1105dvb->i2c_adap); | ||
| 634 | if (dm1105dvb->fe) { | ||
| 635 | dm1105dvb->fe->ops.set_voltage = | ||
| 636 | dm1105dvb_set_voltage; | ||
| 637 | dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61, | ||
| 638 | &dm1105dvb->i2c_adap); | ||
| 639 | } | ||
| 640 | } | ||
| 641 | |||
| 642 | if (!dm1105dvb->fe) { | ||
| 643 | dm1105dvb->fe = dvb_attach( | ||
| 644 | si21xx_attach, &serit_config, | ||
| 645 | &dm1105dvb->i2c_adap); | ||
| 646 | if (dm1105dvb->fe) | ||
| 647 | dm1105dvb->fe->ops.set_voltage = | ||
| 648 | dm1105dvb_set_voltage; | ||
| 649 | } | ||
| 650 | break; | ||
| 651 | case PCI_DEVICE_ID_DW2004: | ||
| 652 | dm1105dvb->fe = dvb_attach( | ||
| 653 | cx24116_attach, &serit_sp2633_config, | ||
| 654 | &dm1105dvb->i2c_adap); | ||
| 655 | if (dm1105dvb->fe) | ||
| 656 | dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; | ||
| 657 | break; | ||
| 658 | } | ||
| 659 | |||
| 660 | if (!dm1105dvb->fe) { | ||
| 661 | dev_err(&dm1105dvb->pdev->dev, "could not attach frontend\n"); | ||
| 662 | return -ENODEV; | ||
| 663 | } | ||
| 664 | |||
| 665 | ret = dvb_register_frontend(&dm1105dvb->dvb_adapter, dm1105dvb->fe); | ||
| 666 | if (ret < 0) { | ||
| 667 | if (dm1105dvb->fe->ops.release) | ||
| 668 | dm1105dvb->fe->ops.release(dm1105dvb->fe); | ||
| 669 | dm1105dvb->fe = NULL; | ||
| 670 | return ret; | ||
| 671 | } | ||
| 672 | |||
| 673 | return 0; | ||
| 674 | } | ||
| 675 | |||
| 676 | static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac) | ||
| 677 | { | ||
| 678 | static u8 command[1] = { 0x28 }; | ||
| 679 | |||
| 680 | struct i2c_msg msg[] = { | ||
| 681 | { .addr = IIC_24C01_addr >> 1, .flags = 0, | ||
| 682 | .buf = command, .len = 1 }, | ||
| 683 | { .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD, | ||
| 684 | .buf = mac, .len = 6 }, | ||
| 685 | }; | ||
| 686 | |||
| 687 | dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2); | ||
| 688 | dev_info(&dm1105dvb->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
| 689 | mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); | ||
| 690 | } | ||
| 691 | |||
| 692 | static int __devinit dm1105_probe(struct pci_dev *pdev, | ||
| 693 | const struct pci_device_id *ent) | ||
| 694 | { | ||
| 695 | struct dm1105dvb *dm1105dvb; | ||
| 696 | struct dvb_adapter *dvb_adapter; | ||
| 697 | struct dvb_demux *dvbdemux; | ||
| 698 | struct dmx_demux *dmx; | ||
| 699 | int ret = -ENOMEM; | ||
| 700 | |||
| 701 | dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL); | ||
| 702 | if (!dm1105dvb) | ||
| 703 | goto out; | ||
| 704 | |||
| 705 | dm1105dvb->pdev = pdev; | ||
| 706 | dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES; | ||
| 707 | dm1105dvb->PacketErrorCount = 0; | ||
| 708 | dm1105dvb->dmarst = 0; | ||
| 709 | |||
| 710 | ret = pci_enable_device(pdev); | ||
| 711 | if (ret < 0) | ||
| 712 | goto err_kfree; | ||
| 713 | |||
| 714 | ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | ||
| 715 | if (ret < 0) | ||
| 716 | goto err_pci_disable_device; | ||
| 717 | |||
| 718 | pci_set_master(pdev); | ||
| 719 | |||
| 720 | ret = pci_request_regions(pdev, DRIVER_NAME); | ||
| 721 | if (ret < 0) | ||
| 722 | goto err_pci_disable_device; | ||
| 723 | |||
| 724 | dm1105dvb->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); | ||
| 725 | if (!dm1105dvb->io_mem) { | ||
| 726 | ret = -EIO; | ||
| 727 | goto err_pci_release_regions; | ||
| 728 | } | ||
| 729 | |||
| 730 | spin_lock_init(&dm1105dvb->lock); | ||
| 731 | pci_set_drvdata(pdev, dm1105dvb); | ||
| 732 | |||
| 733 | ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb); | ||
| 734 | if (ret < 0) | ||
| 735 | goto err_pci_iounmap; | ||
| 736 | |||
| 737 | ret = dm1105dvb_hw_init(dm1105dvb); | ||
| 738 | if (ret < 0) | ||
| 739 | goto err_free_irq; | ||
| 740 | |||
| 741 | /* i2c */ | ||
| 742 | i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb); | ||
| 743 | strcpy(dm1105dvb->i2c_adap.name, DRIVER_NAME); | ||
| 744 | dm1105dvb->i2c_adap.owner = THIS_MODULE; | ||
| 745 | dm1105dvb->i2c_adap.class = I2C_CLASS_TV_DIGITAL; | ||
| 746 | dm1105dvb->i2c_adap.dev.parent = &pdev->dev; | ||
| 747 | dm1105dvb->i2c_adap.algo = &dm1105_algo; | ||
| 748 | dm1105dvb->i2c_adap.algo_data = dm1105dvb; | ||
| 749 | ret = i2c_add_adapter(&dm1105dvb->i2c_adap); | ||
| 750 | |||
| 751 | if (ret < 0) | ||
| 752 | goto err_dm1105dvb_hw_exit; | ||
| 753 | |||
| 754 | /* dvb */ | ||
| 755 | ret = dvb_register_adapter(&dm1105dvb->dvb_adapter, DRIVER_NAME, | ||
| 756 | THIS_MODULE, &pdev->dev, adapter_nr); | ||
| 757 | if (ret < 0) | ||
| 758 | goto err_i2c_del_adapter; | ||
| 759 | |||
| 760 | dvb_adapter = &dm1105dvb->dvb_adapter; | ||
| 761 | |||
| 762 | dm1105dvb_read_mac(dm1105dvb, dvb_adapter->proposed_mac); | ||
| 763 | |||
| 764 | dvbdemux = &dm1105dvb->demux; | ||
| 765 | dvbdemux->filternum = 256; | ||
| 766 | dvbdemux->feednum = 256; | ||
| 767 | dvbdemux->start_feed = dm1105dvb_start_feed; | ||
| 768 | dvbdemux->stop_feed = dm1105dvb_stop_feed; | ||
| 769 | dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | | ||
| 770 | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); | ||
| 771 | ret = dvb_dmx_init(dvbdemux); | ||
| 772 | if (ret < 0) | ||
| 773 | goto err_dvb_unregister_adapter; | ||
| 774 | |||
| 775 | dmx = &dvbdemux->dmx; | ||
| 776 | dm1105dvb->dmxdev.filternum = 256; | ||
| 777 | dm1105dvb->dmxdev.demux = dmx; | ||
| 778 | dm1105dvb->dmxdev.capabilities = 0; | ||
| 779 | |||
| 780 | ret = dvb_dmxdev_init(&dm1105dvb->dmxdev, dvb_adapter); | ||
| 781 | if (ret < 0) | ||
| 782 | goto err_dvb_dmx_release; | ||
| 783 | |||
| 784 | dm1105dvb->hw_frontend.source = DMX_FRONTEND_0; | ||
| 785 | |||
| 786 | ret = dmx->add_frontend(dmx, &dm1105dvb->hw_frontend); | ||
| 787 | if (ret < 0) | ||
| 788 | goto err_dvb_dmxdev_release; | ||
| 789 | |||
| 790 | dm1105dvb->mem_frontend.source = DMX_MEMORY_FE; | ||
| 791 | |||
| 792 | ret = dmx->add_frontend(dmx, &dm1105dvb->mem_frontend); | ||
| 793 | if (ret < 0) | ||
| 794 | goto err_remove_hw_frontend; | ||
| 795 | |||
| 796 | ret = dmx->connect_frontend(dmx, &dm1105dvb->hw_frontend); | ||
| 797 | if (ret < 0) | ||
| 798 | goto err_remove_mem_frontend; | ||
| 799 | |||
| 800 | ret = frontend_init(dm1105dvb); | ||
| 801 | if (ret < 0) | ||
| 802 | goto err_disconnect_frontend; | ||
| 803 | |||
| 804 | dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx); | ||
| 805 | dm1105_ir_init(dm1105dvb); | ||
| 806 | out: | ||
| 807 | return ret; | ||
| 808 | |||
| 809 | err_disconnect_frontend: | ||
| 810 | dmx->disconnect_frontend(dmx); | ||
| 811 | err_remove_mem_frontend: | ||
| 812 | dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend); | ||
| 813 | err_remove_hw_frontend: | ||
| 814 | dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend); | ||
| 815 | err_dvb_dmxdev_release: | ||
| 816 | dvb_dmxdev_release(&dm1105dvb->dmxdev); | ||
| 817 | err_dvb_dmx_release: | ||
| 818 | dvb_dmx_release(dvbdemux); | ||
| 819 | err_dvb_unregister_adapter: | ||
| 820 | dvb_unregister_adapter(dvb_adapter); | ||
| 821 | err_i2c_del_adapter: | ||
| 822 | i2c_del_adapter(&dm1105dvb->i2c_adap); | ||
| 823 | err_dm1105dvb_hw_exit: | ||
| 824 | dm1105dvb_hw_exit(dm1105dvb); | ||
| 825 | err_free_irq: | ||
| 826 | free_irq(pdev->irq, dm1105dvb); | ||
| 827 | err_pci_iounmap: | ||
| 828 | pci_iounmap(pdev, dm1105dvb->io_mem); | ||
| 829 | err_pci_release_regions: | ||
| 830 | pci_release_regions(pdev); | ||
| 831 | err_pci_disable_device: | ||
| 832 | pci_disable_device(pdev); | ||
| 833 | err_kfree: | ||
| 834 | pci_set_drvdata(pdev, NULL); | ||
| 835 | kfree(dm1105dvb); | ||
| 836 | goto out; | ||
| 837 | } | ||
| 838 | |||
| 839 | static void __devexit dm1105_remove(struct pci_dev *pdev) | ||
| 840 | { | ||
| 841 | struct dm1105dvb *dm1105dvb = pci_get_drvdata(pdev); | ||
| 842 | struct dvb_adapter *dvb_adapter = &dm1105dvb->dvb_adapter; | ||
| 843 | struct dvb_demux *dvbdemux = &dm1105dvb->demux; | ||
| 844 | struct dmx_demux *dmx = &dvbdemux->dmx; | ||
| 845 | |||
| 846 | dm1105_ir_exit(dm1105dvb); | ||
| 847 | dmx->close(dmx); | ||
| 848 | dvb_net_release(&dm1105dvb->dvbnet); | ||
| 849 | if (dm1105dvb->fe) | ||
| 850 | dvb_unregister_frontend(dm1105dvb->fe); | ||
| 851 | |||
| 852 | dmx->disconnect_frontend(dmx); | ||
| 853 | dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend); | ||
| 854 | dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend); | ||
| 855 | dvb_dmxdev_release(&dm1105dvb->dmxdev); | ||
| 856 | dvb_dmx_release(dvbdemux); | ||
| 857 | dvb_unregister_adapter(dvb_adapter); | ||
| 858 | if (&dm1105dvb->i2c_adap) | ||
| 859 | i2c_del_adapter(&dm1105dvb->i2c_adap); | ||
| 860 | |||
| 861 | dm1105dvb_hw_exit(dm1105dvb); | ||
| 862 | synchronize_irq(pdev->irq); | ||
| 863 | free_irq(pdev->irq, dm1105dvb); | ||
| 864 | pci_iounmap(pdev, dm1105dvb->io_mem); | ||
| 865 | pci_release_regions(pdev); | ||
| 866 | pci_disable_device(pdev); | ||
| 867 | pci_set_drvdata(pdev, NULL); | ||
| 868 | kfree(dm1105dvb); | ||
| 869 | } | ||
| 870 | |||
| 871 | static struct pci_device_id dm1105_id_table[] __devinitdata = { | ||
| 872 | { | ||
| 873 | .vendor = PCI_VENDOR_ID_TRIGEM, | ||
| 874 | .device = PCI_DEVICE_ID_DM1105, | ||
| 875 | .subvendor = PCI_ANY_ID, | ||
| 876 | .subdevice = PCI_DEVICE_ID_DW2002, | ||
| 877 | }, { | ||
| 878 | .vendor = PCI_VENDOR_ID_TRIGEM, | ||
| 879 | .device = PCI_DEVICE_ID_DM1105, | ||
| 880 | .subvendor = PCI_ANY_ID, | ||
| 881 | .subdevice = PCI_DEVICE_ID_DW2004, | ||
| 882 | }, { | ||
| 883 | /* empty */ | ||
| 884 | }, | ||
| 885 | }; | ||
| 886 | |||
| 887 | MODULE_DEVICE_TABLE(pci, dm1105_id_table); | ||
| 888 | |||
| 889 | static struct pci_driver dm1105_driver = { | ||
| 890 | .name = DRIVER_NAME, | ||
| 891 | .id_table = dm1105_id_table, | ||
| 892 | .probe = dm1105_probe, | ||
| 893 | .remove = __devexit_p(dm1105_remove), | ||
| 894 | }; | ||
| 895 | |||
| 896 | static int __init dm1105_init(void) | ||
| 897 | { | ||
| 898 | return pci_register_driver(&dm1105_driver); | ||
| 899 | } | ||
| 900 | |||
| 901 | static void __exit dm1105_exit(void) | ||
| 902 | { | ||
| 903 | pci_unregister_driver(&dm1105_driver); | ||
| 904 | } | ||
| 905 | |||
| 906 | module_init(dm1105_init); | ||
| 907 | module_exit(dm1105_exit); | ||
| 908 | |||
| 909 | MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>"); | ||
| 910 | MODULE_DESCRIPTION("SDMC DM1105 DVB driver"); | ||
| 911 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 3526e3ee9487..f170e822fadc 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | 40 | ||
| 41 | #include "dvb_frontend.h" | 41 | #include "dvb_frontend.h" |
| 42 | #include "dvbdev.h" | 42 | #include "dvbdev.h" |
| 43 | #include <linux/dvb/version.h> | ||
| 43 | 44 | ||
| 44 | static int dvb_frontend_debug; | 45 | static int dvb_frontend_debug; |
| 45 | static int dvb_shutdown_timeout; | 46 | static int dvb_shutdown_timeout; |
| @@ -755,6 +756,539 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, | |||
| 755 | return 0; | 756 | return 0; |
| 756 | } | 757 | } |
| 757 | 758 | ||
| 759 | struct dtv_cmds_h dtv_cmds[] = { | ||
| 760 | [DTV_TUNE] = { | ||
| 761 | .name = "DTV_TUNE", | ||
| 762 | .cmd = DTV_TUNE, | ||
| 763 | .set = 1, | ||
| 764 | }, | ||
| 765 | [DTV_CLEAR] = { | ||
| 766 | .name = "DTV_CLEAR", | ||
| 767 | .cmd = DTV_CLEAR, | ||
| 768 | .set = 1, | ||
| 769 | }, | ||
| 770 | |||
| 771 | /* Set */ | ||
| 772 | [DTV_FREQUENCY] = { | ||
| 773 | .name = "DTV_FREQUENCY", | ||
| 774 | .cmd = DTV_FREQUENCY, | ||
| 775 | .set = 1, | ||
| 776 | }, | ||
| 777 | [DTV_BANDWIDTH_HZ] = { | ||
| 778 | .name = "DTV_BANDWIDTH_HZ", | ||
| 779 | .cmd = DTV_BANDWIDTH_HZ, | ||
| 780 | .set = 1, | ||
| 781 | }, | ||
| 782 | [DTV_MODULATION] = { | ||
| 783 | .name = "DTV_MODULATION", | ||
| 784 | .cmd = DTV_MODULATION, | ||
| 785 | .set = 1, | ||
| 786 | }, | ||
| 787 | [DTV_INVERSION] = { | ||
| 788 | .name = "DTV_INVERSION", | ||
| 789 | .cmd = DTV_INVERSION, | ||
| 790 | .set = 1, | ||
| 791 | }, | ||
| 792 | [DTV_DISEQC_MASTER] = { | ||
| 793 | .name = "DTV_DISEQC_MASTER", | ||
| 794 | .cmd = DTV_DISEQC_MASTER, | ||
| 795 | .set = 1, | ||
| 796 | .buffer = 1, | ||
| 797 | }, | ||
| 798 | [DTV_SYMBOL_RATE] = { | ||
| 799 | .name = "DTV_SYMBOL_RATE", | ||
| 800 | .cmd = DTV_SYMBOL_RATE, | ||
| 801 | .set = 1, | ||
| 802 | }, | ||
| 803 | [DTV_INNER_FEC] = { | ||
| 804 | .name = "DTV_INNER_FEC", | ||
| 805 | .cmd = DTV_INNER_FEC, | ||
| 806 | .set = 1, | ||
| 807 | }, | ||
| 808 | [DTV_VOLTAGE] = { | ||
| 809 | .name = "DTV_VOLTAGE", | ||
| 810 | .cmd = DTV_VOLTAGE, | ||
| 811 | .set = 1, | ||
| 812 | }, | ||
| 813 | [DTV_TONE] = { | ||
| 814 | .name = "DTV_TONE", | ||
| 815 | .cmd = DTV_TONE, | ||
| 816 | .set = 1, | ||
| 817 | }, | ||
| 818 | [DTV_PILOT] = { | ||
| 819 | .name = "DTV_PILOT", | ||
| 820 | .cmd = DTV_PILOT, | ||
| 821 | .set = 1, | ||
| 822 | }, | ||
| 823 | [DTV_ROLLOFF] = { | ||
| 824 | .name = "DTV_ROLLOFF", | ||
| 825 | .cmd = DTV_ROLLOFF, | ||
| 826 | .set = 1, | ||
| 827 | }, | ||
| 828 | [DTV_DELIVERY_SYSTEM] = { | ||
| 829 | .name = "DTV_DELIVERY_SYSTEM", | ||
| 830 | .cmd = DTV_DELIVERY_SYSTEM, | ||
| 831 | .set = 1, | ||
| 832 | }, | ||
| 833 | [DTV_HIERARCHY] = { | ||
| 834 | .name = "DTV_HIERARCHY", | ||
| 835 | .cmd = DTV_HIERARCHY, | ||
| 836 | .set = 1, | ||
| 837 | }, | ||
| 838 | [DTV_CODE_RATE_HP] = { | ||
| 839 | .name = "DTV_CODE_RATE_HP", | ||
| 840 | .cmd = DTV_CODE_RATE_HP, | ||
| 841 | .set = 1, | ||
| 842 | }, | ||
| 843 | [DTV_CODE_RATE_LP] = { | ||
| 844 | .name = "DTV_CODE_RATE_LP", | ||
| 845 | .cmd = DTV_CODE_RATE_LP, | ||
| 846 | .set = 1, | ||
| 847 | }, | ||
| 848 | [DTV_GUARD_INTERVAL] = { | ||
| 849 | .name = "DTV_GUARD_INTERVAL", | ||
| 850 | .cmd = DTV_GUARD_INTERVAL, | ||
| 851 | .set = 1, | ||
| 852 | }, | ||
| 853 | [DTV_TRANSMISSION_MODE] = { | ||
| 854 | .name = "DTV_TRANSMISSION_MODE", | ||
| 855 | .cmd = DTV_TRANSMISSION_MODE, | ||
| 856 | .set = 1, | ||
| 857 | }, | ||
| 858 | /* Get */ | ||
| 859 | [DTV_DISEQC_SLAVE_REPLY] = { | ||
| 860 | .name = "DTV_DISEQC_SLAVE_REPLY", | ||
| 861 | .cmd = DTV_DISEQC_SLAVE_REPLY, | ||
| 862 | .set = 0, | ||
| 863 | .buffer = 1, | ||
| 864 | }, | ||
| 865 | [DTV_API_VERSION] = { | ||
| 866 | .name = "DTV_API_VERSION", | ||
| 867 | .cmd = DTV_API_VERSION, | ||
| 868 | .set = 0, | ||
| 869 | }, | ||
| 870 | [DTV_CODE_RATE_HP] = { | ||
| 871 | .name = "DTV_CODE_RATE_HP", | ||
| 872 | .cmd = DTV_CODE_RATE_HP, | ||
| 873 | .set = 0, | ||
| 874 | }, | ||
| 875 | [DTV_CODE_RATE_LP] = { | ||
| 876 | .name = "DTV_CODE_RATE_LP", | ||
| 877 | .cmd = DTV_CODE_RATE_LP, | ||
| 878 | .set = 0, | ||
| 879 | }, | ||
| 880 | [DTV_GUARD_INTERVAL] = { | ||
| 881 | .name = "DTV_GUARD_INTERVAL", | ||
| 882 | .cmd = DTV_GUARD_INTERVAL, | ||
| 883 | .set = 0, | ||
| 884 | }, | ||
| 885 | [DTV_TRANSMISSION_MODE] = { | ||
| 886 | .name = "DTV_TRANSMISSION_MODE", | ||
| 887 | .cmd = DTV_TRANSMISSION_MODE, | ||
| 888 | .set = 0, | ||
| 889 | }, | ||
| 890 | [DTV_HIERARCHY] = { | ||
| 891 | .name = "DTV_HIERARCHY", | ||
| 892 | .cmd = DTV_HIERARCHY, | ||
| 893 | .set = 0, | ||
| 894 | }, | ||
| 895 | }; | ||
| 896 | |||
| 897 | void dtv_property_dump(struct dtv_property *tvp) | ||
| 898 | { | ||
| 899 | int i; | ||
| 900 | |||
| 901 | if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { | ||
| 902 | printk("%s: tvp.cmd = 0x%08x (undefined/unknown/invalid)\n", | ||
| 903 | __func__, tvp->cmd); | ||
| 904 | return; | ||
| 905 | } | ||
| 906 | |||
| 907 | printk("%s() tvp.cmd = 0x%08x (%s)\n" | ||
| 908 | ,__FUNCTION__ | ||
| 909 | ,tvp->cmd | ||
| 910 | ,dtv_cmds[ tvp->cmd ].name); | ||
| 911 | |||
| 912 | if(dtv_cmds[ tvp->cmd ].buffer) { | ||
| 913 | |||
| 914 | printk("%s() tvp.u.buffer.len = 0x%02x\n" | ||
| 915 | ,__FUNCTION__ | ||
| 916 | ,tvp->u.buffer.len); | ||
| 917 | |||
| 918 | for(i = 0; i < tvp->u.buffer.len; i++) | ||
| 919 | printk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n" | ||
| 920 | ,__FUNCTION__ | ||
| 921 | ,i | ||
| 922 | ,tvp->u.buffer.data[i]); | ||
| 923 | |||
| 924 | } else | ||
| 925 | printk("%s() tvp.u.data = 0x%08x\n", __FUNCTION__, tvp->u.data); | ||
| 926 | } | ||
| 927 | |||
| 928 | int is_legacy_delivery_system(fe_delivery_system_t s) | ||
| 929 | { | ||
| 930 | if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) || | ||
| 931 | (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS)) | ||
| 932 | return 1; | ||
| 933 | |||
| 934 | return 0; | ||
| 935 | } | ||
| 936 | |||
| 937 | /* Synchronise the legacy tuning parameters into the cache, so that demodulator | ||
| 938 | * drivers can use a single set_frontend tuning function, regardless of whether | ||
| 939 | * it's being used for the legacy or new API, reducing code and complexity. | ||
| 940 | */ | ||
| 941 | void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) | ||
| 942 | { | ||
| 943 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 944 | |||
| 945 | printk("%s()\n", __FUNCTION__); | ||
| 946 | |||
| 947 | c->frequency = p->frequency; | ||
| 948 | c->inversion = p->inversion; | ||
| 949 | |||
| 950 | switch (fe->ops.info.type) { | ||
| 951 | case FE_QPSK: | ||
| 952 | c->modulation = QPSK; /* implied for DVB-S in legacy API */ | ||
| 953 | c->rolloff = ROLLOFF_35;/* implied for DVB-S */ | ||
| 954 | c->symbol_rate = p->u.qpsk.symbol_rate; | ||
| 955 | c->fec_inner = p->u.qpsk.fec_inner; | ||
| 956 | c->delivery_system = SYS_DVBS; | ||
| 957 | break; | ||
| 958 | case FE_QAM: | ||
| 959 | c->symbol_rate = p->u.qam.symbol_rate; | ||
| 960 | c->fec_inner = p->u.qam.fec_inner; | ||
| 961 | c->modulation = p->u.qam.modulation; | ||
| 962 | c->delivery_system = SYS_DVBC_ANNEX_AC; | ||
| 963 | break; | ||
| 964 | case FE_OFDM: | ||
| 965 | if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ) | ||
| 966 | c->bandwidth_hz = 6000000; | ||
| 967 | else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ) | ||
| 968 | c->bandwidth_hz = 7000000; | ||
| 969 | else if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) | ||
| 970 | c->bandwidth_hz = 8000000; | ||
| 971 | else | ||
| 972 | /* Including BANDWIDTH_AUTO */ | ||
| 973 | c->bandwidth_hz = 0; | ||
| 974 | c->code_rate_HP = p->u.ofdm.code_rate_HP; | ||
| 975 | c->code_rate_LP = p->u.ofdm.code_rate_LP; | ||
| 976 | c->modulation = p->u.ofdm.constellation; | ||
| 977 | c->transmission_mode = p->u.ofdm.transmission_mode; | ||
| 978 | c->guard_interval = p->u.ofdm.guard_interval; | ||
| 979 | c->hierarchy = p->u.ofdm.hierarchy_information; | ||
| 980 | c->delivery_system = SYS_DVBT; | ||
| 981 | break; | ||
| 982 | case FE_ATSC: | ||
| 983 | c->modulation = p->u.vsb.modulation; | ||
| 984 | if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) | ||
| 985 | c->delivery_system = SYS_ATSC; | ||
| 986 | else | ||
| 987 | c->delivery_system = SYS_DVBC_ANNEX_B; | ||
| 988 | break; | ||
| 989 | } | ||
| 990 | } | ||
| 991 | |||
| 992 | /* Ensure the cached values are set correctly in the frontend | ||
| 993 | * legacy tuning structures, for the advanced tuning API. | ||
| 994 | */ | ||
| 995 | void dtv_property_legacy_params_sync(struct dvb_frontend *fe) | ||
| 996 | { | ||
| 997 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 998 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
| 999 | struct dvb_frontend_parameters *p = &fepriv->parameters; | ||
| 1000 | |||
| 1001 | printk("%s()\n", __FUNCTION__); | ||
| 1002 | |||
| 1003 | p->frequency = c->frequency; | ||
| 1004 | p->inversion = c->inversion; | ||
| 1005 | |||
| 1006 | switch (fe->ops.info.type) { | ||
| 1007 | case FE_QPSK: | ||
| 1008 | printk("%s() Preparing QPSK req\n", __FUNCTION__); | ||
| 1009 | p->u.qpsk.symbol_rate = c->symbol_rate; | ||
| 1010 | p->u.qpsk.fec_inner = c->fec_inner; | ||
| 1011 | c->delivery_system = SYS_DVBS; | ||
| 1012 | break; | ||
| 1013 | case FE_QAM: | ||
| 1014 | printk("%s() Preparing QAM req\n", __FUNCTION__); | ||
| 1015 | p->u.qam.symbol_rate = c->symbol_rate; | ||
| 1016 | p->u.qam.fec_inner = c->fec_inner; | ||
| 1017 | p->u.qam.modulation = c->modulation; | ||
| 1018 | c->delivery_system = SYS_DVBC_ANNEX_AC; | ||
| 1019 | break; | ||
| 1020 | case FE_OFDM: | ||
| 1021 | printk("%s() Preparing OFDM req\n", __FUNCTION__); | ||
| 1022 | if (c->bandwidth_hz == 6000000) | ||
| 1023 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
| 1024 | else if (c->bandwidth_hz == 7000000) | ||
| 1025 | p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | ||
| 1026 | else if (c->bandwidth_hz == 8000000) | ||
| 1027 | p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | ||
| 1028 | else | ||
| 1029 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; | ||
| 1030 | p->u.ofdm.code_rate_HP = c->code_rate_HP; | ||
| 1031 | p->u.ofdm.code_rate_LP = c->code_rate_LP; | ||
| 1032 | p->u.ofdm.constellation = c->modulation; | ||
| 1033 | p->u.ofdm.transmission_mode = c->transmission_mode; | ||
| 1034 | p->u.ofdm.guard_interval = c->guard_interval; | ||
| 1035 | p->u.ofdm.hierarchy_information = c->hierarchy; | ||
| 1036 | c->delivery_system = SYS_DVBT; | ||
| 1037 | break; | ||
| 1038 | case FE_ATSC: | ||
| 1039 | printk("%s() Preparing VSB req\n", __FUNCTION__); | ||
| 1040 | p->u.vsb.modulation = c->modulation; | ||
| 1041 | if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) | ||
| 1042 | c->delivery_system = SYS_ATSC; | ||
| 1043 | else | ||
| 1044 | c->delivery_system = SYS_DVBC_ANNEX_B; | ||
| 1045 | break; | ||
| 1046 | } | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | /* Ensure the cached values are set correctly in the frontend | ||
| 1050 | * legacy tuning structures, for the legacy tuning API. | ||
| 1051 | */ | ||
| 1052 | void dtv_property_adv_params_sync(struct dvb_frontend *fe) | ||
| 1053 | { | ||
| 1054 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 1055 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
| 1056 | struct dvb_frontend_parameters *p = &fepriv->parameters; | ||
| 1057 | |||
| 1058 | printk("%s()\n", __FUNCTION__); | ||
| 1059 | |||
| 1060 | p->frequency = c->frequency; | ||
| 1061 | p->inversion = c->inversion; | ||
| 1062 | |||
| 1063 | switch(c->modulation) { | ||
| 1064 | case PSK_8: | ||
| 1065 | case APSK_16: | ||
| 1066 | case QPSK: | ||
| 1067 | p->u.qpsk.symbol_rate = c->symbol_rate; | ||
| 1068 | p->u.qpsk.fec_inner = c->fec_inner; | ||
| 1069 | break; | ||
| 1070 | default: | ||
| 1071 | break; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | if(c->delivery_system == SYS_ISDBT) { | ||
| 1075 | /* Fake out a generic DVB-T request so we pass validation in the ioctl */ | ||
| 1076 | p->frequency = c->frequency; | ||
| 1077 | p->inversion = INVERSION_AUTO; | ||
| 1078 | p->u.ofdm.constellation = QAM_AUTO; | ||
| 1079 | p->u.ofdm.code_rate_HP = FEC_AUTO; | ||
| 1080 | p->u.ofdm.code_rate_LP = FEC_AUTO; | ||
| 1081 | p->u.ofdm.bandwidth = BANDWIDTH_AUTO; | ||
| 1082 | p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; | ||
| 1083 | p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; | ||
| 1084 | p->u.ofdm.hierarchy_information = HIERARCHY_AUTO; | ||
| 1085 | } | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | void dtv_property_cache_submit(struct dvb_frontend *fe) | ||
| 1089 | { | ||
| 1090 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 1091 | |||
| 1092 | printk("%s()\n", __FUNCTION__); | ||
| 1093 | |||
| 1094 | /* For legacy delivery systems we don't need the delivery_system to | ||
| 1095 | * be specified, but we populate the older structures from the cache | ||
| 1096 | * so we can call set_frontend on older drivers. | ||
| 1097 | */ | ||
| 1098 | if(is_legacy_delivery_system(c->delivery_system)) { | ||
| 1099 | |||
| 1100 | printk("%s() legacy, modulation = %d\n", __FUNCTION__, c->modulation); | ||
| 1101 | dtv_property_legacy_params_sync(fe); | ||
| 1102 | |||
| 1103 | } else { | ||
| 1104 | printk("%s() adv, modulation = %d\n", __FUNCTION__, c->modulation); | ||
| 1105 | |||
| 1106 | /* For advanced delivery systems / modulation types ... | ||
| 1107 | * we seed the lecacy dvb_frontend_parameters structure | ||
| 1108 | * so that the sanity checking code later in the IOCTL processing | ||
| 1109 | * can validate our basic frequency ranges, symbolrates, modulation | ||
| 1110 | * etc. | ||
| 1111 | */ | ||
| 1112 | dtv_property_adv_params_sync(fe); | ||
| 1113 | } | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, | ||
| 1117 | unsigned int cmd, void *parg); | ||
| 1118 | static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, | ||
| 1119 | unsigned int cmd, void *parg); | ||
| 1120 | |||
| 1121 | int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp, | ||
| 1122 | struct inode *inode, struct file *file) | ||
| 1123 | { | ||
| 1124 | int r = 0; | ||
| 1125 | |||
| 1126 | printk("%s()\n", __FUNCTION__); | ||
| 1127 | |||
| 1128 | dtv_property_dump(tvp); | ||
| 1129 | |||
| 1130 | /* Allow the frontend to validate incoming properties */ | ||
| 1131 | if (fe->ops.get_property) | ||
| 1132 | r = fe->ops.get_property(fe, tvp); | ||
| 1133 | |||
| 1134 | if (r < 0) | ||
| 1135 | return r; | ||
| 1136 | |||
| 1137 | switch(tvp->cmd) { | ||
| 1138 | case DTV_FREQUENCY: | ||
| 1139 | tvp->u.data = fe->dtv_property_cache.frequency; | ||
| 1140 | break; | ||
| 1141 | case DTV_MODULATION: | ||
| 1142 | tvp->u.data = fe->dtv_property_cache.modulation; | ||
| 1143 | break; | ||
| 1144 | case DTV_BANDWIDTH_HZ: | ||
| 1145 | tvp->u.data = fe->dtv_property_cache.bandwidth_hz; | ||
| 1146 | break; | ||
| 1147 | case DTV_INVERSION: | ||
| 1148 | tvp->u.data = fe->dtv_property_cache.inversion; | ||
| 1149 | break; | ||
| 1150 | case DTV_SYMBOL_RATE: | ||
| 1151 | tvp->u.data = fe->dtv_property_cache.symbol_rate; | ||
| 1152 | break; | ||
| 1153 | case DTV_INNER_FEC: | ||
| 1154 | tvp->u.data = fe->dtv_property_cache.fec_inner; | ||
| 1155 | break; | ||
| 1156 | case DTV_PILOT: | ||
| 1157 | tvp->u.data = fe->dtv_property_cache.pilot; | ||
| 1158 | break; | ||
| 1159 | case DTV_ROLLOFF: | ||
| 1160 | tvp->u.data = fe->dtv_property_cache.rolloff; | ||
| 1161 | break; | ||
| 1162 | case DTV_DELIVERY_SYSTEM: | ||
| 1163 | tvp->u.data = fe->dtv_property_cache.delivery_system; | ||
| 1164 | break; | ||
| 1165 | case DTV_VOLTAGE: | ||
| 1166 | tvp->u.data = fe->dtv_property_cache.voltage; | ||
| 1167 | break; | ||
| 1168 | case DTV_TONE: | ||
| 1169 | tvp->u.data = fe->dtv_property_cache.sectone; | ||
| 1170 | break; | ||
| 1171 | case DTV_API_VERSION: | ||
| 1172 | tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR; | ||
| 1173 | break; | ||
| 1174 | case DTV_CODE_RATE_HP: | ||
| 1175 | tvp->u.data = fe->dtv_property_cache.code_rate_HP; | ||
| 1176 | break; | ||
| 1177 | case DTV_CODE_RATE_LP: | ||
| 1178 | tvp->u.data = fe->dtv_property_cache.code_rate_LP; | ||
| 1179 | break; | ||
| 1180 | case DTV_GUARD_INTERVAL: | ||
| 1181 | tvp->u.data = fe->dtv_property_cache.guard_interval; | ||
| 1182 | break; | ||
| 1183 | case DTV_TRANSMISSION_MODE: | ||
| 1184 | tvp->u.data = fe->dtv_property_cache.transmission_mode; | ||
| 1185 | break; | ||
| 1186 | case DTV_HIERARCHY: | ||
| 1187 | tvp->u.data = fe->dtv_property_cache.hierarchy; | ||
| 1188 | break; | ||
| 1189 | default: | ||
| 1190 | r = -1; | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | return r; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp, | ||
| 1197 | struct inode *inode, struct file *file) | ||
| 1198 | { | ||
| 1199 | int r = 0; | ||
| 1200 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
| 1201 | printk("%s()\n", __FUNCTION__); | ||
| 1202 | dtv_property_dump(tvp); | ||
| 1203 | |||
| 1204 | /* Allow the frontend to validate incoming properties */ | ||
| 1205 | if (fe->ops.set_property) | ||
| 1206 | r = fe->ops.set_property(fe, tvp); | ||
| 1207 | |||
| 1208 | if (r < 0) | ||
| 1209 | return r; | ||
| 1210 | |||
| 1211 | switch(tvp->cmd) { | ||
| 1212 | case DTV_CLEAR: | ||
| 1213 | /* Reset a cache of data specific to the frontend here. This does | ||
| 1214 | * not effect hardware. | ||
| 1215 | */ | ||
| 1216 | printk("%s() Flushing property cache\n", __FUNCTION__); | ||
| 1217 | memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties)); | ||
| 1218 | fe->dtv_property_cache.state = tvp->cmd; | ||
| 1219 | fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; | ||
| 1220 | break; | ||
| 1221 | case DTV_TUNE: | ||
| 1222 | /* interpret the cache of data, build either a traditional frontend | ||
| 1223 | * tunerequest so we can pass validation in the FE_SET_FRONTEND | ||
| 1224 | * ioctl. | ||
| 1225 | */ | ||
| 1226 | fe->dtv_property_cache.state = tvp->cmd; | ||
| 1227 | printk("%s() Finalised property cache\n", __FUNCTION__); | ||
| 1228 | dtv_property_cache_submit(fe); | ||
| 1229 | |||
| 1230 | r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, | ||
| 1231 | &fepriv->parameters); | ||
| 1232 | break; | ||
| 1233 | case DTV_FREQUENCY: | ||
| 1234 | fe->dtv_property_cache.frequency = tvp->u.data; | ||
| 1235 | break; | ||
| 1236 | case DTV_MODULATION: | ||
| 1237 | fe->dtv_property_cache.modulation = tvp->u.data; | ||
| 1238 | break; | ||
| 1239 | case DTV_BANDWIDTH_HZ: | ||
| 1240 | fe->dtv_property_cache.bandwidth_hz = tvp->u.data; | ||
| 1241 | break; | ||
| 1242 | case DTV_INVERSION: | ||
| 1243 | fe->dtv_property_cache.inversion = tvp->u.data; | ||
| 1244 | break; | ||
| 1245 | case DTV_SYMBOL_RATE: | ||
| 1246 | fe->dtv_property_cache.symbol_rate = tvp->u.data; | ||
| 1247 | break; | ||
| 1248 | case DTV_INNER_FEC: | ||
| 1249 | fe->dtv_property_cache.fec_inner = tvp->u.data; | ||
| 1250 | break; | ||
| 1251 | case DTV_PILOT: | ||
| 1252 | fe->dtv_property_cache.pilot = tvp->u.data; | ||
| 1253 | break; | ||
| 1254 | case DTV_ROLLOFF: | ||
| 1255 | fe->dtv_property_cache.rolloff = tvp->u.data; | ||
| 1256 | break; | ||
| 1257 | case DTV_DELIVERY_SYSTEM: | ||
| 1258 | fe->dtv_property_cache.delivery_system = tvp->u.data; | ||
| 1259 | break; | ||
| 1260 | case DTV_VOLTAGE: | ||
| 1261 | fe->dtv_property_cache.voltage = tvp->u.data; | ||
| 1262 | r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_VOLTAGE, | ||
| 1263 | (void *)fe->dtv_property_cache.voltage); | ||
| 1264 | break; | ||
| 1265 | case DTV_TONE: | ||
| 1266 | fe->dtv_property_cache.sectone = tvp->u.data; | ||
| 1267 | r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_TONE, | ||
| 1268 | (void *)fe->dtv_property_cache.sectone); | ||
| 1269 | break; | ||
| 1270 | case DTV_CODE_RATE_HP: | ||
| 1271 | fe->dtv_property_cache.code_rate_HP = tvp->u.data; | ||
| 1272 | break; | ||
| 1273 | case DTV_CODE_RATE_LP: | ||
| 1274 | fe->dtv_property_cache.code_rate_LP = tvp->u.data; | ||
| 1275 | break; | ||
| 1276 | case DTV_GUARD_INTERVAL: | ||
| 1277 | fe->dtv_property_cache.guard_interval = tvp->u.data; | ||
| 1278 | break; | ||
| 1279 | case DTV_TRANSMISSION_MODE: | ||
| 1280 | fe->dtv_property_cache.transmission_mode = tvp->u.data; | ||
| 1281 | break; | ||
| 1282 | case DTV_HIERARCHY: | ||
| 1283 | fe->dtv_property_cache.hierarchy = tvp->u.data; | ||
| 1284 | break; | ||
| 1285 | default: | ||
| 1286 | r = -1; | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | return r; | ||
| 1290 | } | ||
| 1291 | |||
| 758 | static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | 1292 | static int dvb_frontend_ioctl(struct inode *inode, struct file *file, |
| 759 | unsigned int cmd, void *parg) | 1293 | unsigned int cmd, void *parg) |
| 760 | { | 1294 | { |
| @@ -776,6 +1310,116 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | |||
| 776 | if (down_interruptible (&fepriv->sem)) | 1310 | if (down_interruptible (&fepriv->sem)) |
| 777 | return -ERESTARTSYS; | 1311 | return -ERESTARTSYS; |
| 778 | 1312 | ||
| 1313 | if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) | ||
| 1314 | err = dvb_frontend_ioctl_properties(inode, file, cmd, parg); | ||
| 1315 | else { | ||
| 1316 | fe->dtv_property_cache.state = DTV_UNDEFINED; | ||
| 1317 | err = dvb_frontend_ioctl_legacy(inode, file, cmd, parg); | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | up(&fepriv->sem); | ||
| 1321 | return err; | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, | ||
| 1325 | unsigned int cmd, void *parg) | ||
| 1326 | { | ||
| 1327 | struct dvb_device *dvbdev = file->private_data; | ||
| 1328 | struct dvb_frontend *fe = dvbdev->priv; | ||
| 1329 | int err = 0; | ||
| 1330 | |||
| 1331 | struct dtv_properties *tvps = NULL; | ||
| 1332 | struct dtv_property *tvp = NULL; | ||
| 1333 | int i; | ||
| 1334 | |||
| 1335 | dprintk("%s\n", __func__); | ||
| 1336 | |||
| 1337 | if(cmd == FE_SET_PROPERTY) { | ||
| 1338 | printk("%s() FE_SET_PROPERTY\n", __FUNCTION__); | ||
| 1339 | |||
| 1340 | tvps = (struct dtv_properties __user *)parg; | ||
| 1341 | |||
| 1342 | printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num); | ||
| 1343 | printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props); | ||
| 1344 | |||
| 1345 | /* Put an arbitrary limit on the number of messages that can | ||
| 1346 | * be sent at once */ | ||
| 1347 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) | ||
| 1348 | return -EINVAL; | ||
| 1349 | |||
| 1350 | tvp = (struct dtv_property *) kmalloc(tvps->num * | ||
| 1351 | sizeof(struct dtv_property), GFP_KERNEL); | ||
| 1352 | if (!tvp) { | ||
| 1353 | err = -ENOMEM; | ||
| 1354 | goto out; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { | ||
| 1358 | err = -EFAULT; | ||
| 1359 | goto out; | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | for (i = 0; i < tvps->num; i++) { | ||
| 1363 | (tvp + i)->result = dtv_property_process_set(fe, tvp + i, inode, file); | ||
| 1364 | err |= (tvp + i)->result; | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | if(fe->dtv_property_cache.state == DTV_TUNE) { | ||
| 1368 | printk("%s() Property cache is full, tuning\n", __FUNCTION__); | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | } else | ||
| 1372 | if(cmd == FE_GET_PROPERTY) { | ||
| 1373 | printk("%s() FE_GET_PROPERTY\n", __FUNCTION__); | ||
| 1374 | |||
| 1375 | tvps = (struct dtv_properties __user *)parg; | ||
| 1376 | |||
| 1377 | printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num); | ||
| 1378 | printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props); | ||
| 1379 | |||
| 1380 | /* Put an arbitrary limit on the number of messages that can | ||
| 1381 | * be sent at once */ | ||
| 1382 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) | ||
| 1383 | return -EINVAL; | ||
| 1384 | |||
| 1385 | tvp = (struct dtv_property *) kmalloc(tvps->num * | ||
| 1386 | sizeof(struct dtv_property), GFP_KERNEL); | ||
| 1387 | if (!tvp) { | ||
| 1388 | err = -ENOMEM; | ||
| 1389 | goto out; | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { | ||
| 1393 | err = -EFAULT; | ||
| 1394 | goto out; | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | for (i = 0; i < tvps->num; i++) { | ||
| 1398 | (tvp + i)->result = dtv_property_process_get(fe, tvp + i, inode, file); | ||
| 1399 | err |= (tvp + i)->result; | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { | ||
| 1403 | err = -EFAULT; | ||
| 1404 | goto out; | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | } else | ||
| 1408 | err = -EOPNOTSUPP; | ||
| 1409 | |||
| 1410 | out: | ||
| 1411 | kfree(tvp); | ||
| 1412 | return err; | ||
| 1413 | } | ||
| 1414 | |||
| 1415 | static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, | ||
| 1416 | unsigned int cmd, void *parg) | ||
| 1417 | { | ||
| 1418 | struct dvb_device *dvbdev = file->private_data; | ||
| 1419 | struct dvb_frontend *fe = dvbdev->priv; | ||
| 1420 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | ||
| 1421 | int err = -EOPNOTSUPP; | ||
| 1422 | |||
| 779 | switch (cmd) { | 1423 | switch (cmd) { |
| 780 | case FE_GET_INFO: { | 1424 | case FE_GET_INFO: { |
| 781 | struct dvb_frontend_info* info = parg; | 1425 | struct dvb_frontend_info* info = parg; |
| @@ -942,13 +1586,21 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | |||
| 942 | case FE_SET_FRONTEND: { | 1586 | case FE_SET_FRONTEND: { |
| 943 | struct dvb_frontend_tune_settings fetunesettings; | 1587 | struct dvb_frontend_tune_settings fetunesettings; |
| 944 | 1588 | ||
| 945 | if (dvb_frontend_check_parameters(fe, parg) < 0) { | 1589 | if(fe->dtv_property_cache.state == DTV_TUNE) { |
| 946 | err = -EINVAL; | 1590 | if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { |
| 947 | break; | 1591 | err = -EINVAL; |
| 948 | } | 1592 | break; |
| 1593 | } | ||
| 1594 | } else { | ||
| 1595 | if (dvb_frontend_check_parameters(fe, parg) < 0) { | ||
| 1596 | err = -EINVAL; | ||
| 1597 | break; | ||
| 1598 | } | ||
| 949 | 1599 | ||
| 950 | memcpy (&fepriv->parameters, parg, | 1600 | memcpy (&fepriv->parameters, parg, |
| 951 | sizeof (struct dvb_frontend_parameters)); | 1601 | sizeof (struct dvb_frontend_parameters)); |
| 1602 | dtv_property_cache_sync(fe, &fepriv->parameters); | ||
| 1603 | } | ||
| 952 | 1604 | ||
| 953 | memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); | 1605 | memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); |
| 954 | memcpy(&fetunesettings.parameters, parg, | 1606 | memcpy(&fetunesettings.parameters, parg, |
| @@ -1027,10 +1679,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | |||
| 1027 | break; | 1679 | break; |
| 1028 | }; | 1680 | }; |
| 1029 | 1681 | ||
| 1030 | up (&fepriv->sem); | ||
| 1031 | return err; | 1682 | return err; |
| 1032 | } | 1683 | } |
| 1033 | 1684 | ||
| 1685 | |||
| 1034 | static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) | 1686 | static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait) |
| 1035 | { | 1687 | { |
| 1036 | struct dvb_device *dvbdev = file->private_data; | 1688 | struct dvb_device *dvbdev = file->private_data; |
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index aa4133f0bd19..3055301ff3ca 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h | |||
| @@ -169,6 +169,9 @@ struct dvb_frontend_ops { | |||
| 169 | 169 | ||
| 170 | struct dvb_tuner_ops tuner_ops; | 170 | struct dvb_tuner_ops tuner_ops; |
| 171 | struct analog_demod_ops analog_ops; | 171 | struct analog_demod_ops analog_ops; |
| 172 | |||
| 173 | int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); | ||
| 174 | int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); | ||
| 172 | }; | 175 | }; |
| 173 | 176 | ||
| 174 | #define MAX_EVENT 8 | 177 | #define MAX_EVENT 8 |
| @@ -182,6 +185,32 @@ struct dvb_fe_events { | |||
| 182 | struct mutex mtx; | 185 | struct mutex mtx; |
| 183 | }; | 186 | }; |
| 184 | 187 | ||
| 188 | struct dtv_frontend_properties { | ||
| 189 | |||
| 190 | /* Cache State */ | ||
| 191 | u32 state; | ||
| 192 | |||
| 193 | u32 frequency; | ||
| 194 | fe_modulation_t modulation; | ||
| 195 | |||
| 196 | fe_sec_voltage_t voltage; | ||
| 197 | fe_sec_tone_mode_t sectone; | ||
| 198 | fe_spectral_inversion_t inversion; | ||
| 199 | fe_code_rate_t fec_inner; | ||
| 200 | fe_transmit_mode_t transmission_mode; | ||
| 201 | u32 bandwidth_hz; /* 0 = AUTO */ | ||
| 202 | fe_guard_interval_t guard_interval; | ||
| 203 | fe_hierarchy_t hierarchy; | ||
| 204 | u32 symbol_rate; | ||
| 205 | fe_code_rate_t code_rate_HP; | ||
| 206 | fe_code_rate_t code_rate_LP; | ||
| 207 | |||
| 208 | fe_pilot_t pilot; | ||
| 209 | fe_rolloff_t rolloff; | ||
| 210 | |||
| 211 | fe_delivery_system_t delivery_system; | ||
| 212 | }; | ||
| 213 | |||
| 185 | struct dvb_frontend { | 214 | struct dvb_frontend { |
| 186 | struct dvb_frontend_ops ops; | 215 | struct dvb_frontend_ops ops; |
| 187 | struct dvb_adapter *dvb; | 216 | struct dvb_adapter *dvb; |
| @@ -190,6 +219,9 @@ struct dvb_frontend { | |||
| 190 | void *frontend_priv; | 219 | void *frontend_priv; |
| 191 | void *sec_priv; | 220 | void *sec_priv; |
| 192 | void *analog_demod_priv; | 221 | void *analog_demod_priv; |
| 222 | struct dtv_frontend_properties dtv_property_cache; | ||
| 223 | #define DVB_FRONTEND_COMPONENT_TUNER 0 | ||
| 224 | int (*callback)(void *adapter_priv, int component, int cmd, int arg); | ||
| 193 | }; | 225 | }; |
| 194 | 226 | ||
| 195 | extern int dvb_register_frontend(struct dvb_adapter *dvb, | 227 | extern int dvb_register_frontend(struct dvb_adapter *dvb, |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index e84152b7576d..3c13bcfa6385 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
| @@ -72,9 +72,11 @@ config DVB_USB_DIB0700 | |||
| 72 | select DVB_DIB7000P | 72 | select DVB_DIB7000P |
| 73 | select DVB_DIB7000M | 73 | select DVB_DIB7000M |
| 74 | select DVB_DIB3000MC | 74 | select DVB_DIB3000MC |
| 75 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | ||
| 75 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 76 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE |
| 76 | select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE | 77 | select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE |
| 77 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE | 78 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE |
| 79 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE | ||
| 78 | select DVB_TUNER_DIB0070 | 80 | select DVB_TUNER_DIB0070 |
| 79 | help | 81 | help |
| 80 | Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The | 82 | Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The |
| @@ -108,6 +110,8 @@ config DVB_USB_CXUSB | |||
| 108 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | 110 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE |
| 109 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE | 111 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE |
| 110 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE | 112 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE |
| 113 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE | ||
| 114 | select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE | ||
| 111 | help | 115 | help |
| 112 | Say Y here to support the Conexant USB2.0 hybrid reference design. | 116 | Say Y here to support the Conexant USB2.0 hybrid reference design. |
| 113 | Currently, only DVB and ATSC modes are supported, analog mode | 117 | Currently, only DVB and ATSC modes are supported, analog mode |
| @@ -245,12 +249,25 @@ config DVB_USB_AF9005_REMOTE | |||
| 245 | Afatech AF9005 based receiver. | 249 | Afatech AF9005 based receiver. |
| 246 | 250 | ||
| 247 | config DVB_USB_DW2102 | 251 | config DVB_USB_DW2102 |
| 248 | tristate "DvbWorld 2102 DVB-S USB2.0 receiver" | 252 | tristate "DvbWorld DVB-S/S2 USB2.0 support" |
| 249 | depends on DVB_USB | 253 | depends on DVB_USB |
| 250 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
| 251 | select DVB_PLL if !DVB_FE_CUSTOMISE | 254 | select DVB_PLL if !DVB_FE_CUSTOMISE |
| 255 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
| 256 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | ||
| 257 | select DVB_STB6000 if !DVB_FE_CUSTOMISE | ||
| 258 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | ||
| 259 | select DVB_SI21XX if !DVB_FE_CUSTOMISE | ||
| 252 | help | 260 | help |
| 253 | Say Y here to support the DvbWorld 2102 DVB-S USB2.0 receiver. | 261 | Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers |
| 262 | and the TeVii S650. | ||
| 263 | |||
| 264 | config DVB_USB_CINERGY_T2 | ||
| 265 | tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" | ||
| 266 | depends on DVB_USB | ||
| 267 | help | ||
| 268 | Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers | ||
| 269 | |||
| 270 | Say Y if you own such a device and want to use it. | ||
| 254 | 271 | ||
| 255 | config DVB_USB_ANYSEE | 272 | config DVB_USB_ANYSEE |
| 256 | tristate "Anysee DVB-T/C USB2.0 support" | 273 | tristate "Anysee DVB-T/C USB2.0 support" |
| @@ -262,3 +279,22 @@ config DVB_USB_ANYSEE | |||
| 262 | help | 279 | help |
| 263 | Say Y here to support the Anysee E30, Anysee E30 Plus or | 280 | Say Y here to support the Anysee E30, Anysee E30 Plus or |
| 264 | Anysee E30 C Plus DVB USB2.0 receiver. | 281 | Anysee E30 C Plus DVB USB2.0 receiver. |
| 282 | |||
| 283 | config DVB_USB_DTV5100 | ||
| 284 | tristate "AME DTV-5100 USB2.0 DVB-T support" | ||
| 285 | depends on DVB_USB | ||
| 286 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | ||
| 287 | help | ||
| 288 | Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. | ||
| 289 | |||
| 290 | config DVB_USB_AF9015 | ||
| 291 | tristate "Afatech AF9015 DVB-T USB2.0 support" | ||
| 292 | depends on DVB_USB && EXPERIMENTAL | ||
| 293 | select DVB_AF9013 | ||
| 294 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 295 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | ||
| 296 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | ||
| 297 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE | ||
| 298 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE | ||
| 299 | help | ||
| 300 | Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver | ||
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index e206f1ea0027..3122b7cc2c23 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
| @@ -67,6 +67,16 @@ obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o | |||
| 67 | dvb-usb-dw2102-objs = dw2102.o | 67 | dvb-usb-dw2102-objs = dw2102.o |
| 68 | obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o | 68 | obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o |
| 69 | 69 | ||
| 70 | dvb-usb-dtv5100-objs = dtv5100.o | ||
| 71 | obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o | ||
| 72 | |||
| 73 | dvb-usb-af9015-objs = af9015.o | ||
| 74 | obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o | ||
| 75 | |||
| 76 | dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o | ||
| 77 | obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o | ||
| 78 | |||
| 79 | |||
| 70 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | 80 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ |
| 71 | # due to tuner-xc3028 | 81 | # due to tuner-xc3028 |
| 72 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | 82 | EXTRA_CFLAGS += -Idrivers/media/common/tuners |
diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c index ff00c0e8f4a1..7c596f926764 100644 --- a/drivers/media/dvb/dvb-usb/af9005-remote.c +++ b/drivers/media/dvb/dvb-usb/af9005-remote.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | */ | 25 | */ |
| 26 | #include "af9005.h" | 26 | #include "af9005.h" |
| 27 | /* debug */ | 27 | /* debug */ |
| 28 | int dvb_usb_af9005_remote_debug; | 28 | static int dvb_usb_af9005_remote_debug; |
| 29 | module_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644); | 29 | module_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644); |
| 30 | MODULE_PARM_DESC(debug, | 30 | MODULE_PARM_DESC(debug, |
| 31 | "enable (1) or disable (0) debug messages." | 31 | "enable (1) or disable (0) debug messages." |
diff --git a/drivers/media/dvb/dvb-usb/af9005-script.h b/drivers/media/dvb/dvb-usb/af9005-script.h index 6eeaae51b1ca..4d69045426dd 100644 --- a/drivers/media/dvb/dvb-usb/af9005-script.h +++ b/drivers/media/dvb/dvb-usb/af9005-script.h | |||
| @@ -14,7 +14,7 @@ typedef struct { | |||
| 14 | u8 val; | 14 | u8 val; |
| 15 | } RegDesc; | 15 | } RegDesc; |
| 16 | 16 | ||
| 17 | RegDesc script[] = { | 17 | static RegDesc script[] = { |
| 18 | {0xa180, 0x0, 0x8, 0xa}, | 18 | {0xa180, 0x0, 0x8, 0xa}, |
| 19 | {0xa181, 0x0, 0x8, 0xd7}, | 19 | {0xa181, 0x0, 0x8, 0xd7}, |
| 20 | {0xa182, 0x0, 0x8, 0xa3}, | 20 | {0xa182, 0x0, 0x8, 0xa3}, |
diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c index cfe71feefcad..ca5a0a4d2a47 100644 --- a/drivers/media/dvb/dvb-usb/af9005.c +++ b/drivers/media/dvb/dvb-usb/af9005.c | |||
| @@ -35,17 +35,17 @@ module_param_named(led, dvb_usb_af9005_led, bool, 0644); | |||
| 35 | MODULE_PARM_DESC(led, "enable led (default: 1)."); | 35 | MODULE_PARM_DESC(led, "enable led (default: 1)."); |
| 36 | 36 | ||
| 37 | /* eeprom dump */ | 37 | /* eeprom dump */ |
| 38 | int dvb_usb_af9005_dump_eeprom = 0; | 38 | static int dvb_usb_af9005_dump_eeprom; |
| 39 | module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0); | 39 | module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0); |
| 40 | MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom."); | 40 | MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom."); |
| 41 | 41 | ||
| 42 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 42 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 43 | 43 | ||
| 44 | /* remote control decoder */ | 44 | /* remote control decoder */ |
| 45 | int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event, | 45 | static int (*rc_decode) (struct dvb_usb_device *d, u8 *data, int len, |
| 46 | int *state); | 46 | u32 *event, int *state); |
| 47 | void *rc_keys; | 47 | static void *rc_keys; |
| 48 | int *rc_keys_size; | 48 | static int *rc_keys_size; |
| 49 | 49 | ||
| 50 | u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; | 50 | u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; |
| 51 | 51 | ||
| @@ -54,8 +54,8 @@ struct af9005_device_state { | |||
| 54 | int led_state; | 54 | int led_state; |
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen, | 57 | static int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, |
| 58 | u8 * rbuf, u16 rlen, int delay_ms) | 58 | u8 *rbuf, u16 rlen, int delay_ms) |
| 59 | { | 59 | { |
| 60 | int actlen, ret = -ENOMEM; | 60 | int actlen, ret = -ENOMEM; |
| 61 | 61 | ||
| @@ -98,12 +98,7 @@ int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen, | |||
| 98 | return ret; | 98 | return ret; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | int af9005_usb_generic_write(struct dvb_usb_device *d, u8 * buf, u16 len) | 101 | static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, |
| 102 | { | ||
| 103 | return af9005_usb_generic_rw(d, buf, len, NULL, 0, 0); | ||
| 104 | } | ||
| 105 | |||
| 106 | int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, | ||
| 107 | int readwrite, int type, u8 * values, int len) | 102 | int readwrite, int type, u8 * values, int len) |
| 108 | { | 103 | { |
| 109 | struct af9005_device_state *st = d->priv; | 104 | struct af9005_device_state *st = d->priv; |
| @@ -765,7 +760,7 @@ static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply) | |||
| 765 | return 0; | 760 | return 0; |
| 766 | } | 761 | } |
| 767 | 762 | ||
| 768 | int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw) | 763 | static int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw) |
| 769 | { | 764 | { |
| 770 | int i, packets, ret, act_len; | 765 | int i, packets, ret, act_len; |
| 771 | 766 | ||
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c new file mode 100644 index 000000000000..cb0829c038ce --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9015.c | |||
| @@ -0,0 +1,1474 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * Thanks to Afatech who kindly provided information. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include "af9015.h" | ||
| 25 | #include "af9013.h" | ||
| 26 | #include "mt2060.h" | ||
| 27 | #include "qt1010.h" | ||
| 28 | #include "tda18271.h" | ||
| 29 | #include "mxl5005s.h" | ||
| 30 | #if 0 | ||
| 31 | #include "mc44s80x.h" | ||
| 32 | #endif | ||
| 33 | |||
| 34 | int dvb_usb_af9015_debug; | ||
| 35 | module_param_named(debug, dvb_usb_af9015_debug, int, 0644); | ||
| 36 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
| 37 | int dvb_usb_af9015_remote; | ||
| 38 | module_param_named(remote, dvb_usb_af9015_remote, int, 0644); | ||
| 39 | MODULE_PARM_DESC(remote, "select remote"); | ||
| 40 | int dvb_usb_af9015_dual_mode; | ||
| 41 | module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644); | ||
| 42 | MODULE_PARM_DESC(dual_mode, "enable dual mode"); | ||
| 43 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 44 | |||
| 45 | static DEFINE_MUTEX(af9015_usb_mutex); | ||
| 46 | |||
| 47 | static struct af9015_config af9015_config; | ||
| 48 | static struct dvb_usb_device_properties af9015_properties[2]; | ||
| 49 | int af9015_properties_count = ARRAY_SIZE(af9015_properties); | ||
| 50 | |||
| 51 | static struct af9013_config af9015_af9013_config[] = { | ||
| 52 | { | ||
| 53 | .demod_address = AF9015_I2C_DEMOD, | ||
| 54 | .output_mode = AF9013_OUTPUT_MODE_USB, | ||
| 55 | .api_version = { 0, 1, 9, 0 }, | ||
| 56 | .gpio[0] = AF9013_GPIO_HI, | ||
| 57 | .gpio[3] = AF9013_GPIO_TUNER_ON, | ||
| 58 | |||
| 59 | }, { | ||
| 60 | .output_mode = AF9013_OUTPUT_MODE_SERIAL, | ||
| 61 | .api_version = { 0, 1, 9, 0 }, | ||
| 62 | .gpio[0] = AF9013_GPIO_TUNER_ON, | ||
| 63 | .gpio[1] = AF9013_GPIO_LO, | ||
| 64 | } | ||
| 65 | }; | ||
| 66 | |||
| 67 | static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) | ||
| 68 | { | ||
| 69 | int act_len, ret; | ||
| 70 | u8 buf[64]; | ||
| 71 | u8 write = 1; | ||
| 72 | u8 msg_len = 8; | ||
| 73 | static u8 seq; /* packet sequence number */ | ||
| 74 | |||
| 75 | if (mutex_lock_interruptible(&af9015_usb_mutex) < 0) | ||
| 76 | return -EAGAIN; | ||
| 77 | |||
| 78 | buf[0] = req->cmd; | ||
| 79 | buf[1] = seq++; | ||
| 80 | buf[2] = req->i2c_addr; | ||
| 81 | buf[3] = req->addr >> 8; | ||
| 82 | buf[4] = req->addr & 0xff; | ||
| 83 | buf[5] = req->mbox; | ||
| 84 | buf[6] = req->addr_len; | ||
| 85 | buf[7] = req->data_len; | ||
| 86 | |||
| 87 | switch (req->cmd) { | ||
| 88 | case GET_CONFIG: | ||
| 89 | case BOOT: | ||
| 90 | case READ_MEMORY: | ||
| 91 | case RECONNECT_USB: | ||
| 92 | case GET_IR_CODE: | ||
| 93 | write = 0; | ||
| 94 | break; | ||
| 95 | case READ_I2C: | ||
| 96 | write = 0; | ||
| 97 | buf[2] |= 0x01; /* set I2C direction */ | ||
| 98 | case WRITE_I2C: | ||
| 99 | buf[0] = READ_WRITE_I2C; | ||
| 100 | break; | ||
| 101 | case WRITE_MEMORY: | ||
| 102 | if (((req->addr & 0xff00) == 0xff00) || | ||
| 103 | ((req->addr & 0xae00) == 0xae00)) | ||
| 104 | buf[0] = WRITE_VIRTUAL_MEMORY; | ||
| 105 | case WRITE_VIRTUAL_MEMORY: | ||
| 106 | case COPY_FIRMWARE: | ||
| 107 | case DOWNLOAD_FIRMWARE: | ||
| 108 | break; | ||
| 109 | default: | ||
| 110 | err("unknown command:%d", req->cmd); | ||
| 111 | ret = -1; | ||
| 112 | goto error_unlock; | ||
| 113 | } | ||
| 114 | |||
| 115 | /* write requested */ | ||
| 116 | if (write) { | ||
| 117 | memcpy(&buf[8], req->data, req->data_len); | ||
| 118 | msg_len += req->data_len; | ||
| 119 | } | ||
| 120 | deb_xfer(">>> "); | ||
| 121 | debug_dump(buf, msg_len, deb_xfer); | ||
| 122 | |||
| 123 | /* send req */ | ||
| 124 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, | ||
| 125 | &act_len, AF9015_USB_TIMEOUT); | ||
| 126 | if (ret) | ||
| 127 | err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len); | ||
| 128 | else | ||
| 129 | if (act_len != msg_len) | ||
| 130 | ret = -1; /* all data is not send */ | ||
| 131 | if (ret) | ||
| 132 | goto error_unlock; | ||
| 133 | |||
| 134 | /* no ack for those packets */ | ||
| 135 | if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) | ||
| 136 | goto exit_unlock; | ||
| 137 | |||
| 138 | /* receive ack and data if read req */ | ||
| 139 | msg_len = 1 + 1 + req->data_len; /* seq + status + data len */ | ||
| 140 | ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, | ||
| 141 | &act_len, AF9015_USB_TIMEOUT); | ||
| 142 | if (ret) { | ||
| 143 | err("recv bulk message failed:%d", ret); | ||
| 144 | ret = -1; | ||
| 145 | goto error_unlock; | ||
| 146 | } | ||
| 147 | |||
| 148 | deb_xfer("<<< "); | ||
| 149 | debug_dump(buf, act_len, deb_xfer); | ||
| 150 | |||
| 151 | /* remote controller query status is 1 if remote code is not received */ | ||
| 152 | if (req->cmd == GET_IR_CODE && buf[1] == 1) { | ||
| 153 | buf[1] = 0; /* clear command "error" status */ | ||
| 154 | memset(&buf[2], 0, req->data_len); | ||
| 155 | buf[3] = 1; /* no remote code received mark */ | ||
| 156 | } | ||
| 157 | |||
| 158 | /* check status */ | ||
| 159 | if (buf[1]) { | ||
| 160 | err("command failed:%d", buf[1]); | ||
| 161 | ret = -1; | ||
| 162 | goto error_unlock; | ||
| 163 | } | ||
| 164 | |||
| 165 | /* read request, copy returned data to return buf */ | ||
| 166 | if (!write) | ||
| 167 | memcpy(req->data, &buf[2], req->data_len); | ||
| 168 | |||
| 169 | error_unlock: | ||
| 170 | exit_unlock: | ||
| 171 | mutex_unlock(&af9015_usb_mutex); | ||
| 172 | |||
| 173 | return ret; | ||
| 174 | } | ||
| 175 | |||
| 176 | static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) | ||
| 177 | { | ||
| 178 | return af9015_rw_udev(d->udev, req); | ||
| 179 | } | ||
| 180 | |||
| 181 | static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val, | ||
| 182 | u8 len) | ||
| 183 | { | ||
| 184 | struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, | ||
| 185 | val}; | ||
| 186 | return af9015_ctrl_msg(d, &req); | ||
| 187 | } | ||
| 188 | |||
| 189 | static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val) | ||
| 190 | { | ||
| 191 | return af9015_write_regs(d, addr, &val, 1); | ||
| 192 | } | ||
| 193 | |||
| 194 | static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val) | ||
| 195 | { | ||
| 196 | struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, 1, val}; | ||
| 197 | return af9015_ctrl_msg(d, &req); | ||
| 198 | } | ||
| 199 | |||
| 200 | static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, | ||
| 201 | u8 val) | ||
| 202 | { | ||
| 203 | struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val}; | ||
| 204 | |||
| 205 | if (addr == af9015_af9013_config[0].demod_address || | ||
| 206 | addr == af9015_af9013_config[1].demod_address) | ||
| 207 | req.addr_len = 3; | ||
| 208 | |||
| 209 | return af9015_ctrl_msg(d, &req); | ||
| 210 | } | ||
| 211 | |||
| 212 | static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, | ||
| 213 | u8 *val) | ||
| 214 | { | ||
| 215 | struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val}; | ||
| 216 | |||
| 217 | if (addr == af9015_af9013_config[0].demod_address || | ||
| 218 | addr == af9015_af9013_config[1].demod_address) | ||
| 219 | req.addr_len = 3; | ||
| 220 | |||
| 221 | return af9015_ctrl_msg(d, &req); | ||
| 222 | } | ||
| 223 | |||
| 224 | static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 225 | int num) | ||
| 226 | { | ||
| 227 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 228 | int ret = 0, i = 0; | ||
| 229 | u16 addr; | ||
| 230 | u8 mbox, addr_len; | ||
| 231 | struct req_t req; | ||
| 232 | |||
| 233 | /* TODO: implement bus lock | ||
| 234 | |||
| 235 | The bus lock is needed because there is two tuners both using same I2C-address. | ||
| 236 | Due to that the only way to select correct tuner is use demodulator I2C-gate. | ||
| 237 | |||
| 238 | ................................................ | ||
| 239 | . AF9015 includes integrated AF9013 demodulator. | ||
| 240 | . ____________ ____________ . ____________ | ||
| 241 | .| uC | | demod | . | tuner | | ||
| 242 | .|------------| |------------| . |------------| | ||
| 243 | .| AF9015 | | AF9013/5 | . | MXL5003 | | ||
| 244 | .| |--+----I2C-------|-----/ -----|-.-----I2C-------| | | ||
| 245 | .| | | | addr 0x38 | . | addr 0xc6 | | ||
| 246 | .|____________| | |____________| . |____________| | ||
| 247 | .................|.............................. | ||
| 248 | | ____________ ____________ | ||
| 249 | | | demod | | tuner | | ||
| 250 | | |------------| |------------| | ||
| 251 | | | AF9013 | | MXL5003 | | ||
| 252 | +----I2C-------|-----/ -----|-------I2C-------| | | ||
| 253 | | addr 0x3a | | addr 0xc6 | | ||
| 254 | |____________| |____________| | ||
| 255 | */ | ||
| 256 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 257 | return -EAGAIN; | ||
| 258 | |||
| 259 | while (i < num) { | ||
| 260 | if (msg[i].addr == af9015_af9013_config[0].demod_address || | ||
| 261 | msg[i].addr == af9015_af9013_config[1].demod_address) { | ||
| 262 | addr = msg[i].buf[0] << 8; | ||
| 263 | addr += msg[i].buf[1]; | ||
| 264 | mbox = msg[i].buf[2]; | ||
| 265 | addr_len = 3; | ||
| 266 | } else { | ||
| 267 | addr = msg[i].buf[0]; | ||
| 268 | addr_len = 1; | ||
| 269 | mbox = 0; | ||
| 270 | } | ||
| 271 | |||
| 272 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
| 273 | if (msg[i].addr == | ||
| 274 | af9015_af9013_config[0].demod_address) | ||
| 275 | req.cmd = READ_MEMORY; | ||
| 276 | else | ||
| 277 | req.cmd = READ_I2C; | ||
| 278 | req.i2c_addr = msg[i].addr; | ||
| 279 | req.addr = addr; | ||
| 280 | req.mbox = mbox; | ||
| 281 | req.addr_len = addr_len; | ||
| 282 | req.data_len = msg[i+1].len; | ||
| 283 | req.data = &msg[i+1].buf[0]; | ||
| 284 | ret = af9015_ctrl_msg(d, &req); | ||
| 285 | i += 2; | ||
| 286 | } else { | ||
| 287 | if (msg[i].addr == | ||
| 288 | af9015_af9013_config[0].demod_address) | ||
| 289 | req.cmd = WRITE_MEMORY; | ||
| 290 | else | ||
| 291 | req.cmd = WRITE_I2C; | ||
| 292 | req.i2c_addr = msg[i].addr; | ||
| 293 | req.addr = addr; | ||
| 294 | req.mbox = mbox; | ||
| 295 | req.addr_len = addr_len; | ||
| 296 | req.data_len = msg[i].len-addr_len; | ||
| 297 | req.data = &msg[i].buf[addr_len]; | ||
| 298 | ret = af9015_ctrl_msg(d, &req); | ||
| 299 | i += 1; | ||
| 300 | } | ||
| 301 | if (ret) | ||
| 302 | goto error; | ||
| 303 | |||
| 304 | } | ||
| 305 | ret = i; | ||
| 306 | |||
| 307 | error: | ||
| 308 | mutex_unlock(&d->i2c_mutex); | ||
| 309 | |||
| 310 | return ret; | ||
| 311 | } | ||
| 312 | |||
| 313 | static u32 af9015_i2c_func(struct i2c_adapter *adapter) | ||
| 314 | { | ||
| 315 | return I2C_FUNC_I2C; | ||
| 316 | } | ||
| 317 | |||
| 318 | static struct i2c_algorithm af9015_i2c_algo = { | ||
| 319 | .master_xfer = af9015_i2c_xfer, | ||
| 320 | .functionality = af9015_i2c_func, | ||
| 321 | }; | ||
| 322 | |||
| 323 | static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op) | ||
| 324 | { | ||
| 325 | int ret; | ||
| 326 | u8 val, mask = 0x01; | ||
| 327 | |||
| 328 | ret = af9015_read_reg(d, addr, &val); | ||
| 329 | if (ret) | ||
| 330 | return ret; | ||
| 331 | |||
| 332 | mask <<= bit; | ||
| 333 | if (op) { | ||
| 334 | /* set bit */ | ||
| 335 | val |= mask; | ||
| 336 | } else { | ||
| 337 | /* clear bit */ | ||
| 338 | mask ^= 0xff; | ||
| 339 | val &= mask; | ||
| 340 | } | ||
| 341 | |||
| 342 | return af9015_write_reg(d, addr, val); | ||
| 343 | } | ||
| 344 | |||
| 345 | static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) | ||
| 346 | { | ||
| 347 | return af9015_do_reg_bit(d, addr, bit, 1); | ||
| 348 | } | ||
| 349 | |||
| 350 | static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) | ||
| 351 | { | ||
| 352 | return af9015_do_reg_bit(d, addr, bit, 0); | ||
| 353 | } | ||
| 354 | |||
| 355 | static int af9015_init_endpoint(struct dvb_usb_device *d) | ||
| 356 | { | ||
| 357 | int ret; | ||
| 358 | u16 frame_size; | ||
| 359 | u8 packet_size; | ||
| 360 | deb_info("%s: USB speed:%d\n", __func__, d->udev->speed); | ||
| 361 | |||
| 362 | #define TS_PACKET_SIZE 188 | ||
| 363 | |||
| 364 | #define TS_USB20_PACKET_COUNT 348 | ||
| 365 | #define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT) | ||
| 366 | |||
| 367 | #define TS_USB11_PACKET_COUNT 21 | ||
| 368 | #define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT) | ||
| 369 | |||
| 370 | #define TS_USB20_MAX_PACKET_SIZE 512 | ||
| 371 | #define TS_USB11_MAX_PACKET_SIZE 64 | ||
| 372 | |||
| 373 | if (d->udev->speed == USB_SPEED_FULL) { | ||
| 374 | frame_size = TS_USB11_FRAME_SIZE/4; | ||
| 375 | packet_size = TS_USB11_MAX_PACKET_SIZE/4; | ||
| 376 | } else { | ||
| 377 | frame_size = TS_USB20_FRAME_SIZE/4; | ||
| 378 | packet_size = TS_USB20_MAX_PACKET_SIZE/4; | ||
| 379 | } | ||
| 380 | |||
| 381 | ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */ | ||
| 382 | if (ret) | ||
| 383 | goto error; | ||
| 384 | ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */ | ||
| 385 | if (ret) | ||
| 386 | goto error; | ||
| 387 | ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */ | ||
| 388 | if (ret) | ||
| 389 | goto error; | ||
| 390 | ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */ | ||
| 391 | if (ret) | ||
| 392 | goto error; | ||
| 393 | ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */ | ||
| 394 | if (ret) | ||
| 395 | goto error; | ||
| 396 | if (af9015_config.dual_mode) { | ||
| 397 | ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */ | ||
| 398 | if (ret) | ||
| 399 | goto error; | ||
| 400 | } | ||
| 401 | ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */ | ||
| 402 | if (ret) | ||
| 403 | goto error; | ||
| 404 | if (af9015_config.dual_mode) { | ||
| 405 | ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */ | ||
| 406 | if (ret) | ||
| 407 | goto error; | ||
| 408 | } | ||
| 409 | /* EP4 xfer length */ | ||
| 410 | ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff); | ||
| 411 | if (ret) | ||
| 412 | goto error; | ||
| 413 | ret = af9015_write_reg(d, 0xdd89, frame_size >> 8); | ||
| 414 | if (ret) | ||
| 415 | goto error; | ||
| 416 | /* EP5 xfer length */ | ||
| 417 | ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff); | ||
| 418 | if (ret) | ||
| 419 | goto error; | ||
| 420 | ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8); | ||
| 421 | if (ret) | ||
| 422 | goto error; | ||
| 423 | ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */ | ||
| 424 | if (ret) | ||
| 425 | goto error; | ||
| 426 | ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */ | ||
| 427 | if (ret) | ||
| 428 | goto error; | ||
| 429 | ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */ | ||
| 430 | if (ret) | ||
| 431 | goto error; | ||
| 432 | if (af9015_config.dual_mode) { | ||
| 433 | ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */ | ||
| 434 | if (ret) | ||
| 435 | goto error; | ||
| 436 | } | ||
| 437 | |||
| 438 | /* enable / disable mp2if2 */ | ||
| 439 | if (af9015_config.dual_mode) | ||
| 440 | ret = af9015_set_reg_bit(d, 0xd50b, 0); | ||
| 441 | else | ||
| 442 | ret = af9015_clear_reg_bit(d, 0xd50b, 0); | ||
| 443 | error: | ||
| 444 | if (ret) | ||
| 445 | err("endpoint init failed:%d", ret); | ||
| 446 | return ret; | ||
| 447 | } | ||
| 448 | |||
| 449 | static int af9015_copy_firmware(struct dvb_usb_device *d) | ||
| 450 | { | ||
| 451 | int ret; | ||
| 452 | u8 fw_params[4]; | ||
| 453 | u8 val, i; | ||
| 454 | struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params), | ||
| 455 | fw_params }; | ||
| 456 | deb_info("%s:\n", __func__); | ||
| 457 | |||
| 458 | fw_params[0] = af9015_config.firmware_size >> 8; | ||
| 459 | fw_params[1] = af9015_config.firmware_size & 0xff; | ||
| 460 | fw_params[2] = af9015_config.firmware_checksum >> 8; | ||
| 461 | fw_params[3] = af9015_config.firmware_checksum & 0xff; | ||
| 462 | |||
| 463 | /* wait 2nd demodulator ready */ | ||
| 464 | msleep(100); | ||
| 465 | |||
| 466 | ret = af9015_read_reg_i2c(d, 0x3a, 0x98be, &val); | ||
| 467 | if (ret) | ||
| 468 | goto error; | ||
| 469 | else | ||
| 470 | deb_info("%s: firmware status:%02x\n", __func__, val); | ||
| 471 | |||
| 472 | if (val == 0x0c) /* fw is running, no need for download */ | ||
| 473 | goto exit; | ||
| 474 | |||
| 475 | /* set I2C master clock to fast (to speed up firmware copy) */ | ||
| 476 | ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */ | ||
| 477 | if (ret) | ||
| 478 | goto error; | ||
| 479 | |||
| 480 | msleep(50); | ||
| 481 | |||
| 482 | /* copy firmware */ | ||
| 483 | ret = af9015_ctrl_msg(d, &req); | ||
| 484 | if (ret) | ||
| 485 | err("firmware copy cmd failed:%d", ret); | ||
| 486 | deb_info("%s: firmware copy done\n", __func__); | ||
| 487 | |||
| 488 | /* set I2C master clock back to normal */ | ||
| 489 | ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */ | ||
| 490 | if (ret) | ||
| 491 | goto error; | ||
| 492 | |||
| 493 | /* request boot firmware */ | ||
| 494 | ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].demod_address, | ||
| 495 | 0xe205, 1); | ||
| 496 | deb_info("%s: firmware boot cmd status:%d\n", __func__, ret); | ||
| 497 | if (ret) | ||
| 498 | goto error; | ||
| 499 | |||
| 500 | for (i = 0; i < 15; i++) { | ||
| 501 | msleep(100); | ||
| 502 | |||
| 503 | /* check firmware status */ | ||
| 504 | ret = af9015_read_reg_i2c(d, | ||
| 505 | af9015_af9013_config[1].demod_address, 0x98be, &val); | ||
| 506 | deb_info("%s: firmware status cmd status:%d fw status:%02x\n", | ||
| 507 | __func__, ret, val); | ||
| 508 | if (ret) | ||
| 509 | goto error; | ||
| 510 | |||
| 511 | if (val == 0x0c || val == 0x04) /* success or fail */ | ||
| 512 | break; | ||
| 513 | } | ||
| 514 | |||
| 515 | if (val == 0x04) { | ||
| 516 | err("firmware did not run"); | ||
| 517 | ret = -1; | ||
| 518 | } else if (val != 0x0c) { | ||
| 519 | err("firmware boot timeout"); | ||
| 520 | ret = -1; | ||
| 521 | } | ||
| 522 | |||
| 523 | error: | ||
| 524 | exit: | ||
| 525 | return ret; | ||
| 526 | } | ||
| 527 | |||
| 528 | /* dump eeprom */ | ||
| 529 | static int af9015_eeprom_dump(struct dvb_usb_device *d) | ||
| 530 | { | ||
| 531 | char buf[52], buf2[4]; | ||
| 532 | u8 reg, val; | ||
| 533 | |||
| 534 | for (reg = 0; ; reg++) { | ||
| 535 | if (reg % 16 == 0) { | ||
| 536 | if (reg) | ||
| 537 | deb_info("%s\n", buf); | ||
| 538 | sprintf(buf, "%02x: ", reg); | ||
| 539 | } | ||
| 540 | if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0) | ||
| 541 | sprintf(buf2, "%02x ", val); | ||
| 542 | else | ||
| 543 | strcpy(buf2, "-- "); | ||
| 544 | strcat(buf, buf2); | ||
| 545 | if (reg == 0xff) | ||
| 546 | break; | ||
| 547 | } | ||
| 548 | deb_info("%s\n", buf); | ||
| 549 | return 0; | ||
| 550 | } | ||
| 551 | |||
| 552 | int af9015_download_ir_table(struct dvb_usb_device *d) | ||
| 553 | { | ||
| 554 | int i, packets = 0, ret; | ||
| 555 | u16 addr = 0x9a56; /* ir-table start address */ | ||
| 556 | struct req_t req = {WRITE_MEMORY, 0, 0, 0, 0, 1, NULL}; | ||
| 557 | u8 *data = NULL; | ||
| 558 | deb_info("%s:\n", __func__); | ||
| 559 | |||
| 560 | data = af9015_config.ir_table; | ||
| 561 | packets = af9015_config.ir_table_size; | ||
| 562 | |||
| 563 | /* no remote */ | ||
| 564 | if (!packets) | ||
| 565 | goto exit; | ||
| 566 | |||
| 567 | /* load remote ir-table */ | ||
| 568 | for (i = 0; i < packets; i++) { | ||
| 569 | req.addr = addr + i; | ||
| 570 | req.data = &data[i]; | ||
| 571 | ret = af9015_ctrl_msg(d, &req); | ||
| 572 | if (ret) { | ||
| 573 | err("ir-table download failed at packet %d with " \ | ||
| 574 | "code %d", i, ret); | ||
| 575 | return ret; | ||
| 576 | } | ||
| 577 | } | ||
| 578 | |||
| 579 | exit: | ||
| 580 | return 0; | ||
| 581 | } | ||
| 582 | |||
| 583 | static int af9015_init(struct dvb_usb_device *d) | ||
| 584 | { | ||
| 585 | int ret; | ||
| 586 | deb_info("%s:\n", __func__); | ||
| 587 | |||
| 588 | ret = af9015_init_endpoint(d); | ||
| 589 | if (ret) | ||
| 590 | goto error; | ||
| 591 | |||
| 592 | ret = af9015_download_ir_table(d); | ||
| 593 | if (ret) | ||
| 594 | goto error; | ||
| 595 | |||
| 596 | error: | ||
| 597 | return ret; | ||
| 598 | } | ||
| 599 | |||
| 600 | static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 601 | { | ||
| 602 | int ret; | ||
| 603 | deb_info("%s: onoff:%d\n", __func__, onoff); | ||
| 604 | |||
| 605 | if (onoff) | ||
| 606 | ret = af9015_set_reg_bit(adap->dev, 0xd503, 0); | ||
| 607 | else | ||
| 608 | ret = af9015_clear_reg_bit(adap->dev, 0xd503, 0); | ||
| 609 | |||
| 610 | return ret; | ||
| 611 | } | ||
| 612 | |||
| 613 | static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | ||
| 614 | int onoff) | ||
| 615 | { | ||
| 616 | int ret; | ||
| 617 | u8 idx; | ||
| 618 | |||
| 619 | deb_info("%s: set pid filter, index %d, pid %x, onoff %d\n", | ||
| 620 | __func__, index, pid, onoff); | ||
| 621 | |||
| 622 | ret = af9015_write_reg(adap->dev, 0xd505, (pid & 0xff)); | ||
| 623 | if (ret) | ||
| 624 | goto error; | ||
| 625 | |||
| 626 | ret = af9015_write_reg(adap->dev, 0xd506, (pid >> 8)); | ||
| 627 | if (ret) | ||
| 628 | goto error; | ||
| 629 | |||
| 630 | idx = ((index & 0x1f) | (1 << 5)); | ||
| 631 | ret = af9015_write_reg(adap->dev, 0xd504, idx); | ||
| 632 | |||
| 633 | error: | ||
| 634 | return ret; | ||
| 635 | } | ||
| 636 | |||
| 637 | static int af9015_download_firmware(struct usb_device *udev, | ||
| 638 | const struct firmware *fw) | ||
| 639 | { | ||
| 640 | int i, len, packets, remainder, ret; | ||
| 641 | struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL}; | ||
| 642 | u16 addr = 0x5100; /* firmware start address */ | ||
| 643 | u16 checksum = 0; | ||
| 644 | |||
| 645 | deb_info("%s:\n", __func__); | ||
| 646 | |||
| 647 | /* calc checksum */ | ||
| 648 | for (i = 0; i < fw->size; i++) | ||
| 649 | checksum += fw->data[i]; | ||
| 650 | |||
| 651 | af9015_config.firmware_size = fw->size; | ||
| 652 | af9015_config.firmware_checksum = checksum; | ||
| 653 | |||
| 654 | #define FW_PACKET_MAX_DATA 55 | ||
| 655 | |||
| 656 | packets = fw->size / FW_PACKET_MAX_DATA; | ||
| 657 | remainder = fw->size % FW_PACKET_MAX_DATA; | ||
| 658 | len = FW_PACKET_MAX_DATA; | ||
| 659 | for (i = 0; i <= packets; i++) { | ||
| 660 | if (i == packets) /* set size of the last packet */ | ||
| 661 | len = remainder; | ||
| 662 | |||
| 663 | req.data_len = len; | ||
| 664 | req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA); | ||
| 665 | req.addr = addr; | ||
| 666 | addr += FW_PACKET_MAX_DATA; | ||
| 667 | |||
| 668 | ret = af9015_rw_udev(udev, &req); | ||
| 669 | if (ret) { | ||
| 670 | err("firmware download failed at packet %d with " \ | ||
| 671 | "code %d", i, ret); | ||
| 672 | goto error; | ||
| 673 | } | ||
| 674 | } | ||
| 675 | |||
| 676 | /* firmware loaded, request boot */ | ||
| 677 | req.cmd = BOOT; | ||
| 678 | ret = af9015_rw_udev(udev, &req); | ||
| 679 | if (ret) { | ||
| 680 | err("firmware boot failed:%d", ret); | ||
| 681 | goto error; | ||
| 682 | } | ||
| 683 | |||
| 684 | /* firmware is running, reconnect device in the usb bus */ | ||
| 685 | req.cmd = RECONNECT_USB; | ||
| 686 | ret = af9015_rw_udev(udev, &req); | ||
| 687 | if (ret) | ||
| 688 | err("reconnect failed: %d", ret); | ||
| 689 | |||
| 690 | error: | ||
| 691 | return ret; | ||
| 692 | } | ||
| 693 | |||
| 694 | static int af9015_read_config(struct usb_device *udev) | ||
| 695 | { | ||
| 696 | int ret; | ||
| 697 | u8 val, i, offset = 0; | ||
| 698 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; | ||
| 699 | char manufacturer[10]; | ||
| 700 | |||
| 701 | /* IR remote controller */ | ||
| 702 | req.addr = AF9015_EEPROM_IR_MODE; | ||
| 703 | ret = af9015_rw_udev(udev, &req); | ||
| 704 | if (ret) | ||
| 705 | goto error; | ||
| 706 | deb_info("%s: IR mode:%d\n", __func__, val); | ||
| 707 | for (i = 0; i < af9015_properties_count; i++) { | ||
| 708 | if (val == AF9015_IR_MODE_DISABLED || val == 0x04) { | ||
| 709 | af9015_properties[i].rc_key_map = NULL; | ||
| 710 | af9015_properties[i].rc_key_map_size = 0; | ||
| 711 | } else if (dvb_usb_af9015_remote) { | ||
| 712 | /* load remote defined as module param */ | ||
| 713 | switch (dvb_usb_af9015_remote) { | ||
| 714 | case AF9015_REMOTE_A_LINK_DTU_M: | ||
| 715 | af9015_properties[i].rc_key_map = | ||
| 716 | af9015_rc_keys_a_link; | ||
| 717 | af9015_properties[i].rc_key_map_size = | ||
| 718 | ARRAY_SIZE(af9015_rc_keys_a_link); | ||
| 719 | af9015_config.ir_table = af9015_ir_table_a_link; | ||
| 720 | af9015_config.ir_table_size = | ||
| 721 | ARRAY_SIZE(af9015_ir_table_a_link); | ||
| 722 | break; | ||
| 723 | case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3: | ||
| 724 | af9015_properties[i].rc_key_map = | ||
| 725 | af9015_rc_keys_msi; | ||
| 726 | af9015_properties[i].rc_key_map_size = | ||
| 727 | ARRAY_SIZE(af9015_rc_keys_msi); | ||
| 728 | af9015_config.ir_table = af9015_ir_table_msi; | ||
| 729 | af9015_config.ir_table_size = | ||
| 730 | ARRAY_SIZE(af9015_ir_table_msi); | ||
| 731 | break; | ||
| 732 | case AF9015_REMOTE_MYGICTV_U718: | ||
| 733 | af9015_properties[i].rc_key_map = | ||
| 734 | af9015_rc_keys_mygictv; | ||
| 735 | af9015_properties[i].rc_key_map_size = | ||
| 736 | ARRAY_SIZE(af9015_rc_keys_mygictv); | ||
| 737 | af9015_config.ir_table = | ||
| 738 | af9015_ir_table_mygictv; | ||
| 739 | af9015_config.ir_table_size = | ||
| 740 | ARRAY_SIZE(af9015_ir_table_mygictv); | ||
| 741 | break; | ||
| 742 | } | ||
| 743 | } else { | ||
| 744 | switch (udev->descriptor.idVendor) { | ||
| 745 | case USB_VID_LEADTEK: | ||
| 746 | af9015_properties[i].rc_key_map = | ||
| 747 | af9015_rc_keys_leadtek; | ||
| 748 | af9015_properties[i].rc_key_map_size = | ||
| 749 | ARRAY_SIZE(af9015_rc_keys_leadtek); | ||
| 750 | af9015_config.ir_table = | ||
| 751 | af9015_ir_table_leadtek; | ||
| 752 | af9015_config.ir_table_size = | ||
| 753 | ARRAY_SIZE(af9015_ir_table_leadtek); | ||
| 754 | break; | ||
| 755 | case USB_VID_VISIONPLUS: | ||
| 756 | if (udev->descriptor.idProduct == | ||
| 757 | USB_PID_AZUREWAVE_AD_TU700) { | ||
| 758 | af9015_properties[i].rc_key_map = | ||
| 759 | af9015_rc_keys_twinhan; | ||
| 760 | af9015_properties[i].rc_key_map_size = | ||
| 761 | ARRAY_SIZE(af9015_rc_keys_twinhan); | ||
| 762 | af9015_config.ir_table = | ||
| 763 | af9015_ir_table_twinhan; | ||
| 764 | af9015_config.ir_table_size = | ||
| 765 | ARRAY_SIZE(af9015_ir_table_twinhan); | ||
| 766 | } | ||
| 767 | break; | ||
| 768 | case USB_VID_KWORLD_2: | ||
| 769 | /* TODO: use correct rc keys */ | ||
| 770 | af9015_properties[i].rc_key_map = | ||
| 771 | af9015_rc_keys_twinhan; | ||
| 772 | af9015_properties[i].rc_key_map_size = | ||
| 773 | ARRAY_SIZE(af9015_rc_keys_twinhan); | ||
| 774 | af9015_config.ir_table = af9015_ir_table_kworld; | ||
| 775 | af9015_config.ir_table_size = | ||
| 776 | ARRAY_SIZE(af9015_ir_table_kworld); | ||
| 777 | break; | ||
| 778 | /* Check USB manufacturer and product strings and try | ||
| 779 | to determine correct remote in case of chip vendor | ||
| 780 | reference IDs are used. */ | ||
| 781 | case USB_VID_AFATECH: | ||
| 782 | memset(manufacturer, 0, sizeof(manufacturer)); | ||
| 783 | usb_string(udev, udev->descriptor.iManufacturer, | ||
| 784 | manufacturer, sizeof(manufacturer)); | ||
| 785 | if (!strcmp("Geniatech", manufacturer)) { | ||
| 786 | /* iManufacturer 1 Geniatech | ||
| 787 | iProduct 2 AF9015 */ | ||
| 788 | af9015_properties[i].rc_key_map = | ||
| 789 | af9015_rc_keys_mygictv; | ||
| 790 | af9015_properties[i].rc_key_map_size = | ||
| 791 | ARRAY_SIZE(af9015_rc_keys_mygictv); | ||
| 792 | af9015_config.ir_table = | ||
| 793 | af9015_ir_table_mygictv; | ||
| 794 | af9015_config.ir_table_size = | ||
| 795 | ARRAY_SIZE(af9015_ir_table_mygictv); | ||
| 796 | } else if (!strcmp("MSI", manufacturer)) { | ||
| 797 | /* iManufacturer 1 MSI | ||
| 798 | iProduct 2 MSI K-VOX */ | ||
| 799 | af9015_properties[i].rc_key_map = | ||
| 800 | af9015_rc_keys_msi; | ||
| 801 | af9015_properties[i].rc_key_map_size = | ||
| 802 | ARRAY_SIZE(af9015_rc_keys_msi); | ||
| 803 | af9015_config.ir_table = | ||
| 804 | af9015_ir_table_msi; | ||
| 805 | af9015_config.ir_table_size = | ||
| 806 | ARRAY_SIZE(af9015_ir_table_msi); | ||
| 807 | } | ||
| 808 | break; | ||
| 809 | } | ||
| 810 | } | ||
| 811 | } | ||
| 812 | |||
| 813 | /* TS mode - one or two receivers */ | ||
| 814 | req.addr = AF9015_EEPROM_TS_MODE; | ||
| 815 | ret = af9015_rw_udev(udev, &req); | ||
| 816 | if (ret) | ||
| 817 | goto error; | ||
| 818 | af9015_config.dual_mode = val; | ||
| 819 | deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode); | ||
| 820 | /* disable dual mode by default because it is buggy */ | ||
| 821 | if (!dvb_usb_af9015_dual_mode) | ||
| 822 | af9015_config.dual_mode = 0; | ||
| 823 | |||
| 824 | /* set buffer size according to USB port speed */ | ||
| 825 | for (i = 0; i < af9015_properties_count; i++) { | ||
| 826 | /* USB1.1 set smaller buffersize and disable 2nd adapter */ | ||
| 827 | if (udev->speed == USB_SPEED_FULL) { | ||
| 828 | af9015_properties[i].adapter->stream.u.bulk.buffersize = | ||
| 829 | TS_USB11_MAX_PACKET_SIZE; | ||
| 830 | /* disable 2nd adapter because we don't have | ||
| 831 | PID-filters */ | ||
| 832 | af9015_config.dual_mode = 0; | ||
| 833 | } else { | ||
| 834 | af9015_properties[i].adapter->stream.u.bulk.buffersize = | ||
| 835 | TS_USB20_MAX_PACKET_SIZE; | ||
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 839 | if (af9015_config.dual_mode) { | ||
| 840 | /* read 2nd demodulator I2C address */ | ||
| 841 | req.addr = AF9015_EEPROM_DEMOD2_I2C; | ||
| 842 | ret = af9015_rw_udev(udev, &req); | ||
| 843 | if (ret) | ||
| 844 | goto error; | ||
| 845 | af9015_af9013_config[1].demod_address = val; | ||
| 846 | |||
| 847 | /* enable 2nd adapter */ | ||
| 848 | for (i = 0; i < af9015_properties_count; i++) | ||
| 849 | af9015_properties[i].num_adapters = 2; | ||
| 850 | |||
| 851 | } else { | ||
| 852 | /* disable 2nd adapter */ | ||
| 853 | for (i = 0; i < af9015_properties_count; i++) | ||
| 854 | af9015_properties[i].num_adapters = 1; | ||
| 855 | } | ||
| 856 | |||
| 857 | for (i = 0; i < af9015_properties[0].num_adapters; i++) { | ||
| 858 | if (i == 1) | ||
| 859 | offset = AF9015_EEPROM_OFFSET; | ||
| 860 | /* xtal */ | ||
| 861 | req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset; | ||
| 862 | ret = af9015_rw_udev(udev, &req); | ||
| 863 | if (ret) | ||
| 864 | goto error; | ||
| 865 | switch (val) { | ||
| 866 | case 0: | ||
| 867 | af9015_af9013_config[i].adc_clock = 28800; | ||
| 868 | break; | ||
| 869 | case 1: | ||
| 870 | af9015_af9013_config[i].adc_clock = 20480; | ||
| 871 | break; | ||
| 872 | case 2: | ||
| 873 | af9015_af9013_config[i].adc_clock = 28000; | ||
| 874 | break; | ||
| 875 | case 3: | ||
| 876 | af9015_af9013_config[i].adc_clock = 25000; | ||
| 877 | break; | ||
| 878 | }; | ||
| 879 | deb_info("%s: [%d] xtal:%d set adc_clock:%d\n", __func__, i, | ||
| 880 | val, af9015_af9013_config[i].adc_clock); | ||
| 881 | |||
| 882 | /* tuner IF */ | ||
| 883 | req.addr = AF9015_EEPROM_IF1H + offset; | ||
| 884 | ret = af9015_rw_udev(udev, &req); | ||
| 885 | if (ret) | ||
| 886 | goto error; | ||
| 887 | af9015_af9013_config[i].tuner_if = val << 8; | ||
| 888 | req.addr = AF9015_EEPROM_IF1L + offset; | ||
| 889 | ret = af9015_rw_udev(udev, &req); | ||
| 890 | if (ret) | ||
| 891 | goto error; | ||
| 892 | af9015_af9013_config[i].tuner_if += val; | ||
| 893 | deb_info("%s: [%d] IF1:%d\n", __func__, i, | ||
| 894 | af9015_af9013_config[0].tuner_if); | ||
| 895 | |||
| 896 | /* MT2060 IF1 */ | ||
| 897 | req.addr = AF9015_EEPROM_MT2060_IF1H + offset; | ||
| 898 | ret = af9015_rw_udev(udev, &req); | ||
| 899 | if (ret) | ||
| 900 | goto error; | ||
| 901 | af9015_config.mt2060_if1[i] = val << 8; | ||
| 902 | req.addr = AF9015_EEPROM_MT2060_IF1L + offset; | ||
| 903 | ret = af9015_rw_udev(udev, &req); | ||
| 904 | if (ret) | ||
| 905 | goto error; | ||
| 906 | af9015_config.mt2060_if1[i] += val; | ||
| 907 | deb_info("%s: [%d] MT2060 IF1:%d\n", __func__, i, | ||
| 908 | af9015_config.mt2060_if1[i]); | ||
| 909 | |||
| 910 | /* tuner */ | ||
| 911 | req.addr = AF9015_EEPROM_TUNER_ID1 + offset; | ||
| 912 | ret = af9015_rw_udev(udev, &req); | ||
| 913 | if (ret) | ||
| 914 | goto error; | ||
| 915 | switch (val) { | ||
| 916 | case AF9013_TUNER_ENV77H11D5: | ||
| 917 | case AF9013_TUNER_MT2060: | ||
| 918 | case AF9013_TUNER_MC44S803: | ||
| 919 | case AF9013_TUNER_QT1010: | ||
| 920 | case AF9013_TUNER_UNKNOWN: | ||
| 921 | case AF9013_TUNER_MT2060_2: | ||
| 922 | case AF9013_TUNER_TDA18271: | ||
| 923 | case AF9013_TUNER_QT1010A: | ||
| 924 | af9015_af9013_config[i].rf_spec_inv = 1; | ||
| 925 | break; | ||
| 926 | case AF9013_TUNER_MXL5003D: | ||
| 927 | case AF9013_TUNER_MXL5005D: | ||
| 928 | case AF9013_TUNER_MXL5005R: | ||
| 929 | af9015_af9013_config[i].rf_spec_inv = 0; | ||
| 930 | break; | ||
| 931 | default: | ||
| 932 | warn("tuner id:%d not supported, please report!", val); | ||
| 933 | return -ENODEV; | ||
| 934 | }; | ||
| 935 | |||
| 936 | af9015_af9013_config[i].tuner = val; | ||
| 937 | deb_info("%s: [%d] tuner id:%d\n", __func__, i, val); | ||
| 938 | } | ||
| 939 | |||
| 940 | error: | ||
| 941 | if (ret) | ||
| 942 | err("eeprom read failed:%d", ret); | ||
| 943 | |||
| 944 | return ret; | ||
| 945 | } | ||
| 946 | |||
| 947 | static int af9015_identify_state(struct usb_device *udev, | ||
| 948 | struct dvb_usb_device_properties *props, | ||
| 949 | struct dvb_usb_device_description **desc, | ||
| 950 | int *cold) | ||
| 951 | { | ||
| 952 | int ret; | ||
| 953 | u8 reply; | ||
| 954 | struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply}; | ||
| 955 | |||
| 956 | ret = af9015_rw_udev(udev, &req); | ||
| 957 | if (ret) | ||
| 958 | return ret; | ||
| 959 | |||
| 960 | deb_info("%s: reply:%02x\n", __func__, reply); | ||
| 961 | if (reply == 0x02) | ||
| 962 | *cold = 0; | ||
| 963 | else | ||
| 964 | *cold = 1; | ||
| 965 | |||
| 966 | return ret; | ||
| 967 | } | ||
| 968 | |||
| 969 | static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 970 | { | ||
| 971 | u8 buf[8]; | ||
| 972 | struct req_t req = {GET_IR_CODE, 0, 0, 0, 0, sizeof(buf), buf}; | ||
| 973 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | ||
| 974 | int i, ret; | ||
| 975 | |||
| 976 | memset(buf, 0, sizeof(buf)); | ||
| 977 | |||
| 978 | ret = af9015_ctrl_msg(d, &req); | ||
| 979 | if (ret) | ||
| 980 | return ret; | ||
| 981 | |||
| 982 | *event = 0; | ||
| 983 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 984 | |||
| 985 | for (i = 0; i < d->props.rc_key_map_size; i++) { | ||
| 986 | if (!buf[1] && keymap[i].custom == buf[0] && | ||
| 987 | keymap[i].data == buf[2]) { | ||
| 988 | *event = keymap[i].event; | ||
| 989 | *state = REMOTE_KEY_PRESSED; | ||
| 990 | break; | ||
| 991 | } | ||
| 992 | } | ||
| 993 | if (!buf[1]) | ||
| 994 | deb_rc("%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
| 995 | __func__, buf[0], buf[1], buf[2], buf[3], buf[4], | ||
| 996 | buf[5], buf[6], buf[7]); | ||
| 997 | |||
| 998 | return 0; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | /* init 2nd I2C adapter */ | ||
| 1002 | int af9015_i2c_init(struct dvb_usb_device *d) | ||
| 1003 | { | ||
| 1004 | int ret; | ||
| 1005 | struct af9015_state *state = d->priv; | ||
| 1006 | deb_info("%s:\n", __func__); | ||
| 1007 | |||
| 1008 | strncpy(state->i2c_adap.name, d->desc->name, | ||
| 1009 | sizeof(state->i2c_adap.name)); | ||
| 1010 | #ifdef I2C_ADAP_CLASS_TV_DIGITAL | ||
| 1011 | state->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL, | ||
| 1012 | #else | ||
| 1013 | state->i2c_adap.class = I2C_CLASS_TV_DIGITAL, | ||
| 1014 | #endif | ||
| 1015 | state->i2c_adap.algo = d->props.i2c_algo; | ||
| 1016 | state->i2c_adap.algo_data = NULL; | ||
| 1017 | state->i2c_adap.dev.parent = &d->udev->dev; | ||
| 1018 | |||
| 1019 | i2c_set_adapdata(&state->i2c_adap, d); | ||
| 1020 | |||
| 1021 | ret = i2c_add_adapter(&state->i2c_adap); | ||
| 1022 | if (ret < 0) | ||
| 1023 | err("could not add i2c adapter"); | ||
| 1024 | |||
| 1025 | return ret; | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1029 | { | ||
| 1030 | int ret; | ||
| 1031 | struct af9015_state *state = adap->dev->priv; | ||
| 1032 | struct i2c_adapter *i2c_adap; | ||
| 1033 | |||
| 1034 | if (adap->id == 0) { | ||
| 1035 | /* select I2C adapter */ | ||
| 1036 | i2c_adap = &adap->dev->i2c_adap; | ||
| 1037 | |||
| 1038 | deb_info("%s: init I2C\n", __func__); | ||
| 1039 | ret = af9015_i2c_init(adap->dev); | ||
| 1040 | |||
| 1041 | /* dump eeprom (debug) */ | ||
| 1042 | ret = af9015_eeprom_dump(adap->dev); | ||
| 1043 | if (ret) | ||
| 1044 | return ret; | ||
| 1045 | } else { | ||
| 1046 | /* select I2C adapter */ | ||
| 1047 | i2c_adap = &state->i2c_adap; | ||
| 1048 | |||
| 1049 | /* copy firmware to 2nd demodulator */ | ||
| 1050 | if (af9015_config.dual_mode) { | ||
| 1051 | ret = af9015_copy_firmware(adap->dev); | ||
| 1052 | if (ret) { | ||
| 1053 | err("firmware copy to 2nd frontend " \ | ||
| 1054 | "failed, will disable it"); | ||
| 1055 | af9015_config.dual_mode = 0; | ||
| 1056 | return -ENODEV; | ||
| 1057 | } | ||
| 1058 | } else { | ||
| 1059 | return -ENODEV; | ||
| 1060 | } | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | /* attach demodulator */ | ||
| 1064 | adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id], | ||
| 1065 | i2c_adap); | ||
| 1066 | |||
| 1067 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | static struct mt2060_config af9015_mt2060_config = { | ||
| 1071 | .i2c_address = 0xc0, | ||
| 1072 | .clock_out = 0, | ||
| 1073 | }; | ||
| 1074 | |||
| 1075 | static struct qt1010_config af9015_qt1010_config = { | ||
| 1076 | .i2c_address = 0xc4, | ||
| 1077 | }; | ||
| 1078 | |||
| 1079 | static struct tda18271_config af9015_tda18271_config = { | ||
| 1080 | .gate = TDA18271_GATE_DIGITAL, | ||
| 1081 | .small_i2c = 1, | ||
| 1082 | }; | ||
| 1083 | |||
| 1084 | static struct mxl5005s_config af9015_mxl5003_config = { | ||
| 1085 | .i2c_address = 0xc6, | ||
| 1086 | .if_freq = IF_FREQ_4570000HZ, | ||
| 1087 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
| 1088 | .agc_mode = MXL_SINGLE_AGC, | ||
| 1089 | .tracking_filter = MXL_TF_DEFAULT, | ||
| 1090 | .rssi_enable = MXL_RSSI_ENABLE, | ||
| 1091 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
| 1092 | .div_out = MXL_DIV_OUT_4, | ||
| 1093 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
| 1094 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
| 1095 | .top = MXL5005S_TOP_25P2, | ||
| 1096 | .mod_mode = MXL_DIGITAL_MODE, | ||
| 1097 | .if_mode = MXL_ZERO_IF, | ||
| 1098 | .AgcMasterByte = 0x00, | ||
| 1099 | }; | ||
| 1100 | |||
| 1101 | static struct mxl5005s_config af9015_mxl5005_config = { | ||
| 1102 | .i2c_address = 0xc6, | ||
| 1103 | .if_freq = IF_FREQ_4570000HZ, | ||
| 1104 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
| 1105 | .agc_mode = MXL_SINGLE_AGC, | ||
| 1106 | .tracking_filter = MXL_TF_OFF, | ||
| 1107 | .rssi_enable = MXL_RSSI_ENABLE, | ||
| 1108 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
| 1109 | .div_out = MXL_DIV_OUT_4, | ||
| 1110 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
| 1111 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
| 1112 | .top = MXL5005S_TOP_25P2, | ||
| 1113 | .mod_mode = MXL_DIGITAL_MODE, | ||
| 1114 | .if_mode = MXL_ZERO_IF, | ||
| 1115 | .AgcMasterByte = 0x00, | ||
| 1116 | }; | ||
| 1117 | |||
| 1118 | static int af9015_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1119 | { | ||
| 1120 | struct af9015_state *state = adap->dev->priv; | ||
| 1121 | struct i2c_adapter *i2c_adap; | ||
| 1122 | int ret; | ||
| 1123 | deb_info("%s: \n", __func__); | ||
| 1124 | |||
| 1125 | /* select I2C adapter */ | ||
| 1126 | if (adap->id == 0) | ||
| 1127 | i2c_adap = &adap->dev->i2c_adap; | ||
| 1128 | else | ||
| 1129 | i2c_adap = &state->i2c_adap; | ||
| 1130 | |||
| 1131 | switch (af9015_af9013_config[adap->id].tuner) { | ||
| 1132 | case AF9013_TUNER_MT2060: | ||
| 1133 | case AF9013_TUNER_MT2060_2: | ||
| 1134 | ret = dvb_attach(mt2060_attach, adap->fe, i2c_adap, | ||
| 1135 | &af9015_mt2060_config, | ||
| 1136 | af9015_config.mt2060_if1[adap->id]) | ||
| 1137 | == NULL ? -ENODEV : 0; | ||
| 1138 | break; | ||
| 1139 | case AF9013_TUNER_QT1010: | ||
| 1140 | case AF9013_TUNER_QT1010A: | ||
| 1141 | ret = dvb_attach(qt1010_attach, adap->fe, i2c_adap, | ||
| 1142 | &af9015_qt1010_config) == NULL ? -ENODEV : 0; | ||
| 1143 | break; | ||
| 1144 | case AF9013_TUNER_TDA18271: | ||
| 1145 | ret = dvb_attach(tda18271_attach, adap->fe, 0xc0, i2c_adap, | ||
| 1146 | &af9015_tda18271_config) == NULL ? -ENODEV : 0; | ||
| 1147 | break; | ||
| 1148 | case AF9013_TUNER_MXL5003D: | ||
| 1149 | ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap, | ||
| 1150 | &af9015_mxl5003_config) == NULL ? -ENODEV : 0; | ||
| 1151 | break; | ||
| 1152 | case AF9013_TUNER_MXL5005D: | ||
| 1153 | case AF9013_TUNER_MXL5005R: | ||
| 1154 | ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap, | ||
| 1155 | &af9015_mxl5005_config) == NULL ? -ENODEV : 0; | ||
| 1156 | break; | ||
| 1157 | case AF9013_TUNER_ENV77H11D5: | ||
| 1158 | ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0, i2c_adap, | ||
| 1159 | DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; | ||
| 1160 | break; | ||
| 1161 | case AF9013_TUNER_MC44S803: | ||
| 1162 | #if 0 | ||
| 1163 | ret = dvb_attach(mc44s80x_attach, adap->fe, i2c_adap) | ||
| 1164 | == NULL ? -ENODEV : 0; | ||
| 1165 | #else | ||
| 1166 | ret = -ENODEV; | ||
| 1167 | info("Freescale MC44S803 tuner found but no driver for that" \ | ||
| 1168 | "tuner. Look at the Linuxtv.org for tuner driver" \ | ||
| 1169 | "status."); | ||
| 1170 | #endif | ||
| 1171 | break; | ||
| 1172 | case AF9013_TUNER_UNKNOWN: | ||
| 1173 | default: | ||
| 1174 | ret = -ENODEV; | ||
| 1175 | err("Unknown tuner id:%d", | ||
| 1176 | af9015_af9013_config[adap->id].tuner); | ||
| 1177 | } | ||
| 1178 | return ret; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | static struct usb_device_id af9015_usb_table[] = { | ||
| 1182 | /* 0 */{USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)}, | ||
| 1183 | {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)}, | ||
| 1184 | {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)}, | ||
| 1185 | {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)}, | ||
| 1186 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)}, | ||
| 1187 | /* 5 */{USB_DEVICE(USB_VID_VISIONPLUS, | ||
| 1188 | USB_PID_TINYTWIN)}, | ||
| 1189 | {USB_DEVICE(USB_VID_VISIONPLUS, | ||
| 1190 | USB_PID_AZUREWAVE_AD_TU700)}, | ||
| 1191 | {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)}, | ||
| 1192 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)}, | ||
| 1193 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)}, | ||
| 1194 | /* 10 */{USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)}, | ||
| 1195 | {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)}, | ||
| 1196 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)}, | ||
| 1197 | {USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)}, | ||
| 1198 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)}, | ||
| 1199 | /* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)}, | ||
| 1200 | {0}, | ||
| 1201 | }; | ||
| 1202 | MODULE_DEVICE_TABLE(usb, af9015_usb_table); | ||
| 1203 | |||
| 1204 | static struct dvb_usb_device_properties af9015_properties[] = { | ||
| 1205 | { | ||
| 1206 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1207 | |||
| 1208 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1209 | .download_firmware = af9015_download_firmware, | ||
| 1210 | .firmware = "dvb-usb-af9015.fw", | ||
| 1211 | |||
| 1212 | .size_of_priv = sizeof(struct af9015_state), \ | ||
| 1213 | |||
| 1214 | .num_adapters = 2, | ||
| 1215 | .adapter = { | ||
| 1216 | { | ||
| 1217 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 1218 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1219 | |||
| 1220 | .pid_filter_count = 32, | ||
| 1221 | .pid_filter = af9015_pid_filter, | ||
| 1222 | .pid_filter_ctrl = af9015_pid_filter_ctrl, | ||
| 1223 | |||
| 1224 | .frontend_attach = | ||
| 1225 | af9015_af9013_frontend_attach, | ||
| 1226 | .tuner_attach = af9015_tuner_attach, | ||
| 1227 | .stream = { | ||
| 1228 | .type = USB_BULK, | ||
| 1229 | .count = 6, | ||
| 1230 | .endpoint = 0x84, | ||
| 1231 | }, | ||
| 1232 | }, | ||
| 1233 | { | ||
| 1234 | .frontend_attach = | ||
| 1235 | af9015_af9013_frontend_attach, | ||
| 1236 | .tuner_attach = af9015_tuner_attach, | ||
| 1237 | .stream = { | ||
| 1238 | .type = USB_BULK, | ||
| 1239 | .count = 6, | ||
| 1240 | .endpoint = 0x85, | ||
| 1241 | }, | ||
| 1242 | } | ||
| 1243 | }, | ||
| 1244 | |||
| 1245 | .identify_state = af9015_identify_state, | ||
| 1246 | |||
| 1247 | .rc_query = af9015_rc_query, | ||
| 1248 | .rc_interval = 150, | ||
| 1249 | |||
| 1250 | .i2c_algo = &af9015_i2c_algo, | ||
| 1251 | |||
| 1252 | .num_device_descs = 9, | ||
| 1253 | .devices = { | ||
| 1254 | { | ||
| 1255 | .name = "Afatech AF9015 DVB-T USB2.0 stick", | ||
| 1256 | .cold_ids = {&af9015_usb_table[0], | ||
| 1257 | &af9015_usb_table[1], NULL}, | ||
| 1258 | .warm_ids = {NULL}, | ||
| 1259 | }, | ||
| 1260 | { | ||
| 1261 | .name = "Leadtek WinFast DTV Dongle Gold", | ||
| 1262 | .cold_ids = {&af9015_usb_table[2], NULL}, | ||
| 1263 | .warm_ids = {NULL}, | ||
| 1264 | }, | ||
| 1265 | { | ||
| 1266 | .name = "Pinnacle PCTV 71e", | ||
| 1267 | .cold_ids = {&af9015_usb_table[3], NULL}, | ||
| 1268 | .warm_ids = {NULL}, | ||
| 1269 | }, | ||
| 1270 | { | ||
| 1271 | .name = "KWorld PlusTV Dual DVB-T Stick " \ | ||
| 1272 | "(DVB-T 399U)", | ||
| 1273 | .cold_ids = {&af9015_usb_table[4], NULL}, | ||
| 1274 | .warm_ids = {NULL}, | ||
| 1275 | }, | ||
| 1276 | { | ||
| 1277 | .name = "DigitalNow TinyTwin DVB-T Receiver", | ||
| 1278 | .cold_ids = {&af9015_usb_table[5], NULL}, | ||
| 1279 | .warm_ids = {NULL}, | ||
| 1280 | }, | ||
| 1281 | { | ||
| 1282 | .name = "TwinHan AzureWave AD-TU700(704J)", | ||
| 1283 | .cold_ids = {&af9015_usb_table[6], NULL}, | ||
| 1284 | .warm_ids = {NULL}, | ||
| 1285 | }, | ||
| 1286 | { | ||
| 1287 | .name = "TerraTec Cinergy T USB XE", | ||
| 1288 | .cold_ids = {&af9015_usb_table[7], NULL}, | ||
| 1289 | .warm_ids = {NULL}, | ||
| 1290 | }, | ||
| 1291 | { | ||
| 1292 | .name = "KWorld PlusTV Dual DVB-T PCI " \ | ||
| 1293 | "(DVB-T PC160-2T)", | ||
| 1294 | .cold_ids = {&af9015_usb_table[8], NULL}, | ||
| 1295 | .warm_ids = {NULL}, | ||
| 1296 | }, | ||
| 1297 | { | ||
| 1298 | .name = "AVerMedia AVerTV DVB-T Volar X", | ||
| 1299 | .cold_ids = {&af9015_usb_table[9], NULL}, | ||
| 1300 | .warm_ids = {NULL}, | ||
| 1301 | }, | ||
| 1302 | } | ||
| 1303 | }, { | ||
| 1304 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1305 | |||
| 1306 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1307 | .download_firmware = af9015_download_firmware, | ||
| 1308 | .firmware = "dvb-usb-af9015.fw", | ||
| 1309 | |||
| 1310 | .size_of_priv = sizeof(struct af9015_state), \ | ||
| 1311 | |||
| 1312 | .num_adapters = 2, | ||
| 1313 | .adapter = { | ||
| 1314 | { | ||
| 1315 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 1316 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1317 | |||
| 1318 | .pid_filter_count = 32, | ||
| 1319 | .pid_filter = af9015_pid_filter, | ||
| 1320 | .pid_filter_ctrl = af9015_pid_filter_ctrl, | ||
| 1321 | |||
| 1322 | .frontend_attach = | ||
| 1323 | af9015_af9013_frontend_attach, | ||
| 1324 | .tuner_attach = af9015_tuner_attach, | ||
| 1325 | .stream = { | ||
| 1326 | .type = USB_BULK, | ||
| 1327 | .count = 6, | ||
| 1328 | .endpoint = 0x84, | ||
| 1329 | }, | ||
| 1330 | }, | ||
| 1331 | { | ||
| 1332 | .frontend_attach = | ||
| 1333 | af9015_af9013_frontend_attach, | ||
| 1334 | .tuner_attach = af9015_tuner_attach, | ||
| 1335 | .stream = { | ||
| 1336 | .type = USB_BULK, | ||
| 1337 | .count = 6, | ||
| 1338 | .endpoint = 0x85, | ||
| 1339 | }, | ||
| 1340 | } | ||
| 1341 | }, | ||
| 1342 | |||
| 1343 | .identify_state = af9015_identify_state, | ||
| 1344 | |||
| 1345 | .rc_query = af9015_rc_query, | ||
| 1346 | .rc_interval = 150, | ||
| 1347 | |||
| 1348 | .i2c_algo = &af9015_i2c_algo, | ||
| 1349 | |||
| 1350 | .num_device_descs = 6, | ||
| 1351 | .devices = { | ||
| 1352 | { | ||
| 1353 | .name = "Xtensions XD-380", | ||
| 1354 | .cold_ids = {&af9015_usb_table[10], NULL}, | ||
| 1355 | .warm_ids = {NULL}, | ||
| 1356 | }, | ||
| 1357 | { | ||
| 1358 | .name = "MSI DIGIVOX Duo", | ||
| 1359 | .cold_ids = {&af9015_usb_table[11], NULL}, | ||
| 1360 | .warm_ids = {NULL}, | ||
| 1361 | }, | ||
| 1362 | { | ||
| 1363 | .name = "Fujitsu-Siemens Slim Mobile USB DVB-T", | ||
| 1364 | .cold_ids = {&af9015_usb_table[12], NULL}, | ||
| 1365 | .warm_ids = {NULL}, | ||
| 1366 | }, | ||
| 1367 | { | ||
| 1368 | .name = "Telestar Starstick 2", | ||
| 1369 | .cold_ids = {&af9015_usb_table[13], NULL}, | ||
| 1370 | .warm_ids = {NULL}, | ||
| 1371 | }, | ||
| 1372 | { | ||
| 1373 | .name = "AVerMedia A309", | ||
| 1374 | .cold_ids = {&af9015_usb_table[14], NULL}, | ||
| 1375 | .warm_ids = {NULL}, | ||
| 1376 | }, | ||
| 1377 | { | ||
| 1378 | .name = "MSI Digi VOX mini III", | ||
| 1379 | .cold_ids = {&af9015_usb_table[15], NULL}, | ||
| 1380 | .warm_ids = {NULL}, | ||
| 1381 | }, | ||
| 1382 | } | ||
| 1383 | } | ||
| 1384 | }; | ||
| 1385 | |||
| 1386 | static int af9015_usb_probe(struct usb_interface *intf, | ||
| 1387 | const struct usb_device_id *id) | ||
| 1388 | { | ||
| 1389 | int ret = 0; | ||
| 1390 | struct dvb_usb_device *d = NULL; | ||
| 1391 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 1392 | u8 i; | ||
| 1393 | |||
| 1394 | deb_info("%s: interface:%d\n", __func__, | ||
| 1395 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
| 1396 | |||
| 1397 | /* interface 0 is used by DVB-T receiver and | ||
| 1398 | interface 1 is for remote controller (HID) */ | ||
| 1399 | if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { | ||
| 1400 | ret = af9015_read_config(udev); | ||
| 1401 | if (ret) | ||
| 1402 | return ret; | ||
| 1403 | |||
| 1404 | for (i = 0; i < af9015_properties_count; i++) { | ||
| 1405 | ret = dvb_usb_device_init(intf, &af9015_properties[i], | ||
| 1406 | THIS_MODULE, &d, adapter_nr); | ||
| 1407 | if (!ret) | ||
| 1408 | break; | ||
| 1409 | if (ret != -ENODEV) | ||
| 1410 | return ret; | ||
| 1411 | } | ||
| 1412 | if (ret) | ||
| 1413 | return ret; | ||
| 1414 | |||
| 1415 | if (d) | ||
| 1416 | ret = af9015_init(d); | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | return ret; | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | void af9015_i2c_exit(struct dvb_usb_device *d) | ||
| 1423 | { | ||
| 1424 | struct af9015_state *state = d->priv; | ||
| 1425 | deb_info("%s: \n", __func__); | ||
| 1426 | |||
| 1427 | /* remove 2nd I2C adapter */ | ||
| 1428 | if (d->state & DVB_USB_STATE_I2C) | ||
| 1429 | i2c_del_adapter(&state->i2c_adap); | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | static void af9015_usb_device_exit(struct usb_interface *intf) | ||
| 1433 | { | ||
| 1434 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
| 1435 | deb_info("%s: \n", __func__); | ||
| 1436 | |||
| 1437 | /* remove 2nd I2C adapter */ | ||
| 1438 | if (d != NULL && d->desc != NULL) | ||
| 1439 | af9015_i2c_exit(d); | ||
| 1440 | |||
| 1441 | dvb_usb_device_exit(intf); | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 1445 | static struct usb_driver af9015_usb_driver = { | ||
| 1446 | .name = "dvb_usb_af9015", | ||
| 1447 | .probe = af9015_usb_probe, | ||
| 1448 | .disconnect = af9015_usb_device_exit, | ||
| 1449 | .id_table = af9015_usb_table, | ||
| 1450 | }; | ||
| 1451 | |||
| 1452 | /* module stuff */ | ||
| 1453 | static int __init af9015_usb_module_init(void) | ||
| 1454 | { | ||
| 1455 | int ret; | ||
| 1456 | ret = usb_register(&af9015_usb_driver); | ||
| 1457 | if (ret) | ||
| 1458 | err("module init failed:%d", ret); | ||
| 1459 | |||
| 1460 | return ret; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | static void __exit af9015_usb_module_exit(void) | ||
| 1464 | { | ||
| 1465 | /* deregister this driver from the USB subsystem */ | ||
| 1466 | usb_deregister(&af9015_usb_driver); | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | module_init(af9015_usb_module_init); | ||
| 1470 | module_exit(af9015_usb_module_exit); | ||
| 1471 | |||
| 1472 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 1473 | MODULE_DESCRIPTION("Driver for Afatech AF9015 DVB-T"); | ||
| 1474 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h new file mode 100644 index 000000000000..882e8a4b3681 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9015.h | |||
| @@ -0,0 +1,524 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * Thanks to Afatech who kindly provided information. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef _DVB_USB_AF9015_H_ | ||
| 25 | #define _DVB_USB_AF9015_H_ | ||
| 26 | |||
| 27 | #define DVB_USB_LOG_PREFIX "af9015" | ||
| 28 | #include "dvb-usb.h" | ||
| 29 | |||
| 30 | extern int dvb_usb_af9015_debug; | ||
| 31 | #define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args) | ||
| 32 | #define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args) | ||
| 33 | #define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args) | ||
| 34 | #define deb_reg(args...) dprintk(dvb_usb_af9015_debug, 0x08, args) | ||
| 35 | #define deb_i2c(args...) dprintk(dvb_usb_af9015_debug, 0x10, args) | ||
| 36 | #define deb_fw(args...) dprintk(dvb_usb_af9015_debug, 0x20, args) | ||
| 37 | |||
| 38 | #define AF9015_I2C_EEPROM 0xa0 | ||
| 39 | #define AF9015_I2C_DEMOD 0x38 | ||
| 40 | #define AF9015_USB_TIMEOUT 2000 | ||
| 41 | |||
| 42 | /* EEPROM locations */ | ||
| 43 | #define AF9015_EEPROM_IR_MODE 0x18 | ||
| 44 | #define AF9015_EEPROM_IR_REMOTE_TYPE 0x34 | ||
| 45 | #define AF9015_EEPROM_TS_MODE 0x31 | ||
| 46 | #define AF9015_EEPROM_DEMOD2_I2C 0x32 | ||
| 47 | |||
| 48 | #define AF9015_EEPROM_SAW_BW1 0x35 | ||
| 49 | #define AF9015_EEPROM_XTAL_TYPE1 0x36 | ||
| 50 | #define AF9015_EEPROM_SPEC_INV1 0x37 | ||
| 51 | #define AF9015_EEPROM_IF1L 0x38 | ||
| 52 | #define AF9015_EEPROM_IF1H 0x39 | ||
| 53 | #define AF9015_EEPROM_MT2060_IF1L 0x3a | ||
| 54 | #define AF9015_EEPROM_MT2060_IF1H 0x3b | ||
| 55 | #define AF9015_EEPROM_TUNER_ID1 0x3c | ||
| 56 | |||
| 57 | #define AF9015_EEPROM_SAW_BW2 0x45 | ||
| 58 | #define AF9015_EEPROM_XTAL_TYPE2 0x46 | ||
| 59 | #define AF9015_EEPROM_SPEC_INV2 0x47 | ||
| 60 | #define AF9015_EEPROM_IF2L 0x48 | ||
| 61 | #define AF9015_EEPROM_IF2H 0x49 | ||
| 62 | #define AF9015_EEPROM_MT2060_IF2L 0x4a | ||
| 63 | #define AF9015_EEPROM_MT2060_IF2H 0x4b | ||
| 64 | #define AF9015_EEPROM_TUNER_ID2 0x4c | ||
| 65 | |||
| 66 | #define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1) | ||
| 67 | |||
| 68 | #define AF9015_GPIO_ON (1 << 0) | ||
| 69 | #define AF9015_GPIO_EN (1 << 1) | ||
| 70 | #define AF9015_GPIO_O (1 << 2) | ||
| 71 | #define AF9015_GPIO_I (1 << 3) | ||
| 72 | |||
| 73 | #define AF9015_GPIO_TUNER_ON (AF9015_GPIO_ON|AF9015_GPIO_EN) | ||
| 74 | #define AF9015_GPIO_TUNER_OFF (AF9015_GPIO_ON|AF9015_GPIO_EN|AF9015_GPIO_O) | ||
| 75 | |||
| 76 | struct req_t { | ||
| 77 | u8 cmd; /* [0] */ | ||
| 78 | /* seq */ /* [1] */ | ||
| 79 | u8 i2c_addr; /* [2] */ | ||
| 80 | u16 addr; /* [3|4] */ | ||
| 81 | u8 mbox; /* [5] */ | ||
| 82 | u8 addr_len; /* [6] */ | ||
| 83 | u8 data_len; /* [7] */ | ||
| 84 | u8 *data; | ||
| 85 | }; | ||
| 86 | |||
| 87 | enum af9015_cmd { | ||
| 88 | GET_CONFIG = 0x10, | ||
| 89 | DOWNLOAD_FIRMWARE = 0x11, | ||
| 90 | BOOT = 0x13, | ||
| 91 | READ_MEMORY = 0x20, | ||
| 92 | WRITE_MEMORY = 0x21, | ||
| 93 | READ_WRITE_I2C = 0x22, | ||
| 94 | COPY_FIRMWARE = 0x23, | ||
| 95 | RECONNECT_USB = 0x5a, | ||
| 96 | WRITE_VIRTUAL_MEMORY = 0x26, | ||
| 97 | GET_IR_CODE = 0x27, | ||
| 98 | READ_I2C, | ||
| 99 | WRITE_I2C, | ||
| 100 | }; | ||
| 101 | |||
| 102 | enum af9015_ir_mode { | ||
| 103 | AF9015_IR_MODE_DISABLED = 0, | ||
| 104 | AF9015_IR_MODE_HID, | ||
| 105 | AF9015_IR_MODE_RLC, | ||
| 106 | AF9015_IR_MODE_RC6, | ||
| 107 | }; | ||
| 108 | |||
| 109 | struct af9015_state { | ||
| 110 | struct i2c_adapter i2c_adap; /* I2C adapter for 2nd FE */ | ||
| 111 | }; | ||
| 112 | |||
| 113 | struct af9015_config { | ||
| 114 | u8 dual_mode:1; | ||
| 115 | u16 mt2060_if1[2]; | ||
| 116 | u16 firmware_size; | ||
| 117 | u16 firmware_checksum; | ||
| 118 | u8 *ir_table; | ||
| 119 | u16 ir_table_size; | ||
| 120 | }; | ||
| 121 | |||
| 122 | enum af9015_remote { | ||
| 123 | AF9015_REMOTE_NONE = 0, | ||
| 124 | AF9015_REMOTE_A_LINK_DTU_M, | ||
| 125 | AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, | ||
| 126 | AF9015_REMOTE_MYGICTV_U718, | ||
| 127 | }; | ||
| 128 | |||
| 129 | /* Leadtek WinFast DTV Dongle Gold */ | ||
| 130 | static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = { | ||
| 131 | { 0x00, 0x1e, KEY_1 }, | ||
| 132 | { 0x00, 0x1f, KEY_2 }, | ||
| 133 | { 0x00, 0x20, KEY_3 }, | ||
| 134 | { 0x00, 0x21, KEY_4 }, | ||
| 135 | { 0x00, 0x22, KEY_5 }, | ||
| 136 | { 0x00, 0x23, KEY_6 }, | ||
| 137 | { 0x00, 0x24, KEY_7 }, | ||
| 138 | { 0x00, 0x25, KEY_8 }, | ||
| 139 | { 0x00, 0x26, KEY_9 }, | ||
| 140 | { 0x00, 0x27, KEY_0 }, | ||
| 141 | { 0x00, 0x28, KEY_ENTER }, | ||
| 142 | { 0x00, 0x4f, KEY_VOLUMEUP }, | ||
| 143 | { 0x00, 0x50, KEY_VOLUMEDOWN }, | ||
| 144 | { 0x00, 0x51, KEY_CHANNELDOWN }, | ||
| 145 | { 0x00, 0x52, KEY_CHANNELUP }, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static u8 af9015_ir_table_leadtek[] = { | ||
| 149 | 0x03, 0xfc, 0x00, 0xff, 0x1a, 0x01, 0x00, | ||
| 150 | 0x03, 0xfc, 0x56, 0xa9, 0x00, 0x00, 0x00, | ||
| 151 | 0x03, 0xfc, 0x4b, 0xb4, 0x00, 0x00, 0x00, | ||
| 152 | 0x03, 0xfc, 0x4c, 0xb3, 0xb2, 0x04, 0x00, | ||
| 153 | 0x03, 0xfc, 0x4d, 0xb2, 0x00, 0x00, 0x00, | ||
| 154 | 0x03, 0xfc, 0x4e, 0xb1, 0x00, 0x00, 0x00, | ||
| 155 | 0x03, 0xfc, 0x1f, 0xe0, 0x3d, 0x00, 0x00, | ||
| 156 | 0x03, 0xfc, 0x40, 0xbf, 0x13, 0x01, 0x00, | ||
| 157 | 0x03, 0xfc, 0x14, 0xeb, 0x10, 0x00, 0x00, | ||
| 158 | 0x03, 0xfc, 0x49, 0xb6, 0x05, 0x01, 0x00, | ||
| 159 | 0x03, 0xfc, 0x50, 0xaf, 0x29, 0x00, 0x00, | ||
| 160 | 0x03, 0xfc, 0x0c, 0xf3, 0x52, 0x00, 0x00, | ||
| 161 | 0x03, 0xfc, 0x03, 0xfc, 0x09, 0x00, 0x00, | ||
| 162 | 0x03, 0xfc, 0x08, 0xf7, 0x50, 0x00, 0x00, | ||
| 163 | 0x03, 0xfc, 0x13, 0xec, 0x28, 0x00, 0x00, | ||
| 164 | 0x03, 0xfc, 0x04, 0xfb, 0x4f, 0x00, 0x00, | ||
| 165 | 0x03, 0xfc, 0x4f, 0xb0, 0x0f, 0x01, 0x00, | ||
| 166 | 0x03, 0xfc, 0x10, 0xef, 0x51, 0x00, 0x00, | ||
| 167 | 0x03, 0xfc, 0x51, 0xae, 0x3f, 0x00, 0x00, | ||
| 168 | 0x03, 0xfc, 0x42, 0xbd, 0x13, 0x00, 0x00, | ||
| 169 | 0x03, 0xfc, 0x43, 0xbc, 0x00, 0x00, 0x00, | ||
| 170 | 0x03, 0xfc, 0x44, 0xbb, 0x11, 0x00, 0x00, | ||
| 171 | 0x03, 0xfc, 0x52, 0xad, 0x19, 0x00, 0x00, | ||
| 172 | 0x03, 0xfc, 0x54, 0xab, 0x05, 0x00, 0x00, | ||
| 173 | 0x03, 0xfc, 0x46, 0xb9, 0x29, 0x00, 0x00, | ||
| 174 | 0x03, 0xfc, 0x55, 0xaa, 0x2b, 0x00, 0x00, | ||
| 175 | 0x03, 0xfc, 0x53, 0xac, 0x41, 0x00, 0x00, | ||
| 176 | 0x03, 0xfc, 0x05, 0xfa, 0x1e, 0x00, 0x00, | ||
| 177 | 0x03, 0xfc, 0x06, 0xf9, 0x1f, 0x00, 0x00, | ||
| 178 | 0x03, 0xfc, 0x07, 0xf8, 0x20, 0x00, 0x00, | ||
| 179 | 0x03, 0xfc, 0x1e, 0xe1, 0x19, 0x00, 0x00, | ||
| 180 | 0x03, 0xfc, 0x09, 0xf6, 0x21, 0x00, 0x00, | ||
| 181 | 0x03, 0xfc, 0x0a, 0xf5, 0x22, 0x00, 0x00, | ||
| 182 | 0x03, 0xfc, 0x0b, 0xf4, 0x23, 0x00, 0x00, | ||
| 183 | 0x03, 0xfc, 0x1b, 0xe4, 0x16, 0x00, 0x00, | ||
| 184 | 0x03, 0xfc, 0x0d, 0xf2, 0x24, 0x00, 0x00, | ||
| 185 | 0x03, 0xfc, 0x0e, 0xf1, 0x25, 0x00, 0x00, | ||
| 186 | 0x03, 0xfc, 0x0f, 0xf0, 0x26, 0x00, 0x00, | ||
| 187 | 0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00, | ||
| 188 | 0x03, 0xfc, 0x41, 0xbe, 0x37, 0x00, 0x00, | ||
| 189 | 0x03, 0xfc, 0x12, 0xed, 0x27, 0x00, 0x00, | ||
| 190 | 0x03, 0xfc, 0x11, 0xee, 0x2a, 0x00, 0x00, | ||
| 191 | 0x03, 0xfc, 0x48, 0xb7, 0x2c, 0x00, 0x00, | ||
| 192 | 0x03, 0xfc, 0x4a, 0xb5, 0x3c, 0x00, 0x00, | ||
| 193 | 0x03, 0xfc, 0x47, 0xb8, 0x15, 0x01, 0x00, | ||
| 194 | 0x03, 0xfc, 0x45, 0xba, 0x0b, 0x01, 0x00, | ||
| 195 | 0x03, 0xfc, 0x5e, 0xa1, 0x43, 0x00, 0x00, | ||
| 196 | 0x03, 0xfc, 0x5a, 0xa5, 0x42, 0x00, 0x00, | ||
| 197 | 0x03, 0xfc, 0x5b, 0xa4, 0x4b, 0x00, 0x00, | ||
| 198 | 0x03, 0xfc, 0x5f, 0xa0, 0x4e, 0x00, 0x00, | ||
| 199 | }; | ||
| 200 | |||
| 201 | /* TwinHan AzureWave AD-TU700(704J) */ | ||
| 202 | static struct dvb_usb_rc_key af9015_rc_keys_twinhan[] = { | ||
| 203 | { 0x05, 0x3f, KEY_POWER }, | ||
| 204 | { 0x00, 0x19, KEY_FAVORITES }, /* Favorite List */ | ||
| 205 | { 0x00, 0x04, KEY_TEXT }, /* Teletext */ | ||
| 206 | { 0x00, 0x0e, KEY_POWER }, | ||
| 207 | { 0x00, 0x0e, KEY_INFO }, /* Preview */ | ||
| 208 | { 0x00, 0x08, KEY_EPG }, /* Info/EPG */ | ||
| 209 | { 0x00, 0x0f, KEY_LIST }, /* Record List */ | ||
| 210 | { 0x00, 0x1e, KEY_1 }, | ||
| 211 | { 0x00, 0x1f, KEY_2 }, | ||
| 212 | { 0x00, 0x20, KEY_3 }, | ||
| 213 | { 0x00, 0x21, KEY_4 }, | ||
| 214 | { 0x00, 0x22, KEY_5 }, | ||
| 215 | { 0x00, 0x23, KEY_6 }, | ||
| 216 | { 0x00, 0x24, KEY_7 }, | ||
| 217 | { 0x00, 0x25, KEY_8 }, | ||
| 218 | { 0x00, 0x26, KEY_9 }, | ||
| 219 | { 0x00, 0x27, KEY_0 }, | ||
| 220 | { 0x00, 0x29, KEY_CANCEL }, /* Cancel */ | ||
| 221 | { 0x00, 0x4c, KEY_CLEAR }, /* Clear */ | ||
| 222 | { 0x00, 0x2a, KEY_BACK }, /* Back */ | ||
| 223 | { 0x00, 0x2b, KEY_TAB }, /* Tab */ | ||
| 224 | { 0x00, 0x52, KEY_UP }, /* up arrow */ | ||
| 225 | { 0x00, 0x51, KEY_DOWN }, /* down arrow */ | ||
| 226 | { 0x00, 0x4f, KEY_RIGHT }, /* right arrow */ | ||
| 227 | { 0x00, 0x50, KEY_LEFT }, /* left arrow */ | ||
| 228 | { 0x00, 0x28, KEY_ENTER }, /* Enter / ok */ | ||
| 229 | { 0x02, 0x52, KEY_VOLUMEUP }, | ||
| 230 | { 0x02, 0x51, KEY_VOLUMEDOWN }, | ||
| 231 | { 0x00, 0x4e, KEY_CHANNELDOWN }, | ||
| 232 | { 0x00, 0x4b, KEY_CHANNELUP }, | ||
| 233 | { 0x00, 0x4a, KEY_RECORD }, | ||
| 234 | { 0x01, 0x11, KEY_PLAY }, | ||
| 235 | { 0x00, 0x17, KEY_PAUSE }, | ||
| 236 | { 0x00, 0x0c, KEY_REWIND }, /* FR << */ | ||
| 237 | { 0x00, 0x11, KEY_FASTFORWARD }, /* FF >> */ | ||
| 238 | { 0x01, 0x15, KEY_PREVIOUS }, /* Replay */ | ||
| 239 | { 0x01, 0x0e, KEY_NEXT }, /* Skip */ | ||
| 240 | { 0x00, 0x13, KEY_CAMERA }, /* Capture */ | ||
| 241 | { 0x01, 0x0f, KEY_LANGUAGE }, /* SAP */ | ||
| 242 | { 0x01, 0x13, KEY_TV2 }, /* PIP */ | ||
| 243 | { 0x00, 0x1d, KEY_ZOOM }, /* Full Screen */ | ||
| 244 | { 0x01, 0x17, KEY_SUBTITLE }, /* Subtitle / CC */ | ||
| 245 | { 0x00, 0x10, KEY_MUTE }, | ||
| 246 | { 0x01, 0x19, KEY_AUDIO }, /* L/R */ /* TODO better event */ | ||
| 247 | { 0x01, 0x16, KEY_SLEEP }, /* Hibernate */ | ||
| 248 | { 0x01, 0x16, KEY_SWITCHVIDEOMODE }, | ||
| 249 | /* A/V */ /* TODO does not work */ | ||
| 250 | { 0x00, 0x06, KEY_AGAIN }, /* Recall */ | ||
| 251 | { 0x01, 0x16, KEY_KPPLUS }, /* Zoom+ */ /* TODO does not work */ | ||
| 252 | { 0x01, 0x16, KEY_KPMINUS }, /* Zoom- */ /* TODO does not work */ | ||
| 253 | { 0x02, 0x15, KEY_RED }, | ||
| 254 | { 0x02, 0x0a, KEY_GREEN }, | ||
| 255 | { 0x02, 0x1c, KEY_YELLOW }, | ||
| 256 | { 0x02, 0x05, KEY_BLUE }, | ||
| 257 | }; | ||
| 258 | |||
| 259 | static u8 af9015_ir_table_twinhan[] = { | ||
| 260 | 0x00, 0xff, 0x16, 0xe9, 0x3f, 0x05, 0x00, | ||
| 261 | 0x00, 0xff, 0x07, 0xf8, 0x16, 0x01, 0x00, | ||
| 262 | 0x00, 0xff, 0x14, 0xeb, 0x11, 0x01, 0x00, | ||
| 263 | 0x00, 0xff, 0x1a, 0xe5, 0x4d, 0x00, 0x00, | ||
| 264 | 0x00, 0xff, 0x4c, 0xb3, 0x17, 0x00, 0x00, | ||
| 265 | 0x00, 0xff, 0x12, 0xed, 0x11, 0x00, 0x00, | ||
| 266 | 0x00, 0xff, 0x40, 0xbf, 0x0c, 0x00, 0x00, | ||
| 267 | 0x00, 0xff, 0x11, 0xee, 0x4a, 0x00, 0x00, | ||
| 268 | 0x00, 0xff, 0x54, 0xab, 0x13, 0x00, 0x00, | ||
| 269 | 0x00, 0xff, 0x41, 0xbe, 0x15, 0x01, 0x00, | ||
| 270 | 0x00, 0xff, 0x42, 0xbd, 0x0e, 0x01, 0x00, | ||
| 271 | 0x00, 0xff, 0x43, 0xbc, 0x17, 0x01, 0x00, | ||
| 272 | 0x00, 0xff, 0x50, 0xaf, 0x0f, 0x01, 0x00, | ||
| 273 | 0x00, 0xff, 0x4d, 0xb2, 0x1d, 0x00, 0x00, | ||
| 274 | 0x00, 0xff, 0x47, 0xb8, 0x13, 0x01, 0x00, | ||
| 275 | 0x00, 0xff, 0x05, 0xfa, 0x4b, 0x00, 0x00, | ||
| 276 | 0x00, 0xff, 0x02, 0xfd, 0x4e, 0x00, 0x00, | ||
| 277 | 0x00, 0xff, 0x0e, 0xf1, 0x06, 0x00, 0x00, | ||
| 278 | 0x00, 0xff, 0x1e, 0xe1, 0x52, 0x02, 0x00, | ||
| 279 | 0x00, 0xff, 0x0a, 0xf5, 0x51, 0x02, 0x00, | ||
| 280 | 0x00, 0xff, 0x10, 0xef, 0x10, 0x00, 0x00, | ||
| 281 | 0x00, 0xff, 0x49, 0xb6, 0x19, 0x01, 0x00, | ||
| 282 | 0x00, 0xff, 0x15, 0xea, 0x27, 0x00, 0x00, | ||
| 283 | 0x00, 0xff, 0x03, 0xfc, 0x1e, 0x00, 0x00, | ||
| 284 | 0x00, 0xff, 0x01, 0xfe, 0x1f, 0x00, 0x00, | ||
| 285 | 0x00, 0xff, 0x06, 0xf9, 0x20, 0x00, 0x00, | ||
| 286 | 0x00, 0xff, 0x09, 0xf6, 0x21, 0x00, 0x00, | ||
| 287 | 0x00, 0xff, 0x1d, 0xe2, 0x22, 0x00, 0x00, | ||
| 288 | 0x00, 0xff, 0x1f, 0xe0, 0x23, 0x00, 0x00, | ||
| 289 | 0x00, 0xff, 0x0d, 0xf2, 0x24, 0x00, 0x00, | ||
| 290 | 0x00, 0xff, 0x19, 0xe6, 0x25, 0x00, 0x00, | ||
| 291 | 0x00, 0xff, 0x1b, 0xe4, 0x26, 0x00, 0x00, | ||
| 292 | 0x00, 0xff, 0x00, 0xff, 0x2b, 0x00, 0x00, | ||
| 293 | 0x00, 0xff, 0x4a, 0xb5, 0x4c, 0x00, 0x00, | ||
| 294 | 0x00, 0xff, 0x4b, 0xb4, 0x52, 0x00, 0x00, | ||
| 295 | 0x00, 0xff, 0x51, 0xae, 0x51, 0x00, 0x00, | ||
| 296 | 0x00, 0xff, 0x52, 0xad, 0x4f, 0x00, 0x00, | ||
| 297 | 0x00, 0xff, 0x4e, 0xb1, 0x50, 0x00, 0x00, | ||
| 298 | 0x00, 0xff, 0x0c, 0xf3, 0x29, 0x00, 0x00, | ||
| 299 | 0x00, 0xff, 0x4f, 0xb0, 0x28, 0x00, 0x00, | ||
| 300 | 0x00, 0xff, 0x13, 0xec, 0x2a, 0x00, 0x00, | ||
| 301 | 0x00, 0xff, 0x17, 0xe8, 0x19, 0x00, 0x00, | ||
| 302 | 0x00, 0xff, 0x04, 0xfb, 0x0f, 0x00, 0x00, | ||
| 303 | 0x00, 0xff, 0x48, 0xb7, 0x0e, 0x00, 0x00, | ||
| 304 | 0x00, 0xff, 0x0f, 0xf0, 0x04, 0x00, 0x00, | ||
| 305 | 0x00, 0xff, 0x1c, 0xe3, 0x08, 0x00, 0x00, | ||
| 306 | 0x00, 0xff, 0x18, 0xe7, 0x15, 0x02, 0x00, | ||
| 307 | 0x00, 0xff, 0x53, 0xac, 0x0a, 0x02, 0x00, | ||
| 308 | 0x00, 0xff, 0x5e, 0xa1, 0x1c, 0x02, 0x00, | ||
| 309 | 0x00, 0xff, 0x5f, 0xa0, 0x05, 0x02, 0x00, | ||
| 310 | }; | ||
| 311 | |||
| 312 | /* A-Link DTU(m) */ | ||
| 313 | static struct dvb_usb_rc_key af9015_rc_keys_a_link[] = { | ||
| 314 | { 0x00, 0x1e, KEY_1 }, | ||
| 315 | { 0x00, 0x1f, KEY_2 }, | ||
| 316 | { 0x00, 0x20, KEY_3 }, | ||
| 317 | { 0x00, 0x21, KEY_4 }, | ||
| 318 | { 0x00, 0x22, KEY_5 }, | ||
| 319 | { 0x00, 0x23, KEY_6 }, | ||
| 320 | { 0x00, 0x24, KEY_7 }, | ||
| 321 | { 0x00, 0x25, KEY_8 }, | ||
| 322 | { 0x00, 0x26, KEY_9 }, | ||
| 323 | { 0x00, 0x27, KEY_0 }, | ||
| 324 | { 0x00, 0x2e, KEY_CHANNELUP }, | ||
| 325 | { 0x00, 0x2d, KEY_CHANNELDOWN }, | ||
| 326 | { 0x04, 0x28, KEY_ZOOM }, | ||
| 327 | { 0x00, 0x41, KEY_MUTE }, | ||
| 328 | { 0x00, 0x42, KEY_VOLUMEDOWN }, | ||
| 329 | { 0x00, 0x43, KEY_VOLUMEUP }, | ||
| 330 | { 0x00, 0x44, KEY_GOTO }, /* jump */ | ||
| 331 | { 0x05, 0x45, KEY_POWER }, | ||
| 332 | }; | ||
| 333 | |||
| 334 | static u8 af9015_ir_table_a_link[] = { | ||
| 335 | 0x08, 0xf7, 0x12, 0xed, 0x45, 0x05, 0x00, /* power */ | ||
| 336 | 0x08, 0xf7, 0x1a, 0xe5, 0x41, 0x00, 0x00, /* mute */ | ||
| 337 | 0x08, 0xf7, 0x01, 0xfe, 0x1e, 0x00, 0x00, /* 1 */ | ||
| 338 | 0x08, 0xf7, 0x1c, 0xe3, 0x21, 0x00, 0x00, /* 4 */ | ||
| 339 | 0x08, 0xf7, 0x03, 0xfc, 0x24, 0x00, 0x00, /* 7 */ | ||
| 340 | 0x08, 0xf7, 0x05, 0xfa, 0x28, 0x04, 0x00, /* zoom */ | ||
| 341 | 0x08, 0xf7, 0x00, 0xff, 0x43, 0x00, 0x00, /* volume up */ | ||
| 342 | 0x08, 0xf7, 0x16, 0xe9, 0x42, 0x00, 0x00, /* volume down */ | ||
| 343 | 0x08, 0xf7, 0x0f, 0xf0, 0x1f, 0x00, 0x00, /* 2 */ | ||
| 344 | 0x08, 0xf7, 0x0d, 0xf2, 0x22, 0x00, 0x00, /* 5 */ | ||
| 345 | 0x08, 0xf7, 0x1b, 0xe4, 0x25, 0x00, 0x00, /* 8 */ | ||
| 346 | 0x08, 0xf7, 0x06, 0xf9, 0x27, 0x00, 0x00, /* 0 */ | ||
| 347 | 0x08, 0xf7, 0x14, 0xeb, 0x2e, 0x00, 0x00, /* channel up */ | ||
| 348 | 0x08, 0xf7, 0x1d, 0xe2, 0x2d, 0x00, 0x00, /* channel down */ | ||
| 349 | 0x08, 0xf7, 0x02, 0xfd, 0x20, 0x00, 0x00, /* 3 */ | ||
| 350 | 0x08, 0xf7, 0x18, 0xe7, 0x23, 0x00, 0x00, /* 6 */ | ||
| 351 | 0x08, 0xf7, 0x04, 0xfb, 0x26, 0x00, 0x00, /* 9 */ | ||
| 352 | 0x08, 0xf7, 0x07, 0xf8, 0x44, 0x00, 0x00, /* jump */ | ||
| 353 | }; | ||
| 354 | |||
| 355 | /* MSI DIGIVOX mini II V3.0 */ | ||
| 356 | static struct dvb_usb_rc_key af9015_rc_keys_msi[] = { | ||
| 357 | { 0x00, 0x1e, KEY_1 }, | ||
| 358 | { 0x00, 0x1f, KEY_2 }, | ||
| 359 | { 0x00, 0x20, KEY_3 }, | ||
| 360 | { 0x00, 0x21, KEY_4 }, | ||
| 361 | { 0x00, 0x22, KEY_5 }, | ||
| 362 | { 0x00, 0x23, KEY_6 }, | ||
| 363 | { 0x00, 0x24, KEY_7 }, | ||
| 364 | { 0x00, 0x25, KEY_8 }, | ||
| 365 | { 0x00, 0x26, KEY_9 }, | ||
| 366 | { 0x00, 0x27, KEY_0 }, | ||
| 367 | { 0x03, 0x0f, KEY_CHANNELUP }, | ||
| 368 | { 0x03, 0x0e, KEY_CHANNELDOWN }, | ||
| 369 | { 0x00, 0x42, KEY_VOLUMEDOWN }, | ||
| 370 | { 0x00, 0x43, KEY_VOLUMEUP }, | ||
| 371 | { 0x05, 0x45, KEY_POWER }, | ||
| 372 | { 0x00, 0x52, KEY_UP }, /* up */ | ||
| 373 | { 0x00, 0x51, KEY_DOWN }, /* down */ | ||
| 374 | { 0x00, 0x28, KEY_ENTER }, | ||
| 375 | }; | ||
| 376 | |||
| 377 | static u8 af9015_ir_table_msi[] = { | ||
| 378 | 0x03, 0xfc, 0x17, 0xe8, 0x45, 0x05, 0x00, /* power */ | ||
| 379 | 0x03, 0xfc, 0x0d, 0xf2, 0x51, 0x00, 0x00, /* down */ | ||
| 380 | 0x03, 0xfc, 0x03, 0xfc, 0x52, 0x00, 0x00, /* up */ | ||
| 381 | 0x03, 0xfc, 0x1a, 0xe5, 0x1e, 0x00, 0x00, /* 1 */ | ||
| 382 | 0x03, 0xfc, 0x02, 0xfd, 0x1f, 0x00, 0x00, /* 2 */ | ||
| 383 | 0x03, 0xfc, 0x04, 0xfb, 0x20, 0x00, 0x00, /* 3 */ | ||
| 384 | 0x03, 0xfc, 0x1c, 0xe3, 0x21, 0x00, 0x00, /* 4 */ | ||
| 385 | 0x03, 0xfc, 0x08, 0xf7, 0x22, 0x00, 0x00, /* 5 */ | ||
| 386 | 0x03, 0xfc, 0x1d, 0xe2, 0x23, 0x00, 0x00, /* 6 */ | ||
| 387 | 0x03, 0xfc, 0x11, 0xee, 0x24, 0x00, 0x00, /* 7 */ | ||
| 388 | 0x03, 0xfc, 0x0b, 0xf4, 0x25, 0x00, 0x00, /* 8 */ | ||
| 389 | 0x03, 0xfc, 0x10, 0xef, 0x26, 0x00, 0x00, /* 9 */ | ||
| 390 | 0x03, 0xfc, 0x09, 0xf6, 0x27, 0x00, 0x00, /* 0 */ | ||
| 391 | 0x03, 0xfc, 0x14, 0xeb, 0x43, 0x00, 0x00, /* volume up */ | ||
| 392 | 0x03, 0xfc, 0x1f, 0xe0, 0x42, 0x00, 0x00, /* volume down */ | ||
| 393 | 0x03, 0xfc, 0x15, 0xea, 0x0f, 0x03, 0x00, /* channel up */ | ||
| 394 | 0x03, 0xfc, 0x05, 0xfa, 0x0e, 0x03, 0x00, /* channel down */ | ||
| 395 | 0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00, /* enter */ | ||
| 396 | }; | ||
| 397 | |||
| 398 | /* MYGICTV U718 */ | ||
| 399 | static struct dvb_usb_rc_key af9015_rc_keys_mygictv[] = { | ||
| 400 | { 0x00, 0x3d, KEY_SWITCHVIDEOMODE }, | ||
| 401 | /* TV / AV */ | ||
| 402 | { 0x05, 0x45, KEY_POWER }, | ||
| 403 | { 0x00, 0x1e, KEY_1 }, | ||
| 404 | { 0x00, 0x1f, KEY_2 }, | ||
| 405 | { 0x00, 0x20, KEY_3 }, | ||
| 406 | { 0x00, 0x21, KEY_4 }, | ||
| 407 | { 0x00, 0x22, KEY_5 }, | ||
| 408 | { 0x00, 0x23, KEY_6 }, | ||
| 409 | { 0x00, 0x24, KEY_7 }, | ||
| 410 | { 0x00, 0x25, KEY_8 }, | ||
| 411 | { 0x00, 0x26, KEY_9 }, | ||
| 412 | { 0x00, 0x27, KEY_0 }, | ||
| 413 | { 0x00, 0x41, KEY_MUTE }, | ||
| 414 | { 0x00, 0x2a, KEY_ESC }, /* Esc */ | ||
| 415 | { 0x00, 0x2e, KEY_CHANNELUP }, | ||
| 416 | { 0x00, 0x2d, KEY_CHANNELDOWN }, | ||
| 417 | { 0x00, 0x42, KEY_VOLUMEDOWN }, | ||
| 418 | { 0x00, 0x43, KEY_VOLUMEUP }, | ||
| 419 | { 0x00, 0x52, KEY_UP }, /* up arrow */ | ||
| 420 | { 0x00, 0x51, KEY_DOWN }, /* down arrow */ | ||
| 421 | { 0x00, 0x4f, KEY_RIGHT }, /* right arrow */ | ||
| 422 | { 0x00, 0x50, KEY_LEFT }, /* left arrow */ | ||
| 423 | { 0x00, 0x28, KEY_ENTER }, /* ok */ | ||
| 424 | { 0x01, 0x15, KEY_RECORD }, | ||
| 425 | { 0x03, 0x13, KEY_PLAY }, | ||
| 426 | { 0x01, 0x13, KEY_PAUSE }, | ||
| 427 | { 0x01, 0x16, KEY_STOP }, | ||
| 428 | { 0x03, 0x07, KEY_REWIND }, /* FR << */ | ||
| 429 | { 0x03, 0x09, KEY_FASTFORWARD }, /* FF >> */ | ||
| 430 | { 0x00, 0x3b, KEY_TIME }, /* TimeShift */ | ||
| 431 | { 0x00, 0x3e, KEY_CAMERA }, /* Snapshot */ | ||
| 432 | { 0x03, 0x16, KEY_CYCLEWINDOWS }, /* yellow, min / max */ | ||
| 433 | { 0x00, 0x00, KEY_ZOOM }, /* 'select' (?) */ | ||
| 434 | { 0x03, 0x16, KEY_SHUFFLE }, /* Shuffle */ | ||
| 435 | { 0x03, 0x45, KEY_POWER }, | ||
| 436 | }; | ||
| 437 | |||
| 438 | static u8 af9015_ir_table_mygictv[] = { | ||
| 439 | 0x02, 0xbd, 0x0c, 0xf3, 0x3d, 0x00, 0x00, /* TV / AV */ | ||
| 440 | 0x02, 0xbd, 0x14, 0xeb, 0x45, 0x05, 0x00, /* power */ | ||
| 441 | 0x02, 0xbd, 0x00, 0xff, 0x1e, 0x00, 0x00, /* 1 */ | ||
| 442 | 0x02, 0xbd, 0x01, 0xfe, 0x1f, 0x00, 0x00, /* 2 */ | ||
| 443 | 0x02, 0xbd, 0x02, 0xfd, 0x20, 0x00, 0x00, /* 3 */ | ||
| 444 | 0x02, 0xbd, 0x03, 0xfc, 0x21, 0x00, 0x00, /* 4 */ | ||
| 445 | 0x02, 0xbd, 0x04, 0xfb, 0x22, 0x00, 0x00, /* 5 */ | ||
| 446 | 0x02, 0xbd, 0x05, 0xfa, 0x23, 0x00, 0x00, /* 6 */ | ||
| 447 | 0x02, 0xbd, 0x06, 0xf9, 0x24, 0x00, 0x00, /* 7 */ | ||
| 448 | 0x02, 0xbd, 0x07, 0xf8, 0x25, 0x00, 0x00, /* 8 */ | ||
| 449 | 0x02, 0xbd, 0x08, 0xf7, 0x26, 0x00, 0x00, /* 9 */ | ||
| 450 | 0x02, 0xbd, 0x09, 0xf6, 0x27, 0x00, 0x00, /* 0 */ | ||
| 451 | 0x02, 0xbd, 0x0a, 0xf5, 0x41, 0x00, 0x00, /* mute */ | ||
| 452 | 0x02, 0xbd, 0x1c, 0xe3, 0x2a, 0x00, 0x00, /* esc */ | ||
| 453 | 0x02, 0xbd, 0x1f, 0xe0, 0x43, 0x00, 0x00, /* volume up */ | ||
| 454 | 0x02, 0xbd, 0x12, 0xed, 0x52, 0x00, 0x00, /* up arrow */ | ||
| 455 | 0x02, 0xbd, 0x11, 0xee, 0x50, 0x00, 0x00, /* left arrow */ | ||
| 456 | 0x02, 0xbd, 0x15, 0xea, 0x28, 0x00, 0x00, /* ok */ | ||
| 457 | 0x02, 0xbd, 0x10, 0xef, 0x4f, 0x00, 0x00, /* right arrow */ | ||
| 458 | 0x02, 0xbd, 0x13, 0xec, 0x51, 0x00, 0x00, /* down arrow */ | ||
| 459 | 0x02, 0xbd, 0x0e, 0xf1, 0x42, 0x00, 0x00, /* volume down */ | ||
| 460 | 0x02, 0xbd, 0x19, 0xe6, 0x15, 0x01, 0x00, /* record */ | ||
| 461 | 0x02, 0xbd, 0x1e, 0xe1, 0x13, 0x03, 0x00, /* play */ | ||
| 462 | 0x02, 0xbd, 0x16, 0xe9, 0x16, 0x01, 0x00, /* stop */ | ||
| 463 | 0x02, 0xbd, 0x0b, 0xf4, 0x28, 0x04, 0x00, /* yellow, min / max */ | ||
| 464 | 0x02, 0xbd, 0x0f, 0xf0, 0x3b, 0x00, 0x00, /* time shift */ | ||
| 465 | 0x02, 0xbd, 0x18, 0xe7, 0x2e, 0x00, 0x00, /* channel up */ | ||
| 466 | 0x02, 0xbd, 0x1a, 0xe5, 0x2d, 0x00, 0x00, /* channel down */ | ||
| 467 | 0x02, 0xbd, 0x17, 0xe8, 0x3e, 0x00, 0x00, /* snapshot */ | ||
| 468 | 0x02, 0xbd, 0x40, 0xbf, 0x13, 0x01, 0x00, /* pause */ | ||
| 469 | 0x02, 0xbd, 0x41, 0xbe, 0x09, 0x03, 0x00, /* FF >> */ | ||
| 470 | 0x02, 0xbd, 0x42, 0xbd, 0x07, 0x03, 0x00, /* FR << */ | ||
| 471 | 0x02, 0xbd, 0x43, 0xbc, 0x00, 0x00, 0x00, /* 'select' (?) */ | ||
| 472 | 0x02, 0xbd, 0x44, 0xbb, 0x16, 0x03, 0x00, /* shuffle */ | ||
| 473 | 0x02, 0xbd, 0x45, 0xba, 0x45, 0x03, 0x00, /* power */ | ||
| 474 | }; | ||
| 475 | |||
| 476 | /* KWorld PlusTV Dual DVB-T Stick (DVB-T 399U) */ | ||
| 477 | static u8 af9015_ir_table_kworld[] = { | ||
| 478 | 0x86, 0x6b, 0x0c, 0xf3, 0x2e, 0x07, 0x00, | ||
| 479 | 0x86, 0x6b, 0x16, 0xe9, 0x2d, 0x07, 0x00, | ||
| 480 | 0x86, 0x6b, 0x1d, 0xe2, 0x37, 0x07, 0x00, | ||
| 481 | 0x86, 0x6b, 0x00, 0xff, 0x1e, 0x07, 0x00, | ||
| 482 | 0x86, 0x6b, 0x01, 0xfe, 0x1f, 0x07, 0x00, | ||
| 483 | 0x86, 0x6b, 0x02, 0xfd, 0x20, 0x07, 0x00, | ||
| 484 | 0x86, 0x6b, 0x03, 0xfc, 0x21, 0x07, 0x00, | ||
| 485 | 0x86, 0x6b, 0x04, 0xfb, 0x22, 0x07, 0x00, | ||
| 486 | 0x86, 0x6b, 0x05, 0xfa, 0x23, 0x07, 0x00, | ||
| 487 | 0x86, 0x6b, 0x06, 0xf9, 0x24, 0x07, 0x00, | ||
| 488 | 0x86, 0x6b, 0x07, 0xf8, 0x25, 0x07, 0x00, | ||
| 489 | 0x86, 0x6b, 0x08, 0xf7, 0x26, 0x07, 0x00, | ||
| 490 | 0x86, 0x6b, 0x09, 0xf6, 0x4d, 0x07, 0x00, | ||
| 491 | 0x86, 0x6b, 0x0a, 0xf5, 0x4e, 0x07, 0x00, | ||
| 492 | 0x86, 0x6b, 0x14, 0xeb, 0x4f, 0x07, 0x00, | ||
| 493 | 0x86, 0x6b, 0x1e, 0xe1, 0x50, 0x07, 0x00, | ||
| 494 | 0x86, 0x6b, 0x17, 0xe8, 0x52, 0x07, 0x00, | ||
| 495 | 0x86, 0x6b, 0x1f, 0xe0, 0x51, 0x07, 0x00, | ||
| 496 | 0x86, 0x6b, 0x0e, 0xf1, 0x0b, 0x07, 0x00, | ||
| 497 | 0x86, 0x6b, 0x20, 0xdf, 0x0c, 0x07, 0x00, | ||
| 498 | 0x86, 0x6b, 0x42, 0xbd, 0x0d, 0x07, 0x00, | ||
| 499 | 0x86, 0x6b, 0x0b, 0xf4, 0x0e, 0x07, 0x00, | ||
| 500 | 0x86, 0x6b, 0x43, 0xbc, 0x0f, 0x07, 0x00, | ||
| 501 | 0x86, 0x6b, 0x10, 0xef, 0x10, 0x07, 0x00, | ||
| 502 | 0x86, 0x6b, 0x21, 0xde, 0x11, 0x07, 0x00, | ||
| 503 | 0x86, 0x6b, 0x13, 0xec, 0x12, 0x07, 0x00, | ||
| 504 | 0x86, 0x6b, 0x11, 0xee, 0x13, 0x07, 0x00, | ||
| 505 | 0x86, 0x6b, 0x12, 0xed, 0x14, 0x07, 0x00, | ||
| 506 | 0x86, 0x6b, 0x19, 0xe6, 0x15, 0x07, 0x00, | ||
| 507 | 0x86, 0x6b, 0x1a, 0xe5, 0x16, 0x07, 0x00, | ||
| 508 | 0x86, 0x6b, 0x1b, 0xe4, 0x17, 0x07, 0x00, | ||
| 509 | 0x86, 0x6b, 0x4b, 0xb4, 0x18, 0x07, 0x00, | ||
| 510 | 0x86, 0x6b, 0x40, 0xbf, 0x19, 0x07, 0x00, | ||
| 511 | 0x86, 0x6b, 0x44, 0xbb, 0x1a, 0x07, 0x00, | ||
| 512 | 0x86, 0x6b, 0x41, 0xbe, 0x1b, 0x07, 0x00, | ||
| 513 | 0x86, 0x6b, 0x22, 0xdd, 0x1c, 0x07, 0x00, | ||
| 514 | 0x86, 0x6b, 0x15, 0xea, 0x1d, 0x07, 0x00, | ||
| 515 | 0x86, 0x6b, 0x0f, 0xf0, 0x3f, 0x07, 0x00, | ||
| 516 | 0x86, 0x6b, 0x1c, 0xe3, 0x40, 0x07, 0x00, | ||
| 517 | 0x86, 0x6b, 0x4a, 0xb5, 0x41, 0x07, 0x00, | ||
| 518 | 0x86, 0x6b, 0x48, 0xb7, 0x42, 0x07, 0x00, | ||
| 519 | 0x86, 0x6b, 0x49, 0xb6, 0x43, 0x07, 0x00, | ||
| 520 | 0x86, 0x6b, 0x18, 0xe7, 0x44, 0x07, 0x00, | ||
| 521 | 0x86, 0x6b, 0x23, 0xdc, 0x45, 0x07, 0x00, | ||
| 522 | }; | ||
| 523 | |||
| 524 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 2f408d2e1ef3..c786359fba03 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c | |||
| @@ -41,6 +41,9 @@ | |||
| 41 | static int dvb_usb_anysee_debug; | 41 | static int dvb_usb_anysee_debug; |
| 42 | module_param_named(debug, dvb_usb_anysee_debug, int, 0644); | 42 | module_param_named(debug, dvb_usb_anysee_debug, int, 0644); |
| 43 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | 43 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); |
| 44 | int dvb_usb_anysee_delsys; | ||
| 45 | module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644); | ||
| 46 | MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)"); | ||
| 44 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 47 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 45 | 48 | ||
| 46 | static struct mutex anysee_usb_mutex; | 49 | static struct mutex anysee_usb_mutex; |
| @@ -178,14 +181,14 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 178 | inc = 1; | 181 | inc = 1; |
| 179 | } | 182 | } |
| 180 | if (ret) | 183 | if (ret) |
| 181 | return ret; | 184 | break; |
| 182 | 185 | ||
| 183 | i += inc; | 186 | i += inc; |
| 184 | } | 187 | } |
| 185 | 188 | ||
| 186 | mutex_unlock(&d->i2c_mutex); | 189 | mutex_unlock(&d->i2c_mutex); |
| 187 | 190 | ||
| 188 | return i; | 191 | return ret ? ret : i; |
| 189 | } | 192 | } |
| 190 | 193 | ||
| 191 | static u32 anysee_i2c_func(struct i2c_adapter *adapter) | 194 | static u32 anysee_i2c_func(struct i2c_adapter *adapter) |
| @@ -272,9 +275,11 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 272 | model demod hw firmware | 275 | model demod hw firmware |
| 273 | 1. E30 MT352 02 0.2.1 | 276 | 1. E30 MT352 02 0.2.1 |
| 274 | 2. E30 ZL10353 02 0.2.1 | 277 | 2. E30 ZL10353 02 0.2.1 |
| 275 | 3. E30 Plus ZL10353 06 0.1.0 | 278 | 3. E30 Combo ZL10353 0f 0.1.2 DVB-T/C combo |
| 276 | 4. E30C Plus TDA10023 0a 0.1.0 rev 0.2 | 279 | 4. E30 Plus ZL10353 06 0.1.0 |
| 277 | 4. E30C Plus TDA10023 0f 0.1.2 rev 0.4 | 280 | 5. E30C Plus TDA10023 0a 0.1.0 rev 0.2 |
| 281 | E30C Plus TDA10023 0f 0.1.2 rev 0.4 | ||
| 282 | E30 Combo TDA10023 0f 0.1.2 DVB-T/C combo | ||
| 278 | */ | 283 | */ |
| 279 | 284 | ||
| 280 | /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */ | 285 | /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */ |
| @@ -293,6 +298,21 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 293 | return 0; | 298 | return 0; |
| 294 | } | 299 | } |
| 295 | 300 | ||
| 301 | /* for E30 Combo Plus DVB-T demodulator */ | ||
| 302 | if (dvb_usb_anysee_delsys) { | ||
| 303 | ret = anysee_write_reg(adap->dev, 0xb0, 0x01); | ||
| 304 | if (ret) | ||
| 305 | return ret; | ||
| 306 | |||
| 307 | /* Zarlink ZL10353 DVB-T demod */ | ||
| 308 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | ||
| 309 | &adap->dev->i2c_adap); | ||
| 310 | if (adap->fe != NULL) { | ||
| 311 | state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A; | ||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 296 | /* connect demod on IO port D for TDA10023 & ZL10353 */ | 316 | /* connect demod on IO port D for TDA10023 & ZL10353 */ |
| 297 | ret = anysee_write_reg(adap->dev, 0xb0, 0x25); | 317 | ret = anysee_write_reg(adap->dev, 0xb0, 0x25); |
| 298 | if (ret) | 318 | if (ret) |
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c new file mode 100644 index 000000000000..3ac9f74e9fbf --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c | |||
| @@ -0,0 +1,268 @@ | |||
| 1 | /* | ||
| 2 | * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) | ||
| 5 | * | ||
| 6 | * Based on the dvb-usb-framework code and the | ||
| 7 | * original Terratec Cinergy T2 driver by: | ||
| 8 | * | ||
| 9 | * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and | ||
| 10 | * Holger Waechtler <holger@qanu.de> | ||
| 11 | * | ||
| 12 | * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or modify | ||
| 15 | * it under the terms of the GNU General Public License as published by | ||
| 16 | * the Free Software Foundation; either version 2 of the License, or | ||
| 17 | * (at your option) any later version. | ||
| 18 | * | ||
| 19 | * This program is distributed in the hope that it will be useful, | ||
| 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 22 | * GNU General Public License for more details. | ||
| 23 | * | ||
| 24 | * You should have received a copy of the GNU General Public License | ||
| 25 | * along with this program; if not, write to the Free Software | ||
| 26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include "cinergyT2.h" | ||
| 31 | |||
| 32 | |||
| 33 | /* debug */ | ||
| 34 | int dvb_usb_cinergyt2_debug; | ||
| 35 | int disable_remote; | ||
| 36 | |||
| 37 | module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644); | ||
| 38 | MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 " | ||
| 39 | "(or-able))."); | ||
| 40 | |||
| 41 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 42 | |||
| 43 | struct cinergyt2_state { | ||
| 44 | u8 rc_counter; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* We are missing a release hook with usb_device data */ | ||
| 48 | struct dvb_usb_device *cinergyt2_usb_device; | ||
| 49 | |||
| 50 | static struct dvb_usb_device_properties cinergyt2_properties; | ||
| 51 | |||
| 52 | static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) | ||
| 53 | { | ||
| 54 | char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; | ||
| 55 | char result[64]; | ||
| 56 | return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result, | ||
| 57 | sizeof(result), 0); | ||
| 58 | } | ||
| 59 | |||
| 60 | static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable) | ||
| 61 | { | ||
| 62 | char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 }; | ||
| 63 | char state[3]; | ||
| 64 | return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0); | ||
| 65 | } | ||
| 66 | |||
| 67 | static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 68 | { | ||
| 69 | char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION }; | ||
| 70 | char state[3]; | ||
| 71 | int ret; | ||
| 72 | |||
| 73 | adap->fe = cinergyt2_fe_attach(adap->dev); | ||
| 74 | |||
| 75 | ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state, | ||
| 76 | sizeof(state), 0); | ||
| 77 | if (ret < 0) { | ||
| 78 | deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep " | ||
| 79 | "state info\n"); | ||
| 80 | } | ||
| 81 | |||
| 82 | /* Copy this pointer as we are gonna need it in the release phase */ | ||
| 83 | cinergyt2_usb_device = adap->dev; | ||
| 84 | |||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | static struct dvb_usb_rc_key cinergyt2_rc_keys[] = { | ||
| 89 | { 0x04, 0x01, KEY_POWER }, | ||
| 90 | { 0x04, 0x02, KEY_1 }, | ||
| 91 | { 0x04, 0x03, KEY_2 }, | ||
| 92 | { 0x04, 0x04, KEY_3 }, | ||
| 93 | { 0x04, 0x05, KEY_4 }, | ||
| 94 | { 0x04, 0x06, KEY_5 }, | ||
| 95 | { 0x04, 0x07, KEY_6 }, | ||
| 96 | { 0x04, 0x08, KEY_7 }, | ||
| 97 | { 0x04, 0x09, KEY_8 }, | ||
| 98 | { 0x04, 0x0a, KEY_9 }, | ||
| 99 | { 0x04, 0x0c, KEY_0 }, | ||
| 100 | { 0x04, 0x0b, KEY_VIDEO }, | ||
| 101 | { 0x04, 0x0d, KEY_REFRESH }, | ||
| 102 | { 0x04, 0x0e, KEY_SELECT }, | ||
| 103 | { 0x04, 0x0f, KEY_EPG }, | ||
| 104 | { 0x04, 0x10, KEY_UP }, | ||
| 105 | { 0x04, 0x14, KEY_DOWN }, | ||
| 106 | { 0x04, 0x11, KEY_LEFT }, | ||
| 107 | { 0x04, 0x13, KEY_RIGHT }, | ||
| 108 | { 0x04, 0x12, KEY_OK }, | ||
| 109 | { 0x04, 0x15, KEY_TEXT }, | ||
| 110 | { 0x04, 0x16, KEY_INFO }, | ||
| 111 | { 0x04, 0x17, KEY_RED }, | ||
| 112 | { 0x04, 0x18, KEY_GREEN }, | ||
| 113 | { 0x04, 0x19, KEY_YELLOW }, | ||
| 114 | { 0x04, 0x1a, KEY_BLUE }, | ||
| 115 | { 0x04, 0x1c, KEY_VOLUMEUP }, | ||
| 116 | { 0x04, 0x1e, KEY_VOLUMEDOWN }, | ||
| 117 | { 0x04, 0x1d, KEY_MUTE }, | ||
| 118 | { 0x04, 0x1b, KEY_CHANNELUP }, | ||
| 119 | { 0x04, 0x1f, KEY_CHANNELDOWN }, | ||
| 120 | { 0x04, 0x40, KEY_PAUSE }, | ||
| 121 | { 0x04, 0x4c, KEY_PLAY }, | ||
| 122 | { 0x04, 0x58, KEY_RECORD }, | ||
| 123 | { 0x04, 0x54, KEY_PREVIOUS }, | ||
| 124 | { 0x04, 0x48, KEY_STOP }, | ||
| 125 | { 0x04, 0x5c, KEY_NEXT } | ||
| 126 | }; | ||
| 127 | |||
| 128 | /* Number of keypresses to ignore before detect repeating */ | ||
| 129 | #define RC_REPEAT_DELAY 3 | ||
| 130 | |||
| 131 | static int repeatable_keys[] = { | ||
| 132 | KEY_UP, | ||
| 133 | KEY_DOWN, | ||
| 134 | KEY_LEFT, | ||
| 135 | KEY_RIGHT, | ||
| 136 | KEY_VOLUMEUP, | ||
| 137 | KEY_VOLUMEDOWN, | ||
| 138 | KEY_CHANNELUP, | ||
| 139 | KEY_CHANNELDOWN | ||
| 140 | }; | ||
| 141 | |||
| 142 | static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 143 | { | ||
| 144 | struct cinergyt2_state *st = d->priv; | ||
| 145 | u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS; | ||
| 146 | int i; | ||
| 147 | |||
| 148 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 149 | |||
| 150 | dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0); | ||
| 151 | if (key[4] == 0xff) { | ||
| 152 | /* key repeat */ | ||
| 153 | st->rc_counter++; | ||
| 154 | if (st->rc_counter > RC_REPEAT_DELAY) { | ||
| 155 | for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) { | ||
| 156 | if (d->last_event == repeatable_keys[i]) { | ||
| 157 | *state = REMOTE_KEY_REPEAT; | ||
| 158 | *event = d->last_event; | ||
| 159 | deb_rc("repeat key, event %x\n", | ||
| 160 | *event); | ||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | deb_rc("repeated key (non repeatable)\n"); | ||
| 165 | } | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* hack to pass checksum on the custom field */ | ||
| 170 | key[2] = ~key[1]; | ||
| 171 | dvb_usb_nec_rc_key_to_event(d, key, event, state); | ||
| 172 | if (key[0] != 0) { | ||
| 173 | if (*event != d->last_event) | ||
| 174 | st->rc_counter = 0; | ||
| 175 | |||
| 176 | deb_rc("key: %x %x %x %x %x\n", | ||
| 177 | key[0], key[1], key[2], key[3], key[4]); | ||
| 178 | } | ||
| 179 | return 0; | ||
| 180 | } | ||
| 181 | |||
| 182 | static int cinergyt2_usb_probe(struct usb_interface *intf, | ||
| 183 | const struct usb_device_id *id) | ||
| 184 | { | ||
| 185 | return dvb_usb_device_init(intf, &cinergyt2_properties, | ||
| 186 | THIS_MODULE, NULL, adapter_nr); | ||
| 187 | } | ||
| 188 | |||
| 189 | |||
| 190 | static struct usb_device_id cinergyt2_usb_table[] = { | ||
| 191 | { USB_DEVICE(USB_VID_TERRATEC, 0x0038) }, | ||
| 192 | { 0 } | ||
| 193 | }; | ||
| 194 | |||
| 195 | MODULE_DEVICE_TABLE(usb, cinergyt2_usb_table); | ||
| 196 | |||
| 197 | static struct dvb_usb_device_properties cinergyt2_properties = { | ||
| 198 | .size_of_priv = sizeof(struct cinergyt2_state), | ||
| 199 | .num_adapters = 1, | ||
| 200 | .adapter = { | ||
| 201 | { | ||
| 202 | .streaming_ctrl = cinergyt2_streaming_ctrl, | ||
| 203 | .frontend_attach = cinergyt2_frontend_attach, | ||
| 204 | |||
| 205 | /* parameter for the MPEG2-data transfer */ | ||
| 206 | .stream = { | ||
| 207 | .type = USB_BULK, | ||
| 208 | .count = 5, | ||
| 209 | .endpoint = 0x02, | ||
| 210 | .u = { | ||
| 211 | .bulk = { | ||
| 212 | .buffersize = 512, | ||
| 213 | } | ||
| 214 | } | ||
| 215 | }, | ||
| 216 | } | ||
| 217 | }, | ||
| 218 | |||
| 219 | .power_ctrl = cinergyt2_power_ctrl, | ||
| 220 | |||
| 221 | .rc_interval = 50, | ||
| 222 | .rc_key_map = cinergyt2_rc_keys, | ||
| 223 | .rc_key_map_size = ARRAY_SIZE(cinergyt2_rc_keys), | ||
| 224 | .rc_query = cinergyt2_rc_query, | ||
| 225 | |||
| 226 | .generic_bulk_ctrl_endpoint = 1, | ||
| 227 | |||
| 228 | .num_device_descs = 1, | ||
| 229 | .devices = { | ||
| 230 | { .name = "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver", | ||
| 231 | .cold_ids = {NULL}, | ||
| 232 | .warm_ids = { &cinergyt2_usb_table[0], NULL }, | ||
| 233 | }, | ||
| 234 | { NULL }, | ||
| 235 | } | ||
| 236 | }; | ||
| 237 | |||
| 238 | |||
| 239 | static struct usb_driver cinergyt2_driver = { | ||
| 240 | .name = "cinergyT2", | ||
| 241 | .probe = cinergyt2_usb_probe, | ||
| 242 | .disconnect = dvb_usb_device_exit, | ||
| 243 | .id_table = cinergyt2_usb_table | ||
| 244 | }; | ||
| 245 | |||
| 246 | static int __init cinergyt2_usb_init(void) | ||
| 247 | { | ||
| 248 | int err; | ||
| 249 | |||
| 250 | err = usb_register(&cinergyt2_driver); | ||
| 251 | if (err) { | ||
| 252 | err("usb_register() failed! (err %i)\n", err); | ||
| 253 | return err; | ||
| 254 | } | ||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | static void __exit cinergyt2_usb_exit(void) | ||
| 259 | { | ||
| 260 | usb_deregister(&cinergyt2_driver); | ||
| 261 | } | ||
| 262 | |||
| 263 | module_init(cinergyt2_usb_init); | ||
| 264 | module_exit(cinergyt2_usb_exit); | ||
| 265 | |||
| 266 | MODULE_DESCRIPTION("Terratec Cinergy T2 DVB-T driver"); | ||
| 267 | MODULE_LICENSE("GPL"); | ||
| 268 | MODULE_AUTHOR("Tomi Orava"); | ||
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c new file mode 100644 index 000000000000..649f25cca49e --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c | |||
| @@ -0,0 +1,351 @@ | |||
| 1 | /* | ||
| 2 | * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) | ||
| 5 | * | ||
| 6 | * Based on the dvb-usb-framework code and the | ||
| 7 | * original Terratec Cinergy T2 driver by: | ||
| 8 | * | ||
| 9 | * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and | ||
| 10 | * Holger Waechtler <holger@qanu.de> | ||
| 11 | * | ||
| 12 | * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or modify | ||
| 15 | * it under the terms of the GNU General Public License as published by | ||
| 16 | * the Free Software Foundation; either version 2 of the License, or | ||
| 17 | * (at your option) any later version. | ||
| 18 | * | ||
| 19 | * This program is distributed in the hope that it will be useful, | ||
| 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 22 | * GNU General Public License for more details. | ||
| 23 | * | ||
| 24 | * You should have received a copy of the GNU General Public License | ||
| 25 | * along with this program; if not, write to the Free Software | ||
| 26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include "cinergyT2.h" | ||
| 31 | |||
| 32 | |||
| 33 | /** | ||
| 34 | * convert linux-dvb frontend parameter set into TPS. | ||
| 35 | * See ETSI ETS-300744, section 4.6.2, table 9 for details. | ||
| 36 | * | ||
| 37 | * This function is probably reusable and may better get placed in a support | ||
| 38 | * library. | ||
| 39 | * | ||
| 40 | * We replace errornous fields by default TPS fields (the ones with value 0). | ||
| 41 | */ | ||
| 42 | |||
| 43 | static uint16_t compute_tps(struct dvb_frontend_parameters *p) | ||
| 44 | { | ||
| 45 | struct dvb_ofdm_parameters *op = &p->u.ofdm; | ||
| 46 | uint16_t tps = 0; | ||
| 47 | |||
| 48 | switch (op->code_rate_HP) { | ||
| 49 | case FEC_2_3: | ||
| 50 | tps |= (1 << 7); | ||
| 51 | break; | ||
| 52 | case FEC_3_4: | ||
| 53 | tps |= (2 << 7); | ||
| 54 | break; | ||
| 55 | case FEC_5_6: | ||
| 56 | tps |= (3 << 7); | ||
| 57 | break; | ||
| 58 | case FEC_7_8: | ||
| 59 | tps |= (4 << 7); | ||
| 60 | break; | ||
| 61 | case FEC_1_2: | ||
| 62 | case FEC_AUTO: | ||
| 63 | default: | ||
| 64 | /* tps |= (0 << 7) */; | ||
| 65 | } | ||
| 66 | |||
| 67 | switch (op->code_rate_LP) { | ||
| 68 | case FEC_2_3: | ||
| 69 | tps |= (1 << 4); | ||
| 70 | break; | ||
| 71 | case FEC_3_4: | ||
| 72 | tps |= (2 << 4); | ||
| 73 | break; | ||
| 74 | case FEC_5_6: | ||
| 75 | tps |= (3 << 4); | ||
| 76 | break; | ||
| 77 | case FEC_7_8: | ||
| 78 | tps |= (4 << 4); | ||
| 79 | break; | ||
| 80 | case FEC_1_2: | ||
| 81 | case FEC_AUTO: | ||
| 82 | default: | ||
| 83 | /* tps |= (0 << 4) */; | ||
| 84 | } | ||
| 85 | |||
| 86 | switch (op->constellation) { | ||
| 87 | case QAM_16: | ||
| 88 | tps |= (1 << 13); | ||
| 89 | break; | ||
| 90 | case QAM_64: | ||
| 91 | tps |= (2 << 13); | ||
| 92 | break; | ||
| 93 | case QPSK: | ||
| 94 | default: | ||
| 95 | /* tps |= (0 << 13) */; | ||
| 96 | } | ||
| 97 | |||
| 98 | switch (op->transmission_mode) { | ||
| 99 | case TRANSMISSION_MODE_8K: | ||
| 100 | tps |= (1 << 0); | ||
| 101 | break; | ||
| 102 | case TRANSMISSION_MODE_2K: | ||
| 103 | default: | ||
| 104 | /* tps |= (0 << 0) */; | ||
| 105 | } | ||
| 106 | |||
| 107 | switch (op->guard_interval) { | ||
| 108 | case GUARD_INTERVAL_1_16: | ||
| 109 | tps |= (1 << 2); | ||
| 110 | break; | ||
| 111 | case GUARD_INTERVAL_1_8: | ||
| 112 | tps |= (2 << 2); | ||
| 113 | break; | ||
| 114 | case GUARD_INTERVAL_1_4: | ||
| 115 | tps |= (3 << 2); | ||
| 116 | break; | ||
| 117 | case GUARD_INTERVAL_1_32: | ||
| 118 | default: | ||
| 119 | /* tps |= (0 << 2) */; | ||
| 120 | } | ||
| 121 | |||
| 122 | switch (op->hierarchy_information) { | ||
| 123 | case HIERARCHY_1: | ||
| 124 | tps |= (1 << 10); | ||
| 125 | break; | ||
| 126 | case HIERARCHY_2: | ||
| 127 | tps |= (2 << 10); | ||
| 128 | break; | ||
| 129 | case HIERARCHY_4: | ||
| 130 | tps |= (3 << 10); | ||
| 131 | break; | ||
| 132 | case HIERARCHY_NONE: | ||
| 133 | default: | ||
| 134 | /* tps |= (0 << 10) */; | ||
| 135 | } | ||
| 136 | |||
| 137 | return tps; | ||
| 138 | } | ||
| 139 | |||
| 140 | struct cinergyt2_fe_state { | ||
| 141 | struct dvb_frontend fe; | ||
| 142 | struct dvb_usb_device *d; | ||
| 143 | }; | ||
| 144 | |||
| 145 | static int cinergyt2_fe_read_status(struct dvb_frontend *fe, | ||
| 146 | fe_status_t *status) | ||
| 147 | { | ||
| 148 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
| 149 | struct dvbt_get_status_msg result; | ||
| 150 | u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 151 | int ret; | ||
| 152 | |||
| 153 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result, | ||
| 154 | sizeof(result), 0); | ||
| 155 | if (ret < 0) | ||
| 156 | return ret; | ||
| 157 | |||
| 158 | *status = 0; | ||
| 159 | |||
| 160 | if (0xffff - le16_to_cpu(result.gain) > 30) | ||
| 161 | *status |= FE_HAS_SIGNAL; | ||
| 162 | if (result.lock_bits & (1 << 6)) | ||
| 163 | *status |= FE_HAS_LOCK; | ||
| 164 | if (result.lock_bits & (1 << 5)) | ||
| 165 | *status |= FE_HAS_SYNC; | ||
| 166 | if (result.lock_bits & (1 << 4)) | ||
| 167 | *status |= FE_HAS_CARRIER; | ||
| 168 | if (result.lock_bits & (1 << 1)) | ||
| 169 | *status |= FE_HAS_VITERBI; | ||
| 170 | |||
| 171 | if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != | ||
| 172 | (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) | ||
| 173 | *status &= ~FE_HAS_LOCK; | ||
| 174 | |||
| 175 | return 0; | ||
| 176 | } | ||
| 177 | |||
| 178 | static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
| 179 | { | ||
| 180 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
| 181 | struct dvbt_get_status_msg status; | ||
| 182 | char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 183 | int ret; | ||
| 184 | |||
| 185 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, | ||
| 186 | sizeof(status), 0); | ||
| 187 | if (ret < 0) | ||
| 188 | return ret; | ||
| 189 | |||
| 190 | *ber = le32_to_cpu(status.viterbi_error_rate); | ||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) | ||
| 195 | { | ||
| 196 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
| 197 | struct dvbt_get_status_msg status; | ||
| 198 | u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 199 | int ret; | ||
| 200 | |||
| 201 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status, | ||
| 202 | sizeof(status), 0); | ||
| 203 | if (ret < 0) { | ||
| 204 | err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n", | ||
| 205 | ret); | ||
| 206 | return ret; | ||
| 207 | } | ||
| 208 | *unc = le32_to_cpu(status.uncorrected_block_count); | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe, | ||
| 213 | u16 *strength) | ||
| 214 | { | ||
| 215 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
| 216 | struct dvbt_get_status_msg status; | ||
| 217 | char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 218 | int ret; | ||
| 219 | |||
| 220 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, | ||
| 221 | sizeof(status), 0); | ||
| 222 | if (ret < 0) { | ||
| 223 | err("cinergyt2_fe_read_signal_strength() Failed!" | ||
| 224 | " (Error=%d)\n", ret); | ||
| 225 | return ret; | ||
| 226 | } | ||
| 227 | *strength = (0xffff - le16_to_cpu(status.gain)); | ||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
| 232 | { | ||
| 233 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
| 234 | struct dvbt_get_status_msg status; | ||
| 235 | char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 236 | int ret; | ||
| 237 | |||
| 238 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, | ||
| 239 | sizeof(status), 0); | ||
| 240 | if (ret < 0) { | ||
| 241 | err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret); | ||
| 242 | return ret; | ||
| 243 | } | ||
| 244 | *snr = (status.snr << 8) | status.snr; | ||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | |||
| 248 | static int cinergyt2_fe_init(struct dvb_frontend *fe) | ||
| 249 | { | ||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | |||
| 253 | static int cinergyt2_fe_sleep(struct dvb_frontend *fe) | ||
| 254 | { | ||
| 255 | deb_info("cinergyt2_fe_sleep() Called\n"); | ||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | static int cinergyt2_fe_get_tune_settings(struct dvb_frontend *fe, | ||
| 260 | struct dvb_frontend_tune_settings *tune) | ||
| 261 | { | ||
| 262 | tune->min_delay_ms = 800; | ||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | |||
| 266 | static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe, | ||
| 267 | struct dvb_frontend_parameters *fep) | ||
| 268 | { | ||
| 269 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
| 270 | struct dvbt_set_parameters_msg param; | ||
| 271 | char result[2]; | ||
| 272 | int err; | ||
| 273 | |||
| 274 | param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; | ||
| 275 | param.tps = cpu_to_le16(compute_tps(fep)); | ||
| 276 | param.freq = cpu_to_le32(fep->frequency / 1000); | ||
| 277 | param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ; | ||
| 278 | |||
| 279 | err = dvb_usb_generic_rw(state->d, | ||
| 280 | (char *)¶m, sizeof(param), | ||
| 281 | result, sizeof(result), 0); | ||
| 282 | if (err < 0) | ||
| 283 | err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); | ||
| 284 | |||
| 285 | return (err < 0) ? err : 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int cinergyt2_fe_get_frontend(struct dvb_frontend *fe, | ||
| 289 | struct dvb_frontend_parameters *fep) | ||
| 290 | { | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | static void cinergyt2_fe_release(struct dvb_frontend *fe) | ||
| 295 | { | ||
| 296 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
| 297 | if (state != NULL) | ||
| 298 | kfree(state); | ||
| 299 | } | ||
| 300 | |||
| 301 | static struct dvb_frontend_ops cinergyt2_fe_ops; | ||
| 302 | |||
| 303 | struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d) | ||
| 304 | { | ||
| 305 | struct cinergyt2_fe_state *s = kzalloc(sizeof( | ||
| 306 | struct cinergyt2_fe_state), GFP_KERNEL); | ||
| 307 | if (s == NULL) | ||
| 308 | return NULL; | ||
| 309 | |||
| 310 | s->d = d; | ||
| 311 | memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops)); | ||
| 312 | s->fe.demodulator_priv = s; | ||
| 313 | return &s->fe; | ||
| 314 | } | ||
| 315 | |||
| 316 | |||
| 317 | static struct dvb_frontend_ops cinergyt2_fe_ops = { | ||
| 318 | .info = { | ||
| 319 | .name = DRIVER_NAME, | ||
| 320 | .type = FE_OFDM, | ||
| 321 | .frequency_min = 174000000, | ||
| 322 | .frequency_max = 862000000, | ||
| 323 | .frequency_stepsize = 166667, | ||
| 324 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | ||
| 325 | | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ||
| 326 | | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | ||
| 327 | | FE_CAN_FEC_AUTO | FE_CAN_QPSK | ||
| 328 | | FE_CAN_QAM_16 | FE_CAN_QAM_64 | ||
| 329 | | FE_CAN_QAM_AUTO | ||
| 330 | | FE_CAN_TRANSMISSION_MODE_AUTO | ||
| 331 | | FE_CAN_GUARD_INTERVAL_AUTO | ||
| 332 | | FE_CAN_HIERARCHY_AUTO | ||
| 333 | | FE_CAN_RECOVER | ||
| 334 | | FE_CAN_MUTE_TS | ||
| 335 | }, | ||
| 336 | |||
| 337 | .release = cinergyt2_fe_release, | ||
| 338 | |||
| 339 | .init = cinergyt2_fe_init, | ||
| 340 | .sleep = cinergyt2_fe_sleep, | ||
| 341 | |||
| 342 | .set_frontend = cinergyt2_fe_set_frontend, | ||
| 343 | .get_frontend = cinergyt2_fe_get_frontend, | ||
| 344 | .get_tune_settings = cinergyt2_fe_get_tune_settings, | ||
| 345 | |||
| 346 | .read_status = cinergyt2_fe_read_status, | ||
| 347 | .read_ber = cinergyt2_fe_read_ber, | ||
| 348 | .read_signal_strength = cinergyt2_fe_read_signal_strength, | ||
| 349 | .read_snr = cinergyt2_fe_read_snr, | ||
| 350 | .read_ucblocks = cinergyt2_fe_read_unc_blocks, | ||
| 351 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2.h b/drivers/media/dvb/dvb-usb/cinergyT2.h new file mode 100644 index 000000000000..11d79eb384c8 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2.h | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | /* | ||
| 2 | * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) | ||
| 5 | * | ||
| 6 | * Based on the dvb-usb-framework code and the | ||
| 7 | * original Terratec Cinergy T2 driver by: | ||
| 8 | * | ||
| 9 | * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and | ||
| 10 | * Holger Waechtler <holger@qanu.de> | ||
| 11 | * | ||
| 12 | * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or modify | ||
| 15 | * it under the terms of the GNU General Public License as published by | ||
| 16 | * the Free Software Foundation; either version 2 of the License, or | ||
| 17 | * (at your option) any later version. | ||
| 18 | * | ||
| 19 | * This program is distributed in the hope that it will be useful, | ||
| 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 22 | * GNU General Public License for more details. | ||
| 23 | * | ||
| 24 | * You should have received a copy of the GNU General Public License | ||
| 25 | * along with this program; if not, write to the Free Software | ||
| 26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | #ifndef _DVB_USB_CINERGYT2_H_ | ||
| 31 | #define _DVB_USB_CINERGYT2_H_ | ||
| 32 | |||
| 33 | #include <linux/usb/input.h> | ||
| 34 | |||
| 35 | #define DVB_USB_LOG_PREFIX "cinergyT2" | ||
| 36 | #include "dvb-usb.h" | ||
| 37 | |||
| 38 | #define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver" | ||
| 39 | |||
| 40 | extern int dvb_usb_cinergyt2_debug; | ||
| 41 | |||
| 42 | #define deb_info(args...) dprintk(dvb_usb_cinergyt2_debug, 0x001, args) | ||
| 43 | #define deb_xfer(args...) dprintk(dvb_usb_cinergyt2_debug, 0x002, args) | ||
| 44 | #define deb_pll(args...) dprintk(dvb_usb_cinergyt2_debug, 0x004, args) | ||
| 45 | #define deb_ts(args...) dprintk(dvb_usb_cinergyt2_debug, 0x008, args) | ||
| 46 | #define deb_err(args...) dprintk(dvb_usb_cinergyt2_debug, 0x010, args) | ||
| 47 | #define deb_rc(args...) dprintk(dvb_usb_cinergyt2_debug, 0x020, args) | ||
| 48 | #define deb_fw(args...) dprintk(dvb_usb_cinergyt2_debug, 0x040, args) | ||
| 49 | #define deb_mem(args...) dprintk(dvb_usb_cinergyt2_debug, 0x080, args) | ||
| 50 | #define deb_uxfer(args...) dprintk(dvb_usb_cinergyt2_debug, 0x100, args) | ||
| 51 | |||
| 52 | |||
| 53 | |||
| 54 | enum cinergyt2_ep1_cmd { | ||
| 55 | CINERGYT2_EP1_PID_TABLE_RESET = 0x01, | ||
| 56 | CINERGYT2_EP1_PID_SETUP = 0x02, | ||
| 57 | CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03, | ||
| 58 | CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04, | ||
| 59 | CINERGYT2_EP1_GET_TUNER_STATUS = 0x05, | ||
| 60 | CINERGYT2_EP1_START_SCAN = 0x06, | ||
| 61 | CINERGYT2_EP1_CONTINUE_SCAN = 0x07, | ||
| 62 | CINERGYT2_EP1_GET_RC_EVENTS = 0x08, | ||
| 63 | CINERGYT2_EP1_SLEEP_MODE = 0x09, | ||
| 64 | CINERGYT2_EP1_GET_FIRMWARE_VERSION = 0x0A | ||
| 65 | }; | ||
| 66 | |||
| 67 | |||
| 68 | struct dvbt_get_status_msg { | ||
| 69 | uint32_t freq; | ||
| 70 | uint8_t bandwidth; | ||
| 71 | uint16_t tps; | ||
| 72 | uint8_t flags; | ||
| 73 | uint16_t gain; | ||
| 74 | uint8_t snr; | ||
| 75 | uint32_t viterbi_error_rate; | ||
| 76 | uint32_t rs_error_rate; | ||
| 77 | uint32_t uncorrected_block_count; | ||
| 78 | uint8_t lock_bits; | ||
| 79 | uint8_t prev_lock_bits; | ||
| 80 | } __attribute__((packed)); | ||
| 81 | |||
| 82 | |||
| 83 | struct dvbt_set_parameters_msg { | ||
| 84 | uint8_t cmd; | ||
| 85 | uint32_t freq; | ||
| 86 | uint8_t bandwidth; | ||
| 87 | uint16_t tps; | ||
| 88 | uint8_t flags; | ||
| 89 | } __attribute__((packed)); | ||
| 90 | |||
| 91 | |||
| 92 | extern struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d); | ||
| 93 | |||
| 94 | #endif /* _DVB_USB_CINERGYT2_H_ */ | ||
| 95 | |||
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 563400277a42..406d7fba369d 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c | |||
| @@ -36,6 +36,9 @@ | |||
| 36 | #include "tuner-xc2028.h" | 36 | #include "tuner-xc2028.h" |
| 37 | #include "tuner-simple.h" | 37 | #include "tuner-simple.h" |
| 38 | #include "mxl5005s.h" | 38 | #include "mxl5005s.h" |
| 39 | #include "dib7000p.h" | ||
| 40 | #include "dib0070.h" | ||
| 41 | #include "lgs8gl5.h" | ||
| 39 | 42 | ||
| 40 | /* debug */ | 43 | /* debug */ |
| 41 | static int dvb_usb_cxusb_debug; | 44 | static int dvb_usb_cxusb_debug; |
| @@ -109,6 +112,25 @@ static void cxusb_nano2_led(struct dvb_usb_device *d, int onoff) | |||
| 109 | cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40); | 112 | cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40); |
| 110 | } | 113 | } |
| 111 | 114 | ||
| 115 | static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d, | ||
| 116 | u8 addr, int onoff) | ||
| 117 | { | ||
| 118 | u8 o[2] = {addr, onoff}; | ||
| 119 | u8 i; | ||
| 120 | int rc; | ||
| 121 | |||
| 122 | rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); | ||
| 123 | |||
| 124 | if (rc < 0) | ||
| 125 | return rc; | ||
| 126 | if (i == 0x01) | ||
| 127 | return 0; | ||
| 128 | else { | ||
| 129 | deb_info("gpio_write failed.\n"); | ||
| 130 | return -EIO; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 112 | /* I2C */ | 134 | /* I2C */ |
| 113 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | 135 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
| 114 | int num) | 136 | int num) |
| @@ -262,6 +284,20 @@ static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff) | |||
| 262 | return rc; | 284 | return rc; |
| 263 | } | 285 | } |
| 264 | 286 | ||
| 287 | static int cxusb_d680_dmb_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 288 | { | ||
| 289 | int ret; | ||
| 290 | u8 b; | ||
| 291 | ret = cxusb_power_ctrl(d, onoff); | ||
| 292 | if (!onoff) | ||
| 293 | return ret; | ||
| 294 | |||
| 295 | msleep(128); | ||
| 296 | cxusb_ctrl_msg(d, CMD_DIGITAL, NULL, 0, &b, 1); | ||
| 297 | msleep(100); | ||
| 298 | return ret; | ||
| 299 | } | ||
| 300 | |||
| 265 | static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | 301 | static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
| 266 | { | 302 | { |
| 267 | u8 buf[2] = { 0x03, 0x00 }; | 303 | u8 buf[2] = { 0x03, 0x00 }; |
| @@ -283,6 +319,67 @@ static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
| 283 | return 0; | 319 | return 0; |
| 284 | } | 320 | } |
| 285 | 321 | ||
| 322 | static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d) | ||
| 323 | { | ||
| 324 | int ep = d->props.generic_bulk_ctrl_endpoint; | ||
| 325 | const int timeout = 100; | ||
| 326 | const int junk_len = 32; | ||
| 327 | u8 *junk; | ||
| 328 | int rd_count; | ||
| 329 | |||
| 330 | /* Discard remaining data in video pipe */ | ||
| 331 | junk = kmalloc(junk_len, GFP_KERNEL); | ||
| 332 | if (!junk) | ||
| 333 | return; | ||
| 334 | while (1) { | ||
| 335 | if (usb_bulk_msg(d->udev, | ||
| 336 | usb_rcvbulkpipe(d->udev, ep), | ||
| 337 | junk, junk_len, &rd_count, timeout) < 0) | ||
| 338 | break; | ||
| 339 | if (!rd_count) | ||
| 340 | break; | ||
| 341 | } | ||
| 342 | kfree(junk); | ||
| 343 | } | ||
| 344 | |||
| 345 | static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d) | ||
| 346 | { | ||
| 347 | struct usb_data_stream_properties *p = &d->props.adapter[0].stream; | ||
| 348 | const int timeout = 100; | ||
| 349 | const int junk_len = p->u.bulk.buffersize; | ||
| 350 | u8 *junk; | ||
| 351 | int rd_count; | ||
| 352 | |||
| 353 | /* Discard remaining data in video pipe */ | ||
| 354 | junk = kmalloc(junk_len, GFP_KERNEL); | ||
| 355 | if (!junk) | ||
| 356 | return; | ||
| 357 | while (1) { | ||
| 358 | if (usb_bulk_msg(d->udev, | ||
| 359 | usb_rcvbulkpipe(d->udev, p->endpoint), | ||
| 360 | junk, junk_len, &rd_count, timeout) < 0) | ||
| 361 | break; | ||
| 362 | if (!rd_count) | ||
| 363 | break; | ||
| 364 | } | ||
| 365 | kfree(junk); | ||
| 366 | } | ||
| 367 | |||
| 368 | static int cxusb_d680_dmb_streaming_ctrl( | ||
| 369 | struct dvb_usb_adapter *adap, int onoff) | ||
| 370 | { | ||
| 371 | if (onoff) { | ||
| 372 | u8 buf[2] = { 0x03, 0x00 }; | ||
| 373 | cxusb_d680_dmb_drain_video(adap->dev); | ||
| 374 | return cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON, | ||
| 375 | buf, sizeof(buf), NULL, 0); | ||
| 376 | } else { | ||
| 377 | int ret = cxusb_ctrl_msg(adap->dev, | ||
| 378 | CMD_STREAMING_OFF, NULL, 0, NULL, 0); | ||
| 379 | return ret; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 286 | static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 383 | static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
| 287 | { | 384 | { |
| 288 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | 385 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; |
| @@ -335,6 +432,32 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event, | |||
| 335 | return 0; | 432 | return 0; |
| 336 | } | 433 | } |
| 337 | 434 | ||
| 435 | static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, | ||
| 436 | int *state) | ||
| 437 | { | ||
| 438 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | ||
| 439 | u8 ircode[2]; | ||
| 440 | int i; | ||
| 441 | |||
| 442 | *event = 0; | ||
| 443 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 444 | |||
| 445 | if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0) | ||
| 446 | return 0; | ||
| 447 | |||
| 448 | for (i = 0; i < d->props.rc_key_map_size; i++) { | ||
| 449 | if (keymap[i].custom == ircode[0] && | ||
| 450 | keymap[i].data == ircode[1]) { | ||
| 451 | *event = keymap[i].event; | ||
| 452 | *state = REMOTE_KEY_PRESSED; | ||
| 453 | |||
| 454 | return 0; | ||
| 455 | } | ||
| 456 | } | ||
| 457 | |||
| 458 | return 0; | ||
| 459 | } | ||
| 460 | |||
| 338 | static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { | 461 | static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { |
| 339 | { 0xfe, 0x02, KEY_TV }, | 462 | { 0xfe, 0x02, KEY_TV }, |
| 340 | { 0xfe, 0x0e, KEY_MP3 }, | 463 | { 0xfe, 0x0e, KEY_MP3 }, |
| @@ -422,6 +545,44 @@ static struct dvb_usb_rc_key dvico_portable_rc_keys[] = { | |||
| 422 | { 0xfc, 0x00, KEY_UNKNOWN }, /* HD */ | 545 | { 0xfc, 0x00, KEY_UNKNOWN }, /* HD */ |
| 423 | }; | 546 | }; |
| 424 | 547 | ||
| 548 | static struct dvb_usb_rc_key d680_dmb_rc_keys[] = { | ||
| 549 | { 0x00, 0x38, KEY_UNKNOWN }, /* TV/AV */ | ||
| 550 | { 0x08, 0x0c, KEY_ZOOM }, | ||
| 551 | { 0x08, 0x00, KEY_0 }, | ||
| 552 | { 0x00, 0x01, KEY_1 }, | ||
| 553 | { 0x08, 0x02, KEY_2 }, | ||
| 554 | { 0x00, 0x03, KEY_3 }, | ||
| 555 | { 0x08, 0x04, KEY_4 }, | ||
| 556 | { 0x00, 0x05, KEY_5 }, | ||
| 557 | { 0x08, 0x06, KEY_6 }, | ||
| 558 | { 0x00, 0x07, KEY_7 }, | ||
| 559 | { 0x08, 0x08, KEY_8 }, | ||
| 560 | { 0x00, 0x09, KEY_9 }, | ||
| 561 | { 0x00, 0x0a, KEY_MUTE }, | ||
| 562 | { 0x08, 0x29, KEY_BACK }, | ||
| 563 | { 0x00, 0x12, KEY_CHANNELUP }, | ||
| 564 | { 0x08, 0x13, KEY_CHANNELDOWN }, | ||
| 565 | { 0x00, 0x2b, KEY_VOLUMEUP }, | ||
| 566 | { 0x08, 0x2c, KEY_VOLUMEDOWN }, | ||
| 567 | { 0x00, 0x20, KEY_UP }, | ||
| 568 | { 0x08, 0x21, KEY_DOWN }, | ||
| 569 | { 0x00, 0x11, KEY_LEFT }, | ||
| 570 | { 0x08, 0x10, KEY_RIGHT }, | ||
| 571 | { 0x00, 0x0d, KEY_OK }, | ||
| 572 | { 0x08, 0x1f, KEY_RECORD }, | ||
| 573 | { 0x00, 0x17, KEY_PLAYPAUSE }, | ||
| 574 | { 0x08, 0x16, KEY_PLAYPAUSE }, | ||
| 575 | { 0x00, 0x0b, KEY_STOP }, | ||
| 576 | { 0x08, 0x27, KEY_FASTFORWARD }, | ||
| 577 | { 0x00, 0x26, KEY_REWIND }, | ||
| 578 | { 0x08, 0x1e, KEY_UNKNOWN }, /* Time Shift */ | ||
| 579 | { 0x00, 0x0e, KEY_UNKNOWN }, /* Snapshot */ | ||
| 580 | { 0x08, 0x2d, KEY_UNKNOWN }, /* Mouse Cursor */ | ||
| 581 | { 0x00, 0x0f, KEY_UNKNOWN }, /* Minimize/Maximize */ | ||
| 582 | { 0x08, 0x14, KEY_UNKNOWN }, /* Shuffle */ | ||
| 583 | { 0x00, 0x25, KEY_POWER }, | ||
| 584 | }; | ||
| 585 | |||
| 425 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) | 586 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) |
| 426 | { | 587 | { |
| 427 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; | 588 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; |
| @@ -527,6 +688,24 @@ static struct mxl5005s_config aver_a868r_tuner = { | |||
| 527 | .AgcMasterByte = 0x00, | 688 | .AgcMasterByte = 0x00, |
| 528 | }; | 689 | }; |
| 529 | 690 | ||
| 691 | /* FIXME: needs tweaking */ | ||
| 692 | static struct mxl5005s_config d680_dmb_tuner = { | ||
| 693 | .i2c_address = 0x63, | ||
| 694 | .if_freq = 36125000UL, | ||
| 695 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
| 696 | .agc_mode = MXL_SINGLE_AGC, | ||
| 697 | .tracking_filter = MXL_TF_C, | ||
| 698 | .rssi_enable = MXL_RSSI_ENABLE, | ||
| 699 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
| 700 | .div_out = MXL_DIV_OUT_4, | ||
| 701 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
| 702 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
| 703 | .top = MXL5005S_TOP_25P2, | ||
| 704 | .mod_mode = MXL_DIGITAL_MODE, | ||
| 705 | .if_mode = MXL_ZERO_IF, | ||
| 706 | .AgcMasterByte = 0x00, | ||
| 707 | }; | ||
| 708 | |||
| 530 | /* Callbacks for DVB USB */ | 709 | /* Callbacks for DVB USB */ |
| 531 | static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) | 710 | static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) |
| 532 | { | 711 | { |
| @@ -563,7 +742,8 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 563 | return 0; | 742 | return 0; |
| 564 | } | 743 | } |
| 565 | 744 | ||
| 566 | static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg) | 745 | static int dvico_bluebird_xc2028_callback(void *ptr, int component, |
| 746 | int command, int arg) | ||
| 567 | { | 747 | { |
| 568 | struct dvb_usb_adapter *adap = ptr; | 748 | struct dvb_usb_adapter *adap = ptr; |
| 569 | struct dvb_usb_device *d = adap->dev; | 749 | struct dvb_usb_device *d = adap->dev; |
| @@ -591,14 +771,16 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 591 | struct xc2028_config cfg = { | 771 | struct xc2028_config cfg = { |
| 592 | .i2c_adap = &adap->dev->i2c_adap, | 772 | .i2c_adap = &adap->dev->i2c_adap, |
| 593 | .i2c_addr = 0x61, | 773 | .i2c_addr = 0x61, |
| 594 | .callback = dvico_bluebird_xc2028_callback, | ||
| 595 | }; | 774 | }; |
| 596 | static struct xc2028_ctrl ctl = { | 775 | static struct xc2028_ctrl ctl = { |
| 597 | .fname = "xc3028-v27.fw", | 776 | .fname = XC2028_DEFAULT_FIRMWARE, |
| 598 | .max_len = 64, | 777 | .max_len = 64, |
| 599 | .demod = XC3028_FE_ZARLINK456, | 778 | .demod = XC3028_FE_ZARLINK456, |
| 600 | }; | 779 | }; |
| 601 | 780 | ||
| 781 | /* FIXME: generalize & move to common area */ | ||
| 782 | adap->fe->callback = dvico_bluebird_xc2028_callback; | ||
| 783 | |||
| 602 | fe = dvb_attach(xc2028_attach, adap->fe, &cfg); | 784 | fe = dvb_attach(xc2028_attach, adap->fe, &cfg); |
| 603 | if (fe == NULL || fe->ops.tuner_ops.set_config == NULL) | 785 | if (fe == NULL || fe->ops.tuner_ops.set_config == NULL) |
| 604 | return -EIO; | 786 | return -EIO; |
| @@ -615,6 +797,14 @@ static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 615 | return 0; | 797 | return 0; |
| 616 | } | 798 | } |
| 617 | 799 | ||
| 800 | static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 801 | { | ||
| 802 | struct dvb_frontend *fe; | ||
| 803 | fe = dvb_attach(mxl5005s_attach, adap->fe, | ||
| 804 | &adap->dev->i2c_adap, &d680_dmb_tuner); | ||
| 805 | return (fe == NULL) ? -EIO : 0; | ||
| 806 | } | ||
| 807 | |||
| 618 | static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) | 808 | static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) |
| 619 | { | 809 | { |
| 620 | u8 b; | 810 | u8 b; |
| @@ -726,6 +916,159 @@ no_IR: | |||
| 726 | return 0; | 916 | return 0; |
| 727 | } | 917 | } |
| 728 | 918 | ||
| 919 | static struct dibx000_agc_config dib7070_agc_config = { | ||
| 920 | .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, | ||
| 921 | |||
| 922 | /* | ||
| 923 | * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, | ||
| 924 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | ||
| 925 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 | ||
| 926 | */ | ||
| 927 | .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | | ||
| 928 | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
| 929 | .inv_gain = 600, | ||
| 930 | .time_stabiliz = 10, | ||
| 931 | .alpha_level = 0, | ||
| 932 | .thlock = 118, | ||
| 933 | .wbd_inv = 0, | ||
| 934 | .wbd_ref = 3530, | ||
| 935 | .wbd_sel = 1, | ||
| 936 | .wbd_alpha = 5, | ||
| 937 | .agc1_max = 65535, | ||
| 938 | .agc1_min = 0, | ||
| 939 | .agc2_max = 65535, | ||
| 940 | .agc2_min = 0, | ||
| 941 | .agc1_pt1 = 0, | ||
| 942 | .agc1_pt2 = 40, | ||
| 943 | .agc1_pt3 = 183, | ||
| 944 | .agc1_slope1 = 206, | ||
| 945 | .agc1_slope2 = 255, | ||
| 946 | .agc2_pt1 = 72, | ||
| 947 | .agc2_pt2 = 152, | ||
| 948 | .agc2_slope1 = 88, | ||
| 949 | .agc2_slope2 = 90, | ||
| 950 | .alpha_mant = 17, | ||
| 951 | .alpha_exp = 27, | ||
| 952 | .beta_mant = 23, | ||
| 953 | .beta_exp = 51, | ||
| 954 | .perform_agc_softsplit = 0, | ||
| 955 | }; | ||
| 956 | |||
| 957 | static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { | ||
| 958 | .internal = 60000, | ||
| 959 | .sampling = 15000, | ||
| 960 | .pll_prediv = 1, | ||
| 961 | .pll_ratio = 20, | ||
| 962 | .pll_range = 3, | ||
| 963 | .pll_reset = 1, | ||
| 964 | .pll_bypass = 0, | ||
| 965 | .enable_refdiv = 0, | ||
| 966 | .bypclk_div = 0, | ||
| 967 | .IO_CLK_en_core = 1, | ||
| 968 | .ADClkSrc = 1, | ||
| 969 | .modulo = 2, | ||
| 970 | /* refsel, sel, freq_15k */ | ||
| 971 | .sad_cfg = (3 << 14) | (1 << 12) | (524 << 0), | ||
| 972 | .ifreq = (0 << 25) | 0, | ||
| 973 | .timf = 20452225, | ||
| 974 | .xtal_hz = 12000000, | ||
| 975 | }; | ||
| 976 | |||
| 977 | static struct dib7000p_config cxusb_dualdig4_rev2_config = { | ||
| 978 | .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, | ||
| 979 | .output_mpeg2_in_188_bytes = 1, | ||
| 980 | |||
| 981 | .agc_config_count = 1, | ||
| 982 | .agc = &dib7070_agc_config, | ||
| 983 | .bw = &dib7070_bw_config_12_mhz, | ||
| 984 | .tuner_is_baseband = 1, | ||
| 985 | .spur_protect = 1, | ||
| 986 | |||
| 987 | .gpio_dir = 0xfcef, | ||
| 988 | .gpio_val = 0x0110, | ||
| 989 | |||
| 990 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 991 | |||
| 992 | .hostbus_diversity = 1, | ||
| 993 | }; | ||
| 994 | |||
| 995 | static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 996 | { | ||
| 997 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) | ||
| 998 | err("set interface failed"); | ||
| 999 | |||
| 1000 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | ||
| 1001 | |||
| 1002 | cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); | ||
| 1003 | |||
| 1004 | dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | ||
| 1005 | &cxusb_dualdig4_rev2_config); | ||
| 1006 | |||
| 1007 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | ||
| 1008 | &cxusb_dualdig4_rev2_config); | ||
| 1009 | if (adap->fe == NULL) | ||
| 1010 | return -EIO; | ||
| 1011 | |||
| 1012 | return 0; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) | ||
| 1016 | { | ||
| 1017 | return dib7000p_set_gpio(fe, 8, 0, !onoff); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) | ||
| 1021 | { | ||
| 1022 | return 0; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | static struct dib0070_config dib7070p_dib0070_config = { | ||
| 1026 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
| 1027 | .reset = dib7070_tuner_reset, | ||
| 1028 | .sleep = dib7070_tuner_sleep, | ||
| 1029 | .clock_khz = 12000, | ||
| 1030 | }; | ||
| 1031 | |||
| 1032 | struct dib0700_adapter_state { | ||
| 1033 | int (*set_param_save) (struct dvb_frontend *, | ||
| 1034 | struct dvb_frontend_parameters *); | ||
| 1035 | }; | ||
| 1036 | |||
| 1037 | static int dib7070_set_param_override(struct dvb_frontend *fe, | ||
| 1038 | struct dvb_frontend_parameters *fep) | ||
| 1039 | { | ||
| 1040 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 1041 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1042 | |||
| 1043 | u16 offset; | ||
| 1044 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
| 1045 | switch (band) { | ||
| 1046 | case BAND_VHF: offset = 950; break; | ||
| 1047 | default: | ||
| 1048 | case BAND_UHF: offset = 550; break; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); | ||
| 1052 | |||
| 1053 | return state->set_param_save(fe, fep); | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1057 | { | ||
| 1058 | struct dib0700_adapter_state *st = adap->priv; | ||
| 1059 | struct i2c_adapter *tun_i2c = | ||
| 1060 | dib7000p_get_i2c_master(adap->fe, | ||
| 1061 | DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 1062 | |||
| 1063 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, | ||
| 1064 | &dib7070p_dib0070_config) == NULL) | ||
| 1065 | return -ENODEV; | ||
| 1066 | |||
| 1067 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
| 1068 | adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override; | ||
| 1069 | return 0; | ||
| 1070 | } | ||
| 1071 | |||
| 729 | static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) | 1072 | static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) |
| 730 | { | 1073 | { |
| 731 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) | 1074 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) |
| @@ -751,6 +1094,54 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 751 | return -EIO; | 1094 | return -EIO; |
| 752 | } | 1095 | } |
| 753 | 1096 | ||
| 1097 | static struct lgs8gl5_config lgs8gl5_cfg = { | ||
| 1098 | .demod_address = 0x19, | ||
| 1099 | }; | ||
| 1100 | |||
| 1101 | static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1102 | { | ||
| 1103 | struct dvb_usb_device *d = adap->dev; | ||
| 1104 | int n; | ||
| 1105 | |||
| 1106 | /* Select required USB configuration */ | ||
| 1107 | if (usb_set_interface(d->udev, 0, 0) < 0) | ||
| 1108 | err("set interface failed"); | ||
| 1109 | |||
| 1110 | /* Unblock all USB pipes */ | ||
| 1111 | usb_clear_halt(d->udev, | ||
| 1112 | usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | ||
| 1113 | usb_clear_halt(d->udev, | ||
| 1114 | usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | ||
| 1115 | usb_clear_halt(d->udev, | ||
| 1116 | usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint)); | ||
| 1117 | |||
| 1118 | /* Drain USB pipes to avoid hang after reboot */ | ||
| 1119 | for (n = 0; n < 5; n++) { | ||
| 1120 | cxusb_d680_dmb_drain_message(d); | ||
| 1121 | cxusb_d680_dmb_drain_video(d); | ||
| 1122 | msleep(200); | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | /* Reset the tuner */ | ||
| 1126 | if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) { | ||
| 1127 | err("clear tuner gpio failed"); | ||
| 1128 | return -EIO; | ||
| 1129 | } | ||
| 1130 | msleep(100); | ||
| 1131 | if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) { | ||
| 1132 | err("set tuner gpio failed"); | ||
| 1133 | return -EIO; | ||
| 1134 | } | ||
| 1135 | msleep(100); | ||
| 1136 | |||
| 1137 | /* Attach frontend */ | ||
| 1138 | adap->fe = dvb_attach(lgs8gl5_attach, &lgs8gl5_cfg, &d->i2c_adap); | ||
| 1139 | if (adap->fe == NULL) | ||
| 1140 | return -EIO; | ||
| 1141 | |||
| 1142 | return 0; | ||
| 1143 | } | ||
| 1144 | |||
| 754 | /* | 1145 | /* |
| 755 | * DViCO has shipped two devices with the same USB ID, but only one of them | 1146 | * DViCO has shipped two devices with the same USB ID, but only one of them |
| 756 | * needs a firmware download. Check the device class details to see if they | 1147 | * needs a firmware download. Check the device class details to see if they |
| @@ -826,9 +1217,11 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties; | |||
| 826 | static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; | 1217 | static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; |
| 827 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; | 1218 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; |
| 828 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; | 1219 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; |
| 1220 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties; | ||
| 829 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; | 1221 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; |
| 830 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; | 1222 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; |
| 831 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; | 1223 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; |
| 1224 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties; | ||
| 832 | 1225 | ||
| 833 | static int cxusb_probe(struct usb_interface *intf, | 1226 | static int cxusb_probe(struct usb_interface *intf, |
| 834 | const struct usb_device_id *id) | 1227 | const struct usb_device_id *id) |
| @@ -852,6 +1245,11 @@ static int cxusb_probe(struct usb_interface *intf, | |||
| 852 | THIS_MODULE, NULL, adapter_nr) || | 1245 | THIS_MODULE, NULL, adapter_nr) || |
| 853 | 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, | 1246 | 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, |
| 854 | THIS_MODULE, NULL, adapter_nr) || | 1247 | THIS_MODULE, NULL, adapter_nr) || |
| 1248 | 0 == dvb_usb_device_init(intf, | ||
| 1249 | &cxusb_bluebird_dualdig4_rev2_properties, | ||
| 1250 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1251 | 0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties, | ||
| 1252 | THIS_MODULE, NULL, adapter_nr) || | ||
| 855 | 0) | 1253 | 0) |
| 856 | return 0; | 1254 | return 0; |
| 857 | 1255 | ||
| @@ -876,6 +1274,8 @@ static struct usb_device_id cxusb_table [] = { | |||
| 876 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) }, | 1274 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) }, |
| 877 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) }, | 1275 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) }, |
| 878 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) }, | 1276 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) }, |
| 1277 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) }, | ||
| 1278 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, | ||
| 879 | {} /* Terminating entry */ | 1279 | {} /* Terminating entry */ |
| 880 | }; | 1280 | }; |
| 881 | MODULE_DEVICE_TABLE (usb, cxusb_table); | 1281 | MODULE_DEVICE_TABLE (usb, cxusb_table); |
| @@ -1321,6 +1721,104 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = { | |||
| 1321 | } | 1721 | } |
| 1322 | }; | 1722 | }; |
| 1323 | 1723 | ||
| 1724 | static | ||
| 1725 | struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { | ||
| 1726 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1727 | |||
| 1728 | .usb_ctrl = CYPRESS_FX2, | ||
| 1729 | |||
| 1730 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1731 | |||
| 1732 | .num_adapters = 1, | ||
| 1733 | .adapter = { | ||
| 1734 | { | ||
| 1735 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 1736 | .frontend_attach = cxusb_dualdig4_rev2_frontend_attach, | ||
| 1737 | .tuner_attach = cxusb_dualdig4_rev2_tuner_attach, | ||
| 1738 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
| 1739 | /* parameter for the MPEG2-data transfer */ | ||
| 1740 | .stream = { | ||
| 1741 | .type = USB_BULK, | ||
| 1742 | .count = 7, | ||
| 1743 | .endpoint = 0x02, | ||
| 1744 | .u = { | ||
| 1745 | .bulk = { | ||
| 1746 | .buffersize = 4096, | ||
| 1747 | } | ||
| 1748 | } | ||
| 1749 | }, | ||
| 1750 | }, | ||
| 1751 | }, | ||
| 1752 | |||
| 1753 | .power_ctrl = cxusb_bluebird_power_ctrl, | ||
| 1754 | |||
| 1755 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1756 | |||
| 1757 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1758 | |||
| 1759 | .rc_interval = 100, | ||
| 1760 | .rc_key_map = dvico_mce_rc_keys, | ||
| 1761 | .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys), | ||
| 1762 | .rc_query = cxusb_rc_query, | ||
| 1763 | |||
| 1764 | .num_device_descs = 1, | ||
| 1765 | .devices = { | ||
| 1766 | { "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)", | ||
| 1767 | { NULL }, | ||
| 1768 | { &cxusb_table[17], NULL }, | ||
| 1769 | }, | ||
| 1770 | } | ||
| 1771 | }; | ||
| 1772 | |||
| 1773 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties = { | ||
| 1774 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1775 | |||
| 1776 | .usb_ctrl = CYPRESS_FX2, | ||
| 1777 | |||
| 1778 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1779 | |||
| 1780 | .num_adapters = 1, | ||
| 1781 | .adapter = { | ||
| 1782 | { | ||
| 1783 | .streaming_ctrl = cxusb_d680_dmb_streaming_ctrl, | ||
| 1784 | .frontend_attach = cxusb_d680_dmb_frontend_attach, | ||
| 1785 | .tuner_attach = cxusb_d680_dmb_tuner_attach, | ||
| 1786 | |||
| 1787 | /* parameter for the MPEG2-data transfer */ | ||
| 1788 | .stream = { | ||
| 1789 | .type = USB_BULK, | ||
| 1790 | .count = 5, | ||
| 1791 | .endpoint = 0x02, | ||
| 1792 | .u = { | ||
| 1793 | .bulk = { | ||
| 1794 | .buffersize = 8192, | ||
| 1795 | } | ||
| 1796 | } | ||
| 1797 | }, | ||
| 1798 | }, | ||
| 1799 | }, | ||
| 1800 | |||
| 1801 | .power_ctrl = cxusb_d680_dmb_power_ctrl, | ||
| 1802 | |||
| 1803 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1804 | |||
| 1805 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1806 | |||
| 1807 | .rc_interval = 100, | ||
| 1808 | .rc_key_map = d680_dmb_rc_keys, | ||
| 1809 | .rc_key_map_size = ARRAY_SIZE(d680_dmb_rc_keys), | ||
| 1810 | .rc_query = cxusb_d680_dmb_rc_query, | ||
| 1811 | |||
| 1812 | .num_device_descs = 1, | ||
| 1813 | .devices = { | ||
| 1814 | { | ||
| 1815 | "Conexant DMB-TH Stick", | ||
| 1816 | { NULL }, | ||
| 1817 | { &cxusb_table[18], NULL }, | ||
| 1818 | }, | ||
| 1819 | } | ||
| 1820 | }; | ||
| 1821 | |||
| 1324 | static struct usb_driver cxusb_driver = { | 1822 | static struct usb_driver cxusb_driver = { |
| 1325 | .name = "dvb_usb_cxusb", | 1823 | .name = "dvb_usb_cxusb", |
| 1326 | .probe = cxusb_probe, | 1824 | .probe = cxusb_probe, |
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 66d4dc6ba46f..739193943c17 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h | |||
| @@ -31,6 +31,8 @@ extern int dvb_usb_dib0700_debug; | |||
| 31 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) | 31 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) |
| 32 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) | 32 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) |
| 33 | #define REQUEST_SET_RC 0x11 | 33 | #define REQUEST_SET_RC 0x11 |
| 34 | #define REQUEST_NEW_I2C_READ 0x12 | ||
| 35 | #define REQUEST_NEW_I2C_WRITE 0x13 | ||
| 34 | #define REQUEST_GET_VERSION 0x15 | 36 | #define REQUEST_GET_VERSION 0x15 |
| 35 | 37 | ||
| 36 | struct dib0700_state { | 38 | struct dib0700_state { |
| @@ -39,6 +41,8 @@ struct dib0700_state { | |||
| 39 | u8 rc_toggle; | 41 | u8 rc_toggle; |
| 40 | u8 rc_counter; | 42 | u8 rc_counter; |
| 41 | u8 is_dib7000pc; | 43 | u8 is_dib7000pc; |
| 44 | u8 fw_use_new_i2c_api; | ||
| 45 | u8 disable_streaming_master_mode; | ||
| 42 | }; | 46 | }; |
| 43 | 47 | ||
| 44 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); | 48 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 595a04696c87..dd53cee3896d 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c | |||
| @@ -82,9 +82,98 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | /* | 84 | /* |
| 85 | * I2C master xfer function | 85 | * I2C master xfer function (supported in 1.20 firmware) |
| 86 | */ | 86 | */ |
| 87 | static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num) | 87 | static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, |
| 88 | int num) | ||
| 89 | { | ||
| 90 | /* The new i2c firmware messages are more reliable and in particular | ||
| 91 | properly support i2c read calls not preceded by a write */ | ||
| 92 | |||
| 93 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 94 | uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */ | ||
| 95 | uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */ | ||
| 96 | uint8_t en_start = 0; | ||
| 97 | uint8_t en_stop = 0; | ||
| 98 | uint8_t buf[255]; /* TBV: malloc ? */ | ||
| 99 | int result, i; | ||
| 100 | |||
| 101 | /* Ensure nobody else hits the i2c bus while we're sending our | ||
| 102 | sequence of messages, (such as the remote control thread) */ | ||
| 103 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 104 | return -EAGAIN; | ||
| 105 | |||
| 106 | for (i = 0; i < num; i++) { | ||
| 107 | if (i == 0) { | ||
| 108 | /* First message in the transaction */ | ||
| 109 | en_start = 1; | ||
| 110 | } else if (!(msg[i].flags & I2C_M_NOSTART)) { | ||
| 111 | /* Device supports repeated-start */ | ||
| 112 | en_start = 1; | ||
| 113 | } else { | ||
| 114 | /* Not the first packet and device doesn't support | ||
| 115 | repeated start */ | ||
| 116 | en_start = 0; | ||
| 117 | } | ||
| 118 | if (i == (num - 1)) { | ||
| 119 | /* Last message in the transaction */ | ||
| 120 | en_stop = 1; | ||
| 121 | } | ||
| 122 | |||
| 123 | if (msg[i].flags & I2C_M_RD) { | ||
| 124 | /* Read request */ | ||
| 125 | u16 index, value; | ||
| 126 | uint8_t i2c_dest; | ||
| 127 | |||
| 128 | i2c_dest = (msg[i].addr << 1); | ||
| 129 | value = ((en_start << 7) | (en_stop << 6) | | ||
| 130 | (msg[i].len & 0x3F)) << 8 | i2c_dest; | ||
| 131 | /* I2C ctrl + FE bus; */ | ||
| 132 | index = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30); | ||
| 133 | |||
| 134 | result = usb_control_msg(d->udev, | ||
| 135 | usb_rcvctrlpipe(d->udev, 0), | ||
| 136 | REQUEST_NEW_I2C_READ, | ||
| 137 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
| 138 | value, index, msg[i].buf, | ||
| 139 | msg[i].len, | ||
| 140 | USB_CTRL_GET_TIMEOUT); | ||
| 141 | if (result < 0) { | ||
| 142 | err("i2c read error (status = %d)\n", result); | ||
| 143 | break; | ||
| 144 | } | ||
| 145 | } else { | ||
| 146 | /* Write request */ | ||
| 147 | buf[0] = REQUEST_NEW_I2C_WRITE; | ||
| 148 | buf[1] = (msg[i].addr << 1); | ||
| 149 | buf[2] = (en_start << 7) | (en_stop << 6) | | ||
| 150 | (msg[i].len & 0x3F); | ||
| 151 | /* I2C ctrl + FE bus; */ | ||
| 152 | buf[3] = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30); | ||
| 153 | /* The Actual i2c payload */ | ||
| 154 | memcpy(&buf[4], msg[i].buf, msg[i].len); | ||
| 155 | |||
| 156 | result = usb_control_msg(d->udev, | ||
| 157 | usb_sndctrlpipe(d->udev, 0), | ||
| 158 | REQUEST_NEW_I2C_WRITE, | ||
| 159 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 160 | 0, 0, buf, msg[i].len + 4, | ||
| 161 | USB_CTRL_GET_TIMEOUT); | ||
| 162 | if (result < 0) { | ||
| 163 | err("i2c write error (status = %d)\n", result); | ||
| 164 | break; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | } | ||
| 168 | mutex_unlock(&d->i2c_mutex); | ||
| 169 | return i; | ||
| 170 | } | ||
| 171 | |||
| 172 | /* | ||
| 173 | * I2C master xfer function (pre-1.20 firmware) | ||
| 174 | */ | ||
| 175 | static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, | ||
| 176 | struct i2c_msg *msg, int num) | ||
| 88 | { | 177 | { |
| 89 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 178 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
| 90 | int i,len; | 179 | int i,len; |
| @@ -124,6 +213,21 @@ static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num | |||
| 124 | return i; | 213 | return i; |
| 125 | } | 214 | } |
| 126 | 215 | ||
| 216 | static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | ||
| 217 | int num) | ||
| 218 | { | ||
| 219 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 220 | struct dib0700_state *st = d->priv; | ||
| 221 | |||
| 222 | if (st->fw_use_new_i2c_api == 1) { | ||
| 223 | /* User running at least fw 1.20 */ | ||
| 224 | return dib0700_i2c_xfer_new(adap, msg, num); | ||
| 225 | } else { | ||
| 226 | /* Use legacy calls */ | ||
| 227 | return dib0700_i2c_xfer_legacy(adap, msg, num); | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 127 | static u32 dib0700_i2c_func(struct i2c_adapter *adapter) | 231 | static u32 dib0700_i2c_func(struct i2c_adapter *adapter) |
| 128 | { | 232 | { |
| 129 | return I2C_FUNC_I2C; | 233 | return I2C_FUNC_I2C; |
| @@ -246,7 +350,12 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
| 246 | 350 | ||
| 247 | b[0] = REQUEST_ENABLE_VIDEO; | 351 | b[0] = REQUEST_ENABLE_VIDEO; |
| 248 | b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ | 352 | b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ |
| 249 | b[2] = (0x01 << 4); /* Master mode */ | 353 | |
| 354 | if (st->disable_streaming_master_mode == 1) | ||
| 355 | b[2] = 0x00; | ||
| 356 | else | ||
| 357 | b[2] = (0x01 << 4); /* Master mode */ | ||
| 358 | |||
| 250 | b[3] = 0x00; | 359 | b[3] = 0x00; |
| 251 | 360 | ||
| 252 | deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); | 361 | deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 6c0e5c5f4362..0cfccc24b190 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #include "mt2060.h" | 14 | #include "mt2060.h" |
| 15 | #include "mt2266.h" | 15 | #include "mt2266.h" |
| 16 | #include "tuner-xc2028.h" | 16 | #include "tuner-xc2028.h" |
| 17 | #include "xc5000.h" | ||
| 18 | #include "s5h1411.h" | ||
| 17 | #include "dib0070.h" | 19 | #include "dib0070.h" |
| 18 | 20 | ||
| 19 | static int force_lna_activation; | 21 | static int force_lna_activation; |
| @@ -366,7 +368,8 @@ static struct dib7000p_config stk7700ph_dib7700_xc3028_config = { | |||
| 366 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | 368 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, |
| 367 | }; | 369 | }; |
| 368 | 370 | ||
| 369 | static int stk7700ph_xc3028_callback(void *ptr, int command, int arg) | 371 | static int stk7700ph_xc3028_callback(void *ptr, int component, |
| 372 | int command, int arg) | ||
| 370 | { | 373 | { |
| 371 | struct dvb_usb_adapter *adap = ptr; | 374 | struct dvb_usb_adapter *adap = ptr; |
| 372 | 375 | ||
| @@ -394,7 +397,6 @@ static struct xc2028_ctrl stk7700ph_xc3028_ctrl = { | |||
| 394 | 397 | ||
| 395 | static struct xc2028_config stk7700ph_xc3028_config = { | 398 | static struct xc2028_config stk7700ph_xc3028_config = { |
| 396 | .i2c_addr = 0x61, | 399 | .i2c_addr = 0x61, |
| 397 | .callback = stk7700ph_xc3028_callback, | ||
| 398 | .ctrl = &stk7700ph_xc3028_ctrl, | 400 | .ctrl = &stk7700ph_xc3028_ctrl, |
| 399 | }; | 401 | }; |
| 400 | 402 | ||
| @@ -435,7 +437,9 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 435 | DIBX000_I2C_INTERFACE_TUNER, 1); | 437 | DIBX000_I2C_INTERFACE_TUNER, 1); |
| 436 | 438 | ||
| 437 | stk7700ph_xc3028_config.i2c_adap = tun_i2c; | 439 | stk7700ph_xc3028_config.i2c_adap = tun_i2c; |
| 438 | stk7700ph_xc3028_config.video_dev = adap; | 440 | |
| 441 | /* FIXME: generalize & move to common area */ | ||
| 442 | adap->fe->callback = stk7700ph_xc3028_callback; | ||
| 439 | 443 | ||
| 440 | return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config) | 444 | return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config) |
| 441 | == NULL ? -ENODEV : 0; | 445 | == NULL ? -ENODEV : 0; |
| @@ -677,6 +681,43 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = { | |||
| 677 | { 0x01, 0x7d, KEY_VOLUMEDOWN }, | 681 | { 0x01, 0x7d, KEY_VOLUMEDOWN }, |
| 678 | { 0x02, 0x42, KEY_CHANNELUP }, | 682 | { 0x02, 0x42, KEY_CHANNELUP }, |
| 679 | { 0x00, 0x7d, KEY_CHANNELDOWN }, | 683 | { 0x00, 0x7d, KEY_CHANNELDOWN }, |
| 684 | |||
| 685 | /* Key codes for Nova-TD "credit card" remote control. */ | ||
| 686 | { 0x1d, 0x00, KEY_0 }, | ||
| 687 | { 0x1d, 0x01, KEY_1 }, | ||
| 688 | { 0x1d, 0x02, KEY_2 }, | ||
| 689 | { 0x1d, 0x03, KEY_3 }, | ||
| 690 | { 0x1d, 0x04, KEY_4 }, | ||
| 691 | { 0x1d, 0x05, KEY_5 }, | ||
| 692 | { 0x1d, 0x06, KEY_6 }, | ||
| 693 | { 0x1d, 0x07, KEY_7 }, | ||
| 694 | { 0x1d, 0x08, KEY_8 }, | ||
| 695 | { 0x1d, 0x09, KEY_9 }, | ||
| 696 | { 0x1d, 0x0a, KEY_TEXT }, | ||
| 697 | { 0x1d, 0x0d, KEY_MENU }, | ||
| 698 | { 0x1d, 0x0f, KEY_MUTE }, | ||
| 699 | { 0x1d, 0x10, KEY_VOLUMEUP }, | ||
| 700 | { 0x1d, 0x11, KEY_VOLUMEDOWN }, | ||
| 701 | { 0x1d, 0x12, KEY_CHANNEL }, | ||
| 702 | { 0x1d, 0x14, KEY_UP }, | ||
| 703 | { 0x1d, 0x15, KEY_DOWN }, | ||
| 704 | { 0x1d, 0x16, KEY_LEFT }, | ||
| 705 | { 0x1d, 0x17, KEY_RIGHT }, | ||
| 706 | { 0x1d, 0x1c, KEY_TV }, | ||
| 707 | { 0x1d, 0x1e, KEY_NEXT }, | ||
| 708 | { 0x1d, 0x1f, KEY_BACK }, | ||
| 709 | { 0x1d, 0x20, KEY_CHANNELUP }, | ||
| 710 | { 0x1d, 0x21, KEY_CHANNELDOWN }, | ||
| 711 | { 0x1d, 0x24, KEY_LAST }, | ||
| 712 | { 0x1d, 0x25, KEY_OK }, | ||
| 713 | { 0x1d, 0x30, KEY_PAUSE }, | ||
| 714 | { 0x1d, 0x32, KEY_REWIND }, | ||
| 715 | { 0x1d, 0x34, KEY_FASTFORWARD }, | ||
| 716 | { 0x1d, 0x35, KEY_PLAY }, | ||
| 717 | { 0x1d, 0x36, KEY_STOP }, | ||
| 718 | { 0x1d, 0x37, KEY_RECORD }, | ||
| 719 | { 0x1d, 0x3b, KEY_GOTO }, | ||
| 720 | { 0x1d, 0x3d, KEY_POWER }, | ||
| 680 | }; | 721 | }; |
| 681 | 722 | ||
| 682 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ | 723 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ |
| @@ -1078,6 +1119,97 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap) | |||
| 1078 | return adap->fe == NULL ? -ENODEV : 0; | 1119 | return adap->fe == NULL ? -ENODEV : 0; |
| 1079 | } | 1120 | } |
| 1080 | 1121 | ||
| 1122 | /* S5H1411 */ | ||
| 1123 | static struct s5h1411_config pinnacle_801e_config = { | ||
| 1124 | .output_mode = S5H1411_PARALLEL_OUTPUT, | ||
| 1125 | .gpio = S5H1411_GPIO_OFF, | ||
| 1126 | .mpeg_timing = S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, | ||
| 1127 | .qam_if = S5H1411_IF_44000, | ||
| 1128 | .vsb_if = S5H1411_IF_44000, | ||
| 1129 | .inversion = S5H1411_INVERSION_OFF, | ||
| 1130 | .status_mode = S5H1411_DEMODLOCKING | ||
| 1131 | }; | ||
| 1132 | |||
| 1133 | /* Pinnacle PCTV HD Pro 801e GPIOs map: | ||
| 1134 | GPIO0 - currently unknown | ||
| 1135 | GPIO1 - xc5000 tuner reset | ||
| 1136 | GPIO2 - CX25843 sleep | ||
| 1137 | GPIO3 - currently unknown | ||
| 1138 | GPIO4 - currently unknown | ||
| 1139 | GPIO6 - currently unknown | ||
| 1140 | GPIO7 - currently unknown | ||
| 1141 | GPIO9 - currently unknown | ||
| 1142 | GPIO10 - CX25843 reset | ||
| 1143 | */ | ||
| 1144 | static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1145 | { | ||
| 1146 | struct dib0700_state *st = adap->dev->priv; | ||
| 1147 | |||
| 1148 | /* Make use of the new i2c functions from FW 1.20 */ | ||
| 1149 | st->fw_use_new_i2c_api = 1; | ||
| 1150 | |||
| 1151 | /* The s5h1411 requires the dib0700 to not be in master mode */ | ||
| 1152 | st->disable_streaming_master_mode = 1; | ||
| 1153 | |||
| 1154 | /* All msleep values taken from Windows USB trace */ | ||
| 1155 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0); | ||
| 1156 | dib0700_set_gpio(adap->dev, GPIO3, GPIO_OUT, 0); | ||
| 1157 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 1158 | msleep(400); | ||
| 1159 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 1160 | msleep(60); | ||
| 1161 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 1162 | msleep(30); | ||
| 1163 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 1164 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 1165 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 1166 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 1167 | dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 0); | ||
| 1168 | msleep(30); | ||
| 1169 | |||
| 1170 | /* Put the CX25843 to sleep for now since we're in digital mode */ | ||
| 1171 | dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1); | ||
| 1172 | |||
| 1173 | /* GPIOs are initialized, do the attach */ | ||
| 1174 | adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config, | ||
| 1175 | &adap->dev->i2c_adap); | ||
| 1176 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | static int dib0700_xc5000_tuner_callback(void *priv, int component, | ||
| 1180 | int command, int arg) | ||
| 1181 | { | ||
| 1182 | struct dvb_usb_adapter *adap = priv; | ||
| 1183 | |||
| 1184 | if (command == XC5000_TUNER_RESET) { | ||
| 1185 | /* Reset the tuner */ | ||
| 1186 | dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0); | ||
| 1187 | msleep(330); /* from Windows USB trace */ | ||
| 1188 | dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1); | ||
| 1189 | msleep(330); /* from Windows USB trace */ | ||
| 1190 | } else { | ||
| 1191 | err("xc5000: unknown tuner callback command: %d\n", command); | ||
| 1192 | return -EINVAL; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | return 0; | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | static struct xc5000_config s5h1411_xc5000_tunerconfig = { | ||
| 1199 | .i2c_address = 0x64, | ||
| 1200 | .if_khz = 5380, | ||
| 1201 | }; | ||
| 1202 | |||
| 1203 | static int xc5000_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1204 | { | ||
| 1205 | /* FIXME: generalize & move to common area */ | ||
| 1206 | adap->fe->callback = dib0700_xc5000_tuner_callback; | ||
| 1207 | |||
| 1208 | return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 1209 | &s5h1411_xc5000_tunerconfig) | ||
| 1210 | == NULL ? -ENODEV : 0; | ||
| 1211 | } | ||
| 1212 | |||
| 1081 | /* DVB-USB and USB stuff follows */ | 1213 | /* DVB-USB and USB stuff follows */ |
| 1082 | struct usb_device_id dib0700_usb_id_table[] = { | 1214 | struct usb_device_id dib0700_usb_id_table[] = { |
| 1083 | /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, | 1215 | /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, |
| @@ -1119,6 +1251,11 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
| 1119 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, | 1251 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, |
| 1120 | /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, | 1252 | /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, |
| 1121 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) }, | 1253 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) }, |
| 1254 | { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U8000) }, | ||
| 1255 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700PH) }, | ||
| 1256 | { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, | ||
| 1257 | /* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) }, | ||
| 1258 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) }, | ||
| 1122 | { 0 } /* Terminating entry */ | 1259 | { 0 } /* Terminating entry */ |
| 1123 | }; | 1260 | }; |
| 1124 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 1261 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
| @@ -1126,7 +1263,7 @@ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | |||
| 1126 | #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ | 1263 | #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ |
| 1127 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ | 1264 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ |
| 1128 | .usb_ctrl = DEVICE_SPECIFIC, \ | 1265 | .usb_ctrl = DEVICE_SPECIFIC, \ |
| 1129 | .firmware = "dvb-usb-dib0700-1.10.fw", \ | 1266 | .firmware = "dvb-usb-dib0700-1.20.fw", \ |
| 1130 | .download_firmware = dib0700_download_firmware, \ | 1267 | .download_firmware = dib0700_download_firmware, \ |
| 1131 | .no_reconnect = 1, \ | 1268 | .no_reconnect = 1, \ |
| 1132 | .size_of_priv = sizeof(struct dib0700_state), \ | 1269 | .size_of_priv = sizeof(struct dib0700_state), \ |
| @@ -1293,7 +1430,12 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
| 1293 | { &dib0700_usb_id_table[31], NULL }, | 1430 | { &dib0700_usb_id_table[31], NULL }, |
| 1294 | { NULL }, | 1431 | { NULL }, |
| 1295 | } | 1432 | } |
| 1296 | } | 1433 | }, |
| 1434 | |||
| 1435 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 1436 | .rc_key_map = dib0700_rc_keys, | ||
| 1437 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
| 1438 | .rc_query = dib0700_rc_query | ||
| 1297 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 1439 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
| 1298 | 1440 | ||
| 1299 | .num_adapters = 1, | 1441 | .num_adapters = 1, |
| @@ -1408,7 +1550,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
| 1408 | }, | 1550 | }, |
| 1409 | }, | 1551 | }, |
| 1410 | 1552 | ||
| 1411 | .num_device_descs = 3, | 1553 | .num_device_descs = 5, |
| 1412 | .devices = { | 1554 | .devices = { |
| 1413 | { "Terratec Cinergy HT USB XE", | 1555 | { "Terratec Cinergy HT USB XE", |
| 1414 | { &dib0700_usb_id_table[27], NULL }, | 1556 | { &dib0700_usb_id_table[27], NULL }, |
| @@ -1422,6 +1564,47 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
| 1422 | { &dib0700_usb_id_table[32], NULL }, | 1564 | { &dib0700_usb_id_table[32], NULL }, |
| 1423 | { NULL }, | 1565 | { NULL }, |
| 1424 | }, | 1566 | }, |
| 1567 | { "Gigabyte U8000-RH", | ||
| 1568 | { &dib0700_usb_id_table[37], NULL }, | ||
| 1569 | { NULL }, | ||
| 1570 | }, | ||
| 1571 | { "YUAN High-Tech STK7700PH", | ||
| 1572 | { &dib0700_usb_id_table[38], NULL }, | ||
| 1573 | { NULL }, | ||
| 1574 | }, | ||
| 1575 | { "Asus My Cinema-U3000Hybrid", | ||
| 1576 | { &dib0700_usb_id_table[39], NULL }, | ||
| 1577 | { NULL }, | ||
| 1578 | }, | ||
| 1579 | }, | ||
| 1580 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 1581 | .rc_key_map = dib0700_rc_keys, | ||
| 1582 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
| 1583 | .rc_query = dib0700_rc_query | ||
| 1584 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 1585 | .num_adapters = 1, | ||
| 1586 | .adapter = { | ||
| 1587 | { | ||
| 1588 | .frontend_attach = s5h1411_frontend_attach, | ||
| 1589 | .tuner_attach = xc5000_tuner_attach, | ||
| 1590 | |||
| 1591 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 1592 | |||
| 1593 | .size_of_priv = sizeof(struct | ||
| 1594 | dib0700_adapter_state), | ||
| 1595 | }, | ||
| 1596 | }, | ||
| 1597 | |||
| 1598 | .num_device_descs = 2, | ||
| 1599 | .devices = { | ||
| 1600 | { "Pinnacle PCTV HD Pro USB Stick", | ||
| 1601 | { &dib0700_usb_id_table[40], NULL }, | ||
| 1602 | { NULL }, | ||
| 1603 | }, | ||
| 1604 | { "Pinnacle PCTV HD USB Stick", | ||
| 1605 | { &dib0700_usb_id_table[41], NULL }, | ||
| 1606 | { NULL }, | ||
| 1607 | }, | ||
| 1425 | }, | 1608 | }, |
| 1426 | .rc_interval = DEFAULT_RC_INTERVAL, | 1609 | .rc_interval = DEFAULT_RC_INTERVAL, |
| 1427 | .rc_key_map = dib0700_rc_keys, | 1610 | .rc_key_map = dib0700_rc_keys, |
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c new file mode 100644 index 000000000000..078ce92ca436 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtv5100.c | |||
| @@ -0,0 +1,240 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Antoine Jacquet <royale@zerezo.com> | ||
| 5 | * http://royale.zerezo.com/dtv5100/ | ||
| 6 | * | ||
| 7 | * Inspired by gl861.c and au6610.c drivers | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include "dtv5100.h" | ||
| 25 | #include "zl10353.h" | ||
| 26 | #include "qt1010.h" | ||
| 27 | |||
| 28 | /* debug */ | ||
| 29 | static int dvb_usb_dtv5100_debug; | ||
| 30 | module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644); | ||
| 31 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
| 32 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 33 | |||
| 34 | static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
| 35 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
| 36 | { | ||
| 37 | u8 request; | ||
| 38 | u8 type; | ||
| 39 | u16 value; | ||
| 40 | u16 index; | ||
| 41 | |||
| 42 | switch (wlen) { | ||
| 43 | case 1: | ||
| 44 | /* write { reg }, read { value } */ | ||
| 45 | request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ : | ||
| 46 | DTV5100_TUNER_READ); | ||
| 47 | type = USB_TYPE_VENDOR | USB_DIR_IN; | ||
| 48 | value = 0; | ||
| 49 | break; | ||
| 50 | case 2: | ||
| 51 | /* write { reg, value } */ | ||
| 52 | request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE : | ||
| 53 | DTV5100_TUNER_WRITE); | ||
| 54 | type = USB_TYPE_VENDOR | USB_DIR_OUT; | ||
| 55 | value = wbuf[1]; | ||
| 56 | break; | ||
| 57 | default: | ||
| 58 | warn("wlen = %x, aborting.", wlen); | ||
| 59 | return -EINVAL; | ||
| 60 | } | ||
| 61 | index = (addr << 8) + wbuf[0]; | ||
| 62 | |||
| 63 | msleep(1); /* avoid I2C errors */ | ||
| 64 | return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request, | ||
| 65 | type, value, index, rbuf, rlen, | ||
| 66 | DTV5100_USB_TIMEOUT); | ||
| 67 | } | ||
| 68 | |||
| 69 | /* I2C */ | ||
| 70 | static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 71 | int num) | ||
| 72 | { | ||
| 73 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 74 | int i; | ||
| 75 | |||
| 76 | if (num > 2) | ||
| 77 | return -EINVAL; | ||
| 78 | |||
| 79 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 80 | return -EAGAIN; | ||
| 81 | |||
| 82 | for (i = 0; i < num; i++) { | ||
| 83 | /* write/read request */ | ||
| 84 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
| 85 | if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
| 86 | msg[i].len, msg[i+1].buf, | ||
| 87 | msg[i+1].len) < 0) | ||
| 88 | break; | ||
| 89 | i++; | ||
| 90 | } else if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
| 91 | msg[i].len, NULL, 0) < 0) | ||
| 92 | break; | ||
| 93 | } | ||
| 94 | |||
| 95 | mutex_unlock(&d->i2c_mutex); | ||
| 96 | return i; | ||
| 97 | } | ||
| 98 | |||
| 99 | static u32 dtv5100_i2c_func(struct i2c_adapter *adapter) | ||
| 100 | { | ||
| 101 | return I2C_FUNC_I2C; | ||
| 102 | } | ||
| 103 | |||
| 104 | static struct i2c_algorithm dtv5100_i2c_algo = { | ||
| 105 | .master_xfer = dtv5100_i2c_xfer, | ||
| 106 | .functionality = dtv5100_i2c_func, | ||
| 107 | }; | ||
| 108 | |||
| 109 | /* Callbacks for DVB USB */ | ||
| 110 | static struct zl10353_config dtv5100_zl10353_config = { | ||
| 111 | .demod_address = DTV5100_DEMOD_ADDR, | ||
| 112 | .no_tuner = 1, | ||
| 113 | .parallel_ts = 1, | ||
| 114 | }; | ||
| 115 | |||
| 116 | static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 117 | { | ||
| 118 | adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config, | ||
| 119 | &adap->dev->i2c_adap); | ||
| 120 | if (adap->fe == NULL) | ||
| 121 | return -EIO; | ||
| 122 | |||
| 123 | /* disable i2c gate, or it won't work... is this safe? */ | ||
| 124 | adap->fe->ops.i2c_gate_ctrl = NULL; | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static struct qt1010_config dtv5100_qt1010_config = { | ||
| 130 | .i2c_address = DTV5100_TUNER_ADDR | ||
| 131 | }; | ||
| 132 | |||
| 133 | static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 134 | { | ||
| 135 | return dvb_attach(qt1010_attach, | ||
| 136 | adap->fe, &adap->dev->i2c_adap, | ||
| 137 | &dtv5100_qt1010_config) == NULL ? -ENODEV : 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | /* DVB USB Driver stuff */ | ||
| 141 | static struct dvb_usb_device_properties dtv5100_properties; | ||
| 142 | |||
| 143 | static int dtv5100_probe(struct usb_interface *intf, | ||
| 144 | const struct usb_device_id *id) | ||
| 145 | { | ||
| 146 | int i, ret; | ||
| 147 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 148 | |||
| 149 | /* initialize non qt1010/zl10353 part? */ | ||
| 150 | for (i = 0; dtv5100_init[i].request; i++) { | ||
| 151 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 152 | dtv5100_init[i].request, | ||
| 153 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 154 | dtv5100_init[i].value, | ||
| 155 | dtv5100_init[i].index, NULL, 0, | ||
| 156 | DTV5100_USB_TIMEOUT); | ||
| 157 | if (ret) | ||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | ret = dvb_usb_device_init(intf, &dtv5100_properties, | ||
| 162 | THIS_MODULE, NULL, adapter_nr); | ||
| 163 | if (ret) | ||
| 164 | return ret; | ||
| 165 | |||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | static struct usb_device_id dtv5100_table[] = { | ||
| 170 | { USB_DEVICE(0x06be, 0xa232) }, | ||
| 171 | { } /* Terminating entry */ | ||
| 172 | }; | ||
| 173 | MODULE_DEVICE_TABLE(usb, dtv5100_table); | ||
| 174 | |||
| 175 | static struct dvb_usb_device_properties dtv5100_properties = { | ||
| 176 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 177 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 178 | |||
| 179 | .size_of_priv = 0, | ||
| 180 | |||
| 181 | .num_adapters = 1, | ||
| 182 | .adapter = {{ | ||
| 183 | .frontend_attach = dtv5100_frontend_attach, | ||
| 184 | .tuner_attach = dtv5100_tuner_attach, | ||
| 185 | |||
| 186 | .stream = { | ||
| 187 | .type = USB_BULK, | ||
| 188 | .count = 8, | ||
| 189 | .endpoint = 0x82, | ||
| 190 | .u = { | ||
| 191 | .bulk = { | ||
| 192 | .buffersize = 4096, | ||
| 193 | } | ||
| 194 | } | ||
| 195 | }, | ||
| 196 | } }, | ||
| 197 | |||
| 198 | .i2c_algo = &dtv5100_i2c_algo, | ||
| 199 | |||
| 200 | .num_device_descs = 1, | ||
| 201 | .devices = { | ||
| 202 | { | ||
| 203 | .name = "AME DTV-5100 USB2.0 DVB-T", | ||
| 204 | .cold_ids = { NULL }, | ||
| 205 | .warm_ids = { &dtv5100_table[0], NULL }, | ||
| 206 | }, | ||
| 207 | } | ||
| 208 | }; | ||
| 209 | |||
| 210 | static struct usb_driver dtv5100_driver = { | ||
| 211 | .name = "dvb_usb_dtv5100", | ||
| 212 | .probe = dtv5100_probe, | ||
| 213 | .disconnect = dvb_usb_device_exit, | ||
| 214 | .id_table = dtv5100_table, | ||
| 215 | }; | ||
| 216 | |||
| 217 | /* module stuff */ | ||
| 218 | static int __init dtv5100_module_init(void) | ||
| 219 | { | ||
| 220 | int ret; | ||
| 221 | |||
| 222 | ret = usb_register(&dtv5100_driver); | ||
| 223 | if (ret) | ||
| 224 | err("usb_register failed. Error number %d", ret); | ||
| 225 | |||
| 226 | return ret; | ||
| 227 | } | ||
| 228 | |||
| 229 | static void __exit dtv5100_module_exit(void) | ||
| 230 | { | ||
| 231 | /* deregister this driver from the USB subsystem */ | ||
| 232 | usb_deregister(&dtv5100_driver); | ||
| 233 | } | ||
| 234 | |||
| 235 | module_init(dtv5100_module_init); | ||
| 236 | module_exit(dtv5100_module_exit); | ||
| 237 | |||
| 238 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 239 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 240 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.h b/drivers/media/dvb/dvb-usb/dtv5100.h new file mode 100644 index 000000000000..93e96e04a82a --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtv5100.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Antoine Jacquet <royale@zerezo.com> | ||
| 5 | * http://royale.zerezo.com/dtv5100/ | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef _DVB_USB_DTV5100_H_ | ||
| 23 | #define _DVB_USB_DTV5100_H_ | ||
| 24 | |||
| 25 | #define DVB_USB_LOG_PREFIX "dtv5100" | ||
| 26 | #include "dvb-usb.h" | ||
| 27 | |||
| 28 | #define DTV5100_USB_TIMEOUT 500 | ||
| 29 | |||
| 30 | #define DTV5100_DEMOD_ADDR 0x00 | ||
| 31 | #define DTV5100_DEMOD_WRITE 0xc0 | ||
| 32 | #define DTV5100_DEMOD_READ 0xc1 | ||
| 33 | |||
| 34 | #define DTV5100_TUNER_ADDR 0xc4 | ||
| 35 | #define DTV5100_TUNER_WRITE 0xc7 | ||
| 36 | #define DTV5100_TUNER_READ 0xc8 | ||
| 37 | |||
| 38 | #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" | ||
| 39 | #define DRIVER_DESC "AME DTV-5100 USB2.0 DVB-T" | ||
| 40 | |||
| 41 | static struct { | ||
| 42 | u8 request; | ||
| 43 | u8 value; | ||
| 44 | u16 index; | ||
| 45 | } dtv5100_init[] = { | ||
| 46 | { 0x000000c5, 0x00000000, 0x00000001 }, | ||
| 47 | { 0x000000c5, 0x00000001, 0x00000001 }, | ||
| 48 | { } /* Terminating entry */ | ||
| 49 | }; | ||
| 50 | |||
| 51 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 03dfb9f2fe30..7380b94b3b36 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #define USB_VID_AVERMEDIA 0x07ca | 22 | #define USB_VID_AVERMEDIA 0x07ca |
| 23 | #define USB_VID_COMPRO 0x185b | 23 | #define USB_VID_COMPRO 0x185b |
| 24 | #define USB_VID_COMPRO_UNK 0x145f | 24 | #define USB_VID_COMPRO_UNK 0x145f |
| 25 | #define USB_VID_CONEXANT 0x0572 | ||
| 25 | #define USB_VID_CYPRESS 0x04b4 | 26 | #define USB_VID_CYPRESS 0x04b4 |
| 26 | #define USB_VID_DIBCOM 0x10b8 | 27 | #define USB_VID_DIBCOM 0x10b8 |
| 27 | #define USB_VID_DPOSH 0x1498 | 28 | #define USB_VID_DPOSH 0x1498 |
| @@ -33,16 +34,19 @@ | |||
| 33 | #define USB_VID_HAUPPAUGE 0x2040 | 34 | #define USB_VID_HAUPPAUGE 0x2040 |
| 34 | #define USB_VID_HYPER_PALTEK 0x1025 | 35 | #define USB_VID_HYPER_PALTEK 0x1025 |
| 35 | #define USB_VID_KWORLD 0xeb2a | 36 | #define USB_VID_KWORLD 0xeb2a |
| 37 | #define USB_VID_KWORLD_2 0x1b80 | ||
| 36 | #define USB_VID_KYE 0x0458 | 38 | #define USB_VID_KYE 0x0458 |
| 37 | #define USB_VID_LEADTEK 0x0413 | 39 | #define USB_VID_LEADTEK 0x0413 |
| 38 | #define USB_VID_LITEON 0x04ca | 40 | #define USB_VID_LITEON 0x04ca |
| 39 | #define USB_VID_MEDION 0x1660 | 41 | #define USB_VID_MEDION 0x1660 |
| 40 | #define USB_VID_MIGLIA 0x18f3 | 42 | #define USB_VID_MIGLIA 0x18f3 |
| 41 | #define USB_VID_MSI 0x0db0 | 43 | #define USB_VID_MSI 0x0db0 |
| 44 | #define USB_VID_MSI_2 0x1462 | ||
| 42 | #define USB_VID_OPERA1 0x695c | 45 | #define USB_VID_OPERA1 0x695c |
| 43 | #define USB_VID_PINNACLE 0x2304 | 46 | #define USB_VID_PINNACLE 0x2304 |
| 44 | #define USB_VID_TECHNOTREND 0x0b48 | 47 | #define USB_VID_TECHNOTREND 0x0b48 |
| 45 | #define USB_VID_TERRATEC 0x0ccd | 48 | #define USB_VID_TERRATEC 0x0ccd |
| 49 | #define USB_VID_TELESTAR 0x10b9 | ||
| 46 | #define USB_VID_VISIONPLUS 0x13d3 | 50 | #define USB_VID_VISIONPLUS 0x13d3 |
| 47 | #define USB_VID_TWINHAN 0x1822 | 51 | #define USB_VID_TWINHAN 0x1822 |
| 48 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 | 52 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 |
| @@ -50,15 +54,18 @@ | |||
| 50 | #define USB_VID_WIDEVIEW 0x14aa | 54 | #define USB_VID_WIDEVIEW 0x14aa |
| 51 | #define USB_VID_GIGABYTE 0x1044 | 55 | #define USB_VID_GIGABYTE 0x1044 |
| 52 | #define USB_VID_YUAN 0x1164 | 56 | #define USB_VID_YUAN 0x1164 |
| 53 | 57 | #define USB_VID_XTENSIONS 0x1ae7 | |
| 54 | 58 | ||
| 55 | /* Product IDs */ | 59 | /* Product IDs */ |
| 56 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 | 60 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 |
| 57 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 | 61 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 |
| 58 | #define USB_PID_AFATECH_AF9005 0x9020 | 62 | #define USB_PID_AFATECH_AF9005 0x9020 |
| 63 | #define USB_PID_AFATECH_AF9015_9015 0x9015 | ||
| 64 | #define USB_PID_AFATECH_AF9015_9016 0x9016 | ||
| 59 | #define USB_VID_ALINK_DTU 0xf170 | 65 | #define USB_VID_ALINK_DTU 0xf170 |
| 60 | #define USB_PID_ANSONIC_DVBT_USB 0x6000 | 66 | #define USB_PID_ANSONIC_DVBT_USB 0x6000 |
| 61 | #define USB_PID_ANYSEE 0x861f | 67 | #define USB_PID_ANYSEE 0x861f |
| 68 | #define USB_PID_AZUREWAVE_AD_TU700 0x3237 | ||
| 62 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 | 69 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 |
| 63 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 | 70 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 |
| 64 | #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 | 71 | #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 |
| @@ -69,6 +76,7 @@ | |||
| 69 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | 76 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d |
| 70 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 | 77 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 |
| 71 | #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 | 78 | #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 |
| 79 | #define USB_PID_CONEXANT_D680_DMB 0x86d6 | ||
| 72 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 | 80 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 |
| 73 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 | 81 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 |
| 74 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | 82 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 |
| @@ -87,9 +95,12 @@ | |||
| 87 | #define USB_PID_UNIWILL_STK7700P 0x6003 | 95 | #define USB_PID_UNIWILL_STK7700P 0x6003 |
| 88 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | 96 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 |
| 89 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 | 97 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 |
| 98 | #define USB_PID_KWORLD_399U 0xe399 | ||
| 99 | #define USB_PID_KWORLD_PC160_2T 0xc160 | ||
| 90 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | 100 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de |
| 91 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df | 101 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df |
| 92 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 | 102 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 |
| 103 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069 | ||
| 93 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 | 104 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 |
| 94 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 | 105 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 |
| 95 | #define USB_PID_TWINHAN_VP7020_COLD 0x3203 | 106 | #define USB_PID_TWINHAN_VP7020_COLD 0x3203 |
| @@ -98,6 +109,7 @@ | |||
| 98 | #define USB_PID_TWINHAN_VP7045_WARM 0x3206 | 109 | #define USB_PID_TWINHAN_VP7045_WARM 0x3206 |
| 99 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 | 110 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 |
| 100 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 | 111 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 |
| 112 | #define USB_PID_TINYTWIN 0x3226 | ||
| 101 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 | 113 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 |
| 102 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 | 114 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 |
| 103 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 | 115 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 |
| @@ -144,6 +156,9 @@ | |||
| 144 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039 | 156 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039 |
| 145 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039 | 157 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039 |
| 146 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039 | 158 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039 |
| 159 | #define USB_PID_AVERMEDIA_VOLAR_X 0xa815 | ||
| 160 | #define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150 | ||
| 161 | #define USB_PID_AVERMEDIA_A309 0xa309 | ||
| 147 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 | 162 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 |
| 148 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a | 163 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a |
| 149 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 | 164 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 |
| @@ -153,8 +168,11 @@ | |||
| 153 | #define USB_PID_PINNACLE_PCTV2000E 0x022c | 168 | #define USB_PID_PINNACLE_PCTV2000E 0x022c |
| 154 | #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 | 169 | #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 |
| 155 | #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229 | 170 | #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229 |
| 171 | #define USB_PID_PINNACLE_PCTV71E 0x022b | ||
| 156 | #define USB_PID_PINNACLE_PCTV72E 0x0236 | 172 | #define USB_PID_PINNACLE_PCTV72E 0x0236 |
| 157 | #define USB_PID_PINNACLE_PCTV73E 0x0237 | 173 | #define USB_PID_PINNACLE_PCTV73E 0x0237 |
| 174 | #define USB_PID_PINNACLE_PCTV801E 0x023a | ||
| 175 | #define USB_PID_PINNACLE_PCTV801E_SE 0x023b | ||
| 158 | #define USB_PID_PCTV_200E 0x020e | 176 | #define USB_PID_PCTV_200E 0x020e |
| 159 | #define USB_PID_PCTV_400E 0x020f | 177 | #define USB_PID_PCTV_400E 0x020f |
| 160 | #define USB_PID_PCTV_450E 0x0222 | 178 | #define USB_PID_PCTV_450E 0x0222 |
| @@ -171,6 +189,7 @@ | |||
| 171 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 | 189 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 |
| 172 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 | 190 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 |
| 173 | #define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78 | 191 | #define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78 |
| 192 | #define USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2 0xdb98 | ||
| 174 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70 | 193 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70 |
| 175 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71 | 194 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71 |
| 176 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 | 195 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 |
| @@ -190,6 +209,7 @@ | |||
| 190 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 | 209 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 |
| 191 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 | 210 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 |
| 192 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 | 211 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 |
| 212 | #define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029 | ||
| 193 | #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 | 213 | #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 |
| 194 | #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 | 214 | #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 |
| 195 | #define USB_PID_GENPIX_8PSK_REV_2 0x0202 | 215 | #define USB_PID_GENPIX_8PSK_REV_2 0x0202 |
| @@ -197,14 +217,21 @@ | |||
| 197 | #define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204 | 217 | #define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204 |
| 198 | #define USB_PID_SIGMATEK_DVB_110 0x6610 | 218 | #define USB_PID_SIGMATEK_DVB_110 0x6610 |
| 199 | #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 | 219 | #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 |
| 220 | #define USB_PID_MSI_DIGIVOX_DUO 0x8801 | ||
| 200 | #define USB_PID_OPERA1_COLD 0x2830 | 221 | #define USB_PID_OPERA1_COLD 0x2830 |
| 201 | #define USB_PID_OPERA1_WARM 0x3829 | 222 | #define USB_PID_OPERA1_WARM 0x3829 |
| 202 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 | 223 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 |
| 203 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 | 224 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 |
| 204 | #define USB_PID_GIGABYTE_U7000 0x7001 | 225 | #define USB_PID_GIGABYTE_U7000 0x7001 |
| 226 | #define USB_PID_GIGABYTE_U8000 0x7002 | ||
| 205 | #define USB_PID_ASUS_U3000 0x171f | 227 | #define USB_PID_ASUS_U3000 0x171f |
| 228 | #define USB_PID_ASUS_U3000H 0x1736 | ||
| 206 | #define USB_PID_ASUS_U3100 0x173f | 229 | #define USB_PID_ASUS_U3100 0x173f |
| 207 | #define USB_PID_YUAN_EC372S 0x1edc | 230 | #define USB_PID_YUAN_EC372S 0x1edc |
| 231 | #define USB_PID_YUAN_STK7700PH 0x1f08 | ||
| 208 | #define USB_PID_DW2102 0x2102 | 232 | #define USB_PID_DW2102 0x2102 |
| 233 | #define USB_PID_XTENSIONS_XD_380 0x0381 | ||
| 234 | #define USB_PID_TELESTAR_STARSTICK_2 0x8000 | ||
| 235 | #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 | ||
| 209 | 236 | ||
| 210 | #endif | 237 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index a4d898b44e55..ca53df61caa8 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | /* DVB USB framework compliant Linux driver for the DVBWorld DVB-S 2102 Card | 1 | /* DVB USB framework compliant Linux driver for the |
| 2 | * DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card | ||
| 2 | * | 3 | * |
| 3 | * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) | 4 | * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) |
| 4 | * | 5 | * |
| @@ -10,62 +11,74 @@ | |||
| 10 | */ | 11 | */ |
| 11 | #include <linux/version.h> | 12 | #include <linux/version.h> |
| 12 | #include "dw2102.h" | 13 | #include "dw2102.h" |
| 14 | #include "si21xx.h" | ||
| 13 | #include "stv0299.h" | 15 | #include "stv0299.h" |
| 14 | #include "z0194a.h" | 16 | #include "z0194a.h" |
| 17 | #include "stv0288.h" | ||
| 18 | #include "stb6000.h" | ||
| 19 | #include "eds1547.h" | ||
| 20 | #include "cx24116.h" | ||
| 15 | 21 | ||
| 16 | #ifndef USB_PID_DW2102 | 22 | #ifndef USB_PID_DW2102 |
| 17 | #define USB_PID_DW2102 0x2102 | 23 | #define USB_PID_DW2102 0x2102 |
| 18 | #endif | 24 | #endif |
| 19 | 25 | ||
| 20 | #define DW2102_READ_MSG 0 | 26 | #ifndef USB_PID_DW2104 |
| 21 | #define DW2102_WRITE_MSG 1 | 27 | #define USB_PID_DW2104 0x2104 |
| 28 | #endif | ||
| 29 | |||
| 30 | #define DW210X_READ_MSG 0 | ||
| 31 | #define DW210X_WRITE_MSG 1 | ||
| 22 | 32 | ||
| 23 | #define REG_1F_SYMBOLRATE_BYTE0 0x1f | 33 | #define REG_1F_SYMBOLRATE_BYTE0 0x1f |
| 24 | #define REG_20_SYMBOLRATE_BYTE1 0x20 | 34 | #define REG_20_SYMBOLRATE_BYTE1 0x20 |
| 25 | #define REG_21_SYMBOLRATE_BYTE2 0x21 | 35 | #define REG_21_SYMBOLRATE_BYTE2 0x21 |
| 26 | 36 | /* on my own*/ | |
| 27 | #define DW2102_VOLTAGE_CTRL (0x1800) | 37 | #define DW2102_VOLTAGE_CTRL (0x1800) |
| 28 | #define DW2102_RC_QUERY (0x1a00) | 38 | #define DW2102_RC_QUERY (0x1a00) |
| 29 | 39 | ||
| 30 | struct dw2102_state { | 40 | struct dw210x_state { |
| 31 | u32 last_key_pressed; | 41 | u32 last_key_pressed; |
| 32 | }; | 42 | }; |
| 33 | struct dw2102_rc_keys { | 43 | struct dw210x_rc_keys { |
| 34 | u32 keycode; | 44 | u32 keycode; |
| 35 | u32 event; | 45 | u32 event; |
| 36 | }; | 46 | }; |
| 37 | 47 | ||
| 48 | /* debug */ | ||
| 49 | static int dvb_usb_dw2102_debug; | ||
| 50 | module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); | ||
| 51 | MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 52 | |||
| 38 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 53 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 39 | 54 | ||
| 40 | static int dw2102_op_rw(struct usb_device *dev, u8 request, u16 value, | 55 | static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, |
| 41 | u8 *data, u16 len, int flags) | 56 | u16 index, u8 * data, u16 len, int flags) |
| 42 | { | 57 | { |
| 43 | int ret; | 58 | int ret; |
| 44 | u8 u8buf[len]; | 59 | u8 u8buf[len]; |
| 45 | 60 | ||
| 46 | unsigned int pipe = (flags == DW2102_READ_MSG) ? | 61 | unsigned int pipe = (flags == DW210X_READ_MSG) ? |
| 47 | usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); | 62 | usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); |
| 48 | u8 request_type = (flags == DW2102_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; | 63 | u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; |
| 49 | 64 | ||
| 50 | if (flags == DW2102_WRITE_MSG) | 65 | if (flags == DW210X_WRITE_MSG) |
| 51 | memcpy(u8buf, data, len); | 66 | memcpy(u8buf, data, len); |
| 52 | ret = usb_control_msg(dev, pipe, request, | 67 | ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, |
| 53 | request_type | USB_TYPE_VENDOR, value, 0 , u8buf, len, 2000); | 68 | value, index , u8buf, len, 2000); |
| 54 | 69 | ||
| 55 | if (flags == DW2102_READ_MSG) | 70 | if (flags == DW210X_READ_MSG) |
| 56 | memcpy(data, u8buf, len); | 71 | memcpy(data, u8buf, len); |
| 57 | return ret; | 72 | return ret; |
| 58 | } | 73 | } |
| 59 | 74 | ||
| 60 | /* I2C */ | 75 | /* I2C */ |
| 61 | |||
| 62 | static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | 76 | static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
| 63 | int num) | 77 | int num) |
| 64 | { | 78 | { |
| 65 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 79 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
| 66 | int i = 0, ret = 0; | 80 | int i = 0, ret = 0; |
| 67 | u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; | 81 | u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; |
| 68 | u8 request; | ||
| 69 | u16 value; | 82 | u16 value; |
| 70 | 83 | ||
| 71 | if (!d) | 84 | if (!d) |
| @@ -76,14 +89,12 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); | |||
| 76 | switch (num) { | 89 | switch (num) { |
| 77 | case 2: | 90 | case 2: |
| 78 | /* read stv0299 register */ | 91 | /* read stv0299 register */ |
| 79 | request = 0xb5; | ||
| 80 | value = msg[0].buf[0];/* register */ | 92 | value = msg[0].buf[0];/* register */ |
| 81 | for (i = 0; i < msg[1].len; i++) { | 93 | for (i = 0; i < msg[1].len; i++) { |
| 82 | value = value + i; | 94 | value = value + i; |
| 83 | ret = dw2102_op_rw(d->udev, 0xb5, | 95 | ret = dw210x_op_rw(d->udev, 0xb5, value, 0, |
| 84 | value, buf6, 2, DW2102_READ_MSG); | 96 | buf6, 2, DW210X_READ_MSG); |
| 85 | msg[1].buf[i] = buf6[0]; | 97 | msg[1].buf[i] = buf6[0]; |
| 86 | |||
| 87 | } | 98 | } |
| 88 | break; | 99 | break; |
| 89 | case 1: | 100 | case 1: |
| @@ -93,8 +104,8 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); | |||
| 93 | buf6[0] = 0x2a; | 104 | buf6[0] = 0x2a; |
| 94 | buf6[1] = msg[0].buf[0]; | 105 | buf6[1] = msg[0].buf[0]; |
| 95 | buf6[2] = msg[0].buf[1]; | 106 | buf6[2] = msg[0].buf[1]; |
| 96 | ret = dw2102_op_rw(d->udev, 0xb2, | 107 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, |
| 97 | 0, buf6, 3, DW2102_WRITE_MSG); | 108 | buf6, 3, DW210X_WRITE_MSG); |
| 98 | break; | 109 | break; |
| 99 | case 0x60: | 110 | case 0x60: |
| 100 | if (msg[0].flags == 0) { | 111 | if (msg[0].flags == 0) { |
| @@ -106,26 +117,26 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); | |||
| 106 | buf6[4] = msg[0].buf[1]; | 117 | buf6[4] = msg[0].buf[1]; |
| 107 | buf6[5] = msg[0].buf[2]; | 118 | buf6[5] = msg[0].buf[2]; |
| 108 | buf6[6] = msg[0].buf[3]; | 119 | buf6[6] = msg[0].buf[3]; |
| 109 | ret = dw2102_op_rw(d->udev, 0xb2, | 120 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, |
| 110 | 0, buf6, 7, DW2102_WRITE_MSG); | 121 | buf6, 7, DW210X_WRITE_MSG); |
| 111 | } else { | 122 | } else { |
| 112 | /* write to tuner pll */ | 123 | /* read from tuner */ |
| 113 | ret = dw2102_op_rw(d->udev, 0xb5, | 124 | ret = dw210x_op_rw(d->udev, 0xb5, 0, 0, |
| 114 | 0, buf6, 1, DW2102_READ_MSG); | 125 | buf6, 1, DW210X_READ_MSG); |
| 115 | msg[0].buf[0] = buf6[0]; | 126 | msg[0].buf[0] = buf6[0]; |
| 116 | } | 127 | } |
| 117 | break; | 128 | break; |
| 118 | case (DW2102_RC_QUERY): | 129 | case (DW2102_RC_QUERY): |
| 119 | ret = dw2102_op_rw(d->udev, 0xb8, | 130 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, |
| 120 | 0, buf6, 2, DW2102_READ_MSG); | 131 | buf6, 2, DW210X_READ_MSG); |
| 121 | msg[0].buf[0] = buf6[0]; | 132 | msg[0].buf[0] = buf6[0]; |
| 122 | msg[0].buf[1] = buf6[1]; | 133 | msg[0].buf[1] = buf6[1]; |
| 123 | break; | 134 | break; |
| 124 | case (DW2102_VOLTAGE_CTRL): | 135 | case (DW2102_VOLTAGE_CTRL): |
| 125 | buf6[0] = 0x30; | 136 | buf6[0] = 0x30; |
| 126 | buf6[1] = msg[0].buf[0]; | 137 | buf6[1] = msg[0].buf[0]; |
| 127 | ret = dw2102_op_rw(d->udev, 0xb2, | 138 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, |
| 128 | 0, buf6, 2, DW2102_WRITE_MSG); | 139 | buf6, 2, DW210X_WRITE_MSG); |
| 129 | break; | 140 | break; |
| 130 | } | 141 | } |
| 131 | 142 | ||
| @@ -136,17 +147,265 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); | |||
| 136 | return num; | 147 | return num; |
| 137 | } | 148 | } |
| 138 | 149 | ||
| 139 | static u32 dw2102_i2c_func(struct i2c_adapter *adapter) | 150 | static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, |
| 151 | struct i2c_msg msg[], int num) | ||
| 152 | { | ||
| 153 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 154 | int ret = 0; | ||
| 155 | u8 buf6[] = {0, 0, 0, 0, 0, 0, 0}; | ||
| 156 | |||
| 157 | if (!d) | ||
| 158 | return -ENODEV; | ||
| 159 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 160 | return -EAGAIN; | ||
| 161 | |||
| 162 | switch (num) { | ||
| 163 | case 2: | ||
| 164 | /* read si2109 register by number */ | ||
| 165 | buf6[0] = 0xd0; | ||
| 166 | buf6[1] = msg[0].len; | ||
| 167 | buf6[2] = msg[0].buf[0]; | ||
| 168 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 169 | buf6, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 170 | /* read si2109 register */ | ||
| 171 | ret = dw210x_op_rw(d->udev, 0xc3, 0xd0, 0, | ||
| 172 | buf6, msg[1].len + 2, DW210X_READ_MSG); | ||
| 173 | memcpy(msg[1].buf, buf6 + 2, msg[1].len); | ||
| 174 | |||
| 175 | break; | ||
| 176 | case 1: | ||
| 177 | switch (msg[0].addr) { | ||
| 178 | case 0x68: | ||
| 179 | /* write to si2109 register */ | ||
| 180 | buf6[0] = 0xd0; | ||
| 181 | buf6[1] = msg[0].len; | ||
| 182 | memcpy(buf6 + 2, msg[0].buf, msg[0].len); | ||
| 183 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6, | ||
| 184 | msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 185 | break; | ||
| 186 | case(DW2102_RC_QUERY): | ||
| 187 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
| 188 | buf6, 2, DW210X_READ_MSG); | ||
| 189 | msg[0].buf[0] = buf6[0]; | ||
| 190 | msg[0].buf[1] = buf6[1]; | ||
| 191 | break; | ||
| 192 | case(DW2102_VOLTAGE_CTRL): | ||
| 193 | buf6[0] = 0x30; | ||
| 194 | buf6[1] = msg[0].buf[0]; | ||
| 195 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
| 196 | buf6, 2, DW210X_WRITE_MSG); | ||
| 197 | break; | ||
| 198 | } | ||
| 199 | break; | ||
| 200 | } | ||
| 201 | |||
| 202 | mutex_unlock(&d->i2c_mutex); | ||
| 203 | return num; | ||
| 204 | } | ||
| 205 | static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) | ||
| 206 | { | ||
| 207 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 208 | int ret = 0; | ||
| 209 | |||
| 210 | if (!d) | ||
| 211 | return -ENODEV; | ||
| 212 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 213 | return -EAGAIN; | ||
| 214 | |||
| 215 | switch (num) { | ||
| 216 | case 2: { | ||
| 217 | /* read */ | ||
| 218 | /* first write first register number */ | ||
| 219 | u8 ibuf [msg[1].len + 2], obuf[3]; | ||
| 220 | obuf[0] = 0xd0; | ||
| 221 | obuf[1] = msg[0].len; | ||
| 222 | obuf[2] = msg[0].buf[0]; | ||
| 223 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 224 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 225 | /* second read registers */ | ||
| 226 | ret = dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0, | ||
| 227 | ibuf, msg[1].len + 2, DW210X_READ_MSG); | ||
| 228 | memcpy(msg[1].buf, ibuf + 2, msg[1].len); | ||
| 229 | |||
| 230 | break; | ||
| 231 | } | ||
| 232 | case 1: | ||
| 233 | switch (msg[0].addr) { | ||
| 234 | case 0x68: { | ||
| 235 | /* write to register */ | ||
| 236 | u8 obuf[msg[0].len + 2]; | ||
| 237 | obuf[0] = 0xd0; | ||
| 238 | obuf[1] = msg[0].len; | ||
| 239 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
| 240 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 241 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 242 | break; | ||
| 243 | } | ||
| 244 | case 0x61: { | ||
| 245 | /* write to tuner */ | ||
| 246 | u8 obuf[msg[0].len + 2]; | ||
| 247 | obuf[0] = 0xc2; | ||
| 248 | obuf[1] = msg[0].len; | ||
| 249 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
| 250 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 251 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 252 | break; | ||
| 253 | } | ||
| 254 | case(DW2102_RC_QUERY): { | ||
| 255 | u8 ibuf[2]; | ||
| 256 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
| 257 | ibuf, 2, DW210X_READ_MSG); | ||
| 258 | memcpy(msg[0].buf, ibuf , 2); | ||
| 259 | break; | ||
| 260 | } | ||
| 261 | case(DW2102_VOLTAGE_CTRL): { | ||
| 262 | u8 obuf[2]; | ||
| 263 | obuf[0] = 0x30; | ||
| 264 | obuf[1] = msg[0].buf[0]; | ||
| 265 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
| 266 | obuf, 2, DW210X_WRITE_MSG); | ||
| 267 | break; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | break; | ||
| 272 | } | ||
| 273 | |||
| 274 | mutex_unlock(&d->i2c_mutex); | ||
| 275 | return num; | ||
| 276 | } | ||
| 277 | |||
| 278 | static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) | ||
| 279 | { | ||
| 280 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 281 | int ret = 0; | ||
| 282 | int len, i; | ||
| 283 | |||
| 284 | if (!d) | ||
| 285 | return -ENODEV; | ||
| 286 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 287 | return -EAGAIN; | ||
| 288 | |||
| 289 | switch (num) { | ||
| 290 | case 2: { | ||
| 291 | /* read */ | ||
| 292 | /* first write first register number */ | ||
| 293 | u8 ibuf [msg[1].len + 2], obuf[3]; | ||
| 294 | obuf[0] = 0xaa; | ||
| 295 | obuf[1] = msg[0].len; | ||
| 296 | obuf[2] = msg[0].buf[0]; | ||
| 297 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 298 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 299 | /* second read registers */ | ||
| 300 | ret = dw210x_op_rw(d->udev, 0xc3, 0xab , 0, | ||
| 301 | ibuf, msg[1].len + 2, DW210X_READ_MSG); | ||
| 302 | memcpy(msg[1].buf, ibuf + 2, msg[1].len); | ||
| 303 | |||
| 304 | break; | ||
| 305 | } | ||
| 306 | case 1: | ||
| 307 | switch (msg[0].addr) { | ||
| 308 | case 0x55: { | ||
| 309 | if (msg[0].buf[0] == 0xf7) { | ||
| 310 | /* firmware */ | ||
| 311 | /* Write in small blocks */ | ||
| 312 | u8 obuf[19]; | ||
| 313 | obuf[0] = 0xaa; | ||
| 314 | obuf[1] = 0x11; | ||
| 315 | obuf[2] = 0xf7; | ||
| 316 | len = msg[0].len - 1; | ||
| 317 | i = 1; | ||
| 318 | do { | ||
| 319 | memcpy(obuf + 3, msg[0].buf + i, (len > 16 ? 16 : len)); | ||
| 320 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 321 | obuf, (len > 16 ? 16 : len) + 3, DW210X_WRITE_MSG); | ||
| 322 | i += 16; | ||
| 323 | len -= 16; | ||
| 324 | } while (len > 0); | ||
| 325 | } else { | ||
| 326 | /* write to register */ | ||
| 327 | u8 obuf[msg[0].len + 2]; | ||
| 328 | obuf[0] = 0xaa; | ||
| 329 | obuf[1] = msg[0].len; | ||
| 330 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
| 331 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 332 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 333 | } | ||
| 334 | break; | ||
| 335 | } | ||
| 336 | case(DW2102_RC_QUERY): { | ||
| 337 | u8 ibuf[2]; | ||
| 338 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
| 339 | ibuf, 2, DW210X_READ_MSG); | ||
| 340 | memcpy(msg[0].buf, ibuf , 2); | ||
| 341 | break; | ||
| 342 | } | ||
| 343 | case(DW2102_VOLTAGE_CTRL): { | ||
| 344 | u8 obuf[2]; | ||
| 345 | obuf[0] = 0x30; | ||
| 346 | obuf[1] = msg[0].buf[0]; | ||
| 347 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
| 348 | obuf, 2, DW210X_WRITE_MSG); | ||
| 349 | break; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | break; | ||
| 354 | } | ||
| 355 | |||
| 356 | mutex_unlock(&d->i2c_mutex); | ||
| 357 | return num; | ||
| 358 | } | ||
| 359 | |||
| 360 | static u32 dw210x_i2c_func(struct i2c_adapter *adapter) | ||
| 140 | { | 361 | { |
| 141 | return I2C_FUNC_I2C; | 362 | return I2C_FUNC_I2C; |
| 142 | } | 363 | } |
| 143 | 364 | ||
| 144 | static struct i2c_algorithm dw2102_i2c_algo = { | 365 | static struct i2c_algorithm dw2102_i2c_algo = { |
| 145 | .master_xfer = dw2102_i2c_transfer, | 366 | .master_xfer = dw2102_i2c_transfer, |
| 146 | .functionality = dw2102_i2c_func, | 367 | .functionality = dw210x_i2c_func, |
| 368 | }; | ||
| 369 | |||
| 370 | static struct i2c_algorithm dw2102_serit_i2c_algo = { | ||
| 371 | .master_xfer = dw2102_serit_i2c_transfer, | ||
| 372 | .functionality = dw210x_i2c_func, | ||
| 373 | }; | ||
| 374 | |||
| 375 | static struct i2c_algorithm dw2102_earda_i2c_algo = { | ||
| 376 | .master_xfer = dw2102_earda_i2c_transfer, | ||
| 377 | .functionality = dw210x_i2c_func, | ||
| 378 | }; | ||
| 379 | |||
| 380 | static struct i2c_algorithm dw2104_i2c_algo = { | ||
| 381 | .master_xfer = dw2104_i2c_transfer, | ||
| 382 | .functionality = dw210x_i2c_func, | ||
| 147 | }; | 383 | }; |
| 148 | 384 | ||
| 149 | static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | 385 | static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) |
| 386 | { | ||
| 387 | int i; | ||
| 388 | u8 ibuf[] = {0, 0}; | ||
| 389 | u8 eeprom[256], eepromline[16]; | ||
| 390 | |||
| 391 | for (i = 0; i < 256; i++) { | ||
| 392 | if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) { | ||
| 393 | err("read eeprom failed."); | ||
| 394 | return -1; | ||
| 395 | } else { | ||
| 396 | eepromline[i%16] = ibuf[0]; | ||
| 397 | eeprom[i] = ibuf[0]; | ||
| 398 | } | ||
| 399 | if ((i % 16) == 15) { | ||
| 400 | deb_xfer("%02x: ", i - 15); | ||
| 401 | debug_dump(eepromline, 16, deb_xfer); | ||
| 402 | } | ||
| 403 | } | ||
| 404 | memcpy(mac, eeprom + 8, 6); | ||
| 405 | return 0; | ||
| 406 | }; | ||
| 407 | |||
| 408 | static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
| 150 | { | 409 | { |
| 151 | static u8 command_13v[1] = {0x00}; | 410 | static u8 command_13v[1] = {0x00}; |
| 152 | static u8 command_18v[1] = {0x01}; | 411 | static u8 command_18v[1] = {0x01}; |
| @@ -163,18 +422,66 @@ static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | |||
| 163 | return 0; | 422 | return 0; |
| 164 | } | 423 | } |
| 165 | 424 | ||
| 166 | static int dw2102_frontend_attach(struct dvb_usb_adapter *d) | 425 | static struct cx24116_config dw2104_config = { |
| 426 | .demod_address = 0x55, | ||
| 427 | .mpg_clk_pos_pol = 0x01, | ||
| 428 | }; | ||
| 429 | |||
| 430 | static struct si21xx_config serit_sp1511lhb_config = { | ||
| 431 | .demod_address = 0x68, | ||
| 432 | .min_delay_ms = 100, | ||
| 433 | |||
| 434 | }; | ||
| 435 | |||
| 436 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) | ||
| 167 | { | 437 | { |
| 168 | d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, | 438 | if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, |
| 169 | &d->dev->i2c_adap); | 439 | &d->dev->i2c_adap)) != NULL) { |
| 170 | if (d->fe != NULL) { | 440 | d->fe->ops.set_voltage = dw210x_set_voltage; |
| 171 | d->fe->ops.set_voltage = dw2102_set_voltage; | 441 | info("Attached cx24116!\n"); |
| 172 | info("Attached stv0299!\n"); | ||
| 173 | return 0; | 442 | return 0; |
| 174 | } | 443 | } |
| 175 | return -EIO; | 444 | return -EIO; |
| 176 | } | 445 | } |
| 177 | 446 | ||
| 447 | static struct dvb_usb_device_properties dw2102_properties; | ||
| 448 | |||
| 449 | static int dw2102_frontend_attach(struct dvb_usb_adapter *d) | ||
| 450 | { | ||
| 451 | if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) { | ||
| 452 | /*dw2102_properties.adapter->tuner_attach = NULL;*/ | ||
| 453 | d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config, | ||
| 454 | &d->dev->i2c_adap); | ||
| 455 | if (d->fe != NULL) { | ||
| 456 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 457 | info("Attached si21xx!\n"); | ||
| 458 | return 0; | ||
| 459 | } | ||
| 460 | } | ||
| 461 | if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) { | ||
| 462 | /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ | ||
| 463 | d->fe = dvb_attach(stv0288_attach, &earda_config, | ||
| 464 | &d->dev->i2c_adap); | ||
| 465 | if (d->fe != NULL) { | ||
| 466 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 467 | info("Attached stv0288!\n"); | ||
| 468 | return 0; | ||
| 469 | } | ||
| 470 | } | ||
| 471 | |||
| 472 | if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) { | ||
| 473 | /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ | ||
| 474 | d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, | ||
| 475 | &d->dev->i2c_adap); | ||
| 476 | if (d->fe != NULL) { | ||
| 477 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 478 | info("Attached stv0299!\n"); | ||
| 479 | return 0; | ||
| 480 | } | ||
| 481 | } | ||
| 482 | return -EIO; | ||
| 483 | } | ||
| 484 | |||
| 178 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) | 485 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) |
| 179 | { | 486 | { |
| 180 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, | 487 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, |
| @@ -182,7 +489,15 @@ static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 182 | return 0; | 489 | return 0; |
| 183 | } | 490 | } |
| 184 | 491 | ||
| 185 | static struct dvb_usb_rc_key dw2102_rc_keys[] = { | 492 | static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap) |
| 493 | { | ||
| 494 | dvb_attach(stb6000_attach, adap->fe, 0x61, | ||
| 495 | &adap->dev->i2c_adap); | ||
| 496 | |||
| 497 | return 0; | ||
| 498 | } | ||
| 499 | |||
| 500 | static struct dvb_usb_rc_key dw210x_rc_keys[] = { | ||
| 186 | { 0xf8, 0x0a, KEY_Q }, /*power*/ | 501 | { 0xf8, 0x0a, KEY_Q }, /*power*/ |
| 187 | { 0xf8, 0x0c, KEY_M }, /*mute*/ | 502 | { 0xf8, 0x0c, KEY_M }, /*mute*/ |
| 188 | { 0xf8, 0x11, KEY_1 }, | 503 | { 0xf8, 0x11, KEY_1 }, |
| @@ -221,7 +536,7 @@ static struct dvb_usb_rc_key dw2102_rc_keys[] = { | |||
| 221 | 536 | ||
| 222 | static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 537 | static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
| 223 | { | 538 | { |
| 224 | struct dw2102_state *st = d->priv; | 539 | struct dw210x_state *st = d->priv; |
| 225 | u8 key[2]; | 540 | u8 key[2]; |
| 226 | struct i2c_msg msg[] = { | 541 | struct i2c_msg msg[] = { |
| 227 | {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key, | 542 | {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key, |
| @@ -231,12 +546,12 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
| 231 | 546 | ||
| 232 | *state = REMOTE_NO_KEY_PRESSED; | 547 | *state = REMOTE_NO_KEY_PRESSED; |
| 233 | if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { | 548 | if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { |
| 234 | for (i = 0; i < ARRAY_SIZE(dw2102_rc_keys); i++) { | 549 | for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) { |
| 235 | if (dw2102_rc_keys[i].data == msg[0].buf[0]) { | 550 | if (dw210x_rc_keys[i].data == msg[0].buf[0]) { |
| 236 | *state = REMOTE_KEY_PRESSED; | 551 | *state = REMOTE_KEY_PRESSED; |
| 237 | *event = dw2102_rc_keys[i].event; | 552 | *event = dw210x_rc_keys[i].event; |
| 238 | st->last_key_pressed = | 553 | st->last_key_pressed = |
| 239 | dw2102_rc_keys[i].event; | 554 | dw210x_rc_keys[i].event; |
| 240 | break; | 555 | break; |
| 241 | } | 556 | } |
| 242 | st->last_key_pressed = 0; | 557 | st->last_key_pressed = 0; |
| @@ -249,6 +564,8 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
| 249 | static struct usb_device_id dw2102_table[] = { | 564 | static struct usb_device_id dw2102_table[] = { |
| 250 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, | 565 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, |
| 251 | {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, | 566 | {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, |
| 567 | {USB_DEVICE(USB_VID_CYPRESS, 0x2104)}, | ||
| 568 | {USB_DEVICE(0x9022, 0xd650)}, | ||
| 252 | { } | 569 | { } |
| 253 | }; | 570 | }; |
| 254 | 571 | ||
| @@ -260,7 +577,7 @@ static int dw2102_load_firmware(struct usb_device *dev, | |||
| 260 | u8 *b, *p; | 577 | u8 *b, *p; |
| 261 | int ret = 0, i; | 578 | int ret = 0, i; |
| 262 | u8 reset; | 579 | u8 reset; |
| 263 | u8 reset16 [] = {0, 0, 0, 0, 0, 0, 0}; | 580 | u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; |
| 264 | const struct firmware *fw; | 581 | const struct firmware *fw; |
| 265 | const char *filename = "dvb-usb-dw2101.fw"; | 582 | const char *filename = "dvb-usb-dw2101.fw"; |
| 266 | switch (dev->descriptor.idProduct) { | 583 | switch (dev->descriptor.idProduct) { |
| @@ -273,25 +590,23 @@ static int dw2102_load_firmware(struct usb_device *dev, | |||
| 273 | return ret; | 590 | return ret; |
| 274 | } | 591 | } |
| 275 | break; | 592 | break; |
| 276 | case USB_PID_DW2102: | 593 | default: |
| 277 | fw = frmwr; | 594 | fw = frmwr; |
| 278 | break; | 595 | break; |
| 279 | } | 596 | } |
| 280 | info("start downloading DW2102 firmware"); | 597 | info("start downloading DW210X firmware"); |
| 281 | p = kmalloc(fw->size, GFP_KERNEL); | 598 | p = kmalloc(fw->size, GFP_KERNEL); |
| 282 | reset = 1; | 599 | reset = 1; |
| 283 | /*stop the CPU*/ | 600 | /*stop the CPU*/ |
| 284 | dw2102_op_rw(dev, 0xa0, 0x7f92, &reset, 1, DW2102_WRITE_MSG); | 601 | dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG); |
| 285 | dw2102_op_rw(dev, 0xa0, 0xe600, &reset, 1, DW2102_WRITE_MSG); | 602 | dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG); |
| 286 | 603 | ||
| 287 | if (p != NULL) { | 604 | if (p != NULL) { |
| 288 | memcpy(p, fw->data, fw->size); | 605 | memcpy(p, fw->data, fw->size); |
| 289 | for (i = 0; i < fw->size; i += 0x40) { | 606 | for (i = 0; i < fw->size; i += 0x40) { |
| 290 | b = (u8 *) p + i; | 607 | b = (u8 *) p + i; |
| 291 | if (dw2102_op_rw | 608 | if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40, |
| 292 | (dev, 0xa0, i, b , 0x40, | 609 | DW210X_WRITE_MSG) != 0x40) { |
| 293 | DW2102_WRITE_MSG) != 0x40 | ||
| 294 | ) { | ||
| 295 | err("error while transferring firmware"); | 610 | err("error while transferring firmware"); |
| 296 | ret = -EINVAL; | 611 | ret = -EINVAL; |
| 297 | break; | 612 | break; |
| @@ -299,43 +614,66 @@ static int dw2102_load_firmware(struct usb_device *dev, | |||
| 299 | } | 614 | } |
| 300 | /* restart the CPU */ | 615 | /* restart the CPU */ |
| 301 | reset = 0; | 616 | reset = 0; |
| 302 | if (ret || dw2102_op_rw | 617 | if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, |
| 303 | (dev, 0xa0, 0x7f92, &reset, 1, | 618 | DW210X_WRITE_MSG) != 1) { |
| 304 | DW2102_WRITE_MSG) != 1) { | ||
| 305 | err("could not restart the USB controller CPU."); | 619 | err("could not restart the USB controller CPU."); |
| 306 | ret = -EINVAL; | 620 | ret = -EINVAL; |
| 307 | } | 621 | } |
| 308 | if (ret || dw2102_op_rw | 622 | if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, |
| 309 | (dev, 0xa0, 0xe600, &reset, 1, | 623 | DW210X_WRITE_MSG) != 1) { |
| 310 | DW2102_WRITE_MSG) != 1) { | ||
| 311 | err("could not restart the USB controller CPU."); | 624 | err("could not restart the USB controller CPU."); |
| 312 | ret = -EINVAL; | 625 | ret = -EINVAL; |
| 313 | } | 626 | } |
| 314 | /* init registers */ | 627 | /* init registers */ |
| 315 | switch (dev->descriptor.idProduct) { | 628 | switch (dev->descriptor.idProduct) { |
| 316 | case USB_PID_DW2102: | 629 | case USB_PID_DW2104: |
| 317 | dw2102_op_rw | 630 | case 0xd650: |
| 318 | (dev, 0xbf, 0x0040, &reset, 0, | 631 | reset = 1; |
| 319 | DW2102_WRITE_MSG); | 632 | dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, |
| 320 | dw2102_op_rw | 633 | DW210X_WRITE_MSG); |
| 321 | (dev, 0xb9, 0x0000, &reset16[0], 2, | 634 | reset = 0; |
| 322 | DW2102_READ_MSG); | 635 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, |
| 636 | DW210X_WRITE_MSG); | ||
| 323 | break; | 637 | break; |
| 638 | case USB_PID_DW2102: | ||
| 639 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, | ||
| 640 | DW210X_WRITE_MSG); | ||
| 641 | dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, | ||
| 642 | DW210X_READ_MSG); | ||
| 643 | /* check STV0299 frontend */ | ||
| 644 | dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2, | ||
| 645 | DW210X_READ_MSG); | ||
| 646 | if (reset16[0] == 0xa1) { | ||
| 647 | dw2102_properties.i2c_algo = &dw2102_i2c_algo; | ||
| 648 | dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach; | ||
| 649 | break; | ||
| 650 | } else { | ||
| 651 | /* check STV0288 frontend */ | ||
| 652 | reset16[0] = 0xd0; | ||
| 653 | reset16[1] = 1; | ||
| 654 | reset16[2] = 0; | ||
| 655 | dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3, | ||
| 656 | DW210X_WRITE_MSG); | ||
| 657 | dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3, | ||
| 658 | DW210X_READ_MSG); | ||
| 659 | if (reset16[2] == 0x11) { | ||
| 660 | dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo; | ||
| 661 | dw2102_properties.adapter->tuner_attach = &dw2102_earda_tuner_attach; | ||
| 662 | break; | ||
| 663 | } | ||
| 664 | } | ||
| 324 | case 0x2101: | 665 | case 0x2101: |
| 325 | dw2102_op_rw | 666 | dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, |
| 326 | (dev, 0xbc, 0x0030, &reset16[0], 2, | 667 | DW210X_READ_MSG); |
| 327 | DW2102_READ_MSG); | 668 | dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, |
| 328 | dw2102_op_rw | 669 | DW210X_READ_MSG); |
| 329 | (dev, 0xba, 0x0000, &reset16[0], 7, | 670 | dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, |
| 330 | DW2102_READ_MSG); | 671 | DW210X_READ_MSG); |
| 331 | dw2102_op_rw | 672 | dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, |
| 332 | (dev, 0xba, 0x0000, &reset16[0], 7, | 673 | DW210X_READ_MSG); |
| 333 | DW2102_READ_MSG); | ||
| 334 | dw2102_op_rw | ||
| 335 | (dev, 0xb9, 0x0000, &reset16[0], 2, | ||
| 336 | DW2102_READ_MSG); | ||
| 337 | break; | 674 | break; |
| 338 | } | 675 | } |
| 676 | msleep(100); | ||
| 339 | kfree(p); | 677 | kfree(p); |
| 340 | } | 678 | } |
| 341 | return ret; | 679 | return ret; |
| @@ -345,12 +683,12 @@ static struct dvb_usb_device_properties dw2102_properties = { | |||
| 345 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | 683 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
| 346 | .usb_ctrl = DEVICE_SPECIFIC, | 684 | .usb_ctrl = DEVICE_SPECIFIC, |
| 347 | .firmware = "dvb-usb-dw2102.fw", | 685 | .firmware = "dvb-usb-dw2102.fw", |
| 348 | .size_of_priv = sizeof(struct dw2102_state), | 686 | .size_of_priv = sizeof(struct dw210x_state), |
| 349 | .no_reconnect = 1, | 687 | .no_reconnect = 1, |
| 350 | 688 | ||
| 351 | .i2c_algo = &dw2102_i2c_algo, | 689 | .i2c_algo = &dw2102_serit_i2c_algo, |
| 352 | .rc_key_map = dw2102_rc_keys, | 690 | .rc_key_map = dw210x_rc_keys, |
| 353 | .rc_key_map_size = ARRAY_SIZE(dw2102_rc_keys), | 691 | .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), |
| 354 | .rc_interval = 150, | 692 | .rc_interval = 150, |
| 355 | .rc_query = dw2102_rc_query, | 693 | .rc_query = dw2102_rc_query, |
| 356 | 694 | ||
| @@ -358,11 +696,12 @@ static struct dvb_usb_device_properties dw2102_properties = { | |||
| 358 | /* parameter for the MPEG2-data transfer */ | 696 | /* parameter for the MPEG2-data transfer */ |
| 359 | .num_adapters = 1, | 697 | .num_adapters = 1, |
| 360 | .download_firmware = dw2102_load_firmware, | 698 | .download_firmware = dw2102_load_firmware, |
| 361 | .adapter = { | 699 | .read_mac_address = dw210x_read_mac_address, |
| 700 | .adapter = { | ||
| 362 | { | 701 | { |
| 363 | .frontend_attach = dw2102_frontend_attach, | 702 | .frontend_attach = dw2102_frontend_attach, |
| 364 | .streaming_ctrl = NULL, | 703 | .streaming_ctrl = NULL, |
| 365 | .tuner_attach = dw2102_tuner_attach, | 704 | .tuner_attach = NULL, |
| 366 | .stream = { | 705 | .stream = { |
| 367 | .type = USB_BULK, | 706 | .type = USB_BULK, |
| 368 | .count = 8, | 707 | .count = 8, |
| @@ -388,11 +727,64 @@ static struct dvb_usb_device_properties dw2102_properties = { | |||
| 388 | } | 727 | } |
| 389 | }; | 728 | }; |
| 390 | 729 | ||
| 730 | static struct dvb_usb_device_properties dw2104_properties = { | ||
| 731 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 732 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 733 | .firmware = "dvb-usb-dw2104.fw", | ||
| 734 | .size_of_priv = sizeof(struct dw210x_state), | ||
| 735 | .no_reconnect = 1, | ||
| 736 | |||
| 737 | .i2c_algo = &dw2104_i2c_algo, | ||
| 738 | .rc_key_map = dw210x_rc_keys, | ||
| 739 | .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), | ||
| 740 | .rc_interval = 150, | ||
| 741 | .rc_query = dw2102_rc_query, | ||
| 742 | |||
| 743 | .generic_bulk_ctrl_endpoint = 0x81, | ||
| 744 | /* parameter for the MPEG2-data transfer */ | ||
| 745 | .num_adapters = 1, | ||
| 746 | .download_firmware = dw2102_load_firmware, | ||
| 747 | .read_mac_address = dw210x_read_mac_address, | ||
| 748 | .adapter = { | ||
| 749 | { | ||
| 750 | .frontend_attach = dw2104_frontend_attach, | ||
| 751 | .streaming_ctrl = NULL, | ||
| 752 | /*.tuner_attach = dw2104_tuner_attach,*/ | ||
| 753 | .stream = { | ||
| 754 | .type = USB_BULK, | ||
| 755 | .count = 8, | ||
| 756 | .endpoint = 0x82, | ||
| 757 | .u = { | ||
| 758 | .bulk = { | ||
| 759 | .buffersize = 4096, | ||
| 760 | } | ||
| 761 | } | ||
| 762 | }, | ||
| 763 | } | ||
| 764 | }, | ||
| 765 | .num_device_descs = 2, | ||
| 766 | .devices = { | ||
| 767 | { "DVBWorld DW2104 USB2.0", | ||
| 768 | {&dw2102_table[2], NULL}, | ||
| 769 | {NULL}, | ||
| 770 | }, | ||
| 771 | { "TeVii S650 USB2.0", | ||
| 772 | {&dw2102_table[3], NULL}, | ||
| 773 | {NULL}, | ||
| 774 | }, | ||
| 775 | } | ||
| 776 | }; | ||
| 777 | |||
| 391 | static int dw2102_probe(struct usb_interface *intf, | 778 | static int dw2102_probe(struct usb_interface *intf, |
| 392 | const struct usb_device_id *id) | 779 | const struct usb_device_id *id) |
| 393 | { | 780 | { |
| 394 | return dvb_usb_device_init(intf, &dw2102_properties, | 781 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, |
| 395 | THIS_MODULE, NULL, adapter_nr); | 782 | THIS_MODULE, NULL, adapter_nr) || |
| 783 | 0 == dvb_usb_device_init(intf, &dw2104_properties, | ||
| 784 | THIS_MODULE, NULL, adapter_nr)) { | ||
| 785 | return 0; | ||
| 786 | } | ||
| 787 | return -ENODEV; | ||
| 396 | } | 788 | } |
| 397 | 789 | ||
| 398 | static struct usb_driver dw2102_driver = { | 790 | static struct usb_driver dw2102_driver = { |
| @@ -420,6 +812,6 @@ module_init(dw2102_module_init); | |||
| 420 | module_exit(dw2102_module_exit); | 812 | module_exit(dw2102_module_exit); |
| 421 | 813 | ||
| 422 | MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); | 814 | MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); |
| 423 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101 2102 USB2.0 device"); | 815 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device"); |
| 424 | MODULE_VERSION("0.1"); | 816 | MODULE_VERSION("0.1"); |
| 425 | MODULE_LICENSE("GPL"); | 817 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h index 7a310f906837..e3370734e95a 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.h +++ b/drivers/media/dvb/dvb-usb/dw2102.h | |||
| @@ -4,6 +4,5 @@ | |||
| 4 | #define DVB_USB_LOG_PREFIX "dw2102" | 4 | #define DVB_USB_LOG_PREFIX "dw2102" |
| 5 | #include "dvb-usb.h" | 5 | #include "dvb-usb.h" |
| 6 | 6 | ||
| 7 | extern int dvb_usb_dw2102_debug; | ||
| 8 | #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args) | 7 | #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args) |
| 9 | #endif | 8 | #endif |
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 7dbb4a223c99..96b93e21a84b 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
| @@ -43,6 +43,20 @@ config DVB_S5H1420 | |||
| 43 | help | 43 | help |
| 44 | A DVB-S tuner module. Say Y when you want to support this frontend. | 44 | A DVB-S tuner module. Say Y when you want to support this frontend. |
| 45 | 45 | ||
| 46 | config DVB_STV0288 | ||
| 47 | tristate "ST STV0288 based" | ||
| 48 | depends on DVB_CORE && I2C | ||
| 49 | default m if DVB_FE_CUSTOMISE | ||
| 50 | help | ||
| 51 | A DVB-S tuner module. Say Y when you want to support this frontend. | ||
| 52 | |||
| 53 | config DVB_STB6000 | ||
| 54 | tristate "ST STB6000 silicon tuner" | ||
| 55 | depends on DVB_CORE && I2C | ||
| 56 | default m if DVB_FE_CUSTOMISE | ||
| 57 | help | ||
| 58 | A DVB-S silicon tuner module. Say Y when you want to support this tuner. | ||
| 59 | |||
| 46 | config DVB_STV0299 | 60 | config DVB_STV0299 |
| 47 | tristate "ST STV0299 based" | 61 | tristate "ST STV0299 based" |
| 48 | depends on DVB_CORE && I2C | 62 | depends on DVB_CORE && I2C |
| @@ -92,6 +106,20 @@ config DVB_TUA6100 | |||
| 92 | help | 106 | help |
| 93 | A DVB-S PLL chip. | 107 | A DVB-S PLL chip. |
| 94 | 108 | ||
| 109 | config DVB_CX24116 | ||
| 110 | tristate "Conexant CX24116 based" | ||
| 111 | depends on DVB_CORE && I2C | ||
| 112 | default m if DVB_FE_CUSTOMISE | ||
| 113 | help | ||
| 114 | A DVB-S/S2 tuner module. Say Y when you want to support this frontend. | ||
| 115 | |||
| 116 | config DVB_SI21XX | ||
| 117 | tristate "Silicon Labs SI21XX based" | ||
| 118 | depends on DVB_CORE && I2C | ||
| 119 | default m if DVB_FE_CUSTOMISE | ||
| 120 | help | ||
| 121 | A DVB-S tuner module. Say Y when you want to support this frontend. | ||
| 122 | |||
| 95 | comment "DVB-T (terrestrial) frontends" | 123 | comment "DVB-T (terrestrial) frontends" |
| 96 | depends on DVB_CORE | 124 | depends on DVB_CORE |
| 97 | 125 | ||
| @@ -385,4 +413,23 @@ config DVB_ISL6421 | |||
| 385 | help | 413 | help |
| 386 | An SEC control chip. | 414 | An SEC control chip. |
| 387 | 415 | ||
| 416 | config DVB_LGS8GL5 | ||
| 417 | tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)" | ||
| 418 | depends on DVB_CORE && I2C | ||
| 419 | default m if DVB_FE_CUSTOMISE | ||
| 420 | help | ||
| 421 | A DMB-TH tuner module. Say Y when you want to support this frontend. | ||
| 422 | |||
| 423 | comment "Tools to develop new frontends" | ||
| 424 | |||
| 425 | config DVB_DUMMY_FE | ||
| 426 | tristate "Dummy frontend driver" | ||
| 427 | default n | ||
| 428 | |||
| 429 | config DVB_AF9013 | ||
| 430 | tristate "Afatech AF9013 demodulator" | ||
| 431 | depends on DVB_CORE && I2C | ||
| 432 | default m if DVB_FE_CUSTOMISE | ||
| 433 | help | ||
| 434 | Say Y when you want to support this frontend. | ||
| 388 | endmenu | 435 | endmenu |
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 028da55611c0..aba79f4a63a7 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
| @@ -48,3 +48,10 @@ obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o | |||
| 48 | obj-$(CONFIG_DVB_AU8522) += au8522.o | 48 | obj-$(CONFIG_DVB_AU8522) += au8522.o |
| 49 | obj-$(CONFIG_DVB_TDA10048) += tda10048.o | 49 | obj-$(CONFIG_DVB_TDA10048) += tda10048.o |
| 50 | obj-$(CONFIG_DVB_S5H1411) += s5h1411.o | 50 | obj-$(CONFIG_DVB_S5H1411) += s5h1411.o |
| 51 | obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o | ||
| 52 | obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o | ||
| 53 | obj-$(CONFIG_DVB_AF9013) += af9013.o | ||
| 54 | obj-$(CONFIG_DVB_CX24116) += cx24116.o | ||
| 55 | obj-$(CONFIG_DVB_SI21XX) += si21xx.o | ||
| 56 | obj-$(CONFIG_DVB_STV0288) += stv0288.o | ||
| 57 | obj-$(CONFIG_DVB_STB6000) += stb6000.o | ||
diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c new file mode 100644 index 000000000000..21c1060cf10e --- /dev/null +++ b/drivers/media/dvb/frontends/af9013.c | |||
| @@ -0,0 +1,1685 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * Thanks to Afatech who kindly provided information. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/moduleparam.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | #include <linux/string.h> | ||
| 30 | #include <linux/slab.h> | ||
| 31 | #include <linux/firmware.h> | ||
| 32 | |||
| 33 | #include "dvb_frontend.h" | ||
| 34 | #include "af9013_priv.h" | ||
| 35 | #include "af9013.h" | ||
| 36 | |||
| 37 | int af9013_debug; | ||
| 38 | |||
| 39 | struct af9013_state { | ||
| 40 | struct i2c_adapter *i2c; | ||
| 41 | struct dvb_frontend frontend; | ||
| 42 | |||
| 43 | struct af9013_config config; | ||
| 44 | |||
| 45 | u16 signal_strength; | ||
| 46 | u32 ber; | ||
| 47 | u32 ucblocks; | ||
| 48 | u16 snr; | ||
| 49 | u32 frequency; | ||
| 50 | unsigned long next_statistics_check; | ||
| 51 | }; | ||
| 52 | |||
| 53 | static u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; | ||
| 54 | |||
| 55 | static int af9013_write_regs(struct af9013_state *state, u8 mbox, u16 reg, | ||
| 56 | u8 *val, u8 len) | ||
| 57 | { | ||
| 58 | u8 buf[3+len]; | ||
| 59 | struct i2c_msg msg = { | ||
| 60 | .addr = state->config.demod_address, | ||
| 61 | .flags = 0, | ||
| 62 | .len = sizeof(buf), | ||
| 63 | .buf = buf }; | ||
| 64 | |||
| 65 | buf[0] = reg >> 8; | ||
| 66 | buf[1] = reg & 0xff; | ||
| 67 | buf[2] = mbox; | ||
| 68 | memcpy(&buf[3], val, len); | ||
| 69 | |||
| 70 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | ||
| 71 | warn("I2C write failed reg:%04x len:%d", reg, len); | ||
| 72 | return -EREMOTEIO; | ||
| 73 | } | ||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | static int af9013_write_ofdm_regs(struct af9013_state *state, u16 reg, u8 *val, | ||
| 78 | u8 len) | ||
| 79 | { | ||
| 80 | u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(0 << 6)|(0 << 7); | ||
| 81 | return af9013_write_regs(state, mbox, reg, val, len); | ||
| 82 | } | ||
| 83 | |||
| 84 | static int af9013_write_ofsm_regs(struct af9013_state *state, u16 reg, u8 *val, | ||
| 85 | u8 len) | ||
| 86 | { | ||
| 87 | u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(1 << 6)|(1 << 7); | ||
| 88 | return af9013_write_regs(state, mbox, reg, val, len); | ||
| 89 | } | ||
| 90 | |||
| 91 | /* write single register */ | ||
| 92 | static int af9013_write_reg(struct af9013_state *state, u16 reg, u8 val) | ||
| 93 | { | ||
| 94 | return af9013_write_ofdm_regs(state, reg, &val, 1); | ||
| 95 | } | ||
| 96 | |||
| 97 | /* read single register */ | ||
| 98 | static int af9013_read_reg(struct af9013_state *state, u16 reg, u8 *val) | ||
| 99 | { | ||
| 100 | u8 obuf[3] = { reg >> 8, reg & 0xff, 0 }; | ||
| 101 | u8 ibuf[1]; | ||
| 102 | struct i2c_msg msg[2] = { | ||
| 103 | { | ||
| 104 | .addr = state->config.demod_address, | ||
| 105 | .flags = 0, | ||
| 106 | .len = sizeof(obuf), | ||
| 107 | .buf = obuf | ||
| 108 | }, { | ||
| 109 | .addr = state->config.demod_address, | ||
| 110 | .flags = I2C_M_RD, | ||
| 111 | .len = sizeof(ibuf), | ||
| 112 | .buf = ibuf | ||
| 113 | } | ||
| 114 | }; | ||
| 115 | |||
| 116 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | ||
| 117 | warn("I2C read failed reg:%04x", reg); | ||
| 118 | return -EREMOTEIO; | ||
| 119 | } | ||
| 120 | *val = ibuf[0]; | ||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | static int af9013_write_reg_bits(struct af9013_state *state, u16 reg, u8 pos, | ||
| 125 | u8 len, u8 val) | ||
| 126 | { | ||
| 127 | int ret; | ||
| 128 | u8 tmp, mask; | ||
| 129 | |||
| 130 | ret = af9013_read_reg(state, reg, &tmp); | ||
| 131 | if (ret) | ||
| 132 | return ret; | ||
| 133 | |||
| 134 | mask = regmask[len - 1] << pos; | ||
| 135 | tmp = (tmp & ~mask) | ((val << pos) & mask); | ||
| 136 | |||
| 137 | return af9013_write_reg(state, reg, tmp); | ||
| 138 | } | ||
| 139 | |||
| 140 | static int af9013_read_reg_bits(struct af9013_state *state, u16 reg, u8 pos, | ||
| 141 | u8 len, u8 *val) | ||
| 142 | { | ||
| 143 | int ret; | ||
| 144 | u8 tmp; | ||
| 145 | |||
| 146 | ret = af9013_read_reg(state, reg, &tmp); | ||
| 147 | if (ret) | ||
| 148 | return ret; | ||
| 149 | *val = (tmp >> pos) & regmask[len - 1]; | ||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval) | ||
| 154 | { | ||
| 155 | int ret; | ||
| 156 | u8 pos; | ||
| 157 | u16 addr; | ||
| 158 | deb_info("%s: gpio:%d gpioval:%02x\n", __func__, gpio, gpioval); | ||
| 159 | |||
| 160 | /* GPIO0 & GPIO1 0xd735 | ||
| 161 | GPIO2 & GPIO3 0xd736 */ | ||
| 162 | |||
| 163 | switch (gpio) { | ||
| 164 | case 0: | ||
| 165 | case 1: | ||
| 166 | addr = 0xd735; | ||
| 167 | break; | ||
| 168 | case 2: | ||
| 169 | case 3: | ||
| 170 | addr = 0xd736; | ||
| 171 | break; | ||
| 172 | |||
| 173 | default: | ||
| 174 | err("invalid gpio:%d\n", gpio); | ||
| 175 | ret = -EINVAL; | ||
| 176 | goto error; | ||
| 177 | }; | ||
| 178 | |||
| 179 | switch (gpio) { | ||
| 180 | case 0: | ||
| 181 | case 2: | ||
| 182 | pos = 0; | ||
| 183 | break; | ||
| 184 | case 1: | ||
| 185 | case 3: | ||
| 186 | default: | ||
| 187 | pos = 4; | ||
| 188 | break; | ||
| 189 | }; | ||
| 190 | |||
| 191 | ret = af9013_write_reg_bits(state, addr, pos, 4, gpioval); | ||
| 192 | |||
| 193 | error: | ||
| 194 | return ret; | ||
| 195 | } | ||
| 196 | |||
| 197 | static u32 af913_div(u32 a, u32 b, u32 x) | ||
| 198 | { | ||
| 199 | u32 r = 0, c = 0, i; | ||
| 200 | deb_info("%s: a:%d b:%d x:%d\n", __func__, a, b, x); | ||
| 201 | |||
| 202 | if (a > b) { | ||
| 203 | c = a / b; | ||
| 204 | a = a - c * b; | ||
| 205 | } | ||
| 206 | |||
| 207 | for (i = 0; i < x; i++) { | ||
| 208 | if (a >= b) { | ||
| 209 | r += 1; | ||
| 210 | a -= b; | ||
| 211 | } | ||
| 212 | a <<= 1; | ||
| 213 | r <<= 1; | ||
| 214 | } | ||
| 215 | r = (c << (u32)x) + r; | ||
| 216 | |||
| 217 | deb_info("%s: a:%d b:%d x:%d r:%d r:%x\n", __func__, a, b, x, r, r); | ||
| 218 | return r; | ||
| 219 | } | ||
| 220 | |||
| 221 | static int af9013_set_coeff(struct af9013_state *state, fe_bandwidth_t bw) | ||
| 222 | { | ||
| 223 | int ret = 0; | ||
| 224 | u8 i = 0; | ||
| 225 | u8 buf[24]; | ||
| 226 | u32 ns_coeff1_2048nu; | ||
| 227 | u32 ns_coeff1_8191nu; | ||
| 228 | u32 ns_coeff1_8192nu; | ||
| 229 | u32 ns_coeff1_8193nu; | ||
| 230 | u32 ns_coeff2_2k; | ||
| 231 | u32 ns_coeff2_8k; | ||
| 232 | |||
| 233 | deb_info("%s: adc_clock:%d bw:%d\n", __func__, | ||
| 234 | state->config.adc_clock, bw); | ||
| 235 | |||
| 236 | switch (state->config.adc_clock) { | ||
| 237 | case 28800: /* 28.800 MHz */ | ||
| 238 | switch (bw) { | ||
| 239 | case BANDWIDTH_6_MHZ: | ||
| 240 | ns_coeff1_2048nu = 0x01e79e7a; | ||
| 241 | ns_coeff1_8191nu = 0x0079eb6e; | ||
| 242 | ns_coeff1_8192nu = 0x0079e79e; | ||
| 243 | ns_coeff1_8193nu = 0x0079e3cf; | ||
| 244 | ns_coeff2_2k = 0x00f3cf3d; | ||
| 245 | ns_coeff2_8k = 0x003cf3cf; | ||
| 246 | break; | ||
| 247 | case BANDWIDTH_7_MHZ: | ||
| 248 | ns_coeff1_2048nu = 0x0238e38e; | ||
| 249 | ns_coeff1_8191nu = 0x008e3d55; | ||
| 250 | ns_coeff1_8192nu = 0x008e38e4; | ||
| 251 | ns_coeff1_8193nu = 0x008e3472; | ||
| 252 | ns_coeff2_2k = 0x011c71c7; | ||
| 253 | ns_coeff2_8k = 0x00471c72; | ||
| 254 | break; | ||
| 255 | case BANDWIDTH_8_MHZ: | ||
| 256 | ns_coeff1_2048nu = 0x028a28a3; | ||
| 257 | ns_coeff1_8191nu = 0x00a28f3d; | ||
| 258 | ns_coeff1_8192nu = 0x00a28a29; | ||
| 259 | ns_coeff1_8193nu = 0x00a28514; | ||
| 260 | ns_coeff2_2k = 0x01451451; | ||
| 261 | ns_coeff2_8k = 0x00514514; | ||
| 262 | break; | ||
| 263 | default: | ||
| 264 | ret = -EINVAL; | ||
| 265 | } | ||
| 266 | break; | ||
| 267 | case 20480: /* 20.480 MHz */ | ||
| 268 | switch (bw) { | ||
| 269 | case BANDWIDTH_6_MHZ: | ||
| 270 | ns_coeff1_2048nu = 0x02adb6dc; | ||
| 271 | ns_coeff1_8191nu = 0x00ab7313; | ||
| 272 | ns_coeff1_8192nu = 0x00ab6db7; | ||
| 273 | ns_coeff1_8193nu = 0x00ab685c; | ||
| 274 | ns_coeff2_2k = 0x0156db6e; | ||
| 275 | ns_coeff2_8k = 0x0055b6dc; | ||
| 276 | break; | ||
| 277 | case BANDWIDTH_7_MHZ: | ||
| 278 | ns_coeff1_2048nu = 0x03200001; | ||
| 279 | ns_coeff1_8191nu = 0x00c80640; | ||
| 280 | ns_coeff1_8192nu = 0x00c80000; | ||
| 281 | ns_coeff1_8193nu = 0x00c7f9c0; | ||
| 282 | ns_coeff2_2k = 0x01900000; | ||
| 283 | ns_coeff2_8k = 0x00640000; | ||
| 284 | break; | ||
| 285 | case BANDWIDTH_8_MHZ: | ||
| 286 | ns_coeff1_2048nu = 0x03924926; | ||
| 287 | ns_coeff1_8191nu = 0x00e4996e; | ||
| 288 | ns_coeff1_8192nu = 0x00e49249; | ||
| 289 | ns_coeff1_8193nu = 0x00e48b25; | ||
| 290 | ns_coeff2_2k = 0x01c92493; | ||
| 291 | ns_coeff2_8k = 0x00724925; | ||
| 292 | break; | ||
| 293 | default: | ||
| 294 | ret = -EINVAL; | ||
| 295 | } | ||
| 296 | break; | ||
| 297 | case 28000: /* 28.000 MHz */ | ||
| 298 | switch (bw) { | ||
| 299 | case BANDWIDTH_6_MHZ: | ||
| 300 | ns_coeff1_2048nu = 0x01f58d10; | ||
| 301 | ns_coeff1_8191nu = 0x007d672f; | ||
| 302 | ns_coeff1_8192nu = 0x007d6344; | ||
| 303 | ns_coeff1_8193nu = 0x007d5f59; | ||
| 304 | ns_coeff2_2k = 0x00fac688; | ||
| 305 | ns_coeff2_8k = 0x003eb1a2; | ||
| 306 | break; | ||
| 307 | case BANDWIDTH_7_MHZ: | ||
| 308 | ns_coeff1_2048nu = 0x02492492; | ||
| 309 | ns_coeff1_8191nu = 0x00924db7; | ||
| 310 | ns_coeff1_8192nu = 0x00924925; | ||
| 311 | ns_coeff1_8193nu = 0x00924492; | ||
| 312 | ns_coeff2_2k = 0x01249249; | ||
| 313 | ns_coeff2_8k = 0x00492492; | ||
| 314 | break; | ||
| 315 | case BANDWIDTH_8_MHZ: | ||
| 316 | ns_coeff1_2048nu = 0x029cbc15; | ||
| 317 | ns_coeff1_8191nu = 0x00a7343f; | ||
| 318 | ns_coeff1_8192nu = 0x00a72f05; | ||
| 319 | ns_coeff1_8193nu = 0x00a729cc; | ||
| 320 | ns_coeff2_2k = 0x014e5e0a; | ||
| 321 | ns_coeff2_8k = 0x00539783; | ||
| 322 | break; | ||
| 323 | default: | ||
| 324 | ret = -EINVAL; | ||
| 325 | } | ||
| 326 | break; | ||
| 327 | case 25000: /* 25.000 MHz */ | ||
| 328 | switch (bw) { | ||
| 329 | case BANDWIDTH_6_MHZ: | ||
| 330 | ns_coeff1_2048nu = 0x0231bcb5; | ||
| 331 | ns_coeff1_8191nu = 0x008c7391; | ||
| 332 | ns_coeff1_8192nu = 0x008c6f2d; | ||
| 333 | ns_coeff1_8193nu = 0x008c6aca; | ||
| 334 | ns_coeff2_2k = 0x0118de5b; | ||
| 335 | ns_coeff2_8k = 0x00463797; | ||
| 336 | break; | ||
| 337 | case BANDWIDTH_7_MHZ: | ||
| 338 | ns_coeff1_2048nu = 0x028f5c29; | ||
| 339 | ns_coeff1_8191nu = 0x00a3dc29; | ||
| 340 | ns_coeff1_8192nu = 0x00a3d70a; | ||
| 341 | ns_coeff1_8193nu = 0x00a3d1ec; | ||
| 342 | ns_coeff2_2k = 0x0147ae14; | ||
| 343 | ns_coeff2_8k = 0x0051eb85; | ||
| 344 | break; | ||
| 345 | case BANDWIDTH_8_MHZ: | ||
| 346 | ns_coeff1_2048nu = 0x02ecfb9d; | ||
| 347 | ns_coeff1_8191nu = 0x00bb44c1; | ||
| 348 | ns_coeff1_8192nu = 0x00bb3ee7; | ||
| 349 | ns_coeff1_8193nu = 0x00bb390d; | ||
| 350 | ns_coeff2_2k = 0x01767dce; | ||
| 351 | ns_coeff2_8k = 0x005d9f74; | ||
| 352 | break; | ||
| 353 | default: | ||
| 354 | ret = -EINVAL; | ||
| 355 | } | ||
| 356 | break; | ||
| 357 | default: | ||
| 358 | err("invalid xtal"); | ||
| 359 | return -EINVAL; | ||
| 360 | } | ||
| 361 | if (ret) { | ||
| 362 | err("invalid bandwidth"); | ||
| 363 | return ret; | ||
| 364 | } | ||
| 365 | |||
| 366 | buf[i++] = (u8) ((ns_coeff1_2048nu & 0x03000000) >> 24); | ||
| 367 | buf[i++] = (u8) ((ns_coeff1_2048nu & 0x00ff0000) >> 16); | ||
| 368 | buf[i++] = (u8) ((ns_coeff1_2048nu & 0x0000ff00) >> 8); | ||
| 369 | buf[i++] = (u8) ((ns_coeff1_2048nu & 0x000000ff)); | ||
| 370 | buf[i++] = (u8) ((ns_coeff2_2k & 0x01c00000) >> 22); | ||
| 371 | buf[i++] = (u8) ((ns_coeff2_2k & 0x003fc000) >> 14); | ||
| 372 | buf[i++] = (u8) ((ns_coeff2_2k & 0x00003fc0) >> 6); | ||
| 373 | buf[i++] = (u8) ((ns_coeff2_2k & 0x0000003f)); | ||
| 374 | buf[i++] = (u8) ((ns_coeff1_8191nu & 0x03000000) >> 24); | ||
| 375 | buf[i++] = (u8) ((ns_coeff1_8191nu & 0x00ffc000) >> 16); | ||
| 376 | buf[i++] = (u8) ((ns_coeff1_8191nu & 0x0000ff00) >> 8); | ||
| 377 | buf[i++] = (u8) ((ns_coeff1_8191nu & 0x000000ff)); | ||
| 378 | buf[i++] = (u8) ((ns_coeff1_8192nu & 0x03000000) >> 24); | ||
| 379 | buf[i++] = (u8) ((ns_coeff1_8192nu & 0x00ffc000) >> 16); | ||
| 380 | buf[i++] = (u8) ((ns_coeff1_8192nu & 0x0000ff00) >> 8); | ||
| 381 | buf[i++] = (u8) ((ns_coeff1_8192nu & 0x000000ff)); | ||
| 382 | buf[i++] = (u8) ((ns_coeff1_8193nu & 0x03000000) >> 24); | ||
| 383 | buf[i++] = (u8) ((ns_coeff1_8193nu & 0x00ffc000) >> 16); | ||
| 384 | buf[i++] = (u8) ((ns_coeff1_8193nu & 0x0000ff00) >> 8); | ||
| 385 | buf[i++] = (u8) ((ns_coeff1_8193nu & 0x000000ff)); | ||
| 386 | buf[i++] = (u8) ((ns_coeff2_8k & 0x01c00000) >> 22); | ||
| 387 | buf[i++] = (u8) ((ns_coeff2_8k & 0x003fc000) >> 14); | ||
| 388 | buf[i++] = (u8) ((ns_coeff2_8k & 0x00003fc0) >> 6); | ||
| 389 | buf[i++] = (u8) ((ns_coeff2_8k & 0x0000003f)); | ||
| 390 | |||
| 391 | deb_info("%s: coeff:", __func__); | ||
| 392 | debug_dump(buf, sizeof(buf), deb_info); | ||
| 393 | |||
| 394 | /* program */ | ||
| 395 | for (i = 0; i < sizeof(buf); i++) { | ||
| 396 | ret = af9013_write_reg(state, 0xae00 + i, buf[i]); | ||
| 397 | if (ret) | ||
| 398 | break; | ||
| 399 | } | ||
| 400 | |||
| 401 | return ret; | ||
| 402 | } | ||
| 403 | |||
| 404 | static int af9013_set_adc_ctrl(struct af9013_state *state) | ||
| 405 | { | ||
| 406 | int ret; | ||
| 407 | u8 buf[3], tmp, i; | ||
| 408 | u32 adc_cw; | ||
| 409 | |||
| 410 | deb_info("%s: adc_clock:%d\n", __func__, state->config.adc_clock); | ||
| 411 | |||
| 412 | /* adc frequency type */ | ||
| 413 | switch (state->config.adc_clock) { | ||
| 414 | case 28800: /* 28.800 MHz */ | ||
| 415 | tmp = 0; | ||
| 416 | break; | ||
| 417 | case 20480: /* 20.480 MHz */ | ||
| 418 | tmp = 1; | ||
| 419 | break; | ||
| 420 | case 28000: /* 28.000 MHz */ | ||
| 421 | tmp = 2; | ||
| 422 | break; | ||
| 423 | case 25000: /* 25.000 MHz */ | ||
| 424 | tmp = 3; | ||
| 425 | break; | ||
| 426 | default: | ||
| 427 | err("invalid xtal"); | ||
| 428 | return -EINVAL; | ||
| 429 | } | ||
| 430 | |||
| 431 | adc_cw = af913_div(state->config.adc_clock*1000, 1000000ul, 19ul); | ||
| 432 | |||
| 433 | buf[0] = (u8) ((adc_cw & 0x000000ff)); | ||
| 434 | buf[1] = (u8) ((adc_cw & 0x0000ff00) >> 8); | ||
| 435 | buf[2] = (u8) ((adc_cw & 0x00ff0000) >> 16); | ||
| 436 | |||
| 437 | deb_info("%s: adc_cw:", __func__); | ||
| 438 | debug_dump(buf, sizeof(buf), deb_info); | ||
| 439 | |||
| 440 | /* program */ | ||
| 441 | for (i = 0; i < sizeof(buf); i++) { | ||
| 442 | ret = af9013_write_reg(state, 0xd180 + i, buf[i]); | ||
| 443 | if (ret) | ||
| 444 | goto error; | ||
| 445 | } | ||
| 446 | ret = af9013_write_reg_bits(state, 0x9bd2, 0, 4, tmp); | ||
| 447 | error: | ||
| 448 | return ret; | ||
| 449 | } | ||
| 450 | |||
| 451 | static int af9013_set_freq_ctrl(struct af9013_state *state, fe_bandwidth_t bw) | ||
| 452 | { | ||
| 453 | int ret; | ||
| 454 | u16 addr; | ||
| 455 | u8 buf[3], i, j; | ||
| 456 | u32 adc_freq, freq_cw; | ||
| 457 | s8 bfs_spec_inv; | ||
| 458 | int if_sample_freq; | ||
| 459 | |||
| 460 | for (j = 0; j < 3; j++) { | ||
| 461 | if (j == 0) { | ||
| 462 | addr = 0xd140; /* fcw normal */ | ||
| 463 | bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1; | ||
| 464 | } else if (j == 1) { | ||
| 465 | addr = 0x9be7; /* fcw dummy ram */ | ||
| 466 | bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1; | ||
| 467 | } else { | ||
| 468 | addr = 0x9bea; /* fcw inverted */ | ||
| 469 | bfs_spec_inv = state->config.rf_spec_inv ? 1 : -1; | ||
| 470 | } | ||
| 471 | |||
| 472 | adc_freq = state->config.adc_clock * 1000; | ||
| 473 | if_sample_freq = state->config.tuner_if * 1000; | ||
| 474 | |||
| 475 | /* TDA18271 uses different sampling freq for every bw */ | ||
| 476 | if (state->config.tuner == AF9013_TUNER_TDA18271) { | ||
| 477 | switch (bw) { | ||
| 478 | case BANDWIDTH_6_MHZ: | ||
| 479 | if_sample_freq = 3300000; /* 3.3 MHz */ | ||
| 480 | break; | ||
| 481 | case BANDWIDTH_7_MHZ: | ||
| 482 | if_sample_freq = 3800000; /* 3.8 MHz */ | ||
| 483 | break; | ||
| 484 | case BANDWIDTH_8_MHZ: | ||
| 485 | default: | ||
| 486 | if_sample_freq = 4300000; /* 4.3 MHz */ | ||
| 487 | break; | ||
| 488 | } | ||
| 489 | } | ||
| 490 | |||
| 491 | while (if_sample_freq > (adc_freq / 2)) | ||
| 492 | if_sample_freq = if_sample_freq - adc_freq; | ||
| 493 | |||
| 494 | if (if_sample_freq >= 0) | ||
| 495 | bfs_spec_inv = bfs_spec_inv * (-1); | ||
| 496 | else | ||
| 497 | if_sample_freq = if_sample_freq * (-1); | ||
| 498 | |||
| 499 | freq_cw = af913_div(if_sample_freq, adc_freq, 23ul); | ||
| 500 | |||
| 501 | if (bfs_spec_inv == -1) | ||
| 502 | freq_cw = 0x00800000 - freq_cw; | ||
| 503 | |||
| 504 | buf[0] = (u8) ((freq_cw & 0x000000ff)); | ||
| 505 | buf[1] = (u8) ((freq_cw & 0x0000ff00) >> 8); | ||
| 506 | buf[2] = (u8) ((freq_cw & 0x007f0000) >> 16); | ||
| 507 | |||
| 508 | |||
| 509 | deb_info("%s: freq_cw:", __func__); | ||
| 510 | debug_dump(buf, sizeof(buf), deb_info); | ||
| 511 | |||
| 512 | /* program */ | ||
| 513 | for (i = 0; i < sizeof(buf); i++) { | ||
| 514 | ret = af9013_write_reg(state, addr++, buf[i]); | ||
| 515 | if (ret) | ||
| 516 | goto error; | ||
| 517 | } | ||
| 518 | } | ||
| 519 | error: | ||
| 520 | return ret; | ||
| 521 | } | ||
| 522 | |||
| 523 | static int af9013_set_ofdm_params(struct af9013_state *state, | ||
| 524 | struct dvb_ofdm_parameters *params, u8 *auto_mode) | ||
| 525 | { | ||
| 526 | int ret; | ||
| 527 | u8 i, buf[3] = {0, 0, 0}; | ||
| 528 | *auto_mode = 0; /* set if parameters are requested to auto set */ | ||
| 529 | |||
| 530 | switch (params->transmission_mode) { | ||
| 531 | case TRANSMISSION_MODE_AUTO: | ||
| 532 | *auto_mode = 1; | ||
| 533 | case TRANSMISSION_MODE_2K: | ||
| 534 | break; | ||
| 535 | case TRANSMISSION_MODE_8K: | ||
| 536 | buf[0] |= (1 << 0); | ||
| 537 | break; | ||
| 538 | default: | ||
| 539 | return -EINVAL; | ||
| 540 | } | ||
| 541 | |||
| 542 | switch (params->guard_interval) { | ||
| 543 | case GUARD_INTERVAL_AUTO: | ||
| 544 | *auto_mode = 1; | ||
| 545 | case GUARD_INTERVAL_1_32: | ||
| 546 | break; | ||
| 547 | case GUARD_INTERVAL_1_16: | ||
| 548 | buf[0] |= (1 << 2); | ||
| 549 | break; | ||
| 550 | case GUARD_INTERVAL_1_8: | ||
| 551 | buf[0] |= (2 << 2); | ||
| 552 | break; | ||
| 553 | case GUARD_INTERVAL_1_4: | ||
| 554 | buf[0] |= (3 << 2); | ||
| 555 | break; | ||
| 556 | default: | ||
| 557 | return -EINVAL; | ||
| 558 | } | ||
| 559 | |||
| 560 | switch (params->hierarchy_information) { | ||
| 561 | case HIERARCHY_AUTO: | ||
| 562 | *auto_mode = 1; | ||
| 563 | case HIERARCHY_NONE: | ||
| 564 | break; | ||
| 565 | case HIERARCHY_1: | ||
| 566 | buf[0] |= (1 << 4); | ||
| 567 | break; | ||
| 568 | case HIERARCHY_2: | ||
| 569 | buf[0] |= (2 << 4); | ||
| 570 | break; | ||
| 571 | case HIERARCHY_4: | ||
| 572 | buf[0] |= (3 << 4); | ||
| 573 | break; | ||
| 574 | default: | ||
| 575 | return -EINVAL; | ||
| 576 | }; | ||
| 577 | |||
| 578 | switch (params->constellation) { | ||
| 579 | case QAM_AUTO: | ||
| 580 | *auto_mode = 1; | ||
| 581 | case QPSK: | ||
| 582 | break; | ||
| 583 | case QAM_16: | ||
| 584 | buf[1] |= (1 << 6); | ||
| 585 | break; | ||
| 586 | case QAM_64: | ||
| 587 | buf[1] |= (2 << 6); | ||
| 588 | break; | ||
| 589 | default: | ||
| 590 | return -EINVAL; | ||
| 591 | } | ||
| 592 | |||
| 593 | /* Use HP. How and which case we can switch to LP? */ | ||
| 594 | buf[1] |= (1 << 4); | ||
| 595 | |||
| 596 | switch (params->code_rate_HP) { | ||
| 597 | case FEC_AUTO: | ||
| 598 | *auto_mode = 1; | ||
| 599 | case FEC_1_2: | ||
| 600 | break; | ||
| 601 | case FEC_2_3: | ||
| 602 | buf[2] |= (1 << 0); | ||
| 603 | break; | ||
| 604 | case FEC_3_4: | ||
| 605 | buf[2] |= (2 << 0); | ||
| 606 | break; | ||
| 607 | case FEC_5_6: | ||
| 608 | buf[2] |= (3 << 0); | ||
| 609 | break; | ||
| 610 | case FEC_7_8: | ||
| 611 | buf[2] |= (4 << 0); | ||
| 612 | break; | ||
| 613 | default: | ||
| 614 | return -EINVAL; | ||
| 615 | } | ||
| 616 | |||
| 617 | switch (params->code_rate_LP) { | ||
| 618 | case FEC_AUTO: | ||
| 619 | /* if HIERARCHY_NONE and FEC_NONE then LP FEC is set to FEC_AUTO | ||
| 620 | by dvb_frontend.c for compatibility */ | ||
| 621 | if (params->hierarchy_information != HIERARCHY_NONE) | ||
| 622 | *auto_mode = 1; | ||
| 623 | case FEC_1_2: | ||
| 624 | break; | ||
| 625 | case FEC_2_3: | ||
| 626 | buf[2] |= (1 << 3); | ||
| 627 | break; | ||
| 628 | case FEC_3_4: | ||
| 629 | buf[2] |= (2 << 3); | ||
| 630 | break; | ||
| 631 | case FEC_5_6: | ||
| 632 | buf[2] |= (3 << 3); | ||
| 633 | break; | ||
| 634 | case FEC_7_8: | ||
| 635 | buf[2] |= (4 << 3); | ||
| 636 | break; | ||
| 637 | case FEC_NONE: | ||
| 638 | if (params->hierarchy_information == HIERARCHY_AUTO) | ||
| 639 | break; | ||
| 640 | default: | ||
| 641 | return -EINVAL; | ||
| 642 | } | ||
| 643 | |||
| 644 | switch (params->bandwidth) { | ||
| 645 | case BANDWIDTH_6_MHZ: | ||
| 646 | break; | ||
| 647 | case BANDWIDTH_7_MHZ: | ||
| 648 | buf[1] |= (1 << 2); | ||
| 649 | break; | ||
| 650 | case BANDWIDTH_8_MHZ: | ||
| 651 | buf[1] |= (2 << 2); | ||
| 652 | break; | ||
| 653 | default: | ||
| 654 | return -EINVAL; | ||
| 655 | } | ||
| 656 | |||
| 657 | /* program */ | ||
| 658 | for (i = 0; i < sizeof(buf); i++) { | ||
| 659 | ret = af9013_write_reg(state, 0xd3c0 + i, buf[i]); | ||
| 660 | if (ret) | ||
| 661 | break; | ||
| 662 | } | ||
| 663 | |||
| 664 | return ret; | ||
| 665 | } | ||
| 666 | |||
| 667 | static int af9013_reset(struct af9013_state *state, u8 sleep) | ||
| 668 | { | ||
| 669 | int ret; | ||
| 670 | u8 tmp, i; | ||
| 671 | deb_info("%s\n", __func__); | ||
| 672 | |||
| 673 | /* enable OFDM reset */ | ||
| 674 | ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 1); | ||
| 675 | if (ret) | ||
| 676 | goto error; | ||
| 677 | |||
| 678 | /* start reset mechanism */ | ||
| 679 | ret = af9013_write_reg(state, 0xaeff, 1); | ||
| 680 | if (ret) | ||
| 681 | goto error; | ||
| 682 | |||
| 683 | /* reset is done when bit 1 is set */ | ||
| 684 | for (i = 0; i < 150; i++) { | ||
| 685 | ret = af9013_read_reg_bits(state, 0xd417, 1, 1, &tmp); | ||
| 686 | if (ret) | ||
| 687 | goto error; | ||
| 688 | if (tmp) | ||
| 689 | break; /* reset done */ | ||
| 690 | msleep(10); | ||
| 691 | } | ||
| 692 | if (!tmp) | ||
| 693 | return -ETIMEDOUT; | ||
| 694 | |||
| 695 | /* don't clear reset when going to sleep */ | ||
| 696 | if (!sleep) { | ||
| 697 | /* clear OFDM reset */ | ||
| 698 | ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0); | ||
| 699 | if (ret) | ||
| 700 | goto error; | ||
| 701 | |||
| 702 | /* disable OFDM reset */ | ||
| 703 | ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0); | ||
| 704 | } | ||
| 705 | error: | ||
| 706 | return ret; | ||
| 707 | } | ||
| 708 | |||
| 709 | static int af9013_power_ctrl(struct af9013_state *state, u8 onoff) | ||
| 710 | { | ||
| 711 | int ret; | ||
| 712 | deb_info("%s: onoff:%d\n", __func__, onoff); | ||
| 713 | |||
| 714 | if (onoff) { | ||
| 715 | /* power on */ | ||
| 716 | ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 0); | ||
| 717 | if (ret) | ||
| 718 | goto error; | ||
| 719 | ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0); | ||
| 720 | if (ret) | ||
| 721 | goto error; | ||
| 722 | ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0); | ||
| 723 | } else { | ||
| 724 | /* power off */ | ||
| 725 | ret = af9013_reset(state, 1); | ||
| 726 | if (ret) | ||
| 727 | goto error; | ||
| 728 | ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 1); | ||
| 729 | } | ||
| 730 | error: | ||
| 731 | return ret; | ||
| 732 | } | ||
| 733 | |||
| 734 | static int af9013_lock_led(struct af9013_state *state, u8 onoff) | ||
| 735 | { | ||
| 736 | deb_info("%s: onoff:%d\n", __func__, onoff); | ||
| 737 | |||
| 738 | return af9013_write_reg_bits(state, 0xd730, 0, 1, onoff); | ||
| 739 | } | ||
| 740 | |||
| 741 | static int af9013_set_frontend(struct dvb_frontend *fe, | ||
| 742 | struct dvb_frontend_parameters *params) | ||
| 743 | { | ||
| 744 | struct af9013_state *state = fe->demodulator_priv; | ||
| 745 | int ret; | ||
| 746 | u8 auto_mode; /* auto set TPS */ | ||
| 747 | |||
| 748 | deb_info("%s: freq:%d bw:%d\n", __func__, params->frequency, | ||
| 749 | params->u.ofdm.bandwidth); | ||
| 750 | |||
| 751 | state->frequency = params->frequency; | ||
| 752 | |||
| 753 | /* program CFOE coefficients */ | ||
| 754 | ret = af9013_set_coeff(state, params->u.ofdm.bandwidth); | ||
| 755 | if (ret) | ||
| 756 | goto error; | ||
| 757 | |||
| 758 | /* program frequency control */ | ||
| 759 | ret = af9013_set_freq_ctrl(state, params->u.ofdm.bandwidth); | ||
| 760 | if (ret) | ||
| 761 | goto error; | ||
| 762 | |||
| 763 | /* clear TPS lock flag (inverted flag) */ | ||
| 764 | ret = af9013_write_reg_bits(state, 0xd330, 3, 1, 1); | ||
| 765 | if (ret) | ||
| 766 | goto error; | ||
| 767 | |||
| 768 | /* clear MPEG2 lock flag */ | ||
| 769 | ret = af9013_write_reg_bits(state, 0xd507, 6, 1, 0); | ||
| 770 | if (ret) | ||
| 771 | goto error; | ||
| 772 | |||
| 773 | /* empty channel function */ | ||
| 774 | ret = af9013_write_reg_bits(state, 0x9bfe, 0, 1, 0); | ||
| 775 | if (ret) | ||
| 776 | goto error; | ||
| 777 | |||
| 778 | /* empty DVB-T channel function */ | ||
| 779 | ret = af9013_write_reg_bits(state, 0x9bc2, 0, 1, 0); | ||
| 780 | if (ret) | ||
| 781 | goto error; | ||
| 782 | |||
| 783 | /* program tuner */ | ||
| 784 | if (fe->ops.tuner_ops.set_params) | ||
| 785 | fe->ops.tuner_ops.set_params(fe, params); | ||
| 786 | |||
| 787 | /* program TPS and bandwidth, check if auto mode needed */ | ||
| 788 | ret = af9013_set_ofdm_params(state, ¶ms->u.ofdm, &auto_mode); | ||
| 789 | if (ret) | ||
| 790 | goto error; | ||
| 791 | |||
| 792 | if (auto_mode) { | ||
| 793 | /* clear easy mode flag */ | ||
| 794 | ret = af9013_write_reg(state, 0xaefd, 0); | ||
| 795 | deb_info("%s: auto TPS\n", __func__); | ||
| 796 | } else { | ||
| 797 | /* set easy mode flag */ | ||
| 798 | ret = af9013_write_reg(state, 0xaefd, 1); | ||
| 799 | if (ret) | ||
| 800 | goto error; | ||
| 801 | ret = af9013_write_reg(state, 0xaefe, 0); | ||
| 802 | deb_info("%s: manual TPS\n", __func__); | ||
| 803 | } | ||
| 804 | if (ret) | ||
| 805 | goto error; | ||
| 806 | |||
| 807 | /* everything is set, lets try to receive channel - OFSM GO! */ | ||
| 808 | ret = af9013_write_reg(state, 0xffff, 0); | ||
| 809 | if (ret) | ||
| 810 | goto error; | ||
| 811 | |||
| 812 | error: | ||
| 813 | return ret; | ||
| 814 | } | ||
| 815 | |||
| 816 | static int af9013_get_frontend(struct dvb_frontend *fe, | ||
| 817 | struct dvb_frontend_parameters *p) | ||
| 818 | { | ||
| 819 | struct af9013_state *state = fe->demodulator_priv; | ||
| 820 | int ret; | ||
| 821 | u8 i, buf[3]; | ||
| 822 | deb_info("%s\n", __func__); | ||
| 823 | |||
| 824 | /* read TPS registers */ | ||
| 825 | for (i = 0; i < 3; i++) { | ||
| 826 | ret = af9013_read_reg(state, 0xd3c0 + i, &buf[i]); | ||
| 827 | if (ret) | ||
| 828 | goto error; | ||
| 829 | } | ||
| 830 | |||
| 831 | switch ((buf[1] >> 6) & 3) { | ||
| 832 | case 0: | ||
| 833 | p->u.ofdm.constellation = QPSK; | ||
| 834 | break; | ||
| 835 | case 1: | ||
| 836 | p->u.ofdm.constellation = QAM_16; | ||
| 837 | break; | ||
| 838 | case 2: | ||
| 839 | p->u.ofdm.constellation = QAM_64; | ||
| 840 | break; | ||
| 841 | } | ||
| 842 | |||
| 843 | switch ((buf[0] >> 0) & 3) { | ||
| 844 | case 0: | ||
| 845 | p->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; | ||
| 846 | break; | ||
| 847 | case 1: | ||
| 848 | p->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; | ||
| 849 | } | ||
| 850 | |||
| 851 | switch ((buf[0] >> 2) & 3) { | ||
| 852 | case 0: | ||
| 853 | p->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; | ||
| 854 | break; | ||
| 855 | case 1: | ||
| 856 | p->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; | ||
| 857 | break; | ||
| 858 | case 2: | ||
| 859 | p->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; | ||
| 860 | break; | ||
| 861 | case 3: | ||
| 862 | p->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; | ||
| 863 | break; | ||
| 864 | } | ||
| 865 | |||
| 866 | switch ((buf[0] >> 4) & 7) { | ||
| 867 | case 0: | ||
| 868 | p->u.ofdm.hierarchy_information = HIERARCHY_NONE; | ||
| 869 | break; | ||
| 870 | case 1: | ||
| 871 | p->u.ofdm.hierarchy_information = HIERARCHY_1; | ||
| 872 | break; | ||
| 873 | case 2: | ||
| 874 | p->u.ofdm.hierarchy_information = HIERARCHY_2; | ||
| 875 | break; | ||
| 876 | case 3: | ||
| 877 | p->u.ofdm.hierarchy_information = HIERARCHY_4; | ||
| 878 | break; | ||
| 879 | } | ||
| 880 | |||
| 881 | switch ((buf[2] >> 0) & 7) { | ||
| 882 | case 0: | ||
| 883 | p->u.ofdm.code_rate_HP = FEC_1_2; | ||
| 884 | break; | ||
| 885 | case 1: | ||
| 886 | p->u.ofdm.code_rate_HP = FEC_2_3; | ||
| 887 | break; | ||
| 888 | case 2: | ||
| 889 | p->u.ofdm.code_rate_HP = FEC_3_4; | ||
| 890 | break; | ||
| 891 | case 3: | ||
| 892 | p->u.ofdm.code_rate_HP = FEC_5_6; | ||
| 893 | break; | ||
| 894 | case 4: | ||
| 895 | p->u.ofdm.code_rate_HP = FEC_7_8; | ||
| 896 | break; | ||
| 897 | } | ||
| 898 | |||
| 899 | switch ((buf[2] >> 3) & 7) { | ||
| 900 | case 0: | ||
| 901 | p->u.ofdm.code_rate_LP = FEC_1_2; | ||
| 902 | break; | ||
| 903 | case 1: | ||
| 904 | p->u.ofdm.code_rate_LP = FEC_2_3; | ||
| 905 | break; | ||
| 906 | case 2: | ||
| 907 | p->u.ofdm.code_rate_LP = FEC_3_4; | ||
| 908 | break; | ||
| 909 | case 3: | ||
| 910 | p->u.ofdm.code_rate_LP = FEC_5_6; | ||
| 911 | break; | ||
| 912 | case 4: | ||
| 913 | p->u.ofdm.code_rate_LP = FEC_7_8; | ||
| 914 | break; | ||
| 915 | } | ||
| 916 | |||
| 917 | switch ((buf[1] >> 2) & 3) { | ||
| 918 | case 0: | ||
| 919 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
| 920 | break; | ||
| 921 | case 1: | ||
| 922 | p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | ||
| 923 | break; | ||
| 924 | case 2: | ||
| 925 | p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | ||
| 926 | break; | ||
| 927 | } | ||
| 928 | |||
| 929 | p->inversion = INVERSION_AUTO; | ||
| 930 | p->frequency = state->frequency; | ||
| 931 | |||
| 932 | error: | ||
| 933 | return ret; | ||
| 934 | } | ||
| 935 | |||
| 936 | static int af9013_update_ber_unc(struct dvb_frontend *fe) | ||
| 937 | { | ||
| 938 | struct af9013_state *state = fe->demodulator_priv; | ||
| 939 | int ret; | ||
| 940 | u8 buf[3], i; | ||
| 941 | u32 error_bit_count = 0; | ||
| 942 | u32 total_bit_count = 0; | ||
| 943 | u32 abort_packet_count = 0; | ||
| 944 | |||
| 945 | state->ber = 0; | ||
| 946 | |||
| 947 | /* check if error bit count is ready */ | ||
| 948 | ret = af9013_read_reg_bits(state, 0xd391, 4, 1, &buf[0]); | ||
| 949 | if (ret) | ||
| 950 | goto error; | ||
| 951 | if (!buf[0]) | ||
| 952 | goto exit; | ||
| 953 | |||
| 954 | /* get RSD packet abort count */ | ||
| 955 | for (i = 0; i < 2; i++) { | ||
| 956 | ret = af9013_read_reg(state, 0xd38a + i, &buf[i]); | ||
| 957 | if (ret) | ||
| 958 | goto error; | ||
| 959 | } | ||
| 960 | abort_packet_count = (buf[1] << 8) + buf[0]; | ||
| 961 | |||
| 962 | /* get error bit count */ | ||
| 963 | for (i = 0; i < 3; i++) { | ||
| 964 | ret = af9013_read_reg(state, 0xd387 + i, &buf[i]); | ||
| 965 | if (ret) | ||
| 966 | goto error; | ||
| 967 | } | ||
| 968 | error_bit_count = (buf[2] << 16) + (buf[1] << 8) + buf[0]; | ||
| 969 | error_bit_count = error_bit_count - abort_packet_count * 8 * 8; | ||
| 970 | |||
| 971 | /* get used RSD counting period (10000 RSD packets used) */ | ||
| 972 | for (i = 0; i < 2; i++) { | ||
| 973 | ret = af9013_read_reg(state, 0xd385 + i, &buf[i]); | ||
| 974 | if (ret) | ||
| 975 | goto error; | ||
| 976 | } | ||
| 977 | total_bit_count = (buf[1] << 8) + buf[0]; | ||
| 978 | total_bit_count = total_bit_count - abort_packet_count; | ||
| 979 | total_bit_count = total_bit_count * 204 * 8; | ||
| 980 | |||
| 981 | if (total_bit_count) | ||
| 982 | state->ber = error_bit_count * 1000000000 / total_bit_count; | ||
| 983 | |||
| 984 | state->ucblocks += abort_packet_count; | ||
| 985 | |||
| 986 | deb_info("%s: err bits:%d total bits:%d abort count:%d\n", __func__, | ||
| 987 | error_bit_count, total_bit_count, abort_packet_count); | ||
| 988 | |||
| 989 | /* set BER counting range */ | ||
| 990 | ret = af9013_write_reg(state, 0xd385, 10000 & 0xff); | ||
| 991 | if (ret) | ||
| 992 | goto error; | ||
| 993 | ret = af9013_write_reg(state, 0xd386, 10000 >> 8); | ||
| 994 | if (ret) | ||
| 995 | goto error; | ||
| 996 | /* reset and start BER counter */ | ||
| 997 | ret = af9013_write_reg_bits(state, 0xd391, 4, 1, 1); | ||
| 998 | if (ret) | ||
| 999 | goto error; | ||
| 1000 | |||
| 1001 | exit: | ||
| 1002 | error: | ||
| 1003 | return ret; | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | static int af9013_update_snr(struct dvb_frontend *fe) | ||
| 1007 | { | ||
| 1008 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1009 | int ret; | ||
| 1010 | u8 buf[3], i, len; | ||
| 1011 | u32 quant = 0; | ||
| 1012 | struct snr_table *snr_table; | ||
| 1013 | |||
| 1014 | /* check if quantizer ready (for snr) */ | ||
| 1015 | ret = af9013_read_reg_bits(state, 0xd2e1, 3, 1, &buf[0]); | ||
| 1016 | if (ret) | ||
| 1017 | goto error; | ||
| 1018 | if (buf[0]) { | ||
| 1019 | /* quantizer ready - read it */ | ||
| 1020 | for (i = 0; i < 3; i++) { | ||
| 1021 | ret = af9013_read_reg(state, 0xd2e3 + i, &buf[i]); | ||
| 1022 | if (ret) | ||
| 1023 | goto error; | ||
| 1024 | } | ||
| 1025 | quant = (buf[2] << 16) + (buf[1] << 8) + buf[0]; | ||
| 1026 | |||
| 1027 | /* read current constellation */ | ||
| 1028 | ret = af9013_read_reg(state, 0xd3c1, &buf[0]); | ||
| 1029 | if (ret) | ||
| 1030 | goto error; | ||
| 1031 | |||
| 1032 | switch ((buf[0] >> 6) & 3) { | ||
| 1033 | case 0: | ||
| 1034 | len = ARRAY_SIZE(qpsk_snr_table); | ||
| 1035 | snr_table = qpsk_snr_table; | ||
| 1036 | break; | ||
| 1037 | case 1: | ||
| 1038 | len = ARRAY_SIZE(qam16_snr_table); | ||
| 1039 | snr_table = qam16_snr_table; | ||
| 1040 | break; | ||
| 1041 | case 2: | ||
| 1042 | len = ARRAY_SIZE(qam64_snr_table); | ||
| 1043 | snr_table = qam64_snr_table; | ||
| 1044 | break; | ||
| 1045 | default: | ||
| 1046 | len = 0; | ||
| 1047 | break; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | if (len) { | ||
| 1051 | for (i = 0; i < len; i++) { | ||
| 1052 | if (quant < snr_table[i].val) { | ||
| 1053 | state->snr = snr_table[i].snr * 10; | ||
| 1054 | break; | ||
| 1055 | } | ||
| 1056 | } | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | /* set quantizer super frame count */ | ||
| 1060 | ret = af9013_write_reg(state, 0xd2e2, 1); | ||
| 1061 | if (ret) | ||
| 1062 | goto error; | ||
| 1063 | |||
| 1064 | /* check quantizer availability */ | ||
| 1065 | for (i = 0; i < 10; i++) { | ||
| 1066 | msleep(10); | ||
| 1067 | ret = af9013_read_reg_bits(state, 0xd2e6, 0, 1, | ||
| 1068 | &buf[0]); | ||
| 1069 | if (ret) | ||
| 1070 | goto error; | ||
| 1071 | if (!buf[0]) | ||
| 1072 | break; | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | /* reset quantizer */ | ||
| 1076 | ret = af9013_write_reg_bits(state, 0xd2e1, 3, 1, 1); | ||
| 1077 | if (ret) | ||
| 1078 | goto error; | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | error: | ||
| 1082 | return ret; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | static int af9013_update_signal_strength(struct dvb_frontend *fe) | ||
| 1086 | { | ||
| 1087 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1088 | int ret; | ||
| 1089 | u8 tmp0; | ||
| 1090 | u8 rf_gain, rf_50, rf_80, if_gain, if_50, if_80; | ||
| 1091 | int signal_strength; | ||
| 1092 | |||
| 1093 | deb_info("%s\n", __func__); | ||
| 1094 | |||
| 1095 | state->signal_strength = 0; | ||
| 1096 | |||
| 1097 | ret = af9013_read_reg_bits(state, 0x9bee, 0, 1, &tmp0); | ||
| 1098 | if (ret) | ||
| 1099 | goto error; | ||
| 1100 | if (tmp0) { | ||
| 1101 | ret = af9013_read_reg(state, 0x9bbd, &rf_50); | ||
| 1102 | if (ret) | ||
| 1103 | goto error; | ||
| 1104 | ret = af9013_read_reg(state, 0x9bd0, &rf_80); | ||
| 1105 | if (ret) | ||
| 1106 | goto error; | ||
| 1107 | ret = af9013_read_reg(state, 0x9be2, &if_50); | ||
| 1108 | if (ret) | ||
| 1109 | goto error; | ||
| 1110 | ret = af9013_read_reg(state, 0x9be4, &if_80); | ||
| 1111 | if (ret) | ||
| 1112 | goto error; | ||
| 1113 | ret = af9013_read_reg(state, 0xd07c, &rf_gain); | ||
| 1114 | if (ret) | ||
| 1115 | goto error; | ||
| 1116 | ret = af9013_read_reg(state, 0xd07d, &if_gain); | ||
| 1117 | if (ret) | ||
| 1118 | goto error; | ||
| 1119 | signal_strength = (0xffff / (9 * (rf_50 + if_50) - \ | ||
| 1120 | 11 * (rf_80 + if_80))) * (10 * (rf_gain + if_gain) - \ | ||
| 1121 | 11 * (rf_80 + if_80)); | ||
| 1122 | if (signal_strength < 0) | ||
| 1123 | signal_strength = 0; | ||
| 1124 | else if (signal_strength > 0xffff) | ||
| 1125 | signal_strength = 0xffff; | ||
| 1126 | |||
| 1127 | state->signal_strength = signal_strength; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | error: | ||
| 1131 | return ret; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | static int af9013_update_statistics(struct dvb_frontend *fe) | ||
| 1135 | { | ||
| 1136 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1137 | int ret; | ||
| 1138 | |||
| 1139 | if (time_before(jiffies, state->next_statistics_check)) | ||
| 1140 | return 0; | ||
| 1141 | |||
| 1142 | /* set minimum statistic update interval */ | ||
| 1143 | state->next_statistics_check = jiffies + msecs_to_jiffies(1200); | ||
| 1144 | |||
| 1145 | ret = af9013_update_signal_strength(fe); | ||
| 1146 | if (ret) | ||
| 1147 | goto error; | ||
| 1148 | ret = af9013_update_snr(fe); | ||
| 1149 | if (ret) | ||
| 1150 | goto error; | ||
| 1151 | ret = af9013_update_ber_unc(fe); | ||
| 1152 | if (ret) | ||
| 1153 | goto error; | ||
| 1154 | |||
| 1155 | error: | ||
| 1156 | return ret; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | static int af9013_get_tune_settings(struct dvb_frontend *fe, | ||
| 1160 | struct dvb_frontend_tune_settings *fesettings) | ||
| 1161 | { | ||
| 1162 | fesettings->min_delay_ms = 800; | ||
| 1163 | fesettings->step_size = 0; | ||
| 1164 | fesettings->max_drift = 0; | ||
| 1165 | |||
| 1166 | return 0; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
| 1170 | { | ||
| 1171 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1172 | int ret = 0; | ||
| 1173 | u8 tmp; | ||
| 1174 | *status = 0; | ||
| 1175 | |||
| 1176 | /* TPS lock */ | ||
| 1177 | ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp); | ||
| 1178 | if (ret) | ||
| 1179 | goto error; | ||
| 1180 | if (tmp) | ||
| 1181 | *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; | ||
| 1182 | |||
| 1183 | /* MPEG2 lock */ | ||
| 1184 | ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp); | ||
| 1185 | if (ret) | ||
| 1186 | goto error; | ||
| 1187 | if (tmp) | ||
| 1188 | *status |= FE_HAS_SYNC | FE_HAS_LOCK; | ||
| 1189 | |||
| 1190 | if (!*status & FE_HAS_SIGNAL) { | ||
| 1191 | /* AGC lock */ | ||
| 1192 | ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp); | ||
| 1193 | if (ret) | ||
| 1194 | goto error; | ||
| 1195 | if (tmp) | ||
| 1196 | *status |= FE_HAS_SIGNAL; | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | if (!*status & FE_HAS_CARRIER) { | ||
| 1200 | /* CFO lock */ | ||
| 1201 | ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp); | ||
| 1202 | if (ret) | ||
| 1203 | goto error; | ||
| 1204 | if (tmp) | ||
| 1205 | *status |= FE_HAS_CARRIER; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | if (!*status & FE_HAS_CARRIER) { | ||
| 1209 | /* SFOE lock */ | ||
| 1210 | ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp); | ||
| 1211 | if (ret) | ||
| 1212 | goto error; | ||
| 1213 | if (tmp) | ||
| 1214 | *status |= FE_HAS_CARRIER; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | ret = af9013_update_statistics(fe); | ||
| 1218 | |||
| 1219 | error: | ||
| 1220 | return ret; | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | |||
| 1224 | static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
| 1225 | { | ||
| 1226 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1227 | int ret; | ||
| 1228 | ret = af9013_update_statistics(fe); | ||
| 1229 | *ber = state->ber; | ||
| 1230 | return ret; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | static int af9013_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
| 1234 | { | ||
| 1235 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1236 | int ret; | ||
| 1237 | ret = af9013_update_statistics(fe); | ||
| 1238 | *strength = state->signal_strength; | ||
| 1239 | return ret; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
| 1243 | { | ||
| 1244 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1245 | int ret; | ||
| 1246 | ret = af9013_update_statistics(fe); | ||
| 1247 | *snr = state->snr; | ||
| 1248 | return ret; | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | static int af9013_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
| 1252 | { | ||
| 1253 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1254 | int ret; | ||
| 1255 | ret = af9013_update_statistics(fe); | ||
| 1256 | *ucblocks = state->ucblocks; | ||
| 1257 | return ret; | ||
| 1258 | } | ||
| 1259 | |||
| 1260 | static int af9013_sleep(struct dvb_frontend *fe) | ||
| 1261 | { | ||
| 1262 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1263 | int ret; | ||
| 1264 | deb_info("%s\n", __func__); | ||
| 1265 | |||
| 1266 | ret = af9013_lock_led(state, 0); | ||
| 1267 | if (ret) | ||
| 1268 | goto error; | ||
| 1269 | |||
| 1270 | ret = af9013_power_ctrl(state, 0); | ||
| 1271 | error: | ||
| 1272 | return ret; | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | static int af9013_init(struct dvb_frontend *fe) | ||
| 1276 | { | ||
| 1277 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1278 | int ret, i, len; | ||
| 1279 | u8 tmp0, tmp1; | ||
| 1280 | struct regdesc *init; | ||
| 1281 | deb_info("%s\n", __func__); | ||
| 1282 | |||
| 1283 | /* reset OFDM */ | ||
| 1284 | ret = af9013_reset(state, 0); | ||
| 1285 | if (ret) | ||
| 1286 | goto error; | ||
| 1287 | |||
| 1288 | /* power on */ | ||
| 1289 | ret = af9013_power_ctrl(state, 1); | ||
| 1290 | if (ret) | ||
| 1291 | goto error; | ||
| 1292 | |||
| 1293 | /* enable ADC */ | ||
| 1294 | ret = af9013_write_reg(state, 0xd73a, 0xa4); | ||
| 1295 | if (ret) | ||
| 1296 | goto error; | ||
| 1297 | |||
| 1298 | /* write API version to firmware */ | ||
| 1299 | for (i = 0; i < sizeof(state->config.api_version); i++) { | ||
| 1300 | ret = af9013_write_reg(state, 0x9bf2 + i, | ||
| 1301 | state->config.api_version[i]); | ||
| 1302 | if (ret) | ||
| 1303 | goto error; | ||
| 1304 | } | ||
| 1305 | |||
| 1306 | /* program ADC control */ | ||
| 1307 | ret = af9013_set_adc_ctrl(state); | ||
| 1308 | if (ret) | ||
| 1309 | goto error; | ||
| 1310 | |||
| 1311 | /* set I2C master clock */ | ||
| 1312 | ret = af9013_write_reg(state, 0xd416, 0x14); | ||
| 1313 | if (ret) | ||
| 1314 | goto error; | ||
| 1315 | |||
| 1316 | /* set 16 embx */ | ||
| 1317 | ret = af9013_write_reg_bits(state, 0xd700, 1, 1, 1); | ||
| 1318 | if (ret) | ||
| 1319 | goto error; | ||
| 1320 | |||
| 1321 | /* set no trigger */ | ||
| 1322 | ret = af9013_write_reg_bits(state, 0xd700, 2, 1, 0); | ||
| 1323 | if (ret) | ||
| 1324 | goto error; | ||
| 1325 | |||
| 1326 | /* set read-update bit for constellation */ | ||
| 1327 | ret = af9013_write_reg_bits(state, 0xd371, 1, 1, 1); | ||
| 1328 | if (ret) | ||
| 1329 | goto error; | ||
| 1330 | |||
| 1331 | /* enable FEC monitor */ | ||
| 1332 | ret = af9013_write_reg_bits(state, 0xd392, 1, 1, 1); | ||
| 1333 | if (ret) | ||
| 1334 | goto error; | ||
| 1335 | |||
| 1336 | /* load OFSM settings */ | ||
| 1337 | deb_info("%s: load ofsm settings\n", __func__); | ||
| 1338 | len = ARRAY_SIZE(ofsm_init); | ||
| 1339 | init = ofsm_init; | ||
| 1340 | for (i = 0; i < len; i++) { | ||
| 1341 | ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos, | ||
| 1342 | init[i].len, init[i].val); | ||
| 1343 | if (ret) | ||
| 1344 | goto error; | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | /* load tuner specific settings */ | ||
| 1348 | deb_info("%s: load tuner specific settings\n", __func__); | ||
| 1349 | switch (state->config.tuner) { | ||
| 1350 | case AF9013_TUNER_MXL5003D: | ||
| 1351 | len = ARRAY_SIZE(tuner_init_mxl5003d); | ||
| 1352 | init = tuner_init_mxl5003d; | ||
| 1353 | break; | ||
| 1354 | case AF9013_TUNER_MXL5005D: | ||
| 1355 | case AF9013_TUNER_MXL5005R: | ||
| 1356 | len = ARRAY_SIZE(tuner_init_mxl5005); | ||
| 1357 | init = tuner_init_mxl5005; | ||
| 1358 | break; | ||
| 1359 | case AF9013_TUNER_ENV77H11D5: | ||
| 1360 | len = ARRAY_SIZE(tuner_init_env77h11d5); | ||
| 1361 | init = tuner_init_env77h11d5; | ||
| 1362 | break; | ||
| 1363 | case AF9013_TUNER_MT2060: | ||
| 1364 | len = ARRAY_SIZE(tuner_init_mt2060); | ||
| 1365 | init = tuner_init_mt2060; | ||
| 1366 | break; | ||
| 1367 | case AF9013_TUNER_MC44S803: | ||
| 1368 | len = ARRAY_SIZE(tuner_init_mc44s803); | ||
| 1369 | init = tuner_init_mc44s803; | ||
| 1370 | break; | ||
| 1371 | case AF9013_TUNER_QT1010: | ||
| 1372 | case AF9013_TUNER_QT1010A: | ||
| 1373 | len = ARRAY_SIZE(tuner_init_qt1010); | ||
| 1374 | init = tuner_init_qt1010; | ||
| 1375 | break; | ||
| 1376 | case AF9013_TUNER_MT2060_2: | ||
| 1377 | len = ARRAY_SIZE(tuner_init_mt2060_2); | ||
| 1378 | init = tuner_init_mt2060_2; | ||
| 1379 | break; | ||
| 1380 | case AF9013_TUNER_TDA18271: | ||
| 1381 | len = ARRAY_SIZE(tuner_init_tda18271); | ||
| 1382 | init = tuner_init_tda18271; | ||
| 1383 | break; | ||
| 1384 | case AF9013_TUNER_UNKNOWN: | ||
| 1385 | default: | ||
| 1386 | len = ARRAY_SIZE(tuner_init_unknown); | ||
| 1387 | init = tuner_init_unknown; | ||
| 1388 | break; | ||
| 1389 | } | ||
| 1390 | |||
| 1391 | for (i = 0; i < len; i++) { | ||
| 1392 | ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos, | ||
| 1393 | init[i].len, init[i].val); | ||
| 1394 | if (ret) | ||
| 1395 | goto error; | ||
| 1396 | } | ||
| 1397 | |||
| 1398 | /* set TS mode */ | ||
| 1399 | deb_info("%s: setting ts mode\n", __func__); | ||
| 1400 | tmp0 = 0; /* parallel mode */ | ||
| 1401 | tmp1 = 0; /* serial mode */ | ||
| 1402 | switch (state->config.output_mode) { | ||
| 1403 | case AF9013_OUTPUT_MODE_PARALLEL: | ||
| 1404 | tmp0 = 1; | ||
| 1405 | break; | ||
| 1406 | case AF9013_OUTPUT_MODE_SERIAL: | ||
| 1407 | tmp1 = 1; | ||
| 1408 | break; | ||
| 1409 | case AF9013_OUTPUT_MODE_USB: | ||
| 1410 | /* usb mode for AF9015 */ | ||
| 1411 | default: | ||
| 1412 | break; | ||
| 1413 | } | ||
| 1414 | ret = af9013_write_reg_bits(state, 0xd500, 1, 1, tmp0); /* parallel */ | ||
| 1415 | if (ret) | ||
| 1416 | goto error; | ||
| 1417 | ret = af9013_write_reg_bits(state, 0xd500, 2, 1, tmp1); /* serial */ | ||
| 1418 | if (ret) | ||
| 1419 | goto error; | ||
| 1420 | |||
| 1421 | /* enable lock led */ | ||
| 1422 | ret = af9013_lock_led(state, 1); | ||
| 1423 | if (ret) | ||
| 1424 | goto error; | ||
| 1425 | |||
| 1426 | error: | ||
| 1427 | return ret; | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | static struct dvb_frontend_ops af9013_ops; | ||
| 1431 | |||
| 1432 | static int af9013_download_firmware(struct af9013_state *state) | ||
| 1433 | { | ||
| 1434 | int i, len, packets, remainder, ret; | ||
| 1435 | const struct firmware *fw; | ||
| 1436 | u16 addr = 0x5100; /* firmware start address */ | ||
| 1437 | u16 checksum = 0; | ||
| 1438 | u8 val; | ||
| 1439 | u8 fw_params[4]; | ||
| 1440 | u8 *data; | ||
| 1441 | u8 *fw_file = AF9013_DEFAULT_FIRMWARE; | ||
| 1442 | |||
| 1443 | msleep(100); | ||
| 1444 | /* check whether firmware is already running */ | ||
| 1445 | ret = af9013_read_reg(state, 0x98be, &val); | ||
| 1446 | if (ret) | ||
| 1447 | goto error; | ||
| 1448 | else | ||
| 1449 | deb_info("%s: firmware status:%02x\n", __func__, val); | ||
| 1450 | |||
| 1451 | if (val == 0x0c) /* fw is running, no need for download */ | ||
| 1452 | goto exit; | ||
| 1453 | |||
| 1454 | info("found a '%s' in cold state, will try to load a firmware", | ||
| 1455 | af9013_ops.info.name); | ||
| 1456 | |||
| 1457 | /* request the firmware, this will block and timeout */ | ||
| 1458 | ret = request_firmware(&fw, fw_file, &state->i2c->dev); | ||
| 1459 | if (ret) { | ||
| 1460 | err("did not find the firmware file. (%s) " | ||
| 1461 | "Please see linux/Documentation/dvb/ for more details" \ | ||
| 1462 | " on firmware-problems. (%d)", | ||
| 1463 | fw_file, ret); | ||
| 1464 | goto error; | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | info("downloading firmware from file '%s'", fw_file); | ||
| 1468 | |||
| 1469 | /* calc checksum */ | ||
| 1470 | for (i = 0; i < fw->size; i++) | ||
| 1471 | checksum += fw->data[i]; | ||
| 1472 | |||
| 1473 | fw_params[0] = checksum >> 8; | ||
| 1474 | fw_params[1] = checksum & 0xff; | ||
| 1475 | fw_params[2] = fw->size >> 8; | ||
| 1476 | fw_params[3] = fw->size & 0xff; | ||
| 1477 | |||
| 1478 | /* write fw checksum & size */ | ||
| 1479 | ret = af9013_write_ofsm_regs(state, 0x50fc, | ||
| 1480 | fw_params, sizeof(fw_params)); | ||
| 1481 | if (ret) | ||
| 1482 | goto error_release; | ||
| 1483 | |||
| 1484 | #define FW_PACKET_MAX_DATA 16 | ||
| 1485 | |||
| 1486 | packets = fw->size / FW_PACKET_MAX_DATA; | ||
| 1487 | remainder = fw->size % FW_PACKET_MAX_DATA; | ||
| 1488 | len = FW_PACKET_MAX_DATA; | ||
| 1489 | for (i = 0; i <= packets; i++) { | ||
| 1490 | if (i == packets) /* set size of the last packet */ | ||
| 1491 | len = remainder; | ||
| 1492 | |||
| 1493 | data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA); | ||
| 1494 | ret = af9013_write_ofsm_regs(state, addr, data, len); | ||
| 1495 | addr += FW_PACKET_MAX_DATA; | ||
| 1496 | |||
| 1497 | if (ret) { | ||
| 1498 | err("firmware download failed at %d with %d", i, ret); | ||
| 1499 | goto error_release; | ||
| 1500 | } | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | /* request boot firmware */ | ||
| 1504 | ret = af9013_write_reg(state, 0xe205, 1); | ||
| 1505 | if (ret) | ||
| 1506 | goto error_release; | ||
| 1507 | |||
| 1508 | for (i = 0; i < 15; i++) { | ||
| 1509 | msleep(100); | ||
| 1510 | |||
| 1511 | /* check firmware status */ | ||
| 1512 | ret = af9013_read_reg(state, 0x98be, &val); | ||
| 1513 | if (ret) | ||
| 1514 | goto error_release; | ||
| 1515 | |||
| 1516 | deb_info("%s: firmware status:%02x\n", __func__, val); | ||
| 1517 | |||
| 1518 | if (val == 0x0c || val == 0x04) /* success or fail */ | ||
| 1519 | break; | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | if (val == 0x04) { | ||
| 1523 | err("firmware did not run"); | ||
| 1524 | ret = -1; | ||
| 1525 | } else if (val != 0x0c) { | ||
| 1526 | err("firmware boot timeout"); | ||
| 1527 | ret = -1; | ||
| 1528 | } | ||
| 1529 | |||
| 1530 | error_release: | ||
| 1531 | release_firmware(fw); | ||
| 1532 | error: | ||
| 1533 | exit: | ||
| 1534 | if (!ret) | ||
| 1535 | info("found a '%s' in warm state.", af9013_ops.info.name); | ||
| 1536 | return ret; | ||
| 1537 | } | ||
| 1538 | |||
| 1539 | static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | ||
| 1540 | { | ||
| 1541 | int ret; | ||
| 1542 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1543 | deb_info("%s: enable:%d\n", __func__, enable); | ||
| 1544 | |||
| 1545 | if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) | ||
| 1546 | ret = af9013_write_reg_bits(state, 0xd417, 3, 1, enable); | ||
| 1547 | else | ||
| 1548 | ret = af9013_write_reg_bits(state, 0xd607, 2, 1, enable); | ||
| 1549 | |||
| 1550 | return ret; | ||
| 1551 | } | ||
| 1552 | |||
| 1553 | static void af9013_release(struct dvb_frontend *fe) | ||
| 1554 | { | ||
| 1555 | struct af9013_state *state = fe->demodulator_priv; | ||
| 1556 | kfree(state); | ||
| 1557 | } | ||
| 1558 | |||
| 1559 | static struct dvb_frontend_ops af9013_ops; | ||
| 1560 | |||
| 1561 | struct dvb_frontend *af9013_attach(const struct af9013_config *config, | ||
| 1562 | struct i2c_adapter *i2c) | ||
| 1563 | { | ||
| 1564 | int ret; | ||
| 1565 | struct af9013_state *state = NULL; | ||
| 1566 | u8 buf[3], i; | ||
| 1567 | |||
| 1568 | /* allocate memory for the internal state */ | ||
| 1569 | state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL); | ||
| 1570 | if (state == NULL) | ||
| 1571 | goto error; | ||
| 1572 | |||
| 1573 | /* setup the state */ | ||
| 1574 | state->i2c = i2c; | ||
| 1575 | memcpy(&state->config, config, sizeof(struct af9013_config)); | ||
| 1576 | |||
| 1577 | /* chip version */ | ||
| 1578 | ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]); | ||
| 1579 | if (ret) | ||
| 1580 | goto error; | ||
| 1581 | |||
| 1582 | /* ROM version */ | ||
| 1583 | for (i = 0; i < 2; i++) { | ||
| 1584 | ret = af9013_read_reg(state, 0x116b + i, &buf[i]); | ||
| 1585 | if (ret) | ||
| 1586 | goto error; | ||
| 1587 | } | ||
| 1588 | deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__, | ||
| 1589 | buf[2], buf[0], buf[1]); | ||
| 1590 | |||
| 1591 | /* download firmware */ | ||
| 1592 | if (state->config.output_mode != AF9013_OUTPUT_MODE_USB) { | ||
| 1593 | ret = af9013_download_firmware(state); | ||
| 1594 | if (ret) | ||
| 1595 | goto error; | ||
| 1596 | } | ||
| 1597 | |||
| 1598 | /* firmware version */ | ||
| 1599 | for (i = 0; i < 3; i++) { | ||
| 1600 | ret = af9013_read_reg(state, 0x5103 + i, &buf[i]); | ||
| 1601 | if (ret) | ||
| 1602 | goto error; | ||
| 1603 | } | ||
| 1604 | info("firmware version:%d.%d.%d", buf[0], buf[1], buf[2]); | ||
| 1605 | |||
| 1606 | /* settings for mp2if */ | ||
| 1607 | if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) { | ||
| 1608 | /* AF9015 split PSB to 1.5k + 0.5k */ | ||
| 1609 | ret = af9013_write_reg_bits(state, 0xd50b, 2, 1, 1); | ||
| 1610 | } else { | ||
| 1611 | /* AF9013 change the output bit to data7 */ | ||
| 1612 | ret = af9013_write_reg_bits(state, 0xd500, 3, 1, 1); | ||
| 1613 | if (ret) | ||
| 1614 | goto error; | ||
| 1615 | /* AF9013 set mpeg to full speed */ | ||
| 1616 | ret = af9013_write_reg_bits(state, 0xd502, 4, 1, 1); | ||
| 1617 | } | ||
| 1618 | if (ret) | ||
| 1619 | goto error; | ||
| 1620 | ret = af9013_write_reg_bits(state, 0xd520, 4, 1, 1); | ||
| 1621 | if (ret) | ||
| 1622 | goto error; | ||
| 1623 | |||
| 1624 | /* set GPIOs */ | ||
| 1625 | for (i = 0; i < sizeof(state->config.gpio); i++) { | ||
| 1626 | ret = af9013_set_gpio(state, i, state->config.gpio[i]); | ||
| 1627 | if (ret) | ||
| 1628 | goto error; | ||
| 1629 | } | ||
| 1630 | |||
| 1631 | /* create dvb_frontend */ | ||
| 1632 | memcpy(&state->frontend.ops, &af9013_ops, | ||
| 1633 | sizeof(struct dvb_frontend_ops)); | ||
| 1634 | state->frontend.demodulator_priv = state; | ||
| 1635 | |||
| 1636 | return &state->frontend; | ||
| 1637 | error: | ||
| 1638 | kfree(state); | ||
| 1639 | return NULL; | ||
| 1640 | } | ||
| 1641 | EXPORT_SYMBOL(af9013_attach); | ||
| 1642 | |||
| 1643 | static struct dvb_frontend_ops af9013_ops = { | ||
| 1644 | .info = { | ||
| 1645 | .name = "Afatech AF9013 DVB-T", | ||
| 1646 | .type = FE_OFDM, | ||
| 1647 | .frequency_min = 174000000, | ||
| 1648 | .frequency_max = 862000000, | ||
| 1649 | .frequency_stepsize = 250000, | ||
| 1650 | .frequency_tolerance = 0, | ||
| 1651 | .caps = | ||
| 1652 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 1653 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
| 1654 | FE_CAN_QPSK | FE_CAN_QAM_16 | | ||
| 1655 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
| 1656 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
| 1657 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
| 1658 | FE_CAN_HIERARCHY_AUTO | | ||
| 1659 | FE_CAN_RECOVER | | ||
| 1660 | FE_CAN_MUTE_TS | ||
| 1661 | }, | ||
| 1662 | |||
| 1663 | .release = af9013_release, | ||
| 1664 | .init = af9013_init, | ||
| 1665 | .sleep = af9013_sleep, | ||
| 1666 | .i2c_gate_ctrl = af9013_i2c_gate_ctrl, | ||
| 1667 | |||
| 1668 | .set_frontend = af9013_set_frontend, | ||
| 1669 | .get_frontend = af9013_get_frontend, | ||
| 1670 | |||
| 1671 | .get_tune_settings = af9013_get_tune_settings, | ||
| 1672 | |||
| 1673 | .read_status = af9013_read_status, | ||
| 1674 | .read_ber = af9013_read_ber, | ||
| 1675 | .read_signal_strength = af9013_read_signal_strength, | ||
| 1676 | .read_snr = af9013_read_snr, | ||
| 1677 | .read_ucblocks = af9013_read_ucblocks, | ||
| 1678 | }; | ||
| 1679 | |||
| 1680 | module_param_named(debug, af9013_debug, int, 0644); | ||
| 1681 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
| 1682 | |||
| 1683 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 1684 | MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver"); | ||
| 1685 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb/frontends/af9013.h new file mode 100644 index 000000000000..28b90c91c766 --- /dev/null +++ b/drivers/media/dvb/frontends/af9013.h | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * Thanks to Afatech who kindly provided information. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef _AF9013_H_ | ||
| 25 | #define _AF9013_H_ | ||
| 26 | |||
| 27 | #include <linux/dvb/frontend.h> | ||
| 28 | |||
| 29 | enum af9013_ts_mode { | ||
| 30 | AF9013_OUTPUT_MODE_PARALLEL, | ||
| 31 | AF9013_OUTPUT_MODE_SERIAL, | ||
| 32 | AF9013_OUTPUT_MODE_USB, /* only for AF9015 */ | ||
| 33 | }; | ||
| 34 | |||
| 35 | enum af9013_tuner { | ||
| 36 | AF9013_TUNER_MXL5003D = 3, /* MaxLinear */ | ||
| 37 | AF9013_TUNER_MXL5005D = 13, /* MaxLinear */ | ||
| 38 | AF9013_TUNER_MXL5005R = 30, /* MaxLinear */ | ||
| 39 | AF9013_TUNER_ENV77H11D5 = 129, /* Panasonic */ | ||
| 40 | AF9013_TUNER_MT2060 = 130, /* Microtune */ | ||
| 41 | AF9013_TUNER_MC44S803 = 133, /* Freescale */ | ||
| 42 | AF9013_TUNER_QT1010 = 134, /* Quantek */ | ||
| 43 | AF9013_TUNER_UNKNOWN = 140, /* for can tuners ? */ | ||
| 44 | AF9013_TUNER_MT2060_2 = 147, /* Microtune */ | ||
| 45 | AF9013_TUNER_TDA18271 = 156, /* NXP */ | ||
| 46 | AF9013_TUNER_QT1010A = 162, /* Quantek */ | ||
| 47 | }; | ||
| 48 | |||
| 49 | /* AF9013/5 GPIOs (mostly guessed) | ||
| 50 | demod#1-gpio#0 - set demod#2 i2c-addr for dual devices | ||
| 51 | demod#1-gpio#1 - xtal setting (?) | ||
| 52 | demod#1-gpio#3 - tuner#1 | ||
| 53 | demod#2-gpio#0 - tuner#2 | ||
| 54 | demod#2-gpio#1 - xtal setting (?) | ||
| 55 | */ | ||
| 56 | #define AF9013_GPIO_ON (1 << 0) | ||
| 57 | #define AF9013_GPIO_EN (1 << 1) | ||
| 58 | #define AF9013_GPIO_O (1 << 2) | ||
| 59 | #define AF9013_GPIO_I (1 << 3) | ||
| 60 | |||
| 61 | #define AF9013_GPIO_LO (AF9013_GPIO_ON|AF9013_GPIO_EN) | ||
| 62 | #define AF9013_GPIO_HI (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O) | ||
| 63 | |||
| 64 | #define AF9013_GPIO_TUNER_ON (AF9013_GPIO_ON|AF9013_GPIO_EN) | ||
| 65 | #define AF9013_GPIO_TUNER_OFF (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O) | ||
| 66 | |||
| 67 | struct af9013_config { | ||
| 68 | /* demodulator's I2C address */ | ||
| 69 | u8 demod_address; | ||
| 70 | |||
| 71 | /* frequencies in kHz */ | ||
| 72 | u32 adc_clock; | ||
| 73 | |||
| 74 | /* tuner ID */ | ||
| 75 | u8 tuner; | ||
| 76 | |||
| 77 | /* tuner IF */ | ||
| 78 | u16 tuner_if; | ||
| 79 | |||
| 80 | /* TS data output mode */ | ||
| 81 | u8 output_mode:2; | ||
| 82 | |||
| 83 | /* RF spectrum inversion */ | ||
| 84 | u8 rf_spec_inv:1; | ||
| 85 | |||
| 86 | /* API version */ | ||
| 87 | u8 api_version[4]; | ||
| 88 | |||
| 89 | /* GPIOs */ | ||
| 90 | u8 gpio[4]; | ||
| 91 | }; | ||
| 92 | |||
| 93 | |||
| 94 | #if defined(CONFIG_DVB_AF9013) || \ | ||
| 95 | (defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE)) | ||
| 96 | extern struct dvb_frontend *af9013_attach(const struct af9013_config *config, | ||
| 97 | struct i2c_adapter *i2c); | ||
| 98 | #else | ||
| 99 | static inline struct dvb_frontend *af9013_attach( | ||
| 100 | const struct af9013_config *config, struct i2c_adapter *i2c) | ||
| 101 | { | ||
| 102 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 103 | return NULL; | ||
| 104 | } | ||
| 105 | #endif /* CONFIG_DVB_AF9013 */ | ||
| 106 | |||
| 107 | #endif /* _AF9013_H_ */ | ||
diff --git a/drivers/media/dvb/frontends/af9013_priv.h b/drivers/media/dvb/frontends/af9013_priv.h new file mode 100644 index 000000000000..163e251d0b73 --- /dev/null +++ b/drivers/media/dvb/frontends/af9013_priv.h | |||
| @@ -0,0 +1,869 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
| 5 | * | ||
| 6 | * Thanks to Afatech who kindly provided information. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef _AF9013_PRIV_ | ||
| 25 | #define _AF9013_PRIV_ | ||
| 26 | |||
| 27 | #define LOG_PREFIX "af9013" | ||
| 28 | extern int af9013_debug; | ||
| 29 | |||
| 30 | #define dprintk(var, level, args...) \ | ||
| 31 | do { if ((var & level)) printk(args); } while (0) | ||
| 32 | |||
| 33 | #define debug_dump(b, l, func) {\ | ||
| 34 | int loop_; \ | ||
| 35 | for (loop_ = 0; loop_ < l; loop_++) \ | ||
| 36 | func("%02x ", b[loop_]); \ | ||
| 37 | func("\n");\ | ||
| 38 | } | ||
| 39 | |||
| 40 | #define deb_info(args...) dprintk(af9013_debug, 0x01, args) | ||
| 41 | |||
| 42 | #undef err | ||
| 43 | #define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) | ||
| 44 | #undef info | ||
| 45 | #define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | ||
| 46 | #undef warn | ||
| 47 | #define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) | ||
| 48 | |||
| 49 | #define AF9013_DEFAULT_FIRMWARE "dvb-fe-af9013.fw" | ||
| 50 | |||
| 51 | struct regdesc { | ||
| 52 | u16 addr; | ||
| 53 | u8 pos:4; | ||
| 54 | u8 len:4; | ||
| 55 | u8 val; | ||
| 56 | }; | ||
| 57 | |||
| 58 | struct snr_table { | ||
| 59 | u32 val; | ||
| 60 | u8 snr; | ||
| 61 | }; | ||
| 62 | |||
| 63 | /* QPSK SNR lookup table */ | ||
| 64 | static struct snr_table qpsk_snr_table[] = { | ||
| 65 | { 0x0b4771, 0 }, | ||
| 66 | { 0x0c1aed, 1 }, | ||
| 67 | { 0x0d0d27, 2 }, | ||
| 68 | { 0x0e4d19, 3 }, | ||
| 69 | { 0x0e5da8, 4 }, | ||
| 70 | { 0x107097, 5 }, | ||
| 71 | { 0x116975, 6 }, | ||
| 72 | { 0x1252d9, 7 }, | ||
| 73 | { 0x131fa4, 8 }, | ||
| 74 | { 0x13d5e1, 9 }, | ||
| 75 | { 0x148e53, 10 }, | ||
| 76 | { 0x15358b, 11 }, | ||
| 77 | { 0x15dd29, 12 }, | ||
| 78 | { 0x168112, 13 }, | ||
| 79 | { 0x170b61, 14 }, | ||
| 80 | { 0xffffff, 15 }, | ||
| 81 | }; | ||
| 82 | |||
| 83 | /* QAM16 SNR lookup table */ | ||
| 84 | static struct snr_table qam16_snr_table[] = { | ||
| 85 | { 0x05eb62, 5 }, | ||
| 86 | { 0x05fecf, 6 }, | ||
| 87 | { 0x060b80, 7 }, | ||
| 88 | { 0x062501, 8 }, | ||
| 89 | { 0x064865, 9 }, | ||
| 90 | { 0x069604, 10 }, | ||
| 91 | { 0x06f356, 11 }, | ||
| 92 | { 0x07706a, 12 }, | ||
| 93 | { 0x0804d3, 13 }, | ||
| 94 | { 0x089d1a, 14 }, | ||
| 95 | { 0x093e3d, 15 }, | ||
| 96 | { 0x09e35d, 16 }, | ||
| 97 | { 0x0a7c3c, 17 }, | ||
| 98 | { 0x0afaf8, 18 }, | ||
| 99 | { 0x0b719d, 19 }, | ||
| 100 | { 0xffffff, 20 }, | ||
| 101 | }; | ||
| 102 | |||
| 103 | /* QAM64 SNR lookup table */ | ||
| 104 | static struct snr_table qam64_snr_table[] = { | ||
| 105 | { 0x03109b, 12 }, | ||
| 106 | { 0x0310d4, 13 }, | ||
| 107 | { 0x031920, 14 }, | ||
| 108 | { 0x0322d0, 15 }, | ||
| 109 | { 0x0339fc, 16 }, | ||
| 110 | { 0x0364a1, 17 }, | ||
| 111 | { 0x038bcc, 18 }, | ||
| 112 | { 0x03c7d3, 19 }, | ||
| 113 | { 0x0408cc, 20 }, | ||
| 114 | { 0x043bed, 21 }, | ||
| 115 | { 0x048061, 22 }, | ||
| 116 | { 0x04be95, 23 }, | ||
| 117 | { 0x04fa7d, 24 }, | ||
| 118 | { 0x052405, 25 }, | ||
| 119 | { 0x05570d, 26 }, | ||
| 120 | { 0xffffff, 27 }, | ||
| 121 | }; | ||
| 122 | |||
| 123 | static struct regdesc ofsm_init[] = { | ||
| 124 | { 0xd73a, 0, 8, 0xa1 }, | ||
| 125 | { 0xd73b, 0, 8, 0x1f }, | ||
| 126 | { 0xd73c, 4, 4, 0x0a }, | ||
| 127 | { 0xd732, 3, 1, 0x00 }, | ||
| 128 | { 0xd731, 4, 2, 0x03 }, | ||
| 129 | { 0xd73d, 7, 1, 0x01 }, | ||
| 130 | { 0xd740, 0, 1, 0x00 }, | ||
| 131 | { 0xd740, 1, 1, 0x00 }, | ||
| 132 | { 0xd740, 2, 1, 0x00 }, | ||
| 133 | { 0xd740, 3, 1, 0x01 }, | ||
| 134 | { 0xd3c1, 4, 1, 0x01 }, | ||
| 135 | { 0xd3a2, 0, 8, 0x00 }, | ||
| 136 | { 0xd3a3, 0, 8, 0x04 }, | ||
| 137 | { 0xd305, 0, 8, 0x32 }, | ||
| 138 | { 0xd306, 0, 8, 0x10 }, | ||
| 139 | { 0xd304, 0, 8, 0x04 }, | ||
| 140 | { 0x9112, 0, 1, 0x01 }, | ||
| 141 | { 0x911d, 0, 1, 0x01 }, | ||
| 142 | { 0x911a, 0, 1, 0x01 }, | ||
| 143 | { 0x911b, 0, 1, 0x01 }, | ||
| 144 | { 0x9bce, 0, 4, 0x02 }, | ||
| 145 | { 0x9116, 0, 1, 0x01 }, | ||
| 146 | { 0x9bd1, 0, 1, 0x01 }, | ||
| 147 | { 0xd2e0, 0, 8, 0xd0 }, | ||
| 148 | { 0xd2e9, 0, 4, 0x0d }, | ||
| 149 | { 0xd38c, 0, 8, 0xfc }, | ||
| 150 | { 0xd38d, 0, 8, 0x00 }, | ||
| 151 | { 0xd38e, 0, 8, 0x7e }, | ||
| 152 | { 0xd38f, 0, 8, 0x00 }, | ||
| 153 | { 0xd390, 0, 8, 0x2f }, | ||
| 154 | { 0xd145, 4, 1, 0x01 }, | ||
| 155 | { 0xd1a9, 4, 1, 0x01 }, | ||
| 156 | { 0xd158, 5, 3, 0x01 }, | ||
| 157 | { 0xd159, 0, 6, 0x06 }, | ||
| 158 | { 0xd167, 0, 8, 0x00 }, | ||
| 159 | { 0xd168, 0, 4, 0x07 }, | ||
| 160 | { 0xd1c3, 5, 3, 0x00 }, | ||
| 161 | { 0xd1c4, 0, 6, 0x00 }, | ||
| 162 | { 0xd1c5, 0, 7, 0x10 }, | ||
| 163 | { 0xd1c6, 0, 3, 0x02 }, | ||
| 164 | { 0xd080, 2, 5, 0x03 }, | ||
| 165 | { 0xd081, 4, 4, 0x09 }, | ||
| 166 | { 0xd098, 4, 4, 0x0f }, | ||
| 167 | { 0xd098, 0, 4, 0x03 }, | ||
| 168 | { 0xdbc0, 3, 1, 0x01 }, | ||
| 169 | { 0xdbc0, 4, 1, 0x01 }, | ||
| 170 | { 0xdbc7, 0, 8, 0x08 }, | ||
| 171 | { 0xdbc8, 4, 4, 0x00 }, | ||
| 172 | { 0xdbc9, 0, 5, 0x01 }, | ||
| 173 | { 0xd280, 0, 8, 0xe0 }, | ||
| 174 | { 0xd281, 0, 8, 0xff }, | ||
| 175 | { 0xd282, 0, 8, 0xff }, | ||
| 176 | { 0xd283, 0, 8, 0xc3 }, | ||
| 177 | { 0xd284, 0, 8, 0xff }, | ||
| 178 | { 0xd285, 0, 4, 0x01 }, | ||
| 179 | { 0xd0f0, 0, 7, 0x1a }, | ||
| 180 | { 0xd0f1, 4, 1, 0x01 }, | ||
| 181 | { 0xd0f2, 0, 8, 0x0c }, | ||
| 182 | { 0xd103, 0, 4, 0x08 }, | ||
| 183 | { 0xd0f8, 0, 7, 0x20 }, | ||
| 184 | { 0xd111, 5, 1, 0x00 }, | ||
| 185 | { 0xd111, 6, 1, 0x00 }, | ||
| 186 | { 0x910b, 0, 8, 0x0a }, | ||
| 187 | { 0x9115, 0, 8, 0x02 }, | ||
| 188 | { 0x910c, 0, 8, 0x02 }, | ||
| 189 | { 0x910d, 0, 8, 0x08 }, | ||
| 190 | { 0x910e, 0, 8, 0x0a }, | ||
| 191 | { 0x9bf6, 0, 8, 0x06 }, | ||
| 192 | { 0x9bf8, 0, 8, 0x02 }, | ||
| 193 | { 0x9bf7, 0, 8, 0x05 }, | ||
| 194 | { 0x9bf9, 0, 8, 0x0f }, | ||
| 195 | { 0x9bfc, 0, 8, 0x13 }, | ||
| 196 | { 0x9bd3, 0, 8, 0xff }, | ||
| 197 | { 0x9bbe, 0, 1, 0x01 }, | ||
| 198 | { 0x9bcc, 0, 1, 0x01 }, | ||
| 199 | }; | ||
| 200 | |||
| 201 | /* Panasonic ENV77H11D5 tuner init | ||
| 202 | AF9013_TUNER_ENV77H11D5 = 129 */ | ||
| 203 | static struct regdesc tuner_init_env77h11d5[] = { | ||
| 204 | { 0x9bd5, 0, 8, 0x01 }, | ||
| 205 | { 0x9bd6, 0, 8, 0x03 }, | ||
| 206 | { 0x9bbe, 0, 8, 0x01 }, | ||
| 207 | { 0xd1a0, 1, 1, 0x01 }, | ||
| 208 | { 0xd000, 0, 1, 0x01 }, | ||
| 209 | { 0xd000, 1, 1, 0x00 }, | ||
| 210 | { 0xd001, 1, 1, 0x01 }, | ||
| 211 | { 0xd001, 0, 1, 0x00 }, | ||
| 212 | { 0xd001, 5, 1, 0x00 }, | ||
| 213 | { 0xd002, 0, 5, 0x19 }, | ||
| 214 | { 0xd003, 0, 5, 0x1a }, | ||
| 215 | { 0xd004, 0, 5, 0x19 }, | ||
| 216 | { 0xd005, 0, 5, 0x1a }, | ||
| 217 | { 0xd00e, 0, 5, 0x10 }, | ||
| 218 | { 0xd00f, 0, 3, 0x04 }, | ||
| 219 | { 0xd00f, 3, 3, 0x05 }, | ||
| 220 | { 0xd010, 0, 3, 0x04 }, | ||
| 221 | { 0xd010, 3, 3, 0x05 }, | ||
| 222 | { 0xd016, 4, 4, 0x03 }, | ||
| 223 | { 0xd01f, 0, 6, 0x0a }, | ||
| 224 | { 0xd020, 0, 6, 0x0a }, | ||
| 225 | { 0x9bda, 0, 8, 0x00 }, | ||
| 226 | { 0x9be3, 0, 8, 0x00 }, | ||
| 227 | { 0xd015, 0, 8, 0x50 }, | ||
| 228 | { 0xd016, 0, 1, 0x00 }, | ||
| 229 | { 0xd044, 0, 8, 0x46 }, | ||
| 230 | { 0xd045, 0, 1, 0x00 }, | ||
| 231 | { 0xd008, 0, 8, 0xdf }, | ||
| 232 | { 0xd009, 0, 2, 0x02 }, | ||
| 233 | { 0xd006, 0, 8, 0x44 }, | ||
| 234 | { 0xd007, 0, 2, 0x01 }, | ||
| 235 | { 0xd00c, 0, 8, 0xeb }, | ||
| 236 | { 0xd00d, 0, 2, 0x02 }, | ||
| 237 | { 0xd00a, 0, 8, 0xf4 }, | ||
| 238 | { 0xd00b, 0, 2, 0x01 }, | ||
| 239 | { 0x9bba, 0, 8, 0xf9 }, | ||
| 240 | { 0x9bc3, 0, 8, 0xdf }, | ||
| 241 | { 0x9bc4, 0, 8, 0x02 }, | ||
| 242 | { 0x9bc5, 0, 8, 0xeb }, | ||
| 243 | { 0x9bc6, 0, 8, 0x02 }, | ||
| 244 | { 0x9bc9, 0, 8, 0x52 }, | ||
| 245 | { 0xd011, 0, 8, 0x3c }, | ||
| 246 | { 0xd012, 0, 2, 0x01 }, | ||
| 247 | { 0xd013, 0, 8, 0xf7 }, | ||
| 248 | { 0xd014, 0, 2, 0x02 }, | ||
| 249 | { 0xd040, 0, 8, 0x0b }, | ||
| 250 | { 0xd041, 0, 2, 0x02 }, | ||
| 251 | { 0xd042, 0, 8, 0x4d }, | ||
| 252 | { 0xd043, 0, 2, 0x00 }, | ||
| 253 | { 0xd045, 1, 1, 0x00 }, | ||
| 254 | { 0x9bcf, 0, 1, 0x01 }, | ||
| 255 | { 0xd045, 2, 1, 0x01 }, | ||
| 256 | { 0xd04f, 0, 8, 0x9a }, | ||
| 257 | { 0xd050, 0, 1, 0x01 }, | ||
| 258 | { 0xd051, 0, 8, 0x5a }, | ||
| 259 | { 0xd052, 0, 1, 0x01 }, | ||
| 260 | { 0xd053, 0, 8, 0x50 }, | ||
| 261 | { 0xd054, 0, 8, 0x46 }, | ||
| 262 | { 0x9bd7, 0, 8, 0x0a }, | ||
| 263 | { 0x9bd8, 0, 8, 0x14 }, | ||
| 264 | { 0x9bd9, 0, 8, 0x08 }, | ||
| 265 | }; | ||
| 266 | |||
| 267 | /* Microtune MT2060 tuner init | ||
| 268 | AF9013_TUNER_MT2060 = 130 */ | ||
| 269 | static struct regdesc tuner_init_mt2060[] = { | ||
| 270 | { 0x9bd5, 0, 8, 0x01 }, | ||
| 271 | { 0x9bd6, 0, 8, 0x07 }, | ||
| 272 | { 0xd1a0, 1, 1, 0x01 }, | ||
| 273 | { 0xd000, 0, 1, 0x01 }, | ||
| 274 | { 0xd000, 1, 1, 0x00 }, | ||
| 275 | { 0xd001, 1, 1, 0x01 }, | ||
| 276 | { 0xd001, 0, 1, 0x00 }, | ||
| 277 | { 0xd001, 5, 1, 0x00 }, | ||
| 278 | { 0xd002, 0, 5, 0x19 }, | ||
| 279 | { 0xd003, 0, 5, 0x1a }, | ||
| 280 | { 0xd004, 0, 5, 0x19 }, | ||
| 281 | { 0xd005, 0, 5, 0x1a }, | ||
| 282 | { 0xd00e, 0, 5, 0x10 }, | ||
| 283 | { 0xd00f, 0, 3, 0x04 }, | ||
| 284 | { 0xd00f, 3, 3, 0x05 }, | ||
| 285 | { 0xd010, 0, 3, 0x04 }, | ||
| 286 | { 0xd010, 3, 3, 0x05 }, | ||
| 287 | { 0xd016, 4, 4, 0x03 }, | ||
| 288 | { 0xd01f, 0, 6, 0x0a }, | ||
| 289 | { 0xd020, 0, 6, 0x0a }, | ||
| 290 | { 0x9bda, 0, 8, 0x00 }, | ||
| 291 | { 0x9be3, 0, 8, 0x00 }, | ||
| 292 | { 0x9bbe, 0, 1, 0x00 }, | ||
| 293 | { 0x9bcc, 0, 1, 0x00 }, | ||
| 294 | { 0x9bb9, 0, 8, 0x75 }, | ||
| 295 | { 0x9bcd, 0, 8, 0x24 }, | ||
| 296 | { 0x9bff, 0, 8, 0x30 }, | ||
| 297 | { 0xd015, 0, 8, 0x46 }, | ||
| 298 | { 0xd016, 0, 1, 0x00 }, | ||
| 299 | { 0xd044, 0, 8, 0x46 }, | ||
| 300 | { 0xd045, 0, 1, 0x00 }, | ||
| 301 | { 0xd008, 0, 8, 0x0f }, | ||
| 302 | { 0xd009, 0, 2, 0x02 }, | ||
| 303 | { 0xd006, 0, 8, 0x32 }, | ||
| 304 | { 0xd007, 0, 2, 0x01 }, | ||
| 305 | { 0xd00c, 0, 8, 0x36 }, | ||
| 306 | { 0xd00d, 0, 2, 0x03 }, | ||
| 307 | { 0xd00a, 0, 8, 0x35 }, | ||
| 308 | { 0xd00b, 0, 2, 0x01 }, | ||
| 309 | { 0x9bc7, 0, 8, 0x07 }, | ||
| 310 | { 0x9bc8, 0, 8, 0x90 }, | ||
| 311 | { 0x9bc3, 0, 8, 0x0f }, | ||
| 312 | { 0x9bc4, 0, 8, 0x02 }, | ||
| 313 | { 0x9bc5, 0, 8, 0x36 }, | ||
| 314 | { 0x9bc6, 0, 8, 0x03 }, | ||
| 315 | { 0x9bba, 0, 8, 0xc9 }, | ||
| 316 | { 0x9bc9, 0, 8, 0x79 }, | ||
| 317 | { 0xd011, 0, 8, 0x10 }, | ||
| 318 | { 0xd012, 0, 2, 0x01 }, | ||
| 319 | { 0xd013, 0, 8, 0x45 }, | ||
| 320 | { 0xd014, 0, 2, 0x03 }, | ||
| 321 | { 0xd040, 0, 8, 0x98 }, | ||
| 322 | { 0xd041, 0, 2, 0x00 }, | ||
| 323 | { 0xd042, 0, 8, 0xcf }, | ||
| 324 | { 0xd043, 0, 2, 0x03 }, | ||
| 325 | { 0xd045, 1, 1, 0x00 }, | ||
| 326 | { 0x9bcf, 0, 1, 0x01 }, | ||
| 327 | { 0xd045, 2, 1, 0x01 }, | ||
| 328 | { 0xd04f, 0, 8, 0x9a }, | ||
| 329 | { 0xd050, 0, 1, 0x01 }, | ||
| 330 | { 0xd051, 0, 8, 0x5a }, | ||
| 331 | { 0xd052, 0, 1, 0x01 }, | ||
| 332 | { 0xd053, 0, 8, 0x50 }, | ||
| 333 | { 0xd054, 0, 8, 0x46 }, | ||
| 334 | { 0x9bd7, 0, 8, 0x0a }, | ||
| 335 | { 0x9bd8, 0, 8, 0x14 }, | ||
| 336 | { 0x9bd9, 0, 8, 0x08 }, | ||
| 337 | { 0x9bd0, 0, 8, 0xcc }, | ||
| 338 | { 0x9be4, 0, 8, 0xa0 }, | ||
| 339 | { 0x9bbd, 0, 8, 0x8e }, | ||
| 340 | { 0x9be2, 0, 8, 0x4d }, | ||
| 341 | { 0x9bee, 0, 1, 0x01 }, | ||
| 342 | }; | ||
| 343 | |||
| 344 | /* Microtune MT2060 tuner init | ||
| 345 | AF9013_TUNER_MT2060_2 = 147 */ | ||
| 346 | static struct regdesc tuner_init_mt2060_2[] = { | ||
| 347 | { 0x9bd5, 0, 8, 0x01 }, | ||
| 348 | { 0x9bd6, 0, 8, 0x06 }, | ||
| 349 | { 0x9bbe, 0, 8, 0x01 }, | ||
| 350 | { 0xd1a0, 1, 1, 0x01 }, | ||
| 351 | { 0xd000, 0, 1, 0x01 }, | ||
| 352 | { 0xd000, 1, 1, 0x00 }, | ||
| 353 | { 0xd001, 1, 1, 0x01 }, | ||
| 354 | { 0xd001, 0, 1, 0x00 }, | ||
| 355 | { 0xd001, 5, 1, 0x00 }, | ||
| 356 | { 0xd002, 0, 5, 0x19 }, | ||
| 357 | { 0xd003, 0, 5, 0x1a }, | ||
| 358 | { 0xd004, 0, 5, 0x19 }, | ||
| 359 | { 0xd005, 0, 5, 0x1a }, | ||
| 360 | { 0xd00e, 0, 5, 0x10 }, | ||
| 361 | { 0xd00f, 0, 3, 0x04 }, | ||
| 362 | { 0xd00f, 3, 3, 0x05 }, | ||
| 363 | { 0xd010, 0, 3, 0x04 }, | ||
| 364 | { 0xd010, 3, 3, 0x05 }, | ||
| 365 | { 0xd016, 4, 4, 0x03 }, | ||
| 366 | { 0xd01f, 0, 6, 0x0a }, | ||
| 367 | { 0xd020, 0, 6, 0x0a }, | ||
| 368 | { 0xd015, 0, 8, 0x46 }, | ||
| 369 | { 0xd016, 0, 1, 0x00 }, | ||
| 370 | { 0xd044, 0, 8, 0x46 }, | ||
| 371 | { 0xd045, 0, 1, 0x00 }, | ||
| 372 | { 0xd008, 0, 8, 0x0f }, | ||
| 373 | { 0xd009, 0, 2, 0x02 }, | ||
| 374 | { 0xd006, 0, 8, 0x32 }, | ||
| 375 | { 0xd007, 0, 2, 0x01 }, | ||
| 376 | { 0xd00c, 0, 8, 0x36 }, | ||
| 377 | { 0xd00d, 0, 2, 0x03 }, | ||
| 378 | { 0xd00a, 0, 8, 0x35 }, | ||
| 379 | { 0xd00b, 0, 2, 0x01 }, | ||
| 380 | { 0x9bc7, 0, 8, 0x07 }, | ||
| 381 | { 0x9bc8, 0, 8, 0x90 }, | ||
| 382 | { 0x9bc3, 0, 8, 0x0f }, | ||
| 383 | { 0x9bc4, 0, 8, 0x02 }, | ||
| 384 | { 0x9bc5, 0, 8, 0x36 }, | ||
| 385 | { 0x9bc6, 0, 8, 0x03 }, | ||
| 386 | { 0x9bba, 0, 8, 0xc9 }, | ||
| 387 | { 0x9bc9, 0, 8, 0x79 }, | ||
| 388 | { 0xd011, 0, 8, 0x10 }, | ||
| 389 | { 0xd012, 0, 2, 0x01 }, | ||
| 390 | { 0xd013, 0, 8, 0x45 }, | ||
| 391 | { 0xd014, 0, 2, 0x03 }, | ||
| 392 | { 0xd040, 0, 8, 0x98 }, | ||
| 393 | { 0xd041, 0, 2, 0x00 }, | ||
| 394 | { 0xd042, 0, 8, 0xcf }, | ||
| 395 | { 0xd043, 0, 2, 0x03 }, | ||
| 396 | { 0xd045, 1, 1, 0x00 }, | ||
| 397 | { 0x9bcf, 0, 8, 0x01 }, | ||
| 398 | { 0xd045, 2, 1, 0x01 }, | ||
| 399 | { 0xd04f, 0, 8, 0x9a }, | ||
| 400 | { 0xd050, 0, 1, 0x01 }, | ||
| 401 | { 0xd051, 0, 8, 0x5a }, | ||
| 402 | { 0xd052, 0, 1, 0x01 }, | ||
| 403 | { 0xd053, 0, 8, 0x96 }, | ||
| 404 | { 0xd054, 0, 8, 0x46 }, | ||
| 405 | { 0xd045, 7, 1, 0x00 }, | ||
| 406 | { 0x9bd7, 0, 8, 0x0a }, | ||
| 407 | { 0x9bd8, 0, 8, 0x14 }, | ||
| 408 | { 0x9bd9, 0, 8, 0x08 }, | ||
| 409 | }; | ||
| 410 | |||
| 411 | /* MaxLinear MXL5003 tuner init | ||
| 412 | AF9013_TUNER_MXL5003D = 3 */ | ||
| 413 | static struct regdesc tuner_init_mxl5003d[] = { | ||
| 414 | { 0x9bd5, 0, 8, 0x01 }, | ||
| 415 | { 0x9bd6, 0, 8, 0x09 }, | ||
| 416 | { 0xd1a0, 1, 1, 0x01 }, | ||
| 417 | { 0xd000, 0, 1, 0x01 }, | ||
| 418 | { 0xd000, 1, 1, 0x00 }, | ||
| 419 | { 0xd001, 1, 1, 0x01 }, | ||
| 420 | { 0xd001, 0, 1, 0x00 }, | ||
| 421 | { 0xd001, 5, 1, 0x00 }, | ||
| 422 | { 0xd002, 0, 5, 0x19 }, | ||
| 423 | { 0xd003, 0, 5, 0x1a }, | ||
| 424 | { 0xd004, 0, 5, 0x19 }, | ||
| 425 | { 0xd005, 0, 5, 0x1a }, | ||
| 426 | { 0xd00e, 0, 5, 0x10 }, | ||
| 427 | { 0xd00f, 0, 3, 0x04 }, | ||
| 428 | { 0xd00f, 3, 3, 0x05 }, | ||
| 429 | { 0xd010, 0, 3, 0x04 }, | ||
| 430 | { 0xd010, 3, 3, 0x05 }, | ||
| 431 | { 0xd016, 4, 4, 0x03 }, | ||
| 432 | { 0xd01f, 0, 6, 0x0a }, | ||
| 433 | { 0xd020, 0, 6, 0x0a }, | ||
| 434 | { 0x9bda, 0, 8, 0x00 }, | ||
| 435 | { 0x9be3, 0, 8, 0x00 }, | ||
| 436 | { 0x9bfc, 0, 8, 0x0f }, | ||
| 437 | { 0x9bf6, 0, 8, 0x01 }, | ||
| 438 | { 0x9bbe, 0, 1, 0x01 }, | ||
| 439 | { 0xd015, 0, 8, 0x33 }, | ||
| 440 | { 0xd016, 0, 1, 0x00 }, | ||
| 441 | { 0xd044, 0, 8, 0x40 }, | ||
| 442 | { 0xd045, 0, 1, 0x00 }, | ||
| 443 | { 0xd008, 0, 8, 0x0f }, | ||
| 444 | { 0xd009, 0, 2, 0x02 }, | ||
| 445 | { 0xd006, 0, 8, 0x6c }, | ||
| 446 | { 0xd007, 0, 2, 0x00 }, | ||
| 447 | { 0xd00c, 0, 8, 0x3d }, | ||
| 448 | { 0xd00d, 0, 2, 0x00 }, | ||
| 449 | { 0xd00a, 0, 8, 0x45 }, | ||
| 450 | { 0xd00b, 0, 2, 0x01 }, | ||
| 451 | { 0x9bc7, 0, 8, 0x07 }, | ||
| 452 | { 0x9bc8, 0, 8, 0x52 }, | ||
| 453 | { 0x9bc3, 0, 8, 0x0f }, | ||
| 454 | { 0x9bc4, 0, 8, 0x02 }, | ||
| 455 | { 0x9bc5, 0, 8, 0x3d }, | ||
| 456 | { 0x9bc6, 0, 8, 0x00 }, | ||
| 457 | { 0x9bba, 0, 8, 0xa2 }, | ||
| 458 | { 0x9bc9, 0, 8, 0xa0 }, | ||
| 459 | { 0xd011, 0, 8, 0x56 }, | ||
| 460 | { 0xd012, 0, 2, 0x00 }, | ||
| 461 | { 0xd013, 0, 8, 0x50 }, | ||
| 462 | { 0xd014, 0, 2, 0x00 }, | ||
| 463 | { 0xd040, 0, 8, 0x56 }, | ||
| 464 | { 0xd041, 0, 2, 0x00 }, | ||
| 465 | { 0xd042, 0, 8, 0x50 }, | ||
| 466 | { 0xd043, 0, 2, 0x00 }, | ||
| 467 | { 0xd045, 1, 1, 0x00 }, | ||
| 468 | { 0x9bcf, 0, 8, 0x01 }, | ||
| 469 | { 0xd045, 2, 1, 0x01 }, | ||
| 470 | { 0xd04f, 0, 8, 0x9a }, | ||
| 471 | { 0xd050, 0, 1, 0x01 }, | ||
| 472 | { 0xd051, 0, 8, 0x5a }, | ||
| 473 | { 0xd052, 0, 1, 0x01 }, | ||
| 474 | { 0xd053, 0, 8, 0x50 }, | ||
| 475 | { 0xd054, 0, 8, 0x46 }, | ||
| 476 | { 0x9bd7, 0, 8, 0x0a }, | ||
| 477 | { 0x9bd8, 0, 8, 0x14 }, | ||
| 478 | { 0x9bd9, 0, 8, 0x08 }, | ||
| 479 | }; | ||
| 480 | |||
| 481 | /* MaxLinear MXL5005 tuner init | ||
| 482 | AF9013_TUNER_MXL5005D = 13 | ||
| 483 | AF9013_TUNER_MXL5005R = 30 */ | ||
| 484 | static struct regdesc tuner_init_mxl5005[] = { | ||
| 485 | { 0x9bd5, 0, 8, 0x01 }, | ||
| 486 | { 0x9bd6, 0, 8, 0x07 }, | ||
| 487 | { 0xd1a0, 1, 1, 0x01 }, | ||
| 488 | { 0xd000, 0, 1, 0x01 }, | ||
| 489 | { 0xd000, 1, 1, 0x00 }, | ||
| 490 | { 0xd001, 1, 1, 0x01 }, | ||
| 491 | { 0xd001, 0, 1, 0x00 }, | ||
| 492 | { 0xd001, 5, 1, 0x00 }, | ||
| 493 | { 0xd002, 0, 5, 0x19 }, | ||
| 494 | { 0xd003, 0, 5, 0x1a }, | ||
| 495 | { 0xd004, 0, 5, 0x19 }, | ||
| 496 | { 0xd005, 0, 5, 0x1a }, | ||
| 497 | { 0xd00e, 0, 5, 0x10 }, | ||
| 498 | { 0xd00f, 0, 3, 0x04 }, | ||
| 499 | { 0xd00f, 3, 3, 0x05 }, | ||
| 500 | { 0xd010, 0, 3, 0x04 }, | ||
| 501 | { 0xd010, 3, 3, 0x05 }, | ||
| 502 | { 0xd016, 4, 4, 0x03 }, | ||
| 503 | { 0xd01f, 0, 6, 0x0a }, | ||
| 504 | { 0xd020, 0, 6, 0x0a }, | ||
| 505 | { 0x9bda, 0, 8, 0x01 }, | ||
| 506 | { 0x9be3, 0, 8, 0x01 }, | ||
| 507 | { 0x9bbe, 0, 1, 0x01 }, | ||
| 508 | { 0x9bcc, 0, 1, 0x01 }, | ||
| 509 | { 0x9bb9, 0, 8, 0x00 }, | ||
| 510 | { 0x9bcd, 0, 8, 0x28 }, | ||
| 511 | { 0x9bff, 0, 8, 0x24 }, | ||
| 512 | { 0xd015, 0, 8, 0x40 }, | ||
| 513 | { 0xd016, 0, 1, 0x00 }, | ||
| 514 | { 0xd044, 0, 8, 0x40 }, | ||
| 515 | { 0xd045, 0, 1, 0x00 }, | ||
| 516 | { 0xd008, 0, 8, 0x0f }, | ||
| 517 | { 0xd009, 0, 2, 0x02 }, | ||
| 518 | { 0xd006, 0, 8, 0x73 }, | ||
| 519 | { 0xd007, 0, 2, 0x01 }, | ||
| 520 | { 0xd00c, 0, 8, 0xfa }, | ||
| 521 | { 0xd00d, 0, 2, 0x01 }, | ||
| 522 | { 0xd00a, 0, 8, 0xff }, | ||
| 523 | { 0xd00b, 0, 2, 0x01 }, | ||
| 524 | { 0x9bc7, 0, 8, 0x23 }, | ||
| 525 | { 0x9bc8, 0, 8, 0x55 }, | ||
| 526 | { 0x9bc3, 0, 8, 0x01 }, | ||
| 527 | { 0x9bc4, 0, 8, 0x02 }, | ||
| 528 | { 0x9bc5, 0, 8, 0xfa }, | ||
| 529 | { 0x9bc6, 0, 8, 0x01 }, | ||
| 530 | { 0x9bba, 0, 8, 0xff }, | ||
| 531 | { 0x9bc9, 0, 8, 0xff }, | ||
| 532 | { 0x9bd3, 0, 8, 0x95 }, | ||
| 533 | { 0xd011, 0, 8, 0x70 }, | ||
| 534 | { 0xd012, 0, 2, 0x01 }, | ||
| 535 | { 0xd013, 0, 8, 0xfb }, | ||
| 536 | { 0xd014, 0, 2, 0x01 }, | ||
| 537 | { 0xd040, 0, 8, 0x70 }, | ||
| 538 | { 0xd041, 0, 2, 0x01 }, | ||
| 539 | { 0xd042, 0, 8, 0xfb }, | ||
| 540 | { 0xd043, 0, 2, 0x01 }, | ||
| 541 | { 0xd045, 1, 1, 0x00 }, | ||
| 542 | { 0x9bcf, 0, 1, 0x01 }, | ||
| 543 | { 0xd045, 2, 1, 0x01 }, | ||
| 544 | { 0xd04f, 0, 8, 0x9a }, | ||
| 545 | { 0xd050, 0, 1, 0x01 }, | ||
| 546 | { 0xd051, 0, 8, 0x5a }, | ||
| 547 | { 0xd052, 0, 1, 0x01 }, | ||
| 548 | { 0xd053, 0, 8, 0x50 }, | ||
| 549 | { 0xd054, 0, 8, 0x46 }, | ||
| 550 | { 0x9bd7, 0, 8, 0x0a }, | ||
| 551 | { 0x9bd8, 0, 8, 0x14 }, | ||
| 552 | { 0x9bd9, 0, 8, 0x08 }, | ||
| 553 | { 0x9bd0, 0, 8, 0x93 }, | ||
| 554 | { 0x9be4, 0, 8, 0xfe }, | ||
| 555 | { 0x9bbd, 0, 8, 0x63 }, | ||
| 556 | { 0x9be2, 0, 8, 0xfe }, | ||
| 557 | { 0x9bee, 0, 1, 0x01 }, | ||
| 558 | }; | ||
| 559 | |||
| 560 | /* Quantek QT1010 tuner init | ||
| 561 | AF9013_TUNER_QT1010 = 134 | ||
| 562 | AF9013_TUNER_QT1010A = 162 */ | ||
| 563 | static struct regdesc tuner_init_qt1010[] = { | ||
| 564 | { 0x9bd5, 0, 8, 0x01 }, | ||
| 565 | { 0x9bd6, 0, 8, 0x09 }, | ||
| 566 | { 0xd1a0, 1, 1, 0x01 }, | ||
| 567 | { 0xd000, 0, 1, 0x01 }, | ||
| 568 | { 0xd000, 1, 1, 0x00 }, | ||
| 569 | { 0xd001, 1, 1, 0x01 }, | ||
| 570 | { 0xd001, 0, 1, 0x00 }, | ||
| 571 | { 0xd001, 5, 1, 0x00 }, | ||
| 572 | { 0xd002, 0, 5, 0x19 }, | ||
| 573 | { 0xd003, 0, 5, 0x1a }, | ||
| 574 | { 0xd004, 0, 5, 0x19 }, | ||
| 575 | { 0xd005, 0, 5, 0x1a }, | ||
| 576 | { 0xd00e, 0, 5, 0x10 }, | ||
| 577 | { 0xd00f, 0, 3, 0x04 }, | ||
| 578 | { 0xd00f, 3, 3, 0x05 }, | ||
| 579 | { 0xd010, 0, 3, 0x04 }, | ||
| 580 | { 0xd010, 3, 3, 0x05 }, | ||
| 581 | { 0xd016, 4, 4, 0x03 }, | ||
| 582 | { 0xd01f, 0, 6, 0x0a }, | ||
| 583 | { 0xd020, 0, 6, 0x0a }, | ||
| 584 | { 0x9bda, 0, 8, 0x01 }, | ||
| 585 | { 0x9be3, 0, 8, 0x01 }, | ||
| 586 | { 0xd015, 0, 8, 0x46 }, | ||
| 587 | { 0xd016, 0, 1, 0x00 }, | ||
| 588 | { 0xd044, 0, 8, 0x46 }, | ||
| 589 | { 0xd045, 0, 1, 0x00 }, | ||
| 590 | { 0x9bbe, 0, 1, 0x01 }, | ||
| 591 | { 0x9bcc, 0, 1, 0x01 }, | ||
| 592 | { 0x9bb9, 0, 8, 0x00 }, | ||
| 593 | { 0x9bcd, 0, 8, 0x28 }, | ||
| 594 | { 0x9bff, 0, 8, 0x20 }, | ||
| 595 | { 0xd008, 0, 8, 0x0f }, | ||
| 596 | { 0xd009, 0, 2, 0x02 }, | ||
| 597 | { 0xd006, 0, 8, 0x99 }, | ||
| 598 | { 0xd007, 0, 2, 0x01 }, | ||
| 599 | { 0xd00c, 0, 8, 0x0f }, | ||
| 600 | { 0xd00d, 0, 2, 0x02 }, | ||
| 601 | { 0xd00a, 0, 8, 0x50 }, | ||
| 602 | { 0xd00b, 0, 2, 0x01 }, | ||
| 603 | { 0x9bc7, 0, 8, 0x00 }, | ||
| 604 | { 0x9bc8, 0, 8, 0x00 }, | ||
| 605 | { 0x9bc3, 0, 8, 0x0f }, | ||
| 606 | { 0x9bc4, 0, 8, 0x02 }, | ||
| 607 | { 0x9bc5, 0, 8, 0x0f }, | ||
| 608 | { 0x9bc6, 0, 8, 0x02 }, | ||
| 609 | { 0x9bba, 0, 8, 0xc5 }, | ||
| 610 | { 0x9bc9, 0, 8, 0xff }, | ||
| 611 | { 0xd011, 0, 8, 0x58 }, | ||
| 612 | { 0xd012, 0, 2, 0x02 }, | ||
| 613 | { 0xd013, 0, 8, 0x89 }, | ||
| 614 | { 0xd014, 0, 2, 0x01 }, | ||
| 615 | { 0xd040, 0, 8, 0x58 }, | ||
| 616 | { 0xd041, 0, 2, 0x02 }, | ||
| 617 | { 0xd042, 0, 8, 0x89 }, | ||
| 618 | { 0xd043, 0, 2, 0x01 }, | ||
| 619 | { 0xd045, 1, 1, 0x00 }, | ||
| 620 | { 0x9bcf, 0, 1, 0x01 }, | ||
| 621 | { 0xd045, 2, 1, 0x01 }, | ||
| 622 | { 0xd04f, 0, 8, 0x9a }, | ||
| 623 | { 0xd050, 0, 1, 0x01 }, | ||
| 624 | { 0xd051, 0, 8, 0x5a }, | ||
| 625 | { 0xd052, 0, 1, 0x01 }, | ||
| 626 | { 0xd053, 0, 8, 0x50 }, | ||
| 627 | { 0xd054, 0, 8, 0x46 }, | ||
| 628 | { 0x9bd7, 0, 8, 0x0a }, | ||
| 629 | { 0x9bd8, 0, 8, 0x14 }, | ||
| 630 | { 0x9bd9, 0, 8, 0x08 }, | ||
| 631 | { 0x9bd0, 0, 8, 0xcd }, | ||
| 632 | { 0x9be4, 0, 8, 0xbb }, | ||
| 633 | { 0x9bbd, 0, 8, 0x93 }, | ||
| 634 | { 0x9be2, 0, 8, 0x80 }, | ||
| 635 | { 0x9bee, 0, 1, 0x01 }, | ||
| 636 | }; | ||
| 637 | |||
| 638 | /* Freescale MC44S803 tuner init | ||
| 639 | AF9013_TUNER_MC44S803 = 133 */ | ||
| 640 | static struct regdesc tuner_init_mc44s803[] = { | ||
| 641 | { 0x9bd5, 0, 8, 0x01 }, | ||
| 642 | { 0x9bd6, 0, 8, 0x06 }, | ||
| 643 | { 0xd1a0, 1, 1, 0x01 }, | ||
| 644 | { 0xd000, 0, 1, 0x01 }, | ||
| 645 | { 0xd000, 1, 1, 0x00 }, | ||
| 646 | { 0xd001, 1, 1, 0x01 }, | ||
| 647 | { 0xd001, 0, 1, 0x00 }, | ||
| 648 | { 0xd001, 5, 1, 0x00 }, | ||
| 649 | { 0xd002, 0, 5, 0x19 }, | ||
| 650 | { 0xd003, 0, 5, 0x1a }, | ||
| 651 | { 0xd004, 0, 5, 0x19 }, | ||
| 652 | { 0xd005, 0, 5, 0x1a }, | ||
| 653 | { 0xd00e, 0, 5, 0x10 }, | ||
| 654 | { 0xd00f, 0, 3, 0x04 }, | ||
| 655 | { 0xd00f, 3, 3, 0x05 }, | ||
| 656 | { 0xd010, 0, 3, 0x04 }, | ||
| 657 | { 0xd010, 3, 3, 0x05 }, | ||
| 658 | { 0xd016, 4, 4, 0x03 }, | ||
| 659 | { 0xd01f, 0, 6, 0x0a }, | ||
| 660 | { 0xd020, 0, 6, 0x0a }, | ||
| 661 | { 0x9bda, 0, 8, 0x00 }, | ||
| 662 | { 0x9be3, 0, 8, 0x00 }, | ||
| 663 | { 0x9bf6, 0, 8, 0x01 }, | ||
| 664 | { 0x9bf8, 0, 8, 0x02 }, | ||
| 665 | { 0x9bf9, 0, 8, 0x02 }, | ||
| 666 | { 0x9bfc, 0, 8, 0x1f }, | ||
| 667 | { 0x9bbe, 0, 1, 0x01 }, | ||
| 668 | { 0x9bcc, 0, 1, 0x01 }, | ||
| 669 | { 0x9bb9, 0, 8, 0x00 }, | ||
| 670 | { 0x9bcd, 0, 8, 0x24 }, | ||
| 671 | { 0x9bff, 0, 8, 0x24 }, | ||
| 672 | { 0xd015, 0, 8, 0x46 }, | ||
| 673 | { 0xd016, 0, 1, 0x00 }, | ||
| 674 | { 0xd044, 0, 8, 0x46 }, | ||
| 675 | { 0xd045, 0, 1, 0x00 }, | ||
| 676 | { 0xd008, 0, 8, 0x01 }, | ||
| 677 | { 0xd009, 0, 2, 0x02 }, | ||
| 678 | { 0xd006, 0, 8, 0x7b }, | ||
| 679 | { 0xd007, 0, 2, 0x00 }, | ||
| 680 | { 0xd00c, 0, 8, 0x7c }, | ||
| 681 | { 0xd00d, 0, 2, 0x02 }, | ||
| 682 | { 0xd00a, 0, 8, 0xfe }, | ||
| 683 | { 0xd00b, 0, 2, 0x01 }, | ||
| 684 | { 0x9bc7, 0, 8, 0x08 }, | ||
| 685 | { 0x9bc8, 0, 8, 0x9a }, | ||
| 686 | { 0x9bc3, 0, 8, 0x01 }, | ||
| 687 | { 0x9bc4, 0, 8, 0x02 }, | ||
| 688 | { 0x9bc5, 0, 8, 0x7c }, | ||
| 689 | { 0x9bc6, 0, 8, 0x02 }, | ||
| 690 | { 0x9bba, 0, 8, 0xfc }, | ||
| 691 | { 0x9bc9, 0, 8, 0xaa }, | ||
| 692 | { 0xd011, 0, 8, 0x6b }, | ||
| 693 | { 0xd012, 0, 2, 0x00 }, | ||
| 694 | { 0xd013, 0, 8, 0x88 }, | ||
| 695 | { 0xd014, 0, 2, 0x02 }, | ||
| 696 | { 0xd040, 0, 8, 0x6b }, | ||
| 697 | { 0xd041, 0, 2, 0x00 }, | ||
| 698 | { 0xd042, 0, 8, 0x7c }, | ||
| 699 | { 0xd043, 0, 2, 0x02 }, | ||
| 700 | { 0xd045, 1, 1, 0x00 }, | ||
| 701 | { 0x9bcf, 0, 1, 0x01 }, | ||
| 702 | { 0xd045, 2, 1, 0x01 }, | ||
| 703 | { 0xd04f, 0, 8, 0x9a }, | ||
| 704 | { 0xd050, 0, 1, 0x01 }, | ||
| 705 | { 0xd051, 0, 8, 0x5a }, | ||
| 706 | { 0xd052, 0, 1, 0x01 }, | ||
| 707 | { 0xd053, 0, 8, 0x50 }, | ||
| 708 | { 0xd054, 0, 8, 0x46 }, | ||
| 709 | { 0x9bd7, 0, 8, 0x0a }, | ||
| 710 | { 0x9bd8, 0, 8, 0x14 }, | ||
| 711 | { 0x9bd9, 0, 8, 0x08 }, | ||
| 712 | { 0x9bd0, 0, 8, 0x9e }, | ||
| 713 | { 0x9be4, 0, 8, 0xff }, | ||
| 714 | { 0x9bbd, 0, 8, 0x9e }, | ||
| 715 | { 0x9be2, 0, 8, 0x25 }, | ||
| 716 | { 0x9bee, 0, 1, 0x01 }, | ||
| 717 | { 0xd73b, 3, 1, 0x00 }, | ||
| 718 | }; | ||
| 719 | |||
| 720 | /* unknown, probably for tin can tuner, tuner init | ||
| 721 | AF9013_TUNER_UNKNOWN = 140 */ | ||
| 722 | static struct regdesc tuner_init_unknown[] = { | ||
| 723 | { 0x9bd5, 0, 8, 0x01 }, | ||
| 724 | { 0x9bd6, 0, 8, 0x02 }, | ||
| 725 | { 0xd1a0, 1, 1, 0x01 }, | ||
| 726 | { 0xd000, 0, 1, 0x01 }, | ||
| 727 | { 0xd000, 1, 1, 0x00 }, | ||
| 728 | { 0xd001, 1, 1, 0x01 }, | ||
| 729 | { 0xd001, 0, 1, 0x00 }, | ||
| 730 | { 0xd001, 5, 1, 0x00 }, | ||
| 731 | { 0xd002, 0, 5, 0x19 }, | ||
| 732 | { 0xd003, 0, 5, 0x1a }, | ||
| 733 | { 0xd004, 0, 5, 0x19 }, | ||
| 734 | { 0xd005, 0, 5, 0x1a }, | ||
| 735 | { 0xd00e, 0, 5, 0x10 }, | ||
| 736 | { 0xd00f, 0, 3, 0x04 }, | ||
| 737 | { 0xd00f, 3, 3, 0x05 }, | ||
| 738 | { 0xd010, 0, 3, 0x04 }, | ||
| 739 | { 0xd010, 3, 3, 0x05 }, | ||
| 740 | { 0xd016, 4, 4, 0x03 }, | ||
| 741 | { 0xd01f, 0, 6, 0x0a }, | ||
| 742 | { 0xd020, 0, 6, 0x0a }, | ||
| 743 | { 0x9bda, 0, 8, 0x01 }, | ||
| 744 | { 0x9be3, 0, 8, 0x01 }, | ||
| 745 | { 0xd1a0, 1, 1, 0x00 }, | ||
| 746 | { 0x9bbe, 0, 1, 0x01 }, | ||
| 747 | { 0x9bcc, 0, 1, 0x01 }, | ||
| 748 | { 0x9bb9, 0, 8, 0x00 }, | ||
| 749 | { 0x9bcd, 0, 8, 0x18 }, | ||
| 750 | { 0x9bff, 0, 8, 0x2c }, | ||
| 751 | { 0xd015, 0, 8, 0x46 }, | ||
| 752 | { 0xd016, 0, 1, 0x00 }, | ||
| 753 | { 0xd044, 0, 8, 0x46 }, | ||
| 754 | { 0xd045, 0, 1, 0x00 }, | ||
| 755 | { 0xd008, 0, 8, 0xdf }, | ||
| 756 | { 0xd009, 0, 2, 0x02 }, | ||
| 757 | { 0xd006, 0, 8, 0x44 }, | ||
| 758 | { 0xd007, 0, 2, 0x01 }, | ||
| 759 | { 0xd00c, 0, 8, 0x00 }, | ||
| 760 | { 0xd00d, 0, 2, 0x02 }, | ||
| 761 | { 0xd00a, 0, 8, 0xf6 }, | ||
| 762 | { 0xd00b, 0, 2, 0x01 }, | ||
| 763 | { 0x9bba, 0, 8, 0xf9 }, | ||
| 764 | { 0x9bc8, 0, 8, 0xaa }, | ||
| 765 | { 0x9bc3, 0, 8, 0xdf }, | ||
| 766 | { 0x9bc4, 0, 8, 0x02 }, | ||
| 767 | { 0x9bc5, 0, 8, 0x00 }, | ||
| 768 | { 0x9bc6, 0, 8, 0x02 }, | ||
| 769 | { 0x9bc9, 0, 8, 0xf0 }, | ||
| 770 | { 0xd011, 0, 8, 0x3c }, | ||
| 771 | { 0xd012, 0, 2, 0x01 }, | ||
| 772 | { 0xd013, 0, 8, 0xf7 }, | ||
| 773 | { 0xd014, 0, 2, 0x02 }, | ||
| 774 | { 0xd040, 0, 8, 0x0b }, | ||
| 775 | { 0xd041, 0, 2, 0x02 }, | ||
| 776 | { 0xd042, 0, 8, 0x4d }, | ||
| 777 | { 0xd043, 0, 2, 0x00 }, | ||
| 778 | { 0xd045, 1, 1, 0x00 }, | ||
| 779 | { 0x9bcf, 0, 1, 0x01 }, | ||
| 780 | { 0xd045, 2, 1, 0x01 }, | ||
| 781 | { 0xd04f, 0, 8, 0x9a }, | ||
| 782 | { 0xd050, 0, 1, 0x01 }, | ||
| 783 | { 0xd051, 0, 8, 0x5a }, | ||
| 784 | { 0xd052, 0, 1, 0x01 }, | ||
| 785 | { 0xd053, 0, 8, 0x50 }, | ||
| 786 | { 0xd054, 0, 8, 0x46 }, | ||
| 787 | { 0x9bd7, 0, 8, 0x0a }, | ||
| 788 | { 0x9bd8, 0, 8, 0x14 }, | ||
| 789 | { 0x9bd9, 0, 8, 0x08 }, | ||
| 790 | }; | ||
| 791 | |||
| 792 | /* NXP TDA18271 tuner init | ||
| 793 | AF9013_TUNER_TDA18271 = 156 */ | ||
| 794 | static struct regdesc tuner_init_tda18271[] = { | ||
| 795 | { 0x9bd5, 0, 8, 0x01 }, | ||
| 796 | { 0x9bd6, 0, 8, 0x04 }, | ||
| 797 | { 0xd1a0, 1, 1, 0x01 }, | ||
| 798 | { 0xd000, 0, 1, 0x01 }, | ||
| 799 | { 0xd000, 1, 1, 0x00 }, | ||
| 800 | { 0xd001, 1, 1, 0x01 }, | ||
| 801 | { 0xd001, 0, 1, 0x00 }, | ||
| 802 | { 0xd001, 5, 1, 0x00 }, | ||
| 803 | { 0xd002, 0, 5, 0x19 }, | ||
| 804 | { 0xd003, 0, 5, 0x1a }, | ||
| 805 | { 0xd004, 0, 5, 0x19 }, | ||
| 806 | { 0xd005, 0, 5, 0x1a }, | ||
| 807 | { 0xd00e, 0, 5, 0x10 }, | ||
| 808 | { 0xd00f, 0, 3, 0x04 }, | ||
| 809 | { 0xd00f, 3, 3, 0x05 }, | ||
| 810 | { 0xd010, 0, 3, 0x04 }, | ||
| 811 | { 0xd010, 3, 3, 0x05 }, | ||
| 812 | { 0xd016, 4, 4, 0x03 }, | ||
| 813 | { 0xd01f, 0, 6, 0x0a }, | ||
| 814 | { 0xd020, 0, 6, 0x0a }, | ||
| 815 | { 0x9bda, 0, 8, 0x01 }, | ||
| 816 | { 0x9be3, 0, 8, 0x01 }, | ||
| 817 | { 0xd1a0, 1, 1, 0x00 }, | ||
| 818 | { 0x9bbe, 0, 1, 0x01 }, | ||
| 819 | { 0x9bcc, 0, 1, 0x01 }, | ||
| 820 | { 0x9bb9, 0, 8, 0x00 }, | ||
| 821 | { 0x9bcd, 0, 8, 0x18 }, | ||
| 822 | { 0x9bff, 0, 8, 0x2c }, | ||
| 823 | { 0xd015, 0, 8, 0x46 }, | ||
| 824 | { 0xd016, 0, 1, 0x00 }, | ||
| 825 | { 0xd044, 0, 8, 0x46 }, | ||
| 826 | { 0xd045, 0, 1, 0x00 }, | ||
| 827 | { 0xd008, 0, 8, 0xdf }, | ||
| 828 | { 0xd009, 0, 2, 0x02 }, | ||
| 829 | { 0xd006, 0, 8, 0x44 }, | ||
| 830 | { 0xd007, 0, 2, 0x01 }, | ||
| 831 | { 0xd00c, 0, 8, 0x00 }, | ||
| 832 | { 0xd00d, 0, 2, 0x02 }, | ||
| 833 | { 0xd00a, 0, 8, 0xf6 }, | ||
| 834 | { 0xd00b, 0, 2, 0x01 }, | ||
| 835 | { 0x9bba, 0, 8, 0xf9 }, | ||
| 836 | { 0x9bc8, 0, 8, 0xaa }, | ||
| 837 | { 0x9bc3, 0, 8, 0xdf }, | ||
| 838 | { 0x9bc4, 0, 8, 0x02 }, | ||
| 839 | { 0x9bc5, 0, 8, 0x00 }, | ||
| 840 | { 0x9bc6, 0, 8, 0x02 }, | ||
| 841 | { 0x9bc9, 0, 8, 0xf0 }, | ||
| 842 | { 0xd011, 0, 8, 0x3c }, | ||
| 843 | { 0xd012, 0, 2, 0x01 }, | ||
| 844 | { 0xd013, 0, 8, 0xf7 }, | ||
| 845 | { 0xd014, 0, 2, 0x02 }, | ||
| 846 | { 0xd040, 0, 8, 0x0b }, | ||
| 847 | { 0xd041, 0, 2, 0x02 }, | ||
| 848 | { 0xd042, 0, 8, 0x4d }, | ||
| 849 | { 0xd043, 0, 2, 0x00 }, | ||
| 850 | { 0xd045, 1, 1, 0x00 }, | ||
| 851 | { 0x9bcf, 0, 1, 0x01 }, | ||
| 852 | { 0xd045, 2, 1, 0x01 }, | ||
| 853 | { 0xd04f, 0, 8, 0x9a }, | ||
| 854 | { 0xd050, 0, 1, 0x01 }, | ||
| 855 | { 0xd051, 0, 8, 0x5a }, | ||
| 856 | { 0xd052, 0, 1, 0x01 }, | ||
| 857 | { 0xd053, 0, 8, 0x50 }, | ||
| 858 | { 0xd054, 0, 8, 0x46 }, | ||
| 859 | { 0x9bd7, 0, 8, 0x0a }, | ||
| 860 | { 0x9bd8, 0, 8, 0x14 }, | ||
| 861 | { 0x9bd9, 0, 8, 0x08 }, | ||
| 862 | { 0x9bd0, 0, 8, 0xa8 }, | ||
| 863 | { 0x9be4, 0, 8, 0x7f }, | ||
| 864 | { 0x9bbd, 0, 8, 0xa8 }, | ||
| 865 | { 0x9be2, 0, 8, 0x20 }, | ||
| 866 | { 0x9bee, 0, 1, 0x01 }, | ||
| 867 | }; | ||
| 868 | |||
| 869 | #endif /* _AF9013_PRIV_ */ | ||
diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index 0b82cc2a1e16..eabf9a68e7ec 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c | |||
| @@ -40,6 +40,8 @@ struct au8522_state { | |||
| 40 | u32 current_frequency; | 40 | u32 current_frequency; |
| 41 | fe_modulation_t current_modulation; | 41 | fe_modulation_t current_modulation; |
| 42 | 42 | ||
| 43 | u32 fe_status; | ||
| 44 | unsigned int led_state; | ||
| 43 | }; | 45 | }; |
| 44 | 46 | ||
| 45 | static int debug; | 47 | static int debug; |
| @@ -538,11 +540,98 @@ static int au8522_init(struct dvb_frontend *fe) | |||
| 538 | return 0; | 540 | return 0; |
| 539 | } | 541 | } |
| 540 | 542 | ||
| 543 | static int au8522_led_gpio_enable(struct au8522_state *state, int onoff) | ||
| 544 | { | ||
| 545 | struct au8522_led_config *led_config = state->config->led_cfg; | ||
| 546 | u8 val; | ||
| 547 | |||
| 548 | /* bail out if we cant control an LED */ | ||
| 549 | if (!led_config || !led_config->gpio_output || | ||
| 550 | !led_config->gpio_output_enable || !led_config->gpio_output_disable) | ||
| 551 | return 0; | ||
| 552 | |||
| 553 | val = au8522_readreg(state, 0x4000 | | ||
| 554 | (led_config->gpio_output & ~0xc000)); | ||
| 555 | if (onoff) { | ||
| 556 | /* enable GPIO output */ | ||
| 557 | val &= ~((led_config->gpio_output_enable >> 8) & 0xff); | ||
| 558 | val |= (led_config->gpio_output_enable & 0xff); | ||
| 559 | } else { | ||
| 560 | /* disable GPIO output */ | ||
| 561 | val &= ~((led_config->gpio_output_disable >> 8) & 0xff); | ||
| 562 | val |= (led_config->gpio_output_disable & 0xff); | ||
| 563 | } | ||
| 564 | return au8522_writereg(state, 0x8000 | | ||
| 565 | (led_config->gpio_output & ~0xc000), val); | ||
| 566 | } | ||
| 567 | |||
| 568 | /* led = 0 | off | ||
| 569 | * led = 1 | signal ok | ||
| 570 | * led = 2 | signal strong | ||
| 571 | * led < 0 | only light led if leds are currently off | ||
| 572 | */ | ||
| 573 | static int au8522_led_ctrl(struct au8522_state *state, int led) | ||
| 574 | { | ||
| 575 | struct au8522_led_config *led_config = state->config->led_cfg; | ||
| 576 | int i, ret = 0; | ||
| 577 | |||
| 578 | /* bail out if we cant control an LED */ | ||
| 579 | if (!led_config || !led_config->gpio_leds || | ||
| 580 | !led_config->num_led_states || !led_config->led_states) | ||
| 581 | return 0; | ||
| 582 | |||
| 583 | if (led < 0) { | ||
| 584 | /* if LED is already lit, then leave it as-is */ | ||
| 585 | if (state->led_state) | ||
| 586 | return 0; | ||
| 587 | else | ||
| 588 | led *= -1; | ||
| 589 | } | ||
| 590 | |||
| 591 | /* toggle LED if changing state */ | ||
| 592 | if (state->led_state != led) { | ||
| 593 | u8 val; | ||
| 594 | |||
| 595 | dprintk("%s: %d\n", __func__, led); | ||
| 596 | |||
| 597 | au8522_led_gpio_enable(state, 1); | ||
| 598 | |||
| 599 | val = au8522_readreg(state, 0x4000 | | ||
| 600 | (led_config->gpio_leds & ~0xc000)); | ||
| 601 | |||
| 602 | /* start with all leds off */ | ||
| 603 | for (i = 0; i < led_config->num_led_states; i++) | ||
| 604 | val &= ~led_config->led_states[i]; | ||
| 605 | |||
| 606 | /* set selected LED state */ | ||
| 607 | if (led < led_config->num_led_states) | ||
| 608 | val |= led_config->led_states[led]; | ||
| 609 | else if (led_config->num_led_states) | ||
| 610 | val |= | ||
| 611 | led_config->led_states[led_config->num_led_states - 1]; | ||
| 612 | |||
| 613 | ret = au8522_writereg(state, 0x8000 | | ||
| 614 | (led_config->gpio_leds & ~0xc000), val); | ||
| 615 | if (ret < 0) | ||
| 616 | return ret; | ||
| 617 | |||
| 618 | state->led_state = led; | ||
| 619 | |||
| 620 | if (led == 0) | ||
| 621 | au8522_led_gpio_enable(state, 0); | ||
| 622 | } | ||
| 623 | |||
| 624 | return 0; | ||
| 625 | } | ||
| 626 | |||
| 541 | static int au8522_sleep(struct dvb_frontend *fe) | 627 | static int au8522_sleep(struct dvb_frontend *fe) |
| 542 | { | 628 | { |
| 543 | struct au8522_state *state = fe->demodulator_priv; | 629 | struct au8522_state *state = fe->demodulator_priv; |
| 544 | dprintk("%s()\n", __func__); | 630 | dprintk("%s()\n", __func__); |
| 545 | 631 | ||
| 632 | /* turn off led */ | ||
| 633 | au8522_led_ctrl(state, 0); | ||
| 634 | |||
| 546 | state->current_frequency = 0; | 635 | state->current_frequency = 0; |
| 547 | 636 | ||
| 548 | return 0; | 637 | return 0; |
| @@ -592,12 +681,53 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) | |||
| 592 | *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; | 681 | *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; |
| 593 | break; | 682 | break; |
| 594 | } | 683 | } |
| 684 | state->fe_status = *status; | ||
| 685 | |||
| 686 | if (*status & FE_HAS_LOCK) | ||
| 687 | /* turn on LED, if it isn't on already */ | ||
| 688 | au8522_led_ctrl(state, -1); | ||
| 689 | else | ||
| 690 | /* turn off LED */ | ||
| 691 | au8522_led_ctrl(state, 0); | ||
| 595 | 692 | ||
| 596 | dprintk("%s() status 0x%08x\n", __func__, *status); | 693 | dprintk("%s() status 0x%08x\n", __func__, *status); |
| 597 | 694 | ||
| 598 | return 0; | 695 | return 0; |
| 599 | } | 696 | } |
| 600 | 697 | ||
| 698 | static int au8522_led_status(struct au8522_state *state, const u16 *snr) | ||
| 699 | { | ||
| 700 | struct au8522_led_config *led_config = state->config->led_cfg; | ||
| 701 | int led; | ||
| 702 | u16 strong; | ||
| 703 | |||
| 704 | /* bail out if we cant control an LED */ | ||
| 705 | if (!led_config) | ||
| 706 | return 0; | ||
| 707 | |||
| 708 | if (0 == (state->fe_status & FE_HAS_LOCK)) | ||
| 709 | return au8522_led_ctrl(state, 0); | ||
| 710 | else if (state->current_modulation == QAM_256) | ||
| 711 | strong = led_config->qam256_strong; | ||
| 712 | else if (state->current_modulation == QAM_64) | ||
| 713 | strong = led_config->qam64_strong; | ||
| 714 | else /* (state->current_modulation == VSB_8) */ | ||
| 715 | strong = led_config->vsb8_strong; | ||
| 716 | |||
| 717 | if (*snr >= strong) | ||
| 718 | led = 2; | ||
| 719 | else | ||
| 720 | led = 1; | ||
| 721 | |||
| 722 | if ((state->led_state) && | ||
| 723 | (((strong < *snr) ? (*snr - strong) : (strong - *snr)) <= 10)) | ||
| 724 | /* snr didn't change enough to bother | ||
| 725 | * changing the color of the led */ | ||
| 726 | return 0; | ||
| 727 | |||
| 728 | return au8522_led_ctrl(state, led); | ||
| 729 | } | ||
| 730 | |||
| 601 | static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) | 731 | static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) |
| 602 | { | 732 | { |
| 603 | struct au8522_state *state = fe->demodulator_priv; | 733 | struct au8522_state *state = fe->demodulator_priv; |
| @@ -621,6 +751,9 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr) | |||
| 621 | au8522_readreg(state, 0x4311), | 751 | au8522_readreg(state, 0x4311), |
| 622 | snr); | 752 | snr); |
| 623 | 753 | ||
| 754 | if (state->config->led_cfg) | ||
| 755 | au8522_led_status(state, snr); | ||
| 756 | |||
| 624 | return ret; | 757 | return ret; |
| 625 | } | 758 | } |
| 626 | 759 | ||
diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h index 595915ade8c3..7b94f554a093 100644 --- a/drivers/media/dvb/frontends/au8522.h +++ b/drivers/media/dvb/frontends/au8522.h | |||
| @@ -30,6 +30,21 @@ enum au8522_if_freq { | |||
| 30 | AU8522_IF_3_25MHZ, | 30 | AU8522_IF_3_25MHZ, |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | struct au8522_led_config { | ||
| 34 | u16 vsb8_strong; | ||
| 35 | u16 qam64_strong; | ||
| 36 | u16 qam256_strong; | ||
| 37 | |||
| 38 | u16 gpio_output; | ||
| 39 | /* unset hi bits, set low bits */ | ||
| 40 | u16 gpio_output_enable; | ||
| 41 | u16 gpio_output_disable; | ||
| 42 | |||
| 43 | u16 gpio_leds; | ||
| 44 | u8 *led_states; | ||
| 45 | unsigned int num_led_states; | ||
| 46 | }; | ||
| 47 | |||
| 33 | struct au8522_config { | 48 | struct au8522_config { |
| 34 | /* the demodulator's i2c address */ | 49 | /* the demodulator's i2c address */ |
| 35 | u8 demod_address; | 50 | u8 demod_address; |
| @@ -39,6 +54,8 @@ struct au8522_config { | |||
| 39 | #define AU8522_DEMODLOCKING 1 | 54 | #define AU8522_DEMODLOCKING 1 |
| 40 | u8 status_mode; | 55 | u8 status_mode; |
| 41 | 56 | ||
| 57 | struct au8522_led_config *led_cfg; | ||
| 58 | |||
| 42 | enum au8522_if_freq vsb_if; | 59 | enum au8522_if_freq vsb_if; |
| 43 | enum au8522_if_freq qam_if; | 60 | enum au8522_if_freq qam_if; |
| 44 | }; | 61 | }; |
diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h index 1792adb23c4d..fdcceee91f3a 100644 --- a/drivers/media/dvb/frontends/cx24110.h +++ b/drivers/media/dvb/frontends/cx24110.h | |||
| @@ -33,12 +33,17 @@ struct cx24110_config | |||
| 33 | u8 demod_address; | 33 | u8 demod_address; |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) { | 36 | static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) |
| 37 | int r = 0; | 37 | { |
| 38 | u8 buf[] = {(u8) (val>>24), (u8) (val>>16), (u8) (val>>8)}; | 38 | u8 buf[] = { |
| 39 | (u8)((val >> 24) & 0xff), | ||
| 40 | (u8)((val >> 16) & 0xff), | ||
| 41 | (u8)((val >> 8) & 0xff) | ||
| 42 | }; | ||
| 43 | |||
| 39 | if (fe->ops.write) | 44 | if (fe->ops.write) |
| 40 | r = fe->ops.write(fe, buf, 3); | 45 | return fe->ops.write(fe, buf, 3); |
| 41 | return r; | 46 | return 0; |
| 42 | } | 47 | } |
| 43 | 48 | ||
| 44 | #if defined(CONFIG_DVB_CX24110) || (defined(CONFIG_DVB_CX24110_MODULE) && defined(MODULE)) | 49 | #if defined(CONFIG_DVB_CX24110) || (defined(CONFIG_DVB_CX24110_MODULE) && defined(MODULE)) |
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c new file mode 100644 index 000000000000..deb36f469ada --- /dev/null +++ b/drivers/media/dvb/frontends/cx24116.c | |||
| @@ -0,0 +1,1423 @@ | |||
| 1 | /* | ||
| 2 | Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver | ||
| 3 | |||
| 4 | Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com> | ||
| 5 | Copyright (C) 2006-2007 Georg Acher | ||
| 6 | Copyright (C) 2007-2008 Darron Broad | ||
| 7 | March 2007 | ||
| 8 | Fixed some bugs. | ||
| 9 | Added diseqc support. | ||
| 10 | Added corrected signal strength support. | ||
| 11 | August 2007 | ||
| 12 | Sync with legacy version. | ||
| 13 | Some clean ups. | ||
| 14 | Copyright (C) 2008 Igor Liplianin | ||
| 15 | September, 9th 2008 | ||
| 16 | Fixed locking on high symbol rates (>30000). | ||
| 17 | Implement MPEG initialization parameter. | ||
| 18 | |||
| 19 | This program is free software; you can redistribute it and/or modify | ||
| 20 | it under the terms of the GNU General Public License as published by | ||
| 21 | the Free Software Foundation; either version 2 of the License, or | ||
| 22 | (at your option) any later version. | ||
| 23 | |||
| 24 | This program is distributed in the hope that it will be useful, | ||
| 25 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 27 | GNU General Public License for more details. | ||
| 28 | |||
| 29 | You should have received a copy of the GNU General Public License | ||
| 30 | along with this program; if not, write to the Free Software | ||
| 31 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include <linux/slab.h> | ||
| 35 | #include <linux/kernel.h> | ||
| 36 | #include <linux/module.h> | ||
| 37 | #include <linux/moduleparam.h> | ||
| 38 | #include <linux/init.h> | ||
| 39 | #include <linux/firmware.h> | ||
| 40 | |||
| 41 | #include "dvb_frontend.h" | ||
| 42 | #include "cx24116.h" | ||
| 43 | |||
| 44 | static int debug = 0; | ||
| 45 | #define dprintk(args...) \ | ||
| 46 | do { \ | ||
| 47 | if (debug) printk ("cx24116: " args); \ | ||
| 48 | } while (0) | ||
| 49 | |||
| 50 | #define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw" | ||
| 51 | #define CX24116_SEARCH_RANGE_KHZ 5000 | ||
| 52 | |||
| 53 | /* known registers */ | ||
| 54 | #define CX24116_REG_COMMAND (0x00) /* command args 0x00..0x1e */ | ||
| 55 | #define CX24116_REG_EXECUTE (0x1f) /* execute command */ | ||
| 56 | #define CX24116_REG_MAILBOX (0x96) /* FW or multipurpose mailbox? */ | ||
| 57 | #define CX24116_REG_RESET (0x20) /* reset status > 0 */ | ||
| 58 | #define CX24116_REG_SIGNAL (0x9e) /* signal low */ | ||
| 59 | #define CX24116_REG_SSTATUS (0x9d) /* signal high / status */ | ||
| 60 | #define CX24116_REG_QUALITY8 (0xa3) | ||
| 61 | #define CX24116_REG_QSTATUS (0xbc) | ||
| 62 | #define CX24116_REG_QUALITY0 (0xd5) | ||
| 63 | #define CX24116_REG_BER0 (0xc9) | ||
| 64 | #define CX24116_REG_BER8 (0xc8) | ||
| 65 | #define CX24116_REG_BER16 (0xc7) | ||
| 66 | #define CX24116_REG_BER24 (0xc6) | ||
| 67 | #define CX24116_REG_UCB0 (0xcb) | ||
| 68 | #define CX24116_REG_UCB8 (0xca) | ||
| 69 | #define CX24116_REG_CLKDIV (0xf3) | ||
| 70 | #define CX24116_REG_RATEDIV (0xf9) | ||
| 71 | #define CX24116_REG_FECSTATUS (0x9c) /* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */ | ||
| 72 | |||
| 73 | /* FECSTATUS bits */ | ||
| 74 | #define CX24116_FEC_FECMASK (0x1f) /* mask to determine configured fec (not tuned) or actual fec (tuned) */ | ||
| 75 | #define CX24116_FEC_DVBS (0x20) /* Select DVB-S demodulator, else DVB-S2 */ | ||
| 76 | #define CX24116_FEC_UNKNOWN (0x40) /* Unknown/unused */ | ||
| 77 | #define CX24116_FEC_PILOT (0x80) /* Pilot mode requested when tuning else always reset when tuned */ | ||
| 78 | |||
| 79 | /* arg buffer size */ | ||
| 80 | #define CX24116_ARGLEN (0x1e) | ||
| 81 | |||
| 82 | /* rolloff */ | ||
| 83 | #define CX24116_ROLLOFF_020 (0x00) | ||
| 84 | #define CX24116_ROLLOFF_025 (0x01) | ||
| 85 | #define CX24116_ROLLOFF_035 (0x02) | ||
| 86 | |||
| 87 | /* pilot bit */ | ||
| 88 | #define CX24116_PILOT_OFF (0x00) | ||
| 89 | #define CX24116_PILOT_ON (0x40) | ||
| 90 | |||
| 91 | /* signal status */ | ||
| 92 | #define CX24116_HAS_SIGNAL (0x01) | ||
| 93 | #define CX24116_HAS_CARRIER (0x02) | ||
| 94 | #define CX24116_HAS_VITERBI (0x04) | ||
| 95 | #define CX24116_HAS_SYNCLOCK (0x08) | ||
| 96 | #define CX24116_HAS_UNKNOWN1 (0x10) | ||
| 97 | #define CX24116_HAS_UNKNOWN2 (0x20) | ||
| 98 | #define CX24116_STATUS_MASK (0x3f) | ||
| 99 | #define CX24116_SIGNAL_MASK (0xc0) | ||
| 100 | |||
| 101 | #define CX24116_DISEQC_TONEOFF (0) /* toneburst never sent */ | ||
| 102 | #define CX24116_DISEQC_TONECACHE (1) /* toneburst cached */ | ||
| 103 | #define CX24116_DISEQC_MESGCACHE (2) /* message cached */ | ||
| 104 | |||
| 105 | /* arg offset for DiSEqC */ | ||
| 106 | #define CX24116_DISEQC_BURST (1) | ||
| 107 | #define CX24116_DISEQC_ARG2_2 (2) /* unknown value=2 */ | ||
| 108 | #define CX24116_DISEQC_ARG3_0 (3) /* unknown value=0 */ | ||
| 109 | #define CX24116_DISEQC_ARG4_0 (4) /* unknown value=0 */ | ||
| 110 | #define CX24116_DISEQC_MSGLEN (5) | ||
| 111 | #define CX24116_DISEQC_MSGOFS (6) | ||
| 112 | |||
| 113 | /* DiSEqC burst */ | ||
| 114 | #define CX24116_DISEQC_MINI_A (0) | ||
| 115 | #define CX24116_DISEQC_MINI_B (1) | ||
| 116 | |||
| 117 | /* DiSEqC tone burst */ | ||
| 118 | static int toneburst = 1; | ||
| 119 | |||
| 120 | /* SNR measurements */ | ||
| 121 | static int esno_snr = 0; | ||
| 122 | |||
| 123 | enum cmds | ||
| 124 | { | ||
| 125 | CMD_SET_VCO = 0x10, | ||
| 126 | CMD_TUNEREQUEST = 0x11, | ||
| 127 | CMD_MPEGCONFIG = 0x13, | ||
| 128 | CMD_TUNERINIT = 0x14, | ||
| 129 | CMD_BANDWIDTH = 0x15, | ||
| 130 | CMD_GETAGC = 0x19, | ||
| 131 | CMD_LNBCONFIG = 0x20, | ||
| 132 | CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */ | ||
| 133 | CMD_SET_TONEPRE = 0x22, | ||
| 134 | CMD_SET_TONE = 0x23, | ||
| 135 | CMD_UPDFWVERS = 0x35, | ||
| 136 | CMD_TUNERSLEEP = 0x36, | ||
| 137 | CMD_AGCCONTROL = 0x3b, /* Unknown */ | ||
| 138 | }; | ||
| 139 | |||
| 140 | /* The Demod/Tuner can't easily provide these, we cache them */ | ||
| 141 | struct cx24116_tuning | ||
| 142 | { | ||
| 143 | u32 frequency; | ||
| 144 | u32 symbol_rate; | ||
| 145 | fe_spectral_inversion_t inversion; | ||
| 146 | fe_code_rate_t fec; | ||
| 147 | |||
| 148 | fe_modulation_t modulation; | ||
| 149 | fe_pilot_t pilot; | ||
| 150 | fe_rolloff_t rolloff; | ||
| 151 | |||
| 152 | /* Demod values */ | ||
| 153 | u8 fec_val; | ||
| 154 | u8 fec_mask; | ||
| 155 | u8 inversion_val; | ||
| 156 | u8 pilot_val; | ||
| 157 | u8 rolloff_val; | ||
| 158 | }; | ||
| 159 | |||
| 160 | /* Basic commands that are sent to the firmware */ | ||
| 161 | struct cx24116_cmd | ||
| 162 | { | ||
| 163 | u8 len; | ||
| 164 | u8 args[CX24116_ARGLEN]; | ||
| 165 | }; | ||
| 166 | |||
| 167 | struct cx24116_state | ||
| 168 | { | ||
| 169 | struct i2c_adapter* i2c; | ||
| 170 | const struct cx24116_config* config; | ||
| 171 | |||
| 172 | struct dvb_frontend frontend; | ||
| 173 | |||
| 174 | struct cx24116_tuning dcur; | ||
| 175 | struct cx24116_tuning dnxt; | ||
| 176 | |||
| 177 | u8 skip_fw_load; | ||
| 178 | u8 burst; | ||
| 179 | struct cx24116_cmd dsec_cmd; | ||
| 180 | }; | ||
| 181 | |||
| 182 | static int cx24116_writereg(struct cx24116_state* state, int reg, int data) | ||
| 183 | { | ||
| 184 | u8 buf[] = { reg, data }; | ||
| 185 | struct i2c_msg msg = { .addr = state->config->demod_address, | ||
| 186 | .flags = 0, .buf = buf, .len = 2 }; | ||
| 187 | int err; | ||
| 188 | |||
| 189 | if (debug>1) | ||
| 190 | printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n", | ||
| 191 | __func__,reg, data); | ||
| 192 | |||
| 193 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { | ||
| 194 | printk("%s: writereg error(err == %i, reg == 0x%02x," | ||
| 195 | " value == 0x%02x)\n", __func__, err, reg, data); | ||
| 196 | return -EREMOTEIO; | ||
| 197 | } | ||
| 198 | |||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 202 | /* Bulk byte writes to a single I2C address, for 32k firmware load */ | ||
| 203 | static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 len) | ||
| 204 | { | ||
| 205 | int ret = -EREMOTEIO; | ||
| 206 | struct i2c_msg msg; | ||
| 207 | u8 *buf; | ||
| 208 | |||
| 209 | buf = kmalloc(len + 1, GFP_KERNEL); | ||
| 210 | if (buf == NULL) { | ||
| 211 | printk("Unable to kmalloc\n"); | ||
| 212 | ret = -ENOMEM; | ||
| 213 | goto error; | ||
| 214 | } | ||
| 215 | |||
| 216 | *(buf) = reg; | ||
| 217 | memcpy(buf + 1, data, len); | ||
| 218 | |||
| 219 | msg.addr = state->config->demod_address; | ||
| 220 | msg.flags = 0; | ||
| 221 | msg.buf = buf; | ||
| 222 | msg.len = len + 1; | ||
| 223 | |||
| 224 | if (debug>1) | ||
| 225 | printk("cx24116: %s: write regN 0x%02x, len = %d\n", | ||
| 226 | __func__,reg, len); | ||
| 227 | |||
| 228 | if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) { | ||
| 229 | printk("%s: writereg error(err == %i, reg == 0x%02x\n", | ||
| 230 | __func__, ret, reg); | ||
| 231 | ret = -EREMOTEIO; | ||
| 232 | } | ||
| 233 | |||
| 234 | error: | ||
| 235 | kfree(buf); | ||
| 236 | |||
| 237 | return ret; | ||
| 238 | } | ||
| 239 | |||
| 240 | static int cx24116_readreg(struct cx24116_state* state, u8 reg) | ||
| 241 | { | ||
| 242 | int ret; | ||
| 243 | u8 b0[] = { reg }; | ||
| 244 | u8 b1[] = { 0 }; | ||
| 245 | struct i2c_msg msg[] = { | ||
| 246 | { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 }, | ||
| 247 | { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } | ||
| 248 | }; | ||
| 249 | |||
| 250 | ret = i2c_transfer(state->i2c, msg, 2); | ||
| 251 | |||
| 252 | if (ret != 2) { | ||
| 253 | printk("%s: reg=0x%x (error=%d)\n", __func__, reg, ret); | ||
| 254 | return ret; | ||
| 255 | } | ||
| 256 | |||
| 257 | if (debug>1) | ||
| 258 | printk("cx24116: read reg 0x%02x, value 0x%02x\n",reg, b1[0]); | ||
| 259 | |||
| 260 | return b1[0]; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_inversion_t inversion) | ||
| 264 | { | ||
| 265 | dprintk("%s(%d)\n", __func__, inversion); | ||
| 266 | |||
| 267 | switch (inversion) { | ||
| 268 | case INVERSION_OFF: | ||
| 269 | state->dnxt.inversion_val = 0x00; | ||
| 270 | break; | ||
| 271 | case INVERSION_ON: | ||
| 272 | state->dnxt.inversion_val = 0x04; | ||
| 273 | break; | ||
| 274 | case INVERSION_AUTO: | ||
| 275 | state->dnxt.inversion_val = 0x0C; | ||
| 276 | break; | ||
| 277 | default: | ||
| 278 | return -EINVAL; | ||
| 279 | } | ||
| 280 | |||
| 281 | state->dnxt.inversion = inversion; | ||
| 282 | |||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | /* | ||
| 287 | * modfec (modulation and FEC) | ||
| 288 | * =========================== | ||
| 289 | * | ||
| 290 | * MOD FEC mask/val standard | ||
| 291 | * ---- -------- ----------- -------- | ||
| 292 | * QPSK FEC_1_2 0x02 0x02+X DVB-S | ||
| 293 | * QPSK FEC_2_3 0x04 0x02+X DVB-S | ||
| 294 | * QPSK FEC_3_4 0x08 0x02+X DVB-S | ||
| 295 | * QPSK FEC_4_5 0x10 0x02+X DVB-S (?) | ||
| 296 | * QPSK FEC_5_6 0x20 0x02+X DVB-S | ||
| 297 | * QPSK FEC_6_7 0x40 0x02+X DVB-S | ||
| 298 | * QPSK FEC_7_8 0x80 0x02+X DVB-S | ||
| 299 | * QPSK FEC_8_9 0x01 0x02+X DVB-S (?) (NOT SUPPORTED?) | ||
| 300 | * QPSK AUTO 0xff 0x02+X DVB-S | ||
| 301 | * | ||
| 302 | * For DVB-S high byte probably represents FEC | ||
| 303 | * and low byte selects the modulator. The high | ||
| 304 | * byte is search range mask. Bit 5 may turn | ||
| 305 | * on DVB-S and remaining bits represent some | ||
| 306 | * kind of calibration (how/what i do not know). | ||
| 307 | * | ||
| 308 | * Eg.(2/3) szap "Zone Horror" | ||
| 309 | * | ||
| 310 | * mask/val = 0x04, 0x20 | ||
| 311 | * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 00000000 | FE_HAS_LOCK | ||
| 312 | * | ||
| 313 | * mask/val = 0x04, 0x30 | ||
| 314 | * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 00000000 | FE_HAS_LOCK | ||
| 315 | * | ||
| 316 | * After tuning FECSTATUS contains actual FEC | ||
| 317 | * in use numbered 1 through to 8 for 1/2 .. 2/3 etc | ||
| 318 | * | ||
| 319 | * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only) | ||
| 320 | * | ||
| 321 | * NBC-QPSK FEC_1_2 0x00, 0x04 DVB-S2 | ||
| 322 | * NBC-QPSK FEC_3_5 0x00, 0x05 DVB-S2 | ||
| 323 | * NBC-QPSK FEC_2_3 0x00, 0x06 DVB-S2 | ||
| 324 | * NBC-QPSK FEC_3_4 0x00, 0x07 DVB-S2 | ||
| 325 | * NBC-QPSK FEC_4_5 0x00, 0x08 DVB-S2 | ||
| 326 | * NBC-QPSK FEC_5_6 0x00, 0x09 DVB-S2 | ||
| 327 | * NBC-QPSK FEC_8_9 0x00, 0x0a DVB-S2 | ||
| 328 | * NBC-QPSK FEC_9_10 0x00, 0x0b DVB-S2 | ||
| 329 | * | ||
| 330 | * NBC-8PSK FEC_3_5 0x00, 0x0c DVB-S2 | ||
| 331 | * NBC-8PSK FEC_2_3 0x00, 0x0d DVB-S2 | ||
| 332 | * NBC-8PSK FEC_3_4 0x00, 0x0e DVB-S2 | ||
| 333 | * NBC-8PSK FEC_5_6 0x00, 0x0f DVB-S2 | ||
| 334 | * NBC-8PSK FEC_8_9 0x00, 0x10 DVB-S2 | ||
| 335 | * NBC-8PSK FEC_9_10 0x00, 0x11 DVB-S2 | ||
| 336 | * | ||
| 337 | * For DVB-S2 low bytes selects both modulator | ||
| 338 | * and FEC. High byte is meaningless here. To | ||
| 339 | * set pilot, bit 6 (0x40) is set. When inspecting | ||
| 340 | * FECSTATUS bit 7 (0x80) represents the pilot | ||
| 341 | * selection whilst not tuned. When tuned, actual FEC | ||
| 342 | * in use is found in FECSTATUS as per above. Pilot | ||
| 343 | * value is reset. | ||
| 344 | */ | ||
| 345 | |||
| 346 | /* A table of modulation, fec and configuration bytes for the demod. | ||
| 347 | * Not all S2 mmodulation schemes are support and not all rates with | ||
| 348 | * a scheme are support. Especially, no auto detect when in S2 mode. | ||
| 349 | */ | ||
| 350 | struct cx24116_modfec { | ||
| 351 | fe_delivery_system_t delivery_system; | ||
| 352 | fe_modulation_t modulation; | ||
| 353 | fe_code_rate_t fec; | ||
| 354 | u8 mask; /* In DVBS mode this is used to autodetect */ | ||
| 355 | u8 val; /* Passed to the firmware to indicate mode selection */ | ||
| 356 | } CX24116_MODFEC_MODES[] = { | ||
| 357 | /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */ | ||
| 358 | |||
| 359 | /*mod fec mask val */ | ||
| 360 | { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 }, | ||
| 361 | { SYS_DVBS, QPSK, FEC_1_2, 0x02, 0x2e }, /* 00000010 00101110 */ | ||
| 362 | { SYS_DVBS, QPSK, FEC_2_3, 0x04, 0x2f }, /* 00000100 00101111 */ | ||
| 363 | { SYS_DVBS, QPSK, FEC_3_4, 0x08, 0x30 }, /* 00001000 00110000 */ | ||
| 364 | { SYS_DVBS, QPSK, FEC_4_5, 0xfe, 0x30 }, /* 000?0000 ? */ | ||
| 365 | { SYS_DVBS, QPSK, FEC_5_6, 0x20, 0x31 }, /* 00100000 00110001 */ | ||
| 366 | { SYS_DVBS, QPSK, FEC_6_7, 0xfe, 0x30 }, /* 0?000000 ? */ | ||
| 367 | { SYS_DVBS, QPSK, FEC_7_8, 0x80, 0x32 }, /* 10000000 00110010 */ | ||
| 368 | { SYS_DVBS, QPSK, FEC_8_9, 0xfe, 0x30 }, /* 0000000? ? */ | ||
| 369 | { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 }, | ||
| 370 | /* NBC-QPSK */ | ||
| 371 | { SYS_DVBS2, QPSK, FEC_1_2, 0x00, 0x04 }, | ||
| 372 | { SYS_DVBS2, QPSK, FEC_3_5, 0x00, 0x05 }, | ||
| 373 | { SYS_DVBS2, QPSK, FEC_2_3, 0x00, 0x06 }, | ||
| 374 | { SYS_DVBS2, QPSK, FEC_3_4, 0x00, 0x07 }, | ||
| 375 | { SYS_DVBS2, QPSK, FEC_4_5, 0x00, 0x08 }, | ||
| 376 | { SYS_DVBS2, QPSK, FEC_5_6, 0x00, 0x09 }, | ||
| 377 | { SYS_DVBS2, QPSK, FEC_8_9, 0x00, 0x0a }, | ||
| 378 | { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b }, | ||
| 379 | /* 8PSK */ | ||
| 380 | { SYS_DVBS2, PSK_8, FEC_3_5, 0x00, 0x0c }, | ||
| 381 | { SYS_DVBS2, PSK_8, FEC_2_3, 0x00, 0x0d }, | ||
| 382 | { SYS_DVBS2, PSK_8, FEC_3_4, 0x00, 0x0e }, | ||
| 383 | { SYS_DVBS2, PSK_8, FEC_5_6, 0x00, 0x0f }, | ||
| 384 | { SYS_DVBS2, PSK_8, FEC_8_9, 0x00, 0x10 }, | ||
| 385 | { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 }, | ||
| 386 | /* | ||
| 387 | * `val' can be found in the FECSTATUS register when tuning. | ||
| 388 | * FECSTATUS will give the actual FEC in use if tuning was successful. | ||
| 389 | */ | ||
| 390 | }; | ||
| 391 | |||
| 392 | static int cx24116_lookup_fecmod(struct cx24116_state* state, | ||
| 393 | fe_modulation_t m, fe_code_rate_t f) | ||
| 394 | { | ||
| 395 | int i, ret = -EOPNOTSUPP; | ||
| 396 | |||
| 397 | dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f); | ||
| 398 | |||
| 399 | for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++) | ||
| 400 | { | ||
| 401 | if( (m == CX24116_MODFEC_MODES[i].modulation) && | ||
| 402 | (f == CX24116_MODFEC_MODES[i].fec) ) | ||
| 403 | { | ||
| 404 | ret = i; | ||
| 405 | break; | ||
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | return ret; | ||
| 410 | } | ||
| 411 | |||
| 412 | static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec) | ||
| 413 | { | ||
| 414 | int ret = 0; | ||
| 415 | |||
| 416 | dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec); | ||
| 417 | |||
| 418 | ret = cx24116_lookup_fecmod(state, mod, fec); | ||
| 419 | |||
| 420 | if(ret < 0) | ||
| 421 | return ret; | ||
| 422 | |||
| 423 | state->dnxt.fec = fec; | ||
| 424 | state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val; | ||
| 425 | state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask; | ||
| 426 | dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__, | ||
| 427 | state->dnxt.fec_mask, state->dnxt.fec_val); | ||
| 428 | |||
| 429 | return 0; | ||
| 430 | } | ||
| 431 | |||
| 432 | static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate) | ||
| 433 | { | ||
| 434 | dprintk("%s(%d)\n", __func__, rate); | ||
| 435 | |||
| 436 | /* check if symbol rate is within limits */ | ||
| 437 | if ((rate > state->frontend.ops.info.symbol_rate_max) || | ||
| 438 | (rate < state->frontend.ops.info.symbol_rate_min)) { | ||
| 439 | dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate); | ||
| 440 | return -EOPNOTSUPP; | ||
| 441 | } | ||
| 442 | |||
| 443 | state->dnxt.symbol_rate = rate; | ||
| 444 | dprintk("%s() symbol_rate = %d\n", __func__, rate); | ||
| 445 | |||
| 446 | return 0; | ||
| 447 | } | ||
| 448 | |||
| 449 | static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw); | ||
| 450 | |||
| 451 | static int cx24116_firmware_ondemand(struct dvb_frontend* fe) | ||
| 452 | { | ||
| 453 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 454 | const struct firmware *fw; | ||
| 455 | int ret = 0; | ||
| 456 | |||
| 457 | dprintk("%s()\n",__func__); | ||
| 458 | |||
| 459 | if (cx24116_readreg(state, 0x20) > 0) | ||
| 460 | { | ||
| 461 | |||
| 462 | if (state->skip_fw_load) | ||
| 463 | return 0; | ||
| 464 | |||
| 465 | /* Load firmware */ | ||
| 466 | /* request the firmware, this will block until someone uploads it */ | ||
| 467 | printk("%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE); | ||
| 468 | ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, &state->i2c->dev); | ||
| 469 | printk("%s: Waiting for firmware upload(2)...\n", __func__); | ||
| 470 | if (ret) { | ||
| 471 | printk("%s: No firmware uploaded (timeout or file not found?)\n", __func__); | ||
| 472 | return ret; | ||
| 473 | } | ||
| 474 | |||
| 475 | /* Make sure we don't recurse back through here during loading */ | ||
| 476 | state->skip_fw_load = 1; | ||
| 477 | |||
| 478 | ret = cx24116_load_firmware(fe, fw); | ||
| 479 | if (ret) | ||
| 480 | printk("%s: Writing firmware to device failed\n", __func__); | ||
| 481 | |||
| 482 | release_firmware(fw); | ||
| 483 | |||
| 484 | printk("%s: Firmware upload %s\n", __func__, ret == 0 ? "complete" : "failed"); | ||
| 485 | |||
| 486 | /* Ensure firmware is always loaded if required */ | ||
| 487 | state->skip_fw_load = 0; | ||
| 488 | } | ||
| 489 | |||
| 490 | return ret; | ||
| 491 | } | ||
| 492 | |||
| 493 | /* Take a basic firmware command structure, format it and forward it for processing */ | ||
| 494 | static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd) | ||
| 495 | { | ||
| 496 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 497 | int i, ret; | ||
| 498 | |||
| 499 | dprintk("%s()\n", __func__); | ||
| 500 | |||
| 501 | /* Load the firmware if required */ | ||
| 502 | if ( (ret = cx24116_firmware_ondemand(fe)) != 0) | ||
| 503 | { | ||
| 504 | printk("%s(): Unable initialise the firmware\n", __func__); | ||
| 505 | return ret; | ||
| 506 | } | ||
| 507 | |||
| 508 | /* Write the command */ | ||
| 509 | for(i = 0; i < cmd->len ; i++) | ||
| 510 | { | ||
| 511 | dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]); | ||
| 512 | cx24116_writereg(state, i, cmd->args[i]); | ||
| 513 | } | ||
| 514 | |||
| 515 | /* Start execution and wait for cmd to terminate */ | ||
| 516 | cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01); | ||
| 517 | while( cx24116_readreg(state, CX24116_REG_EXECUTE) ) | ||
| 518 | { | ||
| 519 | msleep(10); | ||
| 520 | if(i++ > 64) | ||
| 521 | { | ||
| 522 | /* Avoid looping forever if the firmware does no respond */ | ||
| 523 | printk("%s() Firmware not responding\n", __func__); | ||
| 524 | return -EREMOTEIO; | ||
| 525 | } | ||
| 526 | } | ||
| 527 | return 0; | ||
| 528 | } | ||
| 529 | |||
| 530 | static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw) | ||
| 531 | { | ||
| 532 | struct cx24116_state* state = fe->demodulator_priv; | ||
| 533 | struct cx24116_cmd cmd; | ||
| 534 | int i, ret; | ||
| 535 | unsigned char vers[4]; | ||
| 536 | |||
| 537 | dprintk("%s\n", __func__); | ||
| 538 | dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n" | ||
| 539 | ,fw->size | ||
| 540 | ,fw->data[0] | ||
| 541 | ,fw->data[1] | ||
| 542 | ,fw->data[ fw->size-2 ] | ||
| 543 | ,fw->data[ fw->size-1 ] | ||
| 544 | ); | ||
| 545 | |||
| 546 | /* Toggle 88x SRST pin to reset demod */ | ||
| 547 | if (state->config->reset_device) | ||
| 548 | state->config->reset_device(fe); | ||
| 549 | |||
| 550 | /* Begin the firmware load process */ | ||
| 551 | /* Prepare the demod, load the firmware, cleanup after load */ | ||
| 552 | |||
| 553 | /* Init PLL */ | ||
| 554 | cx24116_writereg(state, 0xE5, 0x00); | ||
| 555 | cx24116_writereg(state, 0xF1, 0x08); | ||
| 556 | cx24116_writereg(state, 0xF2, 0x13); | ||
| 557 | |||
| 558 | /* Start PLL */ | ||
| 559 | cx24116_writereg(state, 0xe0, 0x03); | ||
| 560 | cx24116_writereg(state, 0xe0, 0x00); | ||
| 561 | |||
| 562 | /* Unknown */ | ||
| 563 | cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46); | ||
| 564 | cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00); | ||
| 565 | |||
| 566 | /* Unknown */ | ||
| 567 | cx24116_writereg(state, 0xF0, 0x03); | ||
| 568 | cx24116_writereg(state, 0xF4, 0x81); | ||
| 569 | cx24116_writereg(state, 0xF5, 0x00); | ||
| 570 | cx24116_writereg(state, 0xF6, 0x00); | ||
| 571 | |||
| 572 | /* write the entire firmware as one transaction */ | ||
| 573 | cx24116_writeregN(state, 0xF7, fw->data, fw->size); | ||
| 574 | |||
| 575 | cx24116_writereg(state, 0xF4, 0x10); | ||
| 576 | cx24116_writereg(state, 0xF0, 0x00); | ||
| 577 | cx24116_writereg(state, 0xF8, 0x06); | ||
| 578 | |||
| 579 | /* Firmware CMD 10: VCO config */ | ||
| 580 | cmd.args[0x00] = CMD_SET_VCO; | ||
| 581 | cmd.args[0x01] = 0x05; | ||
| 582 | cmd.args[0x02] = 0xdc; | ||
| 583 | cmd.args[0x03] = 0xda; | ||
| 584 | cmd.args[0x04] = 0xae; | ||
| 585 | cmd.args[0x05] = 0xaa; | ||
| 586 | cmd.args[0x06] = 0x04; | ||
| 587 | cmd.args[0x07] = 0x9d; | ||
| 588 | cmd.args[0x08] = 0xfc; | ||
| 589 | cmd.args[0x09] = 0x06; | ||
| 590 | cmd.len= 0x0a; | ||
| 591 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 592 | if (ret != 0) | ||
| 593 | return ret; | ||
| 594 | |||
| 595 | cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00); | ||
| 596 | |||
| 597 | /* Firmware CMD 14: Tuner config */ | ||
| 598 | cmd.args[0x00] = CMD_TUNERINIT; | ||
| 599 | cmd.args[0x01] = 0x00; | ||
| 600 | cmd.args[0x02] = 0x00; | ||
| 601 | cmd.len= 0x03; | ||
| 602 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 603 | if (ret != 0) | ||
| 604 | return ret; | ||
| 605 | |||
| 606 | cx24116_writereg(state, 0xe5, 0x00); | ||
| 607 | |||
| 608 | /* Firmware CMD 13: MPEG config */ | ||
| 609 | cmd.args[0x00] = CMD_MPEGCONFIG; | ||
| 610 | cmd.args[0x01] = 0x01; | ||
| 611 | cmd.args[0x02] = 0x75; | ||
| 612 | cmd.args[0x03] = 0x00; | ||
| 613 | if (state->config->mpg_clk_pos_pol) | ||
| 614 | cmd.args[0x04] = state->config->mpg_clk_pos_pol; | ||
| 615 | else | ||
| 616 | cmd.args[0x04] = 0x02; | ||
| 617 | cmd.args[0x05] = 0x00; | ||
| 618 | cmd.len= 0x06; | ||
| 619 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 620 | if (ret != 0) | ||
| 621 | return ret; | ||
| 622 | |||
| 623 | /* Firmware CMD 35: Get firmware version */ | ||
| 624 | cmd.args[0x00] = CMD_UPDFWVERS; | ||
| 625 | cmd.len= 0x02; | ||
| 626 | for(i=0; i<4; i++) { | ||
| 627 | cmd.args[0x01] = i; | ||
| 628 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 629 | if (ret != 0) | ||
| 630 | return ret; | ||
| 631 | vers[i]= cx24116_readreg(state, CX24116_REG_MAILBOX); | ||
| 632 | } | ||
| 633 | printk("%s: FW version %i.%i.%i.%i\n", __func__, | ||
| 634 | vers[0], vers[1], vers[2], vers[3]); | ||
| 635 | |||
| 636 | return 0; | ||
| 637 | } | ||
| 638 | |||
| 639 | static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) | ||
| 640 | { | ||
| 641 | /* The isl6421 module will override this function in the fops. */ | ||
| 642 | dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__); | ||
| 643 | |||
| 644 | return -EOPNOTSUPP; | ||
| 645 | } | ||
| 646 | |||
| 647 | static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status) | ||
| 648 | { | ||
| 649 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 650 | |||
| 651 | int lock = cx24116_readreg(state, CX24116_REG_SSTATUS); | ||
| 652 | |||
| 653 | dprintk("%s: status = 0x%02x\n", __func__, lock); | ||
| 654 | |||
| 655 | *status = 0; | ||
| 656 | |||
| 657 | if (lock & CX24116_HAS_SIGNAL) | ||
| 658 | *status |= FE_HAS_SIGNAL; | ||
| 659 | if (lock & CX24116_HAS_CARRIER) | ||
| 660 | *status |= FE_HAS_CARRIER; | ||
| 661 | if (lock & CX24116_HAS_VITERBI) | ||
| 662 | *status |= FE_HAS_VITERBI; | ||
| 663 | if (lock & CX24116_HAS_SYNCLOCK) | ||
| 664 | *status |= FE_HAS_SYNC | FE_HAS_LOCK; | ||
| 665 | |||
| 666 | return 0; | ||
| 667 | } | ||
| 668 | |||
| 669 | static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber) | ||
| 670 | { | ||
| 671 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 672 | |||
| 673 | dprintk("%s()\n", __func__); | ||
| 674 | |||
| 675 | *ber = ( cx24116_readreg(state, CX24116_REG_BER24) << 24 ) | | ||
| 676 | ( cx24116_readreg(state, CX24116_REG_BER16) << 16 ) | | ||
| 677 | ( cx24116_readreg(state, CX24116_REG_BER8 ) << 8 ) | | ||
| 678 | cx24116_readreg(state, CX24116_REG_BER0 ); | ||
| 679 | |||
| 680 | return 0; | ||
| 681 | } | ||
| 682 | |||
| 683 | /* TODO Determine function and scale appropriately */ | ||
| 684 | static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) | ||
| 685 | { | ||
| 686 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 687 | struct cx24116_cmd cmd; | ||
| 688 | int ret; | ||
| 689 | u16 sig_reading; | ||
| 690 | |||
| 691 | dprintk("%s()\n", __func__); | ||
| 692 | |||
| 693 | /* Firmware CMD 19: Get AGC */ | ||
| 694 | cmd.args[0x00] = CMD_GETAGC; | ||
| 695 | cmd.len= 0x01; | ||
| 696 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 697 | if (ret != 0) | ||
| 698 | return ret; | ||
| 699 | |||
| 700 | sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) | | ||
| 701 | ( cx24116_readreg(state, CX24116_REG_SIGNAL) << 6 ); | ||
| 702 | *signal_strength= 0 - sig_reading; | ||
| 703 | |||
| 704 | dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength); | ||
| 705 | |||
| 706 | return 0; | ||
| 707 | } | ||
| 708 | |||
| 709 | /* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */ | ||
| 710 | static int cx24116_read_snr_pct(struct dvb_frontend* fe, u16* snr) | ||
| 711 | { | ||
| 712 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 713 | u8 snr_reading; | ||
| 714 | static const u32 snr_tab[] = { /* 10 x Table (rounded up) */ | ||
| 715 | 0x00000,0x0199A,0x03333,0x04ccD,0x06667, | ||
| 716 | 0x08000,0x0999A,0x0b333,0x0cccD,0x0e667, | ||
| 717 | 0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 }; | ||
| 718 | |||
| 719 | dprintk("%s()\n", __func__); | ||
| 720 | |||
| 721 | snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0); | ||
| 722 | |||
| 723 | if(snr_reading >= 0xa0 /* 100% */) | ||
| 724 | *snr = 0xffff; | ||
| 725 | else | ||
| 726 | *snr = snr_tab [ ( snr_reading & 0xf0 ) >> 4 ] + | ||
| 727 | ( snr_tab [ ( snr_reading & 0x0f ) ] >> 4 ); | ||
| 728 | |||
| 729 | dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__, | ||
| 730 | snr_reading, *snr); | ||
| 731 | |||
| 732 | return 0; | ||
| 733 | } | ||
| 734 | |||
| 735 | /* The reelbox patches show the value in the registers represents | ||
| 736 | * ESNO, from 0->30db (values 0->300). We provide this value by | ||
| 737 | * default. | ||
| 738 | */ | ||
| 739 | static int cx24116_read_snr_esno(struct dvb_frontend* fe, u16* snr) | ||
| 740 | { | ||
| 741 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 742 | |||
| 743 | dprintk("%s()\n", __func__); | ||
| 744 | |||
| 745 | *snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 | | ||
| 746 | cx24116_readreg(state, CX24116_REG_QUALITY0); | ||
| 747 | |||
| 748 | dprintk("%s: raw 0x%04x\n", __func__, *snr); | ||
| 749 | |||
| 750 | return 0; | ||
| 751 | } | ||
| 752 | |||
| 753 | static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr) | ||
| 754 | { | ||
| 755 | if (esno_snr == 1) | ||
| 756 | return cx24116_read_snr_esno(fe, snr); | ||
| 757 | else | ||
| 758 | return cx24116_read_snr_pct(fe, snr); | ||
| 759 | } | ||
| 760 | |||
| 761 | static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | ||
| 762 | { | ||
| 763 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 764 | |||
| 765 | dprintk("%s()\n", __func__); | ||
| 766 | |||
| 767 | *ucblocks = ( cx24116_readreg(state, CX24116_REG_UCB8) << 8 ) | | ||
| 768 | cx24116_readreg(state, CX24116_REG_UCB0); | ||
| 769 | |||
| 770 | return 0; | ||
| 771 | } | ||
| 772 | |||
| 773 | /* Overwrite the current tuning params, we are about to tune */ | ||
| 774 | static void cx24116_clone_params(struct dvb_frontend* fe) | ||
| 775 | { | ||
| 776 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 777 | memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur)); | ||
| 778 | } | ||
| 779 | |||
| 780 | /* Wait for LNB */ | ||
| 781 | static int cx24116_wait_for_lnb(struct dvb_frontend* fe) | ||
| 782 | { | ||
| 783 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 784 | int i; | ||
| 785 | |||
| 786 | dprintk("%s() qstatus = 0x%02x\n", __func__, | ||
| 787 | cx24116_readreg(state, CX24116_REG_QSTATUS)); | ||
| 788 | |||
| 789 | /* Wait for up to 300 ms */ | ||
| 790 | for(i = 0; i < 30 ; i++) { | ||
| 791 | if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20) | ||
| 792 | return 0; | ||
| 793 | msleep(10); | ||
| 794 | } | ||
| 795 | |||
| 796 | dprintk("%s(): LNB not ready\n", __func__); | ||
| 797 | |||
| 798 | return -ETIMEDOUT; /* -EBUSY ? */ | ||
| 799 | } | ||
| 800 | |||
| 801 | static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | ||
| 802 | { | ||
| 803 | struct cx24116_cmd cmd; | ||
| 804 | int ret; | ||
| 805 | |||
| 806 | dprintk("%s(%d)\n", __func__, tone); | ||
| 807 | if ( (tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF) ) { | ||
| 808 | printk("%s: Invalid, tone=%d\n", __func__, tone); | ||
| 809 | return -EINVAL; | ||
| 810 | } | ||
| 811 | |||
| 812 | /* Wait for LNB ready */ | ||
| 813 | ret = cx24116_wait_for_lnb(fe); | ||
| 814 | if(ret != 0) | ||
| 815 | return ret; | ||
| 816 | |||
| 817 | /* Min delay time after DiSEqC send */ | ||
| 818 | msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */ | ||
| 819 | |||
| 820 | /* This is always done before the tone is set */ | ||
| 821 | cmd.args[0x00] = CMD_SET_TONEPRE; | ||
| 822 | cmd.args[0x01] = 0x00; | ||
| 823 | cmd.len= 0x02; | ||
| 824 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 825 | if (ret != 0) | ||
| 826 | return ret; | ||
| 827 | |||
| 828 | /* Now we set the tone */ | ||
| 829 | cmd.args[0x00] = CMD_SET_TONE; | ||
| 830 | cmd.args[0x01] = 0x00; | ||
| 831 | cmd.args[0x02] = 0x00; | ||
| 832 | |||
| 833 | switch (tone) { | ||
| 834 | case SEC_TONE_ON: | ||
| 835 | dprintk("%s: setting tone on\n", __func__); | ||
| 836 | cmd.args[0x03] = 0x01; | ||
| 837 | break; | ||
| 838 | case SEC_TONE_OFF: | ||
| 839 | dprintk("%s: setting tone off\n",__func__); | ||
| 840 | cmd.args[0x03] = 0x00; | ||
| 841 | break; | ||
| 842 | } | ||
| 843 | cmd.len= 0x04; | ||
| 844 | |||
| 845 | /* Min delay time before DiSEqC send */ | ||
| 846 | msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */ | ||
| 847 | |||
| 848 | return cx24116_cmd_execute(fe, &cmd); | ||
| 849 | } | ||
| 850 | |||
| 851 | /* Initialise DiSEqC */ | ||
| 852 | static int cx24116_diseqc_init(struct dvb_frontend* fe) | ||
| 853 | { | ||
| 854 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 855 | struct cx24116_cmd cmd; | ||
| 856 | int ret; | ||
| 857 | |||
| 858 | /* Firmware CMD 20: LNB/DiSEqC config */ | ||
| 859 | cmd.args[0x00] = CMD_LNBCONFIG; | ||
| 860 | cmd.args[0x01] = 0x00; | ||
| 861 | cmd.args[0x02] = 0x10; | ||
| 862 | cmd.args[0x03] = 0x00; | ||
| 863 | cmd.args[0x04] = 0x8f; | ||
| 864 | cmd.args[0x05] = 0x28; | ||
| 865 | cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01; | ||
| 866 | cmd.args[0x07] = 0x01; | ||
| 867 | cmd.len= 0x08; | ||
| 868 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 869 | if (ret != 0) | ||
| 870 | return ret; | ||
| 871 | |||
| 872 | /* Prepare a DiSEqC command */ | ||
| 873 | state->dsec_cmd.args[0x00] = CMD_LNBSEND; | ||
| 874 | |||
| 875 | /* DiSEqC burst */ | ||
| 876 | state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; | ||
| 877 | |||
| 878 | /* Unknown */ | ||
| 879 | state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02; | ||
| 880 | state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00; | ||
| 881 | state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; /* Continuation flag? */ | ||
| 882 | |||
| 883 | /* DiSEqC message length */ | ||
| 884 | state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00; | ||
| 885 | |||
| 886 | /* Command length */ | ||
| 887 | state->dsec_cmd.len= CX24116_DISEQC_MSGOFS; | ||
| 888 | |||
| 889 | return 0; | ||
| 890 | } | ||
| 891 | |||
| 892 | /* Send DiSEqC message with derived burst (hack) || previous burst */ | ||
| 893 | static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d) | ||
| 894 | { | ||
| 895 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 896 | int i, ret; | ||
| 897 | |||
| 898 | /* Dump DiSEqC message */ | ||
| 899 | if (debug) { | ||
| 900 | printk("cx24116: %s(", __func__); | ||
| 901 | for(i = 0 ; i < d->msg_len ;) { | ||
| 902 | printk("0x%02x", d->msg[i]); | ||
| 903 | if(++i < d->msg_len) | ||
| 904 | printk(", "); | ||
| 905 | } | ||
| 906 | printk(") toneburst=%d\n", toneburst); | ||
| 907 | } | ||
| 908 | |||
| 909 | /* Validate length */ | ||
| 910 | if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS)) | ||
| 911 | return -EINVAL; | ||
| 912 | |||
| 913 | /* DiSEqC message */ | ||
| 914 | for (i = 0; i < d->msg_len; i++) | ||
| 915 | state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i]; | ||
| 916 | |||
| 917 | /* DiSEqC message length */ | ||
| 918 | state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len; | ||
| 919 | |||
| 920 | /* Command length */ | ||
| 921 | state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN]; | ||
| 922 | |||
| 923 | /* DiSEqC toneburst */ | ||
| 924 | if(toneburst == CX24116_DISEQC_MESGCACHE) | ||
| 925 | /* Message is cached */ | ||
| 926 | return 0; | ||
| 927 | |||
| 928 | else if(toneburst == CX24116_DISEQC_TONEOFF) | ||
| 929 | /* Message is sent without burst */ | ||
| 930 | state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0; | ||
| 931 | |||
| 932 | else if(toneburst == CX24116_DISEQC_TONECACHE) { | ||
| 933 | /* | ||
| 934 | * Message is sent with derived else cached burst | ||
| 935 | * | ||
| 936 | * WRITE PORT GROUP COMMAND 38 | ||
| 937 | * | ||
| 938 | * 0/A/A: E0 10 38 F0..F3 | ||
| 939 | * 1/B/B: E0 10 38 F4..F7 | ||
| 940 | * 2/C/A: E0 10 38 F8..FB | ||
| 941 | * 3/D/B: E0 10 38 FC..FF | ||
| 942 | * | ||
| 943 | * databyte[3]= 8421:8421 | ||
| 944 | * ABCD:WXYZ | ||
| 945 | * CLR :SET | ||
| 946 | * | ||
| 947 | * WX= PORT SELECT 0..3 (X=TONEBURST) | ||
| 948 | * Y = VOLTAGE (0=13V, 1=18V) | ||
| 949 | * Z = BAND (0=LOW, 1=HIGH(22K)) | ||
| 950 | */ | ||
| 951 | if(d->msg_len >= 4 && d->msg[2] == 0x38) | ||
| 952 | state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2); | ||
| 953 | if(debug) | ||
| 954 | dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]); | ||
| 955 | } | ||
| 956 | |||
| 957 | /* Wait for LNB ready */ | ||
| 958 | ret = cx24116_wait_for_lnb(fe); | ||
| 959 | if(ret != 0) | ||
| 960 | return ret; | ||
| 961 | |||
| 962 | /* Wait for voltage/min repeat delay */ | ||
| 963 | msleep(100); | ||
| 964 | |||
| 965 | /* Command */ | ||
| 966 | ret = cx24116_cmd_execute(fe, &state->dsec_cmd); | ||
| 967 | if(ret != 0) | ||
| 968 | return ret; | ||
| 969 | /* | ||
| 970 | * Wait for send | ||
| 971 | * | ||
| 972 | * Eutelsat spec: | ||
| 973 | * >15ms delay + (XXX determine if FW does this, see set_tone) | ||
| 974 | * 13.5ms per byte + | ||
| 975 | * >15ms delay + | ||
| 976 | * 12.5ms burst + | ||
| 977 | * >15ms delay (XXX determine if FW does this, see set_tone) | ||
| 978 | */ | ||
| 979 | msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) ); | ||
| 980 | |||
| 981 | return 0; | ||
| 982 | } | ||
| 983 | |||
| 984 | /* Send DiSEqC burst */ | ||
| 985 | static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) | ||
| 986 | { | ||
| 987 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 988 | int ret; | ||
| 989 | |||
| 990 | dprintk("%s(%d) toneburst=%d\n",__func__, burst, toneburst); | ||
| 991 | |||
| 992 | /* DiSEqC burst */ | ||
| 993 | if (burst == SEC_MINI_A) | ||
| 994 | state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A; | ||
| 995 | else if(burst == SEC_MINI_B) | ||
| 996 | state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B; | ||
| 997 | else | ||
| 998 | return -EINVAL; | ||
| 999 | |||
| 1000 | /* DiSEqC toneburst */ | ||
| 1001 | if(toneburst != CX24116_DISEQC_MESGCACHE) | ||
| 1002 | /* Burst is cached */ | ||
| 1003 | return 0; | ||
| 1004 | |||
| 1005 | /* Burst is to be sent with cached message */ | ||
| 1006 | |||
| 1007 | /* Wait for LNB ready */ | ||
| 1008 | ret = cx24116_wait_for_lnb(fe); | ||
| 1009 | if(ret != 0) | ||
| 1010 | return ret; | ||
| 1011 | |||
| 1012 | /* Wait for voltage/min repeat delay */ | ||
| 1013 | msleep(100); | ||
| 1014 | |||
| 1015 | /* Command */ | ||
| 1016 | ret = cx24116_cmd_execute(fe, &state->dsec_cmd); | ||
| 1017 | if(ret != 0) | ||
| 1018 | return ret; | ||
| 1019 | |||
| 1020 | /* | ||
| 1021 | * Wait for send | ||
| 1022 | * | ||
| 1023 | * Eutelsat spec: | ||
| 1024 | * >15ms delay + (XXX determine if FW does this, see set_tone) | ||
| 1025 | * 13.5ms per byte + | ||
| 1026 | * >15ms delay + | ||
| 1027 | * 12.5ms burst + | ||
| 1028 | * >15ms delay (XXX determine if FW does this, see set_tone) | ||
| 1029 | */ | ||
| 1030 | msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 ); | ||
| 1031 | |||
| 1032 | return 0; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | static void cx24116_release(struct dvb_frontend* fe) | ||
| 1036 | { | ||
| 1037 | struct cx24116_state* state = fe->demodulator_priv; | ||
| 1038 | dprintk("%s\n",__func__); | ||
| 1039 | kfree(state); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | static struct dvb_frontend_ops cx24116_ops; | ||
| 1043 | |||
| 1044 | struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, | ||
| 1045 | struct i2c_adapter* i2c) | ||
| 1046 | { | ||
| 1047 | struct cx24116_state* state = NULL; | ||
| 1048 | int ret; | ||
| 1049 | |||
| 1050 | dprintk("%s\n",__func__); | ||
| 1051 | |||
| 1052 | /* allocate memory for the internal state */ | ||
| 1053 | state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL); | ||
| 1054 | if (state == NULL) { | ||
| 1055 | printk("Unable to kmalloc\n"); | ||
| 1056 | goto error1; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | /* setup the state */ | ||
| 1060 | memset(state, 0, sizeof(struct cx24116_state)); | ||
| 1061 | |||
| 1062 | state->config = config; | ||
| 1063 | state->i2c = i2c; | ||
| 1064 | |||
| 1065 | /* check if the demod is present */ | ||
| 1066 | ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE); | ||
| 1067 | if (ret != 0x0501) { | ||
| 1068 | printk("Invalid probe, probably not a CX24116 device\n"); | ||
| 1069 | goto error2; | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | /* create dvb_frontend */ | ||
| 1073 | memcpy(&state->frontend.ops, &cx24116_ops, sizeof(struct dvb_frontend_ops)); | ||
| 1074 | state->frontend.demodulator_priv = state; | ||
| 1075 | return &state->frontend; | ||
| 1076 | |||
| 1077 | error2: kfree(state); | ||
| 1078 | error1: return NULL; | ||
| 1079 | } | ||
| 1080 | /* | ||
| 1081 | * Initialise or wake up device | ||
| 1082 | * | ||
| 1083 | * Power config will reset and load initial firmware if required | ||
| 1084 | */ | ||
| 1085 | static int cx24116_initfe(struct dvb_frontend* fe) | ||
| 1086 | { | ||
| 1087 | struct cx24116_state* state = fe->demodulator_priv; | ||
| 1088 | struct cx24116_cmd cmd; | ||
| 1089 | int ret; | ||
| 1090 | |||
| 1091 | dprintk("%s()\n",__func__); | ||
| 1092 | |||
| 1093 | /* Power on */ | ||
| 1094 | cx24116_writereg(state, 0xe0, 0); | ||
| 1095 | cx24116_writereg(state, 0xe1, 0); | ||
| 1096 | cx24116_writereg(state, 0xea, 0); | ||
| 1097 | |||
| 1098 | /* Firmware CMD 36: Power config */ | ||
| 1099 | cmd.args[0x00] = CMD_TUNERSLEEP; | ||
| 1100 | cmd.args[0x01] = 0; | ||
| 1101 | cmd.len= 0x02; | ||
| 1102 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 1103 | if(ret != 0) | ||
| 1104 | return ret; | ||
| 1105 | |||
| 1106 | return cx24116_diseqc_init(fe); | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | /* | ||
| 1110 | * Put device to sleep | ||
| 1111 | */ | ||
| 1112 | static int cx24116_sleep(struct dvb_frontend* fe) | ||
| 1113 | { | ||
| 1114 | struct cx24116_state* state = fe->demodulator_priv; | ||
| 1115 | struct cx24116_cmd cmd; | ||
| 1116 | int ret; | ||
| 1117 | |||
| 1118 | dprintk("%s()\n",__func__); | ||
| 1119 | |||
| 1120 | /* Firmware CMD 36: Power config */ | ||
| 1121 | cmd.args[0x00] = CMD_TUNERSLEEP; | ||
| 1122 | cmd.args[0x01] = 1; | ||
| 1123 | cmd.len= 0x02; | ||
| 1124 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 1125 | if(ret != 0) | ||
| 1126 | return ret; | ||
| 1127 | |||
| 1128 | /* Power off (Shutdown clocks) */ | ||
| 1129 | cx24116_writereg(state, 0xea, 0xff); | ||
| 1130 | cx24116_writereg(state, 0xe1, 1); | ||
| 1131 | cx24116_writereg(state, 0xe0, 1); | ||
| 1132 | |||
| 1133 | return 0; | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp) | ||
| 1137 | { | ||
| 1138 | dprintk("%s(..)\n", __func__); | ||
| 1139 | return 0; | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp) | ||
| 1143 | { | ||
| 1144 | dprintk("%s(..)\n", __func__); | ||
| 1145 | return 0; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | /* dvb-core told us to tune, the tv property cache will be complete, | ||
| 1149 | * it's safe for is to pull values and use them for tuning purposes. | ||
| 1150 | */ | ||
| 1151 | static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | ||
| 1152 | { | ||
| 1153 | struct cx24116_state *state = fe->demodulator_priv; | ||
| 1154 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 1155 | struct cx24116_cmd cmd; | ||
| 1156 | fe_status_t tunerstat; | ||
| 1157 | int i, status, ret, retune; | ||
| 1158 | |||
| 1159 | dprintk("%s()\n",__func__); | ||
| 1160 | |||
| 1161 | switch(c->delivery_system) { | ||
| 1162 | case SYS_DVBS: | ||
| 1163 | dprintk("%s: DVB-S delivery system selected\n",__func__); | ||
| 1164 | |||
| 1165 | /* Only QPSK is supported for DVB-S */ | ||
| 1166 | if(c->modulation != QPSK) { | ||
| 1167 | dprintk("%s: unsupported modulation selected (%d)\n", | ||
| 1168 | __func__, c->modulation); | ||
| 1169 | return -EOPNOTSUPP; | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | /* Pilot doesn't exist in DVB-S, turn bit off */ | ||
| 1173 | state->dnxt.pilot_val = CX24116_PILOT_OFF; | ||
| 1174 | retune = 1; | ||
| 1175 | |||
| 1176 | /* DVB-S only supports 0.35 */ | ||
| 1177 | if(c->rolloff != ROLLOFF_35) { | ||
| 1178 | dprintk("%s: unsupported rolloff selected (%d)\n", | ||
| 1179 | __func__, c->rolloff); | ||
| 1180 | return -EOPNOTSUPP; | ||
| 1181 | } | ||
| 1182 | state->dnxt.rolloff_val = CX24116_ROLLOFF_035; | ||
| 1183 | break; | ||
| 1184 | |||
| 1185 | case SYS_DVBS2: | ||
| 1186 | dprintk("%s: DVB-S2 delivery system selected\n",__func__); | ||
| 1187 | |||
| 1188 | /* | ||
| 1189 | * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2, | ||
| 1190 | * but not hardware auto detection | ||
| 1191 | */ | ||
| 1192 | if(c->modulation != PSK_8 && c->modulation != QPSK) { | ||
| 1193 | dprintk("%s: unsupported modulation selected (%d)\n", | ||
| 1194 | __func__, c->modulation); | ||
| 1195 | return -EOPNOTSUPP; | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | switch(c->pilot) { | ||
| 1199 | case PILOT_AUTO: /* Not supported but emulated */ | ||
| 1200 | retune = 2; /* Fall-through */ | ||
| 1201 | case PILOT_OFF: | ||
| 1202 | state->dnxt.pilot_val = CX24116_PILOT_OFF; | ||
| 1203 | break; | ||
| 1204 | case PILOT_ON: | ||
| 1205 | state->dnxt.pilot_val = CX24116_PILOT_ON; | ||
| 1206 | break; | ||
| 1207 | default: | ||
| 1208 | dprintk("%s: unsupported pilot mode selected (%d)\n", | ||
| 1209 | __func__, c->pilot); | ||
| 1210 | return -EOPNOTSUPP; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | switch(c->rolloff) { | ||
| 1214 | case ROLLOFF_20: | ||
| 1215 | state->dnxt.rolloff_val= CX24116_ROLLOFF_020; | ||
| 1216 | break; | ||
| 1217 | case ROLLOFF_25: | ||
| 1218 | state->dnxt.rolloff_val= CX24116_ROLLOFF_025; | ||
| 1219 | break; | ||
| 1220 | case ROLLOFF_35: | ||
| 1221 | state->dnxt.rolloff_val= CX24116_ROLLOFF_035; | ||
| 1222 | break; | ||
| 1223 | case ROLLOFF_AUTO: /* Rolloff must be explicit */ | ||
| 1224 | default: | ||
| 1225 | dprintk("%s: unsupported rolloff selected (%d)\n", | ||
| 1226 | __func__, c->rolloff); | ||
| 1227 | return -EOPNOTSUPP; | ||
| 1228 | } | ||
| 1229 | break; | ||
| 1230 | |||
| 1231 | default: | ||
| 1232 | dprintk("%s: unsupported delivery system selected (%d)\n", | ||
| 1233 | __func__, c->delivery_system); | ||
| 1234 | return -EOPNOTSUPP; | ||
| 1235 | } | ||
| 1236 | state->dnxt.modulation = c->modulation; | ||
| 1237 | state->dnxt.frequency = c->frequency; | ||
| 1238 | state->dnxt.pilot = c->pilot; | ||
| 1239 | state->dnxt.rolloff = c->rolloff; | ||
| 1240 | |||
| 1241 | if ((ret = cx24116_set_inversion(state, c->inversion)) != 0) | ||
| 1242 | return ret; | ||
| 1243 | |||
| 1244 | /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */ | ||
| 1245 | if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) != 0) | ||
| 1246 | return ret; | ||
| 1247 | |||
| 1248 | if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) != 0) | ||
| 1249 | return ret; | ||
| 1250 | |||
| 1251 | /* discard the 'current' tuning parameters and prepare to tune */ | ||
| 1252 | cx24116_clone_params(fe); | ||
| 1253 | |||
| 1254 | dprintk("%s: modulation = %d\n", __func__, state->dcur.modulation); | ||
| 1255 | dprintk("%s: frequency = %d\n", __func__, state->dcur.frequency); | ||
| 1256 | dprintk("%s: pilot = %d (val = 0x%02x)\n", __func__, | ||
| 1257 | state->dcur.pilot, state->dcur.pilot_val); | ||
| 1258 | dprintk("%s: retune = %d\n", __func__, retune); | ||
| 1259 | dprintk("%s: rolloff = %d (val = 0x%02x)\n", __func__, | ||
| 1260 | state->dcur.rolloff, state->dcur.rolloff_val); | ||
| 1261 | dprintk("%s: symbol_rate = %d\n", __func__, state->dcur.symbol_rate); | ||
| 1262 | dprintk("%s: FEC = %d (mask/val = 0x%02x/0x%02x)\n", __func__, | ||
| 1263 | state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val); | ||
| 1264 | dprintk("%s: Inversion = %d (val = 0x%02x)\n", __func__, | ||
| 1265 | state->dcur.inversion, state->dcur.inversion_val); | ||
| 1266 | |||
| 1267 | /* This is also done in advise/acquire on HVR4000 but not on LITE */ | ||
| 1268 | if (state->config->set_ts_params) | ||
| 1269 | state->config->set_ts_params(fe, 0); | ||
| 1270 | |||
| 1271 | /* Set/Reset B/W */ | ||
| 1272 | cmd.args[0x00] = CMD_BANDWIDTH; | ||
| 1273 | cmd.args[0x01] = 0x01; | ||
| 1274 | cmd.len= 0x02; | ||
| 1275 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 1276 | if (ret != 0) | ||
| 1277 | return ret; | ||
| 1278 | |||
| 1279 | /* Prepare a tune request */ | ||
| 1280 | cmd.args[0x00] = CMD_TUNEREQUEST; | ||
| 1281 | |||
| 1282 | /* Frequency */ | ||
| 1283 | cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16; | ||
| 1284 | cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8; | ||
| 1285 | cmd.args[0x03] = (state->dcur.frequency & 0x0000ff); | ||
| 1286 | |||
| 1287 | /* Symbol Rate */ | ||
| 1288 | cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8; | ||
| 1289 | cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff); | ||
| 1290 | |||
| 1291 | /* Automatic Inversion */ | ||
| 1292 | cmd.args[0x06] = state->dcur.inversion_val; | ||
| 1293 | |||
| 1294 | /* Modulation / FEC / Pilot */ | ||
| 1295 | cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val; | ||
| 1296 | |||
| 1297 | cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8; | ||
| 1298 | cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff; | ||
| 1299 | cmd.args[0x0a] = 0x00; | ||
| 1300 | cmd.args[0x0b] = 0x00; | ||
| 1301 | cmd.args[0x0c] = state->dcur.rolloff_val; | ||
| 1302 | cmd.args[0x0d] = state->dcur.fec_mask; | ||
| 1303 | |||
| 1304 | if (state->dcur.symbol_rate > 30000000) { | ||
| 1305 | cmd.args[0x0e] = 0x04; | ||
| 1306 | cmd.args[0x0f] = 0x00; | ||
| 1307 | cmd.args[0x10] = 0x01; | ||
| 1308 | cmd.args[0x11] = 0x77; | ||
| 1309 | cmd.args[0x12] = 0x36; | ||
| 1310 | cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44); | ||
| 1311 | cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01); | ||
| 1312 | } else { | ||
| 1313 | cmd.args[0x0e] = 0x06; | ||
| 1314 | cmd.args[0x0f] = 0x00; | ||
| 1315 | cmd.args[0x10] = 0x00; | ||
| 1316 | cmd.args[0x11] = 0xFA; | ||
| 1317 | cmd.args[0x12] = 0x24; | ||
| 1318 | cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46); | ||
| 1319 | cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00); | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | cmd.len= 0x13; | ||
| 1323 | |||
| 1324 | /* We need to support pilot and non-pilot tuning in the | ||
| 1325 | * driver automatically. This is a workaround for because | ||
| 1326 | * the demod does not support autodetect. | ||
| 1327 | */ | ||
| 1328 | do { | ||
| 1329 | /* Reset status register */ | ||
| 1330 | status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK; | ||
| 1331 | cx24116_writereg(state, CX24116_REG_SSTATUS, status); | ||
| 1332 | |||
| 1333 | /* Tune */ | ||
| 1334 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 1335 | if( ret != 0 ) | ||
| 1336 | break; | ||
| 1337 | |||
| 1338 | /* | ||
| 1339 | * Wait for up to 500 ms before retrying | ||
| 1340 | * | ||
| 1341 | * If we are able to tune then generally it occurs within 100ms. | ||
| 1342 | * If it takes longer, try a different toneburst setting. | ||
| 1343 | */ | ||
| 1344 | for(i = 0; i < 50 ; i++) { | ||
| 1345 | cx24116_read_status(fe, &tunerstat); | ||
| 1346 | status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC); | ||
| 1347 | if(status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) { | ||
| 1348 | dprintk("%s: Tuned\n",__func__); | ||
| 1349 | goto tuned; | ||
| 1350 | } | ||
| 1351 | msleep(10); | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | dprintk("%s: Not tuned\n",__func__); | ||
| 1355 | |||
| 1356 | /* Toggle pilot bit when in auto-pilot */ | ||
| 1357 | if(state->dcur.pilot == PILOT_AUTO) | ||
| 1358 | cmd.args[0x07] ^= CX24116_PILOT_ON; | ||
| 1359 | } | ||
| 1360 | while(--retune); | ||
| 1361 | |||
| 1362 | tuned: /* Set/Reset B/W */ | ||
| 1363 | cmd.args[0x00] = CMD_BANDWIDTH; | ||
| 1364 | cmd.args[0x01] = 0x00; | ||
| 1365 | cmd.len= 0x02; | ||
| 1366 | ret = cx24116_cmd_execute(fe, &cmd); | ||
| 1367 | if (ret != 0) | ||
| 1368 | return ret; | ||
| 1369 | |||
| 1370 | return ret; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | static struct dvb_frontend_ops cx24116_ops = { | ||
| 1374 | |||
| 1375 | .info = { | ||
| 1376 | .name = "Conexant CX24116/CX24118", | ||
| 1377 | .type = FE_QPSK, | ||
| 1378 | .frequency_min = 950000, | ||
| 1379 | .frequency_max = 2150000, | ||
| 1380 | .frequency_stepsize = 1011, /* kHz for QPSK frontends */ | ||
| 1381 | .frequency_tolerance = 5000, | ||
| 1382 | .symbol_rate_min = 1000000, | ||
| 1383 | .symbol_rate_max = 45000000, | ||
| 1384 | .caps = FE_CAN_INVERSION_AUTO | | ||
| 1385 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 1386 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | | ||
| 1387 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
| 1388 | FE_CAN_QPSK | FE_CAN_RECOVER | ||
| 1389 | }, | ||
| 1390 | |||
| 1391 | .release = cx24116_release, | ||
| 1392 | |||
| 1393 | .init = cx24116_initfe, | ||
| 1394 | .sleep = cx24116_sleep, | ||
| 1395 | .read_status = cx24116_read_status, | ||
| 1396 | .read_ber = cx24116_read_ber, | ||
| 1397 | .read_signal_strength = cx24116_read_signal_strength, | ||
| 1398 | .read_snr = cx24116_read_snr, | ||
| 1399 | .read_ucblocks = cx24116_read_ucblocks, | ||
| 1400 | .set_tone = cx24116_set_tone, | ||
| 1401 | .set_voltage = cx24116_set_voltage, | ||
| 1402 | .diseqc_send_master_cmd = cx24116_send_diseqc_msg, | ||
| 1403 | .diseqc_send_burst = cx24116_diseqc_send_burst, | ||
| 1404 | |||
| 1405 | .set_property = cx24116_set_property, | ||
| 1406 | .get_property = cx24116_get_property, | ||
| 1407 | .set_frontend = cx24116_set_frontend, | ||
| 1408 | }; | ||
| 1409 | |||
| 1410 | module_param(debug, int, 0644); | ||
| 1411 | MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); | ||
| 1412 | |||
| 1413 | module_param(toneburst, int, 0644); | ||
| 1414 | MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)"); | ||
| 1415 | |||
| 1416 | module_param(esno_snr, int, 0644); | ||
| 1417 | MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, 1=ESNO(db * 10) (default:0)"); | ||
| 1418 | |||
| 1419 | MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware"); | ||
| 1420 | MODULE_AUTHOR("Steven Toth"); | ||
| 1421 | MODULE_LICENSE("GPL"); | ||
| 1422 | |||
| 1423 | EXPORT_SYMBOL(cx24116_attach); | ||
diff --git a/drivers/media/dvb/frontends/cx24116.h b/drivers/media/dvb/frontends/cx24116.h new file mode 100644 index 000000000000..8dbcec268394 --- /dev/null +++ b/drivers/media/dvb/frontends/cx24116.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /* | ||
| 2 | Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver | ||
| 3 | |||
| 4 | Copyright (C) 2006 Steven Toth <stoth@linuxtv.com> | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef CX24116_H | ||
| 22 | #define CX24116_H | ||
| 23 | |||
| 24 | #include <linux/dvb/frontend.h> | ||
| 25 | |||
| 26 | struct cx24116_config | ||
| 27 | { | ||
| 28 | /* the demodulator's i2c address */ | ||
| 29 | u8 demod_address; | ||
| 30 | |||
| 31 | /* Need to set device param for start_dma */ | ||
| 32 | int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); | ||
| 33 | |||
| 34 | /* Need to reset device during firmware loading */ | ||
| 35 | int (*reset_device)(struct dvb_frontend* fe); | ||
| 36 | |||
| 37 | /* Need to set MPEG parameters */ | ||
| 38 | u8 mpg_clk_pos_pol:0x02; | ||
| 39 | }; | ||
| 40 | |||
| 41 | #if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE) | ||
| 42 | extern struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, | ||
| 43 | struct i2c_adapter* i2c); | ||
| 44 | #else | ||
| 45 | static inline struct dvb_frontend* cx24116_attach(const struct cx24116_config* config, | ||
| 46 | struct i2c_adapter* i2c) | ||
| 47 | { | ||
| 48 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | ||
| 49 | return NULL; | ||
| 50 | } | ||
| 51 | #endif // CONFIG_DVB_CX24116 | ||
| 52 | |||
| 53 | #endif /* CX24116_H */ | ||
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h index 3eedfdf505bc..21f2c5161af4 100644 --- a/drivers/media/dvb/frontends/dib0070.h +++ b/drivers/media/dvb/frontends/dib0070.h | |||
| @@ -41,6 +41,7 @@ struct dib0070_config { | |||
| 41 | extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, | 41 | extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, |
| 42 | struct i2c_adapter *i2c, | 42 | struct i2c_adapter *i2c, |
| 43 | struct dib0070_config *cfg); | 43 | struct dib0070_config *cfg); |
| 44 | extern u16 dib0070_wbd_offset(struct dvb_frontend *); | ||
| 44 | #else | 45 | #else |
| 45 | static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, | 46 | static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, |
| 46 | struct i2c_adapter *i2c, | 47 | struct i2c_adapter *i2c, |
| @@ -49,9 +50,14 @@ static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, | |||
| 49 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 50 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
| 50 | return NULL; | 51 | return NULL; |
| 51 | } | 52 | } |
| 53 | |||
| 54 | static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe) | ||
| 55 | { | ||
| 56 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 57 | return -ENODEV; | ||
| 58 | } | ||
| 52 | #endif | 59 | #endif |
| 53 | 60 | ||
| 54 | extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open); | 61 | extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open); |
| 55 | extern u16 dib0070_wbd_offset(struct dvb_frontend *); | ||
| 56 | 62 | ||
| 57 | #endif | 63 | #endif |
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index 5f1375e30dfc..0109720353bd 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c | |||
| @@ -1284,7 +1284,10 @@ struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum di | |||
| 1284 | } | 1284 | } |
| 1285 | EXPORT_SYMBOL(dib7000m_get_i2c_master); | 1285 | EXPORT_SYMBOL(dib7000m_get_i2c_master); |
| 1286 | 1286 | ||
| 1287 | int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[]) | 1287 | #if 0 |
| 1288 | /* used with some prototype boards */ | ||
| 1289 | int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, | ||
| 1290 | u8 default_addr, struct dib7000m_config cfg[]) | ||
| 1288 | { | 1291 | { |
| 1289 | struct dib7000m_state st = { .i2c_adap = i2c }; | 1292 | struct dib7000m_state st = { .i2c_adap = i2c }; |
| 1290 | int k = 0; | 1293 | int k = 0; |
| @@ -1329,6 +1332,7 @@ int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau | |||
| 1329 | return 0; | 1332 | return 0; |
| 1330 | } | 1333 | } |
| 1331 | EXPORT_SYMBOL(dib7000m_i2c_enumeration); | 1334 | EXPORT_SYMBOL(dib7000m_i2c_enumeration); |
| 1335 | #endif | ||
| 1332 | 1336 | ||
| 1333 | static struct dvb_frontend_ops dib7000m_ops; | 1337 | static struct dvb_frontend_ops dib7000m_ops; |
| 1334 | struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg) | 1338 | struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg) |
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 1a0142e0d741..8217e5b38f47 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c | |||
| @@ -1333,7 +1333,8 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, | |||
| 1333 | /* Ensure the output mode remains at the previous default if it's | 1333 | /* Ensure the output mode remains at the previous default if it's |
| 1334 | * not specifically set by the caller. | 1334 | * not specifically set by the caller. |
| 1335 | */ | 1335 | */ |
| 1336 | if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) | 1336 | if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && |
| 1337 | (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK)) | ||
| 1337 | st->cfg.output_mode = OUTMODE_MPEG2_FIFO; | 1338 | st->cfg.output_mode = OUTMODE_MPEG2_FIFO; |
| 1338 | 1339 | ||
| 1339 | demod = &st->demod; | 1340 | demod = &st->demod; |
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 07c4d12ed5b7..3e8126857127 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h | |||
| @@ -41,6 +41,14 @@ struct dib7000p_config { | |||
| 41 | extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, | 41 | extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, |
| 42 | u8 i2c_addr, | 42 | u8 i2c_addr, |
| 43 | struct dib7000p_config *cfg); | 43 | struct dib7000p_config *cfg); |
| 44 | extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, | ||
| 45 | enum dibx000_i2c_interface, | ||
| 46 | int); | ||
| 47 | extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, | ||
| 48 | int no_of_demods, u8 default_addr, | ||
| 49 | struct dib7000p_config cfg[]); | ||
| 50 | extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); | ||
| 51 | extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value); | ||
| 44 | #else | 52 | #else |
| 45 | static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, | 53 | static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, |
| 46 | u8 i2c_addr, | 54 | u8 i2c_addr, |
| @@ -49,13 +57,36 @@ static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, | |||
| 49 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 57 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
| 50 | return NULL; | 58 | return NULL; |
| 51 | } | 59 | } |
| 52 | #endif | ||
| 53 | 60 | ||
| 54 | extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]); | 61 | static inline |
| 62 | struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, | ||
| 63 | enum dibx000_i2c_interface i, int x) | ||
| 64 | { | ||
| 65 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 66 | return NULL; | ||
| 67 | } | ||
| 68 | |||
| 69 | extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, | ||
| 70 | int no_of_demods, u8 default_addr, | ||
| 71 | struct dib7000p_config cfg[]) | ||
| 72 | { | ||
| 73 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 74 | return -ENODEV; | ||
| 75 | } | ||
| 76 | |||
| 77 | extern int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) | ||
| 78 | { | ||
| 79 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 80 | return -ENODEV; | ||
| 81 | } | ||
| 82 | |||
| 83 | extern int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value) | ||
| 84 | { | ||
| 85 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 86 | return -ENODEV; | ||
| 87 | } | ||
| 88 | #endif | ||
| 55 | 89 | ||
| 56 | extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); | ||
| 57 | extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); | 90 | extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); |
| 58 | extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); | ||
| 59 | extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value); | ||
| 60 | 91 | ||
| 61 | #endif | 92 | #endif |
diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c index 3cbed874a6f8..b9ca5c8d2dd9 100644 --- a/drivers/media/dvb/frontends/drx397xD.c +++ b/drivers/media/dvb/frontends/drx397xD.c | |||
| @@ -38,35 +38,32 @@ static const char mod_name[] = "drx397xD"; | |||
| 38 | #define F_SET_0D0h 1 | 38 | #define F_SET_0D0h 1 |
| 39 | #define F_SET_0D4h 2 | 39 | #define F_SET_0D4h 2 |
| 40 | 40 | ||
| 41 | typedef enum fw_ix { | 41 | enum fw_ix { |
| 42 | #define _FW_ENTRY(a, b) b | 42 | #define _FW_ENTRY(a, b) b |
| 43 | #include "drx397xD_fw.h" | 43 | #include "drx397xD_fw.h" |
| 44 | } fw_ix_t; | 44 | }; |
| 45 | 45 | ||
| 46 | /* chip specifics */ | 46 | /* chip specifics */ |
| 47 | struct drx397xD_state { | 47 | struct drx397xD_state { |
| 48 | struct i2c_adapter *i2c; | 48 | struct i2c_adapter *i2c; |
| 49 | struct dvb_frontend frontend; | 49 | struct dvb_frontend frontend; |
| 50 | struct drx397xD_config config; | 50 | struct drx397xD_config config; |
| 51 | fw_ix_t chip_rev; | 51 | enum fw_ix chip_rev; |
| 52 | int flags; | 52 | int flags; |
| 53 | u32 bandwidth_parm; /* internal bandwidth conversions */ | 53 | u32 bandwidth_parm; /* internal bandwidth conversions */ |
| 54 | u32 f_osc; /* w90: actual osc frequency [Hz] */ | 54 | u32 f_osc; /* w90: actual osc frequency [Hz] */ |
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | /******************************************************************************* | 57 | /* Firmware */ |
| 58 | * Firmware | ||
| 59 | ******************************************************************************/ | ||
| 60 | |||
| 61 | static const char *blob_name[] = { | 58 | static const char *blob_name[] = { |
| 62 | #define _BLOB_ENTRY(a, b) a | 59 | #define _BLOB_ENTRY(a, b) a |
| 63 | #include "drx397xD_fw.h" | 60 | #include "drx397xD_fw.h" |
| 64 | }; | 61 | }; |
| 65 | 62 | ||
| 66 | typedef enum blob_ix { | 63 | enum blob_ix { |
| 67 | #define _BLOB_ENTRY(a, b) b | 64 | #define _BLOB_ENTRY(a, b) b |
| 68 | #include "drx397xD_fw.h" | 65 | #include "drx397xD_fw.h" |
| 69 | } blob_ix_t; | 66 | }; |
| 70 | 67 | ||
| 71 | static struct { | 68 | static struct { |
| 72 | const char *name; | 69 | const char *name; |
| @@ -85,7 +82,7 @@ static struct { | |||
| 85 | }; | 82 | }; |
| 86 | 83 | ||
| 87 | /* use only with writer lock aquired */ | 84 | /* use only with writer lock aquired */ |
| 88 | static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix) | 85 | static void _drx_release_fw(struct drx397xD_state *s, enum fw_ix ix) |
| 89 | { | 86 | { |
| 90 | memset(&fw[ix].data[0], 0, sizeof(fw[0].data)); | 87 | memset(&fw[ix].data[0], 0, sizeof(fw[0].data)); |
| 91 | if (fw[ix].file) | 88 | if (fw[ix].file) |
| @@ -94,9 +91,9 @@ static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix) | |||
| 94 | 91 | ||
| 95 | static void drx_release_fw(struct drx397xD_state *s) | 92 | static void drx_release_fw(struct drx397xD_state *s) |
| 96 | { | 93 | { |
| 97 | fw_ix_t ix = s->chip_rev; | 94 | enum fw_ix ix = s->chip_rev; |
| 98 | 95 | ||
| 99 | pr_debug("%s\n", __FUNCTION__); | 96 | pr_debug("%s\n", __func__); |
| 100 | 97 | ||
| 101 | write_lock(&fw[ix].lock); | 98 | write_lock(&fw[ix].lock); |
| 102 | if (fw[ix].refcnt) { | 99 | if (fw[ix].refcnt) { |
| @@ -107,13 +104,13 @@ static void drx_release_fw(struct drx397xD_state *s) | |||
| 107 | write_unlock(&fw[ix].lock); | 104 | write_unlock(&fw[ix].lock); |
| 108 | } | 105 | } |
| 109 | 106 | ||
| 110 | static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix) | 107 | static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix) |
| 111 | { | 108 | { |
| 112 | const u8 *data; | 109 | const u8 *data; |
| 113 | size_t size, len; | 110 | size_t size, len; |
| 114 | int i = 0, j, rc = -EINVAL; | 111 | int i = 0, j, rc = -EINVAL; |
| 115 | 112 | ||
| 116 | pr_debug("%s\n", __FUNCTION__); | 113 | pr_debug("%s\n", __func__); |
| 117 | 114 | ||
| 118 | if (ix < 0 || ix >= ARRAY_SIZE(fw)) | 115 | if (ix < 0 || ix >= ARRAY_SIZE(fw)) |
| 119 | return -EINVAL; | 116 | return -EINVAL; |
| @@ -175,32 +172,34 @@ static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix) | |||
| 175 | goto exit_corrupt; | 172 | goto exit_corrupt; |
| 176 | } | 173 | } |
| 177 | } while (i < size); | 174 | } while (i < size); |
| 178 | exit_corrupt: | 175 | |
| 176 | exit_corrupt: | ||
| 179 | printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name); | 177 | printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name); |
| 180 | exit_err: | 178 | exit_err: |
| 181 | _drx_release_fw(s, ix); | 179 | _drx_release_fw(s, ix); |
| 182 | fw[ix].refcnt--; | 180 | fw[ix].refcnt--; |
| 183 | exit_ok: | 181 | exit_ok: |
| 184 | fw[ix].refcnt++; | 182 | fw[ix].refcnt++; |
| 185 | write_unlock(&fw[ix].lock); | 183 | write_unlock(&fw[ix].lock); |
| 184 | |||
| 186 | return rc; | 185 | return rc; |
| 187 | } | 186 | } |
| 188 | 187 | ||
| 189 | /******************************************************************************* | 188 | /* i2c bus IO */ |
| 190 | * i2c bus IO | 189 | static int write_fw(struct drx397xD_state *s, enum blob_ix ix) |
| 191 | ******************************************************************************/ | ||
| 192 | |||
| 193 | static int write_fw(struct drx397xD_state *s, blob_ix_t ix) | ||
| 194 | { | 190 | { |
| 195 | struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 }; | ||
| 196 | const u8 *data; | 191 | const u8 *data; |
| 197 | int len, rc = 0, i = 0; | 192 | int len, rc = 0, i = 0; |
| 193 | struct i2c_msg msg = { | ||
| 194 | .addr = s->config.demod_address, | ||
| 195 | .flags = 0 | ||
| 196 | }; | ||
| 198 | 197 | ||
| 199 | if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) { | 198 | if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) { |
| 200 | pr_debug("%s drx_fw_ix_t out of range\n", __FUNCTION__); | 199 | pr_debug("%s drx_fw_ix_t out of range\n", __func__); |
| 201 | return -EINVAL; | 200 | return -EINVAL; |
| 202 | } | 201 | } |
| 203 | pr_debug("%s %s\n", __FUNCTION__, blob_name[ix]); | 202 | pr_debug("%s %s\n", __func__, blob_name[ix]); |
| 204 | 203 | ||
| 205 | read_lock(&fw[s->chip_rev].lock); | 204 | read_lock(&fw[s->chip_rev].lock); |
| 206 | data = fw[s->chip_rev].data[ix]; | 205 | data = fw[s->chip_rev].data[ix]; |
| @@ -229,33 +228,33 @@ static int write_fw(struct drx397xD_state *s, blob_ix_t ix) | |||
| 229 | goto exit_rc; | 228 | goto exit_rc; |
| 230 | } | 229 | } |
| 231 | } | 230 | } |
| 232 | exit_rc: | 231 | exit_rc: |
| 233 | read_unlock(&fw[s->chip_rev].lock); | 232 | read_unlock(&fw[s->chip_rev].lock); |
| 233 | |||
| 234 | return 0; | 234 | return 0; |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | /* Function is not endian safe, use the RD16 wrapper below */ | 237 | /* Function is not endian safe, use the RD16 wrapper below */ |
| 238 | static int _read16(struct drx397xD_state *s, u32 i2c_adr) | 238 | static int _read16(struct drx397xD_state *s, __le32 i2c_adr) |
| 239 | { | 239 | { |
| 240 | int rc; | 240 | int rc; |
| 241 | u8 a[4]; | 241 | u8 a[4]; |
| 242 | u16 v; | 242 | __le16 v; |
| 243 | struct i2c_msg msg[2] = { | 243 | struct i2c_msg msg[2] = { |
| 244 | { | 244 | { |
| 245 | .addr = s->config.demod_address, | 245 | .addr = s->config.demod_address, |
| 246 | .flags = 0, | 246 | .flags = 0, |
| 247 | .buf = a, | 247 | .buf = a, |
| 248 | .len = sizeof(a) | 248 | .len = sizeof(a) |
| 249 | } | 249 | }, { |
| 250 | , { | 250 | .addr = s->config.demod_address, |
| 251 | .addr = s->config.demod_address, | 251 | .flags = I2C_M_RD, |
| 252 | .flags = I2C_M_RD, | 252 | .buf = (u8 *)&v, |
| 253 | .buf = (u8 *) & v, | 253 | .len = sizeof(v) |
| 254 | .len = sizeof(v) | 254 | } |
| 255 | } | ||
| 256 | }; | 255 | }; |
| 257 | 256 | ||
| 258 | *(u32 *) a = i2c_adr; | 257 | *(__le32 *) a = i2c_adr; |
| 259 | 258 | ||
| 260 | rc = i2c_transfer(s->i2c, msg, 2); | 259 | rc = i2c_transfer(s->i2c, msg, 2); |
| 261 | if (rc != 2) | 260 | if (rc != 2) |
| @@ -265,7 +264,7 @@ static int _read16(struct drx397xD_state *s, u32 i2c_adr) | |||
| 265 | } | 264 | } |
| 266 | 265 | ||
| 267 | /* Function is not endian safe, use the WR16.. wrappers below */ | 266 | /* Function is not endian safe, use the WR16.. wrappers below */ |
| 268 | static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val) | 267 | static int _write16(struct drx397xD_state *s, __le32 i2c_adr, __le16 val) |
| 269 | { | 268 | { |
| 270 | u8 a[6]; | 269 | u8 a[6]; |
| 271 | int rc; | 270 | int rc; |
| @@ -276,28 +275,28 @@ static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val) | |||
| 276 | .len = sizeof(a) | 275 | .len = sizeof(a) |
| 277 | }; | 276 | }; |
| 278 | 277 | ||
| 279 | *(u32 *) a = i2c_adr; | 278 | *(__le32 *)a = i2c_adr; |
| 280 | *(u16 *) & a[4] = val; | 279 | *(__le16 *)&a[4] = val; |
| 281 | 280 | ||
| 282 | rc = i2c_transfer(s->i2c, &msg, 1); | 281 | rc = i2c_transfer(s->i2c, &msg, 1); |
| 283 | if (rc != 1) | 282 | if (rc != 1) |
| 284 | return -EIO; | 283 | return -EIO; |
| 284 | |||
| 285 | return 0; | 285 | return 0; |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | #define WR16(ss,adr, val) \ | 288 | #define WR16(ss, adr, val) \ |
| 289 | _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val)) | 289 | _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val)) |
| 290 | #define WR16_E0(ss,adr, val) \ | 290 | #define WR16_E0(ss, adr, val) \ |
| 291 | _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val)) | 291 | _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val)) |
| 292 | #define RD16(ss,adr) \ | 292 | #define RD16(ss, adr) \ |
| 293 | _read16(ss, I2C_ADR_C0(adr)) | 293 | _read16(ss, I2C_ADR_C0(adr)) |
| 294 | 294 | ||
| 295 | #define EXIT_RC( cmd ) if ( (rc = (cmd)) < 0) goto exit_rc | 295 | #define EXIT_RC(cmd) \ |
| 296 | 296 | if ((rc = (cmd)) < 0) \ | |
| 297 | /******************************************************************************* | 297 | goto exit_rc |
| 298 | * Tuner callback | ||
| 299 | ******************************************************************************/ | ||
| 300 | 298 | ||
| 299 | /* Tuner callback */ | ||
| 301 | static int PLL_Set(struct drx397xD_state *s, | 300 | static int PLL_Set(struct drx397xD_state *s, |
| 302 | struct dvb_frontend_parameters *fep, int *df_tuner) | 301 | struct dvb_frontend_parameters *fep, int *df_tuner) |
| 303 | { | 302 | { |
| @@ -305,7 +304,7 @@ static int PLL_Set(struct drx397xD_state *s, | |||
| 305 | u32 f_tuner, f = fep->frequency; | 304 | u32 f_tuner, f = fep->frequency; |
| 306 | int rc; | 305 | int rc; |
| 307 | 306 | ||
| 308 | pr_debug("%s\n", __FUNCTION__); | 307 | pr_debug("%s\n", __func__); |
| 309 | 308 | ||
| 310 | if ((f > s->frontend.ops.tuner_ops.info.frequency_max) || | 309 | if ((f > s->frontend.ops.tuner_ops.info.frequency_max) || |
| 311 | (f < s->frontend.ops.tuner_ops.info.frequency_min)) | 310 | (f < s->frontend.ops.tuner_ops.info.frequency_min)) |
| @@ -325,28 +324,26 @@ static int PLL_Set(struct drx397xD_state *s, | |||
| 325 | return rc; | 324 | return rc; |
| 326 | 325 | ||
| 327 | *df_tuner = f_tuner - f; | 326 | *df_tuner = f_tuner - f; |
| 328 | pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __FUNCTION__, f, | 327 | pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __func__, f, |
| 329 | f_tuner); | 328 | f_tuner); |
| 330 | 329 | ||
| 331 | return 0; | 330 | return 0; |
| 332 | } | 331 | } |
| 333 | 332 | ||
| 334 | /******************************************************************************* | 333 | /* Demodulator helper functions */ |
| 335 | * Demodulator helper functions | ||
| 336 | ******************************************************************************/ | ||
| 337 | |||
| 338 | static int SC_WaitForReady(struct drx397xD_state *s) | 334 | static int SC_WaitForReady(struct drx397xD_state *s) |
| 339 | { | 335 | { |
| 340 | int cnt = 1000; | 336 | int cnt = 1000; |
| 341 | int rc; | 337 | int rc; |
| 342 | 338 | ||
| 343 | pr_debug("%s\n", __FUNCTION__); | 339 | pr_debug("%s\n", __func__); |
| 344 | 340 | ||
| 345 | while (cnt--) { | 341 | while (cnt--) { |
| 346 | rc = RD16(s, 0x820043); | 342 | rc = RD16(s, 0x820043); |
| 347 | if (rc == 0) | 343 | if (rc == 0) |
| 348 | return 0; | 344 | return 0; |
| 349 | } | 345 | } |
| 346 | |||
| 350 | return -1; | 347 | return -1; |
| 351 | } | 348 | } |
| 352 | 349 | ||
| @@ -354,13 +351,14 @@ static int SC_SendCommand(struct drx397xD_state *s, int cmd) | |||
| 354 | { | 351 | { |
| 355 | int rc; | 352 | int rc; |
| 356 | 353 | ||
| 357 | pr_debug("%s\n", __FUNCTION__); | 354 | pr_debug("%s\n", __func__); |
| 358 | 355 | ||
| 359 | WR16(s, 0x820043, cmd); | 356 | WR16(s, 0x820043, cmd); |
| 360 | SC_WaitForReady(s); | 357 | SC_WaitForReady(s); |
| 361 | rc = RD16(s, 0x820042); | 358 | rc = RD16(s, 0x820042); |
| 362 | if ((rc & 0xffff) == 0xffff) | 359 | if ((rc & 0xffff) == 0xffff) |
| 363 | return -1; | 360 | return -1; |
| 361 | |||
| 364 | return 0; | 362 | return 0; |
| 365 | } | 363 | } |
| 366 | 364 | ||
| @@ -368,7 +366,7 @@ static int HI_Command(struct drx397xD_state *s, u16 cmd) | |||
| 368 | { | 366 | { |
| 369 | int rc, cnt = 1000; | 367 | int rc, cnt = 1000; |
| 370 | 368 | ||
| 371 | pr_debug("%s\n", __FUNCTION__); | 369 | pr_debug("%s\n", __func__); |
| 372 | 370 | ||
| 373 | rc = WR16(s, 0x420032, cmd); | 371 | rc = WR16(s, 0x420032, cmd); |
| 374 | if (rc < 0) | 372 | if (rc < 0) |
| @@ -383,22 +381,24 @@ static int HI_Command(struct drx397xD_state *s, u16 cmd) | |||
| 383 | if (rc < 0) | 381 | if (rc < 0) |
| 384 | return rc; | 382 | return rc; |
| 385 | } while (--cnt); | 383 | } while (--cnt); |
| 384 | |||
| 386 | return rc; | 385 | return rc; |
| 387 | } | 386 | } |
| 388 | 387 | ||
| 389 | static int HI_CfgCommand(struct drx397xD_state *s) | 388 | static int HI_CfgCommand(struct drx397xD_state *s) |
| 390 | { | 389 | { |
| 391 | 390 | ||
| 392 | pr_debug("%s\n", __FUNCTION__); | 391 | pr_debug("%s\n", __func__); |
| 393 | 392 | ||
| 394 | WR16(s, 0x420033, 0x3973); | 393 | WR16(s, 0x420033, 0x3973); |
| 395 | WR16(s, 0x420034, s->config.w50); // code 4, log 4 | 394 | WR16(s, 0x420034, s->config.w50); /* code 4, log 4 */ |
| 396 | WR16(s, 0x420035, s->config.w52); // code 15, log 9 | 395 | WR16(s, 0x420035, s->config.w52); /* code 15, log 9 */ |
| 397 | WR16(s, 0x420036, s->config.demod_address << 1); | 396 | WR16(s, 0x420036, s->config.demod_address << 1); |
| 398 | WR16(s, 0x420037, s->config.w56); // code (set_i2c ?? initX 1 ), log 1 | 397 | WR16(s, 0x420037, s->config.w56); /* code (set_i2c ?? initX 1 ), log 1 */ |
| 399 | // WR16(s, 0x420033, 0x3973); | 398 | /* WR16(s, 0x420033, 0x3973); */ |
| 400 | if ((s->config.w56 & 8) == 0) | 399 | if ((s->config.w56 & 8) == 0) |
| 401 | return HI_Command(s, 3); | 400 | return HI_Command(s, 3); |
| 401 | |||
| 402 | return WR16(s, 0x420032, 0x3); | 402 | return WR16(s, 0x420032, 0x3); |
| 403 | } | 403 | } |
| 404 | 404 | ||
| @@ -419,7 +419,7 @@ static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc) | |||
| 419 | u16 w0C = agc->w0C; | 419 | u16 w0C = agc->w0C; |
| 420 | int quot, rem, i, rc = -EINVAL; | 420 | int quot, rem, i, rc = -EINVAL; |
| 421 | 421 | ||
| 422 | pr_debug("%s\n", __FUNCTION__); | 422 | pr_debug("%s\n", __func__); |
| 423 | 423 | ||
| 424 | if (agc->w04 > 0x3ff) | 424 | if (agc->w04 > 0x3ff) |
| 425 | goto exit_rc; | 425 | goto exit_rc; |
| @@ -468,7 +468,7 @@ static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc) | |||
| 468 | i = slowIncrDecLUT_15272[rem / 28]; | 468 | i = slowIncrDecLUT_15272[rem / 28]; |
| 469 | EXIT_RC(WR16(s, 0x0c2002b, i)); | 469 | EXIT_RC(WR16(s, 0x0c2002b, i)); |
| 470 | rc = WR16(s, 0x0c2002c, i); | 470 | rc = WR16(s, 0x0c2002c, i); |
| 471 | exit_rc: | 471 | exit_rc: |
| 472 | return rc; | 472 | return rc; |
| 473 | } | 473 | } |
| 474 | 474 | ||
| @@ -478,7 +478,7 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc) | |||
| 478 | u16 w06 = agc->w06; | 478 | u16 w06 = agc->w06; |
| 479 | int rc = -1; | 479 | int rc = -1; |
| 480 | 480 | ||
| 481 | pr_debug("%s %d 0x%x 0x%x\n", __FUNCTION__, agc->d00, w04, w06); | 481 | pr_debug("%s %d 0x%x 0x%x\n", __func__, agc->d00, w04, w06); |
| 482 | 482 | ||
| 483 | if (w04 > 0x3ff) | 483 | if (w04 > 0x3ff) |
| 484 | goto exit_rc; | 484 | goto exit_rc; |
| @@ -498,7 +498,7 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc) | |||
| 498 | rc &= ~2; | 498 | rc &= ~2; |
| 499 | break; | 499 | break; |
| 500 | case 0: | 500 | case 0: |
| 501 | // loc_8000659 | 501 | /* loc_8000659 */ |
| 502 | s->config.w9C &= ~2; | 502 | s->config.w9C &= ~2; |
| 503 | EXIT_RC(WR16(s, 0x0c20015, s->config.w9C)); | 503 | EXIT_RC(WR16(s, 0x0c20015, s->config.w9C)); |
| 504 | EXIT_RC(RD16(s, 0x0c20010)); | 504 | EXIT_RC(RD16(s, 0x0c20010)); |
| @@ -522,7 +522,8 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc) | |||
| 522 | rc |= 2; | 522 | rc |= 2; |
| 523 | } | 523 | } |
| 524 | rc = WR16(s, 0x0c20013, rc); | 524 | rc = WR16(s, 0x0c20013, rc); |
| 525 | exit_rc: | 525 | |
| 526 | exit_rc: | ||
| 526 | return rc; | 527 | return rc; |
| 527 | } | 528 | } |
| 528 | 529 | ||
| @@ -554,7 +555,7 @@ static int CorrectSysClockDeviation(struct drx397xD_state *s) | |||
| 554 | int lockstat; | 555 | int lockstat; |
| 555 | u32 clk, clk_limit; | 556 | u32 clk, clk_limit; |
| 556 | 557 | ||
| 557 | pr_debug("%s\n", __FUNCTION__); | 558 | pr_debug("%s\n", __func__); |
| 558 | 559 | ||
| 559 | if (s->config.d5C == 0) { | 560 | if (s->config.d5C == 0) { |
| 560 | EXIT_RC(WR16(s, 0x08200e8, 0x010)); | 561 | EXIT_RC(WR16(s, 0x08200e8, 0x010)); |
| @@ -598,11 +599,12 @@ static int CorrectSysClockDeviation(struct drx397xD_state *s) | |||
| 598 | 599 | ||
| 599 | if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) { | 600 | if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) { |
| 600 | s->f_osc = clk; | 601 | s->f_osc = clk; |
| 601 | pr_debug("%s: osc %d %d [Hz]\n", __FUNCTION__, | 602 | pr_debug("%s: osc %d %d [Hz]\n", __func__, |
| 602 | s->config.f_osc * 1000, clk - s->config.f_osc * 1000); | 603 | s->config.f_osc * 1000, clk - s->config.f_osc * 1000); |
| 603 | } | 604 | } |
| 604 | rc = WR16(s, 0x08200e8, 0); | 605 | rc = WR16(s, 0x08200e8, 0); |
| 605 | exit_rc: | 606 | |
| 607 | exit_rc: | ||
| 606 | return rc; | 608 | return rc; |
| 607 | } | 609 | } |
| 608 | 610 | ||
| @@ -610,7 +612,7 @@ static int ConfigureMPEGOutput(struct drx397xD_state *s, int type) | |||
| 610 | { | 612 | { |
| 611 | int rc, si, bp; | 613 | int rc, si, bp; |
| 612 | 614 | ||
| 613 | pr_debug("%s\n", __FUNCTION__); | 615 | pr_debug("%s\n", __func__); |
| 614 | 616 | ||
| 615 | si = s->config.wA0; | 617 | si = s->config.wA0; |
| 616 | if (s->config.w98 == 0) { | 618 | if (s->config.w98 == 0) { |
| @@ -620,17 +622,17 @@ static int ConfigureMPEGOutput(struct drx397xD_state *s, int type) | |||
| 620 | si &= ~1; | 622 | si &= ~1; |
| 621 | bp = 0x200; | 623 | bp = 0x200; |
| 622 | } | 624 | } |
| 623 | if (s->config.w9A == 0) { | 625 | if (s->config.w9A == 0) |
| 624 | si |= 0x80; | 626 | si |= 0x80; |
| 625 | } else { | 627 | else |
| 626 | si &= ~0x80; | 628 | si &= ~0x80; |
| 627 | } | ||
| 628 | 629 | ||
| 629 | EXIT_RC(WR16(s, 0x2150045, 0)); | 630 | EXIT_RC(WR16(s, 0x2150045, 0)); |
| 630 | EXIT_RC(WR16(s, 0x2150010, si)); | 631 | EXIT_RC(WR16(s, 0x2150010, si)); |
| 631 | EXIT_RC(WR16(s, 0x2150011, bp)); | 632 | EXIT_RC(WR16(s, 0x2150011, bp)); |
| 632 | rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0)); | 633 | rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0)); |
| 633 | exit_rc: | 634 | |
| 635 | exit_rc: | ||
| 634 | return rc; | 636 | return rc; |
| 635 | } | 637 | } |
| 636 | 638 | ||
| @@ -646,7 +648,7 @@ static int drx_tune(struct drx397xD_state *s, | |||
| 646 | 648 | ||
| 647 | int rc, df_tuner; | 649 | int rc, df_tuner; |
| 648 | int a, b, c, d; | 650 | int a, b, c, d; |
| 649 | pr_debug("%s %d\n", __FUNCTION__, s->config.d60); | 651 | pr_debug("%s %d\n", __func__, s->config.d60); |
| 650 | 652 | ||
| 651 | if (s->config.d60 != 2) | 653 | if (s->config.d60 != 2) |
| 652 | goto set_tuner; | 654 | goto set_tuner; |
| @@ -658,7 +660,7 @@ static int drx_tune(struct drx397xD_state *s, | |||
| 658 | rc = ConfigureMPEGOutput(s, 0); | 660 | rc = ConfigureMPEGOutput(s, 0); |
| 659 | if (rc < 0) | 661 | if (rc < 0) |
| 660 | goto set_tuner; | 662 | goto set_tuner; |
| 661 | set_tuner: | 663 | set_tuner: |
| 662 | 664 | ||
| 663 | rc = PLL_Set(s, fep, &df_tuner); | 665 | rc = PLL_Set(s, fep, &df_tuner); |
| 664 | if (rc < 0) { | 666 | if (rc < 0) { |
| @@ -835,16 +837,16 @@ static int drx_tune(struct drx397xD_state *s, | |||
| 835 | rc = WR16(s, 0x2010012, 0); | 837 | rc = WR16(s, 0x2010012, 0); |
| 836 | if (rc < 0) | 838 | if (rc < 0) |
| 837 | goto exit_rc; | 839 | goto exit_rc; |
| 838 | // QPSK QAM16 QAM64 | 840 | /* QPSK QAM16 QAM64 */ |
| 839 | ebx = 0x19f; // 62 | 841 | ebx = 0x19f; /* 62 */ |
| 840 | ebp = 0x1fb; // 15 | 842 | ebp = 0x1fb; /* 15 */ |
| 841 | v20 = 0x16a; // 62 | 843 | v20 = 0x16a; /* 62 */ |
| 842 | v1E = 0x195; // 62 | 844 | v1E = 0x195; /* 62 */ |
| 843 | v16 = 0x1bb; // 15 | 845 | v16 = 0x1bb; /* 15 */ |
| 844 | v14 = 0x1ef; // 15 | 846 | v14 = 0x1ef; /* 15 */ |
| 845 | v12 = 5; // 16 | 847 | v12 = 5; /* 16 */ |
| 846 | v10 = 5; // 16 | 848 | v10 = 5; /* 16 */ |
| 847 | v0E = 5; // 16 | 849 | v0E = 5; /* 16 */ |
| 848 | } | 850 | } |
| 849 | 851 | ||
| 850 | switch (fep->u.ofdm.constellation) { | 852 | switch (fep->u.ofdm.constellation) { |
| @@ -997,17 +999,17 @@ static int drx_tune(struct drx397xD_state *s, | |||
| 997 | case BANDWIDTH_8_MHZ: /* 0 */ | 999 | case BANDWIDTH_8_MHZ: /* 0 */ |
| 998 | case BANDWIDTH_AUTO: | 1000 | case BANDWIDTH_AUTO: |
| 999 | rc = WR16(s, 0x0c2003f, 0x32); | 1001 | rc = WR16(s, 0x0c2003f, 0x32); |
| 1000 | s->bandwidth_parm = ebx = 0x8b8249; // 9142857 | 1002 | s->bandwidth_parm = ebx = 0x8b8249; |
| 1001 | edx = 0; | 1003 | edx = 0; |
| 1002 | break; | 1004 | break; |
| 1003 | case BANDWIDTH_7_MHZ: | 1005 | case BANDWIDTH_7_MHZ: |
| 1004 | rc = WR16(s, 0x0c2003f, 0x3b); | 1006 | rc = WR16(s, 0x0c2003f, 0x3b); |
| 1005 | s->bandwidth_parm = ebx = 0x7a1200; // 8000000 | 1007 | s->bandwidth_parm = ebx = 0x7a1200; |
| 1006 | edx = 0x4807; | 1008 | edx = 0x4807; |
| 1007 | break; | 1009 | break; |
| 1008 | case BANDWIDTH_6_MHZ: | 1010 | case BANDWIDTH_6_MHZ: |
| 1009 | rc = WR16(s, 0x0c2003f, 0x47); | 1011 | rc = WR16(s, 0x0c2003f, 0x47); |
| 1010 | s->bandwidth_parm = ebx = 0x68a1b6; // 6857142 | 1012 | s->bandwidth_parm = ebx = 0x68a1b6; |
| 1011 | edx = 0x0f07; | 1013 | edx = 0x0f07; |
| 1012 | break; | 1014 | break; |
| 1013 | }; | 1015 | }; |
| @@ -1060,8 +1062,6 @@ static int drx_tune(struct drx397xD_state *s, | |||
| 1060 | WR16(s, 0x0820040, 1); | 1062 | WR16(s, 0x0820040, 1); |
| 1061 | SC_SendCommand(s, 1); | 1063 | SC_SendCommand(s, 1); |
| 1062 | 1064 | ||
| 1063 | // rc = WR16(s, 0x2150000, 1); | ||
| 1064 | // if (rc < 0) goto exit_rc; | ||
| 1065 | 1065 | ||
| 1066 | rc = WR16(s, 0x2150000, 2); | 1066 | rc = WR16(s, 0x2150000, 2); |
| 1067 | rc = WR16(s, 0x2150016, a); | 1067 | rc = WR16(s, 0x2150016, a); |
| @@ -1069,7 +1069,8 @@ static int drx_tune(struct drx397xD_state *s, | |||
| 1069 | rc = WR16(s, 0x2150036, 0); | 1069 | rc = WR16(s, 0x2150036, 0); |
| 1070 | rc = WR16(s, 0x2150000, 1); | 1070 | rc = WR16(s, 0x2150000, 1); |
| 1071 | s->config.d60 = 2; | 1071 | s->config.d60 = 2; |
| 1072 | exit_rc: | 1072 | |
| 1073 | exit_rc: | ||
| 1073 | return rc; | 1074 | return rc; |
| 1074 | } | 1075 | } |
| 1075 | 1076 | ||
| @@ -1082,7 +1083,7 @@ static int drx397x_init(struct dvb_frontend *fe) | |||
| 1082 | struct drx397xD_state *s = fe->demodulator_priv; | 1083 | struct drx397xD_state *s = fe->demodulator_priv; |
| 1083 | int rc; | 1084 | int rc; |
| 1084 | 1085 | ||
| 1085 | pr_debug("%s\n", __FUNCTION__); | 1086 | pr_debug("%s\n", __func__); |
| 1086 | 1087 | ||
| 1087 | s->config.rfagc.d00 = 2; /* 0x7c */ | 1088 | s->config.rfagc.d00 = 2; /* 0x7c */ |
| 1088 | s->config.rfagc.w04 = 0; | 1089 | s->config.rfagc.w04 = 0; |
| @@ -1102,18 +1103,18 @@ static int drx397x_init(struct dvb_frontend *fe) | |||
| 1102 | 1103 | ||
| 1103 | /* HI_CfgCommand */ | 1104 | /* HI_CfgCommand */ |
| 1104 | s->config.w50 = 4; | 1105 | s->config.w50 = 4; |
| 1105 | s->config.w52 = 9; // 0xf; | 1106 | s->config.w52 = 9; |
| 1106 | 1107 | ||
| 1107 | s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */ | 1108 | s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */ |
| 1108 | s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */ | 1109 | s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */ |
| 1109 | s->config.w92 = 12000; // 20000; | 1110 | s->config.w92 = 12000; |
| 1110 | 1111 | ||
| 1111 | s->config.w9C = 0x000e; | 1112 | s->config.w9C = 0x000e; |
| 1112 | s->config.w9E = 0x0000; | 1113 | s->config.w9E = 0x0000; |
| 1113 | 1114 | ||
| 1114 | /* ConfigureMPEGOutput params */ | 1115 | /* ConfigureMPEGOutput params */ |
| 1115 | s->config.wA0 = 4; | 1116 | s->config.wA0 = 4; |
| 1116 | s->config.w98 = 1; // 0; | 1117 | s->config.w98 = 1; |
| 1117 | s->config.w9A = 1; | 1118 | s->config.w9A = 1; |
| 1118 | 1119 | ||
| 1119 | /* get chip revision */ | 1120 | /* get chip revision */ |
| @@ -1248,7 +1249,7 @@ static int drx397x_init(struct dvb_frontend *fe) | |||
| 1248 | rc = WR16(s, 0x0c20012, 1); | 1249 | rc = WR16(s, 0x0c20012, 1); |
| 1249 | } | 1250 | } |
| 1250 | 1251 | ||
| 1251 | write_DRXD_InitFE_1: | 1252 | write_DRXD_InitFE_1: |
| 1252 | 1253 | ||
| 1253 | rc = write_fw(s, DRXD_InitFE_1); | 1254 | rc = write_fw(s, DRXD_InitFE_1); |
| 1254 | if (rc < 0) | 1255 | if (rc < 0) |
| @@ -1311,7 +1312,8 @@ static int drx397x_init(struct dvb_frontend *fe) | |||
| 1311 | s->config.d5C = 0; | 1312 | s->config.d5C = 0; |
| 1312 | s->config.d60 = 1; | 1313 | s->config.d60 = 1; |
| 1313 | s->config.d48 = 1; | 1314 | s->config.d48 = 1; |
| 1314 | error: | 1315 | |
| 1316 | error: | ||
| 1315 | return rc; | 1317 | return rc; |
| 1316 | } | 1318 | } |
| 1317 | 1319 | ||
| @@ -1326,7 +1328,8 @@ static int drx397x_set_frontend(struct dvb_frontend *fe, | |||
| 1326 | { | 1328 | { |
| 1327 | struct drx397xD_state *s = fe->demodulator_priv; | 1329 | struct drx397xD_state *s = fe->demodulator_priv; |
| 1328 | 1330 | ||
| 1329 | s->config.s20d24 = 1; // 0; | 1331 | s->config.s20d24 = 1; |
| 1332 | |||
| 1330 | return drx_tune(s, params); | 1333 | return drx_tune(s, params); |
| 1331 | } | 1334 | } |
| 1332 | 1335 | ||
| @@ -1337,18 +1340,16 @@ static int drx397x_get_tune_settings(struct dvb_frontend *fe, | |||
| 1337 | fe_tune_settings->min_delay_ms = 10000; | 1340 | fe_tune_settings->min_delay_ms = 10000; |
| 1338 | fe_tune_settings->step_size = 0; | 1341 | fe_tune_settings->step_size = 0; |
| 1339 | fe_tune_settings->max_drift = 0; | 1342 | fe_tune_settings->max_drift = 0; |
| 1343 | |||
| 1340 | return 0; | 1344 | return 0; |
| 1341 | } | 1345 | } |
| 1342 | 1346 | ||
| 1343 | static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status) | 1347 | static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t *status) |
| 1344 | { | 1348 | { |
| 1345 | struct drx397xD_state *s = fe->demodulator_priv; | 1349 | struct drx397xD_state *s = fe->demodulator_priv; |
| 1346 | int lockstat; | 1350 | int lockstat; |
| 1347 | 1351 | ||
| 1348 | GetLockStatus(s, &lockstat); | 1352 | GetLockStatus(s, &lockstat); |
| 1349 | /* TODO */ | ||
| 1350 | // if (lockstat & 1) | ||
| 1351 | // CorrectSysClockDeviation(s); | ||
| 1352 | 1353 | ||
| 1353 | *status = 0; | 1354 | *status = 0; |
| 1354 | if (lockstat & 2) { | 1355 | if (lockstat & 2) { |
| @@ -1356,9 +1357,8 @@ static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status) | |||
| 1356 | ConfigureMPEGOutput(s, 1); | 1357 | ConfigureMPEGOutput(s, 1); |
| 1357 | *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI; | 1358 | *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI; |
| 1358 | } | 1359 | } |
| 1359 | if (lockstat & 4) { | 1360 | if (lockstat & 4) |
| 1360 | *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; | 1361 | *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; |
| 1361 | } | ||
| 1362 | 1362 | ||
| 1363 | return 0; | 1363 | return 0; |
| 1364 | } | 1364 | } |
| @@ -1366,16 +1366,18 @@ static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status) | |||
| 1366 | static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber) | 1366 | static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber) |
| 1367 | { | 1367 | { |
| 1368 | *ber = 0; | 1368 | *ber = 0; |
| 1369 | |||
| 1369 | return 0; | 1370 | return 0; |
| 1370 | } | 1371 | } |
| 1371 | 1372 | ||
| 1372 | static int drx397x_read_snr(struct dvb_frontend *fe, u16 * snr) | 1373 | static int drx397x_read_snr(struct dvb_frontend *fe, u16 *snr) |
| 1373 | { | 1374 | { |
| 1374 | *snr = 0; | 1375 | *snr = 0; |
| 1376 | |||
| 1375 | return 0; | 1377 | return 0; |
| 1376 | } | 1378 | } |
| 1377 | 1379 | ||
| 1378 | static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | 1380 | static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 *strength) |
| 1379 | { | 1381 | { |
| 1380 | struct drx397xD_state *s = fe->demodulator_priv; | 1382 | struct drx397xD_state *s = fe->demodulator_priv; |
| 1381 | int rc; | 1383 | int rc; |
| @@ -1401,6 +1403,7 @@ static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength) | |||
| 1401 | * The following does the same but with less rounding errors: | 1403 | * The following does the same but with less rounding errors: |
| 1402 | */ | 1404 | */ |
| 1403 | *strength = ~(7720 + (rc * 30744 >> 10)); | 1405 | *strength = ~(7720 + (rc * 30744 >> 10)); |
| 1406 | |||
| 1404 | return 0; | 1407 | return 0; |
| 1405 | } | 1408 | } |
| 1406 | 1409 | ||
| @@ -1408,6 +1411,7 @@ static int drx397x_read_ucblocks(struct dvb_frontend *fe, | |||
| 1408 | unsigned int *ucblocks) | 1411 | unsigned int *ucblocks) |
| 1409 | { | 1412 | { |
| 1410 | *ucblocks = 0; | 1413 | *ucblocks = 0; |
| 1414 | |||
| 1411 | return 0; | 1415 | return 0; |
| 1412 | } | 1416 | } |
| 1413 | 1417 | ||
| @@ -1436,22 +1440,22 @@ static struct dvb_frontend_ops drx397x_ops = { | |||
| 1436 | .frequency_max = 855250000, | 1440 | .frequency_max = 855250000, |
| 1437 | .frequency_stepsize = 166667, | 1441 | .frequency_stepsize = 166667, |
| 1438 | .frequency_tolerance = 0, | 1442 | .frequency_tolerance = 0, |
| 1439 | .caps = /* 0x0C01B2EAE */ | 1443 | .caps = /* 0x0C01B2EAE */ |
| 1440 | FE_CAN_FEC_1_2 | // = 0x2, | 1444 | FE_CAN_FEC_1_2 | /* = 0x2, */ |
| 1441 | FE_CAN_FEC_2_3 | // = 0x4, | 1445 | FE_CAN_FEC_2_3 | /* = 0x4, */ |
| 1442 | FE_CAN_FEC_3_4 | // = 0x8, | 1446 | FE_CAN_FEC_3_4 | /* = 0x8, */ |
| 1443 | FE_CAN_FEC_5_6 | // = 0x20, | 1447 | FE_CAN_FEC_5_6 | /* = 0x20, */ |
| 1444 | FE_CAN_FEC_7_8 | // = 0x80, | 1448 | FE_CAN_FEC_7_8 | /* = 0x80, */ |
| 1445 | FE_CAN_FEC_AUTO | // = 0x200, | 1449 | FE_CAN_FEC_AUTO | /* = 0x200, */ |
| 1446 | FE_CAN_QPSK | // = 0x400, | 1450 | FE_CAN_QPSK | /* = 0x400, */ |
| 1447 | FE_CAN_QAM_16 | // = 0x800, | 1451 | FE_CAN_QAM_16 | /* = 0x800, */ |
| 1448 | FE_CAN_QAM_64 | // = 0x2000, | 1452 | FE_CAN_QAM_64 | /* = 0x2000, */ |
| 1449 | FE_CAN_QAM_AUTO | // = 0x10000, | 1453 | FE_CAN_QAM_AUTO | /* = 0x10000, */ |
| 1450 | FE_CAN_TRANSMISSION_MODE_AUTO | // = 0x20000, | 1454 | FE_CAN_TRANSMISSION_MODE_AUTO | /* = 0x20000, */ |
| 1451 | FE_CAN_GUARD_INTERVAL_AUTO | // = 0x80000, | 1455 | FE_CAN_GUARD_INTERVAL_AUTO | /* = 0x80000, */ |
| 1452 | FE_CAN_HIERARCHY_AUTO | // = 0x100000, | 1456 | FE_CAN_HIERARCHY_AUTO | /* = 0x100000, */ |
| 1453 | FE_CAN_RECOVER | // = 0x40000000, | 1457 | FE_CAN_RECOVER | /* = 0x40000000, */ |
| 1454 | FE_CAN_MUTE_TS // = 0x80000000 | 1458 | FE_CAN_MUTE_TS /* = 0x80000000 */ |
| 1455 | }, | 1459 | }, |
| 1456 | 1460 | ||
| 1457 | .release = drx397x_release, | 1461 | .release = drx397x_release, |
| @@ -1472,33 +1476,35 @@ static struct dvb_frontend_ops drx397x_ops = { | |||
| 1472 | struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config, | 1476 | struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config, |
| 1473 | struct i2c_adapter *i2c) | 1477 | struct i2c_adapter *i2c) |
| 1474 | { | 1478 | { |
| 1475 | struct drx397xD_state *s = NULL; | 1479 | struct drx397xD_state *state; |
| 1476 | 1480 | ||
| 1477 | /* allocate memory for the internal state */ | 1481 | /* allocate memory for the internal state */ |
| 1478 | s = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL); | 1482 | state = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL); |
| 1479 | if (s == NULL) | 1483 | if (!state) |
| 1480 | goto error; | 1484 | goto error; |
| 1481 | 1485 | ||
| 1482 | /* setup the state */ | 1486 | /* setup the state */ |
| 1483 | s->i2c = i2c; | 1487 | state->i2c = i2c; |
| 1484 | memcpy(&s->config, config, sizeof(struct drx397xD_config)); | 1488 | memcpy(&state->config, config, sizeof(struct drx397xD_config)); |
| 1485 | 1489 | ||
| 1486 | /* check if the demod is there */ | 1490 | /* check if the demod is there */ |
| 1487 | if (RD16(s, 0x2410019) < 0) | 1491 | if (RD16(state, 0x2410019) < 0) |
| 1488 | goto error; | 1492 | goto error; |
| 1489 | 1493 | ||
| 1490 | /* create dvb_frontend */ | 1494 | /* create dvb_frontend */ |
| 1491 | memcpy(&s->frontend.ops, &drx397x_ops, sizeof(struct dvb_frontend_ops)); | 1495 | memcpy(&state->frontend.ops, &drx397x_ops, |
| 1492 | s->frontend.demodulator_priv = s; | 1496 | sizeof(struct dvb_frontend_ops)); |
| 1497 | state->frontend.demodulator_priv = state; | ||
| 1498 | |||
| 1499 | return &state->frontend; | ||
| 1500 | error: | ||
| 1501 | kfree(state); | ||
| 1493 | 1502 | ||
| 1494 | return &s->frontend; | ||
| 1495 | error: | ||
| 1496 | kfree(s); | ||
| 1497 | return NULL; | 1503 | return NULL; |
| 1498 | } | 1504 | } |
| 1505 | EXPORT_SYMBOL(drx397xD_attach); | ||
| 1499 | 1506 | ||
| 1500 | MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend"); | 1507 | MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend"); |
| 1501 | MODULE_AUTHOR("Henk Vergonet"); | 1508 | MODULE_AUTHOR("Henk Vergonet"); |
| 1502 | MODULE_LICENSE("GPL"); | 1509 | MODULE_LICENSE("GPL"); |
| 1503 | 1510 | ||
| 1504 | EXPORT_SYMBOL(drx397xD_attach); | ||
diff --git a/drivers/media/dvb/frontends/drx397xD.h b/drivers/media/dvb/frontends/drx397xD.h index ddc7a07971b7..ba05d17290c6 100644 --- a/drivers/media/dvb/frontends/drx397xD.h +++ b/drivers/media/dvb/frontends/drx397xD.h | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | #define DRX_F_OFFSET 36000000 | 28 | #define DRX_F_OFFSET 36000000 |
| 29 | 29 | ||
| 30 | #define I2C_ADR_C0(x) \ | 30 | #define I2C_ADR_C0(x) \ |
| 31 | ( (u32)cpu_to_le32( \ | 31 | ( cpu_to_le32( \ |
| 32 | (u32)( \ | 32 | (u32)( \ |
| 33 | (((u32)(x) & (u32)0x000000ffUL) ) | \ | 33 | (((u32)(x) & (u32)0x000000ffUL) ) | \ |
| 34 | (((u32)(x) & (u32)0x0000ff00UL) << 16) | \ | 34 | (((u32)(x) & (u32)0x0000ff00UL) << 16) | \ |
| @@ -38,7 +38,7 @@ | |||
| 38 | ) | 38 | ) |
| 39 | 39 | ||
| 40 | #define I2C_ADR_E0(x) \ | 40 | #define I2C_ADR_E0(x) \ |
| 41 | ( (u32)cpu_to_le32( \ | 41 | ( cpu_to_le32( \ |
| 42 | (u32)( \ | 42 | (u32)( \ |
| 43 | (((u32)(x) & (u32)0x000000ffUL) ) | \ | 43 | (((u32)(x) & (u32)0x000000ffUL) ) | \ |
| 44 | (((u32)(x) & (u32)0x0000ff00UL) << 16) | \ | 44 | (((u32)(x) & (u32)0x0000ff00UL) << 16) | \ |
| @@ -122,7 +122,7 @@ extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config | |||
| 122 | static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config, | 122 | static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config, |
| 123 | struct i2c_adapter *i2c) | 123 | struct i2c_adapter *i2c) |
| 124 | { | 124 | { |
| 125 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); | 125 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
| 126 | return NULL; | 126 | return NULL; |
| 127 | } | 127 | } |
| 128 | #endif /* CONFIG_DVB_DRX397XD */ | 128 | #endif /* CONFIG_DVB_DRX397XD */ |
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c index fed09dfb2b7c..db8a937cc630 100644 --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c | |||
| @@ -75,9 +75,10 @@ static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_fronten | |||
| 75 | 75 | ||
| 76 | static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | 76 | static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) |
| 77 | { | 77 | { |
| 78 | if (fe->ops->tuner_ops->set_params) { | 78 | if (fe->ops.tuner_ops.set_params) { |
| 79 | fe->ops->tuner_ops->set_params(fe, p); | 79 | fe->ops.tuner_ops.set_params(fe, p); |
| 80 | if (fe->ops->i2c_gate_ctrl) fe->ops->i2c_gate_ctrl(fe, 0); | 80 | if (fe->ops.i2c_gate_ctrl) |
| 81 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
| 81 | } | 82 | } |
| 82 | 83 | ||
| 83 | return 0; | 84 | return 0; |
| @@ -131,7 +132,7 @@ error: | |||
| 131 | 132 | ||
| 132 | static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops; | 133 | static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops; |
| 133 | 134 | ||
| 134 | struct dvb_frontend* dvb_dummy_fe_qpsk_attach() | 135 | struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void) |
| 135 | { | 136 | { |
| 136 | struct dvb_dummy_fe_state* state = NULL; | 137 | struct dvb_dummy_fe_state* state = NULL; |
| 137 | 138 | ||
| @@ -151,7 +152,7 @@ error: | |||
| 151 | 152 | ||
| 152 | static struct dvb_frontend_ops dvb_dummy_fe_qam_ops; | 153 | static struct dvb_frontend_ops dvb_dummy_fe_qam_ops; |
| 153 | 154 | ||
| 154 | struct dvb_frontend* dvb_dummy_fe_qam_attach() | 155 | struct dvb_frontend *dvb_dummy_fe_qam_attach(void) |
| 155 | { | 156 | { |
| 156 | struct dvb_dummy_fe_state* state = NULL; | 157 | struct dvb_dummy_fe_state* state = NULL; |
| 157 | 158 | ||
diff --git a/drivers/media/dvb/frontends/eds1547.h b/drivers/media/dvb/frontends/eds1547.h new file mode 100644 index 000000000000..fa79b7c83dd2 --- /dev/null +++ b/drivers/media/dvb/frontends/eds1547.h | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | /* eds1547.h Earda EDS-1547 tuner support | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License as published by the | ||
| 7 | * Free Software Foundation, version 2. | ||
| 8 | * | ||
| 9 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef EDS1547 | ||
| 13 | #define EDS1547 | ||
| 14 | |||
| 15 | static u8 stv0288_earda_inittab[] = { | ||
| 16 | 0x01, 0x57, | ||
| 17 | 0x02, 0x20, | ||
| 18 | 0x03, 0x8e, | ||
| 19 | 0x04, 0x8e, | ||
| 20 | 0x05, 0x12, | ||
| 21 | 0x06, 0x00, | ||
| 22 | 0x07, 0x00, | ||
| 23 | 0x09, 0x00, | ||
| 24 | 0x0a, 0x04, | ||
| 25 | 0x0b, 0x00, | ||
| 26 | 0x0c, 0x00, | ||
| 27 | 0x0d, 0x00, | ||
| 28 | 0x0e, 0xd4, | ||
| 29 | 0x0f, 0x30, | ||
| 30 | 0x11, 0x44, | ||
| 31 | 0x12, 0x03, | ||
| 32 | 0x13, 0x48, | ||
| 33 | 0x14, 0x84, | ||
| 34 | 0x15, 0x45, | ||
| 35 | 0x16, 0xb7, | ||
| 36 | 0x17, 0x9c, | ||
| 37 | 0x18, 0x00, | ||
| 38 | 0x19, 0xa6, | ||
| 39 | 0x1a, 0x88, | ||
| 40 | 0x1b, 0x8f, | ||
| 41 | 0x1c, 0xf0, | ||
| 42 | 0x20, 0x0b, | ||
| 43 | 0x21, 0x54, | ||
| 44 | 0x22, 0x00, | ||
| 45 | 0x23, 0x00, | ||
| 46 | 0x2b, 0xff, | ||
| 47 | 0x2c, 0xf7, | ||
| 48 | 0x30, 0x00, | ||
| 49 | 0x31, 0x1e, | ||
| 50 | 0x32, 0x14, | ||
| 51 | 0x33, 0x0f, | ||
| 52 | 0x34, 0x09, | ||
| 53 | 0x35, 0x0c, | ||
| 54 | 0x36, 0x05, | ||
| 55 | 0x37, 0x2f, | ||
| 56 | 0x38, 0x16, | ||
| 57 | 0x39, 0xbd, | ||
| 58 | 0x3a, 0x00, | ||
| 59 | 0x3b, 0x13, | ||
| 60 | 0x3c, 0x11, | ||
| 61 | 0x3d, 0x30, | ||
| 62 | 0x40, 0x63, | ||
| 63 | 0x41, 0x04, | ||
| 64 | 0x42, 0x60, | ||
| 65 | 0x43, 0x00, | ||
| 66 | 0x44, 0x00, | ||
| 67 | 0x45, 0x00, | ||
| 68 | 0x46, 0x00, | ||
| 69 | 0x47, 0x00, | ||
| 70 | 0x4a, 0x00, | ||
| 71 | 0x50, 0x10, | ||
| 72 | 0x51, 0x36, | ||
| 73 | 0x52, 0x09, | ||
| 74 | 0x53, 0x94, | ||
| 75 | 0x54, 0x62, | ||
| 76 | 0x55, 0x29, | ||
| 77 | 0x56, 0x64, | ||
| 78 | 0x57, 0x2b, | ||
| 79 | 0x58, 0x54, | ||
| 80 | 0x59, 0x86, | ||
| 81 | 0x5a, 0x00, | ||
| 82 | 0x5b, 0x9b, | ||
| 83 | 0x5c, 0x08, | ||
| 84 | 0x5d, 0x7f, | ||
| 85 | 0x5e, 0x00, | ||
| 86 | 0x5f, 0xff, | ||
| 87 | 0x70, 0x00, | ||
| 88 | 0x71, 0x00, | ||
| 89 | 0x72, 0x00, | ||
| 90 | 0x74, 0x00, | ||
| 91 | 0x75, 0x00, | ||
| 92 | 0x76, 0x00, | ||
| 93 | 0x81, 0x00, | ||
| 94 | 0x82, 0x3f, | ||
| 95 | 0x83, 0x3f, | ||
| 96 | 0x84, 0x00, | ||
| 97 | 0x85, 0x00, | ||
| 98 | 0x88, 0x00, | ||
| 99 | 0x89, 0x00, | ||
| 100 | 0x8a, 0x00, | ||
| 101 | 0x8b, 0x00, | ||
| 102 | 0x8c, 0x00, | ||
| 103 | 0x90, 0x00, | ||
| 104 | 0x91, 0x00, | ||
| 105 | 0x92, 0x00, | ||
| 106 | 0x93, 0x00, | ||
| 107 | 0x94, 0x1c, | ||
| 108 | 0x97, 0x00, | ||
| 109 | 0xa0, 0x48, | ||
| 110 | 0xa1, 0x00, | ||
| 111 | 0xb0, 0xb8, | ||
| 112 | 0xb1, 0x3a, | ||
| 113 | 0xb2, 0x10, | ||
| 114 | 0xb3, 0x82, | ||
| 115 | 0xb4, 0x80, | ||
| 116 | 0xb5, 0x82, | ||
| 117 | 0xb6, 0x82, | ||
| 118 | 0xb7, 0x82, | ||
| 119 | 0xb8, 0x20, | ||
| 120 | 0xb9, 0x00, | ||
| 121 | 0xf0, 0x00, | ||
| 122 | 0xf1, 0x00, | ||
| 123 | 0xf2, 0xc0, | ||
| 124 | 0xff,0xff, | ||
| 125 | }; | ||
| 126 | |||
| 127 | static struct stv0288_config earda_config = { | ||
| 128 | .demod_address = 0x68, | ||
| 129 | .min_delay_ms = 100, | ||
| 130 | .inittab = stv0288_earda_inittab, | ||
| 131 | }; | ||
| 132 | |||
| 133 | #endif | ||
diff --git a/drivers/media/dvb/frontends/lgs8gl5.c b/drivers/media/dvb/frontends/lgs8gl5.c new file mode 100644 index 000000000000..855852fddf22 --- /dev/null +++ b/drivers/media/dvb/frontends/lgs8gl5.c | |||
| @@ -0,0 +1,454 @@ | |||
| 1 | /* | ||
| 2 | Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver | ||
| 3 | |||
| 4 | Copyright (C) 2008 Sirius International (Hong Kong) Limited | ||
| 5 | Timothy Lee <timothy.lee@siriushk.com> | ||
| 6 | |||
| 7 | This program is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 2 of the License, or | ||
| 10 | (at your option) any later version. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; if not, write to the Free Software | ||
| 19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 20 | |||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/string.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include "dvb_frontend.h" | ||
| 29 | #include "lgs8gl5.h" | ||
| 30 | |||
| 31 | |||
| 32 | #define REG_RESET 0x02 | ||
| 33 | #define REG_RESET_OFF 0x01 | ||
| 34 | #define REG_03 0x03 | ||
| 35 | #define REG_04 0x04 | ||
| 36 | #define REG_07 0x07 | ||
| 37 | #define REG_09 0x09 | ||
| 38 | #define REG_0A 0x0a | ||
| 39 | #define REG_0B 0x0b | ||
| 40 | #define REG_0C 0x0c | ||
| 41 | #define REG_37 0x37 | ||
| 42 | #define REG_STRENGTH 0x4b | ||
| 43 | #define REG_STRENGTH_MASK 0x7f | ||
| 44 | #define REG_STRENGTH_CARRIER 0x80 | ||
| 45 | #define REG_INVERSION 0x7c | ||
| 46 | #define REG_INVERSION_ON 0x80 | ||
| 47 | #define REG_7D 0x7d | ||
| 48 | #define REG_7E 0x7e | ||
| 49 | #define REG_A2 0xa2 | ||
| 50 | #define REG_STATUS 0xa4 | ||
| 51 | #define REG_STATUS_SYNC 0x04 | ||
| 52 | #define REG_STATUS_LOCK 0x01 | ||
| 53 | |||
| 54 | |||
| 55 | struct lgs8gl5_state { | ||
| 56 | struct i2c_adapter *i2c; | ||
| 57 | const struct lgs8gl5_config *config; | ||
| 58 | struct dvb_frontend frontend; | ||
| 59 | }; | ||
| 60 | |||
| 61 | |||
| 62 | static int debug; | ||
| 63 | #define dprintk(args...) \ | ||
| 64 | do { \ | ||
| 65 | if (debug) \ | ||
| 66 | printk(KERN_DEBUG "lgs8gl5: " args); \ | ||
| 67 | } while (0) | ||
| 68 | |||
| 69 | |||
| 70 | /* Writes into demod's register */ | ||
| 71 | static int | ||
| 72 | lgs8gl5_write_reg(struct lgs8gl5_state *state, u8 reg, u8 data) | ||
| 73 | { | ||
| 74 | int ret; | ||
| 75 | u8 buf[] = {reg, data}; | ||
| 76 | struct i2c_msg msg = { | ||
| 77 | .addr = state->config->demod_address, | ||
| 78 | .flags = 0, | ||
| 79 | .buf = buf, | ||
| 80 | .len = 2 | ||
| 81 | }; | ||
| 82 | |||
| 83 | ret = i2c_transfer(state->i2c, &msg, 1); | ||
| 84 | if (ret != 1) | ||
| 85 | dprintk("%s: error (reg=0x%02x, val=0x%02x, ret=%i)\n", | ||
| 86 | __func__, reg, data, ret); | ||
| 87 | return (ret != 1) ? -1 : 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | |||
| 91 | /* Reads from demod's register */ | ||
| 92 | static int | ||
| 93 | lgs8gl5_read_reg(struct lgs8gl5_state *state, u8 reg) | ||
| 94 | { | ||
| 95 | int ret; | ||
| 96 | u8 b0[] = {reg}; | ||
| 97 | u8 b1[] = {0}; | ||
| 98 | struct i2c_msg msg[2] = { | ||
| 99 | { | ||
| 100 | .addr = state->config->demod_address, | ||
| 101 | .flags = 0, | ||
| 102 | .buf = b0, | ||
| 103 | .len = 1 | ||
| 104 | }, | ||
| 105 | { | ||
| 106 | .addr = state->config->demod_address, | ||
| 107 | .flags = I2C_M_RD, | ||
| 108 | .buf = b1, | ||
| 109 | .len = 1 | ||
| 110 | } | ||
| 111 | }; | ||
| 112 | |||
| 113 | ret = i2c_transfer(state->i2c, msg, 2); | ||
| 114 | if (ret != 2) | ||
| 115 | return -EIO; | ||
| 116 | |||
| 117 | return b1[0]; | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 121 | static int | ||
| 122 | lgs8gl5_update_reg(struct lgs8gl5_state *state, u8 reg, u8 data) | ||
| 123 | { | ||
| 124 | lgs8gl5_read_reg(state, reg); | ||
| 125 | lgs8gl5_write_reg(state, reg, data); | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | |||
| 130 | /* Writes into alternate device's register */ | ||
| 131 | /* TODO: Find out what that device is for! */ | ||
| 132 | static int | ||
| 133 | lgs8gl5_update_alt_reg(struct lgs8gl5_state *state, u8 reg, u8 data) | ||
| 134 | { | ||
| 135 | int ret; | ||
| 136 | u8 b0[] = {reg}; | ||
| 137 | u8 b1[] = {0}; | ||
| 138 | u8 b2[] = {reg, data}; | ||
| 139 | struct i2c_msg msg[3] = { | ||
| 140 | { | ||
| 141 | .addr = state->config->demod_address + 2, | ||
| 142 | .flags = 0, | ||
| 143 | .buf = b0, | ||
| 144 | .len = 1 | ||
| 145 | }, | ||
| 146 | { | ||
| 147 | .addr = state->config->demod_address + 2, | ||
| 148 | .flags = I2C_M_RD, | ||
| 149 | .buf = b1, | ||
| 150 | .len = 1 | ||
| 151 | }, | ||
| 152 | { | ||
| 153 | .addr = state->config->demod_address + 2, | ||
| 154 | .flags = 0, | ||
| 155 | .buf = b2, | ||
| 156 | .len = 2 | ||
| 157 | }, | ||
| 158 | }; | ||
| 159 | |||
| 160 | ret = i2c_transfer(state->i2c, msg, 3); | ||
| 161 | return (ret != 3) ? -1 : 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | |||
| 165 | static void | ||
| 166 | lgs8gl5_soft_reset(struct lgs8gl5_state *state) | ||
| 167 | { | ||
| 168 | u8 val; | ||
| 169 | |||
| 170 | dprintk("%s\n", __func__); | ||
| 171 | |||
| 172 | val = lgs8gl5_read_reg(state, REG_RESET); | ||
| 173 | lgs8gl5_write_reg(state, REG_RESET, val & ~REG_RESET_OFF); | ||
| 174 | lgs8gl5_write_reg(state, REG_RESET, val | REG_RESET_OFF); | ||
| 175 | msleep(5); | ||
| 176 | } | ||
| 177 | |||
| 178 | |||
| 179 | /* Starts demodulation */ | ||
| 180 | static void | ||
| 181 | lgs8gl5_start_demod(struct lgs8gl5_state *state) | ||
| 182 | { | ||
| 183 | u8 val; | ||
| 184 | int n; | ||
| 185 | |||
| 186 | dprintk("%s\n", __func__); | ||
| 187 | |||
| 188 | lgs8gl5_update_alt_reg(state, 0xc2, 0x28); | ||
| 189 | lgs8gl5_soft_reset(state); | ||
| 190 | lgs8gl5_update_reg(state, REG_07, 0x10); | ||
| 191 | lgs8gl5_update_reg(state, REG_07, 0x10); | ||
| 192 | lgs8gl5_write_reg(state, REG_09, 0x0e); | ||
| 193 | lgs8gl5_write_reg(state, REG_0A, 0xe5); | ||
| 194 | lgs8gl5_write_reg(state, REG_0B, 0x35); | ||
| 195 | lgs8gl5_write_reg(state, REG_0C, 0x30); | ||
| 196 | |||
| 197 | lgs8gl5_update_reg(state, REG_03, 0x00); | ||
| 198 | lgs8gl5_update_reg(state, REG_7E, 0x01); | ||
| 199 | lgs8gl5_update_alt_reg(state, 0xc5, 0x00); | ||
| 200 | lgs8gl5_update_reg(state, REG_04, 0x02); | ||
| 201 | lgs8gl5_update_reg(state, REG_37, 0x01); | ||
| 202 | lgs8gl5_soft_reset(state); | ||
| 203 | |||
| 204 | /* Wait for carrier */ | ||
| 205 | for (n = 0; n < 10; n++) { | ||
| 206 | val = lgs8gl5_read_reg(state, REG_STRENGTH); | ||
| 207 | dprintk("Wait for carrier[%d] 0x%02X\n", n, val); | ||
| 208 | if (val & REG_STRENGTH_CARRIER) | ||
| 209 | break; | ||
| 210 | msleep(4); | ||
| 211 | } | ||
| 212 | if (!(val & REG_STRENGTH_CARRIER)) | ||
| 213 | return; | ||
| 214 | |||
| 215 | /* Wait for lock */ | ||
| 216 | for (n = 0; n < 20; n++) { | ||
| 217 | val = lgs8gl5_read_reg(state, REG_STATUS); | ||
| 218 | dprintk("Wait for lock[%d] 0x%02X\n", n, val); | ||
| 219 | if (val & REG_STATUS_LOCK) | ||
| 220 | break; | ||
| 221 | msleep(12); | ||
| 222 | } | ||
| 223 | if (!(val & REG_STATUS_LOCK)) | ||
| 224 | return; | ||
| 225 | |||
| 226 | lgs8gl5_write_reg(state, REG_7D, lgs8gl5_read_reg(state, REG_A2)); | ||
| 227 | lgs8gl5_soft_reset(state); | ||
| 228 | } | ||
| 229 | |||
| 230 | |||
| 231 | static int | ||
| 232 | lgs8gl5_init(struct dvb_frontend *fe) | ||
| 233 | { | ||
| 234 | struct lgs8gl5_state *state = fe->demodulator_priv; | ||
| 235 | |||
| 236 | dprintk("%s\n", __func__); | ||
| 237 | |||
| 238 | lgs8gl5_update_alt_reg(state, 0xc2, 0x28); | ||
| 239 | lgs8gl5_soft_reset(state); | ||
| 240 | lgs8gl5_update_reg(state, REG_07, 0x10); | ||
| 241 | lgs8gl5_update_reg(state, REG_07, 0x10); | ||
| 242 | lgs8gl5_write_reg(state, REG_09, 0x0e); | ||
| 243 | lgs8gl5_write_reg(state, REG_0A, 0xe5); | ||
| 244 | lgs8gl5_write_reg(state, REG_0B, 0x35); | ||
| 245 | lgs8gl5_write_reg(state, REG_0C, 0x30); | ||
| 246 | |||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | |||
| 250 | |||
| 251 | static int | ||
| 252 | lgs8gl5_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
| 253 | { | ||
| 254 | struct lgs8gl5_state *state = fe->demodulator_priv; | ||
| 255 | u8 level = lgs8gl5_read_reg(state, REG_STRENGTH); | ||
| 256 | u8 flags = lgs8gl5_read_reg(state, REG_STATUS); | ||
| 257 | |||
| 258 | *status = 0; | ||
| 259 | |||
| 260 | if ((level & REG_STRENGTH_MASK) > 0) | ||
| 261 | *status |= FE_HAS_SIGNAL; | ||
| 262 | if (level & REG_STRENGTH_CARRIER) | ||
| 263 | *status |= FE_HAS_CARRIER; | ||
| 264 | if (flags & REG_STATUS_SYNC) | ||
| 265 | *status |= FE_HAS_SYNC; | ||
| 266 | if (flags & REG_STATUS_LOCK) | ||
| 267 | *status |= FE_HAS_LOCK; | ||
| 268 | |||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | |||
| 272 | |||
| 273 | static int | ||
| 274 | lgs8gl5_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
| 275 | { | ||
| 276 | *ber = 0; | ||
| 277 | |||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | |||
| 282 | static int | ||
| 283 | lgs8gl5_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) | ||
| 284 | { | ||
| 285 | struct lgs8gl5_state *state = fe->demodulator_priv; | ||
| 286 | u8 level = lgs8gl5_read_reg(state, REG_STRENGTH); | ||
| 287 | *signal_strength = (level & REG_STRENGTH_MASK) << 8; | ||
| 288 | |||
| 289 | return 0; | ||
| 290 | } | ||
| 291 | |||
| 292 | |||
| 293 | static int | ||
| 294 | lgs8gl5_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
| 295 | { | ||
| 296 | struct lgs8gl5_state *state = fe->demodulator_priv; | ||
| 297 | u8 level = lgs8gl5_read_reg(state, REG_STRENGTH); | ||
| 298 | *snr = (level & REG_STRENGTH_MASK) << 8; | ||
| 299 | |||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | |||
| 304 | static int | ||
| 305 | lgs8gl5_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
| 306 | { | ||
| 307 | *ucblocks = 0; | ||
| 308 | |||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | |||
| 313 | static int | ||
| 314 | lgs8gl5_set_frontend(struct dvb_frontend *fe, | ||
| 315 | struct dvb_frontend_parameters *p) | ||
| 316 | { | ||
| 317 | struct lgs8gl5_state *state = fe->demodulator_priv; | ||
| 318 | |||
| 319 | dprintk("%s\n", __func__); | ||
| 320 | |||
| 321 | if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ) | ||
| 322 | return -EINVAL; | ||
| 323 | |||
| 324 | if (fe->ops.tuner_ops.set_params) { | ||
| 325 | fe->ops.tuner_ops.set_params(fe, p); | ||
| 326 | if (fe->ops.i2c_gate_ctrl) | ||
| 327 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
| 328 | } | ||
| 329 | |||
| 330 | /* lgs8gl5_set_inversion(state, p->inversion); */ | ||
| 331 | |||
| 332 | lgs8gl5_start_demod(state); | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | |||
| 338 | static int | ||
| 339 | lgs8gl5_get_frontend(struct dvb_frontend *fe, | ||
| 340 | struct dvb_frontend_parameters *p) | ||
| 341 | { | ||
| 342 | struct lgs8gl5_state *state = fe->demodulator_priv; | ||
| 343 | u8 inv = lgs8gl5_read_reg(state, REG_INVERSION); | ||
| 344 | struct dvb_ofdm_parameters *o = &p->u.ofdm; | ||
| 345 | |||
| 346 | p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF; | ||
| 347 | |||
| 348 | o->code_rate_HP = FEC_1_2; | ||
| 349 | o->code_rate_LP = FEC_7_8; | ||
| 350 | o->guard_interval = GUARD_INTERVAL_1_32; | ||
| 351 | o->transmission_mode = TRANSMISSION_MODE_2K; | ||
| 352 | o->constellation = QAM_64; | ||
| 353 | o->hierarchy_information = HIERARCHY_NONE; | ||
| 354 | o->bandwidth = BANDWIDTH_8_MHZ; | ||
| 355 | |||
| 356 | return 0; | ||
| 357 | } | ||
| 358 | |||
| 359 | |||
| 360 | static int | ||
| 361 | lgs8gl5_get_tune_settings(struct dvb_frontend *fe, | ||
| 362 | struct dvb_frontend_tune_settings *fesettings) | ||
| 363 | { | ||
| 364 | fesettings->min_delay_ms = 240; | ||
| 365 | fesettings->step_size = 0; | ||
| 366 | fesettings->max_drift = 0; | ||
| 367 | return 0; | ||
| 368 | } | ||
| 369 | |||
| 370 | |||
| 371 | static void | ||
| 372 | lgs8gl5_release(struct dvb_frontend *fe) | ||
| 373 | { | ||
| 374 | struct lgs8gl5_state *state = fe->demodulator_priv; | ||
| 375 | kfree(state); | ||
| 376 | } | ||
| 377 | |||
| 378 | |||
| 379 | static struct dvb_frontend_ops lgs8gl5_ops; | ||
| 380 | |||
| 381 | |||
| 382 | struct dvb_frontend* | ||
| 383 | lgs8gl5_attach(const struct lgs8gl5_config *config, struct i2c_adapter *i2c) | ||
| 384 | { | ||
| 385 | struct lgs8gl5_state *state = NULL; | ||
| 386 | |||
| 387 | dprintk("%s\n", __func__); | ||
| 388 | |||
| 389 | /* Allocate memory for the internal state */ | ||
| 390 | state = kmalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL); | ||
| 391 | if (state == NULL) | ||
| 392 | goto error; | ||
| 393 | |||
| 394 | /* Setup the state */ | ||
| 395 | state->config = config; | ||
| 396 | state->i2c = i2c; | ||
| 397 | |||
| 398 | /* Check if the demod is there */ | ||
| 399 | if (lgs8gl5_read_reg(state, REG_RESET) < 0) | ||
| 400 | goto error; | ||
| 401 | |||
| 402 | /* Create dvb_frontend */ | ||
| 403 | memcpy(&state->frontend.ops, &lgs8gl5_ops, | ||
| 404 | sizeof(struct dvb_frontend_ops)); | ||
| 405 | state->frontend.demodulator_priv = state; | ||
| 406 | return &state->frontend; | ||
| 407 | |||
| 408 | error: | ||
| 409 | kfree(state); | ||
| 410 | return NULL; | ||
| 411 | } | ||
| 412 | EXPORT_SYMBOL(lgs8gl5_attach); | ||
| 413 | |||
| 414 | |||
| 415 | static struct dvb_frontend_ops lgs8gl5_ops = { | ||
| 416 | .info = { | ||
| 417 | .name = "Legend Silicon LGS-8GL5 DMB-TH", | ||
| 418 | .type = FE_OFDM, | ||
| 419 | .frequency_min = 474000000, | ||
| 420 | .frequency_max = 858000000, | ||
| 421 | .frequency_stepsize = 10000, | ||
| 422 | .frequency_tolerance = 0, | ||
| 423 | .caps = FE_CAN_FEC_AUTO | | ||
| 424 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 | | ||
| 425 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
| 426 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
| 427 | FE_CAN_BANDWIDTH_AUTO | | ||
| 428 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
| 429 | FE_CAN_HIERARCHY_AUTO | | ||
| 430 | FE_CAN_RECOVER | ||
| 431 | }, | ||
| 432 | |||
| 433 | .release = lgs8gl5_release, | ||
| 434 | |||
| 435 | .init = lgs8gl5_init, | ||
| 436 | |||
| 437 | .set_frontend = lgs8gl5_set_frontend, | ||
| 438 | .get_frontend = lgs8gl5_get_frontend, | ||
| 439 | .get_tune_settings = lgs8gl5_get_tune_settings, | ||
| 440 | |||
| 441 | .read_status = lgs8gl5_read_status, | ||
| 442 | .read_ber = lgs8gl5_read_ber, | ||
| 443 | .read_signal_strength = lgs8gl5_read_signal_strength, | ||
| 444 | .read_snr = lgs8gl5_read_snr, | ||
| 445 | .read_ucblocks = lgs8gl5_read_ucblocks, | ||
| 446 | }; | ||
| 447 | |||
| 448 | |||
| 449 | module_param(debug, int, 0644); | ||
| 450 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
| 451 | |||
| 452 | MODULE_DESCRIPTION("Legend Silicon LGS-8GL5 DMB-TH Demodulator driver"); | ||
| 453 | MODULE_AUTHOR("Timothy Lee"); | ||
| 454 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/lgs8gl5.h b/drivers/media/dvb/frontends/lgs8gl5.h new file mode 100644 index 000000000000..d14176787a7d --- /dev/null +++ b/drivers/media/dvb/frontends/lgs8gl5.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | /* | ||
| 2 | Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver | ||
| 3 | |||
| 4 | Copyright (C) 2008 Sirius International (Hong Kong) Limited | ||
| 5 | Timothy Lee <timothy.lee@siriushk.com> | ||
| 6 | |||
| 7 | This program is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 2 of the License, or | ||
| 10 | (at your option) any later version. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; if not, write to the Free Software | ||
| 19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 20 | |||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef LGS8GL5_H | ||
| 24 | #define LGS8GL5_H | ||
| 25 | |||
| 26 | #include <linux/dvb/frontend.h> | ||
| 27 | |||
| 28 | struct lgs8gl5_config { | ||
| 29 | /* the demodulator's i2c address */ | ||
| 30 | u8 demod_address; | ||
| 31 | }; | ||
| 32 | |||
| 33 | #if defined(CONFIG_DVB_LGS8GL5) || \ | ||
| 34 | (defined(CONFIG_DVB_LGS8GL5_MODULE) && defined(MODULE)) | ||
| 35 | extern struct dvb_frontend *lgs8gl5_attach( | ||
| 36 | const struct lgs8gl5_config *config, struct i2c_adapter *i2c); | ||
| 37 | #else | ||
| 38 | static inline struct dvb_frontend *lgs8gl5_attach( | ||
| 39 | const struct lgs8gl5_config *config, struct i2c_adapter *i2c) { | ||
| 40 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 41 | return NULL; | ||
| 42 | } | ||
| 43 | #endif /* CONFIG_DVB_LGS8GL5 */ | ||
| 44 | |||
| 45 | #endif /* LGS8GL5_H */ | ||
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c index af298358e822..a8429ebfa8a2 100644 --- a/drivers/media/dvb/frontends/nxt200x.c +++ b/drivers/media/dvb/frontends/nxt200x.c | |||
| @@ -80,7 +80,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len | |||
| 80 | return 0; | 80 | return 0; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len) | 83 | static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len) |
| 84 | { | 84 | { |
| 85 | int err; | 85 | int err; |
| 86 | struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len }; | 86 | struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len }; |
| @@ -111,7 +111,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, | |||
| 111 | return 0; | 111 | return 0; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 len) | 114 | static int nxt200x_readbytes(struct nxt200x_state *state, u8 reg, u8 *buf, u8 len) |
| 115 | { | 115 | { |
| 116 | u8 reg2 [] = { reg }; | 116 | u8 reg2 [] = { reg }; |
| 117 | 117 | ||
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c index 6afe12aaca4e..16cf2fdd5d7d 100644 --- a/drivers/media/dvb/frontends/or51211.c +++ b/drivers/media/dvb/frontends/or51211.c | |||
| @@ -88,7 +88,7 @@ static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf, | |||
| 88 | return 0; | 88 | return 0; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | static u8 i2c_readbytes (struct or51211_state* state, u8 reg, u8* buf, int len) | 91 | static int i2c_readbytes(struct or51211_state *state, u8 reg, u8 *buf, int len) |
| 92 | { | 92 | { |
| 93 | int err; | 93 | int err; |
| 94 | struct i2c_msg msg; | 94 | struct i2c_msg msg; |
diff --git a/drivers/media/dvb/frontends/si21xx.c b/drivers/media/dvb/frontends/si21xx.c new file mode 100644 index 000000000000..3ddbe69c45ce --- /dev/null +++ b/drivers/media/dvb/frontends/si21xx.c | |||
| @@ -0,0 +1,974 @@ | |||
| 1 | /* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | #include <linux/version.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/string.h> | ||
| 16 | #include <linux/slab.h> | ||
| 17 | #include <linux/jiffies.h> | ||
| 18 | #include <asm/div64.h> | ||
| 19 | |||
| 20 | #include "dvb_frontend.h" | ||
| 21 | #include "si21xx.h" | ||
| 22 | |||
| 23 | #define REVISION_REG 0x00 | ||
| 24 | #define SYSTEM_MODE_REG 0x01 | ||
| 25 | #define TS_CTRL_REG_1 0x02 | ||
| 26 | #define TS_CTRL_REG_2 0x03 | ||
| 27 | #define PIN_CTRL_REG_1 0x04 | ||
| 28 | #define PIN_CTRL_REG_2 0x05 | ||
| 29 | #define LOCK_STATUS_REG_1 0x0f | ||
| 30 | #define LOCK_STATUS_REG_2 0x10 | ||
| 31 | #define ACQ_STATUS_REG 0x11 | ||
| 32 | #define ACQ_CTRL_REG_1 0x13 | ||
| 33 | #define ACQ_CTRL_REG_2 0x14 | ||
| 34 | #define PLL_DIVISOR_REG 0x15 | ||
| 35 | #define COARSE_TUNE_REG 0x16 | ||
| 36 | #define FINE_TUNE_REG_L 0x17 | ||
| 37 | #define FINE_TUNE_REG_H 0x18 | ||
| 38 | |||
| 39 | #define ANALOG_AGC_POWER_LEVEL_REG 0x28 | ||
| 40 | #define CFO_ESTIMATOR_CTRL_REG_1 0x29 | ||
| 41 | #define CFO_ESTIMATOR_CTRL_REG_2 0x2a | ||
| 42 | #define CFO_ESTIMATOR_CTRL_REG_3 0x2b | ||
| 43 | |||
| 44 | #define SYM_RATE_ESTIMATE_REG_L 0x31 | ||
| 45 | #define SYM_RATE_ESTIMATE_REG_M 0x32 | ||
| 46 | #define SYM_RATE_ESTIMATE_REG_H 0x33 | ||
| 47 | |||
| 48 | #define CFO_ESTIMATOR_OFFSET_REG_L 0x36 | ||
| 49 | #define CFO_ESTIMATOR_OFFSET_REG_H 0x37 | ||
| 50 | #define CFO_ERROR_REG_L 0x38 | ||
| 51 | #define CFO_ERROR_REG_H 0x39 | ||
| 52 | #define SYM_RATE_ESTIMATOR_CTRL_REG 0x3a | ||
| 53 | |||
| 54 | #define SYM_RATE_REG_L 0x3f | ||
| 55 | #define SYM_RATE_REG_M 0x40 | ||
| 56 | #define SYM_RATE_REG_H 0x41 | ||
| 57 | #define SYM_RATE_ESTIMATOR_MAXIMUM_REG 0x42 | ||
| 58 | #define SYM_RATE_ESTIMATOR_MINIMUM_REG 0x43 | ||
| 59 | |||
| 60 | #define C_N_ESTIMATOR_CTRL_REG 0x7c | ||
| 61 | #define C_N_ESTIMATOR_THRSHLD_REG 0x7d | ||
| 62 | #define C_N_ESTIMATOR_LEVEL_REG_L 0x7e | ||
| 63 | #define C_N_ESTIMATOR_LEVEL_REG_H 0x7f | ||
| 64 | |||
| 65 | #define BLIND_SCAN_CTRL_REG 0x80 | ||
| 66 | |||
| 67 | #define LSA_CTRL_REG_1 0x8D | ||
| 68 | #define SPCTRM_TILT_CORR_THRSHLD_REG 0x8f | ||
| 69 | #define ONE_DB_BNDWDTH_THRSHLD_REG 0x90 | ||
| 70 | #define TWO_DB_BNDWDTH_THRSHLD_REG 0x91 | ||
| 71 | #define THREE_DB_BNDWDTH_THRSHLD_REG 0x92 | ||
| 72 | #define INBAND_POWER_THRSHLD_REG 0x93 | ||
| 73 | #define REF_NOISE_LVL_MRGN_THRSHLD_REG 0x94 | ||
| 74 | |||
| 75 | #define VIT_SRCH_CTRL_REG_1 0xa0 | ||
| 76 | #define VIT_SRCH_CTRL_REG_2 0xa1 | ||
| 77 | #define VIT_SRCH_CTRL_REG_3 0xa2 | ||
| 78 | #define VIT_SRCH_STATUS_REG 0xa3 | ||
| 79 | #define VITERBI_BER_COUNT_REG_L 0xab | ||
| 80 | #define REED_SOLOMON_CTRL_REG 0xb0 | ||
| 81 | #define REED_SOLOMON_ERROR_COUNT_REG_L 0xb1 | ||
| 82 | #define PRBS_CTRL_REG 0xb5 | ||
| 83 | |||
| 84 | #define LNB_CTRL_REG_1 0xc0 | ||
| 85 | #define LNB_CTRL_REG_2 0xc1 | ||
| 86 | #define LNB_CTRL_REG_3 0xc2 | ||
| 87 | #define LNB_CTRL_REG_4 0xc3 | ||
| 88 | #define LNB_CTRL_STATUS_REG 0xc4 | ||
| 89 | #define LNB_FIFO_REGS_0 0xc5 | ||
| 90 | #define LNB_FIFO_REGS_1 0xc6 | ||
| 91 | #define LNB_FIFO_REGS_2 0xc7 | ||
| 92 | #define LNB_FIFO_REGS_3 0xc8 | ||
| 93 | #define LNB_FIFO_REGS_4 0xc9 | ||
| 94 | #define LNB_FIFO_REGS_5 0xca | ||
| 95 | #define LNB_SUPPLY_CTRL_REG_1 0xcb | ||
| 96 | #define LNB_SUPPLY_CTRL_REG_2 0xcc | ||
| 97 | #define LNB_SUPPLY_CTRL_REG_3 0xcd | ||
| 98 | #define LNB_SUPPLY_CTRL_REG_4 0xce | ||
| 99 | #define LNB_SUPPLY_STATUS_REG 0xcf | ||
| 100 | |||
| 101 | #define FALSE 0 | ||
| 102 | #define TRUE 1 | ||
| 103 | #define FAIL -1 | ||
| 104 | #define PASS 0 | ||
| 105 | |||
| 106 | #define ALLOWABLE_FS_COUNT 10 | ||
| 107 | #define STATUS_BER 0 | ||
| 108 | #define STATUS_UCBLOCKS 1 | ||
| 109 | |||
| 110 | static int debug; | ||
| 111 | #define dprintk(args...) \ | ||
| 112 | do { \ | ||
| 113 | if (debug) \ | ||
| 114 | printk(KERN_DEBUG "si21xx: " args); \ | ||
| 115 | } while (0) | ||
| 116 | |||
| 117 | enum { | ||
| 118 | ACTIVE_HIGH, | ||
| 119 | ACTIVE_LOW | ||
| 120 | }; | ||
| 121 | enum { | ||
| 122 | BYTE_WIDE, | ||
| 123 | BIT_WIDE | ||
| 124 | }; | ||
| 125 | enum { | ||
| 126 | CLK_GAPPED_MODE, | ||
| 127 | CLK_CONTINUOUS_MODE | ||
| 128 | }; | ||
| 129 | enum { | ||
| 130 | RISING_EDGE, | ||
| 131 | FALLING_EDGE | ||
| 132 | }; | ||
| 133 | enum { | ||
| 134 | MSB_FIRST, | ||
| 135 | LSB_FIRST | ||
| 136 | }; | ||
| 137 | enum { | ||
| 138 | SERIAL, | ||
| 139 | PARALLEL | ||
| 140 | }; | ||
| 141 | |||
| 142 | struct si21xx_state { | ||
| 143 | struct i2c_adapter *i2c; | ||
| 144 | const struct si21xx_config *config; | ||
| 145 | struct dvb_frontend frontend; | ||
| 146 | u8 initialised:1; | ||
| 147 | int errmode; | ||
| 148 | int fs; /*Sampling rate of the ADC in MHz*/ | ||
| 149 | }; | ||
| 150 | |||
| 151 | /* register default initialization */ | ||
| 152 | static u8 serit_sp1511lhb_inittab[] = { | ||
| 153 | 0x01, 0x28, /* set i2c_inc_disable */ | ||
| 154 | 0x20, 0x03, | ||
| 155 | 0x27, 0x20, | ||
| 156 | 0xe0, 0x45, | ||
| 157 | 0xe1, 0x08, | ||
| 158 | 0xfe, 0x01, | ||
| 159 | 0x01, 0x28, | ||
| 160 | 0x89, 0x09, | ||
| 161 | 0x04, 0x80, | ||
| 162 | 0x05, 0x01, | ||
| 163 | 0x06, 0x00, | ||
| 164 | 0x20, 0x03, | ||
| 165 | 0x24, 0x88, | ||
| 166 | 0x29, 0x09, | ||
| 167 | 0x2a, 0x0f, | ||
| 168 | 0x2c, 0x10, | ||
| 169 | 0x2d, 0x19, | ||
| 170 | 0x2e, 0x08, | ||
| 171 | 0x2f, 0x10, | ||
| 172 | 0x30, 0x19, | ||
| 173 | 0x34, 0x20, | ||
| 174 | 0x35, 0x03, | ||
| 175 | 0x45, 0x02, | ||
| 176 | 0x46, 0x45, | ||
| 177 | 0x47, 0xd0, | ||
| 178 | 0x48, 0x00, | ||
| 179 | 0x49, 0x40, | ||
| 180 | 0x4a, 0x03, | ||
| 181 | 0x4c, 0xfd, | ||
| 182 | 0x4f, 0x2e, | ||
| 183 | 0x50, 0x2e, | ||
| 184 | 0x51, 0x10, | ||
| 185 | 0x52, 0x10, | ||
| 186 | 0x56, 0x92, | ||
| 187 | 0x59, 0x00, | ||
| 188 | 0x5a, 0x2d, | ||
| 189 | 0x5b, 0x33, | ||
| 190 | 0x5c, 0x1f, | ||
| 191 | 0x5f, 0x76, | ||
| 192 | 0x62, 0xc0, | ||
| 193 | 0x63, 0xc0, | ||
| 194 | 0x64, 0xf3, | ||
| 195 | 0x65, 0xf3, | ||
| 196 | 0x79, 0x40, | ||
| 197 | 0x6a, 0x40, | ||
| 198 | 0x6b, 0x0a, | ||
| 199 | 0x6c, 0x80, | ||
| 200 | 0x6d, 0x27, | ||
| 201 | 0x71, 0x06, | ||
| 202 | 0x75, 0x60, | ||
| 203 | 0x78, 0x00, | ||
| 204 | 0x79, 0xb5, | ||
| 205 | 0x7c, 0x05, | ||
| 206 | 0x7d, 0x1a, | ||
| 207 | 0x87, 0x55, | ||
| 208 | 0x88, 0x72, | ||
| 209 | 0x8f, 0x08, | ||
| 210 | 0x90, 0xe0, | ||
| 211 | 0x94, 0x40, | ||
| 212 | 0xa0, 0x3f, | ||
| 213 | 0xa1, 0xc0, | ||
| 214 | 0xa4, 0xcc, | ||
| 215 | 0xa5, 0x66, | ||
| 216 | 0xa6, 0x66, | ||
| 217 | 0xa7, 0x7b, | ||
| 218 | 0xa8, 0x7b, | ||
| 219 | 0xa9, 0x7b, | ||
| 220 | 0xaa, 0x9a, | ||
| 221 | 0xed, 0x04, | ||
| 222 | 0xad, 0x00, | ||
| 223 | 0xae, 0x03, | ||
| 224 | 0xcc, 0xab, | ||
| 225 | 0x01, 0x08, | ||
| 226 | 0xff, 0xff | ||
| 227 | }; | ||
| 228 | |||
| 229 | /* low level read/writes */ | ||
| 230 | static int si21_writeregs(struct si21xx_state *state, u8 reg1, | ||
| 231 | u8 *data, int len) | ||
| 232 | { | ||
| 233 | int ret; | ||
| 234 | u8 buf[60];/* = { reg1, data };*/ | ||
| 235 | struct i2c_msg msg = { | ||
| 236 | .addr = state->config->demod_address, | ||
| 237 | .flags = 0, | ||
| 238 | .buf = buf, | ||
| 239 | .len = len + 1 | ||
| 240 | }; | ||
| 241 | |||
| 242 | msg.buf[0] = reg1; | ||
| 243 | memcpy(msg.buf + 1, data, len); | ||
| 244 | |||
| 245 | ret = i2c_transfer(state->i2c, &msg, 1); | ||
| 246 | |||
| 247 | if (ret != 1) | ||
| 248 | dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, " | ||
| 249 | "ret == %i)\n", __func__, reg1, data[0], ret); | ||
| 250 | |||
| 251 | return (ret != 1) ? -EREMOTEIO : 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data) | ||
| 255 | { | ||
| 256 | int ret; | ||
| 257 | u8 buf[] = { reg, data }; | ||
| 258 | struct i2c_msg msg = { | ||
| 259 | .addr = state->config->demod_address, | ||
| 260 | .flags = 0, | ||
| 261 | .buf = buf, | ||
| 262 | .len = 2 | ||
| 263 | }; | ||
| 264 | |||
| 265 | ret = i2c_transfer(state->i2c, &msg, 1); | ||
| 266 | |||
| 267 | if (ret != 1) | ||
| 268 | dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, " | ||
| 269 | "ret == %i)\n", __func__, reg, data, ret); | ||
| 270 | |||
| 271 | return (ret != 1) ? -EREMOTEIO : 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | static int si21_write(struct dvb_frontend *fe, u8 *buf, int len) | ||
| 275 | { | ||
| 276 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 277 | |||
| 278 | if (len != 2) | ||
| 279 | return -EINVAL; | ||
| 280 | |||
| 281 | return si21_writereg(state, buf[0], buf[1]); | ||
| 282 | } | ||
| 283 | |||
| 284 | static u8 si21_readreg(struct si21xx_state *state, u8 reg) | ||
| 285 | { | ||
| 286 | int ret; | ||
| 287 | u8 b0[] = { reg }; | ||
| 288 | u8 b1[] = { 0 }; | ||
| 289 | struct i2c_msg msg[] = { | ||
| 290 | { | ||
| 291 | .addr = state->config->demod_address, | ||
| 292 | .flags = 0, | ||
| 293 | .buf = b0, | ||
| 294 | .len = 1 | ||
| 295 | }, { | ||
| 296 | .addr = state->config->demod_address, | ||
| 297 | .flags = I2C_M_RD, | ||
| 298 | .buf = b1, | ||
| 299 | .len = 1 | ||
| 300 | } | ||
| 301 | }; | ||
| 302 | |||
| 303 | ret = i2c_transfer(state->i2c, msg, 2); | ||
| 304 | |||
| 305 | if (ret != 2) | ||
| 306 | dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", | ||
| 307 | __func__, reg, ret); | ||
| 308 | |||
| 309 | return b1[0]; | ||
| 310 | } | ||
| 311 | |||
| 312 | static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len) | ||
| 313 | { | ||
| 314 | int ret; | ||
| 315 | struct i2c_msg msg[] = { | ||
| 316 | { | ||
| 317 | .addr = state->config->demod_address, | ||
| 318 | .flags = 0, | ||
| 319 | .buf = ®1, | ||
| 320 | .len = 1 | ||
| 321 | }, { | ||
| 322 | .addr = state->config->demod_address, | ||
| 323 | .flags = I2C_M_RD, | ||
| 324 | .buf = b, | ||
| 325 | .len = len | ||
| 326 | } | ||
| 327 | }; | ||
| 328 | |||
| 329 | ret = i2c_transfer(state->i2c, msg, 2); | ||
| 330 | |||
| 331 | if (ret != 2) | ||
| 332 | dprintk("%s: readreg error (ret == %i)\n", __func__, ret); | ||
| 333 | |||
| 334 | return ret == 2 ? 0 : -1; | ||
| 335 | } | ||
| 336 | |||
| 337 | static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout) | ||
| 338 | { | ||
| 339 | unsigned long start = jiffies; | ||
| 340 | |||
| 341 | dprintk("%s\n", __func__); | ||
| 342 | |||
| 343 | while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) { | ||
| 344 | if (jiffies - start > timeout) { | ||
| 345 | dprintk("%s: timeout!!\n", __func__); | ||
| 346 | return -ETIMEDOUT; | ||
| 347 | } | ||
| 348 | msleep(10); | ||
| 349 | }; | ||
| 350 | |||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate) | ||
| 355 | { | ||
| 356 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 357 | u32 sym_rate, data_rate; | ||
| 358 | int i; | ||
| 359 | u8 sym_rate_bytes[3]; | ||
| 360 | |||
| 361 | dprintk("%s : srate = %i\n", __func__ , srate); | ||
| 362 | |||
| 363 | if ((srate < 1000000) || (srate > 45000000)) | ||
| 364 | return -EINVAL; | ||
| 365 | |||
| 366 | data_rate = srate; | ||
| 367 | sym_rate = 0; | ||
| 368 | |||
| 369 | for (i = 0; i < 4; ++i) { | ||
| 370 | sym_rate /= 100; | ||
| 371 | sym_rate = sym_rate + ((data_rate % 100) * 0x800000) / | ||
| 372 | state->fs; | ||
| 373 | data_rate /= 100; | ||
| 374 | } | ||
| 375 | for (i = 0; i < 3; ++i) | ||
| 376 | sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff); | ||
| 377 | |||
| 378 | si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03); | ||
| 379 | |||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 383 | static int si21xx_send_diseqc_msg(struct dvb_frontend *fe, | ||
| 384 | struct dvb_diseqc_master_cmd *m) | ||
| 385 | { | ||
| 386 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 387 | u8 lnb_status; | ||
| 388 | u8 LNB_CTRL_1; | ||
| 389 | int status; | ||
| 390 | |||
| 391 | dprintk("%s\n", __func__); | ||
| 392 | |||
| 393 | status = PASS; | ||
| 394 | LNB_CTRL_1 = 0; | ||
| 395 | |||
| 396 | status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01); | ||
| 397 | status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01); | ||
| 398 | |||
| 399 | /*fill the FIFO*/ | ||
| 400 | status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len); | ||
| 401 | |||
| 402 | LNB_CTRL_1 = (lnb_status & 0x70); | ||
| 403 | LNB_CTRL_1 |= m->msg_len; | ||
| 404 | |||
| 405 | LNB_CTRL_1 |= 0x80; /* begin LNB signaling */ | ||
| 406 | |||
| 407 | status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01); | ||
| 408 | |||
| 409 | return status; | ||
| 410 | } | ||
| 411 | |||
| 412 | static int si21xx_send_diseqc_burst(struct dvb_frontend *fe, | ||
| 413 | fe_sec_mini_cmd_t burst) | ||
| 414 | { | ||
| 415 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 416 | u8 val; | ||
| 417 | |||
| 418 | dprintk("%s\n", __func__); | ||
| 419 | |||
| 420 | if (si21xx_wait_diseqc_idle(state, 100) < 0) | ||
| 421 | return -ETIMEDOUT; | ||
| 422 | |||
| 423 | val = (0x80 | si21_readreg(state, 0xc1)); | ||
| 424 | if (si21_writereg(state, LNB_CTRL_REG_1, | ||
| 425 | burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10))) | ||
| 426 | return -EREMOTEIO; | ||
| 427 | |||
| 428 | if (si21xx_wait_diseqc_idle(state, 100) < 0) | ||
| 429 | return -ETIMEDOUT; | ||
| 430 | |||
| 431 | if (si21_writereg(state, LNB_CTRL_REG_1, val)) | ||
| 432 | return -EREMOTEIO; | ||
| 433 | |||
| 434 | return 0; | ||
| 435 | } | ||
| 436 | /* 30.06.2008 */ | ||
| 437 | static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | ||
| 438 | { | ||
| 439 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 440 | u8 val; | ||
| 441 | |||
| 442 | dprintk("%s\n", __func__); | ||
| 443 | val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1)); | ||
| 444 | |||
| 445 | switch (tone) { | ||
| 446 | case SEC_TONE_ON: | ||
| 447 | return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20); | ||
| 448 | |||
| 449 | case SEC_TONE_OFF: | ||
| 450 | return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20)); | ||
| 451 | |||
| 452 | default: | ||
| 453 | return -EINVAL; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) | ||
| 458 | { | ||
| 459 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 460 | |||
| 461 | u8 val; | ||
| 462 | dprintk("%s: %s\n", __func__, | ||
| 463 | volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : | ||
| 464 | volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); | ||
| 465 | |||
| 466 | |||
| 467 | val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1)); | ||
| 468 | |||
| 469 | switch (volt) { | ||
| 470 | case SEC_VOLTAGE_18: | ||
| 471 | return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40); | ||
| 472 | break; | ||
| 473 | case SEC_VOLTAGE_13: | ||
| 474 | return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40)); | ||
| 475 | break; | ||
| 476 | default: | ||
| 477 | return -EINVAL; | ||
| 478 | }; | ||
| 479 | } | ||
| 480 | |||
| 481 | static int si21xx_init(struct dvb_frontend *fe) | ||
| 482 | { | ||
| 483 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 484 | int i; | ||
| 485 | int status = 0; | ||
| 486 | u8 reg1; | ||
| 487 | u8 val; | ||
| 488 | u8 reg2[2]; | ||
| 489 | |||
| 490 | dprintk("%s\n", __func__); | ||
| 491 | |||
| 492 | for (i = 0; ; i += 2) { | ||
| 493 | reg1 = serit_sp1511lhb_inittab[i]; | ||
| 494 | val = serit_sp1511lhb_inittab[i+1]; | ||
| 495 | if (reg1 == 0xff && val == 0xff) | ||
| 496 | break; | ||
| 497 | si21_writeregs(state, reg1, &val, 1); | ||
| 498 | } | ||
| 499 | |||
| 500 | /*DVB QPSK SYSTEM MODE REG*/ | ||
| 501 | reg1 = 0x08; | ||
| 502 | si21_writeregs(state, SYSTEM_MODE_REG, ®1, 0x01); | ||
| 503 | |||
| 504 | /*transport stream config*/ | ||
| 505 | /* | ||
| 506 | mode = PARALLEL; | ||
| 507 | sdata_form = LSB_FIRST; | ||
| 508 | clk_edge = FALLING_EDGE; | ||
| 509 | clk_mode = CLK_GAPPED_MODE; | ||
| 510 | strt_len = BYTE_WIDE; | ||
| 511 | sync_pol = ACTIVE_HIGH; | ||
| 512 | val_pol = ACTIVE_HIGH; | ||
| 513 | err_pol = ACTIVE_HIGH; | ||
| 514 | sclk_rate = 0x00; | ||
| 515 | parity = 0x00 ; | ||
| 516 | data_delay = 0x00; | ||
| 517 | clk_delay = 0x00; | ||
| 518 | pclk_smooth = 0x00; | ||
| 519 | */ | ||
| 520 | reg2[0] = | ||
| 521 | PARALLEL + (LSB_FIRST << 1) | ||
| 522 | + (FALLING_EDGE << 2) + (CLK_GAPPED_MODE << 3) | ||
| 523 | + (BYTE_WIDE << 4) + (ACTIVE_HIGH << 5) | ||
| 524 | + (ACTIVE_HIGH << 6) + (ACTIVE_HIGH << 7); | ||
| 525 | |||
| 526 | reg2[1] = 0; | ||
| 527 | /* sclk_rate + (parity << 2) | ||
| 528 | + (data_delay << 3) + (clk_delay << 4) | ||
| 529 | + (pclk_smooth << 5); | ||
| 530 | */ | ||
| 531 | status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02); | ||
| 532 | if (status != 0) | ||
| 533 | dprintk(" %s : TS Set Error\n", __func__); | ||
| 534 | |||
| 535 | return 0; | ||
| 536 | |||
| 537 | } | ||
| 538 | |||
| 539 | static int si21_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
| 540 | { | ||
| 541 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 542 | u8 regs_read[2]; | ||
| 543 | u8 reg_read; | ||
| 544 | u8 i; | ||
| 545 | u8 lock; | ||
| 546 | u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG); | ||
| 547 | |||
| 548 | si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02); | ||
| 549 | reg_read = 0; | ||
| 550 | |||
| 551 | for (i = 0; i < 7; ++i) | ||
| 552 | reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i); | ||
| 553 | |||
| 554 | lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80)); | ||
| 555 | |||
| 556 | dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock); | ||
| 557 | *status = 0; | ||
| 558 | |||
| 559 | if (signal > 10) | ||
| 560 | *status |= FE_HAS_SIGNAL; | ||
| 561 | |||
| 562 | if (lock & 0x2) | ||
| 563 | *status |= FE_HAS_CARRIER; | ||
| 564 | |||
| 565 | if (lock & 0x20) | ||
| 566 | *status |= FE_HAS_VITERBI; | ||
| 567 | |||
| 568 | if (lock & 0x40) | ||
| 569 | *status |= FE_HAS_SYNC; | ||
| 570 | |||
| 571 | if ((lock & 0x7b) == 0x7b) | ||
| 572 | *status |= FE_HAS_LOCK; | ||
| 573 | |||
| 574 | return 0; | ||
| 575 | } | ||
| 576 | |||
| 577 | static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
| 578 | { | ||
| 579 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 580 | |||
| 581 | /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG, | ||
| 582 | (u8*)agclevel, 0x01);*/ | ||
| 583 | |||
| 584 | u16 signal = (3 * si21_readreg(state, 0x27) * | ||
| 585 | si21_readreg(state, 0x28)); | ||
| 586 | |||
| 587 | dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__, | ||
| 588 | si21_readreg(state, 0x27), | ||
| 589 | si21_readreg(state, 0x28), (int) signal); | ||
| 590 | |||
| 591 | signal <<= 4; | ||
| 592 | *strength = signal; | ||
| 593 | |||
| 594 | return 0; | ||
| 595 | } | ||
| 596 | |||
| 597 | static int si21_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
| 598 | { | ||
| 599 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 600 | |||
| 601 | dprintk("%s\n", __func__); | ||
| 602 | |||
| 603 | if (state->errmode != STATUS_BER) | ||
| 604 | return 0; | ||
| 605 | |||
| 606 | *ber = (si21_readreg(state, 0x1d) << 8) | | ||
| 607 | si21_readreg(state, 0x1e); | ||
| 608 | |||
| 609 | return 0; | ||
| 610 | } | ||
| 611 | |||
| 612 | static int si21_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
| 613 | { | ||
| 614 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 615 | |||
| 616 | s32 xsnr = 0xffff - ((si21_readreg(state, 0x24) << 8) | | ||
| 617 | si21_readreg(state, 0x25)); | ||
| 618 | xsnr = 3 * (xsnr - 0xa100); | ||
| 619 | *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr; | ||
| 620 | |||
| 621 | dprintk("%s\n", __func__); | ||
| 622 | |||
| 623 | return 0; | ||
| 624 | } | ||
| 625 | |||
| 626 | static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
| 627 | { | ||
| 628 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 629 | |||
| 630 | dprintk("%s\n", __func__); | ||
| 631 | |||
| 632 | if (state->errmode != STATUS_UCBLOCKS) | ||
| 633 | *ucblocks = 0; | ||
| 634 | else | ||
| 635 | *ucblocks = (si21_readreg(state, 0x1d) << 8) | | ||
| 636 | si21_readreg(state, 0x1e); | ||
| 637 | |||
| 638 | return 0; | ||
| 639 | } | ||
| 640 | |||
| 641 | /* initiates a channel acquisition sequence | ||
| 642 | using the specified symbol rate and code rate */ | ||
| 643 | static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate, | ||
| 644 | fe_code_rate_t crate) | ||
| 645 | { | ||
| 646 | |||
| 647 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 648 | u8 coderates[] = { | ||
| 649 | 0x0, 0x01, 0x02, 0x04, 0x00, | ||
| 650 | 0x8, 0x10, 0x20, 0x00, 0x3f | ||
| 651 | }; | ||
| 652 | |||
| 653 | u8 coderate_ptr; | ||
| 654 | int status; | ||
| 655 | u8 start_acq = 0x80; | ||
| 656 | u8 reg, regs[3]; | ||
| 657 | |||
| 658 | dprintk("%s\n", __func__); | ||
| 659 | |||
| 660 | status = PASS; | ||
| 661 | coderate_ptr = coderates[crate]; | ||
| 662 | |||
| 663 | si21xx_set_symbolrate(fe, symbrate); | ||
| 664 | |||
| 665 | /* write code rates to use in the Viterbi search */ | ||
| 666 | status |= si21_writeregs(state, | ||
| 667 | VIT_SRCH_CTRL_REG_1, | ||
| 668 | &coderate_ptr, 0x01); | ||
| 669 | |||
| 670 | /* clear acq_start bit */ | ||
| 671 | status |= si21_readregs(state, ACQ_CTRL_REG_2, ®, 0x01); | ||
| 672 | reg &= ~start_acq; | ||
| 673 | status |= si21_writeregs(state, ACQ_CTRL_REG_2, ®, 0x01); | ||
| 674 | |||
| 675 | /* use new Carrier Frequency Offset Estimator (QuickLock) */ | ||
| 676 | regs[0] = 0xCB; | ||
| 677 | regs[1] = 0x40; | ||
| 678 | regs[2] = 0xCB; | ||
| 679 | |||
| 680 | status |= si21_writeregs(state, | ||
| 681 | TWO_DB_BNDWDTH_THRSHLD_REG, | ||
| 682 | ®s[0], 0x03); | ||
| 683 | reg = 0x56; | ||
| 684 | status |= si21_writeregs(state, | ||
| 685 | LSA_CTRL_REG_1, ®, 1); | ||
| 686 | reg = 0x05; | ||
| 687 | status |= si21_writeregs(state, | ||
| 688 | BLIND_SCAN_CTRL_REG, ®, 1); | ||
| 689 | /* start automatic acq */ | ||
| 690 | status |= si21_writeregs(state, | ||
| 691 | ACQ_CTRL_REG_2, &start_acq, 0x01); | ||
| 692 | |||
| 693 | return status; | ||
| 694 | } | ||
| 695 | |||
| 696 | static int si21xx_set_property(struct dvb_frontend *fe, struct dtv_property *p) | ||
| 697 | { | ||
| 698 | dprintk("%s(..)\n", __func__); | ||
| 699 | return 0; | ||
| 700 | } | ||
| 701 | |||
| 702 | static int si21xx_get_property(struct dvb_frontend *fe, struct dtv_property *p) | ||
| 703 | { | ||
| 704 | dprintk("%s(..)\n", __func__); | ||
| 705 | return 0; | ||
| 706 | } | ||
| 707 | |||
| 708 | static int si21xx_set_frontend(struct dvb_frontend *fe, | ||
| 709 | struct dvb_frontend_parameters *dfp) | ||
| 710 | { | ||
| 711 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 712 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 713 | |||
| 714 | /* freq Channel carrier frequency in KHz (i.e. 1550000 KHz) | ||
| 715 | datarate Channel symbol rate in Sps (i.e. 22500000 Sps)*/ | ||
| 716 | |||
| 717 | /* in MHz */ | ||
| 718 | unsigned char coarse_tune_freq; | ||
| 719 | int fine_tune_freq; | ||
| 720 | unsigned char sample_rate = 0; | ||
| 721 | /* boolean */ | ||
| 722 | unsigned int inband_interferer_ind; | ||
| 723 | |||
| 724 | /* INTERMEDIATE VALUES */ | ||
| 725 | int icoarse_tune_freq; /* MHz */ | ||
| 726 | int ifine_tune_freq; /* MHz */ | ||
| 727 | unsigned int band_high; | ||
| 728 | unsigned int band_low; | ||
| 729 | unsigned int x1; | ||
| 730 | unsigned int x2; | ||
| 731 | int i; | ||
| 732 | unsigned int inband_interferer_div2[ALLOWABLE_FS_COUNT] = { | ||
| 733 | FALSE, FALSE, FALSE, FALSE, FALSE, | ||
| 734 | FALSE, FALSE, FALSE, FALSE, FALSE | ||
| 735 | }; | ||
| 736 | unsigned int inband_interferer_div4[ALLOWABLE_FS_COUNT] = { | ||
| 737 | FALSE, FALSE, FALSE, FALSE, FALSE, | ||
| 738 | FALSE, FALSE, FALSE, FALSE, FALSE | ||
| 739 | }; | ||
| 740 | |||
| 741 | int status; | ||
| 742 | |||
| 743 | /* allowable sample rates for ADC in MHz */ | ||
| 744 | int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195, | ||
| 745 | 196, 204, 205, 206, 207 | ||
| 746 | }; | ||
| 747 | /* in MHz */ | ||
| 748 | int if_limit_high; | ||
| 749 | int if_limit_low; | ||
| 750 | int lnb_lo; | ||
| 751 | int lnb_uncertanity; | ||
| 752 | |||
| 753 | int rf_freq; | ||
| 754 | int data_rate; | ||
| 755 | unsigned char regs[4]; | ||
| 756 | |||
| 757 | dprintk("%s : FE_SET_FRONTEND\n", __func__); | ||
| 758 | |||
| 759 | if (c->delivery_system != SYS_DVBS) { | ||
| 760 | dprintk("%s: unsupported delivery system selected (%d)\n", | ||
| 761 | __func__, c->delivery_system); | ||
| 762 | return -EOPNOTSUPP; | ||
| 763 | } | ||
| 764 | |||
| 765 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) | ||
| 766 | inband_interferer_div2[i] = inband_interferer_div4[i] = FALSE; | ||
| 767 | |||
| 768 | if_limit_high = -700000; | ||
| 769 | if_limit_low = -100000; | ||
| 770 | /* in MHz */ | ||
| 771 | lnb_lo = 0; | ||
| 772 | lnb_uncertanity = 0; | ||
| 773 | |||
| 774 | rf_freq = 10 * c->frequency ; | ||
| 775 | data_rate = c->symbol_rate / 100; | ||
| 776 | |||
| 777 | status = PASS; | ||
| 778 | |||
| 779 | band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200) | ||
| 780 | + (data_rate * 135)) / 200; | ||
| 781 | |||
| 782 | band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200) | ||
| 783 | + (data_rate * 135)) / 200; | ||
| 784 | |||
| 785 | |||
| 786 | icoarse_tune_freq = 100000 * | ||
| 787 | (((rf_freq - lnb_lo) - | ||
| 788 | (if_limit_low + if_limit_high) / 2) | ||
| 789 | / 100000); | ||
| 790 | |||
| 791 | ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ; | ||
| 792 | |||
| 793 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { | ||
| 794 | x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) * | ||
| 795 | (afs[i] * 2500) + afs[i] * 2500; | ||
| 796 | |||
| 797 | x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) * | ||
| 798 | (afs[i] * 2500); | ||
| 799 | |||
| 800 | if (((band_low < x1) && (x1 < band_high)) || | ||
| 801 | ((band_low < x2) && (x2 < band_high))) | ||
| 802 | inband_interferer_div4[i] = TRUE; | ||
| 803 | |||
| 804 | } | ||
| 805 | |||
| 806 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { | ||
| 807 | x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) * | ||
| 808 | (afs[i] * 5000) + afs[i] * 5000; | ||
| 809 | |||
| 810 | x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) * | ||
| 811 | (afs[i] * 5000); | ||
| 812 | |||
| 813 | if (((band_low < x1) && (x1 < band_high)) || | ||
| 814 | ((band_low < x2) && (x2 < band_high))) | ||
| 815 | inband_interferer_div2[i] = TRUE; | ||
| 816 | } | ||
| 817 | |||
| 818 | inband_interferer_ind = TRUE; | ||
| 819 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) | ||
| 820 | inband_interferer_ind &= inband_interferer_div2[i] | | ||
| 821 | inband_interferer_div4[i]; | ||
| 822 | |||
| 823 | if (inband_interferer_ind) { | ||
| 824 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { | ||
| 825 | if (inband_interferer_div2[i] == FALSE) { | ||
| 826 | sample_rate = (u8) afs[i]; | ||
| 827 | break; | ||
| 828 | } | ||
| 829 | } | ||
| 830 | } else { | ||
| 831 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { | ||
| 832 | if ((inband_interferer_div2[i] | | ||
| 833 | inband_interferer_div4[i]) == FALSE) { | ||
| 834 | sample_rate = (u8) afs[i]; | ||
| 835 | break; | ||
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 839 | } | ||
| 840 | |||
| 841 | if (sample_rate > 207 || sample_rate < 192) | ||
| 842 | sample_rate = 200; | ||
| 843 | |||
| 844 | fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) / | ||
| 845 | ((sample_rate) * 1000)); | ||
| 846 | |||
| 847 | coarse_tune_freq = (u8)(icoarse_tune_freq / 100000); | ||
| 848 | |||
| 849 | regs[0] = sample_rate; | ||
| 850 | regs[1] = coarse_tune_freq; | ||
| 851 | regs[2] = fine_tune_freq & 0xFF; | ||
| 852 | regs[3] = fine_tune_freq >> 8 & 0xFF; | ||
| 853 | |||
| 854 | status |= si21_writeregs(state, PLL_DIVISOR_REG, ®s[0], 0x04); | ||
| 855 | |||
| 856 | state->fs = sample_rate;/*ADC MHz*/ | ||
| 857 | si21xx_setacquire(fe, c->symbol_rate, c->fec_inner); | ||
| 858 | |||
| 859 | return 0; | ||
| 860 | } | ||
| 861 | |||
| 862 | static int si21xx_sleep(struct dvb_frontend *fe) | ||
| 863 | { | ||
| 864 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 865 | u8 regdata; | ||
| 866 | |||
| 867 | dprintk("%s\n", __func__); | ||
| 868 | |||
| 869 | si21_readregs(state, SYSTEM_MODE_REG, ®data, 0x01); | ||
| 870 | regdata |= 1 << 6; | ||
| 871 | si21_writeregs(state, SYSTEM_MODE_REG, ®data, 0x01); | ||
| 872 | state->initialised = 0; | ||
| 873 | |||
| 874 | return 0; | ||
| 875 | } | ||
| 876 | |||
| 877 | static void si21xx_release(struct dvb_frontend *fe) | ||
| 878 | { | ||
| 879 | struct si21xx_state *state = fe->demodulator_priv; | ||
| 880 | |||
| 881 | dprintk("%s\n", __func__); | ||
| 882 | |||
| 883 | kfree(state); | ||
| 884 | } | ||
| 885 | |||
| 886 | static struct dvb_frontend_ops si21xx_ops = { | ||
| 887 | |||
| 888 | .info = { | ||
| 889 | .name = "SL SI21XX DVB-S", | ||
| 890 | .type = FE_QPSK, | ||
| 891 | .frequency_min = 950000, | ||
| 892 | .frequency_max = 2150000, | ||
| 893 | .frequency_stepsize = 125, /* kHz for QPSK frontends */ | ||
| 894 | .frequency_tolerance = 0, | ||
| 895 | .symbol_rate_min = 1000000, | ||
| 896 | .symbol_rate_max = 45000000, | ||
| 897 | .symbol_rate_tolerance = 500, /* ppm */ | ||
| 898 | .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 899 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | | ||
| 900 | FE_CAN_QPSK | | ||
| 901 | FE_CAN_FEC_AUTO | ||
| 902 | }, | ||
| 903 | |||
| 904 | .release = si21xx_release, | ||
| 905 | .init = si21xx_init, | ||
| 906 | .sleep = si21xx_sleep, | ||
| 907 | .write = si21_write, | ||
| 908 | .read_status = si21_read_status, | ||
| 909 | .read_ber = si21_read_ber, | ||
| 910 | .read_signal_strength = si21_read_signal_strength, | ||
| 911 | .read_snr = si21_read_snr, | ||
| 912 | .read_ucblocks = si21_read_ucblocks, | ||
| 913 | .diseqc_send_master_cmd = si21xx_send_diseqc_msg, | ||
| 914 | .diseqc_send_burst = si21xx_send_diseqc_burst, | ||
| 915 | .set_tone = si21xx_set_tone, | ||
| 916 | .set_voltage = si21xx_set_voltage, | ||
| 917 | |||
| 918 | .set_property = si21xx_set_property, | ||
| 919 | .get_property = si21xx_get_property, | ||
| 920 | .set_frontend = si21xx_set_frontend, | ||
| 921 | }; | ||
| 922 | |||
| 923 | struct dvb_frontend *si21xx_attach(const struct si21xx_config *config, | ||
| 924 | struct i2c_adapter *i2c) | ||
| 925 | { | ||
| 926 | struct si21xx_state *state = NULL; | ||
| 927 | int id; | ||
| 928 | |||
| 929 | dprintk("%s\n", __func__); | ||
| 930 | |||
| 931 | /* allocate memory for the internal state */ | ||
| 932 | state = kmalloc(sizeof(struct si21xx_state), GFP_KERNEL); | ||
| 933 | if (state == NULL) | ||
| 934 | goto error; | ||
| 935 | |||
| 936 | /* setup the state */ | ||
| 937 | state->config = config; | ||
| 938 | state->i2c = i2c; | ||
| 939 | state->initialised = 0; | ||
| 940 | state->errmode = STATUS_BER; | ||
| 941 | |||
| 942 | /* check if the demod is there */ | ||
| 943 | id = si21_readreg(state, SYSTEM_MODE_REG); | ||
| 944 | si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */ | ||
| 945 | msleep(200); | ||
| 946 | id = si21_readreg(state, 0x00); | ||
| 947 | |||
| 948 | /* register 0x00 contains: | ||
| 949 | 0x34 for SI2107 | ||
| 950 | 0x24 for SI2108 | ||
| 951 | 0x14 for SI2109 | ||
| 952 | 0x04 for SI2110 | ||
| 953 | */ | ||
| 954 | if (id != 0x04 && id != 0x14) | ||
| 955 | goto error; | ||
| 956 | |||
| 957 | /* create dvb_frontend */ | ||
| 958 | memcpy(&state->frontend.ops, &si21xx_ops, | ||
| 959 | sizeof(struct dvb_frontend_ops)); | ||
| 960 | state->frontend.demodulator_priv = state; | ||
| 961 | return &state->frontend; | ||
| 962 | |||
| 963 | error: | ||
| 964 | kfree(state); | ||
| 965 | return NULL; | ||
| 966 | } | ||
| 967 | EXPORT_SYMBOL(si21xx_attach); | ||
| 968 | |||
| 969 | module_param(debug, int, 0644); | ||
| 970 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
| 971 | |||
| 972 | MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver"); | ||
| 973 | MODULE_AUTHOR("Igor M. Liplianin"); | ||
| 974 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/si21xx.h b/drivers/media/dvb/frontends/si21xx.h new file mode 100644 index 000000000000..141b5b8a5f63 --- /dev/null +++ b/drivers/media/dvb/frontends/si21xx.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | #ifndef SI21XX_H | ||
| 2 | #define SI21XX_H | ||
| 3 | |||
| 4 | #include <linux/dvb/frontend.h> | ||
| 5 | #include "dvb_frontend.h" | ||
| 6 | |||
| 7 | struct si21xx_config { | ||
| 8 | /* the demodulator's i2c address */ | ||
| 9 | u8 demod_address; | ||
| 10 | |||
| 11 | /* minimum delay before retuning */ | ||
| 12 | int min_delay_ms; | ||
| 13 | }; | ||
| 14 | |||
| 15 | #if defined(CONFIG_DVB_SI21XX) || \ | ||
| 16 | (defined(CONFIG_DVB_SI21XX_MODULE) && defined(MODULE)) | ||
| 17 | extern struct dvb_frontend *si21xx_attach(const struct si21xx_config *config, | ||
| 18 | struct i2c_adapter *i2c); | ||
| 19 | #else | ||
| 20 | static inline struct dvb_frontend *si21xx_attach( | ||
| 21 | const struct si21xx_config *config, struct i2c_adapter *i2c) | ||
| 22 | { | ||
| 23 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 24 | return NULL; | ||
| 25 | } | ||
| 26 | #endif | ||
| 27 | |||
| 28 | static inline int si21xx_writeregister(struct dvb_frontend *fe, u8 reg, u8 val) | ||
| 29 | { | ||
| 30 | int r = 0; | ||
| 31 | u8 buf[] = {reg, val}; | ||
| 32 | if (fe->ops.write) | ||
| 33 | r = fe->ops.write(fe, buf, 2); | ||
| 34 | return r; | ||
| 35 | } | ||
| 36 | |||
| 37 | #endif | ||
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c index 4543609e1816..559509ab4dab 100644 --- a/drivers/media/dvb/frontends/sp887x.c +++ b/drivers/media/dvb/frontends/sp887x.c | |||
| @@ -337,7 +337,8 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe, | |||
| 337 | struct dvb_frontend_parameters *p) | 337 | struct dvb_frontend_parameters *p) |
| 338 | { | 338 | { |
| 339 | struct sp887x_state* state = fe->demodulator_priv; | 339 | struct sp887x_state* state = fe->demodulator_priv; |
| 340 | int actual_freq, err; | 340 | unsigned actual_freq; |
| 341 | int err; | ||
| 341 | u16 val, reg0xc05; | 342 | u16 val, reg0xc05; |
| 342 | 343 | ||
| 343 | if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ && | 344 | if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ && |
diff --git a/drivers/media/dvb/frontends/stb6000.c b/drivers/media/dvb/frontends/stb6000.c new file mode 100644 index 000000000000..0e2cb0df1441 --- /dev/null +++ b/drivers/media/dvb/frontends/stb6000.c | |||
| @@ -0,0 +1,255 @@ | |||
| 1 | /* | ||
| 2 | Driver for ST STB6000 DVBS Silicon tuner | ||
| 3 | |||
| 4 | Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | |||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; if not, write to the Free Software | ||
| 19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 20 | |||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/dvb/frontend.h> | ||
| 25 | #include <asm/types.h> | ||
| 26 | |||
| 27 | #include "stb6000.h" | ||
| 28 | |||
| 29 | static int debug; | ||
| 30 | #define dprintk(args...) \ | ||
| 31 | do { \ | ||
| 32 | if (debug) \ | ||
| 33 | printk(KERN_DEBUG "stb6000: " args); \ | ||
| 34 | } while (0) | ||
| 35 | |||
| 36 | struct stb6000_priv { | ||
| 37 | /* i2c details */ | ||
| 38 | int i2c_address; | ||
| 39 | struct i2c_adapter *i2c; | ||
| 40 | u32 frequency; | ||
| 41 | }; | ||
| 42 | |||
| 43 | static int stb6000_release(struct dvb_frontend *fe) | ||
| 44 | { | ||
| 45 | kfree(fe->tuner_priv); | ||
| 46 | fe->tuner_priv = NULL; | ||
| 47 | return 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | static int stb6000_sleep(struct dvb_frontend *fe) | ||
| 51 | { | ||
| 52 | struct stb6000_priv *priv = fe->tuner_priv; | ||
| 53 | int ret; | ||
| 54 | u8 buf[] = { 10, 0 }; | ||
| 55 | struct i2c_msg msg = { | ||
| 56 | .addr = priv->i2c_address, | ||
| 57 | .flags = 0, | ||
| 58 | .buf = buf, | ||
| 59 | .len = 2 | ||
| 60 | }; | ||
| 61 | |||
| 62 | dprintk("%s:\n", __func__); | ||
| 63 | |||
| 64 | if (fe->ops.i2c_gate_ctrl) | ||
| 65 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
| 66 | |||
| 67 | ret = i2c_transfer(priv->i2c, &msg, 1); | ||
| 68 | if (ret != 1) | ||
| 69 | dprintk("%s: i2c error\n", __func__); | ||
| 70 | |||
| 71 | if (fe->ops.i2c_gate_ctrl) | ||
| 72 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
| 73 | |||
| 74 | return (ret == 1) ? 0 : ret; | ||
| 75 | } | ||
| 76 | |||
| 77 | static int stb6000_set_params(struct dvb_frontend *fe, | ||
| 78 | struct dvb_frontend_parameters *params) | ||
| 79 | { | ||
| 80 | struct stb6000_priv *priv = fe->tuner_priv; | ||
| 81 | unsigned int n, m; | ||
| 82 | int ret; | ||
| 83 | u32 freq_mhz; | ||
| 84 | int bandwidth; | ||
| 85 | u8 buf[12]; | ||
| 86 | struct i2c_msg msg = { | ||
| 87 | .addr = priv->i2c_address, | ||
| 88 | .flags = 0, | ||
| 89 | .buf = buf, | ||
| 90 | .len = 12 | ||
| 91 | }; | ||
| 92 | |||
| 93 | dprintk("%s:\n", __func__); | ||
| 94 | |||
| 95 | freq_mhz = params->frequency / 1000; | ||
| 96 | bandwidth = params->u.qpsk.symbol_rate / 1000000; | ||
| 97 | |||
| 98 | if (bandwidth > 31) | ||
| 99 | bandwidth = 31; | ||
| 100 | |||
| 101 | if ((freq_mhz > 949) && (freq_mhz < 2151)) { | ||
| 102 | buf[0] = 0x01; | ||
| 103 | buf[1] = 0xac; | ||
| 104 | if (freq_mhz < 1950) | ||
| 105 | buf[1] = 0xaa; | ||
| 106 | if (freq_mhz < 1800) | ||
| 107 | buf[1] = 0xa8; | ||
| 108 | if (freq_mhz < 1650) | ||
| 109 | buf[1] = 0xa6; | ||
| 110 | if (freq_mhz < 1530) | ||
| 111 | buf[1] = 0xa5; | ||
| 112 | if (freq_mhz < 1470) | ||
| 113 | buf[1] = 0xa4; | ||
| 114 | if (freq_mhz < 1370) | ||
| 115 | buf[1] = 0xa2; | ||
| 116 | if (freq_mhz < 1300) | ||
| 117 | buf[1] = 0xa1; | ||
| 118 | if (freq_mhz < 1200) | ||
| 119 | buf[1] = 0xa0; | ||
| 120 | if (freq_mhz < 1075) | ||
| 121 | buf[1] = 0xbc; | ||
| 122 | if (freq_mhz < 1000) | ||
| 123 | buf[1] = 0xba; | ||
| 124 | if (freq_mhz < 1075) { | ||
| 125 | n = freq_mhz / 8; /* vco=lo*4 */ | ||
| 126 | m = 2; | ||
| 127 | } else { | ||
| 128 | n = freq_mhz / 16; /* vco=lo*2 */ | ||
| 129 | m = 1; | ||
| 130 | } | ||
| 131 | buf[2] = n >> 1; | ||
| 132 | buf[3] = (unsigned char)(((n & 1) << 7) | | ||
| 133 | (m * freq_mhz - n * 16) | 0x60); | ||
| 134 | buf[4] = 0x04; | ||
| 135 | buf[5] = 0x0e; | ||
| 136 | |||
| 137 | buf[6] = (unsigned char)(bandwidth); | ||
| 138 | |||
| 139 | buf[7] = 0xd8; | ||
| 140 | buf[8] = 0xd0; | ||
| 141 | buf[9] = 0x50; | ||
| 142 | buf[10] = 0xeb; | ||
| 143 | buf[11] = 0x4f; | ||
| 144 | |||
| 145 | if (fe->ops.i2c_gate_ctrl) | ||
| 146 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
| 147 | |||
| 148 | ret = i2c_transfer(priv->i2c, &msg, 1); | ||
| 149 | if (ret != 1) | ||
| 150 | dprintk("%s: i2c error\n", __func__); | ||
| 151 | |||
| 152 | udelay(10); | ||
| 153 | if (fe->ops.i2c_gate_ctrl) | ||
| 154 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
| 155 | |||
| 156 | buf[0] = 0x07; | ||
| 157 | buf[1] = 0xdf; | ||
| 158 | buf[2] = 0xd0; | ||
| 159 | buf[3] = 0x50; | ||
| 160 | buf[4] = 0xfb; | ||
| 161 | msg.len = 5; | ||
| 162 | |||
| 163 | if (fe->ops.i2c_gate_ctrl) | ||
| 164 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
| 165 | |||
| 166 | ret = i2c_transfer(priv->i2c, &msg, 1); | ||
| 167 | if (ret != 1) | ||
| 168 | dprintk("%s: i2c error\n", __func__); | ||
| 169 | |||
| 170 | udelay(10); | ||
| 171 | if (fe->ops.i2c_gate_ctrl) | ||
| 172 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
| 173 | |||
| 174 | priv->frequency = freq_mhz * 1000; | ||
| 175 | |||
| 176 | return (ret == 1) ? 0 : ret; | ||
| 177 | } | ||
| 178 | return -1; | ||
| 179 | } | ||
| 180 | |||
| 181 | static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
| 182 | { | ||
| 183 | struct stb6000_priv *priv = fe->tuner_priv; | ||
| 184 | *frequency = priv->frequency; | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static struct dvb_tuner_ops stb6000_tuner_ops = { | ||
| 189 | .info = { | ||
| 190 | .name = "ST STB6000", | ||
| 191 | .frequency_min = 950000, | ||
| 192 | .frequency_max = 2150000 | ||
| 193 | }, | ||
| 194 | .release = stb6000_release, | ||
| 195 | .sleep = stb6000_sleep, | ||
| 196 | .set_params = stb6000_set_params, | ||
| 197 | .get_frequency = stb6000_get_frequency, | ||
| 198 | }; | ||
| 199 | |||
| 200 | struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr, | ||
| 201 | struct i2c_adapter *i2c) | ||
| 202 | { | ||
| 203 | struct stb6000_priv *priv = NULL; | ||
| 204 | u8 b0[] = { 0 }; | ||
| 205 | u8 b1[] = { 0, 0 }; | ||
| 206 | struct i2c_msg msg[2] = { | ||
| 207 | { | ||
| 208 | .addr = addr, | ||
| 209 | .flags = 0, | ||
| 210 | .buf = b0, | ||
| 211 | .len = 0 | ||
| 212 | }, { | ||
| 213 | .addr = addr, | ||
| 214 | .flags = I2C_M_RD, | ||
| 215 | .buf = b1, | ||
| 216 | .len = 2 | ||
| 217 | } | ||
| 218 | }; | ||
| 219 | int ret; | ||
| 220 | |||
| 221 | dprintk("%s:\n", __func__); | ||
| 222 | |||
| 223 | if (fe->ops.i2c_gate_ctrl) | ||
| 224 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
| 225 | |||
| 226 | /* is some i2c device here ? */ | ||
| 227 | ret = i2c_transfer(i2c, msg, 2); | ||
| 228 | if (fe->ops.i2c_gate_ctrl) | ||
| 229 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
| 230 | |||
| 231 | if (ret != 2) | ||
| 232 | return NULL; | ||
| 233 | |||
| 234 | priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL); | ||
| 235 | if (priv == NULL) | ||
| 236 | return NULL; | ||
| 237 | |||
| 238 | priv->i2c_address = addr; | ||
| 239 | priv->i2c = i2c; | ||
| 240 | |||
| 241 | memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops, | ||
| 242 | sizeof(struct dvb_tuner_ops)); | ||
| 243 | |||
| 244 | fe->tuner_priv = priv; | ||
| 245 | |||
| 246 | return fe; | ||
| 247 | } | ||
| 248 | EXPORT_SYMBOL(stb6000_attach); | ||
| 249 | |||
| 250 | module_param(debug, int, 0644); | ||
| 251 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
| 252 | |||
| 253 | MODULE_DESCRIPTION("DVB STB6000 driver"); | ||
| 254 | MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>"); | ||
| 255 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/stb6000.h b/drivers/media/dvb/frontends/stb6000.h new file mode 100644 index 000000000000..7be479c22d5b --- /dev/null +++ b/drivers/media/dvb/frontends/stb6000.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | /* | ||
| 2 | Driver for ST stb6000 DVBS Silicon tuner | ||
| 3 | |||
| 4 | Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | |||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; if not, write to the Free Software | ||
| 19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 20 | |||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef __DVB_STB6000_H__ | ||
| 24 | #define __DVB_STB6000_H__ | ||
| 25 | |||
| 26 | #include <linux/i2c.h> | ||
| 27 | #include "dvb_frontend.h" | ||
| 28 | |||
| 29 | /** | ||
| 30 | * Attach a stb6000 tuner to the supplied frontend structure. | ||
| 31 | * | ||
| 32 | * @param fe Frontend to attach to. | ||
| 33 | * @param addr i2c address of the tuner. | ||
| 34 | * @param i2c i2c adapter to use. | ||
| 35 | * @return FE pointer on success, NULL on failure. | ||
| 36 | */ | ||
| 37 | #if defined(CONFIG_DVB_STB6000) || (defined(CONFIG_DVB_STB6000_MODULE) \ | ||
| 38 | && defined(MODULE)) | ||
| 39 | extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr, | ||
| 40 | struct i2c_adapter *i2c); | ||
| 41 | #else | ||
| 42 | static inline struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, | ||
| 43 | int addr, | ||
| 44 | struct i2c_adapter *i2c) | ||
| 45 | { | ||
| 46 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 47 | return NULL; | ||
| 48 | } | ||
| 49 | #endif /* CONFIG_DVB_STB6000 */ | ||
| 50 | |||
| 51 | #endif /* __DVB_STB6000_H__ */ | ||
diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c new file mode 100644 index 000000000000..ff1194de34c0 --- /dev/null +++ b/drivers/media/dvb/frontends/stv0288.c | |||
| @@ -0,0 +1,618 @@ | |||
| 1 | /* | ||
| 2 | Driver for ST STV0288 demodulator | ||
| 3 | Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de | ||
| 4 | for Reel Multimedia | ||
| 5 | Copyright (C) 2008 TurboSight.com, Bob Liu <bob@turbosight.com> | ||
| 6 | Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by> | ||
| 7 | Removed stb6000 specific tuner code and revised some | ||
| 8 | procedures. | ||
| 9 | |||
| 10 | This program is free software; you can redistribute it and/or modify | ||
| 11 | it under the terms of the GNU General Public License as published by | ||
| 12 | the Free Software Foundation; either version 2 of the License, or | ||
| 13 | (at your option) any later version. | ||
| 14 | |||
| 15 | This program is distributed in the hope that it will be useful, | ||
| 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | GNU General Public License for more details. | ||
| 19 | |||
| 20 | You should have received a copy of the GNU General Public License | ||
| 21 | along with this program; if not, write to the Free Software | ||
| 22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 23 | |||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/kernel.h> | ||
| 28 | #include <linux/module.h> | ||
| 29 | #include <linux/string.h> | ||
| 30 | #include <linux/slab.h> | ||
| 31 | #include <linux/jiffies.h> | ||
| 32 | #include <asm/div64.h> | ||
| 33 | |||
| 34 | #include "dvb_frontend.h" | ||
| 35 | #include "stv0288.h" | ||
| 36 | |||
| 37 | struct stv0288_state { | ||
| 38 | struct i2c_adapter *i2c; | ||
| 39 | const struct stv0288_config *config; | ||
| 40 | struct dvb_frontend frontend; | ||
| 41 | |||
| 42 | u8 initialised:1; | ||
| 43 | u32 tuner_frequency; | ||
| 44 | u32 symbol_rate; | ||
| 45 | fe_code_rate_t fec_inner; | ||
| 46 | int errmode; | ||
| 47 | }; | ||
| 48 | |||
| 49 | #define STATUS_BER 0 | ||
| 50 | #define STATUS_UCBLOCKS 1 | ||
| 51 | |||
| 52 | static int debug; | ||
| 53 | static int debug_legacy_dish_switch; | ||
| 54 | #define dprintk(args...) \ | ||
| 55 | do { \ | ||
| 56 | if (debug) \ | ||
| 57 | printk(KERN_DEBUG "stv0288: " args); \ | ||
| 58 | } while (0) | ||
| 59 | |||
| 60 | |||
| 61 | static int stv0288_writeregI(struct stv0288_state *state, u8 reg, u8 data) | ||
| 62 | { | ||
| 63 | int ret; | ||
| 64 | u8 buf[] = { reg, data }; | ||
| 65 | struct i2c_msg msg = { | ||
| 66 | .addr = state->config->demod_address, | ||
| 67 | .flags = 0, | ||
| 68 | .buf = buf, | ||
| 69 | .len = 2 | ||
| 70 | }; | ||
| 71 | |||
| 72 | ret = i2c_transfer(state->i2c, &msg, 1); | ||
| 73 | |||
| 74 | if (ret != 1) | ||
| 75 | dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, " | ||
| 76 | "ret == %i)\n", __func__, reg, data, ret); | ||
| 77 | |||
| 78 | return (ret != 1) ? -EREMOTEIO : 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | static int stv0288_write(struct dvb_frontend *fe, u8 *buf, int len) | ||
| 82 | { | ||
| 83 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 84 | |||
| 85 | if (len != 2) | ||
| 86 | return -EINVAL; | ||
| 87 | |||
| 88 | return stv0288_writeregI(state, buf[0], buf[1]); | ||
| 89 | } | ||
| 90 | |||
| 91 | static u8 stv0288_readreg(struct stv0288_state *state, u8 reg) | ||
| 92 | { | ||
| 93 | int ret; | ||
| 94 | u8 b0[] = { reg }; | ||
| 95 | u8 b1[] = { 0 }; | ||
| 96 | struct i2c_msg msg[] = { | ||
| 97 | { | ||
| 98 | .addr = state->config->demod_address, | ||
| 99 | .flags = 0, | ||
| 100 | .buf = b0, | ||
| 101 | .len = 1 | ||
| 102 | }, { | ||
| 103 | .addr = state->config->demod_address, | ||
| 104 | .flags = I2C_M_RD, | ||
| 105 | .buf = b1, | ||
| 106 | .len = 1 | ||
| 107 | } | ||
| 108 | }; | ||
| 109 | |||
| 110 | ret = i2c_transfer(state->i2c, msg, 2); | ||
| 111 | |||
| 112 | if (ret != 2) | ||
| 113 | dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", | ||
| 114 | __func__, reg, ret); | ||
| 115 | |||
| 116 | return b1[0]; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate) | ||
| 120 | { | ||
| 121 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 122 | unsigned int temp; | ||
| 123 | unsigned char b[3]; | ||
| 124 | |||
| 125 | if ((srate < 1000000) || (srate > 45000000)) | ||
| 126 | return -EINVAL; | ||
| 127 | |||
| 128 | temp = (unsigned int)srate / 1000; | ||
| 129 | |||
| 130 | temp = temp * 32768; | ||
| 131 | temp = temp / 25; | ||
| 132 | temp = temp / 125; | ||
| 133 | b[0] = (unsigned char)((temp >> 12) & 0xff); | ||
| 134 | b[1] = (unsigned char)((temp >> 4) & 0xff); | ||
| 135 | b[2] = (unsigned char)((temp << 4) & 0xf0); | ||
| 136 | stv0288_writeregI(state, 0x28, 0x80); /* SFRH */ | ||
| 137 | stv0288_writeregI(state, 0x29, 0); /* SFRM */ | ||
| 138 | stv0288_writeregI(state, 0x2a, 0); /* SFRL */ | ||
| 139 | |||
| 140 | stv0288_writeregI(state, 0x28, b[0]); | ||
| 141 | stv0288_writeregI(state, 0x29, b[1]); | ||
| 142 | stv0288_writeregI(state, 0x2a, b[2]); | ||
| 143 | dprintk("stv0288: stv0288_set_symbolrate\n"); | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int stv0288_send_diseqc_msg(struct dvb_frontend *fe, | ||
| 149 | struct dvb_diseqc_master_cmd *m) | ||
| 150 | { | ||
| 151 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 152 | |||
| 153 | int i; | ||
| 154 | |||
| 155 | dprintk("%s\n", __func__); | ||
| 156 | |||
| 157 | stv0288_writeregI(state, 0x09, 0); | ||
| 158 | msleep(30); | ||
| 159 | stv0288_writeregI(state, 0x05, 0x16); | ||
| 160 | |||
| 161 | for (i = 0; i < m->msg_len; i++) { | ||
| 162 | if (stv0288_writeregI(state, 0x06, m->msg[i])) | ||
| 163 | return -EREMOTEIO; | ||
| 164 | msleep(12); | ||
| 165 | } | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | static int stv0288_send_diseqc_burst(struct dvb_frontend *fe, | ||
| 171 | fe_sec_mini_cmd_t burst) | ||
| 172 | { | ||
| 173 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 174 | |||
| 175 | dprintk("%s\n", __func__); | ||
| 176 | |||
| 177 | if (stv0288_writeregI(state, 0x05, 0x16))/* burst mode */ | ||
| 178 | return -EREMOTEIO; | ||
| 179 | |||
| 180 | if (stv0288_writeregI(state, 0x06, burst == SEC_MINI_A ? 0x00 : 0xff)) | ||
| 181 | return -EREMOTEIO; | ||
| 182 | |||
| 183 | if (stv0288_writeregI(state, 0x06, 0x12)) | ||
| 184 | return -EREMOTEIO; | ||
| 185 | |||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | |||
| 189 | static int stv0288_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | ||
| 190 | { | ||
| 191 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 192 | |||
| 193 | switch (tone) { | ||
| 194 | case SEC_TONE_ON: | ||
| 195 | if (stv0288_writeregI(state, 0x05, 0x10))/* burst mode */ | ||
| 196 | return -EREMOTEIO; | ||
| 197 | return stv0288_writeregI(state, 0x06, 0xff); | ||
| 198 | |||
| 199 | case SEC_TONE_OFF: | ||
| 200 | if (stv0288_writeregI(state, 0x05, 0x13))/* burst mode */ | ||
| 201 | return -EREMOTEIO; | ||
| 202 | return stv0288_writeregI(state, 0x06, 0x00); | ||
| 203 | |||
| 204 | default: | ||
| 205 | return -EINVAL; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | static u8 stv0288_inittab[] = { | ||
| 210 | 0x01, 0x15, | ||
| 211 | 0x02, 0x20, | ||
| 212 | 0x09, 0x0, | ||
| 213 | 0x0a, 0x4, | ||
| 214 | 0x0b, 0x0, | ||
| 215 | 0x0c, 0x0, | ||
| 216 | 0x0d, 0x0, | ||
| 217 | 0x0e, 0xd4, | ||
| 218 | 0x0f, 0x30, | ||
| 219 | 0x11, 0x80, | ||
| 220 | 0x12, 0x03, | ||
| 221 | 0x13, 0x48, | ||
| 222 | 0x14, 0x84, | ||
| 223 | 0x15, 0x45, | ||
| 224 | 0x16, 0xb7, | ||
| 225 | 0x17, 0x9c, | ||
| 226 | 0x18, 0x0, | ||
| 227 | 0x19, 0xa6, | ||
| 228 | 0x1a, 0x88, | ||
| 229 | 0x1b, 0x8f, | ||
| 230 | 0x1c, 0xf0, | ||
| 231 | 0x20, 0x0b, | ||
| 232 | 0x21, 0x54, | ||
| 233 | 0x22, 0x0, | ||
| 234 | 0x23, 0x0, | ||
| 235 | 0x2b, 0xff, | ||
| 236 | 0x2c, 0xf7, | ||
| 237 | 0x30, 0x0, | ||
| 238 | 0x31, 0x1e, | ||
| 239 | 0x32, 0x14, | ||
| 240 | 0x33, 0x0f, | ||
| 241 | 0x34, 0x09, | ||
| 242 | 0x35, 0x0c, | ||
| 243 | 0x36, 0x05, | ||
| 244 | 0x37, 0x2f, | ||
| 245 | 0x38, 0x16, | ||
| 246 | 0x39, 0xbe, | ||
| 247 | 0x3a, 0x0, | ||
| 248 | 0x3b, 0x13, | ||
| 249 | 0x3c, 0x11, | ||
| 250 | 0x3d, 0x30, | ||
| 251 | 0x40, 0x63, | ||
| 252 | 0x41, 0x04, | ||
| 253 | 0x42, 0x60, | ||
| 254 | 0x43, 0x00, | ||
| 255 | 0x44, 0x00, | ||
| 256 | 0x45, 0x00, | ||
| 257 | 0x46, 0x00, | ||
| 258 | 0x47, 0x00, | ||
| 259 | 0x4a, 0x00, | ||
| 260 | 0x50, 0x10, | ||
| 261 | 0x51, 0x38, | ||
| 262 | 0x52, 0x21, | ||
| 263 | 0x58, 0x54, | ||
| 264 | 0x59, 0x86, | ||
| 265 | 0x5a, 0x0, | ||
| 266 | 0x5b, 0x9b, | ||
| 267 | 0x5c, 0x08, | ||
| 268 | 0x5d, 0x7f, | ||
| 269 | 0x5e, 0x0, | ||
| 270 | 0x5f, 0xff, | ||
| 271 | 0x70, 0x0, | ||
| 272 | 0x71, 0x0, | ||
| 273 | 0x72, 0x0, | ||
| 274 | 0x74, 0x0, | ||
| 275 | 0x75, 0x0, | ||
| 276 | 0x76, 0x0, | ||
| 277 | 0x81, 0x0, | ||
| 278 | 0x82, 0x3f, | ||
| 279 | 0x83, 0x3f, | ||
| 280 | 0x84, 0x0, | ||
| 281 | 0x85, 0x0, | ||
| 282 | 0x88, 0x0, | ||
| 283 | 0x89, 0x0, | ||
| 284 | 0x8a, 0x0, | ||
| 285 | 0x8b, 0x0, | ||
| 286 | 0x8c, 0x0, | ||
| 287 | 0x90, 0x0, | ||
| 288 | 0x91, 0x0, | ||
| 289 | 0x92, 0x0, | ||
| 290 | 0x93, 0x0, | ||
| 291 | 0x94, 0x1c, | ||
| 292 | 0x97, 0x0, | ||
| 293 | 0xa0, 0x48, | ||
| 294 | 0xa1, 0x0, | ||
| 295 | 0xb0, 0xb8, | ||
| 296 | 0xb1, 0x3a, | ||
| 297 | 0xb2, 0x10, | ||
| 298 | 0xb3, 0x82, | ||
| 299 | 0xb4, 0x80, | ||
| 300 | 0xb5, 0x82, | ||
| 301 | 0xb6, 0x82, | ||
| 302 | 0xb7, 0x82, | ||
| 303 | 0xb8, 0x20, | ||
| 304 | 0xb9, 0x0, | ||
| 305 | 0xf0, 0x0, | ||
| 306 | 0xf1, 0x0, | ||
| 307 | 0xf2, 0xc0, | ||
| 308 | 0x51, 0x36, | ||
| 309 | 0x52, 0x09, | ||
| 310 | 0x53, 0x94, | ||
| 311 | 0x54, 0x62, | ||
| 312 | 0x55, 0x29, | ||
| 313 | 0x56, 0x64, | ||
| 314 | 0x57, 0x2b, | ||
| 315 | 0xff, 0xff, | ||
| 316 | }; | ||
| 317 | |||
| 318 | static int stv0288_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt) | ||
| 319 | { | ||
| 320 | dprintk("%s: %s\n", __func__, | ||
| 321 | volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : | ||
| 322 | volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); | ||
| 323 | |||
| 324 | return 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | static int stv0288_init(struct dvb_frontend *fe) | ||
| 328 | { | ||
| 329 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 330 | int i; | ||
| 331 | u8 reg; | ||
| 332 | u8 val; | ||
| 333 | |||
| 334 | dprintk("stv0288: init chip\n"); | ||
| 335 | stv0288_writeregI(state, 0x41, 0x04); | ||
| 336 | msleep(50); | ||
| 337 | |||
| 338 | /* we have default inittab */ | ||
| 339 | if (state->config->inittab == NULL) { | ||
| 340 | for (i = 0; !(stv0288_inittab[i] == 0xff && | ||
| 341 | stv0288_inittab[i + 1] == 0xff); i += 2) | ||
| 342 | stv0288_writeregI(state, stv0288_inittab[i], | ||
| 343 | stv0288_inittab[i + 1]); | ||
| 344 | } else { | ||
| 345 | for (i = 0; ; i += 2) { | ||
| 346 | reg = state->config->inittab[i]; | ||
| 347 | val = state->config->inittab[i+1]; | ||
| 348 | if (reg == 0xff && val == 0xff) | ||
| 349 | break; | ||
| 350 | stv0288_writeregI(state, reg, val); | ||
| 351 | } | ||
| 352 | } | ||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | |||
| 356 | static int stv0288_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
| 357 | { | ||
| 358 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 359 | |||
| 360 | u8 sync = stv0288_readreg(state, 0x24); | ||
| 361 | if (sync == 255) | ||
| 362 | sync = 0; | ||
| 363 | |||
| 364 | dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync); | ||
| 365 | |||
| 366 | *status = 0; | ||
| 367 | |||
| 368 | if ((sync & 0x08) == 0x08) { | ||
| 369 | *status |= FE_HAS_LOCK; | ||
| 370 | dprintk("stv0288 has locked\n"); | ||
| 371 | } | ||
| 372 | |||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | static int stv0288_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
| 377 | { | ||
| 378 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 379 | |||
| 380 | if (state->errmode != STATUS_BER) | ||
| 381 | return 0; | ||
| 382 | *ber = (stv0288_readreg(state, 0x26) << 8) | | ||
| 383 | stv0288_readreg(state, 0x27); | ||
| 384 | dprintk("stv0288_read_ber %d\n", *ber); | ||
| 385 | |||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | |||
| 389 | |||
| 390 | static int stv0288_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
| 391 | { | ||
| 392 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 393 | |||
| 394 | s32 signal = 0xffff - ((stv0288_readreg(state, 0x10) << 8)); | ||
| 395 | |||
| 396 | |||
| 397 | signal = signal * 5 / 4; | ||
| 398 | *strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal; | ||
| 399 | dprintk("stv0288_read_signal_strength %d\n", *strength); | ||
| 400 | |||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | static int stv0288_sleep(struct dvb_frontend *fe) | ||
| 404 | { | ||
| 405 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 406 | |||
| 407 | stv0288_writeregI(state, 0x41, 0x84); | ||
| 408 | state->initialised = 0; | ||
| 409 | |||
| 410 | return 0; | ||
| 411 | } | ||
| 412 | static int stv0288_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
| 413 | { | ||
| 414 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 415 | |||
| 416 | s32 xsnr = 0xffff - ((stv0288_readreg(state, 0x2d) << 8) | ||
| 417 | | stv0288_readreg(state, 0x2e)); | ||
| 418 | xsnr = 3 * (xsnr - 0xa100); | ||
| 419 | *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr; | ||
| 420 | dprintk("stv0288_read_snr %d\n", *snr); | ||
| 421 | |||
| 422 | return 0; | ||
| 423 | } | ||
| 424 | |||
| 425 | static int stv0288_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
| 426 | { | ||
| 427 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 428 | |||
| 429 | if (state->errmode != STATUS_BER) | ||
| 430 | return 0; | ||
| 431 | *ucblocks = (stv0288_readreg(state, 0x26) << 8) | | ||
| 432 | stv0288_readreg(state, 0x27); | ||
| 433 | dprintk("stv0288_read_ber %d\n", *ucblocks); | ||
| 434 | |||
| 435 | return 0; | ||
| 436 | } | ||
| 437 | |||
| 438 | static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p) | ||
| 439 | { | ||
| 440 | dprintk("%s(..)\n", __func__); | ||
| 441 | return 0; | ||
| 442 | } | ||
| 443 | |||
| 444 | static int stv0288_get_property(struct dvb_frontend *fe, struct dtv_property *p) | ||
| 445 | { | ||
| 446 | dprintk("%s(..)\n", __func__); | ||
| 447 | return 0; | ||
| 448 | } | ||
| 449 | |||
| 450 | static int stv0288_set_frontend(struct dvb_frontend *fe, | ||
| 451 | struct dvb_frontend_parameters *dfp) | ||
| 452 | { | ||
| 453 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 454 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 455 | |||
| 456 | char tm; | ||
| 457 | unsigned char tda[3]; | ||
| 458 | |||
| 459 | dprintk("%s : FE_SET_FRONTEND\n", __func__); | ||
| 460 | |||
| 461 | if (c->delivery_system != SYS_DVBS) { | ||
| 462 | dprintk("%s: unsupported delivery " | ||
| 463 | "system selected (%d)\n", | ||
| 464 | __func__, c->delivery_system); | ||
| 465 | return -EOPNOTSUPP; | ||
| 466 | } | ||
| 467 | |||
| 468 | if (state->config->set_ts_params) | ||
| 469 | state->config->set_ts_params(fe, 0); | ||
| 470 | |||
| 471 | /* only frequency & symbol_rate are used for tuner*/ | ||
| 472 | dfp->frequency = c->frequency; | ||
| 473 | dfp->u.qpsk.symbol_rate = c->symbol_rate; | ||
| 474 | if (fe->ops.tuner_ops.set_params) { | ||
| 475 | fe->ops.tuner_ops.set_params(fe, dfp); | ||
| 476 | if (fe->ops.i2c_gate_ctrl) | ||
| 477 | fe->ops.i2c_gate_ctrl(fe, 0); | ||
| 478 | } | ||
| 479 | |||
| 480 | udelay(10); | ||
| 481 | stv0288_set_symbolrate(fe, c->symbol_rate); | ||
| 482 | /* Carrier lock control register */ | ||
| 483 | stv0288_writeregI(state, 0x15, 0xc5); | ||
| 484 | |||
| 485 | tda[0] = 0x2b; /* CFRM */ | ||
| 486 | tda[2] = 0x0; /* CFRL */ | ||
| 487 | for (tm = -6; tm < 7;) { | ||
| 488 | /* Viterbi status */ | ||
| 489 | if (stv0288_readreg(state, 0x24) & 0x80) | ||
| 490 | break; | ||
| 491 | |||
| 492 | tda[2] += 40; | ||
| 493 | if (tda[2] < 40) | ||
| 494 | tm++; | ||
| 495 | tda[1] = (unsigned char)tm; | ||
| 496 | stv0288_writeregI(state, 0x2b, tda[1]); | ||
| 497 | stv0288_writeregI(state, 0x2c, tda[2]); | ||
| 498 | udelay(30); | ||
| 499 | } | ||
| 500 | |||
| 501 | state->tuner_frequency = c->frequency; | ||
| 502 | state->fec_inner = FEC_AUTO; | ||
| 503 | state->symbol_rate = c->symbol_rate; | ||
| 504 | |||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | |||
| 508 | static int stv0288_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | ||
| 509 | { | ||
| 510 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 511 | |||
| 512 | if (enable) | ||
| 513 | stv0288_writeregI(state, 0x01, 0xb5); | ||
| 514 | else | ||
| 515 | stv0288_writeregI(state, 0x01, 0x35); | ||
| 516 | |||
| 517 | udelay(1); | ||
| 518 | |||
| 519 | return 0; | ||
| 520 | } | ||
| 521 | |||
| 522 | static void stv0288_release(struct dvb_frontend *fe) | ||
| 523 | { | ||
| 524 | struct stv0288_state *state = fe->demodulator_priv; | ||
| 525 | kfree(state); | ||
| 526 | } | ||
| 527 | |||
| 528 | static struct dvb_frontend_ops stv0288_ops = { | ||
| 529 | |||
| 530 | .info = { | ||
| 531 | .name = "ST STV0288 DVB-S", | ||
| 532 | .type = FE_QPSK, | ||
| 533 | .frequency_min = 950000, | ||
| 534 | .frequency_max = 2150000, | ||
| 535 | .frequency_stepsize = 1000, /* kHz for QPSK frontends */ | ||
| 536 | .frequency_tolerance = 0, | ||
| 537 | .symbol_rate_min = 1000000, | ||
| 538 | .symbol_rate_max = 45000000, | ||
| 539 | .symbol_rate_tolerance = 500, /* ppm */ | ||
| 540 | .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 541 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | | ||
| 542 | FE_CAN_QPSK | | ||
| 543 | FE_CAN_FEC_AUTO | ||
| 544 | }, | ||
| 545 | |||
| 546 | .release = stv0288_release, | ||
| 547 | .init = stv0288_init, | ||
| 548 | .sleep = stv0288_sleep, | ||
| 549 | .write = stv0288_write, | ||
| 550 | .i2c_gate_ctrl = stv0288_i2c_gate_ctrl, | ||
| 551 | .read_status = stv0288_read_status, | ||
| 552 | .read_ber = stv0288_read_ber, | ||
| 553 | .read_signal_strength = stv0288_read_signal_strength, | ||
| 554 | .read_snr = stv0288_read_snr, | ||
| 555 | .read_ucblocks = stv0288_read_ucblocks, | ||
| 556 | .diseqc_send_master_cmd = stv0288_send_diseqc_msg, | ||
| 557 | .diseqc_send_burst = stv0288_send_diseqc_burst, | ||
| 558 | .set_tone = stv0288_set_tone, | ||
| 559 | .set_voltage = stv0288_set_voltage, | ||
| 560 | |||
| 561 | .set_property = stv0288_set_property, | ||
| 562 | .get_property = stv0288_get_property, | ||
| 563 | .set_frontend = stv0288_set_frontend, | ||
| 564 | }; | ||
| 565 | |||
| 566 | struct dvb_frontend *stv0288_attach(const struct stv0288_config *config, | ||
| 567 | struct i2c_adapter *i2c) | ||
| 568 | { | ||
| 569 | struct stv0288_state *state = NULL; | ||
| 570 | int id; | ||
| 571 | |||
| 572 | /* allocate memory for the internal state */ | ||
| 573 | state = kmalloc(sizeof(struct stv0288_state), GFP_KERNEL); | ||
| 574 | if (state == NULL) | ||
| 575 | goto error; | ||
| 576 | |||
| 577 | /* setup the state */ | ||
| 578 | state->config = config; | ||
| 579 | state->i2c = i2c; | ||
| 580 | state->initialised = 0; | ||
| 581 | state->tuner_frequency = 0; | ||
| 582 | state->symbol_rate = 0; | ||
| 583 | state->fec_inner = 0; | ||
| 584 | state->errmode = STATUS_BER; | ||
| 585 | |||
| 586 | stv0288_writeregI(state, 0x41, 0x04); | ||
| 587 | msleep(200); | ||
| 588 | id = stv0288_readreg(state, 0x00); | ||
| 589 | dprintk("stv0288 id %x\n", id); | ||
| 590 | |||
| 591 | /* register 0x00 contains 0x11 for STV0288 */ | ||
| 592 | if (id != 0x11) | ||
| 593 | goto error; | ||
| 594 | |||
| 595 | /* create dvb_frontend */ | ||
| 596 | memcpy(&state->frontend.ops, &stv0288_ops, | ||
| 597 | sizeof(struct dvb_frontend_ops)); | ||
| 598 | state->frontend.demodulator_priv = state; | ||
| 599 | return &state->frontend; | ||
| 600 | |||
| 601 | error: | ||
| 602 | kfree(state); | ||
| 603 | |||
| 604 | return NULL; | ||
| 605 | } | ||
| 606 | EXPORT_SYMBOL(stv0288_attach); | ||
| 607 | |||
| 608 | module_param(debug_legacy_dish_switch, int, 0444); | ||
| 609 | MODULE_PARM_DESC(debug_legacy_dish_switch, | ||
| 610 | "Enable timing analysis for Dish Network legacy switches"); | ||
| 611 | |||
| 612 | module_param(debug, int, 0644); | ||
| 613 | MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); | ||
| 614 | |||
| 615 | MODULE_DESCRIPTION("ST STV0288 DVB Demodulator driver"); | ||
| 616 | MODULE_AUTHOR("Georg Acher, Bob Liu, Igor liplianin"); | ||
| 617 | MODULE_LICENSE("GPL"); | ||
| 618 | |||
diff --git a/drivers/media/dvb/frontends/stv0288.h b/drivers/media/dvb/frontends/stv0288.h new file mode 100644 index 000000000000..f2b53db0606d --- /dev/null +++ b/drivers/media/dvb/frontends/stv0288.h | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | /* | ||
| 2 | Driver for ST STV0288 demodulator | ||
| 3 | |||
| 4 | Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de | ||
| 5 | for Reel Multimedia | ||
| 6 | Copyright (C) 2008 TurboSight.com, <bob@turbosight.com> | ||
| 7 | Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by> | ||
| 8 | Removed stb6000 specific tuner code and revised some | ||
| 9 | procedures. | ||
| 10 | |||
| 11 | This program is free software; you can redistribute it and/or modify | ||
| 12 | it under the terms of the GNU General Public License as published by | ||
| 13 | the Free Software Foundation; either version 2 of the License, or | ||
| 14 | (at your option) any later version. | ||
| 15 | |||
| 16 | This program is distributed in the hope that it will be useful, | ||
| 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | GNU General Public License for more details. | ||
| 20 | |||
| 21 | You should have received a copy of the GNU General Public License | ||
| 22 | along with this program; if not, write to the Free Software | ||
| 23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | |||
| 25 | */ | ||
| 26 | |||
| 27 | #ifndef STV0288_H | ||
| 28 | #define STV0288_H | ||
| 29 | |||
| 30 | #include <linux/dvb/frontend.h> | ||
| 31 | #include "dvb_frontend.h" | ||
| 32 | |||
| 33 | struct stv0288_config { | ||
| 34 | /* the demodulator's i2c address */ | ||
| 35 | u8 demod_address; | ||
| 36 | |||
| 37 | u8* inittab; | ||
| 38 | |||
| 39 | /* minimum delay before retuning */ | ||
| 40 | int min_delay_ms; | ||
| 41 | |||
| 42 | int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); | ||
| 43 | }; | ||
| 44 | |||
| 45 | #if defined(CONFIG_DVB_STV0288) || (defined(CONFIG_DVB_STV0288_MODULE) && \ | ||
| 46 | defined(MODULE)) | ||
| 47 | extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config, | ||
| 48 | struct i2c_adapter *i2c); | ||
| 49 | #else | ||
| 50 | static inline struct dvb_frontend *stv0288_attach(const struct stv0288_config *config, | ||
| 51 | struct i2c_adapter *i2c) | ||
| 52 | { | ||
| 53 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
| 54 | return NULL; | ||
| 55 | } | ||
| 56 | #endif /* CONFIG_DVB_STV0288 */ | ||
| 57 | |||
| 58 | static inline int stv0288_writereg(struct dvb_frontend *fe, u8 reg, u8 val) | ||
| 59 | { | ||
| 60 | int r = 0; | ||
| 61 | u8 buf[] = { reg, val }; | ||
| 62 | if (fe->ops.write) | ||
| 63 | r = fe->ops.write(fe, buf, 2); | ||
| 64 | return r; | ||
| 65 | } | ||
| 66 | |||
| 67 | #endif /* STV0288_H */ | ||
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 35435bef8e79..6c1cb1973c6e 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c | |||
| @@ -559,6 +559,8 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par | |||
| 559 | int invval = 0; | 559 | int invval = 0; |
| 560 | 560 | ||
| 561 | dprintk ("%s : FE_SET_FRONTEND\n", __func__); | 561 | dprintk ("%s : FE_SET_FRONTEND\n", __func__); |
| 562 | if (state->config->set_ts_params) | ||
| 563 | state->config->set_ts_params(fe, 0); | ||
| 562 | 564 | ||
| 563 | // set the inversion | 565 | // set the inversion |
| 564 | if (p->inversion == INVERSION_OFF) invval = 0; | 566 | if (p->inversion == INVERSION_OFF) invval = 0; |
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h index 3282f43022f5..0fd96e22b650 100644 --- a/drivers/media/dvb/frontends/stv0299.h +++ b/drivers/media/dvb/frontends/stv0299.h | |||
| @@ -89,15 +89,18 @@ struct stv0299_config | |||
| 89 | int min_delay_ms; | 89 | int min_delay_ms; |
| 90 | 90 | ||
| 91 | /* Set the symbol rate */ | 91 | /* Set the symbol rate */ |
| 92 | int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio); | 92 | int (*set_symbol_rate)(struct dvb_frontend *fe, u32 srate, u32 ratio); |
| 93 | |||
| 94 | /* Set device param to start dma */ | ||
| 95 | int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); | ||
| 93 | }; | 96 | }; |
| 94 | 97 | ||
| 95 | #if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE)) | 98 | #if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE)) |
| 96 | extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, | 99 | extern struct dvb_frontend *stv0299_attach(const struct stv0299_config *config, |
| 97 | struct i2c_adapter* i2c); | 100 | struct i2c_adapter *i2c); |
| 98 | #else | 101 | #else |
| 99 | static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, | 102 | static inline struct dvb_frontend *stv0299_attach(const struct stv0299_config *config, |
| 100 | struct i2c_adapter* i2c) | 103 | struct i2c_adapter *i2c) |
| 101 | { | 104 | { |
| 102 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 105 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
| 103 | return NULL; | 106 | return NULL; |
diff --git a/drivers/media/dvb/frontends/tdhd1.h b/drivers/media/dvb/frontends/tdhd1.h new file mode 100644 index 000000000000..51f170678650 --- /dev/null +++ b/drivers/media/dvb/frontends/tdhd1.h | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | /* | ||
| 2 | * tdhd1.h - ALPS TDHD1-204A tuner support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Oliver Endriss <o.endriss@gmx.de> | ||
| 5 | * | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License | ||
| 9 | * as published by the Free Software Foundation; either version 2 | ||
| 10 | * of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 20 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
| 21 | * | ||
| 22 | * | ||
| 23 | * The project's page is at http://www.linuxtv.org | ||
| 24 | */ | ||
| 25 | |||
| 26 | #ifndef TDHD1_H | ||
| 27 | #define TDHD1_H | ||
| 28 | |||
| 29 | #include "tda1004x.h" | ||
| 30 | |||
| 31 | static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name); | ||
| 32 | |||
| 33 | static struct tda1004x_config alps_tdhd1_204a_config = { | ||
| 34 | .demod_address = 0x8, | ||
| 35 | .invert = 1, | ||
| 36 | .invert_oclk = 0, | ||
| 37 | .xtal_freq = TDA10046_XTAL_4M, | ||
| 38 | .agc_config = TDA10046_AGC_DEFAULT, | ||
| 39 | .if_freq = TDA10046_FREQ_3617, | ||
| 40 | .request_firmware = alps_tdhd1_204_request_firmware | ||
| 41 | }; | ||
| 42 | |||
| 43 | static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | ||
| 44 | { | ||
| 45 | struct i2c_adapter *i2c = fe->tuner_priv; | ||
| 46 | u8 data[4]; | ||
| 47 | struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; | ||
| 48 | u32 div; | ||
| 49 | |||
| 50 | div = (params->frequency + 36166666) / 166666; | ||
| 51 | |||
| 52 | data[0] = (div >> 8) & 0x7f; | ||
| 53 | data[1] = div & 0xff; | ||
| 54 | data[2] = 0x85; | ||
| 55 | |||
| 56 | if (params->frequency >= 174000000 && params->frequency <= 230000000) | ||
| 57 | data[3] = 0x02; | ||
| 58 | else if (params->frequency >= 470000000 && params->frequency <= 823000000) | ||
| 59 | data[3] = 0x0C; | ||
| 60 | else if (params->frequency > 823000000 && params->frequency <= 862000000) | ||
| 61 | data[3] = 0x8C; | ||
| 62 | else | ||
| 63 | return -EINVAL; | ||
| 64 | |||
| 65 | if (fe->ops.i2c_gate_ctrl) | ||
| 66 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
| 67 | if (i2c_transfer(i2c, &msg, 1) != 1) | ||
| 68 | return -EIO; | ||
| 69 | |||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | #endif /* TDHD1_H */ | ||
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 41b5a988b619..867027ceab3e 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
| @@ -86,6 +86,7 @@ config DVB_BUDGET | |||
| 86 | select DVB_TDA10086 if !DVB_FE_CUSTOMISE | 86 | select DVB_TDA10086 if !DVB_FE_CUSTOMISE |
| 87 | select DVB_TDA826X if !DVB_FE_CUSTOMISE | 87 | select DVB_TDA826X if !DVB_FE_CUSTOMISE |
| 88 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | 88 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE |
| 89 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE | ||
| 89 | help | 90 | help |
| 90 | Support for simple SAA7146 based DVB cards (so called Budget- | 91 | Support for simple SAA7146 based DVB cards (so called Budget- |
| 91 | or Nova-PCI cards) without onboard MPEG2 decoder, and without | 92 | or Nova-PCI cards) without onboard MPEG2 decoder, and without |
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 0777e8f9544b..c7c770c28988 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c | |||
| @@ -88,6 +88,7 @@ static int budgetpatch; | |||
| 88 | static int wss_cfg_4_3 = 0x4008; | 88 | static int wss_cfg_4_3 = 0x4008; |
| 89 | static int wss_cfg_16_9 = 0x0007; | 89 | static int wss_cfg_16_9 = 0x0007; |
| 90 | static int tv_standard; | 90 | static int tv_standard; |
| 91 | static int full_ts; | ||
| 91 | 92 | ||
| 92 | module_param_named(debug, av7110_debug, int, 0644); | 93 | module_param_named(debug, av7110_debug, int, 0644); |
| 93 | MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); | 94 | MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)"); |
| @@ -106,6 +107,8 @@ module_param(volume, int, 0444); | |||
| 106 | MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)"); | 107 | MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)"); |
| 107 | module_param(budgetpatch, int, 0444); | 108 | module_param(budgetpatch, int, 0444); |
| 108 | MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)"); | 109 | MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)"); |
| 110 | module_param(full_ts, int, 0444); | ||
| 111 | MODULE_PARM_DESC(full_ts, "enable code for full-ts hardware modification: 0 disable (default), 1 enable"); | ||
| 109 | module_param(wss_cfg_4_3, int, 0444); | 112 | module_param(wss_cfg_4_3, int, 0444); |
| 110 | MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data"); | 113 | MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data"); |
| 111 | module_param(wss_cfg_16_9, int, 0444); | 114 | module_param(wss_cfg_16_9, int, 0444); |
| @@ -116,6 +119,8 @@ MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC"); | |||
| 116 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 119 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 117 | 120 | ||
| 118 | static void restart_feeds(struct av7110 *av7110); | 121 | static void restart_feeds(struct av7110 *av7110); |
| 122 | static int budget_start_feed(struct dvb_demux_feed *feed); | ||
| 123 | static int budget_stop_feed(struct dvb_demux_feed *feed); | ||
| 119 | 124 | ||
| 120 | static int av7110_num; | 125 | static int av7110_num; |
| 121 | 126 | ||
| @@ -376,9 +381,9 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir, | |||
| 376 | irdebi(av7110, DEBISWAB, addr, 0, len); | 381 | irdebi(av7110, DEBISWAB, addr, 0, len); |
| 377 | } | 382 | } |
| 378 | 383 | ||
| 379 | static void debiirq(unsigned long data) | 384 | static void debiirq(unsigned long cookie) |
| 380 | { | 385 | { |
| 381 | struct av7110 *av7110 = (struct av7110 *) data; | 386 | struct av7110 *av7110 = (struct av7110 *)cookie; |
| 382 | int type = av7110->debitype; | 387 | int type = av7110->debitype; |
| 383 | int handle = (type >> 8) & 0x1f; | 388 | int handle = (type >> 8) & 0x1f; |
| 384 | unsigned int xfer = 0; | 389 | unsigned int xfer = 0; |
| @@ -487,9 +492,9 @@ debi_done: | |||
| 487 | } | 492 | } |
| 488 | 493 | ||
| 489 | /* irq from av7110 firmware writing the mailbox register in the DPRAM */ | 494 | /* irq from av7110 firmware writing the mailbox register in the DPRAM */ |
| 490 | static void gpioirq(unsigned long data) | 495 | static void gpioirq(unsigned long cookie) |
| 491 | { | 496 | { |
| 492 | struct av7110 *av7110 = (struct av7110 *) data; | 497 | struct av7110 *av7110 = (struct av7110 *)cookie; |
| 493 | u32 rxbuf, txbuf; | 498 | u32 rxbuf, txbuf; |
| 494 | int len; | 499 | int len; |
| 495 | 500 | ||
| @@ -806,6 +811,9 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) | |||
| 806 | 811 | ||
| 807 | dprintk(4, "%p\n", av7110); | 812 | dprintk(4, "%p\n", av7110); |
| 808 | 813 | ||
| 814 | if (av7110->full_ts) | ||
| 815 | return 0; | ||
| 816 | |||
| 809 | if (dvbdmxfilter->type == DMX_TYPE_SEC) { | 817 | if (dvbdmxfilter->type == DMX_TYPE_SEC) { |
| 810 | if (hw_sections) { | 818 | if (hw_sections) { |
| 811 | buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) | | 819 | buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) | |
| @@ -854,6 +862,9 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) | |||
| 854 | 862 | ||
| 855 | dprintk(4, "%p\n", av7110); | 863 | dprintk(4, "%p\n", av7110); |
| 856 | 864 | ||
| 865 | if (av7110->full_ts) | ||
| 866 | return 0; | ||
| 867 | |||
| 857 | handle = dvbdmxfilter->hw_handle; | 868 | handle = dvbdmxfilter->hw_handle; |
| 858 | if (handle >= 32) { | 869 | if (handle >= 32) { |
| 859 | printk("%s tried to stop invalid filter %04x, filter type = %x\n", | 870 | printk("%s tried to stop invalid filter %04x, filter type = %x\n", |
| @@ -913,7 +924,7 @@ static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed) | |||
| 913 | return ret; | 924 | return ret; |
| 914 | } | 925 | } |
| 915 | 926 | ||
| 916 | if ((dvbdmxfeed->ts_type & TS_PACKET)) { | 927 | if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) { |
| 917 | if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000)) | 928 | if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000)) |
| 918 | ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed); | 929 | ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed); |
| 919 | if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000)) | 930 | if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000)) |
| @@ -974,7 +985,7 @@ static int av7110_start_feed(struct dvb_demux_feed *feed) | |||
| 974 | if (!demux->dmx.frontend) | 985 | if (!demux->dmx.frontend) |
| 975 | return -EINVAL; | 986 | return -EINVAL; |
| 976 | 987 | ||
| 977 | if (feed->pid > 0x1fff) | 988 | if (!av7110->full_ts && feed->pid > 0x1fff) |
| 978 | return -EINVAL; | 989 | return -EINVAL; |
| 979 | 990 | ||
| 980 | if (feed->type == DMX_TYPE_TS) { | 991 | if (feed->type == DMX_TYPE_TS) { |
| @@ -1003,7 +1014,12 @@ static int av7110_start_feed(struct dvb_demux_feed *feed) | |||
| 1003 | } | 1014 | } |
| 1004 | } | 1015 | } |
| 1005 | 1016 | ||
| 1006 | else if (feed->type == DMX_TYPE_SEC) { | 1017 | if (av7110->full_ts) { |
| 1018 | budget_start_feed(feed); | ||
| 1019 | return ret; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | if (feed->type == DMX_TYPE_SEC) { | ||
| 1007 | int i; | 1023 | int i; |
| 1008 | 1024 | ||
| 1009 | for (i = 0; i < demux->filternum; i++) { | 1025 | for (i = 0; i < demux->filternum; i++) { |
| @@ -1050,7 +1066,12 @@ static int av7110_stop_feed(struct dvb_demux_feed *feed) | |||
| 1050 | ret = StopHWFilter(feed->filter); | 1066 | ret = StopHWFilter(feed->filter); |
| 1051 | } | 1067 | } |
| 1052 | 1068 | ||
| 1053 | if (!ret && feed->type == DMX_TYPE_SEC) { | 1069 | if (av7110->full_ts) { |
| 1070 | budget_stop_feed(feed); | ||
| 1071 | return ret; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | if (feed->type == DMX_TYPE_SEC) { | ||
| 1054 | for (i = 0; i<demux->filternum; i++) { | 1075 | for (i = 0; i<demux->filternum; i++) { |
| 1055 | if (demux->filter[i].state == DMX_STATE_GO && | 1076 | if (demux->filter[i].state == DMX_STATE_GO && |
| 1056 | demux->filter[i].filter.parent == &feed->feed.sec) { | 1077 | demux->filter[i].filter.parent == &feed->feed.sec) { |
| @@ -1074,6 +1095,7 @@ static void restart_feeds(struct av7110 *av7110) | |||
| 1074 | struct dvb_demux *dvbdmx = &av7110->demux; | 1095 | struct dvb_demux *dvbdmx = &av7110->demux; |
| 1075 | struct dvb_demux_feed *feed; | 1096 | struct dvb_demux_feed *feed; |
| 1076 | int mode; | 1097 | int mode; |
| 1098 | int feeding; | ||
| 1077 | int i, j; | 1099 | int i, j; |
| 1078 | 1100 | ||
| 1079 | dprintk(4, "%p\n", av7110); | 1101 | dprintk(4, "%p\n", av7110); |
| @@ -1082,6 +1104,8 @@ static void restart_feeds(struct av7110 *av7110) | |||
| 1082 | av7110->playing = 0; | 1104 | av7110->playing = 0; |
| 1083 | av7110->rec_mode = 0; | 1105 | av7110->rec_mode = 0; |
| 1084 | 1106 | ||
| 1107 | feeding = av7110->feeding1; /* full_ts mod */ | ||
| 1108 | |||
| 1085 | for (i = 0; i < dvbdmx->feednum; i++) { | 1109 | for (i = 0; i < dvbdmx->feednum; i++) { |
| 1086 | feed = &dvbdmx->feed[i]; | 1110 | feed = &dvbdmx->feed[i]; |
| 1087 | if (feed->state == DMX_STATE_GO) { | 1111 | if (feed->state == DMX_STATE_GO) { |
| @@ -1099,6 +1123,8 @@ static void restart_feeds(struct av7110 *av7110) | |||
| 1099 | } | 1123 | } |
| 1100 | } | 1124 | } |
| 1101 | 1125 | ||
| 1126 | av7110->feeding1 = feeding; /* full_ts mod */ | ||
| 1127 | |||
| 1102 | if (mode) | 1128 | if (mode) |
| 1103 | av7110_av_start_play(av7110, mode); | 1129 | av7110_av_start_play(av7110, mode); |
| 1104 | } | 1130 | } |
| @@ -1197,8 +1223,9 @@ static int start_ts_capture(struct av7110 *budget) | |||
| 1197 | 1223 | ||
| 1198 | if (budget->feeding1) | 1224 | if (budget->feeding1) |
| 1199 | return ++budget->feeding1; | 1225 | return ++budget->feeding1; |
| 1200 | memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH); | 1226 | memset(budget->grabbing, 0x00, TS_BUFLEN); |
| 1201 | budget->ttbp = 0; | 1227 | budget->ttbp = 0; |
| 1228 | SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */ | ||
| 1202 | SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */ | 1229 | SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */ |
| 1203 | saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */ | 1230 | saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */ |
| 1204 | return ++budget->feeding1; | 1231 | return ++budget->feeding1; |
| @@ -1233,18 +1260,14 @@ static int budget_stop_feed(struct dvb_demux_feed *feed) | |||
| 1233 | return status; | 1260 | return status; |
| 1234 | } | 1261 | } |
| 1235 | 1262 | ||
| 1236 | static void vpeirq(unsigned long data) | 1263 | static void vpeirq(unsigned long cookie) |
| 1237 | { | 1264 | { |
| 1238 | struct av7110 *budget = (struct av7110 *) data; | 1265 | struct av7110 *budget = (struct av7110 *)cookie; |
| 1239 | u8 *mem = (u8 *) (budget->grabbing); | 1266 | u8 *mem = (u8 *) (budget->grabbing); |
| 1240 | u32 olddma = budget->ttbp; | 1267 | u32 olddma = budget->ttbp; |
| 1241 | u32 newdma = saa7146_read(budget->dev, PCI_VDP3); | 1268 | u32 newdma = saa7146_read(budget->dev, PCI_VDP3); |
| 1269 | struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1; | ||
| 1242 | 1270 | ||
| 1243 | if (!budgetpatch) { | ||
| 1244 | printk("av7110.c: vpeirq() called while budgetpatch disabled!" | ||
| 1245 | " check saa7146 IER register\n"); | ||
| 1246 | BUG(); | ||
| 1247 | } | ||
| 1248 | /* nearest lower position divisible by 188 */ | 1271 | /* nearest lower position divisible by 188 */ |
| 1249 | newdma -= newdma % 188; | 1272 | newdma -= newdma % 188; |
| 1250 | 1273 | ||
| @@ -1268,11 +1291,11 @@ static void vpeirq(unsigned long data) | |||
| 1268 | 1291 | ||
| 1269 | if (newdma > olddma) | 1292 | if (newdma > olddma) |
| 1270 | /* no wraparound, dump olddma..newdma */ | 1293 | /* no wraparound, dump olddma..newdma */ |
| 1271 | dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188); | 1294 | dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188); |
| 1272 | else { | 1295 | else { |
| 1273 | /* wraparound, dump olddma..buflen and 0..newdma */ | 1296 | /* wraparound, dump olddma..buflen and 0..newdma */ |
| 1274 | dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188); | 1297 | dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188); |
| 1275 | dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188); | 1298 | dvb_dmx_swfilter_packets(demux, mem, newdma / 188); |
| 1276 | } | 1299 | } |
| 1277 | } | 1300 | } |
| 1278 | 1301 | ||
| @@ -1294,8 +1317,8 @@ static int av7110_register(struct av7110 *av7110) | |||
| 1294 | for (i = 0; i < 32; i++) | 1317 | for (i = 0; i < 32; i++) |
| 1295 | av7110->handle2filter[i] = NULL; | 1318 | av7110->handle2filter[i] = NULL; |
| 1296 | 1319 | ||
| 1297 | dvbdemux->filternum = 32; | 1320 | dvbdemux->filternum = (av7110->full_ts) ? 256 : 32; |
| 1298 | dvbdemux->feednum = 32; | 1321 | dvbdemux->feednum = (av7110->full_ts) ? 256 : 32; |
| 1299 | dvbdemux->start_feed = av7110_start_feed; | 1322 | dvbdemux->start_feed = av7110_start_feed; |
| 1300 | dvbdemux->stop_feed = av7110_stop_feed; | 1323 | dvbdemux->stop_feed = av7110_stop_feed; |
| 1301 | dvbdemux->write_to_decoder = av7110_write_to_decoder; | 1324 | dvbdemux->write_to_decoder = av7110_write_to_decoder; |
| @@ -1305,7 +1328,7 @@ static int av7110_register(struct av7110 *av7110) | |||
| 1305 | dvb_dmx_init(&av7110->demux); | 1328 | dvb_dmx_init(&av7110->demux); |
| 1306 | av7110->demux.dmx.get_stc = dvb_get_stc; | 1329 | av7110->demux.dmx.get_stc = dvb_get_stc; |
| 1307 | 1330 | ||
| 1308 | av7110->dmxdev.filternum = 32; | 1331 | av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32; |
| 1309 | av7110->dmxdev.demux = &dvbdemux->dmx; | 1332 | av7110->dmxdev.demux = &dvbdemux->dmx; |
| 1310 | av7110->dmxdev.capabilities = 0; | 1333 | av7110->dmxdev.capabilities = 0; |
| 1311 | 1334 | ||
| @@ -1422,7 +1445,6 @@ int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val) | |||
| 1422 | return i2c_transfer(&av7110->i2c_adap, &msgs, 1); | 1445 | return i2c_transfer(&av7110->i2c_adap, &msgs, 1); |
| 1423 | } | 1446 | } |
| 1424 | 1447 | ||
| 1425 | #if 0 | ||
| 1426 | u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) | 1448 | u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) |
| 1427 | { | 1449 | { |
| 1428 | u8 mm1[] = {0x00}; | 1450 | u8 mm1[] = {0x00}; |
| @@ -1439,7 +1461,6 @@ u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) | |||
| 1439 | 1461 | ||
| 1440 | return mm2[0]; | 1462 | return mm2[0]; |
| 1441 | } | 1463 | } |
| 1442 | #endif | ||
| 1443 | 1464 | ||
| 1444 | /**************************************************************************** | 1465 | /**************************************************************************** |
| 1445 | * INITIALIZATION | 1466 | * INITIALIZATION |
| @@ -2256,7 +2277,7 @@ static int frontend_init(struct av7110 *av7110) | |||
| 2256 | if (!av7110->fe) { | 2277 | if (!av7110->fe) { |
| 2257 | /* FIXME: propagate the failure code from the lower layers */ | 2278 | /* FIXME: propagate the failure code from the lower layers */ |
| 2258 | ret = -ENOMEM; | 2279 | ret = -ENOMEM; |
| 2259 | printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", | 2280 | printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", |
| 2260 | av7110->dev->pci->vendor, | 2281 | av7110->dev->pci->vendor, |
| 2261 | av7110->dev->pci->device, | 2282 | av7110->dev->pci->device, |
| 2262 | av7110->dev->pci->subsystem_vendor, | 2283 | av7110->dev->pci->subsystem_vendor, |
| @@ -2484,7 +2505,47 @@ static int __devinit av7110_attach(struct saa7146_dev* dev, | |||
| 2484 | av7110->dvb_adapter.proposed_mac); | 2505 | av7110->dvb_adapter.proposed_mac); |
| 2485 | ret = -ENOMEM; | 2506 | ret = -ENOMEM; |
| 2486 | 2507 | ||
| 2487 | if (budgetpatch) { | 2508 | /* full-ts mod? */ |
| 2509 | if (full_ts) | ||
| 2510 | av7110->full_ts = true; | ||
| 2511 | |||
| 2512 | /* check for full-ts flag in eeprom */ | ||
| 2513 | if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) { | ||
| 2514 | u8 flags = i2c_readreg(av7110, 0xaa, 2); | ||
| 2515 | if (flags != 0xff && (flags & 0x01)) | ||
| 2516 | av7110->full_ts = true; | ||
| 2517 | } | ||
| 2518 | |||
| 2519 | if (av7110->full_ts) { | ||
| 2520 | printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n"); | ||
| 2521 | spin_lock_init(&av7110->feedlock1); | ||
| 2522 | av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length, | ||
| 2523 | &av7110->pt); | ||
| 2524 | if (!av7110->grabbing) | ||
| 2525 | goto err_i2c_del_3; | ||
| 2526 | |||
| 2527 | saa7146_write(dev, DD1_STREAM_B, 0x00000000); | ||
| 2528 | saa7146_write(dev, MC2, (MASK_10 | MASK_26)); | ||
| 2529 | |||
| 2530 | saa7146_write(dev, DD1_INIT, 0x00000600); | ||
| 2531 | saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); | ||
| 2532 | |||
| 2533 | saa7146_write(dev, BRS_CTRL, 0x60000000); | ||
| 2534 | saa7146_write(dev, MC2, MASK_08 | MASK_24); | ||
| 2535 | |||
| 2536 | /* dma3 */ | ||
| 2537 | saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000)); | ||
| 2538 | saa7146_write(dev, BASE_ODD3, 0); | ||
| 2539 | saa7146_write(dev, BASE_EVEN3, 0); | ||
| 2540 | saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT); | ||
| 2541 | saa7146_write(dev, PITCH3, TS_WIDTH); | ||
| 2542 | saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90); | ||
| 2543 | saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH); | ||
| 2544 | saa7146_write(dev, MC2, MASK_04 | MASK_20); | ||
| 2545 | |||
| 2546 | tasklet_init(&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110); | ||
| 2547 | |||
| 2548 | } else if (budgetpatch) { | ||
| 2488 | spin_lock_init(&av7110->feedlock1); | 2549 | spin_lock_init(&av7110->feedlock1); |
| 2489 | av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length, | 2550 | av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length, |
| 2490 | &av7110->pt); | 2551 | &av7110->pt); |
| @@ -2710,11 +2771,13 @@ static int __devexit av7110_detach(struct saa7146_dev* saa) | |||
| 2710 | #if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE) | 2771 | #if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE) |
| 2711 | av7110_ir_exit(av7110); | 2772 | av7110_ir_exit(av7110); |
| 2712 | #endif | 2773 | #endif |
| 2713 | if (budgetpatch) { | 2774 | if (budgetpatch || av7110->full_ts) { |
| 2714 | /* Disable RPS1 */ | 2775 | if (budgetpatch) { |
| 2715 | saa7146_write(saa, MC1, MASK_29); | 2776 | /* Disable RPS1 */ |
| 2716 | /* VSYNC LOW (inactive) */ | 2777 | saa7146_write(saa, MC1, MASK_29); |
| 2717 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); | 2778 | /* VSYNC LOW (inactive) */ |
| 2779 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); | ||
| 2780 | } | ||
| 2718 | saa7146_write(saa, MC1, MASK_20); /* DMA3 off */ | 2781 | saa7146_write(saa, MC1, MASK_20); /* DMA3 off */ |
| 2719 | SAA7146_IER_DISABLE(saa, MASK_10); | 2782 | SAA7146_IER_DISABLE(saa, MASK_10); |
| 2720 | SAA7146_ISR_CLEAR(saa, MASK_10); | 2783 | SAA7146_ISR_CLEAR(saa, MASK_10); |
| @@ -2794,7 +2857,7 @@ static void av7110_irq(struct saa7146_dev* dev, u32 *isr) | |||
| 2794 | tasklet_schedule(&av7110->gpio_tasklet); | 2857 | tasklet_schedule(&av7110->gpio_tasklet); |
| 2795 | } | 2858 | } |
| 2796 | 2859 | ||
| 2797 | if ((*isr & MASK_10) && budgetpatch) | 2860 | if (*isr & MASK_10) |
| 2798 | tasklet_schedule(&av7110->vpe_tasklet); | 2861 | tasklet_schedule(&av7110->vpe_tasklet); |
| 2799 | } | 2862 | } |
| 2800 | 2863 | ||
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h index 55f23ddcb994..d85b8512ac30 100644 --- a/drivers/media/dvb/ttpci/av7110.h +++ b/drivers/media/dvb/ttpci/av7110.h | |||
| @@ -192,6 +192,7 @@ struct av7110 { | |||
| 192 | unsigned char *grabbing; | 192 | unsigned char *grabbing; |
| 193 | struct saa7146_pgtable pt; | 193 | struct saa7146_pgtable pt; |
| 194 | struct tasklet_struct vpe_tasklet; | 194 | struct tasklet_struct vpe_tasklet; |
| 195 | bool full_ts; | ||
| 195 | 196 | ||
| 196 | int fe_synced; | 197 | int fe_synced; |
| 197 | struct mutex pid_mutex; | 198 | struct mutex pid_mutex; |
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index 184647ad1c7c..bdc62acf2099 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c | |||
| @@ -788,6 +788,9 @@ int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t l | |||
| 788 | 788 | ||
| 789 | dprintk(2, "av7110:%p, \n", av7110); | 789 | dprintk(2, "av7110:%p, \n", av7110); |
| 790 | 790 | ||
| 791 | if (av7110->full_ts && demux->dmx.frontend->source != DMX_MEMORY_FE) | ||
| 792 | return 0; | ||
| 793 | |||
| 791 | switch (feed->pes_type) { | 794 | switch (feed->pes_type) { |
| 792 | case 0: | 795 | case 0: |
| 793 | if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY) | 796 | if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY) |
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index b7d1f2f18d3a..1032ea77837e 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c | |||
| @@ -57,6 +57,8 @@ | |||
| 57 | #define SLOTSTATUS_READY 8 | 57 | #define SLOTSTATUS_READY 8 |
| 58 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) | 58 | #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY) |
| 59 | 59 | ||
| 60 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 61 | |||
| 60 | struct budget_av { | 62 | struct budget_av { |
| 61 | struct budget budget; | 63 | struct budget budget; |
| 62 | struct video_device *vd; | 64 | struct video_device *vd; |
| @@ -1049,7 +1051,7 @@ static void frontend_init(struct budget_av *budget_av) | |||
| 1049 | 1051 | ||
| 1050 | if (fe == NULL) { | 1052 | if (fe == NULL) { |
| 1051 | printk(KERN_ERR "budget-av: A frontend driver was not found " | 1053 | printk(KERN_ERR "budget-av: A frontend driver was not found " |
| 1052 | "for device %04x/%04x subsystem %04x/%04x\n", | 1054 | "for device [%04x:%04x] subsystem [%04x:%04x]\n", |
| 1053 | saa->pci->vendor, | 1055 | saa->pci->vendor, |
| 1054 | saa->pci->device, | 1056 | saa->pci->device, |
| 1055 | saa->pci->subsystem_vendor, | 1057 | saa->pci->subsystem_vendor, |
| @@ -1127,7 +1129,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
| 1127 | 1129 | ||
| 1128 | dev->ext_priv = budget_av; | 1130 | dev->ext_priv = budget_av; |
| 1129 | 1131 | ||
| 1130 | if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) { | 1132 | err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE, |
| 1133 | adapter_nr); | ||
| 1134 | if (err) { | ||
| 1131 | kfree(budget_av); | 1135 | kfree(budget_av); |
| 1132 | return err; | 1136 | return err; |
| 1133 | } | 1137 | } |
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 060e7c785326..0a5aad45435d 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
| @@ -92,6 +92,8 @@ static int ir_debug; | |||
| 92 | module_param(ir_debug, int, 0644); | 92 | module_param(ir_debug, int, 0644); |
| 93 | MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); | 93 | MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); |
| 94 | 94 | ||
| 95 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 96 | |||
| 95 | struct budget_ci_ir { | 97 | struct budget_ci_ir { |
| 96 | struct input_dev *dev; | 98 | struct input_dev *dev; |
| 97 | struct tasklet_struct msp430_irq_tasklet; | 99 | struct tasklet_struct msp430_irq_tasklet; |
| @@ -1153,7 +1155,7 @@ static void frontend_init(struct budget_ci *budget_ci) | |||
| 1153 | } | 1155 | } |
| 1154 | 1156 | ||
| 1155 | if (budget_ci->budget.dvb_frontend == NULL) { | 1157 | if (budget_ci->budget.dvb_frontend == NULL) { |
| 1156 | printk("budget-ci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", | 1158 | printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", |
| 1157 | budget_ci->budget.dev->pci->vendor, | 1159 | budget_ci->budget.dev->pci->vendor, |
| 1158 | budget_ci->budget.dev->pci->device, | 1160 | budget_ci->budget.dev->pci->device, |
| 1159 | budget_ci->budget.dev->pci->subsystem_vendor, | 1161 | budget_ci->budget.dev->pci->subsystem_vendor, |
| @@ -1183,7 +1185,8 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
| 1183 | 1185 | ||
| 1184 | dev->ext_priv = budget_ci; | 1186 | dev->ext_priv = budget_ci; |
| 1185 | 1187 | ||
| 1186 | err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE); | 1188 | err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE, |
| 1189 | adapter_nr); | ||
| 1187 | if (err) | 1190 | if (err) |
| 1188 | goto out2; | 1191 | goto out2; |
| 1189 | 1192 | ||
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 6f4ddb643fee..ba18e56d5f11 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c | |||
| @@ -57,8 +57,6 @@ module_param_named(bufsize, dma_buffer_size, int, 0444); | |||
| 57 | MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off)."); | 57 | MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off)."); |
| 58 | MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)"); | 58 | MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)"); |
| 59 | 59 | ||
| 60 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 61 | |||
| 62 | /**************************************************************************** | 60 | /**************************************************************************** |
| 63 | * TT budget / WinTV Nova | 61 | * TT budget / WinTV Nova |
| 64 | ****************************************************************************/ | 62 | ****************************************************************************/ |
| @@ -411,7 +409,7 @@ static void budget_unregister(struct budget *budget) | |||
| 411 | 409 | ||
| 412 | int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, | 410 | int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, |
| 413 | struct saa7146_pci_extension_data *info, | 411 | struct saa7146_pci_extension_data *info, |
| 414 | struct module *owner) | 412 | struct module *owner, short *adapter_nums) |
| 415 | { | 413 | { |
| 416 | int ret = 0; | 414 | int ret = 0; |
| 417 | struct budget_info *bi = info->ext_priv; | 415 | struct budget_info *bi = info->ext_priv; |
| @@ -474,7 +472,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, | |||
| 474 | printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size); | 472 | printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size); |
| 475 | 473 | ||
| 476 | ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, | 474 | ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, |
| 477 | owner, &budget->dev->pci->dev, adapter_nr); | 475 | owner, &budget->dev->pci->dev, adapter_nums); |
| 478 | if (ret < 0) | 476 | if (ret < 0) |
| 479 | return ret; | 477 | return ret; |
| 480 | 478 | ||
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index aa5ed4ef19f2..60136688a9a4 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c | |||
| @@ -39,6 +39,8 @@ | |||
| 39 | 39 | ||
| 40 | #include "bsru6.h" | 40 | #include "bsru6.h" |
| 41 | 41 | ||
| 42 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 43 | |||
| 42 | #define budget_patch budget | 44 | #define budget_patch budget |
| 43 | 45 | ||
| 44 | static struct saa7146_extension budget_extension; | 46 | static struct saa7146_extension budget_extension; |
| @@ -360,7 +362,7 @@ static void frontend_init(struct budget_patch* budget) | |||
| 360 | } | 362 | } |
| 361 | 363 | ||
| 362 | if (budget->dvb_frontend == NULL) { | 364 | if (budget->dvb_frontend == NULL) { |
| 363 | printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", | 365 | printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", |
| 364 | budget->dev->pci->vendor, | 366 | budget->dev->pci->vendor, |
| 365 | budget->dev->pci->device, | 367 | budget->dev->pci->device, |
| 366 | budget->dev->pci->subsystem_vendor, | 368 | budget->dev->pci->subsystem_vendor, |
| @@ -592,8 +594,9 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte | |||
| 592 | 594 | ||
| 593 | dprintk(2, "budget: %p\n", budget); | 595 | dprintk(2, "budget: %p\n", budget); |
| 594 | 596 | ||
| 595 | if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { | 597 | err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr); |
| 596 | kfree (budget); | 598 | if (err) { |
| 599 | kfree(budget); | ||
| 597 | return err; | 600 | return err; |
| 598 | } | 601 | } |
| 599 | 602 | ||
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index f0068996ac07..1638e1d9f538 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c | |||
| @@ -46,11 +46,14 @@ | |||
| 46 | #include "lnbp21.h" | 46 | #include "lnbp21.h" |
| 47 | #include "bsru6.h" | 47 | #include "bsru6.h" |
| 48 | #include "bsbe1.h" | 48 | #include "bsbe1.h" |
| 49 | #include "tdhd1.h" | ||
| 49 | 50 | ||
| 50 | static int diseqc_method; | 51 | static int diseqc_method; |
| 51 | module_param(diseqc_method, int, 0444); | 52 | module_param(diseqc_method, int, 0444); |
| 52 | MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)"); | 53 | MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)"); |
| 53 | 54 | ||
| 55 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 56 | |||
| 54 | static void Set22K (struct budget *budget, int state) | 57 | static void Set22K (struct budget *budget, int state) |
| 55 | { | 58 | { |
| 56 | struct saa7146_dev *dev=budget->dev; | 59 | struct saa7146_dev *dev=budget->dev; |
| @@ -390,6 +393,13 @@ static struct stv0299_config alps_bsbe1_config_activy = { | |||
| 390 | .set_symbol_rate = alps_bsbe1_set_symbol_rate, | 393 | .set_symbol_rate = alps_bsbe1_set_symbol_rate, |
| 391 | }; | 394 | }; |
| 392 | 395 | ||
| 396 | static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name) | ||
| 397 | { | ||
| 398 | struct budget *budget = (struct budget *)fe->dvb->priv; | ||
| 399 | |||
| 400 | return request_firmware(fw, name, &budget->dev->pci->dev); | ||
| 401 | } | ||
| 402 | |||
| 393 | 403 | ||
| 394 | static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg) | 404 | static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg) |
| 395 | { | 405 | { |
| @@ -511,6 +521,14 @@ static void frontend_init(struct budget *budget) | |||
| 511 | } | 521 | } |
| 512 | break; | 522 | break; |
| 513 | 523 | ||
| 524 | case 0x5f60: /* Fujitsu Siemens Activy Budget-T PCI rev AL (tda10046/ALPS TDHD1-204A) */ | ||
| 525 | budget->dvb_frontend = dvb_attach(tda10046_attach, &alps_tdhd1_204a_config, &budget->i2c_adap); | ||
| 526 | if (budget->dvb_frontend) { | ||
| 527 | budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdhd1_204a_tuner_set_params; | ||
| 528 | budget->dvb_frontend->tuner_priv = &budget->i2c_adap; | ||
| 529 | } | ||
| 530 | break; | ||
| 531 | |||
| 514 | case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */ | 532 | case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */ |
| 515 | budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap); | 533 | budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap); |
| 516 | if (budget->dvb_frontend) { | 534 | if (budget->dvb_frontend) { |
| @@ -550,7 +568,7 @@ static void frontend_init(struct budget *budget) | |||
| 550 | } | 568 | } |
| 551 | 569 | ||
| 552 | if (budget->dvb_frontend == NULL) { | 570 | if (budget->dvb_frontend == NULL) { |
| 553 | printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", | 571 | printk("budget: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n", |
| 554 | budget->dev->pci->vendor, | 572 | budget->dev->pci->vendor, |
| 555 | budget->dev->pci->device, | 573 | budget->dev->pci->device, |
| 556 | budget->dev->pci->subsystem_vendor, | 574 | budget->dev->pci->subsystem_vendor, |
| @@ -582,7 +600,8 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_ | |||
| 582 | 600 | ||
| 583 | dev->ext_priv = budget; | 601 | dev->ext_priv = budget; |
| 584 | 602 | ||
| 585 | if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { | 603 | err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr); |
| 604 | if (err) { | ||
| 586 | printk("==> failed\n"); | 605 | printk("==> failed\n"); |
| 587 | kfree (budget); | 606 | kfree (budget); |
| 588 | return err; | 607 | return err; |
| @@ -624,6 +643,7 @@ MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT); | |||
| 624 | MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY); | 643 | MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY); |
| 625 | MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY); | 644 | MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY); |
| 626 | MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY); | 645 | MAKE_BUDGET_INFO(fsact, "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY); |
| 646 | MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY); | ||
| 627 | 647 | ||
| 628 | static struct pci_device_id pci_tbl[] = { | 648 | static struct pci_device_id pci_tbl[] = { |
| 629 | MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), | 649 | MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), |
| @@ -634,6 +654,7 @@ static struct pci_device_id pci_tbl[] = { | |||
| 634 | MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018), | 654 | MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018), |
| 635 | MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), | 655 | MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60), |
| 636 | MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), | 656 | MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61), |
| 657 | MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60), | ||
| 637 | MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61), | 658 | MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61), |
| 638 | { | 659 | { |
| 639 | .vendor = 0, | 660 | .vendor = 0, |
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h index dd450b739bff..86435bf16260 100644 --- a/drivers/media/dvb/ttpci/budget.h +++ b/drivers/media/dvb/ttpci/budget.h | |||
| @@ -109,7 +109,7 @@ static struct saa7146_pci_extension_data x_var = { \ | |||
| 109 | 109 | ||
| 110 | extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, | 110 | extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, |
| 111 | struct saa7146_pci_extension_data *info, | 111 | struct saa7146_pci_extension_data *info, |
| 112 | struct module *owner); | 112 | struct module *owner, short *adapter_nums); |
| 113 | extern void ttpci_budget_init_hooks(struct budget *budget); | 113 | extern void ttpci_budget_init_hooks(struct budget *budget); |
| 114 | extern int ttpci_budget_deinit(struct budget *budget); | 114 | extern int ttpci_budget_deinit(struct budget *budget); |
| 115 | extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr); | 115 | extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr); |
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index e6c9cd2e3b94..66ab0c6e9783 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | |||
| @@ -1614,7 +1614,7 @@ static void frontend_init(struct ttusb* ttusb) | |||
| 1614 | } | 1614 | } |
| 1615 | 1615 | ||
| 1616 | if (ttusb->fe == NULL) { | 1616 | if (ttusb->fe == NULL) { |
| 1617 | printk("dvb-ttusb-budget: A frontend driver was not found for device %04x/%04x\n", | 1617 | printk("dvb-ttusb-budget: A frontend driver was not found for device [%04x:%04x]\n", |
| 1618 | le16_to_cpu(ttusb->dev->descriptor.idVendor), | 1618 | le16_to_cpu(ttusb->dev->descriptor.idVendor), |
| 1619 | le16_to_cpu(ttusb->dev->descriptor.idProduct)); | 1619 | le16_to_cpu(ttusb->dev->descriptor.idProduct)); |
| 1620 | } else { | 1620 | } else { |
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index de5829b863fd..ab33fec8a19f 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c | |||
| @@ -1665,7 +1665,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, | |||
| 1665 | } | 1665 | } |
| 1666 | 1666 | ||
| 1667 | if (dec->fe == NULL) { | 1667 | if (dec->fe == NULL) { |
| 1668 | printk("dvb-ttusb-dec: A frontend driver was not found for device %04x/%04x\n", | 1668 | printk("dvb-ttusb-dec: A frontend driver was not found for device [%04x:%04x]\n", |
| 1669 | le16_to_cpu(dec->udev->descriptor.idVendor), | 1669 | le16_to_cpu(dec->udev->descriptor.idVendor), |
| 1670 | le16_to_cpu(dec->udev->descriptor.idProduct)); | 1670 | le16_to_cpu(dec->udev->descriptor.idProduct)); |
| 1671 | } else { | 1671 | } else { |
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c index 443af24097f3..21260aad1e54 100644 --- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c +++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c | |||
| @@ -38,7 +38,17 @@ struct ttusbdecfe_state { | |||
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status) | 41 | static int ttusbdecfe_dvbs_read_status(struct dvb_frontend *fe, |
| 42 | fe_status_t *status) | ||
| 43 | { | ||
| 44 | *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | | ||
| 45 | FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; | ||
| 46 | return 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | |||
| 50 | static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe, | ||
| 51 | fe_status_t *status) | ||
| 42 | { | 52 | { |
| 43 | struct ttusbdecfe_state* state = fe->demodulator_priv; | 53 | struct ttusbdecfe_state* state = fe->demodulator_priv; |
| 44 | u8 b[] = { 0x00, 0x00, 0x00, 0x00, | 54 | u8 b[] = { 0x00, 0x00, 0x00, 0x00, |
| @@ -251,7 +261,7 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = { | |||
| 251 | 261 | ||
| 252 | .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings, | 262 | .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings, |
| 253 | 263 | ||
| 254 | .read_status = ttusbdecfe_read_status, | 264 | .read_status = ttusbdecfe_dvbt_read_status, |
| 255 | }; | 265 | }; |
| 256 | 266 | ||
| 257 | static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = { | 267 | static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = { |
| @@ -273,7 +283,7 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = { | |||
| 273 | 283 | ||
| 274 | .set_frontend = ttusbdecfe_dvbs_set_frontend, | 284 | .set_frontend = ttusbdecfe_dvbs_set_frontend, |
| 275 | 285 | ||
| 276 | .read_status = ttusbdecfe_read_status, | 286 | .read_status = ttusbdecfe_dvbs_read_status, |
| 277 | 287 | ||
| 278 | .diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd, | 288 | .diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd, |
| 279 | .set_voltage = ttusbdecfe_dvbs_set_voltage, | 289 | .set_voltage = ttusbdecfe_dvbs_set_voltage, |
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 1b41b3f77cf9..e51d707e58d3 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig | |||
| @@ -361,4 +361,16 @@ config USB_SI470X | |||
| 361 | To compile this driver as a module, choose M here: the | 361 | To compile this driver as a module, choose M here: the |
| 362 | module will be called radio-silabs. | 362 | module will be called radio-silabs. |
| 363 | 363 | ||
| 364 | config USB_MR800 | ||
| 365 | tristate "AverMedia MR 800 USB FM radio support" | ||
| 366 | depends on USB && VIDEO_V4L2 | ||
| 367 | ---help--- | ||
| 368 | Say Y here if you want to connect this type of radio to your | ||
| 369 | computer's USB port. Note that the audio is not digital, and | ||
| 370 | you must connect the line out connector to a sound card or a | ||
| 371 | set of speakers. | ||
| 372 | |||
| 373 | To compile this driver as a module, choose M here: the | ||
| 374 | module will be called radio-mr800. | ||
| 375 | |||
| 364 | endif # RADIO_ADAPTERS | 376 | endif # RADIO_ADAPTERS |
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 7ca71ab96b43..240ec63cdafc 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile | |||
| @@ -18,5 +18,6 @@ obj-$(CONFIG_RADIO_TRUST) += radio-trust.o | |||
| 18 | obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o | 18 | obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o |
| 19 | obj-$(CONFIG_USB_DSBR) += dsbr100.o | 19 | obj-$(CONFIG_USB_DSBR) += dsbr100.o |
| 20 | obj-$(CONFIG_USB_SI470X) += radio-si470x.o | 20 | obj-$(CONFIG_USB_SI470X) += radio-si470x.o |
| 21 | obj-$(CONFIG_USB_MR800) += radio-mr800.o | ||
| 21 | 22 | ||
| 22 | EXTRA_CFLAGS += -Isound | 23 | EXTRA_CFLAGS += -Isound |
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 70c65a745923..66783fffe4c1 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c | |||
| @@ -274,7 +274,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
| 274 | static int vidioc_g_tuner(struct file *file, void *priv, | 274 | static int vidioc_g_tuner(struct file *file, void *priv, |
| 275 | struct v4l2_tuner *v) | 275 | struct v4l2_tuner *v) |
| 276 | { | 276 | { |
| 277 | struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); | 277 | struct dsbr100_device *radio = video_drvdata(file); |
| 278 | 278 | ||
| 279 | if (v->index > 0) | 279 | if (v->index > 0) |
| 280 | return -EINVAL; | 280 | return -EINVAL; |
| @@ -306,7 +306,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
| 306 | static int vidioc_s_frequency(struct file *file, void *priv, | 306 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 307 | struct v4l2_frequency *f) | 307 | struct v4l2_frequency *f) |
| 308 | { | 308 | { |
| 309 | struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); | 309 | struct dsbr100_device *radio = video_drvdata(file); |
| 310 | 310 | ||
| 311 | radio->curfreq = f->frequency; | 311 | radio->curfreq = f->frequency; |
| 312 | if (dsbr100_setfreq(radio, radio->curfreq)==-1) | 312 | if (dsbr100_setfreq(radio, radio->curfreq)==-1) |
| @@ -317,7 +317,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 317 | static int vidioc_g_frequency(struct file *file, void *priv, | 317 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 318 | struct v4l2_frequency *f) | 318 | struct v4l2_frequency *f) |
| 319 | { | 319 | { |
| 320 | struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); | 320 | struct dsbr100_device *radio = video_drvdata(file); |
| 321 | 321 | ||
| 322 | f->type = V4L2_TUNER_RADIO; | 322 | f->type = V4L2_TUNER_RADIO; |
| 323 | f->frequency = radio->curfreq; | 323 | f->frequency = radio->curfreq; |
| @@ -342,7 +342,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 342 | static int vidioc_g_ctrl(struct file *file, void *priv, | 342 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 343 | struct v4l2_control *ctrl) | 343 | struct v4l2_control *ctrl) |
| 344 | { | 344 | { |
| 345 | struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); | 345 | struct dsbr100_device *radio = video_drvdata(file); |
| 346 | 346 | ||
| 347 | switch (ctrl->id) { | 347 | switch (ctrl->id) { |
| 348 | case V4L2_CID_AUDIO_MUTE: | 348 | case V4L2_CID_AUDIO_MUTE: |
| @@ -355,16 +355,20 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 355 | static int vidioc_s_ctrl(struct file *file, void *priv, | 355 | static int vidioc_s_ctrl(struct file *file, void *priv, |
| 356 | struct v4l2_control *ctrl) | 356 | struct v4l2_control *ctrl) |
| 357 | { | 357 | { |
| 358 | struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); | 358 | struct dsbr100_device *radio = video_drvdata(file); |
| 359 | 359 | ||
| 360 | switch (ctrl->id) { | 360 | switch (ctrl->id) { |
| 361 | case V4L2_CID_AUDIO_MUTE: | 361 | case V4L2_CID_AUDIO_MUTE: |
| 362 | if (ctrl->value) { | 362 | if (ctrl->value) { |
| 363 | if (dsbr100_stop(radio)==-1) | 363 | if (dsbr100_stop(radio) == -1) { |
| 364 | warn("Radio did not respond properly"); | 364 | warn("Radio did not respond properly"); |
| 365 | return -EBUSY; | ||
| 366 | } | ||
| 365 | } else { | 367 | } else { |
| 366 | if (dsbr100_start(radio)==-1) | 368 | if (dsbr100_start(radio) == -1) { |
| 367 | warn("Radio did not respond properly"); | 369 | warn("Radio did not respond properly"); |
| 370 | return -EBUSY; | ||
| 371 | } | ||
| 368 | } | 372 | } |
| 369 | return 0; | 373 | return 0; |
| 370 | } | 374 | } |
| @@ -405,23 +409,26 @@ static int vidioc_s_audio(struct file *file, void *priv, | |||
| 405 | 409 | ||
| 406 | static int usb_dsbr100_open(struct inode *inode, struct file *file) | 410 | static int usb_dsbr100_open(struct inode *inode, struct file *file) |
| 407 | { | 411 | { |
| 408 | struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); | 412 | struct dsbr100_device *radio = video_drvdata(file); |
| 409 | 413 | ||
| 414 | lock_kernel(); | ||
| 410 | radio->users = 1; | 415 | radio->users = 1; |
| 411 | radio->muted = 1; | 416 | radio->muted = 1; |
| 412 | 417 | ||
| 413 | if (dsbr100_start(radio)<0) { | 418 | if (dsbr100_start(radio)<0) { |
| 414 | warn("Radio did not start up properly"); | 419 | warn("Radio did not start up properly"); |
| 415 | radio->users = 0; | 420 | radio->users = 0; |
| 421 | unlock_kernel(); | ||
| 416 | return -EIO; | 422 | return -EIO; |
| 417 | } | 423 | } |
| 418 | dsbr100_setfreq(radio, radio->curfreq); | 424 | dsbr100_setfreq(radio, radio->curfreq); |
| 425 | unlock_kernel(); | ||
| 419 | return 0; | 426 | return 0; |
| 420 | } | 427 | } |
| 421 | 428 | ||
| 422 | static int usb_dsbr100_close(struct inode *inode, struct file *file) | 429 | static int usb_dsbr100_close(struct inode *inode, struct file *file) |
| 423 | { | 430 | { |
| 424 | struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); | 431 | struct dsbr100_device *radio = video_drvdata(file); |
| 425 | 432 | ||
| 426 | if (!radio) | 433 | if (!radio) |
| 427 | return -ENODEV; | 434 | return -ENODEV; |
| @@ -507,7 +514,8 @@ static int usb_dsbr100_probe(struct usb_interface *intf, | |||
| 507 | static int __init dsbr100_init(void) | 514 | static int __init dsbr100_init(void) |
| 508 | { | 515 | { |
| 509 | int retval = usb_register(&usb_dsbr100_driver); | 516 | int retval = usb_register(&usb_dsbr100_driver); |
| 510 | info(DRIVER_VERSION ":" DRIVER_DESC); | 517 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
| 518 | DRIVER_DESC "\n"); | ||
| 511 | return retval; | 519 | return retval; |
| 512 | } | 520 | } |
| 513 | 521 | ||
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 1f064f4b32df..9305e958fc66 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c | |||
| @@ -51,6 +51,7 @@ static struct mutex lock; | |||
| 51 | 51 | ||
| 52 | struct rt_device | 52 | struct rt_device |
| 53 | { | 53 | { |
| 54 | unsigned long in_use; | ||
| 54 | int port; | 55 | int port; |
| 55 | int curvol; | 56 | int curvol; |
| 56 | unsigned long curfreq; | 57 | unsigned long curfreq; |
| @@ -245,8 +246,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
| 245 | static int vidioc_g_tuner(struct file *file, void *priv, | 246 | static int vidioc_g_tuner(struct file *file, void *priv, |
| 246 | struct v4l2_tuner *v) | 247 | struct v4l2_tuner *v) |
| 247 | { | 248 | { |
| 248 | struct video_device *dev = video_devdata(file); | 249 | struct rt_device *rt = video_drvdata(file); |
| 249 | struct rt_device *rt = dev->priv; | ||
| 250 | 250 | ||
| 251 | if (v->index > 0) | 251 | if (v->index > 0) |
| 252 | return -EINVAL; | 252 | return -EINVAL; |
| @@ -273,8 +273,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
| 273 | static int vidioc_s_frequency(struct file *file, void *priv, | 273 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 274 | struct v4l2_frequency *f) | 274 | struct v4l2_frequency *f) |
| 275 | { | 275 | { |
| 276 | struct video_device *dev = video_devdata(file); | 276 | struct rt_device *rt = video_drvdata(file); |
| 277 | struct rt_device *rt = dev->priv; | ||
| 278 | 277 | ||
| 279 | rt->curfreq = f->frequency; | 278 | rt->curfreq = f->frequency; |
| 280 | rt_setfreq(rt, rt->curfreq); | 279 | rt_setfreq(rt, rt->curfreq); |
| @@ -284,8 +283,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 284 | static int vidioc_g_frequency(struct file *file, void *priv, | 283 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 285 | struct v4l2_frequency *f) | 284 | struct v4l2_frequency *f) |
| 286 | { | 285 | { |
| 287 | struct video_device *dev = video_devdata(file); | 286 | struct rt_device *rt = video_drvdata(file); |
| 288 | struct rt_device *rt = dev->priv; | ||
| 289 | 287 | ||
| 290 | f->type = V4L2_TUNER_RADIO; | 288 | f->type = V4L2_TUNER_RADIO; |
| 291 | f->frequency = rt->curfreq; | 289 | f->frequency = rt->curfreq; |
| @@ -310,8 +308,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 310 | static int vidioc_g_ctrl(struct file *file, void *priv, | 308 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 311 | struct v4l2_control *ctrl) | 309 | struct v4l2_control *ctrl) |
| 312 | { | 310 | { |
| 313 | struct video_device *dev = video_devdata(file); | 311 | struct rt_device *rt = video_drvdata(file); |
| 314 | struct rt_device *rt = dev->priv; | ||
| 315 | 312 | ||
| 316 | switch (ctrl->id) { | 313 | switch (ctrl->id) { |
| 317 | case V4L2_CID_AUDIO_MUTE: | 314 | case V4L2_CID_AUDIO_MUTE: |
| @@ -327,8 +324,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 327 | static int vidioc_s_ctrl(struct file *file, void *priv, | 324 | static int vidioc_s_ctrl(struct file *file, void *priv, |
| 328 | struct v4l2_control *ctrl) | 325 | struct v4l2_control *ctrl) |
| 329 | { | 326 | { |
| 330 | struct video_device *dev = video_devdata(file); | 327 | struct rt_device *rt = video_drvdata(file); |
| 331 | struct rt_device *rt = dev->priv; | ||
| 332 | 328 | ||
| 333 | switch (ctrl->id) { | 329 | switch (ctrl->id) { |
| 334 | case V4L2_CID_AUDIO_MUTE: | 330 | case V4L2_CID_AUDIO_MUTE: |
| @@ -378,10 +374,21 @@ static int vidioc_s_audio(struct file *file, void *priv, | |||
| 378 | 374 | ||
| 379 | static struct rt_device rtrack_unit; | 375 | static struct rt_device rtrack_unit; |
| 380 | 376 | ||
| 377 | static int rtrack_exclusive_open(struct inode *inode, struct file *file) | ||
| 378 | { | ||
| 379 | return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0; | ||
| 380 | } | ||
| 381 | |||
| 382 | static int rtrack_exclusive_release(struct inode *inode, struct file *file) | ||
| 383 | { | ||
| 384 | clear_bit(0, &rtrack_unit.in_use); | ||
| 385 | return 0; | ||
| 386 | } | ||
| 387 | |||
| 381 | static const struct file_operations rtrack_fops = { | 388 | static const struct file_operations rtrack_fops = { |
| 382 | .owner = THIS_MODULE, | 389 | .owner = THIS_MODULE, |
| 383 | .open = video_exclusive_open, | 390 | .open = rtrack_exclusive_open, |
| 384 | .release = video_exclusive_release, | 391 | .release = rtrack_exclusive_release, |
| 385 | .ioctl = video_ioctl2, | 392 | .ioctl = video_ioctl2, |
| 386 | #ifdef CONFIG_COMPAT | 393 | #ifdef CONFIG_COMPAT |
| 387 | .compat_ioctl = v4l_compat_ioctl32, | 394 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -408,6 +415,7 @@ static struct video_device rtrack_radio = { | |||
| 408 | .name = "RadioTrack radio", | 415 | .name = "RadioTrack radio", |
| 409 | .fops = &rtrack_fops, | 416 | .fops = &rtrack_fops, |
| 410 | .ioctl_ops = &rtrack_ioctl_ops, | 417 | .ioctl_ops = &rtrack_ioctl_ops, |
| 418 | .release = video_device_release_empty, | ||
| 411 | }; | 419 | }; |
| 412 | 420 | ||
| 413 | static int __init rtrack_init(void) | 421 | static int __init rtrack_init(void) |
| @@ -424,7 +432,7 @@ static int __init rtrack_init(void) | |||
| 424 | return -EBUSY; | 432 | return -EBUSY; |
| 425 | } | 433 | } |
| 426 | 434 | ||
| 427 | rtrack_radio.priv=&rtrack_unit; | 435 | video_set_drvdata(&rtrack_radio, &rtrack_unit); |
| 428 | 436 | ||
| 429 | if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) { | 437 | if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) { |
| 430 | release_region(io, 2); | 438 | release_region(io, 2); |
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 628c689e3ffe..d78489573230 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c | |||
| @@ -70,6 +70,7 @@ static struct mutex lock; | |||
| 70 | 70 | ||
| 71 | struct az_device | 71 | struct az_device |
| 72 | { | 72 | { |
| 73 | unsigned long in_use; | ||
| 73 | int curvol; | 74 | int curvol; |
| 74 | unsigned long curfreq; | 75 | unsigned long curfreq; |
| 75 | int stereo; | 76 | int stereo; |
| @@ -195,8 +196,7 @@ static int vidioc_querycap (struct file *file, void *priv, | |||
| 195 | static int vidioc_g_tuner (struct file *file, void *priv, | 196 | static int vidioc_g_tuner (struct file *file, void *priv, |
| 196 | struct v4l2_tuner *v) | 197 | struct v4l2_tuner *v) |
| 197 | { | 198 | { |
| 198 | struct video_device *dev = video_devdata(file); | 199 | struct az_device *az = video_drvdata(file); |
| 199 | struct az_device *az = dev->priv; | ||
| 200 | 200 | ||
| 201 | if (v->index > 0) | 201 | if (v->index > 0) |
| 202 | return -EINVAL; | 202 | return -EINVAL; |
| @@ -264,8 +264,7 @@ static int vidioc_s_audio (struct file *file, void *priv, | |||
| 264 | static int vidioc_s_frequency (struct file *file, void *priv, | 264 | static int vidioc_s_frequency (struct file *file, void *priv, |
| 265 | struct v4l2_frequency *f) | 265 | struct v4l2_frequency *f) |
| 266 | { | 266 | { |
| 267 | struct video_device *dev = video_devdata(file); | 267 | struct az_device *az = video_drvdata(file); |
| 268 | struct az_device *az = dev->priv; | ||
| 269 | 268 | ||
| 270 | az->curfreq = f->frequency; | 269 | az->curfreq = f->frequency; |
| 271 | az_setfreq(az, az->curfreq); | 270 | az_setfreq(az, az->curfreq); |
| @@ -275,8 +274,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, | |||
| 275 | static int vidioc_g_frequency (struct file *file, void *priv, | 274 | static int vidioc_g_frequency (struct file *file, void *priv, |
| 276 | struct v4l2_frequency *f) | 275 | struct v4l2_frequency *f) |
| 277 | { | 276 | { |
| 278 | struct video_device *dev = video_devdata(file); | 277 | struct az_device *az = video_drvdata(file); |
| 279 | struct az_device *az = dev->priv; | ||
| 280 | 278 | ||
| 281 | f->type = V4L2_TUNER_RADIO; | 279 | f->type = V4L2_TUNER_RADIO; |
| 282 | f->frequency = az->curfreq; | 280 | f->frequency = az->curfreq; |
| @@ -302,8 +300,7 @@ static int vidioc_queryctrl (struct file *file, void *priv, | |||
| 302 | static int vidioc_g_ctrl (struct file *file, void *priv, | 300 | static int vidioc_g_ctrl (struct file *file, void *priv, |
| 303 | struct v4l2_control *ctrl) | 301 | struct v4l2_control *ctrl) |
| 304 | { | 302 | { |
| 305 | struct video_device *dev = video_devdata(file); | 303 | struct az_device *az = video_drvdata(file); |
| 306 | struct az_device *az = dev->priv; | ||
| 307 | 304 | ||
| 308 | switch (ctrl->id) { | 305 | switch (ctrl->id) { |
| 309 | case V4L2_CID_AUDIO_MUTE: | 306 | case V4L2_CID_AUDIO_MUTE: |
| @@ -322,8 +319,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, | |||
| 322 | static int vidioc_s_ctrl (struct file *file, void *priv, | 319 | static int vidioc_s_ctrl (struct file *file, void *priv, |
| 323 | struct v4l2_control *ctrl) | 320 | struct v4l2_control *ctrl) |
| 324 | { | 321 | { |
| 325 | struct video_device *dev = video_devdata(file); | 322 | struct az_device *az = video_drvdata(file); |
| 326 | struct az_device *az = dev->priv; | ||
| 327 | 323 | ||
| 328 | switch (ctrl->id) { | 324 | switch (ctrl->id) { |
| 329 | case V4L2_CID_AUDIO_MUTE: | 325 | case V4L2_CID_AUDIO_MUTE: |
| @@ -342,10 +338,21 @@ static int vidioc_s_ctrl (struct file *file, void *priv, | |||
| 342 | 338 | ||
| 343 | static struct az_device aztech_unit; | 339 | static struct az_device aztech_unit; |
| 344 | 340 | ||
| 341 | static int aztech_exclusive_open(struct inode *inode, struct file *file) | ||
| 342 | { | ||
| 343 | return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0; | ||
| 344 | } | ||
| 345 | |||
| 346 | static int aztech_exclusive_release(struct inode *inode, struct file *file) | ||
| 347 | { | ||
| 348 | clear_bit(0, &aztech_unit.in_use); | ||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | |||
| 345 | static const struct file_operations aztech_fops = { | 352 | static const struct file_operations aztech_fops = { |
| 346 | .owner = THIS_MODULE, | 353 | .owner = THIS_MODULE, |
| 347 | .open = video_exclusive_open, | 354 | .open = aztech_exclusive_open, |
| 348 | .release = video_exclusive_release, | 355 | .release = aztech_exclusive_release, |
| 349 | .ioctl = video_ioctl2, | 356 | .ioctl = video_ioctl2, |
| 350 | #ifdef CONFIG_COMPAT | 357 | #ifdef CONFIG_COMPAT |
| 351 | .compat_ioctl = v4l_compat_ioctl32, | 358 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -369,9 +376,10 @@ static const struct v4l2_ioctl_ops aztech_ioctl_ops = { | |||
| 369 | }; | 376 | }; |
| 370 | 377 | ||
| 371 | static struct video_device aztech_radio = { | 378 | static struct video_device aztech_radio = { |
| 372 | .name = "Aztech radio", | 379 | .name = "Aztech radio", |
| 373 | .fops = &aztech_fops, | 380 | .fops = &aztech_fops, |
| 374 | .ioctl_ops = &aztech_ioctl_ops, | 381 | .ioctl_ops = &aztech_ioctl_ops, |
| 382 | .release = video_device_release_empty, | ||
| 375 | }; | 383 | }; |
| 376 | 384 | ||
| 377 | module_param_named(debug,aztech_radio.debug, int, 0644); | 385 | module_param_named(debug,aztech_radio.debug, int, 0644); |
| @@ -392,7 +400,7 @@ static int __init aztech_init(void) | |||
| 392 | } | 400 | } |
| 393 | 401 | ||
| 394 | mutex_init(&lock); | 402 | mutex_init(&lock); |
| 395 | aztech_radio.priv=&aztech_unit; | 403 | video_set_drvdata(&aztech_radio, &aztech_unit); |
| 396 | 404 | ||
| 397 | if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) { | 405 | if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) { |
| 398 | release_region(io,2); | 406 | release_region(io,2); |
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 04c3698d32e4..0490a1fa999d 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c | |||
| @@ -589,6 +589,7 @@ static struct video_device cadet_radio = { | |||
| 589 | .name = "Cadet radio", | 589 | .name = "Cadet radio", |
| 590 | .fops = &cadet_fops, | 590 | .fops = &cadet_fops, |
| 591 | .ioctl_ops = &cadet_ioctl_ops, | 591 | .ioctl_ops = &cadet_ioctl_ops, |
| 592 | .release = video_device_release_empty, | ||
| 592 | }; | 593 | }; |
| 593 | 594 | ||
| 594 | #ifdef CONFIG_PNP | 595 | #ifdef CONFIG_PNP |
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 5cd7f032298d..e15bee6d7cfc 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c | |||
| @@ -100,9 +100,8 @@ struct gemtek_pci_card { | |||
| 100 | u8 mute; | 100 | u8 mute; |
| 101 | }; | 101 | }; |
| 102 | 102 | ||
| 103 | static const char rcsid[] = "$Id: radio-gemtek-pci.c,v 1.1 2001/07/23 08:08:16 ted Exp ted $"; | ||
| 104 | |||
| 105 | static int nr_radio = -1; | 103 | static int nr_radio = -1; |
| 104 | static unsigned long in_use; | ||
| 106 | 105 | ||
| 107 | static inline u8 gemtek_pci_out( u16 value, u32 port ) | 106 | static inline u8 gemtek_pci_out( u16 value, u32 port ) |
| 108 | { | 107 | { |
| @@ -205,8 +204,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
| 205 | static int vidioc_g_tuner(struct file *file, void *priv, | 204 | static int vidioc_g_tuner(struct file *file, void *priv, |
| 206 | struct v4l2_tuner *v) | 205 | struct v4l2_tuner *v) |
| 207 | { | 206 | { |
| 208 | struct video_device *dev = video_devdata(file); | 207 | struct gemtek_pci_card *card = video_drvdata(file); |
| 209 | struct gemtek_pci_card *card = dev->priv; | ||
| 210 | 208 | ||
| 211 | if (v->index > 0) | 209 | if (v->index > 0) |
| 212 | return -EINVAL; | 210 | return -EINVAL; |
| @@ -233,8 +231,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
| 233 | static int vidioc_s_frequency(struct file *file, void *priv, | 231 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 234 | struct v4l2_frequency *f) | 232 | struct v4l2_frequency *f) |
| 235 | { | 233 | { |
| 236 | struct video_device *dev = video_devdata(file); | 234 | struct gemtek_pci_card *card = video_drvdata(file); |
| 237 | struct gemtek_pci_card *card = dev->priv; | ||
| 238 | 235 | ||
| 239 | if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) || | 236 | if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) || |
| 240 | (f->frequency > GEMTEK_PCI_RANGE_HIGH) ) | 237 | (f->frequency > GEMTEK_PCI_RANGE_HIGH) ) |
| @@ -248,8 +245,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 248 | static int vidioc_g_frequency(struct file *file, void *priv, | 245 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 249 | struct v4l2_frequency *f) | 246 | struct v4l2_frequency *f) |
| 250 | { | 247 | { |
| 251 | struct video_device *dev = video_devdata(file); | 248 | struct gemtek_pci_card *card = video_drvdata(file); |
| 252 | struct gemtek_pci_card *card = dev->priv; | ||
| 253 | 249 | ||
| 254 | f->type = V4L2_TUNER_RADIO; | 250 | f->type = V4L2_TUNER_RADIO; |
| 255 | f->frequency = card->current_frequency; | 251 | f->frequency = card->current_frequency; |
| @@ -273,8 +269,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 273 | static int vidioc_g_ctrl(struct file *file, void *priv, | 269 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 274 | struct v4l2_control *ctrl) | 270 | struct v4l2_control *ctrl) |
| 275 | { | 271 | { |
| 276 | struct video_device *dev = video_devdata(file); | 272 | struct gemtek_pci_card *card = video_drvdata(file); |
| 277 | struct gemtek_pci_card *card = dev->priv; | ||
| 278 | 273 | ||
| 279 | switch (ctrl->id) { | 274 | switch (ctrl->id) { |
| 280 | case V4L2_CID_AUDIO_MUTE: | 275 | case V4L2_CID_AUDIO_MUTE: |
| @@ -293,8 +288,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 293 | static int vidioc_s_ctrl(struct file *file, void *priv, | 288 | static int vidioc_s_ctrl(struct file *file, void *priv, |
| 294 | struct v4l2_control *ctrl) | 289 | struct v4l2_control *ctrl) |
| 295 | { | 290 | { |
| 296 | struct video_device *dev = video_devdata(file); | 291 | struct gemtek_pci_card *card = video_drvdata(file); |
| 297 | struct gemtek_pci_card *card = dev->priv; | ||
| 298 | 292 | ||
| 299 | switch (ctrl->id) { | 293 | switch (ctrl->id) { |
| 300 | case V4L2_CID_AUDIO_MUTE: | 294 | case V4L2_CID_AUDIO_MUTE: |
| @@ -364,10 +358,21 @@ MODULE_DEVICE_TABLE( pci, gemtek_pci_id ); | |||
| 364 | 358 | ||
| 365 | static int mx = 1; | 359 | static int mx = 1; |
| 366 | 360 | ||
| 361 | static int gemtek_pci_exclusive_open(struct inode *inode, struct file *file) | ||
| 362 | { | ||
| 363 | return test_and_set_bit(0, &in_use) ? -EBUSY : 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | static int gemtek_pci_exclusive_release(struct inode *inode, struct file *file) | ||
| 367 | { | ||
| 368 | clear_bit(0, &in_use); | ||
| 369 | return 0; | ||
| 370 | } | ||
| 371 | |||
| 367 | static const struct file_operations gemtek_pci_fops = { | 372 | static const struct file_operations gemtek_pci_fops = { |
| 368 | .owner = THIS_MODULE, | 373 | .owner = THIS_MODULE, |
| 369 | .open = video_exclusive_open, | 374 | .open = gemtek_pci_exclusive_open, |
| 370 | .release = video_exclusive_release, | 375 | .release = gemtek_pci_exclusive_release, |
| 371 | .ioctl = video_ioctl2, | 376 | .ioctl = video_ioctl2, |
| 372 | #ifdef CONFIG_COMPAT | 377 | #ifdef CONFIG_COMPAT |
| 373 | .compat_ioctl = v4l_compat_ioctl32, | 378 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -391,9 +396,10 @@ static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = { | |||
| 391 | }; | 396 | }; |
| 392 | 397 | ||
| 393 | static struct video_device vdev_template = { | 398 | static struct video_device vdev_template = { |
| 394 | .name = "Gemtek PCI Radio", | 399 | .name = "Gemtek PCI Radio", |
| 395 | .fops = &gemtek_pci_fops, | 400 | .fops = &gemtek_pci_fops, |
| 396 | .ioctl_ops = &gemtek_pci_ioctl_ops, | 401 | .ioctl_ops = &gemtek_pci_ioctl_ops, |
| 402 | .release = video_device_release_empty, | ||
| 397 | }; | 403 | }; |
| 398 | 404 | ||
| 399 | static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id ) | 405 | static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id ) |
| @@ -431,7 +437,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci | |||
| 431 | } | 437 | } |
| 432 | 438 | ||
| 433 | card->videodev = devradio; | 439 | card->videodev = devradio; |
| 434 | devradio->priv = card; | 440 | video_set_drvdata(devradio, card); |
| 435 | gemtek_pci_mute( card ); | 441 | gemtek_pci_mute( card ); |
| 436 | 442 | ||
| 437 | printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", | 443 | printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", |
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 0a0f956bb308..d131a5d38128 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c | |||
| @@ -57,6 +57,7 @@ static int shutdown = 1; | |||
| 57 | static int keepmuted = 1; | 57 | static int keepmuted = 1; |
| 58 | static int initmute = 1; | 58 | static int initmute = 1; |
| 59 | static int radio_nr = -1; | 59 | static int radio_nr = -1; |
| 60 | static unsigned long in_use; | ||
| 60 | 61 | ||
| 61 | module_param(io, int, 0444); | 62 | module_param(io, int, 0444); |
| 62 | MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic " | 63 | MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic " |
| @@ -393,10 +394,21 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
| 393 | } | 394 | } |
| 394 | }; | 395 | }; |
| 395 | 396 | ||
| 397 | static int gemtek_exclusive_open(struct inode *inode, struct file *file) | ||
| 398 | { | ||
| 399 | return test_and_set_bit(0, &in_use) ? -EBUSY : 0; | ||
| 400 | } | ||
| 401 | |||
| 402 | static int gemtek_exclusive_release(struct inode *inode, struct file *file) | ||
| 403 | { | ||
| 404 | clear_bit(0, &in_use); | ||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | |||
| 396 | static const struct file_operations gemtek_fops = { | 408 | static const struct file_operations gemtek_fops = { |
| 397 | .owner = THIS_MODULE, | 409 | .owner = THIS_MODULE, |
| 398 | .open = video_exclusive_open, | 410 | .open = gemtek_exclusive_open, |
| 399 | .release = video_exclusive_release, | 411 | .release = gemtek_exclusive_release, |
| 400 | .ioctl = video_ioctl2, | 412 | .ioctl = video_ioctl2, |
| 401 | #ifdef CONFIG_COMPAT | 413 | #ifdef CONFIG_COMPAT |
| 402 | .compat_ioctl = v4l_compat_ioctl32, | 414 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -447,8 +459,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) | |||
| 447 | static int vidioc_s_frequency(struct file *file, void *priv, | 459 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 448 | struct v4l2_frequency *f) | 460 | struct v4l2_frequency *f) |
| 449 | { | 461 | { |
| 450 | struct video_device *dev = video_devdata(file); | 462 | struct gemtek_device *rt = video_drvdata(file); |
| 451 | struct gemtek_device *rt = dev->priv; | ||
| 452 | 463 | ||
| 453 | gemtek_setfreq(rt, f->frequency); | 464 | gemtek_setfreq(rt, f->frequency); |
| 454 | 465 | ||
| @@ -458,8 +469,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 458 | static int vidioc_g_frequency(struct file *file, void *priv, | 469 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 459 | struct v4l2_frequency *f) | 470 | struct v4l2_frequency *f) |
| 460 | { | 471 | { |
| 461 | struct video_device *dev = video_devdata(file); | 472 | struct gemtek_device *rt = video_drvdata(file); |
| 462 | struct gemtek_device *rt = dev->priv; | ||
| 463 | 473 | ||
| 464 | f->type = V4L2_TUNER_RADIO; | 474 | f->type = V4L2_TUNER_RADIO; |
| 465 | f->frequency = rt->lastfreq; | 475 | f->frequency = rt->lastfreq; |
| @@ -483,8 +493,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 483 | static int vidioc_g_ctrl(struct file *file, void *priv, | 493 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 484 | struct v4l2_control *ctrl) | 494 | struct v4l2_control *ctrl) |
| 485 | { | 495 | { |
| 486 | struct video_device *dev = video_devdata(file); | 496 | struct gemtek_device *rt = video_drvdata(file); |
| 487 | struct gemtek_device *rt = dev->priv; | ||
| 488 | 497 | ||
| 489 | switch (ctrl->id) { | 498 | switch (ctrl->id) { |
| 490 | case V4L2_CID_AUDIO_MUTE: | 499 | case V4L2_CID_AUDIO_MUTE: |
| @@ -503,8 +512,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 503 | static int vidioc_s_ctrl(struct file *file, void *priv, | 512 | static int vidioc_s_ctrl(struct file *file, void *priv, |
| 504 | struct v4l2_control *ctrl) | 513 | struct v4l2_control *ctrl) |
| 505 | { | 514 | { |
| 506 | struct video_device *dev = video_devdata(file); | 515 | struct gemtek_device *rt = video_drvdata(file); |
| 507 | struct gemtek_device *rt = dev->priv; | ||
| 508 | 516 | ||
| 509 | switch (ctrl->id) { | 517 | switch (ctrl->id) { |
| 510 | case V4L2_CID_AUDIO_MUTE: | 518 | case V4L2_CID_AUDIO_MUTE: |
| @@ -569,9 +577,10 @@ static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { | |||
| 569 | }; | 577 | }; |
| 570 | 578 | ||
| 571 | static struct video_device gemtek_radio = { | 579 | static struct video_device gemtek_radio = { |
| 572 | .name = "GemTek Radio card", | 580 | .name = "GemTek Radio card", |
| 573 | .fops = &gemtek_fops, | 581 | .fops = &gemtek_fops, |
| 574 | .ioctl_ops = &gemtek_ioctl_ops, | 582 | .ioctl_ops = &gemtek_ioctl_ops, |
| 583 | .release = video_device_release_empty, | ||
| 575 | }; | 584 | }; |
| 576 | 585 | ||
| 577 | /* | 586 | /* |
| @@ -610,7 +619,7 @@ static int __init gemtek_init(void) | |||
| 610 | return -EINVAL; | 619 | return -EINVAL; |
| 611 | } | 620 | } |
| 612 | 621 | ||
| 613 | gemtek_radio.priv = &gemtek_unit; | 622 | video_set_drvdata(&gemtek_radio, &gemtek_unit); |
| 614 | 623 | ||
| 615 | if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) { | 624 | if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) { |
| 616 | release_region(io, 1); | 625 | release_region(io, 1); |
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 9ef0a763eeb7..4bf4d007bcfa 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c | |||
| @@ -75,7 +75,21 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
| 75 | static int radio_nr = -1; | 75 | static int radio_nr = -1; |
| 76 | module_param(radio_nr, int, 0); | 76 | module_param(radio_nr, int, 0); |
| 77 | 77 | ||
| 78 | static unsigned long in_use; | ||
| 79 | |||
| 78 | static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent); | 80 | static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent); |
| 81 | |||
| 82 | static int maestro_exclusive_open(struct inode *inode, struct file *file) | ||
| 83 | { | ||
| 84 | return test_and_set_bit(0, &in_use) ? -EBUSY : 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int maestro_exclusive_release(struct inode *inode, struct file *file) | ||
| 88 | { | ||
| 89 | clear_bit(0, &in_use); | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 79 | static void maestro_remove(struct pci_dev *pdev); | 93 | static void maestro_remove(struct pci_dev *pdev); |
| 80 | 94 | ||
| 81 | static struct pci_device_id maestro_r_pci_tbl[] = { | 95 | static struct pci_device_id maestro_r_pci_tbl[] = { |
| @@ -98,8 +112,8 @@ static struct pci_driver maestro_r_driver = { | |||
| 98 | 112 | ||
| 99 | static const struct file_operations maestro_fops = { | 113 | static const struct file_operations maestro_fops = { |
| 100 | .owner = THIS_MODULE, | 114 | .owner = THIS_MODULE, |
| 101 | .open = video_exclusive_open, | 115 | .open = maestro_exclusive_open, |
| 102 | .release = video_exclusive_release, | 116 | .release = maestro_exclusive_release, |
| 103 | .ioctl = video_ioctl2, | 117 | .ioctl = video_ioctl2, |
| 104 | #ifdef CONFIG_COMPAT | 118 | #ifdef CONFIG_COMPAT |
| 105 | .compat_ioctl = v4l_compat_ioctl32, | 119 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -196,8 +210,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
| 196 | static int vidioc_g_tuner(struct file *file, void *priv, | 210 | static int vidioc_g_tuner(struct file *file, void *priv, |
| 197 | struct v4l2_tuner *v) | 211 | struct v4l2_tuner *v) |
| 198 | { | 212 | { |
| 199 | struct video_device *dev = video_devdata(file); | 213 | struct radio_device *card = video_drvdata(file); |
| 200 | struct radio_device *card = video_get_drvdata(dev); | ||
| 201 | 214 | ||
| 202 | if (v->index > 0) | 215 | if (v->index > 0) |
| 203 | return -EINVAL; | 216 | return -EINVAL; |
| @@ -229,8 +242,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
| 229 | static int vidioc_s_frequency(struct file *file, void *priv, | 242 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 230 | struct v4l2_frequency *f) | 243 | struct v4l2_frequency *f) |
| 231 | { | 244 | { |
| 232 | struct video_device *dev = video_devdata(file); | 245 | struct radio_device *card = video_drvdata(file); |
| 233 | struct radio_device *card = video_get_drvdata(dev); | ||
| 234 | 246 | ||
| 235 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) | 247 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) |
| 236 | return -EINVAL; | 248 | return -EINVAL; |
| @@ -241,8 +253,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 241 | static int vidioc_g_frequency(struct file *file, void *priv, | 253 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 242 | struct v4l2_frequency *f) | 254 | struct v4l2_frequency *f) |
| 243 | { | 255 | { |
| 244 | struct video_device *dev = video_devdata(file); | 256 | struct radio_device *card = video_drvdata(file); |
| 245 | struct radio_device *card = video_get_drvdata(dev); | ||
| 246 | 257 | ||
| 247 | f->type = V4L2_TUNER_RADIO; | 258 | f->type = V4L2_TUNER_RADIO; |
| 248 | f->frequency = BITS2FREQ(radio_bits_get(card)); | 259 | f->frequency = BITS2FREQ(radio_bits_get(card)); |
| @@ -267,8 +278,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 267 | static int vidioc_g_ctrl(struct file *file, void *priv, | 278 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 268 | struct v4l2_control *ctrl) | 279 | struct v4l2_control *ctrl) |
| 269 | { | 280 | { |
| 270 | struct video_device *dev = video_devdata(file); | 281 | struct radio_device *card = video_drvdata(file); |
| 271 | struct radio_device *card = video_get_drvdata(dev); | ||
| 272 | 282 | ||
| 273 | switch (ctrl->id) { | 283 | switch (ctrl->id) { |
| 274 | case V4L2_CID_AUDIO_MUTE: | 284 | case V4L2_CID_AUDIO_MUTE: |
| @@ -281,8 +291,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 281 | static int vidioc_s_ctrl(struct file *file, void *priv, | 291 | static int vidioc_s_ctrl(struct file *file, void *priv, |
| 282 | struct v4l2_control *ctrl) | 292 | struct v4l2_control *ctrl) |
| 283 | { | 293 | { |
| 284 | struct video_device *dev = video_devdata(file); | 294 | struct radio_device *card = video_drvdata(file); |
| 285 | struct radio_device *card = video_get_drvdata(dev); | ||
| 286 | register u16 io = card->io; | 295 | register u16 io = card->io; |
| 287 | register u16 omask = inw(io + IO_MASK); | 296 | register u16 omask = inw(io + IO_MASK); |
| 288 | 297 | ||
| @@ -374,6 +383,7 @@ static struct video_device maestro_radio = { | |||
| 374 | .name = "Maestro radio", | 383 | .name = "Maestro radio", |
| 375 | .fops = &maestro_fops, | 384 | .fops = &maestro_fops, |
| 376 | .ioctl_ops = &maestro_ioctl_ops, | 385 | .ioctl_ops = &maestro_ioctl_ops, |
| 386 | .release = video_device_release, | ||
| 377 | }; | 387 | }; |
| 378 | 388 | ||
| 379 | static int __devinit maestro_probe(struct pci_dev *pdev, | 389 | static int __devinit maestro_probe(struct pci_dev *pdev, |
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 0cc6fcb041fd..c777a17b00bc 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c | |||
| @@ -85,6 +85,7 @@ static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16 ; | |||
| 85 | static int radio_nr = -1; | 85 | static int radio_nr = -1; |
| 86 | module_param(radio_nr, int, 0); | 86 | module_param(radio_nr, int, 0); |
| 87 | 87 | ||
| 88 | static unsigned long in_use; | ||
| 88 | 89 | ||
| 89 | #define FREQ_LO 50*16000 | 90 | #define FREQ_LO 50*16000 |
| 90 | #define FREQ_HI 150*16000 | 91 | #define FREQ_HI 150*16000 |
| @@ -99,10 +100,21 @@ module_param(radio_nr, int, 0); | |||
| 99 | #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) | 100 | #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) |
| 100 | 101 | ||
| 101 | 102 | ||
| 103 | static int maxiradio_exclusive_open(struct inode *inode, struct file *file) | ||
| 104 | { | ||
| 105 | return test_and_set_bit(0, &in_use) ? -EBUSY : 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | static int maxiradio_exclusive_release(struct inode *inode, struct file *file) | ||
| 109 | { | ||
| 110 | clear_bit(0, &in_use); | ||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 102 | static const struct file_operations maxiradio_fops = { | 114 | static const struct file_operations maxiradio_fops = { |
| 103 | .owner = THIS_MODULE, | 115 | .owner = THIS_MODULE, |
| 104 | .open = video_exclusive_open, | 116 | .open = maxiradio_exclusive_open, |
| 105 | .release = video_exclusive_release, | 117 | .release = maxiradio_exclusive_release, |
| 106 | .ioctl = video_ioctl2, | 118 | .ioctl = video_ioctl2, |
| 107 | #ifdef CONFIG_COMPAT | 119 | #ifdef CONFIG_COMPAT |
| 108 | .compat_ioctl = v4l_compat_ioctl32, | 120 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -219,8 +231,7 @@ static int vidioc_querycap (struct file *file, void *priv, | |||
| 219 | static int vidioc_g_tuner (struct file *file, void *priv, | 231 | static int vidioc_g_tuner (struct file *file, void *priv, |
| 220 | struct v4l2_tuner *v) | 232 | struct v4l2_tuner *v) |
| 221 | { | 233 | { |
| 222 | struct video_device *dev = video_devdata(file); | 234 | struct radio_device *card = video_drvdata(file); |
| 223 | struct radio_device *card=dev->priv; | ||
| 224 | 235 | ||
| 225 | if (v->index > 0) | 236 | if (v->index > 0) |
| 226 | return -EINVAL; | 237 | return -EINVAL; |
| @@ -290,8 +301,7 @@ static int vidioc_s_audio (struct file *file, void *priv, | |||
| 290 | static int vidioc_s_frequency (struct file *file, void *priv, | 301 | static int vidioc_s_frequency (struct file *file, void *priv, |
| 291 | struct v4l2_frequency *f) | 302 | struct v4l2_frequency *f) |
| 292 | { | 303 | { |
| 293 | struct video_device *dev = video_devdata(file); | 304 | struct radio_device *card = video_drvdata(file); |
| 294 | struct radio_device *card=dev->priv; | ||
| 295 | 305 | ||
| 296 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { | 306 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { |
| 297 | dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", | 307 | dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", |
| @@ -312,8 +322,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, | |||
| 312 | static int vidioc_g_frequency (struct file *file, void *priv, | 322 | static int vidioc_g_frequency (struct file *file, void *priv, |
| 313 | struct v4l2_frequency *f) | 323 | struct v4l2_frequency *f) |
| 314 | { | 324 | { |
| 315 | struct video_device *dev = video_devdata(file); | 325 | struct radio_device *card = video_drvdata(file); |
| 316 | struct radio_device *card=dev->priv; | ||
| 317 | 326 | ||
| 318 | f->type = V4L2_TUNER_RADIO; | 327 | f->type = V4L2_TUNER_RADIO; |
| 319 | f->frequency = card->freq; | 328 | f->frequency = card->freq; |
| @@ -343,8 +352,7 @@ static int vidioc_queryctrl (struct file *file, void *priv, | |||
| 343 | static int vidioc_g_ctrl (struct file *file, void *priv, | 352 | static int vidioc_g_ctrl (struct file *file, void *priv, |
| 344 | struct v4l2_control *ctrl) | 353 | struct v4l2_control *ctrl) |
| 345 | { | 354 | { |
| 346 | struct video_device *dev = video_devdata(file); | 355 | struct radio_device *card = video_drvdata(file); |
| 347 | struct radio_device *card=dev->priv; | ||
| 348 | 356 | ||
| 349 | switch (ctrl->id) { | 357 | switch (ctrl->id) { |
| 350 | case V4L2_CID_AUDIO_MUTE: | 358 | case V4L2_CID_AUDIO_MUTE: |
| @@ -358,8 +366,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, | |||
| 358 | static int vidioc_s_ctrl (struct file *file, void *priv, | 366 | static int vidioc_s_ctrl (struct file *file, void *priv, |
| 359 | struct v4l2_control *ctrl) | 367 | struct v4l2_control *ctrl) |
| 360 | { | 368 | { |
| 361 | struct video_device *dev = video_devdata(file); | 369 | struct radio_device *card = video_drvdata(file); |
| 362 | struct radio_device *card=dev->priv; | ||
| 363 | 370 | ||
| 364 | switch (ctrl->id) { | 371 | switch (ctrl->id) { |
| 365 | case V4L2_CID_AUDIO_MUTE: | 372 | case V4L2_CID_AUDIO_MUTE: |
| @@ -390,9 +397,10 @@ static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { | |||
| 390 | }; | 397 | }; |
| 391 | 398 | ||
| 392 | static struct video_device maxiradio_radio = { | 399 | static struct video_device maxiradio_radio = { |
| 393 | .name = "Maxi Radio FM2000 radio", | 400 | .name = "Maxi Radio FM2000 radio", |
| 394 | .fops = &maxiradio_fops, | 401 | .fops = &maxiradio_fops, |
| 395 | .ioctl_ops = &maxiradio_ioctl_ops, | 402 | .ioctl_ops = &maxiradio_ioctl_ops, |
| 403 | .release = video_device_release_empty, | ||
| 396 | }; | 404 | }; |
| 397 | 405 | ||
| 398 | static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 406 | static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
| @@ -408,7 +416,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d | |||
| 408 | 416 | ||
| 409 | radio_unit.io = pci_resource_start(pdev, 0); | 417 | radio_unit.io = pci_resource_start(pdev, 0); |
| 410 | mutex_init(&radio_unit.lock); | 418 | mutex_init(&radio_unit.lock); |
| 411 | maxiradio_radio.priv = &radio_unit; | 419 | video_set_drvdata(&maxiradio_radio, &radio_unit); |
| 412 | 420 | ||
| 413 | if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) { | 421 | if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) { |
| 414 | printk("radio-maxiradio: can't register device!"); | 422 | printk("radio-maxiradio: can't register device!"); |
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c new file mode 100644 index 000000000000..a33717c48003 --- /dev/null +++ b/drivers/media/radio/radio-mr800.c | |||
| @@ -0,0 +1,628 @@ | |||
| 1 | /* | ||
| 2 | * A driver for the AverMedia MR 800 USB FM radio. This device plugs | ||
| 3 | * into both the USB and an analog audio input, so this thing | ||
| 4 | * only deals with initialization and frequency setting, the | ||
| 5 | * audio data has to be handled by a sound driver. | ||
| 6 | * | ||
| 7 | * Copyright (c) 2008 Alexey Klimov <klimov.linux@gmail.com> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 22 | */ | ||
| 23 | |||
| 24 | /* | ||
| 25 | * Big thanks to authors of dsbr100.c and radio-si470x.c | ||
| 26 | * | ||
| 27 | * When work was looked pretty good, i discover this: | ||
| 28 | * http://av-usbradio.sourceforge.net/index.php | ||
| 29 | * http://sourceforge.net/projects/av-usbradio/ | ||
| 30 | * Latest release of theirs project was in 2005. | ||
| 31 | * Probably, this driver could be improved trough using their | ||
| 32 | * achievements (specifications given). | ||
| 33 | * So, we have smth to begin with. | ||
| 34 | * | ||
| 35 | * History: | ||
| 36 | * Version 0.01: First working version. | ||
| 37 | * It's required to blacklist AverMedia USB Radio | ||
| 38 | * in usbhid/hid-quirks.c | ||
| 39 | * | ||
| 40 | * Many things to do: | ||
| 41 | * - Correct power managment of device (suspend & resume) | ||
| 42 | * - Make x86 independance (little-endian and big-endian stuff) | ||
| 43 | * - Add code for scanning and smooth tuning | ||
| 44 | * - Checked and add stereo&mono stuff | ||
| 45 | * - Add code for sensitivity value | ||
| 46 | * - Correct mistakes | ||
| 47 | * - In Japan another FREQ_MIN and FREQ_MAX | ||
| 48 | */ | ||
| 49 | |||
| 50 | /* kernel includes */ | ||
| 51 | #include <linux/kernel.h> | ||
| 52 | #include <linux/module.h> | ||
| 53 | #include <linux/init.h> | ||
| 54 | #include <linux/slab.h> | ||
| 55 | #include <linux/input.h> | ||
| 56 | #include <linux/videodev2.h> | ||
| 57 | #include <media/v4l2-common.h> | ||
| 58 | #include <media/v4l2-ioctl.h> | ||
| 59 | #include <linux/usb.h> | ||
| 60 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | ||
| 61 | |||
| 62 | /* driver and module definitions */ | ||
| 63 | #define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>" | ||
| 64 | #define DRIVER_DESC "AverMedia MR 800 USB FM radio driver" | ||
| 65 | #define DRIVER_VERSION "0.01" | ||
| 66 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 1) | ||
| 67 | |||
| 68 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 69 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 70 | MODULE_LICENSE("GPL"); | ||
| 71 | |||
| 72 | #define USB_AMRADIO_VENDOR 0x07ca | ||
| 73 | #define USB_AMRADIO_PRODUCT 0xb800 | ||
| 74 | |||
| 75 | /* Probably USB_TIMEOUT should be modified in module parameter */ | ||
| 76 | #define BUFFER_LENGTH 8 | ||
| 77 | #define USB_TIMEOUT 500 | ||
| 78 | |||
| 79 | /* Frequency limits in MHz -- these are European values. For Japanese | ||
| 80 | devices, that would be 76 and 91. */ | ||
| 81 | #define FREQ_MIN 87.5 | ||
| 82 | #define FREQ_MAX 108.0 | ||
| 83 | #define FREQ_MUL 16000 | ||
| 84 | |||
| 85 | /* module parameter */ | ||
| 86 | static int radio_nr = -1; | ||
| 87 | module_param(radio_nr, int, 0); | ||
| 88 | MODULE_PARM_DESC(radio_nr, "Radio Nr"); | ||
| 89 | |||
| 90 | static struct v4l2_queryctrl radio_qctrl[] = { | ||
| 91 | { | ||
| 92 | .id = V4L2_CID_AUDIO_MUTE, | ||
| 93 | .name = "Mute", | ||
| 94 | .minimum = 0, | ||
| 95 | .maximum = 1, | ||
| 96 | .step = 1, | ||
| 97 | .default_value = 1, | ||
| 98 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 99 | }, | ||
| 100 | /* HINT: the disabled controls are only here to satify kradio and such apps */ | ||
| 101 | { .id = V4L2_CID_AUDIO_VOLUME, | ||
| 102 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
| 103 | }, | ||
| 104 | { | ||
| 105 | .id = V4L2_CID_AUDIO_BALANCE, | ||
| 106 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
| 107 | }, | ||
| 108 | { | ||
| 109 | .id = V4L2_CID_AUDIO_BASS, | ||
| 110 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
| 111 | }, | ||
| 112 | { | ||
| 113 | .id = V4L2_CID_AUDIO_TREBLE, | ||
| 114 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
| 115 | }, | ||
| 116 | { | ||
| 117 | .id = V4L2_CID_AUDIO_LOUDNESS, | ||
| 118 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
| 119 | }, | ||
| 120 | }; | ||
| 121 | |||
| 122 | static int usb_amradio_probe(struct usb_interface *intf, | ||
| 123 | const struct usb_device_id *id); | ||
| 124 | static void usb_amradio_disconnect(struct usb_interface *intf); | ||
| 125 | static int usb_amradio_open(struct inode *inode, struct file *file); | ||
| 126 | static int usb_amradio_close(struct inode *inode, struct file *file); | ||
| 127 | static int usb_amradio_suspend(struct usb_interface *intf, | ||
| 128 | pm_message_t message); | ||
| 129 | static int usb_amradio_resume(struct usb_interface *intf); | ||
| 130 | |||
| 131 | /* Data for one (physical) device */ | ||
| 132 | struct amradio_device { | ||
| 133 | /* reference to USB and video device */ | ||
| 134 | struct usb_device *usbdev; | ||
| 135 | struct video_device *videodev; | ||
| 136 | |||
| 137 | unsigned char *buffer; | ||
| 138 | struct mutex lock; /* buffer locking */ | ||
| 139 | int curfreq; | ||
| 140 | int stereo; | ||
| 141 | int users; | ||
| 142 | int removed; | ||
| 143 | int muted; | ||
| 144 | }; | ||
| 145 | |||
| 146 | /* USB Device ID List */ | ||
| 147 | static struct usb_device_id usb_amradio_device_table[] = { | ||
| 148 | {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT, | ||
| 149 | USB_CLASS_HID, 0, 0) }, | ||
| 150 | { } /* Terminating entry */ | ||
| 151 | }; | ||
| 152 | |||
| 153 | MODULE_DEVICE_TABLE(usb, usb_amradio_device_table); | ||
| 154 | |||
| 155 | /* USB subsystem interface */ | ||
| 156 | static struct usb_driver usb_amradio_driver = { | ||
| 157 | .name = "radio-mr800", | ||
| 158 | .probe = usb_amradio_probe, | ||
| 159 | .disconnect = usb_amradio_disconnect, | ||
| 160 | .suspend = usb_amradio_suspend, | ||
| 161 | .resume = usb_amradio_resume, | ||
| 162 | .reset_resume = usb_amradio_resume, | ||
| 163 | .id_table = usb_amradio_device_table, | ||
| 164 | .supports_autosuspend = 1, | ||
| 165 | }; | ||
| 166 | |||
| 167 | /* switch on radio. Send 8 bytes to device. */ | ||
| 168 | static int amradio_start(struct amradio_device *radio) | ||
| 169 | { | ||
| 170 | int retval; | ||
| 171 | int size; | ||
| 172 | |||
| 173 | mutex_lock(&radio->lock); | ||
| 174 | |||
| 175 | radio->buffer[0] = 0x00; | ||
| 176 | radio->buffer[1] = 0x55; | ||
| 177 | radio->buffer[2] = 0xaa; | ||
| 178 | radio->buffer[3] = 0x00; | ||
| 179 | radio->buffer[4] = 0xab; | ||
| 180 | radio->buffer[5] = 0x00; | ||
| 181 | radio->buffer[6] = 0x00; | ||
| 182 | radio->buffer[7] = 0x00; | ||
| 183 | |||
| 184 | retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), | ||
| 185 | (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); | ||
| 186 | |||
| 187 | if (retval) { | ||
| 188 | mutex_unlock(&radio->lock); | ||
| 189 | return retval; | ||
| 190 | } | ||
| 191 | |||
| 192 | mutex_unlock(&radio->lock); | ||
| 193 | |||
| 194 | radio->muted = 0; | ||
| 195 | |||
| 196 | return retval; | ||
| 197 | } | ||
| 198 | |||
| 199 | /* switch off radio */ | ||
| 200 | static int amradio_stop(struct amradio_device *radio) | ||
| 201 | { | ||
| 202 | int retval; | ||
| 203 | int size; | ||
| 204 | |||
| 205 | mutex_lock(&radio->lock); | ||
| 206 | |||
| 207 | radio->buffer[0] = 0x00; | ||
| 208 | radio->buffer[1] = 0x55; | ||
| 209 | radio->buffer[2] = 0xaa; | ||
| 210 | radio->buffer[3] = 0x00; | ||
| 211 | radio->buffer[4] = 0xab; | ||
| 212 | radio->buffer[5] = 0x01; | ||
| 213 | radio->buffer[6] = 0x00; | ||
| 214 | radio->buffer[7] = 0x00; | ||
| 215 | |||
| 216 | retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), | ||
| 217 | (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); | ||
| 218 | |||
| 219 | if (retval) { | ||
| 220 | mutex_unlock(&radio->lock); | ||
| 221 | return retval; | ||
| 222 | } | ||
| 223 | |||
| 224 | mutex_unlock(&radio->lock); | ||
| 225 | |||
| 226 | radio->muted = 1; | ||
| 227 | |||
| 228 | return retval; | ||
| 229 | } | ||
| 230 | |||
| 231 | /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ | ||
| 232 | static int amradio_setfreq(struct amradio_device *radio, int freq) | ||
| 233 | { | ||
| 234 | int retval; | ||
| 235 | int size; | ||
| 236 | unsigned short freq_send = 0x13 + (freq >> 3) / 25; | ||
| 237 | |||
| 238 | mutex_lock(&radio->lock); | ||
| 239 | |||
| 240 | radio->buffer[0] = 0x00; | ||
| 241 | radio->buffer[1] = 0x55; | ||
| 242 | radio->buffer[2] = 0xaa; | ||
| 243 | radio->buffer[3] = 0x03; | ||
| 244 | radio->buffer[4] = 0xa4; | ||
| 245 | radio->buffer[5] = 0x00; | ||
| 246 | radio->buffer[6] = 0x00; | ||
| 247 | radio->buffer[7] = 0x08; | ||
| 248 | |||
| 249 | retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), | ||
| 250 | (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); | ||
| 251 | |||
| 252 | if (retval) { | ||
| 253 | mutex_unlock(&radio->lock); | ||
| 254 | return retval; | ||
| 255 | } | ||
| 256 | |||
| 257 | /* frequency is calculated from freq_send and placed in first 2 bytes */ | ||
| 258 | radio->buffer[0] = (freq_send >> 8) & 0xff; | ||
| 259 | radio->buffer[1] = freq_send & 0xff; | ||
| 260 | radio->buffer[2] = 0x01; | ||
| 261 | radio->buffer[3] = 0x00; | ||
| 262 | radio->buffer[4] = 0x00; | ||
| 263 | /* 5 and 6 bytes of buffer already = 0x00 */ | ||
| 264 | radio->buffer[7] = 0x00; | ||
| 265 | |||
| 266 | retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), | ||
| 267 | (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); | ||
| 268 | |||
| 269 | if (retval) { | ||
| 270 | mutex_unlock(&radio->lock); | ||
| 271 | return retval; | ||
| 272 | } | ||
| 273 | |||
| 274 | mutex_unlock(&radio->lock); | ||
| 275 | |||
| 276 | radio->stereo = 0; | ||
| 277 | |||
| 278 | return retval; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* USB subsystem interface begins here */ | ||
| 282 | |||
| 283 | /* handle unplugging of the device, release data structures | ||
| 284 | if nothing keeps us from doing it. If something is still | ||
| 285 | keeping us busy, the release callback of v4l will take care | ||
| 286 | of releasing it. */ | ||
| 287 | static void usb_amradio_disconnect(struct usb_interface *intf) | ||
| 288 | { | ||
| 289 | struct amradio_device *radio = usb_get_intfdata(intf); | ||
| 290 | |||
| 291 | usb_set_intfdata(intf, NULL); | ||
| 292 | |||
| 293 | if (radio) { | ||
| 294 | video_unregister_device(radio->videodev); | ||
| 295 | radio->videodev = NULL; | ||
| 296 | if (radio->users) { | ||
| 297 | kfree(radio->buffer); | ||
| 298 | kfree(radio); | ||
| 299 | } else { | ||
| 300 | radio->removed = 1; | ||
| 301 | } | ||
| 302 | } | ||
| 303 | } | ||
| 304 | |||
| 305 | /* vidioc_querycap - query device capabilities */ | ||
| 306 | static int vidioc_querycap(struct file *file, void *priv, | ||
| 307 | struct v4l2_capability *v) | ||
| 308 | { | ||
| 309 | strlcpy(v->driver, "radio-mr800", sizeof(v->driver)); | ||
| 310 | strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card)); | ||
| 311 | sprintf(v->bus_info, "USB"); | ||
| 312 | v->version = RADIO_VERSION; | ||
| 313 | v->capabilities = V4L2_CAP_TUNER; | ||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | /* vidioc_g_tuner - get tuner attributes */ | ||
| 318 | static int vidioc_g_tuner(struct file *file, void *priv, | ||
| 319 | struct v4l2_tuner *v) | ||
| 320 | { | ||
| 321 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | ||
| 322 | |||
| 323 | if (v->index > 0) | ||
| 324 | return -EINVAL; | ||
| 325 | |||
| 326 | /* TODO: Add function which look is signal stereo or not | ||
| 327 | * amradio_getstat(radio); | ||
| 328 | */ | ||
| 329 | radio->stereo = -1; | ||
| 330 | strcpy(v->name, "FM"); | ||
| 331 | v->type = V4L2_TUNER_RADIO; | ||
| 332 | v->rangelow = FREQ_MIN * FREQ_MUL; | ||
| 333 | v->rangehigh = FREQ_MAX * FREQ_MUL; | ||
| 334 | v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
| 335 | v->capability = V4L2_TUNER_CAP_LOW; | ||
| 336 | if (radio->stereo) | ||
| 337 | v->audmode = V4L2_TUNER_MODE_STEREO; | ||
| 338 | else | ||
| 339 | v->audmode = V4L2_TUNER_MODE_MONO; | ||
| 340 | v->signal = 0xffff; /* Can't get the signal strength, sad.. */ | ||
| 341 | v->afc = 0; /* Don't know what is this */ | ||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | |||
| 345 | /* vidioc_s_tuner - set tuner attributes */ | ||
| 346 | static int vidioc_s_tuner(struct file *file, void *priv, | ||
| 347 | struct v4l2_tuner *v) | ||
| 348 | { | ||
| 349 | if (v->index > 0) | ||
| 350 | return -EINVAL; | ||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | /* vidioc_s_frequency - set tuner radio frequency */ | ||
| 355 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
| 356 | struct v4l2_frequency *f) | ||
| 357 | { | ||
| 358 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | ||
| 359 | |||
| 360 | radio->curfreq = f->frequency; | ||
| 361 | if (amradio_setfreq(radio, radio->curfreq) < 0) | ||
| 362 | warn("Set frequency failed"); | ||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | /* vidioc_g_frequency - get tuner radio frequency */ | ||
| 367 | static int vidioc_g_frequency(struct file *file, void *priv, | ||
| 368 | struct v4l2_frequency *f) | ||
| 369 | { | ||
| 370 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | ||
| 371 | |||
| 372 | f->type = V4L2_TUNER_RADIO; | ||
| 373 | f->frequency = radio->curfreq; | ||
| 374 | return 0; | ||
| 375 | } | ||
| 376 | |||
| 377 | /* vidioc_queryctrl - enumerate control items */ | ||
| 378 | static int vidioc_queryctrl(struct file *file, void *priv, | ||
| 379 | struct v4l2_queryctrl *qc) | ||
| 380 | { | ||
| 381 | int i; | ||
| 382 | |||
| 383 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | ||
| 384 | if (qc->id && qc->id == radio_qctrl[i].id) { | ||
| 385 | memcpy(qc, &(radio_qctrl[i]), | ||
| 386 | sizeof(*qc)); | ||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | return -EINVAL; | ||
| 391 | } | ||
| 392 | |||
| 393 | /* vidioc_g_ctrl - get the value of a control */ | ||
| 394 | static int vidioc_g_ctrl(struct file *file, void *priv, | ||
| 395 | struct v4l2_control *ctrl) | ||
| 396 | { | ||
| 397 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | ||
| 398 | |||
| 399 | switch (ctrl->id) { | ||
| 400 | case V4L2_CID_AUDIO_MUTE: | ||
| 401 | ctrl->value = radio->muted; | ||
| 402 | return 0; | ||
| 403 | } | ||
| 404 | return -EINVAL; | ||
| 405 | } | ||
| 406 | |||
| 407 | /* vidioc_s_ctrl - set the value of a control */ | ||
| 408 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
| 409 | struct v4l2_control *ctrl) | ||
| 410 | { | ||
| 411 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | ||
| 412 | |||
| 413 | switch (ctrl->id) { | ||
| 414 | case V4L2_CID_AUDIO_MUTE: | ||
| 415 | if (ctrl->value) { | ||
| 416 | if (amradio_stop(radio) < 0) { | ||
| 417 | warn("amradio_stop() failed"); | ||
| 418 | return -1; | ||
| 419 | } | ||
| 420 | } else { | ||
| 421 | if (amradio_start(radio) < 0) { | ||
| 422 | warn("amradio_start() failed"); | ||
| 423 | return -1; | ||
| 424 | } | ||
| 425 | } | ||
| 426 | return 0; | ||
| 427 | } | ||
| 428 | return -EINVAL; | ||
| 429 | } | ||
| 430 | |||
| 431 | /* vidioc_g_audio - get audio attributes */ | ||
| 432 | static int vidioc_g_audio(struct file *file, void *priv, | ||
| 433 | struct v4l2_audio *a) | ||
| 434 | { | ||
| 435 | if (a->index > 1) | ||
| 436 | return -EINVAL; | ||
| 437 | |||
| 438 | strcpy(a->name, "Radio"); | ||
| 439 | a->capability = V4L2_AUDCAP_STEREO; | ||
| 440 | return 0; | ||
| 441 | } | ||
| 442 | |||
| 443 | /* vidioc_s_audio - set audio attributes */ | ||
| 444 | static int vidioc_s_audio(struct file *file, void *priv, | ||
| 445 | struct v4l2_audio *a) | ||
| 446 | { | ||
| 447 | if (a->index != 0) | ||
| 448 | return -EINVAL; | ||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | |||
| 452 | /* vidioc_g_input - get input */ | ||
| 453 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | ||
| 454 | { | ||
| 455 | *i = 0; | ||
| 456 | return 0; | ||
| 457 | } | ||
| 458 | |||
| 459 | /* vidioc_s_input - set input */ | ||
| 460 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) | ||
| 461 | { | ||
| 462 | if (i != 0) | ||
| 463 | return -EINVAL; | ||
| 464 | return 0; | ||
| 465 | } | ||
| 466 | |||
| 467 | /* open device - amradio_start() and amradio_setfreq() */ | ||
| 468 | static int usb_amradio_open(struct inode *inode, struct file *file) | ||
| 469 | { | ||
| 470 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | ||
| 471 | |||
| 472 | radio->users = 1; | ||
| 473 | radio->muted = 1; | ||
| 474 | |||
| 475 | if (amradio_start(radio) < 0) { | ||
| 476 | warn("Radio did not start up properly"); | ||
| 477 | radio->users = 0; | ||
| 478 | return -EIO; | ||
| 479 | } | ||
| 480 | if (amradio_setfreq(radio, radio->curfreq) < 0) | ||
| 481 | warn("Set frequency failed"); | ||
| 482 | return 0; | ||
| 483 | } | ||
| 484 | |||
| 485 | /*close device - free driver structures */ | ||
| 486 | static int usb_amradio_close(struct inode *inode, struct file *file) | ||
| 487 | { | ||
| 488 | struct amradio_device *radio = video_get_drvdata(video_devdata(file)); | ||
| 489 | |||
| 490 | if (!radio) | ||
| 491 | return -ENODEV; | ||
| 492 | radio->users = 0; | ||
| 493 | if (radio->removed) { | ||
| 494 | kfree(radio->buffer); | ||
| 495 | kfree(radio); | ||
| 496 | } | ||
| 497 | return 0; | ||
| 498 | } | ||
| 499 | |||
| 500 | /* Suspend device - stop device. Need to be checked and fixed */ | ||
| 501 | static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) | ||
| 502 | { | ||
| 503 | struct amradio_device *radio = usb_get_intfdata(intf); | ||
| 504 | |||
| 505 | if (amradio_stop(radio) < 0) | ||
| 506 | warn("amradio_stop() failed"); | ||
| 507 | |||
| 508 | info("radio-mr800: Going into suspend.."); | ||
| 509 | |||
| 510 | return 0; | ||
| 511 | } | ||
| 512 | |||
| 513 | /* Resume device - start device. Need to be checked and fixed */ | ||
| 514 | static int usb_amradio_resume(struct usb_interface *intf) | ||
| 515 | { | ||
| 516 | struct amradio_device *radio = usb_get_intfdata(intf); | ||
| 517 | |||
| 518 | if (amradio_start(radio) < 0) | ||
| 519 | warn("amradio_start() failed"); | ||
| 520 | |||
| 521 | info("radio-mr800: Coming out of suspend.."); | ||
| 522 | |||
| 523 | return 0; | ||
| 524 | } | ||
| 525 | |||
| 526 | /* File system interface */ | ||
| 527 | static const struct file_operations usb_amradio_fops = { | ||
| 528 | .owner = THIS_MODULE, | ||
| 529 | .open = usb_amradio_open, | ||
| 530 | .release = usb_amradio_close, | ||
| 531 | .ioctl = video_ioctl2, | ||
| 532 | #ifdef CONFIG_COMPAT | ||
| 533 | .compat_ioctl = v4l_compat_ioctl32, | ||
| 534 | #endif | ||
| 535 | .llseek = no_llseek, | ||
| 536 | }; | ||
| 537 | |||
| 538 | static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { | ||
| 539 | .vidioc_querycap = vidioc_querycap, | ||
| 540 | .vidioc_g_tuner = vidioc_g_tuner, | ||
| 541 | .vidioc_s_tuner = vidioc_s_tuner, | ||
| 542 | .vidioc_g_frequency = vidioc_g_frequency, | ||
| 543 | .vidioc_s_frequency = vidioc_s_frequency, | ||
| 544 | .vidioc_queryctrl = vidioc_queryctrl, | ||
| 545 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
| 546 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
| 547 | .vidioc_g_audio = vidioc_g_audio, | ||
| 548 | .vidioc_s_audio = vidioc_s_audio, | ||
| 549 | .vidioc_g_input = vidioc_g_input, | ||
| 550 | .vidioc_s_input = vidioc_s_input, | ||
| 551 | }; | ||
| 552 | |||
| 553 | /* V4L2 interface */ | ||
| 554 | static struct video_device amradio_videodev_template = { | ||
| 555 | .name = "AverMedia MR 800 USB FM Radio", | ||
| 556 | .fops = &usb_amradio_fops, | ||
| 557 | .ioctl_ops = &usb_amradio_ioctl_ops, | ||
| 558 | .release = video_device_release, | ||
| 559 | }; | ||
| 560 | |||
| 561 | /* check if the device is present and register with v4l and | ||
| 562 | usb if it is */ | ||
| 563 | static int usb_amradio_probe(struct usb_interface *intf, | ||
| 564 | const struct usb_device_id *id) | ||
| 565 | { | ||
| 566 | struct amradio_device *radio; | ||
| 567 | |||
| 568 | radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL); | ||
| 569 | |||
| 570 | if (!(radio)) | ||
| 571 | return -ENOMEM; | ||
| 572 | |||
| 573 | radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); | ||
| 574 | |||
| 575 | if (!(radio->buffer)) { | ||
| 576 | kfree(radio); | ||
| 577 | return -ENOMEM; | ||
| 578 | } | ||
| 579 | |||
| 580 | radio->videodev = video_device_alloc(); | ||
| 581 | |||
| 582 | if (!(radio->videodev)) { | ||
| 583 | kfree(radio->buffer); | ||
| 584 | kfree(radio); | ||
| 585 | return -ENOMEM; | ||
| 586 | } | ||
| 587 | |||
| 588 | memcpy(radio->videodev, &amradio_videodev_template, | ||
| 589 | sizeof(amradio_videodev_template)); | ||
| 590 | |||
| 591 | radio->removed = 0; | ||
| 592 | radio->users = 0; | ||
| 593 | radio->usbdev = interface_to_usbdev(intf); | ||
| 594 | radio->curfreq = 95.16 * FREQ_MUL; | ||
| 595 | |||
| 596 | mutex_init(&radio->lock); | ||
| 597 | |||
| 598 | video_set_drvdata(radio->videodev, radio); | ||
| 599 | if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { | ||
| 600 | warn("Could not register video device"); | ||
| 601 | video_device_release(radio->videodev); | ||
| 602 | kfree(radio->buffer); | ||
| 603 | kfree(radio); | ||
| 604 | return -EIO; | ||
| 605 | } | ||
| 606 | |||
| 607 | usb_set_intfdata(intf, radio); | ||
| 608 | return 0; | ||
| 609 | } | ||
| 610 | |||
| 611 | static int __init amradio_init(void) | ||
| 612 | { | ||
| 613 | int retval = usb_register(&usb_amradio_driver); | ||
| 614 | |||
| 615 | info(DRIVER_VERSION " " DRIVER_DESC); | ||
| 616 | if (retval) | ||
| 617 | err("usb_register failed. Error number %d", retval); | ||
| 618 | return retval; | ||
| 619 | } | ||
| 620 | |||
| 621 | static void __exit amradio_exit(void) | ||
| 622 | { | ||
| 623 | usb_deregister(&usb_amradio_driver); | ||
| 624 | } | ||
| 625 | |||
| 626 | module_init(amradio_init); | ||
| 627 | module_exit(amradio_exit); | ||
| 628 | |||
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 6d820e2481e7..a67079777419 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c | |||
| @@ -52,6 +52,7 @@ static spinlock_t lock; | |||
| 52 | 52 | ||
| 53 | struct rt_device | 53 | struct rt_device |
| 54 | { | 54 | { |
| 55 | unsigned long in_use; | ||
| 55 | int port; | 56 | int port; |
| 56 | unsigned long curfreq; | 57 | unsigned long curfreq; |
| 57 | int muted; | 58 | int muted; |
| @@ -153,8 +154,7 @@ static int rt_getsigstr(struct rt_device *dev) | |||
| 153 | static int vidioc_g_tuner(struct file *file, void *priv, | 154 | static int vidioc_g_tuner(struct file *file, void *priv, |
| 154 | struct v4l2_tuner *v) | 155 | struct v4l2_tuner *v) |
| 155 | { | 156 | { |
| 156 | struct video_device *dev = video_devdata(file); | 157 | struct rt_device *rt = video_drvdata(file); |
| 157 | struct rt_device *rt = dev->priv; | ||
| 158 | 158 | ||
| 159 | if (v->index > 0) | 159 | if (v->index > 0) |
| 160 | return -EINVAL; | 160 | return -EINVAL; |
| @@ -173,8 +173,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
| 173 | static int vidioc_s_frequency(struct file *file, void *priv, | 173 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 174 | struct v4l2_frequency *f) | 174 | struct v4l2_frequency *f) |
| 175 | { | 175 | { |
| 176 | struct video_device *dev = video_devdata(file); | 176 | struct rt_device *rt = video_drvdata(file); |
| 177 | struct rt_device *rt = dev->priv; | ||
| 178 | 177 | ||
| 179 | rt->curfreq = f->frequency; | 178 | rt->curfreq = f->frequency; |
| 180 | rt_setfreq(rt, rt->curfreq); | 179 | rt_setfreq(rt, rt->curfreq); |
| @@ -184,8 +183,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 184 | static int vidioc_g_frequency(struct file *file, void *priv, | 183 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 185 | struct v4l2_frequency *f) | 184 | struct v4l2_frequency *f) |
| 186 | { | 185 | { |
| 187 | struct video_device *dev = video_devdata(file); | 186 | struct rt_device *rt = video_drvdata(file); |
| 188 | struct rt_device *rt = dev->priv; | ||
| 189 | 187 | ||
| 190 | f->type = V4L2_TUNER_RADIO; | 188 | f->type = V4L2_TUNER_RADIO; |
| 191 | f->frequency = rt->curfreq; | 189 | f->frequency = rt->curfreq; |
| @@ -210,8 +208,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 210 | static int vidioc_g_ctrl(struct file *file, void *priv, | 208 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 211 | struct v4l2_control *ctrl) | 209 | struct v4l2_control *ctrl) |
| 212 | { | 210 | { |
| 213 | struct video_device *dev = video_devdata(file); | 211 | struct rt_device *rt = video_drvdata(file); |
| 214 | struct rt_device *rt = dev->priv; | ||
| 215 | 212 | ||
| 216 | switch (ctrl->id) { | 213 | switch (ctrl->id) { |
| 217 | case V4L2_CID_AUDIO_MUTE: | 214 | case V4L2_CID_AUDIO_MUTE: |
| @@ -230,8 +227,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 230 | static int vidioc_s_ctrl(struct file *file, void *priv, | 227 | static int vidioc_s_ctrl(struct file *file, void *priv, |
| 231 | struct v4l2_control *ctrl) | 228 | struct v4l2_control *ctrl) |
| 232 | { | 229 | { |
| 233 | struct video_device *dev = video_devdata(file); | 230 | struct rt_device *rt = video_drvdata(file); |
| 234 | struct rt_device *rt = dev->priv; | ||
| 235 | 231 | ||
| 236 | switch (ctrl->id) { | 232 | switch (ctrl->id) { |
| 237 | case V4L2_CID_AUDIO_MUTE: | 233 | case V4L2_CID_AUDIO_MUTE: |
| @@ -284,10 +280,21 @@ static int vidioc_s_audio(struct file *file, void *priv, | |||
| 284 | 280 | ||
| 285 | static struct rt_device rtrack2_unit; | 281 | static struct rt_device rtrack2_unit; |
| 286 | 282 | ||
| 283 | static int rtrack2_exclusive_open(struct inode *inode, struct file *file) | ||
| 284 | { | ||
| 285 | return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int rtrack2_exclusive_release(struct inode *inode, struct file *file) | ||
| 289 | { | ||
| 290 | clear_bit(0, &rtrack2_unit.in_use); | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 287 | static const struct file_operations rtrack2_fops = { | 294 | static const struct file_operations rtrack2_fops = { |
| 288 | .owner = THIS_MODULE, | 295 | .owner = THIS_MODULE, |
| 289 | .open = video_exclusive_open, | 296 | .open = rtrack2_exclusive_open, |
| 290 | .release = video_exclusive_release, | 297 | .release = rtrack2_exclusive_release, |
| 291 | .ioctl = video_ioctl2, | 298 | .ioctl = video_ioctl2, |
| 292 | #ifdef CONFIG_COMPAT | 299 | #ifdef CONFIG_COMPAT |
| 293 | .compat_ioctl = v4l_compat_ioctl32, | 300 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -314,6 +321,7 @@ static struct video_device rtrack2_radio = { | |||
| 314 | .name = "RadioTrack II radio", | 321 | .name = "RadioTrack II radio", |
| 315 | .fops = &rtrack2_fops, | 322 | .fops = &rtrack2_fops, |
| 316 | .ioctl_ops = &rtrack2_ioctl_ops, | 323 | .ioctl_ops = &rtrack2_ioctl_ops, |
| 324 | .release = video_device_release_empty, | ||
| 317 | }; | 325 | }; |
| 318 | 326 | ||
| 319 | static int __init rtrack2_init(void) | 327 | static int __init rtrack2_init(void) |
| @@ -329,7 +337,7 @@ static int __init rtrack2_init(void) | |||
| 329 | return -EBUSY; | 337 | return -EBUSY; |
| 330 | } | 338 | } |
| 331 | 339 | ||
| 332 | rtrack2_radio.priv=&rtrack2_unit; | 340 | video_set_drvdata(&rtrack2_radio, &rtrack2_unit); |
| 333 | 341 | ||
| 334 | spin_lock_init(&lock); | 342 | spin_lock_init(&lock); |
| 335 | if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { | 343 | if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { |
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 0d478f54a907..329c90bddadd 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c | |||
| @@ -45,6 +45,7 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
| 45 | 45 | ||
| 46 | struct fmi_device | 46 | struct fmi_device |
| 47 | { | 47 | { |
| 48 | unsigned long in_use; | ||
| 48 | int port; | 49 | int port; |
| 49 | int curvol; /* 1 or 0 */ | 50 | int curvol; /* 1 or 0 */ |
| 50 | unsigned long curfreq; /* freq in kHz */ | 51 | unsigned long curfreq; /* freq in kHz */ |
| @@ -146,8 +147,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
| 146 | struct v4l2_tuner *v) | 147 | struct v4l2_tuner *v) |
| 147 | { | 148 | { |
| 148 | int mult; | 149 | int mult; |
| 149 | struct video_device *dev = video_devdata(file); | 150 | struct fmi_device *fmi = video_drvdata(file); |
| 150 | struct fmi_device *fmi = dev->priv; | ||
| 151 | 151 | ||
| 152 | if (v->index > 0) | 152 | if (v->index > 0) |
| 153 | return -EINVAL; | 153 | return -EINVAL; |
| @@ -175,8 +175,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
| 175 | static int vidioc_s_frequency(struct file *file, void *priv, | 175 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 176 | struct v4l2_frequency *f) | 176 | struct v4l2_frequency *f) |
| 177 | { | 177 | { |
| 178 | struct video_device *dev = video_devdata(file); | 178 | struct fmi_device *fmi = video_drvdata(file); |
| 179 | struct fmi_device *fmi = dev->priv; | ||
| 180 | 179 | ||
| 181 | if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) | 180 | if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) |
| 182 | f->frequency *= 1000; | 181 | f->frequency *= 1000; |
| @@ -193,8 +192,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 193 | static int vidioc_g_frequency(struct file *file, void *priv, | 192 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 194 | struct v4l2_frequency *f) | 193 | struct v4l2_frequency *f) |
| 195 | { | 194 | { |
| 196 | struct video_device *dev = video_devdata(file); | 195 | struct fmi_device *fmi = video_drvdata(file); |
| 197 | struct fmi_device *fmi = dev->priv; | ||
| 198 | 196 | ||
| 199 | f->type = V4L2_TUNER_RADIO; | 197 | f->type = V4L2_TUNER_RADIO; |
| 200 | f->frequency = fmi->curfreq; | 198 | f->frequency = fmi->curfreq; |
| @@ -221,8 +219,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 221 | static int vidioc_g_ctrl(struct file *file, void *priv, | 219 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 222 | struct v4l2_control *ctrl) | 220 | struct v4l2_control *ctrl) |
| 223 | { | 221 | { |
| 224 | struct video_device *dev = video_devdata(file); | 222 | struct fmi_device *fmi = video_drvdata(file); |
| 225 | struct fmi_device *fmi = dev->priv; | ||
| 226 | 223 | ||
| 227 | switch (ctrl->id) { | 224 | switch (ctrl->id) { |
| 228 | case V4L2_CID_AUDIO_MUTE: | 225 | case V4L2_CID_AUDIO_MUTE: |
| @@ -235,8 +232,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 235 | static int vidioc_s_ctrl(struct file *file, void *priv, | 232 | static int vidioc_s_ctrl(struct file *file, void *priv, |
| 236 | struct v4l2_control *ctrl) | 233 | struct v4l2_control *ctrl) |
| 237 | { | 234 | { |
| 238 | struct video_device *dev = video_devdata(file); | 235 | struct fmi_device *fmi = video_drvdata(file); |
| 239 | struct fmi_device *fmi = dev->priv; | ||
| 240 | 236 | ||
| 241 | switch (ctrl->id) { | 237 | switch (ctrl->id) { |
| 242 | case V4L2_CID_AUDIO_MUTE: | 238 | case V4L2_CID_AUDIO_MUTE: |
| @@ -284,10 +280,21 @@ static int vidioc_s_audio(struct file *file, void *priv, | |||
| 284 | 280 | ||
| 285 | static struct fmi_device fmi_unit; | 281 | static struct fmi_device fmi_unit; |
| 286 | 282 | ||
| 283 | static int fmi_exclusive_open(struct inode *inode, struct file *file) | ||
| 284 | { | ||
| 285 | return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int fmi_exclusive_release(struct inode *inode, struct file *file) | ||
| 289 | { | ||
| 290 | clear_bit(0, &fmi_unit.in_use); | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 287 | static const struct file_operations fmi_fops = { | 294 | static const struct file_operations fmi_fops = { |
| 288 | .owner = THIS_MODULE, | 295 | .owner = THIS_MODULE, |
| 289 | .open = video_exclusive_open, | 296 | .open = fmi_exclusive_open, |
| 290 | .release = video_exclusive_release, | 297 | .release = fmi_exclusive_release, |
| 291 | .ioctl = video_ioctl2, | 298 | .ioctl = video_ioctl2, |
| 292 | #ifdef CONFIG_COMPAT | 299 | #ifdef CONFIG_COMPAT |
| 293 | .compat_ioctl = v4l_compat_ioctl32, | 300 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -314,6 +321,7 @@ static struct video_device fmi_radio = { | |||
| 314 | .name = "SF16FMx radio", | 321 | .name = "SF16FMx radio", |
| 315 | .fops = &fmi_fops, | 322 | .fops = &fmi_fops, |
| 316 | .ioctl_ops = &fmi_ioctl_ops, | 323 | .ioctl_ops = &fmi_ioctl_ops, |
| 324 | .release = video_device_release_empty, | ||
| 317 | }; | 325 | }; |
| 318 | 326 | ||
| 319 | /* ladis: this is my card. does any other types exist? */ | 327 | /* ladis: this is my card. does any other types exist? */ |
| @@ -373,7 +381,7 @@ static int __init fmi_init(void) | |||
| 373 | fmi_unit.curvol = 0; | 381 | fmi_unit.curvol = 0; |
| 374 | fmi_unit.curfreq = 0; | 382 | fmi_unit.curfreq = 0; |
| 375 | fmi_unit.flags = V4L2_TUNER_CAP_LOW; | 383 | fmi_unit.flags = V4L2_TUNER_CAP_LOW; |
| 376 | fmi_radio.priv = &fmi_unit; | 384 | video_set_drvdata(&fmi_radio, &fmi_unit); |
| 377 | 385 | ||
| 378 | mutex_init(&lock); | 386 | mutex_init(&lock); |
| 379 | 387 | ||
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 6290553d24be..b1f47c322e02 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c | |||
| @@ -64,6 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
| 64 | /* this should be static vars for module size */ | 64 | /* this should be static vars for module size */ |
| 65 | struct fmr2_device | 65 | struct fmr2_device |
| 66 | { | 66 | { |
| 67 | unsigned long in_use; | ||
| 67 | int port; | 68 | int port; |
| 68 | int curvol; /* 0-15 */ | 69 | int curvol; /* 0-15 */ |
| 69 | int mute; | 70 | int mute; |
| @@ -229,8 +230,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
| 229 | struct v4l2_tuner *v) | 230 | struct v4l2_tuner *v) |
| 230 | { | 231 | { |
| 231 | int mult; | 232 | int mult; |
| 232 | struct video_device *dev = video_devdata(file); | 233 | struct fmr2_device *fmr2 = video_drvdata(file); |
| 233 | struct fmr2_device *fmr2 = dev->priv; | ||
| 234 | 234 | ||
| 235 | if (v->index > 0) | 235 | if (v->index > 0) |
| 236 | return -EINVAL; | 236 | return -EINVAL; |
| @@ -262,8 +262,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
| 262 | static int vidioc_s_frequency(struct file *file, void *priv, | 262 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 263 | struct v4l2_frequency *f) | 263 | struct v4l2_frequency *f) |
| 264 | { | 264 | { |
| 265 | struct video_device *dev = video_devdata(file); | 265 | struct fmr2_device *fmr2 = video_drvdata(file); |
| 266 | struct fmr2_device *fmr2 = dev->priv; | ||
| 267 | 266 | ||
| 268 | if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) | 267 | if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) |
| 269 | f->frequency *= 1000; | 268 | f->frequency *= 1000; |
| @@ -286,8 +285,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 286 | static int vidioc_g_frequency(struct file *file, void *priv, | 285 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 287 | struct v4l2_frequency *f) | 286 | struct v4l2_frequency *f) |
| 288 | { | 287 | { |
| 289 | struct video_device *dev = video_devdata(file); | 288 | struct fmr2_device *fmr2 = video_drvdata(file); |
| 290 | struct fmr2_device *fmr2 = dev->priv; | ||
| 291 | 289 | ||
| 292 | f->type = V4L2_TUNER_RADIO; | 290 | f->type = V4L2_TUNER_RADIO; |
| 293 | f->frequency = fmr2->curfreq; | 291 | f->frequency = fmr2->curfreq; |
| @@ -313,8 +311,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 313 | static int vidioc_g_ctrl(struct file *file, void *priv, | 311 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 314 | struct v4l2_control *ctrl) | 312 | struct v4l2_control *ctrl) |
| 315 | { | 313 | { |
| 316 | struct video_device *dev = video_devdata(file); | 314 | struct fmr2_device *fmr2 = video_drvdata(file); |
| 317 | struct fmr2_device *fmr2 = dev->priv; | ||
| 318 | 315 | ||
| 319 | switch (ctrl->id) { | 316 | switch (ctrl->id) { |
| 320 | case V4L2_CID_AUDIO_MUTE: | 317 | case V4L2_CID_AUDIO_MUTE: |
| @@ -330,8 +327,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 330 | static int vidioc_s_ctrl(struct file *file, void *priv, | 327 | static int vidioc_s_ctrl(struct file *file, void *priv, |
| 331 | struct v4l2_control *ctrl) | 328 | struct v4l2_control *ctrl) |
| 332 | { | 329 | { |
| 333 | struct video_device *dev = video_devdata(file); | 330 | struct fmr2_device *fmr2 = video_drvdata(file); |
| 334 | struct fmr2_device *fmr2 = dev->priv; | ||
| 335 | 331 | ||
| 336 | switch (ctrl->id) { | 332 | switch (ctrl->id) { |
| 337 | case V4L2_CID_AUDIO_MUTE: | 333 | case V4L2_CID_AUDIO_MUTE: |
| @@ -400,10 +396,21 @@ static int vidioc_s_audio(struct file *file, void *priv, | |||
| 400 | 396 | ||
| 401 | static struct fmr2_device fmr2_unit; | 397 | static struct fmr2_device fmr2_unit; |
| 402 | 398 | ||
| 399 | static int fmr2_exclusive_open(struct inode *inode, struct file *file) | ||
| 400 | { | ||
| 401 | return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0; | ||
| 402 | } | ||
| 403 | |||
| 404 | static int fmr2_exclusive_release(struct inode *inode, struct file *file) | ||
| 405 | { | ||
| 406 | clear_bit(0, &fmr2_unit.in_use); | ||
| 407 | return 0; | ||
| 408 | } | ||
| 409 | |||
| 403 | static const struct file_operations fmr2_fops = { | 410 | static const struct file_operations fmr2_fops = { |
| 404 | .owner = THIS_MODULE, | 411 | .owner = THIS_MODULE, |
| 405 | .open = video_exclusive_open, | 412 | .open = fmr2_exclusive_open, |
| 406 | .release = video_exclusive_release, | 413 | .release = fmr2_exclusive_release, |
| 407 | .ioctl = video_ioctl2, | 414 | .ioctl = video_ioctl2, |
| 408 | #ifdef CONFIG_COMPAT | 415 | #ifdef CONFIG_COMPAT |
| 409 | .compat_ioctl = v4l_compat_ioctl32, | 416 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -430,6 +437,7 @@ static struct video_device fmr2_radio = { | |||
| 430 | .name = "SF16FMR2 radio", | 437 | .name = "SF16FMR2 radio", |
| 431 | .fops = &fmr2_fops, | 438 | .fops = &fmr2_fops, |
| 432 | .ioctl_ops = &fmr2_ioctl_ops, | 439 | .ioctl_ops = &fmr2_ioctl_ops, |
| 440 | .release = video_device_release_empty, | ||
| 433 | }; | 441 | }; |
| 434 | 442 | ||
| 435 | static int __init fmr2_init(void) | 443 | static int __init fmr2_init(void) |
| @@ -441,7 +449,7 @@ static int __init fmr2_init(void) | |||
| 441 | fmr2_unit.stereo = 1; | 449 | fmr2_unit.stereo = 1; |
| 442 | fmr2_unit.flags = V4L2_TUNER_CAP_LOW; | 450 | fmr2_unit.flags = V4L2_TUNER_CAP_LOW; |
| 443 | fmr2_unit.card_type = 0; | 451 | fmr2_unit.card_type = 0; |
| 444 | fmr2_radio.priv = &fmr2_unit; | 452 | video_set_drvdata(&fmr2_radio, &fmr2_unit); |
| 445 | 453 | ||
| 446 | mutex_init(&lock); | 454 | mutex_init(&lock); |
| 447 | 455 | ||
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 16c7ef20265c..f6cedcd3ab97 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c | |||
| @@ -986,7 +986,7 @@ static void si470x_work(struct work_struct *work) | |||
| 986 | static ssize_t si470x_fops_read(struct file *file, char __user *buf, | 986 | static ssize_t si470x_fops_read(struct file *file, char __user *buf, |
| 987 | size_t count, loff_t *ppos) | 987 | size_t count, loff_t *ppos) |
| 988 | { | 988 | { |
| 989 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 989 | struct si470x_device *radio = video_drvdata(file); |
| 990 | int retval = 0; | 990 | int retval = 0; |
| 991 | unsigned int block_count = 0; | 991 | unsigned int block_count = 0; |
| 992 | 992 | ||
| @@ -1047,7 +1047,7 @@ done: | |||
| 1047 | static unsigned int si470x_fops_poll(struct file *file, | 1047 | static unsigned int si470x_fops_poll(struct file *file, |
| 1048 | struct poll_table_struct *pts) | 1048 | struct poll_table_struct *pts) |
| 1049 | { | 1049 | { |
| 1050 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1050 | struct si470x_device *radio = video_drvdata(file); |
| 1051 | int retval = 0; | 1051 | int retval = 0; |
| 1052 | 1052 | ||
| 1053 | /* switch on rds reception */ | 1053 | /* switch on rds reception */ |
| @@ -1071,9 +1071,10 @@ static unsigned int si470x_fops_poll(struct file *file, | |||
| 1071 | */ | 1071 | */ |
| 1072 | static int si470x_fops_open(struct inode *inode, struct file *file) | 1072 | static int si470x_fops_open(struct inode *inode, struct file *file) |
| 1073 | { | 1073 | { |
| 1074 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1074 | struct si470x_device *radio = video_drvdata(file); |
| 1075 | int retval; | 1075 | int retval; |
| 1076 | 1076 | ||
| 1077 | lock_kernel(); | ||
| 1077 | radio->users++; | 1078 | radio->users++; |
| 1078 | 1079 | ||
| 1079 | retval = usb_autopm_get_interface(radio->intf); | 1080 | retval = usb_autopm_get_interface(radio->intf); |
| @@ -1090,6 +1091,7 @@ static int si470x_fops_open(struct inode *inode, struct file *file) | |||
| 1090 | } | 1091 | } |
| 1091 | 1092 | ||
| 1092 | done: | 1093 | done: |
| 1094 | unlock_kernel(); | ||
| 1093 | return retval; | 1095 | return retval; |
| 1094 | } | 1096 | } |
| 1095 | 1097 | ||
| @@ -1099,7 +1101,7 @@ done: | |||
| 1099 | */ | 1101 | */ |
| 1100 | static int si470x_fops_release(struct inode *inode, struct file *file) | 1102 | static int si470x_fops_release(struct inode *inode, struct file *file) |
| 1101 | { | 1103 | { |
| 1102 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1104 | struct si470x_device *radio = video_drvdata(file); |
| 1103 | int retval = 0; | 1105 | int retval = 0; |
| 1104 | 1106 | ||
| 1105 | /* safety check */ | 1107 | /* safety check */ |
| @@ -1282,7 +1284,7 @@ done: | |||
| 1282 | static int si470x_vidioc_g_ctrl(struct file *file, void *priv, | 1284 | static int si470x_vidioc_g_ctrl(struct file *file, void *priv, |
| 1283 | struct v4l2_control *ctrl) | 1285 | struct v4l2_control *ctrl) |
| 1284 | { | 1286 | { |
| 1285 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1287 | struct si470x_device *radio = video_drvdata(file); |
| 1286 | int retval = 0; | 1288 | int retval = 0; |
| 1287 | 1289 | ||
| 1288 | /* safety checks */ | 1290 | /* safety checks */ |
| @@ -1318,7 +1320,7 @@ done: | |||
| 1318 | static int si470x_vidioc_s_ctrl(struct file *file, void *priv, | 1320 | static int si470x_vidioc_s_ctrl(struct file *file, void *priv, |
| 1319 | struct v4l2_control *ctrl) | 1321 | struct v4l2_control *ctrl) |
| 1320 | { | 1322 | { |
| 1321 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1323 | struct si470x_device *radio = video_drvdata(file); |
| 1322 | int retval = 0; | 1324 | int retval = 0; |
| 1323 | 1325 | ||
| 1324 | /* safety checks */ | 1326 | /* safety checks */ |
| @@ -1405,7 +1407,7 @@ done: | |||
| 1405 | static int si470x_vidioc_g_tuner(struct file *file, void *priv, | 1407 | static int si470x_vidioc_g_tuner(struct file *file, void *priv, |
| 1406 | struct v4l2_tuner *tuner) | 1408 | struct v4l2_tuner *tuner) |
| 1407 | { | 1409 | { |
| 1408 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1410 | struct si470x_device *radio = video_drvdata(file); |
| 1409 | int retval = 0; | 1411 | int retval = 0; |
| 1410 | 1412 | ||
| 1411 | /* safety checks */ | 1413 | /* safety checks */ |
| @@ -1471,7 +1473,7 @@ done: | |||
| 1471 | static int si470x_vidioc_s_tuner(struct file *file, void *priv, | 1473 | static int si470x_vidioc_s_tuner(struct file *file, void *priv, |
| 1472 | struct v4l2_tuner *tuner) | 1474 | struct v4l2_tuner *tuner) |
| 1473 | { | 1475 | { |
| 1474 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1476 | struct si470x_device *radio = video_drvdata(file); |
| 1475 | int retval = 0; | 1477 | int retval = 0; |
| 1476 | 1478 | ||
| 1477 | /* safety checks */ | 1479 | /* safety checks */ |
| @@ -1505,7 +1507,7 @@ done: | |||
| 1505 | static int si470x_vidioc_g_frequency(struct file *file, void *priv, | 1507 | static int si470x_vidioc_g_frequency(struct file *file, void *priv, |
| 1506 | struct v4l2_frequency *freq) | 1508 | struct v4l2_frequency *freq) |
| 1507 | { | 1509 | { |
| 1508 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1510 | struct si470x_device *radio = video_drvdata(file); |
| 1509 | int retval = 0; | 1511 | int retval = 0; |
| 1510 | 1512 | ||
| 1511 | /* safety checks */ | 1513 | /* safety checks */ |
| @@ -1534,7 +1536,7 @@ done: | |||
| 1534 | static int si470x_vidioc_s_frequency(struct file *file, void *priv, | 1536 | static int si470x_vidioc_s_frequency(struct file *file, void *priv, |
| 1535 | struct v4l2_frequency *freq) | 1537 | struct v4l2_frequency *freq) |
| 1536 | { | 1538 | { |
| 1537 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1539 | struct si470x_device *radio = video_drvdata(file); |
| 1538 | int retval = 0; | 1540 | int retval = 0; |
| 1539 | 1541 | ||
| 1540 | /* safety checks */ | 1542 | /* safety checks */ |
| @@ -1563,7 +1565,7 @@ done: | |||
| 1563 | static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, | 1565 | static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, |
| 1564 | struct v4l2_hw_freq_seek *seek) | 1566 | struct v4l2_hw_freq_seek *seek) |
| 1565 | { | 1567 | { |
| 1566 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1568 | struct si470x_device *radio = video_drvdata(file); |
| 1567 | int retval = 0; | 1569 | int retval = 0; |
| 1568 | 1570 | ||
| 1569 | /* safety checks */ | 1571 | /* safety checks */ |
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index 0876fecc5f27..0abb186a9473 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c | |||
| @@ -79,6 +79,7 @@ static spinlock_t lock; | |||
| 79 | 79 | ||
| 80 | struct tt_device | 80 | struct tt_device |
| 81 | { | 81 | { |
| 82 | unsigned long in_use; | ||
| 82 | int port; | 83 | int port; |
| 83 | int curvol; | 84 | int curvol; |
| 84 | unsigned long curfreq; | 85 | unsigned long curfreq; |
| @@ -220,8 +221,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
| 220 | static int vidioc_g_tuner(struct file *file, void *priv, | 221 | static int vidioc_g_tuner(struct file *file, void *priv, |
| 221 | struct v4l2_tuner *v) | 222 | struct v4l2_tuner *v) |
| 222 | { | 223 | { |
| 223 | struct video_device *dev = video_devdata(file); | 224 | struct tt_device *tt = video_drvdata(file); |
| 224 | struct tt_device *tt = dev->priv; | ||
| 225 | 225 | ||
| 226 | if (v->index > 0) | 226 | if (v->index > 0) |
| 227 | return -EINVAL; | 227 | return -EINVAL; |
| @@ -248,8 +248,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
| 248 | static int vidioc_s_frequency(struct file *file, void *priv, | 248 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 249 | struct v4l2_frequency *f) | 249 | struct v4l2_frequency *f) |
| 250 | { | 250 | { |
| 251 | struct video_device *dev = video_devdata(file); | 251 | struct tt_device *tt = video_drvdata(file); |
| 252 | struct tt_device *tt = dev->priv; | ||
| 253 | 252 | ||
| 254 | tt->curfreq = f->frequency; | 253 | tt->curfreq = f->frequency; |
| 255 | tt_setfreq(tt, tt->curfreq); | 254 | tt_setfreq(tt, tt->curfreq); |
| @@ -259,8 +258,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 259 | static int vidioc_g_frequency(struct file *file, void *priv, | 258 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 260 | struct v4l2_frequency *f) | 259 | struct v4l2_frequency *f) |
| 261 | { | 260 | { |
| 262 | struct video_device *dev = video_devdata(file); | 261 | struct tt_device *tt = video_drvdata(file); |
| 263 | struct tt_device *tt = dev->priv; | ||
| 264 | 262 | ||
| 265 | f->type = V4L2_TUNER_RADIO; | 263 | f->type = V4L2_TUNER_RADIO; |
| 266 | f->frequency = tt->curfreq; | 264 | f->frequency = tt->curfreq; |
| @@ -285,8 +283,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 285 | static int vidioc_g_ctrl(struct file *file, void *priv, | 283 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 286 | struct v4l2_control *ctrl) | 284 | struct v4l2_control *ctrl) |
| 287 | { | 285 | { |
| 288 | struct video_device *dev = video_devdata(file); | 286 | struct tt_device *tt = video_drvdata(file); |
| 289 | struct tt_device *tt = dev->priv; | ||
| 290 | 287 | ||
| 291 | switch (ctrl->id) { | 288 | switch (ctrl->id) { |
| 292 | case V4L2_CID_AUDIO_MUTE: | 289 | case V4L2_CID_AUDIO_MUTE: |
| @@ -305,8 +302,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 305 | static int vidioc_s_ctrl(struct file *file, void *priv, | 302 | static int vidioc_s_ctrl(struct file *file, void *priv, |
| 306 | struct v4l2_control *ctrl) | 303 | struct v4l2_control *ctrl) |
| 307 | { | 304 | { |
| 308 | struct video_device *dev = video_devdata(file); | 305 | struct tt_device *tt = video_drvdata(file); |
| 309 | struct tt_device *tt = dev->priv; | ||
| 310 | 306 | ||
| 311 | switch (ctrl->id) { | 307 | switch (ctrl->id) { |
| 312 | case V4L2_CID_AUDIO_MUTE: | 308 | case V4L2_CID_AUDIO_MUTE: |
| @@ -356,10 +352,21 @@ static int vidioc_s_audio(struct file *file, void *priv, | |||
| 356 | 352 | ||
| 357 | static struct tt_device terratec_unit; | 353 | static struct tt_device terratec_unit; |
| 358 | 354 | ||
| 355 | static int terratec_exclusive_open(struct inode *inode, struct file *file) | ||
| 356 | { | ||
| 357 | return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0; | ||
| 358 | } | ||
| 359 | |||
| 360 | static int terratec_exclusive_release(struct inode *inode, struct file *file) | ||
| 361 | { | ||
| 362 | clear_bit(0, &terratec_unit.in_use); | ||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 359 | static const struct file_operations terratec_fops = { | 366 | static const struct file_operations terratec_fops = { |
| 360 | .owner = THIS_MODULE, | 367 | .owner = THIS_MODULE, |
| 361 | .open = video_exclusive_open, | 368 | .open = terratec_exclusive_open, |
| 362 | .release = video_exclusive_release, | 369 | .release = terratec_exclusive_release, |
| 363 | .ioctl = video_ioctl2, | 370 | .ioctl = video_ioctl2, |
| 364 | #ifdef CONFIG_COMPAT | 371 | #ifdef CONFIG_COMPAT |
| 365 | .compat_ioctl = v4l_compat_ioctl32, | 372 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -386,6 +393,7 @@ static struct video_device terratec_radio = { | |||
| 386 | .name = "TerraTec ActiveRadio", | 393 | .name = "TerraTec ActiveRadio", |
| 387 | .fops = &terratec_fops, | 394 | .fops = &terratec_fops, |
| 388 | .ioctl_ops = &terratec_ioctl_ops, | 395 | .ioctl_ops = &terratec_ioctl_ops, |
| 396 | .release = video_device_release_empty, | ||
| 389 | }; | 397 | }; |
| 390 | 398 | ||
| 391 | static int __init terratec_init(void) | 399 | static int __init terratec_init(void) |
| @@ -401,7 +409,7 @@ static int __init terratec_init(void) | |||
| 401 | return -EBUSY; | 409 | return -EBUSY; |
| 402 | } | 410 | } |
| 403 | 411 | ||
| 404 | terratec_radio.priv=&terratec_unit; | 412 | video_set_drvdata(&terratec_radio, &terratec_unit); |
| 405 | 413 | ||
| 406 | spin_lock_init(&lock); | 414 | spin_lock_init(&lock); |
| 407 | 415 | ||
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index 193161956253..e7b111fcd105 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c | |||
| @@ -78,6 +78,7 @@ static __u16 curtreble; | |||
| 78 | static unsigned long curfreq; | 78 | static unsigned long curfreq; |
| 79 | static int curstereo; | 79 | static int curstereo; |
| 80 | static int curmute; | 80 | static int curmute; |
| 81 | static unsigned long in_use; | ||
| 81 | 82 | ||
| 82 | /* i2c addresses */ | 83 | /* i2c addresses */ |
| 83 | #define TDA7318_ADDR 0x88 | 84 | #define TDA7318_ADDR 0x88 |
| @@ -336,10 +337,21 @@ static int vidioc_s_audio(struct file *file, void *priv, | |||
| 336 | return 0; | 337 | return 0; |
| 337 | } | 338 | } |
| 338 | 339 | ||
| 340 | static int trust_exclusive_open(struct inode *inode, struct file *file) | ||
| 341 | { | ||
| 342 | return test_and_set_bit(0, &in_use) ? -EBUSY : 0; | ||
| 343 | } | ||
| 344 | |||
| 345 | static int trust_exclusive_release(struct inode *inode, struct file *file) | ||
| 346 | { | ||
| 347 | clear_bit(0, &in_use); | ||
| 348 | return 0; | ||
| 349 | } | ||
| 350 | |||
| 339 | static const struct file_operations trust_fops = { | 351 | static const struct file_operations trust_fops = { |
| 340 | .owner = THIS_MODULE, | 352 | .owner = THIS_MODULE, |
| 341 | .open = video_exclusive_open, | 353 | .open = trust_exclusive_open, |
| 342 | .release = video_exclusive_release, | 354 | .release = trust_exclusive_release, |
| 343 | .ioctl = video_ioctl2, | 355 | .ioctl = video_ioctl2, |
| 344 | #ifdef CONFIG_COMPAT | 356 | #ifdef CONFIG_COMPAT |
| 345 | .compat_ioctl = v4l_compat_ioctl32, | 357 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -366,6 +378,7 @@ static struct video_device trust_radio = { | |||
| 366 | .name = "Trust FM Radio", | 378 | .name = "Trust FM Radio", |
| 367 | .fops = &trust_fops, | 379 | .fops = &trust_fops, |
| 368 | .ioctl_ops = &trust_ioctl_ops, | 380 | .ioctl_ops = &trust_ioctl_ops, |
| 381 | .release = video_device_release_empty, | ||
| 369 | }; | 382 | }; |
| 370 | 383 | ||
| 371 | static int __init trust_init(void) | 384 | static int __init trust_init(void) |
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index f8d62cfea774..952ec35a8415 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c | |||
| @@ -79,7 +79,7 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
| 79 | #endif | 79 | #endif |
| 80 | 80 | ||
| 81 | struct typhoon_device { | 81 | struct typhoon_device { |
| 82 | int users; | 82 | unsigned long in_use; |
| 83 | int iobase; | 83 | int iobase; |
| 84 | int curvol; | 84 | int curvol; |
| 85 | int muted; | 85 | int muted; |
| @@ -223,8 +223,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
| 223 | static int vidioc_s_frequency(struct file *file, void *priv, | 223 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 224 | struct v4l2_frequency *f) | 224 | struct v4l2_frequency *f) |
| 225 | { | 225 | { |
| 226 | struct video_device *dev = video_devdata(file); | 226 | struct typhoon_device *typhoon = video_drvdata(file); |
| 227 | struct typhoon_device *typhoon = dev->priv; | ||
| 228 | 227 | ||
| 229 | typhoon->curfreq = f->frequency; | 228 | typhoon->curfreq = f->frequency; |
| 230 | typhoon_setfreq(typhoon, typhoon->curfreq); | 229 | typhoon_setfreq(typhoon, typhoon->curfreq); |
| @@ -234,8 +233,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 234 | static int vidioc_g_frequency(struct file *file, void *priv, | 233 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 235 | struct v4l2_frequency *f) | 234 | struct v4l2_frequency *f) |
| 236 | { | 235 | { |
| 237 | struct video_device *dev = video_devdata(file); | 236 | struct typhoon_device *typhoon = video_drvdata(file); |
| 238 | struct typhoon_device *typhoon = dev->priv; | ||
| 239 | 237 | ||
| 240 | f->type = V4L2_TUNER_RADIO; | 238 | f->type = V4L2_TUNER_RADIO; |
| 241 | f->frequency = typhoon->curfreq; | 239 | f->frequency = typhoon->curfreq; |
| @@ -261,8 +259,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 261 | static int vidioc_g_ctrl(struct file *file, void *priv, | 259 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 262 | struct v4l2_control *ctrl) | 260 | struct v4l2_control *ctrl) |
| 263 | { | 261 | { |
| 264 | struct video_device *dev = video_devdata(file); | 262 | struct typhoon_device *typhoon = video_drvdata(file); |
| 265 | struct typhoon_device *typhoon = dev->priv; | ||
| 266 | 263 | ||
| 267 | switch (ctrl->id) { | 264 | switch (ctrl->id) { |
| 268 | case V4L2_CID_AUDIO_MUTE: | 265 | case V4L2_CID_AUDIO_MUTE: |
| @@ -278,8 +275,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 278 | static int vidioc_s_ctrl (struct file *file, void *priv, | 275 | static int vidioc_s_ctrl (struct file *file, void *priv, |
| 279 | struct v4l2_control *ctrl) | 276 | struct v4l2_control *ctrl) |
| 280 | { | 277 | { |
| 281 | struct video_device *dev = video_devdata(file); | 278 | struct typhoon_device *typhoon = video_drvdata(file); |
| 282 | struct typhoon_device *typhoon = dev->priv; | ||
| 283 | 279 | ||
| 284 | switch (ctrl->id) { | 280 | switch (ctrl->id) { |
| 285 | case V4L2_CID_AUDIO_MUTE: | 281 | case V4L2_CID_AUDIO_MUTE: |
| @@ -334,10 +330,21 @@ static struct typhoon_device typhoon_unit = | |||
| 334 | .mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ, | 330 | .mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ, |
| 335 | }; | 331 | }; |
| 336 | 332 | ||
| 333 | static int typhoon_exclusive_open(struct inode *inode, struct file *file) | ||
| 334 | { | ||
| 335 | return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | static int typhoon_exclusive_release(struct inode *inode, struct file *file) | ||
| 339 | { | ||
| 340 | clear_bit(0, &typhoon_unit.in_use); | ||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | |||
| 337 | static const struct file_operations typhoon_fops = { | 344 | static const struct file_operations typhoon_fops = { |
| 338 | .owner = THIS_MODULE, | 345 | .owner = THIS_MODULE, |
| 339 | .open = video_exclusive_open, | 346 | .open = typhoon_exclusive_open, |
| 340 | .release = video_exclusive_release, | 347 | .release = typhoon_exclusive_release, |
| 341 | .ioctl = video_ioctl2, | 348 | .ioctl = video_ioctl2, |
| 342 | #ifdef CONFIG_COMPAT | 349 | #ifdef CONFIG_COMPAT |
| 343 | .compat_ioctl = v4l_compat_ioctl32, | 350 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -364,6 +371,7 @@ static struct video_device typhoon_radio = { | |||
| 364 | .name = "Typhoon Radio", | 371 | .name = "Typhoon Radio", |
| 365 | .fops = &typhoon_fops, | 372 | .fops = &typhoon_fops, |
| 366 | .ioctl_ops = &typhoon_ioctl_ops, | 373 | .ioctl_ops = &typhoon_ioctl_ops, |
| 374 | .release = video_device_release_empty, | ||
| 367 | }; | 375 | }; |
| 368 | 376 | ||
| 369 | #ifdef CONFIG_RADIO_TYPHOON_PROC_FS | 377 | #ifdef CONFIG_RADIO_TYPHOON_PROC_FS |
| @@ -446,9 +454,8 @@ static int __init typhoon_init(void) | |||
| 446 | return -EBUSY; | 454 | return -EBUSY; |
| 447 | } | 455 | } |
| 448 | 456 | ||
| 449 | typhoon_radio.priv = &typhoon_unit; | 457 | video_set_drvdata(&typhoon_radio, &typhoon_unit); |
| 450 | if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) == -1) | 458 | if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) < 0) { |
| 451 | { | ||
| 452 | release_region(io, 8); | 459 | release_region(io, 8); |
| 453 | return -EINVAL; | 460 | return -EINVAL; |
| 454 | } | 461 | } |
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 51d57ed3b3e1..15b10bad6796 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c | |||
| @@ -69,6 +69,7 @@ static int io = CONFIG_RADIO_ZOLTRIX_PORT; | |||
| 69 | static int radio_nr = -1; | 69 | static int radio_nr = -1; |
| 70 | 70 | ||
| 71 | struct zol_device { | 71 | struct zol_device { |
| 72 | unsigned long in_use; | ||
| 72 | int port; | 73 | int port; |
| 73 | int curvol; | 74 | int curvol; |
| 74 | unsigned long curfreq; | 75 | unsigned long curfreq; |
| @@ -122,8 +123,11 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) | |||
| 122 | unsigned int stereo = dev->stereo; | 123 | unsigned int stereo = dev->stereo; |
| 123 | int i; | 124 | int i; |
| 124 | 125 | ||
| 125 | if (freq == 0) | 126 | if (freq == 0) { |
| 126 | return 1; | 127 | printk(KERN_WARNING "zoltrix: received zero freq. Failed to set.\n"); |
| 128 | return -EINVAL; | ||
| 129 | } | ||
| 130 | |||
| 127 | m = (freq / 160 - 8800) * 2; | 131 | m = (freq / 160 - 8800) * 2; |
| 128 | f = (unsigned long long) m + 0x4d1c; | 132 | f = (unsigned long long) m + 0x4d1c; |
| 129 | 133 | ||
| @@ -245,8 +249,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
| 245 | static int vidioc_g_tuner(struct file *file, void *priv, | 249 | static int vidioc_g_tuner(struct file *file, void *priv, |
| 246 | struct v4l2_tuner *v) | 250 | struct v4l2_tuner *v) |
| 247 | { | 251 | { |
| 248 | struct video_device *dev = video_devdata(file); | 252 | struct zol_device *zol = video_drvdata(file); |
| 249 | struct zol_device *zol = dev->priv; | ||
| 250 | 253 | ||
| 251 | if (v->index > 0) | 254 | if (v->index > 0) |
| 252 | return -EINVAL; | 255 | return -EINVAL; |
| @@ -276,19 +279,20 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
| 276 | static int vidioc_s_frequency(struct file *file, void *priv, | 279 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 277 | struct v4l2_frequency *f) | 280 | struct v4l2_frequency *f) |
| 278 | { | 281 | { |
| 279 | struct video_device *dev = video_devdata(file); | 282 | struct zol_device *zol = video_drvdata(file); |
| 280 | struct zol_device *zol = dev->priv; | ||
| 281 | 283 | ||
| 282 | zol->curfreq = f->frequency; | 284 | zol->curfreq = f->frequency; |
| 283 | zol_setfreq(zol, zol->curfreq); | 285 | if (zol_setfreq(zol, zol->curfreq) != 0) { |
| 286 | printk(KERN_WARNING "zoltrix: Set frequency failed.\n"); | ||
| 287 | return -EINVAL; | ||
| 288 | } | ||
| 284 | return 0; | 289 | return 0; |
| 285 | } | 290 | } |
| 286 | 291 | ||
| 287 | static int vidioc_g_frequency(struct file *file, void *priv, | 292 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 288 | struct v4l2_frequency *f) | 293 | struct v4l2_frequency *f) |
| 289 | { | 294 | { |
| 290 | struct video_device *dev = video_devdata(file); | 295 | struct zol_device *zol = video_drvdata(file); |
| 291 | struct zol_device *zol = dev->priv; | ||
| 292 | 296 | ||
| 293 | f->type = V4L2_TUNER_RADIO; | 297 | f->type = V4L2_TUNER_RADIO; |
| 294 | f->frequency = zol->curfreq; | 298 | f->frequency = zol->curfreq; |
| @@ -313,8 +317,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
| 313 | static int vidioc_g_ctrl(struct file *file, void *priv, | 317 | static int vidioc_g_ctrl(struct file *file, void *priv, |
| 314 | struct v4l2_control *ctrl) | 318 | struct v4l2_control *ctrl) |
| 315 | { | 319 | { |
| 316 | struct video_device *dev = video_devdata(file); | 320 | struct zol_device *zol = video_drvdata(file); |
| 317 | struct zol_device *zol = dev->priv; | ||
| 318 | 321 | ||
| 319 | switch (ctrl->id) { | 322 | switch (ctrl->id) { |
| 320 | case V4L2_CID_AUDIO_MUTE: | 323 | case V4L2_CID_AUDIO_MUTE: |
| @@ -330,8 +333,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
| 330 | static int vidioc_s_ctrl(struct file *file, void *priv, | 333 | static int vidioc_s_ctrl(struct file *file, void *priv, |
| 331 | struct v4l2_control *ctrl) | 334 | struct v4l2_control *ctrl) |
| 332 | { | 335 | { |
| 333 | struct video_device *dev = video_devdata(file); | 336 | struct zol_device *zol = video_drvdata(file); |
| 334 | struct zol_device *zol = dev->priv; | ||
| 335 | 337 | ||
| 336 | switch (ctrl->id) { | 338 | switch (ctrl->id) { |
| 337 | case V4L2_CID_AUDIO_MUTE: | 339 | case V4L2_CID_AUDIO_MUTE: |
| @@ -347,7 +349,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
| 347 | return 0; | 349 | return 0; |
| 348 | } | 350 | } |
| 349 | zol->stereo = 1; | 351 | zol->stereo = 1; |
| 350 | zol_setfreq(zol, zol->curfreq); | 352 | if (zol_setfreq(zol, zol->curfreq) != 0) { |
| 353 | printk(KERN_WARNING "zoltrix: Set frequency failed.\n"); | ||
| 354 | return -EINVAL; | ||
| 355 | } | ||
| 351 | #if 0 | 356 | #if 0 |
| 352 | /* FIXME: Implement stereo/mono switch on V4L2 */ | 357 | /* FIXME: Implement stereo/mono switch on V4L2 */ |
| 353 | if (v->mode & VIDEO_SOUND_STEREO) { | 358 | if (v->mode & VIDEO_SOUND_STEREO) { |
| @@ -396,11 +401,22 @@ static int vidioc_s_audio(struct file *file, void *priv, | |||
| 396 | 401 | ||
| 397 | static struct zol_device zoltrix_unit; | 402 | static struct zol_device zoltrix_unit; |
| 398 | 403 | ||
| 404 | static int zoltrix_exclusive_open(struct inode *inode, struct file *file) | ||
| 405 | { | ||
| 406 | return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | static int zoltrix_exclusive_release(struct inode *inode, struct file *file) | ||
| 410 | { | ||
| 411 | clear_bit(0, &zoltrix_unit.in_use); | ||
| 412 | return 0; | ||
| 413 | } | ||
| 414 | |||
| 399 | static const struct file_operations zoltrix_fops = | 415 | static const struct file_operations zoltrix_fops = |
| 400 | { | 416 | { |
| 401 | .owner = THIS_MODULE, | 417 | .owner = THIS_MODULE, |
| 402 | .open = video_exclusive_open, | 418 | .open = zoltrix_exclusive_open, |
| 403 | .release = video_exclusive_release, | 419 | .release = zoltrix_exclusive_release, |
| 404 | .ioctl = video_ioctl2, | 420 | .ioctl = video_ioctl2, |
| 405 | #ifdef CONFIG_COMPAT | 421 | #ifdef CONFIG_COMPAT |
| 406 | .compat_ioctl = v4l_compat_ioctl32, | 422 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -427,6 +443,7 @@ static struct video_device zoltrix_radio = { | |||
| 427 | .name = "Zoltrix Radio Plus", | 443 | .name = "Zoltrix Radio Plus", |
| 428 | .fops = &zoltrix_fops, | 444 | .fops = &zoltrix_fops, |
| 429 | .ioctl_ops = &zoltrix_ioctl_ops, | 445 | .ioctl_ops = &zoltrix_ioctl_ops, |
| 446 | .release = video_device_release_empty, | ||
| 430 | }; | 447 | }; |
| 431 | 448 | ||
| 432 | static int __init zoltrix_init(void) | 449 | static int __init zoltrix_init(void) |
| @@ -440,7 +457,7 @@ static int __init zoltrix_init(void) | |||
| 440 | return -ENXIO; | 457 | return -ENXIO; |
| 441 | } | 458 | } |
| 442 | 459 | ||
| 443 | zoltrix_radio.priv = &zoltrix_unit; | 460 | video_set_drvdata(&zoltrix_radio, &zoltrix_unit); |
| 444 | if (!request_region(io, 2, "zoltrix")) { | 461 | if (!request_region(io, 2, "zoltrix")) { |
| 445 | printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io); | 462 | printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io); |
| 446 | return -EBUSY; | 463 | return -EBUSY; |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 3e9e0dcd217e..47102c2c8250 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
| @@ -34,6 +34,7 @@ config VIDEOBUF_DVB | |||
| 34 | select VIDEOBUF_GEN | 34 | select VIDEOBUF_GEN |
| 35 | 35 | ||
| 36 | config VIDEO_BTCX | 36 | config VIDEO_BTCX |
| 37 | depends on PCI | ||
| 37 | tristate | 38 | tristate |
| 38 | 39 | ||
| 39 | config VIDEO_IR | 40 | config VIDEO_IR |
| @@ -71,6 +72,15 @@ config VIDEO_ADV_DEBUG | |||
| 71 | V4L devices. | 72 | V4L devices. |
| 72 | In doubt, say N. | 73 | In doubt, say N. |
| 73 | 74 | ||
| 75 | config VIDEO_FIXED_MINOR_RANGES | ||
| 76 | bool "Enable old-style fixed minor ranges for video devices" | ||
| 77 | default n | ||
| 78 | ---help--- | ||
| 79 | Say Y here to enable the old-style fixed-range minor assignments. | ||
| 80 | Only useful if you rely on the old behavior and use mknod instead of udev. | ||
| 81 | |||
| 82 | When in doubt, say N. | ||
| 83 | |||
| 74 | config VIDEO_HELPER_CHIPS_AUTO | 84 | config VIDEO_HELPER_CHIPS_AUTO |
| 75 | bool "Autoselect pertinent encoders/decoders and other helper chips" | 85 | bool "Autoselect pertinent encoders/decoders and other helper chips" |
| 76 | default y | 86 | default y |
| @@ -578,13 +588,6 @@ config VIDEO_SAA5249 | |||
| 578 | To compile this driver as a module, choose M here: the | 588 | To compile this driver as a module, choose M here: the |
| 579 | module will be called saa5249. | 589 | module will be called saa5249. |
| 580 | 590 | ||
| 581 | config TUNER_3036 | ||
| 582 | tristate "SAB3036 tuner" | ||
| 583 | depends on I2C && VIDEO_V4L1 | ||
| 584 | help | ||
| 585 | Say Y here to include support for Philips SAB3036 compatible tuners. | ||
| 586 | If in doubt, say N. | ||
| 587 | |||
| 588 | config VIDEO_VINO | 591 | config VIDEO_VINO |
| 589 | tristate "SGI Vino Video For Linux (EXPERIMENTAL)" | 592 | tristate "SGI Vino Video For Linux (EXPERIMENTAL)" |
| 590 | depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 | 593 | depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 |
| @@ -602,79 +605,7 @@ config VIDEO_STRADIS | |||
| 602 | driver for PCI. There is a product page at | 605 | driver for PCI. There is a product page at |
| 603 | <http://www.stradis.com/>. | 606 | <http://www.stradis.com/>. |
| 604 | 607 | ||
| 605 | config VIDEO_ZORAN | 608 | source "drivers/media/video/zoran/Kconfig" |
| 606 | tristate "Zoran ZR36057/36067 Video For Linux" | ||
| 607 | depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS | ||
| 608 | help | ||
| 609 | Say Y for support for MJPEG capture cards based on the Zoran | ||
| 610 | 36057/36067 PCI controller chipset. This includes the Iomega | ||
| 611 | Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is | ||
| 612 | a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For | ||
| 613 | more information, check <file:Documentation/video4linux/Zoran>. | ||
| 614 | |||
| 615 | To compile this driver as a module, choose M here: the | ||
| 616 | module will be called zr36067. | ||
| 617 | |||
| 618 | config VIDEO_ZORAN_DC30 | ||
| 619 | tristate "Pinnacle/Miro DC30(+) support" | ||
| 620 | depends on VIDEO_ZORAN | ||
| 621 | select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO | ||
| 622 | select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO | ||
| 623 | help | ||
| 624 | Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback | ||
| 625 | card. This also supports really old DC10 cards based on the | ||
| 626 | zr36050 MJPEG codec and zr36016 VFE. | ||
| 627 | |||
| 628 | config VIDEO_ZORAN_ZR36060 | ||
| 629 | tristate "Zoran ZR36060" | ||
| 630 | depends on VIDEO_ZORAN | ||
| 631 | help | ||
| 632 | Say Y to support Zoran boards based on 36060 chips. | ||
| 633 | This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33 | ||
| 634 | and 33 R10 and AverMedia 6 boards. | ||
| 635 | |||
| 636 | config VIDEO_ZORAN_BUZ | ||
| 637 | tristate "Iomega Buz support" | ||
| 638 | depends on VIDEO_ZORAN_ZR36060 | ||
| 639 | select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO | ||
| 640 | select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO | ||
| 641 | help | ||
| 642 | Support for the Iomega Buz MJPEG capture/playback card. | ||
| 643 | |||
| 644 | config VIDEO_ZORAN_DC10 | ||
| 645 | tristate "Pinnacle/Miro DC10(+) support" | ||
| 646 | depends on VIDEO_ZORAN_ZR36060 | ||
| 647 | select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO | ||
| 648 | select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO | ||
| 649 | help | ||
| 650 | Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback | ||
| 651 | card. | ||
| 652 | |||
| 653 | config VIDEO_ZORAN_LML33 | ||
| 654 | tristate "Linux Media Labs LML33 support" | ||
| 655 | depends on VIDEO_ZORAN_ZR36060 | ||
| 656 | select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO | ||
| 657 | select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO | ||
| 658 | help | ||
| 659 | Support for the Linux Media Labs LML33 MJPEG capture/playback | ||
| 660 | card. | ||
| 661 | |||
| 662 | config VIDEO_ZORAN_LML33R10 | ||
| 663 | tristate "Linux Media Labs LML33R10 support" | ||
| 664 | depends on VIDEO_ZORAN_ZR36060 | ||
| 665 | select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO | ||
| 666 | select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO | ||
| 667 | help | ||
| 668 | support for the Linux Media Labs LML33R10 MJPEG capture/playback | ||
| 669 | card. | ||
| 670 | |||
| 671 | config VIDEO_ZORAN_AVS6EYES | ||
| 672 | tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" | ||
| 673 | depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 | ||
| 674 | select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO | ||
| 675 | select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO | ||
| 676 | help | ||
| 677 | Support for the AverMedia 6 Eyes video surveillance card. | ||
| 678 | 609 | ||
| 679 | config VIDEO_MEYE | 610 | config VIDEO_MEYE |
| 680 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" | 611 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" |
| @@ -697,7 +628,7 @@ config VIDEO_MXB | |||
| 697 | depends on PCI && VIDEO_V4L1 && I2C | 628 | depends on PCI && VIDEO_V4L1 && I2C |
| 698 | select VIDEO_SAA7146_VV | 629 | select VIDEO_SAA7146_VV |
| 699 | select VIDEO_TUNER | 630 | select VIDEO_TUNER |
| 700 | select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO | 631 | select VIDEO_SAA7115 if VIDEO_HELPER_CHIPS_AUTO |
| 701 | select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO | 632 | select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO |
| 702 | select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO | 633 | select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO |
| 703 | select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO | 634 | select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO |
| @@ -708,21 +639,6 @@ config VIDEO_MXB | |||
| 708 | To compile this driver as a module, choose M here: the | 639 | To compile this driver as a module, choose M here: the |
| 709 | module will be called mxb. | 640 | module will be called mxb. |
| 710 | 641 | ||
| 711 | config VIDEO_DPC | ||
| 712 | tristate "Philips-Semiconductors 'dpc7146 demonstration board'" | ||
| 713 | depends on PCI && VIDEO_V4L1 && I2C | ||
| 714 | select VIDEO_SAA7146_VV | ||
| 715 | select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO | ||
| 716 | ---help--- | ||
| 717 | This is a video4linux driver for the 'dpc7146 demonstration | ||
| 718 | board' by Philips-Semiconductors. It's the reference design | ||
| 719 | for SAA7146 bases boards, so if you have some unsupported | ||
| 720 | saa7146 based, analog video card, chances are good that it | ||
| 721 | will work with this skeleton driver. | ||
| 722 | |||
| 723 | To compile this driver as a module, choose M here: the | ||
| 724 | module will be called dpc7146. | ||
| 725 | |||
| 726 | config VIDEO_HEXIUM_ORION | 642 | config VIDEO_HEXIUM_ORION |
| 727 | tristate "Hexium HV-PCI6 and Orion frame grabber" | 643 | tristate "Hexium HV-PCI6 and Orion frame grabber" |
| 728 | depends on PCI && VIDEO_V4L2 && I2C | 644 | depends on PCI && VIDEO_V4L2 && I2C |
| @@ -784,6 +700,70 @@ config VIDEO_CAFE_CCIC | |||
| 784 | CMOS camera controller. This is the controller found on first- | 700 | CMOS camera controller. This is the controller found on first- |
| 785 | generation OLPC systems. | 701 | generation OLPC systems. |
| 786 | 702 | ||
| 703 | config SOC_CAMERA | ||
| 704 | tristate "SoC camera support" | ||
| 705 | depends on VIDEO_V4L2 && HAS_DMA | ||
| 706 | select VIDEOBUF_GEN | ||
| 707 | help | ||
| 708 | SoC Camera is a common API to several cameras, not connecting | ||
| 709 | over a bus like PCI or USB. For example some i2c camera connected | ||
| 710 | directly to the data bus of an SoC. | ||
| 711 | |||
| 712 | config SOC_CAMERA_MT9M001 | ||
| 713 | tristate "mt9m001 support" | ||
| 714 | depends on SOC_CAMERA && I2C | ||
| 715 | select GPIO_PCA953X if MT9M001_PCA9536_SWITCH | ||
| 716 | help | ||
| 717 | This driver supports MT9M001 cameras from Micron, monochrome | ||
| 718 | and colour models. | ||
| 719 | |||
| 720 | config MT9M001_PCA9536_SWITCH | ||
| 721 | bool "pca9536 datawidth switch for mt9m001" | ||
| 722 | depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO | ||
| 723 | help | ||
| 724 | Select this if your MT9M001 camera uses a PCA9536 I2C GPIO | ||
| 725 | extender to switch between 8 and 10 bit datawidth modes | ||
| 726 | |||
| 727 | config SOC_CAMERA_MT9M111 | ||
| 728 | tristate "mt9m111 support" | ||
| 729 | depends on SOC_CAMERA && I2C | ||
| 730 | help | ||
| 731 | This driver supports MT9M111 cameras from Micron | ||
| 732 | |||
| 733 | config SOC_CAMERA_MT9V022 | ||
| 734 | tristate "mt9v022 support" | ||
| 735 | depends on SOC_CAMERA && I2C | ||
| 736 | select GPIO_PCA953X if MT9V022_PCA9536_SWITCH | ||
| 737 | help | ||
| 738 | This driver supports MT9V022 cameras from Micron | ||
| 739 | |||
| 740 | config MT9V022_PCA9536_SWITCH | ||
| 741 | bool "pca9536 datawidth switch for mt9v022" | ||
| 742 | depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO | ||
| 743 | help | ||
| 744 | Select this if your MT9V022 camera uses a PCA9536 I2C GPIO | ||
| 745 | extender to switch between 8 and 10 bit datawidth modes | ||
| 746 | |||
| 747 | config SOC_CAMERA_PLATFORM | ||
| 748 | tristate "platform camera support" | ||
| 749 | depends on SOC_CAMERA | ||
| 750 | help | ||
| 751 | This is a generic SoC camera platform driver, useful for testing | ||
| 752 | |||
| 753 | config VIDEO_PXA27x | ||
| 754 | tristate "PXA27x Quick Capture Interface driver" | ||
| 755 | depends on VIDEO_DEV && PXA27x && SOC_CAMERA | ||
| 756 | select VIDEOBUF_DMA_SG | ||
| 757 | ---help--- | ||
| 758 | This is a v4l2 driver for the PXA27x Quick Capture Interface | ||
| 759 | |||
| 760 | config VIDEO_SH_MOBILE_CEU | ||
| 761 | tristate "SuperH Mobile CEU Interface driver" | ||
| 762 | depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA | ||
| 763 | select VIDEOBUF_DMA_CONTIG | ||
| 764 | ---help--- | ||
| 765 | This is a v4l2 driver for the SuperH Mobile CEU Interface | ||
| 766 | |||
| 787 | # | 767 | # |
| 788 | # USB Multimedia device configuration | 768 | # USB Multimedia device configuration |
| 789 | # | 769 | # |
| @@ -822,8 +802,7 @@ config VIDEO_OVCAMCHIP | |||
| 822 | 802 | ||
| 823 | config USB_W9968CF | 803 | config USB_W9968CF |
| 824 | tristate "USB W996[87]CF JPEG Dual Mode Camera support" | 804 | tristate "USB W996[87]CF JPEG Dual Mode Camera support" |
| 825 | depends on VIDEO_V4L1 && I2C | 805 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP |
| 826 | select VIDEO_OVCAMCHIP | ||
| 827 | ---help--- | 806 | ---help--- |
| 828 | Say Y here if you want support for cameras based on OV681 or | 807 | Say Y here if you want support for cameras based on OV681 or |
| 829 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. | 808 | Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. |
| @@ -914,64 +893,4 @@ config USB_S2255 | |||
| 914 | 893 | ||
| 915 | endif # V4L_USB_DRIVERS | 894 | endif # V4L_USB_DRIVERS |
| 916 | 895 | ||
| 917 | config SOC_CAMERA | ||
| 918 | tristate "SoC camera support" | ||
| 919 | depends on VIDEO_V4L2 && HAS_DMA | ||
| 920 | select VIDEOBUF_GEN | ||
| 921 | help | ||
| 922 | SoC Camera is a common API to several cameras, not connecting | ||
| 923 | over a bus like PCI or USB. For example some i2c camera connected | ||
| 924 | directly to the data bus of an SoC. | ||
| 925 | |||
| 926 | config SOC_CAMERA_MT9M001 | ||
| 927 | tristate "mt9m001 support" | ||
| 928 | depends on SOC_CAMERA && I2C | ||
| 929 | select GPIO_PCA953X if MT9M001_PCA9536_SWITCH | ||
| 930 | help | ||
| 931 | This driver supports MT9M001 cameras from Micron, monochrome | ||
| 932 | and colour models. | ||
| 933 | |||
| 934 | config MT9M001_PCA9536_SWITCH | ||
| 935 | bool "pca9536 datawidth switch for mt9m001" | ||
| 936 | depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO | ||
| 937 | help | ||
| 938 | Select this if your MT9M001 camera uses a PCA9536 I2C GPIO | ||
| 939 | extender to switch between 8 and 10 bit datawidth modes | ||
| 940 | |||
| 941 | config SOC_CAMERA_MT9V022 | ||
| 942 | tristate "mt9v022 support" | ||
| 943 | depends on SOC_CAMERA && I2C | ||
| 944 | select GPIO_PCA953X if MT9V022_PCA9536_SWITCH | ||
| 945 | help | ||
| 946 | This driver supports MT9V022 cameras from Micron | ||
| 947 | |||
| 948 | config MT9V022_PCA9536_SWITCH | ||
| 949 | bool "pca9536 datawidth switch for mt9v022" | ||
| 950 | depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO | ||
| 951 | help | ||
| 952 | Select this if your MT9V022 camera uses a PCA9536 I2C GPIO | ||
| 953 | extender to switch between 8 and 10 bit datawidth modes | ||
| 954 | |||
| 955 | config SOC_CAMERA_PLATFORM | ||
| 956 | tristate "platform camera support" | ||
| 957 | depends on SOC_CAMERA | ||
| 958 | help | ||
| 959 | This is a generic SoC camera platform driver, useful for testing | ||
| 960 | |||
| 961 | config VIDEO_PXA27x | ||
| 962 | tristate "PXA27x Quick Capture Interface driver" | ||
| 963 | depends on VIDEO_DEV && PXA27x | ||
| 964 | select SOC_CAMERA | ||
| 965 | select VIDEOBUF_DMA_SG | ||
| 966 | ---help--- | ||
| 967 | This is a v4l2 driver for the PXA27x Quick Capture Interface | ||
| 968 | |||
| 969 | config VIDEO_SH_MOBILE_CEU | ||
| 970 | tristate "SuperH Mobile CEU Interface driver" | ||
| 971 | depends on VIDEO_DEV && HAS_DMA | ||
| 972 | select SOC_CAMERA | ||
| 973 | select VIDEOBUF_DMA_CONTIG | ||
| 974 | ---help--- | ||
| 975 | This is a v4l2 driver for the SuperH Mobile CEU Interface | ||
| 976 | |||
| 977 | endif # VIDEO_CAPTURE_DRIVERS | 896 | endif # VIDEO_CAPTURE_DRIVERS |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index ef7c8d3ffb18..16962f3aa157 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
| @@ -2,8 +2,6 @@ | |||
| 2 | # Makefile for the video capture/playback device drivers. | 2 | # Makefile for the video capture/playback device drivers. |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | zr36067-objs := zoran_procfs.o zoran_device.o \ | ||
| 6 | zoran_driver.o zoran_card.o | ||
| 7 | tuner-objs := tuner-core.o | 5 | tuner-objs := tuner-core.o |
| 8 | 6 | ||
| 9 | msp3400-objs := msp3400-driver.o msp3400-kthreads.o | 7 | msp3400-objs := msp3400-driver.o msp3400-kthreads.o |
| @@ -54,9 +52,7 @@ obj-$(CONFIG_VIDEO_BT856) += bt856.o | |||
| 54 | obj-$(CONFIG_VIDEO_BT866) += bt866.o | 52 | obj-$(CONFIG_VIDEO_BT866) += bt866.o |
| 55 | obj-$(CONFIG_VIDEO_KS0127) += ks0127.o | 53 | obj-$(CONFIG_VIDEO_KS0127) += ks0127.o |
| 56 | 54 | ||
| 57 | obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o | 55 | obj-$(CONFIG_VIDEO_ZORAN) += zoran/ |
| 58 | obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o | ||
| 59 | obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o | ||
| 60 | 56 | ||
| 61 | obj-$(CONFIG_VIDEO_PMS) += pms.o | 57 | obj-$(CONFIG_VIDEO_PMS) += pms.o |
| 62 | obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o | 58 | obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o |
| @@ -84,8 +80,6 @@ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ | |||
| 84 | obj-$(CONFIG_VIDEO_MXB) += mxb.o | 80 | obj-$(CONFIG_VIDEO_MXB) += mxb.o |
| 85 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o | 81 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o |
| 86 | obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o | 82 | obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o |
| 87 | obj-$(CONFIG_VIDEO_DPC) += dpc7146.o | ||
| 88 | obj-$(CONFIG_TUNER_3036) += tuner-3036.o | ||
| 89 | 83 | ||
| 90 | obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o | 84 | obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o |
| 91 | obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o | 85 | obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o |
| @@ -137,6 +131,7 @@ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o | |||
| 137 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o | 131 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o |
| 138 | obj-$(CONFIG_SOC_CAMERA) += soc_camera.o | 132 | obj-$(CONFIG_SOC_CAMERA) += soc_camera.o |
| 139 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o | 133 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o |
| 134 | obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o | ||
| 140 | obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o | 135 | obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o |
| 141 | obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o | 136 | obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o |
| 142 | 137 | ||
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 9e436ad3d34b..218754b4906a 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c | |||
| @@ -116,6 +116,7 @@ struct ar_device { | |||
| 116 | int width, height; | 116 | int width, height; |
| 117 | int frame_bytes, line_bytes; | 117 | int frame_bytes, line_bytes; |
| 118 | wait_queue_head_t wait; | 118 | wait_queue_head_t wait; |
| 119 | unsigned long in_use; | ||
| 119 | struct mutex lock; | 120 | struct mutex lock; |
| 120 | }; | 121 | }; |
| 121 | 122 | ||
| @@ -269,7 +270,7 @@ static inline void wait_for_vertical_sync(int exp_line) | |||
| 269 | static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) | 270 | static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) |
| 270 | { | 271 | { |
| 271 | struct video_device *v = video_devdata(file); | 272 | struct video_device *v = video_devdata(file); |
| 272 | struct ar_device *ar = v->priv; | 273 | struct ar_device *ar = video_get_drvdata(v); |
| 273 | long ret = ar->frame_bytes; /* return read bytes */ | 274 | long ret = ar->frame_bytes; /* return read bytes */ |
| 274 | unsigned long arvcr1 = 0; | 275 | unsigned long arvcr1 = 0; |
| 275 | unsigned long flags; | 276 | unsigned long flags; |
| @@ -399,7 +400,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file, | |||
| 399 | unsigned int cmd, void *arg) | 400 | unsigned int cmd, void *arg) |
| 400 | { | 401 | { |
| 401 | struct video_device *dev = video_devdata(file); | 402 | struct video_device *dev = video_devdata(file); |
| 402 | struct ar_device *ar = dev->priv; | 403 | struct ar_device *ar = video_get_drvdata(dev); |
| 403 | 404 | ||
| 404 | DEBUG(1, "ar_ioctl()\n"); | 405 | DEBUG(1, "ar_ioctl()\n"); |
| 405 | switch(cmd) { | 406 | switch(cmd) { |
| @@ -625,7 +626,7 @@ static void ar_interrupt(int irq, void *dev) | |||
| 625 | */ | 626 | */ |
| 626 | static int ar_initialize(struct video_device *dev) | 627 | static int ar_initialize(struct video_device *dev) |
| 627 | { | 628 | { |
| 628 | struct ar_device *ar = dev->priv; | 629 | struct ar_device *ar = video_get_drvdata(dev); |
| 629 | unsigned long cr = 0; | 630 | unsigned long cr = 0; |
| 630 | int i,found=0; | 631 | int i,found=0; |
| 631 | 632 | ||
| @@ -732,7 +733,7 @@ static int ar_initialize(struct video_device *dev) | |||
| 732 | 733 | ||
| 733 | void ar_release(struct video_device *vfd) | 734 | void ar_release(struct video_device *vfd) |
| 734 | { | 735 | { |
| 735 | struct ar_device *ar = vfd->priv; | 736 | struct ar_device *ar = video_get_drvdata(vfd); |
| 736 | mutex_lock(&ar->lock); | 737 | mutex_lock(&ar->lock); |
| 737 | video_device_release(vfd); | 738 | video_device_release(vfd); |
| 738 | } | 739 | } |
| @@ -742,10 +743,23 @@ void ar_release(struct video_device *vfd) | |||
| 742 | * Video4Linux Module functions | 743 | * Video4Linux Module functions |
| 743 | * | 744 | * |
| 744 | ****************************************************************************/ | 745 | ****************************************************************************/ |
| 746 | static struct ar_device ardev; | ||
| 747 | |||
| 748 | static int ar_exclusive_open(struct inode *inode, struct file *file) | ||
| 749 | { | ||
| 750 | return test_and_set_bit(0, &ardev.in_use) ? -EBUSY : 0; | ||
| 751 | } | ||
| 752 | |||
| 753 | static int ar_exclusive_release(struct inode *inode, struct file *file) | ||
| 754 | { | ||
| 755 | clear_bit(0, &ardev.in_use); | ||
| 756 | return 0; | ||
| 757 | } | ||
| 758 | |||
| 745 | static const struct file_operations ar_fops = { | 759 | static const struct file_operations ar_fops = { |
| 746 | .owner = THIS_MODULE, | 760 | .owner = THIS_MODULE, |
| 747 | .open = video_exclusive_open, | 761 | .open = ar_exclusive_open, |
| 748 | .release = video_exclusive_release, | 762 | .release = ar_exclusive_release, |
| 749 | .read = ar_read, | 763 | .read = ar_read, |
| 750 | .ioctl = ar_ioctl, | 764 | .ioctl = ar_ioctl, |
| 751 | #ifdef CONFIG_COMPAT | 765 | #ifdef CONFIG_COMPAT |
| @@ -762,7 +776,6 @@ static struct video_device ar_template = { | |||
| 762 | }; | 776 | }; |
| 763 | 777 | ||
| 764 | #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) | 778 | #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) |
| 765 | static struct ar_device ardev; | ||
| 766 | 779 | ||
| 767 | static int __init ar_init(void) | 780 | static int __init ar_init(void) |
| 768 | { | 781 | { |
| @@ -802,7 +815,7 @@ static int __init ar_init(void) | |||
| 802 | return -ENOMEM; | 815 | return -ENOMEM; |
| 803 | } | 816 | } |
| 804 | memcpy(ar->vdev, &ar_template, sizeof(ar_template)); | 817 | memcpy(ar->vdev, &ar_template, sizeof(ar_template)); |
| 805 | ar->vdev->priv = ar; | 818 | video_set_drvdata(ar->vdev, ar); |
| 806 | 819 | ||
| 807 | if (vga) { | 820 | if (vga) { |
| 808 | ar->width = AR_WIDTH_VGA; | 821 | ar->width = AR_WIDTH_VGA; |
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index ed48908a9034..5f07a8a072b6 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c | |||
| @@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = { | |||
| 46 | /* Tuner callback function for au0828 boards. Currently only needed | 46 | /* Tuner callback function for au0828 boards. Currently only needed |
| 47 | * for HVR1500Q, which has an xc5000 tuner. | 47 | * for HVR1500Q, which has an xc5000 tuner. |
| 48 | */ | 48 | */ |
| 49 | int au0828_tuner_callback(void *priv, int command, int arg) | 49 | int au0828_tuner_callback(void *priv, int component, int command, int arg) |
| 50 | { | 50 | { |
| 51 | struct au0828_dev *dev = priv; | 51 | struct au0828_dev *dev = priv; |
| 52 | 52 | ||
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index ba94be7e0ac1..f0fcdb4769d7 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c | |||
| @@ -36,11 +36,39 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
| 36 | #define _AU0828_BULKPIPE 0x83 | 36 | #define _AU0828_BULKPIPE 0x83 |
| 37 | #define _BULKPIPESIZE 0xe522 | 37 | #define _BULKPIPESIZE 0xe522 |
| 38 | 38 | ||
| 39 | static u8 hauppauge_hvr950q_led_states[] = { | ||
| 40 | 0x00, /* off */ | ||
| 41 | 0x02, /* yellow */ | ||
| 42 | 0x04, /* green */ | ||
| 43 | }; | ||
| 44 | |||
| 45 | static struct au8522_led_config hauppauge_hvr950q_led_cfg = { | ||
| 46 | .gpio_output = 0x00e0, | ||
| 47 | .gpio_output_enable = 0x6006, | ||
| 48 | .gpio_output_disable = 0x0660, | ||
| 49 | |||
| 50 | .gpio_leds = 0x00e2, | ||
| 51 | .led_states = hauppauge_hvr950q_led_states, | ||
| 52 | .num_led_states = sizeof(hauppauge_hvr950q_led_states), | ||
| 53 | |||
| 54 | .vsb8_strong = 20 /* dB */ * 10, | ||
| 55 | .qam64_strong = 25 /* dB */ * 10, | ||
| 56 | .qam256_strong = 32 /* dB */ * 10, | ||
| 57 | }; | ||
| 58 | |||
| 39 | static struct au8522_config hauppauge_hvr950q_config = { | 59 | static struct au8522_config hauppauge_hvr950q_config = { |
| 40 | .demod_address = 0x8e >> 1, | 60 | .demod_address = 0x8e >> 1, |
| 41 | .status_mode = AU8522_DEMODLOCKING, | 61 | .status_mode = AU8522_DEMODLOCKING, |
| 42 | .qam_if = AU8522_IF_6MHZ, | 62 | .qam_if = AU8522_IF_6MHZ, |
| 43 | .vsb_if = AU8522_IF_6MHZ, | 63 | .vsb_if = AU8522_IF_6MHZ, |
| 64 | .led_cfg = &hauppauge_hvr950q_led_cfg, | ||
| 65 | }; | ||
| 66 | |||
| 67 | static struct au8522_config fusionhdtv7usb_config = { | ||
| 68 | .demod_address = 0x8e >> 1, | ||
| 69 | .status_mode = AU8522_DEMODLOCKING, | ||
| 70 | .qam_if = AU8522_IF_6MHZ, | ||
| 71 | .vsb_if = AU8522_IF_6MHZ, | ||
| 44 | }; | 72 | }; |
| 45 | 73 | ||
| 46 | static struct au8522_config hauppauge_woodbury_config = { | 74 | static struct au8522_config hauppauge_woodbury_config = { |
| @@ -53,7 +81,6 @@ static struct au8522_config hauppauge_woodbury_config = { | |||
| 53 | static struct xc5000_config hauppauge_hvr950q_tunerconfig = { | 81 | static struct xc5000_config hauppauge_hvr950q_tunerconfig = { |
| 54 | .i2c_address = 0x61, | 82 | .i2c_address = 0x61, |
| 55 | .if_khz = 6000, | 83 | .if_khz = 6000, |
| 56 | .tuner_callback = au0828_tuner_callback | ||
| 57 | }; | 84 | }; |
| 58 | 85 | ||
| 59 | static struct mxl5007t_config mxl5007t_hvr950q_config = { | 86 | static struct mxl5007t_config mxl5007t_hvr950q_config = { |
| @@ -353,14 +380,12 @@ int au0828_dvb_register(struct au0828_dev *dev) | |||
| 353 | switch (dev->board) { | 380 | switch (dev->board) { |
| 354 | case AU0828_BOARD_HAUPPAUGE_HVR850: | 381 | case AU0828_BOARD_HAUPPAUGE_HVR850: |
| 355 | case AU0828_BOARD_HAUPPAUGE_HVR950Q: | 382 | case AU0828_BOARD_HAUPPAUGE_HVR950Q: |
| 356 | case AU0828_BOARD_DVICO_FUSIONHDTV7: | ||
| 357 | dvb->frontend = dvb_attach(au8522_attach, | 383 | dvb->frontend = dvb_attach(au8522_attach, |
| 358 | &hauppauge_hvr950q_config, | 384 | &hauppauge_hvr950q_config, |
| 359 | &dev->i2c_adap); | 385 | &dev->i2c_adap); |
| 360 | if (dvb->frontend != NULL) | 386 | if (dvb->frontend != NULL) |
| 361 | dvb_attach(xc5000_attach, dvb->frontend, | 387 | dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, |
| 362 | &dev->i2c_adap, | 388 | &hauppauge_hvr950q_tunerconfig); |
| 363 | &hauppauge_hvr950q_tunerconfig, dev); | ||
| 364 | break; | 389 | break; |
| 365 | case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: | 390 | case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: |
| 366 | dvb->frontend = dvb_attach(au8522_attach, | 391 | dvb->frontend = dvb_attach(au8522_attach, |
| @@ -380,6 +405,16 @@ int au0828_dvb_register(struct au0828_dev *dev) | |||
| 380 | 0x60, &dev->i2c_adap, | 405 | 0x60, &dev->i2c_adap, |
| 381 | &hauppauge_woodbury_tunerconfig); | 406 | &hauppauge_woodbury_tunerconfig); |
| 382 | break; | 407 | break; |
| 408 | case AU0828_BOARD_DVICO_FUSIONHDTV7: | ||
| 409 | dvb->frontend = dvb_attach(au8522_attach, | ||
| 410 | &fusionhdtv7usb_config, | ||
| 411 | &dev->i2c_adap); | ||
| 412 | if (dvb->frontend != NULL) { | ||
| 413 | dvb_attach(xc5000_attach, dvb->frontend, | ||
| 414 | &dev->i2c_adap, | ||
| 415 | &hauppauge_hvr950q_tunerconfig); | ||
| 416 | } | ||
| 417 | break; | ||
| 383 | default: | 418 | default: |
| 384 | printk(KERN_WARNING "The frontend of your DVB/ATSC card " | 419 | printk(KERN_WARNING "The frontend of your DVB/ATSC card " |
| 385 | "isn't supported yet\n"); | 420 | "isn't supported yet\n"); |
| @@ -390,6 +425,8 @@ int au0828_dvb_register(struct au0828_dev *dev) | |||
| 390 | __func__); | 425 | __func__); |
| 391 | return -1; | 426 | return -1; |
| 392 | } | 427 | } |
| 428 | /* define general-purpose callback pointer */ | ||
| 429 | dvb->frontend->callback = au0828_tuner_callback; | ||
| 393 | 430 | ||
| 394 | /* register everything */ | 431 | /* register everything */ |
| 395 | ret = dvb_register(dev); | 432 | ret = dvb_register(dev); |
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 4f10ff300135..9d6a1161dc98 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h | |||
| @@ -103,7 +103,8 @@ extern int au0828_debug; | |||
| 103 | extern struct au0828_board au0828_boards[]; | 103 | extern struct au0828_board au0828_boards[]; |
| 104 | extern struct usb_device_id au0828_usb_id_table[]; | 104 | extern struct usb_device_id au0828_usb_id_table[]; |
| 105 | extern void au0828_gpio_setup(struct au0828_dev *dev); | 105 | extern void au0828_gpio_setup(struct au0828_dev *dev); |
| 106 | extern int au0828_tuner_callback(void *priv, int command, int arg); | 106 | extern int au0828_tuner_callback(void *priv, int component, |
| 107 | int command, int arg); | ||
| 107 | extern void au0828_card_setup(struct au0828_dev *dev); | 108 | extern void au0828_card_setup(struct au0828_dev *dev); |
| 108 | 109 | ||
| 109 | /* ----------------------------------------------------------- */ | 110 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 98ee2d8feb34..ab2ce4d7b5de 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c | |||
| @@ -68,8 +68,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); | |||
| 68 | 68 | ||
| 69 | /* ----------------------------------------------------------------------- */ | 69 | /* ----------------------------------------------------------------------- */ |
| 70 | 70 | ||
| 71 | #define REG_OFFSET 0xDA | 71 | #define BT856_REG_OFFSET 0xDA |
| 72 | #define BT856_NR_REG 6 | 72 | #define BT856_NR_REG 6 |
| 73 | 73 | ||
| 74 | struct bt856 { | 74 | struct bt856 { |
| 75 | unsigned char reg[BT856_NR_REG]; | 75 | unsigned char reg[BT856_NR_REG]; |
| @@ -89,7 +89,7 @@ bt856_write (struct i2c_client *client, | |||
| 89 | { | 89 | { |
| 90 | struct bt856 *encoder = i2c_get_clientdata(client); | 90 | struct bt856 *encoder = i2c_get_clientdata(client); |
| 91 | 91 | ||
| 92 | encoder->reg[reg - REG_OFFSET] = value; | 92 | encoder->reg[reg - BT856_REG_OFFSET] = value; |
| 93 | return i2c_smbus_write_byte_data(client, reg, value); | 93 | return i2c_smbus_write_byte_data(client, reg, value); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| @@ -103,7 +103,7 @@ bt856_setbit (struct i2c_client *client, | |||
| 103 | 103 | ||
| 104 | return bt856_write(client, reg, | 104 | return bt856_write(client, reg, |
| 105 | (encoder-> | 105 | (encoder-> |
| 106 | reg[reg - REG_OFFSET] & ~(1 << bit)) | | 106 | reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) | |
| 107 | (value ? (1 << bit) : 0)); | 107 | (value ? (1 << bit) : 0)); |
| 108 | } | 108 | } |
| 109 | 109 | ||
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 6081edc362df..13742b0bbe3e 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c | |||
| @@ -305,7 +305,7 @@ static struct CARD { | |||
| 305 | { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, | 305 | { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, |
| 306 | { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" }, | 306 | { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" }, |
| 307 | { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" }, | 307 | { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" }, |
| 308 | 308 | { 0x18011000, BTTV_BOARD_ENLTV_FM_2, "Encore ENL TV-FM-2" }, | |
| 309 | { 0, -1, NULL } | 309 | { 0, -1, NULL } |
| 310 | }; | 310 | }; |
| 311 | 311 | ||
| @@ -3037,6 +3037,31 @@ struct tvcard bttv_tvcards[] = { | |||
| 3037 | .has_radio = 1, | 3037 | .has_radio = 1, |
| 3038 | .has_remote = 1, | 3038 | .has_remote = 1, |
| 3039 | }, | 3039 | }, |
| 3040 | [BTTV_BOARD_ENLTV_FM_2] = { | ||
| 3041 | /* Encore TV Tuner Pro ENL TV-FM-2 | ||
| 3042 | Mauro Carvalho Chehab <mchehab@infradead.org */ | ||
| 3043 | .name = "Encore ENL TV-FM-2", | ||
| 3044 | .video_inputs = 3, | ||
| 3045 | .audio_inputs = 1, | ||
| 3046 | .tuner = 0, | ||
| 3047 | .svhs = 2, | ||
| 3048 | /* bit 6 -> IR disabled | ||
| 3049 | bit 18/17 = 00 -> mute | ||
| 3050 | 01 -> enable external audio input | ||
| 3051 | 10 -> internal audio input (mono?) | ||
| 3052 | 11 -> internal audio input | ||
| 3053 | */ | ||
| 3054 | .gpiomask = 0x060040, | ||
| 3055 | .muxsel = { 2, 3, 3 }, | ||
| 3056 | .gpiomux = { 0x60000, 0x60000, 0x20000, 0x20000 }, | ||
| 3057 | .gpiomute = 0, | ||
| 3058 | .tuner_type = TUNER_TCL_MF02GIP_5N, | ||
| 3059 | .tuner_addr = ADDR_UNSET, | ||
| 3060 | .radio_addr = ADDR_UNSET, | ||
| 3061 | .pll = PLL_28, | ||
| 3062 | .has_radio = 1, | ||
| 3063 | .has_remote = 1, | ||
| 3064 | } | ||
| 3040 | }; | 3065 | }; |
| 3041 | 3066 | ||
| 3042 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); | 3067 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 933eaef41ead..5858bf5ff41c 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
| @@ -76,9 +76,9 @@ static unsigned int gbuffers = 8; | |||
| 76 | static unsigned int gbufsize = 0x208000; | 76 | static unsigned int gbufsize = 0x208000; |
| 77 | static unsigned int reset_crop = 1; | 77 | static unsigned int reset_crop = 1; |
| 78 | 78 | ||
| 79 | static int video_nr = -1; | 79 | static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; |
| 80 | static int radio_nr = -1; | 80 | static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; |
| 81 | static int vbi_nr = -1; | 81 | static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; |
| 82 | static int debug_latency; | 82 | static int debug_latency; |
| 83 | 83 | ||
| 84 | static unsigned int fdsr; | 84 | static unsigned int fdsr; |
| @@ -108,9 +108,6 @@ module_param(irq_debug, int, 0644); | |||
| 108 | module_param(debug_latency, int, 0644); | 108 | module_param(debug_latency, int, 0644); |
| 109 | 109 | ||
| 110 | module_param(fdsr, int, 0444); | 110 | module_param(fdsr, int, 0444); |
| 111 | module_param(video_nr, int, 0444); | ||
| 112 | module_param(radio_nr, int, 0444); | ||
| 113 | module_param(vbi_nr, int, 0444); | ||
| 114 | module_param(gbuffers, int, 0444); | 111 | module_param(gbuffers, int, 0444); |
| 115 | module_param(gbufsize, int, 0444); | 112 | module_param(gbufsize, int, 0444); |
| 116 | module_param(reset_crop, int, 0444); | 113 | module_param(reset_crop, int, 0444); |
| @@ -130,7 +127,10 @@ module_param(uv_ratio, int, 0444); | |||
| 130 | module_param(full_luma_range, int, 0444); | 127 | module_param(full_luma_range, int, 0444); |
| 131 | module_param(coring, int, 0444); | 128 | module_param(coring, int, 0444); |
| 132 | 129 | ||
| 133 | module_param_array(radio, int, NULL, 0444); | 130 | module_param_array(radio, int, NULL, 0444); |
| 131 | module_param_array(video_nr, int, NULL, 0444); | ||
| 132 | module_param_array(radio_nr, int, NULL, 0444); | ||
| 133 | module_param_array(vbi_nr, int, NULL, 0444); | ||
| 134 | 134 | ||
| 135 | MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)"); | 135 | MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)"); |
| 136 | MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian"); | 136 | MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian"); |
| @@ -152,6 +152,9 @@ MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler"); | |||
| 152 | MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50"); | 152 | MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50"); |
| 153 | MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)"); | 153 | MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)"); |
| 154 | MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)"); | 154 | MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)"); |
| 155 | MODULE_PARM_DESC(video_nr, "video device numbers"); | ||
| 156 | MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); | ||
| 157 | MODULE_PARM_DESC(radio_nr, "radio device numbers"); | ||
| 155 | 158 | ||
| 156 | MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards"); | 159 | MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards"); |
| 157 | MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); | 160 | MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); |
| @@ -1367,7 +1370,7 @@ static void init_irqreg(struct bttv *btv) | |||
| 1367 | (btv->gpioirq ? BT848_INT_GPINT : 0) | | 1370 | (btv->gpioirq ? BT848_INT_GPINT : 0) | |
| 1368 | BT848_INT_SCERR | | 1371 | BT848_INT_SCERR | |
| 1369 | (fdsr ? BT848_INT_FDSR : 0) | | 1372 | (fdsr ? BT848_INT_FDSR : 0) | |
| 1370 | BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| | 1373 | BT848_INT_RISCI | BT848_INT_OCERR | |
| 1371 | BT848_INT_FMTCHG|BT848_INT_HLOCK| | 1374 | BT848_INT_FMTCHG|BT848_INT_HLOCK| |
| 1372 | BT848_INT_I2CDONE, | 1375 | BT848_INT_I2CDONE, |
| 1373 | BT848_INT_MASK); | 1376 | BT848_INT_MASK); |
| @@ -2661,18 +2664,6 @@ static int bttv_querycap(struct file *file, void *priv, | |||
| 2661 | return 0; | 2664 | return 0; |
| 2662 | } | 2665 | } |
| 2663 | 2666 | ||
| 2664 | static int bttv_enum_fmt_vbi_cap(struct file *file, void *priv, | ||
| 2665 | struct v4l2_fmtdesc *f) | ||
| 2666 | { | ||
| 2667 | if (0 != f->index) | ||
| 2668 | return -EINVAL; | ||
| 2669 | |||
| 2670 | f->pixelformat = V4L2_PIX_FMT_GREY; | ||
| 2671 | strcpy(f->description, "vbi data"); | ||
| 2672 | |||
| 2673 | return 0; | ||
| 2674 | } | ||
| 2675 | |||
| 2676 | static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f) | 2667 | static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f) |
| 2677 | { | 2668 | { |
| 2678 | int index = -1, i; | 2669 | int index = -1, i; |
| @@ -3227,6 +3218,7 @@ static int bttv_open(struct inode *inode, struct file *file) | |||
| 3227 | 3218 | ||
| 3228 | dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); | 3219 | dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); |
| 3229 | 3220 | ||
| 3221 | lock_kernel(); | ||
| 3230 | for (i = 0; i < bttv_num; i++) { | 3222 | for (i = 0; i < bttv_num; i++) { |
| 3231 | if (bttvs[i].video_dev && | 3223 | if (bttvs[i].video_dev && |
| 3232 | bttvs[i].video_dev->minor == minor) { | 3224 | bttvs[i].video_dev->minor == minor) { |
| @@ -3241,16 +3233,20 @@ static int bttv_open(struct inode *inode, struct file *file) | |||
| 3241 | break; | 3233 | break; |
| 3242 | } | 3234 | } |
| 3243 | } | 3235 | } |
| 3244 | if (NULL == btv) | 3236 | if (NULL == btv) { |
| 3237 | unlock_kernel(); | ||
| 3245 | return -ENODEV; | 3238 | return -ENODEV; |
| 3239 | } | ||
| 3246 | 3240 | ||
| 3247 | dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", | 3241 | dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", |
| 3248 | btv->c.nr,v4l2_type_names[type]); | 3242 | btv->c.nr,v4l2_type_names[type]); |
| 3249 | 3243 | ||
| 3250 | /* allocate per filehandle data */ | 3244 | /* allocate per filehandle data */ |
| 3251 | fh = kmalloc(sizeof(*fh),GFP_KERNEL); | 3245 | fh = kmalloc(sizeof(*fh),GFP_KERNEL); |
| 3252 | if (NULL == fh) | 3246 | if (NULL == fh) { |
| 3247 | unlock_kernel(); | ||
| 3253 | return -ENOMEM; | 3248 | return -ENOMEM; |
| 3249 | } | ||
| 3254 | file->private_data = fh; | 3250 | file->private_data = fh; |
| 3255 | *fh = btv->init; | 3251 | *fh = btv->init; |
| 3256 | fh->type = type; | 3252 | fh->type = type; |
| @@ -3270,6 +3266,7 @@ static int bttv_open(struct inode *inode, struct file *file) | |||
| 3270 | sizeof(struct bttv_buffer), | 3266 | sizeof(struct bttv_buffer), |
| 3271 | fh); | 3267 | fh); |
| 3272 | set_tvnorm(btv,btv->tvnorm); | 3268 | set_tvnorm(btv,btv->tvnorm); |
| 3269 | set_input(btv, btv->input, btv->tvnorm); | ||
| 3273 | 3270 | ||
| 3274 | btv->users++; | 3271 | btv->users++; |
| 3275 | 3272 | ||
| @@ -3290,6 +3287,7 @@ static int bttv_open(struct inode *inode, struct file *file) | |||
| 3290 | bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm); | 3287 | bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm); |
| 3291 | 3288 | ||
| 3292 | bttv_field_count(btv); | 3289 | bttv_field_count(btv); |
| 3290 | unlock_kernel(); | ||
| 3293 | return 0; | 3291 | return 0; |
| 3294 | } | 3292 | } |
| 3295 | 3293 | ||
| @@ -3330,6 +3328,10 @@ static int bttv_release(struct inode *inode, struct file *file) | |||
| 3330 | 3328 | ||
| 3331 | btv->users--; | 3329 | btv->users--; |
| 3332 | bttv_field_count(btv); | 3330 | bttv_field_count(btv); |
| 3331 | |||
| 3332 | if (!btv->users) | ||
| 3333 | audio_mute(btv, 1); | ||
| 3334 | |||
| 3333 | return 0; | 3335 | return 0; |
| 3334 | } | 3336 | } |
| 3335 | 3337 | ||
| @@ -3367,7 +3369,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = { | |||
| 3367 | .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay, | 3369 | .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay, |
| 3368 | .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay, | 3370 | .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay, |
| 3369 | .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay, | 3371 | .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay, |
| 3370 | .vidioc_enum_fmt_vbi_cap = bttv_enum_fmt_vbi_cap, | ||
| 3371 | .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap, | 3372 | .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap, |
| 3372 | .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap, | 3373 | .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap, |
| 3373 | .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap, | 3374 | .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap, |
| @@ -3430,21 +3431,26 @@ static int radio_open(struct inode *inode, struct file *file) | |||
| 3430 | 3431 | ||
| 3431 | dprintk("bttv: open minor=%d\n",minor); | 3432 | dprintk("bttv: open minor=%d\n",minor); |
| 3432 | 3433 | ||
| 3434 | lock_kernel(); | ||
| 3433 | for (i = 0; i < bttv_num; i++) { | 3435 | for (i = 0; i < bttv_num; i++) { |
| 3434 | if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) { | 3436 | if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) { |
| 3435 | btv = &bttvs[i]; | 3437 | btv = &bttvs[i]; |
| 3436 | break; | 3438 | break; |
| 3437 | } | 3439 | } |
| 3438 | } | 3440 | } |
| 3439 | if (NULL == btv) | 3441 | if (NULL == btv) { |
| 3442 | unlock_kernel(); | ||
| 3440 | return -ENODEV; | 3443 | return -ENODEV; |
| 3444 | } | ||
| 3441 | 3445 | ||
| 3442 | dprintk("bttv%d: open called (radio)\n",btv->c.nr); | 3446 | dprintk("bttv%d: open called (radio)\n",btv->c.nr); |
| 3443 | 3447 | ||
| 3444 | /* allocate per filehandle data */ | 3448 | /* allocate per filehandle data */ |
| 3445 | fh = kmalloc(sizeof(*fh), GFP_KERNEL); | 3449 | fh = kmalloc(sizeof(*fh), GFP_KERNEL); |
| 3446 | if (NULL == fh) | 3450 | if (NULL == fh) { |
| 3451 | unlock_kernel(); | ||
| 3447 | return -ENOMEM; | 3452 | return -ENOMEM; |
| 3453 | } | ||
| 3448 | file->private_data = fh; | 3454 | file->private_data = fh; |
| 3449 | *fh = btv->init; | 3455 | *fh = btv->init; |
| 3450 | v4l2_prio_open(&btv->prio, &fh->prio); | 3456 | v4l2_prio_open(&btv->prio, &fh->prio); |
| @@ -3457,6 +3463,7 @@ static int radio_open(struct inode *inode, struct file *file) | |||
| 3457 | audio_input(btv,TVAUDIO_INPUT_RADIO); | 3463 | audio_input(btv,TVAUDIO_INPUT_RADIO); |
| 3458 | 3464 | ||
| 3459 | mutex_unlock(&btv->lock); | 3465 | mutex_unlock(&btv->lock); |
| 3466 | unlock_kernel(); | ||
| 3460 | return 0; | 3467 | return 0; |
| 3461 | } | 3468 | } |
| 3462 | 3469 | ||
| @@ -4235,7 +4242,8 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
| 4235 | 4242 | ||
| 4236 | if (NULL == btv->video_dev) | 4243 | if (NULL == btv->video_dev) |
| 4237 | goto err; | 4244 | goto err; |
| 4238 | if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) | 4245 | if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER, |
| 4246 | video_nr[btv->c.nr]) < 0) | ||
| 4239 | goto err; | 4247 | goto err; |
| 4240 | printk(KERN_INFO "bttv%d: registered device video%d\n", | 4248 | printk(KERN_INFO "bttv%d: registered device video%d\n", |
| 4241 | btv->c.nr,btv->video_dev->minor & 0x1f); | 4249 | btv->c.nr,btv->video_dev->minor & 0x1f); |
| @@ -4251,7 +4259,8 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
| 4251 | 4259 | ||
| 4252 | if (NULL == btv->vbi_dev) | 4260 | if (NULL == btv->vbi_dev) |
| 4253 | goto err; | 4261 | goto err; |
| 4254 | if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) | 4262 | if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI, |
| 4263 | vbi_nr[btv->c.nr]) < 0) | ||
| 4255 | goto err; | 4264 | goto err; |
| 4256 | printk(KERN_INFO "bttv%d: registered device vbi%d\n", | 4265 | printk(KERN_INFO "bttv%d: registered device vbi%d\n", |
| 4257 | btv->c.nr,btv->vbi_dev->minor & 0x1f); | 4266 | btv->c.nr,btv->vbi_dev->minor & 0x1f); |
| @@ -4262,7 +4271,8 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
| 4262 | btv->radio_dev = vdev_init(btv, &radio_template, "radio"); | 4271 | btv->radio_dev = vdev_init(btv, &radio_template, "radio"); |
| 4263 | if (NULL == btv->radio_dev) | 4272 | if (NULL == btv->radio_dev) |
| 4264 | goto err; | 4273 | goto err; |
| 4265 | if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) | 4274 | if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO, |
| 4275 | radio_nr[btv->c.nr]) < 0) | ||
| 4266 | goto err; | 4276 | goto err; |
| 4267 | printk(KERN_INFO "bttv%d: registered device radio%d\n", | 4277 | printk(KERN_INFO "bttv%d: registered device radio%d\n", |
| 4268 | btv->c.nr,btv->radio_dev->minor & 0x1f); | 4278 | btv->c.nr,btv->radio_dev->minor & 0x1f); |
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index a38af98f4cae..2f289d981fe6 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
| @@ -28,8 +28,8 @@ | |||
| 28 | #include "bttvp.h" | 28 | #include "bttvp.h" |
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | static int debug; | 31 | static int ir_debug; |
| 32 | module_param(debug, int, 0644); /* debug level (0,1,2) */ | 32 | module_param(ir_debug, int, 0644); |
| 33 | static int repeat_delay = 500; | 33 | static int repeat_delay = 500; |
| 34 | module_param(repeat_delay, int, 0644); | 34 | module_param(repeat_delay, int, 0644); |
| 35 | static int repeat_period = 33; | 35 | static int repeat_period = 33; |
| @@ -40,6 +40,12 @@ module_param(ir_rc5_remote_gap, int, 0644); | |||
| 40 | static int ir_rc5_key_timeout = 200; | 40 | static int ir_rc5_key_timeout = 200; |
| 41 | module_param(ir_rc5_key_timeout, int, 0644); | 41 | module_param(ir_rc5_key_timeout, int, 0644); |
| 42 | 42 | ||
| 43 | #undef dprintk | ||
| 44 | #define dprintk(arg...) do { \ | ||
| 45 | if (ir_debug >= 1) \ | ||
| 46 | printk(arg); \ | ||
| 47 | } while (0) | ||
| 48 | |||
| 43 | #define DEVNAME "bttv-input" | 49 | #define DEVNAME "bttv-input" |
| 44 | 50 | ||
| 45 | /* ---------------------------------------------------------------------- */ | 51 | /* ---------------------------------------------------------------------- */ |
| @@ -79,6 +85,45 @@ static void ir_handle_key(struct bttv *btv) | |||
| 79 | 85 | ||
| 80 | } | 86 | } |
| 81 | 87 | ||
| 88 | static void ir_enltv_handle_key(struct bttv *btv) | ||
| 89 | { | ||
| 90 | struct card_ir *ir = btv->remote; | ||
| 91 | u32 gpio, data, keyup; | ||
| 92 | |||
| 93 | /* read gpio value */ | ||
| 94 | gpio = bttv_gpio_read(&btv->c); | ||
| 95 | |||
| 96 | /* extract data */ | ||
| 97 | data = ir_extract_bits(gpio, ir->mask_keycode); | ||
| 98 | |||
| 99 | /* Check if it is keyup */ | ||
| 100 | keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0; | ||
| 101 | |||
| 102 | if ((ir->last_gpio & 0x7f) != data) { | ||
| 103 | dprintk(KERN_INFO DEVNAME ": gpio=0x%x code=%d | %s\n", | ||
| 104 | gpio, data, | ||
| 105 | (gpio & ir->mask_keyup) ? " up" : "up/down"); | ||
| 106 | |||
| 107 | ir_input_keydown(ir->dev, &ir->ir, data, data); | ||
| 108 | if (keyup) | ||
| 109 | ir_input_nokey(ir->dev, &ir->ir); | ||
| 110 | } else { | ||
| 111 | if ((ir->last_gpio & 1 << 31) == keyup) | ||
| 112 | return; | ||
| 113 | |||
| 114 | dprintk(KERN_INFO DEVNAME ":(cnt) gpio=0x%x code=%d | %s\n", | ||
| 115 | gpio, data, | ||
| 116 | (gpio & ir->mask_keyup) ? " up" : "down"); | ||
| 117 | |||
| 118 | if (keyup) | ||
| 119 | ir_input_nokey(ir->dev, &ir->ir); | ||
| 120 | else | ||
| 121 | ir_input_keydown(ir->dev, &ir->ir, data, data); | ||
| 122 | } | ||
| 123 | |||
| 124 | ir->last_gpio = data | keyup; | ||
| 125 | } | ||
| 126 | |||
| 82 | void bttv_input_irq(struct bttv *btv) | 127 | void bttv_input_irq(struct bttv *btv) |
| 83 | { | 128 | { |
| 84 | struct card_ir *ir = btv->remote; | 129 | struct card_ir *ir = btv->remote; |
| @@ -92,7 +137,10 @@ static void bttv_input_timer(unsigned long data) | |||
| 92 | struct bttv *btv = (struct bttv*)data; | 137 | struct bttv *btv = (struct bttv*)data; |
| 93 | struct card_ir *ir = btv->remote; | 138 | struct card_ir *ir = btv->remote; |
| 94 | 139 | ||
| 95 | ir_handle_key(btv); | 140 | if (btv->c.type == BTTV_BOARD_ENLTV_FM_2) |
| 141 | ir_enltv_handle_key(btv); | ||
| 142 | else | ||
| 143 | ir_handle_key(btv); | ||
| 96 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); | 144 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); |
| 97 | } | 145 | } |
| 98 | 146 | ||
| @@ -284,6 +332,14 @@ int bttv_input_init(struct bttv *btv) | |||
| 284 | ir->mask_keyup = 0x006000; | 332 | ir->mask_keyup = 0x006000; |
| 285 | ir->polling = 50; /* ms */ | 333 | ir->polling = 50; /* ms */ |
| 286 | break; | 334 | break; |
| 335 | case BTTV_BOARD_ENLTV_FM_2: | ||
| 336 | ir_codes = ir_codes_encore_enltv2; | ||
| 337 | ir->mask_keycode = 0x00fd00; | ||
| 338 | ir->mask_keyup = 0x000080; | ||
| 339 | ir->polling = 1; /* ms */ | ||
| 340 | ir->last_gpio = ir_extract_bits(bttv_gpio_read(&btv->c), | ||
| 341 | ir->mask_keycode); | ||
| 342 | break; | ||
| 287 | } | 343 | } |
| 288 | if (NULL == ir_codes) { | 344 | if (NULL == ir_codes) { |
| 289 | dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); | 345 | dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); |
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index 6d93d16c96e4..46cb90e0985b 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h | |||
| @@ -176,7 +176,7 @@ | |||
| 176 | #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95 | 176 | #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95 |
| 177 | #define BTTV_BOARD_GEOVISION_GV600 0x96 | 177 | #define BTTV_BOARD_GEOVISION_GV600 0x96 |
| 178 | #define BTTV_BOARD_KOZUMI_KTV_01C 0x97 | 178 | #define BTTV_BOARD_KOZUMI_KTV_01C 0x97 |
| 179 | 179 | #define BTTV_BOARD_ENLTV_FM_2 0x98 | |
| 180 | 180 | ||
| 181 | /* more card-specific defines */ | 181 | /* more card-specific defines */ |
| 182 | #define PT2254_L_CHANNEL 0x10 | 182 | #define PT2254_L_CHANNEL 0x10 |
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c index 3324ab38f58c..ac1b2687a20d 100644 --- a/drivers/media/video/btcx-risc.c +++ b/drivers/media/video/btcx-risc.c | |||
| @@ -64,7 +64,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci, | |||
| 64 | unsigned int size) | 64 | unsigned int size) |
| 65 | { | 65 | { |
| 66 | __le32 *cpu; | 66 | __le32 *cpu; |
| 67 | dma_addr_t dma; | 67 | dma_addr_t dma = 0; |
| 68 | 68 | ||
| 69 | if (NULL != risc->cpu && risc->size < size) | 69 | if (NULL != risc->cpu && risc->size < size) |
| 70 | btcx_riscmem_free(pci,risc); | 70 | btcx_riscmem_free(pci,risc); |
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index 6e39e253ce53..ace4ff9ea023 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c | |||
| @@ -495,7 +495,7 @@ static void qc_set(struct qcam_device *q) | |||
| 495 | val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * | 495 | val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * |
| 496 | q->transfer_scale; | 496 | q->transfer_scale; |
| 497 | } | 497 | } |
| 498 | val = (val + val2 - 1) / val2; | 498 | val = DIV_ROUND_UP(val, val2); |
| 499 | qc_command(q, 0x13); | 499 | qc_command(q, 0x13); |
| 500 | qc_command(q, val); | 500 | qc_command(q, val); |
| 501 | 501 | ||
| @@ -651,7 +651,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l | |||
| 651 | transperline = q->width * q->bpp; | 651 | transperline = q->width * q->bpp; |
| 652 | divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * | 652 | divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) * |
| 653 | q->transfer_scale; | 653 | q->transfer_scale; |
| 654 | transperline = (transperline + divisor - 1) / divisor; | 654 | transperline = DIV_ROUND_UP(transperline, divisor); |
| 655 | 655 | ||
| 656 | for (i = 0, yield = yieldlines; i < linestotrans; i++) | 656 | for (i = 0, yield = yieldlines; i < linestotrans; i++) |
| 657 | { | 657 | { |
| @@ -894,10 +894,27 @@ static ssize_t qcam_read(struct file *file, char __user *buf, | |||
| 894 | return len; | 894 | return len; |
| 895 | } | 895 | } |
| 896 | 896 | ||
| 897 | static int qcam_exclusive_open(struct inode *inode, struct file *file) | ||
| 898 | { | ||
| 899 | struct video_device *dev = video_devdata(file); | ||
| 900 | struct qcam_device *qcam = (struct qcam_device *)dev; | ||
| 901 | |||
| 902 | return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; | ||
| 903 | } | ||
| 904 | |||
| 905 | static int qcam_exclusive_release(struct inode *inode, struct file *file) | ||
| 906 | { | ||
| 907 | struct video_device *dev = video_devdata(file); | ||
| 908 | struct qcam_device *qcam = (struct qcam_device *)dev; | ||
| 909 | |||
| 910 | clear_bit(0, &qcam->in_use); | ||
| 911 | return 0; | ||
| 912 | } | ||
| 913 | |||
| 897 | static const struct file_operations qcam_fops = { | 914 | static const struct file_operations qcam_fops = { |
| 898 | .owner = THIS_MODULE, | 915 | .owner = THIS_MODULE, |
| 899 | .open = video_exclusive_open, | 916 | .open = qcam_exclusive_open, |
| 900 | .release = video_exclusive_release, | 917 | .release = qcam_exclusive_release, |
| 901 | .ioctl = qcam_ioctl, | 918 | .ioctl = qcam_ioctl, |
| 902 | #ifdef CONFIG_COMPAT | 919 | #ifdef CONFIG_COMPAT |
| 903 | .compat_ioctl = v4l_compat_ioctl32, | 920 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -909,6 +926,7 @@ static struct video_device qcam_template= | |||
| 909 | { | 926 | { |
| 910 | .name = "Connectix Quickcam", | 927 | .name = "Connectix Quickcam", |
| 911 | .fops = &qcam_fops, | 928 | .fops = &qcam_fops, |
| 929 | .release = video_device_release_empty, | ||
| 912 | }; | 930 | }; |
| 913 | 931 | ||
| 914 | #define MAX_CAMS 4 | 932 | #define MAX_CAMS 4 |
diff --git a/drivers/media/video/bw-qcam.h b/drivers/media/video/bw-qcam.h index 6701dafbc0da..8a60c5de0935 100644 --- a/drivers/media/video/bw-qcam.h +++ b/drivers/media/video/bw-qcam.h | |||
| @@ -65,4 +65,5 @@ struct qcam_device { | |||
| 65 | int top, left; | 65 | int top, left; |
| 66 | int status; | 66 | int status; |
| 67 | unsigned int saved_bits; | 67 | unsigned int saved_bits; |
| 68 | unsigned long in_use; | ||
| 68 | }; | 69 | }; |
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 7f6c6b4bec10..17aa0adb3467 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c | |||
| @@ -51,6 +51,7 @@ struct qcam_device { | |||
| 51 | int contrast, brightness, whitebal; | 51 | int contrast, brightness, whitebal; |
| 52 | int top, left; | 52 | int top, left; |
| 53 | unsigned int bidirectional; | 53 | unsigned int bidirectional; |
| 54 | unsigned long in_use; | ||
| 54 | struct mutex lock; | 55 | struct mutex lock; |
| 55 | }; | 56 | }; |
| 56 | 57 | ||
| @@ -687,11 +688,28 @@ static ssize_t qcam_read(struct file *file, char __user *buf, | |||
| 687 | return len; | 688 | return len; |
| 688 | } | 689 | } |
| 689 | 690 | ||
| 691 | static int qcam_exclusive_open(struct inode *inode, struct file *file) | ||
| 692 | { | ||
| 693 | struct video_device *dev = video_devdata(file); | ||
| 694 | struct qcam_device *qcam = (struct qcam_device *)dev; | ||
| 695 | |||
| 696 | return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0; | ||
| 697 | } | ||
| 698 | |||
| 699 | static int qcam_exclusive_release(struct inode *inode, struct file *file) | ||
| 700 | { | ||
| 701 | struct video_device *dev = video_devdata(file); | ||
| 702 | struct qcam_device *qcam = (struct qcam_device *)dev; | ||
| 703 | |||
| 704 | clear_bit(0, &qcam->in_use); | ||
| 705 | return 0; | ||
| 706 | } | ||
| 707 | |||
| 690 | /* video device template */ | 708 | /* video device template */ |
| 691 | static const struct file_operations qcam_fops = { | 709 | static const struct file_operations qcam_fops = { |
| 692 | .owner = THIS_MODULE, | 710 | .owner = THIS_MODULE, |
| 693 | .open = video_exclusive_open, | 711 | .open = qcam_exclusive_open, |
| 694 | .release = video_exclusive_release, | 712 | .release = qcam_exclusive_release, |
| 695 | .ioctl = qcam_ioctl, | 713 | .ioctl = qcam_ioctl, |
| 696 | #ifdef CONFIG_COMPAT | 714 | #ifdef CONFIG_COMPAT |
| 697 | .compat_ioctl = v4l_compat_ioctl32, | 715 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -704,6 +722,7 @@ static struct video_device qcam_template= | |||
| 704 | { | 722 | { |
| 705 | .name = "Colour QuickCam", | 723 | .name = "Colour QuickCam", |
| 706 | .fops = &qcam_fops, | 724 | .fops = &qcam_fops, |
| 725 | .release = video_device_release_empty, | ||
| 707 | }; | 726 | }; |
| 708 | 727 | ||
| 709 | /* Initialize the QuickCam driver control structure. */ | 728 | /* Initialize the QuickCam driver control structure. */ |
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 08efbe7254ff..fc9497bdd322 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
| @@ -1476,9 +1476,12 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) | |||
| 1476 | { | 1476 | { |
| 1477 | struct cafe_camera *cam; | 1477 | struct cafe_camera *cam; |
| 1478 | 1478 | ||
| 1479 | lock_kernel(); | ||
| 1479 | cam = cafe_find_dev(iminor(inode)); | 1480 | cam = cafe_find_dev(iminor(inode)); |
| 1480 | if (cam == NULL) | 1481 | if (cam == NULL) { |
| 1482 | unlock_kernel(); | ||
| 1481 | return -ENODEV; | 1483 | return -ENODEV; |
| 1484 | } | ||
| 1482 | filp->private_data = cam; | 1485 | filp->private_data = cam; |
| 1483 | 1486 | ||
| 1484 | mutex_lock(&cam->s_mutex); | 1487 | mutex_lock(&cam->s_mutex); |
| @@ -1490,6 +1493,7 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) | |||
| 1490 | } | 1493 | } |
| 1491 | (cam->users)++; | 1494 | (cam->users)++; |
| 1492 | mutex_unlock(&cam->s_mutex); | 1495 | mutex_unlock(&cam->s_mutex); |
| 1496 | unlock_kernel(); | ||
| 1493 | return 0; | 1497 | return 0; |
| 1494 | } | 1498 | } |
| 1495 | 1499 | ||
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index a661800b0e69..c325e926de8a 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c | |||
| @@ -3155,7 +3155,7 @@ static void put_cam(struct cpia_camera_ops* ops) | |||
| 3155 | static int cpia_open(struct inode *inode, struct file *file) | 3155 | static int cpia_open(struct inode *inode, struct file *file) |
| 3156 | { | 3156 | { |
| 3157 | struct video_device *dev = video_devdata(file); | 3157 | struct video_device *dev = video_devdata(file); |
| 3158 | struct cam_data *cam = dev->priv; | 3158 | struct cam_data *cam = video_get_drvdata(dev); |
| 3159 | int err; | 3159 | int err; |
| 3160 | 3160 | ||
| 3161 | if (!cam) { | 3161 | if (!cam) { |
| @@ -3202,7 +3202,7 @@ static int cpia_open(struct inode *inode, struct file *file) | |||
| 3202 | 3202 | ||
| 3203 | /* Set ownership of /proc/cpia/videoX to current user */ | 3203 | /* Set ownership of /proc/cpia/videoX to current user */ |
| 3204 | if(cam->proc_entry) | 3204 | if(cam->proc_entry) |
| 3205 | cam->proc_entry->uid = current->uid; | 3205 | cam->proc_entry->uid = current_uid(); |
| 3206 | 3206 | ||
| 3207 | /* set mark for loading first frame uncompressed */ | 3207 | /* set mark for loading first frame uncompressed */ |
| 3208 | cam->first_frame = 1; | 3208 | cam->first_frame = 1; |
| @@ -3232,7 +3232,7 @@ static int cpia_open(struct inode *inode, struct file *file) | |||
| 3232 | static int cpia_close(struct inode *inode, struct file *file) | 3232 | static int cpia_close(struct inode *inode, struct file *file) |
| 3233 | { | 3233 | { |
| 3234 | struct video_device *dev = file->private_data; | 3234 | struct video_device *dev = file->private_data; |
| 3235 | struct cam_data *cam = dev->priv; | 3235 | struct cam_data *cam = video_get_drvdata(dev); |
| 3236 | 3236 | ||
| 3237 | if (cam->ops) { | 3237 | if (cam->ops) { |
| 3238 | /* Return ownership of /proc/cpia/videoX to root */ | 3238 | /* Return ownership of /proc/cpia/videoX to root */ |
| @@ -3284,7 +3284,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf, | |||
| 3284 | size_t count, loff_t *ppos) | 3284 | size_t count, loff_t *ppos) |
| 3285 | { | 3285 | { |
| 3286 | struct video_device *dev = file->private_data; | 3286 | struct video_device *dev = file->private_data; |
| 3287 | struct cam_data *cam = dev->priv; | 3287 | struct cam_data *cam = video_get_drvdata(dev); |
| 3288 | int err; | 3288 | int err; |
| 3289 | 3289 | ||
| 3290 | /* make this _really_ smp and multithread-safe */ | 3290 | /* make this _really_ smp and multithread-safe */ |
| @@ -3341,7 +3341,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, | |||
| 3341 | unsigned int ioctlnr, void *arg) | 3341 | unsigned int ioctlnr, void *arg) |
| 3342 | { | 3342 | { |
| 3343 | struct video_device *dev = file->private_data; | 3343 | struct video_device *dev = file->private_data; |
| 3344 | struct cam_data *cam = dev->priv; | 3344 | struct cam_data *cam = video_get_drvdata(dev); |
| 3345 | int retval = 0; | 3345 | int retval = 0; |
| 3346 | 3346 | ||
| 3347 | if (!cam || !cam->ops) | 3347 | if (!cam || !cam->ops) |
| @@ -3739,7 +3739,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 3739 | unsigned long start = vma->vm_start; | 3739 | unsigned long start = vma->vm_start; |
| 3740 | unsigned long size = vma->vm_end - vma->vm_start; | 3740 | unsigned long size = vma->vm_end - vma->vm_start; |
| 3741 | unsigned long page, pos; | 3741 | unsigned long page, pos; |
| 3742 | struct cam_data *cam = dev->priv; | 3742 | struct cam_data *cam = video_get_drvdata(dev); |
| 3743 | int retval; | 3743 | int retval; |
| 3744 | 3744 | ||
| 3745 | if (!cam || !cam->ops) | 3745 | if (!cam || !cam->ops) |
| @@ -3801,6 +3801,7 @@ static const struct file_operations cpia_fops = { | |||
| 3801 | static struct video_device cpia_template = { | 3801 | static struct video_device cpia_template = { |
| 3802 | .name = "CPiA Camera", | 3802 | .name = "CPiA Camera", |
| 3803 | .fops = &cpia_fops, | 3803 | .fops = &cpia_fops, |
| 3804 | .release = video_device_release_empty, | ||
| 3804 | }; | 3805 | }; |
| 3805 | 3806 | ||
| 3806 | /* initialise cam_data structure */ | 3807 | /* initialise cam_data structure */ |
| @@ -3928,7 +3929,7 @@ static void init_camera_struct(struct cam_data *cam, | |||
| 3928 | cam->proc_entry = NULL; | 3929 | cam->proc_entry = NULL; |
| 3929 | 3930 | ||
| 3930 | memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template)); | 3931 | memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template)); |
| 3931 | cam->vdev.priv = cam; | 3932 | video_set_drvdata(&cam->vdev, cam); |
| 3932 | 3933 | ||
| 3933 | cam->curframe = 0; | 3934 | cam->curframe = 0; |
| 3934 | for (i = 0; i < FRAME_NUM; i++) { | 3935 | for (i = 0; i < FRAME_NUM; i++) { |
diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index af8b9ec8e358..7e791b6923f9 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c | |||
| @@ -1537,7 +1537,7 @@ static int config_sensor_500(struct camera_data *cam, | |||
| 1537 | * | 1537 | * |
| 1538 | * This sets all user changeable properties to the values in cam->params. | 1538 | * This sets all user changeable properties to the values in cam->params. |
| 1539 | *****************************************************************************/ | 1539 | *****************************************************************************/ |
| 1540 | int set_all_properties(struct camera_data *cam) | 1540 | static int set_all_properties(struct camera_data *cam) |
| 1541 | { | 1541 | { |
| 1542 | /** | 1542 | /** |
| 1543 | * Don't set target_kb here, it will be set later. | 1543 | * Don't set target_kb here, it will be set later. |
| @@ -1588,7 +1588,7 @@ void cpia2_save_camera_state(struct camera_data *cam) | |||
| 1588 | * get_color_params | 1588 | * get_color_params |
| 1589 | * | 1589 | * |
| 1590 | *****************************************************************************/ | 1590 | *****************************************************************************/ |
| 1591 | void get_color_params(struct camera_data *cam) | 1591 | static void get_color_params(struct camera_data *cam) |
| 1592 | { | 1592 | { |
| 1593 | cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS, TRANSFER_READ, 0); | 1593 | cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS, TRANSFER_READ, 0); |
| 1594 | cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION, TRANSFER_READ, 0); | 1594 | cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION, TRANSFER_READ, 0); |
| @@ -1881,7 +1881,7 @@ void cpia2_set_saturation(struct camera_data *cam, unsigned char value) | |||
| 1881 | * wake_system | 1881 | * wake_system |
| 1882 | * | 1882 | * |
| 1883 | *****************************************************************************/ | 1883 | *****************************************************************************/ |
| 1884 | void wake_system(struct camera_data *cam) | 1884 | static void wake_system(struct camera_data *cam) |
| 1885 | { | 1885 | { |
| 1886 | cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0); | 1886 | cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0); |
| 1887 | } | 1887 | } |
| @@ -1892,7 +1892,7 @@ void wake_system(struct camera_data *cam) | |||
| 1892 | * | 1892 | * |
| 1893 | * Valid for STV500 sensor only | 1893 | * Valid for STV500 sensor only |
| 1894 | *****************************************************************************/ | 1894 | *****************************************************************************/ |
| 1895 | void set_lowlight_boost(struct camera_data *cam) | 1895 | static void set_lowlight_boost(struct camera_data *cam) |
| 1896 | { | 1896 | { |
| 1897 | struct cpia2_command cmd; | 1897 | struct cpia2_command cmd; |
| 1898 | 1898 | ||
| @@ -2169,7 +2169,7 @@ void cpia2_dbg_dump_registers(struct camera_data *cam) | |||
| 2169 | * | 2169 | * |
| 2170 | * Sets all values to the defaults | 2170 | * Sets all values to the defaults |
| 2171 | *****************************************************************************/ | 2171 | *****************************************************************************/ |
| 2172 | void reset_camera_struct(struct camera_data *cam) | 2172 | static void reset_camera_struct(struct camera_data *cam) |
| 2173 | { | 2173 | { |
| 2174 | /*** | 2174 | /*** |
| 2175 | * The following parameter values are the defaults from the register map. | 2175 | * The following parameter values are the defaults from the register map. |
diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c index a8a199047cbd..73511a542077 100644 --- a/drivers/media/video/cpia2/cpia2_usb.c +++ b/drivers/media/video/cpia2/cpia2_usb.c | |||
| @@ -478,7 +478,7 @@ int cpia2_usb_change_streaming_alternate(struct camera_data *cam, | |||
| 478 | * set_alternate | 478 | * set_alternate |
| 479 | * | 479 | * |
| 480 | *****************************************************************************/ | 480 | *****************************************************************************/ |
| 481 | int set_alternate(struct camera_data *cam, unsigned int alt) | 481 | static int set_alternate(struct camera_data *cam, unsigned int alt) |
| 482 | { | 482 | { |
| 483 | int ret = 0; | 483 | int ret = 0; |
| 484 | 484 | ||
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index eb9f15cd4c45..897e8d1a5c3c 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c | |||
| @@ -241,8 +241,7 @@ static struct v4l2_queryctrl controls[] = { | |||
| 241 | *****************************************************************************/ | 241 | *****************************************************************************/ |
| 242 | static int cpia2_open(struct inode *inode, struct file *file) | 242 | static int cpia2_open(struct inode *inode, struct file *file) |
| 243 | { | 243 | { |
| 244 | struct video_device *dev = video_devdata(file); | 244 | struct camera_data *cam = video_drvdata(file); |
| 245 | struct camera_data *cam = video_get_drvdata(dev); | ||
| 246 | int retval = 0; | 245 | int retval = 0; |
| 247 | 246 | ||
| 248 | if (!cam) { | 247 | if (!cam) { |
| @@ -357,8 +356,7 @@ static int cpia2_close(struct inode *inode, struct file *file) | |||
| 357 | static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, | 356 | static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, |
| 358 | loff_t *off) | 357 | loff_t *off) |
| 359 | { | 358 | { |
| 360 | struct video_device *dev = video_devdata(file); | 359 | struct camera_data *cam = video_drvdata(file); |
| 361 | struct camera_data *cam = video_get_drvdata(dev); | ||
| 362 | int noblock = file->f_flags&O_NONBLOCK; | 360 | int noblock = file->f_flags&O_NONBLOCK; |
| 363 | 361 | ||
| 364 | struct cpia2_fh *fh = file->private_data; | 362 | struct cpia2_fh *fh = file->private_data; |
| @@ -382,9 +380,7 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count, | |||
| 382 | *****************************************************************************/ | 380 | *****************************************************************************/ |
| 383 | static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait) | 381 | static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait) |
| 384 | { | 382 | { |
| 385 | struct video_device *dev = video_devdata(filp); | 383 | struct camera_data *cam = video_drvdata(filp); |
| 386 | struct camera_data *cam = video_get_drvdata(dev); | ||
| 387 | |||
| 388 | struct cpia2_fh *fh = filp->private_data; | 384 | struct cpia2_fh *fh = filp->private_data; |
| 389 | 385 | ||
| 390 | if(!cam) | 386 | if(!cam) |
| @@ -1579,8 +1575,7 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file) | |||
| 1579 | static int cpia2_do_ioctl(struct inode *inode, struct file *file, | 1575 | static int cpia2_do_ioctl(struct inode *inode, struct file *file, |
| 1580 | unsigned int ioctl_nr, void *arg) | 1576 | unsigned int ioctl_nr, void *arg) |
| 1581 | { | 1577 | { |
| 1582 | struct video_device *dev = video_devdata(file); | 1578 | struct camera_data *cam = video_drvdata(file); |
| 1583 | struct camera_data *cam = video_get_drvdata(dev); | ||
| 1584 | int retval = 0; | 1579 | int retval = 0; |
| 1585 | 1580 | ||
| 1586 | if (!cam) | 1581 | if (!cam) |
| @@ -1860,9 +1855,8 @@ static int cpia2_ioctl(struct inode *inode, struct file *file, | |||
| 1860 | *****************************************************************************/ | 1855 | *****************************************************************************/ |
| 1861 | static int cpia2_mmap(struct file *file, struct vm_area_struct *area) | 1856 | static int cpia2_mmap(struct file *file, struct vm_area_struct *area) |
| 1862 | { | 1857 | { |
| 1858 | struct camera_data *cam = video_drvdata(file); | ||
| 1863 | int retval; | 1859 | int retval; |
| 1864 | struct video_device *dev = video_devdata(file); | ||
| 1865 | struct camera_data *cam = video_get_drvdata(dev); | ||
| 1866 | 1860 | ||
| 1867 | /* Priority check */ | 1861 | /* Priority check */ |
| 1868 | struct cpia2_fh *fh = file->private_data; | 1862 | struct cpia2_fh *fh = file->private_data; |
diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile index b23d2e26120f..f7bf0edf93f9 100644 --- a/drivers/media/video/cx18/Makefile +++ b/drivers/media/video/cx18/Makefile | |||
| @@ -2,7 +2,7 @@ cx18-objs := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio. | |||
| 2 | cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \ | 2 | cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \ |
| 3 | cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \ | 3 | cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \ |
| 4 | cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \ | 4 | cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \ |
| 5 | cx18-dvb.o | 5 | cx18-dvb.o cx18-io.o |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_VIDEO_CX18) += cx18.o | 7 | obj-$(CONFIG_VIDEO_CX18) += cx18.o |
| 8 | 8 | ||
diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c index 6d5b94fc7087..57beddf0af4d 100644 --- a/drivers/media/video/cx18/cx18-audio.c +++ b/drivers/media/video/cx18/cx18-audio.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
| 25 | #include "cx18-io.h" | ||
| 25 | #include "cx18-i2c.h" | 26 | #include "cx18-i2c.h" |
| 26 | #include "cx18-cards.h" | 27 | #include "cx18-cards.h" |
| 27 | #include "cx18-audio.h" | 28 | #include "cx18-audio.h" |
| @@ -60,10 +61,10 @@ int cx18_audio_set_io(struct cx18 *cx) | |||
| 60 | if (err) | 61 | if (err) |
| 61 | return err; | 62 | return err; |
| 62 | 63 | ||
| 63 | val = read_reg(CX18_AUDIO_ENABLE) & ~0x30; | 64 | val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30; |
| 64 | val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : | 65 | val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : |
| 65 | (audio_input << 4); | 66 | (audio_input << 4); |
| 66 | write_reg(val | 0xb00, CX18_AUDIO_ENABLE); | 67 | cx18_write_reg(cx, val | 0xb00, CX18_AUDIO_ENABLE); |
| 67 | cx18_vapi(cx, CX18_APU_RESETAI, 1, 0); | 68 | cx18_vapi(cx, CX18_APU_RESETAI, 1, 0); |
| 68 | return 0; | 69 | return 0; |
| 69 | } | 70 | } |
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 3b0a2c450605..73f5141a42d1 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c | |||
| @@ -22,27 +22,35 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
| 25 | #include "cx18-io.h" | ||
| 25 | 26 | ||
| 26 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value) | 27 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value) |
| 27 | { | 28 | { |
| 28 | u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3)); | 29 | u32 reg = 0xc40000 + (addr & ~3); |
| 29 | u32 mask = 0xff; | 30 | u32 mask = 0xff; |
| 30 | int shift = (addr & 3) * 8; | 31 | int shift = (addr & 3) * 8; |
| 32 | u32 x = cx18_read_reg(cx, reg); | ||
| 31 | 33 | ||
| 32 | x = (x & ~(mask << shift)) | ((u32)value << shift); | 34 | x = (x & ~(mask << shift)) | ((u32)value << shift); |
| 33 | writel(x, cx->reg_mem + 0xc40000 + (addr & ~3)); | 35 | cx18_write_reg(cx, x, reg); |
| 34 | return 0; | 36 | return 0; |
| 35 | } | 37 | } |
| 36 | 38 | ||
| 37 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value) | 39 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value) |
| 38 | { | 40 | { |
| 39 | writel(value, cx->reg_mem + 0xc40000 + addr); | 41 | cx18_write_reg(cx, value, 0xc40000 + addr); |
| 42 | return 0; | ||
| 43 | } | ||
| 44 | |||
| 45 | int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value) | ||
| 46 | { | ||
| 47 | cx18_write_reg_noretry(cx, value, 0xc40000 + addr); | ||
| 40 | return 0; | 48 | return 0; |
| 41 | } | 49 | } |
| 42 | 50 | ||
| 43 | u8 cx18_av_read(struct cx18 *cx, u16 addr) | 51 | u8 cx18_av_read(struct cx18 *cx, u16 addr) |
| 44 | { | 52 | { |
| 45 | u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3)); | 53 | u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3)); |
| 46 | int shift = (addr & 3) * 8; | 54 | int shift = (addr & 3) * 8; |
| 47 | 55 | ||
| 48 | return (x >> shift) & 0xff; | 56 | return (x >> shift) & 0xff; |
| @@ -50,7 +58,12 @@ u8 cx18_av_read(struct cx18 *cx, u16 addr) | |||
| 50 | 58 | ||
| 51 | u32 cx18_av_read4(struct cx18 *cx, u16 addr) | 59 | u32 cx18_av_read4(struct cx18 *cx, u16 addr) |
| 52 | { | 60 | { |
| 53 | return readl(cx->reg_mem + 0xc40000 + addr); | 61 | return cx18_read_reg(cx, 0xc40000 + addr); |
| 62 | } | ||
| 63 | |||
| 64 | u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr) | ||
| 65 | { | ||
| 66 | return cx18_read_reg_noretry(cx, 0xc40000 + addr); | ||
| 54 | } | 67 | } |
| 55 | 68 | ||
| 56 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask, | 69 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask, |
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index eb61fa1e0965..b67d8df20cc6 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h | |||
| @@ -301,8 +301,10 @@ struct cx18_av_state { | |||
| 301 | /* cx18_av-core.c */ | 301 | /* cx18_av-core.c */ |
| 302 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); | 302 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); |
| 303 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); | 303 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); |
| 304 | int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value); | ||
| 304 | u8 cx18_av_read(struct cx18 *cx, u16 addr); | 305 | u8 cx18_av_read(struct cx18 *cx, u16 addr); |
| 305 | u32 cx18_av_read4(struct cx18 *cx, u16 addr); | 306 | u32 cx18_av_read4(struct cx18 *cx, u16 addr); |
| 307 | u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr); | ||
| 306 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); | 308 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); |
| 307 | int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); | 309 | int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); |
| 308 | int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); | 310 | int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); |
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index e996a4e3123a..522a035b2e8f 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include "cx18-driver.h" | 22 | #include "cx18-driver.h" |
| 23 | #include "cx18-io.h" | ||
| 23 | #include <linux/firmware.h> | 24 | #include <linux/firmware.h> |
| 24 | 25 | ||
| 25 | #define CX18_AUDIO_ENABLE 0xc72014 | 26 | #define CX18_AUDIO_ENABLE 0xc72014 |
| @@ -49,7 +50,7 @@ int cx18_av_loadfw(struct cx18 *cx) | |||
| 49 | cx18_av_write4(cx, 0x8100, 0x00010000); | 50 | cx18_av_write4(cx, 0x8100, 0x00010000); |
| 50 | 51 | ||
| 51 | /* Put the 8051 in reset and enable firmware upload */ | 52 | /* Put the 8051 in reset and enable firmware upload */ |
| 52 | cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000); | 53 | cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000); |
| 53 | 54 | ||
| 54 | ptr = fw->data; | 55 | ptr = fw->data; |
| 55 | size = fw->size; | 56 | size = fw->size; |
| @@ -58,22 +59,28 @@ int cx18_av_loadfw(struct cx18 *cx) | |||
| 58 | u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16); | 59 | u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16); |
| 59 | u32 value = 0; | 60 | u32 value = 0; |
| 60 | int retries2; | 61 | int retries2; |
| 62 | int unrec_err = 0; | ||
| 61 | 63 | ||
| 62 | for (retries2 = 0; retries2 < 5; retries2++) { | 64 | for (retries2 = 0; retries2 < CX18_MAX_MMIO_RETRIES; |
| 63 | cx18_av_write4(cx, CXADEC_DL_CTL, dl_control); | 65 | retries2++) { |
| 66 | cx18_av_write4_noretry(cx, CXADEC_DL_CTL, | ||
| 67 | dl_control); | ||
| 64 | udelay(10); | 68 | udelay(10); |
| 65 | value = cx18_av_read4(cx, CXADEC_DL_CTL); | 69 | value = cx18_av_read4_noretry(cx, |
| 70 | CXADEC_DL_CTL); | ||
| 66 | if (value == dl_control) | 71 | if (value == dl_control) |
| 67 | break; | 72 | break; |
| 68 | /* Check if we can correct the byte by changing | 73 | /* Check if we can correct the byte by changing |
| 69 | the address. We can only write the lower | 74 | the address. We can only write the lower |
| 70 | address byte of the address. */ | 75 | address byte of the address. */ |
| 71 | if ((value & 0x3F00) != (dl_control & 0x3F00)) { | 76 | if ((value & 0x3F00) != (dl_control & 0x3F00)) { |
| 72 | retries2 = 5; | 77 | unrec_err = 1; |
| 73 | break; | 78 | break; |
| 74 | } | 79 | } |
| 75 | } | 80 | } |
| 76 | if (retries2 >= 5) | 81 | cx18_log_write_retries(cx, retries2, |
| 82 | cx->reg_mem + 0xc40000 + CXADEC_DL_CTL); | ||
| 83 | if (unrec_err || retries2 >= CX18_MAX_MMIO_RETRIES) | ||
| 77 | break; | 84 | break; |
| 78 | } | 85 | } |
| 79 | if (i == size) | 86 | if (i == size) |
| @@ -119,10 +126,10 @@ int cx18_av_loadfw(struct cx18 *cx) | |||
| 119 | have a name in the spec. */ | 126 | have a name in the spec. */ |
| 120 | cx18_av_write4(cx, 0x09CC, 1); | 127 | cx18_av_write4(cx, 0x09CC, 1); |
| 121 | 128 | ||
| 122 | v = read_reg(CX18_AUDIO_ENABLE); | 129 | v = cx18_read_reg(cx, CX18_AUDIO_ENABLE); |
| 123 | /* If bit 11 is 1 */ | 130 | /* If bit 11 is 1, clear bit 10 */ |
| 124 | if (v & 0x800) | 131 | if (v & 0x800) |
| 125 | write_reg(v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); /* Clear bit 10 */ | 132 | cx18_write_reg(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); |
| 126 | 133 | ||
| 127 | /* Enable WW auto audio standard detection */ | 134 | /* Enable WW auto audio standard detection */ |
| 128 | v = cx18_av_read4(cx, CXADEC_STD_DET_CTL); | 135 | v = cx18_av_read4(cx, CXADEC_STD_DET_CTL); |
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 3cb9734ec07b..5efe01ebe9db 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
| @@ -292,12 +292,111 @@ static const struct cx18_card cx18_card_cnxt_raptor_pal = { | |||
| 292 | 292 | ||
| 293 | /* ------------------------------------------------------------------------- */ | 293 | /* ------------------------------------------------------------------------- */ |
| 294 | 294 | ||
| 295 | /* Toshiba Qosmio laptop internal DVB-T/Analog Hybrid Tuner */ | ||
| 296 | |||
| 297 | static const struct cx18_card_pci_info cx18_pci_toshiba_qosmio_dvbt[] = { | ||
| 298 | { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_TOSHIBA, 0x0110 }, | ||
| 299 | { 0, 0, 0 } | ||
| 300 | }; | ||
| 301 | |||
| 302 | static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = { | ||
| 303 | .type = CX18_CARD_TOSHIBA_QOSMIO_DVBT, | ||
| 304 | .name = "Toshiba Qosmio DVB-T/Analog", | ||
| 305 | .comment = "Experimenters and photos needed for device to work well.\n" | ||
| 306 | "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", | ||
| 307 | .v4l2_capabilities = CX18_CAP_ENCODER, | ||
| 308 | .hw_audio_ctrl = CX18_HW_CX23418, | ||
| 309 | .hw_all = CX18_HW_TUNER, | ||
| 310 | .video_inputs = { | ||
| 311 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE6 }, | ||
| 312 | { CX18_CARD_INPUT_SVIDEO1, 1, | ||
| 313 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, | ||
| 314 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 }, | ||
| 315 | }, | ||
| 316 | .audio_inputs = { | ||
| 317 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, | ||
| 318 | { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, | ||
| 319 | }, | ||
| 320 | .tuners = { | ||
| 321 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | ||
| 322 | }, | ||
| 323 | .ddr = { | ||
| 324 | .chip_config = 0x202, | ||
| 325 | .refresh = 0x3bb, | ||
| 326 | .timing1 = 0x33320a63, | ||
| 327 | .timing2 = 0x0a, | ||
| 328 | .tune_lane = 0, | ||
| 329 | .initial_emrs = 0x42, | ||
| 330 | }, | ||
| 331 | .xceive_pin = 15, | ||
| 332 | .pci_list = cx18_pci_toshiba_qosmio_dvbt, | ||
| 333 | .i2c = &cx18_i2c_std, | ||
| 334 | }; | ||
| 335 | |||
| 336 | /* ------------------------------------------------------------------------- */ | ||
| 337 | |||
| 338 | /* Leadtek WinFast PVR2100 */ | ||
| 339 | |||
| 340 | static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = { | ||
| 341 | { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, | ||
| 342 | { 0, 0, 0 } | ||
| 343 | }; | ||
| 344 | |||
| 345 | static const struct cx18_card cx18_card_leadtek_pvr2100 = { | ||
| 346 | .type = CX18_CARD_LEADTEK_PVR2100, | ||
| 347 | .name = "Leadtek WinFast PVR2100", | ||
| 348 | .comment = "Experimenters and photos needed for device to work well.\n" | ||
| 349 | "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", | ||
| 350 | .v4l2_capabilities = CX18_CAP_ENCODER, | ||
| 351 | .hw_audio_ctrl = CX18_HW_CX23418, | ||
| 352 | .hw_muxer = CX18_HW_GPIO, | ||
| 353 | .hw_all = CX18_HW_TUNER | CX18_HW_GPIO, | ||
| 354 | .video_inputs = { | ||
| 355 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, | ||
| 356 | { CX18_CARD_INPUT_SVIDEO1, 1, | ||
| 357 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, | ||
| 358 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 }, | ||
| 359 | }, | ||
| 360 | .audio_inputs = { | ||
| 361 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, | ||
| 362 | { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 }, | ||
| 363 | }, | ||
| 364 | .tuners = { | ||
| 365 | /* XC3028 tuner */ | ||
| 366 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | ||
| 367 | }, | ||
| 368 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 }, | ||
| 369 | .ddr = { | ||
| 370 | /* | ||
| 371 | * Pointer to proper DDR config values provided by | ||
| 372 | * Terry Wu <terrywu at leadtek.com.tw> | ||
| 373 | */ | ||
| 374 | .chip_config = 0x303, | ||
| 375 | .refresh = 0x3bb, | ||
| 376 | .timing1 = 0x24220e83, | ||
| 377 | .timing2 = 0x1f, | ||
| 378 | .tune_lane = 0, | ||
| 379 | .initial_emrs = 0x2, | ||
| 380 | }, | ||
| 381 | .gpio_init.initial_value = 0x6, | ||
| 382 | .gpio_init.direction = 0x7, | ||
| 383 | .gpio_audio_input = { .mask = 0x7, | ||
| 384 | .tuner = 0x6, .linein = 0x2, .radio = 0x2 }, | ||
| 385 | .xceive_pin = 15, | ||
| 386 | .pci_list = cx18_pci_leadtek_pvr2100, | ||
| 387 | .i2c = &cx18_i2c_std, | ||
| 388 | }; | ||
| 389 | |||
| 390 | /* ------------------------------------------------------------------------- */ | ||
| 391 | |||
| 295 | static const struct cx18_card *cx18_card_list[] = { | 392 | static const struct cx18_card *cx18_card_list[] = { |
| 296 | &cx18_card_hvr1600_esmt, | 393 | &cx18_card_hvr1600_esmt, |
| 297 | &cx18_card_hvr1600_samsung, | 394 | &cx18_card_hvr1600_samsung, |
| 298 | &cx18_card_h900, | 395 | &cx18_card_h900, |
| 299 | &cx18_card_mpc718, | 396 | &cx18_card_mpc718, |
| 300 | &cx18_card_cnxt_raptor_pal, | 397 | &cx18_card_cnxt_raptor_pal, |
| 398 | &cx18_card_toshiba_qosmio_dvbt, | ||
| 399 | &cx18_card_leadtek_pvr2100, | ||
| 301 | }; | 400 | }; |
| 302 | 401 | ||
| 303 | const struct cx18_card *cx18_get_card(u16 index) | 402 | const struct cx18_card *cx18_get_card(u16 index) |
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index bd18afebbf86..085121c2b47f 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | * Derived from ivtv-driver.c | 4 | * Derived from ivtv-driver.c |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> | 6 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> |
| 7 | * Copyright (C) 2008 Andy Walls <awalls@radix.net> | ||
| 7 | * | 8 | * |
| 8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
| @@ -22,6 +23,7 @@ | |||
| 22 | */ | 23 | */ |
| 23 | 24 | ||
| 24 | #include "cx18-driver.h" | 25 | #include "cx18-driver.h" |
| 26 | #include "cx18-io.h" | ||
| 25 | #include "cx18-version.h" | 27 | #include "cx18-version.h" |
| 26 | #include "cx18-cards.h" | 28 | #include "cx18-cards.h" |
| 27 | #include "cx18-i2c.h" | 29 | #include "cx18-i2c.h" |
| @@ -73,10 +75,14 @@ static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | |||
| 73 | -1, -1, -1, -1, -1, -1, -1, -1, | 75 | -1, -1, -1, -1, -1, -1, -1, -1, |
| 74 | -1, -1, -1, -1, -1, -1, -1, -1, | 76 | -1, -1, -1, -1, -1, -1, -1, -1, |
| 75 | -1, -1, -1, -1, -1, -1, -1, -1 }; | 77 | -1, -1, -1, -1, -1, -1, -1, -1 }; |
| 76 | 78 | static int mmio_ndelay[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | |
| 79 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 80 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
| 81 | -1, -1, -1, -1, -1, -1, -1, -1 }; | ||
| 77 | static unsigned cardtype_c = 1; | 82 | static unsigned cardtype_c = 1; |
| 78 | static unsigned tuner_c = 1; | 83 | static unsigned tuner_c = 1; |
| 79 | static unsigned radio_c = 1; | 84 | static unsigned radio_c = 1; |
| 85 | static unsigned mmio_ndelay_c = 1; | ||
| 80 | static char pal[] = "--"; | 86 | static char pal[] = "--"; |
| 81 | static char secam[] = "--"; | 87 | static char secam[] = "--"; |
| 82 | static char ntsc[] = "-"; | 88 | static char ntsc[] = "-"; |
| @@ -90,15 +96,18 @@ static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS; | |||
| 90 | 96 | ||
| 91 | static int cx18_pci_latency = 1; | 97 | static int cx18_pci_latency = 1; |
| 92 | 98 | ||
| 99 | int cx18_retry_mmio = 1; | ||
| 93 | int cx18_debug; | 100 | int cx18_debug; |
| 94 | 101 | ||
| 95 | module_param_array(tuner, int, &tuner_c, 0644); | 102 | module_param_array(tuner, int, &tuner_c, 0644); |
| 96 | module_param_array(radio, bool, &radio_c, 0644); | 103 | module_param_array(radio, bool, &radio_c, 0644); |
| 97 | module_param_array(cardtype, int, &cardtype_c, 0644); | 104 | module_param_array(cardtype, int, &cardtype_c, 0644); |
| 105 | module_param_array(mmio_ndelay, int, &mmio_ndelay_c, 0644); | ||
| 98 | module_param_string(pal, pal, sizeof(pal), 0644); | 106 | module_param_string(pal, pal, sizeof(pal), 0644); |
| 99 | module_param_string(secam, secam, sizeof(secam), 0644); | 107 | module_param_string(secam, secam, sizeof(secam), 0644); |
| 100 | module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); | 108 | module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); |
| 101 | module_param_named(debug, cx18_debug, int, 0644); | 109 | module_param_named(debug, cx18_debug, int, 0644); |
| 110 | module_param_named(retry_mmio, cx18_retry_mmio, int, 0644); | ||
| 102 | module_param(cx18_pci_latency, int, 0644); | 111 | module_param(cx18_pci_latency, int, 0644); |
| 103 | module_param(cx18_first_minor, int, 0644); | 112 | module_param(cx18_first_minor, int, 0644); |
| 104 | 113 | ||
| @@ -121,6 +130,8 @@ MODULE_PARM_DESC(cardtype, | |||
| 121 | "\t\t\t 3 = Compro VideoMate H900\n" | 130 | "\t\t\t 3 = Compro VideoMate H900\n" |
| 122 | "\t\t\t 4 = Yuan MPC718\n" | 131 | "\t\t\t 4 = Yuan MPC718\n" |
| 123 | "\t\t\t 5 = Conexant Raptor PAL/SECAM\n" | 132 | "\t\t\t 5 = Conexant Raptor PAL/SECAM\n" |
| 133 | "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n" | ||
| 134 | "\t\t\t 7 = Leadtek WinFast PVR2100\n" | ||
| 124 | "\t\t\t 0 = Autodetect (default)\n" | 135 | "\t\t\t 0 = Autodetect (default)\n" |
| 125 | "\t\t\t-1 = Ignore this card\n\t\t"); | 136 | "\t\t\t-1 = Ignore this card\n\t\t"); |
| 126 | MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); | 137 | MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); |
| @@ -140,6 +151,14 @@ MODULE_PARM_DESC(debug, | |||
| 140 | MODULE_PARM_DESC(cx18_pci_latency, | 151 | MODULE_PARM_DESC(cx18_pci_latency, |
| 141 | "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" | 152 | "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" |
| 142 | "\t\t\tDefault: Yes"); | 153 | "\t\t\tDefault: Yes"); |
| 154 | MODULE_PARM_DESC(retry_mmio, | ||
| 155 | "Check and retry memory mapped IO accesses\n" | ||
| 156 | "\t\t\tDefault: 1 [Yes]"); | ||
| 157 | MODULE_PARM_DESC(mmio_ndelay, | ||
| 158 | "Delay (ns) for each CX23418 memory mapped IO access.\n" | ||
| 159 | "\t\t\tTry larger values that are close to a multiple of the\n" | ||
| 160 | "\t\t\tPCI clock period, 30.3 ns, if your card doesn't work.\n" | ||
| 161 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_MMIO_NDELAY)); | ||
| 143 | MODULE_PARM_DESC(enc_mpg_buffers, | 162 | MODULE_PARM_DESC(enc_mpg_buffers, |
| 144 | "Encoder MPG Buffers (in MB)\n" | 163 | "Encoder MPG Buffers (in MB)\n" |
| 145 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS)); | 164 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS)); |
| @@ -156,7 +175,7 @@ MODULE_PARM_DESC(enc_pcm_buffers, | |||
| 156 | "Encoder PCM buffers (in MB)\n" | 175 | "Encoder PCM buffers (in MB)\n" |
| 157 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); | 176 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS)); |
| 158 | 177 | ||
| 159 | MODULE_PARM_DESC(cx18_first_minor, "Set minor assigned to first card"); | 178 | MODULE_PARM_DESC(cx18_first_minor, "Set kernel number assigned to first card"); |
| 160 | 179 | ||
| 161 | MODULE_AUTHOR("Hans Verkuil"); | 180 | MODULE_AUTHOR("Hans Verkuil"); |
| 162 | MODULE_DESCRIPTION("CX23418 driver"); | 181 | MODULE_DESCRIPTION("CX23418 driver"); |
| @@ -356,6 +375,11 @@ static void cx18_process_options(struct cx18 *cx) | |||
| 356 | cx->options.tuner = tuner[cx->num]; | 375 | cx->options.tuner = tuner[cx->num]; |
| 357 | cx->options.radio = radio[cx->num]; | 376 | cx->options.radio = radio[cx->num]; |
| 358 | 377 | ||
| 378 | if (mmio_ndelay[cx->num] < 0) | ||
| 379 | cx->options.mmio_ndelay = CX18_DEFAULT_MMIO_NDELAY; | ||
| 380 | else | ||
| 381 | cx->options.mmio_ndelay = mmio_ndelay[cx->num]; | ||
| 382 | |||
| 359 | cx->std = cx18_parse_std(cx); | 383 | cx->std = cx18_parse_std(cx); |
| 360 | if (cx->options.cardtype == -1) { | 384 | if (cx->options.cardtype == -1) { |
| 361 | CX18_INFO("Ignore card\n"); | 385 | CX18_INFO("Ignore card\n"); |
| @@ -395,9 +419,9 @@ done: | |||
| 395 | 419 | ||
| 396 | if (cx->card == NULL) { | 420 | if (cx->card == NULL) { |
| 397 | cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); | 421 | cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); |
| 398 | CX18_ERR("Unknown card: vendor/device: %04x/%04x\n", | 422 | CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n", |
| 399 | cx->dev->vendor, cx->dev->device); | 423 | cx->dev->vendor, cx->dev->device); |
| 400 | CX18_ERR(" subsystem vendor/device: %04x/%04x\n", | 424 | CX18_ERR(" subsystem vendor/device: [%04x:%04x]\n", |
| 401 | cx->dev->subsystem_vendor, cx->dev->subsystem_device); | 425 | cx->dev->subsystem_vendor, cx->dev->subsystem_device); |
| 402 | CX18_ERR("Defaulting to %s card\n", cx->card->name); | 426 | CX18_ERR("Defaulting to %s card\n", cx->card->name); |
| 403 | CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); | 427 | CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); |
| @@ -511,9 +535,9 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, | |||
| 511 | return -EIO; | 535 | return -EIO; |
| 512 | } | 536 | } |
| 513 | 537 | ||
| 514 | /* Check for bus mastering */ | 538 | /* Enable bus mastering and memory mapped IO for the CX23418 */ |
| 515 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | 539 | pci_read_config_word(dev, PCI_COMMAND, &cmd); |
| 516 | cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; | 540 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; |
| 517 | pci_write_config_word(dev, PCI_COMMAND, cmd); | 541 | pci_write_config_word(dev, PCI_COMMAND, cmd); |
| 518 | 542 | ||
| 519 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev); | 543 | pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev); |
| @@ -525,11 +549,6 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, | |||
| 525 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); | 549 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); |
| 526 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); | 550 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); |
| 527 | } | 551 | } |
| 528 | /* This config space value relates to DMA latencies. The | ||
| 529 | default value 0x8080 is too low however and will lead | ||
| 530 | to DMA errors. 0xffff is the max value which solves | ||
| 531 | these problems. */ | ||
| 532 | pci_write_config_dword(dev, 0x40, 0xffff); | ||
| 533 | 552 | ||
| 534 | CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, " | 553 | CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, " |
| 535 | "irq: %d, latency: %d, memory: 0x%lx\n", | 554 | "irq: %d, latency: %d, memory: 0x%lx\n", |
| @@ -656,7 +675,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, | |||
| 656 | goto free_mem; | 675 | goto free_mem; |
| 657 | } | 676 | } |
| 658 | cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET; | 677 | cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET; |
| 659 | devtype = read_reg(0xC72028); | 678 | devtype = cx18_read_reg(cx, 0xC72028); |
| 660 | switch (devtype & 0xff000000) { | 679 | switch (devtype & 0xff000000) { |
| 661 | case 0xff000000: | 680 | case 0xff000000: |
| 662 | CX18_INFO("cx23418 revision %08x (A)\n", devtype); | 681 | CX18_INFO("cx23418 revision %08x (A)\n", devtype); |
| @@ -815,6 +834,7 @@ err: | |||
| 815 | if (retval == 0) | 834 | if (retval == 0) |
| 816 | retval = -ENODEV; | 835 | retval = -ENODEV; |
| 817 | CX18_ERR("Error %d on initialization\n", retval); | 836 | CX18_ERR("Error %d on initialization\n", retval); |
| 837 | cx18_log_statistics(cx); | ||
| 818 | 838 | ||
| 819 | kfree(cx18_cards[cx18_cards_active]); | 839 | kfree(cx18_cards[cx18_cards_active]); |
| 820 | cx18_cards[cx18_cards_active] = NULL; | 840 | cx18_cards[cx18_cards_active] = NULL; |
| @@ -902,8 +922,8 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
| 902 | cx18_stop_all_captures(cx); | 922 | cx18_stop_all_captures(cx); |
| 903 | 923 | ||
| 904 | /* Interrupts */ | 924 | /* Interrupts */ |
| 905 | sw1_irq_disable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); | 925 | cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); |
| 906 | sw2_irq_disable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); | 926 | cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); |
| 907 | 927 | ||
| 908 | cx18_halt_firmware(cx); | 928 | cx18_halt_firmware(cx); |
| 909 | 929 | ||
| @@ -919,6 +939,7 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
| 919 | 939 | ||
| 920 | pci_disable_device(cx->dev); | 940 | pci_disable_device(cx->dev); |
| 921 | 941 | ||
| 942 | cx18_log_statistics(cx); | ||
| 922 | CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num); | 943 | CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num); |
| 923 | } | 944 | } |
| 924 | 945 | ||
| @@ -938,7 +959,7 @@ static int module_start(void) | |||
| 938 | 959 | ||
| 939 | /* Validate parameters */ | 960 | /* Validate parameters */ |
| 940 | if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { | 961 | if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { |
| 941 | printk(KERN_ERR "cx18: Exiting, ivtv_first_minor must be between 0 and %d\n", | 962 | printk(KERN_ERR "cx18: Exiting, cx18_first_minor must be between 0 and %d\n", |
| 942 | CX18_MAX_CARDS - 1); | 963 | CX18_MAX_CARDS - 1); |
| 943 | return -1; | 964 | return -1; |
| 944 | } | 965 | } |
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 4801bc7fb5b2..fa8be0731a3f 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
| @@ -38,7 +38,6 @@ | |||
| 38 | #include <linux/i2c-algo-bit.h> | 38 | #include <linux/i2c-algo-bit.h> |
| 39 | #include <linux/list.h> | 39 | #include <linux/list.h> |
| 40 | #include <linux/unistd.h> | 40 | #include <linux/unistd.h> |
| 41 | #include <linux/byteorder/swab.h> | ||
| 42 | #include <linux/pagemap.h> | 41 | #include <linux/pagemap.h> |
| 43 | #include <linux/workqueue.h> | 42 | #include <linux/workqueue.h> |
| 44 | #include <linux/mutex.h> | 43 | #include <linux/mutex.h> |
| @@ -64,6 +63,9 @@ | |||
| 64 | # error "This driver requires kernel PCI support." | 63 | # error "This driver requires kernel PCI support." |
| 65 | #endif | 64 | #endif |
| 66 | 65 | ||
| 66 | /* Default delay to throttle mmio access to the CX23418 */ | ||
| 67 | #define CX18_DEFAULT_MMIO_NDELAY 0 /* 0 ns = 0 PCI clock(s) / 33 MHz */ | ||
| 68 | |||
| 67 | #define CX18_MEM_OFFSET 0x00000000 | 69 | #define CX18_MEM_OFFSET 0x00000000 |
| 68 | #define CX18_MEM_SIZE 0x04000000 | 70 | #define CX18_MEM_SIZE 0x04000000 |
| 69 | #define CX18_REG_OFFSET 0x02000000 | 71 | #define CX18_REG_OFFSET 0x02000000 |
| @@ -77,7 +79,9 @@ | |||
| 77 | #define CX18_CARD_COMPRO_H900 2 /* Compro VideoMate H900 */ | 79 | #define CX18_CARD_COMPRO_H900 2 /* Compro VideoMate H900 */ |
| 78 | #define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */ | 80 | #define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */ |
| 79 | #define CX18_CARD_CNXT_RAPTOR_PAL 4 /* Conexant Raptor PAL */ | 81 | #define CX18_CARD_CNXT_RAPTOR_PAL 4 /* Conexant Raptor PAL */ |
| 80 | #define CX18_CARD_LAST 4 | 82 | #define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/ |
| 83 | #define CX18_CARD_LEADTEK_PVR2100 6 /* Leadtek WinFast PVR2100 */ | ||
| 84 | #define CX18_CARD_LAST 6 | ||
| 81 | 85 | ||
| 82 | #define CX18_ENC_STREAM_TYPE_MPG 0 | 86 | #define CX18_ENC_STREAM_TYPE_MPG 0 |
| 83 | #define CX18_ENC_STREAM_TYPE_TS 1 | 87 | #define CX18_ENC_STREAM_TYPE_TS 1 |
| @@ -97,6 +101,8 @@ | |||
| 97 | #define CX18_PCI_ID_COMPRO 0x185b | 101 | #define CX18_PCI_ID_COMPRO 0x185b |
| 98 | #define CX18_PCI_ID_YUAN 0x12ab | 102 | #define CX18_PCI_ID_YUAN 0x12ab |
| 99 | #define CX18_PCI_ID_CONEXANT 0x14f1 | 103 | #define CX18_PCI_ID_CONEXANT 0x14f1 |
| 104 | #define CX18_PCI_ID_TOSHIBA 0x1179 | ||
| 105 | #define CX18_PCI_ID_LEADTEK 0x107D | ||
| 100 | 106 | ||
| 101 | /* ======================================================================== */ | 107 | /* ======================================================================== */ |
| 102 | /* ========================== START USER SETTABLE DMA VARIABLES =========== */ | 108 | /* ========================== START USER SETTABLE DMA VARIABLES =========== */ |
| @@ -169,6 +175,7 @@ | |||
| 169 | 175 | ||
| 170 | #define CX18_MAX_PGM_INDEX (400) | 176 | #define CX18_MAX_PGM_INDEX (400) |
| 171 | 177 | ||
| 178 | extern int cx18_retry_mmio; /* enable check & retry of mmio accesses */ | ||
| 172 | extern int cx18_debug; | 179 | extern int cx18_debug; |
| 173 | 180 | ||
| 174 | 181 | ||
| @@ -177,6 +184,7 @@ struct cx18_options { | |||
| 177 | int cardtype; /* force card type on load */ | 184 | int cardtype; /* force card type on load */ |
| 178 | int tuner; /* set tuner on load */ | 185 | int tuner; /* set tuner on load */ |
| 179 | int radio; /* enable/disable radio */ | 186 | int radio; /* enable/disable radio */ |
| 187 | unsigned long mmio_ndelay; /* delay in ns after every PCI mmio access */ | ||
| 180 | }; | 188 | }; |
| 181 | 189 | ||
| 182 | /* per-buffer bit flags */ | 190 | /* per-buffer bit flags */ |
| @@ -216,8 +224,7 @@ struct cx18_buffer { | |||
| 216 | 224 | ||
| 217 | struct cx18_queue { | 225 | struct cx18_queue { |
| 218 | struct list_head list; | 226 | struct list_head list; |
| 219 | u32 buffers; | 227 | atomic_t buffers; |
| 220 | u32 length; | ||
| 221 | u32 bytesused; | 228 | u32 bytesused; |
| 222 | }; | 229 | }; |
| 223 | 230 | ||
| @@ -237,6 +244,8 @@ struct cx18_dvb { | |||
| 237 | struct cx18; /* forward reference */ | 244 | struct cx18; /* forward reference */ |
| 238 | struct cx18_scb; /* forward reference */ | 245 | struct cx18_scb; /* forward reference */ |
| 239 | 246 | ||
| 247 | #define CX18_INVALID_TASK_HANDLE 0xffffffff | ||
| 248 | |||
| 240 | struct cx18_stream { | 249 | struct cx18_stream { |
| 241 | /* These first four fields are always set, even if the stream | 250 | /* These first four fields are always set, even if the stream |
| 242 | is not actually created. */ | 251 | is not actually created. */ |
| @@ -259,7 +268,6 @@ struct cx18_stream { | |||
| 259 | /* Buffer Stats */ | 268 | /* Buffer Stats */ |
| 260 | u32 buffers; | 269 | u32 buffers; |
| 261 | u32 buf_size; | 270 | u32 buf_size; |
| 262 | u32 buffers_stolen; | ||
| 263 | 271 | ||
| 264 | /* Buffer Queues */ | 272 | /* Buffer Queues */ |
| 265 | struct cx18_queue q_free; /* free buffers */ | 273 | struct cx18_queue q_free; /* free buffers */ |
| @@ -341,6 +349,13 @@ struct cx18_i2c_algo_callback_data { | |||
| 341 | int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */ | 349 | int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */ |
| 342 | }; | 350 | }; |
| 343 | 351 | ||
| 352 | #define CX18_MAX_MMIO_RETRIES 10 | ||
| 353 | |||
| 354 | struct cx18_mmio_stats { | ||
| 355 | atomic_t retried_write[CX18_MAX_MMIO_RETRIES+1]; | ||
| 356 | atomic_t retried_read[CX18_MAX_MMIO_RETRIES+1]; | ||
| 357 | }; | ||
| 358 | |||
| 344 | /* Struct to hold info about cx18 cards */ | 359 | /* Struct to hold info about cx18 cards */ |
| 345 | struct cx18 { | 360 | struct cx18 { |
| 346 | int num; /* board number, -1 during init! */ | 361 | int num; /* board number, -1 during init! */ |
| @@ -430,6 +445,9 @@ struct cx18 { | |||
| 430 | u32 gpio_val; | 445 | u32 gpio_val; |
| 431 | struct mutex gpio_lock; | 446 | struct mutex gpio_lock; |
| 432 | 447 | ||
| 448 | /* Statistics */ | ||
| 449 | struct cx18_mmio_stats mmio_stats; | ||
| 450 | |||
| 433 | /* v4l2 and User settings */ | 451 | /* v4l2 and User settings */ |
| 434 | 452 | ||
| 435 | /* codec settings */ | 453 | /* codec settings */ |
| @@ -458,47 +476,4 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv); | |||
| 458 | /* First-open initialization: load firmware, etc. */ | 476 | /* First-open initialization: load firmware, etc. */ |
| 459 | int cx18_init_on_first_open(struct cx18 *cx); | 477 | int cx18_init_on_first_open(struct cx18 *cx); |
| 460 | 478 | ||
| 461 | /* This is a PCI post thing, where if the pci register is not read, then | ||
| 462 | the write doesn't always take effect right away. By reading back the | ||
| 463 | register any pending PCI writes will be performed (in order), and so | ||
| 464 | you can be sure that the writes are guaranteed to be done. | ||
| 465 | |||
| 466 | Rarely needed, only in some timing sensitive cases. | ||
| 467 | Apparently if this is not done some motherboards seem | ||
| 468 | to kill the firmware and get into the broken state until computer is | ||
| 469 | rebooted. */ | ||
| 470 | #define write_sync(val, reg) \ | ||
| 471 | do { writel(val, reg); readl(reg); } while (0) | ||
| 472 | |||
| 473 | #define read_reg(reg) readl(cx->reg_mem + (reg)) | ||
| 474 | #define write_reg(val, reg) writel(val, cx->reg_mem + (reg)) | ||
| 475 | #define write_reg_sync(val, reg) \ | ||
| 476 | do { write_reg(val, reg); read_reg(reg); } while (0) | ||
| 477 | |||
| 478 | #define read_enc(addr) readl(cx->enc_mem + (u32)(addr)) | ||
| 479 | #define write_enc(val, addr) writel(val, cx->enc_mem + (u32)(addr)) | ||
| 480 | #define write_enc_sync(val, addr) \ | ||
| 481 | do { write_enc(val, addr); read_enc(addr); } while (0) | ||
| 482 | |||
| 483 | #define sw1_irq_enable(val) do { \ | ||
| 484 | write_reg(val, SW1_INT_STATUS); \ | ||
| 485 | write_reg(read_reg(SW1_INT_ENABLE_PCI) | (val), SW1_INT_ENABLE_PCI); \ | ||
| 486 | } while (0) | ||
| 487 | |||
| 488 | #define sw1_irq_disable(val) \ | ||
| 489 | write_reg(read_reg(SW1_INT_ENABLE_PCI) & ~(val), SW1_INT_ENABLE_PCI); | ||
| 490 | |||
| 491 | #define sw2_irq_enable(val) do { \ | ||
| 492 | write_reg(val, SW2_INT_STATUS); \ | ||
| 493 | write_reg(read_reg(SW2_INT_ENABLE_PCI) | (val), SW2_INT_ENABLE_PCI); \ | ||
| 494 | } while (0) | ||
| 495 | |||
| 496 | #define sw2_irq_disable(val) \ | ||
| 497 | write_reg(read_reg(SW2_INT_ENABLE_PCI) & ~(val), SW2_INT_ENABLE_PCI); | ||
| 498 | |||
| 499 | #define setup_page(addr) do { \ | ||
| 500 | u32 val = read_reg(0xD000F8) & ~0x1f00; \ | ||
| 501 | write_reg(val | (((addr) >> 17) & 0x1f00), 0xD000F8); \ | ||
| 502 | } while (0) | ||
| 503 | |||
| 504 | #endif /* CX18_DRIVER_H */ | 479 | #endif /* CX18_DRIVER_H */ |
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 1e420a804fc9..afc694e7bdb2 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | #include "cx18-version.h" | 22 | #include "cx18-version.h" |
| 23 | #include "cx18-dvb.h" | 23 | #include "cx18-dvb.h" |
| 24 | #include "cx18-io.h" | ||
| 24 | #include "cx18-streams.h" | 25 | #include "cx18-streams.h" |
| 25 | #include "cx18-cards.h" | 26 | #include "cx18-cards.h" |
| 26 | #include "s5h1409.h" | 27 | #include "s5h1409.h" |
| @@ -87,13 +88,13 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
| 87 | switch (cx->card->type) { | 88 | switch (cx->card->type) { |
| 88 | case CX18_CARD_HVR_1600_ESMT: | 89 | case CX18_CARD_HVR_1600_ESMT: |
| 89 | case CX18_CARD_HVR_1600_SAMSUNG: | 90 | case CX18_CARD_HVR_1600_SAMSUNG: |
| 90 | v = read_reg(CX18_REG_DMUX_NUM_PORT_0_CONTROL); | 91 | v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL); |
| 91 | v |= 0x00400000; /* Serial Mode */ | 92 | v |= 0x00400000; /* Serial Mode */ |
| 92 | v |= 0x00002000; /* Data Length - Byte */ | 93 | v |= 0x00002000; /* Data Length - Byte */ |
| 93 | v |= 0x00010000; /* Error - Polarity */ | 94 | v |= 0x00010000; /* Error - Polarity */ |
| 94 | v |= 0x00020000; /* Error - Passthru */ | 95 | v |= 0x00020000; /* Error - Passthru */ |
| 95 | v |= 0x000c0000; /* Error - Ignore */ | 96 | v |= 0x000c0000; /* Error - Ignore */ |
| 96 | write_reg(v, CX18_REG_DMUX_NUM_PORT_0_CONTROL); | 97 | cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL); |
| 97 | break; | 98 | break; |
| 98 | 99 | ||
| 99 | default: | 100 | default: |
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 1e537fe04a23..5f9089907544 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
| @@ -132,6 +132,7 @@ static void cx18_dualwatch(struct cx18 *cx) | |||
| 132 | u16 new_stereo_mode; | 132 | u16 new_stereo_mode; |
| 133 | const u16 stereo_mask = 0x0300; | 133 | const u16 stereo_mask = 0x0300; |
| 134 | const u16 dual = 0x0200; | 134 | const u16 dual = 0x0200; |
| 135 | u32 h; | ||
| 135 | 136 | ||
| 136 | new_stereo_mode = cx->params.audio_properties & stereo_mask; | 137 | new_stereo_mode = cx->params.audio_properties & stereo_mask; |
| 137 | memset(&vt, 0, sizeof(vt)); | 138 | memset(&vt, 0, sizeof(vt)); |
| @@ -143,13 +144,21 @@ static void cx18_dualwatch(struct cx18 *cx) | |||
| 143 | if (new_stereo_mode == cx->dualwatch_stereo_mode) | 144 | if (new_stereo_mode == cx->dualwatch_stereo_mode) |
| 144 | return; | 145 | return; |
| 145 | 146 | ||
| 146 | new_bitmap = new_stereo_mode | (cx->params.audio_properties & ~stereo_mask); | 147 | new_bitmap = new_stereo_mode |
| 148 | | (cx->params.audio_properties & ~stereo_mask); | ||
| 147 | 149 | ||
| 148 | CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n", | 150 | CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. " |
| 149 | cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap); | 151 | "new audio_bitmask=0x%ux\n", |
| 152 | cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap); | ||
| 150 | 153 | ||
| 151 | if (cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2, | 154 | h = cx18_find_handle(cx); |
| 152 | cx18_find_handle(cx), new_bitmap) == 0) { | 155 | if (h == CX18_INVALID_TASK_HANDLE) { |
| 156 | CX18_DEBUG_INFO("dualwatch: can't find valid task handle\n"); | ||
| 157 | return; | ||
| 158 | } | ||
| 159 | |||
| 160 | if (cx18_vapi(cx, | ||
| 161 | CX18_CPU_SET_AUDIO_PARAMETERS, 2, h, new_bitmap) == 0) { | ||
| 153 | cx->dualwatch_stereo_mode = new_stereo_mode; | 162 | cx->dualwatch_stereo_mode = new_stereo_mode; |
| 154 | return; | 163 | return; |
| 155 | } | 164 | } |
| @@ -223,7 +232,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, | |||
| 223 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | 232 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
| 224 | /* New buffers might have become available before we were added | 233 | /* New buffers might have become available before we were added |
| 225 | to the waitqueue */ | 234 | to the waitqueue */ |
| 226 | if (!s->q_full.buffers) | 235 | if (!atomic_read(&s->q_full.buffers)) |
| 227 | schedule(); | 236 | schedule(); |
| 228 | finish_wait(&s->waitq, &wait); | 237 | finish_wait(&s->waitq, &wait); |
| 229 | if (signal_pending(current)) { | 238 | if (signal_pending(current)) { |
| @@ -509,7 +518,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait) | |||
| 509 | CX18_DEBUG_HI_FILE("Encoder poll\n"); | 518 | CX18_DEBUG_HI_FILE("Encoder poll\n"); |
| 510 | poll_wait(filp, &s->waitq, wait); | 519 | poll_wait(filp, &s->waitq, wait); |
| 511 | 520 | ||
| 512 | if (s->q_full.length || s->q_io.length) | 521 | if (atomic_read(&s->q_full.buffers) || atomic_read(&s->q_io.buffers)) |
| 513 | return POLLIN | POLLRDNORM; | 522 | return POLLIN | POLLRDNORM; |
| 514 | if (eof) | 523 | if (eof) |
| 515 | return POLLHUP; | 524 | return POLLHUP; |
| @@ -695,20 +704,28 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp) | |||
| 695 | 704 | ||
| 696 | void cx18_mute(struct cx18 *cx) | 705 | void cx18_mute(struct cx18 *cx) |
| 697 | { | 706 | { |
| 698 | if (atomic_read(&cx->ana_capturing)) | 707 | u32 h; |
| 699 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, | 708 | if (atomic_read(&cx->ana_capturing)) { |
| 700 | cx18_find_handle(cx), 1); | 709 | h = cx18_find_handle(cx); |
| 710 | if (h != CX18_INVALID_TASK_HANDLE) | ||
| 711 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1); | ||
| 712 | else | ||
| 713 | CX18_ERR("Can't find valid task handle for mute\n"); | ||
| 714 | } | ||
| 701 | CX18_DEBUG_INFO("Mute\n"); | 715 | CX18_DEBUG_INFO("Mute\n"); |
| 702 | } | 716 | } |
| 703 | 717 | ||
| 704 | void cx18_unmute(struct cx18 *cx) | 718 | void cx18_unmute(struct cx18 *cx) |
| 705 | { | 719 | { |
| 720 | u32 h; | ||
| 706 | if (atomic_read(&cx->ana_capturing)) { | 721 | if (atomic_read(&cx->ana_capturing)) { |
| 707 | cx18_msleep_timeout(100, 0); | 722 | h = cx18_find_handle(cx); |
| 708 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, | 723 | if (h != CX18_INVALID_TASK_HANDLE) { |
| 709 | cx18_find_handle(cx), 12); | 724 | cx18_msleep_timeout(100, 0); |
| 710 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, | 725 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12); |
| 711 | cx18_find_handle(cx), 0); | 726 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0); |
| 727 | } else | ||
| 728 | CX18_ERR("Can't find valid task handle for unmute\n"); | ||
| 712 | } | 729 | } |
| 713 | CX18_DEBUG_INFO("Unmute\n"); | 730 | CX18_DEBUG_INFO("Unmute\n"); |
| 714 | } | 731 | } |
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c index 78fadd2ada5d..51534428cd00 100644 --- a/drivers/media/video/cx18/cx18-firmware.c +++ b/drivers/media/video/cx18/cx18-firmware.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include "cx18-driver.h" | 22 | #include "cx18-driver.h" |
| 23 | #include "cx18-io.h" | ||
| 23 | #include "cx18-scb.h" | 24 | #include "cx18-scb.h" |
| 24 | #include "cx18-irq.h" | 25 | #include "cx18-irq.h" |
| 25 | #include "cx18-firmware.h" | 26 | #include "cx18-firmware.h" |
| @@ -113,11 +114,11 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx) | |||
| 113 | src = (const u32 *)fw->data; | 114 | src = (const u32 *)fw->data; |
| 114 | 115 | ||
| 115 | for (i = 0; i < fw->size; i += 4096) { | 116 | for (i = 0; i < fw->size; i += 4096) { |
| 116 | setup_page(i); | 117 | cx18_setup_page(cx, i); |
| 117 | for (j = i; j < fw->size && j < i + 4096; j += 4) { | 118 | for (j = i; j < fw->size && j < i + 4096; j += 4) { |
| 118 | /* no need for endianness conversion on the ppc */ | 119 | /* no need for endianness conversion on the ppc */ |
| 119 | __raw_writel(*src, dst); | 120 | cx18_raw_writel(cx, *src, dst); |
| 120 | if (__raw_readl(dst) != *src) { | 121 | if (cx18_raw_readl(cx, dst) != *src) { |
| 121 | CX18_ERR("Mismatch at offset %x\n", i); | 122 | CX18_ERR("Mismatch at offset %x\n", i); |
| 122 | release_firmware(fw); | 123 | release_firmware(fw); |
| 123 | return -EIO; | 124 | return -EIO; |
| @@ -170,12 +171,15 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx) | |||
| 170 | if (offset + seghdr.size > sz) | 171 | if (offset + seghdr.size > sz) |
| 171 | break; | 172 | break; |
| 172 | for (i = 0; i < seghdr.size; i += 4096) { | 173 | for (i = 0; i < seghdr.size; i += 4096) { |
| 173 | setup_page(offset + i); | 174 | cx18_setup_page(cx, offset + i); |
| 174 | for (j = i; j < seghdr.size && j < i + 4096; j += 4) { | 175 | for (j = i; j < seghdr.size && j < i + 4096; j += 4) { |
| 175 | /* no need for endianness conversion on the ppc */ | 176 | /* no need for endianness conversion on the ppc */ |
| 176 | __raw_writel(src[(offset + j) / 4], dst + seghdr.addr + j); | 177 | cx18_raw_writel(cx, src[(offset + j) / 4], |
| 177 | if (__raw_readl(dst + seghdr.addr + j) != src[(offset + j) / 4]) { | 178 | dst + seghdr.addr + j); |
| 178 | CX18_ERR("Mismatch at offset %x\n", offset + j); | 179 | if (cx18_raw_readl(cx, dst + seghdr.addr + j) |
| 180 | != src[(offset + j) / 4]) { | ||
| 181 | CX18_ERR("Mismatch at offset %x\n", | ||
| 182 | offset + j); | ||
| 179 | release_firmware(fw); | 183 | release_firmware(fw); |
| 180 | return -EIO; | 184 | return -EIO; |
| 181 | } | 185 | } |
| @@ -189,43 +193,45 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx) | |||
| 189 | size = fw->size; | 193 | size = fw->size; |
| 190 | release_firmware(fw); | 194 | release_firmware(fw); |
| 191 | /* Clear bit0 for APU to start from 0 */ | 195 | /* Clear bit0 for APU to start from 0 */ |
| 192 | write_reg(read_reg(0xc72030) & ~1, 0xc72030); | 196 | cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030); |
| 193 | return size; | 197 | return size; |
| 194 | } | 198 | } |
| 195 | 199 | ||
| 196 | void cx18_halt_firmware(struct cx18 *cx) | 200 | void cx18_halt_firmware(struct cx18 *cx) |
| 197 | { | 201 | { |
| 198 | CX18_DEBUG_INFO("Preparing for firmware halt.\n"); | 202 | CX18_DEBUG_INFO("Preparing for firmware halt.\n"); |
| 199 | write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ | 203 | cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ |
| 200 | write_reg(0x00020002, CX18_ADEC_CONTROL); | 204 | cx18_write_reg(cx, 0x00020002, CX18_ADEC_CONTROL); |
| 201 | } | 205 | } |
| 202 | 206 | ||
| 203 | void cx18_init_power(struct cx18 *cx, int lowpwr) | 207 | void cx18_init_power(struct cx18 *cx, int lowpwr) |
| 204 | { | 208 | { |
| 205 | /* power-down Spare and AOM PLLs */ | 209 | /* power-down Spare and AOM PLLs */ |
| 206 | /* power-up fast, slow and mpeg PLLs */ | 210 | /* power-up fast, slow and mpeg PLLs */ |
| 207 | write_reg(0x00000008, CX18_PLL_POWER_DOWN); | 211 | cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN); |
| 208 | 212 | ||
| 209 | /* ADEC out of sleep */ | 213 | /* ADEC out of sleep */ |
| 210 | write_reg(0x00020000, CX18_ADEC_CONTROL); | 214 | cx18_write_reg(cx, 0x00020000, CX18_ADEC_CONTROL); |
| 211 | 215 | ||
| 212 | /* The fast clock is at 200/245 MHz */ | 216 | /* The fast clock is at 200/245 MHz */ |
| 213 | write_reg(lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); | 217 | cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT); |
| 214 | write_reg(lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC); | 218 | cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7, |
| 219 | CX18_FAST_CLOCK_PLL_FRAC); | ||
| 215 | 220 | ||
| 216 | write_reg(2, CX18_FAST_CLOCK_PLL_POST); | 221 | cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST); |
| 217 | write_reg(1, CX18_FAST_CLOCK_PLL_PRESCALE); | 222 | cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE); |
| 218 | write_reg(4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH); | 223 | cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH); |
| 219 | 224 | ||
| 220 | /* set slow clock to 125/120 MHz */ | 225 | /* set slow clock to 125/120 MHz */ |
| 221 | write_reg(lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT); | 226 | cx18_write_reg(cx, lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT); |
| 222 | write_reg(lowpwr ? 0xEBAF05 : 0x18618A8, CX18_SLOW_CLOCK_PLL_FRAC); | 227 | cx18_write_reg(cx, lowpwr ? 0xEBAF05 : 0x18618A8, |
| 223 | write_reg(4, CX18_SLOW_CLOCK_PLL_POST); | 228 | CX18_SLOW_CLOCK_PLL_FRAC); |
| 229 | cx18_write_reg(cx, 4, CX18_SLOW_CLOCK_PLL_POST); | ||
| 224 | 230 | ||
| 225 | /* mpeg clock pll 54MHz */ | 231 | /* mpeg clock pll 54MHz */ |
| 226 | write_reg(0xF, CX18_MPEG_CLOCK_PLL_INT); | 232 | cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT); |
| 227 | write_reg(0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC); | 233 | cx18_write_reg(cx, 0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC); |
| 228 | write_reg(8, CX18_MPEG_CLOCK_PLL_POST); | 234 | cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST); |
| 229 | 235 | ||
| 230 | /* Defaults */ | 236 | /* Defaults */ |
| 231 | /* APU = SC or SC/2 = 125/62.5 */ | 237 | /* APU = SC or SC/2 = 125/62.5 */ |
| @@ -242,81 +248,84 @@ void cx18_init_power(struct cx18 *cx, int lowpwr) | |||
| 242 | /* VFC = disabled */ | 248 | /* VFC = disabled */ |
| 243 | /* USB = disabled */ | 249 | /* USB = disabled */ |
| 244 | 250 | ||
| 245 | write_reg(lowpwr ? 0xFFFF0020 : 0x00060004, CX18_CLOCK_SELECT1); | 251 | cx18_write_reg(cx, lowpwr ? 0xFFFF0020 : 0x00060004, |
| 246 | write_reg(lowpwr ? 0xFFFF0004 : 0x00060006, CX18_CLOCK_SELECT2); | 252 | CX18_CLOCK_SELECT1); |
| 253 | cx18_write_reg(cx, lowpwr ? 0xFFFF0004 : 0x00060006, | ||
| 254 | CX18_CLOCK_SELECT2); | ||
| 247 | 255 | ||
| 248 | write_reg(0xFFFF0002, CX18_HALF_CLOCK_SELECT1); | 256 | cx18_write_reg(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1); |
| 249 | write_reg(0xFFFF0104, CX18_HALF_CLOCK_SELECT2); | 257 | cx18_write_reg(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2); |
| 250 | 258 | ||
| 251 | write_reg(0xFFFF9026, CX18_CLOCK_ENABLE1); | 259 | cx18_write_reg(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1); |
| 252 | write_reg(0xFFFF3105, CX18_CLOCK_ENABLE2); | 260 | cx18_write_reg(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2); |
| 253 | } | 261 | } |
| 254 | 262 | ||
| 255 | void cx18_init_memory(struct cx18 *cx) | 263 | void cx18_init_memory(struct cx18 *cx) |
| 256 | { | 264 | { |
| 257 | cx18_msleep_timeout(10, 0); | 265 | cx18_msleep_timeout(10, 0); |
| 258 | write_reg(0x10000, CX18_DDR_SOFT_RESET); | 266 | cx18_write_reg(cx, 0x10000, CX18_DDR_SOFT_RESET); |
| 259 | cx18_msleep_timeout(10, 0); | 267 | cx18_msleep_timeout(10, 0); |
| 260 | 268 | ||
| 261 | write_reg(cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG); | 269 | cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG); |
| 262 | 270 | ||
| 263 | cx18_msleep_timeout(10, 0); | 271 | cx18_msleep_timeout(10, 0); |
| 264 | 272 | ||
| 265 | write_reg(cx->card->ddr.refresh, CX18_DDR_REFRESH); | 273 | cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH); |
| 266 | write_reg(cx->card->ddr.timing1, CX18_DDR_TIMING1); | 274 | cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1); |
| 267 | write_reg(cx->card->ddr.timing2, CX18_DDR_TIMING2); | 275 | cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2); |
| 268 | 276 | ||
| 269 | cx18_msleep_timeout(10, 0); | 277 | cx18_msleep_timeout(10, 0); |
| 270 | 278 | ||
| 271 | /* Initialize DQS pad time */ | 279 | /* Initialize DQS pad time */ |
| 272 | write_reg(cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE); | 280 | cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE); |
| 273 | write_reg(cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS); | 281 | cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS); |
| 274 | 282 | ||
| 275 | cx18_msleep_timeout(10, 0); | 283 | cx18_msleep_timeout(10, 0); |
| 276 | 284 | ||
| 277 | write_reg(0x20000, CX18_DDR_SOFT_RESET); | 285 | cx18_write_reg(cx, 0x20000, CX18_DDR_SOFT_RESET); |
| 278 | cx18_msleep_timeout(10, 0); | 286 | cx18_msleep_timeout(10, 0); |
| 279 | 287 | ||
| 280 | /* use power-down mode when idle */ | 288 | /* use power-down mode when idle */ |
| 281 | write_reg(0x00000010, CX18_DDR_POWER_REG); | 289 | cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG); |
| 282 | 290 | ||
| 283 | write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN); | 291 | cx18_write_reg(cx, 0x10001, CX18_REG_BUS_TIMEOUT_EN); |
| 284 | 292 | ||
| 285 | write_reg(0x48, CX18_DDR_MB_PER_ROW_7); | 293 | cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7); |
| 286 | write_reg(0xE0000, CX18_DDR_BASE_63_ADDR); | 294 | cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR); |
| 287 | 295 | ||
| 288 | write_reg(0x00000101, CX18_WMB_CLIENT02); /* AO */ | 296 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02); /* AO */ |
| 289 | write_reg(0x00000101, CX18_WMB_CLIENT09); /* AI2 */ | 297 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09); /* AI2 */ |
| 290 | write_reg(0x00000101, CX18_WMB_CLIENT05); /* VIM1 */ | 298 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05); /* VIM1 */ |
| 291 | write_reg(0x00000101, CX18_WMB_CLIENT06); /* AI1 */ | 299 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06); /* AI1 */ |
| 292 | write_reg(0x00000101, CX18_WMB_CLIENT07); /* 3D comb */ | 300 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07); /* 3D comb */ |
| 293 | write_reg(0x00000101, CX18_WMB_CLIENT10); /* ME */ | 301 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10); /* ME */ |
| 294 | write_reg(0x00000101, CX18_WMB_CLIENT12); /* ENC */ | 302 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12); /* ENC */ |
| 295 | write_reg(0x00000101, CX18_WMB_CLIENT13); /* PK */ | 303 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13); /* PK */ |
| 296 | write_reg(0x00000101, CX18_WMB_CLIENT11); /* RC */ | 304 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11); /* RC */ |
| 297 | write_reg(0x00000101, CX18_WMB_CLIENT14); /* AVO */ | 305 | cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14); /* AVO */ |
| 298 | } | 306 | } |
| 299 | 307 | ||
| 300 | int cx18_firmware_init(struct cx18 *cx) | 308 | int cx18_firmware_init(struct cx18 *cx) |
| 301 | { | 309 | { |
| 302 | /* Allow chip to control CLKRUN */ | 310 | /* Allow chip to control CLKRUN */ |
| 303 | write_reg(0x5, CX18_DSP0_INTERRUPT_MASK); | 311 | cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK); |
| 304 | 312 | ||
| 305 | write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ | 313 | cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */ |
| 306 | 314 | ||
| 307 | cx18_msleep_timeout(1, 0); | 315 | cx18_msleep_timeout(1, 0); |
| 308 | 316 | ||
| 309 | sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); | 317 | cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); |
| 310 | sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); | 318 | cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); |
| 311 | 319 | ||
| 312 | /* Only if the processor is not running */ | 320 | /* Only if the processor is not running */ |
| 313 | if (read_reg(CX18_PROC_SOFT_RESET) & 8) { | 321 | if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) { |
| 314 | int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", | 322 | int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", |
| 315 | cx->enc_mem, cx); | 323 | cx->enc_mem, cx); |
| 316 | 324 | ||
| 317 | write_enc(0xE51FF004, 0); | 325 | cx18_write_enc(cx, 0xE51FF004, 0); |
| 318 | write_enc(0xa00000, 4); /* todo: not hardcoded */ | 326 | cx18_write_enc(cx, 0xa00000, 4); /* todo: not hardcoded */ |
| 319 | write_reg(0x00010000, CX18_PROC_SOFT_RESET); /* Start APU */ | 327 | /* Start APU */ |
| 328 | cx18_write_reg(cx, 0x00010000, CX18_PROC_SOFT_RESET); | ||
| 320 | cx18_msleep_timeout(500, 0); | 329 | cx18_msleep_timeout(500, 0); |
| 321 | 330 | ||
| 322 | sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", | 331 | sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", |
| @@ -326,9 +335,10 @@ int cx18_firmware_init(struct cx18 *cx) | |||
| 326 | int retries = 0; | 335 | int retries = 0; |
| 327 | 336 | ||
| 328 | /* start the CPU */ | 337 | /* start the CPU */ |
| 329 | write_reg(0x00080000, CX18_PROC_SOFT_RESET); | 338 | cx18_write_reg(cx, 0x00080000, CX18_PROC_SOFT_RESET); |
| 330 | while (retries++ < 50) { /* Loop for max 500mS */ | 339 | while (retries++ < 50) { /* Loop for max 500mS */ |
| 331 | if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0) | 340 | if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) |
| 341 | & 1) == 0) | ||
| 332 | break; | 342 | break; |
| 333 | cx18_msleep_timeout(10, 0); | 343 | cx18_msleep_timeout(10, 0); |
| 334 | } | 344 | } |
| @@ -342,6 +352,6 @@ int cx18_firmware_init(struct cx18 *cx) | |||
| 342 | return -EIO; | 352 | return -EIO; |
| 343 | } | 353 | } |
| 344 | /* initialize GPIO */ | 354 | /* initialize GPIO */ |
| 345 | write_reg(0x14001400, 0xC78110); | 355 | cx18_write_reg(cx, 0x14001400, 0xC78110); |
| 346 | return 0; | 356 | return 0; |
| 347 | } | 357 | } |
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index 3d495dba4983..0e560421989e 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
| 25 | #include "cx18-io.h" | ||
| 25 | #include "cx18-cards.h" | 26 | #include "cx18-cards.h" |
| 26 | #include "cx18-gpio.h" | 27 | #include "cx18-gpio.h" |
| 27 | #include "tuner-xc2028.h" | 28 | #include "tuner-xc2028.h" |
| @@ -49,11 +50,11 @@ static void gpio_write(struct cx18 *cx) | |||
| 49 | u32 dir = cx->gpio_dir; | 50 | u32 dir = cx->gpio_dir; |
| 50 | u32 val = cx->gpio_val; | 51 | u32 val = cx->gpio_val; |
| 51 | 52 | ||
| 52 | write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); | 53 | cx18_write_reg(cx, (dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); |
| 53 | write_reg(((dir & 0xffff) << 16) | (val & 0xffff), | 54 | cx18_write_reg(cx, ((dir & 0xffff) << 16) | (val & 0xffff), |
| 54 | CX18_REG_GPIO_OUT1); | 55 | CX18_REG_GPIO_OUT1); |
| 55 | write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2); | 56 | cx18_write_reg(cx, dir & 0xffff0000, CX18_REG_GPIO_DIR2); |
| 56 | write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16), | 57 | cx18_write_reg_sync(cx, (dir & 0xffff0000) | ((val & 0xffff0000) >> 16), |
| 57 | CX18_REG_GPIO_OUT2); | 58 | CX18_REG_GPIO_OUT2); |
| 58 | } | 59 | } |
| 59 | 60 | ||
| @@ -141,15 +142,17 @@ void cx18_gpio_init(struct cx18 *cx) | |||
| 141 | } | 142 | } |
| 142 | 143 | ||
| 143 | CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", | 144 | CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", |
| 144 | read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2), | 145 | cx18_read_reg(cx, CX18_REG_GPIO_DIR1), |
| 145 | read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2)); | 146 | cx18_read_reg(cx, CX18_REG_GPIO_DIR2), |
| 147 | cx18_read_reg(cx, CX18_REG_GPIO_OUT1), | ||
| 148 | cx18_read_reg(cx, CX18_REG_GPIO_OUT2)); | ||
| 146 | 149 | ||
| 147 | gpio_write(cx); | 150 | gpio_write(cx); |
| 148 | mutex_unlock(&cx->gpio_lock); | 151 | mutex_unlock(&cx->gpio_lock); |
| 149 | } | 152 | } |
| 150 | 153 | ||
| 151 | /* Xceive tuner reset function */ | 154 | /* Xceive tuner reset function */ |
| 152 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value) | 155 | int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value) |
| 153 | { | 156 | { |
| 154 | struct i2c_algo_bit_data *algo = dev; | 157 | struct i2c_algo_bit_data *algo = dev; |
| 155 | struct cx18_i2c_algo_callback_data *cb_data = algo->data; | 158 | struct cx18_i2c_algo_callback_data *cb_data = algo->data; |
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h index 22cd7ddf8554..beb7424b9944 100644 --- a/drivers/media/video/cx18/cx18-gpio.h +++ b/drivers/media/video/cx18/cx18-gpio.h | |||
| @@ -23,5 +23,5 @@ | |||
| 23 | void cx18_gpio_init(struct cx18 *cx); | 23 | void cx18_gpio_init(struct cx18 *cx); |
| 24 | void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); | 24 | void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); |
| 25 | void cx18_reset_ir_gpio(void *data); | 25 | void cx18_reset_ir_gpio(void *data); |
| 26 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value); | 26 | int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value); |
| 27 | int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg); | 27 | int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg); |
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 6023ba3bd3a6..aa09e557b195 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c | |||
| @@ -22,13 +22,12 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
| 25 | #include "cx18-io.h" | ||
| 25 | #include "cx18-cards.h" | 26 | #include "cx18-cards.h" |
| 26 | #include "cx18-gpio.h" | 27 | #include "cx18-gpio.h" |
| 27 | #include "cx18-av-core.h" | 28 | #include "cx18-av-core.h" |
| 28 | #include "cx18-i2c.h" | 29 | #include "cx18-i2c.h" |
| 29 | 30 | ||
| 30 | #include <media/ir-kbd-i2c.h> | ||
| 31 | |||
| 32 | #define CX18_REG_I2C_1_WR 0xf15000 | 31 | #define CX18_REG_I2C_1_WR 0xf15000 |
| 33 | #define CX18_REG_I2C_1_RD 0xf15008 | 32 | #define CX18_REG_I2C_1_RD 0xf15008 |
| 34 | #define CX18_REG_I2C_2_WR 0xf25100 | 33 | #define CX18_REG_I2C_2_WR 0xf25100 |
| @@ -158,12 +157,12 @@ static void cx18_setscl(void *data, int state) | |||
| 158 | struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; | 157 | struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; |
| 159 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; | 158 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; |
| 160 | u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR; | 159 | u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR; |
| 161 | u32 r = read_reg(addr); | 160 | u32 r = cx18_read_reg(cx, addr); |
| 162 | 161 | ||
| 163 | if (state) | 162 | if (state) |
| 164 | write_reg_sync(r | SETSCL_BIT, addr); | 163 | cx18_write_reg_sync(cx, r | SETSCL_BIT, addr); |
| 165 | else | 164 | else |
| 166 | write_reg_sync(r & ~SETSCL_BIT, addr); | 165 | cx18_write_reg_sync(cx, r & ~SETSCL_BIT, addr); |
| 167 | } | 166 | } |
| 168 | 167 | ||
| 169 | static void cx18_setsda(void *data, int state) | 168 | static void cx18_setsda(void *data, int state) |
| @@ -171,12 +170,12 @@ static void cx18_setsda(void *data, int state) | |||
| 171 | struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; | 170 | struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx; |
| 172 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; | 171 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; |
| 173 | u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR; | 172 | u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR; |
| 174 | u32 r = read_reg(addr); | 173 | u32 r = cx18_read_reg(cx, addr); |
| 175 | 174 | ||
| 176 | if (state) | 175 | if (state) |
| 177 | write_reg_sync(r | SETSDL_BIT, addr); | 176 | cx18_write_reg_sync(cx, r | SETSDL_BIT, addr); |
| 178 | else | 177 | else |
| 179 | write_reg_sync(r & ~SETSDL_BIT, addr); | 178 | cx18_write_reg_sync(cx, r & ~SETSDL_BIT, addr); |
| 180 | } | 179 | } |
| 181 | 180 | ||
| 182 | static int cx18_getscl(void *data) | 181 | static int cx18_getscl(void *data) |
| @@ -185,7 +184,7 @@ static int cx18_getscl(void *data) | |||
| 185 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; | 184 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; |
| 186 | u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD; | 185 | u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD; |
| 187 | 186 | ||
| 188 | return read_reg(addr) & GETSCL_BIT; | 187 | return cx18_read_reg(cx, addr) & GETSCL_BIT; |
| 189 | } | 188 | } |
| 190 | 189 | ||
| 191 | static int cx18_getsda(void *data) | 190 | static int cx18_getsda(void *data) |
| @@ -194,7 +193,7 @@ static int cx18_getsda(void *data) | |||
| 194 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; | 193 | int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index; |
| 195 | u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD; | 194 | u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD; |
| 196 | 195 | ||
| 197 | return read_reg(addr) & GETSDL_BIT; | 196 | return cx18_read_reg(cx, addr) & GETSDL_BIT; |
| 198 | } | 197 | } |
| 199 | 198 | ||
| 200 | /* template for i2c-bit-algo */ | 199 | /* template for i2c-bit-algo */ |
| @@ -394,29 +393,33 @@ int init_cx18_i2c(struct cx18 *cx) | |||
| 394 | cx->i2c_adap[i].dev.parent = &cx->dev->dev; | 393 | cx->i2c_adap[i].dev.parent = &cx->dev->dev; |
| 395 | } | 394 | } |
| 396 | 395 | ||
| 397 | if (read_reg(CX18_REG_I2C_2_WR) != 0x0003c02f) { | 396 | if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) { |
| 398 | /* Reset/Unreset I2C hardware block */ | 397 | /* Reset/Unreset I2C hardware block */ |
| 399 | write_reg(0x10000000, 0xc71004); /* Clock select 220MHz */ | 398 | /* Clock select 220MHz */ |
| 400 | write_reg_sync(0x10001000, 0xc71024); /* Clock Enable */ | 399 | cx18_write_reg(cx, 0x10000000, 0xc71004); |
| 400 | /* Clock Enable */ | ||
| 401 | cx18_write_reg_sync(cx, 0x10001000, 0xc71024); | ||
| 401 | } | 402 | } |
| 402 | /* courtesy of Steven Toth <stoth@hauppauge.com> */ | 403 | /* courtesy of Steven Toth <stoth@hauppauge.com> */ |
| 403 | write_reg_sync(0x00c00000, 0xc7001c); | 404 | cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c); |
| 404 | mdelay(10); | 405 | mdelay(10); |
| 405 | write_reg_sync(0x00c000c0, 0xc7001c); | 406 | cx18_write_reg_sync(cx, 0x00c000c0, 0xc7001c); |
| 406 | mdelay(10); | 407 | mdelay(10); |
| 407 | write_reg_sync(0x00c00000, 0xc7001c); | 408 | cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c); |
| 408 | mdelay(10); | 409 | mdelay(10); |
| 409 | 410 | ||
| 410 | write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */ | 411 | /* Set to edge-triggered intrs. */ |
| 411 | write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */ | 412 | cx18_write_reg_sync(cx, 0x00c00000, 0xc730c8); |
| 413 | /* Clear any stale intrs */ | ||
| 414 | cx18_write_reg_sync(cx, 0x00c00000, 0xc730c4); | ||
| 412 | 415 | ||
| 413 | /* Hw I2C1 Clock Freq ~100kHz */ | 416 | /* Hw I2C1 Clock Freq ~100kHz */ |
| 414 | write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_1_WR); | 417 | cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR); |
| 415 | cx18_setscl(&cx->i2c_algo_cb_data[0], 1); | 418 | cx18_setscl(&cx->i2c_algo_cb_data[0], 1); |
| 416 | cx18_setsda(&cx->i2c_algo_cb_data[0], 1); | 419 | cx18_setsda(&cx->i2c_algo_cb_data[0], 1); |
| 417 | 420 | ||
| 418 | /* Hw I2C2 Clock Freq ~100kHz */ | 421 | /* Hw I2C2 Clock Freq ~100kHz */ |
| 419 | write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_2_WR); | 422 | cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR); |
| 420 | cx18_setscl(&cx->i2c_algo_cb_data[1], 1); | 423 | cx18_setscl(&cx->i2c_algo_cb_data[1], 1); |
| 421 | cx18_setsda(&cx->i2c_algo_cb_data[1], 1); | 424 | cx18_setsda(&cx->i2c_algo_cb_data[1], 1); |
| 422 | 425 | ||
| @@ -430,8 +433,10 @@ void exit_cx18_i2c(struct cx18 *cx) | |||
| 430 | { | 433 | { |
| 431 | int i; | 434 | int i; |
| 432 | CX18_DEBUG_I2C("i2c exit\n"); | 435 | CX18_DEBUG_I2C("i2c exit\n"); |
| 433 | write_reg(read_reg(CX18_REG_I2C_1_WR) | 4, CX18_REG_I2C_1_WR); | 436 | cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4, |
| 434 | write_reg(read_reg(CX18_REG_I2C_2_WR) | 4, CX18_REG_I2C_2_WR); | 437 | CX18_REG_I2C_1_WR); |
| 438 | cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4, | ||
| 439 | CX18_REG_I2C_2_WR); | ||
| 435 | 440 | ||
| 436 | for (i = 0; i < 2; i++) { | 441 | for (i = 0; i < 2; i++) { |
| 437 | i2c_del_adapter(&cx->i2c_adap[i]); | 442 | i2c_del_adapter(&cx->i2c_adap[i]); |
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c new file mode 100644 index 000000000000..700ab9439c16 --- /dev/null +++ b/drivers/media/video/cx18/cx18-io.c | |||
| @@ -0,0 +1,254 @@ | |||
| 1 | /* | ||
| 2 | * cx18 driver PCI memory mapped IO access routines | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
| 5 | * Copyright (C) 2008 Andy Walls <awalls@radix.net> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
| 20 | * 02111-1307 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include "cx18-driver.h" | ||
| 24 | #include "cx18-io.h" | ||
| 25 | #include "cx18-irq.h" | ||
| 26 | |||
| 27 | void cx18_log_statistics(struct cx18 *cx) | ||
| 28 | { | ||
| 29 | int i; | ||
| 30 | |||
| 31 | if (!(cx18_debug & CX18_DBGFLG_INFO)) | ||
| 32 | return; | ||
| 33 | |||
| 34 | for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++) | ||
| 35 | CX18_DEBUG_INFO("retried_write[%d] = %d\n", i, | ||
| 36 | atomic_read(&cx->mmio_stats.retried_write[i])); | ||
| 37 | for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++) | ||
| 38 | CX18_DEBUG_INFO("retried_read[%d] = %d\n", i, | ||
| 39 | atomic_read(&cx->mmio_stats.retried_read[i])); | ||
| 40 | return; | ||
| 41 | } | ||
| 42 | |||
| 43 | void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
| 44 | { | ||
| 45 | int i; | ||
| 46 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 47 | cx18_raw_writel_noretry(cx, val, addr); | ||
| 48 | if (val == cx18_raw_readl_noretry(cx, addr)) | ||
| 49 | break; | ||
| 50 | } | ||
| 51 | cx18_log_write_retries(cx, i, addr); | ||
| 52 | } | ||
| 53 | |||
| 54 | u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr) | ||
| 55 | { | ||
| 56 | int i; | ||
| 57 | u32 val; | ||
| 58 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 59 | val = cx18_raw_readl_noretry(cx, addr); | ||
| 60 | if (val != 0xffffffff) /* PCI bus read error */ | ||
| 61 | break; | ||
| 62 | } | ||
| 63 | cx18_log_read_retries(cx, i, addr); | ||
| 64 | return val; | ||
| 65 | } | ||
| 66 | |||
| 67 | u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr) | ||
| 68 | { | ||
| 69 | int i; | ||
| 70 | u16 val; | ||
| 71 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 72 | val = cx18_raw_readw_noretry(cx, addr); | ||
| 73 | if (val != 0xffff) /* PCI bus read error */ | ||
| 74 | break; | ||
| 75 | } | ||
| 76 | cx18_log_read_retries(cx, i, addr); | ||
| 77 | return val; | ||
| 78 | } | ||
| 79 | |||
| 80 | void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
| 81 | { | ||
| 82 | int i; | ||
| 83 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 84 | cx18_writel_noretry(cx, val, addr); | ||
| 85 | if (val == cx18_readl_noretry(cx, addr)) | ||
| 86 | break; | ||
| 87 | } | ||
| 88 | cx18_log_write_retries(cx, i, addr); | ||
| 89 | } | ||
| 90 | |||
| 91 | void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr) | ||
| 92 | { | ||
| 93 | int i; | ||
| 94 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 95 | cx18_writew_noretry(cx, val, addr); | ||
| 96 | if (val == cx18_readw_noretry(cx, addr)) | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | cx18_log_write_retries(cx, i, addr); | ||
| 100 | } | ||
| 101 | |||
| 102 | void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr) | ||
| 103 | { | ||
| 104 | int i; | ||
| 105 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 106 | cx18_writeb_noretry(cx, val, addr); | ||
| 107 | if (val == cx18_readb_noretry(cx, addr)) | ||
| 108 | break; | ||
| 109 | } | ||
| 110 | cx18_log_write_retries(cx, i, addr); | ||
| 111 | } | ||
| 112 | |||
| 113 | u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr) | ||
| 114 | { | ||
| 115 | int i; | ||
| 116 | u32 val; | ||
| 117 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 118 | val = cx18_readl_noretry(cx, addr); | ||
| 119 | if (val != 0xffffffff) /* PCI bus read error */ | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | cx18_log_read_retries(cx, i, addr); | ||
| 123 | return val; | ||
| 124 | } | ||
| 125 | |||
| 126 | u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr) | ||
| 127 | { | ||
| 128 | int i; | ||
| 129 | u16 val; | ||
| 130 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 131 | val = cx18_readw_noretry(cx, addr); | ||
| 132 | if (val != 0xffff) /* PCI bus read error */ | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | cx18_log_read_retries(cx, i, addr); | ||
| 136 | return val; | ||
| 137 | } | ||
| 138 | |||
| 139 | u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr) | ||
| 140 | { | ||
| 141 | int i; | ||
| 142 | u8 val; | ||
| 143 | for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { | ||
| 144 | val = cx18_readb_noretry(cx, addr); | ||
| 145 | if (val != 0xff) /* PCI bus read error */ | ||
| 146 | break; | ||
| 147 | } | ||
| 148 | cx18_log_read_retries(cx, i, addr); | ||
| 149 | return val; | ||
| 150 | } | ||
| 151 | |||
| 152 | void cx18_memcpy_fromio(struct cx18 *cx, void *to, | ||
| 153 | const void __iomem *from, unsigned int len) | ||
| 154 | { | ||
| 155 | const u8 __iomem *src = from; | ||
| 156 | u8 *dst = to; | ||
| 157 | |||
| 158 | /* Align reads on the CX23418's addresses */ | ||
| 159 | if ((len > 0) && ((unsigned long) src & 1)) { | ||
| 160 | *dst = cx18_readb(cx, src); | ||
| 161 | len--; | ||
| 162 | dst++; | ||
| 163 | src++; | ||
| 164 | } | ||
| 165 | if ((len > 1) && ((unsigned long) src & 2)) { | ||
| 166 | *((u16 *)dst) = cx18_raw_readw(cx, src); | ||
| 167 | len -= 2; | ||
| 168 | dst += 2; | ||
| 169 | src += 2; | ||
| 170 | } | ||
| 171 | while (len > 3) { | ||
| 172 | *((u32 *)dst) = cx18_raw_readl(cx, src); | ||
| 173 | len -= 4; | ||
| 174 | dst += 4; | ||
| 175 | src += 4; | ||
| 176 | } | ||
| 177 | if (len > 1) { | ||
| 178 | *((u16 *)dst) = cx18_raw_readw(cx, src); | ||
| 179 | len -= 2; | ||
| 180 | dst += 2; | ||
| 181 | src += 2; | ||
| 182 | } | ||
| 183 | if (len > 0) | ||
| 184 | *dst = cx18_readb(cx, src); | ||
| 185 | } | ||
| 186 | |||
| 187 | void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) | ||
| 188 | { | ||
| 189 | u8 __iomem *dst = addr; | ||
| 190 | u16 val2 = val | (val << 8); | ||
| 191 | u32 val4 = val2 | (val2 << 16); | ||
| 192 | |||
| 193 | /* Align writes on the CX23418's addresses */ | ||
| 194 | if ((count > 0) && ((unsigned long)dst & 1)) { | ||
| 195 | cx18_writeb(cx, (u8) val, dst); | ||
| 196 | count--; | ||
| 197 | dst++; | ||
| 198 | } | ||
| 199 | if ((count > 1) && ((unsigned long)dst & 2)) { | ||
| 200 | cx18_writew(cx, val2, dst); | ||
| 201 | count -= 2; | ||
| 202 | dst += 2; | ||
| 203 | } | ||
| 204 | while (count > 3) { | ||
| 205 | cx18_writel(cx, val4, dst); | ||
| 206 | count -= 4; | ||
| 207 | dst += 4; | ||
| 208 | } | ||
| 209 | if (count > 1) { | ||
| 210 | cx18_writew(cx, val2, dst); | ||
| 211 | count -= 2; | ||
| 212 | dst += 2; | ||
| 213 | } | ||
| 214 | if (count > 0) | ||
| 215 | cx18_writeb(cx, (u8) val, dst); | ||
| 216 | } | ||
| 217 | |||
| 218 | void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) | ||
| 219 | { | ||
| 220 | u32 r; | ||
| 221 | cx18_write_reg(cx, val, SW1_INT_STATUS); | ||
| 222 | r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); | ||
| 223 | cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); | ||
| 224 | } | ||
| 225 | |||
| 226 | void cx18_sw1_irq_disable(struct cx18 *cx, u32 val) | ||
| 227 | { | ||
| 228 | u32 r; | ||
| 229 | r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); | ||
| 230 | cx18_write_reg(cx, r & ~val, SW1_INT_ENABLE_PCI); | ||
| 231 | } | ||
| 232 | |||
| 233 | void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) | ||
| 234 | { | ||
| 235 | u32 r; | ||
| 236 | cx18_write_reg(cx, val, SW2_INT_STATUS); | ||
| 237 | r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); | ||
| 238 | cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); | ||
| 239 | } | ||
| 240 | |||
| 241 | void cx18_sw2_irq_disable(struct cx18 *cx, u32 val) | ||
| 242 | { | ||
| 243 | u32 r; | ||
| 244 | r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); | ||
| 245 | cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_PCI); | ||
| 246 | } | ||
| 247 | |||
| 248 | void cx18_setup_page(struct cx18 *cx, u32 addr) | ||
| 249 | { | ||
| 250 | u32 val; | ||
| 251 | val = cx18_read_reg(cx, 0xD000F8); | ||
| 252 | val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00); | ||
| 253 | cx18_write_reg(cx, val, 0xD000F8); | ||
| 254 | } | ||
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h new file mode 100644 index 000000000000..197d4fbd9f95 --- /dev/null +++ b/drivers/media/video/cx18/cx18-io.h | |||
| @@ -0,0 +1,378 @@ | |||
| 1 | /* | ||
| 2 | * cx18 driver PCI memory mapped IO access routines | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> | ||
| 5 | * Copyright (C) 2008 Andy Walls <awalls@radix.net> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
| 20 | * 02111-1307 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef CX18_IO_H | ||
| 24 | #define CX18_IO_H | ||
| 25 | |||
| 26 | #include "cx18-driver.h" | ||
| 27 | |||
| 28 | static inline void cx18_io_delay(struct cx18 *cx) | ||
| 29 | { | ||
| 30 | if (cx->options.mmio_ndelay) | ||
| 31 | ndelay(cx->options.mmio_ndelay); | ||
| 32 | } | ||
| 33 | |||
| 34 | /* | ||
| 35 | * Readback and retry of MMIO access for reliability: | ||
| 36 | * The concept was suggested by Steve Toth <stoth@linuxtv.org>. | ||
| 37 | * The implmentation is the fault of Andy Walls <awalls@radix.net>. | ||
| 38 | */ | ||
| 39 | |||
| 40 | /* Statistics gathering */ | ||
| 41 | static inline | ||
| 42 | void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr) | ||
| 43 | { | ||
| 44 | if (i > CX18_MAX_MMIO_RETRIES) | ||
| 45 | i = CX18_MAX_MMIO_RETRIES; | ||
| 46 | atomic_inc(&cx->mmio_stats.retried_write[i]); | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline | ||
| 51 | void cx18_log_read_retries(struct cx18 *cx, int i, const void *addr) | ||
| 52 | { | ||
| 53 | if (i > CX18_MAX_MMIO_RETRIES) | ||
| 54 | i = CX18_MAX_MMIO_RETRIES; | ||
| 55 | atomic_inc(&cx->mmio_stats.retried_read[i]); | ||
| 56 | return; | ||
| 57 | } | ||
| 58 | |||
| 59 | void cx18_log_statistics(struct cx18 *cx); | ||
| 60 | |||
| 61 | /* Non byteswapping memory mapped IO */ | ||
| 62 | static inline | ||
| 63 | void cx18_raw_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
| 64 | { | ||
| 65 | __raw_writel(val, addr); | ||
| 66 | cx18_io_delay(cx); | ||
| 67 | } | ||
| 68 | |||
| 69 | void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr); | ||
| 70 | |||
| 71 | static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr) | ||
| 72 | { | ||
| 73 | if (cx18_retry_mmio) | ||
| 74 | cx18_raw_writel_retry(cx, val, addr); | ||
| 75 | else | ||
| 76 | cx18_raw_writel_noretry(cx, val, addr); | ||
| 77 | } | ||
| 78 | |||
| 79 | |||
| 80 | static inline | ||
| 81 | u32 cx18_raw_readl_noretry(struct cx18 *cx, const void __iomem *addr) | ||
| 82 | { | ||
| 83 | u32 ret = __raw_readl(addr); | ||
| 84 | cx18_io_delay(cx); | ||
| 85 | return ret; | ||
| 86 | } | ||
| 87 | |||
| 88 | u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr); | ||
| 89 | |||
| 90 | static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr) | ||
| 91 | { | ||
| 92 | if (cx18_retry_mmio) | ||
| 93 | return cx18_raw_readl_retry(cx, addr); | ||
| 94 | |||
| 95 | return cx18_raw_readl_noretry(cx, addr); | ||
| 96 | } | ||
| 97 | |||
| 98 | |||
| 99 | static inline | ||
| 100 | u16 cx18_raw_readw_noretry(struct cx18 *cx, const void __iomem *addr) | ||
| 101 | { | ||
| 102 | u16 ret = __raw_readw(addr); | ||
| 103 | cx18_io_delay(cx); | ||
| 104 | return ret; | ||
| 105 | } | ||
| 106 | |||
| 107 | u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr); | ||
| 108 | |||
| 109 | static inline u16 cx18_raw_readw(struct cx18 *cx, const void __iomem *addr) | ||
| 110 | { | ||
| 111 | if (cx18_retry_mmio) | ||
| 112 | return cx18_raw_readw_retry(cx, addr); | ||
| 113 | |||
| 114 | return cx18_raw_readw_noretry(cx, addr); | ||
| 115 | } | ||
| 116 | |||
| 117 | |||
| 118 | /* Normal memory mapped IO */ | ||
| 119 | static inline | ||
| 120 | void cx18_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
| 121 | { | ||
| 122 | writel(val, addr); | ||
| 123 | cx18_io_delay(cx); | ||
| 124 | } | ||
| 125 | |||
| 126 | void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr); | ||
| 127 | |||
| 128 | static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) | ||
| 129 | { | ||
| 130 | if (cx18_retry_mmio) | ||
| 131 | cx18_writel_retry(cx, val, addr); | ||
| 132 | else | ||
| 133 | cx18_writel_noretry(cx, val, addr); | ||
| 134 | } | ||
| 135 | |||
| 136 | |||
| 137 | static inline | ||
| 138 | void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr) | ||
| 139 | { | ||
| 140 | writew(val, addr); | ||
| 141 | cx18_io_delay(cx); | ||
| 142 | } | ||
| 143 | |||
| 144 | void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr); | ||
| 145 | |||
| 146 | static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr) | ||
| 147 | { | ||
| 148 | if (cx18_retry_mmio) | ||
| 149 | cx18_writew_retry(cx, val, addr); | ||
| 150 | else | ||
| 151 | cx18_writew_noretry(cx, val, addr); | ||
| 152 | } | ||
| 153 | |||
| 154 | |||
| 155 | static inline | ||
| 156 | void cx18_writeb_noretry(struct cx18 *cx, u8 val, void __iomem *addr) | ||
| 157 | { | ||
| 158 | writeb(val, addr); | ||
| 159 | cx18_io_delay(cx); | ||
| 160 | } | ||
| 161 | |||
| 162 | void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr); | ||
| 163 | |||
| 164 | static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr) | ||
| 165 | { | ||
| 166 | if (cx18_retry_mmio) | ||
| 167 | cx18_writeb_retry(cx, val, addr); | ||
| 168 | else | ||
| 169 | cx18_writeb_noretry(cx, val, addr); | ||
| 170 | } | ||
| 171 | |||
| 172 | |||
| 173 | static inline u32 cx18_readl_noretry(struct cx18 *cx, const void __iomem *addr) | ||
| 174 | { | ||
| 175 | u32 ret = readl(addr); | ||
| 176 | cx18_io_delay(cx); | ||
| 177 | return ret; | ||
| 178 | } | ||
| 179 | |||
| 180 | u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr); | ||
| 181 | |||
| 182 | static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr) | ||
| 183 | { | ||
| 184 | if (cx18_retry_mmio) | ||
| 185 | return cx18_readl_retry(cx, addr); | ||
| 186 | |||
| 187 | return cx18_readl_noretry(cx, addr); | ||
| 188 | } | ||
| 189 | |||
| 190 | |||
| 191 | static inline u16 cx18_readw_noretry(struct cx18 *cx, const void __iomem *addr) | ||
| 192 | { | ||
| 193 | u16 ret = readw(addr); | ||
| 194 | cx18_io_delay(cx); | ||
| 195 | return ret; | ||
| 196 | } | ||
| 197 | |||
| 198 | u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr); | ||
| 199 | |||
| 200 | static inline u16 cx18_readw(struct cx18 *cx, const void __iomem *addr) | ||
| 201 | { | ||
| 202 | if (cx18_retry_mmio) | ||
| 203 | return cx18_readw_retry(cx, addr); | ||
| 204 | |||
| 205 | return cx18_readw_noretry(cx, addr); | ||
| 206 | } | ||
| 207 | |||
| 208 | |||
| 209 | static inline u8 cx18_readb_noretry(struct cx18 *cx, const void __iomem *addr) | ||
| 210 | { | ||
| 211 | u8 ret = readb(addr); | ||
| 212 | cx18_io_delay(cx); | ||
| 213 | return ret; | ||
| 214 | } | ||
| 215 | |||
| 216 | u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr); | ||
| 217 | |||
| 218 | static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr) | ||
| 219 | { | ||
| 220 | if (cx18_retry_mmio) | ||
| 221 | return cx18_readb_retry(cx, addr); | ||
| 222 | |||
| 223 | return cx18_readb_noretry(cx, addr); | ||
| 224 | } | ||
| 225 | |||
| 226 | |||
| 227 | static inline | ||
| 228 | u32 cx18_write_sync_noretry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
| 229 | { | ||
| 230 | cx18_writel_noretry(cx, val, addr); | ||
| 231 | return cx18_readl_noretry(cx, addr); | ||
| 232 | } | ||
| 233 | |||
| 234 | static inline | ||
| 235 | u32 cx18_write_sync_retry(struct cx18 *cx, u32 val, void __iomem *addr) | ||
| 236 | { | ||
| 237 | cx18_writel_retry(cx, val, addr); | ||
| 238 | return cx18_readl_retry(cx, addr); | ||
| 239 | } | ||
| 240 | |||
| 241 | static inline u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr) | ||
| 242 | { | ||
| 243 | if (cx18_retry_mmio) | ||
| 244 | return cx18_write_sync_retry(cx, val, addr); | ||
| 245 | |||
| 246 | return cx18_write_sync_noretry(cx, val, addr); | ||
| 247 | } | ||
| 248 | |||
| 249 | |||
| 250 | void cx18_memcpy_fromio(struct cx18 *cx, void *to, | ||
| 251 | const void __iomem *from, unsigned int len); | ||
| 252 | void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count); | ||
| 253 | |||
| 254 | |||
| 255 | /* Access "register" region of CX23418 memory mapped I/O */ | ||
| 256 | static inline void cx18_write_reg_noretry(struct cx18 *cx, u32 val, u32 reg) | ||
| 257 | { | ||
| 258 | cx18_writel_noretry(cx, val, cx->reg_mem + reg); | ||
| 259 | } | ||
| 260 | |||
| 261 | static inline void cx18_write_reg_retry(struct cx18 *cx, u32 val, u32 reg) | ||
| 262 | { | ||
| 263 | cx18_writel_retry(cx, val, cx->reg_mem + reg); | ||
| 264 | } | ||
| 265 | |||
| 266 | static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) | ||
| 267 | { | ||
| 268 | if (cx18_retry_mmio) | ||
| 269 | cx18_write_reg_retry(cx, val, reg); | ||
| 270 | else | ||
| 271 | cx18_write_reg_noretry(cx, val, reg); | ||
| 272 | } | ||
| 273 | |||
| 274 | |||
| 275 | static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg) | ||
| 276 | { | ||
| 277 | return cx18_readl_noretry(cx, cx->reg_mem + reg); | ||
| 278 | } | ||
| 279 | |||
| 280 | static inline u32 cx18_read_reg_retry(struct cx18 *cx, u32 reg) | ||
| 281 | { | ||
| 282 | return cx18_readl_retry(cx, cx->reg_mem + reg); | ||
| 283 | } | ||
| 284 | |||
| 285 | static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg) | ||
| 286 | { | ||
| 287 | if (cx18_retry_mmio) | ||
| 288 | return cx18_read_reg_retry(cx, reg); | ||
| 289 | |||
| 290 | return cx18_read_reg_noretry(cx, reg); | ||
| 291 | } | ||
| 292 | |||
| 293 | |||
| 294 | static inline u32 cx18_write_reg_sync_noretry(struct cx18 *cx, u32 val, u32 reg) | ||
| 295 | { | ||
| 296 | return cx18_write_sync_noretry(cx, val, cx->reg_mem + reg); | ||
| 297 | } | ||
| 298 | |||
| 299 | static inline u32 cx18_write_reg_sync_retry(struct cx18 *cx, u32 val, u32 reg) | ||
| 300 | { | ||
| 301 | return cx18_write_sync_retry(cx, val, cx->reg_mem + reg); | ||
| 302 | } | ||
| 303 | |||
| 304 | static inline u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg) | ||
| 305 | { | ||
| 306 | if (cx18_retry_mmio) | ||
| 307 | return cx18_write_reg_sync_retry(cx, val, reg); | ||
| 308 | |||
| 309 | return cx18_write_reg_sync_noretry(cx, val, reg); | ||
| 310 | } | ||
| 311 | |||
| 312 | |||
| 313 | /* Access "encoder memory" region of CX23418 memory mapped I/O */ | ||
| 314 | static inline void cx18_write_enc_noretry(struct cx18 *cx, u32 val, u32 addr) | ||
| 315 | { | ||
| 316 | cx18_writel_noretry(cx, val, cx->enc_mem + addr); | ||
| 317 | } | ||
| 318 | |||
| 319 | static inline void cx18_write_enc_retry(struct cx18 *cx, u32 val, u32 addr) | ||
| 320 | { | ||
| 321 | cx18_writel_retry(cx, val, cx->enc_mem + addr); | ||
| 322 | } | ||
| 323 | |||
| 324 | static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr) | ||
| 325 | { | ||
| 326 | if (cx18_retry_mmio) | ||
| 327 | cx18_write_enc_retry(cx, val, addr); | ||
| 328 | else | ||
| 329 | cx18_write_enc_noretry(cx, val, addr); | ||
| 330 | } | ||
| 331 | |||
| 332 | |||
| 333 | static inline u32 cx18_read_enc_noretry(struct cx18 *cx, u32 addr) | ||
| 334 | { | ||
| 335 | return cx18_readl_noretry(cx, cx->enc_mem + addr); | ||
| 336 | } | ||
| 337 | |||
| 338 | static inline u32 cx18_read_enc_retry(struct cx18 *cx, u32 addr) | ||
| 339 | { | ||
| 340 | return cx18_readl_retry(cx, cx->enc_mem + addr); | ||
| 341 | } | ||
| 342 | |||
| 343 | static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr) | ||
| 344 | { | ||
| 345 | if (cx18_retry_mmio) | ||
| 346 | return cx18_read_enc_retry(cx, addr); | ||
| 347 | |||
| 348 | return cx18_read_enc_noretry(cx, addr); | ||
| 349 | } | ||
| 350 | |||
| 351 | static inline | ||
| 352 | u32 cx18_write_enc_sync_noretry(struct cx18 *cx, u32 val, u32 addr) | ||
| 353 | { | ||
| 354 | return cx18_write_sync_noretry(cx, val, cx->enc_mem + addr); | ||
| 355 | } | ||
| 356 | |||
| 357 | static inline | ||
| 358 | u32 cx18_write_enc_sync_retry(struct cx18 *cx, u32 val, u32 addr) | ||
| 359 | { | ||
| 360 | return cx18_write_sync_retry(cx, val, cx->enc_mem + addr); | ||
| 361 | } | ||
| 362 | |||
| 363 | static inline | ||
| 364 | u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr) | ||
| 365 | { | ||
| 366 | if (cx18_retry_mmio) | ||
| 367 | return cx18_write_enc_sync_retry(cx, val, addr); | ||
| 368 | |||
| 369 | return cx18_write_enc_sync_noretry(cx, val, addr); | ||
| 370 | } | ||
| 371 | |||
| 372 | void cx18_sw1_irq_enable(struct cx18 *cx, u32 val); | ||
| 373 | void cx18_sw1_irq_disable(struct cx18 *cx, u32 val); | ||
| 374 | void cx18_sw2_irq_enable(struct cx18 *cx, u32 val); | ||
| 375 | void cx18_sw2_irq_disable(struct cx18 *cx, u32 val); | ||
| 376 | void cx18_setup_page(struct cx18 *cx, u32 addr); | ||
| 377 | |||
| 378 | #endif /* CX18_IO_H */ | ||
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index a7f839631d6a..f0ca50f5fdde 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
| 25 | #include "cx18-io.h" | ||
| 25 | #include "cx18-version.h" | 26 | #include "cx18-version.h" |
| 26 | #include "cx18-mailbox.h" | 27 | #include "cx18-mailbox.h" |
| 27 | #include "cx18-i2c.h" | 28 | #include "cx18-i2c.h" |
| @@ -170,7 +171,6 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh, | |||
| 170 | { | 171 | { |
| 171 | struct cx18_open_id *id = fh; | 172 | struct cx18_open_id *id = fh; |
| 172 | struct cx18 *cx = id->cx; | 173 | struct cx18 *cx = id->cx; |
| 173 | |||
| 174 | int w = fmt->fmt.pix.width; | 174 | int w = fmt->fmt.pix.width; |
| 175 | int h = fmt->fmt.pix.height; | 175 | int h = fmt->fmt.pix.height; |
| 176 | 176 | ||
| @@ -202,8 +202,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, | |||
| 202 | struct cx18_open_id *id = fh; | 202 | struct cx18_open_id *id = fh; |
| 203 | struct cx18 *cx = id->cx; | 203 | struct cx18 *cx = id->cx; |
| 204 | int ret; | 204 | int ret; |
| 205 | int w = fmt->fmt.pix.width; | 205 | int w, h; |
| 206 | int h = fmt->fmt.pix.height; | ||
| 207 | 206 | ||
| 208 | ret = v4l2_prio_check(&cx->prio, &id->prio); | 207 | ret = v4l2_prio_check(&cx->prio, &id->prio); |
| 209 | if (ret) | 208 | if (ret) |
| @@ -212,6 +211,8 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh, | |||
| 212 | ret = cx18_try_fmt_vid_cap(file, fh, fmt); | 211 | ret = cx18_try_fmt_vid_cap(file, fh, fmt); |
| 213 | if (ret) | 212 | if (ret) |
| 214 | return ret; | 213 | return ret; |
| 214 | w = fmt->fmt.pix.width; | ||
| 215 | h = fmt->fmt.pix.height; | ||
| 215 | 216 | ||
| 216 | if (cx->params.width == w && cx->params.height == h) | 217 | if (cx->params.width == w && cx->params.height == h) |
| 217 | return 0; | 218 | return 0; |
| @@ -286,9 +287,9 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg) | |||
| 286 | 287 | ||
| 287 | spin_lock_irqsave(&cx18_cards_lock, flags); | 288 | spin_lock_irqsave(&cx18_cards_lock, flags); |
| 288 | if (cmd == VIDIOC_DBG_G_REGISTER) | 289 | if (cmd == VIDIOC_DBG_G_REGISTER) |
| 289 | regs->val = read_enc(regs->reg); | 290 | regs->val = cx18_read_enc(cx, regs->reg); |
| 290 | else | 291 | else |
| 291 | write_enc(regs->val, regs->reg); | 292 | cx18_write_enc(cx, regs->val, regs->reg); |
| 292 | spin_unlock_irqrestore(&cx18_cards_lock, flags); | 293 | spin_unlock_irqrestore(&cx18_cards_lock, flags); |
| 293 | return 0; | 294 | return 0; |
| 294 | } | 295 | } |
| @@ -345,7 +346,7 @@ static int cx18_querycap(struct file *file, void *fh, | |||
| 345 | 346 | ||
| 346 | strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); | 347 | strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); |
| 347 | strlcpy(vcap->card, cx->card_name, sizeof(vcap->card)); | 348 | strlcpy(vcap->card, cx->card_name, sizeof(vcap->card)); |
| 348 | strlcpy(vcap->bus_info, pci_name(cx->dev), sizeof(vcap->bus_info)); | 349 | snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(cx->dev)); |
| 349 | vcap->version = CX18_DRIVER_VERSION; /* version */ | 350 | vcap->version = CX18_DRIVER_VERSION; /* version */ |
| 350 | vcap->capabilities = cx->v4l2_cap; /* capabilities */ | 351 | vcap->capabilities = cx->v4l2_cap; /* capabilities */ |
| 351 | return 0; | 352 | return 0; |
| @@ -622,6 +623,7 @@ static int cx18_encoder_cmd(struct file *file, void *fh, | |||
| 622 | { | 623 | { |
| 623 | struct cx18_open_id *id = fh; | 624 | struct cx18_open_id *id = fh; |
| 624 | struct cx18 *cx = id->cx; | 625 | struct cx18 *cx = id->cx; |
| 626 | u32 h; | ||
| 625 | 627 | ||
| 626 | switch (enc->cmd) { | 628 | switch (enc->cmd) { |
| 627 | case V4L2_ENC_CMD_START: | 629 | case V4L2_ENC_CMD_START: |
| @@ -643,8 +645,14 @@ static int cx18_encoder_cmd(struct file *file, void *fh, | |||
| 643 | return -EPERM; | 645 | return -EPERM; |
| 644 | if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) | 646 | if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) |
| 645 | return 0; | 647 | return 0; |
| 648 | h = cx18_find_handle(cx); | ||
| 649 | if (h == CX18_INVALID_TASK_HANDLE) { | ||
| 650 | CX18_ERR("Can't find valid task handle for " | ||
| 651 | "V4L2_ENC_CMD_PAUSE\n"); | ||
| 652 | return -EBADFD; | ||
| 653 | } | ||
| 646 | cx18_mute(cx); | 654 | cx18_mute(cx); |
| 647 | cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx)); | 655 | cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h); |
| 648 | break; | 656 | break; |
| 649 | 657 | ||
| 650 | case V4L2_ENC_CMD_RESUME: | 658 | case V4L2_ENC_CMD_RESUME: |
| @@ -654,7 +662,13 @@ static int cx18_encoder_cmd(struct file *file, void *fh, | |||
| 654 | return -EPERM; | 662 | return -EPERM; |
| 655 | if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) | 663 | if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) |
| 656 | return 0; | 664 | return 0; |
| 657 | cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx)); | 665 | h = cx18_find_handle(cx); |
| 666 | if (h == CX18_INVALID_TASK_HANDLE) { | ||
| 667 | CX18_ERR("Can't find valid task handle for " | ||
| 668 | "V4L2_ENC_CMD_RESUME\n"); | ||
| 669 | return -EBADFD; | ||
| 670 | } | ||
| 671 | cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h); | ||
| 658 | cx18_unmute(cx); | 672 | cx18_unmute(cx); |
| 659 | break; | 673 | break; |
| 660 | 674 | ||
| @@ -731,12 +745,14 @@ static int cx18_log_status(struct file *file, void *fh) | |||
| 731 | continue; | 745 | continue; |
| 732 | CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", | 746 | CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", |
| 733 | s->name, s->s_flags, | 747 | s->name, s->s_flags, |
| 734 | (s->buffers - s->q_free.buffers) * 100 / s->buffers, | 748 | (s->buffers - atomic_read(&s->q_free.buffers)) |
| 749 | * 100 / s->buffers, | ||
| 735 | (s->buffers * s->buf_size) / 1024, s->buffers); | 750 | (s->buffers * s->buf_size) / 1024, s->buffers); |
| 736 | } | 751 | } |
| 737 | CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", | 752 | CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", |
| 738 | (long long)cx->mpg_data_received, | 753 | (long long)cx->mpg_data_received, |
| 739 | (long long)cx->vbi_data_inserted); | 754 | (long long)cx->vbi_data_inserted); |
| 755 | cx18_log_statistics(cx); | ||
| 740 | CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num); | 756 | CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num); |
| 741 | return 0; | 757 | return 0; |
| 742 | } | 758 | } |
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index ab218315c84b..360330f5463f 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include "cx18-driver.h" | 22 | #include "cx18-driver.h" |
| 23 | #include "cx18-io.h" | ||
| 23 | #include "cx18-firmware.h" | 24 | #include "cx18-firmware.h" |
| 24 | #include "cx18-fileops.h" | 25 | #include "cx18-fileops.h" |
| 25 | #include "cx18-queue.h" | 26 | #include "cx18-queue.h" |
| @@ -48,8 +49,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) | |||
| 48 | break; | 49 | break; |
| 49 | } | 50 | } |
| 50 | if (i == CX18_MAX_STREAMS) { | 51 | if (i == CX18_MAX_STREAMS) { |
| 51 | CX18_WARN("DMA done for unknown handle %d for stream %s\n", | 52 | CX18_WARN("Got DMA done notification for unknown/inactive" |
| 52 | handle, s->name); | 53 | " handle %d\n", handle); |
| 53 | mb->error = CXERR_NOT_OPEN; | 54 | mb->error = CXERR_NOT_OPEN; |
| 54 | mb->cmd = 0; | 55 | mb->cmd = 0; |
| 55 | cx18_mb_ack(cx, mb); | 56 | cx18_mb_ack(cx, mb); |
| @@ -60,8 +61,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) | |||
| 60 | if (mb->args[2] != 1) | 61 | if (mb->args[2] != 1) |
| 61 | CX18_WARN("Ack struct = %d for %s\n", | 62 | CX18_WARN("Ack struct = %d for %s\n", |
| 62 | mb->args[2], s->name); | 63 | mb->args[2], s->name); |
| 63 | id = read_enc(off); | 64 | id = cx18_read_enc(cx, off); |
| 64 | buf = cx18_queue_get_buf_irq(s, id, read_enc(off + 4)); | 65 | buf = cx18_queue_get_buf_irq(s, id, cx18_read_enc(cx, off + 4)); |
| 65 | CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); | 66 | CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); |
| 66 | if (buf) { | 67 | if (buf) { |
| 67 | cx18_buf_sync_for_cpu(s, buf); | 68 | cx18_buf_sync_for_cpu(s, buf); |
| @@ -81,7 +82,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) | |||
| 81 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); | 82 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); |
| 82 | } else { | 83 | } else { |
| 83 | CX18_WARN("Could not find buf %d for stream %s\n", | 84 | CX18_WARN("Could not find buf %d for stream %s\n", |
| 84 | read_enc(off), s->name); | 85 | cx18_read_enc(cx, off), s->name); |
| 85 | } | 86 | } |
| 86 | mb->error = 0; | 87 | mb->error = 0; |
| 87 | mb->cmd = 0; | 88 | mb->cmd = 0; |
| @@ -97,8 +98,8 @@ static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb) | |||
| 97 | char *p; | 98 | char *p; |
| 98 | 99 | ||
| 99 | if (mb->args[1]) { | 100 | if (mb->args[1]) { |
| 100 | setup_page(mb->args[1]); | 101 | cx18_setup_page(cx, mb->args[1]); |
| 101 | memcpy_fromio(str, cx->enc_mem + mb->args[1], 252); | 102 | cx18_memcpy_fromio(cx, str, cx->enc_mem + mb->args[1], 252); |
| 102 | str[252] = 0; | 103 | str[252] = 0; |
| 103 | } | 104 | } |
| 104 | cx18_mb_ack(cx, mb); | 105 | cx18_mb_ack(cx, mb); |
| @@ -113,7 +114,7 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1) | |||
| 113 | struct cx18_mailbox mb; | 114 | struct cx18_mailbox mb; |
| 114 | 115 | ||
| 115 | if (sw1 & IRQ_CPU_TO_EPU) { | 116 | if (sw1 & IRQ_CPU_TO_EPU) { |
| 116 | memcpy_fromio(&mb, &cx->scb->cpu2epu_mb, sizeof(mb)); | 117 | cx18_memcpy_fromio(cx, &mb, &cx->scb->cpu2epu_mb, sizeof(mb)); |
| 117 | mb.error = 0; | 118 | mb.error = 0; |
| 118 | 119 | ||
| 119 | switch (mb.cmd) { | 120 | switch (mb.cmd) { |
| @@ -141,16 +142,16 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) | |||
| 141 | 142 | ||
| 142 | spin_lock(&cx->dma_reg_lock); | 143 | spin_lock(&cx->dma_reg_lock); |
| 143 | 144 | ||
| 144 | hw2_mask = read_reg(HW2_INT_MASK5_PCI); | 145 | hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); |
| 145 | hw2 = read_reg(HW2_INT_CLR_STATUS) & hw2_mask; | 146 | hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; |
| 146 | sw2_mask = read_reg(SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; | 147 | sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; |
| 147 | sw2 = read_reg(SW2_INT_STATUS) & sw2_mask; | 148 | sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; |
| 148 | sw1_mask = read_reg(SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; | 149 | sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; |
| 149 | sw1 = read_reg(SW1_INT_STATUS) & sw1_mask; | 150 | sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; |
| 150 | 151 | ||
| 151 | write_reg(sw2&sw2_mask, SW2_INT_STATUS); | 152 | cx18_write_reg(cx, sw2&sw2_mask, SW2_INT_STATUS); |
| 152 | write_reg(sw1&sw1_mask, SW1_INT_STATUS); | 153 | cx18_write_reg(cx, sw1&sw1_mask, SW1_INT_STATUS); |
| 153 | write_reg(hw2&hw2_mask, HW2_INT_CLR_STATUS); | 154 | cx18_write_reg(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS); |
| 154 | 155 | ||
| 155 | if (sw1 || sw2 || hw2) | 156 | if (sw1 || sw2 || hw2) |
| 156 | CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); | 157 | CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); |
| @@ -161,15 +162,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) | |||
| 161 | */ | 162 | */ |
| 162 | 163 | ||
| 163 | if (sw2) { | 164 | if (sw2) { |
| 164 | if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) | | 165 | if (sw2 & (cx18_readl(cx, &cx->scb->cpu2hpu_irq_ack) | |
| 165 | readl(&cx->scb->cpu2epu_irq_ack))) | 166 | cx18_readl(cx, &cx->scb->cpu2epu_irq_ack))) |
| 166 | wake_up(&cx->mb_cpu_waitq); | 167 | wake_up(&cx->mb_cpu_waitq); |
| 167 | if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) | | 168 | if (sw2 & (cx18_readl(cx, &cx->scb->apu2hpu_irq_ack) | |
| 168 | readl(&cx->scb->apu2epu_irq_ack))) | 169 | cx18_readl(cx, &cx->scb->apu2epu_irq_ack))) |
| 169 | wake_up(&cx->mb_apu_waitq); | 170 | wake_up(&cx->mb_apu_waitq); |
| 170 | if (sw2 & readl(&cx->scb->epu2hpu_irq_ack)) | 171 | if (sw2 & cx18_readl(cx, &cx->scb->epu2hpu_irq_ack)) |
| 171 | wake_up(&cx->mb_epu_waitq); | 172 | wake_up(&cx->mb_epu_waitq); |
| 172 | if (sw2 & readl(&cx->scb->hpu2epu_irq_ack)) | 173 | if (sw2 & cx18_readl(cx, &cx->scb->hpu2epu_irq_ack)) |
| 173 | wake_up(&cx->mb_hpu_waitq); | 174 | wake_up(&cx->mb_hpu_waitq); |
| 174 | } | 175 | } |
| 175 | 176 | ||
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 93177514e846..9d18dd22de76 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <stdarg.h> | 22 | #include <stdarg.h> |
| 23 | 23 | ||
| 24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
| 25 | #include "cx18-io.h" | ||
| 25 | #include "cx18-scb.h" | 26 | #include "cx18-scb.h" |
| 26 | #include "cx18-irq.h" | 27 | #include "cx18-irq.h" |
| 27 | #include "cx18-mailbox.h" | 28 | #include "cx18-mailbox.h" |
| @@ -82,6 +83,7 @@ static const struct cx18_api_info api_info[] = { | |||
| 82 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), | 83 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), |
| 83 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), | 84 | API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), |
| 84 | API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), | 85 | API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), |
| 86 | API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, 0), | ||
| 85 | API_ENTRY(0, 0, 0), | 87 | API_ENTRY(0, 0, 0), |
| 86 | }; | 88 | }; |
| 87 | 89 | ||
| @@ -105,20 +107,20 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu | |||
| 105 | switch (rpu) { | 107 | switch (rpu) { |
| 106 | case APU: | 108 | case APU: |
| 107 | mb = &cx->scb->epu2apu_mb; | 109 | mb = &cx->scb->epu2apu_mb; |
| 108 | *state = readl(&cx->scb->apu_state); | 110 | *state = cx18_readl(cx, &cx->scb->apu_state); |
| 109 | *irq = readl(&cx->scb->epu2apu_irq); | 111 | *irq = cx18_readl(cx, &cx->scb->epu2apu_irq); |
| 110 | break; | 112 | break; |
| 111 | 113 | ||
| 112 | case CPU: | 114 | case CPU: |
| 113 | mb = &cx->scb->epu2cpu_mb; | 115 | mb = &cx->scb->epu2cpu_mb; |
| 114 | *state = readl(&cx->scb->cpu_state); | 116 | *state = cx18_readl(cx, &cx->scb->cpu_state); |
| 115 | *irq = readl(&cx->scb->epu2cpu_irq); | 117 | *irq = cx18_readl(cx, &cx->scb->epu2cpu_irq); |
| 116 | break; | 118 | break; |
| 117 | 119 | ||
| 118 | case HPU: | 120 | case HPU: |
| 119 | mb = &cx->scb->epu2hpu_mb; | 121 | mb = &cx->scb->epu2hpu_mb; |
| 120 | *state = readl(&cx->scb->hpu_state); | 122 | *state = cx18_readl(cx, &cx->scb->hpu_state); |
| 121 | *irq = readl(&cx->scb->epu2hpu_irq); | 123 | *irq = cx18_readl(cx, &cx->scb->epu2hpu_irq); |
| 122 | break; | 124 | break; |
| 123 | } | 125 | } |
| 124 | 126 | ||
| @@ -126,8 +128,8 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu | |||
| 126 | return mb; | 128 | return mb; |
| 127 | 129 | ||
| 128 | do { | 130 | do { |
| 129 | *req = readl(&mb->request); | 131 | *req = cx18_readl(cx, &mb->request); |
| 130 | ack = readl(&mb->ack); | 132 | ack = cx18_readl(cx, &mb->ack); |
| 131 | wait_count++; | 133 | wait_count++; |
| 132 | } while (*req != ack && wait_count < 600); | 134 | } while (*req != ack && wait_count < 600); |
| 133 | 135 | ||
| @@ -172,9 +174,9 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) | |||
| 172 | return -EINVAL; | 174 | return -EINVAL; |
| 173 | } | 175 | } |
| 174 | 176 | ||
| 175 | setup_page(SCB_OFFSET); | 177 | cx18_setup_page(cx, SCB_OFFSET); |
| 176 | write_sync(mb->request, &ack_mb->ack); | 178 | cx18_write_sync(cx, mb->request, &ack_mb->ack); |
| 177 | write_reg(ack_irq, SW2_INT_SET); | 179 | cx18_write_reg(cx, ack_irq, SW2_INT_SET); |
| 178 | return 0; | 180 | return 0; |
| 179 | } | 181 | } |
| 180 | 182 | ||
| @@ -199,7 +201,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
| 199 | CX18_DEBUG_HI_API("%s\n", info->name); | 201 | CX18_DEBUG_HI_API("%s\n", info->name); |
| 200 | else | 202 | else |
| 201 | CX18_DEBUG_API("%s\n", info->name); | 203 | CX18_DEBUG_API("%s\n", info->name); |
| 202 | setup_page(SCB_OFFSET); | 204 | cx18_setup_page(cx, SCB_OFFSET); |
| 203 | mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req); | 205 | mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req); |
| 204 | 206 | ||
| 205 | if (mb == NULL) { | 207 | if (mb == NULL) { |
| @@ -208,11 +210,11 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
| 208 | } | 210 | } |
| 209 | 211 | ||
| 210 | oldreq = req - 1; | 212 | oldreq = req - 1; |
| 211 | writel(cmd, &mb->cmd); | 213 | cx18_writel(cx, cmd, &mb->cmd); |
| 212 | for (i = 0; i < args; i++) | 214 | for (i = 0; i < args; i++) |
| 213 | writel(data[i], &mb->args[i]); | 215 | cx18_writel(cx, data[i], &mb->args[i]); |
| 214 | writel(0, &mb->error); | 216 | cx18_writel(cx, 0, &mb->error); |
| 215 | writel(req, &mb->request); | 217 | cx18_writel(cx, req, &mb->request); |
| 216 | 218 | ||
| 217 | switch (info->rpu) { | 219 | switch (info->rpu) { |
| 218 | case APU: waitq = &cx->mb_apu_waitq; break; | 220 | case APU: waitq = &cx->mb_apu_waitq; break; |
| @@ -223,9 +225,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
| 223 | } | 225 | } |
| 224 | if (info->flags & API_FAST) | 226 | if (info->flags & API_FAST) |
| 225 | timeout /= 2; | 227 | timeout /= 2; |
| 226 | write_reg(irq, SW1_INT_SET); | 228 | cx18_write_reg(cx, irq, SW1_INT_SET); |
| 227 | 229 | ||
| 228 | while (!sig && readl(&mb->ack) != readl(&mb->request) && cnt < 660) { | 230 | while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) |
| 231 | && cnt < 660) { | ||
| 229 | if (cnt > 200 && !in_atomic()) | 232 | if (cnt > 200 && !in_atomic()) |
| 230 | sig = cx18_msleep_timeout(10, 1); | 233 | sig = cx18_msleep_timeout(10, 1); |
| 231 | cnt++; | 234 | cnt++; |
| @@ -233,13 +236,13 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
| 233 | if (sig) | 236 | if (sig) |
| 234 | return -EINTR; | 237 | return -EINTR; |
| 235 | if (cnt == 660) { | 238 | if (cnt == 660) { |
| 236 | writel(oldreq, &mb->request); | 239 | cx18_writel(cx, oldreq, &mb->request); |
| 237 | CX18_ERR("mb %s failed\n", info->name); | 240 | CX18_ERR("mb %s failed\n", info->name); |
| 238 | return -EINVAL; | 241 | return -EINVAL; |
| 239 | } | 242 | } |
| 240 | for (i = 0; i < MAX_MB_ARGUMENTS; i++) | 243 | for (i = 0; i < MAX_MB_ARGUMENTS; i++) |
| 241 | data[i] = readl(&mb->args[i]); | 244 | data[i] = cx18_readl(cx, &mb->args[i]); |
| 242 | err = readl(&mb->error); | 245 | err = cx18_readl(cx, &mb->error); |
| 243 | if (!in_atomic() && (info->flags & API_SLOW)) | 246 | if (!in_atomic() && (info->flags & API_SLOW)) |
| 244 | cx18_msleep_timeout(300, 0); | 247 | cx18_msleep_timeout(300, 0); |
| 245 | if (err) | 248 | if (err) |
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index dbe792ac3001..a33ba04a2686 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c | |||
| @@ -37,8 +37,7 @@ void cx18_buf_swap(struct cx18_buffer *buf) | |||
| 37 | void cx18_queue_init(struct cx18_queue *q) | 37 | void cx18_queue_init(struct cx18_queue *q) |
| 38 | { | 38 | { |
| 39 | INIT_LIST_HEAD(&q->list); | 39 | INIT_LIST_HEAD(&q->list); |
| 40 | q->buffers = 0; | 40 | atomic_set(&q->buffers, 0); |
| 41 | q->length = 0; | ||
| 42 | q->bytesused = 0; | 41 | q->bytesused = 0; |
| 43 | } | 42 | } |
| 44 | 43 | ||
| @@ -55,8 +54,7 @@ void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, | |||
| 55 | } | 54 | } |
| 56 | spin_lock_irqsave(&s->qlock, flags); | 55 | spin_lock_irqsave(&s->qlock, flags); |
| 57 | list_add_tail(&buf->list, &q->list); | 56 | list_add_tail(&buf->list, &q->list); |
| 58 | q->buffers++; | 57 | atomic_inc(&q->buffers); |
| 59 | q->length += s->buf_size; | ||
| 60 | q->bytesused += buf->bytesused - buf->readpos; | 58 | q->bytesused += buf->bytesused - buf->readpos; |
| 61 | spin_unlock_irqrestore(&s->qlock, flags); | 59 | spin_unlock_irqrestore(&s->qlock, flags); |
| 62 | } | 60 | } |
| @@ -70,8 +68,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) | |||
| 70 | if (!list_empty(&q->list)) { | 68 | if (!list_empty(&q->list)) { |
| 71 | buf = list_entry(q->list.next, struct cx18_buffer, list); | 69 | buf = list_entry(q->list.next, struct cx18_buffer, list); |
| 72 | list_del_init(q->list.next); | 70 | list_del_init(q->list.next); |
| 73 | q->buffers--; | 71 | atomic_dec(&q->buffers); |
| 74 | q->length -= s->buf_size; | ||
| 75 | q->bytesused -= buf->bytesused - buf->readpos; | 72 | q->bytesused -= buf->bytesused - buf->readpos; |
| 76 | } | 73 | } |
| 77 | spin_unlock_irqrestore(&s->qlock, flags); | 74 | spin_unlock_irqrestore(&s->qlock, flags); |
| @@ -95,10 +92,8 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id, | |||
| 95 | /* the transport buffers are handled differently, | 92 | /* the transport buffers are handled differently, |
| 96 | they are not moved to the full queue */ | 93 | they are not moved to the full queue */ |
| 97 | if (s->type != CX18_ENC_STREAM_TYPE_TS) { | 94 | if (s->type != CX18_ENC_STREAM_TYPE_TS) { |
| 98 | s->q_free.buffers--; | 95 | atomic_dec(&s->q_free.buffers); |
| 99 | s->q_free.length -= s->buf_size; | 96 | atomic_inc(&s->q_full.buffers); |
| 100 | s->q_full.buffers++; | ||
| 101 | s->q_full.length += s->buf_size; | ||
| 102 | s->q_full.bytesused += buf->bytesused; | 97 | s->q_full.bytesused += buf->bytesused; |
| 103 | list_move_tail(&buf->list, &s->q_full.list); | 98 | list_move_tail(&buf->list, &s->q_full.list); |
| 104 | } | 99 | } |
| @@ -124,8 +119,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) | |||
| 124 | buf = list_entry(q->list.next, struct cx18_buffer, list); | 119 | buf = list_entry(q->list.next, struct cx18_buffer, list); |
| 125 | list_move_tail(q->list.next, &s->q_free.list); | 120 | list_move_tail(q->list.next, &s->q_free.list); |
| 126 | buf->bytesused = buf->readpos = buf->b_flags = 0; | 121 | buf->bytesused = buf->readpos = buf->b_flags = 0; |
| 127 | s->q_free.buffers++; | 122 | atomic_inc(&s->q_free.buffers); |
| 128 | s->q_free.length += s->buf_size; | ||
| 129 | } | 123 | } |
| 130 | cx18_queue_init(q); | 124 | cx18_queue_init(q); |
| 131 | spin_unlock_irqrestore(&s->qlock, flags); | 125 | spin_unlock_irqrestore(&s->qlock, flags); |
diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c index 30bc803e30da..f56d3772aa67 100644 --- a/drivers/media/video/cx18/cx18-scb.c +++ b/drivers/media/video/cx18/cx18-scb.c | |||
| @@ -20,102 +20,103 @@ | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include "cx18-driver.h" | 22 | #include "cx18-driver.h" |
| 23 | #include "cx18-io.h" | ||
| 23 | #include "cx18-scb.h" | 24 | #include "cx18-scb.h" |
| 24 | 25 | ||
| 25 | void cx18_init_scb(struct cx18 *cx) | 26 | void cx18_init_scb(struct cx18 *cx) |
| 26 | { | 27 | { |
| 27 | setup_page(SCB_OFFSET); | 28 | cx18_setup_page(cx, SCB_OFFSET); |
| 28 | memset_io(cx->scb, 0, 0x10000); | 29 | cx18_memset_io(cx, cx->scb, 0, 0x10000); |
| 29 | 30 | ||
| 30 | writel(IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq); | 31 | cx18_writel(cx, IRQ_APU_TO_CPU, &cx->scb->apu2cpu_irq); |
| 31 | writel(IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack); | 32 | cx18_writel(cx, IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack); |
| 32 | writel(IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq); | 33 | cx18_writel(cx, IRQ_HPU_TO_CPU, &cx->scb->hpu2cpu_irq); |
| 33 | writel(IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack); | 34 | cx18_writel(cx, IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack); |
| 34 | writel(IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq); | 35 | cx18_writel(cx, IRQ_PPU_TO_CPU, &cx->scb->ppu2cpu_irq); |
| 35 | writel(IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack); | 36 | cx18_writel(cx, IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack); |
| 36 | writel(IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq); | 37 | cx18_writel(cx, IRQ_EPU_TO_CPU, &cx->scb->epu2cpu_irq); |
| 37 | writel(IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack); | 38 | cx18_writel(cx, IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack); |
| 38 | 39 | ||
| 39 | writel(IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq); | 40 | cx18_writel(cx, IRQ_CPU_TO_APU, &cx->scb->cpu2apu_irq); |
| 40 | writel(IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack); | 41 | cx18_writel(cx, IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack); |
| 41 | writel(IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq); | 42 | cx18_writel(cx, IRQ_HPU_TO_APU, &cx->scb->hpu2apu_irq); |
| 42 | writel(IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack); | 43 | cx18_writel(cx, IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack); |
| 43 | writel(IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq); | 44 | cx18_writel(cx, IRQ_PPU_TO_APU, &cx->scb->ppu2apu_irq); |
| 44 | writel(IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack); | 45 | cx18_writel(cx, IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack); |
| 45 | writel(IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq); | 46 | cx18_writel(cx, IRQ_EPU_TO_APU, &cx->scb->epu2apu_irq); |
| 46 | writel(IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack); | 47 | cx18_writel(cx, IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack); |
| 47 | 48 | ||
| 48 | writel(IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq); | 49 | cx18_writel(cx, IRQ_CPU_TO_HPU, &cx->scb->cpu2hpu_irq); |
| 49 | writel(IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack); | 50 | cx18_writel(cx, IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack); |
| 50 | writel(IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq); | 51 | cx18_writel(cx, IRQ_APU_TO_HPU, &cx->scb->apu2hpu_irq); |
| 51 | writel(IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack); | 52 | cx18_writel(cx, IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack); |
| 52 | writel(IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq); | 53 | cx18_writel(cx, IRQ_PPU_TO_HPU, &cx->scb->ppu2hpu_irq); |
| 53 | writel(IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack); | 54 | cx18_writel(cx, IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack); |
| 54 | writel(IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq); | 55 | cx18_writel(cx, IRQ_EPU_TO_HPU, &cx->scb->epu2hpu_irq); |
| 55 | writel(IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack); | 56 | cx18_writel(cx, IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack); |
| 56 | 57 | ||
| 57 | writel(IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq); | 58 | cx18_writel(cx, IRQ_CPU_TO_PPU, &cx->scb->cpu2ppu_irq); |
| 58 | writel(IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack); | 59 | cx18_writel(cx, IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack); |
| 59 | writel(IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq); | 60 | cx18_writel(cx, IRQ_APU_TO_PPU, &cx->scb->apu2ppu_irq); |
| 60 | writel(IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack); | 61 | cx18_writel(cx, IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack); |
| 61 | writel(IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq); | 62 | cx18_writel(cx, IRQ_HPU_TO_PPU, &cx->scb->hpu2ppu_irq); |
| 62 | writel(IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack); | 63 | cx18_writel(cx, IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack); |
| 63 | writel(IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq); | 64 | cx18_writel(cx, IRQ_EPU_TO_PPU, &cx->scb->epu2ppu_irq); |
| 64 | writel(IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack); | 65 | cx18_writel(cx, IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack); |
| 65 | 66 | ||
| 66 | writel(IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq); | 67 | cx18_writel(cx, IRQ_CPU_TO_EPU, &cx->scb->cpu2epu_irq); |
| 67 | writel(IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack); | 68 | cx18_writel(cx, IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack); |
| 68 | writel(IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq); | 69 | cx18_writel(cx, IRQ_APU_TO_EPU, &cx->scb->apu2epu_irq); |
| 69 | writel(IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack); | 70 | cx18_writel(cx, IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack); |
| 70 | writel(IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq); | 71 | cx18_writel(cx, IRQ_HPU_TO_EPU, &cx->scb->hpu2epu_irq); |
| 71 | writel(IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack); | 72 | cx18_writel(cx, IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack); |
| 72 | writel(IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq); | 73 | cx18_writel(cx, IRQ_PPU_TO_EPU, &cx->scb->ppu2epu_irq); |
| 73 | writel(IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack); | 74 | cx18_writel(cx, IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack); |
| 74 | 75 | ||
| 75 | writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb), | 76 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb), |
| 76 | &cx->scb->apu2cpu_mb_offset); | 77 | &cx->scb->apu2cpu_mb_offset); |
| 77 | writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb), | 78 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb), |
| 78 | &cx->scb->hpu2cpu_mb_offset); | 79 | &cx->scb->hpu2cpu_mb_offset); |
| 79 | writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb), | 80 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb), |
| 80 | &cx->scb->ppu2cpu_mb_offset); | 81 | &cx->scb->ppu2cpu_mb_offset); |
| 81 | writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb), | 82 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb), |
| 82 | &cx->scb->epu2cpu_mb_offset); | 83 | &cx->scb->epu2cpu_mb_offset); |
| 83 | writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb), | 84 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb), |
| 84 | &cx->scb->cpu2apu_mb_offset); | 85 | &cx->scb->cpu2apu_mb_offset); |
| 85 | writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb), | 86 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb), |
| 86 | &cx->scb->hpu2apu_mb_offset); | 87 | &cx->scb->hpu2apu_mb_offset); |
| 87 | writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb), | 88 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb), |
| 88 | &cx->scb->ppu2apu_mb_offset); | 89 | &cx->scb->ppu2apu_mb_offset); |
| 89 | writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb), | 90 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb), |
| 90 | &cx->scb->epu2apu_mb_offset); | 91 | &cx->scb->epu2apu_mb_offset); |
| 91 | writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb), | 92 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb), |
| 92 | &cx->scb->cpu2hpu_mb_offset); | 93 | &cx->scb->cpu2hpu_mb_offset); |
| 93 | writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb), | 94 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb), |
| 94 | &cx->scb->apu2hpu_mb_offset); | 95 | &cx->scb->apu2hpu_mb_offset); |
| 95 | writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb), | 96 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb), |
| 96 | &cx->scb->ppu2hpu_mb_offset); | 97 | &cx->scb->ppu2hpu_mb_offset); |
| 97 | writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb), | 98 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb), |
| 98 | &cx->scb->epu2hpu_mb_offset); | 99 | &cx->scb->epu2hpu_mb_offset); |
| 99 | writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb), | 100 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb), |
| 100 | &cx->scb->cpu2ppu_mb_offset); | 101 | &cx->scb->cpu2ppu_mb_offset); |
| 101 | writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb), | 102 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb), |
| 102 | &cx->scb->apu2ppu_mb_offset); | 103 | &cx->scb->apu2ppu_mb_offset); |
| 103 | writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb), | 104 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb), |
| 104 | &cx->scb->hpu2ppu_mb_offset); | 105 | &cx->scb->hpu2ppu_mb_offset); |
| 105 | writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb), | 106 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb), |
| 106 | &cx->scb->epu2ppu_mb_offset); | 107 | &cx->scb->epu2ppu_mb_offset); |
| 107 | writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb), | 108 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb), |
| 108 | &cx->scb->cpu2epu_mb_offset); | 109 | &cx->scb->cpu2epu_mb_offset); |
| 109 | writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb), | 110 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb), |
| 110 | &cx->scb->apu2epu_mb_offset); | 111 | &cx->scb->apu2epu_mb_offset); |
| 111 | writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb), | 112 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb), |
| 112 | &cx->scb->hpu2epu_mb_offset); | 113 | &cx->scb->hpu2epu_mb_offset); |
| 113 | writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb), | 114 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb), |
| 114 | &cx->scb->ppu2epu_mb_offset); | 115 | &cx->scb->ppu2epu_mb_offset); |
| 115 | 116 | ||
| 116 | writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu_state), | 117 | cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state), |
| 117 | &cx->scb->ipc_offset); | 118 | &cx->scb->ipc_offset); |
| 118 | 119 | ||
| 119 | writel(1, &cx->scb->hpu_state); | 120 | cx18_writel(cx, 1, &cx->scb->hpu_state); |
| 120 | writel(1, &cx->scb->epu_state); | 121 | cx18_writel(cx, 1, &cx->scb->epu_state); |
| 121 | } | 122 | } |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 0da57f583bf7..0c8e7542cf60 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
| 25 | #include "cx18-io.h" | ||
| 25 | #include "cx18-fileops.h" | 26 | #include "cx18-fileops.h" |
| 26 | #include "cx18-mailbox.h" | 27 | #include "cx18-mailbox.h" |
| 27 | #include "cx18-i2c.h" | 28 | #include "cx18-i2c.h" |
| @@ -56,7 +57,7 @@ static struct file_operations cx18_v4l2_enc_fops = { | |||
| 56 | static struct { | 57 | static struct { |
| 57 | const char *name; | 58 | const char *name; |
| 58 | int vfl_type; | 59 | int vfl_type; |
| 59 | int minor_offset; | 60 | int num_offset; |
| 60 | int dma; | 61 | int dma; |
| 61 | enum v4l2_buf_type buf_type; | 62 | enum v4l2_buf_type buf_type; |
| 62 | struct file_operations *fops; | 63 | struct file_operations *fops; |
| @@ -119,7 +120,7 @@ static void cx18_stream_init(struct cx18 *cx, int type) | |||
| 119 | s->cx = cx; | 120 | s->cx = cx; |
| 120 | s->type = type; | 121 | s->type = type; |
| 121 | s->name = cx18_stream_info[type].name; | 122 | s->name = cx18_stream_info[type].name; |
| 122 | s->handle = 0xffffffff; | 123 | s->handle = CX18_INVALID_TASK_HANDLE; |
| 123 | 124 | ||
| 124 | s->dma = cx18_stream_info[type].dma; | 125 | s->dma = cx18_stream_info[type].dma; |
| 125 | s->buf_size = cx->stream_buf_size[type]; | 126 | s->buf_size = cx->stream_buf_size[type]; |
| @@ -143,8 +144,8 @@ static int cx18_prep_dev(struct cx18 *cx, int type) | |||
| 143 | { | 144 | { |
| 144 | struct cx18_stream *s = &cx->streams[type]; | 145 | struct cx18_stream *s = &cx->streams[type]; |
| 145 | u32 cap = cx->v4l2_cap; | 146 | u32 cap = cx->v4l2_cap; |
| 146 | int minor_offset = cx18_stream_info[type].minor_offset; | 147 | int num_offset = cx18_stream_info[type].num_offset; |
| 147 | int minor; | 148 | int num = cx->num + cx18_first_minor + num_offset; |
| 148 | 149 | ||
| 149 | /* These four fields are always initialized. If v4l2dev == NULL, then | 150 | /* These four fields are always initialized. If v4l2dev == NULL, then |
| 150 | this stream is not in use. In that case no other fields but these | 151 | this stream is not in use. In that case no other fields but these |
| @@ -163,9 +164,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type) | |||
| 163 | !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE))) | 164 | !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE))) |
| 164 | return 0; | 165 | return 0; |
| 165 | 166 | ||
| 166 | /* card number + user defined offset + device offset */ | ||
| 167 | minor = cx->num + cx18_first_minor + minor_offset; | ||
| 168 | |||
| 169 | /* User explicitly selected 0 buffers for these streams, so don't | 167 | /* User explicitly selected 0 buffers for these streams, so don't |
| 170 | create them. */ | 168 | create them. */ |
| 171 | if (cx18_stream_info[type].dma != PCI_DMA_NONE && | 169 | if (cx18_stream_info[type].dma != PCI_DMA_NONE && |
| @@ -176,7 +174,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) | |||
| 176 | 174 | ||
| 177 | cx18_stream_init(cx, type); | 175 | cx18_stream_init(cx, type); |
| 178 | 176 | ||
| 179 | if (minor_offset == -1) | 177 | if (num_offset == -1) |
| 180 | return 0; | 178 | return 0; |
| 181 | 179 | ||
| 182 | /* allocate and initialize the v4l2 video device structure */ | 180 | /* allocate and initialize the v4l2 video device structure */ |
| @@ -190,7 +188,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type) | |||
| 190 | snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d", | 188 | snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d", |
| 191 | cx->num); | 189 | cx->num); |
| 192 | 190 | ||
| 193 | s->v4l2dev->minor = minor; | 191 | s->v4l2dev->num = num; |
| 194 | s->v4l2dev->parent = &cx->dev->dev; | 192 | s->v4l2dev->parent = &cx->dev->dev; |
| 195 | s->v4l2dev->fops = cx18_stream_info[type].fops; | 193 | s->v4l2dev->fops = cx18_stream_info[type].fops; |
| 196 | s->v4l2dev->release = video_device_release; | 194 | s->v4l2dev->release = video_device_release; |
| @@ -226,7 +224,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) | |||
| 226 | { | 224 | { |
| 227 | struct cx18_stream *s = &cx->streams[type]; | 225 | struct cx18_stream *s = &cx->streams[type]; |
| 228 | int vfl_type = cx18_stream_info[type].vfl_type; | 226 | int vfl_type = cx18_stream_info[type].vfl_type; |
| 229 | int minor; | 227 | int num; |
| 230 | 228 | ||
| 231 | /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? | 229 | /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? |
| 232 | * We need a VFL_TYPE_TS defined. | 230 | * We need a VFL_TYPE_TS defined. |
| @@ -244,38 +242,44 @@ static int cx18_reg_dev(struct cx18 *cx, int type) | |||
| 244 | if (s->v4l2dev == NULL) | 242 | if (s->v4l2dev == NULL) |
| 245 | return 0; | 243 | return 0; |
| 246 | 244 | ||
| 247 | minor = s->v4l2dev->minor; | 245 | num = s->v4l2dev->num; |
| 246 | /* card number + user defined offset + device offset */ | ||
| 247 | if (type != CX18_ENC_STREAM_TYPE_MPG) { | ||
| 248 | struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG]; | ||
| 249 | |||
| 250 | if (s_mpg->v4l2dev) | ||
| 251 | num = s_mpg->v4l2dev->num + cx18_stream_info[type].num_offset; | ||
| 252 | } | ||
| 248 | 253 | ||
| 249 | /* Register device. First try the desired minor, then any free one. */ | 254 | /* Register device. First try the desired minor, then any free one. */ |
| 250 | if (video_register_device(s->v4l2dev, vfl_type, minor) && | 255 | if (video_register_device(s->v4l2dev, vfl_type, num)) { |
| 251 | video_register_device(s->v4l2dev, vfl_type, -1)) { | 256 | CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n", |
| 252 | CX18_ERR("Couldn't register v4l2 device for %s minor %d\n", | 257 | s->name, num); |
| 253 | s->name, minor); | ||
| 254 | video_device_release(s->v4l2dev); | 258 | video_device_release(s->v4l2dev); |
| 255 | s->v4l2dev = NULL; | 259 | s->v4l2dev = NULL; |
| 256 | return -ENOMEM; | 260 | return -ENOMEM; |
| 257 | } | 261 | } |
| 258 | minor = s->v4l2dev->minor; | 262 | num = s->v4l2dev->num; |
| 259 | 263 | ||
| 260 | switch (vfl_type) { | 264 | switch (vfl_type) { |
| 261 | case VFL_TYPE_GRABBER: | 265 | case VFL_TYPE_GRABBER: |
| 262 | CX18_INFO("Registered device video%d for %s (%d MB)\n", | 266 | CX18_INFO("Registered device video%d for %s (%d MB)\n", |
| 263 | minor, s->name, cx->options.megabytes[type]); | 267 | num, s->name, cx->options.megabytes[type]); |
| 264 | break; | 268 | break; |
| 265 | 269 | ||
| 266 | case VFL_TYPE_RADIO: | 270 | case VFL_TYPE_RADIO: |
| 267 | CX18_INFO("Registered device radio%d for %s\n", | 271 | CX18_INFO("Registered device radio%d for %s\n", |
| 268 | minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); | 272 | num, s->name); |
| 269 | break; | 273 | break; |
| 270 | 274 | ||
| 271 | case VFL_TYPE_VBI: | 275 | case VFL_TYPE_VBI: |
| 272 | if (cx->options.megabytes[type]) | 276 | if (cx->options.megabytes[type]) |
| 273 | CX18_INFO("Registered device vbi%d for %s (%d MB)\n", | 277 | CX18_INFO("Registered device vbi%d for %s (%d MB)\n", |
| 274 | minor - MINOR_VFL_TYPE_VBI_MIN, | 278 | num, |
| 275 | s->name, cx->options.megabytes[type]); | 279 | s->name, cx->options.megabytes[type]); |
| 276 | else | 280 | else |
| 277 | CX18_INFO("Registered device vbi%d for %s\n", | 281 | CX18_INFO("Registered device vbi%d for %s\n", |
| 278 | minor - MINOR_VFL_TYPE_VBI_MIN, s->name); | 282 | num, s->name); |
| 279 | break; | 283 | break; |
| 280 | } | 284 | } |
| 281 | 285 | ||
| @@ -432,7 +436,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
| 432 | default: | 436 | default: |
| 433 | return -EINVAL; | 437 | return -EINVAL; |
| 434 | } | 438 | } |
| 435 | s->buffers_stolen = 0; | ||
| 436 | 439 | ||
| 437 | /* mute/unmute video */ | 440 | /* mute/unmute video */ |
| 438 | cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, | 441 | cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, |
| @@ -470,7 +473,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
| 470 | 473 | ||
| 471 | if (atomic_read(&cx->tot_capturing) == 0) { | 474 | if (atomic_read(&cx->tot_capturing) == 0) { |
| 472 | clear_bit(CX18_F_I_EOS, &cx->i_flags); | 475 | clear_bit(CX18_F_I_EOS, &cx->i_flags); |
| 473 | write_reg(7, CX18_DSP0_INTERRUPT_MASK); | 476 | cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK); |
| 474 | } | 477 | } |
| 475 | 478 | ||
| 476 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle, | 479 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle, |
| @@ -480,8 +483,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
| 480 | list_for_each(p, &s->q_free.list) { | 483 | list_for_each(p, &s->q_free.list) { |
| 481 | struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); | 484 | struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); |
| 482 | 485 | ||
| 483 | writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); | 486 | cx18_writel(cx, buf->dma_handle, |
| 484 | writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length); | 487 | &cx->scb->cpu_mdl[buf->id].paddr); |
| 488 | cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); | ||
| 485 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | 489 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, |
| 486 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | 490 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, |
| 487 | 1, buf->id, s->buf_size); | 491 | 1, buf->id, s->buf_size); |
| @@ -489,7 +493,14 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
| 489 | /* begin_capture */ | 493 | /* begin_capture */ |
| 490 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { | 494 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { |
| 491 | CX18_DEBUG_WARN("Error starting capture!\n"); | 495 | CX18_DEBUG_WARN("Error starting capture!\n"); |
| 496 | /* Ensure we're really not capturing before releasing MDLs */ | ||
| 497 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) | ||
| 498 | cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1); | ||
| 499 | else | ||
| 500 | cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle); | ||
| 501 | cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); | ||
| 492 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); | 502 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); |
| 503 | /* FIXME - clean-up DSP0_INT mask, i_flags, s_flags, etc. */ | ||
| 493 | return -EINVAL; | 504 | return -EINVAL; |
| 494 | } | 505 | } |
| 495 | 506 | ||
| @@ -541,6 +552,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
| 541 | CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); | 552 | CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); |
| 542 | } | 553 | } |
| 543 | 554 | ||
| 555 | /* Tell the CX23418 it can't use our buffers anymore */ | ||
| 556 | cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); | ||
| 557 | |||
| 544 | if (s->type != CX18_ENC_STREAM_TYPE_TS) | 558 | if (s->type != CX18_ENC_STREAM_TYPE_TS) |
| 545 | atomic_dec(&cx->ana_capturing); | 559 | atomic_dec(&cx->ana_capturing); |
| 546 | atomic_dec(&cx->tot_capturing); | 560 | atomic_dec(&cx->tot_capturing); |
| @@ -549,12 +563,12 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
| 549 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | 563 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); |
| 550 | 564 | ||
| 551 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); | 565 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); |
| 552 | s->handle = 0xffffffff; | 566 | s->handle = CX18_INVALID_TASK_HANDLE; |
| 553 | 567 | ||
| 554 | if (atomic_read(&cx->tot_capturing) > 0) | 568 | if (atomic_read(&cx->tot_capturing) > 0) |
| 555 | return 0; | 569 | return 0; |
| 556 | 570 | ||
| 557 | write_reg(5, CX18_DSP0_INTERRUPT_MASK); | 571 | cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK); |
| 558 | wake_up(&s->waitq); | 572 | wake_up(&s->waitq); |
| 559 | 573 | ||
| 560 | return 0; | 574 | return 0; |
| @@ -568,8 +582,8 @@ u32 cx18_find_handle(struct cx18 *cx) | |||
| 568 | for (i = 0; i < CX18_MAX_STREAMS; i++) { | 582 | for (i = 0; i < CX18_MAX_STREAMS; i++) { |
| 569 | struct cx18_stream *s = &cx->streams[i]; | 583 | struct cx18_stream *s = &cx->streams[i]; |
| 570 | 584 | ||
| 571 | if (s->v4l2dev && s->handle) | 585 | if (s->v4l2dev && (s->handle != CX18_INVALID_TASK_HANDLE)) |
| 572 | return s->handle; | 586 | return s->handle; |
| 573 | } | 587 | } |
| 574 | return 0; | 588 | return CX18_INVALID_TASK_HANDLE; |
| 575 | } | 589 | } |
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h index d5c7a6f968dd..9f6be2d457fb 100644 --- a/drivers/media/video/cx18/cx18-version.h +++ b/drivers/media/video/cx18/cx18-version.h | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #define CX18_DRIVER_NAME "cx18" | 25 | #define CX18_DRIVER_NAME "cx18" |
| 26 | #define CX18_DRIVER_VERSION_MAJOR 1 | 26 | #define CX18_DRIVER_VERSION_MAJOR 1 |
| 27 | #define CX18_DRIVER_VERSION_MINOR 0 | 27 | #define CX18_DRIVER_VERSION_MINOR 0 |
| 28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 0 | 28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 1 |
| 29 | 29 | ||
| 30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) | 30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) |
| 31 | #define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \ | 31 | #define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \ |
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h index e7ed053059a8..668f968d7761 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/video/cx18/cx23418.h | |||
| @@ -351,7 +351,7 @@ | |||
| 351 | Descriptor Lists to the driver | 351 | Descriptor Lists to the driver |
| 352 | IN[0] - Task handle. Handle of the task to start | 352 | IN[0] - Task handle. Handle of the task to start |
| 353 | ReturnCode - One of the ERR_DE_... */ | 353 | ReturnCode - One of the ERR_DE_... */ |
| 354 | /* #define CX18_CPU_DE_ReleaseMDL (CPU_CMD_MASK_DE | 0x0006) */ | 354 | #define CX18_CPU_DE_RELEASE_MDL (CPU_CMD_MASK_DE | 0x0006) |
| 355 | 355 | ||
| 356 | /* Description: This command signals the cpu that the dat buffer has been | 356 | /* Description: This command signals the cpu that the dat buffer has been |
| 357 | consumed and ready for re-use. | 357 | consumed and ready for re-use. |
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 22847a0444f5..cbbe47fb87b7 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c | |||
| @@ -508,7 +508,10 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, | |||
| 508 | /* this setting is read-only for the cx2341x since the | 508 | /* this setting is read-only for the cx2341x since the |
| 509 | V4L2_CID_MPEG_STREAM_TYPE really determines the | 509 | V4L2_CID_MPEG_STREAM_TYPE really determines the |
| 510 | MPEG-1/2 setting */ | 510 | MPEG-1/2 setting */ |
| 511 | err = v4l2_ctrl_query_fill_std(qctrl); | 511 | err = v4l2_ctrl_query_fill(qctrl, |
| 512 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1, | ||
| 513 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, | ||
| 514 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); | ||
| 512 | if (err == 0) | 515 | if (err == 0) |
| 513 | qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | 516 | qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
| 514 | return err; | 517 | return err; |
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index e60bd31b51a3..8c1b7fa47a41 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig | |||
| @@ -15,6 +15,7 @@ config VIDEO_CX23885 | |||
| 15 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE | 15 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE |
| 16 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | 16 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE |
| 17 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 17 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
| 18 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
| 18 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE | 19 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE |
| 19 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE | 20 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE |
| 20 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE | 21 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE |
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 7b0e8c01692e..395c11fa47ce 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <media/cx2341x.h> | 36 | #include <media/cx2341x.h> |
| 37 | 37 | ||
| 38 | #include "cx23885.h" | 38 | #include "cx23885.h" |
| 39 | #include "media/cx2341x.h" | ||
| 40 | 39 | ||
| 41 | #define CX23885_FIRM_IMAGE_SIZE 376836 | 40 | #define CX23885_FIRM_IMAGE_SIZE 376836 |
| 42 | #define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" | 41 | #define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw" |
| @@ -632,7 +631,7 @@ int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value) | |||
| 632 | /* ------------------------------------------------------------------ */ | 631 | /* ------------------------------------------------------------------ */ |
| 633 | 632 | ||
| 634 | /* MPEG encoder API */ | 633 | /* MPEG encoder API */ |
| 635 | char *cmd_to_str(int cmd) | 634 | static char *cmd_to_str(int cmd) |
| 636 | { | 635 | { |
| 637 | switch (cmd) { | 636 | switch (cmd) { |
| 638 | case CX2341X_ENC_PING_FW: | 637 | case CX2341X_ENC_PING_FW: |
| @@ -1583,6 +1582,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
| 1583 | 1582 | ||
| 1584 | dprintk(2, "%s()\n", __func__); | 1583 | dprintk(2, "%s()\n", __func__); |
| 1585 | 1584 | ||
| 1585 | lock_kernel(); | ||
| 1586 | list_for_each(list, &cx23885_devlist) { | 1586 | list_for_each(list, &cx23885_devlist) { |
| 1587 | h = list_entry(list, struct cx23885_dev, devlist); | 1587 | h = list_entry(list, struct cx23885_dev, devlist); |
| 1588 | if (h->v4l_device->minor == minor) { | 1588 | if (h->v4l_device->minor == minor) { |
| @@ -1591,13 +1591,17 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
| 1591 | } | 1591 | } |
| 1592 | } | 1592 | } |
| 1593 | 1593 | ||
| 1594 | if (dev == NULL) | 1594 | if (dev == NULL) { |
| 1595 | unlock_kernel(); | ||
| 1595 | return -ENODEV; | 1596 | return -ENODEV; |
| 1597 | } | ||
| 1596 | 1598 | ||
| 1597 | /* allocate + initialize per filehandle data */ | 1599 | /* allocate + initialize per filehandle data */ |
| 1598 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | 1600 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); |
| 1599 | if (NULL == fh) | 1601 | if (NULL == fh) { |
| 1602 | unlock_kernel(); | ||
| 1600 | return -ENOMEM; | 1603 | return -ENOMEM; |
| 1604 | } | ||
| 1601 | 1605 | ||
| 1602 | file->private_data = fh; | 1606 | file->private_data = fh; |
| 1603 | fh->dev = dev; | 1607 | fh->dev = dev; |
| @@ -1608,6 +1612,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
| 1608 | V4L2_FIELD_INTERLACED, | 1612 | V4L2_FIELD_INTERLACED, |
| 1609 | sizeof(struct cx23885_buffer), | 1613 | sizeof(struct cx23885_buffer), |
| 1610 | fh); | 1614 | fh); |
| 1615 | unlock_kernel(); | ||
| 1611 | 1616 | ||
| 1612 | return 0; | 1617 | return 0; |
| 1613 | } | 1618 | } |
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index c36d3f632104..2cda15f829fd 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <media/cx25840.h> | 26 | #include <media/cx25840.h> |
| 27 | 27 | ||
| 28 | #include "cx23885.h" | 28 | #include "cx23885.h" |
| 29 | #include "tuner-xc2028.h" | ||
| 29 | 30 | ||
| 30 | /* ------------------------------------------------------------------ */ | 31 | /* ------------------------------------------------------------------ */ |
| 31 | /* board config info */ | 32 | /* board config info */ |
| @@ -148,6 +149,15 @@ struct cx23885_board cx23885_boards[] = { | |||
| 148 | .portb = CX23885_MPEG_DVB, | 149 | .portb = CX23885_MPEG_DVB, |
| 149 | .portc = CX23885_MPEG_DVB, | 150 | .portc = CX23885_MPEG_DVB, |
| 150 | }, | 151 | }, |
| 152 | [CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP] = { | ||
| 153 | .name = "DViCO FusionHDTV DVB-T Dual Express", | ||
| 154 | .portb = CX23885_MPEG_DVB, | ||
| 155 | .portc = CX23885_MPEG_DVB, | ||
| 156 | }, | ||
| 157 | [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H] = { | ||
| 158 | .name = "Leadtek Winfast PxDVR3200 H", | ||
| 159 | .portc = CX23885_MPEG_DVB, | ||
| 160 | }, | ||
| 151 | }; | 161 | }; |
| 152 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); | 162 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); |
| 153 | 163 | ||
| @@ -219,6 +229,14 @@ struct cx23885_subid cx23885_subids[] = { | |||
| 219 | .subvendor = 0x18ac, | 229 | .subvendor = 0x18ac, |
| 220 | .subdevice = 0xd618, | 230 | .subdevice = 0xd618, |
| 221 | .card = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP, | 231 | .card = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP, |
| 232 | },{ | ||
| 233 | .subvendor = 0x18ac, | ||
| 234 | .subdevice = 0xdb78, | ||
| 235 | .card = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP, | ||
| 236 | }, { | ||
| 237 | .subvendor = 0x107d, | ||
| 238 | .subdevice = 0x6681, | ||
| 239 | .card = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H, | ||
| 222 | }, | 240 | }, |
| 223 | }; | 241 | }; |
| 224 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); | 242 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); |
| @@ -319,15 +337,15 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) | |||
| 319 | dev->name, tv.model); | 337 | dev->name, tv.model); |
| 320 | } | 338 | } |
| 321 | 339 | ||
| 322 | /* Tuner callback function for cx23885 boards. Currently only needed | 340 | int cx23885_tuner_callback(void *priv, int component, int command, int arg) |
| 323 | * for HVR1500Q, which has an xc5000 tuner. | ||
| 324 | */ | ||
| 325 | int cx23885_tuner_callback(void *priv, int command, int arg) | ||
| 326 | { | 341 | { |
| 327 | struct cx23885_i2c *bus = priv; | 342 | struct cx23885_tsport *port = priv; |
| 328 | struct cx23885_dev *dev = bus->dev; | 343 | struct cx23885_dev *dev = port->dev; |
| 329 | u32 bitmask = 0; | 344 | u32 bitmask = 0; |
| 330 | 345 | ||
| 346 | if (command == XC2028_RESET_CLK) | ||
| 347 | return 0; | ||
| 348 | |||
| 331 | if (command != 0) { | 349 | if (command != 0) { |
| 332 | printk(KERN_ERR "%s(): Unknown command 0x%x.\n", | 350 | printk(KERN_ERR "%s(): Unknown command 0x%x.\n", |
| 333 | __func__, command); | 351 | __func__, command); |
| @@ -335,21 +353,21 @@ int cx23885_tuner_callback(void *priv, int command, int arg) | |||
| 335 | } | 353 | } |
| 336 | 354 | ||
| 337 | switch(dev->board) { | 355 | switch(dev->board) { |
| 356 | case CX23885_BOARD_HAUPPAUGE_HVR1400: | ||
| 357 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | ||
| 338 | case CX23885_BOARD_HAUPPAUGE_HVR1500Q: | 358 | case CX23885_BOARD_HAUPPAUGE_HVR1500Q: |
| 339 | /* Tuner Reset Command from xc5000 */ | 359 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: |
| 340 | if (command == 0) | 360 | /* Tuner Reset Command */ |
| 341 | bitmask = 0x04; | 361 | bitmask = 0x04; |
| 342 | break; | 362 | break; |
| 343 | case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: | 363 | case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: |
| 344 | if (command == 0) { | 364 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: |
| 345 | 365 | /* Two identical tuners on two different i2c buses, | |
| 346 | /* Two identical tuners on two different i2c buses, | 366 | * we need to reset the correct gpio. */ |
| 347 | * we need to reset the correct gpio. */ | 367 | if (port->nr == 0) |
| 348 | if (bus->nr == 0) | 368 | bitmask = 0x01; |
| 349 | bitmask = 0x01; | 369 | else if (port->nr == 1) |
| 350 | else if (bus->nr == 1) | 370 | bitmask = 0x04; |
| 351 | bitmask = 0x04; | ||
| 352 | } | ||
| 353 | break; | 371 | break; |
| 354 | } | 372 | } |
| 355 | 373 | ||
| @@ -465,6 +483,32 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
| 465 | mdelay(20); | 483 | mdelay(20); |
| 466 | cx_set(GP0_IO, 0x000f000f); | 484 | cx_set(GP0_IO, 0x000f000f); |
| 467 | break; | 485 | break; |
| 486 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: | ||
| 487 | /* GPIO-0 portb xc3028 reset */ | ||
| 488 | /* GPIO-1 portb zl10353 reset */ | ||
| 489 | /* GPIO-2 portc xc3028 reset */ | ||
| 490 | /* GPIO-3 portc zl10353 reset */ | ||
| 491 | |||
| 492 | /* Put the parts into reset and back */ | ||
| 493 | cx_set(GP0_IO, 0x000f0000); | ||
| 494 | mdelay(20); | ||
| 495 | cx_clear(GP0_IO, 0x0000000f); | ||
| 496 | mdelay(20); | ||
| 497 | cx_set(GP0_IO, 0x000f000f); | ||
| 498 | break; | ||
| 499 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | ||
| 500 | /* GPIO-2 xc3028 tuner reset */ | ||
| 501 | |||
| 502 | /* The following GPIO's are on the internal AVCore (cx25840) */ | ||
| 503 | /* GPIO-? zl10353 demod reset */ | ||
| 504 | |||
| 505 | /* Put the parts into reset and back */ | ||
| 506 | cx_set(GP0_IO, 0x00040000); | ||
| 507 | mdelay(20); | ||
| 508 | cx_clear(GP0_IO, 0x00000004); | ||
| 509 | mdelay(20); | ||
| 510 | cx_set(GP0_IO, 0x00040004); | ||
| 511 | break; | ||
| 468 | } | 512 | } |
| 469 | } | 513 | } |
| 470 | 514 | ||
| @@ -479,6 +523,9 @@ int cx23885_ir_init(struct cx23885_dev *dev) | |||
| 479 | case CX23885_BOARD_HAUPPAUGE_HVR1400: | 523 | case CX23885_BOARD_HAUPPAUGE_HVR1400: |
| 480 | /* FIXME: Implement me */ | 524 | /* FIXME: Implement me */ |
| 481 | break; | 525 | break; |
| 526 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: | ||
| 527 | request_module("ir-kbd-i2c"); | ||
| 528 | break; | ||
| 482 | } | 529 | } |
| 483 | 530 | ||
| 484 | return 0; | 531 | return 0; |
| @@ -516,6 +563,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
| 516 | 563 | ||
| 517 | switch (dev->board) { | 564 | switch (dev->board) { |
| 518 | case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: | 565 | case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: |
| 566 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: | ||
| 519 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ | 567 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ |
| 520 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 568 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
| 521 | ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | 569 | ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; |
| @@ -548,6 +596,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
| 548 | case CX23885_BOARD_HAUPPAUGE_HVR1200: | 596 | case CX23885_BOARD_HAUPPAUGE_HVR1200: |
| 549 | case CX23885_BOARD_HAUPPAUGE_HVR1700: | 597 | case CX23885_BOARD_HAUPPAUGE_HVR1700: |
| 550 | case CX23885_BOARD_HAUPPAUGE_HVR1400: | 598 | case CX23885_BOARD_HAUPPAUGE_HVR1400: |
| 599 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | ||
| 551 | default: | 600 | default: |
| 552 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ | 601 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ |
| 553 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 602 | ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
| @@ -561,6 +610,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
| 561 | case CX23885_BOARD_HAUPPAUGE_HVR1800: | 610 | case CX23885_BOARD_HAUPPAUGE_HVR1800: |
| 562 | case CX23885_BOARD_HAUPPAUGE_HVR1800lp: | 611 | case CX23885_BOARD_HAUPPAUGE_HVR1800lp: |
| 563 | case CX23885_BOARD_HAUPPAUGE_HVR1700: | 612 | case CX23885_BOARD_HAUPPAUGE_HVR1700: |
| 613 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | ||
| 564 | request_module("cx25840"); | 614 | request_module("cx25840"); |
| 565 | break; | 615 | break; |
| 566 | } | 616 | } |
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 25fb09938744..beb3e61669a3 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
| @@ -1442,7 +1442,7 @@ void cx23885_cancel_buffers(struct cx23885_tsport *port) | |||
| 1442 | struct cx23885_dev *dev = port->dev; | 1442 | struct cx23885_dev *dev = port->dev; |
| 1443 | struct cx23885_dmaqueue *q = &port->mpegq; | 1443 | struct cx23885_dmaqueue *q = &port->mpegq; |
| 1444 | 1444 | ||
| 1445 | dprintk(1, "%s()\n", __FUNCTION__); | 1445 | dprintk(1, "%s()\n", __func__); |
| 1446 | del_timer_sync(&q->timeout); | 1446 | del_timer_sync(&q->timeout); |
| 1447 | cx23885_stop_dma(port); | 1447 | cx23885_stop_dma(port); |
| 1448 | do_cancel_buffers(port, "cancel", 0); | 1448 | do_cancel_buffers(port, "cancel", 0); |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 291b9d008da8..24bd18327aa0 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include "tuner-simple.h" | 42 | #include "tuner-simple.h" |
| 43 | #include "dib7000p.h" | 43 | #include "dib7000p.h" |
| 44 | #include "dibx000_common.h" | 44 | #include "dibx000_common.h" |
| 45 | #include "zl10353.h" | ||
| 45 | 46 | ||
| 46 | static unsigned int debug; | 47 | static unsigned int debug; |
| 47 | 48 | ||
| @@ -188,13 +189,11 @@ static struct s5h1411_config dvico_s5h1411_config = { | |||
| 188 | static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { | 189 | static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { |
| 189 | .i2c_address = 0x61, | 190 | .i2c_address = 0x61, |
| 190 | .if_khz = 5380, | 191 | .if_khz = 5380, |
| 191 | .tuner_callback = cx23885_tuner_callback | ||
| 192 | }; | 192 | }; |
| 193 | 193 | ||
| 194 | static struct xc5000_config dvico_xc5000_tunerconfig = { | 194 | static struct xc5000_config dvico_xc5000_tunerconfig = { |
| 195 | .i2c_address = 0x64, | 195 | .i2c_address = 0x64, |
| 196 | .if_khz = 5380, | 196 | .if_khz = 5380, |
| 197 | .tuner_callback = cx23885_tuner_callback | ||
| 198 | }; | 197 | }; |
| 199 | 198 | ||
| 200 | static struct tda829x_config tda829x_no_probe = { | 199 | static struct tda829x_config tda829x_no_probe = { |
| @@ -303,35 +302,11 @@ static struct dib7000p_config hauppauge_hvr1400_dib7000_config = { | |||
| 303 | .output_mode = OUTMODE_MPEG2_SERIAL, | 302 | .output_mode = OUTMODE_MPEG2_SERIAL, |
| 304 | }; | 303 | }; |
| 305 | 304 | ||
| 306 | static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) | 305 | static struct zl10353_config dvico_fusionhdtv_xc3028 = { |
| 307 | { | 306 | .demod_address = 0x0f, |
| 308 | struct cx23885_tsport *port = ptr; | 307 | .if2 = 45600, |
| 309 | struct cx23885_dev *dev = port->dev; | 308 | .no_tuner = 1, |
| 310 | 309 | }; | |
| 311 | switch (command) { | ||
| 312 | case XC2028_TUNER_RESET: | ||
| 313 | /* Send the tuner in then out of reset */ | ||
| 314 | /* GPIO-2 xc3028 tuner */ | ||
| 315 | dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); | ||
| 316 | |||
| 317 | cx_set(GP0_IO, 0x00040000); | ||
| 318 | cx_clear(GP0_IO, 0x00000004); | ||
| 319 | msleep(5); | ||
| 320 | |||
| 321 | cx_set(GP0_IO, 0x00040004); | ||
| 322 | msleep(5); | ||
| 323 | break; | ||
| 324 | case XC2028_RESET_CLK: | ||
| 325 | dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); | ||
| 326 | break; | ||
| 327 | default: | ||
| 328 | dprintk(1, "%s: unknown command %d, arg %d\n", __func__, | ||
| 329 | command, arg); | ||
| 330 | return -EINVAL; | ||
| 331 | } | ||
| 332 | |||
| 333 | return 0; | ||
| 334 | } | ||
| 335 | 310 | ||
| 336 | static int dvb_register(struct cx23885_tsport *port) | 311 | static int dvb_register(struct cx23885_tsport *port) |
| 337 | { | 312 | { |
| @@ -413,8 +388,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
| 413 | &dev->i2c_bus[0].i2c_adap); | 388 | &dev->i2c_bus[0].i2c_adap); |
| 414 | if (port->dvb.frontend != NULL) | 389 | if (port->dvb.frontend != NULL) |
| 415 | dvb_attach(xc5000_attach, port->dvb.frontend, | 390 | dvb_attach(xc5000_attach, port->dvb.frontend, |
| 416 | &i2c_bus->i2c_adap, | 391 | &i2c_bus->i2c_adap, |
| 417 | &hauppauge_hvr1500q_tunerconfig, i2c_bus); | 392 | &hauppauge_hvr1500q_tunerconfig); |
| 418 | break; | 393 | break; |
| 419 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | 394 | case CX23885_BOARD_HAUPPAUGE_HVR1500: |
| 420 | i2c_bus = &dev->i2c_bus[1]; | 395 | i2c_bus = &dev->i2c_bus[1]; |
| @@ -426,10 +401,9 @@ static int dvb_register(struct cx23885_tsport *port) | |||
| 426 | struct xc2028_config cfg = { | 401 | struct xc2028_config cfg = { |
| 427 | .i2c_adap = &i2c_bus->i2c_adap, | 402 | .i2c_adap = &i2c_bus->i2c_adap, |
| 428 | .i2c_addr = 0x61, | 403 | .i2c_addr = 0x61, |
| 429 | .callback = cx23885_hvr1500_xc3028_callback, | ||
| 430 | }; | 404 | }; |
| 431 | static struct xc2028_ctrl ctl = { | 405 | static struct xc2028_ctrl ctl = { |
| 432 | .fname = "xc3028-v27.fw", | 406 | .fname = XC2028_DEFAULT_FIRMWARE, |
| 433 | .max_len = 64, | 407 | .max_len = 64, |
| 434 | .scode_table = XC3028_FE_OREN538, | 408 | .scode_table = XC3028_FE_OREN538, |
| 435 | }; | 409 | }; |
| @@ -465,13 +439,13 @@ static int dvb_register(struct cx23885_tsport *port) | |||
| 465 | struct xc2028_config cfg = { | 439 | struct xc2028_config cfg = { |
| 466 | .i2c_adap = &dev->i2c_bus[1].i2c_adap, | 440 | .i2c_adap = &dev->i2c_bus[1].i2c_adap, |
| 467 | .i2c_addr = 0x64, | 441 | .i2c_addr = 0x64, |
| 468 | .callback = cx23885_hvr1500_xc3028_callback, | ||
| 469 | }; | 442 | }; |
| 470 | static struct xc2028_ctrl ctl = { | 443 | static struct xc2028_ctrl ctl = { |
| 471 | .fname = "xc3028L-v36.fw", | 444 | .fname = XC3028L_DEFAULT_FIRMWARE, |
| 472 | .max_len = 64, | 445 | .max_len = 64, |
| 473 | .demod = 5000, | 446 | .demod = 5000, |
| 474 | .d2633 = 1 | 447 | /* This is true for all demods with v36 firmware? */ |
| 448 | .type = XC2028_D2633, | ||
| 475 | }; | 449 | }; |
| 476 | 450 | ||
| 477 | fe = dvb_attach(xc2028_attach, | 451 | fe = dvb_attach(xc2028_attach, |
| @@ -492,8 +466,57 @@ static int dvb_register(struct cx23885_tsport *port) | |||
| 492 | &i2c_bus->i2c_adap); | 466 | &i2c_bus->i2c_adap); |
| 493 | if (port->dvb.frontend != NULL) | 467 | if (port->dvb.frontend != NULL) |
| 494 | dvb_attach(xc5000_attach, port->dvb.frontend, | 468 | dvb_attach(xc5000_attach, port->dvb.frontend, |
| 495 | &i2c_bus->i2c_adap, | 469 | &i2c_bus->i2c_adap, |
| 496 | &dvico_xc5000_tunerconfig, i2c_bus); | 470 | &dvico_xc5000_tunerconfig); |
| 471 | break; | ||
| 472 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: { | ||
| 473 | i2c_bus = &dev->i2c_bus[port->nr - 1]; | ||
| 474 | |||
| 475 | port->dvb.frontend = dvb_attach(zl10353_attach, | ||
| 476 | &dvico_fusionhdtv_xc3028, | ||
| 477 | &i2c_bus->i2c_adap); | ||
| 478 | if (port->dvb.frontend != NULL) { | ||
| 479 | struct dvb_frontend *fe; | ||
| 480 | struct xc2028_config cfg = { | ||
| 481 | .i2c_adap = &i2c_bus->i2c_adap, | ||
| 482 | .i2c_addr = 0x61, | ||
| 483 | }; | ||
| 484 | static struct xc2028_ctrl ctl = { | ||
| 485 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
| 486 | .max_len = 64, | ||
| 487 | .demod = XC3028_FE_ZARLINK456, | ||
| 488 | }; | ||
| 489 | |||
| 490 | fe = dvb_attach(xc2028_attach, port->dvb.frontend, | ||
| 491 | &cfg); | ||
| 492 | if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) | ||
| 493 | fe->ops.tuner_ops.set_config(fe, &ctl); | ||
| 494 | } | ||
| 495 | break; | ||
| 496 | } | ||
| 497 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | ||
| 498 | i2c_bus = &dev->i2c_bus[0]; | ||
| 499 | |||
| 500 | port->dvb.frontend = dvb_attach(zl10353_attach, | ||
| 501 | &dvico_fusionhdtv_xc3028, | ||
| 502 | &i2c_bus->i2c_adap); | ||
| 503 | if (port->dvb.frontend != NULL) { | ||
| 504 | struct dvb_frontend *fe; | ||
| 505 | struct xc2028_config cfg = { | ||
| 506 | .i2c_adap = &dev->i2c_bus[1].i2c_adap, | ||
| 507 | .i2c_addr = 0x61, | ||
| 508 | }; | ||
| 509 | static struct xc2028_ctrl ctl = { | ||
| 510 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
| 511 | .max_len = 64, | ||
| 512 | .demod = XC3028_FE_ZARLINK456, | ||
| 513 | }; | ||
| 514 | |||
| 515 | fe = dvb_attach(xc2028_attach, port->dvb.frontend, | ||
| 516 | &cfg); | ||
| 517 | if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) | ||
| 518 | fe->ops.tuner_ops.set_config(fe, &ctl); | ||
| 519 | } | ||
| 497 | break; | 520 | break; |
| 498 | default: | 521 | default: |
| 499 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", | 522 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", |
| @@ -504,6 +527,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
| 504 | printk("%s: frontend initialization failed\n", dev->name); | 527 | printk("%s: frontend initialization failed\n", dev->name); |
| 505 | return -1; | 528 | return -1; |
| 506 | } | 529 | } |
| 530 | /* define general-purpose callback pointer */ | ||
| 531 | port->dvb.frontend->callback = cx23885_tuner_callback; | ||
| 507 | 532 | ||
| 508 | /* Put the analog decoder in standby to keep it quiet */ | 533 | /* Put the analog decoder in standby to keep it quiet */ |
| 509 | cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); | 534 | cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); |
diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c index 35e61cd112fc..5b297f0323b6 100644 --- a/drivers/media/video/cx23885/cx23885-vbi.c +++ b/drivers/media/video/cx23885/cx23885-vbi.c | |||
| @@ -85,18 +85,8 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev, | |||
| 85 | return 0; | 85 | return 0; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | int cx23885_stop_vbi_dma(struct cx23885_dev *dev) | ||
| 89 | { | ||
| 90 | /* stop dma */ | ||
| 91 | cx_clear(VID_A_DMA_CTL, 0x00000022); | ||
| 92 | |||
| 93 | /* disable irqs */ | ||
| 94 | cx_clear(PCI_INT_MSK, 0x000001); | ||
| 95 | cx_clear(VID_A_INT_MSK, 0x00000022); | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | 88 | ||
| 99 | int cx23885_restart_vbi_queue(struct cx23885_dev *dev, | 89 | static int cx23885_restart_vbi_queue(struct cx23885_dev *dev, |
| 100 | struct cx23885_dmaqueue *q) | 90 | struct cx23885_dmaqueue *q) |
| 101 | { | 91 | { |
| 102 | struct cx23885_buffer *buf; | 92 | struct cx23885_buffer *buf; |
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 6047c78d84bf..f75ed1c9b71a 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
| @@ -244,7 +244,7 @@ static struct cx23885_ctrl cx23885_ctls[] = { | |||
| 244 | }; | 244 | }; |
| 245 | static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls); | 245 | static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls); |
| 246 | 246 | ||
| 247 | const u32 cx23885_user_ctrls[] = { | 247 | static const u32 cx23885_user_ctrls[] = { |
| 248 | V4L2_CID_USER_CLASS, | 248 | V4L2_CID_USER_CLASS, |
| 249 | V4L2_CID_BRIGHTNESS, | 249 | V4L2_CID_BRIGHTNESS, |
| 250 | V4L2_CID_CONTRAST, | 250 | V4L2_CID_CONTRAST, |
| @@ -254,14 +254,13 @@ const u32 cx23885_user_ctrls[] = { | |||
| 254 | V4L2_CID_AUDIO_MUTE, | 254 | V4L2_CID_AUDIO_MUTE, |
| 255 | 0 | 255 | 0 |
| 256 | }; | 256 | }; |
| 257 | EXPORT_SYMBOL(cx23885_user_ctrls); | ||
| 258 | 257 | ||
| 259 | static const u32 *ctrl_classes[] = { | 258 | static const u32 *ctrl_classes[] = { |
| 260 | cx23885_user_ctrls, | 259 | cx23885_user_ctrls, |
| 261 | NULL | 260 | NULL |
| 262 | }; | 261 | }; |
| 263 | 262 | ||
| 264 | void cx23885_video_wakeup(struct cx23885_dev *dev, | 263 | static void cx23885_video_wakeup(struct cx23885_dev *dev, |
| 265 | struct cx23885_dmaqueue *q, u32 count) | 264 | struct cx23885_dmaqueue *q, u32 count) |
| 266 | { | 265 | { |
| 267 | struct cx23885_buffer *buf; | 266 | struct cx23885_buffer *buf; |
| @@ -296,7 +295,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev, | |||
| 296 | __func__, bc); | 295 | __func__, bc); |
| 297 | } | 296 | } |
| 298 | 297 | ||
| 299 | int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) | 298 | static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) |
| 300 | { | 299 | { |
| 301 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", | 300 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", |
| 302 | __func__, | 301 | __func__, |
| @@ -314,7 +313,7 @@ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) | |||
| 314 | return 0; | 313 | return 0; |
| 315 | } | 314 | } |
| 316 | 315 | ||
| 317 | struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, | 316 | static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, |
| 318 | struct pci_dev *pci, | 317 | struct pci_dev *pci, |
| 319 | struct video_device *template, | 318 | struct video_device *template, |
| 320 | char *type) | 319 | char *type) |
| @@ -334,7 +333,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, | |||
| 334 | return vfd; | 333 | return vfd; |
| 335 | } | 334 | } |
| 336 | 335 | ||
| 337 | int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl) | 336 | static int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl) |
| 338 | { | 337 | { |
| 339 | int i; | 338 | int i; |
| 340 | 339 | ||
| @@ -351,7 +350,6 @@ int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl) | |||
| 351 | *qctrl = cx23885_ctls[i].v; | 350 | *qctrl = cx23885_ctls[i].v; |
| 352 | return 0; | 351 | return 0; |
| 353 | } | 352 | } |
| 354 | EXPORT_SYMBOL(cx23885_ctrl_query); | ||
| 355 | 353 | ||
| 356 | /* ------------------------------------------------------------------- */ | 354 | /* ------------------------------------------------------------------- */ |
| 357 | /* resource management */ | 355 | /* resource management */ |
| @@ -402,7 +400,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh, | |||
| 402 | mutex_unlock(&dev->lock); | 400 | mutex_unlock(&dev->lock); |
| 403 | } | 401 | } |
| 404 | 402 | ||
| 405 | int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) | 403 | static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) |
| 406 | { | 404 | { |
| 407 | struct v4l2_routing route; | 405 | struct v4l2_routing route; |
| 408 | memset(&route, 0, sizeof(route)); | 406 | memset(&route, 0, sizeof(route)); |
| @@ -422,10 +420,9 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) | |||
| 422 | 420 | ||
| 423 | return 0; | 421 | return 0; |
| 424 | } | 422 | } |
| 425 | EXPORT_SYMBOL(cx23885_video_mux); | ||
| 426 | 423 | ||
| 427 | /* ------------------------------------------------------------------ */ | 424 | /* ------------------------------------------------------------------ */ |
| 428 | int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width, | 425 | static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width, |
| 429 | unsigned int height, enum v4l2_field field) | 426 | unsigned int height, enum v4l2_field field) |
| 430 | { | 427 | { |
| 431 | dprintk(1, "%s()\n", __func__); | 428 | dprintk(1, "%s()\n", __func__); |
| @@ -731,6 +728,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 731 | enum v4l2_buf_type type = 0; | 728 | enum v4l2_buf_type type = 0; |
| 732 | int radio = 0; | 729 | int radio = 0; |
| 733 | 730 | ||
| 731 | lock_kernel(); | ||
| 734 | list_for_each(list, &cx23885_devlist) { | 732 | list_for_each(list, &cx23885_devlist) { |
| 735 | h = list_entry(list, struct cx23885_dev, devlist); | 733 | h = list_entry(list, struct cx23885_dev, devlist); |
| 736 | if (h->video_dev->minor == minor) { | 734 | if (h->video_dev->minor == minor) { |
| @@ -748,16 +746,20 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 748 | dev = h; | 746 | dev = h; |
| 749 | } | 747 | } |
| 750 | } | 748 | } |
| 751 | if (NULL == dev) | 749 | if (NULL == dev) { |
| 750 | unlock_kernel(); | ||
| 752 | return -ENODEV; | 751 | return -ENODEV; |
| 752 | } | ||
| 753 | 753 | ||
| 754 | dprintk(1, "open minor=%d radio=%d type=%s\n", | 754 | dprintk(1, "open minor=%d radio=%d type=%s\n", |
| 755 | minor, radio, v4l2_type_names[type]); | 755 | minor, radio, v4l2_type_names[type]); |
| 756 | 756 | ||
| 757 | /* allocate + initialize per filehandle data */ | 757 | /* allocate + initialize per filehandle data */ |
| 758 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | 758 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); |
| 759 | if (NULL == fh) | 759 | if (NULL == fh) { |
| 760 | unlock_kernel(); | ||
| 760 | return -ENOMEM; | 761 | return -ENOMEM; |
| 762 | } | ||
| 761 | file->private_data = fh; | 763 | file->private_data = fh; |
| 762 | fh->dev = dev; | 764 | fh->dev = dev; |
| 763 | fh->radio = radio; | 765 | fh->radio = radio; |
| @@ -775,6 +777,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 775 | 777 | ||
| 776 | dprintk(1, "post videobuf_queue_init()\n"); | 778 | dprintk(1, "post videobuf_queue_init()\n"); |
| 777 | 779 | ||
| 780 | unlock_kernel(); | ||
| 778 | 781 | ||
| 779 | return 0; | 782 | return 0; |
| 780 | } | 783 | } |
| @@ -884,21 +887,19 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 884 | /* ------------------------------------------------------------------ */ | 887 | /* ------------------------------------------------------------------ */ |
| 885 | /* VIDEO CTRL IOCTLS */ | 888 | /* VIDEO CTRL IOCTLS */ |
| 886 | 889 | ||
| 887 | int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl) | 890 | static int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl) |
| 888 | { | 891 | { |
| 889 | dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); | 892 | dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); |
| 890 | cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl); | 893 | cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl); |
| 891 | return 0; | 894 | return 0; |
| 892 | } | 895 | } |
| 893 | EXPORT_SYMBOL(cx23885_get_control); | ||
| 894 | 896 | ||
| 895 | int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl) | 897 | static int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl) |
| 896 | { | 898 | { |
| 897 | dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)" | 899 | dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)" |
| 898 | " (disabled - no action)\n", __func__); | 900 | " (disabled - no action)\n", __func__); |
| 899 | return 0; | 901 | return 0; |
| 900 | } | 902 | } |
| 901 | EXPORT_SYMBOL(cx23885_set_control); | ||
| 902 | 903 | ||
| 903 | static void init_controls(struct cx23885_dev *dev) | 904 | static void init_controls(struct cx23885_dev *dev) |
| 904 | { | 905 | { |
| @@ -1146,7 +1147,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) | |||
| 1146 | return 0; | 1147 | return 0; |
| 1147 | } | 1148 | } |
| 1148 | 1149 | ||
| 1149 | int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) | 1150 | static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) |
| 1150 | { | 1151 | { |
| 1151 | static const char *iname[] = { | 1152 | static const char *iname[] = { |
| 1152 | [CX23885_VMUX_COMPOSITE1] = "Composite1", | 1153 | [CX23885_VMUX_COMPOSITE1] = "Composite1", |
| @@ -1179,7 +1180,6 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) | |||
| 1179 | i->std = CX23885_NORMS; | 1180 | i->std = CX23885_NORMS; |
| 1180 | return 0; | 1181 | return 0; |
| 1181 | } | 1182 | } |
| 1182 | EXPORT_SYMBOL(cx23885_enum_input); | ||
| 1183 | 1183 | ||
| 1184 | static int vidioc_enum_input(struct file *file, void *priv, | 1184 | static int vidioc_enum_input(struct file *file, void *priv, |
| 1185 | struct v4l2_input *i) | 1185 | struct v4l2_input *i) |
| @@ -1288,7 +1288,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
| 1288 | return 0; | 1288 | return 0; |
| 1289 | } | 1289 | } |
| 1290 | 1290 | ||
| 1291 | int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) | 1291 | static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) |
| 1292 | { | 1292 | { |
| 1293 | if (unlikely(UNSET == dev->tuner_type)) | 1293 | if (unlikely(UNSET == dev->tuner_type)) |
| 1294 | return -EINVAL; | 1294 | return -EINVAL; |
| @@ -1307,7 +1307,6 @@ int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) | |||
| 1307 | 1307 | ||
| 1308 | return 0; | 1308 | return 0; |
| 1309 | } | 1309 | } |
| 1310 | EXPORT_SYMBOL(cx23885_set_freq); | ||
| 1311 | 1310 | ||
| 1312 | static int vidioc_s_frequency(struct file *file, void *priv, | 1311 | static int vidioc_s_frequency(struct file *file, void *priv, |
| 1313 | struct v4l2_frequency *f) | 1312 | struct v4l2_frequency *f) |
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index e23d97c071e0..ba4e0aaed463 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
| @@ -64,6 +64,8 @@ | |||
| 64 | #define CX23885_BOARD_HAUPPAUGE_HVR1700 8 | 64 | #define CX23885_BOARD_HAUPPAUGE_HVR1700 8 |
| 65 | #define CX23885_BOARD_HAUPPAUGE_HVR1400 9 | 65 | #define CX23885_BOARD_HAUPPAUGE_HVR1400 9 |
| 66 | #define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10 | 66 | #define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10 |
| 67 | #define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11 | ||
| 68 | #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12 | ||
| 67 | 69 | ||
| 68 | /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ | 70 | /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ |
| 69 | #define CX23885_NORMS (\ | 71 | #define CX23885_NORMS (\ |
| @@ -409,7 +411,7 @@ extern const unsigned int cx23885_bcount; | |||
| 409 | extern struct cx23885_subid cx23885_subids[]; | 411 | extern struct cx23885_subid cx23885_subids[]; |
| 410 | extern const unsigned int cx23885_idcount; | 412 | extern const unsigned int cx23885_idcount; |
| 411 | 413 | ||
| 412 | extern int cx23885_tuner_callback(void *priv, int command, int arg); | 414 | extern int cx23885_tuner_callback(void *priv, int component, int command, int arg); |
| 413 | extern void cx23885_card_list(struct cx23885_dev *dev); | 415 | extern void cx23885_card_list(struct cx23885_dev *dev); |
| 414 | extern int cx23885_ir_init(struct cx23885_dev *dev); | 416 | extern int cx23885_ir_init(struct cx23885_dev *dev); |
| 415 | extern void cx23885_gpio_setup(struct cx23885_dev *dev); | 417 | extern void cx23885_gpio_setup(struct cx23885_dev *dev); |
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 69f2bbdbb929..58e6ef1c28a0 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c | |||
| @@ -141,10 +141,11 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
| 141 | u8 lcr[24]; | 141 | u8 lcr[24]; |
| 142 | 142 | ||
| 143 | fmt = arg; | 143 | fmt = arg; |
| 144 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | 144 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE && |
| 145 | fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE) | ||
| 145 | return -EINVAL; | 146 | return -EINVAL; |
| 146 | svbi = &fmt->fmt.sliced; | 147 | svbi = &fmt->fmt.sliced; |
| 147 | if (svbi->service_set == 0) { | 148 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
| 148 | /* raw VBI */ | 149 | /* raw VBI */ |
| 149 | memset(svbi, 0, sizeof(*svbi)); | 150 | memset(svbi, 0, sizeof(*svbi)); |
| 150 | 151 | ||
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 9dd7bdf659b9..0b9e5fac6239 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
| @@ -58,6 +58,10 @@ config VIDEO_CX88_DVB | |||
| 58 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE | 58 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE |
| 59 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | 59 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE |
| 60 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | 60 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE |
| 61 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | ||
| 62 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
| 63 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | ||
| 64 | select DVB_STB6000 if !DVB_FE_CUSTOMISE | ||
| 61 | ---help--- | 65 | ---help--- |
| 62 | This adds support for DVB/ATSC cards based on the | 66 | This adds support for DVB/ATSC cards based on the |
| 63 | Conexant 2388x chip. | 67 | Conexant 2388x chip. |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 9a1374a38ec7..e71369754305 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
| @@ -1057,12 +1057,15 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
| 1057 | struct cx8802_driver *drv = NULL; | 1057 | struct cx8802_driver *drv = NULL; |
| 1058 | int err; | 1058 | int err; |
| 1059 | 1059 | ||
| 1060 | lock_kernel(); | ||
| 1060 | dev = cx8802_get_device(inode); | 1061 | dev = cx8802_get_device(inode); |
| 1061 | 1062 | ||
| 1062 | dprintk( 1, "%s\n", __func__); | 1063 | dprintk( 1, "%s\n", __func__); |
| 1063 | 1064 | ||
| 1064 | if (dev == NULL) | 1065 | if (dev == NULL) { |
| 1066 | unlock_kernel(); | ||
| 1065 | return -ENODEV; | 1067 | return -ENODEV; |
| 1068 | } | ||
| 1066 | 1069 | ||
| 1067 | /* Make sure we can acquire the hardware */ | 1070 | /* Make sure we can acquire the hardware */ |
| 1068 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | 1071 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); |
| @@ -1070,6 +1073,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
| 1070 | err = drv->request_acquire(drv); | 1073 | err = drv->request_acquire(drv); |
| 1071 | if(err != 0) { | 1074 | if(err != 0) { |
| 1072 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); | 1075 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); |
| 1076 | unlock_kernel(); | ||
| 1073 | return err; | 1077 | return err; |
| 1074 | } | 1078 | } |
| 1075 | } | 1079 | } |
| @@ -1077,6 +1081,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
| 1077 | if (blackbird_initialize_codec(dev) < 0) { | 1081 | if (blackbird_initialize_codec(dev) < 0) { |
| 1078 | if (drv) | 1082 | if (drv) |
| 1079 | drv->request_release(drv); | 1083 | drv->request_release(drv); |
| 1084 | unlock_kernel(); | ||
| 1080 | return -EINVAL; | 1085 | return -EINVAL; |
| 1081 | } | 1086 | } |
| 1082 | dprintk(1,"open minor=%d\n",minor); | 1087 | dprintk(1,"open minor=%d\n",minor); |
| @@ -1086,6 +1091,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
| 1086 | if (NULL == fh) { | 1091 | if (NULL == fh) { |
| 1087 | if (drv) | 1092 | if (drv) |
| 1088 | drv->request_release(drv); | 1093 | drv->request_release(drv); |
| 1094 | unlock_kernel(); | ||
| 1089 | return -ENOMEM; | 1095 | return -ENOMEM; |
| 1090 | } | 1096 | } |
| 1091 | file->private_data = fh; | 1097 | file->private_data = fh; |
| @@ -1101,6 +1107,7 @@ static int mpeg_open(struct inode *inode, struct file *file) | |||
| 1101 | /* FIXME: locking against other video device */ | 1107 | /* FIXME: locking against other video device */ |
| 1102 | cx88_set_scale(dev->core, dev->width, dev->height, | 1108 | cx88_set_scale(dev->core, dev->width, dev->height, |
| 1103 | fh->mpegq.field); | 1109 | fh->mpegq.field); |
| 1110 | unlock_kernel(); | ||
| 1104 | 1111 | ||
| 1105 | return 0; | 1112 | return 0; |
| 1106 | } | 1113 | } |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index de199a206a15..5da04e811ca2 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
| @@ -1349,27 +1349,30 @@ static const struct cx88_board cx88_boards[] = { | |||
| 1349 | .radio_addr = ADDR_UNSET, | 1349 | .radio_addr = ADDR_UNSET, |
| 1350 | .tda9887_conf = TDA9887_PRESENT, | 1350 | .tda9887_conf = TDA9887_PRESENT, |
| 1351 | .audio_chip = V4L2_IDENT_WM8775, | 1351 | .audio_chip = V4L2_IDENT_WM8775, |
| 1352 | /* | ||
| 1353 | * gpio0 as reported by Mike Crash <mike AT mikecrash.com> | ||
| 1354 | */ | ||
| 1352 | .input = {{ | 1355 | .input = {{ |
| 1353 | .type = CX88_VMUX_TELEVISION, | 1356 | .type = CX88_VMUX_TELEVISION, |
| 1354 | .vmux = 0, | 1357 | .vmux = 0, |
| 1355 | .gpio0 = 0xe780, | 1358 | .gpio0 = 0xef88, |
| 1356 | .audioroute = 1, | 1359 | .audioroute = 1, |
| 1357 | },{ | 1360 | },{ |
| 1358 | .type = CX88_VMUX_COMPOSITE1, | 1361 | .type = CX88_VMUX_COMPOSITE1, |
| 1359 | .vmux = 1, | 1362 | .vmux = 1, |
| 1360 | .gpio0 = 0xe780, | 1363 | .gpio0 = 0xef88, |
| 1361 | .audioroute = 2, | 1364 | .audioroute = 2, |
| 1362 | },{ | 1365 | },{ |
| 1363 | .type = CX88_VMUX_SVIDEO, | 1366 | .type = CX88_VMUX_SVIDEO, |
| 1364 | .vmux = 2, | 1367 | .vmux = 2, |
| 1365 | .gpio0 = 0xe780, | 1368 | .gpio0 = 0xef88, |
| 1366 | .audioroute = 2, | 1369 | .audioroute = 2, |
| 1367 | }}, | 1370 | }}, |
| 1368 | /* fixme: Add radio support */ | 1371 | /* fixme: Add radio support */ |
| 1369 | .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, | 1372 | .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, |
| 1370 | .radio = { | 1373 | .radio = { |
| 1371 | .type = CX88_RADIO, | 1374 | .type = CX88_RADIO, |
| 1372 | .gpio0 = 0xe780, | 1375 | .gpio0 = 0xef88, |
| 1373 | }, | 1376 | }, |
| 1374 | }, | 1377 | }, |
| 1375 | [CX88_BOARD_ADSTECH_PTV_390] = { | 1378 | [CX88_BOARD_ADSTECH_PTV_390] = { |
| @@ -1446,15 +1449,26 @@ static const struct cx88_board cx88_boards[] = { | |||
| 1446 | .name = "Pinnacle Hybrid PCTV", | 1449 | .name = "Pinnacle Hybrid PCTV", |
| 1447 | .tuner_type = TUNER_XC2028, | 1450 | .tuner_type = TUNER_XC2028, |
| 1448 | .tuner_addr = 0x61, | 1451 | .tuner_addr = 0x61, |
| 1452 | .radio_type = TUNER_XC2028, | ||
| 1453 | .radio_addr = 0x61, | ||
| 1449 | .input = { { | 1454 | .input = { { |
| 1450 | .type = CX88_VMUX_TELEVISION, | 1455 | .type = CX88_VMUX_TELEVISION, |
| 1451 | .vmux = 0, | 1456 | .vmux = 0, |
| 1457 | .gpio0 = 0x004ff, | ||
| 1458 | .gpio1 = 0x010ff, | ||
| 1459 | .gpio2 = 0x00001, | ||
| 1452 | }, { | 1460 | }, { |
| 1453 | .type = CX88_VMUX_COMPOSITE1, | 1461 | .type = CX88_VMUX_COMPOSITE1, |
| 1454 | .vmux = 1, | 1462 | .vmux = 1, |
| 1463 | .gpio0 = 0x004fb, | ||
| 1464 | .gpio1 = 0x010ef, | ||
| 1465 | .audioroute = 1, | ||
| 1455 | }, { | 1466 | }, { |
| 1456 | .type = CX88_VMUX_SVIDEO, | 1467 | .type = CX88_VMUX_SVIDEO, |
| 1457 | .vmux = 2, | 1468 | .vmux = 2, |
| 1469 | .gpio0 = 0x004fb, | ||
| 1470 | .gpio1 = 0x010ef, | ||
| 1471 | .audioroute = 1, | ||
| 1458 | } }, | 1472 | } }, |
| 1459 | .radio = { | 1473 | .radio = { |
| 1460 | .type = CX88_RADIO, | 1474 | .type = CX88_RADIO, |
| @@ -1462,6 +1476,7 @@ static const struct cx88_board cx88_boards[] = { | |||
| 1462 | .gpio1 = 0x010ff, | 1476 | .gpio1 = 0x010ff, |
| 1463 | .gpio2 = 0x0ff, | 1477 | .gpio2 = 0x0ff, |
| 1464 | }, | 1478 | }, |
| 1479 | .mpeg = CX88_MPEG_DVB, | ||
| 1465 | }, | 1480 | }, |
| 1466 | [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { | 1481 | [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { |
| 1467 | .name = "Winfast TV2000 XP Global", | 1482 | .name = "Winfast TV2000 XP Global", |
| @@ -1566,9 +1581,9 @@ static const struct cx88_board cx88_boards[] = { | |||
| 1566 | }, | 1581 | }, |
| 1567 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { | 1582 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { |
| 1568 | .name = "DViCO FusionHDTV DVB-T PRO", | 1583 | .name = "DViCO FusionHDTV DVB-T PRO", |
| 1569 | .tuner_type = TUNER_ABSENT, /* XXX: Has XC3028 */ | 1584 | .tuner_type = TUNER_XC2028, |
| 1585 | .tuner_addr = 0x61, | ||
| 1570 | .radio_type = UNSET, | 1586 | .radio_type = UNSET, |
| 1571 | .tuner_addr = ADDR_UNSET, | ||
| 1572 | .radio_addr = ADDR_UNSET, | 1587 | .radio_addr = ADDR_UNSET, |
| 1573 | .input = { { | 1588 | .input = { { |
| 1574 | .type = CX88_VMUX_COMPOSITE1, | 1589 | .type = CX88_VMUX_COMPOSITE1, |
| @@ -1625,6 +1640,36 @@ static const struct cx88_board cx88_boards[] = { | |||
| 1625 | .gpio2 = 0x0cfb, | 1640 | .gpio2 = 0x0cfb, |
| 1626 | }, | 1641 | }, |
| 1627 | }, | 1642 | }, |
| 1643 | [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = { | ||
| 1644 | .name = "Prolink Pixelview Global Extreme", | ||
| 1645 | .tuner_type = TUNER_XC2028, | ||
| 1646 | .tuner_addr = 0x61, | ||
| 1647 | .input = { { | ||
| 1648 | .type = CX88_VMUX_TELEVISION, | ||
| 1649 | .vmux = 0, | ||
| 1650 | .gpio0 = 0x04fb, | ||
| 1651 | .gpio1 = 0x04080, | ||
| 1652 | .gpio2 = 0x0cf7, | ||
| 1653 | }, { | ||
| 1654 | .type = CX88_VMUX_COMPOSITE1, | ||
| 1655 | .vmux = 1, | ||
| 1656 | .gpio0 = 0x04fb, | ||
| 1657 | .gpio1 = 0x04080, | ||
| 1658 | .gpio2 = 0x0cfb, | ||
| 1659 | }, { | ||
| 1660 | .type = CX88_VMUX_SVIDEO, | ||
| 1661 | .vmux = 2, | ||
| 1662 | .gpio0 = 0x04fb, | ||
| 1663 | .gpio1 = 0x04080, | ||
| 1664 | .gpio2 = 0x0cfb, | ||
| 1665 | } }, | ||
| 1666 | .radio = { | ||
| 1667 | .type = CX88_RADIO, | ||
| 1668 | .gpio0 = 0x04ff, | ||
| 1669 | .gpio1 = 0x04080, | ||
| 1670 | .gpio2 = 0x0cf7, | ||
| 1671 | }, | ||
| 1672 | }, | ||
| 1628 | /* Both radio, analog and ATSC work with this board. | 1673 | /* Both radio, analog and ATSC work with this board. |
| 1629 | However, for analog to work, s5h1409 gate should be open, | 1674 | However, for analog to work, s5h1409 gate should be open, |
| 1630 | otherwise, tuner-xc3028 won't be detected. | 1675 | otherwise, tuner-xc3028 won't be detected. |
| @@ -1664,6 +1709,131 @@ static const struct cx88_board cx88_boards[] = { | |||
| 1664 | }, | 1709 | }, |
| 1665 | .mpeg = CX88_MPEG_DVB, | 1710 | .mpeg = CX88_MPEG_DVB, |
| 1666 | }, | 1711 | }, |
| 1712 | [CX88_BOARD_HAUPPAUGE_HVR4000] = { | ||
| 1713 | .name = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid", | ||
| 1714 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, | ||
| 1715 | .radio_type = UNSET, | ||
| 1716 | .tuner_addr = ADDR_UNSET, | ||
| 1717 | .radio_addr = ADDR_UNSET, | ||
| 1718 | .tda9887_conf = TDA9887_PRESENT, | ||
| 1719 | /* | ||
| 1720 | * GPIO0 (WINTV2000) | ||
| 1721 | * | ||
| 1722 | * Analogue SAT DVB-T | ||
| 1723 | * Antenna 0xc4bf 0xc4bb | ||
| 1724 | * Composite 0xc4bf 0xc4bb | ||
| 1725 | * S-Video 0xc4bf 0xc4bb | ||
| 1726 | * Composite1 0xc4ff 0xc4fb | ||
| 1727 | * S-Video1 0xc4ff 0xc4fb | ||
| 1728 | * | ||
| 1729 | * BIT VALUE FUNCTION GP{x}_IO | ||
| 1730 | * 0 1 I:? | ||
| 1731 | * 1 1 I:? | ||
| 1732 | * 2 1 O:DVB-T DEMOD ENABLE LOW/ANALOG DEMOD ENABLE HIGH | ||
| 1733 | * 3 1 I:? | ||
| 1734 | * 4 1 I:? | ||
| 1735 | * 5 1 I:? | ||
| 1736 | * 6 0 O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION | ||
| 1737 | * 7 1 O:DVB-T DEMOD RESET LOW | ||
| 1738 | * | ||
| 1739 | * BIT VALUE FUNCTION GP{x}_OE | ||
| 1740 | * 8 0 I | ||
| 1741 | * 9 0 I | ||
| 1742 | * a 1 O | ||
| 1743 | * b 0 I | ||
| 1744 | * c 0 I | ||
| 1745 | * d 0 I | ||
| 1746 | * e 1 O | ||
| 1747 | * f 1 O | ||
| 1748 | */ | ||
| 1749 | .input = {{ | ||
| 1750 | .type = CX88_VMUX_TELEVISION, | ||
| 1751 | .vmux = 0, | ||
| 1752 | .gpio0 = 0xc4bf, | ||
| 1753 | }, { | ||
| 1754 | .type = CX88_VMUX_COMPOSITE1, | ||
| 1755 | .vmux = 1, | ||
| 1756 | .gpio0 = 0xc4bf, | ||
| 1757 | }, { | ||
| 1758 | .type = CX88_VMUX_SVIDEO, | ||
| 1759 | .vmux = 2, | ||
| 1760 | .gpio0 = 0xc4bf, | ||
| 1761 | } }, | ||
| 1762 | /* fixme: Add radio support */ | ||
| 1763 | .mpeg = CX88_MPEG_DVB, | ||
| 1764 | }, | ||
| 1765 | [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = { | ||
| 1766 | .name = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2", | ||
| 1767 | .tuner_type = UNSET, | ||
| 1768 | .radio_type = UNSET, | ||
| 1769 | .tuner_addr = ADDR_UNSET, | ||
| 1770 | .radio_addr = ADDR_UNSET, | ||
| 1771 | .input = {{ | ||
| 1772 | .type = CX88_VMUX_DVB, | ||
| 1773 | .vmux = 0, | ||
| 1774 | } }, | ||
| 1775 | .mpeg = CX88_MPEG_DVB, | ||
| 1776 | }, | ||
| 1777 | [CX88_BOARD_TEVII_S420] = { | ||
| 1778 | .name = "TeVii S420 DVB-S", | ||
| 1779 | .tuner_type = UNSET, | ||
| 1780 | .radio_type = UNSET, | ||
| 1781 | .tuner_addr = ADDR_UNSET, | ||
| 1782 | .radio_addr = ADDR_UNSET, | ||
| 1783 | .input = {{ | ||
| 1784 | .type = CX88_VMUX_DVB, | ||
| 1785 | .vmux = 0, | ||
| 1786 | } }, | ||
| 1787 | .mpeg = CX88_MPEG_DVB, | ||
| 1788 | }, | ||
| 1789 | [CX88_BOARD_TEVII_S460] = { | ||
| 1790 | .name = "TeVii S460 DVB-S/S2", | ||
| 1791 | .tuner_type = UNSET, | ||
| 1792 | .radio_type = UNSET, | ||
| 1793 | .tuner_addr = ADDR_UNSET, | ||
| 1794 | .radio_addr = ADDR_UNSET, | ||
| 1795 | .input = {{ | ||
| 1796 | .type = CX88_VMUX_DVB, | ||
| 1797 | .vmux = 0, | ||
| 1798 | } }, | ||
| 1799 | .mpeg = CX88_MPEG_DVB, | ||
| 1800 | }, | ||
| 1801 | [CX88_BOARD_OMICOM_SS4_PCI] = { | ||
| 1802 | .name = "Omicom SS4 DVB-S/S2 PCI", | ||
| 1803 | .tuner_type = UNSET, | ||
| 1804 | .radio_type = UNSET, | ||
| 1805 | .tuner_addr = ADDR_UNSET, | ||
| 1806 | .radio_addr = ADDR_UNSET, | ||
| 1807 | .input = {{ | ||
| 1808 | .type = CX88_VMUX_DVB, | ||
| 1809 | .vmux = 0, | ||
| 1810 | } }, | ||
| 1811 | .mpeg = CX88_MPEG_DVB, | ||
| 1812 | }, | ||
| 1813 | [CX88_BOARD_TBS_8920] = { | ||
| 1814 | .name = "TBS 8920 DVB-S/S2", | ||
| 1815 | .tuner_type = TUNER_ABSENT, | ||
| 1816 | .radio_type = UNSET, | ||
| 1817 | .tuner_addr = ADDR_UNSET, | ||
| 1818 | .radio_addr = ADDR_UNSET, | ||
| 1819 | .input = {{ | ||
| 1820 | .type = CX88_VMUX_DVB, | ||
| 1821 | .vmux = 1, | ||
| 1822 | } }, | ||
| 1823 | .mpeg = CX88_MPEG_DVB, | ||
| 1824 | }, | ||
| 1825 | [CX88_BOARD_PROF_7300] = { | ||
| 1826 | .name = "PROF 7300 DVB-S/S2", | ||
| 1827 | .tuner_type = UNSET, | ||
| 1828 | .radio_type = UNSET, | ||
| 1829 | .tuner_addr = ADDR_UNSET, | ||
| 1830 | .radio_addr = ADDR_UNSET, | ||
| 1831 | .input = {{ | ||
| 1832 | .type = CX88_VMUX_DVB, | ||
| 1833 | .vmux = 0, | ||
| 1834 | } }, | ||
| 1835 | .mpeg = CX88_MPEG_DVB, | ||
| 1836 | }, | ||
| 1667 | }; | 1837 | }; |
| 1668 | 1838 | ||
| 1669 | /* ------------------------------------------------------------------ */ | 1839 | /* ------------------------------------------------------------------ */ |
| @@ -2010,9 +2180,53 @@ static const struct cx88_subid cx88_subids[] = { | |||
| 2010 | .subdevice = 0x4935, | 2180 | .subdevice = 0x4935, |
| 2011 | .card = CX88_BOARD_PROLINK_PV_8000GT, | 2181 | .card = CX88_BOARD_PROLINK_PV_8000GT, |
| 2012 | }, { | 2182 | }, { |
| 2183 | .subvendor = 0x1554, | ||
| 2184 | .subdevice = 0x4976, | ||
| 2185 | .card = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME, | ||
| 2186 | }, { | ||
| 2013 | .subvendor = 0x17de, | 2187 | .subvendor = 0x17de, |
| 2014 | .subdevice = 0x08c1, | 2188 | .subdevice = 0x08c1, |
| 2015 | .card = CX88_BOARD_KWORLD_ATSC_120, | 2189 | .card = CX88_BOARD_KWORLD_ATSC_120, |
| 2190 | }, { | ||
| 2191 | .subvendor = 0x0070, | ||
| 2192 | .subdevice = 0x6900, | ||
| 2193 | .card = CX88_BOARD_HAUPPAUGE_HVR4000, | ||
| 2194 | }, { | ||
| 2195 | .subvendor = 0x0070, | ||
| 2196 | .subdevice = 0x6904, | ||
| 2197 | .card = CX88_BOARD_HAUPPAUGE_HVR4000, | ||
| 2198 | }, { | ||
| 2199 | .subvendor = 0x0070, | ||
| 2200 | .subdevice = 0x6902, | ||
| 2201 | .card = CX88_BOARD_HAUPPAUGE_HVR4000, | ||
| 2202 | }, { | ||
| 2203 | .subvendor = 0x0070, | ||
| 2204 | .subdevice = 0x6905, | ||
| 2205 | .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE, | ||
| 2206 | }, { | ||
| 2207 | .subvendor = 0x0070, | ||
| 2208 | .subdevice = 0x6906, | ||
| 2209 | .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE, | ||
| 2210 | }, { | ||
| 2211 | .subvendor = 0xd420, | ||
| 2212 | .subdevice = 0x9022, | ||
| 2213 | .card = CX88_BOARD_TEVII_S420, | ||
| 2214 | }, { | ||
| 2215 | .subvendor = 0xd460, | ||
| 2216 | .subdevice = 0x9022, | ||
| 2217 | .card = CX88_BOARD_TEVII_S460, | ||
| 2218 | }, { | ||
| 2219 | .subvendor = 0xA044, | ||
| 2220 | .subdevice = 0x2011, | ||
| 2221 | .card = CX88_BOARD_OMICOM_SS4_PCI, | ||
| 2222 | }, { | ||
| 2223 | .subvendor = 0x8920, | ||
| 2224 | .subdevice = 0x8888, | ||
| 2225 | .card = CX88_BOARD_TBS_8920, | ||
| 2226 | }, { | ||
| 2227 | .subvendor = 0xB033, | ||
| 2228 | .subdevice = 0x3033, | ||
| 2229 | .card = CX88_BOARD_PROF_7300, | ||
| 2016 | }, | 2230 | }, |
| 2017 | }; | 2231 | }; |
| 2018 | 2232 | ||
| @@ -2065,6 +2279,13 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
| 2065 | case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */ | 2279 | case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */ |
| 2066 | case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ | 2280 | case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ |
| 2067 | case 34519: /* WinTV-PCI-FM */ | 2281 | case 34519: /* WinTV-PCI-FM */ |
| 2282 | case 69009: | ||
| 2283 | /* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */ | ||
| 2284 | case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */ | ||
| 2285 | case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */ | ||
| 2286 | case 69559: | ||
| 2287 | /* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */ | ||
| 2288 | case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */ | ||
| 2068 | case 90002: /* Nova-T-PCI (9002) */ | 2289 | case 90002: /* Nova-T-PCI (9002) */ |
| 2069 | case 92001: /* Nova-S-Plus (Video and IR) */ | 2290 | case 92001: /* Nova-S-Plus (Video and IR) */ |
| 2070 | case 92002: /* Nova-S-Plus (Video and IR) */ | 2291 | case 92002: /* Nova-S-Plus (Video and IR) */ |
| @@ -2149,9 +2370,21 @@ static int cx88_dvico_xc2028_callback(struct cx88_core *core, | |||
| 2149 | { | 2370 | { |
| 2150 | switch (command) { | 2371 | switch (command) { |
| 2151 | case XC2028_TUNER_RESET: | 2372 | case XC2028_TUNER_RESET: |
| 2152 | cx_write(MO_GP0_IO, 0x101000); | 2373 | switch (core->boardnr) { |
| 2153 | mdelay(5); | 2374 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: |
| 2154 | cx_set(MO_GP0_IO, 0x101010); | 2375 | /* GPIO-4 xc3028 tuner */ |
| 2376 | |||
| 2377 | cx_set(MO_GP0_IO, 0x00001000); | ||
| 2378 | cx_clear(MO_GP0_IO, 0x00000010); | ||
| 2379 | msleep(100); | ||
| 2380 | cx_set(MO_GP0_IO, 0x00000010); | ||
| 2381 | msleep(100); | ||
| 2382 | break; | ||
| 2383 | default: | ||
| 2384 | cx_write(MO_GP0_IO, 0x101000); | ||
| 2385 | mdelay(5); | ||
| 2386 | cx_set(MO_GP0_IO, 0x101010); | ||
| 2387 | } | ||
| 2155 | break; | 2388 | break; |
| 2156 | default: | 2389 | default: |
| 2157 | return -EINVAL; | 2390 | return -EINVAL; |
| @@ -2258,8 +2491,10 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, | |||
| 2258 | return cx88_xc3028_geniatech_tuner_callback(core, | 2491 | return cx88_xc3028_geniatech_tuner_callback(core, |
| 2259 | command, arg); | 2492 | command, arg); |
| 2260 | case CX88_BOARD_PROLINK_PV_8000GT: | 2493 | case CX88_BOARD_PROLINK_PV_8000GT: |
| 2494 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: | ||
| 2261 | return cx88_pv_8000gt_callback(core, command, arg); | 2495 | return cx88_pv_8000gt_callback(core, command, arg); |
| 2262 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: | 2496 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: |
| 2497 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | ||
| 2263 | return cx88_dvico_xc2028_callback(core, command, arg); | 2498 | return cx88_dvico_xc2028_callback(core, command, arg); |
| 2264 | } | 2499 | } |
| 2265 | 2500 | ||
| @@ -2327,7 +2562,7 @@ static int cx88_xc5000_tuner_callback(struct cx88_core *core, | |||
| 2327 | return 0; /* Should never be here */ | 2562 | return 0; /* Should never be here */ |
| 2328 | } | 2563 | } |
| 2329 | 2564 | ||
| 2330 | int cx88_tuner_callback(void *priv, int command, int arg) | 2565 | int cx88_tuner_callback(void *priv, int component, int command, int arg) |
| 2331 | { | 2566 | { |
| 2332 | struct i2c_algo_bit_data *i2c_algo = priv; | 2567 | struct i2c_algo_bit_data *i2c_algo = priv; |
| 2333 | struct cx88_core *core; | 2568 | struct cx88_core *core; |
| @@ -2344,6 +2579,9 @@ int cx88_tuner_callback(void *priv, int command, int arg) | |||
| 2344 | return -EINVAL; | 2579 | return -EINVAL; |
| 2345 | } | 2580 | } |
| 2346 | 2581 | ||
| 2582 | if (component != DVB_FRONTEND_COMPONENT_TUNER) | ||
| 2583 | return -EINVAL; | ||
| 2584 | |||
| 2347 | switch (core->board.tuner_type) { | 2585 | switch (core->board.tuner_type) { |
| 2348 | case TUNER_XC2028: | 2586 | case TUNER_XC2028: |
| 2349 | info_printk(core, "Calling XC2028/3028 callback\n"); | 2587 | info_printk(core, "Calling XC2028/3028 callback\n"); |
| @@ -2392,16 +2630,22 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) | |||
| 2392 | { | 2630 | { |
| 2393 | switch (core->boardnr) { | 2631 | switch (core->boardnr) { |
| 2394 | case CX88_BOARD_HAUPPAUGE_HVR1300: | 2632 | case CX88_BOARD_HAUPPAUGE_HVR1300: |
| 2395 | /* Bring the 702 demod up before i2c scanning/attach or devices are hidden */ | 2633 | /* |
| 2396 | /* We leave here with the 702 on the bus */ | 2634 | * Bring the 702 demod up before i2c scanning/attach or devices are hidden |
| 2397 | cx_write(MO_GP0_IO, 0x0000e780); | 2635 | * We leave here with the 702 on the bus |
| 2636 | * | ||
| 2637 | * "reset the IR receiver on GPIO[3]" | ||
| 2638 | * Reported by Mike Crash <mike AT mikecrash.com> | ||
| 2639 | */ | ||
| 2640 | cx_write(MO_GP0_IO, 0x0000ef88); | ||
| 2398 | udelay(1000); | 2641 | udelay(1000); |
| 2399 | cx_clear(MO_GP0_IO, 0x00000080); | 2642 | cx_clear(MO_GP0_IO, 0x00000088); |
| 2400 | udelay(50); | 2643 | udelay(50); |
| 2401 | cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ | 2644 | cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */ |
| 2402 | udelay(1000); | 2645 | udelay(1000); |
| 2403 | break; | 2646 | break; |
| 2404 | 2647 | ||
| 2648 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: | ||
| 2405 | case CX88_BOARD_PROLINK_PV_8000GT: | 2649 | case CX88_BOARD_PROLINK_PV_8000GT: |
| 2406 | cx_write(MO_GP2_IO, 0xcf7); | 2650 | cx_write(MO_GP2_IO, 0xcf7); |
| 2407 | mdelay(50); | 2651 | mdelay(50); |
| @@ -2411,10 +2655,18 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) | |||
| 2411 | msleep(10); | 2655 | msleep(10); |
| 2412 | break; | 2656 | break; |
| 2413 | 2657 | ||
| 2414 | case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: | 2658 | case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: |
| 2415 | /* Enable the xc5000 tuner */ | 2659 | /* Enable the xc5000 tuner */ |
| 2416 | cx_set(MO_GP0_IO, 0x00001010); | 2660 | cx_set(MO_GP0_IO, 0x00001010); |
| 2417 | break; | 2661 | break; |
| 2662 | |||
| 2663 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
| 2664 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
| 2665 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
| 2666 | /* Init GPIO */ | ||
| 2667 | cx_write(MO_GP0_IO, core->board.input[0].gpio0); | ||
| 2668 | udelay(1000); | ||
| 2669 | break; | ||
| 2418 | } | 2670 | } |
| 2419 | } | 2671 | } |
| 2420 | 2672 | ||
| @@ -2435,17 +2687,22 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) | |||
| 2435 | core->i2c_algo.udelay = 16; | 2687 | core->i2c_algo.udelay = 16; |
| 2436 | break; | 2688 | break; |
| 2437 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: | 2689 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: |
| 2438 | ctl->scode_table = XC3028_FE_ZARLINK456; | 2690 | ctl->demod = XC3028_FE_ZARLINK456; |
| 2439 | break; | 2691 | break; |
| 2440 | case CX88_BOARD_KWORLD_ATSC_120: | 2692 | case CX88_BOARD_KWORLD_ATSC_120: |
| 2441 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | 2693 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: |
| 2442 | ctl->demod = XC3028_FE_OREN538; | 2694 | ctl->demod = XC3028_FE_OREN538; |
| 2443 | break; | 2695 | break; |
| 2696 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: | ||
| 2444 | case CX88_BOARD_PROLINK_PV_8000GT: | 2697 | case CX88_BOARD_PROLINK_PV_8000GT: |
| 2445 | /* | 2698 | /* |
| 2446 | * This board uses non-MTS firmware | 2699 | * Those boards uses non-MTS firmware |
| 2447 | */ | 2700 | */ |
| 2448 | break; | 2701 | break; |
| 2702 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: | ||
| 2703 | ctl->demod = XC3028_FE_ZARLINK456; | ||
| 2704 | ctl->mts = 1; | ||
| 2705 | break; | ||
| 2449 | default: | 2706 | default: |
| 2450 | ctl->demod = XC3028_FE_OREN538; | 2707 | ctl->demod = XC3028_FE_OREN538; |
| 2451 | ctl->mts = 1; | 2708 | ctl->mts = 1; |
| @@ -2489,6 +2746,8 @@ static void cx88_card_setup(struct cx88_core *core) | |||
| 2489 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | 2746 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: |
| 2490 | case CX88_BOARD_HAUPPAUGE_HVR3000: | 2747 | case CX88_BOARD_HAUPPAUGE_HVR3000: |
| 2491 | case CX88_BOARD_HAUPPAUGE_HVR1300: | 2748 | case CX88_BOARD_HAUPPAUGE_HVR1300: |
| 2749 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
| 2750 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
| 2492 | if (0 == core->i2c_rc) | 2751 | if (0 == core->i2c_rc) |
| 2493 | hauppauge_eeprom(core, eeprom); | 2752 | hauppauge_eeprom(core, eeprom); |
| 2494 | break; | 2753 | break; |
| @@ -2570,7 +2829,18 @@ static void cx88_card_setup(struct cx88_core *core) | |||
| 2570 | tea5767_cfg.priv = &ctl; | 2829 | tea5767_cfg.priv = &ctl; |
| 2571 | 2830 | ||
| 2572 | cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); | 2831 | cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg); |
| 2832 | break; | ||
| 2573 | } | 2833 | } |
| 2834 | case CX88_BOARD_TEVII_S420: | ||
| 2835 | case CX88_BOARD_TEVII_S460: | ||
| 2836 | case CX88_BOARD_OMICOM_SS4_PCI: | ||
| 2837 | case CX88_BOARD_TBS_8920: | ||
| 2838 | case CX88_BOARD_PROF_7300: | ||
| 2839 | cx_write(MO_SRST_IO, 0); | ||
| 2840 | msleep(100); | ||
| 2841 | cx_write(MO_SRST_IO, 1); | ||
| 2842 | msleep(100); | ||
| 2843 | break; | ||
| 2574 | } /*end switch() */ | 2844 | } /*end switch() */ |
| 2575 | 2845 | ||
| 2576 | 2846 | ||
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index d96173ff1dba..344ed2626e59 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
| @@ -48,6 +48,11 @@ | |||
| 48 | #include "tuner-simple.h" | 48 | #include "tuner-simple.h" |
| 49 | #include "tda9887.h" | 49 | #include "tda9887.h" |
| 50 | #include "s5h1411.h" | 50 | #include "s5h1411.h" |
| 51 | #include "stv0299.h" | ||
| 52 | #include "z0194a.h" | ||
| 53 | #include "stv0288.h" | ||
| 54 | #include "stb6000.h" | ||
| 55 | #include "cx24116.h" | ||
| 51 | 56 | ||
| 52 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); | 57 | MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); |
| 53 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | 58 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); |
| @@ -375,37 +380,28 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, | |||
| 375 | return 0; | 380 | return 0; |
| 376 | } | 381 | } |
| 377 | 382 | ||
| 378 | static int cx88_pci_nano_callback(void *ptr, int command, int arg) | 383 | static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, |
| 384 | fe_sec_voltage_t voltage) | ||
| 379 | { | 385 | { |
| 380 | struct cx88_core *core = ptr; | 386 | struct cx8802_dev *dev= fe->dvb->priv; |
| 381 | 387 | struct cx88_core *core = dev->core; | |
| 382 | switch (command) { | ||
| 383 | case XC2028_TUNER_RESET: | ||
| 384 | /* Send the tuner in then out of reset */ | ||
| 385 | dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg); | ||
| 386 | |||
| 387 | switch (core->boardnr) { | ||
| 388 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | ||
| 389 | /* GPIO-4 xc3028 tuner */ | ||
| 390 | |||
| 391 | cx_set(MO_GP0_IO, 0x00001000); | ||
| 392 | cx_clear(MO_GP0_IO, 0x00000010); | ||
| 393 | msleep(100); | ||
| 394 | cx_set(MO_GP0_IO, 0x00000010); | ||
| 395 | msleep(100); | ||
| 396 | break; | ||
| 397 | } | ||
| 398 | 388 | ||
| 399 | break; | 389 | switch (voltage) { |
| 400 | case XC2028_RESET_CLK: | 390 | case SEC_VOLTAGE_13: |
| 401 | dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg); | 391 | printk("LNB Voltage SEC_VOLTAGE_13\n"); |
| 402 | break; | 392 | cx_write(MO_GP0_IO, 0x00006040); |
| 403 | default: | 393 | break; |
| 404 | dprintk(1, "%s: unknown command %d, arg %d\n", __func__, | 394 | case SEC_VOLTAGE_18: |
| 405 | command, arg); | 395 | printk("LNB Voltage SEC_VOLTAGE_18\n"); |
| 406 | return -EINVAL; | 396 | cx_write(MO_GP0_IO, 0x00006060); |
| 397 | break; | ||
| 398 | case SEC_VOLTAGE_OFF: | ||
| 399 | printk("LNB Voltage SEC_VOLTAGE_off\n"); | ||
| 400 | break; | ||
| 407 | } | 401 | } |
| 408 | 402 | ||
| 403 | if (core->prev_set_voltage) | ||
| 404 | return core->prev_set_voltage(fe, voltage); | ||
| 409 | return 0; | 405 | return 0; |
| 410 | } | 406 | } |
| 411 | 407 | ||
| @@ -456,7 +452,12 @@ static struct s5h1409_config kworld_atsc_120_config = { | |||
| 456 | static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { | 452 | static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { |
| 457 | .i2c_address = 0x64, | 453 | .i2c_address = 0x64, |
| 458 | .if_khz = 5380, | 454 | .if_khz = 5380, |
| 459 | .tuner_callback = cx88_tuner_callback, | 455 | }; |
| 456 | |||
| 457 | static struct zl10353_config cx88_pinnacle_hybrid_pctv = { | ||
| 458 | .demod_address = (0x1e >> 1), | ||
| 459 | .no_tuner = 1, | ||
| 460 | .if2 = 45600, | ||
| 460 | }; | 461 | }; |
| 461 | 462 | ||
| 462 | static struct zl10353_config cx88_geniatech_x8000_mt = { | 463 | static struct zl10353_config cx88_geniatech_x8000_mt = { |
| @@ -477,7 +478,6 @@ static struct s5h1411_config dvico_fusionhdtv7_config = { | |||
| 477 | static struct xc5000_config dvico_fusionhdtv7_tuner_config = { | 478 | static struct xc5000_config dvico_fusionhdtv7_tuner_config = { |
| 478 | .i2c_address = 0xc2 >> 1, | 479 | .i2c_address = 0xc2 >> 1, |
| 479 | .if_khz = 5380, | 480 | .if_khz = 5380, |
| 480 | .tuner_callback = cx88_tuner_callback, | ||
| 481 | }; | 481 | }; |
| 482 | 482 | ||
| 483 | static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | 483 | static int attach_xc3028(u8 addr, struct cx8802_dev *dev) |
| @@ -488,7 +488,6 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | |||
| 488 | .i2c_adap = &dev->core->i2c_adap, | 488 | .i2c_adap = &dev->core->i2c_adap, |
| 489 | .i2c_addr = addr, | 489 | .i2c_addr = addr, |
| 490 | .ctrl = &ctl, | 490 | .ctrl = &ctl, |
| 491 | .callback = cx88_tuner_callback, | ||
| 492 | }; | 491 | }; |
| 493 | 492 | ||
| 494 | if (!dev->dvb.frontend) { | 493 | if (!dev->dvb.frontend) { |
| @@ -518,6 +517,60 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | |||
| 518 | return 0; | 517 | return 0; |
| 519 | } | 518 | } |
| 520 | 519 | ||
| 520 | static int cx24116_set_ts_param(struct dvb_frontend *fe, | ||
| 521 | int is_punctured) | ||
| 522 | { | ||
| 523 | struct cx8802_dev *dev = fe->dvb->priv; | ||
| 524 | dev->ts_gen_cntrl = 0x2; | ||
| 525 | |||
| 526 | return 0; | ||
| 527 | } | ||
| 528 | |||
| 529 | static int cx24116_reset_device(struct dvb_frontend *fe) | ||
| 530 | { | ||
| 531 | struct cx8802_dev *dev = fe->dvb->priv; | ||
| 532 | struct cx88_core *core = dev->core; | ||
| 533 | |||
| 534 | /* Reset the part */ | ||
| 535 | cx_write(MO_SRST_IO, 0); | ||
| 536 | msleep(10); | ||
| 537 | cx_write(MO_SRST_IO, 1); | ||
| 538 | msleep(10); | ||
| 539 | |||
| 540 | return 0; | ||
| 541 | } | ||
| 542 | |||
| 543 | static struct cx24116_config hauppauge_hvr4000_config = { | ||
| 544 | .demod_address = 0x05, | ||
| 545 | .set_ts_params = cx24116_set_ts_param, | ||
| 546 | .reset_device = cx24116_reset_device, | ||
| 547 | }; | ||
| 548 | |||
| 549 | static struct cx24116_config tevii_s460_config = { | ||
| 550 | .demod_address = 0x55, | ||
| 551 | .set_ts_params = cx24116_set_ts_param, | ||
| 552 | .reset_device = cx24116_reset_device, | ||
| 553 | }; | ||
| 554 | |||
| 555 | static struct stv0299_config tevii_tuner_sharp_config = { | ||
| 556 | .demod_address = 0x68, | ||
| 557 | .inittab = sharp_z0194a__inittab, | ||
| 558 | .mclk = 88000000UL, | ||
| 559 | .invert = 1, | ||
| 560 | .skip_reinit = 0, | ||
| 561 | .lock_output = 1, | ||
| 562 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
| 563 | .min_delay_ms = 100, | ||
| 564 | .set_symbol_rate = sharp_z0194a__set_symbol_rate, | ||
| 565 | .set_ts_params = cx24116_set_ts_param, | ||
| 566 | }; | ||
| 567 | |||
| 568 | static struct stv0288_config tevii_tuner_earda_config = { | ||
| 569 | .demod_address = 0x68, | ||
| 570 | .min_delay_ms = 100, | ||
| 571 | .set_ts_params = cx24116_set_ts_param, | ||
| 572 | }; | ||
| 573 | |||
| 521 | static int dvb_register(struct cx8802_dev *dev) | 574 | static int dvb_register(struct cx8802_dev *dev) |
| 522 | { | 575 | { |
| 523 | struct cx88_core *core = dev->core; | 576 | struct cx88_core *core = dev->core; |
| @@ -786,7 +839,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
| 786 | &core->i2c_adap); | 839 | &core->i2c_adap); |
| 787 | if (dev->dvb.frontend) { | 840 | if (dev->dvb.frontend) { |
| 788 | if (!dvb_attach(isl6421_attach, dev->dvb.frontend, | 841 | if (!dvb_attach(isl6421_attach, dev->dvb.frontend, |
| 789 | &core->i2c_adap, 0x08, 0x00, 0x00)) | 842 | &core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) |
| 790 | goto frontend_detach; | 843 | goto frontend_detach; |
| 791 | } | 844 | } |
| 792 | break; | 845 | break; |
| @@ -813,13 +866,9 @@ static int dvb_register(struct cx8802_dev *dev) | |||
| 813 | &pinnacle_pctv_hd_800i_config, | 866 | &pinnacle_pctv_hd_800i_config, |
| 814 | &core->i2c_adap); | 867 | &core->i2c_adap); |
| 815 | if (dev->dvb.frontend != NULL) { | 868 | if (dev->dvb.frontend != NULL) { |
| 816 | /* tuner_config.video_dev must point to | ||
| 817 | * i2c_adap.algo_data | ||
| 818 | */ | ||
| 819 | if (!dvb_attach(xc5000_attach, dev->dvb.frontend, | 869 | if (!dvb_attach(xc5000_attach, dev->dvb.frontend, |
| 820 | &core->i2c_adap, | 870 | &core->i2c_adap, |
| 821 | &pinnacle_pctv_hd_800i_tuner_config, | 871 | &pinnacle_pctv_hd_800i_tuner_config)) |
| 822 | core->i2c_adap.algo_data)) | ||
| 823 | goto frontend_detach; | 872 | goto frontend_detach; |
| 824 | } | 873 | } |
| 825 | break; | 874 | break; |
| @@ -832,10 +881,9 @@ static int dvb_register(struct cx8802_dev *dev) | |||
| 832 | struct xc2028_config cfg = { | 881 | struct xc2028_config cfg = { |
| 833 | .i2c_adap = &core->i2c_adap, | 882 | .i2c_adap = &core->i2c_adap, |
| 834 | .i2c_addr = 0x61, | 883 | .i2c_addr = 0x61, |
| 835 | .callback = cx88_pci_nano_callback, | ||
| 836 | }; | 884 | }; |
| 837 | static struct xc2028_ctrl ctl = { | 885 | static struct xc2028_ctrl ctl = { |
| 838 | .fname = "xc3028-v27.fw", | 886 | .fname = XC2028_DEFAULT_FIRMWARE, |
| 839 | .max_len = 64, | 887 | .max_len = 64, |
| 840 | .scode_table = XC3028_FE_OREN538, | 888 | .scode_table = XC3028_FE_OREN538, |
| 841 | }; | 889 | }; |
| @@ -848,10 +896,13 @@ static int dvb_register(struct cx8802_dev *dev) | |||
| 848 | break; | 896 | break; |
| 849 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: | 897 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: |
| 850 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 898 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
| 851 | &cx88_geniatech_x8000_mt, | 899 | &cx88_pinnacle_hybrid_pctv, |
| 852 | &core->i2c_adap); | 900 | &core->i2c_adap); |
| 853 | if (attach_xc3028(0x61, dev) < 0) | 901 | if (dev->dvb.frontend) { |
| 854 | goto frontend_detach; | 902 | dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; |
| 903 | if (attach_xc3028(0x61, dev) < 0) | ||
| 904 | goto frontend_detach; | ||
| 905 | } | ||
| 855 | break; | 906 | break; |
| 856 | case CX88_BOARD_GENIATECH_X8000_MT: | 907 | case CX88_BOARD_GENIATECH_X8000_MT: |
| 857 | dev->ts_gen_cntrl = 0x00; | 908 | dev->ts_gen_cntrl = 0x00; |
| @@ -874,16 +925,69 @@ static int dvb_register(struct cx8802_dev *dev) | |||
| 874 | &dvico_fusionhdtv7_config, | 925 | &dvico_fusionhdtv7_config, |
| 875 | &core->i2c_adap); | 926 | &core->i2c_adap); |
| 876 | if (dev->dvb.frontend != NULL) { | 927 | if (dev->dvb.frontend != NULL) { |
| 877 | /* tuner_config.video_dev must point to | ||
| 878 | * i2c_adap.algo_data | ||
| 879 | */ | ||
| 880 | if (!dvb_attach(xc5000_attach, dev->dvb.frontend, | 928 | if (!dvb_attach(xc5000_attach, dev->dvb.frontend, |
| 881 | &core->i2c_adap, | 929 | &core->i2c_adap, |
| 882 | &dvico_fusionhdtv7_tuner_config, | 930 | &dvico_fusionhdtv7_tuner_config)) |
| 883 | core->i2c_adap.algo_data)) | ||
| 884 | goto frontend_detach; | 931 | goto frontend_detach; |
| 885 | } | 932 | } |
| 886 | break; | 933 | break; |
| 934 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
| 935 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
| 936 | /* Support for DVB-S only, not DVB-T support */ | ||
| 937 | dev->dvb.frontend = dvb_attach(cx24116_attach, | ||
| 938 | &hauppauge_hvr4000_config, | ||
| 939 | &dev->core->i2c_adap); | ||
| 940 | if (dev->dvb.frontend) { | ||
| 941 | dvb_attach(isl6421_attach, dev->dvb.frontend, | ||
| 942 | &dev->core->i2c_adap, | ||
| 943 | 0x08, ISL6421_DCL, 0x00); | ||
| 944 | } | ||
| 945 | break; | ||
| 946 | case CX88_BOARD_TEVII_S420: | ||
| 947 | dev->dvb.frontend = dvb_attach(stv0299_attach, | ||
| 948 | &tevii_tuner_sharp_config, | ||
| 949 | &core->i2c_adap); | ||
| 950 | if (dev->dvb.frontend != NULL) { | ||
| 951 | if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, | ||
| 952 | &core->i2c_adap, DVB_PLL_OPERA1)) | ||
| 953 | goto frontend_detach; | ||
| 954 | core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | ||
| 955 | dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
| 956 | |||
| 957 | } else { | ||
| 958 | dev->dvb.frontend = dvb_attach(stv0288_attach, | ||
| 959 | &tevii_tuner_earda_config, | ||
| 960 | &core->i2c_adap); | ||
| 961 | if (dev->dvb.frontend != NULL) { | ||
| 962 | if (!dvb_attach(stb6000_attach, dev->dvb.frontend, 0x61, | ||
| 963 | &core->i2c_adap)) | ||
| 964 | goto frontend_detach; | ||
| 965 | core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | ||
| 966 | dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
| 967 | |||
| 968 | } | ||
| 969 | } | ||
| 970 | break; | ||
| 971 | case CX88_BOARD_TEVII_S460: | ||
| 972 | dev->dvb.frontend = dvb_attach(cx24116_attach, | ||
| 973 | &tevii_s460_config, | ||
| 974 | &core->i2c_adap); | ||
| 975 | if (dev->dvb.frontend != NULL) { | ||
| 976 | core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | ||
| 977 | dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
| 978 | } | ||
| 979 | break; | ||
| 980 | case CX88_BOARD_OMICOM_SS4_PCI: | ||
| 981 | case CX88_BOARD_TBS_8920: | ||
| 982 | case CX88_BOARD_PROF_7300: | ||
| 983 | dev->dvb.frontend = dvb_attach(cx24116_attach, | ||
| 984 | &hauppauge_hvr4000_config, | ||
| 985 | &core->i2c_adap); | ||
| 986 | if (dev->dvb.frontend != NULL) { | ||
| 987 | core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | ||
| 988 | dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; | ||
| 989 | } | ||
| 990 | break; | ||
| 887 | default: | 991 | default: |
| 888 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", | 992 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", |
| 889 | core->name); | 993 | core->name); |
| @@ -895,6 +999,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
| 895 | core->name); | 999 | core->name); |
| 896 | return -EINVAL; | 1000 | return -EINVAL; |
| 897 | } | 1001 | } |
| 1002 | /* define general-purpose callback pointer */ | ||
| 1003 | dev->dvb.frontend->callback = cx88_tuner_callback; | ||
| 898 | 1004 | ||
| 899 | /* Ensure all frontends negotiate bus access */ | 1005 | /* Ensure all frontends negotiate bus access */ |
| 900 | dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; | 1006 | dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; |
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index d7406a994f09..8e74d64fdcd2 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
| @@ -201,7 +201,23 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) | |||
| 201 | 201 | ||
| 202 | core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap); | 202 | core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap); |
| 203 | if (0 == core->i2c_rc) { | 203 | if (0 == core->i2c_rc) { |
| 204 | static u8 tuner_data[] = | ||
| 205 | { 0x0b, 0xdc, 0x86, 0x52 }; | ||
| 206 | static struct i2c_msg tuner_msg = | ||
| 207 | { .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 }; | ||
| 208 | |||
| 204 | dprintk(1, "i2c register ok\n"); | 209 | dprintk(1, "i2c register ok\n"); |
| 210 | switch( core->boardnr ) { | ||
| 211 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
| 212 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
| 213 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
| 214 | printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n", | ||
| 215 | core->name); | ||
| 216 | i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1); | ||
| 217 | break; | ||
| 218 | default: | ||
| 219 | break; | ||
| 220 | } | ||
| 205 | if (i2c_scan) | 221 | if (i2c_scan) |
| 206 | do_i2c_scan(core->name,&core->i2c_client); | 222 | do_i2c_scan(core->name,&core->i2c_client); |
| 207 | } else | 223 | } else |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 53526d997a4e..8683d104de72 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
| @@ -224,6 +224,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
| 224 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | 224 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: |
| 225 | case CX88_BOARD_HAUPPAUGE_HVR1100: | 225 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
| 226 | case CX88_BOARD_HAUPPAUGE_HVR3000: | 226 | case CX88_BOARD_HAUPPAUGE_HVR3000: |
| 227 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
| 228 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
| 227 | ir_codes = ir_codes_hauppauge_new; | 229 | ir_codes = ir_codes_hauppauge_new; |
| 228 | ir_type = IR_TYPE_RC5; | 230 | ir_type = IR_TYPE_RC5; |
| 229 | ir->sampling = 1; | 231 | ir->sampling = 1; |
| @@ -259,6 +261,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
| 259 | ir->polling = 1; /* ms */ | 261 | ir->polling = 1; /* ms */ |
| 260 | break; | 262 | break; |
| 261 | case CX88_BOARD_PROLINK_PV_8000GT: | 263 | case CX88_BOARD_PROLINK_PV_8000GT: |
| 264 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: | ||
| 262 | ir_codes = ir_codes_pixelview_new; | 265 | ir_codes = ir_codes_pixelview_new; |
| 263 | ir->gpio_addr = MO_GP1_IO; | 266 | ir->gpio_addr = MO_GP1_IO; |
| 264 | ir->mask_keycode = 0x3f; | 267 | ir->mask_keycode = 0x3f; |
| @@ -392,7 +395,7 @@ void cx88_ir_irq(struct cx88_core *core) | |||
| 392 | { | 395 | { |
| 393 | struct cx88_IR *ir = core->ir; | 396 | struct cx88_IR *ir = core->ir; |
| 394 | u32 samples, ircode; | 397 | u32 samples, ircode; |
| 395 | int i; | 398 | int i, start, range, toggle, dev, code; |
| 396 | 399 | ||
| 397 | if (NULL == ir) | 400 | if (NULL == ir) |
| 398 | return; | 401 | return; |
| @@ -461,6 +464,34 @@ void cx88_ir_irq(struct cx88_core *core) | |||
| 461 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | 464 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: |
| 462 | case CX88_BOARD_HAUPPAUGE_HVR1100: | 465 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
| 463 | case CX88_BOARD_HAUPPAUGE_HVR3000: | 466 | case CX88_BOARD_HAUPPAUGE_HVR3000: |
| 467 | case CX88_BOARD_HAUPPAUGE_HVR4000: | ||
| 468 | case CX88_BOARD_HAUPPAUGE_HVR4000LITE: | ||
| 469 | ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); | ||
| 470 | ir_dprintk("biphase decoded: %x\n", ircode); | ||
| 471 | /* | ||
| 472 | * RC5 has an extension bit which adds a new range | ||
| 473 | * of available codes, this is detected here. Also | ||
| 474 | * hauppauge remotes (black/silver) always use | ||
| 475 | * specific device ids. If we do not filter the | ||
| 476 | * device ids then messages destined for devices | ||
| 477 | * such as TVs (id=0) will get through to the | ||
| 478 | * device causing mis-fired events. | ||
| 479 | */ | ||
| 480 | /* split rc5 data block ... */ | ||
| 481 | start = (ircode & 0x2000) >> 13; | ||
| 482 | range = (ircode & 0x1000) >> 12; | ||
| 483 | toggle= (ircode & 0x0800) >> 11; | ||
| 484 | dev = (ircode & 0x07c0) >> 6; | ||
| 485 | code = (ircode & 0x003f) | ((range << 6) ^ 0x0040); | ||
| 486 | if( start != 1) | ||
| 487 | /* no key pressed */ | ||
| 488 | break; | ||
| 489 | if ( dev != 0x1e && dev != 0x1f ) | ||
| 490 | /* not a hauppauge remote */ | ||
| 491 | break; | ||
| 492 | ir_input_keydown(ir->input, &ir->ir, code, ircode); | ||
| 493 | ir->release = jiffies + msecs_to_jiffies(120); | ||
| 494 | break; | ||
| 464 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: | 495 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: |
| 465 | ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); | 496 | ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); |
| 466 | ir_dprintk("biphase decoded: %x\n", ircode); | 497 | ir_dprintk("biphase decoded: %x\n", ircode); |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index ef4d56ea0027..be45955dff68 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
| @@ -773,6 +773,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 773 | enum v4l2_buf_type type = 0; | 773 | enum v4l2_buf_type type = 0; |
| 774 | int radio = 0; | 774 | int radio = 0; |
| 775 | 775 | ||
| 776 | lock_kernel(); | ||
| 776 | list_for_each_entry(h, &cx8800_devlist, devlist) { | 777 | list_for_each_entry(h, &cx8800_devlist, devlist) { |
| 777 | if (h->video_dev->minor == minor) { | 778 | if (h->video_dev->minor == minor) { |
| 778 | dev = h; | 779 | dev = h; |
| @@ -788,8 +789,10 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 788 | dev = h; | 789 | dev = h; |
| 789 | } | 790 | } |
| 790 | } | 791 | } |
| 791 | if (NULL == dev) | 792 | if (NULL == dev) { |
| 793 | unlock_kernel(); | ||
| 792 | return -ENODEV; | 794 | return -ENODEV; |
| 795 | } | ||
| 793 | 796 | ||
| 794 | core = dev->core; | 797 | core = dev->core; |
| 795 | 798 | ||
| @@ -798,8 +801,10 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 798 | 801 | ||
| 799 | /* allocate + initialize per filehandle data */ | 802 | /* allocate + initialize per filehandle data */ |
| 800 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 803 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
| 801 | if (NULL == fh) | 804 | if (NULL == fh) { |
| 805 | unlock_kernel(); | ||
| 802 | return -ENOMEM; | 806 | return -ENOMEM; |
| 807 | } | ||
| 803 | file->private_data = fh; | 808 | file->private_data = fh; |
| 804 | fh->dev = dev; | 809 | fh->dev = dev; |
| 805 | fh->radio = radio; | 810 | fh->radio = radio; |
| @@ -832,6 +837,9 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 832 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); | 837 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); |
| 833 | cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); | 838 | cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); |
| 834 | } | 839 | } |
| 840 | unlock_kernel(); | ||
| 841 | |||
| 842 | atomic_inc(&core->users); | ||
| 835 | 843 | ||
| 836 | return 0; | 844 | return 0; |
| 837 | } | 845 | } |
| @@ -920,7 +928,8 @@ static int video_release(struct inode *inode, struct file *file) | |||
| 920 | file->private_data = NULL; | 928 | file->private_data = NULL; |
| 921 | kfree(fh); | 929 | kfree(fh); |
| 922 | 930 | ||
| 923 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 931 | if(atomic_dec_and_test(&dev->core->users)) |
| 932 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
| 924 | 933 | ||
| 925 | return 0; | 934 | return 0; |
| 926 | } | 935 | } |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 54fe65094711..dbf01b8b57a5 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
| @@ -221,6 +221,14 @@ extern struct sram_channel cx88_sram_channels[]; | |||
| 221 | #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 | 221 | #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 |
| 222 | #define CX88_BOARD_PROLINK_PV_8000GT 66 | 222 | #define CX88_BOARD_PROLINK_PV_8000GT 66 |
| 223 | #define CX88_BOARD_KWORLD_ATSC_120 67 | 223 | #define CX88_BOARD_KWORLD_ATSC_120 67 |
| 224 | #define CX88_BOARD_HAUPPAUGE_HVR4000 68 | ||
| 225 | #define CX88_BOARD_HAUPPAUGE_HVR4000LITE 69 | ||
| 226 | #define CX88_BOARD_TEVII_S460 70 | ||
| 227 | #define CX88_BOARD_OMICOM_SS4_PCI 71 | ||
| 228 | #define CX88_BOARD_TBS_8920 72 | ||
| 229 | #define CX88_BOARD_TEVII_S420 73 | ||
| 230 | #define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74 | ||
| 231 | #define CX88_BOARD_PROF_7300 75 | ||
| 224 | 232 | ||
| 225 | enum cx88_itype { | 233 | enum cx88_itype { |
| 226 | CX88_VMUX_COMPOSITE1 = 1, | 234 | CX88_VMUX_COMPOSITE1 = 1, |
| @@ -342,6 +350,7 @@ struct cx88_core { | |||
| 342 | struct mutex lock; | 350 | struct mutex lock; |
| 343 | /* various v4l controls */ | 351 | /* various v4l controls */ |
| 344 | u32 freq; | 352 | u32 freq; |
| 353 | atomic_t users; | ||
| 345 | 354 | ||
| 346 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ | 355 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ |
| 347 | struct cx8802_dev *dvbdev; | 356 | struct cx8802_dev *dvbdev; |
| @@ -601,7 +610,7 @@ extern void cx88_call_i2c_clients(struct cx88_core *core, | |||
| 601 | /* ----------------------------------------------------------- */ | 610 | /* ----------------------------------------------------------- */ |
| 602 | /* cx88-cards.c */ | 611 | /* cx88-cards.c */ |
| 603 | 612 | ||
| 604 | extern int cx88_tuner_callback(void *dev, int command, int arg); | 613 | extern int cx88_tuner_callback(void *dev, int component, int command, int arg); |
| 605 | extern int cx88_get_resources(const struct cx88_core *core, | 614 | extern int cx88_get_resources(const struct cx88_core *core, |
| 606 | struct pci_dev *pci); | 615 | struct pci_dev *pci); |
| 607 | extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); | 616 | extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); |
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index 79faedf58521..3aa538afcc0b 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c | |||
| @@ -866,7 +866,8 @@ static int __init dabusb_init (void) | |||
| 866 | 866 | ||
| 867 | dbg("dabusb_init: driver registered"); | 867 | dbg("dabusb_init: driver registered"); |
| 868 | 868 | ||
| 869 | info(DRIVER_VERSION ":" DRIVER_DESC); | 869 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
| 870 | DRIVER_DESC "\n"); | ||
| 870 | 871 | ||
| 871 | out: | 872 | out: |
| 872 | return retval; | 873 | return retval; |
diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c deleted file mode 100644 index 88d6df71d051..000000000000 --- a/drivers/media/video/dpc7146.c +++ /dev/null | |||
| @@ -1,408 +0,0 @@ | |||
| 1 | /* | ||
| 2 | dpc7146.c - v4l2 driver for the dpc7146 demonstration board | ||
| 3 | |||
| 4 | Copyright (C) 2000-2003 Michael Hunold <michael@mihu.de> | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #define DEBUG_VARIABLE debug | ||
| 22 | |||
| 23 | #include <media/saa7146_vv.h> | ||
| 24 | #include <linux/video_decoder.h> /* for saa7111a */ | ||
| 25 | |||
| 26 | #define I2C_SAA7111A 0x24 | ||
| 27 | |||
| 28 | /* All unused bytes are reserverd. */ | ||
| 29 | #define SAA711X_CHIP_VERSION 0x00 | ||
| 30 | #define SAA711X_ANALOG_INPUT_CONTROL_1 0x02 | ||
| 31 | #define SAA711X_ANALOG_INPUT_CONTROL_2 0x03 | ||
| 32 | #define SAA711X_ANALOG_INPUT_CONTROL_3 0x04 | ||
| 33 | #define SAA711X_ANALOG_INPUT_CONTROL_4 0x05 | ||
| 34 | #define SAA711X_HORIZONTAL_SYNC_START 0x06 | ||
| 35 | #define SAA711X_HORIZONTAL_SYNC_STOP 0x07 | ||
| 36 | #define SAA711X_SYNC_CONTROL 0x08 | ||
| 37 | #define SAA711X_LUMINANCE_CONTROL 0x09 | ||
| 38 | #define SAA711X_LUMINANCE_BRIGHTNESS 0x0A | ||
| 39 | #define SAA711X_LUMINANCE_CONTRAST 0x0B | ||
| 40 | #define SAA711X_CHROMA_SATURATION 0x0C | ||
| 41 | #define SAA711X_CHROMA_HUE_CONTROL 0x0D | ||
| 42 | #define SAA711X_CHROMA_CONTROL 0x0E | ||
| 43 | #define SAA711X_FORMAT_DELAY_CONTROL 0x10 | ||
| 44 | #define SAA711X_OUTPUT_CONTROL_1 0x11 | ||
| 45 | #define SAA711X_OUTPUT_CONTROL_2 0x12 | ||
| 46 | #define SAA711X_OUTPUT_CONTROL_3 0x13 | ||
| 47 | #define SAA711X_V_GATE_1_START 0x15 | ||
| 48 | #define SAA711X_V_GATE_1_STOP 0x16 | ||
| 49 | #define SAA711X_V_GATE_1_MSB 0x17 | ||
| 50 | #define SAA711X_TEXT_SLICER_STATUS 0x1A | ||
| 51 | #define SAA711X_DECODED_BYTES_OF_TS_1 0x1B | ||
| 52 | #define SAA711X_DECODED_BYTES_OF_TS_2 0x1C | ||
| 53 | #define SAA711X_STATUS_BYTE 0x1F | ||
| 54 | |||
| 55 | #define DPC_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) | ||
| 56 | |||
| 57 | static int debug; | ||
| 58 | module_param(debug, int, 0); | ||
| 59 | MODULE_PARM_DESC(debug, "debug verbosity"); | ||
| 60 | |||
| 61 | static int dpc_num; | ||
| 62 | |||
| 63 | #define DPC_INPUTS 2 | ||
| 64 | static struct v4l2_input dpc_inputs[DPC_INPUTS] = { | ||
| 65 | { 0, "Port A", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, | ||
| 66 | { 1, "Port B", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, | ||
| 67 | }; | ||
| 68 | |||
| 69 | #define DPC_AUDIOS 0 | ||
| 70 | |||
| 71 | static struct saa7146_extension_ioctls ioctls[] = { | ||
| 72 | { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, | ||
| 73 | { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, | ||
| 74 | { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, | ||
| 75 | { VIDIOC_S_STD, SAA7146_AFTER }, | ||
| 76 | { 0, 0 } | ||
| 77 | }; | ||
| 78 | |||
| 79 | struct dpc | ||
| 80 | { | ||
| 81 | struct video_device *video_dev; | ||
| 82 | struct video_device *vbi_dev; | ||
| 83 | |||
| 84 | struct i2c_adapter i2c_adapter; | ||
| 85 | struct i2c_client *saa7111a; | ||
| 86 | |||
| 87 | int cur_input; /* current input */ | ||
| 88 | }; | ||
| 89 | |||
| 90 | static int dpc_check_clients(struct device *dev, void *data) | ||
| 91 | { | ||
| 92 | struct dpc* dpc = data; | ||
| 93 | struct i2c_client *client = i2c_verify_client(dev); | ||
| 94 | |||
| 95 | if( !client ) | ||
| 96 | return 0; | ||
| 97 | |||
| 98 | if( I2C_SAA7111A == client->addr ) | ||
| 99 | dpc->saa7111a = client; | ||
| 100 | |||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | /* fixme: add vbi stuff here */ | ||
| 105 | static int dpc_probe(struct saa7146_dev* dev) | ||
| 106 | { | ||
| 107 | struct dpc* dpc = NULL; | ||
| 108 | |||
| 109 | dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL); | ||
| 110 | if( NULL == dpc ) { | ||
| 111 | printk("dpc_v4l2.o: dpc_probe: not enough kernel memory.\n"); | ||
| 112 | return -ENOMEM; | ||
| 113 | } | ||
| 114 | |||
| 115 | /* FIXME: enable i2c-port pins, video-port-pins | ||
| 116 | video port pins should be enabled here ?! */ | ||
| 117 | saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); | ||
| 118 | |||
| 119 | dpc->i2c_adapter = (struct i2c_adapter) { | ||
| 120 | .class = I2C_CLASS_TV_ANALOG, | ||
| 121 | .name = "dpc7146", | ||
| 122 | }; | ||
| 123 | saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); | ||
| 124 | if(i2c_add_adapter(&dpc->i2c_adapter) < 0) { | ||
| 125 | DEB_S(("cannot register i2c-device. skipping.\n")); | ||
| 126 | kfree(dpc); | ||
| 127 | return -EFAULT; | ||
| 128 | } | ||
| 129 | |||
| 130 | /* loop through all i2c-devices on the bus and look who is there */ | ||
| 131 | device_for_each_child(&dpc->i2c_adapter.dev, dpc, dpc_check_clients); | ||
| 132 | |||
| 133 | /* check if all devices are present */ | ||
| 134 | if (!dpc->saa7111a) { | ||
| 135 | DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n")); | ||
| 136 | i2c_del_adapter(&dpc->i2c_adapter); | ||
| 137 | kfree(dpc); | ||
| 138 | return -ENODEV; | ||
| 139 | } | ||
| 140 | |||
| 141 | /* all devices are present, probe was successful */ | ||
| 142 | DEB_D(("dpc_v4l2.o: dpc_probe succeeded for this device.\n")); | ||
| 143 | |||
| 144 | /* we store the pointer in our private data field */ | ||
| 145 | dev->ext_priv = dpc; | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | /* bring hardware to a sane state. this has to be done, just in case someone | ||
| 151 | wants to capture from this device before it has been properly initialized. | ||
| 152 | the capture engine would badly fail, because no valid signal arrives on the | ||
| 153 | saa7146, thus leading to timeouts and stuff. */ | ||
| 154 | static int dpc_init_done(struct saa7146_dev* dev) | ||
| 155 | { | ||
| 156 | struct dpc* dpc = (struct dpc*)dev->ext_priv; | ||
| 157 | |||
| 158 | DEB_D(("dpc_v4l2.o: dpc_init_done called.\n")); | ||
| 159 | |||
| 160 | /* initialize the helper ics to useful values */ | ||
| 161 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x00, 0x11); | ||
| 162 | |||
| 163 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x02, 0xc0); | ||
| 164 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x03, 0x30); | ||
| 165 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x04, 0x00); | ||
| 166 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x05, 0x00); | ||
| 167 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x06, 0xde); | ||
| 168 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x07, 0xad); | ||
| 169 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x08, 0xa8); | ||
| 170 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x09, 0x00); | ||
| 171 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x0a, 0x80); | ||
| 172 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x0b, 0x47); | ||
| 173 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x0c, 0x40); | ||
| 174 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x0d, 0x00); | ||
| 175 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x0e, 0x03); | ||
| 176 | |||
| 177 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x10, 0xd0); | ||
| 178 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x11, 0x1c); | ||
| 179 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x12, 0xc1); | ||
| 180 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x13, 0x30); | ||
| 181 | |||
| 182 | i2c_smbus_write_byte_data(dpc->saa7111a, 0x1f, 0x81); | ||
| 183 | |||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | static struct saa7146_ext_vv vv_data; | ||
| 188 | |||
| 189 | /* this function only gets called when the probing was successful */ | ||
| 190 | static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) | ||
| 191 | { | ||
| 192 | struct dpc* dpc = (struct dpc*)dev->ext_priv; | ||
| 193 | |||
| 194 | DEB_D(("dpc_v4l2.o: dpc_attach called.\n")); | ||
| 195 | |||
| 196 | /* checking for i2c-devices can be omitted here, because we | ||
| 197 | already did this in "dpc_vl42_probe" */ | ||
| 198 | |||
| 199 | saa7146_vv_init(dev,&vv_data); | ||
| 200 | if( 0 != saa7146_register_device(&dpc->video_dev, dev, "dpc", VFL_TYPE_GRABBER)) { | ||
| 201 | ERR(("cannot register capture v4l2 device. skipping.\n")); | ||
| 202 | return -1; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ | ||
| 206 | if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) { | ||
| 207 | if( 0 != saa7146_register_device(&dpc->vbi_dev, dev, "dpc", VFL_TYPE_VBI)) { | ||
| 208 | ERR(("cannot register vbi v4l2 device. skipping.\n")); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | i2c_use_client(dpc->saa7111a); | ||
| 213 | |||
| 214 | printk("dpc: found 'dpc7146 demonstration board'-%d.\n",dpc_num); | ||
| 215 | dpc_num++; | ||
| 216 | |||
| 217 | /* the rest */ | ||
| 218 | dpc->cur_input = 0; | ||
| 219 | dpc_init_done(dev); | ||
| 220 | |||
| 221 | return 0; | ||
| 222 | } | ||
| 223 | |||
| 224 | static int dpc_detach(struct saa7146_dev* dev) | ||
| 225 | { | ||
| 226 | struct dpc* dpc = (struct dpc*)dev->ext_priv; | ||
| 227 | |||
| 228 | DEB_EE(("dev:%p\n",dev)); | ||
| 229 | |||
| 230 | i2c_release_client(dpc->saa7111a); | ||
| 231 | |||
| 232 | saa7146_unregister_device(&dpc->video_dev,dev); | ||
| 233 | if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) { | ||
| 234 | saa7146_unregister_device(&dpc->vbi_dev,dev); | ||
| 235 | } | ||
| 236 | saa7146_vv_release(dev); | ||
| 237 | |||
| 238 | dpc_num--; | ||
| 239 | |||
| 240 | i2c_del_adapter(&dpc->i2c_adapter); | ||
| 241 | kfree(dpc); | ||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | #ifdef axa | ||
| 246 | int dpc_vbi_bypass(struct saa7146_dev* dev) | ||
| 247 | { | ||
| 248 | struct dpc* dpc = (struct dpc*)dev->ext_priv; | ||
| 249 | |||
| 250 | int i = 1; | ||
| 251 | |||
| 252 | /* switch bypass in saa7111a */ | ||
| 253 | if ( 0 != dpc->saa7111a->driver->command(dpc->saa7111a,SAA711X_VBI_BYPASS, &i)) { | ||
| 254 | printk("dpc_v4l2.o: VBI_BYPASS: could not address saa7111a.\n"); | ||
| 255 | return -1; | ||
| 256 | } | ||
| 257 | |||
| 258 | return 0; | ||
| 259 | } | ||
| 260 | #endif | ||
| 261 | |||
| 262 | static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | ||
| 263 | { | ||
| 264 | struct saa7146_dev *dev = fh->dev; | ||
| 265 | struct dpc* dpc = (struct dpc*)dev->ext_priv; | ||
| 266 | /* | ||
| 267 | struct saa7146_vv *vv = dev->vv_data; | ||
| 268 | */ | ||
| 269 | switch(cmd) | ||
| 270 | { | ||
| 271 | case VIDIOC_ENUMINPUT: | ||
| 272 | { | ||
| 273 | struct v4l2_input *i = arg; | ||
| 274 | DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); | ||
| 275 | |||
| 276 | if( i->index < 0 || i->index >= DPC_INPUTS) { | ||
| 277 | return -EINVAL; | ||
| 278 | } | ||
| 279 | |||
| 280 | memcpy(i, &dpc_inputs[i->index], sizeof(struct v4l2_input)); | ||
| 281 | |||
| 282 | DEB_D(("dpc_v4l2.o: v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n",i->index)); | ||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | case VIDIOC_G_INPUT: | ||
| 286 | { | ||
| 287 | int *input = (int *)arg; | ||
| 288 | *input = dpc->cur_input; | ||
| 289 | |||
| 290 | DEB_D(("dpc_v4l2.o: VIDIOC_G_INPUT: %d\n",*input)); | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | case VIDIOC_S_INPUT: | ||
| 294 | { | ||
| 295 | int input = *(int *)arg; | ||
| 296 | |||
| 297 | if (input < 0 || input >= DPC_INPUTS) { | ||
| 298 | return -EINVAL; | ||
| 299 | } | ||
| 300 | |||
| 301 | dpc->cur_input = input; | ||
| 302 | |||
| 303 | /* fixme: switch input here, switch audio, too! */ | ||
| 304 | // saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); | ||
| 305 | printk("dpc_v4l2.o: VIDIOC_S_INPUT: fixme switch input.\n"); | ||
| 306 | |||
| 307 | return 0; | ||
| 308 | } | ||
| 309 | default: | ||
| 310 | /* | ||
| 311 | DEB_D(("dpc_v4l2.o: v4l2_ioctl does not handle this ioctl.\n")); | ||
| 312 | */ | ||
| 313 | return -ENOIOCTLCMD; | ||
| 314 | } | ||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) | ||
| 319 | { | ||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | static struct saa7146_standard standard[] = { | ||
| 324 | { | ||
| 325 | .name = "PAL", .id = V4L2_STD_PAL, | ||
| 326 | .v_offset = 0x17, .v_field = 288, | ||
| 327 | .h_offset = 0x14, .h_pixels = 680, | ||
| 328 | .v_max_out = 576, .h_max_out = 768, | ||
| 329 | }, { | ||
| 330 | .name = "NTSC", .id = V4L2_STD_NTSC, | ||
| 331 | .v_offset = 0x16, .v_field = 240, | ||
| 332 | .h_offset = 0x06, .h_pixels = 708, | ||
| 333 | .v_max_out = 480, .h_max_out = 640, | ||
| 334 | }, { | ||
| 335 | .name = "SECAM", .id = V4L2_STD_SECAM, | ||
| 336 | .v_offset = 0x14, .v_field = 288, | ||
| 337 | .h_offset = 0x14, .h_pixels = 720, | ||
| 338 | .v_max_out = 576, .h_max_out = 768, | ||
| 339 | } | ||
| 340 | }; | ||
| 341 | |||
| 342 | static struct saa7146_extension extension; | ||
| 343 | |||
| 344 | static struct saa7146_pci_extension_data dpc = { | ||
| 345 | .ext_priv = "Multimedia eXtension Board", | ||
| 346 | .ext = &extension, | ||
| 347 | }; | ||
| 348 | |||
| 349 | static struct pci_device_id pci_tbl[] = { | ||
| 350 | { | ||
| 351 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
| 352 | .device = PCI_DEVICE_ID_PHILIPS_SAA7146, | ||
| 353 | .subvendor = 0x0000, | ||
| 354 | .subdevice = 0x0000, | ||
| 355 | .driver_data = (unsigned long)&dpc, | ||
| 356 | }, { | ||
| 357 | .vendor = 0, | ||
| 358 | } | ||
| 359 | }; | ||
| 360 | |||
| 361 | MODULE_DEVICE_TABLE(pci, pci_tbl); | ||
| 362 | |||
| 363 | static struct saa7146_ext_vv vv_data = { | ||
| 364 | .inputs = DPC_INPUTS, | ||
| 365 | .capabilities = V4L2_CAP_VBI_CAPTURE, | ||
| 366 | .stds = &standard[0], | ||
| 367 | .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), | ||
| 368 | .std_callback = &std_callback, | ||
| 369 | .ioctls = &ioctls[0], | ||
| 370 | .ioctl = dpc_ioctl, | ||
| 371 | }; | ||
| 372 | |||
| 373 | static struct saa7146_extension extension = { | ||
| 374 | .name = "dpc7146 demonstration board", | ||
| 375 | .flags = SAA7146_USE_I2C_IRQ, | ||
| 376 | |||
| 377 | .pci_tbl = &pci_tbl[0], | ||
| 378 | .module = THIS_MODULE, | ||
| 379 | |||
| 380 | .probe = dpc_probe, | ||
| 381 | .attach = dpc_attach, | ||
| 382 | .detach = dpc_detach, | ||
| 383 | |||
| 384 | .irq_mask = 0, | ||
| 385 | .irq_func = NULL, | ||
| 386 | }; | ||
| 387 | |||
| 388 | static int __init dpc_init_module(void) | ||
| 389 | { | ||
| 390 | if( 0 != saa7146_register_extension(&extension)) { | ||
| 391 | DEB_S(("failed to register extension.\n")); | ||
| 392 | return -ENODEV; | ||
| 393 | } | ||
| 394 | |||
| 395 | return 0; | ||
| 396 | } | ||
| 397 | |||
| 398 | static void __exit dpc_cleanup_module(void) | ||
| 399 | { | ||
| 400 | saa7146_unregister_extension(&extension); | ||
| 401 | } | ||
| 402 | |||
| 403 | module_init(dpc_init_module); | ||
| 404 | module_exit(dpc_cleanup_module); | ||
| 405 | |||
| 406 | MODULE_DESCRIPTION("video4linux-2 driver for the 'dpc7146 demonstration board'"); | ||
| 407 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); | ||
| 408 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index de943cf6c169..d65d0572403b 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
| @@ -1101,7 +1101,7 @@ struct usb_device_id em28xx_id_table [] = { | |||
| 1101 | { USB_DEVICE(0xeb1a, 0x2820), | 1101 | { USB_DEVICE(0xeb1a, 0x2820), |
| 1102 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1102 | .driver_info = EM2820_BOARD_UNKNOWN }, |
| 1103 | { USB_DEVICE(0xeb1a, 0x2821), | 1103 | { USB_DEVICE(0xeb1a, 0x2821), |
| 1104 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1104 | .driver_info = EM2820_BOARD_PROLINK_PLAYTV_USB2 }, |
| 1105 | { USB_DEVICE(0xeb1a, 0x2860), | 1105 | { USB_DEVICE(0xeb1a, 0x2860), |
| 1106 | .driver_info = EM2820_BOARD_UNKNOWN }, | 1106 | .driver_info = EM2820_BOARD_UNKNOWN }, |
| 1107 | { USB_DEVICE(0xeb1a, 0x2861), | 1107 | { USB_DEVICE(0xeb1a, 0x2861), |
| @@ -1271,7 +1271,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { | |||
| 1271 | {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT}, | 1271 | {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT}, |
| 1272 | }; | 1272 | }; |
| 1273 | 1273 | ||
| 1274 | int em28xx_tuner_callback(void *ptr, int command, int arg) | 1274 | int em28xx_tuner_callback(void *ptr, int component, int command, int arg) |
| 1275 | { | 1275 | { |
| 1276 | int rc = 0; | 1276 | int rc = 0; |
| 1277 | struct em28xx *dev = ptr; | 1277 | struct em28xx *dev = ptr; |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index d2b1a1a52689..c99e2383b7ec 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
| @@ -249,7 +249,6 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) | |||
| 249 | memset(&cfg, 0, sizeof(cfg)); | 249 | memset(&cfg, 0, sizeof(cfg)); |
| 250 | cfg.i2c_adap = &dev->i2c_adap; | 250 | cfg.i2c_adap = &dev->i2c_adap; |
| 251 | cfg.i2c_addr = addr; | 251 | cfg.i2c_addr = addr; |
| 252 | cfg.callback = em28xx_tuner_callback; | ||
| 253 | 252 | ||
| 254 | if (!dev->dvb->frontend) { | 253 | if (!dev->dvb->frontend) { |
| 255 | printk(KERN_ERR "%s/2: dvb frontend not attached. " | 254 | printk(KERN_ERR "%s/2: dvb frontend not attached. " |
| @@ -274,7 +273,7 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) | |||
| 274 | 273 | ||
| 275 | /* ------------------------------------------------------------------ */ | 274 | /* ------------------------------------------------------------------ */ |
| 276 | 275 | ||
| 277 | int register_dvb(struct em28xx_dvb *dvb, | 276 | static int register_dvb(struct em28xx_dvb *dvb, |
| 278 | struct module *module, | 277 | struct module *module, |
| 279 | struct em28xx *dev, | 278 | struct em28xx *dev, |
| 280 | struct device *device) | 279 | struct device *device) |
| @@ -422,6 +421,8 @@ static int dvb_init(struct em28xx *dev) | |||
| 422 | } | 421 | } |
| 423 | break; | 422 | break; |
| 424 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | 423 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
| 424 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | ||
| 425 | case EM2880_BOARD_KWORLD_DVB_310U: | ||
| 425 | dvb->frontend = dvb_attach(zl10353_attach, | 426 | dvb->frontend = dvb_attach(zl10353_attach, |
| 426 | &em28xx_zl10353_with_xc3028, | 427 | &em28xx_zl10353_with_xc3028, |
| 427 | &dev->i2c_adap); | 428 | &dev->i2c_adap); |
| @@ -443,24 +444,6 @@ static int dvb_init(struct em28xx *dev) | |||
| 443 | } | 444 | } |
| 444 | break; | 445 | break; |
| 445 | #endif | 446 | #endif |
| 446 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | ||
| 447 | dvb->frontend = dvb_attach(zl10353_attach, | ||
| 448 | &em28xx_zl10353_with_xc3028, | ||
| 449 | &dev->i2c_adap); | ||
| 450 | if (attach_xc3028(0x61, dev) < 0) { | ||
| 451 | result = -EINVAL; | ||
| 452 | goto out_free; | ||
| 453 | } | ||
| 454 | break; | ||
| 455 | case EM2880_BOARD_KWORLD_DVB_310U: | ||
| 456 | dvb->frontend = dvb_attach(zl10353_attach, | ||
| 457 | &em28xx_zl10353_with_xc3028, | ||
| 458 | &dev->i2c_adap); | ||
| 459 | if (attach_xc3028(0x61, dev) < 0) { | ||
| 460 | result = -EINVAL; | ||
| 461 | goto out_free; | ||
| 462 | } | ||
| 463 | break; | ||
| 464 | default: | 447 | default: |
| 465 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" | 448 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" |
| 466 | " isn't supported yet\n", | 449 | " isn't supported yet\n", |
| @@ -474,6 +457,8 @@ static int dvb_init(struct em28xx *dev) | |||
| 474 | result = -EINVAL; | 457 | result = -EINVAL; |
| 475 | goto out_free; | 458 | goto out_free; |
| 476 | } | 459 | } |
| 460 | /* define general-purpose callback pointer */ | ||
| 461 | dvb->frontend->callback = em28xx_tuner_callback; | ||
| 477 | 462 | ||
| 478 | /* register everything */ | 463 | /* register everything */ |
| 479 | result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); | 464 | result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); |
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 97853384c943..3bab56b997fc 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c | |||
| @@ -143,10 +143,11 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) | |||
| 143 | } | 143 | } |
| 144 | for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; | 144 | for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; |
| 145 | write_timeout -= 5) { | 145 | write_timeout -= 5) { |
| 146 | unsigned msg = dev->em28xx_read_reg(dev, 0x5); | 146 | unsigned reg = dev->em28xx_read_reg(dev, 0x5); |
| 147 | if (msg == 0x94) | 147 | |
| 148 | if (reg == 0x94) | ||
| 148 | return -ENODEV; | 149 | return -ENODEV; |
| 149 | else if (msg == 0x84) | 150 | else if (reg == 0x84) |
| 150 | return 0; | 151 | return 0; |
| 151 | msleep(5); | 152 | msleep(5); |
| 152 | } | 153 | } |
| @@ -335,8 +336,11 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) | |||
| 335 | 336 | ||
| 336 | /* Check if board has eeprom */ | 337 | /* Check if board has eeprom */ |
| 337 | err = i2c_master_recv(&dev->i2c_client, &buf, 0); | 338 | err = i2c_master_recv(&dev->i2c_client, &buf, 0); |
| 338 | if (err < 0) | 339 | if (err < 0) { |
| 339 | return -1; | 340 | em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n", |
| 341 | __func__, err); | ||
| 342 | return err; | ||
| 343 | } | ||
| 340 | 344 | ||
| 341 | buf = 0; | 345 | buf = 0; |
| 342 | 346 | ||
| @@ -344,7 +348,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) | |||
| 344 | if (err != 1) { | 348 | if (err != 1) { |
| 345 | printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", | 349 | printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", |
| 346 | dev->name, err); | 350 | dev->name, err); |
| 347 | return -1; | 351 | return err; |
| 348 | } | 352 | } |
| 349 | while (size > 0) { | 353 | while (size > 0) { |
| 350 | if (size > 16) | 354 | if (size > 16) |
| @@ -357,7 +361,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) | |||
| 357 | printk(KERN_WARNING | 361 | printk(KERN_WARNING |
| 358 | "%s: i2c eeprom read error (err=%d)\n", | 362 | "%s: i2c eeprom read error (err=%d)\n", |
| 359 | dev->name, err); | 363 | dev->name, err); |
| 360 | return -1; | 364 | return err; |
| 361 | } | 365 | } |
| 362 | size -= block; | 366 | size -= block; |
| 363 | p += block; | 367 | p += block; |
| @@ -585,18 +589,31 @@ void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg) | |||
| 585 | */ | 589 | */ |
| 586 | int em28xx_i2c_register(struct em28xx *dev) | 590 | int em28xx_i2c_register(struct em28xx *dev) |
| 587 | { | 591 | { |
| 592 | int retval; | ||
| 593 | |||
| 588 | BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); | 594 | BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); |
| 589 | BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); | 595 | BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); |
| 590 | dev->i2c_adap = em28xx_adap_template; | 596 | dev->i2c_adap = em28xx_adap_template; |
| 591 | dev->i2c_adap.dev.parent = &dev->udev->dev; | 597 | dev->i2c_adap.dev.parent = &dev->udev->dev; |
| 592 | strcpy(dev->i2c_adap.name, dev->name); | 598 | strcpy(dev->i2c_adap.name, dev->name); |
| 593 | dev->i2c_adap.algo_data = dev; | 599 | dev->i2c_adap.algo_data = dev; |
| 594 | i2c_add_adapter(&dev->i2c_adap); | 600 | |
| 601 | retval = i2c_add_adapter(&dev->i2c_adap); | ||
| 602 | if (retval < 0) { | ||
| 603 | em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", | ||
| 604 | __func__, retval); | ||
| 605 | return retval; | ||
| 606 | } | ||
| 595 | 607 | ||
| 596 | dev->i2c_client = em28xx_client_template; | 608 | dev->i2c_client = em28xx_client_template; |
| 597 | dev->i2c_client.adapter = &dev->i2c_adap; | 609 | dev->i2c_client.adapter = &dev->i2c_adap; |
| 598 | 610 | ||
| 599 | em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); | 611 | retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); |
| 612 | if (retval < 0) { | ||
| 613 | em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", | ||
| 614 | __func__, retval); | ||
| 615 | return retval; | ||
| 616 | } | ||
| 600 | 617 | ||
| 601 | if (i2c_scan) | 618 | if (i2c_scan) |
| 602 | em28xx_do_i2c_scan(dev); | 619 | em28xx_do_i2c_scan(dev); |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 49ab0629702e..c53649e5315b 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
| @@ -513,10 +513,17 @@ static struct videobuf_queue_ops em28xx_video_qops = { | |||
| 513 | */ | 513 | */ |
| 514 | static int em28xx_config(struct em28xx *dev) | 514 | static int em28xx_config(struct em28xx *dev) |
| 515 | { | 515 | { |
| 516 | int retval; | ||
| 516 | 517 | ||
| 517 | /* Sets I2C speed to 100 KHz */ | 518 | /* Sets I2C speed to 100 KHz */ |
| 518 | if (!dev->is_em2800) | 519 | if (!dev->is_em2800) { |
| 519 | em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); | 520 | retval = em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1); |
| 521 | if (retval < 0) { | ||
| 522 | em28xx_errdev("%s: em28xx_write_regs_req failed! retval [%d]\n", | ||
| 523 | __func__, retval); | ||
| 524 | return retval; | ||
| 525 | } | ||
| 526 | } | ||
| 520 | 527 | ||
| 521 | /* enable vbi capturing */ | 528 | /* enable vbi capturing */ |
| 522 | 529 | ||
| @@ -1512,6 +1519,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
| 1512 | struct em28xx_fh *fh; | 1519 | struct em28xx_fh *fh; |
| 1513 | enum v4l2_buf_type fh_type = 0; | 1520 | enum v4l2_buf_type fh_type = 0; |
| 1514 | 1521 | ||
| 1522 | lock_kernel(); | ||
| 1515 | list_for_each_entry(h, &em28xx_devlist, devlist) { | 1523 | list_for_each_entry(h, &em28xx_devlist, devlist) { |
| 1516 | if (h->vdev->minor == minor) { | 1524 | if (h->vdev->minor == minor) { |
| 1517 | dev = h; | 1525 | dev = h; |
| @@ -1527,8 +1535,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
| 1527 | dev = h; | 1535 | dev = h; |
| 1528 | } | 1536 | } |
| 1529 | } | 1537 | } |
| 1530 | if (NULL == dev) | 1538 | if (NULL == dev) { |
| 1539 | unlock_kernel(); | ||
| 1531 | return -ENODEV; | 1540 | return -ENODEV; |
| 1541 | } | ||
| 1532 | 1542 | ||
| 1533 | em28xx_videodbg("open minor=%d type=%s users=%d\n", | 1543 | em28xx_videodbg("open minor=%d type=%s users=%d\n", |
| 1534 | minor, v4l2_type_names[fh_type], dev->users); | 1544 | minor, v4l2_type_names[fh_type], dev->users); |
| @@ -1537,6 +1547,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
| 1537 | fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); | 1547 | fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); |
| 1538 | if (!fh) { | 1548 | if (!fh) { |
| 1539 | em28xx_errdev("em28xx-video.c: Out of memory?!\n"); | 1549 | em28xx_errdev("em28xx-video.c: Out of memory?!\n"); |
| 1550 | unlock_kernel(); | ||
| 1540 | return -ENOMEM; | 1551 | return -ENOMEM; |
| 1541 | } | 1552 | } |
| 1542 | mutex_lock(&dev->lock); | 1553 | mutex_lock(&dev->lock); |
| @@ -1573,6 +1584,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
| 1573 | sizeof(struct em28xx_buffer), fh); | 1584 | sizeof(struct em28xx_buffer), fh); |
| 1574 | 1585 | ||
| 1575 | mutex_unlock(&dev->lock); | 1586 | mutex_unlock(&dev->lock); |
| 1587 | unlock_kernel(); | ||
| 1576 | 1588 | ||
| 1577 | return errCode; | 1589 | return errCode; |
| 1578 | } | 1590 | } |
| @@ -1588,8 +1600,7 @@ static void em28xx_release_resources(struct em28xx *dev) | |||
| 1588 | /*FIXME: I2C IR should be disconnected */ | 1600 | /*FIXME: I2C IR should be disconnected */ |
| 1589 | 1601 | ||
| 1590 | em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n", | 1602 | em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n", |
| 1591 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, | 1603 | dev->vdev->num, dev->vbi_dev->num); |
| 1592 | dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); | ||
| 1593 | list_del(&dev->devlist); | 1604 | list_del(&dev->devlist); |
| 1594 | if (dev->sbutton_input_dev) | 1605 | if (dev->sbutton_input_dev) |
| 1595 | em28xx_deregister_snapshot_button(dev); | 1606 | em28xx_deregister_snapshot_button(dev); |
| @@ -1948,13 +1959,23 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
| 1948 | } | 1959 | } |
| 1949 | 1960 | ||
| 1950 | /* register i2c bus */ | 1961 | /* register i2c bus */ |
| 1951 | em28xx_i2c_register(dev); | 1962 | errCode = em28xx_i2c_register(dev); |
| 1963 | if (errCode < 0) { | ||
| 1964 | em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n", | ||
| 1965 | __func__, errCode); | ||
| 1966 | return errCode; | ||
| 1967 | } | ||
| 1952 | 1968 | ||
| 1953 | /* Do board specific init and eeprom reading */ | 1969 | /* Do board specific init and eeprom reading */ |
| 1954 | em28xx_card_setup(dev); | 1970 | em28xx_card_setup(dev); |
| 1955 | 1971 | ||
| 1956 | /* Configure audio */ | 1972 | /* Configure audio */ |
| 1957 | em28xx_audio_analog_set(dev); | 1973 | errCode = em28xx_audio_analog_set(dev); |
| 1974 | if (errCode < 0) { | ||
| 1975 | em28xx_errdev("%s: em28xx_audio_analog_set - errCode [%d]!\n", | ||
| 1976 | __func__, errCode); | ||
| 1977 | return errCode; | ||
| 1978 | } | ||
| 1958 | 1979 | ||
| 1959 | /* configure the device */ | 1980 | /* configure the device */ |
| 1960 | em28xx_config_i2c(dev); | 1981 | em28xx_config_i2c(dev); |
| @@ -1974,6 +1995,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
| 1974 | dev->ctl_input = 2; | 1995 | dev->ctl_input = 2; |
| 1975 | 1996 | ||
| 1976 | errCode = em28xx_config(dev); | 1997 | errCode = em28xx_config(dev); |
| 1998 | if (errCode < 0) { | ||
| 1999 | em28xx_errdev("%s: em28xx_config - errCode [%d]!\n", | ||
| 2000 | __func__, errCode); | ||
| 2001 | return errCode; | ||
| 2002 | } | ||
| 1977 | 2003 | ||
| 1978 | list_add_tail(&dev->devlist, &em28xx_devlist); | 2004 | list_add_tail(&dev->devlist, &em28xx_devlist); |
| 1979 | 2005 | ||
| @@ -2026,17 +2052,27 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
| 2026 | 2052 | ||
| 2027 | if (dev->has_msp34xx) { | 2053 | if (dev->has_msp34xx) { |
| 2028 | /* Send a reset to other chips via gpio */ | 2054 | /* Send a reset to other chips via gpio */ |
| 2029 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); | 2055 | errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); |
| 2056 | if (errCode < 0) { | ||
| 2057 | em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(1) failed! errCode [%d]\n", | ||
| 2058 | __func__, errCode); | ||
| 2059 | return errCode; | ||
| 2060 | } | ||
| 2030 | msleep(3); | 2061 | msleep(3); |
| 2031 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1); | 2062 | |
| 2063 | errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1); | ||
| 2064 | if (errCode < 0) { | ||
| 2065 | em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(2) failed! errCode [%d]\n", | ||
| 2066 | __func__, errCode); | ||
| 2067 | return errCode; | ||
| 2068 | } | ||
| 2032 | msleep(3); | 2069 | msleep(3); |
| 2033 | } | 2070 | } |
| 2034 | 2071 | ||
| 2035 | video_mux(dev, 0); | 2072 | video_mux(dev, 0); |
| 2036 | 2073 | ||
| 2037 | em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", | 2074 | em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", |
| 2038 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, | 2075 | dev->vdev->num, dev->vbi_dev->num); |
| 2039 | dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); | ||
| 2040 | 2076 | ||
| 2041 | mutex_lock(&em28xx_extension_devlist_lock); | 2077 | mutex_lock(&em28xx_extension_devlist_lock); |
| 2042 | if (!list_empty(&em28xx_extension_devlist)) { | 2078 | if (!list_empty(&em28xx_extension_devlist)) { |
| @@ -2236,7 +2272,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) | |||
| 2236 | em28xx_warn | 2272 | em28xx_warn |
| 2237 | ("device /dev/video%d is open! Deregistration and memory " | 2273 | ("device /dev/video%d is open! Deregistration and memory " |
| 2238 | "deallocation are deferred on close.\n", | 2274 | "deallocation are deferred on close.\n", |
| 2239 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN); | 2275 | dev->vdev->num); |
| 2240 | 2276 | ||
| 2241 | dev->state |= DEV_MISCONFIGURED; | 2277 | dev->state |= DEV_MISCONFIGURED; |
| 2242 | em28xx_uninit_isoc(dev); | 2278 | em28xx_uninit_isoc(dev); |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 9a3310748685..82781178e0a3 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
| @@ -411,8 +411,8 @@ struct em28xx { | |||
| 411 | /* frame properties */ | 411 | /* frame properties */ |
| 412 | int width; /* current frame width */ | 412 | int width; /* current frame width */ |
| 413 | int height; /* current frame height */ | 413 | int height; /* current frame height */ |
| 414 | int hscale; /* horizontal scale factor (see datasheet) */ | 414 | unsigned hscale; /* horizontal scale factor (see datasheet) */ |
| 415 | int vscale; /* vertical scale factor (see datasheet) */ | 415 | unsigned vscale; /* vertical scale factor (see datasheet) */ |
| 416 | int interlaced; /* 1=interlace fileds, 0=just top fileds */ | 416 | int interlaced; /* 1=interlace fileds, 0=just top fileds */ |
| 417 | unsigned int video_bytesread; /* Number of bytes read */ | 417 | unsigned int video_bytesread; /* Number of bytes read */ |
| 418 | 418 | ||
| @@ -528,7 +528,7 @@ extern struct em28xx_board em28xx_boards[]; | |||
| 528 | extern struct usb_device_id em28xx_id_table[]; | 528 | extern struct usb_device_id em28xx_id_table[]; |
| 529 | extern const unsigned int em28xx_bcount; | 529 | extern const unsigned int em28xx_bcount; |
| 530 | void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); | 530 | void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); |
| 531 | int em28xx_tuner_callback(void *ptr, int command, int arg); | 531 | int em28xx_tuner_callback(void *ptr, int component, int command, int arg); |
| 532 | 532 | ||
| 533 | /* Provided by em28xx-input.c */ | 533 | /* Provided by em28xx-input.c */ |
| 534 | /* TODO: Check if the standard get_key handlers on ir-common can be used */ | 534 | /* TODO: Check if the standard get_key handlers on ir-common can be used */ |
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 8db2a05bf9c5..7a85c41b0eea 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c | |||
| @@ -1214,7 +1214,7 @@ static int et61x251_open(struct inode* inode, struct file* filp) | |||
| 1214 | if (!down_read_trylock(&et61x251_dev_lock)) | 1214 | if (!down_read_trylock(&et61x251_dev_lock)) |
| 1215 | return -ERESTARTSYS; | 1215 | return -ERESTARTSYS; |
| 1216 | 1216 | ||
| 1217 | cam = video_get_drvdata(video_devdata(filp)); | 1217 | cam = video_drvdata(filp); |
| 1218 | 1218 | ||
| 1219 | if (wait_for_completion_interruptible(&cam->probe)) { | 1219 | if (wait_for_completion_interruptible(&cam->probe)) { |
| 1220 | up_read(&et61x251_dev_lock); | 1220 | up_read(&et61x251_dev_lock); |
| @@ -1297,7 +1297,7 @@ static int et61x251_release(struct inode* inode, struct file* filp) | |||
| 1297 | 1297 | ||
| 1298 | down_write(&et61x251_dev_lock); | 1298 | down_write(&et61x251_dev_lock); |
| 1299 | 1299 | ||
| 1300 | cam = video_get_drvdata(video_devdata(filp)); | 1300 | cam = video_drvdata(filp); |
| 1301 | 1301 | ||
| 1302 | et61x251_stop_transfer(cam); | 1302 | et61x251_stop_transfer(cam); |
| 1303 | et61x251_release_buffers(cam); | 1303 | et61x251_release_buffers(cam); |
| @@ -1318,7 +1318,7 @@ static ssize_t | |||
| 1318 | et61x251_read(struct file* filp, char __user * buf, | 1318 | et61x251_read(struct file* filp, char __user * buf, |
| 1319 | size_t count, loff_t* f_pos) | 1319 | size_t count, loff_t* f_pos) |
| 1320 | { | 1320 | { |
| 1321 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 1321 | struct et61x251_device *cam = video_drvdata(filp); |
| 1322 | struct et61x251_frame_t* f, * i; | 1322 | struct et61x251_frame_t* f, * i; |
| 1323 | unsigned long lock_flags; | 1323 | unsigned long lock_flags; |
| 1324 | long timeout; | 1324 | long timeout; |
| @@ -1426,7 +1426,7 @@ exit: | |||
| 1426 | 1426 | ||
| 1427 | static unsigned int et61x251_poll(struct file *filp, poll_table *wait) | 1427 | static unsigned int et61x251_poll(struct file *filp, poll_table *wait) |
| 1428 | { | 1428 | { |
| 1429 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 1429 | struct et61x251_device *cam = video_drvdata(filp); |
| 1430 | struct et61x251_frame_t* f; | 1430 | struct et61x251_frame_t* f; |
| 1431 | unsigned long lock_flags; | 1431 | unsigned long lock_flags; |
| 1432 | unsigned int mask = 0; | 1432 | unsigned int mask = 0; |
| @@ -1502,7 +1502,7 @@ static struct vm_operations_struct et61x251_vm_ops = { | |||
| 1502 | 1502 | ||
| 1503 | static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) | 1503 | static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma) |
| 1504 | { | 1504 | { |
| 1505 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 1505 | struct et61x251_device *cam = video_drvdata(filp); |
| 1506 | unsigned long size = vma->vm_end - vma->vm_start, | 1506 | unsigned long size = vma->vm_end - vma->vm_start, |
| 1507 | start = vma->vm_start; | 1507 | start = vma->vm_start; |
| 1508 | void *pos; | 1508 | void *pos; |
| @@ -2395,7 +2395,7 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg) | |||
| 2395 | static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, | 2395 | static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, |
| 2396 | unsigned int cmd, void __user * arg) | 2396 | unsigned int cmd, void __user * arg) |
| 2397 | { | 2397 | { |
| 2398 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 2398 | struct et61x251_device *cam = video_drvdata(filp); |
| 2399 | 2399 | ||
| 2400 | switch (cmd) { | 2400 | switch (cmd) { |
| 2401 | 2401 | ||
| @@ -2490,7 +2490,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
| 2490 | static int et61x251_ioctl(struct inode* inode, struct file* filp, | 2490 | static int et61x251_ioctl(struct inode* inode, struct file* filp, |
| 2491 | unsigned int cmd, unsigned long arg) | 2491 | unsigned int cmd, unsigned long arg) |
| 2492 | { | 2492 | { |
| 2493 | struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); | 2493 | struct et61x251_device *cam = video_drvdata(filp); |
| 2494 | int err = 0; | 2494 | int err = 0; |
| 2495 | 2495 | ||
| 2496 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | 2496 | if (mutex_lock_interruptible(&cam->fileop_mutex)) |
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 42b90742b40b..4d0817471c9f 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
| @@ -1,13 +1,212 @@ | |||
| 1 | config USB_GSPCA | 1 | menuconfig USB_GSPCA |
| 2 | tristate "USB GSPCA driver" | 2 | tristate "GSPCA based webcams" |
| 3 | depends on VIDEO_V4L2 | 3 | depends on VIDEO_V4L2 |
| 4 | default m | ||
| 4 | ---help--- | 5 | ---help--- |
| 5 | Say Y here if you want support for various USB webcams. | 6 | Say Y here if you want to enable selecting webcams based |
| 7 | on the GSPCA framework. | ||
| 6 | 8 | ||
| 7 | See <file:Documentation/video4linux/gspca.txt> for more info. | 9 | See <file:Documentation/video4linux/gspca.txt> for more info. |
| 8 | 10 | ||
| 9 | This driver uses the Video For Linux API. You must say Y or M to | 11 | This driver uses the Video For Linux API. You must say Y or M to |
| 10 | "Video For Linux" to use this driver. | 12 | "Video For Linux" to use this driver. |
| 11 | 13 | ||
| 12 | To compile this driver as modules, choose M here: the | 14 | To compile this driver as modules, choose M here: the |
| 13 | modules will be called gspca_xxxx. | 15 | modules will be called gspca_main. |
| 16 | |||
| 17 | |||
| 18 | if USB_GSPCA && VIDEO_V4L2 | ||
| 19 | |||
| 20 | source "drivers/media/video/gspca/m5602/Kconfig" | ||
| 21 | |||
| 22 | config USB_GSPCA_CONEX | ||
| 23 | tristate "Conexant Camera Driver" | ||
| 24 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 25 | help | ||
| 26 | Say Y here if you want support for cameras based on the Conexant chip. | ||
| 27 | |||
| 28 | To compile this driver as a module, choose M here: the | ||
| 29 | module will be called gspca_conex. | ||
| 30 | |||
| 31 | config USB_GSPCA_ETOMS | ||
| 32 | tristate "Etoms USB Camera Driver" | ||
| 33 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 34 | help | ||
| 35 | Say Y here if you want support for cameras based on the Etoms chip. | ||
| 36 | |||
| 37 | To compile this driver as a module, choose M here: the | ||
| 38 | module will be called gspca_etoms. | ||
| 39 | |||
| 40 | config USB_GSPCA_FINEPIX | ||
| 41 | tristate "Fujifilm FinePix USB V4L2 driver" | ||
| 42 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 43 | help | ||
| 44 | Say Y here if you want support for cameras based on the FinePix chip. | ||
| 45 | |||
| 46 | To compile this driver as a module, choose M here: the | ||
| 47 | module will be called gspca_finepix. | ||
| 48 | |||
| 49 | config USB_GSPCA_MARS | ||
| 50 | tristate "Mars USB Camera Driver" | ||
| 51 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 52 | help | ||
| 53 | Say Y here if you want support for cameras based on the Mars chip. | ||
| 54 | |||
| 55 | To compile this driver as a module, choose M here: the | ||
| 56 | module will be called gspca_mars. | ||
| 57 | |||
| 58 | config USB_GSPCA_OV519 | ||
| 59 | tristate "OV519 USB Camera Driver" | ||
| 60 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 61 | help | ||
| 62 | Say Y here if you want support for cameras based on the OV519 chip. | ||
| 63 | |||
| 64 | To compile this driver as a module, choose M here: the | ||
| 65 | module will be called gspca_ov519. | ||
| 66 | |||
| 67 | config USB_GSPCA_PAC207 | ||
| 68 | tristate "Pixart PAC207 USB Camera Driver" | ||
| 69 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 70 | help | ||
| 71 | Say Y here if you want support for cameras based on the PAC207 chip. | ||
| 72 | |||
| 73 | To compile this driver as a module, choose M here: the | ||
| 74 | module will be called gspca_pac207. | ||
| 75 | |||
| 76 | config USB_GSPCA_PAC7311 | ||
| 77 | tristate "Pixart PAC7311 USB Camera Driver" | ||
| 78 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 79 | help | ||
| 80 | Say Y here if you want support for cameras based on the PAC7311 chip. | ||
| 81 | |||
| 82 | To compile this driver as a module, choose M here: the | ||
| 83 | module will be called gspca_pac7311. | ||
| 84 | |||
| 85 | config USB_GSPCA_SONIXB | ||
| 86 | tristate "SN9C102 USB Camera Driver" | ||
| 87 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 88 | help | ||
| 89 | Say Y here if you want support for cameras based on the SONIXB chip. | ||
| 90 | |||
| 91 | To compile this driver as a module, choose M here: the | ||
| 92 | module will be called gspca_sonixb. | ||
| 93 | |||
| 94 | config USB_GSPCA_SONIXJ | ||
| 95 | tristate "SONIX JPEG USB Camera Driver" | ||
| 96 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 97 | help | ||
| 98 | Say Y here if you want support for cameras based on the SONIXJ chip. | ||
| 99 | |||
| 100 | To compile this driver as a module, choose M here: the | ||
| 101 | module will be called gspca_sonixj | ||
| 102 | |||
| 103 | config USB_GSPCA_SPCA500 | ||
| 104 | tristate "SPCA500 USB Camera Driver" | ||
| 105 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 106 | help | ||
| 107 | Say Y here if you want support for cameras based on the SPCA500 chip. | ||
| 108 | |||
| 109 | To compile this driver as a module, choose M here: the | ||
| 110 | module will be called gspca_spca500. | ||
| 111 | |||
| 112 | config USB_GSPCA_SPCA501 | ||
| 113 | tristate "SPCA501 USB Camera Driver" | ||
| 114 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 115 | help | ||
| 116 | Say Y here if you want support for cameras based on the SPCA501 chip. | ||
| 117 | |||
| 118 | To compile this driver as a module, choose M here: the | ||
| 119 | module will be called gspca_spca501. | ||
| 120 | |||
| 121 | config USB_GSPCA_SPCA505 | ||
| 122 | tristate "SPCA505 USB Camera Driver" | ||
| 123 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 124 | help | ||
| 125 | Say Y here if you want support for cameras based on the SPCA505 chip. | ||
| 126 | |||
| 127 | To compile this driver as a module, choose M here: the | ||
| 128 | module will be called gspca_spca505. | ||
| 129 | |||
| 130 | config USB_GSPCA_SPCA506 | ||
| 131 | tristate "SPCA506 USB Camera Driver" | ||
| 132 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 133 | help | ||
| 134 | Say Y here if you want support for cameras based on the SPCA506 chip. | ||
| 135 | |||
| 136 | To compile this driver as a module, choose M here: the | ||
| 137 | module will be called gspca_spca506. | ||
| 138 | |||
| 139 | config USB_GSPCA_SPCA508 | ||
| 140 | tristate "SPCA508 USB Camera Driver" | ||
| 141 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 142 | help | ||
| 143 | Say Y here if you want support for cameras based on the SPCA508 chip. | ||
| 144 | |||
| 145 | To compile this driver as a module, choose M here: the | ||
| 146 | module will be called gspca_spca508. | ||
| 147 | |||
| 148 | config USB_GSPCA_SPCA561 | ||
| 149 | tristate "SPCA561 USB Camera Driver" | ||
| 150 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 151 | help | ||
| 152 | Say Y here if you want support for cameras based on the SPCA561 chip. | ||
| 153 | |||
| 154 | To compile this driver as a module, choose M here: the | ||
| 155 | module will be called gspca_spca561. | ||
| 156 | |||
| 157 | config USB_GSPCA_STK014 | ||
| 158 | tristate "Syntek DV4000 (STK014) USB Camera Driver" | ||
| 159 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 160 | help | ||
| 161 | Say Y here if you want support for cameras based on the STK014 chip. | ||
| 162 | |||
| 163 | To compile this driver as a module, choose M here: the | ||
| 164 | module will be called gspca_stk014. | ||
| 165 | |||
| 166 | config USB_GSPCA_SUNPLUS | ||
| 167 | tristate "SUNPLUS USB Camera Driver" | ||
| 168 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 169 | help | ||
| 170 | Say Y here if you want support for cameras based on the Sunplus | ||
| 171 | SPCA504(abc) SPCA533 SPCA536 chips. | ||
| 172 | |||
| 173 | To compile this driver as a module, choose M here: the | ||
| 174 | module will be called gspca_spca5xx. | ||
| 175 | |||
| 176 | config USB_GSPCA_T613 | ||
| 177 | tristate "T613 (JPEG Compliance) USB Camera Driver" | ||
| 178 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 179 | help | ||
| 180 | Say Y here if you want support for cameras based on the T613 chip. | ||
| 181 | |||
| 182 | To compile this driver as a module, choose M here: the | ||
| 183 | module will be called gspca_t613. | ||
| 184 | |||
| 185 | config USB_GSPCA_TV8532 | ||
| 186 | tristate "TV8532 USB Camera Driver" | ||
| 187 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 188 | help | ||
| 189 | Say Y here if you want support for cameras based on the TV8531 chip. | ||
| 190 | |||
| 191 | To compile this driver as a module, choose M here: the | ||
| 192 | module will be called gspca_tv8532. | ||
| 193 | |||
| 194 | config USB_GSPCA_VC032X | ||
| 195 | tristate "VC032X USB Camera Driver" | ||
| 196 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 197 | help | ||
| 198 | Say Y here if you want support for cameras based on the VC032X chip. | ||
| 199 | |||
| 200 | To compile this driver as a module, choose M here: the | ||
| 201 | module will be called gspca_vc032x. | ||
| 202 | |||
| 203 | config USB_GSPCA_ZC3XX | ||
| 204 | tristate "VC3xx USB Camera Driver" | ||
| 205 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 206 | help | ||
| 207 | Say Y here if you want support for cameras based on the ZC3XX chip. | ||
| 208 | |||
| 209 | To compile this driver as a module, choose M here: the | ||
| 210 | module will be called gspca_zc3xx. | ||
| 211 | |||
| 212 | endif | ||
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index e68a8965297a..22734f5a6c32 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile | |||
| @@ -1,29 +1,48 @@ | |||
| 1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o \ | 1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o |
| 2 | gspca_conex.o gspca_etoms.o gspca_mars.o \ | 2 | obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o |
| 3 | gspca_ov519.o gspca_pac207.o gspca_pac7311.o \ | 3 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o |
| 4 | gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \ | 4 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o |
| 5 | gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \ | 5 | obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o |
| 6 | gspca_sunplus.o gspca_stk014.o gspca_t613.o gspca_tv8532.o \ | 6 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o |
| 7 | gspca_vc032x.o gspca_zc3xx.o | 7 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o |
| 8 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o | ||
| 9 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o | ||
| 10 | obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o | ||
| 11 | obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o | ||
| 12 | obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o | ||
| 13 | obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o | ||
| 14 | obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o | ||
| 15 | obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o | ||
| 16 | obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o | ||
| 17 | obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o | ||
| 18 | obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o | ||
| 19 | obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o | ||
| 20 | obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o | ||
| 21 | obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o | ||
| 22 | obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o | ||
| 23 | |||
| 24 | gspca_main-objs := gspca.o | ||
| 25 | gspca_conex-objs := conex.o | ||
| 26 | gspca_etoms-objs := etoms.o | ||
| 27 | gspca_finepix-objs := finepix.o | ||
| 28 | gspca_mars-objs := mars.o | ||
| 29 | gspca_ov519-objs := ov519.o | ||
| 30 | gspca_pac207-objs := pac207.o | ||
| 31 | gspca_pac7311-objs := pac7311.o | ||
| 32 | gspca_sonixb-objs := sonixb.o | ||
| 33 | gspca_sonixj-objs := sonixj.o | ||
| 34 | gspca_spca500-objs := spca500.o | ||
| 35 | gspca_spca501-objs := spca501.o | ||
| 36 | gspca_spca505-objs := spca505.o | ||
| 37 | gspca_spca506-objs := spca506.o | ||
| 38 | gspca_spca508-objs := spca508.o | ||
| 39 | gspca_spca561-objs := spca561.o | ||
| 40 | gspca_stk014-objs := stk014.o | ||
| 41 | gspca_sunplus-objs := sunplus.o | ||
| 42 | gspca_t613-objs := t613.o | ||
| 43 | gspca_tv8532-objs := tv8532.o | ||
| 44 | gspca_vc032x-objs := vc032x.o | ||
| 45 | gspca_zc3xx-objs := zc3xx.o | ||
| 46 | |||
| 47 | obj-$(CONFIG_USB_M5602) += m5602/ | ||
| 8 | 48 | ||
| 9 | gspca_main-objs := gspca.o | ||
| 10 | gspca_conex-objs := conex.o | ||
| 11 | gspca_etoms-objs := etoms.o | ||
| 12 | gspca_mars-objs := mars.o | ||
| 13 | gspca_ov519-objs := ov519.o | ||
| 14 | gspca_pac207-objs := pac207.o | ||
| 15 | gspca_pac7311-objs := pac7311.o | ||
| 16 | gspca_sonixb-objs := sonixb.o | ||
| 17 | gspca_sonixj-objs := sonixj.o | ||
| 18 | gspca_spca500-objs := spca500.o | ||
| 19 | gspca_spca501-objs := spca501.o | ||
| 20 | gspca_spca505-objs := spca505.o | ||
| 21 | gspca_spca506-objs := spca506.o | ||
| 22 | gspca_spca508-objs := spca508.o | ||
| 23 | gspca_spca561-objs := spca561.o | ||
| 24 | gspca_stk014-objs := stk014.o | ||
| 25 | gspca_sunplus-objs := sunplus.o | ||
| 26 | gspca_t613-objs := t613.o | ||
| 27 | gspca_tv8532-objs := tv8532.o | ||
| 28 | gspca_vc032x-objs := vc032x.o | ||
| 29 | gspca_zc3xx-objs := zc3xx.o | ||
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 4d9f4cc255a9..a9d51ba7c57c 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c | |||
| @@ -837,12 +837,13 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 837 | return 0; | 837 | return 0; |
| 838 | } | 838 | } |
| 839 | 839 | ||
| 840 | static void sd_start(struct gspca_dev *gspca_dev) | 840 | static int sd_start(struct gspca_dev *gspca_dev) |
| 841 | { | 841 | { |
| 842 | cx11646_initsize(gspca_dev); | 842 | cx11646_initsize(gspca_dev); |
| 843 | cx11646_fw(gspca_dev); | 843 | cx11646_fw(gspca_dev); |
| 844 | cx_sensor(gspca_dev); | 844 | cx_sensor(gspca_dev); |
| 845 | cx11646_jpeg(gspca_dev); | 845 | cx11646_jpeg(gspca_dev); |
| 846 | return 0; | ||
| 846 | } | 847 | } |
| 847 | 848 | ||
| 848 | static void sd_stop0(struct gspca_dev *gspca_dev) | 849 | static void sd_stop0(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index 4ff0e386914b..3be30b420a26 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c | |||
| @@ -691,7 +691,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 691 | } | 691 | } |
| 692 | 692 | ||
| 693 | /* -- start the camera -- */ | 693 | /* -- start the camera -- */ |
| 694 | static void sd_start(struct gspca_dev *gspca_dev) | 694 | static int sd_start(struct gspca_dev *gspca_dev) |
| 695 | { | 695 | { |
| 696 | struct sd *sd = (struct sd *) gspca_dev; | 696 | struct sd *sd = (struct sd *) gspca_dev; |
| 697 | 697 | ||
| @@ -704,6 +704,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 704 | 704 | ||
| 705 | reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); | 705 | reg_w_val(gspca_dev, ET_RESET_ALL, 0x08); |
| 706 | et_video(gspca_dev, 1); /* video on */ | 706 | et_video(gspca_dev, 1); /* video on */ |
| 707 | return 0; | ||
| 707 | } | 708 | } |
| 708 | 709 | ||
| 709 | static void sd_stopN(struct gspca_dev *gspca_dev) | 710 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c new file mode 100644 index 000000000000..65d3cbfe6b27 --- /dev/null +++ b/drivers/media/video/gspca/finepix.c | |||
| @@ -0,0 +1,466 @@ | |||
| 1 | /* | ||
| 2 | * Fujifilm Finepix subdriver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Frank Zago | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #define MODULE_NAME "finepix" | ||
| 22 | |||
| 23 | #include "gspca.h" | ||
| 24 | |||
| 25 | MODULE_AUTHOR("Frank Zago <frank@zago.net>"); | ||
| 26 | MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver"); | ||
| 27 | MODULE_LICENSE("GPL"); | ||
| 28 | |||
| 29 | /* Default timeout, in ms */ | ||
| 30 | #define FPIX_TIMEOUT (HZ / 10) | ||
| 31 | |||
| 32 | /* Maximum transfer size to use. The windows driver reads by chunks of | ||
| 33 | * 0x2000 bytes, so do the same. Note: reading more seems to work | ||
| 34 | * too. */ | ||
| 35 | #define FPIX_MAX_TRANSFER 0x2000 | ||
| 36 | |||
| 37 | /* Structure to hold all of our device specific stuff */ | ||
| 38 | struct usb_fpix { | ||
| 39 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
| 40 | |||
| 41 | /* | ||
| 42 | * USB stuff | ||
| 43 | */ | ||
| 44 | struct usb_ctrlrequest ctrlreq; | ||
| 45 | struct urb *control_urb; | ||
| 46 | struct timer_list bulk_timer; | ||
| 47 | |||
| 48 | enum { | ||
| 49 | FPIX_NOP, /* inactive, else streaming */ | ||
| 50 | FPIX_RESET, /* must reset */ | ||
| 51 | FPIX_REQ_FRAME, /* requesting a frame */ | ||
| 52 | FPIX_READ_FRAME, /* reading frame */ | ||
| 53 | } state; | ||
| 54 | |||
| 55 | /* | ||
| 56 | * Driver stuff | ||
| 57 | */ | ||
| 58 | struct delayed_work wqe; | ||
| 59 | struct completion can_close; | ||
| 60 | int streaming; | ||
| 61 | }; | ||
| 62 | |||
| 63 | /* Delay after which claim the next frame. If the delay is too small, | ||
| 64 | * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms | ||
| 65 | * will fail every 4 or 5 frames, but 30ms is perfect. */ | ||
| 66 | #define NEXT_FRAME_DELAY (((HZ * 30) + 999) / 1000) | ||
| 67 | |||
| 68 | #define dev_new_state(new_state) { \ | ||
| 69 | PDEBUG(D_STREAM, "new state from %d to %d at %s:%d", \ | ||
| 70 | dev->state, new_state, __func__, __LINE__); \ | ||
| 71 | dev->state = new_state; \ | ||
| 72 | } | ||
| 73 | |||
| 74 | /* These cameras only support 320x200. */ | ||
| 75 | static struct v4l2_pix_format fpix_mode[1] = { | ||
| 76 | { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
| 77 | .bytesperline = 320, | ||
| 78 | .sizeimage = 320 * 240 * 3 / 8 + 590, | ||
| 79 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 80 | .priv = 0} | ||
| 81 | }; | ||
| 82 | |||
| 83 | /* Reads part of a frame */ | ||
| 84 | static void read_frame_part(struct usb_fpix *dev) | ||
| 85 | { | ||
| 86 | int ret; | ||
| 87 | |||
| 88 | PDEBUG(D_STREAM, "read_frame_part"); | ||
| 89 | |||
| 90 | /* Reads part of a frame */ | ||
| 91 | ret = usb_submit_urb(dev->gspca_dev.urb[0], GFP_ATOMIC); | ||
| 92 | if (ret) { | ||
| 93 | dev_new_state(FPIX_RESET); | ||
| 94 | schedule_delayed_work(&dev->wqe, 1); | ||
| 95 | PDEBUG(D_STREAM, "usb_submit_urb failed with %d", | ||
| 96 | ret); | ||
| 97 | } else { | ||
| 98 | /* Sometimes we never get a callback, so use a timer. | ||
| 99 | * Is this masking a bug somewhere else? */ | ||
| 100 | dev->bulk_timer.expires = jiffies + msecs_to_jiffies(150); | ||
| 101 | add_timer(&dev->bulk_timer); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | /* Callback for URBs. */ | ||
| 106 | static void urb_callback(struct urb *urb) | ||
| 107 | { | ||
| 108 | struct gspca_dev *gspca_dev = urb->context; | ||
| 109 | struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; | ||
| 110 | |||
| 111 | PDEBUG(D_PACK, | ||
| 112 | "enter urb_callback - status=%d, length=%d", | ||
| 113 | urb->status, urb->actual_length); | ||
| 114 | |||
| 115 | if (dev->state == FPIX_READ_FRAME) | ||
| 116 | del_timer(&dev->bulk_timer); | ||
| 117 | |||
| 118 | if (urb->status != 0) { | ||
| 119 | /* We kill a stuck urb every 50 frames on average, so don't | ||
| 120 | * display a log message for that. */ | ||
| 121 | if (urb->status != -ECONNRESET) | ||
| 122 | PDEBUG(D_STREAM, "bad URB status %d", urb->status); | ||
| 123 | dev_new_state(FPIX_RESET); | ||
| 124 | schedule_delayed_work(&dev->wqe, 1); | ||
| 125 | } | ||
| 126 | |||
| 127 | switch (dev->state) { | ||
| 128 | case FPIX_REQ_FRAME: | ||
| 129 | dev_new_state(FPIX_READ_FRAME); | ||
| 130 | read_frame_part(dev); | ||
| 131 | break; | ||
| 132 | |||
| 133 | case FPIX_READ_FRAME: { | ||
| 134 | unsigned char *data = urb->transfer_buffer; | ||
| 135 | struct gspca_frame *frame; | ||
| 136 | |||
| 137 | frame = gspca_get_i_frame(&dev->gspca_dev); | ||
| 138 | if (frame == NULL) | ||
| 139 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
| 140 | if (urb->actual_length < FPIX_MAX_TRANSFER || | ||
| 141 | (data[urb->actual_length-2] == 0xff && | ||
| 142 | data[urb->actual_length-1] == 0xd9)) { | ||
| 143 | |||
| 144 | /* If the result is less than what was asked | ||
| 145 | * for, then it's the end of the | ||
| 146 | * frame. Sometime the jpeg is not complete, | ||
| 147 | * but there's nothing we can do. We also end | ||
| 148 | * here if the the jpeg ends right at the end | ||
| 149 | * of the frame. */ | ||
| 150 | if (frame) | ||
| 151 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
| 152 | frame, | ||
| 153 | data, urb->actual_length); | ||
| 154 | dev_new_state(FPIX_REQ_FRAME); | ||
| 155 | schedule_delayed_work(&dev->wqe, NEXT_FRAME_DELAY); | ||
| 156 | } else { | ||
| 157 | |||
| 158 | /* got a partial image */ | ||
| 159 | if (frame) | ||
| 160 | gspca_frame_add(gspca_dev, | ||
| 161 | gspca_dev->last_packet_type | ||
| 162 | == LAST_PACKET | ||
| 163 | ? FIRST_PACKET : INTER_PACKET, | ||
| 164 | frame, | ||
| 165 | data, urb->actual_length); | ||
| 166 | read_frame_part(dev); | ||
| 167 | } | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | |||
| 171 | case FPIX_NOP: | ||
| 172 | case FPIX_RESET: | ||
| 173 | PDEBUG(D_STREAM, "invalid state %d", dev->state); | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | /* Request a new frame */ | ||
| 179 | static void request_frame(struct usb_fpix *dev) | ||
| 180 | { | ||
| 181 | int ret; | ||
| 182 | struct gspca_dev *gspca_dev = &dev->gspca_dev; | ||
| 183 | |||
| 184 | /* Setup command packet */ | ||
| 185 | memset(gspca_dev->usb_buf, 0, 12); | ||
| 186 | gspca_dev->usb_buf[0] = 0xd3; | ||
| 187 | gspca_dev->usb_buf[7] = 0x01; | ||
| 188 | |||
| 189 | /* Request a frame */ | ||
| 190 | dev->ctrlreq.bRequestType = | ||
| 191 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
| 192 | dev->ctrlreq.bRequest = USB_REQ_GET_STATUS; | ||
| 193 | dev->ctrlreq.wValue = 0; | ||
| 194 | dev->ctrlreq.wIndex = 0; | ||
| 195 | dev->ctrlreq.wLength = cpu_to_le16(12); | ||
| 196 | |||
| 197 | usb_fill_control_urb(dev->control_urb, | ||
| 198 | gspca_dev->dev, | ||
| 199 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
| 200 | (unsigned char *) &dev->ctrlreq, | ||
| 201 | gspca_dev->usb_buf, | ||
| 202 | 12, urb_callback, gspca_dev); | ||
| 203 | |||
| 204 | ret = usb_submit_urb(dev->control_urb, GFP_ATOMIC); | ||
| 205 | if (ret) { | ||
| 206 | dev_new_state(FPIX_RESET); | ||
| 207 | schedule_delayed_work(&dev->wqe, 1); | ||
| 208 | PDEBUG(D_STREAM, "usb_submit_urb failed with %d", ret); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | /*--------------------------------------------------------------------------*/ | ||
| 213 | |||
| 214 | /* State machine. */ | ||
| 215 | static void fpix_sm(struct work_struct *work) | ||
| 216 | { | ||
| 217 | struct usb_fpix *dev = container_of(work, struct usb_fpix, wqe.work); | ||
| 218 | |||
| 219 | PDEBUG(D_STREAM, "fpix_sm state %d", dev->state); | ||
| 220 | |||
| 221 | /* verify that the device wasn't unplugged */ | ||
| 222 | if (!dev->gspca_dev.present) { | ||
| 223 | PDEBUG(D_STREAM, "device is gone"); | ||
| 224 | dev_new_state(FPIX_NOP); | ||
| 225 | complete(&dev->can_close); | ||
| 226 | return; | ||
| 227 | } | ||
| 228 | |||
| 229 | if (!dev->streaming) { | ||
| 230 | PDEBUG(D_STREAM, "stopping state machine"); | ||
| 231 | dev_new_state(FPIX_NOP); | ||
| 232 | complete(&dev->can_close); | ||
| 233 | return; | ||
| 234 | } | ||
| 235 | |||
| 236 | switch (dev->state) { | ||
| 237 | case FPIX_RESET: | ||
| 238 | dev_new_state(FPIX_REQ_FRAME); | ||
| 239 | schedule_delayed_work(&dev->wqe, HZ / 10); | ||
| 240 | break; | ||
| 241 | |||
| 242 | case FPIX_REQ_FRAME: | ||
| 243 | /* get an image */ | ||
| 244 | request_frame(dev); | ||
| 245 | break; | ||
| 246 | |||
| 247 | case FPIX_NOP: | ||
| 248 | case FPIX_READ_FRAME: | ||
| 249 | PDEBUG(D_STREAM, "invalid state %d", dev->state); | ||
| 250 | break; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | /* this function is called at probe time */ | ||
| 255 | static int sd_config(struct gspca_dev *gspca_dev, | ||
| 256 | const struct usb_device_id *id) | ||
| 257 | { | ||
| 258 | struct cam *cam = &gspca_dev->cam; | ||
| 259 | |||
| 260 | cam->cam_mode = fpix_mode; | ||
| 261 | cam->nmodes = 1; | ||
| 262 | cam->epaddr = 0x01; /* todo: correct for all cams? */ | ||
| 263 | cam->bulk_size = FPIX_MAX_TRANSFER; | ||
| 264 | |||
| 265 | /* gspca_dev->nbalt = 1; * use bulk transfer */ | ||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | /* Stop streaming and free the ressources allocated by sd_start. */ | ||
| 270 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
| 271 | { | ||
| 272 | struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; | ||
| 273 | |||
| 274 | dev->streaming = 0; | ||
| 275 | |||
| 276 | /* Stop the state machine */ | ||
| 277 | if (dev->state != FPIX_NOP) | ||
| 278 | wait_for_completion(&dev->can_close); | ||
| 279 | |||
| 280 | usb_free_urb(dev->control_urb); | ||
| 281 | dev->control_urb = NULL; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* Kill an URB that hasn't completed. */ | ||
| 285 | static void timeout_kill(unsigned long data) | ||
| 286 | { | ||
| 287 | struct urb *urb = (struct urb *) data; | ||
| 288 | |||
| 289 | usb_unlink_urb(urb); | ||
| 290 | } | ||
| 291 | |||
| 292 | /* this function is called at probe and resume time */ | ||
| 293 | static int sd_init(struct gspca_dev *gspca_dev) | ||
| 294 | { | ||
| 295 | struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; | ||
| 296 | |||
| 297 | INIT_DELAYED_WORK(&dev->wqe, fpix_sm); | ||
| 298 | |||
| 299 | init_timer(&dev->bulk_timer); | ||
| 300 | dev->bulk_timer.function = timeout_kill; | ||
| 301 | |||
| 302 | return 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | static int sd_start(struct gspca_dev *gspca_dev) | ||
| 306 | { | ||
| 307 | struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; | ||
| 308 | int ret; | ||
| 309 | int size_ret; | ||
| 310 | |||
| 311 | /* Reset bulk in endpoint */ | ||
| 312 | usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr); | ||
| 313 | |||
| 314 | /* Init the device */ | ||
| 315 | memset(gspca_dev->usb_buf, 0, 12); | ||
| 316 | gspca_dev->usb_buf[0] = 0xc6; | ||
| 317 | gspca_dev->usb_buf[8] = 0x20; | ||
| 318 | |||
| 319 | ret = usb_control_msg(gspca_dev->dev, | ||
| 320 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
| 321 | USB_REQ_GET_STATUS, | ||
| 322 | USB_DIR_OUT | USB_TYPE_CLASS | | ||
| 323 | USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, | ||
| 324 | 12, FPIX_TIMEOUT); | ||
| 325 | |||
| 326 | if (ret != 12) { | ||
| 327 | PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret); | ||
| 328 | ret = -EIO; | ||
| 329 | goto error; | ||
| 330 | } | ||
| 331 | |||
| 332 | /* Read the result of the command. Ignore the result, for it | ||
| 333 | * varies with the device. */ | ||
| 334 | ret = usb_bulk_msg(gspca_dev->dev, | ||
| 335 | usb_rcvbulkpipe(gspca_dev->dev, | ||
| 336 | gspca_dev->cam.epaddr), | ||
| 337 | gspca_dev->usb_buf, FPIX_MAX_TRANSFER, &size_ret, | ||
| 338 | FPIX_TIMEOUT); | ||
| 339 | if (ret != 0) { | ||
| 340 | PDEBUG(D_STREAM, "usb_bulk_msg failed (%d)", ret); | ||
| 341 | ret = -EIO; | ||
| 342 | goto error; | ||
| 343 | } | ||
| 344 | |||
| 345 | /* Request a frame, but don't read it */ | ||
| 346 | memset(gspca_dev->usb_buf, 0, 12); | ||
| 347 | gspca_dev->usb_buf[0] = 0xd3; | ||
| 348 | gspca_dev->usb_buf[7] = 0x01; | ||
| 349 | |||
| 350 | ret = usb_control_msg(gspca_dev->dev, | ||
| 351 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
| 352 | USB_REQ_GET_STATUS, | ||
| 353 | USB_DIR_OUT | USB_TYPE_CLASS | | ||
| 354 | USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf, | ||
| 355 | 12, FPIX_TIMEOUT); | ||
| 356 | if (ret != 12) { | ||
| 357 | PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret); | ||
| 358 | ret = -EIO; | ||
| 359 | goto error; | ||
| 360 | } | ||
| 361 | |||
| 362 | /* Again, reset bulk in endpoint */ | ||
| 363 | usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr); | ||
| 364 | |||
| 365 | /* Allocate a control URB */ | ||
| 366 | dev->control_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 367 | if (!dev->control_urb) { | ||
| 368 | PDEBUG(D_STREAM, "No free urbs available"); | ||
| 369 | ret = -EIO; | ||
| 370 | goto error; | ||
| 371 | } | ||
| 372 | |||
| 373 | /* Various initializations. */ | ||
| 374 | init_completion(&dev->can_close); | ||
| 375 | dev->bulk_timer.data = (unsigned long)dev->gspca_dev.urb[0]; | ||
| 376 | dev->gspca_dev.urb[0]->complete = urb_callback; | ||
| 377 | dev->streaming = 1; | ||
| 378 | |||
| 379 | /* Schedule a frame request. */ | ||
| 380 | dev_new_state(FPIX_REQ_FRAME); | ||
| 381 | schedule_delayed_work(&dev->wqe, 1); | ||
| 382 | |||
| 383 | return 0; | ||
| 384 | |||
| 385 | error: | ||
| 386 | /* Free the ressources */ | ||
| 387 | sd_stopN(gspca_dev); | ||
| 388 | return ret; | ||
| 389 | } | ||
| 390 | |||
| 391 | /* Table of supported USB devices */ | ||
| 392 | static const __devinitdata struct usb_device_id device_table[] = { | ||
| 393 | {USB_DEVICE(0x04cb, 0x0104)}, | ||
| 394 | {USB_DEVICE(0x04cb, 0x0109)}, | ||
| 395 | {USB_DEVICE(0x04cb, 0x010b)}, | ||
| 396 | {USB_DEVICE(0x04cb, 0x010f)}, | ||
| 397 | {USB_DEVICE(0x04cb, 0x0111)}, | ||
| 398 | {USB_DEVICE(0x04cb, 0x0113)}, | ||
| 399 | {USB_DEVICE(0x04cb, 0x0115)}, | ||
| 400 | {USB_DEVICE(0x04cb, 0x0117)}, | ||
| 401 | {USB_DEVICE(0x04cb, 0x0119)}, | ||
| 402 | {USB_DEVICE(0x04cb, 0x011b)}, | ||
| 403 | {USB_DEVICE(0x04cb, 0x011d)}, | ||
| 404 | {USB_DEVICE(0x04cb, 0x0121)}, | ||
| 405 | {USB_DEVICE(0x04cb, 0x0123)}, | ||
| 406 | {USB_DEVICE(0x04cb, 0x0125)}, | ||
| 407 | {USB_DEVICE(0x04cb, 0x0127)}, | ||
| 408 | {USB_DEVICE(0x04cb, 0x0129)}, | ||
| 409 | {USB_DEVICE(0x04cb, 0x012b)}, | ||
| 410 | {USB_DEVICE(0x04cb, 0x012d)}, | ||
| 411 | {USB_DEVICE(0x04cb, 0x012f)}, | ||
| 412 | {USB_DEVICE(0x04cb, 0x0131)}, | ||
| 413 | {USB_DEVICE(0x04cb, 0x013b)}, | ||
| 414 | {USB_DEVICE(0x04cb, 0x013d)}, | ||
| 415 | {USB_DEVICE(0x04cb, 0x013f)}, | ||
| 416 | {} | ||
| 417 | }; | ||
| 418 | |||
| 419 | MODULE_DEVICE_TABLE(usb, device_table); | ||
| 420 | |||
| 421 | /* sub-driver description */ | ||
| 422 | static const struct sd_desc sd_desc = { | ||
| 423 | .name = MODULE_NAME, | ||
| 424 | .config = sd_config, | ||
| 425 | .init = sd_init, | ||
| 426 | .start = sd_start, | ||
| 427 | .stopN = sd_stopN, | ||
| 428 | }; | ||
| 429 | |||
| 430 | /* -- device connect -- */ | ||
| 431 | static int sd_probe(struct usb_interface *intf, | ||
| 432 | const struct usb_device_id *id) | ||
| 433 | { | ||
| 434 | return gspca_dev_probe(intf, id, | ||
| 435 | &sd_desc, | ||
| 436 | sizeof(struct usb_fpix), | ||
| 437 | THIS_MODULE); | ||
| 438 | } | ||
| 439 | |||
| 440 | static struct usb_driver sd_driver = { | ||
| 441 | .name = MODULE_NAME, | ||
| 442 | .id_table = device_table, | ||
| 443 | .probe = sd_probe, | ||
| 444 | .disconnect = gspca_disconnect, | ||
| 445 | #ifdef CONFIG_PM | ||
| 446 | .suspend = gspca_suspend, | ||
| 447 | .resume = gspca_resume, | ||
| 448 | #endif | ||
| 449 | }; | ||
| 450 | |||
| 451 | /* -- module insert / remove -- */ | ||
| 452 | static int __init sd_mod_init(void) | ||
| 453 | { | ||
| 454 | if (usb_register(&sd_driver) < 0) | ||
| 455 | return -1; | ||
| 456 | PDEBUG(D_PROBE, "registered"); | ||
| 457 | return 0; | ||
| 458 | } | ||
| 459 | static void __exit sd_mod_exit(void) | ||
| 460 | { | ||
| 461 | usb_deregister(&sd_driver); | ||
| 462 | PDEBUG(D_PROBE, "deregistered"); | ||
| 463 | } | ||
| 464 | |||
| 465 | module_init(sd_mod_init); | ||
| 466 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index ac95c55887df..c21af312ee7c 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/string.h> | 29 | #include <linux/string.h> |
| 30 | #include <linux/pagemap.h> | 30 | #include <linux/pagemap.h> |
| 31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
| 32 | #include <linux/kref.h> | ||
| 32 | #include <asm/page.h> | 33 | #include <asm/page.h> |
| 33 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
| 34 | #include <linux/jiffies.h> | 35 | #include <linux/jiffies.h> |
| @@ -43,7 +44,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
| 43 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 44 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
| 44 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
| 45 | 46 | ||
| 46 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 2, 0) | 47 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 3, 0) |
| 47 | 48 | ||
| 48 | static int video_nr = -1; | 49 | static int video_nr = -1; |
| 49 | 50 | ||
| @@ -102,6 +103,22 @@ static struct vm_operations_struct gspca_vm_ops = { | |||
| 102 | .close = gspca_vm_close, | 103 | .close = gspca_vm_close, |
| 103 | }; | 104 | }; |
| 104 | 105 | ||
| 106 | /* get the current input frame buffer */ | ||
| 107 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) | ||
| 108 | { | ||
| 109 | struct gspca_frame *frame; | ||
| 110 | int i; | ||
| 111 | |||
| 112 | i = gspca_dev->fr_i; | ||
| 113 | i = gspca_dev->fr_queue[i]; | ||
| 114 | frame = &gspca_dev->frame[i]; | ||
| 115 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | ||
| 116 | != V4L2_BUF_FLAG_QUEUED) | ||
| 117 | return NULL; | ||
| 118 | return frame; | ||
| 119 | } | ||
| 120 | EXPORT_SYMBOL(gspca_get_i_frame); | ||
| 121 | |||
| 105 | /* | 122 | /* |
| 106 | * fill a video frame from an URB and resubmit | 123 | * fill a video frame from an URB and resubmit |
| 107 | */ | 124 | */ |
| @@ -110,7 +127,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, | |||
| 110 | { | 127 | { |
| 111 | struct gspca_frame *frame; | 128 | struct gspca_frame *frame; |
| 112 | __u8 *data; /* address of data in the iso message */ | 129 | __u8 *data; /* address of data in the iso message */ |
| 113 | int i, j, len, st; | 130 | int i, len, st; |
| 114 | cam_pkt_op pkt_scan; | 131 | cam_pkt_op pkt_scan; |
| 115 | 132 | ||
| 116 | if (urb->status != 0) { | 133 | if (urb->status != 0) { |
| @@ -124,11 +141,8 @@ static void fill_frame(struct gspca_dev *gspca_dev, | |||
| 124 | for (i = 0; i < urb->number_of_packets; i++) { | 141 | for (i = 0; i < urb->number_of_packets; i++) { |
| 125 | 142 | ||
| 126 | /* check the availability of the frame buffer */ | 143 | /* check the availability of the frame buffer */ |
| 127 | j = gspca_dev->fr_i; | 144 | frame = gspca_get_i_frame(gspca_dev); |
| 128 | j = gspca_dev->fr_queue[j]; | 145 | if (!frame) { |
| 129 | frame = &gspca_dev->frame[j]; | ||
| 130 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | ||
| 131 | != V4L2_BUF_FLAG_QUEUED) { | ||
| 132 | gspca_dev->last_packet_type = DISCARD_PACKET; | 146 | gspca_dev->last_packet_type = DISCARD_PACKET; |
| 133 | break; | 147 | break; |
| 134 | } | 148 | } |
| @@ -178,6 +192,39 @@ static void isoc_irq(struct urb *urb | |||
| 178 | } | 192 | } |
| 179 | 193 | ||
| 180 | /* | 194 | /* |
| 195 | * bulk message interrupt from the USB device | ||
| 196 | */ | ||
| 197 | static void bulk_irq(struct urb *urb | ||
| 198 | ) | ||
| 199 | { | ||
| 200 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
| 201 | struct gspca_frame *frame; | ||
| 202 | |||
| 203 | PDEBUG(D_PACK, "bulk irq"); | ||
| 204 | if (!gspca_dev->streaming) | ||
| 205 | return; | ||
| 206 | if (urb->status != 0 && urb->status != -ECONNRESET) { | ||
| 207 | #ifdef CONFIG_PM | ||
| 208 | if (!gspca_dev->frozen) | ||
| 209 | #endif | ||
| 210 | PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); | ||
| 211 | return; /* disconnection ? */ | ||
| 212 | } | ||
| 213 | |||
| 214 | /* check the availability of the frame buffer */ | ||
| 215 | frame = gspca_get_i_frame(gspca_dev); | ||
| 216 | if (!frame) { | ||
| 217 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
| 218 | } else { | ||
| 219 | PDEBUG(D_PACK, "packet l:%d", urb->actual_length); | ||
| 220 | gspca_dev->sd_desc->pkt_scan(gspca_dev, | ||
| 221 | frame, | ||
| 222 | urb->transfer_buffer, | ||
| 223 | urb->actual_length); | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | /* | ||
| 181 | * add data to the current frame | 228 | * add data to the current frame |
| 182 | * | 229 | * |
| 183 | * This function is called by the subdrivers at interrupt level. | 230 | * This function is called by the subdrivers at interrupt level. |
| @@ -190,7 +237,7 @@ static void isoc_irq(struct urb *urb | |||
| 190 | * On LAST_PACKET, a new frame is returned. | 237 | * On LAST_PACKET, a new frame is returned. |
| 191 | */ | 238 | */ |
| 192 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | 239 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, |
| 193 | int packet_type, | 240 | enum gspca_packet_type packet_type, |
| 194 | struct gspca_frame *frame, | 241 | struct gspca_frame *frame, |
| 195 | const __u8 *data, | 242 | const __u8 *data, |
| 196 | int len) | 243 | int len) |
| @@ -232,7 +279,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | |||
| 232 | } | 279 | } |
| 233 | gspca_dev->last_packet_type = packet_type; | 280 | gspca_dev->last_packet_type = packet_type; |
| 234 | 281 | ||
| 235 | /* if last packet, wake the application and advance in the queue */ | 282 | /* if last packet, wake up the application and advance in the queue */ |
| 236 | if (packet_type == LAST_PACKET) { | 283 | if (packet_type == LAST_PACKET) { |
| 237 | frame->v4l2_buf.bytesused = frame->data_end - frame->data; | 284 | frame->v4l2_buf.bytesused = frame->data_end - frame->data; |
| 238 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; | 285 | frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; |
| @@ -270,7 +317,6 @@ static void *rvmalloc(unsigned long size) | |||
| 270 | void *mem; | 317 | void *mem; |
| 271 | unsigned long adr; | 318 | unsigned long adr; |
| 272 | 319 | ||
| 273 | /* size = PAGE_ALIGN(size); (already done) */ | ||
| 274 | mem = vmalloc_32(size); | 320 | mem = vmalloc_32(size); |
| 275 | if (mem != NULL) { | 321 | if (mem != NULL) { |
| 276 | adr = (unsigned long) mem; | 322 | adr = (unsigned long) mem; |
| @@ -374,10 +420,11 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) | |||
| 374 | } | 420 | } |
| 375 | 421 | ||
| 376 | /* | 422 | /* |
| 377 | * search an input isochronous endpoint in an alternate setting | 423 | * look for an input transfer endpoint in an alternate setting |
| 378 | */ | 424 | */ |
| 379 | static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, | 425 | static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, |
| 380 | __u8 epaddr) | 426 | __u8 epaddr, |
| 427 | __u8 xfer) | ||
| 381 | { | 428 | { |
| 382 | struct usb_host_endpoint *ep; | 429 | struct usb_host_endpoint *ep; |
| 383 | int i, attr; | 430 | int i, attr; |
| @@ -388,7 +435,7 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, | |||
| 388 | if (ep->desc.bEndpointAddress == epaddr) { | 435 | if (ep->desc.bEndpointAddress == epaddr) { |
| 389 | attr = ep->desc.bmAttributes | 436 | attr = ep->desc.bmAttributes |
| 390 | & USB_ENDPOINT_XFERTYPE_MASK; | 437 | & USB_ENDPOINT_XFERTYPE_MASK; |
| 391 | if (attr == USB_ENDPOINT_XFER_ISOC) | 438 | if (attr == xfer) |
| 392 | return ep; | 439 | return ep; |
| 393 | break; | 440 | break; |
| 394 | } | 441 | } |
| @@ -397,14 +444,14 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt, | |||
| 397 | } | 444 | } |
| 398 | 445 | ||
| 399 | /* | 446 | /* |
| 400 | * search an input isochronous endpoint | 447 | * look for an input (isoc or bulk) endpoint |
| 401 | * | 448 | * |
| 402 | * The endpoint is defined by the subdriver. | 449 | * The endpoint is defined by the subdriver. |
| 403 | * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep). | 450 | * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep). |
| 404 | * This routine may be called many times when the bandwidth is too small | 451 | * This routine may be called many times when the bandwidth is too small |
| 405 | * (the bandwidth is checked on urb submit). | 452 | * (the bandwidth is checked on urb submit). |
| 406 | */ | 453 | */ |
| 407 | static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev) | 454 | static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) |
| 408 | { | 455 | { |
| 409 | struct usb_interface *intf; | 456 | struct usb_interface *intf; |
| 410 | struct usb_host_endpoint *ep; | 457 | struct usb_host_endpoint *ep; |
| @@ -413,28 +460,41 @@ static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev) | |||
| 413 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); | 460 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); |
| 414 | ep = NULL; | 461 | ep = NULL; |
| 415 | i = gspca_dev->alt; /* previous alt setting */ | 462 | i = gspca_dev->alt; /* previous alt setting */ |
| 463 | |||
| 464 | /* try isoc */ | ||
| 416 | while (--i > 0) { /* alt 0 is unusable */ | 465 | while (--i > 0) { /* alt 0 is unusable */ |
| 417 | ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr); | 466 | ep = alt_xfer(&intf->altsetting[i], |
| 467 | gspca_dev->cam.epaddr, | ||
| 468 | USB_ENDPOINT_XFER_ISOC); | ||
| 418 | if (ep) | 469 | if (ep) |
| 419 | break; | 470 | break; |
| 420 | } | 471 | } |
| 472 | |||
| 473 | /* if no isoc, try bulk */ | ||
| 421 | if (ep == NULL) { | 474 | if (ep == NULL) { |
| 422 | err("no ISOC endpoint found"); | 475 | ep = alt_xfer(&intf->altsetting[0], |
| 423 | return NULL; | 476 | gspca_dev->cam.epaddr, |
| 477 | USB_ENDPOINT_XFER_BULK); | ||
| 478 | if (ep == NULL) { | ||
| 479 | err("no transfer endpoint found"); | ||
| 480 | return NULL; | ||
| 481 | } | ||
| 424 | } | 482 | } |
| 425 | PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x", | 483 | PDEBUG(D_STREAM, "use alt %d ep 0x%02x", |
| 426 | i, ep->desc.bEndpointAddress); | 484 | i, ep->desc.bEndpointAddress); |
| 427 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); | 485 | if (i > 0) { |
| 428 | if (ret < 0) { | 486 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); |
| 429 | err("set interface err %d", ret); | 487 | if (ret < 0) { |
| 430 | return NULL; | 488 | err("set interface err %d", ret); |
| 489 | return NULL; | ||
| 490 | } | ||
| 431 | } | 491 | } |
| 432 | gspca_dev->alt = i; /* memorize the current alt setting */ | 492 | gspca_dev->alt = i; /* memorize the current alt setting */ |
| 433 | return ep; | 493 | return ep; |
| 434 | } | 494 | } |
| 435 | 495 | ||
| 436 | /* | 496 | /* |
| 437 | * create the isochronous URBs | 497 | * create the URBs for image transfer |
| 438 | */ | 498 | */ |
| 439 | static int create_urbs(struct gspca_dev *gspca_dev, | 499 | static int create_urbs(struct gspca_dev *gspca_dev, |
| 440 | struct usb_host_endpoint *ep) | 500 | struct usb_host_endpoint *ep) |
| @@ -445,15 +505,27 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
| 445 | /* calculate the packet size and the number of packets */ | 505 | /* calculate the packet size and the number of packets */ |
| 446 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | 506 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); |
| 447 | 507 | ||
| 448 | /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ | 508 | if (gspca_dev->alt != 0) { /* isoc */ |
| 449 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | 509 | |
| 450 | npkt = ISO_MAX_SIZE / psize; | 510 | /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */ |
| 451 | if (npkt > ISO_MAX_PKT) | 511 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); |
| 452 | npkt = ISO_MAX_PKT; | 512 | npkt = ISO_MAX_SIZE / psize; |
| 453 | bsize = psize * npkt; | 513 | if (npkt > ISO_MAX_PKT) |
| 454 | PDEBUG(D_STREAM, | 514 | npkt = ISO_MAX_PKT; |
| 455 | "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize); | 515 | bsize = psize * npkt; |
| 456 | nurbs = DEF_NURBS; | 516 | PDEBUG(D_STREAM, |
| 517 | "isoc %d pkts size %d = bsize:%d", | ||
| 518 | npkt, psize, bsize); | ||
| 519 | nurbs = DEF_NURBS; | ||
| 520 | } else { /* bulk */ | ||
| 521 | npkt = 0; | ||
| 522 | bsize = gspca_dev->cam. bulk_size; | ||
| 523 | if (bsize == 0) | ||
| 524 | bsize = psize; | ||
| 525 | PDEBUG(D_STREAM, "bulk bsize:%d", bsize); | ||
| 526 | nurbs = 1; | ||
| 527 | } | ||
| 528 | |||
| 457 | gspca_dev->nurbs = nurbs; | 529 | gspca_dev->nurbs = nurbs; |
| 458 | for (n = 0; n < nurbs; n++) { | 530 | for (n = 0; n < nurbs; n++) { |
| 459 | urb = usb_alloc_urb(npkt, GFP_KERNEL); | 531 | urb = usb_alloc_urb(npkt, GFP_KERNEL); |
| @@ -476,17 +548,24 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
| 476 | gspca_dev->urb[n] = urb; | 548 | gspca_dev->urb[n] = urb; |
| 477 | urb->dev = gspca_dev->dev; | 549 | urb->dev = gspca_dev->dev; |
| 478 | urb->context = gspca_dev; | 550 | urb->context = gspca_dev; |
| 479 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, | ||
| 480 | ep->desc.bEndpointAddress); | ||
| 481 | urb->transfer_flags = URB_ISO_ASAP | ||
| 482 | | URB_NO_TRANSFER_DMA_MAP; | ||
| 483 | urb->interval = ep->desc.bInterval; | ||
| 484 | urb->complete = isoc_irq; | ||
| 485 | urb->number_of_packets = npkt; | ||
| 486 | urb->transfer_buffer_length = bsize; | 551 | urb->transfer_buffer_length = bsize; |
| 487 | for (i = 0; i < npkt; i++) { | 552 | if (npkt != 0) { /* ISOC */ |
| 488 | urb->iso_frame_desc[i].length = psize; | 553 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, |
| 489 | urb->iso_frame_desc[i].offset = psize * i; | 554 | ep->desc.bEndpointAddress); |
| 555 | urb->transfer_flags = URB_ISO_ASAP | ||
| 556 | | URB_NO_TRANSFER_DMA_MAP; | ||
| 557 | urb->interval = ep->desc.bInterval; | ||
| 558 | urb->complete = isoc_irq; | ||
| 559 | urb->number_of_packets = npkt; | ||
| 560 | for (i = 0; i < npkt; i++) { | ||
| 561 | urb->iso_frame_desc[i].length = psize; | ||
| 562 | urb->iso_frame_desc[i].offset = psize * i; | ||
| 563 | } | ||
| 564 | } else { /* bulk */ | ||
| 565 | urb->pipe = usb_rcvbulkpipe(gspca_dev->dev, | ||
| 566 | ep->desc.bEndpointAddress), | ||
| 567 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
| 568 | urb->complete = bulk_irq; | ||
| 490 | } | 569 | } |
| 491 | } | 570 | } |
| 492 | return 0; | 571 | return 0; |
| @@ -508,7 +587,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
| 508 | gspca_dev->alt = gspca_dev->nbalt; | 587 | gspca_dev->alt = gspca_dev->nbalt; |
| 509 | for (;;) { | 588 | for (;;) { |
| 510 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); | 589 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); |
| 511 | ep = get_isoc_ep(gspca_dev); | 590 | ep = get_ep(gspca_dev); |
| 512 | if (ep == NULL) { | 591 | if (ep == NULL) { |
| 513 | ret = -EIO; | 592 | ret = -EIO; |
| 514 | goto out; | 593 | goto out; |
| @@ -518,10 +597,18 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
| 518 | goto out; | 597 | goto out; |
| 519 | 598 | ||
| 520 | /* start the cam */ | 599 | /* start the cam */ |
| 521 | gspca_dev->sd_desc->start(gspca_dev); | 600 | ret = gspca_dev->sd_desc->start(gspca_dev); |
| 601 | if (ret < 0) { | ||
| 602 | destroy_urbs(gspca_dev); | ||
| 603 | goto out; | ||
| 604 | } | ||
| 522 | gspca_dev->streaming = 1; | 605 | gspca_dev->streaming = 1; |
| 523 | atomic_set(&gspca_dev->nevent, 0); | 606 | atomic_set(&gspca_dev->nevent, 0); |
| 524 | 607 | ||
| 608 | /* bulk transfers are started by the subdriver */ | ||
| 609 | if (gspca_dev->alt == 0) | ||
| 610 | break; | ||
| 611 | |||
| 525 | /* submit the URBs */ | 612 | /* submit the URBs */ |
| 526 | for (n = 0; n < gspca_dev->nurbs; n++) { | 613 | for (n = 0; n < gspca_dev->nurbs; n++) { |
| 527 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); | 614 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); |
| @@ -553,7 +640,7 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev) | |||
| 553 | return ret; | 640 | return ret; |
| 554 | } | 641 | } |
| 555 | 642 | ||
| 556 | /* Note both the queue and the usb lock should be hold when calling this */ | 643 | /* Note: both the queue and the usb locks should be held when calling this */ |
| 557 | static void gspca_stream_off(struct gspca_dev *gspca_dev) | 644 | static void gspca_stream_off(struct gspca_dev *gspca_dev) |
| 558 | { | 645 | { |
| 559 | gspca_dev->streaming = 0; | 646 | gspca_dev->streaming = 0; |
| @@ -759,6 +846,16 @@ out: | |||
| 759 | return ret; | 846 | return ret; |
| 760 | } | 847 | } |
| 761 | 848 | ||
| 849 | static void gspca_delete(struct kref *kref) | ||
| 850 | { | ||
| 851 | struct gspca_dev *gspca_dev = container_of(kref, struct gspca_dev, kref); | ||
| 852 | |||
| 853 | PDEBUG(D_STREAM, "device deleted"); | ||
| 854 | |||
| 855 | kfree(gspca_dev->usb_buf); | ||
| 856 | kfree(gspca_dev); | ||
| 857 | } | ||
| 858 | |||
| 762 | static int dev_open(struct inode *inode, struct file *file) | 859 | static int dev_open(struct inode *inode, struct file *file) |
| 763 | { | 860 | { |
| 764 | struct gspca_dev *gspca_dev; | 861 | struct gspca_dev *gspca_dev; |
| @@ -778,13 +875,19 @@ static int dev_open(struct inode *inode, struct file *file) | |||
| 778 | goto out; | 875 | goto out; |
| 779 | } | 876 | } |
| 780 | gspca_dev->users++; | 877 | gspca_dev->users++; |
| 878 | |||
| 879 | /* one more user */ | ||
| 880 | kref_get(&gspca_dev->kref); | ||
| 881 | |||
| 781 | file->private_data = gspca_dev; | 882 | file->private_data = gspca_dev; |
| 782 | #ifdef GSPCA_DEBUG | 883 | #ifdef GSPCA_DEBUG |
| 783 | /* activate the v4l2 debug */ | 884 | /* activate the v4l2 debug */ |
| 784 | if (gspca_debug & D_V4L2) | 885 | if (gspca_debug & D_V4L2) |
| 785 | gspca_dev->vdev.debug |= 3; | 886 | gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL |
| 887 | | V4L2_DEBUG_IOCTL_ARG; | ||
| 786 | else | 888 | else |
| 787 | gspca_dev->vdev.debug &= ~3; | 889 | gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL |
| 890 | | V4L2_DEBUG_IOCTL_ARG); | ||
| 788 | #endif | 891 | #endif |
| 789 | ret = 0; | 892 | ret = 0; |
| 790 | out: | 893 | out: |
| @@ -818,7 +921,11 @@ static int dev_close(struct inode *inode, struct file *file) | |||
| 818 | } | 921 | } |
| 819 | file->private_data = NULL; | 922 | file->private_data = NULL; |
| 820 | mutex_unlock(&gspca_dev->queue_lock); | 923 | mutex_unlock(&gspca_dev->queue_lock); |
| 924 | |||
| 821 | PDEBUG(D_STREAM, "close done"); | 925 | PDEBUG(D_STREAM, "close done"); |
| 926 | |||
| 927 | kref_put(&gspca_dev->kref, gspca_delete); | ||
| 928 | |||
| 822 | return 0; | 929 | return 0; |
| 823 | } | 930 | } |
| 824 | 931 | ||
| @@ -829,7 +936,6 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
| 829 | 936 | ||
| 830 | memset(cap, 0, sizeof *cap); | 937 | memset(cap, 0, sizeof *cap); |
| 831 | strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); | 938 | strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); |
| 832 | /* strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card); */ | ||
| 833 | if (gspca_dev->dev->product != NULL) { | 939 | if (gspca_dev->dev->product != NULL) { |
| 834 | strncpy(cap->card, gspca_dev->dev->product, | 940 | strncpy(cap->card, gspca_dev->dev->product, |
| 835 | sizeof cap->card); | 941 | sizeof cap->card); |
| @@ -1463,7 +1569,6 @@ static int vidioc_qbuf(struct file *file, void *priv, | |||
| 1463 | } | 1569 | } |
| 1464 | 1570 | ||
| 1465 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; | 1571 | frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED; |
| 1466 | /* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */ | ||
| 1467 | 1572 | ||
| 1468 | if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { | 1573 | if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) { |
| 1469 | frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; | 1574 | frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr; |
| @@ -1610,7 +1715,7 @@ static ssize_t dev_read(struct file *file, char __user *data, | |||
| 1610 | } | 1715 | } |
| 1611 | 1716 | ||
| 1612 | /* if the process slept for more than 1 second, | 1717 | /* if the process slept for more than 1 second, |
| 1613 | * get anewer frame */ | 1718 | * get a newer frame */ |
| 1614 | frame = &gspca_dev->frame[v4l2_buf.index]; | 1719 | frame = &gspca_dev->frame[v4l2_buf.index]; |
| 1615 | if (--n < 0) | 1720 | if (--n < 0) |
| 1616 | break; /* avoid infinite loop */ | 1721 | break; /* avoid infinite loop */ |
| @@ -1728,21 +1833,21 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
| 1728 | if (dev_size < sizeof *gspca_dev) | 1833 | if (dev_size < sizeof *gspca_dev) |
| 1729 | dev_size = sizeof *gspca_dev; | 1834 | dev_size = sizeof *gspca_dev; |
| 1730 | gspca_dev = kzalloc(dev_size, GFP_KERNEL); | 1835 | gspca_dev = kzalloc(dev_size, GFP_KERNEL); |
| 1731 | if (gspca_dev == NULL) { | 1836 | if (!gspca_dev) { |
| 1732 | err("couldn't kzalloc gspca struct"); | 1837 | err("couldn't kzalloc gspca struct"); |
| 1733 | return -EIO; | 1838 | return -ENOMEM; |
| 1734 | } | 1839 | } |
| 1840 | kref_init(&gspca_dev->kref); | ||
| 1735 | gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); | 1841 | gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); |
| 1736 | if (!gspca_dev->usb_buf) { | 1842 | if (!gspca_dev->usb_buf) { |
| 1737 | err("out of memory"); | 1843 | err("out of memory"); |
| 1738 | ret = -EIO; | 1844 | ret = -ENOMEM; |
| 1739 | goto out; | 1845 | goto out; |
| 1740 | } | 1846 | } |
| 1741 | gspca_dev->dev = dev; | 1847 | gspca_dev->dev = dev; |
| 1742 | gspca_dev->iface = interface->bInterfaceNumber; | 1848 | gspca_dev->iface = interface->bInterfaceNumber; |
| 1743 | gspca_dev->nbalt = intf->num_altsetting; | 1849 | gspca_dev->nbalt = intf->num_altsetting; |
| 1744 | gspca_dev->sd_desc = sd_desc; | 1850 | gspca_dev->sd_desc = sd_desc; |
| 1745 | /* gspca_dev->users = 0; (done by kzalloc) */ | ||
| 1746 | gspca_dev->nbufread = 2; | 1851 | gspca_dev->nbufread = 2; |
| 1747 | 1852 | ||
| 1748 | /* configure the subdriver and initialize the USB device */ | 1853 | /* configure the subdriver and initialize the USB device */ |
| @@ -1781,8 +1886,7 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
| 1781 | PDEBUG(D_PROBE, "probe ok"); | 1886 | PDEBUG(D_PROBE, "probe ok"); |
| 1782 | return 0; | 1887 | return 0; |
| 1783 | out: | 1888 | out: |
| 1784 | kfree(gspca_dev->usb_buf); | 1889 | kref_put(&gspca_dev->kref, gspca_delete); |
| 1785 | kfree(gspca_dev); | ||
| 1786 | return ret; | 1890 | return ret; |
| 1787 | } | 1891 | } |
| 1788 | EXPORT_SYMBOL(gspca_dev_probe); | 1892 | EXPORT_SYMBOL(gspca_dev_probe); |
| @@ -1797,25 +1901,16 @@ void gspca_disconnect(struct usb_interface *intf) | |||
| 1797 | { | 1901 | { |
| 1798 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 1902 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
| 1799 | 1903 | ||
| 1800 | if (!gspca_dev) | 1904 | usb_set_intfdata(intf, NULL); |
| 1801 | return; | 1905 | |
| 1802 | gspca_dev->present = 0; | ||
| 1803 | mutex_lock(&gspca_dev->queue_lock); | ||
| 1804 | mutex_lock(&gspca_dev->usb_lock); | ||
| 1805 | gspca_dev->streaming = 0; | ||
| 1806 | destroy_urbs(gspca_dev); | ||
| 1807 | mutex_unlock(&gspca_dev->usb_lock); | ||
| 1808 | mutex_unlock(&gspca_dev->queue_lock); | ||
| 1809 | while (gspca_dev->users != 0) { /* wait until fully closed */ | ||
| 1810 | atomic_inc(&gspca_dev->nevent); | ||
| 1811 | wake_up_interruptible(&gspca_dev->wq); /* wake processes */ | ||
| 1812 | schedule(); | ||
| 1813 | } | ||
| 1814 | /* We don't want people trying to open up the device */ | 1906 | /* We don't want people trying to open up the device */ |
| 1815 | video_unregister_device(&gspca_dev->vdev); | 1907 | video_unregister_device(&gspca_dev->vdev); |
| 1816 | /* Free the memory */ | 1908 | |
| 1817 | kfree(gspca_dev->usb_buf); | 1909 | gspca_dev->present = 0; |
| 1818 | kfree(gspca_dev); | 1910 | gspca_dev->streaming = 0; |
| 1911 | |||
| 1912 | kref_put(&gspca_dev->kref, gspca_delete); | ||
| 1913 | |||
| 1819 | PDEBUG(D_PROBE, "disconnect complete"); | 1914 | PDEBUG(D_PROBE, "disconnect complete"); |
| 1820 | } | 1915 | } |
| 1821 | EXPORT_SYMBOL(gspca_disconnect); | 1916 | EXPORT_SYMBOL(gspca_disconnect); |
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index c17625cff9ba..4779dd0b06da 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
| @@ -49,13 +49,14 @@ extern int gspca_debug; | |||
| 49 | } while (0) | 49 | } while (0) |
| 50 | 50 | ||
| 51 | #define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */ | 51 | #define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */ |
| 52 | /* ISOC transfers */ | 52 | /* image transfers */ |
| 53 | #define MAX_NURBS 16 /* max number of URBs */ | 53 | #define MAX_NURBS 4 /* max number of URBs */ |
| 54 | #define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */ | 54 | #define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */ |
| 55 | #define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */ | 55 | #define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */ |
| 56 | 56 | ||
| 57 | /* device information - set at probe time */ | 57 | /* device information - set at probe time */ |
| 58 | struct cam { | 58 | struct cam { |
| 59 | int bulk_size; /* buffer size when image transfer by bulk */ | ||
| 59 | struct v4l2_pix_format *cam_mode; /* size nmodes */ | 60 | struct v4l2_pix_format *cam_mode; /* size nmodes */ |
| 60 | char nmodes; | 61 | char nmodes; |
| 61 | __u8 epaddr; | 62 | __u8 epaddr; |
| @@ -93,7 +94,7 @@ struct sd_desc { | |||
| 93 | /* mandatory operations */ | 94 | /* mandatory operations */ |
| 94 | cam_cf_op config; /* called on probe */ | 95 | cam_cf_op config; /* called on probe */ |
| 95 | cam_op init; /* called on probe and resume */ | 96 | cam_op init; /* called on probe and resume */ |
| 96 | cam_v_op start; /* called on stream on */ | 97 | cam_op start; /* called on stream on */ |
| 97 | cam_pkt_op pkt_scan; | 98 | cam_pkt_op pkt_scan; |
| 98 | /* optional operations */ | 99 | /* optional operations */ |
| 99 | cam_v_op stopN; /* called on stream off - main alt */ | 100 | cam_v_op stopN; /* called on stream off - main alt */ |
| @@ -105,10 +106,12 @@ struct sd_desc { | |||
| 105 | }; | 106 | }; |
| 106 | 107 | ||
| 107 | /* packet types when moving from iso buf to frame buf */ | 108 | /* packet types when moving from iso buf to frame buf */ |
| 108 | #define DISCARD_PACKET 0 | 109 | enum gspca_packet_type { |
| 109 | #define FIRST_PACKET 1 | 110 | DISCARD_PACKET, |
| 110 | #define INTER_PACKET 2 | 111 | FIRST_PACKET, |
| 111 | #define LAST_PACKET 3 | 112 | INTER_PACKET, |
| 113 | LAST_PACKET | ||
| 114 | }; | ||
| 112 | 115 | ||
| 113 | struct gspca_frame { | 116 | struct gspca_frame { |
| 114 | __u8 *data; /* frame buffer */ | 117 | __u8 *data; /* frame buffer */ |
| @@ -121,6 +124,7 @@ struct gspca_dev { | |||
| 121 | struct video_device vdev; /* !! must be the first item */ | 124 | struct video_device vdev; /* !! must be the first item */ |
| 122 | struct file_operations fops; | 125 | struct file_operations fops; |
| 123 | struct usb_device *dev; | 126 | struct usb_device *dev; |
| 127 | struct kref kref; | ||
| 124 | struct file *capt_file; /* file doing video capture */ | 128 | struct file *capt_file; /* file doing video capture */ |
| 125 | 129 | ||
| 126 | struct cam cam; /* device information */ | 130 | struct cam cam; /* device information */ |
| @@ -173,10 +177,11 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
| 173 | struct module *module); | 177 | struct module *module); |
| 174 | void gspca_disconnect(struct usb_interface *intf); | 178 | void gspca_disconnect(struct usb_interface *intf); |
| 175 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, | 179 | struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, |
| 176 | int packet_type, | 180 | enum gspca_packet_type packet_type, |
| 177 | struct gspca_frame *frame, | 181 | struct gspca_frame *frame, |
| 178 | const __u8 *data, | 182 | const __u8 *data, |
| 179 | int len); | 183 | int len); |
| 184 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev); | ||
| 180 | #ifdef CONFIG_PM | 185 | #ifdef CONFIG_PM |
| 181 | int gspca_suspend(struct usb_interface *intf, pm_message_t message); | 186 | int gspca_suspend(struct usb_interface *intf, pm_message_t message); |
| 182 | int gspca_resume(struct usb_interface *intf); | 187 | int gspca_resume(struct usb_interface *intf); |
diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/video/gspca/m5602/Kconfig new file mode 100644 index 000000000000..5a69016ed75f --- /dev/null +++ b/drivers/media/video/gspca/m5602/Kconfig | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | config USB_M5602 | ||
| 2 | tristate "ALi USB m5602 Camera Driver" | ||
| 3 | depends on VIDEO_V4L2 && USB_GSPCA | ||
| 4 | help | ||
| 5 | Say Y here if you want support for cameras based on the | ||
| 6 | ALi m5602 connected to various image sensors. | ||
| 7 | |||
| 8 | See <file:Documentation/video4linux/m5602.txt> for more info. | ||
| 9 | |||
| 10 | To compile this driver as a module, choose M here: the | ||
| 11 | module will be called gspca_m5602. | ||
diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile new file mode 100644 index 000000000000..226ab4fc9d60 --- /dev/null +++ b/drivers/media/video/gspca/m5602/Makefile | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | obj-$(CONFIG_USB_M5602) += gspca_m5602.o | ||
| 2 | |||
| 3 | gspca_m5602-objs := m5602_core.o \ | ||
| 4 | m5602_ov9650.o \ | ||
| 5 | m5602_mt9m111.o \ | ||
| 6 | m5602_po1030.o \ | ||
| 7 | m5602_s5k83a.o \ | ||
| 8 | m5602_s5k4aa.o | ||
| 9 | |||
| 10 | EXTRA_CFLAGS += -Idrivers/media/video/gspca | ||
| 11 | |||
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h new file mode 100644 index 000000000000..c786d7d3d44a --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_bridge.h | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | /* | ||
| 2 | * USB Driver for ALi m5602 based webcams | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef M5602_BRIDGE_H_ | ||
| 20 | #define M5602_BRIDGE_H_ | ||
| 21 | |||
| 22 | #include "gspca.h" | ||
| 23 | |||
| 24 | #define MODULE_NAME "ALi m5602" | ||
| 25 | |||
| 26 | /*****************************************************************************/ | ||
| 27 | |||
| 28 | #undef PDEBUG | ||
| 29 | #undef info | ||
| 30 | #undef err | ||
| 31 | |||
| 32 | #define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \ | ||
| 33 | format "\n" , ## arg) | ||
| 34 | #define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \ | ||
| 35 | format "\n" , ## arg) | ||
| 36 | |||
| 37 | /* Debug parameters */ | ||
| 38 | #define DBG_INIT 0x1 | ||
| 39 | #define DBG_PROBE 0x2 | ||
| 40 | #define DBG_V4L2 0x4 | ||
| 41 | #define DBG_TRACE 0x8 | ||
| 42 | #define DBG_DATA 0x10 | ||
| 43 | #define DBG_V4L2_CID 0x20 | ||
| 44 | #define DBG_GSPCA 0x40 | ||
| 45 | |||
| 46 | #define PDEBUG(level, fmt, args...) \ | ||
| 47 | do { \ | ||
| 48 | if (m5602_debug & level) \ | ||
| 49 | info("[%s:%d] " fmt, __func__, __LINE__ , \ | ||
| 50 | ## args); \ | ||
| 51 | } while (0) | ||
| 52 | |||
| 53 | /*****************************************************************************/ | ||
| 54 | |||
| 55 | #define M5602_XB_SENSOR_TYPE 0x00 | ||
| 56 | #define M5602_XB_SENSOR_CTRL 0x01 | ||
| 57 | #define M5602_XB_LINE_OF_FRAME_H 0x02 | ||
| 58 | #define M5602_XB_LINE_OF_FRAME_L 0x03 | ||
| 59 | #define M5602_XB_PIX_OF_LINE_H 0x04 | ||
| 60 | #define M5602_XB_PIX_OF_LINE_L 0x05 | ||
| 61 | #define M5602_XB_VSYNC_PARA 0x06 | ||
| 62 | #define M5602_XB_HSYNC_PARA 0x07 | ||
| 63 | #define M5602_XB_TEST_MODE_1 0x08 | ||
| 64 | #define M5602_XB_TEST_MODE_2 0x09 | ||
| 65 | #define M5602_XB_SIG_INI 0x0a | ||
| 66 | #define M5602_XB_DS_PARA 0x0e | ||
| 67 | #define M5602_XB_TRIG_PARA 0x0f | ||
| 68 | #define M5602_XB_CLK_PD 0x10 | ||
| 69 | #define M5602_XB_MCU_CLK_CTRL 0x12 | ||
| 70 | #define M5602_XB_MCU_CLK_DIV 0x13 | ||
| 71 | #define M5602_XB_SEN_CLK_CTRL 0x14 | ||
| 72 | #define M5602_XB_SEN_CLK_DIV 0x15 | ||
| 73 | #define M5602_XB_AUD_CLK_CTRL 0x16 | ||
| 74 | #define M5602_XB_AUD_CLK_DIV 0x17 | ||
| 75 | #define M5602_XB_DEVCTR1 0x41 | ||
| 76 | #define M5602_XB_EPSETR0 0x42 | ||
| 77 | #define M5602_XB_EPAFCTR 0x47 | ||
| 78 | #define M5602_XB_EPBFCTR 0x49 | ||
| 79 | #define M5602_XB_EPEFCTR 0x4f | ||
| 80 | #define M5602_XB_TEST_REG 0x53 | ||
| 81 | #define M5602_XB_ALT2SIZE 0x54 | ||
| 82 | #define M5602_XB_ALT3SIZE 0x55 | ||
| 83 | #define M5602_XB_OBSFRAME 0x56 | ||
| 84 | #define M5602_XB_PWR_CTL 0x59 | ||
| 85 | #define M5602_XB_ADC_CTRL 0x60 | ||
| 86 | #define M5602_XB_ADC_DATA 0x61 | ||
| 87 | #define M5602_XB_MISC_CTRL 0x62 | ||
| 88 | #define M5602_XB_SNAPSHOT 0x63 | ||
| 89 | #define M5602_XB_SCRATCH_1 0x64 | ||
| 90 | #define M5602_XB_SCRATCH_2 0x65 | ||
| 91 | #define M5602_XB_SCRATCH_3 0x66 | ||
| 92 | #define M5602_XB_SCRATCH_4 0x67 | ||
| 93 | #define M5602_XB_I2C_CTRL 0x68 | ||
| 94 | #define M5602_XB_I2C_CLK_DIV 0x69 | ||
| 95 | #define M5602_XB_I2C_DEV_ADDR 0x6a | ||
| 96 | #define M5602_XB_I2C_REG_ADDR 0x6b | ||
| 97 | #define M5602_XB_I2C_DATA 0x6c | ||
| 98 | #define M5602_XB_I2C_STATUS 0x6d | ||
| 99 | #define M5602_XB_GPIO_DAT_H 0x70 | ||
| 100 | #define M5602_XB_GPIO_DAT_L 0x71 | ||
| 101 | #define M5602_XB_GPIO_DIR_H 0x72 | ||
| 102 | #define M5602_XB_GPIO_DIR_L 0x73 | ||
| 103 | #define M5602_XB_GPIO_EN_H 0x74 | ||
| 104 | #define M5602_XB_GPIO_EN_L 0x75 | ||
| 105 | #define M5602_XB_GPIO_DAT 0x76 | ||
| 106 | #define M5602_XB_GPIO_DIR 0x77 | ||
| 107 | #define M5602_XB_MISC_CTL 0x70 | ||
| 108 | |||
| 109 | #define I2C_BUSY 0x80 | ||
| 110 | |||
| 111 | /*****************************************************************************/ | ||
| 112 | |||
| 113 | /* Driver info */ | ||
| 114 | #define DRIVER_AUTHOR "ALi m5602 Linux Driver Project" | ||
| 115 | #define DRIVER_DESC "ALi m5602 webcam driver" | ||
| 116 | |||
| 117 | #define M5602_ISOC_ENDPOINT_ADDR 0x81 | ||
| 118 | #define M5602_INTR_ENDPOINT_ADDR 0x82 | ||
| 119 | |||
| 120 | #define M5602_MAX_FRAMES 32 | ||
| 121 | #define M5602_URBS 2 | ||
| 122 | #define M5602_ISOC_PACKETS 14 | ||
| 123 | |||
| 124 | #define M5602_URB_TIMEOUT msecs_to_jiffies(2 * M5602_ISOC_PACKETS) | ||
| 125 | #define M5602_URB_MSG_TIMEOUT 5000 | ||
| 126 | #define M5602_FRAME_TIMEOUT 2 | ||
| 127 | |||
| 128 | /*****************************************************************************/ | ||
| 129 | |||
| 130 | /* A skeleton used for sending messages to the m5602 bridge */ | ||
| 131 | static const unsigned char bridge_urb_skeleton[] = { | ||
| 132 | 0x13, 0x00, 0x81, 0x00 | ||
| 133 | }; | ||
| 134 | |||
| 135 | /* A skeleton used for sending messages to the sensor */ | ||
| 136 | static const unsigned char sensor_urb_skeleton[] = { | ||
| 137 | 0x23, M5602_XB_GPIO_EN_H, 0x81, 0x06, | ||
| 138 | 0x23, M5602_XB_MISC_CTRL, 0x81, 0x80, | ||
| 139 | 0x13, M5602_XB_I2C_DEV_ADDR, 0x81, 0x00, | ||
| 140 | 0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00, | ||
| 141 | 0x13, M5602_XB_I2C_DATA, 0x81, 0x00, | ||
| 142 | 0x13, M5602_XB_I2C_CTRL, 0x81, 0x11 | ||
| 143 | }; | ||
| 144 | |||
| 145 | /* m5602 device descriptor, currently it just wraps the m5602_camera struct */ | ||
| 146 | struct sd { | ||
| 147 | struct gspca_dev gspca_dev; | ||
| 148 | |||
| 149 | /* The name of the m5602 camera */ | ||
| 150 | char *name; | ||
| 151 | |||
| 152 | /* A pointer to the currently connected sensor */ | ||
| 153 | struct m5602_sensor *sensor; | ||
| 154 | |||
| 155 | struct sd_desc *desc; | ||
| 156 | |||
| 157 | /* The current frame's id, used to detect frame boundaries */ | ||
| 158 | u8 frame_id; | ||
| 159 | |||
| 160 | /* The current frame count */ | ||
| 161 | u32 frame_count; | ||
| 162 | }; | ||
| 163 | |||
| 164 | int m5602_read_bridge( | ||
| 165 | struct sd *sd, u8 address, u8 *i2c_data); | ||
| 166 | |||
| 167 | int m5602_write_bridge( | ||
| 168 | struct sd *sd, u8 address, u8 i2c_data); | ||
| 169 | |||
| 170 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c new file mode 100644 index 000000000000..19d5e351ccc1 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_core.c | |||
| @@ -0,0 +1,313 @@ | |||
| 1 | /* | ||
| 2 | * USB Driver for ALi m5602 based webcams | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include "m5602_ov9650.h" | ||
| 20 | #include "m5602_mt9m111.h" | ||
| 21 | #include "m5602_po1030.h" | ||
| 22 | #include "m5602_s5k83a.h" | ||
| 23 | #include "m5602_s5k4aa.h" | ||
| 24 | |||
| 25 | /* Kernel module parameters */ | ||
| 26 | int force_sensor; | ||
| 27 | int dump_bridge; | ||
| 28 | int dump_sensor; | ||
| 29 | unsigned int m5602_debug; | ||
| 30 | |||
| 31 | static const __devinitdata struct usb_device_id m5602_table[] = { | ||
| 32 | {USB_DEVICE(0x0402, 0x5602)}, | ||
| 33 | {} | ||
| 34 | }; | ||
| 35 | |||
| 36 | MODULE_DEVICE_TABLE(usb, m5602_table); | ||
| 37 | |||
| 38 | /* Reads a byte from the m5602 */ | ||
| 39 | int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) | ||
| 40 | { | ||
| 41 | int err; | ||
| 42 | struct usb_device *udev = sd->gspca_dev.dev; | ||
| 43 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
| 44 | |||
| 45 | err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 46 | 0x04, 0xc0, 0x14, | ||
| 47 | 0x8100 + address, buf, | ||
| 48 | 1, M5602_URB_MSG_TIMEOUT); | ||
| 49 | *i2c_data = buf[0]; | ||
| 50 | |||
| 51 | PDEBUG(DBG_TRACE, "Reading bridge register 0x%x containing 0x%x", | ||
| 52 | address, *i2c_data); | ||
| 53 | |||
| 54 | /* usb_control_msg(...) returns the number of bytes sent upon success, | ||
| 55 | mask that and return zero upon success instead*/ | ||
| 56 | return (err < 0) ? err : 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | /* Writes a byte to to the m5602 */ | ||
| 60 | int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) | ||
| 61 | { | ||
| 62 | int err; | ||
| 63 | struct usb_device *udev = sd->gspca_dev.dev; | ||
| 64 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
| 65 | |||
| 66 | PDEBUG(DBG_TRACE, "Writing bridge register 0x%x with 0x%x", | ||
| 67 | address, i2c_data); | ||
| 68 | |||
| 69 | memcpy(buf, bridge_urb_skeleton, | ||
| 70 | sizeof(bridge_urb_skeleton)); | ||
| 71 | buf[1] = address; | ||
| 72 | buf[3] = i2c_data; | ||
| 73 | |||
| 74 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 75 | 0x04, 0x40, 0x19, | ||
| 76 | 0x0000, buf, | ||
| 77 | 4, M5602_URB_MSG_TIMEOUT); | ||
| 78 | |||
| 79 | /* usb_control_msg(...) returns the number of bytes sent upon success, | ||
| 80 | mask that and return zero upon success instead */ | ||
| 81 | return (err < 0) ? err : 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | /* Dump all the registers of the m5602 bridge, | ||
| 85 | unfortunately this breaks the camera until it's power cycled */ | ||
| 86 | static void m5602_dump_bridge(struct sd *sd) | ||
| 87 | { | ||
| 88 | int i; | ||
| 89 | for (i = 0; i < 0x80; i++) { | ||
| 90 | unsigned char val = 0; | ||
| 91 | m5602_read_bridge(sd, i, &val); | ||
| 92 | info("ALi m5602 address 0x%x contains 0x%x", i, val); | ||
| 93 | } | ||
| 94 | info("Warning: The camera probably won't work until it's power cycled"); | ||
| 95 | } | ||
| 96 | |||
| 97 | static int m5602_probe_sensor(struct sd *sd) | ||
| 98 | { | ||
| 99 | /* Try the po1030 */ | ||
| 100 | sd->sensor = &po1030; | ||
| 101 | if (!sd->sensor->probe(sd)) | ||
| 102 | return 0; | ||
| 103 | |||
| 104 | /* Try the mt9m111 sensor */ | ||
| 105 | sd->sensor = &mt9m111; | ||
| 106 | if (!sd->sensor->probe(sd)) | ||
| 107 | return 0; | ||
| 108 | |||
| 109 | /* Try the s5k4aa */ | ||
| 110 | sd->sensor = &s5k4aa; | ||
| 111 | if (!sd->sensor->probe(sd)) | ||
| 112 | return 0; | ||
| 113 | |||
| 114 | /* Try the ov9650 */ | ||
| 115 | sd->sensor = &ov9650; | ||
| 116 | if (!sd->sensor->probe(sd)) | ||
| 117 | return 0; | ||
| 118 | |||
| 119 | /* Try the s5k83a */ | ||
| 120 | sd->sensor = &s5k83a; | ||
| 121 | if (!sd->sensor->probe(sd)) | ||
| 122 | return 0; | ||
| 123 | |||
| 124 | /* More sensor probe function goes here */ | ||
| 125 | info("Failed to find a sensor"); | ||
| 126 | sd->sensor = NULL; | ||
| 127 | return -ENODEV; | ||
| 128 | } | ||
| 129 | |||
| 130 | static int m5602_configure(struct gspca_dev *gspca_dev, | ||
| 131 | const struct usb_device_id *id); | ||
| 132 | |||
| 133 | static int m5602_init(struct gspca_dev *gspca_dev) | ||
| 134 | { | ||
| 135 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 136 | int err; | ||
| 137 | |||
| 138 | PDEBUG(DBG_TRACE, "Initializing ALi m5602 webcam"); | ||
| 139 | /* Run the init sequence */ | ||
| 140 | err = sd->sensor->init(sd); | ||
| 141 | |||
| 142 | return err; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int m5602_start_transfer(struct gspca_dev *gspca_dev) | ||
| 146 | { | ||
| 147 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 148 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
| 149 | |||
| 150 | /* Send start command to the camera */ | ||
| 151 | const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01}; | ||
| 152 | memcpy(buf, buffer, sizeof(buffer)); | ||
| 153 | usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), | ||
| 154 | 0x04, 0x40, 0x19, 0x0000, buf, | ||
| 155 | 4, M5602_URB_MSG_TIMEOUT); | ||
| 156 | |||
| 157 | PDEBUG(DBG_V4L2, "Transfer started"); | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | static void m5602_urb_complete(struct gspca_dev *gspca_dev, | ||
| 162 | struct gspca_frame *frame, | ||
| 163 | __u8 *data, int len) | ||
| 164 | { | ||
| 165 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 166 | |||
| 167 | if (len < 6) { | ||
| 168 | PDEBUG(DBG_DATA, "Packet is less than 6 bytes"); | ||
| 169 | return; | ||
| 170 | } | ||
| 171 | |||
| 172 | /* Frame delimiter: ff xx xx xx ff ff */ | ||
| 173 | if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff && | ||
| 174 | data[2] != sd->frame_id) { | ||
| 175 | PDEBUG(DBG_DATA, "Frame delimiter detected"); | ||
| 176 | sd->frame_id = data[2]; | ||
| 177 | |||
| 178 | /* Remove the extra fluff appended on each header */ | ||
| 179 | data += 6; | ||
| 180 | len -= 6; | ||
| 181 | |||
| 182 | /* Complete the last frame (if any) */ | ||
| 183 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, | ||
| 184 | frame, data, 0); | ||
| 185 | sd->frame_count++; | ||
| 186 | |||
| 187 | /* Create a new frame */ | ||
| 188 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); | ||
| 189 | |||
| 190 | PDEBUG(DBG_V4L2, "Starting new frame %d", | ||
| 191 | sd->frame_count); | ||
| 192 | |||
| 193 | } else { | ||
| 194 | int cur_frame_len = frame->data_end - frame->data; | ||
| 195 | |||
| 196 | /* Remove urb header */ | ||
| 197 | data += 4; | ||
| 198 | len -= 4; | ||
| 199 | |||
| 200 | if (cur_frame_len + len <= frame->v4l2_buf.length) { | ||
| 201 | PDEBUG(DBG_DATA, "Continuing frame %d copying %d bytes", | ||
| 202 | sd->frame_count, len); | ||
| 203 | |||
| 204 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
| 205 | data, len); | ||
| 206 | } else if (frame->v4l2_buf.length - cur_frame_len > 0) { | ||
| 207 | /* Add the remaining data up to frame size */ | ||
| 208 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, | ||
| 209 | frame->v4l2_buf.length - cur_frame_len); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | static void m5602_stop_transfer(struct gspca_dev *gspca_dev) | ||
| 215 | { | ||
| 216 | /* Is there are a command to stop a data transfer? */ | ||
| 217 | } | ||
| 218 | |||
| 219 | /* sub-driver description, the ctrl and nctrl is filled at probe time */ | ||
| 220 | static struct sd_desc sd_desc = { | ||
| 221 | .name = MODULE_NAME, | ||
| 222 | .config = m5602_configure, | ||
| 223 | .init = m5602_init, | ||
| 224 | .start = m5602_start_transfer, | ||
| 225 | .stopN = m5602_stop_transfer, | ||
| 226 | .pkt_scan = m5602_urb_complete | ||
| 227 | }; | ||
| 228 | |||
| 229 | /* this function is called at probe time */ | ||
| 230 | static int m5602_configure(struct gspca_dev *gspca_dev, | ||
| 231 | const struct usb_device_id *id) | ||
| 232 | { | ||
| 233 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 234 | struct cam *cam; | ||
| 235 | int err; | ||
| 236 | |||
| 237 | PDEBUG(DBG_GSPCA, "m5602_configure start"); | ||
| 238 | |||
| 239 | cam = &gspca_dev->cam; | ||
| 240 | cam->epaddr = M5602_ISOC_ENDPOINT_ADDR; | ||
| 241 | sd->desc = &sd_desc; | ||
| 242 | |||
| 243 | if (dump_bridge) | ||
| 244 | m5602_dump_bridge(sd); | ||
| 245 | |||
| 246 | /* Probe sensor */ | ||
| 247 | err = m5602_probe_sensor(sd); | ||
| 248 | if (err) | ||
| 249 | goto fail; | ||
| 250 | |||
| 251 | PDEBUG(DBG_GSPCA, "m5602_configure end"); | ||
| 252 | return 0; | ||
| 253 | |||
| 254 | fail: | ||
| 255 | PDEBUG(DBG_GSPCA, "m5602_configure failed"); | ||
| 256 | cam->cam_mode = NULL; | ||
| 257 | cam->nmodes = 0; | ||
| 258 | |||
| 259 | return err; | ||
| 260 | } | ||
| 261 | |||
| 262 | static int m5602_probe(struct usb_interface *intf, | ||
| 263 | const struct usb_device_id *id) | ||
| 264 | { | ||
| 265 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
| 266 | THIS_MODULE); | ||
| 267 | } | ||
| 268 | |||
| 269 | static struct usb_driver sd_driver = { | ||
| 270 | .name = MODULE_NAME, | ||
| 271 | .id_table = m5602_table, | ||
| 272 | .probe = m5602_probe, | ||
| 273 | #ifdef CONFIG_PM | ||
| 274 | .suspend = gspca_suspend, | ||
| 275 | .resume = gspca_resume, | ||
| 276 | #endif | ||
| 277 | .disconnect = gspca_disconnect | ||
| 278 | }; | ||
| 279 | |||
| 280 | /* -- module insert / remove -- */ | ||
| 281 | static int __init mod_m5602_init(void) | ||
| 282 | { | ||
| 283 | if (usb_register(&sd_driver) < 0) | ||
| 284 | return -1; | ||
| 285 | PDEBUG(D_PROBE, "m5602 module registered"); | ||
| 286 | return 0; | ||
| 287 | } | ||
| 288 | static void __exit mod_m5602_exit(void) | ||
| 289 | { | ||
| 290 | usb_deregister(&sd_driver); | ||
| 291 | PDEBUG(D_PROBE, "m5602 module deregistered"); | ||
| 292 | } | ||
| 293 | |||
| 294 | module_init(mod_m5602_init); | ||
| 295 | module_exit(mod_m5602_exit); | ||
| 296 | |||
| 297 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 298 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 299 | MODULE_LICENSE("GPL"); | ||
| 300 | module_param_named(debug, m5602_debug, int, S_IRUGO | S_IWUSR); | ||
| 301 | MODULE_PARM_DESC(debug, "toggles debug on/off"); | ||
| 302 | |||
| 303 | module_param(force_sensor, int, S_IRUGO | S_IWUSR); | ||
| 304 | MODULE_PARM_DESC(force_sensor, | ||
| 305 | "force detection of sensor, " | ||
| 306 | "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030"); | ||
| 307 | |||
| 308 | module_param(dump_bridge, bool, S_IRUGO | S_IWUSR); | ||
| 309 | MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup"); | ||
| 310 | |||
| 311 | module_param(dump_sensor, bool, S_IRUGO | S_IWUSR); | ||
| 312 | MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers " | ||
| 313 | "at startup providing a sensor is found"); | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c new file mode 100644 index 000000000000..566d4925a0e8 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c | |||
| @@ -0,0 +1,345 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the mt9m111 sensor | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include "m5602_mt9m111.h" | ||
| 20 | |||
| 21 | int mt9m111_probe(struct sd *sd) | ||
| 22 | { | ||
| 23 | u8 data[2] = {0x00, 0x00}; | ||
| 24 | int i; | ||
| 25 | |||
| 26 | if (force_sensor) { | ||
| 27 | if (force_sensor == MT9M111_SENSOR) { | ||
| 28 | info("Forcing a %s sensor", mt9m111.name); | ||
| 29 | goto sensor_found; | ||
| 30 | } | ||
| 31 | /* If we want to force another sensor, don't try to probe this | ||
| 32 | * one */ | ||
| 33 | return -ENODEV; | ||
| 34 | } | ||
| 35 | |||
| 36 | info("Probing for a mt9m111 sensor"); | ||
| 37 | |||
| 38 | /* Do the preinit */ | ||
| 39 | for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) { | ||
| 40 | if (preinit_mt9m111[i][0] == BRIDGE) { | ||
| 41 | m5602_write_bridge(sd, | ||
| 42 | preinit_mt9m111[i][1], | ||
| 43 | preinit_mt9m111[i][2]); | ||
| 44 | } else { | ||
| 45 | data[0] = preinit_mt9m111[i][2]; | ||
| 46 | data[1] = preinit_mt9m111[i][3]; | ||
| 47 | mt9m111_write_sensor(sd, | ||
| 48 | preinit_mt9m111[i][1], data, 2); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | if (mt9m111_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2)) | ||
| 53 | return -ENODEV; | ||
| 54 | |||
| 55 | if ((data[0] == 0x14) && (data[1] == 0x3a)) { | ||
| 56 | info("Detected a mt9m111 sensor"); | ||
| 57 | goto sensor_found; | ||
| 58 | } | ||
| 59 | |||
| 60 | return -ENODEV; | ||
| 61 | |||
| 62 | sensor_found: | ||
| 63 | sd->gspca_dev.cam.cam_mode = mt9m111.modes; | ||
| 64 | sd->gspca_dev.cam.nmodes = mt9m111.nmodes; | ||
| 65 | sd->desc->ctrls = mt9m111.ctrls; | ||
| 66 | sd->desc->nctrls = mt9m111.nctrls; | ||
| 67 | return 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | int mt9m111_init(struct sd *sd) | ||
| 71 | { | ||
| 72 | int i, err = 0; | ||
| 73 | |||
| 74 | /* Init the sensor */ | ||
| 75 | for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) { | ||
| 76 | u8 data[2]; | ||
| 77 | |||
| 78 | if (init_mt9m111[i][0] == BRIDGE) { | ||
| 79 | err = m5602_write_bridge(sd, | ||
| 80 | init_mt9m111[i][1], | ||
| 81 | init_mt9m111[i][2]); | ||
| 82 | } else { | ||
| 83 | data[0] = init_mt9m111[i][2]; | ||
| 84 | data[1] = init_mt9m111[i][3]; | ||
| 85 | err = mt9m111_write_sensor(sd, | ||
| 86 | init_mt9m111[i][1], data, 2); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | if (dump_sensor) | ||
| 91 | mt9m111_dump_registers(sd); | ||
| 92 | |||
| 93 | return (err < 0) ? err : 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | int mt9m111_power_down(struct sd *sd) | ||
| 97 | { | ||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 102 | { | ||
| 103 | int err; | ||
| 104 | u8 data[2] = {0x00, 0x00}; | ||
| 105 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 106 | |||
| 107 | err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, | ||
| 108 | data, 2); | ||
| 109 | *val = data[0] & MT9M111_RMB_MIRROR_ROWS; | ||
| 110 | PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); | ||
| 111 | |||
| 112 | return (err < 0) ? err : 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | ||
| 116 | { | ||
| 117 | int err; | ||
| 118 | u8 data[2] = {0x00, 0x00}; | ||
| 119 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 120 | |||
| 121 | PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); | ||
| 122 | |||
| 123 | /* Set the correct page map */ | ||
| 124 | err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); | ||
| 125 | if (err < 0) | ||
| 126 | goto out; | ||
| 127 | |||
| 128 | err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); | ||
| 129 | if (err < 0) | ||
| 130 | goto out; | ||
| 131 | |||
| 132 | data[0] = (data[0] & 0xfe) | val; | ||
| 133 | err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, | ||
| 134 | data, 2); | ||
| 135 | out: | ||
| 136 | return (err < 0) ? err : 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 140 | { | ||
| 141 | int err; | ||
| 142 | u8 data[2] = {0x00, 0x00}; | ||
| 143 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 144 | |||
| 145 | err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, | ||
| 146 | data, 2); | ||
| 147 | *val = data[0] & MT9M111_RMB_MIRROR_COLS; | ||
| 148 | PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); | ||
| 149 | |||
| 150 | return (err < 0) ? err : 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | ||
| 154 | { | ||
| 155 | int err; | ||
| 156 | u8 data[2] = {0x00, 0x00}; | ||
| 157 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 158 | |||
| 159 | PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val); | ||
| 160 | |||
| 161 | /* Set the correct page map */ | ||
| 162 | err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); | ||
| 163 | if (err < 0) | ||
| 164 | goto out; | ||
| 165 | |||
| 166 | err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); | ||
| 167 | if (err < 0) | ||
| 168 | goto out; | ||
| 169 | |||
| 170 | data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02); | ||
| 171 | err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, | ||
| 172 | data, 2); | ||
| 173 | out: | ||
| 174 | return (err < 0) ? err : 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 178 | { | ||
| 179 | int err, tmp; | ||
| 180 | u8 data[2] = {0x00, 0x00}; | ||
| 181 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 182 | |||
| 183 | err = mt9m111_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2); | ||
| 184 | tmp = ((data[1] << 8) | data[0]); | ||
| 185 | |||
| 186 | *val = ((tmp & (1 << 10)) * 2) | | ||
| 187 | ((tmp & (1 << 9)) * 2) | | ||
| 188 | ((tmp & (1 << 8)) * 2) | | ||
| 189 | (tmp & 0x7f); | ||
| 190 | |||
| 191 | PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); | ||
| 192 | |||
| 193 | return (err < 0) ? err : 0; | ||
| 194 | } | ||
| 195 | |||
| 196 | int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
| 197 | { | ||
| 198 | int err, tmp; | ||
| 199 | u8 data[2] = {0x00, 0x00}; | ||
| 200 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 201 | |||
| 202 | /* Set the correct page map */ | ||
| 203 | err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); | ||
| 204 | if (err < 0) | ||
| 205 | goto out; | ||
| 206 | |||
| 207 | if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2) | ||
| 208 | return -EINVAL; | ||
| 209 | |||
| 210 | if ((val >= INITIAL_MAX_GAIN * 2 * 2) && | ||
| 211 | (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2)) | ||
| 212 | tmp = (1 << 10) | (val << 9) | | ||
| 213 | (val << 8) | (val / 8); | ||
| 214 | else if ((val >= INITIAL_MAX_GAIN * 2) && | ||
| 215 | (val < INITIAL_MAX_GAIN * 2 * 2)) | ||
| 216 | tmp = (1 << 9) | (1 << 8) | (val / 4); | ||
| 217 | else if ((val >= INITIAL_MAX_GAIN) && | ||
| 218 | (val < INITIAL_MAX_GAIN * 2)) | ||
| 219 | tmp = (1 << 8) | (val / 2); | ||
| 220 | else | ||
| 221 | tmp = val; | ||
| 222 | |||
| 223 | data[1] = (tmp & 0xff00) >> 8; | ||
| 224 | data[0] = (tmp & 0xff); | ||
| 225 | PDEBUG(DBG_V4L2_CID, "tmp=%d, data[1]=%d, data[0]=%d", tmp, | ||
| 226 | data[1], data[0]); | ||
| 227 | |||
| 228 | err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, | ||
| 229 | data, 2); | ||
| 230 | out: | ||
| 231 | return (err < 0) ? err : 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | int mt9m111_read_sensor(struct sd *sd, const u8 address, | ||
| 235 | u8 *i2c_data, const u8 len) { | ||
| 236 | int err, i; | ||
| 237 | |||
| 238 | do { | ||
| 239 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
| 240 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
| 241 | if (err < 0) | ||
| 242 | goto out; | ||
| 243 | |||
| 244 | err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, | ||
| 245 | sd->sensor->i2c_slave_id); | ||
| 246 | if (err < 0) | ||
| 247 | goto out; | ||
| 248 | |||
| 249 | err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); | ||
| 250 | if (err < 0) | ||
| 251 | goto out; | ||
| 252 | |||
| 253 | err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x1a); | ||
| 254 | if (err < 0) | ||
| 255 | goto out; | ||
| 256 | |||
| 257 | for (i = 0; i < len && !err; i++) { | ||
| 258 | err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); | ||
| 259 | |||
| 260 | PDEBUG(DBG_TRACE, "Reading sensor register " | ||
| 261 | "0x%x contains 0x%x ", address, *i2c_data); | ||
| 262 | } | ||
| 263 | out: | ||
| 264 | return (err < 0) ? err : 0; | ||
| 265 | } | ||
| 266 | |||
| 267 | int mt9m111_write_sensor(struct sd *sd, const u8 address, | ||
| 268 | u8 *i2c_data, const u8 len) | ||
| 269 | { | ||
| 270 | int err, i; | ||
| 271 | u8 *p; | ||
| 272 | struct usb_device *udev = sd->gspca_dev.dev; | ||
| 273 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
| 274 | |||
| 275 | /* No sensor with a data width larger | ||
| 276 | than 16 bits has yet been seen, nor with 0 :p*/ | ||
| 277 | if (len > 2 || !len) | ||
| 278 | return -EINVAL; | ||
| 279 | |||
| 280 | memcpy(buf, sensor_urb_skeleton, | ||
| 281 | sizeof(sensor_urb_skeleton)); | ||
| 282 | |||
| 283 | buf[11] = sd->sensor->i2c_slave_id; | ||
| 284 | buf[15] = address; | ||
| 285 | |||
| 286 | p = buf + 16; | ||
| 287 | |||
| 288 | /* Copy a four byte write sequence for each byte to be written to */ | ||
| 289 | for (i = 0; i < len; i++) { | ||
| 290 | memcpy(p, sensor_urb_skeleton + 16, 4); | ||
| 291 | p[3] = i2c_data[i]; | ||
| 292 | p += 4; | ||
| 293 | PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", | ||
| 294 | address, i2c_data[i]); | ||
| 295 | } | ||
| 296 | |||
| 297 | /* Copy the tailer */ | ||
| 298 | memcpy(p, sensor_urb_skeleton + 20, 4); | ||
| 299 | |||
| 300 | /* Set the total length */ | ||
| 301 | p[3] = 0x10 + len; | ||
| 302 | |||
| 303 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 304 | 0x04, 0x40, 0x19, | ||
| 305 | 0x0000, buf, | ||
| 306 | 20 + len * 4, M5602_URB_MSG_TIMEOUT); | ||
| 307 | |||
| 308 | return (err < 0) ? err : 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | void mt9m111_dump_registers(struct sd *sd) | ||
| 312 | { | ||
| 313 | u8 address, value[2] = {0x00, 0x00}; | ||
| 314 | |||
| 315 | info("Dumping the mt9m111 register state"); | ||
| 316 | |||
| 317 | info("Dumping the mt9m111 sensor core registers"); | ||
| 318 | value[1] = MT9M111_SENSOR_CORE; | ||
| 319 | mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); | ||
| 320 | for (address = 0; address < 0xff; address++) { | ||
| 321 | mt9m111_read_sensor(sd, address, value, 2); | ||
| 322 | info("register 0x%x contains 0x%x%x", | ||
| 323 | address, value[0], value[1]); | ||
| 324 | } | ||
| 325 | |||
| 326 | info("Dumping the mt9m111 color pipeline registers"); | ||
| 327 | value[1] = MT9M111_COLORPIPE; | ||
| 328 | mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); | ||
| 329 | for (address = 0; address < 0xff; address++) { | ||
| 330 | mt9m111_read_sensor(sd, address, value, 2); | ||
| 331 | info("register 0x%x contains 0x%x%x", | ||
| 332 | address, value[0], value[1]); | ||
| 333 | } | ||
| 334 | |||
| 335 | info("Dumping the mt9m111 camera control registers"); | ||
| 336 | value[1] = MT9M111_CAMERA_CONTROL; | ||
| 337 | mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2); | ||
| 338 | for (address = 0; address < 0xff; address++) { | ||
| 339 | mt9m111_read_sensor(sd, address, value, 2); | ||
| 340 | info("register 0x%x contains 0x%x%x", | ||
| 341 | address, value[0], value[1]); | ||
| 342 | } | ||
| 343 | |||
| 344 | info("mt9m111 register state dump complete"); | ||
| 345 | } | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h new file mode 100644 index 000000000000..79a5d8878190 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.h | |||
| @@ -0,0 +1,1020 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the mt9m111 sensor | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * Some defines taken from the mt9m111 sensor driver | ||
| 14 | * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr> | ||
| 15 | * | ||
| 16 | * This program is free software; you can redistribute it and/or | ||
| 17 | * modify it under the terms of the GNU General Public License as | ||
| 18 | * published by the Free Software Foundation, version 2. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef M5602_MT9M111_H_ | ||
| 23 | #define M5602_MT9M111_H_ | ||
| 24 | |||
| 25 | #include "m5602_sensor.h" | ||
| 26 | |||
| 27 | /*****************************************************************************/ | ||
| 28 | |||
| 29 | #define MT9M111_SC_CHIPVER 0x00 | ||
| 30 | #define MT9M111_SC_ROWSTART 0x01 | ||
| 31 | #define MT9M111_SC_COLSTART 0x02 | ||
| 32 | #define MT9M111_SC_WINDOW_HEIGHT 0x03 | ||
| 33 | #define MT9M111_SC_WINDOW_WIDTH 0x04 | ||
| 34 | #define MT9M111_SC_HBLANK_CONTEXT_B 0x05 | ||
| 35 | #define MT9M111_SC_VBLANK_CONTEXT_B 0x06 | ||
| 36 | #define MT9M111_SC_HBLANK_CONTEXT_A 0x07 | ||
| 37 | #define MT9M111_SC_VBLANK_CONTEXT_A 0x08 | ||
| 38 | #define MT9M111_SC_SHUTTER_WIDTH 0x09 | ||
| 39 | #define MT9M111_SC_ROW_SPEED 0x0a | ||
| 40 | |||
| 41 | #define MT9M111_SC_EXTRA_DELAY 0x0b | ||
| 42 | #define MT9M111_SC_SHUTTER_DELAY 0x0c | ||
| 43 | #define MT9M111_SC_RESET 0x0d | ||
| 44 | #define MT9M111_SC_R_MODE_CONTEXT_B 0x20 | ||
| 45 | #define MT9M111_SC_R_MODE_CONTEXT_A 0x21 | ||
| 46 | #define MT9M111_SC_FLASH_CONTROL 0x23 | ||
| 47 | #define MT9M111_SC_GREEN_1_GAIN 0x2b | ||
| 48 | #define MT9M111_SC_BLUE_GAIN 0x2c | ||
| 49 | #define MT9M111_SC_RED_GAIN 0x2d | ||
| 50 | #define MT9M111_SC_GREEN_2_GAIN 0x2e | ||
| 51 | #define MT9M111_SC_GLOBAL_GAIN 0x2f | ||
| 52 | |||
| 53 | #define MT9M111_RMB_MIRROR_ROWS (1 << 0) | ||
| 54 | #define MT9M111_RMB_MIRROR_COLS (1 << 1) | ||
| 55 | |||
| 56 | #define MT9M111_CONTEXT_CONTROL 0xc8 | ||
| 57 | #define MT9M111_PAGE_MAP 0xf0 | ||
| 58 | #define MT9M111_BYTEWISE_ADDRESS 0xf1 | ||
| 59 | |||
| 60 | #define MT9M111_CP_OPERATING_MODE_CTL 0x06 | ||
| 61 | #define MT9M111_CP_LUMA_OFFSET 0x34 | ||
| 62 | #define MT9M111_CP_LUMA_CLIP 0x35 | ||
| 63 | #define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A 0x3a | ||
| 64 | #define MT9M111_CP_LENS_CORRECTION_1 0x3b | ||
| 65 | #define MT9M111_CP_DEFECT_CORR_CONTEXT_A 0x4c | ||
| 66 | #define MT9M111_CP_DEFECT_CORR_CONTEXT_B 0x4d | ||
| 67 | #define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B 0x9b | ||
| 68 | #define MT9M111_CP_GLOBAL_CLK_CONTROL 0xb3 | ||
| 69 | |||
| 70 | #define MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18 0x65 | ||
| 71 | #define MT9M111_CC_AWB_PARAMETER_7 0x28 | ||
| 72 | |||
| 73 | #define MT9M111_SENSOR_CORE 0x00 | ||
| 74 | #define MT9M111_COLORPIPE 0x01 | ||
| 75 | #define MT9M111_CAMERA_CONTROL 0x02 | ||
| 76 | |||
| 77 | #define INITIAL_MAX_GAIN 64 | ||
| 78 | #define DEFAULT_GAIN 283 | ||
| 79 | |||
| 80 | /*****************************************************************************/ | ||
| 81 | |||
| 82 | /* Kernel module parameters */ | ||
| 83 | extern int force_sensor; | ||
| 84 | extern int dump_sensor; | ||
| 85 | extern unsigned int m5602_debug; | ||
| 86 | |||
| 87 | int mt9m111_probe(struct sd *sd); | ||
| 88 | int mt9m111_init(struct sd *sd); | ||
| 89 | int mt9m111_power_down(struct sd *sd); | ||
| 90 | |||
| 91 | int mt9m111_read_sensor(struct sd *sd, const u8 address, | ||
| 92 | u8 *i2c_data, const u8 len); | ||
| 93 | |||
| 94 | int mt9m111_write_sensor(struct sd *sd, const u8 address, | ||
| 95 | u8 *i2c_data, const u8 len); | ||
| 96 | |||
| 97 | void mt9m111_dump_registers(struct sd *sd); | ||
| 98 | |||
| 99 | int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
| 100 | int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 101 | int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 102 | int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
| 103 | int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 104 | int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
| 105 | |||
| 106 | static struct m5602_sensor mt9m111 = { | ||
| 107 | .name = "MT9M111", | ||
| 108 | |||
| 109 | .i2c_slave_id = 0xba, | ||
| 110 | |||
| 111 | .probe = mt9m111_probe, | ||
| 112 | .init = mt9m111_init, | ||
| 113 | .power_down = mt9m111_power_down, | ||
| 114 | |||
| 115 | .read_sensor = mt9m111_read_sensor, | ||
| 116 | .write_sensor = mt9m111_write_sensor, | ||
| 117 | |||
| 118 | .nctrls = 3, | ||
| 119 | .ctrls = { | ||
| 120 | { | ||
| 121 | { | ||
| 122 | .id = V4L2_CID_VFLIP, | ||
| 123 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 124 | .name = "vertical flip", | ||
| 125 | .minimum = 0, | ||
| 126 | .maximum = 1, | ||
| 127 | .step = 1, | ||
| 128 | .default_value = 0 | ||
| 129 | }, | ||
| 130 | .set = mt9m111_set_vflip, | ||
| 131 | .get = mt9m111_get_vflip | ||
| 132 | }, { | ||
| 133 | { | ||
| 134 | .id = V4L2_CID_HFLIP, | ||
| 135 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 136 | .name = "horizontal flip", | ||
| 137 | .minimum = 0, | ||
| 138 | .maximum = 1, | ||
| 139 | .step = 1, | ||
| 140 | .default_value = 0 | ||
| 141 | }, | ||
| 142 | .set = mt9m111_set_hflip, | ||
| 143 | .get = mt9m111_get_hflip | ||
| 144 | }, { | ||
| 145 | { | ||
| 146 | .id = V4L2_CID_GAIN, | ||
| 147 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 148 | .name = "gain", | ||
| 149 | .minimum = 0, | ||
| 150 | .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, | ||
| 151 | .step = 1, | ||
| 152 | .default_value = DEFAULT_GAIN, | ||
| 153 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 154 | }, | ||
| 155 | .set = mt9m111_set_hflip, | ||
| 156 | .get = mt9m111_get_hflip | ||
| 157 | } | ||
| 158 | }, | ||
| 159 | |||
| 160 | .nmodes = 1, | ||
| 161 | .modes = { | ||
| 162 | { | ||
| 163 | M5602_DEFAULT_FRAME_WIDTH, | ||
| 164 | M5602_DEFAULT_FRAME_HEIGHT, | ||
| 165 | V4L2_PIX_FMT_SBGGR8, | ||
| 166 | V4L2_FIELD_NONE, | ||
| 167 | .sizeimage = | ||
| 168 | M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, | ||
| 169 | .bytesperline = M5602_DEFAULT_FRAME_WIDTH, | ||
| 170 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 171 | .priv = 1 | ||
| 172 | } | ||
| 173 | } | ||
| 174 | }; | ||
| 175 | |||
| 176 | static const unsigned char preinit_mt9m111[][4] = | ||
| 177 | { | ||
| 178 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
| 179 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
| 180 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 181 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 182 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, | ||
| 183 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, | ||
| 184 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 185 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 186 | |||
| 187 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 188 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7}, | ||
| 189 | |||
| 190 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
| 191 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
| 192 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
| 193 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
| 194 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
| 195 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 196 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 197 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 198 | |||
| 199 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 200 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 201 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
| 202 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
| 203 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 204 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 205 | |||
| 206 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00} | ||
| 207 | }; | ||
| 208 | |||
| 209 | static const unsigned char init_mt9m111[][4] = | ||
| 210 | { | ||
| 211 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
| 212 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
| 213 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 214 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 215 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 216 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, | ||
| 217 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, | ||
| 218 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 219 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 220 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 221 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 222 | |||
| 223 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 224 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, | ||
| 225 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, | ||
| 226 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xde}, | ||
| 227 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xff}, | ||
| 228 | {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7}, | ||
| 229 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
| 230 | |||
| 231 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, | ||
| 232 | |||
| 233 | {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0xff, 0xff}, | ||
| 234 | |||
| 235 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
| 236 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
| 237 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
| 238 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
| 239 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
| 240 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 241 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 242 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 243 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, | ||
| 244 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 245 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 246 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 247 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 248 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 249 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 250 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 251 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
| 252 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
| 253 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 254 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 255 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, | ||
| 256 | |||
| 257 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 258 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, | ||
| 259 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 260 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
| 261 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 262 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
| 263 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
| 264 | {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, | ||
| 265 | {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, | ||
| 266 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, | ||
| 267 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, | ||
| 268 | {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, | ||
| 269 | {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, | ||
| 270 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, | ||
| 271 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, | ||
| 272 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, | ||
| 273 | |||
| 274 | {SENSOR, 0xcd, 0x00, 0x0e}, | ||
| 275 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, | ||
| 276 | {SENSOR, 0xd0, 0x00, 0x40}, | ||
| 277 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, | ||
| 278 | {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, | ||
| 279 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
| 280 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, | ||
| 281 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
| 282 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, | ||
| 283 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 284 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
| 285 | {SENSOR, 0x33, 0x03, 0x49}, | ||
| 286 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
| 287 | |||
| 288 | {SENSOR, 0x33, 0x03, 0x49}, | ||
| 289 | {SENSOR, 0x34, 0xc0, 0x19}, | ||
| 290 | {SENSOR, 0x3f, 0x20, 0x20}, | ||
| 291 | {SENSOR, 0x40, 0x20, 0x20}, | ||
| 292 | {SENSOR, 0x5a, 0xc0, 0x0a}, | ||
| 293 | {SENSOR, 0x70, 0x7b, 0x0a}, | ||
| 294 | {SENSOR, 0x71, 0xff, 0x00}, | ||
| 295 | {SENSOR, 0x72, 0x19, 0x0e}, | ||
| 296 | {SENSOR, 0x73, 0x18, 0x0f}, | ||
| 297 | {SENSOR, 0x74, 0x57, 0x32}, | ||
| 298 | {SENSOR, 0x75, 0x56, 0x34}, | ||
| 299 | {SENSOR, 0x76, 0x73, 0x35}, | ||
| 300 | {SENSOR, 0x77, 0x30, 0x12}, | ||
| 301 | {SENSOR, 0x78, 0x79, 0x02}, | ||
| 302 | {SENSOR, 0x79, 0x75, 0x06}, | ||
| 303 | {SENSOR, 0x7a, 0x77, 0x0a}, | ||
| 304 | {SENSOR, 0x7b, 0x78, 0x09}, | ||
| 305 | {SENSOR, 0x7c, 0x7d, 0x06}, | ||
| 306 | {SENSOR, 0x7d, 0x31, 0x10}, | ||
| 307 | {SENSOR, 0x7e, 0x00, 0x7e}, | ||
| 308 | {SENSOR, 0x80, 0x59, 0x04}, | ||
| 309 | {SENSOR, 0x81, 0x59, 0x04}, | ||
| 310 | {SENSOR, 0x82, 0x57, 0x0a}, | ||
| 311 | {SENSOR, 0x83, 0x58, 0x0b}, | ||
| 312 | {SENSOR, 0x84, 0x47, 0x0c}, | ||
| 313 | {SENSOR, 0x85, 0x48, 0x0e}, | ||
| 314 | {SENSOR, 0x86, 0x5b, 0x02}, | ||
| 315 | {SENSOR, 0x87, 0x00, 0x5c}, | ||
| 316 | {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, | ||
| 317 | {SENSOR, 0x60, 0x00, 0x80}, | ||
| 318 | {SENSOR, 0x61, 0x00, 0x00}, | ||
| 319 | {SENSOR, 0x62, 0x00, 0x00}, | ||
| 320 | {SENSOR, 0x63, 0x00, 0x00}, | ||
| 321 | {SENSOR, 0x64, 0x00, 0x00}, | ||
| 322 | |||
| 323 | {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, | ||
| 324 | {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, | ||
| 325 | {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, | ||
| 326 | {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, | ||
| 327 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, | ||
| 328 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, | ||
| 329 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, | ||
| 330 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, | ||
| 331 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, | ||
| 332 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, | ||
| 333 | {SENSOR, 0x30, 0x04, 0x00}, | ||
| 334 | |||
| 335 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 336 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 337 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 338 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 339 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 340 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 341 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 342 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 343 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 344 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 345 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 346 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
| 347 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
| 348 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 349 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 350 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 351 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
| 352 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 353 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 354 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, | ||
| 355 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, | ||
| 356 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 357 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 358 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, | ||
| 359 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 360 | {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, | ||
| 361 | {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, | ||
| 362 | |||
| 363 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 364 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 365 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 366 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 367 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 368 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 369 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 370 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 371 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 372 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 373 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 374 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
| 375 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
| 376 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 377 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 378 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 379 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
| 380 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 381 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 382 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, | ||
| 383 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, | ||
| 384 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 385 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 386 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 387 | |||
| 388 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 389 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, | ||
| 390 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
| 391 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
| 392 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, | ||
| 393 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, | ||
| 394 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
| 395 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, | ||
| 396 | {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, | ||
| 397 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
| 398 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
| 399 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
| 400 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
| 401 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
| 402 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 403 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 404 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 405 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, | ||
| 406 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 407 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 408 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 409 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 410 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 411 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 412 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 413 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
| 414 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
| 415 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 416 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 417 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, | ||
| 418 | |||
| 419 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 420 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, | ||
| 421 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 422 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
| 423 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 424 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
| 425 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
| 426 | {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, | ||
| 427 | {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, | ||
| 428 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, | ||
| 429 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, | ||
| 430 | {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, | ||
| 431 | {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, | ||
| 432 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, | ||
| 433 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, | ||
| 434 | |||
| 435 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, | ||
| 436 | {SENSOR, 0xcd, 0x00, 0x0e}, | ||
| 437 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, | ||
| 438 | {SENSOR, 0xd0, 0x00, 0x40}, | ||
| 439 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, | ||
| 440 | {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, | ||
| 441 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
| 442 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, | ||
| 443 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
| 444 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, | ||
| 445 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 446 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
| 447 | {SENSOR, 0x33, 0x03, 0x49}, | ||
| 448 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
| 449 | |||
| 450 | {SENSOR, 0x33, 0x03, 0x49}, | ||
| 451 | {SENSOR, 0x34, 0xc0, 0x19}, | ||
| 452 | {SENSOR, 0x3f, 0x20, 0x20}, | ||
| 453 | {SENSOR, 0x40, 0x20, 0x20}, | ||
| 454 | {SENSOR, 0x5a, 0xc0, 0x0a}, | ||
| 455 | {SENSOR, 0x70, 0x7b, 0x0a}, | ||
| 456 | {SENSOR, 0x71, 0xff, 0x00}, | ||
| 457 | {SENSOR, 0x72, 0x19, 0x0e}, | ||
| 458 | {SENSOR, 0x73, 0x18, 0x0f}, | ||
| 459 | {SENSOR, 0x74, 0x57, 0x32}, | ||
| 460 | {SENSOR, 0x75, 0x56, 0x34}, | ||
| 461 | {SENSOR, 0x76, 0x73, 0x35}, | ||
| 462 | {SENSOR, 0x77, 0x30, 0x12}, | ||
| 463 | {SENSOR, 0x78, 0x79, 0x02}, | ||
| 464 | {SENSOR, 0x79, 0x75, 0x06}, | ||
| 465 | {SENSOR, 0x7a, 0x77, 0x0a}, | ||
| 466 | {SENSOR, 0x7b, 0x78, 0x09}, | ||
| 467 | {SENSOR, 0x7c, 0x7d, 0x06}, | ||
| 468 | {SENSOR, 0x7d, 0x31, 0x10}, | ||
| 469 | {SENSOR, 0x7e, 0x00, 0x7e}, | ||
| 470 | {SENSOR, 0x80, 0x59, 0x04}, | ||
| 471 | {SENSOR, 0x81, 0x59, 0x04}, | ||
| 472 | {SENSOR, 0x82, 0x57, 0x0a}, | ||
| 473 | {SENSOR, 0x83, 0x58, 0x0b}, | ||
| 474 | {SENSOR, 0x84, 0x47, 0x0c}, | ||
| 475 | {SENSOR, 0x85, 0x48, 0x0e}, | ||
| 476 | {SENSOR, 0x86, 0x5b, 0x02}, | ||
| 477 | {SENSOR, 0x87, 0x00, 0x5c}, | ||
| 478 | {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, | ||
| 479 | {SENSOR, 0x60, 0x00, 0x80}, | ||
| 480 | {SENSOR, 0x61, 0x00, 0x00}, | ||
| 481 | {SENSOR, 0x62, 0x00, 0x00}, | ||
| 482 | {SENSOR, 0x63, 0x00, 0x00}, | ||
| 483 | {SENSOR, 0x64, 0x00, 0x00}, | ||
| 484 | |||
| 485 | {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, | ||
| 486 | {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, | ||
| 487 | {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, | ||
| 488 | {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, | ||
| 489 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, | ||
| 490 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, | ||
| 491 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, | ||
| 492 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, | ||
| 493 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, | ||
| 494 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, | ||
| 495 | {SENSOR, 0x30, 0x04, 0x00}, | ||
| 496 | |||
| 497 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 498 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 499 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 500 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 501 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 502 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 503 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 504 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 505 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 506 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 507 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 508 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
| 509 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
| 510 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 511 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 512 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 513 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
| 514 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 515 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 516 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, | ||
| 517 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, | ||
| 518 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 519 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 520 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, | ||
| 521 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 522 | {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, | ||
| 523 | {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, | ||
| 524 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 525 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 526 | |||
| 527 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 528 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, | ||
| 529 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
| 530 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
| 531 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, | ||
| 532 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, | ||
| 533 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
| 534 | |||
| 535 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, | ||
| 536 | {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, | ||
| 537 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
| 538 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
| 539 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
| 540 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
| 541 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
| 542 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 543 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 544 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 545 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, | ||
| 546 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 547 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 548 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 549 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 550 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 551 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 552 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 553 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
| 554 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
| 555 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 556 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 557 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, | ||
| 558 | |||
| 559 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 560 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, | ||
| 561 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 562 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
| 563 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 564 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
| 565 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
| 566 | {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, | ||
| 567 | {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, | ||
| 568 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, | ||
| 569 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, | ||
| 570 | {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, | ||
| 571 | {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, | ||
| 572 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, | ||
| 573 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, | ||
| 574 | |||
| 575 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, | ||
| 576 | {SENSOR, 0xcd, 0x00, 0x0e}, | ||
| 577 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, | ||
| 578 | {SENSOR, 0xd0, 0x00, 0x40}, | ||
| 579 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, | ||
| 580 | {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, | ||
| 581 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
| 582 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, | ||
| 583 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
| 584 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, | ||
| 585 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 586 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
| 587 | {SENSOR, 0x33, 0x03, 0x49}, | ||
| 588 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
| 589 | |||
| 590 | {SENSOR, 0x33, 0x03, 0x49}, | ||
| 591 | {SENSOR, 0x34, 0xc0, 0x19}, | ||
| 592 | {SENSOR, 0x3f, 0x20, 0x20}, | ||
| 593 | {SENSOR, 0x40, 0x20, 0x20}, | ||
| 594 | {SENSOR, 0x5a, 0xc0, 0x0a}, | ||
| 595 | {SENSOR, 0x70, 0x7b, 0x0a}, | ||
| 596 | {SENSOR, 0x71, 0xff, 0x00}, | ||
| 597 | {SENSOR, 0x72, 0x19, 0x0e}, | ||
| 598 | {SENSOR, 0x73, 0x18, 0x0f}, | ||
| 599 | {SENSOR, 0x74, 0x57, 0x32}, | ||
| 600 | {SENSOR, 0x75, 0x56, 0x34}, | ||
| 601 | {SENSOR, 0x76, 0x73, 0x35}, | ||
| 602 | {SENSOR, 0x77, 0x30, 0x12}, | ||
| 603 | {SENSOR, 0x78, 0x79, 0x02}, | ||
| 604 | {SENSOR, 0x79, 0x75, 0x06}, | ||
| 605 | {SENSOR, 0x7a, 0x77, 0x0a}, | ||
| 606 | {SENSOR, 0x7b, 0x78, 0x09}, | ||
| 607 | {SENSOR, 0x7c, 0x7d, 0x06}, | ||
| 608 | {SENSOR, 0x7d, 0x31, 0x10}, | ||
| 609 | {SENSOR, 0x7e, 0x00, 0x7e}, | ||
| 610 | {SENSOR, 0x80, 0x59, 0x04}, | ||
| 611 | {SENSOR, 0x81, 0x59, 0x04}, | ||
| 612 | {SENSOR, 0x82, 0x57, 0x0a}, | ||
| 613 | {SENSOR, 0x83, 0x58, 0x0b}, | ||
| 614 | {SENSOR, 0x84, 0x47, 0x0c}, | ||
| 615 | {SENSOR, 0x85, 0x48, 0x0e}, | ||
| 616 | {SENSOR, 0x86, 0x5b, 0x02}, | ||
| 617 | {SENSOR, 0x87, 0x00, 0x5c}, | ||
| 618 | {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, | ||
| 619 | {SENSOR, 0x60, 0x00, 0x80}, | ||
| 620 | {SENSOR, 0x61, 0x00, 0x00}, | ||
| 621 | {SENSOR, 0x62, 0x00, 0x00}, | ||
| 622 | {SENSOR, 0x63, 0x00, 0x00}, | ||
| 623 | {SENSOR, 0x64, 0x00, 0x00}, | ||
| 624 | |||
| 625 | {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, | ||
| 626 | {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18}, | ||
| 627 | {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04}, | ||
| 628 | {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08}, | ||
| 629 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38}, | ||
| 630 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, | ||
| 631 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38}, | ||
| 632 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, | ||
| 633 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03}, | ||
| 634 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03}, | ||
| 635 | {SENSOR, 0x30, 0x04, 0x00}, | ||
| 636 | |||
| 637 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 638 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 639 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 640 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 641 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 642 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 643 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 644 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 645 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 646 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 647 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 648 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
| 649 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00}, | ||
| 650 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 651 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 652 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 653 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 654 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00}, | ||
| 655 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00}, | ||
| 656 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 657 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 658 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, | ||
| 659 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 660 | {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4}, | ||
| 661 | {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea}, | ||
| 662 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 663 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 664 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 665 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 666 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 667 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 668 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, | ||
| 669 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 670 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 671 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 672 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
| 673 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 674 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 675 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 676 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
| 677 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 678 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 679 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 680 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, | ||
| 681 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 682 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 683 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 684 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, | ||
| 685 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
| 686 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 687 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, | ||
| 688 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 689 | {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, | ||
| 690 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
| 691 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
| 692 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
| 693 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
| 694 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
| 695 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 696 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 697 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 698 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, | ||
| 699 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 700 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 701 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 702 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 703 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 704 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 705 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 706 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
| 707 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
| 708 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 709 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 710 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, | ||
| 711 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 712 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 713 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 714 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 715 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, | ||
| 716 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 717 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 718 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 719 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 720 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
| 721 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 722 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 723 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 724 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 725 | |||
| 726 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
| 727 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
| 728 | {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, | ||
| 729 | {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, | ||
| 730 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, | ||
| 731 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, | ||
| 732 | {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, | ||
| 733 | {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, | ||
| 734 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, | ||
| 735 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, | ||
| 736 | |||
| 737 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 738 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, | ||
| 739 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 740 | {SENSOR, 0xcd, 0x00, 0x0e}, | ||
| 741 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 742 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, | ||
| 743 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 744 | {SENSOR, 0xd0, 0x00, 0x40}, | ||
| 745 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, | ||
| 746 | {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, | ||
| 747 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 748 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
| 749 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 750 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, | ||
| 751 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 752 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
| 753 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 754 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, | ||
| 755 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 756 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 757 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
| 758 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 759 | {SENSOR, 0x33, 0x03, 0x49}, | ||
| 760 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 761 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
| 762 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 763 | |||
| 764 | {SENSOR, 0x33, 0x03, 0x49}, | ||
| 765 | {SENSOR, 0x34, 0xc0, 0x19}, | ||
| 766 | {SENSOR, 0x3f, 0x20, 0x20}, | ||
| 767 | {SENSOR, 0x40, 0x20, 0x20}, | ||
| 768 | {SENSOR, 0x5a, 0xc0, 0x0a}, | ||
| 769 | {SENSOR, 0x70, 0x7b, 0x0a}, | ||
| 770 | {SENSOR, 0x71, 0xff, 0x00}, | ||
| 771 | {SENSOR, 0x72, 0x19, 0x0e}, | ||
| 772 | {SENSOR, 0x73, 0x18, 0x0f}, | ||
| 773 | {SENSOR, 0x74, 0x57, 0x32}, | ||
| 774 | {SENSOR, 0x75, 0x56, 0x34}, | ||
| 775 | {SENSOR, 0x76, 0x73, 0x35}, | ||
| 776 | {SENSOR, 0x77, 0x30, 0x12}, | ||
| 777 | {SENSOR, 0x78, 0x79, 0x02}, | ||
| 778 | {SENSOR, 0x79, 0x75, 0x06}, | ||
| 779 | {SENSOR, 0x7a, 0x77, 0x0a}, | ||
| 780 | {SENSOR, 0x7b, 0x78, 0x09}, | ||
| 781 | {SENSOR, 0x7c, 0x7d, 0x06}, | ||
| 782 | {SENSOR, 0x7d, 0x31, 0x10}, | ||
| 783 | {SENSOR, 0x7e, 0x00, 0x7e}, | ||
| 784 | {SENSOR, 0x80, 0x59, 0x04}, | ||
| 785 | {SENSOR, 0x81, 0x59, 0x04}, | ||
| 786 | {SENSOR, 0x82, 0x57, 0x0a}, | ||
| 787 | {SENSOR, 0x83, 0x58, 0x0b}, | ||
| 788 | {SENSOR, 0x84, 0x47, 0x0c}, | ||
| 789 | {SENSOR, 0x85, 0x48, 0x0e}, | ||
| 790 | {SENSOR, 0x86, 0x5b, 0x02}, | ||
| 791 | {SENSOR, 0x87, 0x00, 0x5c}, | ||
| 792 | {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, | ||
| 793 | {SENSOR, 0x60, 0x00, 0x80}, | ||
| 794 | {SENSOR, 0x61, 0x00, 0x00}, | ||
| 795 | {SENSOR, 0x62, 0x00, 0x00}, | ||
| 796 | {SENSOR, 0x63, 0x00, 0x00}, | ||
| 797 | {SENSOR, 0x64, 0x00, 0x00}, | ||
| 798 | {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, | ||
| 799 | {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, | ||
| 800 | {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, | ||
| 801 | {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, | ||
| 802 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, | ||
| 803 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, | ||
| 804 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, | ||
| 805 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, | ||
| 806 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, | ||
| 807 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, | ||
| 808 | {SENSOR, 0x30, 0x04, 0x00}, | ||
| 809 | |||
| 810 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 811 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 812 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 813 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 814 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 815 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 816 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 817 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 818 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 819 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 820 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 821 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
| 822 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe3, 0x00}, | ||
| 823 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 824 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 825 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 826 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
| 827 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 828 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 829 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
| 830 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, | ||
| 831 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 832 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 833 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 834 | |||
| 835 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 836 | {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, | ||
| 837 | {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xe6}, | ||
| 838 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 839 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 840 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 841 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 842 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 843 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 844 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x09}, | ||
| 845 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 846 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 847 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 848 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
| 849 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 850 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 851 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 852 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
| 853 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 854 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 855 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 856 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c}, | ||
| 857 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 858 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 859 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 860 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x04}, | ||
| 861 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
| 862 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 863 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00}, | ||
| 864 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 865 | {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03}, | ||
| 866 | |||
| 867 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00}, | ||
| 868 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00}, | ||
| 869 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00}, | ||
| 870 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00}, | ||
| 871 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00}, | ||
| 872 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 873 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 874 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 875 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00}, | ||
| 876 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 877 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 878 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 879 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 880 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 881 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 882 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 883 | {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00}, | ||
| 884 | {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00}, | ||
| 885 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 886 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 887 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}, | ||
| 888 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 889 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 890 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 891 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 892 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x05}, | ||
| 893 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 894 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 895 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 896 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 897 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x29}, | ||
| 898 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 899 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 900 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00}, | ||
| 901 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 902 | {SENSOR, MT9M111_SC_RESET, 0x00, 0x08}, | ||
| 903 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01}, | ||
| 904 | {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10}, | ||
| 905 | {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a}, | ||
| 906 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01}, | ||
| 907 | {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01}, | ||
| 908 | {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00}, | ||
| 909 | {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00}, | ||
| 910 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00}, | ||
| 911 | {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00}, | ||
| 912 | |||
| 913 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 914 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00}, | ||
| 915 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 916 | {SENSOR, 0xcd, 0x00, 0x0e}, | ||
| 917 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 918 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00}, | ||
| 919 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 920 | {SENSOR, 0xd0, 0x00, 0x40}, | ||
| 921 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02}, | ||
| 922 | {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00}, | ||
| 923 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 924 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
| 925 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 926 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07}, | ||
| 927 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 928 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00}, | ||
| 929 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 930 | {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03}, | ||
| 931 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 932 | |||
| 933 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 934 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
| 935 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 936 | {SENSOR, 0x33, 0x03, 0x49}, | ||
| 937 | {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00}, | ||
| 938 | {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00}, | ||
| 939 | {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00}, | ||
| 940 | |||
| 941 | {SENSOR, 0x33, 0x03, 0x49}, | ||
| 942 | {SENSOR, 0x34, 0xc0, 0x19}, | ||
| 943 | {SENSOR, 0x3f, 0x20, 0x20}, | ||
| 944 | {SENSOR, 0x40, 0x20, 0x20}, | ||
| 945 | {SENSOR, 0x5a, 0xc0, 0x0a}, | ||
| 946 | {SENSOR, 0x70, 0x7b, 0x0a}, | ||
| 947 | {SENSOR, 0x71, 0xff, 0x00}, | ||
| 948 | {SENSOR, 0x72, 0x19, 0x0e}, | ||
| 949 | {SENSOR, 0x73, 0x18, 0x0f}, | ||
| 950 | {SENSOR, 0x74, 0x57, 0x32}, | ||
| 951 | {SENSOR, 0x75, 0x56, 0x34}, | ||
| 952 | {SENSOR, 0x76, 0x73, 0x35}, | ||
| 953 | {SENSOR, 0x77, 0x30, 0x12}, | ||
| 954 | {SENSOR, 0x78, 0x79, 0x02}, | ||
| 955 | {SENSOR, 0x79, 0x75, 0x06}, | ||
| 956 | {SENSOR, 0x7a, 0x77, 0x0a}, | ||
| 957 | {SENSOR, 0x7b, 0x78, 0x09}, | ||
| 958 | {SENSOR, 0x7c, 0x7d, 0x06}, | ||
| 959 | {SENSOR, 0x7d, 0x31, 0x10}, | ||
| 960 | {SENSOR, 0x7e, 0x00, 0x7e}, | ||
| 961 | {SENSOR, 0x80, 0x59, 0x04}, | ||
| 962 | {SENSOR, 0x81, 0x59, 0x04}, | ||
| 963 | {SENSOR, 0x82, 0x57, 0x0a}, | ||
| 964 | {SENSOR, 0x83, 0x58, 0x0b}, | ||
| 965 | {SENSOR, 0x84, 0x47, 0x0c}, | ||
| 966 | {SENSOR, 0x85, 0x48, 0x0e}, | ||
| 967 | {SENSOR, 0x86, 0x5b, 0x02}, | ||
| 968 | {SENSOR, 0x87, 0x00, 0x5c}, | ||
| 969 | {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08}, | ||
| 970 | {SENSOR, 0x60, 0x00, 0x80}, | ||
| 971 | {SENSOR, 0x61, 0x00, 0x00}, | ||
| 972 | {SENSOR, 0x62, 0x00, 0x00}, | ||
| 973 | {SENSOR, 0x63, 0x00, 0x00}, | ||
| 974 | {SENSOR, 0x64, 0x00, 0x00}, | ||
| 975 | |||
| 976 | {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, | ||
| 977 | {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, | ||
| 978 | {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, | ||
| 979 | {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, | ||
| 980 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, | ||
| 981 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, | ||
| 982 | {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, | ||
| 983 | {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, | ||
| 984 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f}, | ||
| 985 | {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, | ||
| 986 | {SENSOR, 0x30, 0x04, 0x00}, | ||
| 987 | |||
| 988 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 989 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 990 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 991 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 992 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 993 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 994 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 995 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 996 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 997 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 998 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 999 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
| 1000 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, | ||
| 1001 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 1002 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 1003 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 1004 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
| 1005 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 1006 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 1007 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
| 1008 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, | ||
| 1009 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 1010 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 1011 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 1012 | |||
| 1013 | {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00}, | ||
| 1014 | /* Set number of blank rows chosen to 400 */ | ||
| 1015 | {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90}, | ||
| 1016 | /* Set the global gain to 283 (of 512) */ | ||
| 1017 | {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x03, 0x63} | ||
| 1018 | }; | ||
| 1019 | |||
| 1020 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c new file mode 100644 index 000000000000..31c5896250e7 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c | |||
| @@ -0,0 +1,546 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the ov9650 sensor | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include "m5602_ov9650.h" | ||
| 20 | |||
| 21 | int ov9650_read_sensor(struct sd *sd, const u8 address, | ||
| 22 | u8 *i2c_data, const u8 len) | ||
| 23 | { | ||
| 24 | int err, i; | ||
| 25 | |||
| 26 | /* The ov9650 registers have a max depth of one byte */ | ||
| 27 | if (len > 1 || !len) | ||
| 28 | return -EINVAL; | ||
| 29 | |||
| 30 | do { | ||
| 31 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
| 32 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
| 33 | |||
| 34 | m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, | ||
| 35 | ov9650.i2c_slave_id); | ||
| 36 | m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); | ||
| 37 | m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); | ||
| 38 | m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); | ||
| 39 | |||
| 40 | for (i = 0; i < len; i++) { | ||
| 41 | err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); | ||
| 42 | |||
| 43 | PDEBUG(DBG_TRACE, "Reading sensor register " | ||
| 44 | "0x%x containing 0x%x ", address, *i2c_data); | ||
| 45 | } | ||
| 46 | return (err < 0) ? err : 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | int ov9650_write_sensor(struct sd *sd, const u8 address, | ||
| 50 | u8 *i2c_data, const u8 len) | ||
| 51 | { | ||
| 52 | int err, i; | ||
| 53 | u8 *p; | ||
| 54 | struct usb_device *udev = sd->gspca_dev.dev; | ||
| 55 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
| 56 | |||
| 57 | /* The ov9650 only supports one byte writes */ | ||
| 58 | if (len > 1 || !len) | ||
| 59 | return -EINVAL; | ||
| 60 | |||
| 61 | memcpy(buf, sensor_urb_skeleton, | ||
| 62 | sizeof(sensor_urb_skeleton)); | ||
| 63 | |||
| 64 | buf[11] = sd->sensor->i2c_slave_id; | ||
| 65 | buf[15] = address; | ||
| 66 | |||
| 67 | /* Special case larger sensor writes */ | ||
| 68 | p = buf + 16; | ||
| 69 | |||
| 70 | /* Copy a four byte write sequence for each byte to be written to */ | ||
| 71 | for (i = 0; i < len; i++) { | ||
| 72 | memcpy(p, sensor_urb_skeleton + 16, 4); | ||
| 73 | p[3] = i2c_data[i]; | ||
| 74 | p += 4; | ||
| 75 | PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", | ||
| 76 | address, i2c_data[i]); | ||
| 77 | } | ||
| 78 | |||
| 79 | /* Copy the tailer */ | ||
| 80 | memcpy(p, sensor_urb_skeleton + 20, 4); | ||
| 81 | |||
| 82 | /* Set the total length */ | ||
| 83 | p[3] = 0x10 + len; | ||
| 84 | |||
| 85 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 86 | 0x04, 0x40, 0x19, | ||
| 87 | 0x0000, buf, | ||
| 88 | 20 + len * 4, M5602_URB_MSG_TIMEOUT); | ||
| 89 | |||
| 90 | return (err < 0) ? err : 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | int ov9650_probe(struct sd *sd) | ||
| 94 | { | ||
| 95 | u8 prod_id = 0, ver_id = 0, i; | ||
| 96 | |||
| 97 | if (force_sensor) { | ||
| 98 | if (force_sensor == OV9650_SENSOR) { | ||
| 99 | info("Forcing an %s sensor", ov9650.name); | ||
| 100 | goto sensor_found; | ||
| 101 | } | ||
| 102 | /* If we want to force another sensor, | ||
| 103 | don't try to probe this one */ | ||
| 104 | return -ENODEV; | ||
| 105 | } | ||
| 106 | |||
| 107 | info("Probing for an ov9650 sensor"); | ||
| 108 | |||
| 109 | /* Run the pre-init to actually probe the unit */ | ||
| 110 | for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) { | ||
| 111 | u8 data = preinit_ov9650[i][2]; | ||
| 112 | if (preinit_ov9650[i][0] == SENSOR) | ||
| 113 | ov9650_write_sensor(sd, | ||
| 114 | preinit_ov9650[i][1], &data, 1); | ||
| 115 | else | ||
| 116 | m5602_write_bridge(sd, preinit_ov9650[i][1], data); | ||
| 117 | } | ||
| 118 | |||
| 119 | if (ov9650_read_sensor(sd, OV9650_PID, &prod_id, 1)) | ||
| 120 | return -ENODEV; | ||
| 121 | |||
| 122 | if (ov9650_read_sensor(sd, OV9650_VER, &ver_id, 1)) | ||
| 123 | return -ENODEV; | ||
| 124 | |||
| 125 | if ((prod_id == 0x96) && (ver_id == 0x52)) { | ||
| 126 | info("Detected an ov9650 sensor"); | ||
| 127 | goto sensor_found; | ||
| 128 | } | ||
| 129 | |||
| 130 | return -ENODEV; | ||
| 131 | |||
| 132 | sensor_found: | ||
| 133 | sd->gspca_dev.cam.cam_mode = ov9650.modes; | ||
| 134 | sd->gspca_dev.cam.nmodes = ov9650.nmodes; | ||
| 135 | sd->desc->ctrls = ov9650.ctrls; | ||
| 136 | sd->desc->nctrls = ov9650.nctrls; | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | int ov9650_init(struct sd *sd) | ||
| 141 | { | ||
| 142 | int i, err = 0; | ||
| 143 | u8 data; | ||
| 144 | |||
| 145 | if (dump_sensor) | ||
| 146 | ov9650_dump_registers(sd); | ||
| 147 | |||
| 148 | for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) { | ||
| 149 | data = init_ov9650[i][2]; | ||
| 150 | if (init_ov9650[i][0] == SENSOR) | ||
| 151 | err = ov9650_write_sensor(sd, init_ov9650[i][1], | ||
| 152 | &data, 1); | ||
| 153 | else | ||
| 154 | err = m5602_write_bridge(sd, init_ov9650[i][1], data); | ||
| 155 | } | ||
| 156 | |||
| 157 | if (!err && dmi_check_system(ov9650_flip_dmi_table)) { | ||
| 158 | info("vflip quirk active"); | ||
| 159 | data = 0x30; | ||
| 160 | err = ov9650_write_sensor(sd, OV9650_MVFP, &data, 1); | ||
| 161 | } | ||
| 162 | |||
| 163 | return (err < 0) ? err : 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | int ov9650_power_down(struct sd *sd) | ||
| 167 | { | ||
| 168 | int i; | ||
| 169 | for (i = 0; i < ARRAY_SIZE(power_down_ov9650); i++) { | ||
| 170 | u8 data = power_down_ov9650[i][2]; | ||
| 171 | if (power_down_ov9650[i][0] == SENSOR) | ||
| 172 | ov9650_write_sensor(sd, | ||
| 173 | power_down_ov9650[i][1], &data, 1); | ||
| 174 | else | ||
| 175 | m5602_write_bridge(sd, power_down_ov9650[i][1], data); | ||
| 176 | } | ||
| 177 | |||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | |||
| 181 | int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 182 | { | ||
| 183 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 184 | u8 i2c_data; | ||
| 185 | int err; | ||
| 186 | |||
| 187 | err = ov9650_read_sensor(sd, OV9650_COM1, &i2c_data, 1); | ||
| 188 | if (err < 0) | ||
| 189 | goto out; | ||
| 190 | *val = i2c_data & 0x03; | ||
| 191 | |||
| 192 | err = ov9650_read_sensor(sd, OV9650_AECH, &i2c_data, 1); | ||
| 193 | if (err < 0) | ||
| 194 | goto out; | ||
| 195 | *val |= (i2c_data << 2); | ||
| 196 | |||
| 197 | err = ov9650_read_sensor(sd, OV9650_AECHM, &i2c_data, 1); | ||
| 198 | if (err < 0) | ||
| 199 | goto out; | ||
| 200 | *val |= (i2c_data & 0x3f) << 10; | ||
| 201 | |||
| 202 | PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val); | ||
| 203 | out: | ||
| 204 | return (err < 0) ? err : 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | ||
| 208 | { | ||
| 209 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 210 | u8 i2c_data; | ||
| 211 | int err; | ||
| 212 | |||
| 213 | PDEBUG(DBG_V4L2_CID, "Set exposure to %d", | ||
| 214 | val & 0xffff); | ||
| 215 | |||
| 216 | /* The 6 MSBs */ | ||
| 217 | i2c_data = (val >> 10) & 0x3f; | ||
| 218 | err = ov9650_write_sensor(sd, OV9650_AECHM, | ||
| 219 | &i2c_data, 1); | ||
| 220 | if (err < 0) | ||
| 221 | goto out; | ||
| 222 | |||
| 223 | /* The 8 middle bits */ | ||
| 224 | i2c_data = (val >> 2) & 0xff; | ||
| 225 | err = ov9650_write_sensor(sd, OV9650_AECH, | ||
| 226 | &i2c_data, 1); | ||
| 227 | if (err < 0) | ||
| 228 | goto out; | ||
| 229 | |||
| 230 | /* The 2 LSBs */ | ||
| 231 | i2c_data = val & 0x03; | ||
| 232 | err = ov9650_write_sensor(sd, OV9650_COM1, &i2c_data, 1); | ||
| 233 | |||
| 234 | out: | ||
| 235 | return (err < 0) ? err : 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 239 | { | ||
| 240 | int err; | ||
| 241 | u8 i2c_data; | ||
| 242 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 243 | |||
| 244 | ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
| 245 | *val = (i2c_data & 0x03) << 8; | ||
| 246 | |||
| 247 | err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); | ||
| 248 | *val |= i2c_data; | ||
| 249 | PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); | ||
| 250 | return (err < 0) ? err : 0; | ||
| 251 | } | ||
| 252 | |||
| 253 | int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
| 254 | { | ||
| 255 | int err; | ||
| 256 | u8 i2c_data; | ||
| 257 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 258 | |||
| 259 | /* The 2 MSB */ | ||
| 260 | /* Read the OV9650_VREF register first to avoid | ||
| 261 | corrupting the VREF high and low bits */ | ||
| 262 | ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
| 263 | /* Mask away all uninteresting bits */ | ||
| 264 | i2c_data = ((val & 0x0300) >> 2) | | ||
| 265 | (i2c_data & 0x3F); | ||
| 266 | err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
| 267 | |||
| 268 | /* The 8 LSBs */ | ||
| 269 | i2c_data = val & 0xff; | ||
| 270 | err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); | ||
| 271 | return (err < 0) ? err : 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 275 | { | ||
| 276 | int err; | ||
| 277 | u8 i2c_data; | ||
| 278 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 279 | |||
| 280 | err = ov9650_read_sensor(sd, OV9650_RED, &i2c_data, 1); | ||
| 281 | *val = i2c_data; | ||
| 282 | |||
| 283 | PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val); | ||
| 284 | |||
| 285 | return (err < 0) ? err : 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
| 289 | { | ||
| 290 | int err; | ||
| 291 | u8 i2c_data; | ||
| 292 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 293 | |||
| 294 | PDEBUG(DBG_V4L2_CID, "Set red gain to %d", | ||
| 295 | val & 0xff); | ||
| 296 | |||
| 297 | i2c_data = val & 0xff; | ||
| 298 | err = ov9650_write_sensor(sd, OV9650_RED, &i2c_data, 1); | ||
| 299 | |||
| 300 | return (err < 0) ? err : 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 304 | { | ||
| 305 | int err; | ||
| 306 | u8 i2c_data; | ||
| 307 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 308 | |||
| 309 | err = ov9650_read_sensor(sd, OV9650_BLUE, &i2c_data, 1); | ||
| 310 | *val = i2c_data; | ||
| 311 | |||
| 312 | PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val); | ||
| 313 | |||
| 314 | return (err < 0) ? err : 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
| 318 | { | ||
| 319 | int err; | ||
| 320 | u8 i2c_data; | ||
| 321 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 322 | |||
| 323 | PDEBUG(DBG_V4L2_CID, "Set blue gain to %d", | ||
| 324 | val & 0xff); | ||
| 325 | |||
| 326 | i2c_data = val & 0xff; | ||
| 327 | err = ov9650_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); | ||
| 328 | |||
| 329 | return (err < 0) ? err : 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 333 | { | ||
| 334 | int err; | ||
| 335 | u8 i2c_data; | ||
| 336 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 337 | |||
| 338 | err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
| 339 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
| 340 | *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1; | ||
| 341 | else | ||
| 342 | *val = (i2c_data & OV9650_HFLIP) >> 5; | ||
| 343 | PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); | ||
| 344 | |||
| 345 | return (err < 0) ? err : 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | ||
| 349 | { | ||
| 350 | int err; | ||
| 351 | u8 i2c_data; | ||
| 352 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 353 | |||
| 354 | PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val); | ||
| 355 | err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
| 356 | if (err < 0) | ||
| 357 | goto out; | ||
| 358 | |||
| 359 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
| 360 | i2c_data = ((i2c_data & 0xdf) | | ||
| 361 | (((val ? 0 : 1) & 0x01) << 5)); | ||
| 362 | else | ||
| 363 | i2c_data = ((i2c_data & 0xdf) | | ||
| 364 | ((val & 0x01) << 5)); | ||
| 365 | |||
| 366 | err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
| 367 | out: | ||
| 368 | return (err < 0) ? err : 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 372 | { | ||
| 373 | int err; | ||
| 374 | u8 i2c_data; | ||
| 375 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 376 | |||
| 377 | err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
| 378 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
| 379 | *val = ((i2c_data & 0x10) >> 4) ? 0 : 1; | ||
| 380 | else | ||
| 381 | *val = (i2c_data & 0x10) >> 4; | ||
| 382 | PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); | ||
| 383 | |||
| 384 | return (err < 0) ? err : 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | ||
| 388 | { | ||
| 389 | int err; | ||
| 390 | u8 i2c_data; | ||
| 391 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 392 | |||
| 393 | PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); | ||
| 394 | err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
| 395 | if (err < 0) | ||
| 396 | goto out; | ||
| 397 | |||
| 398 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
| 399 | i2c_data = ((i2c_data & 0xef) | | ||
| 400 | (((val ? 0 : 1) & 0x01) << 4)); | ||
| 401 | else | ||
| 402 | i2c_data = ((i2c_data & 0xef) | | ||
| 403 | ((val & 0x01) << 4)); | ||
| 404 | |||
| 405 | err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
| 406 | out: | ||
| 407 | return (err < 0) ? err : 0; | ||
| 408 | } | ||
| 409 | |||
| 410 | int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 411 | { | ||
| 412 | int err; | ||
| 413 | u8 i2c_data; | ||
| 414 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 415 | |||
| 416 | err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
| 417 | if (err < 0) | ||
| 418 | goto out; | ||
| 419 | *val = (i2c_data & 0x03) << 8; | ||
| 420 | |||
| 421 | err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); | ||
| 422 | *val |= i2c_data; | ||
| 423 | PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); | ||
| 424 | out: | ||
| 425 | return (err < 0) ? err : 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | ||
| 429 | { | ||
| 430 | int err; | ||
| 431 | u8 i2c_data; | ||
| 432 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 433 | |||
| 434 | PDEBUG(DBG_V4L2_CID, "Set gain to %d", val & 0x3ff); | ||
| 435 | |||
| 436 | /* Read the OV9650_VREF register first to avoid | ||
| 437 | corrupting the VREF high and low bits */ | ||
| 438 | err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
| 439 | if (err < 0) | ||
| 440 | goto out; | ||
| 441 | |||
| 442 | /* Mask away all uninteresting bits */ | ||
| 443 | i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); | ||
| 444 | err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1); | ||
| 445 | if (err < 0) | ||
| 446 | goto out; | ||
| 447 | |||
| 448 | /* The 8 LSBs */ | ||
| 449 | i2c_data = val & 0xff; | ||
| 450 | err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); | ||
| 451 | |||
| 452 | out: | ||
| 453 | return (err < 0) ? err : 0; | ||
| 454 | } | ||
| 455 | |||
| 456 | int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 457 | { | ||
| 458 | int err; | ||
| 459 | u8 i2c_data; | ||
| 460 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 461 | |||
| 462 | err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
| 463 | *val = (i2c_data & OV9650_AWB_EN) >> 1; | ||
| 464 | PDEBUG(DBG_V4L2_CID, "Read auto white balance %d", *val); | ||
| 465 | |||
| 466 | return (err < 0) ? err : 0; | ||
| 467 | } | ||
| 468 | |||
| 469 | int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
| 470 | { | ||
| 471 | int err; | ||
| 472 | u8 i2c_data; | ||
| 473 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 474 | |||
| 475 | PDEBUG(DBG_V4L2_CID, "Set auto white balance to %d", val); | ||
| 476 | err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
| 477 | if (err < 0) | ||
| 478 | goto out; | ||
| 479 | |||
| 480 | i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); | ||
| 481 | err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
| 482 | out: | ||
| 483 | return (err < 0) ? err : 0; | ||
| 484 | } | ||
| 485 | |||
| 486 | int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 487 | { | ||
| 488 | int err; | ||
| 489 | u8 i2c_data; | ||
| 490 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 491 | |||
| 492 | err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
| 493 | *val = (i2c_data & OV9650_AGC_EN) >> 2; | ||
| 494 | PDEBUG(DBG_V4L2_CID, "Read auto gain control %d", *val); | ||
| 495 | |||
| 496 | return (err < 0) ? err : 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
| 500 | { | ||
| 501 | int err; | ||
| 502 | u8 i2c_data; | ||
| 503 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 504 | |||
| 505 | PDEBUG(DBG_V4L2_CID, "Set auto gain control to %d", val); | ||
| 506 | err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
| 507 | if (err < 0) | ||
| 508 | goto out; | ||
| 509 | |||
| 510 | i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); | ||
| 511 | err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1); | ||
| 512 | out: | ||
| 513 | return (err < 0) ? err : 0; | ||
| 514 | } | ||
| 515 | |||
| 516 | void ov9650_dump_registers(struct sd *sd) | ||
| 517 | { | ||
| 518 | int address; | ||
| 519 | info("Dumping the ov9650 register state"); | ||
| 520 | for (address = 0; address < 0xa9; address++) { | ||
| 521 | u8 value; | ||
| 522 | ov9650_read_sensor(sd, address, &value, 1); | ||
| 523 | info("register 0x%x contains 0x%x", | ||
| 524 | address, value); | ||
| 525 | } | ||
| 526 | |||
| 527 | info("ov9650 register state dump complete"); | ||
| 528 | |||
| 529 | info("Probing for which registers that are read/write"); | ||
| 530 | for (address = 0; address < 0xff; address++) { | ||
| 531 | u8 old_value, ctrl_value; | ||
| 532 | u8 test_value[2] = {0xff, 0xff}; | ||
| 533 | |||
| 534 | ov9650_read_sensor(sd, address, &old_value, 1); | ||
| 535 | ov9650_write_sensor(sd, address, test_value, 1); | ||
| 536 | ov9650_read_sensor(sd, address, &ctrl_value, 1); | ||
| 537 | |||
| 538 | if (ctrl_value == test_value[0]) | ||
| 539 | info("register 0x%x is writeable", address); | ||
| 540 | else | ||
| 541 | info("register 0x%x is read only", address); | ||
| 542 | |||
| 543 | /* Restore original value */ | ||
| 544 | ov9650_write_sensor(sd, address, &old_value, 1); | ||
| 545 | } | ||
| 546 | } | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h new file mode 100644 index 000000000000..2f29cb056f30 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.h | |||
| @@ -0,0 +1,503 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the ov9650 sensor | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef M5602_OV9650_H_ | ||
| 20 | #define M5602_OV9650_H_ | ||
| 21 | |||
| 22 | #include <linux/dmi.h> | ||
| 23 | |||
| 24 | #include "m5602_sensor.h" | ||
| 25 | |||
| 26 | /*****************************************************************************/ | ||
| 27 | |||
| 28 | #define OV9650_GAIN 0x00 | ||
| 29 | #define OV9650_BLUE 0x01 | ||
| 30 | #define OV9650_RED 0x02 | ||
| 31 | #define OV9650_VREF 0x03 | ||
| 32 | #define OV9650_COM1 0x04 | ||
| 33 | #define OV9650_BAVE 0x05 | ||
| 34 | #define OV9650_GEAVE 0x06 | ||
| 35 | #define OV9650_RSVD7 0x07 | ||
| 36 | #define OV9650_PID 0x0a | ||
| 37 | #define OV9650_VER 0x0b | ||
| 38 | #define OV9650_COM3 0x0c | ||
| 39 | #define OV9650_COM5 0x0e | ||
| 40 | #define OV9650_COM6 0x0f | ||
| 41 | #define OV9650_AECH 0x10 | ||
| 42 | #define OV9650_CLKRC 0x11 | ||
| 43 | #define OV9650_COM7 0x12 | ||
| 44 | #define OV9650_COM8 0x13 | ||
| 45 | #define OV9650_COM9 0x14 | ||
| 46 | #define OV9650_COM10 0x15 | ||
| 47 | #define OV9650_RSVD16 0x16 | ||
| 48 | #define OV9650_HSTART 0x17 | ||
| 49 | #define OV9650_HSTOP 0x18 | ||
| 50 | #define OV9650_VSTRT 0x19 | ||
| 51 | #define OV9650_VSTOP 0x1a | ||
| 52 | #define OV9650_PSHFT 0x1b | ||
| 53 | #define OV9650_MVFP 0x1e | ||
| 54 | #define OV9650_AEW 0x24 | ||
| 55 | #define OV9650_AEB 0x25 | ||
| 56 | #define OV9650_VPT 0x26 | ||
| 57 | #define OV9650_BBIAS 0x27 | ||
| 58 | #define OV9650_GbBIAS 0x28 | ||
| 59 | #define OV9650_Gr_COM 0x29 | ||
| 60 | #define OV9650_RBIAS 0x2c | ||
| 61 | #define OV9650_HREF 0x32 | ||
| 62 | #define OV9650_CHLF 0x33 | ||
| 63 | #define OV9650_ARBLM 0x34 | ||
| 64 | #define OV9650_RSVD35 0x35 | ||
| 65 | #define OV9650_RSVD36 0x36 | ||
| 66 | #define OV9650_ADC 0x37 | ||
| 67 | #define OV9650_ACOM38 0x38 | ||
| 68 | #define OV9650_OFON 0x39 | ||
| 69 | #define OV9650_TSLB 0x3a | ||
| 70 | #define OV9650_COM12 0x3c | ||
| 71 | #define OV9650_COM13 0x3d | ||
| 72 | #define OV9650_COM15 0x40 | ||
| 73 | #define OV9650_COM16 0x41 | ||
| 74 | #define OV9650_LCC1 0x62 | ||
| 75 | #define OV9650_LCC2 0x63 | ||
| 76 | #define OV9650_LCC3 0x64 | ||
| 77 | #define OV9650_LCC4 0x65 | ||
| 78 | #define OV9650_LCC5 0x66 | ||
| 79 | #define OV9650_HV 0x69 | ||
| 80 | #define OV9650_DBLV 0x6b | ||
| 81 | #define OV9650_COM21 0x8b | ||
| 82 | #define OV9650_COM22 0x8c | ||
| 83 | #define OV9650_COM24 0x8e | ||
| 84 | #define OV9650_DBLC1 0x8f | ||
| 85 | #define OV9650_RSVD94 0x94 | ||
| 86 | #define OV9650_RSVD95 0x95 | ||
| 87 | #define OV9650_RSVD96 0x96 | ||
| 88 | #define OV9650_LCCFB 0x9d | ||
| 89 | #define OV9650_LCCFR 0x9e | ||
| 90 | #define OV9650_AECHM 0xa1 | ||
| 91 | #define OV9650_COM26 0xa5 | ||
| 92 | #define OV9650_ACOMA8 0xa8 | ||
| 93 | #define OV9650_ACOMA9 0xa9 | ||
| 94 | |||
| 95 | #define OV9650_REGISTER_RESET (1 << 7) | ||
| 96 | #define OV9650_VGA_SELECT (1 << 6) | ||
| 97 | #define OV9650_RGB_SELECT (1 << 2) | ||
| 98 | #define OV9650_RAW_RGB_SELECT (1 << 0) | ||
| 99 | |||
| 100 | #define OV9650_FAST_AGC_AEC (1 << 7) | ||
| 101 | #define OV9650_AEC_UNLIM_STEP_SIZE (1 << 6) | ||
| 102 | #define OV9650_BANDING (1 << 5) | ||
| 103 | #define OV9650_AGC_EN (1 << 2) | ||
| 104 | #define OV9650_AWB_EN (1 << 1) | ||
| 105 | #define OV9650_AEC_EN (1 << 0) | ||
| 106 | |||
| 107 | #define OV9650_VARIOPIXEL (1 << 2) | ||
| 108 | #define OV9650_SYSTEM_CLK_SEL (1 << 7) | ||
| 109 | #define OV9650_SLAM_MODE (1 << 4) | ||
| 110 | |||
| 111 | #define OV9650_VFLIP (1 << 4) | ||
| 112 | #define OV9650_HFLIP (1 << 5) | ||
| 113 | |||
| 114 | #define GAIN_DEFAULT 0x14 | ||
| 115 | #define RED_GAIN_DEFAULT 0x70 | ||
| 116 | #define BLUE_GAIN_DEFAULT 0x20 | ||
| 117 | #define EXPOSURE_DEFAULT 0x5003 | ||
| 118 | |||
| 119 | /*****************************************************************************/ | ||
| 120 | |||
| 121 | /* Kernel module parameters */ | ||
| 122 | extern int force_sensor; | ||
| 123 | extern int dump_sensor; | ||
| 124 | extern unsigned int m5602_debug; | ||
| 125 | |||
| 126 | int ov9650_probe(struct sd *sd); | ||
| 127 | int ov9650_init(struct sd *sd); | ||
| 128 | int ov9650_power_down(struct sd *sd); | ||
| 129 | |||
| 130 | int ov9650_read_sensor(struct sd *sd, const u8 address, | ||
| 131 | u8 *i2c_data, const u8 len); | ||
| 132 | int ov9650_write_sensor(struct sd *sd, const u8 address, | ||
| 133 | u8 *i2c_data, const u8 len); | ||
| 134 | |||
| 135 | void ov9650_dump_registers(struct sd *sd); | ||
| 136 | |||
| 137 | int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
| 138 | int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 139 | int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 140 | int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
| 141 | int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 142 | int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
| 143 | int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 144 | int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
| 145 | int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 146 | int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
| 147 | int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 148 | int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
| 149 | int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 150 | int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val); | ||
| 151 | int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 152 | int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
| 153 | int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 154 | int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
| 155 | |||
| 156 | static struct m5602_sensor ov9650 = { | ||
| 157 | .name = "OV9650", | ||
| 158 | .i2c_slave_id = 0x60, | ||
| 159 | .probe = ov9650_probe, | ||
| 160 | .init = ov9650_init, | ||
| 161 | .power_down = ov9650_power_down, | ||
| 162 | .read_sensor = ov9650_read_sensor, | ||
| 163 | .write_sensor = ov9650_write_sensor, | ||
| 164 | |||
| 165 | .nctrls = 8, | ||
| 166 | .ctrls = { | ||
| 167 | { | ||
| 168 | { | ||
| 169 | .id = V4L2_CID_EXPOSURE, | ||
| 170 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 171 | .name = "exposure", | ||
| 172 | .minimum = 0x00, | ||
| 173 | .maximum = 0xffff, | ||
| 174 | .step = 0x1, | ||
| 175 | .default_value = EXPOSURE_DEFAULT, | ||
| 176 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 177 | }, | ||
| 178 | .set = ov9650_set_exposure, | ||
| 179 | .get = ov9650_get_exposure | ||
| 180 | }, { | ||
| 181 | { | ||
| 182 | .id = V4L2_CID_GAIN, | ||
| 183 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 184 | .name = "gain", | ||
| 185 | .minimum = 0x00, | ||
| 186 | .maximum = 0x3ff, | ||
| 187 | .step = 0x1, | ||
| 188 | .default_value = GAIN_DEFAULT, | ||
| 189 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 190 | }, | ||
| 191 | .set = ov9650_set_gain, | ||
| 192 | .get = ov9650_get_gain | ||
| 193 | }, { | ||
| 194 | { | ||
| 195 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 196 | .name = "red balance", | ||
| 197 | .minimum = 0x00, | ||
| 198 | .maximum = 0xff, | ||
| 199 | .step = 0x1, | ||
| 200 | .default_value = RED_GAIN_DEFAULT, | ||
| 201 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 202 | }, | ||
| 203 | .set = ov9650_set_red_balance, | ||
| 204 | .get = ov9650_get_red_balance | ||
| 205 | }, { | ||
| 206 | { | ||
| 207 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 208 | .name = "blue balance", | ||
| 209 | .minimum = 0x00, | ||
| 210 | .maximum = 0xff, | ||
| 211 | .step = 0x1, | ||
| 212 | .default_value = BLUE_GAIN_DEFAULT, | ||
| 213 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 214 | }, | ||
| 215 | .set = ov9650_set_blue_balance, | ||
| 216 | .get = ov9650_get_blue_balance | ||
| 217 | }, { | ||
| 218 | { | ||
| 219 | .id = V4L2_CID_HFLIP, | ||
| 220 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 221 | .name = "horizontal flip", | ||
| 222 | .minimum = 0, | ||
| 223 | .maximum = 1, | ||
| 224 | .step = 1, | ||
| 225 | .default_value = 0 | ||
| 226 | }, | ||
| 227 | .set = ov9650_set_hflip, | ||
| 228 | .get = ov9650_get_hflip | ||
| 229 | }, { | ||
| 230 | { | ||
| 231 | .id = V4L2_CID_VFLIP, | ||
| 232 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 233 | .name = "vertical flip", | ||
| 234 | .minimum = 0, | ||
| 235 | .maximum = 1, | ||
| 236 | .step = 1, | ||
| 237 | .default_value = 0 | ||
| 238 | }, | ||
| 239 | .set = ov9650_set_vflip, | ||
| 240 | .get = ov9650_get_vflip | ||
| 241 | }, { | ||
| 242 | { | ||
| 243 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
| 244 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 245 | .name = "auto white balance", | ||
| 246 | .minimum = 0, | ||
| 247 | .maximum = 1, | ||
| 248 | .step = 1, | ||
| 249 | .default_value = 0 | ||
| 250 | }, | ||
| 251 | .set = ov9650_set_auto_white_balance, | ||
| 252 | .get = ov9650_get_auto_white_balance | ||
| 253 | }, { | ||
| 254 | { | ||
| 255 | .id = V4L2_CID_AUTOGAIN, | ||
| 256 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 257 | .name = "auto gain control", | ||
| 258 | .minimum = 0, | ||
| 259 | .maximum = 1, | ||
| 260 | .step = 1, | ||
| 261 | .default_value = 0 | ||
| 262 | }, | ||
| 263 | .set = ov9650_set_auto_gain, | ||
| 264 | .get = ov9650_get_auto_gain | ||
| 265 | } | ||
| 266 | }, | ||
| 267 | |||
| 268 | .nmodes = 1, | ||
| 269 | .modes = { | ||
| 270 | { | ||
| 271 | M5602_DEFAULT_FRAME_WIDTH, | ||
| 272 | M5602_DEFAULT_FRAME_HEIGHT, | ||
| 273 | V4L2_PIX_FMT_SBGGR8, | ||
| 274 | V4L2_FIELD_NONE, | ||
| 275 | .sizeimage = | ||
| 276 | M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, | ||
| 277 | .bytesperline = M5602_DEFAULT_FRAME_WIDTH, | ||
| 278 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 279 | .priv = 1 | ||
| 280 | } | ||
| 281 | } | ||
| 282 | }; | ||
| 283 | |||
| 284 | static const unsigned char preinit_ov9650[][3] = | ||
| 285 | { | ||
| 286 | /* [INITCAM] */ | ||
| 287 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, | ||
| 288 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, | ||
| 289 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
| 290 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 291 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 292 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, | ||
| 293 | |||
| 294 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08}, | ||
| 295 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
| 296 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
| 297 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
| 298 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
| 299 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, | ||
| 300 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, | ||
| 301 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a}, | ||
| 302 | /* Reset chip */ | ||
| 303 | {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, | ||
| 304 | /* Enable double clock */ | ||
| 305 | {SENSOR, OV9650_CLKRC, 0x80}, | ||
| 306 | /* Do something out of spec with the power */ | ||
| 307 | {SENSOR, OV9650_OFON, 0x40} | ||
| 308 | }; | ||
| 309 | |||
| 310 | static const unsigned char init_ov9650[][3] = | ||
| 311 | { | ||
| 312 | /* [INITCAM] */ | ||
| 313 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, | ||
| 314 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, | ||
| 315 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
| 316 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 317 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 318 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, | ||
| 319 | |||
| 320 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08}, | ||
| 321 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
| 322 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
| 323 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
| 324 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
| 325 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00}, | ||
| 326 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, | ||
| 327 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a}, | ||
| 328 | /* Reset chip */ | ||
| 329 | {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET}, | ||
| 330 | /* Enable double clock */ | ||
| 331 | {SENSOR, OV9650_CLKRC, 0x80}, | ||
| 332 | /* Do something out of spec with the power */ | ||
| 333 | {SENSOR, OV9650_OFON, 0x40}, | ||
| 334 | |||
| 335 | /* Set QQVGA */ | ||
| 336 | {SENSOR, OV9650_COM1, 0x20}, | ||
| 337 | /* Set fast AGC/AEC algorithm with unlimited step size */ | ||
| 338 | {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC | | ||
| 339 | OV9650_AEC_UNLIM_STEP_SIZE | | ||
| 340 | OV9650_AWB_EN | OV9650_AGC_EN}, | ||
| 341 | |||
| 342 | {SENSOR, OV9650_CHLF, 0x10}, | ||
| 343 | {SENSOR, OV9650_ARBLM, 0xbf}, | ||
| 344 | {SENSOR, OV9650_ACOM38, 0x81}, | ||
| 345 | /* Turn off color matrix coefficient double option */ | ||
| 346 | {SENSOR, OV9650_COM16, 0x00}, | ||
| 347 | /* Enable color matrix for RGB/YUV, Delay Y channel, | ||
| 348 | set output Y/UV delay to 1 */ | ||
| 349 | {SENSOR, OV9650_COM13, 0x19}, | ||
| 350 | /* Enable digital BLC, Set output mode to U Y V Y */ | ||
| 351 | {SENSOR, OV9650_TSLB, 0x0c}, | ||
| 352 | /* Limit the AGC/AEC stable upper region */ | ||
| 353 | {SENSOR, OV9650_COM24, 0x00}, | ||
| 354 | /* Enable HREF and some out of spec things */ | ||
| 355 | {SENSOR, OV9650_COM12, 0x73}, | ||
| 356 | /* Set all DBLC offset signs to positive and | ||
| 357 | do some out of spec stuff */ | ||
| 358 | {SENSOR, OV9650_DBLC1, 0xdf}, | ||
| 359 | {SENSOR, OV9650_COM21, 0x06}, | ||
| 360 | {SENSOR, OV9650_RSVD35, 0x91}, | ||
| 361 | /* Necessary, no camera stream without it */ | ||
| 362 | {SENSOR, OV9650_RSVD16, 0x06}, | ||
| 363 | {SENSOR, OV9650_RSVD94, 0x99}, | ||
| 364 | {SENSOR, OV9650_RSVD95, 0x99}, | ||
| 365 | {SENSOR, OV9650_RSVD96, 0x04}, | ||
| 366 | /* Enable full range output */ | ||
| 367 | {SENSOR, OV9650_COM15, 0x0}, | ||
| 368 | /* Enable HREF at optical black, enable ADBLC bias, | ||
| 369 | enable ADBLC, reset timings at format change */ | ||
| 370 | {SENSOR, OV9650_COM6, 0x4b}, | ||
| 371 | /* Subtract 32 from the B channel bias */ | ||
| 372 | {SENSOR, OV9650_BBIAS, 0xa0}, | ||
| 373 | /* Subtract 32 from the Gb channel bias */ | ||
| 374 | {SENSOR, OV9650_GbBIAS, 0xa0}, | ||
| 375 | /* Do not bypass the analog BLC and to some out of spec stuff */ | ||
| 376 | {SENSOR, OV9650_Gr_COM, 0x00}, | ||
| 377 | /* Subtract 32 from the R channel bias */ | ||
| 378 | {SENSOR, OV9650_RBIAS, 0xa0}, | ||
| 379 | /* Subtract 32 from the R channel bias */ | ||
| 380 | {SENSOR, OV9650_RBIAS, 0x0}, | ||
| 381 | {SENSOR, OV9650_COM26, 0x80}, | ||
| 382 | {SENSOR, OV9650_ACOMA9, 0x98}, | ||
| 383 | /* Set the AGC/AEC stable region upper limit */ | ||
| 384 | {SENSOR, OV9650_AEW, 0x68}, | ||
| 385 | /* Set the AGC/AEC stable region lower limit */ | ||
| 386 | {SENSOR, OV9650_AEB, 0x5c}, | ||
| 387 | /* Set the high and low limit nibbles to 3 */ | ||
| 388 | {SENSOR, OV9650_VPT, 0xc3}, | ||
| 389 | /* Set the Automatic Gain Ceiling (AGC) to 128x, | ||
| 390 | drop VSYNC at frame drop, | ||
| 391 | limit exposure timing, | ||
| 392 | drop frame when the AEC step is larger than the exposure gap */ | ||
| 393 | {SENSOR, OV9650_COM9, 0x6e}, | ||
| 394 | /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync) | ||
| 395 | and set PWDN to SLVS (slave mode vertical sync) */ | ||
| 396 | {SENSOR, OV9650_COM10, 0x42}, | ||
| 397 | /* Set horizontal column start high to default value */ | ||
| 398 | {SENSOR, OV9650_HSTART, 0x1a}, | ||
| 399 | /* Set horizontal column end */ | ||
| 400 | {SENSOR, OV9650_HSTOP, 0xbf}, | ||
| 401 | /* Complementing register to the two writes above */ | ||
| 402 | {SENSOR, OV9650_HREF, 0xb2}, | ||
| 403 | /* Set vertical row start high bits */ | ||
| 404 | {SENSOR, OV9650_VSTRT, 0x02}, | ||
| 405 | /* Set vertical row end low bits */ | ||
| 406 | {SENSOR, OV9650_VSTOP, 0x7e}, | ||
| 407 | /* Set complementing vertical frame control */ | ||
| 408 | {SENSOR, OV9650_VREF, 0x10}, | ||
| 409 | /* Set raw RGB output format with VGA resolution */ | ||
| 410 | {SENSOR, OV9650_COM7, OV9650_VGA_SELECT | | ||
| 411 | OV9650_RGB_SELECT | | ||
| 412 | OV9650_RAW_RGB_SELECT}, | ||
| 413 | {SENSOR, OV9650_ADC, 0x04}, | ||
| 414 | {SENSOR, OV9650_HV, 0x40}, | ||
| 415 | /* Enable denoise, and white-pixel erase */ | ||
| 416 | {SENSOR, OV9650_COM22, 0x23}, | ||
| 417 | |||
| 418 | /* Set the high bits of the exposure value */ | ||
| 419 | {SENSOR, OV9650_AECH, ((EXPOSURE_DEFAULT & 0xff00) >> 8)}, | ||
| 420 | |||
| 421 | /* Set the low bits of the exposure value */ | ||
| 422 | {SENSOR, OV9650_COM1, (EXPOSURE_DEFAULT & 0xff)}, | ||
| 423 | {SENSOR, OV9650_GAIN, GAIN_DEFAULT}, | ||
| 424 | {SENSOR, OV9650_BLUE, BLUE_GAIN_DEFAULT}, | ||
| 425 | {SENSOR, OV9650_RED, RED_GAIN_DEFAULT}, | ||
| 426 | |||
| 427 | {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL}, | ||
| 428 | {SENSOR, OV9650_COM5, OV9650_SYSTEM_CLK_SEL}, | ||
| 429 | |||
| 430 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82}, | ||
| 431 | {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00}, | ||
| 432 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, | ||
| 433 | {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00}, | ||
| 434 | {BRIDGE, M5602_XB_SIG_INI, 0x01}, | ||
| 435 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 436 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x09}, | ||
| 437 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 438 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, | ||
| 439 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0}, | ||
| 440 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 441 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
| 442 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x5e}, | ||
| 443 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, | ||
| 444 | {BRIDGE, M5602_XB_HSYNC_PARA, 0xde} | ||
| 445 | }; | ||
| 446 | |||
| 447 | static const unsigned char power_down_ov9650[][3] = | ||
| 448 | { | ||
| 449 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
| 450 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 451 | {SENSOR, OV9650_COM7, 0x80}, | ||
| 452 | {SENSOR, OV9650_OFON, 0xf4}, | ||
| 453 | {SENSOR, OV9650_MVFP, 0x80}, | ||
| 454 | {SENSOR, OV9650_DBLV, 0x3f}, | ||
| 455 | {SENSOR, OV9650_RSVD36, 0x49}, | ||
| 456 | {SENSOR, OV9650_COM7, 0x05}, | ||
| 457 | |||
| 458 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
| 459 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
| 460 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
| 461 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x06}, | ||
| 462 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, | ||
| 463 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
| 464 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0} | ||
| 465 | }; | ||
| 466 | |||
| 467 | /* Vertically and horizontally flips the image if matched, needed for machines | ||
| 468 | where the sensor is mounted upside down */ | ||
| 469 | static | ||
| 470 | const | ||
| 471 | struct dmi_system_id ov9650_flip_dmi_table[] = { | ||
| 472 | { | ||
| 473 | .ident = "ASUS A6VC", | ||
| 474 | .matches = { | ||
| 475 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
| 476 | DMI_MATCH(DMI_PRODUCT_NAME, "A6VC") | ||
| 477 | } | ||
| 478 | }, | ||
| 479 | { | ||
| 480 | .ident = "ASUS A6VM", | ||
| 481 | .matches = { | ||
| 482 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
| 483 | DMI_MATCH(DMI_PRODUCT_NAME, "A6VM") | ||
| 484 | } | ||
| 485 | }, | ||
| 486 | { | ||
| 487 | .ident = "ASUS A6JC", | ||
| 488 | .matches = { | ||
| 489 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
| 490 | DMI_MATCH(DMI_PRODUCT_NAME, "A6JC") | ||
| 491 | } | ||
| 492 | }, | ||
| 493 | { | ||
| 494 | .ident = "ASUS A6Kt", | ||
| 495 | .matches = { | ||
| 496 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
| 497 | DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt") | ||
| 498 | } | ||
| 499 | }, | ||
| 500 | { } | ||
| 501 | }; | ||
| 502 | |||
| 503 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c new file mode 100644 index 000000000000..08c015bde115 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_po1030.c | |||
| @@ -0,0 +1,336 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the po1030 sensor | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008 Erik Andren | ||
| 5 | * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include "m5602_po1030.h" | ||
| 20 | |||
| 21 | int po1030_probe(struct sd *sd) | ||
| 22 | { | ||
| 23 | u8 prod_id = 0, ver_id = 0, i; | ||
| 24 | |||
| 25 | if (force_sensor) { | ||
| 26 | if (force_sensor == PO1030_SENSOR) { | ||
| 27 | info("Forcing a %s sensor", po1030.name); | ||
| 28 | goto sensor_found; | ||
| 29 | } | ||
| 30 | /* If we want to force another sensor, don't try to probe this | ||
| 31 | * one */ | ||
| 32 | return -ENODEV; | ||
| 33 | } | ||
| 34 | |||
| 35 | info("Probing for a po1030 sensor"); | ||
| 36 | |||
| 37 | /* Run the pre-init to actually probe the unit */ | ||
| 38 | for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) { | ||
| 39 | u8 data = preinit_po1030[i][2]; | ||
| 40 | if (preinit_po1030[i][0] == SENSOR) | ||
| 41 | po1030_write_sensor(sd, | ||
| 42 | preinit_po1030[i][1], &data, 1); | ||
| 43 | else | ||
| 44 | m5602_write_bridge(sd, preinit_po1030[i][1], data); | ||
| 45 | } | ||
| 46 | |||
| 47 | if (po1030_read_sensor(sd, 0x3, &prod_id, 1)) | ||
| 48 | return -ENODEV; | ||
| 49 | |||
| 50 | if (po1030_read_sensor(sd, 0x4, &ver_id, 1)) | ||
| 51 | return -ENODEV; | ||
| 52 | |||
| 53 | if ((prod_id == 0x02) && (ver_id == 0xef)) { | ||
| 54 | info("Detected a po1030 sensor"); | ||
| 55 | goto sensor_found; | ||
| 56 | } | ||
| 57 | return -ENODEV; | ||
| 58 | |||
| 59 | sensor_found: | ||
| 60 | sd->gspca_dev.cam.cam_mode = po1030.modes; | ||
| 61 | sd->gspca_dev.cam.nmodes = po1030.nmodes; | ||
| 62 | sd->desc->ctrls = po1030.ctrls; | ||
| 63 | sd->desc->nctrls = po1030.nctrls; | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | int po1030_read_sensor(struct sd *sd, const u8 address, | ||
| 68 | u8 *i2c_data, const u8 len) | ||
| 69 | { | ||
| 70 | int err, i; | ||
| 71 | |||
| 72 | do { | ||
| 73 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
| 74 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
| 75 | |||
| 76 | m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, | ||
| 77 | sd->sensor->i2c_slave_id); | ||
| 78 | m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); | ||
| 79 | m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len); | ||
| 80 | m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08); | ||
| 81 | |||
| 82 | for (i = 0; i < len; i++) { | ||
| 83 | err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); | ||
| 84 | |||
| 85 | PDEBUG(DBG_TRACE, "Reading sensor register " | ||
| 86 | "0x%x containing 0x%x ", address, *i2c_data); | ||
| 87 | } | ||
| 88 | return (err < 0) ? err : 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | int po1030_write_sensor(struct sd *sd, const u8 address, | ||
| 92 | u8 *i2c_data, const u8 len) | ||
| 93 | { | ||
| 94 | int err, i; | ||
| 95 | u8 *p; | ||
| 96 | struct usb_device *udev = sd->gspca_dev.dev; | ||
| 97 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
| 98 | |||
| 99 | /* The po1030 only supports one byte writes */ | ||
| 100 | if (len > 1 || !len) | ||
| 101 | return -EINVAL; | ||
| 102 | |||
| 103 | memcpy(buf, sensor_urb_skeleton, sizeof(sensor_urb_skeleton)); | ||
| 104 | |||
| 105 | buf[11] = sd->sensor->i2c_slave_id; | ||
| 106 | buf[15] = address; | ||
| 107 | |||
| 108 | p = buf + 16; | ||
| 109 | |||
| 110 | /* Copy a four byte write sequence for each byte to be written to */ | ||
| 111 | for (i = 0; i < len; i++) { | ||
| 112 | memcpy(p, sensor_urb_skeleton + 16, 4); | ||
| 113 | p[3] = i2c_data[i]; | ||
| 114 | p += 4; | ||
| 115 | PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", | ||
| 116 | address, i2c_data[i]); | ||
| 117 | } | ||
| 118 | |||
| 119 | /* Copy the footer */ | ||
| 120 | memcpy(p, sensor_urb_skeleton + 20, 4); | ||
| 121 | |||
| 122 | /* Set the total length */ | ||
| 123 | p[3] = 0x10 + len; | ||
| 124 | |||
| 125 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 126 | 0x04, 0x40, 0x19, | ||
| 127 | 0x0000, buf, | ||
| 128 | 20 + len * 4, M5602_URB_MSG_TIMEOUT); | ||
| 129 | |||
| 130 | return (err < 0) ? err : 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | int po1030_init(struct sd *sd) | ||
| 134 | { | ||
| 135 | int i, err = 0; | ||
| 136 | |||
| 137 | /* Init the sensor */ | ||
| 138 | for (i = 0; i < ARRAY_SIZE(init_po1030); i++) { | ||
| 139 | u8 data[2] = {0x00, 0x00}; | ||
| 140 | |||
| 141 | switch (init_po1030[i][0]) { | ||
| 142 | case BRIDGE: | ||
| 143 | err = m5602_write_bridge(sd, | ||
| 144 | init_po1030[i][1], | ||
| 145 | init_po1030[i][2]); | ||
| 146 | break; | ||
| 147 | |||
| 148 | case SENSOR: | ||
| 149 | data[0] = init_po1030[i][2]; | ||
| 150 | err = po1030_write_sensor(sd, | ||
| 151 | init_po1030[i][1], data, 1); | ||
| 152 | break; | ||
| 153 | |||
| 154 | case SENSOR_LONG: | ||
| 155 | data[0] = init_po1030[i][2]; | ||
| 156 | data[1] = init_po1030[i][3]; | ||
| 157 | err = po1030_write_sensor(sd, | ||
| 158 | init_po1030[i][1], data, 2); | ||
| 159 | break; | ||
| 160 | default: | ||
| 161 | info("Invalid stream command, exiting init"); | ||
| 162 | return -EINVAL; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | if (dump_sensor) | ||
| 167 | po1030_dump_registers(sd); | ||
| 168 | |||
| 169 | return (err < 0) ? err : 0; | ||
| 170 | } | ||
| 171 | |||
| 172 | int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 173 | { | ||
| 174 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 175 | u8 i2c_data; | ||
| 176 | int err; | ||
| 177 | |||
| 178 | err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_H, | ||
| 179 | &i2c_data, 1); | ||
| 180 | if (err < 0) | ||
| 181 | goto out; | ||
| 182 | *val = (i2c_data << 8); | ||
| 183 | |||
| 184 | err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_M, | ||
| 185 | &i2c_data, 1); | ||
| 186 | *val |= i2c_data; | ||
| 187 | |||
| 188 | PDEBUG(DBG_V4L2_CID, "Exposure read as %d", *val); | ||
| 189 | out: | ||
| 190 | return (err < 0) ? err : 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | ||
| 194 | { | ||
| 195 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 196 | u8 i2c_data; | ||
| 197 | int err; | ||
| 198 | |||
| 199 | PDEBUG(DBG_V4L2, "Set exposure to %d", val & 0xffff); | ||
| 200 | |||
| 201 | i2c_data = ((val & 0xff00) >> 8); | ||
| 202 | PDEBUG(DBG_V4L2, "Set exposure to high byte to 0x%x", | ||
| 203 | i2c_data); | ||
| 204 | |||
| 205 | err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_H, | ||
| 206 | &i2c_data, 1); | ||
| 207 | if (err < 0) | ||
| 208 | goto out; | ||
| 209 | |||
| 210 | i2c_data = (val & 0xff); | ||
| 211 | PDEBUG(DBG_V4L2, "Set exposure to low byte to 0x%x", | ||
| 212 | i2c_data); | ||
| 213 | err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_M, | ||
| 214 | &i2c_data, 1); | ||
| 215 | |||
| 216 | out: | ||
| 217 | return (err < 0) ? err : 0; | ||
| 218 | } | ||
| 219 | |||
| 220 | int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 221 | { | ||
| 222 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 223 | u8 i2c_data; | ||
| 224 | int err; | ||
| 225 | |||
| 226 | err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN, | ||
| 227 | &i2c_data, 1); | ||
| 228 | *val = i2c_data; | ||
| 229 | PDEBUG(DBG_V4L2_CID, "Read global gain %d", *val); | ||
| 230 | |||
| 231 | return (err < 0) ? err : 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
| 235 | { | ||
| 236 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 237 | u8 i2c_data; | ||
| 238 | int err; | ||
| 239 | |||
| 240 | i2c_data = val & 0xff; | ||
| 241 | PDEBUG(DBG_V4L2, "Set global gain to %d", i2c_data); | ||
| 242 | err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN, | ||
| 243 | &i2c_data, 1); | ||
| 244 | return (err < 0) ? err : 0; | ||
| 245 | } | ||
| 246 | |||
| 247 | int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 248 | { | ||
| 249 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 250 | u8 i2c_data; | ||
| 251 | int err; | ||
| 252 | |||
| 253 | err = po1030_read_sensor(sd, PO1030_REG_RED_GAIN, | ||
| 254 | &i2c_data, 1); | ||
| 255 | *val = i2c_data; | ||
| 256 | PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val); | ||
| 257 | return (err < 0) ? err : 0; | ||
| 258 | } | ||
| 259 | |||
| 260 | int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
| 261 | { | ||
| 262 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 263 | u8 i2c_data; | ||
| 264 | int err; | ||
| 265 | |||
| 266 | i2c_data = val & 0xff; | ||
| 267 | PDEBUG(DBG_V4L2, "Set red gain to %d", i2c_data); | ||
| 268 | err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN, | ||
| 269 | &i2c_data, 1); | ||
| 270 | return (err < 0) ? err : 0; | ||
| 271 | } | ||
| 272 | |||
| 273 | int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 274 | { | ||
| 275 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 276 | u8 i2c_data; | ||
| 277 | int err; | ||
| 278 | |||
| 279 | err = po1030_read_sensor(sd, PO1030_REG_BLUE_GAIN, | ||
| 280 | &i2c_data, 1); | ||
| 281 | *val = i2c_data; | ||
| 282 | PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val); | ||
| 283 | |||
| 284 | return (err < 0) ? err : 0; | ||
| 285 | } | ||
| 286 | |||
| 287 | int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) | ||
| 288 | { | ||
| 289 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 290 | u8 i2c_data; | ||
| 291 | int err; | ||
| 292 | i2c_data = val & 0xff; | ||
| 293 | PDEBUG(DBG_V4L2, "Set blue gain to %d", i2c_data); | ||
| 294 | err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN, | ||
| 295 | &i2c_data, 1); | ||
| 296 | |||
| 297 | return (err < 0) ? err : 0; | ||
| 298 | } | ||
| 299 | |||
| 300 | int po1030_power_down(struct sd *sd) | ||
| 301 | { | ||
| 302 | return 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | void po1030_dump_registers(struct sd *sd) | ||
| 306 | { | ||
| 307 | int address; | ||
| 308 | u8 value = 0; | ||
| 309 | |||
| 310 | info("Dumping the po1030 sensor core registers"); | ||
| 311 | for (address = 0; address < 0x7f; address++) { | ||
| 312 | po1030_read_sensor(sd, address, &value, 1); | ||
| 313 | info("register 0x%x contains 0x%x", | ||
| 314 | address, value); | ||
| 315 | } | ||
| 316 | |||
| 317 | info("po1030 register state dump complete"); | ||
| 318 | |||
| 319 | info("Probing for which registers that are read/write"); | ||
| 320 | for (address = 0; address < 0xff; address++) { | ||
| 321 | u8 old_value, ctrl_value; | ||
| 322 | u8 test_value[2] = {0xff, 0xff}; | ||
| 323 | |||
| 324 | po1030_read_sensor(sd, address, &old_value, 1); | ||
| 325 | po1030_write_sensor(sd, address, test_value, 1); | ||
| 326 | po1030_read_sensor(sd, address, &ctrl_value, 1); | ||
| 327 | |||
| 328 | if (ctrl_value == test_value[0]) | ||
| 329 | info("register 0x%x is writeable", address); | ||
| 330 | else | ||
| 331 | info("register 0x%x is read only", address); | ||
| 332 | |||
| 333 | /* Restore original value */ | ||
| 334 | po1030_write_sensor(sd, address, &old_value, 1); | ||
| 335 | } | ||
| 336 | } | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h new file mode 100644 index 000000000000..68f34c97bf44 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_po1030.h | |||
| @@ -0,0 +1,478 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the po1030 sensor. | ||
| 3 | * This is probably a pixel plus sensor but we haven't identified it yet | ||
| 4 | * | ||
| 5 | * Copyright (c) 2008 Erik Andren | ||
| 6 | * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 7 | * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 8 | * | ||
| 9 | * Portions of code to USB interface and ALi driver software, | ||
| 10 | * Copyright (c) 2006 Willem Duinker | ||
| 11 | * v4l2 interface modeled after the V4L2 driver | ||
| 12 | * for SN9C10x PC Camera Controllers | ||
| 13 | * | ||
| 14 | * Register defines taken from Pascal Stangs Proxycon Armlib | ||
| 15 | * | ||
| 16 | * This program is free software; you can redistribute it and/or | ||
| 17 | * modify it under the terms of the GNU General Public License as | ||
| 18 | * published by the Free Software Foundation, version 2. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef M5602_PO1030_H_ | ||
| 23 | #define M5602_PO1030_H_ | ||
| 24 | |||
| 25 | #include "m5602_sensor.h" | ||
| 26 | |||
| 27 | /*****************************************************************************/ | ||
| 28 | |||
| 29 | #define PO1030_REG_DEVID_H 0x00 | ||
| 30 | #define PO1030_REG_DEVID_L 0x01 | ||
| 31 | #define PO1030_REG_FRAMEWIDTH_H 0x04 | ||
| 32 | #define PO1030_REG_FRAMEWIDTH_L 0x05 | ||
| 33 | #define PO1030_REG_FRAMEHEIGHT_H 0x06 | ||
| 34 | #define PO1030_REG_FRAMEHEIGHT_L 0x07 | ||
| 35 | #define PO1030_REG_WINDOWX_H 0x08 | ||
| 36 | #define PO1030_REG_WINDOWX_L 0x09 | ||
| 37 | #define PO1030_REG_WINDOWY_H 0x0a | ||
| 38 | #define PO1030_REG_WINDOWY_L 0x0b | ||
| 39 | #define PO1030_REG_WINDOWWIDTH_H 0x0c | ||
| 40 | #define PO1030_REG_WINDOWWIDTH_L 0x0d | ||
| 41 | #define PO1030_REG_WINDOWHEIGHT_H 0x0e | ||
| 42 | #define PO1030_REG_WINDOWHEIGHT_L 0x0f | ||
| 43 | |||
| 44 | #define PO1030_REG_GLOBALIBIAS 0x12 | ||
| 45 | #define PO1030_REG_PIXELIBIAS 0x13 | ||
| 46 | |||
| 47 | #define PO1030_REG_GLOBALGAIN 0x15 | ||
| 48 | #define PO1030_REG_RED_GAIN 0x16 | ||
| 49 | #define PO1030_REG_GREEN_1_GAIN 0x17 | ||
| 50 | #define PO1030_REG_BLUE_GAIN 0x18 | ||
| 51 | #define PO1030_REG_GREEN_2_GAIN 0x19 | ||
| 52 | |||
| 53 | #define PO1030_REG_INTEGLINES_H 0x1a | ||
| 54 | #define PO1030_REG_INTEGLINES_M 0x1b | ||
| 55 | #define PO1030_REG_INTEGLINES_L 0x1c | ||
| 56 | |||
| 57 | #define PO1030_REG_CONTROL1 0x1d | ||
| 58 | #define PO1030_REG_CONTROL2 0x1e | ||
| 59 | #define PO1030_REG_CONTROL3 0x1f | ||
| 60 | #define PO1030_REG_CONTROL4 0x20 | ||
| 61 | |||
| 62 | #define PO1030_REG_PERIOD50_H 0x23 | ||
| 63 | #define PO1030_REG_PERIOD50_L 0x24 | ||
| 64 | #define PO1030_REG_PERIOD60_H 0x25 | ||
| 65 | #define PO1030_REG_PERIOD60_L 0x26 | ||
| 66 | #define PO1030_REG_REGCLK167 0x27 | ||
| 67 | #define PO1030_REG_DELTA50 0x28 | ||
| 68 | #define PO1030_REG_DELTA60 0x29 | ||
| 69 | |||
| 70 | #define PO1030_REG_ADCOFFSET 0x2c | ||
| 71 | |||
| 72 | /* Gamma Correction Coeffs */ | ||
| 73 | #define PO1030_REG_GC0 0x2d | ||
| 74 | #define PO1030_REG_GC1 0x2e | ||
| 75 | #define PO1030_REG_GC2 0x2f | ||
| 76 | #define PO1030_REG_GC3 0x30 | ||
| 77 | #define PO1030_REG_GC4 0x31 | ||
| 78 | #define PO1030_REG_GC5 0x32 | ||
| 79 | #define PO1030_REG_GC6 0x33 | ||
| 80 | #define PO1030_REG_GC7 0x34 | ||
| 81 | |||
| 82 | /* Color Transform Matrix */ | ||
| 83 | #define PO1030_REG_CT0 0x35 | ||
| 84 | #define PO1030_REG_CT1 0x36 | ||
| 85 | #define PO1030_REG_CT2 0x37 | ||
| 86 | #define PO1030_REG_CT3 0x38 | ||
| 87 | #define PO1030_REG_CT4 0x39 | ||
| 88 | #define PO1030_REG_CT5 0x3a | ||
| 89 | #define PO1030_REG_CT6 0x3b | ||
| 90 | #define PO1030_REG_CT7 0x3c | ||
| 91 | #define PO1030_REG_CT8 0x3d | ||
| 92 | |||
| 93 | #define PO1030_REG_AUTOCTRL1 0x3e | ||
| 94 | #define PO1030_REG_AUTOCTRL2 0x3f | ||
| 95 | |||
| 96 | #define PO1030_REG_YTARGET 0x40 | ||
| 97 | #define PO1030_REG_GLOBALGAINMIN 0x41 | ||
| 98 | #define PO1030_REG_GLOBALGAINMAX 0x42 | ||
| 99 | |||
| 100 | /* Output format control */ | ||
| 101 | #define PO1030_REG_OUTFORMCTRL1 0x5a | ||
| 102 | #define PO1030_REG_OUTFORMCTRL2 0x5b | ||
| 103 | #define PO1030_REG_OUTFORMCTRL3 0x5c | ||
| 104 | #define PO1030_REG_OUTFORMCTRL4 0x5d | ||
| 105 | #define PO1030_REG_OUTFORMCTRL5 0x5e | ||
| 106 | |||
| 107 | /* Imaging coefficients */ | ||
| 108 | #define PO1030_REG_YBRIGHT 0x73 | ||
| 109 | #define PO1030_REG_YCONTRAST 0x74 | ||
| 110 | #define PO1030_REG_YSATURATION 0x75 | ||
| 111 | |||
| 112 | /*****************************************************************************/ | ||
| 113 | |||
| 114 | #define PO1030_GLOBAL_GAIN_DEFAULT 0x12 | ||
| 115 | #define PO1030_EXPOSURE_DEFAULT 0xf0ff | ||
| 116 | #define PO1030_BLUE_GAIN_DEFAULT 0x40 | ||
| 117 | #define PO1030_RED_GAIN_DEFAULT 0x40 | ||
| 118 | |||
| 119 | /*****************************************************************************/ | ||
| 120 | |||
| 121 | /* Kernel module parameters */ | ||
| 122 | extern int force_sensor; | ||
| 123 | extern int dump_sensor; | ||
| 124 | extern unsigned int m5602_debug; | ||
| 125 | |||
| 126 | int po1030_probe(struct sd *sd); | ||
| 127 | int po1030_init(struct sd *sd); | ||
| 128 | int po1030_power_down(struct sd *sd); | ||
| 129 | |||
| 130 | void po1030_dump_registers(struct sd *sd); | ||
| 131 | |||
| 132 | int po1030_read_sensor(struct sd *sd, const u8 address, | ||
| 133 | u8 *i2c_data, const u8 len); | ||
| 134 | int po1030_write_sensor(struct sd *sd, const u8 address, | ||
| 135 | u8 *i2c_data, const u8 len); | ||
| 136 | |||
| 137 | int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 138 | int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
| 139 | int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 140 | int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
| 141 | int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 142 | int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
| 143 | int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 144 | int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
| 145 | |||
| 146 | static struct m5602_sensor po1030 = { | ||
| 147 | .name = "PO1030", | ||
| 148 | |||
| 149 | .i2c_slave_id = 0xdc, | ||
| 150 | |||
| 151 | .probe = po1030_probe, | ||
| 152 | .init = po1030_init, | ||
| 153 | .power_down = po1030_power_down, | ||
| 154 | |||
| 155 | .nctrls = 4, | ||
| 156 | .ctrls = { | ||
| 157 | { | ||
| 158 | { | ||
| 159 | .id = V4L2_CID_GAIN, | ||
| 160 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 161 | .name = "gain", | ||
| 162 | .minimum = 0x00, | ||
| 163 | .maximum = 0xff, | ||
| 164 | .step = 0x1, | ||
| 165 | .default_value = PO1030_GLOBAL_GAIN_DEFAULT, | ||
| 166 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 167 | }, | ||
| 168 | .set = po1030_set_gain, | ||
| 169 | .get = po1030_get_gain | ||
| 170 | }, { | ||
| 171 | { | ||
| 172 | .id = V4L2_CID_EXPOSURE, | ||
| 173 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 174 | .name = "exposure", | ||
| 175 | .minimum = 0x00, | ||
| 176 | .maximum = 0xffff, | ||
| 177 | .step = 0x1, | ||
| 178 | .default_value = PO1030_EXPOSURE_DEFAULT, | ||
| 179 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 180 | }, | ||
| 181 | .set = po1030_set_exposure, | ||
| 182 | .get = po1030_get_exposure | ||
| 183 | }, { | ||
| 184 | { | ||
| 185 | .id = V4L2_CID_RED_BALANCE, | ||
| 186 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 187 | .name = "red balance", | ||
| 188 | .minimum = 0x00, | ||
| 189 | .maximum = 0xff, | ||
| 190 | .step = 0x1, | ||
| 191 | .default_value = PO1030_RED_GAIN_DEFAULT, | ||
| 192 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 193 | }, | ||
| 194 | .set = po1030_set_red_balance, | ||
| 195 | .get = po1030_get_red_balance | ||
| 196 | }, { | ||
| 197 | { | ||
| 198 | .id = V4L2_CID_BLUE_BALANCE, | ||
| 199 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 200 | .name = "blue balance", | ||
| 201 | .minimum = 0x00, | ||
| 202 | .maximum = 0xff, | ||
| 203 | .step = 0x1, | ||
| 204 | .default_value = PO1030_BLUE_GAIN_DEFAULT, | ||
| 205 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 206 | }, | ||
| 207 | .set = po1030_set_blue_balance, | ||
| 208 | .get = po1030_get_blue_balance | ||
| 209 | } | ||
| 210 | }, | ||
| 211 | .nmodes = 1, | ||
| 212 | .modes = { | ||
| 213 | { | ||
| 214 | M5602_DEFAULT_FRAME_WIDTH, | ||
| 215 | M5602_DEFAULT_FRAME_HEIGHT, | ||
| 216 | V4L2_PIX_FMT_SBGGR8, | ||
| 217 | V4L2_FIELD_NONE, | ||
| 218 | .sizeimage = | ||
| 219 | M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, | ||
| 220 | .bytesperline = M5602_DEFAULT_FRAME_WIDTH, | ||
| 221 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 222 | .priv = 1 | ||
| 223 | } | ||
| 224 | } | ||
| 225 | }; | ||
| 226 | |||
| 227 | static const unsigned char preinit_po1030[][3] = | ||
| 228 | { | ||
| 229 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, | ||
| 230 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, | ||
| 231 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
| 232 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 233 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 234 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, | ||
| 235 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, | ||
| 236 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 237 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
| 238 | |||
| 239 | {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, | ||
| 240 | |||
| 241 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
| 242 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
| 243 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
| 244 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
| 245 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, | ||
| 246 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
| 247 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 248 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, | ||
| 249 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 250 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 251 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
| 252 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, | ||
| 253 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, | ||
| 254 | {BRIDGE, M5602_XB_SIG_INI, 0x01}, | ||
| 255 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 256 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, | ||
| 257 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 258 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 259 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, | ||
| 260 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, | ||
| 261 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 262 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 263 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
| 264 | {BRIDGE, M5602_XB_SIG_INI, 0x02}, | ||
| 265 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
| 266 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
| 267 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, | ||
| 268 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, | ||
| 269 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
| 270 | |||
| 271 | {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, | ||
| 272 | |||
| 273 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
| 274 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
| 275 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
| 276 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
| 277 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, | ||
| 278 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
| 279 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 280 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
| 281 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 282 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 283 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
| 284 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
| 285 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00} | ||
| 286 | }; | ||
| 287 | |||
| 288 | static const unsigned char init_po1030[][4] = | ||
| 289 | { | ||
| 290 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02}, | ||
| 291 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0}, | ||
| 292 | /*sequence 1*/ | ||
| 293 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
| 294 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 295 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 296 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d}, | ||
| 297 | |||
| 298 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00}, | ||
| 299 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 300 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
| 301 | /*end of sequence 1*/ | ||
| 302 | |||
| 303 | /*sequence 2 (same as stop sequence)*/ | ||
| 304 | {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, | ||
| 305 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
| 306 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
| 307 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
| 308 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
| 309 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, | ||
| 310 | |||
| 311 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
| 312 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 313 | /*end of sequence 2*/ | ||
| 314 | |||
| 315 | /*sequence 5*/ | ||
| 316 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, | ||
| 317 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 318 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 319 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
| 320 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, | ||
| 321 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, | ||
| 322 | {BRIDGE, M5602_XB_SIG_INI, 0x01}, | ||
| 323 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 324 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, | ||
| 325 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 326 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 327 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, | ||
| 328 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, | ||
| 329 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 330 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 331 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
| 332 | {BRIDGE, M5602_XB_SIG_INI, 0x02}, | ||
| 333 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
| 334 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
| 335 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, | ||
| 336 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x87}, | ||
| 337 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
| 338 | /*end of sequence 5*/ | ||
| 339 | |||
| 340 | /*sequence 2 stop */ | ||
| 341 | {SENSOR, PO1030_REG_AUTOCTRL2, 0x24}, | ||
| 342 | |||
| 343 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
| 344 | {BRIDGE, M5602_XB_GPIO_DAT, 0x04}, | ||
| 345 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
| 346 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06}, | ||
| 347 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02}, | ||
| 348 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04}, | ||
| 349 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 350 | /*end of sequence 2 stop */ | ||
| 351 | |||
| 352 | /* --------------------------------- | ||
| 353 | * end of init - begin of start | ||
| 354 | * --------------------------------- */ | ||
| 355 | |||
| 356 | /*sequence 3*/ | ||
| 357 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
| 358 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 359 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 360 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
| 361 | /*end of sequence 3*/ | ||
| 362 | /*sequence 4*/ | ||
| 363 | {BRIDGE, M5602_XB_GPIO_DIR, 0x05}, | ||
| 364 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00}, | ||
| 365 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06}, | ||
| 366 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}, | ||
| 367 | |||
| 368 | {SENSOR, PO1030_REG_AUTOCTRL2, 0x04}, | ||
| 369 | |||
| 370 | /* Set the width to 751 */ | ||
| 371 | {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02}, | ||
| 372 | {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef}, | ||
| 373 | |||
| 374 | /* Set the height to 540 */ | ||
| 375 | {SENSOR, PO1030_REG_FRAMEHEIGHT_H, 0x02}, | ||
| 376 | {SENSOR, PO1030_REG_FRAMEHEIGHT_L, 0x1c}, | ||
| 377 | |||
| 378 | /* Set the x window to 1 */ | ||
| 379 | {SENSOR, PO1030_REG_WINDOWX_H, 0x00}, | ||
| 380 | {SENSOR, PO1030_REG_WINDOWX_L, 0x01}, | ||
| 381 | |||
| 382 | /* Set the y window to 1 */ | ||
| 383 | {SENSOR, PO1030_REG_WINDOWY_H, 0x00}, | ||
| 384 | {SENSOR, PO1030_REG_WINDOWX_L, 0x01}, | ||
| 385 | |||
| 386 | {SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02}, | ||
| 387 | {SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87}, | ||
| 388 | {SENSOR, PO1030_REG_WINDOWHEIGHT_H, 0x01}, | ||
| 389 | {SENSOR, PO1030_REG_WINDOWHEIGHT_L, 0xe3}, | ||
| 390 | |||
| 391 | {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04}, | ||
| 392 | {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04}, | ||
| 393 | {SENSOR, PO1030_REG_AUTOCTRL1, 0x08}, | ||
| 394 | {SENSOR, PO1030_REG_CONTROL2, 0x03}, | ||
| 395 | {SENSOR, 0x21, 0x90}, | ||
| 396 | {SENSOR, PO1030_REG_YTARGET, 0x60}, | ||
| 397 | {SENSOR, 0x59, 0x13}, | ||
| 398 | {SENSOR, PO1030_REG_OUTFORMCTRL1, 0x40}, | ||
| 399 | {SENSOR, 0x5f, 0x00}, | ||
| 400 | {SENSOR, 0x60, 0x80}, | ||
| 401 | {SENSOR, 0x78, 0x14}, | ||
| 402 | {SENSOR, 0x6f, 0x01}, | ||
| 403 | {SENSOR, PO1030_REG_CONTROL1, 0x18}, | ||
| 404 | {SENSOR, PO1030_REG_GLOBALGAINMAX, 0x14}, | ||
| 405 | {SENSOR, 0x63, 0x38}, | ||
| 406 | {SENSOR, 0x64, 0x38}, | ||
| 407 | {SENSOR, PO1030_REG_CONTROL1, 0x58}, | ||
| 408 | {SENSOR, PO1030_REG_RED_GAIN, 0x30}, | ||
| 409 | {SENSOR, PO1030_REG_GREEN_1_GAIN, 0x30}, | ||
| 410 | {SENSOR, PO1030_REG_BLUE_GAIN, 0x30}, | ||
| 411 | {SENSOR, PO1030_REG_GREEN_2_GAIN, 0x30}, | ||
| 412 | {SENSOR, PO1030_REG_GC0, 0x10}, | ||
| 413 | {SENSOR, PO1030_REG_GC1, 0x20}, | ||
| 414 | {SENSOR, PO1030_REG_GC2, 0x40}, | ||
| 415 | {SENSOR, PO1030_REG_GC3, 0x60}, | ||
| 416 | {SENSOR, PO1030_REG_GC4, 0x80}, | ||
| 417 | {SENSOR, PO1030_REG_GC5, 0xa0}, | ||
| 418 | {SENSOR, PO1030_REG_GC6, 0xc0}, | ||
| 419 | {SENSOR, PO1030_REG_GC7, 0xff}, | ||
| 420 | /*end of sequence 4*/ | ||
| 421 | /*sequence 5*/ | ||
| 422 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06}, | ||
| 423 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 424 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0}, | ||
| 425 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c}, | ||
| 426 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81}, | ||
| 427 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82}, | ||
| 428 | {BRIDGE, M5602_XB_SIG_INI, 0x01}, | ||
| 429 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 430 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x02}, | ||
| 431 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 432 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 433 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01}, | ||
| 434 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xec}, | ||
| 435 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 436 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00}, | ||
| 437 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
| 438 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
| 439 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
| 440 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00}, | ||
| 441 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02}, | ||
| 442 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e}, | ||
| 443 | {BRIDGE, M5602_XB_SIG_INI, 0x00}, | ||
| 444 | /*end of sequence 5*/ | ||
| 445 | |||
| 446 | /*sequence 6*/ | ||
| 447 | /* Changing 40 in f0 the image becomes green in bayer mode and red in | ||
| 448 | * rgb mode */ | ||
| 449 | {SENSOR, PO1030_REG_RED_GAIN, PO1030_RED_GAIN_DEFAULT}, | ||
| 450 | /* in changing 40 in f0 the image becomes green in bayer mode and red in | ||
| 451 | * rgb mode */ | ||
| 452 | {SENSOR, PO1030_REG_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT}, | ||
| 453 | |||
| 454 | /* with a very low lighted environment increase the exposure but | ||
| 455 | * decrease the FPS (Frame Per Second) */ | ||
| 456 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00}, | ||
| 457 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}, | ||
| 458 | |||
| 459 | /* Controls high exposure more than SENSOR_LOW_EXPOSURE, use only in | ||
| 460 | * low lighted environment (f0 is more than ff ?)*/ | ||
| 461 | {SENSOR, PO1030_REG_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2) | ||
| 462 | & 0xff)}, | ||
| 463 | |||
| 464 | /* Controls middle exposure, use only in high lighted environment */ | ||
| 465 | {SENSOR, PO1030_REG_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff}, | ||
| 466 | |||
| 467 | /* Controls clarity (not sure) */ | ||
| 468 | {SENSOR, PO1030_REG_INTEGLINES_L, 0x00}, | ||
| 469 | /* Controls gain (the image is more lighted) */ | ||
| 470 | {SENSOR, PO1030_REG_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT}, | ||
| 471 | |||
| 472 | /* Sets the width */ | ||
| 473 | {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02}, | ||
| 474 | {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef} | ||
| 475 | /*end of sequence 6*/ | ||
| 476 | }; | ||
| 477 | |||
| 478 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c new file mode 100644 index 000000000000..68202565325d --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | |||
| @@ -0,0 +1,463 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the s5k4aa sensor | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include "m5602_s5k4aa.h" | ||
| 20 | |||
| 21 | int s5k4aa_probe(struct sd *sd) | ||
| 22 | { | ||
| 23 | u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
| 24 | const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75}; | ||
| 25 | int i, err = 0; | ||
| 26 | |||
| 27 | if (force_sensor) { | ||
| 28 | if (force_sensor == S5K4AA_SENSOR) { | ||
| 29 | info("Forcing a %s sensor", s5k4aa.name); | ||
| 30 | goto sensor_found; | ||
| 31 | } | ||
| 32 | /* If we want to force another sensor, don't try to probe this | ||
| 33 | * one */ | ||
| 34 | return -ENODEV; | ||
| 35 | } | ||
| 36 | |||
| 37 | info("Probing for a s5k4aa sensor"); | ||
| 38 | |||
| 39 | /* Preinit the sensor */ | ||
| 40 | for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) { | ||
| 41 | u8 data[2] = {0x00, 0x00}; | ||
| 42 | |||
| 43 | switch (preinit_s5k4aa[i][0]) { | ||
| 44 | case BRIDGE: | ||
| 45 | err = m5602_write_bridge(sd, | ||
| 46 | preinit_s5k4aa[i][1], | ||
| 47 | preinit_s5k4aa[i][2]); | ||
| 48 | break; | ||
| 49 | |||
| 50 | case SENSOR: | ||
| 51 | data[0] = preinit_s5k4aa[i][2]; | ||
| 52 | err = s5k4aa_write_sensor(sd, | ||
| 53 | preinit_s5k4aa[i][1], | ||
| 54 | data, 1); | ||
| 55 | break; | ||
| 56 | |||
| 57 | case SENSOR_LONG: | ||
| 58 | data[0] = preinit_s5k4aa[i][2]; | ||
| 59 | data[1] = preinit_s5k4aa[i][3]; | ||
| 60 | err = s5k4aa_write_sensor(sd, | ||
| 61 | preinit_s5k4aa[i][1], | ||
| 62 | data, 2); | ||
| 63 | break; | ||
| 64 | default: | ||
| 65 | info("Invalid stream command, exiting init"); | ||
| 66 | return -EINVAL; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | /* Test some registers, but we don't know their exact meaning yet */ | ||
| 71 | if (s5k4aa_read_sensor(sd, 0x00, prod_id, sizeof(prod_id))) | ||
| 72 | return -ENODEV; | ||
| 73 | |||
| 74 | if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) | ||
| 75 | return -ENODEV; | ||
| 76 | else | ||
| 77 | info("Detected a s5k4aa sensor"); | ||
| 78 | sensor_found: | ||
| 79 | sd->gspca_dev.cam.cam_mode = s5k4aa.modes; | ||
| 80 | sd->gspca_dev.cam.nmodes = s5k4aa.nmodes; | ||
| 81 | sd->desc->ctrls = s5k4aa.ctrls; | ||
| 82 | sd->desc->nctrls = s5k4aa.nctrls; | ||
| 83 | |||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | int s5k4aa_read_sensor(struct sd *sd, const u8 address, | ||
| 88 | u8 *i2c_data, const u8 len) | ||
| 89 | { | ||
| 90 | int err, i; | ||
| 91 | |||
| 92 | do { | ||
| 93 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
| 94 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
| 95 | if (err < 0) | ||
| 96 | goto out; | ||
| 97 | |||
| 98 | err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, | ||
| 99 | sd->sensor->i2c_slave_id); | ||
| 100 | if (err < 0) | ||
| 101 | goto out; | ||
| 102 | |||
| 103 | err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); | ||
| 104 | if (err < 0) | ||
| 105 | goto out; | ||
| 106 | |||
| 107 | err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); | ||
| 108 | if (err < 0) | ||
| 109 | goto out; | ||
| 110 | |||
| 111 | do { | ||
| 112 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
| 113 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
| 114 | if (err < 0) | ||
| 115 | goto out; | ||
| 116 | |||
| 117 | for (i = 0; (i < len) & !err; i++) { | ||
| 118 | err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); | ||
| 119 | |||
| 120 | PDEBUG(DBG_TRACE, "Reading sensor register " | ||
| 121 | "0x%x containing 0x%x ", address, *i2c_data); | ||
| 122 | } | ||
| 123 | out: | ||
| 124 | return (err < 0) ? err : 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | int s5k4aa_write_sensor(struct sd *sd, const u8 address, | ||
| 128 | u8 *i2c_data, const u8 len) | ||
| 129 | { | ||
| 130 | int err, i; | ||
| 131 | u8 *p; | ||
| 132 | struct usb_device *udev = sd->gspca_dev.dev; | ||
| 133 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
| 134 | |||
| 135 | /* No sensor with a data width larger than 16 bits has yet been seen */ | ||
| 136 | if (len > 2 || !len) | ||
| 137 | return -EINVAL; | ||
| 138 | |||
| 139 | memcpy(buf, sensor_urb_skeleton, | ||
| 140 | sizeof(sensor_urb_skeleton)); | ||
| 141 | |||
| 142 | buf[11] = sd->sensor->i2c_slave_id; | ||
| 143 | buf[15] = address; | ||
| 144 | |||
| 145 | /* Special case larger sensor writes */ | ||
| 146 | p = buf + 16; | ||
| 147 | |||
| 148 | /* Copy a four byte write sequence for each byte to be written to */ | ||
| 149 | for (i = 0; i < len; i++) { | ||
| 150 | memcpy(p, sensor_urb_skeleton + 16, 4); | ||
| 151 | p[3] = i2c_data[i]; | ||
| 152 | p += 4; | ||
| 153 | PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", | ||
| 154 | address, i2c_data[i]); | ||
| 155 | } | ||
| 156 | |||
| 157 | /* Copy the tailer */ | ||
| 158 | memcpy(p, sensor_urb_skeleton + 20, 4); | ||
| 159 | |||
| 160 | /* Set the total length */ | ||
| 161 | p[3] = 0x10 + len; | ||
| 162 | |||
| 163 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 164 | 0x04, 0x40, 0x19, | ||
| 165 | 0x0000, buf, | ||
| 166 | 20 + len * 4, M5602_URB_MSG_TIMEOUT); | ||
| 167 | |||
| 168 | return (err < 0) ? err : 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | int s5k4aa_init(struct sd *sd) | ||
| 172 | { | ||
| 173 | int i, err = 0; | ||
| 174 | |||
| 175 | for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) { | ||
| 176 | u8 data[2] = {0x00, 0x00}; | ||
| 177 | |||
| 178 | switch (init_s5k4aa[i][0]) { | ||
| 179 | case BRIDGE: | ||
| 180 | err = m5602_write_bridge(sd, | ||
| 181 | init_s5k4aa[i][1], | ||
| 182 | init_s5k4aa[i][2]); | ||
| 183 | break; | ||
| 184 | |||
| 185 | case SENSOR: | ||
| 186 | data[0] = init_s5k4aa[i][2]; | ||
| 187 | err = s5k4aa_write_sensor(sd, | ||
| 188 | init_s5k4aa[i][1], data, 1); | ||
| 189 | break; | ||
| 190 | |||
| 191 | case SENSOR_LONG: | ||
| 192 | data[0] = init_s5k4aa[i][2]; | ||
| 193 | data[1] = init_s5k4aa[i][3]; | ||
| 194 | err = s5k4aa_write_sensor(sd, | ||
| 195 | init_s5k4aa[i][1], data, 2); | ||
| 196 | break; | ||
| 197 | default: | ||
| 198 | info("Invalid stream command, exiting init"); | ||
| 199 | return -EINVAL; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | if (dump_sensor) | ||
| 204 | s5k4aa_dump_registers(sd); | ||
| 205 | |||
| 206 | if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) { | ||
| 207 | u8 data = 0x02; | ||
| 208 | info("vertical flip quirk active"); | ||
| 209 | s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 210 | s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
| 211 | data |= S5K4AA_RM_V_FLIP; | ||
| 212 | data &= ~S5K4AA_RM_H_FLIP; | ||
| 213 | s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
| 214 | |||
| 215 | /* Decrement COLSTART to preserve color order (BGGR) */ | ||
| 216 | s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
| 217 | data--; | ||
| 218 | s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
| 219 | |||
| 220 | /* Increment ROWSTART to preserve color order (BGGR) */ | ||
| 221 | s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
| 222 | data++; | ||
| 223 | s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
| 224 | } | ||
| 225 | |||
| 226 | return (err < 0) ? err : 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | int s5k4aa_power_down(struct sd *sd) | ||
| 230 | { | ||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 235 | { | ||
| 236 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 237 | u8 data = S5K4AA_PAGE_MAP_2; | ||
| 238 | int err; | ||
| 239 | |||
| 240 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 241 | if (err < 0) | ||
| 242 | goto out; | ||
| 243 | |||
| 244 | err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); | ||
| 245 | if (err < 0) | ||
| 246 | goto out; | ||
| 247 | |||
| 248 | *val = data << 8; | ||
| 249 | err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); | ||
| 250 | *val |= data; | ||
| 251 | PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val); | ||
| 252 | out: | ||
| 253 | return (err < 0) ? err : 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | ||
| 257 | { | ||
| 258 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 259 | u8 data = S5K4AA_PAGE_MAP_2; | ||
| 260 | int err; | ||
| 261 | |||
| 262 | PDEBUG(DBG_V4L2_CID, "Set exposure to %d", val); | ||
| 263 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 264 | if (err < 0) | ||
| 265 | goto out; | ||
| 266 | data = (val >> 8) & 0xff; | ||
| 267 | err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1); | ||
| 268 | if (err < 0) | ||
| 269 | goto out; | ||
| 270 | data = val & 0xff; | ||
| 271 | err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); | ||
| 272 | out: | ||
| 273 | return (err < 0) ? err : 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 277 | { | ||
| 278 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 279 | u8 data = S5K4AA_PAGE_MAP_2; | ||
| 280 | int err; | ||
| 281 | |||
| 282 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 283 | if (err < 0) | ||
| 284 | goto out; | ||
| 285 | |||
| 286 | err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 287 | *val = (data & S5K4AA_RM_V_FLIP) >> 7; | ||
| 288 | PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); | ||
| 289 | |||
| 290 | out: | ||
| 291 | return (err < 0) ? err : 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | ||
| 295 | { | ||
| 296 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 297 | u8 data = S5K4AA_PAGE_MAP_2; | ||
| 298 | int err; | ||
| 299 | |||
| 300 | PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); | ||
| 301 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 302 | if (err < 0) | ||
| 303 | goto out; | ||
| 304 | err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
| 305 | if (err < 0) | ||
| 306 | goto out; | ||
| 307 | data = ((data & ~S5K4AA_RM_V_FLIP) | ||
| 308 | | ((val & 0x01) << 7)); | ||
| 309 | err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
| 310 | if (err < 0) | ||
| 311 | goto out; | ||
| 312 | |||
| 313 | if (val) { | ||
| 314 | err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
| 315 | if (err < 0) | ||
| 316 | goto out; | ||
| 317 | |||
| 318 | data++; | ||
| 319 | err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
| 320 | } else { | ||
| 321 | err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
| 322 | if (err < 0) | ||
| 323 | goto out; | ||
| 324 | |||
| 325 | data--; | ||
| 326 | err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | ||
| 327 | } | ||
| 328 | out: | ||
| 329 | return (err < 0) ? err : 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 333 | { | ||
| 334 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 335 | u8 data = S5K4AA_PAGE_MAP_2; | ||
| 336 | int err; | ||
| 337 | |||
| 338 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 339 | if (err < 0) | ||
| 340 | goto out; | ||
| 341 | |||
| 342 | err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 343 | *val = (data & S5K4AA_RM_H_FLIP) >> 6; | ||
| 344 | PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); | ||
| 345 | out: | ||
| 346 | return (err < 0) ? err : 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | ||
| 350 | { | ||
| 351 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 352 | u8 data = S5K4AA_PAGE_MAP_2; | ||
| 353 | int err; | ||
| 354 | |||
| 355 | PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", | ||
| 356 | val); | ||
| 357 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 358 | if (err < 0) | ||
| 359 | goto out; | ||
| 360 | err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
| 361 | if (err < 0) | ||
| 362 | goto out; | ||
| 363 | |||
| 364 | data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6)); | ||
| 365 | err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); | ||
| 366 | if (err < 0) | ||
| 367 | goto out; | ||
| 368 | |||
| 369 | if (val) { | ||
| 370 | err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
| 371 | if (err < 0) | ||
| 372 | goto out; | ||
| 373 | data++; | ||
| 374 | err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
| 375 | if (err < 0) | ||
| 376 | goto out; | ||
| 377 | } else { | ||
| 378 | err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
| 379 | if (err < 0) | ||
| 380 | goto out; | ||
| 381 | data--; | ||
| 382 | err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | ||
| 383 | } | ||
| 384 | out: | ||
| 385 | return (err < 0) ? err : 0; | ||
| 386 | } | ||
| 387 | |||
| 388 | int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 389 | { | ||
| 390 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 391 | u8 data = S5K4AA_PAGE_MAP_2; | ||
| 392 | int err; | ||
| 393 | |||
| 394 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 395 | if (err < 0) | ||
| 396 | goto out; | ||
| 397 | |||
| 398 | err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1); | ||
| 399 | *val = data; | ||
| 400 | PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); | ||
| 401 | |||
| 402 | out: | ||
| 403 | return (err < 0) ? err : 0; | ||
| 404 | } | ||
| 405 | |||
| 406 | int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
| 407 | { | ||
| 408 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 409 | u8 data = S5K4AA_PAGE_MAP_2; | ||
| 410 | int err; | ||
| 411 | |||
| 412 | PDEBUG(DBG_V4L2_CID, "Set gain to %d", val); | ||
| 413 | err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); | ||
| 414 | if (err < 0) | ||
| 415 | goto out; | ||
| 416 | |||
| 417 | data = val & 0xff; | ||
| 418 | err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1); | ||
| 419 | |||
| 420 | out: | ||
| 421 | return (err < 0) ? err : 0; | ||
| 422 | } | ||
| 423 | |||
| 424 | void s5k4aa_dump_registers(struct sd *sd) | ||
| 425 | { | ||
| 426 | int address; | ||
| 427 | u8 page, old_page; | ||
| 428 | s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); | ||
| 429 | for (page = 0; page < 16; page++) { | ||
| 430 | s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); | ||
| 431 | info("Dumping the s5k4aa register state for page 0x%x", page); | ||
| 432 | for (address = 0; address <= 0xff; address++) { | ||
| 433 | u8 value = 0; | ||
| 434 | s5k4aa_read_sensor(sd, address, &value, 1); | ||
| 435 | info("register 0x%x contains 0x%x", | ||
| 436 | address, value); | ||
| 437 | } | ||
| 438 | } | ||
| 439 | info("s5k4aa register state dump complete"); | ||
| 440 | |||
| 441 | for (page = 0; page < 16; page++) { | ||
| 442 | s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1); | ||
| 443 | info("Probing for which registers that are " | ||
| 444 | "read/write for page 0x%x", page); | ||
| 445 | for (address = 0; address <= 0xff; address++) { | ||
| 446 | u8 old_value, ctrl_value, test_value = 0xff; | ||
| 447 | |||
| 448 | s5k4aa_read_sensor(sd, address, &old_value, 1); | ||
| 449 | s5k4aa_write_sensor(sd, address, &test_value, 1); | ||
| 450 | s5k4aa_read_sensor(sd, address, &ctrl_value, 1); | ||
| 451 | |||
| 452 | if (ctrl_value == test_value) | ||
| 453 | info("register 0x%x is writeable", address); | ||
| 454 | else | ||
| 455 | info("register 0x%x is read only", address); | ||
| 456 | |||
| 457 | /* Restore original value */ | ||
| 458 | s5k4aa_write_sensor(sd, address, &old_value, 1); | ||
| 459 | } | ||
| 460 | } | ||
| 461 | info("Read/write register probing complete"); | ||
| 462 | s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1); | ||
| 463 | } | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h new file mode 100644 index 000000000000..bb7f7e3e90af --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h | |||
| @@ -0,0 +1,370 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the s5k4aa sensor | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef M5602_S5K4AA_H_ | ||
| 20 | #define M5602_S5K4AA_H_ | ||
| 21 | |||
| 22 | #include <linux/dmi.h> | ||
| 23 | |||
| 24 | #include "m5602_sensor.h" | ||
| 25 | |||
| 26 | /*****************************************************************************/ | ||
| 27 | |||
| 28 | #define S5K4AA_PAGE_MAP 0xec | ||
| 29 | |||
| 30 | #define S5K4AA_PAGE_MAP_0 0x00 | ||
| 31 | #define S5K4AA_PAGE_MAP_1 0x01 | ||
| 32 | #define S5K4AA_PAGE_MAP_2 0x02 | ||
| 33 | |||
| 34 | /* Sensor register definitions for page 0x02 */ | ||
| 35 | #define S5K4AA_READ_MODE 0x03 | ||
| 36 | #define S5K4AA_ROWSTART_HI 0x04 | ||
| 37 | #define S5K4AA_ROWSTART_LO 0x05 | ||
| 38 | #define S5K4AA_COLSTART_HI 0x06 | ||
| 39 | #define S5K4AA_COLSTART_LO 0x07 | ||
| 40 | #define S5K4AA_WINDOW_HEIGHT_HI 0x08 | ||
| 41 | #define S5K4AA_WINDOW_HEIGHT_LO 0x09 | ||
| 42 | #define S5K4AA_WINDOW_WIDTH_HI 0x0a | ||
| 43 | #define S5K4AA_WINDOW_WIDTH_LO 0x0b | ||
| 44 | #define S5K4AA_GLOBAL_GAIN__ 0x0f /* Only a guess ATM !!! */ | ||
| 45 | #define S5K4AA_H_BLANK_HI__ 0x1d /* Only a guess ATM !!! sync lost | ||
| 46 | if too low, reduces frame rate | ||
| 47 | if too high */ | ||
| 48 | #define S5K4AA_H_BLANK_LO__ 0x1e /* Only a guess ATM !!! */ | ||
| 49 | #define S5K4AA_EXPOSURE_HI 0x17 | ||
| 50 | #define S5K4AA_EXPOSURE_LO 0x18 | ||
| 51 | #define S5K4AA_GAIN_1 0x1f /* (digital?) gain : 5 bits */ | ||
| 52 | #define S5K4AA_GAIN_2 0x20 /* (analogue?) gain : 7 bits */ | ||
| 53 | |||
| 54 | #define S5K4AA_RM_ROW_SKIP_4X 0x08 | ||
| 55 | #define S5K4AA_RM_ROW_SKIP_2X 0x04 | ||
| 56 | #define S5K4AA_RM_COL_SKIP_4X 0x02 | ||
| 57 | #define S5K4AA_RM_COL_SKIP_2X 0x01 | ||
| 58 | #define S5K4AA_RM_H_FLIP 0x40 | ||
| 59 | #define S5K4AA_RM_V_FLIP 0x80 | ||
| 60 | |||
| 61 | /*****************************************************************************/ | ||
| 62 | |||
| 63 | /* Kernel module parameters */ | ||
| 64 | extern int force_sensor; | ||
| 65 | extern int dump_sensor; | ||
| 66 | extern unsigned int m5602_debug; | ||
| 67 | |||
| 68 | int s5k4aa_probe(struct sd *sd); | ||
| 69 | int s5k4aa_init(struct sd *sd); | ||
| 70 | int s5k4aa_power_down(struct sd *sd); | ||
| 71 | |||
| 72 | void s5k4aa_dump_registers(struct sd *sd); | ||
| 73 | |||
| 74 | int s5k4aa_read_sensor(struct sd *sd, const u8 address, | ||
| 75 | u8 *i2c_data, const u8 len); | ||
| 76 | int s5k4aa_write_sensor(struct sd *sd, const u8 address, | ||
| 77 | u8 *i2c_data, const u8 len); | ||
| 78 | |||
| 79 | int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 80 | int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
| 81 | int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 82 | int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
| 83 | int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 84 | int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
| 85 | int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 86 | int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
| 87 | |||
| 88 | static struct m5602_sensor s5k4aa = { | ||
| 89 | .name = "S5K4AA", | ||
| 90 | .probe = s5k4aa_probe, | ||
| 91 | .init = s5k4aa_init, | ||
| 92 | .power_down = s5k4aa_power_down, | ||
| 93 | .read_sensor = s5k4aa_read_sensor, | ||
| 94 | .write_sensor = s5k4aa_write_sensor, | ||
| 95 | .i2c_slave_id = 0x5a, | ||
| 96 | .nctrls = 4, | ||
| 97 | .ctrls = { | ||
| 98 | { | ||
| 99 | { | ||
| 100 | .id = V4L2_CID_VFLIP, | ||
| 101 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 102 | .name = "vertical flip", | ||
| 103 | .minimum = 0, | ||
| 104 | .maximum = 1, | ||
| 105 | .step = 1, | ||
| 106 | .default_value = 0 | ||
| 107 | }, | ||
| 108 | .set = s5k4aa_set_vflip, | ||
| 109 | .get = s5k4aa_get_vflip | ||
| 110 | |||
| 111 | }, { | ||
| 112 | { | ||
| 113 | .id = V4L2_CID_HFLIP, | ||
| 114 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 115 | .name = "horizontal flip", | ||
| 116 | .minimum = 0, | ||
| 117 | .maximum = 1, | ||
| 118 | .step = 1, | ||
| 119 | .default_value = 0 | ||
| 120 | }, | ||
| 121 | .set = s5k4aa_set_hflip, | ||
| 122 | .get = s5k4aa_get_hflip | ||
| 123 | |||
| 124 | }, { | ||
| 125 | { | ||
| 126 | .id = V4L2_CID_GAIN, | ||
| 127 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 128 | .name = "Gain", | ||
| 129 | .minimum = 0, | ||
| 130 | .maximum = 127, | ||
| 131 | .step = 1, | ||
| 132 | .default_value = 0xa0, | ||
| 133 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 134 | }, | ||
| 135 | .set = s5k4aa_set_gain, | ||
| 136 | .get = s5k4aa_get_gain | ||
| 137 | }, { | ||
| 138 | { | ||
| 139 | .id = V4L2_CID_EXPOSURE, | ||
| 140 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 141 | .name = "Exposure", | ||
| 142 | .minimum = 13, | ||
| 143 | .maximum = 0xfff, | ||
| 144 | .step = 1, | ||
| 145 | .default_value = 0x100, | ||
| 146 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 147 | }, | ||
| 148 | .set = s5k4aa_set_exposure, | ||
| 149 | .get = s5k4aa_get_exposure | ||
| 150 | } | ||
| 151 | }, | ||
| 152 | |||
| 153 | .nmodes = 1, | ||
| 154 | .modes = { | ||
| 155 | { | ||
| 156 | M5602_DEFAULT_FRAME_WIDTH, | ||
| 157 | M5602_DEFAULT_FRAME_HEIGHT, | ||
| 158 | V4L2_PIX_FMT_SBGGR8, | ||
| 159 | V4L2_FIELD_NONE, | ||
| 160 | .sizeimage = | ||
| 161 | M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, | ||
| 162 | .bytesperline = M5602_DEFAULT_FRAME_WIDTH, | ||
| 163 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 164 | .priv = 1 | ||
| 165 | } | ||
| 166 | } | ||
| 167 | }; | ||
| 168 | |||
| 169 | static const unsigned char preinit_s5k4aa[][4] = | ||
| 170 | { | ||
| 171 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
| 172 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
| 173 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 174 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 175 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 176 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, | ||
| 177 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, | ||
| 178 | |||
| 179 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 180 | {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, | ||
| 181 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, | ||
| 182 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, | ||
| 183 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, | ||
| 184 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, | ||
| 185 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
| 186 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 187 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00}, | ||
| 188 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 189 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 190 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 191 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 192 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 193 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 194 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, | ||
| 195 | |||
| 196 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
| 197 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
| 198 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 199 | {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00}, | ||
| 200 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 201 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, | ||
| 202 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 203 | {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, | ||
| 204 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 205 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, | ||
| 206 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
| 207 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 208 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, | ||
| 209 | |||
| 210 | {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00} | ||
| 211 | }; | ||
| 212 | |||
| 213 | static const unsigned char init_s5k4aa[][4] = | ||
| 214 | { | ||
| 215 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
| 216 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
| 217 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 218 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 219 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 220 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, | ||
| 221 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, | ||
| 222 | |||
| 223 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 224 | {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, | ||
| 225 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, | ||
| 226 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, | ||
| 227 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, | ||
| 228 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, | ||
| 229 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
| 230 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 231 | {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00}, | ||
| 232 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 233 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 234 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 235 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 236 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 237 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 238 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, | ||
| 239 | |||
| 240 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
| 241 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
| 242 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 243 | {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00}, | ||
| 244 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 245 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, | ||
| 246 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 247 | {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, | ||
| 248 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 249 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, | ||
| 250 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
| 251 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 252 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, | ||
| 253 | |||
| 254 | {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00}, | ||
| 255 | {SENSOR, 0x36, 0x01, 0x00}, | ||
| 256 | {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}, | ||
| 257 | {SENSOR, 0x7b, 0xff, 0x00}, | ||
| 258 | {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, | ||
| 259 | {SENSOR, 0x0c, 0x05, 0x00}, | ||
| 260 | {SENSOR, 0x02, 0x0e, 0x00}, | ||
| 261 | {SENSOR, S5K4AA_GAIN_1, 0x0f, 0x00}, | ||
| 262 | {SENSOR, S5K4AA_GAIN_2, 0x00, 0x00}, | ||
| 263 | {SENSOR, S5K4AA_GLOBAL_GAIN__, 0x01, 0x00}, | ||
| 264 | {SENSOR, 0x11, 0x00, 0x00}, | ||
| 265 | {SENSOR, 0x12, 0x00, 0x00}, | ||
| 266 | {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, | ||
| 267 | {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00}, | ||
| 268 | {SENSOR, 0x37, 0x00, 0x00}, | ||
| 269 | {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, | ||
| 270 | {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, | ||
| 271 | {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, | ||
| 272 | {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00}, | ||
| 273 | {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, | ||
| 274 | {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc4, 0x00}, | ||
| 275 | {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, | ||
| 276 | {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x08, 0x00}, | ||
| 277 | {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, | ||
| 278 | {SENSOR, S5K4AA_H_BLANK_LO__, 0x48, 0x00}, | ||
| 279 | {SENSOR, S5K4AA_EXPOSURE_HI, 0x00, 0x00}, | ||
| 280 | {SENSOR, S5K4AA_EXPOSURE_LO, 0x43, 0x00}, | ||
| 281 | {SENSOR, 0x11, 0x04, 0x00}, | ||
| 282 | {SENSOR, 0x12, 0xc3, 0x00}, | ||
| 283 | {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, | ||
| 284 | |||
| 285 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 286 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 287 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 288 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00}, | ||
| 289 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 290 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 291 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 292 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 293 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 294 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 295 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 296 | /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */ | ||
| 297 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
| 298 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00}, | ||
| 299 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 300 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 301 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 302 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
| 303 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 304 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 305 | /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */ | ||
| 306 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
| 307 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00}, | ||
| 308 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 309 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 310 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */ | ||
| 311 | |||
| 312 | {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, | ||
| 313 | {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X | ||
| 314 | | S5K4AA_RM_COL_SKIP_2X, 0x00}, | ||
| 315 | /* 0x37 : Fix image stability when light is too bright and improves | ||
| 316 | * image quality in 640x480, but worsens it in 1280x1024 */ | ||
| 317 | {SENSOR, 0x37, 0x01, 0x00}, | ||
| 318 | /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */ | ||
| 319 | {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00}, | ||
| 320 | {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00}, | ||
| 321 | {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00}, | ||
| 322 | {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00}, | ||
| 323 | /* window_height_hi, window_height_lo : 960 = 0x03c0 */ | ||
| 324 | {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00}, | ||
| 325 | {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00}, | ||
| 326 | /* window_width_hi, window_width_lo : 1280 = 0x0500 */ | ||
| 327 | {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00}, | ||
| 328 | {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00}, | ||
| 329 | {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00}, | ||
| 330 | {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */ | ||
| 331 | {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00}, | ||
| 332 | {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00}, | ||
| 333 | {SENSOR, 0x11, 0x04, 0x00}, | ||
| 334 | {SENSOR, 0x12, 0xc3, 0x00}, | ||
| 335 | {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00}, | ||
| 336 | {SENSOR, 0x02, 0x0e, 0x00}, | ||
| 337 | {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00}, | ||
| 338 | {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00}, | ||
| 339 | {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00} | ||
| 340 | }; | ||
| 341 | |||
| 342 | static | ||
| 343 | const | ||
| 344 | struct dmi_system_id s5k4aa_vflip_dmi_table[] = { | ||
| 345 | { | ||
| 346 | .ident = "Fujitsu-Siemens Amilo Xa 2528", | ||
| 347 | .matches = { | ||
| 348 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
| 349 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528") | ||
| 350 | } | ||
| 351 | }, | ||
| 352 | { | ||
| 353 | .ident = "Fujitsu-Siemens Amilo Xi 2550", | ||
| 354 | .matches = { | ||
| 355 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
| 356 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550") | ||
| 357 | } | ||
| 358 | }, | ||
| 359 | { | ||
| 360 | .ident = "MSI GX700", | ||
| 361 | .matches = { | ||
| 362 | DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), | ||
| 363 | DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), | ||
| 364 | DMI_MATCH(DMI_BIOS_DATE, "07/26/2007") | ||
| 365 | } | ||
| 366 | }, | ||
| 367 | { } | ||
| 368 | }; | ||
| 369 | |||
| 370 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c new file mode 100644 index 000000000000..b4b33c2d0499 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c | |||
| @@ -0,0 +1,423 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the s5k83a sensor | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include "m5602_s5k83a.h" | ||
| 20 | |||
| 21 | int s5k83a_probe(struct sd *sd) | ||
| 22 | { | ||
| 23 | u8 prod_id = 0, ver_id = 0; | ||
| 24 | int i, err = 0; | ||
| 25 | |||
| 26 | if (force_sensor) { | ||
| 27 | if (force_sensor == S5K83A_SENSOR) { | ||
| 28 | info("Forcing a %s sensor", s5k83a.name); | ||
| 29 | goto sensor_found; | ||
| 30 | } | ||
| 31 | /* If we want to force another sensor, don't try to probe this | ||
| 32 | * one */ | ||
| 33 | return -ENODEV; | ||
| 34 | } | ||
| 35 | |||
| 36 | info("Probing for a s5k83a sensor"); | ||
| 37 | |||
| 38 | /* Preinit the sensor */ | ||
| 39 | for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) { | ||
| 40 | u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]}; | ||
| 41 | if (preinit_s5k83a[i][0] == SENSOR) | ||
| 42 | err = s5k83a_write_sensor(sd, preinit_s5k83a[i][1], | ||
| 43 | data, 2); | ||
| 44 | else | ||
| 45 | err = m5602_write_bridge(sd, preinit_s5k83a[i][1], | ||
| 46 | data[0]); | ||
| 47 | } | ||
| 48 | |||
| 49 | /* We don't know what register (if any) that contain the product id | ||
| 50 | * Just pick the first addresses that seem to produce the same results | ||
| 51 | * on multiple machines */ | ||
| 52 | if (s5k83a_read_sensor(sd, 0x00, &prod_id, 1)) | ||
| 53 | return -ENODEV; | ||
| 54 | |||
| 55 | if (s5k83a_read_sensor(sd, 0x01, &ver_id, 1)) | ||
| 56 | return -ENODEV; | ||
| 57 | |||
| 58 | if ((prod_id == 0xff) || (ver_id == 0xff)) | ||
| 59 | return -ENODEV; | ||
| 60 | else | ||
| 61 | info("Detected a s5k83a sensor"); | ||
| 62 | |||
| 63 | sensor_found: | ||
| 64 | sd->gspca_dev.cam.cam_mode = s5k83a.modes; | ||
| 65 | sd->gspca_dev.cam.nmodes = s5k83a.nmodes; | ||
| 66 | sd->desc->ctrls = s5k83a.ctrls; | ||
| 67 | sd->desc->nctrls = s5k83a.nctrls; | ||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | int s5k83a_read_sensor(struct sd *sd, const u8 address, | ||
| 72 | u8 *i2c_data, const u8 len) | ||
| 73 | { | ||
| 74 | int err, i; | ||
| 75 | |||
| 76 | do { | ||
| 77 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
| 78 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
| 79 | if (err < 0) | ||
| 80 | goto out; | ||
| 81 | |||
| 82 | err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR, | ||
| 83 | sd->sensor->i2c_slave_id); | ||
| 84 | if (err < 0) | ||
| 85 | goto out; | ||
| 86 | |||
| 87 | err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address); | ||
| 88 | if (err < 0) | ||
| 89 | goto out; | ||
| 90 | |||
| 91 | err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len); | ||
| 92 | if (err < 0) | ||
| 93 | goto out; | ||
| 94 | |||
| 95 | do { | ||
| 96 | err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data); | ||
| 97 | } while ((*i2c_data & I2C_BUSY) && !err); | ||
| 98 | |||
| 99 | if (err < 0) | ||
| 100 | goto out; | ||
| 101 | for (i = 0; i < len && !len; i++) { | ||
| 102 | err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); | ||
| 103 | |||
| 104 | PDEBUG(DBG_TRACE, "Reading sensor register " | ||
| 105 | "0x%x containing 0x%x ", address, *i2c_data); | ||
| 106 | } | ||
| 107 | |||
| 108 | out: | ||
| 109 | return (err < 0) ? err : 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | int s5k83a_write_sensor(struct sd *sd, const u8 address, | ||
| 113 | u8 *i2c_data, const u8 len) | ||
| 114 | { | ||
| 115 | int err, i; | ||
| 116 | u8 *p; | ||
| 117 | struct usb_device *udev = sd->gspca_dev.dev; | ||
| 118 | __u8 *buf = sd->gspca_dev.usb_buf; | ||
| 119 | |||
| 120 | /* No sensor with a data width larger than 16 bits has yet been seen */ | ||
| 121 | if (len > 2 || !len) | ||
| 122 | return -EINVAL; | ||
| 123 | |||
| 124 | memcpy(buf, sensor_urb_skeleton, | ||
| 125 | sizeof(sensor_urb_skeleton)); | ||
| 126 | |||
| 127 | buf[11] = sd->sensor->i2c_slave_id; | ||
| 128 | buf[15] = address; | ||
| 129 | |||
| 130 | /* Special case larger sensor writes */ | ||
| 131 | p = buf + 16; | ||
| 132 | |||
| 133 | /* Copy a four byte write sequence for each byte to be written to */ | ||
| 134 | for (i = 0; i < len; i++) { | ||
| 135 | memcpy(p, sensor_urb_skeleton + 16, 4); | ||
| 136 | p[3] = i2c_data[i]; | ||
| 137 | p += 4; | ||
| 138 | PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", | ||
| 139 | address, i2c_data[i]); | ||
| 140 | } | ||
| 141 | |||
| 142 | /* Copy the tailer */ | ||
| 143 | memcpy(p, sensor_urb_skeleton + 20, 4); | ||
| 144 | |||
| 145 | /* Set the total length */ | ||
| 146 | p[3] = 0x10 + len; | ||
| 147 | |||
| 148 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 149 | 0x04, 0x40, 0x19, | ||
| 150 | 0x0000, buf, | ||
| 151 | 20 + len * 4, M5602_URB_MSG_TIMEOUT); | ||
| 152 | |||
| 153 | return (err < 0) ? err : 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | int s5k83a_init(struct sd *sd) | ||
| 157 | { | ||
| 158 | int i, err = 0; | ||
| 159 | |||
| 160 | for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) { | ||
| 161 | u8 data[2] = {0x00, 0x00}; | ||
| 162 | |||
| 163 | switch (init_s5k83a[i][0]) { | ||
| 164 | case BRIDGE: | ||
| 165 | err = m5602_write_bridge(sd, | ||
| 166 | init_s5k83a[i][1], | ||
| 167 | init_s5k83a[i][2]); | ||
| 168 | break; | ||
| 169 | |||
| 170 | case SENSOR: | ||
| 171 | data[0] = init_s5k83a[i][2]; | ||
| 172 | err = s5k83a_write_sensor(sd, | ||
| 173 | init_s5k83a[i][1], data, 1); | ||
| 174 | break; | ||
| 175 | |||
| 176 | case SENSOR_LONG: | ||
| 177 | data[0] = init_s5k83a[i][2]; | ||
| 178 | data[1] = init_s5k83a[i][3]; | ||
| 179 | err = s5k83a_write_sensor(sd, | ||
| 180 | init_s5k83a[i][1], data, 2); | ||
| 181 | break; | ||
| 182 | default: | ||
| 183 | info("Invalid stream command, exiting init"); | ||
| 184 | return -EINVAL; | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | if (dump_sensor) | ||
| 189 | s5k83a_dump_registers(sd); | ||
| 190 | |||
| 191 | return (err < 0) ? err : 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | int s5k83a_power_down(struct sd *sd) | ||
| 195 | { | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | |||
| 199 | void s5k83a_dump_registers(struct sd *sd) | ||
| 200 | { | ||
| 201 | int address; | ||
| 202 | u8 page, old_page; | ||
| 203 | s5k83a_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); | ||
| 204 | |||
| 205 | for (page = 0; page < 16; page++) { | ||
| 206 | s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); | ||
| 207 | info("Dumping the s5k83a register state for page 0x%x", page); | ||
| 208 | for (address = 0; address <= 0xff; address++) { | ||
| 209 | u8 val = 0; | ||
| 210 | s5k83a_read_sensor(sd, address, &val, 1); | ||
| 211 | info("register 0x%x contains 0x%x", | ||
| 212 | address, val); | ||
| 213 | } | ||
| 214 | } | ||
| 215 | info("s5k83a register state dump complete"); | ||
| 216 | |||
| 217 | for (page = 0; page < 16; page++) { | ||
| 218 | s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1); | ||
| 219 | info("Probing for which registers that are read/write " | ||
| 220 | "for page 0x%x", page); | ||
| 221 | for (address = 0; address <= 0xff; address++) { | ||
| 222 | u8 old_val, ctrl_val, test_val = 0xff; | ||
| 223 | |||
| 224 | s5k83a_read_sensor(sd, address, &old_val, 1); | ||
| 225 | s5k83a_write_sensor(sd, address, &test_val, 1); | ||
| 226 | s5k83a_read_sensor(sd, address, &ctrl_val, 1); | ||
| 227 | |||
| 228 | if (ctrl_val == test_val) | ||
| 229 | info("register 0x%x is writeable", address); | ||
| 230 | else | ||
| 231 | info("register 0x%x is read only", address); | ||
| 232 | |||
| 233 | /* Restore original val */ | ||
| 234 | s5k83a_write_sensor(sd, address, &old_val, 1); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | info("Read/write register probing complete"); | ||
| 238 | s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1); | ||
| 239 | } | ||
| 240 | |||
| 241 | int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 242 | { | ||
| 243 | int err; | ||
| 244 | u8 data[2]; | ||
| 245 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 246 | |||
| 247 | err = s5k83a_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2); | ||
| 248 | data[1] = data[1] << 1; | ||
| 249 | *val = data[1]; | ||
| 250 | |||
| 251 | return (err < 0) ? err : 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | ||
| 255 | { | ||
| 256 | int err; | ||
| 257 | u8 data[2]; | ||
| 258 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 259 | |||
| 260 | data[0] = 0x00; | ||
| 261 | data[1] = 0x20; | ||
| 262 | err = s5k83a_write_sensor(sd, 0x14, data, 2); | ||
| 263 | if (err < 0) | ||
| 264 | return err; | ||
| 265 | |||
| 266 | data[0] = 0x01; | ||
| 267 | data[1] = 0x00; | ||
| 268 | err = s5k83a_write_sensor(sd, 0x0d, data, 2); | ||
| 269 | if (err < 0) | ||
| 270 | return err; | ||
| 271 | |||
| 272 | /* FIXME: This is not sane, we need to figure out the composition | ||
| 273 | of these registers */ | ||
| 274 | data[0] = val >> 3; /* brightness, high 5 bits */ | ||
| 275 | data[1] = val >> 1; /* brightness, high 7 bits */ | ||
| 276 | err = s5k83a_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2); | ||
| 277 | |||
| 278 | return (err < 0) ? err : 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 282 | { | ||
| 283 | int err; | ||
| 284 | u8 data; | ||
| 285 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 286 | |||
| 287 | err = s5k83a_read_sensor(sd, S5K83A_WHITENESS, &data, 1); | ||
| 288 | |||
| 289 | *val = data; | ||
| 290 | return (err < 0) ? err : 0; | ||
| 291 | } | ||
| 292 | |||
| 293 | int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val) | ||
| 294 | { | ||
| 295 | int err; | ||
| 296 | u8 data[1]; | ||
| 297 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 298 | |||
| 299 | data[0] = val; | ||
| 300 | err = s5k83a_write_sensor(sd, S5K83A_WHITENESS, data, 1); | ||
| 301 | |||
| 302 | return (err < 0) ? err : 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 306 | { | ||
| 307 | int err; | ||
| 308 | u8 data[2]; | ||
| 309 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 310 | |||
| 311 | err = s5k83a_read_sensor(sd, S5K83A_GAIN, data, 2); | ||
| 312 | |||
| 313 | data[1] = data[1] & 0x3f; | ||
| 314 | if (data[1] > S5K83A_MAXIMUM_GAIN) | ||
| 315 | data[1] = S5K83A_MAXIMUM_GAIN; | ||
| 316 | |||
| 317 | *val = data[1]; | ||
| 318 | |||
| 319 | return (err < 0) ? err : 0; | ||
| 320 | } | ||
| 321 | |||
| 322 | int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
| 323 | { | ||
| 324 | int err; | ||
| 325 | u8 data[2]; | ||
| 326 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 327 | |||
| 328 | data[0] = 0; | ||
| 329 | data[1] = val; | ||
| 330 | err = s5k83a_write_sensor(sd, S5K83A_GAIN, data, 2); | ||
| 331 | |||
| 332 | return (err < 0) ? err : 0; | ||
| 333 | } | ||
| 334 | |||
| 335 | int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 336 | { | ||
| 337 | int err; | ||
| 338 | u8 data[1]; | ||
| 339 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 340 | |||
| 341 | data[0] = 0x05; | ||
| 342 | err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); | ||
| 343 | if (err < 0) | ||
| 344 | return err; | ||
| 345 | |||
| 346 | err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); | ||
| 347 | *val = (data[0] | 0x40) ? 1 : 0; | ||
| 348 | |||
| 349 | return (err < 0) ? err : 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | ||
| 353 | { | ||
| 354 | int err; | ||
| 355 | u8 data[1]; | ||
| 356 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 357 | |||
| 358 | data[0] = 0x05; | ||
| 359 | err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); | ||
| 360 | if (err < 0) | ||
| 361 | return err; | ||
| 362 | |||
| 363 | err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); | ||
| 364 | if (err < 0) | ||
| 365 | return err; | ||
| 366 | |||
| 367 | /* set or zero six bit, seven is hflip */ | ||
| 368 | data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK | ||
| 369 | : (data[0] & 0x80) | S5K83A_FLIP_MASK; | ||
| 370 | err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1); | ||
| 371 | if (err < 0) | ||
| 372 | return err; | ||
| 373 | |||
| 374 | data[0] = (val) ? 0x0b : 0x0a; | ||
| 375 | err = s5k83a_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1); | ||
| 376 | |||
| 377 | return (err < 0) ? err : 0; | ||
| 378 | } | ||
| 379 | |||
| 380 | int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 381 | { | ||
| 382 | int err; | ||
| 383 | u8 data[1]; | ||
| 384 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 385 | |||
| 386 | data[0] = 0x05; | ||
| 387 | err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); | ||
| 388 | if (err < 0) | ||
| 389 | return err; | ||
| 390 | |||
| 391 | err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); | ||
| 392 | *val = (data[0] | 0x80) ? 1 : 0; | ||
| 393 | |||
| 394 | return (err < 0) ? err : 0; | ||
| 395 | } | ||
| 396 | |||
| 397 | int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | ||
| 398 | { | ||
| 399 | int err; | ||
| 400 | u8 data[1]; | ||
| 401 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 402 | |||
| 403 | data[0] = 0x05; | ||
| 404 | err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1); | ||
| 405 | if (err < 0) | ||
| 406 | return err; | ||
| 407 | |||
| 408 | err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1); | ||
| 409 | if (err < 0) | ||
| 410 | return err; | ||
| 411 | |||
| 412 | /* set or zero seven bit, six is vflip */ | ||
| 413 | data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK | ||
| 414 | : (data[0] & 0x40) | S5K83A_FLIP_MASK; | ||
| 415 | err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1); | ||
| 416 | if (err < 0) | ||
| 417 | return err; | ||
| 418 | |||
| 419 | data[0] = (val) ? 0x0a : 0x0b; | ||
| 420 | err = s5k83a_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1); | ||
| 421 | |||
| 422 | return (err < 0) ? err : 0; | ||
| 423 | } | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h new file mode 100644 index 000000000000..833708eb5a42 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.h | |||
| @@ -0,0 +1,484 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the s5k83a sensor | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef M5602_S5K83A_H_ | ||
| 20 | #define M5602_S5K83A_H_ | ||
| 21 | |||
| 22 | #include "m5602_sensor.h" | ||
| 23 | |||
| 24 | #define S5K83A_FLIP 0x01 | ||
| 25 | #define S5K83A_HFLIP_TUNE 0x03 | ||
| 26 | #define S5K83A_VFLIP_TUNE 0x05 | ||
| 27 | #define S5K83A_WHITENESS 0x0a | ||
| 28 | #define S5K83A_GAIN 0x18 | ||
| 29 | #define S5K83A_BRIGHTNESS 0x1b | ||
| 30 | #define S5K83A_PAGE_MAP 0xec | ||
| 31 | |||
| 32 | #define S5K83A_DEFAULT_BRIGHTNESS 0x71 | ||
| 33 | #define S5K83A_DEFAULT_WHITENESS 0x7e | ||
| 34 | #define S5K83A_DEFAULT_GAIN 0x00 | ||
| 35 | #define S5K83A_MAXIMUM_GAIN 0x3c | ||
| 36 | #define S5K83A_FLIP_MASK 0x10 | ||
| 37 | |||
| 38 | |||
| 39 | /*****************************************************************************/ | ||
| 40 | |||
| 41 | /* Kernel module parameters */ | ||
| 42 | extern int force_sensor; | ||
| 43 | extern int dump_sensor; | ||
| 44 | extern unsigned int m5602_debug; | ||
| 45 | |||
| 46 | |||
| 47 | int s5k83a_probe(struct sd *sd); | ||
| 48 | int s5k83a_init(struct sd *sd); | ||
| 49 | int s5k83a_power_down(struct sd *sd); | ||
| 50 | |||
| 51 | void s5k83a_dump_registers(struct sd *sd); | ||
| 52 | |||
| 53 | int s5k83a_read_sensor(struct sd *sd, const u8 address, | ||
| 54 | u8 *i2c_data, const u8 len); | ||
| 55 | int s5k83a_write_sensor(struct sd *sd, const u8 address, | ||
| 56 | u8 *i2c_data, const u8 len); | ||
| 57 | |||
| 58 | int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); | ||
| 59 | int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 60 | int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val); | ||
| 61 | int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 62 | int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
| 63 | int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 64 | int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 65 | int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
| 66 | int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 67 | int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
| 68 | |||
| 69 | |||
| 70 | static struct m5602_sensor s5k83a = { | ||
| 71 | .name = "S5K83A", | ||
| 72 | .probe = s5k83a_probe, | ||
| 73 | .init = s5k83a_init, | ||
| 74 | .power_down = s5k83a_power_down, | ||
| 75 | .read_sensor = s5k83a_read_sensor, | ||
| 76 | .write_sensor = s5k83a_write_sensor, | ||
| 77 | .i2c_slave_id = 0x5a, | ||
| 78 | .nctrls = 5, | ||
| 79 | .ctrls = { | ||
| 80 | { | ||
| 81 | { | ||
| 82 | .id = V4L2_CID_BRIGHTNESS, | ||
| 83 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 84 | .name = "brightness", | ||
| 85 | .minimum = 0x00, | ||
| 86 | .maximum = 0xff, | ||
| 87 | .step = 0x01, | ||
| 88 | .default_value = S5K83A_DEFAULT_BRIGHTNESS, | ||
| 89 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 90 | }, | ||
| 91 | .set = s5k83a_set_brightness, | ||
| 92 | .get = s5k83a_get_brightness | ||
| 93 | |||
| 94 | }, { | ||
| 95 | { | ||
| 96 | .id = V4L2_CID_WHITENESS, | ||
| 97 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 98 | .name = "whiteness", | ||
| 99 | .minimum = 0x00, | ||
| 100 | .maximum = 0xff, | ||
| 101 | .step = 0x01, | ||
| 102 | .default_value = S5K83A_DEFAULT_WHITENESS, | ||
| 103 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 104 | }, | ||
| 105 | .set = s5k83a_set_whiteness, | ||
| 106 | .get = s5k83a_get_whiteness, | ||
| 107 | }, { | ||
| 108 | { | ||
| 109 | .id = V4L2_CID_GAIN, | ||
| 110 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 111 | .name = "gain", | ||
| 112 | .minimum = 0x00, | ||
| 113 | .maximum = S5K83A_MAXIMUM_GAIN, | ||
| 114 | .step = 0x01, | ||
| 115 | .default_value = S5K83A_DEFAULT_GAIN, | ||
| 116 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
| 117 | }, | ||
| 118 | .set = s5k83a_set_gain, | ||
| 119 | .get = s5k83a_get_gain | ||
| 120 | }, { | ||
| 121 | { | ||
| 122 | .id = V4L2_CID_HFLIP, | ||
| 123 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 124 | .name = "horizontal flip", | ||
| 125 | .minimum = 0, | ||
| 126 | .maximum = 1, | ||
| 127 | .step = 1, | ||
| 128 | .default_value = 0 | ||
| 129 | }, | ||
| 130 | .set = s5k83a_set_hflip, | ||
| 131 | .get = s5k83a_get_hflip | ||
| 132 | }, { | ||
| 133 | { | ||
| 134 | .id = V4L2_CID_VFLIP, | ||
| 135 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 136 | .name = "vertical flip", | ||
| 137 | .minimum = 0, | ||
| 138 | .maximum = 1, | ||
| 139 | .step = 1, | ||
| 140 | .default_value = 0 | ||
| 141 | }, | ||
| 142 | .set = s5k83a_set_vflip, | ||
| 143 | .get = s5k83a_get_vflip | ||
| 144 | } | ||
| 145 | }, | ||
| 146 | .nmodes = 1, | ||
| 147 | .modes = { | ||
| 148 | { | ||
| 149 | M5602_DEFAULT_FRAME_WIDTH, | ||
| 150 | M5602_DEFAULT_FRAME_HEIGHT, | ||
| 151 | V4L2_PIX_FMT_SBGGR8, | ||
| 152 | V4L2_FIELD_NONE, | ||
| 153 | .sizeimage = | ||
| 154 | M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT, | ||
| 155 | .bytesperline = M5602_DEFAULT_FRAME_WIDTH, | ||
| 156 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 157 | .priv = 1 | ||
| 158 | } | ||
| 159 | } | ||
| 160 | }; | ||
| 161 | |||
| 162 | static const unsigned char preinit_s5k83a[][4] = | ||
| 163 | { | ||
| 164 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
| 165 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
| 166 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 167 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 168 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 169 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00}, | ||
| 170 | {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00}, | ||
| 171 | |||
| 172 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 173 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 174 | {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, | ||
| 175 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, | ||
| 176 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, | ||
| 177 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
| 178 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 179 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 180 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 181 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, | ||
| 182 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, | ||
| 183 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 184 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 185 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 186 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 187 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
| 188 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
| 189 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 190 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, | ||
| 191 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 192 | {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, | ||
| 193 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 194 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, | ||
| 195 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
| 196 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 197 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, | ||
| 198 | |||
| 199 | {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00} | ||
| 200 | }; | ||
| 201 | |||
| 202 | /* This could probably be considerably shortened. | ||
| 203 | I don't have the hardware to experiment with it, patches welcome | ||
| 204 | */ | ||
| 205 | static const unsigned char init_s5k83a[][4] = | ||
| 206 | { | ||
| 207 | {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, | ||
| 208 | {SENSOR, 0xaf, 0x01, 0x00}, | ||
| 209 | {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, | ||
| 210 | {SENSOR, 0x7b, 0xff, 0x00}, | ||
| 211 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 212 | {SENSOR, 0x01, 0x50, 0x00}, | ||
| 213 | {SENSOR, 0x12, 0x20, 0x00}, | ||
| 214 | {SENSOR, 0x17, 0x40, 0x00}, | ||
| 215 | {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, | ||
| 216 | {SENSOR, 0x1c, 0x00, 0x00}, | ||
| 217 | {SENSOR, 0x02, 0x70, 0x00}, | ||
| 218 | {SENSOR, 0x03, 0x0b, 0x00}, | ||
| 219 | {SENSOR, 0x04, 0xf0, 0x00}, | ||
| 220 | {SENSOR, 0x05, 0x0b, 0x00}, | ||
| 221 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 222 | |||
| 223 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 224 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 225 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 226 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 227 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 228 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 229 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 230 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 231 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 232 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 233 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 234 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
| 235 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, | ||
| 236 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 237 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 238 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 239 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
| 240 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 241 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 242 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
| 243 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, | ||
| 244 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 245 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 246 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 247 | |||
| 248 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 249 | {SENSOR, 0x06, 0x71, 0x00}, | ||
| 250 | {SENSOR, 0x07, 0xe8, 0x00}, | ||
| 251 | {SENSOR, 0x08, 0x02, 0x00}, | ||
| 252 | {SENSOR, 0x09, 0x88, 0x00}, | ||
| 253 | {SENSOR, 0x14, 0x00, 0x00}, | ||
| 254 | {SENSOR, 0x15, 0x20, 0x00}, | ||
| 255 | {SENSOR, 0x19, 0x00, 0x00}, | ||
| 256 | {SENSOR, 0x1a, 0x98, 0x00}, | ||
| 257 | {SENSOR, 0x0f, 0x02, 0x00}, | ||
| 258 | {SENSOR, 0x10, 0xe5, 0x00}, | ||
| 259 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 260 | {SENSOR_LONG, 0x14, 0x00, 0x20}, | ||
| 261 | {SENSOR_LONG, 0x0d, 0x00, 0x7d}, | ||
| 262 | {SENSOR_LONG, 0x1b, 0x0d, 0x05}, | ||
| 263 | |||
| 264 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 265 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 266 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 267 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 268 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 269 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 270 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 271 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 272 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 273 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 274 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 275 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
| 276 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, | ||
| 277 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 278 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 279 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 280 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
| 281 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 282 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 283 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
| 284 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00}, | ||
| 285 | |||
| 286 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 287 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 288 | {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, | ||
| 289 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, | ||
| 290 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, | ||
| 291 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
| 292 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 293 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 294 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 295 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, | ||
| 296 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, | ||
| 297 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 298 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 299 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 300 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 301 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
| 302 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
| 303 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 304 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, | ||
| 305 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 306 | {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, | ||
| 307 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 308 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, | ||
| 309 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
| 310 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 311 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, | ||
| 312 | |||
| 313 | {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, | ||
| 314 | {SENSOR, 0xaf, 0x01, 0x00}, | ||
| 315 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 316 | /* ff ( init value )is very dark) || 71 and f0 better */ | ||
| 317 | {SENSOR, 0x7b, 0xff, 0x00}, | ||
| 318 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 319 | {SENSOR, 0x01, 0x50, 0x00}, | ||
| 320 | {SENSOR, 0x12, 0x20, 0x00}, | ||
| 321 | {SENSOR, 0x17, 0x40, 0x00}, | ||
| 322 | {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, | ||
| 323 | {SENSOR, 0x1c, 0x00, 0x00}, | ||
| 324 | {SENSOR, 0x02, 0x70, 0x00}, | ||
| 325 | /* some values like 0x10 give a blue-purple image */ | ||
| 326 | {SENSOR, 0x03, 0x0b, 0x00}, | ||
| 327 | {SENSOR, 0x04, 0xf0, 0x00}, | ||
| 328 | {SENSOR, 0x05, 0x0b, 0x00}, | ||
| 329 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 330 | |||
| 331 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 332 | /* under 80 don't work, highter depend on value */ | ||
| 333 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 334 | |||
| 335 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 336 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 337 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 338 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 339 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 340 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 341 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 342 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 343 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 344 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
| 345 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, | ||
| 346 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 347 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 348 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
| 349 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 350 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 351 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
| 352 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, | ||
| 353 | |||
| 354 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 355 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 356 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 357 | |||
| 358 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 359 | {SENSOR, 0x06, 0x71, 0x00}, | ||
| 360 | {SENSOR, 0x07, 0xe8, 0x00}, | ||
| 361 | {SENSOR, 0x08, 0x02, 0x00}, | ||
| 362 | {SENSOR, 0x09, 0x88, 0x00}, | ||
| 363 | {SENSOR, 0x14, 0x00, 0x00}, | ||
| 364 | {SENSOR, 0x15, 0x20, 0x00}, | ||
| 365 | {SENSOR, 0x19, 0x00, 0x00}, | ||
| 366 | {SENSOR, 0x1a, 0x98, 0x00}, | ||
| 367 | {SENSOR, 0x0f, 0x02, 0x00}, | ||
| 368 | {SENSOR, 0x10, 0xe5, 0x00}, | ||
| 369 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 370 | {SENSOR_LONG, 0x14, 0x00, 0x20}, | ||
| 371 | {SENSOR_LONG, 0x0d, 0x00, 0x7d}, | ||
| 372 | {SENSOR_LONG, 0x1b, 0x0d, 0x05}, | ||
| 373 | |||
| 374 | /* The following sequence is useless after a clean boot | ||
| 375 | but is necessary after resume from suspend */ | ||
| 376 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 377 | {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00}, | ||
| 378 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00}, | ||
| 379 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00}, | ||
| 380 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
| 381 | {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00}, | ||
| 382 | {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00}, | ||
| 383 | {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00}, | ||
| 384 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00}, | ||
| 385 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00}, | ||
| 386 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 387 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 388 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 389 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 390 | {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, | ||
| 391 | {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, | ||
| 392 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 393 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00}, | ||
| 394 | {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00}, | ||
| 395 | {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00}, | ||
| 396 | {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00}, | ||
| 397 | {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00}, | ||
| 398 | {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00}, | ||
| 399 | {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00}, | ||
| 400 | {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00}, | ||
| 401 | |||
| 402 | {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00}, | ||
| 403 | {SENSOR, 0xaf, 0x01, 0x00}, | ||
| 404 | {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}, | ||
| 405 | {SENSOR, 0x7b, 0xff, 0x00}, | ||
| 406 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 407 | {SENSOR, 0x01, 0x50, 0x00}, | ||
| 408 | {SENSOR, 0x12, 0x20, 0x00}, | ||
| 409 | {SENSOR, 0x17, 0x40, 0x00}, | ||
| 410 | {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00}, | ||
| 411 | {SENSOR, 0x1c, 0x00, 0x00}, | ||
| 412 | {SENSOR, 0x02, 0x70, 0x00}, | ||
| 413 | {SENSOR, 0x03, 0x0b, 0x00}, | ||
| 414 | {SENSOR, 0x04, 0xf0, 0x00}, | ||
| 415 | {SENSOR, 0x05, 0x0b, 0x00}, | ||
| 416 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 417 | |||
| 418 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00}, | ||
| 419 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 420 | {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00}, | ||
| 421 | {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00}, | ||
| 422 | {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, | ||
| 423 | {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, | ||
| 424 | {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, | ||
| 425 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 426 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 427 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 428 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 429 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, | ||
| 430 | {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, | ||
| 431 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 432 | {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, | ||
| 433 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 434 | {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00}, | ||
| 435 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 436 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, | ||
| 437 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, | ||
| 438 | {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, | ||
| 439 | {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00}, | ||
| 440 | {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00}, | ||
| 441 | {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00}, | ||
| 442 | |||
| 443 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 444 | {SENSOR, 0x06, 0x71, 0x00}, | ||
| 445 | {SENSOR, 0x07, 0xe8, 0x00}, | ||
| 446 | {SENSOR, 0x08, 0x02, 0x00}, | ||
| 447 | {SENSOR, 0x09, 0x88, 0x00}, | ||
| 448 | {SENSOR, 0x14, 0x00, 0x00}, | ||
| 449 | {SENSOR, 0x15, 0x20, 0x00}, | ||
| 450 | {SENSOR, 0x19, 0x00, 0x00}, | ||
| 451 | {SENSOR, 0x1a, 0x98, 0x00}, | ||
| 452 | {SENSOR, 0x0f, 0x02, 0x00}, | ||
| 453 | |||
| 454 | {SENSOR, 0x10, 0xe5, 0x00}, | ||
| 455 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 456 | {SENSOR_LONG, 0x14, 0x00, 0x20}, | ||
| 457 | {SENSOR_LONG, 0x0d, 0x00, 0x7d}, | ||
| 458 | {SENSOR_LONG, 0x1b, 0x0d, 0x05}, | ||
| 459 | |||
| 460 | /* normal colors | ||
| 461 | (this is value after boot, but after tries can be different) */ | ||
| 462 | {SENSOR, 0x00, 0x06, 0x00}, | ||
| 463 | |||
| 464 | /* set default brightness */ | ||
| 465 | {SENSOR_LONG, 0x14, 0x00, 0x20}, | ||
| 466 | {SENSOR_LONG, 0x0d, 0x01, 0x00}, | ||
| 467 | {SENSOR_LONG, 0x1b, S5K83A_DEFAULT_BRIGHTNESS >> 3, | ||
| 468 | S5K83A_DEFAULT_BRIGHTNESS >> 1}, | ||
| 469 | |||
| 470 | /* set default whiteness */ | ||
| 471 | {SENSOR, S5K83A_WHITENESS, S5K83A_DEFAULT_WHITENESS, 0x00}, | ||
| 472 | |||
| 473 | /* set default gain */ | ||
| 474 | {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN}, | ||
| 475 | |||
| 476 | /* set default flip */ | ||
| 477 | {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00}, | ||
| 478 | {SENSOR, S5K83A_FLIP, 0x00 | S5K83A_FLIP_MASK, 0x00}, | ||
| 479 | {SENSOR, S5K83A_HFLIP_TUNE, 0x0b, 0x00}, | ||
| 480 | {SENSOR, S5K83A_VFLIP_TUNE, 0x0a, 0x00} | ||
| 481 | |||
| 482 | }; | ||
| 483 | |||
| 484 | #endif | ||
diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h new file mode 100644 index 000000000000..930fcaab4416 --- /dev/null +++ b/drivers/media/video/gspca/m5602/m5602_sensor.h | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | /* | ||
| 2 | * USB Driver for ALi m5602 based webcams | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Erik Andren | ||
| 5 | * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. | ||
| 6 | * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> | ||
| 7 | * | ||
| 8 | * Portions of code to USB interface and ALi driver software, | ||
| 9 | * Copyright (c) 2006 Willem Duinker | ||
| 10 | * v4l2 interface modeled after the V4L2 driver | ||
| 11 | * for SN9C10x PC Camera Controllers | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or | ||
| 14 | * modify it under the terms of the GNU General Public License as | ||
| 15 | * published by the Free Software Foundation, version 2. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef M5602_SENSOR_H_ | ||
| 20 | #define M5602_SENSOR_H_ | ||
| 21 | |||
| 22 | #include "m5602_bridge.h" | ||
| 23 | |||
| 24 | #define M5602_DEFAULT_FRAME_WIDTH 640 | ||
| 25 | #define M5602_DEFAULT_FRAME_HEIGHT 480 | ||
| 26 | |||
| 27 | #define M5602_MAX_CTRLS (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10) | ||
| 28 | |||
| 29 | /* Enumerates all supported sensors */ | ||
| 30 | enum sensors { | ||
| 31 | OV9650_SENSOR = 1, | ||
| 32 | S5K83A_SENSOR = 2, | ||
| 33 | S5K4AA_SENSOR = 3, | ||
| 34 | MT9M111_SENSOR = 4, | ||
| 35 | PO1030_SENSOR = 5 | ||
| 36 | }; | ||
| 37 | |||
| 38 | /* Enumerates all possible instruction types */ | ||
| 39 | enum instruction { | ||
| 40 | BRIDGE, | ||
| 41 | SENSOR, | ||
| 42 | SENSOR_LONG | ||
| 43 | }; | ||
| 44 | |||
| 45 | struct m5602_sensor { | ||
| 46 | /* Defines the name of a sensor */ | ||
| 47 | char name[32]; | ||
| 48 | |||
| 49 | /* What i2c address the sensor is connected to */ | ||
| 50 | u8 i2c_slave_id; | ||
| 51 | |||
| 52 | /* Probes if the sensor is connected */ | ||
| 53 | int (*probe)(struct sd *sd); | ||
| 54 | |||
| 55 | /* Performs a initialization sequence */ | ||
| 56 | int (*init)(struct sd *sd); | ||
| 57 | |||
| 58 | /* Performs a power down sequence */ | ||
| 59 | int (*power_down)(struct sd *sd); | ||
| 60 | |||
| 61 | /* Reads a sensor register */ | ||
| 62 | int (*read_sensor)(struct sd *sd, const u8 address, | ||
| 63 | u8 *i2c_data, const u8 len); | ||
| 64 | |||
| 65 | /* Writes to a sensor register */ | ||
| 66 | int (*write_sensor)(struct sd *sd, const u8 address, | ||
| 67 | u8 *i2c_data, const u8 len); | ||
| 68 | |||
| 69 | int nctrls; | ||
| 70 | struct ctrl ctrls[M5602_MAX_CTRLS]; | ||
| 71 | |||
| 72 | char nmodes; | ||
| 73 | struct v4l2_pix_format modes[]; | ||
| 74 | }; | ||
| 75 | |||
| 76 | #endif | ||
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 4d5db47ba8cb..277ca34a8817 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c | |||
| @@ -134,7 +134,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 134 | return 0; | 134 | return 0; |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static void sd_start(struct gspca_dev *gspca_dev) | 137 | static int sd_start(struct gspca_dev *gspca_dev) |
| 138 | { | 138 | { |
| 139 | int err_code; | 139 | int err_code; |
| 140 | __u8 *data; | 140 | __u8 *data; |
| @@ -143,9 +143,10 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 143 | int intpipe; | 143 | int intpipe; |
| 144 | 144 | ||
| 145 | PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface); | 145 | PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface); |
| 146 | if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8) < 0) { | 146 | err_code = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8); |
| 147 | if (err_code < 0) { | ||
| 147 | PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error"); | 148 | PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error"); |
| 148 | return; | 149 | return err_code; |
| 149 | } | 150 | } |
| 150 | 151 | ||
| 151 | data = gspca_dev->usb_buf; | 152 | data = gspca_dev->usb_buf; |
| @@ -154,7 +155,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 154 | 155 | ||
| 155 | err_code = reg_w(gspca_dev, data[0], 2); | 156 | err_code = reg_w(gspca_dev, data[0], 2); |
| 156 | if (err_code < 0) | 157 | if (err_code < 0) |
| 157 | return; | 158 | return err_code; |
| 158 | 159 | ||
| 159 | /* | 160 | /* |
| 160 | Initialize the MR97113 chip register | 161 | Initialize the MR97113 chip register |
| @@ -180,14 +181,14 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 180 | 181 | ||
| 181 | err_code = reg_w(gspca_dev, data[0], 11); | 182 | err_code = reg_w(gspca_dev, data[0], 11); |
| 182 | if (err_code < 0) | 183 | if (err_code < 0) |
| 183 | return; | 184 | return err_code; |
| 184 | 185 | ||
| 185 | data[0] = 0x23; /* address */ | 186 | data[0] = 0x23; /* address */ |
| 186 | data[1] = 0x09; /* reg 35, append frame header */ | 187 | data[1] = 0x09; /* reg 35, append frame header */ |
| 187 | 188 | ||
| 188 | err_code = reg_w(gspca_dev, data[0], 2); | 189 | err_code = reg_w(gspca_dev, data[0], 2); |
| 189 | if (err_code < 0) | 190 | if (err_code < 0) |
| 190 | return; | 191 | return err_code; |
| 191 | 192 | ||
| 192 | data[0] = 0x3c; /* address */ | 193 | data[0] = 0x3c; /* address */ |
| 193 | /* if (gspca_dev->width == 1280) */ | 194 | /* if (gspca_dev->width == 1280) */ |
| @@ -198,7 +199,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 198 | * (unit: 4KB) 200KB */ | 199 | * (unit: 4KB) 200KB */ |
| 199 | err_code = reg_w(gspca_dev, data[0], 2); | 200 | err_code = reg_w(gspca_dev, data[0], 2); |
| 200 | if (err_code < 0) | 201 | if (err_code < 0) |
| 201 | return; | 202 | return err_code; |
| 202 | 203 | ||
| 203 | if (0) { /* fixed dark-gain */ | 204 | if (0) { /* fixed dark-gain */ |
| 204 | data[1] = 0; /* reg 94, Y Gain (1.75) */ | 205 | data[1] = 0; /* reg 94, Y Gain (1.75) */ |
| @@ -240,13 +241,13 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 240 | 241 | ||
| 241 | err_code = reg_w(gspca_dev, data[0], 6); | 242 | err_code = reg_w(gspca_dev, data[0], 6); |
| 242 | if (err_code < 0) | 243 | if (err_code < 0) |
| 243 | return; | 244 | return err_code; |
| 244 | 245 | ||
| 245 | data[0] = 0x67; | 246 | data[0] = 0x67; |
| 246 | data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */ | 247 | data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */ |
| 247 | err_code = reg_w(gspca_dev, data[0], 2); | 248 | err_code = reg_w(gspca_dev, data[0], 2); |
| 248 | if (err_code < 0) | 249 | if (err_code < 0) |
| 249 | return; | 250 | return err_code; |
| 250 | 251 | ||
| 251 | /* | 252 | /* |
| 252 | * initialize the value of MI sensor... | 253 | * initialize the value of MI sensor... |
| @@ -326,6 +327,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 326 | data[0] = 0x00; | 327 | data[0] = 0x00; |
| 327 | data[1] = 0x4d; /* ISOC transfering enable... */ | 328 | data[1] = 0x4d; /* ISOC transfering enable... */ |
| 328 | reg_w(gspca_dev, data[0], 2); | 329 | reg_w(gspca_dev, data[0], 2); |
| 330 | return err_code; | ||
| 329 | } | 331 | } |
| 330 | 332 | ||
| 331 | static void sd_stopN(struct gspca_dev *gspca_dev) | 333 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 4df4eec9f7e7..ca671194679e 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
| @@ -1854,7 +1854,7 @@ static int set_ov_sensor_window(struct sd *sd) | |||
| 1854 | } | 1854 | } |
| 1855 | 1855 | ||
| 1856 | /* -- start the camera -- */ | 1856 | /* -- start the camera -- */ |
| 1857 | static void sd_start(struct gspca_dev *gspca_dev) | 1857 | static int sd_start(struct gspca_dev *gspca_dev) |
| 1858 | { | 1858 | { |
| 1859 | struct sd *sd = (struct sd *) gspca_dev; | 1859 | struct sd *sd = (struct sd *) gspca_dev; |
| 1860 | int ret; | 1860 | int ret; |
| @@ -1871,9 +1871,10 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 1871 | goto out; | 1871 | goto out; |
| 1872 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); | 1872 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); |
| 1873 | ov51x_led_control(sd, 1); | 1873 | ov51x_led_control(sd, 1); |
| 1874 | return; | 1874 | return 0; |
| 1875 | out: | 1875 | out: |
| 1876 | PDEBUG(D_ERR, "camera start error:%d", ret); | 1876 | PDEBUG(D_ERR, "camera start error:%d", ret); |
| 1877 | return ret; | ||
| 1877 | } | 1878 | } |
| 1878 | 1879 | ||
| 1879 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1880 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 83b5f740c947..0b0c573d06da 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c | |||
| @@ -281,7 +281,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | /* -- start the camera -- */ | 283 | /* -- start the camera -- */ |
| 284 | static void sd_start(struct gspca_dev *gspca_dev) | 284 | static int sd_start(struct gspca_dev *gspca_dev) |
| 285 | { | 285 | { |
| 286 | struct sd *sd = (struct sd *) gspca_dev; | 286 | struct sd *sd = (struct sd *) gspca_dev; |
| 287 | __u8 mode; | 287 | __u8 mode; |
| @@ -323,6 +323,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 323 | sd->sof_read = 0; | 323 | sd->sof_read = 0; |
| 324 | sd->autogain_ignore_frames = 0; | 324 | sd->autogain_ignore_frames = 0; |
| 325 | atomic_set(&sd->avg_lum, -1); | 325 | atomic_set(&sd->avg_lum, -1); |
| 326 | return 0; | ||
| 326 | } | 327 | } |
| 327 | 328 | ||
| 328 | static void sd_stopN(struct gspca_dev *gspca_dev) | 329 | static void sd_stopN(struct gspca_dev *gspca_dev) |
| @@ -534,6 +535,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
| 534 | {USB_DEVICE(0x093a, 0x2470)}, | 535 | {USB_DEVICE(0x093a, 0x2470)}, |
| 535 | {USB_DEVICE(0x093a, 0x2471)}, | 536 | {USB_DEVICE(0x093a, 0x2471)}, |
| 536 | {USB_DEVICE(0x093a, 0x2472)}, | 537 | {USB_DEVICE(0x093a, 0x2472)}, |
| 538 | {USB_DEVICE(0x093a, 0x2476)}, | ||
| 537 | {USB_DEVICE(0x2001, 0xf115)}, | 539 | {USB_DEVICE(0x2001, 0xf115)}, |
| 538 | {} | 540 | {} |
| 539 | }; | 541 | }; |
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index ba865b7f1ed8..e5ff9a6199ef 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
| @@ -675,7 +675,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 675 | return 0; | 675 | return 0; |
| 676 | } | 676 | } |
| 677 | 677 | ||
| 678 | static void sd_start(struct gspca_dev *gspca_dev) | 678 | static int sd_start(struct gspca_dev *gspca_dev) |
| 679 | { | 679 | { |
| 680 | struct sd *sd = (struct sd *) gspca_dev; | 680 | struct sd *sd = (struct sd *) gspca_dev; |
| 681 | 681 | ||
| @@ -724,6 +724,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 724 | reg_w(gspca_dev, 0x78, 0x01); | 724 | reg_w(gspca_dev, 0x78, 0x01); |
| 725 | else | 725 | else |
| 726 | reg_w(gspca_dev, 0x78, 0x05); | 726 | reg_w(gspca_dev, 0x78, 0x05); |
| 727 | return 0; | ||
| 727 | } | 728 | } |
| 728 | 729 | ||
| 729 | static void sd_stopN(struct gspca_dev *gspca_dev) | 730 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 12b81ae526b7..6c69bc7778fc 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
| @@ -490,7 +490,7 @@ static const __u8 tas5130_sensor_init[][8] = { | |||
| 490 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}, | 490 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}, |
| 491 | }; | 491 | }; |
| 492 | 492 | ||
| 493 | struct sensor_data sensor_data[] = { | 493 | static struct sensor_data sensor_data[] = { |
| 494 | SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), | 494 | SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), |
| 495 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), | 495 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), |
| 496 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, | 496 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, |
| @@ -892,7 +892,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 892 | } | 892 | } |
| 893 | 893 | ||
| 894 | /* -- start the camera -- */ | 894 | /* -- start the camera -- */ |
| 895 | static void sd_start(struct gspca_dev *gspca_dev) | 895 | static int sd_start(struct gspca_dev *gspca_dev) |
| 896 | { | 896 | { |
| 897 | struct sd *sd = (struct sd *) gspca_dev; | 897 | struct sd *sd = (struct sd *) gspca_dev; |
| 898 | struct cam *cam = &gspca_dev->cam; | 898 | struct cam *cam = &gspca_dev->cam; |
| @@ -976,6 +976,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 976 | sd->frames_to_drop = 0; | 976 | sd->frames_to_drop = 0; |
| 977 | sd->autogain_ignore_frames = 0; | 977 | sd->autogain_ignore_frames = 0; |
| 978 | atomic_set(&sd->avg_lum, -1); | 978 | atomic_set(&sd->avg_lum, -1); |
| 979 | return 0; | ||
| 979 | } | 980 | } |
| 980 | 981 | ||
| 981 | static void sd_stopN(struct gspca_dev *gspca_dev) | 982 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 572b0f363b64..53cb82d9e7c6 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
| @@ -39,6 +39,7 @@ struct sd { | |||
| 39 | unsigned char contrast; | 39 | unsigned char contrast; |
| 40 | unsigned char colors; | 40 | unsigned char colors; |
| 41 | unsigned char autogain; | 41 | unsigned char autogain; |
| 42 | __u8 vflip; /* ov7630 only */ | ||
| 42 | 43 | ||
| 43 | signed char ag_cnt; | 44 | signed char ag_cnt; |
| 44 | #define AG_CNT_START 13 | 45 | #define AG_CNT_START 13 |
| @@ -70,6 +71,8 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | |||
| 70 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | 71 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); |
| 71 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 72 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
| 72 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 73 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
| 74 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | ||
| 75 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
| 73 | 76 | ||
| 74 | static struct ctrl sd_ctrls[] = { | 77 | static struct ctrl sd_ctrls[] = { |
| 75 | { | 78 | { |
| @@ -131,6 +134,22 @@ static struct ctrl sd_ctrls[] = { | |||
| 131 | .set = sd_setautogain, | 134 | .set = sd_setautogain, |
| 132 | .get = sd_getautogain, | 135 | .get = sd_getautogain, |
| 133 | }, | 136 | }, |
| 137 | /* ov7630 only */ | ||
| 138 | #define VFLIP_IDX 4 | ||
| 139 | { | ||
| 140 | { | ||
| 141 | .id = V4L2_CID_VFLIP, | ||
| 142 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 143 | .name = "Vflip", | ||
| 144 | .minimum = 0, | ||
| 145 | .maximum = 1, | ||
| 146 | .step = 1, | ||
| 147 | #define VFLIP_DEF 1 | ||
| 148 | .default_value = VFLIP_DEF, | ||
| 149 | }, | ||
| 150 | .set = sd_setvflip, | ||
| 151 | .get = sd_getvflip, | ||
| 152 | }, | ||
| 134 | }; | 153 | }; |
| 135 | 154 | ||
| 136 | static struct v4l2_pix_format vga_mode[] = { | 155 | static struct v4l2_pix_format vga_mode[] = { |
| @@ -248,10 +267,12 @@ static const __u8 gamma_def[] = { | |||
| 248 | 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff | 267 | 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff |
| 249 | }; | 268 | }; |
| 250 | 269 | ||
| 270 | /* color matrix and offsets */ | ||
| 251 | static const __u8 reg84[] = { | 271 | static const __u8 reg84[] = { |
| 252 | 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f, | 272 | 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */ |
| 253 | 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f, | 273 | 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */ |
| 254 | 0xf7, 0x0f, 0x00, 0x00, 0x00 | 274 | 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */ |
| 275 | 0x00, 0x00, 0x00 /* YUV offsets */ | ||
| 255 | }; | 276 | }; |
| 256 | static const __u8 hv7131r_sensor_init[][8] = { | 277 | static const __u8 hv7131r_sensor_init[][8] = { |
| 257 | {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, | 278 | {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, |
| @@ -434,7 +455,8 @@ static const __u8 ov7630_sensor_init[][8] = { | |||
| 434 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, | 455 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, |
| 435 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, | 456 | {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, |
| 436 | /*fixme: + 0x12, 0x04*/ | 457 | /*fixme: + 0x12, 0x04*/ |
| 437 | {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, | 458 | /* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN |
| 459 | * set by setvflip */ | ||
| 438 | {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, | 460 | {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, |
| 439 | {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, | 461 | {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, |
| 440 | {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, | 462 | {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, |
| @@ -949,6 +971,8 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 949 | gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX); | 971 | gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX); |
| 950 | break; | 972 | break; |
| 951 | } | 973 | } |
| 974 | if (sd->sensor != SENSOR_OV7630) | ||
| 975 | gspca_dev->ctrl_dis |= (1 << VFLIP_IDX); | ||
| 952 | 976 | ||
| 953 | return 0; | 977 | return 0; |
| 954 | } | 978 | } |
| @@ -1080,20 +1104,17 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev, | |||
| 1080 | static void setbrightcont(struct gspca_dev *gspca_dev) | 1104 | static void setbrightcont(struct gspca_dev *gspca_dev) |
| 1081 | { | 1105 | { |
| 1082 | struct sd *sd = (struct sd *) gspca_dev; | 1106 | struct sd *sd = (struct sd *) gspca_dev; |
| 1083 | unsigned val; | 1107 | int val; |
| 1084 | __u8 reg84_full[0x15]; | 1108 | __u8 reg84_full[0x15]; |
| 1085 | 1109 | ||
| 1086 | memset(reg84_full, 0, sizeof reg84_full); | 1110 | memcpy(reg84_full, reg84, sizeof reg84_full); |
| 1087 | val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */ | 1111 | val = sd->contrast * 0x30 / CONTRAST_MAX + 0x10; /* 10..40 */ |
| 1088 | reg84_full[2] = val; | 1112 | reg84_full[0] = (val + 1) / 2; /* red */ |
| 1089 | reg84_full[0] = (val + 1) / 2; | 1113 | reg84_full[2] = val; /* green */ |
| 1090 | reg84_full[4] = (val + 1) / 5; | 1114 | reg84_full[4] = (val + 1) / 5; /* blue */ |
| 1091 | if (val > BRIGHTNESS_DEF) | 1115 | val = (sd->brightness - BRIGHTNESS_DEF) * 0x10 |
| 1092 | val = (sd->brightness - BRIGHTNESS_DEF) * 0x20 | ||
| 1093 | / BRIGHTNESS_MAX; | 1116 | / BRIGHTNESS_MAX; |
| 1094 | else | 1117 | reg84_full[0x12] = val & 0x1f; /* 5:0 signed value */ |
| 1095 | val = 0; | ||
| 1096 | reg84_full[0x12] = val; /* 00..1f */ | ||
| 1097 | reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full); | 1118 | reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full); |
| 1098 | } | 1119 | } |
| 1099 | 1120 | ||
| @@ -1172,8 +1193,16 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
| 1172 | sd->ag_cnt = -1; | 1193 | sd->ag_cnt = -1; |
| 1173 | } | 1194 | } |
| 1174 | 1195 | ||
| 1196 | static void setvflip(struct sd *sd) | ||
| 1197 | { | ||
| 1198 | if (sd->sensor != SENSOR_OV7630) | ||
| 1199 | return; | ||
| 1200 | i2c_w1(&sd->gspca_dev, 0x75, /* COMN */ | ||
| 1201 | sd->vflip ? 0x82 : 0x02); | ||
| 1202 | } | ||
| 1203 | |||
| 1175 | /* -- start the camera -- */ | 1204 | /* -- start the camera -- */ |
| 1176 | static void sd_start(struct gspca_dev *gspca_dev) | 1205 | static int sd_start(struct gspca_dev *gspca_dev) |
| 1177 | { | 1206 | { |
| 1178 | struct sd *sd = (struct sd *) gspca_dev; | 1207 | struct sd *sd = (struct sd *) gspca_dev; |
| 1179 | int i; | 1208 | int i; |
| @@ -1263,6 +1292,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 1263 | break; | 1292 | break; |
| 1264 | case SENSOR_OV7630: | 1293 | case SENSOR_OV7630: |
| 1265 | ov7630_InitSensor(gspca_dev); | 1294 | ov7630_InitSensor(gspca_dev); |
| 1295 | setvflip(sd); | ||
| 1266 | reg17 = 0xe2; | 1296 | reg17 = 0xe2; |
| 1267 | reg1 = 0x44; | 1297 | reg1 = 0x44; |
| 1268 | break; | 1298 | break; |
| @@ -1320,12 +1350,16 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 1320 | setbrightness(gspca_dev); | 1350 | setbrightness(gspca_dev); |
| 1321 | setcontrast(gspca_dev); | 1351 | setcontrast(gspca_dev); |
| 1322 | break; | 1352 | break; |
| 1353 | case SENSOR_OV7630: | ||
| 1354 | setvflip(sd); | ||
| 1355 | /* fall thru */ | ||
| 1323 | default: /* OV76xx */ | 1356 | default: /* OV76xx */ |
| 1324 | setbrightcont(gspca_dev); | 1357 | setbrightcont(gspca_dev); |
| 1325 | break; | 1358 | break; |
| 1326 | } | 1359 | } |
| 1327 | setautogain(gspca_dev); | 1360 | setautogain(gspca_dev); |
| 1328 | reg_w1(gspca_dev, 0x01, reg1); | 1361 | reg_w1(gspca_dev, 0x01, reg1); |
| 1362 | return 0; | ||
| 1329 | } | 1363 | } |
| 1330 | 1364 | ||
| 1331 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1365 | static void sd_stopN(struct gspca_dev *gspca_dev) |
| @@ -1546,6 +1580,24 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | |||
| 1546 | return 0; | 1580 | return 0; |
| 1547 | } | 1581 | } |
| 1548 | 1582 | ||
| 1583 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | ||
| 1584 | { | ||
| 1585 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 1586 | |||
| 1587 | sd->vflip = val; | ||
| 1588 | if (gspca_dev->streaming) | ||
| 1589 | setvflip(sd); | ||
| 1590 | return 0; | ||
| 1591 | } | ||
| 1592 | |||
| 1593 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
| 1594 | { | ||
| 1595 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 1596 | |||
| 1597 | *val = sd->vflip; | ||
| 1598 | return 0; | ||
| 1599 | } | ||
| 1600 | |||
| 1549 | /* sub-driver description */ | 1601 | /* sub-driver description */ |
| 1550 | static const struct sd_desc sd_desc = { | 1602 | static const struct sd_desc sd_desc = { |
| 1551 | .name = MODULE_NAME, | 1603 | .name = MODULE_NAME, |
| @@ -1567,6 +1619,7 @@ static const struct sd_desc sd_desc = { | |||
| 1567 | static const __devinitdata struct usb_device_id device_table[] = { | 1619 | static const __devinitdata struct usb_device_id device_table[] = { |
| 1568 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1620 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
| 1569 | {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)}, | 1621 | {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)}, |
| 1622 | {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)}, | ||
| 1570 | {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)}, | 1623 | {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)}, |
| 1571 | {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)}, | 1624 | {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)}, |
| 1572 | {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)}, | 1625 | {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)}, |
| @@ -1588,7 +1641,9 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
| 1588 | /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */ | 1641 | /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */ |
| 1589 | {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, | 1642 | {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, |
| 1590 | {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, | 1643 | {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, |
| 1591 | /* {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */ | 1644 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
| 1645 | {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, | ||
| 1646 | #endif | ||
| 1592 | /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */ | 1647 | /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */ |
| 1593 | /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ | 1648 | /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ |
| 1594 | /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ | 1649 | /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ |
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 6e733901fcca..bca106c153fa 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c | |||
| @@ -660,7 +660,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 660 | return 0; | 660 | return 0; |
| 661 | } | 661 | } |
| 662 | 662 | ||
| 663 | static void sd_start(struct gspca_dev *gspca_dev) | 663 | static int sd_start(struct gspca_dev *gspca_dev) |
| 664 | { | 664 | { |
| 665 | struct sd *sd = (struct sd *) gspca_dev; | 665 | struct sd *sd = (struct sd *) gspca_dev; |
| 666 | int err; | 666 | int err; |
| @@ -867,6 +867,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 867 | write_vector(gspca_dev, Clicksmart510_defaults); | 867 | write_vector(gspca_dev, Clicksmart510_defaults); |
| 868 | break; | 868 | break; |
| 869 | } | 869 | } |
| 870 | return 0; | ||
| 870 | } | 871 | } |
| 871 | 872 | ||
| 872 | static void sd_stopN(struct gspca_dev *gspca_dev) | 873 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index e9eb59bae4fb..b742f260c7ca 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c | |||
| @@ -1980,7 +1980,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 1980 | return 0; | 1980 | return 0; |
| 1981 | } | 1981 | } |
| 1982 | 1982 | ||
| 1983 | static void sd_start(struct gspca_dev *gspca_dev) | 1983 | static int sd_start(struct gspca_dev *gspca_dev) |
| 1984 | { | 1984 | { |
| 1985 | struct usb_device *dev = gspca_dev->dev; | 1985 | struct usb_device *dev = gspca_dev->dev; |
| 1986 | int mode; | 1986 | int mode; |
| @@ -2012,6 +2012,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 2012 | setbrightness(gspca_dev); | 2012 | setbrightness(gspca_dev); |
| 2013 | setcontrast(gspca_dev); | 2013 | setcontrast(gspca_dev); |
| 2014 | setcolors(gspca_dev); | 2014 | setcolors(gspca_dev); |
| 2015 | return 0; | ||
| 2015 | } | 2016 | } |
| 2016 | 2017 | ||
| 2017 | static void sd_stopN(struct gspca_dev *gspca_dev) | 2018 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index f601daf19ebe..b345749213cf 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c | |||
| @@ -688,7 +688,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 688 | return 0; | 688 | return 0; |
| 689 | } | 689 | } |
| 690 | 690 | ||
| 691 | static void sd_start(struct gspca_dev *gspca_dev) | 691 | static int sd_start(struct gspca_dev *gspca_dev) |
| 692 | { | 692 | { |
| 693 | struct usb_device *dev = gspca_dev->dev; | 693 | struct usb_device *dev = gspca_dev->dev; |
| 694 | int ret; | 694 | int ret; |
| @@ -733,6 +733,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 733 | /* reg_write(dev, 0x5, 0x0, 0x0); */ | 733 | /* reg_write(dev, 0x5, 0x0, 0x0); */ |
| 734 | /* reg_write(dev, 0x5, 0x0, 0x1); */ | 734 | /* reg_write(dev, 0x5, 0x0, 0x1); */ |
| 735 | /* reg_write(dev, 0x5, 0x11, 0x2); */ | 735 | /* reg_write(dev, 0x5, 0x11, 0x2); */ |
| 736 | return ret; | ||
| 736 | } | 737 | } |
| 737 | 738 | ||
| 738 | static void sd_stopN(struct gspca_dev *gspca_dev) | 739 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 195dce96ef06..645ee9d44d02 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c | |||
| @@ -422,7 +422,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 422 | return 0; | 422 | return 0; |
| 423 | } | 423 | } |
| 424 | 424 | ||
| 425 | static void sd_start(struct gspca_dev *gspca_dev) | 425 | static int sd_start(struct gspca_dev *gspca_dev) |
| 426 | { | 426 | { |
| 427 | struct usb_device *dev = gspca_dev->dev; | 427 | struct usb_device *dev = gspca_dev->dev; |
| 428 | __u16 norme; | 428 | __u16 norme; |
| @@ -549,6 +549,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 549 | PDEBUG(D_STREAM, "webcam started"); | 549 | PDEBUG(D_STREAM, "webcam started"); |
| 550 | spca506_GetNormeInput(gspca_dev, &norme, &channel); | 550 | spca506_GetNormeInput(gspca_dev, &norme, &channel); |
| 551 | spca506_SetNormeInput(gspca_dev, norme, channel); | 551 | spca506_SetNormeInput(gspca_dev, norme, channel); |
| 552 | return 0; | ||
| 552 | } | 553 | } |
| 553 | 554 | ||
| 554 | static void sd_stopN(struct gspca_dev *gspca_dev) | 555 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 281ce02103a3..63ec902c895d 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c | |||
| @@ -1528,7 +1528,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 1528 | return 0; | 1528 | return 0; |
| 1529 | } | 1529 | } |
| 1530 | 1530 | ||
| 1531 | static void sd_start(struct gspca_dev *gspca_dev) | 1531 | static int sd_start(struct gspca_dev *gspca_dev) |
| 1532 | { | 1532 | { |
| 1533 | int mode; | 1533 | int mode; |
| 1534 | 1534 | ||
| @@ -1546,6 +1546,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 1546 | break; | 1546 | break; |
| 1547 | } | 1547 | } |
| 1548 | reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20); | 1548 | reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20); |
| 1549 | return 0; | ||
| 1549 | } | 1550 | } |
| 1550 | 1551 | ||
| 1551 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1552 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 95fcfcb9e31b..020a03c466c1 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
| @@ -152,7 +152,7 @@ static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value) | |||
| 152 | 152 | ||
| 153 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 153 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
| 154 | 0, /* request */ | 154 | 0, /* request */ |
| 155 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 155 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 156 | value, index, NULL, 0, 500); | 156 | value, index, NULL, 0, 500); |
| 157 | PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value); | 157 | PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value); |
| 158 | if (ret < 0) | 158 | if (ret < 0) |
| @@ -699,7 +699,7 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
| 699 | sd->ag_cnt = -1; | 699 | sd->ag_cnt = -1; |
| 700 | } | 700 | } |
| 701 | 701 | ||
| 702 | static void sd_start_12a(struct gspca_dev *gspca_dev) | 702 | static int sd_start_12a(struct gspca_dev *gspca_dev) |
| 703 | { | 703 | { |
| 704 | struct usb_device *dev = gspca_dev->dev; | 704 | struct usb_device *dev = gspca_dev->dev; |
| 705 | int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */ | 705 | int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */ |
| @@ -725,8 +725,9 @@ static void sd_start_12a(struct gspca_dev *gspca_dev) | |||
| 725 | setwhite(gspca_dev); | 725 | setwhite(gspca_dev); |
| 726 | setautogain(gspca_dev); | 726 | setautogain(gspca_dev); |
| 727 | setexposure(gspca_dev); | 727 | setexposure(gspca_dev); |
| 728 | return 0; | ||
| 728 | } | 729 | } |
| 729 | static void sd_start_72a(struct gspca_dev *gspca_dev) | 730 | static int sd_start_72a(struct gspca_dev *gspca_dev) |
| 730 | { | 731 | { |
| 731 | struct usb_device *dev = gspca_dev->dev; | 732 | struct usb_device *dev = gspca_dev->dev; |
| 732 | int Clck; | 733 | int Clck; |
| @@ -750,6 +751,7 @@ static void sd_start_72a(struct gspca_dev *gspca_dev) | |||
| 750 | reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ | 751 | reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ |
| 751 | reg_w_val(dev, 0x8112, 0x10 | 0x20); | 752 | reg_w_val(dev, 0x8112, 0x10 | 0x20); |
| 752 | setautogain(gspca_dev); | 753 | setautogain(gspca_dev); |
| 754 | return 0; | ||
| 753 | } | 755 | } |
| 754 | 756 | ||
| 755 | static void sd_stopN(struct gspca_dev *gspca_dev) | 757 | static void sd_stopN(struct gspca_dev *gspca_dev) |
| @@ -1064,7 +1066,7 @@ static struct ctrl sd_ctrls_12a[] = { | |||
| 1064 | { | 1066 | { |
| 1065 | .id = V4L2_CID_DO_WHITE_BALANCE, | 1067 | .id = V4L2_CID_DO_WHITE_BALANCE, |
| 1066 | .type = V4L2_CTRL_TYPE_INTEGER, | 1068 | .type = V4L2_CTRL_TYPE_INTEGER, |
| 1067 | .name = "While Balance", | 1069 | .name = "White Balance", |
| 1068 | .minimum = WHITE_MIN, | 1070 | .minimum = WHITE_MIN, |
| 1069 | .maximum = WHITE_MAX, | 1071 | .maximum = WHITE_MAX, |
| 1070 | .step = 1, | 1072 | .step = 1, |
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 2f2de429e273..d9d64911f22a 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
| @@ -324,7 +324,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | /* -- start the camera -- */ | 326 | /* -- start the camera -- */ |
| 327 | static void sd_start(struct gspca_dev *gspca_dev) | 327 | static int sd_start(struct gspca_dev *gspca_dev) |
| 328 | { | 328 | { |
| 329 | int ret, value; | 329 | int ret, value; |
| 330 | 330 | ||
| @@ -374,9 +374,10 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 374 | set_par(gspca_dev, 0x01000000); | 374 | set_par(gspca_dev, 0x01000000); |
| 375 | set_par(gspca_dev, 0x01000000); | 375 | set_par(gspca_dev, 0x01000000); |
| 376 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); | 376 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); |
| 377 | return; | 377 | return 0; |
| 378 | out: | 378 | out: |
| 379 | PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret); | 379 | PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret); |
| 380 | return ret; | ||
| 380 | } | 381 | } |
| 381 | 382 | ||
| 382 | static void sd_stopN(struct gspca_dev *gspca_dev) | 383 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 1cfcc6c49558..bd9288665a80 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c | |||
| @@ -961,7 +961,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 961 | return 0; | 961 | return 0; |
| 962 | } | 962 | } |
| 963 | 963 | ||
| 964 | static void sd_start(struct gspca_dev *gspca_dev) | 964 | static int sd_start(struct gspca_dev *gspca_dev) |
| 965 | { | 965 | { |
| 966 | struct sd *sd = (struct sd *) gspca_dev; | 966 | struct sd *sd = (struct sd *) gspca_dev; |
| 967 | struct usb_device *dev = gspca_dev->dev; | 967 | struct usb_device *dev = gspca_dev->dev; |
| @@ -1042,6 +1042,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 1042 | break; | 1042 | break; |
| 1043 | } | 1043 | } |
| 1044 | sp5xx_initContBrigHueRegisters(gspca_dev); | 1044 | sp5xx_initContBrigHueRegisters(gspca_dev); |
| 1045 | return 0; | ||
| 1045 | } | 1046 | } |
| 1046 | 1047 | ||
| 1047 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1048 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index f034c748fc7e..b561f7c4f066 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c | |||
| @@ -28,8 +28,6 @@ | |||
| 28 | 28 | ||
| 29 | #include "gspca.h" | 29 | #include "gspca.h" |
| 30 | 30 | ||
| 31 | #define MAX_GAMMA 0x10 /* 0 to 15 */ | ||
| 32 | |||
| 33 | #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0) | 31 | #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0) |
| 34 | 32 | ||
| 35 | MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>"); | 33 | MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>"); |
| @@ -49,6 +47,10 @@ struct sd { | |||
| 49 | unsigned char whitebalance; | 47 | unsigned char whitebalance; |
| 50 | unsigned char mirror; | 48 | unsigned char mirror; |
| 51 | unsigned char effect; | 49 | unsigned char effect; |
| 50 | |||
| 51 | __u8 sensor; | ||
| 52 | #define SENSOR_TAS5130A 0 | ||
| 53 | #define SENSOR_OTHER 1 | ||
| 52 | }; | 54 | }; |
| 53 | 55 | ||
| 54 | /* V4L2 controls supported by the driver */ | 56 | /* V4L2 controls supported by the driver */ |
| @@ -83,9 +85,9 @@ static struct ctrl sd_ctrls[] = { | |||
| 83 | .type = V4L2_CTRL_TYPE_INTEGER, | 85 | .type = V4L2_CTRL_TYPE_INTEGER, |
| 84 | .name = "Brightness", | 86 | .name = "Brightness", |
| 85 | .minimum = 0, | 87 | .minimum = 0, |
| 86 | .maximum = 0x0f, | 88 | .maximum = 14, |
| 87 | .step = 1, | 89 | .step = 1, |
| 88 | .default_value = 0x09, | 90 | .default_value = 8, |
| 89 | }, | 91 | }, |
| 90 | .set = sd_setbrightness, | 92 | .set = sd_setbrightness, |
| 91 | .get = sd_getbrightness, | 93 | .get = sd_getbrightness, |
| @@ -118,16 +120,17 @@ static struct ctrl sd_ctrls[] = { | |||
| 118 | .set = sd_setcolors, | 120 | .set = sd_setcolors, |
| 119 | .get = sd_getcolors, | 121 | .get = sd_getcolors, |
| 120 | }, | 122 | }, |
| 121 | #define SD_GAMMA 3 | 123 | #define GAMMA_MAX 16 |
| 124 | #define GAMMA_DEF 10 | ||
| 122 | { | 125 | { |
| 123 | { | 126 | { |
| 124 | .id = V4L2_CID_GAMMA, /* (gamma on win) */ | 127 | .id = V4L2_CID_GAMMA, /* (gamma on win) */ |
| 125 | .type = V4L2_CTRL_TYPE_INTEGER, | 128 | .type = V4L2_CTRL_TYPE_INTEGER, |
| 126 | .name = "Gamma (Untested)", | 129 | .name = "Gamma", |
| 127 | .minimum = 0, | 130 | .minimum = 0, |
| 128 | .maximum = MAX_GAMMA, | 131 | .maximum = GAMMA_MAX - 1, |
| 129 | .step = 1, | 132 | .step = 1, |
| 130 | .default_value = 0x09, | 133 | .default_value = GAMMA_DEF, |
| 131 | }, | 134 | }, |
| 132 | .set = sd_setgamma, | 135 | .set = sd_setgamma, |
| 133 | .get = sd_getgamma, | 136 | .get = sd_getgamma, |
| @@ -197,7 +200,7 @@ static struct ctrl sd_ctrls[] = { | |||
| 197 | .type = V4L2_CTRL_TYPE_INTEGER, | 200 | .type = V4L2_CTRL_TYPE_INTEGER, |
| 198 | .name = "Sharpness", | 201 | .name = "Sharpness", |
| 199 | .minimum = 0, | 202 | .minimum = 0, |
| 200 | .maximum = MAX_GAMMA, /* 0 to 16 */ | 203 | .maximum = 15, |
| 201 | .step = 1, | 204 | .step = 1, |
| 202 | .default_value = 0x06, | 205 | .default_value = 0x06, |
| 203 | }, | 206 | }, |
| @@ -258,7 +261,6 @@ static struct v4l2_pix_format vga_mode_t16[] = { | |||
| 258 | .priv = 0}, | 261 | .priv = 0}, |
| 259 | }; | 262 | }; |
| 260 | 263 | ||
| 261 | #define T16_OFFSET_DATA 631 | ||
| 262 | #define MAX_EFFECTS 7 | 264 | #define MAX_EFFECTS 7 |
| 263 | /* easily done by soft, this table could be removed, | 265 | /* easily done by soft, this table could be removed, |
| 264 | * i keep it here just in case */ | 266 | * i keep it here just in case */ |
| @@ -272,87 +274,87 @@ static const __u8 effects_table[MAX_EFFECTS][6] = { | |||
| 272 | {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */ | 274 | {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */ |
| 273 | }; | 275 | }; |
| 274 | 276 | ||
| 275 | static const __u8 gamma_table[MAX_GAMMA][34] = { | 277 | static const __u8 gamma_table[GAMMA_MAX][34] = { |
| 276 | {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, | 278 | {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85, /* 0 */ |
| 277 | 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9, | 279 | 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9, |
| 278 | 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb, | 280 | 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb, |
| 279 | 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8, | 281 | 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8, |
| 280 | 0xa0, 0xff}, | 282 | 0xa0, 0xff}, |
| 281 | {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75, | 283 | {0x90, 0x00, 0x91, 0x33, 0x92, 0x5a, 0x93, 0x75, /* 1 */ |
| 282 | 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD, | 284 | 0x94, 0x85, 0x95, 0x93, 0x96, 0xa1, 0x97, 0xad, |
| 283 | 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4, | 285 | 0x98, 0xb7, 0x99, 0xc2, 0x9a, 0xcb, 0x9b, 0xd4, |
| 284 | 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7, | 286 | 0x9c, 0xde, 0x9D, 0xe7, 0x9e, 0xf0, 0x9f, 0xf7, |
| 285 | 0xa0, 0xff}, | 287 | 0xa0, 0xff}, |
| 286 | {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B, | 288 | {0x90, 0x00, 0x91, 0x2f, 0x92, 0x51, 0x93, 0x6b, /* 2 */ |
| 287 | 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6, | 289 | 0x94, 0x7c, 0x95, 0x8a, 0x96, 0x99, 0x97, 0xa6, |
| 288 | 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0, | 290 | 0x98, 0xb1, 0x99, 0xbc, 0x9a, 0xc6, 0x9b, 0xd0, |
| 289 | 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6, | 291 | 0x9c, 0xdb, 0x9d, 0xe4, 0x9e, 0xed, 0x9f, 0xf6, |
| 290 | 0xa0, 0xff}, | 292 | 0xa0, 0xff}, |
| 291 | {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, | 293 | {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60, /* 3 */ |
| 292 | 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E, | 294 | 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9e, |
| 293 | 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB, | 295 | 0x98, 0xaa, 0x99, 0xb5, 0x9a, 0xbf, 0x9b, 0xcb, |
| 294 | 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5, | 296 | 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5, |
| 295 | 0xa0, 0xff}, | 297 | 0xa0, 0xff}, |
| 296 | {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55, | 298 | {0x90, 0x00, 0x91, 0x23, 0x92, 0x3f, 0x93, 0x55, /* 4 */ |
| 297 | 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95, | 299 | 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95, |
| 298 | 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6, | 300 | 0x98, 0xa2, 0x99, 0xad, 0x9a, 0xb9, 0x9b, 0xc6, |
| 299 | 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4, | 301 | 0x9c, 0xd2, 0x9d, 0xde, 0x9e, 0xe9, 0x9f, 0xf4, |
| 300 | 0xa0, 0xff}, | 302 | 0xa0, 0xff}, |
| 301 | {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48, | 303 | {0x90, 0x00, 0x91, 0x1b, 0x92, 0x33, 0x93, 0x48, /* 5 */ |
| 302 | 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87, | 304 | 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87, |
| 303 | 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE, | 305 | 0x98, 0x96, 0x99, 0xa3, 0x9a, 0xb1, 0x9b, 0xbe, |
| 304 | 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3, | 306 | 0x9c, 0xcc, 0x9d, 0xda, 0x9e, 0xe7, 0x9f, 0xf3, |
| 305 | 0xa0, 0xff}, | 307 | 0xa0, 0xff}, |
| 306 | {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, | 308 | {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20, /* 6 */ |
| 307 | 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67, | 309 | 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67, |
| 308 | 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa, | 310 | 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa, |
| 309 | 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee, | 311 | 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee, |
| 310 | 0xa0, 0xff}, | 312 | 0xa0, 0xff}, |
| 311 | {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, | 313 | {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26, /* 7 */ |
| 312 | 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70, | 314 | 0x94, 0x38, 0x95, 0x4a, 0x96, 0x60, 0x97, 0x70, |
| 313 | 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0, | 315 | 0x98, 0x80, 0x99, 0x90, 0x9a, 0xa0, 0x9b, 0xb0, |
| 314 | 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0, | 316 | 0x9c, 0xc0, 0x9D, 0xd0, 0x9e, 0xe0, 0x9f, 0xf0, |
| 315 | 0xa0, 0xff}, | 317 | 0xa0, 0xff}, |
| 316 | {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, | 318 | {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35, /* 8 */ |
| 317 | 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79, | 319 | 0x94, 0x47, 0x95, 0x5a, 0x96, 0x69, 0x97, 0x79, |
| 318 | 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6, | 320 | 0x98, 0x88, 0x99, 0x97, 0x9a, 0xa7, 0x9b, 0xb6, |
| 319 | 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0, | 321 | 0x9c, 0xc4, 0x9d, 0xd3, 0x9e, 0xe0, 0x9f, 0xf0, |
| 320 | 0xa0, 0xff}, | 322 | 0xa0, 0xff}, |
| 321 | {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, | 323 | {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40, /* 9 */ |
| 322 | 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84, | 324 | 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84, |
| 323 | 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, | 325 | 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, |
| 324 | 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0, | 326 | 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0, |
| 325 | 0xa0, 0xff}, | 327 | 0xa0, 0xff}, |
| 326 | {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44, | 328 | {0x90, 0x00, 0x91, 0x18, 0x92, 0x2b, 0x93, 0x44, /* 10 */ |
| 327 | 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E, | 329 | 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8e, |
| 328 | 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4, | 330 | 0x98, 0x9c, 0x99, 0xaa, 0x9a, 0xb7, 0x9b, 0xc4, |
| 329 | 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0, | 331 | 0x9c, 0xd0, 0x9d, 0xd8, 0x9e, 0xe2, 0x9f, 0xf0, |
| 330 | 0xa0, 0xff}, | 332 | 0xa0, 0xff}, |
| 331 | {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52, | 333 | {0x90, 0x00, 0x91, 0x1a, 0x92, 0x34, 0x93, 0x52, /* 11 */ |
| 332 | 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B, | 334 | 0x94, 0x66, 0x95, 0x7e, 0x96, 0x8D, 0x97, 0x9B, |
| 333 | 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB, | 335 | 0x98, 0xa8, 0x99, 0xb4, 0x9a, 0xc0, 0x9b, 0xcb, |
| 334 | 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5, | 336 | 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5, |
| 335 | 0xa0, 0xff}, | 337 | 0xa0, 0xff}, |
| 336 | {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E, | 338 | {0x90, 0x00, 0x91, 0x3f, 0x92, 0x5a, 0x93, 0x6e, /* 12 */ |
| 337 | 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8, | 339 | 0x94, 0x7f, 0x95, 0x8e, 0x96, 0x9c, 0x97, 0xa8, |
| 338 | 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3, | 340 | 0x98, 0xb4, 0x99, 0xbf, 0x9a, 0xc9, 0x9b, 0xd3, |
| 339 | 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6, | 341 | 0x9c, 0xdc, 0x9d, 0xe5, 0x9e, 0xee, 0x9f, 0xf6, |
| 340 | 0xA0, 0xFF}, | ||
| 341 | {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83, | ||
| 342 | 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7, | ||
| 343 | 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC, | ||
| 344 | 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9, | ||
| 345 | 0xa0, 0xff}, | 342 | 0xa0, 0xff}, |
| 346 | {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A, | 343 | {0x90, 0x00, 0x91, 0x54, 0x92, 0x6f, 0x93, 0x83, /* 13 */ |
| 347 | 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6, | 344 | 0x94, 0x93, 0x95, 0xa0, 0x96, 0xad, 0x97, 0xb7, |
| 348 | 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3, | 345 | 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdc, |
| 349 | 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA, | 346 | 0x9c, 0xe4, 0x9d, 0xeb, 0x9e, 0xf2, 0x9f, 0xf9, |
| 350 | 0xa0, 0xff}, | 347 | 0xa0, 0xff}, |
| 351 | {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7, | 348 | {0x90, 0x00, 0x91, 0x6e, 0x92, 0x88, 0x93, 0x9a, /* 14 */ |
| 352 | 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8, | 349 | 0x94, 0xa8, 0x95, 0xb3, 0x96, 0xbd, 0x97, 0xc6, |
| 353 | 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED, | 350 | 0x98, 0xcf, 0x99, 0xd6, 0x9a, 0xdd, 0x9b, 0xe3, |
| 354 | 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC, | 351 | 0x9c, 0xe9, 0x9d, 0xef, 0x9e, 0xf4, 0x9f, 0xfa, |
| 355 | 0xA0, 0xFF} | 352 | 0xa0, 0xff}, |
| 353 | {0x90, 0x00, 0x91, 0x93, 0x92, 0xa8, 0x93, 0xb7, /* 15 */ | ||
| 354 | 0x94, 0xc1, 0x95, 0xca, 0x96, 0xd2, 0x97, 0xd8, | ||
| 355 | 0x98, 0xde, 0x99, 0xe3, 0x9a, 0xe8, 0x9b, 0xed, | ||
| 356 | 0x9c, 0xf1, 0x9d, 0xf5, 0x9e, 0xf8, 0x9f, 0xfc, | ||
| 357 | 0xa0, 0xff} | ||
| 356 | }; | 358 | }; |
| 357 | 359 | ||
| 358 | static const __u8 tas5130a_sensor_init[][8] = { | 360 | static const __u8 tas5130a_sensor_init[][8] = { |
| @@ -364,7 +366,7 @@ static const __u8 tas5130a_sensor_init[][8] = { | |||
| 364 | }; | 366 | }; |
| 365 | 367 | ||
| 366 | /* read 1 byte */ | 368 | /* read 1 byte */ |
| 367 | static int reg_r_1(struct gspca_dev *gspca_dev, | 369 | static int reg_r(struct gspca_dev *gspca_dev, |
| 368 | __u16 index) | 370 | __u16 index) |
| 369 | { | 371 | { |
| 370 | usb_control_msg(gspca_dev->dev, | 372 | usb_control_msg(gspca_dev->dev, |
| @@ -378,26 +380,26 @@ static int reg_r_1(struct gspca_dev *gspca_dev, | |||
| 378 | } | 380 | } |
| 379 | 381 | ||
| 380 | static void reg_w(struct gspca_dev *gspca_dev, | 382 | static void reg_w(struct gspca_dev *gspca_dev, |
| 381 | __u16 value, | 383 | __u16 index) |
| 382 | __u16 index, | 384 | { |
| 383 | const __u8 *buffer, __u16 len) | 385 | usb_control_msg(gspca_dev->dev, |
| 386 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
| 387 | 0, | ||
| 388 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
| 389 | 0, index, | ||
| 390 | NULL, 0, 500); | ||
| 391 | } | ||
| 392 | |||
| 393 | static void i2c_w(struct gspca_dev *gspca_dev, | ||
| 394 | const __u8 *buffer, __u16 len) | ||
| 384 | { | 395 | { |
| 385 | if (buffer == NULL) { | ||
| 386 | usb_control_msg(gspca_dev->dev, | ||
| 387 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
| 388 | 0, | ||
| 389 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
| 390 | value, index, | ||
| 391 | NULL, 0, 500); | ||
| 392 | return; | ||
| 393 | } | ||
| 394 | if (len <= USB_BUF_SZ) { | 396 | if (len <= USB_BUF_SZ) { |
| 395 | memcpy(gspca_dev->usb_buf, buffer, len); | 397 | memcpy(gspca_dev->usb_buf, buffer, len); |
| 396 | usb_control_msg(gspca_dev->dev, | 398 | usb_control_msg(gspca_dev->dev, |
| 397 | usb_sndctrlpipe(gspca_dev->dev, 0), | 399 | usb_sndctrlpipe(gspca_dev->dev, 0), |
| 398 | 0, | 400 | 0, |
| 399 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | 401 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, |
| 400 | value, index, | 402 | 0x01, 0, |
| 401 | gspca_dev->usb_buf, len, 500); | 403 | gspca_dev->usb_buf, len, 500); |
| 402 | } else { | 404 | } else { |
| 403 | __u8 *tmpbuf; | 405 | __u8 *tmpbuf; |
| @@ -408,12 +410,56 @@ static void reg_w(struct gspca_dev *gspca_dev, | |||
| 408 | usb_sndctrlpipe(gspca_dev->dev, 0), | 410 | usb_sndctrlpipe(gspca_dev->dev, 0), |
| 409 | 0, | 411 | 0, |
| 410 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | 412 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, |
| 411 | value, index, | 413 | 0x01, 0, |
| 412 | tmpbuf, len, 500); | 414 | tmpbuf, len, 500); |
| 413 | kfree(tmpbuf); | 415 | kfree(tmpbuf); |
| 414 | } | 416 | } |
| 415 | } | 417 | } |
| 416 | 418 | ||
| 419 | static void other_sensor_init(struct gspca_dev *gspca_dev) | ||
| 420 | { | ||
| 421 | int i; | ||
| 422 | const __u8 *p; | ||
| 423 | __u8 byte; | ||
| 424 | __u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05}; | ||
| 425 | static const __u8 sensor_init[] = { | ||
| 426 | 0xdf, 0x6d, | ||
| 427 | 0xdd, 0x18, | ||
| 428 | 0x5a, 0xe0, | ||
| 429 | 0x5c, 0x07, | ||
| 430 | 0x5d, 0xb0, | ||
| 431 | 0x5e, 0x1e, | ||
| 432 | 0x60, 0x71, | ||
| 433 | 0xef, 0x00, | ||
| 434 | 0xe9, 0x00, | ||
| 435 | 0xea, 0x00, | ||
| 436 | 0x90, 0x24, | ||
| 437 | 0x91, 0xb2, | ||
| 438 | 0x82, 0x32, | ||
| 439 | 0xfd, 0x00, | ||
| 440 | 0xfd, 0x01, | ||
| 441 | 0xfd, 0x41, | ||
| 442 | 0x00 /* table end */ | ||
| 443 | }; | ||
| 444 | |||
| 445 | p = sensor_init; | ||
| 446 | while (*p != 0) { | ||
| 447 | val[1] = *p++; | ||
| 448 | val[3] = *p++; | ||
| 449 | if (*p == 0) | ||
| 450 | reg_w(gspca_dev, 0x3c80); | ||
| 451 | i2c_w(gspca_dev, val, sizeof val); | ||
| 452 | i = 4; | ||
| 453 | while (--i >= 0) { | ||
| 454 | msleep(15); | ||
| 455 | byte = reg_r(gspca_dev, 0x60); | ||
| 456 | if (!(byte & 0x01)) | ||
| 457 | break; | ||
| 458 | } | ||
| 459 | } | ||
| 460 | reg_w(gspca_dev, 0x3c80); | ||
| 461 | } | ||
| 462 | |||
| 417 | /* this function is called at probe time */ | 463 | /* this function is called at probe time */ |
| 418 | static int sd_config(struct gspca_dev *gspca_dev, | 464 | static int sd_config(struct gspca_dev *gspca_dev, |
| 419 | const struct usb_device_id *id) | 465 | const struct usb_device_id *id) |
| @@ -430,7 +476,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 430 | sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; | 476 | sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; |
| 431 | sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; | 477 | sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; |
| 432 | sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; | 478 | sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; |
| 433 | sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value; | 479 | sd->gamma = GAMMA_DEF; |
| 434 | sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value; | 480 | sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value; |
| 435 | sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value; | 481 | sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value; |
| 436 | sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value; | 482 | sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value; |
| @@ -439,27 +485,37 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 439 | return 0; | 485 | return 0; |
| 440 | } | 486 | } |
| 441 | 487 | ||
| 442 | static int init_default_parameters(struct gspca_dev *gspca_dev) | 488 | static void setgamma(struct gspca_dev *gspca_dev) |
| 489 | { | ||
| 490 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 491 | |||
| 492 | PDEBUG(D_CONF, "Gamma: %d", sd->gamma); | ||
| 493 | i2c_w(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]); | ||
| 494 | } | ||
| 495 | |||
| 496 | /* this function is called at probe and resume time */ | ||
| 497 | static int sd_init(struct gspca_dev *gspca_dev) | ||
| 443 | { | 498 | { |
| 444 | /* some of this registers are not really neded, because | 499 | /* some of this registers are not really neded, because |
| 445 | * they are overriden by setbrigthness, setcontrast, etc, | 500 | * they are overriden by setbrigthness, setcontrast, etc, |
| 446 | * but wont hurt anyway, and can help someone with similar webcam | 501 | * but wont hurt anyway, and can help someone with similar webcam |
| 447 | * to see the initial parameters.*/ | 502 | * to see the initial parameters.*/ |
| 448 | int i = 0; | 503 | struct sd *sd = (struct sd *) gspca_dev; |
| 449 | __u8 test_byte; | 504 | int i; |
| 505 | __u8 byte, test_byte; | ||
| 450 | 506 | ||
| 451 | static const __u8 read_indexs[] = | 507 | static const __u8 read_indexs[] = |
| 452 | { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, | 508 | { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, |
| 453 | 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 }; | 509 | 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 }; |
| 454 | static const __u8 n1[6] = | 510 | static const __u8 n1[] = |
| 455 | {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; | 511 | {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; |
| 456 | static const __u8 n2[2] = | 512 | static const __u8 n2[] = |
| 457 | {0x08, 0x00}; | 513 | {0x08, 0x00}; |
| 458 | static const __u8 nset[6] = | 514 | static const __u8 nset[] = |
| 459 | { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 }; | 515 | { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 }; |
| 460 | static const __u8 n3[6] = | 516 | static const __u8 n3[] = |
| 461 | {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}; | 517 | {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}; |
| 462 | static const __u8 n4[0x46] = | 518 | static const __u8 n4[] = |
| 463 | {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, | 519 | {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, |
| 464 | 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, | 520 | 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, |
| 465 | 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, | 521 | 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, |
| @@ -469,33 +525,26 @@ static int init_default_parameters(struct gspca_dev *gspca_dev) | |||
| 469 | 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, | 525 | 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, |
| 470 | 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, | 526 | 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, |
| 471 | 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46}; | 527 | 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46}; |
| 472 | static const __u8 nset4[18] = { | 528 | static const __u8 nset4[] = { |
| 473 | 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8, | 529 | 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8, |
| 474 | 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8, | 530 | 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8, |
| 475 | 0xe8, 0xe0 | 531 | 0xe8, 0xe0 |
| 476 | }; | 532 | }; |
| 477 | /* ojo puede ser 0xe6 en vez de 0xe9 */ | 533 | /* ojo puede ser 0xe6 en vez de 0xe9 */ |
| 478 | static const __u8 nset2[20] = { | 534 | static const __u8 nset2[] = { |
| 479 | 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb, | 535 | 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb, |
| 480 | 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27, | 536 | 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27, |
| 481 | 0xd8, 0xc8, 0xd9, 0xfc | 537 | 0xd8, 0xc8, 0xd9, 0xfc |
| 482 | }; | 538 | }; |
| 483 | static const __u8 missing[8] = | 539 | static const __u8 missing[] = |
| 484 | { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 }; | 540 | { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 }; |
| 485 | static const __u8 nset3[18] = { | 541 | static const __u8 nset3[] = { |
| 486 | 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8, | 542 | 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8, |
| 487 | 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8, | 543 | 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8, |
| 488 | 0xcf, 0xe0 | 544 | 0xcf, 0xe0 |
| 489 | }; | 545 | }; |
| 490 | static const __u8 nset5[4] = | 546 | static const __u8 nset5[] = |
| 491 | { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */ | 547 | { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */ |
| 492 | static const __u8 nset6[34] = { | ||
| 493 | 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54, | ||
| 494 | 0x95, 0x65, 0x96, 0x75, 0x97, 0x84, | ||
| 495 | 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca, | ||
| 496 | 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2, | ||
| 497 | 0xa0, 0xff | ||
| 498 | }; /* Gamma */ | ||
| 499 | static const __u8 nset7[4] = | 548 | static const __u8 nset7[4] = |
| 500 | { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */ | 549 | { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */ |
| 501 | static const __u8 nset9[4] = | 550 | static const __u8 nset9[4] = |
| @@ -505,95 +554,111 @@ static int init_default_parameters(struct gspca_dev *gspca_dev) | |||
| 505 | static const __u8 nset10[6] = | 554 | static const __u8 nset10[6] = |
| 506 | { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 }; | 555 | { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 }; |
| 507 | 556 | ||
| 508 | reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06); | 557 | byte = reg_r(gspca_dev, 0x06); |
| 509 | reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06); | 558 | test_byte = reg_r(gspca_dev, 0x07); |
| 510 | reg_r_1(gspca_dev, 0x0063); | 559 | if (byte == 0x08 && test_byte == 0x07) { |
| 511 | reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02); | 560 | PDEBUG(D_CONF, "other sensor"); |
| 561 | sd->sensor = SENSOR_OTHER; | ||
| 562 | } else { | ||
| 563 | PDEBUG(D_CONF, "sensor %02x %02x", byte, test_byte); | ||
| 564 | sd->sensor = SENSOR_TAS5130A; | ||
| 565 | } | ||
| 566 | |||
| 567 | i2c_w(gspca_dev, n1, sizeof n1); | ||
| 568 | test_byte = 0; | ||
| 569 | i = 5; | ||
| 570 | while (--i >= 0) { | ||
| 571 | i2c_w(gspca_dev, nset, sizeof nset); | ||
| 572 | msleep(5); | ||
| 573 | test_byte = reg_r(gspca_dev, 0x0063); | ||
| 574 | msleep(100); | ||
| 575 | if (test_byte == 0x17) | ||
| 576 | break; /* OK */ | ||
| 577 | } | ||
| 578 | if (i < 0) { | ||
| 579 | err("Bad sensor reset %02x", test_byte); | ||
| 580 | /* return -EIO; */ | ||
| 581 | /*fixme: test - continue */ | ||
| 582 | } | ||
| 583 | i2c_w(gspca_dev, n2, sizeof n2); | ||
| 512 | 584 | ||
| 585 | i = 0; | ||
| 513 | while (read_indexs[i] != 0x00) { | 586 | while (read_indexs[i] != 0x00) { |
| 514 | test_byte = reg_r_1(gspca_dev, read_indexs[i]); | 587 | test_byte = reg_r(gspca_dev, read_indexs[i]); |
| 515 | PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i], | 588 | PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i], |
| 516 | test_byte); | 589 | test_byte); |
| 517 | i++; | 590 | i++; |
| 518 | } | 591 | } |
| 519 | 592 | ||
| 520 | reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06); | 593 | i2c_w(gspca_dev, n3, sizeof n3); |
| 521 | reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46); | 594 | i2c_w(gspca_dev, n4, sizeof n4); |
| 522 | reg_r_1(gspca_dev, 0x0080); | 595 | reg_r(gspca_dev, 0x0080); |
| 523 | reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0); | 596 | reg_w(gspca_dev, 0x2c80); |
| 524 | reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14); | 597 | i2c_w(gspca_dev, nset2, sizeof nset2); |
| 525 | reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12); | 598 | i2c_w(gspca_dev, nset3, sizeof nset3); |
| 526 | reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12); | 599 | i2c_w(gspca_dev, nset4, sizeof nset4); |
| 527 | reg_w(gspca_dev, 0x00, 0x3880, NULL, 0); | 600 | reg_w(gspca_dev, 0x3880); |
| 528 | reg_w(gspca_dev, 0x00, 0x3880, NULL, 0); | 601 | reg_w(gspca_dev, 0x3880); |
| 529 | reg_w(gspca_dev, 0x00, 0x338e, NULL, 0); | 602 | reg_w(gspca_dev, 0x338e); |
| 530 | reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04); | 603 | i2c_w(gspca_dev, nset5, sizeof nset5); |
| 531 | reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0); | 604 | reg_w(gspca_dev, 0x00a9); |
| 532 | reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22); | 605 | setgamma(gspca_dev); |
| 533 | reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0); | 606 | reg_w(gspca_dev, 0x86bb); |
| 534 | reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0); | 607 | reg_w(gspca_dev, 0x4aa6); |
| 535 | 608 | ||
| 536 | reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08); | 609 | i2c_w(gspca_dev, missing, sizeof missing); |
| 537 | 610 | ||
| 538 | reg_w(gspca_dev, 0x00, 0x2087, NULL, 0); | 611 | reg_w(gspca_dev, 0x2087); |
| 539 | reg_w(gspca_dev, 0x00, 0x2088, NULL, 0); | 612 | reg_w(gspca_dev, 0x2088); |
| 540 | reg_w(gspca_dev, 0x00, 0x2089, NULL, 0); | 613 | reg_w(gspca_dev, 0x2089); |
| 541 | 614 | ||
| 542 | reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04); | 615 | i2c_w(gspca_dev, nset7, sizeof nset7); |
| 543 | reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06); | 616 | i2c_w(gspca_dev, nset10, sizeof nset10); |
| 544 | reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06); | 617 | i2c_w(gspca_dev, nset8, sizeof nset8); |
| 545 | reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04); | 618 | i2c_w(gspca_dev, nset9, sizeof nset9); |
| 546 | 619 | ||
| 547 | reg_w(gspca_dev, 0x00, 0x2880, NULL, 0); | 620 | reg_w(gspca_dev, 0x2880); |
| 548 | reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14); | 621 | i2c_w(gspca_dev, nset2, sizeof nset2); |
| 549 | reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12); | 622 | i2c_w(gspca_dev, nset3, sizeof nset3); |
| 550 | reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12); | 623 | i2c_w(gspca_dev, nset4, sizeof nset4); |
| 551 | 624 | ||
| 552 | return 0; | 625 | return 0; |
| 553 | } | 626 | } |
| 554 | 627 | ||
| 555 | /* this function is called at probe and resume time */ | ||
| 556 | static int sd_init(struct gspca_dev *gspca_dev) | ||
| 557 | { | ||
| 558 | init_default_parameters(gspca_dev); | ||
| 559 | return 0; | ||
| 560 | } | ||
| 561 | |||
| 562 | static void setbrightness(struct gspca_dev *gspca_dev) | 628 | static void setbrightness(struct gspca_dev *gspca_dev) |
| 563 | { | 629 | { |
| 564 | struct sd *sd = (struct sd *) gspca_dev; | 630 | struct sd *sd = (struct sd *) gspca_dev; |
| 565 | unsigned int brightness; | 631 | unsigned int brightness; |
| 566 | __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 }; | 632 | __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x00 }; |
| 567 | brightness = sd->brightness; | ||
| 568 | 633 | ||
| 634 | brightness = sd->brightness; | ||
| 569 | if (brightness < 7) { | 635 | if (brightness < 7) { |
| 570 | set6[3] = 0x70 - (brightness * 0xa); | 636 | set6[3] = 0x70 - brightness * 0x10; |
| 571 | } else { | 637 | } else { |
| 572 | set6[1] = 0x24; | 638 | set6[1] = 0x24; |
| 573 | set6[3] = 0x00 + ((brightness - 7) * 0xa); | 639 | set6[3] = 0x00 + ((brightness - 7) * 0x10); |
| 574 | } | 640 | } |
| 575 | 641 | ||
| 576 | reg_w(gspca_dev, 0x01, 0x0000, set6, 4); | 642 | i2c_w(gspca_dev, set6, sizeof set6); |
| 577 | } | 643 | } |
| 578 | 644 | ||
| 579 | static void setflip(struct gspca_dev *gspca_dev) | 645 | static void setflip(struct gspca_dev *gspca_dev) |
| 580 | { | 646 | { |
| 581 | struct sd *sd = (struct sd *) gspca_dev; | 647 | struct sd *sd = (struct sd *) gspca_dev; |
| 582 | |||
| 583 | __u8 flipcmd[8] = | 648 | __u8 flipcmd[8] = |
| 584 | { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 }; | 649 | {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}; |
| 585 | 650 | ||
| 586 | if (sd->mirror == 1) | 651 | if (sd->mirror) |
| 587 | flipcmd[3] = 0x01; | 652 | flipcmd[3] = 0x01; |
| 588 | 653 | ||
| 589 | reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8); | 654 | i2c_w(gspca_dev, flipcmd, sizeof flipcmd); |
| 590 | } | 655 | } |
| 591 | 656 | ||
| 592 | static void seteffect(struct gspca_dev *gspca_dev) | 657 | static void seteffect(struct gspca_dev *gspca_dev) |
| 593 | { | 658 | { |
| 594 | struct sd *sd = (struct sd *) gspca_dev; | 659 | struct sd *sd = (struct sd *) gspca_dev; |
| 595 | 660 | ||
| 596 | reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06); | 661 | i2c_w(gspca_dev, effects_table[sd->effect], sizeof effects_table[0]); |
| 597 | if (sd->effect == 1 || sd->effect == 5) { | 662 | if (sd->effect == 1 || sd->effect == 5) { |
| 598 | PDEBUG(D_CONF, | 663 | PDEBUG(D_CONF, |
| 599 | "This effect have been disabled for webcam \"safety\""); | 664 | "This effect have been disabled for webcam \"safety\""); |
| @@ -601,9 +666,9 @@ static void seteffect(struct gspca_dev *gspca_dev) | |||
| 601 | } | 666 | } |
| 602 | 667 | ||
| 603 | if (sd->effect == 1 || sd->effect == 4) | 668 | if (sd->effect == 1 || sd->effect == 4) |
| 604 | reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0); | 669 | reg_w(gspca_dev, 0x4aa6); |
| 605 | else | 670 | else |
| 606 | reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0); | 671 | reg_w(gspca_dev, 0xfaa6); |
| 607 | } | 672 | } |
| 608 | 673 | ||
| 609 | static void setwhitebalance(struct gspca_dev *gspca_dev) | 674 | static void setwhitebalance(struct gspca_dev *gspca_dev) |
| @@ -616,7 +681,7 @@ static void setwhitebalance(struct gspca_dev *gspca_dev) | |||
| 616 | if (sd->whitebalance == 1) | 681 | if (sd->whitebalance == 1) |
| 617 | white_balance[7] = 0x3c; | 682 | white_balance[7] = 0x3c; |
| 618 | 683 | ||
| 619 | reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8); | 684 | i2c_w(gspca_dev, white_balance, sizeof white_balance); |
| 620 | } | 685 | } |
| 621 | 686 | ||
| 622 | static void setlightfreq(struct gspca_dev *gspca_dev) | 687 | static void setlightfreq(struct gspca_dev *gspca_dev) |
| @@ -627,21 +692,21 @@ static void setlightfreq(struct gspca_dev *gspca_dev) | |||
| 627 | if (sd->freq == 2) /* 60hz */ | 692 | if (sd->freq == 2) /* 60hz */ |
| 628 | freq[1] = 0x00; | 693 | freq[1] = 0x00; |
| 629 | 694 | ||
| 630 | reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4); | 695 | i2c_w(gspca_dev, freq, sizeof freq); |
| 631 | } | 696 | } |
| 632 | 697 | ||
| 633 | static void setcontrast(struct gspca_dev *gspca_dev) | 698 | static void setcontrast(struct gspca_dev *gspca_dev) |
| 634 | { | 699 | { |
| 635 | struct sd *sd = (struct sd *) gspca_dev; | 700 | struct sd *sd = (struct sd *) gspca_dev; |
| 636 | unsigned int contrast = sd->contrast; | 701 | unsigned int contrast = sd->contrast; |
| 637 | __u16 reg_to_write = 0x00; | 702 | __u16 reg_to_write; |
| 638 | 703 | ||
| 639 | if (contrast < 7) | 704 | if (contrast < 7) |
| 640 | reg_to_write = 0x8ea9 - (0x200 * contrast); | 705 | reg_to_write = 0x8ea9 - (0x200 * contrast); |
| 641 | else | 706 | else |
| 642 | reg_to_write = (0x00a9 + ((contrast - 7) * 0x200)); | 707 | reg_to_write = (0x00a9 + ((contrast - 7) * 0x200)); |
| 643 | 708 | ||
| 644 | reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0); | 709 | reg_w(gspca_dev, reg_to_write); |
| 645 | } | 710 | } |
| 646 | 711 | ||
| 647 | static void setcolors(struct gspca_dev *gspca_dev) | 712 | static void setcolors(struct gspca_dev *gspca_dev) |
| @@ -650,11 +715,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
| 650 | __u16 reg_to_write; | 715 | __u16 reg_to_write; |
| 651 | 716 | ||
| 652 | reg_to_write = 0xc0bb + sd->colors * 0x100; | 717 | reg_to_write = 0xc0bb + sd->colors * 0x100; |
| 653 | reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0); | 718 | reg_w(gspca_dev, reg_to_write); |
| 654 | } | ||
| 655 | |||
| 656 | static void setgamma(struct gspca_dev *gspca_dev) | ||
| 657 | { | ||
| 658 | } | 719 | } |
| 659 | 720 | ||
| 660 | static void setsharpness(struct gspca_dev *gspca_dev) | 721 | static void setsharpness(struct gspca_dev *gspca_dev) |
| @@ -664,7 +725,99 @@ static void setsharpness(struct gspca_dev *gspca_dev) | |||
| 664 | 725 | ||
| 665 | reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness; | 726 | reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness; |
| 666 | 727 | ||
| 667 | reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0); | 728 | reg_w(gspca_dev, reg_to_write); |
| 729 | } | ||
| 730 | |||
| 731 | static int sd_start(struct gspca_dev *gspca_dev) | ||
| 732 | { | ||
| 733 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 734 | int i, mode; | ||
| 735 | static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 }; | ||
| 736 | __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; | ||
| 737 | static const __u8 t3[] = | ||
| 738 | { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06, | ||
| 739 | 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 }; | ||
| 740 | static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 }; | ||
| 741 | |||
| 742 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv; | ||
| 743 | switch (mode) { | ||
| 744 | case 1: /* 352x288 */ | ||
| 745 | t2[1] = 0x40; | ||
| 746 | break; | ||
| 747 | case 2: /* 320x240 */ | ||
| 748 | t2[1] = 0x10; | ||
| 749 | break; | ||
| 750 | case 3: /* 176x144 */ | ||
| 751 | t2[1] = 0x50; | ||
| 752 | break; | ||
| 753 | case 4: /* 160x120 */ | ||
| 754 | t2[1] = 0x20; | ||
| 755 | break; | ||
| 756 | default: /* 640x480 (0x00) */ | ||
| 757 | break; | ||
| 758 | } | ||
| 759 | |||
| 760 | if (sd->sensor == SENSOR_TAS5130A) { | ||
| 761 | i = 0; | ||
| 762 | while (tas5130a_sensor_init[i][0] != 0) { | ||
| 763 | i2c_w(gspca_dev, tas5130a_sensor_init[i], | ||
| 764 | sizeof tas5130a_sensor_init[0]); | ||
| 765 | i++; | ||
| 766 | } | ||
| 767 | reg_w(gspca_dev, 0x3c80); | ||
| 768 | /* just in case and to keep sync with logs (for mine) */ | ||
| 769 | i2c_w(gspca_dev, tas5130a_sensor_init[3], | ||
| 770 | sizeof tas5130a_sensor_init[0]); | ||
| 771 | reg_w(gspca_dev, 0x3c80); | ||
| 772 | } else { | ||
| 773 | other_sensor_init(gspca_dev); | ||
| 774 | } | ||
| 775 | /* just in case and to keep sync with logs (for mine) */ | ||
| 776 | i2c_w(gspca_dev, t1, sizeof t1); | ||
| 777 | i2c_w(gspca_dev, t2, sizeof t2); | ||
| 778 | reg_r(gspca_dev, 0x0012); | ||
| 779 | i2c_w(gspca_dev, t3, sizeof t3); | ||
| 780 | reg_w(gspca_dev, 0x0013); | ||
| 781 | i2c_w(gspca_dev, t4, sizeof t4); | ||
| 782 | /* restart on each start, just in case, sometimes regs goes wrong | ||
| 783 | * when using controls from app */ | ||
| 784 | setbrightness(gspca_dev); | ||
| 785 | setcontrast(gspca_dev); | ||
| 786 | setcolors(gspca_dev); | ||
| 787 | return 0; | ||
| 788 | } | ||
| 789 | |||
| 790 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
| 791 | struct gspca_frame *frame, /* target */ | ||
| 792 | __u8 *data, /* isoc packet */ | ||
| 793 | int len) /* iso packet length */ | ||
| 794 | { | ||
| 795 | static __u8 ffd9[] = { 0xff, 0xd9 }; | ||
| 796 | |||
| 797 | if (data[0] == 0x5a) { | ||
| 798 | /* Control Packet, after this came the header again, | ||
| 799 | * but extra bytes came in the packet before this, | ||
| 800 | * sometimes an EOF arrives, sometimes not... */ | ||
| 801 | return; | ||
| 802 | } | ||
| 803 | data += 2; | ||
| 804 | len -= 2; | ||
| 805 | if (data[0] == 0xff && data[1] == 0xd8) { | ||
| 806 | /* extra bytes....., could be processed too but would be | ||
| 807 | * a waste of time, right now leave the application and | ||
| 808 | * libjpeg do it for ourserlves.. */ | ||
| 809 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | ||
| 810 | ffd9, 2); | ||
| 811 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); | ||
| 812 | return; | ||
| 813 | } | ||
| 814 | |||
| 815 | if (data[len - 2] == 0xff && data[len - 1] == 0xd9) { | ||
| 816 | /* Just in case, i have seen packets with the marker, | ||
| 817 | * other's do not include it... */ | ||
| 818 | len -= 2; | ||
| 819 | } | ||
| 820 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | ||
| 668 | } | 821 | } |
| 669 | 822 | ||
| 670 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 823 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
| @@ -788,6 +941,7 @@ static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) | |||
| 788 | static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) | 941 | static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) |
| 789 | { | 942 | { |
| 790 | struct sd *sd = (struct sd *) gspca_dev; | 943 | struct sd *sd = (struct sd *) gspca_dev; |
| 944 | |||
| 791 | *val = sd->gamma; | 945 | *val = sd->gamma; |
| 792 | return 0; | 946 | return 0; |
| 793 | } | 947 | } |
| @@ -835,9 +989,9 @@ static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val) | |||
| 835 | 989 | ||
| 836 | sd->autogain = val; | 990 | sd->autogain = val; |
| 837 | if (val != 0) | 991 | if (val != 0) |
| 838 | reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0); | 992 | reg_w(gspca_dev, 0xf48e); |
| 839 | else | 993 | else |
| 840 | reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0); | 994 | reg_w(gspca_dev, 0xb48e); |
| 841 | return 0; | 995 | return 0; |
| 842 | } | 996 | } |
| 843 | 997 | ||
| @@ -849,99 +1003,6 @@ static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val) | |||
| 849 | return 0; | 1003 | return 0; |
| 850 | } | 1004 | } |
| 851 | 1005 | ||
| 852 | static void sd_start(struct gspca_dev *gspca_dev) | ||
| 853 | { | ||
| 854 | int mode; | ||
| 855 | |||
| 856 | static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 }; | ||
| 857 | __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; | ||
| 858 | static const __u8 t3[] = | ||
| 859 | { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06, | ||
| 860 | 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 }; | ||
| 861 | static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 }; | ||
| 862 | |||
| 863 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv; | ||
| 864 | switch (mode) { | ||
| 865 | case 1: /* 352x288 */ | ||
| 866 | t2[1] = 0x40; | ||
| 867 | break; | ||
| 868 | case 2: /* 320x240 */ | ||
| 869 | t2[1] = 0x10; | ||
| 870 | break; | ||
| 871 | case 3: /* 176x144 */ | ||
| 872 | t2[1] = 0x50; | ||
| 873 | break; | ||
| 874 | case 4: /* 160x120 */ | ||
| 875 | t2[1] = 0x20; | ||
| 876 | break; | ||
| 877 | default: /* 640x480 (0x00) */ | ||
| 878 | break; | ||
| 879 | } | ||
| 880 | |||
| 881 | reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8); | ||
| 882 | reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8); | ||
| 883 | reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8); | ||
| 884 | reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8); | ||
| 885 | reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0); | ||
| 886 | /* just in case and to keep sync with logs (for mine) */ | ||
| 887 | reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8); | ||
| 888 | reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0); | ||
| 889 | /* just in case and to keep sync with logs (for mine) */ | ||
| 890 | reg_w(gspca_dev, 0x01, 0x0000, t1, 4); | ||
| 891 | reg_w(gspca_dev, 0x01, 0x0000, t2, 6); | ||
| 892 | reg_r_1(gspca_dev, 0x0012); | ||
| 893 | reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10); | ||
| 894 | reg_w(gspca_dev, 0x00, 0x0013, NULL, 0); | ||
| 895 | reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4); | ||
| 896 | /* restart on each start, just in case, sometimes regs goes wrong | ||
| 897 | * when using controls from app */ | ||
| 898 | setbrightness(gspca_dev); | ||
| 899 | setcontrast(gspca_dev); | ||
| 900 | setcolors(gspca_dev); | ||
| 901 | } | ||
| 902 | |||
| 903 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
| 904 | struct gspca_frame *frame, /* target */ | ||
| 905 | __u8 *data, /* isoc packet */ | ||
| 906 | int len) /* iso packet length */ | ||
| 907 | { | ||
| 908 | int sof = 0; | ||
| 909 | static __u8 ffd9[] = { 0xff, 0xd9 }; | ||
| 910 | |||
| 911 | if (data[0] == 0x5a) { | ||
| 912 | /* Control Packet, after this came the header again, | ||
| 913 | * but extra bytes came in the packet before this, | ||
| 914 | * sometimes an EOF arrives, sometimes not... */ | ||
| 915 | return; | ||
| 916 | } | ||
| 917 | |||
| 918 | if (data[len - 1] == 0xff && data[len] == 0xd9) { | ||
| 919 | /* Just in case, i have seen packets with the marker, | ||
| 920 | * other's do not include it... */ | ||
| 921 | data += 2; | ||
| 922 | len -= 4; | ||
| 923 | } else if (data[2] == 0xff && data[3] == 0xd8) { | ||
| 924 | sof = 1; | ||
| 925 | data += 2; | ||
| 926 | len -= 2; | ||
| 927 | } else { | ||
| 928 | data += 2; | ||
| 929 | len -= 2; | ||
| 930 | } | ||
| 931 | |||
| 932 | if (sof) { | ||
| 933 | /* extra bytes....., could be processed too but would be | ||
| 934 | * a waste of time, right now leave the application and | ||
| 935 | * libjpeg do it for ourserlves.. */ | ||
| 936 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, | ||
| 937 | ffd9, 2); | ||
| 938 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); | ||
| 939 | return; | ||
| 940 | } | ||
| 941 | |||
| 942 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); | ||
| 943 | } | ||
| 944 | |||
| 945 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 1006 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
| 946 | struct v4l2_querymenu *menu) | 1007 | struct v4l2_querymenu *menu) |
| 947 | { | 1008 | { |
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 084af05302a0..968a5911704f 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c | |||
| @@ -390,7 +390,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | /* -- start the camera -- */ | 392 | /* -- start the camera -- */ |
| 393 | static void sd_start(struct gspca_dev *gspca_dev) | 393 | static int sd_start(struct gspca_dev *gspca_dev) |
| 394 | { | 394 | { |
| 395 | reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); | 395 | reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); |
| 396 | reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); | 396 | reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); |
| @@ -443,6 +443,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 443 | /************************************************/ | 443 | /************************************************/ |
| 444 | tv_8532_PollReg(gspca_dev); | 444 | tv_8532_PollReg(gspca_dev); |
| 445 | reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ | 445 | reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */ |
| 446 | return 0; | ||
| 446 | } | 447 | } |
| 447 | 448 | ||
| 448 | static void sd_stopN(struct gspca_dev *gspca_dev) | 449 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index bd4c226c9a07..be46d9232540 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c | |||
| @@ -80,7 +80,6 @@ static struct ctrl sd_ctrls[] = { | |||
| 80 | .step = 1, | 80 | .step = 1, |
| 81 | #define FREQ_DEF 1 | 81 | #define FREQ_DEF 1 |
| 82 | .default_value = FREQ_DEF, | 82 | .default_value = FREQ_DEF, |
| 83 | .default_value = 1, | ||
| 84 | }, | 83 | }, |
| 85 | .set = sd_setfreq, | 84 | .set = sd_setfreq, |
| 86 | .get = sd_getfreq, | 85 | .get = sd_getfreq, |
| @@ -1502,7 +1501,7 @@ static void setlightfreq(struct gspca_dev *gspca_dev) | |||
| 1502 | usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]); | 1501 | usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]); |
| 1503 | } | 1502 | } |
| 1504 | 1503 | ||
| 1505 | static void sd_start(struct gspca_dev *gspca_dev) | 1504 | static int sd_start(struct gspca_dev *gspca_dev) |
| 1506 | { | 1505 | { |
| 1507 | struct sd *sd = (struct sd *) gspca_dev; | 1506 | struct sd *sd = (struct sd *) gspca_dev; |
| 1508 | const __u8 *GammaT = NULL; | 1507 | const __u8 *GammaT = NULL; |
| @@ -1586,7 +1585,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 1586 | break; | 1585 | break; |
| 1587 | default: | 1586 | default: |
| 1588 | PDEBUG(D_PROBE, "Damned !! no sensor found Bye"); | 1587 | PDEBUG(D_PROBE, "Damned !! no sensor found Bye"); |
| 1589 | return; | 1588 | return -EMEDIUMTYPE; |
| 1590 | } | 1589 | } |
| 1591 | if (GammaT && MatrixT) { | 1590 | if (GammaT && MatrixT) { |
| 1592 | put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a); | 1591 | put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a); |
| @@ -1622,6 +1621,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 1622 | setautogain(gspca_dev); | 1621 | setautogain(gspca_dev); |
| 1623 | setlightfreq(gspca_dev); | 1622 | setlightfreq(gspca_dev); |
| 1624 | } | 1623 | } |
| 1624 | return 0; | ||
| 1625 | } | 1625 | } |
| 1626 | 1626 | ||
| 1627 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1627 | static void sd_stopN(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index d61ef727e0c2..d0a4451dc46f 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
| @@ -7178,7 +7178,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 7178 | return 0; | 7178 | return 0; |
| 7179 | } | 7179 | } |
| 7180 | 7180 | ||
| 7181 | static void sd_start(struct gspca_dev *gspca_dev) | 7181 | static int sd_start(struct gspca_dev *gspca_dev) |
| 7182 | { | 7182 | { |
| 7183 | struct sd *sd = (struct sd *) gspca_dev; | 7183 | struct sd *sd = (struct sd *) gspca_dev; |
| 7184 | struct usb_device *dev = gspca_dev->dev; | 7184 | struct usb_device *dev = gspca_dev->dev; |
| @@ -7331,6 +7331,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
| 7331 | reg_w(dev, 0x02, 0x0008); | 7331 | reg_w(dev, 0x02, 0x0008); |
| 7332 | break; | 7332 | break; |
| 7333 | } | 7333 | } |
| 7334 | return 0; | ||
| 7334 | } | 7335 | } |
| 7335 | 7336 | ||
| 7336 | static void sd_stop0(struct gspca_dev *gspca_dev) | 7337 | static void sd_stop0(struct gspca_dev *gspca_dev) |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index a30254bed311..efe849981ab7 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
| @@ -12,6 +12,10 @@ | |||
| 12 | * Markus Rechberger <mrechberger@gmail.com> | 12 | * Markus Rechberger <mrechberger@gmail.com> |
| 13 | * modified for DViCO Fusion HDTV 5 RT GOLD by | 13 | * modified for DViCO Fusion HDTV 5 RT GOLD by |
| 14 | * Chaogui Zhang <czhang1974@gmail.com> | 14 | * Chaogui Zhang <czhang1974@gmail.com> |
| 15 | * modified for MSI TV@nywhere Plus by | ||
| 16 | * Henry Wong <henry@stuffedcow.net> | ||
| 17 | * Mark Schultz <n9xmj@yahoo.com> | ||
| 18 | * Brian Rogers <brian_rogers@comcast.net> | ||
| 15 | * | 19 | * |
| 16 | * This program is free software; you can redistribute it and/or modify | 20 | * This program is free software; you can redistribute it and/or modify |
| 17 | * it under the terms of the GNU General Public License as published by | 21 | * it under the terms of the GNU General Public License as published by |
| @@ -65,7 +69,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, | |||
| 65 | int size, int offset) | 69 | int size, int offset) |
| 66 | { | 70 | { |
| 67 | unsigned char buf[6]; | 71 | unsigned char buf[6]; |
| 68 | int start, range, toggle, dev, code; | 72 | int start, range, toggle, dev, code, ircode; |
| 69 | 73 | ||
| 70 | /* poll IR chip */ | 74 | /* poll IR chip */ |
| 71 | if (size != i2c_master_recv(&ir->c,buf,size)) | 75 | if (size != i2c_master_recv(&ir->c,buf,size)) |
| @@ -85,6 +89,24 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, | |||
| 85 | if (!start) | 89 | if (!start) |
| 86 | /* no key pressed */ | 90 | /* no key pressed */ |
| 87 | return 0; | 91 | return 0; |
| 92 | /* | ||
| 93 | * Hauppauge remotes (black/silver) always use | ||
| 94 | * specific device ids. If we do not filter the | ||
| 95 | * device ids then messages destined for devices | ||
| 96 | * such as TVs (id=0) will get through causing | ||
| 97 | * mis-fired events. | ||
| 98 | * | ||
| 99 | * We also filter out invalid key presses which | ||
| 100 | * produce annoying debug log entries. | ||
| 101 | */ | ||
| 102 | ircode= (start << 12) | (toggle << 11) | (dev << 6) | code; | ||
| 103 | if ((ircode & 0x1fff)==0x1fff) | ||
| 104 | /* invalid key press */ | ||
| 105 | return 0; | ||
| 106 | |||
| 107 | if (dev!=0x1e && dev!=0x1f) | ||
| 108 | /* not a hauppauge remote */ | ||
| 109 | return 0; | ||
| 88 | 110 | ||
| 89 | if (!range) | 111 | if (!range) |
| 90 | code += 64; | 112 | code += 64; |
| @@ -94,7 +116,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, | |||
| 94 | 116 | ||
| 95 | /* return key */ | 117 | /* return key */ |
| 96 | *ir_key = code; | 118 | *ir_key = code; |
| 97 | *ir_raw = (start << 12) | (toggle << 11) | (dev << 6) | code; | 119 | *ir_raw = ircode; |
| 98 | return 1; | 120 | return 1; |
| 99 | } | 121 | } |
| 100 | 122 | ||
| @@ -224,9 +246,15 @@ static void ir_timer(unsigned long data) | |||
| 224 | static void ir_work(struct work_struct *work) | 246 | static void ir_work(struct work_struct *work) |
| 225 | { | 247 | { |
| 226 | struct IR_i2c *ir = container_of(work, struct IR_i2c, work); | 248 | struct IR_i2c *ir = container_of(work, struct IR_i2c, work); |
| 249 | int polling_interval = 100; | ||
| 250 | |||
| 251 | /* MSI TV@nywhere Plus requires more frequent polling | ||
| 252 | otherwise it will miss some keypresses */ | ||
| 253 | if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30) | ||
| 254 | polling_interval = 50; | ||
| 227 | 255 | ||
| 228 | ir_key_poll(ir); | 256 | ir_key_poll(ir); |
| 229 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(100)); | 257 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval)); |
| 230 | } | 258 | } |
| 231 | 259 | ||
| 232 | /* ----------------------------------------------------------------------- */ | 260 | /* ----------------------------------------------------------------------- */ |
| @@ -465,9 +493,37 @@ static int ir_probe(struct i2c_adapter *adap) | |||
| 465 | (1 == rc) ? "yes" : "no"); | 493 | (1 == rc) ? "yes" : "no"); |
| 466 | if (1 == rc) { | 494 | if (1 == rc) { |
| 467 | ir_attach(adap, probe[i], 0, 0); | 495 | ir_attach(adap, probe[i], 0, 0); |
| 468 | break; | 496 | return 0; |
| 469 | } | 497 | } |
| 470 | } | 498 | } |
| 499 | |||
| 500 | /* Special case for MSI TV@nywhere Plus remote */ | ||
| 501 | if (adap->id == I2C_HW_SAA7134) { | ||
| 502 | u8 temp; | ||
| 503 | |||
| 504 | /* MSI TV@nywhere Plus controller doesn't seem to | ||
| 505 | respond to probes unless we read something from | ||
| 506 | an existing device. Weird... */ | ||
| 507 | |||
| 508 | msg.addr = 0x50; | ||
| 509 | rc = i2c_transfer(adap, &msg, 1); | ||
| 510 | dprintk(1, "probe 0x%02x @ %s: %s\n", | ||
| 511 | msg.addr, adap->name, | ||
| 512 | (1 == rc) ? "yes" : "no"); | ||
| 513 | |||
| 514 | /* Now do the probe. The controller does not respond | ||
| 515 | to 0-byte reads, so we use a 1-byte read instead. */ | ||
| 516 | msg.addr = 0x30; | ||
| 517 | msg.len = 1; | ||
| 518 | msg.buf = &temp; | ||
| 519 | rc = i2c_transfer(adap, &msg, 1); | ||
| 520 | dprintk(1, "probe 0x%02x @ %s: %s\n", | ||
| 521 | msg.addr, adap->name, | ||
| 522 | (1 == rc) ? "yes" : "no"); | ||
| 523 | if (1 == rc) | ||
| 524 | ir_attach(adap, msg.addr, 0, 0); | ||
| 525 | } | ||
| 526 | |||
| 471 | return 0; | 527 | return 0; |
| 472 | } | 528 | } |
| 473 | 529 | ||
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 381af1bceef8..0b8fe85fb697 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h | |||
| @@ -154,7 +154,7 @@ | |||
| 154 | #define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ | 154 | #define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ |
| 155 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ | 155 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ |
| 156 | V4L2_CAP_SLICED_VBI_CAPTURE) | 156 | V4L2_CAP_SLICED_VBI_CAPTURE) |
| 157 | #define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \ | 157 | #define IVTV_CAP_DECODER (V4L2_CAP_VIDEO_OUTPUT | \ |
| 158 | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY) | 158 | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY) |
| 159 | 159 | ||
| 160 | struct ivtv_card_video_input { | 160 | struct ivtv_card_video_input { |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 4afc7ea07e86..aeaa13f6cb36 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
| @@ -61,14 +61,14 @@ | |||
| 61 | #include "tuner-xc2028.h" | 61 | #include "tuner-xc2028.h" |
| 62 | 62 | ||
| 63 | /* var to keep track of the number of array elements in use */ | 63 | /* var to keep track of the number of array elements in use */ |
| 64 | int ivtv_cards_active = 0; | 64 | int ivtv_cards_active; |
| 65 | 65 | ||
| 66 | /* If you have already X v4l cards, then set this to X. This way | 66 | /* If you have already X v4l cards, then set this to X. This way |
| 67 | the device numbers stay matched. Example: you have a WinTV card | 67 | the device numbers stay matched. Example: you have a WinTV card |
| 68 | without radio and a PVR-350 with. Normally this would give a | 68 | without radio and a PVR-350 with. Normally this would give a |
| 69 | video1 device together with a radio0 device for the PVR. By | 69 | video1 device together with a radio0 device for the PVR. By |
| 70 | setting this to 1 you ensure that radio0 is now also radio1. */ | 70 | setting this to 1 you ensure that radio0 is now also radio1. */ |
| 71 | int ivtv_first_minor = 0; | 71 | int ivtv_first_minor; |
| 72 | 72 | ||
| 73 | /* Master variable for all ivtv info */ | 73 | /* Master variable for all ivtv info */ |
| 74 | struct ivtv *ivtv_cards[IVTV_MAX_CARDS]; | 74 | struct ivtv *ivtv_cards[IVTV_MAX_CARDS]; |
| @@ -251,7 +251,7 @@ MODULE_PARM_DESC(newi2c, | |||
| 251 | "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" | 251 | "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" |
| 252 | "\t\t\tDefault is autodetect"); | 252 | "\t\t\tDefault is autodetect"); |
| 253 | 253 | ||
| 254 | MODULE_PARM_DESC(ivtv_first_minor, "Set minor assigned to first card"); | 254 | MODULE_PARM_DESC(ivtv_first_minor, "Set kernel number assigned to first card"); |
| 255 | 255 | ||
| 256 | MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); | 256 | MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); |
| 257 | MODULE_DESCRIPTION("CX23415/CX23416 driver"); | 257 | MODULE_DESCRIPTION("CX23415/CX23416 driver"); |
| @@ -655,9 +655,9 @@ done: | |||
| 655 | 655 | ||
| 656 | if (itv->card == NULL) { | 656 | if (itv->card == NULL) { |
| 657 | itv->card = ivtv_get_card(IVTV_CARD_PVR_150); | 657 | itv->card = ivtv_get_card(IVTV_CARD_PVR_150); |
| 658 | IVTV_ERR("Unknown card: vendor/device: %04x/%04x\n", | 658 | IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n", |
| 659 | itv->dev->vendor, itv->dev->device); | 659 | itv->dev->vendor, itv->dev->device); |
| 660 | IVTV_ERR(" subsystem vendor/device: %04x/%04x\n", | 660 | IVTV_ERR(" subsystem vendor/device: [%04x:%04x]\n", |
| 661 | itv->dev->subsystem_vendor, itv->dev->subsystem_device); | 661 | itv->dev->subsystem_vendor, itv->dev->subsystem_device); |
| 662 | IVTV_ERR(" %s based\n", chipname); | 662 | IVTV_ERR(" %s based\n", chipname); |
| 663 | IVTV_ERR("Defaulting to %s card\n", itv->card->name); | 663 | IVTV_ERR("Defaulting to %s card\n", itv->card->name); |
| @@ -720,7 +720,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) | |||
| 720 | itv->speed = 1000; | 720 | itv->speed = 1000; |
| 721 | 721 | ||
| 722 | /* VBI */ | 722 | /* VBI */ |
| 723 | itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | 723 | itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; |
| 724 | itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced; | 724 | itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced; |
| 725 | 725 | ||
| 726 | /* Init the sg table for osd/yuv output */ | 726 | /* Init the sg table for osd/yuv output */ |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 2ceb5227637c..bc29436e8a3c 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
| @@ -49,7 +49,6 @@ | |||
| 49 | #include <linux/i2c-algo-bit.h> | 49 | #include <linux/i2c-algo-bit.h> |
| 50 | #include <linux/list.h> | 50 | #include <linux/list.h> |
| 51 | #include <linux/unistd.h> | 51 | #include <linux/unistd.h> |
| 52 | #include <linux/byteorder/swab.h> | ||
| 53 | #include <linux/pagemap.h> | 52 | #include <linux/pagemap.h> |
| 54 | #include <linux/scatterlist.h> | 53 | #include <linux/scatterlist.h> |
| 55 | #include <linux/workqueue.h> | 54 | #include <linux/workqueue.h> |
| @@ -507,6 +506,8 @@ struct yuv_playback_info | |||
| 507 | struct v4l2_rect main_rect; | 506 | struct v4l2_rect main_rect; |
| 508 | u32 v4l2_src_w; | 507 | u32 v4l2_src_w; |
| 509 | u32 v4l2_src_h; | 508 | u32 v4l2_src_h; |
| 509 | |||
| 510 | u8 running; /* Have any frames been displayed */ | ||
| 510 | }; | 511 | }; |
| 511 | 512 | ||
| 512 | #define IVTV_VBI_FRAMES 32 | 513 | #define IVTV_VBI_FRAMES 32 |
| @@ -751,6 +752,12 @@ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv); | |||
| 751 | /* First-open initialization: load firmware, init cx25840, etc. */ | 752 | /* First-open initialization: load firmware, init cx25840, etc. */ |
| 752 | int ivtv_init_on_first_open(struct ivtv *itv); | 753 | int ivtv_init_on_first_open(struct ivtv *itv); |
| 753 | 754 | ||
| 755 | /* Test if the current VBI mode is raw (1) or sliced (0) */ | ||
| 756 | static inline int ivtv_raw_vbi(const struct ivtv *itv) | ||
| 757 | { | ||
| 758 | return itv->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE; | ||
| 759 | } | ||
| 760 | |||
| 754 | /* This is a PCI post thing, where if the pci register is not read, then | 761 | /* This is a PCI post thing, where if the pci register is not read, then |
| 755 | the write doesn't always take effect right away. By reading back the | 762 | the write doesn't always take effect right away. By reading back the |
| 756 | register any pending PCI writes will be performed (in order), and so | 763 | register any pending PCI writes will be performed (in order), and so |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 7ec5c99f9ad1..b7457fc60ba5 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | associated VBI streams are also automatically claimed. | 39 | associated VBI streams are also automatically claimed. |
| 40 | Possible error returns: -EBUSY if someone else has claimed | 40 | Possible error returns: -EBUSY if someone else has claimed |
| 41 | the stream or 0 on success. */ | 41 | the stream or 0 on success. */ |
| 42 | int ivtv_claim_stream(struct ivtv_open_id *id, int type) | 42 | static int ivtv_claim_stream(struct ivtv_open_id *id, int type) |
| 43 | { | 43 | { |
| 44 | struct ivtv *itv = id->itv; | 44 | struct ivtv *itv = id->itv; |
| 45 | struct ivtv_stream *s = &itv->streams[type]; | 45 | struct ivtv_stream *s = &itv->streams[type]; |
| @@ -78,7 +78,7 @@ int ivtv_claim_stream(struct ivtv_open_id *id, int type) | |||
| 78 | if (type == IVTV_DEC_STREAM_TYPE_MPG) { | 78 | if (type == IVTV_DEC_STREAM_TYPE_MPG) { |
| 79 | vbi_type = IVTV_DEC_STREAM_TYPE_VBI; | 79 | vbi_type = IVTV_DEC_STREAM_TYPE_VBI; |
| 80 | } else if (type == IVTV_ENC_STREAM_TYPE_MPG && | 80 | } else if (type == IVTV_ENC_STREAM_TYPE_MPG && |
| 81 | itv->vbi.insert_mpeg && itv->vbi.sliced_in->service_set) { | 81 | itv->vbi.insert_mpeg && !ivtv_raw_vbi(itv)) { |
| 82 | vbi_type = IVTV_ENC_STREAM_TYPE_VBI; | 82 | vbi_type = IVTV_ENC_STREAM_TYPE_VBI; |
| 83 | } else { | 83 | } else { |
| 84 | return 0; | 84 | return 0; |
| @@ -305,7 +305,7 @@ static size_t ivtv_copy_buf_to_user(struct ivtv_stream *s, struct ivtv_buffer *b | |||
| 305 | 305 | ||
| 306 | if (len > ucount) len = ucount; | 306 | if (len > ucount) len = ucount; |
| 307 | if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG && | 307 | if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG && |
| 308 | itv->vbi.sliced_in->service_set && buf != &itv->vbi.sliced_mpeg_buf) { | 308 | !ivtv_raw_vbi(itv) && buf != &itv->vbi.sliced_mpeg_buf) { |
| 309 | const char *start = buf->buf + buf->readpos; | 309 | const char *start = buf->buf + buf->readpos; |
| 310 | const char *p = start + 1; | 310 | const char *p = start + 1; |
| 311 | const u8 *q; | 311 | const u8 *q; |
| @@ -372,7 +372,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co | |||
| 372 | /* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should | 372 | /* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should |
| 373 | arrive one-by-one, so make sure we never output more than one VBI frame at a time */ | 373 | arrive one-by-one, so make sure we never output more than one VBI frame at a time */ |
| 374 | if (s->type == IVTV_DEC_STREAM_TYPE_VBI || | 374 | if (s->type == IVTV_DEC_STREAM_TYPE_VBI || |
| 375 | (s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set)) | 375 | (s->type == IVTV_ENC_STREAM_TYPE_VBI && !ivtv_raw_vbi(itv))) |
| 376 | single_frame = 1; | 376 | single_frame = 1; |
| 377 | 377 | ||
| 378 | for (;;) { | 378 | for (;;) { |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/video/ivtv/ivtv-fileops.h index 2c8d5186c9c3..df81e790147f 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.h +++ b/drivers/media/video/ivtv/ivtv-fileops.h | |||
| @@ -38,11 +38,6 @@ void ivtv_unmute(struct ivtv *itv); | |||
| 38 | 38 | ||
| 39 | /* Utilities */ | 39 | /* Utilities */ |
| 40 | 40 | ||
| 41 | /* Try to claim a stream for the filehandle. Return 0 on success, | ||
| 42 | -EBUSY if stream already claimed. Once a stream is claimed, it | ||
| 43 | remains claimed until the associated filehandle is closed. */ | ||
| 44 | int ivtv_claim_stream(struct ivtv_open_id *id, int type); | ||
| 45 | |||
| 46 | /* Release a previously claimed stream. */ | 41 | /* Release a previously claimed stream. */ |
| 47 | void ivtv_release_stream(struct ivtv_stream *s); | 42 | void ivtv_release_stream(struct ivtv_stream *s); |
| 48 | 43 | ||
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c index bc22905ea20f..74a44844ccaf 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.c +++ b/drivers/media/video/ivtv/ivtv-gpio.c | |||
| @@ -124,7 +124,7 @@ void ivtv_reset_ir_gpio(struct ivtv *itv) | |||
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | /* Xceive tuner reset function */ | 126 | /* Xceive tuner reset function */ |
| 127 | int ivtv_reset_tuner_gpio(void *dev, int cmd, int value) | 127 | int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value) |
| 128 | { | 128 | { |
| 129 | struct i2c_algo_bit_data *algo = dev; | 129 | struct i2c_algo_bit_data *algo = dev; |
| 130 | struct ivtv *itv = algo->data; | 130 | struct ivtv *itv = algo->data; |
diff --git a/drivers/media/video/ivtv/ivtv-gpio.h b/drivers/media/video/ivtv/ivtv-gpio.h index 964a265d91a9..48b6291613a2 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.h +++ b/drivers/media/video/ivtv/ivtv-gpio.h | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | /* GPIO stuff */ | 24 | /* GPIO stuff */ |
| 25 | void ivtv_gpio_init(struct ivtv *itv); | 25 | void ivtv_gpio_init(struct ivtv *itv); |
| 26 | void ivtv_reset_ir_gpio(struct ivtv *itv); | 26 | void ivtv_reset_ir_gpio(struct ivtv *itv); |
| 27 | int ivtv_reset_tuner_gpio(void *dev, int cmd, int value); | 27 | int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value); |
| 28 | int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg); | 28 | int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg); |
| 29 | 29 | ||
| 30 | #endif | 30 | #endif |
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index af154238fb9a..24700c211d52 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
| @@ -64,8 +64,6 @@ | |||
| 64 | #include "ivtv-gpio.h" | 64 | #include "ivtv-gpio.h" |
| 65 | #include "ivtv-i2c.h" | 65 | #include "ivtv-i2c.h" |
| 66 | 66 | ||
| 67 | #include <media/ir-kbd-i2c.h> | ||
| 68 | |||
| 69 | /* i2c implementation for cx23415/6 chip, ivtv project. | 67 | /* i2c implementation for cx23415/6 chip, ivtv project. |
| 70 | * Author: Kevin Thayer (nufan_wfk at yahoo.com) | 68 | * Author: Kevin Thayer (nufan_wfk at yahoo.com) |
| 71 | */ | 69 | */ |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 61030309d0ad..8696527ab134 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
| @@ -101,18 +101,15 @@ void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | |||
| 101 | } | 101 | } |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | 104 | static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) |
| 105 | { | 105 | { |
| 106 | int f, l; | 106 | int f, l; |
| 107 | u16 set = 0; | ||
| 108 | 107 | ||
| 109 | for (f = 0; f < 2; f++) { | 108 | for (f = 0; f < 2; f++) { |
| 110 | for (l = 0; l < 24; l++) { | 109 | for (l = 0; l < 24; l++) { |
| 111 | fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal); | 110 | fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal); |
| 112 | set |= fmt->service_lines[f][l]; | ||
| 113 | } | 111 | } |
| 114 | } | 112 | } |
| 115 | return set != 0; | ||
| 116 | } | 113 | } |
| 117 | 114 | ||
| 118 | u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) | 115 | u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) |
| @@ -474,7 +471,7 @@ static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format | |||
| 474 | int h = fmt->fmt.pix.height; | 471 | int h = fmt->fmt.pix.height; |
| 475 | 472 | ||
| 476 | w = min(w, 720); | 473 | w = min(w, 720); |
| 477 | w = max(w, 1); | 474 | w = max(w, 2); |
| 478 | h = min(h, itv->is_50hz ? 576 : 480); | 475 | h = min(h, itv->is_50hz ? 576 : 480); |
| 479 | h = max(h, 2); | 476 | h = max(h, 2); |
| 480 | ivtv_g_fmt_vid_cap(file, fh, fmt); | 477 | ivtv_g_fmt_vid_cap(file, fh, fmt); |
| @@ -512,27 +509,20 @@ static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_ | |||
| 512 | static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) | 509 | static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) |
| 513 | { | 510 | { |
| 514 | struct ivtv_open_id *id = fh; | 511 | struct ivtv_open_id *id = fh; |
| 515 | s32 w, h; | 512 | struct ivtv *itv = id->itv; |
| 516 | int field; | 513 | s32 w = fmt->fmt.pix.width; |
| 517 | int ret; | 514 | s32 h = fmt->fmt.pix.height; |
| 515 | int field = fmt->fmt.pix.field; | ||
| 516 | int ret = ivtv_g_fmt_vid_out(file, fh, fmt); | ||
| 518 | 517 | ||
| 519 | w = fmt->fmt.pix.width; | 518 | w = min(w, 720); |
| 520 | h = fmt->fmt.pix.height; | 519 | w = max(w, 2); |
| 521 | field = fmt->fmt.pix.field; | 520 | h = min(h, itv->is_out_50hz ? 576 : 480); |
| 522 | ret = ivtv_g_fmt_vid_out(file, fh, fmt); | 521 | h = max(h, 2); |
| 522 | if (id->type == IVTV_DEC_STREAM_TYPE_YUV) | ||
| 523 | fmt->fmt.pix.field = field; | ||
| 523 | fmt->fmt.pix.width = w; | 524 | fmt->fmt.pix.width = w; |
| 524 | fmt->fmt.pix.height = h; | 525 | fmt->fmt.pix.height = h; |
| 525 | if (!ret && id->type == IVTV_DEC_STREAM_TYPE_YUV) { | ||
| 526 | fmt->fmt.pix.field = field; | ||
| 527 | if (fmt->fmt.pix.width < 2) | ||
| 528 | fmt->fmt.pix.width = 2; | ||
| 529 | if (fmt->fmt.pix.width > 720) | ||
| 530 | fmt->fmt.pix.width = 720; | ||
| 531 | if (fmt->fmt.pix.height < 2) | ||
| 532 | fmt->fmt.pix.height = 2; | ||
| 533 | if (fmt->fmt.pix.height > 576) | ||
| 534 | fmt->fmt.pix.height = 576; | ||
| 535 | } | ||
| 536 | return ret; | 526 | return ret; |
| 537 | } | 527 | } |
| 538 | 528 | ||
| @@ -560,9 +550,9 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f | |||
| 560 | struct ivtv_open_id *id = fh; | 550 | struct ivtv_open_id *id = fh; |
| 561 | struct ivtv *itv = id->itv; | 551 | struct ivtv *itv = id->itv; |
| 562 | struct cx2341x_mpeg_params *p = &itv->params; | 552 | struct cx2341x_mpeg_params *p = &itv->params; |
| 553 | int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); | ||
| 563 | int w = fmt->fmt.pix.width; | 554 | int w = fmt->fmt.pix.width; |
| 564 | int h = fmt->fmt.pix.height; | 555 | int h = fmt->fmt.pix.height; |
| 565 | int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); | ||
| 566 | 556 | ||
| 567 | if (ret) | 557 | if (ret) |
| 568 | return ret; | 558 | return ret; |
| @@ -585,8 +575,11 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f | |||
| 585 | { | 575 | { |
| 586 | struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; | 576 | struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv; |
| 587 | 577 | ||
| 578 | if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) | ||
| 579 | return -EBUSY; | ||
| 588 | itv->vbi.sliced_in->service_set = 0; | 580 | itv->vbi.sliced_in->service_set = 0; |
| 589 | itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in); | 581 | itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; |
| 582 | itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); | ||
| 590 | return ivtv_g_fmt_vbi_cap(file, fh, fmt); | 583 | return ivtv_g_fmt_vbi_cap(file, fh, fmt); |
| 591 | } | 584 | } |
| 592 | 585 | ||
| @@ -600,10 +593,10 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo | |||
| 600 | if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI) | 593 | if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI) |
| 601 | return ret; | 594 | return ret; |
| 602 | 595 | ||
| 603 | if (check_service_set(vbifmt, itv->is_50hz) == 0) | 596 | check_service_set(vbifmt, itv->is_50hz); |
| 604 | return -EINVAL; | 597 | if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) |
| 605 | if (atomic_read(&itv->capturing) > 0) | ||
| 606 | return -EBUSY; | 598 | return -EBUSY; |
| 599 | itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
| 607 | itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); | 600 | itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); |
| 608 | memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); | 601 | memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); |
| 609 | return 0; | 602 | return 0; |
| @@ -651,8 +644,6 @@ static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f | |||
| 651 | itv->dma_data_req_size = | 644 | itv->dma_data_req_size = |
| 652 | 1080 * ((yi->v4l2_src_h + 31) & ~31); | 645 | 1080 * ((yi->v4l2_src_h + 31) & ~31); |
| 653 | 646 | ||
| 654 | /* Force update of yuv registers */ | ||
| 655 | yi->yuv_forced_update = 1; | ||
| 656 | return 0; | 647 | return 0; |
| 657 | } | 648 | } |
| 658 | 649 | ||
| @@ -761,7 +752,7 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc | |||
| 761 | 752 | ||
| 762 | strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); | 753 | strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); |
| 763 | strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); | 754 | strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); |
| 764 | strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->bus_info)); | 755 | snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->dev)); |
| 765 | vcap->version = IVTV_DRIVER_VERSION; /* version */ | 756 | vcap->version = IVTV_DRIVER_VERSION; /* version */ |
| 766 | vcap->capabilities = itv->v4l2_cap; /* capabilities */ | 757 | vcap->capabilities = itv->v4l2_cap; /* capabilities */ |
| 767 | return 0; | 758 | return 0; |
| @@ -1370,6 +1361,9 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) | |||
| 1370 | if (itv->osd_global_alpha_state) | 1361 | if (itv->osd_global_alpha_state) |
| 1371 | fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; | 1362 | fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; |
| 1372 | 1363 | ||
| 1364 | if (yi->track_osd) | ||
| 1365 | fb->flags |= V4L2_FBUF_FLAG_OVERLAY; | ||
| 1366 | |||
| 1373 | pixfmt &= 7; | 1367 | pixfmt &= 7; |
| 1374 | 1368 | ||
| 1375 | /* no local alpha for RGB565 or unknown formats */ | 1369 | /* no local alpha for RGB565 or unknown formats */ |
| @@ -1389,8 +1383,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) | |||
| 1389 | else | 1383 | else |
| 1390 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; | 1384 | fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; |
| 1391 | } | 1385 | } |
| 1392 | if (yi->track_osd) | ||
| 1393 | fb->flags |= V4L2_FBUF_FLAG_OVERLAY; | ||
| 1394 | 1386 | ||
| 1395 | return 0; | 1387 | return 0; |
| 1396 | } | 1388 | } |
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 34f3ab827858..f5d00ec5da73 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
| @@ -753,7 +753,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
| 753 | */ | 753 | */ |
| 754 | unsigned int frame = read_reg(0x28c0) & 1; | 754 | unsigned int frame = read_reg(0x28c0) & 1; |
| 755 | struct yuv_playback_info *yi = &itv->yuv_info; | 755 | struct yuv_playback_info *yi = &itv->yuv_info; |
| 756 | int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame); | 756 | int last_dma_frame = atomic_read(&yi->next_dma_frame); |
| 757 | struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame]; | 757 | struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame]; |
| 758 | 758 | ||
| 759 | if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); | 759 | if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); |
| @@ -772,6 +772,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
| 772 | next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS; | 772 | next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS; |
| 773 | atomic_set(&yi->next_dma_frame, next_dma_frame); | 773 | atomic_set(&yi->next_dma_frame, next_dma_frame); |
| 774 | yi->fields_lapsed = -1; | 774 | yi->fields_lapsed = -1; |
| 775 | yi->running = 1; | ||
| 775 | } | 776 | } |
| 776 | } | 777 | } |
| 777 | } | 778 | } |
| @@ -804,9 +805,11 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
| 804 | } | 805 | } |
| 805 | 806 | ||
| 806 | /* Check if we need to update the yuv registers */ | 807 | /* Check if we need to update the yuv registers */ |
| 807 | if ((yi->yuv_forced_update || f->update) && last_dma_frame != -1) { | 808 | if (yi->running && (yi->yuv_forced_update || f->update)) { |
| 808 | if (!f->update) { | 809 | if (!f->update) { |
| 809 | last_dma_frame = (u8)(last_dma_frame - 1) % IVTV_YUV_BUFFERS; | 810 | last_dma_frame = |
| 811 | (u8)(atomic_read(&yi->next_dma_frame) - | ||
| 812 | 1) % IVTV_YUV_BUFFERS; | ||
| 810 | f = &yi->new_frame_info[last_dma_frame]; | 813 | f = &yi->new_frame_info[last_dma_frame]; |
| 811 | } | 814 | } |
| 812 | 815 | ||
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 730e85d86fc8..5bbf31e39304 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
| @@ -75,7 +75,7 @@ static const struct file_operations ivtv_v4l2_dec_fops = { | |||
| 75 | static struct { | 75 | static struct { |
| 76 | const char *name; | 76 | const char *name; |
| 77 | int vfl_type; | 77 | int vfl_type; |
| 78 | int minor_offset; | 78 | int num_offset; |
| 79 | int dma, pio; | 79 | int dma, pio; |
| 80 | enum v4l2_buf_type buf_type; | 80 | enum v4l2_buf_type buf_type; |
| 81 | const struct file_operations *fops; | 81 | const struct file_operations *fops; |
| @@ -171,8 +171,8 @@ static void ivtv_stream_init(struct ivtv *itv, int type) | |||
| 171 | static int ivtv_prep_dev(struct ivtv *itv, int type) | 171 | static int ivtv_prep_dev(struct ivtv *itv, int type) |
| 172 | { | 172 | { |
| 173 | struct ivtv_stream *s = &itv->streams[type]; | 173 | struct ivtv_stream *s = &itv->streams[type]; |
| 174 | int minor_offset = ivtv_stream_info[type].minor_offset; | 174 | int num_offset = ivtv_stream_info[type].num_offset; |
| 175 | int minor; | 175 | int num = itv->num + ivtv_first_minor + num_offset; |
| 176 | 176 | ||
| 177 | /* These four fields are always initialized. If v4l2dev == NULL, then | 177 | /* These four fields are always initialized. If v4l2dev == NULL, then |
| 178 | this stream is not in use. In that case no other fields but these | 178 | this stream is not in use. In that case no other fields but these |
| @@ -188,9 +188,6 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) | |||
| 188 | if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 188 | if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
| 189 | return 0; | 189 | return 0; |
| 190 | 190 | ||
| 191 | /* card number + user defined offset + device offset */ | ||
| 192 | minor = itv->num + ivtv_first_minor + minor_offset; | ||
| 193 | |||
| 194 | /* User explicitly selected 0 buffers for these streams, so don't | 191 | /* User explicitly selected 0 buffers for these streams, so don't |
| 195 | create them. */ | 192 | create them. */ |
| 196 | if (ivtv_stream_info[type].dma != PCI_DMA_NONE && | 193 | if (ivtv_stream_info[type].dma != PCI_DMA_NONE && |
| @@ -211,7 +208,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) | |||
| 211 | snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s", | 208 | snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s", |
| 212 | itv->num, s->name); | 209 | itv->num, s->name); |
| 213 | 210 | ||
| 214 | s->v4l2dev->minor = minor; | 211 | s->v4l2dev->num = num; |
| 215 | s->v4l2dev->parent = &itv->dev->dev; | 212 | s->v4l2dev->parent = &itv->dev->dev; |
| 216 | s->v4l2dev->fops = ivtv_stream_info[type].fops; | 213 | s->v4l2dev->fops = ivtv_stream_info[type].fops; |
| 217 | s->v4l2dev->release = video_device_release; | 214 | s->v4l2dev->release = video_device_release; |
| @@ -250,39 +247,46 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) | |||
| 250 | { | 247 | { |
| 251 | struct ivtv_stream *s = &itv->streams[type]; | 248 | struct ivtv_stream *s = &itv->streams[type]; |
| 252 | int vfl_type = ivtv_stream_info[type].vfl_type; | 249 | int vfl_type = ivtv_stream_info[type].vfl_type; |
| 253 | int minor; | 250 | int num; |
| 254 | 251 | ||
| 255 | if (s->v4l2dev == NULL) | 252 | if (s->v4l2dev == NULL) |
| 256 | return 0; | 253 | return 0; |
| 257 | 254 | ||
| 258 | minor = s->v4l2dev->minor; | 255 | num = s->v4l2dev->num; |
| 256 | /* card number + user defined offset + device offset */ | ||
| 257 | if (type != IVTV_ENC_STREAM_TYPE_MPG) { | ||
| 258 | struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG]; | ||
| 259 | |||
| 260 | if (s_mpg->v4l2dev) | ||
| 261 | num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset; | ||
| 262 | } | ||
| 263 | |||
| 259 | /* Register device. First try the desired minor, then any free one. */ | 264 | /* Register device. First try the desired minor, then any free one. */ |
| 260 | if (video_register_device(s->v4l2dev, vfl_type, minor) && | 265 | if (video_register_device(s->v4l2dev, vfl_type, num)) { |
| 261 | video_register_device(s->v4l2dev, vfl_type, -1)) { | 266 | IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n", |
| 262 | IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n", | 267 | s->name, num); |
| 263 | s->name, minor); | ||
| 264 | video_device_release(s->v4l2dev); | 268 | video_device_release(s->v4l2dev); |
| 265 | s->v4l2dev = NULL; | 269 | s->v4l2dev = NULL; |
| 266 | return -ENOMEM; | 270 | return -ENOMEM; |
| 267 | } | 271 | } |
| 272 | num = s->v4l2dev->num; | ||
| 268 | 273 | ||
| 269 | switch (vfl_type) { | 274 | switch (vfl_type) { |
| 270 | case VFL_TYPE_GRABBER: | 275 | case VFL_TYPE_GRABBER: |
| 271 | IVTV_INFO("Registered device video%d for %s (%d kB)\n", | 276 | IVTV_INFO("Registered device video%d for %s (%d kB)\n", |
| 272 | s->v4l2dev->minor, s->name, itv->options.kilobytes[type]); | 277 | num, s->name, itv->options.kilobytes[type]); |
| 273 | break; | 278 | break; |
| 274 | case VFL_TYPE_RADIO: | 279 | case VFL_TYPE_RADIO: |
| 275 | IVTV_INFO("Registered device radio%d for %s\n", | 280 | IVTV_INFO("Registered device radio%d for %s\n", |
| 276 | s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); | 281 | num, s->name); |
| 277 | break; | 282 | break; |
| 278 | case VFL_TYPE_VBI: | 283 | case VFL_TYPE_VBI: |
| 279 | if (itv->options.kilobytes[type]) | 284 | if (itv->options.kilobytes[type]) |
| 280 | IVTV_INFO("Registered device vbi%d for %s (%d kB)\n", | 285 | IVTV_INFO("Registered device vbi%d for %s (%d kB)\n", |
| 281 | s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, | 286 | num, s->name, itv->options.kilobytes[type]); |
| 282 | s->name, itv->options.kilobytes[type]); | ||
| 283 | else | 287 | else |
| 284 | IVTV_INFO("Registered device vbi%d for %s\n", | 288 | IVTV_INFO("Registered device vbi%d for %s\n", |
| 285 | s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name); | 289 | num, s->name); |
| 286 | break; | 290 | break; |
| 287 | } | 291 | } |
| 288 | return 0; | 292 | return 0; |
| @@ -330,7 +334,7 @@ void ivtv_streams_cleanup(struct ivtv *itv, int unregister) | |||
| 330 | 334 | ||
| 331 | static void ivtv_vbi_setup(struct ivtv *itv) | 335 | static void ivtv_vbi_setup(struct ivtv *itv) |
| 332 | { | 336 | { |
| 333 | int raw = itv->vbi.sliced_in->service_set == 0; | 337 | int raw = ivtv_raw_vbi(itv); |
| 334 | u32 data[CX2341X_MBOX_MAX_DATA]; | 338 | u32 data[CX2341X_MBOX_MAX_DATA]; |
| 335 | int lines; | 339 | int lines; |
| 336 | int i; | 340 | int i; |
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index 1ce9deb1104f..4a37a7d2e69d 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c | |||
| @@ -334,7 +334,7 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, | |||
| 334 | int y; | 334 | int y; |
| 335 | 335 | ||
| 336 | /* Raw VBI data */ | 336 | /* Raw VBI data */ |
| 337 | if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set == 0) { | 337 | if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) { |
| 338 | u8 type; | 338 | u8 type; |
| 339 | 339 | ||
| 340 | ivtv_buf_swap(buf); | 340 | ivtv_buf_swap(buf); |
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index 3092ff1d00a0..ee91107376c7 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c | |||
| @@ -1147,6 +1147,7 @@ void ivtv_yuv_close(struct ivtv *itv) | |||
| 1147 | IVTV_DEBUG_YUV("ivtv_yuv_close\n"); | 1147 | IVTV_DEBUG_YUV("ivtv_yuv_close\n"); |
| 1148 | ivtv_waitq(&itv->vsync_waitq); | 1148 | ivtv_waitq(&itv->vsync_waitq); |
| 1149 | 1149 | ||
| 1150 | yi->running = 0; | ||
| 1150 | atomic_set(&yi->next_dma_frame, -1); | 1151 | atomic_set(&yi->next_dma_frame, -1); |
| 1151 | atomic_set(&yi->next_fill_frame, 0); | 1152 | atomic_set(&yi->next_fill_frame, 0); |
| 1152 | 1153 | ||
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index bdfda48e56bf..8a4a150b12fb 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c | |||
| @@ -275,7 +275,6 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, | |||
| 275 | int size_in_bytes) | 275 | int size_in_bytes) |
| 276 | { | 276 | { |
| 277 | DEFINE_WAIT(wait); | 277 | DEFINE_WAIT(wait); |
| 278 | int ret = 0; | ||
| 279 | int got_sig = 0; | 278 | int got_sig = 0; |
| 280 | 279 | ||
| 281 | mutex_lock(&itv->udma.lock); | 280 | mutex_lock(&itv->udma.lock); |
| @@ -316,7 +315,7 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, | |||
| 316 | return -EINTR; | 315 | return -EINTR; |
| 317 | } | 316 | } |
| 318 | 317 | ||
| 319 | return ret; | 318 | return 0; |
| 320 | } | 319 | } |
| 321 | 320 | ||
| 322 | static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, | 321 | static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, |
| @@ -368,11 +367,12 @@ static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, | |||
| 368 | } | 367 | } |
| 369 | 368 | ||
| 370 | static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, | 369 | static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, |
| 371 | size_t count, loff_t *ppos) | 370 | size_t count, loff_t *ppos) |
| 372 | { | 371 | { |
| 373 | unsigned long p = *ppos; | 372 | unsigned long p = *ppos; |
| 374 | void *dst; | 373 | void *dst; |
| 375 | int err = 0; | 374 | int err = 0; |
| 375 | int dma_err; | ||
| 376 | unsigned long total_size; | 376 | unsigned long total_size; |
| 377 | struct ivtv *itv = (struct ivtv *) info->par; | 377 | struct ivtv *itv = (struct ivtv *) info->par; |
| 378 | unsigned long dma_offset = | 378 | unsigned long dma_offset = |
| @@ -399,7 +399,6 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, | |||
| 399 | if (count + p > total_size) { | 399 | if (count + p > total_size) { |
| 400 | if (!err) | 400 | if (!err) |
| 401 | err = -ENOSPC; | 401 | err = -ENOSPC; |
| 402 | |||
| 403 | count = total_size - p; | 402 | count = total_size - p; |
| 404 | } | 403 | } |
| 405 | 404 | ||
| @@ -408,39 +407,34 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, | |||
| 408 | if (info->fbops->fb_sync) | 407 | if (info->fbops->fb_sync) |
| 409 | info->fbops->fb_sync(info); | 408 | info->fbops->fb_sync(info); |
| 410 | 409 | ||
| 411 | if (!access_ok(VERIFY_READ, buf, count)) { | 410 | /* If transfer size > threshold and both src/dst |
| 412 | IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n", | 411 | addresses are aligned, use DMA */ |
| 413 | (unsigned long)buf); | 412 | if (count >= 4096 && |
| 414 | err = -EFAULT; | 413 | ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) { |
| 415 | } | 414 | /* Odd address = can't DMA. Align */ |
| 416 | 415 | if ((unsigned long)dst & 3) { | |
| 417 | if (!err) { | 416 | lead = 4 - ((unsigned long)dst & 3); |
| 418 | /* If transfer size > threshold and both src/dst | 417 | if (copy_from_user(dst, buf, lead)) |
| 419 | addresses are aligned, use DMA */ | 418 | return -EFAULT; |
| 420 | if (count >= 4096 && | 419 | buf += lead; |
| 421 | ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) { | 420 | dst += lead; |
| 422 | /* Odd address = can't DMA. Align */ | ||
| 423 | if ((unsigned long)dst & 3) { | ||
| 424 | lead = 4 - ((unsigned long)dst & 3); | ||
| 425 | memcpy(dst, buf, lead); | ||
| 426 | buf += lead; | ||
| 427 | dst += lead; | ||
| 428 | } | ||
| 429 | /* DMA resolution is 32 bits */ | ||
| 430 | if ((count - lead) & 3) | ||
| 431 | tail = (count - lead) & 3; | ||
| 432 | /* DMA the data */ | ||
| 433 | dma_size = count - lead - tail; | ||
| 434 | err = ivtvfb_prep_dec_dma_to_device(itv, | ||
| 435 | p + lead + dma_offset, (void *)buf, dma_size); | ||
| 436 | dst += dma_size; | ||
| 437 | buf += dma_size; | ||
| 438 | /* Copy any leftover data */ | ||
| 439 | if (tail) | ||
| 440 | memcpy(dst, buf, tail); | ||
| 441 | } else { | ||
| 442 | memcpy(dst, buf, count); | ||
| 443 | } | 421 | } |
| 422 | /* DMA resolution is 32 bits */ | ||
| 423 | if ((count - lead) & 3) | ||
| 424 | tail = (count - lead) & 3; | ||
| 425 | /* DMA the data */ | ||
| 426 | dma_size = count - lead - tail; | ||
| 427 | dma_err = ivtvfb_prep_dec_dma_to_device(itv, | ||
| 428 | p + lead + dma_offset, (void __user *)buf, dma_size); | ||
| 429 | if (dma_err) | ||
| 430 | return dma_err; | ||
| 431 | dst += dma_size; | ||
| 432 | buf += dma_size; | ||
| 433 | /* Copy any leftover data */ | ||
| 434 | if (tail && copy_from_user(dst, buf, tail)) | ||
| 435 | return -EFAULT; | ||
| 436 | } else if (copy_from_user(dst, buf, count)) { | ||
| 437 | return -EFAULT; | ||
| 444 | } | 438 | } |
| 445 | 439 | ||
| 446 | if (!err) | 440 | if (!err) |
| @@ -463,9 +457,12 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar | |||
| 463 | vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | | 457 | vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | |
| 464 | FB_VBLANK_HAVE_VSYNC; | 458 | FB_VBLANK_HAVE_VSYNC; |
| 465 | trace = read_reg(0x028c0) >> 16; | 459 | trace = read_reg(0x028c0) >> 16; |
| 466 | if (itv->is_50hz && trace > 312) trace -= 312; | 460 | if (itv->is_50hz && trace > 312) |
| 467 | else if (itv->is_60hz && trace > 262) trace -= 262; | 461 | trace -= 312; |
| 468 | if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING; | 462 | else if (itv->is_60hz && trace > 262) |
| 463 | trace -= 262; | ||
| 464 | if (trace == 1) | ||
| 465 | vblank.flags |= FB_VBLANK_VSYNCING; | ||
| 469 | vblank.count = itv->last_vsync_field; | 466 | vblank.count = itv->last_vsync_field; |
| 470 | vblank.vcount = trace; | 467 | vblank.vcount = trace; |
| 471 | vblank.hcount = 0; | 468 | vblank.hcount = 0; |
| @@ -476,7 +473,8 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar | |||
| 476 | 473 | ||
| 477 | case FBIO_WAITFORVSYNC: | 474 | case FBIO_WAITFORVSYNC: |
| 478 | prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE); | 475 | prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE); |
| 479 | if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT; | 476 | if (!schedule_timeout(msecs_to_jiffies(50))) |
| 477 | rc = -ETIMEDOUT; | ||
| 480 | finish_wait(&itv->vsync_waitq, &wait); | 478 | finish_wait(&itv->vsync_waitq, &wait); |
| 481 | return rc; | 479 | return rc; |
| 482 | 480 | ||
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index a9ef7802eb5f..6418f4a78f2a 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c | |||
| @@ -843,17 +843,16 @@ again: | |||
| 843 | 843 | ||
| 844 | static int meye_open(struct inode *inode, struct file *file) | 844 | static int meye_open(struct inode *inode, struct file *file) |
| 845 | { | 845 | { |
| 846 | int i, err; | 846 | int i; |
| 847 | 847 | ||
| 848 | err = video_exclusive_open(inode, file); | 848 | if (test_and_set_bit(0, &meye.in_use)) |
| 849 | if (err < 0) | 849 | return -EBUSY; |
| 850 | return err; | ||
| 851 | 850 | ||
| 852 | mchip_hic_stop(); | 851 | mchip_hic_stop(); |
| 853 | 852 | ||
| 854 | if (mchip_dma_alloc()) { | 853 | if (mchip_dma_alloc()) { |
| 855 | printk(KERN_ERR "meye: mchip framebuffer allocation failed\n"); | 854 | printk(KERN_ERR "meye: mchip framebuffer allocation failed\n"); |
| 856 | video_exclusive_release(inode, file); | 855 | clear_bit(0, &meye.in_use); |
| 857 | return -ENOBUFS; | 856 | return -ENOBUFS; |
| 858 | } | 857 | } |
| 859 | 858 | ||
| @@ -868,7 +867,7 @@ static int meye_release(struct inode *inode, struct file *file) | |||
| 868 | { | 867 | { |
| 869 | mchip_hic_stop(); | 868 | mchip_hic_stop(); |
| 870 | mchip_dma_free(); | 869 | mchip_dma_free(); |
| 871 | video_exclusive_release(inode, file); | 870 | clear_bit(0, &meye.in_use); |
| 872 | return 0; | 871 | return 0; |
| 873 | } | 872 | } |
| 874 | 873 | ||
| @@ -1774,6 +1773,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, | |||
| 1774 | goto outnotdev; | 1773 | goto outnotdev; |
| 1775 | } | 1774 | } |
| 1776 | 1775 | ||
| 1776 | ret = -ENOMEM; | ||
| 1777 | meye.mchip_dev = pcidev; | 1777 | meye.mchip_dev = pcidev; |
| 1778 | meye.video_dev = video_device_alloc(); | 1778 | meye.video_dev = video_device_alloc(); |
| 1779 | if (!meye.video_dev) { | 1779 | if (!meye.video_dev) { |
| @@ -1781,7 +1781,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev, | |||
| 1781 | goto outnotdev; | 1781 | goto outnotdev; |
| 1782 | } | 1782 | } |
| 1783 | 1783 | ||
| 1784 | ret = -ENOMEM; | ||
| 1785 | meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); | 1784 | meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE); |
| 1786 | if (!meye.grab_temp) { | 1785 | if (!meye.grab_temp) { |
| 1787 | printk(KERN_ERR "meye: grab buffer allocation failed\n"); | 1786 | printk(KERN_ERR "meye: grab buffer allocation failed\n"); |
diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index d535748df445..5f70a106ba2b 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h | |||
| @@ -311,6 +311,7 @@ struct meye { | |||
| 311 | struct video_device *video_dev; /* video device parameters */ | 311 | struct video_device *video_dev; /* video device parameters */ |
| 312 | struct video_picture picture; /* video picture parameters */ | 312 | struct video_picture picture; /* video picture parameters */ |
| 313 | struct meye_params params; /* additional parameters */ | 313 | struct meye_params params; /* additional parameters */ |
| 314 | unsigned long in_use; /* set to 1 if the device is in use */ | ||
| 314 | #ifdef CONFIG_PM | 315 | #ifdef CONFIG_PM |
| 315 | u8 pm_mchip_mode; /* old mchip mode */ | 316 | u8 pm_mchip_mode; /* old mchip mode */ |
| 316 | #endif | 317 | #endif |
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 554d2295484e..0c524376b67e 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c | |||
| @@ -117,24 +117,51 @@ static int reg_clear(struct soc_camera_device *icd, const u8 reg, | |||
| 117 | 117 | ||
| 118 | static int mt9m001_init(struct soc_camera_device *icd) | 118 | static int mt9m001_init(struct soc_camera_device *icd) |
| 119 | { | 119 | { |
| 120 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | ||
| 121 | struct soc_camera_link *icl = mt9m001->client->dev.platform_data; | ||
| 120 | int ret; | 122 | int ret; |
| 121 | 123 | ||
| 122 | /* Disable chip, synchronous option update */ | ||
| 123 | dev_dbg(icd->vdev->parent, "%s\n", __func__); | 124 | dev_dbg(icd->vdev->parent, "%s\n", __func__); |
| 124 | 125 | ||
| 125 | ret = reg_write(icd, MT9M001_RESET, 1); | 126 | if (icl->power) { |
| 126 | if (ret >= 0) | 127 | ret = icl->power(&mt9m001->client->dev, 1); |
| 127 | ret = reg_write(icd, MT9M001_RESET, 0); | 128 | if (ret < 0) { |
| 128 | if (ret >= 0) | 129 | dev_err(icd->vdev->parent, |
| 130 | "Platform failed to power-on the camera.\n"); | ||
| 131 | return ret; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | /* The camera could have been already on, we reset it additionally */ | ||
| 136 | if (icl->reset) | ||
| 137 | ret = icl->reset(&mt9m001->client->dev); | ||
| 138 | else | ||
| 139 | ret = -ENODEV; | ||
| 140 | |||
| 141 | if (ret < 0) { | ||
| 142 | /* Either no platform reset, or platform reset failed */ | ||
| 143 | ret = reg_write(icd, MT9M001_RESET, 1); | ||
| 144 | if (!ret) | ||
| 145 | ret = reg_write(icd, MT9M001_RESET, 0); | ||
| 146 | } | ||
| 147 | /* Disable chip, synchronous option update */ | ||
| 148 | if (!ret) | ||
| 129 | ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); | 149 | ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); |
| 130 | 150 | ||
| 131 | return ret >= 0 ? 0 : -EIO; | 151 | return ret; |
| 132 | } | 152 | } |
| 133 | 153 | ||
| 134 | static int mt9m001_release(struct soc_camera_device *icd) | 154 | static int mt9m001_release(struct soc_camera_device *icd) |
| 135 | { | 155 | { |
| 156 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | ||
| 157 | struct soc_camera_link *icl = mt9m001->client->dev.platform_data; | ||
| 158 | |||
| 136 | /* Disable the chip */ | 159 | /* Disable the chip */ |
| 137 | reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); | 160 | reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); |
| 161 | |||
| 162 | if (icl->power) | ||
| 163 | icl->power(&mt9m001->client->dev, 0); | ||
| 164 | |||
| 138 | return 0; | 165 | return 0; |
| 139 | } | 166 | } |
| 140 | 167 | ||
| @@ -267,24 +294,24 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, | |||
| 267 | 294 | ||
| 268 | /* Blanking and start values - default... */ | 295 | /* Blanking and start values - default... */ |
| 269 | ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); | 296 | ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); |
| 270 | if (ret >= 0) | 297 | if (!ret) |
| 271 | ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); | 298 | ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank); |
| 272 | 299 | ||
| 273 | /* The caller provides a supported format, as verified per | 300 | /* The caller provides a supported format, as verified per |
| 274 | * call to icd->try_fmt_cap() */ | 301 | * call to icd->try_fmt_cap() */ |
| 275 | if (ret >= 0) | 302 | if (!ret) |
| 276 | ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); | 303 | ret = reg_write(icd, MT9M001_COLUMN_START, rect->left); |
| 277 | if (ret >= 0) | 304 | if (!ret) |
| 278 | ret = reg_write(icd, MT9M001_ROW_START, rect->top); | 305 | ret = reg_write(icd, MT9M001_ROW_START, rect->top); |
| 279 | if (ret >= 0) | 306 | if (!ret) |
| 280 | ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1); | 307 | ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1); |
| 281 | if (ret >= 0) | 308 | if (!ret) |
| 282 | ret = reg_write(icd, MT9M001_WINDOW_HEIGHT, | 309 | ret = reg_write(icd, MT9M001_WINDOW_HEIGHT, |
| 283 | rect->height + icd->y_skip_top - 1); | 310 | rect->height + icd->y_skip_top - 1); |
| 284 | if (ret >= 0 && mt9m001->autoexposure) { | 311 | if (!ret && mt9m001->autoexposure) { |
| 285 | ret = reg_write(icd, MT9M001_SHUTTER_WIDTH, | 312 | ret = reg_write(icd, MT9M001_SHUTTER_WIDTH, |
| 286 | rect->height + icd->y_skip_top + vblank); | 313 | rect->height + icd->y_skip_top + vblank); |
| 287 | if (ret >= 0) { | 314 | if (!ret) { |
| 288 | const struct v4l2_queryctrl *qctrl = | 315 | const struct v4l2_queryctrl *qctrl = |
| 289 | soc_camera_find_qctrl(icd->ops, | 316 | soc_camera_find_qctrl(icd->ops, |
| 290 | V4L2_CID_EXPOSURE); | 317 | V4L2_CID_EXPOSURE); |
| @@ -295,7 +322,7 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, | |||
| 295 | } | 322 | } |
| 296 | } | 323 | } |
| 297 | 324 | ||
| 298 | return ret < 0 ? ret : 0; | 325 | return ret; |
| 299 | } | 326 | } |
| 300 | 327 | ||
| 301 | static int mt9m001_try_fmt_cap(struct soc_camera_device *icd, | 328 | static int mt9m001_try_fmt_cap(struct soc_camera_device *icd, |
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c new file mode 100644 index 000000000000..da0b2d553fd0 --- /dev/null +++ b/drivers/media/video/mt9m111.c | |||
| @@ -0,0 +1,973 @@ | |||
| 1 | /* | ||
| 2 | * Driver for MT9M111 CMOS Image Sensor from Micron | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | #include <linux/videodev2.h> | ||
| 11 | #include <linux/slab.h> | ||
| 12 | #include <linux/i2c.h> | ||
| 13 | #include <linux/log2.h> | ||
| 14 | #include <linux/gpio.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | |||
| 17 | #include <media/v4l2-common.h> | ||
| 18 | #include <media/v4l2-chip-ident.h> | ||
| 19 | #include <media/soc_camera.h> | ||
| 20 | |||
| 21 | /* | ||
| 22 | * mt9m111 i2c address is 0x5d or 0x48 (depending on SAddr pin) | ||
| 23 | * The platform has to define i2c_board_info and call i2c_register_board_info() | ||
| 24 | */ | ||
| 25 | |||
| 26 | /* mt9m111: Sensor register addresses */ | ||
| 27 | #define MT9M111_CHIP_VERSION 0x000 | ||
| 28 | #define MT9M111_ROW_START 0x001 | ||
| 29 | #define MT9M111_COLUMN_START 0x002 | ||
| 30 | #define MT9M111_WINDOW_HEIGHT 0x003 | ||
| 31 | #define MT9M111_WINDOW_WIDTH 0x004 | ||
| 32 | #define MT9M111_HORIZONTAL_BLANKING_B 0x005 | ||
| 33 | #define MT9M111_VERTICAL_BLANKING_B 0x006 | ||
| 34 | #define MT9M111_HORIZONTAL_BLANKING_A 0x007 | ||
| 35 | #define MT9M111_VERTICAL_BLANKING_A 0x008 | ||
| 36 | #define MT9M111_SHUTTER_WIDTH 0x009 | ||
| 37 | #define MT9M111_ROW_SPEED 0x00a | ||
| 38 | #define MT9M111_EXTRA_DELAY 0x00b | ||
| 39 | #define MT9M111_SHUTTER_DELAY 0x00c | ||
| 40 | #define MT9M111_RESET 0x00d | ||
| 41 | #define MT9M111_READ_MODE_B 0x020 | ||
| 42 | #define MT9M111_READ_MODE_A 0x021 | ||
| 43 | #define MT9M111_FLASH_CONTROL 0x023 | ||
| 44 | #define MT9M111_GREEN1_GAIN 0x02b | ||
| 45 | #define MT9M111_BLUE_GAIN 0x02c | ||
| 46 | #define MT9M111_RED_GAIN 0x02d | ||
| 47 | #define MT9M111_GREEN2_GAIN 0x02e | ||
| 48 | #define MT9M111_GLOBAL_GAIN 0x02f | ||
| 49 | #define MT9M111_CONTEXT_CONTROL 0x0c8 | ||
| 50 | #define MT9M111_PAGE_MAP 0x0f0 | ||
| 51 | #define MT9M111_BYTE_WISE_ADDR 0x0f1 | ||
| 52 | |||
| 53 | #define MT9M111_RESET_SYNC_CHANGES (1 << 15) | ||
| 54 | #define MT9M111_RESET_RESTART_BAD_FRAME (1 << 9) | ||
| 55 | #define MT9M111_RESET_SHOW_BAD_FRAMES (1 << 8) | ||
| 56 | #define MT9M111_RESET_RESET_SOC (1 << 5) | ||
| 57 | #define MT9M111_RESET_OUTPUT_DISABLE (1 << 4) | ||
| 58 | #define MT9M111_RESET_CHIP_ENABLE (1 << 3) | ||
| 59 | #define MT9M111_RESET_ANALOG_STANDBY (1 << 2) | ||
| 60 | #define MT9M111_RESET_RESTART_FRAME (1 << 1) | ||
| 61 | #define MT9M111_RESET_RESET_MODE (1 << 0) | ||
| 62 | |||
| 63 | #define MT9M111_RMB_MIRROR_COLS (1 << 1) | ||
| 64 | #define MT9M111_RMB_MIRROR_ROWS (1 << 0) | ||
| 65 | #define MT9M111_CTXT_CTRL_RESTART (1 << 15) | ||
| 66 | #define MT9M111_CTXT_CTRL_DEFECTCOR_B (1 << 12) | ||
| 67 | #define MT9M111_CTXT_CTRL_RESIZE_B (1 << 10) | ||
| 68 | #define MT9M111_CTXT_CTRL_CTRL2_B (1 << 9) | ||
| 69 | #define MT9M111_CTXT_CTRL_GAMMA_B (1 << 8) | ||
| 70 | #define MT9M111_CTXT_CTRL_XENON_EN (1 << 7) | ||
| 71 | #define MT9M111_CTXT_CTRL_READ_MODE_B (1 << 3) | ||
| 72 | #define MT9M111_CTXT_CTRL_LED_FLASH_EN (1 << 2) | ||
| 73 | #define MT9M111_CTXT_CTRL_VBLANK_SEL_B (1 << 1) | ||
| 74 | #define MT9M111_CTXT_CTRL_HBLANK_SEL_B (1 << 0) | ||
| 75 | /* | ||
| 76 | * mt9m111: Colorpipe register addresses (0x100..0x1ff) | ||
| 77 | */ | ||
| 78 | #define MT9M111_OPER_MODE_CTRL 0x106 | ||
| 79 | #define MT9M111_OUTPUT_FORMAT_CTRL 0x108 | ||
| 80 | #define MT9M111_REDUCER_XZOOM_B 0x1a0 | ||
| 81 | #define MT9M111_REDUCER_XSIZE_B 0x1a1 | ||
| 82 | #define MT9M111_REDUCER_YZOOM_B 0x1a3 | ||
| 83 | #define MT9M111_REDUCER_YSIZE_B 0x1a4 | ||
| 84 | #define MT9M111_REDUCER_XZOOM_A 0x1a6 | ||
| 85 | #define MT9M111_REDUCER_XSIZE_A 0x1a7 | ||
| 86 | #define MT9M111_REDUCER_YZOOM_A 0x1a9 | ||
| 87 | #define MT9M111_REDUCER_YSIZE_A 0x1aa | ||
| 88 | |||
| 89 | #define MT9M111_OUTPUT_FORMAT_CTRL2_A 0x13a | ||
| 90 | #define MT9M111_OUTPUT_FORMAT_CTRL2_B 0x19b | ||
| 91 | |||
| 92 | #define MT9M111_OPMODE_AUTOEXPO_EN (1 << 14) | ||
| 93 | |||
| 94 | |||
| 95 | #define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14) | ||
| 96 | #define MT9M111_OUTFMT_BYPASS_IFP (1 << 10) | ||
| 97 | #define MT9M111_OUTFMT_INV_PIX_CLOCK (1 << 9) | ||
| 98 | #define MT9M111_OUTFMT_RGB (1 << 8) | ||
| 99 | #define MT9M111_OUTFMT_RGB565 (0x0 << 6) | ||
| 100 | #define MT9M111_OUTFMT_RGB555 (0x1 << 6) | ||
| 101 | #define MT9M111_OUTFMT_RGB444x (0x2 << 6) | ||
| 102 | #define MT9M111_OUTFMT_RGBx444 (0x3 << 6) | ||
| 103 | #define MT9M111_OUTFMT_TST_RAMP_OFF (0x0 << 4) | ||
| 104 | #define MT9M111_OUTFMT_TST_RAMP_COL (0x1 << 4) | ||
| 105 | #define MT9M111_OUTFMT_TST_RAMP_ROW (0x2 << 4) | ||
| 106 | #define MT9M111_OUTFMT_TST_RAMP_FRAME (0x3 << 4) | ||
| 107 | #define MT9M111_OUTFMT_SHIFT_3_UP (1 << 3) | ||
| 108 | #define MT9M111_OUTFMT_AVG_CHROMA (1 << 2) | ||
| 109 | #define MT9M111_OUTFMT_SWAP_YCbCr_C_Y (1 << 1) | ||
| 110 | #define MT9M111_OUTFMT_SWAP_RGB_EVEN (1 << 1) | ||
| 111 | #define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr (1 << 0) | ||
| 112 | /* | ||
| 113 | * mt9m111: Camera control register addresses (0x200..0x2ff not implemented) | ||
| 114 | */ | ||
| 115 | |||
| 116 | #define reg_read(reg) mt9m111_reg_read(icd, MT9M111_##reg) | ||
| 117 | #define reg_write(reg, val) mt9m111_reg_write(icd, MT9M111_##reg, (val)) | ||
| 118 | #define reg_set(reg, val) mt9m111_reg_set(icd, MT9M111_##reg, (val)) | ||
| 119 | #define reg_clear(reg, val) mt9m111_reg_clear(icd, MT9M111_##reg, (val)) | ||
| 120 | |||
| 121 | #define MT9M111_MIN_DARK_ROWS 8 | ||
| 122 | #define MT9M111_MIN_DARK_COLS 24 | ||
| 123 | #define MT9M111_MAX_HEIGHT 1024 | ||
| 124 | #define MT9M111_MAX_WIDTH 1280 | ||
| 125 | |||
| 126 | #define COL_FMT(_name, _depth, _fourcc, _colorspace) \ | ||
| 127 | { .name = _name, .depth = _depth, .fourcc = _fourcc, \ | ||
| 128 | .colorspace = _colorspace } | ||
| 129 | #define RGB_FMT(_name, _depth, _fourcc) \ | ||
| 130 | COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB) | ||
| 131 | |||
| 132 | static const struct soc_camera_data_format mt9m111_colour_formats[] = { | ||
| 133 | COL_FMT("YCrYCb 8 bit", 8, V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_JPEG), | ||
| 134 | RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565), | ||
| 135 | RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555), | ||
| 136 | RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16), | ||
| 137 | RGB_FMT("Bayer (sRGB) 8 bit", 8, V4L2_PIX_FMT_SBGGR8), | ||
| 138 | }; | ||
| 139 | |||
| 140 | enum mt9m111_context { | ||
| 141 | HIGHPOWER = 0, | ||
| 142 | LOWPOWER, | ||
| 143 | }; | ||
| 144 | |||
| 145 | struct mt9m111 { | ||
| 146 | struct i2c_client *client; | ||
| 147 | struct soc_camera_device icd; | ||
| 148 | int model; /* V4L2_IDENT_MT9M111* codes from v4l2-chip-ident.h */ | ||
| 149 | enum mt9m111_context context; | ||
| 150 | unsigned int left, top, width, height; | ||
| 151 | u32 pixfmt; | ||
| 152 | unsigned char autoexposure; | ||
| 153 | unsigned char datawidth; | ||
| 154 | unsigned int powered:1; | ||
| 155 | unsigned int hflip:1; | ||
| 156 | unsigned int vflip:1; | ||
| 157 | unsigned int swap_rgb_even_odd:1; | ||
| 158 | unsigned int swap_rgb_red_blue:1; | ||
| 159 | unsigned int swap_yuv_y_chromas:1; | ||
| 160 | unsigned int swap_yuv_cb_cr:1; | ||
| 161 | }; | ||
| 162 | |||
| 163 | static int reg_page_map_set(struct i2c_client *client, const u16 reg) | ||
| 164 | { | ||
| 165 | int ret; | ||
| 166 | u16 page; | ||
| 167 | static int lastpage = -1; /* PageMap cache value */ | ||
| 168 | |||
| 169 | page = (reg >> 8); | ||
| 170 | if (page == lastpage) | ||
| 171 | return 0; | ||
| 172 | if (page > 2) | ||
| 173 | return -EINVAL; | ||
| 174 | |||
| 175 | ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page)); | ||
| 176 | if (!ret) | ||
| 177 | lastpage = page; | ||
| 178 | return ret; | ||
| 179 | } | ||
| 180 | |||
| 181 | static int mt9m111_reg_read(struct soc_camera_device *icd, const u16 reg) | ||
| 182 | { | ||
| 183 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 184 | struct i2c_client *client = mt9m111->client; | ||
| 185 | int ret; | ||
| 186 | |||
| 187 | ret = reg_page_map_set(client, reg); | ||
| 188 | if (!ret) | ||
| 189 | ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff))); | ||
| 190 | |||
| 191 | dev_dbg(&icd->dev, "read reg.%03x -> %04x\n", reg, ret); | ||
| 192 | return ret; | ||
| 193 | } | ||
| 194 | |||
| 195 | static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg, | ||
| 196 | const u16 data) | ||
| 197 | { | ||
| 198 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 199 | struct i2c_client *client = mt9m111->client; | ||
| 200 | int ret; | ||
| 201 | |||
| 202 | ret = reg_page_map_set(client, reg); | ||
| 203 | if (!ret) | ||
| 204 | ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff), | ||
| 205 | swab16(data)); | ||
| 206 | dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); | ||
| 207 | return ret; | ||
| 208 | } | ||
| 209 | |||
| 210 | static int mt9m111_reg_set(struct soc_camera_device *icd, const u16 reg, | ||
| 211 | const u16 data) | ||
| 212 | { | ||
| 213 | int ret; | ||
| 214 | |||
| 215 | ret = mt9m111_reg_read(icd, reg); | ||
| 216 | if (ret >= 0) | ||
| 217 | ret = mt9m111_reg_write(icd, reg, ret | data); | ||
| 218 | return ret; | ||
| 219 | } | ||
| 220 | |||
| 221 | static int mt9m111_reg_clear(struct soc_camera_device *icd, const u16 reg, | ||
| 222 | const u16 data) | ||
| 223 | { | ||
| 224 | int ret; | ||
| 225 | |||
| 226 | ret = mt9m111_reg_read(icd, reg); | ||
| 227 | return mt9m111_reg_write(icd, reg, ret & ~data); | ||
| 228 | } | ||
| 229 | |||
| 230 | static int mt9m111_set_context(struct soc_camera_device *icd, | ||
| 231 | enum mt9m111_context ctxt) | ||
| 232 | { | ||
| 233 | int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | ||
| 234 | | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | ||
| 235 | | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B | ||
| 236 | | MT9M111_CTXT_CTRL_VBLANK_SEL_B | ||
| 237 | | MT9M111_CTXT_CTRL_HBLANK_SEL_B; | ||
| 238 | int valA = MT9M111_CTXT_CTRL_RESTART; | ||
| 239 | |||
| 240 | if (ctxt == HIGHPOWER) | ||
| 241 | return reg_write(CONTEXT_CONTROL, valB); | ||
| 242 | else | ||
| 243 | return reg_write(CONTEXT_CONTROL, valA); | ||
| 244 | } | ||
| 245 | |||
| 246 | static int mt9m111_setup_rect(struct soc_camera_device *icd) | ||
| 247 | { | ||
| 248 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 249 | int ret, is_raw_format; | ||
| 250 | int width = mt9m111->width; | ||
| 251 | int height = mt9m111->height; | ||
| 252 | |||
| 253 | if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8) | ||
| 254 | || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)) | ||
| 255 | is_raw_format = 1; | ||
| 256 | else | ||
| 257 | is_raw_format = 0; | ||
| 258 | |||
| 259 | ret = reg_write(COLUMN_START, mt9m111->left); | ||
| 260 | if (!ret) | ||
| 261 | ret = reg_write(ROW_START, mt9m111->top); | ||
| 262 | |||
| 263 | if (is_raw_format) { | ||
| 264 | if (!ret) | ||
| 265 | ret = reg_write(WINDOW_WIDTH, width); | ||
| 266 | if (!ret) | ||
| 267 | ret = reg_write(WINDOW_HEIGHT, height); | ||
| 268 | } else { | ||
| 269 | if (!ret) | ||
| 270 | ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH); | ||
| 271 | if (!ret) | ||
| 272 | ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT); | ||
| 273 | if (!ret) | ||
| 274 | ret = reg_write(REDUCER_XSIZE_B, width); | ||
| 275 | if (!ret) | ||
| 276 | ret = reg_write(REDUCER_YSIZE_B, height); | ||
| 277 | if (!ret) | ||
| 278 | ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH); | ||
| 279 | if (!ret) | ||
| 280 | ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT); | ||
| 281 | if (!ret) | ||
| 282 | ret = reg_write(REDUCER_XSIZE_A, width); | ||
| 283 | if (!ret) | ||
| 284 | ret = reg_write(REDUCER_YSIZE_A, height); | ||
| 285 | } | ||
| 286 | |||
| 287 | return ret; | ||
| 288 | } | ||
| 289 | |||
| 290 | static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) | ||
| 291 | { | ||
| 292 | int ret; | ||
| 293 | |||
| 294 | ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); | ||
| 295 | if (!ret) | ||
| 296 | ret = reg_write(OUTPUT_FORMAT_CTRL2_B, outfmt); | ||
| 297 | return ret; | ||
| 298 | } | ||
| 299 | |||
| 300 | static int mt9m111_setfmt_bayer8(struct soc_camera_device *icd) | ||
| 301 | { | ||
| 302 | return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_PROCESSED_BAYER); | ||
| 303 | } | ||
| 304 | |||
| 305 | static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) | ||
| 306 | { | ||
| 307 | return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_BYPASS_IFP); | ||
| 308 | } | ||
| 309 | |||
| 310 | static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) | ||
| 311 | { | ||
| 312 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 313 | int val = 0; | ||
| 314 | |||
| 315 | if (mt9m111->swap_rgb_red_blue) | ||
| 316 | val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr; | ||
| 317 | if (mt9m111->swap_rgb_even_odd) | ||
| 318 | val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; | ||
| 319 | val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565; | ||
| 320 | |||
| 321 | return mt9m111_setup_pixfmt(icd, val); | ||
| 322 | } | ||
| 323 | |||
| 324 | static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) | ||
| 325 | { | ||
| 326 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 327 | int val = 0; | ||
| 328 | |||
| 329 | if (mt9m111->swap_rgb_red_blue) | ||
| 330 | val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr; | ||
| 331 | if (mt9m111->swap_rgb_even_odd) | ||
| 332 | val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; | ||
| 333 | val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555; | ||
| 334 | |||
| 335 | return mt9m111_setup_pixfmt(icd, val); | ||
| 336 | } | ||
| 337 | |||
| 338 | static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) | ||
| 339 | { | ||
| 340 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 341 | int val = 0; | ||
| 342 | |||
| 343 | if (mt9m111->swap_yuv_cb_cr) | ||
| 344 | val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr; | ||
| 345 | if (mt9m111->swap_yuv_y_chromas) | ||
| 346 | val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y; | ||
| 347 | |||
| 348 | return mt9m111_setup_pixfmt(icd, val); | ||
| 349 | } | ||
| 350 | |||
| 351 | static int mt9m111_enable(struct soc_camera_device *icd) | ||
| 352 | { | ||
| 353 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 354 | struct soc_camera_link *icl = mt9m111->client->dev.platform_data; | ||
| 355 | int ret; | ||
| 356 | |||
| 357 | if (icl->power) { | ||
| 358 | ret = icl->power(&mt9m111->client->dev, 1); | ||
| 359 | if (ret < 0) { | ||
| 360 | dev_err(icd->vdev->parent, | ||
| 361 | "Platform failed to power-on the camera.\n"); | ||
| 362 | return ret; | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); | ||
| 367 | if (!ret) | ||
| 368 | mt9m111->powered = 1; | ||
| 369 | return ret; | ||
| 370 | } | ||
| 371 | |||
| 372 | static int mt9m111_disable(struct soc_camera_device *icd) | ||
| 373 | { | ||
| 374 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 375 | struct soc_camera_link *icl = mt9m111->client->dev.platform_data; | ||
| 376 | int ret; | ||
| 377 | |||
| 378 | ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); | ||
| 379 | if (!ret) | ||
| 380 | mt9m111->powered = 0; | ||
| 381 | |||
| 382 | if (icl->power) | ||
| 383 | icl->power(&mt9m111->client->dev, 0); | ||
| 384 | |||
| 385 | return ret; | ||
| 386 | } | ||
| 387 | |||
| 388 | static int mt9m111_reset(struct soc_camera_device *icd) | ||
| 389 | { | ||
| 390 | int ret; | ||
| 391 | |||
| 392 | ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); | ||
| 393 | if (!ret) | ||
| 394 | ret = reg_set(RESET, MT9M111_RESET_RESET_SOC); | ||
| 395 | if (!ret) | ||
| 396 | ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE | ||
| 397 | | MT9M111_RESET_RESET_SOC); | ||
| 398 | return ret; | ||
| 399 | } | ||
| 400 | |||
| 401 | static int mt9m111_start_capture(struct soc_camera_device *icd) | ||
| 402 | { | ||
| 403 | return 0; | ||
| 404 | } | ||
| 405 | |||
| 406 | static int mt9m111_stop_capture(struct soc_camera_device *icd) | ||
| 407 | { | ||
| 408 | return 0; | ||
| 409 | } | ||
| 410 | |||
| 411 | static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) | ||
| 412 | { | ||
| 413 | return SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | | ||
| 414 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | | ||
| 415 | SOCAM_DATAWIDTH_8; | ||
| 416 | } | ||
| 417 | |||
| 418 | static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) | ||
| 419 | { | ||
| 420 | return 0; | ||
| 421 | } | ||
| 422 | |||
| 423 | static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) | ||
| 424 | { | ||
| 425 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 426 | int ret; | ||
| 427 | |||
| 428 | switch (pixfmt) { | ||
| 429 | case V4L2_PIX_FMT_SBGGR8: | ||
| 430 | ret = mt9m111_setfmt_bayer8(icd); | ||
| 431 | break; | ||
| 432 | case V4L2_PIX_FMT_SBGGR16: | ||
| 433 | ret = mt9m111_setfmt_bayer10(icd); | ||
| 434 | break; | ||
| 435 | case V4L2_PIX_FMT_RGB555: | ||
| 436 | ret = mt9m111_setfmt_rgb555(icd); | ||
| 437 | break; | ||
| 438 | case V4L2_PIX_FMT_RGB565: | ||
| 439 | ret = mt9m111_setfmt_rgb565(icd); | ||
| 440 | break; | ||
| 441 | case V4L2_PIX_FMT_YUYV: | ||
| 442 | ret = mt9m111_setfmt_yuv(icd); | ||
| 443 | break; | ||
| 444 | default: | ||
| 445 | dev_err(&icd->dev, "Pixel format not handled : %x\n", pixfmt); | ||
| 446 | ret = -EINVAL; | ||
| 447 | } | ||
| 448 | |||
| 449 | if (!ret) | ||
| 450 | mt9m111->pixfmt = pixfmt; | ||
| 451 | |||
| 452 | return ret; | ||
| 453 | } | ||
| 454 | |||
| 455 | static int mt9m111_set_fmt_cap(struct soc_camera_device *icd, | ||
| 456 | __u32 pixfmt, struct v4l2_rect *rect) | ||
| 457 | { | ||
| 458 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 459 | int ret; | ||
| 460 | |||
| 461 | mt9m111->left = rect->left; | ||
| 462 | mt9m111->top = rect->top; | ||
| 463 | mt9m111->width = rect->width; | ||
| 464 | mt9m111->height = rect->height; | ||
| 465 | |||
| 466 | dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", | ||
| 467 | __func__, pixfmt, mt9m111->left, mt9m111->top, mt9m111->width, | ||
| 468 | mt9m111->height); | ||
| 469 | |||
| 470 | ret = mt9m111_setup_rect(icd); | ||
| 471 | if (!ret) | ||
| 472 | ret = mt9m111_set_pixfmt(icd, pixfmt); | ||
| 473 | return ret; | ||
| 474 | } | ||
| 475 | |||
| 476 | static int mt9m111_try_fmt_cap(struct soc_camera_device *icd, | ||
| 477 | struct v4l2_format *f) | ||
| 478 | { | ||
| 479 | if (f->fmt.pix.height > MT9M111_MAX_HEIGHT) | ||
| 480 | f->fmt.pix.height = MT9M111_MAX_HEIGHT; | ||
| 481 | if (f->fmt.pix.width > MT9M111_MAX_WIDTH) | ||
| 482 | f->fmt.pix.width = MT9M111_MAX_WIDTH; | ||
| 483 | |||
| 484 | return 0; | ||
| 485 | } | ||
| 486 | |||
| 487 | static int mt9m111_get_chip_id(struct soc_camera_device *icd, | ||
| 488 | struct v4l2_chip_ident *id) | ||
| 489 | { | ||
| 490 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 491 | |||
| 492 | if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR) | ||
| 493 | return -EINVAL; | ||
| 494 | |||
| 495 | if (id->match_chip != mt9m111->client->addr) | ||
| 496 | return -ENODEV; | ||
| 497 | |||
| 498 | id->ident = mt9m111->model; | ||
| 499 | id->revision = 0; | ||
| 500 | |||
| 501 | return 0; | ||
| 502 | } | ||
| 503 | |||
| 504 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
| 505 | static int mt9m111_get_register(struct soc_camera_device *icd, | ||
| 506 | struct v4l2_register *reg) | ||
| 507 | { | ||
| 508 | int val; | ||
| 509 | |||
| 510 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 511 | |||
| 512 | if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) | ||
| 513 | return -EINVAL; | ||
| 514 | if (reg->match_chip != mt9m111->client->addr) | ||
| 515 | return -ENODEV; | ||
| 516 | |||
| 517 | val = mt9m111_reg_read(icd, reg->reg); | ||
| 518 | reg->val = (u64)val; | ||
| 519 | |||
| 520 | if (reg->val > 0xffff) | ||
| 521 | return -EIO; | ||
| 522 | |||
| 523 | return 0; | ||
| 524 | } | ||
| 525 | |||
| 526 | static int mt9m111_set_register(struct soc_camera_device *icd, | ||
| 527 | struct v4l2_register *reg) | ||
| 528 | { | ||
| 529 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 530 | |||
| 531 | if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) | ||
| 532 | return -EINVAL; | ||
| 533 | |||
| 534 | if (reg->match_chip != mt9m111->client->addr) | ||
| 535 | return -ENODEV; | ||
| 536 | |||
| 537 | if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0) | ||
| 538 | return -EIO; | ||
| 539 | |||
| 540 | return 0; | ||
| 541 | } | ||
| 542 | #endif | ||
| 543 | |||
| 544 | static const struct v4l2_queryctrl mt9m111_controls[] = { | ||
| 545 | { | ||
| 546 | .id = V4L2_CID_VFLIP, | ||
| 547 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 548 | .name = "Flip Verticaly", | ||
| 549 | .minimum = 0, | ||
| 550 | .maximum = 1, | ||
| 551 | .step = 1, | ||
| 552 | .default_value = 0, | ||
| 553 | }, { | ||
| 554 | .id = V4L2_CID_HFLIP, | ||
| 555 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 556 | .name = "Flip Horizontaly", | ||
| 557 | .minimum = 0, | ||
| 558 | .maximum = 1, | ||
| 559 | .step = 1, | ||
| 560 | .default_value = 0, | ||
| 561 | }, { /* gain = 1/32*val (=>gain=1 if val==32) */ | ||
| 562 | .id = V4L2_CID_GAIN, | ||
| 563 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 564 | .name = "Gain", | ||
| 565 | .minimum = 0, | ||
| 566 | .maximum = 63 * 2 * 2, | ||
| 567 | .step = 1, | ||
| 568 | .default_value = 32, | ||
| 569 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
| 570 | }, { | ||
| 571 | .id = V4L2_CID_EXPOSURE_AUTO, | ||
| 572 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 573 | .name = "Auto Exposure", | ||
| 574 | .minimum = 0, | ||
| 575 | .maximum = 1, | ||
| 576 | .step = 1, | ||
| 577 | .default_value = 1, | ||
| 578 | } | ||
| 579 | }; | ||
| 580 | |||
| 581 | static int mt9m111_video_probe(struct soc_camera_device *); | ||
| 582 | static void mt9m111_video_remove(struct soc_camera_device *); | ||
| 583 | static int mt9m111_get_control(struct soc_camera_device *, | ||
| 584 | struct v4l2_control *); | ||
| 585 | static int mt9m111_set_control(struct soc_camera_device *, | ||
| 586 | struct v4l2_control *); | ||
| 587 | static int mt9m111_resume(struct soc_camera_device *icd); | ||
| 588 | static int mt9m111_init(struct soc_camera_device *icd); | ||
| 589 | static int mt9m111_release(struct soc_camera_device *icd); | ||
| 590 | |||
| 591 | static struct soc_camera_ops mt9m111_ops = { | ||
| 592 | .owner = THIS_MODULE, | ||
| 593 | .probe = mt9m111_video_probe, | ||
| 594 | .remove = mt9m111_video_remove, | ||
| 595 | .init = mt9m111_init, | ||
| 596 | .resume = mt9m111_resume, | ||
| 597 | .release = mt9m111_release, | ||
| 598 | .start_capture = mt9m111_start_capture, | ||
| 599 | .stop_capture = mt9m111_stop_capture, | ||
| 600 | .set_fmt_cap = mt9m111_set_fmt_cap, | ||
| 601 | .try_fmt_cap = mt9m111_try_fmt_cap, | ||
| 602 | .query_bus_param = mt9m111_query_bus_param, | ||
| 603 | .set_bus_param = mt9m111_set_bus_param, | ||
| 604 | .controls = mt9m111_controls, | ||
| 605 | .num_controls = ARRAY_SIZE(mt9m111_controls), | ||
| 606 | .get_control = mt9m111_get_control, | ||
| 607 | .set_control = mt9m111_set_control, | ||
| 608 | .get_chip_id = mt9m111_get_chip_id, | ||
| 609 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
| 610 | .get_register = mt9m111_get_register, | ||
| 611 | .set_register = mt9m111_set_register, | ||
| 612 | #endif | ||
| 613 | }; | ||
| 614 | |||
| 615 | static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) | ||
| 616 | { | ||
| 617 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 618 | int ret; | ||
| 619 | |||
| 620 | if (mt9m111->context == HIGHPOWER) { | ||
| 621 | if (flip) | ||
| 622 | ret = reg_set(READ_MODE_B, mask); | ||
| 623 | else | ||
| 624 | ret = reg_clear(READ_MODE_B, mask); | ||
| 625 | } else { | ||
| 626 | if (flip) | ||
| 627 | ret = reg_set(READ_MODE_A, mask); | ||
| 628 | else | ||
| 629 | ret = reg_clear(READ_MODE_A, mask); | ||
| 630 | } | ||
| 631 | |||
| 632 | return ret; | ||
| 633 | } | ||
| 634 | |||
| 635 | static int mt9m111_get_global_gain(struct soc_camera_device *icd) | ||
| 636 | { | ||
| 637 | unsigned int data, gain; | ||
| 638 | |||
| 639 | data = reg_read(GLOBAL_GAIN); | ||
| 640 | if (data >= 0) | ||
| 641 | gain = ((data & (1 << 10)) * 2) | ||
| 642 | | ((data & (1 << 9)) * 2) | ||
| 643 | | (data & 0x2f); | ||
| 644 | else | ||
| 645 | gain = data; | ||
| 646 | |||
| 647 | return gain; | ||
| 648 | } | ||
| 649 | static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) | ||
| 650 | { | ||
| 651 | u16 val; | ||
| 652 | |||
| 653 | if (gain > 63 * 2 * 2) | ||
| 654 | return -EINVAL; | ||
| 655 | |||
| 656 | icd->gain = gain; | ||
| 657 | if ((gain >= 64 * 2) && (gain < 63 * 2 * 2)) | ||
| 658 | val = (1 << 10) | (1 << 9) | (gain / 4); | ||
| 659 | else if ((gain >= 64) && (gain < 64 * 2)) | ||
| 660 | val = (1 << 9) | (gain / 2); | ||
| 661 | else | ||
| 662 | val = gain; | ||
| 663 | |||
| 664 | return reg_write(GLOBAL_GAIN, val); | ||
| 665 | } | ||
| 666 | |||
| 667 | static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) | ||
| 668 | { | ||
| 669 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 670 | int ret; | ||
| 671 | |||
| 672 | if (on) | ||
| 673 | ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN); | ||
| 674 | else | ||
| 675 | ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN); | ||
| 676 | |||
| 677 | if (!ret) | ||
| 678 | mt9m111->autoexposure = on; | ||
| 679 | |||
| 680 | return ret; | ||
| 681 | } | ||
| 682 | static int mt9m111_get_control(struct soc_camera_device *icd, | ||
| 683 | struct v4l2_control *ctrl) | ||
| 684 | { | ||
| 685 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 686 | int data; | ||
| 687 | |||
| 688 | switch (ctrl->id) { | ||
| 689 | case V4L2_CID_VFLIP: | ||
| 690 | if (mt9m111->context == HIGHPOWER) | ||
| 691 | data = reg_read(READ_MODE_B); | ||
| 692 | else | ||
| 693 | data = reg_read(READ_MODE_A); | ||
| 694 | |||
| 695 | if (data < 0) | ||
| 696 | return -EIO; | ||
| 697 | ctrl->value = !!(data & MT9M111_RMB_MIRROR_ROWS); | ||
| 698 | break; | ||
| 699 | case V4L2_CID_HFLIP: | ||
| 700 | if (mt9m111->context == HIGHPOWER) | ||
| 701 | data = reg_read(READ_MODE_B); | ||
| 702 | else | ||
| 703 | data = reg_read(READ_MODE_A); | ||
| 704 | |||
| 705 | if (data < 0) | ||
| 706 | return -EIO; | ||
| 707 | ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS); | ||
| 708 | break; | ||
| 709 | case V4L2_CID_GAIN: | ||
| 710 | data = mt9m111_get_global_gain(icd); | ||
| 711 | if (data < 0) | ||
| 712 | return data; | ||
| 713 | ctrl->value = data; | ||
| 714 | break; | ||
| 715 | case V4L2_CID_EXPOSURE_AUTO: | ||
| 716 | ctrl->value = mt9m111->autoexposure; | ||
| 717 | break; | ||
| 718 | } | ||
| 719 | return 0; | ||
| 720 | } | ||
| 721 | |||
| 722 | static int mt9m111_set_control(struct soc_camera_device *icd, | ||
| 723 | struct v4l2_control *ctrl) | ||
| 724 | { | ||
| 725 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 726 | const struct v4l2_queryctrl *qctrl; | ||
| 727 | int ret; | ||
| 728 | |||
| 729 | qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id); | ||
| 730 | |||
| 731 | if (!qctrl) | ||
| 732 | return -EINVAL; | ||
| 733 | |||
| 734 | switch (ctrl->id) { | ||
| 735 | case V4L2_CID_VFLIP: | ||
| 736 | mt9m111->vflip = ctrl->value; | ||
| 737 | ret = mt9m111_set_flip(icd, ctrl->value, | ||
| 738 | MT9M111_RMB_MIRROR_ROWS); | ||
| 739 | break; | ||
| 740 | case V4L2_CID_HFLIP: | ||
| 741 | mt9m111->hflip = ctrl->value; | ||
| 742 | ret = mt9m111_set_flip(icd, ctrl->value, | ||
| 743 | MT9M111_RMB_MIRROR_COLS); | ||
| 744 | break; | ||
| 745 | case V4L2_CID_GAIN: | ||
| 746 | ret = mt9m111_set_global_gain(icd, ctrl->value); | ||
| 747 | break; | ||
| 748 | case V4L2_CID_EXPOSURE_AUTO: | ||
| 749 | ret = mt9m111_set_autoexposure(icd, ctrl->value); | ||
| 750 | break; | ||
| 751 | default: | ||
| 752 | ret = -EINVAL; | ||
| 753 | } | ||
| 754 | |||
| 755 | return ret; | ||
| 756 | } | ||
| 757 | |||
| 758 | static int mt9m111_restore_state(struct soc_camera_device *icd) | ||
| 759 | { | ||
| 760 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 761 | |||
| 762 | mt9m111_set_context(icd, mt9m111->context); | ||
| 763 | mt9m111_set_pixfmt(icd, mt9m111->pixfmt); | ||
| 764 | mt9m111_setup_rect(icd); | ||
| 765 | mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); | ||
| 766 | mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); | ||
| 767 | mt9m111_set_global_gain(icd, icd->gain); | ||
| 768 | mt9m111_set_autoexposure(icd, mt9m111->autoexposure); | ||
| 769 | return 0; | ||
| 770 | } | ||
| 771 | |||
| 772 | static int mt9m111_resume(struct soc_camera_device *icd) | ||
| 773 | { | ||
| 774 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 775 | int ret = 0; | ||
| 776 | |||
| 777 | if (mt9m111->powered) { | ||
| 778 | ret = mt9m111_enable(icd); | ||
| 779 | if (!ret) | ||
| 780 | ret = mt9m111_reset(icd); | ||
| 781 | if (!ret) | ||
| 782 | ret = mt9m111_restore_state(icd); | ||
| 783 | } | ||
| 784 | return ret; | ||
| 785 | } | ||
| 786 | |||
| 787 | static int mt9m111_init(struct soc_camera_device *icd) | ||
| 788 | { | ||
| 789 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 790 | int ret; | ||
| 791 | |||
| 792 | mt9m111->context = HIGHPOWER; | ||
| 793 | ret = mt9m111_enable(icd); | ||
| 794 | if (!ret) | ||
| 795 | ret = mt9m111_reset(icd); | ||
| 796 | if (!ret) | ||
| 797 | ret = mt9m111_set_context(icd, mt9m111->context); | ||
| 798 | if (!ret) | ||
| 799 | ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure); | ||
| 800 | if (ret) | ||
| 801 | dev_err(&icd->dev, "mt9m111 init failed: %d\n", ret); | ||
| 802 | return ret; | ||
| 803 | } | ||
| 804 | |||
| 805 | static int mt9m111_release(struct soc_camera_device *icd) | ||
| 806 | { | ||
| 807 | int ret; | ||
| 808 | |||
| 809 | ret = mt9m111_disable(icd); | ||
| 810 | if (ret < 0) | ||
| 811 | dev_err(&icd->dev, "mt9m111 release failed: %d\n", ret); | ||
| 812 | |||
| 813 | return ret; | ||
| 814 | } | ||
| 815 | |||
| 816 | /* | ||
| 817 | * Interface active, can use i2c. If it fails, it can indeed mean, that | ||
| 818 | * this wasn't our capture interface, so, we wait for the right one | ||
| 819 | */ | ||
| 820 | static int mt9m111_video_probe(struct soc_camera_device *icd) | ||
| 821 | { | ||
| 822 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 823 | s32 data; | ||
| 824 | int ret; | ||
| 825 | |||
| 826 | /* | ||
| 827 | * We must have a parent by now. And it cannot be a wrong one. | ||
| 828 | * So this entire test is completely redundant. | ||
| 829 | */ | ||
| 830 | if (!icd->dev.parent || | ||
| 831 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) | ||
| 832 | return -ENODEV; | ||
| 833 | |||
| 834 | ret = mt9m111_enable(icd); | ||
| 835 | if (ret) | ||
| 836 | goto ei2c; | ||
| 837 | ret = mt9m111_reset(icd); | ||
| 838 | if (ret) | ||
| 839 | goto ei2c; | ||
| 840 | |||
| 841 | data = reg_read(CHIP_VERSION); | ||
| 842 | |||
| 843 | switch (data) { | ||
| 844 | case 0x143a: | ||
| 845 | mt9m111->model = V4L2_IDENT_MT9M111; | ||
| 846 | icd->formats = mt9m111_colour_formats; | ||
| 847 | icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats); | ||
| 848 | break; | ||
| 849 | default: | ||
| 850 | ret = -ENODEV; | ||
| 851 | dev_err(&icd->dev, | ||
| 852 | "No MT9M111 chip detected, register read %x\n", data); | ||
| 853 | goto ei2c; | ||
| 854 | } | ||
| 855 | |||
| 856 | dev_info(&icd->dev, "Detected a MT9M111 chip ID 0x143a\n"); | ||
| 857 | |||
| 858 | ret = soc_camera_video_start(icd); | ||
| 859 | if (ret) | ||
| 860 | goto eisis; | ||
| 861 | |||
| 862 | mt9m111->autoexposure = 1; | ||
| 863 | |||
| 864 | mt9m111->swap_rgb_even_odd = 1; | ||
| 865 | mt9m111->swap_rgb_red_blue = 1; | ||
| 866 | |||
| 867 | return 0; | ||
| 868 | eisis: | ||
| 869 | ei2c: | ||
| 870 | return ret; | ||
| 871 | } | ||
| 872 | |||
| 873 | static void mt9m111_video_remove(struct soc_camera_device *icd) | ||
| 874 | { | ||
| 875 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); | ||
| 876 | |||
| 877 | dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr, | ||
| 878 | mt9m111->icd.dev.parent, mt9m111->icd.vdev); | ||
| 879 | soc_camera_video_stop(&mt9m111->icd); | ||
| 880 | } | ||
| 881 | |||
| 882 | static int mt9m111_probe(struct i2c_client *client, | ||
| 883 | const struct i2c_device_id *did) | ||
| 884 | { | ||
| 885 | struct mt9m111 *mt9m111; | ||
| 886 | struct soc_camera_device *icd; | ||
| 887 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
| 888 | struct soc_camera_link *icl = client->dev.platform_data; | ||
| 889 | int ret; | ||
| 890 | |||
| 891 | if (!icl) { | ||
| 892 | dev_err(&client->dev, "MT9M111 driver needs platform data\n"); | ||
| 893 | return -EINVAL; | ||
| 894 | } | ||
| 895 | |||
| 896 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { | ||
| 897 | dev_warn(&adapter->dev, | ||
| 898 | "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); | ||
| 899 | return -EIO; | ||
| 900 | } | ||
| 901 | |||
| 902 | mt9m111 = kzalloc(sizeof(struct mt9m111), GFP_KERNEL); | ||
| 903 | if (!mt9m111) | ||
| 904 | return -ENOMEM; | ||
| 905 | |||
| 906 | mt9m111->client = client; | ||
| 907 | i2c_set_clientdata(client, mt9m111); | ||
| 908 | |||
| 909 | /* Second stage probe - when a capture adapter is there */ | ||
| 910 | icd = &mt9m111->icd; | ||
| 911 | icd->ops = &mt9m111_ops; | ||
| 912 | icd->control = &client->dev; | ||
| 913 | icd->x_min = MT9M111_MIN_DARK_COLS; | ||
| 914 | icd->y_min = MT9M111_MIN_DARK_ROWS; | ||
| 915 | icd->x_current = icd->x_min; | ||
| 916 | icd->y_current = icd->y_min; | ||
| 917 | icd->width_min = MT9M111_MIN_DARK_ROWS; | ||
| 918 | icd->width_max = MT9M111_MAX_WIDTH; | ||
| 919 | icd->height_min = MT9M111_MIN_DARK_COLS; | ||
| 920 | icd->height_max = MT9M111_MAX_HEIGHT; | ||
| 921 | icd->y_skip_top = 0; | ||
| 922 | icd->iface = icl->bus_id; | ||
| 923 | |||
| 924 | ret = soc_camera_device_register(icd); | ||
| 925 | if (ret) | ||
| 926 | goto eisdr; | ||
| 927 | return 0; | ||
| 928 | |||
| 929 | eisdr: | ||
| 930 | kfree(mt9m111); | ||
| 931 | return ret; | ||
| 932 | } | ||
| 933 | |||
| 934 | static int mt9m111_remove(struct i2c_client *client) | ||
| 935 | { | ||
| 936 | struct mt9m111 *mt9m111 = i2c_get_clientdata(client); | ||
| 937 | soc_camera_device_unregister(&mt9m111->icd); | ||
| 938 | kfree(mt9m111); | ||
| 939 | |||
| 940 | return 0; | ||
| 941 | } | ||
| 942 | |||
| 943 | static const struct i2c_device_id mt9m111_id[] = { | ||
| 944 | { "mt9m111", 0 }, | ||
| 945 | { } | ||
| 946 | }; | ||
| 947 | MODULE_DEVICE_TABLE(i2c, mt9m111_id); | ||
| 948 | |||
| 949 | static struct i2c_driver mt9m111_i2c_driver = { | ||
| 950 | .driver = { | ||
| 951 | .name = "mt9m111", | ||
| 952 | }, | ||
| 953 | .probe = mt9m111_probe, | ||
| 954 | .remove = mt9m111_remove, | ||
| 955 | .id_table = mt9m111_id, | ||
| 956 | }; | ||
| 957 | |||
| 958 | static int __init mt9m111_mod_init(void) | ||
| 959 | { | ||
| 960 | return i2c_add_driver(&mt9m111_i2c_driver); | ||
| 961 | } | ||
| 962 | |||
| 963 | static void __exit mt9m111_mod_exit(void) | ||
| 964 | { | ||
| 965 | i2c_del_driver(&mt9m111_i2c_driver); | ||
| 966 | } | ||
| 967 | |||
| 968 | module_init(mt9m111_mod_init); | ||
| 969 | module_exit(mt9m111_mod_exit); | ||
| 970 | |||
| 971 | MODULE_DESCRIPTION("Micron MT9M111 Camera driver"); | ||
| 972 | MODULE_AUTHOR("Robert Jarzmik"); | ||
| 973 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 56808cd2f8a9..2584201059d8 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
| @@ -134,34 +134,56 @@ static int reg_clear(struct soc_camera_device *icd, const u8 reg, | |||
| 134 | static int mt9v022_init(struct soc_camera_device *icd) | 134 | static int mt9v022_init(struct soc_camera_device *icd) |
| 135 | { | 135 | { |
| 136 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 136 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); |
| 137 | struct soc_camera_link *icl = mt9v022->client->dev.platform_data; | ||
| 137 | int ret; | 138 | int ret; |
| 138 | 139 | ||
| 140 | if (icl->power) { | ||
| 141 | ret = icl->power(&mt9v022->client->dev, 1); | ||
| 142 | if (ret < 0) { | ||
| 143 | dev_err(icd->vdev->parent, | ||
| 144 | "Platform failed to power-on the camera.\n"); | ||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | /* | ||
| 150 | * The camera could have been already on, we hard-reset it additionally, | ||
| 151 | * if available. Soft reset is done in video_probe(). | ||
| 152 | */ | ||
| 153 | if (icl->reset) | ||
| 154 | icl->reset(&mt9v022->client->dev); | ||
| 155 | |||
| 139 | /* Almost the default mode: master, parallel, simultaneous, and an | 156 | /* Almost the default mode: master, parallel, simultaneous, and an |
| 140 | * undocumented bit 0x200, which is present in table 7, but not in 8, | 157 | * undocumented bit 0x200, which is present in table 7, but not in 8, |
| 141 | * plus snapshot mode to disable scan for now */ | 158 | * plus snapshot mode to disable scan for now */ |
| 142 | mt9v022->chip_control |= 0x10; | 159 | mt9v022->chip_control |= 0x10; |
| 143 | ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); | 160 | ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); |
| 144 | if (ret >= 0) | 161 | if (!ret) |
| 145 | reg_write(icd, MT9V022_READ_MODE, 0x300); | 162 | ret = reg_write(icd, MT9V022_READ_MODE, 0x300); |
| 146 | 163 | ||
| 147 | /* All defaults */ | 164 | /* All defaults */ |
| 148 | if (ret >= 0) | 165 | if (!ret) |
| 149 | /* AEC, AGC on */ | 166 | /* AEC, AGC on */ |
| 150 | ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3); | 167 | ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3); |
| 151 | if (ret >= 0) | 168 | if (!ret) |
| 152 | ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); | 169 | ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); |
| 153 | if (ret >= 0) | 170 | if (!ret) |
| 154 | /* default - auto */ | 171 | /* default - auto */ |
| 155 | ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); | 172 | ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1); |
| 156 | if (ret >= 0) | 173 | if (!ret) |
| 157 | ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0); | 174 | ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0); |
| 158 | 175 | ||
| 159 | return ret >= 0 ? 0 : -EIO; | 176 | return ret; |
| 160 | } | 177 | } |
| 161 | 178 | ||
| 162 | static int mt9v022_release(struct soc_camera_device *icd) | 179 | static int mt9v022_release(struct soc_camera_device *icd) |
| 163 | { | 180 | { |
| 164 | /* Nothing? */ | 181 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); |
| 182 | struct soc_camera_link *icl = mt9v022->client->dev.platform_data; | ||
| 183 | |||
| 184 | if (icl->power) | ||
| 185 | icl->power(&mt9v022->client->dev, 0); | ||
| 186 | |||
| 165 | return 0; | 187 | return 0; |
| 166 | } | 188 | } |
| 167 | 189 | ||
| @@ -352,21 +374,21 @@ static int mt9v022_set_fmt_cap(struct soc_camera_device *icd, | |||
| 352 | rect->height + icd->y_skip_top + 43); | 374 | rect->height + icd->y_skip_top + 43); |
| 353 | } | 375 | } |
| 354 | /* Setup frame format: defaults apart from width and height */ | 376 | /* Setup frame format: defaults apart from width and height */ |
| 355 | if (ret >= 0) | 377 | if (!ret) |
| 356 | ret = reg_write(icd, MT9V022_COLUMN_START, rect->left); | 378 | ret = reg_write(icd, MT9V022_COLUMN_START, rect->left); |
| 357 | if (ret >= 0) | 379 | if (!ret) |
| 358 | ret = reg_write(icd, MT9V022_ROW_START, rect->top); | 380 | ret = reg_write(icd, MT9V022_ROW_START, rect->top); |
| 359 | if (ret >= 0) | 381 | if (!ret) |
| 360 | /* Default 94, Phytec driver says: | 382 | /* Default 94, Phytec driver says: |
| 361 | * "width + horizontal blank >= 660" */ | 383 | * "width + horizontal blank >= 660" */ |
| 362 | ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING, | 384 | ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING, |
| 363 | rect->width > 660 - 43 ? 43 : | 385 | rect->width > 660 - 43 ? 43 : |
| 364 | 660 - rect->width); | 386 | 660 - rect->width); |
| 365 | if (ret >= 0) | 387 | if (!ret) |
| 366 | ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45); | 388 | ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45); |
| 367 | if (ret >= 0) | 389 | if (!ret) |
| 368 | ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width); | 390 | ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width); |
| 369 | if (ret >= 0) | 391 | if (!ret) |
| 370 | ret = reg_write(icd, MT9V022_WINDOW_HEIGHT, | 392 | ret = reg_write(icd, MT9V022_WINDOW_HEIGHT, |
| 371 | rect->height + icd->y_skip_top); | 393 | rect->height + icd->y_skip_top); |
| 372 | 394 | ||
| @@ -717,7 +739,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) | |||
| 717 | icd->num_formats = 1; | 739 | icd->num_formats = 1; |
| 718 | } | 740 | } |
| 719 | 741 | ||
| 720 | if (ret >= 0) | 742 | if (!ret) |
| 721 | ret = soc_camera_video_start(icd); | 743 | ret = soc_camera_video_start(icd); |
| 722 | if (ret < 0) | 744 | if (ret < 0) |
| 723 | goto eisis; | 745 | goto eisis; |
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 8ef578caba3b..7f130284b5c7 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <media/tuner.h> | 27 | #include <media/tuner.h> |
| 28 | #include <linux/video_decoder.h> | 28 | #include <linux/video_decoder.h> |
| 29 | #include <media/v4l2-common.h> | 29 | #include <media/v4l2-common.h> |
| 30 | #include <media/saa7115.h> | ||
| 30 | 31 | ||
| 31 | #include "mxb.h" | 32 | #include "mxb.h" |
| 32 | #include "tea6415c.h" | 33 | #include "tea6415c.h" |
| @@ -122,6 +123,8 @@ static struct saa7146_extension_ioctls ioctls[] = { | |||
| 122 | { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE }, | 123 | { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE }, |
| 123 | { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, | 124 | { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, |
| 124 | { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, | 125 | { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, |
| 126 | { VIDIOC_DBG_G_REGISTER, SAA7146_EXCLUSIVE }, | ||
| 127 | { VIDIOC_DBG_S_REGISTER, SAA7146_EXCLUSIVE }, | ||
| 125 | { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */ | 128 | { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */ |
| 126 | { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */ | 129 | { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */ |
| 127 | { 0, 0 } | 130 | { 0, 0 } |
| @@ -134,12 +137,12 @@ struct mxb | |||
| 134 | 137 | ||
| 135 | struct i2c_adapter i2c_adapter; | 138 | struct i2c_adapter i2c_adapter; |
| 136 | 139 | ||
| 137 | struct i2c_client* saa7111a; | 140 | struct i2c_client *saa7111a; |
| 138 | struct i2c_client* tda9840; | 141 | struct i2c_client *tda9840; |
| 139 | struct i2c_client* tea6415c; | 142 | struct i2c_client *tea6415c; |
| 140 | struct i2c_client* tuner; | 143 | struct i2c_client *tuner; |
| 141 | struct i2c_client* tea6420_1; | 144 | struct i2c_client *tea6420_1; |
| 142 | struct i2c_client* tea6420_2; | 145 | struct i2c_client *tea6420_2; |
| 143 | 146 | ||
| 144 | int cur_mode; /* current audio mode (mono, stereo, ...) */ | 147 | int cur_mode; /* current audio mode (mono, stereo, ...) */ |
| 145 | int cur_input; /* current input */ | 148 | int cur_input; /* current input */ |
| @@ -151,23 +154,23 @@ static struct saa7146_extension extension; | |||
| 151 | 154 | ||
| 152 | static int mxb_check_clients(struct device *dev, void *data) | 155 | static int mxb_check_clients(struct device *dev, void *data) |
| 153 | { | 156 | { |
| 154 | struct mxb* mxb = data; | 157 | struct mxb *mxb = data; |
| 155 | struct i2c_client *client = i2c_verify_client(dev); | 158 | struct i2c_client *client = i2c_verify_client(dev); |
| 156 | 159 | ||
| 157 | if( !client ) | 160 | if (!client) |
| 158 | return 0; | 161 | return 0; |
| 159 | 162 | ||
| 160 | if( I2C_ADDR_TEA6420_1 == client->addr ) | 163 | if (I2C_ADDR_TEA6420_1 == client->addr) |
| 161 | mxb->tea6420_1 = client; | 164 | mxb->tea6420_1 = client; |
| 162 | if( I2C_ADDR_TEA6420_2 == client->addr ) | 165 | if (I2C_ADDR_TEA6420_2 == client->addr) |
| 163 | mxb->tea6420_2 = client; | 166 | mxb->tea6420_2 = client; |
| 164 | if( I2C_TEA6415C_2 == client->addr ) | 167 | if (I2C_TEA6415C_2 == client->addr) |
| 165 | mxb->tea6415c = client; | 168 | mxb->tea6415c = client; |
| 166 | if( I2C_ADDR_TDA9840 == client->addr ) | 169 | if (I2C_ADDR_TDA9840 == client->addr) |
| 167 | mxb->tda9840 = client; | 170 | mxb->tda9840 = client; |
| 168 | if( I2C_SAA7111 == client->addr ) | 171 | if (I2C_SAA7111 == client->addr) |
| 169 | mxb->saa7111a = client; | 172 | mxb->saa7111a = client; |
| 170 | if( 0x60 == client->addr ) | 173 | if (0x60 == client->addr) |
| 171 | mxb->tuner = client; | 174 | mxb->tuner = client; |
| 172 | 175 | ||
| 173 | return 0; | 176 | return 0; |
| @@ -178,23 +181,28 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
| 178 | struct mxb* mxb = NULL; | 181 | struct mxb* mxb = NULL; |
| 179 | int result; | 182 | int result; |
| 180 | 183 | ||
| 181 | if ((result = request_module("saa7111")) < 0) { | 184 | result = request_module("saa7115"); |
| 185 | if (result < 0) { | ||
| 182 | printk("mxb: saa7111 i2c module not available.\n"); | 186 | printk("mxb: saa7111 i2c module not available.\n"); |
| 183 | return -ENODEV; | 187 | return -ENODEV; |
| 184 | } | 188 | } |
| 185 | if ((result = request_module("tea6420")) < 0) { | 189 | result = request_module("tea6420"); |
| 190 | if (result < 0) { | ||
| 186 | printk("mxb: tea6420 i2c module not available.\n"); | 191 | printk("mxb: tea6420 i2c module not available.\n"); |
| 187 | return -ENODEV; | 192 | return -ENODEV; |
| 188 | } | 193 | } |
| 189 | if ((result = request_module("tea6415c")) < 0) { | 194 | result = request_module("tea6415c"); |
| 195 | if (result < 0) { | ||
| 190 | printk("mxb: tea6415c i2c module not available.\n"); | 196 | printk("mxb: tea6415c i2c module not available.\n"); |
| 191 | return -ENODEV; | 197 | return -ENODEV; |
| 192 | } | 198 | } |
| 193 | if ((result = request_module("tda9840")) < 0) { | 199 | result = request_module("tda9840"); |
| 200 | if (result < 0) { | ||
| 194 | printk("mxb: tda9840 i2c module not available.\n"); | 201 | printk("mxb: tda9840 i2c module not available.\n"); |
| 195 | return -ENODEV; | 202 | return -ENODEV; |
| 196 | } | 203 | } |
| 197 | if ((result = request_module("tuner")) < 0) { | 204 | result = request_module("tuner"); |
| 205 | if (result < 0) { | ||
| 198 | printk("mxb: tuner i2c module not available.\n"); | 206 | printk("mxb: tuner i2c module not available.\n"); |
| 199 | return -ENODEV; | 207 | return -ENODEV; |
| 200 | } | 208 | } |
| @@ -207,9 +215,10 @@ static int mxb_probe(struct saa7146_dev* dev) | |||
| 207 | 215 | ||
| 208 | mxb->i2c_adapter = (struct i2c_adapter) { | 216 | mxb->i2c_adapter = (struct i2c_adapter) { |
| 209 | .class = I2C_CLASS_TV_ANALOG, | 217 | .class = I2C_CLASS_TV_ANALOG, |
| 210 | .name = "mxb", | ||
| 211 | }; | 218 | }; |
| 212 | 219 | ||
| 220 | snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num); | ||
| 221 | |||
| 213 | saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); | 222 | saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); |
| 214 | if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { | 223 | if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { |
| 215 | DEB_S(("cannot register i2c-device. skipping.\n")); | 224 | DEB_S(("cannot register i2c-device. skipping.\n")); |
| @@ -290,38 +299,7 @@ static struct { | |||
| 290 | { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, | 299 | { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, |
| 291 | { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, | 300 | { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } }, |
| 292 | { 3, { 0x80, 0xb3, 0x0a } }, | 301 | { 3, { 0x80, 0xb3, 0x0a } }, |
| 293 | {-1, { 0} } | 302 | {-1, { 0 } } |
| 294 | }; | ||
| 295 | |||
| 296 | static const unsigned char mxb_saa7111_init[] = { | ||
| 297 | 0x00, 0x00, /* 00 - ID byte */ | ||
| 298 | 0x01, 0x00, /* 01 - reserved */ | ||
| 299 | |||
| 300 | /*front end */ | ||
| 301 | 0x02, 0xd8, /* 02 - FUSE=x, GUDL=x, MODE=x */ | ||
| 302 | 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ | ||
| 303 | 0x04, 0x00, /* 04 - GAI1=256 */ | ||
| 304 | 0x05, 0x00, /* 05 - GAI2=256 */ | ||
| 305 | |||
| 306 | /* decoder */ | ||
| 307 | 0x06, 0xf0, /* 06 - HSB at xx(50Hz) / xx(60Hz) pixels after end of last line */ | ||
| 308 | 0x07, 0x30, /* 07 - HSS at xx(50Hz) / xx(60Hz) pixels after end of last line */ | ||
| 309 | 0x08, 0xa8, /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */ | ||
| 310 | 0x09, 0x02, /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */ | ||
| 311 | 0x0a, 0x80, /* 0a - BRIG=128 */ | ||
| 312 | 0x0b, 0x47, /* 0b - CONT=1.109 */ | ||
| 313 | 0x0c, 0x40, /* 0c - SATN=1.0 */ | ||
| 314 | 0x0d, 0x00, /* 0d - HUE=0 */ | ||
| 315 | 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */ | ||
| 316 | 0x0f, 0x00, /* 0f - reserved */ | ||
| 317 | 0x10, 0xd0, /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */ | ||
| 318 | 0x11, 0x8c, /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */ | ||
| 319 | 0x12, 0x80, /* 12 - xx output control 2 */ | ||
| 320 | 0x13, 0x30, /* 13 - xx output control 3 */ | ||
| 321 | 0x14, 0x00, /* 14 - reserved */ | ||
| 322 | 0x15, 0x15, /* 15 - VBI */ | ||
| 323 | 0x16, 0x04, /* 16 - VBI */ | ||
| 324 | 0x17, 0x00, /* 17 - VBI */ | ||
| 325 | }; | 303 | }; |
| 326 | 304 | ||
| 327 | /* bring hardware to a sane state. this has to be done, just in case someone | 305 | /* bring hardware to a sane state. this has to be done, just in case someone |
| @@ -331,37 +309,28 @@ static const unsigned char mxb_saa7111_init[] = { | |||
| 331 | static int mxb_init_done(struct saa7146_dev* dev) | 309 | static int mxb_init_done(struct saa7146_dev* dev) |
| 332 | { | 310 | { |
| 333 | struct mxb* mxb = (struct mxb*)dev->ext_priv; | 311 | struct mxb* mxb = (struct mxb*)dev->ext_priv; |
| 334 | struct video_decoder_init init; | ||
| 335 | struct i2c_msg msg; | 312 | struct i2c_msg msg; |
| 336 | struct tuner_setup tun_setup; | 313 | struct tuner_setup tun_setup; |
| 337 | v4l2_std_id std = V4L2_STD_PAL_BG; | 314 | v4l2_std_id std = V4L2_STD_PAL_BG; |
| 315 | struct v4l2_routing route; | ||
| 338 | 316 | ||
| 339 | int i = 0, err = 0; | 317 | int i = 0, err = 0; |
| 340 | struct tea6415c_multiplex vm; | 318 | struct tea6415c_multiplex vm; |
| 341 | 319 | ||
| 342 | /* select video mode in saa7111a */ | 320 | /* select video mode in saa7111a */ |
| 343 | i = VIDEO_MODE_PAL; | 321 | mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std); |
| 344 | /* fixme: currently pointless: gets overwritten by configuration below */ | ||
| 345 | mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i); | ||
| 346 | |||
| 347 | /* write configuration to saa7111a */ | ||
| 348 | init.data = mxb_saa7111_init; | ||
| 349 | init.len = sizeof(mxb_saa7111_init); | ||
| 350 | mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_INIT, &init); | ||
| 351 | 322 | ||
| 352 | /* select tuner-output on saa7111a */ | 323 | /* select tuner-output on saa7111a */ |
| 353 | i = 0; | 324 | i = 0; |
| 354 | mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i); | 325 | route.input = SAA7115_COMPOSITE0; |
| 355 | 326 | route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS; | |
| 356 | /* enable vbi bypass */ | 327 | mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
| 357 | i = 1; | ||
| 358 | mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_VBI_BYPASS, &i); | ||
| 359 | 328 | ||
| 360 | /* select a tuner type */ | 329 | /* select a tuner type */ |
| 361 | tun_setup.mode_mask = T_ANALOG_TV; | 330 | tun_setup.mode_mask = T_ANALOG_TV; |
| 362 | tun_setup.addr = ADDR_UNSET; | 331 | tun_setup.addr = ADDR_UNSET; |
| 363 | tun_setup.type = TUNER_PHILIPS_PAL; | 332 | tun_setup.type = TUNER_PHILIPS_PAL; |
| 364 | mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE_ADDR, &tun_setup); | 333 | mxb->tuner->driver->command(mxb->tuner, TUNER_SET_TYPE_ADDR, &tun_setup); |
| 365 | /* tune in some frequency on tuner */ | 334 | /* tune in some frequency on tuner */ |
| 366 | mxb->cur_freq.tuner = 0; | 335 | mxb->cur_freq.tuner = 0; |
| 367 | mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV; | 336 | mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV; |
| @@ -373,27 +342,26 @@ static int mxb_init_done(struct saa7146_dev* dev) | |||
| 373 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); | 342 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); |
| 374 | 343 | ||
| 375 | /* mute audio on tea6420s */ | 344 | /* mute audio on tea6420s */ |
| 376 | mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]); | 345 | mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[6][0]); |
| 377 | mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]); | 346 | mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[6][1]); |
| 378 | mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[6][0]); | 347 | mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[6][0]); |
| 379 | mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[6][1]); | 348 | mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[6][1]); |
| 380 | 349 | ||
| 381 | /* switch to tuner-channel on tea6415c*/ | 350 | /* switch to tuner-channel on tea6415c*/ |
| 382 | vm.out = 17; | 351 | vm.out = 17; |
| 383 | vm.in = 3; | 352 | vm.in = 3; |
| 384 | mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm); | 353 | mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm); |
| 385 | 354 | ||
| 386 | /* select tuner-output on multicable on tea6415c*/ | 355 | /* select tuner-output on multicable on tea6415c*/ |
| 387 | vm.in = 3; | 356 | vm.in = 3; |
| 388 | vm.out = 13; | 357 | vm.out = 13; |
| 389 | mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm); | 358 | mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm); |
| 390 | 359 | ||
| 391 | /* the rest for mxb */ | 360 | /* the rest for mxb */ |
| 392 | mxb->cur_input = 0; | 361 | mxb->cur_input = 0; |
| 393 | mxb->cur_mute = 1; | 362 | mxb->cur_mute = 1; |
| 394 | 363 | ||
| 395 | mxb->cur_mode = V4L2_TUNER_MODE_STEREO; | 364 | mxb->cur_mode = V4L2_TUNER_MODE_STEREO; |
| 396 | mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode); | ||
| 397 | 365 | ||
| 398 | /* check if the saa7740 (aka 'sound arena module') is present | 366 | /* check if the saa7740 (aka 'sound arena module') is present |
| 399 | on the mxb. if so, we must initialize it. due to lack of | 367 | on the mxb. if so, we must initialize it. due to lack of |
| @@ -404,21 +372,22 @@ static int mxb_init_done(struct saa7146_dev* dev) | |||
| 404 | msg.len = mxb_saa7740_init[0].length; | 372 | msg.len = mxb_saa7740_init[0].length; |
| 405 | msg.buf = &mxb_saa7740_init[0].data[0]; | 373 | msg.buf = &mxb_saa7740_init[0].data[0]; |
| 406 | 374 | ||
| 407 | if( 1 == (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) { | 375 | err = i2c_transfer(&mxb->i2c_adapter, &msg, 1); |
| 376 | if (err == 1) { | ||
| 408 | /* the sound arena module is a pos, that's probably the reason | 377 | /* the sound arena module is a pos, that's probably the reason |
| 409 | philips refuses to hand out a datasheet for the saa7740... | 378 | philips refuses to hand out a datasheet for the saa7740... |
| 410 | it seems to screw up the i2c bus, so we disable fast irq | 379 | it seems to screw up the i2c bus, so we disable fast irq |
| 411 | based i2c transactions here and rely on the slow and safe | 380 | based i2c transactions here and rely on the slow and safe |
| 412 | polling method ... */ | 381 | polling method ... */ |
| 413 | extension.flags &= ~SAA7146_USE_I2C_IRQ; | 382 | extension.flags &= ~SAA7146_USE_I2C_IRQ; |
| 414 | for(i = 1;;i++) { | 383 | for (i = 1; ; i++) { |
| 415 | if( -1 == mxb_saa7740_init[i].length ) { | 384 | if (-1 == mxb_saa7740_init[i].length) |
| 416 | break; | 385 | break; |
| 417 | } | ||
| 418 | 386 | ||
| 419 | msg.len = mxb_saa7740_init[i].length; | 387 | msg.len = mxb_saa7740_init[i].length; |
| 420 | msg.buf = &mxb_saa7740_init[i].data[0]; | 388 | msg.buf = &mxb_saa7740_init[i].data[0]; |
| 421 | if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) { | 389 | err = i2c_transfer(&mxb->i2c_adapter, &msg, 1); |
| 390 | if (err != 1) { | ||
| 422 | DEB_D(("failed to initialize 'sound arena module'.\n")); | 391 | DEB_D(("failed to initialize 'sound arena module'.\n")); |
| 423 | goto err; | 392 | goto err; |
| 424 | } | 393 | } |
| @@ -432,7 +401,8 @@ err: | |||
| 432 | /* ext->saa has been filled by the core driver */ | 401 | /* ext->saa has been filled by the core driver */ |
| 433 | 402 | ||
| 434 | /* some stuff is done via variables */ | 403 | /* some stuff is done via variables */ |
| 435 | saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync); | 404 | saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, |
| 405 | input_port_selection[mxb->cur_input].hps_sync); | ||
| 436 | 406 | ||
| 437 | /* some stuff is done via direct write to the registers */ | 407 | /* some stuff is done via direct write to the registers */ |
| 438 | 408 | ||
| @@ -457,24 +427,24 @@ void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask) | |||
| 457 | static struct saa7146_ext_vv vv_data; | 427 | static struct saa7146_ext_vv vv_data; |
| 458 | 428 | ||
| 459 | /* this function only gets called when the probing was successful */ | 429 | /* this function only gets called when the probing was successful */ |
| 460 | static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) | 430 | static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) |
| 461 | { | 431 | { |
| 462 | struct mxb* mxb = (struct mxb*)dev->ext_priv; | 432 | struct mxb *mxb = (struct mxb *)dev->ext_priv; |
| 463 | 433 | ||
| 464 | DEB_EE(("dev:%p\n",dev)); | 434 | DEB_EE(("dev:%p\n", dev)); |
| 465 | 435 | ||
| 466 | /* checking for i2c-devices can be omitted here, because we | 436 | /* checking for i2c-devices can be omitted here, because we |
| 467 | already did this in "mxb_vl42_probe" */ | 437 | already did this in "mxb_vl42_probe" */ |
| 468 | 438 | ||
| 469 | saa7146_vv_init(dev,&vv_data); | 439 | saa7146_vv_init(dev, &vv_data); |
| 470 | if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { | 440 | if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { |
| 471 | ERR(("cannot register capture v4l2 device. skipping.\n")); | 441 | ERR(("cannot register capture v4l2 device. skipping.\n")); |
| 472 | return -1; | 442 | return -1; |
| 473 | } | 443 | } |
| 474 | 444 | ||
| 475 | /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ | 445 | /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ |
| 476 | if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { | 446 | if (MXB_BOARD_CAN_DO_VBI(dev)) { |
| 477 | if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { | 447 | if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { |
| 478 | ERR(("cannot register vbi v4l2 device. skipping.\n")); | 448 | ERR(("cannot register vbi v4l2 device. skipping.\n")); |
| 479 | } | 449 | } |
| 480 | } | 450 | } |
| @@ -486,18 +456,18 @@ static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data | |||
| 486 | i2c_use_client(mxb->saa7111a); | 456 | i2c_use_client(mxb->saa7111a); |
| 487 | i2c_use_client(mxb->tuner); | 457 | i2c_use_client(mxb->tuner); |
| 488 | 458 | ||
| 489 | printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num); | 459 | printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num); |
| 490 | 460 | ||
| 491 | mxb_num++; | 461 | mxb_num++; |
| 492 | mxb_init_done(dev); | 462 | mxb_init_done(dev); |
| 493 | return 0; | 463 | return 0; |
| 494 | } | 464 | } |
| 495 | 465 | ||
| 496 | static int mxb_detach(struct saa7146_dev* dev) | 466 | static int mxb_detach(struct saa7146_dev *dev) |
| 497 | { | 467 | { |
| 498 | struct mxb* mxb = (struct mxb*)dev->ext_priv; | 468 | struct mxb *mxb = (struct mxb *)dev->ext_priv; |
| 499 | 469 | ||
| 500 | DEB_EE(("dev:%p\n",dev)); | 470 | DEB_EE(("dev:%p\n", dev)); |
| 501 | 471 | ||
| 502 | i2c_release_client(mxb->tea6420_1); | 472 | i2c_release_client(mxb->tea6420_1); |
| 503 | i2c_release_client(mxb->tea6420_2); | 473 | i2c_release_client(mxb->tea6420_2); |
| @@ -507,9 +477,8 @@ static int mxb_detach(struct saa7146_dev* dev) | |||
| 507 | i2c_release_client(mxb->tuner); | 477 | i2c_release_client(mxb->tuner); |
| 508 | 478 | ||
| 509 | saa7146_unregister_device(&mxb->video_dev,dev); | 479 | saa7146_unregister_device(&mxb->video_dev,dev); |
| 510 | if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { | 480 | if (MXB_BOARD_CAN_DO_VBI(dev)) |
| 511 | saa7146_unregister_device(&mxb->vbi_dev,dev); | 481 | saa7146_unregister_device(&mxb->vbi_dev, dev); |
| 512 | } | ||
| 513 | saa7146_vv_release(dev); | 482 | saa7146_vv_release(dev); |
| 514 | 483 | ||
| 515 | mxb_num--; | 484 | mxb_num--; |
| @@ -523,7 +492,7 @@ static int mxb_detach(struct saa7146_dev* dev) | |||
| 523 | static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | 492 | static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) |
| 524 | { | 493 | { |
| 525 | struct saa7146_dev *dev = fh->dev; | 494 | struct saa7146_dev *dev = fh->dev; |
| 526 | struct mxb* mxb = (struct mxb*)dev->ext_priv; | 495 | struct mxb *mxb = (struct mxb *)dev->ext_priv; |
| 527 | struct saa7146_vv *vv = dev->vv_data; | 496 | struct saa7146_vv *vv = dev->vv_data; |
| 528 | 497 | ||
| 529 | switch(cmd) { | 498 | switch(cmd) { |
| @@ -532,11 +501,9 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
| 532 | struct v4l2_input *i = arg; | 501 | struct v4l2_input *i = arg; |
| 533 | 502 | ||
| 534 | DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); | 503 | DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index)); |
| 535 | if( i->index < 0 || i->index >= MXB_INPUTS) { | 504 | if (i->index < 0 || i->index >= MXB_INPUTS) |
| 536 | return -EINVAL; | 505 | return -EINVAL; |
| 537 | } | ||
| 538 | memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); | 506 | memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input)); |
| 539 | |||
| 540 | return 0; | 507 | return 0; |
| 541 | } | 508 | } |
| 542 | /* the saa7146 provides some controls (brightness, contrast, saturation) | 509 | /* the saa7146 provides some controls (brightness, contrast, saturation) |
| @@ -550,7 +517,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
| 550 | for (i = MAXCONTROLS - 1; i >= 0; i--) { | 517 | for (i = MAXCONTROLS - 1; i >= 0; i--) { |
| 551 | if (mxb_controls[i].id == qc->id) { | 518 | if (mxb_controls[i].id == qc->id) { |
| 552 | *qc = mxb_controls[i]; | 519 | *qc = mxb_controls[i]; |
| 553 | DEB_D(("VIDIOC_QUERYCTRL %d.\n",qc->id)); | 520 | DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id)); |
| 554 | return 0; | 521 | return 0; |
| 555 | } | 522 | } |
| 556 | } | 523 | } |
| @@ -562,56 +529,51 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
| 562 | int i; | 529 | int i; |
| 563 | 530 | ||
| 564 | for (i = MAXCONTROLS - 1; i >= 0; i--) { | 531 | for (i = MAXCONTROLS - 1; i >= 0; i--) { |
| 565 | if (mxb_controls[i].id == vc->id) { | 532 | if (mxb_controls[i].id == vc->id) |
| 566 | break; | 533 | break; |
| 567 | } | ||
| 568 | } | 534 | } |
| 569 | 535 | ||
| 570 | if( i < 0 ) { | 536 | if (i < 0) |
| 571 | return -EAGAIN; | 537 | return -EAGAIN; |
| 572 | } | ||
| 573 | 538 | ||
| 574 | switch (vc->id ) { | 539 | if (vc->id == V4L2_CID_AUDIO_MUTE) { |
| 575 | case V4L2_CID_AUDIO_MUTE: { | 540 | vc->value = mxb->cur_mute; |
| 576 | vc->value = mxb->cur_mute; | 541 | DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value)); |
| 577 | DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value)); | 542 | return 0; |
| 578 | return 0; | ||
| 579 | } | ||
| 580 | } | 543 | } |
| 581 | 544 | ||
| 582 | DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value)); | 545 | DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value)); |
| 583 | return 0; | 546 | return 0; |
| 584 | } | 547 | } |
| 585 | 548 | ||
| 586 | case VIDIOC_S_CTRL: | 549 | case VIDIOC_S_CTRL: |
| 587 | { | 550 | { |
| 588 | struct v4l2_control *vc = arg; | 551 | struct v4l2_control *vc = arg; |
| 589 | int i = 0; | 552 | int i = 0; |
| 590 | 553 | ||
| 591 | for (i = MAXCONTROLS - 1; i >= 0; i--) { | 554 | for (i = MAXCONTROLS - 1; i >= 0; i--) { |
| 592 | if (mxb_controls[i].id == vc->id) { | 555 | if (mxb_controls[i].id == vc->id) |
| 593 | break; | 556 | break; |
| 594 | } | ||
| 595 | } | 557 | } |
| 596 | 558 | ||
| 597 | if( i < 0 ) { | 559 | if (i < 0) |
| 598 | return -EAGAIN; | 560 | return -EAGAIN; |
| 599 | } | ||
| 600 | 561 | ||
| 601 | switch (vc->id ) { | 562 | if (vc->id == V4L2_CID_AUDIO_MUTE) { |
| 602 | case V4L2_CID_AUDIO_MUTE: { | 563 | mxb->cur_mute = vc->value; |
| 603 | mxb->cur_mute = vc->value; | 564 | if (!vc->value) { |
| 604 | if( 0 == vc->value ) { | 565 | /* switch the audio-source */ |
| 605 | /* switch the audio-source */ | 566 | mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, |
| 606 | mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); | 567 | &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); |
| 607 | mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); | 568 | mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, |
| 608 | } else { | 569 | &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); |
| 609 | mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]); | 570 | } else { |
| 610 | mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]); | 571 | mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, |
| 611 | } | 572 | &TEA6420_line[6][0]); |
| 612 | DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value)); | 573 | mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, |
| 613 | break; | 574 | &TEA6420_line[6][1]); |
| 614 | } | 575 | } |
| 576 | DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value)); | ||
| 615 | } | 577 | } |
| 616 | return 0; | 578 | return 0; |
| 617 | } | 579 | } |
| @@ -620,106 +582,84 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
| 620 | int *input = (int *)arg; | 582 | int *input = (int *)arg; |
| 621 | *input = mxb->cur_input; | 583 | *input = mxb->cur_input; |
| 622 | 584 | ||
| 623 | DEB_EE(("VIDIOC_G_INPUT %d.\n",*input)); | 585 | DEB_EE(("VIDIOC_G_INPUT %d.\n", *input)); |
| 624 | return 0; | 586 | return 0; |
| 625 | } | 587 | } |
| 626 | case VIDIOC_S_INPUT: | 588 | case VIDIOC_S_INPUT: |
| 627 | { | 589 | { |
| 628 | int input = *(int *)arg; | 590 | int input = *(int *)arg; |
| 629 | struct tea6415c_multiplex vm; | 591 | struct tea6415c_multiplex vm; |
| 592 | struct v4l2_routing route; | ||
| 630 | int i = 0; | 593 | int i = 0; |
| 631 | 594 | ||
| 632 | DEB_EE(("VIDIOC_S_INPUT %d.\n",input)); | 595 | DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); |
| 633 | 596 | ||
| 634 | if (input < 0 || input >= MXB_INPUTS) { | 597 | if (input < 0 || input >= MXB_INPUTS) |
| 635 | return -EINVAL; | 598 | return -EINVAL; |
| 636 | } | ||
| 637 | |||
| 638 | /* fixme: locke das setzen des inputs mit hilfe des mutexes | ||
| 639 | mutex_lock(&dev->lock); | ||
| 640 | video_mux(dev,*i); | ||
| 641 | mutex_unlock(&dev->lock); | ||
| 642 | */ | ||
| 643 | |||
| 644 | /* fixme: check if streaming capture | ||
| 645 | if ( 0 != dev->streaming ) { | ||
| 646 | DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n")); | ||
| 647 | return -EPERM; | ||
| 648 | } | ||
| 649 | */ | ||
| 650 | 599 | ||
| 651 | mxb->cur_input = input; | 600 | mxb->cur_input = input; |
| 652 | 601 | ||
| 653 | saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); | 602 | saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, |
| 603 | input_port_selection[input].hps_sync); | ||
| 654 | 604 | ||
| 655 | /* prepare switching of tea6415c and saa7111a; | 605 | /* prepare switching of tea6415c and saa7111a; |
| 656 | have a look at the 'background'-file for further informations */ | 606 | have a look at the 'background'-file for further informations */ |
| 657 | switch( input ) { | 607 | switch (input) { |
| 658 | 608 | case TUNER: | |
| 659 | case TUNER: | 609 | i = SAA7115_COMPOSITE0; |
| 660 | { | 610 | vm.in = 3; |
| 661 | i = 0; | 611 | vm.out = 17; |
| 662 | vm.in = 3; | 612 | |
| 663 | vm.out = 17; | 613 | if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { |
| 664 | 614 | printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n"); | |
| 665 | if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) { | 615 | return -EFAULT; |
| 666 | printk("VIDIOC_S_INPUT: could not address tea6415c #1\n"); | ||
| 667 | return -EFAULT; | ||
| 668 | } | ||
| 669 | /* connect tuner-output always to multicable */ | ||
| 670 | vm.in = 3; | ||
| 671 | vm.out = 13; | ||
| 672 | break; | ||
| 673 | } | ||
| 674 | case AUX3_YC: | ||
| 675 | { | ||
| 676 | /* nothing to be done here. aux3_yc is | ||
| 677 | directly connected to the saa711a */ | ||
| 678 | i = 5; | ||
| 679 | break; | ||
| 680 | } | ||
| 681 | case AUX3: | ||
| 682 | { | ||
| 683 | /* nothing to be done here. aux3 is | ||
| 684 | directly connected to the saa711a */ | ||
| 685 | i = 1; | ||
| 686 | break; | ||
| 687 | } | ||
| 688 | case AUX1: | ||
| 689 | { | ||
| 690 | i = 0; | ||
| 691 | vm.in = 1; | ||
| 692 | vm.out = 17; | ||
| 693 | break; | ||
| 694 | } | 616 | } |
| 617 | /* connect tuner-output always to multicable */ | ||
| 618 | vm.in = 3; | ||
| 619 | vm.out = 13; | ||
| 620 | break; | ||
| 621 | case AUX3_YC: | ||
| 622 | /* nothing to be done here. aux3_yc is | ||
| 623 | directly connected to the saa711a */ | ||
| 624 | i = SAA7115_SVIDEO1; | ||
| 625 | break; | ||
| 626 | case AUX3: | ||
| 627 | /* nothing to be done here. aux3 is | ||
| 628 | directly connected to the saa711a */ | ||
| 629 | i = SAA7115_COMPOSITE1; | ||
| 630 | break; | ||
| 631 | case AUX1: | ||
| 632 | i = SAA7115_COMPOSITE0; | ||
| 633 | vm.in = 1; | ||
| 634 | vm.out = 17; | ||
| 635 | break; | ||
| 695 | } | 636 | } |
| 696 | 637 | ||
| 697 | /* switch video in tea6415c only if necessary */ | 638 | /* switch video in tea6415c only if necessary */ |
| 698 | switch( input ) { | 639 | switch (input) { |
| 699 | case TUNER: | 640 | case TUNER: |
| 700 | case AUX1: | 641 | case AUX1: |
| 701 | { | 642 | if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { |
| 702 | if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) { | 643 | printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n"); |
| 703 | printk("VIDIOC_S_INPUT: could not address tea6415c #3\n"); | 644 | return -EFAULT; |
| 704 | return -EFAULT; | ||
| 705 | } | ||
| 706 | break; | ||
| 707 | } | ||
| 708 | default: | ||
| 709 | { | ||
| 710 | break; | ||
| 711 | } | 645 | } |
| 646 | break; | ||
| 647 | default: | ||
| 648 | break; | ||
| 712 | } | 649 | } |
| 713 | 650 | ||
| 714 | /* switch video in saa7111a */ | 651 | /* switch video in saa7111a */ |
| 715 | if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) { | 652 | route.input = i; |
| 653 | route.output = 0; | ||
| 654 | if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route)) | ||
| 716 | printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n"); | 655 | printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n"); |
| 717 | } | ||
| 718 | 656 | ||
| 719 | /* switch the audio-source only if necessary */ | 657 | /* switch the audio-source only if necessary */ |
| 720 | if( 0 == mxb->cur_mute ) { | 658 | if( 0 == mxb->cur_mute ) { |
| 721 | mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]); | 659 | mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, |
| 722 | mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]); | 660 | &TEA6420_line[video_audio_connect[input]][0]); |
| 661 | mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, | ||
| 662 | &TEA6420_line[video_audio_connect[input]][1]); | ||
| 723 | } | 663 | } |
| 724 | 664 | ||
| 725 | return 0; | 665 | return 0; |
| @@ -727,114 +667,44 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
| 727 | case VIDIOC_G_TUNER: | 667 | case VIDIOC_G_TUNER: |
| 728 | { | 668 | { |
| 729 | struct v4l2_tuner *t = arg; | 669 | struct v4l2_tuner *t = arg; |
| 730 | int byte = 0; | ||
| 731 | 670 | ||
| 732 | if( 0 != t->index ) { | 671 | if (t->index) { |
| 733 | DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index)); | 672 | DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index)); |
| 734 | return -EINVAL; | 673 | return -EINVAL; |
| 735 | } | 674 | } |
| 736 | 675 | ||
| 737 | DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); | 676 | DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); |
| 738 | 677 | ||
| 739 | memset(t,0,sizeof(*t)); | 678 | memset(t, 0, sizeof(*t)); |
| 740 | strcpy(t->name, "Television"); | 679 | i2c_clients_command(&mxb->i2c_adapter, cmd, arg); |
| 741 | 680 | ||
| 681 | strlcpy(t->name, "TV Tuner", sizeof(t->name)); | ||
| 742 | t->type = V4L2_TUNER_ANALOG_TV; | 682 | t->type = V4L2_TUNER_ANALOG_TV; |
| 743 | t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; | 683 | t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | \ |
| 744 | t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ | 684 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; |
| 745 | t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ | ||
| 746 | /* FIXME: add the real signal strength here */ | ||
| 747 | t->signal = 0xffff; | ||
| 748 | t->afc = 0; | ||
| 749 | |||
| 750 | mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte); | ||
| 751 | t->audmode = mxb->cur_mode; | 685 | t->audmode = mxb->cur_mode; |
| 752 | |||
| 753 | if( byte < 0 ) { | ||
| 754 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
| 755 | } else { | ||
| 756 | switch(byte) { | ||
| 757 | case TDA9840_MONO_DETECT: { | ||
| 758 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
| 759 | DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n")); | ||
| 760 | break; | ||
| 761 | } | ||
| 762 | case TDA9840_DUAL_DETECT: { | ||
| 763 | t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
| 764 | DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n")); | ||
| 765 | break; | ||
| 766 | } | ||
| 767 | case TDA9840_STEREO_DETECT: { | ||
| 768 | t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; | ||
| 769 | DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n")); | ||
| 770 | break; | ||
| 771 | } | ||
| 772 | default: { /* TDA9840_INCORRECT_DETECT */ | ||
| 773 | t->rxsubchans = V4L2_TUNER_MODE_MONO; | ||
| 774 | DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n")); | ||
| 775 | break; | ||
| 776 | } | ||
| 777 | } | ||
| 778 | } | ||
| 779 | |||
| 780 | return 0; | 686 | return 0; |
| 781 | } | 687 | } |
| 782 | case VIDIOC_S_TUNER: | 688 | case VIDIOC_S_TUNER: |
| 783 | { | 689 | { |
| 784 | struct v4l2_tuner *t = arg; | 690 | struct v4l2_tuner *t = arg; |
| 785 | int result = 0; | ||
| 786 | int byte = 0; | ||
| 787 | 691 | ||
| 788 | if( 0 != t->index ) { | 692 | if (t->index) { |
| 789 | DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index)); | 693 | DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index)); |
| 790 | return -EINVAL; | 694 | return -EINVAL; |
| 791 | } | 695 | } |
| 792 | 696 | ||
| 793 | switch(t->audmode) { | 697 | mxb->cur_mode = t->audmode; |
| 794 | case V4L2_TUNER_MODE_STEREO: { | 698 | i2c_clients_command(&mxb->i2c_adapter, cmd, arg); |
| 795 | mxb->cur_mode = V4L2_TUNER_MODE_STEREO; | ||
| 796 | byte = TDA9840_SET_STEREO; | ||
| 797 | DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n")); | ||
| 798 | break; | ||
| 799 | } | ||
| 800 | case V4L2_TUNER_MODE_LANG1_LANG2: { | ||
| 801 | mxb->cur_mode = V4L2_TUNER_MODE_LANG1_LANG2; | ||
| 802 | byte = TDA9840_SET_BOTH; | ||
| 803 | DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n")); | ||
| 804 | break; | ||
| 805 | } | ||
| 806 | case V4L2_TUNER_MODE_LANG1: { | ||
| 807 | mxb->cur_mode = V4L2_TUNER_MODE_LANG1; | ||
| 808 | byte = TDA9840_SET_LANG1; | ||
| 809 | DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n")); | ||
| 810 | break; | ||
| 811 | } | ||
| 812 | case V4L2_TUNER_MODE_LANG2: { | ||
| 813 | mxb->cur_mode = V4L2_TUNER_MODE_LANG2; | ||
| 814 | byte = TDA9840_SET_LANG2; | ||
| 815 | DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n")); | ||
| 816 | break; | ||
| 817 | } | ||
| 818 | default: { /* case V4L2_TUNER_MODE_MONO: {*/ | ||
| 819 | mxb->cur_mode = V4L2_TUNER_MODE_MONO; | ||
| 820 | byte = TDA9840_SET_MONO; | ||
| 821 | DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n")); | ||
| 822 | break; | ||
| 823 | } | ||
| 824 | } | ||
| 825 | |||
| 826 | if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) { | ||
| 827 | printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte); | ||
| 828 | } | ||
| 829 | |||
| 830 | return 0; | 699 | return 0; |
| 831 | } | 700 | } |
| 832 | case VIDIOC_G_FREQUENCY: | 701 | case VIDIOC_G_FREQUENCY: |
| 833 | { | 702 | { |
| 834 | struct v4l2_frequency *f = arg; | 703 | struct v4l2_frequency *f = arg; |
| 835 | 704 | ||
| 836 | if(0 != mxb->cur_input) { | 705 | if (mxb->cur_input) { |
| 837 | DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); | 706 | DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n", |
| 707 | mxb->cur_input)); | ||
| 838 | return -EINVAL; | 708 | return -EINVAL; |
| 839 | } | 709 | } |
| 840 | 710 | ||
| @@ -847,14 +717,14 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
| 847 | { | 717 | { |
| 848 | struct v4l2_frequency *f = arg; | 718 | struct v4l2_frequency *f = arg; |
| 849 | 719 | ||
| 850 | if (0 != f->tuner) | 720 | if (f->tuner) |
| 851 | return -EINVAL; | 721 | return -EINVAL; |
| 852 | 722 | ||
| 853 | if (V4L2_TUNER_ANALOG_TV != f->type) | 723 | if (V4L2_TUNER_ANALOG_TV != f->type) |
| 854 | return -EINVAL; | 724 | return -EINVAL; |
| 855 | 725 | ||
| 856 | if(0 != mxb->cur_input) { | 726 | if (mxb->cur_input) { |
| 857 | DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input)); | 727 | DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input)); |
| 858 | return -EINVAL; | 728 | return -EINVAL; |
| 859 | } | 729 | } |
| 860 | 730 | ||
| @@ -875,7 +745,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
| 875 | { | 745 | { |
| 876 | int i = *(int*)arg; | 746 | int i = *(int*)arg; |
| 877 | 747 | ||
| 878 | if( i < 0 || i >= MXB_AUDIOS ) { | 748 | if (i < 0 || i >= MXB_AUDIOS) { |
| 879 | DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i)); | 749 | DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i)); |
| 880 | return -EINVAL; | 750 | return -EINVAL; |
| 881 | } | 751 | } |
| @@ -891,7 +761,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
| 891 | { | 761 | { |
| 892 | int i = *(int*)arg; | 762 | int i = *(int*)arg; |
| 893 | 763 | ||
| 894 | if( i < 0 || i >= MXB_AUDIOS ) { | 764 | if (i < 0 || i >= MXB_AUDIOS) { |
| 895 | DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i)); | 765 | DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i)); |
| 896 | return -EINVAL; | 766 | return -EINVAL; |
| 897 | } | 767 | } |
| @@ -906,12 +776,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
| 906 | { | 776 | { |
| 907 | struct v4l2_audio *a = arg; | 777 | struct v4l2_audio *a = arg; |
| 908 | 778 | ||
| 909 | if( a->index < 0 || a->index > MXB_INPUTS ) { | 779 | if (a->index < 0 || a->index > MXB_INPUTS) { |
| 910 | DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index)); | 780 | DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index)); |
| 911 | return -EINVAL; | 781 | return -EINVAL; |
| 912 | } | 782 | } |
| 913 | 783 | ||
| 914 | DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index)); | 784 | DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index)); |
| 915 | memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); | 785 | memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio)); |
| 916 | 786 | ||
| 917 | return 0; | 787 | return 0; |
| @@ -919,9 +789,16 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) | |||
| 919 | case VIDIOC_S_AUDIO: | 789 | case VIDIOC_S_AUDIO: |
| 920 | { | 790 | { |
| 921 | struct v4l2_audio *a = arg; | 791 | struct v4l2_audio *a = arg; |
| 922 | DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index)); | 792 | |
| 793 | DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index)); | ||
| 923 | return 0; | 794 | return 0; |
| 924 | } | 795 | } |
| 796 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
| 797 | case VIDIOC_DBG_S_REGISTER: | ||
| 798 | case VIDIOC_DBG_G_REGISTER: | ||
| 799 | i2c_clients_command(&mxb->i2c_adapter, cmd, arg); | ||
| 800 | return 0; | ||
| 801 | #endif | ||
| 925 | default: | 802 | default: |
| 926 | /* | 803 | /* |
| 927 | DEB2(printk("does not handle this ioctl.\n")); | 804 | DEB2(printk("does not handle this ioctl.\n")); |
| @@ -944,7 +821,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa | |||
| 944 | /* set the 7146 gpio register -- I don't know what this does exactly */ | 821 | /* set the 7146 gpio register -- I don't know what this does exactly */ |
| 945 | saa7146_write(dev, GPIO_CTRL, 0x00404050); | 822 | saa7146_write(dev, GPIO_CTRL, 0x00404050); |
| 946 | /* unset the 7111 gpio register -- I don't know what this does exactly */ | 823 | /* unset the 7111 gpio register -- I don't know what this does exactly */ |
| 947 | mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &zero); | 824 | mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &zero); |
| 948 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); | 825 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); |
| 949 | } else { | 826 | } else { |
| 950 | v4l2_std_id std = V4L2_STD_PAL_BG; | 827 | v4l2_std_id std = V4L2_STD_PAL_BG; |
| @@ -953,7 +830,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa | |||
| 953 | /* set the 7146 gpio register -- I don't know what this does exactly */ | 830 | /* set the 7146 gpio register -- I don't know what this does exactly */ |
| 954 | saa7146_write(dev, GPIO_CTRL, 0x00404050); | 831 | saa7146_write(dev, GPIO_CTRL, 0x00404050); |
| 955 | /* set the 7111 gpio register -- I don't know what this does exactly */ | 832 | /* set the 7111 gpio register -- I don't know what this does exactly */ |
| 956 | mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &one); | 833 | mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &one); |
| 957 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); | 834 | mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); |
| 958 | } | 835 | } |
| 959 | return 0; | 836 | return 0; |
| @@ -1029,7 +906,7 @@ static struct saa7146_extension extension = { | |||
| 1029 | 906 | ||
| 1030 | static int __init mxb_init_module(void) | 907 | static int __init mxb_init_module(void) |
| 1031 | { | 908 | { |
| 1032 | if( 0 != saa7146_register_extension(&extension)) { | 909 | if (saa7146_register_extension(&extension)) { |
| 1033 | DEB_S(("failed to register extension.\n")); | 910 | DEB_S(("failed to register extension.\n")); |
| 1034 | return -ENODEV; | 911 | return -ENODEV; |
| 1035 | } | 912 | } |
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index c6852402c5e9..935d73de57bd 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c | |||
| @@ -974,14 +974,14 @@ dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn) | |||
| 974 | 974 | ||
| 975 | for (i = reg1; i <= regn; i++) { | 975 | for (i = reg1; i <= regn; i++) { |
| 976 | rc = i2c_r(ov, i); | 976 | rc = i2c_r(ov, i); |
| 977 | info("Sensor[0x%02X] = 0x%02X", i, rc); | 977 | dev_info(&ov->dev->dev, "Sensor[0x%02X] = 0x%02X\n", i, rc); |
| 978 | } | 978 | } |
| 979 | } | 979 | } |
| 980 | 980 | ||
| 981 | static void | 981 | static void |
| 982 | dump_i2c_regs(struct usb_ov511 *ov) | 982 | dump_i2c_regs(struct usb_ov511 *ov) |
| 983 | { | 983 | { |
| 984 | info("I2C REGS"); | 984 | dev_info(&ov->dev->dev, "I2C REGS\n"); |
| 985 | dump_i2c_range(ov, 0x00, 0x7C); | 985 | dump_i2c_range(ov, 0x00, 0x7C); |
| 986 | } | 986 | } |
| 987 | 987 | ||
| @@ -992,28 +992,28 @@ dump_reg_range(struct usb_ov511 *ov, int reg1, int regn) | |||
| 992 | 992 | ||
| 993 | for (i = reg1; i <= regn; i++) { | 993 | for (i = reg1; i <= regn; i++) { |
| 994 | rc = reg_r(ov, i); | 994 | rc = reg_r(ov, i); |
| 995 | info("OV511[0x%02X] = 0x%02X", i, rc); | 995 | dev_info(&ov->dev->dev, "OV511[0x%02X] = 0x%02X\n", i, rc); |
| 996 | } | 996 | } |
| 997 | } | 997 | } |
| 998 | 998 | ||
| 999 | static void | 999 | static void |
| 1000 | ov511_dump_regs(struct usb_ov511 *ov) | 1000 | ov511_dump_regs(struct usb_ov511 *ov) |
| 1001 | { | 1001 | { |
| 1002 | info("CAMERA INTERFACE REGS"); | 1002 | dev_info(&ov->dev->dev, "CAMERA INTERFACE REGS\n"); |
| 1003 | dump_reg_range(ov, 0x10, 0x1f); | 1003 | dump_reg_range(ov, 0x10, 0x1f); |
| 1004 | info("DRAM INTERFACE REGS"); | 1004 | dev_info(&ov->dev->dev, "DRAM INTERFACE REGS\n"); |
| 1005 | dump_reg_range(ov, 0x20, 0x23); | 1005 | dump_reg_range(ov, 0x20, 0x23); |
| 1006 | info("ISO FIFO REGS"); | 1006 | dev_info(&ov->dev->dev, "ISO FIFO REGS\n"); |
| 1007 | dump_reg_range(ov, 0x30, 0x31); | 1007 | dump_reg_range(ov, 0x30, 0x31); |
| 1008 | info("PIO REGS"); | 1008 | dev_info(&ov->dev->dev, "PIO REGS\n"); |
| 1009 | dump_reg_range(ov, 0x38, 0x39); | 1009 | dump_reg_range(ov, 0x38, 0x39); |
| 1010 | dump_reg_range(ov, 0x3e, 0x3e); | 1010 | dump_reg_range(ov, 0x3e, 0x3e); |
| 1011 | info("I2C REGS"); | 1011 | dev_info(&ov->dev->dev, "I2C REGS\n"); |
| 1012 | dump_reg_range(ov, 0x40, 0x49); | 1012 | dump_reg_range(ov, 0x40, 0x49); |
| 1013 | info("SYSTEM CONTROL REGS"); | 1013 | dev_info(&ov->dev->dev, "SYSTEM CONTROL REGS\n"); |
| 1014 | dump_reg_range(ov, 0x50, 0x55); | 1014 | dump_reg_range(ov, 0x50, 0x55); |
| 1015 | dump_reg_range(ov, 0x5e, 0x5f); | 1015 | dump_reg_range(ov, 0x5e, 0x5f); |
| 1016 | info("OmniCE REGS"); | 1016 | dev_info(&ov->dev->dev, "OmniCE REGS\n"); |
| 1017 | dump_reg_range(ov, 0x70, 0x79); | 1017 | dump_reg_range(ov, 0x70, 0x79); |
| 1018 | /* NOTE: Quantization tables are not readable. You will get the value | 1018 | /* NOTE: Quantization tables are not readable. You will get the value |
| 1019 | * in reg. 0x79 for every table register */ | 1019 | * in reg. 0x79 for every table register */ |
| @@ -1025,25 +1025,25 @@ ov511_dump_regs(struct usb_ov511 *ov) | |||
| 1025 | static void | 1025 | static void |
| 1026 | ov518_dump_regs(struct usb_ov511 *ov) | 1026 | ov518_dump_regs(struct usb_ov511 *ov) |
| 1027 | { | 1027 | { |
| 1028 | info("VIDEO MODE REGS"); | 1028 | dev_info(&ov->dev->dev, "VIDEO MODE REGS\n"); |
| 1029 | dump_reg_range(ov, 0x20, 0x2f); | 1029 | dump_reg_range(ov, 0x20, 0x2f); |
| 1030 | info("DATA PUMP AND SNAPSHOT REGS"); | 1030 | dev_info(&ov->dev->dev, "DATA PUMP AND SNAPSHOT REGS\n"); |
| 1031 | dump_reg_range(ov, 0x30, 0x3f); | 1031 | dump_reg_range(ov, 0x30, 0x3f); |
| 1032 | info("I2C REGS"); | 1032 | dev_info(&ov->dev->dev, "I2C REGS\n"); |
| 1033 | dump_reg_range(ov, 0x40, 0x4f); | 1033 | dump_reg_range(ov, 0x40, 0x4f); |
| 1034 | info("SYSTEM CONTROL AND VENDOR REGS"); | 1034 | dev_info(&ov->dev->dev, "SYSTEM CONTROL AND VENDOR REGS\n"); |
| 1035 | dump_reg_range(ov, 0x50, 0x5f); | 1035 | dump_reg_range(ov, 0x50, 0x5f); |
| 1036 | info("60 - 6F"); | 1036 | dev_info(&ov->dev->dev, "60 - 6F\n"); |
| 1037 | dump_reg_range(ov, 0x60, 0x6f); | 1037 | dump_reg_range(ov, 0x60, 0x6f); |
| 1038 | info("70 - 7F"); | 1038 | dev_info(&ov->dev->dev, "70 - 7F\n"); |
| 1039 | dump_reg_range(ov, 0x70, 0x7f); | 1039 | dump_reg_range(ov, 0x70, 0x7f); |
| 1040 | info("Y QUANTIZATION TABLE"); | 1040 | dev_info(&ov->dev->dev, "Y QUANTIZATION TABLE\n"); |
| 1041 | dump_reg_range(ov, 0x80, 0x8f); | 1041 | dump_reg_range(ov, 0x80, 0x8f); |
| 1042 | info("UV QUANTIZATION TABLE"); | 1042 | dev_info(&ov->dev->dev, "UV QUANTIZATION TABLE\n"); |
| 1043 | dump_reg_range(ov, 0x90, 0x9f); | 1043 | dump_reg_range(ov, 0x90, 0x9f); |
| 1044 | info("A0 - BF"); | 1044 | dev_info(&ov->dev->dev, "A0 - BF\n"); |
| 1045 | dump_reg_range(ov, 0xa0, 0xbf); | 1045 | dump_reg_range(ov, 0xa0, 0xbf); |
| 1046 | info("CBR"); | 1046 | dev_info(&ov->dev->dev, "CBR\n"); |
| 1047 | dump_reg_range(ov, 0xc0, 0xcf); | 1047 | dump_reg_range(ov, 0xc0, 0xcf); |
| 1048 | } | 1048 | } |
| 1049 | #endif | 1049 | #endif |
| @@ -3205,9 +3205,10 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n) | |||
| 3205 | */ | 3205 | */ |
| 3206 | 3206 | ||
| 3207 | if (printph) { | 3207 | if (printph) { |
| 3208 | info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", | 3208 | dev_info(&ov->dev->dev, |
| 3209 | pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6], | 3209 | "ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", |
| 3210 | in[7], in[8], in[9], in[10], in[11]); | 3210 | pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6], |
| 3211 | in[7], in[8], in[9], in[10], in[11]); | ||
| 3211 | } | 3212 | } |
| 3212 | 3213 | ||
| 3213 | /* Check for SOF/EOF packet */ | 3214 | /* Check for SOF/EOF packet */ |
| @@ -3366,8 +3367,10 @@ ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n) | |||
| 3366 | * the definitive SOF/EOF format */ | 3367 | * the definitive SOF/EOF format */ |
| 3367 | if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) { | 3368 | if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) { |
| 3368 | if (printph) { | 3369 | if (printph) { |
| 3369 | info("ph: %2x %2x %2x %2x %2x %2x %2x %2x", in[0], | 3370 | dev_info(&ov->dev->dev, |
| 3370 | in[1], in[2], in[3], in[4], in[5], in[6], in[7]); | 3371 | "ph: %2x %2x %2x %2x %2x %2x %2x %2x\n", |
| 3372 | in[0], in[1], in[2], in[3], in[4], in[5], | ||
| 3373 | in[6], in[7]); | ||
| 3371 | } | 3374 | } |
| 3372 | 3375 | ||
| 3373 | if (frame->scanstate == STATE_LINES) { | 3376 | if (frame->scanstate == STATE_LINES) { |
| @@ -3646,14 +3649,16 @@ ov51x_init_isoc(struct usb_ov511 *ov) | |||
| 3646 | if (packetsize == -1) { | 3649 | if (packetsize == -1) { |
| 3647 | ov518_set_packet_size(ov, 640); | 3650 | ov518_set_packet_size(ov, 640); |
| 3648 | } else { | 3651 | } else { |
| 3649 | info("Forcing packet size to %d", packetsize); | 3652 | dev_info(&ov->dev->dev, "Forcing packet size to %d\n", |
| 3653 | packetsize); | ||
| 3650 | ov518_set_packet_size(ov, packetsize); | 3654 | ov518_set_packet_size(ov, packetsize); |
| 3651 | } | 3655 | } |
| 3652 | } else { | 3656 | } else { |
| 3653 | if (packetsize == -1) { | 3657 | if (packetsize == -1) { |
| 3654 | ov511_set_packet_size(ov, size); | 3658 | ov511_set_packet_size(ov, size); |
| 3655 | } else { | 3659 | } else { |
| 3656 | info("Forcing packet size to %d", packetsize); | 3660 | dev_info(&ov->dev->dev, "Forcing packet size to %d\n", |
| 3661 | packetsize); | ||
| 3657 | ov511_set_packet_size(ov, packetsize); | 3662 | ov511_set_packet_size(ov, packetsize); |
| 3658 | } | 3663 | } |
| 3659 | } | 3664 | } |
| @@ -4121,7 +4126,7 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file, | |||
| 4121 | return -EIO; | 4126 | return -EIO; |
| 4122 | 4127 | ||
| 4123 | if (force_palette && p->palette != force_palette) { | 4128 | if (force_palette && p->palette != force_palette) { |
| 4124 | info("Palette rejected (%s)", | 4129 | dev_info(&ov->dev->dev, "Palette rejected (%s)\n", |
| 4125 | symbolic(v4l1_plist, p->palette)); | 4130 | symbolic(v4l1_plist, p->palette)); |
| 4126 | return -EINVAL; | 4131 | return -EINVAL; |
| 4127 | } | 4132 | } |
| @@ -4849,26 +4854,27 @@ ov7xx0_configure(struct usb_ov511 *ov) | |||
| 4849 | err("Error detecting sensor type"); | 4854 | err("Error detecting sensor type"); |
| 4850 | return -1; | 4855 | return -1; |
| 4851 | } else if ((rc & 3) == 3) { | 4856 | } else if ((rc & 3) == 3) { |
| 4852 | info("Sensor is an OV7610"); | 4857 | dev_info(&ov->dev->dev, "Sensor is an OV7610\n"); |
| 4853 | ov->sensor = SEN_OV7610; | 4858 | ov->sensor = SEN_OV7610; |
| 4854 | } else if ((rc & 3) == 1) { | 4859 | } else if ((rc & 3) == 1) { |
| 4855 | /* I don't know what's different about the 76BE yet. */ | 4860 | /* I don't know what's different about the 76BE yet. */ |
| 4856 | if (i2c_r(ov, 0x15) & 1) | 4861 | if (i2c_r(ov, 0x15) & 1) |
| 4857 | info("Sensor is an OV7620AE"); | 4862 | dev_info(&ov->dev->dev, "Sensor is an OV7620AE\n"); |
| 4858 | else | 4863 | else |
| 4859 | info("Sensor is an OV76BE"); | 4864 | dev_info(&ov->dev->dev, "Sensor is an OV76BE\n"); |
| 4860 | 4865 | ||
| 4861 | /* OV511+ will return all zero isoc data unless we | 4866 | /* OV511+ will return all zero isoc data unless we |
| 4862 | * configure the sensor as a 7620. Someone needs to | 4867 | * configure the sensor as a 7620. Someone needs to |
| 4863 | * find the exact reg. setting that causes this. */ | 4868 | * find the exact reg. setting that causes this. */ |
| 4864 | if (ov->bridge == BRG_OV511PLUS) { | 4869 | if (ov->bridge == BRG_OV511PLUS) { |
| 4865 | info("Enabling 511+/7620AE workaround"); | 4870 | dev_info(&ov->dev->dev, |
| 4871 | "Enabling 511+/7620AE workaround\n"); | ||
| 4866 | ov->sensor = SEN_OV7620; | 4872 | ov->sensor = SEN_OV7620; |
| 4867 | } else { | 4873 | } else { |
| 4868 | ov->sensor = SEN_OV76BE; | 4874 | ov->sensor = SEN_OV76BE; |
| 4869 | } | 4875 | } |
| 4870 | } else if ((rc & 3) == 0) { | 4876 | } else if ((rc & 3) == 0) { |
| 4871 | info("Sensor is an OV7620"); | 4877 | dev_info(&ov->dev->dev, "Sensor is an OV7620\n"); |
| 4872 | ov->sensor = SEN_OV7620; | 4878 | ov->sensor = SEN_OV7620; |
| 4873 | } else { | 4879 | } else { |
| 4874 | err("Unknown image sensor version: %d", rc & 3); | 4880 | err("Unknown image sensor version: %d", rc & 3); |
| @@ -5024,16 +5030,16 @@ ov6xx0_configure(struct usb_ov511 *ov) | |||
| 5024 | 5030 | ||
| 5025 | if ((rc & 3) == 0) { | 5031 | if ((rc & 3) == 0) { |
| 5026 | ov->sensor = SEN_OV6630; | 5032 | ov->sensor = SEN_OV6630; |
| 5027 | info("Sensor is an OV6630"); | 5033 | dev_info(&ov->dev->dev, "Sensor is an OV6630\n"); |
| 5028 | } else if ((rc & 3) == 1) { | 5034 | } else if ((rc & 3) == 1) { |
| 5029 | ov->sensor = SEN_OV6620; | 5035 | ov->sensor = SEN_OV6620; |
| 5030 | info("Sensor is an OV6620"); | 5036 | dev_info(&ov->dev->dev, "Sensor is an OV6620\n"); |
| 5031 | } else if ((rc & 3) == 2) { | 5037 | } else if ((rc & 3) == 2) { |
| 5032 | ov->sensor = SEN_OV6630; | 5038 | ov->sensor = SEN_OV6630; |
| 5033 | info("Sensor is an OV6630AE"); | 5039 | dev_info(&ov->dev->dev, "Sensor is an OV6630AE\n"); |
| 5034 | } else if ((rc & 3) == 3) { | 5040 | } else if ((rc & 3) == 3) { |
| 5035 | ov->sensor = SEN_OV6630; | 5041 | ov->sensor = SEN_OV6630; |
| 5036 | info("Sensor is an OV6630AF"); | 5042 | dev_info(&ov->dev->dev, "Sensor is an OV6630AF\n"); |
| 5037 | } | 5043 | } |
| 5038 | 5044 | ||
| 5039 | /* Set sensor-specific vars */ | 5045 | /* Set sensor-specific vars */ |
| @@ -5088,10 +5094,10 @@ ks0127_configure(struct usb_ov511 *ov) | |||
| 5088 | err("Error detecting sensor type"); | 5094 | err("Error detecting sensor type"); |
| 5089 | return -1; | 5095 | return -1; |
| 5090 | } else if ((rc & 0x0f) == 0) { | 5096 | } else if ((rc & 0x0f) == 0) { |
| 5091 | info("Sensor is a KS0127"); | 5097 | dev_info(&ov->dev->dev, "Sensor is a KS0127\n"); |
| 5092 | ov->sensor = SEN_KS0127; | 5098 | ov->sensor = SEN_KS0127; |
| 5093 | } else if ((rc & 0x0f) == 9) { | 5099 | } else if ((rc & 0x0f) == 9) { |
| 5094 | info("Sensor is a KS0127B Rev. A"); | 5100 | dev_info(&ov->dev->dev, "Sensor is a KS0127B Rev. A\n"); |
| 5095 | ov->sensor = SEN_KS0127B; | 5101 | ov->sensor = SEN_KS0127B; |
| 5096 | } | 5102 | } |
| 5097 | } else { | 5103 | } else { |
| @@ -5200,7 +5206,8 @@ saa7111a_configure(struct usb_ov511 *ov) | |||
| 5200 | err("Error detecting sensor version"); | 5206 | err("Error detecting sensor version"); |
| 5201 | return -1; | 5207 | return -1; |
| 5202 | } else { | 5208 | } else { |
| 5203 | info("Sensor is an SAA7111A (version 0x%x)", rc); | 5209 | dev_info(&ov->dev->dev, |
| 5210 | "Sensor is an SAA7111A (version 0x%x)\n", rc); | ||
| 5204 | ov->sensor = SEN_SAA7111A; | 5211 | ov->sensor = SEN_SAA7111A; |
| 5205 | } | 5212 | } |
| 5206 | 5213 | ||
| @@ -5262,7 +5269,7 @@ ov511_configure(struct usb_ov511 *ov) | |||
| 5262 | 5269 | ||
| 5263 | PDEBUG (1, "CustomID = %d", ov->customid); | 5270 | PDEBUG (1, "CustomID = %d", ov->customid); |
| 5264 | ov->desc = symbolic(camlist, ov->customid); | 5271 | ov->desc = symbolic(camlist, ov->customid); |
| 5265 | info("model: %s", ov->desc); | 5272 | dev_info(&ov->dev->dev, "model: %s\n", ov->desc); |
| 5266 | 5273 | ||
| 5267 | if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) { | 5274 | if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) { |
| 5268 | err("Camera type (%d) not recognized", ov->customid); | 5275 | err("Camera type (%d) not recognized", ov->customid); |
| @@ -5426,7 +5433,8 @@ ov518_configure(struct usb_ov511 *ov) | |||
| 5426 | PDEBUG(4, ""); | 5433 | PDEBUG(4, ""); |
| 5427 | 5434 | ||
| 5428 | /* First 5 bits of custom ID reg are a revision ID on OV518 */ | 5435 | /* First 5 bits of custom ID reg are a revision ID on OV518 */ |
| 5429 | info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID)); | 5436 | dev_info(&ov->dev->dev, "Device revision %d\n", |
| 5437 | 0x1F & reg_r(ov, R511_SYS_CUST_ID)); | ||
| 5430 | 5438 | ||
| 5431 | /* Give it the default description */ | 5439 | /* Give it the default description */ |
| 5432 | ov->desc = symbolic(camlist, 0); | 5440 | ov->desc = symbolic(camlist, 0); |
| @@ -5773,7 +5781,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
| 5773 | goto error; | 5781 | goto error; |
| 5774 | } | 5782 | } |
| 5775 | 5783 | ||
| 5776 | info("USB %s video device found", symbolic(brglist, ov->bridge)); | 5784 | dev_info(&intf->dev, "USB %s video device found\n", |
| 5785 | symbolic(brglist, ov->bridge)); | ||
| 5777 | 5786 | ||
| 5778 | init_waitqueue_head(&ov->wq); | 5787 | init_waitqueue_head(&ov->wq); |
| 5779 | 5788 | ||
| @@ -5854,8 +5863,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
| 5854 | goto error; | 5863 | goto error; |
| 5855 | } | 5864 | } |
| 5856 | 5865 | ||
| 5857 | info("Device at %s registered to minor %d", ov->usb_path, | 5866 | dev_info(&intf->dev, "Device at %s registered to minor %d\n", |
| 5858 | ov->vdev->minor); | 5867 | ov->usb_path, ov->vdev->minor); |
| 5859 | 5868 | ||
| 5860 | usb_set_intfdata(intf, ov); | 5869 | usb_set_intfdata(intf, ov); |
| 5861 | if (ov_create_sysfs(ov->vdev)) { | 5870 | if (ov_create_sysfs(ov->vdev)) { |
| @@ -5958,7 +5967,8 @@ usb_ov511_init(void) | |||
| 5958 | if (retval) | 5967 | if (retval) |
| 5959 | goto out; | 5968 | goto out; |
| 5960 | 5969 | ||
| 5961 | info(DRIVER_VERSION " : " DRIVER_DESC); | 5970 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
| 5971 | DRIVER_DESC "\n"); | ||
| 5962 | 5972 | ||
| 5963 | out: | 5973 | out: |
| 5964 | return retval; | 5974 | return retval; |
| @@ -5968,8 +5978,7 @@ static void __exit | |||
| 5968 | usb_ov511_exit(void) | 5978 | usb_ov511_exit(void) |
| 5969 | { | 5979 | { |
| 5970 | usb_deregister(&ov511_driver); | 5980 | usb_deregister(&ov511_driver); |
| 5971 | info("driver deregistered"); | 5981 | printk(KERN_INFO KBUILD_MODNAME ": driver deregistered\n"); |
| 5972 | |||
| 5973 | } | 5982 | } |
| 5974 | 5983 | ||
| 5975 | module_init(usb_ov511_init); | 5984 | module_init(usb_ov511_init); |
diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h index baded1262ca9..70d99e52329d 100644 --- a/drivers/media/video/ov511.h +++ b/drivers/media/video/ov511.h | |||
| @@ -12,7 +12,8 @@ | |||
| 12 | 12 | ||
| 13 | #ifdef OV511_DEBUG | 13 | #ifdef OV511_DEBUG |
| 14 | #define PDEBUG(level, fmt, args...) \ | 14 | #define PDEBUG(level, fmt, args...) \ |
| 15 | if (debug >= (level)) info("[%s:%d] " fmt, \ | 15 | if (debug >= (level)) \ |
| 16 | printk(KERN_INFO KBUILD_MODNAME "[%s:%d] \n" fmt, \ | ||
| 16 | __func__, __LINE__ , ## args) | 17 | __func__, __LINE__ , ## args) |
| 17 | #else | 18 | #else |
| 18 | #define PDEBUG(level, fmt, args...) do {} while(0) | 19 | #define PDEBUG(level, fmt, args...) do {} while(0) |
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c index 065c2454113e..2c4acbf5a4fe 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/drivers/media/video/ovcamchip/ovcamchip_core.c | |||
| @@ -49,12 +49,6 @@ MODULE_LICENSE("GPL"); | |||
| 49 | #define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */ | 49 | #define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */ |
| 50 | #define GENERIC_REG_COM_I 0x29 /* misc ID bits */ | 50 | #define GENERIC_REG_COM_I 0x29 /* misc ID bits */ |
| 51 | 51 | ||
| 52 | extern struct ovcamchip_ops ov6x20_ops; | ||
| 53 | extern struct ovcamchip_ops ov6x30_ops; | ||
| 54 | extern struct ovcamchip_ops ov7x10_ops; | ||
| 55 | extern struct ovcamchip_ops ov7x20_ops; | ||
| 56 | extern struct ovcamchip_ops ov76be_ops; | ||
| 57 | |||
| 58 | static char *chip_names[NUM_CC_TYPES] = { | 52 | static char *chip_names[NUM_CC_TYPES] = { |
| 59 | [CC_UNKNOWN] = "Unknown chip", | 53 | [CC_UNKNOWN] = "Unknown chip", |
| 60 | [CC_OV76BE] = "OV76BE", | 54 | [CC_OV76BE] = "OV76BE", |
diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h index 9afa4fe47726..a05650faedda 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_priv.h +++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h | |||
| @@ -53,6 +53,12 @@ struct ovcamchip { | |||
| 53 | int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */ | 53 | int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */ |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | extern struct ovcamchip_ops ov6x20_ops; | ||
| 57 | extern struct ovcamchip_ops ov6x30_ops; | ||
| 58 | extern struct ovcamchip_ops ov7x10_ops; | ||
| 59 | extern struct ovcamchip_ops ov7x20_ops; | ||
| 60 | extern struct ovcamchip_ops ov76be_ops; | ||
| 61 | |||
| 56 | /* --------------------------------- */ | 62 | /* --------------------------------- */ |
| 57 | /* I2C I/O */ | 63 | /* I2C I/O */ |
| 58 | /* --------------------------------- */ | 64 | /* --------------------------------- */ |
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 7c84f795db54..994807818aa2 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c | |||
| @@ -47,6 +47,7 @@ struct pms_device | |||
| 47 | struct video_picture picture; | 47 | struct video_picture picture; |
| 48 | int height; | 48 | int height; |
| 49 | int width; | 49 | int width; |
| 50 | unsigned long in_use; | ||
| 50 | struct mutex lock; | 51 | struct mutex lock; |
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| @@ -881,10 +882,27 @@ static ssize_t pms_read(struct file *file, char __user *buf, | |||
| 881 | return len; | 882 | return len; |
| 882 | } | 883 | } |
| 883 | 884 | ||
| 885 | static int pms_exclusive_open(struct inode *inode, struct file *file) | ||
| 886 | { | ||
| 887 | struct video_device *v = video_devdata(file); | ||
| 888 | struct pms_device *pd = (struct pms_device *)v; | ||
| 889 | |||
| 890 | return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0; | ||
| 891 | } | ||
| 892 | |||
| 893 | static int pms_exclusive_release(struct inode *inode, struct file *file) | ||
| 894 | { | ||
| 895 | struct video_device *v = video_devdata(file); | ||
| 896 | struct pms_device *pd = (struct pms_device *)v; | ||
| 897 | |||
| 898 | clear_bit(0, &pd->in_use); | ||
| 899 | return 0; | ||
| 900 | } | ||
| 901 | |||
| 884 | static const struct file_operations pms_fops = { | 902 | static const struct file_operations pms_fops = { |
| 885 | .owner = THIS_MODULE, | 903 | .owner = THIS_MODULE, |
| 886 | .open = video_exclusive_open, | 904 | .open = pms_exclusive_open, |
| 887 | .release = video_exclusive_release, | 905 | .release = pms_exclusive_release, |
| 888 | .ioctl = pms_ioctl, | 906 | .ioctl = pms_ioctl, |
| 889 | #ifdef CONFIG_COMPAT | 907 | #ifdef CONFIG_COMPAT |
| 890 | .compat_ioctl = v4l_compat_ioctl32, | 908 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -897,6 +915,7 @@ static struct video_device pms_template= | |||
| 897 | { | 915 | { |
| 898 | .name = "Mediavision PMS", | 916 | .name = "Mediavision PMS", |
| 899 | .fops = &pms_fops, | 917 | .fops = &pms_fops, |
| 918 | .release = video_device_release_empty, | ||
| 900 | }; | 919 | }; |
| 901 | 920 | ||
| 902 | static struct pms_device pms_device; | 921 | static struct pms_device pms_device; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index 0764fbfffb73..203f54cd18a1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c | |||
| @@ -134,13 +134,17 @@ int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr) | |||
| 134 | 134 | ||
| 135 | 135 | ||
| 136 | /* Retrieve control's default value (any type) */ | 136 | /* Retrieve control's default value (any type) */ |
| 137 | int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr) | 137 | int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr) |
| 138 | { | 138 | { |
| 139 | int ret = 0; | 139 | int ret = 0; |
| 140 | if (!cptr) return 0; | 140 | if (!cptr) return 0; |
| 141 | LOCK_TAKE(cptr->hdw->big_lock); do { | 141 | LOCK_TAKE(cptr->hdw->big_lock); do { |
| 142 | if (cptr->info->type == pvr2_ctl_int) { | 142 | if (cptr->info->type == pvr2_ctl_int) { |
| 143 | ret = cptr->info->default_value; | 143 | if (cptr->info->get_def_value) { |
| 144 | ret = cptr->info->get_def_value(cptr, valptr); | ||
| 145 | } else { | ||
| 146 | *valptr = cptr->info->default_value; | ||
| 147 | } | ||
| 144 | } | 148 | } |
| 145 | } while(0); LOCK_GIVE(cptr->hdw->big_lock); | 149 | } while(0); LOCK_GIVE(cptr->hdw->big_lock); |
| 146 | return ret; | 150 | return ret; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h index 0371ae6e6e4e..794ff90121c7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h | |||
| @@ -49,7 +49,7 @@ int pvr2_ctrl_get_max(struct pvr2_ctrl *); | |||
| 49 | int pvr2_ctrl_get_min(struct pvr2_ctrl *); | 49 | int pvr2_ctrl_get_min(struct pvr2_ctrl *); |
| 50 | 50 | ||
| 51 | /* Retrieve control's default value (any type) */ | 51 | /* Retrieve control's default value (any type) */ |
| 52 | int pvr2_ctrl_get_def(struct pvr2_ctrl *); | 52 | int pvr2_ctrl_get_def(struct pvr2_ctrl *, int *valptr); |
| 53 | 53 | ||
| 54 | /* Retrieve control's enumeration count (enum only) */ | 54 | /* Retrieve control's enumeration count (enum only) */ |
| 55 | int pvr2_ctrl_get_cnt(struct pvr2_ctrl *); | 55 | int pvr2_ctrl_get_cnt(struct pvr2_ctrl *); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index 657f861593b3..de7ee7264be6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | |||
| @@ -82,6 +82,7 @@ struct pvr2_ctl_info { | |||
| 82 | 82 | ||
| 83 | /* Control's implementation */ | 83 | /* Control's implementation */ |
| 84 | pvr2_ctlf_get_value get_value; /* Get its value */ | 84 | pvr2_ctlf_get_value get_value; /* Get its value */ |
| 85 | pvr2_ctlf_get_value get_def_value; /* Get its default value */ | ||
| 85 | pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */ | 86 | pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */ |
| 86 | pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */ | 87 | pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */ |
| 87 | pvr2_ctlf_set_value set_value; /* Set its value */ | 88 | pvr2_ctlf_set_value set_value; /* Set its value */ |
| @@ -307,6 +308,10 @@ struct pvr2_hdw { | |||
| 307 | struct v4l2_tuner tuner_signal_info; | 308 | struct v4l2_tuner tuner_signal_info; |
| 308 | int tuner_signal_stale; | 309 | int tuner_signal_stale; |
| 309 | 310 | ||
| 311 | /* Cropping capability info */ | ||
| 312 | struct v4l2_cropcap cropcap_info; | ||
| 313 | int cropcap_stale; | ||
| 314 | |||
| 310 | /* Video standard handling */ | 315 | /* Video standard handling */ |
| 311 | v4l2_std_id std_mask_eeprom; // Hardware supported selections | 316 | v4l2_std_id std_mask_eeprom; // Hardware supported selections |
| 312 | v4l2_std_id std_mask_avail; // Which standards we may select from | 317 | v4l2_std_id std_mask_avail; // Which standards we may select from |
| @@ -367,6 +372,10 @@ struct pvr2_hdw { | |||
| 367 | VCREATE_DATA(bass); | 372 | VCREATE_DATA(bass); |
| 368 | VCREATE_DATA(treble); | 373 | VCREATE_DATA(treble); |
| 369 | VCREATE_DATA(mute); | 374 | VCREATE_DATA(mute); |
| 375 | VCREATE_DATA(cropl); | ||
| 376 | VCREATE_DATA(cropt); | ||
| 377 | VCREATE_DATA(cropw); | ||
| 378 | VCREATE_DATA(croph); | ||
| 370 | VCREATE_DATA(input); | 379 | VCREATE_DATA(input); |
| 371 | VCREATE_DATA(audiomode); | 380 | VCREATE_DATA(audiomode); |
| 372 | VCREATE_DATA(res_hor); | 381 | VCREATE_DATA(res_hor); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f051c6aa7f1f..94265bd3d926 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
| @@ -298,6 +298,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, | |||
| 298 | unsigned int timeout,int probe_fl, | 298 | unsigned int timeout,int probe_fl, |
| 299 | void *write_data,unsigned int write_len, | 299 | void *write_data,unsigned int write_len, |
| 300 | void *read_data,unsigned int read_len); | 300 | void *read_data,unsigned int read_len); |
| 301 | static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw); | ||
| 301 | 302 | ||
| 302 | 303 | ||
| 303 | static void trace_stbit(const char *name,int val) | 304 | static void trace_stbit(const char *name,int val) |
| @@ -402,6 +403,194 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) | |||
| 402 | return 0; | 403 | return 0; |
| 403 | } | 404 | } |
| 404 | 405 | ||
| 406 | static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left) | ||
| 407 | { | ||
| 408 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 409 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 410 | if (stat != 0) { | ||
| 411 | return stat; | ||
| 412 | } | ||
| 413 | *left = cap->bounds.left; | ||
| 414 | return 0; | ||
| 415 | } | ||
| 416 | |||
| 417 | static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left) | ||
| 418 | { | ||
| 419 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 420 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 421 | if (stat != 0) { | ||
| 422 | return stat; | ||
| 423 | } | ||
| 424 | *left = cap->bounds.left; | ||
| 425 | if (cap->bounds.width > cptr->hdw->cropw_val) { | ||
| 426 | *left += cap->bounds.width - cptr->hdw->cropw_val; | ||
| 427 | } | ||
| 428 | return 0; | ||
| 429 | } | ||
| 430 | |||
| 431 | static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top) | ||
| 432 | { | ||
| 433 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 434 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 435 | if (stat != 0) { | ||
| 436 | return stat; | ||
| 437 | } | ||
| 438 | *top = cap->bounds.top; | ||
| 439 | return 0; | ||
| 440 | } | ||
| 441 | |||
| 442 | static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top) | ||
| 443 | { | ||
| 444 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 445 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 446 | if (stat != 0) { | ||
| 447 | return stat; | ||
| 448 | } | ||
| 449 | *top = cap->bounds.top; | ||
| 450 | if (cap->bounds.height > cptr->hdw->croph_val) { | ||
| 451 | *top += cap->bounds.height - cptr->hdw->croph_val; | ||
| 452 | } | ||
| 453 | return 0; | ||
| 454 | } | ||
| 455 | |||
| 456 | static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *val) | ||
| 457 | { | ||
| 458 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 459 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 460 | if (stat != 0) { | ||
| 461 | return stat; | ||
| 462 | } | ||
| 463 | *val = 0; | ||
| 464 | if (cap->bounds.width > cptr->hdw->cropl_val) { | ||
| 465 | *val = cap->bounds.width - cptr->hdw->cropl_val; | ||
| 466 | } | ||
| 467 | return 0; | ||
| 468 | } | ||
| 469 | |||
| 470 | static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *val) | ||
| 471 | { | ||
| 472 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 473 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 474 | if (stat != 0) { | ||
| 475 | return stat; | ||
| 476 | } | ||
| 477 | *val = 0; | ||
| 478 | if (cap->bounds.height > cptr->hdw->cropt_val) { | ||
| 479 | *val = cap->bounds.height - cptr->hdw->cropt_val; | ||
| 480 | } | ||
| 481 | return 0; | ||
| 482 | } | ||
| 483 | |||
| 484 | static int ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val) | ||
| 485 | { | ||
| 486 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 487 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 488 | if (stat != 0) { | ||
| 489 | return stat; | ||
| 490 | } | ||
| 491 | *val = cap->bounds.left; | ||
| 492 | return 0; | ||
| 493 | } | ||
| 494 | |||
| 495 | static int ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val) | ||
| 496 | { | ||
| 497 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 498 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 499 | if (stat != 0) { | ||
| 500 | return stat; | ||
| 501 | } | ||
| 502 | *val = cap->bounds.top; | ||
| 503 | return 0; | ||
| 504 | } | ||
| 505 | |||
| 506 | static int ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val) | ||
| 507 | { | ||
| 508 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 509 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 510 | if (stat != 0) { | ||
| 511 | return stat; | ||
| 512 | } | ||
| 513 | *val = cap->bounds.width; | ||
| 514 | return 0; | ||
| 515 | } | ||
| 516 | |||
| 517 | static int ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val) | ||
| 518 | { | ||
| 519 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 520 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 521 | if (stat != 0) { | ||
| 522 | return stat; | ||
| 523 | } | ||
| 524 | *val = cap->bounds.height; | ||
| 525 | return 0; | ||
| 526 | } | ||
| 527 | |||
| 528 | static int ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val) | ||
| 529 | { | ||
| 530 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 531 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 532 | if (stat != 0) { | ||
| 533 | return stat; | ||
| 534 | } | ||
| 535 | *val = cap->defrect.left; | ||
| 536 | return 0; | ||
| 537 | } | ||
| 538 | |||
| 539 | static int ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val) | ||
| 540 | { | ||
| 541 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 542 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 543 | if (stat != 0) { | ||
| 544 | return stat; | ||
| 545 | } | ||
| 546 | *val = cap->defrect.top; | ||
| 547 | return 0; | ||
| 548 | } | ||
| 549 | |||
| 550 | static int ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val) | ||
| 551 | { | ||
| 552 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 553 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 554 | if (stat != 0) { | ||
| 555 | return stat; | ||
| 556 | } | ||
| 557 | *val = cap->defrect.width; | ||
| 558 | return 0; | ||
| 559 | } | ||
| 560 | |||
| 561 | static int ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val) | ||
| 562 | { | ||
| 563 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 564 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 565 | if (stat != 0) { | ||
| 566 | return stat; | ||
| 567 | } | ||
| 568 | *val = cap->defrect.height; | ||
| 569 | return 0; | ||
| 570 | } | ||
| 571 | |||
| 572 | static int ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val) | ||
| 573 | { | ||
| 574 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 575 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 576 | if (stat != 0) { | ||
| 577 | return stat; | ||
| 578 | } | ||
| 579 | *val = cap->pixelaspect.numerator; | ||
| 580 | return 0; | ||
| 581 | } | ||
| 582 | |||
| 583 | static int ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val) | ||
| 584 | { | ||
| 585 | struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info; | ||
| 586 | int stat = pvr2_hdw_check_cropcap(cptr->hdw); | ||
| 587 | if (stat != 0) { | ||
| 588 | return stat; | ||
| 589 | } | ||
| 590 | *val = cap->pixelaspect.denominator; | ||
| 591 | return 0; | ||
| 592 | } | ||
| 593 | |||
| 405 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) | 594 | static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp) |
| 406 | { | 595 | { |
| 407 | /* Actual maximum depends on the video standard in effect. */ | 596 | /* Actual maximum depends on the video standard in effect. */ |
| @@ -779,6 +968,10 @@ VCREATE_FUNCS(balance) | |||
| 779 | VCREATE_FUNCS(bass) | 968 | VCREATE_FUNCS(bass) |
| 780 | VCREATE_FUNCS(treble) | 969 | VCREATE_FUNCS(treble) |
| 781 | VCREATE_FUNCS(mute) | 970 | VCREATE_FUNCS(mute) |
| 971 | VCREATE_FUNCS(cropl) | ||
| 972 | VCREATE_FUNCS(cropt) | ||
| 973 | VCREATE_FUNCS(cropw) | ||
| 974 | VCREATE_FUNCS(croph) | ||
| 782 | VCREATE_FUNCS(audiomode) | 975 | VCREATE_FUNCS(audiomode) |
| 783 | VCREATE_FUNCS(res_hor) | 976 | VCREATE_FUNCS(res_hor) |
| 784 | VCREATE_FUNCS(res_ver) | 977 | VCREATE_FUNCS(res_ver) |
| @@ -849,6 +1042,72 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
| 849 | .default_value = 0, | 1042 | .default_value = 0, |
| 850 | DEFREF(mute), | 1043 | DEFREF(mute), |
| 851 | DEFBOOL, | 1044 | DEFBOOL, |
| 1045 | }, { | ||
| 1046 | .desc = "Capture crop left margin", | ||
| 1047 | .name = "crop_left", | ||
| 1048 | .internal_id = PVR2_CID_CROPL, | ||
| 1049 | .default_value = 0, | ||
| 1050 | DEFREF(cropl), | ||
| 1051 | DEFINT(-129, 340), | ||
| 1052 | .get_min_value = ctrl_cropl_min_get, | ||
| 1053 | .get_max_value = ctrl_cropl_max_get, | ||
| 1054 | .get_def_value = ctrl_get_cropcapdl, | ||
| 1055 | }, { | ||
| 1056 | .desc = "Capture crop top margin", | ||
| 1057 | .name = "crop_top", | ||
| 1058 | .internal_id = PVR2_CID_CROPT, | ||
| 1059 | .default_value = 0, | ||
| 1060 | DEFREF(cropt), | ||
| 1061 | DEFINT(-35, 544), | ||
| 1062 | .get_min_value = ctrl_cropt_min_get, | ||
| 1063 | .get_max_value = ctrl_cropt_max_get, | ||
| 1064 | .get_def_value = ctrl_get_cropcapdt, | ||
| 1065 | }, { | ||
| 1066 | .desc = "Capture crop width", | ||
| 1067 | .name = "crop_width", | ||
| 1068 | .internal_id = PVR2_CID_CROPW, | ||
| 1069 | .default_value = 720, | ||
| 1070 | DEFREF(cropw), | ||
| 1071 | .get_max_value = ctrl_cropw_max_get, | ||
| 1072 | .get_def_value = ctrl_get_cropcapdw, | ||
| 1073 | }, { | ||
| 1074 | .desc = "Capture crop height", | ||
| 1075 | .name = "crop_height", | ||
| 1076 | .internal_id = PVR2_CID_CROPH, | ||
| 1077 | .default_value = 480, | ||
| 1078 | DEFREF(croph), | ||
| 1079 | .get_max_value = ctrl_croph_max_get, | ||
| 1080 | .get_def_value = ctrl_get_cropcapdh, | ||
| 1081 | }, { | ||
| 1082 | .desc = "Capture capability pixel aspect numerator", | ||
| 1083 | .name = "cropcap_pixel_numerator", | ||
| 1084 | .internal_id = PVR2_CID_CROPCAPPAN, | ||
| 1085 | .get_value = ctrl_get_cropcappan, | ||
| 1086 | }, { | ||
| 1087 | .desc = "Capture capability pixel aspect denominator", | ||
| 1088 | .name = "cropcap_pixel_denominator", | ||
| 1089 | .internal_id = PVR2_CID_CROPCAPPAD, | ||
| 1090 | .get_value = ctrl_get_cropcappad, | ||
| 1091 | }, { | ||
| 1092 | .desc = "Capture capability bounds top", | ||
| 1093 | .name = "cropcap_bounds_top", | ||
| 1094 | .internal_id = PVR2_CID_CROPCAPBT, | ||
| 1095 | .get_value = ctrl_get_cropcapbt, | ||
| 1096 | }, { | ||
| 1097 | .desc = "Capture capability bounds left", | ||
| 1098 | .name = "cropcap_bounds_left", | ||
| 1099 | .internal_id = PVR2_CID_CROPCAPBL, | ||
| 1100 | .get_value = ctrl_get_cropcapbl, | ||
| 1101 | }, { | ||
| 1102 | .desc = "Capture capability bounds width", | ||
| 1103 | .name = "cropcap_bounds_width", | ||
| 1104 | .internal_id = PVR2_CID_CROPCAPBW, | ||
| 1105 | .get_value = ctrl_get_cropcapbw, | ||
| 1106 | }, { | ||
| 1107 | .desc = "Capture capability bounds height", | ||
| 1108 | .name = "cropcap_bounds_height", | ||
| 1109 | .internal_id = PVR2_CID_CROPCAPBH, | ||
| 1110 | .get_value = ctrl_get_cropcapbh, | ||
| 852 | },{ | 1111 | },{ |
| 853 | .desc = "Video Source", | 1112 | .desc = "Video Source", |
| 854 | .name = "input", | 1113 | .name = "input", |
| @@ -1313,9 +1572,19 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) | |||
| 1313 | if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE; | 1572 | if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE; |
| 1314 | memcpy(fw_ptr, fw_entry->data + fw_done, bcnt); | 1573 | memcpy(fw_ptr, fw_entry->data + fw_done, bcnt); |
| 1315 | /* Usbsnoop log shows that we must swap bytes... */ | 1574 | /* Usbsnoop log shows that we must swap bytes... */ |
| 1575 | /* Some background info: The data being swapped here is a | ||
| 1576 | firmware image destined for the mpeg encoder chip that | ||
| 1577 | lives at the other end of a USB endpoint. The encoder | ||
| 1578 | chip always talks in 32 bit chunks and its storage is | ||
| 1579 | organized into 32 bit words. However from the file | ||
| 1580 | system to the encoder chip everything is purely a byte | ||
| 1581 | stream. The firmware file's contents are always 32 bit | ||
| 1582 | swapped from what the encoder expects. Thus the need | ||
| 1583 | always exists to swap the bytes regardless of the endian | ||
| 1584 | type of the host processor and therefore swab32() makes | ||
| 1585 | the most sense. */ | ||
| 1316 | for (icnt = 0; icnt < bcnt/4 ; icnt++) | 1586 | for (icnt = 0; icnt < bcnt/4 ; icnt++) |
| 1317 | ((u32 *)fw_ptr)[icnt] = | 1587 | ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]); |
| 1318 | ___swab32(((u32 *)fw_ptr)[icnt]); | ||
| 1319 | 1588 | ||
| 1320 | ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt, | 1589 | ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt, |
| 1321 | &actual_length, HZ); | 1590 | &actual_length, HZ); |
| @@ -1905,7 +2174,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
| 1905 | const struct usb_device_id *devid) | 2174 | const struct usb_device_id *devid) |
| 1906 | { | 2175 | { |
| 1907 | unsigned int idx,cnt1,cnt2,m; | 2176 | unsigned int idx,cnt1,cnt2,m; |
| 1908 | struct pvr2_hdw *hdw; | 2177 | struct pvr2_hdw *hdw = NULL; |
| 1909 | int valid_std_mask; | 2178 | int valid_std_mask; |
| 1910 | struct pvr2_ctrl *cptr; | 2179 | struct pvr2_ctrl *cptr; |
| 1911 | const struct pvr2_device_desc *hdw_desc; | 2180 | const struct pvr2_device_desc *hdw_desc; |
| @@ -1915,6 +2184,16 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
| 1915 | 2184 | ||
| 1916 | hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info); | 2185 | hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info); |
| 1917 | 2186 | ||
| 2187 | if (hdw_desc == NULL) { | ||
| 2188 | pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create:" | ||
| 2189 | " No device description pointer," | ||
| 2190 | " unable to continue."); | ||
| 2191 | pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type," | ||
| 2192 | " please contact Mike Isely <isely@pobox.com>" | ||
| 2193 | " to get it included in the driver\n"); | ||
| 2194 | goto fail; | ||
| 2195 | } | ||
| 2196 | |||
| 1918 | hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); | 2197 | hdw = kzalloc(sizeof(*hdw),GFP_KERNEL); |
| 1919 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", | 2198 | pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", |
| 1920 | hdw,hdw_desc->description); | 2199 | hdw,hdw_desc->description); |
| @@ -2072,6 +2351,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
| 2072 | valid_std_mask; | 2351 | valid_std_mask; |
| 2073 | } | 2352 | } |
| 2074 | 2353 | ||
| 2354 | hdw->cropcap_stale = !0; | ||
| 2075 | hdw->eeprom_addr = -1; | 2355 | hdw->eeprom_addr = -1; |
| 2076 | hdw->unit_number = -1; | 2356 | hdw->unit_number = -1; |
| 2077 | hdw->v4l_minor_number_video = -1; | 2357 | hdw->v4l_minor_number_video = -1; |
| @@ -2508,6 +2788,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) | |||
| 2508 | /* Can't commit anything until pathway is ok. */ | 2788 | /* Can't commit anything until pathway is ok. */ |
| 2509 | return 0; | 2789 | return 0; |
| 2510 | } | 2790 | } |
| 2791 | /* The broadcast decoder can only scale down, so if | ||
| 2792 | * res_*_dirty && crop window < output format ==> enlarge crop. | ||
| 2793 | * | ||
| 2794 | * The mpeg encoder receives fields of res_hor_val dots and | ||
| 2795 | * res_ver_val halflines. Limits: hor<=720, ver<=576. | ||
| 2796 | */ | ||
| 2797 | if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) { | ||
| 2798 | hdw->cropw_val = hdw->res_hor_val; | ||
| 2799 | hdw->cropw_dirty = !0; | ||
| 2800 | } else if (hdw->cropw_dirty) { | ||
| 2801 | hdw->res_hor_dirty = !0; /* must rescale */ | ||
| 2802 | hdw->res_hor_val = min(720, hdw->cropw_val); | ||
| 2803 | } | ||
| 2804 | if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) { | ||
| 2805 | hdw->croph_val = hdw->res_ver_val; | ||
| 2806 | hdw->croph_dirty = !0; | ||
| 2807 | } else if (hdw->croph_dirty) { | ||
| 2808 | int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576; | ||
| 2809 | hdw->res_ver_dirty = !0; | ||
| 2810 | hdw->res_ver_val = min(nvres, hdw->croph_val); | ||
| 2811 | } | ||
| 2812 | |||
| 2511 | /* If any of the below has changed, then we can't do the update | 2813 | /* If any of the below has changed, then we can't do the update |
| 2512 | while the pipeline is running. Pipeline must be paused first | 2814 | while the pipeline is running. Pipeline must be paused first |
| 2513 | and decoder -> encoder connection be made quiescent before we | 2815 | and decoder -> encoder connection be made quiescent before we |
| @@ -2518,6 +2820,8 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) | |||
| 2518 | hdw->srate_dirty || | 2820 | hdw->srate_dirty || |
| 2519 | hdw->res_ver_dirty || | 2821 | hdw->res_ver_dirty || |
| 2520 | hdw->res_hor_dirty || | 2822 | hdw->res_hor_dirty || |
| 2823 | hdw->cropw_dirty || | ||
| 2824 | hdw->croph_dirty || | ||
| 2521 | hdw->input_dirty || | 2825 | hdw->input_dirty || |
| 2522 | (hdw->active_stream_type != hdw->desired_stream_type)); | 2826 | (hdw->active_stream_type != hdw->desired_stream_type)); |
| 2523 | if (disruptive_change && !hdw->state_pipeline_idle) { | 2827 | if (disruptive_change && !hdw->state_pipeline_idle) { |
| @@ -2587,6 +2891,9 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) | |||
| 2587 | } | 2891 | } |
| 2588 | 2892 | ||
| 2589 | hdw->state_pipeline_config = !0; | 2893 | hdw->state_pipeline_config = !0; |
| 2894 | /* Hardware state may have changed in a way to cause the cropping | ||
| 2895 | capabilities to have changed. So mark it stale, which will | ||
| 2896 | cause a later re-fetch. */ | ||
| 2590 | trace_stbit("state_pipeline_config",hdw->state_pipeline_config); | 2897 | trace_stbit("state_pipeline_config",hdw->state_pipeline_config); |
| 2591 | return !0; | 2898 | return !0; |
| 2592 | } | 2899 | } |
| @@ -2677,6 +2984,33 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) | |||
| 2677 | } | 2984 | } |
| 2678 | 2985 | ||
| 2679 | 2986 | ||
| 2987 | static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw) | ||
| 2988 | { | ||
| 2989 | if (!hdw->cropcap_stale) { | ||
| 2990 | return 0; | ||
| 2991 | } | ||
| 2992 | pvr2_i2c_core_status_poll(hdw); | ||
| 2993 | if (hdw->cropcap_stale) { | ||
| 2994 | return -EIO; | ||
| 2995 | } | ||
| 2996 | return 0; | ||
| 2997 | } | ||
| 2998 | |||
| 2999 | |||
| 3000 | /* Return information about cropping capabilities */ | ||
| 3001 | int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp) | ||
| 3002 | { | ||
| 3003 | int stat = 0; | ||
| 3004 | LOCK_TAKE(hdw->big_lock); | ||
| 3005 | stat = pvr2_hdw_check_cropcap(hdw); | ||
| 3006 | if (!stat) { | ||
| 3007 | memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info)); | ||
| 3008 | } | ||
| 3009 | LOCK_GIVE(hdw->big_lock); | ||
| 3010 | return stat; | ||
| 3011 | } | ||
| 3012 | |||
| 3013 | |||
| 2680 | /* Return information about the tuner */ | 3014 | /* Return information about the tuner */ |
| 2681 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) | 3015 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) |
| 2682 | { | 3016 | { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index c04956d304a7..49482d1f2b28 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
| @@ -36,6 +36,16 @@ | |||
| 36 | #define PVR2_CID_FREQUENCY 6 | 36 | #define PVR2_CID_FREQUENCY 6 |
| 37 | #define PVR2_CID_HRES 7 | 37 | #define PVR2_CID_HRES 7 |
| 38 | #define PVR2_CID_VRES 8 | 38 | #define PVR2_CID_VRES 8 |
| 39 | #define PVR2_CID_CROPL 9 | ||
| 40 | #define PVR2_CID_CROPT 10 | ||
| 41 | #define PVR2_CID_CROPW 11 | ||
| 42 | #define PVR2_CID_CROPH 12 | ||
| 43 | #define PVR2_CID_CROPCAPPAN 13 | ||
| 44 | #define PVR2_CID_CROPCAPPAD 14 | ||
| 45 | #define PVR2_CID_CROPCAPBL 15 | ||
| 46 | #define PVR2_CID_CROPCAPBT 16 | ||
| 47 | #define PVR2_CID_CROPCAPBW 17 | ||
| 48 | #define PVR2_CID_CROPCAPBH 18 | ||
| 39 | 49 | ||
| 40 | /* Legal values for the INPUT state variable */ | 50 | /* Legal values for the INPUT state variable */ |
| 41 | #define PVR2_CVAL_INPUT_TV 0 | 51 | #define PVR2_CVAL_INPUT_TV 0 |
| @@ -170,6 +180,9 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *); | |||
| 170 | /* Return information about the tuner */ | 180 | /* Return information about the tuner */ |
| 171 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); | 181 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); |
| 172 | 182 | ||
| 183 | /* Return information about cropping capabilities */ | ||
| 184 | int pvr2_hdw_get_cropcap(struct pvr2_hdw *, struct v4l2_cropcap *); | ||
| 185 | |||
| 173 | /* Query device and see if it thinks it is on a high-speed USB link */ | 186 | /* Query device and see if it thinks it is on a high-speed USB link */ |
| 174 | int pvr2_hdw_is_hsm(struct pvr2_hdw *); | 187 | int pvr2_hdw_is_hsm(struct pvr2_hdw *); |
| 175 | 188 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index ccdb429fc7af..94a47718e88e 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | |||
| @@ -37,8 +37,9 @@ | |||
| 37 | #define OP_VOLUME 3 | 37 | #define OP_VOLUME 3 |
| 38 | #define OP_FREQ 4 | 38 | #define OP_FREQ 4 |
| 39 | #define OP_AUDIORATE 5 | 39 | #define OP_AUDIORATE 5 |
| 40 | #define OP_SIZE 6 | 40 | #define OP_CROP 6 |
| 41 | #define OP_LOG 7 | 41 | #define OP_SIZE 7 |
| 42 | #define OP_LOG 8 | ||
| 42 | 43 | ||
| 43 | static const struct pvr2_i2c_op * const ops[] = { | 44 | static const struct pvr2_i2c_op * const ops[] = { |
| 44 | [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, | 45 | [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, |
| @@ -46,6 +47,7 @@ static const struct pvr2_i2c_op * const ops[] = { | |||
| 46 | [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, | 47 | [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, |
| 47 | [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, | 48 | [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, |
| 48 | [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, | 49 | [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, |
| 50 | [OP_CROP] = &pvr2_i2c_op_v4l2_crop, | ||
| 49 | [OP_SIZE] = &pvr2_i2c_op_v4l2_size, | 51 | [OP_SIZE] = &pvr2_i2c_op_v4l2_size, |
| 50 | [OP_LOG] = &pvr2_i2c_op_v4l2_log, | 52 | [OP_LOG] = &pvr2_i2c_op_v4l2_log, |
| 51 | }; | 53 | }; |
| @@ -59,6 +61,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | |||
| 59 | (1 << OP_BCSH) | | 61 | (1 << OP_BCSH) | |
| 60 | (1 << OP_VOLUME) | | 62 | (1 << OP_VOLUME) | |
| 61 | (1 << OP_FREQ) | | 63 | (1 << OP_FREQ) | |
| 64 | (1 << OP_CROP) | | ||
| 62 | (1 << OP_SIZE) | | 65 | (1 << OP_SIZE) | |
| 63 | (1 << OP_LOG)); | 66 | (1 << OP_LOG)); |
| 64 | cp->status_poll = pvr2_v4l2_cmd_status_poll; | 67 | cp->status_poll = pvr2_v4l2_cmd_status_poll; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 55f04a0b2047..16bb11902a52 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | |||
| @@ -37,6 +37,7 @@ static void set_standard(struct pvr2_hdw *hdw) | |||
| 37 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); | 37 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); |
| 38 | } | 38 | } |
| 39 | hdw->tuner_signal_stale = !0; | 39 | hdw->tuner_signal_stale = !0; |
| 40 | hdw->cropcap_stale = !0; | ||
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | 43 | ||
| @@ -233,6 +234,37 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = { | |||
| 233 | }; | 234 | }; |
| 234 | 235 | ||
| 235 | 236 | ||
| 237 | static void set_crop(struct pvr2_hdw *hdw) | ||
| 238 | { | ||
| 239 | struct v4l2_crop crop; | ||
| 240 | |||
| 241 | memset(&crop, 0, sizeof crop); | ||
| 242 | crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 243 | crop.c.left = hdw->cropl_val; | ||
| 244 | crop.c.top = hdw->cropt_val; | ||
| 245 | crop.c.height = hdw->croph_val; | ||
| 246 | crop.c.width = hdw->cropw_val; | ||
| 247 | |||
| 248 | pvr2_trace(PVR2_TRACE_CHIPS, | ||
| 249 | "i2c v4l2 set_crop crop=%d:%d:%d:%d", | ||
| 250 | crop.c.width, crop.c.height, crop.c.left, crop.c.top); | ||
| 251 | |||
| 252 | pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop); | ||
| 253 | } | ||
| 254 | |||
| 255 | static int check_crop(struct pvr2_hdw *hdw) | ||
| 256 | { | ||
| 257 | return (hdw->cropl_dirty || hdw->cropt_dirty || | ||
| 258 | hdw->cropw_dirty || hdw->croph_dirty); | ||
| 259 | } | ||
| 260 | |||
| 261 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = { | ||
| 262 | .check = check_crop, | ||
| 263 | .update = set_crop, | ||
| 264 | .name = "v4l2_crop", | ||
| 265 | }; | ||
| 266 | |||
| 267 | |||
| 236 | static void do_log(struct pvr2_hdw *hdw) | 268 | static void do_log(struct pvr2_hdw *hdw) |
| 237 | { | 269 | { |
| 238 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()"); | 270 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()"); |
| @@ -263,7 +295,19 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) | |||
| 263 | 295 | ||
| 264 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) | 296 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) |
| 265 | { | 297 | { |
| 266 | pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info); | 298 | int stat; |
| 299 | struct pvr2_hdw *hdw = cp->hdw; | ||
| 300 | if (hdw->cropcap_stale) { | ||
| 301 | hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 302 | stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP, | ||
| 303 | &hdw->cropcap_info); | ||
| 304 | if (stat == 0) { | ||
| 305 | /* Check was successful, so the data is no | ||
| 306 | longer considered stale. */ | ||
| 307 | hdw->cropcap_stale = 0; | ||
| 308 | } | ||
| 309 | } | ||
| 310 | pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info); | ||
| 267 | } | 311 | } |
| 268 | 312 | ||
| 269 | 313 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index 7fa38683b3b1..eb744a20610d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | |||
| @@ -29,6 +29,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio; | |||
| 29 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; | 29 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; |
| 30 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; | 30 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; |
| 31 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; | 31 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; |
| 32 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop; | ||
| 32 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; | 33 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; |
| 33 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; | 34 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; |
| 34 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; | 35 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index e600576a6c4b..d6a35401fefb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
| @@ -827,7 +827,7 @@ static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, | |||
| 827 | if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { | 827 | if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { |
| 828 | unsigned int idx; | 828 | unsigned int idx; |
| 829 | unsigned long msk,sm; | 829 | unsigned long msk,sm; |
| 830 | int spcfl; | 830 | |
| 831 | bcnt = scnprintf(buf,maxlen," ["); | 831 | bcnt = scnprintf(buf,maxlen," ["); |
| 832 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | 832 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; |
| 833 | sm = 0; | 833 | sm = 0; |
| @@ -891,6 +891,7 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client) | |||
| 891 | INIT_LIST_HEAD(&cp->list); | 891 | INIT_LIST_HEAD(&cp->list); |
| 892 | cp->client = client; | 892 | cp->client = client; |
| 893 | mutex_lock(&hdw->i2c_list_lock); do { | 893 | mutex_lock(&hdw->i2c_list_lock); do { |
| 894 | hdw->cropcap_stale = !0; | ||
| 894 | list_add_tail(&cp->list,&hdw->i2c_clients); | 895 | list_add_tail(&cp->list,&hdw->i2c_clients); |
| 895 | hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; | 896 | hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; |
| 896 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | 897 | } while (0); mutex_unlock(&hdw->i2c_list_lock); |
| @@ -905,6 +906,7 @@ static int pvr2_i2c_detach_inform(struct i2c_client *client) | |||
| 905 | unsigned long amask = 0; | 906 | unsigned long amask = 0; |
| 906 | int foundfl = 0; | 907 | int foundfl = 0; |
| 907 | mutex_lock(&hdw->i2c_list_lock); do { | 908 | mutex_lock(&hdw->i2c_list_lock); do { |
| 909 | hdw->cropcap_stale = !0; | ||
| 908 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { | 910 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { |
| 909 | if (cp->client == client) { | 911 | if (cp->client == client) { |
| 910 | trace_i2c("pvr2_i2c_detach" | 912 | trace_i2c("pvr2_i2c_detach" |
| @@ -946,22 +948,32 @@ static struct i2c_adapter pvr2_i2c_adap_template = { | |||
| 946 | .client_unregister = pvr2_i2c_detach_inform, | 948 | .client_unregister = pvr2_i2c_detach_inform, |
| 947 | }; | 949 | }; |
| 948 | 950 | ||
| 949 | static void do_i2c_scan(struct pvr2_hdw *hdw) | 951 | |
| 952 | /* Return true if device exists at given address */ | ||
| 953 | static int do_i2c_probe(struct pvr2_hdw *hdw, int addr) | ||
| 950 | { | 954 | { |
| 951 | struct i2c_msg msg[1]; | 955 | struct i2c_msg msg[1]; |
| 952 | int i,rc; | 956 | int rc; |
| 953 | msg[0].addr = 0; | 957 | msg[0].addr = 0; |
| 954 | msg[0].flags = I2C_M_RD; | 958 | msg[0].flags = I2C_M_RD; |
| 955 | msg[0].len = 0; | 959 | msg[0].len = 0; |
| 956 | msg[0].buf = NULL; | 960 | msg[0].buf = NULL; |
| 957 | printk("%s: i2c scan beginning\n",hdw->name); | 961 | msg[0].addr = addr; |
| 962 | rc = i2c_transfer(&hdw->i2c_adap, msg, ARRAY_SIZE(msg)); | ||
| 963 | return rc == 1; | ||
| 964 | } | ||
| 965 | |||
| 966 | static void do_i2c_scan(struct pvr2_hdw *hdw) | ||
| 967 | { | ||
| 968 | int i; | ||
| 969 | printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name); | ||
| 958 | for (i = 0; i < 128; i++) { | 970 | for (i = 0; i < 128; i++) { |
| 959 | msg[0].addr = i; | 971 | if (do_i2c_probe(hdw, i)) { |
| 960 | rc = i2c_transfer(&hdw->i2c_adap,msg, ARRAY_SIZE(msg)); | 972 | printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n", |
| 961 | if (rc != 1) continue; | 973 | hdw->name, i); |
| 962 | printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i); | 974 | } |
| 963 | } | 975 | } |
| 964 | printk("%s: i2c scan done.\n",hdw->name); | 976 | printk(KERN_INFO "%s: i2c scan done.\n", hdw->name); |
| 965 | } | 977 | } |
| 966 | 978 | ||
| 967 | void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | 979 | void pvr2_i2c_core_init(struct pvr2_hdw *hdw) |
| @@ -980,8 +992,6 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | |||
| 980 | hdw->i2c_func[0x18] = i2c_black_hole; | 992 | hdw->i2c_func[0x18] = i2c_black_hole; |
| 981 | } else if (ir_mode[hdw->unit_number] == 1) { | 993 | } else if (ir_mode[hdw->unit_number] == 1) { |
| 982 | if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) { | 994 | if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) { |
| 983 | /* This comment is present PURELY to get | ||
| 984 | checkpatch.pl to STFU. Lovely, eh? */ | ||
| 985 | hdw->i2c_func[0x18] = i2c_24xxx_ir; | 995 | hdw->i2c_func[0x18] = i2c_24xxx_ir; |
| 986 | } | 996 | } |
| 987 | } | 997 | } |
| @@ -1006,6 +1016,16 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | |||
| 1006 | mutex_init(&hdw->i2c_list_lock); | 1016 | mutex_init(&hdw->i2c_list_lock); |
| 1007 | hdw->i2c_linked = !0; | 1017 | hdw->i2c_linked = !0; |
| 1008 | i2c_add_adapter(&hdw->i2c_adap); | 1018 | i2c_add_adapter(&hdw->i2c_adap); |
| 1019 | if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { | ||
| 1020 | /* Probe for a different type of IR receiver on this | ||
| 1021 | device. If present, disable the emulated IR receiver. */ | ||
| 1022 | if (do_i2c_probe(hdw, 0x71)) { | ||
| 1023 | pvr2_trace(PVR2_TRACE_INFO, | ||
| 1024 | "Device has newer IR hardware;" | ||
| 1025 | " disabling unneeded virtual IR device"); | ||
| 1026 | hdw->i2c_func[0x18] = NULL; | ||
| 1027 | } | ||
| 1028 | } | ||
| 1009 | if (i2c_scan) do_i2c_scan(hdw); | 1029 | if (i2c_scan) do_i2c_scan(hdw); |
| 1010 | } | 1030 | } |
| 1011 | 1031 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index ad0d98c2ebb4..9b3c874d96d6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c | |||
| @@ -137,9 +137,11 @@ static int __init pvr_init(void) | |||
| 137 | ret = usb_register(&pvr_driver); | 137 | ret = usb_register(&pvr_driver); |
| 138 | 138 | ||
| 139 | if (ret == 0) | 139 | if (ret == 0) |
| 140 | info(DRIVER_DESC " : " DRIVER_VERSION); | 140 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
| 141 | if (pvrusb2_debug) info("Debug mask is %d (0x%x)", | 141 | DRIVER_DESC "\n"); |
| 142 | pvrusb2_debug,pvrusb2_debug); | 142 | if (pvrusb2_debug) |
| 143 | printk(KERN_INFO KBUILD_MODNAME ": Debug mask is %d (0x%x)\n", | ||
| 144 | pvrusb2_debug,pvrusb2_debug); | ||
| 143 | 145 | ||
| 144 | pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); | 146 | pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); |
| 145 | 147 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 46a8c39ba030..733680f21317 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | |||
| @@ -65,6 +65,7 @@ struct pvr2_sysfs_ctl_item { | |||
| 65 | struct device_attribute attr_type; | 65 | struct device_attribute attr_type; |
| 66 | struct device_attribute attr_min; | 66 | struct device_attribute attr_min; |
| 67 | struct device_attribute attr_max; | 67 | struct device_attribute attr_max; |
| 68 | struct device_attribute attr_def; | ||
| 68 | struct device_attribute attr_enum; | 69 | struct device_attribute attr_enum; |
| 69 | struct device_attribute attr_bits; | 70 | struct device_attribute attr_bits; |
| 70 | struct device_attribute attr_val; | 71 | struct device_attribute attr_val; |
| @@ -145,6 +146,23 @@ static ssize_t show_max(struct device *class_dev, | |||
| 145 | return scnprintf(buf, PAGE_SIZE, "%ld\n", val); | 146 | return scnprintf(buf, PAGE_SIZE, "%ld\n", val); |
| 146 | } | 147 | } |
| 147 | 148 | ||
| 149 | static ssize_t show_def(struct device *class_dev, | ||
| 150 | struct device_attribute *attr, | ||
| 151 | char *buf) | ||
| 152 | { | ||
| 153 | struct pvr2_sysfs_ctl_item *cip; | ||
| 154 | int val; | ||
| 155 | int ret; | ||
| 156 | cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def); | ||
| 157 | ret = pvr2_ctrl_get_def(cip->cptr, &val); | ||
| 158 | pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %d, stat=%d", | ||
| 159 | cip->chptr, cip->ctl_id, val, ret); | ||
| 160 | if (ret < 0) { | ||
| 161 | return ret; | ||
| 162 | } | ||
| 163 | return scnprintf(buf, PAGE_SIZE, "%d\n", val); | ||
| 164 | } | ||
| 165 | |||
| 148 | static ssize_t show_val_norm(struct device *class_dev, | 166 | static ssize_t show_val_norm(struct device *class_dev, |
| 149 | struct device_attribute *attr, | 167 | struct device_attribute *attr, |
| 150 | char *buf) | 168 | char *buf) |
| @@ -320,6 +338,10 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) | |||
| 320 | cip->attr_max.attr.mode = S_IRUGO; | 338 | cip->attr_max.attr.mode = S_IRUGO; |
| 321 | cip->attr_max.show = show_max; | 339 | cip->attr_max.show = show_max; |
| 322 | 340 | ||
| 341 | cip->attr_def.attr.name = "def_val"; | ||
| 342 | cip->attr_def.attr.mode = S_IRUGO; | ||
| 343 | cip->attr_def.show = show_def; | ||
| 344 | |||
| 323 | cip->attr_val.attr.name = "cur_val"; | 345 | cip->attr_val.attr.name = "cur_val"; |
| 324 | cip->attr_val.attr.mode = S_IRUGO; | 346 | cip->attr_val.attr.mode = S_IRUGO; |
| 325 | 347 | ||
| @@ -343,6 +365,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) | |||
| 343 | cip->attr_gen[acnt++] = &cip->attr_name.attr; | 365 | cip->attr_gen[acnt++] = &cip->attr_name.attr; |
| 344 | cip->attr_gen[acnt++] = &cip->attr_type.attr; | 366 | cip->attr_gen[acnt++] = &cip->attr_type.attr; |
| 345 | cip->attr_gen[acnt++] = &cip->attr_val.attr; | 367 | cip->attr_gen[acnt++] = &cip->attr_val.attr; |
| 368 | cip->attr_gen[acnt++] = &cip->attr_def.attr; | ||
| 346 | cip->attr_val.show = show_val_norm; | 369 | cip->attr_val.show = show_val_norm; |
| 347 | cip->attr_val.store = store_val_norm; | 370 | cip->attr_val.store = store_val_norm; |
| 348 | if (pvr2_ctrl_has_custom_symbols(cptr)) { | 371 | if (pvr2_ctrl_has_custom_symbols(cptr)) { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 00306faeac01..f048d80b77e5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
| @@ -533,7 +533,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
| 533 | 533 | ||
| 534 | lmin = pvr2_ctrl_get_min(hcp); | 534 | lmin = pvr2_ctrl_get_min(hcp); |
| 535 | lmax = pvr2_ctrl_get_max(hcp); | 535 | lmax = pvr2_ctrl_get_max(hcp); |
| 536 | ldef = pvr2_ctrl_get_def(hcp); | 536 | pvr2_ctrl_get_def(hcp, &ldef); |
| 537 | if (w == -1) { | 537 | if (w == -1) { |
| 538 | w = ldef; | 538 | w = ldef; |
| 539 | } else if (w < lmin) { | 539 | } else if (w < lmin) { |
| @@ -543,7 +543,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
| 543 | } | 543 | } |
| 544 | lmin = pvr2_ctrl_get_min(vcp); | 544 | lmin = pvr2_ctrl_get_min(vcp); |
| 545 | lmax = pvr2_ctrl_get_max(vcp); | 545 | lmax = pvr2_ctrl_get_max(vcp); |
| 546 | ldef = pvr2_ctrl_get_def(vcp); | 546 | pvr2_ctrl_get_def(vcp, &ldef); |
| 547 | if (h == -1) { | 547 | if (h == -1) { |
| 548 | h = ldef; | 548 | h = ldef; |
| 549 | } else if (h < lmin) { | 549 | } else if (h < lmin) { |
| @@ -604,6 +604,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
| 604 | case VIDIOC_QUERYCTRL: | 604 | case VIDIOC_QUERYCTRL: |
| 605 | { | 605 | { |
| 606 | struct pvr2_ctrl *cptr; | 606 | struct pvr2_ctrl *cptr; |
| 607 | int val; | ||
| 607 | struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; | 608 | struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; |
| 608 | ret = 0; | 609 | ret = 0; |
| 609 | if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { | 610 | if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { |
| @@ -627,7 +628,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
| 627 | pvr2_ctrl_get_desc(cptr)); | 628 | pvr2_ctrl_get_desc(cptr)); |
| 628 | strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); | 629 | strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); |
| 629 | vc->flags = pvr2_ctrl_get_v4lflags(cptr); | 630 | vc->flags = pvr2_ctrl_get_v4lflags(cptr); |
| 630 | vc->default_value = pvr2_ctrl_get_def(cptr); | 631 | pvr2_ctrl_get_def(cptr, &val); |
| 632 | vc->default_value = val; | ||
| 631 | switch (pvr2_ctrl_get_type(cptr)) { | 633 | switch (pvr2_ctrl_get_type(cptr)) { |
| 632 | case pvr2_ctl_enum: | 634 | case pvr2_ctl_enum: |
| 633 | vc->type = V4L2_CTRL_TYPE_MENU; | 635 | vc->type = V4L2_CTRL_TYPE_MENU; |
| @@ -753,6 +755,92 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
| 753 | break; | 755 | break; |
| 754 | } | 756 | } |
| 755 | 757 | ||
| 758 | case VIDIOC_CROPCAP: | ||
| 759 | { | ||
| 760 | struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg; | ||
| 761 | if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
| 762 | ret = -EINVAL; | ||
| 763 | break; | ||
| 764 | } | ||
| 765 | ret = pvr2_hdw_get_cropcap(hdw, cap); | ||
| 766 | cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */ | ||
| 767 | break; | ||
| 768 | } | ||
| 769 | case VIDIOC_G_CROP: | ||
| 770 | { | ||
| 771 | struct v4l2_crop *crop = (struct v4l2_crop *)arg; | ||
| 772 | int val = 0; | ||
| 773 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
| 774 | ret = -EINVAL; | ||
| 775 | break; | ||
| 776 | } | ||
| 777 | ret = pvr2_ctrl_get_value( | ||
| 778 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val); | ||
| 779 | if (ret != 0) { | ||
| 780 | ret = -EINVAL; | ||
| 781 | break; | ||
| 782 | } | ||
| 783 | crop->c.left = val; | ||
| 784 | ret = pvr2_ctrl_get_value( | ||
| 785 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val); | ||
| 786 | if (ret != 0) { | ||
| 787 | ret = -EINVAL; | ||
| 788 | break; | ||
| 789 | } | ||
| 790 | crop->c.top = val; | ||
| 791 | ret = pvr2_ctrl_get_value( | ||
| 792 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val); | ||
| 793 | if (ret != 0) { | ||
| 794 | ret = -EINVAL; | ||
| 795 | break; | ||
| 796 | } | ||
| 797 | crop->c.width = val; | ||
| 798 | ret = pvr2_ctrl_get_value( | ||
| 799 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val); | ||
| 800 | if (ret != 0) { | ||
| 801 | ret = -EINVAL; | ||
| 802 | break; | ||
| 803 | } | ||
| 804 | crop->c.height = val; | ||
| 805 | } | ||
| 806 | case VIDIOC_S_CROP: | ||
| 807 | { | ||
| 808 | struct v4l2_crop *crop = (struct v4l2_crop *)arg; | ||
| 809 | struct v4l2_cropcap cap; | ||
| 810 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
| 811 | ret = -EINVAL; | ||
| 812 | break; | ||
| 813 | } | ||
| 814 | cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 815 | ret = pvr2_ctrl_set_value( | ||
| 816 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), | ||
| 817 | crop->c.left); | ||
| 818 | if (ret != 0) { | ||
| 819 | ret = -EINVAL; | ||
| 820 | break; | ||
| 821 | } | ||
| 822 | ret = pvr2_ctrl_set_value( | ||
| 823 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), | ||
| 824 | crop->c.top); | ||
| 825 | if (ret != 0) { | ||
| 826 | ret = -EINVAL; | ||
| 827 | break; | ||
| 828 | } | ||
| 829 | ret = pvr2_ctrl_set_value( | ||
| 830 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), | ||
| 831 | crop->c.width); | ||
| 832 | if (ret != 0) { | ||
| 833 | ret = -EINVAL; | ||
| 834 | break; | ||
| 835 | } | ||
| 836 | ret = pvr2_ctrl_set_value( | ||
| 837 | pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), | ||
| 838 | crop->c.height); | ||
| 839 | if (ret != 0) { | ||
| 840 | ret = -EINVAL; | ||
| 841 | break; | ||
| 842 | } | ||
| 843 | } | ||
| 756 | case VIDIOC_LOG_STATUS: | 844 | case VIDIOC_LOG_STATUS: |
| 757 | { | 845 | { |
| 758 | pvr2_hdw_trigger_module_log(hdw); | 846 | pvr2_hdw_trigger_module_log(hdw); |
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index dbc560742553..c66530210192 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
| 42 | #endif | 42 | #endif |
| 43 | #include <asm/errno.h> | 43 | #include <asm/errno.h> |
| 44 | #include <linux/version.h> | ||
| 45 | 44 | ||
| 46 | #include "pwc.h" | 45 | #include "pwc.h" |
| 47 | #include "pwc-uncompress.h" | 46 | #include "pwc-uncompress.h" |
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 9aee7cb6f79a..ab28389b4cda 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
| @@ -1112,7 +1112,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) | |||
| 1112 | 1112 | ||
| 1113 | PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev); | 1113 | PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev); |
| 1114 | 1114 | ||
| 1115 | pdev = (struct pwc_device *)vdev->priv; | 1115 | pdev = video_get_drvdata(vdev); |
| 1116 | BUG_ON(!pdev); | 1116 | BUG_ON(!pdev); |
| 1117 | if (pdev->vopen) { | 1117 | if (pdev->vopen) { |
| 1118 | PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n"); | 1118 | PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n"); |
| @@ -1233,7 +1233,7 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
| 1233 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); | 1233 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); |
| 1234 | 1234 | ||
| 1235 | lock_kernel(); | 1235 | lock_kernel(); |
| 1236 | pdev = (struct pwc_device *)vdev->priv; | 1236 | pdev = video_get_drvdata(vdev); |
| 1237 | if (pdev->vopen == 0) | 1237 | if (pdev->vopen == 0) |
| 1238 | PWC_DEBUG_MODULE("video_close() called on closed device?\n"); | 1238 | PWC_DEBUG_MODULE("video_close() called on closed device?\n"); |
| 1239 | 1239 | ||
| @@ -1304,7 +1304,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, | |||
| 1304 | vdev, buf, count); | 1304 | vdev, buf, count); |
| 1305 | if (vdev == NULL) | 1305 | if (vdev == NULL) |
| 1306 | return -EFAULT; | 1306 | return -EFAULT; |
| 1307 | pdev = vdev->priv; | 1307 | pdev = video_get_drvdata(vdev); |
| 1308 | if (pdev == NULL) | 1308 | if (pdev == NULL) |
| 1309 | return -EFAULT; | 1309 | return -EFAULT; |
| 1310 | 1310 | ||
| @@ -1386,7 +1386,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) | |||
| 1386 | 1386 | ||
| 1387 | if (vdev == NULL) | 1387 | if (vdev == NULL) |
| 1388 | return -EFAULT; | 1388 | return -EFAULT; |
| 1389 | pdev = vdev->priv; | 1389 | pdev = video_get_drvdata(vdev); |
| 1390 | if (pdev == NULL) | 1390 | if (pdev == NULL) |
| 1391 | return -EFAULT; | 1391 | return -EFAULT; |
| 1392 | 1392 | ||
| @@ -1408,7 +1408,7 @@ static int pwc_video_ioctl(struct inode *inode, struct file *file, | |||
| 1408 | 1408 | ||
| 1409 | if (!vdev) | 1409 | if (!vdev) |
| 1410 | goto out; | 1410 | goto out; |
| 1411 | pdev = vdev->priv; | 1411 | pdev = video_get_drvdata(vdev); |
| 1412 | 1412 | ||
| 1413 | mutex_lock(&pdev->modlock); | 1413 | mutex_lock(&pdev->modlock); |
| 1414 | if (!pdev->unplugged) | 1414 | if (!pdev->unplugged) |
| @@ -1428,7 +1428,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 1428 | int index; | 1428 | int index; |
| 1429 | 1429 | ||
| 1430 | PWC_DEBUG_MEMORY(">> %s\n", __func__); | 1430 | PWC_DEBUG_MEMORY(">> %s\n", __func__); |
| 1431 | pdev = vdev->priv; | 1431 | pdev = video_get_drvdata(vdev); |
| 1432 | size = vma->vm_end - vma->vm_start; | 1432 | size = vma->vm_end - vma->vm_start; |
| 1433 | start = vma->vm_start; | 1433 | start = vma->vm_start; |
| 1434 | 1434 | ||
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 1742889874df..76a1376c9751 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c | |||
| @@ -346,7 +346,7 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file, | |||
| 346 | 346 | ||
| 347 | if (vdev == NULL) | 347 | if (vdev == NULL) |
| 348 | return -EFAULT; | 348 | return -EFAULT; |
| 349 | pdev = vdev->priv; | 349 | pdev = video_get_drvdata(vdev); |
| 350 | if (pdev == NULL) | 350 | if (pdev == NULL) |
| 351 | return -EFAULT; | 351 | return -EFAULT; |
| 352 | 352 | ||
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index cf96b2cc4f1c..eb6be5802928 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
| @@ -629,17 +629,6 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) | |||
| 629 | pdata->init(pcdev->dev); | 629 | pdata->init(pcdev->dev); |
| 630 | } | 630 | } |
| 631 | 631 | ||
| 632 | if (pdata && pdata->power) { | ||
| 633 | dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__); | ||
| 634 | pdata->power(pcdev->dev, 1); | ||
| 635 | } | ||
| 636 | |||
| 637 | if (pdata && pdata->reset) { | ||
| 638 | dev_dbg(pcdev->dev, "%s: Releasing camera reset\n", | ||
| 639 | __func__); | ||
| 640 | pdata->reset(pcdev->dev, 1); | ||
| 641 | } | ||
| 642 | |||
| 643 | CICR0 = 0x3FF; /* disable all interrupts */ | 632 | CICR0 = 0x3FF; /* disable all interrupts */ |
| 644 | 633 | ||
| 645 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) | 634 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) |
| @@ -660,20 +649,7 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) | |||
| 660 | 649 | ||
| 661 | static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) | 650 | static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) |
| 662 | { | 651 | { |
| 663 | struct pxacamera_platform_data *board = pcdev->pdata; | ||
| 664 | |||
| 665 | clk_disable(pcdev->clk); | 652 | clk_disable(pcdev->clk); |
| 666 | |||
| 667 | if (board && board->reset) { | ||
| 668 | dev_dbg(pcdev->dev, "%s: Asserting camera reset\n", | ||
| 669 | __func__); | ||
| 670 | board->reset(pcdev->dev, 0); | ||
| 671 | } | ||
| 672 | |||
| 673 | if (board && board->power) { | ||
| 674 | dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__); | ||
| 675 | board->power(pcdev->dev, 0); | ||
| 676 | } | ||
| 677 | } | 653 | } |
| 678 | 654 | ||
| 679 | static irqreturn_t pxa_camera_irq(int irq, void *data) | 655 | static irqreturn_t pxa_camera_irq(int irq, void *data) |
| @@ -1144,31 +1120,31 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
| 1144 | pcdev->dev = &pdev->dev; | 1120 | pcdev->dev = &pdev->dev; |
| 1145 | 1121 | ||
| 1146 | /* request dma */ | 1122 | /* request dma */ |
| 1147 | pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, | 1123 | err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, |
| 1148 | pxa_camera_dma_irq_y, pcdev); | 1124 | pxa_camera_dma_irq_y, pcdev); |
| 1149 | if (pcdev->dma_chans[0] < 0) { | 1125 | if (err < 0) { |
| 1150 | dev_err(pcdev->dev, "Can't request DMA for Y\n"); | 1126 | dev_err(pcdev->dev, "Can't request DMA for Y\n"); |
| 1151 | err = -ENOMEM; | ||
| 1152 | goto exit_iounmap; | 1127 | goto exit_iounmap; |
| 1153 | } | 1128 | } |
| 1129 | pcdev->dma_chans[0] = err; | ||
| 1154 | dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); | 1130 | dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); |
| 1155 | 1131 | ||
| 1156 | pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH, | 1132 | err = pxa_request_dma("CI_U", DMA_PRIO_HIGH, |
| 1157 | pxa_camera_dma_irq_u, pcdev); | 1133 | pxa_camera_dma_irq_u, pcdev); |
| 1158 | if (pcdev->dma_chans[1] < 0) { | 1134 | if (err < 0) { |
| 1159 | dev_err(pcdev->dev, "Can't request DMA for U\n"); | 1135 | dev_err(pcdev->dev, "Can't request DMA for U\n"); |
| 1160 | err = -ENOMEM; | ||
| 1161 | goto exit_free_dma_y; | 1136 | goto exit_free_dma_y; |
| 1162 | } | 1137 | } |
| 1138 | pcdev->dma_chans[1] = err; | ||
| 1163 | dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); | 1139 | dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); |
| 1164 | 1140 | ||
| 1165 | pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH, | 1141 | err = pxa_request_dma("CI_V", DMA_PRIO_HIGH, |
| 1166 | pxa_camera_dma_irq_v, pcdev); | 1142 | pxa_camera_dma_irq_v, pcdev); |
| 1167 | if (pcdev->dma_chans[0] < 0) { | 1143 | if (err < 0) { |
| 1168 | dev_err(pcdev->dev, "Can't request DMA for V\n"); | 1144 | dev_err(pcdev->dev, "Can't request DMA for V\n"); |
| 1169 | err = -ENOMEM; | ||
| 1170 | goto exit_free_dma_u; | 1145 | goto exit_free_dma_u; |
| 1171 | } | 1146 | } |
| 1147 | pcdev->dma_chans[2] = err; | ||
| 1172 | dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); | 1148 | dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); |
| 1173 | 1149 | ||
| 1174 | DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; | 1150 | DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; |
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 92b83feae366..5272926db73e 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
| @@ -58,6 +58,8 @@ | |||
| 58 | 58 | ||
| 59 | 59 | ||
| 60 | 60 | ||
| 61 | /* default JPEG quality */ | ||
| 62 | #define S2255_DEF_JPEG_QUAL 50 | ||
| 61 | /* vendor request in */ | 63 | /* vendor request in */ |
| 62 | #define S2255_VR_IN 0 | 64 | #define S2255_VR_IN 0 |
| 63 | /* vendor request out */ | 65 | /* vendor request out */ |
| @@ -67,20 +69,21 @@ | |||
| 67 | /* USB endpoint number for configuring the device */ | 69 | /* USB endpoint number for configuring the device */ |
| 68 | #define S2255_CONFIG_EP 2 | 70 | #define S2255_CONFIG_EP 2 |
| 69 | /* maximum time for DSP to start responding after last FW word loaded(ms) */ | 71 | /* maximum time for DSP to start responding after last FW word loaded(ms) */ |
| 70 | #define S2255_DSP_BOOTTIME 400 | 72 | #define S2255_DSP_BOOTTIME 800 |
| 71 | /* maximum time to wait for firmware to load (ms) */ | 73 | /* maximum time to wait for firmware to load (ms) */ |
| 72 | #define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME) | 74 | #define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME) |
| 73 | #define S2255_DEF_BUFS 16 | 75 | #define S2255_DEF_BUFS 16 |
| 76 | #define S2255_SETMODE_TIMEOUT 500 | ||
| 74 | #define MAX_CHANNELS 4 | 77 | #define MAX_CHANNELS 4 |
| 75 | #define FRAME_MARKER 0x2255DA4AL | 78 | #define S2255_MARKER_FRAME 0x2255DA4AL |
| 76 | #define MAX_PIPE_USBBLOCK (40 * 1024) | 79 | #define S2255_MARKER_RESPONSE 0x2255ACACL |
| 77 | #define DEFAULT_PIPE_USBBLOCK (16 * 1024) | 80 | #define S2255_USB_XFER_SIZE (16 * 1024) |
| 78 | #define MAX_CHANNELS 4 | 81 | #define MAX_CHANNELS 4 |
| 79 | #define MAX_PIPE_BUFFERS 1 | 82 | #define MAX_PIPE_BUFFERS 1 |
| 80 | #define SYS_FRAMES 4 | 83 | #define SYS_FRAMES 4 |
| 81 | /* maximum size is PAL full size plus room for the marker header(s) */ | 84 | /* maximum size is PAL full size plus room for the marker header(s) */ |
| 82 | #define SYS_FRAMES_MAXSIZE (720 * 288 * 2 * 2 + 4096) | 85 | #define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096) |
| 83 | #define DEF_USB_BLOCK (4096) | 86 | #define DEF_USB_BLOCK S2255_USB_XFER_SIZE |
| 84 | #define LINE_SZ_4CIFS_NTSC 640 | 87 | #define LINE_SZ_4CIFS_NTSC 640 |
| 85 | #define LINE_SZ_2CIFS_NTSC 640 | 88 | #define LINE_SZ_2CIFS_NTSC 640 |
| 86 | #define LINE_SZ_1CIFS_NTSC 320 | 89 | #define LINE_SZ_1CIFS_NTSC 320 |
| @@ -108,6 +111,9 @@ | |||
| 108 | #define COLOR_YUVPL 1 /* YUV planar */ | 111 | #define COLOR_YUVPL 1 /* YUV planar */ |
| 109 | #define COLOR_YUVPK 2 /* YUV packed */ | 112 | #define COLOR_YUVPK 2 /* YUV packed */ |
| 110 | #define COLOR_Y8 4 /* monochrome */ | 113 | #define COLOR_Y8 4 /* monochrome */ |
| 114 | #define COLOR_JPG 5 /* JPEG */ | ||
| 115 | #define MASK_COLOR 0xff | ||
| 116 | #define MASK_JPG_QUALITY 0xff00 | ||
| 111 | 117 | ||
| 112 | /* frame decimation. Not implemented by V4L yet(experimental in V4L) */ | 118 | /* frame decimation. Not implemented by V4L yet(experimental in V4L) */ |
| 113 | #define FDEC_1 1 /* capture every frame. default */ | 119 | #define FDEC_1 1 /* capture every frame. default */ |
| @@ -148,16 +154,14 @@ struct s2255_mode { | |||
| 148 | u32 restart; /* if DSP requires restart */ | 154 | u32 restart; /* if DSP requires restart */ |
| 149 | }; | 155 | }; |
| 150 | 156 | ||
| 151 | /* frame structure */ | ||
| 152 | #define FRAME_STATE_UNUSED 0 | ||
| 153 | #define FRAME_STATE_FILLING 1 | ||
| 154 | #define FRAME_STATE_FULL 2 | ||
| 155 | 157 | ||
| 158 | #define S2255_READ_IDLE 0 | ||
| 159 | #define S2255_READ_FRAME 1 | ||
| 156 | 160 | ||
| 161 | /* frame structure */ | ||
| 157 | struct s2255_framei { | 162 | struct s2255_framei { |
| 158 | unsigned long size; | 163 | unsigned long size; |
| 159 | 164 | unsigned long ulState; /* ulState:S2255_READ_IDLE, S2255_READ_FRAME*/ | |
| 160 | unsigned long ulState; /* ulState ==0 unused, 1 being filled, 2 full */ | ||
| 161 | void *lpvbits; /* image data */ | 165 | void *lpvbits; /* image data */ |
| 162 | unsigned long cur_size; /* current data copied to it */ | 166 | unsigned long cur_size; /* current data copied to it */ |
| 163 | }; | 167 | }; |
| @@ -188,6 +192,10 @@ struct s2255_dmaqueue { | |||
| 188 | #define S2255_FW_FAILED 3 | 192 | #define S2255_FW_FAILED 3 |
| 189 | #define S2255_FW_DISCONNECTING 4 | 193 | #define S2255_FW_DISCONNECTING 4 |
| 190 | 194 | ||
| 195 | #define S2255_FW_MARKER 0x22552f2f | ||
| 196 | /* 2255 read states */ | ||
| 197 | #define S2255_READ_IDLE 0 | ||
| 198 | #define S2255_READ_FRAME 1 | ||
| 191 | struct s2255_fw { | 199 | struct s2255_fw { |
| 192 | int fw_loaded; | 200 | int fw_loaded; |
| 193 | int fw_size; | 201 | int fw_size; |
| @@ -195,7 +203,6 @@ struct s2255_fw { | |||
| 195 | atomic_t fw_state; | 203 | atomic_t fw_state; |
| 196 | void *pfw_data; | 204 | void *pfw_data; |
| 197 | wait_queue_head_t wait_fw; | 205 | wait_queue_head_t wait_fw; |
| 198 | struct timer_list dsp_wait; | ||
| 199 | const struct firmware *fw; | 206 | const struct firmware *fw; |
| 200 | }; | 207 | }; |
| 201 | 208 | ||
| @@ -237,15 +244,27 @@ struct s2255_dev { | |||
| 237 | struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; | 244 | struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; |
| 238 | struct s2255_bufferi buffer[MAX_CHANNELS]; | 245 | struct s2255_bufferi buffer[MAX_CHANNELS]; |
| 239 | struct s2255_mode mode[MAX_CHANNELS]; | 246 | struct s2255_mode mode[MAX_CHANNELS]; |
| 247 | /* jpeg compression */ | ||
| 248 | struct v4l2_jpegcompression jc[MAX_CHANNELS]; | ||
| 240 | const struct s2255_fmt *cur_fmt[MAX_CHANNELS]; | 249 | const struct s2255_fmt *cur_fmt[MAX_CHANNELS]; |
| 241 | int cur_frame[MAX_CHANNELS]; | 250 | int cur_frame[MAX_CHANNELS]; |
| 242 | int last_frame[MAX_CHANNELS]; | 251 | int last_frame[MAX_CHANNELS]; |
| 243 | u32 cc; /* current channel */ | 252 | u32 cc; /* current channel */ |
| 244 | int b_acquire[MAX_CHANNELS]; | 253 | int b_acquire[MAX_CHANNELS]; |
| 254 | /* allocated image size */ | ||
| 245 | unsigned long req_image_size[MAX_CHANNELS]; | 255 | unsigned long req_image_size[MAX_CHANNELS]; |
| 256 | /* received packet size */ | ||
| 257 | unsigned long pkt_size[MAX_CHANNELS]; | ||
| 246 | int bad_payload[MAX_CHANNELS]; | 258 | int bad_payload[MAX_CHANNELS]; |
| 247 | unsigned long frame_count[MAX_CHANNELS]; | 259 | unsigned long frame_count[MAX_CHANNELS]; |
| 248 | int frame_ready; | 260 | int frame_ready; |
| 261 | /* if JPEG image */ | ||
| 262 | int jpg_size[MAX_CHANNELS]; | ||
| 263 | /* if channel configured to default state */ | ||
| 264 | int chn_configured[MAX_CHANNELS]; | ||
| 265 | wait_queue_head_t wait_setmode[MAX_CHANNELS]; | ||
| 266 | int setmode_ready[MAX_CHANNELS]; | ||
| 267 | int chn_ready; | ||
| 249 | struct kref kref; | 268 | struct kref kref; |
| 250 | spinlock_t slock; | 269 | spinlock_t slock; |
| 251 | }; | 270 | }; |
| @@ -306,12 +325,16 @@ static void s2255_stop_readpipe(struct s2255_dev *dev); | |||
| 306 | static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn); | 325 | static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn); |
| 307 | static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn); | 326 | static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn); |
| 308 | static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | 327 | static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, |
| 309 | int chn); | 328 | int chn, int jpgsize); |
| 310 | static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | 329 | static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, |
| 311 | struct s2255_mode *mode); | 330 | struct s2255_mode *mode); |
| 312 | static int s2255_board_shutdown(struct s2255_dev *dev); | 331 | static int s2255_board_shutdown(struct s2255_dev *dev); |
| 313 | static void s2255_exit_v4l(struct s2255_dev *dev); | 332 | static void s2255_exit_v4l(struct s2255_dev *dev); |
| 314 | static void s2255_fwload_start(struct s2255_dev *dev); | 333 | static void s2255_fwload_start(struct s2255_dev *dev, int reset); |
| 334 | static void s2255_destroy(struct kref *kref); | ||
| 335 | static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req, | ||
| 336 | u16 index, u16 value, void *buf, | ||
| 337 | s32 buf_len, int bOut); | ||
| 315 | 338 | ||
| 316 | #define dprintk(level, fmt, arg...) \ | 339 | #define dprintk(level, fmt, arg...) \ |
| 317 | do { \ | 340 | do { \ |
| @@ -407,6 +430,10 @@ static const struct s2255_fmt formats[] = { | |||
| 407 | .fourcc = V4L2_PIX_FMT_UYVY, | 430 | .fourcc = V4L2_PIX_FMT_UYVY, |
| 408 | .depth = 16 | 431 | .depth = 16 |
| 409 | }, { | 432 | }, { |
| 433 | .name = "JPG", | ||
| 434 | .fourcc = V4L2_PIX_FMT_JPEG, | ||
| 435 | .depth = 24 | ||
| 436 | }, { | ||
| 410 | .name = "8bpp GREY", | 437 | .name = "8bpp GREY", |
| 411 | .fourcc = V4L2_PIX_FMT_GREY, | 438 | .fourcc = V4L2_PIX_FMT_GREY, |
| 412 | .depth = 8 | 439 | .depth = 8 |
| @@ -464,6 +491,13 @@ static void planar422p_to_yuv_packed(const unsigned char *in, | |||
| 464 | return; | 491 | return; |
| 465 | } | 492 | } |
| 466 | 493 | ||
| 494 | static void s2255_reset_dsppower(struct s2255_dev *dev) | ||
| 495 | { | ||
| 496 | s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b0b, NULL, 0, 1); | ||
| 497 | msleep(10); | ||
| 498 | s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1); | ||
| 499 | return; | ||
| 500 | } | ||
| 467 | 501 | ||
| 468 | /* kickstarts the firmware loading. from probe | 502 | /* kickstarts the firmware loading. from probe |
| 469 | */ | 503 | */ |
| @@ -480,18 +514,6 @@ static void s2255_timer(unsigned long user_data) | |||
| 480 | } | 514 | } |
| 481 | } | 515 | } |
| 482 | 516 | ||
| 483 | /* called when DSP is up and running. DSP is guaranteed to | ||
| 484 | be running after S2255_DSP_BOOTTIME */ | ||
| 485 | static void s2255_dsp_running(unsigned long user_data) | ||
| 486 | { | ||
| 487 | struct s2255_fw *data = (struct s2255_fw *)user_data; | ||
| 488 | dprintk(1, "dsp running\n"); | ||
| 489 | atomic_set(&data->fw_state, S2255_FW_SUCCESS); | ||
| 490 | wake_up(&data->wait_fw); | ||
| 491 | printk(KERN_INFO "s2255: firmware loaded successfully\n"); | ||
| 492 | return; | ||
| 493 | } | ||
| 494 | |||
| 495 | 517 | ||
| 496 | /* this loads the firmware asynchronously. | 518 | /* this loads the firmware asynchronously. |
| 497 | Originally this was done synchroously in probe. | 519 | Originally this was done synchroously in probe. |
| @@ -549,19 +571,14 @@ static void s2255_fwchunk_complete(struct urb *urb) | |||
| 549 | } | 571 | } |
| 550 | data->fw_loaded += len; | 572 | data->fw_loaded += len; |
| 551 | } else { | 573 | } else { |
| 552 | init_timer(&data->dsp_wait); | ||
| 553 | data->dsp_wait.function = s2255_dsp_running; | ||
| 554 | data->dsp_wait.data = (unsigned long)data; | ||
| 555 | atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT); | 574 | atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT); |
| 556 | mod_timer(&data->dsp_wait, msecs_to_jiffies(S2255_DSP_BOOTTIME) | ||
| 557 | + jiffies); | ||
| 558 | } | 575 | } |
| 559 | dprintk(100, "2255 complete done\n"); | 576 | dprintk(100, "2255 complete done\n"); |
| 560 | return; | 577 | return; |
| 561 | 578 | ||
| 562 | } | 579 | } |
| 563 | 580 | ||
| 564 | static int s2255_got_frame(struct s2255_dev *dev, int chn) | 581 | static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize) |
| 565 | { | 582 | { |
| 566 | struct s2255_dmaqueue *dma_q = &dev->vidq[chn]; | 583 | struct s2255_dmaqueue *dma_q = &dev->vidq[chn]; |
| 567 | struct s2255_buffer *buf; | 584 | struct s2255_buffer *buf; |
| @@ -586,8 +603,7 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn) | |||
| 586 | list_del(&buf->vb.queue); | 603 | list_del(&buf->vb.queue); |
| 587 | do_gettimeofday(&buf->vb.ts); | 604 | do_gettimeofday(&buf->vb.ts); |
| 588 | dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i); | 605 | dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i); |
| 589 | 606 | s2255_fillbuff(dev, buf, dma_q->channel, jpgsize); | |
| 590 | s2255_fillbuff(dev, buf, dma_q->channel); | ||
| 591 | wake_up(&buf->vb.done); | 607 | wake_up(&buf->vb.done); |
| 592 | dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i); | 608 | dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i); |
| 593 | unlock: | 609 | unlock: |
| @@ -621,7 +637,7 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc) | |||
| 621 | * | 637 | * |
| 622 | */ | 638 | */ |
| 623 | static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | 639 | static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, |
| 624 | int chn) | 640 | int chn, int jpgsize) |
| 625 | { | 641 | { |
| 626 | int pos = 0; | 642 | int pos = 0; |
| 627 | struct timeval ts; | 643 | struct timeval ts; |
| @@ -649,6 +665,10 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | |||
| 649 | case V4L2_PIX_FMT_GREY: | 665 | case V4L2_PIX_FMT_GREY: |
| 650 | memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height); | 666 | memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height); |
| 651 | break; | 667 | break; |
| 668 | case V4L2_PIX_FMT_JPEG: | ||
| 669 | buf->vb.size = jpgsize; | ||
| 670 | memcpy(vbuf, tmpbuf, buf->vb.size); | ||
| 671 | break; | ||
| 652 | case V4L2_PIX_FMT_YUV422P: | 672 | case V4L2_PIX_FMT_YUV422P: |
| 653 | memcpy(vbuf, tmpbuf, | 673 | memcpy(vbuf, tmpbuf, |
| 654 | buf->vb.width * buf->vb.height * 2); | 674 | buf->vb.width * buf->vb.height * 2); |
| @@ -657,9 +677,6 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf, | |||
| 657 | printk(KERN_DEBUG "s2255: unknown format?\n"); | 677 | printk(KERN_DEBUG "s2255: unknown format?\n"); |
| 658 | } | 678 | } |
| 659 | dev->last_frame[chn] = -1; | 679 | dev->last_frame[chn] = -1; |
| 660 | /* done with the frame, free it */ | ||
| 661 | frm->ulState = 0; | ||
| 662 | dprintk(4, "freeing buffer\n"); | ||
| 663 | } else { | 680 | } else { |
| 664 | printk(KERN_ERR "s2255: =======no frame\n"); | 681 | printk(KERN_ERR "s2255: =======no frame\n"); |
| 665 | return; | 682 | return; |
| @@ -1021,6 +1038,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
| 1021 | case V4L2_PIX_FMT_GREY: | 1038 | case V4L2_PIX_FMT_GREY: |
| 1022 | fh->mode.color = COLOR_Y8; | 1039 | fh->mode.color = COLOR_Y8; |
| 1023 | break; | 1040 | break; |
| 1041 | case V4L2_PIX_FMT_JPEG: | ||
| 1042 | fh->mode.color = COLOR_JPG | | ||
| 1043 | (fh->dev->jc[fh->channel].quality << 8); | ||
| 1044 | break; | ||
| 1024 | case V4L2_PIX_FMT_YUV422P: | 1045 | case V4L2_PIX_FMT_YUV422P: |
| 1025 | fh->mode.color = COLOR_YUVPL; | 1046 | fh->mode.color = COLOR_YUVPL; |
| 1026 | break; | 1047 | break; |
| @@ -1139,7 +1160,7 @@ static u32 get_transfer_size(struct s2255_mode *mode) | |||
| 1139 | } | 1160 | } |
| 1140 | } | 1161 | } |
| 1141 | outImageSize = linesPerFrame * pixelsPerLine; | 1162 | outImageSize = linesPerFrame * pixelsPerLine; |
| 1142 | if (mode->color != COLOR_Y8) { | 1163 | if ((mode->color & MASK_COLOR) != COLOR_Y8) { |
| 1143 | /* 2 bytes/pixel if not monochrome */ | 1164 | /* 2 bytes/pixel if not monochrome */ |
| 1144 | outImageSize *= 2; | 1165 | outImageSize *= 2; |
| 1145 | } | 1166 | } |
| @@ -1185,12 +1206,17 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
| 1185 | u32 *buffer; | 1206 | u32 *buffer; |
| 1186 | unsigned long chn_rev; | 1207 | unsigned long chn_rev; |
| 1187 | 1208 | ||
| 1209 | mutex_lock(&dev->lock); | ||
| 1188 | chn_rev = G_chnmap[chn]; | 1210 | chn_rev = G_chnmap[chn]; |
| 1189 | dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale); | 1211 | dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale); |
| 1190 | dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn], | 1212 | dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn], |
| 1191 | dev->mode[chn].scale); | 1213 | dev->mode[chn].scale); |
| 1192 | dprintk(2, "mode contrast %x\n", mode->contrast); | 1214 | dprintk(2, "mode contrast %x\n", mode->contrast); |
| 1193 | 1215 | ||
| 1216 | /* if JPEG, set the quality */ | ||
| 1217 | if ((mode->color & MASK_COLOR) == COLOR_JPG) | ||
| 1218 | mode->color = (dev->jc[chn].quality << 8) | COLOR_JPG; | ||
| 1219 | |||
| 1194 | /* save the mode */ | 1220 | /* save the mode */ |
| 1195 | dev->mode[chn] = *mode; | 1221 | dev->mode[chn] = *mode; |
| 1196 | dev->req_image_size[chn] = get_transfer_size(mode); | 1222 | dev->req_image_size[chn] = get_transfer_size(mode); |
| @@ -1199,6 +1225,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
| 1199 | buffer = kzalloc(512, GFP_KERNEL); | 1225 | buffer = kzalloc(512, GFP_KERNEL); |
| 1200 | if (buffer == NULL) { | 1226 | if (buffer == NULL) { |
| 1201 | dev_err(&dev->udev->dev, "out of mem\n"); | 1227 | dev_err(&dev->udev->dev, "out of mem\n"); |
| 1228 | mutex_unlock(&dev->lock); | ||
| 1202 | return -ENOMEM; | 1229 | return -ENOMEM; |
| 1203 | } | 1230 | } |
| 1204 | 1231 | ||
| @@ -1214,12 +1241,20 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, | |||
| 1214 | dprintk(1, "set mode done chn %lu, %d\n", chn, res); | 1241 | dprintk(1, "set mode done chn %lu, %d\n", chn, res); |
| 1215 | 1242 | ||
| 1216 | /* wait at least 3 frames before continuing */ | 1243 | /* wait at least 3 frames before continuing */ |
| 1217 | if (mode->restart) | 1244 | if (mode->restart) { |
| 1218 | msleep(125); | 1245 | dev->setmode_ready[chn] = 0; |
| 1246 | wait_event_timeout(dev->wait_setmode[chn], | ||
| 1247 | (dev->setmode_ready[chn] != 0), | ||
| 1248 | msecs_to_jiffies(S2255_SETMODE_TIMEOUT)); | ||
| 1249 | if (dev->setmode_ready[chn] != 1) { | ||
| 1250 | printk(KERN_DEBUG "s2255: no set mode response\n"); | ||
| 1251 | res = -EFAULT; | ||
| 1252 | } | ||
| 1253 | } | ||
| 1219 | 1254 | ||
| 1220 | /* clear the restart flag */ | 1255 | /* clear the restart flag */ |
| 1221 | dev->mode[chn].restart = 0; | 1256 | dev->mode[chn].restart = 0; |
| 1222 | 1257 | mutex_unlock(&dev->lock); | |
| 1223 | return res; | 1258 | return res; |
| 1224 | } | 1259 | } |
| 1225 | 1260 | ||
| @@ -1270,7 +1305,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
| 1270 | dev->cur_frame[chn] = 0; | 1305 | dev->cur_frame[chn] = 0; |
| 1271 | dev->frame_count[chn] = 0; | 1306 | dev->frame_count[chn] = 0; |
| 1272 | for (j = 0; j < SYS_FRAMES; j++) { | 1307 | for (j = 0; j < SYS_FRAMES; j++) { |
| 1273 | dev->buffer[chn].frame[j].ulState = 0; | 1308 | dev->buffer[chn].frame[j].ulState = S2255_READ_IDLE; |
| 1274 | dev->buffer[chn].frame[j].cur_size = 0; | 1309 | dev->buffer[chn].frame[j].cur_size = 0; |
| 1275 | } | 1310 | } |
| 1276 | res = videobuf_streamon(&fh->vb_vidq); | 1311 | res = videobuf_streamon(&fh->vb_vidq); |
| @@ -1446,6 +1481,27 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
| 1446 | return -EINVAL; | 1481 | return -EINVAL; |
| 1447 | } | 1482 | } |
| 1448 | 1483 | ||
| 1484 | static int vidioc_g_jpegcomp(struct file *file, void *priv, | ||
| 1485 | struct v4l2_jpegcompression *jc) | ||
| 1486 | { | ||
| 1487 | struct s2255_fh *fh = priv; | ||
| 1488 | struct s2255_dev *dev = fh->dev; | ||
| 1489 | *jc = dev->jc[fh->channel]; | ||
| 1490 | dprintk(2, "getting jpegcompression, quality %d\n", jc->quality); | ||
| 1491 | return 0; | ||
| 1492 | } | ||
| 1493 | |||
| 1494 | static int vidioc_s_jpegcomp(struct file *file, void *priv, | ||
| 1495 | struct v4l2_jpegcompression *jc) | ||
| 1496 | { | ||
| 1497 | struct s2255_fh *fh = priv; | ||
| 1498 | struct s2255_dev *dev = fh->dev; | ||
| 1499 | if (jc->quality < 0 || jc->quality > 100) | ||
| 1500 | return -EINVAL; | ||
| 1501 | dev->jc[fh->channel].quality = jc->quality; | ||
| 1502 | dprintk(2, "setting jpeg quality %d\n", jc->quality); | ||
| 1503 | return 0; | ||
| 1504 | } | ||
| 1449 | static int s2255_open(struct inode *inode, struct file *file) | 1505 | static int s2255_open(struct inode *inode, struct file *file) |
| 1450 | { | 1506 | { |
| 1451 | int minor = iminor(inode); | 1507 | int minor = iminor(inode); |
| @@ -1455,8 +1511,10 @@ static int s2255_open(struct inode *inode, struct file *file) | |||
| 1455 | enum v4l2_buf_type type = 0; | 1511 | enum v4l2_buf_type type = 0; |
| 1456 | int i = 0; | 1512 | int i = 0; |
| 1457 | int cur_channel = -1; | 1513 | int cur_channel = -1; |
| 1514 | int state; | ||
| 1458 | dprintk(1, "s2255: open called (minor=%d)\n", minor); | 1515 | dprintk(1, "s2255: open called (minor=%d)\n", minor); |
| 1459 | 1516 | ||
| 1517 | lock_kernel(); | ||
| 1460 | list_for_each(list, &s2255_devlist) { | 1518 | list_for_each(list, &s2255_devlist) { |
| 1461 | h = list_entry(list, struct s2255_dev, s2255_devlist); | 1519 | h = list_entry(list, struct s2255_dev, s2255_devlist); |
| 1462 | for (i = 0; i < MAX_CHANNELS; i++) { | 1520 | for (i = 0; i < MAX_CHANNELS; i++) { |
| @@ -1469,45 +1527,78 @@ static int s2255_open(struct inode *inode, struct file *file) | |||
| 1469 | } | 1527 | } |
| 1470 | 1528 | ||
| 1471 | if ((NULL == dev) || (cur_channel == -1)) { | 1529 | if ((NULL == dev) || (cur_channel == -1)) { |
| 1472 | dprintk(1, "s2255: openv4l no dev\n"); | 1530 | unlock_kernel(); |
| 1531 | printk(KERN_INFO "s2255: openv4l no dev\n"); | ||
| 1473 | return -ENODEV; | 1532 | return -ENODEV; |
| 1474 | } | 1533 | } |
| 1475 | 1534 | ||
| 1535 | if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) { | ||
| 1536 | unlock_kernel(); | ||
| 1537 | printk(KERN_INFO "disconnecting\n"); | ||
| 1538 | return -ENODEV; | ||
| 1539 | } | ||
| 1540 | kref_get(&dev->kref); | ||
| 1476 | mutex_lock(&dev->open_lock); | 1541 | mutex_lock(&dev->open_lock); |
| 1477 | 1542 | ||
| 1478 | dev->users[cur_channel]++; | 1543 | dev->users[cur_channel]++; |
| 1479 | dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]); | 1544 | dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]); |
| 1480 | 1545 | ||
| 1481 | if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) { | 1546 | switch (atomic_read(&dev->fw_data->fw_state)) { |
| 1547 | case S2255_FW_FAILED: | ||
| 1482 | err("2255 firmware load failed. retrying.\n"); | 1548 | err("2255 firmware load failed. retrying.\n"); |
| 1483 | s2255_fwload_start(dev); | 1549 | s2255_fwload_start(dev, 1); |
| 1484 | wait_event_timeout(dev->fw_data->wait_fw, | 1550 | wait_event_timeout(dev->fw_data->wait_fw, |
| 1485 | (atomic_read(&dev->fw_data->fw_state) | 1551 | ((atomic_read(&dev->fw_data->fw_state) |
| 1486 | != S2255_FW_NOTLOADED), | 1552 | == S2255_FW_SUCCESS) || |
| 1553 | (atomic_read(&dev->fw_data->fw_state) | ||
| 1554 | == S2255_FW_DISCONNECTING)), | ||
| 1487 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); | 1555 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); |
| 1488 | if (atomic_read(&dev->fw_data->fw_state) | 1556 | break; |
| 1489 | != S2255_FW_SUCCESS) { | 1557 | case S2255_FW_NOTLOADED: |
| 1490 | printk(KERN_INFO "2255 FW load failed.\n"); | 1558 | case S2255_FW_LOADED_DSPWAIT: |
| 1491 | dev->users[cur_channel]--; | ||
| 1492 | mutex_unlock(&dev->open_lock); | ||
| 1493 | return -EFAULT; | ||
| 1494 | } | ||
| 1495 | } else if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_NOTLOADED) { | ||
| 1496 | /* give S2255_LOAD_TIMEOUT time for firmware to load in case | 1559 | /* give S2255_LOAD_TIMEOUT time for firmware to load in case |
| 1497 | driver loaded and then device immediately opened */ | 1560 | driver loaded and then device immediately opened */ |
| 1498 | printk(KERN_INFO "%s waiting for firmware load\n", __func__); | 1561 | printk(KERN_INFO "%s waiting for firmware load\n", __func__); |
| 1499 | wait_event_timeout(dev->fw_data->wait_fw, | 1562 | wait_event_timeout(dev->fw_data->wait_fw, |
| 1500 | (atomic_read(&dev->fw_data->fw_state) | 1563 | ((atomic_read(&dev->fw_data->fw_state) |
| 1501 | != S2255_FW_NOTLOADED), | 1564 | == S2255_FW_SUCCESS) || |
| 1502 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); | 1565 | (atomic_read(&dev->fw_data->fw_state) |
| 1503 | if (atomic_read(&dev->fw_data->fw_state) | 1566 | == S2255_FW_DISCONNECTING)), |
| 1504 | != S2255_FW_SUCCESS) { | 1567 | msecs_to_jiffies(S2255_LOAD_TIMEOUT)); |
| 1505 | printk(KERN_INFO "2255 firmware not loaded" | 1568 | break; |
| 1506 | "try again\n"); | 1569 | case S2255_FW_SUCCESS: |
| 1507 | dev->users[cur_channel]--; | 1570 | default: |
| 1508 | mutex_unlock(&dev->open_lock); | 1571 | break; |
| 1509 | return -EBUSY; | 1572 | } |
| 1573 | state = atomic_read(&dev->fw_data->fw_state); | ||
| 1574 | if (state != S2255_FW_SUCCESS) { | ||
| 1575 | int rc; | ||
| 1576 | switch (state) { | ||
| 1577 | case S2255_FW_FAILED: | ||
| 1578 | printk(KERN_INFO "2255 FW load failed. %d\n", state); | ||
| 1579 | rc = -ENODEV; | ||
| 1580 | break; | ||
| 1581 | case S2255_FW_DISCONNECTING: | ||
| 1582 | printk(KERN_INFO "%s: disconnecting\n", __func__); | ||
| 1583 | rc = -ENODEV; | ||
| 1584 | break; | ||
| 1585 | case S2255_FW_LOADED_DSPWAIT: | ||
| 1586 | case S2255_FW_NOTLOADED: | ||
| 1587 | printk(KERN_INFO "%s: firmware not loaded yet" | ||
| 1588 | "please try again later\n", | ||
| 1589 | __func__); | ||
| 1590 | rc = -EAGAIN; | ||
| 1591 | break; | ||
| 1592 | default: | ||
| 1593 | printk(KERN_INFO "%s: unknown state\n", __func__); | ||
| 1594 | rc = -EFAULT; | ||
| 1595 | break; | ||
| 1510 | } | 1596 | } |
| 1597 | dev->users[cur_channel]--; | ||
| 1598 | mutex_unlock(&dev->open_lock); | ||
| 1599 | kref_put(&dev->kref, s2255_destroy); | ||
| 1600 | unlock_kernel(); | ||
| 1601 | return rc; | ||
| 1511 | } | 1602 | } |
| 1512 | 1603 | ||
| 1513 | /* allocate + initialize per filehandle data */ | 1604 | /* allocate + initialize per filehandle data */ |
| @@ -1515,6 +1606,8 @@ static int s2255_open(struct inode *inode, struct file *file) | |||
| 1515 | if (NULL == fh) { | 1606 | if (NULL == fh) { |
| 1516 | dev->users[cur_channel]--; | 1607 | dev->users[cur_channel]--; |
| 1517 | mutex_unlock(&dev->open_lock); | 1608 | mutex_unlock(&dev->open_lock); |
| 1609 | kref_put(&dev->kref, s2255_destroy); | ||
| 1610 | unlock_kernel(); | ||
| 1518 | return -ENOMEM; | 1611 | return -ENOMEM; |
| 1519 | } | 1612 | } |
| 1520 | 1613 | ||
| @@ -1528,6 +1621,13 @@ static int s2255_open(struct inode *inode, struct file *file) | |||
| 1528 | fh->height = NUM_LINES_4CIFS_NTSC * 2; | 1621 | fh->height = NUM_LINES_4CIFS_NTSC * 2; |
| 1529 | fh->channel = cur_channel; | 1622 | fh->channel = cur_channel; |
| 1530 | 1623 | ||
| 1624 | /* configure channel to default state */ | ||
| 1625 | if (!dev->chn_configured[cur_channel]) { | ||
| 1626 | s2255_set_mode(dev, cur_channel, &fh->mode); | ||
| 1627 | dev->chn_configured[cur_channel] = 1; | ||
| 1628 | } | ||
| 1629 | |||
| 1630 | |||
| 1531 | /* Put all controls at a sane state */ | 1631 | /* Put all controls at a sane state */ |
| 1532 | for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) | 1632 | for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) |
| 1533 | qctl_regs[i] = s2255_qctrl[i].default_value; | 1633 | qctl_regs[i] = s2255_qctrl[i].default_value; |
| @@ -1546,8 +1646,8 @@ static int s2255_open(struct inode *inode, struct file *file) | |||
| 1546 | V4L2_FIELD_INTERLACED, | 1646 | V4L2_FIELD_INTERLACED, |
| 1547 | sizeof(struct s2255_buffer), fh); | 1647 | sizeof(struct s2255_buffer), fh); |
| 1548 | 1648 | ||
| 1549 | kref_get(&dev->kref); | ||
| 1550 | mutex_unlock(&dev->open_lock); | 1649 | mutex_unlock(&dev->open_lock); |
| 1650 | unlock_kernel(); | ||
| 1551 | return 0; | 1651 | return 0; |
| 1552 | } | 1652 | } |
| 1553 | 1653 | ||
| @@ -1569,30 +1669,24 @@ static unsigned int s2255_poll(struct file *file, | |||
| 1569 | static void s2255_destroy(struct kref *kref) | 1669 | static void s2255_destroy(struct kref *kref) |
| 1570 | { | 1670 | { |
| 1571 | struct s2255_dev *dev = to_s2255_dev(kref); | 1671 | struct s2255_dev *dev = to_s2255_dev(kref); |
| 1672 | struct list_head *list; | ||
| 1673 | int i; | ||
| 1572 | if (!dev) { | 1674 | if (!dev) { |
| 1573 | printk(KERN_ERR "s2255drv: kref problem\n"); | 1675 | printk(KERN_ERR "s2255drv: kref problem\n"); |
| 1574 | return; | 1676 | return; |
| 1575 | } | 1677 | } |
| 1576 | |||
| 1577 | /* | ||
| 1578 | * Wake up any firmware load waiting (only done in .open, | ||
| 1579 | * which holds the open_lock mutex) | ||
| 1580 | */ | ||
| 1581 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); | 1678 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); |
| 1582 | wake_up(&dev->fw_data->wait_fw); | 1679 | wake_up(&dev->fw_data->wait_fw); |
| 1583 | 1680 | for (i = 0; i < MAX_CHANNELS; i++) { | |
| 1584 | /* prevent s2255_disconnect from racing s2255_open */ | 1681 | dev->setmode_ready[i] = 1; |
| 1682 | wake_up(&dev->wait_setmode[i]); | ||
| 1683 | } | ||
| 1585 | mutex_lock(&dev->open_lock); | 1684 | mutex_lock(&dev->open_lock); |
| 1685 | /* reset the DSP so firmware can be reload next time */ | ||
| 1686 | s2255_reset_dsppower(dev); | ||
| 1586 | s2255_exit_v4l(dev); | 1687 | s2255_exit_v4l(dev); |
| 1587 | /* | ||
| 1588 | * device unregistered so no longer possible to open. open_mutex | ||
| 1589 | * can be unlocked and timers deleted afterwards. | ||
| 1590 | */ | ||
| 1591 | mutex_unlock(&dev->open_lock); | ||
| 1592 | |||
| 1593 | /* board shutdown stops the read pipe if it is running */ | 1688 | /* board shutdown stops the read pipe if it is running */ |
| 1594 | s2255_board_shutdown(dev); | 1689 | s2255_board_shutdown(dev); |
| 1595 | |||
| 1596 | /* make sure firmware still not trying to load */ | 1690 | /* make sure firmware still not trying to load */ |
| 1597 | del_timer(&dev->timer); /* only started in .probe and .open */ | 1691 | del_timer(&dev->timer); /* only started in .probe and .open */ |
| 1598 | 1692 | ||
| @@ -1602,23 +1696,19 @@ static void s2255_destroy(struct kref *kref) | |||
| 1602 | usb_free_urb(dev->fw_data->fw_urb); | 1696 | usb_free_urb(dev->fw_data->fw_urb); |
| 1603 | dev->fw_data->fw_urb = NULL; | 1697 | dev->fw_data->fw_urb = NULL; |
| 1604 | } | 1698 | } |
| 1605 | |||
| 1606 | /* | ||
| 1607 | * delete the dsp_wait timer, which sets the firmware | ||
| 1608 | * state on completion. This is done before fw_data | ||
| 1609 | * is freed below. | ||
| 1610 | */ | ||
| 1611 | |||
| 1612 | del_timer(&dev->fw_data->dsp_wait); /* only started in .open */ | ||
| 1613 | |||
| 1614 | if (dev->fw_data->fw) | 1699 | if (dev->fw_data->fw) |
| 1615 | release_firmware(dev->fw_data->fw); | 1700 | release_firmware(dev->fw_data->fw); |
| 1616 | kfree(dev->fw_data->pfw_data); | 1701 | kfree(dev->fw_data->pfw_data); |
| 1617 | kfree(dev->fw_data); | 1702 | kfree(dev->fw_data); |
| 1618 | |||
| 1619 | usb_put_dev(dev->udev); | 1703 | usb_put_dev(dev->udev); |
| 1620 | dprintk(1, "%s", __func__); | 1704 | dprintk(1, "%s", __func__); |
| 1621 | kfree(dev); | 1705 | kfree(dev); |
| 1706 | |||
| 1707 | while (!list_empty(&s2255_devlist)) { | ||
| 1708 | list = s2255_devlist.next; | ||
| 1709 | list_del(list); | ||
| 1710 | } | ||
| 1711 | mutex_unlock(&dev->open_lock); | ||
| 1622 | } | 1712 | } |
| 1623 | 1713 | ||
| 1624 | static int s2255_close(struct inode *inode, struct file *file) | 1714 | static int s2255_close(struct inode *inode, struct file *file) |
| @@ -1702,6 +1792,8 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = { | |||
| 1702 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1792 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
| 1703 | .vidiocgmbuf = vidioc_cgmbuf, | 1793 | .vidiocgmbuf = vidioc_cgmbuf, |
| 1704 | #endif | 1794 | #endif |
| 1795 | .vidioc_s_jpegcomp = vidioc_s_jpegcomp, | ||
| 1796 | .vidioc_g_jpegcomp = vidioc_g_jpegcomp, | ||
| 1705 | }; | 1797 | }; |
| 1706 | 1798 | ||
| 1707 | static struct video_device template = { | 1799 | static struct video_device template = { |
| @@ -1740,7 +1832,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
| 1740 | ret = video_register_device(dev->vdev[i], | 1832 | ret = video_register_device(dev->vdev[i], |
| 1741 | VFL_TYPE_GRABBER, | 1833 | VFL_TYPE_GRABBER, |
| 1742 | cur_nr + i); | 1834 | cur_nr + i); |
| 1743 | dev->vdev[i]->priv = dev; | 1835 | video_set_drvdata(dev->vdev[i], dev); |
| 1744 | 1836 | ||
| 1745 | if (ret != 0) { | 1837 | if (ret != 0) { |
| 1746 | dev_err(&dev->udev->dev, | 1838 | dev_err(&dev->udev->dev, |
| @@ -1754,18 +1846,16 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
| 1754 | 1846 | ||
| 1755 | static void s2255_exit_v4l(struct s2255_dev *dev) | 1847 | static void s2255_exit_v4l(struct s2255_dev *dev) |
| 1756 | { | 1848 | { |
| 1757 | struct list_head *list; | 1849 | |
| 1758 | int i; | 1850 | int i; |
| 1759 | /* unregister the video devices */ | ||
| 1760 | while (!list_empty(&s2255_devlist)) { | ||
| 1761 | list = s2255_devlist.next; | ||
| 1762 | list_del(list); | ||
| 1763 | } | ||
| 1764 | for (i = 0; i < MAX_CHANNELS; i++) { | 1851 | for (i = 0; i < MAX_CHANNELS; i++) { |
| 1765 | if (-1 != dev->vdev[i]->minor) | 1852 | if (-1 != dev->vdev[i]->minor) { |
| 1766 | video_unregister_device(dev->vdev[i]); | 1853 | video_unregister_device(dev->vdev[i]); |
| 1767 | else | 1854 | printk(KERN_INFO "s2255 unregistered\n"); |
| 1855 | } else { | ||
| 1768 | video_device_release(dev->vdev[i]); | 1856 | video_device_release(dev->vdev[i]); |
| 1857 | printk(KERN_INFO "s2255 released\n"); | ||
| 1858 | } | ||
| 1769 | } | 1859 | } |
| 1770 | } | 1860 | } |
| 1771 | 1861 | ||
| @@ -1775,134 +1865,123 @@ static void s2255_exit_v4l(struct s2255_dev *dev) | |||
| 1775 | * function again). | 1865 | * function again). |
| 1776 | * | 1866 | * |
| 1777 | * Received frame structure: | 1867 | * Received frame structure: |
| 1778 | * bytes 0-3: marker : 0x2255DA4AL (FRAME_MARKER) | 1868 | * bytes 0-3: marker : 0x2255DA4AL (S2255_MARKER_FRAME) |
| 1779 | * bytes 4-7: channel: 0-3 | 1869 | * bytes 4-7: channel: 0-3 |
| 1780 | * bytes 8-11: payload size: size of the frame | 1870 | * bytes 8-11: payload size: size of the frame |
| 1781 | * bytes 12-payloadsize+12: frame data | 1871 | * bytes 12-payloadsize+12: frame data |
| 1782 | */ | 1872 | */ |
| 1783 | static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | 1873 | static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) |
| 1784 | { | 1874 | { |
| 1785 | static int dbgsync; /* = 0; */ | ||
| 1786 | char *pdest; | 1875 | char *pdest; |
| 1787 | u32 offset = 0; | 1876 | u32 offset = 0; |
| 1788 | int bsync = 0; | 1877 | int bframe = 0; |
| 1789 | int btrunc = 0; | ||
| 1790 | char *psrc; | 1878 | char *psrc; |
| 1791 | unsigned long copy_size; | 1879 | unsigned long copy_size; |
| 1792 | unsigned long size; | 1880 | unsigned long size; |
| 1793 | s32 idx = -1; | 1881 | s32 idx = -1; |
| 1794 | struct s2255_framei *frm; | 1882 | struct s2255_framei *frm; |
| 1795 | unsigned char *pdata; | 1883 | unsigned char *pdata; |
| 1796 | unsigned long cur_size; | 1884 | |
| 1797 | int bsearch = 0; | ||
| 1798 | struct s2255_bufferi *buf; | ||
| 1799 | dprintk(100, "buffer to user\n"); | 1885 | dprintk(100, "buffer to user\n"); |
| 1800 | 1886 | ||
| 1801 | idx = dev->cur_frame[dev->cc]; | 1887 | idx = dev->cur_frame[dev->cc]; |
| 1802 | buf = &dev->buffer[dev->cc]; | 1888 | frm = &dev->buffer[dev->cc].frame[idx]; |
| 1803 | frm = &buf->frame[idx]; | ||
| 1804 | |||
| 1805 | if (frm->ulState == 0) { | ||
| 1806 | frm->ulState = 1; | ||
| 1807 | frm->cur_size = 0; | ||
| 1808 | bsearch = 1; | ||
| 1809 | } else if (frm->ulState == 2) { | ||
| 1810 | /* system frame was not freed */ | ||
| 1811 | dprintk(2, "sys frame not free. overrun ringbuf\n"); | ||
| 1812 | bsearch = 1; | ||
| 1813 | frm->ulState = 1; | ||
| 1814 | frm->cur_size = 0; | ||
| 1815 | } | ||
| 1816 | |||
| 1817 | if (bsearch) { | ||
| 1818 | if (*(s32 *) pipe_info->transfer_buffer != FRAME_MARKER) { | ||
| 1819 | u32 jj; | ||
| 1820 | if (dbgsync == 0) { | ||
| 1821 | dprintk(3, "not synched, discarding all packets" | ||
| 1822 | "until marker\n"); | ||
| 1823 | 1889 | ||
| 1824 | dbgsync++; | 1890 | if (frm->ulState == S2255_READ_IDLE) { |
| 1825 | } | 1891 | int jj; |
| 1826 | pdata = (unsigned char *)pipe_info->transfer_buffer; | 1892 | unsigned int cc; |
| 1827 | for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); | 1893 | s32 *pdword; |
| 1828 | jj++) { | 1894 | int payload; |
| 1829 | if (*(s32 *) pdata == FRAME_MARKER) { | 1895 | /* search for marker codes */ |
| 1830 | int cc; | 1896 | pdata = (unsigned char *)pipe_info->transfer_buffer; |
| 1831 | dprintk(3, | 1897 | for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) { |
| 1832 | "found frame marker at offset:" | 1898 | switch (*(s32 *) pdata) { |
| 1833 | " %d [%x %x]\n", jj, pdata[0], | 1899 | case S2255_MARKER_FRAME: |
| 1834 | pdata[1]); | 1900 | pdword = (s32 *)pdata; |
| 1835 | offset = jj; | 1901 | dprintk(4, "found frame marker at offset:" |
| 1836 | bsync = 1; | 1902 | " %d [%x %x]\n", jj, pdata[0], |
| 1837 | cc = *(u32 *) (pdata + sizeof(u32)); | 1903 | pdata[1]); |
| 1838 | if (cc >= MAX_CHANNELS) { | 1904 | offset = jj + PREFIX_SIZE; |
| 1839 | printk(KERN_ERR | 1905 | bframe = 1; |
| 1840 | "bad channel\n"); | 1906 | cc = pdword[1]; |
| 1841 | return -EINVAL; | 1907 | if (cc >= MAX_CHANNELS) { |
| 1842 | } | 1908 | printk(KERN_ERR |
| 1843 | /* reverse it */ | 1909 | "bad channel\n"); |
| 1844 | dev->cc = G_chnmap[cc]; | 1910 | return -EINVAL; |
| 1911 | } | ||
| 1912 | /* reverse it */ | ||
| 1913 | dev->cc = G_chnmap[cc]; | ||
| 1914 | payload = pdword[3]; | ||
| 1915 | if (payload > dev->req_image_size[dev->cc]) { | ||
| 1916 | dev->bad_payload[dev->cc]++; | ||
| 1917 | /* discard the bad frame */ | ||
| 1918 | return -EINVAL; | ||
| 1919 | } | ||
| 1920 | dev->pkt_size[dev->cc] = payload; | ||
| 1921 | dev->jpg_size[dev->cc] = pdword[4]; | ||
| 1922 | break; | ||
| 1923 | case S2255_MARKER_RESPONSE: | ||
| 1924 | pdword = (s32 *)pdata; | ||
| 1925 | pdata += DEF_USB_BLOCK; | ||
| 1926 | jj += DEF_USB_BLOCK; | ||
| 1927 | if (pdword[1] >= MAX_CHANNELS) | ||
| 1928 | break; | ||
| 1929 | cc = G_chnmap[pdword[1]]; | ||
| 1930 | if (!(cc >= 0 && cc < MAX_CHANNELS)) | ||
| 1931 | break; | ||
| 1932 | switch (pdword[2]) { | ||
| 1933 | case 0x01: | ||
| 1934 | /* check if channel valid */ | ||
| 1935 | /* set mode ready */ | ||
| 1936 | dev->setmode_ready[cc] = 1; | ||
| 1937 | wake_up(&dev->wait_setmode[cc]); | ||
| 1938 | dprintk(5, "setmode ready %d\n", cc); | ||
| 1845 | break; | 1939 | break; |
| 1940 | case 0x10: | ||
| 1941 | |||
| 1942 | dev->chn_ready |= (1 << cc); | ||
| 1943 | if ((dev->chn_ready & 0x0f) != 0x0f) | ||
| 1944 | break; | ||
| 1945 | /* all channels ready */ | ||
| 1946 | printk(KERN_INFO "s2255: fw loaded\n"); | ||
| 1947 | atomic_set(&dev->fw_data->fw_state, | ||
| 1948 | S2255_FW_SUCCESS); | ||
| 1949 | wake_up(&dev->fw_data->wait_fw); | ||
| 1950 | break; | ||
| 1951 | default: | ||
| 1952 | printk(KERN_INFO "s2255 unknwn resp\n"); | ||
| 1846 | } | 1953 | } |
| 1954 | default: | ||
| 1847 | pdata++; | 1955 | pdata++; |
| 1956 | break; | ||
| 1848 | } | 1957 | } |
| 1849 | if (bsync == 0) | 1958 | if (bframe) |
| 1850 | return -EINVAL; | 1959 | break; |
| 1851 | } else { | 1960 | } /* for */ |
| 1852 | u32 *pword; | 1961 | if (!bframe) |
| 1853 | u32 payload; | 1962 | return -EINVAL; |
| 1854 | int cc; | ||
| 1855 | dbgsync = 0; | ||
| 1856 | bsync = 1; | ||
| 1857 | pword = (u32 *) pipe_info->transfer_buffer; | ||
| 1858 | cc = pword[1]; | ||
| 1859 | |||
| 1860 | if (cc >= MAX_CHANNELS) { | ||
| 1861 | printk("invalid channel found. " | ||
| 1862 | "throwing out data!\n"); | ||
| 1863 | return -EINVAL; | ||
| 1864 | } | ||
| 1865 | dev->cc = G_chnmap[cc]; | ||
| 1866 | payload = pword[2]; | ||
| 1867 | if (payload != dev->req_image_size[dev->cc]) { | ||
| 1868 | dprintk(1, "[%d][%d]unexpected payload: %d" | ||
| 1869 | "required: %lu \n", cc, dev->cc, | ||
| 1870 | payload, dev->req_image_size[dev->cc]); | ||
| 1871 | dev->bad_payload[dev->cc]++; | ||
| 1872 | /* discard the bad frame */ | ||
| 1873 | return -EINVAL; | ||
| 1874 | } | ||
| 1875 | |||
| 1876 | } | ||
| 1877 | } | ||
| 1878 | /* search done. now find out if should be acquiring | ||
| 1879 | on this channel */ | ||
| 1880 | if (!dev->b_acquire[dev->cc]) { | ||
| 1881 | frm->ulState = 0; | ||
| 1882 | return -EINVAL; | ||
| 1883 | } | 1963 | } |
| 1884 | 1964 | ||
| 1965 | |||
| 1885 | idx = dev->cur_frame[dev->cc]; | 1966 | idx = dev->cur_frame[dev->cc]; |
| 1886 | frm = &dev->buffer[dev->cc].frame[idx]; | 1967 | frm = &dev->buffer[dev->cc].frame[idx]; |
| 1887 | 1968 | ||
| 1888 | if (frm->ulState == 0) { | 1969 | /* search done. now find out if should be acquiring on this channel */ |
| 1889 | frm->ulState = 1; | 1970 | if (!dev->b_acquire[dev->cc]) { |
| 1890 | frm->cur_size = 0; | 1971 | /* we found a frame, but this channel is turned off */ |
| 1891 | } else if (frm->ulState == 2) { | 1972 | frm->ulState = S2255_READ_IDLE; |
| 1892 | /* system frame ring buffer overrun */ | 1973 | return -EINVAL; |
| 1893 | dprintk(2, "sys frame overrun. overwriting frame %d %d\n", | ||
| 1894 | dev->cc, idx); | ||
| 1895 | frm->ulState = 1; | ||
| 1896 | frm->cur_size = 0; | ||
| 1897 | } | 1974 | } |
| 1898 | 1975 | ||
| 1899 | if (bsync) { | 1976 | if (frm->ulState == S2255_READ_IDLE) { |
| 1900 | /* skip the marker 512 bytes (and offset if out of sync) */ | 1977 | frm->ulState = S2255_READ_FRAME; |
| 1901 | psrc = (u8 *)pipe_info->transfer_buffer + offset + PREFIX_SIZE; | 1978 | frm->cur_size = 0; |
| 1902 | } else { | ||
| 1903 | psrc = (u8 *)pipe_info->transfer_buffer; | ||
| 1904 | } | 1979 | } |
| 1905 | 1980 | ||
| 1981 | /* skip the marker 512 bytes (and offset if out of sync) */ | ||
| 1982 | psrc = (u8 *)pipe_info->transfer_buffer + offset; | ||
| 1983 | |||
| 1984 | |||
| 1906 | if (frm->lpvbits == NULL) { | 1985 | if (frm->lpvbits == NULL) { |
| 1907 | dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d", | 1986 | dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d", |
| 1908 | frm, dev, dev->cc, idx); | 1987 | frm, dev, dev->cc, idx); |
| @@ -1911,33 +1990,20 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
| 1911 | 1990 | ||
| 1912 | pdest = frm->lpvbits + frm->cur_size; | 1991 | pdest = frm->lpvbits + frm->cur_size; |
| 1913 | 1992 | ||
| 1914 | if (bsync) { | 1993 | copy_size = (pipe_info->cur_transfer_size - offset); |
| 1915 | copy_size = | ||
| 1916 | (pipe_info->cur_transfer_size - offset) - PREFIX_SIZE; | ||
| 1917 | if (copy_size > pipe_info->cur_transfer_size) { | ||
| 1918 | printk("invalid copy size, overflow!\n"); | ||
| 1919 | return -ENOMEM; | ||
| 1920 | } | ||
| 1921 | } else { | ||
| 1922 | copy_size = pipe_info->cur_transfer_size; | ||
| 1923 | } | ||
| 1924 | 1994 | ||
| 1925 | cur_size = frm->cur_size; | 1995 | size = dev->pkt_size[dev->cc] - PREFIX_SIZE; |
| 1926 | size = dev->req_image_size[dev->cc]; | ||
| 1927 | 1996 | ||
| 1928 | if ((copy_size + cur_size) > size) { | 1997 | /* sanity check on pdest */ |
| 1929 | copy_size = size - cur_size; | 1998 | if ((copy_size + frm->cur_size) < dev->req_image_size[dev->cc]) |
| 1930 | btrunc = 1; | 1999 | memcpy(pdest, psrc, copy_size); |
| 1931 | } | ||
| 1932 | 2000 | ||
| 1933 | memcpy(pdest, psrc, copy_size); | ||
| 1934 | cur_size += copy_size; | ||
| 1935 | frm->cur_size += copy_size; | 2001 | frm->cur_size += copy_size; |
| 1936 | dprintk(50, "cur_size size %lu size %lu \n", cur_size, size); | 2002 | dprintk(4, "cur_size size %lu size %lu \n", frm->cur_size, size); |
| 2003 | |||
| 2004 | if (frm->cur_size >= size) { | ||
| 1937 | 2005 | ||
| 1938 | if (cur_size >= (size - PREFIX_SIZE)) { | ||
| 1939 | u32 cc = dev->cc; | 2006 | u32 cc = dev->cc; |
| 1940 | frm->ulState = 2; | ||
| 1941 | dprintk(2, "****************[%d]Buffer[%d]full*************\n", | 2007 | dprintk(2, "****************[%d]Buffer[%d]full*************\n", |
| 1942 | cc, idx); | 2008 | cc, idx); |
| 1943 | dev->last_frame[cc] = dev->cur_frame[cc]; | 2009 | dev->last_frame[cc] = dev->cur_frame[cc]; |
| @@ -1946,16 +2012,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
| 1946 | if ((dev->cur_frame[cc] == SYS_FRAMES) || | 2012 | if ((dev->cur_frame[cc] == SYS_FRAMES) || |
| 1947 | (dev->cur_frame[cc] == dev->buffer[cc].dwFrames)) | 2013 | (dev->cur_frame[cc] == dev->buffer[cc].dwFrames)) |
| 1948 | dev->cur_frame[cc] = 0; | 2014 | dev->cur_frame[cc] = 0; |
| 1949 | 2015 | /* frame ready */ | |
| 1950 | /* signal the semaphore for this channel */ | ||
| 1951 | if (dev->b_acquire[cc]) | 2016 | if (dev->b_acquire[cc]) |
| 1952 | s2255_got_frame(dev, cc); | 2017 | s2255_got_frame(dev, cc, dev->jpg_size[cc]); |
| 1953 | dev->frame_count[cc]++; | 2018 | dev->frame_count[cc]++; |
| 1954 | } | 2019 | frm->ulState = S2255_READ_IDLE; |
| 1955 | /* frame was truncated */ | 2020 | frm->cur_size = 0; |
| 1956 | if (btrunc) { | 2021 | |
| 1957 | /* return more data to process */ | ||
| 1958 | return EAGAIN; | ||
| 1959 | } | 2022 | } |
| 1960 | /* done successfully */ | 2023 | /* done successfully */ |
| 1961 | return 0; | 2024 | return 0; |
| @@ -1974,8 +2037,8 @@ static void s2255_read_video_callback(struct s2255_dev *dev, | |||
| 1974 | } | 2037 | } |
| 1975 | /* otherwise copy to the system buffers */ | 2038 | /* otherwise copy to the system buffers */ |
| 1976 | res = save_frame(dev, pipe_info); | 2039 | res = save_frame(dev, pipe_info); |
| 1977 | if (res == EAGAIN) | 2040 | if (res != 0) |
| 1978 | save_frame(dev, pipe_info); | 2041 | dprintk(4, "s2255: read callback failed\n"); |
| 1979 | 2042 | ||
| 1980 | dprintk(50, "callback read video done\n"); | 2043 | dprintk(50, "callback read video done\n"); |
| 1981 | return; | 2044 | return; |
| @@ -2095,11 +2158,9 @@ static int s2255_board_init(struct s2255_dev *dev) | |||
| 2095 | 2158 | ||
| 2096 | memset(pipe, 0, sizeof(*pipe)); | 2159 | memset(pipe, 0, sizeof(*pipe)); |
| 2097 | pipe->dev = dev; | 2160 | pipe->dev = dev; |
| 2098 | pipe->cur_transfer_size = DEFAULT_PIPE_USBBLOCK; | 2161 | pipe->cur_transfer_size = S2255_USB_XFER_SIZE; |
| 2099 | pipe->max_transfer_size = MAX_PIPE_USBBLOCK; | 2162 | pipe->max_transfer_size = S2255_USB_XFER_SIZE; |
| 2100 | 2163 | ||
| 2101 | if (pipe->cur_transfer_size > pipe->max_transfer_size) | ||
| 2102 | pipe->cur_transfer_size = pipe->max_transfer_size; | ||
| 2103 | pipe->transfer_buffer = kzalloc(pipe->max_transfer_size, | 2164 | pipe->transfer_buffer = kzalloc(pipe->max_transfer_size, |
| 2104 | GFP_KERNEL); | 2165 | GFP_KERNEL); |
| 2105 | if (pipe->transfer_buffer == NULL) { | 2166 | if (pipe->transfer_buffer == NULL) { |
| @@ -2119,6 +2180,7 @@ static int s2255_board_init(struct s2255_dev *dev) | |||
| 2119 | for (j = 0; j < MAX_CHANNELS; j++) { | 2180 | for (j = 0; j < MAX_CHANNELS; j++) { |
| 2120 | dev->b_acquire[j] = 0; | 2181 | dev->b_acquire[j] = 0; |
| 2121 | dev->mode[j] = mode_def; | 2182 | dev->mode[j] = mode_def; |
| 2183 | dev->jc[j].quality = S2255_DEF_JPEG_QUAL; | ||
| 2122 | dev->cur_fmt[j] = &formats[0]; | 2184 | dev->cur_fmt[j] = &formats[0]; |
| 2123 | dev->mode[j].restart = 1; | 2185 | dev->mode[j].restart = 1; |
| 2124 | dev->req_image_size[j] = get_transfer_size(&mode_def); | 2186 | dev->req_image_size[j] = get_transfer_size(&mode_def); |
| @@ -2323,7 +2385,7 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn) | |||
| 2323 | kfree(buffer); | 2385 | kfree(buffer); |
| 2324 | dev->b_acquire[chn] = 0; | 2386 | dev->b_acquire[chn] = 0; |
| 2325 | 2387 | ||
| 2326 | return 0; | 2388 | return res; |
| 2327 | } | 2389 | } |
| 2328 | 2390 | ||
| 2329 | static void s2255_stop_readpipe(struct s2255_dev *dev) | 2391 | static void s2255_stop_readpipe(struct s2255_dev *dev) |
| @@ -2359,8 +2421,10 @@ static void s2255_stop_readpipe(struct s2255_dev *dev) | |||
| 2359 | return; | 2421 | return; |
| 2360 | } | 2422 | } |
| 2361 | 2423 | ||
| 2362 | static void s2255_fwload_start(struct s2255_dev *dev) | 2424 | static void s2255_fwload_start(struct s2255_dev *dev, int reset) |
| 2363 | { | 2425 | { |
| 2426 | if (reset) | ||
| 2427 | s2255_reset_dsppower(dev); | ||
| 2364 | dev->fw_data->fw_size = dev->fw_data->fw->size; | 2428 | dev->fw_data->fw_size = dev->fw_data->fw->size; |
| 2365 | atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED); | 2429 | atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED); |
| 2366 | memcpy(dev->fw_data->pfw_data, | 2430 | memcpy(dev->fw_data->pfw_data, |
| @@ -2383,6 +2447,8 @@ static int s2255_probe(struct usb_interface *interface, | |||
| 2383 | struct usb_endpoint_descriptor *endpoint; | 2447 | struct usb_endpoint_descriptor *endpoint; |
| 2384 | int i; | 2448 | int i; |
| 2385 | int retval = -ENOMEM; | 2449 | int retval = -ENOMEM; |
| 2450 | __le32 *pdata; | ||
| 2451 | int fw_size; | ||
| 2386 | 2452 | ||
| 2387 | dprintk(2, "s2255: probe\n"); | 2453 | dprintk(2, "s2255: probe\n"); |
| 2388 | 2454 | ||
| @@ -2437,6 +2503,8 @@ static int s2255_probe(struct usb_interface *interface, | |||
| 2437 | dev->timer.data = (unsigned long)dev->fw_data; | 2503 | dev->timer.data = (unsigned long)dev->fw_data; |
| 2438 | 2504 | ||
| 2439 | init_waitqueue_head(&dev->fw_data->wait_fw); | 2505 | init_waitqueue_head(&dev->fw_data->wait_fw); |
| 2506 | for (i = 0; i < MAX_CHANNELS; i++) | ||
| 2507 | init_waitqueue_head(&dev->wait_setmode[i]); | ||
| 2440 | 2508 | ||
| 2441 | 2509 | ||
| 2442 | dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); | 2510 | dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL); |
| @@ -2456,16 +2524,30 @@ static int s2255_probe(struct usb_interface *interface, | |||
| 2456 | printk(KERN_ERR "sensoray 2255 failed to get firmware\n"); | 2524 | printk(KERN_ERR "sensoray 2255 failed to get firmware\n"); |
| 2457 | goto error; | 2525 | goto error; |
| 2458 | } | 2526 | } |
| 2527 | /* check the firmware is valid */ | ||
| 2528 | fw_size = dev->fw_data->fw->size; | ||
| 2529 | pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8]; | ||
| 2459 | 2530 | ||
| 2531 | if (*pdata != S2255_FW_MARKER) { | ||
| 2532 | printk(KERN_INFO "Firmware invalid.\n"); | ||
| 2533 | retval = -ENODEV; | ||
| 2534 | goto error; | ||
| 2535 | } else { | ||
| 2536 | /* make sure firmware is the latest */ | ||
| 2537 | __le32 *pRel; | ||
| 2538 | pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; | ||
| 2539 | printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); | ||
| 2540 | } | ||
| 2460 | /* loads v4l specific */ | 2541 | /* loads v4l specific */ |
| 2461 | s2255_probe_v4l(dev); | 2542 | s2255_probe_v4l(dev); |
| 2543 | usb_reset_device(dev->udev); | ||
| 2462 | /* load 2255 board specific */ | 2544 | /* load 2255 board specific */ |
| 2463 | s2255_board_init(dev); | 2545 | s2255_board_init(dev); |
| 2464 | 2546 | ||
| 2465 | dprintk(4, "before probe done %p\n", dev); | 2547 | dprintk(4, "before probe done %p\n", dev); |
| 2466 | spin_lock_init(&dev->slock); | 2548 | spin_lock_init(&dev->slock); |
| 2467 | 2549 | ||
| 2468 | s2255_fwload_start(dev); | 2550 | s2255_fwload_start(dev, 0); |
| 2469 | dev_info(&interface->dev, "Sensoray 2255 detected\n"); | 2551 | dev_info(&interface->dev, "Sensoray 2255 detected\n"); |
| 2470 | return 0; | 2552 | return 0; |
| 2471 | error: | 2553 | error: |
| @@ -2476,14 +2558,30 @@ error: | |||
| 2476 | static void s2255_disconnect(struct usb_interface *interface) | 2558 | static void s2255_disconnect(struct usb_interface *interface) |
| 2477 | { | 2559 | { |
| 2478 | struct s2255_dev *dev = NULL; | 2560 | struct s2255_dev *dev = NULL; |
| 2561 | int i; | ||
| 2479 | dprintk(1, "s2255: disconnect interface %p\n", interface); | 2562 | dprintk(1, "s2255: disconnect interface %p\n", interface); |
| 2480 | dev = usb_get_intfdata(interface); | 2563 | dev = usb_get_intfdata(interface); |
| 2564 | |||
| 2565 | /* | ||
| 2566 | * wake up any of the timers to allow open_lock to be | ||
| 2567 | * acquired sooner | ||
| 2568 | */ | ||
| 2569 | atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING); | ||
| 2570 | wake_up(&dev->fw_data->wait_fw); | ||
| 2571 | for (i = 0; i < MAX_CHANNELS; i++) { | ||
| 2572 | dev->setmode_ready[i] = 1; | ||
| 2573 | wake_up(&dev->wait_setmode[i]); | ||
| 2574 | } | ||
| 2575 | |||
| 2576 | mutex_lock(&dev->open_lock); | ||
| 2577 | usb_set_intfdata(interface, NULL); | ||
| 2578 | mutex_unlock(&dev->open_lock); | ||
| 2579 | |||
| 2481 | if (dev) { | 2580 | if (dev) { |
| 2482 | kref_put(&dev->kref, s2255_destroy); | 2581 | kref_put(&dev->kref, s2255_destroy); |
| 2483 | dprintk(1, "s2255drv: disconnect\n"); | 2582 | dprintk(1, "s2255drv: disconnect\n"); |
| 2484 | dev_info(&interface->dev, "s2255usb now disconnected\n"); | 2583 | dev_info(&interface->dev, "s2255usb now disconnected\n"); |
| 2485 | } | 2584 | } |
| 2486 | usb_set_intfdata(interface, NULL); | ||
| 2487 | } | 2585 | } |
| 2488 | 2586 | ||
| 2489 | static struct usb_driver s2255_driver = { | 2587 | static struct usb_driver s2255_driver = { |
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index 6ee63e69b36c..4a21b8a6a709 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c | |||
| @@ -43,135 +43,363 @@ | |||
| 43 | #include <linux/mm.h> | 43 | #include <linux/mm.h> |
| 44 | #include <linux/init.h> | 44 | #include <linux/init.h> |
| 45 | #include <linux/i2c.h> | 45 | #include <linux/i2c.h> |
| 46 | #include <linux/smp_lock.h> | ||
| 47 | #include <linux/mutex.h> | ||
| 46 | #include <linux/videotext.h> | 48 | #include <linux/videotext.h> |
| 47 | #include <linux/videodev.h> | 49 | #include <linux/videodev.h> |
| 48 | #include <media/v4l2-common.h> | 50 | #include <media/v4l2-common.h> |
| 49 | #include <media/v4l2-ioctl.h> | 51 | #include <media/v4l2-ioctl.h> |
| 50 | #include <linux/mutex.h> | 52 | #include <media/v4l2-i2c-drv-legacy.h> |
| 51 | |||
| 52 | #include "saa5246a.h" | ||
| 53 | 53 | ||
| 54 | MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>"); | 54 | MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>"); |
| 55 | MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver"); | 55 | MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver"); |
| 56 | MODULE_LICENSE("GPL"); | 56 | MODULE_LICENSE("GPL"); |
| 57 | 57 | ||
| 58 | struct saa5246a_device | 58 | #define MAJOR_VERSION 1 /* driver major version number */ |
| 59 | { | 59 | #define MINOR_VERSION 8 /* driver minor version number */ |
| 60 | u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; | 60 | |
| 61 | int is_searching[NUM_DAUS]; | 61 | /* Number of DAUs = number of pages that can be searched at the same time. */ |
| 62 | struct i2c_client *client; | 62 | #define NUM_DAUS 4 |
| 63 | struct mutex lock; | 63 | |
| 64 | }; | 64 | #define NUM_ROWS_PER_PAGE 40 |
| 65 | |||
| 66 | /* first column is 0 (not 1) */ | ||
| 67 | #define POS_TIME_START 32 | ||
| 68 | #define POS_TIME_END 39 | ||
| 69 | |||
| 70 | #define POS_HEADER_START 7 | ||
| 71 | #define POS_HEADER_END 31 | ||
| 72 | |||
| 73 | /* Returns 'true' if the part of the videotext page described with req contains | ||
| 74 | (at least parts of) the time field */ | ||
| 75 | #define REQ_CONTAINS_TIME(p_req) \ | ||
| 76 | ((p_req)->start <= POS_TIME_END && \ | ||
| 77 | (p_req)->end >= POS_TIME_START) | ||
| 78 | |||
| 79 | /* Returns 'true' if the part of the videotext page described with req contains | ||
| 80 | (at least parts of) the page header */ | ||
| 81 | #define REQ_CONTAINS_HEADER(p_req) \ | ||
| 82 | ((p_req)->start <= POS_HEADER_END && \ | ||
| 83 | (p_req)->end >= POS_HEADER_START) | ||
| 84 | |||
| 85 | /*****************************************************************************/ | ||
| 86 | /* Mode register numbers of the SAA5246A */ | ||
| 87 | /*****************************************************************************/ | ||
| 88 | #define SAA5246A_REGISTER_R0 0 | ||
| 89 | #define SAA5246A_REGISTER_R1 1 | ||
| 90 | #define SAA5246A_REGISTER_R2 2 | ||
| 91 | #define SAA5246A_REGISTER_R3 3 | ||
| 92 | #define SAA5246A_REGISTER_R4 4 | ||
| 93 | #define SAA5246A_REGISTER_R5 5 | ||
| 94 | #define SAA5246A_REGISTER_R6 6 | ||
| 95 | #define SAA5246A_REGISTER_R7 7 | ||
| 96 | #define SAA5246A_REGISTER_R8 8 | ||
| 97 | #define SAA5246A_REGISTER_R9 9 | ||
| 98 | #define SAA5246A_REGISTER_R10 10 | ||
| 99 | #define SAA5246A_REGISTER_R11 11 | ||
| 100 | #define SAA5246A_REGISTER_R11B 11 | ||
| 101 | |||
| 102 | /* SAA5246A mode registers often autoincrement to the next register. | ||
| 103 | Therefore we use variable argument lists. The following macro indicates | ||
| 104 | the end of a command list. */ | ||
| 105 | #define COMMAND_END (-1) | ||
| 106 | |||
| 107 | /*****************************************************************************/ | ||
| 108 | /* Contents of the mode registers of the SAA5246A */ | ||
| 109 | /*****************************************************************************/ | ||
| 110 | /* Register R0 (Advanced Control) */ | ||
| 111 | #define R0_SELECT_R11 0x00 | ||
| 112 | #define R0_SELECT_R11B 0x01 | ||
| 113 | |||
| 114 | #define R0_PLL_TIME_CONSTANT_LONG 0x00 | ||
| 115 | #define R0_PLL_TIME_CONSTANT_SHORT 0x02 | ||
| 116 | |||
| 117 | #define R0_ENABLE_nODD_EVEN_OUTPUT 0x00 | ||
| 118 | #define R0_DISABLE_nODD_EVEN_OUTPUT 0x04 | ||
| 119 | |||
| 120 | #define R0_ENABLE_HDR_POLL 0x00 | ||
| 121 | #define R0_DISABLE_HDR_POLL 0x10 | ||
| 122 | |||
| 123 | #define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00 | ||
| 124 | #define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x20 | ||
| 125 | |||
| 126 | #define R0_NO_FREE_RUN_PLL 0x00 | ||
| 127 | #define R0_FREE_RUN_PLL 0x40 | ||
| 128 | |||
| 129 | #define R0_NO_AUTOMATIC_FASTEXT_PROMPT 0x00 | ||
| 130 | #define R0_AUTOMATIC_FASTEXT_PROMPT 0x80 | ||
| 131 | |||
| 132 | /* Register R1 (Mode) */ | ||
| 133 | #define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES 0x00 | ||
| 134 | #define R1_NON_INTERLACED_312_313_LINES 0x01 | ||
| 135 | #define R1_NON_INTERLACED_312_312_LINES 0x02 | ||
| 136 | #define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE 0x03 | ||
| 137 | #define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE 0x07 | ||
| 138 | |||
| 139 | #define R1_DEW 0x00 | ||
| 140 | #define R1_FULL_FIELD 0x08 | ||
| 141 | |||
| 142 | #define R1_EXTENDED_PACKET_DISABLE 0x00 | ||
| 143 | #define R1_EXTENDED_PACKET_ENABLE 0x10 | ||
| 144 | |||
| 145 | #define R1_DAUS_ALL_ON 0x00 | ||
| 146 | #define R1_DAUS_ALL_OFF 0x20 | ||
| 147 | |||
| 148 | #define R1_7_BITS_PLUS_PARITY 0x00 | ||
| 149 | #define R1_8_BITS_NO_PARITY 0x40 | ||
| 150 | |||
| 151 | #define R1_VCS_TO_SCS 0x00 | ||
| 152 | #define R1_NO_VCS_TO_SCS 0x80 | ||
| 153 | |||
| 154 | /* Register R2 (Page request address) */ | ||
| 155 | #define R2_IN_R3_SELECT_PAGE_HUNDREDS 0x00 | ||
| 156 | #define R2_IN_R3_SELECT_PAGE_TENS 0x01 | ||
| 157 | #define R2_IN_R3_SELECT_PAGE_UNITS 0x02 | ||
| 158 | #define R2_IN_R3_SELECT_HOURS_TENS 0x03 | ||
| 159 | #define R2_IN_R3_SELECT_HOURS_UNITS 0x04 | ||
| 160 | #define R2_IN_R3_SELECT_MINUTES_TENS 0x05 | ||
| 161 | #define R2_IN_R3_SELECT_MINUTES_UNITS 0x06 | ||
| 162 | |||
| 163 | #define R2_DAU_0 0x00 | ||
| 164 | #define R2_DAU_1 0x10 | ||
| 165 | #define R2_DAU_2 0x20 | ||
| 166 | #define R2_DAU_3 0x30 | ||
| 167 | |||
| 168 | #define R2_BANK_0 0x00 | ||
| 169 | #define R2_BANK 1 0x40 | ||
| 170 | |||
| 171 | #define R2_HAMMING_CHECK_ON 0x80 | ||
| 172 | #define R2_HAMMING_CHECK_OFF 0x00 | ||
| 173 | |||
| 174 | /* Register R3 (Page request data) */ | ||
| 175 | #define R3_PAGE_HUNDREDS_0 0x00 | ||
| 176 | #define R3_PAGE_HUNDREDS_1 0x01 | ||
| 177 | #define R3_PAGE_HUNDREDS_2 0x02 | ||
| 178 | #define R3_PAGE_HUNDREDS_3 0x03 | ||
| 179 | #define R3_PAGE_HUNDREDS_4 0x04 | ||
| 180 | #define R3_PAGE_HUNDREDS_5 0x05 | ||
| 181 | #define R3_PAGE_HUNDREDS_6 0x06 | ||
| 182 | #define R3_PAGE_HUNDREDS_7 0x07 | ||
| 65 | 183 | ||
| 66 | static struct video_device saa_template; /* Declared near bottom */ | 184 | #define R3_HOLD_PAGE 0x00 |
| 185 | #define R3_UPDATE_PAGE 0x08 | ||
| 67 | 186 | ||
| 68 | /* Addresses to scan */ | 187 | #define R3_PAGE_HUNDREDS_DO_NOT_CARE 0x00 |
| 69 | static unsigned short normal_i2c[] = { I2C_ADDRESS, I2C_CLIENT_END }; | 188 | #define R3_PAGE_HUNDREDS_DO_CARE 0x10 |
| 70 | 189 | ||
| 71 | I2C_CLIENT_INSMOD; | 190 | #define R3_PAGE_TENS_DO_NOT_CARE 0x00 |
| 191 | #define R3_PAGE_TENS_DO_CARE 0x10 | ||
| 72 | 192 | ||
| 73 | static struct i2c_client client_template; | 193 | #define R3_PAGE_UNITS_DO_NOT_CARE 0x00 |
| 194 | #define R3_PAGE_UNITS_DO_CARE 0x10 | ||
| 74 | 195 | ||
| 75 | static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind) | 196 | #define R3_HOURS_TENS_DO_NOT_CARE 0x00 |
| 76 | { | 197 | #define R3_HOURS_TENS_DO_CARE 0x10 |
| 77 | int pgbuf; | ||
| 78 | int err; | ||
| 79 | struct i2c_client *client; | ||
| 80 | struct video_device *vd; | ||
| 81 | struct saa5246a_device *t; | ||
| 82 | 198 | ||
| 83 | printk(KERN_INFO "saa5246a: teletext chip found.\n"); | 199 | #define R3_HOURS_UNITS_DO_NOT_CARE 0x00 |
| 84 | client=kmalloc(sizeof(*client), GFP_KERNEL); | 200 | #define R3_HOURS_UNITS_DO_CARE 0x10 |
| 85 | if(client==NULL) | ||
| 86 | return -ENOMEM; | ||
| 87 | client_template.adapter = adap; | ||
| 88 | client_template.addr = addr; | ||
| 89 | memcpy(client, &client_template, sizeof(*client)); | ||
| 90 | t = kzalloc(sizeof(*t), GFP_KERNEL); | ||
| 91 | if(t==NULL) | ||
| 92 | { | ||
| 93 | kfree(client); | ||
| 94 | return -ENOMEM; | ||
| 95 | } | ||
| 96 | strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); | ||
| 97 | mutex_init(&t->lock); | ||
| 98 | 201 | ||
| 99 | /* | 202 | #define R3_MINUTES_TENS_DO_NOT_CARE 0x00 |
| 100 | * Now create a video4linux device | 203 | #define R3_MINUTES_TENS_DO_CARE 0x10 |
| 101 | */ | ||
| 102 | 204 | ||
| 103 | vd = video_device_alloc(); | 205 | #define R3_MINUTES_UNITS_DO_NOT_CARE 0x00 |
| 104 | if(vd==NULL) | 206 | #define R3_MINUTES_UNITS_DO_CARE 0x10 |
| 105 | { | ||
| 106 | kfree(t); | ||
| 107 | kfree(client); | ||
| 108 | return -ENOMEM; | ||
| 109 | } | ||
| 110 | i2c_set_clientdata(client, vd); | ||
| 111 | memcpy(vd, &saa_template, sizeof(*vd)); | ||
| 112 | 207 | ||
| 113 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) | 208 | /* Register R4 (Display chapter) */ |
| 114 | { | 209 | #define R4_DISPLAY_PAGE_0 0x00 |
| 115 | memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); | 210 | #define R4_DISPLAY_PAGE_1 0x01 |
| 116 | t->is_searching[pgbuf] = false; | 211 | #define R4_DISPLAY_PAGE_2 0x02 |
| 117 | } | 212 | #define R4_DISPLAY_PAGE_3 0x03 |
| 118 | vd->priv=t; | 213 | #define R4_DISPLAY_PAGE_4 0x04 |
| 214 | #define R4_DISPLAY_PAGE_5 0x05 | ||
| 215 | #define R4_DISPLAY_PAGE_6 0x06 | ||
| 216 | #define R4_DISPLAY_PAGE_7 0x07 | ||
| 119 | 217 | ||
| 218 | /* Register R5 (Normal display control) */ | ||
| 219 | #define R5_PICTURE_INSIDE_BOXING_OFF 0x00 | ||
| 220 | #define R5_PICTURE_INSIDE_BOXING_ON 0x01 | ||
| 120 | 221 | ||
| 121 | /* | 222 | #define R5_PICTURE_OUTSIDE_BOXING_OFF 0x00 |
| 122 | * Register it | 223 | #define R5_PICTURE_OUTSIDE_BOXING_ON 0x02 |
| 123 | */ | ||
| 124 | 224 | ||
| 125 | if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0) | 225 | #define R5_TEXT_INSIDE_BOXING_OFF 0x00 |
| 126 | { | 226 | #define R5_TEXT_INSIDE_BOXING_ON 0x04 |
| 127 | kfree(t); | ||
| 128 | kfree(client); | ||
| 129 | video_device_release(vd); | ||
| 130 | return err; | ||
| 131 | } | ||
| 132 | t->client = client; | ||
| 133 | i2c_attach_client(client); | ||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | 227 | ||
| 137 | /* | 228 | #define R5_TEXT_OUTSIDE_BOXING_OFF 0x00 |
| 138 | * We do most of the hard work when we become a device on the i2c. | 229 | #define R5_TEXT_OUTSIDE_BOXING_ON 0x08 |
| 139 | */ | ||
| 140 | static int saa5246a_probe(struct i2c_adapter *adap) | ||
| 141 | { | ||
| 142 | if (adap->class & I2C_CLASS_TV_ANALOG) | ||
| 143 | return i2c_probe(adap, &addr_data, saa5246a_attach); | ||
| 144 | return 0; | ||
| 145 | } | ||
| 146 | 230 | ||
| 147 | static int saa5246a_detach(struct i2c_client *client) | 231 | #define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 |
| 148 | { | 232 | #define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 |
| 149 | struct video_device *vd = i2c_get_clientdata(client); | ||
| 150 | i2c_detach_client(client); | ||
| 151 | video_unregister_device(vd); | ||
| 152 | kfree(vd->priv); | ||
| 153 | kfree(client); | ||
| 154 | return 0; | ||
| 155 | } | ||
| 156 | 233 | ||
| 157 | /* | 234 | #define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 |
| 158 | * I2C interfaces | 235 | #define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 |
| 159 | */ | 236 | |
| 237 | #define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 | ||
| 238 | #define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 | ||
| 239 | |||
| 240 | #define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 | ||
| 241 | #define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 | ||
| 242 | |||
| 243 | /* Register R6 (Newsflash display) */ | ||
| 244 | #define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF 0x00 | ||
| 245 | #define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON 0x01 | ||
| 246 | |||
| 247 | #define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF 0x00 | ||
| 248 | #define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON 0x02 | ||
| 249 | |||
| 250 | #define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF 0x00 | ||
| 251 | #define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON 0x04 | ||
| 252 | |||
| 253 | #define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF 0x00 | ||
| 254 | #define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON 0x08 | ||
| 255 | |||
| 256 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 | ||
| 257 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 | ||
| 258 | |||
| 259 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 | ||
| 260 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 | ||
| 261 | |||
| 262 | #define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 | ||
| 263 | #define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 | ||
| 264 | |||
| 265 | #define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 | ||
| 266 | #define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 | ||
| 267 | |||
| 268 | /* Register R7 (Display mode) */ | ||
| 269 | #define R7_BOX_OFF_ROW_0 0x00 | ||
| 270 | #define R7_BOX_ON_ROW_0 0x01 | ||
| 271 | |||
| 272 | #define R7_BOX_OFF_ROW_1_TO_23 0x00 | ||
| 273 | #define R7_BOX_ON_ROW_1_TO_23 0x02 | ||
| 274 | |||
| 275 | #define R7_BOX_OFF_ROW_24 0x00 | ||
| 276 | #define R7_BOX_ON_ROW_24 0x04 | ||
| 277 | |||
| 278 | #define R7_SINGLE_HEIGHT 0x00 | ||
| 279 | #define R7_DOUBLE_HEIGHT 0x08 | ||
| 280 | |||
| 281 | #define R7_TOP_HALF 0x00 | ||
| 282 | #define R7_BOTTOM_HALF 0x10 | ||
| 283 | |||
| 284 | #define R7_REVEAL_OFF 0x00 | ||
| 285 | #define R7_REVEAL_ON 0x20 | ||
| 286 | |||
| 287 | #define R7_CURSER_OFF 0x00 | ||
| 288 | #define R7_CURSER_ON 0x40 | ||
| 289 | |||
| 290 | #define R7_STATUS_BOTTOM 0x00 | ||
| 291 | #define R7_STATUS_TOP 0x80 | ||
| 292 | |||
| 293 | /* Register R8 (Active chapter) */ | ||
| 294 | #define R8_ACTIVE_CHAPTER_0 0x00 | ||
| 295 | #define R8_ACTIVE_CHAPTER_1 0x01 | ||
| 296 | #define R8_ACTIVE_CHAPTER_2 0x02 | ||
| 297 | #define R8_ACTIVE_CHAPTER_3 0x03 | ||
| 298 | #define R8_ACTIVE_CHAPTER_4 0x04 | ||
| 299 | #define R8_ACTIVE_CHAPTER_5 0x05 | ||
| 300 | #define R8_ACTIVE_CHAPTER_6 0x06 | ||
| 301 | #define R8_ACTIVE_CHAPTER_7 0x07 | ||
| 302 | |||
| 303 | #define R8_CLEAR_MEMORY 0x08 | ||
| 304 | #define R8_DO_NOT_CLEAR_MEMORY 0x00 | ||
| 305 | |||
| 306 | /* Register R9 (Curser row) */ | ||
| 307 | #define R9_CURSER_ROW_0 0x00 | ||
| 308 | #define R9_CURSER_ROW_1 0x01 | ||
| 309 | #define R9_CURSER_ROW_2 0x02 | ||
| 310 | #define R9_CURSER_ROW_25 0x19 | ||
| 311 | |||
| 312 | /* Register R10 (Curser column) */ | ||
| 313 | #define R10_CURSER_COLUMN_0 0x00 | ||
| 314 | #define R10_CURSER_COLUMN_6 0x06 | ||
| 315 | #define R10_CURSER_COLUMN_8 0x08 | ||
| 316 | |||
| 317 | /*****************************************************************************/ | ||
| 318 | /* Row 25 control data in column 0 to 9 */ | ||
| 319 | /*****************************************************************************/ | ||
| 320 | #define ROW25_COLUMN0_PAGE_UNITS 0x0F | ||
| 321 | |||
| 322 | #define ROW25_COLUMN1_PAGE_TENS 0x0F | ||
| 323 | |||
| 324 | #define ROW25_COLUMN2_MINUTES_UNITS 0x0F | ||
| 160 | 325 | ||
| 161 | static struct i2c_driver i2c_driver_videotext = | 326 | #define ROW25_COLUMN3_MINUTES_TENS 0x07 |
| 327 | #define ROW25_COLUMN3_DELETE_PAGE 0x08 | ||
| 328 | |||
| 329 | #define ROW25_COLUMN4_HOUR_UNITS 0x0F | ||
| 330 | |||
| 331 | #define ROW25_COLUMN5_HOUR_TENS 0x03 | ||
| 332 | #define ROW25_COLUMN5_INSERT_HEADLINE 0x04 | ||
| 333 | #define ROW25_COLUMN5_INSERT_SUBTITLE 0x08 | ||
| 334 | |||
| 335 | #define ROW25_COLUMN6_SUPPRESS_HEADER 0x01 | ||
| 336 | #define ROW25_COLUMN6_UPDATE_PAGE 0x02 | ||
| 337 | #define ROW25_COLUMN6_INTERRUPTED_SEQUENCE 0x04 | ||
| 338 | #define ROW25_COLUMN6_SUPPRESS_DISPLAY 0x08 | ||
| 339 | |||
| 340 | #define ROW25_COLUMN7_SERIAL_MODE 0x01 | ||
| 341 | #define ROW25_COLUMN7_CHARACTER_SET 0x0E | ||
| 342 | |||
| 343 | #define ROW25_COLUMN8_PAGE_HUNDREDS 0x07 | ||
| 344 | #define ROW25_COLUMN8_PAGE_NOT_FOUND 0x10 | ||
| 345 | |||
| 346 | #define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR 0x20 | ||
| 347 | |||
| 348 | #define ROW25_COLUMN0_TO_7_HAMMING_ERROR 0x10 | ||
| 349 | |||
| 350 | /*****************************************************************************/ | ||
| 351 | /* Helper macros for extracting page, hour and minute digits */ | ||
| 352 | /*****************************************************************************/ | ||
| 353 | /* BYTE_POS 0 is at row 0, column 0, | ||
| 354 | BYTE_POS 1 is at row 0, column 1, | ||
| 355 | BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40) | ||
| 356 | BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40), | ||
| 357 | ... */ | ||
| 358 | #define ROW(BYTE_POS) (BYTE_POS / NUM_ROWS_PER_PAGE) | ||
| 359 | #define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE) | ||
| 360 | |||
| 361 | /*****************************************************************************/ | ||
| 362 | /* Helper macros for extracting page, hour and minute digits */ | ||
| 363 | /*****************************************************************************/ | ||
| 364 | /* Macros for extracting hundreds, tens and units of a page number which | ||
| 365 | must be in the range 0 ... 0x799. | ||
| 366 | Note that page is coded in hexadecimal, i.e. 0x123 means page 123. | ||
| 367 | page 0x.. means page 8.. */ | ||
| 368 | #define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7) | ||
| 369 | #define TENS_OF_PAGE(page) (((page) / 0x10) & 0xF) | ||
| 370 | #define UNITS_OF_PAGE(page) ((page) & 0xF) | ||
| 371 | |||
| 372 | /* Macros for extracting tens and units of a hour information which | ||
| 373 | must be in the range 0 ... 0x24. | ||
| 374 | Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */ | ||
| 375 | #define TENS_OF_HOUR(hour) ((hour) / 0x10) | ||
| 376 | #define UNITS_OF_HOUR(hour) ((hour) & 0xF) | ||
| 377 | |||
| 378 | /* Macros for extracting tens and units of a minute information which | ||
| 379 | must be in the range 0 ... 0x59. | ||
| 380 | Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */ | ||
| 381 | #define TENS_OF_MINUTE(minute) ((minute) / 0x10) | ||
| 382 | #define UNITS_OF_MINUTE(minute) ((minute) & 0xF) | ||
| 383 | |||
| 384 | #define HOUR_MAX 0x23 | ||
| 385 | #define MINUTE_MAX 0x59 | ||
| 386 | #define PAGE_MAX 0x8FF | ||
| 387 | |||
| 388 | |||
| 389 | struct saa5246a_device | ||
| 162 | { | 390 | { |
| 163 | .driver = { | 391 | u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; |
| 164 | .name = IF_NAME, /* name */ | 392 | int is_searching[NUM_DAUS]; |
| 165 | }, | 393 | struct i2c_client *client; |
| 166 | .id = I2C_DRIVERID_SAA5249, /* in i2c.h */ | 394 | unsigned long in_use; |
| 167 | .attach_adapter = saa5246a_probe, | 395 | struct mutex lock; |
| 168 | .detach_client = saa5246a_detach, | ||
| 169 | }; | 396 | }; |
| 170 | 397 | ||
| 171 | static struct i2c_client client_template = { | 398 | static struct video_device saa_template; /* Declared near bottom */ |
| 172 | .driver = &i2c_driver_videotext, | 399 | |
| 173 | .name = "(unset)", | 400 | /* |
| 174 | }; | 401 | * I2C interfaces |
| 402 | */ | ||
| 175 | 403 | ||
| 176 | static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data) | 404 | static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data) |
| 177 | { | 405 | { |
| @@ -579,8 +807,8 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t, | |||
| 579 | static int do_saa5246a_ioctl(struct inode *inode, struct file *file, | 807 | static int do_saa5246a_ioctl(struct inode *inode, struct file *file, |
| 580 | unsigned int cmd, void *arg) | 808 | unsigned int cmd, void *arg) |
| 581 | { | 809 | { |
| 582 | struct video_device *vd = video_devdata(file); | 810 | struct saa5246a_device *t = video_drvdata(file); |
| 583 | struct saa5246a_device *t=vd->priv; | 811 | |
| 584 | switch(cmd) | 812 | switch(cmd) |
| 585 | { | 813 | { |
| 586 | case VTXIOCGETINFO: | 814 | case VTXIOCGETINFO: |
| @@ -720,8 +948,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) | |||
| 720 | static int saa5246a_ioctl(struct inode *inode, struct file *file, | 948 | static int saa5246a_ioctl(struct inode *inode, struct file *file, |
| 721 | unsigned int cmd, unsigned long arg) | 949 | unsigned int cmd, unsigned long arg) |
| 722 | { | 950 | { |
| 723 | struct video_device *vd = video_devdata(file); | 951 | struct saa5246a_device *t = video_drvdata(file); |
| 724 | struct saa5246a_device *t = vd->priv; | ||
| 725 | int err; | 952 | int err; |
| 726 | 953 | ||
| 727 | cmd = vtx_fix_command(cmd); | 954 | cmd = vtx_fix_command(cmd); |
| @@ -733,21 +960,15 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file, | |||
| 733 | 960 | ||
| 734 | static int saa5246a_open(struct inode *inode, struct file *file) | 961 | static int saa5246a_open(struct inode *inode, struct file *file) |
| 735 | { | 962 | { |
| 736 | struct video_device *vd = video_devdata(file); | 963 | struct saa5246a_device *t = video_drvdata(file); |
| 737 | struct saa5246a_device *t = vd->priv; | ||
| 738 | int err; | ||
| 739 | 964 | ||
| 740 | err = video_exclusive_open(inode,file); | 965 | if (t->client == NULL) |
| 741 | if (err < 0) | 966 | return -ENODEV; |
| 742 | return err; | ||
| 743 | 967 | ||
| 744 | if (t->client==NULL) { | 968 | if (test_and_set_bit(0, &t->in_use)) |
| 745 | err = -ENODEV; | 969 | return -EBUSY; |
| 746 | goto fail; | ||
| 747 | } | ||
| 748 | 970 | ||
| 749 | if (i2c_senddata(t, SAA5246A_REGISTER_R0, | 971 | if (i2c_senddata(t, SAA5246A_REGISTER_R0, |
| 750 | |||
| 751 | R0_SELECT_R11 | | 972 | R0_SELECT_R11 | |
| 752 | R0_PLL_TIME_CONSTANT_LONG | | 973 | R0_PLL_TIME_CONSTANT_LONG | |
| 753 | R0_ENABLE_nODD_EVEN_OUTPUT | | 974 | R0_ENABLE_nODD_EVEN_OUTPUT | |
| @@ -773,21 +994,15 @@ static int saa5246a_open(struct inode *inode, struct file *file) | |||
| 773 | 994 | ||
| 774 | COMMAND_END)) | 995 | COMMAND_END)) |
| 775 | { | 996 | { |
| 776 | err = -EIO; | 997 | clear_bit(0, &t->in_use); |
| 777 | goto fail; | 998 | return -EIO; |
| 778 | } | 999 | } |
| 779 | |||
| 780 | return 0; | 1000 | return 0; |
| 781 | |||
| 782 | fail: | ||
| 783 | video_exclusive_release(inode,file); | ||
| 784 | return err; | ||
| 785 | } | 1001 | } |
| 786 | 1002 | ||
| 787 | static int saa5246a_release(struct inode *inode, struct file *file) | 1003 | static int saa5246a_release(struct inode *inode, struct file *file) |
| 788 | { | 1004 | { |
| 789 | struct video_device *vd = video_devdata(file); | 1005 | struct saa5246a_device *t = video_drvdata(file); |
| 790 | struct saa5246a_device *t = vd->priv; | ||
| 791 | 1006 | ||
| 792 | /* Stop all acquisition circuits. */ | 1007 | /* Stop all acquisition circuits. */ |
| 793 | i2c_senddata(t, SAA5246A_REGISTER_R1, | 1008 | i2c_senddata(t, SAA5246A_REGISTER_R1, |
| @@ -800,26 +1015,10 @@ static int saa5246a_release(struct inode *inode, struct file *file) | |||
| 800 | R1_VCS_TO_SCS, | 1015 | R1_VCS_TO_SCS, |
| 801 | 1016 | ||
| 802 | COMMAND_END); | 1017 | COMMAND_END); |
| 803 | video_exclusive_release(inode,file); | 1018 | clear_bit(0, &t->in_use); |
| 804 | return 0; | 1019 | return 0; |
| 805 | } | 1020 | } |
| 806 | 1021 | ||
| 807 | static int __init init_saa_5246a (void) | ||
| 808 | { | ||
| 809 | printk(KERN_INFO | ||
| 810 | "SAA5246A (or compatible) Teletext decoder driver version %d.%d\n", | ||
| 811 | MAJOR_VERSION, MINOR_VERSION); | ||
| 812 | return i2c_add_driver(&i2c_driver_videotext); | ||
| 813 | } | ||
| 814 | |||
| 815 | static void __exit cleanup_saa_5246a (void) | ||
| 816 | { | ||
| 817 | i2c_del_driver(&i2c_driver_videotext); | ||
| 818 | } | ||
| 819 | |||
| 820 | module_init(init_saa_5246a); | ||
| 821 | module_exit(cleanup_saa_5246a); | ||
| 822 | |||
| 823 | static const struct file_operations saa_fops = { | 1022 | static const struct file_operations saa_fops = { |
| 824 | .owner = THIS_MODULE, | 1023 | .owner = THIS_MODULE, |
| 825 | .open = saa5246a_open, | 1024 | .open = saa5246a_open, |
| @@ -830,8 +1029,79 @@ static const struct file_operations saa_fops = { | |||
| 830 | 1029 | ||
| 831 | static struct video_device saa_template = | 1030 | static struct video_device saa_template = |
| 832 | { | 1031 | { |
| 833 | .name = IF_NAME, | 1032 | .name = "saa5246a", |
| 834 | .fops = &saa_fops, | 1033 | .fops = &saa_fops, |
| 835 | .release = video_device_release, | 1034 | .release = video_device_release, |
| 836 | .minor = -1, | 1035 | .minor = -1, |
| 837 | }; | 1036 | }; |
| 1037 | |||
| 1038 | /* Addresses to scan */ | ||
| 1039 | static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; | ||
| 1040 | |||
| 1041 | I2C_CLIENT_INSMOD; | ||
| 1042 | |||
| 1043 | static int saa5246a_probe(struct i2c_client *client, | ||
| 1044 | const struct i2c_device_id *id) | ||
| 1045 | { | ||
| 1046 | int pgbuf; | ||
| 1047 | int err; | ||
| 1048 | struct video_device *vd; | ||
| 1049 | struct saa5246a_device *t; | ||
| 1050 | |||
| 1051 | v4l_info(client, "chip found @ 0x%x (%s)\n", | ||
| 1052 | client->addr << 1, client->adapter->name); | ||
| 1053 | v4l_info(client, "VideoText version %d.%d\n", | ||
| 1054 | MAJOR_VERSION, MINOR_VERSION); | ||
| 1055 | t = kzalloc(sizeof(*t), GFP_KERNEL); | ||
| 1056 | if (t == NULL) | ||
| 1057 | return -ENOMEM; | ||
| 1058 | mutex_init(&t->lock); | ||
| 1059 | |||
| 1060 | /* Now create a video4linux device */ | ||
| 1061 | vd = video_device_alloc(); | ||
| 1062 | if (vd == NULL) { | ||
| 1063 | kfree(t); | ||
| 1064 | return -ENOMEM; | ||
| 1065 | } | ||
| 1066 | i2c_set_clientdata(client, vd); | ||
| 1067 | memcpy(vd, &saa_template, sizeof(*vd)); | ||
| 1068 | |||
| 1069 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { | ||
| 1070 | memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); | ||
| 1071 | t->is_searching[pgbuf] = false; | ||
| 1072 | } | ||
| 1073 | video_set_drvdata(vd, t); | ||
| 1074 | |||
| 1075 | /* Register it */ | ||
| 1076 | err = video_register_device(vd, VFL_TYPE_VTX, -1); | ||
| 1077 | if (err < 0) { | ||
| 1078 | kfree(t); | ||
| 1079 | video_device_release(vd); | ||
| 1080 | return err; | ||
| 1081 | } | ||
| 1082 | t->client = client; | ||
| 1083 | return 0; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | static int saa5246a_remove(struct i2c_client *client) | ||
| 1087 | { | ||
| 1088 | struct video_device *vd = i2c_get_clientdata(client); | ||
| 1089 | |||
| 1090 | video_unregister_device(vd); | ||
| 1091 | kfree(video_get_drvdata(vd)); | ||
| 1092 | return 0; | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | static const struct i2c_device_id saa5246a_id[] = { | ||
| 1096 | { "saa5246a", 0 }, | ||
| 1097 | { } | ||
| 1098 | }; | ||
| 1099 | MODULE_DEVICE_TABLE(i2c, saa5246a_id); | ||
| 1100 | |||
| 1101 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
| 1102 | .name = "saa5246a", | ||
| 1103 | .driverid = I2C_DRIVERID_SAA5249, | ||
| 1104 | .probe = saa5246a_probe, | ||
| 1105 | .remove = saa5246a_remove, | ||
| 1106 | .id_table = saa5246a_id, | ||
| 1107 | }; | ||
diff --git a/drivers/media/video/saa5246a.h b/drivers/media/video/saa5246a.h deleted file mode 100644 index 64394c036c60..000000000000 --- a/drivers/media/video/saa5246a.h +++ /dev/null | |||
| @@ -1,359 +0,0 @@ | |||
| 1 | /* | ||
| 2 | Driver for the SAA5246A or SAA5281 Teletext (=Videotext) decoder chips from | ||
| 3 | Philips. | ||
| 4 | |||
| 5 | Copyright (C) 2004 Michael Geng (linux@MichaelGeng.de) | ||
| 6 | |||
| 7 | This program is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 2 of the License, or | ||
| 10 | (at your option) any later version. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; if not, write to the Free Software | ||
| 19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 20 | |||
| 21 | */ | ||
| 22 | #ifndef __SAA5246A_H__ | ||
| 23 | #define __SAA5246A_H__ | ||
| 24 | |||
| 25 | #define MAJOR_VERSION 1 /* driver major version number */ | ||
| 26 | #define MINOR_VERSION 8 /* driver minor version number */ | ||
| 27 | |||
| 28 | #define IF_NAME "SAA5246A" | ||
| 29 | |||
| 30 | #define I2C_ADDRESS 17 | ||
| 31 | |||
| 32 | /* Number of DAUs = number of pages that can be searched at the same time. */ | ||
| 33 | #define NUM_DAUS 4 | ||
| 34 | |||
| 35 | #define NUM_ROWS_PER_PAGE 40 | ||
| 36 | |||
| 37 | /* first column is 0 (not 1) */ | ||
| 38 | #define POS_TIME_START 32 | ||
| 39 | #define POS_TIME_END 39 | ||
| 40 | |||
| 41 | #define POS_HEADER_START 7 | ||
| 42 | #define POS_HEADER_END 31 | ||
| 43 | |||
| 44 | /* Returns 'true' if the part of the videotext page described with req contains | ||
| 45 | (at least parts of) the time field */ | ||
| 46 | #define REQ_CONTAINS_TIME(p_req) \ | ||
| 47 | ((p_req)->start <= POS_TIME_END && \ | ||
| 48 | (p_req)->end >= POS_TIME_START) | ||
| 49 | |||
| 50 | /* Returns 'true' if the part of the videotext page described with req contains | ||
| 51 | (at least parts of) the page header */ | ||
| 52 | #define REQ_CONTAINS_HEADER(p_req) \ | ||
| 53 | ((p_req)->start <= POS_HEADER_END && \ | ||
| 54 | (p_req)->end >= POS_HEADER_START) | ||
| 55 | |||
| 56 | /*****************************************************************************/ | ||
| 57 | /* Mode register numbers of the SAA5246A */ | ||
| 58 | /*****************************************************************************/ | ||
| 59 | #define SAA5246A_REGISTER_R0 0 | ||
| 60 | #define SAA5246A_REGISTER_R1 1 | ||
| 61 | #define SAA5246A_REGISTER_R2 2 | ||
| 62 | #define SAA5246A_REGISTER_R3 3 | ||
| 63 | #define SAA5246A_REGISTER_R4 4 | ||
| 64 | #define SAA5246A_REGISTER_R5 5 | ||
| 65 | #define SAA5246A_REGISTER_R6 6 | ||
| 66 | #define SAA5246A_REGISTER_R7 7 | ||
| 67 | #define SAA5246A_REGISTER_R8 8 | ||
| 68 | #define SAA5246A_REGISTER_R9 9 | ||
| 69 | #define SAA5246A_REGISTER_R10 10 | ||
| 70 | #define SAA5246A_REGISTER_R11 11 | ||
| 71 | #define SAA5246A_REGISTER_R11B 11 | ||
| 72 | |||
| 73 | /* SAA5246A mode registers often autoincrement to the next register. | ||
| 74 | Therefore we use variable argument lists. The following macro indicates | ||
| 75 | the end of a command list. */ | ||
| 76 | #define COMMAND_END (- 1) | ||
| 77 | |||
| 78 | /*****************************************************************************/ | ||
| 79 | /* Contents of the mode registers of the SAA5246A */ | ||
| 80 | /*****************************************************************************/ | ||
| 81 | /* Register R0 (Advanced Control) */ | ||
| 82 | #define R0_SELECT_R11 0x00 | ||
| 83 | #define R0_SELECT_R11B 0x01 | ||
| 84 | |||
| 85 | #define R0_PLL_TIME_CONSTANT_LONG 0x00 | ||
| 86 | #define R0_PLL_TIME_CONSTANT_SHORT 0x02 | ||
| 87 | |||
| 88 | #define R0_ENABLE_nODD_EVEN_OUTPUT 0x00 | ||
| 89 | #define R0_DISABLE_nODD_EVEN_OUTPUT 0x04 | ||
| 90 | |||
| 91 | #define R0_ENABLE_HDR_POLL 0x00 | ||
| 92 | #define R0_DISABLE_HDR_POLL 0x10 | ||
| 93 | |||
| 94 | #define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00 | ||
| 95 | #define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x20 | ||
| 96 | |||
| 97 | #define R0_NO_FREE_RUN_PLL 0x00 | ||
| 98 | #define R0_FREE_RUN_PLL 0x40 | ||
| 99 | |||
| 100 | #define R0_NO_AUTOMATIC_FASTEXT_PROMPT 0x00 | ||
| 101 | #define R0_AUTOMATIC_FASTEXT_PROMPT 0x80 | ||
| 102 | |||
| 103 | /* Register R1 (Mode) */ | ||
| 104 | #define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES 0x00 | ||
| 105 | #define R1_NON_INTERLACED_312_313_LINES 0x01 | ||
| 106 | #define R1_NON_INTERLACED_312_312_LINES 0x02 | ||
| 107 | #define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE 0x03 | ||
| 108 | #define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE 0x07 | ||
| 109 | |||
| 110 | #define R1_DEW 0x00 | ||
| 111 | #define R1_FULL_FIELD 0x08 | ||
| 112 | |||
| 113 | #define R1_EXTENDED_PACKET_DISABLE 0x00 | ||
| 114 | #define R1_EXTENDED_PACKET_ENABLE 0x10 | ||
| 115 | |||
| 116 | #define R1_DAUS_ALL_ON 0x00 | ||
| 117 | #define R1_DAUS_ALL_OFF 0x20 | ||
| 118 | |||
| 119 | #define R1_7_BITS_PLUS_PARITY 0x00 | ||
| 120 | #define R1_8_BITS_NO_PARITY 0x40 | ||
| 121 | |||
| 122 | #define R1_VCS_TO_SCS 0x00 | ||
| 123 | #define R1_NO_VCS_TO_SCS 0x80 | ||
| 124 | |||
| 125 | /* Register R2 (Page request address) */ | ||
| 126 | #define R2_IN_R3_SELECT_PAGE_HUNDREDS 0x00 | ||
| 127 | #define R2_IN_R3_SELECT_PAGE_TENS 0x01 | ||
| 128 | #define R2_IN_R3_SELECT_PAGE_UNITS 0x02 | ||
| 129 | #define R2_IN_R3_SELECT_HOURS_TENS 0x03 | ||
| 130 | #define R2_IN_R3_SELECT_HOURS_UNITS 0x04 | ||
| 131 | #define R2_IN_R3_SELECT_MINUTES_TENS 0x05 | ||
| 132 | #define R2_IN_R3_SELECT_MINUTES_UNITS 0x06 | ||
| 133 | |||
| 134 | #define R2_DAU_0 0x00 | ||
| 135 | #define R2_DAU_1 0x10 | ||
| 136 | #define R2_DAU_2 0x20 | ||
| 137 | #define R2_DAU_3 0x30 | ||
| 138 | |||
| 139 | #define R2_BANK_0 0x00 | ||
| 140 | #define R2_BANK 1 0x40 | ||
| 141 | |||
| 142 | #define R2_HAMMING_CHECK_ON 0x80 | ||
| 143 | #define R2_HAMMING_CHECK_OFF 0x00 | ||
| 144 | |||
| 145 | /* Register R3 (Page request data) */ | ||
| 146 | #define R3_PAGE_HUNDREDS_0 0x00 | ||
| 147 | #define R3_PAGE_HUNDREDS_1 0x01 | ||
| 148 | #define R3_PAGE_HUNDREDS_2 0x02 | ||
| 149 | #define R3_PAGE_HUNDREDS_3 0x03 | ||
| 150 | #define R3_PAGE_HUNDREDS_4 0x04 | ||
| 151 | #define R3_PAGE_HUNDREDS_5 0x05 | ||
| 152 | #define R3_PAGE_HUNDREDS_6 0x06 | ||
| 153 | #define R3_PAGE_HUNDREDS_7 0x07 | ||
| 154 | |||
| 155 | #define R3_HOLD_PAGE 0x00 | ||
| 156 | #define R3_UPDATE_PAGE 0x08 | ||
| 157 | |||
| 158 | #define R3_PAGE_HUNDREDS_DO_NOT_CARE 0x00 | ||
| 159 | #define R3_PAGE_HUNDREDS_DO_CARE 0x10 | ||
| 160 | |||
| 161 | #define R3_PAGE_TENS_DO_NOT_CARE 0x00 | ||
| 162 | #define R3_PAGE_TENS_DO_CARE 0x10 | ||
| 163 | |||
| 164 | #define R3_PAGE_UNITS_DO_NOT_CARE 0x00 | ||
| 165 | #define R3_PAGE_UNITS_DO_CARE 0x10 | ||
| 166 | |||
| 167 | #define R3_HOURS_TENS_DO_NOT_CARE 0x00 | ||
| 168 | #define R3_HOURS_TENS_DO_CARE 0x10 | ||
| 169 | |||
| 170 | #define R3_HOURS_UNITS_DO_NOT_CARE 0x00 | ||
| 171 | #define R3_HOURS_UNITS_DO_CARE 0x10 | ||
| 172 | |||
| 173 | #define R3_MINUTES_TENS_DO_NOT_CARE 0x00 | ||
| 174 | #define R3_MINUTES_TENS_DO_CARE 0x10 | ||
| 175 | |||
| 176 | #define R3_MINUTES_UNITS_DO_NOT_CARE 0x00 | ||
| 177 | #define R3_MINUTES_UNITS_DO_CARE 0x10 | ||
| 178 | |||
| 179 | /* Register R4 (Display chapter) */ | ||
| 180 | #define R4_DISPLAY_PAGE_0 0x00 | ||
| 181 | #define R4_DISPLAY_PAGE_1 0x01 | ||
| 182 | #define R4_DISPLAY_PAGE_2 0x02 | ||
| 183 | #define R4_DISPLAY_PAGE_3 0x03 | ||
| 184 | #define R4_DISPLAY_PAGE_4 0x04 | ||
| 185 | #define R4_DISPLAY_PAGE_5 0x05 | ||
| 186 | #define R4_DISPLAY_PAGE_6 0x06 | ||
| 187 | #define R4_DISPLAY_PAGE_7 0x07 | ||
| 188 | |||
| 189 | /* Register R5 (Normal display control) */ | ||
| 190 | #define R5_PICTURE_INSIDE_BOXING_OFF 0x00 | ||
| 191 | #define R5_PICTURE_INSIDE_BOXING_ON 0x01 | ||
| 192 | |||
| 193 | #define R5_PICTURE_OUTSIDE_BOXING_OFF 0x00 | ||
| 194 | #define R5_PICTURE_OUTSIDE_BOXING_ON 0x02 | ||
| 195 | |||
| 196 | #define R5_TEXT_INSIDE_BOXING_OFF 0x00 | ||
| 197 | #define R5_TEXT_INSIDE_BOXING_ON 0x04 | ||
| 198 | |||
| 199 | #define R5_TEXT_OUTSIDE_BOXING_OFF 0x00 | ||
| 200 | #define R5_TEXT_OUTSIDE_BOXING_ON 0x08 | ||
| 201 | |||
| 202 | #define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 | ||
| 203 | #define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 | ||
| 204 | |||
| 205 | #define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 | ||
| 206 | #define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 | ||
| 207 | |||
| 208 | #define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 | ||
| 209 | #define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 | ||
| 210 | |||
| 211 | #define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 | ||
| 212 | #define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 | ||
| 213 | |||
| 214 | /* Register R6 (Newsflash display) */ | ||
| 215 | #define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF 0x00 | ||
| 216 | #define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON 0x01 | ||
| 217 | |||
| 218 | #define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF 0x00 | ||
| 219 | #define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON 0x02 | ||
| 220 | |||
| 221 | #define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF 0x00 | ||
| 222 | #define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON 0x04 | ||
| 223 | |||
| 224 | #define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF 0x00 | ||
| 225 | #define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON 0x08 | ||
| 226 | |||
| 227 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 | ||
| 228 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 | ||
| 229 | |||
| 230 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 | ||
| 231 | #define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 | ||
| 232 | |||
| 233 | #define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 | ||
| 234 | #define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 | ||
| 235 | |||
| 236 | #define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 | ||
| 237 | #define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 | ||
| 238 | |||
| 239 | /* Register R7 (Display mode) */ | ||
| 240 | #define R7_BOX_OFF_ROW_0 0x00 | ||
| 241 | #define R7_BOX_ON_ROW_0 0x01 | ||
| 242 | |||
| 243 | #define R7_BOX_OFF_ROW_1_TO_23 0x00 | ||
| 244 | #define R7_BOX_ON_ROW_1_TO_23 0x02 | ||
| 245 | |||
| 246 | #define R7_BOX_OFF_ROW_24 0x00 | ||
| 247 | #define R7_BOX_ON_ROW_24 0x04 | ||
| 248 | |||
| 249 | #define R7_SINGLE_HEIGHT 0x00 | ||
| 250 | #define R7_DOUBLE_HEIGHT 0x08 | ||
| 251 | |||
| 252 | #define R7_TOP_HALF 0x00 | ||
| 253 | #define R7_BOTTOM_HALF 0x10 | ||
| 254 | |||
| 255 | #define R7_REVEAL_OFF 0x00 | ||
| 256 | #define R7_REVEAL_ON 0x20 | ||
| 257 | |||
| 258 | #define R7_CURSER_OFF 0x00 | ||
| 259 | #define R7_CURSER_ON 0x40 | ||
| 260 | |||
| 261 | #define R7_STATUS_BOTTOM 0x00 | ||
| 262 | #define R7_STATUS_TOP 0x80 | ||
| 263 | |||
| 264 | /* Register R8 (Active chapter) */ | ||
| 265 | #define R8_ACTIVE_CHAPTER_0 0x00 | ||
| 266 | #define R8_ACTIVE_CHAPTER_1 0x01 | ||
| 267 | #define R8_ACTIVE_CHAPTER_2 0x02 | ||
| 268 | #define R8_ACTIVE_CHAPTER_3 0x03 | ||
| 269 | #define R8_ACTIVE_CHAPTER_4 0x04 | ||
| 270 | #define R8_ACTIVE_CHAPTER_5 0x05 | ||
| 271 | #define R8_ACTIVE_CHAPTER_6 0x06 | ||
| 272 | #define R8_ACTIVE_CHAPTER_7 0x07 | ||
| 273 | |||
| 274 | #define R8_CLEAR_MEMORY 0x08 | ||
| 275 | #define R8_DO_NOT_CLEAR_MEMORY 0x00 | ||
| 276 | |||
| 277 | /* Register R9 (Curser row) */ | ||
| 278 | #define R9_CURSER_ROW_0 0x00 | ||
| 279 | #define R9_CURSER_ROW_1 0x01 | ||
| 280 | #define R9_CURSER_ROW_2 0x02 | ||
| 281 | #define R9_CURSER_ROW_25 0x19 | ||
| 282 | |||
| 283 | /* Register R10 (Curser column) */ | ||
| 284 | #define R10_CURSER_COLUMN_0 0x00 | ||
| 285 | #define R10_CURSER_COLUMN_6 0x06 | ||
| 286 | #define R10_CURSER_COLUMN_8 0x08 | ||
| 287 | |||
| 288 | /*****************************************************************************/ | ||
| 289 | /* Row 25 control data in column 0 to 9 */ | ||
| 290 | /*****************************************************************************/ | ||
| 291 | #define ROW25_COLUMN0_PAGE_UNITS 0x0F | ||
| 292 | |||
| 293 | #define ROW25_COLUMN1_PAGE_TENS 0x0F | ||
| 294 | |||
| 295 | #define ROW25_COLUMN2_MINUTES_UNITS 0x0F | ||
| 296 | |||
| 297 | #define ROW25_COLUMN3_MINUTES_TENS 0x07 | ||
| 298 | #define ROW25_COLUMN3_DELETE_PAGE 0x08 | ||
| 299 | |||
| 300 | #define ROW25_COLUMN4_HOUR_UNITS 0x0F | ||
| 301 | |||
| 302 | #define ROW25_COLUMN5_HOUR_TENS 0x03 | ||
| 303 | #define ROW25_COLUMN5_INSERT_HEADLINE 0x04 | ||
| 304 | #define ROW25_COLUMN5_INSERT_SUBTITLE 0x08 | ||
| 305 | |||
| 306 | #define ROW25_COLUMN6_SUPPRESS_HEADER 0x01 | ||
| 307 | #define ROW25_COLUMN6_UPDATE_PAGE 0x02 | ||
| 308 | #define ROW25_COLUMN6_INTERRUPTED_SEQUENCE 0x04 | ||
| 309 | #define ROW25_COLUMN6_SUPPRESS_DISPLAY 0x08 | ||
| 310 | |||
| 311 | #define ROW25_COLUMN7_SERIAL_MODE 0x01 | ||
| 312 | #define ROW25_COLUMN7_CHARACTER_SET 0x0E | ||
| 313 | |||
| 314 | #define ROW25_COLUMN8_PAGE_HUNDREDS 0x07 | ||
| 315 | #define ROW25_COLUMN8_PAGE_NOT_FOUND 0x10 | ||
| 316 | |||
| 317 | #define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR 0x20 | ||
| 318 | |||
| 319 | #define ROW25_COLUMN0_TO_7_HAMMING_ERROR 0x10 | ||
| 320 | |||
| 321 | /*****************************************************************************/ | ||
| 322 | /* Helper macros for extracting page, hour and minute digits */ | ||
| 323 | /*****************************************************************************/ | ||
| 324 | /* BYTE_POS 0 is at row 0, column 0, | ||
| 325 | BYTE_POS 1 is at row 0, column 1, | ||
| 326 | BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40) | ||
| 327 | BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40), | ||
| 328 | ... */ | ||
| 329 | #define ROW(BYTE_POS) (BYTE_POS / NUM_ROWS_PER_PAGE) | ||
| 330 | #define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE) | ||
| 331 | |||
| 332 | /*****************************************************************************/ | ||
| 333 | /* Helper macros for extracting page, hour and minute digits */ | ||
| 334 | /*****************************************************************************/ | ||
| 335 | /* Macros for extracting hundreds, tens and units of a page number which | ||
| 336 | must be in the range 0 ... 0x799. | ||
| 337 | Note that page is coded in hexadecimal, i.e. 0x123 means page 123. | ||
| 338 | page 0x.. means page 8.. */ | ||
| 339 | #define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7) | ||
| 340 | #define TENS_OF_PAGE(page) (((page) / 0x10) & 0xF) | ||
| 341 | #define UNITS_OF_PAGE(page) ((page) & 0xF) | ||
| 342 | |||
| 343 | /* Macros for extracting tens and units of a hour information which | ||
| 344 | must be in the range 0 ... 0x24. | ||
| 345 | Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */ | ||
| 346 | #define TENS_OF_HOUR(hour) ((hour) / 0x10) | ||
| 347 | #define UNITS_OF_HOUR(hour) ((hour) & 0xF) | ||
| 348 | |||
| 349 | /* Macros for extracting tens and units of a minute information which | ||
| 350 | must be in the range 0 ... 0x59. | ||
| 351 | Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */ | ||
| 352 | #define TENS_OF_MINUTE(minute) ((minute) / 0x10) | ||
| 353 | #define UNITS_OF_MINUTE(minute) ((minute) & 0xF) | ||
| 354 | |||
| 355 | #define HOUR_MAX 0x23 | ||
| 356 | #define MINUTE_MAX 0x59 | ||
| 357 | #define PAGE_MAX 0x8FF | ||
| 358 | |||
| 359 | #endif /* __SAA5246A_H__ */ | ||
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 0d639738d4e6..3bb959c25d9d 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c | |||
| @@ -15,8 +15,6 @@ | |||
| 15 | * | 15 | * |
| 16 | * Copyright (c) 1998 Richard Guenther <richard.guenther@student.uni-tuebingen.de> | 16 | * Copyright (c) 1998 Richard Guenther <richard.guenther@student.uni-tuebingen.de> |
| 17 | * | 17 | * |
| 18 | * $Id: saa5249.c,v 1.1 1998/03/30 22:23:23 alan Exp $ | ||
| 19 | * | ||
| 20 | * Derived From | 18 | * Derived From |
| 21 | * | 19 | * |
| 22 | * vtx.c: | 20 | * vtx.c: |
| @@ -45,33 +43,28 @@ | |||
| 45 | 43 | ||
| 46 | #include <linux/module.h> | 44 | #include <linux/module.h> |
| 47 | #include <linux/kernel.h> | 45 | #include <linux/kernel.h> |
| 48 | #include <linux/sched.h> | ||
| 49 | #include <linux/mm.h> | 46 | #include <linux/mm.h> |
| 50 | #include <linux/errno.h> | ||
| 51 | #include <linux/delay.h> | ||
| 52 | #include <linux/ioport.h> | ||
| 53 | #include <linux/slab.h> | ||
| 54 | #include <linux/init.h> | 47 | #include <linux/init.h> |
| 55 | #include <stdarg.h> | ||
| 56 | #include <linux/i2c.h> | 48 | #include <linux/i2c.h> |
| 49 | #include <linux/smp_lock.h> | ||
| 50 | #include <linux/mutex.h> | ||
| 51 | #include <linux/delay.h> | ||
| 57 | #include <linux/videotext.h> | 52 | #include <linux/videotext.h> |
| 58 | #include <linux/videodev.h> | 53 | #include <linux/videodev.h> |
| 59 | #include <media/v4l2-common.h> | 54 | #include <media/v4l2-common.h> |
| 60 | #include <media/v4l2-ioctl.h> | 55 | #include <media/v4l2-ioctl.h> |
| 61 | #include <linux/mutex.h> | 56 | #include <media/v4l2-i2c-drv-legacy.h> |
| 62 | |||
| 63 | 57 | ||
| 64 | #include <asm/io.h> | 58 | MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>"); |
| 65 | #include <asm/uaccess.h> | 59 | MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver"); |
| 60 | MODULE_LICENSE("GPL"); | ||
| 66 | 61 | ||
| 67 | #define VTX_VER_MAJ 1 | 62 | #define VTX_VER_MAJ 1 |
| 68 | #define VTX_VER_MIN 8 | 63 | #define VTX_VER_MIN 8 |
| 69 | 64 | ||
| 70 | 65 | ||
| 71 | |||
| 72 | #define NUM_DAUS 4 | 66 | #define NUM_DAUS 4 |
| 73 | #define NUM_BUFS 8 | 67 | #define NUM_BUFS 8 |
| 74 | #define IF_NAME "SAA5249" | ||
| 75 | 68 | ||
| 76 | static const int disp_modes[8][3] = | 69 | static const int disp_modes[8][3] = |
| 77 | { | 70 | { |
| @@ -109,6 +102,7 @@ struct saa5249_device | |||
| 109 | int disp_mode; | 102 | int disp_mode; |
| 110 | int virtual_mode; | 103 | int virtual_mode; |
| 111 | struct i2c_client *client; | 104 | struct i2c_client *client; |
| 105 | unsigned long in_use; | ||
| 112 | struct mutex lock; | 106 | struct mutex lock; |
| 113 | }; | 107 | }; |
| 114 | 108 | ||
| @@ -123,125 +117,8 @@ struct saa5249_device | |||
| 123 | 117 | ||
| 124 | #define VTX_DEV_MINOR 0 | 118 | #define VTX_DEV_MINOR 0 |
| 125 | 119 | ||
| 126 | /* General defines and debugging support */ | ||
| 127 | |||
| 128 | #define RESCHED do { cond_resched(); } while(0) | ||
| 129 | |||
| 130 | static struct video_device saa_template; /* Declared near bottom */ | 120 | static struct video_device saa_template; /* Declared near bottom */ |
| 131 | 121 | ||
| 132 | /* Addresses to scan */ | ||
| 133 | static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END}; | ||
| 134 | |||
| 135 | I2C_CLIENT_INSMOD; | ||
| 136 | |||
| 137 | static struct i2c_client client_template; | ||
| 138 | |||
| 139 | static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind) | ||
| 140 | { | ||
| 141 | int pgbuf; | ||
| 142 | int err; | ||
| 143 | struct i2c_client *client; | ||
| 144 | struct video_device *vd; | ||
| 145 | struct saa5249_device *t; | ||
| 146 | |||
| 147 | printk(KERN_INFO "saa5249: teletext chip found.\n"); | ||
| 148 | client=kmalloc(sizeof(*client), GFP_KERNEL); | ||
| 149 | if(client==NULL) | ||
| 150 | return -ENOMEM; | ||
| 151 | client_template.adapter = adap; | ||
| 152 | client_template.addr = addr; | ||
| 153 | memcpy(client, &client_template, sizeof(*client)); | ||
| 154 | t = kzalloc(sizeof(*t), GFP_KERNEL); | ||
| 155 | if(t==NULL) | ||
| 156 | { | ||
| 157 | kfree(client); | ||
| 158 | return -ENOMEM; | ||
| 159 | } | ||
| 160 | strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); | ||
| 161 | mutex_init(&t->lock); | ||
| 162 | |||
| 163 | /* | ||
| 164 | * Now create a video4linux device | ||
| 165 | */ | ||
| 166 | |||
| 167 | vd = kmalloc(sizeof(struct video_device), GFP_KERNEL); | ||
| 168 | if(vd==NULL) | ||
| 169 | { | ||
| 170 | kfree(t); | ||
| 171 | kfree(client); | ||
| 172 | return -ENOMEM; | ||
| 173 | } | ||
| 174 | i2c_set_clientdata(client, vd); | ||
| 175 | memcpy(vd, &saa_template, sizeof(*vd)); | ||
| 176 | |||
| 177 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) | ||
| 178 | { | ||
| 179 | memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); | ||
| 180 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); | ||
| 181 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); | ||
| 182 | t->vdau[pgbuf].expire = 0; | ||
| 183 | t->vdau[pgbuf].clrfound = true; | ||
| 184 | t->vdau[pgbuf].stopped = true; | ||
| 185 | t->is_searching[pgbuf] = false; | ||
| 186 | } | ||
| 187 | vd->priv=t; | ||
| 188 | |||
| 189 | |||
| 190 | /* | ||
| 191 | * Register it | ||
| 192 | */ | ||
| 193 | |||
| 194 | if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0) | ||
| 195 | { | ||
| 196 | kfree(t); | ||
| 197 | kfree(vd); | ||
| 198 | kfree(client); | ||
| 199 | return err; | ||
| 200 | } | ||
| 201 | t->client = client; | ||
| 202 | i2c_attach_client(client); | ||
| 203 | return 0; | ||
| 204 | } | ||
| 205 | |||
| 206 | /* | ||
| 207 | * We do most of the hard work when we become a device on the i2c. | ||
| 208 | */ | ||
| 209 | |||
| 210 | static int saa5249_probe(struct i2c_adapter *adap) | ||
| 211 | { | ||
| 212 | if (adap->class & I2C_CLASS_TV_ANALOG) | ||
| 213 | return i2c_probe(adap, &addr_data, saa5249_attach); | ||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | static int saa5249_detach(struct i2c_client *client) | ||
| 218 | { | ||
| 219 | struct video_device *vd = i2c_get_clientdata(client); | ||
| 220 | i2c_detach_client(client); | ||
| 221 | video_unregister_device(vd); | ||
| 222 | kfree(vd->priv); | ||
| 223 | kfree(vd); | ||
| 224 | kfree(client); | ||
| 225 | return 0; | ||
| 226 | } | ||
| 227 | |||
| 228 | /* new I2C driver support */ | ||
| 229 | |||
| 230 | static struct i2c_driver i2c_driver_videotext = | ||
| 231 | { | ||
| 232 | .driver = { | ||
| 233 | .name = IF_NAME, /* name */ | ||
| 234 | }, | ||
| 235 | .id = I2C_DRIVERID_SAA5249, /* in i2c.h */ | ||
| 236 | .attach_adapter = saa5249_probe, | ||
| 237 | .detach_client = saa5249_detach, | ||
| 238 | }; | ||
| 239 | |||
| 240 | static struct i2c_client client_template = { | ||
| 241 | .driver = &i2c_driver_videotext, | ||
| 242 | .name = "(unset)", | ||
| 243 | }; | ||
| 244 | |||
| 245 | /* | 122 | /* |
| 246 | * Wait the given number of jiffies (10ms). This calls the scheduler, so the actual | 123 | * Wait the given number of jiffies (10ms). This calls the scheduler, so the actual |
| 247 | * delay may be longer. | 124 | * delay may be longer. |
| @@ -275,7 +152,7 @@ static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data) | |||
| 275 | buf[0] = reg; | 152 | buf[0] = reg; |
| 276 | memcpy(buf+1, data, count); | 153 | memcpy(buf+1, data, count); |
| 277 | 154 | ||
| 278 | if(i2c_master_send(t->client, buf, count+1)==count+1) | 155 | if (i2c_master_send(t->client, buf, count + 1) == count + 1) |
| 279 | return 0; | 156 | return 0; |
| 280 | return -1; | 157 | return -1; |
| 281 | } | 158 | } |
| @@ -317,246 +194,236 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file, | |||
| 317 | unsigned int cmd, void *arg) | 194 | unsigned int cmd, void *arg) |
| 318 | { | 195 | { |
| 319 | static int virtual_mode = false; | 196 | static int virtual_mode = false; |
| 320 | struct video_device *vd = video_devdata(file); | 197 | struct saa5249_device *t = video_drvdata(file); |
| 321 | struct saa5249_device *t=vd->priv; | ||
| 322 | 198 | ||
| 323 | switch(cmd) | 199 | switch (cmd) { |
| 200 | case VTXIOCGETINFO: | ||
| 324 | { | 201 | { |
| 325 | case VTXIOCGETINFO: | 202 | vtx_info_t *info = arg; |
| 326 | { | 203 | info->version_major = VTX_VER_MAJ; |
| 327 | vtx_info_t *info = arg; | 204 | info->version_minor = VTX_VER_MIN; |
| 328 | info->version_major = VTX_VER_MAJ; | 205 | info->numpages = NUM_DAUS; |
| 329 | info->version_minor = VTX_VER_MIN; | 206 | /*info->cct_type = CCT_TYPE;*/ |
| 330 | info->numpages = NUM_DAUS; | 207 | return 0; |
| 331 | /*info->cct_type = CCT_TYPE;*/ | 208 | } |
| 332 | return 0; | ||
| 333 | } | ||
| 334 | 209 | ||
| 335 | case VTXIOCCLRPAGE: | 210 | case VTXIOCCLRPAGE: |
| 336 | { | 211 | { |
| 337 | vtx_pagereq_t *req = arg; | 212 | vtx_pagereq_t *req = arg; |
| 338 | 213 | ||
| 339 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 214 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
| 340 | return -EINVAL; | 215 | return -EINVAL; |
| 341 | memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); | 216 | memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); |
| 342 | t->vdau[req->pgbuf].clrfound = true; | 217 | t->vdau[req->pgbuf].clrfound = true; |
| 343 | return 0; | 218 | return 0; |
| 344 | } | 219 | } |
| 345 | 220 | ||
| 346 | case VTXIOCCLRFOUND: | 221 | case VTXIOCCLRFOUND: |
| 347 | { | 222 | { |
| 348 | vtx_pagereq_t *req = arg; | 223 | vtx_pagereq_t *req = arg; |
| 349 | 224 | ||
| 350 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 225 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
| 351 | return -EINVAL; | 226 | return -EINVAL; |
| 352 | t->vdau[req->pgbuf].clrfound = true; | 227 | t->vdau[req->pgbuf].clrfound = true; |
| 353 | return 0; | 228 | return 0; |
| 354 | } | 229 | } |
| 355 | 230 | ||
| 356 | case VTXIOCPAGEREQ: | 231 | case VTXIOCPAGEREQ: |
| 357 | { | 232 | { |
| 358 | vtx_pagereq_t *req = arg; | 233 | vtx_pagereq_t *req = arg; |
| 359 | if (!(req->pagemask & PGMASK_PAGE)) | 234 | if (!(req->pagemask & PGMASK_PAGE)) |
| 360 | req->page = 0; | 235 | req->page = 0; |
| 361 | if (!(req->pagemask & PGMASK_HOUR)) | 236 | if (!(req->pagemask & PGMASK_HOUR)) |
| 362 | req->hour = 0; | 237 | req->hour = 0; |
| 363 | if (!(req->pagemask & PGMASK_MINUTE)) | 238 | if (!(req->pagemask & PGMASK_MINUTE)) |
| 364 | req->minute = 0; | 239 | req->minute = 0; |
| 365 | if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */ | 240 | if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */ |
| 366 | return -EINVAL; | 241 | return -EINVAL; |
| 367 | req->page &= 0x7ff; | 242 | req->page &= 0x7ff; |
| 368 | if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f || | 243 | if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f || |
| 369 | req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 244 | req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
| 370 | return -EINVAL; | 245 | return -EINVAL; |
| 371 | t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100); | 246 | t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100); |
| 372 | t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf); | 247 | t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf); |
| 373 | t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf); | 248 | t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf); |
| 374 | t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10); | 249 | t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10); |
| 375 | t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf); | 250 | t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf); |
| 376 | t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10); | 251 | t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10); |
| 377 | t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf); | 252 | t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf); |
| 378 | t->vdau[req->pgbuf].stopped = false; | 253 | t->vdau[req->pgbuf].stopped = false; |
| 379 | t->vdau[req->pgbuf].clrfound = true; | 254 | t->vdau[req->pgbuf].clrfound = true; |
| 380 | t->is_searching[req->pgbuf] = true; | 255 | t->is_searching[req->pgbuf] = true; |
| 381 | return 0; | 256 | return 0; |
| 382 | } | 257 | } |
| 383 | 258 | ||
| 384 | case VTXIOCGETSTAT: | 259 | case VTXIOCGETSTAT: |
| 385 | { | 260 | { |
| 386 | vtx_pagereq_t *req = arg; | 261 | vtx_pagereq_t *req = arg; |
| 387 | u8 infobits[10]; | 262 | u8 infobits[10]; |
| 388 | vtx_pageinfo_t info; | 263 | vtx_pageinfo_t info; |
| 389 | int a; | 264 | int a; |
| 390 | 265 | ||
| 391 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 266 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
| 392 | return -EINVAL; | 267 | return -EINVAL; |
| 393 | if (!t->vdau[req->pgbuf].stopped) | 268 | if (!t->vdau[req->pgbuf].stopped) { |
| 394 | { | 269 | if (i2c_senddata(t, 2, 0, -1) || |
| 395 | if (i2c_senddata(t, 2, 0, -1) || | 270 | i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) || |
| 396 | i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) || | 271 | i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) || |
| 397 | i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) || | 272 | i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) || |
| 398 | i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) || | 273 | i2c_senddata(t, 8, 0, 25, 0, -1)) |
| 399 | i2c_senddata(t, 8, 0, 25, 0, -1)) | 274 | return -EIO; |
| 400 | return -EIO; | 275 | jdelay(PAGE_WAIT); |
| 401 | jdelay(PAGE_WAIT); | 276 | if (i2c_getdata(t, 10, infobits)) |
| 402 | if (i2c_getdata(t, 10, infobits)) | 277 | return -EIO; |
| 403 | return -EIO; | ||
| 404 | 278 | ||
| 405 | if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */ | 279 | if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */ |
| 406 | (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) || | 280 | (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) || |
| 407 | time_after_eq(jiffies, t->vdau[req->pgbuf].expire))) | 281 | time_after_eq(jiffies, t->vdau[req->pgbuf].expire))) |
| 408 | { /* check if new page arrived */ | 282 | { /* check if new page arrived */ |
| 409 | if (i2c_senddata(t, 8, 0, 0, 0, -1) || | 283 | if (i2c_senddata(t, 8, 0, 0, 0, -1) || |
| 410 | i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf)) | 284 | i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf)) |
| 285 | return -EIO; | ||
| 286 | t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE; | ||
| 287 | memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE); | ||
| 288 | if (t->virtual_mode) { | ||
| 289 | /* Packet X/24 */ | ||
| 290 | if (i2c_senddata(t, 8, 0, 0x20, 0, -1) || | ||
| 291 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40)) | ||
| 292 | return -EIO; | ||
| 293 | /* Packet X/27/0 */ | ||
| 294 | if (i2c_senddata(t, 8, 0, 0x21, 0, -1) || | ||
| 295 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40)) | ||
| 296 | return -EIO; | ||
| 297 | /* Packet 8/30/0...8/30/15 | ||
| 298 | * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30, | ||
| 299 | * so we should undo this here. | ||
| 300 | */ | ||
| 301 | if (i2c_senddata(t, 8, 0, 0x22, 0, -1) || | ||
| 302 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40)) | ||
| 411 | return -EIO; | 303 | return -EIO; |
| 412 | t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE; | ||
| 413 | memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE); | ||
| 414 | if (t->virtual_mode) | ||
| 415 | { | ||
| 416 | /* Packet X/24 */ | ||
| 417 | if (i2c_senddata(t, 8, 0, 0x20, 0, -1) || | ||
| 418 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40)) | ||
| 419 | return -EIO; | ||
| 420 | /* Packet X/27/0 */ | ||
| 421 | if (i2c_senddata(t, 8, 0, 0x21, 0, -1) || | ||
| 422 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40)) | ||
| 423 | return -EIO; | ||
| 424 | /* Packet 8/30/0...8/30/15 | ||
| 425 | * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30, | ||
| 426 | * so we should undo this here. | ||
| 427 | */ | ||
| 428 | if (i2c_senddata(t, 8, 0, 0x22, 0, -1) || | ||
| 429 | i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40)) | ||
| 430 | return -EIO; | ||
| 431 | } | ||
| 432 | t->vdau[req->pgbuf].clrfound = false; | ||
| 433 | memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits)); | ||
| 434 | } | ||
| 435 | else | ||
| 436 | { | ||
| 437 | memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); | ||
| 438 | } | 304 | } |
| 439 | } | 305 | t->vdau[req->pgbuf].clrfound = false; |
| 440 | else | 306 | memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits)); |
| 441 | { | 307 | } else { |
| 442 | memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); | 308 | memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); |
| 443 | } | 309 | } |
| 310 | } else { | ||
| 311 | memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)); | ||
| 312 | } | ||
| 444 | 313 | ||
| 445 | info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f); | 314 | info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f); |
| 446 | if (info.pagenum < 0x100) | 315 | if (info.pagenum < 0x100) |
| 447 | info.pagenum += 0x800; | 316 | info.pagenum += 0x800; |
| 448 | info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f); | 317 | info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f); |
| 449 | info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f); | 318 | info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f); |
| 450 | info.charset = ((infobits[7] >> 1) & 7); | 319 | info.charset = ((infobits[7] >> 1) & 7); |
| 451 | info.delete = !!(infobits[3] & 8); | 320 | info.delete = !!(infobits[3] & 8); |
| 452 | info.headline = !!(infobits[5] & 4); | 321 | info.headline = !!(infobits[5] & 4); |
| 453 | info.subtitle = !!(infobits[5] & 8); | 322 | info.subtitle = !!(infobits[5] & 8); |
| 454 | info.supp_header = !!(infobits[6] & 1); | 323 | info.supp_header = !!(infobits[6] & 1); |
| 455 | info.update = !!(infobits[6] & 2); | 324 | info.update = !!(infobits[6] & 2); |
| 456 | info.inter_seq = !!(infobits[6] & 4); | 325 | info.inter_seq = !!(infobits[6] & 4); |
| 457 | info.dis_disp = !!(infobits[6] & 8); | 326 | info.dis_disp = !!(infobits[6] & 8); |
| 458 | info.serial = !!(infobits[7] & 1); | 327 | info.serial = !!(infobits[7] & 1); |
| 459 | info.notfound = !!(infobits[8] & 0x10); | 328 | info.notfound = !!(infobits[8] & 0x10); |
| 460 | info.pblf = !!(infobits[9] & 0x20); | 329 | info.pblf = !!(infobits[9] & 0x20); |
| 461 | info.hamming = 0; | 330 | info.hamming = 0; |
| 462 | for (a = 0; a <= 7; a++) | 331 | for (a = 0; a <= 7; a++) { |
| 463 | { | 332 | if (infobits[a] & 0xf0) { |
| 464 | if (infobits[a] & 0xf0) | 333 | info.hamming = 1; |
| 465 | { | 334 | break; |
| 466 | info.hamming = 1; | ||
| 467 | break; | ||
| 468 | } | ||
| 469 | } | ||
| 470 | if (t->vdau[req->pgbuf].clrfound) | ||
| 471 | info.notfound = 1; | ||
| 472 | if(copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t))) | ||
| 473 | return -EFAULT; | ||
| 474 | if (!info.hamming && !info.notfound) | ||
| 475 | { | ||
| 476 | t->is_searching[req->pgbuf] = false; | ||
| 477 | } | 335 | } |
| 478 | return 0; | ||
| 479 | } | 336 | } |
| 337 | if (t->vdau[req->pgbuf].clrfound) | ||
| 338 | info.notfound = 1; | ||
| 339 | if (copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t))) | ||
| 340 | return -EFAULT; | ||
| 341 | if (!info.hamming && !info.notfound) | ||
| 342 | t->is_searching[req->pgbuf] = false; | ||
| 343 | return 0; | ||
| 344 | } | ||
| 480 | 345 | ||
| 481 | case VTXIOCGETPAGE: | 346 | case VTXIOCGETPAGE: |
| 482 | { | 347 | { |
| 483 | vtx_pagereq_t *req = arg; | 348 | vtx_pagereq_t *req = arg; |
| 484 | int start, end; | 349 | int start, end; |
| 485 | 350 | ||
| 486 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 || | 351 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 || |
| 487 | req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE)) | 352 | req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE)) |
| 488 | return -EINVAL; | 353 | return -EINVAL; |
| 489 | if(copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1)) | 354 | if (copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1)) |
| 355 | return -EFAULT; | ||
| 356 | |||
| 357 | /* | ||
| 358 | * Always read the time directly from SAA5249 | ||
| 359 | */ | ||
| 360 | |||
| 361 | if (req->start <= 39 && req->end >= 32) { | ||
| 362 | int len; | ||
| 363 | char buf[16]; | ||
| 364 | start = max(req->start, 32); | ||
| 365 | end = min(req->end, 39); | ||
| 366 | len = end - start + 1; | ||
| 367 | if (i2c_senddata(t, 8, 0, 0, start, -1) || | ||
| 368 | i2c_getdata(t, len, buf)) | ||
| 369 | return -EIO; | ||
| 370 | if (copy_to_user(req->buffer + start - req->start, buf, len)) | ||
| 371 | return -EFAULT; | ||
| 372 | } | ||
| 373 | /* Insert the current header if DAU is still searching for a page */ | ||
| 374 | if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) { | ||
| 375 | char buf[32]; | ||
| 376 | int len; | ||
| 377 | |||
| 378 | start = max(req->start, 7); | ||
| 379 | end = min(req->end, 31); | ||
| 380 | len = end - start + 1; | ||
| 381 | if (i2c_senddata(t, 8, 0, 0, start, -1) || | ||
| 382 | i2c_getdata(t, len, buf)) | ||
| 383 | return -EIO; | ||
| 384 | if (copy_to_user(req->buffer + start - req->start, buf, len)) | ||
| 490 | return -EFAULT; | 385 | return -EFAULT; |
| 491 | |||
| 492 | /* | ||
| 493 | * Always read the time directly from SAA5249 | ||
| 494 | */ | ||
| 495 | |||
| 496 | if (req->start <= 39 && req->end >= 32) | ||
| 497 | { | ||
| 498 | int len; | ||
| 499 | char buf[16]; | ||
| 500 | start = max(req->start, 32); | ||
| 501 | end = min(req->end, 39); | ||
| 502 | len=end-start+1; | ||
| 503 | if (i2c_senddata(t, 8, 0, 0, start, -1) || | ||
| 504 | i2c_getdata(t, len, buf)) | ||
| 505 | return -EIO; | ||
| 506 | if(copy_to_user(req->buffer+start-req->start, buf, len)) | ||
| 507 | return -EFAULT; | ||
| 508 | } | ||
| 509 | /* Insert the current header if DAU is still searching for a page */ | ||
| 510 | if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) | ||
| 511 | { | ||
| 512 | char buf[32]; | ||
| 513 | int len; | ||
| 514 | start = max(req->start, 7); | ||
| 515 | end = min(req->end, 31); | ||
| 516 | len=end-start+1; | ||
| 517 | if (i2c_senddata(t, 8, 0, 0, start, -1) || | ||
| 518 | i2c_getdata(t, len, buf)) | ||
| 519 | return -EIO; | ||
| 520 | if(copy_to_user(req->buffer+start-req->start, buf, len)) | ||
| 521 | return -EFAULT; | ||
| 522 | } | ||
| 523 | return 0; | ||
| 524 | } | 386 | } |
| 387 | return 0; | ||
| 388 | } | ||
| 525 | 389 | ||
| 526 | case VTXIOCSTOPDAU: | 390 | case VTXIOCSTOPDAU: |
| 527 | { | 391 | { |
| 528 | vtx_pagereq_t *req = arg; | 392 | vtx_pagereq_t *req = arg; |
| 529 | 393 | ||
| 530 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) | 394 | if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) |
| 531 | return -EINVAL; | 395 | return -EINVAL; |
| 532 | t->vdau[req->pgbuf].stopped = true; | 396 | t->vdau[req->pgbuf].stopped = true; |
| 533 | t->is_searching[req->pgbuf] = false; | 397 | t->is_searching[req->pgbuf] = false; |
| 534 | return 0; | 398 | return 0; |
| 535 | } | 399 | } |
| 536 | 400 | ||
| 537 | case VTXIOCPUTPAGE: | 401 | case VTXIOCPUTPAGE: |
| 538 | case VTXIOCSETDISP: | 402 | case VTXIOCSETDISP: |
| 539 | case VTXIOCPUTSTAT: | 403 | case VTXIOCPUTSTAT: |
| 540 | return 0; | 404 | return 0; |
| 541 | 405 | ||
| 542 | case VTXIOCCLRCACHE: | 406 | case VTXIOCCLRCACHE: |
| 543 | { | 407 | { |
| 544 | if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11, | 408 | if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11, |
| 545 | ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', | 409 | ' ', ' ', ' ', ' ', ' ', ' ', |
| 546 | ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', -1)) | 410 | ' ', ' ', ' ', ' ', ' ', ' ', |
| 547 | return -EIO; | 411 | ' ', ' ', ' ', ' ', ' ', ' ', |
| 548 | if (i2c_senddata(t, 3, 0x20, -1)) | 412 | ' ', ' ', ' ', ' ', ' ', ' ', |
| 549 | return -EIO; | 413 | -1)) |
| 550 | jdelay(10 * CLEAR_DELAY); /* I have no idea how long we have to wait here */ | 414 | return -EIO; |
| 551 | return 0; | 415 | if (i2c_senddata(t, 3, 0x20, -1)) |
| 552 | } | 416 | return -EIO; |
| 417 | jdelay(10 * CLEAR_DELAY); /* I have no idea how long we have to wait here */ | ||
| 418 | return 0; | ||
| 419 | } | ||
| 553 | 420 | ||
| 554 | case VTXIOCSETVIRT: | 421 | case VTXIOCSETVIRT: |
| 555 | { | 422 | { |
| 556 | /* The SAA5249 has virtual-row reception turned on always */ | 423 | /* The SAA5249 has virtual-row reception turned on always */ |
| 557 | t->virtual_mode = (int)(long)arg; | 424 | t->virtual_mode = (int)(long)arg; |
| 558 | return 0; | 425 | return 0; |
| 559 | } | 426 | } |
| 560 | } | 427 | } |
| 561 | return -EINVAL; | 428 | return -EINVAL; |
| 562 | } | 429 | } |
| @@ -616,8 +483,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd) | |||
| 616 | static int saa5249_ioctl(struct inode *inode, struct file *file, | 483 | static int saa5249_ioctl(struct inode *inode, struct file *file, |
| 617 | unsigned int cmd, unsigned long arg) | 484 | unsigned int cmd, unsigned long arg) |
| 618 | { | 485 | { |
| 619 | struct video_device *vd = video_devdata(file); | 486 | struct saa5249_device *t = video_drvdata(file); |
| 620 | struct saa5249_device *t=vd->priv; | ||
| 621 | int err; | 487 | int err; |
| 622 | 488 | ||
| 623 | cmd = vtx_fix_command(cmd); | 489 | cmd = vtx_fix_command(cmd); |
| @@ -629,32 +495,27 @@ static int saa5249_ioctl(struct inode *inode, struct file *file, | |||
| 629 | 495 | ||
| 630 | static int saa5249_open(struct inode *inode, struct file *file) | 496 | static int saa5249_open(struct inode *inode, struct file *file) |
| 631 | { | 497 | { |
| 632 | struct video_device *vd = video_devdata(file); | 498 | struct saa5249_device *t = video_drvdata(file); |
| 633 | struct saa5249_device *t=vd->priv; | 499 | int pgbuf; |
| 634 | int err,pgbuf; | ||
| 635 | 500 | ||
| 636 | err = video_exclusive_open(inode,file); | 501 | if (t->client == NULL) |
| 637 | if (err < 0) | 502 | return -ENODEV; |
| 638 | return err; | ||
| 639 | 503 | ||
| 640 | if (t->client==NULL) { | 504 | if (test_and_set_bit(0, &t->in_use)) |
| 641 | err = -ENODEV; | 505 | return -EBUSY; |
| 642 | goto fail; | ||
| 643 | } | ||
| 644 | 506 | ||
| 645 | if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */ | 507 | if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */ |
| 646 | /* Turn off parity checks (we do this ourselves) */ | 508 | /* Turn off parity checks (we do this ourselves) */ |
| 647 | i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) || | 509 | i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) || |
| 648 | /* Display TV-picture, no virtual rows */ | 510 | /* Display TV-picture, no virtual rows */ |
| 649 | i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) /* Set display to page 4 */ | 511 | i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) |
| 650 | 512 | /* Set display to page 4 */ | |
| 651 | { | 513 | { |
| 652 | err = -EIO; | 514 | clear_bit(0, &t->in_use); |
| 653 | goto fail; | 515 | return -EIO; |
| 654 | } | 516 | } |
| 655 | 517 | ||
| 656 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) | 518 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { |
| 657 | { | ||
| 658 | memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); | 519 | memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); |
| 659 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); | 520 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); |
| 660 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); | 521 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); |
| @@ -665,39 +526,20 @@ static int saa5249_open(struct inode *inode, struct file *file) | |||
| 665 | } | 526 | } |
| 666 | t->virtual_mode = false; | 527 | t->virtual_mode = false; |
| 667 | return 0; | 528 | return 0; |
| 668 | |||
| 669 | fail: | ||
| 670 | video_exclusive_release(inode,file); | ||
| 671 | return err; | ||
| 672 | } | 529 | } |
| 673 | 530 | ||
| 674 | 531 | ||
| 675 | 532 | ||
| 676 | static int saa5249_release(struct inode *inode, struct file *file) | 533 | static int saa5249_release(struct inode *inode, struct file *file) |
| 677 | { | 534 | { |
| 678 | struct video_device *vd = video_devdata(file); | 535 | struct saa5249_device *t = video_drvdata(file); |
| 679 | struct saa5249_device *t=vd->priv; | 536 | |
| 680 | i2c_senddata(t, 1, 0x20, -1); /* Turn off CCT */ | 537 | i2c_senddata(t, 1, 0x20, -1); /* Turn off CCT */ |
| 681 | i2c_senddata(t, 5, 3, 3, -1); /* Turn off TV-display */ | 538 | i2c_senddata(t, 5, 3, 3, -1); /* Turn off TV-display */ |
| 682 | video_exclusive_release(inode,file); | 539 | clear_bit(0, &t->in_use); |
| 683 | return 0; | 540 | return 0; |
| 684 | } | 541 | } |
| 685 | 542 | ||
| 686 | static int __init init_saa_5249 (void) | ||
| 687 | { | ||
| 688 | printk(KERN_INFO "SAA5249 driver (" IF_NAME " interface) for VideoText version %d.%d\n", | ||
| 689 | VTX_VER_MAJ, VTX_VER_MIN); | ||
| 690 | return i2c_add_driver(&i2c_driver_videotext); | ||
| 691 | } | ||
| 692 | |||
| 693 | static void __exit cleanup_saa_5249 (void) | ||
| 694 | { | ||
| 695 | i2c_del_driver(&i2c_driver_videotext); | ||
| 696 | } | ||
| 697 | |||
| 698 | module_init(init_saa_5249); | ||
| 699 | module_exit(cleanup_saa_5249); | ||
| 700 | |||
| 701 | static const struct file_operations saa_fops = { | 543 | static const struct file_operations saa_fops = { |
| 702 | .owner = THIS_MODULE, | 544 | .owner = THIS_MODULE, |
| 703 | .open = saa5249_open, | 545 | .open = saa5249_open, |
| @@ -711,8 +553,84 @@ static const struct file_operations saa_fops = { | |||
| 711 | 553 | ||
| 712 | static struct video_device saa_template = | 554 | static struct video_device saa_template = |
| 713 | { | 555 | { |
| 714 | .name = IF_NAME, | 556 | .name = "saa5249", |
| 715 | .fops = &saa_fops, | 557 | .fops = &saa_fops, |
| 558 | .release = video_device_release, | ||
| 716 | }; | 559 | }; |
| 717 | 560 | ||
| 718 | MODULE_LICENSE("GPL"); | 561 | /* Addresses to scan */ |
| 562 | static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; | ||
| 563 | |||
| 564 | I2C_CLIENT_INSMOD; | ||
| 565 | |||
| 566 | static int saa5249_probe(struct i2c_client *client, | ||
| 567 | const struct i2c_device_id *id) | ||
| 568 | { | ||
| 569 | int pgbuf; | ||
| 570 | int err; | ||
| 571 | struct video_device *vd; | ||
| 572 | struct saa5249_device *t; | ||
| 573 | |||
| 574 | v4l_info(client, "chip found @ 0x%x (%s)\n", | ||
| 575 | client->addr << 1, client->adapter->name); | ||
| 576 | v4l_info(client, "VideoText version %d.%d\n", | ||
| 577 | VTX_VER_MAJ, VTX_VER_MIN); | ||
| 578 | t = kzalloc(sizeof(*t), GFP_KERNEL); | ||
| 579 | if (t == NULL) | ||
| 580 | return -ENOMEM; | ||
| 581 | mutex_init(&t->lock); | ||
| 582 | |||
| 583 | /* Now create a video4linux device */ | ||
| 584 | vd = kmalloc(sizeof(struct video_device), GFP_KERNEL); | ||
| 585 | if (vd == NULL) { | ||
| 586 | kfree(client); | ||
| 587 | return -ENOMEM; | ||
| 588 | } | ||
| 589 | i2c_set_clientdata(client, vd); | ||
| 590 | memcpy(vd, &saa_template, sizeof(*vd)); | ||
| 591 | |||
| 592 | for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { | ||
| 593 | memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); | ||
| 594 | memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs)); | ||
| 595 | memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat)); | ||
| 596 | t->vdau[pgbuf].expire = 0; | ||
| 597 | t->vdau[pgbuf].clrfound = true; | ||
| 598 | t->vdau[pgbuf].stopped = true; | ||
| 599 | t->is_searching[pgbuf] = false; | ||
| 600 | } | ||
| 601 | video_set_drvdata(vd, t); | ||
| 602 | |||
| 603 | /* Register it */ | ||
| 604 | err = video_register_device(vd, VFL_TYPE_VTX, -1); | ||
| 605 | if (err < 0) { | ||
| 606 | kfree(t); | ||
| 607 | kfree(vd); | ||
| 608 | return err; | ||
| 609 | } | ||
| 610 | t->client = client; | ||
| 611 | return 0; | ||
| 612 | } | ||
| 613 | |||
| 614 | static int saa5249_remove(struct i2c_client *client) | ||
| 615 | { | ||
| 616 | struct video_device *vd = i2c_get_clientdata(client); | ||
| 617 | |||
| 618 | video_unregister_device(vd); | ||
| 619 | kfree(video_get_drvdata(vd)); | ||
| 620 | kfree(vd); | ||
| 621 | return 0; | ||
| 622 | } | ||
| 623 | |||
| 624 | static const struct i2c_device_id saa5249_id[] = { | ||
| 625 | { "saa5249", 0 }, | ||
| 626 | { } | ||
| 627 | }; | ||
| 628 | MODULE_DEVICE_TABLE(i2c, saa5249_id); | ||
| 629 | |||
| 630 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
| 631 | .name = "saa5249", | ||
| 632 | .driverid = I2C_DRIVERID_SAA5249, | ||
| 633 | .probe = saa5249_probe, | ||
| 634 | .remove = saa5249_remove, | ||
| 635 | .id_table = saa5249_id, | ||
| 636 | }; | ||
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index ad733caec720..c8e9cb3db30a 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
| @@ -1057,7 +1057,7 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo | |||
| 1057 | for (i = 0; i <= 23; i++) | 1057 | for (i = 0; i <= 23; i++) |
| 1058 | lcr[i] = 0xff; | 1058 | lcr[i] = 0xff; |
| 1059 | 1059 | ||
| 1060 | if (fmt->service_set == 0) { | 1060 | if (fmt == NULL) { |
| 1061 | /* raw VBI */ | 1061 | /* raw VBI */ |
| 1062 | if (is_50hz) | 1062 | if (is_50hz) |
| 1063 | for (i = 6; i <= 23; i++) | 1063 | for (i = 6; i <= 23; i++) |
| @@ -1113,7 +1113,7 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo | |||
| 1113 | } | 1113 | } |
| 1114 | 1114 | ||
| 1115 | /* enable/disable raw VBI capturing */ | 1115 | /* enable/disable raw VBI capturing */ |
| 1116 | saa711x_writeregs(client, fmt->service_set == 0 ? | 1116 | saa711x_writeregs(client, fmt == NULL ? |
| 1117 | saa7115_cfg_vbi_on : | 1117 | saa7115_cfg_vbi_on : |
| 1118 | saa7115_cfg_vbi_off); | 1118 | saa7115_cfg_vbi_off); |
| 1119 | } | 1119 | } |
| @@ -1153,6 +1153,10 @@ static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt | |||
| 1153 | saa711x_set_lcr(client, &fmt->fmt.sliced); | 1153 | saa711x_set_lcr(client, &fmt->fmt.sliced); |
| 1154 | return 0; | 1154 | return 0; |
| 1155 | } | 1155 | } |
| 1156 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
| 1157 | saa711x_set_lcr(client, NULL); | ||
| 1158 | return 0; | ||
| 1159 | } | ||
| 1156 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1160 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
| 1157 | return -EINVAL; | 1161 | return -EINVAL; |
| 1158 | 1162 | ||
| @@ -1309,10 +1313,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
| 1309 | case VIDIOC_INT_S_VIDEO_ROUTING: | 1313 | case VIDIOC_INT_S_VIDEO_ROUTING: |
| 1310 | { | 1314 | { |
| 1311 | struct v4l2_routing *route = arg; | 1315 | struct v4l2_routing *route = arg; |
| 1316 | u32 input = route->input; | ||
| 1317 | u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0; | ||
| 1312 | 1318 | ||
| 1313 | v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); | 1319 | v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); |
| 1314 | /* saa7113 does not have these inputs */ | 1320 | /* saa7111/3 does not have these inputs */ |
| 1315 | if (state->ident == V4L2_IDENT_SAA7113 && | 1321 | if ((state->ident == V4L2_IDENT_SAA7113 || |
| 1322 | state->ident == V4L2_IDENT_SAA7111) && | ||
| 1316 | (route->input == SAA7115_COMPOSITE4 || | 1323 | (route->input == SAA7115_COMPOSITE4 || |
| 1317 | route->input == SAA7115_COMPOSITE5)) { | 1324 | route->input == SAA7115_COMPOSITE5)) { |
| 1318 | return -EINVAL; | 1325 | return -EINVAL; |
| @@ -1327,10 +1334,23 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
| 1327 | (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); | 1334 | (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); |
| 1328 | state->input = route->input; | 1335 | state->input = route->input; |
| 1329 | 1336 | ||
| 1337 | /* saa7111 has slightly different input numbering */ | ||
| 1338 | if (state->ident == V4L2_IDENT_SAA7111) { | ||
| 1339 | if (input >= SAA7115_COMPOSITE4) | ||
| 1340 | input -= 2; | ||
| 1341 | /* saa7111 specific */ | ||
| 1342 | saa711x_write(client, R_10_CHROMA_CNTL_2, | ||
| 1343 | (saa711x_read(client, R_10_CHROMA_CNTL_2) & 0x3f) | | ||
| 1344 | ((route->output & 0xc0) ^ 0x40)); | ||
| 1345 | saa711x_write(client, R_13_RT_X_PORT_OUT_CNTL, | ||
| 1346 | (saa711x_read(client, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) | | ||
| 1347 | ((route->output & 2) ? 0x0a : 0)); | ||
| 1348 | } | ||
| 1349 | |||
| 1330 | /* select mode */ | 1350 | /* select mode */ |
| 1331 | saa711x_write(client, R_02_INPUT_CNTL_1, | 1351 | saa711x_write(client, R_02_INPUT_CNTL_1, |
| 1332 | (saa711x_read(client, R_02_INPUT_CNTL_1) & 0xf0) | | 1352 | (saa711x_read(client, R_02_INPUT_CNTL_1) & mask) | |
| 1333 | state->input); | 1353 | input); |
| 1334 | 1354 | ||
| 1335 | /* bypass chrominance trap for S-Video modes */ | 1355 | /* bypass chrominance trap for S-Video modes */ |
| 1336 | saa711x_write(client, R_09_LUMA_CNTL, | 1356 | saa711x_write(client, R_09_LUMA_CNTL, |
| @@ -1384,6 +1404,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
| 1384 | saa711x_writeregs(client, saa7115_cfg_reset_scaler); | 1404 | saa711x_writeregs(client, saa7115_cfg_reset_scaler); |
| 1385 | break; | 1405 | break; |
| 1386 | 1406 | ||
| 1407 | case VIDIOC_INT_S_GPIO: | ||
| 1408 | if (state->ident != V4L2_IDENT_SAA7111) | ||
| 1409 | return -EINVAL; | ||
| 1410 | saa711x_write(client, 0x11, (saa711x_read(client, 0x11) & 0x7f) | | ||
| 1411 | (*(u32 *)arg ? 0x80 : 0)); | ||
| 1412 | break; | ||
| 1413 | |||
| 1387 | case VIDIOC_INT_G_VBI_DATA: | 1414 | case VIDIOC_INT_G_VBI_DATA: |
| 1388 | { | 1415 | { |
| 1389 | struct v4l2_sliced_vbi_data *data = arg; | 1416 | struct v4l2_sliced_vbi_data *data = arg; |
| @@ -1539,7 +1566,8 @@ static int saa7115_probe(struct i2c_client *client, | |||
| 1539 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; | 1566 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; |
| 1540 | saa711x_writeregs(client, saa7115_init_auto_input); | 1567 | saa711x_writeregs(client, saa7115_init_auto_input); |
| 1541 | } | 1568 | } |
| 1542 | saa711x_writeregs(client, saa7115_init_misc); | 1569 | if (state->ident != V4L2_IDENT_SAA7111) |
| 1570 | saa711x_writeregs(client, saa7115_init_misc); | ||
| 1543 | saa711x_set_v4lstd(client, V4L2_STD_NTSC); | 1571 | saa711x_set_v4lstd(client, V4L2_STD_NTSC); |
| 1544 | 1572 | ||
| 1545 | v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n", | 1573 | v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n", |
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 707be175509d..1fb6eccdade3 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c | |||
| @@ -1,3 +1,27 @@ | |||
| 1 | /* | ||
| 2 | saa6752hs - i2c-driver for the saa6752hs by Philips | ||
| 3 | |||
| 4 | Copyright (C) 2004 Andrew de Quincey | ||
| 5 | |||
| 6 | AC-3 support: | ||
| 7 | |||
| 8 | Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> | ||
| 9 | |||
| 10 | This program is free software; you can redistribute it and/or modify | ||
| 11 | it under the terms of the GNU General Public License vs published by | ||
| 12 | the Free Software Foundation; either version 2 of the License, or | ||
| 13 | (at your option) any later version. | ||
| 14 | |||
| 15 | This program is distributed in the hope that it will be useful, | ||
| 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | GNU General Public License for more details. | ||
| 19 | |||
| 20 | You should have received a copy of the GNU General Public License | ||
| 21 | along with this program; if not, write to the Free Software | ||
| 22 | Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA. | ||
| 23 | */ | ||
| 24 | |||
| 1 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| 2 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 3 | #include <linux/string.h> | 27 | #include <linux/string.h> |
| @@ -10,6 +34,8 @@ | |||
| 10 | #include <linux/types.h> | 34 | #include <linux/types.h> |
| 11 | #include <linux/videodev2.h> | 35 | #include <linux/videodev2.h> |
| 12 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
| 37 | #include <media/v4l2-chip-ident.h> | ||
| 38 | #include <media/v4l2-i2c-drv-legacy.h> | ||
| 13 | #include <linux/init.h> | 39 | #include <linux/init.h> |
| 14 | #include <linux/crc32.h> | 40 | #include <linux/crc32.h> |
| 15 | 41 | ||
| @@ -27,9 +53,6 @@ MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder"); | |||
| 27 | MODULE_AUTHOR("Andrew de Quincey"); | 53 | MODULE_AUTHOR("Andrew de Quincey"); |
| 28 | MODULE_LICENSE("GPL"); | 54 | MODULE_LICENSE("GPL"); |
| 29 | 55 | ||
| 30 | static struct i2c_driver driver; | ||
| 31 | static struct i2c_client client_template; | ||
| 32 | |||
| 33 | enum saa6752hs_videoformat { | 56 | enum saa6752hs_videoformat { |
| 34 | SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */ | 57 | SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */ |
| 35 | SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */ | 58 | SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */ |
| @@ -46,7 +69,9 @@ struct saa6752hs_mpeg_params { | |||
| 46 | __u16 ts_pid_pcr; | 69 | __u16 ts_pid_pcr; |
| 47 | 70 | ||
| 48 | /* audio */ | 71 | /* audio */ |
| 49 | enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; | 72 | enum v4l2_mpeg_audio_encoding au_encoding; |
| 73 | enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; | ||
| 74 | enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate; | ||
| 50 | 75 | ||
| 51 | /* video */ | 76 | /* video */ |
| 52 | enum v4l2_mpeg_video_aspect vi_aspect; | 77 | enum v4l2_mpeg_video_aspect vi_aspect; |
| @@ -70,7 +95,9 @@ static const struct v4l2_format v4l2_format_table[] = | |||
| 70 | }; | 95 | }; |
| 71 | 96 | ||
| 72 | struct saa6752hs_state { | 97 | struct saa6752hs_state { |
| 73 | struct i2c_client client; | 98 | int chip; |
| 99 | u32 revision; | ||
| 100 | int has_ac3; | ||
| 74 | struct saa6752hs_mpeg_params params; | 101 | struct saa6752hs_mpeg_params params; |
| 75 | enum saa6752hs_videoformat video_format; | 102 | enum saa6752hs_videoformat video_format; |
| 76 | v4l2_std_id standard; | 103 | v4l2_std_id standard; |
| @@ -145,6 +172,39 @@ static u8 PMT[] = { | |||
| 145 | 0x00, 0x00, 0x00, 0x00 /* CRC32 */ | 172 | 0x00, 0x00, 0x00, 0x00 /* CRC32 */ |
| 146 | }; | 173 | }; |
| 147 | 174 | ||
| 175 | static u8 PMT_AC3[] = { | ||
| 176 | 0xc2, /* i2c register */ | ||
| 177 | 0x01, /* table number for encoder(1) */ | ||
| 178 | 0x47, /* sync */ | ||
| 179 | |||
| 180 | 0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */ | ||
| 181 | 0x10, /* PMT PID (0x0010) */ | ||
| 182 | 0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */ | ||
| 183 | |||
| 184 | 0x00, /* PSI pointer to start of table */ | ||
| 185 | |||
| 186 | 0x02, /* TID (2) */ | ||
| 187 | 0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */ | ||
| 188 | |||
| 189 | 0x00, 0x01, /* program_number(1) */ | ||
| 190 | |||
| 191 | 0xc1, /* version_number(0), current_next_indicator(1) */ | ||
| 192 | |||
| 193 | 0x00, 0x00, /* section_number(0), last_section_number(0) */ | ||
| 194 | |||
| 195 | 0xe1, 0x04, /* PCR_PID (0x0104) */ | ||
| 196 | |||
| 197 | 0xf0, 0x00, /* program_info_length(0) */ | ||
| 198 | |||
| 199 | 0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */ | ||
| 200 | 0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */ | ||
| 201 | 0x6a, /* AC3 */ | ||
| 202 | 0x01, /* Descriptor_length(1) */ | ||
| 203 | 0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */ | ||
| 204 | |||
| 205 | 0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */ | ||
| 206 | }; | ||
| 207 | |||
| 148 | static struct saa6752hs_mpeg_params param_defaults = | 208 | static struct saa6752hs_mpeg_params param_defaults = |
| 149 | { | 209 | { |
| 150 | .ts_pid_pmt = 16, | 210 | .ts_pid_pmt = 16, |
| @@ -157,12 +217,14 @@ static struct saa6752hs_mpeg_params param_defaults = | |||
| 157 | .vi_bitrate_peak = 6000, | 217 | .vi_bitrate_peak = 6000, |
| 158 | .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, | 218 | .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, |
| 159 | 219 | ||
| 220 | .au_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
| 160 | .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, | 221 | .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, |
| 222 | .au_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_256K, | ||
| 161 | }; | 223 | }; |
| 162 | 224 | ||
| 163 | /* ---------------------------------------------------------------------- */ | 225 | /* ---------------------------------------------------------------------- */ |
| 164 | 226 | ||
| 165 | static int saa6752hs_chip_command(struct i2c_client* client, | 227 | static int saa6752hs_chip_command(struct i2c_client *client, |
| 166 | enum saa6752hs_command command) | 228 | enum saa6752hs_command command) |
| 167 | { | 229 | { |
| 168 | unsigned char buf[3]; | 230 | unsigned char buf[3]; |
| @@ -229,45 +291,61 @@ static int saa6752hs_chip_command(struct i2c_client* client, | |||
| 229 | } | 291 | } |
| 230 | 292 | ||
| 231 | 293 | ||
| 232 | static int saa6752hs_set_bitrate(struct i2c_client* client, | 294 | static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val) |
| 233 | struct saa6752hs_mpeg_params* params) | 295 | { |
| 296 | u8 buf[2]; | ||
| 297 | |||
| 298 | buf[0] = reg; | ||
| 299 | buf[1] = val; | ||
| 300 | i2c_master_send(client, buf, 2); | ||
| 301 | } | ||
| 302 | |||
| 303 | static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val) | ||
| 234 | { | 304 | { |
| 235 | u8 buf[3]; | 305 | u8 buf[3]; |
| 306 | |||
| 307 | buf[0] = reg; | ||
| 308 | buf[1] = val >> 8; | ||
| 309 | buf[2] = val & 0xff; | ||
| 310 | i2c_master_send(client, buf, 3); | ||
| 311 | } | ||
| 312 | |||
| 313 | static int saa6752hs_set_bitrate(struct i2c_client *client, | ||
| 314 | struct saa6752hs_state *h) | ||
| 315 | { | ||
| 316 | struct saa6752hs_mpeg_params *params = &h->params; | ||
| 236 | int tot_bitrate; | 317 | int tot_bitrate; |
| 318 | int is_384k; | ||
| 237 | 319 | ||
| 238 | /* set the bitrate mode */ | 320 | /* set the bitrate mode */ |
| 239 | buf[0] = 0x71; | 321 | set_reg8(client, 0x71, |
| 240 | buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1; | 322 | params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); |
| 241 | i2c_master_send(client, buf, 2); | ||
| 242 | 323 | ||
| 243 | /* set the video bitrate */ | 324 | /* set the video bitrate */ |
| 244 | if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { | 325 | if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { |
| 245 | /* set the target bitrate */ | 326 | /* set the target bitrate */ |
| 246 | buf[0] = 0x80; | 327 | set_reg16(client, 0x80, params->vi_bitrate); |
| 247 | buf[1] = params->vi_bitrate >> 8; | ||
| 248 | buf[2] = params->vi_bitrate & 0xff; | ||
| 249 | i2c_master_send(client, buf, 3); | ||
| 250 | 328 | ||
| 251 | /* set the max bitrate */ | 329 | /* set the max bitrate */ |
| 252 | buf[0] = 0x81; | 330 | set_reg16(client, 0x81, params->vi_bitrate_peak); |
| 253 | buf[1] = params->vi_bitrate_peak >> 8; | ||
| 254 | buf[2] = params->vi_bitrate_peak & 0xff; | ||
| 255 | i2c_master_send(client, buf, 3); | ||
| 256 | tot_bitrate = params->vi_bitrate_peak; | 331 | tot_bitrate = params->vi_bitrate_peak; |
| 257 | } else { | 332 | } else { |
| 258 | /* set the target bitrate (no max bitrate for CBR) */ | 333 | /* set the target bitrate (no max bitrate for CBR) */ |
| 259 | buf[0] = 0x81; | 334 | set_reg16(client, 0x81, params->vi_bitrate); |
| 260 | buf[1] = params->vi_bitrate >> 8; | ||
| 261 | buf[2] = params->vi_bitrate & 0xff; | ||
| 262 | i2c_master_send(client, buf, 3); | ||
| 263 | tot_bitrate = params->vi_bitrate; | 335 | tot_bitrate = params->vi_bitrate; |
| 264 | } | 336 | } |
| 265 | 337 | ||
| 338 | /* set the audio encoding */ | ||
| 339 | set_reg8(client, 0x93, | ||
| 340 | params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3); | ||
| 341 | |||
| 266 | /* set the audio bitrate */ | 342 | /* set the audio bitrate */ |
| 267 | buf[0] = 0x94; | 343 | if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) |
| 268 | buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1; | 344 | is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate; |
| 269 | i2c_master_send(client, buf, 2); | 345 | else |
| 270 | tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384; | 346 | is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate; |
| 347 | set_reg8(client, 0x94, is_384k); | ||
| 348 | tot_bitrate += is_384k ? 384 : 256; | ||
| 271 | 349 | ||
| 272 | /* Note: the total max bitrate is determined by adding the video and audio | 350 | /* Note: the total max bitrate is determined by adding the video and audio |
| 273 | bitrates together and also adding an extra 768kbit/s to stay on the | 351 | bitrates together and also adding an extra 768kbit/s to stay on the |
| @@ -278,16 +356,12 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, | |||
| 278 | tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX; | 356 | tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX; |
| 279 | 357 | ||
| 280 | /* set the total bitrate */ | 358 | /* set the total bitrate */ |
| 281 | buf[0] = 0xb1; | 359 | set_reg16(client, 0xb1, tot_bitrate); |
| 282 | buf[1] = tot_bitrate >> 8; | ||
| 283 | buf[2] = tot_bitrate & 0xff; | ||
| 284 | i2c_master_send(client, buf, 3); | ||
| 285 | |||
| 286 | return 0; | 360 | return 0; |
| 287 | } | 361 | } |
| 288 | 362 | ||
| 289 | static void saa6752hs_set_subsampling(struct i2c_client* client, | 363 | static void saa6752hs_set_subsampling(struct i2c_client *client, |
| 290 | struct v4l2_format* f) | 364 | struct v4l2_format *f) |
| 291 | { | 365 | { |
| 292 | struct saa6752hs_state *h = i2c_get_clientdata(client); | 366 | struct saa6752hs_state *h = i2c_get_clientdata(client); |
| 293 | int dist_352, dist_480, dist_720; | 367 | int dist_352, dist_480, dist_720; |
| @@ -332,7 +406,7 @@ static void saa6752hs_set_subsampling(struct i2c_client* client, | |||
| 332 | } | 406 | } |
| 333 | 407 | ||
| 334 | 408 | ||
| 335 | static int handle_ctrl(struct saa6752hs_mpeg_params *params, | 409 | static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, |
| 336 | struct v4l2_ext_control *ctrl, unsigned int cmd) | 410 | struct v4l2_ext_control *ctrl, unsigned int cmd) |
| 337 | { | 411 | { |
| 338 | int old = 0, new; | 412 | int old = 0, new; |
| @@ -379,8 +453,9 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, | |||
| 379 | params->ts_pid_pcr = new; | 453 | params->ts_pid_pcr = new; |
| 380 | break; | 454 | break; |
| 381 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 455 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
| 382 | old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2; | 456 | old = params->au_encoding; |
| 383 | if (set && new != old) | 457 | if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && |
| 458 | (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) | ||
| 384 | return -ERANGE; | 459 | return -ERANGE; |
| 385 | new = old; | 460 | new = old; |
| 386 | break; | 461 | break; |
| @@ -395,6 +470,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, | |||
| 395 | new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; | 470 | new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; |
| 396 | params->au_l2_bitrate = new; | 471 | params->au_l2_bitrate = new; |
| 397 | break; | 472 | break; |
| 473 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
| 474 | if (!has_ac3) | ||
| 475 | return -EINVAL; | ||
| 476 | old = params->au_ac3_bitrate; | ||
| 477 | if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && | ||
| 478 | new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) | ||
| 479 | return -ERANGE; | ||
| 480 | if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) | ||
| 481 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; | ||
| 482 | else | ||
| 483 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; | ||
| 484 | params->au_ac3_bitrate = new; | ||
| 485 | break; | ||
| 398 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | 486 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
| 399 | old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; | 487 | old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; |
| 400 | if (set && new != old) | 488 | if (set && new != old) |
| @@ -448,17 +536,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, | |||
| 448 | return 0; | 536 | return 0; |
| 449 | } | 537 | } |
| 450 | 538 | ||
| 451 | static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, | 539 | static int saa6752hs_qctrl(struct saa6752hs_state *h, |
| 452 | struct v4l2_queryctrl *qctrl) | 540 | struct v4l2_queryctrl *qctrl) |
| 453 | { | 541 | { |
| 542 | struct saa6752hs_mpeg_params *params = &h->params; | ||
| 454 | int err; | 543 | int err; |
| 455 | 544 | ||
| 456 | switch (qctrl->id) { | 545 | switch (qctrl->id) { |
| 457 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 546 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
| 458 | return v4l2_ctrl_query_fill(qctrl, | 547 | return v4l2_ctrl_query_fill(qctrl, |
| 459 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | 548 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
| 460 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, | 549 | h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : |
| 461 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | 550 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
| 551 | 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | ||
| 462 | 552 | ||
| 463 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | 553 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
| 464 | return v4l2_ctrl_query_fill(qctrl, | 554 | return v4l2_ctrl_query_fill(qctrl, |
| @@ -466,6 +556,14 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, | |||
| 466 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, | 556 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, |
| 467 | V4L2_MPEG_AUDIO_L2_BITRATE_256K); | 557 | V4L2_MPEG_AUDIO_L2_BITRATE_256K); |
| 468 | 558 | ||
| 559 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
| 560 | if (!h->has_ac3) | ||
| 561 | return -EINVAL; | ||
| 562 | return v4l2_ctrl_query_fill(qctrl, | ||
| 563 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K, | ||
| 564 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1, | ||
| 565 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K); | ||
| 566 | |||
| 469 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | 567 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
| 470 | return v4l2_ctrl_query_fill(qctrl, | 568 | return v4l2_ctrl_query_fill(qctrl, |
| 471 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, | 569 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, |
| @@ -512,44 +610,57 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, | |||
| 512 | return -EINVAL; | 610 | return -EINVAL; |
| 513 | } | 611 | } |
| 514 | 612 | ||
| 515 | static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params, | 613 | static int saa6752hs_qmenu(struct saa6752hs_state *h, |
| 516 | struct v4l2_querymenu *qmenu) | 614 | struct v4l2_querymenu *qmenu) |
| 517 | { | 615 | { |
| 518 | static const char *mpeg_audio_l2_bitrate[] = { | 616 | static const u32 mpeg_audio_encoding[] = { |
| 519 | "", | 617 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
| 520 | "", | 618 | V4L2_CTRL_MENU_IDS_END |
| 521 | "", | 619 | }; |
| 522 | "", | 620 | static const u32 mpeg_audio_ac3_encoding[] = { |
| 523 | "", | 621 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
| 524 | "", | 622 | V4L2_MPEG_AUDIO_ENCODING_AC3, |
| 525 | "", | 623 | V4L2_CTRL_MENU_IDS_END |
| 526 | "", | 624 | }; |
| 527 | "", | 625 | static u32 mpeg_audio_l2_bitrate[] = { |
| 528 | "", | 626 | V4L2_MPEG_AUDIO_L2_BITRATE_256K, |
| 529 | "", | 627 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, |
| 530 | "256 kbps", | 628 | V4L2_CTRL_MENU_IDS_END |
| 531 | "", | 629 | }; |
| 532 | "384 kbps", | 630 | static u32 mpeg_audio_ac3_bitrate[] = { |
| 533 | NULL | 631 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K, |
| 632 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, | ||
| 633 | V4L2_CTRL_MENU_IDS_END | ||
| 534 | }; | 634 | }; |
| 535 | struct v4l2_queryctrl qctrl; | 635 | struct v4l2_queryctrl qctrl; |
| 536 | int err; | 636 | int err; |
| 537 | 637 | ||
| 538 | qctrl.id = qmenu->id; | 638 | qctrl.id = qmenu->id; |
| 539 | err = saa6752hs_qctrl(params, &qctrl); | 639 | err = saa6752hs_qctrl(h, &qctrl); |
| 540 | if (err) | 640 | if (err) |
| 541 | return err; | 641 | return err; |
| 542 | if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE) | 642 | switch (qmenu->id) { |
| 543 | return v4l2_ctrl_query_menu(qmenu, &qctrl, | 643 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
| 644 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
| 544 | mpeg_audio_l2_bitrate); | 645 | mpeg_audio_l2_bitrate); |
| 545 | return v4l2_ctrl_query_menu(qmenu, &qctrl, | 646 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: |
| 546 | v4l2_ctrl_get_menu(qmenu->id)); | 647 | if (!h->has_ac3) |
| 648 | return -EINVAL; | ||
| 649 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
| 650 | mpeg_audio_ac3_bitrate); | ||
| 651 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
| 652 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
| 653 | h->has_ac3 ? mpeg_audio_ac3_encoding : | ||
| 654 | mpeg_audio_encoding); | ||
| 655 | } | ||
| 656 | return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); | ||
| 547 | } | 657 | } |
| 548 | 658 | ||
| 549 | static int saa6752hs_init(struct i2c_client* client) | 659 | static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) |
| 550 | { | 660 | { |
| 551 | unsigned char buf[9], buf2[4]; | 661 | unsigned char buf[9], buf2[4]; |
| 552 | struct saa6752hs_state *h; | 662 | struct saa6752hs_state *h; |
| 663 | unsigned size; | ||
| 553 | u32 crc; | 664 | u32 crc; |
| 554 | unsigned char localPAT[256]; | 665 | unsigned char localPAT[256]; |
| 555 | unsigned char localPMT[256]; | 666 | unsigned char localPMT[256]; |
| @@ -557,45 +668,31 @@ static int saa6752hs_init(struct i2c_client* client) | |||
| 557 | h = i2c_get_clientdata(client); | 668 | h = i2c_get_clientdata(client); |
| 558 | 669 | ||
| 559 | /* Set video format - must be done first as it resets other settings */ | 670 | /* Set video format - must be done first as it resets other settings */ |
| 560 | buf[0] = 0x41; | 671 | set_reg8(client, 0x41, h->video_format); |
| 561 | buf[1] = h->video_format; | ||
| 562 | i2c_master_send(client, buf, 2); | ||
| 563 | 672 | ||
| 564 | /* Set number of lines in input signal */ | 673 | /* Set number of lines in input signal */ |
| 565 | buf[0] = 0x40; | 674 | set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0); |
| 566 | buf[1] = 0x00; | ||
| 567 | if (h->standard & V4L2_STD_525_60) | ||
| 568 | buf[1] = 0x01; | ||
| 569 | i2c_master_send(client, buf, 2); | ||
| 570 | 675 | ||
| 571 | /* set bitrate */ | 676 | /* set bitrate */ |
| 572 | saa6752hs_set_bitrate(client, &h->params); | 677 | saa6752hs_set_bitrate(client, h); |
| 573 | 678 | ||
| 574 | /* Set GOP structure {3, 13} */ | 679 | /* Set GOP structure {3, 13} */ |
| 575 | buf[0] = 0x72; | 680 | set_reg16(client, 0x72, 0x030d); |
| 576 | buf[1] = 0x03; | ||
| 577 | buf[2] = 0x0D; | ||
| 578 | i2c_master_send(client,buf,3); | ||
| 579 | 681 | ||
| 580 | /* Set minimum Q-scale {4} */ | 682 | /* Set minimum Q-scale {4} */ |
| 581 | buf[0] = 0x82; | 683 | set_reg8(client, 0x82, 0x04); |
| 582 | buf[1] = 0x04; | ||
| 583 | i2c_master_send(client,buf,2); | ||
| 584 | 684 | ||
| 585 | /* Set maximum Q-scale {12} */ | 685 | /* Set maximum Q-scale {12} */ |
| 586 | buf[0] = 0x83; | 686 | set_reg8(client, 0x83, 0x0c); |
| 587 | buf[1] = 0x0C; | ||
| 588 | i2c_master_send(client,buf,2); | ||
| 589 | 687 | ||
| 590 | /* Set Output Protocol */ | 688 | /* Set Output Protocol */ |
| 591 | buf[0] = 0xD0; | 689 | set_reg8(client, 0xd0, 0x81); |
| 592 | buf[1] = 0x81; | ||
| 593 | i2c_master_send(client,buf,2); | ||
| 594 | 690 | ||
| 595 | /* Set video output stream format {TS} */ | 691 | /* Set video output stream format {TS} */ |
| 596 | buf[0] = 0xB0; | 692 | set_reg8(client, 0xb0, 0x05); |
| 597 | buf[1] = 0x05; | 693 | |
| 598 | i2c_master_send(client,buf,2); | 694 | /* Set leading null byte for TS */ |
| 695 | set_reg16(client, 0xf6, leading_null_bytes); | ||
| 599 | 696 | ||
| 600 | /* compute PAT */ | 697 | /* compute PAT */ |
| 601 | memcpy(localPAT, PAT, sizeof(PAT)); | 698 | memcpy(localPAT, PAT, sizeof(PAT)); |
| @@ -608,7 +705,13 @@ static int saa6752hs_init(struct i2c_client* client) | |||
| 608 | localPAT[sizeof(PAT) - 1] = crc & 0xFF; | 705 | localPAT[sizeof(PAT) - 1] = crc & 0xFF; |
| 609 | 706 | ||
| 610 | /* compute PMT */ | 707 | /* compute PMT */ |
| 611 | memcpy(localPMT, PMT, sizeof(PMT)); | 708 | if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) { |
| 709 | size = sizeof(PMT_AC3); | ||
| 710 | memcpy(localPMT, PMT_AC3, size); | ||
| 711 | } else { | ||
| 712 | size = sizeof(PMT); | ||
| 713 | memcpy(localPMT, PMT, size); | ||
| 714 | } | ||
| 612 | localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); | 715 | localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); |
| 613 | localPMT[4] = h->params.ts_pid_pmt & 0xff; | 716 | localPMT[4] = h->params.ts_pid_pmt & 0xff; |
| 614 | localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F); | 717 | localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F); |
| @@ -617,40 +720,28 @@ static int saa6752hs_init(struct i2c_client* client) | |||
| 617 | localPMT[21] = h->params.ts_pid_video & 0xFF; | 720 | localPMT[21] = h->params.ts_pid_video & 0xFF; |
| 618 | localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F); | 721 | localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F); |
| 619 | localPMT[26] = h->params.ts_pid_audio & 0xFF; | 722 | localPMT[26] = h->params.ts_pid_audio & 0xFF; |
| 620 | crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4); | 723 | crc = crc32_be(~0, &localPMT[7], size - 7 - 4); |
| 621 | localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF; | 724 | localPMT[size - 4] = (crc >> 24) & 0xFF; |
| 622 | localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF; | 725 | localPMT[size - 3] = (crc >> 16) & 0xFF; |
| 623 | localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF; | 726 | localPMT[size - 2] = (crc >> 8) & 0xFF; |
| 624 | localPMT[sizeof(PMT) - 1] = crc & 0xFF; | 727 | localPMT[size - 1] = crc & 0xFF; |
| 625 | 728 | ||
| 626 | /* Set Audio PID */ | 729 | /* Set Audio PID */ |
| 627 | buf[0] = 0xC1; | 730 | set_reg16(client, 0xc1, h->params.ts_pid_audio); |
| 628 | buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF; | ||
| 629 | buf[2] = h->params.ts_pid_audio & 0xFF; | ||
| 630 | i2c_master_send(client,buf,3); | ||
| 631 | 731 | ||
| 632 | /* Set Video PID */ | 732 | /* Set Video PID */ |
| 633 | buf[0] = 0xC0; | 733 | set_reg16(client, 0xc0, h->params.ts_pid_video); |
| 634 | buf[1] = (h->params.ts_pid_video >> 8) & 0xFF; | ||
| 635 | buf[2] = h->params.ts_pid_video & 0xFF; | ||
| 636 | i2c_master_send(client,buf,3); | ||
| 637 | 734 | ||
| 638 | /* Set PCR PID */ | 735 | /* Set PCR PID */ |
| 639 | buf[0] = 0xC4; | 736 | set_reg16(client, 0xc4, h->params.ts_pid_pcr); |
| 640 | buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF; | ||
| 641 | buf[2] = h->params.ts_pid_pcr & 0xFF; | ||
| 642 | i2c_master_send(client,buf,3); | ||
| 643 | 737 | ||
| 644 | /* Send SI tables */ | 738 | /* Send SI tables */ |
| 645 | i2c_master_send(client,localPAT,sizeof(PAT)); | 739 | i2c_master_send(client, localPAT, sizeof(PAT)); |
| 646 | i2c_master_send(client,localPMT,sizeof(PMT)); | 740 | i2c_master_send(client, localPMT, size); |
| 647 | 741 | ||
| 648 | /* mute then unmute audio. This removes buzzing artefacts */ | 742 | /* mute then unmute audio. This removes buzzing artefacts */ |
| 649 | buf[0] = 0xa4; | 743 | set_reg8(client, 0xa4, 1); |
| 650 | buf[1] = 1; | 744 | set_reg8(client, 0xa4, 0); |
| 651 | i2c_master_send(client, buf, 2); | ||
| 652 | buf[1] = 0; | ||
| 653 | i2c_master_send(client, buf, 2); | ||
| 654 | 745 | ||
| 655 | /* start it going */ | 746 | /* start it going */ |
| 656 | saa6752hs_chip_command(client, SAA6752HS_COMMAND_START); | 747 | saa6752hs_chip_command(client, SAA6752HS_COMMAND_START); |
| @@ -688,45 +779,6 @@ static int saa6752hs_init(struct i2c_client* client) | |||
| 688 | return 0; | 779 | return 0; |
| 689 | } | 780 | } |
| 690 | 781 | ||
| 691 | static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) | ||
| 692 | { | ||
| 693 | struct saa6752hs_state *h; | ||
| 694 | |||
| 695 | |||
| 696 | if (NULL == (h = kzalloc(sizeof(*h), GFP_KERNEL))) | ||
| 697 | return -ENOMEM; | ||
| 698 | h->client = client_template; | ||
| 699 | h->params = param_defaults; | ||
| 700 | h->client.adapter = adap; | ||
| 701 | h->client.addr = addr; | ||
| 702 | |||
| 703 | /* Assume 625 input lines */ | ||
| 704 | h->standard = 0; | ||
| 705 | |||
| 706 | i2c_set_clientdata(&h->client, h); | ||
| 707 | i2c_attach_client(&h->client); | ||
| 708 | |||
| 709 | v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1); | ||
| 710 | return 0; | ||
| 711 | } | ||
| 712 | |||
| 713 | static int saa6752hs_probe(struct i2c_adapter *adap) | ||
| 714 | { | ||
| 715 | if (adap->class & I2C_CLASS_TV_ANALOG) | ||
| 716 | return i2c_probe(adap, &addr_data, saa6752hs_attach); | ||
| 717 | return 0; | ||
| 718 | } | ||
| 719 | |||
| 720 | static int saa6752hs_detach(struct i2c_client *client) | ||
| 721 | { | ||
| 722 | struct saa6752hs_state *h; | ||
| 723 | |||
| 724 | h = i2c_get_clientdata(client); | ||
| 725 | i2c_detach_client(client); | ||
| 726 | kfree(h); | ||
| 727 | return 0; | ||
| 728 | } | ||
| 729 | |||
| 730 | static int | 782 | static int |
| 731 | saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | 783 | saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) |
| 732 | { | 784 | { |
| @@ -737,14 +789,13 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
| 737 | int i; | 789 | int i; |
| 738 | 790 | ||
| 739 | switch (cmd) { | 791 | switch (cmd) { |
| 792 | case VIDIOC_INT_INIT: | ||
| 793 | /* apply settings and start encoder */ | ||
| 794 | saa6752hs_init(client, *(u32 *)arg); | ||
| 795 | break; | ||
| 740 | case VIDIOC_S_EXT_CTRLS: | 796 | case VIDIOC_S_EXT_CTRLS: |
| 741 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 797 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
| 742 | return -EINVAL; | 798 | return -EINVAL; |
| 743 | if (ctrls->count == 0) { | ||
| 744 | /* apply settings and start encoder */ | ||
| 745 | saa6752hs_init(client); | ||
| 746 | break; | ||
| 747 | } | ||
| 748 | /* fall through */ | 799 | /* fall through */ |
| 749 | case VIDIOC_TRY_EXT_CTRLS: | 800 | case VIDIOC_TRY_EXT_CTRLS: |
| 750 | case VIDIOC_G_EXT_CTRLS: | 801 | case VIDIOC_G_EXT_CTRLS: |
| @@ -752,7 +803,8 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
| 752 | return -EINVAL; | 803 | return -EINVAL; |
| 753 | params = h->params; | 804 | params = h->params; |
| 754 | for (i = 0; i < ctrls->count; i++) { | 805 | for (i = 0; i < ctrls->count; i++) { |
| 755 | if ((err = handle_ctrl(¶ms, ctrls->controls + i, cmd))) { | 806 | err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, cmd); |
| 807 | if (err) { | ||
| 756 | ctrls->error_idx = i; | 808 | ctrls->error_idx = i; |
| 757 | return err; | 809 | return err; |
| 758 | } | 810 | } |
| @@ -760,9 +812,9 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
| 760 | h->params = params; | 812 | h->params = params; |
| 761 | break; | 813 | break; |
| 762 | case VIDIOC_QUERYCTRL: | 814 | case VIDIOC_QUERYCTRL: |
| 763 | return saa6752hs_qctrl(&h->params, arg); | 815 | return saa6752hs_qctrl(h, arg); |
| 764 | case VIDIOC_QUERYMENU: | 816 | case VIDIOC_QUERYMENU: |
| 765 | return saa6752hs_qmenu(&h->params, arg); | 817 | return saa6752hs_qmenu(h, arg); |
| 766 | case VIDIOC_G_FMT: | 818 | case VIDIOC_G_FMT: |
| 767 | { | 819 | { |
| 768 | struct v4l2_format *f = arg; | 820 | struct v4l2_format *f = arg; |
| @@ -785,6 +837,11 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
| 785 | case VIDIOC_S_STD: | 837 | case VIDIOC_S_STD: |
| 786 | h->standard = *((v4l2_std_id *) arg); | 838 | h->standard = *((v4l2_std_id *) arg); |
| 787 | break; | 839 | break; |
| 840 | |||
| 841 | case VIDIOC_G_CHIP_IDENT: | ||
| 842 | return v4l2_chip_ident_i2c_client(client, | ||
| 843 | arg, h->chip, h->revision); | ||
| 844 | |||
| 788 | default: | 845 | default: |
| 789 | /* nothing */ | 846 | /* nothing */ |
| 790 | break; | 847 | break; |
| @@ -793,36 +850,55 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
| 793 | return err; | 850 | return err; |
| 794 | } | 851 | } |
| 795 | 852 | ||
| 796 | /* ----------------------------------------------------------------------- */ | 853 | static int saa6752hs_probe(struct i2c_client *client, |
| 854 | const struct i2c_device_id *id) | ||
| 855 | { | ||
| 856 | struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); | ||
| 857 | u8 addr = 0x13; | ||
| 858 | u8 data[12]; | ||
| 797 | 859 | ||
| 798 | static struct i2c_driver driver = { | 860 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
| 799 | .driver = { | 861 | client->addr << 1, client->adapter->name); |
| 800 | .name = "saa6752hs", | 862 | if (h == NULL) |
| 801 | }, | 863 | return -ENOMEM; |
| 802 | .id = I2C_DRIVERID_SAA6752HS, | ||
| 803 | .attach_adapter = saa6752hs_probe, | ||
| 804 | .detach_client = saa6752hs_detach, | ||
| 805 | .command = saa6752hs_command, | ||
| 806 | }; | ||
| 807 | 864 | ||
| 808 | static struct i2c_client client_template = | 865 | i2c_master_send(client, &addr, 1); |
| 809 | { | 866 | i2c_master_recv(client, data, sizeof(data)); |
| 810 | .name = "saa6752hs", | 867 | h->chip = V4L2_IDENT_SAA6752HS; |
| 811 | .driver = &driver, | 868 | h->revision = (data[8] << 8) | data[9]; |
| 812 | }; | 869 | h->has_ac3 = 0; |
| 870 | if (h->revision == 0x0206) { | ||
| 871 | h->chip = V4L2_IDENT_SAA6752HS_AC3; | ||
| 872 | h->has_ac3 = 1; | ||
| 873 | v4l_info(client, "support AC-3\n"); | ||
| 874 | } | ||
| 875 | h->params = param_defaults; | ||
| 876 | h->standard = 0; /* Assume 625 input lines */ | ||
| 813 | 877 | ||
| 814 | static int __init saa6752hs_init_module(void) | 878 | i2c_set_clientdata(client, h); |
| 815 | { | 879 | return 0; |
| 816 | return i2c_add_driver(&driver); | ||
| 817 | } | 880 | } |
| 818 | 881 | ||
| 819 | static void __exit saa6752hs_cleanup_module(void) | 882 | static int saa6752hs_remove(struct i2c_client *client) |
| 820 | { | 883 | { |
| 821 | i2c_del_driver(&driver); | 884 | kfree(i2c_get_clientdata(client)); |
| 885 | return 0; | ||
| 822 | } | 886 | } |
| 823 | 887 | ||
| 824 | module_init(saa6752hs_init_module); | 888 | static const struct i2c_device_id saa6752hs_id[] = { |
| 825 | module_exit(saa6752hs_cleanup_module); | 889 | { "saa6752hs", 0 }, |
| 890 | { } | ||
| 891 | }; | ||
| 892 | MODULE_DEVICE_TABLE(i2c, saa6752hs_id); | ||
| 893 | |||
| 894 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
| 895 | .name = "saa6752hs", | ||
| 896 | .driverid = I2C_DRIVERID_SAA6752HS, | ||
| 897 | .command = saa6752hs_command, | ||
| 898 | .probe = saa6752hs_probe, | ||
| 899 | .remove = saa6752hs_remove, | ||
| 900 | .id_table = saa6752hs_id, | ||
| 901 | }; | ||
| 826 | 902 | ||
| 827 | /* | 903 | /* |
| 828 | * Overrides for Emacs so that we follow Linus's tabbing style. | 904 | * Overrides for Emacs so that we follow Linus's tabbing style. |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 98364d171def..ddc5402c5fb0 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
| @@ -3260,6 +3260,7 @@ struct saa7134_board saa7134_boards[] = { | |||
| 3260 | }, | 3260 | }, |
| 3261 | [SAA7134_BOARD_HAUPPAUGE_HVR1110] = { | 3261 | [SAA7134_BOARD_HAUPPAUGE_HVR1110] = { |
| 3262 | /* Thomas Genty <tomlohave@gmail.com> */ | 3262 | /* Thomas Genty <tomlohave@gmail.com> */ |
| 3263 | /* David Bentham <db260179@hotmail.com> */ | ||
| 3263 | .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid", | 3264 | .name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid", |
| 3264 | .audio_clock = 0x00187de7, | 3265 | .audio_clock = 0x00187de7, |
| 3265 | .tuner_type = TUNER_PHILIPS_TDA8290, | 3266 | .tuner_type = TUNER_PHILIPS_TDA8290, |
| @@ -3268,23 +3269,26 @@ struct saa7134_board saa7134_boards[] = { | |||
| 3268 | .radio_addr = ADDR_UNSET, | 3269 | .radio_addr = ADDR_UNSET, |
| 3269 | .tuner_config = 1, | 3270 | .tuner_config = 1, |
| 3270 | .mpeg = SAA7134_MPEG_DVB, | 3271 | .mpeg = SAA7134_MPEG_DVB, |
| 3272 | .gpiomask = 0x0200100, | ||
| 3271 | .inputs = {{ | 3273 | .inputs = {{ |
| 3272 | .name = name_tv, | 3274 | .name = name_tv, |
| 3273 | .vmux = 1, | 3275 | .vmux = 1, |
| 3274 | .amux = TV, | 3276 | .amux = TV, |
| 3275 | .tv = 1, | 3277 | .tv = 1, |
| 3276 | },{ | 3278 | .gpio = 0x0000100, |
| 3277 | .name = name_comp1, | 3279 | }, { |
| 3278 | .vmux = 3, | 3280 | .name = name_comp1, |
| 3279 | .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ | 3281 | .vmux = 3, |
| 3280 | },{ | 3282 | .amux = LINE1, |
| 3281 | .name = name_svideo, | 3283 | }, { |
| 3282 | .vmux = 8, | 3284 | .name = name_svideo, |
| 3283 | .amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */ | 3285 | .vmux = 8, |
| 3284 | }}, | 3286 | .amux = LINE1, |
| 3287 | } }, | ||
| 3285 | .radio = { | 3288 | .radio = { |
| 3286 | .name = name_radio, | 3289 | .name = name_radio, |
| 3287 | .amux = TV, | 3290 | .amux = TV, |
| 3291 | .gpio = 0x0200100, | ||
| 3288 | }, | 3292 | }, |
| 3289 | }, | 3293 | }, |
| 3290 | [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { | 3294 | [SAA7134_BOARD_CINERGY_HT_PCMCIA] = { |
| @@ -3388,6 +3392,42 @@ struct saa7134_board saa7134_boards[] = { | |||
| 3388 | .amux = 0, | 3392 | .amux = 0, |
| 3389 | }, | 3393 | }, |
| 3390 | }, | 3394 | }, |
| 3395 | [SAA7134_BOARD_ENCORE_ENLTV_FM53] = { | ||
| 3396 | .name = "Encore ENLTV-FM v5.3", | ||
| 3397 | .audio_clock = 0x00200000, | ||
| 3398 | .tuner_type = TUNER_TNF_5335MF, | ||
| 3399 | .radio_type = UNSET, | ||
| 3400 | .tuner_addr = ADDR_UNSET, | ||
| 3401 | .radio_addr = ADDR_UNSET, | ||
| 3402 | .gpiomask = 0x7000, | ||
| 3403 | .inputs = { { | ||
| 3404 | .name = name_tv, | ||
| 3405 | .vmux = 1, | ||
| 3406 | .amux = 1, | ||
| 3407 | .tv = 1, | ||
| 3408 | .gpio = 0x50000, | ||
| 3409 | }, { | ||
| 3410 | .name = name_comp1, | ||
| 3411 | .vmux = 3, | ||
| 3412 | .amux = 2, | ||
| 3413 | .gpio = 0x2000, | ||
| 3414 | }, { | ||
| 3415 | .name = name_svideo, | ||
| 3416 | .vmux = 8, | ||
| 3417 | .amux = 2, | ||
| 3418 | .gpio = 0x2000, | ||
| 3419 | } }, | ||
| 3420 | .radio = { | ||
| 3421 | .name = name_radio, | ||
| 3422 | .vmux = 1, | ||
| 3423 | .amux = 1, | ||
| 3424 | }, | ||
| 3425 | .mute = { | ||
| 3426 | .name = name_mute, | ||
| 3427 | .gpio = 0xf000, | ||
| 3428 | .amux = 0, | ||
| 3429 | }, | ||
| 3430 | }, | ||
| 3391 | [SAA7134_BOARD_CINERGY_HT_PCI] = { | 3431 | [SAA7134_BOARD_CINERGY_HT_PCI] = { |
| 3392 | .name = "Terratec Cinergy HT PCI", | 3432 | .name = "Terratec Cinergy HT PCI", |
| 3393 | .audio_clock = 0x00187de7, | 3433 | .audio_clock = 0x00187de7, |
| @@ -3631,6 +3671,40 @@ struct saa7134_board saa7134_boards[] = { | |||
| 3631 | .tv = 1, | 3671 | .tv = 1, |
| 3632 | }}, | 3672 | }}, |
| 3633 | }, | 3673 | }, |
| 3674 | [SAA7134_BOARD_AVERMEDIA_M135A] = { | ||
| 3675 | .name = "Avermedia PCI pure analog (M135A)", | ||
| 3676 | .audio_clock = 0x00187de7, | ||
| 3677 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
| 3678 | .radio_type = UNSET, | ||
| 3679 | .tuner_addr = ADDR_UNSET, | ||
| 3680 | .radio_addr = ADDR_UNSET, | ||
| 3681 | .tuner_config = 2, | ||
| 3682 | .gpiomask = 0x020200000, | ||
| 3683 | .inputs = {{ | ||
| 3684 | .name = name_tv, | ||
| 3685 | .vmux = 1, | ||
| 3686 | .amux = TV, | ||
| 3687 | .tv = 1, | ||
| 3688 | }, { | ||
| 3689 | .name = name_comp1, | ||
| 3690 | .vmux = 3, | ||
| 3691 | .amux = LINE1, | ||
| 3692 | }, { | ||
| 3693 | .name = name_svideo, | ||
| 3694 | .vmux = 8, | ||
| 3695 | .amux = LINE1, | ||
| 3696 | } }, | ||
| 3697 | .radio = { | ||
| 3698 | .name = name_radio, | ||
| 3699 | .amux = TV, | ||
| 3700 | .gpio = 0x00200000, | ||
| 3701 | }, | ||
| 3702 | .mute = { | ||
| 3703 | .name = name_mute, | ||
| 3704 | .amux = TV, | ||
| 3705 | .gpio = 0x01, | ||
| 3706 | }, | ||
| 3707 | }, | ||
| 3634 | [SAA7134_BOARD_BEHOLD_401] = { | 3708 | [SAA7134_BOARD_BEHOLD_401] = { |
| 3635 | /* Beholder Intl. Ltd. 2008 */ | 3709 | /* Beholder Intl. Ltd. 2008 */ |
| 3636 | /*Dmitry Belimov <d.belimov@gmail.com> */ | 3710 | /*Dmitry Belimov <d.belimov@gmail.com> */ |
| @@ -4409,6 +4483,129 @@ struct saa7134_board saa7134_boards[] = { | |||
| 4409 | /* no DVB support for now */ | 4483 | /* no DVB support for now */ |
| 4410 | /* .mpeg = SAA7134_MPEG_DVB, */ | 4484 | /* .mpeg = SAA7134_MPEG_DVB, */ |
| 4411 | }, | 4485 | }, |
| 4486 | [SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = { | ||
| 4487 | .name = "Asus Tiger 3in1", | ||
| 4488 | .audio_clock = 0x00187de7, | ||
| 4489 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
| 4490 | .radio_type = UNSET, | ||
| 4491 | .tuner_addr = ADDR_UNSET, | ||
| 4492 | .radio_addr = ADDR_UNSET, | ||
| 4493 | .tuner_config = 2, | ||
| 4494 | .gpiomask = 1 << 21, | ||
| 4495 | .mpeg = SAA7134_MPEG_DVB, | ||
| 4496 | .inputs = {{ | ||
| 4497 | .name = name_tv, | ||
| 4498 | .vmux = 1, | ||
| 4499 | .amux = TV, | ||
| 4500 | .tv = 1, | ||
| 4501 | }, { | ||
| 4502 | .name = name_comp, | ||
| 4503 | .vmux = 0, | ||
| 4504 | .amux = LINE2, | ||
| 4505 | }, { | ||
| 4506 | .name = name_svideo, | ||
| 4507 | .vmux = 8, | ||
| 4508 | .amux = LINE2, | ||
| 4509 | } }, | ||
| 4510 | .radio = { | ||
| 4511 | .name = name_radio, | ||
| 4512 | .amux = TV, | ||
| 4513 | .gpio = 0x0200000, | ||
| 4514 | }, | ||
| 4515 | }, | ||
| 4516 | [SAA7134_BOARD_REAL_ANGEL_220] = { | ||
| 4517 | .name = "Zogis Real Angel 220", | ||
| 4518 | .audio_clock = 0x00187de7, | ||
| 4519 | .tuner_type = TUNER_TNF_5335MF, | ||
| 4520 | .radio_type = UNSET, | ||
| 4521 | .tuner_addr = ADDR_UNSET, | ||
| 4522 | .radio_addr = ADDR_UNSET, | ||
| 4523 | .gpiomask = 0x801a8087, | ||
| 4524 | .inputs = { { | ||
| 4525 | .name = name_tv, | ||
| 4526 | .vmux = 3, | ||
| 4527 | .amux = LINE2, | ||
| 4528 | .tv = 1, | ||
| 4529 | .gpio = 0x624000, | ||
| 4530 | }, { | ||
| 4531 | .name = name_comp1, | ||
| 4532 | .vmux = 1, | ||
| 4533 | .amux = LINE1, | ||
| 4534 | .gpio = 0x624000, | ||
| 4535 | }, { | ||
| 4536 | .name = name_svideo, | ||
| 4537 | .vmux = 1, | ||
| 4538 | .amux = LINE1, | ||
| 4539 | .gpio = 0x624000, | ||
| 4540 | } }, | ||
| 4541 | .radio = { | ||
| 4542 | .name = name_radio, | ||
| 4543 | .amux = LINE2, | ||
| 4544 | .gpio = 0x624001, | ||
| 4545 | }, | ||
| 4546 | .mute = { | ||
| 4547 | .name = name_mute, | ||
| 4548 | .amux = TV, | ||
| 4549 | }, | ||
| 4550 | }, | ||
| 4551 | [SAA7134_BOARD_ADS_INSTANT_HDTV_PCI] = { | ||
| 4552 | .name = "ADS Tech Instant HDTV", | ||
| 4553 | .audio_clock = 0x00187de7, | ||
| 4554 | .tuner_type = TUNER_PHILIPS_TUV1236D, | ||
| 4555 | .radio_type = UNSET, | ||
| 4556 | .tuner_addr = ADDR_UNSET, | ||
| 4557 | .radio_addr = ADDR_UNSET, | ||
| 4558 | .tda9887_conf = TDA9887_PRESENT, | ||
| 4559 | .mpeg = SAA7134_MPEG_DVB, | ||
| 4560 | .inputs = { { | ||
| 4561 | .name = name_tv, | ||
| 4562 | .vmux = 1, | ||
| 4563 | .amux = TV, | ||
| 4564 | .tv = 1, | ||
| 4565 | }, { | ||
| 4566 | .name = name_comp, | ||
| 4567 | .vmux = 4, | ||
| 4568 | .amux = LINE1, | ||
| 4569 | }, { | ||
| 4570 | .name = name_svideo, | ||
| 4571 | .vmux = 8, | ||
| 4572 | .amux = LINE1, | ||
| 4573 | } }, | ||
| 4574 | }, | ||
| 4575 | [SAA7134_BOARD_ASUSTeK_TIGER] = { | ||
| 4576 | .name = "Asus Tiger Rev:1.00", | ||
| 4577 | .audio_clock = 0x00187de7, | ||
| 4578 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
| 4579 | .radio_type = UNSET, | ||
| 4580 | .tuner_addr = ADDR_UNSET, | ||
| 4581 | .radio_addr = ADDR_UNSET, | ||
| 4582 | .tuner_config = 0, | ||
| 4583 | .mpeg = SAA7134_MPEG_DVB, | ||
| 4584 | .gpiomask = 0x0200000, | ||
| 4585 | .inputs = { { | ||
| 4586 | .name = name_tv, | ||
| 4587 | .vmux = 1, | ||
| 4588 | .amux = TV, | ||
| 4589 | .tv = 1, | ||
| 4590 | }, { | ||
| 4591 | .name = name_comp1, | ||
| 4592 | .vmux = 3, | ||
| 4593 | .amux = LINE2, | ||
| 4594 | }, { | ||
| 4595 | .name = name_comp2, | ||
| 4596 | .vmux = 0, | ||
| 4597 | .amux = LINE2, | ||
| 4598 | }, { | ||
| 4599 | .name = name_svideo, | ||
| 4600 | .vmux = 8, | ||
| 4601 | .amux = LINE2, | ||
| 4602 | } }, | ||
| 4603 | .radio = { | ||
| 4604 | .name = name_radio, | ||
| 4605 | .amux = TV, | ||
| 4606 | .gpio = 0x0200000, | ||
| 4607 | }, | ||
| 4608 | }, | ||
| 4412 | }; | 4609 | }; |
| 4413 | 4610 | ||
| 4414 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 4611 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
| @@ -4777,6 +4974,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
| 4777 | 4974 | ||
| 4778 | },{ | 4975 | },{ |
| 4779 | .vendor = PCI_VENDOR_ID_PHILIPS, | 4976 | .vendor = PCI_VENDOR_ID_PHILIPS, |
| 4977 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
| 4978 | .subvendor = 0x1461, /* Avermedia Technologies Inc */ | ||
| 4979 | .subdevice = 0xf11d, | ||
| 4980 | .driver_data = SAA7134_BOARD_AVERMEDIA_M135A, | ||
| 4981 | }, { | ||
| 4982 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
| 4780 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | 4983 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, |
| 4781 | .subvendor = PCI_VENDOR_ID_PHILIPS, | 4984 | .subvendor = PCI_VENDOR_ID_PHILIPS, |
| 4782 | .subdevice = 0x2004, | 4985 | .subdevice = 0x2004, |
| @@ -5157,6 +5360,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
| 5157 | .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM, | 5360 | .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM, |
| 5158 | },{ | 5361 | },{ |
| 5159 | .vendor = PCI_VENDOR_ID_PHILIPS, | 5362 | .vendor = PCI_VENDOR_ID_PHILIPS, |
| 5363 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
| 5364 | .subvendor = 0x1a7f, | ||
| 5365 | .subdevice = 0x2008, | ||
| 5366 | .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM53, | ||
| 5367 | }, { | ||
| 5368 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
| 5160 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 5369 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
| 5161 | .subvendor = 0x153b, | 5370 | .subvendor = 0x153b, |
| 5162 | .subdevice = 0x1175, | 5371 | .subdevice = 0x1175, |
| @@ -5183,8 +5392,8 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
| 5183 | .vendor = PCI_VENDOR_ID_PHILIPS, | 5392 | .vendor = PCI_VENDOR_ID_PHILIPS, |
| 5184 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 5393 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
| 5185 | .subvendor = 0x1043, | 5394 | .subvendor = 0x1043, |
| 5186 | .subdevice = 0x4857, | 5395 | .subdevice = 0x4857, /* REV:1.00 */ |
| 5187 | .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, | 5396 | .driver_data = SAA7134_BOARD_ASUSTeK_TIGER, |
| 5188 | },{ | 5397 | },{ |
| 5189 | .vendor = PCI_VENDOR_ID_PHILIPS, | 5398 | .vendor = PCI_VENDOR_ID_PHILIPS, |
| 5190 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 5399 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
| @@ -5415,6 +5624,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
| 5415 | .driver_data = SAA7134_BOARD_VIDEOMATE_T750, | 5624 | .driver_data = SAA7134_BOARD_VIDEOMATE_T750, |
| 5416 | }, { | 5625 | }, { |
| 5417 | .vendor = PCI_VENDOR_ID_PHILIPS, | 5626 | .vendor = PCI_VENDOR_ID_PHILIPS, |
| 5627 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ | ||
| 5628 | .subvendor = 0x1421, | ||
| 5629 | .subdevice = 0x0380, | ||
| 5630 | .driver_data = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI, | ||
| 5631 | }, { | ||
| 5632 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
| 5418 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | 5633 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, |
| 5419 | .subvendor = 0x5169, | 5634 | .subvendor = 0x5169, |
| 5420 | .subdevice = 0x1502, | 5635 | .subdevice = 0x1502, |
| @@ -5432,6 +5647,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
| 5432 | .subdevice = 0xf636, | 5647 | .subdevice = 0xf636, |
| 5433 | .driver_data = SAA7134_BOARD_AVERMEDIA_M103, | 5648 | .driver_data = SAA7134_BOARD_AVERMEDIA_M103, |
| 5434 | }, { | 5649 | }, { |
| 5650 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
| 5651 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
| 5652 | .subvendor = 0x1043, | ||
| 5653 | .subdevice = 0x4878, /* REV:1.02G */ | ||
| 5654 | .driver_data = SAA7134_BOARD_ASUSTeK_TIGER_3IN1, | ||
| 5655 | }, { | ||
| 5435 | /* --- boards without eeprom + subsystem ID --- */ | 5656 | /* --- boards without eeprom + subsystem ID --- */ |
| 5436 | .vendor = PCI_VENDOR_ID_PHILIPS, | 5657 | .vendor = PCI_VENDOR_ID_PHILIPS, |
| 5437 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 5658 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
| @@ -5540,7 +5761,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, | |||
| 5540 | return 0; | 5761 | return 0; |
| 5541 | } | 5762 | } |
| 5542 | 5763 | ||
| 5543 | int saa7134_tuner_callback(void *priv, int command, int arg) | 5764 | int saa7134_tuner_callback(void *priv, int component, int command, int arg) |
| 5544 | { | 5765 | { |
| 5545 | struct saa7134_dev *dev = priv; | 5766 | struct saa7134_dev *dev = priv; |
| 5546 | if (dev != NULL) { | 5767 | if (dev != NULL) { |
| @@ -5620,6 +5841,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
| 5620 | case SAA7134_BOARD_AVERMEDIA_STUDIO_507: | 5841 | case SAA7134_BOARD_AVERMEDIA_STUDIO_507: |
| 5621 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: | 5842 | case SAA7134_BOARD_AVERMEDIA_GO_007_FM: |
| 5622 | case SAA7134_BOARD_AVERMEDIA_777: | 5843 | case SAA7134_BOARD_AVERMEDIA_777: |
| 5844 | case SAA7134_BOARD_AVERMEDIA_M135A: | ||
| 5623 | /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ | 5845 | /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ |
| 5624 | case SAA7134_BOARD_VIDEOMATE_TV_PVR: | 5846 | case SAA7134_BOARD_VIDEOMATE_TV_PVR: |
| 5625 | case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: | 5847 | case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: |
| @@ -5644,6 +5866,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
| 5644 | case SAA7134_BOARD_AVERMEDIA_A16AR: | 5866 | case SAA7134_BOARD_AVERMEDIA_A16AR: |
| 5645 | case SAA7134_BOARD_ENCORE_ENLTV: | 5867 | case SAA7134_BOARD_ENCORE_ENLTV: |
| 5646 | case SAA7134_BOARD_ENCORE_ENLTV_FM: | 5868 | case SAA7134_BOARD_ENCORE_ENLTV_FM: |
| 5869 | case SAA7134_BOARD_ENCORE_ENLTV_FM53: | ||
| 5647 | case SAA7134_BOARD_10MOONSTVMASTER3: | 5870 | case SAA7134_BOARD_10MOONSTVMASTER3: |
| 5648 | case SAA7134_BOARD_BEHOLD_401: | 5871 | case SAA7134_BOARD_BEHOLD_401: |
| 5649 | case SAA7134_BOARD_BEHOLD_403: | 5872 | case SAA7134_BOARD_BEHOLD_403: |
| @@ -5656,6 +5879,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
| 5656 | case SAA7134_BOARD_BEHOLD_505FM: | 5879 | case SAA7134_BOARD_BEHOLD_505FM: |
| 5657 | case SAA7134_BOARD_BEHOLD_507_9FM: | 5880 | case SAA7134_BOARD_BEHOLD_507_9FM: |
| 5658 | case SAA7134_BOARD_GENIUS_TVGO_A11MCE: | 5881 | case SAA7134_BOARD_GENIUS_TVGO_A11MCE: |
| 5882 | case SAA7134_BOARD_REAL_ANGEL_220: | ||
| 5659 | dev->has_remote = SAA7134_REMOTE_GPIO; | 5883 | dev->has_remote = SAA7134_REMOTE_GPIO; |
| 5660 | break; | 5884 | break; |
| 5661 | case SAA7134_BOARD_FLYDVBS_LR300: | 5885 | case SAA7134_BOARD_FLYDVBS_LR300: |
| @@ -5745,6 +5969,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
| 5745 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 5969 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
| 5746 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | 5970 | case SAA7134_BOARD_PINNACLE_PCTV_310i: |
| 5747 | case SAA7134_BOARD_UPMOST_PURPLE_TV: | 5971 | case SAA7134_BOARD_UPMOST_PURPLE_TV: |
| 5972 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: | ||
| 5748 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | 5973 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: |
| 5749 | case SAA7134_BOARD_BEHOLD_607_9FM: | 5974 | case SAA7134_BOARD_BEHOLD_607_9FM: |
| 5750 | case SAA7134_BOARD_BEHOLD_M6: | 5975 | case SAA7134_BOARD_BEHOLD_M6: |
| @@ -5987,6 +6212,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
| 5987 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | 6212 | case SAA7134_BOARD_PINNACLE_PCTV_310i: |
| 5988 | case SAA7134_BOARD_KWORLD_DVBT_210: | 6213 | case SAA7134_BOARD_KWORLD_DVBT_210: |
| 5989 | case SAA7134_BOARD_TEVION_DVBT_220RF: | 6214 | case SAA7134_BOARD_TEVION_DVBT_220RF: |
| 6215 | case SAA7134_BOARD_ASUSTeK_TIGER: | ||
| 5990 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 6216 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
| 5991 | case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: | 6217 | case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: |
| 5992 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: | 6218 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: |
| @@ -6002,6 +6228,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
| 6002 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 6228 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
| 6003 | break; | 6229 | break; |
| 6004 | } | 6230 | } |
| 6231 | case SAA7134_BOARD_ASUSTeK_TIGER_3IN1: | ||
| 6232 | { | ||
| 6233 | u8 data[] = { 0x3c, 0x33, 0x60}; | ||
| 6234 | struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data, | ||
| 6235 | .len = sizeof(data)}; | ||
| 6236 | i2c_transfer(&dev->i2c_adap, &msg, 1); | ||
| 6237 | break; | ||
| 6238 | } | ||
| 6005 | case SAA7134_BOARD_FLYDVB_TRIO: | 6239 | case SAA7134_BOARD_FLYDVB_TRIO: |
| 6006 | { | 6240 | { |
| 6007 | u8 data[] = { 0x3c, 0x33, 0x62}; | 6241 | u8 data[] = { 0x3c, 0x33, 0x62}; |
| @@ -6027,6 +6261,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
| 6027 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 6261 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
| 6028 | break; | 6262 | break; |
| 6029 | } | 6263 | } |
| 6264 | case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: | ||
| 6030 | case SAA7134_BOARD_KWORLD_ATSC110: | 6265 | case SAA7134_BOARD_KWORLD_ATSC110: |
| 6031 | { | 6266 | { |
| 6032 | /* enable tuner */ | 6267 | /* enable tuner */ |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 75d618415f4f..b686bfabbde0 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
| @@ -215,7 +215,7 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf) | |||
| 215 | int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) | 215 | int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) |
| 216 | { | 216 | { |
| 217 | __le32 *cpu; | 217 | __le32 *cpu; |
| 218 | dma_addr_t dma_addr; | 218 | dma_addr_t dma_addr = 0; |
| 219 | 219 | ||
| 220 | cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); | 220 | cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); |
| 221 | if (NULL == cpu) | 221 | if (NULL == cpu) |
| @@ -359,32 +359,6 @@ void saa7134_buffer_timeout(unsigned long data) | |||
| 359 | spin_unlock_irqrestore(&dev->slock,flags); | 359 | spin_unlock_irqrestore(&dev->slock,flags); |
| 360 | } | 360 | } |
| 361 | 361 | ||
| 362 | /* resends a current buffer in queue after resume */ | ||
| 363 | |||
| 364 | static int saa7134_buffer_requeue(struct saa7134_dev *dev, | ||
| 365 | struct saa7134_dmaqueue *q) | ||
| 366 | { | ||
| 367 | struct saa7134_buf *buf, *next; | ||
| 368 | |||
| 369 | assert_spin_locked(&dev->slock); | ||
| 370 | |||
| 371 | buf = q->curr; | ||
| 372 | next = buf; | ||
| 373 | dprintk("buffer_requeue\n"); | ||
| 374 | |||
| 375 | if (!buf) | ||
| 376 | return 0; | ||
| 377 | |||
| 378 | dprintk("buffer_requeue : resending active buffers \n"); | ||
| 379 | |||
| 380 | if (!list_empty(&q->queue)) | ||
| 381 | next = list_entry(q->queue.next, struct saa7134_buf, | ||
| 382 | vb.queue); | ||
| 383 | buf->activate(dev, buf, next); | ||
| 384 | |||
| 385 | return 0; | ||
| 386 | } | ||
| 387 | |||
| 388 | /* ------------------------------------------------------------------ */ | 362 | /* ------------------------------------------------------------------ */ |
| 389 | 363 | ||
| 390 | int saa7134_set_dmabits(struct saa7134_dev *dev) | 364 | int saa7134_set_dmabits(struct saa7134_dev *dev) |
| @@ -442,9 +416,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) | |||
| 442 | /* TS capture -- dma 5 */ | 416 | /* TS capture -- dma 5 */ |
| 443 | if (dev->ts_q.curr) { | 417 | if (dev->ts_q.curr) { |
| 444 | ctrl |= SAA7134_MAIN_CTRL_TE5; | 418 | ctrl |= SAA7134_MAIN_CTRL_TE5; |
| 445 | irq |= SAA7134_IRQ1_INTE_RA2_3 | | 419 | irq |= SAA7134_IRQ1_INTE_RA2_1 | |
| 446 | SAA7134_IRQ1_INTE_RA2_2 | | ||
| 447 | SAA7134_IRQ1_INTE_RA2_1 | | ||
| 448 | SAA7134_IRQ1_INTE_RA2_0; | 420 | SAA7134_IRQ1_INTE_RA2_0; |
| 449 | } | 421 | } |
| 450 | 422 | ||
| @@ -727,6 +699,10 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev) | |||
| 727 | irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A; | 699 | irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A; |
| 728 | } | 700 | } |
| 729 | 701 | ||
| 702 | if (dev->has_remote == SAA7134_REMOTE_I2C) { | ||
| 703 | request_module("ir-kbd-i2c"); | ||
| 704 | } | ||
| 705 | |||
| 730 | saa_writel(SAA7134_IRQ1, 0); | 706 | saa_writel(SAA7134_IRQ1, 0); |
| 731 | saa_writel(SAA7134_IRQ2, irq2_mask); | 707 | saa_writel(SAA7134_IRQ2, irq2_mask); |
| 732 | 708 | ||
| @@ -1139,6 +1115,32 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) | |||
| 1139 | } | 1115 | } |
| 1140 | 1116 | ||
| 1141 | #ifdef CONFIG_PM | 1117 | #ifdef CONFIG_PM |
| 1118 | |||
| 1119 | /* resends a current buffer in queue after resume */ | ||
| 1120 | static int saa7134_buffer_requeue(struct saa7134_dev *dev, | ||
| 1121 | struct saa7134_dmaqueue *q) | ||
| 1122 | { | ||
| 1123 | struct saa7134_buf *buf, *next; | ||
| 1124 | |||
| 1125 | assert_spin_locked(&dev->slock); | ||
| 1126 | |||
| 1127 | buf = q->curr; | ||
| 1128 | next = buf; | ||
| 1129 | dprintk("buffer_requeue\n"); | ||
| 1130 | |||
| 1131 | if (!buf) | ||
| 1132 | return 0; | ||
| 1133 | |||
| 1134 | dprintk("buffer_requeue : resending active buffers \n"); | ||
| 1135 | |||
| 1136 | if (!list_empty(&q->queue)) | ||
| 1137 | next = list_entry(q->queue.next, struct saa7134_buf, | ||
| 1138 | vb.queue); | ||
| 1139 | buf->activate(dev, buf, next); | ||
| 1140 | |||
| 1141 | return 0; | ||
| 1142 | } | ||
| 1143 | |||
| 1142 | static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) | 1144 | static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state) |
| 1143 | { | 1145 | { |
| 1144 | 1146 | ||
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index be48b9b66a67..87c10983266f 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
| @@ -553,7 +553,6 @@ static int configure_tda827x_fe(struct saa7134_dev *dev, | |||
| 553 | /* ------------------------------------------------------------------ */ | 553 | /* ------------------------------------------------------------------ */ |
| 554 | 554 | ||
| 555 | static struct tda827x_config tda827x_cfg_0 = { | 555 | static struct tda827x_config tda827x_cfg_0 = { |
| 556 | .tuner_callback = saa7134_tuner_callback, | ||
| 557 | .init = philips_tda827x_tuner_init, | 556 | .init = philips_tda827x_tuner_init, |
| 558 | .sleep = philips_tda827x_tuner_sleep, | 557 | .sleep = philips_tda827x_tuner_sleep, |
| 559 | .config = 0, | 558 | .config = 0, |
| @@ -561,7 +560,6 @@ static struct tda827x_config tda827x_cfg_0 = { | |||
| 561 | }; | 560 | }; |
| 562 | 561 | ||
| 563 | static struct tda827x_config tda827x_cfg_1 = { | 562 | static struct tda827x_config tda827x_cfg_1 = { |
| 564 | .tuner_callback = saa7134_tuner_callback, | ||
| 565 | .init = philips_tda827x_tuner_init, | 563 | .init = philips_tda827x_tuner_init, |
| 566 | .sleep = philips_tda827x_tuner_sleep, | 564 | .sleep = philips_tda827x_tuner_sleep, |
| 567 | .config = 1, | 565 | .config = 1, |
| @@ -569,7 +567,6 @@ static struct tda827x_config tda827x_cfg_1 = { | |||
| 569 | }; | 567 | }; |
| 570 | 568 | ||
| 571 | static struct tda827x_config tda827x_cfg_2 = { | 569 | static struct tda827x_config tda827x_cfg_2 = { |
| 572 | .tuner_callback = saa7134_tuner_callback, | ||
| 573 | .init = philips_tda827x_tuner_init, | 570 | .init = philips_tda827x_tuner_init, |
| 574 | .sleep = philips_tda827x_tuner_sleep, | 571 | .sleep = philips_tda827x_tuner_sleep, |
| 575 | .config = 2, | 572 | .config = 2, |
| @@ -577,7 +574,6 @@ static struct tda827x_config tda827x_cfg_2 = { | |||
| 577 | }; | 574 | }; |
| 578 | 575 | ||
| 579 | static struct tda827x_config tda827x_cfg_2_sw42 = { | 576 | static struct tda827x_config tda827x_cfg_2_sw42 = { |
| 580 | .tuner_callback = saa7134_tuner_callback, | ||
| 581 | .init = philips_tda827x_tuner_init, | 577 | .init = philips_tda827x_tuner_init, |
| 582 | .sleep = philips_tda827x_tuner_sleep, | 578 | .sleep = philips_tda827x_tuner_sleep, |
| 583 | .config = 2, | 579 | .config = 2, |
| @@ -799,6 +795,20 @@ static struct tda1004x_config twinhan_dtv_dvb_3056_config = { | |||
| 799 | .request_firmware = philips_tda1004x_request_firmware | 795 | .request_firmware = philips_tda1004x_request_firmware |
| 800 | }; | 796 | }; |
| 801 | 797 | ||
| 798 | static struct tda1004x_config asus_tiger_3in1_config = { | ||
| 799 | .demod_address = 0x0b, | ||
| 800 | .invert = 1, | ||
| 801 | .invert_oclk = 0, | ||
| 802 | .xtal_freq = TDA10046_XTAL_16M, | ||
| 803 | .agc_config = TDA10046_AGC_TDA827X, | ||
| 804 | .gpio_config = TDA10046_GP11_I, | ||
| 805 | .if_freq = TDA10046_FREQ_045, | ||
| 806 | .i2c_gate = 0x4b, | ||
| 807 | .tuner_address = 0x61, | ||
| 808 | .antenna_switch = 1, | ||
| 809 | .request_firmware = philips_tda1004x_request_firmware | ||
| 810 | }; | ||
| 811 | |||
| 802 | /* ------------------------------------------------------------------ | 812 | /* ------------------------------------------------------------------ |
| 803 | * special case: this card uses saa713x GPIO22 for the mode switch | 813 | * special case: this card uses saa713x GPIO22 for the mode switch |
| 804 | */ | 814 | */ |
| @@ -822,7 +832,6 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe) | |||
| 822 | } | 832 | } |
| 823 | 833 | ||
| 824 | static struct tda827x_config ads_duo_cfg = { | 834 | static struct tda827x_config ads_duo_cfg = { |
| 825 | .tuner_callback = saa7134_tuner_callback, | ||
| 826 | .init = ads_duo_tuner_init, | 835 | .init = ads_duo_tuner_init, |
| 827 | .sleep = ads_duo_tuner_sleep, | 836 | .sleep = ads_duo_tuner_sleep, |
| 828 | .config = 0 | 837 | .config = 0 |
| @@ -1147,6 +1156,7 @@ static int dvb_init(struct saa7134_dev *dev) | |||
| 1147 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 1156 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
| 1148 | NULL, DVB_PLL_TDHU2); | 1157 | NULL, DVB_PLL_TDHU2); |
| 1149 | break; | 1158 | break; |
| 1159 | case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: | ||
| 1150 | case SAA7134_BOARD_KWORLD_ATSC110: | 1160 | case SAA7134_BOARD_KWORLD_ATSC110: |
| 1151 | dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, | 1161 | dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, |
| 1152 | &dev->i2c_adap); | 1162 | &dev->i2c_adap); |
| @@ -1300,6 +1310,36 @@ static int dvb_init(struct saa7134_dev *dev) | |||
| 1300 | &dev->i2c_adap); | 1310 | &dev->i2c_adap); |
| 1301 | attach_xc3028 = 1; | 1311 | attach_xc3028 = 1; |
| 1302 | break; | 1312 | break; |
| 1313 | case SAA7134_BOARD_ASUSTeK_TIGER_3IN1: | ||
| 1314 | if (!use_frontend) { /* terrestrial */ | ||
| 1315 | if (configure_tda827x_fe(dev, &asus_tiger_3in1_config, | ||
| 1316 | &tda827x_cfg_2) < 0) | ||
| 1317 | goto dettach_frontend; | ||
| 1318 | } else { /* satellite */ | ||
| 1319 | dev->dvb.frontend = dvb_attach(tda10086_attach, | ||
| 1320 | &flydvbs, &dev->i2c_adap); | ||
| 1321 | if (dev->dvb.frontend) { | ||
| 1322 | if (dvb_attach(tda826x_attach, | ||
| 1323 | dev->dvb.frontend, 0x60, | ||
| 1324 | &dev->i2c_adap, 0) == NULL) { | ||
| 1325 | wprintk("%s: Asus Tiger 3in1, no " | ||
| 1326 | "tda826x found!\n", __func__); | ||
| 1327 | goto dettach_frontend; | ||
| 1328 | } | ||
| 1329 | if (dvb_attach(lnbp21_attach, dev->dvb.frontend, | ||
| 1330 | &dev->i2c_adap, 0, 0) == NULL) { | ||
| 1331 | wprintk("%s: Asus Tiger 3in1, no lnbp21" | ||
| 1332 | " found!\n", __func__); | ||
| 1333 | goto dettach_frontend; | ||
| 1334 | } | ||
| 1335 | } | ||
| 1336 | } | ||
| 1337 | break; | ||
| 1338 | case SAA7134_BOARD_ASUSTeK_TIGER: | ||
| 1339 | if (configure_tda827x_fe(dev, &philips_tiger_config, | ||
| 1340 | &tda827x_cfg_0) < 0) | ||
| 1341 | goto dettach_frontend; | ||
| 1342 | break; | ||
| 1303 | default: | 1343 | default: |
| 1304 | wprintk("Huh? unknown DVB card?\n"); | 1344 | wprintk("Huh? unknown DVB card?\n"); |
| 1305 | break; | 1345 | break; |
| @@ -1327,6 +1367,8 @@ static int dvb_init(struct saa7134_dev *dev) | |||
| 1327 | printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); | 1367 | printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); |
| 1328 | return -1; | 1368 | return -1; |
| 1329 | } | 1369 | } |
| 1370 | /* define general-purpose callback pointer */ | ||
| 1371 | dev->dvb.frontend->callback = saa7134_tuner_callback; | ||
| 1330 | 1372 | ||
| 1331 | /* register everything else */ | 1373 | /* register everything else */ |
| 1332 | ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, | 1374 | ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index c0c5d7509c25..9a8766a78a0c 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | #include <media/saa6752hs.h> | 30 | #include <media/saa6752hs.h> |
| 31 | #include <media/v4l2-common.h> | 31 | #include <media/v4l2-common.h> |
| 32 | #include <media/v4l2-chip-ident.h> | ||
| 32 | 33 | ||
| 33 | /* ------------------------------------------------------------------ */ | 34 | /* ------------------------------------------------------------------ */ |
| 34 | 35 | ||
| @@ -63,10 +64,19 @@ static void ts_reset_encoder(struct saa7134_dev* dev) | |||
| 63 | 64 | ||
| 64 | static int ts_init_encoder(struct saa7134_dev* dev) | 65 | static int ts_init_encoder(struct saa7134_dev* dev) |
| 65 | { | 66 | { |
| 66 | struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 }; | 67 | u32 leading_null_bytes = 0; |
| 67 | 68 | ||
| 69 | /* If more cards start to need this, then this | ||
| 70 | should probably be added to the card definitions. */ | ||
| 71 | switch (dev->board) { | ||
| 72 | case SAA7134_BOARD_BEHOLD_M6: | ||
| 73 | case SAA7134_BOARD_BEHOLD_M63: | ||
| 74 | case SAA7134_BOARD_BEHOLD_M6_EXTRA: | ||
| 75 | leading_null_bytes = 1; | ||
| 76 | break; | ||
| 77 | } | ||
| 68 | ts_reset_encoder(dev); | 78 | ts_reset_encoder(dev); |
| 69 | saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls); | 79 | saa7134_i2c_call_clients(dev, VIDIOC_INT_INIT, &leading_null_bytes); |
| 70 | dev->empress_started = 1; | 80 | dev->empress_started = 1; |
| 71 | return 0; | 81 | return 0; |
| 72 | } | 82 | } |
| @@ -79,9 +89,11 @@ static int ts_open(struct inode *inode, struct file *file) | |||
| 79 | struct saa7134_dev *dev; | 89 | struct saa7134_dev *dev; |
| 80 | int err; | 90 | int err; |
| 81 | 91 | ||
| 92 | lock_kernel(); | ||
| 82 | list_for_each_entry(dev, &saa7134_devlist, devlist) | 93 | list_for_each_entry(dev, &saa7134_devlist, devlist) |
| 83 | if (dev->empress_dev && dev->empress_dev->minor == minor) | 94 | if (dev->empress_dev && dev->empress_dev->minor == minor) |
| 84 | goto found; | 95 | goto found; |
| 96 | unlock_kernel(); | ||
| 85 | return -ENODEV; | 97 | return -ENODEV; |
| 86 | found: | 98 | found: |
| 87 | 99 | ||
| @@ -103,6 +115,7 @@ static int ts_open(struct inode *inode, struct file *file) | |||
| 103 | done_up: | 115 | done_up: |
| 104 | mutex_unlock(&dev->empress_tsq.vb_lock); | 116 | mutex_unlock(&dev->empress_tsq.vb_lock); |
| 105 | done: | 117 | done: |
| 118 | unlock_kernel(); | ||
| 106 | return err; | 119 | return err; |
| 107 | } | 120 | } |
| 108 | 121 | ||
| @@ -290,15 +303,6 @@ static int empress_streamoff(struct file *file, void *priv, | |||
| 290 | return videobuf_streamoff(&dev->empress_tsq); | 303 | return videobuf_streamoff(&dev->empress_tsq); |
| 291 | } | 304 | } |
| 292 | 305 | ||
| 293 | static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, | ||
| 294 | unsigned int cmd, void *arg) | ||
| 295 | { | ||
| 296 | if (dev->mpeg_i2c_client == NULL) | ||
| 297 | return -EINVAL; | ||
| 298 | return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client, | ||
| 299 | cmd, arg); | ||
| 300 | } | ||
| 301 | |||
| 302 | static int empress_s_ext_ctrls(struct file *file, void *priv, | 306 | static int empress_s_ext_ctrls(struct file *file, void *priv, |
| 303 | struct v4l2_ext_controls *ctrls) | 307 | struct v4l2_ext_controls *ctrls) |
| 304 | { | 308 | { |
| @@ -400,6 +404,39 @@ static int empress_querymenu(struct file *file, void *priv, | |||
| 400 | return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c); | 404 | return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c); |
| 401 | } | 405 | } |
| 402 | 406 | ||
| 407 | static int empress_g_chip_ident(struct file *file, void *fh, | ||
| 408 | struct v4l2_chip_ident *chip) | ||
| 409 | { | ||
| 410 | struct saa7134_dev *dev = file->private_data; | ||
| 411 | |||
| 412 | chip->ident = V4L2_IDENT_NONE; | ||
| 413 | chip->revision = 0; | ||
| 414 | if (dev->mpeg_i2c_client == NULL) | ||
| 415 | return -EINVAL; | ||
| 416 | if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER && | ||
| 417 | chip->match_chip == I2C_DRIVERID_SAA6752HS) | ||
| 418 | return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip); | ||
| 419 | if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR && | ||
| 420 | chip->match_chip == dev->mpeg_i2c_client->addr) | ||
| 421 | return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip); | ||
| 422 | return -EINVAL; | ||
| 423 | } | ||
| 424 | |||
| 425 | static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id) | ||
| 426 | { | ||
| 427 | struct saa7134_dev *dev = file->private_data; | ||
| 428 | |||
| 429 | return saa7134_s_std_internal(dev, NULL, id); | ||
| 430 | } | ||
| 431 | |||
| 432 | static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||
| 433 | { | ||
| 434 | struct saa7134_dev *dev = file->private_data; | ||
| 435 | |||
| 436 | *id = dev->tvnorm->id; | ||
| 437 | return 0; | ||
| 438 | } | ||
| 439 | |||
| 403 | static const struct file_operations ts_fops = | 440 | static const struct file_operations ts_fops = |
| 404 | { | 441 | { |
| 405 | .owner = THIS_MODULE, | 442 | .owner = THIS_MODULE, |
| @@ -428,11 +465,13 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { | |||
| 428 | .vidioc_enum_input = empress_enum_input, | 465 | .vidioc_enum_input = empress_enum_input, |
| 429 | .vidioc_g_input = empress_g_input, | 466 | .vidioc_g_input = empress_g_input, |
| 430 | .vidioc_s_input = empress_s_input, | 467 | .vidioc_s_input = empress_s_input, |
| 431 | |||
| 432 | .vidioc_queryctrl = empress_queryctrl, | 468 | .vidioc_queryctrl = empress_queryctrl, |
| 433 | .vidioc_querymenu = empress_querymenu, | 469 | .vidioc_querymenu = empress_querymenu, |
| 434 | .vidioc_g_ctrl = empress_g_ctrl, | 470 | .vidioc_g_ctrl = empress_g_ctrl, |
| 435 | .vidioc_s_ctrl = empress_s_ctrl, | 471 | .vidioc_s_ctrl = empress_s_ctrl, |
| 472 | .vidioc_g_chip_ident = empress_g_chip_ident, | ||
| 473 | .vidioc_s_std = empress_s_std, | ||
| 474 | .vidioc_g_std = empress_g_std, | ||
| 436 | }; | 475 | }; |
| 437 | 476 | ||
| 438 | /* ----------------------------------------------------------- */ | 477 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 5f713e637683..20c1b33caf7b 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
| @@ -337,6 +337,7 @@ static int attach_inform(struct i2c_client *client) | |||
| 337 | case 0x47: | 337 | case 0x47: |
| 338 | case 0x71: | 338 | case 0x71: |
| 339 | case 0x2d: | 339 | case 0x2d: |
| 340 | case 0x30: | ||
| 340 | { | 341 | { |
| 341 | struct IR_i2c *ir = i2c_get_clientdata(client); | 342 | struct IR_i2c *ir = i2c_get_clientdata(client); |
| 342 | d1printk("%s i2c IR detected (%s).\n", | 343 | d1printk("%s i2c IR detected (%s).\n", |
| @@ -427,6 +428,16 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev, | |||
| 427 | i2c_clients_command(&dev->i2c_adap, cmd, arg); | 428 | i2c_clients_command(&dev->i2c_adap, cmd, arg); |
| 428 | } | 429 | } |
| 429 | 430 | ||
| 431 | int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, | ||
| 432 | unsigned int cmd, void *arg) | ||
| 433 | { | ||
| 434 | if (dev->mpeg_i2c_client == NULL) | ||
| 435 | return -EINVAL; | ||
| 436 | return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client, | ||
| 437 | cmd, arg); | ||
| 438 | } | ||
| 439 | EXPORT_SYMBOL_GPL(saa7134_i2c_call_saa6752); | ||
| 440 | |||
| 430 | int saa7134_i2c_register(struct saa7134_dev *dev) | 441 | int saa7134_i2c_register(struct saa7134_dev *dev) |
| 431 | { | 442 | { |
| 432 | dev->i2c_adap = saa7134_adap_template; | 443 | dev->i2c_adap = saa7134_adap_template; |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ad08d13dffdd..c53fd5f9f6b5 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
| @@ -62,8 +62,11 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of " | |||
| 62 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ | 62 | #define i2cdprintk(fmt, arg...) if (ir_debug) \ |
| 63 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) | 63 | printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg) |
| 64 | 64 | ||
| 65 | /** rc5 functions */ | 65 | /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */ |
| 66 | static int saa7134_rc5_irq(struct saa7134_dev *dev); | 66 | static int saa7134_rc5_irq(struct saa7134_dev *dev); |
| 67 | static int saa7134_nec_irq(struct saa7134_dev *dev); | ||
| 68 | static void nec_task(unsigned long data); | ||
| 69 | static void saa7134_nec_timer(unsigned long data); | ||
| 67 | 70 | ||
| 68 | /* -------------------- GPIO generic keycode builder -------------------- */ | 71 | /* -------------------- GPIO generic keycode builder -------------------- */ |
| 69 | 72 | ||
| @@ -115,6 +118,53 @@ static int build_key(struct saa7134_dev *dev) | |||
| 115 | 118 | ||
| 116 | /* --------------------- Chip specific I2C key builders ----------------- */ | 119 | /* --------------------- Chip specific I2C key builders ----------------- */ |
| 117 | 120 | ||
| 121 | static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, | ||
| 122 | u32 *ir_raw) | ||
| 123 | { | ||
| 124 | unsigned char b; | ||
| 125 | int gpio; | ||
| 126 | |||
| 127 | /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ | ||
| 128 | struct saa7134_dev *dev = ir->c.adapter->algo_data; | ||
| 129 | if (dev == NULL) { | ||
| 130 | dprintk("get_key_msi_tvanywhere_plus: " | ||
| 131 | "gir->c.adapter->algo_data is NULL!\n"); | ||
| 132 | return -EIO; | ||
| 133 | } | ||
| 134 | |||
| 135 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
| 136 | |||
| 137 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
| 138 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
| 139 | |||
| 140 | gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); | ||
| 141 | |||
| 142 | /* GPIO&0x40 is pulsed low when a button is pressed. Don't do | ||
| 143 | I2C receive if gpio&0x40 is not low. */ | ||
| 144 | |||
| 145 | if (gpio & 0x40) | ||
| 146 | return 0; /* No button press */ | ||
| 147 | |||
| 148 | /* GPIO says there is a button press. Get it. */ | ||
| 149 | |||
| 150 | if (1 != i2c_master_recv(&ir->c, &b, 1)) { | ||
| 151 | i2cdprintk("read error\n"); | ||
| 152 | return -EIO; | ||
| 153 | } | ||
| 154 | |||
| 155 | /* No button press */ | ||
| 156 | |||
| 157 | if (b == 0xff) | ||
| 158 | return 0; | ||
| 159 | |||
| 160 | /* Button pressed */ | ||
| 161 | |||
| 162 | dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b); | ||
| 163 | *ir_key = b; | ||
| 164 | *ir_raw = b; | ||
| 165 | return 1; | ||
| 166 | } | ||
| 167 | |||
| 118 | static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | 168 | static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) |
| 119 | { | 169 | { |
| 120 | unsigned char b; | 170 | unsigned char b; |
| @@ -280,7 +330,9 @@ void saa7134_input_irq(struct saa7134_dev *dev) | |||
| 280 | { | 330 | { |
| 281 | struct card_ir *ir = dev->remote; | 331 | struct card_ir *ir = dev->remote; |
| 282 | 332 | ||
| 283 | if (!ir->polling && !ir->rc5_gpio) { | 333 | if (ir->nec_gpio) { |
| 334 | saa7134_nec_irq(dev); | ||
| 335 | } else if (!ir->polling && !ir->rc5_gpio) { | ||
| 284 | build_key(dev); | 336 | build_key(dev); |
| 285 | } else if (ir->rc5_gpio) { | 337 | } else if (ir->rc5_gpio) { |
| 286 | saa7134_rc5_irq(dev); | 338 | saa7134_rc5_irq(dev); |
| @@ -316,6 +368,10 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir) | |||
| 316 | ir->addr = 0x17; | 368 | ir->addr = 0x17; |
| 317 | ir->rc5_key_timeout = ir_rc5_key_timeout; | 369 | ir->rc5_key_timeout = ir_rc5_key_timeout; |
| 318 | ir->rc5_remote_gap = ir_rc5_remote_gap; | 370 | ir->rc5_remote_gap = ir_rc5_remote_gap; |
| 371 | } else if (ir->nec_gpio) { | ||
| 372 | setup_timer(&ir->timer_keyup, saa7134_nec_timer, | ||
| 373 | (unsigned long)dev); | ||
| 374 | tasklet_init(&ir->tlet, nec_task, (unsigned long)dev); | ||
| 319 | } | 375 | } |
| 320 | } | 376 | } |
| 321 | 377 | ||
| @@ -335,6 +391,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
| 335 | u32 mask_keyup = 0; | 391 | u32 mask_keyup = 0; |
| 336 | int polling = 0; | 392 | int polling = 0; |
| 337 | int rc5_gpio = 0; | 393 | int rc5_gpio = 0; |
| 394 | int nec_gpio = 0; | ||
| 338 | int ir_type = IR_TYPE_OTHER; | 395 | int ir_type = IR_TYPE_OTHER; |
| 339 | int err; | 396 | int err; |
| 340 | 397 | ||
| @@ -391,6 +448,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
| 391 | saa_setb(SAA7134_GPIO_GPMODE0, 0x4); | 448 | saa_setb(SAA7134_GPIO_GPMODE0, 0x4); |
| 392 | saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); | 449 | saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); |
| 393 | break; | 450 | break; |
| 451 | case SAA7134_BOARD_AVERMEDIA_M135A: | ||
| 452 | ir_codes = ir_codes_avermedia_m135a; | ||
| 453 | mask_keydown = 0x0040000; | ||
| 454 | mask_keycode = 0x00013f; | ||
| 455 | nec_gpio = 1; | ||
| 456 | break; | ||
| 394 | case SAA7134_BOARD_AVERMEDIA_777: | 457 | case SAA7134_BOARD_AVERMEDIA_777: |
| 395 | case SAA7134_BOARD_AVERMEDIA_A16AR: | 458 | case SAA7134_BOARD_AVERMEDIA_A16AR: |
| 396 | ir_codes = ir_codes_avermedia; | 459 | ir_codes = ir_codes_avermedia; |
| @@ -499,6 +562,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
| 499 | mask_keyup = 0x040000; | 562 | mask_keyup = 0x040000; |
| 500 | polling = 50; // ms | 563 | polling = 50; // ms |
| 501 | break; | 564 | break; |
| 565 | case SAA7134_BOARD_ENCORE_ENLTV_FM53: | ||
| 566 | ir_codes = ir_codes_encore_enltv_fm53; | ||
| 567 | mask_keydown = 0x0040000; | ||
| 568 | mask_keycode = 0x00007f; | ||
| 569 | nec_gpio = 1; | ||
| 570 | break; | ||
| 502 | case SAA7134_BOARD_10MOONSTVMASTER3: | 571 | case SAA7134_BOARD_10MOONSTVMASTER3: |
| 503 | ir_codes = ir_codes_encore_enltv; | 572 | ir_codes = ir_codes_encore_enltv; |
| 504 | mask_keycode = 0x5f80000; | 573 | mask_keycode = 0x5f80000; |
| @@ -511,6 +580,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
| 511 | mask_keydown = 0xf00000; | 580 | mask_keydown = 0xf00000; |
| 512 | polling = 50; /* ms */ | 581 | polling = 50; /* ms */ |
| 513 | break; | 582 | break; |
| 583 | case SAA7134_BOARD_REAL_ANGEL_220: | ||
| 584 | ir_codes = ir_codes_real_audio_220_32_keys; | ||
| 585 | mask_keycode = 0x3f00; | ||
| 586 | mask_keyup = 0x4000; | ||
| 587 | polling = 50; /* ms */ | ||
| 588 | break; | ||
| 514 | } | 589 | } |
| 515 | if (NULL == ir_codes) { | 590 | if (NULL == ir_codes) { |
| 516 | printk("%s: Oops: IR config error [card=%d]\n", | 591 | printk("%s: Oops: IR config error [card=%d]\n", |
| @@ -533,6 +608,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
| 533 | ir->mask_keyup = mask_keyup; | 608 | ir->mask_keyup = mask_keyup; |
| 534 | ir->polling = polling; | 609 | ir->polling = polling; |
| 535 | ir->rc5_gpio = rc5_gpio; | 610 | ir->rc5_gpio = rc5_gpio; |
| 611 | ir->nec_gpio = nec_gpio; | ||
| 536 | 612 | ||
| 537 | /* init input device */ | 613 | /* init input device */ |
| 538 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", | 614 | snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", |
| @@ -612,6 +688,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
| 612 | ir->get_key = get_key_purpletv; | 688 | ir->get_key = get_key_purpletv; |
| 613 | ir->ir_codes = ir_codes_purpletv; | 689 | ir->ir_codes = ir_codes_purpletv; |
| 614 | break; | 690 | break; |
| 691 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: | ||
| 692 | snprintf(ir->c.name, sizeof(ir->c.name), "MSI TV@nywhere Plus"); | ||
| 693 | ir->get_key = get_key_msi_tvanywhere_plus; | ||
| 694 | ir->ir_codes = ir_codes_msi_tvanywhere_plus; | ||
| 695 | break; | ||
| 615 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | 696 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: |
| 616 | snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); | 697 | snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); |
| 617 | ir->get_key = get_key_hvr1110; | 698 | ir->get_key = get_key_hvr1110; |
| @@ -675,8 +756,125 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev) | |||
| 675 | return 1; | 756 | return 1; |
| 676 | } | 757 | } |
| 677 | 758 | ||
| 678 | /* ---------------------------------------------------------------------- | 759 | |
| 679 | * Local variables: | 760 | /* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms |
| 680 | * c-basic-offset: 8 | 761 | The first pulse (start) has 9 + 4.5 ms |
| 681 | * End: | ||
| 682 | */ | 762 | */ |
| 763 | |||
| 764 | static void saa7134_nec_timer(unsigned long data) | ||
| 765 | { | ||
| 766 | struct saa7134_dev *dev = (struct saa7134_dev *) data; | ||
| 767 | struct card_ir *ir = dev->remote; | ||
| 768 | |||
| 769 | dprintk("Cancel key repeat\n"); | ||
| 770 | |||
| 771 | ir_input_nokey(ir->dev, &ir->ir); | ||
| 772 | } | ||
| 773 | |||
| 774 | static void nec_task(unsigned long data) | ||
| 775 | { | ||
| 776 | struct saa7134_dev *dev = (struct saa7134_dev *) data; | ||
| 777 | struct card_ir *ir; | ||
| 778 | struct timeval tv; | ||
| 779 | int count, pulse, oldpulse, gap; | ||
| 780 | u32 ircode = 0, not_code = 0; | ||
| 781 | int ngap = 0; | ||
| 782 | |||
| 783 | if (!data) { | ||
| 784 | printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n"); | ||
| 785 | /* GPIO will be kept disabled */ | ||
| 786 | return; | ||
| 787 | } | ||
| 788 | |||
| 789 | ir = dev->remote; | ||
| 790 | |||
| 791 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
| 792 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
| 793 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
| 794 | |||
| 795 | oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; | ||
| 796 | pulse = oldpulse; | ||
| 797 | |||
| 798 | do_gettimeofday(&tv); | ||
| 799 | ir->base_time = tv; | ||
| 800 | |||
| 801 | /* Decode NEC pulsecode. This code can take up to 76.5 ms to run. | ||
| 802 | Unfortunately, using IRQ to decode pulse didn't work, since it uses | ||
| 803 | a pulse train of 38KHz. This means one pulse on each 52 us | ||
| 804 | */ | ||
| 805 | do { | ||
| 806 | /* Wait until the end of pulse/space or 5 ms */ | ||
| 807 | for (count = 0; count < 500; count++) { | ||
| 808 | udelay(10); | ||
| 809 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
| 810 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
| 811 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
| 812 | pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) | ||
| 813 | & ir->mask_keydown; | ||
| 814 | if (pulse != oldpulse) | ||
| 815 | break; | ||
| 816 | } | ||
| 817 | |||
| 818 | do_gettimeofday(&tv); | ||
| 819 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
| 820 | tv.tv_usec - ir->base_time.tv_usec; | ||
| 821 | |||
| 822 | if (!pulse) { | ||
| 823 | /* Bit 0 has 560 us, while bit 1 has 1120 us. | ||
| 824 | Do something only if bit == 1 | ||
| 825 | */ | ||
| 826 | if (ngap && (gap > 560 + 280)) { | ||
| 827 | unsigned int shift = ngap - 1; | ||
| 828 | |||
| 829 | /* Address first, then command */ | ||
| 830 | if (shift < 8) { | ||
| 831 | shift += 8; | ||
| 832 | ircode |= 1 << shift; | ||
| 833 | } else if (shift < 16) { | ||
| 834 | not_code |= 1 << shift; | ||
| 835 | } else if (shift < 24) { | ||
| 836 | shift -= 16; | ||
| 837 | ircode |= 1 << shift; | ||
| 838 | } else { | ||
| 839 | shift -= 24; | ||
| 840 | not_code |= 1 << shift; | ||
| 841 | } | ||
| 842 | } | ||
| 843 | ngap++; | ||
| 844 | } | ||
| 845 | |||
| 846 | |||
| 847 | ir->base_time = tv; | ||
| 848 | |||
| 849 | /* TIMEOUT - Long pulse */ | ||
| 850 | if (gap >= 5000) | ||
| 851 | break; | ||
| 852 | oldpulse = pulse; | ||
| 853 | } while (ngap < 32); | ||
| 854 | |||
| 855 | if (ngap == 32) { | ||
| 856 | /* FIXME: should check if not_code == ~ircode */ | ||
| 857 | ir->code = ir_extract_bits(ircode, ir->mask_keycode); | ||
| 858 | |||
| 859 | dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n", | ||
| 860 | ir->code, ircode, not_code); | ||
| 861 | |||
| 862 | ir_input_keydown(ir->dev, &ir->ir, ir->code, ir->code); | ||
| 863 | } else | ||
| 864 | dprintk("Repeat last key\n"); | ||
| 865 | |||
| 866 | /* Keep repeating the last key */ | ||
| 867 | mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150)); | ||
| 868 | |||
| 869 | saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | ||
| 870 | } | ||
| 871 | |||
| 872 | static int saa7134_nec_irq(struct saa7134_dev *dev) | ||
| 873 | { | ||
| 874 | struct card_ir *ir = dev->remote; | ||
| 875 | |||
| 876 | saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18); | ||
| 877 | tasklet_schedule(&ir->tlet); | ||
| 878 | |||
| 879 | return 1; | ||
| 880 | } | ||
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index eae72fd60cec..ef55a59f0cda 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c | |||
| @@ -66,11 +66,29 @@ static int buffer_activate(struct saa7134_dev *dev, | |||
| 66 | saa7134_set_dmabits(dev); | 66 | saa7134_set_dmabits(dev); |
| 67 | 67 | ||
| 68 | mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT); | 68 | mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT); |
| 69 | |||
| 70 | if (dev->ts_state == SAA7134_TS_BUFF_DONE) { | ||
| 71 | /* Clear TS cache */ | ||
| 72 | dev->buff_cnt = 0; | ||
| 73 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | ||
| 74 | saa_writeb(SAA7134_TS_SERIAL1, 0x03); | ||
| 75 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | ||
| 76 | saa_writeb(SAA7134_TS_SERIAL1, 0x01); | ||
| 77 | |||
| 78 | /* TS clock non-inverted */ | ||
| 79 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | ||
| 80 | |||
| 81 | /* Start TS stream */ | ||
| 82 | saa_writeb(SAA7134_TS_SERIAL0, 0x40); | ||
| 83 | saa_writeb(SAA7134_TS_PARALLEL, 0xEC); | ||
| 84 | dev->ts_state = SAA7134_TS_STARTED; | ||
| 85 | } | ||
| 86 | |||
| 69 | return 0; | 87 | return 0; |
| 70 | } | 88 | } |
| 71 | 89 | ||
| 72 | static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 90 | static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, |
| 73 | enum v4l2_field field) | 91 | enum v4l2_field field) |
| 74 | { | 92 | { |
| 75 | struct saa7134_dev *dev = q->priv_data; | 93 | struct saa7134_dev *dev = q->priv_data; |
| 76 | struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | 94 | struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); |
| @@ -110,16 +128,22 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
| 110 | goto oops; | 128 | goto oops; |
| 111 | } | 129 | } |
| 112 | 130 | ||
| 113 | /* dma: setup channel 5 (= TS) */ | 131 | dev->buff_cnt++; |
| 114 | control = SAA7134_RS_CONTROL_BURST_16 | | 132 | |
| 115 | SAA7134_RS_CONTROL_ME | | 133 | if (dev->buff_cnt == dev->ts.nr_bufs) { |
| 116 | (buf->pt->dma >> 12); | 134 | dev->ts_state = SAA7134_TS_BUFF_DONE; |
| 117 | 135 | /* dma: setup channel 5 (= TS) */ | |
| 118 | saa_writeb(SAA7134_TS_DMA0, ((lines-1)&0xff)); | 136 | control = SAA7134_RS_CONTROL_BURST_16 | |
| 119 | saa_writeb(SAA7134_TS_DMA1, (((lines-1)>>8)&0xff)); | 137 | SAA7134_RS_CONTROL_ME | |
| 120 | saa_writeb(SAA7134_TS_DMA2, ((((lines-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ | 138 | (buf->pt->dma >> 12); |
| 121 | saa_writel(SAA7134_RS_PITCH(5),TS_PACKET_SIZE); | 139 | |
| 122 | saa_writel(SAA7134_RS_CONTROL(5),control); | 140 | saa_writeb(SAA7134_TS_DMA0, (lines - 1) & 0xff); |
| 141 | saa_writeb(SAA7134_TS_DMA1, ((lines - 1) >> 8) & 0xff); | ||
| 142 | /* TSNOPIT=0, TSCOLAP=0 */ | ||
| 143 | saa_writeb(SAA7134_TS_DMA2, (((lines - 1) >> 16) & 0x3f) | 0x00); | ||
| 144 | saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); | ||
| 145 | saa_writel(SAA7134_RS_CONTROL(5), control); | ||
| 146 | } | ||
| 123 | 147 | ||
| 124 | buf->vb.state = VIDEOBUF_PREPARED; | 148 | buf->vb.state = VIDEOBUF_PREPARED; |
| 125 | buf->activate = buffer_activate; | 149 | buf->activate = buffer_activate; |
| @@ -140,6 +164,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | |||
| 140 | if (0 == *count) | 164 | if (0 == *count) |
| 141 | *count = dev->ts.nr_bufs; | 165 | *count = dev->ts.nr_bufs; |
| 142 | *count = saa7134_buffer_count(*size,*count); | 166 | *count = saa7134_buffer_count(*size,*count); |
| 167 | dev->buff_cnt = 0; | ||
| 168 | dev->ts_state = SAA7134_TS_STOPPED; | ||
| 143 | return 0; | 169 | return 0; |
| 144 | } | 170 | } |
| 145 | 171 | ||
| @@ -154,7 +180,13 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | |||
| 154 | static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | 180 | static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) |
| 155 | { | 181 | { |
| 156 | struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); | 182 | struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb); |
| 183 | struct saa7134_dev *dev = q->priv_data; | ||
| 157 | 184 | ||
| 185 | if (dev->ts_state == SAA7134_TS_STARTED) { | ||
| 186 | /* Stop TS transport */ | ||
| 187 | saa_writeb(SAA7134_TS_PARALLEL, 0x6c); | ||
| 188 | dev->ts_state = SAA7134_TS_STOPPED; | ||
| 189 | } | ||
| 158 | saa7134_dma_free(q,buf); | 190 | saa7134_dma_free(q,buf); |
| 159 | } | 191 | } |
| 160 | 192 | ||
| @@ -182,7 +214,7 @@ int saa7134_ts_init_hw(struct saa7134_dev *dev) | |||
| 182 | /* deactivate TS softreset */ | 214 | /* deactivate TS softreset */ |
| 183 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | 215 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); |
| 184 | /* TSSOP high active, TSVAL high active, TSLOCK ignored */ | 216 | /* TSSOP high active, TSVAL high active, TSLOCK ignored */ |
| 185 | saa_writeb(SAA7134_TS_PARALLEL, 0xec); | 217 | saa_writeb(SAA7134_TS_PARALLEL, 0x6c); |
| 186 | saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); | 218 | saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); |
| 187 | saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); | 219 | saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); |
| 188 | saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); | 220 | saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); |
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 68c268981861..02bb6747a39c 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
| @@ -628,6 +628,9 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev) | |||
| 628 | 628 | ||
| 629 | if (card_in(dev, dev->ctl_input).tv) | 629 | if (card_in(dev, dev->ctl_input).tv) |
| 630 | saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); | 630 | saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); |
| 631 | /* Set the correct norm for the saa6752hs. This function | ||
| 632 | does nothing if there is no saa6752hs. */ | ||
| 633 | saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id); | ||
| 631 | } | 634 | } |
| 632 | 635 | ||
| 633 | static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) | 636 | static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale) |
| @@ -1330,6 +1333,8 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 1330 | struct saa7134_fh *fh; | 1333 | struct saa7134_fh *fh; |
| 1331 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1334 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| 1332 | int radio = 0; | 1335 | int radio = 0; |
| 1336 | |||
| 1337 | lock_kernel(); | ||
| 1333 | list_for_each_entry(dev, &saa7134_devlist, devlist) { | 1338 | list_for_each_entry(dev, &saa7134_devlist, devlist) { |
| 1334 | if (dev->video_dev && (dev->video_dev->minor == minor)) | 1339 | if (dev->video_dev && (dev->video_dev->minor == minor)) |
| 1335 | goto found; | 1340 | goto found; |
| @@ -1342,6 +1347,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 1342 | goto found; | 1347 | goto found; |
| 1343 | } | 1348 | } |
| 1344 | } | 1349 | } |
| 1350 | unlock_kernel(); | ||
| 1345 | return -ENODEV; | 1351 | return -ENODEV; |
| 1346 | found: | 1352 | found: |
| 1347 | 1353 | ||
| @@ -1350,8 +1356,10 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 1350 | 1356 | ||
| 1351 | /* allocate + initialize per filehandle data */ | 1357 | /* allocate + initialize per filehandle data */ |
| 1352 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 1358 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
| 1353 | if (NULL == fh) | 1359 | if (NULL == fh) { |
| 1360 | unlock_kernel(); | ||
| 1354 | return -ENOMEM; | 1361 | return -ENOMEM; |
| 1362 | } | ||
| 1355 | file->private_data = fh; | 1363 | file->private_data = fh; |
| 1356 | fh->dev = dev; | 1364 | fh->dev = dev; |
| 1357 | fh->radio = radio; | 1365 | fh->radio = radio; |
| @@ -1384,6 +1392,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 1384 | /* switch to video/vbi mode */ | 1392 | /* switch to video/vbi mode */ |
| 1385 | video_mux(dev,dev->ctl_input); | 1393 | video_mux(dev,dev->ctl_input); |
| 1386 | } | 1394 | } |
| 1395 | unlock_kernel(); | ||
| 1387 | return 0; | 1396 | return 0; |
| 1388 | } | 1397 | } |
| 1389 | 1398 | ||
| @@ -1790,18 +1799,25 @@ static int saa7134_querycap(struct file *file, void *priv, | |||
| 1790 | return 0; | 1799 | return 0; |
| 1791 | } | 1800 | } |
| 1792 | 1801 | ||
| 1793 | static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) | 1802 | int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id) |
| 1794 | { | 1803 | { |
| 1795 | struct saa7134_fh *fh = priv; | ||
| 1796 | struct saa7134_dev *dev = fh->dev; | ||
| 1797 | unsigned long flags; | 1804 | unsigned long flags; |
| 1798 | unsigned int i; | 1805 | unsigned int i; |
| 1799 | v4l2_std_id fixup; | 1806 | v4l2_std_id fixup; |
| 1800 | int err; | 1807 | int err; |
| 1801 | 1808 | ||
| 1802 | err = v4l2_prio_check(&dev->prio, &fh->prio); | 1809 | /* When called from the empress code fh == NULL. |
| 1803 | if (0 != err) | 1810 | That needs to be fixed somehow, but for now this is |
| 1804 | return err; | 1811 | good enough. */ |
| 1812 | if (fh) { | ||
| 1813 | err = v4l2_prio_check(&dev->prio, &fh->prio); | ||
| 1814 | if (0 != err) | ||
| 1815 | return err; | ||
| 1816 | } else if (res_locked(dev, RESOURCE_OVERLAY)) { | ||
| 1817 | /* Don't change the std from the mpeg device | ||
| 1818 | if overlay is active. */ | ||
| 1819 | return -EBUSY; | ||
| 1820 | } | ||
| 1805 | 1821 | ||
| 1806 | for (i = 0; i < TVNORMS; i++) | 1822 | for (i = 0; i < TVNORMS; i++) |
| 1807 | if (*id == tvnorms[i].id) | 1823 | if (*id == tvnorms[i].id) |
| @@ -1834,7 +1850,7 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) | |||
| 1834 | *id = tvnorms[i].id; | 1850 | *id = tvnorms[i].id; |
| 1835 | 1851 | ||
| 1836 | mutex_lock(&dev->lock); | 1852 | mutex_lock(&dev->lock); |
| 1837 | if (res_check(fh, RESOURCE_OVERLAY)) { | 1853 | if (fh && res_check(fh, RESOURCE_OVERLAY)) { |
| 1838 | spin_lock_irqsave(&dev->slock, flags); | 1854 | spin_lock_irqsave(&dev->slock, flags); |
| 1839 | stop_preview(dev, fh); | 1855 | stop_preview(dev, fh); |
| 1840 | spin_unlock_irqrestore(&dev->slock, flags); | 1856 | spin_unlock_irqrestore(&dev->slock, flags); |
| @@ -1851,6 +1867,23 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) | |||
| 1851 | mutex_unlock(&dev->lock); | 1867 | mutex_unlock(&dev->lock); |
| 1852 | return 0; | 1868 | return 0; |
| 1853 | } | 1869 | } |
| 1870 | EXPORT_SYMBOL_GPL(saa7134_s_std_internal); | ||
| 1871 | |||
| 1872 | static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id) | ||
| 1873 | { | ||
| 1874 | struct saa7134_fh *fh = priv; | ||
| 1875 | |||
| 1876 | return saa7134_s_std_internal(fh->dev, fh, id); | ||
| 1877 | } | ||
| 1878 | |||
| 1879 | static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||
| 1880 | { | ||
| 1881 | struct saa7134_fh *fh = priv; | ||
| 1882 | struct saa7134_dev *dev = fh->dev; | ||
| 1883 | |||
| 1884 | *id = dev->tvnorm->id; | ||
| 1885 | return 0; | ||
| 1886 | } | ||
| 1854 | 1887 | ||
| 1855 | static int saa7134_cropcap(struct file *file, void *priv, | 1888 | static int saa7134_cropcap(struct file *file, void *priv, |
| 1856 | struct v4l2_cropcap *cap) | 1889 | struct v4l2_cropcap *cap) |
| @@ -2077,18 +2110,6 @@ static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv, | |||
| 2077 | return 0; | 2110 | return 0; |
| 2078 | } | 2111 | } |
| 2079 | 2112 | ||
| 2080 | static int saa7134_enum_fmt_vbi_cap(struct file *file, void *priv, | ||
| 2081 | struct v4l2_fmtdesc *f) | ||
| 2082 | { | ||
| 2083 | if (0 != f->index) | ||
| 2084 | return -EINVAL; | ||
| 2085 | |||
| 2086 | f->pixelformat = V4L2_PIX_FMT_GREY; | ||
| 2087 | strcpy(f->description, "vbi data"); | ||
| 2088 | |||
| 2089 | return 0; | ||
| 2090 | } | ||
| 2091 | |||
| 2092 | static int saa7134_g_fbuf(struct file *file, void *f, | 2113 | static int saa7134_g_fbuf(struct file *file, void *f, |
| 2093 | struct v4l2_framebuffer *fb) | 2114 | struct v4l2_framebuffer *fb) |
| 2094 | { | 2115 | { |
| @@ -2379,7 +2400,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
| 2379 | .vidioc_g_fmt_vid_overlay = saa7134_g_fmt_vid_overlay, | 2400 | .vidioc_g_fmt_vid_overlay = saa7134_g_fmt_vid_overlay, |
| 2380 | .vidioc_try_fmt_vid_overlay = saa7134_try_fmt_vid_overlay, | 2401 | .vidioc_try_fmt_vid_overlay = saa7134_try_fmt_vid_overlay, |
| 2381 | .vidioc_s_fmt_vid_overlay = saa7134_s_fmt_vid_overlay, | 2402 | .vidioc_s_fmt_vid_overlay = saa7134_s_fmt_vid_overlay, |
| 2382 | .vidioc_enum_fmt_vbi_cap = saa7134_enum_fmt_vbi_cap, | ||
| 2383 | .vidioc_g_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, | 2403 | .vidioc_g_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, |
| 2384 | .vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, | 2404 | .vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, |
| 2385 | .vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, | 2405 | .vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, |
| @@ -2391,6 +2411,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
| 2391 | .vidioc_qbuf = saa7134_qbuf, | 2411 | .vidioc_qbuf = saa7134_qbuf, |
| 2392 | .vidioc_dqbuf = saa7134_dqbuf, | 2412 | .vidioc_dqbuf = saa7134_dqbuf, |
| 2393 | .vidioc_s_std = saa7134_s_std, | 2413 | .vidioc_s_std = saa7134_s_std, |
| 2414 | .vidioc_g_std = saa7134_g_std, | ||
| 2394 | .vidioc_enum_input = saa7134_enum_input, | 2415 | .vidioc_enum_input = saa7134_enum_input, |
| 2395 | .vidioc_g_input = saa7134_g_input, | 2416 | .vidioc_g_input = saa7134_g_input, |
| 2396 | .vidioc_s_input = saa7134_s_input, | 2417 | .vidioc_s_input = saa7134_s_input, |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index a0884f639f65..491ab1f8fdd3 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
| @@ -269,6 +269,12 @@ struct saa7134_format { | |||
| 269 | #define SAA7134_BOARD_BEHOLD_M6_EXTRA 144 | 269 | #define SAA7134_BOARD_BEHOLD_M6_EXTRA 144 |
| 270 | #define SAA7134_BOARD_AVERMEDIA_M103 145 | 270 | #define SAA7134_BOARD_AVERMEDIA_M103 145 |
| 271 | #define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146 | 271 | #define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146 |
| 272 | #define SAA7134_BOARD_ASUSTeK_TIGER_3IN1 147 | ||
| 273 | #define SAA7134_BOARD_ENCORE_ENLTV_FM53 148 | ||
| 274 | #define SAA7134_BOARD_AVERMEDIA_M135A 149 | ||
| 275 | #define SAA7134_BOARD_REAL_ANGEL_220 150 | ||
| 276 | #define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151 | ||
| 277 | #define SAA7134_BOARD_ASUSTeK_TIGER 152 | ||
| 272 | 278 | ||
| 273 | #define SAA7134_MAXBOARDS 8 | 279 | #define SAA7134_MAXBOARDS 8 |
| 274 | #define SAA7134_INPUT_MAX 8 | 280 | #define SAA7134_INPUT_MAX 8 |
| @@ -462,6 +468,12 @@ struct saa7134_mpeg_ops { | |||
| 462 | void (*signal_change)(struct saa7134_dev *dev); | 468 | void (*signal_change)(struct saa7134_dev *dev); |
| 463 | }; | 469 | }; |
| 464 | 470 | ||
| 471 | enum saa7134_ts_status { | ||
| 472 | SAA7134_TS_STOPPED, | ||
| 473 | SAA7134_TS_BUFF_DONE, | ||
| 474 | SAA7134_TS_STARTED, | ||
| 475 | }; | ||
| 476 | |||
| 465 | /* global device status */ | 477 | /* global device status */ |
| 466 | struct saa7134_dev { | 478 | struct saa7134_dev { |
| 467 | struct list_head devlist; | 479 | struct list_head devlist; |
| @@ -555,6 +567,8 @@ struct saa7134_dev { | |||
| 555 | /* SAA7134_MPEG_* */ | 567 | /* SAA7134_MPEG_* */ |
| 556 | struct saa7134_ts ts; | 568 | struct saa7134_ts ts; |
| 557 | struct saa7134_dmaqueue ts_q; | 569 | struct saa7134_dmaqueue ts_q; |
| 570 | enum saa7134_ts_status ts_state; | ||
| 571 | unsigned int buff_cnt; | ||
| 558 | struct saa7134_mpeg_ops *mops; | 572 | struct saa7134_mpeg_ops *mops; |
| 559 | struct i2c_client *mpeg_i2c_client; | 573 | struct i2c_client *mpeg_i2c_client; |
| 560 | 574 | ||
| @@ -644,7 +658,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[]; | |||
| 644 | 658 | ||
| 645 | extern int saa7134_board_init1(struct saa7134_dev *dev); | 659 | extern int saa7134_board_init1(struct saa7134_dev *dev); |
| 646 | extern int saa7134_board_init2(struct saa7134_dev *dev); | 660 | extern int saa7134_board_init2(struct saa7134_dev *dev); |
| 647 | int saa7134_tuner_callback(void *priv, int command, int arg); | 661 | int saa7134_tuner_callback(void *priv, int component, int command, int arg); |
| 648 | 662 | ||
| 649 | 663 | ||
| 650 | /* ----------------------------------------------------------- */ | 664 | /* ----------------------------------------------------------- */ |
| @@ -654,6 +668,8 @@ int saa7134_i2c_register(struct saa7134_dev *dev); | |||
| 654 | int saa7134_i2c_unregister(struct saa7134_dev *dev); | 668 | int saa7134_i2c_unregister(struct saa7134_dev *dev); |
| 655 | void saa7134_i2c_call_clients(struct saa7134_dev *dev, | 669 | void saa7134_i2c_call_clients(struct saa7134_dev *dev, |
| 656 | unsigned int cmd, void *arg); | 670 | unsigned int cmd, void *arg); |
| 671 | int saa7134_i2c_call_saa6752(struct saa7134_dev *dev, | ||
| 672 | unsigned int cmd, void *arg); | ||
| 657 | 673 | ||
| 658 | 674 | ||
| 659 | /* ----------------------------------------------------------- */ | 675 | /* ----------------------------------------------------------- */ |
| @@ -666,6 +682,7 @@ extern struct video_device saa7134_radio_template; | |||
| 666 | int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); | 682 | int saa7134_s_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); |
| 667 | int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); | 683 | int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c); |
| 668 | int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c); | 684 | int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c); |
| 685 | int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id); | ||
| 669 | 686 | ||
| 670 | int saa7134_videoport_init(struct saa7134_dev *dev); | 687 | int saa7134_videoport_init(struct saa7134_dev *dev); |
| 671 | void saa7134_set_tvnorm_hw(struct saa7134_dev *dev); | 688 | void saa7134_set_tvnorm_hw(struct saa7134_dev *dev); |
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index acceed5d04ae..ae3949180c4e 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c | |||
| @@ -288,7 +288,7 @@ static void se401_button_irq(struct urb *urb) | |||
| 288 | int status; | 288 | int status; |
| 289 | 289 | ||
| 290 | if (!se401->dev) { | 290 | if (!se401->dev) { |
| 291 | info("ohoh: device vapourished"); | 291 | dev_info(&urb->dev->dev, "device vapourished\n"); |
| 292 | return; | 292 | return; |
| 293 | } | 293 | } |
| 294 | 294 | ||
| @@ -328,7 +328,7 @@ static void se401_video_irq(struct urb *urb) | |||
| 328 | return; | 328 | return; |
| 329 | 329 | ||
| 330 | if (!se401->dev) { | 330 | if (!se401->dev) { |
| 331 | info ("ohoh: device vapourished"); | 331 | dev_info(&urb->dev->dev, "device vapourished\n"); |
| 332 | return; | 332 | return; |
| 333 | } | 333 | } |
| 334 | 334 | ||
| @@ -375,7 +375,7 @@ static void se401_video_irq(struct urb *urb) | |||
| 375 | urb->status=0; | 375 | urb->status=0; |
| 376 | urb->dev=se401->dev; | 376 | urb->dev=se401->dev; |
| 377 | if(usb_submit_urb(urb, GFP_KERNEL)) | 377 | if(usb_submit_urb(urb, GFP_KERNEL)) |
| 378 | info("urb burned down"); | 378 | dev_info(&urb->dev->dev, "urb burned down\n"); |
| 379 | return; | 379 | return; |
| 380 | } | 380 | } |
| 381 | 381 | ||
| @@ -860,7 +860,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) | |||
| 860 | ); | 860 | ); |
| 861 | if (se401->nullpackets > SE401_MAX_NULLPACKETS) { | 861 | if (se401->nullpackets > SE401_MAX_NULLPACKETS) { |
| 862 | se401->nullpackets=0; | 862 | se401->nullpackets=0; |
| 863 | info("to many null length packets, restarting capture"); | 863 | dev_info(&se401->dev->dev, |
| 864 | "too many null length packets, restarting capture\n"); | ||
| 864 | se401_stop_stream(se401); | 865 | se401_stop_stream(se401); |
| 865 | se401_start_stream(se401); | 866 | se401_start_stream(se401); |
| 866 | } else { | 867 | } else { |
| @@ -880,7 +881,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) | |||
| 880 | se401->scratch_use=0; | 881 | se401->scratch_use=0; |
| 881 | if (errors > SE401_MAX_ERRORS) { | 882 | if (errors > SE401_MAX_ERRORS) { |
| 882 | errors=0; | 883 | errors=0; |
| 883 | info("to much errors, restarting capture"); | 884 | dev_info(&se401->dev->dev, |
| 885 | "too many errors, restarting capture\n"); | ||
| 884 | se401_stop_stream(se401); | 886 | se401_stop_stream(se401); |
| 885 | se401_start_stream(se401); | 887 | se401_start_stream(se401); |
| 886 | } | 888 | } |
| @@ -913,7 +915,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401) | |||
| 913 | usb_kill_urb(se401->inturb); | 915 | usb_kill_urb(se401->inturb); |
| 914 | usb_free_urb(se401->inturb); | 916 | usb_free_urb(se401->inturb); |
| 915 | } | 917 | } |
| 916 | info("%s disconnected", se401->camera_name); | 918 | dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name); |
| 917 | 919 | ||
| 918 | /* Free the memory */ | 920 | /* Free the memory */ |
| 919 | kfree(se401->width); | 921 | kfree(se401->width); |
| @@ -936,14 +938,18 @@ static int se401_open(struct inode *inode, struct file *file) | |||
| 936 | struct usb_se401 *se401 = (struct usb_se401 *)dev; | 938 | struct usb_se401 *se401 = (struct usb_se401 *)dev; |
| 937 | int err = 0; | 939 | int err = 0; |
| 938 | 940 | ||
| 939 | if (se401->user) | 941 | lock_kernel(); |
| 942 | if (se401->user) { | ||
| 943 | unlock_kernel(); | ||
| 940 | return -EBUSY; | 944 | return -EBUSY; |
| 945 | } | ||
| 941 | se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); | 946 | se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES); |
| 942 | if (se401->fbuf) | 947 | if (se401->fbuf) |
| 943 | file->private_data = dev; | 948 | file->private_data = dev; |
| 944 | else | 949 | else |
| 945 | err = -ENOMEM; | 950 | err = -ENOMEM; |
| 946 | se401->user = !err; | 951 | se401->user = !err; |
| 952 | unlock_kernel(); | ||
| 947 | 953 | ||
| 948 | return err; | 954 | return err; |
| 949 | } | 955 | } |
| @@ -956,8 +962,8 @@ static int se401_close(struct inode *inode, struct file *file) | |||
| 956 | 962 | ||
| 957 | rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); | 963 | rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); |
| 958 | if (se401->removed) { | 964 | if (se401->removed) { |
| 965 | dev_info(&se401->dev->dev, "device unregistered\n"); | ||
| 959 | usb_se401_remove_disconnected(se401); | 966 | usb_se401_remove_disconnected(se401); |
| 960 | info("device unregistered"); | ||
| 961 | } else { | 967 | } else { |
| 962 | for (i=0; i<SE401_NUMFRAMES; i++) | 968 | for (i=0; i<SE401_NUMFRAMES; i++) |
| 963 | se401->frame[i].grabstate=FRAME_UNUSED; | 969 | se401->frame[i].grabstate=FRAME_UNUSED; |
| @@ -1232,6 +1238,7 @@ static const struct file_operations se401_fops = { | |||
| 1232 | static struct video_device se401_template = { | 1238 | static struct video_device se401_template = { |
| 1233 | .name = "se401 USB camera", | 1239 | .name = "se401 USB camera", |
| 1234 | .fops = &se401_fops, | 1240 | .fops = &se401_fops, |
| 1241 | .release = video_device_release_empty, | ||
| 1235 | }; | 1242 | }; |
| 1236 | 1243 | ||
| 1237 | 1244 | ||
| @@ -1271,7 +1278,7 @@ static int se401_init(struct usb_se401 *se401, int button) | |||
| 1271 | for (i=0; i<se401->sizes; i++) { | 1278 | for (i=0; i<se401->sizes; i++) { |
| 1272 | sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]); | 1279 | sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]); |
| 1273 | } | 1280 | } |
| 1274 | info("%s", temp); | 1281 | dev_info(&se401->dev->dev, "%s\n", temp); |
| 1275 | se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; | 1282 | se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; |
| 1276 | 1283 | ||
| 1277 | rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); | 1284 | rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); |
| @@ -1305,7 +1312,8 @@ static int se401_init(struct usb_se401 *se401, int button) | |||
| 1305 | if (button) { | 1312 | if (button) { |
| 1306 | se401->inturb=usb_alloc_urb(0, GFP_KERNEL); | 1313 | se401->inturb=usb_alloc_urb(0, GFP_KERNEL); |
| 1307 | if (!se401->inturb) { | 1314 | if (!se401->inturb) { |
| 1308 | info("Allocation of inturb failed"); | 1315 | dev_info(&se401->dev->dev, |
| 1316 | "Allocation of inturb failed\n"); | ||
| 1309 | return 1; | 1317 | return 1; |
| 1310 | } | 1318 | } |
| 1311 | usb_fill_int_urb(se401->inturb, se401->dev, | 1319 | usb_fill_int_urb(se401->inturb, se401->dev, |
| @@ -1316,7 +1324,7 @@ static int se401_init(struct usb_se401 *se401, int button) | |||
| 1316 | 8 | 1324 | 8 |
| 1317 | ); | 1325 | ); |
| 1318 | if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { | 1326 | if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { |
| 1319 | info("int urb burned down"); | 1327 | dev_info(&se401->dev->dev, "int urb burned down\n"); |
| 1320 | return 1; | 1328 | return 1; |
| 1321 | } | 1329 | } |
| 1322 | } else | 1330 | } else |
| @@ -1373,7 +1381,7 @@ static int se401_probe(struct usb_interface *intf, | |||
| 1373 | return -ENODEV; | 1381 | return -ENODEV; |
| 1374 | 1382 | ||
| 1375 | /* We found one */ | 1383 | /* We found one */ |
| 1376 | info("SE401 camera found: %s", camera_name); | 1384 | dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name); |
| 1377 | 1385 | ||
| 1378 | if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { | 1386 | if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { |
| 1379 | err("couldn't kmalloc se401 struct"); | 1387 | err("couldn't kmalloc se401 struct"); |
| @@ -1384,7 +1392,8 @@ static int se401_probe(struct usb_interface *intf, | |||
| 1384 | se401->iface = interface->bInterfaceNumber; | 1392 | se401->iface = interface->bInterfaceNumber; |
| 1385 | se401->camera_name = camera_name; | 1393 | se401->camera_name = camera_name; |
| 1386 | 1394 | ||
| 1387 | info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255); | 1395 | dev_info(&intf->dev, "firmware version: %02x\n", |
| 1396 | le16_to_cpu(dev->descriptor.bcdDevice) & 255); | ||
| 1388 | 1397 | ||
| 1389 | if (se401_init(se401, button)) { | 1398 | if (se401_init(se401, button)) { |
| 1390 | kfree(se401); | 1399 | kfree(se401); |
| @@ -1402,7 +1411,8 @@ static int se401_probe(struct usb_interface *intf, | |||
| 1402 | err("video_register_device failed"); | 1411 | err("video_register_device failed"); |
| 1403 | return -EIO; | 1412 | return -EIO; |
| 1404 | } | 1413 | } |
| 1405 | info("registered new video device: video%d", se401->vdev.minor); | 1414 | dev_info(&intf->dev, "registered new video device: video%d\n", |
| 1415 | se401->vdev.minor); | ||
| 1406 | 1416 | ||
| 1407 | usb_set_intfdata (intf, se401); | 1417 | usb_set_intfdata (intf, se401); |
| 1408 | return 0; | 1418 | return 0; |
| @@ -1446,10 +1456,10 @@ static struct usb_driver se401_driver = { | |||
| 1446 | 1456 | ||
| 1447 | static int __init usb_se401_init(void) | 1457 | static int __init usb_se401_init(void) |
| 1448 | { | 1458 | { |
| 1449 | info("SE401 usb camera driver version %s registering", version); | 1459 | printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version); |
| 1450 | if (flickerless) | 1460 | if (flickerless) |
| 1451 | if (flickerless!=50 && flickerless!=60) { | 1461 | if (flickerless!=50 && flickerless!=60) { |
| 1452 | info("Invallid flickerless value, use 0, 50 or 60."); | 1462 | printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n"); |
| 1453 | return -1; | 1463 | return -1; |
| 1454 | } | 1464 | } |
| 1455 | return usb_register(&se401_driver); | 1465 | return usb_register(&se401_driver); |
| @@ -1458,7 +1468,7 @@ static int __init usb_se401_init(void) | |||
| 1458 | static void __exit usb_se401_exit(void) | 1468 | static void __exit usb_se401_exit(void) |
| 1459 | { | 1469 | { |
| 1460 | usb_deregister(&se401_driver); | 1470 | usb_deregister(&se401_driver); |
| 1461 | info("SE401 driver deregistered"); | 1471 | printk(KERN_INFO "SE401 driver deregistered\frame"); |
| 1462 | } | 1472 | } |
| 1463 | 1473 | ||
| 1464 | module_init(usb_se401_init); | 1474 | module_init(usb_se401_init); |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 318754e73132..76838091dc66 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
| @@ -304,9 +304,6 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
| 304 | "SuperH Mobile CEU driver attached to camera %d\n", | 304 | "SuperH Mobile CEU driver attached to camera %d\n", |
| 305 | icd->devnum); | 305 | icd->devnum); |
| 306 | 306 | ||
| 307 | if (pcdev->pdata->enable_camera) | ||
| 308 | pcdev->pdata->enable_camera(); | ||
| 309 | |||
| 310 | ret = icd->ops->init(icd); | 307 | ret = icd->ops->init(icd); |
| 311 | if (ret) | 308 | if (ret) |
| 312 | goto err; | 309 | goto err; |
| @@ -333,8 +330,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
| 333 | ceu_write(pcdev, CEIER, 0); | 330 | ceu_write(pcdev, CEIER, 0); |
| 334 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | 331 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ |
| 335 | icd->ops->release(icd); | 332 | icd->ops->release(icd); |
| 336 | if (pcdev->pdata->disable_camera) | ||
| 337 | pcdev->pdata->disable_camera(); | ||
| 338 | 333 | ||
| 339 | dev_info(&icd->dev, | 334 | dev_info(&icd->dev, |
| 340 | "SuperH Mobile CEU driver detached from camera %d\n", | 335 | "SuperH Mobile CEU driver detached from camera %d\n", |
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 2da6938718f2..20e30bd9364b 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c | |||
| @@ -116,6 +116,26 @@ MODULE_PARM_DESC(debug, | |||
| 116 | "\n"); | 116 | "\n"); |
| 117 | #endif | 117 | #endif |
| 118 | 118 | ||
| 119 | /* | ||
| 120 | Add the probe entries to this table. Be sure to add the entry in the right | ||
| 121 | place, since, on failure, the next probing routine is called according to | ||
| 122 | the order of the list below, from top to bottom. | ||
| 123 | */ | ||
| 124 | static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = { | ||
| 125 | &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ | ||
| 126 | &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ | ||
| 127 | &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ | ||
| 128 | &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ | ||
| 129 | &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */ | ||
| 130 | &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ | ||
| 131 | &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ | ||
| 132 | &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ | ||
| 133 | &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ | ||
| 134 | &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ | ||
| 135 | &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ | ||
| 136 | &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ | ||
| 137 | }; | ||
| 138 | |||
| 119 | /*****************************************************************************/ | 139 | /*****************************************************************************/ |
| 120 | 140 | ||
| 121 | static u32 | 141 | static u32 |
| @@ -1746,7 +1766,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) | |||
| 1746 | if (!down_read_trylock(&sn9c102_dev_lock)) | 1766 | if (!down_read_trylock(&sn9c102_dev_lock)) |
| 1747 | return -ERESTARTSYS; | 1767 | return -ERESTARTSYS; |
| 1748 | 1768 | ||
| 1749 | cam = video_get_drvdata(video_devdata(filp)); | 1769 | cam = video_drvdata(filp); |
| 1750 | 1770 | ||
| 1751 | if (wait_for_completion_interruptible(&cam->probe)) { | 1771 | if (wait_for_completion_interruptible(&cam->probe)) { |
| 1752 | up_read(&sn9c102_dev_lock); | 1772 | up_read(&sn9c102_dev_lock); |
| @@ -1843,7 +1863,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) | |||
| 1843 | 1863 | ||
| 1844 | down_write(&sn9c102_dev_lock); | 1864 | down_write(&sn9c102_dev_lock); |
| 1845 | 1865 | ||
| 1846 | cam = video_get_drvdata(video_devdata(filp)); | 1866 | cam = video_drvdata(filp); |
| 1847 | 1867 | ||
| 1848 | sn9c102_stop_transfer(cam); | 1868 | sn9c102_stop_transfer(cam); |
| 1849 | sn9c102_release_buffers(cam); | 1869 | sn9c102_release_buffers(cam); |
| @@ -1863,7 +1883,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) | |||
| 1863 | static ssize_t | 1883 | static ssize_t |
| 1864 | sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) | 1884 | sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) |
| 1865 | { | 1885 | { |
| 1866 | struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); | 1886 | struct sn9c102_device *cam = video_drvdata(filp); |
| 1867 | struct sn9c102_frame_t* f, * i; | 1887 | struct sn9c102_frame_t* f, * i; |
| 1868 | unsigned long lock_flags; | 1888 | unsigned long lock_flags; |
| 1869 | long timeout; | 1889 | long timeout; |
| @@ -1987,7 +2007,7 @@ exit: | |||
| 1987 | 2007 | ||
| 1988 | static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) | 2008 | static unsigned int sn9c102_poll(struct file *filp, poll_table *wait) |
| 1989 | { | 2009 | { |
| 1990 | struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); | 2010 | struct sn9c102_device *cam = video_drvdata(filp); |
| 1991 | struct sn9c102_frame_t* f; | 2011 | struct sn9c102_frame_t* f; |
| 1992 | unsigned long lock_flags; | 2012 | unsigned long lock_flags; |
| 1993 | unsigned int mask = 0; | 2013 | unsigned int mask = 0; |
| @@ -2063,7 +2083,7 @@ static struct vm_operations_struct sn9c102_vm_ops = { | |||
| 2063 | 2083 | ||
| 2064 | static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) | 2084 | static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) |
| 2065 | { | 2085 | { |
| 2066 | struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); | 2086 | struct sn9c102_device *cam = video_drvdata(filp); |
| 2067 | unsigned long size = vma->vm_end - vma->vm_start, | 2087 | unsigned long size = vma->vm_end - vma->vm_start, |
| 2068 | start = vma->vm_start; | 2088 | start = vma->vm_start; |
| 2069 | void *pos; | 2089 | void *pos; |
| @@ -3075,7 +3095,7 @@ sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg) | |||
| 3075 | static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, | 3095 | static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, |
| 3076 | unsigned int cmd, void __user * arg) | 3096 | unsigned int cmd, void __user * arg) |
| 3077 | { | 3097 | { |
| 3078 | struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); | 3098 | struct sn9c102_device *cam = video_drvdata(filp); |
| 3079 | 3099 | ||
| 3080 | switch (cmd) { | 3100 | switch (cmd) { |
| 3081 | 3101 | ||
| @@ -3179,7 +3199,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
| 3179 | static int sn9c102_ioctl(struct inode* inode, struct file* filp, | 3199 | static int sn9c102_ioctl(struct inode* inode, struct file* filp, |
| 3180 | unsigned int cmd, unsigned long arg) | 3200 | unsigned int cmd, unsigned long arg) |
| 3181 | { | 3201 | { |
| 3182 | struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); | 3202 | struct sn9c102_device *cam = video_drvdata(filp); |
| 3183 | int err = 0; | 3203 | int err = 0; |
| 3184 | 3204 | ||
| 3185 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | 3205 | if (mutex_lock_interruptible(&cam->fileop_mutex)) |
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 90a401dc3884..e23734f6d6e2 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h | |||
| @@ -140,24 +140,4 @@ extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); | |||
| 140 | extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam); | 140 | extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam); |
| 141 | extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); | 141 | extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); |
| 142 | 142 | ||
| 143 | /* | ||
| 144 | Add the above entries to this table. Be sure to add the entry in the right | ||
| 145 | place, since, on failure, the next probing routine is called according to | ||
| 146 | the order of the list below, from top to bottom. | ||
| 147 | */ | ||
| 148 | static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { | ||
| 149 | &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ | ||
| 150 | &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */ | ||
| 151 | &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ | ||
| 152 | &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */ | ||
| 153 | &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */ | ||
| 154 | &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ | ||
| 155 | &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ | ||
| 156 | &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */ | ||
| 157 | &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */ | ||
| 158 | &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ | ||
| 159 | &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ | ||
| 160 | &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ | ||
| 161 | }; | ||
| 162 | |||
| 163 | #endif /* _SN9C102_DEVTABLE_H_ */ | 143 | #endif /* _SN9C102_DEVTABLE_H_ */ |
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c index eaf9ad0dc8a6..db2434948939 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | 21 | ||
| 22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
| 23 | #include "sn9c102_devtable.h" | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | static int hv7131d_init(struct sn9c102_device* cam) | 26 | static int hv7131d_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/video/sn9c102/sn9c102_hv7131r.c index 0fc401223cfc..4295887ff609 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131r.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131r.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | 21 | ||
| 22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
| 23 | #include "sn9c102_devtable.h" | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | static int hv7131r_init(struct sn9c102_device* cam) | 26 | static int hv7131r_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c index 00b134ca0a3d..1f5b09bec89c 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | 21 | ||
| 22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
| 23 | #include "sn9c102_devtable.h" | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | static int mi0343_init(struct sn9c102_device* cam) | 26 | static int mi0343_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/video/sn9c102/sn9c102_mi0360.c index f8d81d82e8d5..d973fc1973d9 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0360.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0360.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | 21 | ||
| 22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
| 23 | #include "sn9c102_devtable.h" | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | static int mi0360_init(struct sn9c102_device* cam) | 26 | static int mi0360_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_mt9v111.c b/drivers/media/video/sn9c102/sn9c102_mt9v111.c index 3b98ac3bbc38..95986eb492e4 100644 --- a/drivers/media/video/sn9c102/sn9c102_mt9v111.c +++ b/drivers/media/video/sn9c102/sn9c102_mt9v111.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | 21 | ||
| 22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
| 23 | #include "sn9c102_devtable.h" | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | static int mt9v111_init(struct sn9c102_device *cam) | 26 | static int mt9v111_init(struct sn9c102_device *cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c index e4856fd77982..803712c29f02 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | 21 | ||
| 22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
| 23 | #include "sn9c102_devtable.h" | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | static int ov7630_init(struct sn9c102_device* cam) | 26 | static int ov7630_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c index 8aae416ba8ec..7977795d342b 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7660.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | 21 | ||
| 22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
| 23 | #include "sn9c102_devtable.h" | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | static int ov7660_init(struct sn9c102_device* cam) | 26 | static int ov7660_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c index 360f2a848bc0..81cd969c1b7b 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| 23 | #include "sn9c102_sensor.h" | 23 | #include "sn9c102_sensor.h" |
| 24 | #include "sn9c102_devtable.h" | ||
| 24 | 25 | ||
| 25 | 26 | ||
| 26 | static int pas106b_init(struct sn9c102_device* cam) | 27 | static int pas106b_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c index ca4a1506ed3d..2782f94cf6f8 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
| 28 | #include "sn9c102_sensor.h" | 28 | #include "sn9c102_sensor.h" |
| 29 | #include "sn9c102_devtable.h" | ||
| 29 | 30 | ||
| 30 | 31 | ||
| 31 | static int pas202bcb_init(struct sn9c102_device* cam) | 32 | static int pas202bcb_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c index e7d2de2bace1..04cdfdde8564 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | 21 | ||
| 22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
| 23 | #include "sn9c102_devtable.h" | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | static int tas5110c1b_init(struct sn9c102_device* cam) | 26 | static int tas5110c1b_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c index d32fdbccdc5e..9372e6f9fcff 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110d.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110d.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | 21 | ||
| 22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
| 23 | #include "sn9c102_devtable.h" | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | static int tas5110d_init(struct sn9c102_device* cam) | 26 | static int tas5110d_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c index 56fb1d575a8a..a30bbc4389f5 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | 21 | ||
| 22 | #include "sn9c102_sensor.h" | 22 | #include "sn9c102_sensor.h" |
| 23 | #include "sn9c102_devtable.h" | ||
| 23 | 24 | ||
| 24 | 25 | ||
| 25 | static int tas5130d1b_init(struct sn9c102_device* cam) | 26 | static int tas5130d1b_init(struct sn9c102_device* cam) |
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index ad36af30e099..db69bc5556d6 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c | |||
| @@ -65,22 +65,6 @@ static struct usb_device_id stkwebcam_table[] = { | |||
| 65 | }; | 65 | }; |
| 66 | MODULE_DEVICE_TABLE(usb, stkwebcam_table); | 66 | MODULE_DEVICE_TABLE(usb, stkwebcam_table); |
| 67 | 67 | ||
| 68 | static void stk_camera_cleanup(struct kref *kref) | ||
| 69 | { | ||
| 70 | struct stk_camera *dev = to_stk_camera(kref); | ||
| 71 | |||
| 72 | STK_INFO("Syntek USB2.0 Camera release resources" | ||
| 73 | " video device /dev/video%d\n", dev->vdev.minor); | ||
| 74 | video_unregister_device(&dev->vdev); | ||
| 75 | dev->vdev.priv = NULL; | ||
| 76 | |||
| 77 | if (dev->sio_bufs != NULL || dev->isobufs != NULL) | ||
| 78 | STK_ERROR("We are leaking memory\n"); | ||
| 79 | usb_put_intf(dev->interface); | ||
| 80 | kfree(dev); | ||
| 81 | } | ||
| 82 | |||
| 83 | |||
| 84 | /* | 68 | /* |
| 85 | * Basic stuff | 69 | * Basic stuff |
| 86 | */ | 70 | */ |
| @@ -689,34 +673,24 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) | |||
| 689 | vdev = video_devdata(fp); | 673 | vdev = video_devdata(fp); |
| 690 | dev = vdev_to_camera(vdev); | 674 | dev = vdev_to_camera(vdev); |
| 691 | 675 | ||
| 692 | if (dev == NULL || !is_present(dev)) | 676 | lock_kernel(); |
| 677 | if (dev == NULL || !is_present(dev)) { | ||
| 678 | unlock_kernel(); | ||
| 693 | return -ENXIO; | 679 | return -ENXIO; |
| 694 | fp->private_data = vdev; | 680 | } |
| 695 | kref_get(&dev->kref); | 681 | fp->private_data = dev; |
| 696 | usb_autopm_get_interface(dev->interface); | 682 | usb_autopm_get_interface(dev->interface); |
| 683 | unlock_kernel(); | ||
| 697 | 684 | ||
| 698 | return 0; | 685 | return 0; |
| 699 | } | 686 | } |
| 700 | 687 | ||
| 701 | static int v4l_stk_release(struct inode *inode, struct file *fp) | 688 | static int v4l_stk_release(struct inode *inode, struct file *fp) |
| 702 | { | 689 | { |
| 703 | struct stk_camera *dev; | 690 | struct stk_camera *dev = fp->private_data; |
| 704 | struct video_device *vdev; | ||
| 705 | |||
| 706 | vdev = video_devdata(fp); | ||
| 707 | if (vdev == NULL) { | ||
| 708 | STK_ERROR("v4l_release called w/o video devdata\n"); | ||
| 709 | return -EFAULT; | ||
| 710 | } | ||
| 711 | dev = vdev_to_camera(vdev); | ||
| 712 | if (dev == NULL) { | ||
| 713 | STK_ERROR("v4l_release called on removed device\n"); | ||
| 714 | return -ENODEV; | ||
| 715 | } | ||
| 716 | 691 | ||
| 717 | if (dev->owner != fp) { | 692 | if (dev->owner != fp) { |
| 718 | usb_autopm_put_interface(dev->interface); | 693 | usb_autopm_put_interface(dev->interface); |
| 719 | kref_put(&dev->kref, stk_camera_cleanup); | ||
| 720 | return 0; | 694 | return 0; |
| 721 | } | 695 | } |
| 722 | 696 | ||
| @@ -727,7 +701,6 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) | |||
| 727 | dev->owner = NULL; | 701 | dev->owner = NULL; |
| 728 | 702 | ||
| 729 | usb_autopm_put_interface(dev->interface); | 703 | usb_autopm_put_interface(dev->interface); |
| 730 | kref_put(&dev->kref, stk_camera_cleanup); | ||
| 731 | 704 | ||
| 732 | return 0; | 705 | return 0; |
| 733 | } | 706 | } |
| @@ -738,14 +711,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, | |||
| 738 | int i; | 711 | int i; |
| 739 | int ret; | 712 | int ret; |
| 740 | unsigned long flags; | 713 | unsigned long flags; |
| 741 | struct stk_camera *dev; | ||
| 742 | struct video_device *vdev; | ||
| 743 | struct stk_sio_buffer *sbuf; | 714 | struct stk_sio_buffer *sbuf; |
| 744 | 715 | struct stk_camera *dev = fp->private_data; | |
| 745 | vdev = video_devdata(fp); | ||
| 746 | if (vdev == NULL) | ||
| 747 | return -EFAULT; | ||
| 748 | dev = vdev_to_camera(vdev); | ||
| 749 | 716 | ||
| 750 | if (dev == NULL) | 717 | if (dev == NULL) |
| 751 | return -EIO; | 718 | return -EIO; |
| @@ -804,15 +771,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, | |||
| 804 | 771 | ||
| 805 | static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) | 772 | static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) |
| 806 | { | 773 | { |
| 807 | struct stk_camera *dev; | 774 | struct stk_camera *dev = fp->private_data; |
| 808 | struct video_device *vdev; | ||
| 809 | |||
| 810 | vdev = video_devdata(fp); | ||
| 811 | |||
| 812 | if (vdev == NULL) | ||
| 813 | return -EFAULT; | ||
| 814 | 775 | ||
| 815 | dev = vdev_to_camera(vdev); | ||
| 816 | if (dev == NULL) | 776 | if (dev == NULL) |
| 817 | return -ENODEV; | 777 | return -ENODEV; |
| 818 | 778 | ||
| @@ -850,16 +810,12 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma) | |||
| 850 | unsigned int i; | 810 | unsigned int i; |
| 851 | int ret; | 811 | int ret; |
| 852 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | 812 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; |
| 853 | struct stk_camera *dev; | 813 | struct stk_camera *dev = fp->private_data; |
| 854 | struct video_device *vdev; | ||
| 855 | struct stk_sio_buffer *sbuf = NULL; | 814 | struct stk_sio_buffer *sbuf = NULL; |
| 856 | 815 | ||
| 857 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) | 816 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) |
| 858 | return -EINVAL; | 817 | return -EINVAL; |
| 859 | 818 | ||
| 860 | vdev = video_devdata(fp); | ||
| 861 | dev = vdev_to_camera(vdev); | ||
| 862 | |||
| 863 | for (i = 0; i < dev->n_sbufs; i++) { | 819 | for (i = 0; i < dev->n_sbufs; i++) { |
| 864 | if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { | 820 | if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { |
| 865 | sbuf = dev->sio_bufs + i; | 821 | sbuf = dev->sio_bufs + i; |
| @@ -1355,6 +1311,12 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { | |||
| 1355 | 1311 | ||
| 1356 | static void stk_v4l_dev_release(struct video_device *vd) | 1312 | static void stk_v4l_dev_release(struct video_device *vd) |
| 1357 | { | 1313 | { |
| 1314 | struct stk_camera *dev = vdev_to_camera(vd); | ||
| 1315 | |||
| 1316 | if (dev->sio_bufs != NULL || dev->isobufs != NULL) | ||
| 1317 | STK_ERROR("We are leaking memory\n"); | ||
| 1318 | usb_put_intf(dev->interface); | ||
| 1319 | kfree(dev); | ||
| 1358 | } | 1320 | } |
| 1359 | 1321 | ||
| 1360 | static struct video_device stk_v4l_data = { | 1322 | static struct video_device stk_v4l_data = { |
| @@ -1375,7 +1337,6 @@ static int stk_register_video_device(struct stk_camera *dev) | |||
| 1375 | dev->vdev = stk_v4l_data; | 1337 | dev->vdev = stk_v4l_data; |
| 1376 | dev->vdev.debug = debug; | 1338 | dev->vdev.debug = debug; |
| 1377 | dev->vdev.parent = &dev->interface->dev; | 1339 | dev->vdev.parent = &dev->interface->dev; |
| 1378 | dev->vdev.priv = dev; | ||
| 1379 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); | 1340 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); |
| 1380 | if (err) | 1341 | if (err) |
| 1381 | STK_ERROR("v4l registration failed\n"); | 1342 | STK_ERROR("v4l registration failed\n"); |
| @@ -1392,7 +1353,7 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
| 1392 | const struct usb_device_id *id) | 1353 | const struct usb_device_id *id) |
| 1393 | { | 1354 | { |
| 1394 | int i; | 1355 | int i; |
| 1395 | int err; | 1356 | int err = 0; |
| 1396 | 1357 | ||
| 1397 | struct stk_camera *dev = NULL; | 1358 | struct stk_camera *dev = NULL; |
| 1398 | struct usb_device *udev = interface_to_usbdev(interface); | 1359 | struct usb_device *udev = interface_to_usbdev(interface); |
| @@ -1405,7 +1366,6 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
| 1405 | return -ENOMEM; | 1366 | return -ENOMEM; |
| 1406 | } | 1367 | } |
| 1407 | 1368 | ||
| 1408 | kref_init(&dev->kref); | ||
| 1409 | spin_lock_init(&dev->spinlock); | 1369 | spin_lock_init(&dev->spinlock); |
| 1410 | init_waitqueue_head(&dev->wait_frame); | 1370 | init_waitqueue_head(&dev->wait_frame); |
| 1411 | 1371 | ||
| @@ -1438,8 +1398,8 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
| 1438 | } | 1398 | } |
| 1439 | if (!dev->isoc_ep) { | 1399 | if (!dev->isoc_ep) { |
| 1440 | STK_ERROR("Could not find isoc-in endpoint"); | 1400 | STK_ERROR("Could not find isoc-in endpoint"); |
| 1441 | kref_put(&dev->kref, stk_camera_cleanup); | 1401 | err = -ENODEV; |
| 1442 | return -ENODEV; | 1402 | goto error; |
| 1443 | } | 1403 | } |
| 1444 | dev->vsettings.brightness = 0x7fff; | 1404 | dev->vsettings.brightness = 0x7fff; |
| 1445 | dev->vsettings.palette = V4L2_PIX_FMT_RGB565; | 1405 | dev->vsettings.palette = V4L2_PIX_FMT_RGB565; |
| @@ -1453,14 +1413,17 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
| 1453 | 1413 | ||
| 1454 | err = stk_register_video_device(dev); | 1414 | err = stk_register_video_device(dev); |
| 1455 | if (err) { | 1415 | if (err) { |
| 1456 | kref_put(&dev->kref, stk_camera_cleanup); | 1416 | goto error; |
| 1457 | return err; | ||
| 1458 | } | 1417 | } |
| 1459 | 1418 | ||
| 1460 | stk_create_sysfs_files(&dev->vdev); | 1419 | stk_create_sysfs_files(&dev->vdev); |
| 1461 | usb_autopm_enable(dev->interface); | 1420 | usb_autopm_enable(dev->interface); |
| 1462 | 1421 | ||
| 1463 | return 0; | 1422 | return 0; |
| 1423 | |||
| 1424 | error: | ||
| 1425 | kfree(dev); | ||
| 1426 | return err; | ||
| 1464 | } | 1427 | } |
| 1465 | 1428 | ||
| 1466 | static void stk_camera_disconnect(struct usb_interface *interface) | 1429 | static void stk_camera_disconnect(struct usb_interface *interface) |
| @@ -1473,7 +1436,10 @@ static void stk_camera_disconnect(struct usb_interface *interface) | |||
| 1473 | wake_up_interruptible(&dev->wait_frame); | 1436 | wake_up_interruptible(&dev->wait_frame); |
| 1474 | stk_remove_sysfs_files(&dev->vdev); | 1437 | stk_remove_sysfs_files(&dev->vdev); |
| 1475 | 1438 | ||
| 1476 | kref_put(&dev->kref, stk_camera_cleanup); | 1439 | STK_INFO("Syntek USB2.0 Camera release resources" |
| 1440 | "video device /dev/video%d\n", dev->vdev.minor); | ||
| 1441 | |||
| 1442 | video_unregister_device(&dev->vdev); | ||
| 1477 | } | 1443 | } |
| 1478 | 1444 | ||
| 1479 | #ifdef CONFIG_PM | 1445 | #ifdef CONFIG_PM |
diff --git a/drivers/media/video/stk-webcam.h b/drivers/media/video/stk-webcam.h index df4dfefc5327..084a85bdd16e 100644 --- a/drivers/media/video/stk-webcam.h +++ b/drivers/media/video/stk-webcam.h | |||
| @@ -99,7 +99,6 @@ struct stk_camera { | |||
| 99 | 99 | ||
| 100 | u8 isoc_ep; | 100 | u8 isoc_ep; |
| 101 | 101 | ||
| 102 | struct kref kref; | ||
| 103 | /* Not sure if this is right */ | 102 | /* Not sure if this is right */ |
| 104 | atomic_t urbs_used; | 103 | atomic_t urbs_used; |
| 105 | 104 | ||
| @@ -121,7 +120,6 @@ struct stk_camera { | |||
| 121 | unsigned sequence; | 120 | unsigned sequence; |
| 122 | }; | 121 | }; |
| 123 | 122 | ||
| 124 | #define to_stk_camera(d) container_of(d, struct stk_camera, kref) | ||
| 125 | #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) | 123 | #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) |
| 126 | 124 | ||
| 127 | void stk_camera_delete(struct kref *); | 125 | void stk_camera_delete(struct kref *); |
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index 276bded06ab3..bbad54f85c83 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c | |||
| @@ -1882,12 +1882,16 @@ static int saa_open(struct inode *inode, struct file *file) | |||
| 1882 | struct video_device *vdev = video_devdata(file); | 1882 | struct video_device *vdev = video_devdata(file); |
| 1883 | struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev); | 1883 | struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev); |
| 1884 | 1884 | ||
| 1885 | lock_kernel(); | ||
| 1885 | file->private_data = saa; | 1886 | file->private_data = saa; |
| 1886 | 1887 | ||
| 1887 | saa->user++; | 1888 | saa->user++; |
| 1888 | if (saa->user > 1) | 1889 | if (saa->user > 1) { |
| 1890 | unlock_kernel(); | ||
| 1889 | return 0; /* device open already, don't reset */ | 1891 | return 0; /* device open already, don't reset */ |
| 1892 | } | ||
| 1890 | saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ | 1893 | saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ |
| 1894 | unlock_kernel(); | ||
| 1891 | return 0; | 1895 | return 0; |
| 1892 | } | 1896 | } |
| 1893 | 1897 | ||
| @@ -1921,6 +1925,7 @@ static struct video_device saa_template = { | |||
| 1921 | .name = "SAA7146A", | 1925 | .name = "SAA7146A", |
| 1922 | .fops = &saa_fops, | 1926 | .fops = &saa_fops, |
| 1923 | .minor = -1, | 1927 | .minor = -1, |
| 1928 | .release = video_device_release_empty, | ||
| 1924 | }; | 1929 | }; |
| 1925 | 1930 | ||
| 1926 | static int __devinit configure_saa7146(struct pci_dev *pdev, int num) | 1931 | static int __devinit configure_saa7146(struct pci_dev *pdev, int num) |
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index dce947439459..9c549d935994 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c | |||
| @@ -84,7 +84,8 @@ static unsigned int debug; | |||
| 84 | #define PDEBUG(level, fmt, args...) \ | 84 | #define PDEBUG(level, fmt, args...) \ |
| 85 | do { \ | 85 | do { \ |
| 86 | if (debug >= level) \ | 86 | if (debug >= level) \ |
| 87 | info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ | 87 | printk(KERN_INFO KBUILD_MODNAME " [%s:%d] \n" fmt, \ |
| 88 | __func__, __LINE__ , ## args); \ | ||
| 88 | } while (0) | 89 | } while (0) |
| 89 | 90 | ||
| 90 | 91 | ||
| @@ -1086,6 +1087,7 @@ static int stv_open (struct inode *inode, struct file *file) | |||
| 1086 | int err = 0; | 1087 | int err = 0; |
| 1087 | 1088 | ||
| 1088 | /* we are called with the BKL held */ | 1089 | /* we are called with the BKL held */ |
| 1090 | lock_kernel(); | ||
| 1089 | stv680->user = 1; | 1091 | stv680->user = 1; |
| 1090 | err = stv_init (stv680); /* main initialization routine for camera */ | 1092 | err = stv_init (stv680); /* main initialization routine for camera */ |
| 1091 | 1093 | ||
| @@ -1099,6 +1101,7 @@ static int stv_open (struct inode *inode, struct file *file) | |||
| 1099 | } | 1101 | } |
| 1100 | if (err) | 1102 | if (err) |
| 1101 | stv680->user = 0; | 1103 | stv680->user = 0; |
| 1104 | unlock_kernel(); | ||
| 1102 | 1105 | ||
| 1103 | return err; | 1106 | return err; |
| 1104 | } | 1107 | } |
| @@ -1550,7 +1553,8 @@ static int __init usb_stv680_init (void) | |||
| 1550 | } | 1553 | } |
| 1551 | PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION); | 1554 | PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION); |
| 1552 | 1555 | ||
| 1553 | info(DRIVER_DESC " " DRIVER_VERSION); | 1556 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
| 1557 | DRIVER_DESC "\n"); | ||
| 1554 | return 0; | 1558 | return 0; |
| 1555 | } | 1559 | } |
| 1556 | 1560 | ||
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 2437c1a269c5..1c391f0328fd 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | tda9840 - i2c-driver for the tda9840 by SGS Thomson | 2 | tda9840 - i2c-driver for the tda9840 by SGS Thomson |
| 3 | 3 | ||
| 4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> | 4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> |
| 5 | Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> | ||
| 5 | 6 | ||
| 6 | The tda9840 is a stereo/dual sound processor with digital | 7 | The tda9840 is a stereo/dual sound processor with digital |
| 7 | identification. It can be found at address 0x84 on the i2c-bus. | 8 | identification. It can be found at address 0x84 on the i2c-bus. |
| @@ -28,59 +29,118 @@ | |||
| 28 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 29 | #include <linux/ioctl.h> | 30 | #include <linux/ioctl.h> |
| 30 | #include <linux/i2c.h> | 31 | #include <linux/i2c.h> |
| 31 | 32 | #include <media/v4l2-common.h> | |
| 33 | #include <media/v4l2-i2c-drv-legacy.h> | ||
| 32 | #include "tda9840.h" | 34 | #include "tda9840.h" |
| 33 | 35 | ||
| 34 | static int debug; /* insmod parameter */ | 36 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); |
| 37 | MODULE_DESCRIPTION("tda9840 driver"); | ||
| 38 | MODULE_LICENSE("GPL"); | ||
| 39 | |||
| 40 | static int debug; | ||
| 35 | module_param(debug, int, 0644); | 41 | module_param(debug, int, 0644); |
| 36 | MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); | ||
| 37 | 42 | ||
| 38 | #define dprintk(args...) \ | 43 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
| 39 | do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) | ||
| 40 | 44 | ||
| 41 | #define SWITCH 0x00 | 45 | #define SWITCH 0x00 |
| 42 | #define LEVEL_ADJUST 0x02 | 46 | #define LEVEL_ADJUST 0x02 |
| 43 | #define STEREO_ADJUST 0x03 | 47 | #define STEREO_ADJUST 0x03 |
| 44 | #define TEST 0x04 | 48 | #define TEST 0x04 |
| 45 | 49 | ||
| 50 | #define TDA9840_SET_MUTE 0x00 | ||
| 51 | #define TDA9840_SET_MONO 0x10 | ||
| 52 | #define TDA9840_SET_STEREO 0x2a | ||
| 53 | #define TDA9840_SET_LANG1 0x12 | ||
| 54 | #define TDA9840_SET_LANG2 0x1e | ||
| 55 | #define TDA9840_SET_BOTH 0x1a | ||
| 56 | #define TDA9840_SET_BOTH_R 0x16 | ||
| 57 | #define TDA9840_SET_EXTERNAL 0x7a | ||
| 58 | |||
| 46 | /* addresses to scan, found only at 0x42 (7-Bit) */ | 59 | /* addresses to scan, found only at 0x42 (7-Bit) */ |
| 47 | static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; | 60 | static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; |
| 48 | 61 | ||
| 49 | /* magic definition of all other variables and things */ | 62 | /* magic definition of all other variables and things */ |
| 50 | I2C_CLIENT_INSMOD; | 63 | I2C_CLIENT_INSMOD; |
| 51 | 64 | ||
| 52 | static struct i2c_driver driver; | 65 | static void tda9840_write(struct i2c_client *client, u8 reg, u8 val) |
| 53 | static struct i2c_client client_template; | 66 | { |
| 67 | if (i2c_smbus_write_byte_data(client, reg, val)) | ||
| 68 | v4l_dbg(1, debug, client, "error writing %02x to %02x\n", | ||
| 69 | val, reg); | ||
| 70 | } | ||
| 54 | 71 | ||
| 55 | static int command(struct i2c_client *client, unsigned int cmd, void *arg) | 72 | static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) |
| 56 | { | 73 | { |
| 57 | int result; | ||
| 58 | int byte = *(int *)arg; | 74 | int byte = *(int *)arg; |
| 59 | 75 | ||
| 60 | switch (cmd) { | 76 | switch (cmd) { |
| 61 | case TDA9840_SWITCH: | 77 | case VIDIOC_S_TUNER: { |
| 62 | 78 | struct v4l2_tuner *t = arg; | |
| 63 | dprintk("TDA9840_SWITCH: 0x%02x\n", byte); | 79 | int byte; |
| 64 | 80 | ||
| 65 | if (byte != TDA9840_SET_MONO | 81 | if (t->index) |
| 66 | && byte != TDA9840_SET_MUTE | ||
| 67 | && byte != TDA9840_SET_STEREO | ||
| 68 | && byte != TDA9840_SET_LANG1 | ||
| 69 | && byte != TDA9840_SET_LANG2 | ||
| 70 | && byte != TDA9840_SET_BOTH | ||
| 71 | && byte != TDA9840_SET_BOTH_R | ||
| 72 | && byte != TDA9840_SET_EXTERNAL) { | ||
| 73 | return -EINVAL; | 82 | return -EINVAL; |
| 83 | |||
| 84 | switch (t->audmode) { | ||
| 85 | case V4L2_TUNER_MODE_STEREO: | ||
| 86 | byte = TDA9840_SET_STEREO; | ||
| 87 | break; | ||
| 88 | case V4L2_TUNER_MODE_LANG1_LANG2: | ||
| 89 | byte = TDA9840_SET_BOTH; | ||
| 90 | break; | ||
| 91 | case V4L2_TUNER_MODE_LANG1: | ||
| 92 | byte = TDA9840_SET_LANG1; | ||
| 93 | break; | ||
| 94 | case V4L2_TUNER_MODE_LANG2: | ||
| 95 | byte = TDA9840_SET_LANG2; | ||
| 96 | break; | ||
| 97 | default: | ||
| 98 | byte = TDA9840_SET_MONO; | ||
| 99 | break; | ||
| 100 | } | ||
| 101 | v4l_dbg(1, debug, client, "TDA9840_SWITCH: 0x%02x\n", byte); | ||
| 102 | tda9840_write(client, SWITCH, byte); | ||
| 103 | break; | ||
| 104 | } | ||
| 105 | |||
| 106 | case VIDIOC_G_TUNER: { | ||
| 107 | struct v4l2_tuner *t = arg; | ||
| 108 | u8 byte; | ||
| 109 | |||
| 110 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
| 111 | if (1 != i2c_master_recv(client, &byte, 1)) { | ||
| 112 | v4l_dbg(1, debug, client, | ||
| 113 | "i2c_master_recv() failed\n"); | ||
| 114 | return -EIO; | ||
| 74 | } | 115 | } |
| 75 | 116 | ||
| 76 | result = i2c_smbus_write_byte_data(client, SWITCH, byte); | 117 | if (byte & 0x80) { |
| 77 | if (result) | 118 | v4l_dbg(1, debug, client, |
| 78 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); | 119 | "TDA9840_DETECT: register contents invalid\n"); |
| 120 | return -EINVAL; | ||
| 121 | } | ||
| 122 | |||
| 123 | v4l_dbg(1, debug, client, "TDA9840_DETECT: byte: 0x%02x\n", byte); | ||
| 124 | |||
| 125 | switch (byte & 0x60) { | ||
| 126 | case 0x00: | ||
| 127 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
| 128 | break; | ||
| 129 | case 0x20: | ||
| 130 | t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
| 131 | break; | ||
| 132 | case 0x40: | ||
| 133 | t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; | ||
| 134 | break; | ||
| 135 | default: /* Incorrect detect */ | ||
| 136 | t->rxsubchans = V4L2_TUNER_MODE_MONO; | ||
| 137 | break; | ||
| 138 | } | ||
| 79 | break; | 139 | break; |
| 140 | } | ||
| 80 | 141 | ||
| 81 | case TDA9840_LEVEL_ADJUST: | 142 | case TDA9840_LEVEL_ADJUST: |
| 82 | 143 | v4l_dbg(1, debug, client, "TDA9840_LEVEL_ADJUST: %d\n", byte); | |
| 83 | dprintk("TDA9840_LEVEL_ADJUST: %d\n", byte); | ||
| 84 | 144 | ||
| 85 | /* check for correct range */ | 145 | /* check for correct range */ |
| 86 | if (byte > 25 || byte < -20) | 146 | if (byte > 25 || byte < -20) |
| @@ -92,15 +152,11 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
| 92 | byte += 0x8; | 152 | byte += 0x8; |
| 93 | else | 153 | else |
| 94 | byte = -byte; | 154 | byte = -byte; |
| 95 | 155 | tda9840_write(client, LEVEL_ADJUST, byte); | |
| 96 | result = i2c_smbus_write_byte_data(client, LEVEL_ADJUST, byte); | ||
| 97 | if (result) | ||
| 98 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); | ||
| 99 | break; | 156 | break; |
| 100 | 157 | ||
| 101 | case TDA9840_STEREO_ADJUST: | 158 | case TDA9840_STEREO_ADJUST: |
| 102 | 159 | v4l_dbg(1, debug, client, "TDA9840_STEREO_ADJUST: %d\n", byte); | |
| 103 | dprintk("TDA9840_STEREO_ADJUST: %d\n", byte); | ||
| 104 | 160 | ||
| 105 | /* check for correct range */ | 161 | /* check for correct range */ |
| 106 | if (byte > 25 || byte < -24) | 162 | if (byte > 25 || byte < -24) |
| @@ -113,143 +169,59 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
| 113 | else | 169 | else |
| 114 | byte = -byte; | 170 | byte = -byte; |
| 115 | 171 | ||
| 116 | result = i2c_smbus_write_byte_data(client, STEREO_ADJUST, byte); | 172 | tda9840_write(client, STEREO_ADJUST, byte); |
| 117 | if (result) | ||
| 118 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); | ||
| 119 | break; | ||
| 120 | |||
| 121 | case TDA9840_DETECT: { | ||
| 122 | int *ret = (int *)arg; | ||
| 123 | |||
| 124 | byte = i2c_smbus_read_byte_data(client, STEREO_ADJUST); | ||
| 125 | if (byte == -1) { | ||
| 126 | dprintk("i2c_smbus_read_byte_data() failed\n"); | ||
| 127 | return -EIO; | ||
| 128 | } | ||
| 129 | |||
| 130 | if (0 != (byte & 0x80)) { | ||
| 131 | dprintk("TDA9840_DETECT: register contents invalid\n"); | ||
| 132 | return -EINVAL; | ||
| 133 | } | ||
| 134 | |||
| 135 | dprintk("TDA9840_DETECT: byte: 0x%02x\n", byte); | ||
| 136 | *ret = ((byte & 0x60) >> 5); | ||
| 137 | result = 0; | ||
| 138 | break; | ||
| 139 | } | ||
| 140 | case TDA9840_TEST: | ||
| 141 | dprintk("TDA9840_TEST: 0x%02x\n", byte); | ||
| 142 | |||
| 143 | /* mask out irrelevant bits */ | ||
| 144 | byte &= 0x3; | ||
| 145 | |||
| 146 | result = i2c_smbus_write_byte_data(client, TEST, byte); | ||
| 147 | if (result) | ||
| 148 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result); | ||
| 149 | break; | 173 | break; |
| 150 | default: | 174 | default: |
| 151 | return -ENOIOCTLCMD; | 175 | return -ENOIOCTLCMD; |
| 152 | } | 176 | } |
| 153 | 177 | ||
| 154 | if (result) | ||
| 155 | return -EIO; | ||
| 156 | |||
| 157 | return 0; | 178 | return 0; |
| 158 | } | 179 | } |
| 159 | 180 | ||
| 160 | static int detect(struct i2c_adapter *adapter, int address, int kind) | 181 | static int tda9840_probe(struct i2c_client *client, |
| 182 | const struct i2c_device_id *id) | ||
| 161 | { | 183 | { |
| 162 | struct i2c_client *client; | 184 | int result; |
| 163 | int result = 0; | 185 | int byte; |
| 164 | |||
| 165 | int byte = 0x0; | ||
| 166 | 186 | ||
| 167 | /* let's see whether this adapter can support what we need */ | 187 | /* let's see whether this adapter can support what we need */ |
| 168 | if (0 == i2c_check_functionality(adapter, | 188 | if (!i2c_check_functionality(client->adapter, |
| 169 | I2C_FUNC_SMBUS_READ_BYTE_DATA | | 189 | I2C_FUNC_SMBUS_READ_BYTE_DATA | |
| 170 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { | 190 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) |
| 171 | return 0; | 191 | return 0; |
| 172 | } | ||
| 173 | |||
| 174 | /* allocate memory for client structure */ | ||
| 175 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
| 176 | if (!client) { | ||
| 177 | printk("not enough kernel memory\n"); | ||
| 178 | return -ENOMEM; | ||
| 179 | } | ||
| 180 | |||
| 181 | /* fill client structure */ | ||
| 182 | memcpy(client, &client_template, sizeof(struct i2c_client)); | ||
| 183 | client->addr = address; | ||
| 184 | client->adapter = adapter; | ||
| 185 | 192 | ||
| 186 | /* tell the i2c layer a new client has arrived */ | 193 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
| 187 | if (0 != (result = i2c_attach_client(client))) { | 194 | client->addr << 1, client->adapter->name); |
| 188 | kfree(client); | ||
| 189 | return result; | ||
| 190 | } | ||
| 191 | 195 | ||
| 192 | /* set initial values for level & stereo - adjustment, mode */ | 196 | /* set initial values for level & stereo - adjustment, mode */ |
| 193 | byte = 0; | 197 | byte = 0; |
| 194 | result = command(client, TDA9840_LEVEL_ADJUST, &byte); | 198 | result = tda9840_command(client, TDA9840_LEVEL_ADJUST, &byte); |
| 195 | result += command(client, TDA9840_STEREO_ADJUST, &byte); | 199 | result += tda9840_command(client, TDA9840_STEREO_ADJUST, &byte); |
| 196 | byte = TDA9840_SET_MONO; | 200 | tda9840_write(client, SWITCH, TDA9840_SET_STEREO); |
| 197 | result = command(client, TDA9840_SWITCH, &byte); | ||
| 198 | if (result) { | 201 | if (result) { |
| 199 | dprintk("could not initialize tda9840\n"); | 202 | v4l_dbg(1, debug, client, "could not initialize tda9840\n"); |
| 200 | return -ENODEV; | 203 | return -ENODEV; |
| 201 | } | 204 | } |
| 202 | |||
| 203 | printk("tda9840: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); | ||
| 204 | return 0; | 205 | return 0; |
| 205 | } | 206 | } |
| 206 | 207 | ||
| 207 | static int attach(struct i2c_adapter *adapter) | 208 | static int tda9840_legacy_probe(struct i2c_adapter *adapter) |
| 208 | { | ||
| 209 | /* let's see whether this is a know adapter we can attach to */ | ||
| 210 | if (adapter->id != I2C_HW_SAA7146) { | ||
| 211 | dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); | ||
| 212 | return -ENODEV; | ||
| 213 | } | ||
| 214 | |||
| 215 | return i2c_probe(adapter, &addr_data, &detect); | ||
| 216 | } | ||
| 217 | |||
| 218 | static int detach(struct i2c_client *client) | ||
| 219 | { | 209 | { |
| 220 | int ret = i2c_detach_client(client); | 210 | /* Let's see whether this is a known adapter we can attach to. |
| 221 | kfree(client); | 211 | Prevents conflicts with tvaudio.c. */ |
| 222 | return ret; | 212 | return adapter->id == I2C_HW_SAA7146; |
| 223 | } | 213 | } |
| 224 | 214 | static const struct i2c_device_id tda9840_id[] = { | |
| 225 | static struct i2c_driver driver = { | 215 | { "tda9840", 0 }, |
| 226 | .driver = { | 216 | { } |
| 227 | .name = "tda9840", | ||
| 228 | }, | ||
| 229 | .id = I2C_DRIVERID_TDA9840, | ||
| 230 | .attach_adapter = attach, | ||
| 231 | .detach_client = detach, | ||
| 232 | .command = command, | ||
| 233 | }; | 217 | }; |
| 218 | MODULE_DEVICE_TABLE(i2c, tda9840_id); | ||
| 234 | 219 | ||
| 235 | static struct i2c_client client_template = { | 220 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
| 236 | .name = "tda9840", | 221 | .name = "tda9840", |
| 237 | .driver = &driver, | 222 | .driverid = I2C_DRIVERID_TDA9840, |
| 223 | .command = tda9840_command, | ||
| 224 | .probe = tda9840_probe, | ||
| 225 | .legacy_probe = tda9840_legacy_probe, | ||
| 226 | .id_table = tda9840_id, | ||
| 238 | }; | 227 | }; |
| 239 | |||
| 240 | static int __init this_module_init(void) | ||
| 241 | { | ||
| 242 | return i2c_add_driver(&driver); | ||
| 243 | } | ||
| 244 | |||
| 245 | static void __exit this_module_exit(void) | ||
| 246 | { | ||
| 247 | i2c_del_driver(&driver); | ||
| 248 | } | ||
| 249 | |||
| 250 | module_init(this_module_init); | ||
| 251 | module_exit(this_module_exit); | ||
| 252 | |||
| 253 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); | ||
| 254 | MODULE_DESCRIPTION("tda9840 driver"); | ||
| 255 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/tda9840.h b/drivers/media/video/tda9840.h index 7da8432cdca7..dc12ae7caf6f 100644 --- a/drivers/media/video/tda9840.h +++ b/drivers/media/video/tda9840.h | |||
| @@ -3,24 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | #define I2C_ADDR_TDA9840 0x42 | 4 | #define I2C_ADDR_TDA9840 0x42 |
| 5 | 5 | ||
| 6 | #define TDA9840_DETECT _IOR('v',1,int) | ||
| 7 | /* return values for TDA9840_DETCT */ | ||
| 8 | #define TDA9840_MONO_DETECT 0x0 | ||
| 9 | #define TDA9840_DUAL_DETECT 0x1 | ||
| 10 | #define TDA9840_STEREO_DETECT 0x2 | ||
| 11 | #define TDA9840_INCORRECT_DETECT 0x3 | ||
| 12 | |||
| 13 | #define TDA9840_SWITCH _IOW('v',2,int) | ||
| 14 | /* modes than can be set with TDA9840_SWITCH */ | ||
| 15 | #define TDA9840_SET_MUTE 0x00 | ||
| 16 | #define TDA9840_SET_MONO 0x10 | ||
| 17 | #define TDA9840_SET_STEREO 0x2a | ||
| 18 | #define TDA9840_SET_LANG1 0x12 | ||
| 19 | #define TDA9840_SET_LANG2 0x1e | ||
| 20 | #define TDA9840_SET_BOTH 0x1a | ||
| 21 | #define TDA9840_SET_BOTH_R 0x16 | ||
| 22 | #define TDA9840_SET_EXTERNAL 0x7a | ||
| 23 | |||
| 24 | /* values may range between +2.5 and -2.0; | 6 | /* values may range between +2.5 and -2.0; |
| 25 | the value has to be multiplied with 10 */ | 7 | the value has to be multiplied with 10 */ |
| 26 | #define TDA9840_LEVEL_ADJUST _IOW('v',3,int) | 8 | #define TDA9840_LEVEL_ADJUST _IOW('v',3,int) |
| @@ -29,7 +11,4 @@ | |||
| 29 | the value has to be multiplied with 10 */ | 11 | the value has to be multiplied with 10 */ |
| 30 | #define TDA9840_STEREO_ADJUST _IOW('v',4,int) | 12 | #define TDA9840_STEREO_ADJUST _IOW('v',4,int) |
| 31 | 13 | ||
| 32 | /* currently not implemented */ | ||
| 33 | #define TDA9840_TEST _IOW('v',5,int) | ||
| 34 | |||
| 35 | #endif | 14 | #endif |
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index 421c1445e96c..cde092adbb5a 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | tea6415c - i2c-driver for the tea6415c by SGS Thomson | 2 | tea6415c - i2c-driver for the tea6415c by SGS Thomson |
| 3 | 3 | ||
| 4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> | 4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> |
| 5 | Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> | ||
| 5 | 6 | ||
| 6 | The tea6415c is a bus controlled video-matrix-switch | 7 | The tea6415c is a bus controlled video-matrix-switch |
| 7 | with 8 inputs and 6 outputs. | 8 | with 8 inputs and 6 outputs. |
| @@ -30,18 +31,18 @@ | |||
| 30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 31 | #include <linux/ioctl.h> | 32 | #include <linux/ioctl.h> |
| 32 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
| 33 | 34 | #include <media/v4l2-common.h> | |
| 35 | #include <media/v4l2-i2c-drv-legacy.h> | ||
| 34 | #include "tea6415c.h" | 36 | #include "tea6415c.h" |
| 35 | 37 | ||
| 36 | static int debug; /* insmod parameter */ | 38 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); |
| 37 | module_param(debug, int, 0644); | 39 | MODULE_DESCRIPTION("tea6415c driver"); |
| 38 | MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); | 40 | MODULE_LICENSE("GPL"); |
| 39 | 41 | ||
| 40 | #define dprintk(args...) \ | 42 | static int debug; |
| 41 | do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) | 43 | module_param(debug, int, 0644); |
| 42 | 44 | ||
| 43 | #define TEA6415C_NUM_INPUTS 8 | 45 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
| 44 | #define TEA6415C_NUM_OUTPUTS 6 | ||
| 45 | 46 | ||
| 46 | /* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */ | 47 | /* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */ |
| 47 | static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END }; | 48 | static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END }; |
| @@ -49,60 +50,6 @@ static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIEN | |||
| 49 | /* magic definition of all other variables and things */ | 50 | /* magic definition of all other variables and things */ |
| 50 | I2C_CLIENT_INSMOD; | 51 | I2C_CLIENT_INSMOD; |
| 51 | 52 | ||
| 52 | static struct i2c_driver driver; | ||
| 53 | static struct i2c_client client_template; | ||
| 54 | |||
| 55 | /* this function is called by i2c_probe */ | ||
| 56 | static int detect(struct i2c_adapter *adapter, int address, int kind) | ||
| 57 | { | ||
| 58 | struct i2c_client *client = NULL; | ||
| 59 | int err = 0; | ||
| 60 | |||
| 61 | /* let's see whether this adapter can support what we need */ | ||
| 62 | if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) { | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | /* allocate memory for client structure */ | ||
| 67 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
| 68 | if (!client) { | ||
| 69 | return -ENOMEM; | ||
| 70 | } | ||
| 71 | |||
| 72 | /* fill client structure */ | ||
| 73 | memcpy(client, &client_template, sizeof(struct i2c_client)); | ||
| 74 | client->addr = address; | ||
| 75 | client->adapter = adapter; | ||
| 76 | |||
| 77 | /* tell the i2c layer a new client has arrived */ | ||
| 78 | if (0 != (err = i2c_attach_client(client))) { | ||
| 79 | kfree(client); | ||
| 80 | return err; | ||
| 81 | } | ||
| 82 | |||
| 83 | printk("tea6415c: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); | ||
| 84 | |||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | static int attach(struct i2c_adapter *adapter) | ||
| 89 | { | ||
| 90 | /* let's see whether this is a know adapter we can attach to */ | ||
| 91 | if (adapter->id != I2C_HW_SAA7146) { | ||
| 92 | dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); | ||
| 93 | return -ENODEV; | ||
| 94 | } | ||
| 95 | |||
| 96 | return i2c_probe(adapter, &addr_data, &detect); | ||
| 97 | } | ||
| 98 | |||
| 99 | static int detach(struct i2c_client *client) | ||
| 100 | { | ||
| 101 | int ret = i2c_detach_client(client); | ||
| 102 | kfree(client); | ||
| 103 | return ret; | ||
| 104 | } | ||
| 105 | |||
| 106 | /* makes a connection between the input-pin 'i' and the output-pin 'o' | 53 | /* makes a connection between the input-pin 'i' and the output-pin 'o' |
| 107 | for the tea6415c-client 'client' */ | 54 | for the tea6415c-client 'client' */ |
| 108 | static int switch_matrix(struct i2c_client *client, int i, int o) | 55 | static int switch_matrix(struct i2c_client *client, int i, int o) |
| @@ -110,7 +57,7 @@ static int switch_matrix(struct i2c_client *client, int i, int o) | |||
| 110 | u8 byte = 0; | 57 | u8 byte = 0; |
| 111 | int ret; | 58 | int ret; |
| 112 | 59 | ||
| 113 | dprintk("adr:0x%02x, i:%d, o:%d\n", client->addr, i, o); | 60 | v4l_dbg(1, debug, client, "i=%d, o=%d\n", i, o); |
| 114 | 61 | ||
| 115 | /* check if the pins are valid */ | 62 | /* check if the pins are valid */ |
| 116 | if (0 == ((1 == i || 3 == i || 5 == i || 6 == i || 8 == i || 10 == i || 20 == i || 11 == i) | 63 | if (0 == ((1 == i || 3 == i || 5 == i || 6 == i || 8 == i || 10 == i || 20 == i || 11 == i) |
| @@ -168,14 +115,14 @@ static int switch_matrix(struct i2c_client *client, int i, int o) | |||
| 168 | 115 | ||
| 169 | ret = i2c_smbus_write_byte(client, byte); | 116 | ret = i2c_smbus_write_byte(client, byte); |
| 170 | if (ret) { | 117 | if (ret) { |
| 171 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret); | 118 | v4l_dbg(1, debug, client, |
| 119 | "i2c_smbus_write_byte() failed, ret:%d\n", ret); | ||
| 172 | return -EIO; | 120 | return -EIO; |
| 173 | } | 121 | } |
| 174 | |||
| 175 | return ret; | 122 | return ret; |
| 176 | } | 123 | } |
| 177 | 124 | ||
| 178 | static int command(struct i2c_client *client, unsigned int cmd, void *arg) | 125 | static int tea6415c_command(struct i2c_client *client, unsigned cmd, void *arg) |
| 179 | { | 126 | { |
| 180 | struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg; | 127 | struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg; |
| 181 | int result = 0; | 128 | int result = 0; |
| @@ -187,38 +134,40 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
| 187 | default: | 134 | default: |
| 188 | return -ENOIOCTLCMD; | 135 | return -ENOIOCTLCMD; |
| 189 | } | 136 | } |
| 190 | |||
| 191 | return result; | 137 | return result; |
| 192 | } | 138 | } |
| 193 | 139 | ||
| 194 | static struct i2c_driver driver = { | 140 | /* this function is called by i2c_probe */ |
| 195 | .driver = { | 141 | static int tea6415c_probe(struct i2c_client *client, |
| 196 | .name = "tea6415c", | 142 | const struct i2c_device_id *id) |
| 197 | }, | ||
| 198 | .id = I2C_DRIVERID_TEA6415C, | ||
| 199 | .attach_adapter = attach, | ||
| 200 | .detach_client = detach, | ||
| 201 | .command = command, | ||
| 202 | }; | ||
| 203 | |||
| 204 | static struct i2c_client client_template = { | ||
| 205 | .name = "tea6415c", | ||
| 206 | .driver = &driver, | ||
| 207 | }; | ||
| 208 | |||
| 209 | static int __init this_module_init(void) | ||
| 210 | { | 143 | { |
| 211 | return i2c_add_driver(&driver); | 144 | /* let's see whether this adapter can support what we need */ |
| 145 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) | ||
| 146 | return 0; | ||
| 147 | |||
| 148 | v4l_info(client, "chip found @ 0x%x (%s)\n", | ||
| 149 | client->addr << 1, client->adapter->name); | ||
| 150 | return 0; | ||
| 212 | } | 151 | } |
| 213 | 152 | ||
| 214 | static void __exit this_module_exit(void) | 153 | static int tea6415c_legacy_probe(struct i2c_adapter *adapter) |
| 215 | { | 154 | { |
| 216 | i2c_del_driver(&driver); | 155 | /* Let's see whether this is a known adapter we can attach to. |
| 156 | Prevents conflicts with tvaudio.c. */ | ||
| 157 | return adapter->id == I2C_HW_SAA7146; | ||
| 217 | } | 158 | } |
| 218 | 159 | ||
| 219 | module_init(this_module_init); | 160 | static const struct i2c_device_id tea6415c_id[] = { |
| 220 | module_exit(this_module_exit); | 161 | { "tea6415c", 0 }, |
| 162 | { } | ||
| 163 | }; | ||
| 164 | MODULE_DEVICE_TABLE(i2c, tea6415c_id); | ||
| 221 | 165 | ||
| 222 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); | 166 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
| 223 | MODULE_DESCRIPTION("tea6415c driver"); | 167 | .name = "tea6415c", |
| 224 | MODULE_LICENSE("GPL"); | 168 | .driverid = I2C_DRIVERID_TEA6415C, |
| 169 | .command = tea6415c_command, | ||
| 170 | .probe = tea6415c_probe, | ||
| 171 | .legacy_probe = tea6415c_legacy_probe, | ||
| 172 | .id_table = tea6415c_id, | ||
| 173 | }; | ||
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index b5c8957d130e..e50820969e64 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | tea6420 - i2c-driver for the tea6420 by SGS Thomson | 2 | tea6420 - i2c-driver for the tea6420 by SGS Thomson |
| 3 | 3 | ||
| 4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> | 4 | Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de> |
| 5 | Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> | ||
| 5 | 6 | ||
| 6 | The tea6420 is a bus controlled audio-matrix with 5 stereo inputs, | 7 | The tea6420 is a bus controlled audio-matrix with 5 stereo inputs, |
| 7 | 4 stereo outputs and gain control for each output. | 8 | 4 stereo outputs and gain control for each output. |
| @@ -30,15 +31,18 @@ | |||
| 30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 31 | #include <linux/ioctl.h> | 32 | #include <linux/ioctl.h> |
| 32 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
| 33 | 34 | #include <media/v4l2-common.h> | |
| 35 | #include <media/v4l2-i2c-drv-legacy.h> | ||
| 34 | #include "tea6420.h" | 36 | #include "tea6420.h" |
| 35 | 37 | ||
| 36 | static int debug; /* insmod parameter */ | 38 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); |
| 39 | MODULE_DESCRIPTION("tea6420 driver"); | ||
| 40 | MODULE_LICENSE("GPL"); | ||
| 41 | |||
| 42 | static int debug; | ||
| 37 | module_param(debug, int, 0644); | 43 | module_param(debug, int, 0644); |
| 38 | MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); | ||
| 39 | 44 | ||
| 40 | #define dprintk(args...) \ | 45 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
| 41 | do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) | ||
| 42 | 46 | ||
| 43 | /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ | 47 | /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ |
| 44 | static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END }; | 48 | static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END }; |
| @@ -46,23 +50,20 @@ static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I | |||
| 46 | /* magic definition of all other variables and things */ | 50 | /* magic definition of all other variables and things */ |
| 47 | I2C_CLIENT_INSMOD; | 51 | I2C_CLIENT_INSMOD; |
| 48 | 52 | ||
| 49 | static struct i2c_driver driver; | ||
| 50 | static struct i2c_client client_template; | ||
| 51 | |||
| 52 | /* make a connection between the input 'i' and the output 'o' | 53 | /* make a connection between the input 'i' and the output 'o' |
| 53 | with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */ | 54 | with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */ |
| 54 | static int tea6420_switch(struct i2c_client *client, int i, int o, int g) | 55 | static int tea6420_switch(struct i2c_client *client, int i, int o, int g) |
| 55 | { | 56 | { |
| 56 | u8 byte = 0; | 57 | u8 byte; |
| 57 | int ret; | 58 | int ret; |
| 58 | 59 | ||
| 59 | dprintk("adr:0x%02x, i:%d, o:%d, g:%d\n", client->addr, i, o, g); | 60 | v4l_dbg(1, debug, client, "i=%d, o=%d, g=%d\n", i, o, g); |
| 60 | 61 | ||
| 61 | /* check if the parameters are valid */ | 62 | /* check if the parameters are valid */ |
| 62 | if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0) | 63 | if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0) |
| 63 | return -1; | 64 | return -1; |
| 64 | 65 | ||
| 65 | byte = ((o - 1) << 5); | 66 | byte = ((o - 1) << 5); |
| 66 | byte |= (i - 1); | 67 | byte |= (i - 1); |
| 67 | 68 | ||
| 68 | /* to understand this, have a look at the tea6420-specs (p.5) */ | 69 | /* to understand this, have a look at the tea6420-specs (p.5) */ |
| @@ -82,40 +83,41 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) | |||
| 82 | 83 | ||
| 83 | ret = i2c_smbus_write_byte(client, byte); | 84 | ret = i2c_smbus_write_byte(client, byte); |
| 84 | if (ret) { | 85 | if (ret) { |
| 85 | dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret); | 86 | v4l_dbg(1, debug, client, |
| 87 | "i2c_smbus_write_byte() failed, ret:%d\n", ret); | ||
| 86 | return -EIO; | 88 | return -EIO; |
| 87 | } | 89 | } |
| 88 | |||
| 89 | return 0; | 90 | return 0; |
| 90 | } | 91 | } |
| 91 | 92 | ||
| 92 | /* this function is called by i2c_probe */ | 93 | static int tea6420_command(struct i2c_client *client, unsigned cmd, void *arg) |
| 93 | static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind) | ||
| 94 | { | 94 | { |
| 95 | struct i2c_client *client; | 95 | struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; |
| 96 | int err = 0, i = 0; | 96 | int result = 0; |
| 97 | 97 | ||
| 98 | /* let's see whether this adapter can support what we need */ | 98 | switch (cmd) { |
| 99 | if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) { | 99 | case TEA6420_SWITCH: |
| 100 | return 0; | 100 | result = tea6420_switch(client, a->in, a->out, a->gain); |
| 101 | break; | ||
| 102 | default: | ||
| 103 | return -ENOIOCTLCMD; | ||
| 101 | } | 104 | } |
| 102 | 105 | ||
| 103 | /* allocate memory for client structure */ | 106 | return result; |
| 104 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | 107 | } |
| 105 | if (!client) { | ||
| 106 | return -ENOMEM; | ||
| 107 | } | ||
| 108 | 108 | ||
| 109 | /* fill client structure */ | 109 | /* this function is called by i2c_probe */ |
| 110 | memcpy(client, &client_template, sizeof(struct i2c_client)); | 110 | static int tea6420_probe(struct i2c_client *client, |
| 111 | client->addr = address; | 111 | const struct i2c_device_id *id) |
| 112 | client->adapter = adapter; | 112 | { |
| 113 | int err, i; | ||
| 113 | 114 | ||
| 114 | /* tell the i2c layer a new client has arrived */ | 115 | /* let's see whether this adapter can support what we need */ |
| 115 | if (0 != (err = i2c_attach_client(client))) { | 116 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) |
| 116 | kfree(client); | 117 | return -EIO; |
| 117 | return err; | 118 | |
| 118 | } | 119 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
| 120 | client->addr << 1, client->adapter->name); | ||
| 119 | 121 | ||
| 120 | /* set initial values: set "mute"-input to all outputs at gain 0 */ | 122 | /* set initial values: set "mute"-input to all outputs at gain 0 */ |
| 121 | err = 0; | 123 | err = 0; |
| @@ -123,78 +125,31 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 123 | err += tea6420_switch(client, 6, i, 0); | 125 | err += tea6420_switch(client, 6, i, 0); |
| 124 | } | 126 | } |
| 125 | if (err) { | 127 | if (err) { |
| 126 | dprintk("could not initialize tea6420\n"); | 128 | v4l_dbg(1, debug, client, "could not initialize tea6420\n"); |
| 127 | kfree(client); | 129 | kfree(client); |
| 128 | return -ENODEV; | 130 | return -ENODEV; |
| 129 | } | 131 | } |
| 130 | |||
| 131 | printk("tea6420: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]); | ||
| 132 | |||
| 133 | return 0; | 132 | return 0; |
| 134 | } | 133 | } |
| 135 | 134 | ||
| 136 | static int attach(struct i2c_adapter *adapter) | 135 | static int tea6420_legacy_probe(struct i2c_adapter *adapter) |
| 137 | { | 136 | { |
| 138 | /* let's see whether this is a know adapter we can attach to */ | 137 | /* Let's see whether this is a known adapter we can attach to. |
| 139 | if (adapter->id != I2C_HW_SAA7146) { | 138 | Prevents conflicts with tvaudio.c. */ |
| 140 | dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id); | 139 | return adapter->id == I2C_HW_SAA7146; |
| 141 | return -ENODEV; | ||
| 142 | } | ||
| 143 | |||
| 144 | return i2c_probe(adapter, &addr_data, &tea6420_detect); | ||
| 145 | } | ||
| 146 | |||
| 147 | static int detach(struct i2c_client *client) | ||
| 148 | { | ||
| 149 | int ret = i2c_detach_client(client); | ||
| 150 | kfree(client); | ||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | static int command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
| 155 | { | ||
| 156 | struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; | ||
| 157 | int result = 0; | ||
| 158 | |||
| 159 | switch (cmd) { | ||
| 160 | case TEA6420_SWITCH: | ||
| 161 | result = tea6420_switch(client, a->in, a->out, a->gain); | ||
| 162 | break; | ||
| 163 | default: | ||
| 164 | return -ENOIOCTLCMD; | ||
| 165 | } | ||
| 166 | |||
| 167 | return result; | ||
| 168 | } | 140 | } |
| 169 | 141 | ||
| 170 | static struct i2c_driver driver = { | 142 | static const struct i2c_device_id tea6420_id[] = { |
| 171 | .driver = { | 143 | { "tea6420", 0 }, |
| 172 | .name = "tea6420", | 144 | { } |
| 173 | }, | ||
| 174 | .id = I2C_DRIVERID_TEA6420, | ||
| 175 | .attach_adapter = attach, | ||
| 176 | .detach_client = detach, | ||
| 177 | .command = command, | ||
| 178 | }; | 145 | }; |
| 146 | MODULE_DEVICE_TABLE(i2c, tea6420_id); | ||
| 179 | 147 | ||
| 180 | static struct i2c_client client_template = { | 148 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
| 181 | .name = "tea6420", | 149 | .name = "tea6420", |
| 182 | .driver = &driver, | 150 | .driverid = I2C_DRIVERID_TEA6420, |
| 151 | .command = tea6420_command, | ||
| 152 | .probe = tea6420_probe, | ||
| 153 | .legacy_probe = tea6420_legacy_probe, | ||
| 154 | .id_table = tea6420_id, | ||
| 183 | }; | 155 | }; |
| 184 | |||
| 185 | static int __init this_module_init(void) | ||
| 186 | { | ||
| 187 | return i2c_add_driver(&driver); | ||
| 188 | } | ||
| 189 | |||
| 190 | static void __exit this_module_exit(void) | ||
| 191 | { | ||
| 192 | i2c_del_driver(&driver); | ||
| 193 | } | ||
| 194 | |||
| 195 | module_init(this_module_init); | ||
| 196 | module_exit(this_module_exit); | ||
| 197 | |||
| 198 | MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); | ||
| 199 | MODULE_DESCRIPTION("tea6420 driver"); | ||
| 200 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c deleted file mode 100644 index bdf506e6ae27..000000000000 --- a/drivers/media/video/tuner-3036.c +++ /dev/null | |||
| @@ -1,214 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Philips SAB3036 "CITAC" tuner control chip. | ||
| 3 | * | ||
| 4 | * Author: Phil Blundell <philb@gnu.org> | ||
| 5 | * | ||
| 6 | * The SAB3036 is just about different enough from the chips that | ||
| 7 | * tuner.c copes with to make it not worth the effort to crowbar | ||
| 8 | * the support into that file. So instead we have a separate driver. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version | ||
| 13 | * 2 of the License, or (at your option) any later version. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/sched.h> | ||
| 19 | #include <linux/string.h> | ||
| 20 | #include <linux/timer.h> | ||
| 21 | #include <linux/delay.h> | ||
| 22 | #include <linux/errno.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | |||
| 26 | #include <linux/i2c.h> | ||
| 27 | #include <linux/videodev.h> | ||
| 28 | #include <media/v4l2-common.h> | ||
| 29 | |||
| 30 | #include <media/tuner.h> | ||
| 31 | |||
| 32 | static int debug; /* insmod parameter */ | ||
| 33 | static int this_adap; | ||
| 34 | |||
| 35 | static struct i2c_client client_template; | ||
| 36 | |||
| 37 | /* Addresses to scan */ | ||
| 38 | static unsigned short normal_i2c[] = { 0x60, 0x61, I2C_CLIENT_END }; | ||
| 39 | static unsigned short ignore = I2C_CLIENT_END; | ||
| 40 | |||
| 41 | static struct i2c_client_address_data addr_data = { | ||
| 42 | .normal_i2c = normal_i2c, | ||
| 43 | .probe = &ignore, | ||
| 44 | .ignore = &ignore, | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* ---------------------------------------------------------------------- */ | ||
| 48 | |||
| 49 | static unsigned char | ||
| 50 | tuner_getstatus (struct i2c_client *c) | ||
| 51 | { | ||
| 52 | unsigned char byte; | ||
| 53 | if (i2c_master_recv(c, &byte, 1) != 1) | ||
| 54 | printk(KERN_ERR "tuner-3036: I/O error.\n"); | ||
| 55 | return byte; | ||
| 56 | } | ||
| 57 | |||
| 58 | #define TUNER_FL 0x80 | ||
| 59 | |||
| 60 | static int | ||
| 61 | tuner_islocked (struct i2c_client *c) | ||
| 62 | { | ||
| 63 | return (tuner_getstatus(c) & TUNER_FL); | ||
| 64 | } | ||
| 65 | |||
| 66 | /* ---------------------------------------------------------------------- */ | ||
| 67 | |||
| 68 | static void | ||
| 69 | set_tv_freq(struct i2c_client *c, int freq) | ||
| 70 | { | ||
| 71 | u16 div = ((freq * 20) / 16); | ||
| 72 | unsigned long give_up = jiffies + HZ; | ||
| 73 | unsigned char buffer[2]; | ||
| 74 | |||
| 75 | if (debug) | ||
| 76 | printk(KERN_DEBUG "tuner: setting frequency %dMHz, divisor %x\n", freq / 16, div); | ||
| 77 | |||
| 78 | /* Select high tuning current */ | ||
| 79 | buffer[0] = 0x29; | ||
| 80 | buffer[1] = 0x3e; | ||
| 81 | |||
| 82 | if (i2c_master_send(c, buffer, 2) != 2) | ||
| 83 | printk("tuner: i2c i/o error 1\n"); | ||
| 84 | |||
| 85 | buffer[0] = 0x80 | ((div>>8) & 0x7f); | ||
| 86 | buffer[1] = div & 0xff; | ||
| 87 | |||
| 88 | if (i2c_master_send(c, buffer, 2) != 2) | ||
| 89 | printk("tuner: i2c i/o error 2\n"); | ||
| 90 | |||
| 91 | while (!tuner_islocked(c) && time_before(jiffies, give_up)) | ||
| 92 | schedule(); | ||
| 93 | |||
| 94 | if (!tuner_islocked(c)) | ||
| 95 | printk(KERN_WARNING "tuner: failed to achieve PLL lock\n"); | ||
| 96 | |||
| 97 | /* Select low tuning current and engage AFC */ | ||
| 98 | buffer[0] = 0x29; | ||
| 99 | buffer[1] = 0xb2; | ||
| 100 | |||
| 101 | if (i2c_master_send(c, buffer, 2) != 2) | ||
| 102 | printk("tuner: i2c i/o error 3\n"); | ||
| 103 | |||
| 104 | if (debug) | ||
| 105 | printk(KERN_DEBUG "tuner: status %02x\n", tuner_getstatus(c)); | ||
| 106 | } | ||
| 107 | |||
| 108 | /* ---------------------------------------------------------------------- */ | ||
| 109 | |||
| 110 | static int | ||
| 111 | tuner_attach(struct i2c_adapter *adap, int addr, int kind) | ||
| 112 | { | ||
| 113 | static unsigned char buffer[] = { 0x29, 0x32, 0x2a, 0, 0x2b, 0 }; | ||
| 114 | |||
| 115 | struct i2c_client *client; | ||
| 116 | |||
| 117 | if (this_adap > 0) | ||
| 118 | return -1; | ||
| 119 | this_adap++; | ||
| 120 | |||
| 121 | client_template.adapter = adap; | ||
| 122 | client_template.addr = addr; | ||
| 123 | |||
| 124 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
| 125 | if (client == NULL) | ||
| 126 | return -ENOMEM; | ||
| 127 | memcpy(client, &client_template, sizeof(struct i2c_client)); | ||
| 128 | |||
| 129 | printk("tuner: SAB3036 found, status %02x\n", tuner_getstatus(client)); | ||
| 130 | |||
| 131 | i2c_attach_client(client); | ||
| 132 | |||
| 133 | if (i2c_master_send(client, buffer, 2) != 2) | ||
| 134 | printk("tuner: i2c i/o error 1\n"); | ||
| 135 | if (i2c_master_send(client, buffer+2, 2) != 2) | ||
| 136 | printk("tuner: i2c i/o error 2\n"); | ||
| 137 | if (i2c_master_send(client, buffer+4, 2) != 2) | ||
| 138 | printk("tuner: i2c i/o error 3\n"); | ||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | static int | ||
| 143 | tuner_detach(struct i2c_client *c) | ||
| 144 | { | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int | ||
| 149 | tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
| 150 | { | ||
| 151 | int *iarg = (int*)arg; | ||
| 152 | |||
| 153 | switch (cmd) | ||
| 154 | { | ||
| 155 | case VIDIOCSFREQ: | ||
| 156 | set_tv_freq(client, *iarg); | ||
| 157 | break; | ||
| 158 | |||
| 159 | default: | ||
| 160 | return -EINVAL; | ||
| 161 | } | ||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int | ||
| 166 | tuner_probe(struct i2c_adapter *adap) | ||
| 167 | { | ||
| 168 | this_adap = 0; | ||
| 169 | if (adap->id == I2C_HW_B_LP) | ||
| 170 | return i2c_probe(adap, &addr_data, tuner_attach); | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | /* ----------------------------------------------------------------------- */ | ||
| 175 | |||
| 176 | static struct i2c_driver | ||
| 177 | i2c_driver_tuner = | ||
| 178 | { | ||
| 179 | .driver = { | ||
| 180 | .name = "sab3036", | ||
| 181 | }, | ||
| 182 | .id = I2C_DRIVERID_SAB3036, | ||
| 183 | .attach_adapter = tuner_probe, | ||
| 184 | .detach_client = tuner_detach, | ||
| 185 | .command = tuner_command | ||
| 186 | }; | ||
| 187 | |||
| 188 | static struct i2c_client client_template = | ||
| 189 | { | ||
| 190 | .driver = &i2c_driver_tuner, | ||
| 191 | .name = "SAB3036", | ||
| 192 | }; | ||
| 193 | |||
| 194 | static int __init | ||
| 195 | tuner3036_init(void) | ||
| 196 | { | ||
| 197 | return i2c_add_driver(&i2c_driver_tuner); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void __exit | ||
| 201 | tuner3036_exit(void) | ||
| 202 | { | ||
| 203 | i2c_del_driver(&i2c_driver_tuner); | ||
| 204 | } | ||
| 205 | |||
| 206 | MODULE_DESCRIPTION("SAB3036 tuner driver"); | ||
| 207 | MODULE_AUTHOR("Philip Blundell <philb@gnu.org>"); | ||
| 208 | MODULE_LICENSE("GPL"); | ||
| 209 | |||
| 210 | module_param(debug, int, 0); | ||
| 211 | MODULE_PARM_DESC(debug,"Enable debugging output"); | ||
| 212 | |||
| 213 | module_init(tuner3036_init); | ||
| 214 | module_exit(tuner3036_exit); | ||
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index d806a3556eed..4a7735c6c1a6 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
| @@ -92,7 +92,6 @@ struct tuner { | |||
| 92 | 92 | ||
| 93 | unsigned int type; /* chip type id */ | 93 | unsigned int type; /* chip type id */ |
| 94 | unsigned int config; | 94 | unsigned int config; |
| 95 | int (*tuner_callback) (void *dev, int command, int arg); | ||
| 96 | const char *name; | 95 | const char *name; |
| 97 | }; | 96 | }; |
| 98 | 97 | ||
| @@ -346,7 +345,7 @@ static struct xc5000_config xc5000_cfg; | |||
| 346 | 345 | ||
| 347 | static void set_type(struct i2c_client *c, unsigned int type, | 346 | static void set_type(struct i2c_client *c, unsigned int type, |
| 348 | unsigned int new_mode_mask, unsigned int new_config, | 347 | unsigned int new_mode_mask, unsigned int new_config, |
| 349 | int (*tuner_callback) (void *dev, int command,int arg)) | 348 | int (*tuner_callback) (void *dev, int component, int cmd, int arg)) |
| 350 | { | 349 | { |
| 351 | struct tuner *t = i2c_get_clientdata(c); | 350 | struct tuner *t = i2c_get_clientdata(c); |
| 352 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; | 351 | struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops; |
| @@ -362,7 +361,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 362 | t->config = new_config; | 361 | t->config = new_config; |
| 363 | if (tuner_callback != NULL) { | 362 | if (tuner_callback != NULL) { |
| 364 | tuner_dbg("defining GPIO callback\n"); | 363 | tuner_dbg("defining GPIO callback\n"); |
| 365 | t->tuner_callback = tuner_callback; | 364 | t->fe.callback = tuner_callback; |
| 366 | } | 365 | } |
| 367 | 366 | ||
| 368 | if (t->mode == T_UNINITIALIZED) { | 367 | if (t->mode == T_UNINITIALIZED) { |
| @@ -385,7 +384,6 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 385 | { | 384 | { |
| 386 | struct tda829x_config cfg = { | 385 | struct tda829x_config cfg = { |
| 387 | .lna_cfg = t->config, | 386 | .lna_cfg = t->config, |
| 388 | .tuner_callback = t->tuner_callback, | ||
| 389 | }; | 387 | }; |
| 390 | if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter, | 388 | if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter, |
| 391 | t->i2c->addr, &cfg)) | 389 | t->i2c->addr, &cfg)) |
| @@ -433,7 +431,6 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 433 | struct xc2028_config cfg = { | 431 | struct xc2028_config cfg = { |
| 434 | .i2c_adap = t->i2c->adapter, | 432 | .i2c_adap = t->i2c->adapter, |
| 435 | .i2c_addr = t->i2c->addr, | 433 | .i2c_addr = t->i2c->addr, |
| 436 | .callback = t->tuner_callback, | ||
| 437 | }; | 434 | }; |
| 438 | if (!dvb_attach(xc2028_attach, &t->fe, &cfg)) | 435 | if (!dvb_attach(xc2028_attach, &t->fe, &cfg)) |
| 439 | goto attach_failed; | 436 | goto attach_failed; |
| @@ -450,10 +447,8 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
| 450 | 447 | ||
| 451 | xc5000_cfg.i2c_address = t->i2c->addr; | 448 | xc5000_cfg.i2c_address = t->i2c->addr; |
| 452 | xc5000_cfg.if_khz = 5380; | 449 | xc5000_cfg.if_khz = 5380; |
| 453 | xc5000_cfg.tuner_callback = t->tuner_callback; | ||
| 454 | if (!dvb_attach(xc5000_attach, | 450 | if (!dvb_attach(xc5000_attach, |
| 455 | &t->fe, t->i2c->adapter, &xc5000_cfg, | 451 | &t->fe, t->i2c->adapter, &xc5000_cfg)) |
| 456 | c->adapter->algo_data)) | ||
| 457 | goto attach_failed; | 452 | goto attach_failed; |
| 458 | 453 | ||
| 459 | xc_tuner_ops = &t->fe.ops.tuner_ops; | 454 | xc_tuner_ops = &t->fe.ops.tuner_ops; |
| @@ -1225,7 +1220,7 @@ register_client: | |||
| 1225 | } else { | 1220 | } else { |
| 1226 | t->mode = V4L2_TUNER_DIGITAL_TV; | 1221 | t->mode = V4L2_TUNER_DIGITAL_TV; |
| 1227 | } | 1222 | } |
| 1228 | set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback); | 1223 | set_type(client, t->type, t->mode_mask, t->config, t->fe.callback); |
| 1229 | list_add_tail(&t->list, &tuner_list); | 1224 | list_add_tail(&t->list, &tuner_list); |
| 1230 | return 0; | 1225 | return 0; |
| 1231 | } | 1226 | } |
diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index cc27efe121dd..28421d386f1e 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c | |||
| @@ -258,7 +258,9 @@ static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame h | |||
| 258 | (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00)) | 258 | (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00)) |
| 259 | { | 259 | { |
| 260 | #if 0 /* This code helps to detect new frame markers */ | 260 | #if 0 /* This code helps to detect new frame markers */ |
| 261 | info("Header sig: 00 FF 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 3)); | 261 | dev_info(&uvd->dev->dev, |
| 262 | "Header sig: 00 FF 00 %02X\n", | ||
| 263 | RING_QUEUE_PEEK(&uvd->dp, 3)); | ||
| 262 | #endif | 264 | #endif |
| 263 | frame->header = RING_QUEUE_PEEK(&uvd->dp, 3); | 265 | frame->header = RING_QUEUE_PEEK(&uvd->dp, 3); |
| 264 | if ((frame->header == HDRSIG_MODEL1_128x96) || | 266 | if ((frame->header == HDRSIG_MODEL1_128x96) || |
| @@ -266,7 +268,8 @@ static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame h | |||
| 266 | (frame->header == HDRSIG_MODEL1_352x288)) | 268 | (frame->header == HDRSIG_MODEL1_352x288)) |
| 267 | { | 269 | { |
| 268 | #if 0 | 270 | #if 0 |
| 269 | info("Header found."); | 271 | dev_info(&uvd->dev->dev, |
| 272 | "Header found.\n"); | ||
| 270 | #endif | 273 | #endif |
| 271 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); | 274 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); |
| 272 | icam->has_hdr = 1; | 275 | icam->has_hdr = 1; |
| @@ -295,7 +298,7 @@ case IBMCAM_MODEL_4: | |||
| 295 | (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF)) | 298 | (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF)) |
| 296 | { | 299 | { |
| 297 | #if 0 | 300 | #if 0 |
| 298 | info("Header found."); | 301 | dev_info(&uvd->dev->dev, "Header found.\n"); |
| 299 | #endif | 302 | #endif |
| 300 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); | 303 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); |
| 301 | icam->has_hdr = 1; | 304 | icam->has_hdr = 1; |
| @@ -338,7 +341,7 @@ case IBMCAM_MODEL_4: | |||
| 338 | byte4 = RING_QUEUE_PEEK(&uvd->dp, 3); | 341 | byte4 = RING_QUEUE_PEEK(&uvd->dp, 3); |
| 339 | frame->header = (byte3 << 8) | byte4; | 342 | frame->header = (byte3 << 8) | byte4; |
| 340 | #if 0 | 343 | #if 0 |
| 341 | info("Header found."); | 344 | dev_info(&uvd->dev->dev, "Header found.\n"); |
| 342 | #endif | 345 | #endif |
| 343 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); | 346 | RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len); |
| 344 | icam->has_hdr = 1; | 347 | icam->has_hdr = 1; |
| @@ -354,7 +357,8 @@ case IBMCAM_MODEL_4: | |||
| 354 | } | 357 | } |
| 355 | if (!icam->has_hdr) { | 358 | if (!icam->has_hdr) { |
| 356 | if (uvd->debug > 2) | 359 | if (uvd->debug > 2) |
| 357 | info("Skipping frame, no header"); | 360 | dev_info(&uvd->dev->dev, |
| 361 | "Skipping frame, no header\n"); | ||
| 358 | return scan_EndParse; | 362 | return scan_EndParse; |
| 359 | } | 363 | } |
| 360 | 364 | ||
| @@ -881,7 +885,9 @@ static enum ParseState ibmcam_model3_parse_lines( | |||
| 881 | */ | 885 | */ |
| 882 | if ((frame->curline + 1) >= data_h) { | 886 | if ((frame->curline + 1) >= data_h) { |
| 883 | if (uvd->debug >= 3) | 887 | if (uvd->debug >= 3) |
| 884 | info("Reached line %d. (frame is done)", frame->curline); | 888 | dev_info(&uvd->dev->dev, |
| 889 | "Reached line %d. (frame is done)\n", | ||
| 890 | frame->curline); | ||
| 885 | return scan_NextFrame; | 891 | return scan_NextFrame; |
| 886 | } | 892 | } |
| 887 | 893 | ||
| @@ -954,8 +960,9 @@ static enum ParseState ibmcam_model3_parse_lines( | |||
| 954 | 960 | ||
| 955 | if (frame->curline >= VIDEOSIZE_Y(frame->request)) { | 961 | if (frame->curline >= VIDEOSIZE_Y(frame->request)) { |
| 956 | if (uvd->debug >= 3) { | 962 | if (uvd->debug >= 3) { |
| 957 | info("All requested lines (%ld.) done.", | 963 | dev_info(&uvd->dev->dev, |
| 958 | VIDEOSIZE_Y(frame->request)); | 964 | "All requested lines (%ld.) done.\n", |
| 965 | VIDEOSIZE_Y(frame->request)); | ||
| 959 | } | 966 | } |
| 960 | return scan_NextFrame; | 967 | return scan_NextFrame; |
| 961 | } else | 968 | } else |
| @@ -1000,7 +1007,9 @@ static enum ParseState ibmcam_model4_128x96_parse_lines( | |||
| 1000 | */ | 1007 | */ |
| 1001 | if ((frame->curline + 1) >= data_h) { | 1008 | if ((frame->curline + 1) >= data_h) { |
| 1002 | if (uvd->debug >= 3) | 1009 | if (uvd->debug >= 3) |
| 1003 | info("Reached line %d. (frame is done)", frame->curline); | 1010 | dev_info(&uvd->dev->dev, |
| 1011 | "Reached line %d. (frame is done)\n", | ||
| 1012 | frame->curline); | ||
| 1004 | return scan_NextFrame; | 1013 | return scan_NextFrame; |
| 1005 | } | 1014 | } |
| 1006 | 1015 | ||
| @@ -1049,8 +1058,9 @@ static enum ParseState ibmcam_model4_128x96_parse_lines( | |||
| 1049 | 1058 | ||
| 1050 | if (frame->curline >= VIDEOSIZE_Y(frame->request)) { | 1059 | if (frame->curline >= VIDEOSIZE_Y(frame->request)) { |
| 1051 | if (uvd->debug >= 3) { | 1060 | if (uvd->debug >= 3) { |
| 1052 | info("All requested lines (%ld.) done.", | 1061 | dev_info(&uvd->dev->dev, |
| 1053 | VIDEOSIZE_Y(frame->request)); | 1062 | "All requested lines (%ld.) done.\n", |
| 1063 | VIDEOSIZE_Y(frame->request)); | ||
| 1054 | } | 1064 | } |
| 1055 | return scan_NextFrame; | 1065 | return scan_NextFrame; |
| 1056 | } else | 1066 | } else |
| @@ -1171,10 +1181,11 @@ static int ibmcam_veio( | |||
| 1171 | sizeof(cp), | 1181 | sizeof(cp), |
| 1172 | 1000); | 1182 | 1000); |
| 1173 | #if 0 | 1183 | #if 0 |
| 1174 | info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " | 1184 | dev_info(&uvd->dev->dev, |
| 1175 | "(req=$%02x val=$%04x ind=$%04x)", | 1185 | "USB => %02x%02x%02x%02x%02x%02x%02x%02x " |
| 1176 | cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], | 1186 | "(req=$%02x val=$%04x ind=$%04x)\n", |
| 1177 | req, value, index); | 1187 | cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], |
| 1188 | req, value, index); | ||
| 1178 | #endif | 1189 | #endif |
| 1179 | } else { | 1190 | } else { |
| 1180 | i = usb_control_msg( | 1191 | i = usb_control_msg( |
| @@ -1449,10 +1460,9 @@ static void ibmcam_adjust_contrast(struct uvd *uvd) | |||
| 1449 | */ | 1460 | */ |
| 1450 | static void ibmcam_change_lighting_conditions(struct uvd *uvd) | 1461 | static void ibmcam_change_lighting_conditions(struct uvd *uvd) |
| 1451 | { | 1462 | { |
| 1452 | static const char proc[] = "ibmcam_change_lighting_conditions"; | ||
| 1453 | |||
| 1454 | if (debug > 0) | 1463 | if (debug > 0) |
| 1455 | info("%s: Set lighting to %hu.", proc, lighting); | 1464 | dev_info(&uvd->dev->dev, |
| 1465 | "%s: Set lighting to %hu.\n", __func__, lighting); | ||
| 1456 | 1466 | ||
| 1457 | switch (IBMCAM_T(uvd)->camera_model) { | 1467 | switch (IBMCAM_T(uvd)->camera_model) { |
| 1458 | case IBMCAM_MODEL_1: | 1468 | case IBMCAM_MODEL_1: |
| @@ -1495,8 +1505,6 @@ static void ibmcam_change_lighting_conditions(struct uvd *uvd) | |||
| 1495 | */ | 1505 | */ |
| 1496 | static void ibmcam_set_sharpness(struct uvd *uvd) | 1506 | static void ibmcam_set_sharpness(struct uvd *uvd) |
| 1497 | { | 1507 | { |
| 1498 | static const char proc[] = "ibmcam_set_sharpness"; | ||
| 1499 | |||
| 1500 | switch (IBMCAM_T(uvd)->camera_model) { | 1508 | switch (IBMCAM_T(uvd)->camera_model) { |
| 1501 | case IBMCAM_MODEL_1: | 1509 | case IBMCAM_MODEL_1: |
| 1502 | { | 1510 | { |
| @@ -1505,7 +1513,8 @@ static void ibmcam_set_sharpness(struct uvd *uvd) | |||
| 1505 | 1513 | ||
| 1506 | RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); | 1514 | RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); |
| 1507 | if (debug > 0) | 1515 | if (debug > 0) |
| 1508 | info("%s: Set sharpness to %hu.", proc, sharpness); | 1516 | dev_info(&uvd->dev->dev, "%s: Set sharpness to %hu.\n", |
| 1517 | __func__, sharpness); | ||
| 1509 | 1518 | ||
| 1510 | sv = sa[sharpness - SHARPNESS_MIN]; | 1519 | sv = sa[sharpness - SHARPNESS_MIN]; |
| 1511 | for (i=0; i < 2; i++) { | 1520 | for (i=0; i < 2; i++) { |
| @@ -1564,11 +1573,11 @@ static void ibmcam_set_sharpness(struct uvd *uvd) | |||
| 1564 | */ | 1573 | */ |
| 1565 | static void ibmcam_set_brightness(struct uvd *uvd) | 1574 | static void ibmcam_set_brightness(struct uvd *uvd) |
| 1566 | { | 1575 | { |
| 1567 | static const char proc[] = "ibmcam_set_brightness"; | ||
| 1568 | static const unsigned short n = 1; | 1576 | static const unsigned short n = 1; |
| 1569 | 1577 | ||
| 1570 | if (debug > 0) | 1578 | if (debug > 0) |
| 1571 | info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness); | 1579 | dev_info(&uvd->dev->dev, "%s: Set brightness to %hu.\n", |
| 1580 | __func__, uvd->vpic.brightness); | ||
| 1572 | 1581 | ||
| 1573 | switch (IBMCAM_T(uvd)->camera_model) { | 1582 | switch (IBMCAM_T(uvd)->camera_model) { |
| 1574 | case IBMCAM_MODEL_1: | 1583 | case IBMCAM_MODEL_1: |
| @@ -2115,7 +2124,8 @@ static void ibmcam_model2_setup_after_video_if(struct uvd *uvd) | |||
| 2115 | break; | 2124 | break; |
| 2116 | } | 2125 | } |
| 2117 | if (uvd->debug > 0) | 2126 | if (uvd->debug > 0) |
| 2118 | info("Framerate (hardware): %hd.", hw_fps); | 2127 | dev_info(&uvd->dev->dev, "Framerate (hardware): %hd.\n", |
| 2128 | hw_fps); | ||
| 2119 | RESTRICT_TO_RANGE(hw_fps, 0, 31); | 2129 | RESTRICT_TO_RANGE(hw_fps, 0, 31); |
| 2120 | ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps); | 2130 | ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps); |
| 2121 | } | 2131 | } |
| @@ -3487,7 +3497,7 @@ static void ibmcam_model3_setup_after_video_if(struct uvd *uvd) | |||
| 3487 | /* 01.01.08 - Added for RCA video in support -LO */ | 3497 | /* 01.01.08 - Added for RCA video in support -LO */ |
| 3488 | if(init_model3_input) { | 3498 | if(init_model3_input) { |
| 3489 | if (debug > 0) | 3499 | if (debug > 0) |
| 3490 | info("Setting input to RCA."); | 3500 | dev_info(&uvd->dev->dev, "Setting input to RCA.\n"); |
| 3491 | for (i=0; i < ARRAY_SIZE(initData); i++) { | 3501 | for (i=0; i < ARRAY_SIZE(initData); i++) { |
| 3492 | ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index); | 3502 | ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index); |
| 3493 | } | 3503 | } |
| @@ -3685,7 +3695,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3685 | unsigned char video_ep = 0; | 3695 | unsigned char video_ep = 0; |
| 3686 | 3696 | ||
| 3687 | if (debug >= 1) | 3697 | if (debug >= 1) |
| 3688 | info("ibmcam_probe(%p,%u.)", intf, ifnum); | 3698 | dev_info(&uvd->dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); |
| 3689 | 3699 | ||
| 3690 | /* We don't handle multi-config cameras */ | 3700 | /* We don't handle multi-config cameras */ |
| 3691 | if (dev->descriptor.bNumConfigurations != 1) | 3701 | if (dev->descriptor.bNumConfigurations != 1) |
| @@ -3736,14 +3746,16 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3736 | brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ | 3746 | brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ |
| 3737 | break; | 3747 | break; |
| 3738 | } | 3748 | } |
| 3739 | info("%s USB camera found (model %d, rev. 0x%04x)", | 3749 | dev_info(&uvd->dev->dev, |
| 3740 | brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); | 3750 | "%s USB camera found (model %d, rev. 0x%04x)\n", |
| 3751 | brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); | ||
| 3741 | } while (0); | 3752 | } while (0); |
| 3742 | 3753 | ||
| 3743 | /* Validate found interface: must have one ISO endpoint */ | 3754 | /* Validate found interface: must have one ISO endpoint */ |
| 3744 | nas = intf->num_altsetting; | 3755 | nas = intf->num_altsetting; |
| 3745 | if (debug > 0) | 3756 | if (debug > 0) |
| 3746 | info("Number of alternate settings=%d.", nas); | 3757 | dev_info(&uvd->dev->dev, "Number of alternate settings=%d.\n", |
| 3758 | nas); | ||
| 3747 | if (nas < 2) { | 3759 | if (nas < 2) { |
| 3748 | err("Too few alternate settings for this camera!"); | 3760 | err("Too few alternate settings for this camera!"); |
| 3749 | return -ENODEV; | 3761 | return -ENODEV; |
| @@ -3787,7 +3799,9 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3787 | actInterface = i; | 3799 | actInterface = i; |
| 3788 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); | 3800 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); |
| 3789 | if (debug > 0) | 3801 | if (debug > 0) |
| 3790 | info("Active setting=%d. maxPS=%d.", i, maxPS); | 3802 | dev_info(&uvd->dev->dev, |
| 3803 | "Active setting=%d. " | ||
| 3804 | "maxPS=%d.\n", i, maxPS); | ||
| 3791 | } else | 3805 | } else |
| 3792 | err("More than one active alt. setting! Ignoring #%d.", i); | 3806 | err("More than one active alt. setting! Ignoring #%d.", i); |
| 3793 | } | 3807 | } |
| @@ -3826,7 +3840,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3826 | RESTRICT_TO_RANGE(framerate, 0, 5); | 3840 | RESTRICT_TO_RANGE(framerate, 0, 5); |
| 3827 | break; | 3841 | break; |
| 3828 | default: | 3842 | default: |
| 3829 | info("IBM camera: using 320x240"); | 3843 | dev_info(&uvd->dev->dev, "IBM camera: using 320x240\n"); |
| 3830 | size = SIZE_320x240; | 3844 | size = SIZE_320x240; |
| 3831 | /* No break here */ | 3845 | /* No break here */ |
| 3832 | case SIZE_320x240: | 3846 | case SIZE_320x240: |
| @@ -3855,7 +3869,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 3855 | canvasY = 120; | 3869 | canvasY = 120; |
| 3856 | break; | 3870 | break; |
| 3857 | default: | 3871 | default: |
| 3858 | info("IBM NetCamera: using 176x144"); | 3872 | dev_info(&uvd->dev->dev, "IBM NetCamera: using 176x144\n"); |
| 3859 | size = SIZE_176x144; | 3873 | size = SIZE_176x144; |
| 3860 | /* No break here */ | 3874 | /* No break here */ |
| 3861 | case SIZE_176x144: | 3875 | case SIZE_176x144: |
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c index 1c180284ec6c..e986c28b7bb0 100644 --- a/drivers/media/video/usbvideo/konicawc.c +++ b/drivers/media/video/usbvideo/konicawc.c | |||
| @@ -337,7 +337,8 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur | |||
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | if((sts > 0x01) && (sts < 0x80)) { | 339 | if((sts > 0x01) && (sts < 0x80)) { |
| 340 | info("unknown status %2.2x", sts); | 340 | dev_info(&uvd->dev->dev, "unknown status %2.2x\n", |
| 341 | sts); | ||
| 341 | bad++; | 342 | bad++; |
| 342 | continue; | 343 | continue; |
| 343 | } | 344 | } |
| @@ -568,8 +569,12 @@ static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) | |||
| 568 | fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; | 569 | fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; |
| 569 | fdrops--; | 570 | fdrops--; |
| 570 | if(fdrops) { | 571 | if(fdrops) { |
| 571 | info("Dropped %d frames (%d -> %d)", fdrops, | 572 | dev_info(&uvd->dev->dev, |
| 572 | cam->lastframe, curframe); | 573 | "Dropped %d frames " |
| 574 | "(%d -> %d)\n", | ||
| 575 | fdrops, | ||
| 576 | cam->lastframe, | ||
| 577 | curframe); | ||
| 573 | } | 578 | } |
| 574 | } | 579 | } |
| 575 | cam->lastframe = curframe; | 580 | cam->lastframe = curframe; |
| @@ -784,7 +789,8 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id | |||
| 784 | if (dev->descriptor.bNumConfigurations != 1) | 789 | if (dev->descriptor.bNumConfigurations != 1) |
| 785 | return -ENODEV; | 790 | return -ENODEV; |
| 786 | 791 | ||
| 787 | info("Konica Webcam (rev. 0x%04x)", le16_to_cpu(dev->descriptor.bcdDevice)); | 792 | dev_info(&intf->dev, "Konica Webcam (rev. 0x%04x)\n", |
| 793 | le16_to_cpu(dev->descriptor.bcdDevice)); | ||
| 788 | RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); | 794 | RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); |
| 789 | 795 | ||
| 790 | /* Validate found interface: must have one ISO endpoint */ | 796 | /* Validate found interface: must have one ISO endpoint */ |
| @@ -925,7 +931,8 @@ static struct usb_device_id id_table[] = { | |||
| 925 | static int __init konicawc_init(void) | 931 | static int __init konicawc_init(void) |
| 926 | { | 932 | { |
| 927 | struct usbvideo_cb cbTbl; | 933 | struct usbvideo_cb cbTbl; |
| 928 | info(DRIVER_DESC " " DRIVER_VERSION); | 934 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
| 935 | DRIVER_DESC "\n"); | ||
| 929 | memset(&cbTbl, 0, sizeof(cbTbl)); | 936 | memset(&cbTbl, 0, sizeof(cbTbl)); |
| 930 | cbTbl.probe = konicawc_probe; | 937 | cbTbl.probe = konicawc_probe; |
| 931 | cbTbl.setupOnOpen = konicawc_setup_on_open; | 938 | cbTbl.setupOnOpen = konicawc_setup_on_open; |
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index 3d26a30abe1e..05c61b523115 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c | |||
| @@ -1080,7 +1080,8 @@ static struct usbvideo_cb qcm_driver = { | |||
| 1080 | 1080 | ||
| 1081 | static int __init qcm_init(void) | 1081 | static int __init qcm_init(void) |
| 1082 | { | 1082 | { |
| 1083 | info(DRIVER_DESC " " DRIVER_VERSION); | 1083 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
| 1084 | DRIVER_DESC "\n"); | ||
| 1084 | 1085 | ||
| 1085 | return usbvideo_register( | 1086 | return usbvideo_register( |
| 1086 | &cams, | 1087 | &cams, |
diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c index 9544e644bf0d..9714baab7833 100644 --- a/drivers/media/video/usbvideo/ultracam.c +++ b/drivers/media/video/usbvideo/ultracam.c | |||
| @@ -156,10 +156,11 @@ static int ultracam_veio( | |||
| 156 | sizeof(cp), | 156 | sizeof(cp), |
| 157 | 1000); | 157 | 1000); |
| 158 | #if 1 | 158 | #if 1 |
| 159 | info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " | 159 | dev_info(&uvd->dev->dev, |
| 160 | "(req=$%02x val=$%04x ind=$%04x)", | 160 | "USB => %02x%02x%02x%02x%02x%02x%02x%02x " |
| 161 | cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], | 161 | "(req=$%02x val=$%04x ind=$%04x)\n", |
| 162 | req, value, index); | 162 | cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], |
| 163 | req, value, index); | ||
| 163 | #endif | 164 | #endif |
| 164 | } else { | 165 | } else { |
| 165 | i = usb_control_msg( | 166 | i = usb_control_msg( |
| @@ -517,19 +518,20 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id | |||
| 517 | unsigned char video_ep = 0; | 518 | unsigned char video_ep = 0; |
| 518 | 519 | ||
| 519 | if (debug >= 1) | 520 | if (debug >= 1) |
| 520 | info("ultracam_probe(%p)", intf); | 521 | dev_info(&intf->dev, "ultracam_probe\n"); |
| 521 | 522 | ||
| 522 | /* We don't handle multi-config cameras */ | 523 | /* We don't handle multi-config cameras */ |
| 523 | if (dev->descriptor.bNumConfigurations != 1) | 524 | if (dev->descriptor.bNumConfigurations != 1) |
| 524 | return -ENODEV; | 525 | return -ENODEV; |
| 525 | 526 | ||
| 526 | info("IBM Ultra camera found (rev. 0x%04x)", | 527 | dev_info(&intf->dev, "IBM Ultra camera found (rev. 0x%04x)\n", |
| 527 | le16_to_cpu(dev->descriptor.bcdDevice)); | 528 | le16_to_cpu(dev->descriptor.bcdDevice)); |
| 528 | 529 | ||
| 529 | /* Validate found interface: must have one ISO endpoint */ | 530 | /* Validate found interface: must have one ISO endpoint */ |
| 530 | nas = intf->num_altsetting; | 531 | nas = intf->num_altsetting; |
| 531 | if (debug > 0) | 532 | if (debug > 0) |
| 532 | info("Number of alternate settings=%d.", nas); | 533 | dev_info(&intf->dev, "Number of alternate settings=%d.\n", |
| 534 | nas); | ||
| 533 | if (nas < 8) { | 535 | if (nas < 8) { |
| 534 | err("Too few alternate settings for this camera!"); | 536 | err("Too few alternate settings for this camera!"); |
| 535 | return -ENODEV; | 537 | return -ENODEV; |
| @@ -576,7 +578,9 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id | |||
| 576 | actInterface = i; | 578 | actInterface = i; |
| 577 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); | 579 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); |
| 578 | if (debug > 0) | 580 | if (debug > 0) |
| 579 | info("Active setting=%d. maxPS=%d.", i, maxPS); | 581 | dev_info(&intf->dev, |
| 582 | "Active setting=%d. " | ||
| 583 | "maxPS=%d.\n", i, maxPS); | ||
| 580 | } else { | 584 | } else { |
| 581 | /* Got another active alt. setting */ | 585 | /* Got another active alt. setting */ |
| 582 | if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) { | 586 | if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) { |
| @@ -584,8 +588,11 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id | |||
| 584 | actInterface = i; | 588 | actInterface = i; |
| 585 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); | 589 | maxPS = le16_to_cpu(endpoint->wMaxPacketSize); |
| 586 | if (debug > 0) { | 590 | if (debug > 0) { |
| 587 | info("Even better ctive setting=%d. maxPS=%d.", | 591 | dev_info(&intf->dev, |
| 588 | i, maxPS); | 592 | "Even better ctive " |
| 593 | "setting=%d. " | ||
| 594 | "maxPS=%d.\n", | ||
| 595 | i, maxPS); | ||
| 589 | } | 596 | } |
| 590 | } | 597 | } |
| 591 | } | 598 | } |
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index bf1bc2f69b02..07cd87d16f69 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c | |||
| @@ -468,8 +468,9 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd) | |||
| 468 | percent = (100 * goodPackets) / allPackets; | 468 | percent = (100 * goodPackets) / allPackets; |
| 469 | else | 469 | else |
| 470 | percent = goodPackets / (allPackets / 100); | 470 | percent = goodPackets / (allPackets / 100); |
| 471 | info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%", | 471 | dev_info(&uvd->dev->dev, |
| 472 | allPackets, badPackets, percent); | 472 | "Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%\n", |
| 473 | allPackets, badPackets, percent); | ||
| 473 | if (uvd->iso_packet_len > 0) { | 474 | if (uvd->iso_packet_len > 0) { |
| 474 | unsigned long allBytes, xferBytes; | 475 | unsigned long allBytes, xferBytes; |
| 475 | char multiplier = ' '; | 476 | char multiplier = ' '; |
| @@ -497,8 +498,9 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd) | |||
| 497 | } | 498 | } |
| 498 | } | 499 | } |
| 499 | } | 500 | } |
| 500 | info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%", | 501 | dev_info(&uvd->dev->dev, |
| 501 | xferBytes, multiplier, percent); | 502 | "Transfer Statistics: Transferred=%lu%cB Usage=%lu%%\n", |
| 503 | xferBytes, multiplier, percent); | ||
| 502 | } | 504 | } |
| 503 | } | 505 | } |
| 504 | } | 506 | } |
| @@ -545,7 +547,7 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode) | |||
| 545 | { /* For debugging purposes only */ | 547 | { /* For debugging purposes only */ |
| 546 | char tmp[20]; | 548 | char tmp[20]; |
| 547 | usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); | 549 | usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request); |
| 548 | info("testpattern: frame=%s", tmp); | 550 | dev_info(&uvd->dev->dev, "testpattern: frame=%s\n", tmp); |
| 549 | } | 551 | } |
| 550 | #endif | 552 | #endif |
| 551 | /* Form every scan line */ | 553 | /* Form every scan line */ |
| @@ -854,7 +856,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf) | |||
| 854 | 856 | ||
| 855 | usbvideo_ClientIncModCount(uvd); | 857 | usbvideo_ClientIncModCount(uvd); |
| 856 | if (uvd->debug > 0) | 858 | if (uvd->debug > 0) |
| 857 | info("%s(%p.)", __func__, intf); | 859 | dev_info(&intf->dev, "%s(%p.)\n", __func__, intf); |
| 858 | 860 | ||
| 859 | mutex_lock(&uvd->lock); | 861 | mutex_lock(&uvd->lock); |
| 860 | uvd->remove_pending = 1; /* Now all ISO data will be ignored */ | 862 | uvd->remove_pending = 1; /* Now all ISO data will be ignored */ |
| @@ -870,14 +872,15 @@ static void usbvideo_Disconnect(struct usb_interface *intf) | |||
| 870 | 872 | ||
| 871 | video_unregister_device(&uvd->vdev); | 873 | video_unregister_device(&uvd->vdev); |
| 872 | if (uvd->debug > 0) | 874 | if (uvd->debug > 0) |
| 873 | info("%s: Video unregistered.", __func__); | 875 | dev_info(&intf->dev, "%s: Video unregistered.\n", __func__); |
| 874 | 876 | ||
| 875 | if (uvd->user) | 877 | if (uvd->user) |
| 876 | info("%s: In use, disconnect pending.", __func__); | 878 | dev_info(&intf->dev, "%s: In use, disconnect pending.\n", |
| 879 | __func__); | ||
| 877 | else | 880 | else |
| 878 | usbvideo_CameraRelease(uvd); | 881 | usbvideo_CameraRelease(uvd); |
| 879 | mutex_unlock(&uvd->lock); | 882 | mutex_unlock(&uvd->lock); |
| 880 | info("USB camera disconnected."); | 883 | dev_info(&intf->dev, "USB camera disconnected.\n"); |
| 881 | 884 | ||
| 882 | usbvideo_ClientDecModCount(uvd); | 885 | usbvideo_ClientDecModCount(uvd); |
| 883 | } | 886 | } |
| @@ -1015,14 +1018,17 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) | |||
| 1015 | return -EINVAL; | 1018 | return -EINVAL; |
| 1016 | } | 1019 | } |
| 1017 | if (uvd->video_endp == 0) { | 1020 | if (uvd->video_endp == 0) { |
| 1018 | info("%s: No video endpoint specified; data pump disabled.", __func__); | 1021 | dev_info(&uvd->dev->dev, |
| 1022 | "%s: No video endpoint specified; data pump disabled.\n", | ||
| 1023 | __func__); | ||
| 1019 | } | 1024 | } |
| 1020 | if (uvd->paletteBits == 0) { | 1025 | if (uvd->paletteBits == 0) { |
| 1021 | err("%s: No palettes specified!", __func__); | 1026 | err("%s: No palettes specified!", __func__); |
| 1022 | return -EINVAL; | 1027 | return -EINVAL; |
| 1023 | } | 1028 | } |
| 1024 | if (uvd->defaultPalette == 0) { | 1029 | if (uvd->defaultPalette == 0) { |
| 1025 | info("%s: No default palette!", __func__); | 1030 | dev_info(&uvd->dev->dev, "%s: No default palette!\n", |
| 1031 | __func__); | ||
| 1026 | } | 1032 | } |
| 1027 | 1033 | ||
| 1028 | uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * | 1034 | uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) * |
| @@ -1031,25 +1037,29 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) | |||
| 1031 | usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); | 1037 | usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas); |
| 1032 | 1038 | ||
| 1033 | if (uvd->debug > 0) { | 1039 | if (uvd->debug > 0) { |
| 1034 | info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx", | 1040 | dev_info(&uvd->dev->dev, |
| 1035 | __func__, uvd->iface, uvd->video_endp, uvd->paletteBits); | 1041 | "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n", |
| 1042 | __func__, uvd->iface, uvd->video_endp, | ||
| 1043 | uvd->paletteBits); | ||
| 1036 | } | 1044 | } |
| 1037 | if (uvd->dev == NULL) { | 1045 | if (uvd->dev == NULL) { |
| 1038 | err("%s: uvd->dev == NULL", __func__); | 1046 | err("%s: uvd->dev == NULL", __func__); |
| 1039 | return -EINVAL; | 1047 | return -EINVAL; |
| 1040 | } | 1048 | } |
| 1041 | uvd->vdev.parent = &uvd->dev->dev; | 1049 | uvd->vdev.parent = &uvd->dev->dev; |
| 1042 | if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { | 1050 | uvd->vdev.release = video_device_release_empty; |
| 1051 | if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { | ||
| 1043 | err("%s: video_register_device failed", __func__); | 1052 | err("%s: video_register_device failed", __func__); |
| 1044 | return -EPIPE; | 1053 | return -EPIPE; |
| 1045 | } | 1054 | } |
| 1046 | if (uvd->debug > 1) { | 1055 | if (uvd->debug > 1) { |
| 1047 | info("%s: video_register_device() successful", __func__); | 1056 | dev_info(&uvd->dev->dev, |
| 1057 | "%s: video_register_device() successful\n", __func__); | ||
| 1048 | } | 1058 | } |
| 1049 | 1059 | ||
| 1050 | info("%s on /dev/video%d: canvas=%s videosize=%s", | 1060 | dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n", |
| 1051 | (uvd->handle != NULL) ? uvd->handle->drvName : "???", | 1061 | (uvd->handle != NULL) ? uvd->handle->drvName : "???", |
| 1052 | uvd->vdev.minor, tmp2, tmp1); | 1062 | uvd->vdev.minor, tmp2, tmp1); |
| 1053 | 1063 | ||
| 1054 | usb_get_dev(uvd->dev); | 1064 | usb_get_dev(uvd->dev); |
| 1055 | return 0; | 1065 | return 0; |
| @@ -1111,7 +1121,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) | |||
| 1111 | int i, errCode = 0; | 1121 | int i, errCode = 0; |
| 1112 | 1122 | ||
| 1113 | if (uvd->debug > 1) | 1123 | if (uvd->debug > 1) |
| 1114 | info("%s($%p)", __func__, dev); | 1124 | dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); |
| 1115 | 1125 | ||
| 1116 | if (0 < usbvideo_ClientIncModCount(uvd)) | 1126 | if (0 < usbvideo_ClientIncModCount(uvd)) |
| 1117 | return -ENODEV; | 1127 | return -ENODEV; |
| @@ -1178,19 +1188,25 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) | |||
| 1178 | if (errCode == 0) { | 1188 | if (errCode == 0) { |
| 1179 | if (VALID_CALLBACK(uvd, setupOnOpen)) { | 1189 | if (VALID_CALLBACK(uvd, setupOnOpen)) { |
| 1180 | if (uvd->debug > 1) | 1190 | if (uvd->debug > 1) |
| 1181 | info("%s: setupOnOpen callback", __func__); | 1191 | dev_info(&uvd->dev->dev, |
| 1192 | "%s: setupOnOpen callback\n", | ||
| 1193 | __func__); | ||
| 1182 | errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); | 1194 | errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd); |
| 1183 | if (errCode < 0) { | 1195 | if (errCode < 0) { |
| 1184 | err("%s: setupOnOpen callback failed (%d.).", | 1196 | err("%s: setupOnOpen callback failed (%d.).", |
| 1185 | __func__, errCode); | 1197 | __func__, errCode); |
| 1186 | } else if (uvd->debug > 1) { | 1198 | } else if (uvd->debug > 1) { |
| 1187 | info("%s: setupOnOpen callback successful", __func__); | 1199 | dev_info(&uvd->dev->dev, |
| 1200 | "%s: setupOnOpen callback successful\n", | ||
| 1201 | __func__); | ||
| 1188 | } | 1202 | } |
| 1189 | } | 1203 | } |
| 1190 | if (errCode == 0) { | 1204 | if (errCode == 0) { |
| 1191 | uvd->settingsAdjusted = 0; | 1205 | uvd->settingsAdjusted = 0; |
| 1192 | if (uvd->debug > 1) | 1206 | if (uvd->debug > 1) |
| 1193 | info("%s: Open succeeded.", __func__); | 1207 | dev_info(&uvd->dev->dev, |
| 1208 | "%s: Open succeeded.\n", | ||
| 1209 | __func__); | ||
| 1194 | uvd->user++; | 1210 | uvd->user++; |
| 1195 | file->private_data = uvd; | 1211 | file->private_data = uvd; |
| 1196 | } | 1212 | } |
| @@ -1200,7 +1216,8 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) | |||
| 1200 | if (errCode != 0) | 1216 | if (errCode != 0) |
| 1201 | usbvideo_ClientDecModCount(uvd); | 1217 | usbvideo_ClientDecModCount(uvd); |
| 1202 | if (uvd->debug > 0) | 1218 | if (uvd->debug > 0) |
| 1203 | info("%s: Returning %d.", __func__, errCode); | 1219 | dev_info(&uvd->dev->dev, "%s: Returning %d.\n", __func__, |
| 1220 | errCode); | ||
| 1204 | return errCode; | 1221 | return errCode; |
| 1205 | } | 1222 | } |
| 1206 | 1223 | ||
| @@ -1223,7 +1240,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) | |||
| 1223 | int i; | 1240 | int i; |
| 1224 | 1241 | ||
| 1225 | if (uvd->debug > 1) | 1242 | if (uvd->debug > 1) |
| 1226 | info("%s($%p)", __func__, dev); | 1243 | dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev); |
| 1227 | 1244 | ||
| 1228 | mutex_lock(&uvd->lock); | 1245 | mutex_lock(&uvd->lock); |
| 1229 | GET_CALLBACK(uvd, stopDataPump)(uvd); | 1246 | GET_CALLBACK(uvd, stopDataPump)(uvd); |
| @@ -1243,14 +1260,15 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file) | |||
| 1243 | uvd->user--; | 1260 | uvd->user--; |
| 1244 | if (uvd->remove_pending) { | 1261 | if (uvd->remove_pending) { |
| 1245 | if (uvd->debug > 0) | 1262 | if (uvd->debug > 0) |
| 1246 | info("usbvideo_v4l_close: Final disconnect."); | 1263 | dev_info(&uvd->dev->dev, "%s: Final disconnect.\n", |
| 1264 | __func__); | ||
| 1247 | usbvideo_CameraRelease(uvd); | 1265 | usbvideo_CameraRelease(uvd); |
| 1248 | } | 1266 | } |
| 1249 | mutex_unlock(&uvd->lock); | 1267 | mutex_unlock(&uvd->lock); |
| 1250 | usbvideo_ClientDecModCount(uvd); | 1268 | usbvideo_ClientDecModCount(uvd); |
| 1251 | 1269 | ||
| 1252 | if (uvd->debug > 1) | 1270 | if (uvd->debug > 1) |
| 1253 | info("%s: Completed.", __func__); | 1271 | dev_info(&uvd->dev->dev, "%s: Completed.\n", __func__); |
| 1254 | file->private_data = NULL; | 1272 | file->private_data = NULL; |
| 1255 | return 0; | 1273 | return 0; |
| 1256 | } | 1274 | } |
| @@ -1364,8 +1382,9 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, | |||
| 1364 | struct video_mmap *vm = arg; | 1382 | struct video_mmap *vm = arg; |
| 1365 | 1383 | ||
| 1366 | if (uvd->debug >= 1) { | 1384 | if (uvd->debug >= 1) { |
| 1367 | info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.", | 1385 | dev_info(&uvd->dev->dev, |
| 1368 | vm->frame, vm->width, vm->height, vm->format); | 1386 | "VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.\n", |
| 1387 | vm->frame, vm->width, vm->height, vm->format); | ||
| 1369 | } | 1388 | } |
| 1370 | /* | 1389 | /* |
| 1371 | * Check if the requested size is supported. If the requestor | 1390 | * Check if the requested size is supported. If the requestor |
| @@ -1383,18 +1402,24 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, | |||
| 1383 | if ((vm->width > VIDEOSIZE_X(uvd->canvas)) || | 1402 | if ((vm->width > VIDEOSIZE_X(uvd->canvas)) || |
| 1384 | (vm->height > VIDEOSIZE_Y(uvd->canvas))) { | 1403 | (vm->height > VIDEOSIZE_Y(uvd->canvas))) { |
| 1385 | if (uvd->debug > 0) { | 1404 | if (uvd->debug > 0) { |
| 1386 | info("VIDIOCMCAPTURE: Size=%dx%d too large; " | 1405 | dev_info(&uvd->dev->dev, |
| 1387 | "allowed only up to %ldx%ld", vm->width, vm->height, | 1406 | "VIDIOCMCAPTURE: Size=%dx%d " |
| 1388 | VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas)); | 1407 | "too large; allowed only up " |
| 1408 | "to %ldx%ld\n", vm->width, | ||
| 1409 | vm->height, | ||
| 1410 | VIDEOSIZE_X(uvd->canvas), | ||
| 1411 | VIDEOSIZE_Y(uvd->canvas)); | ||
| 1389 | } | 1412 | } |
| 1390 | return -EINVAL; | 1413 | return -EINVAL; |
| 1391 | } | 1414 | } |
| 1392 | /* Check if the palette is supported */ | 1415 | /* Check if the palette is supported */ |
| 1393 | if (((1L << vm->format) & uvd->paletteBits) == 0) { | 1416 | if (((1L << vm->format) & uvd->paletteBits) == 0) { |
| 1394 | if (uvd->debug > 0) { | 1417 | if (uvd->debug > 0) { |
| 1395 | info("VIDIOCMCAPTURE: format=%d. not supported" | 1418 | dev_info(&uvd->dev->dev, |
| 1396 | " (paletteBits=$%08lx)", | 1419 | "VIDIOCMCAPTURE: format=%d. " |
| 1397 | vm->format, uvd->paletteBits); | 1420 | "not supported " |
| 1421 | "(paletteBits=$%08lx)\n", | ||
| 1422 | vm->format, uvd->paletteBits); | ||
| 1398 | } | 1423 | } |
| 1399 | return -EINVAL; | 1424 | return -EINVAL; |
| 1400 | } | 1425 | } |
| @@ -1422,7 +1447,9 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file, | |||
| 1422 | return -EINVAL; | 1447 | return -EINVAL; |
| 1423 | 1448 | ||
| 1424 | if (uvd->debug >= 1) | 1449 | if (uvd->debug >= 1) |
| 1425 | info("VIDIOCSYNC: syncing to frame %d.", *frameNum); | 1450 | dev_info(&uvd->dev->dev, |
| 1451 | "VIDIOCSYNC: syncing to frame %d.\n", | ||
| 1452 | *frameNum); | ||
| 1426 | if (uvd->flags & FLAGS_NO_DECODING) | 1453 | if (uvd->flags & FLAGS_NO_DECODING) |
| 1427 | ret = usbvideo_GetFrame(uvd, *frameNum); | 1454 | ret = usbvideo_GetFrame(uvd, *frameNum); |
| 1428 | else if (VALID_CALLBACK(uvd, getFrame)) { | 1455 | else if (VALID_CALLBACK(uvd, getFrame)) { |
| @@ -1504,7 +1531,9 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf, | |||
| 1504 | return -EFAULT; | 1531 | return -EFAULT; |
| 1505 | 1532 | ||
| 1506 | if (uvd->debug >= 1) | 1533 | if (uvd->debug >= 1) |
| 1507 | info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock); | 1534 | dev_info(&uvd->dev->dev, |
| 1535 | "%s: %Zd. bytes, noblock=%d.\n", | ||
| 1536 | __func__, count, noblock); | ||
| 1508 | 1537 | ||
| 1509 | mutex_lock(&uvd->lock); | 1538 | mutex_lock(&uvd->lock); |
| 1510 | 1539 | ||
| @@ -1685,18 +1714,21 @@ static void usbvideo_IsocIrq(struct urb *urb) | |||
| 1685 | return; | 1714 | return; |
| 1686 | #if 0 | 1715 | #if 0 |
| 1687 | if (urb->actual_length > 0) { | 1716 | if (urb->actual_length > 0) { |
| 1688 | info("urb=$%p status=%d. errcount=%d. length=%d.", | 1717 | dev_info(&uvd->dev->dev, |
| 1689 | urb, urb->status, urb->error_count, urb->actual_length); | 1718 | "urb=$%p status=%d. errcount=%d. length=%d.\n", |
| 1719 | urb, urb->status, urb->error_count, | ||
| 1720 | urb->actual_length); | ||
| 1690 | } else { | 1721 | } else { |
| 1691 | static int c = 0; | 1722 | static int c = 0; |
| 1692 | if (c++ % 100 == 0) | 1723 | if (c++ % 100 == 0) |
| 1693 | info("No Isoc data"); | 1724 | dev_info(&uvd->dev->dev, "No Isoc data\n"); |
| 1694 | } | 1725 | } |
| 1695 | #endif | 1726 | #endif |
| 1696 | 1727 | ||
| 1697 | if (!uvd->streaming) { | 1728 | if (!uvd->streaming) { |
| 1698 | if (uvd->debug >= 1) | 1729 | if (uvd->debug >= 1) |
| 1699 | info("Not streaming, but interrupt!"); | 1730 | dev_info(&uvd->dev->dev, |
| 1731 | "Not streaming, but interrupt!\n"); | ||
| 1700 | return; | 1732 | return; |
| 1701 | } | 1733 | } |
| 1702 | 1734 | ||
| @@ -1741,7 +1773,7 @@ static int usbvideo_StartDataPump(struct uvd *uvd) | |||
| 1741 | int i, errFlag; | 1773 | int i, errFlag; |
| 1742 | 1774 | ||
| 1743 | if (uvd->debug > 1) | 1775 | if (uvd->debug > 1) |
| 1744 | info("%s($%p)", __func__, uvd); | 1776 | dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); |
| 1745 | 1777 | ||
| 1746 | if (!CAMERA_IS_OPERATIONAL(uvd)) { | 1778 | if (!CAMERA_IS_OPERATIONAL(uvd)) { |
| 1747 | err("%s: Camera is not operational", __func__); | 1779 | err("%s: Camera is not operational", __func__); |
| @@ -1789,7 +1821,9 @@ static int usbvideo_StartDataPump(struct uvd *uvd) | |||
| 1789 | 1821 | ||
| 1790 | uvd->streaming = 1; | 1822 | uvd->streaming = 1; |
| 1791 | if (uvd->debug > 1) | 1823 | if (uvd->debug > 1) |
| 1792 | info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp); | 1824 | dev_info(&uvd->dev->dev, |
| 1825 | "%s: streaming=1 video_endp=$%02x\n", __func__, | ||
| 1826 | uvd->video_endp); | ||
| 1793 | return 0; | 1827 | return 0; |
| 1794 | } | 1828 | } |
| 1795 | 1829 | ||
| @@ -1811,14 +1845,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd) | |||
| 1811 | return; | 1845 | return; |
| 1812 | 1846 | ||
| 1813 | if (uvd->debug > 1) | 1847 | if (uvd->debug > 1) |
| 1814 | info("%s($%p)", __func__, uvd); | 1848 | dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd); |
| 1815 | 1849 | ||
| 1816 | /* Unschedule all of the iso td's */ | 1850 | /* Unschedule all of the iso td's */ |
| 1817 | for (i=0; i < USBVIDEO_NUMSBUF; i++) { | 1851 | for (i=0; i < USBVIDEO_NUMSBUF; i++) { |
| 1818 | usb_kill_urb(uvd->sbuf[i].urb); | 1852 | usb_kill_urb(uvd->sbuf[i].urb); |
| 1819 | } | 1853 | } |
| 1820 | if (uvd->debug > 1) | 1854 | if (uvd->debug > 1) |
| 1821 | info("%s: streaming=0", __func__); | 1855 | dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__); |
| 1822 | uvd->streaming = 0; | 1856 | uvd->streaming = 0; |
| 1823 | 1857 | ||
| 1824 | if (!uvd->remove_pending) { | 1858 | if (!uvd->remove_pending) { |
| @@ -1850,7 +1884,8 @@ static int usbvideo_NewFrame(struct uvd *uvd, int framenum) | |||
| 1850 | int n; | 1884 | int n; |
| 1851 | 1885 | ||
| 1852 | if (uvd->debug > 1) | 1886 | if (uvd->debug > 1) |
| 1853 | info("usbvideo_NewFrame($%p,%d.)", uvd, framenum); | 1887 | dev_info(&uvd->dev->dev, "usbvideo_NewFrame($%p,%d.)\n", uvd, |
| 1888 | framenum); | ||
| 1854 | 1889 | ||
| 1855 | /* If we're not grabbing a frame right now and the other frame is */ | 1890 | /* If we're not grabbing a frame right now and the other frame is */ |
| 1856 | /* ready to be grabbed into, then use it instead */ | 1891 | /* ready to be grabbed into, then use it instead */ |
| @@ -1955,12 +1990,14 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
| 1955 | struct usbvideo_frame *frame = &uvd->frame[frameNum]; | 1990 | struct usbvideo_frame *frame = &uvd->frame[frameNum]; |
| 1956 | 1991 | ||
| 1957 | if (uvd->debug >= 2) | 1992 | if (uvd->debug >= 2) |
| 1958 | info("%s($%p,%d.)", __func__, uvd, frameNum); | 1993 | dev_info(&uvd->dev->dev, "%s($%p,%d.)\n", __func__, uvd, |
| 1994 | frameNum); | ||
| 1959 | 1995 | ||
| 1960 | switch (frame->frameState) { | 1996 | switch (frame->frameState) { |
| 1961 | case FrameState_Unused: | 1997 | case FrameState_Unused: |
| 1962 | if (uvd->debug >= 2) | 1998 | if (uvd->debug >= 2) |
| 1963 | info("%s: FrameState_Unused", __func__); | 1999 | dev_info(&uvd->dev->dev, "%s: FrameState_Unused\n", |
| 2000 | __func__); | ||
| 1964 | return -EINVAL; | 2001 | return -EINVAL; |
| 1965 | case FrameState_Ready: | 2002 | case FrameState_Ready: |
| 1966 | case FrameState_Grabbing: | 2003 | case FrameState_Grabbing: |
| @@ -1970,7 +2007,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
| 1970 | redo: | 2007 | redo: |
| 1971 | if (!CAMERA_IS_OPERATIONAL(uvd)) { | 2008 | if (!CAMERA_IS_OPERATIONAL(uvd)) { |
| 1972 | if (uvd->debug >= 2) | 2009 | if (uvd->debug >= 2) |
| 1973 | info("%s: Camera is not operational (1)", __func__); | 2010 | dev_info(&uvd->dev->dev, |
| 2011 | "%s: Camera is not operational (1)\n", | ||
| 2012 | __func__); | ||
| 1974 | return -EIO; | 2013 | return -EIO; |
| 1975 | } | 2014 | } |
| 1976 | ntries = 0; | 2015 | ntries = 0; |
| @@ -1979,24 +2018,33 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
| 1979 | signalPending = signal_pending(current); | 2018 | signalPending = signal_pending(current); |
| 1980 | if (!CAMERA_IS_OPERATIONAL(uvd)) { | 2019 | if (!CAMERA_IS_OPERATIONAL(uvd)) { |
| 1981 | if (uvd->debug >= 2) | 2020 | if (uvd->debug >= 2) |
| 1982 | info("%s: Camera is not operational (2)", __func__); | 2021 | dev_info(&uvd->dev->dev, |
| 2022 | "%s: Camera is not " | ||
| 2023 | "operational (2)\n", __func__); | ||
| 1983 | return -EIO; | 2024 | return -EIO; |
| 1984 | } | 2025 | } |
| 1985 | assert(uvd->fbuf != NULL); | 2026 | assert(uvd->fbuf != NULL); |
| 1986 | if (signalPending) { | 2027 | if (signalPending) { |
| 1987 | if (uvd->debug >= 2) | 2028 | if (uvd->debug >= 2) |
| 1988 | info("%s: Signal=$%08x", __func__, signalPending); | 2029 | dev_info(&uvd->dev->dev, |
| 2030 | "%s: Signal=$%08x\n", __func__, | ||
| 2031 | signalPending); | ||
| 1989 | if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { | 2032 | if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) { |
| 1990 | usbvideo_TestPattern(uvd, 1, 0); | 2033 | usbvideo_TestPattern(uvd, 1, 0); |
| 1991 | uvd->curframe = -1; | 2034 | uvd->curframe = -1; |
| 1992 | uvd->stats.frame_num++; | 2035 | uvd->stats.frame_num++; |
| 1993 | if (uvd->debug >= 2) | 2036 | if (uvd->debug >= 2) |
| 1994 | info("%s: Forced test pattern screen", __func__); | 2037 | dev_info(&uvd->dev->dev, |
| 2038 | "%s: Forced test " | ||
| 2039 | "pattern screen\n", | ||
| 2040 | __func__); | ||
| 1995 | return 0; | 2041 | return 0; |
| 1996 | } else { | 2042 | } else { |
| 1997 | /* Standard answer: Interrupted! */ | 2043 | /* Standard answer: Interrupted! */ |
| 1998 | if (uvd->debug >= 2) | 2044 | if (uvd->debug >= 2) |
| 1999 | info("%s: Interrupted!", __func__); | 2045 | dev_info(&uvd->dev->dev, |
| 2046 | "%s: Interrupted!\n", | ||
| 2047 | __func__); | ||
| 2000 | return -EINTR; | 2048 | return -EINTR; |
| 2001 | } | 2049 | } |
| 2002 | } else { | 2050 | } else { |
| @@ -2010,8 +2058,10 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
| 2010 | } | 2058 | } |
| 2011 | } while (frame->frameState == FrameState_Grabbing); | 2059 | } while (frame->frameState == FrameState_Grabbing); |
| 2012 | if (uvd->debug >= 2) { | 2060 | if (uvd->debug >= 2) { |
| 2013 | info("%s: Grabbing done; state=%d. (%lu. bytes)", | 2061 | dev_info(&uvd->dev->dev, |
| 2014 | __func__, frame->frameState, frame->seqRead_Length); | 2062 | "%s: Grabbing done; state=%d. (%lu. bytes)\n", |
| 2063 | __func__, frame->frameState, | ||
| 2064 | frame->seqRead_Length); | ||
| 2015 | } | 2065 | } |
| 2016 | if (frame->frameState == FrameState_Error) { | 2066 | if (frame->frameState == FrameState_Error) { |
| 2017 | int ret = usbvideo_NewFrame(uvd, frameNum); | 2067 | int ret = usbvideo_NewFrame(uvd, frameNum); |
| @@ -2048,7 +2098,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
| 2048 | } | 2098 | } |
| 2049 | frame->frameState = FrameState_Done_Hold; | 2099 | frame->frameState = FrameState_Done_Hold; |
| 2050 | if (uvd->debug >= 2) | 2100 | if (uvd->debug >= 2) |
| 2051 | info("%s: Entered FrameState_Done_Hold state.", __func__); | 2101 | dev_info(&uvd->dev->dev, |
| 2102 | "%s: Entered FrameState_Done_Hold state.\n", | ||
| 2103 | __func__); | ||
| 2052 | return 0; | 2104 | return 0; |
| 2053 | 2105 | ||
| 2054 | case FrameState_Done_Hold: | 2106 | case FrameState_Done_Hold: |
| @@ -2059,7 +2111,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum) | |||
| 2059 | * it will be released back into the wild to roam freely. | 2111 | * it will be released back into the wild to roam freely. |
| 2060 | */ | 2112 | */ |
| 2061 | if (uvd->debug >= 2) | 2113 | if (uvd->debug >= 2) |
| 2062 | info("%s: FrameState_Done_Hold state.", __func__); | 2114 | dev_info(&uvd->dev->dev, |
| 2115 | "%s: FrameState_Done_Hold state.\n", | ||
| 2116 | __func__); | ||
| 2063 | return 0; | 2117 | return 0; |
| 2064 | } | 2118 | } |
| 2065 | 2119 | ||
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 2eb45829791c..7a127d6bfdee 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c | |||
| @@ -472,9 +472,8 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign | |||
| 472 | static int | 472 | static int |
| 473 | vicam_open(struct inode *inode, struct file *file) | 473 | vicam_open(struct inode *inode, struct file *file) |
| 474 | { | 474 | { |
| 475 | struct video_device *dev = video_devdata(file); | 475 | struct vicam_camera *cam = video_drvdata(file); |
| 476 | struct vicam_camera *cam = | 476 | |
| 477 | (struct vicam_camera *) dev->priv; | ||
| 478 | DBG("open\n"); | 477 | DBG("open\n"); |
| 479 | 478 | ||
| 480 | if (!cam) { | 479 | if (!cam) { |
| @@ -488,20 +487,24 @@ vicam_open(struct inode *inode, struct file *file) | |||
| 488 | * rely on this fact forever. | 487 | * rely on this fact forever. |
| 489 | */ | 488 | */ |
| 490 | 489 | ||
| 490 | lock_kernel(); | ||
| 491 | if (cam->open_count > 0) { | 491 | if (cam->open_count > 0) { |
| 492 | printk(KERN_INFO | 492 | printk(KERN_INFO |
| 493 | "vicam_open called on already opened camera"); | 493 | "vicam_open called on already opened camera"); |
| 494 | unlock_kernel(); | ||
| 494 | return -EBUSY; | 495 | return -EBUSY; |
| 495 | } | 496 | } |
| 496 | 497 | ||
| 497 | cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); | 498 | cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); |
| 498 | if (!cam->raw_image) { | 499 | if (!cam->raw_image) { |
| 500 | unlock_kernel(); | ||
| 499 | return -ENOMEM; | 501 | return -ENOMEM; |
| 500 | } | 502 | } |
| 501 | 503 | ||
| 502 | cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); | 504 | cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); |
| 503 | if (!cam->framebuf) { | 505 | if (!cam->framebuf) { |
| 504 | kfree(cam->raw_image); | 506 | kfree(cam->raw_image); |
| 507 | unlock_kernel(); | ||
| 505 | return -ENOMEM; | 508 | return -ENOMEM; |
| 506 | } | 509 | } |
| 507 | 510 | ||
| @@ -509,6 +512,7 @@ vicam_open(struct inode *inode, struct file *file) | |||
| 509 | if (!cam->cntrlbuf) { | 512 | if (!cam->cntrlbuf) { |
| 510 | kfree(cam->raw_image); | 513 | kfree(cam->raw_image); |
| 511 | rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); | 514 | rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); |
| 515 | unlock_kernel(); | ||
| 512 | return -ENOMEM; | 516 | return -ENOMEM; |
| 513 | } | 517 | } |
| 514 | 518 | ||
| @@ -526,6 +530,7 @@ vicam_open(struct inode *inode, struct file *file) | |||
| 526 | cam->open_count++; | 530 | cam->open_count++; |
| 527 | 531 | ||
| 528 | file->private_data = cam; | 532 | file->private_data = cam; |
| 533 | unlock_kernel(); | ||
| 529 | 534 | ||
| 530 | return 0; | 535 | return 0; |
| 531 | } | 536 | } |
| @@ -795,6 +800,7 @@ static struct video_device vicam_template = { | |||
| 795 | .name = "ViCam-based USB Camera", | 800 | .name = "ViCam-based USB Camera", |
| 796 | .fops = &vicam_fops, | 801 | .fops = &vicam_fops, |
| 797 | .minor = -1, | 802 | .minor = -1, |
| 803 | .release = video_device_release_empty, | ||
| 798 | }; | 804 | }; |
| 799 | 805 | ||
| 800 | /* table of devices that work with this driver */ | 806 | /* table of devices that work with this driver */ |
| @@ -859,9 +865,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) | |||
| 859 | 865 | ||
| 860 | mutex_init(&cam->cam_lock); | 866 | mutex_init(&cam->cam_lock); |
| 861 | 867 | ||
| 862 | memcpy(&cam->vdev, &vicam_template, | 868 | memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template)); |
| 863 | sizeof (vicam_template)); | 869 | video_set_drvdata(&cam->vdev, cam); |
| 864 | cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only | ||
| 865 | 870 | ||
| 866 | cam->udev = dev; | 871 | cam->udev = dev; |
| 867 | cam->bulkEndpoint = bulkEndpoint; | 872 | cam->bulkEndpoint = bulkEndpoint; |
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index c317ed7a8482..b26b563a0b0a 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
| @@ -84,7 +84,8 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]"); | |||
| 84 | #ifdef USBVISION_DEBUG | 84 | #ifdef USBVISION_DEBUG |
| 85 | #define PDEBUG(level, fmt, args...) { \ | 85 | #define PDEBUG(level, fmt, args...) { \ |
| 86 | if (core_debug & (level)) \ | 86 | if (core_debug & (level)) \ |
| 87 | info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ | 87 | printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ |
| 88 | __func__, __LINE__ , ## args); \ | ||
| 88 | } | 89 | } |
| 89 | #else | 90 | #else |
| 90 | #define PDEBUG(level, fmt, args...) do {} while(0) | 91 | #define PDEBUG(level, fmt, args...) do {} while(0) |
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index a6d00858b07e..92427fdc1459 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
| @@ -47,7 +47,8 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | |||
| 47 | 47 | ||
| 48 | #define PDEBUG(level, fmt, args...) { \ | 48 | #define PDEBUG(level, fmt, args...) { \ |
| 49 | if (i2c_debug & (level)) \ | 49 | if (i2c_debug & (level)) \ |
| 50 | info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ | 50 | printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ |
| 51 | __func__, __LINE__ , ## args); \ | ||
| 51 | } | 52 | } |
| 52 | 53 | ||
| 53 | static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, | 54 | static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf, |
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index b977116a0dd9..e10b256aeba4 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
| @@ -98,7 +98,8 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL) | |||
| 98 | #ifdef USBVISION_DEBUG | 98 | #ifdef USBVISION_DEBUG |
| 99 | #define PDEBUG(level, fmt, args...) { \ | 99 | #define PDEBUG(level, fmt, args...) { \ |
| 100 | if (video_debug & (level)) \ | 100 | if (video_debug & (level)) \ |
| 101 | info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \ | 101 | printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \ |
| 102 | __func__, __LINE__ , ## args); \ | ||
| 102 | } | 103 | } |
| 103 | #else | 104 | #else |
| 104 | #define PDEBUG(level, fmt, args...) do {} while(0) | 105 | #define PDEBUG(level, fmt, args...) do {} while(0) |
| @@ -360,13 +361,12 @@ static void usbvision_remove_sysfs(struct video_device *vdev) | |||
| 360 | */ | 361 | */ |
| 361 | static int usbvision_v4l2_open(struct inode *inode, struct file *file) | 362 | static int usbvision_v4l2_open(struct inode *inode, struct file *file) |
| 362 | { | 363 | { |
| 363 | struct video_device *dev = video_devdata(file); | 364 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 364 | struct usb_usbvision *usbvision = | ||
| 365 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 366 | int errCode = 0; | 365 | int errCode = 0; |
| 367 | 366 | ||
| 368 | PDEBUG(DBG_IO, "open"); | 367 | PDEBUG(DBG_IO, "open"); |
| 369 | 368 | ||
| 369 | lock_kernel(); | ||
| 370 | usbvision_reset_powerOffTimer(usbvision); | 370 | usbvision_reset_powerOffTimer(usbvision); |
| 371 | 371 | ||
| 372 | if (usbvision->user) | 372 | if (usbvision->user) |
| @@ -424,6 +424,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) | |||
| 424 | usbvision_empty_framequeues(usbvision); | 424 | usbvision_empty_framequeues(usbvision); |
| 425 | 425 | ||
| 426 | PDEBUG(DBG_IO, "success"); | 426 | PDEBUG(DBG_IO, "success"); |
| 427 | unlock_kernel(); | ||
| 427 | return errCode; | 428 | return errCode; |
| 428 | } | 429 | } |
| 429 | 430 | ||
| @@ -437,9 +438,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) | |||
| 437 | */ | 438 | */ |
| 438 | static int usbvision_v4l2_close(struct inode *inode, struct file *file) | 439 | static int usbvision_v4l2_close(struct inode *inode, struct file *file) |
| 439 | { | 440 | { |
| 440 | struct video_device *dev = video_devdata(file); | 441 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 441 | struct usb_usbvision *usbvision = | ||
| 442 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 443 | 442 | ||
| 444 | PDEBUG(DBG_IO, "close"); | 443 | PDEBUG(DBG_IO, "close"); |
| 445 | mutex_lock(&usbvision->lock); | 444 | mutex_lock(&usbvision->lock); |
| @@ -484,9 +483,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) | |||
| 484 | static int vidioc_g_register (struct file *file, void *priv, | 483 | static int vidioc_g_register (struct file *file, void *priv, |
| 485 | struct v4l2_register *reg) | 484 | struct v4l2_register *reg) |
| 486 | { | 485 | { |
| 487 | struct video_device *dev = video_devdata(file); | 486 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 488 | struct usb_usbvision *usbvision = | ||
| 489 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 490 | int errCode; | 487 | int errCode; |
| 491 | 488 | ||
| 492 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) | 489 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) |
| @@ -505,9 +502,7 @@ static int vidioc_g_register (struct file *file, void *priv, | |||
| 505 | static int vidioc_s_register (struct file *file, void *priv, | 502 | static int vidioc_s_register (struct file *file, void *priv, |
| 506 | struct v4l2_register *reg) | 503 | struct v4l2_register *reg) |
| 507 | { | 504 | { |
| 508 | struct video_device *dev = video_devdata(file); | 505 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 509 | struct usb_usbvision *usbvision = | ||
| 510 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 511 | int errCode; | 506 | int errCode; |
| 512 | 507 | ||
| 513 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) | 508 | if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) |
| @@ -526,9 +521,7 @@ static int vidioc_s_register (struct file *file, void *priv, | |||
| 526 | static int vidioc_querycap (struct file *file, void *priv, | 521 | static int vidioc_querycap (struct file *file, void *priv, |
| 527 | struct v4l2_capability *vc) | 522 | struct v4l2_capability *vc) |
| 528 | { | 523 | { |
| 529 | struct video_device *dev = video_devdata(file); | 524 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 530 | struct usb_usbvision *usbvision = | ||
| 531 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 532 | 525 | ||
| 533 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); | 526 | strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); |
| 534 | strlcpy(vc->card, | 527 | strlcpy(vc->card, |
| @@ -548,9 +541,7 @@ static int vidioc_querycap (struct file *file, void *priv, | |||
| 548 | static int vidioc_enum_input (struct file *file, void *priv, | 541 | static int vidioc_enum_input (struct file *file, void *priv, |
| 549 | struct v4l2_input *vi) | 542 | struct v4l2_input *vi) |
| 550 | { | 543 | { |
| 551 | struct video_device *dev = video_devdata(file); | 544 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 552 | struct usb_usbvision *usbvision = | ||
| 553 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 554 | int chan; | 545 | int chan; |
| 555 | 546 | ||
| 556 | if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) | 547 | if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) ) |
| @@ -603,9 +594,7 @@ static int vidioc_enum_input (struct file *file, void *priv, | |||
| 603 | 594 | ||
| 604 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) | 595 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) |
| 605 | { | 596 | { |
| 606 | struct video_device *dev = video_devdata(file); | 597 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 607 | struct usb_usbvision *usbvision = | ||
| 608 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 609 | 598 | ||
| 610 | *input = usbvision->ctl_input; | 599 | *input = usbvision->ctl_input; |
| 611 | return 0; | 600 | return 0; |
| @@ -613,9 +602,7 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *input) | |||
| 613 | 602 | ||
| 614 | static int vidioc_s_input (struct file *file, void *priv, unsigned int input) | 603 | static int vidioc_s_input (struct file *file, void *priv, unsigned int input) |
| 615 | { | 604 | { |
| 616 | struct video_device *dev = video_devdata(file); | 605 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 617 | struct usb_usbvision *usbvision = | ||
| 618 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 619 | 606 | ||
| 620 | if ((input >= usbvision->video_inputs) || (input < 0) ) | 607 | if ((input >= usbvision->video_inputs) || (input < 0) ) |
| 621 | return -EINVAL; | 608 | return -EINVAL; |
| @@ -632,9 +619,8 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int input) | |||
| 632 | 619 | ||
| 633 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) | 620 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) |
| 634 | { | 621 | { |
| 635 | struct video_device *dev = video_devdata(file); | 622 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 636 | struct usb_usbvision *usbvision = | 623 | |
| 637 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 638 | usbvision->tvnormId=*id; | 624 | usbvision->tvnormId=*id; |
| 639 | 625 | ||
| 640 | mutex_lock(&usbvision->lock); | 626 | mutex_lock(&usbvision->lock); |
| @@ -650,9 +636,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) | |||
| 650 | static int vidioc_g_tuner (struct file *file, void *priv, | 636 | static int vidioc_g_tuner (struct file *file, void *priv, |
| 651 | struct v4l2_tuner *vt) | 637 | struct v4l2_tuner *vt) |
| 652 | { | 638 | { |
| 653 | struct video_device *dev = video_devdata(file); | 639 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 654 | struct usb_usbvision *usbvision = | ||
| 655 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 656 | 640 | ||
| 657 | if (!usbvision->have_tuner || vt->index) // Only tuner 0 | 641 | if (!usbvision->have_tuner || vt->index) // Only tuner 0 |
| 658 | return -EINVAL; | 642 | return -EINVAL; |
| @@ -671,9 +655,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, | |||
| 671 | static int vidioc_s_tuner (struct file *file, void *priv, | 655 | static int vidioc_s_tuner (struct file *file, void *priv, |
| 672 | struct v4l2_tuner *vt) | 656 | struct v4l2_tuner *vt) |
| 673 | { | 657 | { |
| 674 | struct video_device *dev = video_devdata(file); | 658 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 675 | struct usb_usbvision *usbvision = | ||
| 676 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 677 | 659 | ||
| 678 | // Only no or one tuner for now | 660 | // Only no or one tuner for now |
| 679 | if (!usbvision->have_tuner || vt->index) | 661 | if (!usbvision->have_tuner || vt->index) |
| @@ -687,9 +669,7 @@ static int vidioc_s_tuner (struct file *file, void *priv, | |||
| 687 | static int vidioc_g_frequency (struct file *file, void *priv, | 669 | static int vidioc_g_frequency (struct file *file, void *priv, |
| 688 | struct v4l2_frequency *freq) | 670 | struct v4l2_frequency *freq) |
| 689 | { | 671 | { |
| 690 | struct video_device *dev = video_devdata(file); | 672 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 691 | struct usb_usbvision *usbvision = | ||
| 692 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 693 | 673 | ||
| 694 | freq->tuner = 0; // Only one tuner | 674 | freq->tuner = 0; // Only one tuner |
| 695 | if(usbvision->radio) { | 675 | if(usbvision->radio) { |
| @@ -705,9 +685,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, | |||
| 705 | static int vidioc_s_frequency (struct file *file, void *priv, | 685 | static int vidioc_s_frequency (struct file *file, void *priv, |
| 706 | struct v4l2_frequency *freq) | 686 | struct v4l2_frequency *freq) |
| 707 | { | 687 | { |
| 708 | struct video_device *dev = video_devdata(file); | 688 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 709 | struct usb_usbvision *usbvision = | ||
| 710 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 711 | 689 | ||
| 712 | // Only no or one tuner for now | 690 | // Only no or one tuner for now |
| 713 | if (!usbvision->have_tuner || freq->tuner) | 691 | if (!usbvision->have_tuner || freq->tuner) |
| @@ -721,9 +699,7 @@ static int vidioc_s_frequency (struct file *file, void *priv, | |||
| 721 | 699 | ||
| 722 | static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) | 700 | static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a) |
| 723 | { | 701 | { |
| 724 | struct video_device *dev = video_devdata(file); | 702 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 725 | struct usb_usbvision *usbvision = | ||
| 726 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 727 | 703 | ||
| 728 | memset(a,0,sizeof(*a)); | 704 | memset(a,0,sizeof(*a)); |
| 729 | if(usbvision->radio) { | 705 | if(usbvision->radio) { |
| @@ -748,9 +724,7 @@ static int vidioc_s_audio (struct file *file, void *fh, | |||
| 748 | static int vidioc_queryctrl (struct file *file, void *priv, | 724 | static int vidioc_queryctrl (struct file *file, void *priv, |
| 749 | struct v4l2_queryctrl *ctrl) | 725 | struct v4l2_queryctrl *ctrl) |
| 750 | { | 726 | { |
| 751 | struct video_device *dev = video_devdata(file); | 727 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 752 | struct usb_usbvision *usbvision = | ||
| 753 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 754 | int id=ctrl->id; | 728 | int id=ctrl->id; |
| 755 | 729 | ||
| 756 | memset(ctrl,0,sizeof(*ctrl)); | 730 | memset(ctrl,0,sizeof(*ctrl)); |
| @@ -767,9 +741,7 @@ static int vidioc_queryctrl (struct file *file, void *priv, | |||
| 767 | static int vidioc_g_ctrl (struct file *file, void *priv, | 741 | static int vidioc_g_ctrl (struct file *file, void *priv, |
| 768 | struct v4l2_control *ctrl) | 742 | struct v4l2_control *ctrl) |
| 769 | { | 743 | { |
| 770 | struct video_device *dev = video_devdata(file); | 744 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 771 | struct usb_usbvision *usbvision = | ||
| 772 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 773 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); | 745 | call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl); |
| 774 | 746 | ||
| 775 | return 0; | 747 | return 0; |
| @@ -778,9 +750,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv, | |||
| 778 | static int vidioc_s_ctrl (struct file *file, void *priv, | 750 | static int vidioc_s_ctrl (struct file *file, void *priv, |
| 779 | struct v4l2_control *ctrl) | 751 | struct v4l2_control *ctrl) |
| 780 | { | 752 | { |
| 781 | struct video_device *dev = video_devdata(file); | 753 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 782 | struct usb_usbvision *usbvision = | ||
| 783 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 784 | call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); | 754 | call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl); |
| 785 | 755 | ||
| 786 | return 0; | 756 | return 0; |
| @@ -789,9 +759,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv, | |||
| 789 | static int vidioc_reqbufs (struct file *file, | 759 | static int vidioc_reqbufs (struct file *file, |
| 790 | void *priv, struct v4l2_requestbuffers *vr) | 760 | void *priv, struct v4l2_requestbuffers *vr) |
| 791 | { | 761 | { |
| 792 | struct video_device *dev = video_devdata(file); | 762 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 793 | struct usb_usbvision *usbvision = | ||
| 794 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 795 | int ret; | 763 | int ret; |
| 796 | 764 | ||
| 797 | RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); | 765 | RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES); |
| @@ -819,9 +787,7 @@ static int vidioc_reqbufs (struct file *file, | |||
| 819 | static int vidioc_querybuf (struct file *file, | 787 | static int vidioc_querybuf (struct file *file, |
| 820 | void *priv, struct v4l2_buffer *vb) | 788 | void *priv, struct v4l2_buffer *vb) |
| 821 | { | 789 | { |
| 822 | struct video_device *dev = video_devdata(file); | 790 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 823 | struct usb_usbvision *usbvision = | ||
| 824 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 825 | struct usbvision_frame *frame; | 791 | struct usbvision_frame *frame; |
| 826 | 792 | ||
| 827 | /* FIXME : must control | 793 | /* FIXME : must control |
| @@ -857,9 +823,7 @@ static int vidioc_querybuf (struct file *file, | |||
| 857 | 823 | ||
| 858 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) | 824 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) |
| 859 | { | 825 | { |
| 860 | struct video_device *dev = video_devdata(file); | 826 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 861 | struct usb_usbvision *usbvision = | ||
| 862 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 863 | struct usbvision_frame *frame; | 827 | struct usbvision_frame *frame; |
| 864 | unsigned long lock_flags; | 828 | unsigned long lock_flags; |
| 865 | 829 | ||
| @@ -896,9 +860,7 @@ static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb) | |||
| 896 | 860 | ||
| 897 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) | 861 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) |
| 898 | { | 862 | { |
| 899 | struct video_device *dev = video_devdata(file); | 863 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 900 | struct usb_usbvision *usbvision = | ||
| 901 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 902 | int ret; | 864 | int ret; |
| 903 | struct usbvision_frame *f; | 865 | struct usbvision_frame *f; |
| 904 | unsigned long lock_flags; | 866 | unsigned long lock_flags; |
| @@ -939,9 +901,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb) | |||
| 939 | 901 | ||
| 940 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | 902 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
| 941 | { | 903 | { |
| 942 | struct video_device *dev = video_devdata(file); | 904 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 943 | struct usb_usbvision *usbvision = | ||
| 944 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 945 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | 905 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| 946 | 906 | ||
| 947 | usbvision->streaming = Stream_On; | 907 | usbvision->streaming = Stream_On; |
| @@ -953,9 +913,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | |||
| 953 | static int vidioc_streamoff(struct file *file, | 913 | static int vidioc_streamoff(struct file *file, |
| 954 | void *priv, enum v4l2_buf_type type) | 914 | void *priv, enum v4l2_buf_type type) |
| 955 | { | 915 | { |
| 956 | struct video_device *dev = video_devdata(file); | 916 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 957 | struct usb_usbvision *usbvision = | ||
| 958 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 959 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; | 917 | int b=V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| 960 | 918 | ||
| 961 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 919 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
| @@ -988,9 +946,7 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, | |||
| 988 | static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, | 946 | static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, |
| 989 | struct v4l2_format *vf) | 947 | struct v4l2_format *vf) |
| 990 | { | 948 | { |
| 991 | struct video_device *dev = video_devdata(file); | 949 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 992 | struct usb_usbvision *usbvision = | ||
| 993 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 994 | vf->fmt.pix.width = usbvision->curwidth; | 950 | vf->fmt.pix.width = usbvision->curwidth; |
| 995 | vf->fmt.pix.height = usbvision->curheight; | 951 | vf->fmt.pix.height = usbvision->curheight; |
| 996 | vf->fmt.pix.pixelformat = usbvision->palette.format; | 952 | vf->fmt.pix.pixelformat = usbvision->palette.format; |
| @@ -1006,9 +962,7 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, | |||
| 1006 | static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, | 962 | static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, |
| 1007 | struct v4l2_format *vf) | 963 | struct v4l2_format *vf) |
| 1008 | { | 964 | { |
| 1009 | struct video_device *dev = video_devdata(file); | 965 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 1010 | struct usb_usbvision *usbvision = | ||
| 1011 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 1012 | int formatIdx; | 966 | int formatIdx; |
| 1013 | 967 | ||
| 1014 | /* Find requested format in available ones */ | 968 | /* Find requested format in available ones */ |
| @@ -1036,9 +990,7 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, | |||
| 1036 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 990 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
| 1037 | struct v4l2_format *vf) | 991 | struct v4l2_format *vf) |
| 1038 | { | 992 | { |
| 1039 | struct video_device *dev = video_devdata(file); | 993 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 1040 | struct usb_usbvision *usbvision = | ||
| 1041 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 1042 | int ret; | 994 | int ret; |
| 1043 | 995 | ||
| 1044 | if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) { | 996 | if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) { |
| @@ -1066,9 +1018,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
| 1066 | static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, | 1018 | static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, |
| 1067 | size_t count, loff_t *ppos) | 1019 | size_t count, loff_t *ppos) |
| 1068 | { | 1020 | { |
| 1069 | struct video_device *dev = video_devdata(file); | 1021 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 1070 | struct usb_usbvision *usbvision = | ||
| 1071 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 1072 | int noblock = file->f_flags & O_NONBLOCK; | 1022 | int noblock = file->f_flags & O_NONBLOCK; |
| 1073 | unsigned long lock_flags; | 1023 | unsigned long lock_flags; |
| 1074 | 1024 | ||
| @@ -1177,10 +1127,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 1177 | start = vma->vm_start; | 1127 | start = vma->vm_start; |
| 1178 | void *pos; | 1128 | void *pos; |
| 1179 | u32 i; | 1129 | u32 i; |
| 1180 | 1130 | struct usb_usbvision *usbvision = video_drvdata(file); | |
| 1181 | struct video_device *dev = video_devdata(file); | ||
| 1182 | struct usb_usbvision *usbvision = | ||
| 1183 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 1184 | 1131 | ||
| 1185 | PDEBUG(DBG_MMAP, "mmap"); | 1132 | PDEBUG(DBG_MMAP, "mmap"); |
| 1186 | 1133 | ||
| @@ -1237,9 +1184,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 1237 | */ | 1184 | */ |
| 1238 | static int usbvision_radio_open(struct inode *inode, struct file *file) | 1185 | static int usbvision_radio_open(struct inode *inode, struct file *file) |
| 1239 | { | 1186 | { |
| 1240 | struct video_device *dev = video_devdata(file); | 1187 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 1241 | struct usb_usbvision *usbvision = | ||
| 1242 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 1243 | int errCode = 0; | 1188 | int errCode = 0; |
| 1244 | 1189 | ||
| 1245 | PDEBUG(DBG_IO, "%s:", __func__); | 1190 | PDEBUG(DBG_IO, "%s:", __func__); |
| @@ -1289,9 +1234,7 @@ out: | |||
| 1289 | 1234 | ||
| 1290 | static int usbvision_radio_close(struct inode *inode, struct file *file) | 1235 | static int usbvision_radio_close(struct inode *inode, struct file *file) |
| 1291 | { | 1236 | { |
| 1292 | struct video_device *dev = video_devdata(file); | 1237 | struct usb_usbvision *usbvision = video_drvdata(file); |
| 1293 | struct usb_usbvision *usbvision = | ||
| 1294 | (struct usb_usbvision *) video_get_drvdata(dev); | ||
| 1295 | int errCode = 0; | 1238 | int errCode = 0; |
| 1296 | 1239 | ||
| 1297 | PDEBUG(DBG_IO, ""); | 1240 | PDEBUG(DBG_IO, ""); |
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index feab12aa2c7b..f16aafe9cf14 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
| @@ -83,6 +83,22 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
| 83 | }, | 83 | }, |
| 84 | { | 84 | { |
| 85 | .entity = UVC_GUID_UVC_PROCESSING, | 85 | .entity = UVC_GUID_UVC_PROCESSING, |
| 86 | .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, | ||
| 87 | .index = 6, | ||
| 88 | .size = 2, | ||
| 89 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 90 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
| 91 | }, | ||
| 92 | { | ||
| 93 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 94 | .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, | ||
| 95 | .index = 7, | ||
| 96 | .size = 4, | ||
| 97 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 98 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
| 99 | }, | ||
| 100 | { | ||
| 101 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 86 | .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, | 102 | .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, |
| 87 | .index = 8, | 103 | .index = 8, |
| 88 | .size = 2, | 104 | .size = 2, |
| @@ -114,6 +130,60 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
| 114 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 130 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, |
| 115 | }, | 131 | }, |
| 116 | { | 132 | { |
| 133 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 134 | .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, | ||
| 135 | .index = 12, | ||
| 136 | .size = 1, | ||
| 137 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
| 138 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
| 139 | }, | ||
| 140 | { | ||
| 141 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 142 | .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, | ||
| 143 | .index = 13, | ||
| 144 | .size = 1, | ||
| 145 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
| 146 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
| 147 | }, | ||
| 148 | { | ||
| 149 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 150 | .selector = PU_DIGITAL_MULTIPLIER_CONTROL, | ||
| 151 | .index = 14, | ||
| 152 | .size = 2, | ||
| 153 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 154 | | UVC_CONTROL_RESTORE, | ||
| 155 | }, | ||
| 156 | { | ||
| 157 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 158 | .selector = PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, | ||
| 159 | .index = 15, | ||
| 160 | .size = 2, | ||
| 161 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 162 | | UVC_CONTROL_RESTORE, | ||
| 163 | }, | ||
| 164 | { | ||
| 165 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 166 | .selector = PU_ANALOG_VIDEO_STANDARD_CONTROL, | ||
| 167 | .index = 16, | ||
| 168 | .size = 1, | ||
| 169 | .flags = UVC_CONTROL_GET_CUR, | ||
| 170 | }, | ||
| 171 | { | ||
| 172 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 173 | .selector = PU_ANALOG_LOCK_STATUS_CONTROL, | ||
| 174 | .index = 17, | ||
| 175 | .size = 1, | ||
| 176 | .flags = UVC_CONTROL_GET_CUR, | ||
| 177 | }, | ||
| 178 | { | ||
| 179 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 180 | .selector = CT_SCANNING_MODE_CONTROL, | ||
| 181 | .index = 0, | ||
| 182 | .size = 1, | ||
| 183 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
| 184 | | UVC_CONTROL_RESTORE, | ||
| 185 | }, | ||
| 186 | { | ||
| 117 | .entity = UVC_GUID_UVC_CAMERA, | 187 | .entity = UVC_GUID_UVC_CAMERA, |
| 118 | .selector = CT_AE_MODE_CONTROL, | 188 | .selector = CT_AE_MODE_CONTROL, |
| 119 | .index = 1, | 189 | .index = 1, |
| @@ -140,6 +210,14 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
| 140 | }, | 210 | }, |
| 141 | { | 211 | { |
| 142 | .entity = UVC_GUID_UVC_CAMERA, | 212 | .entity = UVC_GUID_UVC_CAMERA, |
| 213 | .selector = CT_EXPOSURE_TIME_RELATIVE_CONTROL, | ||
| 214 | .index = 4, | ||
| 215 | .size = 1, | ||
| 216 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
| 217 | | UVC_CONTROL_RESTORE, | ||
| 218 | }, | ||
| 219 | { | ||
| 220 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 143 | .selector = CT_FOCUS_ABSOLUTE_CONTROL, | 221 | .selector = CT_FOCUS_ABSOLUTE_CONTROL, |
| 144 | .index = 5, | 222 | .index = 5, |
| 145 | .size = 2, | 223 | .size = 2, |
| @@ -148,42 +226,90 @@ static struct uvc_control_info uvc_ctrls[] = { | |||
| 148 | }, | 226 | }, |
| 149 | { | 227 | { |
| 150 | .entity = UVC_GUID_UVC_CAMERA, | 228 | .entity = UVC_GUID_UVC_CAMERA, |
| 151 | .selector = CT_FOCUS_AUTO_CONTROL, | 229 | .selector = CT_FOCUS_RELATIVE_CONTROL, |
| 152 | .index = 17, | 230 | .index = 6, |
| 153 | .size = 1, | 231 | .size = 2, |
| 154 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 232 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE |
| 155 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 233 | | UVC_CONTROL_AUTO_UPDATE, |
| 156 | }, | 234 | }, |
| 157 | { | 235 | { |
| 158 | .entity = UVC_GUID_UVC_PROCESSING, | 236 | .entity = UVC_GUID_UVC_CAMERA, |
| 159 | .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, | 237 | .selector = CT_IRIS_ABSOLUTE_CONTROL, |
| 160 | .index = 12, | 238 | .index = 7, |
| 239 | .size = 2, | ||
| 240 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 241 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
| 242 | }, | ||
| 243 | { | ||
| 244 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 245 | .selector = CT_IRIS_RELATIVE_CONTROL, | ||
| 246 | .index = 8, | ||
| 161 | .size = 1, | 247 | .size = 1, |
| 162 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 248 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR |
| 163 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 249 | | UVC_CONTROL_AUTO_UPDATE, |
| 164 | }, | 250 | }, |
| 165 | { | 251 | { |
| 166 | .entity = UVC_GUID_UVC_PROCESSING, | 252 | .entity = UVC_GUID_UVC_CAMERA, |
| 167 | .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, | 253 | .selector = CT_ZOOM_ABSOLUTE_CONTROL, |
| 168 | .index = 6, | 254 | .index = 9, |
| 169 | .size = 2, | 255 | .size = 2, |
| 170 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 256 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE |
| 171 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 257 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, |
| 172 | }, | 258 | }, |
| 173 | { | 259 | { |
| 174 | .entity = UVC_GUID_UVC_PROCESSING, | 260 | .entity = UVC_GUID_UVC_CAMERA, |
| 175 | .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, | 261 | .selector = CT_ZOOM_RELATIVE_CONTROL, |
| 262 | .index = 10, | ||
| 263 | .size = 3, | ||
| 264 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 265 | | UVC_CONTROL_AUTO_UPDATE, | ||
| 266 | }, | ||
| 267 | { | ||
| 268 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 269 | .selector = CT_PANTILT_ABSOLUTE_CONTROL, | ||
| 270 | .index = 11, | ||
| 271 | .size = 8, | ||
| 272 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 273 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
| 274 | }, | ||
| 275 | { | ||
| 276 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 277 | .selector = CT_PANTILT_RELATIVE_CONTROL, | ||
| 278 | .index = 12, | ||
| 279 | .size = 4, | ||
| 280 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 281 | | UVC_CONTROL_AUTO_UPDATE, | ||
| 282 | }, | ||
| 283 | { | ||
| 284 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 285 | .selector = CT_ROLL_ABSOLUTE_CONTROL, | ||
| 176 | .index = 13, | 286 | .index = 13, |
| 287 | .size = 2, | ||
| 288 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 289 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
| 290 | }, | ||
| 291 | { | ||
| 292 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 293 | .selector = CT_ROLL_RELATIVE_CONTROL, | ||
| 294 | .index = 14, | ||
| 295 | .size = 2, | ||
| 296 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 297 | | UVC_CONTROL_AUTO_UPDATE, | ||
| 298 | }, | ||
| 299 | { | ||
| 300 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 301 | .selector = CT_FOCUS_AUTO_CONTROL, | ||
| 302 | .index = 17, | ||
| 177 | .size = 1, | 303 | .size = 1, |
| 178 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | 304 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR |
| 179 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | 305 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, |
| 180 | }, | 306 | }, |
| 181 | { | 307 | { |
| 182 | .entity = UVC_GUID_UVC_PROCESSING, | 308 | .entity = UVC_GUID_UVC_CAMERA, |
| 183 | .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, | 309 | .selector = CT_PRIVACY_CONTROL, |
| 184 | .index = 7, | 310 | .index = 18, |
| 185 | .size = 4, | 311 | .size = 1, |
| 186 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | 312 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR |
| 187 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | 313 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, |
| 188 | }, | 314 | }, |
| 189 | }; | 315 | }; |
| @@ -711,7 +837,17 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, | |||
| 711 | 837 | ||
| 712 | for (i = 0; i < entity->ncontrols; ++i) { | 838 | for (i = 0; i < entity->ncontrols; ++i) { |
| 713 | ctrl = &entity->controls[i]; | 839 | ctrl = &entity->controls[i]; |
| 714 | if (ctrl->info == NULL || !ctrl->dirty) | 840 | if (ctrl->info == NULL) |
| 841 | continue; | ||
| 842 | |||
| 843 | /* Reset the loaded flag for auto-update controls that were | ||
| 844 | * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent | ||
| 845 | * uvc_ctrl_get from using the cached value. | ||
| 846 | */ | ||
| 847 | if (ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) | ||
| 848 | ctrl->loaded = 0; | ||
| 849 | |||
| 850 | if (!ctrl->dirty) | ||
| 715 | continue; | 851 | continue; |
| 716 | 852 | ||
| 717 | if (!rollback) | 853 | if (!rollback) |
| @@ -727,9 +863,6 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, | |||
| 727 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | 863 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), |
| 728 | ctrl->info->size); | 864 | ctrl->info->size); |
| 729 | 865 | ||
| 730 | if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) | ||
| 731 | ctrl->loaded = 0; | ||
| 732 | |||
| 733 | ctrl->dirty = 0; | 866 | ctrl->dirty = 0; |
| 734 | 867 | ||
| 735 | if (ret < 0) | 868 | if (ret < 0) |
| @@ -787,8 +920,7 @@ int uvc_ctrl_get(struct uvc_video_device *video, | |||
| 787 | if (ret < 0) | 920 | if (ret < 0) |
| 788 | return ret; | 921 | return ret; |
| 789 | 922 | ||
| 790 | if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) | 923 | ctrl->loaded = 1; |
| 791 | ctrl->loaded = 1; | ||
| 792 | } | 924 | } |
| 793 | 925 | ||
| 794 | xctrl->value = uvc_get_le_value( | 926 | xctrl->value = uvc_get_le_value( |
| @@ -839,8 +971,7 @@ int uvc_ctrl_set(struct uvc_video_device *video, | |||
| 839 | return ret; | 971 | return ret; |
| 840 | } | 972 | } |
| 841 | 973 | ||
| 842 | if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) | 974 | ctrl->loaded = 1; |
| 843 | ctrl->loaded = 1; | ||
| 844 | } | 975 | } |
| 845 | 976 | ||
| 846 | if (!ctrl->dirty) { | 977 | if (!ctrl->dirty) { |
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 7e102034d38d..d7ad060640bc 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
| @@ -1663,7 +1663,7 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 1663 | return uvc_video_suspend(&dev->video); | 1663 | return uvc_video_suspend(&dev->video); |
| 1664 | } | 1664 | } |
| 1665 | 1665 | ||
| 1666 | static int uvc_resume(struct usb_interface *intf) | 1666 | static int __uvc_resume(struct usb_interface *intf, int reset) |
| 1667 | { | 1667 | { |
| 1668 | struct uvc_device *dev = usb_get_intfdata(intf); | 1668 | struct uvc_device *dev = usb_get_intfdata(intf); |
| 1669 | int ret; | 1669 | int ret; |
| @@ -1672,7 +1672,7 @@ static int uvc_resume(struct usb_interface *intf) | |||
| 1672 | intf->cur_altsetting->desc.bInterfaceNumber); | 1672 | intf->cur_altsetting->desc.bInterfaceNumber); |
| 1673 | 1673 | ||
| 1674 | if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { | 1674 | if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { |
| 1675 | if ((ret = uvc_ctrl_resume_device(dev)) < 0) | 1675 | if (reset && (ret = uvc_ctrl_resume_device(dev)) < 0) |
| 1676 | return ret; | 1676 | return ret; |
| 1677 | 1677 | ||
| 1678 | return uvc_status_resume(dev); | 1678 | return uvc_status_resume(dev); |
| @@ -1687,6 +1687,16 @@ static int uvc_resume(struct usb_interface *intf) | |||
| 1687 | return uvc_video_resume(&dev->video); | 1687 | return uvc_video_resume(&dev->video); |
| 1688 | } | 1688 | } |
| 1689 | 1689 | ||
| 1690 | static int uvc_resume(struct usb_interface *intf) | ||
| 1691 | { | ||
| 1692 | return __uvc_resume(intf, 0); | ||
| 1693 | } | ||
| 1694 | |||
| 1695 | static int uvc_reset_resume(struct usb_interface *intf) | ||
| 1696 | { | ||
| 1697 | return __uvc_resume(intf, 1); | ||
| 1698 | } | ||
| 1699 | |||
| 1690 | /* ------------------------------------------------------------------------ | 1700 | /* ------------------------------------------------------------------------ |
| 1691 | * Driver initialization and cleanup | 1701 | * Driver initialization and cleanup |
| 1692 | */ | 1702 | */ |
| @@ -1902,6 +1912,24 @@ static struct usb_device_id uvc_ids[] = { | |||
| 1902 | .bInterfaceSubClass = 1, | 1912 | .bInterfaceSubClass = 1, |
| 1903 | .bInterfaceProtocol = 0, | 1913 | .bInterfaceProtocol = 0, |
| 1904 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | 1914 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, |
| 1915 | /* Compaq Presario B1200 - Bison Electronics */ | ||
| 1916 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1917 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1918 | .idVendor = 0x5986, | ||
| 1919 | .idProduct = 0x0104, | ||
| 1920 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1921 | .bInterfaceSubClass = 1, | ||
| 1922 | .bInterfaceProtocol = 0, | ||
| 1923 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1924 | /* Acer Travelmate 7720 - Bison Electronics */ | ||
| 1925 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1926 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1927 | .idVendor = 0x5986, | ||
| 1928 | .idProduct = 0x0105, | ||
| 1929 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1930 | .bInterfaceSubClass = 1, | ||
| 1931 | .bInterfaceProtocol = 0, | ||
| 1932 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1905 | /* Medion Akoya Mini E1210 - Bison Electronics */ | 1933 | /* Medion Akoya Mini E1210 - Bison Electronics */ |
| 1906 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1934 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
| 1907 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1935 | | USB_DEVICE_ID_MATCH_INT_INFO, |
| @@ -1920,6 +1948,24 @@ static struct usb_device_id uvc_ids[] = { | |||
| 1920 | .bInterfaceSubClass = 1, | 1948 | .bInterfaceSubClass = 1, |
| 1921 | .bInterfaceProtocol = 0, | 1949 | .bInterfaceProtocol = 0, |
| 1922 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | 1950 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, |
| 1951 | /* Fujitsu Amilo SI2636 - Bison Electronics */ | ||
| 1952 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1953 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1954 | .idVendor = 0x5986, | ||
| 1955 | .idProduct = 0x0202, | ||
| 1956 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1957 | .bInterfaceSubClass = 1, | ||
| 1958 | .bInterfaceProtocol = 0, | ||
| 1959 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1960 | /* Advent 4211 - Bison Electronics */ | ||
| 1961 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1962 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1963 | .idVendor = 0x5986, | ||
| 1964 | .idProduct = 0x0203, | ||
| 1965 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1966 | .bInterfaceSubClass = 1, | ||
| 1967 | .bInterfaceProtocol = 0, | ||
| 1968 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1923 | /* Bison Electronics */ | 1969 | /* Bison Electronics */ |
| 1924 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1970 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
| 1925 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1971 | | USB_DEVICE_ID_MATCH_INT_INFO, |
| @@ -1952,6 +1998,7 @@ struct uvc_driver uvc_driver = { | |||
| 1952 | .disconnect = uvc_disconnect, | 1998 | .disconnect = uvc_disconnect, |
| 1953 | .suspend = uvc_suspend, | 1999 | .suspend = uvc_suspend, |
| 1954 | .resume = uvc_resume, | 2000 | .resume = uvc_resume, |
| 2001 | .reset_resume = uvc_reset_resume, | ||
| 1955 | .id_table = uvc_ids, | 2002 | .id_table = uvc_ids, |
| 1956 | .supports_autosuspend = 1, | 2003 | .supports_autosuspend = 1, |
| 1957 | }, | 2004 | }, |
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c index 75e678ac54eb..5d60b264d59a 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/video/uvc/uvc_status.c | |||
| @@ -177,9 +177,15 @@ int uvc_status_init(struct uvc_device *dev) | |||
| 177 | 177 | ||
| 178 | uvc_input_init(dev); | 178 | uvc_input_init(dev); |
| 179 | 179 | ||
| 180 | dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL); | ||
| 181 | if (dev->status == NULL) | ||
| 182 | return -ENOMEM; | ||
| 183 | |||
| 180 | dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); | 184 | dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); |
| 181 | if (dev->int_urb == NULL) | 185 | if (dev->int_urb == NULL) { |
| 186 | kfree(dev->status); | ||
| 182 | return -ENOMEM; | 187 | return -ENOMEM; |
| 188 | } | ||
| 183 | 189 | ||
| 184 | pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); | 190 | pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); |
| 185 | 191 | ||
| @@ -192,7 +198,7 @@ int uvc_status_init(struct uvc_device *dev) | |||
| 192 | interval = fls(interval) - 1; | 198 | interval = fls(interval) - 1; |
| 193 | 199 | ||
| 194 | usb_fill_int_urb(dev->int_urb, dev->udev, pipe, | 200 | usb_fill_int_urb(dev->int_urb, dev->udev, pipe, |
| 195 | dev->status, sizeof dev->status, uvc_status_complete, | 201 | dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete, |
| 196 | dev, interval); | 202 | dev, interval); |
| 197 | 203 | ||
| 198 | return usb_submit_urb(dev->int_urb, GFP_KERNEL); | 204 | return usb_submit_urb(dev->int_urb, GFP_KERNEL); |
| @@ -202,6 +208,7 @@ void uvc_status_cleanup(struct uvc_device *dev) | |||
| 202 | { | 208 | { |
| 203 | usb_kill_urb(dev->int_urb); | 209 | usb_kill_urb(dev->int_urb); |
| 204 | usb_free_urb(dev->int_urb); | 210 | usb_free_urb(dev->int_urb); |
| 211 | kfree(dev->status); | ||
| 205 | uvc_input_cleanup(dev); | 212 | uvc_input_cleanup(dev); |
| 206 | } | 213 | } |
| 207 | 214 | ||
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index d7bd71be40a9..78e4c4e09d89 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
| @@ -400,15 +400,13 @@ static int uvc_has_privileges(struct uvc_fh *handle) | |||
| 400 | 400 | ||
| 401 | static int uvc_v4l2_open(struct inode *inode, struct file *file) | 401 | static int uvc_v4l2_open(struct inode *inode, struct file *file) |
| 402 | { | 402 | { |
| 403 | struct video_device *vdev; | ||
| 404 | struct uvc_video_device *video; | 403 | struct uvc_video_device *video; |
| 405 | struct uvc_fh *handle; | 404 | struct uvc_fh *handle; |
| 406 | int ret = 0; | 405 | int ret = 0; |
| 407 | 406 | ||
| 408 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); | 407 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); |
| 409 | mutex_lock(&uvc_driver.open_mutex); | 408 | mutex_lock(&uvc_driver.open_mutex); |
| 410 | vdev = video_devdata(file); | 409 | video = video_drvdata(file); |
| 411 | video = video_get_drvdata(vdev); | ||
| 412 | 410 | ||
| 413 | if (video->dev->state & UVC_DEV_DISCONNECTED) { | 411 | if (video->dev->state & UVC_DEV_DISCONNECTED) { |
| 414 | ret = -ENODEV; | 412 | ret = -ENODEV; |
| @@ -440,8 +438,7 @@ done: | |||
| 440 | 438 | ||
| 441 | static int uvc_v4l2_release(struct inode *inode, struct file *file) | 439 | static int uvc_v4l2_release(struct inode *inode, struct file *file) |
| 442 | { | 440 | { |
| 443 | struct video_device *vdev = video_devdata(file); | 441 | struct uvc_video_device *video = video_drvdata(file); |
| 444 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
| 445 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; | 442 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; |
| 446 | 443 | ||
| 447 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); | 444 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); |
| @@ -845,10 +842,6 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
| 845 | if (ret < 0) | 842 | if (ret < 0) |
| 846 | return ret; | 843 | return ret; |
| 847 | 844 | ||
| 848 | if (!(video->streaming->cur_format->flags & | ||
| 849 | UVC_FMT_FLAG_COMPRESSED)) | ||
| 850 | video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; | ||
| 851 | |||
| 852 | rb->count = ret; | 845 | rb->count = ret; |
| 853 | ret = 0; | 846 | ret = 0; |
| 854 | break; | 847 | break; |
| @@ -1031,8 +1024,7 @@ static struct vm_operations_struct uvc_vm_ops = { | |||
| 1031 | 1024 | ||
| 1032 | static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | 1025 | static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) |
| 1033 | { | 1026 | { |
| 1034 | struct video_device *vdev = video_devdata(file); | 1027 | struct uvc_video_device *video = video_drvdata(file); |
| 1035 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
| 1036 | struct uvc_buffer *uninitialized_var(buffer); | 1028 | struct uvc_buffer *uninitialized_var(buffer); |
| 1037 | struct page *page; | 1029 | struct page *page; |
| 1038 | unsigned long addr, start, size; | 1030 | unsigned long addr, start, size; |
| @@ -1085,8 +1077,7 @@ done: | |||
| 1085 | 1077 | ||
| 1086 | static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) | 1078 | static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) |
| 1087 | { | 1079 | { |
| 1088 | struct video_device *vdev = video_devdata(file); | 1080 | struct uvc_video_device *video = video_drvdata(file); |
| 1089 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
| 1090 | 1081 | ||
| 1091 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); | 1082 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); |
| 1092 | 1083 | ||
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 6854ac78a161..b7bb23820d80 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
| @@ -455,7 +455,8 @@ static void uvc_video_decode_isoc(struct urb *urb, | |||
| 455 | urb->iso_frame_desc[i].actual_length - ret); | 455 | urb->iso_frame_desc[i].actual_length - ret); |
| 456 | 456 | ||
| 457 | /* Process the header again. */ | 457 | /* Process the header again. */ |
| 458 | uvc_video_decode_end(video, buf, mem, ret); | 458 | uvc_video_decode_end(video, buf, mem, |
| 459 | urb->iso_frame_desc[i].actual_length); | ||
| 459 | 460 | ||
| 460 | if (buf->state == UVC_BUF_STATE_DONE || | 461 | if (buf->state == UVC_BUF_STATE_DONE || |
| 461 | buf->state == UVC_BUF_STATE_ERROR) | 462 | buf->state == UVC_BUF_STATE_ERROR) |
| @@ -512,7 +513,7 @@ static void uvc_video_decode_bulk(struct urb *urb, | |||
| 512 | video->bulk.payload_size >= video->bulk.max_payload_size) { | 513 | video->bulk.payload_size >= video->bulk.max_payload_size) { |
| 513 | if (!video->bulk.skip_payload && buf != NULL) { | 514 | if (!video->bulk.skip_payload && buf != NULL) { |
| 514 | uvc_video_decode_end(video, buf, video->bulk.header, | 515 | uvc_video_decode_end(video, buf, video->bulk.header, |
| 515 | video->bulk.header_size); | 516 | video->bulk.payload_size); |
| 516 | if (buf->state == UVC_BUF_STATE_DONE || | 517 | if (buf->state == UVC_BUF_STATE_DONE || |
| 517 | buf->state == UVC_BUF_STATE_ERROR) | 518 | buf->state == UVC_BUF_STATE_ERROR) |
| 518 | buf = uvc_queue_next_buffer(&video->queue, buf); | 519 | buf = uvc_queue_next_buffer(&video->queue, buf); |
| @@ -655,7 +656,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, | |||
| 655 | if (size > UVC_MAX_FRAME_SIZE) | 656 | if (size > UVC_MAX_FRAME_SIZE) |
| 656 | return -EINVAL; | 657 | return -EINVAL; |
| 657 | 658 | ||
| 658 | npackets = (size + psize - 1) / psize; | 659 | npackets = DIV_ROUND_UP(size, psize); |
| 659 | if (npackets > UVC_MAX_ISO_PACKETS) | 660 | if (npackets > UVC_MAX_ISO_PACKETS) |
| 660 | npackets = UVC_MAX_ISO_PACKETS; | 661 | npackets = UVC_MAX_ISO_PACKETS; |
| 661 | 662 | ||
| @@ -970,6 +971,11 @@ int uvc_video_enable(struct uvc_video_device *video, int enable) | |||
| 970 | return 0; | 971 | return 0; |
| 971 | } | 972 | } |
| 972 | 973 | ||
| 974 | if (video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) | ||
| 975 | video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; | ||
| 976 | else | ||
| 977 | video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; | ||
| 978 | |||
| 973 | if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) | 979 | if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) |
| 974 | return ret; | 980 | return ret; |
| 975 | 981 | ||
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index bafe3406e305..9a6bc1aafb16 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
| @@ -303,6 +303,8 @@ struct uvc_xu_control { | |||
| 303 | #define UVC_MAX_FRAME_SIZE (16*1024*1024) | 303 | #define UVC_MAX_FRAME_SIZE (16*1024*1024) |
| 304 | /* Maximum number of video buffers. */ | 304 | /* Maximum number of video buffers. */ |
| 305 | #define UVC_MAX_VIDEO_BUFFERS 32 | 305 | #define UVC_MAX_VIDEO_BUFFERS 32 |
| 306 | /* Maximum status buffer size in bytes of interrupt URB. */ | ||
| 307 | #define UVC_MAX_STATUS_SIZE 16 | ||
| 306 | 308 | ||
| 307 | #define UVC_CTRL_CONTROL_TIMEOUT 300 | 309 | #define UVC_CTRL_CONTROL_TIMEOUT 300 |
| 308 | #define UVC_CTRL_STREAMING_TIMEOUT 1000 | 310 | #define UVC_CTRL_STREAMING_TIMEOUT 1000 |
| @@ -634,7 +636,7 @@ struct uvc_device { | |||
| 634 | /* Status Interrupt Endpoint */ | 636 | /* Status Interrupt Endpoint */ |
| 635 | struct usb_host_endpoint *int_ep; | 637 | struct usb_host_endpoint *int_ep; |
| 636 | struct urb *int_urb; | 638 | struct urb *int_urb; |
| 637 | __u8 status[16]; | 639 | __u8 *status; |
| 638 | struct input_dev *input; | 640 | struct input_dev *input; |
| 639 | 641 | ||
| 640 | /* Video Streaming interfaces */ | 642 | /* Video Streaming interfaces */ |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 88ca13104417..20c3be8617ea 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
| @@ -187,9 +187,11 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
| 187 | NULL | 187 | NULL |
| 188 | }; | 188 | }; |
| 189 | static const char *mpeg_audio_encoding[] = { | 189 | static const char *mpeg_audio_encoding[] = { |
| 190 | "Layer I", | 190 | "MPEG-1/2 Layer I", |
| 191 | "Layer II", | 191 | "MPEG-1/2 Layer II", |
| 192 | "Layer III", | 192 | "MPEG-1/2 Layer III", |
| 193 | "MPEG-2/4 AAC", | ||
| 194 | "AC-3", | ||
| 193 | NULL | 195 | NULL |
| 194 | }; | 196 | }; |
| 195 | static const char *mpeg_audio_l1_bitrate[] = { | 197 | static const char *mpeg_audio_l1_bitrate[] = { |
| @@ -243,6 +245,28 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
| 243 | "320 kbps", | 245 | "320 kbps", |
| 244 | NULL | 246 | NULL |
| 245 | }; | 247 | }; |
| 248 | static const char *mpeg_audio_ac3_bitrate[] = { | ||
| 249 | "32 kbps", | ||
| 250 | "40 kbps", | ||
| 251 | "48 kbps", | ||
| 252 | "56 kbps", | ||
| 253 | "64 kbps", | ||
| 254 | "80 kbps", | ||
| 255 | "96 kbps", | ||
| 256 | "112 kbps", | ||
| 257 | "128 kbps", | ||
| 258 | "160 kbps", | ||
| 259 | "192 kbps", | ||
| 260 | "224 kbps", | ||
| 261 | "256 kbps", | ||
| 262 | "320 kbps", | ||
| 263 | "384 kbps", | ||
| 264 | "448 kbps", | ||
| 265 | "512 kbps", | ||
| 266 | "576 kbps", | ||
| 267 | "640 kbps", | ||
| 268 | NULL | ||
| 269 | }; | ||
| 246 | static const char *mpeg_audio_mode[] = { | 270 | static const char *mpeg_audio_mode[] = { |
| 247 | "Stereo", | 271 | "Stereo", |
| 248 | "Joint Stereo", | 272 | "Joint Stereo", |
| @@ -271,6 +295,7 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
| 271 | static const char *mpeg_video_encoding[] = { | 295 | static const char *mpeg_video_encoding[] = { |
| 272 | "MPEG-1", | 296 | "MPEG-1", |
| 273 | "MPEG-2", | 297 | "MPEG-2", |
| 298 | "MPEG-4 AVC", | ||
| 274 | NULL | 299 | NULL |
| 275 | }; | 300 | }; |
| 276 | static const char *mpeg_video_aspect[] = { | 301 | static const char *mpeg_video_aspect[] = { |
| @@ -311,6 +336,8 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
| 311 | return mpeg_audio_l2_bitrate; | 336 | return mpeg_audio_l2_bitrate; |
| 312 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | 337 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: |
| 313 | return mpeg_audio_l3_bitrate; | 338 | return mpeg_audio_l3_bitrate; |
| 339 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
| 340 | return mpeg_audio_ac3_bitrate; | ||
| 314 | case V4L2_CID_MPEG_AUDIO_MODE: | 341 | case V4L2_CID_MPEG_AUDIO_MODE: |
| 315 | return mpeg_audio_mode; | 342 | return mpeg_audio_mode; |
| 316 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | 343 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: |
| @@ -335,62 +362,73 @@ const char **v4l2_ctrl_get_menu(u32 id) | |||
| 335 | } | 362 | } |
| 336 | EXPORT_SYMBOL(v4l2_ctrl_get_menu); | 363 | EXPORT_SYMBOL(v4l2_ctrl_get_menu); |
| 337 | 364 | ||
| 338 | /* Fill in a struct v4l2_queryctrl */ | 365 | /* Return the control name. */ |
| 339 | int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) | 366 | const char *v4l2_ctrl_get_name(u32 id) |
| 340 | { | 367 | { |
| 341 | const char *name; | 368 | switch (id) { |
| 342 | |||
| 343 | qctrl->flags = 0; | ||
| 344 | switch (qctrl->id) { | ||
| 345 | /* USER controls */ | 369 | /* USER controls */ |
| 346 | case V4L2_CID_USER_CLASS: name = "User Controls"; break; | 370 | case V4L2_CID_USER_CLASS: return "User Controls"; |
| 347 | case V4L2_CID_AUDIO_VOLUME: name = "Volume"; break; | 371 | case V4L2_CID_AUDIO_VOLUME: return "Volume"; |
| 348 | case V4L2_CID_AUDIO_MUTE: name = "Mute"; break; | 372 | case V4L2_CID_AUDIO_MUTE: return "Mute"; |
| 349 | case V4L2_CID_AUDIO_BALANCE: name = "Balance"; break; | 373 | case V4L2_CID_AUDIO_BALANCE: return "Balance"; |
| 350 | case V4L2_CID_AUDIO_BASS: name = "Bass"; break; | 374 | case V4L2_CID_AUDIO_BASS: return "Bass"; |
| 351 | case V4L2_CID_AUDIO_TREBLE: name = "Treble"; break; | 375 | case V4L2_CID_AUDIO_TREBLE: return "Treble"; |
| 352 | case V4L2_CID_AUDIO_LOUDNESS: name = "Loudness"; break; | 376 | case V4L2_CID_AUDIO_LOUDNESS: return "Loudness"; |
| 353 | case V4L2_CID_BRIGHTNESS: name = "Brightness"; break; | 377 | case V4L2_CID_BRIGHTNESS: return "Brightness"; |
| 354 | case V4L2_CID_CONTRAST: name = "Contrast"; break; | 378 | case V4L2_CID_CONTRAST: return "Contrast"; |
| 355 | case V4L2_CID_SATURATION: name = "Saturation"; break; | 379 | case V4L2_CID_SATURATION: return "Saturation"; |
| 356 | case V4L2_CID_HUE: name = "Hue"; break; | 380 | case V4L2_CID_HUE: return "Hue"; |
| 357 | 381 | ||
| 358 | /* MPEG controls */ | 382 | /* MPEG controls */ |
| 359 | case V4L2_CID_MPEG_CLASS: name = "MPEG Encoder Controls"; break; | 383 | case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; |
| 360 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: name = "Audio Sampling Frequency"; break; | 384 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return "Audio Sampling Frequency"; |
| 361 | case V4L2_CID_MPEG_AUDIO_ENCODING: name = "Audio Encoding Layer"; break; | 385 | case V4L2_CID_MPEG_AUDIO_ENCODING: return "Audio Encoding"; |
| 362 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: name = "Audio Layer I Bitrate"; break; | 386 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return "Audio Layer I Bitrate"; |
| 363 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: name = "Audio Layer II Bitrate"; break; | 387 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: return "Audio Layer II Bitrate"; |
| 364 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: name = "Audio Layer III Bitrate"; break; | 388 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return "Audio Layer III Bitrate"; |
| 365 | case V4L2_CID_MPEG_AUDIO_MODE: name = "Audio Stereo Mode"; break; | 389 | case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate"; |
| 366 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: name = "Audio Stereo Mode Extension"; break; | 390 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; |
| 367 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: name = "Audio Emphasis"; break; | 391 | case V4L2_CID_MPEG_AUDIO_MODE: return "Audio Stereo Mode"; |
| 368 | case V4L2_CID_MPEG_AUDIO_CRC: name = "Audio CRC"; break; | 392 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension"; |
| 369 | case V4L2_CID_MPEG_AUDIO_MUTE: name = "Audio Mute"; break; | 393 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: return "Audio Emphasis"; |
| 370 | case V4L2_CID_MPEG_VIDEO_ENCODING: name = "Video Encoding"; break; | 394 | case V4L2_CID_MPEG_AUDIO_CRC: return "Audio CRC"; |
| 371 | case V4L2_CID_MPEG_VIDEO_ASPECT: name = "Video Aspect"; break; | 395 | case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute"; |
| 372 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: name = "Video B Frames"; break; | 396 | case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding"; |
| 373 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: name = "Video GOP Size"; break; | 397 | case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect"; |
| 374 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: name = "Video GOP Closure"; break; | 398 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames"; |
| 375 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: name = "Video Pulldown"; break; | 399 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: return "Video GOP Size"; |
| 376 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: name = "Video Bitrate Mode"; break; | 400 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: return "Video GOP Closure"; |
| 377 | case V4L2_CID_MPEG_VIDEO_BITRATE: name = "Video Bitrate"; break; | 401 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: return "Video Pulldown"; |
| 378 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: name = "Video Peak Bitrate"; break; | 402 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return "Video Bitrate Mode"; |
| 379 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: name = "Video Temporal Decimation"; break; | 403 | case V4L2_CID_MPEG_VIDEO_BITRATE: return "Video Bitrate"; |
| 380 | case V4L2_CID_MPEG_VIDEO_MUTE: name = "Video Mute"; break; | 404 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: return "Video Peak Bitrate"; |
| 381 | case V4L2_CID_MPEG_VIDEO_MUTE_YUV: name = "Video Mute YUV"; break; | 405 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation"; |
| 382 | case V4L2_CID_MPEG_STREAM_TYPE: name = "Stream Type"; break; | 406 | case V4L2_CID_MPEG_VIDEO_MUTE: return "Video Mute"; |
| 383 | case V4L2_CID_MPEG_STREAM_PID_PMT: name = "Stream PMT Program ID"; break; | 407 | case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV"; |
| 384 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: name = "Stream Audio Program ID"; break; | 408 | case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type"; |
| 385 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: name = "Stream Video Program ID"; break; | 409 | case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID"; |
| 386 | case V4L2_CID_MPEG_STREAM_PID_PCR: name = "Stream PCR Program ID"; break; | 410 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID"; |
| 387 | case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: name = "Stream PES Audio ID"; break; | 411 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: return "Stream Video Program ID"; |
| 388 | case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: name = "Stream PES Video ID"; break; | 412 | case V4L2_CID_MPEG_STREAM_PID_PCR: return "Stream PCR Program ID"; |
| 389 | case V4L2_CID_MPEG_STREAM_VBI_FMT: name = "Stream VBI Format"; break; | 413 | case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: return "Stream PES Audio ID"; |
| 414 | case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID"; | ||
| 415 | case V4L2_CID_MPEG_STREAM_VBI_FMT: return "Stream VBI Format"; | ||
| 390 | 416 | ||
| 391 | default: | 417 | default: |
| 392 | return -EINVAL; | 418 | return NULL; |
| 393 | } | 419 | } |
| 420 | } | ||
| 421 | EXPORT_SYMBOL(v4l2_ctrl_get_name); | ||
| 422 | |||
| 423 | /* Fill in a struct v4l2_queryctrl */ | ||
| 424 | int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) | ||
| 425 | { | ||
| 426 | const char *name = v4l2_ctrl_get_name(qctrl->id); | ||
| 427 | |||
| 428 | qctrl->flags = 0; | ||
| 429 | if (name == NULL) | ||
| 430 | return -EINVAL; | ||
| 431 | |||
| 394 | switch (qctrl->id) { | 432 | switch (qctrl->id) { |
| 395 | case V4L2_CID_AUDIO_MUTE: | 433 | case V4L2_CID_AUDIO_MUTE: |
| 396 | case V4L2_CID_AUDIO_LOUDNESS: | 434 | case V4L2_CID_AUDIO_LOUDNESS: |
| @@ -407,6 +445,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste | |||
| 407 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | 445 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: |
| 408 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | 446 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
| 409 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | 447 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: |
| 448 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
| 410 | case V4L2_CID_MPEG_AUDIO_MODE: | 449 | case V4L2_CID_MPEG_AUDIO_MODE: |
| 411 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | 450 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: |
| 412 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: | 451 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: |
| @@ -493,7 +532,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) | |||
| 493 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 532 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
| 494 | return v4l2_ctrl_query_fill(qctrl, | 533 | return v4l2_ctrl_query_fill(qctrl, |
| 495 | V4L2_MPEG_AUDIO_ENCODING_LAYER_1, | 534 | V4L2_MPEG_AUDIO_ENCODING_LAYER_1, |
| 496 | V4L2_MPEG_AUDIO_ENCODING_LAYER_3, 1, | 535 | V4L2_MPEG_AUDIO_ENCODING_AC3, 1, |
| 497 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | 536 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); |
| 498 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | 537 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: |
| 499 | return v4l2_ctrl_query_fill(qctrl, | 538 | return v4l2_ctrl_query_fill(qctrl, |
| @@ -510,6 +549,13 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) | |||
| 510 | V4L2_MPEG_AUDIO_L3_BITRATE_32K, | 549 | V4L2_MPEG_AUDIO_L3_BITRATE_32K, |
| 511 | V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1, | 550 | V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1, |
| 512 | V4L2_MPEG_AUDIO_L3_BITRATE_192K); | 551 | V4L2_MPEG_AUDIO_L3_BITRATE_192K); |
| 552 | case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: | ||
| 553 | return v4l2_ctrl_query_fill(qctrl, 0, 6400, 1, 3200000); | ||
| 554 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
| 555 | return v4l2_ctrl_query_fill(qctrl, | ||
| 556 | V4L2_MPEG_AUDIO_AC3_BITRATE_32K, | ||
| 557 | V4L2_MPEG_AUDIO_AC3_BITRATE_640K, 1, | ||
| 558 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K); | ||
| 513 | case V4L2_CID_MPEG_AUDIO_MODE: | 559 | case V4L2_CID_MPEG_AUDIO_MODE: |
| 514 | return v4l2_ctrl_query_fill(qctrl, | 560 | return v4l2_ctrl_query_fill(qctrl, |
| 515 | V4L2_MPEG_AUDIO_MODE_STEREO, | 561 | V4L2_MPEG_AUDIO_MODE_STEREO, |
| @@ -535,7 +581,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) | |||
| 535 | case V4L2_CID_MPEG_VIDEO_ENCODING: | 581 | case V4L2_CID_MPEG_VIDEO_ENCODING: |
| 536 | return v4l2_ctrl_query_fill(qctrl, | 582 | return v4l2_ctrl_query_fill(qctrl, |
| 537 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1, | 583 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1, |
| 538 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, | 584 | V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1, |
| 539 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); | 585 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2); |
| 540 | case V4L2_CID_MPEG_VIDEO_ASPECT: | 586 | case V4L2_CID_MPEG_VIDEO_ASPECT: |
| 541 | return v4l2_ctrl_query_fill(qctrl, | 587 | return v4l2_ctrl_query_fill(qctrl, |
| @@ -594,12 +640,17 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) | |||
| 594 | EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); | 640 | EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); |
| 595 | 641 | ||
| 596 | /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and | 642 | /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and |
| 597 | the menu. The qctrl pointer may be NULL, in which case it is ignored. */ | 643 | the menu. The qctrl pointer may be NULL, in which case it is ignored. |
| 644 | If menu_items is NULL, then the menu items are retrieved using | ||
| 645 | v4l2_ctrl_get_menu. */ | ||
| 598 | int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, | 646 | int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, |
| 599 | const char **menu_items) | 647 | const char **menu_items) |
| 600 | { | 648 | { |
| 601 | int i; | 649 | int i; |
| 602 | 650 | ||
| 651 | qmenu->reserved = 0; | ||
| 652 | if (menu_items == NULL) | ||
| 653 | menu_items = v4l2_ctrl_get_menu(qmenu->id); | ||
| 603 | if (menu_items == NULL || | 654 | if (menu_items == NULL || |
| 604 | (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum))) | 655 | (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum))) |
| 605 | return -EINVAL; | 656 | return -EINVAL; |
| @@ -607,11 +658,31 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc | |||
| 607 | if (menu_items[i] == NULL || menu_items[i][0] == '\0') | 658 | if (menu_items[i] == NULL || menu_items[i][0] == '\0') |
| 608 | return -EINVAL; | 659 | return -EINVAL; |
| 609 | snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]); | 660 | snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]); |
| 610 | qmenu->reserved = 0; | ||
| 611 | return 0; | 661 | return 0; |
| 612 | } | 662 | } |
| 613 | EXPORT_SYMBOL(v4l2_ctrl_query_menu); | 663 | EXPORT_SYMBOL(v4l2_ctrl_query_menu); |
| 614 | 664 | ||
| 665 | /* Fill in a struct v4l2_querymenu based on the specified array of valid | ||
| 666 | menu items (terminated by V4L2_CTRL_MENU_IDS_END). | ||
| 667 | Use this if there are 'holes' in the list of valid menu items. */ | ||
| 668 | int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids) | ||
| 669 | { | ||
| 670 | const char **menu_items = v4l2_ctrl_get_menu(qmenu->id); | ||
| 671 | |||
| 672 | qmenu->reserved = 0; | ||
| 673 | if (menu_items == NULL || ids == NULL) | ||
| 674 | return -EINVAL; | ||
| 675 | while (*ids != V4L2_CTRL_MENU_IDS_END) { | ||
| 676 | if (*ids++ == qmenu->index) { | ||
| 677 | snprintf(qmenu->name, sizeof(qmenu->name), | ||
| 678 | menu_items[qmenu->index]); | ||
| 679 | return 0; | ||
| 680 | } | ||
| 681 | } | ||
| 682 | return -EINVAL; | ||
| 683 | } | ||
| 684 | EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items); | ||
| 685 | |||
| 615 | /* ctrl_classes points to an array of u32 pointers, the last element is | 686 | /* ctrl_classes points to an array of u32 pointers, the last element is |
| 616 | a NULL pointer. Each u32 array is a 0-terminated array of control IDs. | 687 | a NULL pointer. Each u32 array is a 0-terminated array of control IDs. |
| 617 | Each array must be sorted low to high and belong to the same control | 688 | Each array must be sorted low to high and belong to the same control |
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 155fdec9ac7d..ccd6566a515e 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
| @@ -42,6 +42,7 @@ static ssize_t show_index(struct device *cd, | |||
| 42 | struct device_attribute *attr, char *buf) | 42 | struct device_attribute *attr, char *buf) |
| 43 | { | 43 | { |
| 44 | struct video_device *vfd = container_of(cd, struct video_device, dev); | 44 | struct video_device *vfd = container_of(cd, struct video_device, dev); |
| 45 | |||
| 45 | return sprintf(buf, "%i\n", vfd->index); | 46 | return sprintf(buf, "%i\n", vfd->index); |
| 46 | } | 47 | } |
| 47 | 48 | ||
| @@ -49,6 +50,7 @@ static ssize_t show_name(struct device *cd, | |||
| 49 | struct device_attribute *attr, char *buf) | 50 | struct device_attribute *attr, char *buf) |
| 50 | { | 51 | { |
| 51 | struct video_device *vfd = container_of(cd, struct video_device, dev); | 52 | struct video_device *vfd = container_of(cd, struct video_device, dev); |
| 53 | |||
| 52 | return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name); | 54 | return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name); |
| 53 | } | 55 | } |
| 54 | 56 | ||
| @@ -58,12 +60,16 @@ static struct device_attribute video_device_attrs[] = { | |||
| 58 | __ATTR_NULL | 60 | __ATTR_NULL |
| 59 | }; | 61 | }; |
| 60 | 62 | ||
| 63 | /* | ||
| 64 | * Active devices | ||
| 65 | */ | ||
| 66 | static struct video_device *video_device[VIDEO_NUM_DEVICES]; | ||
| 67 | static DEFINE_MUTEX(videodev_lock); | ||
| 68 | static DECLARE_BITMAP(video_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES); | ||
| 69 | |||
| 61 | struct video_device *video_device_alloc(void) | 70 | struct video_device *video_device_alloc(void) |
| 62 | { | 71 | { |
| 63 | struct video_device *vfd; | 72 | return kzalloc(sizeof(struct video_device), GFP_KERNEL); |
| 64 | |||
| 65 | vfd = kzalloc(sizeof(*vfd), GFP_KERNEL); | ||
| 66 | return vfd; | ||
| 67 | } | 73 | } |
| 68 | EXPORT_SYMBOL(video_device_alloc); | 74 | EXPORT_SYMBOL(video_device_alloc); |
| 69 | 75 | ||
| @@ -73,16 +79,52 @@ void video_device_release(struct video_device *vfd) | |||
| 73 | } | 79 | } |
| 74 | EXPORT_SYMBOL(video_device_release); | 80 | EXPORT_SYMBOL(video_device_release); |
| 75 | 81 | ||
| 82 | void video_device_release_empty(struct video_device *vfd) | ||
| 83 | { | ||
| 84 | /* Do nothing */ | ||
| 85 | /* Only valid when the video_device struct is a static. */ | ||
| 86 | } | ||
| 87 | EXPORT_SYMBOL(video_device_release_empty); | ||
| 88 | |||
| 89 | /* Called when the last user of the character device is gone. */ | ||
| 90 | static void v4l2_chardev_release(struct kobject *kobj) | ||
| 91 | { | ||
| 92 | struct video_device *vfd = container_of(kobj, struct video_device, cdev.kobj); | ||
| 93 | |||
| 94 | mutex_lock(&videodev_lock); | ||
| 95 | if (video_device[vfd->minor] != vfd) { | ||
| 96 | mutex_unlock(&videodev_lock); | ||
| 97 | BUG(); | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | |||
| 101 | /* Free up this device for reuse */ | ||
| 102 | video_device[vfd->minor] = NULL; | ||
| 103 | clear_bit(vfd->num, video_nums[vfd->vfl_type]); | ||
| 104 | mutex_unlock(&videodev_lock); | ||
| 105 | |||
| 106 | /* Release the character device */ | ||
| 107 | vfd->cdev_release(kobj); | ||
| 108 | /* Release video_device and perform other | ||
| 109 | cleanups as needed. */ | ||
| 110 | if (vfd->release) | ||
| 111 | vfd->release(vfd); | ||
| 112 | } | ||
| 113 | |||
| 114 | /* The new kobj_type for the character device */ | ||
| 115 | static struct kobj_type v4l2_ktype_cdev_default = { | ||
| 116 | .release = v4l2_chardev_release, | ||
| 117 | }; | ||
| 118 | |||
| 76 | static void video_release(struct device *cd) | 119 | static void video_release(struct device *cd) |
| 77 | { | 120 | { |
| 78 | struct video_device *vfd = container_of(cd, struct video_device, dev); | 121 | struct video_device *vfd = container_of(cd, struct video_device, dev); |
| 79 | 122 | ||
| 80 | #if 1 | 123 | /* It's now safe to delete the char device. |
| 81 | /* needed until all drivers are fixed */ | 124 | This will either trigger the v4l2_chardev_release immediately (if |
| 82 | if (!vfd->release) | 125 | the refcount goes to 0) or later when the last user of the |
| 83 | return; | 126 | character device closes it. */ |
| 84 | #endif | 127 | cdev_del(&vfd->cdev); |
| 85 | vfd->release(vfd); | ||
| 86 | } | 128 | } |
| 87 | 129 | ||
| 88 | static struct class video_class = { | 130 | static struct class video_class = { |
| @@ -91,87 +133,12 @@ static struct class video_class = { | |||
| 91 | .dev_release = video_release, | 133 | .dev_release = video_release, |
| 92 | }; | 134 | }; |
| 93 | 135 | ||
| 94 | /* | ||
| 95 | * Active devices | ||
| 96 | */ | ||
| 97 | |||
| 98 | static struct video_device *video_device[VIDEO_NUM_DEVICES]; | ||
| 99 | static DEFINE_MUTEX(videodev_lock); | ||
| 100 | |||
| 101 | struct video_device *video_devdata(struct file *file) | 136 | struct video_device *video_devdata(struct file *file) |
| 102 | { | 137 | { |
| 103 | return video_device[iminor(file->f_path.dentry->d_inode)]; | 138 | return video_device[iminor(file->f_path.dentry->d_inode)]; |
| 104 | } | 139 | } |
| 105 | EXPORT_SYMBOL(video_devdata); | 140 | EXPORT_SYMBOL(video_devdata); |
| 106 | 141 | ||
| 107 | /* | ||
| 108 | * Open a video device - FIXME: Obsoleted | ||
| 109 | */ | ||
| 110 | static int video_open(struct inode *inode, struct file *file) | ||
| 111 | { | ||
| 112 | unsigned int minor = iminor(inode); | ||
| 113 | int err = 0; | ||
| 114 | struct video_device *vfl; | ||
| 115 | const struct file_operations *old_fops; | ||
| 116 | |||
| 117 | if (minor >= VIDEO_NUM_DEVICES) | ||
| 118 | return -ENODEV; | ||
| 119 | lock_kernel(); | ||
| 120 | mutex_lock(&videodev_lock); | ||
| 121 | vfl = video_device[minor]; | ||
| 122 | if (vfl == NULL) { | ||
| 123 | mutex_unlock(&videodev_lock); | ||
| 124 | request_module("char-major-%d-%d", VIDEO_MAJOR, minor); | ||
| 125 | mutex_lock(&videodev_lock); | ||
| 126 | vfl = video_device[minor]; | ||
| 127 | if (vfl == NULL) { | ||
| 128 | mutex_unlock(&videodev_lock); | ||
| 129 | unlock_kernel(); | ||
| 130 | return -ENODEV; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | old_fops = file->f_op; | ||
| 134 | file->f_op = fops_get(vfl->fops); | ||
| 135 | if (file->f_op->open) | ||
| 136 | err = file->f_op->open(inode, file); | ||
| 137 | if (err) { | ||
| 138 | fops_put(file->f_op); | ||
| 139 | file->f_op = fops_get(old_fops); | ||
| 140 | } | ||
| 141 | fops_put(old_fops); | ||
| 142 | mutex_unlock(&videodev_lock); | ||
| 143 | unlock_kernel(); | ||
| 144 | return err; | ||
| 145 | } | ||
| 146 | |||
| 147 | /* | ||
| 148 | * open/release helper functions -- handle exclusive opens | ||
| 149 | * Should be removed soon | ||
| 150 | */ | ||
| 151 | int video_exclusive_open(struct inode *inode, struct file *file) | ||
| 152 | { | ||
| 153 | struct video_device *vfl = video_devdata(file); | ||
| 154 | int retval = 0; | ||
| 155 | |||
| 156 | mutex_lock(&vfl->lock); | ||
| 157 | if (vfl->users) | ||
| 158 | retval = -EBUSY; | ||
| 159 | else | ||
| 160 | vfl->users++; | ||
| 161 | mutex_unlock(&vfl->lock); | ||
| 162 | return retval; | ||
| 163 | } | ||
| 164 | EXPORT_SYMBOL(video_exclusive_open); | ||
| 165 | |||
| 166 | int video_exclusive_release(struct inode *inode, struct file *file) | ||
| 167 | { | ||
| 168 | struct video_device *vfl = video_devdata(file); | ||
| 169 | |||
| 170 | vfl->users--; | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | EXPORT_SYMBOL(video_exclusive_release); | ||
| 174 | |||
| 175 | /** | 142 | /** |
| 176 | * get_index - assign stream number based on parent device | 143 | * get_index - assign stream number based on parent device |
| 177 | * @vdev: video_device to assign index number to, vdev->dev should be assigned | 144 | * @vdev: video_device to assign index number to, vdev->dev should be assigned |
| @@ -252,33 +219,29 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, | |||
| 252 | int index) | 219 | int index) |
| 253 | { | 220 | { |
| 254 | int i = 0; | 221 | int i = 0; |
| 255 | int base; | ||
| 256 | int end; | ||
| 257 | int ret; | 222 | int ret; |
| 258 | char *name_base; | 223 | int minor_offset = 0; |
| 224 | int minor_cnt = VIDEO_NUM_DEVICES; | ||
| 225 | const char *name_base; | ||
| 226 | void *priv = video_get_drvdata(vfd); | ||
| 227 | |||
| 228 | /* the release callback MUST be present */ | ||
| 229 | BUG_ON(!vfd->release); | ||
| 259 | 230 | ||
| 260 | if (vfd == NULL) | 231 | if (vfd == NULL) |
| 261 | return -EINVAL; | 232 | return -EINVAL; |
| 262 | 233 | ||
| 263 | switch (type) { | 234 | switch (type) { |
| 264 | case VFL_TYPE_GRABBER: | 235 | case VFL_TYPE_GRABBER: |
| 265 | base = MINOR_VFL_TYPE_GRABBER_MIN; | ||
| 266 | end = MINOR_VFL_TYPE_GRABBER_MAX+1; | ||
| 267 | name_base = "video"; | 236 | name_base = "video"; |
| 268 | break; | 237 | break; |
| 269 | case VFL_TYPE_VTX: | 238 | case VFL_TYPE_VTX: |
| 270 | base = MINOR_VFL_TYPE_VTX_MIN; | ||
| 271 | end = MINOR_VFL_TYPE_VTX_MAX+1; | ||
| 272 | name_base = "vtx"; | 239 | name_base = "vtx"; |
| 273 | break; | 240 | break; |
| 274 | case VFL_TYPE_VBI: | 241 | case VFL_TYPE_VBI: |
| 275 | base = MINOR_VFL_TYPE_VBI_MIN; | ||
| 276 | end = MINOR_VFL_TYPE_VBI_MAX+1; | ||
| 277 | name_base = "vbi"; | 242 | name_base = "vbi"; |
| 278 | break; | 243 | break; |
| 279 | case VFL_TYPE_RADIO: | 244 | case VFL_TYPE_RADIO: |
| 280 | base = MINOR_VFL_TYPE_RADIO_MIN; | ||
| 281 | end = MINOR_VFL_TYPE_RADIO_MAX+1; | ||
| 282 | name_base = "radio"; | 245 | name_base = "radio"; |
| 283 | break; | 246 | break; |
| 284 | default: | 247 | default: |
| @@ -287,28 +250,70 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, | |||
| 287 | return -EINVAL; | 250 | return -EINVAL; |
| 288 | } | 251 | } |
| 289 | 252 | ||
| 253 | vfd->vfl_type = type; | ||
| 254 | |||
| 255 | #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES | ||
| 256 | /* Keep the ranges for the first four types for historical | ||
| 257 | * reasons. | ||
| 258 | * Newer devices (not yet in place) should use the range | ||
| 259 | * of 128-191 and just pick the first free minor there | ||
| 260 | * (new style). */ | ||
| 261 | switch (type) { | ||
| 262 | case VFL_TYPE_GRABBER: | ||
| 263 | minor_offset = 0; | ||
| 264 | minor_cnt = 64; | ||
| 265 | break; | ||
| 266 | case VFL_TYPE_RADIO: | ||
| 267 | minor_offset = 64; | ||
| 268 | minor_cnt = 64; | ||
| 269 | break; | ||
| 270 | case VFL_TYPE_VTX: | ||
| 271 | minor_offset = 192; | ||
| 272 | minor_cnt = 32; | ||
| 273 | break; | ||
| 274 | case VFL_TYPE_VBI: | ||
| 275 | minor_offset = 224; | ||
| 276 | minor_cnt = 32; | ||
| 277 | break; | ||
| 278 | default: | ||
| 279 | minor_offset = 128; | ||
| 280 | minor_cnt = 64; | ||
| 281 | break; | ||
| 282 | } | ||
| 283 | #endif | ||
| 284 | |||
| 285 | /* Initialize the character device */ | ||
| 286 | cdev_init(&vfd->cdev, vfd->fops); | ||
| 287 | vfd->cdev.owner = vfd->fops->owner; | ||
| 290 | /* pick a minor number */ | 288 | /* pick a minor number */ |
| 291 | mutex_lock(&videodev_lock); | 289 | mutex_lock(&videodev_lock); |
| 292 | if (nr >= 0 && nr < end-base) { | 290 | nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr); |
| 293 | /* use the one the driver asked for */ | 291 | if (nr == minor_cnt) |
| 294 | i = base + nr; | 292 | nr = find_first_zero_bit(video_nums[type], minor_cnt); |
| 295 | if (NULL != video_device[i]) { | 293 | if (nr == minor_cnt) { |
| 296 | mutex_unlock(&videodev_lock); | 294 | printk(KERN_ERR "could not get a free kernel number\n"); |
| 297 | return -ENFILE; | 295 | mutex_unlock(&videodev_lock); |
| 298 | } | 296 | return -ENFILE; |
| 299 | } else { | ||
| 300 | /* use first free */ | ||
| 301 | for (i = base; i < end; i++) | ||
| 302 | if (NULL == video_device[i]) | ||
| 303 | break; | ||
| 304 | if (i == end) { | ||
| 305 | mutex_unlock(&videodev_lock); | ||
| 306 | return -ENFILE; | ||
| 307 | } | ||
| 308 | } | 297 | } |
| 309 | video_device[i] = vfd; | 298 | #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES |
| 310 | vfd->vfl_type = type; | 299 | /* 1-on-1 mapping of kernel number to minor number */ |
| 311 | vfd->minor = i; | 300 | i = nr; |
| 301 | #else | ||
| 302 | /* The kernel number and minor numbers are independent */ | ||
| 303 | for (i = 0; i < VIDEO_NUM_DEVICES; i++) | ||
| 304 | if (video_device[i] == NULL) | ||
| 305 | break; | ||
| 306 | if (i == VIDEO_NUM_DEVICES) { | ||
| 307 | mutex_unlock(&videodev_lock); | ||
| 308 | printk(KERN_ERR "could not get a free minor\n"); | ||
| 309 | return -ENFILE; | ||
| 310 | } | ||
| 311 | #endif | ||
| 312 | vfd->minor = i + minor_offset; | ||
| 313 | vfd->num = nr; | ||
| 314 | set_bit(nr, video_nums[type]); | ||
| 315 | BUG_ON(video_device[vfd->minor]); | ||
| 316 | video_device[vfd->minor] = vfd; | ||
| 312 | 317 | ||
| 313 | ret = get_index(vfd, index); | 318 | ret = get_index(vfd, index); |
| 314 | vfd->index = ret; | 319 | vfd->index = ret; |
| @@ -320,35 +325,41 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, | |||
| 320 | goto fail_minor; | 325 | goto fail_minor; |
| 321 | } | 326 | } |
| 322 | 327 | ||
| 323 | mutex_init(&vfd->lock); | 328 | ret = cdev_add(&vfd->cdev, MKDEV(VIDEO_MAJOR, vfd->minor), 1); |
| 324 | 329 | if (ret < 0) { | |
| 330 | printk(KERN_ERR "%s: cdev_add failed\n", __func__); | ||
| 331 | goto fail_minor; | ||
| 332 | } | ||
| 325 | /* sysfs class */ | 333 | /* sysfs class */ |
| 326 | memset(&vfd->dev, 0x00, sizeof(vfd->dev)); | 334 | memset(&vfd->dev, 0, sizeof(vfd->dev)); |
| 335 | /* The memset above cleared the device's drvdata, so | ||
| 336 | put back the copy we made earlier. */ | ||
| 337 | video_set_drvdata(vfd, priv); | ||
| 327 | vfd->dev.class = &video_class; | 338 | vfd->dev.class = &video_class; |
| 328 | vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); | 339 | vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); |
| 329 | if (vfd->parent) | 340 | if (vfd->parent) |
| 330 | vfd->dev.parent = vfd->parent; | 341 | vfd->dev.parent = vfd->parent; |
| 331 | sprintf(vfd->dev.bus_id, "%s%d", name_base, i - base); | 342 | sprintf(vfd->dev.bus_id, "%s%d", name_base, nr); |
| 332 | ret = device_register(&vfd->dev); | 343 | ret = device_register(&vfd->dev); |
| 333 | if (ret < 0) { | 344 | if (ret < 0) { |
| 334 | printk(KERN_ERR "%s: device_register failed\n", __func__); | 345 | printk(KERN_ERR "%s: device_register failed\n", __func__); |
| 335 | goto fail_minor; | 346 | goto del_cdev; |
| 336 | } | 347 | } |
| 337 | 348 | /* Remember the cdev's release function */ | |
| 338 | #if 1 | 349 | vfd->cdev_release = vfd->cdev.kobj.ktype->release; |
| 339 | /* needed until all drivers are fixed */ | 350 | /* Install our own */ |
| 340 | if (!vfd->release) | 351 | vfd->cdev.kobj.ktype = &v4l2_ktype_cdev_default; |
| 341 | printk(KERN_WARNING "videodev: \"%s\" has no release callback. " | ||
| 342 | "Please fix your driver for proper sysfs support, see " | ||
| 343 | "http://lwn.net/Articles/36850/\n", vfd->name); | ||
| 344 | #endif | ||
| 345 | return 0; | 352 | return 0; |
| 346 | 353 | ||
| 354 | del_cdev: | ||
| 355 | cdev_del(&vfd->cdev); | ||
| 356 | |||
| 347 | fail_minor: | 357 | fail_minor: |
| 348 | mutex_lock(&videodev_lock); | 358 | mutex_lock(&videodev_lock); |
| 349 | video_device[vfd->minor] = NULL; | 359 | video_device[vfd->minor] = NULL; |
| 350 | vfd->minor = -1; | 360 | clear_bit(vfd->num, video_nums[type]); |
| 351 | mutex_unlock(&videodev_lock); | 361 | mutex_unlock(&videodev_lock); |
| 362 | vfd->minor = -1; | ||
| 352 | return ret; | 363 | return ret; |
| 353 | } | 364 | } |
| 354 | EXPORT_SYMBOL(video_register_device_index); | 365 | EXPORT_SYMBOL(video_register_device_index); |
| @@ -363,42 +374,29 @@ EXPORT_SYMBOL(video_register_device_index); | |||
| 363 | 374 | ||
| 364 | void video_unregister_device(struct video_device *vfd) | 375 | void video_unregister_device(struct video_device *vfd) |
| 365 | { | 376 | { |
| 366 | mutex_lock(&videodev_lock); | ||
| 367 | if (video_device[vfd->minor] != vfd) | ||
| 368 | panic("videodev: bad unregister"); | ||
| 369 | |||
| 370 | video_device[vfd->minor] = NULL; | ||
| 371 | device_unregister(&vfd->dev); | 377 | device_unregister(&vfd->dev); |
| 372 | mutex_unlock(&videodev_lock); | ||
| 373 | } | 378 | } |
| 374 | EXPORT_SYMBOL(video_unregister_device); | 379 | EXPORT_SYMBOL(video_unregister_device); |
| 375 | 380 | ||
| 376 | /* | 381 | /* |
| 377 | * Video fs operations | ||
| 378 | */ | ||
| 379 | static const struct file_operations video_fops = { | ||
| 380 | .owner = THIS_MODULE, | ||
| 381 | .llseek = no_llseek, | ||
| 382 | .open = video_open, | ||
| 383 | }; | ||
| 384 | |||
| 385 | /* | ||
| 386 | * Initialise video for linux | 382 | * Initialise video for linux |
| 387 | */ | 383 | */ |
| 388 | |||
| 389 | static int __init videodev_init(void) | 384 | static int __init videodev_init(void) |
| 390 | { | 385 | { |
| 386 | dev_t dev = MKDEV(VIDEO_MAJOR, 0); | ||
| 391 | int ret; | 387 | int ret; |
| 392 | 388 | ||
| 393 | printk(KERN_INFO "Linux video capture interface: v2.00\n"); | 389 | printk(KERN_INFO "Linux video capture interface: v2.00\n"); |
| 394 | if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) { | 390 | ret = register_chrdev_region(dev, VIDEO_NUM_DEVICES, VIDEO_NAME); |
| 395 | printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR); | 391 | if (ret < 0) { |
| 396 | return -EIO; | 392 | printk(KERN_WARNING "videodev: unable to get major %d\n", |
| 393 | VIDEO_MAJOR); | ||
| 394 | return ret; | ||
| 397 | } | 395 | } |
| 398 | 396 | ||
| 399 | ret = class_register(&video_class); | 397 | ret = class_register(&video_class); |
| 400 | if (ret < 0) { | 398 | if (ret < 0) { |
| 401 | unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME); | 399 | unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); |
| 402 | printk(KERN_WARNING "video_dev: class_register failed\n"); | 400 | printk(KERN_WARNING "video_dev: class_register failed\n"); |
| 403 | return -EIO; | 401 | return -EIO; |
| 404 | } | 402 | } |
| @@ -408,8 +406,10 @@ static int __init videodev_init(void) | |||
| 408 | 406 | ||
| 409 | static void __exit videodev_exit(void) | 407 | static void __exit videodev_exit(void) |
| 410 | { | 408 | { |
| 409 | dev_t dev = MKDEV(VIDEO_MAJOR, 0); | ||
| 410 | |||
| 411 | class_unregister(&video_class); | 411 | class_unregister(&video_class); |
| 412 | unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME); | 412 | unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); |
| 413 | } | 413 | } |
| 414 | 414 | ||
| 415 | module_init(videodev_init) | 415 | module_init(videodev_init) |
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 140ef92c19c1..155c9d77a463 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c | |||
| @@ -746,18 +746,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
| 746 | ret = ops->vidioc_enum_fmt_vid_overlay(file, | 746 | ret = ops->vidioc_enum_fmt_vid_overlay(file, |
| 747 | fh, f); | 747 | fh, f); |
| 748 | break; | 748 | break; |
| 749 | #if 1 | ||
| 750 | /* V4L2_BUF_TYPE_VBI_CAPTURE should not support VIDIOC_ENUM_FMT | ||
| 751 | * according to the spec. The bttv and saa7134 drivers support | ||
| 752 | * it though, so just warn that this is deprecated and will be | ||
| 753 | * removed in the near future. */ | ||
| 754 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
| 755 | if (ops->vidioc_enum_fmt_vbi_cap) { | ||
| 756 | printk(KERN_WARNING "vidioc_enum_fmt_vbi_cap will be removed in 2.6.28!\n"); | ||
| 757 | ret = ops->vidioc_enum_fmt_vbi_cap(file, fh, f); | ||
| 758 | } | ||
| 759 | break; | ||
| 760 | #endif | ||
| 761 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | 749 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: |
| 762 | if (ops->vidioc_enum_fmt_vid_out) | 750 | if (ops->vidioc_enum_fmt_vid_out) |
| 763 | ret = ops->vidioc_enum_fmt_vid_out(file, fh, f); | 751 | ret = ops->vidioc_enum_fmt_vid_out(file, fh, f); |
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 1edda456fc64..8ec57df1904f 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
| @@ -39,7 +39,6 @@ | |||
| 39 | #include <linux/i2c-algo-sgi.h> | 39 | #include <linux/i2c-algo-sgi.h> |
| 40 | 40 | ||
| 41 | #include <linux/videodev2.h> | 41 | #include <linux/videodev2.h> |
| 42 | #include <media/v4l2-ioctl.h> | ||
| 43 | #include <media/v4l2-common.h> | 42 | #include <media/v4l2-common.h> |
| 44 | #include <media/v4l2-ioctl.h> | 43 | #include <media/v4l2-ioctl.h> |
| 45 | #include <linux/video_decoder.h> | 44 | #include <linux/video_decoder.h> |
| @@ -810,7 +809,7 @@ static void vino_free_buffer_with_count(struct vino_framebuffer *fb, | |||
| 810 | dprintk("vino_free_buffer_with_count(): count = %d\n", count); | 809 | dprintk("vino_free_buffer_with_count(): count = %d\n", count); |
| 811 | 810 | ||
| 812 | for (i = 0; i < count; i++) { | 811 | for (i = 0; i < count; i++) { |
| 813 | ClearPageReserved(virt_to_page(fb->desc_table.virtual[i])); | 812 | ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); |
| 814 | dma_unmap_single(NULL, | 813 | dma_unmap_single(NULL, |
| 815 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], | 814 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], |
| 816 | PAGE_SIZE, DMA_FROM_DEVICE); | 815 | PAGE_SIZE, DMA_FROM_DEVICE); |
| @@ -888,7 +887,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb, | |||
| 888 | dma_data_addr + VINO_PAGE_SIZE * j; | 887 | dma_data_addr + VINO_PAGE_SIZE * j; |
| 889 | } | 888 | } |
| 890 | 889 | ||
| 891 | SetPageReserved(virt_to_page(fb->desc_table.virtual[i])); | 890 | SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); |
| 892 | } | 891 | } |
| 893 | 892 | ||
| 894 | /* page_count needs to be set anyway, because the descriptor table has | 893 | /* page_count needs to be set anyway, because the descriptor table has |
| @@ -975,7 +974,7 @@ static int vino_prepare_user_buffer(struct vino_framebuffer *fb, | |||
| 975 | dma_data_addr + VINO_PAGE_SIZE * j; | 974 | dma_data_addr + VINO_PAGE_SIZE * j; |
| 976 | } | 975 | } |
| 977 | 976 | ||
| 978 | SetPageReserved(virt_to_page(fb->desc_table.virtual[i])); | 977 | SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i])); |
| 979 | } | 978 | } |
| 980 | 979 | ||
| 981 | /* page_count needs to be set anyway, because the descriptor table has | 980 | /* page_count needs to be set anyway, because the descriptor table has |
| @@ -4025,8 +4024,7 @@ out: | |||
| 4025 | 4024 | ||
| 4026 | static int vino_open(struct inode *inode, struct file *file) | 4025 | static int vino_open(struct inode *inode, struct file *file) |
| 4027 | { | 4026 | { |
| 4028 | struct video_device *dev = video_devdata(file); | 4027 | struct vino_channel_settings *vcs = video_drvdata(file); |
| 4029 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
| 4030 | int ret = 0; | 4028 | int ret = 0; |
| 4031 | dprintk("open(): channel = %c\n", | 4029 | dprintk("open(): channel = %c\n", |
| 4032 | (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B'); | 4030 | (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B'); |
| @@ -4057,8 +4055,7 @@ static int vino_open(struct inode *inode, struct file *file) | |||
| 4057 | 4055 | ||
| 4058 | static int vino_close(struct inode *inode, struct file *file) | 4056 | static int vino_close(struct inode *inode, struct file *file) |
| 4059 | { | 4057 | { |
| 4060 | struct video_device *dev = video_devdata(file); | 4058 | struct vino_channel_settings *vcs = video_drvdata(file); |
| 4061 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
| 4062 | dprintk("close():\n"); | 4059 | dprintk("close():\n"); |
| 4063 | 4060 | ||
| 4064 | mutex_lock(&vcs->mutex); | 4061 | mutex_lock(&vcs->mutex); |
| @@ -4101,8 +4098,7 @@ static struct vm_operations_struct vino_vm_ops = { | |||
| 4101 | 4098 | ||
| 4102 | static int vino_mmap(struct file *file, struct vm_area_struct *vma) | 4099 | static int vino_mmap(struct file *file, struct vm_area_struct *vma) |
| 4103 | { | 4100 | { |
| 4104 | struct video_device *dev = video_devdata(file); | 4101 | struct vino_channel_settings *vcs = video_drvdata(file); |
| 4105 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
| 4106 | 4102 | ||
| 4107 | unsigned long start = vma->vm_start; | 4103 | unsigned long start = vma->vm_start; |
| 4108 | unsigned long size = vma->vm_end - vma->vm_start; | 4104 | unsigned long size = vma->vm_end - vma->vm_start; |
| @@ -4207,8 +4203,7 @@ out: | |||
| 4207 | 4203 | ||
| 4208 | static unsigned int vino_poll(struct file *file, poll_table *pt) | 4204 | static unsigned int vino_poll(struct file *file, poll_table *pt) |
| 4209 | { | 4205 | { |
| 4210 | struct video_device *dev = video_devdata(file); | 4206 | struct vino_channel_settings *vcs = video_drvdata(file); |
| 4211 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
| 4212 | unsigned int outgoing; | 4207 | unsigned int outgoing; |
| 4213 | unsigned int ret = 0; | 4208 | unsigned int ret = 0; |
| 4214 | 4209 | ||
| @@ -4248,8 +4243,7 @@ error: | |||
| 4248 | static int vino_do_ioctl(struct inode *inode, struct file *file, | 4243 | static int vino_do_ioctl(struct inode *inode, struct file *file, |
| 4249 | unsigned int cmd, void *arg) | 4244 | unsigned int cmd, void *arg) |
| 4250 | { | 4245 | { |
| 4251 | struct video_device *dev = video_devdata(file); | 4246 | struct vino_channel_settings *vcs = video_drvdata(file); |
| 4252 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
| 4253 | 4247 | ||
| 4254 | #ifdef VINO_DEBUG | 4248 | #ifdef VINO_DEBUG |
| 4255 | switch (_IOC_TYPE(cmd)) { | 4249 | switch (_IOC_TYPE(cmd)) { |
| @@ -4356,8 +4350,7 @@ static int vino_do_ioctl(struct inode *inode, struct file *file, | |||
| 4356 | static int vino_ioctl(struct inode *inode, struct file *file, | 4350 | static int vino_ioctl(struct inode *inode, struct file *file, |
| 4357 | unsigned int cmd, unsigned long arg) | 4351 | unsigned int cmd, unsigned long arg) |
| 4358 | { | 4352 | { |
| 4359 | struct video_device *dev = video_devdata(file); | 4353 | struct vino_channel_settings *vcs = video_drvdata(file); |
| 4360 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
| 4361 | int ret; | 4354 | int ret; |
| 4362 | 4355 | ||
| 4363 | if (mutex_lock_interruptible(&vcs->mutex)) | 4356 | if (mutex_lock_interruptible(&vcs->mutex)) |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 8ba8daafd7ea..65c8af18e767 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
| @@ -898,9 +898,11 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
| 898 | 898 | ||
| 899 | printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor); | 899 | printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor); |
| 900 | 900 | ||
| 901 | lock_kernel(); | ||
| 901 | list_for_each_entry(dev, &vivi_devlist, vivi_devlist) | 902 | list_for_each_entry(dev, &vivi_devlist, vivi_devlist) |
| 902 | if (dev->vfd->minor == minor) | 903 | if (dev->vfd->minor == minor) |
| 903 | goto found; | 904 | goto found; |
| 905 | unlock_kernel(); | ||
| 904 | return -ENODEV; | 906 | return -ENODEV; |
| 905 | 907 | ||
| 906 | found: | 908 | found: |
| @@ -925,8 +927,10 @@ found: | |||
| 925 | } | 927 | } |
| 926 | unlock: | 928 | unlock: |
| 927 | mutex_unlock(&dev->mutex); | 929 | mutex_unlock(&dev->mutex); |
| 928 | if (retval) | 930 | if (retval) { |
| 931 | unlock_kernel(); | ||
| 929 | return retval; | 932 | return retval; |
| 933 | } | ||
| 930 | 934 | ||
| 931 | file->private_data = fh; | 935 | file->private_data = fh; |
| 932 | fh->dev = dev; | 936 | fh->dev = dev; |
| @@ -955,6 +959,7 @@ unlock: | |||
| 955 | sizeof(struct vivi_buffer), fh); | 959 | sizeof(struct vivi_buffer), fh); |
| 956 | 960 | ||
| 957 | vivi_start_thread(fh); | 961 | vivi_start_thread(fh); |
| 962 | unlock_kernel(); | ||
| 958 | 963 | ||
| 959 | return 0; | 964 | return 0; |
| 960 | } | 965 | } |
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index 35293029da02..45be9ec8edc4 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c | |||
| @@ -24,8 +24,6 @@ | |||
| 24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | 26 | ||
| 27 | #include <linux/byteorder/swab.h> | ||
| 28 | |||
| 29 | #include <asm/io.h> | 27 | #include <asm/io.h> |
| 30 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
| 31 | 29 | ||
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 2ff00bc5ad64..b2dbe48a92bb 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c | |||
| @@ -113,6 +113,7 @@ struct w9966_dev { | |||
| 113 | signed char contrast; | 113 | signed char contrast; |
| 114 | signed char color; | 114 | signed char color; |
| 115 | signed char hue; | 115 | signed char hue; |
| 116 | unsigned long in_use; | ||
| 116 | }; | 117 | }; |
| 117 | 118 | ||
| 118 | /* | 119 | /* |
| @@ -184,10 +185,25 @@ static int w9966_v4l_ioctl(struct inode *inode, struct file *file, | |||
| 184 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, | 185 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, |
| 185 | size_t count, loff_t *ppos); | 186 | size_t count, loff_t *ppos); |
| 186 | 187 | ||
| 188 | static int w9966_exclusive_open(struct inode *inode, struct file *file) | ||
| 189 | { | ||
| 190 | struct w9966_dev *cam = video_drvdata(file); | ||
| 191 | |||
| 192 | return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0; | ||
| 193 | } | ||
| 194 | |||
| 195 | static int w9966_exclusive_release(struct inode *inode, struct file *file) | ||
| 196 | { | ||
| 197 | struct w9966_dev *cam = video_drvdata(file); | ||
| 198 | |||
| 199 | clear_bit(0, &cam->in_use); | ||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | |||
| 187 | static const struct file_operations w9966_fops = { | 203 | static const struct file_operations w9966_fops = { |
| 188 | .owner = THIS_MODULE, | 204 | .owner = THIS_MODULE, |
| 189 | .open = video_exclusive_open, | 205 | .open = w9966_exclusive_open, |
| 190 | .release = video_exclusive_release, | 206 | .release = w9966_exclusive_release, |
| 191 | .ioctl = w9966_v4l_ioctl, | 207 | .ioctl = w9966_v4l_ioctl, |
| 192 | #ifdef CONFIG_COMPAT | 208 | #ifdef CONFIG_COMPAT |
| 193 | .compat_ioctl = v4l_compat_ioctl32, | 209 | .compat_ioctl = v4l_compat_ioctl32, |
| @@ -198,6 +214,7 @@ static const struct file_operations w9966_fops = { | |||
| 198 | static struct video_device w9966_template = { | 214 | static struct video_device w9966_template = { |
| 199 | .name = W9966_DRIVERNAME, | 215 | .name = W9966_DRIVERNAME, |
| 200 | .fops = &w9966_fops, | 216 | .fops = &w9966_fops, |
| 217 | .release = video_device_release_empty, | ||
| 201 | }; | 218 | }; |
| 202 | 219 | ||
| 203 | /* | 220 | /* |
| @@ -332,7 +349,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) | |||
| 332 | 349 | ||
| 333 | // Fill in the video_device struct and register us to v4l | 350 | // Fill in the video_device struct and register us to v4l |
| 334 | memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); | 351 | memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); |
| 335 | cam->vdev.priv = cam; | 352 | video_set_drvdata(&cam->vdev, cam); |
| 336 | 353 | ||
| 337 | if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) | 354 | if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) |
| 338 | return -1; | 355 | return -1; |
| @@ -713,8 +730,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data) | |||
| 713 | static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, | 730 | static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, |
| 714 | unsigned int cmd, void *arg) | 731 | unsigned int cmd, void *arg) |
| 715 | { | 732 | { |
| 716 | struct video_device *vdev = video_devdata(file); | 733 | struct w9966_dev *cam = video_drvdata(file); |
| 717 | struct w9966_dev *cam = vdev->priv; | ||
| 718 | 734 | ||
| 719 | switch(cmd) | 735 | switch(cmd) |
| 720 | { | 736 | { |
| @@ -872,8 +888,7 @@ static int w9966_v4l_ioctl(struct inode *inode, struct file *file, | |||
| 872 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, | 888 | static ssize_t w9966_v4l_read(struct file *file, char __user *buf, |
| 873 | size_t count, loff_t *ppos) | 889 | size_t count, loff_t *ppos) |
| 874 | { | 890 | { |
| 875 | struct video_device *vdev = video_devdata(file); | 891 | struct w9966_dev *cam = video_drvdata(file); |
| 876 | struct w9966_dev *cam = vdev->priv; | ||
| 877 | unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000 | 892 | unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000 |
| 878 | unsigned char __user *dest = (unsigned char __user *)buf; | 893 | unsigned char __user *dest = (unsigned char __user *)buf; |
| 879 | unsigned long dleft = count; | 894 | unsigned long dleft = count; |
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 0c3287734c93..6a0902bcba6b 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c | |||
| @@ -657,7 +657,7 @@ static int zc0301_open(struct inode* inode, struct file* filp) | |||
| 657 | if (!down_read_trylock(&zc0301_dev_lock)) | 657 | if (!down_read_trylock(&zc0301_dev_lock)) |
| 658 | return -EAGAIN; | 658 | return -EAGAIN; |
| 659 | 659 | ||
| 660 | cam = video_get_drvdata(video_devdata(filp)); | 660 | cam = video_drvdata(filp); |
| 661 | 661 | ||
| 662 | if (wait_for_completion_interruptible(&cam->probe)) { | 662 | if (wait_for_completion_interruptible(&cam->probe)) { |
| 663 | up_read(&zc0301_dev_lock); | 663 | up_read(&zc0301_dev_lock); |
| @@ -739,7 +739,7 @@ static int zc0301_release(struct inode* inode, struct file* filp) | |||
| 739 | 739 | ||
| 740 | down_write(&zc0301_dev_lock); | 740 | down_write(&zc0301_dev_lock); |
| 741 | 741 | ||
| 742 | cam = video_get_drvdata(video_devdata(filp)); | 742 | cam = video_drvdata(filp); |
| 743 | 743 | ||
| 744 | zc0301_stop_transfer(cam); | 744 | zc0301_stop_transfer(cam); |
| 745 | zc0301_release_buffers(cam); | 745 | zc0301_release_buffers(cam); |
| @@ -759,7 +759,7 @@ static int zc0301_release(struct inode* inode, struct file* filp) | |||
| 759 | static ssize_t | 759 | static ssize_t |
| 760 | zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) | 760 | zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) |
| 761 | { | 761 | { |
| 762 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 762 | struct zc0301_device *cam = video_drvdata(filp); |
| 763 | struct zc0301_frame_t* f, * i; | 763 | struct zc0301_frame_t* f, * i; |
| 764 | unsigned long lock_flags; | 764 | unsigned long lock_flags; |
| 765 | long timeout; | 765 | long timeout; |
| @@ -866,7 +866,7 @@ exit: | |||
| 866 | 866 | ||
| 867 | static unsigned int zc0301_poll(struct file *filp, poll_table *wait) | 867 | static unsigned int zc0301_poll(struct file *filp, poll_table *wait) |
| 868 | { | 868 | { |
| 869 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 869 | struct zc0301_device *cam = video_drvdata(filp); |
| 870 | struct zc0301_frame_t* f; | 870 | struct zc0301_frame_t* f; |
| 871 | unsigned long lock_flags; | 871 | unsigned long lock_flags; |
| 872 | unsigned int mask = 0; | 872 | unsigned int mask = 0; |
| @@ -941,7 +941,7 @@ static struct vm_operations_struct zc0301_vm_ops = { | |||
| 941 | 941 | ||
| 942 | static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) | 942 | static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) |
| 943 | { | 943 | { |
| 944 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 944 | struct zc0301_device *cam = video_drvdata(filp); |
| 945 | unsigned long size = vma->vm_end - vma->vm_start, | 945 | unsigned long size = vma->vm_end - vma->vm_start, |
| 946 | start = vma->vm_start; | 946 | start = vma->vm_start; |
| 947 | void *pos; | 947 | void *pos; |
| @@ -1796,7 +1796,7 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) | |||
| 1796 | static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, | 1796 | static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, |
| 1797 | unsigned int cmd, void __user * arg) | 1797 | unsigned int cmd, void __user * arg) |
| 1798 | { | 1798 | { |
| 1799 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 1799 | struct zc0301_device *cam = video_drvdata(filp); |
| 1800 | 1800 | ||
| 1801 | switch (cmd) { | 1801 | switch (cmd) { |
| 1802 | 1802 | ||
| @@ -1891,7 +1891,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
| 1891 | static int zc0301_ioctl(struct inode* inode, struct file* filp, | 1891 | static int zc0301_ioctl(struct inode* inode, struct file* filp, |
| 1892 | unsigned int cmd, unsigned long arg) | 1892 | unsigned int cmd, unsigned long arg) |
| 1893 | { | 1893 | { |
| 1894 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 1894 | struct zc0301_device *cam = video_drvdata(filp); |
| 1895 | int err = 0; | 1895 | int err = 0; |
| 1896 | 1896 | ||
| 1897 | if (mutex_lock_interruptible(&cam->fileop_mutex)) | 1897 | if (mutex_lock_interruptible(&cam->fileop_mutex)) |
diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig new file mode 100644 index 000000000000..4ea5fa71de89 --- /dev/null +++ b/drivers/media/video/zoran/Kconfig | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | config VIDEO_ZORAN | ||
| 2 | tristate "Zoran ZR36057/36067 Video For Linux" | ||
| 3 | depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS | ||
| 4 | help | ||
| 5 | Say Y for support for MJPEG capture cards based on the Zoran | ||
| 6 | 36057/36067 PCI controller chipset. This includes the Iomega | ||
| 7 | Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is | ||
| 8 | a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For | ||
| 9 | more information, check <file:Documentation/video4linux/Zoran>. | ||
| 10 | |||
| 11 | To compile this driver as a module, choose M here: the | ||
| 12 | module will be called zr36067. | ||
| 13 | |||
| 14 | config VIDEO_ZORAN_DC30 | ||
| 15 | tristate "Pinnacle/Miro DC30(+) support" | ||
| 16 | depends on VIDEO_ZORAN | ||
| 17 | select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO | ||
| 18 | select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO | ||
| 19 | help | ||
| 20 | Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback | ||
| 21 | card. This also supports really old DC10 cards based on the | ||
| 22 | zr36050 MJPEG codec and zr36016 VFE. | ||
| 23 | |||
| 24 | config VIDEO_ZORAN_ZR36060 | ||
| 25 | tristate "Zoran ZR36060" | ||
| 26 | depends on VIDEO_ZORAN | ||
| 27 | help | ||
| 28 | Say Y to support Zoran boards based on 36060 chips. | ||
| 29 | This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33 | ||
| 30 | and 33 R10 and AverMedia 6 boards. | ||
| 31 | |||
| 32 | config VIDEO_ZORAN_BUZ | ||
| 33 | tristate "Iomega Buz support" | ||
| 34 | depends on VIDEO_ZORAN_ZR36060 | ||
| 35 | select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO | ||
| 36 | select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO | ||
| 37 | help | ||
| 38 | Support for the Iomega Buz MJPEG capture/playback card. | ||
| 39 | |||
| 40 | config VIDEO_ZORAN_DC10 | ||
| 41 | tristate "Pinnacle/Miro DC10(+) support" | ||
| 42 | depends on VIDEO_ZORAN_ZR36060 | ||
| 43 | select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO | ||
| 44 | select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO | ||
| 45 | help | ||
| 46 | Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback | ||
| 47 | card. | ||
| 48 | |||
| 49 | config VIDEO_ZORAN_LML33 | ||
| 50 | tristate "Linux Media Labs LML33 support" | ||
| 51 | depends on VIDEO_ZORAN_ZR36060 | ||
| 52 | select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO | ||
| 53 | select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO | ||
| 54 | help | ||
| 55 | Support for the Linux Media Labs LML33 MJPEG capture/playback | ||
| 56 | card. | ||
| 57 | |||
| 58 | config VIDEO_ZORAN_LML33R10 | ||
| 59 | tristate "Linux Media Labs LML33R10 support" | ||
| 60 | depends on VIDEO_ZORAN_ZR36060 | ||
| 61 | select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO | ||
| 62 | select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO | ||
| 63 | help | ||
| 64 | support for the Linux Media Labs LML33R10 MJPEG capture/playback | ||
| 65 | card. | ||
| 66 | |||
| 67 | config VIDEO_ZORAN_AVS6EYES | ||
| 68 | tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" | ||
| 69 | depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 | ||
| 70 | select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO | ||
| 71 | select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO | ||
| 72 | help | ||
| 73 | Support for the AverMedia 6 Eyes video surveillance card. | ||
diff --git a/drivers/media/video/zoran/Makefile b/drivers/media/video/zoran/Makefile new file mode 100644 index 000000000000..44cc13352c88 --- /dev/null +++ b/drivers/media/video/zoran/Makefile | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | zr36067-objs := zoran_procfs.o zoran_device.o \ | ||
| 2 | zoran_driver.o zoran_card.o | ||
| 3 | |||
| 4 | obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o | ||
| 5 | obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o | ||
| 6 | obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o | ||
diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/zoran/videocodec.c index cf24956f3204..cf24956f3204 100644 --- a/drivers/media/video/videocodec.c +++ b/drivers/media/video/zoran/videocodec.c | |||
diff --git a/drivers/media/video/videocodec.h b/drivers/media/video/zoran/videocodec.h index 97a3bbeda505..97a3bbeda505 100644 --- a/drivers/media/video/videocodec.h +++ b/drivers/media/video/zoran/videocodec.h | |||
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran/zoran.h index 46b7ad477ceb..46b7ad477ceb 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran/zoran.h | |||
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 3282be730298..3282be730298 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c | |||
diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran/zoran_card.h index e4dc9d29b404..e4dc9d29b404 100644 --- a/drivers/media/video/zoran_card.h +++ b/drivers/media/video/zoran/zoran_card.h | |||
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index 88d369708e4c..5d948ff7faf0 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c | |||
| @@ -58,8 +58,6 @@ | |||
| 58 | ZR36057_ISR_GIRQ1 | \ | 58 | ZR36057_ISR_GIRQ1 | \ |
| 59 | ZR36057_ISR_JPEGRepIRQ ) | 59 | ZR36057_ISR_JPEGRepIRQ ) |
| 60 | 60 | ||
| 61 | extern const struct zoran_format zoran_formats[]; | ||
| 62 | |||
| 63 | static int lml33dpath; /* default = 0 | 61 | static int lml33dpath; /* default = 0 |
| 64 | * 1 will use digital path in capture | 62 | * 1 will use digital path in capture |
| 65 | * mode instead of analog. It can be | 63 | * mode instead of analog. It can be |
| @@ -377,7 +375,7 @@ zr36057_set_vfe (struct zoran *zr, | |||
| 377 | 375 | ||
| 378 | /* horizontal */ | 376 | /* horizontal */ |
| 379 | VidWinWid = video_width; | 377 | VidWinWid = video_width; |
| 380 | X = (VidWinWid * 64 + tvn->Wa - 1) / tvn->Wa; | 378 | X = DIV_ROUND_UP(VidWinWid * 64, tvn->Wa); |
| 381 | We = (VidWinWid * 64) / X; | 379 | We = (VidWinWid * 64) / X; |
| 382 | HorDcm = 64 - X; | 380 | HorDcm = 64 - X; |
| 383 | hcrop1 = 2 * ((tvn->Wa - We) / 4); | 381 | hcrop1 = 2 * ((tvn->Wa - We) / 4); |
| @@ -403,7 +401,7 @@ zr36057_set_vfe (struct zoran *zr, | |||
| 403 | /* Vertical */ | 401 | /* Vertical */ |
| 404 | DispMode = !(video_height > BUZ_MAX_HEIGHT / 2); | 402 | DispMode = !(video_height > BUZ_MAX_HEIGHT / 2); |
| 405 | VidWinHt = DispMode ? video_height : video_height / 2; | 403 | VidWinHt = DispMode ? video_height : video_height / 2; |
| 406 | Y = (VidWinHt * 64 * 2 + tvn->Ha - 1) / tvn->Ha; | 404 | Y = DIV_ROUND_UP(VidWinHt * 64 * 2, tvn->Ha); |
| 407 | He = (VidWinHt * 64) / Y; | 405 | He = (VidWinHt * 64) / Y; |
| 408 | VerDcm = 64 - Y; | 406 | VerDcm = 64 - Y; |
| 409 | vcrop1 = (tvn->Ha / 2 - He) / 2; | 407 | vcrop1 = (tvn->Ha / 2 - He) / 2; |
diff --git a/drivers/media/video/zoran_device.h b/drivers/media/video/zoran/zoran_device.h index 37fa86a34083..74c6c8edb7d0 100644 --- a/drivers/media/video/zoran_device.h +++ b/drivers/media/video/zoran/zoran_device.h | |||
| @@ -78,6 +78,14 @@ extern void zoran_set_pci_master(struct zoran *zr, | |||
| 78 | extern void zoran_init_hardware(struct zoran *zr); | 78 | extern void zoran_init_hardware(struct zoran *zr); |
| 79 | extern void zr36057_restart(struct zoran *zr); | 79 | extern void zr36057_restart(struct zoran *zr); |
| 80 | 80 | ||
| 81 | extern const struct zoran_format zoran_formats[]; | ||
| 82 | |||
| 83 | extern int v4l_nbufs; | ||
| 84 | extern int v4l_bufsize; | ||
| 85 | extern int jpg_nbufs; | ||
| 86 | extern int jpg_bufsize; | ||
| 87 | extern int pass_through; | ||
| 88 | |||
| 81 | /* i2c */ | 89 | /* i2c */ |
| 82 | extern int decoder_command(struct zoran *zr, | 90 | extern int decoder_command(struct zoran *zr, |
| 83 | int cmd, | 91 | int cmd, |
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 2dab9eea4def..25de7631443e 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
| @@ -194,12 +194,6 @@ const struct zoran_format zoran_formats[] = { | |||
| 194 | // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined | 194 | // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined |
| 195 | 195 | ||
| 196 | 196 | ||
| 197 | extern int v4l_nbufs; | ||
| 198 | extern int v4l_bufsize; | ||
| 199 | extern int jpg_nbufs; | ||
| 200 | extern int jpg_bufsize; | ||
| 201 | extern int pass_through; | ||
| 202 | |||
| 203 | static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */ | 197 | static int lock_norm; /* 0 = default 1 = Don't change TV standard (norm) */ |
| 204 | module_param(lock_norm, int, 0644); | 198 | module_param(lock_norm, int, 0644); |
| 205 | MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); | 199 | MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); |
| @@ -1211,6 +1205,7 @@ zoran_open (struct inode *inode, | |||
| 1211 | struct zoran_fh *fh; | 1205 | struct zoran_fh *fh; |
| 1212 | int i, res, first_open = 0, have_module_locks = 0; | 1206 | int i, res, first_open = 0, have_module_locks = 0; |
| 1213 | 1207 | ||
| 1208 | lock_kernel(); | ||
| 1214 | /* find the device */ | 1209 | /* find the device */ |
| 1215 | for (i = 0; i < zoran_num; i++) { | 1210 | for (i = 0; i < zoran_num; i++) { |
| 1216 | if (zoran[i]->video_dev->minor == minor) { | 1211 | if (zoran[i]->video_dev->minor == minor) { |
| @@ -1321,6 +1316,7 @@ zoran_open (struct inode *inode, | |||
| 1321 | file->private_data = fh; | 1316 | file->private_data = fh; |
| 1322 | fh->zr = zr; | 1317 | fh->zr = zr; |
| 1323 | zoran_open_init_session(file); | 1318 | zoran_open_init_session(file); |
| 1319 | unlock_kernel(); | ||
| 1324 | 1320 | ||
| 1325 | return 0; | 1321 | return 0; |
| 1326 | 1322 | ||
| @@ -1338,6 +1334,7 @@ open_unlock_and_return: | |||
| 1338 | if (zr) { | 1334 | if (zr) { |
| 1339 | /*mutex_unlock(&zr->resource_lock);*/ | 1335 | /*mutex_unlock(&zr->resource_lock);*/ |
| 1340 | } | 1336 | } |
| 1337 | unlock_kernel(); | ||
| 1341 | 1338 | ||
| 1342 | return res; | 1339 | return res; |
| 1343 | } | 1340 | } |
| @@ -2920,6 +2917,8 @@ zoran_do_ioctl (struct inode *inode, | |||
| 2920 | fmt->fmt.pix.bytesperline = 0; | 2917 | fmt->fmt.pix.bytesperline = 0; |
| 2921 | fmt->fmt.pix.sizeimage = | 2918 | fmt->fmt.pix.sizeimage = |
| 2922 | fh->jpg_buffers.buffer_size; | 2919 | fh->jpg_buffers.buffer_size; |
| 2920 | fmt->fmt.pix.colorspace = | ||
| 2921 | V4L2_COLORSPACE_SMPTE170M; | ||
| 2923 | 2922 | ||
| 2924 | /* we hereby abuse this variable to show that | 2923 | /* we hereby abuse this variable to show that |
| 2925 | * we're gonna do mjpeg capture */ | 2924 | * we're gonna do mjpeg capture */ |
| @@ -2979,6 +2978,8 @@ zoran_do_ioctl (struct inode *inode, | |||
| 2979 | fmt->fmt.pix.sizeimage = | 2978 | fmt->fmt.pix.sizeimage = |
| 2980 | fh->v4l_settings.height * | 2979 | fh->v4l_settings.height * |
| 2981 | fh->v4l_settings.bytesperline; | 2980 | fh->v4l_settings.bytesperline; |
| 2981 | fmt->fmt.pix.colorspace = | ||
| 2982 | fh->v4l_settings.format->colorspace; | ||
| 2982 | if (BUZ_MAX_HEIGHT < | 2983 | if (BUZ_MAX_HEIGHT < |
| 2983 | (fh->v4l_settings.height * 2)) | 2984 | (fh->v4l_settings.height * 2)) |
| 2984 | fmt->fmt.pix.field = | 2985 | fmt->fmt.pix.field = |
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran/zoran_procfs.c index 870bc5a70e3f..870bc5a70e3f 100644 --- a/drivers/media/video/zoran_procfs.c +++ b/drivers/media/video/zoran/zoran_procfs.c | |||
diff --git a/drivers/media/video/zoran_procfs.h b/drivers/media/video/zoran/zoran_procfs.h index f2d5b1ba448f..f2d5b1ba448f 100644 --- a/drivers/media/video/zoran_procfs.h +++ b/drivers/media/video/zoran/zoran_procfs.h | |||
diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zoran/zr36016.c index 00d132bcd1e4..00d132bcd1e4 100644 --- a/drivers/media/video/zr36016.c +++ b/drivers/media/video/zoran/zr36016.c | |||
diff --git a/drivers/media/video/zr36016.h b/drivers/media/video/zoran/zr36016.h index 8c79229f69d1..8c79229f69d1 100644 --- a/drivers/media/video/zr36016.h +++ b/drivers/media/video/zoran/zr36016.h | |||
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zoran/zr36050.c index cf8b271a1c8f..cf8b271a1c8f 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zoran/zr36050.c | |||
diff --git a/drivers/media/video/zr36050.h b/drivers/media/video/zoran/zr36050.h index 9f52f0cdde50..9f52f0cdde50 100644 --- a/drivers/media/video/zr36050.h +++ b/drivers/media/video/zoran/zr36050.h | |||
diff --git a/drivers/media/video/zr36057.h b/drivers/media/video/zoran/zr36057.h index 54c9362aa980..54c9362aa980 100644 --- a/drivers/media/video/zr36057.h +++ b/drivers/media/video/zoran/zr36057.h | |||
diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zoran/zr36060.c index 8e74054d5ef1..8e74054d5ef1 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zoran/zr36060.c | |||
diff --git a/drivers/media/video/zr36060.h b/drivers/media/video/zoran/zr36060.h index 914ffa4ad8d3..914ffa4ad8d3 100644 --- a/drivers/media/video/zr36060.h +++ b/drivers/media/video/zoran/zr36060.h | |||
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 18d1c4ba79fb..7cdac99deea6 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | 52 | ||
| 53 | 53 | ||
| 54 | /* Debug macro */ | 54 | /* Debug macro */ |
| 55 | #define DBG(x...) if (debug) info(x) | 55 | #define DBG(x...) if (debug) printk(KERN_INFO KBUILD_MODNAME x) |
| 56 | 56 | ||
| 57 | 57 | ||
| 58 | /* Init methods, need to find nicer names for these | 58 | /* Init methods, need to find nicer names for these |
| @@ -116,6 +116,7 @@ struct zr364xx_camera { | |||
| 116 | int height; | 116 | int height; |
| 117 | int method; | 117 | int method; |
| 118 | struct mutex lock; | 118 | struct mutex lock; |
| 119 | int users; | ||
| 119 | }; | 120 | }; |
| 120 | 121 | ||
| 121 | 122 | ||
| @@ -127,7 +128,7 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value, | |||
| 127 | 128 | ||
| 128 | unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL); | 129 | unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL); |
| 129 | if (!transfer_buffer) { | 130 | if (!transfer_buffer) { |
| 130 | info("kmalloc(%d) failed", size); | 131 | dev_err(&udev->dev, "kmalloc(%d) failed\n", size); |
| 131 | return -ENOMEM; | 132 | return -ENOMEM; |
| 132 | } | 133 | } |
| 133 | 134 | ||
| @@ -143,7 +144,8 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value, | |||
| 143 | kfree(transfer_buffer); | 144 | kfree(transfer_buffer); |
| 144 | 145 | ||
| 145 | if (status < 0) | 146 | if (status < 0) |
| 146 | info("Failed sending control message, error %d.", status); | 147 | dev_err(&udev->dev, |
| 148 | "Failed sending control message, error %d.\n", status); | ||
| 147 | 149 | ||
| 148 | return status; | 150 | return status; |
| 149 | } | 151 | } |
| @@ -303,11 +305,11 @@ static int read_frame(struct zr364xx_camera *cam, int framenum) | |||
| 303 | DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]); | 305 | DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]); |
| 304 | DBG("bulk : n=%d size=%d", n, actual_length); | 306 | DBG("bulk : n=%d size=%d", n, actual_length); |
| 305 | if (n < 0) { | 307 | if (n < 0) { |
| 306 | info("error reading bulk msg"); | 308 | dev_err(&cam->udev->dev, "error reading bulk msg\n"); |
| 307 | return 0; | 309 | return 0; |
| 308 | } | 310 | } |
| 309 | if (actual_length < 0 || actual_length > BUFFER_SIZE) { | 311 | if (actual_length < 0 || actual_length > BUFFER_SIZE) { |
| 310 | info("wrong number of bytes"); | 312 | dev_err(&cam->udev->dev, "wrong number of bytes\n"); |
| 311 | return 0; | 313 | return 0; |
| 312 | } | 314 | } |
| 313 | 315 | ||
| @@ -641,42 +643,47 @@ static int zr364xx_open(struct inode *inode, struct file *file) | |||
| 641 | 643 | ||
| 642 | DBG("zr364xx_open"); | 644 | DBG("zr364xx_open"); |
| 643 | 645 | ||
| 644 | cam->skip = 2; | 646 | mutex_lock(&cam->lock); |
| 645 | 647 | ||
| 646 | err = video_exclusive_open(inode, file); | 648 | if (cam->users) { |
| 647 | if (err < 0) | 649 | err = -EBUSY; |
| 648 | return err; | 650 | goto out; |
| 651 | } | ||
| 649 | 652 | ||
| 650 | if (!cam->framebuf) { | 653 | if (!cam->framebuf) { |
| 651 | cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); | 654 | cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES); |
| 652 | if (!cam->framebuf) { | 655 | if (!cam->framebuf) { |
| 653 | info("vmalloc_32 failed!"); | 656 | dev_err(&cam->udev->dev, "vmalloc_32 failed!\n"); |
| 654 | return -ENOMEM; | 657 | err = -ENOMEM; |
| 658 | goto out; | ||
| 655 | } | 659 | } |
| 656 | } | 660 | } |
| 657 | 661 | ||
| 658 | mutex_lock(&cam->lock); | ||
| 659 | for (i = 0; init[cam->method][i].size != -1; i++) { | 662 | for (i = 0; init[cam->method][i].size != -1; i++) { |
| 660 | err = | 663 | err = |
| 661 | send_control_msg(udev, 1, init[cam->method][i].value, | 664 | send_control_msg(udev, 1, init[cam->method][i].value, |
| 662 | 0, init[cam->method][i].bytes, | 665 | 0, init[cam->method][i].bytes, |
| 663 | init[cam->method][i].size); | 666 | init[cam->method][i].size); |
| 664 | if (err < 0) { | 667 | if (err < 0) { |
| 665 | info("error during open sequence: %d", i); | 668 | dev_err(&cam->udev->dev, |
| 666 | mutex_unlock(&cam->lock); | 669 | "error during open sequence: %d\n", i); |
| 667 | return err; | 670 | goto out; |
| 668 | } | 671 | } |
| 669 | } | 672 | } |
| 670 | 673 | ||
| 674 | cam->skip = 2; | ||
| 675 | cam->users++; | ||
| 671 | file->private_data = vdev; | 676 | file->private_data = vdev; |
| 672 | 677 | ||
| 673 | /* Added some delay here, since opening/closing the camera quickly, | 678 | /* Added some delay here, since opening/closing the camera quickly, |
| 674 | * like Ekiga does during its startup, can crash the webcam | 679 | * like Ekiga does during its startup, can crash the webcam |
| 675 | */ | 680 | */ |
| 676 | mdelay(100); | 681 | mdelay(100); |
| 682 | err = 0; | ||
| 677 | 683 | ||
| 684 | out: | ||
| 678 | mutex_unlock(&cam->lock); | 685 | mutex_unlock(&cam->lock); |
| 679 | return 0; | 686 | return err; |
| 680 | } | 687 | } |
| 681 | 688 | ||
| 682 | 689 | ||
| @@ -697,28 +704,30 @@ static int zr364xx_release(struct inode *inode, struct file *file) | |||
| 697 | udev = cam->udev; | 704 | udev = cam->udev; |
| 698 | 705 | ||
| 699 | mutex_lock(&cam->lock); | 706 | mutex_lock(&cam->lock); |
| 707 | |||
| 708 | cam->users--; | ||
| 709 | file->private_data = NULL; | ||
| 710 | |||
| 700 | for (i = 0; i < 2; i++) { | 711 | for (i = 0; i < 2; i++) { |
| 701 | err = | 712 | err = |
| 702 | send_control_msg(udev, 1, init[cam->method][i].value, | 713 | send_control_msg(udev, 1, init[cam->method][i].value, |
| 703 | 0, init[i][cam->method].bytes, | 714 | 0, init[i][cam->method].bytes, |
| 704 | init[cam->method][i].size); | 715 | init[cam->method][i].size); |
| 705 | if (err < 0) { | 716 | if (err < 0) { |
| 706 | info("error during release sequence"); | 717 | dev_err(&udev->dev, "error during release sequence\n"); |
| 707 | mutex_unlock(&cam->lock); | 718 | goto out; |
| 708 | return err; | ||
| 709 | } | 719 | } |
| 710 | } | 720 | } |
| 711 | 721 | ||
| 712 | file->private_data = NULL; | ||
| 713 | video_exclusive_release(inode, file); | ||
| 714 | |||
| 715 | /* Added some delay here, since opening/closing the camera quickly, | 722 | /* Added some delay here, since opening/closing the camera quickly, |
| 716 | * like Ekiga does during its startup, can crash the webcam | 723 | * like Ekiga does during its startup, can crash the webcam |
| 717 | */ | 724 | */ |
| 718 | mdelay(100); | 725 | mdelay(100); |
| 726 | err = 0; | ||
| 719 | 727 | ||
| 728 | out: | ||
| 720 | mutex_unlock(&cam->lock); | 729 | mutex_unlock(&cam->lock); |
| 721 | return 0; | 730 | return err; |
| 722 | } | 731 | } |
| 723 | 732 | ||
| 724 | 733 | ||
| @@ -801,13 +810,14 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
| 801 | 810 | ||
| 802 | DBG("probing..."); | 811 | DBG("probing..."); |
| 803 | 812 | ||
| 804 | info(DRIVER_DESC " compatible webcam plugged"); | 813 | dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n"); |
| 805 | info("model %04x:%04x detected", udev->descriptor.idVendor, | 814 | dev_info(&intf->dev, "model %04x:%04x detected\n", |
| 806 | udev->descriptor.idProduct); | 815 | le16_to_cpu(udev->descriptor.idVendor), |
| 816 | le16_to_cpu(udev->descriptor.idProduct)); | ||
| 807 | 817 | ||
| 808 | cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL); | 818 | cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL); |
| 809 | if (cam == NULL) { | 819 | if (cam == NULL) { |
| 810 | info("cam: out of memory !"); | 820 | dev_err(&udev->dev, "cam: out of memory !\n"); |
| 811 | return -ENOMEM; | 821 | return -ENOMEM; |
| 812 | } | 822 | } |
| 813 | /* save the init method used by this camera */ | 823 | /* save the init method used by this camera */ |
| @@ -815,7 +825,7 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
| 815 | 825 | ||
| 816 | cam->vdev = video_device_alloc(); | 826 | cam->vdev = video_device_alloc(); |
| 817 | if (cam->vdev == NULL) { | 827 | if (cam->vdev == NULL) { |
| 818 | info("cam->vdev: out of memory !"); | 828 | dev_err(&udev->dev, "cam->vdev: out of memory !\n"); |
| 819 | kfree(cam); | 829 | kfree(cam); |
| 820 | return -ENOMEM; | 830 | return -ENOMEM; |
| 821 | } | 831 | } |
| @@ -827,7 +837,7 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
| 827 | cam->udev = udev; | 837 | cam->udev = udev; |
| 828 | 838 | ||
| 829 | if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) { | 839 | if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) { |
| 830 | info("cam->buffer: out of memory !"); | 840 | dev_info(&udev->dev, "cam->buffer: out of memory !\n"); |
| 831 | video_device_release(cam->vdev); | 841 | video_device_release(cam->vdev); |
| 832 | kfree(cam); | 842 | kfree(cam); |
| 833 | return -ENODEV; | 843 | return -ENODEV; |
| @@ -835,17 +845,17 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
| 835 | 845 | ||
| 836 | switch (mode) { | 846 | switch (mode) { |
| 837 | case 1: | 847 | case 1: |
| 838 | info("160x120 mode selected"); | 848 | dev_info(&udev->dev, "160x120 mode selected\n"); |
| 839 | cam->width = 160; | 849 | cam->width = 160; |
| 840 | cam->height = 120; | 850 | cam->height = 120; |
| 841 | break; | 851 | break; |
| 842 | case 2: | 852 | case 2: |
| 843 | info("640x480 mode selected"); | 853 | dev_info(&udev->dev, "640x480 mode selected\n"); |
| 844 | cam->width = 640; | 854 | cam->width = 640; |
| 845 | cam->height = 480; | 855 | cam->height = 480; |
| 846 | break; | 856 | break; |
| 847 | default: | 857 | default: |
| 848 | info("320x240 mode selected"); | 858 | dev_info(&udev->dev, "320x240 mode selected\n"); |
| 849 | cam->width = 320; | 859 | cam->width = 320; |
| 850 | cam->height = 240; | 860 | cam->height = 240; |
| 851 | break; | 861 | break; |
| @@ -865,7 +875,7 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
| 865 | 875 | ||
| 866 | err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); | 876 | err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1); |
| 867 | if (err) { | 877 | if (err) { |
| 868 | info("video_register_device failed"); | 878 | dev_err(&udev->dev, "video_register_device failed\n"); |
| 869 | video_device_release(cam->vdev); | 879 | video_device_release(cam->vdev); |
| 870 | kfree(cam->buffer); | 880 | kfree(cam->buffer); |
| 871 | kfree(cam); | 881 | kfree(cam); |
| @@ -874,7 +884,8 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
| 874 | 884 | ||
| 875 | usb_set_intfdata(intf, cam); | 885 | usb_set_intfdata(intf, cam); |
| 876 | 886 | ||
| 877 | info(DRIVER_DESC " controlling video device %d", cam->vdev->minor); | 887 | dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", |
| 888 | cam->vdev->minor); | ||
| 878 | return 0; | 889 | return 0; |
| 879 | } | 890 | } |
| 880 | 891 | ||
| @@ -884,7 +895,7 @@ static void zr364xx_disconnect(struct usb_interface *intf) | |||
| 884 | struct zr364xx_camera *cam = usb_get_intfdata(intf); | 895 | struct zr364xx_camera *cam = usb_get_intfdata(intf); |
| 885 | usb_set_intfdata(intf, NULL); | 896 | usb_set_intfdata(intf, NULL); |
| 886 | dev_set_drvdata(&intf->dev, NULL); | 897 | dev_set_drvdata(&intf->dev, NULL); |
| 887 | info(DRIVER_DESC " webcam unplugged"); | 898 | dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n"); |
| 888 | if (cam->vdev) | 899 | if (cam->vdev) |
| 889 | video_unregister_device(cam->vdev); | 900 | video_unregister_device(cam->vdev); |
| 890 | cam->vdev = NULL; | 901 | cam->vdev = NULL; |
| @@ -913,16 +924,16 @@ static int __init zr364xx_init(void) | |||
| 913 | int retval; | 924 | int retval; |
| 914 | retval = usb_register(&zr364xx_driver); | 925 | retval = usb_register(&zr364xx_driver); |
| 915 | if (retval) | 926 | if (retval) |
| 916 | info("usb_register failed!"); | 927 | printk(KERN_ERR KBUILD_MODNAME ": usb_register failed!\n"); |
| 917 | else | 928 | else |
| 918 | info(DRIVER_DESC " module loaded"); | 929 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); |
| 919 | return retval; | 930 | return retval; |
| 920 | } | 931 | } |
| 921 | 932 | ||
| 922 | 933 | ||
| 923 | static void __exit zr364xx_exit(void) | 934 | static void __exit zr364xx_exit(void) |
| 924 | { | 935 | { |
| 925 | info(DRIVER_DESC " module unloaded"); | 936 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC " module unloaded\n"); |
| 926 | usb_deregister(&zr364xx_driver); | 937 | usb_deregister(&zr364xx_driver); |
| 927 | } | 938 | } |
| 928 | 939 | ||
diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index c8cbd90ba375..6e4ace270276 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h | |||
| @@ -62,6 +62,7 @@ typedef enum fe_caps { | |||
| 62 | FE_CAN_HIERARCHY_AUTO = 0x100000, | 62 | FE_CAN_HIERARCHY_AUTO = 0x100000, |
| 63 | FE_CAN_8VSB = 0x200000, | 63 | FE_CAN_8VSB = 0x200000, |
| 64 | FE_CAN_16VSB = 0x400000, | 64 | FE_CAN_16VSB = 0x400000, |
| 65 | FE_HAS_EXTENDED_CAPS = 0x800000, // We need more bitspace for newer APIs, indicate this. | ||
| 65 | FE_NEEDS_BENDING = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending) | 66 | FE_NEEDS_BENDING = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending) |
| 66 | FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically | 67 | FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically |
| 67 | FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output | 68 | FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output |
| @@ -147,7 +148,9 @@ typedef enum fe_code_rate { | |||
| 147 | FEC_6_7, | 148 | FEC_6_7, |
| 148 | FEC_7_8, | 149 | FEC_7_8, |
| 149 | FEC_8_9, | 150 | FEC_8_9, |
| 150 | FEC_AUTO | 151 | FEC_AUTO, |
| 152 | FEC_3_5, | ||
| 153 | FEC_9_10, | ||
| 151 | } fe_code_rate_t; | 154 | } fe_code_rate_t; |
| 152 | 155 | ||
| 153 | 156 | ||
| @@ -160,7 +163,10 @@ typedef enum fe_modulation { | |||
| 160 | QAM_256, | 163 | QAM_256, |
| 161 | QAM_AUTO, | 164 | QAM_AUTO, |
| 162 | VSB_8, | 165 | VSB_8, |
| 163 | VSB_16 | 166 | VSB_16, |
| 167 | PSK_8, | ||
| 168 | APSK_16, | ||
| 169 | DQPSK, | ||
| 164 | } fe_modulation_t; | 170 | } fe_modulation_t; |
| 165 | 171 | ||
| 166 | typedef enum fe_transmit_mode { | 172 | typedef enum fe_transmit_mode { |
| @@ -239,6 +245,106 @@ struct dvb_frontend_event { | |||
| 239 | struct dvb_frontend_parameters parameters; | 245 | struct dvb_frontend_parameters parameters; |
| 240 | }; | 246 | }; |
| 241 | 247 | ||
| 248 | /* S2API Commands */ | ||
| 249 | #define DTV_UNDEFINED 0 | ||
| 250 | #define DTV_TUNE 1 | ||
| 251 | #define DTV_CLEAR 2 | ||
| 252 | #define DTV_FREQUENCY 3 | ||
| 253 | #define DTV_MODULATION 4 | ||
| 254 | #define DTV_BANDWIDTH_HZ 5 | ||
| 255 | #define DTV_INVERSION 6 | ||
| 256 | #define DTV_DISEQC_MASTER 7 | ||
| 257 | #define DTV_SYMBOL_RATE 8 | ||
| 258 | #define DTV_INNER_FEC 9 | ||
| 259 | #define DTV_VOLTAGE 10 | ||
| 260 | #define DTV_TONE 11 | ||
| 261 | #define DTV_PILOT 12 | ||
| 262 | #define DTV_ROLLOFF 13 | ||
| 263 | #define DTV_DISEQC_SLAVE_REPLY 14 | ||
| 264 | |||
| 265 | /* Basic enumeration set for querying unlimited capabilities */ | ||
| 266 | #define DTV_FE_CAPABILITY_COUNT 15 | ||
| 267 | #define DTV_FE_CAPABILITY 16 | ||
| 268 | #define DTV_DELIVERY_SYSTEM 17 | ||
| 269 | |||
| 270 | #define DTV_API_VERSION 35 | ||
| 271 | #define DTV_API_VERSION 35 | ||
| 272 | #define DTV_CODE_RATE_HP 36 | ||
| 273 | #define DTV_CODE_RATE_LP 37 | ||
| 274 | #define DTV_GUARD_INTERVAL 38 | ||
| 275 | #define DTV_TRANSMISSION_MODE 39 | ||
| 276 | #define DTV_HIERARCHY 40 | ||
| 277 | |||
| 278 | #define DTV_MAX_COMMAND DTV_HIERARCHY | ||
| 279 | |||
| 280 | typedef enum fe_pilot { | ||
| 281 | PILOT_ON, | ||
| 282 | PILOT_OFF, | ||
| 283 | PILOT_AUTO, | ||
| 284 | } fe_pilot_t; | ||
| 285 | |||
| 286 | typedef enum fe_rolloff { | ||
| 287 | ROLLOFF_35, /* Implied value in DVB-S, default for DVB-S2 */ | ||
| 288 | ROLLOFF_20, | ||
| 289 | ROLLOFF_25, | ||
| 290 | ROLLOFF_AUTO, | ||
| 291 | } fe_rolloff_t; | ||
| 292 | |||
| 293 | typedef enum fe_delivery_system { | ||
| 294 | SYS_UNDEFINED, | ||
| 295 | SYS_DVBC_ANNEX_AC, | ||
| 296 | SYS_DVBC_ANNEX_B, | ||
| 297 | SYS_DVBT, | ||
| 298 | SYS_DVBS, | ||
| 299 | SYS_DVBS2, | ||
| 300 | SYS_DVBH, | ||
| 301 | SYS_ISDBT, | ||
| 302 | SYS_ISDBS, | ||
| 303 | SYS_ISDBC, | ||
| 304 | SYS_ATSC, | ||
| 305 | SYS_ATSCMH, | ||
| 306 | SYS_DMBTH, | ||
| 307 | SYS_CMMB, | ||
| 308 | SYS_DAB, | ||
| 309 | } fe_delivery_system_t; | ||
| 310 | |||
| 311 | struct dtv_cmds_h { | ||
| 312 | char *name; /* A display name for debugging purposes */ | ||
| 313 | |||
| 314 | __u32 cmd; /* A unique ID */ | ||
| 315 | |||
| 316 | /* Flags */ | ||
| 317 | __u32 set:1; /* Either a set or get property */ | ||
| 318 | __u32 buffer:1; /* Does this property use the buffer? */ | ||
| 319 | __u32 reserved:30; /* Align */ | ||
| 320 | }; | ||
| 321 | |||
| 322 | struct dtv_property { | ||
| 323 | __u32 cmd; | ||
| 324 | __u32 reserved[3]; | ||
| 325 | union { | ||
| 326 | __u32 data; | ||
| 327 | struct { | ||
| 328 | __u8 data[32]; | ||
| 329 | __u32 len; | ||
| 330 | __u32 reserved1[3]; | ||
| 331 | void *reserved2; | ||
| 332 | } buffer; | ||
| 333 | } u; | ||
| 334 | int result; | ||
| 335 | } __attribute__ ((packed)); | ||
| 336 | |||
| 337 | /* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */ | ||
| 338 | #define DTV_IOCTL_MAX_MSGS 64 | ||
| 339 | |||
| 340 | struct dtv_properties { | ||
| 341 | __u32 num; | ||
| 342 | struct dtv_property *props; | ||
| 343 | }; | ||
| 344 | |||
| 345 | #define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties) | ||
| 346 | #define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties) | ||
| 347 | |||
| 242 | 348 | ||
| 243 | /** | 349 | /** |
| 244 | * When set, this flag will disable any zigzagging or other "normal" tuning | 350 | * When set, this flag will disable any zigzagging or other "normal" tuning |
diff --git a/include/linux/dvb/version.h b/include/linux/dvb/version.h index 126e0c26cb09..25b823b81734 100644 --- a/include/linux/dvb/version.h +++ b/include/linux/dvb/version.h | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #ifndef _DVBVERSION_H_ | 23 | #ifndef _DVBVERSION_H_ |
| 24 | #define _DVBVERSION_H_ | 24 | #define _DVBVERSION_H_ |
| 25 | 25 | ||
| 26 | #define DVB_API_VERSION 3 | 26 | #define DVB_API_VERSION 5 |
| 27 | #define DVB_API_VERSION_MINOR 2 | 27 | #define DVB_API_VERSION_MINOR 0 |
| 28 | 28 | ||
| 29 | #endif /*_DVBVERSION_H_*/ | 29 | #endif /*_DVBVERSION_H_*/ |
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index bf34c5f4c051..493435bcdbe5 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #define I2C_DRIVERID_SAA7110 22 /* video decoder */ | 41 | #define I2C_DRIVERID_SAA7110 22 /* video decoder */ |
| 42 | #define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */ | 42 | #define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */ |
| 43 | #define I2C_DRIVERID_PCF8583 25 /* real time clock */ | 43 | #define I2C_DRIVERID_PCF8583 25 /* real time clock */ |
| 44 | #define I2C_DRIVERID_SAB3036 26 /* SAB3036 tuner */ | ||
| 45 | #define I2C_DRIVERID_TDA7432 27 /* Stereo sound processor */ | 44 | #define I2C_DRIVERID_TDA7432 27 /* Stereo sound processor */ |
| 46 | #define I2C_DRIVERID_TVMIXER 28 /* Mixer driver for tv cards */ | 45 | #define I2C_DRIVERID_TVMIXER 28 /* Mixer driver for tv cards */ |
| 47 | #define I2C_DRIVERID_TVAUDIO 29 /* Generic TV sound driver */ | 46 | #define I2C_DRIVERID_TVAUDIO 29 /* Generic TV sound driver */ |
diff --git a/include/linux/ivtv.h b/include/linux/ivtv.h index 17ca64b5a66c..f2720280b9ec 100644 --- a/include/linux/ivtv.h +++ b/include/linux/ivtv.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
| 25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
| 26 | #include <linux/videodev2.h> | ||
| 26 | 27 | ||
| 27 | /* ivtv knows several distinct output modes: MPEG streaming, | 28 | /* ivtv knows several distinct output modes: MPEG streaming, |
| 28 | YUV streaming, YUV updates through user DMA and the passthrough | 29 | YUV streaming, YUV updates through user DMA and the passthrough |
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 303d93ffd6b2..d4b03034ee73 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h | |||
| @@ -910,6 +910,8 @@ enum v4l2_mpeg_audio_encoding { | |||
| 910 | V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, | 910 | V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, |
| 911 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, | 911 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, |
| 912 | V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, | 912 | V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, |
| 913 | V4L2_MPEG_AUDIO_ENCODING_AAC = 3, | ||
| 914 | V4L2_MPEG_AUDIO_ENCODING_AC3 = 4, | ||
| 913 | }; | 915 | }; |
| 914 | #define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) | 916 | #define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) |
| 915 | enum v4l2_mpeg_audio_l1_bitrate { | 917 | enum v4l2_mpeg_audio_l1_bitrate { |
| @@ -988,12 +990,36 @@ enum v4l2_mpeg_audio_crc { | |||
| 988 | V4L2_MPEG_AUDIO_CRC_CRC16 = 1, | 990 | V4L2_MPEG_AUDIO_CRC_CRC16 = 1, |
| 989 | }; | 991 | }; |
| 990 | #define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) | 992 | #define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) |
| 993 | #define V4L2_CID_MPEG_AUDIO_AAC_BITRATE (V4L2_CID_MPEG_BASE+110) | ||
| 994 | #define V4L2_CID_MPEG_AUDIO_AC3_BITRATE (V4L2_CID_MPEG_BASE+111) | ||
| 995 | enum v4l2_mpeg_audio_ac3_bitrate { | ||
| 996 | V4L2_MPEG_AUDIO_AC3_BITRATE_32K = 0, | ||
| 997 | V4L2_MPEG_AUDIO_AC3_BITRATE_40K = 1, | ||
| 998 | V4L2_MPEG_AUDIO_AC3_BITRATE_48K = 2, | ||
| 999 | V4L2_MPEG_AUDIO_AC3_BITRATE_56K = 3, | ||
| 1000 | V4L2_MPEG_AUDIO_AC3_BITRATE_64K = 4, | ||
| 1001 | V4L2_MPEG_AUDIO_AC3_BITRATE_80K = 5, | ||
| 1002 | V4L2_MPEG_AUDIO_AC3_BITRATE_96K = 6, | ||
| 1003 | V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7, | ||
| 1004 | V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8, | ||
| 1005 | V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9, | ||
| 1006 | V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10, | ||
| 1007 | V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11, | ||
| 1008 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12, | ||
| 1009 | V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13, | ||
| 1010 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14, | ||
| 1011 | V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15, | ||
| 1012 | V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16, | ||
| 1013 | V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17, | ||
| 1014 | V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18, | ||
| 1015 | }; | ||
| 991 | 1016 | ||
| 992 | /* MPEG video */ | 1017 | /* MPEG video */ |
| 993 | #define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) | 1018 | #define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) |
| 994 | enum v4l2_mpeg_video_encoding { | 1019 | enum v4l2_mpeg_video_encoding { |
| 995 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, | 1020 | V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, |
| 996 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, | 1021 | V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, |
| 1022 | V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2, | ||
| 997 | }; | 1023 | }; |
| 998 | #define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) | 1024 | #define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) |
| 999 | enum v4l2_mpeg_video_aspect { | 1025 | enum v4l2_mpeg_video_aspect { |
diff --git a/include/media/ir-common.h b/include/media/ir-common.h index b8e8aa91905a..38f2d93c3957 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | #include <linux/input.h> | 26 | #include <linux/input.h> |
| 27 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
| 28 | #include <linux/interrupt.h> | ||
| 28 | 29 | ||
| 29 | #define IR_TYPE_RC5 1 | 30 | #define IR_TYPE_RC5 1 |
| 30 | #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ | 31 | #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ |
| @@ -85,6 +86,10 @@ struct card_ir { | |||
| 85 | u32 code; /* raw code under construction */ | 86 | u32 code; /* raw code under construction */ |
| 86 | struct timeval base_time; /* time of last seen code */ | 87 | struct timeval base_time; /* time of last seen code */ |
| 87 | int active; /* building raw code */ | 88 | int active; /* building raw code */ |
| 89 | |||
| 90 | /* NEC decoding */ | ||
| 91 | u32 nec_gpio; | ||
| 92 | struct tasklet_struct tlet; | ||
| 88 | }; | 93 | }; |
| 89 | 94 | ||
| 90 | void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, | 95 | void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, |
| @@ -105,6 +110,7 @@ void ir_rc5_timer_keyup(unsigned long data); | |||
| 105 | extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; | 110 | extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; |
| 106 | extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; | 111 | extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; |
| 107 | extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; | 112 | extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; |
| 113 | extern IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE]; | ||
| 108 | extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; | 114 | extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; |
| 109 | extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; | 115 | extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; |
| 110 | extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE]; | 116 | extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE]; |
| @@ -139,6 +145,7 @@ extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE]; | |||
| 139 | extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE]; | 145 | extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE]; |
| 140 | extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE]; | 146 | extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE]; |
| 141 | extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; | 147 | extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; |
| 148 | extern IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE]; | ||
| 142 | extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; | 149 | extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; |
| 143 | extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; | 150 | extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; |
| 144 | extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; | 151 | extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; |
| @@ -147,7 +154,9 @@ extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE]; | |||
| 147 | extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; | 154 | extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; |
| 148 | extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE]; | 155 | extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE]; |
| 149 | extern IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE]; | 156 | extern IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE]; |
| 150 | 157 | extern IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE]; | |
| 158 | extern IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE]; | ||
| 159 | extern IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE]; | ||
| 151 | #endif | 160 | #endif |
| 152 | 161 | ||
| 153 | /* | 162 | /* |
diff --git a/include/media/saa7115.h b/include/media/saa7115.h index f677dfb9d373..bab212719591 100644 --- a/include/media/saa7115.h +++ b/include/media/saa7115.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | saa7115.h - definition for saa7113/4/5 inputs and frequency flags | 2 | saa7115.h - definition for saa7111/3/4/5 inputs and frequency flags |
| 3 | 3 | ||
| 4 | Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) | 4 | Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) |
| 5 | 5 | ||
| @@ -21,13 +21,13 @@ | |||
| 21 | #ifndef _SAA7115_H_ | 21 | #ifndef _SAA7115_H_ |
| 22 | #define _SAA7115_H_ | 22 | #define _SAA7115_H_ |
| 23 | 23 | ||
| 24 | /* SAA7113/4/5 HW inputs */ | 24 | /* SAA7111/3/4/5 HW inputs */ |
| 25 | #define SAA7115_COMPOSITE0 0 | 25 | #define SAA7115_COMPOSITE0 0 |
| 26 | #define SAA7115_COMPOSITE1 1 | 26 | #define SAA7115_COMPOSITE1 1 |
| 27 | #define SAA7115_COMPOSITE2 2 | 27 | #define SAA7115_COMPOSITE2 2 |
| 28 | #define SAA7115_COMPOSITE3 3 | 28 | #define SAA7115_COMPOSITE3 3 |
| 29 | #define SAA7115_COMPOSITE4 4 /* not available for the saa7113 */ | 29 | #define SAA7115_COMPOSITE4 4 /* not available for the saa7111/3 */ |
| 30 | #define SAA7115_COMPOSITE5 5 /* not available for the saa7113 */ | 30 | #define SAA7115_COMPOSITE5 5 /* not available for the saa7111/3 */ |
| 31 | #define SAA7115_SVIDEO0 6 | 31 | #define SAA7115_SVIDEO0 6 |
| 32 | #define SAA7115_SVIDEO1 7 | 32 | #define SAA7115_SVIDEO1 7 |
| 33 | #define SAA7115_SVIDEO2 8 | 33 | #define SAA7115_SVIDEO2 8 |
| @@ -42,8 +42,15 @@ | |||
| 42 | #define SAA7115_FREQ_FL_CGCDIV (1 << 1) /* SA 3A[6], CGCDIV, SAA7115 only */ | 42 | #define SAA7115_FREQ_FL_CGCDIV (1 << 1) /* SA 3A[6], CGCDIV, SAA7115 only */ |
| 43 | #define SAA7115_FREQ_FL_APLL (1 << 2) /* SA 3A[3], APLL, SAA7114/5 only */ | 43 | #define SAA7115_FREQ_FL_APLL (1 << 2) /* SA 3A[3], APLL, SAA7114/5 only */ |
| 44 | 44 | ||
| 45 | #define SAA7115_IPORT_ON 1 | 45 | #define SAA7115_IPORT_ON 1 |
| 46 | #define SAA7115_IPORT_OFF 0 | 46 | #define SAA7115_IPORT_OFF 0 |
| 47 | |||
| 48 | /* SAA7111 specific output flags */ | ||
| 49 | #define SAA7111_VBI_BYPASS 2 | ||
| 50 | #define SAA7111_FMT_YUV422 0x00 | ||
| 51 | #define SAA7111_FMT_RGB 0x40 | ||
| 52 | #define SAA7111_FMT_CCIR 0x80 | ||
| 53 | #define SAA7111_FMT_YUV411 0xc0 | ||
| 47 | 54 | ||
| 48 | #endif | 55 | #endif |
| 49 | 56 | ||
diff --git a/include/media/saa7146.h b/include/media/saa7146.h index 2f68f4cd0037..64a2ec746a3e 100644 --- a/include/media/saa7146.h +++ b/include/media/saa7146.h | |||
| @@ -30,7 +30,7 @@ extern unsigned int saa7146_debug; | |||
| 30 | #define DEBUG_VARIABLE saa7146_debug | 30 | #define DEBUG_VARIABLE saa7146_debug |
| 31 | #endif | 31 | #endif |
| 32 | 32 | ||
| 33 | #define DEBUG_PROLOG printk("%s: %s(): ",KBUILD_MODNAME,__FUNCTION__) | 33 | #define DEBUG_PROLOG printk("%s: %s(): ",KBUILD_MODNAME, __func__) |
| 34 | #define INFO(x) { printk("%s: ",KBUILD_MODNAME); printk x; } | 34 | #define INFO(x) { printk("%s: ",KBUILD_MODNAME); printk x; } |
| 35 | 35 | ||
| 36 | #define ERR(x) { DEBUG_PROLOG; printk x; } | 36 | #define ERR(x) { DEBUG_PROLOG; printk x; } |
diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h index 234a4711d2ec..b5dbefea3740 100644 --- a/include/media/sh_mobile_ceu.h +++ b/include/media/sh_mobile_ceu.h | |||
| @@ -5,8 +5,6 @@ | |||
| 5 | 5 | ||
| 6 | struct sh_mobile_ceu_info { | 6 | struct sh_mobile_ceu_info { |
| 7 | unsigned long flags; /* SOCAM_... */ | 7 | unsigned long flags; /* SOCAM_... */ |
| 8 | void (*enable_camera)(void); | ||
| 9 | void (*disable_camera)(void); | ||
| 10 | }; | 8 | }; |
| 11 | 9 | ||
| 12 | #endif /* __ASM_SH_MOBILE_CEU_H__ */ | 10 | #endif /* __ASM_SH_MOBILE_CEU_H__ */ |
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index d548de326722..c5de7bb19fda 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h | |||
| @@ -83,6 +83,9 @@ struct soc_camera_link { | |||
| 83 | int bus_id; | 83 | int bus_id; |
| 84 | /* GPIO number to switch between 8 and 10 bit modes */ | 84 | /* GPIO number to switch between 8 and 10 bit modes */ |
| 85 | unsigned int gpio; | 85 | unsigned int gpio; |
| 86 | /* Optional callbacks to power on or off and reset the sensor */ | ||
| 87 | int (*power)(struct device *, int); | ||
| 88 | int (*reset)(struct device *); | ||
| 86 | }; | 89 | }; |
| 87 | 90 | ||
| 88 | static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) | 91 | static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) |
diff --git a/include/media/tuner.h b/include/media/tuner.h index 77068fcc86bd..67c1f514d0e2 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h | |||
| @@ -122,6 +122,7 @@ | |||
| 122 | #define TUNER_TDA9887 74 /* This tuner should be used only internally */ | 122 | #define TUNER_TDA9887 74 /* This tuner should be used only internally */ |
| 123 | #define TUNER_TEA5761 75 /* Only FM Radio Tuner */ | 123 | #define TUNER_TEA5761 75 /* Only FM Radio Tuner */ |
| 124 | #define TUNER_XC5000 76 /* Xceive Silicon Tuner */ | 124 | #define TUNER_XC5000 76 /* Xceive Silicon Tuner */ |
| 125 | #define TUNER_TCL_MF02GIP_5N 77 /* TCL MF02GIP_5N */ | ||
| 125 | 126 | ||
| 126 | /* tv card specific */ | 127 | /* tv card specific */ |
| 127 | #define TDA9887_PRESENT (1<<0) | 128 | #define TDA9887_PRESENT (1<<0) |
| @@ -178,7 +179,7 @@ struct tuner_setup { | |||
| 178 | unsigned int type; /* Tuner type */ | 179 | unsigned int type; /* Tuner type */ |
| 179 | unsigned int mode_mask; /* Allowed tuner modes */ | 180 | unsigned int mode_mask; /* Allowed tuner modes */ |
| 180 | unsigned int config; /* configuraion for more complex tuners */ | 181 | unsigned int config; /* configuraion for more complex tuners */ |
| 181 | int (*tuner_callback) (void *dev, int command,int arg); | 182 | int (*tuner_callback) (void *dev, int component, int cmd, int arg); |
| 182 | }; | 183 | }; |
| 183 | 184 | ||
| 184 | #endif /* __KERNEL__ */ | 185 | #endif /* __KERNEL__ */ |
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 41b509babf3f..d73a8e9028a5 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h | |||
| @@ -72,6 +72,10 @@ enum { | |||
| 72 | /* module cs5345: just ident 5345 */ | 72 | /* module cs5345: just ident 5345 */ |
| 73 | V4L2_IDENT_CS5345 = 5345, | 73 | V4L2_IDENT_CS5345 = 5345, |
| 74 | 74 | ||
| 75 | /* module saa6752hs: reserved range 6750-6759 */ | ||
| 76 | V4L2_IDENT_SAA6752HS = 6752, | ||
| 77 | V4L2_IDENT_SAA6752HS_AC3 = 6753, | ||
| 78 | |||
| 75 | /* module wm8739: just ident 8739 */ | 79 | /* module wm8739: just ident 8739 */ |
| 76 | V4L2_IDENT_WM8739 = 8739, | 80 | V4L2_IDENT_WM8739 = 8739, |
| 77 | 81 | ||
| @@ -161,6 +165,7 @@ enum { | |||
| 161 | /* Micron CMOS sensor chips: 45000-45099 */ | 165 | /* Micron CMOS sensor chips: 45000-45099 */ |
| 162 | V4L2_IDENT_MT9M001C12ST = 45000, | 166 | V4L2_IDENT_MT9M001C12ST = 45000, |
| 163 | V4L2_IDENT_MT9M001C12STM = 45005, | 167 | V4L2_IDENT_MT9M001C12STM = 45005, |
| 168 | V4L2_IDENT_MT9M111 = 45007, | ||
| 164 | V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ | 169 | V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ |
| 165 | V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ | 170 | V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ |
| 166 | }; | 171 | }; |
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 07d3a9a575d1..2f8719abf5cb 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h | |||
| @@ -76,11 +76,14 @@ int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local); | |||
| 76 | 76 | ||
| 77 | int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, | 77 | int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, |
| 78 | const char **menu_items); | 78 | const char **menu_items); |
| 79 | const char *v4l2_ctrl_get_name(u32 id); | ||
| 79 | const char **v4l2_ctrl_get_menu(u32 id); | 80 | const char **v4l2_ctrl_get_menu(u32 id); |
| 80 | int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def); | 81 | int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def); |
| 81 | int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl); | 82 | int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl); |
| 82 | int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, | 83 | int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, |
| 83 | struct v4l2_queryctrl *qctrl, const char **menu_items); | 84 | struct v4l2_queryctrl *qctrl, const char **menu_items); |
| 85 | #define V4L2_CTRL_MENU_IDS_END (0xffffffff) | ||
| 86 | int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids); | ||
| 84 | u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); | 87 | u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); |
| 85 | 88 | ||
| 86 | /* ------------------------------------------------------------------------- */ | 89 | /* ------------------------------------------------------------------------- */ |
| @@ -222,18 +225,22 @@ struct v4l2_crystal_freq { | |||
| 222 | An extra flags field allows device specific configuration regarding | 225 | An extra flags field allows device specific configuration regarding |
| 223 | clock frequency dividers, etc. If not used, then set flags to 0. | 226 | clock frequency dividers, etc. If not used, then set flags to 0. |
| 224 | If the frequency is not supported, then -EINVAL is returned. */ | 227 | If the frequency is not supported, then -EINVAL is returned. */ |
| 225 | #define VIDIOC_INT_S_CRYSTAL_FREQ _IOW ('d', 113, struct v4l2_crystal_freq) | 228 | #define VIDIOC_INT_S_CRYSTAL_FREQ _IOW('d', 113, struct v4l2_crystal_freq) |
| 226 | 229 | ||
| 227 | /* Initialize the sensor registors to some sort of reasonable | 230 | /* Initialize the sensor registors to some sort of reasonable |
| 228 | default values. */ | 231 | default values. */ |
| 229 | #define VIDIOC_INT_INIT _IOW ('d', 114, u32) | 232 | #define VIDIOC_INT_INIT _IOW('d', 114, u32) |
| 230 | 233 | ||
| 231 | /* Set v4l2_std_id for video OUTPUT devices. This is ignored by | 234 | /* Set v4l2_std_id for video OUTPUT devices. This is ignored by |
| 232 | video input devices. */ | 235 | video input devices. */ |
| 233 | #define VIDIOC_INT_S_STD_OUTPUT _IOW ('d', 115, v4l2_std_id) | 236 | #define VIDIOC_INT_S_STD_OUTPUT _IOW('d', 115, v4l2_std_id) |
| 234 | 237 | ||
| 235 | /* Get v4l2_std_id for video OUTPUT devices. This is ignored by | 238 | /* Get v4l2_std_id for video OUTPUT devices. This is ignored by |
| 236 | video input devices. */ | 239 | video input devices. */ |
| 237 | #define VIDIOC_INT_G_STD_OUTPUT _IOW ('d', 116, v4l2_std_id) | 240 | #define VIDIOC_INT_G_STD_OUTPUT _IOW('d', 116, v4l2_std_id) |
| 241 | |||
| 242 | /* Set GPIO pins. Very simple right now, might need to be extended with | ||
| 243 | a v4l2_gpio struct if a direction is also needed. */ | ||
| 244 | #define VIDIOC_INT_S_GPIO _IOW('d', 117, u32) | ||
| 238 | 245 | ||
| 239 | #endif /* V4L2_COMMON_H_ */ | 246 | #endif /* V4L2_COMMON_H_ */ |
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 2745e1afc722..a0a6b41c5e09 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h | |||
| @@ -9,30 +9,20 @@ | |||
| 9 | #ifndef _V4L2_DEV_H | 9 | #ifndef _V4L2_DEV_H |
| 10 | #define _V4L2_DEV_H | 10 | #define _V4L2_DEV_H |
| 11 | 11 | ||
| 12 | #define OBSOLETE_DEVDATA 1 /* to be removed soon */ | ||
| 13 | |||
| 14 | #include <linux/poll.h> | 12 | #include <linux/poll.h> |
| 15 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
| 16 | #include <linux/device.h> | 14 | #include <linux/device.h> |
| 15 | #include <linux/cdev.h> | ||
| 17 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
| 18 | #include <linux/compiler.h> /* need __user */ | ||
| 19 | #include <linux/videodev2.h> | 17 | #include <linux/videodev2.h> |
| 20 | 18 | ||
| 21 | #define VIDEO_MAJOR 81 | 19 | #define VIDEO_MAJOR 81 |
| 22 | /* Minor device allocation */ | ||
| 23 | #define MINOR_VFL_TYPE_GRABBER_MIN 0 | ||
| 24 | #define MINOR_VFL_TYPE_GRABBER_MAX 63 | ||
| 25 | #define MINOR_VFL_TYPE_RADIO_MIN 64 | ||
| 26 | #define MINOR_VFL_TYPE_RADIO_MAX 127 | ||
| 27 | #define MINOR_VFL_TYPE_VTX_MIN 192 | ||
| 28 | #define MINOR_VFL_TYPE_VTX_MAX 223 | ||
| 29 | #define MINOR_VFL_TYPE_VBI_MIN 224 | ||
| 30 | #define MINOR_VFL_TYPE_VBI_MAX 255 | ||
| 31 | 20 | ||
| 32 | #define VFL_TYPE_GRABBER 0 | 21 | #define VFL_TYPE_GRABBER 0 |
| 33 | #define VFL_TYPE_VBI 1 | 22 | #define VFL_TYPE_VBI 1 |
| 34 | #define VFL_TYPE_RADIO 2 | 23 | #define VFL_TYPE_RADIO 2 |
| 35 | #define VFL_TYPE_VTX 3 | 24 | #define VFL_TYPE_VTX 3 |
| 25 | #define VFL_TYPE_MAX 4 | ||
| 36 | 26 | ||
| 37 | struct v4l2_ioctl_callbacks; | 27 | struct v4l2_ioctl_callbacks; |
| 38 | 28 | ||
| @@ -49,12 +39,15 @@ struct video_device | |||
| 49 | 39 | ||
| 50 | /* sysfs */ | 40 | /* sysfs */ |
| 51 | struct device dev; /* v4l device */ | 41 | struct device dev; /* v4l device */ |
| 42 | struct cdev cdev; /* character device */ | ||
| 43 | void (*cdev_release)(struct kobject *kobj); | ||
| 52 | struct device *parent; /* device parent */ | 44 | struct device *parent; /* device parent */ |
| 53 | 45 | ||
| 54 | /* device info */ | 46 | /* device info */ |
| 55 | char name[32]; | 47 | char name[32]; |
| 56 | int vfl_type; | 48 | int vfl_type; |
| 57 | int minor; | 49 | int minor; |
| 50 | u16 num; | ||
| 58 | /* attribute to differentiate multiple indices on one physical device */ | 51 | /* attribute to differentiate multiple indices on one physical device */ |
| 59 | int index; | 52 | int index; |
| 60 | 53 | ||
| @@ -69,50 +62,50 @@ struct video_device | |||
| 69 | 62 | ||
| 70 | /* ioctl callbacks */ | 63 | /* ioctl callbacks */ |
| 71 | const struct v4l2_ioctl_ops *ioctl_ops; | 64 | const struct v4l2_ioctl_ops *ioctl_ops; |
| 72 | |||
| 73 | #ifdef OBSOLETE_DEVDATA /* to be removed soon */ | ||
| 74 | /* dev->driver_data will be used instead some day. | ||
| 75 | * Use the video_{get|set}_drvdata() helper functions, | ||
| 76 | * so the switch over will be transparent for you. | ||
| 77 | * Or use {pci|usb}_{get|set}_drvdata() directly. */ | ||
| 78 | void *priv; | ||
| 79 | #endif | ||
| 80 | |||
| 81 | /* for videodev.c internal usage -- please don't touch */ | ||
| 82 | int users; /* video_exclusive_{open|close} ... */ | ||
| 83 | struct mutex lock; /* ... helper function uses these */ | ||
| 84 | }; | 65 | }; |
| 85 | 66 | ||
| 86 | /* Class-dev to video-device */ | 67 | /* dev to video-device */ |
| 87 | #define to_video_device(cd) container_of(cd, struct video_device, dev) | 68 | #define to_video_device(cd) container_of(cd, struct video_device, dev) |
| 88 | 69 | ||
| 89 | /* Version 2 functions */ | 70 | /* Register and unregister devices. Note that if video_register_device fails, |
| 90 | extern int video_register_device(struct video_device *vfd, int type, int nr); | 71 | the release() callback of the video_device structure is *not* called, so |
| 91 | int video_register_device_index(struct video_device *vfd, int type, int nr, | 72 | the caller is responsible for freeing any data. Usually that means that |
| 92 | int index); | 73 | you call video_device_release() on failure. */ |
| 93 | void video_unregister_device(struct video_device *); | 74 | int __must_check video_register_device(struct video_device *vfd, int type, int nr); |
| 75 | int __must_check video_register_device_index(struct video_device *vfd, | ||
| 76 | int type, int nr, int index); | ||
| 77 | void video_unregister_device(struct video_device *vfd); | ||
| 94 | 78 | ||
| 95 | /* helper functions to alloc / release struct video_device, the | 79 | /* helper functions to alloc/release struct video_device, the |
| 96 | later can be used for video_device->release() */ | 80 | latter can also be used for video_device->release(). */ |
| 97 | struct video_device *video_device_alloc(void); | 81 | struct video_device * __must_check video_device_alloc(void); |
| 82 | |||
| 83 | /* this release function frees the vfd pointer */ | ||
| 98 | void video_device_release(struct video_device *vfd); | 84 | void video_device_release(struct video_device *vfd); |
| 99 | 85 | ||
| 100 | #ifdef OBSOLETE_DEVDATA /* to be removed soon */ | 86 | /* this release function does nothing, use when the video_device is a |
| 87 | static global struct. Note that having a static video_device is | ||
| 88 | a dubious construction at best. */ | ||
| 89 | void video_device_release_empty(struct video_device *vfd); | ||
| 90 | |||
| 101 | /* helper functions to access driver private data. */ | 91 | /* helper functions to access driver private data. */ |
| 102 | static inline void *video_get_drvdata(struct video_device *dev) | 92 | static inline void *video_get_drvdata(struct video_device *dev) |
| 103 | { | 93 | { |
| 104 | return dev->priv; | 94 | return dev_get_drvdata(&dev->dev); |
| 105 | } | 95 | } |
| 106 | 96 | ||
| 107 | static inline void video_set_drvdata(struct video_device *dev, void *data) | 97 | static inline void video_set_drvdata(struct video_device *dev, void *data) |
| 108 | { | 98 | { |
| 109 | dev->priv = data; | 99 | dev_set_drvdata(&dev->dev, data); |
| 110 | } | 100 | } |
| 111 | 101 | ||
| 112 | /* Obsolete stuff - Still needed for radio devices and obsolete drivers */ | 102 | struct video_device *video_devdata(struct file *file); |
| 113 | extern struct video_device* video_devdata(struct file*); | 103 | |
| 114 | extern int video_exclusive_open(struct inode *inode, struct file *file); | 104 | /* Combine video_get_drvdata and video_devdata as this is |
| 115 | extern int video_exclusive_release(struct inode *inode, struct file *file); | 105 | used very often. */ |
| 116 | #endif | 106 | static inline void *video_drvdata(struct file *file) |
| 107 | { | ||
| 108 | return video_get_drvdata(video_devdata(file)); | ||
| 109 | } | ||
| 117 | 110 | ||
| 118 | #endif /* _V4L2_DEV_H */ | 111 | #endif /* _V4L2_DEV_H */ |
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index dc6404618555..0bef03add796 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h | |||
| @@ -39,11 +39,6 @@ struct v4l2_ioctl_ops { | |||
| 39 | struct v4l2_fmtdesc *f); | 39 | struct v4l2_fmtdesc *f); |
| 40 | int (*vidioc_enum_fmt_vid_out) (struct file *file, void *fh, | 40 | int (*vidioc_enum_fmt_vid_out) (struct file *file, void *fh, |
| 41 | struct v4l2_fmtdesc *f); | 41 | struct v4l2_fmtdesc *f); |
| 42 | #if 1 | ||
| 43 | /* deprecated, will be removed in 2.6.28 */ | ||
| 44 | int (*vidioc_enum_fmt_vbi_cap) (struct file *file, void *fh, | ||
| 45 | struct v4l2_fmtdesc *f); | ||
| 46 | #endif | ||
| 47 | int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh, | 42 | int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh, |
| 48 | struct v4l2_fmtdesc *f); | 43 | struct v4l2_fmtdesc *f); |
| 49 | 44 | ||
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h index b62ce3e077f9..b6870cbaf2b3 100644 --- a/include/sound/tea575x-tuner.h +++ b/include/sound/tea575x-tuner.h | |||
| @@ -43,6 +43,7 @@ struct snd_tea575x { | |||
| 43 | unsigned int freq_fixup; /* crystal onboard */ | 43 | unsigned int freq_fixup; /* crystal onboard */ |
| 44 | unsigned int val; /* hw value */ | 44 | unsigned int val; /* hw value */ |
| 45 | unsigned long freq; /* frequency */ | 45 | unsigned long freq; /* frequency */ |
| 46 | unsigned long in_use; /* set if the device is in use */ | ||
| 46 | struct snd_tea575x_ops *ops; | 47 | struct snd_tea575x_ops *ops; |
| 47 | void *private_data; | 48 | void *private_data; |
| 48 | }; | 49 | }; |
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index 83e90057270e..c13a178383ba 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c | |||
| @@ -87,8 +87,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea) | |||
| 87 | static int snd_tea575x_ioctl(struct inode *inode, struct file *file, | 87 | static int snd_tea575x_ioctl(struct inode *inode, struct file *file, |
| 88 | unsigned int cmd, unsigned long data) | 88 | unsigned int cmd, unsigned long data) |
| 89 | { | 89 | { |
| 90 | struct video_device *dev = video_devdata(file); | 90 | struct snd_tea575x *tea = video_drvdata(file); |
| 91 | struct snd_tea575x *tea = video_get_drvdata(dev); | ||
| 92 | void __user *arg = (void __user *)data; | 91 | void __user *arg = (void __user *)data; |
| 93 | 92 | ||
| 94 | switch(cmd) { | 93 | switch(cmd) { |
| @@ -175,6 +174,21 @@ static void snd_tea575x_release(struct video_device *vfd) | |||
| 175 | { | 174 | { |
| 176 | } | 175 | } |
| 177 | 176 | ||
| 177 | static int snd_tea575x_exclusive_open(struct inode *inode, struct file *file) | ||
| 178 | { | ||
| 179 | struct snd_tea575x *tea = video_drvdata(file); | ||
| 180 | |||
| 181 | return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int snd_tea575x_exclusive_release(struct inode *inode, struct file *file) | ||
| 185 | { | ||
| 186 | struct snd_tea575x *tea = video_drvdata(file); | ||
| 187 | |||
| 188 | clear_bit(0, &tea->in_use); | ||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 178 | /* | 192 | /* |
| 179 | * initialize all the tea575x chips | 193 | * initialize all the tea575x chips |
| 180 | */ | 194 | */ |
| @@ -193,9 +207,10 @@ void snd_tea575x_init(struct snd_tea575x *tea) | |||
| 193 | tea->vd.release = snd_tea575x_release; | 207 | tea->vd.release = snd_tea575x_release; |
| 194 | video_set_drvdata(&tea->vd, tea); | 208 | video_set_drvdata(&tea->vd, tea); |
| 195 | tea->vd.fops = &tea->fops; | 209 | tea->vd.fops = &tea->fops; |
| 210 | tea->in_use = 0; | ||
| 196 | tea->fops.owner = tea->card->module; | 211 | tea->fops.owner = tea->card->module; |
| 197 | tea->fops.open = video_exclusive_open; | 212 | tea->fops.open = snd_tea575x_exclusive_open; |
| 198 | tea->fops.release = video_exclusive_release; | 213 | tea->fops.release = snd_tea575x_exclusive_release; |
| 199 | tea->fops.ioctl = snd_tea575x_ioctl; | 214 | tea->fops.ioctl = snd_tea575x_ioctl; |
| 200 | if (video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->dev_nr - 1) < 0) { | 215 | if (video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->dev_nr - 1) < 0) { |
| 201 | snd_printk(KERN_ERR "unable to register tea575x tuner\n"); | 216 | snd_printk(KERN_ERR "unable to register tea575x tuner\n"); |
