diff options
Diffstat (limited to 'drivers/media/dvb/dvb-usb')
76 files changed, 35983 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig new file mode 100644 index 00000000000..5d73dec8ac0 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
| @@ -0,0 +1,376 @@ | |||
| 1 | config DVB_USB | ||
| 2 | tristate "Support for various USB DVB devices" | ||
| 3 | depends on DVB_CORE && USB && I2C && RC_CORE | ||
| 4 | help | ||
| 5 | By enabling this you will be able to choose the various supported | ||
| 6 | USB1.1 and USB2.0 DVB devices. | ||
| 7 | |||
| 8 | Almost every USB device needs a firmware, please look into | ||
| 9 | <file:Documentation/dvb/README.dvb-usb>. | ||
| 10 | |||
| 11 | For a complete list of supported USB devices see the LinuxTV DVB Wiki: | ||
| 12 | <http://www.linuxtv.org/wiki/index.php/DVB_USB> | ||
| 13 | |||
| 14 | Say Y if you own a USB DVB device. | ||
| 15 | |||
| 16 | config DVB_USB_DEBUG | ||
| 17 | bool "Enable extended debug support for all DVB-USB devices" | ||
| 18 | depends on DVB_USB | ||
| 19 | help | ||
| 20 | Say Y if you want to enable debugging. See modinfo dvb-usb (and the | ||
| 21 | appropriate drivers) for debug levels. | ||
| 22 | |||
| 23 | config DVB_USB_A800 | ||
| 24 | tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" | ||
| 25 | depends on DVB_USB | ||
| 26 | select DVB_DIB3000MC | ||
| 27 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 28 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE | ||
| 29 | help | ||
| 30 | Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. | ||
| 31 | |||
| 32 | config DVB_USB_DIBUSB_MB | ||
| 33 | tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)" | ||
| 34 | depends on DVB_USB | ||
| 35 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 36 | select DVB_DIB3000MB | ||
| 37 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE | ||
| 38 | help | ||
| 39 | Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by | ||
| 40 | DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. | ||
| 41 | |||
| 42 | For an up-to-date list of devices supported by this driver, have a look | ||
| 43 | on the Linux-DVB Wiki at www.linuxtv.org. | ||
| 44 | |||
| 45 | Say Y if you own such a device and want to use it. You should build it as | ||
| 46 | a module. | ||
| 47 | |||
| 48 | config DVB_USB_DIBUSB_MB_FAULTY | ||
| 49 | bool "Support faulty USB IDs" | ||
| 50 | depends on DVB_USB_DIBUSB_MB | ||
| 51 | help | ||
| 52 | Support for faulty USB IDs due to an invalid EEPROM on some Artec devices. | ||
| 53 | |||
| 54 | config DVB_USB_DIBUSB_MC | ||
| 55 | tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" | ||
| 56 | depends on DVB_USB | ||
| 57 | select DVB_DIB3000MC | ||
| 58 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE | ||
| 59 | help | ||
| 60 | Support for USB2.0 DVB-T receivers based on reference designs made by | ||
| 61 | DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. | ||
| 62 | |||
| 63 | For an up-to-date list of devices supported by this driver, have a look | ||
| 64 | on the Linux-DVB Wiki at www.linuxtv.org. | ||
| 65 | |||
| 66 | Say Y if you own such a device and want to use it. You should build it as | ||
| 67 | a module. | ||
| 68 | |||
| 69 | config DVB_USB_DIB0700 | ||
| 70 | tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" | ||
| 71 | depends on DVB_USB | ||
| 72 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE | ||
| 73 | select DVB_DIB7000M if !DVB_FE_CUSTOMISE | ||
| 74 | select DVB_DIB8000 if !DVB_FE_CUSTOMISE | ||
| 75 | select DVB_DIB3000MC if !DVB_FE_CUSTOMISE | ||
| 76 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | ||
| 77 | select DVB_LGDT3305 if !DVB_FE_CUSTOMISE | ||
| 78 | select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE | ||
| 79 | select DVB_TUNER_DIB0090 if !DVB_FE_CUSTOMISE | ||
| 80 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE | ||
| 81 | select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE | ||
| 82 | select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE | ||
| 83 | select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE | ||
| 84 | select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE | ||
| 85 | select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE | ||
| 86 | help | ||
| 87 | Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The | ||
| 88 | USB bridge is also present in devices having the DiB7700 DVB-T-USB | ||
| 89 | silicon. This chip can be found in devices offered by Hauppauge, | ||
| 90 | Avermedia and other big and small companies. | ||
| 91 | |||
| 92 | For an up-to-date list of devices supported by this driver, have a look | ||
| 93 | on the LinuxTV Wiki at www.linuxtv.org. | ||
| 94 | |||
| 95 | Say Y if you own such a device and want to use it. You should build it as | ||
| 96 | a module. | ||
| 97 | |||
| 98 | config DVB_USB_UMT_010 | ||
| 99 | tristate "HanfTek UMT-010 DVB-T USB2.0 support" | ||
| 100 | depends on DVB_USB | ||
| 101 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 102 | select DVB_DIB3000MC | ||
| 103 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE | ||
| 104 | select DVB_MT352 if !DVB_FE_CUSTOMISE | ||
| 105 | help | ||
| 106 | Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. | ||
| 107 | |||
| 108 | config DVB_USB_CXUSB | ||
| 109 | tristate "Conexant USB2.0 hybrid reference design support" | ||
| 110 | depends on DVB_USB | ||
| 111 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 112 | select DVB_CX22702 if !DVB_FE_CUSTOMISE | ||
| 113 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | ||
| 114 | select DVB_MT352 if !DVB_FE_CUSTOMISE | ||
| 115 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
| 116 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE | ||
| 117 | select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE | ||
| 118 | select DVB_ATBM8830 if !DVB_FE_CUSTOMISE | ||
| 119 | select DVB_LGS8GXX if !DVB_FE_CUSTOMISE | ||
| 120 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE | ||
| 121 | select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE | ||
| 122 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | ||
| 123 | select MEDIA_TUNER_MAX2165 if !MEDIA_TUNER_CUSTOMISE | ||
| 124 | help | ||
| 125 | Say Y here to support the Conexant USB2.0 hybrid reference design. | ||
| 126 | Currently, only DVB and ATSC modes are supported, analog mode | ||
| 127 | shall be added in the future. Devices that require this module: | ||
| 128 | |||
| 129 | Medion MD95700 hybrid USB2.0 device. | ||
| 130 | DViCO FusionHDTV (Bluebird) USB2.0 devices | ||
| 131 | |||
| 132 | config DVB_USB_M920X | ||
| 133 | tristate "Uli m920x DVB-T USB2.0 support" | ||
| 134 | depends on DVB_USB | ||
| 135 | select DVB_MT352 if !DVB_FE_CUSTOMISE | ||
| 136 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE | ||
| 137 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE | ||
| 138 | select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE | ||
| 139 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE | ||
| 140 | help | ||
| 141 | Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. | ||
| 142 | Currently, only devices with a product id of | ||
| 143 | "DTV USB MINI" (in cold state) are supported. | ||
| 144 | Firmware required. | ||
| 145 | |||
| 146 | config DVB_USB_GL861 | ||
| 147 | tristate "Genesys Logic GL861 USB2.0 support" | ||
| 148 | depends on DVB_USB | ||
| 149 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
| 150 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE | ||
| 151 | help | ||
| 152 | Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 | ||
| 153 | receiver with USB ID 0db0:5581. | ||
| 154 | |||
| 155 | config DVB_USB_AU6610 | ||
| 156 | tristate "Alcor Micro AU6610 USB2.0 support" | ||
| 157 | depends on DVB_USB | ||
| 158 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
| 159 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE | ||
| 160 | help | ||
| 161 | Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. | ||
| 162 | |||
| 163 | config DVB_USB_DIGITV | ||
| 164 | tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" | ||
| 165 | depends on DVB_USB | ||
| 166 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 167 | select DVB_NXT6000 if !DVB_FE_CUSTOMISE | ||
| 168 | select DVB_MT352 if !DVB_FE_CUSTOMISE | ||
| 169 | help | ||
| 170 | Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver. | ||
| 171 | |||
| 172 | config DVB_USB_VP7045 | ||
| 173 | tristate "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support" | ||
| 174 | depends on DVB_USB | ||
| 175 | help | ||
| 176 | Say Y here to support the | ||
| 177 | |||
| 178 | TwinhanDTV Alpha (stick) (VP-7045), | ||
| 179 | TwinhanDTV MagicBox II (VP-7046), | ||
| 180 | DigitalNow TinyUSB 2 DVB-t, | ||
| 181 | DigitalRise USB 2.0 Ter (Beetle) and | ||
| 182 | TYPHOON DVB-T USB DRIVE | ||
| 183 | |||
| 184 | DVB-T USB2.0 receivers. | ||
| 185 | |||
| 186 | config DVB_USB_VP702X | ||
| 187 | tristate "TwinhanDTV StarBox and clones DVB-S USB2.0 support" | ||
| 188 | depends on DVB_USB | ||
| 189 | help | ||
| 190 | Say Y here to support the | ||
| 191 | |||
| 192 | TwinhanDTV StarBox, | ||
| 193 | DigitalRise USB Starbox and | ||
| 194 | TYPHOON DVB-S USB 2.0 BOX | ||
| 195 | |||
| 196 | DVB-S USB2.0 receivers. | ||
| 197 | |||
| 198 | config DVB_USB_GP8PSK | ||
| 199 | tristate "GENPIX 8PSK->USB module support" | ||
| 200 | depends on DVB_USB | ||
| 201 | help | ||
| 202 | Say Y here to support the | ||
| 203 | GENPIX 8psk module | ||
| 204 | |||
| 205 | DVB-S USB2.0 receivers. | ||
| 206 | |||
| 207 | config DVB_USB_NOVA_T_USB2 | ||
| 208 | tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" | ||
| 209 | depends on DVB_USB | ||
| 210 | select DVB_DIB3000MC | ||
| 211 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 212 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE | ||
| 213 | help | ||
| 214 | Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. | ||
| 215 | |||
| 216 | config DVB_USB_TTUSB2 | ||
| 217 | tristate "Pinnacle 400e DVB-S USB2.0 support" | ||
| 218 | depends on DVB_USB | ||
| 219 | select DVB_TDA10086 if !DVB_FE_CUSTOMISE | ||
| 220 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | ||
| 221 | select DVB_TDA826X if !DVB_FE_CUSTOMISE | ||
| 222 | help | ||
| 223 | Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The | ||
| 224 | firmware protocol used by this module is similar to the one used by the | ||
| 225 | old ttusb-driver - that's why the module is called dvb-usb-ttusb2. | ||
| 226 | |||
| 227 | config DVB_USB_DTT200U | ||
| 228 | tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" | ||
| 229 | depends on DVB_USB | ||
| 230 | help | ||
| 231 | Say Y here to support the WideView/Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver. | ||
| 232 | |||
| 233 | The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan). | ||
| 234 | |||
| 235 | The WT-220U and its clones are pen-sized. | ||
| 236 | |||
| 237 | config DVB_USB_OPERA1 | ||
| 238 | tristate "Opera1 DVB-S USB2.0 receiver" | ||
| 239 | depends on DVB_USB | ||
| 240 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
| 241 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 242 | help | ||
| 243 | Say Y here to support the Opera DVB-S USB2.0 receiver. | ||
| 244 | |||
| 245 | config DVB_USB_AF9005 | ||
| 246 | tristate "Afatech AF9005 DVB-T USB1.1 support" | ||
| 247 | depends on DVB_USB && EXPERIMENTAL | ||
| 248 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE | ||
| 249 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE | ||
| 250 | help | ||
| 251 | Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver | ||
| 252 | and the TerraTec Cinergy T USB XE (Rev.1) | ||
| 253 | |||
| 254 | config DVB_USB_AF9005_REMOTE | ||
| 255 | tristate "Afatech AF9005 default remote control support" | ||
| 256 | depends on DVB_USB_AF9005 | ||
| 257 | help | ||
| 258 | Say Y here to support the default remote control decoding for the | ||
| 259 | Afatech AF9005 based receiver. | ||
| 260 | |||
| 261 | config DVB_USB_DW2102 | ||
| 262 | tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support" | ||
| 263 | depends on DVB_USB | ||
| 264 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 265 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
| 266 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | ||
| 267 | select DVB_STB6000 if !DVB_FE_CUSTOMISE | ||
| 268 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | ||
| 269 | select DVB_SI21XX if !DVB_FE_CUSTOMISE | ||
| 270 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE | ||
| 271 | select DVB_MT312 if !DVB_FE_CUSTOMISE | ||
| 272 | select DVB_ZL10039 if !DVB_FE_CUSTOMISE | ||
| 273 | select DVB_DS3000 if !DVB_FE_CUSTOMISE | ||
| 274 | select DVB_STB6100 if !DVB_FE_CUSTOMISE | ||
| 275 | select DVB_STV6110 if !DVB_FE_CUSTOMISE | ||
| 276 | select DVB_STV0900 if !DVB_FE_CUSTOMISE | ||
| 277 | help | ||
| 278 | Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0 | ||
| 279 | receivers. | ||
| 280 | |||
| 281 | config DVB_USB_CINERGY_T2 | ||
| 282 | tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" | ||
| 283 | depends on DVB_USB | ||
| 284 | help | ||
| 285 | Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers | ||
| 286 | |||
| 287 | Say Y if you own such a device and want to use it. | ||
| 288 | |||
| 289 | config DVB_USB_ANYSEE | ||
| 290 | tristate "Anysee DVB-T/C USB2.0 support" | ||
| 291 | depends on DVB_USB | ||
| 292 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 293 | select DVB_MT352 if !DVB_FE_CUSTOMISE | ||
| 294 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
| 295 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE | ||
| 296 | select MEDIA_TUNER_TDA18212 if !MEDIA_TUNER_CUSTOMISE | ||
| 297 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | ||
| 298 | select DVB_STV0900 if !DVB_FE_CUSTOMISE | ||
| 299 | select DVB_STV6110 if !DVB_FE_CUSTOMISE | ||
| 300 | select DVB_ISL6423 if !DVB_FE_CUSTOMISE | ||
| 301 | help | ||
| 302 | Say Y here to support the Anysee E30, Anysee E30 Plus or | ||
| 303 | Anysee E30 C Plus DVB USB2.0 receiver. | ||
| 304 | |||
| 305 | config DVB_USB_DTV5100 | ||
| 306 | tristate "AME DTV-5100 USB2.0 DVB-T support" | ||
| 307 | depends on DVB_USB | ||
| 308 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
| 309 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE | ||
| 310 | help | ||
| 311 | Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. | ||
| 312 | |||
| 313 | config DVB_USB_AF9015 | ||
| 314 | tristate "Afatech AF9015 DVB-T USB2.0 support" | ||
| 315 | depends on DVB_USB | ||
| 316 | select DVB_AF9013 | ||
| 317 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 318 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE | ||
| 319 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE | ||
| 320 | select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE | ||
| 321 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | ||
| 322 | select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE | ||
| 323 | select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE | ||
| 324 | select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE | ||
| 325 | help | ||
| 326 | Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver | ||
| 327 | |||
| 328 | config DVB_USB_CE6230 | ||
| 329 | tristate "Intel CE6230 DVB-T USB2.0 support" | ||
| 330 | depends on DVB_USB && EXPERIMENTAL | ||
| 331 | select DVB_ZL10353 | ||
| 332 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | ||
| 333 | help | ||
| 334 | Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver | ||
| 335 | |||
| 336 | config DVB_USB_FRIIO | ||
| 337 | tristate "Friio ISDB-T USB2.0 Receiver support" | ||
| 338 | depends on DVB_USB | ||
| 339 | help | ||
| 340 | Say Y here to support the Japanese DTV receiver Friio. | ||
| 341 | |||
| 342 | config DVB_USB_EC168 | ||
| 343 | tristate "E3C EC168 DVB-T USB2.0 support" | ||
| 344 | depends on DVB_USB && EXPERIMENTAL | ||
| 345 | select DVB_EC100 | ||
| 346 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | ||
| 347 | help | ||
| 348 | Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. | ||
| 349 | |||
| 350 | config DVB_USB_AZ6027 | ||
| 351 | tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" | ||
| 352 | depends on DVB_USB | ||
| 353 | select DVB_STB0899 if !DVB_FE_CUSTOMISE | ||
| 354 | select DVB_STB6100 if !DVB_FE_CUSTOMISE | ||
| 355 | help | ||
| 356 | Say Y here to support the AZ6027 device | ||
| 357 | |||
| 358 | config DVB_USB_LME2510 | ||
| 359 | tristate "LME DM04/QQBOX DVB-S USB2.0 support" | ||
| 360 | depends on DVB_USB | ||
| 361 | select DVB_TDA10086 if !DVB_FE_CUSTOMISE | ||
| 362 | select DVB_TDA826X if !DVB_FE_CUSTOMISE | ||
| 363 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | ||
| 364 | select DVB_IX2505V if !DVB_FE_CUSTOMISE | ||
| 365 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
| 366 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
| 367 | help | ||
| 368 | Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 . | ||
| 369 | |||
| 370 | config DVB_USB_TECHNISAT_USB2 | ||
| 371 | tristate "Technisat DVB-S/S2 USB2.0 support" | ||
| 372 | depends on DVB_USB | ||
| 373 | select DVB_STV090x if !DVB_FE_CUSTOMISE | ||
| 374 | select DVB_STV6110x if !DVB_FE_CUSTOMISE | ||
| 375 | help | ||
| 376 | Say Y here to support the Technisat USB2 DVB-S/S2 device | ||
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile new file mode 100644 index 00000000000..4bac13da0c3 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o usb-urb.o | ||
| 2 | obj-$(CONFIG_DVB_USB) += dvb-usb.o | ||
| 3 | |||
| 4 | dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o | ||
| 5 | obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o | ||
| 6 | |||
| 7 | dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o | ||
| 8 | obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o | ||
| 9 | |||
| 10 | dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o | ||
| 11 | obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o | ||
| 12 | |||
| 13 | dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o | ||
| 14 | obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o | ||
| 15 | |||
| 16 | dvb-usb-dibusb-common-objs = dibusb-common.o | ||
| 17 | |||
| 18 | dvb-usb-a800-objs = a800.o | ||
| 19 | obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o | ||
| 20 | |||
| 21 | dvb-usb-dibusb-mb-objs = dibusb-mb.o | ||
| 22 | obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o | ||
| 23 | |||
| 24 | dvb-usb-dibusb-mc-objs = dibusb-mc.o | ||
| 25 | obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o | ||
| 26 | |||
| 27 | dvb-usb-nova-t-usb2-objs = nova-t-usb2.o | ||
| 28 | obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o | ||
| 29 | |||
| 30 | dvb-usb-umt-010-objs = umt-010.o | ||
| 31 | obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o | ||
| 32 | |||
| 33 | dvb-usb-m920x-objs = m920x.o | ||
| 34 | obj-$(CONFIG_DVB_USB_M920X) += dvb-usb-m920x.o | ||
| 35 | |||
| 36 | dvb-usb-gl861-objs = gl861.o | ||
| 37 | obj-$(CONFIG_DVB_USB_GL861) += dvb-usb-gl861.o | ||
| 38 | |||
| 39 | dvb-usb-au6610-objs = au6610.o | ||
| 40 | obj-$(CONFIG_DVB_USB_AU6610) += dvb-usb-au6610.o | ||
| 41 | |||
| 42 | dvb-usb-digitv-objs = digitv.o | ||
| 43 | obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o | ||
| 44 | |||
| 45 | dvb-usb-cxusb-objs = cxusb.o | ||
| 46 | obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o | ||
| 47 | |||
| 48 | dvb-usb-ttusb2-objs = ttusb2.o | ||
| 49 | obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o | ||
| 50 | |||
| 51 | dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o | ||
| 52 | obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o | ||
| 53 | |||
| 54 | dvb-usb-opera-objs = opera1.o | ||
| 55 | obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o | ||
| 56 | |||
| 57 | |||
| 58 | dvb-usb-af9005-objs = af9005.o af9005-fe.o | ||
| 59 | obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o | ||
| 60 | |||
| 61 | dvb-usb-af9005-remote-objs = af9005-remote.o | ||
| 62 | obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o | ||
| 63 | |||
| 64 | dvb-usb-anysee-objs = anysee.o | ||
| 65 | obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o | ||
| 66 | |||
| 67 | dvb-usb-dw2102-objs = dw2102.o | ||
| 68 | obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o | ||
| 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 | dvb-usb-ce6230-objs = ce6230.o | ||
| 80 | obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o | ||
| 81 | |||
| 82 | dvb-usb-friio-objs = friio.o friio-fe.o | ||
| 83 | obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o | ||
| 84 | |||
| 85 | dvb-usb-ec168-objs = ec168.o | ||
| 86 | obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o | ||
| 87 | |||
| 88 | dvb-usb-az6027-objs = az6027.o | ||
| 89 | obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o | ||
| 90 | |||
| 91 | dvb-usb-lmedm04-objs = lmedm04.o | ||
| 92 | obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o | ||
| 93 | |||
| 94 | dvb-usb-technisat-usb2-objs = technisat-usb2.o | ||
| 95 | obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o | ||
| 96 | |||
| 97 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | ||
| 98 | # due to tuner-xc3028 | ||
| 99 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | ||
| 100 | |||
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c new file mode 100644 index 00000000000..b95a95e1784 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/a800.c | |||
| @@ -0,0 +1,208 @@ | |||
| 1 | /* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T | ||
| 2 | * USB2.0 (A800) DVB-T receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 5 | * | ||
| 6 | * Thanks to | ||
| 7 | * - AVerMedia who kindly provided information and | ||
| 8 | * - Glen Harris who suffered from my mistakes during development. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License as published by the Free | ||
| 12 | * Software Foundation, version 2. | ||
| 13 | * | ||
| 14 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 15 | */ | ||
| 16 | #include "dibusb.h" | ||
| 17 | |||
| 18 | static int debug; | ||
| 19 | module_param(debug, int, 0644); | ||
| 20 | MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 21 | |||
| 22 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 23 | |||
| 24 | #define deb_rc(args...) dprintk(debug,0x01,args) | ||
| 25 | |||
| 26 | static int a800_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 27 | { | ||
| 28 | /* do nothing for the AVerMedia */ | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | |||
| 32 | /* assure to put cold to 0 for iManufacturer == 1 */ | ||
| 33 | static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, | ||
| 34 | struct dvb_usb_device_description **desc, int *cold) | ||
| 35 | { | ||
| 36 | *cold = udev->descriptor.iManufacturer != 1; | ||
| 37 | return 0; | ||
| 38 | } | ||
| 39 | |||
| 40 | static struct rc_map_table rc_map_a800_table[] = { | ||
| 41 | { 0x0201, KEY_MODE }, /* SOURCE */ | ||
| 42 | { 0x0200, KEY_POWER2 }, /* POWER */ | ||
| 43 | { 0x0205, KEY_1 }, /* 1 */ | ||
| 44 | { 0x0206, KEY_2 }, /* 2 */ | ||
| 45 | { 0x0207, KEY_3 }, /* 3 */ | ||
| 46 | { 0x0209, KEY_4 }, /* 4 */ | ||
| 47 | { 0x020a, KEY_5 }, /* 5 */ | ||
| 48 | { 0x020b, KEY_6 }, /* 6 */ | ||
| 49 | { 0x020d, KEY_7 }, /* 7 */ | ||
| 50 | { 0x020e, KEY_8 }, /* 8 */ | ||
| 51 | { 0x020f, KEY_9 }, /* 9 */ | ||
| 52 | { 0x0212, KEY_LEFT }, /* L / DISPLAY */ | ||
| 53 | { 0x0211, KEY_0 }, /* 0 */ | ||
| 54 | { 0x0213, KEY_RIGHT }, /* R / CH RTN */ | ||
| 55 | { 0x0217, KEY_CAMERA }, /* SNAP SHOT */ | ||
| 56 | { 0x0210, KEY_LAST }, /* 16-CH PREV */ | ||
| 57 | { 0x021e, KEY_VOLUMEDOWN }, /* VOL DOWN */ | ||
| 58 | { 0x020c, KEY_ZOOM }, /* FULL SCREEN */ | ||
| 59 | { 0x021f, KEY_VOLUMEUP }, /* VOL UP */ | ||
| 60 | { 0x0214, KEY_MUTE }, /* MUTE */ | ||
| 61 | { 0x0208, KEY_AUDIO }, /* AUDIO */ | ||
| 62 | { 0x0219, KEY_RECORD }, /* RECORD */ | ||
| 63 | { 0x0218, KEY_PLAY }, /* PLAY */ | ||
| 64 | { 0x021b, KEY_STOP }, /* STOP */ | ||
| 65 | { 0x021a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */ | ||
| 66 | { 0x021d, KEY_BACK }, /* << / RED */ | ||
| 67 | { 0x021c, KEY_FORWARD }, /* >> / YELLOW */ | ||
| 68 | { 0x0203, KEY_TEXT }, /* TELETEXT */ | ||
| 69 | { 0x0204, KEY_EPG }, /* EPG */ | ||
| 70 | { 0x0215, KEY_MENU }, /* MENU */ | ||
| 71 | |||
| 72 | { 0x0303, KEY_CHANNELUP }, /* CH UP */ | ||
| 73 | { 0x0302, KEY_CHANNELDOWN }, /* CH DOWN */ | ||
| 74 | { 0x0301, KEY_FIRST }, /* |<< / GREEN */ | ||
| 75 | { 0x0300, KEY_LAST }, /* >>| / BLUE */ | ||
| 76 | |||
| 77 | }; | ||
| 78 | |||
| 79 | static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 80 | { | ||
| 81 | int ret; | ||
| 82 | u8 *key = kmalloc(5, GFP_KERNEL); | ||
| 83 | if (!key) | ||
| 84 | return -ENOMEM; | ||
| 85 | |||
| 86 | if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0), | ||
| 87 | 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5, | ||
| 88 | 2000) != 5) { | ||
| 89 | ret = -ENODEV; | ||
| 90 | goto out; | ||
| 91 | } | ||
| 92 | |||
| 93 | /* call the universal NEC remote processor, to find out the key's state and event */ | ||
| 94 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
| 95 | if (key[0] != 0) | ||
| 96 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
| 97 | ret = 0; | ||
| 98 | out: | ||
| 99 | kfree(key); | ||
| 100 | return ret; | ||
| 101 | } | ||
| 102 | |||
| 103 | /* USB Driver stuff */ | ||
| 104 | static struct dvb_usb_device_properties a800_properties; | ||
| 105 | |||
| 106 | static int a800_probe(struct usb_interface *intf, | ||
| 107 | const struct usb_device_id *id) | ||
| 108 | { | ||
| 109 | return dvb_usb_device_init(intf, &a800_properties, | ||
| 110 | THIS_MODULE, NULL, adapter_nr); | ||
| 111 | } | ||
| 112 | |||
| 113 | /* do not change the order of the ID table */ | ||
| 114 | static struct usb_device_id a800_table [] = { | ||
| 115 | /* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_COLD) }, | ||
| 116 | /* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_WARM) }, | ||
| 117 | { } /* Terminating entry */ | ||
| 118 | }; | ||
| 119 | MODULE_DEVICE_TABLE (usb, a800_table); | ||
| 120 | |||
| 121 | static struct dvb_usb_device_properties a800_properties = { | ||
| 122 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 123 | |||
| 124 | .usb_ctrl = CYPRESS_FX2, | ||
| 125 | .firmware = "dvb-usb-avertv-a800-02.fw", | ||
| 126 | |||
| 127 | .num_adapters = 1, | ||
| 128 | .adapter = { | ||
| 129 | { | ||
| 130 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 131 | .pid_filter_count = 32, | ||
| 132 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
| 133 | .pid_filter = dibusb_pid_filter, | ||
| 134 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
| 135 | |||
| 136 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | ||
| 137 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | ||
| 138 | |||
| 139 | /* parameter for the MPEG2-data transfer */ | ||
| 140 | .stream = { | ||
| 141 | .type = USB_BULK, | ||
| 142 | .count = 7, | ||
| 143 | .endpoint = 0x06, | ||
| 144 | .u = { | ||
| 145 | .bulk = { | ||
| 146 | .buffersize = 4096, | ||
| 147 | } | ||
| 148 | } | ||
| 149 | }, | ||
| 150 | |||
| 151 | .size_of_priv = sizeof(struct dibusb_state), | ||
| 152 | }, | ||
| 153 | }, | ||
| 154 | |||
| 155 | .power_ctrl = a800_power_ctrl, | ||
| 156 | .identify_state = a800_identify_state, | ||
| 157 | |||
| 158 | .rc.legacy = { | ||
| 159 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 160 | .rc_map_table = rc_map_a800_table, | ||
| 161 | .rc_map_size = ARRAY_SIZE(rc_map_a800_table), | ||
| 162 | .rc_query = a800_rc_query, | ||
| 163 | }, | ||
| 164 | |||
| 165 | .i2c_algo = &dibusb_i2c_algo, | ||
| 166 | |||
| 167 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 168 | .num_device_descs = 1, | ||
| 169 | .devices = { | ||
| 170 | { "AVerMedia AverTV DVB-T USB 2.0 (A800)", | ||
| 171 | { &a800_table[0], NULL }, | ||
| 172 | { &a800_table[1], NULL }, | ||
| 173 | }, | ||
| 174 | } | ||
| 175 | }; | ||
| 176 | |||
| 177 | static struct usb_driver a800_driver = { | ||
| 178 | .name = "dvb_usb_a800", | ||
| 179 | .probe = a800_probe, | ||
| 180 | .disconnect = dvb_usb_device_exit, | ||
| 181 | .id_table = a800_table, | ||
| 182 | }; | ||
| 183 | |||
| 184 | /* module stuff */ | ||
| 185 | static int __init a800_module_init(void) | ||
| 186 | { | ||
| 187 | int result; | ||
| 188 | if ((result = usb_register(&a800_driver))) { | ||
| 189 | err("usb_register failed. Error number %d",result); | ||
| 190 | return result; | ||
| 191 | } | ||
| 192 | |||
| 193 | return 0; | ||
| 194 | } | ||
| 195 | |||
| 196 | static void __exit a800_module_exit(void) | ||
| 197 | { | ||
| 198 | /* deregister this driver from the USB subsystem */ | ||
| 199 | usb_deregister(&a800_driver); | ||
| 200 | } | ||
| 201 | |||
| 202 | module_init (a800_module_init); | ||
| 203 | module_exit (a800_module_exit); | ||
| 204 | |||
| 205 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 206 | MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)"); | ||
| 207 | MODULE_VERSION("1.0"); | ||
| 208 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c new file mode 100644 index 00000000000..6ad94745bbd --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9005-fe.c | |||
| @@ -0,0 +1,1488 @@ | |||
| 1 | /* Frontend part of the Linux driver for the Afatech 9005 | ||
| 2 | * USB1.1 DVB-T receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org) | ||
| 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 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 23 | */ | ||
| 24 | #include "af9005.h" | ||
| 25 | #include "af9005-script.h" | ||
| 26 | #include "mt2060.h" | ||
| 27 | #include "qt1010.h" | ||
| 28 | #include <asm/div64.h> | ||
| 29 | |||
| 30 | struct af9005_fe_state { | ||
| 31 | struct dvb_usb_device *d; | ||
| 32 | fe_status_t stat; | ||
| 33 | |||
| 34 | /* retraining parameters */ | ||
| 35 | u32 original_fcw; | ||
| 36 | u16 original_rf_top; | ||
| 37 | u16 original_if_top; | ||
| 38 | u16 original_if_min; | ||
| 39 | u16 original_aci0_if_top; | ||
| 40 | u16 original_aci1_if_top; | ||
| 41 | u16 original_aci0_if_min; | ||
| 42 | u8 original_if_unplug_th; | ||
| 43 | u8 original_rf_unplug_th; | ||
| 44 | u8 original_dtop_if_unplug_th; | ||
| 45 | u8 original_dtop_rf_unplug_th; | ||
| 46 | |||
| 47 | /* statistics */ | ||
| 48 | u32 pre_vit_error_count; | ||
| 49 | u32 pre_vit_bit_count; | ||
| 50 | u32 ber; | ||
| 51 | u32 post_vit_error_count; | ||
| 52 | u32 post_vit_bit_count; | ||
| 53 | u32 unc; | ||
| 54 | u16 abort_count; | ||
| 55 | |||
| 56 | int opened; | ||
| 57 | int strong; | ||
| 58 | unsigned long next_status_check; | ||
| 59 | struct dvb_frontend frontend; | ||
| 60 | }; | ||
| 61 | |||
| 62 | static int af9005_write_word_agc(struct dvb_usb_device *d, u16 reghi, | ||
| 63 | u16 reglo, u8 pos, u8 len, u16 value) | ||
| 64 | { | ||
| 65 | int ret; | ||
| 66 | u8 temp; | ||
| 67 | |||
| 68 | if ((ret = af9005_write_ofdm_register(d, reglo, (u8) (value & 0xff)))) | ||
| 69 | return ret; | ||
| 70 | temp = (u8) ((value & 0x0300) >> 8); | ||
| 71 | return af9005_write_register_bits(d, reghi, pos, len, | ||
| 72 | (u8) ((value & 0x300) >> 8)); | ||
| 73 | } | ||
| 74 | |||
| 75 | static int af9005_read_word_agc(struct dvb_usb_device *d, u16 reghi, | ||
| 76 | u16 reglo, u8 pos, u8 len, u16 * value) | ||
| 77 | { | ||
| 78 | int ret; | ||
| 79 | u8 temp0, temp1; | ||
| 80 | |||
| 81 | if ((ret = af9005_read_ofdm_register(d, reglo, &temp0))) | ||
| 82 | return ret; | ||
| 83 | if ((ret = af9005_read_ofdm_register(d, reghi, &temp1))) | ||
| 84 | return ret; | ||
| 85 | switch (pos) { | ||
| 86 | case 0: | ||
| 87 | *value = ((u16) (temp1 & 0x03) << 8) + (u16) temp0; | ||
| 88 | break; | ||
| 89 | case 2: | ||
| 90 | *value = ((u16) (temp1 & 0x0C) << 6) + (u16) temp0; | ||
| 91 | break; | ||
| 92 | case 4: | ||
| 93 | *value = ((u16) (temp1 & 0x30) << 4) + (u16) temp0; | ||
| 94 | break; | ||
| 95 | case 6: | ||
| 96 | *value = ((u16) (temp1 & 0xC0) << 2) + (u16) temp0; | ||
| 97 | break; | ||
| 98 | default: | ||
| 99 | err("invalid pos in read word agc"); | ||
| 100 | return -EINVAL; | ||
| 101 | } | ||
| 102 | return 0; | ||
| 103 | |||
| 104 | } | ||
| 105 | |||
| 106 | static int af9005_is_fecmon_available(struct dvb_frontend *fe, int *available) | ||
| 107 | { | ||
| 108 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 109 | int ret; | ||
| 110 | u8 temp; | ||
| 111 | |||
| 112 | *available = false; | ||
| 113 | |||
| 114 | ret = af9005_read_register_bits(state->d, xd_p_fec_vtb_rsd_mon_en, | ||
| 115 | fec_vtb_rsd_mon_en_pos, | ||
| 116 | fec_vtb_rsd_mon_en_len, &temp); | ||
| 117 | if (ret) | ||
| 118 | return ret; | ||
| 119 | if (temp & 1) { | ||
| 120 | ret = | ||
| 121 | af9005_read_register_bits(state->d, | ||
| 122 | xd_p_reg_ofsm_read_rbc_en, | ||
| 123 | reg_ofsm_read_rbc_en_pos, | ||
| 124 | reg_ofsm_read_rbc_en_len, &temp); | ||
| 125 | if (ret) | ||
| 126 | return ret; | ||
| 127 | if ((temp & 1) == 0) | ||
| 128 | *available = true; | ||
| 129 | |||
| 130 | } | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int af9005_get_post_vit_err_cw_count(struct dvb_frontend *fe, | ||
| 135 | u32 * post_err_count, | ||
| 136 | u32 * post_cw_count, | ||
| 137 | u16 * abort_count) | ||
| 138 | { | ||
| 139 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 140 | int ret; | ||
| 141 | u32 err_count; | ||
| 142 | u32 cw_count; | ||
| 143 | u8 temp, temp0, temp1, temp2; | ||
| 144 | u16 loc_abort_count; | ||
| 145 | |||
| 146 | *post_err_count = 0; | ||
| 147 | *post_cw_count = 0; | ||
| 148 | |||
| 149 | /* check if error bit count is ready */ | ||
| 150 | ret = | ||
| 151 | af9005_read_register_bits(state->d, xd_r_fec_rsd_ber_rdy, | ||
| 152 | fec_rsd_ber_rdy_pos, fec_rsd_ber_rdy_len, | ||
| 153 | &temp); | ||
| 154 | if (ret) | ||
| 155 | return ret; | ||
| 156 | if (!temp) { | ||
| 157 | deb_info("rsd counter not ready\n"); | ||
| 158 | return 100; | ||
| 159 | } | ||
| 160 | /* get abort count */ | ||
| 161 | ret = | ||
| 162 | af9005_read_ofdm_register(state->d, | ||
| 163 | xd_r_fec_rsd_abort_packet_cnt_7_0, | ||
| 164 | &temp0); | ||
| 165 | if (ret) | ||
| 166 | return ret; | ||
| 167 | ret = | ||
| 168 | af9005_read_ofdm_register(state->d, | ||
| 169 | xd_r_fec_rsd_abort_packet_cnt_15_8, | ||
| 170 | &temp1); | ||
| 171 | if (ret) | ||
| 172 | return ret; | ||
| 173 | loc_abort_count = ((u16) temp1 << 8) + temp0; | ||
| 174 | |||
| 175 | /* get error count */ | ||
| 176 | ret = | ||
| 177 | af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_7_0, | ||
| 178 | &temp0); | ||
| 179 | if (ret) | ||
| 180 | return ret; | ||
| 181 | ret = | ||
| 182 | af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_15_8, | ||
| 183 | &temp1); | ||
| 184 | if (ret) | ||
| 185 | return ret; | ||
| 186 | ret = | ||
| 187 | af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_23_16, | ||
| 188 | &temp2); | ||
| 189 | if (ret) | ||
| 190 | return ret; | ||
| 191 | err_count = ((u32) temp2 << 16) + ((u32) temp1 << 8) + temp0; | ||
| 192 | *post_err_count = err_count - (u32) loc_abort_count *8 * 8; | ||
| 193 | |||
| 194 | /* get RSD packet number */ | ||
| 195 | ret = | ||
| 196 | af9005_read_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_7_0, | ||
| 197 | &temp0); | ||
| 198 | if (ret) | ||
| 199 | return ret; | ||
| 200 | ret = | ||
| 201 | af9005_read_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_15_8, | ||
| 202 | &temp1); | ||
| 203 | if (ret) | ||
| 204 | return ret; | ||
| 205 | cw_count = ((u32) temp1 << 8) + temp0; | ||
| 206 | if (cw_count == 0) { | ||
| 207 | err("wrong RSD packet count"); | ||
| 208 | return -EIO; | ||
| 209 | } | ||
| 210 | deb_info("POST abort count %d err count %d rsd packets %d\n", | ||
| 211 | loc_abort_count, err_count, cw_count); | ||
| 212 | *post_cw_count = cw_count - (u32) loc_abort_count; | ||
| 213 | *abort_count = loc_abort_count; | ||
| 214 | return 0; | ||
| 215 | |||
| 216 | } | ||
| 217 | |||
| 218 | static int af9005_get_post_vit_ber(struct dvb_frontend *fe, | ||
| 219 | u32 * post_err_count, u32 * post_cw_count, | ||
| 220 | u16 * abort_count) | ||
| 221 | { | ||
| 222 | u32 loc_cw_count = 0, loc_err_count; | ||
| 223 | u16 loc_abort_count = 0; | ||
| 224 | int ret; | ||
| 225 | |||
| 226 | ret = | ||
| 227 | af9005_get_post_vit_err_cw_count(fe, &loc_err_count, &loc_cw_count, | ||
| 228 | &loc_abort_count); | ||
| 229 | if (ret) | ||
| 230 | return ret; | ||
| 231 | *post_err_count = loc_err_count; | ||
| 232 | *post_cw_count = loc_cw_count * 204 * 8; | ||
| 233 | *abort_count = loc_abort_count; | ||
| 234 | |||
| 235 | return 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | static int af9005_get_pre_vit_err_bit_count(struct dvb_frontend *fe, | ||
| 239 | u32 * pre_err_count, | ||
| 240 | u32 * pre_bit_count) | ||
| 241 | { | ||
| 242 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 243 | u8 temp, temp0, temp1, temp2; | ||
| 244 | u32 super_frame_count, x, bits; | ||
| 245 | int ret; | ||
| 246 | |||
| 247 | ret = | ||
| 248 | af9005_read_register_bits(state->d, xd_r_fec_vtb_ber_rdy, | ||
| 249 | fec_vtb_ber_rdy_pos, fec_vtb_ber_rdy_len, | ||
| 250 | &temp); | ||
| 251 | if (ret) | ||
| 252 | return ret; | ||
| 253 | if (!temp) { | ||
| 254 | deb_info("viterbi counter not ready\n"); | ||
| 255 | return 101; /* ERR_APO_VTB_COUNTER_NOT_READY; */ | ||
| 256 | } | ||
| 257 | ret = | ||
| 258 | af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_7_0, | ||
| 259 | &temp0); | ||
| 260 | if (ret) | ||
| 261 | return ret; | ||
| 262 | ret = | ||
| 263 | af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_15_8, | ||
| 264 | &temp1); | ||
| 265 | if (ret) | ||
| 266 | return ret; | ||
| 267 | ret = | ||
| 268 | af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_23_16, | ||
| 269 | &temp2); | ||
| 270 | if (ret) | ||
| 271 | return ret; | ||
| 272 | *pre_err_count = ((u32) temp2 << 16) + ((u32) temp1 << 8) + temp0; | ||
| 273 | |||
| 274 | ret = | ||
| 275 | af9005_read_ofdm_register(state->d, xd_p_fec_super_frm_unit_7_0, | ||
| 276 | &temp0); | ||
| 277 | if (ret) | ||
| 278 | return ret; | ||
| 279 | ret = | ||
| 280 | af9005_read_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8, | ||
| 281 | &temp1); | ||
| 282 | if (ret) | ||
| 283 | return ret; | ||
| 284 | super_frame_count = ((u32) temp1 << 8) + temp0; | ||
| 285 | if (super_frame_count == 0) { | ||
| 286 | deb_info("super frame count 0\n"); | ||
| 287 | return 102; | ||
| 288 | } | ||
| 289 | |||
| 290 | /* read fft mode */ | ||
| 291 | ret = | ||
| 292 | af9005_read_register_bits(state->d, xd_g_reg_tpsd_txmod, | ||
| 293 | reg_tpsd_txmod_pos, reg_tpsd_txmod_len, | ||
| 294 | &temp); | ||
| 295 | if (ret) | ||
| 296 | return ret; | ||
| 297 | if (temp == 0) { | ||
| 298 | /* 2K */ | ||
| 299 | x = 1512; | ||
| 300 | } else if (temp == 1) { | ||
| 301 | /* 8k */ | ||
| 302 | x = 6048; | ||
| 303 | } else { | ||
| 304 | err("Invalid fft mode"); | ||
| 305 | return -EINVAL; | ||
| 306 | } | ||
| 307 | |||
| 308 | /* read constellation mode */ | ||
| 309 | ret = | ||
| 310 | af9005_read_register_bits(state->d, xd_g_reg_tpsd_const, | ||
| 311 | reg_tpsd_const_pos, reg_tpsd_const_len, | ||
| 312 | &temp); | ||
| 313 | if (ret) | ||
| 314 | return ret; | ||
| 315 | switch (temp) { | ||
| 316 | case 0: /* QPSK */ | ||
| 317 | bits = 2; | ||
| 318 | break; | ||
| 319 | case 1: /* QAM_16 */ | ||
| 320 | bits = 4; | ||
| 321 | break; | ||
| 322 | case 2: /* QAM_64 */ | ||
| 323 | bits = 6; | ||
| 324 | break; | ||
| 325 | default: | ||
| 326 | err("invalid constellation mode"); | ||
| 327 | return -EINVAL; | ||
| 328 | } | ||
| 329 | *pre_bit_count = super_frame_count * 68 * 4 * x * bits; | ||
| 330 | deb_info("PRE err count %d frame count %d bit count %d\n", | ||
| 331 | *pre_err_count, super_frame_count, *pre_bit_count); | ||
| 332 | return 0; | ||
| 333 | } | ||
| 334 | |||
| 335 | static int af9005_reset_pre_viterbi(struct dvb_frontend *fe) | ||
| 336 | { | ||
| 337 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 338 | int ret; | ||
| 339 | |||
| 340 | /* set super frame count to 1 */ | ||
| 341 | ret = | ||
| 342 | af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_7_0, | ||
| 343 | 1 & 0xff); | ||
| 344 | if (ret) | ||
| 345 | return ret; | ||
| 346 | ret = af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8, | ||
| 347 | 1 >> 8); | ||
| 348 | if (ret) | ||
| 349 | return ret; | ||
| 350 | /* reset pre viterbi error count */ | ||
| 351 | ret = | ||
| 352 | af9005_write_register_bits(state->d, xd_p_fec_vtb_ber_rst, | ||
| 353 | fec_vtb_ber_rst_pos, fec_vtb_ber_rst_len, | ||
| 354 | 1); | ||
| 355 | |||
| 356 | return ret; | ||
| 357 | } | ||
| 358 | |||
| 359 | static int af9005_reset_post_viterbi(struct dvb_frontend *fe) | ||
| 360 | { | ||
| 361 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 362 | int ret; | ||
| 363 | |||
| 364 | /* set packet unit */ | ||
| 365 | ret = | ||
| 366 | af9005_write_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_7_0, | ||
| 367 | 10000 & 0xff); | ||
| 368 | if (ret) | ||
| 369 | return ret; | ||
| 370 | ret = | ||
| 371 | af9005_write_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_15_8, | ||
| 372 | 10000 >> 8); | ||
| 373 | if (ret) | ||
| 374 | return ret; | ||
| 375 | /* reset post viterbi error count */ | ||
| 376 | ret = | ||
| 377 | af9005_write_register_bits(state->d, xd_p_fec_rsd_ber_rst, | ||
| 378 | fec_rsd_ber_rst_pos, fec_rsd_ber_rst_len, | ||
| 379 | 1); | ||
| 380 | |||
| 381 | return ret; | ||
| 382 | } | ||
| 383 | |||
| 384 | static int af9005_get_statistic(struct dvb_frontend *fe) | ||
| 385 | { | ||
| 386 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 387 | int ret, fecavailable; | ||
| 388 | u64 numerator, denominator; | ||
| 389 | |||
| 390 | deb_info("GET STATISTIC\n"); | ||
| 391 | ret = af9005_is_fecmon_available(fe, &fecavailable); | ||
| 392 | if (ret) | ||
| 393 | return ret; | ||
| 394 | if (!fecavailable) { | ||
| 395 | deb_info("fecmon not available\n"); | ||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | ret = af9005_get_pre_vit_err_bit_count(fe, &state->pre_vit_error_count, | ||
| 400 | &state->pre_vit_bit_count); | ||
| 401 | if (ret == 0) { | ||
| 402 | af9005_reset_pre_viterbi(fe); | ||
| 403 | if (state->pre_vit_bit_count > 0) { | ||
| 404 | /* according to v 0.0.4 of the dvb api ber should be a multiple | ||
| 405 | of 10E-9 so we have to multiply the error count by | ||
| 406 | 10E9=1000000000 */ | ||
| 407 | numerator = | ||
| 408 | (u64) state->pre_vit_error_count * (u64) 1000000000; | ||
| 409 | denominator = (u64) state->pre_vit_bit_count; | ||
| 410 | state->ber = do_div(numerator, denominator); | ||
| 411 | } else { | ||
| 412 | state->ber = 0xffffffff; | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 416 | ret = af9005_get_post_vit_ber(fe, &state->post_vit_error_count, | ||
| 417 | &state->post_vit_bit_count, | ||
| 418 | &state->abort_count); | ||
| 419 | if (ret == 0) { | ||
| 420 | ret = af9005_reset_post_viterbi(fe); | ||
| 421 | state->unc += state->abort_count; | ||
| 422 | if (ret) | ||
| 423 | return ret; | ||
| 424 | } | ||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | static int af9005_fe_refresh_state(struct dvb_frontend *fe) | ||
| 429 | { | ||
| 430 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 431 | if (time_after(jiffies, state->next_status_check)) { | ||
| 432 | deb_info("REFRESH STATE\n"); | ||
| 433 | |||
| 434 | /* statistics */ | ||
| 435 | if (af9005_get_statistic(fe)) | ||
| 436 | err("get_statistic_failed"); | ||
| 437 | state->next_status_check = jiffies + 250 * HZ / 1000; | ||
| 438 | } | ||
| 439 | return 0; | ||
| 440 | } | ||
| 441 | |||
| 442 | static int af9005_fe_read_status(struct dvb_frontend *fe, fe_status_t * stat) | ||
| 443 | { | ||
| 444 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 445 | u8 temp; | ||
| 446 | int ret; | ||
| 447 | |||
| 448 | if (fe->ops.tuner_ops.release == NULL) | ||
| 449 | return -ENODEV; | ||
| 450 | |||
| 451 | *stat = 0; | ||
| 452 | ret = af9005_read_register_bits(state->d, xd_p_agc_lock, | ||
| 453 | agc_lock_pos, agc_lock_len, &temp); | ||
| 454 | if (ret) | ||
| 455 | return ret; | ||
| 456 | if (temp) | ||
| 457 | *stat |= FE_HAS_SIGNAL; | ||
| 458 | |||
| 459 | ret = af9005_read_register_bits(state->d, xd_p_fd_tpsd_lock, | ||
| 460 | fd_tpsd_lock_pos, fd_tpsd_lock_len, | ||
| 461 | &temp); | ||
| 462 | if (ret) | ||
| 463 | return ret; | ||
| 464 | if (temp) | ||
| 465 | *stat |= FE_HAS_CARRIER; | ||
| 466 | |||
| 467 | ret = af9005_read_register_bits(state->d, | ||
| 468 | xd_r_mp2if_sync_byte_locked, | ||
| 469 | mp2if_sync_byte_locked_pos, | ||
| 470 | mp2if_sync_byte_locked_pos, &temp); | ||
| 471 | if (ret) | ||
| 472 | return ret; | ||
| 473 | if (temp) | ||
| 474 | *stat |= FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_LOCK; | ||
| 475 | if (state->opened) | ||
| 476 | af9005_led_control(state->d, *stat & FE_HAS_LOCK); | ||
| 477 | |||
| 478 | ret = | ||
| 479 | af9005_read_register_bits(state->d, xd_p_reg_strong_sginal_detected, | ||
| 480 | reg_strong_sginal_detected_pos, | ||
| 481 | reg_strong_sginal_detected_len, &temp); | ||
| 482 | if (ret) | ||
| 483 | return ret; | ||
| 484 | if (temp != state->strong) { | ||
| 485 | deb_info("adjust for strong signal %d\n", temp); | ||
| 486 | state->strong = temp; | ||
| 487 | } | ||
| 488 | return 0; | ||
| 489 | } | ||
| 490 | |||
| 491 | static int af9005_fe_read_ber(struct dvb_frontend *fe, u32 * ber) | ||
| 492 | { | ||
| 493 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 494 | if (fe->ops.tuner_ops.release == NULL) | ||
| 495 | return -ENODEV; | ||
| 496 | af9005_fe_refresh_state(fe); | ||
| 497 | *ber = state->ber; | ||
| 498 | return 0; | ||
| 499 | } | ||
| 500 | |||
| 501 | static int af9005_fe_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) | ||
| 502 | { | ||
| 503 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 504 | if (fe->ops.tuner_ops.release == NULL) | ||
| 505 | return -ENODEV; | ||
| 506 | af9005_fe_refresh_state(fe); | ||
| 507 | *unc = state->unc; | ||
| 508 | return 0; | ||
| 509 | } | ||
| 510 | |||
| 511 | static int af9005_fe_read_signal_strength(struct dvb_frontend *fe, | ||
| 512 | u16 * strength) | ||
| 513 | { | ||
| 514 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 515 | int ret; | ||
| 516 | u8 if_gain, rf_gain; | ||
| 517 | |||
| 518 | if (fe->ops.tuner_ops.release == NULL) | ||
| 519 | return -ENODEV; | ||
| 520 | ret = | ||
| 521 | af9005_read_ofdm_register(state->d, xd_r_reg_aagc_rf_gain, | ||
| 522 | &rf_gain); | ||
| 523 | if (ret) | ||
| 524 | return ret; | ||
| 525 | ret = | ||
| 526 | af9005_read_ofdm_register(state->d, xd_r_reg_aagc_if_gain, | ||
| 527 | &if_gain); | ||
| 528 | if (ret) | ||
| 529 | return ret; | ||
| 530 | /* this value has no real meaning, but i don't have the tables that relate | ||
| 531 | the rf and if gain with the dbm, so I just scale the value */ | ||
| 532 | *strength = (512 - rf_gain - if_gain) << 7; | ||
| 533 | return 0; | ||
| 534 | } | ||
| 535 | |||
| 536 | static int af9005_fe_read_snr(struct dvb_frontend *fe, u16 * snr) | ||
| 537 | { | ||
| 538 | /* the snr can be derived from the ber and the constellation | ||
| 539 | but I don't think this kind of complex calculations belong | ||
| 540 | in the driver. I may be wrong.... */ | ||
| 541 | return -ENOSYS; | ||
| 542 | } | ||
| 543 | |||
| 544 | static int af9005_fe_program_cfoe(struct dvb_usb_device *d, fe_bandwidth_t bw) | ||
| 545 | { | ||
| 546 | u8 temp0, temp1, temp2, temp3, buf[4]; | ||
| 547 | int ret; | ||
| 548 | u32 NS_coeff1_2048Nu; | ||
| 549 | u32 NS_coeff1_8191Nu; | ||
| 550 | u32 NS_coeff1_8192Nu; | ||
| 551 | u32 NS_coeff1_8193Nu; | ||
| 552 | u32 NS_coeff2_2k; | ||
| 553 | u32 NS_coeff2_8k; | ||
| 554 | |||
| 555 | switch (bw) { | ||
| 556 | case BANDWIDTH_6_MHZ: | ||
| 557 | NS_coeff1_2048Nu = 0x2ADB6DC; | ||
| 558 | NS_coeff1_8191Nu = 0xAB7313; | ||
| 559 | NS_coeff1_8192Nu = 0xAB6DB7; | ||
| 560 | NS_coeff1_8193Nu = 0xAB685C; | ||
| 561 | NS_coeff2_2k = 0x156DB6E; | ||
| 562 | NS_coeff2_8k = 0x55B6DC; | ||
| 563 | break; | ||
| 564 | |||
| 565 | case BANDWIDTH_7_MHZ: | ||
| 566 | NS_coeff1_2048Nu = 0x3200001; | ||
| 567 | NS_coeff1_8191Nu = 0xC80640; | ||
| 568 | NS_coeff1_8192Nu = 0xC80000; | ||
| 569 | NS_coeff1_8193Nu = 0xC7F9C0; | ||
| 570 | NS_coeff2_2k = 0x1900000; | ||
| 571 | NS_coeff2_8k = 0x640000; | ||
| 572 | break; | ||
| 573 | |||
| 574 | case BANDWIDTH_8_MHZ: | ||
| 575 | NS_coeff1_2048Nu = 0x3924926; | ||
| 576 | NS_coeff1_8191Nu = 0xE4996E; | ||
| 577 | NS_coeff1_8192Nu = 0xE49249; | ||
| 578 | NS_coeff1_8193Nu = 0xE48B25; | ||
| 579 | NS_coeff2_2k = 0x1C92493; | ||
| 580 | NS_coeff2_8k = 0x724925; | ||
| 581 | break; | ||
| 582 | default: | ||
| 583 | err("Invalid bandwidth %d.", bw); | ||
| 584 | return -EINVAL; | ||
| 585 | } | ||
| 586 | |||
| 587 | /* | ||
| 588 | * write NS_coeff1_2048Nu | ||
| 589 | */ | ||
| 590 | |||
| 591 | temp0 = (u8) (NS_coeff1_2048Nu & 0x000000FF); | ||
| 592 | temp1 = (u8) ((NS_coeff1_2048Nu & 0x0000FF00) >> 8); | ||
| 593 | temp2 = (u8) ((NS_coeff1_2048Nu & 0x00FF0000) >> 16); | ||
| 594 | temp3 = (u8) ((NS_coeff1_2048Nu & 0x03000000) >> 24); | ||
| 595 | |||
| 596 | /* big endian to make 8051 happy */ | ||
| 597 | buf[0] = temp3; | ||
| 598 | buf[1] = temp2; | ||
| 599 | buf[2] = temp1; | ||
| 600 | buf[3] = temp0; | ||
| 601 | |||
| 602 | /* cfoe_NS_2k_coeff1_25_24 */ | ||
| 603 | ret = af9005_write_ofdm_register(d, 0xAE00, buf[0]); | ||
| 604 | if (ret) | ||
| 605 | return ret; | ||
| 606 | |||
| 607 | /* cfoe_NS_2k_coeff1_23_16 */ | ||
| 608 | ret = af9005_write_ofdm_register(d, 0xAE01, buf[1]); | ||
| 609 | if (ret) | ||
| 610 | return ret; | ||
| 611 | |||
| 612 | /* cfoe_NS_2k_coeff1_15_8 */ | ||
| 613 | ret = af9005_write_ofdm_register(d, 0xAE02, buf[2]); | ||
| 614 | if (ret) | ||
| 615 | return ret; | ||
| 616 | |||
| 617 | /* cfoe_NS_2k_coeff1_7_0 */ | ||
| 618 | ret = af9005_write_ofdm_register(d, 0xAE03, buf[3]); | ||
| 619 | if (ret) | ||
| 620 | return ret; | ||
| 621 | |||
| 622 | /* | ||
| 623 | * write NS_coeff2_2k | ||
| 624 | */ | ||
| 625 | |||
| 626 | temp0 = (u8) ((NS_coeff2_2k & 0x0000003F)); | ||
| 627 | temp1 = (u8) ((NS_coeff2_2k & 0x00003FC0) >> 6); | ||
| 628 | temp2 = (u8) ((NS_coeff2_2k & 0x003FC000) >> 14); | ||
| 629 | temp3 = (u8) ((NS_coeff2_2k & 0x01C00000) >> 22); | ||
| 630 | |||
| 631 | /* big endian to make 8051 happy */ | ||
| 632 | buf[0] = temp3; | ||
| 633 | buf[1] = temp2; | ||
| 634 | buf[2] = temp1; | ||
| 635 | buf[3] = temp0; | ||
| 636 | |||
| 637 | ret = af9005_write_ofdm_register(d, 0xAE04, buf[0]); | ||
| 638 | if (ret) | ||
| 639 | return ret; | ||
| 640 | |||
| 641 | ret = af9005_write_ofdm_register(d, 0xAE05, buf[1]); | ||
| 642 | if (ret) | ||
| 643 | return ret; | ||
| 644 | |||
| 645 | ret = af9005_write_ofdm_register(d, 0xAE06, buf[2]); | ||
| 646 | if (ret) | ||
| 647 | return ret; | ||
| 648 | |||
| 649 | ret = af9005_write_ofdm_register(d, 0xAE07, buf[3]); | ||
| 650 | if (ret) | ||
| 651 | return ret; | ||
| 652 | |||
| 653 | /* | ||
| 654 | * write NS_coeff1_8191Nu | ||
| 655 | */ | ||
| 656 | |||
| 657 | temp0 = (u8) ((NS_coeff1_8191Nu & 0x000000FF)); | ||
| 658 | temp1 = (u8) ((NS_coeff1_8191Nu & 0x0000FF00) >> 8); | ||
| 659 | temp2 = (u8) ((NS_coeff1_8191Nu & 0x00FFC000) >> 16); | ||
| 660 | temp3 = (u8) ((NS_coeff1_8191Nu & 0x03000000) >> 24); | ||
| 661 | |||
| 662 | /* big endian to make 8051 happy */ | ||
| 663 | buf[0] = temp3; | ||
| 664 | buf[1] = temp2; | ||
| 665 | buf[2] = temp1; | ||
| 666 | buf[3] = temp0; | ||
| 667 | |||
| 668 | ret = af9005_write_ofdm_register(d, 0xAE08, buf[0]); | ||
| 669 | if (ret) | ||
| 670 | return ret; | ||
| 671 | |||
| 672 | ret = af9005_write_ofdm_register(d, 0xAE09, buf[1]); | ||
| 673 | if (ret) | ||
| 674 | return ret; | ||
| 675 | |||
| 676 | ret = af9005_write_ofdm_register(d, 0xAE0A, buf[2]); | ||
| 677 | if (ret) | ||
| 678 | return ret; | ||
| 679 | |||
| 680 | ret = af9005_write_ofdm_register(d, 0xAE0B, buf[3]); | ||
| 681 | if (ret) | ||
| 682 | return ret; | ||
| 683 | |||
| 684 | /* | ||
| 685 | * write NS_coeff1_8192Nu | ||
| 686 | */ | ||
| 687 | |||
| 688 | temp0 = (u8) (NS_coeff1_8192Nu & 0x000000FF); | ||
| 689 | temp1 = (u8) ((NS_coeff1_8192Nu & 0x0000FF00) >> 8); | ||
| 690 | temp2 = (u8) ((NS_coeff1_8192Nu & 0x00FFC000) >> 16); | ||
| 691 | temp3 = (u8) ((NS_coeff1_8192Nu & 0x03000000) >> 24); | ||
| 692 | |||
| 693 | /* big endian to make 8051 happy */ | ||
| 694 | buf[0] = temp3; | ||
| 695 | buf[1] = temp2; | ||
| 696 | buf[2] = temp1; | ||
| 697 | buf[3] = temp0; | ||
| 698 | |||
| 699 | ret = af9005_write_ofdm_register(d, 0xAE0C, buf[0]); | ||
| 700 | if (ret) | ||
| 701 | return ret; | ||
| 702 | |||
| 703 | ret = af9005_write_ofdm_register(d, 0xAE0D, buf[1]); | ||
| 704 | if (ret) | ||
| 705 | return ret; | ||
| 706 | |||
| 707 | ret = af9005_write_ofdm_register(d, 0xAE0E, buf[2]); | ||
| 708 | if (ret) | ||
| 709 | return ret; | ||
| 710 | |||
| 711 | ret = af9005_write_ofdm_register(d, 0xAE0F, buf[3]); | ||
| 712 | if (ret) | ||
| 713 | return ret; | ||
| 714 | |||
| 715 | /* | ||
| 716 | * write NS_coeff1_8193Nu | ||
| 717 | */ | ||
| 718 | |||
| 719 | temp0 = (u8) ((NS_coeff1_8193Nu & 0x000000FF)); | ||
| 720 | temp1 = (u8) ((NS_coeff1_8193Nu & 0x0000FF00) >> 8); | ||
| 721 | temp2 = (u8) ((NS_coeff1_8193Nu & 0x00FFC000) >> 16); | ||
| 722 | temp3 = (u8) ((NS_coeff1_8193Nu & 0x03000000) >> 24); | ||
| 723 | |||
| 724 | /* big endian to make 8051 happy */ | ||
| 725 | buf[0] = temp3; | ||
| 726 | buf[1] = temp2; | ||
| 727 | buf[2] = temp1; | ||
| 728 | buf[3] = temp0; | ||
| 729 | |||
| 730 | ret = af9005_write_ofdm_register(d, 0xAE10, buf[0]); | ||
| 731 | if (ret) | ||
| 732 | return ret; | ||
| 733 | |||
| 734 | ret = af9005_write_ofdm_register(d, 0xAE11, buf[1]); | ||
| 735 | if (ret) | ||
| 736 | return ret; | ||
| 737 | |||
| 738 | ret = af9005_write_ofdm_register(d, 0xAE12, buf[2]); | ||
| 739 | if (ret) | ||
| 740 | return ret; | ||
| 741 | |||
| 742 | ret = af9005_write_ofdm_register(d, 0xAE13, buf[3]); | ||
| 743 | if (ret) | ||
| 744 | return ret; | ||
| 745 | |||
| 746 | /* | ||
| 747 | * write NS_coeff2_8k | ||
| 748 | */ | ||
| 749 | |||
| 750 | temp0 = (u8) ((NS_coeff2_8k & 0x0000003F)); | ||
| 751 | temp1 = (u8) ((NS_coeff2_8k & 0x00003FC0) >> 6); | ||
| 752 | temp2 = (u8) ((NS_coeff2_8k & 0x003FC000) >> 14); | ||
| 753 | temp3 = (u8) ((NS_coeff2_8k & 0x01C00000) >> 22); | ||
| 754 | |||
| 755 | /* big endian to make 8051 happy */ | ||
| 756 | buf[0] = temp3; | ||
| 757 | buf[1] = temp2; | ||
| 758 | buf[2] = temp1; | ||
| 759 | buf[3] = temp0; | ||
| 760 | |||
| 761 | ret = af9005_write_ofdm_register(d, 0xAE14, buf[0]); | ||
| 762 | if (ret) | ||
| 763 | return ret; | ||
| 764 | |||
| 765 | ret = af9005_write_ofdm_register(d, 0xAE15, buf[1]); | ||
| 766 | if (ret) | ||
| 767 | return ret; | ||
| 768 | |||
| 769 | ret = af9005_write_ofdm_register(d, 0xAE16, buf[2]); | ||
| 770 | if (ret) | ||
| 771 | return ret; | ||
| 772 | |||
| 773 | ret = af9005_write_ofdm_register(d, 0xAE17, buf[3]); | ||
| 774 | return ret; | ||
| 775 | |||
| 776 | } | ||
| 777 | |||
| 778 | static int af9005_fe_select_bw(struct dvb_usb_device *d, fe_bandwidth_t bw) | ||
| 779 | { | ||
| 780 | u8 temp; | ||
| 781 | switch (bw) { | ||
| 782 | case BANDWIDTH_6_MHZ: | ||
| 783 | temp = 0; | ||
| 784 | break; | ||
| 785 | case BANDWIDTH_7_MHZ: | ||
| 786 | temp = 1; | ||
| 787 | break; | ||
| 788 | case BANDWIDTH_8_MHZ: | ||
| 789 | temp = 2; | ||
| 790 | break; | ||
| 791 | default: | ||
| 792 | err("Invalid bandwidth %d.", bw); | ||
| 793 | return -EINVAL; | ||
| 794 | } | ||
| 795 | return af9005_write_register_bits(d, xd_g_reg_bw, reg_bw_pos, | ||
| 796 | reg_bw_len, temp); | ||
| 797 | } | ||
| 798 | |||
| 799 | static int af9005_fe_power(struct dvb_frontend *fe, int on) | ||
| 800 | { | ||
| 801 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 802 | u8 temp = on; | ||
| 803 | int ret; | ||
| 804 | deb_info("power %s tuner\n", on ? "on" : "off"); | ||
| 805 | ret = af9005_send_command(state->d, 0x03, &temp, 1, NULL, 0); | ||
| 806 | return ret; | ||
| 807 | } | ||
| 808 | |||
| 809 | static struct mt2060_config af9005_mt2060_config = { | ||
| 810 | 0xC0 | ||
| 811 | }; | ||
| 812 | |||
| 813 | static struct qt1010_config af9005_qt1010_config = { | ||
| 814 | 0xC4 | ||
| 815 | }; | ||
| 816 | |||
| 817 | static int af9005_fe_init(struct dvb_frontend *fe) | ||
| 818 | { | ||
| 819 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 820 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 821 | int ret, i, scriptlen; | ||
| 822 | u8 temp, temp0 = 0, temp1 = 0, temp2 = 0; | ||
| 823 | u8 buf[2]; | ||
| 824 | u16 if1; | ||
| 825 | |||
| 826 | deb_info("in af9005_fe_init\n"); | ||
| 827 | |||
| 828 | /* reset */ | ||
| 829 | deb_info("reset\n"); | ||
| 830 | if ((ret = | ||
| 831 | af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst_en, | ||
| 832 | 4, 1, 0x01))) | ||
| 833 | return ret; | ||
| 834 | if ((ret = af9005_write_ofdm_register(state->d, APO_REG_RESET, 0))) | ||
| 835 | return ret; | ||
| 836 | /* clear ofdm reset */ | ||
| 837 | deb_info("clear ofdm reset\n"); | ||
| 838 | for (i = 0; i < 150; i++) { | ||
| 839 | if ((ret = | ||
| 840 | af9005_read_ofdm_register(state->d, | ||
| 841 | xd_I2C_reg_ofdm_rst, &temp))) | ||
| 842 | return ret; | ||
| 843 | if (temp & (regmask[reg_ofdm_rst_len - 1] << reg_ofdm_rst_pos)) | ||
| 844 | break; | ||
| 845 | msleep(10); | ||
| 846 | } | ||
| 847 | if (i == 150) | ||
| 848 | return -ETIMEDOUT; | ||
| 849 | |||
| 850 | /*FIXME in the dump | ||
| 851 | write B200 A9 | ||
| 852 | write xd_g_reg_ofsm_clk 7 | ||
| 853 | read eepr c6 (2) | ||
| 854 | read eepr c7 (2) | ||
| 855 | misc ctrl 3 -> 1 | ||
| 856 | read eepr ca (6) | ||
| 857 | write xd_g_reg_ofsm_clk 0 | ||
| 858 | write B200 a1 | ||
| 859 | */ | ||
| 860 | ret = af9005_write_ofdm_register(state->d, 0xb200, 0xa9); | ||
| 861 | if (ret) | ||
| 862 | return ret; | ||
| 863 | ret = af9005_write_ofdm_register(state->d, xd_g_reg_ofsm_clk, 0x07); | ||
| 864 | if (ret) | ||
| 865 | return ret; | ||
| 866 | temp = 0x01; | ||
| 867 | ret = af9005_send_command(state->d, 0x03, &temp, 1, NULL, 0); | ||
| 868 | if (ret) | ||
| 869 | return ret; | ||
| 870 | ret = af9005_write_ofdm_register(state->d, xd_g_reg_ofsm_clk, 0x00); | ||
| 871 | if (ret) | ||
| 872 | return ret; | ||
| 873 | ret = af9005_write_ofdm_register(state->d, 0xb200, 0xa1); | ||
| 874 | if (ret) | ||
| 875 | return ret; | ||
| 876 | |||
| 877 | temp = regmask[reg_ofdm_rst_len - 1] << reg_ofdm_rst_pos; | ||
| 878 | if ((ret = | ||
| 879 | af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst, | ||
| 880 | reg_ofdm_rst_pos, reg_ofdm_rst_len, 1))) | ||
| 881 | return ret; | ||
| 882 | ret = af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst, | ||
| 883 | reg_ofdm_rst_pos, reg_ofdm_rst_len, 0); | ||
| 884 | |||
| 885 | if (ret) | ||
| 886 | return ret; | ||
| 887 | /* don't know what register aefc is, but this is what the windows driver does */ | ||
| 888 | ret = af9005_write_ofdm_register(state->d, 0xaefc, 0); | ||
| 889 | if (ret) | ||
| 890 | return ret; | ||
| 891 | |||
| 892 | /* set stand alone chip */ | ||
| 893 | deb_info("set stand alone chip\n"); | ||
| 894 | if ((ret = | ||
| 895 | af9005_write_register_bits(state->d, xd_p_reg_dca_stand_alone, | ||
| 896 | reg_dca_stand_alone_pos, | ||
| 897 | reg_dca_stand_alone_len, 1))) | ||
| 898 | return ret; | ||
| 899 | |||
| 900 | /* set dca upper & lower chip */ | ||
| 901 | deb_info("set dca upper & lower chip\n"); | ||
| 902 | if ((ret = | ||
| 903 | af9005_write_register_bits(state->d, xd_p_reg_dca_upper_chip, | ||
| 904 | reg_dca_upper_chip_pos, | ||
| 905 | reg_dca_upper_chip_len, 0))) | ||
| 906 | return ret; | ||
| 907 | if ((ret = | ||
| 908 | af9005_write_register_bits(state->d, xd_p_reg_dca_lower_chip, | ||
| 909 | reg_dca_lower_chip_pos, | ||
| 910 | reg_dca_lower_chip_len, 0))) | ||
| 911 | return ret; | ||
| 912 | |||
| 913 | /* set 2wire master clock to 0x14 (for 60KHz) */ | ||
| 914 | deb_info("set 2wire master clock to 0x14 (for 60KHz)\n"); | ||
| 915 | if ((ret = | ||
| 916 | af9005_write_ofdm_register(state->d, xd_I2C_i2c_m_period, 0x14))) | ||
| 917 | return ret; | ||
| 918 | |||
| 919 | /* clear dca enable chip */ | ||
| 920 | deb_info("clear dca enable chip\n"); | ||
| 921 | if ((ret = | ||
| 922 | af9005_write_register_bits(state->d, xd_p_reg_dca_en, | ||
| 923 | reg_dca_en_pos, reg_dca_en_len, 0))) | ||
| 924 | return ret; | ||
| 925 | /* FIXME these are register bits, but I don't know which ones */ | ||
| 926 | ret = af9005_write_ofdm_register(state->d, 0xa16c, 1); | ||
| 927 | if (ret) | ||
| 928 | return ret; | ||
| 929 | ret = af9005_write_ofdm_register(state->d, 0xa3c1, 0); | ||
| 930 | if (ret) | ||
| 931 | return ret; | ||
| 932 | |||
| 933 | /* init other parameters: program cfoe and select bandwidth */ | ||
| 934 | deb_info("program cfoe\n"); | ||
| 935 | if ((ret = af9005_fe_program_cfoe(state->d, BANDWIDTH_6_MHZ))) | ||
| 936 | return ret; | ||
| 937 | /* set read-update bit for constellation */ | ||
| 938 | deb_info("set read-update bit for constellation\n"); | ||
| 939 | if ((ret = | ||
| 940 | af9005_write_register_bits(state->d, xd_p_reg_feq_read_update, | ||
| 941 | reg_feq_read_update_pos, | ||
| 942 | reg_feq_read_update_len, 1))) | ||
| 943 | return ret; | ||
| 944 | |||
| 945 | /* sample code has a set MPEG TS code here | ||
| 946 | but sniffing reveals that it doesn't do it */ | ||
| 947 | |||
| 948 | /* set read-update bit to 1 for DCA constellation */ | ||
| 949 | deb_info("set read-update bit 1 for DCA constellation\n"); | ||
| 950 | if ((ret = | ||
| 951 | af9005_write_register_bits(state->d, xd_p_reg_dca_read_update, | ||
| 952 | reg_dca_read_update_pos, | ||
| 953 | reg_dca_read_update_len, 1))) | ||
| 954 | return ret; | ||
| 955 | |||
| 956 | /* enable fec monitor */ | ||
| 957 | deb_info("enable fec monitor\n"); | ||
| 958 | if ((ret = | ||
| 959 | af9005_write_register_bits(state->d, xd_p_fec_vtb_rsd_mon_en, | ||
| 960 | fec_vtb_rsd_mon_en_pos, | ||
| 961 | fec_vtb_rsd_mon_en_len, 1))) | ||
| 962 | return ret; | ||
| 963 | |||
| 964 | /* FIXME should be register bits, I don't know which ones */ | ||
| 965 | ret = af9005_write_ofdm_register(state->d, 0xa601, 0); | ||
| 966 | |||
| 967 | /* set api_retrain_never_freeze */ | ||
| 968 | deb_info("set api_retrain_never_freeze\n"); | ||
| 969 | if ((ret = af9005_write_ofdm_register(state->d, 0xaefb, 0x01))) | ||
| 970 | return ret; | ||
| 971 | |||
| 972 | /* load init script */ | ||
| 973 | deb_info("load init script\n"); | ||
| 974 | scriptlen = sizeof(script) / sizeof(RegDesc); | ||
| 975 | for (i = 0; i < scriptlen; i++) { | ||
| 976 | if ((ret = | ||
| 977 | af9005_write_register_bits(state->d, script[i].reg, | ||
| 978 | script[i].pos, | ||
| 979 | script[i].len, script[i].val))) | ||
| 980 | return ret; | ||
| 981 | /* save 3 bytes of original fcw */ | ||
| 982 | if (script[i].reg == 0xae18) | ||
| 983 | temp2 = script[i].val; | ||
| 984 | if (script[i].reg == 0xae19) | ||
| 985 | temp1 = script[i].val; | ||
| 986 | if (script[i].reg == 0xae1a) | ||
| 987 | temp0 = script[i].val; | ||
| 988 | |||
| 989 | /* save original unplug threshold */ | ||
| 990 | if (script[i].reg == xd_p_reg_unplug_th) | ||
| 991 | state->original_if_unplug_th = script[i].val; | ||
| 992 | if (script[i].reg == xd_p_reg_unplug_rf_gain_th) | ||
| 993 | state->original_rf_unplug_th = script[i].val; | ||
| 994 | if (script[i].reg == xd_p_reg_unplug_dtop_if_gain_th) | ||
| 995 | state->original_dtop_if_unplug_th = script[i].val; | ||
| 996 | if (script[i].reg == xd_p_reg_unplug_dtop_rf_gain_th) | ||
| 997 | state->original_dtop_rf_unplug_th = script[i].val; | ||
| 998 | |||
| 999 | } | ||
| 1000 | state->original_fcw = | ||
| 1001 | ((u32) temp2 << 16) + ((u32) temp1 << 8) + (u32) temp0; | ||
| 1002 | |||
| 1003 | |||
| 1004 | /* save original TOPs */ | ||
| 1005 | deb_info("save original TOPs\n"); | ||
| 1006 | |||
| 1007 | /* RF TOP */ | ||
| 1008 | ret = | ||
| 1009 | af9005_read_word_agc(state->d, | ||
| 1010 | xd_p_reg_aagc_rf_top_numerator_9_8, | ||
| 1011 | xd_p_reg_aagc_rf_top_numerator_7_0, 0, 2, | ||
| 1012 | &state->original_rf_top); | ||
| 1013 | if (ret) | ||
| 1014 | return ret; | ||
| 1015 | |||
| 1016 | /* IF TOP */ | ||
| 1017 | ret = | ||
| 1018 | af9005_read_word_agc(state->d, | ||
| 1019 | xd_p_reg_aagc_if_top_numerator_9_8, | ||
| 1020 | xd_p_reg_aagc_if_top_numerator_7_0, 0, 2, | ||
| 1021 | &state->original_if_top); | ||
| 1022 | if (ret) | ||
| 1023 | return ret; | ||
| 1024 | |||
| 1025 | /* ACI 0 IF TOP */ | ||
| 1026 | ret = | ||
| 1027 | af9005_read_word_agc(state->d, 0xA60E, 0xA60A, 4, 2, | ||
| 1028 | &state->original_aci0_if_top); | ||
| 1029 | if (ret) | ||
| 1030 | return ret; | ||
| 1031 | |||
| 1032 | /* ACI 1 IF TOP */ | ||
| 1033 | ret = | ||
| 1034 | af9005_read_word_agc(state->d, 0xA60E, 0xA60B, 6, 2, | ||
| 1035 | &state->original_aci1_if_top); | ||
| 1036 | if (ret) | ||
| 1037 | return ret; | ||
| 1038 | |||
| 1039 | /* attach tuner and init */ | ||
| 1040 | if (fe->ops.tuner_ops.release == NULL) { | ||
| 1041 | /* read tuner and board id from eeprom */ | ||
| 1042 | ret = af9005_read_eeprom(adap->dev, 0xc6, buf, 2); | ||
| 1043 | if (ret) { | ||
| 1044 | err("Impossible to read EEPROM\n"); | ||
| 1045 | return ret; | ||
| 1046 | } | ||
| 1047 | deb_info("Tuner id %d, board id %d\n", buf[0], buf[1]); | ||
| 1048 | switch (buf[0]) { | ||
| 1049 | case 2: /* MT2060 */ | ||
| 1050 | /* read if1 from eeprom */ | ||
| 1051 | ret = af9005_read_eeprom(adap->dev, 0xc8, buf, 2); | ||
| 1052 | if (ret) { | ||
| 1053 | err("Impossible to read EEPROM\n"); | ||
| 1054 | return ret; | ||
| 1055 | } | ||
| 1056 | if1 = (u16) (buf[0] << 8) + buf[1]; | ||
| 1057 | if (dvb_attach(mt2060_attach, fe, &adap->dev->i2c_adap, | ||
| 1058 | &af9005_mt2060_config, if1) == NULL) { | ||
| 1059 | deb_info("MT2060 attach failed\n"); | ||
| 1060 | return -ENODEV; | ||
| 1061 | } | ||
| 1062 | break; | ||
| 1063 | case 3: /* QT1010 */ | ||
| 1064 | case 9: /* QT1010B */ | ||
| 1065 | if (dvb_attach(qt1010_attach, fe, &adap->dev->i2c_adap, | ||
| 1066 | &af9005_qt1010_config) ==NULL) { | ||
| 1067 | deb_info("QT1010 attach failed\n"); | ||
| 1068 | return -ENODEV; | ||
| 1069 | } | ||
| 1070 | break; | ||
| 1071 | default: | ||
| 1072 | err("Unsupported tuner type %d", buf[0]); | ||
| 1073 | return -ENODEV; | ||
| 1074 | } | ||
| 1075 | ret = fe->ops.tuner_ops.init(fe); | ||
| 1076 | if (ret) | ||
| 1077 | return ret; | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | deb_info("profit!\n"); | ||
| 1081 | return 0; | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | static int af9005_fe_sleep(struct dvb_frontend *fe) | ||
| 1085 | { | ||
| 1086 | return af9005_fe_power(fe, 0); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | static int af9005_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) | ||
| 1090 | { | ||
| 1091 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 1092 | |||
| 1093 | if (acquire) { | ||
| 1094 | state->opened++; | ||
| 1095 | } else { | ||
| 1096 | |||
| 1097 | state->opened--; | ||
| 1098 | if (!state->opened) | ||
| 1099 | af9005_led_control(state->d, 0); | ||
| 1100 | } | ||
| 1101 | return 0; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | static int af9005_fe_set_frontend(struct dvb_frontend *fe, | ||
| 1105 | struct dvb_frontend_parameters *fep) | ||
| 1106 | { | ||
| 1107 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 1108 | int ret; | ||
| 1109 | u8 temp, temp0, temp1, temp2; | ||
| 1110 | |||
| 1111 | deb_info("af9005_fe_set_frontend freq %d bw %d\n", fep->frequency, | ||
| 1112 | fep->u.ofdm.bandwidth); | ||
| 1113 | if (fe->ops.tuner_ops.release == NULL) { | ||
| 1114 | err("Tuner not attached"); | ||
| 1115 | return -ENODEV; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | deb_info("turn off led\n"); | ||
| 1119 | /* not in the log */ | ||
| 1120 | ret = af9005_led_control(state->d, 0); | ||
| 1121 | if (ret) | ||
| 1122 | return ret; | ||
| 1123 | /* not sure about the bits */ | ||
| 1124 | ret = af9005_write_register_bits(state->d, XD_MP2IF_MISC, 2, 1, 0); | ||
| 1125 | if (ret) | ||
| 1126 | return ret; | ||
| 1127 | |||
| 1128 | /* set FCW to default value */ | ||
| 1129 | deb_info("set FCW to default value\n"); | ||
| 1130 | temp0 = (u8) (state->original_fcw & 0x000000ff); | ||
| 1131 | temp1 = (u8) ((state->original_fcw & 0x0000ff00) >> 8); | ||
| 1132 | temp2 = (u8) ((state->original_fcw & 0x00ff0000) >> 16); | ||
| 1133 | ret = af9005_write_ofdm_register(state->d, 0xae1a, temp0); | ||
| 1134 | if (ret) | ||
| 1135 | return ret; | ||
| 1136 | ret = af9005_write_ofdm_register(state->d, 0xae19, temp1); | ||
| 1137 | if (ret) | ||
| 1138 | return ret; | ||
| 1139 | ret = af9005_write_ofdm_register(state->d, 0xae18, temp2); | ||
| 1140 | if (ret) | ||
| 1141 | return ret; | ||
| 1142 | |||
| 1143 | /* restore original TOPs */ | ||
| 1144 | deb_info("restore original TOPs\n"); | ||
| 1145 | ret = | ||
| 1146 | af9005_write_word_agc(state->d, | ||
| 1147 | xd_p_reg_aagc_rf_top_numerator_9_8, | ||
| 1148 | xd_p_reg_aagc_rf_top_numerator_7_0, 0, 2, | ||
| 1149 | state->original_rf_top); | ||
| 1150 | if (ret) | ||
| 1151 | return ret; | ||
| 1152 | ret = | ||
| 1153 | af9005_write_word_agc(state->d, | ||
| 1154 | xd_p_reg_aagc_if_top_numerator_9_8, | ||
| 1155 | xd_p_reg_aagc_if_top_numerator_7_0, 0, 2, | ||
| 1156 | state->original_if_top); | ||
| 1157 | if (ret) | ||
| 1158 | return ret; | ||
| 1159 | ret = | ||
| 1160 | af9005_write_word_agc(state->d, 0xA60E, 0xA60A, 4, 2, | ||
| 1161 | state->original_aci0_if_top); | ||
| 1162 | if (ret) | ||
| 1163 | return ret; | ||
| 1164 | ret = | ||
| 1165 | af9005_write_word_agc(state->d, 0xA60E, 0xA60B, 6, 2, | ||
| 1166 | state->original_aci1_if_top); | ||
| 1167 | if (ret) | ||
| 1168 | return ret; | ||
| 1169 | |||
| 1170 | /* select bandwidth */ | ||
| 1171 | deb_info("select bandwidth"); | ||
| 1172 | ret = af9005_fe_select_bw(state->d, fep->u.ofdm.bandwidth); | ||
| 1173 | if (ret) | ||
| 1174 | return ret; | ||
| 1175 | ret = af9005_fe_program_cfoe(state->d, fep->u.ofdm.bandwidth); | ||
| 1176 | if (ret) | ||
| 1177 | return ret; | ||
| 1178 | |||
| 1179 | /* clear easy mode flag */ | ||
| 1180 | deb_info("clear easy mode flag\n"); | ||
| 1181 | ret = af9005_write_ofdm_register(state->d, 0xaefd, 0); | ||
| 1182 | if (ret) | ||
| 1183 | return ret; | ||
| 1184 | |||
| 1185 | /* set unplug threshold to original value */ | ||
| 1186 | deb_info("set unplug threshold to original value\n"); | ||
| 1187 | ret = | ||
| 1188 | af9005_write_ofdm_register(state->d, xd_p_reg_unplug_th, | ||
| 1189 | state->original_if_unplug_th); | ||
| 1190 | if (ret) | ||
| 1191 | return ret; | ||
| 1192 | /* set tuner */ | ||
| 1193 | deb_info("set tuner\n"); | ||
| 1194 | ret = fe->ops.tuner_ops.set_params(fe, fep); | ||
| 1195 | if (ret) | ||
| 1196 | return ret; | ||
| 1197 | |||
| 1198 | /* trigger ofsm */ | ||
| 1199 | deb_info("trigger ofsm\n"); | ||
| 1200 | temp = 0; | ||
| 1201 | ret = af9005_write_tuner_registers(state->d, 0xffff, &temp, 1); | ||
| 1202 | if (ret) | ||
| 1203 | return ret; | ||
| 1204 | |||
| 1205 | /* clear retrain and freeze flag */ | ||
| 1206 | deb_info("clear retrain and freeze flag\n"); | ||
| 1207 | ret = | ||
| 1208 | af9005_write_register_bits(state->d, | ||
| 1209 | xd_p_reg_api_retrain_request, | ||
| 1210 | reg_api_retrain_request_pos, 2, 0); | ||
| 1211 | if (ret) | ||
| 1212 | return ret; | ||
| 1213 | |||
| 1214 | /* reset pre viterbi and post viterbi registers and statistics */ | ||
| 1215 | af9005_reset_pre_viterbi(fe); | ||
| 1216 | af9005_reset_post_viterbi(fe); | ||
| 1217 | state->pre_vit_error_count = 0; | ||
| 1218 | state->pre_vit_bit_count = 0; | ||
| 1219 | state->ber = 0; | ||
| 1220 | state->post_vit_error_count = 0; | ||
| 1221 | /* state->unc = 0; commented out since it should be ever increasing */ | ||
| 1222 | state->abort_count = 0; | ||
| 1223 | |||
| 1224 | state->next_status_check = jiffies; | ||
| 1225 | state->strong = -1; | ||
| 1226 | |||
| 1227 | return 0; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | static int af9005_fe_get_frontend(struct dvb_frontend *fe, | ||
| 1231 | struct dvb_frontend_parameters *fep) | ||
| 1232 | { | ||
| 1233 | struct af9005_fe_state *state = fe->demodulator_priv; | ||
| 1234 | int ret; | ||
| 1235 | u8 temp; | ||
| 1236 | |||
| 1237 | /* mode */ | ||
| 1238 | ret = | ||
| 1239 | af9005_read_register_bits(state->d, xd_g_reg_tpsd_const, | ||
| 1240 | reg_tpsd_const_pos, reg_tpsd_const_len, | ||
| 1241 | &temp); | ||
| 1242 | if (ret) | ||
| 1243 | return ret; | ||
| 1244 | deb_info("===== fe_get_frontend ==============\n"); | ||
| 1245 | deb_info("CONSTELLATION "); | ||
| 1246 | switch (temp) { | ||
| 1247 | case 0: | ||
| 1248 | fep->u.ofdm.constellation = QPSK; | ||
| 1249 | deb_info("QPSK\n"); | ||
| 1250 | break; | ||
| 1251 | case 1: | ||
| 1252 | fep->u.ofdm.constellation = QAM_16; | ||
| 1253 | deb_info("QAM_16\n"); | ||
| 1254 | break; | ||
| 1255 | case 2: | ||
| 1256 | fep->u.ofdm.constellation = QAM_64; | ||
| 1257 | deb_info("QAM_64\n"); | ||
| 1258 | break; | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | /* tps hierarchy and alpha value */ | ||
| 1262 | ret = | ||
| 1263 | af9005_read_register_bits(state->d, xd_g_reg_tpsd_hier, | ||
| 1264 | reg_tpsd_hier_pos, reg_tpsd_hier_len, | ||
| 1265 | &temp); | ||
| 1266 | if (ret) | ||
| 1267 | return ret; | ||
| 1268 | deb_info("HIERARCHY "); | ||
| 1269 | switch (temp) { | ||
| 1270 | case 0: | ||
| 1271 | fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; | ||
| 1272 | deb_info("NONE\n"); | ||
| 1273 | break; | ||
| 1274 | case 1: | ||
| 1275 | fep->u.ofdm.hierarchy_information = HIERARCHY_1; | ||
| 1276 | deb_info("1\n"); | ||
| 1277 | break; | ||
| 1278 | case 2: | ||
| 1279 | fep->u.ofdm.hierarchy_information = HIERARCHY_2; | ||
| 1280 | deb_info("2\n"); | ||
| 1281 | break; | ||
| 1282 | case 3: | ||
| 1283 | fep->u.ofdm.hierarchy_information = HIERARCHY_4; | ||
| 1284 | deb_info("4\n"); | ||
| 1285 | break; | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | /* high/low priority */ | ||
| 1289 | ret = | ||
| 1290 | af9005_read_register_bits(state->d, xd_g_reg_dec_pri, | ||
| 1291 | reg_dec_pri_pos, reg_dec_pri_len, &temp); | ||
| 1292 | if (ret) | ||
| 1293 | return ret; | ||
| 1294 | /* if temp is set = high priority */ | ||
| 1295 | deb_info("PRIORITY %s\n", temp ? "high" : "low"); | ||
| 1296 | |||
| 1297 | /* high coderate */ | ||
| 1298 | ret = | ||
| 1299 | af9005_read_register_bits(state->d, xd_g_reg_tpsd_hpcr, | ||
| 1300 | reg_tpsd_hpcr_pos, reg_tpsd_hpcr_len, | ||
| 1301 | &temp); | ||
| 1302 | if (ret) | ||
| 1303 | return ret; | ||
| 1304 | deb_info("CODERATE HP "); | ||
| 1305 | switch (temp) { | ||
| 1306 | case 0: | ||
| 1307 | fep->u.ofdm.code_rate_HP = FEC_1_2; | ||
| 1308 | deb_info("FEC_1_2\n"); | ||
| 1309 | break; | ||
| 1310 | case 1: | ||
| 1311 | fep->u.ofdm.code_rate_HP = FEC_2_3; | ||
| 1312 | deb_info("FEC_2_3\n"); | ||
| 1313 | break; | ||
| 1314 | case 2: | ||
| 1315 | fep->u.ofdm.code_rate_HP = FEC_3_4; | ||
| 1316 | deb_info("FEC_3_4\n"); | ||
| 1317 | break; | ||
| 1318 | case 3: | ||
| 1319 | fep->u.ofdm.code_rate_HP = FEC_5_6; | ||
| 1320 | deb_info("FEC_5_6\n"); | ||
| 1321 | break; | ||
| 1322 | case 4: | ||
| 1323 | fep->u.ofdm.code_rate_HP = FEC_7_8; | ||
| 1324 | deb_info("FEC_7_8\n"); | ||
| 1325 | break; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | /* low coderate */ | ||
| 1329 | ret = | ||
| 1330 | af9005_read_register_bits(state->d, xd_g_reg_tpsd_lpcr, | ||
| 1331 | reg_tpsd_lpcr_pos, reg_tpsd_lpcr_len, | ||
| 1332 | &temp); | ||
| 1333 | if (ret) | ||
| 1334 | return ret; | ||
| 1335 | deb_info("CODERATE LP "); | ||
| 1336 | switch (temp) { | ||
| 1337 | case 0: | ||
| 1338 | fep->u.ofdm.code_rate_LP = FEC_1_2; | ||
| 1339 | deb_info("FEC_1_2\n"); | ||
| 1340 | break; | ||
| 1341 | case 1: | ||
| 1342 | fep->u.ofdm.code_rate_LP = FEC_2_3; | ||
| 1343 | deb_info("FEC_2_3\n"); | ||
| 1344 | break; | ||
| 1345 | case 2: | ||
| 1346 | fep->u.ofdm.code_rate_LP = FEC_3_4; | ||
| 1347 | deb_info("FEC_3_4\n"); | ||
| 1348 | break; | ||
| 1349 | case 3: | ||
| 1350 | fep->u.ofdm.code_rate_LP = FEC_5_6; | ||
| 1351 | deb_info("FEC_5_6\n"); | ||
| 1352 | break; | ||
| 1353 | case 4: | ||
| 1354 | fep->u.ofdm.code_rate_LP = FEC_7_8; | ||
| 1355 | deb_info("FEC_7_8\n"); | ||
| 1356 | break; | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | /* guard interval */ | ||
| 1360 | ret = | ||
| 1361 | af9005_read_register_bits(state->d, xd_g_reg_tpsd_gi, | ||
| 1362 | reg_tpsd_gi_pos, reg_tpsd_gi_len, &temp); | ||
| 1363 | if (ret) | ||
| 1364 | return ret; | ||
| 1365 | deb_info("GUARD INTERVAL "); | ||
| 1366 | switch (temp) { | ||
| 1367 | case 0: | ||
| 1368 | fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; | ||
| 1369 | deb_info("1_32\n"); | ||
| 1370 | break; | ||
| 1371 | case 1: | ||
| 1372 | fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; | ||
| 1373 | deb_info("1_16\n"); | ||
| 1374 | break; | ||
| 1375 | case 2: | ||
| 1376 | fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; | ||
| 1377 | deb_info("1_8\n"); | ||
| 1378 | break; | ||
| 1379 | case 3: | ||
| 1380 | fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; | ||
| 1381 | deb_info("1_4\n"); | ||
| 1382 | break; | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | /* fft */ | ||
| 1386 | ret = | ||
| 1387 | af9005_read_register_bits(state->d, xd_g_reg_tpsd_txmod, | ||
| 1388 | reg_tpsd_txmod_pos, reg_tpsd_txmod_len, | ||
| 1389 | &temp); | ||
| 1390 | if (ret) | ||
| 1391 | return ret; | ||
| 1392 | deb_info("TRANSMISSION MODE "); | ||
| 1393 | switch (temp) { | ||
| 1394 | case 0: | ||
| 1395 | fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; | ||
| 1396 | deb_info("2K\n"); | ||
| 1397 | break; | ||
| 1398 | case 1: | ||
| 1399 | fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; | ||
| 1400 | deb_info("8K\n"); | ||
| 1401 | break; | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | /* bandwidth */ | ||
| 1405 | ret = | ||
| 1406 | af9005_read_register_bits(state->d, xd_g_reg_bw, reg_bw_pos, | ||
| 1407 | reg_bw_len, &temp); | ||
| 1408 | deb_info("BANDWIDTH "); | ||
| 1409 | switch (temp) { | ||
| 1410 | case 0: | ||
| 1411 | fep->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
| 1412 | deb_info("6\n"); | ||
| 1413 | break; | ||
| 1414 | case 1: | ||
| 1415 | fep->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; | ||
| 1416 | deb_info("7\n"); | ||
| 1417 | break; | ||
| 1418 | case 2: | ||
| 1419 | fep->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | ||
| 1420 | deb_info("8\n"); | ||
| 1421 | break; | ||
| 1422 | } | ||
| 1423 | return 0; | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | static void af9005_fe_release(struct dvb_frontend *fe) | ||
| 1427 | { | ||
| 1428 | struct af9005_fe_state *state = | ||
| 1429 | (struct af9005_fe_state *)fe->demodulator_priv; | ||
| 1430 | kfree(state); | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | static struct dvb_frontend_ops af9005_fe_ops; | ||
| 1434 | |||
| 1435 | struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d) | ||
| 1436 | { | ||
| 1437 | struct af9005_fe_state *state = NULL; | ||
| 1438 | |||
| 1439 | /* allocate memory for the internal state */ | ||
| 1440 | state = kzalloc(sizeof(struct af9005_fe_state), GFP_KERNEL); | ||
| 1441 | if (state == NULL) | ||
| 1442 | goto error; | ||
| 1443 | |||
| 1444 | deb_info("attaching frontend af9005\n"); | ||
| 1445 | |||
| 1446 | state->d = d; | ||
| 1447 | state->opened = 0; | ||
| 1448 | |||
| 1449 | memcpy(&state->frontend.ops, &af9005_fe_ops, | ||
| 1450 | sizeof(struct dvb_frontend_ops)); | ||
| 1451 | state->frontend.demodulator_priv = state; | ||
| 1452 | |||
| 1453 | return &state->frontend; | ||
| 1454 | error: | ||
| 1455 | return NULL; | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | static struct dvb_frontend_ops af9005_fe_ops = { | ||
| 1459 | .info = { | ||
| 1460 | .name = "AF9005 USB DVB-T", | ||
| 1461 | .type = FE_OFDM, | ||
| 1462 | .frequency_min = 44250000, | ||
| 1463 | .frequency_max = 867250000, | ||
| 1464 | .frequency_stepsize = 250000, | ||
| 1465 | .caps = FE_CAN_INVERSION_AUTO | | ||
| 1466 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 1467 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
| 1468 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | | ||
| 1469 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
| 1470 | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | | ||
| 1471 | FE_CAN_HIERARCHY_AUTO, | ||
| 1472 | }, | ||
| 1473 | |||
| 1474 | .release = af9005_fe_release, | ||
| 1475 | |||
| 1476 | .init = af9005_fe_init, | ||
| 1477 | .sleep = af9005_fe_sleep, | ||
| 1478 | .ts_bus_ctrl = af9005_ts_bus_ctrl, | ||
| 1479 | |||
| 1480 | .set_frontend = af9005_fe_set_frontend, | ||
| 1481 | .get_frontend = af9005_fe_get_frontend, | ||
| 1482 | |||
| 1483 | .read_status = af9005_fe_read_status, | ||
| 1484 | .read_ber = af9005_fe_read_ber, | ||
| 1485 | .read_signal_strength = af9005_fe_read_signal_strength, | ||
| 1486 | .read_snr = af9005_fe_read_snr, | ||
| 1487 | .read_ucblocks = af9005_fe_read_unc_blocks, | ||
| 1488 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c new file mode 100644 index 00000000000..c3bc64ed405 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9005-remote.c | |||
| @@ -0,0 +1,157 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the Afatech 9005 | ||
| 2 | * USB1.1 DVB-T receiver. | ||
| 3 | * | ||
| 4 | * Standard remote decode function | ||
| 5 | * | ||
| 6 | * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org) | ||
| 7 | * | ||
| 8 | * Thanks to Afatech who kindly provided information. | ||
| 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 | * see Documentation/dvb/REDME.dvb-usb for more information | ||
| 25 | */ | ||
| 26 | #include "af9005.h" | ||
| 27 | /* debug */ | ||
| 28 | static int dvb_usb_af9005_remote_debug; | ||
| 29 | module_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644); | ||
| 30 | MODULE_PARM_DESC(debug, | ||
| 31 | "enable (1) or disable (0) debug messages." | ||
| 32 | DVB_USB_DEBUG_STATUS); | ||
| 33 | |||
| 34 | #define deb_decode(args...) dprintk(dvb_usb_af9005_remote_debug,0x01,args) | ||
| 35 | |||
| 36 | struct rc_map_table rc_map_af9005_table[] = { | ||
| 37 | |||
| 38 | {0x01b7, KEY_POWER}, | ||
| 39 | {0x01a7, KEY_VOLUMEUP}, | ||
| 40 | {0x0187, KEY_CHANNELUP}, | ||
| 41 | {0x017f, KEY_MUTE}, | ||
| 42 | {0x01bf, KEY_VOLUMEDOWN}, | ||
| 43 | {0x013f, KEY_CHANNELDOWN}, | ||
| 44 | {0x01df, KEY_1}, | ||
| 45 | {0x015f, KEY_2}, | ||
| 46 | {0x019f, KEY_3}, | ||
| 47 | {0x011f, KEY_4}, | ||
| 48 | {0x01ef, KEY_5}, | ||
| 49 | {0x016f, KEY_6}, | ||
| 50 | {0x01af, KEY_7}, | ||
| 51 | {0x0127, KEY_8}, | ||
| 52 | {0x0107, KEY_9}, | ||
| 53 | {0x01cf, KEY_ZOOM}, | ||
| 54 | {0x014f, KEY_0}, | ||
| 55 | {0x018f, KEY_GOTO}, /* marked jump on the remote */ | ||
| 56 | |||
| 57 | {0x00bd, KEY_POWER}, | ||
| 58 | {0x007d, KEY_VOLUMEUP}, | ||
| 59 | {0x00fd, KEY_CHANNELUP}, | ||
| 60 | {0x009d, KEY_MUTE}, | ||
| 61 | {0x005d, KEY_VOLUMEDOWN}, | ||
| 62 | {0x00dd, KEY_CHANNELDOWN}, | ||
| 63 | {0x00ad, KEY_1}, | ||
| 64 | {0x006d, KEY_2}, | ||
| 65 | {0x00ed, KEY_3}, | ||
| 66 | {0x008d, KEY_4}, | ||
| 67 | {0x004d, KEY_5}, | ||
| 68 | {0x00cd, KEY_6}, | ||
| 69 | {0x00b5, KEY_7}, | ||
| 70 | {0x0075, KEY_8}, | ||
| 71 | {0x00f5, KEY_9}, | ||
| 72 | {0x0095, KEY_ZOOM}, | ||
| 73 | {0x0055, KEY_0}, | ||
| 74 | {0x00d5, KEY_GOTO}, /* marked jump on the remote */ | ||
| 75 | }; | ||
| 76 | |||
| 77 | int rc_map_af9005_table_size = ARRAY_SIZE(rc_map_af9005_table); | ||
| 78 | |||
| 79 | static int repeatable_keys[] = { | ||
| 80 | KEY_VOLUMEUP, | ||
| 81 | KEY_VOLUMEDOWN, | ||
| 82 | KEY_CHANNELUP, | ||
| 83 | KEY_CHANNELDOWN | ||
| 84 | }; | ||
| 85 | |||
| 86 | int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event, | ||
| 87 | int *state) | ||
| 88 | { | ||
| 89 | u16 mark, space; | ||
| 90 | u32 result; | ||
| 91 | u8 cust, dat, invdat; | ||
| 92 | int i; | ||
| 93 | |||
| 94 | if (len >= 6) { | ||
| 95 | mark = (u16) (data[0] << 8) + data[1]; | ||
| 96 | space = (u16) (data[2] << 8) + data[3]; | ||
| 97 | if (space * 3 < mark) { | ||
| 98 | for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) { | ||
| 99 | if (d->last_event == repeatable_keys[i]) { | ||
| 100 | *state = REMOTE_KEY_REPEAT; | ||
| 101 | *event = d->last_event; | ||
| 102 | deb_decode("repeat key, event %x\n", | ||
| 103 | *event); | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | } | ||
| 107 | deb_decode("repeated key ignored (non repeatable)\n"); | ||
| 108 | return 0; | ||
| 109 | } else if (len >= 33 * 4) { /*32 bits + start code */ | ||
| 110 | result = 0; | ||
| 111 | for (i = 4; i < 4 + 32 * 4; i += 4) { | ||
| 112 | result <<= 1; | ||
| 113 | mark = (u16) (data[i] << 8) + data[i + 1]; | ||
| 114 | mark >>= 1; | ||
| 115 | space = (u16) (data[i + 2] << 8) + data[i + 3]; | ||
| 116 | space >>= 1; | ||
| 117 | if (mark * 2 > space) | ||
| 118 | result += 1; | ||
| 119 | } | ||
| 120 | deb_decode("key pressed, raw value %x\n", result); | ||
| 121 | if ((result & 0xff000000) != 0xfe000000) { | ||
| 122 | deb_decode | ||
| 123 | ("doesn't start with 0xfe, ignored\n"); | ||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | cust = (result >> 16) & 0xff; | ||
| 127 | dat = (result >> 8) & 0xff; | ||
| 128 | invdat = (~result) & 0xff; | ||
| 129 | if (dat != invdat) { | ||
| 130 | deb_decode("code != inverted code\n"); | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | for (i = 0; i < rc_map_af9005_table_size; i++) { | ||
| 134 | if (rc5_custom(&rc_map_af9005_table[i]) == cust | ||
| 135 | && rc5_data(&rc_map_af9005_table[i]) == dat) { | ||
| 136 | *event = rc_map_af9005_table[i].keycode; | ||
| 137 | *state = REMOTE_KEY_PRESSED; | ||
| 138 | deb_decode | ||
| 139 | ("key pressed, event %x\n", *event); | ||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | deb_decode("not found in table\n"); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | EXPORT_SYMBOL(rc_map_af9005_table); | ||
| 150 | EXPORT_SYMBOL(rc_map_af9005_table_size); | ||
| 151 | EXPORT_SYMBOL(af9005_rc_decode); | ||
| 152 | |||
| 153 | MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>"); | ||
| 154 | MODULE_DESCRIPTION | ||
| 155 | ("Standard remote control decoder for Afatech 9005 DVB-T USB1.1 stick"); | ||
| 156 | MODULE_VERSION("1.0"); | ||
| 157 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/af9005-script.h b/drivers/media/dvb/dvb-usb/af9005-script.h new file mode 100644 index 00000000000..4d69045426d --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9005-script.h | |||
| @@ -0,0 +1,203 @@ | |||
| 1 | /* | ||
| 2 | File automatically generated by createinit.py using data | ||
| 3 | extracted from AF05BDA.sys (windows driver): | ||
| 4 | |||
| 5 | dd if=AF05BDA.sys of=initsequence bs=1 skip=88316 count=1110 | ||
| 6 | python createinit.py > af9005-script.h | ||
| 7 | |||
| 8 | */ | ||
| 9 | |||
| 10 | typedef struct { | ||
| 11 | u16 reg; | ||
| 12 | u8 pos; | ||
| 13 | u8 len; | ||
| 14 | u8 val; | ||
| 15 | } RegDesc; | ||
| 16 | |||
| 17 | static RegDesc script[] = { | ||
| 18 | {0xa180, 0x0, 0x8, 0xa}, | ||
| 19 | {0xa181, 0x0, 0x8, 0xd7}, | ||
| 20 | {0xa182, 0x0, 0x8, 0xa3}, | ||
| 21 | {0xa0a0, 0x0, 0x8, 0x0}, | ||
| 22 | {0xa0a1, 0x0, 0x5, 0x0}, | ||
| 23 | {0xa0a1, 0x5, 0x1, 0x1}, | ||
| 24 | {0xa0c0, 0x0, 0x4, 0x1}, | ||
| 25 | {0xa20e, 0x4, 0x4, 0xa}, | ||
| 26 | {0xa20f, 0x0, 0x8, 0x40}, | ||
| 27 | {0xa210, 0x0, 0x8, 0x8}, | ||
| 28 | {0xa32a, 0x0, 0x4, 0xa}, | ||
| 29 | {0xa32c, 0x0, 0x8, 0x20}, | ||
| 30 | {0xa32b, 0x0, 0x8, 0x15}, | ||
| 31 | {0xa1a0, 0x1, 0x1, 0x1}, | ||
| 32 | {0xa000, 0x0, 0x1, 0x1}, | ||
| 33 | {0xa000, 0x1, 0x1, 0x0}, | ||
| 34 | {0xa001, 0x1, 0x1, 0x1}, | ||
| 35 | {0xa001, 0x0, 0x1, 0x0}, | ||
| 36 | {0xa001, 0x5, 0x1, 0x0}, | ||
| 37 | {0xa00e, 0x0, 0x5, 0x10}, | ||
| 38 | {0xa00f, 0x0, 0x3, 0x4}, | ||
| 39 | {0xa00f, 0x3, 0x3, 0x5}, | ||
| 40 | {0xa010, 0x0, 0x3, 0x4}, | ||
| 41 | {0xa010, 0x3, 0x3, 0x5}, | ||
| 42 | {0xa016, 0x4, 0x4, 0x3}, | ||
| 43 | {0xa01f, 0x0, 0x6, 0xa}, | ||
| 44 | {0xa020, 0x0, 0x6, 0xa}, | ||
| 45 | {0xa2bc, 0x0, 0x1, 0x1}, | ||
| 46 | {0xa2bc, 0x5, 0x1, 0x1}, | ||
| 47 | {0xa015, 0x0, 0x8, 0x50}, | ||
| 48 | {0xa016, 0x0, 0x1, 0x0}, | ||
| 49 | {0xa02a, 0x0, 0x8, 0x50}, | ||
| 50 | {0xa029, 0x0, 0x8, 0x4b}, | ||
| 51 | {0xa614, 0x0, 0x8, 0x46}, | ||
| 52 | {0xa002, 0x0, 0x5, 0x19}, | ||
| 53 | {0xa003, 0x0, 0x5, 0x1a}, | ||
| 54 | {0xa004, 0x0, 0x5, 0x19}, | ||
| 55 | {0xa005, 0x0, 0x5, 0x1a}, | ||
| 56 | {0xa008, 0x0, 0x8, 0x69}, | ||
| 57 | {0xa009, 0x0, 0x2, 0x2}, | ||
| 58 | {0xae1b, 0x0, 0x8, 0x69}, | ||
| 59 | {0xae1c, 0x0, 0x8, 0x2}, | ||
| 60 | {0xae1d, 0x0, 0x8, 0x2a}, | ||
| 61 | {0xa022, 0x0, 0x8, 0xaa}, | ||
| 62 | {0xa006, 0x0, 0x8, 0xc8}, | ||
| 63 | {0xa007, 0x0, 0x2, 0x0}, | ||
| 64 | {0xa00c, 0x0, 0x8, 0xba}, | ||
| 65 | {0xa00d, 0x0, 0x2, 0x2}, | ||
| 66 | {0xa608, 0x0, 0x8, 0xba}, | ||
| 67 | {0xa60e, 0x0, 0x2, 0x2}, | ||
| 68 | {0xa609, 0x0, 0x8, 0x80}, | ||
| 69 | {0xa60e, 0x2, 0x2, 0x3}, | ||
| 70 | {0xa00a, 0x0, 0x8, 0xb6}, | ||
| 71 | {0xa00b, 0x0, 0x2, 0x0}, | ||
| 72 | {0xa011, 0x0, 0x8, 0xb9}, | ||
| 73 | {0xa012, 0x0, 0x2, 0x0}, | ||
| 74 | {0xa013, 0x0, 0x8, 0xbd}, | ||
| 75 | {0xa014, 0x0, 0x2, 0x2}, | ||
| 76 | {0xa366, 0x0, 0x1, 0x1}, | ||
| 77 | {0xa2bc, 0x3, 0x1, 0x0}, | ||
| 78 | {0xa2bd, 0x0, 0x8, 0xa}, | ||
| 79 | {0xa2be, 0x0, 0x8, 0x14}, | ||
| 80 | {0xa2bf, 0x0, 0x8, 0x8}, | ||
| 81 | {0xa60a, 0x0, 0x8, 0xbd}, | ||
| 82 | {0xa60e, 0x4, 0x2, 0x2}, | ||
| 83 | {0xa60b, 0x0, 0x8, 0x86}, | ||
| 84 | {0xa60e, 0x6, 0x2, 0x3}, | ||
| 85 | {0xa001, 0x2, 0x2, 0x1}, | ||
| 86 | {0xa1c7, 0x0, 0x8, 0xf5}, | ||
| 87 | {0xa03d, 0x0, 0x8, 0xb1}, | ||
| 88 | {0xa616, 0x0, 0x8, 0xff}, | ||
| 89 | {0xa617, 0x0, 0x8, 0xad}, | ||
| 90 | {0xa618, 0x0, 0x8, 0xad}, | ||
| 91 | {0xa61e, 0x3, 0x1, 0x1}, | ||
| 92 | {0xae1a, 0x0, 0x8, 0x0}, | ||
| 93 | {0xae19, 0x0, 0x8, 0xc8}, | ||
| 94 | {0xae18, 0x0, 0x8, 0x61}, | ||
| 95 | {0xa140, 0x0, 0x8, 0x0}, | ||
| 96 | {0xa141, 0x0, 0x8, 0xc8}, | ||
| 97 | {0xa142, 0x0, 0x7, 0x61}, | ||
| 98 | {0xa023, 0x0, 0x8, 0xff}, | ||
| 99 | {0xa021, 0x0, 0x8, 0xad}, | ||
| 100 | {0xa026, 0x0, 0x1, 0x0}, | ||
| 101 | {0xa024, 0x0, 0x8, 0xff}, | ||
| 102 | {0xa025, 0x0, 0x8, 0xff}, | ||
| 103 | {0xa1c8, 0x0, 0x8, 0xf}, | ||
| 104 | {0xa2bc, 0x1, 0x1, 0x0}, | ||
| 105 | {0xa60c, 0x0, 0x4, 0x5}, | ||
| 106 | {0xa60c, 0x4, 0x4, 0x6}, | ||
| 107 | {0xa60d, 0x0, 0x8, 0xa}, | ||
| 108 | {0xa371, 0x0, 0x1, 0x1}, | ||
| 109 | {0xa366, 0x1, 0x3, 0x7}, | ||
| 110 | {0xa338, 0x0, 0x8, 0x10}, | ||
| 111 | {0xa339, 0x0, 0x6, 0x7}, | ||
| 112 | {0xa33a, 0x0, 0x6, 0x1f}, | ||
| 113 | {0xa33b, 0x0, 0x8, 0xf6}, | ||
| 114 | {0xa33c, 0x3, 0x5, 0x4}, | ||
| 115 | {0xa33d, 0x4, 0x4, 0x0}, | ||
| 116 | {0xa33d, 0x1, 0x1, 0x1}, | ||
| 117 | {0xa33d, 0x2, 0x1, 0x1}, | ||
| 118 | {0xa33d, 0x3, 0x1, 0x1}, | ||
| 119 | {0xa16d, 0x0, 0x4, 0xf}, | ||
| 120 | {0xa161, 0x0, 0x5, 0x5}, | ||
| 121 | {0xa162, 0x0, 0x4, 0x5}, | ||
| 122 | {0xa165, 0x0, 0x8, 0xff}, | ||
| 123 | {0xa166, 0x0, 0x8, 0x9c}, | ||
| 124 | {0xa2c3, 0x0, 0x4, 0x5}, | ||
| 125 | {0xa61a, 0x0, 0x6, 0xf}, | ||
| 126 | {0xb200, 0x0, 0x8, 0xa1}, | ||
| 127 | {0xb201, 0x0, 0x8, 0x7}, | ||
| 128 | {0xa093, 0x0, 0x1, 0x0}, | ||
| 129 | {0xa093, 0x1, 0x5, 0xf}, | ||
| 130 | {0xa094, 0x0, 0x8, 0xff}, | ||
| 131 | {0xa095, 0x0, 0x8, 0xf}, | ||
| 132 | {0xa080, 0x2, 0x5, 0x3}, | ||
| 133 | {0xa081, 0x0, 0x4, 0x0}, | ||
| 134 | {0xa081, 0x4, 0x4, 0x9}, | ||
| 135 | {0xa082, 0x0, 0x5, 0x1f}, | ||
| 136 | {0xa08d, 0x0, 0x8, 0x1}, | ||
| 137 | {0xa083, 0x0, 0x8, 0x32}, | ||
| 138 | {0xa084, 0x0, 0x1, 0x0}, | ||
| 139 | {0xa08e, 0x0, 0x8, 0x3}, | ||
| 140 | {0xa085, 0x0, 0x8, 0x32}, | ||
| 141 | {0xa086, 0x0, 0x3, 0x0}, | ||
| 142 | {0xa087, 0x0, 0x8, 0x6e}, | ||
| 143 | {0xa088, 0x0, 0x5, 0x15}, | ||
| 144 | {0xa089, 0x0, 0x8, 0x0}, | ||
| 145 | {0xa08a, 0x0, 0x5, 0x19}, | ||
| 146 | {0xa08b, 0x0, 0x8, 0x92}, | ||
| 147 | {0xa08c, 0x0, 0x5, 0x1c}, | ||
| 148 | {0xa120, 0x0, 0x8, 0x0}, | ||
| 149 | {0xa121, 0x0, 0x5, 0x10}, | ||
| 150 | {0xa122, 0x0, 0x8, 0x0}, | ||
| 151 | {0xa123, 0x0, 0x7, 0x40}, | ||
| 152 | {0xa123, 0x7, 0x1, 0x0}, | ||
| 153 | {0xa124, 0x0, 0x8, 0x13}, | ||
| 154 | {0xa125, 0x0, 0x7, 0x10}, | ||
| 155 | {0xa1c0, 0x0, 0x8, 0x0}, | ||
| 156 | {0xa1c1, 0x0, 0x5, 0x4}, | ||
| 157 | {0xa1c2, 0x0, 0x8, 0x0}, | ||
| 158 | {0xa1c3, 0x0, 0x5, 0x10}, | ||
| 159 | {0xa1c3, 0x5, 0x3, 0x0}, | ||
| 160 | {0xa1c4, 0x0, 0x6, 0x0}, | ||
| 161 | {0xa1c5, 0x0, 0x7, 0x10}, | ||
| 162 | {0xa100, 0x0, 0x8, 0x0}, | ||
| 163 | {0xa101, 0x0, 0x5, 0x10}, | ||
| 164 | {0xa102, 0x0, 0x8, 0x0}, | ||
| 165 | {0xa103, 0x0, 0x7, 0x40}, | ||
| 166 | {0xa103, 0x7, 0x1, 0x0}, | ||
| 167 | {0xa104, 0x0, 0x8, 0x18}, | ||
| 168 | {0xa105, 0x0, 0x7, 0xa}, | ||
| 169 | {0xa106, 0x0, 0x8, 0x20}, | ||
| 170 | {0xa107, 0x0, 0x8, 0x40}, | ||
| 171 | {0xa108, 0x0, 0x4, 0x0}, | ||
| 172 | {0xa38c, 0x0, 0x8, 0xfc}, | ||
| 173 | {0xa38d, 0x0, 0x8, 0x0}, | ||
| 174 | {0xa38e, 0x0, 0x8, 0x7e}, | ||
| 175 | {0xa38f, 0x0, 0x8, 0x0}, | ||
| 176 | {0xa390, 0x0, 0x8, 0x2f}, | ||
| 177 | {0xa60f, 0x5, 0x1, 0x1}, | ||
| 178 | {0xa170, 0x0, 0x8, 0xdc}, | ||
| 179 | {0xa171, 0x0, 0x2, 0x0}, | ||
| 180 | {0xa2ae, 0x0, 0x1, 0x1}, | ||
| 181 | {0xa2ae, 0x1, 0x1, 0x1}, | ||
| 182 | {0xa392, 0x0, 0x1, 0x1}, | ||
| 183 | {0xa391, 0x2, 0x1, 0x0}, | ||
| 184 | {0xabc1, 0x0, 0x8, 0xff}, | ||
| 185 | {0xabc2, 0x0, 0x8, 0x0}, | ||
| 186 | {0xabc8, 0x0, 0x8, 0x8}, | ||
| 187 | {0xabca, 0x0, 0x8, 0x10}, | ||
| 188 | {0xabcb, 0x0, 0x1, 0x0}, | ||
| 189 | {0xabc3, 0x5, 0x3, 0x7}, | ||
| 190 | {0xabc0, 0x6, 0x1, 0x0}, | ||
| 191 | {0xabc0, 0x4, 0x2, 0x0}, | ||
| 192 | {0xa344, 0x4, 0x4, 0x1}, | ||
| 193 | {0xabc0, 0x7, 0x1, 0x1}, | ||
| 194 | {0xabc0, 0x2, 0x1, 0x1}, | ||
| 195 | {0xa345, 0x0, 0x8, 0x66}, | ||
| 196 | {0xa346, 0x0, 0x8, 0x66}, | ||
| 197 | {0xa347, 0x0, 0x4, 0x0}, | ||
| 198 | {0xa343, 0x0, 0x4, 0xa}, | ||
| 199 | {0xa347, 0x4, 0x4, 0x2}, | ||
| 200 | {0xa348, 0x0, 0x4, 0xc}, | ||
| 201 | {0xa348, 0x4, 0x4, 0x7}, | ||
| 202 | {0xa349, 0x0, 0x6, 0x2}, | ||
| 203 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c new file mode 100644 index 00000000000..51f6439dcfd --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9005.c | |||
| @@ -0,0 +1,1105 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the Afatech 9005 | ||
| 2 | * USB1.1 DVB-T receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org) | ||
| 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 | * see Documentation/dvb/REDME.dvb-usb for more information | ||
| 23 | */ | ||
| 24 | #include "af9005.h" | ||
| 25 | |||
| 26 | /* debug */ | ||
| 27 | int dvb_usb_af9005_debug; | ||
| 28 | module_param_named(debug, dvb_usb_af9005_debug, int, 0644); | ||
| 29 | MODULE_PARM_DESC(debug, | ||
| 30 | "set debugging level (1=info,xfer=2,rc=4,reg=8,i2c=16,fw=32 (or-able))." | ||
| 31 | DVB_USB_DEBUG_STATUS); | ||
| 32 | /* enable obnoxious led */ | ||
| 33 | int dvb_usb_af9005_led = 1; | ||
| 34 | module_param_named(led, dvb_usb_af9005_led, bool, 0644); | ||
| 35 | MODULE_PARM_DESC(led, "enable led (default: 1)."); | ||
| 36 | |||
| 37 | /* eeprom dump */ | ||
| 38 | static int dvb_usb_af9005_dump_eeprom; | ||
| 39 | module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0); | ||
| 40 | MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom."); | ||
| 41 | |||
| 42 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 43 | |||
| 44 | /* remote control decoder */ | ||
| 45 | static int (*rc_decode) (struct dvb_usb_device *d, u8 *data, int len, | ||
| 46 | u32 *event, int *state); | ||
| 47 | static void *rc_keys; | ||
| 48 | static int *rc_keys_size; | ||
| 49 | |||
| 50 | u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; | ||
| 51 | |||
| 52 | struct af9005_device_state { | ||
| 53 | u8 sequence; | ||
| 54 | int led_state; | ||
| 55 | }; | ||
| 56 | |||
| 57 | static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, | ||
| 58 | int readwrite, int type, u8 * values, int len) | ||
| 59 | { | ||
| 60 | struct af9005_device_state *st = d->priv; | ||
| 61 | u8 obuf[16] = { 0 }; | ||
| 62 | u8 ibuf[17] = { 0 }; | ||
| 63 | u8 command; | ||
| 64 | int i; | ||
| 65 | int ret; | ||
| 66 | |||
| 67 | if (len < 1) { | ||
| 68 | err("generic read/write, less than 1 byte. Makes no sense."); | ||
| 69 | return -EINVAL; | ||
| 70 | } | ||
| 71 | if (len > 8) { | ||
| 72 | err("generic read/write, more than 8 bytes. Not supported."); | ||
| 73 | return -EINVAL; | ||
| 74 | } | ||
| 75 | |||
| 76 | obuf[0] = 14; /* rest of buffer length low */ | ||
| 77 | obuf[1] = 0; /* rest of buffer length high */ | ||
| 78 | |||
| 79 | obuf[2] = AF9005_REGISTER_RW; /* register operation */ | ||
| 80 | obuf[3] = 12; /* rest of buffer length */ | ||
| 81 | |||
| 82 | obuf[4] = st->sequence++; /* sequence number */ | ||
| 83 | |||
| 84 | obuf[5] = (u8) (reg >> 8); /* register address */ | ||
| 85 | obuf[6] = (u8) (reg & 0xff); | ||
| 86 | |||
| 87 | if (type == AF9005_OFDM_REG) { | ||
| 88 | command = AF9005_CMD_OFDM_REG; | ||
| 89 | } else { | ||
| 90 | command = AF9005_CMD_TUNER; | ||
| 91 | } | ||
| 92 | |||
| 93 | if (len > 1) | ||
| 94 | command |= | ||
| 95 | AF9005_CMD_BURST | AF9005_CMD_AUTOINC | (len - 1) << 3; | ||
| 96 | command |= readwrite; | ||
| 97 | if (readwrite == AF9005_CMD_WRITE) | ||
| 98 | for (i = 0; i < len; i++) | ||
| 99 | obuf[8 + i] = values[i]; | ||
| 100 | else if (type == AF9005_TUNER_REG) | ||
| 101 | /* read command for tuner, the first byte contains the i2c address */ | ||
| 102 | obuf[8] = values[0]; | ||
| 103 | obuf[7] = command; | ||
| 104 | |||
| 105 | ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 17, 0); | ||
| 106 | if (ret) | ||
| 107 | return ret; | ||
| 108 | |||
| 109 | /* sanity check */ | ||
| 110 | if (ibuf[2] != AF9005_REGISTER_RW_ACK) { | ||
| 111 | err("generic read/write, wrong reply code."); | ||
| 112 | return -EIO; | ||
| 113 | } | ||
| 114 | if (ibuf[3] != 0x0d) { | ||
| 115 | err("generic read/write, wrong length in reply."); | ||
| 116 | return -EIO; | ||
| 117 | } | ||
| 118 | if (ibuf[4] != obuf[4]) { | ||
| 119 | err("generic read/write, wrong sequence in reply."); | ||
| 120 | return -EIO; | ||
| 121 | } | ||
| 122 | /* | ||
| 123 | Windows driver doesn't check these fields, in fact sometimes | ||
| 124 | the register in the reply is different that what has been sent | ||
| 125 | |||
| 126 | if (ibuf[5] != obuf[5] || ibuf[6] != obuf[6]) { | ||
| 127 | err("generic read/write, wrong register in reply."); | ||
| 128 | return -EIO; | ||
| 129 | } | ||
| 130 | if (ibuf[7] != command) { | ||
| 131 | err("generic read/write wrong command in reply."); | ||
| 132 | return -EIO; | ||
| 133 | } | ||
| 134 | */ | ||
| 135 | if (ibuf[16] != 0x01) { | ||
| 136 | err("generic read/write wrong status code in reply."); | ||
| 137 | return -EIO; | ||
| 138 | } | ||
| 139 | if (readwrite == AF9005_CMD_READ) | ||
| 140 | for (i = 0; i < len; i++) | ||
| 141 | values[i] = ibuf[8 + i]; | ||
| 142 | |||
| 143 | return 0; | ||
| 144 | |||
| 145 | } | ||
| 146 | |||
| 147 | int af9005_read_ofdm_register(struct dvb_usb_device *d, u16 reg, u8 * value) | ||
| 148 | { | ||
| 149 | int ret; | ||
| 150 | deb_reg("read register %x ", reg); | ||
| 151 | ret = af9005_generic_read_write(d, reg, | ||
| 152 | AF9005_CMD_READ, AF9005_OFDM_REG, | ||
| 153 | value, 1); | ||
| 154 | if (ret) | ||
| 155 | deb_reg("failed\n"); | ||
| 156 | else | ||
| 157 | deb_reg("value %x\n", *value); | ||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | int af9005_read_ofdm_registers(struct dvb_usb_device *d, u16 reg, | ||
| 162 | u8 * values, int len) | ||
| 163 | { | ||
| 164 | int ret; | ||
| 165 | deb_reg("read %d registers %x ", len, reg); | ||
| 166 | ret = af9005_generic_read_write(d, reg, | ||
| 167 | AF9005_CMD_READ, AF9005_OFDM_REG, | ||
| 168 | values, len); | ||
| 169 | if (ret) | ||
| 170 | deb_reg("failed\n"); | ||
| 171 | else | ||
| 172 | debug_dump(values, len, deb_reg); | ||
| 173 | return ret; | ||
| 174 | } | ||
| 175 | |||
| 176 | int af9005_write_ofdm_register(struct dvb_usb_device *d, u16 reg, u8 value) | ||
| 177 | { | ||
| 178 | int ret; | ||
| 179 | u8 temp = value; | ||
| 180 | deb_reg("write register %x value %x ", reg, value); | ||
| 181 | ret = af9005_generic_read_write(d, reg, | ||
| 182 | AF9005_CMD_WRITE, AF9005_OFDM_REG, | ||
| 183 | &temp, 1); | ||
| 184 | if (ret) | ||
| 185 | deb_reg("failed\n"); | ||
| 186 | else | ||
| 187 | deb_reg("ok\n"); | ||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | int af9005_write_ofdm_registers(struct dvb_usb_device *d, u16 reg, | ||
| 192 | u8 * values, int len) | ||
| 193 | { | ||
| 194 | int ret; | ||
| 195 | deb_reg("write %d registers %x values ", len, reg); | ||
| 196 | debug_dump(values, len, deb_reg); | ||
| 197 | |||
| 198 | ret = af9005_generic_read_write(d, reg, | ||
| 199 | AF9005_CMD_WRITE, AF9005_OFDM_REG, | ||
| 200 | values, len); | ||
| 201 | if (ret) | ||
| 202 | deb_reg("failed\n"); | ||
| 203 | else | ||
| 204 | deb_reg("ok\n"); | ||
| 205 | return ret; | ||
| 206 | } | ||
| 207 | |||
| 208 | int af9005_read_register_bits(struct dvb_usb_device *d, u16 reg, u8 pos, | ||
| 209 | u8 len, u8 * value) | ||
| 210 | { | ||
| 211 | u8 temp; | ||
| 212 | int ret; | ||
| 213 | deb_reg("read bits %x %x %x", reg, pos, len); | ||
| 214 | ret = af9005_read_ofdm_register(d, reg, &temp); | ||
| 215 | if (ret) { | ||
| 216 | deb_reg(" failed\n"); | ||
| 217 | return ret; | ||
| 218 | } | ||
| 219 | *value = (temp >> pos) & regmask[len - 1]; | ||
| 220 | deb_reg(" value %x\n", *value); | ||
| 221 | return 0; | ||
| 222 | |||
| 223 | } | ||
| 224 | |||
| 225 | int af9005_write_register_bits(struct dvb_usb_device *d, u16 reg, u8 pos, | ||
| 226 | u8 len, u8 value) | ||
| 227 | { | ||
| 228 | u8 temp, mask; | ||
| 229 | int ret; | ||
| 230 | deb_reg("write bits %x %x %x value %x\n", reg, pos, len, value); | ||
| 231 | if (pos == 0 && len == 8) | ||
| 232 | return af9005_write_ofdm_register(d, reg, value); | ||
| 233 | ret = af9005_read_ofdm_register(d, reg, &temp); | ||
| 234 | if (ret) | ||
| 235 | return ret; | ||
| 236 | mask = regmask[len - 1] << pos; | ||
| 237 | temp = (temp & ~mask) | ((value << pos) & mask); | ||
| 238 | return af9005_write_ofdm_register(d, reg, temp); | ||
| 239 | |||
| 240 | } | ||
| 241 | |||
| 242 | static int af9005_usb_read_tuner_registers(struct dvb_usb_device *d, | ||
| 243 | u16 reg, u8 * values, int len) | ||
| 244 | { | ||
| 245 | return af9005_generic_read_write(d, reg, | ||
| 246 | AF9005_CMD_READ, AF9005_TUNER_REG, | ||
| 247 | values, len); | ||
| 248 | } | ||
| 249 | |||
| 250 | static int af9005_usb_write_tuner_registers(struct dvb_usb_device *d, | ||
| 251 | u16 reg, u8 * values, int len) | ||
| 252 | { | ||
| 253 | return af9005_generic_read_write(d, reg, | ||
| 254 | AF9005_CMD_WRITE, | ||
| 255 | AF9005_TUNER_REG, values, len); | ||
| 256 | } | ||
| 257 | |||
| 258 | int af9005_write_tuner_registers(struct dvb_usb_device *d, u16 reg, | ||
| 259 | u8 * values, int len) | ||
| 260 | { | ||
| 261 | /* don't let the name of this function mislead you: it's just used | ||
| 262 | as an interface from the firmware to the i2c bus. The actual | ||
| 263 | i2c addresses are contained in the data */ | ||
| 264 | int ret, i, done = 0, fail = 0; | ||
| 265 | u8 temp; | ||
| 266 | ret = af9005_usb_write_tuner_registers(d, reg, values, len); | ||
| 267 | if (ret) | ||
| 268 | return ret; | ||
| 269 | if (reg != 0xffff) { | ||
| 270 | /* check if write done (0xa40d bit 1) or fail (0xa40d bit 2) */ | ||
| 271 | for (i = 0; i < 200; i++) { | ||
| 272 | ret = | ||
| 273 | af9005_read_ofdm_register(d, | ||
| 274 | xd_I2C_i2c_m_status_wdat_done, | ||
| 275 | &temp); | ||
| 276 | if (ret) | ||
| 277 | return ret; | ||
| 278 | done = temp & (regmask[i2c_m_status_wdat_done_len - 1] | ||
| 279 | << i2c_m_status_wdat_done_pos); | ||
| 280 | if (done) | ||
| 281 | break; | ||
| 282 | fail = temp & (regmask[i2c_m_status_wdat_fail_len - 1] | ||
| 283 | << i2c_m_status_wdat_fail_pos); | ||
| 284 | if (fail) | ||
| 285 | break; | ||
| 286 | msleep(50); | ||
| 287 | } | ||
| 288 | if (i == 200) | ||
| 289 | return -ETIMEDOUT; | ||
| 290 | if (fail) { | ||
| 291 | /* clear write fail bit */ | ||
| 292 | af9005_write_register_bits(d, | ||
| 293 | xd_I2C_i2c_m_status_wdat_fail, | ||
| 294 | i2c_m_status_wdat_fail_pos, | ||
| 295 | i2c_m_status_wdat_fail_len, | ||
| 296 | 1); | ||
| 297 | return -EIO; | ||
| 298 | } | ||
| 299 | /* clear write done bit */ | ||
| 300 | ret = | ||
| 301 | af9005_write_register_bits(d, | ||
| 302 | xd_I2C_i2c_m_status_wdat_fail, | ||
| 303 | i2c_m_status_wdat_done_pos, | ||
| 304 | i2c_m_status_wdat_done_len, 1); | ||
| 305 | if (ret) | ||
| 306 | return ret; | ||
| 307 | } | ||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | int af9005_read_tuner_registers(struct dvb_usb_device *d, u16 reg, u8 addr, | ||
| 312 | u8 * values, int len) | ||
| 313 | { | ||
| 314 | /* don't let the name of this function mislead you: it's just used | ||
| 315 | as an interface from the firmware to the i2c bus. The actual | ||
| 316 | i2c addresses are contained in the data */ | ||
| 317 | int ret, i; | ||
| 318 | u8 temp, buf[2]; | ||
| 319 | |||
| 320 | buf[0] = addr; /* tuner i2c address */ | ||
| 321 | buf[1] = values[0]; /* tuner register */ | ||
| 322 | |||
| 323 | values[0] = addr + 0x01; /* i2c read address */ | ||
| 324 | |||
| 325 | if (reg == APO_REG_I2C_RW_SILICON_TUNER) { | ||
| 326 | /* write tuner i2c address to tuner, 0c00c0 undocumented, found by sniffing */ | ||
| 327 | ret = af9005_write_tuner_registers(d, 0x00c0, buf, 2); | ||
| 328 | if (ret) | ||
| 329 | return ret; | ||
| 330 | } | ||
| 331 | |||
| 332 | /* send read command to ofsm */ | ||
| 333 | ret = af9005_usb_read_tuner_registers(d, reg, values, 1); | ||
| 334 | if (ret) | ||
| 335 | return ret; | ||
| 336 | |||
| 337 | /* check if read done */ | ||
| 338 | for (i = 0; i < 200; i++) { | ||
| 339 | ret = af9005_read_ofdm_register(d, 0xa408, &temp); | ||
| 340 | if (ret) | ||
| 341 | return ret; | ||
| 342 | if (temp & 0x01) | ||
| 343 | break; | ||
| 344 | msleep(50); | ||
| 345 | } | ||
| 346 | if (i == 200) | ||
| 347 | return -ETIMEDOUT; | ||
| 348 | |||
| 349 | /* clear read done bit (by writing 1) */ | ||
| 350 | ret = af9005_write_ofdm_register(d, xd_I2C_i2c_m_data8, 1); | ||
| 351 | if (ret) | ||
| 352 | return ret; | ||
| 353 | |||
| 354 | /* get read data (available from 0xa400) */ | ||
| 355 | for (i = 0; i < len; i++) { | ||
| 356 | ret = af9005_read_ofdm_register(d, 0xa400 + i, &temp); | ||
| 357 | if (ret) | ||
| 358 | return ret; | ||
| 359 | values[i] = temp; | ||
| 360 | } | ||
| 361 | return 0; | ||
| 362 | } | ||
| 363 | |||
| 364 | static int af9005_i2c_write(struct dvb_usb_device *d, u8 i2caddr, u8 reg, | ||
| 365 | u8 * data, int len) | ||
| 366 | { | ||
| 367 | int ret, i; | ||
| 368 | u8 buf[3]; | ||
| 369 | deb_i2c("i2c_write i2caddr %x, reg %x, len %d data ", i2caddr, | ||
| 370 | reg, len); | ||
| 371 | debug_dump(data, len, deb_i2c); | ||
| 372 | |||
| 373 | for (i = 0; i < len; i++) { | ||
| 374 | buf[0] = i2caddr; | ||
| 375 | buf[1] = reg + (u8) i; | ||
| 376 | buf[2] = data[i]; | ||
| 377 | ret = | ||
| 378 | af9005_write_tuner_registers(d, | ||
| 379 | APO_REG_I2C_RW_SILICON_TUNER, | ||
| 380 | buf, 3); | ||
| 381 | if (ret) { | ||
| 382 | deb_i2c("i2c_write failed\n"); | ||
| 383 | return ret; | ||
| 384 | } | ||
| 385 | } | ||
| 386 | deb_i2c("i2c_write ok\n"); | ||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | static int af9005_i2c_read(struct dvb_usb_device *d, u8 i2caddr, u8 reg, | ||
| 391 | u8 * data, int len) | ||
| 392 | { | ||
| 393 | int ret, i; | ||
| 394 | u8 temp; | ||
| 395 | deb_i2c("i2c_read i2caddr %x, reg %x, len %d\n ", i2caddr, reg, len); | ||
| 396 | for (i = 0; i < len; i++) { | ||
| 397 | temp = reg + i; | ||
| 398 | ret = | ||
| 399 | af9005_read_tuner_registers(d, | ||
| 400 | APO_REG_I2C_RW_SILICON_TUNER, | ||
| 401 | i2caddr, &temp, 1); | ||
| 402 | if (ret) { | ||
| 403 | deb_i2c("i2c_read failed\n"); | ||
| 404 | return ret; | ||
| 405 | } | ||
| 406 | data[i] = temp; | ||
| 407 | } | ||
| 408 | deb_i2c("i2c data read: "); | ||
| 409 | debug_dump(data, len, deb_i2c); | ||
| 410 | return 0; | ||
| 411 | } | ||
| 412 | |||
| 413 | static int af9005_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 414 | int num) | ||
| 415 | { | ||
| 416 | /* only implements what the mt2060 module does, don't know how | ||
| 417 | to make it really generic */ | ||
| 418 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 419 | int ret; | ||
| 420 | u8 reg, addr; | ||
| 421 | u8 *value; | ||
| 422 | |||
| 423 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 424 | return -EAGAIN; | ||
| 425 | |||
| 426 | if (num > 2) | ||
| 427 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
| 428 | |||
| 429 | if (num == 2) { | ||
| 430 | /* reads a single register */ | ||
| 431 | reg = *msg[0].buf; | ||
| 432 | addr = msg[0].addr; | ||
| 433 | value = msg[1].buf; | ||
| 434 | ret = af9005_i2c_read(d, addr, reg, value, 1); | ||
| 435 | if (ret == 0) | ||
| 436 | ret = 2; | ||
| 437 | } else { | ||
| 438 | /* write one or more registers */ | ||
| 439 | reg = msg[0].buf[0]; | ||
| 440 | addr = msg[0].addr; | ||
| 441 | value = &msg[0].buf[1]; | ||
| 442 | ret = af9005_i2c_write(d, addr, reg, value, msg[0].len - 1); | ||
| 443 | if (ret == 0) | ||
| 444 | ret = 1; | ||
| 445 | } | ||
| 446 | |||
| 447 | mutex_unlock(&d->i2c_mutex); | ||
| 448 | return ret; | ||
| 449 | } | ||
| 450 | |||
| 451 | static u32 af9005_i2c_func(struct i2c_adapter *adapter) | ||
| 452 | { | ||
| 453 | return I2C_FUNC_I2C; | ||
| 454 | } | ||
| 455 | |||
| 456 | static struct i2c_algorithm af9005_i2c_algo = { | ||
| 457 | .master_xfer = af9005_i2c_xfer, | ||
| 458 | .functionality = af9005_i2c_func, | ||
| 459 | }; | ||
| 460 | |||
| 461 | int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf, | ||
| 462 | int wlen, u8 * rbuf, int rlen) | ||
| 463 | { | ||
| 464 | struct af9005_device_state *st = d->priv; | ||
| 465 | |||
| 466 | int ret, i, packet_len; | ||
| 467 | u8 buf[64]; | ||
| 468 | u8 ibuf[64]; | ||
| 469 | |||
| 470 | if (wlen < 0) { | ||
| 471 | err("send command, wlen less than 0 bytes. Makes no sense."); | ||
| 472 | return -EINVAL; | ||
| 473 | } | ||
| 474 | if (wlen > 54) { | ||
| 475 | err("send command, wlen more than 54 bytes. Not supported."); | ||
| 476 | return -EINVAL; | ||
| 477 | } | ||
| 478 | if (rlen > 54) { | ||
| 479 | err("send command, rlen more than 54 bytes. Not supported."); | ||
| 480 | return -EINVAL; | ||
| 481 | } | ||
| 482 | packet_len = wlen + 5; | ||
| 483 | buf[0] = (u8) (packet_len & 0xff); | ||
| 484 | buf[1] = (u8) ((packet_len & 0xff00) >> 8); | ||
| 485 | |||
| 486 | buf[2] = 0x26; /* packet type */ | ||
| 487 | buf[3] = wlen + 3; | ||
| 488 | buf[4] = st->sequence++; | ||
| 489 | buf[5] = command; | ||
| 490 | buf[6] = wlen; | ||
| 491 | for (i = 0; i < wlen; i++) | ||
| 492 | buf[7 + i] = wbuf[i]; | ||
| 493 | ret = dvb_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0); | ||
| 494 | if (ret) | ||
| 495 | return ret; | ||
| 496 | if (ibuf[2] != 0x27) { | ||
| 497 | err("send command, wrong reply code."); | ||
| 498 | return -EIO; | ||
| 499 | } | ||
| 500 | if (ibuf[4] != buf[4]) { | ||
| 501 | err("send command, wrong sequence in reply."); | ||
| 502 | return -EIO; | ||
| 503 | } | ||
| 504 | if (ibuf[5] != 0x01) { | ||
| 505 | err("send command, wrong status code in reply."); | ||
| 506 | return -EIO; | ||
| 507 | } | ||
| 508 | if (ibuf[6] != rlen) { | ||
| 509 | err("send command, invalid data length in reply."); | ||
| 510 | return -EIO; | ||
| 511 | } | ||
| 512 | for (i = 0; i < rlen; i++) | ||
| 513 | rbuf[i] = ibuf[i + 7]; | ||
| 514 | return 0; | ||
| 515 | } | ||
| 516 | |||
| 517 | int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values, | ||
| 518 | int len) | ||
| 519 | { | ||
| 520 | struct af9005_device_state *st = d->priv; | ||
| 521 | u8 obuf[16], ibuf[14]; | ||
| 522 | int ret, i; | ||
| 523 | |||
| 524 | memset(obuf, 0, sizeof(obuf)); | ||
| 525 | memset(ibuf, 0, sizeof(ibuf)); | ||
| 526 | |||
| 527 | obuf[0] = 14; /* length of rest of packet low */ | ||
| 528 | obuf[1] = 0; /* length of rest of packer high */ | ||
| 529 | |||
| 530 | obuf[2] = 0x2a; /* read/write eeprom */ | ||
| 531 | |||
| 532 | obuf[3] = 12; /* size */ | ||
| 533 | |||
| 534 | obuf[4] = st->sequence++; | ||
| 535 | |||
| 536 | obuf[5] = 0; /* read */ | ||
| 537 | |||
| 538 | obuf[6] = len; | ||
| 539 | obuf[7] = address; | ||
| 540 | ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 14, 0); | ||
| 541 | if (ret) | ||
| 542 | return ret; | ||
| 543 | if (ibuf[2] != 0x2b) { | ||
| 544 | err("Read eeprom, invalid reply code"); | ||
| 545 | return -EIO; | ||
| 546 | } | ||
| 547 | if (ibuf[3] != 10) { | ||
| 548 | err("Read eeprom, invalid reply length"); | ||
| 549 | return -EIO; | ||
| 550 | } | ||
| 551 | if (ibuf[4] != obuf[4]) { | ||
| 552 | err("Read eeprom, wrong sequence in reply "); | ||
| 553 | return -EIO; | ||
| 554 | } | ||
| 555 | if (ibuf[5] != 1) { | ||
| 556 | err("Read eeprom, wrong status in reply "); | ||
| 557 | return -EIO; | ||
| 558 | } | ||
| 559 | for (i = 0; i < len; i++) { | ||
| 560 | values[i] = ibuf[6 + i]; | ||
| 561 | } | ||
| 562 | return 0; | ||
| 563 | } | ||
| 564 | |||
| 565 | static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply) | ||
| 566 | { | ||
| 567 | u8 buf[FW_BULKOUT_SIZE + 2]; | ||
| 568 | u16 checksum; | ||
| 569 | int act_len, i, ret; | ||
| 570 | memset(buf, 0, sizeof(buf)); | ||
| 571 | buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff); | ||
| 572 | buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff); | ||
| 573 | switch (type) { | ||
| 574 | case FW_CONFIG: | ||
| 575 | buf[2] = 0x11; | ||
| 576 | buf[3] = 0x04; | ||
| 577 | buf[4] = 0x00; /* sequence number, original driver doesn't increment it here */ | ||
| 578 | buf[5] = 0x03; | ||
| 579 | checksum = buf[4] + buf[5]; | ||
| 580 | buf[6] = (u8) ((checksum >> 8) & 0xff); | ||
| 581 | buf[7] = (u8) (checksum & 0xff); | ||
| 582 | break; | ||
| 583 | case FW_CONFIRM: | ||
| 584 | buf[2] = 0x11; | ||
| 585 | buf[3] = 0x04; | ||
| 586 | buf[4] = 0x00; /* sequence number, original driver doesn't increment it here */ | ||
| 587 | buf[5] = 0x01; | ||
| 588 | checksum = buf[4] + buf[5]; | ||
| 589 | buf[6] = (u8) ((checksum >> 8) & 0xff); | ||
| 590 | buf[7] = (u8) (checksum & 0xff); | ||
| 591 | break; | ||
| 592 | case FW_BOOT: | ||
| 593 | buf[2] = 0x10; | ||
| 594 | buf[3] = 0x08; | ||
| 595 | buf[4] = 0x00; /* sequence number, original driver doesn't increment it here */ | ||
| 596 | buf[5] = 0x97; | ||
| 597 | buf[6] = 0xaa; | ||
| 598 | buf[7] = 0x55; | ||
| 599 | buf[8] = 0xa5; | ||
| 600 | buf[9] = 0x5a; | ||
| 601 | checksum = 0; | ||
| 602 | for (i = 4; i <= 9; i++) | ||
| 603 | checksum += buf[i]; | ||
| 604 | buf[10] = (u8) ((checksum >> 8) & 0xff); | ||
| 605 | buf[11] = (u8) (checksum & 0xff); | ||
| 606 | break; | ||
| 607 | default: | ||
| 608 | err("boot packet invalid boot packet type"); | ||
| 609 | return -EINVAL; | ||
| 610 | } | ||
| 611 | deb_fw(">>> "); | ||
| 612 | debug_dump(buf, FW_BULKOUT_SIZE + 2, deb_fw); | ||
| 613 | |||
| 614 | ret = usb_bulk_msg(udev, | ||
| 615 | usb_sndbulkpipe(udev, 0x02), | ||
| 616 | buf, FW_BULKOUT_SIZE + 2, &act_len, 2000); | ||
| 617 | if (ret) | ||
| 618 | err("boot packet bulk message failed: %d (%d/%d)", ret, | ||
| 619 | FW_BULKOUT_SIZE + 2, act_len); | ||
| 620 | else | ||
| 621 | ret = act_len != FW_BULKOUT_SIZE + 2 ? -1 : 0; | ||
| 622 | if (ret) | ||
| 623 | return ret; | ||
| 624 | memset(buf, 0, 9); | ||
| 625 | ret = usb_bulk_msg(udev, | ||
| 626 | usb_rcvbulkpipe(udev, 0x01), buf, 9, &act_len, 2000); | ||
| 627 | if (ret) { | ||
| 628 | err("boot packet recv bulk message failed: %d", ret); | ||
| 629 | return ret; | ||
| 630 | } | ||
| 631 | deb_fw("<<< "); | ||
| 632 | debug_dump(buf, act_len, deb_fw); | ||
| 633 | checksum = 0; | ||
| 634 | switch (type) { | ||
| 635 | case FW_CONFIG: | ||
| 636 | if (buf[2] != 0x11) { | ||
| 637 | err("boot bad config header."); | ||
| 638 | return -EIO; | ||
| 639 | } | ||
| 640 | if (buf[3] != 0x05) { | ||
| 641 | err("boot bad config size."); | ||
| 642 | return -EIO; | ||
| 643 | } | ||
| 644 | if (buf[4] != 0x00) { | ||
| 645 | err("boot bad config sequence."); | ||
| 646 | return -EIO; | ||
| 647 | } | ||
| 648 | if (buf[5] != 0x04) { | ||
| 649 | err("boot bad config subtype."); | ||
| 650 | return -EIO; | ||
| 651 | } | ||
| 652 | for (i = 4; i <= 6; i++) | ||
| 653 | checksum += buf[i]; | ||
| 654 | if (buf[7] * 256 + buf[8] != checksum) { | ||
| 655 | err("boot bad config checksum."); | ||
| 656 | return -EIO; | ||
| 657 | } | ||
| 658 | *reply = buf[6]; | ||
| 659 | break; | ||
| 660 | case FW_CONFIRM: | ||
| 661 | if (buf[2] != 0x11) { | ||
| 662 | err("boot bad confirm header."); | ||
| 663 | return -EIO; | ||
| 664 | } | ||
| 665 | if (buf[3] != 0x05) { | ||
| 666 | err("boot bad confirm size."); | ||
| 667 | return -EIO; | ||
| 668 | } | ||
| 669 | if (buf[4] != 0x00) { | ||
| 670 | err("boot bad confirm sequence."); | ||
| 671 | return -EIO; | ||
| 672 | } | ||
| 673 | if (buf[5] != 0x02) { | ||
| 674 | err("boot bad confirm subtype."); | ||
| 675 | return -EIO; | ||
| 676 | } | ||
| 677 | for (i = 4; i <= 6; i++) | ||
| 678 | checksum += buf[i]; | ||
| 679 | if (buf[7] * 256 + buf[8] != checksum) { | ||
| 680 | err("boot bad confirm checksum."); | ||
| 681 | return -EIO; | ||
| 682 | } | ||
| 683 | *reply = buf[6]; | ||
| 684 | break; | ||
| 685 | case FW_BOOT: | ||
| 686 | if (buf[2] != 0x10) { | ||
| 687 | err("boot bad boot header."); | ||
| 688 | return -EIO; | ||
| 689 | } | ||
| 690 | if (buf[3] != 0x05) { | ||
| 691 | err("boot bad boot size."); | ||
| 692 | return -EIO; | ||
| 693 | } | ||
| 694 | if (buf[4] != 0x00) { | ||
| 695 | err("boot bad boot sequence."); | ||
| 696 | return -EIO; | ||
| 697 | } | ||
| 698 | if (buf[5] != 0x01) { | ||
| 699 | err("boot bad boot pattern 01."); | ||
| 700 | return -EIO; | ||
| 701 | } | ||
| 702 | if (buf[6] != 0x10) { | ||
| 703 | err("boot bad boot pattern 10."); | ||
| 704 | return -EIO; | ||
| 705 | } | ||
| 706 | for (i = 4; i <= 6; i++) | ||
| 707 | checksum += buf[i]; | ||
| 708 | if (buf[7] * 256 + buf[8] != checksum) { | ||
| 709 | err("boot bad boot checksum."); | ||
| 710 | return -EIO; | ||
| 711 | } | ||
| 712 | break; | ||
| 713 | |||
| 714 | } | ||
| 715 | |||
| 716 | return 0; | ||
| 717 | } | ||
| 718 | |||
| 719 | static int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw) | ||
| 720 | { | ||
| 721 | int i, packets, ret, act_len; | ||
| 722 | |||
| 723 | u8 buf[FW_BULKOUT_SIZE + 2]; | ||
| 724 | u8 reply; | ||
| 725 | |||
| 726 | ret = af9005_boot_packet(udev, FW_CONFIG, &reply); | ||
| 727 | if (ret) | ||
| 728 | return ret; | ||
| 729 | if (reply != 0x01) { | ||
| 730 | err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply); | ||
| 731 | return -EIO; | ||
| 732 | } | ||
| 733 | packets = fw->size / FW_BULKOUT_SIZE; | ||
| 734 | buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff); | ||
| 735 | buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff); | ||
| 736 | for (i = 0; i < packets; i++) { | ||
| 737 | memcpy(&buf[2], fw->data + i * FW_BULKOUT_SIZE, | ||
| 738 | FW_BULKOUT_SIZE); | ||
| 739 | deb_fw(">>> "); | ||
| 740 | debug_dump(buf, FW_BULKOUT_SIZE + 2, deb_fw); | ||
| 741 | ret = usb_bulk_msg(udev, | ||
| 742 | usb_sndbulkpipe(udev, 0x02), | ||
| 743 | buf, FW_BULKOUT_SIZE + 2, &act_len, 1000); | ||
| 744 | if (ret) { | ||
| 745 | err("firmware download failed at packet %d with code %d", i, ret); | ||
| 746 | return ret; | ||
| 747 | } | ||
| 748 | } | ||
| 749 | ret = af9005_boot_packet(udev, FW_CONFIRM, &reply); | ||
| 750 | if (ret) | ||
| 751 | return ret; | ||
| 752 | if (reply != (u8) (packets & 0xff)) { | ||
| 753 | err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply); | ||
| 754 | return -EIO; | ||
| 755 | } | ||
| 756 | ret = af9005_boot_packet(udev, FW_BOOT, &reply); | ||
| 757 | if (ret) | ||
| 758 | return ret; | ||
| 759 | ret = af9005_boot_packet(udev, FW_CONFIG, &reply); | ||
| 760 | if (ret) | ||
| 761 | return ret; | ||
| 762 | if (reply != 0x02) { | ||
| 763 | err("after downloading firmware, FW_CONFIG expected 0x02, received 0x%x", reply); | ||
| 764 | return -EIO; | ||
| 765 | } | ||
| 766 | |||
| 767 | return 0; | ||
| 768 | |||
| 769 | } | ||
| 770 | |||
| 771 | int af9005_led_control(struct dvb_usb_device *d, int onoff) | ||
| 772 | { | ||
| 773 | struct af9005_device_state *st = d->priv; | ||
| 774 | int temp, ret; | ||
| 775 | |||
| 776 | if (onoff && dvb_usb_af9005_led) | ||
| 777 | temp = 1; | ||
| 778 | else | ||
| 779 | temp = 0; | ||
| 780 | if (st->led_state != temp) { | ||
| 781 | ret = | ||
| 782 | af9005_write_register_bits(d, xd_p_reg_top_locken1, | ||
| 783 | reg_top_locken1_pos, | ||
| 784 | reg_top_locken1_len, temp); | ||
| 785 | if (ret) | ||
| 786 | return ret; | ||
| 787 | ret = | ||
| 788 | af9005_write_register_bits(d, xd_p_reg_top_lock1, | ||
| 789 | reg_top_lock1_pos, | ||
| 790 | reg_top_lock1_len, temp); | ||
| 791 | if (ret) | ||
| 792 | return ret; | ||
| 793 | st->led_state = temp; | ||
| 794 | } | ||
| 795 | return 0; | ||
| 796 | } | ||
| 797 | |||
| 798 | static int af9005_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 799 | { | ||
| 800 | u8 buf[8]; | ||
| 801 | int i; | ||
| 802 | |||
| 803 | /* without these calls the first commands after downloading | ||
| 804 | the firmware fail. I put these calls here to simulate | ||
| 805 | what it is done in dvb-usb-init.c. | ||
| 806 | */ | ||
| 807 | struct usb_device *udev = adap->dev->udev; | ||
| 808 | usb_clear_halt(udev, usb_sndbulkpipe(udev, 2)); | ||
| 809 | usb_clear_halt(udev, usb_rcvbulkpipe(udev, 1)); | ||
| 810 | if (dvb_usb_af9005_dump_eeprom) { | ||
| 811 | printk("EEPROM DUMP\n"); | ||
| 812 | for (i = 0; i < 255; i += 8) { | ||
| 813 | af9005_read_eeprom(adap->dev, i, buf, 8); | ||
| 814 | printk("ADDR %x ", i); | ||
| 815 | debug_dump(buf, 8, printk); | ||
| 816 | } | ||
| 817 | } | ||
| 818 | adap->fe = af9005_fe_attach(adap->dev); | ||
| 819 | return 0; | ||
| 820 | } | ||
| 821 | |||
| 822 | static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state) | ||
| 823 | { | ||
| 824 | struct af9005_device_state *st = d->priv; | ||
| 825 | int ret, len; | ||
| 826 | |||
| 827 | u8 obuf[5]; | ||
| 828 | u8 ibuf[256]; | ||
| 829 | |||
| 830 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 831 | if (rc_decode == NULL) { | ||
| 832 | /* it shouldn't never come here */ | ||
| 833 | return 0; | ||
| 834 | } | ||
| 835 | /* deb_info("rc_query\n"); */ | ||
| 836 | obuf[0] = 3; /* rest of packet length low */ | ||
| 837 | obuf[1] = 0; /* rest of packet lentgh high */ | ||
| 838 | obuf[2] = 0x40; /* read remote */ | ||
| 839 | obuf[3] = 1; /* rest of packet length */ | ||
| 840 | obuf[4] = st->sequence++; /* sequence number */ | ||
| 841 | ret = dvb_usb_generic_rw(d, obuf, 5, ibuf, 256, 0); | ||
| 842 | if (ret) { | ||
| 843 | err("rc query failed"); | ||
| 844 | return ret; | ||
| 845 | } | ||
| 846 | if (ibuf[2] != 0x41) { | ||
| 847 | err("rc query bad header."); | ||
| 848 | return -EIO; | ||
| 849 | } | ||
| 850 | if (ibuf[4] != obuf[4]) { | ||
| 851 | err("rc query bad sequence."); | ||
| 852 | return -EIO; | ||
| 853 | } | ||
| 854 | len = ibuf[5]; | ||
| 855 | if (len > 246) { | ||
| 856 | err("rc query invalid length"); | ||
| 857 | return -EIO; | ||
| 858 | } | ||
| 859 | if (len > 0) { | ||
| 860 | deb_rc("rc data (%d) ", len); | ||
| 861 | debug_dump((ibuf + 6), len, deb_rc); | ||
| 862 | ret = rc_decode(d, &ibuf[6], len, event, state); | ||
| 863 | if (ret) { | ||
| 864 | err("rc_decode failed"); | ||
| 865 | return ret; | ||
| 866 | } else { | ||
| 867 | deb_rc("rc_decode state %x event %x\n", *state, *event); | ||
| 868 | if (*state == REMOTE_KEY_REPEAT) | ||
| 869 | *event = d->last_event; | ||
| 870 | } | ||
| 871 | } | ||
| 872 | return 0; | ||
| 873 | } | ||
| 874 | |||
| 875 | static int af9005_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 876 | { | ||
| 877 | |||
| 878 | return 0; | ||
| 879 | } | ||
| 880 | |||
| 881 | static int af9005_pid_filter_control(struct dvb_usb_adapter *adap, int onoff) | ||
| 882 | { | ||
| 883 | int ret; | ||
| 884 | deb_info("pid filter control onoff %d\n", onoff); | ||
| 885 | if (onoff) { | ||
| 886 | ret = | ||
| 887 | af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 1); | ||
| 888 | if (ret) | ||
| 889 | return ret; | ||
| 890 | ret = | ||
| 891 | af9005_write_register_bits(adap->dev, | ||
| 892 | XD_MP2IF_DMX_CTRL, 1, 1, 1); | ||
| 893 | if (ret) | ||
| 894 | return ret; | ||
| 895 | ret = | ||
| 896 | af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 1); | ||
| 897 | } else | ||
| 898 | ret = | ||
| 899 | af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 0); | ||
| 900 | if (ret) | ||
| 901 | return ret; | ||
| 902 | deb_info("pid filter control ok\n"); | ||
| 903 | return 0; | ||
| 904 | } | ||
| 905 | |||
| 906 | static int af9005_pid_filter(struct dvb_usb_adapter *adap, int index, | ||
| 907 | u16 pid, int onoff) | ||
| 908 | { | ||
| 909 | u8 cmd = index & 0x1f; | ||
| 910 | int ret; | ||
| 911 | deb_info("set pid filter, index %d, pid %x, onoff %d\n", index, | ||
| 912 | pid, onoff); | ||
| 913 | if (onoff) { | ||
| 914 | /* cannot use it as pid_filter_ctrl since it has to be done | ||
| 915 | before setting the first pid */ | ||
| 916 | if (adap->feedcount == 1) { | ||
| 917 | deb_info("first pid set, enable pid table\n"); | ||
| 918 | ret = af9005_pid_filter_control(adap, onoff); | ||
| 919 | if (ret) | ||
| 920 | return ret; | ||
| 921 | } | ||
| 922 | ret = | ||
| 923 | af9005_write_ofdm_register(adap->dev, | ||
| 924 | XD_MP2IF_PID_DATA_L, | ||
| 925 | (u8) (pid & 0xff)); | ||
| 926 | if (ret) | ||
| 927 | return ret; | ||
| 928 | ret = | ||
| 929 | af9005_write_ofdm_register(adap->dev, | ||
| 930 | XD_MP2IF_PID_DATA_H, | ||
| 931 | (u8) (pid >> 8)); | ||
| 932 | if (ret) | ||
| 933 | return ret; | ||
| 934 | cmd |= 0x20 | 0x40; | ||
| 935 | } else { | ||
| 936 | if (adap->feedcount == 0) { | ||
| 937 | deb_info("last pid unset, disable pid table\n"); | ||
| 938 | ret = af9005_pid_filter_control(adap, onoff); | ||
| 939 | if (ret) | ||
| 940 | return ret; | ||
| 941 | } | ||
| 942 | } | ||
| 943 | ret = af9005_write_ofdm_register(adap->dev, XD_MP2IF_PID_IDX, cmd); | ||
| 944 | if (ret) | ||
| 945 | return ret; | ||
| 946 | deb_info("set pid ok\n"); | ||
| 947 | return 0; | ||
| 948 | } | ||
| 949 | |||
| 950 | static int af9005_identify_state(struct usb_device *udev, | ||
| 951 | struct dvb_usb_device_properties *props, | ||
| 952 | struct dvb_usb_device_description **desc, | ||
| 953 | int *cold) | ||
| 954 | { | ||
| 955 | int ret; | ||
| 956 | u8 reply; | ||
| 957 | ret = af9005_boot_packet(udev, FW_CONFIG, &reply); | ||
| 958 | if (ret) | ||
| 959 | return ret; | ||
| 960 | deb_info("result of FW_CONFIG in identify state %d\n", reply); | ||
| 961 | if (reply == 0x01) | ||
| 962 | *cold = 1; | ||
| 963 | else if (reply == 0x02) | ||
| 964 | *cold = 0; | ||
| 965 | else | ||
| 966 | return -EIO; | ||
| 967 | deb_info("Identify state cold = %d\n", *cold); | ||
| 968 | return 0; | ||
| 969 | } | ||
| 970 | |||
| 971 | static struct dvb_usb_device_properties af9005_properties; | ||
| 972 | |||
| 973 | static int af9005_usb_probe(struct usb_interface *intf, | ||
| 974 | const struct usb_device_id *id) | ||
| 975 | { | ||
| 976 | return dvb_usb_device_init(intf, &af9005_properties, | ||
| 977 | THIS_MODULE, NULL, adapter_nr); | ||
| 978 | } | ||
| 979 | |||
| 980 | static struct usb_device_id af9005_usb_table[] = { | ||
| 981 | {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9005)}, | ||
| 982 | {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE)}, | ||
| 983 | {USB_DEVICE(USB_VID_ANSONIC, USB_PID_ANSONIC_DVBT_USB)}, | ||
| 984 | {0}, | ||
| 985 | }; | ||
| 986 | |||
| 987 | MODULE_DEVICE_TABLE(usb, af9005_usb_table); | ||
| 988 | |||
| 989 | static struct dvb_usb_device_properties af9005_properties = { | ||
| 990 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 991 | |||
| 992 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 993 | .firmware = "af9005.fw", | ||
| 994 | .download_firmware = af9005_download_firmware, | ||
| 995 | .no_reconnect = 1, | ||
| 996 | |||
| 997 | .size_of_priv = sizeof(struct af9005_device_state), | ||
| 998 | |||
| 999 | .num_adapters = 1, | ||
| 1000 | .adapter = { | ||
| 1001 | { | ||
| 1002 | .caps = | ||
| 1003 | DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 1004 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1005 | .pid_filter_count = 32, | ||
| 1006 | .pid_filter = af9005_pid_filter, | ||
| 1007 | /* .pid_filter_ctrl = af9005_pid_filter_control, */ | ||
| 1008 | .frontend_attach = af9005_frontend_attach, | ||
| 1009 | /* .tuner_attach = af9005_tuner_attach, */ | ||
| 1010 | /* parameter for the MPEG2-data transfer */ | ||
| 1011 | .stream = { | ||
| 1012 | .type = USB_BULK, | ||
| 1013 | .count = 10, | ||
| 1014 | .endpoint = 0x04, | ||
| 1015 | .u = { | ||
| 1016 | .bulk = { | ||
| 1017 | .buffersize = 4096, /* actual size seen is 3948 */ | ||
| 1018 | } | ||
| 1019 | } | ||
| 1020 | }, | ||
| 1021 | } | ||
| 1022 | }, | ||
| 1023 | .power_ctrl = af9005_power_ctrl, | ||
| 1024 | .identify_state = af9005_identify_state, | ||
| 1025 | |||
| 1026 | .i2c_algo = &af9005_i2c_algo, | ||
| 1027 | |||
| 1028 | .rc.legacy = { | ||
| 1029 | .rc_interval = 200, | ||
| 1030 | .rc_map_table = NULL, | ||
| 1031 | .rc_map_size = 0, | ||
| 1032 | .rc_query = af9005_rc_query, | ||
| 1033 | }, | ||
| 1034 | |||
| 1035 | .generic_bulk_ctrl_endpoint = 2, | ||
| 1036 | .generic_bulk_ctrl_endpoint_response = 1, | ||
| 1037 | |||
| 1038 | .num_device_descs = 3, | ||
| 1039 | .devices = { | ||
| 1040 | {.name = "Afatech DVB-T USB1.1 stick", | ||
| 1041 | .cold_ids = {&af9005_usb_table[0], NULL}, | ||
| 1042 | .warm_ids = {NULL}, | ||
| 1043 | }, | ||
| 1044 | {.name = "TerraTec Cinergy T USB XE", | ||
| 1045 | .cold_ids = {&af9005_usb_table[1], NULL}, | ||
| 1046 | .warm_ids = {NULL}, | ||
| 1047 | }, | ||
| 1048 | {.name = "Ansonic DVB-T USB1.1 stick", | ||
| 1049 | .cold_ids = {&af9005_usb_table[2], NULL}, | ||
| 1050 | .warm_ids = {NULL}, | ||
| 1051 | }, | ||
| 1052 | {NULL}, | ||
| 1053 | } | ||
| 1054 | }; | ||
| 1055 | |||
| 1056 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 1057 | static struct usb_driver af9005_usb_driver = { | ||
| 1058 | .name = "dvb_usb_af9005", | ||
| 1059 | .probe = af9005_usb_probe, | ||
| 1060 | .disconnect = dvb_usb_device_exit, | ||
| 1061 | .id_table = af9005_usb_table, | ||
| 1062 | }; | ||
| 1063 | |||
| 1064 | /* module stuff */ | ||
| 1065 | static int __init af9005_usb_module_init(void) | ||
| 1066 | { | ||
| 1067 | int result; | ||
| 1068 | if ((result = usb_register(&af9005_usb_driver))) { | ||
| 1069 | err("usb_register failed. (%d)", result); | ||
| 1070 | return result; | ||
| 1071 | } | ||
| 1072 | rc_decode = symbol_request(af9005_rc_decode); | ||
| 1073 | rc_keys = symbol_request(rc_map_af9005_table); | ||
| 1074 | rc_keys_size = symbol_request(rc_map_af9005_table_size); | ||
| 1075 | if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) { | ||
| 1076 | err("af9005_rc_decode function not found, disabling remote"); | ||
| 1077 | af9005_properties.rc.legacy.rc_query = NULL; | ||
| 1078 | } else { | ||
| 1079 | af9005_properties.rc.legacy.rc_map_table = rc_keys; | ||
| 1080 | af9005_properties.rc.legacy.rc_map_size = *rc_keys_size; | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | return 0; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | static void __exit af9005_usb_module_exit(void) | ||
| 1087 | { | ||
| 1088 | /* release rc decode symbols */ | ||
| 1089 | if (rc_decode != NULL) | ||
| 1090 | symbol_put(af9005_rc_decode); | ||
| 1091 | if (rc_keys != NULL) | ||
| 1092 | symbol_put(rc_map_af9005_table); | ||
| 1093 | if (rc_keys_size != NULL) | ||
| 1094 | symbol_put(rc_map_af9005_table_size); | ||
| 1095 | /* deregister this driver from the USB subsystem */ | ||
| 1096 | usb_deregister(&af9005_usb_driver); | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | module_init(af9005_usb_module_init); | ||
| 1100 | module_exit(af9005_usb_module_exit); | ||
| 1101 | |||
| 1102 | MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>"); | ||
| 1103 | MODULE_DESCRIPTION("Driver for Afatech 9005 DVB-T USB1.1 stick"); | ||
| 1104 | MODULE_VERSION("1.0"); | ||
| 1105 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/af9005.h b/drivers/media/dvb/dvb-usb/af9005.h new file mode 100644 index 00000000000..c71c77bd7f4 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9005.h | |||
| @@ -0,0 +1,3496 @@ | |||
| 1 | /* Common header-file of the Linux driver for the Afatech 9005 | ||
| 2 | * USB1.1 DVB-T receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org) | ||
| 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 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 23 | */ | ||
| 24 | #ifndef _DVB_USB_AF9005_H_ | ||
| 25 | #define _DVB_USB_AF9005_H_ | ||
| 26 | |||
| 27 | #define DVB_USB_LOG_PREFIX "af9005" | ||
| 28 | #include "dvb-usb.h" | ||
| 29 | |||
| 30 | extern int dvb_usb_af9005_debug; | ||
| 31 | #define deb_info(args...) dprintk(dvb_usb_af9005_debug,0x01,args) | ||
| 32 | #define deb_xfer(args...) dprintk(dvb_usb_af9005_debug,0x02,args) | ||
| 33 | #define deb_rc(args...) dprintk(dvb_usb_af9005_debug,0x04,args) | ||
| 34 | #define deb_reg(args...) dprintk(dvb_usb_af9005_debug,0x08,args) | ||
| 35 | #define deb_i2c(args...) dprintk(dvb_usb_af9005_debug,0x10,args) | ||
| 36 | #define deb_fw(args...) dprintk(dvb_usb_af9005_debug,0x20,args) | ||
| 37 | |||
| 38 | extern int dvb_usb_af9005_led; | ||
| 39 | |||
| 40 | /* firmware */ | ||
| 41 | #define FW_BULKOUT_SIZE 250 | ||
| 42 | enum { | ||
| 43 | FW_CONFIG, | ||
| 44 | FW_CONFIRM, | ||
| 45 | FW_BOOT | ||
| 46 | }; | ||
| 47 | |||
| 48 | /* af9005 commands */ | ||
| 49 | #define AF9005_OFDM_REG 0 | ||
| 50 | #define AF9005_TUNER_REG 1 | ||
| 51 | |||
| 52 | #define AF9005_REGISTER_RW 0x20 | ||
| 53 | #define AF9005_REGISTER_RW_ACK 0x21 | ||
| 54 | |||
| 55 | #define AF9005_CMD_OFDM_REG 0x00 | ||
| 56 | #define AF9005_CMD_TUNER 0x80 | ||
| 57 | #define AF9005_CMD_BURST 0x02 | ||
| 58 | #define AF9005_CMD_AUTOINC 0x04 | ||
| 59 | #define AF9005_CMD_READ 0x00 | ||
| 60 | #define AF9005_CMD_WRITE 0x01 | ||
| 61 | |||
| 62 | /* af9005 registers */ | ||
| 63 | #define APO_REG_RESET 0xAEFF | ||
| 64 | |||
| 65 | #define APO_REG_I2C_RW_CAN_TUNER 0xF000 | ||
| 66 | #define APO_REG_I2C_RW_SILICON_TUNER 0xF001 | ||
| 67 | #define APO_REG_GPIO_RW_SILICON_TUNER 0xFFFE /* also for OFSM */ | ||
| 68 | #define APO_REG_TRIGGER_OFSM 0xFFFF /* also for OFSM */ | ||
| 69 | |||
| 70 | /*********************************************************************** | ||
| 71 | * Apollo Registers from VLSI * | ||
| 72 | ***********************************************************************/ | ||
| 73 | #define xd_p_reg_aagc_inverted_agc 0xA000 | ||
| 74 | #define reg_aagc_inverted_agc_pos 0 | ||
| 75 | #define reg_aagc_inverted_agc_len 1 | ||
| 76 | #define reg_aagc_inverted_agc_lsb 0 | ||
| 77 | #define xd_p_reg_aagc_sign_only 0xA000 | ||
| 78 | #define reg_aagc_sign_only_pos 1 | ||
| 79 | #define reg_aagc_sign_only_len 1 | ||
| 80 | #define reg_aagc_sign_only_lsb 0 | ||
| 81 | #define xd_p_reg_aagc_slow_adc_en 0xA000 | ||
| 82 | #define reg_aagc_slow_adc_en_pos 2 | ||
| 83 | #define reg_aagc_slow_adc_en_len 1 | ||
| 84 | #define reg_aagc_slow_adc_en_lsb 0 | ||
| 85 | #define xd_p_reg_aagc_slow_adc_scale 0xA000 | ||
| 86 | #define reg_aagc_slow_adc_scale_pos 3 | ||
| 87 | #define reg_aagc_slow_adc_scale_len 5 | ||
| 88 | #define reg_aagc_slow_adc_scale_lsb 0 | ||
| 89 | #define xd_p_reg_aagc_check_slow_adc_lock 0xA001 | ||
| 90 | #define reg_aagc_check_slow_adc_lock_pos 0 | ||
| 91 | #define reg_aagc_check_slow_adc_lock_len 1 | ||
| 92 | #define reg_aagc_check_slow_adc_lock_lsb 0 | ||
| 93 | #define xd_p_reg_aagc_init_control 0xA001 | ||
| 94 | #define reg_aagc_init_control_pos 1 | ||
| 95 | #define reg_aagc_init_control_len 1 | ||
| 96 | #define reg_aagc_init_control_lsb 0 | ||
| 97 | #define xd_p_reg_aagc_total_gain_sel 0xA001 | ||
| 98 | #define reg_aagc_total_gain_sel_pos 2 | ||
| 99 | #define reg_aagc_total_gain_sel_len 2 | ||
| 100 | #define reg_aagc_total_gain_sel_lsb 0 | ||
| 101 | #define xd_p_reg_aagc_out_inv 0xA001 | ||
| 102 | #define reg_aagc_out_inv_pos 5 | ||
| 103 | #define reg_aagc_out_inv_len 1 | ||
| 104 | #define reg_aagc_out_inv_lsb 0 | ||
| 105 | #define xd_p_reg_aagc_int_en 0xA001 | ||
| 106 | #define reg_aagc_int_en_pos 6 | ||
| 107 | #define reg_aagc_int_en_len 1 | ||
| 108 | #define reg_aagc_int_en_lsb 0 | ||
| 109 | #define xd_p_reg_aagc_lock_change_flag 0xA001 | ||
| 110 | #define reg_aagc_lock_change_flag_pos 7 | ||
| 111 | #define reg_aagc_lock_change_flag_len 1 | ||
| 112 | #define reg_aagc_lock_change_flag_lsb 0 | ||
| 113 | #define xd_p_reg_aagc_rf_loop_bw_scale_acquire 0xA002 | ||
| 114 | #define reg_aagc_rf_loop_bw_scale_acquire_pos 0 | ||
| 115 | #define reg_aagc_rf_loop_bw_scale_acquire_len 5 | ||
| 116 | #define reg_aagc_rf_loop_bw_scale_acquire_lsb 0 | ||
| 117 | #define xd_p_reg_aagc_rf_loop_bw_scale_track 0xA003 | ||
| 118 | #define reg_aagc_rf_loop_bw_scale_track_pos 0 | ||
| 119 | #define reg_aagc_rf_loop_bw_scale_track_len 5 | ||
| 120 | #define reg_aagc_rf_loop_bw_scale_track_lsb 0 | ||
| 121 | #define xd_p_reg_aagc_if_loop_bw_scale_acquire 0xA004 | ||
| 122 | #define reg_aagc_if_loop_bw_scale_acquire_pos 0 | ||
| 123 | #define reg_aagc_if_loop_bw_scale_acquire_len 5 | ||
| 124 | #define reg_aagc_if_loop_bw_scale_acquire_lsb 0 | ||
| 125 | #define xd_p_reg_aagc_if_loop_bw_scale_track 0xA005 | ||
| 126 | #define reg_aagc_if_loop_bw_scale_track_pos 0 | ||
| 127 | #define reg_aagc_if_loop_bw_scale_track_len 5 | ||
| 128 | #define reg_aagc_if_loop_bw_scale_track_lsb 0 | ||
| 129 | #define xd_p_reg_aagc_max_rf_agc_7_0 0xA006 | ||
| 130 | #define reg_aagc_max_rf_agc_7_0_pos 0 | ||
| 131 | #define reg_aagc_max_rf_agc_7_0_len 8 | ||
| 132 | #define reg_aagc_max_rf_agc_7_0_lsb 0 | ||
| 133 | #define xd_p_reg_aagc_max_rf_agc_9_8 0xA007 | ||
| 134 | #define reg_aagc_max_rf_agc_9_8_pos 0 | ||
| 135 | #define reg_aagc_max_rf_agc_9_8_len 2 | ||
| 136 | #define reg_aagc_max_rf_agc_9_8_lsb 8 | ||
| 137 | #define xd_p_reg_aagc_min_rf_agc_7_0 0xA008 | ||
| 138 | #define reg_aagc_min_rf_agc_7_0_pos 0 | ||
| 139 | #define reg_aagc_min_rf_agc_7_0_len 8 | ||
| 140 | #define reg_aagc_min_rf_agc_7_0_lsb 0 | ||
| 141 | #define xd_p_reg_aagc_min_rf_agc_9_8 0xA009 | ||
| 142 | #define reg_aagc_min_rf_agc_9_8_pos 0 | ||
| 143 | #define reg_aagc_min_rf_agc_9_8_len 2 | ||
| 144 | #define reg_aagc_min_rf_agc_9_8_lsb 8 | ||
| 145 | #define xd_p_reg_aagc_max_if_agc_7_0 0xA00A | ||
| 146 | #define reg_aagc_max_if_agc_7_0_pos 0 | ||
| 147 | #define reg_aagc_max_if_agc_7_0_len 8 | ||
| 148 | #define reg_aagc_max_if_agc_7_0_lsb 0 | ||
| 149 | #define xd_p_reg_aagc_max_if_agc_9_8 0xA00B | ||
| 150 | #define reg_aagc_max_if_agc_9_8_pos 0 | ||
| 151 | #define reg_aagc_max_if_agc_9_8_len 2 | ||
| 152 | #define reg_aagc_max_if_agc_9_8_lsb 8 | ||
| 153 | #define xd_p_reg_aagc_min_if_agc_7_0 0xA00C | ||
| 154 | #define reg_aagc_min_if_agc_7_0_pos 0 | ||
| 155 | #define reg_aagc_min_if_agc_7_0_len 8 | ||
| 156 | #define reg_aagc_min_if_agc_7_0_lsb 0 | ||
| 157 | #define xd_p_reg_aagc_min_if_agc_9_8 0xA00D | ||
| 158 | #define reg_aagc_min_if_agc_9_8_pos 0 | ||
| 159 | #define reg_aagc_min_if_agc_9_8_len 2 | ||
| 160 | #define reg_aagc_min_if_agc_9_8_lsb 8 | ||
| 161 | #define xd_p_reg_aagc_lock_sample_scale 0xA00E | ||
| 162 | #define reg_aagc_lock_sample_scale_pos 0 | ||
| 163 | #define reg_aagc_lock_sample_scale_len 5 | ||
| 164 | #define reg_aagc_lock_sample_scale_lsb 0 | ||
| 165 | #define xd_p_reg_aagc_rf_agc_lock_scale_acquire 0xA00F | ||
| 166 | #define reg_aagc_rf_agc_lock_scale_acquire_pos 0 | ||
| 167 | #define reg_aagc_rf_agc_lock_scale_acquire_len 3 | ||
| 168 | #define reg_aagc_rf_agc_lock_scale_acquire_lsb 0 | ||
| 169 | #define xd_p_reg_aagc_rf_agc_lock_scale_track 0xA00F | ||
| 170 | #define reg_aagc_rf_agc_lock_scale_track_pos 3 | ||
| 171 | #define reg_aagc_rf_agc_lock_scale_track_len 3 | ||
| 172 | #define reg_aagc_rf_agc_lock_scale_track_lsb 0 | ||
| 173 | #define xd_p_reg_aagc_if_agc_lock_scale_acquire 0xA010 | ||
| 174 | #define reg_aagc_if_agc_lock_scale_acquire_pos 0 | ||
| 175 | #define reg_aagc_if_agc_lock_scale_acquire_len 3 | ||
| 176 | #define reg_aagc_if_agc_lock_scale_acquire_lsb 0 | ||
| 177 | #define xd_p_reg_aagc_if_agc_lock_scale_track 0xA010 | ||
| 178 | #define reg_aagc_if_agc_lock_scale_track_pos 3 | ||
| 179 | #define reg_aagc_if_agc_lock_scale_track_len 3 | ||
| 180 | #define reg_aagc_if_agc_lock_scale_track_lsb 0 | ||
| 181 | #define xd_p_reg_aagc_rf_top_numerator_7_0 0xA011 | ||
| 182 | #define reg_aagc_rf_top_numerator_7_0_pos 0 | ||
| 183 | #define reg_aagc_rf_top_numerator_7_0_len 8 | ||
| 184 | #define reg_aagc_rf_top_numerator_7_0_lsb 0 | ||
| 185 | #define xd_p_reg_aagc_rf_top_numerator_9_8 0xA012 | ||
| 186 | #define reg_aagc_rf_top_numerator_9_8_pos 0 | ||
| 187 | #define reg_aagc_rf_top_numerator_9_8_len 2 | ||
| 188 | #define reg_aagc_rf_top_numerator_9_8_lsb 8 | ||
| 189 | #define xd_p_reg_aagc_if_top_numerator_7_0 0xA013 | ||
| 190 | #define reg_aagc_if_top_numerator_7_0_pos 0 | ||
| 191 | #define reg_aagc_if_top_numerator_7_0_len 8 | ||
| 192 | #define reg_aagc_if_top_numerator_7_0_lsb 0 | ||
| 193 | #define xd_p_reg_aagc_if_top_numerator_9_8 0xA014 | ||
| 194 | #define reg_aagc_if_top_numerator_9_8_pos 0 | ||
| 195 | #define reg_aagc_if_top_numerator_9_8_len 2 | ||
| 196 | #define reg_aagc_if_top_numerator_9_8_lsb 8 | ||
| 197 | #define xd_p_reg_aagc_adc_out_desired_7_0 0xA015 | ||
| 198 | #define reg_aagc_adc_out_desired_7_0_pos 0 | ||
| 199 | #define reg_aagc_adc_out_desired_7_0_len 8 | ||
| 200 | #define reg_aagc_adc_out_desired_7_0_lsb 0 | ||
| 201 | #define xd_p_reg_aagc_adc_out_desired_8 0xA016 | ||
| 202 | #define reg_aagc_adc_out_desired_8_pos 0 | ||
| 203 | #define reg_aagc_adc_out_desired_8_len 1 | ||
| 204 | #define reg_aagc_adc_out_desired_8_lsb 0 | ||
| 205 | #define xd_p_reg_aagc_fixed_gain 0xA016 | ||
| 206 | #define reg_aagc_fixed_gain_pos 3 | ||
| 207 | #define reg_aagc_fixed_gain_len 1 | ||
| 208 | #define reg_aagc_fixed_gain_lsb 0 | ||
| 209 | #define xd_p_reg_aagc_lock_count_th 0xA016 | ||
| 210 | #define reg_aagc_lock_count_th_pos 4 | ||
| 211 | #define reg_aagc_lock_count_th_len 4 | ||
| 212 | #define reg_aagc_lock_count_th_lsb 0 | ||
| 213 | #define xd_p_reg_aagc_fixed_rf_agc_control_7_0 0xA017 | ||
| 214 | #define reg_aagc_fixed_rf_agc_control_7_0_pos 0 | ||
| 215 | #define reg_aagc_fixed_rf_agc_control_7_0_len 8 | ||
| 216 | #define reg_aagc_fixed_rf_agc_control_7_0_lsb 0 | ||
| 217 | #define xd_p_reg_aagc_fixed_rf_agc_control_15_8 0xA018 | ||
| 218 | #define reg_aagc_fixed_rf_agc_control_15_8_pos 0 | ||
| 219 | #define reg_aagc_fixed_rf_agc_control_15_8_len 8 | ||
| 220 | #define reg_aagc_fixed_rf_agc_control_15_8_lsb 8 | ||
| 221 | #define xd_p_reg_aagc_fixed_rf_agc_control_23_16 0xA019 | ||
| 222 | #define reg_aagc_fixed_rf_agc_control_23_16_pos 0 | ||
| 223 | #define reg_aagc_fixed_rf_agc_control_23_16_len 8 | ||
| 224 | #define reg_aagc_fixed_rf_agc_control_23_16_lsb 16 | ||
| 225 | #define xd_p_reg_aagc_fixed_rf_agc_control_30_24 0xA01A | ||
| 226 | #define reg_aagc_fixed_rf_agc_control_30_24_pos 0 | ||
| 227 | #define reg_aagc_fixed_rf_agc_control_30_24_len 7 | ||
| 228 | #define reg_aagc_fixed_rf_agc_control_30_24_lsb 24 | ||
| 229 | #define xd_p_reg_aagc_fixed_if_agc_control_7_0 0xA01B | ||
| 230 | #define reg_aagc_fixed_if_agc_control_7_0_pos 0 | ||
| 231 | #define reg_aagc_fixed_if_agc_control_7_0_len 8 | ||
| 232 | #define reg_aagc_fixed_if_agc_control_7_0_lsb 0 | ||
| 233 | #define xd_p_reg_aagc_fixed_if_agc_control_15_8 0xA01C | ||
| 234 | #define reg_aagc_fixed_if_agc_control_15_8_pos 0 | ||
| 235 | #define reg_aagc_fixed_if_agc_control_15_8_len 8 | ||
| 236 | #define reg_aagc_fixed_if_agc_control_15_8_lsb 8 | ||
| 237 | #define xd_p_reg_aagc_fixed_if_agc_control_23_16 0xA01D | ||
| 238 | #define reg_aagc_fixed_if_agc_control_23_16_pos 0 | ||
| 239 | #define reg_aagc_fixed_if_agc_control_23_16_len 8 | ||
| 240 | #define reg_aagc_fixed_if_agc_control_23_16_lsb 16 | ||
| 241 | #define xd_p_reg_aagc_fixed_if_agc_control_30_24 0xA01E | ||
| 242 | #define reg_aagc_fixed_if_agc_control_30_24_pos 0 | ||
| 243 | #define reg_aagc_fixed_if_agc_control_30_24_len 7 | ||
| 244 | #define reg_aagc_fixed_if_agc_control_30_24_lsb 24 | ||
| 245 | #define xd_p_reg_aagc_rf_agc_unlock_numerator 0xA01F | ||
| 246 | #define reg_aagc_rf_agc_unlock_numerator_pos 0 | ||
| 247 | #define reg_aagc_rf_agc_unlock_numerator_len 6 | ||
| 248 | #define reg_aagc_rf_agc_unlock_numerator_lsb 0 | ||
| 249 | #define xd_p_reg_aagc_if_agc_unlock_numerator 0xA020 | ||
| 250 | #define reg_aagc_if_agc_unlock_numerator_pos 0 | ||
| 251 | #define reg_aagc_if_agc_unlock_numerator_len 6 | ||
| 252 | #define reg_aagc_if_agc_unlock_numerator_lsb 0 | ||
| 253 | #define xd_p_reg_unplug_th 0xA021 | ||
| 254 | #define reg_unplug_th_pos 0 | ||
| 255 | #define reg_unplug_th_len 8 | ||
| 256 | #define reg_aagc_rf_x0_lsb 0 | ||
| 257 | #define xd_p_reg_weak_signal_rfagc_thr 0xA022 | ||
| 258 | #define reg_weak_signal_rfagc_thr_pos 0 | ||
| 259 | #define reg_weak_signal_rfagc_thr_len 8 | ||
| 260 | #define reg_weak_signal_rfagc_thr_lsb 0 | ||
| 261 | #define xd_p_reg_unplug_rf_gain_th 0xA023 | ||
| 262 | #define reg_unplug_rf_gain_th_pos 0 | ||
| 263 | #define reg_unplug_rf_gain_th_len 8 | ||
| 264 | #define reg_unplug_rf_gain_th_lsb 0 | ||
| 265 | #define xd_p_reg_unplug_dtop_rf_gain_th 0xA024 | ||
| 266 | #define reg_unplug_dtop_rf_gain_th_pos 0 | ||
| 267 | #define reg_unplug_dtop_rf_gain_th_len 8 | ||
| 268 | #define reg_unplug_dtop_rf_gain_th_lsb 0 | ||
| 269 | #define xd_p_reg_unplug_dtop_if_gain_th 0xA025 | ||
| 270 | #define reg_unplug_dtop_if_gain_th_pos 0 | ||
| 271 | #define reg_unplug_dtop_if_gain_th_len 8 | ||
| 272 | #define reg_unplug_dtop_if_gain_th_lsb 0 | ||
| 273 | #define xd_p_reg_top_recover_at_unplug_en 0xA026 | ||
| 274 | #define reg_top_recover_at_unplug_en_pos 0 | ||
| 275 | #define reg_top_recover_at_unplug_en_len 1 | ||
| 276 | #define reg_top_recover_at_unplug_en_lsb 0 | ||
| 277 | #define xd_p_reg_aagc_rf_x6 0xA027 | ||
| 278 | #define reg_aagc_rf_x6_pos 0 | ||
| 279 | #define reg_aagc_rf_x6_len 8 | ||
| 280 | #define reg_aagc_rf_x6_lsb 0 | ||
| 281 | #define xd_p_reg_aagc_rf_x7 0xA028 | ||
| 282 | #define reg_aagc_rf_x7_pos 0 | ||
| 283 | #define reg_aagc_rf_x7_len 8 | ||
| 284 | #define reg_aagc_rf_x7_lsb 0 | ||
| 285 | #define xd_p_reg_aagc_rf_x8 0xA029 | ||
| 286 | #define reg_aagc_rf_x8_pos 0 | ||
| 287 | #define reg_aagc_rf_x8_len 8 | ||
| 288 | #define reg_aagc_rf_x8_lsb 0 | ||
| 289 | #define xd_p_reg_aagc_rf_x9 0xA02A | ||
| 290 | #define reg_aagc_rf_x9_pos 0 | ||
| 291 | #define reg_aagc_rf_x9_len 8 | ||
| 292 | #define reg_aagc_rf_x9_lsb 0 | ||
| 293 | #define xd_p_reg_aagc_rf_x10 0xA02B | ||
| 294 | #define reg_aagc_rf_x10_pos 0 | ||
| 295 | #define reg_aagc_rf_x10_len 8 | ||
| 296 | #define reg_aagc_rf_x10_lsb 0 | ||
| 297 | #define xd_p_reg_aagc_rf_x11 0xA02C | ||
| 298 | #define reg_aagc_rf_x11_pos 0 | ||
| 299 | #define reg_aagc_rf_x11_len 8 | ||
| 300 | #define reg_aagc_rf_x11_lsb 0 | ||
| 301 | #define xd_p_reg_aagc_rf_x12 0xA02D | ||
| 302 | #define reg_aagc_rf_x12_pos 0 | ||
| 303 | #define reg_aagc_rf_x12_len 8 | ||
| 304 | #define reg_aagc_rf_x12_lsb 0 | ||
| 305 | #define xd_p_reg_aagc_rf_x13 0xA02E | ||
| 306 | #define reg_aagc_rf_x13_pos 0 | ||
| 307 | #define reg_aagc_rf_x13_len 8 | ||
| 308 | #define reg_aagc_rf_x13_lsb 0 | ||
| 309 | #define xd_p_reg_aagc_if_x0 0xA02F | ||
| 310 | #define reg_aagc_if_x0_pos 0 | ||
| 311 | #define reg_aagc_if_x0_len 8 | ||
| 312 | #define reg_aagc_if_x0_lsb 0 | ||
| 313 | #define xd_p_reg_aagc_if_x1 0xA030 | ||
| 314 | #define reg_aagc_if_x1_pos 0 | ||
| 315 | #define reg_aagc_if_x1_len 8 | ||
| 316 | #define reg_aagc_if_x1_lsb 0 | ||
| 317 | #define xd_p_reg_aagc_if_x2 0xA031 | ||
| 318 | #define reg_aagc_if_x2_pos 0 | ||
| 319 | #define reg_aagc_if_x2_len 8 | ||
| 320 | #define reg_aagc_if_x2_lsb 0 | ||
| 321 | #define xd_p_reg_aagc_if_x3 0xA032 | ||
| 322 | #define reg_aagc_if_x3_pos 0 | ||
| 323 | #define reg_aagc_if_x3_len 8 | ||
| 324 | #define reg_aagc_if_x3_lsb 0 | ||
| 325 | #define xd_p_reg_aagc_if_x4 0xA033 | ||
| 326 | #define reg_aagc_if_x4_pos 0 | ||
| 327 | #define reg_aagc_if_x4_len 8 | ||
| 328 | #define reg_aagc_if_x4_lsb 0 | ||
| 329 | #define xd_p_reg_aagc_if_x5 0xA034 | ||
| 330 | #define reg_aagc_if_x5_pos 0 | ||
| 331 | #define reg_aagc_if_x5_len 8 | ||
| 332 | #define reg_aagc_if_x5_lsb 0 | ||
| 333 | #define xd_p_reg_aagc_if_x6 0xA035 | ||
| 334 | #define reg_aagc_if_x6_pos 0 | ||
| 335 | #define reg_aagc_if_x6_len 8 | ||
| 336 | #define reg_aagc_if_x6_lsb 0 | ||
| 337 | #define xd_p_reg_aagc_if_x7 0xA036 | ||
| 338 | #define reg_aagc_if_x7_pos 0 | ||
| 339 | #define reg_aagc_if_x7_len 8 | ||
| 340 | #define reg_aagc_if_x7_lsb 0 | ||
| 341 | #define xd_p_reg_aagc_if_x8 0xA037 | ||
| 342 | #define reg_aagc_if_x8_pos 0 | ||
| 343 | #define reg_aagc_if_x8_len 8 | ||
| 344 | #define reg_aagc_if_x8_lsb 0 | ||
| 345 | #define xd_p_reg_aagc_if_x9 0xA038 | ||
| 346 | #define reg_aagc_if_x9_pos 0 | ||
| 347 | #define reg_aagc_if_x9_len 8 | ||
| 348 | #define reg_aagc_if_x9_lsb 0 | ||
| 349 | #define xd_p_reg_aagc_if_x10 0xA039 | ||
| 350 | #define reg_aagc_if_x10_pos 0 | ||
| 351 | #define reg_aagc_if_x10_len 8 | ||
| 352 | #define reg_aagc_if_x10_lsb 0 | ||
| 353 | #define xd_p_reg_aagc_if_x11 0xA03A | ||
| 354 | #define reg_aagc_if_x11_pos 0 | ||
| 355 | #define reg_aagc_if_x11_len 8 | ||
| 356 | #define reg_aagc_if_x11_lsb 0 | ||
| 357 | #define xd_p_reg_aagc_if_x12 0xA03B | ||
| 358 | #define reg_aagc_if_x12_pos 0 | ||
| 359 | #define reg_aagc_if_x12_len 8 | ||
| 360 | #define reg_aagc_if_x12_lsb 0 | ||
| 361 | #define xd_p_reg_aagc_if_x13 0xA03C | ||
| 362 | #define reg_aagc_if_x13_pos 0 | ||
| 363 | #define reg_aagc_if_x13_len 8 | ||
| 364 | #define reg_aagc_if_x13_lsb 0 | ||
| 365 | #define xd_p_reg_aagc_min_rf_ctl_8bit_for_dca 0xA03D | ||
| 366 | #define reg_aagc_min_rf_ctl_8bit_for_dca_pos 0 | ||
| 367 | #define reg_aagc_min_rf_ctl_8bit_for_dca_len 8 | ||
| 368 | #define reg_aagc_min_rf_ctl_8bit_for_dca_lsb 0 | ||
| 369 | #define xd_p_reg_aagc_min_if_ctl_8bit_for_dca 0xA03E | ||
| 370 | #define reg_aagc_min_if_ctl_8bit_for_dca_pos 0 | ||
| 371 | #define reg_aagc_min_if_ctl_8bit_for_dca_len 8 | ||
| 372 | #define reg_aagc_min_if_ctl_8bit_for_dca_lsb 0 | ||
| 373 | #define xd_r_reg_aagc_total_gain_7_0 0xA070 | ||
| 374 | #define reg_aagc_total_gain_7_0_pos 0 | ||
| 375 | #define reg_aagc_total_gain_7_0_len 8 | ||
| 376 | #define reg_aagc_total_gain_7_0_lsb 0 | ||
| 377 | #define xd_r_reg_aagc_total_gain_15_8 0xA071 | ||
| 378 | #define reg_aagc_total_gain_15_8_pos 0 | ||
| 379 | #define reg_aagc_total_gain_15_8_len 8 | ||
| 380 | #define reg_aagc_total_gain_15_8_lsb 8 | ||
| 381 | #define xd_p_reg_aagc_in_sat_cnt_7_0 0xA074 | ||
| 382 | #define reg_aagc_in_sat_cnt_7_0_pos 0 | ||
| 383 | #define reg_aagc_in_sat_cnt_7_0_len 8 | ||
| 384 | #define reg_aagc_in_sat_cnt_7_0_lsb 0 | ||
| 385 | #define xd_p_reg_aagc_in_sat_cnt_15_8 0xA075 | ||
| 386 | #define reg_aagc_in_sat_cnt_15_8_pos 0 | ||
| 387 | #define reg_aagc_in_sat_cnt_15_8_len 8 | ||
| 388 | #define reg_aagc_in_sat_cnt_15_8_lsb 8 | ||
| 389 | #define xd_p_reg_aagc_in_sat_cnt_23_16 0xA076 | ||
| 390 | #define reg_aagc_in_sat_cnt_23_16_pos 0 | ||
| 391 | #define reg_aagc_in_sat_cnt_23_16_len 8 | ||
| 392 | #define reg_aagc_in_sat_cnt_23_16_lsb 16 | ||
| 393 | #define xd_p_reg_aagc_in_sat_cnt_31_24 0xA077 | ||
| 394 | #define reg_aagc_in_sat_cnt_31_24_pos 0 | ||
| 395 | #define reg_aagc_in_sat_cnt_31_24_len 8 | ||
| 396 | #define reg_aagc_in_sat_cnt_31_24_lsb 24 | ||
| 397 | #define xd_r_reg_aagc_digital_rf_volt_7_0 0xA078 | ||
| 398 | #define reg_aagc_digital_rf_volt_7_0_pos 0 | ||
| 399 | #define reg_aagc_digital_rf_volt_7_0_len 8 | ||
| 400 | #define reg_aagc_digital_rf_volt_7_0_lsb 0 | ||
| 401 | #define xd_r_reg_aagc_digital_rf_volt_9_8 0xA079 | ||
| 402 | #define reg_aagc_digital_rf_volt_9_8_pos 0 | ||
| 403 | #define reg_aagc_digital_rf_volt_9_8_len 2 | ||
| 404 | #define reg_aagc_digital_rf_volt_9_8_lsb 8 | ||
| 405 | #define xd_r_reg_aagc_digital_if_volt_7_0 0xA07A | ||
| 406 | #define reg_aagc_digital_if_volt_7_0_pos 0 | ||
| 407 | #define reg_aagc_digital_if_volt_7_0_len 8 | ||
| 408 | #define reg_aagc_digital_if_volt_7_0_lsb 0 | ||
| 409 | #define xd_r_reg_aagc_digital_if_volt_9_8 0xA07B | ||
| 410 | #define reg_aagc_digital_if_volt_9_8_pos 0 | ||
| 411 | #define reg_aagc_digital_if_volt_9_8_len 2 | ||
| 412 | #define reg_aagc_digital_if_volt_9_8_lsb 8 | ||
| 413 | #define xd_r_reg_aagc_rf_gain 0xA07C | ||
| 414 | #define reg_aagc_rf_gain_pos 0 | ||
| 415 | #define reg_aagc_rf_gain_len 8 | ||
| 416 | #define reg_aagc_rf_gain_lsb 0 | ||
| 417 | #define xd_r_reg_aagc_if_gain 0xA07D | ||
| 418 | #define reg_aagc_if_gain_pos 0 | ||
| 419 | #define reg_aagc_if_gain_len 8 | ||
| 420 | #define reg_aagc_if_gain_lsb 0 | ||
| 421 | #define xd_p_tinr_imp_indicator 0xA080 | ||
| 422 | #define tinr_imp_indicator_pos 0 | ||
| 423 | #define tinr_imp_indicator_len 2 | ||
| 424 | #define tinr_imp_indicator_lsb 0 | ||
| 425 | #define xd_p_reg_tinr_fifo_size 0xA080 | ||
| 426 | #define reg_tinr_fifo_size_pos 2 | ||
| 427 | #define reg_tinr_fifo_size_len 5 | ||
| 428 | #define reg_tinr_fifo_size_lsb 0 | ||
| 429 | #define xd_p_reg_tinr_saturation_cnt_th 0xA081 | ||
| 430 | #define reg_tinr_saturation_cnt_th_pos 0 | ||
| 431 | #define reg_tinr_saturation_cnt_th_len 4 | ||
| 432 | #define reg_tinr_saturation_cnt_th_lsb 0 | ||
| 433 | #define xd_p_reg_tinr_saturation_th_3_0 0xA081 | ||
| 434 | #define reg_tinr_saturation_th_3_0_pos 4 | ||
| 435 | #define reg_tinr_saturation_th_3_0_len 4 | ||
| 436 | #define reg_tinr_saturation_th_3_0_lsb 0 | ||
| 437 | #define xd_p_reg_tinr_saturation_th_8_4 0xA082 | ||
| 438 | #define reg_tinr_saturation_th_8_4_pos 0 | ||
| 439 | #define reg_tinr_saturation_th_8_4_len 5 | ||
| 440 | #define reg_tinr_saturation_th_8_4_lsb 4 | ||
| 441 | #define xd_p_reg_tinr_imp_duration_th_2k_7_0 0xA083 | ||
| 442 | #define reg_tinr_imp_duration_th_2k_7_0_pos 0 | ||
| 443 | #define reg_tinr_imp_duration_th_2k_7_0_len 8 | ||
| 444 | #define reg_tinr_imp_duration_th_2k_7_0_lsb 0 | ||
| 445 | #define xd_p_reg_tinr_imp_duration_th_2k_8 0xA084 | ||
| 446 | #define reg_tinr_imp_duration_th_2k_8_pos 0 | ||
| 447 | #define reg_tinr_imp_duration_th_2k_8_len 1 | ||
| 448 | #define reg_tinr_imp_duration_th_2k_8_lsb 0 | ||
| 449 | #define xd_p_reg_tinr_imp_duration_th_8k_7_0 0xA085 | ||
| 450 | #define reg_tinr_imp_duration_th_8k_7_0_pos 0 | ||
| 451 | #define reg_tinr_imp_duration_th_8k_7_0_len 8 | ||
| 452 | #define reg_tinr_imp_duration_th_8k_7_0_lsb 0 | ||
| 453 | #define xd_p_reg_tinr_imp_duration_th_8k_10_8 0xA086 | ||
| 454 | #define reg_tinr_imp_duration_th_8k_10_8_pos 0 | ||
| 455 | #define reg_tinr_imp_duration_th_8k_10_8_len 3 | ||
| 456 | #define reg_tinr_imp_duration_th_8k_10_8_lsb 8 | ||
| 457 | #define xd_p_reg_tinr_freq_ratio_6m_7_0 0xA087 | ||
| 458 | #define reg_tinr_freq_ratio_6m_7_0_pos 0 | ||
| 459 | #define reg_tinr_freq_ratio_6m_7_0_len 8 | ||
| 460 | #define reg_tinr_freq_ratio_6m_7_0_lsb 0 | ||
| 461 | #define xd_p_reg_tinr_freq_ratio_6m_12_8 0xA088 | ||
| 462 | #define reg_tinr_freq_ratio_6m_12_8_pos 0 | ||
| 463 | #define reg_tinr_freq_ratio_6m_12_8_len 5 | ||
| 464 | #define reg_tinr_freq_ratio_6m_12_8_lsb 8 | ||
| 465 | #define xd_p_reg_tinr_freq_ratio_7m_7_0 0xA089 | ||
| 466 | #define reg_tinr_freq_ratio_7m_7_0_pos 0 | ||
| 467 | #define reg_tinr_freq_ratio_7m_7_0_len 8 | ||
| 468 | #define reg_tinr_freq_ratio_7m_7_0_lsb 0 | ||
| 469 | #define xd_p_reg_tinr_freq_ratio_7m_12_8 0xA08A | ||
| 470 | #define reg_tinr_freq_ratio_7m_12_8_pos 0 | ||
| 471 | #define reg_tinr_freq_ratio_7m_12_8_len 5 | ||
| 472 | #define reg_tinr_freq_ratio_7m_12_8_lsb 8 | ||
| 473 | #define xd_p_reg_tinr_freq_ratio_8m_7_0 0xA08B | ||
| 474 | #define reg_tinr_freq_ratio_8m_7_0_pos 0 | ||
| 475 | #define reg_tinr_freq_ratio_8m_7_0_len 8 | ||
| 476 | #define reg_tinr_freq_ratio_8m_7_0_lsb 0 | ||
| 477 | #define xd_p_reg_tinr_freq_ratio_8m_12_8 0xA08C | ||
| 478 | #define reg_tinr_freq_ratio_8m_12_8_pos 0 | ||
| 479 | #define reg_tinr_freq_ratio_8m_12_8_len 5 | ||
| 480 | #define reg_tinr_freq_ratio_8m_12_8_lsb 8 | ||
| 481 | #define xd_p_reg_tinr_imp_duration_th_low_2k 0xA08D | ||
| 482 | #define reg_tinr_imp_duration_th_low_2k_pos 0 | ||
| 483 | #define reg_tinr_imp_duration_th_low_2k_len 8 | ||
| 484 | #define reg_tinr_imp_duration_th_low_2k_lsb 0 | ||
| 485 | #define xd_p_reg_tinr_imp_duration_th_low_8k 0xA08E | ||
| 486 | #define reg_tinr_imp_duration_th_low_8k_pos 0 | ||
| 487 | #define reg_tinr_imp_duration_th_low_8k_len 8 | ||
| 488 | #define reg_tinr_imp_duration_th_low_8k_lsb 0 | ||
| 489 | #define xd_r_reg_tinr_counter_7_0 0xA090 | ||
| 490 | #define reg_tinr_counter_7_0_pos 0 | ||
| 491 | #define reg_tinr_counter_7_0_len 8 | ||
| 492 | #define reg_tinr_counter_7_0_lsb 0 | ||
| 493 | #define xd_r_reg_tinr_counter_15_8 0xA091 | ||
| 494 | #define reg_tinr_counter_15_8_pos 0 | ||
| 495 | #define reg_tinr_counter_15_8_len 8 | ||
| 496 | #define reg_tinr_counter_15_8_lsb 8 | ||
| 497 | #define xd_p_reg_tinr_adative_tinr_en 0xA093 | ||
| 498 | #define reg_tinr_adative_tinr_en_pos 0 | ||
| 499 | #define reg_tinr_adative_tinr_en_len 1 | ||
| 500 | #define reg_tinr_adative_tinr_en_lsb 0 | ||
| 501 | #define xd_p_reg_tinr_peak_fifo_size 0xA093 | ||
| 502 | #define reg_tinr_peak_fifo_size_pos 1 | ||
| 503 | #define reg_tinr_peak_fifo_size_len 5 | ||
| 504 | #define reg_tinr_peak_fifo_size_lsb 0 | ||
| 505 | #define xd_p_reg_tinr_counter_rst 0xA093 | ||
| 506 | #define reg_tinr_counter_rst_pos 6 | ||
| 507 | #define reg_tinr_counter_rst_len 1 | ||
| 508 | #define reg_tinr_counter_rst_lsb 0 | ||
| 509 | #define xd_p_reg_tinr_search_period_7_0 0xA094 | ||
| 510 | #define reg_tinr_search_period_7_0_pos 0 | ||
| 511 | #define reg_tinr_search_period_7_0_len 8 | ||
| 512 | #define reg_tinr_search_period_7_0_lsb 0 | ||
| 513 | #define xd_p_reg_tinr_search_period_15_8 0xA095 | ||
| 514 | #define reg_tinr_search_period_15_8_pos 0 | ||
| 515 | #define reg_tinr_search_period_15_8_len 8 | ||
| 516 | #define reg_tinr_search_period_15_8_lsb 8 | ||
| 517 | #define xd_p_reg_ccifs_fcw_7_0 0xA0A0 | ||
| 518 | #define reg_ccifs_fcw_7_0_pos 0 | ||
| 519 | #define reg_ccifs_fcw_7_0_len 8 | ||
| 520 | #define reg_ccifs_fcw_7_0_lsb 0 | ||
| 521 | #define xd_p_reg_ccifs_fcw_12_8 0xA0A1 | ||
| 522 | #define reg_ccifs_fcw_12_8_pos 0 | ||
| 523 | #define reg_ccifs_fcw_12_8_len 5 | ||
| 524 | #define reg_ccifs_fcw_12_8_lsb 8 | ||
| 525 | #define xd_p_reg_ccifs_spec_inv 0xA0A1 | ||
| 526 | #define reg_ccifs_spec_inv_pos 5 | ||
| 527 | #define reg_ccifs_spec_inv_len 1 | ||
| 528 | #define reg_ccifs_spec_inv_lsb 0 | ||
| 529 | #define xd_p_reg_gp_trigger 0xA0A2 | ||
| 530 | #define reg_gp_trigger_pos 0 | ||
| 531 | #define reg_gp_trigger_len 1 | ||
| 532 | #define reg_gp_trigger_lsb 0 | ||
| 533 | #define xd_p_reg_trigger_sel 0xA0A2 | ||
| 534 | #define reg_trigger_sel_pos 1 | ||
| 535 | #define reg_trigger_sel_len 2 | ||
| 536 | #define reg_trigger_sel_lsb 0 | ||
| 537 | #define xd_p_reg_debug_ofdm 0xA0A2 | ||
| 538 | #define reg_debug_ofdm_pos 3 | ||
| 539 | #define reg_debug_ofdm_len 2 | ||
| 540 | #define reg_debug_ofdm_lsb 0 | ||
| 541 | #define xd_p_reg_trigger_module_sel 0xA0A3 | ||
| 542 | #define reg_trigger_module_sel_pos 0 | ||
| 543 | #define reg_trigger_module_sel_len 6 | ||
| 544 | #define reg_trigger_module_sel_lsb 0 | ||
| 545 | #define xd_p_reg_trigger_set_sel 0xA0A4 | ||
| 546 | #define reg_trigger_set_sel_pos 0 | ||
| 547 | #define reg_trigger_set_sel_len 6 | ||
| 548 | #define reg_trigger_set_sel_lsb 0 | ||
| 549 | #define xd_p_reg_fw_int_mask_n 0xA0A4 | ||
| 550 | #define reg_fw_int_mask_n_pos 6 | ||
| 551 | #define reg_fw_int_mask_n_len 1 | ||
| 552 | #define reg_fw_int_mask_n_lsb 0 | ||
| 553 | #define xd_p_reg_debug_group 0xA0A5 | ||
| 554 | #define reg_debug_group_pos 0 | ||
| 555 | #define reg_debug_group_len 4 | ||
| 556 | #define reg_debug_group_lsb 0 | ||
| 557 | #define xd_p_reg_odbg_clk_sel 0xA0A5 | ||
| 558 | #define reg_odbg_clk_sel_pos 4 | ||
| 559 | #define reg_odbg_clk_sel_len 2 | ||
| 560 | #define reg_odbg_clk_sel_lsb 0 | ||
| 561 | #define xd_p_reg_ccif_sc 0xA0C0 | ||
| 562 | #define reg_ccif_sc_pos 0 | ||
| 563 | #define reg_ccif_sc_len 4 | ||
| 564 | #define reg_ccif_sc_lsb 0 | ||
| 565 | #define xd_r_reg_ccif_saturate 0xA0C1 | ||
| 566 | #define reg_ccif_saturate_pos 0 | ||
| 567 | #define reg_ccif_saturate_len 2 | ||
| 568 | #define reg_ccif_saturate_lsb 0 | ||
| 569 | #define xd_r_reg_antif_saturate 0xA0C1 | ||
| 570 | #define reg_antif_saturate_pos 2 | ||
| 571 | #define reg_antif_saturate_len 4 | ||
| 572 | #define reg_antif_saturate_lsb 0 | ||
| 573 | #define xd_r_reg_acif_saturate 0xA0C2 | ||
| 574 | #define reg_acif_saturate_pos 0 | ||
| 575 | #define reg_acif_saturate_len 8 | ||
| 576 | #define reg_acif_saturate_lsb 0 | ||
| 577 | #define xd_p_reg_tmr_timer0_threshold_7_0 0xA0C8 | ||
| 578 | #define reg_tmr_timer0_threshold_7_0_pos 0 | ||
| 579 | #define reg_tmr_timer0_threshold_7_0_len 8 | ||
| 580 | #define reg_tmr_timer0_threshold_7_0_lsb 0 | ||
| 581 | #define xd_p_reg_tmr_timer0_threshold_15_8 0xA0C9 | ||
| 582 | #define reg_tmr_timer0_threshold_15_8_pos 0 | ||
| 583 | #define reg_tmr_timer0_threshold_15_8_len 8 | ||
| 584 | #define reg_tmr_timer0_threshold_15_8_lsb 8 | ||
| 585 | #define xd_p_reg_tmr_timer0_enable 0xA0CA | ||
| 586 | #define reg_tmr_timer0_enable_pos 0 | ||
| 587 | #define reg_tmr_timer0_enable_len 1 | ||
| 588 | #define reg_tmr_timer0_enable_lsb 0 | ||
| 589 | #define xd_p_reg_tmr_timer0_clk_sel 0xA0CA | ||
| 590 | #define reg_tmr_timer0_clk_sel_pos 1 | ||
| 591 | #define reg_tmr_timer0_clk_sel_len 1 | ||
| 592 | #define reg_tmr_timer0_clk_sel_lsb 0 | ||
| 593 | #define xd_p_reg_tmr_timer0_int 0xA0CA | ||
| 594 | #define reg_tmr_timer0_int_pos 2 | ||
| 595 | #define reg_tmr_timer0_int_len 1 | ||
| 596 | #define reg_tmr_timer0_int_lsb 0 | ||
| 597 | #define xd_p_reg_tmr_timer0_rst 0xA0CA | ||
| 598 | #define reg_tmr_timer0_rst_pos 3 | ||
| 599 | #define reg_tmr_timer0_rst_len 1 | ||
| 600 | #define reg_tmr_timer0_rst_lsb 0 | ||
| 601 | #define xd_r_reg_tmr_timer0_count_7_0 0xA0CB | ||
| 602 | #define reg_tmr_timer0_count_7_0_pos 0 | ||
| 603 | #define reg_tmr_timer0_count_7_0_len 8 | ||
| 604 | #define reg_tmr_timer0_count_7_0_lsb 0 | ||
| 605 | #define xd_r_reg_tmr_timer0_count_15_8 0xA0CC | ||
| 606 | #define reg_tmr_timer0_count_15_8_pos 0 | ||
| 607 | #define reg_tmr_timer0_count_15_8_len 8 | ||
| 608 | #define reg_tmr_timer0_count_15_8_lsb 8 | ||
| 609 | #define xd_p_reg_suspend 0xA0CD | ||
| 610 | #define reg_suspend_pos 0 | ||
| 611 | #define reg_suspend_len 1 | ||
| 612 | #define reg_suspend_lsb 0 | ||
| 613 | #define xd_p_reg_suspend_rdy 0xA0CD | ||
| 614 | #define reg_suspend_rdy_pos 1 | ||
| 615 | #define reg_suspend_rdy_len 1 | ||
| 616 | #define reg_suspend_rdy_lsb 0 | ||
| 617 | #define xd_p_reg_resume 0xA0CD | ||
| 618 | #define reg_resume_pos 2 | ||
| 619 | #define reg_resume_len 1 | ||
| 620 | #define reg_resume_lsb 0 | ||
| 621 | #define xd_p_reg_resume_rdy 0xA0CD | ||
| 622 | #define reg_resume_rdy_pos 3 | ||
| 623 | #define reg_resume_rdy_len 1 | ||
| 624 | #define reg_resume_rdy_lsb 0 | ||
| 625 | #define xd_p_reg_fmf 0xA0CE | ||
| 626 | #define reg_fmf_pos 0 | ||
| 627 | #define reg_fmf_len 8 | ||
| 628 | #define reg_fmf_lsb 0 | ||
| 629 | #define xd_p_ccid_accumulate_num_2k_7_0 0xA100 | ||
| 630 | #define ccid_accumulate_num_2k_7_0_pos 0 | ||
| 631 | #define ccid_accumulate_num_2k_7_0_len 8 | ||
| 632 | #define ccid_accumulate_num_2k_7_0_lsb 0 | ||
| 633 | #define xd_p_ccid_accumulate_num_2k_12_8 0xA101 | ||
| 634 | #define ccid_accumulate_num_2k_12_8_pos 0 | ||
| 635 | #define ccid_accumulate_num_2k_12_8_len 5 | ||
| 636 | #define ccid_accumulate_num_2k_12_8_lsb 8 | ||
| 637 | #define xd_p_ccid_accumulate_num_8k_7_0 0xA102 | ||
| 638 | #define ccid_accumulate_num_8k_7_0_pos 0 | ||
| 639 | #define ccid_accumulate_num_8k_7_0_len 8 | ||
| 640 | #define ccid_accumulate_num_8k_7_0_lsb 0 | ||
| 641 | #define xd_p_ccid_accumulate_num_8k_14_8 0xA103 | ||
| 642 | #define ccid_accumulate_num_8k_14_8_pos 0 | ||
| 643 | #define ccid_accumulate_num_8k_14_8_len 7 | ||
| 644 | #define ccid_accumulate_num_8k_14_8_lsb 8 | ||
| 645 | #define xd_p_ccid_desired_level_0 0xA103 | ||
| 646 | #define ccid_desired_level_0_pos 7 | ||
| 647 | #define ccid_desired_level_0_len 1 | ||
| 648 | #define ccid_desired_level_0_lsb 0 | ||
| 649 | #define xd_p_ccid_desired_level_8_1 0xA104 | ||
| 650 | #define ccid_desired_level_8_1_pos 0 | ||
| 651 | #define ccid_desired_level_8_1_len 8 | ||
| 652 | #define ccid_desired_level_8_1_lsb 1 | ||
| 653 | #define xd_p_ccid_apply_delay 0xA105 | ||
| 654 | #define ccid_apply_delay_pos 0 | ||
| 655 | #define ccid_apply_delay_len 7 | ||
| 656 | #define ccid_apply_delay_lsb 0 | ||
| 657 | #define xd_p_ccid_CCID_Threshold1 0xA106 | ||
| 658 | #define ccid_CCID_Threshold1_pos 0 | ||
| 659 | #define ccid_CCID_Threshold1_len 8 | ||
| 660 | #define ccid_CCID_Threshold1_lsb 0 | ||
| 661 | #define xd_p_ccid_CCID_Threshold2 0xA107 | ||
| 662 | #define ccid_CCID_Threshold2_pos 0 | ||
| 663 | #define ccid_CCID_Threshold2_len 8 | ||
| 664 | #define ccid_CCID_Threshold2_lsb 0 | ||
| 665 | #define xd_p_reg_ccid_gain_scale 0xA108 | ||
| 666 | #define reg_ccid_gain_scale_pos 0 | ||
| 667 | #define reg_ccid_gain_scale_len 4 | ||
| 668 | #define reg_ccid_gain_scale_lsb 0 | ||
| 669 | #define xd_p_reg_ccid2_passband_gain_set 0xA108 | ||
| 670 | #define reg_ccid2_passband_gain_set_pos 4 | ||
| 671 | #define reg_ccid2_passband_gain_set_len 4 | ||
| 672 | #define reg_ccid2_passband_gain_set_lsb 0 | ||
| 673 | #define xd_r_ccid_multiplier_7_0 0xA109 | ||
| 674 | #define ccid_multiplier_7_0_pos 0 | ||
| 675 | #define ccid_multiplier_7_0_len 8 | ||
| 676 | #define ccid_multiplier_7_0_lsb 0 | ||
| 677 | #define xd_r_ccid_multiplier_15_8 0xA10A | ||
| 678 | #define ccid_multiplier_15_8_pos 0 | ||
| 679 | #define ccid_multiplier_15_8_len 8 | ||
| 680 | #define ccid_multiplier_15_8_lsb 8 | ||
| 681 | #define xd_r_ccid_right_shift_bits 0xA10B | ||
| 682 | #define ccid_right_shift_bits_pos 0 | ||
| 683 | #define ccid_right_shift_bits_len 4 | ||
| 684 | #define ccid_right_shift_bits_lsb 0 | ||
| 685 | #define xd_r_reg_ccid_sx_7_0 0xA10C | ||
| 686 | #define reg_ccid_sx_7_0_pos 0 | ||
| 687 | #define reg_ccid_sx_7_0_len 8 | ||
| 688 | #define reg_ccid_sx_7_0_lsb 0 | ||
| 689 | #define xd_r_reg_ccid_sx_15_8 0xA10D | ||
| 690 | #define reg_ccid_sx_15_8_pos 0 | ||
| 691 | #define reg_ccid_sx_15_8_len 8 | ||
| 692 | #define reg_ccid_sx_15_8_lsb 8 | ||
| 693 | #define xd_r_reg_ccid_sx_21_16 0xA10E | ||
| 694 | #define reg_ccid_sx_21_16_pos 0 | ||
| 695 | #define reg_ccid_sx_21_16_len 6 | ||
| 696 | #define reg_ccid_sx_21_16_lsb 16 | ||
| 697 | #define xd_r_reg_ccid_sy_7_0 0xA110 | ||
| 698 | #define reg_ccid_sy_7_0_pos 0 | ||
| 699 | #define reg_ccid_sy_7_0_len 8 | ||
| 700 | #define reg_ccid_sy_7_0_lsb 0 | ||
| 701 | #define xd_r_reg_ccid_sy_15_8 0xA111 | ||
| 702 | #define reg_ccid_sy_15_8_pos 0 | ||
| 703 | #define reg_ccid_sy_15_8_len 8 | ||
| 704 | #define reg_ccid_sy_15_8_lsb 8 | ||
| 705 | #define xd_r_reg_ccid_sy_23_16 0xA112 | ||
| 706 | #define reg_ccid_sy_23_16_pos 0 | ||
| 707 | #define reg_ccid_sy_23_16_len 8 | ||
| 708 | #define reg_ccid_sy_23_16_lsb 16 | ||
| 709 | #define xd_r_reg_ccid2_sz_7_0 0xA114 | ||
| 710 | #define reg_ccid2_sz_7_0_pos 0 | ||
| 711 | #define reg_ccid2_sz_7_0_len 8 | ||
| 712 | #define reg_ccid2_sz_7_0_lsb 0 | ||
| 713 | #define xd_r_reg_ccid2_sz_15_8 0xA115 | ||
| 714 | #define reg_ccid2_sz_15_8_pos 0 | ||
| 715 | #define reg_ccid2_sz_15_8_len 8 | ||
| 716 | #define reg_ccid2_sz_15_8_lsb 8 | ||
| 717 | #define xd_r_reg_ccid2_sz_23_16 0xA116 | ||
| 718 | #define reg_ccid2_sz_23_16_pos 0 | ||
| 719 | #define reg_ccid2_sz_23_16_len 8 | ||
| 720 | #define reg_ccid2_sz_23_16_lsb 16 | ||
| 721 | #define xd_r_reg_ccid2_sz_25_24 0xA117 | ||
| 722 | #define reg_ccid2_sz_25_24_pos 0 | ||
| 723 | #define reg_ccid2_sz_25_24_len 2 | ||
| 724 | #define reg_ccid2_sz_25_24_lsb 24 | ||
| 725 | #define xd_r_reg_ccid2_sy_7_0 0xA118 | ||
| 726 | #define reg_ccid2_sy_7_0_pos 0 | ||
| 727 | #define reg_ccid2_sy_7_0_len 8 | ||
| 728 | #define reg_ccid2_sy_7_0_lsb 0 | ||
| 729 | #define xd_r_reg_ccid2_sy_15_8 0xA119 | ||
| 730 | #define reg_ccid2_sy_15_8_pos 0 | ||
| 731 | #define reg_ccid2_sy_15_8_len 8 | ||
| 732 | #define reg_ccid2_sy_15_8_lsb 8 | ||
| 733 | #define xd_r_reg_ccid2_sy_23_16 0xA11A | ||
| 734 | #define reg_ccid2_sy_23_16_pos 0 | ||
| 735 | #define reg_ccid2_sy_23_16_len 8 | ||
| 736 | #define reg_ccid2_sy_23_16_lsb 16 | ||
| 737 | #define xd_r_reg_ccid2_sy_25_24 0xA11B | ||
| 738 | #define reg_ccid2_sy_25_24_pos 0 | ||
| 739 | #define reg_ccid2_sy_25_24_len 2 | ||
| 740 | #define reg_ccid2_sy_25_24_lsb 24 | ||
| 741 | #define xd_p_dagc1_accumulate_num_2k_7_0 0xA120 | ||
| 742 | #define dagc1_accumulate_num_2k_7_0_pos 0 | ||
| 743 | #define dagc1_accumulate_num_2k_7_0_len 8 | ||
| 744 | #define dagc1_accumulate_num_2k_7_0_lsb 0 | ||
| 745 | #define xd_p_dagc1_accumulate_num_2k_12_8 0xA121 | ||
| 746 | #define dagc1_accumulate_num_2k_12_8_pos 0 | ||
| 747 | #define dagc1_accumulate_num_2k_12_8_len 5 | ||
| 748 | #define dagc1_accumulate_num_2k_12_8_lsb 8 | ||
| 749 | #define xd_p_dagc1_accumulate_num_8k_7_0 0xA122 | ||
| 750 | #define dagc1_accumulate_num_8k_7_0_pos 0 | ||
| 751 | #define dagc1_accumulate_num_8k_7_0_len 8 | ||
| 752 | #define dagc1_accumulate_num_8k_7_0_lsb 0 | ||
| 753 | #define xd_p_dagc1_accumulate_num_8k_14_8 0xA123 | ||
| 754 | #define dagc1_accumulate_num_8k_14_8_pos 0 | ||
| 755 | #define dagc1_accumulate_num_8k_14_8_len 7 | ||
| 756 | #define dagc1_accumulate_num_8k_14_8_lsb 8 | ||
| 757 | #define xd_p_dagc1_desired_level_0 0xA123 | ||
| 758 | #define dagc1_desired_level_0_pos 7 | ||
| 759 | #define dagc1_desired_level_0_len 1 | ||
| 760 | #define dagc1_desired_level_0_lsb 0 | ||
| 761 | #define xd_p_dagc1_desired_level_8_1 0xA124 | ||
| 762 | #define dagc1_desired_level_8_1_pos 0 | ||
| 763 | #define dagc1_desired_level_8_1_len 8 | ||
| 764 | #define dagc1_desired_level_8_1_lsb 1 | ||
| 765 | #define xd_p_dagc1_apply_delay 0xA125 | ||
| 766 | #define dagc1_apply_delay_pos 0 | ||
| 767 | #define dagc1_apply_delay_len 7 | ||
| 768 | #define dagc1_apply_delay_lsb 0 | ||
| 769 | #define xd_p_dagc1_bypass_scale_ctl 0xA126 | ||
| 770 | #define dagc1_bypass_scale_ctl_pos 0 | ||
| 771 | #define dagc1_bypass_scale_ctl_len 2 | ||
| 772 | #define dagc1_bypass_scale_ctl_lsb 0 | ||
| 773 | #define xd_p_reg_dagc1_in_sat_cnt_7_0 0xA127 | ||
| 774 | #define reg_dagc1_in_sat_cnt_7_0_pos 0 | ||
| 775 | #define reg_dagc1_in_sat_cnt_7_0_len 8 | ||
| 776 | #define reg_dagc1_in_sat_cnt_7_0_lsb 0 | ||
| 777 | #define xd_p_reg_dagc1_in_sat_cnt_15_8 0xA128 | ||
| 778 | #define reg_dagc1_in_sat_cnt_15_8_pos 0 | ||
| 779 | #define reg_dagc1_in_sat_cnt_15_8_len 8 | ||
| 780 | #define reg_dagc1_in_sat_cnt_15_8_lsb 8 | ||
| 781 | #define xd_p_reg_dagc1_in_sat_cnt_23_16 0xA129 | ||
| 782 | #define reg_dagc1_in_sat_cnt_23_16_pos 0 | ||
| 783 | #define reg_dagc1_in_sat_cnt_23_16_len 8 | ||
| 784 | #define reg_dagc1_in_sat_cnt_23_16_lsb 16 | ||
| 785 | #define xd_p_reg_dagc1_in_sat_cnt_31_24 0xA12A | ||
| 786 | #define reg_dagc1_in_sat_cnt_31_24_pos 0 | ||
| 787 | #define reg_dagc1_in_sat_cnt_31_24_len 8 | ||
| 788 | #define reg_dagc1_in_sat_cnt_31_24_lsb 24 | ||
| 789 | #define xd_p_reg_dagc1_out_sat_cnt_7_0 0xA12B | ||
| 790 | #define reg_dagc1_out_sat_cnt_7_0_pos 0 | ||
| 791 | #define reg_dagc1_out_sat_cnt_7_0_len 8 | ||
| 792 | #define reg_dagc1_out_sat_cnt_7_0_lsb 0 | ||
| 793 | #define xd_p_reg_dagc1_out_sat_cnt_15_8 0xA12C | ||
| 794 | #define reg_dagc1_out_sat_cnt_15_8_pos 0 | ||
| 795 | #define reg_dagc1_out_sat_cnt_15_8_len 8 | ||
| 796 | #define reg_dagc1_out_sat_cnt_15_8_lsb 8 | ||
| 797 | #define xd_p_reg_dagc1_out_sat_cnt_23_16 0xA12D | ||
| 798 | #define reg_dagc1_out_sat_cnt_23_16_pos 0 | ||
| 799 | #define reg_dagc1_out_sat_cnt_23_16_len 8 | ||
| 800 | #define reg_dagc1_out_sat_cnt_23_16_lsb 16 | ||
| 801 | #define xd_p_reg_dagc1_out_sat_cnt_31_24 0xA12E | ||
| 802 | #define reg_dagc1_out_sat_cnt_31_24_pos 0 | ||
| 803 | #define reg_dagc1_out_sat_cnt_31_24_len 8 | ||
| 804 | #define reg_dagc1_out_sat_cnt_31_24_lsb 24 | ||
| 805 | #define xd_r_dagc1_multiplier_7_0 0xA136 | ||
| 806 | #define dagc1_multiplier_7_0_pos 0 | ||
| 807 | #define dagc1_multiplier_7_0_len 8 | ||
| 808 | #define dagc1_multiplier_7_0_lsb 0 | ||
| 809 | #define xd_r_dagc1_multiplier_15_8 0xA137 | ||
| 810 | #define dagc1_multiplier_15_8_pos 0 | ||
| 811 | #define dagc1_multiplier_15_8_len 8 | ||
| 812 | #define dagc1_multiplier_15_8_lsb 8 | ||
| 813 | #define xd_r_dagc1_right_shift_bits 0xA138 | ||
| 814 | #define dagc1_right_shift_bits_pos 0 | ||
| 815 | #define dagc1_right_shift_bits_len 4 | ||
| 816 | #define dagc1_right_shift_bits_lsb 0 | ||
| 817 | #define xd_p_reg_bfs_fcw_7_0 0xA140 | ||
| 818 | #define reg_bfs_fcw_7_0_pos 0 | ||
| 819 | #define reg_bfs_fcw_7_0_len 8 | ||
| 820 | #define reg_bfs_fcw_7_0_lsb 0 | ||
| 821 | #define xd_p_reg_bfs_fcw_15_8 0xA141 | ||
| 822 | #define reg_bfs_fcw_15_8_pos 0 | ||
| 823 | #define reg_bfs_fcw_15_8_len 8 | ||
| 824 | #define reg_bfs_fcw_15_8_lsb 8 | ||
| 825 | #define xd_p_reg_bfs_fcw_22_16 0xA142 | ||
| 826 | #define reg_bfs_fcw_22_16_pos 0 | ||
| 827 | #define reg_bfs_fcw_22_16_len 7 | ||
| 828 | #define reg_bfs_fcw_22_16_lsb 16 | ||
| 829 | #define xd_p_reg_antif_sf_7_0 0xA144 | ||
| 830 | #define reg_antif_sf_7_0_pos 0 | ||
| 831 | #define reg_antif_sf_7_0_len 8 | ||
| 832 | #define reg_antif_sf_7_0_lsb 0 | ||
| 833 | #define xd_p_reg_antif_sf_11_8 0xA145 | ||
| 834 | #define reg_antif_sf_11_8_pos 0 | ||
| 835 | #define reg_antif_sf_11_8_len 4 | ||
| 836 | #define reg_antif_sf_11_8_lsb 8 | ||
| 837 | #define xd_r_bfs_fcw_q_7_0 0xA150 | ||
| 838 | #define bfs_fcw_q_7_0_pos 0 | ||
| 839 | #define bfs_fcw_q_7_0_len 8 | ||
| 840 | #define bfs_fcw_q_7_0_lsb 0 | ||
| 841 | #define xd_r_bfs_fcw_q_15_8 0xA151 | ||
| 842 | #define bfs_fcw_q_15_8_pos 0 | ||
| 843 | #define bfs_fcw_q_15_8_len 8 | ||
| 844 | #define bfs_fcw_q_15_8_lsb 8 | ||
| 845 | #define xd_r_bfs_fcw_q_22_16 0xA152 | ||
| 846 | #define bfs_fcw_q_22_16_pos 0 | ||
| 847 | #define bfs_fcw_q_22_16_len 7 | ||
| 848 | #define bfs_fcw_q_22_16_lsb 16 | ||
| 849 | #define xd_p_reg_dca_enu 0xA160 | ||
| 850 | #define reg_dca_enu_pos 0 | ||
| 851 | #define reg_dca_enu_len 1 | ||
| 852 | #define reg_dca_enu_lsb 0 | ||
| 853 | #define xd_p_reg_dca_enl 0xA160 | ||
| 854 | #define reg_dca_enl_pos 1 | ||
| 855 | #define reg_dca_enl_len 1 | ||
| 856 | #define reg_dca_enl_lsb 0 | ||
| 857 | #define xd_p_reg_dca_lower_chip 0xA160 | ||
| 858 | #define reg_dca_lower_chip_pos 2 | ||
| 859 | #define reg_dca_lower_chip_len 1 | ||
| 860 | #define reg_dca_lower_chip_lsb 0 | ||
| 861 | #define xd_p_reg_dca_upper_chip 0xA160 | ||
| 862 | #define reg_dca_upper_chip_pos 3 | ||
| 863 | #define reg_dca_upper_chip_len 1 | ||
| 864 | #define reg_dca_upper_chip_lsb 0 | ||
| 865 | #define xd_p_reg_dca_platch 0xA160 | ||
| 866 | #define reg_dca_platch_pos 4 | ||
| 867 | #define reg_dca_platch_len 1 | ||
| 868 | #define reg_dca_platch_lsb 0 | ||
| 869 | #define xd_p_reg_dca_th 0xA161 | ||
| 870 | #define reg_dca_th_pos 0 | ||
| 871 | #define reg_dca_th_len 5 | ||
| 872 | #define reg_dca_th_lsb 0 | ||
| 873 | #define xd_p_reg_dca_scale 0xA162 | ||
| 874 | #define reg_dca_scale_pos 0 | ||
| 875 | #define reg_dca_scale_len 4 | ||
| 876 | #define reg_dca_scale_lsb 0 | ||
| 877 | #define xd_p_reg_dca_tone_7_0 0xA163 | ||
| 878 | #define reg_dca_tone_7_0_pos 0 | ||
| 879 | #define reg_dca_tone_7_0_len 8 | ||
| 880 | #define reg_dca_tone_7_0_lsb 0 | ||
| 881 | #define xd_p_reg_dca_tone_12_8 0xA164 | ||
| 882 | #define reg_dca_tone_12_8_pos 0 | ||
| 883 | #define reg_dca_tone_12_8_len 5 | ||
| 884 | #define reg_dca_tone_12_8_lsb 8 | ||
| 885 | #define xd_p_reg_dca_time_7_0 0xA165 | ||
| 886 | #define reg_dca_time_7_0_pos 0 | ||
| 887 | #define reg_dca_time_7_0_len 8 | ||
| 888 | #define reg_dca_time_7_0_lsb 0 | ||
| 889 | #define xd_p_reg_dca_time_15_8 0xA166 | ||
| 890 | #define reg_dca_time_15_8_pos 0 | ||
| 891 | #define reg_dca_time_15_8_len 8 | ||
| 892 | #define reg_dca_time_15_8_lsb 8 | ||
| 893 | #define xd_r_dcasm 0xA167 | ||
| 894 | #define dcasm_pos 0 | ||
| 895 | #define dcasm_len 3 | ||
| 896 | #define dcasm_lsb 0 | ||
| 897 | #define xd_p_reg_qnt_valuew_7_0 0xA168 | ||
| 898 | #define reg_qnt_valuew_7_0_pos 0 | ||
| 899 | #define reg_qnt_valuew_7_0_len 8 | ||
| 900 | #define reg_qnt_valuew_7_0_lsb 0 | ||
| 901 | #define xd_p_reg_qnt_valuew_10_8 0xA169 | ||
| 902 | #define reg_qnt_valuew_10_8_pos 0 | ||
| 903 | #define reg_qnt_valuew_10_8_len 3 | ||
| 904 | #define reg_qnt_valuew_10_8_lsb 8 | ||
| 905 | #define xd_p_dca_sbx_gain_diff_7_0 0xA16A | ||
| 906 | #define dca_sbx_gain_diff_7_0_pos 0 | ||
| 907 | #define dca_sbx_gain_diff_7_0_len 8 | ||
| 908 | #define dca_sbx_gain_diff_7_0_lsb 0 | ||
| 909 | #define xd_p_dca_sbx_gain_diff_9_8 0xA16B | ||
| 910 | #define dca_sbx_gain_diff_9_8_pos 0 | ||
| 911 | #define dca_sbx_gain_diff_9_8_len 2 | ||
| 912 | #define dca_sbx_gain_diff_9_8_lsb 8 | ||
| 913 | #define xd_p_reg_dca_stand_alone 0xA16C | ||
| 914 | #define reg_dca_stand_alone_pos 0 | ||
| 915 | #define reg_dca_stand_alone_len 1 | ||
| 916 | #define reg_dca_stand_alone_lsb 0 | ||
| 917 | #define xd_p_reg_dca_upper_out_en 0xA16C | ||
| 918 | #define reg_dca_upper_out_en_pos 1 | ||
| 919 | #define reg_dca_upper_out_en_len 1 | ||
| 920 | #define reg_dca_upper_out_en_lsb 0 | ||
| 921 | #define xd_p_reg_dca_rc_en 0xA16C | ||
| 922 | #define reg_dca_rc_en_pos 2 | ||
| 923 | #define reg_dca_rc_en_len 1 | ||
| 924 | #define reg_dca_rc_en_lsb 0 | ||
| 925 | #define xd_p_reg_dca_retrain_send 0xA16C | ||
| 926 | #define reg_dca_retrain_send_pos 3 | ||
| 927 | #define reg_dca_retrain_send_len 1 | ||
| 928 | #define reg_dca_retrain_send_lsb 0 | ||
| 929 | #define xd_p_reg_dca_retrain_rec 0xA16C | ||
| 930 | #define reg_dca_retrain_rec_pos 4 | ||
| 931 | #define reg_dca_retrain_rec_len 1 | ||
| 932 | #define reg_dca_retrain_rec_lsb 0 | ||
| 933 | #define xd_p_reg_dca_api_tpsrdy 0xA16C | ||
| 934 | #define reg_dca_api_tpsrdy_pos 5 | ||
| 935 | #define reg_dca_api_tpsrdy_len 1 | ||
| 936 | #define reg_dca_api_tpsrdy_lsb 0 | ||
| 937 | #define xd_p_reg_dca_symbol_gap 0xA16D | ||
| 938 | #define reg_dca_symbol_gap_pos 0 | ||
| 939 | #define reg_dca_symbol_gap_len 4 | ||
| 940 | #define reg_dca_symbol_gap_lsb 0 | ||
| 941 | #define xd_p_reg_qnt_nfvaluew_7_0 0xA16E | ||
| 942 | #define reg_qnt_nfvaluew_7_0_pos 0 | ||
| 943 | #define reg_qnt_nfvaluew_7_0_len 8 | ||
| 944 | #define reg_qnt_nfvaluew_7_0_lsb 0 | ||
| 945 | #define xd_p_reg_qnt_nfvaluew_10_8 0xA16F | ||
| 946 | #define reg_qnt_nfvaluew_10_8_pos 0 | ||
| 947 | #define reg_qnt_nfvaluew_10_8_len 3 | ||
| 948 | #define reg_qnt_nfvaluew_10_8_lsb 8 | ||
| 949 | #define xd_p_reg_qnt_flatness_thr_7_0 0xA170 | ||
| 950 | #define reg_qnt_flatness_thr_7_0_pos 0 | ||
| 951 | #define reg_qnt_flatness_thr_7_0_len 8 | ||
| 952 | #define reg_qnt_flatness_thr_7_0_lsb 0 | ||
| 953 | #define xd_p_reg_qnt_flatness_thr_9_8 0xA171 | ||
| 954 | #define reg_qnt_flatness_thr_9_8_pos 0 | ||
| 955 | #define reg_qnt_flatness_thr_9_8_len 2 | ||
| 956 | #define reg_qnt_flatness_thr_9_8_lsb 8 | ||
| 957 | #define xd_p_reg_dca_tone_idx_5_0 0xA171 | ||
| 958 | #define reg_dca_tone_idx_5_0_pos 2 | ||
| 959 | #define reg_dca_tone_idx_5_0_len 6 | ||
| 960 | #define reg_dca_tone_idx_5_0_lsb 0 | ||
| 961 | #define xd_p_reg_dca_tone_idx_12_6 0xA172 | ||
| 962 | #define reg_dca_tone_idx_12_6_pos 0 | ||
| 963 | #define reg_dca_tone_idx_12_6_len 7 | ||
| 964 | #define reg_dca_tone_idx_12_6_lsb 6 | ||
| 965 | #define xd_p_reg_dca_data_vld 0xA173 | ||
| 966 | #define reg_dca_data_vld_pos 0 | ||
| 967 | #define reg_dca_data_vld_len 1 | ||
| 968 | #define reg_dca_data_vld_lsb 0 | ||
| 969 | #define xd_p_reg_dca_read_update 0xA173 | ||
| 970 | #define reg_dca_read_update_pos 1 | ||
| 971 | #define reg_dca_read_update_len 1 | ||
| 972 | #define reg_dca_read_update_lsb 0 | ||
| 973 | #define xd_r_reg_dca_data_re_5_0 0xA173 | ||
| 974 | #define reg_dca_data_re_5_0_pos 2 | ||
| 975 | #define reg_dca_data_re_5_0_len 6 | ||
| 976 | #define reg_dca_data_re_5_0_lsb 0 | ||
| 977 | #define xd_r_reg_dca_data_re_10_6 0xA174 | ||
| 978 | #define reg_dca_data_re_10_6_pos 0 | ||
| 979 | #define reg_dca_data_re_10_6_len 5 | ||
| 980 | #define reg_dca_data_re_10_6_lsb 6 | ||
| 981 | #define xd_r_reg_dca_data_im_7_0 0xA175 | ||
| 982 | #define reg_dca_data_im_7_0_pos 0 | ||
| 983 | #define reg_dca_data_im_7_0_len 8 | ||
| 984 | #define reg_dca_data_im_7_0_lsb 0 | ||
| 985 | #define xd_r_reg_dca_data_im_10_8 0xA176 | ||
| 986 | #define reg_dca_data_im_10_8_pos 0 | ||
| 987 | #define reg_dca_data_im_10_8_len 3 | ||
| 988 | #define reg_dca_data_im_10_8_lsb 8 | ||
| 989 | #define xd_r_reg_dca_data_h2_7_0 0xA178 | ||
| 990 | #define reg_dca_data_h2_7_0_pos 0 | ||
| 991 | #define reg_dca_data_h2_7_0_len 8 | ||
| 992 | #define reg_dca_data_h2_7_0_lsb 0 | ||
| 993 | #define xd_r_reg_dca_data_h2_9_8 0xA179 | ||
| 994 | #define reg_dca_data_h2_9_8_pos 0 | ||
| 995 | #define reg_dca_data_h2_9_8_len 2 | ||
| 996 | #define reg_dca_data_h2_9_8_lsb 8 | ||
| 997 | #define xd_p_reg_f_adc_7_0 0xA180 | ||
| 998 | #define reg_f_adc_7_0_pos 0 | ||
| 999 | #define reg_f_adc_7_0_len 8 | ||
| 1000 | #define reg_f_adc_7_0_lsb 0 | ||
| 1001 | #define xd_p_reg_f_adc_15_8 0xA181 | ||
| 1002 | #define reg_f_adc_15_8_pos 0 | ||
| 1003 | #define reg_f_adc_15_8_len 8 | ||
| 1004 | #define reg_f_adc_15_8_lsb 8 | ||
| 1005 | #define xd_p_reg_f_adc_23_16 0xA182 | ||
| 1006 | #define reg_f_adc_23_16_pos 0 | ||
| 1007 | #define reg_f_adc_23_16_len 8 | ||
| 1008 | #define reg_f_adc_23_16_lsb 16 | ||
| 1009 | #define xd_r_intp_mu_7_0 0xA190 | ||
| 1010 | #define intp_mu_7_0_pos 0 | ||
| 1011 | #define intp_mu_7_0_len 8 | ||
| 1012 | #define intp_mu_7_0_lsb 0 | ||
| 1013 | #define xd_r_intp_mu_15_8 0xA191 | ||
| 1014 | #define intp_mu_15_8_pos 0 | ||
| 1015 | #define intp_mu_15_8_len 8 | ||
| 1016 | #define intp_mu_15_8_lsb 8 | ||
| 1017 | #define xd_r_intp_mu_19_16 0xA192 | ||
| 1018 | #define intp_mu_19_16_pos 0 | ||
| 1019 | #define intp_mu_19_16_len 4 | ||
| 1020 | #define intp_mu_19_16_lsb 16 | ||
| 1021 | #define xd_p_reg_agc_rst 0xA1A0 | ||
| 1022 | #define reg_agc_rst_pos 0 | ||
| 1023 | #define reg_agc_rst_len 1 | ||
| 1024 | #define reg_agc_rst_lsb 0 | ||
| 1025 | #define xd_p_rf_agc_en 0xA1A0 | ||
| 1026 | #define rf_agc_en_pos 1 | ||
| 1027 | #define rf_agc_en_len 1 | ||
| 1028 | #define rf_agc_en_lsb 0 | ||
| 1029 | #define xd_p_rf_agc_dis 0xA1A0 | ||
| 1030 | #define rf_agc_dis_pos 2 | ||
| 1031 | #define rf_agc_dis_len 1 | ||
| 1032 | #define rf_agc_dis_lsb 0 | ||
| 1033 | #define xd_p_if_agc_rst 0xA1A0 | ||
| 1034 | #define if_agc_rst_pos 3 | ||
| 1035 | #define if_agc_rst_len 1 | ||
| 1036 | #define if_agc_rst_lsb 0 | ||
| 1037 | #define xd_p_if_agc_en 0xA1A0 | ||
| 1038 | #define if_agc_en_pos 4 | ||
| 1039 | #define if_agc_en_len 1 | ||
| 1040 | #define if_agc_en_lsb 0 | ||
| 1041 | #define xd_p_if_agc_dis 0xA1A0 | ||
| 1042 | #define if_agc_dis_pos 5 | ||
| 1043 | #define if_agc_dis_len 1 | ||
| 1044 | #define if_agc_dis_lsb 0 | ||
| 1045 | #define xd_p_agc_lock 0xA1A0 | ||
| 1046 | #define agc_lock_pos 6 | ||
| 1047 | #define agc_lock_len 1 | ||
| 1048 | #define agc_lock_lsb 0 | ||
| 1049 | #define xd_p_reg_tinr_rst 0xA1A1 | ||
| 1050 | #define reg_tinr_rst_pos 0 | ||
| 1051 | #define reg_tinr_rst_len 1 | ||
| 1052 | #define reg_tinr_rst_lsb 0 | ||
| 1053 | #define xd_p_reg_tinr_en 0xA1A1 | ||
| 1054 | #define reg_tinr_en_pos 1 | ||
| 1055 | #define reg_tinr_en_len 1 | ||
| 1056 | #define reg_tinr_en_lsb 0 | ||
| 1057 | #define xd_p_reg_ccifs_en 0xA1A2 | ||
| 1058 | #define reg_ccifs_en_pos 0 | ||
| 1059 | #define reg_ccifs_en_len 1 | ||
| 1060 | #define reg_ccifs_en_lsb 0 | ||
| 1061 | #define xd_p_reg_ccifs_dis 0xA1A2 | ||
| 1062 | #define reg_ccifs_dis_pos 1 | ||
| 1063 | #define reg_ccifs_dis_len 1 | ||
| 1064 | #define reg_ccifs_dis_lsb 0 | ||
| 1065 | #define xd_p_reg_ccifs_rst 0xA1A2 | ||
| 1066 | #define reg_ccifs_rst_pos 2 | ||
| 1067 | #define reg_ccifs_rst_len 1 | ||
| 1068 | #define reg_ccifs_rst_lsb 0 | ||
| 1069 | #define xd_p_reg_ccifs_byp 0xA1A2 | ||
| 1070 | #define reg_ccifs_byp_pos 3 | ||
| 1071 | #define reg_ccifs_byp_len 1 | ||
| 1072 | #define reg_ccifs_byp_lsb 0 | ||
| 1073 | #define xd_p_reg_ccif_en 0xA1A3 | ||
| 1074 | #define reg_ccif_en_pos 0 | ||
| 1075 | #define reg_ccif_en_len 1 | ||
| 1076 | #define reg_ccif_en_lsb 0 | ||
| 1077 | #define xd_p_reg_ccif_dis 0xA1A3 | ||
| 1078 | #define reg_ccif_dis_pos 1 | ||
| 1079 | #define reg_ccif_dis_len 1 | ||
| 1080 | #define reg_ccif_dis_lsb 0 | ||
| 1081 | #define xd_p_reg_ccif_rst 0xA1A3 | ||
| 1082 | #define reg_ccif_rst_pos 2 | ||
| 1083 | #define reg_ccif_rst_len 1 | ||
| 1084 | #define reg_ccif_rst_lsb 0 | ||
| 1085 | #define xd_p_reg_ccif_byp 0xA1A3 | ||
| 1086 | #define reg_ccif_byp_pos 3 | ||
| 1087 | #define reg_ccif_byp_len 1 | ||
| 1088 | #define reg_ccif_byp_lsb 0 | ||
| 1089 | #define xd_p_dagc1_rst 0xA1A4 | ||
| 1090 | #define dagc1_rst_pos 0 | ||
| 1091 | #define dagc1_rst_len 1 | ||
| 1092 | #define dagc1_rst_lsb 0 | ||
| 1093 | #define xd_p_dagc1_en 0xA1A4 | ||
| 1094 | #define dagc1_en_pos 1 | ||
| 1095 | #define dagc1_en_len 1 | ||
| 1096 | #define dagc1_en_lsb 0 | ||
| 1097 | #define xd_p_dagc1_mode 0xA1A4 | ||
| 1098 | #define dagc1_mode_pos 2 | ||
| 1099 | #define dagc1_mode_len 2 | ||
| 1100 | #define dagc1_mode_lsb 0 | ||
| 1101 | #define xd_p_dagc1_done 0xA1A4 | ||
| 1102 | #define dagc1_done_pos 4 | ||
| 1103 | #define dagc1_done_len 1 | ||
| 1104 | #define dagc1_done_lsb 0 | ||
| 1105 | #define xd_p_ccid_rst 0xA1A5 | ||
| 1106 | #define ccid_rst_pos 0 | ||
| 1107 | #define ccid_rst_len 1 | ||
| 1108 | #define ccid_rst_lsb 0 | ||
| 1109 | #define xd_p_ccid_en 0xA1A5 | ||
| 1110 | #define ccid_en_pos 1 | ||
| 1111 | #define ccid_en_len 1 | ||
| 1112 | #define ccid_en_lsb 0 | ||
| 1113 | #define xd_p_ccid_mode 0xA1A5 | ||
| 1114 | #define ccid_mode_pos 2 | ||
| 1115 | #define ccid_mode_len 2 | ||
| 1116 | #define ccid_mode_lsb 0 | ||
| 1117 | #define xd_p_ccid_done 0xA1A5 | ||
| 1118 | #define ccid_done_pos 4 | ||
| 1119 | #define ccid_done_len 1 | ||
| 1120 | #define ccid_done_lsb 0 | ||
| 1121 | #define xd_r_ccid_deted 0xA1A5 | ||
| 1122 | #define ccid_deted_pos 5 | ||
| 1123 | #define ccid_deted_len 1 | ||
| 1124 | #define ccid_deted_lsb 0 | ||
| 1125 | #define xd_p_ccid2_en 0xA1A5 | ||
| 1126 | #define ccid2_en_pos 6 | ||
| 1127 | #define ccid2_en_len 1 | ||
| 1128 | #define ccid2_en_lsb 0 | ||
| 1129 | #define xd_p_ccid2_done 0xA1A5 | ||
| 1130 | #define ccid2_done_pos 7 | ||
| 1131 | #define ccid2_done_len 1 | ||
| 1132 | #define ccid2_done_lsb 0 | ||
| 1133 | #define xd_p_reg_bfs_en 0xA1A6 | ||
| 1134 | #define reg_bfs_en_pos 0 | ||
| 1135 | #define reg_bfs_en_len 1 | ||
| 1136 | #define reg_bfs_en_lsb 0 | ||
| 1137 | #define xd_p_reg_bfs_dis 0xA1A6 | ||
| 1138 | #define reg_bfs_dis_pos 1 | ||
| 1139 | #define reg_bfs_dis_len 1 | ||
| 1140 | #define reg_bfs_dis_lsb 0 | ||
| 1141 | #define xd_p_reg_bfs_rst 0xA1A6 | ||
| 1142 | #define reg_bfs_rst_pos 2 | ||
| 1143 | #define reg_bfs_rst_len 1 | ||
| 1144 | #define reg_bfs_rst_lsb 0 | ||
| 1145 | #define xd_p_reg_bfs_byp 0xA1A6 | ||
| 1146 | #define reg_bfs_byp_pos 3 | ||
| 1147 | #define reg_bfs_byp_len 1 | ||
| 1148 | #define reg_bfs_byp_lsb 0 | ||
| 1149 | #define xd_p_reg_antif_en 0xA1A7 | ||
| 1150 | #define reg_antif_en_pos 0 | ||
| 1151 | #define reg_antif_en_len 1 | ||
| 1152 | #define reg_antif_en_lsb 0 | ||
| 1153 | #define xd_p_reg_antif_dis 0xA1A7 | ||
| 1154 | #define reg_antif_dis_pos 1 | ||
| 1155 | #define reg_antif_dis_len 1 | ||
| 1156 | #define reg_antif_dis_lsb 0 | ||
| 1157 | #define xd_p_reg_antif_rst 0xA1A7 | ||
| 1158 | #define reg_antif_rst_pos 2 | ||
| 1159 | #define reg_antif_rst_len 1 | ||
| 1160 | #define reg_antif_rst_lsb 0 | ||
| 1161 | #define xd_p_reg_antif_byp 0xA1A7 | ||
| 1162 | #define reg_antif_byp_pos 3 | ||
| 1163 | #define reg_antif_byp_len 1 | ||
| 1164 | #define reg_antif_byp_lsb 0 | ||
| 1165 | #define xd_p_intp_en 0xA1A8 | ||
| 1166 | #define intp_en_pos 0 | ||
| 1167 | #define intp_en_len 1 | ||
| 1168 | #define intp_en_lsb 0 | ||
| 1169 | #define xd_p_intp_dis 0xA1A8 | ||
| 1170 | #define intp_dis_pos 1 | ||
| 1171 | #define intp_dis_len 1 | ||
| 1172 | #define intp_dis_lsb 0 | ||
| 1173 | #define xd_p_intp_rst 0xA1A8 | ||
| 1174 | #define intp_rst_pos 2 | ||
| 1175 | #define intp_rst_len 1 | ||
| 1176 | #define intp_rst_lsb 0 | ||
| 1177 | #define xd_p_intp_byp 0xA1A8 | ||
| 1178 | #define intp_byp_pos 3 | ||
| 1179 | #define intp_byp_len 1 | ||
| 1180 | #define intp_byp_lsb 0 | ||
| 1181 | #define xd_p_reg_acif_en 0xA1A9 | ||
| 1182 | #define reg_acif_en_pos 0 | ||
| 1183 | #define reg_acif_en_len 1 | ||
| 1184 | #define reg_acif_en_lsb 0 | ||
| 1185 | #define xd_p_reg_acif_dis 0xA1A9 | ||
| 1186 | #define reg_acif_dis_pos 1 | ||
| 1187 | #define reg_acif_dis_len 1 | ||
| 1188 | #define reg_acif_dis_lsb 0 | ||
| 1189 | #define xd_p_reg_acif_rst 0xA1A9 | ||
| 1190 | #define reg_acif_rst_pos 2 | ||
| 1191 | #define reg_acif_rst_len 1 | ||
| 1192 | #define reg_acif_rst_lsb 0 | ||
| 1193 | #define xd_p_reg_acif_byp 0xA1A9 | ||
| 1194 | #define reg_acif_byp_pos 3 | ||
| 1195 | #define reg_acif_byp_len 1 | ||
| 1196 | #define reg_acif_byp_lsb 0 | ||
| 1197 | #define xd_p_reg_acif_sync_mode 0xA1A9 | ||
| 1198 | #define reg_acif_sync_mode_pos 4 | ||
| 1199 | #define reg_acif_sync_mode_len 1 | ||
| 1200 | #define reg_acif_sync_mode_lsb 0 | ||
| 1201 | #define xd_p_dagc2_rst 0xA1AA | ||
| 1202 | #define dagc2_rst_pos 0 | ||
| 1203 | #define dagc2_rst_len 1 | ||
| 1204 | #define dagc2_rst_lsb 0 | ||
| 1205 | #define xd_p_dagc2_en 0xA1AA | ||
| 1206 | #define dagc2_en_pos 1 | ||
| 1207 | #define dagc2_en_len 1 | ||
| 1208 | #define dagc2_en_lsb 0 | ||
| 1209 | #define xd_p_dagc2_mode 0xA1AA | ||
| 1210 | #define dagc2_mode_pos 2 | ||
| 1211 | #define dagc2_mode_len 2 | ||
| 1212 | #define dagc2_mode_lsb 0 | ||
| 1213 | #define xd_p_dagc2_done 0xA1AA | ||
| 1214 | #define dagc2_done_pos 4 | ||
| 1215 | #define dagc2_done_len 1 | ||
| 1216 | #define dagc2_done_lsb 0 | ||
| 1217 | #define xd_p_reg_dca_en 0xA1AB | ||
| 1218 | #define reg_dca_en_pos 0 | ||
| 1219 | #define reg_dca_en_len 1 | ||
| 1220 | #define reg_dca_en_lsb 0 | ||
| 1221 | #define xd_p_dagc2_accumulate_num_2k_7_0 0xA1C0 | ||
| 1222 | #define dagc2_accumulate_num_2k_7_0_pos 0 | ||
| 1223 | #define dagc2_accumulate_num_2k_7_0_len 8 | ||
| 1224 | #define dagc2_accumulate_num_2k_7_0_lsb 0 | ||
| 1225 | #define xd_p_dagc2_accumulate_num_2k_12_8 0xA1C1 | ||
| 1226 | #define dagc2_accumulate_num_2k_12_8_pos 0 | ||
| 1227 | #define dagc2_accumulate_num_2k_12_8_len 5 | ||
| 1228 | #define dagc2_accumulate_num_2k_12_8_lsb 8 | ||
| 1229 | #define xd_p_dagc2_accumulate_num_8k_7_0 0xA1C2 | ||
| 1230 | #define dagc2_accumulate_num_8k_7_0_pos 0 | ||
| 1231 | #define dagc2_accumulate_num_8k_7_0_len 8 | ||
| 1232 | #define dagc2_accumulate_num_8k_7_0_lsb 0 | ||
| 1233 | #define xd_p_dagc2_accumulate_num_8k_12_8 0xA1C3 | ||
| 1234 | #define dagc2_accumulate_num_8k_12_8_pos 0 | ||
| 1235 | #define dagc2_accumulate_num_8k_12_8_len 5 | ||
| 1236 | #define dagc2_accumulate_num_8k_12_8_lsb 8 | ||
| 1237 | #define xd_p_dagc2_desired_level_2_0 0xA1C3 | ||
| 1238 | #define dagc2_desired_level_2_0_pos 5 | ||
| 1239 | #define dagc2_desired_level_2_0_len 3 | ||
| 1240 | #define dagc2_desired_level_2_0_lsb 0 | ||
| 1241 | #define xd_p_dagc2_desired_level_8_3 0xA1C4 | ||
| 1242 | #define dagc2_desired_level_8_3_pos 0 | ||
| 1243 | #define dagc2_desired_level_8_3_len 6 | ||
| 1244 | #define dagc2_desired_level_8_3_lsb 3 | ||
| 1245 | #define xd_p_dagc2_apply_delay 0xA1C5 | ||
| 1246 | #define dagc2_apply_delay_pos 0 | ||
| 1247 | #define dagc2_apply_delay_len 7 | ||
| 1248 | #define dagc2_apply_delay_lsb 0 | ||
| 1249 | #define xd_p_dagc2_bypass_scale_ctl 0xA1C6 | ||
| 1250 | #define dagc2_bypass_scale_ctl_pos 0 | ||
| 1251 | #define dagc2_bypass_scale_ctl_len 3 | ||
| 1252 | #define dagc2_bypass_scale_ctl_lsb 0 | ||
| 1253 | #define xd_p_dagc2_programmable_shift1 0xA1C7 | ||
| 1254 | #define dagc2_programmable_shift1_pos 0 | ||
| 1255 | #define dagc2_programmable_shift1_len 8 | ||
| 1256 | #define dagc2_programmable_shift1_lsb 0 | ||
| 1257 | #define xd_p_dagc2_programmable_shift2 0xA1C8 | ||
| 1258 | #define dagc2_programmable_shift2_pos 0 | ||
| 1259 | #define dagc2_programmable_shift2_len 8 | ||
| 1260 | #define dagc2_programmable_shift2_lsb 0 | ||
| 1261 | #define xd_p_reg_dagc2_in_sat_cnt_7_0 0xA1C9 | ||
| 1262 | #define reg_dagc2_in_sat_cnt_7_0_pos 0 | ||
| 1263 | #define reg_dagc2_in_sat_cnt_7_0_len 8 | ||
| 1264 | #define reg_dagc2_in_sat_cnt_7_0_lsb 0 | ||
| 1265 | #define xd_p_reg_dagc2_in_sat_cnt_15_8 0xA1CA | ||
| 1266 | #define reg_dagc2_in_sat_cnt_15_8_pos 0 | ||
| 1267 | #define reg_dagc2_in_sat_cnt_15_8_len 8 | ||
| 1268 | #define reg_dagc2_in_sat_cnt_15_8_lsb 8 | ||
| 1269 | #define xd_p_reg_dagc2_in_sat_cnt_23_16 0xA1CB | ||
| 1270 | #define reg_dagc2_in_sat_cnt_23_16_pos 0 | ||
| 1271 | #define reg_dagc2_in_sat_cnt_23_16_len 8 | ||
| 1272 | #define reg_dagc2_in_sat_cnt_23_16_lsb 16 | ||
| 1273 | #define xd_p_reg_dagc2_in_sat_cnt_31_24 0xA1CC | ||
| 1274 | #define reg_dagc2_in_sat_cnt_31_24_pos 0 | ||
| 1275 | #define reg_dagc2_in_sat_cnt_31_24_len 8 | ||
| 1276 | #define reg_dagc2_in_sat_cnt_31_24_lsb 24 | ||
| 1277 | #define xd_p_reg_dagc2_out_sat_cnt_7_0 0xA1CD | ||
| 1278 | #define reg_dagc2_out_sat_cnt_7_0_pos 0 | ||
| 1279 | #define reg_dagc2_out_sat_cnt_7_0_len 8 | ||
| 1280 | #define reg_dagc2_out_sat_cnt_7_0_lsb 0 | ||
| 1281 | #define xd_p_reg_dagc2_out_sat_cnt_15_8 0xA1CE | ||
| 1282 | #define reg_dagc2_out_sat_cnt_15_8_pos 0 | ||
| 1283 | #define reg_dagc2_out_sat_cnt_15_8_len 8 | ||
| 1284 | #define reg_dagc2_out_sat_cnt_15_8_lsb 8 | ||
| 1285 | #define xd_p_reg_dagc2_out_sat_cnt_23_16 0xA1CF | ||
| 1286 | #define reg_dagc2_out_sat_cnt_23_16_pos 0 | ||
| 1287 | #define reg_dagc2_out_sat_cnt_23_16_len 8 | ||
| 1288 | #define reg_dagc2_out_sat_cnt_23_16_lsb 16 | ||
| 1289 | #define xd_p_reg_dagc2_out_sat_cnt_31_24 0xA1D0 | ||
| 1290 | #define reg_dagc2_out_sat_cnt_31_24_pos 0 | ||
| 1291 | #define reg_dagc2_out_sat_cnt_31_24_len 8 | ||
| 1292 | #define reg_dagc2_out_sat_cnt_31_24_lsb 24 | ||
| 1293 | #define xd_r_dagc2_multiplier_7_0 0xA1D6 | ||
| 1294 | #define dagc2_multiplier_7_0_pos 0 | ||
| 1295 | #define dagc2_multiplier_7_0_len 8 | ||
| 1296 | #define dagc2_multiplier_7_0_lsb 0 | ||
| 1297 | #define xd_r_dagc2_multiplier_15_8 0xA1D7 | ||
| 1298 | #define dagc2_multiplier_15_8_pos 0 | ||
| 1299 | #define dagc2_multiplier_15_8_len 8 | ||
| 1300 | #define dagc2_multiplier_15_8_lsb 8 | ||
| 1301 | #define xd_r_dagc2_right_shift_bits 0xA1D8 | ||
| 1302 | #define dagc2_right_shift_bits_pos 0 | ||
| 1303 | #define dagc2_right_shift_bits_len 4 | ||
| 1304 | #define dagc2_right_shift_bits_lsb 0 | ||
| 1305 | #define xd_p_cfoe_NS_coeff1_7_0 0xA200 | ||
| 1306 | #define cfoe_NS_coeff1_7_0_pos 0 | ||
| 1307 | #define cfoe_NS_coeff1_7_0_len 8 | ||
| 1308 | #define cfoe_NS_coeff1_7_0_lsb 0 | ||
| 1309 | #define xd_p_cfoe_NS_coeff1_15_8 0xA201 | ||
| 1310 | #define cfoe_NS_coeff1_15_8_pos 0 | ||
| 1311 | #define cfoe_NS_coeff1_15_8_len 8 | ||
| 1312 | #define cfoe_NS_coeff1_15_8_lsb 8 | ||
| 1313 | #define xd_p_cfoe_NS_coeff1_23_16 0xA202 | ||
| 1314 | #define cfoe_NS_coeff1_23_16_pos 0 | ||
| 1315 | #define cfoe_NS_coeff1_23_16_len 8 | ||
| 1316 | #define cfoe_NS_coeff1_23_16_lsb 16 | ||
| 1317 | #define xd_p_cfoe_NS_coeff1_25_24 0xA203 | ||
| 1318 | #define cfoe_NS_coeff1_25_24_pos 0 | ||
| 1319 | #define cfoe_NS_coeff1_25_24_len 2 | ||
| 1320 | #define cfoe_NS_coeff1_25_24_lsb 24 | ||
| 1321 | #define xd_p_cfoe_NS_coeff2_5_0 0xA203 | ||
| 1322 | #define cfoe_NS_coeff2_5_0_pos 2 | ||
| 1323 | #define cfoe_NS_coeff2_5_0_len 6 | ||
| 1324 | #define cfoe_NS_coeff2_5_0_lsb 0 | ||
| 1325 | #define xd_p_cfoe_NS_coeff2_13_6 0xA204 | ||
| 1326 | #define cfoe_NS_coeff2_13_6_pos 0 | ||
| 1327 | #define cfoe_NS_coeff2_13_6_len 8 | ||
| 1328 | #define cfoe_NS_coeff2_13_6_lsb 6 | ||
| 1329 | #define xd_p_cfoe_NS_coeff2_21_14 0xA205 | ||
| 1330 | #define cfoe_NS_coeff2_21_14_pos 0 | ||
| 1331 | #define cfoe_NS_coeff2_21_14_len 8 | ||
| 1332 | #define cfoe_NS_coeff2_21_14_lsb 14 | ||
| 1333 | #define xd_p_cfoe_NS_coeff2_24_22 0xA206 | ||
| 1334 | #define cfoe_NS_coeff2_24_22_pos 0 | ||
| 1335 | #define cfoe_NS_coeff2_24_22_len 3 | ||
| 1336 | #define cfoe_NS_coeff2_24_22_lsb 22 | ||
| 1337 | #define xd_p_cfoe_lf_c1_4_0 0xA206 | ||
| 1338 | #define cfoe_lf_c1_4_0_pos 3 | ||
| 1339 | #define cfoe_lf_c1_4_0_len 5 | ||
| 1340 | #define cfoe_lf_c1_4_0_lsb 0 | ||
| 1341 | #define xd_p_cfoe_lf_c1_12_5 0xA207 | ||
| 1342 | #define cfoe_lf_c1_12_5_pos 0 | ||
| 1343 | #define cfoe_lf_c1_12_5_len 8 | ||
| 1344 | #define cfoe_lf_c1_12_5_lsb 5 | ||
| 1345 | #define xd_p_cfoe_lf_c1_20_13 0xA208 | ||
| 1346 | #define cfoe_lf_c1_20_13_pos 0 | ||
| 1347 | #define cfoe_lf_c1_20_13_len 8 | ||
| 1348 | #define cfoe_lf_c1_20_13_lsb 13 | ||
| 1349 | #define xd_p_cfoe_lf_c1_25_21 0xA209 | ||
| 1350 | #define cfoe_lf_c1_25_21_pos 0 | ||
| 1351 | #define cfoe_lf_c1_25_21_len 5 | ||
| 1352 | #define cfoe_lf_c1_25_21_lsb 21 | ||
| 1353 | #define xd_p_cfoe_lf_c2_2_0 0xA209 | ||
| 1354 | #define cfoe_lf_c2_2_0_pos 5 | ||
| 1355 | #define cfoe_lf_c2_2_0_len 3 | ||
| 1356 | #define cfoe_lf_c2_2_0_lsb 0 | ||
| 1357 | #define xd_p_cfoe_lf_c2_10_3 0xA20A | ||
| 1358 | #define cfoe_lf_c2_10_3_pos 0 | ||
| 1359 | #define cfoe_lf_c2_10_3_len 8 | ||
| 1360 | #define cfoe_lf_c2_10_3_lsb 3 | ||
| 1361 | #define xd_p_cfoe_lf_c2_18_11 0xA20B | ||
| 1362 | #define cfoe_lf_c2_18_11_pos 0 | ||
| 1363 | #define cfoe_lf_c2_18_11_len 8 | ||
| 1364 | #define cfoe_lf_c2_18_11_lsb 11 | ||
| 1365 | #define xd_p_cfoe_lf_c2_25_19 0xA20C | ||
| 1366 | #define cfoe_lf_c2_25_19_pos 0 | ||
| 1367 | #define cfoe_lf_c2_25_19_len 7 | ||
| 1368 | #define cfoe_lf_c2_25_19_lsb 19 | ||
| 1369 | #define xd_p_cfoe_ifod_7_0 0xA20D | ||
| 1370 | #define cfoe_ifod_7_0_pos 0 | ||
| 1371 | #define cfoe_ifod_7_0_len 8 | ||
| 1372 | #define cfoe_ifod_7_0_lsb 0 | ||
| 1373 | #define xd_p_cfoe_ifod_10_8 0xA20E | ||
| 1374 | #define cfoe_ifod_10_8_pos 0 | ||
| 1375 | #define cfoe_ifod_10_8_len 3 | ||
| 1376 | #define cfoe_ifod_10_8_lsb 8 | ||
| 1377 | #define xd_p_cfoe_Divg_ctr_th 0xA20E | ||
| 1378 | #define cfoe_Divg_ctr_th_pos 4 | ||
| 1379 | #define cfoe_Divg_ctr_th_len 4 | ||
| 1380 | #define cfoe_Divg_ctr_th_lsb 0 | ||
| 1381 | #define xd_p_cfoe_FOT_divg_th 0xA20F | ||
| 1382 | #define cfoe_FOT_divg_th_pos 0 | ||
| 1383 | #define cfoe_FOT_divg_th_len 8 | ||
| 1384 | #define cfoe_FOT_divg_th_lsb 0 | ||
| 1385 | #define xd_p_cfoe_FOT_cnvg_th 0xA210 | ||
| 1386 | #define cfoe_FOT_cnvg_th_pos 0 | ||
| 1387 | #define cfoe_FOT_cnvg_th_len 8 | ||
| 1388 | #define cfoe_FOT_cnvg_th_lsb 0 | ||
| 1389 | #define xd_p_reg_cfoe_offset_7_0 0xA211 | ||
| 1390 | #define reg_cfoe_offset_7_0_pos 0 | ||
| 1391 | #define reg_cfoe_offset_7_0_len 8 | ||
| 1392 | #define reg_cfoe_offset_7_0_lsb 0 | ||
| 1393 | #define xd_p_reg_cfoe_offset_9_8 0xA212 | ||
| 1394 | #define reg_cfoe_offset_9_8_pos 0 | ||
| 1395 | #define reg_cfoe_offset_9_8_len 2 | ||
| 1396 | #define reg_cfoe_offset_9_8_lsb 8 | ||
| 1397 | #define xd_p_reg_cfoe_ifoe_sign_corr 0xA212 | ||
| 1398 | #define reg_cfoe_ifoe_sign_corr_pos 2 | ||
| 1399 | #define reg_cfoe_ifoe_sign_corr_len 1 | ||
| 1400 | #define reg_cfoe_ifoe_sign_corr_lsb 0 | ||
| 1401 | #define xd_r_cfoe_fot_LF_output_7_0 0xA218 | ||
| 1402 | #define cfoe_fot_LF_output_7_0_pos 0 | ||
| 1403 | #define cfoe_fot_LF_output_7_0_len 8 | ||
| 1404 | #define cfoe_fot_LF_output_7_0_lsb 0 | ||
| 1405 | #define xd_r_cfoe_fot_LF_output_15_8 0xA219 | ||
| 1406 | #define cfoe_fot_LF_output_15_8_pos 0 | ||
| 1407 | #define cfoe_fot_LF_output_15_8_len 8 | ||
| 1408 | #define cfoe_fot_LF_output_15_8_lsb 8 | ||
| 1409 | #define xd_r_cfoe_ifo_metric_7_0 0xA21A | ||
| 1410 | #define cfoe_ifo_metric_7_0_pos 0 | ||
| 1411 | #define cfoe_ifo_metric_7_0_len 8 | ||
| 1412 | #define cfoe_ifo_metric_7_0_lsb 0 | ||
| 1413 | #define xd_r_cfoe_ifo_metric_15_8 0xA21B | ||
| 1414 | #define cfoe_ifo_metric_15_8_pos 0 | ||
| 1415 | #define cfoe_ifo_metric_15_8_len 8 | ||
| 1416 | #define cfoe_ifo_metric_15_8_lsb 8 | ||
| 1417 | #define xd_r_cfoe_ifo_metric_23_16 0xA21C | ||
| 1418 | #define cfoe_ifo_metric_23_16_pos 0 | ||
| 1419 | #define cfoe_ifo_metric_23_16_len 8 | ||
| 1420 | #define cfoe_ifo_metric_23_16_lsb 16 | ||
| 1421 | #define xd_p_ste_Nu 0xA220 | ||
| 1422 | #define ste_Nu_pos 0 | ||
| 1423 | #define ste_Nu_len 2 | ||
| 1424 | #define ste_Nu_lsb 0 | ||
| 1425 | #define xd_p_ste_GI 0xA220 | ||
| 1426 | #define ste_GI_pos 2 | ||
| 1427 | #define ste_GI_len 3 | ||
| 1428 | #define ste_GI_lsb 0 | ||
| 1429 | #define xd_p_ste_symbol_num 0xA221 | ||
| 1430 | #define ste_symbol_num_pos 0 | ||
| 1431 | #define ste_symbol_num_len 2 | ||
| 1432 | #define ste_symbol_num_lsb 0 | ||
| 1433 | #define xd_p_ste_sample_num 0xA221 | ||
| 1434 | #define ste_sample_num_pos 2 | ||
| 1435 | #define ste_sample_num_len 2 | ||
| 1436 | #define ste_sample_num_lsb 0 | ||
| 1437 | #define xd_p_reg_ste_buf_en 0xA221 | ||
| 1438 | #define reg_ste_buf_en_pos 7 | ||
| 1439 | #define reg_ste_buf_en_len 1 | ||
| 1440 | #define reg_ste_buf_en_lsb 0 | ||
| 1441 | #define xd_p_ste_FFT_offset_7_0 0xA222 | ||
| 1442 | #define ste_FFT_offset_7_0_pos 0 | ||
| 1443 | #define ste_FFT_offset_7_0_len 8 | ||
| 1444 | #define ste_FFT_offset_7_0_lsb 0 | ||
| 1445 | #define xd_p_ste_FFT_offset_11_8 0xA223 | ||
| 1446 | #define ste_FFT_offset_11_8_pos 0 | ||
| 1447 | #define ste_FFT_offset_11_8_len 4 | ||
| 1448 | #define ste_FFT_offset_11_8_lsb 8 | ||
| 1449 | #define xd_p_reg_ste_tstmod 0xA223 | ||
| 1450 | #define reg_ste_tstmod_pos 5 | ||
| 1451 | #define reg_ste_tstmod_len 1 | ||
| 1452 | #define reg_ste_tstmod_lsb 0 | ||
| 1453 | #define xd_p_ste_adv_start_7_0 0xA224 | ||
| 1454 | #define ste_adv_start_7_0_pos 0 | ||
| 1455 | #define ste_adv_start_7_0_len 8 | ||
| 1456 | #define ste_adv_start_7_0_lsb 0 | ||
| 1457 | #define xd_p_ste_adv_start_10_8 0xA225 | ||
| 1458 | #define ste_adv_start_10_8_pos 0 | ||
| 1459 | #define ste_adv_start_10_8_len 3 | ||
| 1460 | #define ste_adv_start_10_8_lsb 8 | ||
| 1461 | #define xd_p_ste_adv_stop 0xA226 | ||
| 1462 | #define ste_adv_stop_pos 0 | ||
| 1463 | #define ste_adv_stop_len 8 | ||
| 1464 | #define ste_adv_stop_lsb 0 | ||
| 1465 | #define xd_r_ste_P_value_7_0 0xA228 | ||
| 1466 | #define ste_P_value_7_0_pos 0 | ||
| 1467 | #define ste_P_value_7_0_len 8 | ||
| 1468 | #define ste_P_value_7_0_lsb 0 | ||
| 1469 | #define xd_r_ste_P_value_10_8 0xA229 | ||
| 1470 | #define ste_P_value_10_8_pos 0 | ||
| 1471 | #define ste_P_value_10_8_len 3 | ||
| 1472 | #define ste_P_value_10_8_lsb 8 | ||
| 1473 | #define xd_r_ste_M_value_7_0 0xA22A | ||
| 1474 | #define ste_M_value_7_0_pos 0 | ||
| 1475 | #define ste_M_value_7_0_len 8 | ||
| 1476 | #define ste_M_value_7_0_lsb 0 | ||
| 1477 | #define xd_r_ste_M_value_10_8 0xA22B | ||
| 1478 | #define ste_M_value_10_8_pos 0 | ||
| 1479 | #define ste_M_value_10_8_len 3 | ||
| 1480 | #define ste_M_value_10_8_lsb 8 | ||
| 1481 | #define xd_r_ste_H1 0xA22C | ||
| 1482 | #define ste_H1_pos 0 | ||
| 1483 | #define ste_H1_len 7 | ||
| 1484 | #define ste_H1_lsb 0 | ||
| 1485 | #define xd_r_ste_H2 0xA22D | ||
| 1486 | #define ste_H2_pos 0 | ||
| 1487 | #define ste_H2_len 7 | ||
| 1488 | #define ste_H2_lsb 0 | ||
| 1489 | #define xd_r_ste_H3 0xA22E | ||
| 1490 | #define ste_H3_pos 0 | ||
| 1491 | #define ste_H3_len 7 | ||
| 1492 | #define ste_H3_lsb 0 | ||
| 1493 | #define xd_r_ste_H4 0xA22F | ||
| 1494 | #define ste_H4_pos 0 | ||
| 1495 | #define ste_H4_len 7 | ||
| 1496 | #define ste_H4_lsb 0 | ||
| 1497 | #define xd_r_ste_Corr_value_I_7_0 0xA230 | ||
| 1498 | #define ste_Corr_value_I_7_0_pos 0 | ||
| 1499 | #define ste_Corr_value_I_7_0_len 8 | ||
| 1500 | #define ste_Corr_value_I_7_0_lsb 0 | ||
| 1501 | #define xd_r_ste_Corr_value_I_15_8 0xA231 | ||
| 1502 | #define ste_Corr_value_I_15_8_pos 0 | ||
| 1503 | #define ste_Corr_value_I_15_8_len 8 | ||
| 1504 | #define ste_Corr_value_I_15_8_lsb 8 | ||
| 1505 | #define xd_r_ste_Corr_value_I_23_16 0xA232 | ||
| 1506 | #define ste_Corr_value_I_23_16_pos 0 | ||
| 1507 | #define ste_Corr_value_I_23_16_len 8 | ||
| 1508 | #define ste_Corr_value_I_23_16_lsb 16 | ||
| 1509 | #define xd_r_ste_Corr_value_I_27_24 0xA233 | ||
| 1510 | #define ste_Corr_value_I_27_24_pos 0 | ||
| 1511 | #define ste_Corr_value_I_27_24_len 4 | ||
| 1512 | #define ste_Corr_value_I_27_24_lsb 24 | ||
| 1513 | #define xd_r_ste_Corr_value_Q_7_0 0xA234 | ||
| 1514 | #define ste_Corr_value_Q_7_0_pos 0 | ||
| 1515 | #define ste_Corr_value_Q_7_0_len 8 | ||
| 1516 | #define ste_Corr_value_Q_7_0_lsb 0 | ||
| 1517 | #define xd_r_ste_Corr_value_Q_15_8 0xA235 | ||
| 1518 | #define ste_Corr_value_Q_15_8_pos 0 | ||
| 1519 | #define ste_Corr_value_Q_15_8_len 8 | ||
| 1520 | #define ste_Corr_value_Q_15_8_lsb 8 | ||
| 1521 | #define xd_r_ste_Corr_value_Q_23_16 0xA236 | ||
| 1522 | #define ste_Corr_value_Q_23_16_pos 0 | ||
| 1523 | #define ste_Corr_value_Q_23_16_len 8 | ||
| 1524 | #define ste_Corr_value_Q_23_16_lsb 16 | ||
| 1525 | #define xd_r_ste_Corr_value_Q_27_24 0xA237 | ||
| 1526 | #define ste_Corr_value_Q_27_24_pos 0 | ||
| 1527 | #define ste_Corr_value_Q_27_24_len 4 | ||
| 1528 | #define ste_Corr_value_Q_27_24_lsb 24 | ||
| 1529 | #define xd_r_ste_J_num_7_0 0xA238 | ||
| 1530 | #define ste_J_num_7_0_pos 0 | ||
| 1531 | #define ste_J_num_7_0_len 8 | ||
| 1532 | #define ste_J_num_7_0_lsb 0 | ||
| 1533 | #define xd_r_ste_J_num_15_8 0xA239 | ||
| 1534 | #define ste_J_num_15_8_pos 0 | ||
| 1535 | #define ste_J_num_15_8_len 8 | ||
| 1536 | #define ste_J_num_15_8_lsb 8 | ||
| 1537 | #define xd_r_ste_J_num_23_16 0xA23A | ||
| 1538 | #define ste_J_num_23_16_pos 0 | ||
| 1539 | #define ste_J_num_23_16_len 8 | ||
| 1540 | #define ste_J_num_23_16_lsb 16 | ||
| 1541 | #define xd_r_ste_J_num_31_24 0xA23B | ||
| 1542 | #define ste_J_num_31_24_pos 0 | ||
| 1543 | #define ste_J_num_31_24_len 8 | ||
| 1544 | #define ste_J_num_31_24_lsb 24 | ||
| 1545 | #define xd_r_ste_J_den_7_0 0xA23C | ||
| 1546 | #define ste_J_den_7_0_pos 0 | ||
| 1547 | #define ste_J_den_7_0_len 8 | ||
| 1548 | #define ste_J_den_7_0_lsb 0 | ||
| 1549 | #define xd_r_ste_J_den_15_8 0xA23D | ||
| 1550 | #define ste_J_den_15_8_pos 0 | ||
| 1551 | #define ste_J_den_15_8_len 8 | ||
| 1552 | #define ste_J_den_15_8_lsb 8 | ||
| 1553 | #define xd_r_ste_J_den_18_16 0xA23E | ||
| 1554 | #define ste_J_den_18_16_pos 0 | ||
| 1555 | #define ste_J_den_18_16_len 3 | ||
| 1556 | #define ste_J_den_18_16_lsb 16 | ||
| 1557 | #define xd_r_ste_Beacon_Indicator 0xA23E | ||
| 1558 | #define ste_Beacon_Indicator_pos 4 | ||
| 1559 | #define ste_Beacon_Indicator_len 1 | ||
| 1560 | #define ste_Beacon_Indicator_lsb 0 | ||
| 1561 | #define xd_r_tpsd_Frame_Num 0xA250 | ||
| 1562 | #define tpsd_Frame_Num_pos 0 | ||
| 1563 | #define tpsd_Frame_Num_len 2 | ||
| 1564 | #define tpsd_Frame_Num_lsb 0 | ||
| 1565 | #define xd_r_tpsd_Constel 0xA250 | ||
| 1566 | #define tpsd_Constel_pos 2 | ||
| 1567 | #define tpsd_Constel_len 2 | ||
| 1568 | #define tpsd_Constel_lsb 0 | ||
| 1569 | #define xd_r_tpsd_GI 0xA250 | ||
| 1570 | #define tpsd_GI_pos 4 | ||
| 1571 | #define tpsd_GI_len 2 | ||
| 1572 | #define tpsd_GI_lsb 0 | ||
| 1573 | #define xd_r_tpsd_Mode 0xA250 | ||
| 1574 | #define tpsd_Mode_pos 6 | ||
| 1575 | #define tpsd_Mode_len 2 | ||
| 1576 | #define tpsd_Mode_lsb 0 | ||
| 1577 | #define xd_r_tpsd_CR_HP 0xA251 | ||
| 1578 | #define tpsd_CR_HP_pos 0 | ||
| 1579 | #define tpsd_CR_HP_len 3 | ||
| 1580 | #define tpsd_CR_HP_lsb 0 | ||
| 1581 | #define xd_r_tpsd_CR_LP 0xA251 | ||
| 1582 | #define tpsd_CR_LP_pos 3 | ||
| 1583 | #define tpsd_CR_LP_len 3 | ||
| 1584 | #define tpsd_CR_LP_lsb 0 | ||
| 1585 | #define xd_r_tpsd_Hie 0xA252 | ||
| 1586 | #define tpsd_Hie_pos 0 | ||
| 1587 | #define tpsd_Hie_len 3 | ||
| 1588 | #define tpsd_Hie_lsb 0 | ||
| 1589 | #define xd_r_tpsd_Res_Bits 0xA252 | ||
| 1590 | #define tpsd_Res_Bits_pos 3 | ||
| 1591 | #define tpsd_Res_Bits_len 5 | ||
| 1592 | #define tpsd_Res_Bits_lsb 0 | ||
| 1593 | #define xd_r_tpsd_Res_Bits_0 0xA253 | ||
| 1594 | #define tpsd_Res_Bits_0_pos 0 | ||
| 1595 | #define tpsd_Res_Bits_0_len 1 | ||
| 1596 | #define tpsd_Res_Bits_0_lsb 0 | ||
| 1597 | #define xd_r_tpsd_LengthInd 0xA253 | ||
| 1598 | #define tpsd_LengthInd_pos 1 | ||
| 1599 | #define tpsd_LengthInd_len 6 | ||
| 1600 | #define tpsd_LengthInd_lsb 0 | ||
| 1601 | #define xd_r_tpsd_Cell_Id_7_0 0xA254 | ||
| 1602 | #define tpsd_Cell_Id_7_0_pos 0 | ||
| 1603 | #define tpsd_Cell_Id_7_0_len 8 | ||
| 1604 | #define tpsd_Cell_Id_7_0_lsb 0 | ||
| 1605 | #define xd_r_tpsd_Cell_Id_15_8 0xA255 | ||
| 1606 | #define tpsd_Cell_Id_15_8_pos 0 | ||
| 1607 | #define tpsd_Cell_Id_15_8_len 8 | ||
| 1608 | #define tpsd_Cell_Id_15_8_lsb 0 | ||
| 1609 | #define xd_p_reg_fft_mask_tone0_7_0 0xA260 | ||
| 1610 | #define reg_fft_mask_tone0_7_0_pos 0 | ||
| 1611 | #define reg_fft_mask_tone0_7_0_len 8 | ||
| 1612 | #define reg_fft_mask_tone0_7_0_lsb 0 | ||
| 1613 | #define xd_p_reg_fft_mask_tone0_12_8 0xA261 | ||
| 1614 | #define reg_fft_mask_tone0_12_8_pos 0 | ||
| 1615 | #define reg_fft_mask_tone0_12_8_len 5 | ||
| 1616 | #define reg_fft_mask_tone0_12_8_lsb 8 | ||
| 1617 | #define xd_p_reg_fft_mask_tone1_7_0 0xA262 | ||
| 1618 | #define reg_fft_mask_tone1_7_0_pos 0 | ||
| 1619 | #define reg_fft_mask_tone1_7_0_len 8 | ||
| 1620 | #define reg_fft_mask_tone1_7_0_lsb 0 | ||
| 1621 | #define xd_p_reg_fft_mask_tone1_12_8 0xA263 | ||
| 1622 | #define reg_fft_mask_tone1_12_8_pos 0 | ||
| 1623 | #define reg_fft_mask_tone1_12_8_len 5 | ||
| 1624 | #define reg_fft_mask_tone1_12_8_lsb 8 | ||
| 1625 | #define xd_p_reg_fft_mask_tone2_7_0 0xA264 | ||
| 1626 | #define reg_fft_mask_tone2_7_0_pos 0 | ||
| 1627 | #define reg_fft_mask_tone2_7_0_len 8 | ||
| 1628 | #define reg_fft_mask_tone2_7_0_lsb 0 | ||
| 1629 | #define xd_p_reg_fft_mask_tone2_12_8 0xA265 | ||
| 1630 | #define reg_fft_mask_tone2_12_8_pos 0 | ||
| 1631 | #define reg_fft_mask_tone2_12_8_len 5 | ||
| 1632 | #define reg_fft_mask_tone2_12_8_lsb 8 | ||
| 1633 | #define xd_p_reg_fft_mask_tone3_7_0 0xA266 | ||
| 1634 | #define reg_fft_mask_tone3_7_0_pos 0 | ||
| 1635 | #define reg_fft_mask_tone3_7_0_len 8 | ||
| 1636 | #define reg_fft_mask_tone3_7_0_lsb 0 | ||
| 1637 | #define xd_p_reg_fft_mask_tone3_12_8 0xA267 | ||
| 1638 | #define reg_fft_mask_tone3_12_8_pos 0 | ||
| 1639 | #define reg_fft_mask_tone3_12_8_len 5 | ||
| 1640 | #define reg_fft_mask_tone3_12_8_lsb 8 | ||
| 1641 | #define xd_p_reg_fft_mask_from0_7_0 0xA268 | ||
| 1642 | #define reg_fft_mask_from0_7_0_pos 0 | ||
| 1643 | #define reg_fft_mask_from0_7_0_len 8 | ||
| 1644 | #define reg_fft_mask_from0_7_0_lsb 0 | ||
| 1645 | #define xd_p_reg_fft_mask_from0_12_8 0xA269 | ||
| 1646 | #define reg_fft_mask_from0_12_8_pos 0 | ||
| 1647 | #define reg_fft_mask_from0_12_8_len 5 | ||
| 1648 | #define reg_fft_mask_from0_12_8_lsb 8 | ||
| 1649 | #define xd_p_reg_fft_mask_to0_7_0 0xA26A | ||
| 1650 | #define reg_fft_mask_to0_7_0_pos 0 | ||
| 1651 | #define reg_fft_mask_to0_7_0_len 8 | ||
| 1652 | #define reg_fft_mask_to0_7_0_lsb 0 | ||
| 1653 | #define xd_p_reg_fft_mask_to0_12_8 0xA26B | ||
| 1654 | #define reg_fft_mask_to0_12_8_pos 0 | ||
| 1655 | #define reg_fft_mask_to0_12_8_len 5 | ||
| 1656 | #define reg_fft_mask_to0_12_8_lsb 8 | ||
| 1657 | #define xd_p_reg_fft_mask_from1_7_0 0xA26C | ||
| 1658 | #define reg_fft_mask_from1_7_0_pos 0 | ||
| 1659 | #define reg_fft_mask_from1_7_0_len 8 | ||
| 1660 | #define reg_fft_mask_from1_7_0_lsb 0 | ||
| 1661 | #define xd_p_reg_fft_mask_from1_12_8 0xA26D | ||
| 1662 | #define reg_fft_mask_from1_12_8_pos 0 | ||
| 1663 | #define reg_fft_mask_from1_12_8_len 5 | ||
| 1664 | #define reg_fft_mask_from1_12_8_lsb 8 | ||
| 1665 | #define xd_p_reg_fft_mask_to1_7_0 0xA26E | ||
| 1666 | #define reg_fft_mask_to1_7_0_pos 0 | ||
| 1667 | #define reg_fft_mask_to1_7_0_len 8 | ||
| 1668 | #define reg_fft_mask_to1_7_0_lsb 0 | ||
| 1669 | #define xd_p_reg_fft_mask_to1_12_8 0xA26F | ||
| 1670 | #define reg_fft_mask_to1_12_8_pos 0 | ||
| 1671 | #define reg_fft_mask_to1_12_8_len 5 | ||
| 1672 | #define reg_fft_mask_to1_12_8_lsb 8 | ||
| 1673 | #define xd_p_reg_cge_idx0_7_0 0xA280 | ||
| 1674 | #define reg_cge_idx0_7_0_pos 0 | ||
| 1675 | #define reg_cge_idx0_7_0_len 8 | ||
| 1676 | #define reg_cge_idx0_7_0_lsb 0 | ||
| 1677 | #define xd_p_reg_cge_idx0_12_8 0xA281 | ||
| 1678 | #define reg_cge_idx0_12_8_pos 0 | ||
| 1679 | #define reg_cge_idx0_12_8_len 5 | ||
| 1680 | #define reg_cge_idx0_12_8_lsb 8 | ||
| 1681 | #define xd_p_reg_cge_idx1_7_0 0xA282 | ||
| 1682 | #define reg_cge_idx1_7_0_pos 0 | ||
| 1683 | #define reg_cge_idx1_7_0_len 8 | ||
| 1684 | #define reg_cge_idx1_7_0_lsb 0 | ||
| 1685 | #define xd_p_reg_cge_idx1_12_8 0xA283 | ||
| 1686 | #define reg_cge_idx1_12_8_pos 0 | ||
| 1687 | #define reg_cge_idx1_12_8_len 5 | ||
| 1688 | #define reg_cge_idx1_12_8_lsb 8 | ||
| 1689 | #define xd_p_reg_cge_idx2_7_0 0xA284 | ||
| 1690 | #define reg_cge_idx2_7_0_pos 0 | ||
| 1691 | #define reg_cge_idx2_7_0_len 8 | ||
| 1692 | #define reg_cge_idx2_7_0_lsb 0 | ||
| 1693 | #define xd_p_reg_cge_idx2_12_8 0xA285 | ||
| 1694 | #define reg_cge_idx2_12_8_pos 0 | ||
| 1695 | #define reg_cge_idx2_12_8_len 5 | ||
| 1696 | #define reg_cge_idx2_12_8_lsb 8 | ||
| 1697 | #define xd_p_reg_cge_idx3_7_0 0xA286 | ||
| 1698 | #define reg_cge_idx3_7_0_pos 0 | ||
| 1699 | #define reg_cge_idx3_7_0_len 8 | ||
| 1700 | #define reg_cge_idx3_7_0_lsb 0 | ||
| 1701 | #define xd_p_reg_cge_idx3_12_8 0xA287 | ||
| 1702 | #define reg_cge_idx3_12_8_pos 0 | ||
| 1703 | #define reg_cge_idx3_12_8_len 5 | ||
| 1704 | #define reg_cge_idx3_12_8_lsb 8 | ||
| 1705 | #define xd_p_reg_cge_idx4_7_0 0xA288 | ||
| 1706 | #define reg_cge_idx4_7_0_pos 0 | ||
| 1707 | #define reg_cge_idx4_7_0_len 8 | ||
| 1708 | #define reg_cge_idx4_7_0_lsb 0 | ||
| 1709 | #define xd_p_reg_cge_idx4_12_8 0xA289 | ||
| 1710 | #define reg_cge_idx4_12_8_pos 0 | ||
| 1711 | #define reg_cge_idx4_12_8_len 5 | ||
| 1712 | #define reg_cge_idx4_12_8_lsb 8 | ||
| 1713 | #define xd_p_reg_cge_idx5_7_0 0xA28A | ||
| 1714 | #define reg_cge_idx5_7_0_pos 0 | ||
| 1715 | #define reg_cge_idx5_7_0_len 8 | ||
| 1716 | #define reg_cge_idx5_7_0_lsb 0 | ||
| 1717 | #define xd_p_reg_cge_idx5_12_8 0xA28B | ||
| 1718 | #define reg_cge_idx5_12_8_pos 0 | ||
| 1719 | #define reg_cge_idx5_12_8_len 5 | ||
| 1720 | #define reg_cge_idx5_12_8_lsb 8 | ||
| 1721 | #define xd_p_reg_cge_idx6_7_0 0xA28C | ||
| 1722 | #define reg_cge_idx6_7_0_pos 0 | ||
| 1723 | #define reg_cge_idx6_7_0_len 8 | ||
| 1724 | #define reg_cge_idx6_7_0_lsb 0 | ||
| 1725 | #define xd_p_reg_cge_idx6_12_8 0xA28D | ||
| 1726 | #define reg_cge_idx6_12_8_pos 0 | ||
| 1727 | #define reg_cge_idx6_12_8_len 5 | ||
| 1728 | #define reg_cge_idx6_12_8_lsb 8 | ||
| 1729 | #define xd_p_reg_cge_idx7_7_0 0xA28E | ||
| 1730 | #define reg_cge_idx7_7_0_pos 0 | ||
| 1731 | #define reg_cge_idx7_7_0_len 8 | ||
| 1732 | #define reg_cge_idx7_7_0_lsb 0 | ||
| 1733 | #define xd_p_reg_cge_idx7_12_8 0xA28F | ||
| 1734 | #define reg_cge_idx7_12_8_pos 0 | ||
| 1735 | #define reg_cge_idx7_12_8_len 5 | ||
| 1736 | #define reg_cge_idx7_12_8_lsb 8 | ||
| 1737 | #define xd_p_reg_cge_idx8_7_0 0xA290 | ||
| 1738 | #define reg_cge_idx8_7_0_pos 0 | ||
| 1739 | #define reg_cge_idx8_7_0_len 8 | ||
| 1740 | #define reg_cge_idx8_7_0_lsb 0 | ||
| 1741 | #define xd_p_reg_cge_idx8_12_8 0xA291 | ||
| 1742 | #define reg_cge_idx8_12_8_pos 0 | ||
| 1743 | #define reg_cge_idx8_12_8_len 5 | ||
| 1744 | #define reg_cge_idx8_12_8_lsb 8 | ||
| 1745 | #define xd_p_reg_cge_idx9_7_0 0xA292 | ||
| 1746 | #define reg_cge_idx9_7_0_pos 0 | ||
| 1747 | #define reg_cge_idx9_7_0_len 8 | ||
| 1748 | #define reg_cge_idx9_7_0_lsb 0 | ||
| 1749 | #define xd_p_reg_cge_idx9_12_8 0xA293 | ||
| 1750 | #define reg_cge_idx9_12_8_pos 0 | ||
| 1751 | #define reg_cge_idx9_12_8_len 5 | ||
| 1752 | #define reg_cge_idx9_12_8_lsb 8 | ||
| 1753 | #define xd_p_reg_cge_idx10_7_0 0xA294 | ||
| 1754 | #define reg_cge_idx10_7_0_pos 0 | ||
| 1755 | #define reg_cge_idx10_7_0_len 8 | ||
| 1756 | #define reg_cge_idx10_7_0_lsb 0 | ||
| 1757 | #define xd_p_reg_cge_idx10_12_8 0xA295 | ||
| 1758 | #define reg_cge_idx10_12_8_pos 0 | ||
| 1759 | #define reg_cge_idx10_12_8_len 5 | ||
| 1760 | #define reg_cge_idx10_12_8_lsb 8 | ||
| 1761 | #define xd_p_reg_cge_idx11_7_0 0xA296 | ||
| 1762 | #define reg_cge_idx11_7_0_pos 0 | ||
| 1763 | #define reg_cge_idx11_7_0_len 8 | ||
| 1764 | #define reg_cge_idx11_7_0_lsb 0 | ||
| 1765 | #define xd_p_reg_cge_idx11_12_8 0xA297 | ||
| 1766 | #define reg_cge_idx11_12_8_pos 0 | ||
| 1767 | #define reg_cge_idx11_12_8_len 5 | ||
| 1768 | #define reg_cge_idx11_12_8_lsb 8 | ||
| 1769 | #define xd_p_reg_cge_idx12_7_0 0xA298 | ||
| 1770 | #define reg_cge_idx12_7_0_pos 0 | ||
| 1771 | #define reg_cge_idx12_7_0_len 8 | ||
| 1772 | #define reg_cge_idx12_7_0_lsb 0 | ||
| 1773 | #define xd_p_reg_cge_idx12_12_8 0xA299 | ||
| 1774 | #define reg_cge_idx12_12_8_pos 0 | ||
| 1775 | #define reg_cge_idx12_12_8_len 5 | ||
| 1776 | #define reg_cge_idx12_12_8_lsb 8 | ||
| 1777 | #define xd_p_reg_cge_idx13_7_0 0xA29A | ||
| 1778 | #define reg_cge_idx13_7_0_pos 0 | ||
| 1779 | #define reg_cge_idx13_7_0_len 8 | ||
| 1780 | #define reg_cge_idx13_7_0_lsb 0 | ||
| 1781 | #define xd_p_reg_cge_idx13_12_8 0xA29B | ||
| 1782 | #define reg_cge_idx13_12_8_pos 0 | ||
| 1783 | #define reg_cge_idx13_12_8_len 5 | ||
| 1784 | #define reg_cge_idx13_12_8_lsb 8 | ||
| 1785 | #define xd_p_reg_cge_idx14_7_0 0xA29C | ||
| 1786 | #define reg_cge_idx14_7_0_pos 0 | ||
| 1787 | #define reg_cge_idx14_7_0_len 8 | ||
| 1788 | #define reg_cge_idx14_7_0_lsb 0 | ||
| 1789 | #define xd_p_reg_cge_idx14_12_8 0xA29D | ||
| 1790 | #define reg_cge_idx14_12_8_pos 0 | ||
| 1791 | #define reg_cge_idx14_12_8_len 5 | ||
| 1792 | #define reg_cge_idx14_12_8_lsb 8 | ||
| 1793 | #define xd_p_reg_cge_idx15_7_0 0xA29E | ||
| 1794 | #define reg_cge_idx15_7_0_pos 0 | ||
| 1795 | #define reg_cge_idx15_7_0_len 8 | ||
| 1796 | #define reg_cge_idx15_7_0_lsb 0 | ||
| 1797 | #define xd_p_reg_cge_idx15_12_8 0xA29F | ||
| 1798 | #define reg_cge_idx15_12_8_pos 0 | ||
| 1799 | #define reg_cge_idx15_12_8_len 5 | ||
| 1800 | #define reg_cge_idx15_12_8_lsb 8 | ||
| 1801 | #define xd_r_reg_fft_crc 0xA2A8 | ||
| 1802 | #define reg_fft_crc_pos 0 | ||
| 1803 | #define reg_fft_crc_len 8 | ||
| 1804 | #define reg_fft_crc_lsb 0 | ||
| 1805 | #define xd_p_fd_fft_shift_max 0xA2A9 | ||
| 1806 | #define fd_fft_shift_max_pos 0 | ||
| 1807 | #define fd_fft_shift_max_len 4 | ||
| 1808 | #define fd_fft_shift_max_lsb 0 | ||
| 1809 | #define xd_r_fd_fft_shift 0xA2A9 | ||
| 1810 | #define fd_fft_shift_pos 4 | ||
| 1811 | #define fd_fft_shift_len 4 | ||
| 1812 | #define fd_fft_shift_lsb 0 | ||
| 1813 | #define xd_r_fd_fft_frame_num 0xA2AA | ||
| 1814 | #define fd_fft_frame_num_pos 0 | ||
| 1815 | #define fd_fft_frame_num_len 2 | ||
| 1816 | #define fd_fft_frame_num_lsb 0 | ||
| 1817 | #define xd_r_fd_fft_symbol_count 0xA2AB | ||
| 1818 | #define fd_fft_symbol_count_pos 0 | ||
| 1819 | #define fd_fft_symbol_count_len 7 | ||
| 1820 | #define fd_fft_symbol_count_lsb 0 | ||
| 1821 | #define xd_r_reg_fft_idx_max_7_0 0xA2AC | ||
| 1822 | #define reg_fft_idx_max_7_0_pos 0 | ||
| 1823 | #define reg_fft_idx_max_7_0_len 8 | ||
| 1824 | #define reg_fft_idx_max_7_0_lsb 0 | ||
| 1825 | #define xd_r_reg_fft_idx_max_12_8 0xA2AD | ||
| 1826 | #define reg_fft_idx_max_12_8_pos 0 | ||
| 1827 | #define reg_fft_idx_max_12_8_len 5 | ||
| 1828 | #define reg_fft_idx_max_12_8_lsb 8 | ||
| 1829 | #define xd_p_reg_cge_program 0xA2AE | ||
| 1830 | #define reg_cge_program_pos 0 | ||
| 1831 | #define reg_cge_program_len 1 | ||
| 1832 | #define reg_cge_program_lsb 0 | ||
| 1833 | #define xd_p_reg_cge_fixed 0xA2AE | ||
| 1834 | #define reg_cge_fixed_pos 1 | ||
| 1835 | #define reg_cge_fixed_len 1 | ||
| 1836 | #define reg_cge_fixed_lsb 0 | ||
| 1837 | #define xd_p_reg_fft_rotate_en 0xA2AE | ||
| 1838 | #define reg_fft_rotate_en_pos 2 | ||
| 1839 | #define reg_fft_rotate_en_len 1 | ||
| 1840 | #define reg_fft_rotate_en_lsb 0 | ||
| 1841 | #define xd_p_reg_fft_rotate_base_4_0 0xA2AE | ||
| 1842 | #define reg_fft_rotate_base_4_0_pos 3 | ||
| 1843 | #define reg_fft_rotate_base_4_0_len 5 | ||
| 1844 | #define reg_fft_rotate_base_4_0_lsb 0 | ||
| 1845 | #define xd_p_reg_fft_rotate_base_12_5 0xA2AF | ||
| 1846 | #define reg_fft_rotate_base_12_5_pos 0 | ||
| 1847 | #define reg_fft_rotate_base_12_5_len 8 | ||
| 1848 | #define reg_fft_rotate_base_12_5_lsb 5 | ||
| 1849 | #define xd_p_reg_gp_trigger_fd 0xA2B8 | ||
| 1850 | #define reg_gp_trigger_fd_pos 0 | ||
| 1851 | #define reg_gp_trigger_fd_len 1 | ||
| 1852 | #define reg_gp_trigger_fd_lsb 0 | ||
| 1853 | #define xd_p_reg_trigger_sel_fd 0xA2B8 | ||
| 1854 | #define reg_trigger_sel_fd_pos 1 | ||
| 1855 | #define reg_trigger_sel_fd_len 2 | ||
| 1856 | #define reg_trigger_sel_fd_lsb 0 | ||
| 1857 | #define xd_p_reg_trigger_module_sel_fd 0xA2B9 | ||
| 1858 | #define reg_trigger_module_sel_fd_pos 0 | ||
| 1859 | #define reg_trigger_module_sel_fd_len 6 | ||
| 1860 | #define reg_trigger_module_sel_fd_lsb 0 | ||
| 1861 | #define xd_p_reg_trigger_set_sel_fd 0xA2BA | ||
| 1862 | #define reg_trigger_set_sel_fd_pos 0 | ||
| 1863 | #define reg_trigger_set_sel_fd_len 6 | ||
| 1864 | #define reg_trigger_set_sel_fd_lsb 0 | ||
| 1865 | #define xd_p_reg_fd_noname_7_0 0xA2BC | ||
| 1866 | #define reg_fd_noname_7_0_pos 0 | ||
| 1867 | #define reg_fd_noname_7_0_len 8 | ||
| 1868 | #define reg_fd_noname_7_0_lsb 0 | ||
| 1869 | #define xd_p_reg_fd_noname_15_8 0xA2BD | ||
| 1870 | #define reg_fd_noname_15_8_pos 0 | ||
| 1871 | #define reg_fd_noname_15_8_len 8 | ||
| 1872 | #define reg_fd_noname_15_8_lsb 8 | ||
| 1873 | #define xd_p_reg_fd_noname_23_16 0xA2BE | ||
| 1874 | #define reg_fd_noname_23_16_pos 0 | ||
| 1875 | #define reg_fd_noname_23_16_len 8 | ||
| 1876 | #define reg_fd_noname_23_16_lsb 16 | ||
| 1877 | #define xd_p_reg_fd_noname_31_24 0xA2BF | ||
| 1878 | #define reg_fd_noname_31_24_pos 0 | ||
| 1879 | #define reg_fd_noname_31_24_len 8 | ||
| 1880 | #define reg_fd_noname_31_24_lsb 24 | ||
| 1881 | #define xd_r_fd_fpcc_cp_corr_signn 0xA2C0 | ||
| 1882 | #define fd_fpcc_cp_corr_signn_pos 0 | ||
| 1883 | #define fd_fpcc_cp_corr_signn_len 8 | ||
| 1884 | #define fd_fpcc_cp_corr_signn_lsb 0 | ||
| 1885 | #define xd_p_reg_feq_s1 0xA2C1 | ||
| 1886 | #define reg_feq_s1_pos 0 | ||
| 1887 | #define reg_feq_s1_len 5 | ||
| 1888 | #define reg_feq_s1_lsb 0 | ||
| 1889 | #define xd_p_fd_fpcc_cp_corr_tone_th 0xA2C2 | ||
| 1890 | #define fd_fpcc_cp_corr_tone_th_pos 0 | ||
| 1891 | #define fd_fpcc_cp_corr_tone_th_len 6 | ||
| 1892 | #define fd_fpcc_cp_corr_tone_th_lsb 0 | ||
| 1893 | #define xd_p_fd_fpcc_cp_corr_symbol_log_th 0xA2C3 | ||
| 1894 | #define fd_fpcc_cp_corr_symbol_log_th_pos 0 | ||
| 1895 | #define fd_fpcc_cp_corr_symbol_log_th_len 4 | ||
| 1896 | #define fd_fpcc_cp_corr_symbol_log_th_lsb 0 | ||
| 1897 | #define xd_p_fd_fpcc_cp_corr_int 0xA2C4 | ||
| 1898 | #define fd_fpcc_cp_corr_int_pos 0 | ||
| 1899 | #define fd_fpcc_cp_corr_int_len 1 | ||
| 1900 | #define fd_fpcc_cp_corr_int_lsb 0 | ||
| 1901 | #define xd_p_reg_sfoe_ns_7_0 0xA320 | ||
| 1902 | #define reg_sfoe_ns_7_0_pos 0 | ||
| 1903 | #define reg_sfoe_ns_7_0_len 8 | ||
| 1904 | #define reg_sfoe_ns_7_0_lsb 0 | ||
| 1905 | #define xd_p_reg_sfoe_ns_14_8 0xA321 | ||
| 1906 | #define reg_sfoe_ns_14_8_pos 0 | ||
| 1907 | #define reg_sfoe_ns_14_8_len 7 | ||
| 1908 | #define reg_sfoe_ns_14_8_lsb 8 | ||
| 1909 | #define xd_p_reg_sfoe_c1_7_0 0xA322 | ||
| 1910 | #define reg_sfoe_c1_7_0_pos 0 | ||
| 1911 | #define reg_sfoe_c1_7_0_len 8 | ||
| 1912 | #define reg_sfoe_c1_7_0_lsb 0 | ||
| 1913 | #define xd_p_reg_sfoe_c1_15_8 0xA323 | ||
| 1914 | #define reg_sfoe_c1_15_8_pos 0 | ||
| 1915 | #define reg_sfoe_c1_15_8_len 8 | ||
| 1916 | #define reg_sfoe_c1_15_8_lsb 8 | ||
| 1917 | #define xd_p_reg_sfoe_c1_17_16 0xA324 | ||
| 1918 | #define reg_sfoe_c1_17_16_pos 0 | ||
| 1919 | #define reg_sfoe_c1_17_16_len 2 | ||
| 1920 | #define reg_sfoe_c1_17_16_lsb 16 | ||
| 1921 | #define xd_p_reg_sfoe_c2_7_0 0xA325 | ||
| 1922 | #define reg_sfoe_c2_7_0_pos 0 | ||
| 1923 | #define reg_sfoe_c2_7_0_len 8 | ||
| 1924 | #define reg_sfoe_c2_7_0_lsb 0 | ||
| 1925 | #define xd_p_reg_sfoe_c2_15_8 0xA326 | ||
| 1926 | #define reg_sfoe_c2_15_8_pos 0 | ||
| 1927 | #define reg_sfoe_c2_15_8_len 8 | ||
| 1928 | #define reg_sfoe_c2_15_8_lsb 8 | ||
| 1929 | #define xd_p_reg_sfoe_c2_17_16 0xA327 | ||
| 1930 | #define reg_sfoe_c2_17_16_pos 0 | ||
| 1931 | #define reg_sfoe_c2_17_16_len 2 | ||
| 1932 | #define reg_sfoe_c2_17_16_lsb 16 | ||
| 1933 | #define xd_r_reg_sfoe_out_9_2 0xA328 | ||
| 1934 | #define reg_sfoe_out_9_2_pos 0 | ||
| 1935 | #define reg_sfoe_out_9_2_len 8 | ||
| 1936 | #define reg_sfoe_out_9_2_lsb 0 | ||
| 1937 | #define xd_r_reg_sfoe_out_1_0 0xA329 | ||
| 1938 | #define reg_sfoe_out_1_0_pos 0 | ||
| 1939 | #define reg_sfoe_out_1_0_len 2 | ||
| 1940 | #define reg_sfoe_out_1_0_lsb 0 | ||
| 1941 | #define xd_p_reg_sfoe_lm_counter_th 0xA32A | ||
| 1942 | #define reg_sfoe_lm_counter_th_pos 0 | ||
| 1943 | #define reg_sfoe_lm_counter_th_len 4 | ||
| 1944 | #define reg_sfoe_lm_counter_th_lsb 0 | ||
| 1945 | #define xd_p_reg_sfoe_convg_th 0xA32B | ||
| 1946 | #define reg_sfoe_convg_th_pos 0 | ||
| 1947 | #define reg_sfoe_convg_th_len 8 | ||
| 1948 | #define reg_sfoe_convg_th_lsb 0 | ||
| 1949 | #define xd_p_reg_sfoe_divg_th 0xA32C | ||
| 1950 | #define reg_sfoe_divg_th_pos 0 | ||
| 1951 | #define reg_sfoe_divg_th_len 8 | ||
| 1952 | #define reg_sfoe_divg_th_lsb 0 | ||
| 1953 | #define xd_p_fd_tpsd_en 0xA330 | ||
| 1954 | #define fd_tpsd_en_pos 0 | ||
| 1955 | #define fd_tpsd_en_len 1 | ||
| 1956 | #define fd_tpsd_en_lsb 0 | ||
| 1957 | #define xd_p_fd_tpsd_dis 0xA330 | ||
| 1958 | #define fd_tpsd_dis_pos 1 | ||
| 1959 | #define fd_tpsd_dis_len 1 | ||
| 1960 | #define fd_tpsd_dis_lsb 0 | ||
| 1961 | #define xd_p_fd_tpsd_rst 0xA330 | ||
| 1962 | #define fd_tpsd_rst_pos 2 | ||
| 1963 | #define fd_tpsd_rst_len 1 | ||
| 1964 | #define fd_tpsd_rst_lsb 0 | ||
| 1965 | #define xd_p_fd_tpsd_lock 0xA330 | ||
| 1966 | #define fd_tpsd_lock_pos 3 | ||
| 1967 | #define fd_tpsd_lock_len 1 | ||
| 1968 | #define fd_tpsd_lock_lsb 0 | ||
| 1969 | #define xd_r_fd_tpsd_s19 0xA330 | ||
| 1970 | #define fd_tpsd_s19_pos 4 | ||
| 1971 | #define fd_tpsd_s19_len 1 | ||
| 1972 | #define fd_tpsd_s19_lsb 0 | ||
| 1973 | #define xd_r_fd_tpsd_s17 0xA330 | ||
| 1974 | #define fd_tpsd_s17_pos 5 | ||
| 1975 | #define fd_tpsd_s17_len 1 | ||
| 1976 | #define fd_tpsd_s17_lsb 0 | ||
| 1977 | #define xd_p_fd_sfr_ste_en 0xA331 | ||
| 1978 | #define fd_sfr_ste_en_pos 0 | ||
| 1979 | #define fd_sfr_ste_en_len 1 | ||
| 1980 | #define fd_sfr_ste_en_lsb 0 | ||
| 1981 | #define xd_p_fd_sfr_ste_dis 0xA331 | ||
| 1982 | #define fd_sfr_ste_dis_pos 1 | ||
| 1983 | #define fd_sfr_ste_dis_len 1 | ||
| 1984 | #define fd_sfr_ste_dis_lsb 0 | ||
| 1985 | #define xd_p_fd_sfr_ste_rst 0xA331 | ||
| 1986 | #define fd_sfr_ste_rst_pos 2 | ||
| 1987 | #define fd_sfr_ste_rst_len 1 | ||
| 1988 | #define fd_sfr_ste_rst_lsb 0 | ||
| 1989 | #define xd_p_fd_sfr_ste_mode 0xA331 | ||
| 1990 | #define fd_sfr_ste_mode_pos 3 | ||
| 1991 | #define fd_sfr_ste_mode_len 1 | ||
| 1992 | #define fd_sfr_ste_mode_lsb 0 | ||
| 1993 | #define xd_p_fd_sfr_ste_done 0xA331 | ||
| 1994 | #define fd_sfr_ste_done_pos 4 | ||
| 1995 | #define fd_sfr_ste_done_len 1 | ||
| 1996 | #define fd_sfr_ste_done_lsb 0 | ||
| 1997 | #define xd_p_reg_cfoe_ffoe_en 0xA332 | ||
| 1998 | #define reg_cfoe_ffoe_en_pos 0 | ||
| 1999 | #define reg_cfoe_ffoe_en_len 1 | ||
| 2000 | #define reg_cfoe_ffoe_en_lsb 0 | ||
| 2001 | #define xd_p_reg_cfoe_ffoe_dis 0xA332 | ||
| 2002 | #define reg_cfoe_ffoe_dis_pos 1 | ||
| 2003 | #define reg_cfoe_ffoe_dis_len 1 | ||
| 2004 | #define reg_cfoe_ffoe_dis_lsb 0 | ||
| 2005 | #define xd_p_reg_cfoe_ffoe_rst 0xA332 | ||
| 2006 | #define reg_cfoe_ffoe_rst_pos 2 | ||
| 2007 | #define reg_cfoe_ffoe_rst_len 1 | ||
| 2008 | #define reg_cfoe_ffoe_rst_lsb 0 | ||
| 2009 | #define xd_p_reg_cfoe_ifoe_en 0xA332 | ||
| 2010 | #define reg_cfoe_ifoe_en_pos 3 | ||
| 2011 | #define reg_cfoe_ifoe_en_len 1 | ||
| 2012 | #define reg_cfoe_ifoe_en_lsb 0 | ||
| 2013 | #define xd_p_reg_cfoe_ifoe_dis 0xA332 | ||
| 2014 | #define reg_cfoe_ifoe_dis_pos 4 | ||
| 2015 | #define reg_cfoe_ifoe_dis_len 1 | ||
| 2016 | #define reg_cfoe_ifoe_dis_lsb 0 | ||
| 2017 | #define xd_p_reg_cfoe_ifoe_rst 0xA332 | ||
| 2018 | #define reg_cfoe_ifoe_rst_pos 5 | ||
| 2019 | #define reg_cfoe_ifoe_rst_len 1 | ||
| 2020 | #define reg_cfoe_ifoe_rst_lsb 0 | ||
| 2021 | #define xd_p_reg_cfoe_fot_en 0xA332 | ||
| 2022 | #define reg_cfoe_fot_en_pos 6 | ||
| 2023 | #define reg_cfoe_fot_en_len 1 | ||
| 2024 | #define reg_cfoe_fot_en_lsb 0 | ||
| 2025 | #define xd_p_reg_cfoe_fot_lm_en 0xA332 | ||
| 2026 | #define reg_cfoe_fot_lm_en_pos 7 | ||
| 2027 | #define reg_cfoe_fot_lm_en_len 1 | ||
| 2028 | #define reg_cfoe_fot_lm_en_lsb 0 | ||
| 2029 | #define xd_p_reg_cfoe_fot_rst 0xA333 | ||
| 2030 | #define reg_cfoe_fot_rst_pos 0 | ||
| 2031 | #define reg_cfoe_fot_rst_len 1 | ||
| 2032 | #define reg_cfoe_fot_rst_lsb 0 | ||
| 2033 | #define xd_r_fd_cfoe_ffoe_done 0xA333 | ||
| 2034 | #define fd_cfoe_ffoe_done_pos 1 | ||
| 2035 | #define fd_cfoe_ffoe_done_len 1 | ||
| 2036 | #define fd_cfoe_ffoe_done_lsb 0 | ||
| 2037 | #define xd_p_fd_cfoe_metric_vld 0xA333 | ||
| 2038 | #define fd_cfoe_metric_vld_pos 2 | ||
| 2039 | #define fd_cfoe_metric_vld_len 1 | ||
| 2040 | #define fd_cfoe_metric_vld_lsb 0 | ||
| 2041 | #define xd_p_reg_cfoe_ifod_vld 0xA333 | ||
| 2042 | #define reg_cfoe_ifod_vld_pos 3 | ||
| 2043 | #define reg_cfoe_ifod_vld_len 1 | ||
| 2044 | #define reg_cfoe_ifod_vld_lsb 0 | ||
| 2045 | #define xd_r_fd_cfoe_ifoe_done 0xA333 | ||
| 2046 | #define fd_cfoe_ifoe_done_pos 4 | ||
| 2047 | #define fd_cfoe_ifoe_done_len 1 | ||
| 2048 | #define fd_cfoe_ifoe_done_lsb 0 | ||
| 2049 | #define xd_r_fd_cfoe_fot_valid 0xA333 | ||
| 2050 | #define fd_cfoe_fot_valid_pos 5 | ||
| 2051 | #define fd_cfoe_fot_valid_len 1 | ||
| 2052 | #define fd_cfoe_fot_valid_lsb 0 | ||
| 2053 | #define xd_p_reg_cfoe_divg_int 0xA333 | ||
| 2054 | #define reg_cfoe_divg_int_pos 6 | ||
| 2055 | #define reg_cfoe_divg_int_len 1 | ||
| 2056 | #define reg_cfoe_divg_int_lsb 0 | ||
| 2057 | #define xd_r_reg_cfoe_divg_flag 0xA333 | ||
| 2058 | #define reg_cfoe_divg_flag_pos 7 | ||
| 2059 | #define reg_cfoe_divg_flag_len 1 | ||
| 2060 | #define reg_cfoe_divg_flag_lsb 0 | ||
| 2061 | #define xd_p_reg_sfoe_en 0xA334 | ||
| 2062 | #define reg_sfoe_en_pos 0 | ||
| 2063 | #define reg_sfoe_en_len 1 | ||
| 2064 | #define reg_sfoe_en_lsb 0 | ||
| 2065 | #define xd_p_reg_sfoe_dis 0xA334 | ||
| 2066 | #define reg_sfoe_dis_pos 1 | ||
| 2067 | #define reg_sfoe_dis_len 1 | ||
| 2068 | #define reg_sfoe_dis_lsb 0 | ||
| 2069 | #define xd_p_reg_sfoe_rst 0xA334 | ||
| 2070 | #define reg_sfoe_rst_pos 2 | ||
| 2071 | #define reg_sfoe_rst_len 1 | ||
| 2072 | #define reg_sfoe_rst_lsb 0 | ||
| 2073 | #define xd_p_reg_sfoe_vld_int 0xA334 | ||
| 2074 | #define reg_sfoe_vld_int_pos 3 | ||
| 2075 | #define reg_sfoe_vld_int_len 1 | ||
| 2076 | #define reg_sfoe_vld_int_lsb 0 | ||
| 2077 | #define xd_p_reg_sfoe_lm_en 0xA334 | ||
| 2078 | #define reg_sfoe_lm_en_pos 4 | ||
| 2079 | #define reg_sfoe_lm_en_len 1 | ||
| 2080 | #define reg_sfoe_lm_en_lsb 0 | ||
| 2081 | #define xd_p_reg_sfoe_divg_int 0xA334 | ||
| 2082 | #define reg_sfoe_divg_int_pos 5 | ||
| 2083 | #define reg_sfoe_divg_int_len 1 | ||
| 2084 | #define reg_sfoe_divg_int_lsb 0 | ||
| 2085 | #define xd_r_reg_sfoe_divg_flag 0xA334 | ||
| 2086 | #define reg_sfoe_divg_flag_pos 6 | ||
| 2087 | #define reg_sfoe_divg_flag_len 1 | ||
| 2088 | #define reg_sfoe_divg_flag_lsb 0 | ||
| 2089 | #define xd_p_reg_fft_rst 0xA335 | ||
| 2090 | #define reg_fft_rst_pos 0 | ||
| 2091 | #define reg_fft_rst_len 1 | ||
| 2092 | #define reg_fft_rst_lsb 0 | ||
| 2093 | #define xd_p_reg_fft_fast_beacon 0xA335 | ||
| 2094 | #define reg_fft_fast_beacon_pos 1 | ||
| 2095 | #define reg_fft_fast_beacon_len 1 | ||
| 2096 | #define reg_fft_fast_beacon_lsb 0 | ||
| 2097 | #define xd_p_reg_fft_fast_valid 0xA335 | ||
| 2098 | #define reg_fft_fast_valid_pos 2 | ||
| 2099 | #define reg_fft_fast_valid_len 1 | ||
| 2100 | #define reg_fft_fast_valid_lsb 0 | ||
| 2101 | #define xd_p_reg_fft_mask_en 0xA335 | ||
| 2102 | #define reg_fft_mask_en_pos 3 | ||
| 2103 | #define reg_fft_mask_en_len 1 | ||
| 2104 | #define reg_fft_mask_en_lsb 0 | ||
| 2105 | #define xd_p_reg_fft_crc_en 0xA335 | ||
| 2106 | #define reg_fft_crc_en_pos 4 | ||
| 2107 | #define reg_fft_crc_en_len 1 | ||
| 2108 | #define reg_fft_crc_en_lsb 0 | ||
| 2109 | #define xd_p_reg_finr_en 0xA336 | ||
| 2110 | #define reg_finr_en_pos 0 | ||
| 2111 | #define reg_finr_en_len 1 | ||
| 2112 | #define reg_finr_en_lsb 0 | ||
| 2113 | #define xd_p_fd_fste_en 0xA337 | ||
| 2114 | #define fd_fste_en_pos 1 | ||
| 2115 | #define fd_fste_en_len 1 | ||
| 2116 | #define fd_fste_en_lsb 0 | ||
| 2117 | #define xd_p_fd_sqi_tps_level_shift 0xA338 | ||
| 2118 | #define fd_sqi_tps_level_shift_pos 0 | ||
| 2119 | #define fd_sqi_tps_level_shift_len 8 | ||
| 2120 | #define fd_sqi_tps_level_shift_lsb 0 | ||
| 2121 | #define xd_p_fd_pilot_ma_len 0xA339 | ||
| 2122 | #define fd_pilot_ma_len_pos 0 | ||
| 2123 | #define fd_pilot_ma_len_len 6 | ||
| 2124 | #define fd_pilot_ma_len_lsb 0 | ||
| 2125 | #define xd_p_fd_tps_ma_len 0xA33A | ||
| 2126 | #define fd_tps_ma_len_pos 0 | ||
| 2127 | #define fd_tps_ma_len_len 6 | ||
| 2128 | #define fd_tps_ma_len_lsb 0 | ||
| 2129 | #define xd_p_fd_sqi_s3 0xA33B | ||
| 2130 | #define fd_sqi_s3_pos 0 | ||
| 2131 | #define fd_sqi_s3_len 8 | ||
| 2132 | #define fd_sqi_s3_lsb 0 | ||
| 2133 | #define xd_p_fd_sqi_dummy_reg_0 0xA33C | ||
| 2134 | #define fd_sqi_dummy_reg_0_pos 0 | ||
| 2135 | #define fd_sqi_dummy_reg_0_len 1 | ||
| 2136 | #define fd_sqi_dummy_reg_0_lsb 0 | ||
| 2137 | #define xd_p_fd_sqi_debug_sel 0xA33C | ||
| 2138 | #define fd_sqi_debug_sel_pos 1 | ||
| 2139 | #define fd_sqi_debug_sel_len 2 | ||
| 2140 | #define fd_sqi_debug_sel_lsb 0 | ||
| 2141 | #define xd_p_fd_sqi_s2 0xA33C | ||
| 2142 | #define fd_sqi_s2_pos 3 | ||
| 2143 | #define fd_sqi_s2_len 5 | ||
| 2144 | #define fd_sqi_s2_lsb 0 | ||
| 2145 | #define xd_p_fd_sqi_dummy_reg_1 0xA33D | ||
| 2146 | #define fd_sqi_dummy_reg_1_pos 0 | ||
| 2147 | #define fd_sqi_dummy_reg_1_len 1 | ||
| 2148 | #define fd_sqi_dummy_reg_1_lsb 0 | ||
| 2149 | #define xd_p_fd_inr_ignore 0xA33D | ||
| 2150 | #define fd_inr_ignore_pos 1 | ||
| 2151 | #define fd_inr_ignore_len 1 | ||
| 2152 | #define fd_inr_ignore_lsb 0 | ||
| 2153 | #define xd_p_fd_pilot_ignore 0xA33D | ||
| 2154 | #define fd_pilot_ignore_pos 2 | ||
| 2155 | #define fd_pilot_ignore_len 1 | ||
| 2156 | #define fd_pilot_ignore_lsb 0 | ||
| 2157 | #define xd_p_fd_etps_ignore 0xA33D | ||
| 2158 | #define fd_etps_ignore_pos 3 | ||
| 2159 | #define fd_etps_ignore_len 1 | ||
| 2160 | #define fd_etps_ignore_lsb 0 | ||
| 2161 | #define xd_p_fd_sqi_s1 0xA33D | ||
| 2162 | #define fd_sqi_s1_pos 4 | ||
| 2163 | #define fd_sqi_s1_len 4 | ||
| 2164 | #define fd_sqi_s1_lsb 0 | ||
| 2165 | #define xd_p_reg_fste_ehw_7_0 0xA33E | ||
| 2166 | #define reg_fste_ehw_7_0_pos 0 | ||
| 2167 | #define reg_fste_ehw_7_0_len 8 | ||
| 2168 | #define reg_fste_ehw_7_0_lsb 0 | ||
| 2169 | #define xd_p_reg_fste_ehw_9_8 0xA33F | ||
| 2170 | #define reg_fste_ehw_9_8_pos 0 | ||
| 2171 | #define reg_fste_ehw_9_8_len 2 | ||
| 2172 | #define reg_fste_ehw_9_8_lsb 8 | ||
| 2173 | #define xd_p_reg_fste_i_adj_vld 0xA33F | ||
| 2174 | #define reg_fste_i_adj_vld_pos 2 | ||
| 2175 | #define reg_fste_i_adj_vld_len 1 | ||
| 2176 | #define reg_fste_i_adj_vld_lsb 0 | ||
| 2177 | #define xd_p_reg_fste_phase_ini_7_0 0xA340 | ||
| 2178 | #define reg_fste_phase_ini_7_0_pos 0 | ||
| 2179 | #define reg_fste_phase_ini_7_0_len 8 | ||
| 2180 | #define reg_fste_phase_ini_7_0_lsb 0 | ||
| 2181 | #define xd_p_reg_fste_phase_ini_11_8 0xA341 | ||
| 2182 | #define reg_fste_phase_ini_11_8_pos 0 | ||
| 2183 | #define reg_fste_phase_ini_11_8_len 4 | ||
| 2184 | #define reg_fste_phase_ini_11_8_lsb 8 | ||
| 2185 | #define xd_p_reg_fste_phase_inc_3_0 0xA341 | ||
| 2186 | #define reg_fste_phase_inc_3_0_pos 4 | ||
| 2187 | #define reg_fste_phase_inc_3_0_len 4 | ||
| 2188 | #define reg_fste_phase_inc_3_0_lsb 0 | ||
| 2189 | #define xd_p_reg_fste_phase_inc_11_4 0xA342 | ||
| 2190 | #define reg_fste_phase_inc_11_4_pos 0 | ||
| 2191 | #define reg_fste_phase_inc_11_4_len 8 | ||
| 2192 | #define reg_fste_phase_inc_11_4_lsb 4 | ||
| 2193 | #define xd_p_reg_fste_acum_cost_cnt_max 0xA343 | ||
| 2194 | #define reg_fste_acum_cost_cnt_max_pos 0 | ||
| 2195 | #define reg_fste_acum_cost_cnt_max_len 4 | ||
| 2196 | #define reg_fste_acum_cost_cnt_max_lsb 0 | ||
| 2197 | #define xd_p_reg_fste_step_size_std 0xA343 | ||
| 2198 | #define reg_fste_step_size_std_pos 4 | ||
| 2199 | #define reg_fste_step_size_std_len 4 | ||
| 2200 | #define reg_fste_step_size_std_lsb 0 | ||
| 2201 | #define xd_p_reg_fste_step_size_max 0xA344 | ||
| 2202 | #define reg_fste_step_size_max_pos 0 | ||
| 2203 | #define reg_fste_step_size_max_len 4 | ||
| 2204 | #define reg_fste_step_size_max_lsb 0 | ||
| 2205 | #define xd_p_reg_fste_step_size_min 0xA344 | ||
| 2206 | #define reg_fste_step_size_min_pos 4 | ||
| 2207 | #define reg_fste_step_size_min_len 4 | ||
| 2208 | #define reg_fste_step_size_min_lsb 0 | ||
| 2209 | #define xd_p_reg_fste_frac_step_size_7_0 0xA345 | ||
| 2210 | #define reg_fste_frac_step_size_7_0_pos 0 | ||
| 2211 | #define reg_fste_frac_step_size_7_0_len 8 | ||
| 2212 | #define reg_fste_frac_step_size_7_0_lsb 0 | ||
| 2213 | #define xd_p_reg_fste_frac_step_size_15_8 0xA346 | ||
| 2214 | #define reg_fste_frac_step_size_15_8_pos 0 | ||
| 2215 | #define reg_fste_frac_step_size_15_8_len 8 | ||
| 2216 | #define reg_fste_frac_step_size_15_8_lsb 8 | ||
| 2217 | #define xd_p_reg_fste_frac_step_size_19_16 0xA347 | ||
| 2218 | #define reg_fste_frac_step_size_19_16_pos 0 | ||
| 2219 | #define reg_fste_frac_step_size_19_16_len 4 | ||
| 2220 | #define reg_fste_frac_step_size_19_16_lsb 16 | ||
| 2221 | #define xd_p_reg_fste_rpd_dir_cnt_max 0xA347 | ||
| 2222 | #define reg_fste_rpd_dir_cnt_max_pos 4 | ||
| 2223 | #define reg_fste_rpd_dir_cnt_max_len 4 | ||
| 2224 | #define reg_fste_rpd_dir_cnt_max_lsb 0 | ||
| 2225 | #define xd_p_reg_fste_ehs 0xA348 | ||
| 2226 | #define reg_fste_ehs_pos 0 | ||
| 2227 | #define reg_fste_ehs_len 4 | ||
| 2228 | #define reg_fste_ehs_lsb 0 | ||
| 2229 | #define xd_p_reg_fste_frac_cost_cnt_max_3_0 0xA348 | ||
| 2230 | #define reg_fste_frac_cost_cnt_max_3_0_pos 4 | ||
| 2231 | #define reg_fste_frac_cost_cnt_max_3_0_len 4 | ||
| 2232 | #define reg_fste_frac_cost_cnt_max_3_0_lsb 0 | ||
| 2233 | #define xd_p_reg_fste_frac_cost_cnt_max_9_4 0xA349 | ||
| 2234 | #define reg_fste_frac_cost_cnt_max_9_4_pos 0 | ||
| 2235 | #define reg_fste_frac_cost_cnt_max_9_4_len 6 | ||
| 2236 | #define reg_fste_frac_cost_cnt_max_9_4_lsb 4 | ||
| 2237 | #define xd_p_reg_fste_w0_7_0 0xA34A | ||
| 2238 | #define reg_fste_w0_7_0_pos 0 | ||
| 2239 | #define reg_fste_w0_7_0_len 8 | ||
| 2240 | #define reg_fste_w0_7_0_lsb 0 | ||
| 2241 | #define xd_p_reg_fste_w0_11_8 0xA34B | ||
| 2242 | #define reg_fste_w0_11_8_pos 0 | ||
| 2243 | #define reg_fste_w0_11_8_len 4 | ||
| 2244 | #define reg_fste_w0_11_8_lsb 8 | ||
| 2245 | #define xd_p_reg_fste_w1_3_0 0xA34B | ||
| 2246 | #define reg_fste_w1_3_0_pos 4 | ||
| 2247 | #define reg_fste_w1_3_0_len 4 | ||
| 2248 | #define reg_fste_w1_3_0_lsb 0 | ||
| 2249 | #define xd_p_reg_fste_w1_11_4 0xA34C | ||
| 2250 | #define reg_fste_w1_11_4_pos 0 | ||
| 2251 | #define reg_fste_w1_11_4_len 8 | ||
| 2252 | #define reg_fste_w1_11_4_lsb 4 | ||
| 2253 | #define xd_p_reg_fste_w2_7_0 0xA34D | ||
| 2254 | #define reg_fste_w2_7_0_pos 0 | ||
| 2255 | #define reg_fste_w2_7_0_len 8 | ||
| 2256 | #define reg_fste_w2_7_0_lsb 0 | ||
| 2257 | #define xd_p_reg_fste_w2_11_8 0xA34E | ||
| 2258 | #define reg_fste_w2_11_8_pos 0 | ||
| 2259 | #define reg_fste_w2_11_8_len 4 | ||
| 2260 | #define reg_fste_w2_11_8_lsb 8 | ||
| 2261 | #define xd_p_reg_fste_w3_3_0 0xA34E | ||
| 2262 | #define reg_fste_w3_3_0_pos 4 | ||
| 2263 | #define reg_fste_w3_3_0_len 4 | ||
| 2264 | #define reg_fste_w3_3_0_lsb 0 | ||
| 2265 | #define xd_p_reg_fste_w3_11_4 0xA34F | ||
| 2266 | #define reg_fste_w3_11_4_pos 0 | ||
| 2267 | #define reg_fste_w3_11_4_len 8 | ||
| 2268 | #define reg_fste_w3_11_4_lsb 4 | ||
| 2269 | #define xd_p_reg_fste_w4_7_0 0xA350 | ||
| 2270 | #define reg_fste_w4_7_0_pos 0 | ||
| 2271 | #define reg_fste_w4_7_0_len 8 | ||
| 2272 | #define reg_fste_w4_7_0_lsb 0 | ||
| 2273 | #define xd_p_reg_fste_w4_11_8 0xA351 | ||
| 2274 | #define reg_fste_w4_11_8_pos 0 | ||
| 2275 | #define reg_fste_w4_11_8_len 4 | ||
| 2276 | #define reg_fste_w4_11_8_lsb 8 | ||
| 2277 | #define xd_p_reg_fste_w5_3_0 0xA351 | ||
| 2278 | #define reg_fste_w5_3_0_pos 4 | ||
| 2279 | #define reg_fste_w5_3_0_len 4 | ||
| 2280 | #define reg_fste_w5_3_0_lsb 0 | ||
| 2281 | #define xd_p_reg_fste_w5_11_4 0xA352 | ||
| 2282 | #define reg_fste_w5_11_4_pos 0 | ||
| 2283 | #define reg_fste_w5_11_4_len 8 | ||
| 2284 | #define reg_fste_w5_11_4_lsb 4 | ||
| 2285 | #define xd_p_reg_fste_w6_7_0 0xA353 | ||
| 2286 | #define reg_fste_w6_7_0_pos 0 | ||
| 2287 | #define reg_fste_w6_7_0_len 8 | ||
| 2288 | #define reg_fste_w6_7_0_lsb 0 | ||
| 2289 | #define xd_p_reg_fste_w6_11_8 0xA354 | ||
| 2290 | #define reg_fste_w6_11_8_pos 0 | ||
| 2291 | #define reg_fste_w6_11_8_len 4 | ||
| 2292 | #define reg_fste_w6_11_8_lsb 8 | ||
| 2293 | #define xd_p_reg_fste_w7_3_0 0xA354 | ||
| 2294 | #define reg_fste_w7_3_0_pos 4 | ||
| 2295 | #define reg_fste_w7_3_0_len 4 | ||
| 2296 | #define reg_fste_w7_3_0_lsb 0 | ||
| 2297 | #define xd_p_reg_fste_w7_11_4 0xA355 | ||
| 2298 | #define reg_fste_w7_11_4_pos 0 | ||
| 2299 | #define reg_fste_w7_11_4_len 8 | ||
| 2300 | #define reg_fste_w7_11_4_lsb 4 | ||
| 2301 | #define xd_p_reg_fste_w8_7_0 0xA356 | ||
| 2302 | #define reg_fste_w8_7_0_pos 0 | ||
| 2303 | #define reg_fste_w8_7_0_len 8 | ||
| 2304 | #define reg_fste_w8_7_0_lsb 0 | ||
| 2305 | #define xd_p_reg_fste_w8_11_8 0xA357 | ||
| 2306 | #define reg_fste_w8_11_8_pos 0 | ||
| 2307 | #define reg_fste_w8_11_8_len 4 | ||
| 2308 | #define reg_fste_w8_11_8_lsb 8 | ||
| 2309 | #define xd_p_reg_fste_w9_3_0 0xA357 | ||
| 2310 | #define reg_fste_w9_3_0_pos 4 | ||
| 2311 | #define reg_fste_w9_3_0_len 4 | ||
| 2312 | #define reg_fste_w9_3_0_lsb 0 | ||
| 2313 | #define xd_p_reg_fste_w9_11_4 0xA358 | ||
| 2314 | #define reg_fste_w9_11_4_pos 0 | ||
| 2315 | #define reg_fste_w9_11_4_len 8 | ||
| 2316 | #define reg_fste_w9_11_4_lsb 4 | ||
| 2317 | #define xd_p_reg_fste_wa_7_0 0xA359 | ||
| 2318 | #define reg_fste_wa_7_0_pos 0 | ||
| 2319 | #define reg_fste_wa_7_0_len 8 | ||
| 2320 | #define reg_fste_wa_7_0_lsb 0 | ||
| 2321 | #define xd_p_reg_fste_wa_11_8 0xA35A | ||
| 2322 | #define reg_fste_wa_11_8_pos 0 | ||
| 2323 | #define reg_fste_wa_11_8_len 4 | ||
| 2324 | #define reg_fste_wa_11_8_lsb 8 | ||
| 2325 | #define xd_p_reg_fste_wb_3_0 0xA35A | ||
| 2326 | #define reg_fste_wb_3_0_pos 4 | ||
| 2327 | #define reg_fste_wb_3_0_len 4 | ||
| 2328 | #define reg_fste_wb_3_0_lsb 0 | ||
| 2329 | #define xd_p_reg_fste_wb_11_4 0xA35B | ||
| 2330 | #define reg_fste_wb_11_4_pos 0 | ||
| 2331 | #define reg_fste_wb_11_4_len 8 | ||
| 2332 | #define reg_fste_wb_11_4_lsb 4 | ||
| 2333 | #define xd_r_fd_fste_i_adj 0xA35C | ||
| 2334 | #define fd_fste_i_adj_pos 0 | ||
| 2335 | #define fd_fste_i_adj_len 5 | ||
| 2336 | #define fd_fste_i_adj_lsb 0 | ||
| 2337 | #define xd_r_fd_fste_f_adj_7_0 0xA35D | ||
| 2338 | #define fd_fste_f_adj_7_0_pos 0 | ||
| 2339 | #define fd_fste_f_adj_7_0_len 8 | ||
| 2340 | #define fd_fste_f_adj_7_0_lsb 0 | ||
| 2341 | #define xd_r_fd_fste_f_adj_15_8 0xA35E | ||
| 2342 | #define fd_fste_f_adj_15_8_pos 0 | ||
| 2343 | #define fd_fste_f_adj_15_8_len 8 | ||
| 2344 | #define fd_fste_f_adj_15_8_lsb 8 | ||
| 2345 | #define xd_r_fd_fste_f_adj_19_16 0xA35F | ||
| 2346 | #define fd_fste_f_adj_19_16_pos 0 | ||
| 2347 | #define fd_fste_f_adj_19_16_len 4 | ||
| 2348 | #define fd_fste_f_adj_19_16_lsb 16 | ||
| 2349 | #define xd_p_reg_feq_Leak_Bypass 0xA366 | ||
| 2350 | #define reg_feq_Leak_Bypass_pos 0 | ||
| 2351 | #define reg_feq_Leak_Bypass_len 1 | ||
| 2352 | #define reg_feq_Leak_Bypass_lsb 0 | ||
| 2353 | #define xd_p_reg_feq_Leak_Mneg1 0xA366 | ||
| 2354 | #define reg_feq_Leak_Mneg1_pos 1 | ||
| 2355 | #define reg_feq_Leak_Mneg1_len 3 | ||
| 2356 | #define reg_feq_Leak_Mneg1_lsb 0 | ||
| 2357 | #define xd_p_reg_feq_Leak_B_ShiftQ 0xA366 | ||
| 2358 | #define reg_feq_Leak_B_ShiftQ_pos 4 | ||
| 2359 | #define reg_feq_Leak_B_ShiftQ_len 4 | ||
| 2360 | #define reg_feq_Leak_B_ShiftQ_lsb 0 | ||
| 2361 | #define xd_p_reg_feq_Leak_B_Float0 0xA367 | ||
| 2362 | #define reg_feq_Leak_B_Float0_pos 0 | ||
| 2363 | #define reg_feq_Leak_B_Float0_len 8 | ||
| 2364 | #define reg_feq_Leak_B_Float0_lsb 0 | ||
| 2365 | #define xd_p_reg_feq_Leak_B_Float1 0xA368 | ||
| 2366 | #define reg_feq_Leak_B_Float1_pos 0 | ||
| 2367 | #define reg_feq_Leak_B_Float1_len 8 | ||
| 2368 | #define reg_feq_Leak_B_Float1_lsb 0 | ||
| 2369 | #define xd_p_reg_feq_Leak_B_Float2 0xA369 | ||
| 2370 | #define reg_feq_Leak_B_Float2_pos 0 | ||
| 2371 | #define reg_feq_Leak_B_Float2_len 8 | ||
| 2372 | #define reg_feq_Leak_B_Float2_lsb 0 | ||
| 2373 | #define xd_p_reg_feq_Leak_B_Float3 0xA36A | ||
| 2374 | #define reg_feq_Leak_B_Float3_pos 0 | ||
| 2375 | #define reg_feq_Leak_B_Float3_len 8 | ||
| 2376 | #define reg_feq_Leak_B_Float3_lsb 0 | ||
| 2377 | #define xd_p_reg_feq_Leak_B_Float4 0xA36B | ||
| 2378 | #define reg_feq_Leak_B_Float4_pos 0 | ||
| 2379 | #define reg_feq_Leak_B_Float4_len 8 | ||
| 2380 | #define reg_feq_Leak_B_Float4_lsb 0 | ||
| 2381 | #define xd_p_reg_feq_Leak_B_Float5 0xA36C | ||
| 2382 | #define reg_feq_Leak_B_Float5_pos 0 | ||
| 2383 | #define reg_feq_Leak_B_Float5_len 8 | ||
| 2384 | #define reg_feq_Leak_B_Float5_lsb 0 | ||
| 2385 | #define xd_p_reg_feq_Leak_B_Float6 0xA36D | ||
| 2386 | #define reg_feq_Leak_B_Float6_pos 0 | ||
| 2387 | #define reg_feq_Leak_B_Float6_len 8 | ||
| 2388 | #define reg_feq_Leak_B_Float6_lsb 0 | ||
| 2389 | #define xd_p_reg_feq_Leak_B_Float7 0xA36E | ||
| 2390 | #define reg_feq_Leak_B_Float7_pos 0 | ||
| 2391 | #define reg_feq_Leak_B_Float7_len 8 | ||
| 2392 | #define reg_feq_Leak_B_Float7_lsb 0 | ||
| 2393 | #define xd_r_reg_feq_data_h2_7_0 0xA36F | ||
| 2394 | #define reg_feq_data_h2_7_0_pos 0 | ||
| 2395 | #define reg_feq_data_h2_7_0_len 8 | ||
| 2396 | #define reg_feq_data_h2_7_0_lsb 0 | ||
| 2397 | #define xd_r_reg_feq_data_h2_9_8 0xA370 | ||
| 2398 | #define reg_feq_data_h2_9_8_pos 0 | ||
| 2399 | #define reg_feq_data_h2_9_8_len 2 | ||
| 2400 | #define reg_feq_data_h2_9_8_lsb 8 | ||
| 2401 | #define xd_p_reg_feq_leak_use_slice_tps 0xA371 | ||
| 2402 | #define reg_feq_leak_use_slice_tps_pos 0 | ||
| 2403 | #define reg_feq_leak_use_slice_tps_len 1 | ||
| 2404 | #define reg_feq_leak_use_slice_tps_lsb 0 | ||
| 2405 | #define xd_p_reg_feq_read_update 0xA371 | ||
| 2406 | #define reg_feq_read_update_pos 1 | ||
| 2407 | #define reg_feq_read_update_len 1 | ||
| 2408 | #define reg_feq_read_update_lsb 0 | ||
| 2409 | #define xd_p_reg_feq_data_vld 0xA371 | ||
| 2410 | #define reg_feq_data_vld_pos 2 | ||
| 2411 | #define reg_feq_data_vld_len 1 | ||
| 2412 | #define reg_feq_data_vld_lsb 0 | ||
| 2413 | #define xd_p_reg_feq_tone_idx_4_0 0xA371 | ||
| 2414 | #define reg_feq_tone_idx_4_0_pos 3 | ||
| 2415 | #define reg_feq_tone_idx_4_0_len 5 | ||
| 2416 | #define reg_feq_tone_idx_4_0_lsb 0 | ||
| 2417 | #define xd_p_reg_feq_tone_idx_12_5 0xA372 | ||
| 2418 | #define reg_feq_tone_idx_12_5_pos 0 | ||
| 2419 | #define reg_feq_tone_idx_12_5_len 8 | ||
| 2420 | #define reg_feq_tone_idx_12_5_lsb 5 | ||
| 2421 | #define xd_r_reg_feq_data_re_7_0 0xA373 | ||
| 2422 | #define reg_feq_data_re_7_0_pos 0 | ||
| 2423 | #define reg_feq_data_re_7_0_len 8 | ||
| 2424 | #define reg_feq_data_re_7_0_lsb 0 | ||
| 2425 | #define xd_r_reg_feq_data_re_10_8 0xA374 | ||
| 2426 | #define reg_feq_data_re_10_8_pos 0 | ||
| 2427 | #define reg_feq_data_re_10_8_len 3 | ||
| 2428 | #define reg_feq_data_re_10_8_lsb 8 | ||
| 2429 | #define xd_r_reg_feq_data_im_7_0 0xA375 | ||
| 2430 | #define reg_feq_data_im_7_0_pos 0 | ||
| 2431 | #define reg_feq_data_im_7_0_len 8 | ||
| 2432 | #define reg_feq_data_im_7_0_lsb 0 | ||
| 2433 | #define xd_r_reg_feq_data_im_10_8 0xA376 | ||
| 2434 | #define reg_feq_data_im_10_8_pos 0 | ||
| 2435 | #define reg_feq_data_im_10_8_len 3 | ||
| 2436 | #define reg_feq_data_im_10_8_lsb 8 | ||
| 2437 | #define xd_r_reg_feq_y_re 0xA377 | ||
| 2438 | #define reg_feq_y_re_pos 0 | ||
| 2439 | #define reg_feq_y_re_len 8 | ||
| 2440 | #define reg_feq_y_re_lsb 0 | ||
| 2441 | #define xd_r_reg_feq_y_im 0xA378 | ||
| 2442 | #define reg_feq_y_im_pos 0 | ||
| 2443 | #define reg_feq_y_im_len 8 | ||
| 2444 | #define reg_feq_y_im_lsb 0 | ||
| 2445 | #define xd_r_reg_feq_h_re_7_0 0xA379 | ||
| 2446 | #define reg_feq_h_re_7_0_pos 0 | ||
| 2447 | #define reg_feq_h_re_7_0_len 8 | ||
| 2448 | #define reg_feq_h_re_7_0_lsb 0 | ||
| 2449 | #define xd_r_reg_feq_h_re_8 0xA37A | ||
| 2450 | #define reg_feq_h_re_8_pos 0 | ||
| 2451 | #define reg_feq_h_re_8_len 1 | ||
| 2452 | #define reg_feq_h_re_8_lsb 0 | ||
| 2453 | #define xd_r_reg_feq_h_im_7_0 0xA37B | ||
| 2454 | #define reg_feq_h_im_7_0_pos 0 | ||
| 2455 | #define reg_feq_h_im_7_0_len 8 | ||
| 2456 | #define reg_feq_h_im_7_0_lsb 0 | ||
| 2457 | #define xd_r_reg_feq_h_im_8 0xA37C | ||
| 2458 | #define reg_feq_h_im_8_pos 0 | ||
| 2459 | #define reg_feq_h_im_8_len 1 | ||
| 2460 | #define reg_feq_h_im_8_lsb 0 | ||
| 2461 | #define xd_p_fec_super_frm_unit_7_0 0xA380 | ||
| 2462 | #define fec_super_frm_unit_7_0_pos 0 | ||
| 2463 | #define fec_super_frm_unit_7_0_len 8 | ||
| 2464 | #define fec_super_frm_unit_7_0_lsb 0 | ||
| 2465 | #define xd_p_fec_super_frm_unit_15_8 0xA381 | ||
| 2466 | #define fec_super_frm_unit_15_8_pos 0 | ||
| 2467 | #define fec_super_frm_unit_15_8_len 8 | ||
| 2468 | #define fec_super_frm_unit_15_8_lsb 8 | ||
| 2469 | #define xd_r_fec_vtb_err_bit_cnt_7_0 0xA382 | ||
| 2470 | #define fec_vtb_err_bit_cnt_7_0_pos 0 | ||
| 2471 | #define fec_vtb_err_bit_cnt_7_0_len 8 | ||
| 2472 | #define fec_vtb_err_bit_cnt_7_0_lsb 0 | ||
| 2473 | #define xd_r_fec_vtb_err_bit_cnt_15_8 0xA383 | ||
| 2474 | #define fec_vtb_err_bit_cnt_15_8_pos 0 | ||
| 2475 | #define fec_vtb_err_bit_cnt_15_8_len 8 | ||
| 2476 | #define fec_vtb_err_bit_cnt_15_8_lsb 8 | ||
| 2477 | #define xd_r_fec_vtb_err_bit_cnt_23_16 0xA384 | ||
| 2478 | #define fec_vtb_err_bit_cnt_23_16_pos 0 | ||
| 2479 | #define fec_vtb_err_bit_cnt_23_16_len 8 | ||
| 2480 | #define fec_vtb_err_bit_cnt_23_16_lsb 16 | ||
| 2481 | #define xd_p_fec_rsd_packet_unit_7_0 0xA385 | ||
| 2482 | #define fec_rsd_packet_unit_7_0_pos 0 | ||
| 2483 | #define fec_rsd_packet_unit_7_0_len 8 | ||
| 2484 | #define fec_rsd_packet_unit_7_0_lsb 0 | ||
| 2485 | #define xd_p_fec_rsd_packet_unit_15_8 0xA386 | ||
| 2486 | #define fec_rsd_packet_unit_15_8_pos 0 | ||
| 2487 | #define fec_rsd_packet_unit_15_8_len 8 | ||
| 2488 | #define fec_rsd_packet_unit_15_8_lsb 8 | ||
| 2489 | #define xd_r_fec_rsd_bit_err_cnt_7_0 0xA387 | ||
| 2490 | #define fec_rsd_bit_err_cnt_7_0_pos 0 | ||
| 2491 | #define fec_rsd_bit_err_cnt_7_0_len 8 | ||
| 2492 | #define fec_rsd_bit_err_cnt_7_0_lsb 0 | ||
| 2493 | #define xd_r_fec_rsd_bit_err_cnt_15_8 0xA388 | ||
| 2494 | #define fec_rsd_bit_err_cnt_15_8_pos 0 | ||
| 2495 | #define fec_rsd_bit_err_cnt_15_8_len 8 | ||
| 2496 | #define fec_rsd_bit_err_cnt_15_8_lsb 8 | ||
| 2497 | #define xd_r_fec_rsd_bit_err_cnt_23_16 0xA389 | ||
| 2498 | #define fec_rsd_bit_err_cnt_23_16_pos 0 | ||
| 2499 | #define fec_rsd_bit_err_cnt_23_16_len 8 | ||
| 2500 | #define fec_rsd_bit_err_cnt_23_16_lsb 16 | ||
| 2501 | #define xd_r_fec_rsd_abort_packet_cnt_7_0 0xA38A | ||
| 2502 | #define fec_rsd_abort_packet_cnt_7_0_pos 0 | ||
| 2503 | #define fec_rsd_abort_packet_cnt_7_0_len 8 | ||
| 2504 | #define fec_rsd_abort_packet_cnt_7_0_lsb 0 | ||
| 2505 | #define xd_r_fec_rsd_abort_packet_cnt_15_8 0xA38B | ||
| 2506 | #define fec_rsd_abort_packet_cnt_15_8_pos 0 | ||
| 2507 | #define fec_rsd_abort_packet_cnt_15_8_len 8 | ||
| 2508 | #define fec_rsd_abort_packet_cnt_15_8_lsb 8 | ||
| 2509 | #define xd_p_fec_RSD_PKT_NUM_PER_UNIT_7_0 0xA38C | ||
| 2510 | #define fec_RSD_PKT_NUM_PER_UNIT_7_0_pos 0 | ||
| 2511 | #define fec_RSD_PKT_NUM_PER_UNIT_7_0_len 8 | ||
| 2512 | #define fec_RSD_PKT_NUM_PER_UNIT_7_0_lsb 0 | ||
| 2513 | #define xd_p_fec_RSD_PKT_NUM_PER_UNIT_15_8 0xA38D | ||
| 2514 | #define fec_RSD_PKT_NUM_PER_UNIT_15_8_pos 0 | ||
| 2515 | #define fec_RSD_PKT_NUM_PER_UNIT_15_8_len 8 | ||
| 2516 | #define fec_RSD_PKT_NUM_PER_UNIT_15_8_lsb 8 | ||
| 2517 | #define xd_p_fec_RS_TH_1_7_0 0xA38E | ||
| 2518 | #define fec_RS_TH_1_7_0_pos 0 | ||
| 2519 | #define fec_RS_TH_1_7_0_len 8 | ||
| 2520 | #define fec_RS_TH_1_7_0_lsb 0 | ||
| 2521 | #define xd_p_fec_RS_TH_1_15_8 0xA38F | ||
| 2522 | #define fec_RS_TH_1_15_8_pos 0 | ||
| 2523 | #define fec_RS_TH_1_15_8_len 8 | ||
| 2524 | #define fec_RS_TH_1_15_8_lsb 8 | ||
| 2525 | #define xd_p_fec_RS_TH_2 0xA390 | ||
| 2526 | #define fec_RS_TH_2_pos 0 | ||
| 2527 | #define fec_RS_TH_2_len 8 | ||
| 2528 | #define fec_RS_TH_2_lsb 0 | ||
| 2529 | #define xd_p_fec_mon_en 0xA391 | ||
| 2530 | #define fec_mon_en_pos 0 | ||
| 2531 | #define fec_mon_en_len 1 | ||
| 2532 | #define fec_mon_en_lsb 0 | ||
| 2533 | #define xd_p_reg_b8to47 0xA391 | ||
| 2534 | #define reg_b8to47_pos 1 | ||
| 2535 | #define reg_b8to47_len 1 | ||
| 2536 | #define reg_b8to47_lsb 0 | ||
| 2537 | #define xd_p_reg_rsd_sync_rep 0xA391 | ||
| 2538 | #define reg_rsd_sync_rep_pos 2 | ||
| 2539 | #define reg_rsd_sync_rep_len 1 | ||
| 2540 | #define reg_rsd_sync_rep_lsb 0 | ||
| 2541 | #define xd_p_fec_rsd_retrain_rst 0xA391 | ||
| 2542 | #define fec_rsd_retrain_rst_pos 3 | ||
| 2543 | #define fec_rsd_retrain_rst_len 1 | ||
| 2544 | #define fec_rsd_retrain_rst_lsb 0 | ||
| 2545 | #define xd_r_fec_rsd_ber_rdy 0xA391 | ||
| 2546 | #define fec_rsd_ber_rdy_pos 4 | ||
| 2547 | #define fec_rsd_ber_rdy_len 1 | ||
| 2548 | #define fec_rsd_ber_rdy_lsb 0 | ||
| 2549 | #define xd_p_fec_rsd_ber_rst 0xA391 | ||
| 2550 | #define fec_rsd_ber_rst_pos 5 | ||
| 2551 | #define fec_rsd_ber_rst_len 1 | ||
| 2552 | #define fec_rsd_ber_rst_lsb 0 | ||
| 2553 | #define xd_r_fec_vtb_ber_rdy 0xA391 | ||
| 2554 | #define fec_vtb_ber_rdy_pos 6 | ||
| 2555 | #define fec_vtb_ber_rdy_len 1 | ||
| 2556 | #define fec_vtb_ber_rdy_lsb 0 | ||
| 2557 | #define xd_p_fec_vtb_ber_rst 0xA391 | ||
| 2558 | #define fec_vtb_ber_rst_pos 7 | ||
| 2559 | #define fec_vtb_ber_rst_len 1 | ||
| 2560 | #define fec_vtb_ber_rst_lsb 0 | ||
| 2561 | #define xd_p_reg_vtb_clk40en 0xA392 | ||
| 2562 | #define reg_vtb_clk40en_pos 0 | ||
| 2563 | #define reg_vtb_clk40en_len 1 | ||
| 2564 | #define reg_vtb_clk40en_lsb 0 | ||
| 2565 | #define xd_p_fec_vtb_rsd_mon_en 0xA392 | ||
| 2566 | #define fec_vtb_rsd_mon_en_pos 1 | ||
| 2567 | #define fec_vtb_rsd_mon_en_len 1 | ||
| 2568 | #define fec_vtb_rsd_mon_en_lsb 0 | ||
| 2569 | #define xd_p_reg_fec_data_en 0xA392 | ||
| 2570 | #define reg_fec_data_en_pos 2 | ||
| 2571 | #define reg_fec_data_en_len 1 | ||
| 2572 | #define reg_fec_data_en_lsb 0 | ||
| 2573 | #define xd_p_fec_dummy_reg_2 0xA392 | ||
| 2574 | #define fec_dummy_reg_2_pos 3 | ||
| 2575 | #define fec_dummy_reg_2_len 3 | ||
| 2576 | #define fec_dummy_reg_2_lsb 0 | ||
| 2577 | #define xd_p_reg_sync_chk 0xA392 | ||
| 2578 | #define reg_sync_chk_pos 6 | ||
| 2579 | #define reg_sync_chk_len 1 | ||
| 2580 | #define reg_sync_chk_lsb 0 | ||
| 2581 | #define xd_p_fec_rsd_bypass 0xA392 | ||
| 2582 | #define fec_rsd_bypass_pos 7 | ||
| 2583 | #define fec_rsd_bypass_len 1 | ||
| 2584 | #define fec_rsd_bypass_lsb 0 | ||
| 2585 | #define xd_p_fec_sw_rst 0xA393 | ||
| 2586 | #define fec_sw_rst_pos 0 | ||
| 2587 | #define fec_sw_rst_len 1 | ||
| 2588 | #define fec_sw_rst_lsb 0 | ||
| 2589 | #define xd_r_fec_vtb_pm_crc 0xA394 | ||
| 2590 | #define fec_vtb_pm_crc_pos 0 | ||
| 2591 | #define fec_vtb_pm_crc_len 8 | ||
| 2592 | #define fec_vtb_pm_crc_lsb 0 | ||
| 2593 | #define xd_r_fec_vtb_tb_7_crc 0xA395 | ||
| 2594 | #define fec_vtb_tb_7_crc_pos 0 | ||
| 2595 | #define fec_vtb_tb_7_crc_len 8 | ||
| 2596 | #define fec_vtb_tb_7_crc_lsb 0 | ||
| 2597 | #define xd_r_fec_vtb_tb_6_crc 0xA396 | ||
| 2598 | #define fec_vtb_tb_6_crc_pos 0 | ||
| 2599 | #define fec_vtb_tb_6_crc_len 8 | ||
| 2600 | #define fec_vtb_tb_6_crc_lsb 0 | ||
| 2601 | #define xd_r_fec_vtb_tb_5_crc 0xA397 | ||
| 2602 | #define fec_vtb_tb_5_crc_pos 0 | ||
| 2603 | #define fec_vtb_tb_5_crc_len 8 | ||
| 2604 | #define fec_vtb_tb_5_crc_lsb 0 | ||
| 2605 | #define xd_r_fec_vtb_tb_4_crc 0xA398 | ||
| 2606 | #define fec_vtb_tb_4_crc_pos 0 | ||
| 2607 | #define fec_vtb_tb_4_crc_len 8 | ||
| 2608 | #define fec_vtb_tb_4_crc_lsb 0 | ||
| 2609 | #define xd_r_fec_vtb_tb_3_crc 0xA399 | ||
| 2610 | #define fec_vtb_tb_3_crc_pos 0 | ||
| 2611 | #define fec_vtb_tb_3_crc_len 8 | ||
| 2612 | #define fec_vtb_tb_3_crc_lsb 0 | ||
| 2613 | #define xd_r_fec_vtb_tb_2_crc 0xA39A | ||
| 2614 | #define fec_vtb_tb_2_crc_pos 0 | ||
| 2615 | #define fec_vtb_tb_2_crc_len 8 | ||
| 2616 | #define fec_vtb_tb_2_crc_lsb 0 | ||
| 2617 | #define xd_r_fec_vtb_tb_1_crc 0xA39B | ||
| 2618 | #define fec_vtb_tb_1_crc_pos 0 | ||
| 2619 | #define fec_vtb_tb_1_crc_len 8 | ||
| 2620 | #define fec_vtb_tb_1_crc_lsb 0 | ||
| 2621 | #define xd_r_fec_vtb_tb_0_crc 0xA39C | ||
| 2622 | #define fec_vtb_tb_0_crc_pos 0 | ||
| 2623 | #define fec_vtb_tb_0_crc_len 8 | ||
| 2624 | #define fec_vtb_tb_0_crc_lsb 0 | ||
| 2625 | #define xd_r_fec_rsd_bank0_crc 0xA39D | ||
| 2626 | #define fec_rsd_bank0_crc_pos 0 | ||
| 2627 | #define fec_rsd_bank0_crc_len 8 | ||
| 2628 | #define fec_rsd_bank0_crc_lsb 0 | ||
| 2629 | #define xd_r_fec_rsd_bank1_crc 0xA39E | ||
| 2630 | #define fec_rsd_bank1_crc_pos 0 | ||
| 2631 | #define fec_rsd_bank1_crc_len 8 | ||
| 2632 | #define fec_rsd_bank1_crc_lsb 0 | ||
| 2633 | #define xd_r_fec_idi_vtb_crc 0xA39F | ||
| 2634 | #define fec_idi_vtb_crc_pos 0 | ||
| 2635 | #define fec_idi_vtb_crc_len 8 | ||
| 2636 | #define fec_idi_vtb_crc_lsb 0 | ||
| 2637 | #define xd_g_reg_tpsd_txmod 0xA3C0 | ||
| 2638 | #define reg_tpsd_txmod_pos 0 | ||
| 2639 | #define reg_tpsd_txmod_len 2 | ||
| 2640 | #define reg_tpsd_txmod_lsb 0 | ||
| 2641 | #define xd_g_reg_tpsd_gi 0xA3C0 | ||
| 2642 | #define reg_tpsd_gi_pos 2 | ||
| 2643 | #define reg_tpsd_gi_len 2 | ||
| 2644 | #define reg_tpsd_gi_lsb 0 | ||
| 2645 | #define xd_g_reg_tpsd_hier 0xA3C0 | ||
| 2646 | #define reg_tpsd_hier_pos 4 | ||
| 2647 | #define reg_tpsd_hier_len 3 | ||
| 2648 | #define reg_tpsd_hier_lsb 0 | ||
| 2649 | #define xd_g_reg_bw 0xA3C1 | ||
| 2650 | #define reg_bw_pos 2 | ||
| 2651 | #define reg_bw_len 2 | ||
| 2652 | #define reg_bw_lsb 0 | ||
| 2653 | #define xd_g_reg_dec_pri 0xA3C1 | ||
| 2654 | #define reg_dec_pri_pos 4 | ||
| 2655 | #define reg_dec_pri_len 1 | ||
| 2656 | #define reg_dec_pri_lsb 0 | ||
| 2657 | #define xd_g_reg_tpsd_const 0xA3C1 | ||
| 2658 | #define reg_tpsd_const_pos 6 | ||
| 2659 | #define reg_tpsd_const_len 2 | ||
| 2660 | #define reg_tpsd_const_lsb 0 | ||
| 2661 | #define xd_g_reg_tpsd_hpcr 0xA3C2 | ||
| 2662 | #define reg_tpsd_hpcr_pos 0 | ||
| 2663 | #define reg_tpsd_hpcr_len 3 | ||
| 2664 | #define reg_tpsd_hpcr_lsb 0 | ||
| 2665 | #define xd_g_reg_tpsd_lpcr 0xA3C2 | ||
| 2666 | #define reg_tpsd_lpcr_pos 3 | ||
| 2667 | #define reg_tpsd_lpcr_len 3 | ||
| 2668 | #define reg_tpsd_lpcr_lsb 0 | ||
| 2669 | #define xd_g_reg_ofsm_clk 0xA3D0 | ||
| 2670 | #define reg_ofsm_clk_pos 0 | ||
| 2671 | #define reg_ofsm_clk_len 3 | ||
| 2672 | #define reg_ofsm_clk_lsb 0 | ||
| 2673 | #define xd_g_reg_fclk_cfg 0xA3D1 | ||
| 2674 | #define reg_fclk_cfg_pos 0 | ||
| 2675 | #define reg_fclk_cfg_len 1 | ||
| 2676 | #define reg_fclk_cfg_lsb 0 | ||
| 2677 | #define xd_g_reg_fclk_idi 0xA3D1 | ||
| 2678 | #define reg_fclk_idi_pos 1 | ||
| 2679 | #define reg_fclk_idi_len 1 | ||
| 2680 | #define reg_fclk_idi_lsb 0 | ||
| 2681 | #define xd_g_reg_fclk_odi 0xA3D1 | ||
| 2682 | #define reg_fclk_odi_pos 2 | ||
| 2683 | #define reg_fclk_odi_len 1 | ||
| 2684 | #define reg_fclk_odi_lsb 0 | ||
| 2685 | #define xd_g_reg_fclk_rsd 0xA3D1 | ||
| 2686 | #define reg_fclk_rsd_pos 3 | ||
| 2687 | #define reg_fclk_rsd_len 1 | ||
| 2688 | #define reg_fclk_rsd_lsb 0 | ||
| 2689 | #define xd_g_reg_fclk_vtb 0xA3D1 | ||
| 2690 | #define reg_fclk_vtb_pos 4 | ||
| 2691 | #define reg_fclk_vtb_len 1 | ||
| 2692 | #define reg_fclk_vtb_lsb 0 | ||
| 2693 | #define xd_g_reg_fclk_cste 0xA3D1 | ||
| 2694 | #define reg_fclk_cste_pos 5 | ||
| 2695 | #define reg_fclk_cste_len 1 | ||
| 2696 | #define reg_fclk_cste_lsb 0 | ||
| 2697 | #define xd_g_reg_fclk_mp2if 0xA3D1 | ||
| 2698 | #define reg_fclk_mp2if_pos 6 | ||
| 2699 | #define reg_fclk_mp2if_len 1 | ||
| 2700 | #define reg_fclk_mp2if_lsb 0 | ||
| 2701 | #define xd_I2C_i2c_m_slave_addr 0xA400 | ||
| 2702 | #define i2c_m_slave_addr_pos 0 | ||
| 2703 | #define i2c_m_slave_addr_len 8 | ||
| 2704 | #define i2c_m_slave_addr_lsb 0 | ||
| 2705 | #define xd_I2C_i2c_m_data1 0xA401 | ||
| 2706 | #define i2c_m_data1_pos 0 | ||
| 2707 | #define i2c_m_data1_len 8 | ||
| 2708 | #define i2c_m_data1_lsb 0 | ||
| 2709 | #define xd_I2C_i2c_m_data2 0xA402 | ||
| 2710 | #define i2c_m_data2_pos 0 | ||
| 2711 | #define i2c_m_data2_len 8 | ||
| 2712 | #define i2c_m_data2_lsb 0 | ||
| 2713 | #define xd_I2C_i2c_m_data3 0xA403 | ||
| 2714 | #define i2c_m_data3_pos 0 | ||
| 2715 | #define i2c_m_data3_len 8 | ||
| 2716 | #define i2c_m_data3_lsb 0 | ||
| 2717 | #define xd_I2C_i2c_m_data4 0xA404 | ||
| 2718 | #define i2c_m_data4_pos 0 | ||
| 2719 | #define i2c_m_data4_len 8 | ||
| 2720 | #define i2c_m_data4_lsb 0 | ||
| 2721 | #define xd_I2C_i2c_m_data5 0xA405 | ||
| 2722 | #define i2c_m_data5_pos 0 | ||
| 2723 | #define i2c_m_data5_len 8 | ||
| 2724 | #define i2c_m_data5_lsb 0 | ||
| 2725 | #define xd_I2C_i2c_m_data6 0xA406 | ||
| 2726 | #define i2c_m_data6_pos 0 | ||
| 2727 | #define i2c_m_data6_len 8 | ||
| 2728 | #define i2c_m_data6_lsb 0 | ||
| 2729 | #define xd_I2C_i2c_m_data7 0xA407 | ||
| 2730 | #define i2c_m_data7_pos 0 | ||
| 2731 | #define i2c_m_data7_len 8 | ||
| 2732 | #define i2c_m_data7_lsb 0 | ||
| 2733 | #define xd_I2C_i2c_m_data8 0xA408 | ||
| 2734 | #define i2c_m_data8_pos 0 | ||
| 2735 | #define i2c_m_data8_len 8 | ||
| 2736 | #define i2c_m_data8_lsb 0 | ||
| 2737 | #define xd_I2C_i2c_m_data9 0xA409 | ||
| 2738 | #define i2c_m_data9_pos 0 | ||
| 2739 | #define i2c_m_data9_len 8 | ||
| 2740 | #define i2c_m_data9_lsb 0 | ||
| 2741 | #define xd_I2C_i2c_m_data10 0xA40A | ||
| 2742 | #define i2c_m_data10_pos 0 | ||
| 2743 | #define i2c_m_data10_len 8 | ||
| 2744 | #define i2c_m_data10_lsb 0 | ||
| 2745 | #define xd_I2C_i2c_m_data11 0xA40B | ||
| 2746 | #define i2c_m_data11_pos 0 | ||
| 2747 | #define i2c_m_data11_len 8 | ||
| 2748 | #define i2c_m_data11_lsb 0 | ||
| 2749 | #define xd_I2C_i2c_m_cmd_rw 0xA40C | ||
| 2750 | #define i2c_m_cmd_rw_pos 0 | ||
| 2751 | #define i2c_m_cmd_rw_len 1 | ||
| 2752 | #define i2c_m_cmd_rw_lsb 0 | ||
| 2753 | #define xd_I2C_i2c_m_cmd_rwlen 0xA40C | ||
| 2754 | #define i2c_m_cmd_rwlen_pos 3 | ||
| 2755 | #define i2c_m_cmd_rwlen_len 4 | ||
| 2756 | #define i2c_m_cmd_rwlen_lsb 0 | ||
| 2757 | #define xd_I2C_i2c_m_status_cmd_exe 0xA40D | ||
| 2758 | #define i2c_m_status_cmd_exe_pos 0 | ||
| 2759 | #define i2c_m_status_cmd_exe_len 1 | ||
| 2760 | #define i2c_m_status_cmd_exe_lsb 0 | ||
| 2761 | #define xd_I2C_i2c_m_status_wdat_done 0xA40D | ||
| 2762 | #define i2c_m_status_wdat_done_pos 1 | ||
| 2763 | #define i2c_m_status_wdat_done_len 1 | ||
| 2764 | #define i2c_m_status_wdat_done_lsb 0 | ||
| 2765 | #define xd_I2C_i2c_m_status_wdat_fail 0xA40D | ||
| 2766 | #define i2c_m_status_wdat_fail_pos 2 | ||
| 2767 | #define i2c_m_status_wdat_fail_len 1 | ||
| 2768 | #define i2c_m_status_wdat_fail_lsb 0 | ||
| 2769 | #define xd_I2C_i2c_m_period 0xA40E | ||
| 2770 | #define i2c_m_period_pos 0 | ||
| 2771 | #define i2c_m_period_len 8 | ||
| 2772 | #define i2c_m_period_lsb 0 | ||
| 2773 | #define xd_I2C_i2c_m_reg_msb_lsb 0xA40F | ||
| 2774 | #define i2c_m_reg_msb_lsb_pos 0 | ||
| 2775 | #define i2c_m_reg_msb_lsb_len 1 | ||
| 2776 | #define i2c_m_reg_msb_lsb_lsb 0 | ||
| 2777 | #define xd_I2C_reg_ofdm_rst 0xA40F | ||
| 2778 | #define reg_ofdm_rst_pos 1 | ||
| 2779 | #define reg_ofdm_rst_len 1 | ||
| 2780 | #define reg_ofdm_rst_lsb 0 | ||
| 2781 | #define xd_I2C_reg_sample_period_on_tuner 0xA40F | ||
| 2782 | #define reg_sample_period_on_tuner_pos 2 | ||
| 2783 | #define reg_sample_period_on_tuner_len 1 | ||
| 2784 | #define reg_sample_period_on_tuner_lsb 0 | ||
| 2785 | #define xd_I2C_reg_rst_i2c 0xA40F | ||
| 2786 | #define reg_rst_i2c_pos 3 | ||
| 2787 | #define reg_rst_i2c_len 1 | ||
| 2788 | #define reg_rst_i2c_lsb 0 | ||
| 2789 | #define xd_I2C_reg_ofdm_rst_en 0xA40F | ||
| 2790 | #define reg_ofdm_rst_en_pos 4 | ||
| 2791 | #define reg_ofdm_rst_en_len 1 | ||
| 2792 | #define reg_ofdm_rst_en_lsb 0 | ||
| 2793 | #define xd_I2C_reg_tuner_sda_sync_on 0xA40F | ||
| 2794 | #define reg_tuner_sda_sync_on_pos 5 | ||
| 2795 | #define reg_tuner_sda_sync_on_len 1 | ||
| 2796 | #define reg_tuner_sda_sync_on_lsb 0 | ||
| 2797 | #define xd_p_mp2if_data_access_disable_ofsm 0xA500 | ||
| 2798 | #define mp2if_data_access_disable_ofsm_pos 0 | ||
| 2799 | #define mp2if_data_access_disable_ofsm_len 1 | ||
| 2800 | #define mp2if_data_access_disable_ofsm_lsb 0 | ||
| 2801 | #define xd_p_reg_mp2_sw_rst_ofsm 0xA500 | ||
| 2802 | #define reg_mp2_sw_rst_ofsm_pos 1 | ||
| 2803 | #define reg_mp2_sw_rst_ofsm_len 1 | ||
| 2804 | #define reg_mp2_sw_rst_ofsm_lsb 0 | ||
| 2805 | #define xd_p_reg_mp2if_clk_en_ofsm 0xA500 | ||
| 2806 | #define reg_mp2if_clk_en_ofsm_pos 2 | ||
| 2807 | #define reg_mp2if_clk_en_ofsm_len 1 | ||
| 2808 | #define reg_mp2if_clk_en_ofsm_lsb 0 | ||
| 2809 | #define xd_r_mp2if_sync_byte_locked 0xA500 | ||
| 2810 | #define mp2if_sync_byte_locked_pos 3 | ||
| 2811 | #define mp2if_sync_byte_locked_len 1 | ||
| 2812 | #define mp2if_sync_byte_locked_lsb 0 | ||
| 2813 | #define xd_r_mp2if_ts_not_188 0xA500 | ||
| 2814 | #define mp2if_ts_not_188_pos 4 | ||
| 2815 | #define mp2if_ts_not_188_len 1 | ||
| 2816 | #define mp2if_ts_not_188_lsb 0 | ||
| 2817 | #define xd_r_mp2if_psb_empty 0xA500 | ||
| 2818 | #define mp2if_psb_empty_pos 5 | ||
| 2819 | #define mp2if_psb_empty_len 1 | ||
| 2820 | #define mp2if_psb_empty_lsb 0 | ||
| 2821 | #define xd_r_mp2if_psb_overflow 0xA500 | ||
| 2822 | #define mp2if_psb_overflow_pos 6 | ||
| 2823 | #define mp2if_psb_overflow_len 1 | ||
| 2824 | #define mp2if_psb_overflow_lsb 0 | ||
| 2825 | #define xd_p_mp2if_keep_sf_sync_byte_ofsm 0xA500 | ||
| 2826 | #define mp2if_keep_sf_sync_byte_ofsm_pos 7 | ||
| 2827 | #define mp2if_keep_sf_sync_byte_ofsm_len 1 | ||
| 2828 | #define mp2if_keep_sf_sync_byte_ofsm_lsb 0 | ||
| 2829 | #define xd_r_mp2if_psb_mp2if_num_pkt 0xA501 | ||
| 2830 | #define mp2if_psb_mp2if_num_pkt_pos 0 | ||
| 2831 | #define mp2if_psb_mp2if_num_pkt_len 6 | ||
| 2832 | #define mp2if_psb_mp2if_num_pkt_lsb 0 | ||
| 2833 | #define xd_p_reg_mpeg_full_speed_ofsm 0xA501 | ||
| 2834 | #define reg_mpeg_full_speed_ofsm_pos 6 | ||
| 2835 | #define reg_mpeg_full_speed_ofsm_len 1 | ||
| 2836 | #define reg_mpeg_full_speed_ofsm_lsb 0 | ||
| 2837 | #define xd_p_mp2if_mpeg_ser_mode_ofsm 0xA501 | ||
| 2838 | #define mp2if_mpeg_ser_mode_ofsm_pos 7 | ||
| 2839 | #define mp2if_mpeg_ser_mode_ofsm_len 1 | ||
| 2840 | #define mp2if_mpeg_ser_mode_ofsm_lsb 0 | ||
| 2841 | #define xd_p_reg_sw_mon51 0xA600 | ||
| 2842 | #define reg_sw_mon51_pos 0 | ||
| 2843 | #define reg_sw_mon51_len 8 | ||
| 2844 | #define reg_sw_mon51_lsb 0 | ||
| 2845 | #define xd_p_reg_top_pcsel 0xA601 | ||
| 2846 | #define reg_top_pcsel_pos 0 | ||
| 2847 | #define reg_top_pcsel_len 1 | ||
| 2848 | #define reg_top_pcsel_lsb 0 | ||
| 2849 | #define xd_p_reg_top_rs232 0xA601 | ||
| 2850 | #define reg_top_rs232_pos 1 | ||
| 2851 | #define reg_top_rs232_len 1 | ||
| 2852 | #define reg_top_rs232_lsb 0 | ||
| 2853 | #define xd_p_reg_top_pcout 0xA601 | ||
| 2854 | #define reg_top_pcout_pos 2 | ||
| 2855 | #define reg_top_pcout_len 1 | ||
| 2856 | #define reg_top_pcout_lsb 0 | ||
| 2857 | #define xd_p_reg_top_debug 0xA601 | ||
| 2858 | #define reg_top_debug_pos 3 | ||
| 2859 | #define reg_top_debug_len 1 | ||
| 2860 | #define reg_top_debug_lsb 0 | ||
| 2861 | #define xd_p_reg_top_adcdly 0xA601 | ||
| 2862 | #define reg_top_adcdly_pos 4 | ||
| 2863 | #define reg_top_adcdly_len 2 | ||
| 2864 | #define reg_top_adcdly_lsb 0 | ||
| 2865 | #define xd_p_reg_top_pwrdw 0xA601 | ||
| 2866 | #define reg_top_pwrdw_pos 6 | ||
| 2867 | #define reg_top_pwrdw_len 1 | ||
| 2868 | #define reg_top_pwrdw_lsb 0 | ||
| 2869 | #define xd_p_reg_top_pwrdw_inv 0xA601 | ||
| 2870 | #define reg_top_pwrdw_inv_pos 7 | ||
| 2871 | #define reg_top_pwrdw_inv_len 1 | ||
| 2872 | #define reg_top_pwrdw_inv_lsb 0 | ||
| 2873 | #define xd_p_reg_top_int_inv 0xA602 | ||
| 2874 | #define reg_top_int_inv_pos 0 | ||
| 2875 | #define reg_top_int_inv_len 1 | ||
| 2876 | #define reg_top_int_inv_lsb 0 | ||
| 2877 | #define xd_p_reg_top_dio_sel 0xA602 | ||
| 2878 | #define reg_top_dio_sel_pos 1 | ||
| 2879 | #define reg_top_dio_sel_len 1 | ||
| 2880 | #define reg_top_dio_sel_lsb 0 | ||
| 2881 | #define xd_p_reg_top_gpioon0 0xA603 | ||
| 2882 | #define reg_top_gpioon0_pos 0 | ||
| 2883 | #define reg_top_gpioon0_len 1 | ||
| 2884 | #define reg_top_gpioon0_lsb 0 | ||
| 2885 | #define xd_p_reg_top_gpioon1 0xA603 | ||
| 2886 | #define reg_top_gpioon1_pos 1 | ||
| 2887 | #define reg_top_gpioon1_len 1 | ||
| 2888 | #define reg_top_gpioon1_lsb 0 | ||
| 2889 | #define xd_p_reg_top_gpioon2 0xA603 | ||
| 2890 | #define reg_top_gpioon2_pos 2 | ||
| 2891 | #define reg_top_gpioon2_len 1 | ||
| 2892 | #define reg_top_gpioon2_lsb 0 | ||
| 2893 | #define xd_p_reg_top_gpioon3 0xA603 | ||
| 2894 | #define reg_top_gpioon3_pos 3 | ||
| 2895 | #define reg_top_gpioon3_len 1 | ||
| 2896 | #define reg_top_gpioon3_lsb 0 | ||
| 2897 | #define xd_p_reg_top_lockon1 0xA603 | ||
| 2898 | #define reg_top_lockon1_pos 4 | ||
| 2899 | #define reg_top_lockon1_len 1 | ||
| 2900 | #define reg_top_lockon1_lsb 0 | ||
| 2901 | #define xd_p_reg_top_lockon2 0xA603 | ||
| 2902 | #define reg_top_lockon2_pos 5 | ||
| 2903 | #define reg_top_lockon2_len 1 | ||
| 2904 | #define reg_top_lockon2_lsb 0 | ||
| 2905 | #define xd_p_reg_top_gpioo0 0xA604 | ||
| 2906 | #define reg_top_gpioo0_pos 0 | ||
| 2907 | #define reg_top_gpioo0_len 1 | ||
| 2908 | #define reg_top_gpioo0_lsb 0 | ||
| 2909 | #define xd_p_reg_top_gpioo1 0xA604 | ||
| 2910 | #define reg_top_gpioo1_pos 1 | ||
| 2911 | #define reg_top_gpioo1_len 1 | ||
| 2912 | #define reg_top_gpioo1_lsb 0 | ||
| 2913 | #define xd_p_reg_top_gpioo2 0xA604 | ||
| 2914 | #define reg_top_gpioo2_pos 2 | ||
| 2915 | #define reg_top_gpioo2_len 1 | ||
| 2916 | #define reg_top_gpioo2_lsb 0 | ||
| 2917 | #define xd_p_reg_top_gpioo3 0xA604 | ||
| 2918 | #define reg_top_gpioo3_pos 3 | ||
| 2919 | #define reg_top_gpioo3_len 1 | ||
| 2920 | #define reg_top_gpioo3_lsb 0 | ||
| 2921 | #define xd_p_reg_top_lock1 0xA604 | ||
| 2922 | #define reg_top_lock1_pos 4 | ||
| 2923 | #define reg_top_lock1_len 1 | ||
| 2924 | #define reg_top_lock1_lsb 0 | ||
| 2925 | #define xd_p_reg_top_lock2 0xA604 | ||
| 2926 | #define reg_top_lock2_pos 5 | ||
| 2927 | #define reg_top_lock2_len 1 | ||
| 2928 | #define reg_top_lock2_lsb 0 | ||
| 2929 | #define xd_p_reg_top_gpioen0 0xA605 | ||
| 2930 | #define reg_top_gpioen0_pos 0 | ||
| 2931 | #define reg_top_gpioen0_len 1 | ||
| 2932 | #define reg_top_gpioen0_lsb 0 | ||
| 2933 | #define xd_p_reg_top_gpioen1 0xA605 | ||
| 2934 | #define reg_top_gpioen1_pos 1 | ||
| 2935 | #define reg_top_gpioen1_len 1 | ||
| 2936 | #define reg_top_gpioen1_lsb 0 | ||
| 2937 | #define xd_p_reg_top_gpioen2 0xA605 | ||
| 2938 | #define reg_top_gpioen2_pos 2 | ||
| 2939 | #define reg_top_gpioen2_len 1 | ||
| 2940 | #define reg_top_gpioen2_lsb 0 | ||
| 2941 | #define xd_p_reg_top_gpioen3 0xA605 | ||
| 2942 | #define reg_top_gpioen3_pos 3 | ||
| 2943 | #define reg_top_gpioen3_len 1 | ||
| 2944 | #define reg_top_gpioen3_lsb 0 | ||
| 2945 | #define xd_p_reg_top_locken1 0xA605 | ||
| 2946 | #define reg_top_locken1_pos 4 | ||
| 2947 | #define reg_top_locken1_len 1 | ||
| 2948 | #define reg_top_locken1_lsb 0 | ||
| 2949 | #define xd_p_reg_top_locken2 0xA605 | ||
| 2950 | #define reg_top_locken2_pos 5 | ||
| 2951 | #define reg_top_locken2_len 1 | ||
| 2952 | #define reg_top_locken2_lsb 0 | ||
| 2953 | #define xd_r_reg_top_gpioi0 0xA606 | ||
| 2954 | #define reg_top_gpioi0_pos 0 | ||
| 2955 | #define reg_top_gpioi0_len 1 | ||
| 2956 | #define reg_top_gpioi0_lsb 0 | ||
| 2957 | #define xd_r_reg_top_gpioi1 0xA606 | ||
| 2958 | #define reg_top_gpioi1_pos 1 | ||
| 2959 | #define reg_top_gpioi1_len 1 | ||
| 2960 | #define reg_top_gpioi1_lsb 0 | ||
| 2961 | #define xd_r_reg_top_gpioi2 0xA606 | ||
| 2962 | #define reg_top_gpioi2_pos 2 | ||
| 2963 | #define reg_top_gpioi2_len 1 | ||
| 2964 | #define reg_top_gpioi2_lsb 0 | ||
| 2965 | #define xd_r_reg_top_gpioi3 0xA606 | ||
| 2966 | #define reg_top_gpioi3_pos 3 | ||
| 2967 | #define reg_top_gpioi3_len 1 | ||
| 2968 | #define reg_top_gpioi3_lsb 0 | ||
| 2969 | #define xd_r_reg_top_locki1 0xA606 | ||
| 2970 | #define reg_top_locki1_pos 4 | ||
| 2971 | #define reg_top_locki1_len 1 | ||
| 2972 | #define reg_top_locki1_lsb 0 | ||
| 2973 | #define xd_r_reg_top_locki2 0xA606 | ||
| 2974 | #define reg_top_locki2_pos 5 | ||
| 2975 | #define reg_top_locki2_len 1 | ||
| 2976 | #define reg_top_locki2_lsb 0 | ||
| 2977 | #define xd_p_reg_dummy_7_0 0xA608 | ||
| 2978 | #define reg_dummy_7_0_pos 0 | ||
| 2979 | #define reg_dummy_7_0_len 8 | ||
| 2980 | #define reg_dummy_7_0_lsb 0 | ||
| 2981 | #define xd_p_reg_dummy_15_8 0xA609 | ||
| 2982 | #define reg_dummy_15_8_pos 0 | ||
| 2983 | #define reg_dummy_15_8_len 8 | ||
| 2984 | #define reg_dummy_15_8_lsb 8 | ||
| 2985 | #define xd_p_reg_dummy_23_16 0xA60A | ||
| 2986 | #define reg_dummy_23_16_pos 0 | ||
| 2987 | #define reg_dummy_23_16_len 8 | ||
| 2988 | #define reg_dummy_23_16_lsb 16 | ||
| 2989 | #define xd_p_reg_dummy_31_24 0xA60B | ||
| 2990 | #define reg_dummy_31_24_pos 0 | ||
| 2991 | #define reg_dummy_31_24_len 8 | ||
| 2992 | #define reg_dummy_31_24_lsb 24 | ||
| 2993 | #define xd_p_reg_dummy_39_32 0xA60C | ||
| 2994 | #define reg_dummy_39_32_pos 0 | ||
| 2995 | #define reg_dummy_39_32_len 8 | ||
| 2996 | #define reg_dummy_39_32_lsb 32 | ||
| 2997 | #define xd_p_reg_dummy_47_40 0xA60D | ||
| 2998 | #define reg_dummy_47_40_pos 0 | ||
| 2999 | #define reg_dummy_47_40_len 8 | ||
| 3000 | #define reg_dummy_47_40_lsb 40 | ||
| 3001 | #define xd_p_reg_dummy_55_48 0xA60E | ||
| 3002 | #define reg_dummy_55_48_pos 0 | ||
| 3003 | #define reg_dummy_55_48_len 8 | ||
| 3004 | #define reg_dummy_55_48_lsb 48 | ||
| 3005 | #define xd_p_reg_dummy_63_56 0xA60F | ||
| 3006 | #define reg_dummy_63_56_pos 0 | ||
| 3007 | #define reg_dummy_63_56_len 8 | ||
| 3008 | #define reg_dummy_63_56_lsb 56 | ||
| 3009 | #define xd_p_reg_dummy_71_64 0xA610 | ||
| 3010 | #define reg_dummy_71_64_pos 0 | ||
| 3011 | #define reg_dummy_71_64_len 8 | ||
| 3012 | #define reg_dummy_71_64_lsb 64 | ||
| 3013 | #define xd_p_reg_dummy_79_72 0xA611 | ||
| 3014 | #define reg_dummy_79_72_pos 0 | ||
| 3015 | #define reg_dummy_79_72_len 8 | ||
| 3016 | #define reg_dummy_79_72_lsb 72 | ||
| 3017 | #define xd_p_reg_dummy_87_80 0xA612 | ||
| 3018 | #define reg_dummy_87_80_pos 0 | ||
| 3019 | #define reg_dummy_87_80_len 8 | ||
| 3020 | #define reg_dummy_87_80_lsb 80 | ||
| 3021 | #define xd_p_reg_dummy_95_88 0xA613 | ||
| 3022 | #define reg_dummy_95_88_pos 0 | ||
| 3023 | #define reg_dummy_95_88_len 8 | ||
| 3024 | #define reg_dummy_95_88_lsb 88 | ||
| 3025 | #define xd_p_reg_dummy_103_96 0xA614 | ||
| 3026 | #define reg_dummy_103_96_pos 0 | ||
| 3027 | #define reg_dummy_103_96_len 8 | ||
| 3028 | #define reg_dummy_103_96_lsb 96 | ||
| 3029 | |||
| 3030 | #define xd_p_reg_unplug_flag 0xA615 | ||
| 3031 | #define reg_unplug_flag_pos 0 | ||
| 3032 | #define reg_unplug_flag_len 1 | ||
| 3033 | #define reg_unplug_flag_lsb 104 | ||
| 3034 | |||
| 3035 | #define xd_p_reg_api_dca_stes_request 0xA615 | ||
| 3036 | #define reg_api_dca_stes_request_pos 1 | ||
| 3037 | #define reg_api_dca_stes_request_len 1 | ||
| 3038 | #define reg_api_dca_stes_request_lsb 0 | ||
| 3039 | |||
| 3040 | #define xd_p_reg_back_to_dca_flag 0xA615 | ||
| 3041 | #define reg_back_to_dca_flag_pos 2 | ||
| 3042 | #define reg_back_to_dca_flag_len 1 | ||
| 3043 | #define reg_back_to_dca_flag_lsb 106 | ||
| 3044 | |||
| 3045 | #define xd_p_reg_api_retrain_request 0xA615 | ||
| 3046 | #define reg_api_retrain_request_pos 3 | ||
| 3047 | #define reg_api_retrain_request_len 1 | ||
| 3048 | #define reg_api_retrain_request_lsb 0 | ||
| 3049 | |||
| 3050 | #define xd_p_reg_Dyn_Top_Try_flag 0xA615 | ||
| 3051 | #define reg_Dyn_Top_Try_flag_pos 3 | ||
| 3052 | #define reg_Dyn_Top_Try_flag_len 1 | ||
| 3053 | #define reg_Dyn_Top_Try_flag_lsb 107 | ||
| 3054 | |||
| 3055 | #define xd_p_reg_API_retrain_freeze_flag 0xA615 | ||
| 3056 | #define reg_API_retrain_freeze_flag_pos 4 | ||
| 3057 | #define reg_API_retrain_freeze_flag_len 1 | ||
| 3058 | #define reg_API_retrain_freeze_flag_lsb 108 | ||
| 3059 | |||
| 3060 | #define xd_p_reg_dummy_111_104 0xA615 | ||
| 3061 | #define reg_dummy_111_104_pos 0 | ||
| 3062 | #define reg_dummy_111_104_len 8 | ||
| 3063 | #define reg_dummy_111_104_lsb 104 | ||
| 3064 | #define xd_p_reg_dummy_119_112 0xA616 | ||
| 3065 | #define reg_dummy_119_112_pos 0 | ||
| 3066 | #define reg_dummy_119_112_len 8 | ||
| 3067 | #define reg_dummy_119_112_lsb 112 | ||
| 3068 | #define xd_p_reg_dummy_127_120 0xA617 | ||
| 3069 | #define reg_dummy_127_120_pos 0 | ||
| 3070 | #define reg_dummy_127_120_len 8 | ||
| 3071 | #define reg_dummy_127_120_lsb 120 | ||
| 3072 | #define xd_p_reg_dummy_135_128 0xA618 | ||
| 3073 | #define reg_dummy_135_128_pos 0 | ||
| 3074 | #define reg_dummy_135_128_len 8 | ||
| 3075 | #define reg_dummy_135_128_lsb 128 | ||
| 3076 | |||
| 3077 | #define xd_p_reg_dummy_143_136 0xA619 | ||
| 3078 | #define reg_dummy_143_136_pos 0 | ||
| 3079 | #define reg_dummy_143_136_len 8 | ||
| 3080 | #define reg_dummy_143_136_lsb 136 | ||
| 3081 | |||
| 3082 | #define xd_p_reg_CCIR_dis 0xA619 | ||
| 3083 | #define reg_CCIR_dis_pos 0 | ||
| 3084 | #define reg_CCIR_dis_len 1 | ||
| 3085 | #define reg_CCIR_dis_lsb 0 | ||
| 3086 | |||
| 3087 | #define xd_p_reg_dummy_151_144 0xA61A | ||
| 3088 | #define reg_dummy_151_144_pos 0 | ||
| 3089 | #define reg_dummy_151_144_len 8 | ||
| 3090 | #define reg_dummy_151_144_lsb 144 | ||
| 3091 | |||
| 3092 | #define xd_p_reg_dummy_159_152 0xA61B | ||
| 3093 | #define reg_dummy_159_152_pos 0 | ||
| 3094 | #define reg_dummy_159_152_len 8 | ||
| 3095 | #define reg_dummy_159_152_lsb 152 | ||
| 3096 | |||
| 3097 | #define xd_p_reg_dummy_167_160 0xA61C | ||
| 3098 | #define reg_dummy_167_160_pos 0 | ||
| 3099 | #define reg_dummy_167_160_len 8 | ||
| 3100 | #define reg_dummy_167_160_lsb 160 | ||
| 3101 | |||
| 3102 | #define xd_p_reg_dummy_175_168 0xA61D | ||
| 3103 | #define reg_dummy_175_168_pos 0 | ||
| 3104 | #define reg_dummy_175_168_len 8 | ||
| 3105 | #define reg_dummy_175_168_lsb 168 | ||
| 3106 | |||
| 3107 | #define xd_p_reg_dummy_183_176 0xA61E | ||
| 3108 | #define reg_dummy_183_176_pos 0 | ||
| 3109 | #define reg_dummy_183_176_len 8 | ||
| 3110 | #define reg_dummy_183_176_lsb 176 | ||
| 3111 | |||
| 3112 | #define xd_p_reg_ofsm_read_rbc_en 0xA61E | ||
| 3113 | #define reg_ofsm_read_rbc_en_pos 2 | ||
| 3114 | #define reg_ofsm_read_rbc_en_len 1 | ||
| 3115 | #define reg_ofsm_read_rbc_en_lsb 0 | ||
| 3116 | |||
| 3117 | #define xd_p_reg_ce_filter_selection_dis 0xA61E | ||
| 3118 | #define reg_ce_filter_selection_dis_pos 1 | ||
| 3119 | #define reg_ce_filter_selection_dis_len 1 | ||
| 3120 | #define reg_ce_filter_selection_dis_lsb 0 | ||
| 3121 | |||
| 3122 | #define xd_p_reg_OFSM_version_control_7_0 0xA611 | ||
| 3123 | #define reg_OFSM_version_control_7_0_pos 0 | ||
| 3124 | #define reg_OFSM_version_control_7_0_len 8 | ||
| 3125 | #define reg_OFSM_version_control_7_0_lsb 0 | ||
| 3126 | |||
| 3127 | #define xd_p_reg_OFSM_version_control_15_8 0xA61F | ||
| 3128 | #define reg_OFSM_version_control_15_8_pos 0 | ||
| 3129 | #define reg_OFSM_version_control_15_8_len 8 | ||
| 3130 | #define reg_OFSM_version_control_15_8_lsb 0 | ||
| 3131 | |||
| 3132 | #define xd_p_reg_OFSM_version_control_23_16 0xA620 | ||
| 3133 | #define reg_OFSM_version_control_23_16_pos 0 | ||
| 3134 | #define reg_OFSM_version_control_23_16_len 8 | ||
| 3135 | #define reg_OFSM_version_control_23_16_lsb 0 | ||
| 3136 | |||
| 3137 | #define xd_p_reg_dummy_191_184 0xA61F | ||
| 3138 | #define reg_dummy_191_184_pos 0 | ||
| 3139 | #define reg_dummy_191_184_len 8 | ||
| 3140 | #define reg_dummy_191_184_lsb 184 | ||
| 3141 | |||
| 3142 | #define xd_p_reg_dummy_199_192 0xA620 | ||
| 3143 | #define reg_dummy_199_192_pos 0 | ||
| 3144 | #define reg_dummy_199_192_len 8 | ||
| 3145 | #define reg_dummy_199_192_lsb 192 | ||
| 3146 | |||
| 3147 | #define xd_p_reg_ce_en 0xABC0 | ||
| 3148 | #define reg_ce_en_pos 0 | ||
| 3149 | #define reg_ce_en_len 1 | ||
| 3150 | #define reg_ce_en_lsb 0 | ||
| 3151 | #define xd_p_reg_ce_fctrl_en 0xABC0 | ||
| 3152 | #define reg_ce_fctrl_en_pos 1 | ||
| 3153 | #define reg_ce_fctrl_en_len 1 | ||
| 3154 | #define reg_ce_fctrl_en_lsb 0 | ||
| 3155 | #define xd_p_reg_ce_fste_tdi 0xABC0 | ||
| 3156 | #define reg_ce_fste_tdi_pos 2 | ||
| 3157 | #define reg_ce_fste_tdi_len 1 | ||
| 3158 | #define reg_ce_fste_tdi_lsb 0 | ||
| 3159 | #define xd_p_reg_ce_dynamic 0xABC0 | ||
| 3160 | #define reg_ce_dynamic_pos 3 | ||
| 3161 | #define reg_ce_dynamic_len 1 | ||
| 3162 | #define reg_ce_dynamic_lsb 0 | ||
| 3163 | #define xd_p_reg_ce_conf 0xABC0 | ||
| 3164 | #define reg_ce_conf_pos 4 | ||
| 3165 | #define reg_ce_conf_len 2 | ||
| 3166 | #define reg_ce_conf_lsb 0 | ||
| 3167 | #define xd_p_reg_ce_dyn12 0xABC0 | ||
| 3168 | #define reg_ce_dyn12_pos 6 | ||
| 3169 | #define reg_ce_dyn12_len 1 | ||
| 3170 | #define reg_ce_dyn12_lsb 0 | ||
| 3171 | #define xd_p_reg_ce_derot_en 0xABC0 | ||
| 3172 | #define reg_ce_derot_en_pos 7 | ||
| 3173 | #define reg_ce_derot_en_len 1 | ||
| 3174 | #define reg_ce_derot_en_lsb 0 | ||
| 3175 | #define xd_p_reg_ce_dynamic_th_7_0 0xABC1 | ||
| 3176 | #define reg_ce_dynamic_th_7_0_pos 0 | ||
| 3177 | #define reg_ce_dynamic_th_7_0_len 8 | ||
| 3178 | #define reg_ce_dynamic_th_7_0_lsb 0 | ||
| 3179 | #define xd_p_reg_ce_dynamic_th_15_8 0xABC2 | ||
| 3180 | #define reg_ce_dynamic_th_15_8_pos 0 | ||
| 3181 | #define reg_ce_dynamic_th_15_8_len 8 | ||
| 3182 | #define reg_ce_dynamic_th_15_8_lsb 8 | ||
| 3183 | #define xd_p_reg_ce_s1 0xABC3 | ||
| 3184 | #define reg_ce_s1_pos 0 | ||
| 3185 | #define reg_ce_s1_len 5 | ||
| 3186 | #define reg_ce_s1_lsb 0 | ||
| 3187 | #define xd_p_reg_ce_var_forced_value 0xABC3 | ||
| 3188 | #define reg_ce_var_forced_value_pos 5 | ||
| 3189 | #define reg_ce_var_forced_value_len 3 | ||
| 3190 | #define reg_ce_var_forced_value_lsb 0 | ||
| 3191 | #define xd_p_reg_ce_data_im_7_0 0xABC4 | ||
| 3192 | #define reg_ce_data_im_7_0_pos 0 | ||
| 3193 | #define reg_ce_data_im_7_0_len 8 | ||
| 3194 | #define reg_ce_data_im_7_0_lsb 0 | ||
| 3195 | #define xd_p_reg_ce_data_im_8 0xABC5 | ||
| 3196 | #define reg_ce_data_im_8_pos 0 | ||
| 3197 | #define reg_ce_data_im_8_len 1 | ||
| 3198 | #define reg_ce_data_im_8_lsb 0 | ||
| 3199 | #define xd_p_reg_ce_data_re_6_0 0xABC5 | ||
| 3200 | #define reg_ce_data_re_6_0_pos 1 | ||
| 3201 | #define reg_ce_data_re_6_0_len 7 | ||
| 3202 | #define reg_ce_data_re_6_0_lsb 0 | ||
| 3203 | #define xd_p_reg_ce_data_re_8_7 0xABC6 | ||
| 3204 | #define reg_ce_data_re_8_7_pos 0 | ||
| 3205 | #define reg_ce_data_re_8_7_len 2 | ||
| 3206 | #define reg_ce_data_re_8_7_lsb 7 | ||
| 3207 | #define xd_p_reg_ce_tone_5_0 0xABC6 | ||
| 3208 | #define reg_ce_tone_5_0_pos 2 | ||
| 3209 | #define reg_ce_tone_5_0_len 6 | ||
| 3210 | #define reg_ce_tone_5_0_lsb 0 | ||
| 3211 | #define xd_p_reg_ce_tone_12_6 0xABC7 | ||
| 3212 | #define reg_ce_tone_12_6_pos 0 | ||
| 3213 | #define reg_ce_tone_12_6_len 7 | ||
| 3214 | #define reg_ce_tone_12_6_lsb 6 | ||
| 3215 | #define xd_p_reg_ce_centroid_drift_th 0xABC8 | ||
| 3216 | #define reg_ce_centroid_drift_th_pos 0 | ||
| 3217 | #define reg_ce_centroid_drift_th_len 8 | ||
| 3218 | #define reg_ce_centroid_drift_th_lsb 0 | ||
| 3219 | #define xd_p_reg_ce_centroid_count_max 0xABC9 | ||
| 3220 | #define reg_ce_centroid_count_max_pos 0 | ||
| 3221 | #define reg_ce_centroid_count_max_len 4 | ||
| 3222 | #define reg_ce_centroid_count_max_lsb 0 | ||
| 3223 | #define xd_p_reg_ce_centroid_bias_inc_7_0 0xABCA | ||
| 3224 | #define reg_ce_centroid_bias_inc_7_0_pos 0 | ||
| 3225 | #define reg_ce_centroid_bias_inc_7_0_len 8 | ||
| 3226 | #define reg_ce_centroid_bias_inc_7_0_lsb 0 | ||
| 3227 | #define xd_p_reg_ce_centroid_bias_inc_8 0xABCB | ||
| 3228 | #define reg_ce_centroid_bias_inc_8_pos 0 | ||
| 3229 | #define reg_ce_centroid_bias_inc_8_len 1 | ||
| 3230 | #define reg_ce_centroid_bias_inc_8_lsb 0 | ||
| 3231 | #define xd_p_reg_ce_var_th0_7_0 0xABCC | ||
| 3232 | #define reg_ce_var_th0_7_0_pos 0 | ||
| 3233 | #define reg_ce_var_th0_7_0_len 8 | ||
| 3234 | #define reg_ce_var_th0_7_0_lsb 0 | ||
| 3235 | #define xd_p_reg_ce_var_th0_15_8 0xABCD | ||
| 3236 | #define reg_ce_var_th0_15_8_pos 0 | ||
| 3237 | #define reg_ce_var_th0_15_8_len 8 | ||
| 3238 | #define reg_ce_var_th0_15_8_lsb 8 | ||
| 3239 | #define xd_p_reg_ce_var_th1_7_0 0xABCE | ||
| 3240 | #define reg_ce_var_th1_7_0_pos 0 | ||
| 3241 | #define reg_ce_var_th1_7_0_len 8 | ||
| 3242 | #define reg_ce_var_th1_7_0_lsb 0 | ||
| 3243 | #define xd_p_reg_ce_var_th1_15_8 0xABCF | ||
| 3244 | #define reg_ce_var_th1_15_8_pos 0 | ||
| 3245 | #define reg_ce_var_th1_15_8_len 8 | ||
| 3246 | #define reg_ce_var_th1_15_8_lsb 8 | ||
| 3247 | #define xd_p_reg_ce_var_th2_7_0 0xABD0 | ||
| 3248 | #define reg_ce_var_th2_7_0_pos 0 | ||
| 3249 | #define reg_ce_var_th2_7_0_len 8 | ||
| 3250 | #define reg_ce_var_th2_7_0_lsb 0 | ||
| 3251 | #define xd_p_reg_ce_var_th2_15_8 0xABD1 | ||
| 3252 | #define reg_ce_var_th2_15_8_pos 0 | ||
| 3253 | #define reg_ce_var_th2_15_8_len 8 | ||
| 3254 | #define reg_ce_var_th2_15_8_lsb 8 | ||
| 3255 | #define xd_p_reg_ce_var_th3_7_0 0xABD2 | ||
| 3256 | #define reg_ce_var_th3_7_0_pos 0 | ||
| 3257 | #define reg_ce_var_th3_7_0_len 8 | ||
| 3258 | #define reg_ce_var_th3_7_0_lsb 0 | ||
| 3259 | #define xd_p_reg_ce_var_th3_15_8 0xABD3 | ||
| 3260 | #define reg_ce_var_th3_15_8_pos 0 | ||
| 3261 | #define reg_ce_var_th3_15_8_len 8 | ||
| 3262 | #define reg_ce_var_th3_15_8_lsb 8 | ||
| 3263 | #define xd_p_reg_ce_var_th4_7_0 0xABD4 | ||
| 3264 | #define reg_ce_var_th4_7_0_pos 0 | ||
| 3265 | #define reg_ce_var_th4_7_0_len 8 | ||
| 3266 | #define reg_ce_var_th4_7_0_lsb 0 | ||
| 3267 | #define xd_p_reg_ce_var_th4_15_8 0xABD5 | ||
| 3268 | #define reg_ce_var_th4_15_8_pos 0 | ||
| 3269 | #define reg_ce_var_th4_15_8_len 8 | ||
| 3270 | #define reg_ce_var_th4_15_8_lsb 8 | ||
| 3271 | #define xd_p_reg_ce_var_th5_7_0 0xABD6 | ||
| 3272 | #define reg_ce_var_th5_7_0_pos 0 | ||
| 3273 | #define reg_ce_var_th5_7_0_len 8 | ||
| 3274 | #define reg_ce_var_th5_7_0_lsb 0 | ||
| 3275 | #define xd_p_reg_ce_var_th5_15_8 0xABD7 | ||
| 3276 | #define reg_ce_var_th5_15_8_pos 0 | ||
| 3277 | #define reg_ce_var_th5_15_8_len 8 | ||
| 3278 | #define reg_ce_var_th5_15_8_lsb 8 | ||
| 3279 | #define xd_p_reg_ce_var_th6_7_0 0xABD8 | ||
| 3280 | #define reg_ce_var_th6_7_0_pos 0 | ||
| 3281 | #define reg_ce_var_th6_7_0_len 8 | ||
| 3282 | #define reg_ce_var_th6_7_0_lsb 0 | ||
| 3283 | #define xd_p_reg_ce_var_th6_15_8 0xABD9 | ||
| 3284 | #define reg_ce_var_th6_15_8_pos 0 | ||
| 3285 | #define reg_ce_var_th6_15_8_len 8 | ||
| 3286 | #define reg_ce_var_th6_15_8_lsb 8 | ||
| 3287 | #define xd_p_reg_ce_fctrl_reset 0xABDA | ||
| 3288 | #define reg_ce_fctrl_reset_pos 0 | ||
| 3289 | #define reg_ce_fctrl_reset_len 1 | ||
| 3290 | #define reg_ce_fctrl_reset_lsb 0 | ||
| 3291 | #define xd_p_reg_ce_cent_auto_clr_en 0xABDA | ||
| 3292 | #define reg_ce_cent_auto_clr_en_pos 1 | ||
| 3293 | #define reg_ce_cent_auto_clr_en_len 1 | ||
| 3294 | #define reg_ce_cent_auto_clr_en_lsb 0 | ||
| 3295 | #define xd_p_reg_ce_fctrl_auto_reset_en 0xABDA | ||
| 3296 | #define reg_ce_fctrl_auto_reset_en_pos 2 | ||
| 3297 | #define reg_ce_fctrl_auto_reset_en_len 1 | ||
| 3298 | #define reg_ce_fctrl_auto_reset_en_lsb 0 | ||
| 3299 | #define xd_p_reg_ce_var_forced_en 0xABDA | ||
| 3300 | #define reg_ce_var_forced_en_pos 3 | ||
| 3301 | #define reg_ce_var_forced_en_len 1 | ||
| 3302 | #define reg_ce_var_forced_en_lsb 0 | ||
| 3303 | #define xd_p_reg_ce_cent_forced_en 0xABDA | ||
| 3304 | #define reg_ce_cent_forced_en_pos 4 | ||
| 3305 | #define reg_ce_cent_forced_en_len 1 | ||
| 3306 | #define reg_ce_cent_forced_en_lsb 0 | ||
| 3307 | #define xd_p_reg_ce_var_max 0xABDA | ||
| 3308 | #define reg_ce_var_max_pos 5 | ||
| 3309 | #define reg_ce_var_max_len 3 | ||
| 3310 | #define reg_ce_var_max_lsb 0 | ||
| 3311 | #define xd_p_reg_ce_cent_forced_value_7_0 0xABDB | ||
| 3312 | #define reg_ce_cent_forced_value_7_0_pos 0 | ||
| 3313 | #define reg_ce_cent_forced_value_7_0_len 8 | ||
| 3314 | #define reg_ce_cent_forced_value_7_0_lsb 0 | ||
| 3315 | #define xd_p_reg_ce_cent_forced_value_11_8 0xABDC | ||
| 3316 | #define reg_ce_cent_forced_value_11_8_pos 0 | ||
| 3317 | #define reg_ce_cent_forced_value_11_8_len 4 | ||
| 3318 | #define reg_ce_cent_forced_value_11_8_lsb 8 | ||
| 3319 | #define xd_p_reg_ce_fctrl_rd 0xABDD | ||
| 3320 | #define reg_ce_fctrl_rd_pos 0 | ||
| 3321 | #define reg_ce_fctrl_rd_len 1 | ||
| 3322 | #define reg_ce_fctrl_rd_lsb 0 | ||
| 3323 | #define xd_p_reg_ce_centroid_max_6_0 0xABDD | ||
| 3324 | #define reg_ce_centroid_max_6_0_pos 1 | ||
| 3325 | #define reg_ce_centroid_max_6_0_len 7 | ||
| 3326 | #define reg_ce_centroid_max_6_0_lsb 0 | ||
| 3327 | #define xd_p_reg_ce_centroid_max_11_7 0xABDE | ||
| 3328 | #define reg_ce_centroid_max_11_7_pos 0 | ||
| 3329 | #define reg_ce_centroid_max_11_7_len 5 | ||
| 3330 | #define reg_ce_centroid_max_11_7_lsb 7 | ||
| 3331 | #define xd_p_reg_ce_var 0xABDF | ||
| 3332 | #define reg_ce_var_pos 0 | ||
| 3333 | #define reg_ce_var_len 3 | ||
| 3334 | #define reg_ce_var_lsb 0 | ||
| 3335 | #define xd_p_reg_ce_fctrl_rdy 0xABDF | ||
| 3336 | #define reg_ce_fctrl_rdy_pos 3 | ||
| 3337 | #define reg_ce_fctrl_rdy_len 1 | ||
| 3338 | #define reg_ce_fctrl_rdy_lsb 0 | ||
| 3339 | #define xd_p_reg_ce_centroid_out_3_0 0xABDF | ||
| 3340 | #define reg_ce_centroid_out_3_0_pos 4 | ||
| 3341 | #define reg_ce_centroid_out_3_0_len 4 | ||
| 3342 | #define reg_ce_centroid_out_3_0_lsb 0 | ||
| 3343 | #define xd_p_reg_ce_centroid_out_11_4 0xABE0 | ||
| 3344 | #define reg_ce_centroid_out_11_4_pos 0 | ||
| 3345 | #define reg_ce_centroid_out_11_4_len 8 | ||
| 3346 | #define reg_ce_centroid_out_11_4_lsb 4 | ||
| 3347 | #define xd_p_reg_ce_bias_7_0 0xABE1 | ||
| 3348 | #define reg_ce_bias_7_0_pos 0 | ||
| 3349 | #define reg_ce_bias_7_0_len 8 | ||
| 3350 | #define reg_ce_bias_7_0_lsb 0 | ||
| 3351 | #define xd_p_reg_ce_bias_11_8 0xABE2 | ||
| 3352 | #define reg_ce_bias_11_8_pos 0 | ||
| 3353 | #define reg_ce_bias_11_8_len 4 | ||
| 3354 | #define reg_ce_bias_11_8_lsb 8 | ||
| 3355 | #define xd_p_reg_ce_m1_3_0 0xABE2 | ||
| 3356 | #define reg_ce_m1_3_0_pos 4 | ||
| 3357 | #define reg_ce_m1_3_0_len 4 | ||
| 3358 | #define reg_ce_m1_3_0_lsb 0 | ||
| 3359 | #define xd_p_reg_ce_m1_11_4 0xABE3 | ||
| 3360 | #define reg_ce_m1_11_4_pos 0 | ||
| 3361 | #define reg_ce_m1_11_4_len 8 | ||
| 3362 | #define reg_ce_m1_11_4_lsb 4 | ||
| 3363 | #define xd_p_reg_ce_rh0_7_0 0xABE4 | ||
| 3364 | #define reg_ce_rh0_7_0_pos 0 | ||
| 3365 | #define reg_ce_rh0_7_0_len 8 | ||
| 3366 | #define reg_ce_rh0_7_0_lsb 0 | ||
| 3367 | #define xd_p_reg_ce_rh0_15_8 0xABE5 | ||
| 3368 | #define reg_ce_rh0_15_8_pos 0 | ||
| 3369 | #define reg_ce_rh0_15_8_len 8 | ||
| 3370 | #define reg_ce_rh0_15_8_lsb 8 | ||
| 3371 | #define xd_p_reg_ce_rh0_23_16 0xABE6 | ||
| 3372 | #define reg_ce_rh0_23_16_pos 0 | ||
| 3373 | #define reg_ce_rh0_23_16_len 8 | ||
| 3374 | #define reg_ce_rh0_23_16_lsb 16 | ||
| 3375 | #define xd_p_reg_ce_rh0_31_24 0xABE7 | ||
| 3376 | #define reg_ce_rh0_31_24_pos 0 | ||
| 3377 | #define reg_ce_rh0_31_24_len 8 | ||
| 3378 | #define reg_ce_rh0_31_24_lsb 24 | ||
| 3379 | #define xd_p_reg_ce_rh3_real_7_0 0xABE8 | ||
| 3380 | #define reg_ce_rh3_real_7_0_pos 0 | ||
| 3381 | #define reg_ce_rh3_real_7_0_len 8 | ||
| 3382 | #define reg_ce_rh3_real_7_0_lsb 0 | ||
| 3383 | #define xd_p_reg_ce_rh3_real_15_8 0xABE9 | ||
| 3384 | #define reg_ce_rh3_real_15_8_pos 0 | ||
| 3385 | #define reg_ce_rh3_real_15_8_len 8 | ||
| 3386 | #define reg_ce_rh3_real_15_8_lsb 8 | ||
| 3387 | #define xd_p_reg_ce_rh3_real_23_16 0xABEA | ||
| 3388 | #define reg_ce_rh3_real_23_16_pos 0 | ||
| 3389 | #define reg_ce_rh3_real_23_16_len 8 | ||
| 3390 | #define reg_ce_rh3_real_23_16_lsb 16 | ||
| 3391 | #define xd_p_reg_ce_rh3_real_31_24 0xABEB | ||
| 3392 | #define reg_ce_rh3_real_31_24_pos 0 | ||
| 3393 | #define reg_ce_rh3_real_31_24_len 8 | ||
| 3394 | #define reg_ce_rh3_real_31_24_lsb 24 | ||
| 3395 | #define xd_p_reg_ce_rh3_imag_7_0 0xABEC | ||
| 3396 | #define reg_ce_rh3_imag_7_0_pos 0 | ||
| 3397 | #define reg_ce_rh3_imag_7_0_len 8 | ||
| 3398 | #define reg_ce_rh3_imag_7_0_lsb 0 | ||
| 3399 | #define xd_p_reg_ce_rh3_imag_15_8 0xABED | ||
| 3400 | #define reg_ce_rh3_imag_15_8_pos 0 | ||
| 3401 | #define reg_ce_rh3_imag_15_8_len 8 | ||
| 3402 | #define reg_ce_rh3_imag_15_8_lsb 8 | ||
| 3403 | #define xd_p_reg_ce_rh3_imag_23_16 0xABEE | ||
| 3404 | #define reg_ce_rh3_imag_23_16_pos 0 | ||
| 3405 | #define reg_ce_rh3_imag_23_16_len 8 | ||
| 3406 | #define reg_ce_rh3_imag_23_16_lsb 16 | ||
| 3407 | #define xd_p_reg_ce_rh3_imag_31_24 0xABEF | ||
| 3408 | #define reg_ce_rh3_imag_31_24_pos 0 | ||
| 3409 | #define reg_ce_rh3_imag_31_24_len 8 | ||
| 3410 | #define reg_ce_rh3_imag_31_24_lsb 24 | ||
| 3411 | #define xd_p_reg_feq_fix_eh2_7_0 0xABF0 | ||
| 3412 | #define reg_feq_fix_eh2_7_0_pos 0 | ||
| 3413 | #define reg_feq_fix_eh2_7_0_len 8 | ||
| 3414 | #define reg_feq_fix_eh2_7_0_lsb 0 | ||
| 3415 | #define xd_p_reg_feq_fix_eh2_15_8 0xABF1 | ||
| 3416 | #define reg_feq_fix_eh2_15_8_pos 0 | ||
| 3417 | #define reg_feq_fix_eh2_15_8_len 8 | ||
| 3418 | #define reg_feq_fix_eh2_15_8_lsb 8 | ||
| 3419 | #define xd_p_reg_feq_fix_eh2_23_16 0xABF2 | ||
| 3420 | #define reg_feq_fix_eh2_23_16_pos 0 | ||
| 3421 | #define reg_feq_fix_eh2_23_16_len 8 | ||
| 3422 | #define reg_feq_fix_eh2_23_16_lsb 16 | ||
| 3423 | #define xd_p_reg_feq_fix_eh2_31_24 0xABF3 | ||
| 3424 | #define reg_feq_fix_eh2_31_24_pos 0 | ||
| 3425 | #define reg_feq_fix_eh2_31_24_len 8 | ||
| 3426 | #define reg_feq_fix_eh2_31_24_lsb 24 | ||
| 3427 | #define xd_p_reg_ce_m2_central_7_0 0xABF4 | ||
| 3428 | #define reg_ce_m2_central_7_0_pos 0 | ||
| 3429 | #define reg_ce_m2_central_7_0_len 8 | ||
| 3430 | #define reg_ce_m2_central_7_0_lsb 0 | ||
| 3431 | #define xd_p_reg_ce_m2_central_15_8 0xABF5 | ||
| 3432 | #define reg_ce_m2_central_15_8_pos 0 | ||
| 3433 | #define reg_ce_m2_central_15_8_len 8 | ||
| 3434 | #define reg_ce_m2_central_15_8_lsb 8 | ||
| 3435 | #define xd_p_reg_ce_fftshift 0xABF6 | ||
| 3436 | #define reg_ce_fftshift_pos 0 | ||
| 3437 | #define reg_ce_fftshift_len 4 | ||
| 3438 | #define reg_ce_fftshift_lsb 0 | ||
| 3439 | #define xd_p_reg_ce_fftshift1 0xABF6 | ||
| 3440 | #define reg_ce_fftshift1_pos 4 | ||
| 3441 | #define reg_ce_fftshift1_len 4 | ||
| 3442 | #define reg_ce_fftshift1_lsb 0 | ||
| 3443 | #define xd_p_reg_ce_fftshift2 0xABF7 | ||
| 3444 | #define reg_ce_fftshift2_pos 0 | ||
| 3445 | #define reg_ce_fftshift2_len 4 | ||
| 3446 | #define reg_ce_fftshift2_lsb 0 | ||
| 3447 | #define xd_p_reg_ce_top_mobile 0xABF7 | ||
| 3448 | #define reg_ce_top_mobile_pos 4 | ||
| 3449 | #define reg_ce_top_mobile_len 1 | ||
| 3450 | #define reg_ce_top_mobile_lsb 0 | ||
| 3451 | #define xd_p_reg_strong_sginal_detected 0xA2BC | ||
| 3452 | #define reg_strong_sginal_detected_pos 2 | ||
| 3453 | #define reg_strong_sginal_detected_len 1 | ||
| 3454 | #define reg_strong_sginal_detected_lsb 0 | ||
| 3455 | |||
| 3456 | #define XD_MP2IF_BASE 0xB000 | ||
| 3457 | #define XD_MP2IF_CSR (0x00 + XD_MP2IF_BASE) | ||
| 3458 | #define XD_MP2IF_DMX_CTRL (0x03 + XD_MP2IF_BASE) | ||
| 3459 | #define XD_MP2IF_PID_IDX (0x04 + XD_MP2IF_BASE) | ||
| 3460 | #define XD_MP2IF_PID_DATA_L (0x05 + XD_MP2IF_BASE) | ||
| 3461 | #define XD_MP2IF_PID_DATA_H (0x06 + XD_MP2IF_BASE) | ||
| 3462 | #define XD_MP2IF_MISC (0x07 + XD_MP2IF_BASE) | ||
| 3463 | |||
| 3464 | extern struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d); | ||
| 3465 | extern int af9005_read_ofdm_register(struct dvb_usb_device *d, u16 reg, | ||
| 3466 | u8 * value); | ||
| 3467 | extern int af9005_read_ofdm_registers(struct dvb_usb_device *d, u16 reg, | ||
| 3468 | u8 * values, int len); | ||
| 3469 | extern int af9005_write_ofdm_register(struct dvb_usb_device *d, u16 reg, | ||
| 3470 | u8 value); | ||
| 3471 | extern int af9005_write_ofdm_registers(struct dvb_usb_device *d, u16 reg, | ||
| 3472 | u8 * values, int len); | ||
| 3473 | extern int af9005_read_tuner_registers(struct dvb_usb_device *d, u16 reg, | ||
| 3474 | u8 addr, u8 * values, int len); | ||
| 3475 | extern int af9005_write_tuner_registers(struct dvb_usb_device *d, u16 reg, | ||
| 3476 | u8 * values, int len); | ||
| 3477 | extern int af9005_read_register_bits(struct dvb_usb_device *d, u16 reg, | ||
| 3478 | u8 pos, u8 len, u8 * value); | ||
| 3479 | extern int af9005_write_register_bits(struct dvb_usb_device *d, u16 reg, | ||
| 3480 | u8 pos, u8 len, u8 value); | ||
| 3481 | extern int af9005_send_command(struct dvb_usb_device *d, u8 command, | ||
| 3482 | u8 * wbuf, int wlen, u8 * rbuf, int rlen); | ||
| 3483 | extern int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, | ||
| 3484 | u8 * values, int len); | ||
| 3485 | extern int af9005_tuner_attach(struct dvb_usb_adapter *adap); | ||
| 3486 | extern int af9005_led_control(struct dvb_usb_device *d, int onoff); | ||
| 3487 | |||
| 3488 | extern u8 regmask[8]; | ||
| 3489 | |||
| 3490 | /* remote control decoder */ | ||
| 3491 | extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, | ||
| 3492 | u32 * event, int *state); | ||
| 3493 | extern struct rc_map_table rc_map_af9005_table[]; | ||
| 3494 | extern int rc_map_af9005_table_size; | ||
| 3495 | |||
| 3496 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c new file mode 100644 index 00000000000..d7ad05fc383 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9015.c | |||
| @@ -0,0 +1,1718 @@ | |||
| 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/hash.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | |||
| 27 | #include "af9015.h" | ||
| 28 | #include "af9013.h" | ||
| 29 | #include "mt2060.h" | ||
| 30 | #include "qt1010.h" | ||
| 31 | #include "tda18271.h" | ||
| 32 | #include "mxl5005s.h" | ||
| 33 | #include "mc44s803.h" | ||
| 34 | #include "tda18218.h" | ||
| 35 | #include "mxl5007t.h" | ||
| 36 | |||
| 37 | static int dvb_usb_af9015_debug; | ||
| 38 | module_param_named(debug, dvb_usb_af9015_debug, int, 0644); | ||
| 39 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
| 40 | static int dvb_usb_af9015_remote; | ||
| 41 | module_param_named(remote, dvb_usb_af9015_remote, int, 0644); | ||
| 42 | MODULE_PARM_DESC(remote, "select remote"); | ||
| 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[3]; | ||
| 49 | static 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 | #define BUF_LEN 63 | ||
| 70 | #define REQ_HDR_LEN 8 /* send header size */ | ||
| 71 | #define ACK_HDR_LEN 2 /* rece header size */ | ||
| 72 | int act_len, ret; | ||
| 73 | u8 buf[BUF_LEN]; | ||
| 74 | u8 write = 1; | ||
| 75 | u8 msg_len = REQ_HDR_LEN; | ||
| 76 | static u8 seq; /* packet sequence number */ | ||
| 77 | |||
| 78 | if (mutex_lock_interruptible(&af9015_usb_mutex) < 0) | ||
| 79 | return -EAGAIN; | ||
| 80 | |||
| 81 | buf[0] = req->cmd; | ||
| 82 | buf[1] = seq++; | ||
| 83 | buf[2] = req->i2c_addr; | ||
| 84 | buf[3] = req->addr >> 8; | ||
| 85 | buf[4] = req->addr & 0xff; | ||
| 86 | buf[5] = req->mbox; | ||
| 87 | buf[6] = req->addr_len; | ||
| 88 | buf[7] = req->data_len; | ||
| 89 | |||
| 90 | switch (req->cmd) { | ||
| 91 | case GET_CONFIG: | ||
| 92 | case READ_MEMORY: | ||
| 93 | case RECONNECT_USB: | ||
| 94 | write = 0; | ||
| 95 | break; | ||
| 96 | case READ_I2C: | ||
| 97 | write = 0; | ||
| 98 | buf[2] |= 0x01; /* set I2C direction */ | ||
| 99 | case WRITE_I2C: | ||
| 100 | buf[0] = READ_WRITE_I2C; | ||
| 101 | break; | ||
| 102 | case WRITE_MEMORY: | ||
| 103 | if (((req->addr & 0xff00) == 0xff00) || | ||
| 104 | ((req->addr & 0xff00) == 0xae00)) | ||
| 105 | buf[0] = WRITE_VIRTUAL_MEMORY; | ||
| 106 | case WRITE_VIRTUAL_MEMORY: | ||
| 107 | case COPY_FIRMWARE: | ||
| 108 | case DOWNLOAD_FIRMWARE: | ||
| 109 | case BOOT: | ||
| 110 | break; | ||
| 111 | default: | ||
| 112 | err("unknown command:%d", req->cmd); | ||
| 113 | ret = -1; | ||
| 114 | goto error_unlock; | ||
| 115 | } | ||
| 116 | |||
| 117 | /* buffer overflow check */ | ||
| 118 | if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) || | ||
| 119 | (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) { | ||
| 120 | err("too much data; cmd:%d len:%d", req->cmd, req->data_len); | ||
| 121 | ret = -EINVAL; | ||
| 122 | goto error_unlock; | ||
| 123 | } | ||
| 124 | |||
| 125 | /* write requested */ | ||
| 126 | if (write) { | ||
| 127 | memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len); | ||
| 128 | msg_len += req->data_len; | ||
| 129 | } | ||
| 130 | |||
| 131 | deb_xfer(">>> "); | ||
| 132 | debug_dump(buf, msg_len, deb_xfer); | ||
| 133 | |||
| 134 | /* send req */ | ||
| 135 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, | ||
| 136 | &act_len, AF9015_USB_TIMEOUT); | ||
| 137 | if (ret) | ||
| 138 | err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len); | ||
| 139 | else | ||
| 140 | if (act_len != msg_len) | ||
| 141 | ret = -1; /* all data is not send */ | ||
| 142 | if (ret) | ||
| 143 | goto error_unlock; | ||
| 144 | |||
| 145 | /* no ack for those packets */ | ||
| 146 | if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) | ||
| 147 | goto exit_unlock; | ||
| 148 | |||
| 149 | /* write receives seq + status = 2 bytes | ||
| 150 | read receives seq + status + data = 2 + N bytes */ | ||
| 151 | msg_len = ACK_HDR_LEN; | ||
| 152 | if (!write) | ||
| 153 | msg_len += req->data_len; | ||
| 154 | |||
| 155 | ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, | ||
| 156 | &act_len, AF9015_USB_TIMEOUT); | ||
| 157 | if (ret) { | ||
| 158 | err("recv bulk message failed:%d", ret); | ||
| 159 | ret = -1; | ||
| 160 | goto error_unlock; | ||
| 161 | } | ||
| 162 | |||
| 163 | deb_xfer("<<< "); | ||
| 164 | debug_dump(buf, act_len, deb_xfer); | ||
| 165 | |||
| 166 | /* check status */ | ||
| 167 | if (buf[1]) { | ||
| 168 | err("command failed:%d", buf[1]); | ||
| 169 | ret = -1; | ||
| 170 | goto error_unlock; | ||
| 171 | } | ||
| 172 | |||
| 173 | /* read request, copy returned data to return buf */ | ||
| 174 | if (!write) | ||
| 175 | memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len); | ||
| 176 | |||
| 177 | error_unlock: | ||
| 178 | exit_unlock: | ||
| 179 | mutex_unlock(&af9015_usb_mutex); | ||
| 180 | |||
| 181 | return ret; | ||
| 182 | } | ||
| 183 | |||
| 184 | static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) | ||
| 185 | { | ||
| 186 | return af9015_rw_udev(d->udev, req); | ||
| 187 | } | ||
| 188 | |||
| 189 | static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val, | ||
| 190 | u8 len) | ||
| 191 | { | ||
| 192 | struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, | ||
| 193 | val}; | ||
| 194 | return af9015_ctrl_msg(d, &req); | ||
| 195 | } | ||
| 196 | |||
| 197 | static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val) | ||
| 198 | { | ||
| 199 | return af9015_write_regs(d, addr, &val, 1); | ||
| 200 | } | ||
| 201 | |||
| 202 | static int af9015_read_regs(struct dvb_usb_device *d, u16 addr, u8 *val, u8 len) | ||
| 203 | { | ||
| 204 | struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, | ||
| 205 | val}; | ||
| 206 | return af9015_ctrl_msg(d, &req); | ||
| 207 | } | ||
| 208 | |||
| 209 | static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val) | ||
| 210 | { | ||
| 211 | return af9015_read_regs(d, addr, val, 1); | ||
| 212 | } | ||
| 213 | |||
| 214 | static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, | ||
| 215 | u8 val) | ||
| 216 | { | ||
| 217 | struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val}; | ||
| 218 | |||
| 219 | if (addr == af9015_af9013_config[0].demod_address || | ||
| 220 | addr == af9015_af9013_config[1].demod_address) | ||
| 221 | req.addr_len = 3; | ||
| 222 | |||
| 223 | return af9015_ctrl_msg(d, &req); | ||
| 224 | } | ||
| 225 | |||
| 226 | static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, | ||
| 227 | u8 *val) | ||
| 228 | { | ||
| 229 | struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val}; | ||
| 230 | |||
| 231 | if (addr == af9015_af9013_config[0].demod_address || | ||
| 232 | addr == af9015_af9013_config[1].demod_address) | ||
| 233 | req.addr_len = 3; | ||
| 234 | |||
| 235 | return af9015_ctrl_msg(d, &req); | ||
| 236 | } | ||
| 237 | |||
| 238 | static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 239 | int num) | ||
| 240 | { | ||
| 241 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 242 | int ret = 0, i = 0; | ||
| 243 | u16 addr; | ||
| 244 | u8 uninitialized_var(mbox), addr_len; | ||
| 245 | struct req_t req; | ||
| 246 | |||
| 247 | /* TODO: implement bus lock | ||
| 248 | |||
| 249 | The bus lock is needed because there is two tuners both using same I2C-address. | ||
| 250 | Due to that the only way to select correct tuner is use demodulator I2C-gate. | ||
| 251 | |||
| 252 | ................................................ | ||
| 253 | . AF9015 includes integrated AF9013 demodulator. | ||
| 254 | . ____________ ____________ . ____________ | ||
| 255 | .| uC | | demod | . | tuner | | ||
| 256 | .|------------| |------------| . |------------| | ||
| 257 | .| AF9015 | | AF9013/5 | . | MXL5003 | | ||
| 258 | .| |--+----I2C-------|-----/ -----|-.-----I2C-------| | | ||
| 259 | .| | | | addr 0x38 | . | addr 0xc6 | | ||
| 260 | .|____________| | |____________| . |____________| | ||
| 261 | .................|.............................. | ||
| 262 | | ____________ ____________ | ||
| 263 | | | demod | | tuner | | ||
| 264 | | |------------| |------------| | ||
| 265 | | | AF9013 | | MXL5003 | | ||
| 266 | +----I2C-------|-----/ -----|-------I2C-------| | | ||
| 267 | | addr 0x3a | | addr 0xc6 | | ||
| 268 | |____________| |____________| | ||
| 269 | */ | ||
| 270 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 271 | return -EAGAIN; | ||
| 272 | |||
| 273 | while (i < num) { | ||
| 274 | if (msg[i].addr == af9015_af9013_config[0].demod_address || | ||
| 275 | msg[i].addr == af9015_af9013_config[1].demod_address) { | ||
| 276 | addr = msg[i].buf[0] << 8; | ||
| 277 | addr += msg[i].buf[1]; | ||
| 278 | mbox = msg[i].buf[2]; | ||
| 279 | addr_len = 3; | ||
| 280 | } else { | ||
| 281 | addr = msg[i].buf[0]; | ||
| 282 | addr_len = 1; | ||
| 283 | /* mbox is don't care in that case */ | ||
| 284 | } | ||
| 285 | |||
| 286 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
| 287 | if (msg[i].len > 3 || msg[i+1].len > 61) { | ||
| 288 | ret = -EOPNOTSUPP; | ||
| 289 | goto error; | ||
| 290 | } | ||
| 291 | if (msg[i].addr == | ||
| 292 | af9015_af9013_config[0].demod_address) | ||
| 293 | req.cmd = READ_MEMORY; | ||
| 294 | else | ||
| 295 | req.cmd = READ_I2C; | ||
| 296 | req.i2c_addr = msg[i].addr; | ||
| 297 | req.addr = addr; | ||
| 298 | req.mbox = mbox; | ||
| 299 | req.addr_len = addr_len; | ||
| 300 | req.data_len = msg[i+1].len; | ||
| 301 | req.data = &msg[i+1].buf[0]; | ||
| 302 | ret = af9015_ctrl_msg(d, &req); | ||
| 303 | i += 2; | ||
| 304 | } else if (msg[i].flags & I2C_M_RD) { | ||
| 305 | if (msg[i].len > 61) { | ||
| 306 | ret = -EOPNOTSUPP; | ||
| 307 | goto error; | ||
| 308 | } | ||
| 309 | if (msg[i].addr == | ||
| 310 | af9015_af9013_config[0].demod_address) { | ||
| 311 | ret = -EINVAL; | ||
| 312 | goto error; | ||
| 313 | } | ||
| 314 | req.cmd = READ_I2C; | ||
| 315 | req.i2c_addr = msg[i].addr; | ||
| 316 | req.addr = addr; | ||
| 317 | req.mbox = mbox; | ||
| 318 | req.addr_len = addr_len; | ||
| 319 | req.data_len = msg[i].len; | ||
| 320 | req.data = &msg[i].buf[0]; | ||
| 321 | ret = af9015_ctrl_msg(d, &req); | ||
| 322 | i += 1; | ||
| 323 | } else { | ||
| 324 | if (msg[i].len > 21) { | ||
| 325 | ret = -EOPNOTSUPP; | ||
| 326 | goto error; | ||
| 327 | } | ||
| 328 | if (msg[i].addr == | ||
| 329 | af9015_af9013_config[0].demod_address) | ||
| 330 | req.cmd = WRITE_MEMORY; | ||
| 331 | else | ||
| 332 | req.cmd = WRITE_I2C; | ||
| 333 | req.i2c_addr = msg[i].addr; | ||
| 334 | req.addr = addr; | ||
| 335 | req.mbox = mbox; | ||
| 336 | req.addr_len = addr_len; | ||
| 337 | req.data_len = msg[i].len-addr_len; | ||
| 338 | req.data = &msg[i].buf[addr_len]; | ||
| 339 | ret = af9015_ctrl_msg(d, &req); | ||
| 340 | i += 1; | ||
| 341 | } | ||
| 342 | if (ret) | ||
| 343 | goto error; | ||
| 344 | |||
| 345 | } | ||
| 346 | ret = i; | ||
| 347 | |||
| 348 | error: | ||
| 349 | mutex_unlock(&d->i2c_mutex); | ||
| 350 | |||
| 351 | return ret; | ||
| 352 | } | ||
| 353 | |||
| 354 | static u32 af9015_i2c_func(struct i2c_adapter *adapter) | ||
| 355 | { | ||
| 356 | return I2C_FUNC_I2C; | ||
| 357 | } | ||
| 358 | |||
| 359 | static struct i2c_algorithm af9015_i2c_algo = { | ||
| 360 | .master_xfer = af9015_i2c_xfer, | ||
| 361 | .functionality = af9015_i2c_func, | ||
| 362 | }; | ||
| 363 | |||
| 364 | static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op) | ||
| 365 | { | ||
| 366 | int ret; | ||
| 367 | u8 val, mask = 0x01; | ||
| 368 | |||
| 369 | ret = af9015_read_reg(d, addr, &val); | ||
| 370 | if (ret) | ||
| 371 | return ret; | ||
| 372 | |||
| 373 | mask <<= bit; | ||
| 374 | if (op) { | ||
| 375 | /* set bit */ | ||
| 376 | val |= mask; | ||
| 377 | } else { | ||
| 378 | /* clear bit */ | ||
| 379 | mask ^= 0xff; | ||
| 380 | val &= mask; | ||
| 381 | } | ||
| 382 | |||
| 383 | return af9015_write_reg(d, addr, val); | ||
| 384 | } | ||
| 385 | |||
| 386 | static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) | ||
| 387 | { | ||
| 388 | return af9015_do_reg_bit(d, addr, bit, 1); | ||
| 389 | } | ||
| 390 | |||
| 391 | static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) | ||
| 392 | { | ||
| 393 | return af9015_do_reg_bit(d, addr, bit, 0); | ||
| 394 | } | ||
| 395 | |||
| 396 | static int af9015_init_endpoint(struct dvb_usb_device *d) | ||
| 397 | { | ||
| 398 | int ret; | ||
| 399 | u16 frame_size; | ||
| 400 | u8 packet_size; | ||
| 401 | deb_info("%s: USB speed:%d\n", __func__, d->udev->speed); | ||
| 402 | |||
| 403 | /* Windows driver uses packet count 21 for USB1.1 and 348 for USB2.0. | ||
| 404 | We use smaller - about 1/4 from the original, 5 and 87. */ | ||
| 405 | #define TS_PACKET_SIZE 188 | ||
| 406 | |||
| 407 | #define TS_USB20_PACKET_COUNT 87 | ||
| 408 | #define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT) | ||
| 409 | |||
| 410 | #define TS_USB11_PACKET_COUNT 5 | ||
| 411 | #define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT) | ||
| 412 | |||
| 413 | #define TS_USB20_MAX_PACKET_SIZE 512 | ||
| 414 | #define TS_USB11_MAX_PACKET_SIZE 64 | ||
| 415 | |||
| 416 | if (d->udev->speed == USB_SPEED_FULL) { | ||
| 417 | frame_size = TS_USB11_FRAME_SIZE/4; | ||
| 418 | packet_size = TS_USB11_MAX_PACKET_SIZE/4; | ||
| 419 | } else { | ||
| 420 | frame_size = TS_USB20_FRAME_SIZE/4; | ||
| 421 | packet_size = TS_USB20_MAX_PACKET_SIZE/4; | ||
| 422 | } | ||
| 423 | |||
| 424 | ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */ | ||
| 425 | if (ret) | ||
| 426 | goto error; | ||
| 427 | ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */ | ||
| 428 | if (ret) | ||
| 429 | goto error; | ||
| 430 | ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */ | ||
| 431 | if (ret) | ||
| 432 | goto error; | ||
| 433 | ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */ | ||
| 434 | if (ret) | ||
| 435 | goto error; | ||
| 436 | ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */ | ||
| 437 | if (ret) | ||
| 438 | goto error; | ||
| 439 | if (af9015_config.dual_mode) { | ||
| 440 | ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */ | ||
| 441 | if (ret) | ||
| 442 | goto error; | ||
| 443 | } | ||
| 444 | ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */ | ||
| 445 | if (ret) | ||
| 446 | goto error; | ||
| 447 | if (af9015_config.dual_mode) { | ||
| 448 | ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */ | ||
| 449 | if (ret) | ||
| 450 | goto error; | ||
| 451 | } | ||
| 452 | /* EP4 xfer length */ | ||
| 453 | ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff); | ||
| 454 | if (ret) | ||
| 455 | goto error; | ||
| 456 | ret = af9015_write_reg(d, 0xdd89, frame_size >> 8); | ||
| 457 | if (ret) | ||
| 458 | goto error; | ||
| 459 | /* EP5 xfer length */ | ||
| 460 | ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff); | ||
| 461 | if (ret) | ||
| 462 | goto error; | ||
| 463 | ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8); | ||
| 464 | if (ret) | ||
| 465 | goto error; | ||
| 466 | ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */ | ||
| 467 | if (ret) | ||
| 468 | goto error; | ||
| 469 | ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */ | ||
| 470 | if (ret) | ||
| 471 | goto error; | ||
| 472 | ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */ | ||
| 473 | if (ret) | ||
| 474 | goto error; | ||
| 475 | if (af9015_config.dual_mode) { | ||
| 476 | ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */ | ||
| 477 | if (ret) | ||
| 478 | goto error; | ||
| 479 | } | ||
| 480 | |||
| 481 | /* enable / disable mp2if2 */ | ||
| 482 | if (af9015_config.dual_mode) | ||
| 483 | ret = af9015_set_reg_bit(d, 0xd50b, 0); | ||
| 484 | else | ||
| 485 | ret = af9015_clear_reg_bit(d, 0xd50b, 0); | ||
| 486 | |||
| 487 | error: | ||
| 488 | if (ret) | ||
| 489 | err("endpoint init failed:%d", ret); | ||
| 490 | return ret; | ||
| 491 | } | ||
| 492 | |||
| 493 | static int af9015_copy_firmware(struct dvb_usb_device *d) | ||
| 494 | { | ||
| 495 | int ret; | ||
| 496 | u8 fw_params[4]; | ||
| 497 | u8 val, i; | ||
| 498 | struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params), | ||
| 499 | fw_params }; | ||
| 500 | deb_info("%s:\n", __func__); | ||
| 501 | |||
| 502 | fw_params[0] = af9015_config.firmware_size >> 8; | ||
| 503 | fw_params[1] = af9015_config.firmware_size & 0xff; | ||
| 504 | fw_params[2] = af9015_config.firmware_checksum >> 8; | ||
| 505 | fw_params[3] = af9015_config.firmware_checksum & 0xff; | ||
| 506 | |||
| 507 | /* wait 2nd demodulator ready */ | ||
| 508 | msleep(100); | ||
| 509 | |||
| 510 | ret = af9015_read_reg_i2c(d, | ||
| 511 | af9015_af9013_config[1].demod_address, 0x98be, &val); | ||
| 512 | if (ret) | ||
| 513 | goto error; | ||
| 514 | else | ||
| 515 | deb_info("%s: firmware status:%02x\n", __func__, val); | ||
| 516 | |||
| 517 | if (val == 0x0c) /* fw is running, no need for download */ | ||
| 518 | goto exit; | ||
| 519 | |||
| 520 | /* set I2C master clock to fast (to speed up firmware copy) */ | ||
| 521 | ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */ | ||
| 522 | if (ret) | ||
| 523 | goto error; | ||
| 524 | |||
| 525 | msleep(50); | ||
| 526 | |||
| 527 | /* copy firmware */ | ||
| 528 | ret = af9015_ctrl_msg(d, &req); | ||
| 529 | if (ret) | ||
| 530 | err("firmware copy cmd failed:%d", ret); | ||
| 531 | deb_info("%s: firmware copy done\n", __func__); | ||
| 532 | |||
| 533 | /* set I2C master clock back to normal */ | ||
| 534 | ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */ | ||
| 535 | if (ret) | ||
| 536 | goto error; | ||
| 537 | |||
| 538 | /* request boot firmware */ | ||
| 539 | ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].demod_address, | ||
| 540 | 0xe205, 1); | ||
| 541 | deb_info("%s: firmware boot cmd status:%d\n", __func__, ret); | ||
| 542 | if (ret) | ||
| 543 | goto error; | ||
| 544 | |||
| 545 | for (i = 0; i < 15; i++) { | ||
| 546 | msleep(100); | ||
| 547 | |||
| 548 | /* check firmware status */ | ||
| 549 | ret = af9015_read_reg_i2c(d, | ||
| 550 | af9015_af9013_config[1].demod_address, 0x98be, &val); | ||
| 551 | deb_info("%s: firmware status cmd status:%d fw status:%02x\n", | ||
| 552 | __func__, ret, val); | ||
| 553 | if (ret) | ||
| 554 | goto error; | ||
| 555 | |||
| 556 | if (val == 0x0c || val == 0x04) /* success or fail */ | ||
| 557 | break; | ||
| 558 | } | ||
| 559 | |||
| 560 | if (val == 0x04) { | ||
| 561 | err("firmware did not run"); | ||
| 562 | ret = -1; | ||
| 563 | } else if (val != 0x0c) { | ||
| 564 | err("firmware boot timeout"); | ||
| 565 | ret = -1; | ||
| 566 | } | ||
| 567 | |||
| 568 | error: | ||
| 569 | exit: | ||
| 570 | return ret; | ||
| 571 | } | ||
| 572 | |||
| 573 | /* hash (and dump) eeprom */ | ||
| 574 | static int af9015_eeprom_hash(struct usb_device *udev) | ||
| 575 | { | ||
| 576 | static const unsigned int eeprom_size = 256; | ||
| 577 | unsigned int reg; | ||
| 578 | int ret; | ||
| 579 | u8 val, *eeprom; | ||
| 580 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; | ||
| 581 | |||
| 582 | eeprom = kmalloc(eeprom_size, GFP_KERNEL); | ||
| 583 | if (eeprom == NULL) | ||
| 584 | return -ENOMEM; | ||
| 585 | |||
| 586 | for (reg = 0; reg < eeprom_size; reg++) { | ||
| 587 | req.addr = reg; | ||
| 588 | ret = af9015_rw_udev(udev, &req); | ||
| 589 | if (ret) | ||
| 590 | goto free; | ||
| 591 | eeprom[reg] = val; | ||
| 592 | } | ||
| 593 | |||
| 594 | if (dvb_usb_af9015_debug & 0x01) | ||
| 595 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom, | ||
| 596 | eeprom_size); | ||
| 597 | |||
| 598 | BUG_ON(eeprom_size % 4); | ||
| 599 | |||
| 600 | af9015_config.eeprom_sum = 0; | ||
| 601 | for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) { | ||
| 602 | af9015_config.eeprom_sum *= GOLDEN_RATIO_PRIME_32; | ||
| 603 | af9015_config.eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]); | ||
| 604 | } | ||
| 605 | |||
| 606 | deb_info("%s: eeprom sum=%.8x\n", __func__, af9015_config.eeprom_sum); | ||
| 607 | |||
| 608 | ret = 0; | ||
| 609 | free: | ||
| 610 | kfree(eeprom); | ||
| 611 | return ret; | ||
| 612 | } | ||
| 613 | |||
| 614 | static int af9015_init(struct dvb_usb_device *d) | ||
| 615 | { | ||
| 616 | int ret; | ||
| 617 | deb_info("%s:\n", __func__); | ||
| 618 | |||
| 619 | /* init RC canary */ | ||
| 620 | ret = af9015_write_reg(d, 0x98e9, 0xff); | ||
| 621 | if (ret) | ||
| 622 | goto error; | ||
| 623 | |||
| 624 | ret = af9015_init_endpoint(d); | ||
| 625 | if (ret) | ||
| 626 | goto error; | ||
| 627 | |||
| 628 | error: | ||
| 629 | return ret; | ||
| 630 | } | ||
| 631 | |||
| 632 | static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 633 | { | ||
| 634 | int ret; | ||
| 635 | deb_info("%s: onoff:%d\n", __func__, onoff); | ||
| 636 | |||
| 637 | if (onoff) | ||
| 638 | ret = af9015_set_reg_bit(adap->dev, 0xd503, 0); | ||
| 639 | else | ||
| 640 | ret = af9015_clear_reg_bit(adap->dev, 0xd503, 0); | ||
| 641 | |||
| 642 | return ret; | ||
| 643 | } | ||
| 644 | |||
| 645 | static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | ||
| 646 | int onoff) | ||
| 647 | { | ||
| 648 | int ret; | ||
| 649 | u8 idx; | ||
| 650 | |||
| 651 | deb_info("%s: set pid filter, index %d, pid %x, onoff %d\n", | ||
| 652 | __func__, index, pid, onoff); | ||
| 653 | |||
| 654 | ret = af9015_write_reg(adap->dev, 0xd505, (pid & 0xff)); | ||
| 655 | if (ret) | ||
| 656 | goto error; | ||
| 657 | |||
| 658 | ret = af9015_write_reg(adap->dev, 0xd506, (pid >> 8)); | ||
| 659 | if (ret) | ||
| 660 | goto error; | ||
| 661 | |||
| 662 | idx = ((index & 0x1f) | (1 << 5)); | ||
| 663 | ret = af9015_write_reg(adap->dev, 0xd504, idx); | ||
| 664 | |||
| 665 | error: | ||
| 666 | return ret; | ||
| 667 | } | ||
| 668 | |||
| 669 | static int af9015_download_firmware(struct usb_device *udev, | ||
| 670 | const struct firmware *fw) | ||
| 671 | { | ||
| 672 | int i, len, remaining, ret; | ||
| 673 | struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL}; | ||
| 674 | u16 checksum = 0; | ||
| 675 | |||
| 676 | deb_info("%s:\n", __func__); | ||
| 677 | |||
| 678 | /* calc checksum */ | ||
| 679 | for (i = 0; i < fw->size; i++) | ||
| 680 | checksum += fw->data[i]; | ||
| 681 | |||
| 682 | af9015_config.firmware_size = fw->size; | ||
| 683 | af9015_config.firmware_checksum = checksum; | ||
| 684 | |||
| 685 | #define FW_ADDR 0x5100 /* firmware start address */ | ||
| 686 | #define LEN_MAX 55 /* max packet size */ | ||
| 687 | for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) { | ||
| 688 | len = remaining; | ||
| 689 | if (len > LEN_MAX) | ||
| 690 | len = LEN_MAX; | ||
| 691 | |||
| 692 | req.data_len = len; | ||
| 693 | req.data = (u8 *) &fw->data[fw->size - remaining]; | ||
| 694 | req.addr = FW_ADDR + fw->size - remaining; | ||
| 695 | |||
| 696 | ret = af9015_rw_udev(udev, &req); | ||
| 697 | if (ret) { | ||
| 698 | err("firmware download failed:%d", ret); | ||
| 699 | goto error; | ||
| 700 | } | ||
| 701 | } | ||
| 702 | |||
| 703 | /* firmware loaded, request boot */ | ||
| 704 | req.cmd = BOOT; | ||
| 705 | ret = af9015_rw_udev(udev, &req); | ||
| 706 | if (ret) { | ||
| 707 | err("firmware boot failed:%d", ret); | ||
| 708 | goto error; | ||
| 709 | } | ||
| 710 | |||
| 711 | error: | ||
| 712 | return ret; | ||
| 713 | } | ||
| 714 | |||
| 715 | struct af9015_rc_setup { | ||
| 716 | unsigned int id; | ||
| 717 | char *rc_codes; | ||
| 718 | }; | ||
| 719 | |||
| 720 | static char *af9015_rc_setup_match(unsigned int id, | ||
| 721 | const struct af9015_rc_setup *table) | ||
| 722 | { | ||
| 723 | for (; table->rc_codes; table++) | ||
| 724 | if (table->id == id) | ||
| 725 | return table->rc_codes; | ||
| 726 | return NULL; | ||
| 727 | } | ||
| 728 | |||
| 729 | static const struct af9015_rc_setup af9015_rc_setup_modparam[] = { | ||
| 730 | { AF9015_REMOTE_A_LINK_DTU_M, RC_MAP_ALINK_DTU_M }, | ||
| 731 | { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, RC_MAP_MSI_DIGIVOX_II }, | ||
| 732 | { AF9015_REMOTE_MYGICTV_U718, RC_MAP_TOTAL_MEDIA_IN_HAND }, | ||
| 733 | { AF9015_REMOTE_DIGITTRADE_DVB_T, RC_MAP_DIGITTRADE }, | ||
| 734 | { AF9015_REMOTE_AVERMEDIA_KS, RC_MAP_AVERMEDIA_RM_KS }, | ||
| 735 | { } | ||
| 736 | }; | ||
| 737 | |||
| 738 | static const struct af9015_rc_setup af9015_rc_setup_hashes[] = { | ||
| 739 | { 0xb8feb708, RC_MAP_MSI_DIGIVOX_II }, | ||
| 740 | { 0xa3703d00, RC_MAP_ALINK_DTU_M }, | ||
| 741 | { 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */ | ||
| 742 | { 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */ | ||
| 743 | { } | ||
| 744 | }; | ||
| 745 | |||
| 746 | static const struct af9015_rc_setup af9015_rc_setup_usbids[] = { | ||
| 747 | { (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_RC, | ||
| 748 | RC_MAP_TERRATEC_SLIM_2 }, | ||
| 749 | { (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC, | ||
| 750 | RC_MAP_TERRATEC_SLIM }, | ||
| 751 | { (USB_VID_VISIONPLUS << 16) + USB_PID_AZUREWAVE_AD_TU700, | ||
| 752 | RC_MAP_AZUREWAVE_AD_TU700 }, | ||
| 753 | { (USB_VID_VISIONPLUS << 16) + USB_PID_TINYTWIN, | ||
| 754 | RC_MAP_AZUREWAVE_AD_TU700 }, | ||
| 755 | { (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGI_VOX_MINI_III, | ||
| 756 | RC_MAP_MSI_DIGIVOX_III }, | ||
| 757 | { (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGIVOX_DUO, | ||
| 758 | RC_MAP_MSI_DIGIVOX_III }, | ||
| 759 | { (USB_VID_LEADTEK << 16) + USB_PID_WINFAST_DTV_DONGLE_GOLD, | ||
| 760 | RC_MAP_LEADTEK_Y04G0051 }, | ||
| 761 | { (USB_VID_AVERMEDIA << 16) + USB_PID_AVERMEDIA_VOLAR_X, | ||
| 762 | RC_MAP_AVERMEDIA_M135A }, | ||
| 763 | { (USB_VID_AFATECH << 16) + USB_PID_TREKSTOR_DVBT, | ||
| 764 | RC_MAP_TREKSTOR }, | ||
| 765 | { (USB_VID_KWORLD_2 << 16) + USB_PID_TINYTWIN_2, | ||
| 766 | RC_MAP_DIGITALNOW_TINYTWIN }, | ||
| 767 | { (USB_VID_GTEK << 16) + USB_PID_TINYTWIN_3, | ||
| 768 | RC_MAP_DIGITALNOW_TINYTWIN }, | ||
| 769 | { (USB_VID_KWORLD_2 << 16) + USB_PID_SVEON_STV22, | ||
| 770 | RC_MAP_MSI_DIGIVOX_III }, | ||
| 771 | { } | ||
| 772 | }; | ||
| 773 | |||
| 774 | static void af9015_set_remote_config(struct usb_device *udev, | ||
| 775 | struct dvb_usb_device_properties *props) | ||
| 776 | { | ||
| 777 | u16 vid = le16_to_cpu(udev->descriptor.idVendor); | ||
| 778 | u16 pid = le16_to_cpu(udev->descriptor.idProduct); | ||
| 779 | |||
| 780 | /* try to load remote based module param */ | ||
| 781 | props->rc.core.rc_codes = af9015_rc_setup_match( | ||
| 782 | dvb_usb_af9015_remote, af9015_rc_setup_modparam); | ||
| 783 | |||
| 784 | /* try to load remote based eeprom hash */ | ||
| 785 | if (!props->rc.core.rc_codes) | ||
| 786 | props->rc.core.rc_codes = af9015_rc_setup_match( | ||
| 787 | af9015_config.eeprom_sum, af9015_rc_setup_hashes); | ||
| 788 | |||
| 789 | /* try to load remote based USB ID */ | ||
| 790 | if (!props->rc.core.rc_codes) | ||
| 791 | props->rc.core.rc_codes = af9015_rc_setup_match( | ||
| 792 | (vid << 16) + pid, af9015_rc_setup_usbids); | ||
| 793 | |||
| 794 | /* try to load remote based USB iManufacturer string */ | ||
| 795 | if (!props->rc.core.rc_codes && vid == USB_VID_AFATECH) { | ||
| 796 | /* Check USB manufacturer and product strings and try | ||
| 797 | to determine correct remote in case of chip vendor | ||
| 798 | reference IDs are used. | ||
| 799 | DO NOT ADD ANYTHING NEW HERE. Use hashes instead. */ | ||
| 800 | char manufacturer[10]; | ||
| 801 | memset(manufacturer, 0, sizeof(manufacturer)); | ||
| 802 | usb_string(udev, udev->descriptor.iManufacturer, | ||
| 803 | manufacturer, sizeof(manufacturer)); | ||
| 804 | if (!strcmp("MSI", manufacturer)) { | ||
| 805 | /* iManufacturer 1 MSI | ||
| 806 | iProduct 2 MSI K-VOX */ | ||
| 807 | props->rc.core.rc_codes = af9015_rc_setup_match( | ||
| 808 | AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, | ||
| 809 | af9015_rc_setup_modparam); | ||
| 810 | } | ||
| 811 | } | ||
| 812 | |||
| 813 | /* finally load "empty" just for leaving IR receiver enabled */ | ||
| 814 | if (!props->rc.core.rc_codes) | ||
| 815 | props->rc.core.rc_codes = RC_MAP_EMPTY; | ||
| 816 | |||
| 817 | return; | ||
| 818 | } | ||
| 819 | |||
| 820 | static int af9015_read_config(struct usb_device *udev) | ||
| 821 | { | ||
| 822 | int ret; | ||
| 823 | u8 val, i, offset = 0; | ||
| 824 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; | ||
| 825 | |||
| 826 | /* IR remote controller */ | ||
| 827 | req.addr = AF9015_EEPROM_IR_MODE; | ||
| 828 | /* first message will timeout often due to possible hw bug */ | ||
| 829 | for (i = 0; i < 4; i++) { | ||
| 830 | ret = af9015_rw_udev(udev, &req); | ||
| 831 | if (!ret) | ||
| 832 | break; | ||
| 833 | } | ||
| 834 | if (ret) | ||
| 835 | goto error; | ||
| 836 | |||
| 837 | ret = af9015_eeprom_hash(udev); | ||
| 838 | if (ret) | ||
| 839 | goto error; | ||
| 840 | |||
| 841 | deb_info("%s: IR mode:%d\n", __func__, val); | ||
| 842 | for (i = 0; i < af9015_properties_count; i++) { | ||
| 843 | if (val == AF9015_IR_MODE_DISABLED) | ||
| 844 | af9015_properties[i].rc.core.rc_codes = NULL; | ||
| 845 | else | ||
| 846 | af9015_set_remote_config(udev, &af9015_properties[i]); | ||
| 847 | } | ||
| 848 | |||
| 849 | /* TS mode - one or two receivers */ | ||
| 850 | req.addr = AF9015_EEPROM_TS_MODE; | ||
| 851 | ret = af9015_rw_udev(udev, &req); | ||
| 852 | if (ret) | ||
| 853 | goto error; | ||
| 854 | af9015_config.dual_mode = val; | ||
| 855 | deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode); | ||
| 856 | |||
| 857 | /* Set adapter0 buffer size according to USB port speed, adapter1 buffer | ||
| 858 | size can be static because it is enabled only USB2.0 */ | ||
| 859 | for (i = 0; i < af9015_properties_count; i++) { | ||
| 860 | /* USB1.1 set smaller buffersize and disable 2nd adapter */ | ||
| 861 | if (udev->speed == USB_SPEED_FULL) { | ||
| 862 | af9015_properties[i].adapter[0].stream.u.bulk.buffersize | ||
| 863 | = TS_USB11_FRAME_SIZE; | ||
| 864 | /* disable 2nd adapter because we don't have | ||
| 865 | PID-filters */ | ||
| 866 | af9015_config.dual_mode = 0; | ||
| 867 | } else { | ||
| 868 | af9015_properties[i].adapter[0].stream.u.bulk.buffersize | ||
| 869 | = TS_USB20_FRAME_SIZE; | ||
| 870 | } | ||
| 871 | } | ||
| 872 | |||
| 873 | if (af9015_config.dual_mode) { | ||
| 874 | /* read 2nd demodulator I2C address */ | ||
| 875 | req.addr = AF9015_EEPROM_DEMOD2_I2C; | ||
| 876 | ret = af9015_rw_udev(udev, &req); | ||
| 877 | if (ret) | ||
| 878 | goto error; | ||
| 879 | af9015_af9013_config[1].demod_address = val; | ||
| 880 | |||
| 881 | /* enable 2nd adapter */ | ||
| 882 | for (i = 0; i < af9015_properties_count; i++) | ||
| 883 | af9015_properties[i].num_adapters = 2; | ||
| 884 | |||
| 885 | } else { | ||
| 886 | /* disable 2nd adapter */ | ||
| 887 | for (i = 0; i < af9015_properties_count; i++) | ||
| 888 | af9015_properties[i].num_adapters = 1; | ||
| 889 | } | ||
| 890 | |||
| 891 | for (i = 0; i < af9015_properties[0].num_adapters; i++) { | ||
| 892 | if (i == 1) | ||
| 893 | offset = AF9015_EEPROM_OFFSET; | ||
| 894 | /* xtal */ | ||
| 895 | req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset; | ||
| 896 | ret = af9015_rw_udev(udev, &req); | ||
| 897 | if (ret) | ||
| 898 | goto error; | ||
| 899 | switch (val) { | ||
| 900 | case 0: | ||
| 901 | af9015_af9013_config[i].adc_clock = 28800; | ||
| 902 | break; | ||
| 903 | case 1: | ||
| 904 | af9015_af9013_config[i].adc_clock = 20480; | ||
| 905 | break; | ||
| 906 | case 2: | ||
| 907 | af9015_af9013_config[i].adc_clock = 28000; | ||
| 908 | break; | ||
| 909 | case 3: | ||
| 910 | af9015_af9013_config[i].adc_clock = 25000; | ||
| 911 | break; | ||
| 912 | }; | ||
| 913 | deb_info("%s: [%d] xtal:%d set adc_clock:%d\n", __func__, i, | ||
| 914 | val, af9015_af9013_config[i].adc_clock); | ||
| 915 | |||
| 916 | /* tuner IF */ | ||
| 917 | req.addr = AF9015_EEPROM_IF1H + offset; | ||
| 918 | ret = af9015_rw_udev(udev, &req); | ||
| 919 | if (ret) | ||
| 920 | goto error; | ||
| 921 | af9015_af9013_config[i].tuner_if = val << 8; | ||
| 922 | req.addr = AF9015_EEPROM_IF1L + offset; | ||
| 923 | ret = af9015_rw_udev(udev, &req); | ||
| 924 | if (ret) | ||
| 925 | goto error; | ||
| 926 | af9015_af9013_config[i].tuner_if += val; | ||
| 927 | deb_info("%s: [%d] IF1:%d\n", __func__, i, | ||
| 928 | af9015_af9013_config[0].tuner_if); | ||
| 929 | |||
| 930 | /* MT2060 IF1 */ | ||
| 931 | req.addr = AF9015_EEPROM_MT2060_IF1H + offset; | ||
| 932 | ret = af9015_rw_udev(udev, &req); | ||
| 933 | if (ret) | ||
| 934 | goto error; | ||
| 935 | af9015_config.mt2060_if1[i] = val << 8; | ||
| 936 | req.addr = AF9015_EEPROM_MT2060_IF1L + offset; | ||
| 937 | ret = af9015_rw_udev(udev, &req); | ||
| 938 | if (ret) | ||
| 939 | goto error; | ||
| 940 | af9015_config.mt2060_if1[i] += val; | ||
| 941 | deb_info("%s: [%d] MT2060 IF1:%d\n", __func__, i, | ||
| 942 | af9015_config.mt2060_if1[i]); | ||
| 943 | |||
| 944 | /* tuner */ | ||
| 945 | req.addr = AF9015_EEPROM_TUNER_ID1 + offset; | ||
| 946 | ret = af9015_rw_udev(udev, &req); | ||
| 947 | if (ret) | ||
| 948 | goto error; | ||
| 949 | switch (val) { | ||
| 950 | case AF9013_TUNER_ENV77H11D5: | ||
| 951 | case AF9013_TUNER_MT2060: | ||
| 952 | case AF9013_TUNER_QT1010: | ||
| 953 | case AF9013_TUNER_UNKNOWN: | ||
| 954 | case AF9013_TUNER_MT2060_2: | ||
| 955 | case AF9013_TUNER_TDA18271: | ||
| 956 | case AF9013_TUNER_QT1010A: | ||
| 957 | case AF9013_TUNER_TDA18218: | ||
| 958 | af9015_af9013_config[i].rf_spec_inv = 1; | ||
| 959 | break; | ||
| 960 | case AF9013_TUNER_MXL5003D: | ||
| 961 | case AF9013_TUNER_MXL5005D: | ||
| 962 | case AF9013_TUNER_MXL5005R: | ||
| 963 | case AF9013_TUNER_MXL5007T: | ||
| 964 | af9015_af9013_config[i].rf_spec_inv = 0; | ||
| 965 | break; | ||
| 966 | case AF9013_TUNER_MC44S803: | ||
| 967 | af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO; | ||
| 968 | af9015_af9013_config[i].rf_spec_inv = 1; | ||
| 969 | break; | ||
| 970 | default: | ||
| 971 | warn("tuner id:%d not supported, please report!", val); | ||
| 972 | return -ENODEV; | ||
| 973 | }; | ||
| 974 | |||
| 975 | af9015_af9013_config[i].tuner = val; | ||
| 976 | deb_info("%s: [%d] tuner id:%d\n", __func__, i, val); | ||
| 977 | } | ||
| 978 | |||
| 979 | error: | ||
| 980 | if (ret) | ||
| 981 | err("eeprom read failed:%d", ret); | ||
| 982 | |||
| 983 | /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM | ||
| 984 | content :-( Override some wrong values here. Ditto for the | ||
| 985 | AVerTV Red HD+ (A850T) device. */ | ||
| 986 | if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_AVERMEDIA && | ||
| 987 | ((le16_to_cpu(udev->descriptor.idProduct) == | ||
| 988 | USB_PID_AVERMEDIA_A850) || | ||
| 989 | (le16_to_cpu(udev->descriptor.idProduct) == | ||
| 990 | USB_PID_AVERMEDIA_A850T))) { | ||
| 991 | deb_info("%s: AverMedia A850: overriding config\n", __func__); | ||
| 992 | /* disable dual mode */ | ||
| 993 | af9015_config.dual_mode = 0; | ||
| 994 | /* disable 2nd adapter */ | ||
| 995 | for (i = 0; i < af9015_properties_count; i++) | ||
| 996 | af9015_properties[i].num_adapters = 1; | ||
| 997 | |||
| 998 | /* set correct IF */ | ||
| 999 | af9015_af9013_config[0].tuner_if = 4570; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | return ret; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | static int af9015_identify_state(struct usb_device *udev, | ||
| 1006 | struct dvb_usb_device_properties *props, | ||
| 1007 | struct dvb_usb_device_description **desc, | ||
| 1008 | int *cold) | ||
| 1009 | { | ||
| 1010 | int ret; | ||
| 1011 | u8 reply; | ||
| 1012 | struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply}; | ||
| 1013 | |||
| 1014 | ret = af9015_rw_udev(udev, &req); | ||
| 1015 | if (ret) | ||
| 1016 | return ret; | ||
| 1017 | |||
| 1018 | deb_info("%s: reply:%02x\n", __func__, reply); | ||
| 1019 | if (reply == 0x02) | ||
| 1020 | *cold = 0; | ||
| 1021 | else | ||
| 1022 | *cold = 1; | ||
| 1023 | |||
| 1024 | return ret; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | static int af9015_rc_query(struct dvb_usb_device *d) | ||
| 1028 | { | ||
| 1029 | struct af9015_state *priv = d->priv; | ||
| 1030 | int ret; | ||
| 1031 | u8 buf[17]; | ||
| 1032 | |||
| 1033 | /* read registers needed to detect remote controller code */ | ||
| 1034 | ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf)); | ||
| 1035 | if (ret) | ||
| 1036 | goto error; | ||
| 1037 | |||
| 1038 | /* If any of these are non-zero, assume invalid data */ | ||
| 1039 | if (buf[1] || buf[2] || buf[3]) | ||
| 1040 | return ret; | ||
| 1041 | |||
| 1042 | /* Check for repeat of previous code */ | ||
| 1043 | if ((priv->rc_repeat != buf[6] || buf[0]) && | ||
| 1044 | !memcmp(&buf[12], priv->rc_last, 4)) { | ||
| 1045 | deb_rc("%s: key repeated\n", __func__); | ||
| 1046 | rc_keydown(d->rc_dev, priv->rc_keycode, 0); | ||
| 1047 | priv->rc_repeat = buf[6]; | ||
| 1048 | return ret; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | /* Only process key if canary killed */ | ||
| 1052 | if (buf[16] != 0xff && buf[0] != 0x01) { | ||
| 1053 | deb_rc("%s: key pressed %02x %02x %02x %02x\n", __func__, | ||
| 1054 | buf[12], buf[13], buf[14], buf[15]); | ||
| 1055 | |||
| 1056 | /* Reset the canary */ | ||
| 1057 | ret = af9015_write_reg(d, 0x98e9, 0xff); | ||
| 1058 | if (ret) | ||
| 1059 | goto error; | ||
| 1060 | |||
| 1061 | /* Remember this key */ | ||
| 1062 | memcpy(priv->rc_last, &buf[12], 4); | ||
| 1063 | if (buf[14] == (u8) ~buf[15]) { | ||
| 1064 | if (buf[12] == (u8) ~buf[13]) { | ||
| 1065 | /* NEC */ | ||
| 1066 | priv->rc_keycode = buf[12] << 8 | buf[14]; | ||
| 1067 | } else { | ||
| 1068 | /* NEC extended*/ | ||
| 1069 | priv->rc_keycode = buf[12] << 16 | | ||
| 1070 | buf[13] << 8 | buf[14]; | ||
| 1071 | } | ||
| 1072 | } else { | ||
| 1073 | /* 32 bit NEC */ | ||
| 1074 | priv->rc_keycode = buf[12] << 24 | buf[13] << 16 | | ||
| 1075 | buf[14] << 8 | buf[15]; | ||
| 1076 | } | ||
| 1077 | rc_keydown(d->rc_dev, priv->rc_keycode, 0); | ||
| 1078 | } else { | ||
| 1079 | deb_rc("%s: no key press\n", __func__); | ||
| 1080 | /* Invalidate last keypress */ | ||
| 1081 | /* Not really needed, but helps with debug */ | ||
| 1082 | priv->rc_last[2] = priv->rc_last[3]; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | priv->rc_repeat = buf[6]; | ||
| 1086 | |||
| 1087 | error: | ||
| 1088 | if (ret) | ||
| 1089 | err("%s: failed:%d", __func__, ret); | ||
| 1090 | |||
| 1091 | return ret; | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1095 | { | ||
| 1096 | int ret; | ||
| 1097 | |||
| 1098 | if (adap->id == 1) { | ||
| 1099 | /* copy firmware to 2nd demodulator */ | ||
| 1100 | if (af9015_config.dual_mode) { | ||
| 1101 | ret = af9015_copy_firmware(adap->dev); | ||
| 1102 | if (ret) { | ||
| 1103 | err("firmware copy to 2nd frontend " \ | ||
| 1104 | "failed, will disable it"); | ||
| 1105 | af9015_config.dual_mode = 0; | ||
| 1106 | return -ENODEV; | ||
| 1107 | } | ||
| 1108 | } else { | ||
| 1109 | return -ENODEV; | ||
| 1110 | } | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | /* attach demodulator */ | ||
| 1114 | adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id], | ||
| 1115 | &adap->dev->i2c_adap); | ||
| 1116 | |||
| 1117 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | static struct mt2060_config af9015_mt2060_config = { | ||
| 1121 | .i2c_address = 0xc0, | ||
| 1122 | .clock_out = 0, | ||
| 1123 | }; | ||
| 1124 | |||
| 1125 | static struct qt1010_config af9015_qt1010_config = { | ||
| 1126 | .i2c_address = 0xc4, | ||
| 1127 | }; | ||
| 1128 | |||
| 1129 | static struct tda18271_config af9015_tda18271_config = { | ||
| 1130 | .gate = TDA18271_GATE_DIGITAL, | ||
| 1131 | .small_i2c = TDA18271_16_BYTE_CHUNK_INIT, | ||
| 1132 | }; | ||
| 1133 | |||
| 1134 | static struct mxl5005s_config af9015_mxl5003_config = { | ||
| 1135 | .i2c_address = 0xc6, | ||
| 1136 | .if_freq = IF_FREQ_4570000HZ, | ||
| 1137 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
| 1138 | .agc_mode = MXL_SINGLE_AGC, | ||
| 1139 | .tracking_filter = MXL_TF_DEFAULT, | ||
| 1140 | .rssi_enable = MXL_RSSI_ENABLE, | ||
| 1141 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
| 1142 | .div_out = MXL_DIV_OUT_4, | ||
| 1143 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
| 1144 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
| 1145 | .top = MXL5005S_TOP_25P2, | ||
| 1146 | .mod_mode = MXL_DIGITAL_MODE, | ||
| 1147 | .if_mode = MXL_ZERO_IF, | ||
| 1148 | .AgcMasterByte = 0x00, | ||
| 1149 | }; | ||
| 1150 | |||
| 1151 | static struct mxl5005s_config af9015_mxl5005_config = { | ||
| 1152 | .i2c_address = 0xc6, | ||
| 1153 | .if_freq = IF_FREQ_4570000HZ, | ||
| 1154 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
| 1155 | .agc_mode = MXL_SINGLE_AGC, | ||
| 1156 | .tracking_filter = MXL_TF_OFF, | ||
| 1157 | .rssi_enable = MXL_RSSI_ENABLE, | ||
| 1158 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
| 1159 | .div_out = MXL_DIV_OUT_4, | ||
| 1160 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
| 1161 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
| 1162 | .top = MXL5005S_TOP_25P2, | ||
| 1163 | .mod_mode = MXL_DIGITAL_MODE, | ||
| 1164 | .if_mode = MXL_ZERO_IF, | ||
| 1165 | .AgcMasterByte = 0x00, | ||
| 1166 | }; | ||
| 1167 | |||
| 1168 | static struct mc44s803_config af9015_mc44s803_config = { | ||
| 1169 | .i2c_address = 0xc0, | ||
| 1170 | .dig_out = 1, | ||
| 1171 | }; | ||
| 1172 | |||
| 1173 | static struct tda18218_config af9015_tda18218_config = { | ||
| 1174 | .i2c_address = 0xc0, | ||
| 1175 | .i2c_wr_max = 21, /* max wr bytes AF9015 I2C adap can handle at once */ | ||
| 1176 | }; | ||
| 1177 | |||
| 1178 | static struct mxl5007t_config af9015_mxl5007t_config = { | ||
| 1179 | .xtal_freq_hz = MxL_XTAL_24_MHZ, | ||
| 1180 | .if_freq_hz = MxL_IF_4_57_MHZ, | ||
| 1181 | }; | ||
| 1182 | |||
| 1183 | static int af9015_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1184 | { | ||
| 1185 | int ret; | ||
| 1186 | deb_info("%s:\n", __func__); | ||
| 1187 | |||
| 1188 | switch (af9015_af9013_config[adap->id].tuner) { | ||
| 1189 | case AF9013_TUNER_MT2060: | ||
| 1190 | case AF9013_TUNER_MT2060_2: | ||
| 1191 | ret = dvb_attach(mt2060_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 1192 | &af9015_mt2060_config, | ||
| 1193 | af9015_config.mt2060_if1[adap->id]) | ||
| 1194 | == NULL ? -ENODEV : 0; | ||
| 1195 | break; | ||
| 1196 | case AF9013_TUNER_QT1010: | ||
| 1197 | case AF9013_TUNER_QT1010A: | ||
| 1198 | ret = dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 1199 | &af9015_qt1010_config) == NULL ? -ENODEV : 0; | ||
| 1200 | break; | ||
| 1201 | case AF9013_TUNER_TDA18271: | ||
| 1202 | ret = dvb_attach(tda18271_attach, adap->fe, 0xc0, | ||
| 1203 | &adap->dev->i2c_adap, | ||
| 1204 | &af9015_tda18271_config) == NULL ? -ENODEV : 0; | ||
| 1205 | break; | ||
| 1206 | case AF9013_TUNER_TDA18218: | ||
| 1207 | ret = dvb_attach(tda18218_attach, adap->fe, | ||
| 1208 | &adap->dev->i2c_adap, | ||
| 1209 | &af9015_tda18218_config) == NULL ? -ENODEV : 0; | ||
| 1210 | break; | ||
| 1211 | case AF9013_TUNER_MXL5003D: | ||
| 1212 | ret = dvb_attach(mxl5005s_attach, adap->fe, | ||
| 1213 | &adap->dev->i2c_adap, | ||
| 1214 | &af9015_mxl5003_config) == NULL ? -ENODEV : 0; | ||
| 1215 | break; | ||
| 1216 | case AF9013_TUNER_MXL5005D: | ||
| 1217 | case AF9013_TUNER_MXL5005R: | ||
| 1218 | ret = dvb_attach(mxl5005s_attach, adap->fe, | ||
| 1219 | &adap->dev->i2c_adap, | ||
| 1220 | &af9015_mxl5005_config) == NULL ? -ENODEV : 0; | ||
| 1221 | break; | ||
| 1222 | case AF9013_TUNER_ENV77H11D5: | ||
| 1223 | ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0, | ||
| 1224 | &adap->dev->i2c_adap, | ||
| 1225 | DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; | ||
| 1226 | break; | ||
| 1227 | case AF9013_TUNER_MC44S803: | ||
| 1228 | ret = dvb_attach(mc44s803_attach, adap->fe, | ||
| 1229 | &adap->dev->i2c_adap, | ||
| 1230 | &af9015_mc44s803_config) == NULL ? -ENODEV : 0; | ||
| 1231 | break; | ||
| 1232 | case AF9013_TUNER_MXL5007T: | ||
| 1233 | ret = dvb_attach(mxl5007t_attach, adap->fe, | ||
| 1234 | &adap->dev->i2c_adap, | ||
| 1235 | 0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0; | ||
| 1236 | break; | ||
| 1237 | case AF9013_TUNER_UNKNOWN: | ||
| 1238 | default: | ||
| 1239 | ret = -ENODEV; | ||
| 1240 | err("Unknown tuner id:%d", | ||
| 1241 | af9015_af9013_config[adap->id].tuner); | ||
| 1242 | } | ||
| 1243 | return ret; | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | static struct usb_device_id af9015_usb_table[] = { | ||
| 1247 | /* 0 */{USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)}, | ||
| 1248 | {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)}, | ||
| 1249 | {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)}, | ||
| 1250 | {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)}, | ||
| 1251 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)}, | ||
| 1252 | /* 5 */{USB_DEVICE(USB_VID_VISIONPLUS, | ||
| 1253 | USB_PID_TINYTWIN)}, | ||
| 1254 | {USB_DEVICE(USB_VID_VISIONPLUS, | ||
| 1255 | USB_PID_AZUREWAVE_AD_TU700)}, | ||
| 1256 | {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)}, | ||
| 1257 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)}, | ||
| 1258 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)}, | ||
| 1259 | /* 10 */{USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)}, | ||
| 1260 | {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)}, | ||
| 1261 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)}, | ||
| 1262 | {USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)}, | ||
| 1263 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)}, | ||
| 1264 | /* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)}, | ||
| 1265 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)}, | ||
| 1266 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)}, | ||
| 1267 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)}, | ||
| 1268 | {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)}, | ||
| 1269 | /* 20 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)}, | ||
| 1270 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)}, | ||
| 1271 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)}, | ||
| 1272 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)}, | ||
| 1273 | {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)}, | ||
| 1274 | /* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)}, | ||
| 1275 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)}, | ||
| 1276 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)}, | ||
| 1277 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)}, | ||
| 1278 | {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)}, | ||
| 1279 | /* 30 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)}, | ||
| 1280 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)}, | ||
| 1281 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)}, | ||
| 1282 | {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC)}, | ||
| 1283 | {USB_DEVICE(USB_VID_TERRATEC, | ||
| 1284 | USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC)}, | ||
| 1285 | /* 35 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)}, | ||
| 1286 | {USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3)}, | ||
| 1287 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22)}, | ||
| 1288 | {0}, | ||
| 1289 | }; | ||
| 1290 | MODULE_DEVICE_TABLE(usb, af9015_usb_table); | ||
| 1291 | |||
| 1292 | #define AF9015_RC_INTERVAL 500 | ||
| 1293 | static struct dvb_usb_device_properties af9015_properties[] = { | ||
| 1294 | { | ||
| 1295 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1296 | |||
| 1297 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1298 | .download_firmware = af9015_download_firmware, | ||
| 1299 | .firmware = "dvb-usb-af9015.fw", | ||
| 1300 | .no_reconnect = 1, | ||
| 1301 | |||
| 1302 | .size_of_priv = sizeof(struct af9015_state), | ||
| 1303 | |||
| 1304 | .num_adapters = 2, | ||
| 1305 | .adapter = { | ||
| 1306 | { | ||
| 1307 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 1308 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1309 | |||
| 1310 | .pid_filter_count = 32, | ||
| 1311 | .pid_filter = af9015_pid_filter, | ||
| 1312 | .pid_filter_ctrl = af9015_pid_filter_ctrl, | ||
| 1313 | |||
| 1314 | .frontend_attach = | ||
| 1315 | af9015_af9013_frontend_attach, | ||
| 1316 | .tuner_attach = af9015_tuner_attach, | ||
| 1317 | .stream = { | ||
| 1318 | .type = USB_BULK, | ||
| 1319 | .count = 6, | ||
| 1320 | .endpoint = 0x84, | ||
| 1321 | }, | ||
| 1322 | }, | ||
| 1323 | { | ||
| 1324 | .frontend_attach = | ||
| 1325 | af9015_af9013_frontend_attach, | ||
| 1326 | .tuner_attach = af9015_tuner_attach, | ||
| 1327 | .stream = { | ||
| 1328 | .type = USB_BULK, | ||
| 1329 | .count = 6, | ||
| 1330 | .endpoint = 0x85, | ||
| 1331 | .u = { | ||
| 1332 | .bulk = { | ||
| 1333 | .buffersize = | ||
| 1334 | TS_USB20_FRAME_SIZE, | ||
| 1335 | } | ||
| 1336 | } | ||
| 1337 | }, | ||
| 1338 | } | ||
| 1339 | }, | ||
| 1340 | |||
| 1341 | .identify_state = af9015_identify_state, | ||
| 1342 | |||
| 1343 | .rc.core = { | ||
| 1344 | .protocol = RC_TYPE_NEC, | ||
| 1345 | .module_name = "af9015", | ||
| 1346 | .rc_query = af9015_rc_query, | ||
| 1347 | .rc_interval = AF9015_RC_INTERVAL, | ||
| 1348 | .allowed_protos = RC_TYPE_NEC, | ||
| 1349 | }, | ||
| 1350 | |||
| 1351 | .i2c_algo = &af9015_i2c_algo, | ||
| 1352 | |||
| 1353 | .num_device_descs = 12, /* check max from dvb-usb.h */ | ||
| 1354 | .devices = { | ||
| 1355 | { | ||
| 1356 | .name = "Afatech AF9015 DVB-T USB2.0 stick", | ||
| 1357 | .cold_ids = {&af9015_usb_table[0], | ||
| 1358 | &af9015_usb_table[1], NULL}, | ||
| 1359 | .warm_ids = {NULL}, | ||
| 1360 | }, | ||
| 1361 | { | ||
| 1362 | .name = "Leadtek WinFast DTV Dongle Gold", | ||
| 1363 | .cold_ids = {&af9015_usb_table[2], NULL}, | ||
| 1364 | .warm_ids = {NULL}, | ||
| 1365 | }, | ||
| 1366 | { | ||
| 1367 | .name = "Pinnacle PCTV 71e", | ||
| 1368 | .cold_ids = {&af9015_usb_table[3], NULL}, | ||
| 1369 | .warm_ids = {NULL}, | ||
| 1370 | }, | ||
| 1371 | { | ||
| 1372 | .name = "KWorld PlusTV Dual DVB-T Stick " \ | ||
| 1373 | "(DVB-T 399U)", | ||
| 1374 | .cold_ids = {&af9015_usb_table[4], | ||
| 1375 | &af9015_usb_table[25], NULL}, | ||
| 1376 | .warm_ids = {NULL}, | ||
| 1377 | }, | ||
| 1378 | { | ||
| 1379 | .name = "DigitalNow TinyTwin DVB-T Receiver", | ||
| 1380 | .cold_ids = {&af9015_usb_table[5], | ||
| 1381 | &af9015_usb_table[28], | ||
| 1382 | &af9015_usb_table[36], NULL}, | ||
| 1383 | .warm_ids = {NULL}, | ||
| 1384 | }, | ||
| 1385 | { | ||
| 1386 | .name = "TwinHan AzureWave AD-TU700(704J)", | ||
| 1387 | .cold_ids = {&af9015_usb_table[6], NULL}, | ||
| 1388 | .warm_ids = {NULL}, | ||
| 1389 | }, | ||
| 1390 | { | ||
| 1391 | .name = "TerraTec Cinergy T USB XE", | ||
| 1392 | .cold_ids = {&af9015_usb_table[7], NULL}, | ||
| 1393 | .warm_ids = {NULL}, | ||
| 1394 | }, | ||
| 1395 | { | ||
| 1396 | .name = "KWorld PlusTV Dual DVB-T PCI " \ | ||
| 1397 | "(DVB-T PC160-2T)", | ||
| 1398 | .cold_ids = {&af9015_usb_table[8], NULL}, | ||
| 1399 | .warm_ids = {NULL}, | ||
| 1400 | }, | ||
| 1401 | { | ||
| 1402 | .name = "AVerMedia AVerTV DVB-T Volar X", | ||
| 1403 | .cold_ids = {&af9015_usb_table[9], NULL}, | ||
| 1404 | .warm_ids = {NULL}, | ||
| 1405 | }, | ||
| 1406 | { | ||
| 1407 | .name = "TerraTec Cinergy T Stick RC", | ||
| 1408 | .cold_ids = {&af9015_usb_table[33], NULL}, | ||
| 1409 | .warm_ids = {NULL}, | ||
| 1410 | }, | ||
| 1411 | { | ||
| 1412 | .name = "TerraTec Cinergy T Stick Dual RC", | ||
| 1413 | .cold_ids = {&af9015_usb_table[34], NULL}, | ||
| 1414 | .warm_ids = {NULL}, | ||
| 1415 | }, | ||
| 1416 | { | ||
| 1417 | .name = "AverMedia AVerTV Red HD+ (A850T)", | ||
| 1418 | .cold_ids = {&af9015_usb_table[35], NULL}, | ||
| 1419 | .warm_ids = {NULL}, | ||
| 1420 | }, | ||
| 1421 | } | ||
| 1422 | }, { | ||
| 1423 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1424 | |||
| 1425 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1426 | .download_firmware = af9015_download_firmware, | ||
| 1427 | .firmware = "dvb-usb-af9015.fw", | ||
| 1428 | .no_reconnect = 1, | ||
| 1429 | |||
| 1430 | .size_of_priv = sizeof(struct af9015_state), | ||
| 1431 | |||
| 1432 | .num_adapters = 2, | ||
| 1433 | .adapter = { | ||
| 1434 | { | ||
| 1435 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 1436 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1437 | |||
| 1438 | .pid_filter_count = 32, | ||
| 1439 | .pid_filter = af9015_pid_filter, | ||
| 1440 | .pid_filter_ctrl = af9015_pid_filter_ctrl, | ||
| 1441 | |||
| 1442 | .frontend_attach = | ||
| 1443 | af9015_af9013_frontend_attach, | ||
| 1444 | .tuner_attach = af9015_tuner_attach, | ||
| 1445 | .stream = { | ||
| 1446 | .type = USB_BULK, | ||
| 1447 | .count = 6, | ||
| 1448 | .endpoint = 0x84, | ||
| 1449 | }, | ||
| 1450 | }, | ||
| 1451 | { | ||
| 1452 | .frontend_attach = | ||
| 1453 | af9015_af9013_frontend_attach, | ||
| 1454 | .tuner_attach = af9015_tuner_attach, | ||
| 1455 | .stream = { | ||
| 1456 | .type = USB_BULK, | ||
| 1457 | .count = 6, | ||
| 1458 | .endpoint = 0x85, | ||
| 1459 | .u = { | ||
| 1460 | .bulk = { | ||
| 1461 | .buffersize = | ||
| 1462 | TS_USB20_FRAME_SIZE, | ||
| 1463 | } | ||
| 1464 | } | ||
| 1465 | }, | ||
| 1466 | } | ||
| 1467 | }, | ||
| 1468 | |||
| 1469 | .identify_state = af9015_identify_state, | ||
| 1470 | |||
| 1471 | .rc.core = { | ||
| 1472 | .protocol = RC_TYPE_NEC, | ||
| 1473 | .module_name = "af9015", | ||
| 1474 | .rc_query = af9015_rc_query, | ||
| 1475 | .rc_interval = AF9015_RC_INTERVAL, | ||
| 1476 | .allowed_protos = RC_TYPE_NEC, | ||
| 1477 | }, | ||
| 1478 | |||
| 1479 | .i2c_algo = &af9015_i2c_algo, | ||
| 1480 | |||
| 1481 | .num_device_descs = 10, /* check max from dvb-usb.h */ | ||
| 1482 | .devices = { | ||
| 1483 | { | ||
| 1484 | .name = "Xtensions XD-380", | ||
| 1485 | .cold_ids = {&af9015_usb_table[10], NULL}, | ||
| 1486 | .warm_ids = {NULL}, | ||
| 1487 | }, | ||
| 1488 | { | ||
| 1489 | .name = "MSI DIGIVOX Duo", | ||
| 1490 | .cold_ids = {&af9015_usb_table[11], NULL}, | ||
| 1491 | .warm_ids = {NULL}, | ||
| 1492 | }, | ||
| 1493 | { | ||
| 1494 | .name = "Fujitsu-Siemens Slim Mobile USB DVB-T", | ||
| 1495 | .cold_ids = {&af9015_usb_table[12], NULL}, | ||
| 1496 | .warm_ids = {NULL}, | ||
| 1497 | }, | ||
| 1498 | { | ||
| 1499 | .name = "Telestar Starstick 2", | ||
| 1500 | .cold_ids = {&af9015_usb_table[13], NULL}, | ||
| 1501 | .warm_ids = {NULL}, | ||
| 1502 | }, | ||
| 1503 | { | ||
| 1504 | .name = "AVerMedia A309", | ||
| 1505 | .cold_ids = {&af9015_usb_table[14], NULL}, | ||
| 1506 | .warm_ids = {NULL}, | ||
| 1507 | }, | ||
| 1508 | { | ||
| 1509 | .name = "MSI Digi VOX mini III", | ||
| 1510 | .cold_ids = {&af9015_usb_table[15], NULL}, | ||
| 1511 | .warm_ids = {NULL}, | ||
| 1512 | }, | ||
| 1513 | { | ||
| 1514 | .name = "KWorld USB DVB-T TV Stick II " \ | ||
| 1515 | "(VS-DVB-T 395U)", | ||
| 1516 | .cold_ids = {&af9015_usb_table[16], | ||
| 1517 | &af9015_usb_table[17], | ||
| 1518 | &af9015_usb_table[18], | ||
| 1519 | &af9015_usb_table[31], NULL}, | ||
| 1520 | .warm_ids = {NULL}, | ||
| 1521 | }, | ||
| 1522 | { | ||
| 1523 | .name = "TrekStor DVB-T USB Stick", | ||
| 1524 | .cold_ids = {&af9015_usb_table[19], NULL}, | ||
| 1525 | .warm_ids = {NULL}, | ||
| 1526 | }, | ||
| 1527 | { | ||
| 1528 | .name = "AverMedia AVerTV Volar Black HD " \ | ||
| 1529 | "(A850)", | ||
| 1530 | .cold_ids = {&af9015_usb_table[20], NULL}, | ||
| 1531 | .warm_ids = {NULL}, | ||
| 1532 | }, | ||
| 1533 | { | ||
| 1534 | .name = "Sveon STV22 Dual USB DVB-T Tuner HDTV", | ||
| 1535 | .cold_ids = {&af9015_usb_table[37], NULL}, | ||
| 1536 | .warm_ids = {NULL}, | ||
| 1537 | }, | ||
| 1538 | } | ||
| 1539 | }, { | ||
| 1540 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1541 | |||
| 1542 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1543 | .download_firmware = af9015_download_firmware, | ||
| 1544 | .firmware = "dvb-usb-af9015.fw", | ||
| 1545 | .no_reconnect = 1, | ||
| 1546 | |||
| 1547 | .size_of_priv = sizeof(struct af9015_state), | ||
| 1548 | |||
| 1549 | .num_adapters = 2, | ||
| 1550 | .adapter = { | ||
| 1551 | { | ||
| 1552 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 1553 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1554 | |||
| 1555 | .pid_filter_count = 32, | ||
| 1556 | .pid_filter = af9015_pid_filter, | ||
| 1557 | .pid_filter_ctrl = af9015_pid_filter_ctrl, | ||
| 1558 | |||
| 1559 | .frontend_attach = | ||
| 1560 | af9015_af9013_frontend_attach, | ||
| 1561 | .tuner_attach = af9015_tuner_attach, | ||
| 1562 | .stream = { | ||
| 1563 | .type = USB_BULK, | ||
| 1564 | .count = 6, | ||
| 1565 | .endpoint = 0x84, | ||
| 1566 | }, | ||
| 1567 | }, | ||
| 1568 | { | ||
| 1569 | .frontend_attach = | ||
| 1570 | af9015_af9013_frontend_attach, | ||
| 1571 | .tuner_attach = af9015_tuner_attach, | ||
| 1572 | .stream = { | ||
| 1573 | .type = USB_BULK, | ||
| 1574 | .count = 6, | ||
| 1575 | .endpoint = 0x85, | ||
| 1576 | .u = { | ||
| 1577 | .bulk = { | ||
| 1578 | .buffersize = | ||
| 1579 | TS_USB20_FRAME_SIZE, | ||
| 1580 | } | ||
| 1581 | } | ||
| 1582 | }, | ||
| 1583 | } | ||
| 1584 | }, | ||
| 1585 | |||
| 1586 | .identify_state = af9015_identify_state, | ||
| 1587 | |||
| 1588 | .rc.core = { | ||
| 1589 | .protocol = RC_TYPE_NEC, | ||
| 1590 | .module_name = "af9015", | ||
| 1591 | .rc_query = af9015_rc_query, | ||
| 1592 | .rc_interval = AF9015_RC_INTERVAL, | ||
| 1593 | .allowed_protos = RC_TYPE_NEC, | ||
| 1594 | }, | ||
| 1595 | |||
| 1596 | .i2c_algo = &af9015_i2c_algo, | ||
| 1597 | |||
| 1598 | .num_device_descs = 9, /* check max from dvb-usb.h */ | ||
| 1599 | .devices = { | ||
| 1600 | { | ||
| 1601 | .name = "AverMedia AVerTV Volar GPS 805 (A805)", | ||
| 1602 | .cold_ids = {&af9015_usb_table[21], NULL}, | ||
| 1603 | .warm_ids = {NULL}, | ||
| 1604 | }, | ||
| 1605 | { | ||
| 1606 | .name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \ | ||
| 1607 | "V3.0", | ||
| 1608 | .cold_ids = {&af9015_usb_table[22], NULL}, | ||
| 1609 | .warm_ids = {NULL}, | ||
| 1610 | }, | ||
| 1611 | { | ||
| 1612 | .name = "KWorld Digial MC-810", | ||
| 1613 | .cold_ids = {&af9015_usb_table[23], NULL}, | ||
| 1614 | .warm_ids = {NULL}, | ||
| 1615 | }, | ||
| 1616 | { | ||
| 1617 | .name = "Genius TVGo DVB-T03", | ||
| 1618 | .cold_ids = {&af9015_usb_table[24], NULL}, | ||
| 1619 | .warm_ids = {NULL}, | ||
| 1620 | }, | ||
| 1621 | { | ||
| 1622 | .name = "KWorld PlusTV DVB-T PCI Pro Card " \ | ||
| 1623 | "(DVB-T PC160-T)", | ||
| 1624 | .cold_ids = {&af9015_usb_table[26], NULL}, | ||
| 1625 | .warm_ids = {NULL}, | ||
| 1626 | }, | ||
| 1627 | { | ||
| 1628 | .name = "Sveon STV20 Tuner USB DVB-T HDTV", | ||
| 1629 | .cold_ids = {&af9015_usb_table[27], NULL}, | ||
| 1630 | .warm_ids = {NULL}, | ||
| 1631 | }, | ||
| 1632 | { | ||
| 1633 | .name = "Leadtek WinFast DTV2000DS", | ||
| 1634 | .cold_ids = {&af9015_usb_table[29], NULL}, | ||
| 1635 | .warm_ids = {NULL}, | ||
| 1636 | }, | ||
| 1637 | { | ||
| 1638 | .name = "KWorld USB DVB-T Stick Mobile " \ | ||
| 1639 | "(UB383-T)", | ||
| 1640 | .cold_ids = {&af9015_usb_table[30], NULL}, | ||
| 1641 | .warm_ids = {NULL}, | ||
| 1642 | }, | ||
| 1643 | { | ||
| 1644 | .name = "AverMedia AVerTV Volar M (A815Mac)", | ||
| 1645 | .cold_ids = {&af9015_usb_table[32], NULL}, | ||
| 1646 | .warm_ids = {NULL}, | ||
| 1647 | }, | ||
| 1648 | } | ||
| 1649 | }, | ||
| 1650 | }; | ||
| 1651 | |||
| 1652 | static int af9015_usb_probe(struct usb_interface *intf, | ||
| 1653 | const struct usb_device_id *id) | ||
| 1654 | { | ||
| 1655 | int ret = 0; | ||
| 1656 | struct dvb_usb_device *d = NULL; | ||
| 1657 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 1658 | u8 i; | ||
| 1659 | |||
| 1660 | deb_info("%s: interface:%d\n", __func__, | ||
| 1661 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
| 1662 | |||
| 1663 | /* interface 0 is used by DVB-T receiver and | ||
| 1664 | interface 1 is for remote controller (HID) */ | ||
| 1665 | if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { | ||
| 1666 | ret = af9015_read_config(udev); | ||
| 1667 | if (ret) | ||
| 1668 | return ret; | ||
| 1669 | |||
| 1670 | for (i = 0; i < af9015_properties_count; i++) { | ||
| 1671 | ret = dvb_usb_device_init(intf, &af9015_properties[i], | ||
| 1672 | THIS_MODULE, &d, adapter_nr); | ||
| 1673 | if (!ret) | ||
| 1674 | break; | ||
| 1675 | if (ret != -ENODEV) | ||
| 1676 | return ret; | ||
| 1677 | } | ||
| 1678 | if (ret) | ||
| 1679 | return ret; | ||
| 1680 | |||
| 1681 | if (d) | ||
| 1682 | ret = af9015_init(d); | ||
| 1683 | } | ||
| 1684 | |||
| 1685 | return ret; | ||
| 1686 | } | ||
| 1687 | |||
| 1688 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 1689 | static struct usb_driver af9015_usb_driver = { | ||
| 1690 | .name = "dvb_usb_af9015", | ||
| 1691 | .probe = af9015_usb_probe, | ||
| 1692 | .disconnect = dvb_usb_device_exit, | ||
| 1693 | .id_table = af9015_usb_table, | ||
| 1694 | }; | ||
| 1695 | |||
| 1696 | /* module stuff */ | ||
| 1697 | static int __init af9015_usb_module_init(void) | ||
| 1698 | { | ||
| 1699 | int ret; | ||
| 1700 | ret = usb_register(&af9015_usb_driver); | ||
| 1701 | if (ret) | ||
| 1702 | err("module init failed:%d", ret); | ||
| 1703 | |||
| 1704 | return ret; | ||
| 1705 | } | ||
| 1706 | |||
| 1707 | static void __exit af9015_usb_module_exit(void) | ||
| 1708 | { | ||
| 1709 | /* deregister this driver from the USB subsystem */ | ||
| 1710 | usb_deregister(&af9015_usb_driver); | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | module_init(af9015_usb_module_init); | ||
| 1714 | module_exit(af9015_usb_module_exit); | ||
| 1715 | |||
| 1716 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 1717 | MODULE_DESCRIPTION("Driver for Afatech AF9015 DVB-T"); | ||
| 1718 | 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 00000000000..6252ea6c190 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9015.h | |||
| @@ -0,0 +1,124 @@ | |||
| 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 | #define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args) | ||
| 31 | #define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args) | ||
| 32 | #define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args) | ||
| 33 | #define deb_reg(args...) dprintk(dvb_usb_af9015_debug, 0x08, args) | ||
| 34 | #define deb_i2c(args...) dprintk(dvb_usb_af9015_debug, 0x10, args) | ||
| 35 | #define deb_fw(args...) dprintk(dvb_usb_af9015_debug, 0x20, args) | ||
| 36 | |||
| 37 | #define AF9015_I2C_EEPROM 0xa0 | ||
| 38 | #define AF9015_I2C_DEMOD 0x38 | ||
| 39 | #define AF9015_USB_TIMEOUT 2000 | ||
| 40 | |||
| 41 | /* EEPROM locations */ | ||
| 42 | #define AF9015_EEPROM_IR_MODE 0x18 | ||
| 43 | #define AF9015_EEPROM_IR_REMOTE_TYPE 0x34 | ||
| 44 | #define AF9015_EEPROM_TS_MODE 0x31 | ||
| 45 | #define AF9015_EEPROM_DEMOD2_I2C 0x32 | ||
| 46 | |||
| 47 | #define AF9015_EEPROM_SAW_BW1 0x35 | ||
| 48 | #define AF9015_EEPROM_XTAL_TYPE1 0x36 | ||
| 49 | #define AF9015_EEPROM_SPEC_INV1 0x37 | ||
| 50 | #define AF9015_EEPROM_IF1L 0x38 | ||
| 51 | #define AF9015_EEPROM_IF1H 0x39 | ||
| 52 | #define AF9015_EEPROM_MT2060_IF1L 0x3a | ||
| 53 | #define AF9015_EEPROM_MT2060_IF1H 0x3b | ||
| 54 | #define AF9015_EEPROM_TUNER_ID1 0x3c | ||
| 55 | |||
| 56 | #define AF9015_EEPROM_SAW_BW2 0x45 | ||
| 57 | #define AF9015_EEPROM_XTAL_TYPE2 0x46 | ||
| 58 | #define AF9015_EEPROM_SPEC_INV2 0x47 | ||
| 59 | #define AF9015_EEPROM_IF2L 0x48 | ||
| 60 | #define AF9015_EEPROM_IF2H 0x49 | ||
| 61 | #define AF9015_EEPROM_MT2060_IF2L 0x4a | ||
| 62 | #define AF9015_EEPROM_MT2060_IF2H 0x4b | ||
| 63 | #define AF9015_EEPROM_TUNER_ID2 0x4c | ||
| 64 | |||
| 65 | #define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1) | ||
| 66 | |||
| 67 | struct req_t { | ||
| 68 | u8 cmd; /* [0] */ | ||
| 69 | /* seq */ /* [1] */ | ||
| 70 | u8 i2c_addr; /* [2] */ | ||
| 71 | u16 addr; /* [3|4] */ | ||
| 72 | u8 mbox; /* [5] */ | ||
| 73 | u8 addr_len; /* [6] */ | ||
| 74 | u8 data_len; /* [7] */ | ||
| 75 | u8 *data; | ||
| 76 | }; | ||
| 77 | |||
| 78 | enum af9015_cmd { | ||
| 79 | GET_CONFIG = 0x10, | ||
| 80 | DOWNLOAD_FIRMWARE = 0x11, | ||
| 81 | BOOT = 0x13, | ||
| 82 | READ_MEMORY = 0x20, | ||
| 83 | WRITE_MEMORY = 0x21, | ||
| 84 | READ_WRITE_I2C = 0x22, | ||
| 85 | COPY_FIRMWARE = 0x23, | ||
| 86 | RECONNECT_USB = 0x5a, | ||
| 87 | WRITE_VIRTUAL_MEMORY = 0x26, | ||
| 88 | GET_IR_CODE = 0x27, | ||
| 89 | READ_I2C, | ||
| 90 | WRITE_I2C, | ||
| 91 | }; | ||
| 92 | |||
| 93 | enum af9015_ir_mode { | ||
| 94 | AF9015_IR_MODE_DISABLED = 0, | ||
| 95 | AF9015_IR_MODE_HID, | ||
| 96 | AF9015_IR_MODE_RLC, | ||
| 97 | AF9015_IR_MODE_RC6, | ||
| 98 | AF9015_IR_MODE_POLLING, /* just guess */ | ||
| 99 | }; | ||
| 100 | |||
| 101 | struct af9015_state { | ||
| 102 | u8 rc_repeat; | ||
| 103 | u32 rc_keycode; | ||
| 104 | u8 rc_last[4]; | ||
| 105 | }; | ||
| 106 | |||
| 107 | struct af9015_config { | ||
| 108 | u8 dual_mode:1; | ||
| 109 | u16 mt2060_if1[2]; | ||
| 110 | u16 firmware_size; | ||
| 111 | u16 firmware_checksum; | ||
| 112 | u32 eeprom_sum; | ||
| 113 | }; | ||
| 114 | |||
| 115 | enum af9015_remote { | ||
| 116 | AF9015_REMOTE_NONE = 0, | ||
| 117 | /* 1 */ AF9015_REMOTE_A_LINK_DTU_M, | ||
| 118 | AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, | ||
| 119 | AF9015_REMOTE_MYGICTV_U718, | ||
| 120 | AF9015_REMOTE_DIGITTRADE_DVB_T, | ||
| 121 | /* 5 */ AF9015_REMOTE_AVERMEDIA_KS, | ||
| 122 | }; | ||
| 123 | |||
| 124 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c new file mode 100644 index 00000000000..2cbf19a52e3 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/anysee.c | |||
| @@ -0,0 +1,990 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
| 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 | * TODO: | ||
| 21 | * - add smart card reader support for Conditional Access (CA) | ||
| 22 | * | ||
| 23 | * Card reader in Anysee is nothing more than ISO 7816 card reader. | ||
| 24 | * There is no hardware CAM in any Anysee device sold. | ||
| 25 | * In my understanding it should be implemented by making own module | ||
| 26 | * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This | ||
| 27 | * module registers serial interface that can be used to communicate | ||
| 28 | * with any ISO 7816 smart card. | ||
| 29 | * | ||
| 30 | * Any help according to implement serial smart card reader support | ||
| 31 | * is highly welcome! | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include "anysee.h" | ||
| 35 | #include "tda1002x.h" | ||
| 36 | #include "mt352.h" | ||
| 37 | #include "mt352_priv.h" | ||
| 38 | #include "zl10353.h" | ||
| 39 | #include "tda18212.h" | ||
| 40 | #include "cx24116.h" | ||
| 41 | #include "stv0900.h" | ||
| 42 | #include "stv6110.h" | ||
| 43 | #include "isl6423.h" | ||
| 44 | |||
| 45 | /* debug */ | ||
| 46 | static int dvb_usb_anysee_debug; | ||
| 47 | module_param_named(debug, dvb_usb_anysee_debug, int, 0644); | ||
| 48 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
| 49 | static int dvb_usb_anysee_delsys; | ||
| 50 | module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644); | ||
| 51 | MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)"); | ||
| 52 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 53 | |||
| 54 | static DEFINE_MUTEX(anysee_usb_mutex); | ||
| 55 | |||
| 56 | static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, | ||
| 57 | u8 *rbuf, u8 rlen) | ||
| 58 | { | ||
| 59 | struct anysee_state *state = d->priv; | ||
| 60 | int act_len, ret; | ||
| 61 | u8 buf[64]; | ||
| 62 | |||
| 63 | memcpy(&buf[0], sbuf, slen); | ||
| 64 | buf[60] = state->seq++; | ||
| 65 | |||
| 66 | if (mutex_lock_interruptible(&anysee_usb_mutex) < 0) | ||
| 67 | return -EAGAIN; | ||
| 68 | |||
| 69 | /* We need receive one message more after dvb_usb_generic_rw due | ||
| 70 | to weird transaction flow, which is 1 x send + 2 x receive. */ | ||
| 71 | ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); | ||
| 72 | |||
| 73 | if (!ret) { | ||
| 74 | /* receive 2nd answer */ | ||
| 75 | ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, | ||
| 76 | d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), | ||
| 77 | &act_len, 2000); | ||
| 78 | if (ret) | ||
| 79 | err("%s: recv bulk message failed: %d", __func__, ret); | ||
| 80 | else { | ||
| 81 | deb_xfer("<<< "); | ||
| 82 | debug_dump(buf, act_len, deb_xfer); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | /* read request, copy returned data to return buf */ | ||
| 87 | if (!ret && rbuf && rlen) | ||
| 88 | memcpy(rbuf, buf, rlen); | ||
| 89 | |||
| 90 | mutex_unlock(&anysee_usb_mutex); | ||
| 91 | |||
| 92 | return ret; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val) | ||
| 96 | { | ||
| 97 | u8 buf[] = {CMD_REG_READ, reg >> 8, reg & 0xff, 0x01}; | ||
| 98 | int ret; | ||
| 99 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1); | ||
| 100 | deb_info("%s: reg:%04x val:%02x\n", __func__, reg, *val); | ||
| 101 | return ret; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val) | ||
| 105 | { | ||
| 106 | u8 buf[] = {CMD_REG_WRITE, reg >> 8, reg & 0xff, 0x01, val}; | ||
| 107 | deb_info("%s: reg:%04x val:%02x\n", __func__, reg, val); | ||
| 108 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
| 109 | } | ||
| 110 | |||
| 111 | /* write single register with mask */ | ||
| 112 | static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, | ||
| 113 | u8 mask) | ||
| 114 | { | ||
| 115 | int ret; | ||
| 116 | u8 tmp; | ||
| 117 | |||
| 118 | /* no need for read if whole reg is written */ | ||
| 119 | if (mask != 0xff) { | ||
| 120 | ret = anysee_read_reg(d, reg, &tmp); | ||
| 121 | if (ret) | ||
| 122 | return ret; | ||
| 123 | |||
| 124 | val &= mask; | ||
| 125 | tmp &= ~mask; | ||
| 126 | val |= tmp; | ||
| 127 | } | ||
| 128 | |||
| 129 | return anysee_write_reg(d, reg, val); | ||
| 130 | } | ||
| 131 | |||
| 132 | static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id) | ||
| 133 | { | ||
| 134 | u8 buf[] = {CMD_GET_HW_INFO}; | ||
| 135 | return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3); | ||
| 136 | } | ||
| 137 | |||
| 138 | static int anysee_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 139 | { | ||
| 140 | u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00}; | ||
| 141 | deb_info("%s: onoff:%02x\n", __func__, onoff); | ||
| 142 | return anysee_ctrl_msg(adap->dev, buf, sizeof(buf), NULL, 0); | ||
| 143 | } | ||
| 144 | |||
| 145 | static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval) | ||
| 146 | { | ||
| 147 | u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval}; | ||
| 148 | deb_info("%s: state:%02x interval:%02x\n", __func__, mode, interval); | ||
| 149 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
| 150 | } | ||
| 151 | |||
| 152 | static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff) | ||
| 153 | { | ||
| 154 | u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff}; | ||
| 155 | deb_info("%s: onoff:%02x\n", __func__, onoff); | ||
| 156 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
| 157 | } | ||
| 158 | |||
| 159 | static int anysee_init(struct dvb_usb_device *d) | ||
| 160 | { | ||
| 161 | int ret; | ||
| 162 | /* LED light */ | ||
| 163 | ret = anysee_led_ctrl(d, 0x01, 0x03); | ||
| 164 | if (ret) | ||
| 165 | return ret; | ||
| 166 | |||
| 167 | /* enable IR */ | ||
| 168 | ret = anysee_ir_ctrl(d, 1); | ||
| 169 | if (ret) | ||
| 170 | return ret; | ||
| 171 | |||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | /* I2C */ | ||
| 176 | static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | ||
| 177 | int num) | ||
| 178 | { | ||
| 179 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 180 | int ret = 0, inc, i = 0; | ||
| 181 | u8 buf[52]; /* 4 + 48 (I2C WR USB command header + I2C WR max) */ | ||
| 182 | |||
| 183 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 184 | return -EAGAIN; | ||
| 185 | |||
| 186 | while (i < num) { | ||
| 187 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
| 188 | if (msg[i].len > 2 || msg[i+1].len > 60) { | ||
| 189 | ret = -EOPNOTSUPP; | ||
| 190 | break; | ||
| 191 | } | ||
| 192 | buf[0] = CMD_I2C_READ; | ||
| 193 | buf[1] = (msg[i].addr << 1) | 0x01; | ||
| 194 | buf[2] = msg[i].buf[0]; | ||
| 195 | buf[3] = msg[i].buf[1]; | ||
| 196 | buf[4] = msg[i].len-1; | ||
| 197 | buf[5] = msg[i+1].len; | ||
| 198 | ret = anysee_ctrl_msg(d, buf, 6, msg[i+1].buf, | ||
| 199 | msg[i+1].len); | ||
| 200 | inc = 2; | ||
| 201 | } else { | ||
| 202 | if (msg[i].len > 48) { | ||
| 203 | ret = -EOPNOTSUPP; | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | buf[0] = CMD_I2C_WRITE; | ||
| 207 | buf[1] = (msg[i].addr << 1); | ||
| 208 | buf[2] = msg[i].len; | ||
| 209 | buf[3] = 0x01; | ||
| 210 | memcpy(&buf[4], msg[i].buf, msg[i].len); | ||
| 211 | ret = anysee_ctrl_msg(d, buf, 4 + msg[i].len, NULL, 0); | ||
| 212 | inc = 1; | ||
| 213 | } | ||
| 214 | if (ret) | ||
| 215 | break; | ||
| 216 | |||
| 217 | i += inc; | ||
| 218 | } | ||
| 219 | |||
| 220 | mutex_unlock(&d->i2c_mutex); | ||
| 221 | |||
| 222 | return ret ? ret : i; | ||
| 223 | } | ||
| 224 | |||
| 225 | static u32 anysee_i2c_func(struct i2c_adapter *adapter) | ||
| 226 | { | ||
| 227 | return I2C_FUNC_I2C; | ||
| 228 | } | ||
| 229 | |||
| 230 | static struct i2c_algorithm anysee_i2c_algo = { | ||
| 231 | .master_xfer = anysee_master_xfer, | ||
| 232 | .functionality = anysee_i2c_func, | ||
| 233 | }; | ||
| 234 | |||
| 235 | static int anysee_mt352_demod_init(struct dvb_frontend *fe) | ||
| 236 | { | ||
| 237 | static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x28 }; | ||
| 238 | static u8 reset[] = { RESET, 0x80 }; | ||
| 239 | static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; | ||
| 240 | static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0x20 }; | ||
| 241 | static u8 gpp_ctl_cfg[] = { GPP_CTL, 0x33 }; | ||
| 242 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | ||
| 243 | |||
| 244 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
| 245 | udelay(200); | ||
| 246 | mt352_write(fe, reset, sizeof(reset)); | ||
| 247 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
| 248 | |||
| 249 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
| 250 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | ||
| 251 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
| 252 | |||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | /* Callbacks for DVB USB */ | ||
| 257 | static struct tda10023_config anysee_tda10023_config = { | ||
| 258 | .demod_address = (0x1a >> 1), | ||
| 259 | .invert = 0, | ||
| 260 | .xtal = 16000000, | ||
| 261 | .pll_m = 11, | ||
| 262 | .pll_p = 3, | ||
| 263 | .pll_n = 1, | ||
| 264 | .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C, | ||
| 265 | .deltaf = 0xfeeb, | ||
| 266 | }; | ||
| 267 | |||
| 268 | static struct mt352_config anysee_mt352_config = { | ||
| 269 | .demod_address = (0x1e >> 1), | ||
| 270 | .demod_init = anysee_mt352_demod_init, | ||
| 271 | }; | ||
| 272 | |||
| 273 | static struct zl10353_config anysee_zl10353_config = { | ||
| 274 | .demod_address = (0x1e >> 1), | ||
| 275 | .parallel_ts = 1, | ||
| 276 | }; | ||
| 277 | |||
| 278 | static struct zl10353_config anysee_zl10353_tda18212_config2 = { | ||
| 279 | .demod_address = (0x1e >> 1), | ||
| 280 | .parallel_ts = 1, | ||
| 281 | .disable_i2c_gate_ctrl = 1, | ||
| 282 | .no_tuner = 1, | ||
| 283 | .if2 = 41500, | ||
| 284 | }; | ||
| 285 | |||
| 286 | static struct zl10353_config anysee_zl10353_tda18212_config = { | ||
| 287 | .demod_address = (0x18 >> 1), | ||
| 288 | .parallel_ts = 1, | ||
| 289 | .disable_i2c_gate_ctrl = 1, | ||
| 290 | .no_tuner = 1, | ||
| 291 | .if2 = 41500, | ||
| 292 | }; | ||
| 293 | |||
| 294 | static struct tda10023_config anysee_tda10023_tda18212_config = { | ||
| 295 | .demod_address = (0x1a >> 1), | ||
| 296 | .xtal = 16000000, | ||
| 297 | .pll_m = 12, | ||
| 298 | .pll_p = 3, | ||
| 299 | .pll_n = 1, | ||
| 300 | .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C, | ||
| 301 | .deltaf = 0xba02, | ||
| 302 | }; | ||
| 303 | |||
| 304 | static struct tda18212_config anysee_tda18212_config = { | ||
| 305 | .i2c_address = (0xc0 >> 1), | ||
| 306 | .if_dvbt_6 = 4150, | ||
| 307 | .if_dvbt_7 = 4150, | ||
| 308 | .if_dvbt_8 = 4150, | ||
| 309 | .if_dvbc = 5000, | ||
| 310 | }; | ||
| 311 | |||
| 312 | static struct cx24116_config anysee_cx24116_config = { | ||
| 313 | .demod_address = (0xaa >> 1), | ||
| 314 | .mpg_clk_pos_pol = 0x00, | ||
| 315 | .i2c_wr_max = 48, | ||
| 316 | }; | ||
| 317 | |||
| 318 | static struct stv0900_config anysee_stv0900_config = { | ||
| 319 | .demod_address = (0xd0 >> 1), | ||
| 320 | .demod_mode = 0, | ||
| 321 | .xtal = 8000000, | ||
| 322 | .clkmode = 3, | ||
| 323 | .diseqc_mode = 2, | ||
| 324 | .tun1_maddress = 0, | ||
| 325 | .tun1_adc = 1, /* 1 Vpp */ | ||
| 326 | .path1_mode = 3, | ||
| 327 | }; | ||
| 328 | |||
| 329 | static struct stv6110_config anysee_stv6110_config = { | ||
| 330 | .i2c_address = (0xc0 >> 1), | ||
| 331 | .mclk = 16000000, | ||
| 332 | .clk_div = 1, | ||
| 333 | }; | ||
| 334 | |||
| 335 | static struct isl6423_config anysee_isl6423_config = { | ||
| 336 | .current_max = SEC_CURRENT_800m, | ||
| 337 | .curlim = SEC_CURRENT_LIM_OFF, | ||
| 338 | .mod_extern = 1, | ||
| 339 | .addr = (0x10 >> 1), | ||
| 340 | }; | ||
| 341 | |||
| 342 | /* | ||
| 343 | * New USB device strings: Mfr=1, Product=2, SerialNumber=0 | ||
| 344 | * Manufacturer: AMT.CO.KR | ||
| 345 | * | ||
| 346 | * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=???????? | ||
| 347 | * PCB: ? | ||
| 348 | * parts: DNOS404ZH102A(MT352, DTT7579(?)) | ||
| 349 | * | ||
| 350 | * E30 VID=04b4 PID=861f HW=2 FW=2.1 "anysee-T(LP)" | ||
| 351 | * PCB: PCB 507T (rev1.61) | ||
| 352 | * parts: DNOS404ZH103A(ZL10353, DTT7579(?)) | ||
| 353 | * OEA=0a OEB=00 OEC=00 OED=ff OEE=00 | ||
| 354 | * IOA=45 IOB=ff IOC=00 IOD=ff IOE=00 | ||
| 355 | * | ||
| 356 | * E30 Plus VID=04b4 PID=861f HW=6 FW=1.0 "anysee" | ||
| 357 | * PCB: 507CD (rev1.1) | ||
| 358 | * parts: DNOS404ZH103A(ZL10353, DTT7579(?)), CST56I01 | ||
| 359 | * OEA=80 OEB=00 OEC=00 OED=ff OEE=fe | ||
| 360 | * IOA=4f IOB=ff IOC=00 IOD=06 IOE=01 | ||
| 361 | * IOD[0] ZL10353 1=enabled | ||
| 362 | * IOA[7] TS 0=enabled | ||
| 363 | * tuner is not behind ZL10353 I2C-gate (no care if gate disabled or not) | ||
| 364 | * | ||
| 365 | * E30 C Plus VID=04b4 PID=861f HW=10 FW=1.0 "anysee-DC(LP)" | ||
| 366 | * PCB: 507DC (rev0.2) | ||
| 367 | * parts: TDA10023, DTOS403IH102B TM, CST56I01 | ||
| 368 | * OEA=80 OEB=00 OEC=00 OED=ff OEE=fe | ||
| 369 | * IOA=4f IOB=ff IOC=00 IOD=26 IOE=01 | ||
| 370 | * IOD[0] TDA10023 1=enabled | ||
| 371 | * | ||
| 372 | * E30 S2 Plus VID=04b4 PID=861f HW=11 FW=0.1 "anysee-S2(LP)" | ||
| 373 | * PCB: 507SI (rev2.1) | ||
| 374 | * parts: BS2N10WCC01(CX24116, CX24118), ISL6423, TDA8024 | ||
| 375 | * OEA=80 OEB=00 OEC=ff OED=ff OEE=fe | ||
| 376 | * IOA=4d IOB=ff IOC=00 IOD=26 IOE=01 | ||
| 377 | * IOD[0] CX24116 1=enabled | ||
| 378 | * | ||
| 379 | * E30 C Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)" | ||
| 380 | * PCB: 507FA (rev0.4) | ||
| 381 | * parts: TDA10023, DTOS403IH102B TM, TDA8024 | ||
| 382 | * OEA=80 OEB=00 OEC=ff OED=ff OEE=ff | ||
| 383 | * IOA=4d IOB=ff IOC=00 IOD=00 IOE=c0 | ||
| 384 | * IOD[5] TDA10023 1=enabled | ||
| 385 | * IOE[0] tuner 1=enabled | ||
| 386 | * | ||
| 387 | * E30 Combo Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)" | ||
| 388 | * PCB: 507FA (rev1.1) | ||
| 389 | * parts: ZL10353, TDA10023, DTOS403IH102B TM, TDA8024 | ||
| 390 | * OEA=80 OEB=00 OEC=ff OED=ff OEE=ff | ||
| 391 | * IOA=4d IOB=ff IOC=00 IOD=00 IOE=c0 | ||
| 392 | * DVB-C: | ||
| 393 | * IOD[5] TDA10023 1=enabled | ||
| 394 | * IOE[0] tuner 1=enabled | ||
| 395 | * DVB-T: | ||
| 396 | * IOD[0] ZL10353 1=enabled | ||
| 397 | * IOE[0] tuner 0=enabled | ||
| 398 | * tuner is behind ZL10353 I2C-gate | ||
| 399 | * | ||
| 400 | * E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)" | ||
| 401 | * PCB: 508TC (rev0.6) | ||
| 402 | * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212) | ||
| 403 | * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff | ||
| 404 | * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4 | ||
| 405 | * IOA[7] TS 1=enabled | ||
| 406 | * IOE[4] TDA18212 1=enabled | ||
| 407 | * DVB-C: | ||
| 408 | * IOD[6] ZL10353 0=disabled | ||
| 409 | * IOD[5] TDA10023 1=enabled | ||
| 410 | * IOE[0] IF 1=enabled | ||
| 411 | * DVB-T: | ||
| 412 | * IOD[5] TDA10023 0=disabled | ||
| 413 | * IOD[6] ZL10353 1=enabled | ||
| 414 | * IOE[0] IF 0=enabled | ||
| 415 | * | ||
| 416 | * E7 S2 VID=1c73 PID=861f HW=19 FW=0.4 AMTCI=0.5 "anysee-E7S2(LP)" | ||
| 417 | * PCB: 508S2 (rev0.7) | ||
| 418 | * parts: DNBU10512IST(STV0903, STV6110), ISL6423 | ||
| 419 | * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff | ||
| 420 | * IOA=4d IOB=00 IOC=c4 IOD=08 IOE=e4 | ||
| 421 | * IOA[7] TS 1=enabled | ||
| 422 | * IOE[5] STV0903 1=enabled | ||
| 423 | * | ||
| 424 | * E7 PTC VID=1c73 PID=861f HW=21 FW=0.1 AMTCI=?? "anysee-E7PTC(LP)" | ||
| 425 | * PCB: 508PTC (rev0.5) | ||
| 426 | * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212) | ||
| 427 | * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff | ||
| 428 | * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4 | ||
| 429 | * IOA[7] TS 1=enabled | ||
| 430 | * IOE[4] TDA18212 1=enabled | ||
| 431 | * DVB-C: | ||
| 432 | * IOD[6] ZL10353 0=disabled | ||
| 433 | * IOD[5] TDA10023 1=enabled | ||
| 434 | * IOE[0] IF 1=enabled | ||
| 435 | * DVB-T: | ||
| 436 | * IOD[5] TDA10023 0=disabled | ||
| 437 | * IOD[6] ZL10353 1=enabled | ||
| 438 | * IOE[0] IF 0=enabled | ||
| 439 | * | ||
| 440 | * E7 S2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)" | ||
| 441 | * PCB: 508PS2 (rev0.4) | ||
| 442 | * parts: DNBU10512IST(STV0903, STV6110), ISL6423 | ||
| 443 | * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff | ||
| 444 | * IOA=4d IOB=00 IOC=c4 IOD=08 IOE=e4 | ||
| 445 | * IOA[7] TS 1=enabled | ||
| 446 | * IOE[5] STV0903 1=enabled | ||
| 447 | */ | ||
| 448 | |||
| 449 | static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 450 | { | ||
| 451 | int ret; | ||
| 452 | struct anysee_state *state = adap->dev->priv; | ||
| 453 | u8 hw_info[3]; | ||
| 454 | u8 tmp; | ||
| 455 | struct i2c_msg msg[2] = { | ||
| 456 | { | ||
| 457 | .addr = anysee_tda18212_config.i2c_address, | ||
| 458 | .flags = 0, | ||
| 459 | .len = 1, | ||
| 460 | .buf = "\x00", | ||
| 461 | }, { | ||
| 462 | .addr = anysee_tda18212_config.i2c_address, | ||
| 463 | .flags = I2C_M_RD, | ||
| 464 | .len = 1, | ||
| 465 | .buf = &tmp, | ||
| 466 | } | ||
| 467 | }; | ||
| 468 | |||
| 469 | /* Check which hardware we have. | ||
| 470 | * We must do this call two times to get reliable values (hw bug). | ||
| 471 | */ | ||
| 472 | ret = anysee_get_hw_info(adap->dev, hw_info); | ||
| 473 | if (ret) | ||
| 474 | goto error; | ||
| 475 | |||
| 476 | ret = anysee_get_hw_info(adap->dev, hw_info); | ||
| 477 | if (ret) | ||
| 478 | goto error; | ||
| 479 | |||
| 480 | /* Meaning of these info bytes are guessed. */ | ||
| 481 | info("firmware version:%d.%d hardware id:%d", | ||
| 482 | hw_info[1], hw_info[2], hw_info[0]); | ||
| 483 | |||
| 484 | state->hw = hw_info[0]; | ||
| 485 | |||
| 486 | switch (state->hw) { | ||
| 487 | case ANYSEE_HW_507T: /* 2 */ | ||
| 488 | /* E30 */ | ||
| 489 | |||
| 490 | /* attach demod */ | ||
| 491 | adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config, | ||
| 492 | &adap->dev->i2c_adap); | ||
| 493 | if (adap->fe) | ||
| 494 | break; | ||
| 495 | |||
| 496 | /* attach demod */ | ||
| 497 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | ||
| 498 | &adap->dev->i2c_adap); | ||
| 499 | |||
| 500 | break; | ||
| 501 | case ANYSEE_HW_507CD: /* 6 */ | ||
| 502 | /* E30 Plus */ | ||
| 503 | |||
| 504 | /* enable DVB-T demod on IOD[0] */ | ||
| 505 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); | ||
| 506 | if (ret) | ||
| 507 | goto error; | ||
| 508 | |||
| 509 | /* enable transport stream on IOA[7] */ | ||
| 510 | ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (0 << 7), 0x80); | ||
| 511 | if (ret) | ||
| 512 | goto error; | ||
| 513 | |||
| 514 | /* attach demod */ | ||
| 515 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | ||
| 516 | &adap->dev->i2c_adap); | ||
| 517 | |||
| 518 | break; | ||
| 519 | case ANYSEE_HW_507DC: /* 10 */ | ||
| 520 | /* E30 C Plus */ | ||
| 521 | |||
| 522 | /* enable DVB-C demod on IOD[0] */ | ||
| 523 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); | ||
| 524 | if (ret) | ||
| 525 | goto error; | ||
| 526 | |||
| 527 | /* attach demod */ | ||
| 528 | adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config, | ||
| 529 | &adap->dev->i2c_adap, 0x48); | ||
| 530 | |||
| 531 | break; | ||
| 532 | case ANYSEE_HW_507SI: /* 11 */ | ||
| 533 | /* E30 S2 Plus */ | ||
| 534 | |||
| 535 | /* enable DVB-S/S2 demod on IOD[0] */ | ||
| 536 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01); | ||
| 537 | if (ret) | ||
| 538 | goto error; | ||
| 539 | |||
| 540 | /* attach demod */ | ||
| 541 | adap->fe = dvb_attach(cx24116_attach, &anysee_cx24116_config, | ||
| 542 | &adap->dev->i2c_adap); | ||
| 543 | |||
| 544 | break; | ||
| 545 | case ANYSEE_HW_507FA: /* 15 */ | ||
| 546 | /* E30 Combo Plus */ | ||
| 547 | /* E30 C Plus */ | ||
| 548 | |||
| 549 | /* enable tuner on IOE[4] */ | ||
| 550 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); | ||
| 551 | if (ret) | ||
| 552 | goto error; | ||
| 553 | |||
| 554 | /* probe TDA18212 */ | ||
| 555 | tmp = 0; | ||
| 556 | ret = i2c_transfer(&adap->dev->i2c_adap, msg, 2); | ||
| 557 | if (ret == 2 && tmp == 0xc7) | ||
| 558 | deb_info("%s: TDA18212 found\n", __func__); | ||
| 559 | else | ||
| 560 | tmp = 0; | ||
| 561 | |||
| 562 | /* disable tuner on IOE[4] */ | ||
| 563 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10); | ||
| 564 | if (ret) | ||
| 565 | goto error; | ||
| 566 | |||
| 567 | if (dvb_usb_anysee_delsys) { | ||
| 568 | /* disable DVB-C demod on IOD[5] */ | ||
| 569 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5), | ||
| 570 | 0x20); | ||
| 571 | if (ret) | ||
| 572 | goto error; | ||
| 573 | |||
| 574 | /* enable DVB-T demod on IOD[0] */ | ||
| 575 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), | ||
| 576 | 0x01); | ||
| 577 | if (ret) | ||
| 578 | goto error; | ||
| 579 | |||
| 580 | /* attach demod */ | ||
| 581 | if (tmp == 0xc7) { | ||
| 582 | /* TDA18212 config */ | ||
| 583 | adap->fe = dvb_attach(zl10353_attach, | ||
| 584 | &anysee_zl10353_tda18212_config2, | ||
| 585 | &adap->dev->i2c_adap); | ||
| 586 | } else { | ||
| 587 | /* PLL config */ | ||
| 588 | adap->fe = dvb_attach(zl10353_attach, | ||
| 589 | &anysee_zl10353_config, | ||
| 590 | &adap->dev->i2c_adap); | ||
| 591 | } | ||
| 592 | } else { | ||
| 593 | /* disable DVB-T demod on IOD[0] */ | ||
| 594 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0), | ||
| 595 | 0x01); | ||
| 596 | if (ret) | ||
| 597 | goto error; | ||
| 598 | |||
| 599 | /* enable DVB-C demod on IOD[5] */ | ||
| 600 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5), | ||
| 601 | 0x20); | ||
| 602 | if (ret) | ||
| 603 | goto error; | ||
| 604 | |||
| 605 | /* attach demod */ | ||
| 606 | if (tmp == 0xc7) { | ||
| 607 | /* TDA18212 config */ | ||
| 608 | adap->fe = dvb_attach(tda10023_attach, | ||
| 609 | &anysee_tda10023_tda18212_config, | ||
| 610 | &adap->dev->i2c_adap, 0x48); | ||
| 611 | } else { | ||
| 612 | /* PLL config */ | ||
| 613 | adap->fe = dvb_attach(tda10023_attach, | ||
| 614 | &anysee_tda10023_config, | ||
| 615 | &adap->dev->i2c_adap, 0x48); | ||
| 616 | } | ||
| 617 | } | ||
| 618 | |||
| 619 | break; | ||
| 620 | case ANYSEE_HW_508TC: /* 18 */ | ||
| 621 | case ANYSEE_HW_508PTC: /* 21 */ | ||
| 622 | /* E7 TC */ | ||
| 623 | /* E7 PTC */ | ||
| 624 | |||
| 625 | /* enable transport stream on IOA[7] */ | ||
| 626 | ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); | ||
| 627 | if (ret) | ||
| 628 | goto error; | ||
| 629 | |||
| 630 | if (dvb_usb_anysee_delsys) { | ||
| 631 | /* disable DVB-C demod on IOD[5] */ | ||
| 632 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5), | ||
| 633 | 0x20); | ||
| 634 | if (ret) | ||
| 635 | goto error; | ||
| 636 | |||
| 637 | /* enable DVB-T demod on IOD[6] */ | ||
| 638 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6), | ||
| 639 | 0x40); | ||
| 640 | if (ret) | ||
| 641 | goto error; | ||
| 642 | |||
| 643 | /* enable IF route on IOE[0] */ | ||
| 644 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0), | ||
| 645 | 0x01); | ||
| 646 | if (ret) | ||
| 647 | goto error; | ||
| 648 | |||
| 649 | /* attach demod */ | ||
| 650 | adap->fe = dvb_attach(zl10353_attach, | ||
| 651 | &anysee_zl10353_tda18212_config, | ||
| 652 | &adap->dev->i2c_adap); | ||
| 653 | } else { | ||
| 654 | /* disable DVB-T demod on IOD[6] */ | ||
| 655 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6), | ||
| 656 | 0x40); | ||
| 657 | if (ret) | ||
| 658 | goto error; | ||
| 659 | |||
| 660 | /* enable DVB-C demod on IOD[5] */ | ||
| 661 | ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5), | ||
| 662 | 0x20); | ||
| 663 | if (ret) | ||
| 664 | goto error; | ||
| 665 | |||
| 666 | /* enable IF route on IOE[0] */ | ||
| 667 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0), | ||
| 668 | 0x01); | ||
| 669 | if (ret) | ||
| 670 | goto error; | ||
| 671 | |||
| 672 | /* attach demod */ | ||
| 673 | adap->fe = dvb_attach(tda10023_attach, | ||
| 674 | &anysee_tda10023_tda18212_config, | ||
| 675 | &adap->dev->i2c_adap, 0x48); | ||
| 676 | } | ||
| 677 | |||
| 678 | break; | ||
| 679 | case ANYSEE_HW_508S2: /* 19 */ | ||
| 680 | case ANYSEE_HW_508PS2: /* 22 */ | ||
| 681 | /* E7 S2 */ | ||
| 682 | /* E7 PS2 */ | ||
| 683 | |||
| 684 | /* enable transport stream on IOA[7] */ | ||
| 685 | ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80); | ||
| 686 | if (ret) | ||
| 687 | goto error; | ||
| 688 | |||
| 689 | /* enable DVB-S/S2 demod on IOE[5] */ | ||
| 690 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20); | ||
| 691 | if (ret) | ||
| 692 | goto error; | ||
| 693 | |||
| 694 | /* attach demod */ | ||
| 695 | adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config, | ||
| 696 | &adap->dev->i2c_adap, 0); | ||
| 697 | |||
| 698 | break; | ||
| 699 | } | ||
| 700 | |||
| 701 | if (!adap->fe) { | ||
| 702 | /* we have no frontend :-( */ | ||
| 703 | ret = -ENODEV; | ||
| 704 | err("Unsupported Anysee version. " \ | ||
| 705 | "Please report the <linux-media@vger.kernel.org>."); | ||
| 706 | } | ||
| 707 | error: | ||
| 708 | return ret; | ||
| 709 | } | ||
| 710 | |||
| 711 | static int anysee_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 712 | { | ||
| 713 | struct anysee_state *state = adap->dev->priv; | ||
| 714 | struct dvb_frontend *fe; | ||
| 715 | int ret; | ||
| 716 | deb_info("%s:\n", __func__); | ||
| 717 | |||
| 718 | switch (state->hw) { | ||
| 719 | case ANYSEE_HW_507T: /* 2 */ | ||
| 720 | /* E30 */ | ||
| 721 | |||
| 722 | /* attach tuner */ | ||
| 723 | fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1), | ||
| 724 | NULL, DVB_PLL_THOMSON_DTT7579); | ||
| 725 | |||
| 726 | break; | ||
| 727 | case ANYSEE_HW_507CD: /* 6 */ | ||
| 728 | /* E30 Plus */ | ||
| 729 | |||
| 730 | /* attach tuner */ | ||
| 731 | fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1), | ||
| 732 | &adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579); | ||
| 733 | |||
| 734 | break; | ||
| 735 | case ANYSEE_HW_507DC: /* 10 */ | ||
| 736 | /* E30 C Plus */ | ||
| 737 | |||
| 738 | /* attach tuner */ | ||
| 739 | fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1), | ||
| 740 | &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | ||
| 741 | |||
| 742 | break; | ||
| 743 | case ANYSEE_HW_507SI: /* 11 */ | ||
| 744 | /* E30 S2 Plus */ | ||
| 745 | |||
| 746 | /* attach LNB controller */ | ||
| 747 | fe = dvb_attach(isl6423_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 748 | &anysee_isl6423_config); | ||
| 749 | |||
| 750 | break; | ||
| 751 | case ANYSEE_HW_507FA: /* 15 */ | ||
| 752 | /* E30 Combo Plus */ | ||
| 753 | /* E30 C Plus */ | ||
| 754 | |||
| 755 | if (dvb_usb_anysee_delsys) { | ||
| 756 | /* enable DVB-T tuner on IOE[0] */ | ||
| 757 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0), | ||
| 758 | 0x01); | ||
| 759 | if (ret) | ||
| 760 | goto error; | ||
| 761 | } else { | ||
| 762 | /* enable DVB-C tuner on IOE[0] */ | ||
| 763 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0), | ||
| 764 | 0x01); | ||
| 765 | if (ret) | ||
| 766 | goto error; | ||
| 767 | } | ||
| 768 | |||
| 769 | /* Try first attach TDA18212 silicon tuner on IOE[4], if that | ||
| 770 | * fails attach old simple PLL. */ | ||
| 771 | |||
| 772 | /* enable tuner on IOE[4] */ | ||
| 773 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); | ||
| 774 | if (ret) | ||
| 775 | goto error; | ||
| 776 | |||
| 777 | /* attach tuner */ | ||
| 778 | fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 779 | &anysee_tda18212_config); | ||
| 780 | if (fe) | ||
| 781 | break; | ||
| 782 | |||
| 783 | /* disable tuner on IOE[4] */ | ||
| 784 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10); | ||
| 785 | if (ret) | ||
| 786 | goto error; | ||
| 787 | |||
| 788 | /* attach tuner */ | ||
| 789 | fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1), | ||
| 790 | &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | ||
| 791 | |||
| 792 | break; | ||
| 793 | case ANYSEE_HW_508TC: /* 18 */ | ||
| 794 | case ANYSEE_HW_508PTC: /* 21 */ | ||
| 795 | /* E7 TC */ | ||
| 796 | /* E7 PTC */ | ||
| 797 | |||
| 798 | /* enable tuner on IOE[4] */ | ||
| 799 | ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10); | ||
| 800 | if (ret) | ||
| 801 | goto error; | ||
| 802 | |||
| 803 | /* attach tuner */ | ||
| 804 | fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 805 | &anysee_tda18212_config); | ||
| 806 | |||
| 807 | break; | ||
| 808 | case ANYSEE_HW_508S2: /* 19 */ | ||
| 809 | case ANYSEE_HW_508PS2: /* 22 */ | ||
| 810 | /* E7 S2 */ | ||
| 811 | /* E7 PS2 */ | ||
| 812 | |||
| 813 | /* attach tuner */ | ||
| 814 | fe = dvb_attach(stv6110_attach, adap->fe, | ||
| 815 | &anysee_stv6110_config, &adap->dev->i2c_adap); | ||
| 816 | |||
| 817 | if (fe) { | ||
| 818 | /* attach LNB controller */ | ||
| 819 | fe = dvb_attach(isl6423_attach, adap->fe, | ||
| 820 | &adap->dev->i2c_adap, &anysee_isl6423_config); | ||
| 821 | } | ||
| 822 | |||
| 823 | break; | ||
| 824 | default: | ||
| 825 | fe = NULL; | ||
| 826 | } | ||
| 827 | |||
| 828 | if (fe) | ||
| 829 | ret = 0; | ||
| 830 | else | ||
| 831 | ret = -ENODEV; | ||
| 832 | |||
| 833 | error: | ||
| 834 | return ret; | ||
| 835 | } | ||
| 836 | |||
| 837 | static int anysee_rc_query(struct dvb_usb_device *d) | ||
| 838 | { | ||
| 839 | u8 buf[] = {CMD_GET_IR_CODE}; | ||
| 840 | u8 ircode[2]; | ||
| 841 | int ret; | ||
| 842 | |||
| 843 | /* Remote controller is basic NEC using address byte 0x08. | ||
| 844 | Anysee device RC query returns only two bytes, status and code, | ||
| 845 | address byte is dropped. Also it does not return any value for | ||
| 846 | NEC RCs having address byte other than 0x08. Due to that, we | ||
| 847 | cannot use that device as standard NEC receiver. | ||
| 848 | It could be possible make hack which reads whole code directly | ||
| 849 | from device memory... */ | ||
| 850 | |||
| 851 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), ircode, sizeof(ircode)); | ||
| 852 | if (ret) | ||
| 853 | return ret; | ||
| 854 | |||
| 855 | if (ircode[0]) { | ||
| 856 | deb_rc("%s: key pressed %02x\n", __func__, ircode[1]); | ||
| 857 | rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0); | ||
| 858 | } | ||
| 859 | |||
| 860 | return 0; | ||
| 861 | } | ||
| 862 | |||
| 863 | /* DVB USB Driver stuff */ | ||
| 864 | static struct dvb_usb_device_properties anysee_properties; | ||
| 865 | |||
| 866 | static int anysee_probe(struct usb_interface *intf, | ||
| 867 | const struct usb_device_id *id) | ||
| 868 | { | ||
| 869 | struct dvb_usb_device *d; | ||
| 870 | struct usb_host_interface *alt; | ||
| 871 | int ret; | ||
| 872 | |||
| 873 | /* There is one interface with two alternate settings. | ||
| 874 | Alternate setting 0 is for bulk transfer. | ||
| 875 | Alternate setting 1 is for isochronous transfer. | ||
| 876 | We use bulk transfer (alternate setting 0). */ | ||
| 877 | if (intf->num_altsetting < 1) | ||
| 878 | return -ENODEV; | ||
| 879 | |||
| 880 | /* | ||
| 881 | * Anysee is always warm (its USB-bridge, Cypress FX2, uploads | ||
| 882 | * firmware from eeprom). If dvb_usb_device_init() succeeds that | ||
| 883 | * means d is a valid pointer. | ||
| 884 | */ | ||
| 885 | ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d, | ||
| 886 | adapter_nr); | ||
| 887 | if (ret) | ||
| 888 | return ret; | ||
| 889 | |||
| 890 | alt = usb_altnum_to_altsetting(intf, 0); | ||
| 891 | if (alt == NULL) { | ||
| 892 | deb_info("%s: no alt found!\n", __func__); | ||
| 893 | return -ENODEV; | ||
| 894 | } | ||
| 895 | |||
| 896 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, | ||
| 897 | alt->desc.bAlternateSetting); | ||
| 898 | if (ret) | ||
| 899 | return ret; | ||
| 900 | |||
| 901 | return anysee_init(d); | ||
| 902 | } | ||
| 903 | |||
| 904 | static struct usb_device_id anysee_table[] = { | ||
| 905 | { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) }, | ||
| 906 | { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) }, | ||
| 907 | { } /* Terminating entry */ | ||
| 908 | }; | ||
| 909 | MODULE_DEVICE_TABLE(usb, anysee_table); | ||
| 910 | |||
| 911 | static struct dvb_usb_device_properties anysee_properties = { | ||
| 912 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 913 | |||
| 914 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 915 | |||
| 916 | .size_of_priv = sizeof(struct anysee_state), | ||
| 917 | |||
| 918 | .num_adapters = 1, | ||
| 919 | .adapter = { | ||
| 920 | { | ||
| 921 | .streaming_ctrl = anysee_streaming_ctrl, | ||
| 922 | .frontend_attach = anysee_frontend_attach, | ||
| 923 | .tuner_attach = anysee_tuner_attach, | ||
| 924 | .stream = { | ||
| 925 | .type = USB_BULK, | ||
| 926 | .count = 8, | ||
| 927 | .endpoint = 0x82, | ||
| 928 | .u = { | ||
| 929 | .bulk = { | ||
| 930 | .buffersize = (16*512), | ||
| 931 | } | ||
| 932 | } | ||
| 933 | }, | ||
| 934 | } | ||
| 935 | }, | ||
| 936 | |||
| 937 | .rc.core = { | ||
| 938 | .rc_codes = RC_MAP_ANYSEE, | ||
| 939 | .protocol = RC_TYPE_OTHER, | ||
| 940 | .module_name = "anysee", | ||
| 941 | .rc_query = anysee_rc_query, | ||
| 942 | .rc_interval = 250, /* windows driver uses 500ms */ | ||
| 943 | }, | ||
| 944 | |||
| 945 | .i2c_algo = &anysee_i2c_algo, | ||
| 946 | |||
| 947 | .generic_bulk_ctrl_endpoint = 1, | ||
| 948 | |||
| 949 | .num_device_descs = 1, | ||
| 950 | .devices = { | ||
| 951 | { | ||
| 952 | .name = "Anysee DVB USB2.0", | ||
| 953 | .cold_ids = {NULL}, | ||
| 954 | .warm_ids = {&anysee_table[0], | ||
| 955 | &anysee_table[1], NULL}, | ||
| 956 | }, | ||
| 957 | } | ||
| 958 | }; | ||
| 959 | |||
| 960 | static struct usb_driver anysee_driver = { | ||
| 961 | .name = "dvb_usb_anysee", | ||
| 962 | .probe = anysee_probe, | ||
| 963 | .disconnect = dvb_usb_device_exit, | ||
| 964 | .id_table = anysee_table, | ||
| 965 | }; | ||
| 966 | |||
| 967 | /* module stuff */ | ||
| 968 | static int __init anysee_module_init(void) | ||
| 969 | { | ||
| 970 | int ret; | ||
| 971 | |||
| 972 | ret = usb_register(&anysee_driver); | ||
| 973 | if (ret) | ||
| 974 | err("%s: usb_register failed. Error number %d", __func__, ret); | ||
| 975 | |||
| 976 | return ret; | ||
| 977 | } | ||
| 978 | |||
| 979 | static void __exit anysee_module_exit(void) | ||
| 980 | { | ||
| 981 | /* deregister this driver from the USB subsystem */ | ||
| 982 | usb_deregister(&anysee_driver); | ||
| 983 | } | ||
| 984 | |||
| 985 | module_init(anysee_module_init); | ||
| 986 | module_exit(anysee_module_exit); | ||
| 987 | |||
| 988 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 989 | MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0"); | ||
| 990 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h new file mode 100644 index 00000000000..ad6ccd1ea2d --- /dev/null +++ b/drivers/media/dvb/dvb-usb/anysee.h | |||
| @@ -0,0 +1,325 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
| 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 | * TODO: | ||
| 21 | * - add smart card reader support for Conditional Access (CA) | ||
| 22 | * | ||
| 23 | * Card reader in Anysee is nothing more than ISO 7816 card reader. | ||
| 24 | * There is no hardware CAM in any Anysee device sold. | ||
| 25 | * In my understanding it should be implemented by making own module | ||
| 26 | * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This | ||
| 27 | * module registers serial interface that can be used to communicate | ||
| 28 | * with any ISO 7816 smart card. | ||
| 29 | * | ||
| 30 | * Any help according to implement serial smart card reader support | ||
| 31 | * is highly welcome! | ||
| 32 | */ | ||
| 33 | |||
| 34 | #ifndef _DVB_USB_ANYSEE_H_ | ||
| 35 | #define _DVB_USB_ANYSEE_H_ | ||
| 36 | |||
| 37 | #define DVB_USB_LOG_PREFIX "anysee" | ||
| 38 | #include "dvb-usb.h" | ||
| 39 | |||
| 40 | #define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args) | ||
| 41 | #define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args) | ||
| 42 | #define deb_rc(args...) dprintk(dvb_usb_anysee_debug, 0x04, args) | ||
| 43 | #define deb_reg(args...) dprintk(dvb_usb_anysee_debug, 0x08, args) | ||
| 44 | #define deb_i2c(args...) dprintk(dvb_usb_anysee_debug, 0x10, args) | ||
| 45 | #define deb_fw(args...) dprintk(dvb_usb_anysee_debug, 0x20, args) | ||
| 46 | |||
| 47 | enum cmd { | ||
| 48 | CMD_I2C_READ = 0x33, | ||
| 49 | CMD_I2C_WRITE = 0x31, | ||
| 50 | CMD_REG_READ = 0xb0, | ||
| 51 | CMD_REG_WRITE = 0xb1, | ||
| 52 | CMD_STREAMING_CTRL = 0x12, | ||
| 53 | CMD_LED_AND_IR_CTRL = 0x16, | ||
| 54 | CMD_GET_IR_CODE = 0x41, | ||
| 55 | CMD_GET_HW_INFO = 0x19, | ||
| 56 | CMD_SMARTCARD = 0x34, | ||
| 57 | }; | ||
| 58 | |||
| 59 | struct anysee_state { | ||
| 60 | u8 hw; /* PCB ID */ | ||
| 61 | u8 seq; | ||
| 62 | }; | ||
| 63 | |||
| 64 | #define ANYSEE_HW_507T 2 /* E30 */ | ||
| 65 | #define ANYSEE_HW_507CD 6 /* E30 Plus */ | ||
| 66 | #define ANYSEE_HW_507DC 10 /* E30 C Plus */ | ||
| 67 | #define ANYSEE_HW_507SI 11 /* E30 S2 Plus */ | ||
| 68 | #define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */ | ||
| 69 | #define ANYSEE_HW_508TC 18 /* E7 TC */ | ||
| 70 | #define ANYSEE_HW_508S2 19 /* E7 S2 */ | ||
| 71 | #define ANYSEE_HW_508PTC 21 /* E7 PTC Plus */ | ||
| 72 | #define ANYSEE_HW_508PS2 22 /* E7 PS2 Plus */ | ||
| 73 | |||
| 74 | #define REG_IOA 0x80 /* Port A (bit addressable) */ | ||
| 75 | #define REG_IOB 0x90 /* Port B (bit addressable) */ | ||
| 76 | #define REG_IOC 0xa0 /* Port C (bit addressable) */ | ||
| 77 | #define REG_IOD 0xb0 /* Port D (bit addressable) */ | ||
| 78 | #define REG_IOE 0xb1 /* Port E (NOT bit addressable) */ | ||
| 79 | #define REG_OEA 0xb2 /* Port A Output Enable */ | ||
| 80 | #define REG_OEB 0xb3 /* Port B Output Enable */ | ||
| 81 | #define REG_OEC 0xb4 /* Port C Output Enable */ | ||
| 82 | #define REG_OED 0xb5 /* Port D Output Enable */ | ||
| 83 | #define REG_OEE 0xb6 /* Port E Output Enable */ | ||
| 84 | |||
| 85 | #endif | ||
| 86 | |||
| 87 | /*************************************************************************** | ||
| 88 | * USB API description (reverse engineered) | ||
| 89 | *************************************************************************** | ||
| 90 | |||
| 91 | Transaction flow: | ||
| 92 | ================= | ||
| 93 | BULK[00001] >>> REQUEST PACKET 64 bytes | ||
| 94 | BULK[00081] <<< REPLY PACKET #1 64 bytes (PREVIOUS TRANSACTION REPLY) | ||
| 95 | BULK[00081] <<< REPLY PACKET #2 64 bytes (CURRENT TRANSACTION REPLY) | ||
| 96 | |||
| 97 | General reply packet(s) are always used if not own reply defined. | ||
| 98 | |||
| 99 | ============================================================================ | ||
| 100 | | 00-63 | GENERAL REPLY PACKET #1 (PREVIOUS REPLY) | ||
| 101 | ============================================================================ | ||
| 102 | | 00 | reply data (if any) from previous transaction | ||
| 103 | | | Just same reply packet as returned during previous transaction. | ||
| 104 | | | Needed only if reply is missed in previous transaction. | ||
| 105 | | | Just skip normally. | ||
| 106 | ---------------------------------------------------------------------------- | ||
| 107 | | 01-59 | don't care | ||
| 108 | ---------------------------------------------------------------------------- | ||
| 109 | | 60 | packet sequence number | ||
| 110 | ---------------------------------------------------------------------------- | ||
| 111 | | 61-63 | don't care | ||
| 112 | ---------------------------------------------------------------------------- | ||
| 113 | |||
| 114 | ============================================================================ | ||
| 115 | | 00-63 | GENERAL REPLY PACKET #2 (CURRENT REPLY) | ||
| 116 | ============================================================================ | ||
| 117 | | 00 | reply data (if any) | ||
| 118 | ---------------------------------------------------------------------------- | ||
| 119 | | 01-59 | don't care | ||
| 120 | ---------------------------------------------------------------------------- | ||
| 121 | | 60 | packet sequence number | ||
| 122 | ---------------------------------------------------------------------------- | ||
| 123 | | 61-63 | don't care | ||
| 124 | ---------------------------------------------------------------------------- | ||
| 125 | |||
| 126 | ============================================================================ | ||
| 127 | | 00-63 | I2C WRITE REQUEST PACKET | ||
| 128 | ============================================================================ | ||
| 129 | | 00 | 0x31 I2C write command | ||
| 130 | ---------------------------------------------------------------------------- | ||
| 131 | | 01 | i2c address | ||
| 132 | ---------------------------------------------------------------------------- | ||
| 133 | | 02 | data length | ||
| 134 | | | 0x02 (for typical I2C reg / val pair) | ||
| 135 | ---------------------------------------------------------------------------- | ||
| 136 | | 03 | 0x01 | ||
| 137 | ---------------------------------------------------------------------------- | ||
| 138 | | 04- | data | ||
| 139 | ---------------------------------------------------------------------------- | ||
| 140 | | -59 | don't care | ||
| 141 | ---------------------------------------------------------------------------- | ||
| 142 | | 60 | packet sequence number | ||
| 143 | ---------------------------------------------------------------------------- | ||
| 144 | | 61-63 | don't care | ||
| 145 | ---------------------------------------------------------------------------- | ||
| 146 | |||
| 147 | ============================================================================ | ||
| 148 | | 00-63 | I2C READ REQUEST PACKET | ||
| 149 | ============================================================================ | ||
| 150 | | 00 | 0x33 I2C read command | ||
| 151 | ---------------------------------------------------------------------------- | ||
| 152 | | 01 | i2c address + 1 | ||
| 153 | ---------------------------------------------------------------------------- | ||
| 154 | | 02 | register | ||
| 155 | ---------------------------------------------------------------------------- | ||
| 156 | | 03 | 0x00 | ||
| 157 | ---------------------------------------------------------------------------- | ||
| 158 | | 04 | 0x00 | ||
| 159 | ---------------------------------------------------------------------------- | ||
| 160 | | 05 | data length | ||
| 161 | ---------------------------------------------------------------------------- | ||
| 162 | | 06-59 | don't care | ||
| 163 | ---------------------------------------------------------------------------- | ||
| 164 | | 60 | packet sequence number | ||
| 165 | ---------------------------------------------------------------------------- | ||
| 166 | | 61-63 | don't care | ||
| 167 | ---------------------------------------------------------------------------- | ||
| 168 | |||
| 169 | ============================================================================ | ||
| 170 | | 00-63 | USB CONTROLLER REGISTER WRITE REQUEST PACKET | ||
| 171 | ============================================================================ | ||
| 172 | | 00 | 0xb1 register write command | ||
| 173 | ---------------------------------------------------------------------------- | ||
| 174 | | 01-02 | register | ||
| 175 | ---------------------------------------------------------------------------- | ||
| 176 | | 03 | 0x01 | ||
| 177 | ---------------------------------------------------------------------------- | ||
| 178 | | 04 | value | ||
| 179 | ---------------------------------------------------------------------------- | ||
| 180 | | 05-59 | don't care | ||
| 181 | ---------------------------------------------------------------------------- | ||
| 182 | | 60 | packet sequence number | ||
| 183 | ---------------------------------------------------------------------------- | ||
| 184 | | 61-63 | don't care | ||
| 185 | ---------------------------------------------------------------------------- | ||
| 186 | |||
| 187 | ============================================================================ | ||
| 188 | | 00-63 | USB CONTROLLER REGISTER READ REQUEST PACKET | ||
| 189 | ============================================================================ | ||
| 190 | | 00 | 0xb0 register read command | ||
| 191 | ---------------------------------------------------------------------------- | ||
| 192 | | 01-02 | register | ||
| 193 | ---------------------------------------------------------------------------- | ||
| 194 | | 03 | 0x01 | ||
| 195 | ---------------------------------------------------------------------------- | ||
| 196 | | 04-59 | don't care | ||
| 197 | ---------------------------------------------------------------------------- | ||
| 198 | | 60 | packet sequence number | ||
| 199 | ---------------------------------------------------------------------------- | ||
| 200 | | 61-63 | don't care | ||
| 201 | ---------------------------------------------------------------------------- | ||
| 202 | |||
| 203 | ============================================================================ | ||
| 204 | | 00-63 | LED CONTROL REQUEST PACKET | ||
| 205 | ============================================================================ | ||
| 206 | | 00 | 0x16 LED and IR control command | ||
| 207 | ---------------------------------------------------------------------------- | ||
| 208 | | 01 | 0x01 (LED) | ||
| 209 | ---------------------------------------------------------------------------- | ||
| 210 | | 03 | 0x00 blink | ||
| 211 | | | 0x01 lights continuously | ||
| 212 | ---------------------------------------------------------------------------- | ||
| 213 | | 04 | blink interval | ||
| 214 | | | 0x00 fastest (looks like LED lights continuously) | ||
| 215 | | | 0xff slowest | ||
| 216 | ---------------------------------------------------------------------------- | ||
| 217 | | 05-59 | don't care | ||
| 218 | ---------------------------------------------------------------------------- | ||
| 219 | | 60 | packet sequence number | ||
| 220 | ---------------------------------------------------------------------------- | ||
| 221 | | 61-63 | don't care | ||
| 222 | ---------------------------------------------------------------------------- | ||
| 223 | |||
| 224 | ============================================================================ | ||
| 225 | | 00-63 | IR CONTROL REQUEST PACKET | ||
| 226 | ============================================================================ | ||
| 227 | | 00 | 0x16 LED and IR control command | ||
| 228 | ---------------------------------------------------------------------------- | ||
| 229 | | 01 | 0x02 (IR) | ||
| 230 | ---------------------------------------------------------------------------- | ||
| 231 | | 03 | 0x00 IR disabled | ||
| 232 | | | 0x01 IR enabled | ||
| 233 | ---------------------------------------------------------------------------- | ||
| 234 | | 04-59 | don't care | ||
| 235 | ---------------------------------------------------------------------------- | ||
| 236 | | 60 | packet sequence number | ||
| 237 | ---------------------------------------------------------------------------- | ||
| 238 | | 61-63 | don't care | ||
| 239 | ---------------------------------------------------------------------------- | ||
| 240 | |||
| 241 | ============================================================================ | ||
| 242 | | 00-63 | STREAMING CONTROL REQUEST PACKET | ||
| 243 | ============================================================================ | ||
| 244 | | 00 | 0x12 streaming control command | ||
| 245 | ---------------------------------------------------------------------------- | ||
| 246 | | 01 | 0x00 streaming disabled | ||
| 247 | | | 0x01 streaming enabled | ||
| 248 | ---------------------------------------------------------------------------- | ||
| 249 | | 02 | 0x00 | ||
| 250 | ---------------------------------------------------------------------------- | ||
| 251 | | 03-59 | don't care | ||
| 252 | ---------------------------------------------------------------------------- | ||
| 253 | | 60 | packet sequence number | ||
| 254 | ---------------------------------------------------------------------------- | ||
| 255 | | 61-63 | don't care | ||
| 256 | ---------------------------------------------------------------------------- | ||
| 257 | |||
| 258 | ============================================================================ | ||
| 259 | | 00-63 | REMOTE CONTROL REQUEST PACKET | ||
| 260 | ============================================================================ | ||
| 261 | | 00 | 0x41 remote control command | ||
| 262 | ---------------------------------------------------------------------------- | ||
| 263 | | 01-59 | don't care | ||
| 264 | ---------------------------------------------------------------------------- | ||
| 265 | | 60 | packet sequence number | ||
| 266 | ---------------------------------------------------------------------------- | ||
| 267 | | 61-63 | don't care | ||
| 268 | ---------------------------------------------------------------------------- | ||
| 269 | |||
| 270 | ============================================================================ | ||
| 271 | | 00-63 | REMOTE CONTROL REPLY PACKET | ||
| 272 | ============================================================================ | ||
| 273 | | 00 | 0x00 code not received | ||
| 274 | | | 0x01 code received | ||
| 275 | ---------------------------------------------------------------------------- | ||
| 276 | | 01 | remote control code | ||
| 277 | ---------------------------------------------------------------------------- | ||
| 278 | | 02-59 | don't care | ||
| 279 | ---------------------------------------------------------------------------- | ||
| 280 | | 60 | packet sequence number | ||
| 281 | ---------------------------------------------------------------------------- | ||
| 282 | | 61-63 | don't care | ||
| 283 | ---------------------------------------------------------------------------- | ||
| 284 | |||
| 285 | ============================================================================ | ||
| 286 | | 00-63 | GET HARDWARE INFO REQUEST PACKET | ||
| 287 | ============================================================================ | ||
| 288 | | 00 | 0x19 get hardware info command | ||
| 289 | ---------------------------------------------------------------------------- | ||
| 290 | | 01-59 | don't care | ||
| 291 | ---------------------------------------------------------------------------- | ||
| 292 | | 60 | packet sequence number | ||
| 293 | ---------------------------------------------------------------------------- | ||
| 294 | | 61-63 | don't care | ||
| 295 | ---------------------------------------------------------------------------- | ||
| 296 | |||
| 297 | ============================================================================ | ||
| 298 | | 00-63 | GET HARDWARE INFO REPLY PACKET | ||
| 299 | ============================================================================ | ||
| 300 | | 00 | hardware id | ||
| 301 | ---------------------------------------------------------------------------- | ||
| 302 | | 01-02 | firmware version | ||
| 303 | ---------------------------------------------------------------------------- | ||
| 304 | | 03-59 | don't care | ||
| 305 | ---------------------------------------------------------------------------- | ||
| 306 | | 60 | packet sequence number | ||
| 307 | ---------------------------------------------------------------------------- | ||
| 308 | | 61-63 | don't care | ||
| 309 | ---------------------------------------------------------------------------- | ||
| 310 | |||
| 311 | ============================================================================ | ||
| 312 | | 00-63 | SMART CARD READER PACKET | ||
| 313 | ============================================================================ | ||
| 314 | | 00 | 0x34 smart card reader command | ||
| 315 | ---------------------------------------------------------------------------- | ||
| 316 | | xx | | ||
| 317 | ---------------------------------------------------------------------------- | ||
| 318 | | xx-59 | don't care | ||
| 319 | ---------------------------------------------------------------------------- | ||
| 320 | | 60 | packet sequence number | ||
| 321 | ---------------------------------------------------------------------------- | ||
| 322 | | 61-63 | don't care | ||
| 323 | ---------------------------------------------------------------------------- | ||
| 324 | |||
| 325 | */ | ||
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c new file mode 100644 index 00000000000..2351077ff2b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/au6610.c | |||
| @@ -0,0 +1,268 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Antti Palosaari <crope@iki.fi> | ||
| 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 | #include "au6610.h" | ||
| 22 | #include "zl10353.h" | ||
| 23 | #include "qt1010.h" | ||
| 24 | |||
| 25 | /* debug */ | ||
| 26 | static int dvb_usb_au6610_debug; | ||
| 27 | module_param_named(debug, dvb_usb_au6610_debug, int, 0644); | ||
| 28 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
| 29 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 30 | |||
| 31 | static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, | ||
| 32 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
| 33 | { | ||
| 34 | int ret; | ||
| 35 | u16 index; | ||
| 36 | u8 *usb_buf; | ||
| 37 | |||
| 38 | /* | ||
| 39 | * allocate enough for all known requests, | ||
| 40 | * read returns 5 and write 6 bytes | ||
| 41 | */ | ||
| 42 | usb_buf = kmalloc(6, GFP_KERNEL); | ||
| 43 | if (!usb_buf) | ||
| 44 | return -ENOMEM; | ||
| 45 | |||
| 46 | switch (wlen) { | ||
| 47 | case 1: | ||
| 48 | index = wbuf[0] << 8; | ||
| 49 | break; | ||
| 50 | case 2: | ||
| 51 | index = wbuf[0] << 8; | ||
| 52 | index += wbuf[1]; | ||
| 53 | break; | ||
| 54 | default: | ||
| 55 | warn("wlen = %x, aborting.", wlen); | ||
| 56 | ret = -EINVAL; | ||
| 57 | goto error; | ||
| 58 | } | ||
| 59 | |||
| 60 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, | ||
| 61 | USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, | ||
| 62 | usb_buf, 6, AU6610_USB_TIMEOUT); | ||
| 63 | if (ret < 0) | ||
| 64 | goto error; | ||
| 65 | |||
| 66 | switch (operation) { | ||
| 67 | case AU6610_REQ_I2C_READ: | ||
| 68 | case AU6610_REQ_USB_READ: | ||
| 69 | /* requested value is always 5th byte in buffer */ | ||
| 70 | rbuf[0] = usb_buf[4]; | ||
| 71 | } | ||
| 72 | error: | ||
| 73 | kfree(usb_buf); | ||
| 74 | return ret; | ||
| 75 | } | ||
| 76 | |||
| 77 | static int au6610_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
| 78 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
| 79 | { | ||
| 80 | u8 request; | ||
| 81 | u8 wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
| 82 | |||
| 83 | if (wo) { | ||
| 84 | request = AU6610_REQ_I2C_WRITE; | ||
| 85 | } else { /* rw */ | ||
| 86 | request = AU6610_REQ_I2C_READ; | ||
| 87 | } | ||
| 88 | |||
| 89 | return au6610_usb_msg(d, request, addr, wbuf, wlen, rbuf, rlen); | ||
| 90 | } | ||
| 91 | |||
| 92 | |||
| 93 | /* I2C */ | ||
| 94 | static int au6610_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 95 | int num) | ||
| 96 | { | ||
| 97 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 98 | int i; | ||
| 99 | |||
| 100 | if (num > 2) | ||
| 101 | return -EINVAL; | ||
| 102 | |||
| 103 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 104 | return -EAGAIN; | ||
| 105 | |||
| 106 | for (i = 0; i < num; i++) { | ||
| 107 | /* write/read request */ | ||
| 108 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
| 109 | if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
| 110 | msg[i].len, msg[i+1].buf, | ||
| 111 | msg[i+1].len) < 0) | ||
| 112 | break; | ||
| 113 | i++; | ||
| 114 | } else if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
| 115 | msg[i].len, NULL, 0) < 0) | ||
| 116 | break; | ||
| 117 | } | ||
| 118 | |||
| 119 | mutex_unlock(&d->i2c_mutex); | ||
| 120 | return i; | ||
| 121 | } | ||
| 122 | |||
| 123 | |||
| 124 | static u32 au6610_i2c_func(struct i2c_adapter *adapter) | ||
| 125 | { | ||
| 126 | return I2C_FUNC_I2C; | ||
| 127 | } | ||
| 128 | |||
| 129 | static struct i2c_algorithm au6610_i2c_algo = { | ||
| 130 | .master_xfer = au6610_i2c_xfer, | ||
| 131 | .functionality = au6610_i2c_func, | ||
| 132 | }; | ||
| 133 | |||
| 134 | /* Callbacks for DVB USB */ | ||
| 135 | static struct zl10353_config au6610_zl10353_config = { | ||
| 136 | .demod_address = 0x0f, | ||
| 137 | .no_tuner = 1, | ||
| 138 | .parallel_ts = 1, | ||
| 139 | }; | ||
| 140 | |||
| 141 | static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 142 | { | ||
| 143 | adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config, | ||
| 144 | &adap->dev->i2c_adap); | ||
| 145 | if (adap->fe == NULL) | ||
| 146 | return -ENODEV; | ||
| 147 | |||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | |||
| 151 | static struct qt1010_config au6610_qt1010_config = { | ||
| 152 | .i2c_address = 0x62 | ||
| 153 | }; | ||
| 154 | |||
| 155 | static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 156 | { | ||
| 157 | return dvb_attach(qt1010_attach, | ||
| 158 | adap->fe, &adap->dev->i2c_adap, | ||
| 159 | &au6610_qt1010_config) == NULL ? -ENODEV : 0; | ||
| 160 | } | ||
| 161 | |||
| 162 | /* DVB USB Driver stuff */ | ||
| 163 | static struct dvb_usb_device_properties au6610_properties; | ||
| 164 | |||
| 165 | static int au6610_probe(struct usb_interface *intf, | ||
| 166 | const struct usb_device_id *id) | ||
| 167 | { | ||
| 168 | struct dvb_usb_device *d; | ||
| 169 | struct usb_host_interface *alt; | ||
| 170 | int ret; | ||
| 171 | |||
| 172 | if (intf->num_altsetting < AU6610_ALTSETTING_COUNT) | ||
| 173 | return -ENODEV; | ||
| 174 | |||
| 175 | ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d, | ||
| 176 | adapter_nr); | ||
| 177 | if (ret == 0) { | ||
| 178 | alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING); | ||
| 179 | |||
| 180 | if (alt == NULL) { | ||
| 181 | deb_info("%s: no alt found!\n", __func__); | ||
| 182 | return -ENODEV; | ||
| 183 | } | ||
| 184 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, | ||
| 185 | alt->desc.bAlternateSetting); | ||
| 186 | } | ||
| 187 | |||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | static struct usb_device_id au6610_table [] = { | ||
| 192 | { USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) }, | ||
| 193 | { } /* Terminating entry */ | ||
| 194 | }; | ||
| 195 | MODULE_DEVICE_TABLE(usb, au6610_table); | ||
| 196 | |||
| 197 | static struct dvb_usb_device_properties au6610_properties = { | ||
| 198 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 199 | |||
| 200 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 201 | |||
| 202 | .size_of_priv = 0, | ||
| 203 | |||
| 204 | .num_adapters = 1, | ||
| 205 | .adapter = { | ||
| 206 | { | ||
| 207 | .frontend_attach = au6610_zl10353_frontend_attach, | ||
| 208 | .tuner_attach = au6610_qt1010_tuner_attach, | ||
| 209 | |||
| 210 | .stream = { | ||
| 211 | .type = USB_ISOC, | ||
| 212 | .count = 5, | ||
| 213 | .endpoint = 0x82, | ||
| 214 | .u = { | ||
| 215 | .isoc = { | ||
| 216 | .framesperurb = 40, | ||
| 217 | .framesize = 942, | ||
| 218 | .interval = 1, | ||
| 219 | } | ||
| 220 | } | ||
| 221 | }, | ||
| 222 | } | ||
| 223 | }, | ||
| 224 | |||
| 225 | .i2c_algo = &au6610_i2c_algo, | ||
| 226 | |||
| 227 | .num_device_descs = 1, | ||
| 228 | .devices = { | ||
| 229 | { | ||
| 230 | .name = "Sigmatek DVB-110 DVB-T USB2.0", | ||
| 231 | .cold_ids = {NULL}, | ||
| 232 | .warm_ids = {&au6610_table[0], NULL}, | ||
| 233 | }, | ||
| 234 | } | ||
| 235 | }; | ||
| 236 | |||
| 237 | static struct usb_driver au6610_driver = { | ||
| 238 | .name = "dvb_usb_au6610", | ||
| 239 | .probe = au6610_probe, | ||
| 240 | .disconnect = dvb_usb_device_exit, | ||
| 241 | .id_table = au6610_table, | ||
| 242 | }; | ||
| 243 | |||
| 244 | /* module stuff */ | ||
| 245 | static int __init au6610_module_init(void) | ||
| 246 | { | ||
| 247 | int ret; | ||
| 248 | |||
| 249 | ret = usb_register(&au6610_driver); | ||
| 250 | if (ret) | ||
| 251 | err("usb_register failed. Error number %d", ret); | ||
| 252 | |||
| 253 | return ret; | ||
| 254 | } | ||
| 255 | |||
| 256 | static void __exit au6610_module_exit(void) | ||
| 257 | { | ||
| 258 | /* deregister this driver from the USB subsystem */ | ||
| 259 | usb_deregister(&au6610_driver); | ||
| 260 | } | ||
| 261 | |||
| 262 | module_init(au6610_module_init); | ||
| 263 | module_exit(au6610_module_exit); | ||
| 264 | |||
| 265 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 266 | MODULE_DESCRIPTION("Driver for Alcor Micro AU6610 DVB-T USB2.0"); | ||
| 267 | MODULE_VERSION("0.1"); | ||
| 268 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/au6610.h b/drivers/media/dvb/dvb-usb/au6610.h new file mode 100644 index 00000000000..7849abe2c61 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/au6610.h | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Antti Palosaari <crope@iki.fi> | ||
| 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 _DVB_USB_AU6610_H_ | ||
| 22 | #define _DVB_USB_AU6610_H_ | ||
| 23 | |||
| 24 | #define DVB_USB_LOG_PREFIX "au6610" | ||
| 25 | #include "dvb-usb.h" | ||
| 26 | |||
| 27 | #define deb_info(args...) dprintk(dvb_usb_au6610_debug, 0x01, args) | ||
| 28 | |||
| 29 | #define AU6610_REQ_I2C_WRITE 0x14 | ||
| 30 | #define AU6610_REQ_I2C_READ 0x13 | ||
| 31 | #define AU6610_REQ_USB_WRITE 0x16 | ||
| 32 | #define AU6610_REQ_USB_READ 0x15 | ||
| 33 | |||
| 34 | #define AU6610_USB_TIMEOUT 1000 | ||
| 35 | |||
| 36 | #define AU6610_ALTSETTING_COUNT 6 | ||
| 37 | #define AU6610_ALTSETTING 5 | ||
| 38 | |||
| 39 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c new file mode 100644 index 00000000000..57e2444d51a --- /dev/null +++ b/drivers/media/dvb/dvb-usb/az6027.c | |||
| @@ -0,0 +1,1203 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the AZUREWAVE DVB-S/S2 USB2.0 (AZ6027) | ||
| 2 | * receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Adams.Xu <adams.xu@azwave.com.cn> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the Free | ||
| 8 | * Software Foundation, version 2. | ||
| 9 | * | ||
| 10 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 11 | */ | ||
| 12 | #include "az6027.h" | ||
| 13 | |||
| 14 | #include "stb0899_drv.h" | ||
| 15 | #include "stb0899_reg.h" | ||
| 16 | #include "stb0899_cfg.h" | ||
| 17 | |||
| 18 | #include "stb6100.h" | ||
| 19 | #include "stb6100_cfg.h" | ||
| 20 | #include "dvb_ca_en50221.h" | ||
| 21 | |||
| 22 | int dvb_usb_az6027_debug; | ||
| 23 | module_param_named(debug, dvb_usb_az6027_debug, int, 0644); | ||
| 24 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 25 | |||
| 26 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 27 | |||
| 28 | struct az6027_device_state { | ||
| 29 | struct dvb_ca_en50221 ca; | ||
| 30 | struct mutex ca_mutex; | ||
| 31 | u8 power_state; | ||
| 32 | }; | ||
| 33 | |||
| 34 | static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = { | ||
| 35 | |||
| 36 | /* 0x0000000b, SYSREG */ | ||
| 37 | { STB0899_DEV_ID , 0x30 }, | ||
| 38 | { STB0899_DISCNTRL1 , 0x32 }, | ||
| 39 | { STB0899_DISCNTRL2 , 0x80 }, | ||
| 40 | { STB0899_DISRX_ST0 , 0x04 }, | ||
| 41 | { STB0899_DISRX_ST1 , 0x00 }, | ||
| 42 | { STB0899_DISPARITY , 0x00 }, | ||
| 43 | { STB0899_DISFIFO , 0x00 }, | ||
| 44 | { STB0899_DISSTATUS , 0x20 }, | ||
| 45 | { STB0899_DISF22 , 0x99 }, | ||
| 46 | { STB0899_DISF22RX , 0xa8 }, | ||
| 47 | /* SYSREG ? */ | ||
| 48 | { STB0899_ACRPRESC , 0x11 }, | ||
| 49 | { STB0899_ACRDIV1 , 0x0a }, | ||
| 50 | { STB0899_ACRDIV2 , 0x05 }, | ||
| 51 | { STB0899_DACR1 , 0x00 }, | ||
| 52 | { STB0899_DACR2 , 0x00 }, | ||
| 53 | { STB0899_OUTCFG , 0x00 }, | ||
| 54 | { STB0899_MODECFG , 0x00 }, | ||
| 55 | { STB0899_IRQSTATUS_3 , 0xfe }, | ||
| 56 | { STB0899_IRQSTATUS_2 , 0x03 }, | ||
| 57 | { STB0899_IRQSTATUS_1 , 0x7c }, | ||
| 58 | { STB0899_IRQSTATUS_0 , 0xf4 }, | ||
| 59 | { STB0899_IRQMSK_3 , 0xf3 }, | ||
| 60 | { STB0899_IRQMSK_2 , 0xfc }, | ||
| 61 | { STB0899_IRQMSK_1 , 0xff }, | ||
| 62 | { STB0899_IRQMSK_0 , 0xff }, | ||
| 63 | { STB0899_IRQCFG , 0x00 }, | ||
| 64 | { STB0899_I2CCFG , 0x88 }, | ||
| 65 | { STB0899_I2CRPT , 0x58 }, | ||
| 66 | { STB0899_IOPVALUE5 , 0x00 }, | ||
| 67 | { STB0899_IOPVALUE4 , 0x33 }, | ||
| 68 | { STB0899_IOPVALUE3 , 0x6d }, | ||
| 69 | { STB0899_IOPVALUE2 , 0x90 }, | ||
| 70 | { STB0899_IOPVALUE1 , 0x60 }, | ||
| 71 | { STB0899_IOPVALUE0 , 0x00 }, | ||
| 72 | { STB0899_GPIO00CFG , 0x82 }, | ||
| 73 | { STB0899_GPIO01CFG , 0x82 }, | ||
| 74 | { STB0899_GPIO02CFG , 0x82 }, | ||
| 75 | { STB0899_GPIO03CFG , 0x82 }, | ||
| 76 | { STB0899_GPIO04CFG , 0x82 }, | ||
| 77 | { STB0899_GPIO05CFG , 0x82 }, | ||
| 78 | { STB0899_GPIO06CFG , 0x82 }, | ||
| 79 | { STB0899_GPIO07CFG , 0x82 }, | ||
| 80 | { STB0899_GPIO08CFG , 0x82 }, | ||
| 81 | { STB0899_GPIO09CFG , 0x82 }, | ||
| 82 | { STB0899_GPIO10CFG , 0x82 }, | ||
| 83 | { STB0899_GPIO11CFG , 0x82 }, | ||
| 84 | { STB0899_GPIO12CFG , 0x82 }, | ||
| 85 | { STB0899_GPIO13CFG , 0x82 }, | ||
| 86 | { STB0899_GPIO14CFG , 0x82 }, | ||
| 87 | { STB0899_GPIO15CFG , 0x82 }, | ||
| 88 | { STB0899_GPIO16CFG , 0x82 }, | ||
| 89 | { STB0899_GPIO17CFG , 0x82 }, | ||
| 90 | { STB0899_GPIO18CFG , 0x82 }, | ||
| 91 | { STB0899_GPIO19CFG , 0x82 }, | ||
| 92 | { STB0899_GPIO20CFG , 0x82 }, | ||
| 93 | { STB0899_SDATCFG , 0xb8 }, | ||
| 94 | { STB0899_SCLTCFG , 0xba }, | ||
| 95 | { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */ | ||
| 96 | { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */ | ||
| 97 | { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */ | ||
| 98 | { STB0899_DIRCLKCFG , 0x82 }, | ||
| 99 | { STB0899_CLKOUT27CFG , 0x7e }, | ||
| 100 | { STB0899_STDBYCFG , 0x82 }, | ||
| 101 | { STB0899_CS0CFG , 0x82 }, | ||
| 102 | { STB0899_CS1CFG , 0x82 }, | ||
| 103 | { STB0899_DISEQCOCFG , 0x20 }, | ||
| 104 | { STB0899_GPIO32CFG , 0x82 }, | ||
| 105 | { STB0899_GPIO33CFG , 0x82 }, | ||
| 106 | { STB0899_GPIO34CFG , 0x82 }, | ||
| 107 | { STB0899_GPIO35CFG , 0x82 }, | ||
| 108 | { STB0899_GPIO36CFG , 0x82 }, | ||
| 109 | { STB0899_GPIO37CFG , 0x82 }, | ||
| 110 | { STB0899_GPIO38CFG , 0x82 }, | ||
| 111 | { STB0899_GPIO39CFG , 0x82 }, | ||
| 112 | { STB0899_NCOARSE , 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */ | ||
| 113 | { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */ | ||
| 114 | { STB0899_FILTCTRL , 0x00 }, | ||
| 115 | { STB0899_SYSCTRL , 0x01 }, | ||
| 116 | { STB0899_STOPCLK1 , 0x20 }, | ||
| 117 | { STB0899_STOPCLK2 , 0x00 }, | ||
| 118 | { STB0899_INTBUFSTATUS , 0x00 }, | ||
| 119 | { STB0899_INTBUFCTRL , 0x0a }, | ||
| 120 | { 0xffff , 0xff }, | ||
| 121 | }; | ||
| 122 | |||
| 123 | static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = { | ||
| 124 | { STB0899_DEMOD , 0x00 }, | ||
| 125 | { STB0899_RCOMPC , 0xc9 }, | ||
| 126 | { STB0899_AGC1CN , 0x01 }, | ||
| 127 | { STB0899_AGC1REF , 0x10 }, | ||
| 128 | { STB0899_RTC , 0x23 }, | ||
| 129 | { STB0899_TMGCFG , 0x4e }, | ||
| 130 | { STB0899_AGC2REF , 0x34 }, | ||
| 131 | { STB0899_TLSR , 0x84 }, | ||
| 132 | { STB0899_CFD , 0xf7 }, | ||
| 133 | { STB0899_ACLC , 0x87 }, | ||
| 134 | { STB0899_BCLC , 0x94 }, | ||
| 135 | { STB0899_EQON , 0x41 }, | ||
| 136 | { STB0899_LDT , 0xf1 }, | ||
| 137 | { STB0899_LDT2 , 0xe3 }, | ||
| 138 | { STB0899_EQUALREF , 0xb4 }, | ||
| 139 | { STB0899_TMGRAMP , 0x10 }, | ||
| 140 | { STB0899_TMGTHD , 0x30 }, | ||
| 141 | { STB0899_IDCCOMP , 0xfd }, | ||
| 142 | { STB0899_QDCCOMP , 0xff }, | ||
| 143 | { STB0899_POWERI , 0x0c }, | ||
| 144 | { STB0899_POWERQ , 0x0f }, | ||
| 145 | { STB0899_RCOMP , 0x6c }, | ||
| 146 | { STB0899_AGCIQIN , 0x80 }, | ||
| 147 | { STB0899_AGC2I1 , 0x06 }, | ||
| 148 | { STB0899_AGC2I2 , 0x00 }, | ||
| 149 | { STB0899_TLIR , 0x30 }, | ||
| 150 | { STB0899_RTF , 0x7f }, | ||
| 151 | { STB0899_DSTATUS , 0x00 }, | ||
| 152 | { STB0899_LDI , 0xbc }, | ||
| 153 | { STB0899_CFRM , 0xea }, | ||
| 154 | { STB0899_CFRL , 0x31 }, | ||
| 155 | { STB0899_NIRM , 0x2b }, | ||
| 156 | { STB0899_NIRL , 0x80 }, | ||
| 157 | { STB0899_ISYMB , 0x1d }, | ||
| 158 | { STB0899_QSYMB , 0xa6 }, | ||
| 159 | { STB0899_SFRH , 0x2f }, | ||
| 160 | { STB0899_SFRM , 0x68 }, | ||
| 161 | { STB0899_SFRL , 0x40 }, | ||
| 162 | { STB0899_SFRUPH , 0x2f }, | ||
| 163 | { STB0899_SFRUPM , 0x68 }, | ||
| 164 | { STB0899_SFRUPL , 0x40 }, | ||
| 165 | { STB0899_EQUAI1 , 0x02 }, | ||
| 166 | { STB0899_EQUAQ1 , 0xff }, | ||
| 167 | { STB0899_EQUAI2 , 0x04 }, | ||
| 168 | { STB0899_EQUAQ2 , 0x05 }, | ||
| 169 | { STB0899_EQUAI3 , 0x02 }, | ||
| 170 | { STB0899_EQUAQ3 , 0xfd }, | ||
| 171 | { STB0899_EQUAI4 , 0x03 }, | ||
| 172 | { STB0899_EQUAQ4 , 0x07 }, | ||
| 173 | { STB0899_EQUAI5 , 0x08 }, | ||
| 174 | { STB0899_EQUAQ5 , 0xf5 }, | ||
| 175 | { STB0899_DSTATUS2 , 0x00 }, | ||
| 176 | { STB0899_VSTATUS , 0x00 }, | ||
| 177 | { STB0899_VERROR , 0x86 }, | ||
| 178 | { STB0899_IQSWAP , 0x2a }, | ||
| 179 | { STB0899_ECNT1M , 0x00 }, | ||
| 180 | { STB0899_ECNT1L , 0x00 }, | ||
| 181 | { STB0899_ECNT2M , 0x00 }, | ||
| 182 | { STB0899_ECNT2L , 0x00 }, | ||
| 183 | { STB0899_ECNT3M , 0x0a }, | ||
| 184 | { STB0899_ECNT3L , 0xad }, | ||
| 185 | { STB0899_FECAUTO1 , 0x06 }, | ||
| 186 | { STB0899_FECM , 0x01 }, | ||
| 187 | { STB0899_VTH12 , 0xb0 }, | ||
| 188 | { STB0899_VTH23 , 0x7a }, | ||
| 189 | { STB0899_VTH34 , 0x58 }, | ||
| 190 | { STB0899_VTH56 , 0x38 }, | ||
| 191 | { STB0899_VTH67 , 0x34 }, | ||
| 192 | { STB0899_VTH78 , 0x24 }, | ||
| 193 | { STB0899_PRVIT , 0xff }, | ||
| 194 | { STB0899_VITSYNC , 0x19 }, | ||
| 195 | { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ | ||
| 196 | { STB0899_TSULC , 0x42 }, | ||
| 197 | { STB0899_RSLLC , 0x41 }, | ||
| 198 | { STB0899_TSLPL , 0x12 }, | ||
| 199 | { STB0899_TSCFGH , 0x0c }, | ||
| 200 | { STB0899_TSCFGM , 0x00 }, | ||
| 201 | { STB0899_TSCFGL , 0x00 }, | ||
| 202 | { STB0899_TSOUT , 0x69 }, /* 0x0d for CAM */ | ||
| 203 | { STB0899_RSSYNCDEL , 0x00 }, | ||
| 204 | { STB0899_TSINHDELH , 0x02 }, | ||
| 205 | { STB0899_TSINHDELM , 0x00 }, | ||
| 206 | { STB0899_TSINHDELL , 0x00 }, | ||
| 207 | { STB0899_TSLLSTKM , 0x1b }, | ||
| 208 | { STB0899_TSLLSTKL , 0xb3 }, | ||
| 209 | { STB0899_TSULSTKM , 0x00 }, | ||
| 210 | { STB0899_TSULSTKL , 0x00 }, | ||
| 211 | { STB0899_PCKLENUL , 0xbc }, | ||
| 212 | { STB0899_PCKLENLL , 0xcc }, | ||
| 213 | { STB0899_RSPCKLEN , 0xbd }, | ||
| 214 | { STB0899_TSSTATUS , 0x90 }, | ||
| 215 | { STB0899_ERRCTRL1 , 0xb6 }, | ||
| 216 | { STB0899_ERRCTRL2 , 0x95 }, | ||
| 217 | { STB0899_ERRCTRL3 , 0x8d }, | ||
| 218 | { STB0899_DMONMSK1 , 0x27 }, | ||
| 219 | { STB0899_DMONMSK0 , 0x03 }, | ||
| 220 | { STB0899_DEMAPVIT , 0x5c }, | ||
| 221 | { STB0899_PLPARM , 0x19 }, | ||
| 222 | { STB0899_PDELCTRL , 0x48 }, | ||
| 223 | { STB0899_PDELCTRL2 , 0x00 }, | ||
| 224 | { STB0899_BBHCTRL1 , 0x00 }, | ||
| 225 | { STB0899_BBHCTRL2 , 0x00 }, | ||
| 226 | { STB0899_HYSTTHRESH , 0x77 }, | ||
| 227 | { STB0899_MATCSTM , 0x00 }, | ||
| 228 | { STB0899_MATCSTL , 0x00 }, | ||
| 229 | { STB0899_UPLCSTM , 0x00 }, | ||
| 230 | { STB0899_UPLCSTL , 0x00 }, | ||
| 231 | { STB0899_DFLCSTM , 0x00 }, | ||
| 232 | { STB0899_DFLCSTL , 0x00 }, | ||
| 233 | { STB0899_SYNCCST , 0x00 }, | ||
| 234 | { STB0899_SYNCDCSTM , 0x00 }, | ||
| 235 | { STB0899_SYNCDCSTL , 0x00 }, | ||
| 236 | { STB0899_ISI_ENTRY , 0x00 }, | ||
| 237 | { STB0899_ISI_BIT_EN , 0x00 }, | ||
| 238 | { STB0899_MATSTRM , 0xf0 }, | ||
| 239 | { STB0899_MATSTRL , 0x02 }, | ||
| 240 | { STB0899_UPLSTRM , 0x45 }, | ||
| 241 | { STB0899_UPLSTRL , 0x60 }, | ||
| 242 | { STB0899_DFLSTRM , 0xe3 }, | ||
| 243 | { STB0899_DFLSTRL , 0x00 }, | ||
| 244 | { STB0899_SYNCSTR , 0x47 }, | ||
| 245 | { STB0899_SYNCDSTRM , 0x05 }, | ||
| 246 | { STB0899_SYNCDSTRL , 0x18 }, | ||
| 247 | { STB0899_CFGPDELSTATUS1 , 0x19 }, | ||
| 248 | { STB0899_CFGPDELSTATUS2 , 0x2b }, | ||
| 249 | { STB0899_BBFERRORM , 0x00 }, | ||
| 250 | { STB0899_BBFERRORL , 0x01 }, | ||
| 251 | { STB0899_UPKTERRORM , 0x00 }, | ||
| 252 | { STB0899_UPKTERRORL , 0x00 }, | ||
| 253 | { 0xffff , 0xff }, | ||
| 254 | }; | ||
| 255 | |||
| 256 | |||
| 257 | |||
| 258 | struct stb0899_config az6027_stb0899_config = { | ||
| 259 | .init_dev = az6027_stb0899_s1_init_1, | ||
| 260 | .init_s2_demod = stb0899_s2_init_2, | ||
| 261 | .init_s1_demod = az6027_stb0899_s1_init_3, | ||
| 262 | .init_s2_fec = stb0899_s2_init_4, | ||
| 263 | .init_tst = stb0899_s1_init_5, | ||
| 264 | |||
| 265 | .demod_address = 0xd0, /* 0x68, 0xd0 >> 1 */ | ||
| 266 | |||
| 267 | .xtal_freq = 27000000, | ||
| 268 | .inversion = IQ_SWAP_ON, /* 1 */ | ||
| 269 | |||
| 270 | .lo_clk = 76500000, | ||
| 271 | .hi_clk = 99000000, | ||
| 272 | |||
| 273 | .esno_ave = STB0899_DVBS2_ESNO_AVE, | ||
| 274 | .esno_quant = STB0899_DVBS2_ESNO_QUANT, | ||
| 275 | .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE, | ||
| 276 | .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE, | ||
| 277 | .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD, | ||
| 278 | .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ, | ||
| 279 | .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK, | ||
| 280 | .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF, | ||
| 281 | .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT, | ||
| 282 | |||
| 283 | .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS, | ||
| 284 | .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET, | ||
| 285 | .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS, | ||
| 286 | .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER, | ||
| 287 | |||
| 288 | .tuner_get_frequency = stb6100_get_frequency, | ||
| 289 | .tuner_set_frequency = stb6100_set_frequency, | ||
| 290 | .tuner_set_bandwidth = stb6100_set_bandwidth, | ||
| 291 | .tuner_get_bandwidth = stb6100_get_bandwidth, | ||
| 292 | .tuner_set_rfsiggain = NULL, | ||
| 293 | }; | ||
| 294 | |||
| 295 | struct stb6100_config az6027_stb6100_config = { | ||
| 296 | .tuner_address = 0xc0, | ||
| 297 | .refclock = 27000000, | ||
| 298 | }; | ||
| 299 | |||
| 300 | |||
| 301 | /* check for mutex FIXME */ | ||
| 302 | int az6027_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) | ||
| 303 | { | ||
| 304 | int ret = -1; | ||
| 305 | if (mutex_lock_interruptible(&d->usb_mutex)) | ||
| 306 | return -EAGAIN; | ||
| 307 | |||
| 308 | ret = usb_control_msg(d->udev, | ||
| 309 | usb_rcvctrlpipe(d->udev, 0), | ||
| 310 | req, | ||
| 311 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
| 312 | value, | ||
| 313 | index, | ||
| 314 | b, | ||
| 315 | blen, | ||
| 316 | 2000); | ||
| 317 | |||
| 318 | if (ret < 0) { | ||
| 319 | warn("usb in operation failed. (%d)", ret); | ||
| 320 | ret = -EIO; | ||
| 321 | } else | ||
| 322 | ret = 0; | ||
| 323 | |||
| 324 | deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index); | ||
| 325 | debug_dump(b, blen, deb_xfer); | ||
| 326 | |||
| 327 | mutex_unlock(&d->usb_mutex); | ||
| 328 | return ret; | ||
| 329 | } | ||
| 330 | |||
| 331 | static int az6027_usb_out_op(struct dvb_usb_device *d, | ||
| 332 | u8 req, | ||
| 333 | u16 value, | ||
| 334 | u16 index, | ||
| 335 | u8 *b, | ||
| 336 | int blen) | ||
| 337 | { | ||
| 338 | int ret; | ||
| 339 | |||
| 340 | deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index); | ||
| 341 | debug_dump(b, blen, deb_xfer); | ||
| 342 | |||
| 343 | if (mutex_lock_interruptible(&d->usb_mutex)) | ||
| 344 | return -EAGAIN; | ||
| 345 | |||
| 346 | ret = usb_control_msg(d->udev, | ||
| 347 | usb_sndctrlpipe(d->udev, 0), | ||
| 348 | req, | ||
| 349 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 350 | value, | ||
| 351 | index, | ||
| 352 | b, | ||
| 353 | blen, | ||
| 354 | 2000); | ||
| 355 | |||
| 356 | if (ret != blen) { | ||
| 357 | warn("usb out operation failed. (%d)", ret); | ||
| 358 | mutex_unlock(&d->usb_mutex); | ||
| 359 | return -EIO; | ||
| 360 | } else{ | ||
| 361 | mutex_unlock(&d->usb_mutex); | ||
| 362 | return 0; | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 367 | { | ||
| 368 | int ret; | ||
| 369 | u8 req; | ||
| 370 | u16 value; | ||
| 371 | u16 index; | ||
| 372 | int blen; | ||
| 373 | |||
| 374 | deb_info("%s %d", __func__, onoff); | ||
| 375 | |||
| 376 | req = 0xBC; | ||
| 377 | value = onoff; | ||
| 378 | index = 0; | ||
| 379 | blen = 0; | ||
| 380 | |||
| 381 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
| 382 | if (ret != 0) | ||
| 383 | warn("usb out operation failed. (%d)", ret); | ||
| 384 | |||
| 385 | return ret; | ||
| 386 | } | ||
| 387 | |||
| 388 | /* keys for the enclosed remote control */ | ||
| 389 | static struct rc_map_table rc_map_az6027_table[] = { | ||
| 390 | { 0x01, KEY_1 }, | ||
| 391 | { 0x02, KEY_2 }, | ||
| 392 | }; | ||
| 393 | |||
| 394 | /* remote control stuff (does not work with my box) */ | ||
| 395 | static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 396 | { | ||
| 397 | return 0; | ||
| 398 | } | ||
| 399 | |||
| 400 | /* | ||
| 401 | int az6027_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 402 | { | ||
| 403 | u8 v = onoff; | ||
| 404 | return az6027_usb_out_op(d,0xBC,v,3,NULL,1); | ||
| 405 | } | ||
| 406 | */ | ||
| 407 | |||
| 408 | static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, | ||
| 409 | int slot, | ||
| 410 | int address) | ||
| 411 | { | ||
| 412 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
| 413 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
| 414 | |||
| 415 | int ret; | ||
| 416 | u8 req; | ||
| 417 | u16 value; | ||
| 418 | u16 index; | ||
| 419 | int blen; | ||
| 420 | u8 *b; | ||
| 421 | |||
| 422 | if (slot != 0) | ||
| 423 | return -EINVAL; | ||
| 424 | |||
| 425 | b = kmalloc(12, GFP_KERNEL); | ||
| 426 | if (!b) | ||
| 427 | return -ENOMEM; | ||
| 428 | |||
| 429 | mutex_lock(&state->ca_mutex); | ||
| 430 | |||
| 431 | req = 0xC1; | ||
| 432 | value = address; | ||
| 433 | index = 0; | ||
| 434 | blen = 1; | ||
| 435 | |||
| 436 | ret = az6027_usb_in_op(d, req, value, index, b, blen); | ||
| 437 | if (ret < 0) { | ||
| 438 | warn("usb in operation failed. (%d)", ret); | ||
| 439 | ret = -EINVAL; | ||
| 440 | } else { | ||
| 441 | ret = b[0]; | ||
| 442 | } | ||
| 443 | |||
| 444 | mutex_unlock(&state->ca_mutex); | ||
| 445 | kfree(b); | ||
| 446 | return ret; | ||
| 447 | } | ||
| 448 | |||
| 449 | static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, | ||
| 450 | int slot, | ||
| 451 | int address, | ||
| 452 | u8 value) | ||
| 453 | { | ||
| 454 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
| 455 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
| 456 | |||
| 457 | int ret; | ||
| 458 | u8 req; | ||
| 459 | u16 value1; | ||
| 460 | u16 index; | ||
| 461 | int blen; | ||
| 462 | |||
| 463 | deb_info("%s %d", __func__, slot); | ||
| 464 | if (slot != 0) | ||
| 465 | return -EINVAL; | ||
| 466 | |||
| 467 | mutex_lock(&state->ca_mutex); | ||
| 468 | req = 0xC2; | ||
| 469 | value1 = address; | ||
| 470 | index = value; | ||
| 471 | blen = 0; | ||
| 472 | |||
| 473 | ret = az6027_usb_out_op(d, req, value1, index, NULL, blen); | ||
| 474 | if (ret != 0) | ||
| 475 | warn("usb out operation failed. (%d)", ret); | ||
| 476 | |||
| 477 | mutex_unlock(&state->ca_mutex); | ||
| 478 | return ret; | ||
| 479 | } | ||
| 480 | |||
| 481 | static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca, | ||
| 482 | int slot, | ||
| 483 | u8 address) | ||
| 484 | { | ||
| 485 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
| 486 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
| 487 | |||
| 488 | int ret; | ||
| 489 | u8 req; | ||
| 490 | u16 value; | ||
| 491 | u16 index; | ||
| 492 | int blen; | ||
| 493 | u8 *b; | ||
| 494 | |||
| 495 | if (slot != 0) | ||
| 496 | return -EINVAL; | ||
| 497 | |||
| 498 | b = kmalloc(12, GFP_KERNEL); | ||
| 499 | if (!b) | ||
| 500 | return -ENOMEM; | ||
| 501 | |||
| 502 | mutex_lock(&state->ca_mutex); | ||
| 503 | |||
| 504 | req = 0xC3; | ||
| 505 | value = address; | ||
| 506 | index = 0; | ||
| 507 | blen = 2; | ||
| 508 | |||
| 509 | ret = az6027_usb_in_op(d, req, value, index, b, blen); | ||
| 510 | if (ret < 0) { | ||
| 511 | warn("usb in operation failed. (%d)", ret); | ||
| 512 | ret = -EINVAL; | ||
| 513 | } else { | ||
| 514 | if (b[0] == 0) | ||
| 515 | warn("Read CI IO error"); | ||
| 516 | |||
| 517 | ret = b[1]; | ||
| 518 | deb_info("read cam data = %x from 0x%x", b[1], value); | ||
| 519 | } | ||
| 520 | |||
| 521 | mutex_unlock(&state->ca_mutex); | ||
| 522 | kfree(b); | ||
| 523 | return ret; | ||
| 524 | } | ||
| 525 | |||
| 526 | static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca, | ||
| 527 | int slot, | ||
| 528 | u8 address, | ||
| 529 | u8 value) | ||
| 530 | { | ||
| 531 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
| 532 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
| 533 | |||
| 534 | int ret; | ||
| 535 | u8 req; | ||
| 536 | u16 value1; | ||
| 537 | u16 index; | ||
| 538 | int blen; | ||
| 539 | |||
| 540 | if (slot != 0) | ||
| 541 | return -EINVAL; | ||
| 542 | |||
| 543 | mutex_lock(&state->ca_mutex); | ||
| 544 | req = 0xC4; | ||
| 545 | value1 = address; | ||
| 546 | index = value; | ||
| 547 | blen = 0; | ||
| 548 | |||
| 549 | ret = az6027_usb_out_op(d, req, value1, index, NULL, blen); | ||
| 550 | if (ret != 0) { | ||
| 551 | warn("usb out operation failed. (%d)", ret); | ||
| 552 | goto failed; | ||
| 553 | } | ||
| 554 | |||
| 555 | failed: | ||
| 556 | mutex_unlock(&state->ca_mutex); | ||
| 557 | return ret; | ||
| 558 | } | ||
| 559 | |||
| 560 | static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) | ||
| 561 | { | ||
| 562 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
| 563 | |||
| 564 | int ret; | ||
| 565 | u8 req; | ||
| 566 | u16 value; | ||
| 567 | u16 index; | ||
| 568 | int blen; | ||
| 569 | u8 *b; | ||
| 570 | |||
| 571 | b = kmalloc(12, GFP_KERNEL); | ||
| 572 | if (!b) | ||
| 573 | return -ENOMEM; | ||
| 574 | |||
| 575 | req = 0xC8; | ||
| 576 | value = 0; | ||
| 577 | index = 0; | ||
| 578 | blen = 1; | ||
| 579 | |||
| 580 | ret = az6027_usb_in_op(d, req, value, index, b, blen); | ||
| 581 | if (ret < 0) { | ||
| 582 | warn("usb in operation failed. (%d)", ret); | ||
| 583 | ret = -EIO; | ||
| 584 | } else{ | ||
| 585 | ret = b[0]; | ||
| 586 | } | ||
| 587 | kfree(b); | ||
| 588 | return ret; | ||
| 589 | } | ||
| 590 | |||
| 591 | static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) | ||
| 592 | { | ||
| 593 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
| 594 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
| 595 | |||
| 596 | int ret, i; | ||
| 597 | u8 req; | ||
| 598 | u16 value; | ||
| 599 | u16 index; | ||
| 600 | int blen; | ||
| 601 | |||
| 602 | mutex_lock(&state->ca_mutex); | ||
| 603 | |||
| 604 | req = 0xC6; | ||
| 605 | value = 1; | ||
| 606 | index = 0; | ||
| 607 | blen = 0; | ||
| 608 | |||
| 609 | ret = az6027_usb_out_op(d, req, value, index, NULL, blen); | ||
| 610 | if (ret != 0) { | ||
| 611 | warn("usb out operation failed. (%d)", ret); | ||
| 612 | goto failed; | ||
| 613 | } | ||
| 614 | |||
| 615 | msleep(500); | ||
| 616 | req = 0xC6; | ||
| 617 | value = 0; | ||
| 618 | index = 0; | ||
| 619 | blen = 0; | ||
| 620 | |||
| 621 | ret = az6027_usb_out_op(d, req, value, index, NULL, blen); | ||
| 622 | if (ret != 0) { | ||
| 623 | warn("usb out operation failed. (%d)", ret); | ||
| 624 | goto failed; | ||
| 625 | } | ||
| 626 | |||
| 627 | for (i = 0; i < 15; i++) { | ||
| 628 | msleep(100); | ||
| 629 | |||
| 630 | if (CI_CamReady(ca, slot)) { | ||
| 631 | deb_info("CAM Ready"); | ||
| 632 | break; | ||
| 633 | } | ||
| 634 | } | ||
| 635 | msleep(5000); | ||
| 636 | |||
| 637 | failed: | ||
| 638 | mutex_unlock(&state->ca_mutex); | ||
| 639 | return ret; | ||
| 640 | } | ||
| 641 | |||
| 642 | static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) | ||
| 643 | { | ||
| 644 | return 0; | ||
| 645 | } | ||
| 646 | |||
| 647 | static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) | ||
| 648 | { | ||
| 649 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
| 650 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
| 651 | |||
| 652 | int ret; | ||
| 653 | u8 req; | ||
| 654 | u16 value; | ||
| 655 | u16 index; | ||
| 656 | int blen; | ||
| 657 | |||
| 658 | deb_info("%s", __func__); | ||
| 659 | mutex_lock(&state->ca_mutex); | ||
| 660 | req = 0xC7; | ||
| 661 | value = 1; | ||
| 662 | index = 0; | ||
| 663 | blen = 0; | ||
| 664 | |||
| 665 | ret = az6027_usb_out_op(d, req, value, index, NULL, blen); | ||
| 666 | if (ret != 0) { | ||
| 667 | warn("usb out operation failed. (%d)", ret); | ||
| 668 | goto failed; | ||
| 669 | } | ||
| 670 | |||
| 671 | failed: | ||
| 672 | mutex_unlock(&state->ca_mutex); | ||
| 673 | return ret; | ||
| 674 | } | ||
| 675 | |||
| 676 | static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) | ||
| 677 | { | ||
| 678 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
| 679 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
| 680 | int ret; | ||
| 681 | u8 req; | ||
| 682 | u16 value; | ||
| 683 | u16 index; | ||
| 684 | int blen; | ||
| 685 | u8 *b; | ||
| 686 | |||
| 687 | b = kmalloc(12, GFP_KERNEL); | ||
| 688 | if (!b) | ||
| 689 | return -ENOMEM; | ||
| 690 | mutex_lock(&state->ca_mutex); | ||
| 691 | |||
| 692 | req = 0xC5; | ||
| 693 | value = 0; | ||
| 694 | index = 0; | ||
| 695 | blen = 1; | ||
| 696 | |||
| 697 | ret = az6027_usb_in_op(d, req, value, index, b, blen); | ||
| 698 | if (ret < 0) { | ||
| 699 | warn("usb in operation failed. (%d)", ret); | ||
| 700 | ret = -EIO; | ||
| 701 | } else | ||
| 702 | ret = 0; | ||
| 703 | |||
| 704 | if (!ret && b[0] == 1) { | ||
| 705 | ret = DVB_CA_EN50221_POLL_CAM_PRESENT | | ||
| 706 | DVB_CA_EN50221_POLL_CAM_READY; | ||
| 707 | } | ||
| 708 | |||
| 709 | mutex_unlock(&state->ca_mutex); | ||
| 710 | kfree(b); | ||
| 711 | return ret; | ||
| 712 | } | ||
| 713 | |||
| 714 | |||
| 715 | static void az6027_ci_uninit(struct dvb_usb_device *d) | ||
| 716 | { | ||
| 717 | struct az6027_device_state *state; | ||
| 718 | |||
| 719 | deb_info("%s", __func__); | ||
| 720 | |||
| 721 | if (NULL == d) | ||
| 722 | return; | ||
| 723 | |||
| 724 | state = (struct az6027_device_state *)d->priv; | ||
| 725 | if (NULL == state) | ||
| 726 | return; | ||
| 727 | |||
| 728 | if (NULL == state->ca.data) | ||
| 729 | return; | ||
| 730 | |||
| 731 | dvb_ca_en50221_release(&state->ca); | ||
| 732 | |||
| 733 | memset(&state->ca, 0, sizeof(state->ca)); | ||
| 734 | } | ||
| 735 | |||
| 736 | |||
| 737 | static int az6027_ci_init(struct dvb_usb_adapter *a) | ||
| 738 | { | ||
| 739 | struct dvb_usb_device *d = a->dev; | ||
| 740 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
| 741 | int ret; | ||
| 742 | |||
| 743 | deb_info("%s", __func__); | ||
| 744 | |||
| 745 | mutex_init(&state->ca_mutex); | ||
| 746 | |||
| 747 | state->ca.owner = THIS_MODULE; | ||
| 748 | state->ca.read_attribute_mem = az6027_ci_read_attribute_mem; | ||
| 749 | state->ca.write_attribute_mem = az6027_ci_write_attribute_mem; | ||
| 750 | state->ca.read_cam_control = az6027_ci_read_cam_control; | ||
| 751 | state->ca.write_cam_control = az6027_ci_write_cam_control; | ||
| 752 | state->ca.slot_reset = az6027_ci_slot_reset; | ||
| 753 | state->ca.slot_shutdown = az6027_ci_slot_shutdown; | ||
| 754 | state->ca.slot_ts_enable = az6027_ci_slot_ts_enable; | ||
| 755 | state->ca.poll_slot_status = az6027_ci_poll_slot_status; | ||
| 756 | state->ca.data = d; | ||
| 757 | |||
| 758 | ret = dvb_ca_en50221_init(&a->dvb_adap, | ||
| 759 | &state->ca, | ||
| 760 | 0, /* flags */ | ||
| 761 | 1);/* n_slots */ | ||
| 762 | if (ret != 0) { | ||
| 763 | err("Cannot initialize CI: Error %d.", ret); | ||
| 764 | memset(&state->ca, 0, sizeof(state->ca)); | ||
| 765 | return ret; | ||
| 766 | } | ||
| 767 | |||
| 768 | deb_info("CI initialized."); | ||
| 769 | |||
| 770 | return 0; | ||
| 771 | } | ||
| 772 | |||
| 773 | /* | ||
| 774 | static int az6027_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) | ||
| 775 | { | ||
| 776 | az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6); | ||
| 777 | return 0; | ||
| 778 | } | ||
| 779 | */ | ||
| 780 | |||
| 781 | static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
| 782 | { | ||
| 783 | |||
| 784 | u8 buf; | ||
| 785 | int ret; | ||
| 786 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 787 | |||
| 788 | struct i2c_msg i2c_msg = { | ||
| 789 | .addr = 0x99, | ||
| 790 | .flags = 0, | ||
| 791 | .buf = &buf, | ||
| 792 | .len = 1 | ||
| 793 | }; | ||
| 794 | |||
| 795 | /* | ||
| 796 | * 2 --18v | ||
| 797 | * 1 --13v | ||
| 798 | * 0 --off | ||
| 799 | */ | ||
| 800 | switch (voltage) { | ||
| 801 | case SEC_VOLTAGE_13: | ||
| 802 | buf = 1; | ||
| 803 | ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); | ||
| 804 | break; | ||
| 805 | |||
| 806 | case SEC_VOLTAGE_18: | ||
| 807 | buf = 2; | ||
| 808 | ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); | ||
| 809 | break; | ||
| 810 | |||
| 811 | case SEC_VOLTAGE_OFF: | ||
| 812 | buf = 0; | ||
| 813 | ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); | ||
| 814 | break; | ||
| 815 | |||
| 816 | default: | ||
| 817 | return -EINVAL; | ||
| 818 | } | ||
| 819 | return 0; | ||
| 820 | } | ||
| 821 | |||
| 822 | |||
| 823 | static int az6027_frontend_poweron(struct dvb_usb_adapter *adap) | ||
| 824 | { | ||
| 825 | int ret; | ||
| 826 | u8 req; | ||
| 827 | u16 value; | ||
| 828 | u16 index; | ||
| 829 | int blen; | ||
| 830 | |||
| 831 | req = 0xBC; | ||
| 832 | value = 1; /* power on */ | ||
| 833 | index = 3; | ||
| 834 | blen = 0; | ||
| 835 | |||
| 836 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
| 837 | if (ret != 0) | ||
| 838 | return -EIO; | ||
| 839 | |||
| 840 | return 0; | ||
| 841 | } | ||
| 842 | static int az6027_frontend_reset(struct dvb_usb_adapter *adap) | ||
| 843 | { | ||
| 844 | int ret; | ||
| 845 | u8 req; | ||
| 846 | u16 value; | ||
| 847 | u16 index; | ||
| 848 | int blen; | ||
| 849 | |||
| 850 | /* reset demodulator */ | ||
| 851 | req = 0xC0; | ||
| 852 | value = 1; /* high */ | ||
| 853 | index = 3; | ||
| 854 | blen = 0; | ||
| 855 | |||
| 856 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
| 857 | if (ret != 0) | ||
| 858 | return -EIO; | ||
| 859 | |||
| 860 | req = 0xC0; | ||
| 861 | value = 0; /* low */ | ||
| 862 | index = 3; | ||
| 863 | blen = 0; | ||
| 864 | msleep_interruptible(200); | ||
| 865 | |||
| 866 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
| 867 | if (ret != 0) | ||
| 868 | return -EIO; | ||
| 869 | |||
| 870 | msleep_interruptible(200); | ||
| 871 | |||
| 872 | req = 0xC0; | ||
| 873 | value = 1; /*high */ | ||
| 874 | index = 3; | ||
| 875 | blen = 0; | ||
| 876 | |||
| 877 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
| 878 | if (ret != 0) | ||
| 879 | return -EIO; | ||
| 880 | |||
| 881 | msleep_interruptible(200); | ||
| 882 | return 0; | ||
| 883 | } | ||
| 884 | |||
| 885 | static int az6027_frontend_tsbypass(struct dvb_usb_adapter *adap, int onoff) | ||
| 886 | { | ||
| 887 | int ret; | ||
| 888 | u8 req; | ||
| 889 | u16 value; | ||
| 890 | u16 index; | ||
| 891 | int blen; | ||
| 892 | |||
| 893 | /* TS passthrough */ | ||
| 894 | req = 0xC7; | ||
| 895 | value = onoff; | ||
| 896 | index = 0; | ||
| 897 | blen = 0; | ||
| 898 | |||
| 899 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
| 900 | if (ret != 0) | ||
| 901 | return -EIO; | ||
| 902 | |||
| 903 | return 0; | ||
| 904 | } | ||
| 905 | |||
| 906 | static int az6027_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 907 | { | ||
| 908 | |||
| 909 | az6027_frontend_poweron(adap); | ||
| 910 | az6027_frontend_reset(adap); | ||
| 911 | |||
| 912 | deb_info("adap = %p, dev = %p\n", adap, adap->dev); | ||
| 913 | adap->fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap); | ||
| 914 | |||
| 915 | if (adap->fe) { | ||
| 916 | deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address); | ||
| 917 | if (stb6100_attach(adap->fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) { | ||
| 918 | deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address); | ||
| 919 | adap->fe->ops.set_voltage = az6027_set_voltage; | ||
| 920 | az6027_ci_init(adap); | ||
| 921 | } else { | ||
| 922 | adap->fe = NULL; | ||
| 923 | } | ||
| 924 | } else | ||
| 925 | warn("no front-end attached\n"); | ||
| 926 | |||
| 927 | az6027_frontend_tsbypass(adap, 0); | ||
| 928 | |||
| 929 | return 0; | ||
| 930 | } | ||
| 931 | |||
| 932 | static struct dvb_usb_device_properties az6027_properties; | ||
| 933 | |||
| 934 | static void az6027_usb_disconnect(struct usb_interface *intf) | ||
| 935 | { | ||
| 936 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
| 937 | az6027_ci_uninit(d); | ||
| 938 | dvb_usb_device_exit(intf); | ||
| 939 | } | ||
| 940 | |||
| 941 | |||
| 942 | static int az6027_usb_probe(struct usb_interface *intf, | ||
| 943 | const struct usb_device_id *id) | ||
| 944 | { | ||
| 945 | return dvb_usb_device_init(intf, | ||
| 946 | &az6027_properties, | ||
| 947 | THIS_MODULE, | ||
| 948 | NULL, | ||
| 949 | adapter_nr); | ||
| 950 | } | ||
| 951 | |||
| 952 | /* I2C */ | ||
| 953 | static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) | ||
| 954 | { | ||
| 955 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 956 | int i = 0, j = 0, len = 0; | ||
| 957 | int ret; | ||
| 958 | u16 index; | ||
| 959 | u16 value; | ||
| 960 | int length; | ||
| 961 | u8 req; | ||
| 962 | u8 *data; | ||
| 963 | |||
| 964 | data = kmalloc(256, GFP_KERNEL); | ||
| 965 | if (!data) | ||
| 966 | return -ENOMEM; | ||
| 967 | |||
| 968 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) { | ||
| 969 | kfree(data); | ||
| 970 | return -EAGAIN; | ||
| 971 | } | ||
| 972 | |||
| 973 | if (num > 2) | ||
| 974 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
| 975 | |||
| 976 | for (i = 0; i < num; i++) { | ||
| 977 | |||
| 978 | if (msg[i].addr == 0x99) { | ||
| 979 | req = 0xBE; | ||
| 980 | index = 0; | ||
| 981 | value = msg[i].buf[0] & 0x00ff; | ||
| 982 | length = 1; | ||
| 983 | az6027_usb_out_op(d, req, value, index, data, length); | ||
| 984 | } | ||
| 985 | |||
| 986 | if (msg[i].addr == 0xd0) { | ||
| 987 | /* write/read request */ | ||
| 988 | if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) { | ||
| 989 | req = 0xB9; | ||
| 990 | index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff)); | ||
| 991 | value = msg[i].addr + (msg[i].len << 8); | ||
| 992 | length = msg[i + 1].len + 6; | ||
| 993 | ret = az6027_usb_in_op(d, req, value, index, data, length); | ||
| 994 | len = msg[i + 1].len; | ||
| 995 | for (j = 0; j < len; j++) | ||
| 996 | msg[i + 1].buf[j] = data[j + 5]; | ||
| 997 | |||
| 998 | i++; | ||
| 999 | } else { | ||
| 1000 | |||
| 1001 | /* demod 16bit addr */ | ||
| 1002 | req = 0xBD; | ||
| 1003 | index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff)); | ||
| 1004 | value = msg[i].addr + (2 << 8); | ||
| 1005 | length = msg[i].len - 2; | ||
| 1006 | len = msg[i].len - 2; | ||
| 1007 | for (j = 0; j < len; j++) | ||
| 1008 | data[j] = msg[i].buf[j + 2]; | ||
| 1009 | az6027_usb_out_op(d, req, value, index, data, length); | ||
| 1010 | } | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | if (msg[i].addr == 0xc0) { | ||
| 1014 | if (msg[i].flags & I2C_M_RD) { | ||
| 1015 | |||
| 1016 | req = 0xB9; | ||
| 1017 | index = 0x0; | ||
| 1018 | value = msg[i].addr; | ||
| 1019 | length = msg[i].len + 6; | ||
| 1020 | ret = az6027_usb_in_op(d, req, value, index, data, length); | ||
| 1021 | len = msg[i].len; | ||
| 1022 | for (j = 0; j < len; j++) | ||
| 1023 | msg[i].buf[j] = data[j + 5]; | ||
| 1024 | |||
| 1025 | } else { | ||
| 1026 | |||
| 1027 | req = 0xBD; | ||
| 1028 | index = msg[i].buf[0] & 0x00FF; | ||
| 1029 | value = msg[i].addr + (1 << 8); | ||
| 1030 | length = msg[i].len - 1; | ||
| 1031 | len = msg[i].len - 1; | ||
| 1032 | |||
| 1033 | for (j = 0; j < len; j++) | ||
| 1034 | data[j] = msg[i].buf[j + 1]; | ||
| 1035 | |||
| 1036 | az6027_usb_out_op(d, req, value, index, data, length); | ||
| 1037 | } | ||
| 1038 | } | ||
| 1039 | } | ||
| 1040 | mutex_unlock(&d->i2c_mutex); | ||
| 1041 | kfree(data); | ||
| 1042 | |||
| 1043 | return i; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | |||
| 1047 | static u32 az6027_i2c_func(struct i2c_adapter *adapter) | ||
| 1048 | { | ||
| 1049 | return I2C_FUNC_I2C; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | static struct i2c_algorithm az6027_i2c_algo = { | ||
| 1053 | .master_xfer = az6027_i2c_xfer, | ||
| 1054 | .functionality = az6027_i2c_func, | ||
| 1055 | }; | ||
| 1056 | |||
| 1057 | int az6027_identify_state(struct usb_device *udev, | ||
| 1058 | struct dvb_usb_device_properties *props, | ||
| 1059 | struct dvb_usb_device_description **desc, | ||
| 1060 | int *cold) | ||
| 1061 | { | ||
| 1062 | u8 *b; | ||
| 1063 | s16 ret; | ||
| 1064 | |||
| 1065 | b = kmalloc(16, GFP_KERNEL); | ||
| 1066 | if (!b) | ||
| 1067 | return -ENOMEM; | ||
| 1068 | |||
| 1069 | ret = usb_control_msg(udev, | ||
| 1070 | usb_rcvctrlpipe(udev, 0), | ||
| 1071 | 0xb7, | ||
| 1072 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
| 1073 | 6, | ||
| 1074 | 0, | ||
| 1075 | b, | ||
| 1076 | 6, | ||
| 1077 | USB_CTRL_GET_TIMEOUT); | ||
| 1078 | |||
| 1079 | *cold = ret <= 0; | ||
| 1080 | kfree(b); | ||
| 1081 | deb_info("cold: %d\n", *cold); | ||
| 1082 | return 0; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | |||
| 1086 | static struct usb_device_id az6027_usb_table[] = { | ||
| 1087 | { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_AZ6027) }, | ||
| 1088 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI_V1) }, | ||
| 1089 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI_V2) }, | ||
| 1090 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V1) }, | ||
| 1091 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) }, | ||
| 1092 | { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT) }, | ||
| 1093 | { }, | ||
| 1094 | }; | ||
| 1095 | |||
| 1096 | MODULE_DEVICE_TABLE(usb, az6027_usb_table); | ||
| 1097 | |||
| 1098 | static struct dvb_usb_device_properties az6027_properties = { | ||
| 1099 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1100 | .usb_ctrl = CYPRESS_FX2, | ||
| 1101 | .firmware = "dvb-usb-az6027-03.fw", | ||
| 1102 | .no_reconnect = 1, | ||
| 1103 | |||
| 1104 | .size_of_priv = sizeof(struct az6027_device_state), | ||
| 1105 | .identify_state = az6027_identify_state, | ||
| 1106 | .num_adapters = 1, | ||
| 1107 | .adapter = { | ||
| 1108 | { | ||
| 1109 | .streaming_ctrl = az6027_streaming_ctrl, | ||
| 1110 | .frontend_attach = az6027_frontend_attach, | ||
| 1111 | |||
| 1112 | /* parameter for the MPEG2-data transfer */ | ||
| 1113 | .stream = { | ||
| 1114 | .type = USB_BULK, | ||
| 1115 | .count = 10, | ||
| 1116 | .endpoint = 0x02, | ||
| 1117 | .u = { | ||
| 1118 | .bulk = { | ||
| 1119 | .buffersize = 4096, | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 | }, | ||
| 1123 | } | ||
| 1124 | }, | ||
| 1125 | /* | ||
| 1126 | .power_ctrl = az6027_power_ctrl, | ||
| 1127 | .read_mac_address = az6027_read_mac_addr, | ||
| 1128 | */ | ||
| 1129 | .rc.legacy = { | ||
| 1130 | .rc_map_table = rc_map_az6027_table, | ||
| 1131 | .rc_map_size = ARRAY_SIZE(rc_map_az6027_table), | ||
| 1132 | .rc_interval = 400, | ||
| 1133 | .rc_query = az6027_rc_query, | ||
| 1134 | }, | ||
| 1135 | |||
| 1136 | .i2c_algo = &az6027_i2c_algo, | ||
| 1137 | |||
| 1138 | .num_device_descs = 6, | ||
| 1139 | .devices = { | ||
| 1140 | { | ||
| 1141 | .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)", | ||
| 1142 | .cold_ids = { &az6027_usb_table[0], NULL }, | ||
| 1143 | .warm_ids = { NULL }, | ||
| 1144 | }, { | ||
| 1145 | .name = "TERRATEC S7", | ||
| 1146 | .cold_ids = { &az6027_usb_table[1], NULL }, | ||
| 1147 | .warm_ids = { NULL }, | ||
| 1148 | }, { | ||
| 1149 | .name = "TERRATEC S7 MKII", | ||
| 1150 | .cold_ids = { &az6027_usb_table[2], NULL }, | ||
| 1151 | .warm_ids = { NULL }, | ||
| 1152 | }, { | ||
| 1153 | .name = "Technisat SkyStar USB 2 HD CI", | ||
| 1154 | .cold_ids = { &az6027_usb_table[3], NULL }, | ||
| 1155 | .warm_ids = { NULL }, | ||
| 1156 | }, { | ||
| 1157 | .name = "Technisat SkyStar USB 2 HD CI", | ||
| 1158 | .cold_ids = { &az6027_usb_table[4], NULL }, | ||
| 1159 | .warm_ids = { NULL }, | ||
| 1160 | }, { | ||
| 1161 | .name = "Elgato EyeTV Sat", | ||
| 1162 | .cold_ids = { &az6027_usb_table[5], NULL }, | ||
| 1163 | .warm_ids = { NULL }, | ||
| 1164 | }, | ||
| 1165 | { NULL }, | ||
| 1166 | } | ||
| 1167 | }; | ||
| 1168 | |||
| 1169 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 1170 | static struct usb_driver az6027_usb_driver = { | ||
| 1171 | .name = "dvb_usb_az6027", | ||
| 1172 | .probe = az6027_usb_probe, | ||
| 1173 | .disconnect = az6027_usb_disconnect, | ||
| 1174 | .id_table = az6027_usb_table, | ||
| 1175 | }; | ||
| 1176 | |||
| 1177 | /* module stuff */ | ||
| 1178 | static int __init az6027_usb_module_init(void) | ||
| 1179 | { | ||
| 1180 | int result; | ||
| 1181 | |||
| 1182 | result = usb_register(&az6027_usb_driver); | ||
| 1183 | if (result) { | ||
| 1184 | err("usb_register failed. (%d)", result); | ||
| 1185 | return result; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | return 0; | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | static void __exit az6027_usb_module_exit(void) | ||
| 1192 | { | ||
| 1193 | /* deregister this driver from the USB subsystem */ | ||
| 1194 | usb_deregister(&az6027_usb_driver); | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | module_init(az6027_usb_module_init); | ||
| 1198 | module_exit(az6027_usb_module_exit); | ||
| 1199 | |||
| 1200 | MODULE_AUTHOR("Adams Xu <Adams.xu@azwave.com.cn>"); | ||
| 1201 | MODULE_DESCRIPTION("Driver for AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)"); | ||
| 1202 | MODULE_VERSION("1.0"); | ||
| 1203 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/az6027.h b/drivers/media/dvb/dvb-usb/az6027.h new file mode 100644 index 00000000000..f3afe17f3f3 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/az6027.h | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #ifndef _DVB_USB_VP6027_H_ | ||
| 2 | #define _DVB_USB_VP6027_H_ | ||
| 3 | |||
| 4 | #define DVB_USB_LOG_PREFIX "az6027" | ||
| 5 | #include "dvb-usb.h" | ||
| 6 | |||
| 7 | |||
| 8 | extern int dvb_usb_az6027_debug; | ||
| 9 | #define deb_info(args...) dprintk(dvb_usb_az6027_debug, 0x01, args) | ||
| 10 | #define deb_xfer(args...) dprintk(dvb_usb_az6027_debug, 0x02, args) | ||
| 11 | #define deb_rc(args...) dprintk(dvb_usb_az6027_debug, 0x04, args) | ||
| 12 | #define deb_fe(args...) dprintk(dvb_usb_az6027_debug, 0x08, args) | ||
| 13 | |||
| 14 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/ce6230.c b/drivers/media/dvb/dvb-usb/ce6230.c new file mode 100644 index 00000000000..6d1a3041540 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ce6230.c | |||
| @@ -0,0 +1,341 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
| 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 "ce6230.h" | ||
| 23 | #include "zl10353.h" | ||
| 24 | #include "mxl5005s.h" | ||
| 25 | |||
| 26 | /* debug */ | ||
| 27 | static int dvb_usb_ce6230_debug; | ||
| 28 | module_param_named(debug, dvb_usb_ce6230_debug, int, 0644); | ||
| 29 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
| 30 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 31 | |||
| 32 | static struct zl10353_config ce6230_zl10353_config; | ||
| 33 | |||
| 34 | static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req) | ||
| 35 | { | ||
| 36 | int ret; | ||
| 37 | unsigned int pipe; | ||
| 38 | u8 request; | ||
| 39 | u8 requesttype; | ||
| 40 | u16 value; | ||
| 41 | u16 index; | ||
| 42 | u8 *buf; | ||
| 43 | |||
| 44 | request = req->cmd; | ||
| 45 | value = req->value; | ||
| 46 | index = req->index; | ||
| 47 | |||
| 48 | switch (req->cmd) { | ||
| 49 | case I2C_READ: | ||
| 50 | case DEMOD_READ: | ||
| 51 | case REG_READ: | ||
| 52 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | ||
| 53 | break; | ||
| 54 | case I2C_WRITE: | ||
| 55 | case DEMOD_WRITE: | ||
| 56 | case REG_WRITE: | ||
| 57 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | ||
| 58 | break; | ||
| 59 | default: | ||
| 60 | err("unknown command:%02x", req->cmd); | ||
| 61 | ret = -EPERM; | ||
| 62 | goto error; | ||
| 63 | } | ||
| 64 | |||
| 65 | buf = kmalloc(req->data_len, GFP_KERNEL); | ||
| 66 | if (!buf) { | ||
| 67 | ret = -ENOMEM; | ||
| 68 | goto error; | ||
| 69 | } | ||
| 70 | |||
| 71 | if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { | ||
| 72 | /* write */ | ||
| 73 | memcpy(buf, req->data, req->data_len); | ||
| 74 | pipe = usb_sndctrlpipe(udev, 0); | ||
| 75 | } else { | ||
| 76 | /* read */ | ||
| 77 | pipe = usb_rcvctrlpipe(udev, 0); | ||
| 78 | } | ||
| 79 | |||
| 80 | msleep(1); /* avoid I2C errors */ | ||
| 81 | |||
| 82 | ret = usb_control_msg(udev, pipe, request, requesttype, value, index, | ||
| 83 | buf, req->data_len, CE6230_USB_TIMEOUT); | ||
| 84 | |||
| 85 | ce6230_debug_dump(request, requesttype, value, index, buf, | ||
| 86 | req->data_len, deb_xfer); | ||
| 87 | |||
| 88 | if (ret < 0) | ||
| 89 | deb_info("%s: usb_control_msg failed:%d\n", __func__, ret); | ||
| 90 | else | ||
| 91 | ret = 0; | ||
| 92 | |||
| 93 | /* read request, copy returned data to return buf */ | ||
| 94 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) | ||
| 95 | memcpy(req->data, buf, req->data_len); | ||
| 96 | |||
| 97 | kfree(buf); | ||
| 98 | error: | ||
| 99 | return ret; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) | ||
| 103 | { | ||
| 104 | return ce6230_rw_udev(d->udev, req); | ||
| 105 | } | ||
| 106 | |||
| 107 | /* I2C */ | ||
| 108 | static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 109 | int num) | ||
| 110 | { | ||
| 111 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 112 | int i = 0; | ||
| 113 | struct req_t req; | ||
| 114 | int ret = 0; | ||
| 115 | memset(&req, 0, sizeof(req)); | ||
| 116 | |||
| 117 | if (num > 2) | ||
| 118 | return -EINVAL; | ||
| 119 | |||
| 120 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 121 | return -EAGAIN; | ||
| 122 | |||
| 123 | while (i < num) { | ||
| 124 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
| 125 | if (msg[i].addr == | ||
| 126 | ce6230_zl10353_config.demod_address) { | ||
| 127 | req.cmd = DEMOD_READ; | ||
| 128 | req.value = msg[i].addr >> 1; | ||
| 129 | req.index = msg[i].buf[0]; | ||
| 130 | req.data_len = msg[i+1].len; | ||
| 131 | req.data = &msg[i+1].buf[0]; | ||
| 132 | ret = ce6230_ctrl_msg(d, &req); | ||
| 133 | } else { | ||
| 134 | err("i2c read not implemented"); | ||
| 135 | ret = -EPERM; | ||
| 136 | } | ||
| 137 | i += 2; | ||
| 138 | } else { | ||
| 139 | if (msg[i].addr == | ||
| 140 | ce6230_zl10353_config.demod_address) { | ||
| 141 | req.cmd = DEMOD_WRITE; | ||
| 142 | req.value = msg[i].addr >> 1; | ||
| 143 | req.index = msg[i].buf[0]; | ||
| 144 | req.data_len = msg[i].len-1; | ||
| 145 | req.data = &msg[i].buf[1]; | ||
| 146 | ret = ce6230_ctrl_msg(d, &req); | ||
| 147 | } else { | ||
| 148 | req.cmd = I2C_WRITE; | ||
| 149 | req.value = 0x2000 + (msg[i].addr >> 1); | ||
| 150 | req.index = 0x0000; | ||
| 151 | req.data_len = msg[i].len; | ||
| 152 | req.data = &msg[i].buf[0]; | ||
| 153 | ret = ce6230_ctrl_msg(d, &req); | ||
| 154 | } | ||
| 155 | i += 1; | ||
| 156 | } | ||
| 157 | if (ret) | ||
| 158 | break; | ||
| 159 | } | ||
| 160 | |||
| 161 | mutex_unlock(&d->i2c_mutex); | ||
| 162 | return ret ? ret : i; | ||
| 163 | } | ||
| 164 | |||
| 165 | static u32 ce6230_i2c_func(struct i2c_adapter *adapter) | ||
| 166 | { | ||
| 167 | return I2C_FUNC_I2C; | ||
| 168 | } | ||
| 169 | |||
| 170 | static struct i2c_algorithm ce6230_i2c_algo = { | ||
| 171 | .master_xfer = ce6230_i2c_xfer, | ||
| 172 | .functionality = ce6230_i2c_func, | ||
| 173 | }; | ||
| 174 | |||
| 175 | /* Callbacks for DVB USB */ | ||
| 176 | static struct zl10353_config ce6230_zl10353_config = { | ||
| 177 | .demod_address = 0x1e, | ||
| 178 | .adc_clock = 450000, | ||
| 179 | .if2 = 45700, | ||
| 180 | .no_tuner = 1, | ||
| 181 | .parallel_ts = 1, | ||
| 182 | .clock_ctl_1 = 0x34, | ||
| 183 | .pll_0 = 0x0e, | ||
| 184 | }; | ||
| 185 | |||
| 186 | static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 187 | { | ||
| 188 | deb_info("%s:\n", __func__); | ||
| 189 | adap->fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config, | ||
| 190 | &adap->dev->i2c_adap); | ||
| 191 | if (adap->fe == NULL) | ||
| 192 | return -ENODEV; | ||
| 193 | return 0; | ||
| 194 | } | ||
| 195 | |||
| 196 | static struct mxl5005s_config ce6230_mxl5003s_config = { | ||
| 197 | .i2c_address = 0xc6, | ||
| 198 | .if_freq = IF_FREQ_4570000HZ, | ||
| 199 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
| 200 | .agc_mode = MXL_SINGLE_AGC, | ||
| 201 | .tracking_filter = MXL_TF_DEFAULT, | ||
| 202 | .rssi_enable = MXL_RSSI_ENABLE, | ||
| 203 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
| 204 | .div_out = MXL_DIV_OUT_4, | ||
| 205 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
| 206 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
| 207 | .top = MXL5005S_TOP_25P2, | ||
| 208 | .mod_mode = MXL_DIGITAL_MODE, | ||
| 209 | .if_mode = MXL_ZERO_IF, | ||
| 210 | .AgcMasterByte = 0x00, | ||
| 211 | }; | ||
| 212 | |||
| 213 | static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 214 | { | ||
| 215 | int ret; | ||
| 216 | deb_info("%s:\n", __func__); | ||
| 217 | ret = dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 218 | &ce6230_mxl5003s_config) == NULL ? -ENODEV : 0; | ||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | static int ce6230_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 223 | { | ||
| 224 | int ret; | ||
| 225 | deb_info("%s: onoff:%d\n", __func__, onoff); | ||
| 226 | |||
| 227 | /* InterfaceNumber 1 / AlternateSetting 0 idle | ||
| 228 | InterfaceNumber 1 / AlternateSetting 1 streaming */ | ||
| 229 | ret = usb_set_interface(d->udev, 1, onoff); | ||
| 230 | if (ret) | ||
| 231 | err("usb_set_interface failed with error:%d", ret); | ||
| 232 | |||
| 233 | return ret; | ||
| 234 | } | ||
| 235 | |||
| 236 | /* DVB USB Driver stuff */ | ||
| 237 | static struct dvb_usb_device_properties ce6230_properties; | ||
| 238 | |||
| 239 | static int ce6230_probe(struct usb_interface *intf, | ||
| 240 | const struct usb_device_id *id) | ||
| 241 | { | ||
| 242 | int ret = 0; | ||
| 243 | struct dvb_usb_device *d = NULL; | ||
| 244 | |||
| 245 | deb_info("%s: interface:%d\n", __func__, | ||
| 246 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
| 247 | |||
| 248 | if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { | ||
| 249 | ret = dvb_usb_device_init(intf, &ce6230_properties, THIS_MODULE, | ||
| 250 | &d, adapter_nr); | ||
| 251 | if (ret) | ||
| 252 | err("init failed with error:%d\n", ret); | ||
| 253 | } | ||
| 254 | |||
| 255 | return ret; | ||
| 256 | } | ||
| 257 | |||
| 258 | static struct usb_device_id ce6230_table[] = { | ||
| 259 | { USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) }, | ||
| 260 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310) }, | ||
| 261 | { } /* Terminating entry */ | ||
| 262 | }; | ||
| 263 | MODULE_DEVICE_TABLE(usb, ce6230_table); | ||
| 264 | |||
| 265 | static struct dvb_usb_device_properties ce6230_properties = { | ||
| 266 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 267 | |||
| 268 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 269 | .no_reconnect = 1, | ||
| 270 | |||
| 271 | .size_of_priv = 0, | ||
| 272 | |||
| 273 | .num_adapters = 1, | ||
| 274 | .adapter = { | ||
| 275 | { | ||
| 276 | .frontend_attach = ce6230_zl10353_frontend_attach, | ||
| 277 | .tuner_attach = ce6230_mxl5003s_tuner_attach, | ||
| 278 | .stream = { | ||
| 279 | .type = USB_BULK, | ||
| 280 | .count = 6, | ||
| 281 | .endpoint = 0x82, | ||
| 282 | .u = { | ||
| 283 | .bulk = { | ||
| 284 | .buffersize = (16*512), | ||
| 285 | } | ||
| 286 | } | ||
| 287 | }, | ||
| 288 | } | ||
| 289 | }, | ||
| 290 | |||
| 291 | .power_ctrl = ce6230_power_ctrl, | ||
| 292 | |||
| 293 | .i2c_algo = &ce6230_i2c_algo, | ||
| 294 | |||
| 295 | .num_device_descs = 2, | ||
| 296 | .devices = { | ||
| 297 | { | ||
| 298 | .name = "Intel CE9500 reference design", | ||
| 299 | .cold_ids = {NULL}, | ||
| 300 | .warm_ids = {&ce6230_table[0], NULL}, | ||
| 301 | }, | ||
| 302 | { | ||
| 303 | .name = "AVerMedia A310 USB 2.0 DVB-T tuner", | ||
| 304 | .cold_ids = {NULL}, | ||
| 305 | .warm_ids = {&ce6230_table[1], NULL}, | ||
| 306 | }, | ||
| 307 | } | ||
| 308 | }; | ||
| 309 | |||
| 310 | static struct usb_driver ce6230_driver = { | ||
| 311 | .name = "dvb_usb_ce6230", | ||
| 312 | .probe = ce6230_probe, | ||
| 313 | .disconnect = dvb_usb_device_exit, | ||
| 314 | .id_table = ce6230_table, | ||
| 315 | }; | ||
| 316 | |||
| 317 | /* module stuff */ | ||
| 318 | static int __init ce6230_module_init(void) | ||
| 319 | { | ||
| 320 | int ret; | ||
| 321 | deb_info("%s:\n", __func__); | ||
| 322 | ret = usb_register(&ce6230_driver); | ||
| 323 | if (ret) | ||
| 324 | err("usb_register failed with error:%d", ret); | ||
| 325 | |||
| 326 | return ret; | ||
| 327 | } | ||
| 328 | |||
| 329 | static void __exit ce6230_module_exit(void) | ||
| 330 | { | ||
| 331 | deb_info("%s:\n", __func__); | ||
| 332 | /* deregister this driver from the USB subsystem */ | ||
| 333 | usb_deregister(&ce6230_driver); | ||
| 334 | } | ||
| 335 | |||
| 336 | module_init(ce6230_module_init); | ||
| 337 | module_exit(ce6230_module_exit); | ||
| 338 | |||
| 339 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 340 | MODULE_DESCRIPTION("Driver for Intel CE6230 DVB-T USB2.0"); | ||
| 341 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/ce6230.h b/drivers/media/dvb/dvb-usb/ce6230.h new file mode 100644 index 00000000000..97c42482ccb --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ce6230.h | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
| 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 | #ifndef _DVB_USB_CE6230_H_ | ||
| 23 | #define _DVB_USB_CE6230_H_ | ||
| 24 | |||
| 25 | #define DVB_USB_LOG_PREFIX "ce6230" | ||
| 26 | #include "dvb-usb.h" | ||
| 27 | |||
| 28 | #define deb_info(args...) dprintk(dvb_usb_ce6230_debug, 0x01, args) | ||
| 29 | #define deb_rc(args...) dprintk(dvb_usb_ce6230_debug, 0x02, args) | ||
| 30 | #define deb_xfer(args...) dprintk(dvb_usb_ce6230_debug, 0x04, args) | ||
| 31 | #define deb_reg(args...) dprintk(dvb_usb_ce6230_debug, 0x08, args) | ||
| 32 | #define deb_i2c(args...) dprintk(dvb_usb_ce6230_debug, 0x10, args) | ||
| 33 | #define deb_fw(args...) dprintk(dvb_usb_ce6230_debug, 0x20, args) | ||
| 34 | |||
| 35 | #define ce6230_debug_dump(r, t, v, i, b, l, func) { \ | ||
| 36 | int loop_; \ | ||
| 37 | func("%02x %02x %02x %02x %02x %02x %02x %02x", \ | ||
| 38 | t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ | ||
| 39 | if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ | ||
| 40 | func(" >>> "); \ | ||
| 41 | else \ | ||
| 42 | func(" <<< "); \ | ||
| 43 | for (loop_ = 0; loop_ < l; loop_++) \ | ||
| 44 | func("%02x ", b[loop_]); \ | ||
| 45 | func("\n");\ | ||
| 46 | } | ||
| 47 | |||
| 48 | #define CE6230_USB_TIMEOUT 1000 | ||
| 49 | |||
| 50 | struct req_t { | ||
| 51 | u8 cmd; /* [1] */ | ||
| 52 | u16 value; /* [2|3] */ | ||
| 53 | u16 index; /* [4|5] */ | ||
| 54 | u16 data_len; /* [6|7] */ | ||
| 55 | u8 *data; | ||
| 56 | }; | ||
| 57 | |||
| 58 | enum ce6230_cmd { | ||
| 59 | CONFIG_READ = 0xd0, /* rd 0 (unclear) */ | ||
| 60 | UNKNOWN_WRITE = 0xc7, /* wr 7 (unclear) */ | ||
| 61 | I2C_READ = 0xd9, /* rd 9 (unclear) */ | ||
| 62 | I2C_WRITE = 0xca, /* wr a */ | ||
| 63 | DEMOD_READ = 0xdb, /* rd b */ | ||
| 64 | DEMOD_WRITE = 0xcc, /* wr c */ | ||
| 65 | REG_READ = 0xde, /* rd e */ | ||
| 66 | REG_WRITE = 0xcf, /* wr f */ | ||
| 67 | }; | ||
| 68 | |||
| 69 | #endif | ||
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 00000000000..16f2ce2bc15 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c | |||
| @@ -0,0 +1,269 @@ | |||
| 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 | |||
| 36 | module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644); | ||
| 37 | MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 " | ||
| 38 | "(or-able))."); | ||
| 39 | |||
| 40 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 41 | |||
| 42 | struct cinergyt2_state { | ||
| 43 | u8 rc_counter; | ||
| 44 | }; | ||
| 45 | |||
| 46 | /* We are missing a release hook with usb_device data */ | ||
| 47 | static struct dvb_usb_device *cinergyt2_usb_device; | ||
| 48 | |||
| 49 | static struct dvb_usb_device_properties cinergyt2_properties; | ||
| 50 | |||
| 51 | static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) | ||
| 52 | { | ||
| 53 | char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; | ||
| 54 | char result[64]; | ||
| 55 | return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result, | ||
| 56 | sizeof(result), 0); | ||
| 57 | } | ||
| 58 | |||
| 59 | static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable) | ||
| 60 | { | ||
| 61 | char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 }; | ||
| 62 | char state[3]; | ||
| 63 | return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0); | ||
| 64 | } | ||
| 65 | |||
| 66 | static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 67 | { | ||
| 68 | char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION }; | ||
| 69 | char state[3]; | ||
| 70 | int ret; | ||
| 71 | |||
| 72 | adap->fe = cinergyt2_fe_attach(adap->dev); | ||
| 73 | |||
| 74 | ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state, | ||
| 75 | sizeof(state), 0); | ||
| 76 | if (ret < 0) { | ||
| 77 | deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep " | ||
| 78 | "state info\n"); | ||
| 79 | } | ||
| 80 | |||
| 81 | /* Copy this pointer as we are gonna need it in the release phase */ | ||
| 82 | cinergyt2_usb_device = adap->dev; | ||
| 83 | |||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static struct rc_map_table rc_map_cinergyt2_table[] = { | ||
| 88 | { 0x0401, KEY_POWER }, | ||
| 89 | { 0x0402, KEY_1 }, | ||
| 90 | { 0x0403, KEY_2 }, | ||
| 91 | { 0x0404, KEY_3 }, | ||
| 92 | { 0x0405, KEY_4 }, | ||
| 93 | { 0x0406, KEY_5 }, | ||
| 94 | { 0x0407, KEY_6 }, | ||
| 95 | { 0x0408, KEY_7 }, | ||
| 96 | { 0x0409, KEY_8 }, | ||
| 97 | { 0x040a, KEY_9 }, | ||
| 98 | { 0x040c, KEY_0 }, | ||
| 99 | { 0x040b, KEY_VIDEO }, | ||
| 100 | { 0x040d, KEY_REFRESH }, | ||
| 101 | { 0x040e, KEY_SELECT }, | ||
| 102 | { 0x040f, KEY_EPG }, | ||
| 103 | { 0x0410, KEY_UP }, | ||
| 104 | { 0x0414, KEY_DOWN }, | ||
| 105 | { 0x0411, KEY_LEFT }, | ||
| 106 | { 0x0413, KEY_RIGHT }, | ||
| 107 | { 0x0412, KEY_OK }, | ||
| 108 | { 0x0415, KEY_TEXT }, | ||
| 109 | { 0x0416, KEY_INFO }, | ||
| 110 | { 0x0417, KEY_RED }, | ||
| 111 | { 0x0418, KEY_GREEN }, | ||
| 112 | { 0x0419, KEY_YELLOW }, | ||
| 113 | { 0x041a, KEY_BLUE }, | ||
| 114 | { 0x041c, KEY_VOLUMEUP }, | ||
| 115 | { 0x041e, KEY_VOLUMEDOWN }, | ||
| 116 | { 0x041d, KEY_MUTE }, | ||
| 117 | { 0x041b, KEY_CHANNELUP }, | ||
| 118 | { 0x041f, KEY_CHANNELDOWN }, | ||
| 119 | { 0x0440, KEY_PAUSE }, | ||
| 120 | { 0x044c, KEY_PLAY }, | ||
| 121 | { 0x0458, KEY_RECORD }, | ||
| 122 | { 0x0454, KEY_PREVIOUS }, | ||
| 123 | { 0x0448, KEY_STOP }, | ||
| 124 | { 0x045c, KEY_NEXT } | ||
| 125 | }; | ||
| 126 | |||
| 127 | /* Number of keypresses to ignore before detect repeating */ | ||
| 128 | #define RC_REPEAT_DELAY 3 | ||
| 129 | |||
| 130 | static int repeatable_keys[] = { | ||
| 131 | KEY_UP, | ||
| 132 | KEY_DOWN, | ||
| 133 | KEY_LEFT, | ||
| 134 | KEY_RIGHT, | ||
| 135 | KEY_VOLUMEUP, | ||
| 136 | KEY_VOLUMEDOWN, | ||
| 137 | KEY_CHANNELUP, | ||
| 138 | KEY_CHANNELDOWN | ||
| 139 | }; | ||
| 140 | |||
| 141 | static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 142 | { | ||
| 143 | struct cinergyt2_state *st = d->priv; | ||
| 144 | u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS; | ||
| 145 | int i; | ||
| 146 | |||
| 147 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 148 | |||
| 149 | dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0); | ||
| 150 | if (key[4] == 0xff) { | ||
| 151 | /* key repeat */ | ||
| 152 | st->rc_counter++; | ||
| 153 | if (st->rc_counter > RC_REPEAT_DELAY) { | ||
| 154 | for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) { | ||
| 155 | if (d->last_event == repeatable_keys[i]) { | ||
| 156 | *state = REMOTE_KEY_REPEAT; | ||
| 157 | *event = d->last_event; | ||
| 158 | deb_rc("repeat key, event %x\n", | ||
| 159 | *event); | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | deb_rc("repeated key (non repeatable)\n"); | ||
| 164 | } | ||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | /* hack to pass checksum on the custom field */ | ||
| 169 | key[2] = ~key[1]; | ||
| 170 | dvb_usb_nec_rc_key_to_event(d, key, event, state); | ||
| 171 | if (key[0] != 0) { | ||
| 172 | if (*event != d->last_event) | ||
| 173 | st->rc_counter = 0; | ||
| 174 | |||
| 175 | deb_rc("key: %x %x %x %x %x\n", | ||
| 176 | key[0], key[1], key[2], key[3], key[4]); | ||
| 177 | } | ||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | |||
| 181 | static int cinergyt2_usb_probe(struct usb_interface *intf, | ||
| 182 | const struct usb_device_id *id) | ||
| 183 | { | ||
| 184 | return dvb_usb_device_init(intf, &cinergyt2_properties, | ||
| 185 | THIS_MODULE, NULL, adapter_nr); | ||
| 186 | } | ||
| 187 | |||
| 188 | |||
| 189 | static struct usb_device_id cinergyt2_usb_table[] = { | ||
| 190 | { USB_DEVICE(USB_VID_TERRATEC, 0x0038) }, | ||
| 191 | { 0 } | ||
| 192 | }; | ||
| 193 | |||
| 194 | MODULE_DEVICE_TABLE(usb, cinergyt2_usb_table); | ||
| 195 | |||
| 196 | static struct dvb_usb_device_properties cinergyt2_properties = { | ||
| 197 | .size_of_priv = sizeof(struct cinergyt2_state), | ||
| 198 | .num_adapters = 1, | ||
| 199 | .adapter = { | ||
| 200 | { | ||
| 201 | .streaming_ctrl = cinergyt2_streaming_ctrl, | ||
| 202 | .frontend_attach = cinergyt2_frontend_attach, | ||
| 203 | |||
| 204 | /* parameter for the MPEG2-data transfer */ | ||
| 205 | .stream = { | ||
| 206 | .type = USB_BULK, | ||
| 207 | .count = 5, | ||
| 208 | .endpoint = 0x02, | ||
| 209 | .u = { | ||
| 210 | .bulk = { | ||
| 211 | .buffersize = 512, | ||
| 212 | } | ||
| 213 | } | ||
| 214 | }, | ||
| 215 | } | ||
| 216 | }, | ||
| 217 | |||
| 218 | .power_ctrl = cinergyt2_power_ctrl, | ||
| 219 | |||
| 220 | .rc.legacy = { | ||
| 221 | .rc_interval = 50, | ||
| 222 | .rc_map_table = rc_map_cinergyt2_table, | ||
| 223 | .rc_map_size = ARRAY_SIZE(rc_map_cinergyt2_table), | ||
| 224 | .rc_query = cinergyt2_rc_query, | ||
| 225 | }, | ||
| 226 | |||
| 227 | .generic_bulk_ctrl_endpoint = 1, | ||
| 228 | |||
| 229 | .num_device_descs = 1, | ||
| 230 | .devices = { | ||
| 231 | { .name = "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver", | ||
| 232 | .cold_ids = {NULL}, | ||
| 233 | .warm_ids = { &cinergyt2_usb_table[0], NULL }, | ||
| 234 | }, | ||
| 235 | { NULL }, | ||
| 236 | } | ||
| 237 | }; | ||
| 238 | |||
| 239 | |||
| 240 | static struct usb_driver cinergyt2_driver = { | ||
| 241 | .name = "cinergyT2", | ||
| 242 | .probe = cinergyt2_usb_probe, | ||
| 243 | .disconnect = dvb_usb_device_exit, | ||
| 244 | .id_table = cinergyt2_usb_table | ||
| 245 | }; | ||
| 246 | |||
| 247 | static int __init cinergyt2_usb_init(void) | ||
| 248 | { | ||
| 249 | int err; | ||
| 250 | |||
| 251 | err = usb_register(&cinergyt2_driver); | ||
| 252 | if (err) { | ||
| 253 | err("usb_register() failed! (err %i)\n", err); | ||
| 254 | return err; | ||
| 255 | } | ||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | static void __exit cinergyt2_usb_exit(void) | ||
| 260 | { | ||
| 261 | usb_deregister(&cinergyt2_driver); | ||
| 262 | } | ||
| 263 | |||
| 264 | module_init(cinergyt2_usb_init); | ||
| 265 | module_exit(cinergyt2_usb_exit); | ||
| 266 | |||
| 267 | MODULE_DESCRIPTION("Terratec Cinergy T2 DVB-T driver"); | ||
| 268 | MODULE_LICENSE("GPL"); | ||
| 269 | 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 00000000000..9cd51ac1207 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c | |||
| @@ -0,0 +1,352 @@ | |||
| 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 | param.flags = 0; | ||
| 279 | |||
| 280 | err = dvb_usb_generic_rw(state->d, | ||
| 281 | (char *)¶m, sizeof(param), | ||
| 282 | result, sizeof(result), 0); | ||
| 283 | if (err < 0) | ||
| 284 | err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); | ||
| 285 | |||
| 286 | return (err < 0) ? err : 0; | ||
| 287 | } | ||
| 288 | |||
| 289 | static int cinergyt2_fe_get_frontend(struct dvb_frontend *fe, | ||
| 290 | struct dvb_frontend_parameters *fep) | ||
| 291 | { | ||
| 292 | return 0; | ||
| 293 | } | ||
| 294 | |||
| 295 | static void cinergyt2_fe_release(struct dvb_frontend *fe) | ||
| 296 | { | ||
| 297 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
| 298 | if (state != NULL) | ||
| 299 | kfree(state); | ||
| 300 | } | ||
| 301 | |||
| 302 | static struct dvb_frontend_ops cinergyt2_fe_ops; | ||
| 303 | |||
| 304 | struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d) | ||
| 305 | { | ||
| 306 | struct cinergyt2_fe_state *s = kzalloc(sizeof( | ||
| 307 | struct cinergyt2_fe_state), GFP_KERNEL); | ||
| 308 | if (s == NULL) | ||
| 309 | return NULL; | ||
| 310 | |||
| 311 | s->d = d; | ||
| 312 | memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops)); | ||
| 313 | s->fe.demodulator_priv = s; | ||
| 314 | return &s->fe; | ||
| 315 | } | ||
| 316 | |||
| 317 | |||
| 318 | static struct dvb_frontend_ops cinergyt2_fe_ops = { | ||
| 319 | .info = { | ||
| 320 | .name = DRIVER_NAME, | ||
| 321 | .type = FE_OFDM, | ||
| 322 | .frequency_min = 174000000, | ||
| 323 | .frequency_max = 862000000, | ||
| 324 | .frequency_stepsize = 166667, | ||
| 325 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | ||
| 326 | | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ||
| 327 | | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | ||
| 328 | | FE_CAN_FEC_AUTO | FE_CAN_QPSK | ||
| 329 | | FE_CAN_QAM_16 | FE_CAN_QAM_64 | ||
| 330 | | FE_CAN_QAM_AUTO | ||
| 331 | | FE_CAN_TRANSMISSION_MODE_AUTO | ||
| 332 | | FE_CAN_GUARD_INTERVAL_AUTO | ||
| 333 | | FE_CAN_HIERARCHY_AUTO | ||
| 334 | | FE_CAN_RECOVER | ||
| 335 | | FE_CAN_MUTE_TS | ||
| 336 | }, | ||
| 337 | |||
| 338 | .release = cinergyt2_fe_release, | ||
| 339 | |||
| 340 | .init = cinergyt2_fe_init, | ||
| 341 | .sleep = cinergyt2_fe_sleep, | ||
| 342 | |||
| 343 | .set_frontend = cinergyt2_fe_set_frontend, | ||
| 344 | .get_frontend = cinergyt2_fe_get_frontend, | ||
| 345 | .get_tune_settings = cinergyt2_fe_get_tune_settings, | ||
| 346 | |||
| 347 | .read_status = cinergyt2_fe_read_status, | ||
| 348 | .read_ber = cinergyt2_fe_read_ber, | ||
| 349 | .read_signal_strength = cinergyt2_fe_read_signal_strength, | ||
| 350 | .read_snr = cinergyt2_fe_read_snr, | ||
| 351 | .read_ucblocks = cinergyt2_fe_read_unc_blocks, | ||
| 352 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2.h b/drivers/media/dvb/dvb-usb/cinergyT2.h new file mode 100644 index 00000000000..84efe03771e --- /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 | __le16 gain; | ||
| 74 | uint8_t snr; | ||
| 75 | __le32 viterbi_error_rate; | ||
| 76 | uint32_t rs_error_rate; | ||
| 77 | __le32 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 | __le32 freq; | ||
| 86 | uint8_t bandwidth; | ||
| 87 | __le16 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 new file mode 100644 index 00000000000..acb5fb2d2e7 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cxusb.c | |||
| @@ -0,0 +1,2017 @@ | |||
| 1 | /* DVB USB compliant linux driver for Conexant USB reference design. | ||
| 2 | * | ||
| 3 | * The Conexant reference design I saw on their website was only for analogue | ||
| 4 | * capturing (using the cx25842). The box I took to write this driver (reverse | ||
| 5 | * engineered) is the one labeled Medion MD95700. In addition to the cx25842 | ||
| 6 | * for analogue capturing it also has a cx22702 DVB-T demodulator on the main | ||
| 7 | * board. Besides it has a atiremote (X10) and a USB2.0 hub onboard. | ||
| 8 | * | ||
| 9 | * Maybe it is a little bit premature to call this driver cxusb, but I assume | ||
| 10 | * the USB protocol is identical or at least inherited from the reference | ||
| 11 | * design, so it can be reused for the "analogue-only" device (if it will | ||
| 12 | * appear at all). | ||
| 13 | * | ||
| 14 | * TODO: Use the cx25840-driver for the analogue part | ||
| 15 | * | ||
| 16 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 17 | * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) | ||
| 18 | * Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au) | ||
| 19 | * | ||
| 20 | * This program is free software; you can redistribute it and/or modify it | ||
| 21 | * under the terms of the GNU General Public License as published by the Free | ||
| 22 | * Software Foundation, version 2. | ||
| 23 | * | ||
| 24 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 25 | */ | ||
| 26 | #include <media/tuner.h> | ||
| 27 | #include <linux/vmalloc.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | |||
| 30 | #include "cxusb.h" | ||
| 31 | |||
| 32 | #include "cx22702.h" | ||
| 33 | #include "lgdt330x.h" | ||
| 34 | #include "mt352.h" | ||
| 35 | #include "mt352_priv.h" | ||
| 36 | #include "zl10353.h" | ||
| 37 | #include "tuner-xc2028.h" | ||
| 38 | #include "tuner-simple.h" | ||
| 39 | #include "mxl5005s.h" | ||
| 40 | #include "max2165.h" | ||
| 41 | #include "dib7000p.h" | ||
| 42 | #include "dib0070.h" | ||
| 43 | #include "lgs8gxx.h" | ||
| 44 | #include "atbm8830.h" | ||
| 45 | |||
| 46 | /* debug */ | ||
| 47 | static int dvb_usb_cxusb_debug; | ||
| 48 | module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); | ||
| 49 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 50 | |||
| 51 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 52 | |||
| 53 | #define deb_info(args...) dprintk(dvb_usb_cxusb_debug, 0x03, args) | ||
| 54 | #define deb_i2c(args...) dprintk(dvb_usb_cxusb_debug, 0x02, args) | ||
| 55 | |||
| 56 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, | ||
| 57 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
| 58 | { | ||
| 59 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
| 60 | u8 sndbuf[1+wlen]; | ||
| 61 | memset(sndbuf, 0, 1+wlen); | ||
| 62 | |||
| 63 | sndbuf[0] = cmd; | ||
| 64 | memcpy(&sndbuf[1], wbuf, wlen); | ||
| 65 | if (wo) | ||
| 66 | return dvb_usb_generic_write(d, sndbuf, 1+wlen); | ||
| 67 | else | ||
| 68 | return dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0); | ||
| 69 | } | ||
| 70 | |||
| 71 | /* GPIO */ | ||
| 72 | static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff) | ||
| 73 | { | ||
| 74 | struct cxusb_state *st = d->priv; | ||
| 75 | u8 o[2], i; | ||
| 76 | |||
| 77 | if (st->gpio_write_state[GPIO_TUNER] == onoff) | ||
| 78 | return; | ||
| 79 | |||
| 80 | o[0] = GPIO_TUNER; | ||
| 81 | o[1] = onoff; | ||
| 82 | cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); | ||
| 83 | |||
| 84 | if (i != 0x01) | ||
| 85 | deb_info("gpio_write failed.\n"); | ||
| 86 | |||
| 87 | st->gpio_write_state[GPIO_TUNER] = onoff; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int cxusb_bluebird_gpio_rw(struct dvb_usb_device *d, u8 changemask, | ||
| 91 | u8 newval) | ||
| 92 | { | ||
| 93 | u8 o[2], gpio_state; | ||
| 94 | int rc; | ||
| 95 | |||
| 96 | o[0] = 0xff & ~changemask; /* mask of bits to keep */ | ||
| 97 | o[1] = newval & changemask; /* new values for bits */ | ||
| 98 | |||
| 99 | rc = cxusb_ctrl_msg(d, CMD_BLUEBIRD_GPIO_RW, o, 2, &gpio_state, 1); | ||
| 100 | if (rc < 0 || (gpio_state & changemask) != (newval & changemask)) | ||
| 101 | deb_info("bluebird_gpio_write failed.\n"); | ||
| 102 | |||
| 103 | return rc < 0 ? rc : gpio_state; | ||
| 104 | } | ||
| 105 | |||
| 106 | static void cxusb_bluebird_gpio_pulse(struct dvb_usb_device *d, u8 pin, int low) | ||
| 107 | { | ||
| 108 | cxusb_bluebird_gpio_rw(d, pin, low ? 0 : pin); | ||
| 109 | msleep(5); | ||
| 110 | cxusb_bluebird_gpio_rw(d, pin, low ? pin : 0); | ||
| 111 | } | ||
| 112 | |||
| 113 | static void cxusb_nano2_led(struct dvb_usb_device *d, int onoff) | ||
| 114 | { | ||
| 115 | cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40); | ||
| 116 | } | ||
| 117 | |||
| 118 | static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d, | ||
| 119 | u8 addr, int onoff) | ||
| 120 | { | ||
| 121 | u8 o[2] = {addr, onoff}; | ||
| 122 | u8 i; | ||
| 123 | int rc; | ||
| 124 | |||
| 125 | rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); | ||
| 126 | |||
| 127 | if (rc < 0) | ||
| 128 | return rc; | ||
| 129 | if (i == 0x01) | ||
| 130 | return 0; | ||
| 131 | else { | ||
| 132 | deb_info("gpio_write failed.\n"); | ||
| 133 | return -EIO; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | /* I2C */ | ||
| 138 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 139 | int num) | ||
| 140 | { | ||
| 141 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 142 | int i; | ||
| 143 | |||
| 144 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 145 | return -EAGAIN; | ||
| 146 | |||
| 147 | for (i = 0; i < num; i++) { | ||
| 148 | |||
| 149 | if (d->udev->descriptor.idVendor == USB_VID_MEDION) | ||
| 150 | switch (msg[i].addr) { | ||
| 151 | case 0x63: | ||
| 152 | cxusb_gpio_tuner(d, 0); | ||
| 153 | break; | ||
| 154 | default: | ||
| 155 | cxusb_gpio_tuner(d, 1); | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | |||
| 159 | if (msg[i].flags & I2C_M_RD) { | ||
| 160 | /* read only */ | ||
| 161 | u8 obuf[3], ibuf[1+msg[i].len]; | ||
| 162 | obuf[0] = 0; | ||
| 163 | obuf[1] = msg[i].len; | ||
| 164 | obuf[2] = msg[i].addr; | ||
| 165 | if (cxusb_ctrl_msg(d, CMD_I2C_READ, | ||
| 166 | obuf, 3, | ||
| 167 | ibuf, 1+msg[i].len) < 0) { | ||
| 168 | warn("i2c read failed"); | ||
| 169 | break; | ||
| 170 | } | ||
| 171 | memcpy(msg[i].buf, &ibuf[1], msg[i].len); | ||
| 172 | } else if (i+1 < num && (msg[i+1].flags & I2C_M_RD) && | ||
| 173 | msg[i].addr == msg[i+1].addr) { | ||
| 174 | /* write to then read from same address */ | ||
| 175 | u8 obuf[3+msg[i].len], ibuf[1+msg[i+1].len]; | ||
| 176 | obuf[0] = msg[i].len; | ||
| 177 | obuf[1] = msg[i+1].len; | ||
| 178 | obuf[2] = msg[i].addr; | ||
| 179 | memcpy(&obuf[3], msg[i].buf, msg[i].len); | ||
| 180 | |||
| 181 | if (cxusb_ctrl_msg(d, CMD_I2C_READ, | ||
| 182 | obuf, 3+msg[i].len, | ||
| 183 | ibuf, 1+msg[i+1].len) < 0) | ||
| 184 | break; | ||
| 185 | |||
| 186 | if (ibuf[0] != 0x08) | ||
| 187 | deb_i2c("i2c read may have failed\n"); | ||
| 188 | |||
| 189 | memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len); | ||
| 190 | |||
| 191 | i++; | ||
| 192 | } else { | ||
| 193 | /* write only */ | ||
| 194 | u8 obuf[2+msg[i].len], ibuf; | ||
| 195 | obuf[0] = msg[i].addr; | ||
| 196 | obuf[1] = msg[i].len; | ||
| 197 | memcpy(&obuf[2], msg[i].buf, msg[i].len); | ||
| 198 | |||
| 199 | if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf, | ||
| 200 | 2+msg[i].len, &ibuf,1) < 0) | ||
| 201 | break; | ||
| 202 | if (ibuf != 0x08) | ||
| 203 | deb_i2c("i2c write may have failed\n"); | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | mutex_unlock(&d->i2c_mutex); | ||
| 208 | return i == num ? num : -EREMOTEIO; | ||
| 209 | } | ||
| 210 | |||
| 211 | static u32 cxusb_i2c_func(struct i2c_adapter *adapter) | ||
| 212 | { | ||
| 213 | return I2C_FUNC_I2C; | ||
| 214 | } | ||
| 215 | |||
| 216 | static struct i2c_algorithm cxusb_i2c_algo = { | ||
| 217 | .master_xfer = cxusb_i2c_xfer, | ||
| 218 | .functionality = cxusb_i2c_func, | ||
| 219 | }; | ||
| 220 | |||
| 221 | static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 222 | { | ||
| 223 | u8 b = 0; | ||
| 224 | if (onoff) | ||
| 225 | return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0); | ||
| 226 | else | ||
| 227 | return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0); | ||
| 228 | } | ||
| 229 | |||
| 230 | static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 231 | { | ||
| 232 | int ret; | ||
| 233 | if (!onoff) | ||
| 234 | return cxusb_ctrl_msg(d, CMD_POWER_OFF, NULL, 0, NULL, 0); | ||
| 235 | if (d->state == DVB_USB_STATE_INIT && | ||
| 236 | usb_set_interface(d->udev, 0, 0) < 0) | ||
| 237 | err("set interface failed"); | ||
| 238 | do {} while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) && | ||
| 239 | !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) && | ||
| 240 | !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0); | ||
| 241 | if (!ret) { | ||
| 242 | /* FIXME: We don't know why, but we need to configure the | ||
| 243 | * lgdt3303 with the register settings below on resume */ | ||
| 244 | int i; | ||
| 245 | u8 buf, bufs[] = { | ||
| 246 | 0x0e, 0x2, 0x00, 0x7f, | ||
| 247 | 0x0e, 0x2, 0x02, 0xfe, | ||
| 248 | 0x0e, 0x2, 0x02, 0x01, | ||
| 249 | 0x0e, 0x2, 0x00, 0x03, | ||
| 250 | 0x0e, 0x2, 0x0d, 0x40, | ||
| 251 | 0x0e, 0x2, 0x0e, 0x87, | ||
| 252 | 0x0e, 0x2, 0x0f, 0x8e, | ||
| 253 | 0x0e, 0x2, 0x10, 0x01, | ||
| 254 | 0x0e, 0x2, 0x14, 0xd7, | ||
| 255 | 0x0e, 0x2, 0x47, 0x88, | ||
| 256 | }; | ||
| 257 | msleep(20); | ||
| 258 | for (i = 0; i < sizeof(bufs)/sizeof(u8); i += 4/sizeof(u8)) { | ||
| 259 | ret = cxusb_ctrl_msg(d, CMD_I2C_WRITE, | ||
| 260 | bufs+i, 4, &buf, 1); | ||
| 261 | if (ret) | ||
| 262 | break; | ||
| 263 | if (buf != 0x8) | ||
| 264 | return -EREMOTEIO; | ||
| 265 | } | ||
| 266 | } | ||
| 267 | return ret; | ||
| 268 | } | ||
| 269 | |||
| 270 | static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 271 | { | ||
| 272 | u8 b = 0; | ||
| 273 | if (onoff) | ||
| 274 | return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0); | ||
| 275 | else | ||
| 276 | return 0; | ||
| 277 | } | ||
| 278 | |||
| 279 | static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 280 | { | ||
| 281 | int rc = 0; | ||
| 282 | |||
| 283 | rc = cxusb_power_ctrl(d, onoff); | ||
| 284 | if (!onoff) | ||
| 285 | cxusb_nano2_led(d, 0); | ||
| 286 | |||
| 287 | return rc; | ||
| 288 | } | ||
| 289 | |||
| 290 | static int cxusb_d680_dmb_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 291 | { | ||
| 292 | int ret; | ||
| 293 | u8 b; | ||
| 294 | ret = cxusb_power_ctrl(d, onoff); | ||
| 295 | if (!onoff) | ||
| 296 | return ret; | ||
| 297 | |||
| 298 | msleep(128); | ||
| 299 | cxusb_ctrl_msg(d, CMD_DIGITAL, NULL, 0, &b, 1); | ||
| 300 | msleep(100); | ||
| 301 | return ret; | ||
| 302 | } | ||
| 303 | |||
| 304 | static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 305 | { | ||
| 306 | u8 buf[2] = { 0x03, 0x00 }; | ||
| 307 | if (onoff) | ||
| 308 | cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON, buf, 2, NULL, 0); | ||
| 309 | else | ||
| 310 | cxusb_ctrl_msg(adap->dev, CMD_STREAMING_OFF, NULL, 0, NULL, 0); | ||
| 311 | |||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 316 | { | ||
| 317 | if (onoff) | ||
| 318 | cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_ON, NULL, 0, NULL, 0); | ||
| 319 | else | ||
| 320 | cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_OFF, | ||
| 321 | NULL, 0, NULL, 0); | ||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d) | ||
| 326 | { | ||
| 327 | int ep = d->props.generic_bulk_ctrl_endpoint; | ||
| 328 | const int timeout = 100; | ||
| 329 | const int junk_len = 32; | ||
| 330 | u8 *junk; | ||
| 331 | int rd_count; | ||
| 332 | |||
| 333 | /* Discard remaining data in video pipe */ | ||
| 334 | junk = kmalloc(junk_len, GFP_KERNEL); | ||
| 335 | if (!junk) | ||
| 336 | return; | ||
| 337 | while (1) { | ||
| 338 | if (usb_bulk_msg(d->udev, | ||
| 339 | usb_rcvbulkpipe(d->udev, ep), | ||
| 340 | junk, junk_len, &rd_count, timeout) < 0) | ||
| 341 | break; | ||
| 342 | if (!rd_count) | ||
| 343 | break; | ||
| 344 | } | ||
| 345 | kfree(junk); | ||
| 346 | } | ||
| 347 | |||
| 348 | static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d) | ||
| 349 | { | ||
| 350 | struct usb_data_stream_properties *p = &d->props.adapter[0].stream; | ||
| 351 | const int timeout = 100; | ||
| 352 | const int junk_len = p->u.bulk.buffersize; | ||
| 353 | u8 *junk; | ||
| 354 | int rd_count; | ||
| 355 | |||
| 356 | /* Discard remaining data in video pipe */ | ||
| 357 | junk = kmalloc(junk_len, GFP_KERNEL); | ||
| 358 | if (!junk) | ||
| 359 | return; | ||
| 360 | while (1) { | ||
| 361 | if (usb_bulk_msg(d->udev, | ||
| 362 | usb_rcvbulkpipe(d->udev, p->endpoint), | ||
| 363 | junk, junk_len, &rd_count, timeout) < 0) | ||
| 364 | break; | ||
| 365 | if (!rd_count) | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | kfree(junk); | ||
| 369 | } | ||
| 370 | |||
| 371 | static int cxusb_d680_dmb_streaming_ctrl( | ||
| 372 | struct dvb_usb_adapter *adap, int onoff) | ||
| 373 | { | ||
| 374 | if (onoff) { | ||
| 375 | u8 buf[2] = { 0x03, 0x00 }; | ||
| 376 | cxusb_d680_dmb_drain_video(adap->dev); | ||
| 377 | return cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON, | ||
| 378 | buf, sizeof(buf), NULL, 0); | ||
| 379 | } else { | ||
| 380 | int ret = cxusb_ctrl_msg(adap->dev, | ||
| 381 | CMD_STREAMING_OFF, NULL, 0, NULL, 0); | ||
| 382 | return ret; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 387 | { | ||
| 388 | struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; | ||
| 389 | u8 ircode[4]; | ||
| 390 | int i; | ||
| 391 | |||
| 392 | cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4); | ||
| 393 | |||
| 394 | *event = 0; | ||
| 395 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 396 | |||
| 397 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { | ||
| 398 | if (rc5_custom(&keymap[i]) == ircode[2] && | ||
| 399 | rc5_data(&keymap[i]) == ircode[3]) { | ||
| 400 | *event = keymap[i].keycode; | ||
| 401 | *state = REMOTE_KEY_PRESSED; | ||
| 402 | |||
| 403 | return 0; | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 407 | return 0; | ||
| 408 | } | ||
| 409 | |||
| 410 | static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event, | ||
| 411 | int *state) | ||
| 412 | { | ||
| 413 | struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; | ||
| 414 | u8 ircode[4]; | ||
| 415 | int i; | ||
| 416 | struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD, | ||
| 417 | .buf = ircode, .len = 4 }; | ||
| 418 | |||
| 419 | *event = 0; | ||
| 420 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 421 | |||
| 422 | if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1) | ||
| 423 | return 0; | ||
| 424 | |||
| 425 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { | ||
| 426 | if (rc5_custom(&keymap[i]) == ircode[1] && | ||
| 427 | rc5_data(&keymap[i]) == ircode[2]) { | ||
| 428 | *event = keymap[i].keycode; | ||
| 429 | *state = REMOTE_KEY_PRESSED; | ||
| 430 | |||
| 431 | return 0; | ||
| 432 | } | ||
| 433 | } | ||
| 434 | |||
| 435 | return 0; | ||
| 436 | } | ||
| 437 | |||
| 438 | static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, | ||
| 439 | int *state) | ||
| 440 | { | ||
| 441 | struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; | ||
| 442 | u8 ircode[2]; | ||
| 443 | int i; | ||
| 444 | |||
| 445 | *event = 0; | ||
| 446 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 447 | |||
| 448 | if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0) | ||
| 449 | return 0; | ||
| 450 | |||
| 451 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { | ||
| 452 | if (rc5_custom(&keymap[i]) == ircode[0] && | ||
| 453 | rc5_data(&keymap[i]) == ircode[1]) { | ||
| 454 | *event = keymap[i].keycode; | ||
| 455 | *state = REMOTE_KEY_PRESSED; | ||
| 456 | |||
| 457 | return 0; | ||
| 458 | } | ||
| 459 | } | ||
| 460 | |||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | |||
| 464 | static struct rc_map_table rc_map_dvico_mce_table[] = { | ||
| 465 | { 0xfe02, KEY_TV }, | ||
| 466 | { 0xfe0e, KEY_MP3 }, | ||
| 467 | { 0xfe1a, KEY_DVD }, | ||
| 468 | { 0xfe1e, KEY_FAVORITES }, | ||
| 469 | { 0xfe16, KEY_SETUP }, | ||
| 470 | { 0xfe46, KEY_POWER2 }, | ||
| 471 | { 0xfe0a, KEY_EPG }, | ||
| 472 | { 0xfe49, KEY_BACK }, | ||
| 473 | { 0xfe4d, KEY_MENU }, | ||
| 474 | { 0xfe51, KEY_UP }, | ||
| 475 | { 0xfe5b, KEY_LEFT }, | ||
| 476 | { 0xfe5f, KEY_RIGHT }, | ||
| 477 | { 0xfe53, KEY_DOWN }, | ||
| 478 | { 0xfe5e, KEY_OK }, | ||
| 479 | { 0xfe59, KEY_INFO }, | ||
| 480 | { 0xfe55, KEY_TAB }, | ||
| 481 | { 0xfe0f, KEY_PREVIOUSSONG },/* Replay */ | ||
| 482 | { 0xfe12, KEY_NEXTSONG }, /* Skip */ | ||
| 483 | { 0xfe42, KEY_ENTER }, /* Windows/Start */ | ||
| 484 | { 0xfe15, KEY_VOLUMEUP }, | ||
| 485 | { 0xfe05, KEY_VOLUMEDOWN }, | ||
| 486 | { 0xfe11, KEY_CHANNELUP }, | ||
| 487 | { 0xfe09, KEY_CHANNELDOWN }, | ||
| 488 | { 0xfe52, KEY_CAMERA }, | ||
| 489 | { 0xfe5a, KEY_TUNER }, /* Live */ | ||
| 490 | { 0xfe19, KEY_OPEN }, | ||
| 491 | { 0xfe0b, KEY_1 }, | ||
| 492 | { 0xfe17, KEY_2 }, | ||
| 493 | { 0xfe1b, KEY_3 }, | ||
| 494 | { 0xfe07, KEY_4 }, | ||
| 495 | { 0xfe50, KEY_5 }, | ||
| 496 | { 0xfe54, KEY_6 }, | ||
| 497 | { 0xfe48, KEY_7 }, | ||
| 498 | { 0xfe4c, KEY_8 }, | ||
| 499 | { 0xfe58, KEY_9 }, | ||
| 500 | { 0xfe13, KEY_ANGLE }, /* Aspect */ | ||
| 501 | { 0xfe03, KEY_0 }, | ||
| 502 | { 0xfe1f, KEY_ZOOM }, | ||
| 503 | { 0xfe43, KEY_REWIND }, | ||
| 504 | { 0xfe47, KEY_PLAYPAUSE }, | ||
| 505 | { 0xfe4f, KEY_FASTFORWARD }, | ||
| 506 | { 0xfe57, KEY_MUTE }, | ||
| 507 | { 0xfe0d, KEY_STOP }, | ||
| 508 | { 0xfe01, KEY_RECORD }, | ||
| 509 | { 0xfe4e, KEY_POWER }, | ||
| 510 | }; | ||
| 511 | |||
| 512 | static struct rc_map_table rc_map_dvico_portable_table[] = { | ||
| 513 | { 0xfc02, KEY_SETUP }, /* Profile */ | ||
| 514 | { 0xfc43, KEY_POWER2 }, | ||
| 515 | { 0xfc06, KEY_EPG }, | ||
| 516 | { 0xfc5a, KEY_BACK }, | ||
| 517 | { 0xfc05, KEY_MENU }, | ||
| 518 | { 0xfc47, KEY_INFO }, | ||
| 519 | { 0xfc01, KEY_TAB }, | ||
| 520 | { 0xfc42, KEY_PREVIOUSSONG },/* Replay */ | ||
| 521 | { 0xfc49, KEY_VOLUMEUP }, | ||
| 522 | { 0xfc09, KEY_VOLUMEDOWN }, | ||
| 523 | { 0xfc54, KEY_CHANNELUP }, | ||
| 524 | { 0xfc0b, KEY_CHANNELDOWN }, | ||
| 525 | { 0xfc16, KEY_CAMERA }, | ||
| 526 | { 0xfc40, KEY_TUNER }, /* ATV/DTV */ | ||
| 527 | { 0xfc45, KEY_OPEN }, | ||
| 528 | { 0xfc19, KEY_1 }, | ||
| 529 | { 0xfc18, KEY_2 }, | ||
| 530 | { 0xfc1b, KEY_3 }, | ||
| 531 | { 0xfc1a, KEY_4 }, | ||
| 532 | { 0xfc58, KEY_5 }, | ||
| 533 | { 0xfc59, KEY_6 }, | ||
| 534 | { 0xfc15, KEY_7 }, | ||
| 535 | { 0xfc14, KEY_8 }, | ||
| 536 | { 0xfc17, KEY_9 }, | ||
| 537 | { 0xfc44, KEY_ANGLE }, /* Aspect */ | ||
| 538 | { 0xfc55, KEY_0 }, | ||
| 539 | { 0xfc07, KEY_ZOOM }, | ||
| 540 | { 0xfc0a, KEY_REWIND }, | ||
| 541 | { 0xfc08, KEY_PLAYPAUSE }, | ||
| 542 | { 0xfc4b, KEY_FASTFORWARD }, | ||
| 543 | { 0xfc5b, KEY_MUTE }, | ||
| 544 | { 0xfc04, KEY_STOP }, | ||
| 545 | { 0xfc56, KEY_RECORD }, | ||
| 546 | { 0xfc57, KEY_POWER }, | ||
| 547 | { 0xfc41, KEY_UNKNOWN }, /* INPUT */ | ||
| 548 | { 0xfc00, KEY_UNKNOWN }, /* HD */ | ||
| 549 | }; | ||
| 550 | |||
| 551 | static struct rc_map_table rc_map_d680_dmb_table[] = { | ||
| 552 | { 0x0038, KEY_UNKNOWN }, /* TV/AV */ | ||
| 553 | { 0x080c, KEY_ZOOM }, | ||
| 554 | { 0x0800, KEY_0 }, | ||
| 555 | { 0x0001, KEY_1 }, | ||
| 556 | { 0x0802, KEY_2 }, | ||
| 557 | { 0x0003, KEY_3 }, | ||
| 558 | { 0x0804, KEY_4 }, | ||
| 559 | { 0x0005, KEY_5 }, | ||
| 560 | { 0x0806, KEY_6 }, | ||
| 561 | { 0x0007, KEY_7 }, | ||
| 562 | { 0x0808, KEY_8 }, | ||
| 563 | { 0x0009, KEY_9 }, | ||
| 564 | { 0x000a, KEY_MUTE }, | ||
| 565 | { 0x0829, KEY_BACK }, | ||
| 566 | { 0x0012, KEY_CHANNELUP }, | ||
| 567 | { 0x0813, KEY_CHANNELDOWN }, | ||
| 568 | { 0x002b, KEY_VOLUMEUP }, | ||
| 569 | { 0x082c, KEY_VOLUMEDOWN }, | ||
| 570 | { 0x0020, KEY_UP }, | ||
| 571 | { 0x0821, KEY_DOWN }, | ||
| 572 | { 0x0011, KEY_LEFT }, | ||
| 573 | { 0x0810, KEY_RIGHT }, | ||
| 574 | { 0x000d, KEY_OK }, | ||
| 575 | { 0x081f, KEY_RECORD }, | ||
| 576 | { 0x0017, KEY_PLAYPAUSE }, | ||
| 577 | { 0x0816, KEY_PLAYPAUSE }, | ||
| 578 | { 0x000b, KEY_STOP }, | ||
| 579 | { 0x0827, KEY_FASTFORWARD }, | ||
| 580 | { 0x0026, KEY_REWIND }, | ||
| 581 | { 0x081e, KEY_UNKNOWN }, /* Time Shift */ | ||
| 582 | { 0x000e, KEY_UNKNOWN }, /* Snapshot */ | ||
| 583 | { 0x082d, KEY_UNKNOWN }, /* Mouse Cursor */ | ||
| 584 | { 0x000f, KEY_UNKNOWN }, /* Minimize/Maximize */ | ||
| 585 | { 0x0814, KEY_UNKNOWN }, /* Shuffle */ | ||
| 586 | { 0x0025, KEY_POWER }, | ||
| 587 | }; | ||
| 588 | |||
| 589 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) | ||
| 590 | { | ||
| 591 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; | ||
| 592 | static u8 reset [] = { RESET, 0x80 }; | ||
| 593 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | ||
| 594 | static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; | ||
| 595 | static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; | ||
| 596 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | ||
| 597 | |||
| 598 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
| 599 | udelay(200); | ||
| 600 | mt352_write(fe, reset, sizeof(reset)); | ||
| 601 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
| 602 | |||
| 603 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
| 604 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | ||
| 605 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
| 606 | |||
| 607 | return 0; | ||
| 608 | } | ||
| 609 | |||
| 610 | static int cxusb_mt352_demod_init(struct dvb_frontend* fe) | ||
| 611 | { /* used in both lgz201 and th7579 */ | ||
| 612 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x29 }; | ||
| 613 | static u8 reset [] = { RESET, 0x80 }; | ||
| 614 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | ||
| 615 | static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; | ||
| 616 | static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; | ||
| 617 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | ||
| 618 | |||
| 619 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
| 620 | udelay(200); | ||
| 621 | mt352_write(fe, reset, sizeof(reset)); | ||
| 622 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
| 623 | |||
| 624 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
| 625 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | ||
| 626 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
| 627 | return 0; | ||
| 628 | } | ||
| 629 | |||
| 630 | static struct cx22702_config cxusb_cx22702_config = { | ||
| 631 | .demod_address = 0x63, | ||
| 632 | .output_mode = CX22702_PARALLEL_OUTPUT, | ||
| 633 | }; | ||
| 634 | |||
| 635 | static struct lgdt330x_config cxusb_lgdt3303_config = { | ||
| 636 | .demod_address = 0x0e, | ||
| 637 | .demod_chip = LGDT3303, | ||
| 638 | }; | ||
| 639 | |||
| 640 | static struct lgdt330x_config cxusb_aver_lgdt3303_config = { | ||
| 641 | .demod_address = 0x0e, | ||
| 642 | .demod_chip = LGDT3303, | ||
| 643 | .clock_polarity_flip = 2, | ||
| 644 | }; | ||
| 645 | |||
| 646 | static struct mt352_config cxusb_dee1601_config = { | ||
| 647 | .demod_address = 0x0f, | ||
| 648 | .demod_init = cxusb_dee1601_demod_init, | ||
| 649 | }; | ||
| 650 | |||
| 651 | static struct zl10353_config cxusb_zl10353_dee1601_config = { | ||
| 652 | .demod_address = 0x0f, | ||
| 653 | .parallel_ts = 1, | ||
| 654 | }; | ||
| 655 | |||
| 656 | static struct mt352_config cxusb_mt352_config = { | ||
| 657 | /* used in both lgz201 and th7579 */ | ||
| 658 | .demod_address = 0x0f, | ||
| 659 | .demod_init = cxusb_mt352_demod_init, | ||
| 660 | }; | ||
| 661 | |||
| 662 | static struct zl10353_config cxusb_zl10353_xc3028_config = { | ||
| 663 | .demod_address = 0x0f, | ||
| 664 | .if2 = 45600, | ||
| 665 | .no_tuner = 1, | ||
| 666 | .parallel_ts = 1, | ||
| 667 | }; | ||
| 668 | |||
| 669 | static struct zl10353_config cxusb_zl10353_xc3028_config_no_i2c_gate = { | ||
| 670 | .demod_address = 0x0f, | ||
| 671 | .if2 = 45600, | ||
| 672 | .no_tuner = 1, | ||
| 673 | .parallel_ts = 1, | ||
| 674 | .disable_i2c_gate_ctrl = 1, | ||
| 675 | }; | ||
| 676 | |||
| 677 | static struct mt352_config cxusb_mt352_xc3028_config = { | ||
| 678 | .demod_address = 0x0f, | ||
| 679 | .if2 = 4560, | ||
| 680 | .no_tuner = 1, | ||
| 681 | .demod_init = cxusb_mt352_demod_init, | ||
| 682 | }; | ||
| 683 | |||
| 684 | /* FIXME: needs tweaking */ | ||
| 685 | static struct mxl5005s_config aver_a868r_tuner = { | ||
| 686 | .i2c_address = 0x63, | ||
| 687 | .if_freq = 6000000UL, | ||
| 688 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
| 689 | .agc_mode = MXL_SINGLE_AGC, | ||
| 690 | .tracking_filter = MXL_TF_C, | ||
| 691 | .rssi_enable = MXL_RSSI_ENABLE, | ||
| 692 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
| 693 | .div_out = MXL_DIV_OUT_4, | ||
| 694 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
| 695 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
| 696 | .top = MXL5005S_TOP_25P2, | ||
| 697 | .mod_mode = MXL_DIGITAL_MODE, | ||
| 698 | .if_mode = MXL_ZERO_IF, | ||
| 699 | .AgcMasterByte = 0x00, | ||
| 700 | }; | ||
| 701 | |||
| 702 | /* FIXME: needs tweaking */ | ||
| 703 | static struct mxl5005s_config d680_dmb_tuner = { | ||
| 704 | .i2c_address = 0x63, | ||
| 705 | .if_freq = 36125000UL, | ||
| 706 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
| 707 | .agc_mode = MXL_SINGLE_AGC, | ||
| 708 | .tracking_filter = MXL_TF_C, | ||
| 709 | .rssi_enable = MXL_RSSI_ENABLE, | ||
| 710 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
| 711 | .div_out = MXL_DIV_OUT_4, | ||
| 712 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
| 713 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
| 714 | .top = MXL5005S_TOP_25P2, | ||
| 715 | .mod_mode = MXL_DIGITAL_MODE, | ||
| 716 | .if_mode = MXL_ZERO_IF, | ||
| 717 | .AgcMasterByte = 0x00, | ||
| 718 | }; | ||
| 719 | |||
| 720 | static struct max2165_config mygica_d689_max2165_cfg = { | ||
| 721 | .i2c_address = 0x60, | ||
| 722 | .osc_clk = 20 | ||
| 723 | }; | ||
| 724 | |||
| 725 | /* Callbacks for DVB USB */ | ||
| 726 | static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 727 | { | ||
| 728 | dvb_attach(simple_tuner_attach, adap->fe, | ||
| 729 | &adap->dev->i2c_adap, 0x61, | ||
| 730 | TUNER_PHILIPS_FMD1216ME_MK3); | ||
| 731 | return 0; | ||
| 732 | } | ||
| 733 | |||
| 734 | static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 735 | { | ||
| 736 | dvb_attach(dvb_pll_attach, adap->fe, 0x61, | ||
| 737 | NULL, DVB_PLL_THOMSON_DTT7579); | ||
| 738 | return 0; | ||
| 739 | } | ||
| 740 | |||
| 741 | static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 742 | { | ||
| 743 | dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_LG_Z201); | ||
| 744 | return 0; | ||
| 745 | } | ||
| 746 | |||
| 747 | static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 748 | { | ||
| 749 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, | ||
| 750 | NULL, DVB_PLL_THOMSON_DTT7579); | ||
| 751 | return 0; | ||
| 752 | } | ||
| 753 | |||
| 754 | static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 755 | { | ||
| 756 | dvb_attach(simple_tuner_attach, adap->fe, | ||
| 757 | &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF); | ||
| 758 | return 0; | ||
| 759 | } | ||
| 760 | |||
| 761 | static int dvico_bluebird_xc2028_callback(void *ptr, int component, | ||
| 762 | int command, int arg) | ||
| 763 | { | ||
| 764 | struct dvb_usb_adapter *adap = ptr; | ||
| 765 | struct dvb_usb_device *d = adap->dev; | ||
| 766 | |||
| 767 | switch (command) { | ||
| 768 | case XC2028_TUNER_RESET: | ||
| 769 | deb_info("%s: XC2028_TUNER_RESET %d\n", __func__, arg); | ||
| 770 | cxusb_bluebird_gpio_pulse(d, 0x01, 1); | ||
| 771 | break; | ||
| 772 | case XC2028_RESET_CLK: | ||
| 773 | deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg); | ||
| 774 | break; | ||
| 775 | default: | ||
| 776 | deb_info("%s: unknown command %d, arg %d\n", __func__, | ||
| 777 | command, arg); | ||
| 778 | return -EINVAL; | ||
| 779 | } | ||
| 780 | |||
| 781 | return 0; | ||
| 782 | } | ||
| 783 | |||
| 784 | static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 785 | { | ||
| 786 | struct dvb_frontend *fe; | ||
| 787 | struct xc2028_config cfg = { | ||
| 788 | .i2c_adap = &adap->dev->i2c_adap, | ||
| 789 | .i2c_addr = 0x61, | ||
| 790 | }; | ||
| 791 | static struct xc2028_ctrl ctl = { | ||
| 792 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
| 793 | .max_len = 64, | ||
| 794 | .demod = XC3028_FE_ZARLINK456, | ||
| 795 | }; | ||
| 796 | |||
| 797 | /* FIXME: generalize & move to common area */ | ||
| 798 | adap->fe->callback = dvico_bluebird_xc2028_callback; | ||
| 799 | |||
| 800 | fe = dvb_attach(xc2028_attach, adap->fe, &cfg); | ||
| 801 | if (fe == NULL || fe->ops.tuner_ops.set_config == NULL) | ||
| 802 | return -EIO; | ||
| 803 | |||
| 804 | fe->ops.tuner_ops.set_config(fe, &ctl); | ||
| 805 | |||
| 806 | return 0; | ||
| 807 | } | ||
| 808 | |||
| 809 | static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 810 | { | ||
| 811 | dvb_attach(mxl5005s_attach, adap->fe, | ||
| 812 | &adap->dev->i2c_adap, &aver_a868r_tuner); | ||
| 813 | return 0; | ||
| 814 | } | ||
| 815 | |||
| 816 | static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 817 | { | ||
| 818 | struct dvb_frontend *fe; | ||
| 819 | fe = dvb_attach(mxl5005s_attach, adap->fe, | ||
| 820 | &adap->dev->i2c_adap, &d680_dmb_tuner); | ||
| 821 | return (fe == NULL) ? -EIO : 0; | ||
| 822 | } | ||
| 823 | |||
| 824 | static int cxusb_mygica_d689_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 825 | { | ||
| 826 | struct dvb_frontend *fe; | ||
| 827 | fe = dvb_attach(max2165_attach, adap->fe, | ||
| 828 | &adap->dev->i2c_adap, &mygica_d689_max2165_cfg); | ||
| 829 | return (fe == NULL) ? -EIO : 0; | ||
| 830 | } | ||
| 831 | |||
| 832 | static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 833 | { | ||
| 834 | u8 b; | ||
| 835 | if (usb_set_interface(adap->dev->udev, 0, 6) < 0) | ||
| 836 | err("set interface failed"); | ||
| 837 | |||
| 838 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1); | ||
| 839 | |||
| 840 | if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, | ||
| 841 | &adap->dev->i2c_adap)) != NULL) | ||
| 842 | return 0; | ||
| 843 | |||
| 844 | return -EIO; | ||
| 845 | } | ||
| 846 | |||
| 847 | static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 848 | { | ||
| 849 | if (usb_set_interface(adap->dev->udev, 0, 7) < 0) | ||
| 850 | err("set interface failed"); | ||
| 851 | |||
| 852 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | ||
| 853 | |||
| 854 | if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, | ||
| 855 | &adap->dev->i2c_adap)) != NULL) | ||
| 856 | return 0; | ||
| 857 | |||
| 858 | return -EIO; | ||
| 859 | } | ||
| 860 | |||
| 861 | static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 862 | { | ||
| 863 | adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config, | ||
| 864 | &adap->dev->i2c_adap); | ||
| 865 | if (adap->fe != NULL) | ||
| 866 | return 0; | ||
| 867 | |||
| 868 | return -EIO; | ||
| 869 | } | ||
| 870 | |||
| 871 | static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 872 | { | ||
| 873 | /* used in both lgz201 and th7579 */ | ||
| 874 | if (usb_set_interface(adap->dev->udev, 0, 0) < 0) | ||
| 875 | err("set interface failed"); | ||
| 876 | |||
| 877 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | ||
| 878 | |||
| 879 | if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, | ||
| 880 | &adap->dev->i2c_adap)) != NULL) | ||
| 881 | return 0; | ||
| 882 | |||
| 883 | return -EIO; | ||
| 884 | } | ||
| 885 | |||
| 886 | static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 887 | { | ||
| 888 | if (usb_set_interface(adap->dev->udev, 0, 0) < 0) | ||
| 889 | err("set interface failed"); | ||
| 890 | |||
| 891 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | ||
| 892 | |||
| 893 | if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, | ||
| 894 | &adap->dev->i2c_adap)) != NULL) || | ||
| 895 | ((adap->fe = dvb_attach(zl10353_attach, | ||
| 896 | &cxusb_zl10353_dee1601_config, | ||
| 897 | &adap->dev->i2c_adap)) != NULL)) | ||
| 898 | return 0; | ||
| 899 | |||
| 900 | return -EIO; | ||
| 901 | } | ||
| 902 | |||
| 903 | static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 904 | { | ||
| 905 | u8 ircode[4]; | ||
| 906 | int i; | ||
| 907 | struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD, | ||
| 908 | .buf = ircode, .len = 4 }; | ||
| 909 | |||
| 910 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) | ||
| 911 | err("set interface failed"); | ||
| 912 | |||
| 913 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | ||
| 914 | |||
| 915 | /* reset the tuner and demodulator */ | ||
| 916 | cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0); | ||
| 917 | cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1); | ||
| 918 | cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); | ||
| 919 | |||
| 920 | if ((adap->fe = dvb_attach(zl10353_attach, | ||
| 921 | &cxusb_zl10353_xc3028_config_no_i2c_gate, | ||
| 922 | &adap->dev->i2c_adap)) == NULL) | ||
| 923 | return -EIO; | ||
| 924 | |||
| 925 | /* try to determine if there is no IR decoder on the I2C bus */ | ||
| 926 | for (i = 0; adap->dev->props.rc.legacy.rc_map_table != NULL && i < 5; i++) { | ||
| 927 | msleep(20); | ||
| 928 | if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1) | ||
| 929 | goto no_IR; | ||
| 930 | if (ircode[0] == 0 && ircode[1] == 0) | ||
| 931 | continue; | ||
| 932 | if (ircode[2] + ircode[3] != 0xff) { | ||
| 933 | no_IR: | ||
| 934 | adap->dev->props.rc.legacy.rc_map_table = NULL; | ||
| 935 | info("No IR receiver detected on this device."); | ||
| 936 | break; | ||
| 937 | } | ||
| 938 | } | ||
| 939 | |||
| 940 | return 0; | ||
| 941 | } | ||
| 942 | |||
| 943 | static struct dibx000_agc_config dib7070_agc_config = { | ||
| 944 | .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, | ||
| 945 | |||
| 946 | /* | ||
| 947 | * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, | ||
| 948 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | ||
| 949 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 | ||
| 950 | */ | ||
| 951 | .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | | ||
| 952 | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
| 953 | .inv_gain = 600, | ||
| 954 | .time_stabiliz = 10, | ||
| 955 | .alpha_level = 0, | ||
| 956 | .thlock = 118, | ||
| 957 | .wbd_inv = 0, | ||
| 958 | .wbd_ref = 3530, | ||
| 959 | .wbd_sel = 1, | ||
| 960 | .wbd_alpha = 5, | ||
| 961 | .agc1_max = 65535, | ||
| 962 | .agc1_min = 0, | ||
| 963 | .agc2_max = 65535, | ||
| 964 | .agc2_min = 0, | ||
| 965 | .agc1_pt1 = 0, | ||
| 966 | .agc1_pt2 = 40, | ||
| 967 | .agc1_pt3 = 183, | ||
| 968 | .agc1_slope1 = 206, | ||
| 969 | .agc1_slope2 = 255, | ||
| 970 | .agc2_pt1 = 72, | ||
| 971 | .agc2_pt2 = 152, | ||
| 972 | .agc2_slope1 = 88, | ||
| 973 | .agc2_slope2 = 90, | ||
| 974 | .alpha_mant = 17, | ||
| 975 | .alpha_exp = 27, | ||
| 976 | .beta_mant = 23, | ||
| 977 | .beta_exp = 51, | ||
| 978 | .perform_agc_softsplit = 0, | ||
| 979 | }; | ||
| 980 | |||
| 981 | static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { | ||
| 982 | .internal = 60000, | ||
| 983 | .sampling = 15000, | ||
| 984 | .pll_prediv = 1, | ||
| 985 | .pll_ratio = 20, | ||
| 986 | .pll_range = 3, | ||
| 987 | .pll_reset = 1, | ||
| 988 | .pll_bypass = 0, | ||
| 989 | .enable_refdiv = 0, | ||
| 990 | .bypclk_div = 0, | ||
| 991 | .IO_CLK_en_core = 1, | ||
| 992 | .ADClkSrc = 1, | ||
| 993 | .modulo = 2, | ||
| 994 | /* refsel, sel, freq_15k */ | ||
| 995 | .sad_cfg = (3 << 14) | (1 << 12) | (524 << 0), | ||
| 996 | .ifreq = (0 << 25) | 0, | ||
| 997 | .timf = 20452225, | ||
| 998 | .xtal_hz = 12000000, | ||
| 999 | }; | ||
| 1000 | |||
| 1001 | static struct dib7000p_config cxusb_dualdig4_rev2_config = { | ||
| 1002 | .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, | ||
| 1003 | .output_mpeg2_in_188_bytes = 1, | ||
| 1004 | |||
| 1005 | .agc_config_count = 1, | ||
| 1006 | .agc = &dib7070_agc_config, | ||
| 1007 | .bw = &dib7070_bw_config_12_mhz, | ||
| 1008 | .tuner_is_baseband = 1, | ||
| 1009 | .spur_protect = 1, | ||
| 1010 | |||
| 1011 | .gpio_dir = 0xfcef, | ||
| 1012 | .gpio_val = 0x0110, | ||
| 1013 | |||
| 1014 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 1015 | |||
| 1016 | .hostbus_diversity = 1, | ||
| 1017 | }; | ||
| 1018 | |||
| 1019 | static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1020 | { | ||
| 1021 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) | ||
| 1022 | err("set interface failed"); | ||
| 1023 | |||
| 1024 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | ||
| 1025 | |||
| 1026 | cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); | ||
| 1027 | |||
| 1028 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | ||
| 1029 | &cxusb_dualdig4_rev2_config) < 0) { | ||
| 1030 | printk(KERN_WARNING "Unable to enumerate dib7000p\n"); | ||
| 1031 | return -ENODEV; | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | ||
| 1035 | &cxusb_dualdig4_rev2_config); | ||
| 1036 | if (adap->fe == NULL) | ||
| 1037 | return -EIO; | ||
| 1038 | |||
| 1039 | return 0; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) | ||
| 1043 | { | ||
| 1044 | return dib7000p_set_gpio(fe, 8, 0, !onoff); | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) | ||
| 1048 | { | ||
| 1049 | return 0; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | static struct dib0070_config dib7070p_dib0070_config = { | ||
| 1053 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
| 1054 | .reset = dib7070_tuner_reset, | ||
| 1055 | .sleep = dib7070_tuner_sleep, | ||
| 1056 | .clock_khz = 12000, | ||
| 1057 | }; | ||
| 1058 | |||
| 1059 | struct dib0700_adapter_state { | ||
| 1060 | int (*set_param_save) (struct dvb_frontend *, | ||
| 1061 | struct dvb_frontend_parameters *); | ||
| 1062 | }; | ||
| 1063 | |||
| 1064 | static int dib7070_set_param_override(struct dvb_frontend *fe, | ||
| 1065 | struct dvb_frontend_parameters *fep) | ||
| 1066 | { | ||
| 1067 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 1068 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1069 | |||
| 1070 | u16 offset; | ||
| 1071 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
| 1072 | switch (band) { | ||
| 1073 | case BAND_VHF: offset = 950; break; | ||
| 1074 | default: | ||
| 1075 | case BAND_UHF: offset = 550; break; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); | ||
| 1079 | |||
| 1080 | return state->set_param_save(fe, fep); | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1084 | { | ||
| 1085 | struct dib0700_adapter_state *st = adap->priv; | ||
| 1086 | struct i2c_adapter *tun_i2c = | ||
| 1087 | dib7000p_get_i2c_master(adap->fe, | ||
| 1088 | DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 1089 | |||
| 1090 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, | ||
| 1091 | &dib7070p_dib0070_config) == NULL) | ||
| 1092 | return -ENODEV; | ||
| 1093 | |||
| 1094 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
| 1095 | adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override; | ||
| 1096 | return 0; | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1100 | { | ||
| 1101 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) | ||
| 1102 | err("set interface failed"); | ||
| 1103 | |||
| 1104 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | ||
| 1105 | |||
| 1106 | /* reset the tuner and demodulator */ | ||
| 1107 | cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0); | ||
| 1108 | cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1); | ||
| 1109 | cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); | ||
| 1110 | |||
| 1111 | if ((adap->fe = dvb_attach(zl10353_attach, | ||
| 1112 | &cxusb_zl10353_xc3028_config, | ||
| 1113 | &adap->dev->i2c_adap)) != NULL) | ||
| 1114 | return 0; | ||
| 1115 | |||
| 1116 | if ((adap->fe = dvb_attach(mt352_attach, | ||
| 1117 | &cxusb_mt352_xc3028_config, | ||
| 1118 | &adap->dev->i2c_adap)) != NULL) | ||
| 1119 | return 0; | ||
| 1120 | |||
| 1121 | return -EIO; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | static struct lgs8gxx_config d680_lgs8gl5_cfg = { | ||
| 1125 | .prod = LGS8GXX_PROD_LGS8GL5, | ||
| 1126 | .demod_address = 0x19, | ||
| 1127 | .serial_ts = 0, | ||
| 1128 | .ts_clk_pol = 0, | ||
| 1129 | .ts_clk_gated = 1, | ||
| 1130 | .if_clk_freq = 30400, /* 30.4 MHz */ | ||
| 1131 | .if_freq = 5725, /* 5.725 MHz */ | ||
| 1132 | .if_neg_center = 0, | ||
| 1133 | .ext_adc = 0, | ||
| 1134 | .adc_signed = 0, | ||
| 1135 | .if_neg_edge = 0, | ||
| 1136 | }; | ||
| 1137 | |||
| 1138 | static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1139 | { | ||
| 1140 | struct dvb_usb_device *d = adap->dev; | ||
| 1141 | int n; | ||
| 1142 | |||
| 1143 | /* Select required USB configuration */ | ||
| 1144 | if (usb_set_interface(d->udev, 0, 0) < 0) | ||
| 1145 | err("set interface failed"); | ||
| 1146 | |||
| 1147 | /* Unblock all USB pipes */ | ||
| 1148 | usb_clear_halt(d->udev, | ||
| 1149 | usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | ||
| 1150 | usb_clear_halt(d->udev, | ||
| 1151 | usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | ||
| 1152 | usb_clear_halt(d->udev, | ||
| 1153 | usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint)); | ||
| 1154 | |||
| 1155 | /* Drain USB pipes to avoid hang after reboot */ | ||
| 1156 | for (n = 0; n < 5; n++) { | ||
| 1157 | cxusb_d680_dmb_drain_message(d); | ||
| 1158 | cxusb_d680_dmb_drain_video(d); | ||
| 1159 | msleep(200); | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | /* Reset the tuner */ | ||
| 1163 | if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) { | ||
| 1164 | err("clear tuner gpio failed"); | ||
| 1165 | return -EIO; | ||
| 1166 | } | ||
| 1167 | msleep(100); | ||
| 1168 | if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) { | ||
| 1169 | err("set tuner gpio failed"); | ||
| 1170 | return -EIO; | ||
| 1171 | } | ||
| 1172 | msleep(100); | ||
| 1173 | |||
| 1174 | /* Attach frontend */ | ||
| 1175 | adap->fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap); | ||
| 1176 | if (adap->fe == NULL) | ||
| 1177 | return -EIO; | ||
| 1178 | |||
| 1179 | return 0; | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | static struct atbm8830_config mygica_d689_atbm8830_cfg = { | ||
| 1183 | .prod = ATBM8830_PROD_8830, | ||
| 1184 | .demod_address = 0x40, | ||
| 1185 | .serial_ts = 0, | ||
| 1186 | .ts_sampling_edge = 1, | ||
| 1187 | .ts_clk_gated = 0, | ||
| 1188 | .osc_clk_freq = 30400, /* in kHz */ | ||
| 1189 | .if_freq = 0, /* zero IF */ | ||
| 1190 | .zif_swap_iq = 1, | ||
| 1191 | .agc_min = 0x2E, | ||
| 1192 | .agc_max = 0x90, | ||
| 1193 | .agc_hold_loop = 0, | ||
| 1194 | }; | ||
| 1195 | |||
| 1196 | static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1197 | { | ||
| 1198 | struct dvb_usb_device *d = adap->dev; | ||
| 1199 | |||
| 1200 | /* Select required USB configuration */ | ||
| 1201 | if (usb_set_interface(d->udev, 0, 0) < 0) | ||
| 1202 | err("set interface failed"); | ||
| 1203 | |||
| 1204 | /* Unblock all USB pipes */ | ||
| 1205 | usb_clear_halt(d->udev, | ||
| 1206 | usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | ||
| 1207 | usb_clear_halt(d->udev, | ||
| 1208 | usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | ||
| 1209 | usb_clear_halt(d->udev, | ||
| 1210 | usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint)); | ||
| 1211 | |||
| 1212 | |||
| 1213 | /* Reset the tuner */ | ||
| 1214 | if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) { | ||
| 1215 | err("clear tuner gpio failed"); | ||
| 1216 | return -EIO; | ||
| 1217 | } | ||
| 1218 | msleep(100); | ||
| 1219 | if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) { | ||
| 1220 | err("set tuner gpio failed"); | ||
| 1221 | return -EIO; | ||
| 1222 | } | ||
| 1223 | msleep(100); | ||
| 1224 | |||
| 1225 | /* Attach frontend */ | ||
| 1226 | adap->fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg, | ||
| 1227 | &d->i2c_adap); | ||
| 1228 | if (adap->fe == NULL) | ||
| 1229 | return -EIO; | ||
| 1230 | |||
| 1231 | return 0; | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | /* | ||
| 1235 | * DViCO has shipped two devices with the same USB ID, but only one of them | ||
| 1236 | * needs a firmware download. Check the device class details to see if they | ||
| 1237 | * have non-default values to decide whether the device is actually cold or | ||
| 1238 | * not, and forget a match if it turns out we selected the wrong device. | ||
| 1239 | */ | ||
| 1240 | static int bluebird_fx2_identify_state(struct usb_device *udev, | ||
| 1241 | struct dvb_usb_device_properties *props, | ||
| 1242 | struct dvb_usb_device_description **desc, | ||
| 1243 | int *cold) | ||
| 1244 | { | ||
| 1245 | int wascold = *cold; | ||
| 1246 | |||
| 1247 | *cold = udev->descriptor.bDeviceClass == 0xff && | ||
| 1248 | udev->descriptor.bDeviceSubClass == 0xff && | ||
| 1249 | udev->descriptor.bDeviceProtocol == 0xff; | ||
| 1250 | |||
| 1251 | if (*cold && !wascold) | ||
| 1252 | *desc = NULL; | ||
| 1253 | |||
| 1254 | return 0; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | /* | ||
| 1258 | * DViCO bluebird firmware needs the "warm" product ID to be patched into the | ||
| 1259 | * firmware file before download. | ||
| 1260 | */ | ||
| 1261 | |||
| 1262 | static const int dvico_firmware_id_offsets[] = { 6638, 3204 }; | ||
| 1263 | static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, | ||
| 1264 | const struct firmware *fw) | ||
| 1265 | { | ||
| 1266 | int pos; | ||
| 1267 | |||
| 1268 | for (pos = 0; pos < ARRAY_SIZE(dvico_firmware_id_offsets); pos++) { | ||
| 1269 | int idoff = dvico_firmware_id_offsets[pos]; | ||
| 1270 | |||
| 1271 | if (fw->size < idoff + 4) | ||
| 1272 | continue; | ||
| 1273 | |||
| 1274 | if (fw->data[idoff] == (USB_VID_DVICO & 0xff) && | ||
| 1275 | fw->data[idoff + 1] == USB_VID_DVICO >> 8) { | ||
| 1276 | struct firmware new_fw; | ||
| 1277 | u8 *new_fw_data = vmalloc(fw->size); | ||
| 1278 | int ret; | ||
| 1279 | |||
| 1280 | if (!new_fw_data) | ||
| 1281 | return -ENOMEM; | ||
| 1282 | |||
| 1283 | memcpy(new_fw_data, fw->data, fw->size); | ||
| 1284 | new_fw.size = fw->size; | ||
| 1285 | new_fw.data = new_fw_data; | ||
| 1286 | |||
| 1287 | new_fw_data[idoff + 2] = | ||
| 1288 | le16_to_cpu(udev->descriptor.idProduct) + 1; | ||
| 1289 | new_fw_data[idoff + 3] = | ||
| 1290 | le16_to_cpu(udev->descriptor.idProduct) >> 8; | ||
| 1291 | |||
| 1292 | ret = usb_cypress_load_firmware(udev, &new_fw, | ||
| 1293 | CYPRESS_FX2); | ||
| 1294 | vfree(new_fw_data); | ||
| 1295 | return ret; | ||
| 1296 | } | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | return -EINVAL; | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | /* DVB USB Driver stuff */ | ||
| 1303 | static struct dvb_usb_device_properties cxusb_medion_properties; | ||
| 1304 | static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties; | ||
| 1305 | static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties; | ||
| 1306 | static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; | ||
| 1307 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; | ||
| 1308 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; | ||
| 1309 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties; | ||
| 1310 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; | ||
| 1311 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; | ||
| 1312 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; | ||
| 1313 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties; | ||
| 1314 | static struct dvb_usb_device_properties cxusb_mygica_d689_properties; | ||
| 1315 | |||
| 1316 | static int cxusb_probe(struct usb_interface *intf, | ||
| 1317 | const struct usb_device_id *id) | ||
| 1318 | { | ||
| 1319 | if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties, | ||
| 1320 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1321 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties, | ||
| 1322 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1323 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties, | ||
| 1324 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1325 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties, | ||
| 1326 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1327 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties, | ||
| 1328 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1329 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties, | ||
| 1330 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1331 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties, | ||
| 1332 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1333 | 0 == dvb_usb_device_init(intf, | ||
| 1334 | &cxusb_bluebird_nano2_needsfirmware_properties, | ||
| 1335 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1336 | 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, | ||
| 1337 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1338 | 0 == dvb_usb_device_init(intf, | ||
| 1339 | &cxusb_bluebird_dualdig4_rev2_properties, | ||
| 1340 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1341 | 0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties, | ||
| 1342 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1343 | 0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, | ||
| 1344 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1345 | 0) | ||
| 1346 | return 0; | ||
| 1347 | |||
| 1348 | return -EINVAL; | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | static struct usb_device_id cxusb_table [] = { | ||
| 1352 | { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, | ||
| 1353 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, | ||
| 1354 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) }, | ||
| 1355 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) }, | ||
| 1356 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) }, | ||
| 1357 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) }, | ||
| 1358 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) }, | ||
| 1359 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) }, | ||
| 1360 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) }, | ||
| 1361 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) }, | ||
| 1362 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) }, | ||
| 1363 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) }, | ||
| 1364 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) }, | ||
| 1365 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) }, | ||
| 1366 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) }, | ||
| 1367 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) }, | ||
| 1368 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) }, | ||
| 1369 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) }, | ||
| 1370 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, | ||
| 1371 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) }, | ||
| 1372 | {} /* Terminating entry */ | ||
| 1373 | }; | ||
| 1374 | MODULE_DEVICE_TABLE (usb, cxusb_table); | ||
| 1375 | |||
| 1376 | static struct dvb_usb_device_properties cxusb_medion_properties = { | ||
| 1377 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1378 | |||
| 1379 | .usb_ctrl = CYPRESS_FX2, | ||
| 1380 | |||
| 1381 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1382 | |||
| 1383 | .num_adapters = 1, | ||
| 1384 | .adapter = { | ||
| 1385 | { | ||
| 1386 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 1387 | .frontend_attach = cxusb_cx22702_frontend_attach, | ||
| 1388 | .tuner_attach = cxusb_fmd1216me_tuner_attach, | ||
| 1389 | /* parameter for the MPEG2-data transfer */ | ||
| 1390 | .stream = { | ||
| 1391 | .type = USB_BULK, | ||
| 1392 | .count = 5, | ||
| 1393 | .endpoint = 0x02, | ||
| 1394 | .u = { | ||
| 1395 | .bulk = { | ||
| 1396 | .buffersize = 8192, | ||
| 1397 | } | ||
| 1398 | } | ||
| 1399 | }, | ||
| 1400 | |||
| 1401 | }, | ||
| 1402 | }, | ||
| 1403 | .power_ctrl = cxusb_power_ctrl, | ||
| 1404 | |||
| 1405 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1406 | |||
| 1407 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1408 | |||
| 1409 | .num_device_descs = 1, | ||
| 1410 | .devices = { | ||
| 1411 | { "Medion MD95700 (MDUSBTV-HYBRID)", | ||
| 1412 | { NULL }, | ||
| 1413 | { &cxusb_table[0], NULL }, | ||
| 1414 | }, | ||
| 1415 | } | ||
| 1416 | }; | ||
| 1417 | |||
| 1418 | static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { | ||
| 1419 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1420 | |||
| 1421 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1422 | .firmware = "dvb-usb-bluebird-01.fw", | ||
| 1423 | .download_firmware = bluebird_patch_dvico_firmware_download, | ||
| 1424 | /* use usb alt setting 0 for EP4 transfer (dvb-t), | ||
| 1425 | use usb alt setting 7 for EP2 transfer (atsc) */ | ||
| 1426 | |||
| 1427 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1428 | |||
| 1429 | .num_adapters = 1, | ||
| 1430 | .adapter = { | ||
| 1431 | { | ||
| 1432 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 1433 | .frontend_attach = cxusb_lgdt3303_frontend_attach, | ||
| 1434 | .tuner_attach = cxusb_lgh064f_tuner_attach, | ||
| 1435 | |||
| 1436 | /* parameter for the MPEG2-data transfer */ | ||
| 1437 | .stream = { | ||
| 1438 | .type = USB_BULK, | ||
| 1439 | .count = 5, | ||
| 1440 | .endpoint = 0x02, | ||
| 1441 | .u = { | ||
| 1442 | .bulk = { | ||
| 1443 | .buffersize = 8192, | ||
| 1444 | } | ||
| 1445 | } | ||
| 1446 | }, | ||
| 1447 | }, | ||
| 1448 | }, | ||
| 1449 | |||
| 1450 | .power_ctrl = cxusb_bluebird_power_ctrl, | ||
| 1451 | |||
| 1452 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1453 | |||
| 1454 | .rc.legacy = { | ||
| 1455 | .rc_interval = 100, | ||
| 1456 | .rc_map_table = rc_map_dvico_portable_table, | ||
| 1457 | .rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table), | ||
| 1458 | .rc_query = cxusb_rc_query, | ||
| 1459 | }, | ||
| 1460 | |||
| 1461 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1462 | |||
| 1463 | .num_device_descs = 1, | ||
| 1464 | .devices = { | ||
| 1465 | { "DViCO FusionHDTV5 USB Gold", | ||
| 1466 | { &cxusb_table[1], NULL }, | ||
| 1467 | { &cxusb_table[2], NULL }, | ||
| 1468 | }, | ||
| 1469 | } | ||
| 1470 | }; | ||
| 1471 | |||
| 1472 | static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = { | ||
| 1473 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1474 | |||
| 1475 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1476 | .firmware = "dvb-usb-bluebird-01.fw", | ||
| 1477 | .download_firmware = bluebird_patch_dvico_firmware_download, | ||
| 1478 | /* use usb alt setting 0 for EP4 transfer (dvb-t), | ||
| 1479 | use usb alt setting 7 for EP2 transfer (atsc) */ | ||
| 1480 | |||
| 1481 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1482 | |||
| 1483 | .num_adapters = 1, | ||
| 1484 | .adapter = { | ||
| 1485 | { | ||
| 1486 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 1487 | .frontend_attach = cxusb_dee1601_frontend_attach, | ||
| 1488 | .tuner_attach = cxusb_dee1601_tuner_attach, | ||
| 1489 | /* parameter for the MPEG2-data transfer */ | ||
| 1490 | .stream = { | ||
| 1491 | .type = USB_BULK, | ||
| 1492 | .count = 5, | ||
| 1493 | .endpoint = 0x04, | ||
| 1494 | .u = { | ||
| 1495 | .bulk = { | ||
| 1496 | .buffersize = 8192, | ||
| 1497 | } | ||
| 1498 | } | ||
| 1499 | }, | ||
| 1500 | }, | ||
| 1501 | }, | ||
| 1502 | |||
| 1503 | .power_ctrl = cxusb_bluebird_power_ctrl, | ||
| 1504 | |||
| 1505 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1506 | |||
| 1507 | .rc.legacy = { | ||
| 1508 | .rc_interval = 150, | ||
| 1509 | .rc_map_table = rc_map_dvico_mce_table, | ||
| 1510 | .rc_map_size = ARRAY_SIZE(rc_map_dvico_mce_table), | ||
| 1511 | .rc_query = cxusb_rc_query, | ||
| 1512 | }, | ||
| 1513 | |||
| 1514 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1515 | |||
| 1516 | .num_device_descs = 3, | ||
| 1517 | .devices = { | ||
| 1518 | { "DViCO FusionHDTV DVB-T Dual USB", | ||
| 1519 | { &cxusb_table[3], NULL }, | ||
| 1520 | { &cxusb_table[4], NULL }, | ||
| 1521 | }, | ||
| 1522 | { "DigitalNow DVB-T Dual USB", | ||
| 1523 | { &cxusb_table[9], NULL }, | ||
| 1524 | { &cxusb_table[10], NULL }, | ||
| 1525 | }, | ||
| 1526 | { "DViCO FusionHDTV DVB-T Dual Digital 2", | ||
| 1527 | { &cxusb_table[11], NULL }, | ||
| 1528 | { &cxusb_table[12], NULL }, | ||
| 1529 | }, | ||
| 1530 | } | ||
| 1531 | }; | ||
| 1532 | |||
| 1533 | static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { | ||
| 1534 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1535 | |||
| 1536 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1537 | .firmware = "dvb-usb-bluebird-01.fw", | ||
| 1538 | .download_firmware = bluebird_patch_dvico_firmware_download, | ||
| 1539 | /* use usb alt setting 0 for EP4 transfer (dvb-t), | ||
| 1540 | use usb alt setting 7 for EP2 transfer (atsc) */ | ||
| 1541 | |||
| 1542 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1543 | |||
| 1544 | .num_adapters = 2, | ||
| 1545 | .adapter = { | ||
| 1546 | { | ||
| 1547 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 1548 | .frontend_attach = cxusb_mt352_frontend_attach, | ||
| 1549 | .tuner_attach = cxusb_lgz201_tuner_attach, | ||
| 1550 | |||
| 1551 | /* parameter for the MPEG2-data transfer */ | ||
| 1552 | .stream = { | ||
| 1553 | .type = USB_BULK, | ||
| 1554 | .count = 5, | ||
| 1555 | .endpoint = 0x04, | ||
| 1556 | .u = { | ||
| 1557 | .bulk = { | ||
| 1558 | .buffersize = 8192, | ||
| 1559 | } | ||
| 1560 | } | ||
| 1561 | }, | ||
| 1562 | }, | ||
| 1563 | }, | ||
| 1564 | .power_ctrl = cxusb_bluebird_power_ctrl, | ||
| 1565 | |||
| 1566 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1567 | |||
| 1568 | .rc.legacy = { | ||
| 1569 | .rc_interval = 100, | ||
| 1570 | .rc_map_table = rc_map_dvico_portable_table, | ||
| 1571 | .rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table), | ||
| 1572 | .rc_query = cxusb_rc_query, | ||
| 1573 | }, | ||
| 1574 | |||
| 1575 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1576 | .num_device_descs = 1, | ||
| 1577 | .devices = { | ||
| 1578 | { "DViCO FusionHDTV DVB-T USB (LGZ201)", | ||
| 1579 | { &cxusb_table[5], NULL }, | ||
| 1580 | { &cxusb_table[6], NULL }, | ||
| 1581 | }, | ||
| 1582 | } | ||
| 1583 | }; | ||
| 1584 | |||
| 1585 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { | ||
| 1586 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1587 | |||
| 1588 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1589 | .firmware = "dvb-usb-bluebird-01.fw", | ||
| 1590 | .download_firmware = bluebird_patch_dvico_firmware_download, | ||
| 1591 | /* use usb alt setting 0 for EP4 transfer (dvb-t), | ||
| 1592 | use usb alt setting 7 for EP2 transfer (atsc) */ | ||
| 1593 | |||
| 1594 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1595 | |||
| 1596 | .num_adapters = 1, | ||
| 1597 | .adapter = { | ||
| 1598 | { | ||
| 1599 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 1600 | .frontend_attach = cxusb_mt352_frontend_attach, | ||
| 1601 | .tuner_attach = cxusb_dtt7579_tuner_attach, | ||
| 1602 | |||
| 1603 | /* parameter for the MPEG2-data transfer */ | ||
| 1604 | .stream = { | ||
| 1605 | .type = USB_BULK, | ||
| 1606 | .count = 5, | ||
| 1607 | .endpoint = 0x04, | ||
| 1608 | .u = { | ||
| 1609 | .bulk = { | ||
| 1610 | .buffersize = 8192, | ||
| 1611 | } | ||
| 1612 | } | ||
| 1613 | }, | ||
| 1614 | }, | ||
| 1615 | }, | ||
| 1616 | .power_ctrl = cxusb_bluebird_power_ctrl, | ||
| 1617 | |||
| 1618 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1619 | |||
| 1620 | .rc.legacy = { | ||
| 1621 | .rc_interval = 100, | ||
| 1622 | .rc_map_table = rc_map_dvico_portable_table, | ||
| 1623 | .rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table), | ||
| 1624 | .rc_query = cxusb_rc_query, | ||
| 1625 | }, | ||
| 1626 | |||
| 1627 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1628 | |||
| 1629 | .num_device_descs = 1, | ||
| 1630 | .devices = { | ||
| 1631 | { "DViCO FusionHDTV DVB-T USB (TH7579)", | ||
| 1632 | { &cxusb_table[7], NULL }, | ||
| 1633 | { &cxusb_table[8], NULL }, | ||
| 1634 | }, | ||
| 1635 | } | ||
| 1636 | }; | ||
| 1637 | |||
| 1638 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = { | ||
| 1639 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1640 | |||
| 1641 | .usb_ctrl = CYPRESS_FX2, | ||
| 1642 | |||
| 1643 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1644 | |||
| 1645 | .num_adapters = 1, | ||
| 1646 | .adapter = { | ||
| 1647 | { | ||
| 1648 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 1649 | .frontend_attach = cxusb_dualdig4_frontend_attach, | ||
| 1650 | .tuner_attach = cxusb_dvico_xc3028_tuner_attach, | ||
| 1651 | /* parameter for the MPEG2-data transfer */ | ||
| 1652 | .stream = { | ||
| 1653 | .type = USB_BULK, | ||
| 1654 | .count = 5, | ||
| 1655 | .endpoint = 0x02, | ||
| 1656 | .u = { | ||
| 1657 | .bulk = { | ||
| 1658 | .buffersize = 8192, | ||
| 1659 | } | ||
| 1660 | } | ||
| 1661 | }, | ||
| 1662 | }, | ||
| 1663 | }, | ||
| 1664 | |||
| 1665 | .power_ctrl = cxusb_power_ctrl, | ||
| 1666 | |||
| 1667 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1668 | |||
| 1669 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1670 | |||
| 1671 | .rc.legacy = { | ||
| 1672 | .rc_interval = 100, | ||
| 1673 | .rc_map_table = rc_map_dvico_mce_table, | ||
| 1674 | .rc_map_size = ARRAY_SIZE(rc_map_dvico_mce_table), | ||
| 1675 | .rc_query = cxusb_bluebird2_rc_query, | ||
| 1676 | }, | ||
| 1677 | |||
| 1678 | .num_device_descs = 1, | ||
| 1679 | .devices = { | ||
| 1680 | { "DViCO FusionHDTV DVB-T Dual Digital 4", | ||
| 1681 | { NULL }, | ||
| 1682 | { &cxusb_table[13], NULL }, | ||
| 1683 | }, | ||
| 1684 | } | ||
| 1685 | }; | ||
| 1686 | |||
| 1687 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = { | ||
| 1688 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1689 | |||
| 1690 | .usb_ctrl = CYPRESS_FX2, | ||
| 1691 | .identify_state = bluebird_fx2_identify_state, | ||
| 1692 | |||
| 1693 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1694 | |||
| 1695 | .num_adapters = 1, | ||
| 1696 | .adapter = { | ||
| 1697 | { | ||
| 1698 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 1699 | .frontend_attach = cxusb_nano2_frontend_attach, | ||
| 1700 | .tuner_attach = cxusb_dvico_xc3028_tuner_attach, | ||
| 1701 | /* parameter for the MPEG2-data transfer */ | ||
| 1702 | .stream = { | ||
| 1703 | .type = USB_BULK, | ||
| 1704 | .count = 5, | ||
| 1705 | .endpoint = 0x02, | ||
| 1706 | .u = { | ||
| 1707 | .bulk = { | ||
| 1708 | .buffersize = 8192, | ||
| 1709 | } | ||
| 1710 | } | ||
| 1711 | }, | ||
| 1712 | }, | ||
| 1713 | }, | ||
| 1714 | |||
| 1715 | .power_ctrl = cxusb_nano2_power_ctrl, | ||
| 1716 | |||
| 1717 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1718 | |||
| 1719 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1720 | |||
| 1721 | .rc.legacy = { | ||
| 1722 | .rc_interval = 100, | ||
| 1723 | .rc_map_table = rc_map_dvico_portable_table, | ||
| 1724 | .rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table), | ||
| 1725 | .rc_query = cxusb_bluebird2_rc_query, | ||
| 1726 | }, | ||
| 1727 | |||
| 1728 | .num_device_descs = 1, | ||
| 1729 | .devices = { | ||
| 1730 | { "DViCO FusionHDTV DVB-T NANO2", | ||
| 1731 | { NULL }, | ||
| 1732 | { &cxusb_table[14], NULL }, | ||
| 1733 | }, | ||
| 1734 | } | ||
| 1735 | }; | ||
| 1736 | |||
| 1737 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties = { | ||
| 1738 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1739 | |||
| 1740 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1741 | .firmware = "dvb-usb-bluebird-02.fw", | ||
| 1742 | .download_firmware = bluebird_patch_dvico_firmware_download, | ||
| 1743 | .identify_state = bluebird_fx2_identify_state, | ||
| 1744 | |||
| 1745 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1746 | |||
| 1747 | .num_adapters = 1, | ||
| 1748 | .adapter = { | ||
| 1749 | { | ||
| 1750 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 1751 | .frontend_attach = cxusb_nano2_frontend_attach, | ||
| 1752 | .tuner_attach = cxusb_dvico_xc3028_tuner_attach, | ||
| 1753 | /* parameter for the MPEG2-data transfer */ | ||
| 1754 | .stream = { | ||
| 1755 | .type = USB_BULK, | ||
| 1756 | .count = 5, | ||
| 1757 | .endpoint = 0x02, | ||
| 1758 | .u = { | ||
| 1759 | .bulk = { | ||
| 1760 | .buffersize = 8192, | ||
| 1761 | } | ||
| 1762 | } | ||
| 1763 | }, | ||
| 1764 | }, | ||
| 1765 | }, | ||
| 1766 | |||
| 1767 | .power_ctrl = cxusb_nano2_power_ctrl, | ||
| 1768 | |||
| 1769 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1770 | |||
| 1771 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1772 | |||
| 1773 | .rc.legacy = { | ||
| 1774 | .rc_interval = 100, | ||
| 1775 | .rc_map_table = rc_map_dvico_portable_table, | ||
| 1776 | .rc_map_size = ARRAY_SIZE(rc_map_dvico_portable_table), | ||
| 1777 | .rc_query = cxusb_rc_query, | ||
| 1778 | }, | ||
| 1779 | |||
| 1780 | .num_device_descs = 1, | ||
| 1781 | .devices = { | ||
| 1782 | { "DViCO FusionHDTV DVB-T NANO2 w/o firmware", | ||
| 1783 | { &cxusb_table[14], NULL }, | ||
| 1784 | { &cxusb_table[15], NULL }, | ||
| 1785 | }, | ||
| 1786 | } | ||
| 1787 | }; | ||
| 1788 | |||
| 1789 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties = { | ||
| 1790 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1791 | |||
| 1792 | .usb_ctrl = CYPRESS_FX2, | ||
| 1793 | |||
| 1794 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1795 | |||
| 1796 | .num_adapters = 1, | ||
| 1797 | .adapter = { | ||
| 1798 | { | ||
| 1799 | .streaming_ctrl = cxusb_aver_streaming_ctrl, | ||
| 1800 | .frontend_attach = cxusb_aver_lgdt3303_frontend_attach, | ||
| 1801 | .tuner_attach = cxusb_mxl5003s_tuner_attach, | ||
| 1802 | /* parameter for the MPEG2-data transfer */ | ||
| 1803 | .stream = { | ||
| 1804 | .type = USB_BULK, | ||
| 1805 | .count = 5, | ||
| 1806 | .endpoint = 0x04, | ||
| 1807 | .u = { | ||
| 1808 | .bulk = { | ||
| 1809 | .buffersize = 8192, | ||
| 1810 | } | ||
| 1811 | } | ||
| 1812 | }, | ||
| 1813 | |||
| 1814 | }, | ||
| 1815 | }, | ||
| 1816 | .power_ctrl = cxusb_aver_power_ctrl, | ||
| 1817 | |||
| 1818 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1819 | |||
| 1820 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1821 | |||
| 1822 | .num_device_descs = 1, | ||
| 1823 | .devices = { | ||
| 1824 | { "AVerMedia AVerTVHD Volar (A868R)", | ||
| 1825 | { NULL }, | ||
| 1826 | { &cxusb_table[16], NULL }, | ||
| 1827 | }, | ||
| 1828 | } | ||
| 1829 | }; | ||
| 1830 | |||
| 1831 | static | ||
| 1832 | struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { | ||
| 1833 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1834 | |||
| 1835 | .usb_ctrl = CYPRESS_FX2, | ||
| 1836 | |||
| 1837 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1838 | |||
| 1839 | .num_adapters = 1, | ||
| 1840 | .adapter = { | ||
| 1841 | { | ||
| 1842 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 1843 | .frontend_attach = cxusb_dualdig4_rev2_frontend_attach, | ||
| 1844 | .tuner_attach = cxusb_dualdig4_rev2_tuner_attach, | ||
| 1845 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
| 1846 | /* parameter for the MPEG2-data transfer */ | ||
| 1847 | .stream = { | ||
| 1848 | .type = USB_BULK, | ||
| 1849 | .count = 7, | ||
| 1850 | .endpoint = 0x02, | ||
| 1851 | .u = { | ||
| 1852 | .bulk = { | ||
| 1853 | .buffersize = 4096, | ||
| 1854 | } | ||
| 1855 | } | ||
| 1856 | }, | ||
| 1857 | }, | ||
| 1858 | }, | ||
| 1859 | |||
| 1860 | .power_ctrl = cxusb_bluebird_power_ctrl, | ||
| 1861 | |||
| 1862 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1863 | |||
| 1864 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1865 | |||
| 1866 | .rc.legacy = { | ||
| 1867 | .rc_interval = 100, | ||
| 1868 | .rc_map_table = rc_map_dvico_mce_table, | ||
| 1869 | .rc_map_size = ARRAY_SIZE(rc_map_dvico_mce_table), | ||
| 1870 | .rc_query = cxusb_rc_query, | ||
| 1871 | }, | ||
| 1872 | |||
| 1873 | .num_device_descs = 1, | ||
| 1874 | .devices = { | ||
| 1875 | { "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)", | ||
| 1876 | { NULL }, | ||
| 1877 | { &cxusb_table[17], NULL }, | ||
| 1878 | }, | ||
| 1879 | } | ||
| 1880 | }; | ||
| 1881 | |||
| 1882 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties = { | ||
| 1883 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1884 | |||
| 1885 | .usb_ctrl = CYPRESS_FX2, | ||
| 1886 | |||
| 1887 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1888 | |||
| 1889 | .num_adapters = 1, | ||
| 1890 | .adapter = { | ||
| 1891 | { | ||
| 1892 | .streaming_ctrl = cxusb_d680_dmb_streaming_ctrl, | ||
| 1893 | .frontend_attach = cxusb_d680_dmb_frontend_attach, | ||
| 1894 | .tuner_attach = cxusb_d680_dmb_tuner_attach, | ||
| 1895 | |||
| 1896 | /* parameter for the MPEG2-data transfer */ | ||
| 1897 | .stream = { | ||
| 1898 | .type = USB_BULK, | ||
| 1899 | .count = 5, | ||
| 1900 | .endpoint = 0x02, | ||
| 1901 | .u = { | ||
| 1902 | .bulk = { | ||
| 1903 | .buffersize = 8192, | ||
| 1904 | } | ||
| 1905 | } | ||
| 1906 | }, | ||
| 1907 | }, | ||
| 1908 | }, | ||
| 1909 | |||
| 1910 | .power_ctrl = cxusb_d680_dmb_power_ctrl, | ||
| 1911 | |||
| 1912 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1913 | |||
| 1914 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1915 | |||
| 1916 | .rc.legacy = { | ||
| 1917 | .rc_interval = 100, | ||
| 1918 | .rc_map_table = rc_map_d680_dmb_table, | ||
| 1919 | .rc_map_size = ARRAY_SIZE(rc_map_d680_dmb_table), | ||
| 1920 | .rc_query = cxusb_d680_dmb_rc_query, | ||
| 1921 | }, | ||
| 1922 | |||
| 1923 | .num_device_descs = 1, | ||
| 1924 | .devices = { | ||
| 1925 | { | ||
| 1926 | "Conexant DMB-TH Stick", | ||
| 1927 | { NULL }, | ||
| 1928 | { &cxusb_table[18], NULL }, | ||
| 1929 | }, | ||
| 1930 | } | ||
| 1931 | }; | ||
| 1932 | |||
| 1933 | static struct dvb_usb_device_properties cxusb_mygica_d689_properties = { | ||
| 1934 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1935 | |||
| 1936 | .usb_ctrl = CYPRESS_FX2, | ||
| 1937 | |||
| 1938 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 1939 | |||
| 1940 | .num_adapters = 1, | ||
| 1941 | .adapter = { | ||
| 1942 | { | ||
| 1943 | .streaming_ctrl = cxusb_d680_dmb_streaming_ctrl, | ||
| 1944 | .frontend_attach = cxusb_mygica_d689_frontend_attach, | ||
| 1945 | .tuner_attach = cxusb_mygica_d689_tuner_attach, | ||
| 1946 | |||
| 1947 | /* parameter for the MPEG2-data transfer */ | ||
| 1948 | .stream = { | ||
| 1949 | .type = USB_BULK, | ||
| 1950 | .count = 5, | ||
| 1951 | .endpoint = 0x02, | ||
| 1952 | .u = { | ||
| 1953 | .bulk = { | ||
| 1954 | .buffersize = 8192, | ||
| 1955 | } | ||
| 1956 | } | ||
| 1957 | }, | ||
| 1958 | }, | ||
| 1959 | }, | ||
| 1960 | |||
| 1961 | .power_ctrl = cxusb_d680_dmb_power_ctrl, | ||
| 1962 | |||
| 1963 | .i2c_algo = &cxusb_i2c_algo, | ||
| 1964 | |||
| 1965 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1966 | |||
| 1967 | .rc.legacy = { | ||
| 1968 | .rc_interval = 100, | ||
| 1969 | .rc_map_table = rc_map_d680_dmb_table, | ||
| 1970 | .rc_map_size = ARRAY_SIZE(rc_map_d680_dmb_table), | ||
| 1971 | .rc_query = cxusb_d680_dmb_rc_query, | ||
| 1972 | }, | ||
| 1973 | |||
| 1974 | .num_device_descs = 1, | ||
| 1975 | .devices = { | ||
| 1976 | { | ||
| 1977 | "Mygica D689 DMB-TH", | ||
| 1978 | { NULL }, | ||
| 1979 | { &cxusb_table[19], NULL }, | ||
| 1980 | }, | ||
| 1981 | } | ||
| 1982 | }; | ||
| 1983 | |||
| 1984 | static struct usb_driver cxusb_driver = { | ||
| 1985 | .name = "dvb_usb_cxusb", | ||
| 1986 | .probe = cxusb_probe, | ||
| 1987 | .disconnect = dvb_usb_device_exit, | ||
| 1988 | .id_table = cxusb_table, | ||
| 1989 | }; | ||
| 1990 | |||
| 1991 | /* module stuff */ | ||
| 1992 | static int __init cxusb_module_init(void) | ||
| 1993 | { | ||
| 1994 | int result; | ||
| 1995 | if ((result = usb_register(&cxusb_driver))) { | ||
| 1996 | err("usb_register failed. Error number %d",result); | ||
| 1997 | return result; | ||
| 1998 | } | ||
| 1999 | |||
| 2000 | return 0; | ||
| 2001 | } | ||
| 2002 | |||
| 2003 | static void __exit cxusb_module_exit(void) | ||
| 2004 | { | ||
| 2005 | /* deregister this driver from the USB subsystem */ | ||
| 2006 | usb_deregister(&cxusb_driver); | ||
| 2007 | } | ||
| 2008 | |||
| 2009 | module_init (cxusb_module_init); | ||
| 2010 | module_exit (cxusb_module_exit); | ||
| 2011 | |||
| 2012 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 2013 | MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); | ||
| 2014 | MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); | ||
| 2015 | MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); | ||
| 2016 | MODULE_VERSION("1.0-alpha"); | ||
| 2017 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h new file mode 100644 index 00000000000..1a51eafd31b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cxusb.h | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | #ifndef _DVB_USB_CXUSB_H_ | ||
| 2 | #define _DVB_USB_CXUSB_H_ | ||
| 3 | |||
| 4 | #define DVB_USB_LOG_PREFIX "cxusb" | ||
| 5 | #include "dvb-usb.h" | ||
| 6 | |||
| 7 | /* usb commands - some of it are guesses, don't have a reference yet */ | ||
| 8 | #define CMD_BLUEBIRD_GPIO_RW 0x05 | ||
| 9 | |||
| 10 | #define CMD_I2C_WRITE 0x08 | ||
| 11 | #define CMD_I2C_READ 0x09 | ||
| 12 | |||
| 13 | #define CMD_GPIO_READ 0x0d | ||
| 14 | #define CMD_GPIO_WRITE 0x0e | ||
| 15 | #define GPIO_TUNER 0x02 | ||
| 16 | |||
| 17 | #define CMD_POWER_OFF 0xdc | ||
| 18 | #define CMD_POWER_ON 0xde | ||
| 19 | |||
| 20 | #define CMD_STREAMING_ON 0x36 | ||
| 21 | #define CMD_STREAMING_OFF 0x37 | ||
| 22 | |||
| 23 | #define CMD_AVER_STREAM_ON 0x18 | ||
| 24 | #define CMD_AVER_STREAM_OFF 0x19 | ||
| 25 | |||
| 26 | #define CMD_GET_IR_CODE 0x47 | ||
| 27 | |||
| 28 | #define CMD_ANALOG 0x50 | ||
| 29 | #define CMD_DIGITAL 0x51 | ||
| 30 | |||
| 31 | struct cxusb_state { | ||
| 32 | u8 gpio_write_state[3]; | ||
| 33 | }; | ||
| 34 | |||
| 35 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h new file mode 100644 index 00000000000..9bd6d51b3b9 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dib0700.h | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | /* Linux driver for devices based on the DiBcom DiB0700 USB bridge | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify it | ||
| 4 | * under the terms of the GNU General Public License as published by the Free | ||
| 5 | * Software Foundation, version 2. | ||
| 6 | * | ||
| 7 | * Copyright (C) 2005-6 DiBcom, SA | ||
| 8 | */ | ||
| 9 | #ifndef _DIB0700_H_ | ||
| 10 | #define _DIB0700_H_ | ||
| 11 | |||
| 12 | #define DVB_USB_LOG_PREFIX "dib0700" | ||
| 13 | #include "dvb-usb.h" | ||
| 14 | |||
| 15 | #include "dib07x0.h" | ||
| 16 | |||
| 17 | extern int dvb_usb_dib0700_debug; | ||
| 18 | #define deb_info(args...) dprintk(dvb_usb_dib0700_debug,0x01,args) | ||
| 19 | #define deb_fw(args...) dprintk(dvb_usb_dib0700_debug,0x02,args) | ||
| 20 | #define deb_fwdata(args...) dprintk(dvb_usb_dib0700_debug,0x04,args) | ||
| 21 | #define deb_data(args...) dprintk(dvb_usb_dib0700_debug,0x08,args) | ||
| 22 | |||
| 23 | #define REQUEST_SET_USB_XFER_LEN 0x0 /* valid only for firmware version */ | ||
| 24 | /* higher than 1.21 */ | ||
| 25 | #define REQUEST_I2C_READ 0x2 | ||
| 26 | #define REQUEST_I2C_WRITE 0x3 | ||
| 27 | #define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */ | ||
| 28 | #define REQUEST_JUMPRAM 0x8 | ||
| 29 | #define REQUEST_SET_CLOCK 0xB | ||
| 30 | #define REQUEST_SET_GPIO 0xC | ||
| 31 | #define REQUEST_ENABLE_VIDEO 0xF | ||
| 32 | // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) | ||
| 33 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) | ||
| 34 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) | ||
| 35 | #define REQUEST_SET_I2C_PARAM 0x10 | ||
| 36 | #define REQUEST_SET_RC 0x11 | ||
| 37 | #define REQUEST_NEW_I2C_READ 0x12 | ||
| 38 | #define REQUEST_NEW_I2C_WRITE 0x13 | ||
| 39 | #define REQUEST_GET_VERSION 0x15 | ||
| 40 | |||
| 41 | struct dib0700_state { | ||
| 42 | u8 channel_state; | ||
| 43 | u16 mt2060_if1[2]; | ||
| 44 | u8 rc_toggle; | ||
| 45 | u8 rc_counter; | ||
| 46 | u8 is_dib7000pc; | ||
| 47 | u8 fw_use_new_i2c_api; | ||
| 48 | u8 disable_streaming_master_mode; | ||
| 49 | u32 fw_version; | ||
| 50 | u32 nb_packet_buffer_size; | ||
| 51 | u8 buf[255]; | ||
| 52 | }; | ||
| 53 | |||
| 54 | extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, | ||
| 55 | u32 *romversion, u32 *ramversion, u32 *fwtype); | ||
| 56 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); | ||
| 57 | extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); | ||
| 58 | extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen); | ||
| 59 | extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); | ||
| 60 | extern int dib0700_rc_setup(struct dvb_usb_device *d); | ||
| 61 | extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); | ||
| 62 | extern struct i2c_algorithm dib0700_i2c_algo; | ||
| 63 | extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, | ||
| 64 | struct dvb_usb_device_description **desc, int *cold); | ||
| 65 | extern int dib0700_change_protocol(struct rc_dev *dev, u64 rc_type); | ||
| 66 | extern int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz); | ||
| 67 | |||
| 68 | extern int dib0700_device_count; | ||
| 69 | extern int dvb_usb_dib0700_ir_proto; | ||
| 70 | extern struct dvb_usb_device_properties dib0700_devices[]; | ||
| 71 | extern struct usb_device_id dib0700_usb_id_table[]; | ||
| 72 | |||
| 73 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c new file mode 100644 index 00000000000..a224e94325b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c | |||
| @@ -0,0 +1,860 @@ | |||
| 1 | /* Linux driver for devices based on the DiBcom DiB0700 USB bridge | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify it | ||
| 4 | * under the terms of the GNU General Public License as published by the Free | ||
| 5 | * Software Foundation, version 2. | ||
| 6 | * | ||
| 7 | * Copyright (C) 2005-6 DiBcom, SA | ||
| 8 | */ | ||
| 9 | #include "dib0700.h" | ||
| 10 | |||
| 11 | /* debug */ | ||
| 12 | int dvb_usb_dib0700_debug; | ||
| 13 | module_param_named(debug,dvb_usb_dib0700_debug, int, 0644); | ||
| 14 | MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 15 | |||
| 16 | static int nb_packet_buffer_size = 21; | ||
| 17 | module_param(nb_packet_buffer_size, int, 0644); | ||
| 18 | MODULE_PARM_DESC(nb_packet_buffer_size, | ||
| 19 | "Set the dib0700 driver data buffer size. This parameter " | ||
| 20 | "corresponds to the number of TS packets. The actual size of " | ||
| 21 | "the data buffer corresponds to this parameter " | ||
| 22 | "multiplied by 188 (default: 21)"); | ||
| 23 | |||
| 24 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 25 | |||
| 26 | |||
| 27 | int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, | ||
| 28 | u32 *romversion, u32 *ramversion, u32 *fwtype) | ||
| 29 | { | ||
| 30 | struct dib0700_state *st = d->priv; | ||
| 31 | int ret; | ||
| 32 | |||
| 33 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
| 34 | deb_info("could not acquire lock"); | ||
| 35 | return 0; | ||
| 36 | } | ||
| 37 | |||
| 38 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), | ||
| 39 | REQUEST_GET_VERSION, | ||
| 40 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | ||
| 41 | st->buf, 16, USB_CTRL_GET_TIMEOUT); | ||
| 42 | if (hwversion != NULL) | ||
| 43 | *hwversion = (st->buf[0] << 24) | (st->buf[1] << 16) | | ||
| 44 | (st->buf[2] << 8) | st->buf[3]; | ||
| 45 | if (romversion != NULL) | ||
| 46 | *romversion = (st->buf[4] << 24) | (st->buf[5] << 16) | | ||
| 47 | (st->buf[6] << 8) | st->buf[7]; | ||
| 48 | if (ramversion != NULL) | ||
| 49 | *ramversion = (st->buf[8] << 24) | (st->buf[9] << 16) | | ||
| 50 | (st->buf[10] << 8) | st->buf[11]; | ||
| 51 | if (fwtype != NULL) | ||
| 52 | *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | | ||
| 53 | (st->buf[14] << 8) | st->buf[15]; | ||
| 54 | mutex_unlock(&d->usb_mutex); | ||
| 55 | return ret; | ||
| 56 | } | ||
| 57 | |||
| 58 | /* expecting rx buffer: request data[0] data[1] ... data[2] */ | ||
| 59 | static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) | ||
| 60 | { | ||
| 61 | int status; | ||
| 62 | |||
| 63 | deb_data(">>> "); | ||
| 64 | debug_dump(tx, txlen, deb_data); | ||
| 65 | |||
| 66 | status = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0), | ||
| 67 | tx[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, tx, txlen, | ||
| 68 | USB_CTRL_GET_TIMEOUT); | ||
| 69 | |||
| 70 | if (status != txlen) | ||
| 71 | deb_data("ep 0 write error (status = %d, len: %d)\n",status,txlen); | ||
| 72 | |||
| 73 | return status < 0 ? status : 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | /* expecting tx buffer: request data[0] ... data[n] (n <= 4) */ | ||
| 77 | int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen) | ||
| 78 | { | ||
| 79 | u16 index, value; | ||
| 80 | int status; | ||
| 81 | |||
| 82 | if (txlen < 2) { | ||
| 83 | err("tx buffer length is smaller than 2. Makes no sense."); | ||
| 84 | return -EINVAL; | ||
| 85 | } | ||
| 86 | if (txlen > 4) { | ||
| 87 | err("tx buffer length is larger than 4. Not supported."); | ||
| 88 | return -EINVAL; | ||
| 89 | } | ||
| 90 | |||
| 91 | deb_data(">>> "); | ||
| 92 | debug_dump(tx,txlen,deb_data); | ||
| 93 | |||
| 94 | value = ((txlen - 2) << 8) | tx[1]; | ||
| 95 | index = 0; | ||
| 96 | if (txlen > 2) | ||
| 97 | index |= (tx[2] << 8); | ||
| 98 | if (txlen > 3) | ||
| 99 | index |= tx[3]; | ||
| 100 | |||
| 101 | status = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev,0), tx[0], | ||
| 102 | USB_TYPE_VENDOR | USB_DIR_IN, value, index, rx, rxlen, | ||
| 103 | USB_CTRL_GET_TIMEOUT); | ||
| 104 | |||
| 105 | if (status < 0) | ||
| 106 | deb_info("ep 0 read error (status = %d)\n",status); | ||
| 107 | |||
| 108 | deb_data("<<< "); | ||
| 109 | debug_dump(rx, rxlen, deb_data); | ||
| 110 | |||
| 111 | return status; /* length in case of success */ | ||
| 112 | } | ||
| 113 | |||
| 114 | int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) | ||
| 115 | { | ||
| 116 | struct dib0700_state *st = d->priv; | ||
| 117 | int ret; | ||
| 118 | |||
| 119 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
| 120 | deb_info("could not acquire lock"); | ||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | st->buf[0] = REQUEST_SET_GPIO; | ||
| 125 | st->buf[1] = gpio; | ||
| 126 | st->buf[2] = ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6); | ||
| 127 | |||
| 128 | ret = dib0700_ctrl_wr(d, st->buf, 3); | ||
| 129 | |||
| 130 | mutex_unlock(&d->usb_mutex); | ||
| 131 | return ret; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) | ||
| 135 | { | ||
| 136 | struct dib0700_state *st = d->priv; | ||
| 137 | int ret; | ||
| 138 | |||
| 139 | if (st->fw_version >= 0x10201) { | ||
| 140 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
| 141 | deb_info("could not acquire lock"); | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | st->buf[0] = REQUEST_SET_USB_XFER_LEN; | ||
| 146 | st->buf[1] = (nb_ts_packets >> 8) & 0xff; | ||
| 147 | st->buf[2] = nb_ts_packets & 0xff; | ||
| 148 | |||
| 149 | deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); | ||
| 150 | |||
| 151 | ret = dib0700_ctrl_wr(d, st->buf, 3); | ||
| 152 | mutex_unlock(&d->usb_mutex); | ||
| 153 | } else { | ||
| 154 | deb_info("this firmware does not allow to change the USB xfer len\n"); | ||
| 155 | ret = -EIO; | ||
| 156 | } | ||
| 157 | |||
| 158 | return ret; | ||
| 159 | } | ||
| 160 | |||
| 161 | /* | ||
| 162 | * I2C master xfer function (supported in 1.20 firmware) | ||
| 163 | */ | ||
| 164 | static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, | ||
| 165 | int num) | ||
| 166 | { | ||
| 167 | /* The new i2c firmware messages are more reliable and in particular | ||
| 168 | properly support i2c read calls not preceded by a write */ | ||
| 169 | |||
| 170 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 171 | struct dib0700_state *st = d->priv; | ||
| 172 | uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */ | ||
| 173 | uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */ | ||
| 174 | uint8_t en_start = 0; | ||
| 175 | uint8_t en_stop = 0; | ||
| 176 | int result, i; | ||
| 177 | |||
| 178 | /* Ensure nobody else hits the i2c bus while we're sending our | ||
| 179 | sequence of messages, (such as the remote control thread) */ | ||
| 180 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 181 | return -EAGAIN; | ||
| 182 | |||
| 183 | for (i = 0; i < num; i++) { | ||
| 184 | if (i == 0) { | ||
| 185 | /* First message in the transaction */ | ||
| 186 | en_start = 1; | ||
| 187 | } else if (!(msg[i].flags & I2C_M_NOSTART)) { | ||
| 188 | /* Device supports repeated-start */ | ||
| 189 | en_start = 1; | ||
| 190 | } else { | ||
| 191 | /* Not the first packet and device doesn't support | ||
| 192 | repeated start */ | ||
| 193 | en_start = 0; | ||
| 194 | } | ||
| 195 | if (i == (num - 1)) { | ||
| 196 | /* Last message in the transaction */ | ||
| 197 | en_stop = 1; | ||
| 198 | } | ||
| 199 | |||
| 200 | if (msg[i].flags & I2C_M_RD) { | ||
| 201 | /* Read request */ | ||
| 202 | u16 index, value; | ||
| 203 | uint8_t i2c_dest; | ||
| 204 | |||
| 205 | i2c_dest = (msg[i].addr << 1); | ||
| 206 | value = ((en_start << 7) | (en_stop << 6) | | ||
| 207 | (msg[i].len & 0x3F)) << 8 | i2c_dest; | ||
| 208 | /* I2C ctrl + FE bus; */ | ||
| 209 | index = ((gen_mode << 6) & 0xC0) | | ||
| 210 | ((bus_mode << 4) & 0x30); | ||
| 211 | |||
| 212 | result = usb_control_msg(d->udev, | ||
| 213 | usb_rcvctrlpipe(d->udev, 0), | ||
| 214 | REQUEST_NEW_I2C_READ, | ||
| 215 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
| 216 | value, index, msg[i].buf, | ||
| 217 | msg[i].len, | ||
| 218 | USB_CTRL_GET_TIMEOUT); | ||
| 219 | if (result < 0) { | ||
| 220 | deb_info("i2c read error (status = %d)\n", result); | ||
| 221 | break; | ||
| 222 | } | ||
| 223 | |||
| 224 | deb_data("<<< "); | ||
| 225 | debug_dump(msg[i].buf, msg[i].len, deb_data); | ||
| 226 | |||
| 227 | } else { | ||
| 228 | /* Write request */ | ||
| 229 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
| 230 | deb_info("could not acquire lock"); | ||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | st->buf[0] = REQUEST_NEW_I2C_WRITE; | ||
| 234 | st->buf[1] = msg[i].addr << 1; | ||
| 235 | st->buf[2] = (en_start << 7) | (en_stop << 6) | | ||
| 236 | (msg[i].len & 0x3F); | ||
| 237 | /* I2C ctrl + FE bus; */ | ||
| 238 | st->buf[3] = ((gen_mode << 6) & 0xC0) | | ||
| 239 | ((bus_mode << 4) & 0x30); | ||
| 240 | /* The Actual i2c payload */ | ||
| 241 | memcpy(&st->buf[4], msg[i].buf, msg[i].len); | ||
| 242 | |||
| 243 | deb_data(">>> "); | ||
| 244 | debug_dump(st->buf, msg[i].len + 4, deb_data); | ||
| 245 | |||
| 246 | result = usb_control_msg(d->udev, | ||
| 247 | usb_sndctrlpipe(d->udev, 0), | ||
| 248 | REQUEST_NEW_I2C_WRITE, | ||
| 249 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 250 | 0, 0, st->buf, msg[i].len + 4, | ||
| 251 | USB_CTRL_GET_TIMEOUT); | ||
| 252 | mutex_unlock(&d->usb_mutex); | ||
| 253 | if (result < 0) { | ||
| 254 | deb_info("i2c write error (status = %d)\n", result); | ||
| 255 | break; | ||
| 256 | } | ||
| 257 | } | ||
| 258 | } | ||
| 259 | mutex_unlock(&d->i2c_mutex); | ||
| 260 | return i; | ||
| 261 | } | ||
| 262 | |||
| 263 | /* | ||
| 264 | * I2C master xfer function (pre-1.20 firmware) | ||
| 265 | */ | ||
| 266 | static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, | ||
| 267 | struct i2c_msg *msg, int num) | ||
| 268 | { | ||
| 269 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 270 | struct dib0700_state *st = d->priv; | ||
| 271 | int i,len; | ||
| 272 | |||
| 273 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 274 | return -EAGAIN; | ||
| 275 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
| 276 | deb_info("could not acquire lock"); | ||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | for (i = 0; i < num; i++) { | ||
| 281 | /* fill in the address */ | ||
| 282 | st->buf[1] = msg[i].addr << 1; | ||
| 283 | /* fill the buffer */ | ||
| 284 | memcpy(&st->buf[2], msg[i].buf, msg[i].len); | ||
| 285 | |||
| 286 | /* write/read request */ | ||
| 287 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
| 288 | st->buf[0] = REQUEST_I2C_READ; | ||
| 289 | st->buf[1] |= 1; | ||
| 290 | |||
| 291 | /* special thing in the current firmware: when length is zero the read-failed */ | ||
| 292 | len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2, | ||
| 293 | msg[i+1].buf, msg[i+1].len); | ||
| 294 | if (len <= 0) { | ||
| 295 | deb_info("I2C read failed on address 0x%02x\n", | ||
| 296 | msg[i].addr); | ||
| 297 | break; | ||
| 298 | } | ||
| 299 | |||
| 300 | msg[i+1].len = len; | ||
| 301 | |||
| 302 | i++; | ||
| 303 | } else { | ||
| 304 | st->buf[0] = REQUEST_I2C_WRITE; | ||
| 305 | if (dib0700_ctrl_wr(d, st->buf, msg[i].len + 2) < 0) | ||
| 306 | break; | ||
| 307 | } | ||
| 308 | } | ||
| 309 | mutex_unlock(&d->usb_mutex); | ||
| 310 | mutex_unlock(&d->i2c_mutex); | ||
| 311 | |||
| 312 | return i; | ||
| 313 | } | ||
| 314 | |||
| 315 | static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | ||
| 316 | int num) | ||
| 317 | { | ||
| 318 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 319 | struct dib0700_state *st = d->priv; | ||
| 320 | |||
| 321 | if (st->fw_use_new_i2c_api == 1) { | ||
| 322 | /* User running at least fw 1.20 */ | ||
| 323 | return dib0700_i2c_xfer_new(adap, msg, num); | ||
| 324 | } else { | ||
| 325 | /* Use legacy calls */ | ||
| 326 | return dib0700_i2c_xfer_legacy(adap, msg, num); | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | static u32 dib0700_i2c_func(struct i2c_adapter *adapter) | ||
| 331 | { | ||
| 332 | return I2C_FUNC_I2C; | ||
| 333 | } | ||
| 334 | |||
| 335 | struct i2c_algorithm dib0700_i2c_algo = { | ||
| 336 | .master_xfer = dib0700_i2c_xfer, | ||
| 337 | .functionality = dib0700_i2c_func, | ||
| 338 | }; | ||
| 339 | |||
| 340 | int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, | ||
| 341 | struct dvb_usb_device_description **desc, int *cold) | ||
| 342 | { | ||
| 343 | s16 ret; | ||
| 344 | u8 *b; | ||
| 345 | |||
| 346 | b = kmalloc(16, GFP_KERNEL); | ||
| 347 | if (!b) | ||
| 348 | return -ENOMEM; | ||
| 349 | |||
| 350 | |||
| 351 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 352 | REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT); | ||
| 353 | |||
| 354 | deb_info("FW GET_VERSION length: %d\n",ret); | ||
| 355 | |||
| 356 | *cold = ret <= 0; | ||
| 357 | deb_info("cold: %d\n", *cold); | ||
| 358 | |||
| 359 | kfree(b); | ||
| 360 | return 0; | ||
| 361 | } | ||
| 362 | |||
| 363 | static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, | ||
| 364 | u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv, | ||
| 365 | u16 pll_loopdiv, u16 free_div, u16 dsuScaler) | ||
| 366 | { | ||
| 367 | struct dib0700_state *st = d->priv; | ||
| 368 | int ret; | ||
| 369 | |||
| 370 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
| 371 | deb_info("could not acquire lock"); | ||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | |||
| 375 | st->buf[0] = REQUEST_SET_CLOCK; | ||
| 376 | st->buf[1] = (en_pll << 7) | (pll_src << 6) | | ||
| 377 | (pll_range << 5) | (clock_gpio3 << 4); | ||
| 378 | st->buf[2] = (pll_prediv >> 8) & 0xff; /* MSB */ | ||
| 379 | st->buf[3] = pll_prediv & 0xff; /* LSB */ | ||
| 380 | st->buf[4] = (pll_loopdiv >> 8) & 0xff; /* MSB */ | ||
| 381 | st->buf[5] = pll_loopdiv & 0xff; /* LSB */ | ||
| 382 | st->buf[6] = (free_div >> 8) & 0xff; /* MSB */ | ||
| 383 | st->buf[7] = free_div & 0xff; /* LSB */ | ||
| 384 | st->buf[8] = (dsuScaler >> 8) & 0xff; /* MSB */ | ||
| 385 | st->buf[9] = dsuScaler & 0xff; /* LSB */ | ||
| 386 | |||
| 387 | ret = dib0700_ctrl_wr(d, st->buf, 10); | ||
| 388 | mutex_unlock(&d->usb_mutex); | ||
| 389 | |||
| 390 | return ret; | ||
| 391 | } | ||
| 392 | |||
| 393 | int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) | ||
| 394 | { | ||
| 395 | struct dib0700_state *st = d->priv; | ||
| 396 | u16 divider; | ||
| 397 | int ret; | ||
| 398 | |||
| 399 | if (scl_kHz == 0) | ||
| 400 | return -EINVAL; | ||
| 401 | |||
| 402 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
| 403 | deb_info("could not acquire lock"); | ||
| 404 | return 0; | ||
| 405 | } | ||
| 406 | |||
| 407 | st->buf[0] = REQUEST_SET_I2C_PARAM; | ||
| 408 | divider = (u16) (30000 / scl_kHz); | ||
| 409 | st->buf[1] = 0; | ||
| 410 | st->buf[2] = (u8) (divider >> 8); | ||
| 411 | st->buf[3] = (u8) (divider & 0xff); | ||
| 412 | divider = (u16) (72000 / scl_kHz); | ||
| 413 | st->buf[4] = (u8) (divider >> 8); | ||
| 414 | st->buf[5] = (u8) (divider & 0xff); | ||
| 415 | divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */ | ||
| 416 | st->buf[6] = (u8) (divider >> 8); | ||
| 417 | st->buf[7] = (u8) (divider & 0xff); | ||
| 418 | |||
| 419 | deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", | ||
| 420 | (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | | ||
| 421 | st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); | ||
| 422 | |||
| 423 | ret = dib0700_ctrl_wr(d, st->buf, 8); | ||
| 424 | mutex_unlock(&d->usb_mutex); | ||
| 425 | |||
| 426 | return ret; | ||
| 427 | } | ||
| 428 | |||
| 429 | |||
| 430 | int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3) | ||
| 431 | { | ||
| 432 | switch (clk_MHz) { | ||
| 433 | case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break; | ||
| 434 | default: return -EINVAL; | ||
| 435 | } | ||
| 436 | return 0; | ||
| 437 | } | ||
| 438 | |||
| 439 | static int dib0700_jumpram(struct usb_device *udev, u32 address) | ||
| 440 | { | ||
| 441 | int ret = 0, actlen; | ||
| 442 | u8 *buf; | ||
| 443 | |||
| 444 | buf = kmalloc(8, GFP_KERNEL); | ||
| 445 | if (!buf) | ||
| 446 | return -ENOMEM; | ||
| 447 | buf[0] = REQUEST_JUMPRAM; | ||
| 448 | buf[1] = 0; | ||
| 449 | buf[2] = 0; | ||
| 450 | buf[3] = 0; | ||
| 451 | buf[4] = (address >> 24) & 0xff; | ||
| 452 | buf[5] = (address >> 16) & 0xff; | ||
| 453 | buf[6] = (address >> 8) & 0xff; | ||
| 454 | buf[7] = address & 0xff; | ||
| 455 | |||
| 456 | if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) { | ||
| 457 | deb_fw("jumpram to 0x%x failed\n",address); | ||
| 458 | goto out; | ||
| 459 | } | ||
| 460 | if (actlen != 8) { | ||
| 461 | deb_fw("jumpram to 0x%x failed\n",address); | ||
| 462 | ret = -EIO; | ||
| 463 | goto out; | ||
| 464 | } | ||
| 465 | out: | ||
| 466 | kfree(buf); | ||
| 467 | return ret; | ||
| 468 | } | ||
| 469 | |||
| 470 | int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw) | ||
| 471 | { | ||
| 472 | struct hexline hx; | ||
| 473 | int pos = 0, ret, act_len, i, adap_num; | ||
| 474 | u8 *buf; | ||
| 475 | u32 fw_version; | ||
| 476 | |||
| 477 | buf = kmalloc(260, GFP_KERNEL); | ||
| 478 | if (!buf) | ||
| 479 | return -ENOMEM; | ||
| 480 | |||
| 481 | while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) { | ||
| 482 | deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n", | ||
| 483 | hx.addr, hx.len, hx.chk); | ||
| 484 | |||
| 485 | buf[0] = hx.len; | ||
| 486 | buf[1] = (hx.addr >> 8) & 0xff; | ||
| 487 | buf[2] = hx.addr & 0xff; | ||
| 488 | buf[3] = hx.type; | ||
| 489 | memcpy(&buf[4],hx.data,hx.len); | ||
| 490 | buf[4+hx.len] = hx.chk; | ||
| 491 | |||
| 492 | ret = usb_bulk_msg(udev, | ||
| 493 | usb_sndbulkpipe(udev, 0x01), | ||
| 494 | buf, | ||
| 495 | hx.len + 5, | ||
| 496 | &act_len, | ||
| 497 | 1000); | ||
| 498 | |||
| 499 | if (ret < 0) { | ||
| 500 | err("firmware download failed at %d with %d",pos,ret); | ||
| 501 | goto out; | ||
| 502 | } | ||
| 503 | } | ||
| 504 | |||
| 505 | if (ret == 0) { | ||
| 506 | /* start the firmware */ | ||
| 507 | if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) { | ||
| 508 | info("firmware started successfully."); | ||
| 509 | msleep(500); | ||
| 510 | } | ||
| 511 | } else | ||
| 512 | ret = -EIO; | ||
| 513 | |||
| 514 | /* the number of ts packet has to be at least 1 */ | ||
| 515 | if (nb_packet_buffer_size < 1) | ||
| 516 | nb_packet_buffer_size = 1; | ||
| 517 | |||
| 518 | /* get the fimware version */ | ||
| 519 | usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 520 | REQUEST_GET_VERSION, | ||
| 521 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | ||
| 522 | buf, 16, USB_CTRL_GET_TIMEOUT); | ||
| 523 | fw_version = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11]; | ||
| 524 | |||
| 525 | /* set the buffer size - DVB-USB is allocating URB buffers | ||
| 526 | * only after the firwmare download was successful */ | ||
| 527 | for (i = 0; i < dib0700_device_count; i++) { | ||
| 528 | for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters; | ||
| 529 | adap_num++) { | ||
| 530 | if (fw_version >= 0x10201) { | ||
| 531 | dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size; | ||
| 532 | } else { | ||
| 533 | /* for fw version older than 1.20.1, | ||
| 534 | * the buffersize has to be n times 512 */ | ||
| 535 | dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512; | ||
| 536 | if (dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize < 512) | ||
| 537 | dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 512; | ||
| 538 | } | ||
| 539 | } | ||
| 540 | } | ||
| 541 | out: | ||
| 542 | kfree(buf); | ||
| 543 | return ret; | ||
| 544 | } | ||
| 545 | |||
| 546 | int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 547 | { | ||
| 548 | struct dib0700_state *st = adap->dev->priv; | ||
| 549 | int ret; | ||
| 550 | |||
| 551 | if ((onoff != 0) && (st->fw_version >= 0x10201)) { | ||
| 552 | /* for firmware later than 1.20.1, | ||
| 553 | * the USB xfer length can be set */ | ||
| 554 | ret = dib0700_set_usb_xfer_len(adap->dev, | ||
| 555 | st->nb_packet_buffer_size); | ||
| 556 | if (ret < 0) { | ||
| 557 | deb_info("can not set the USB xfer len\n"); | ||
| 558 | return ret; | ||
| 559 | } | ||
| 560 | } | ||
| 561 | |||
| 562 | if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { | ||
| 563 | deb_info("could not acquire lock"); | ||
| 564 | return 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | st->buf[0] = REQUEST_ENABLE_VIDEO; | ||
| 568 | /* this bit gives a kind of command, | ||
| 569 | * rather than enabling something or not */ | ||
| 570 | st->buf[1] = (onoff << 4) | 0x00; | ||
| 571 | |||
| 572 | if (st->disable_streaming_master_mode == 1) | ||
| 573 | st->buf[2] = 0x00; | ||
| 574 | else | ||
| 575 | st->buf[2] = 0x01 << 4; /* Master mode */ | ||
| 576 | |||
| 577 | st->buf[3] = 0x00; | ||
| 578 | |||
| 579 | deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); | ||
| 580 | |||
| 581 | st->channel_state &= ~0x3; | ||
| 582 | if ((adap->stream.props.endpoint != 2) | ||
| 583 | && (adap->stream.props.endpoint != 3)) { | ||
| 584 | deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->stream.props.endpoint); | ||
| 585 | if (onoff) | ||
| 586 | st->channel_state |= 1 << (adap->id); | ||
| 587 | else | ||
| 588 | st->channel_state |= 1 << ~(adap->id); | ||
| 589 | } else { | ||
| 590 | if (onoff) | ||
| 591 | st->channel_state |= 1 << (adap->stream.props.endpoint-2); | ||
| 592 | else | ||
| 593 | st->channel_state |= 1 << (3-adap->stream.props.endpoint); | ||
| 594 | } | ||
| 595 | |||
| 596 | st->buf[2] |= st->channel_state; | ||
| 597 | |||
| 598 | deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); | ||
| 599 | |||
| 600 | ret = dib0700_ctrl_wr(adap->dev, st->buf, 4); | ||
| 601 | mutex_unlock(&adap->dev->usb_mutex); | ||
| 602 | |||
| 603 | return ret; | ||
| 604 | } | ||
| 605 | |||
| 606 | int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) | ||
| 607 | { | ||
| 608 | struct dvb_usb_device *d = rc->priv; | ||
| 609 | struct dib0700_state *st = d->priv; | ||
| 610 | int new_proto, ret; | ||
| 611 | |||
| 612 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
| 613 | deb_info("could not acquire lock"); | ||
| 614 | return 0; | ||
| 615 | } | ||
| 616 | |||
| 617 | st->buf[0] = REQUEST_SET_RC; | ||
| 618 | st->buf[1] = 0; | ||
| 619 | st->buf[2] = 0; | ||
| 620 | |||
| 621 | /* Set the IR mode */ | ||
| 622 | if (rc_type == RC_TYPE_RC5) | ||
| 623 | new_proto = 1; | ||
| 624 | else if (rc_type == RC_TYPE_NEC) | ||
| 625 | new_proto = 0; | ||
| 626 | else if (rc_type == RC_TYPE_RC6) { | ||
| 627 | if (st->fw_version < 0x10200) { | ||
| 628 | ret = -EINVAL; | ||
| 629 | goto out; | ||
| 630 | } | ||
| 631 | |||
| 632 | new_proto = 2; | ||
| 633 | } else { | ||
| 634 | ret = -EINVAL; | ||
| 635 | goto out; | ||
| 636 | } | ||
| 637 | |||
| 638 | st->buf[1] = new_proto; | ||
| 639 | |||
| 640 | ret = dib0700_ctrl_wr(d, st->buf, 3); | ||
| 641 | if (ret < 0) { | ||
| 642 | err("ir protocol setup failed"); | ||
| 643 | goto out; | ||
| 644 | } | ||
| 645 | |||
| 646 | d->props.rc.core.protocol = rc_type; | ||
| 647 | |||
| 648 | out: | ||
| 649 | mutex_unlock(&d->usb_mutex); | ||
| 650 | return ret; | ||
| 651 | } | ||
| 652 | |||
| 653 | /* Number of keypresses to ignore before start repeating */ | ||
| 654 | #define RC_REPEAT_DELAY_V1_20 10 | ||
| 655 | |||
| 656 | /* This is the structure of the RC response packet starting in firmware 1.20 */ | ||
| 657 | struct dib0700_rc_response { | ||
| 658 | u8 report_id; | ||
| 659 | u8 data_state; | ||
| 660 | union { | ||
| 661 | u16 system16; | ||
| 662 | struct { | ||
| 663 | u8 not_system; | ||
| 664 | u8 system; | ||
| 665 | }; | ||
| 666 | }; | ||
| 667 | u8 data; | ||
| 668 | u8 not_data; | ||
| 669 | }; | ||
| 670 | #define RC_MSG_SIZE_V1_20 6 | ||
| 671 | |||
| 672 | static void dib0700_rc_urb_completion(struct urb *purb) | ||
| 673 | { | ||
| 674 | struct dvb_usb_device *d = purb->context; | ||
| 675 | struct dib0700_rc_response *poll_reply; | ||
| 676 | u32 uninitialized_var(keycode); | ||
| 677 | u8 toggle; | ||
| 678 | |||
| 679 | deb_info("%s()\n", __func__); | ||
| 680 | if (d == NULL) | ||
| 681 | return; | ||
| 682 | |||
| 683 | if (d->rc_dev == NULL) { | ||
| 684 | /* This will occur if disable_rc_polling=1 */ | ||
| 685 | usb_free_urb(purb); | ||
| 686 | return; | ||
| 687 | } | ||
| 688 | |||
| 689 | poll_reply = purb->transfer_buffer; | ||
| 690 | |||
| 691 | if (purb->status < 0) { | ||
| 692 | deb_info("discontinuing polling\n"); | ||
| 693 | usb_free_urb(purb); | ||
| 694 | return; | ||
| 695 | } | ||
| 696 | |||
| 697 | if (purb->actual_length != RC_MSG_SIZE_V1_20) { | ||
| 698 | deb_info("malformed rc msg size=%d\n", purb->actual_length); | ||
| 699 | goto resubmit; | ||
| 700 | } | ||
| 701 | |||
| 702 | deb_data("IR ID = %02X state = %02X System = %02X %02X Cmd = %02X %02X (len %d)\n", | ||
| 703 | poll_reply->report_id, poll_reply->data_state, | ||
| 704 | poll_reply->system, poll_reply->not_system, | ||
| 705 | poll_reply->data, poll_reply->not_data, | ||
| 706 | purb->actual_length); | ||
| 707 | |||
| 708 | switch (d->props.rc.core.protocol) { | ||
| 709 | case RC_TYPE_NEC: | ||
| 710 | toggle = 0; | ||
| 711 | |||
| 712 | /* NEC protocol sends repeat code as 0 0 0 FF */ | ||
| 713 | if ((poll_reply->system == 0x00) && (poll_reply->data == 0x00) | ||
| 714 | && (poll_reply->not_data == 0xff)) { | ||
| 715 | poll_reply->data_state = 2; | ||
| 716 | break; | ||
| 717 | } | ||
| 718 | |||
| 719 | if ((poll_reply->system ^ poll_reply->not_system) != 0xff) { | ||
| 720 | deb_data("NEC extended protocol\n"); | ||
| 721 | /* NEC extended code - 24 bits */ | ||
| 722 | keycode = be16_to_cpu(poll_reply->system16) << 8 | poll_reply->data; | ||
| 723 | } else { | ||
| 724 | deb_data("NEC normal protocol\n"); | ||
| 725 | /* normal NEC code - 16 bits */ | ||
| 726 | keycode = poll_reply->system << 8 | poll_reply->data; | ||
| 727 | } | ||
| 728 | |||
| 729 | break; | ||
| 730 | default: | ||
| 731 | deb_data("RC5 protocol\n"); | ||
| 732 | /* RC5 Protocol */ | ||
| 733 | toggle = poll_reply->report_id; | ||
| 734 | keycode = poll_reply->system << 8 | poll_reply->data; | ||
| 735 | |||
| 736 | break; | ||
| 737 | } | ||
| 738 | |||
| 739 | if ((poll_reply->data + poll_reply->not_data) != 0xff) { | ||
| 740 | /* Key failed integrity check */ | ||
| 741 | err("key failed integrity check: %04x %02x %02x", | ||
| 742 | poll_reply->system, | ||
| 743 | poll_reply->data, poll_reply->not_data); | ||
| 744 | goto resubmit; | ||
| 745 | } | ||
| 746 | |||
| 747 | rc_keydown(d->rc_dev, keycode, toggle); | ||
| 748 | |||
| 749 | resubmit: | ||
| 750 | /* Clean the buffer before we requeue */ | ||
| 751 | memset(purb->transfer_buffer, 0, RC_MSG_SIZE_V1_20); | ||
| 752 | |||
| 753 | /* Requeue URB */ | ||
| 754 | usb_submit_urb(purb, GFP_ATOMIC); | ||
| 755 | } | ||
| 756 | |||
| 757 | int dib0700_rc_setup(struct dvb_usb_device *d) | ||
| 758 | { | ||
| 759 | struct dib0700_state *st = d->priv; | ||
| 760 | struct urb *purb; | ||
| 761 | int ret; | ||
| 762 | |||
| 763 | /* Poll-based. Don't initialize bulk mode */ | ||
| 764 | if (st->fw_version < 0x10200) | ||
| 765 | return 0; | ||
| 766 | |||
| 767 | /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ | ||
| 768 | purb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 769 | if (purb == NULL) { | ||
| 770 | err("rc usb alloc urb failed\n"); | ||
| 771 | return -ENOMEM; | ||
| 772 | } | ||
| 773 | |||
| 774 | purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL); | ||
| 775 | if (purb->transfer_buffer == NULL) { | ||
| 776 | err("rc kzalloc failed\n"); | ||
| 777 | usb_free_urb(purb); | ||
| 778 | return -ENOMEM; | ||
| 779 | } | ||
| 780 | |||
| 781 | purb->status = -EINPROGRESS; | ||
| 782 | usb_fill_bulk_urb(purb, d->udev, usb_rcvbulkpipe(d->udev, 1), | ||
| 783 | purb->transfer_buffer, RC_MSG_SIZE_V1_20, | ||
| 784 | dib0700_rc_urb_completion, d); | ||
| 785 | |||
| 786 | ret = usb_submit_urb(purb, GFP_ATOMIC); | ||
| 787 | if (ret) | ||
| 788 | err("rc submit urb failed\n"); | ||
| 789 | |||
| 790 | return ret; | ||
| 791 | } | ||
| 792 | |||
| 793 | static int dib0700_probe(struct usb_interface *intf, | ||
| 794 | const struct usb_device_id *id) | ||
| 795 | { | ||
| 796 | int i; | ||
| 797 | struct dvb_usb_device *dev; | ||
| 798 | |||
| 799 | for (i = 0; i < dib0700_device_count; i++) | ||
| 800 | if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, | ||
| 801 | &dev, adapter_nr) == 0) { | ||
| 802 | struct dib0700_state *st = dev->priv; | ||
| 803 | u32 hwversion, romversion, fw_version, fwtype; | ||
| 804 | |||
| 805 | dib0700_get_version(dev, &hwversion, &romversion, | ||
| 806 | &fw_version, &fwtype); | ||
| 807 | |||
| 808 | deb_info("Firmware version: %x, %d, 0x%x, %d\n", | ||
| 809 | hwversion, romversion, fw_version, fwtype); | ||
| 810 | |||
| 811 | st->fw_version = fw_version; | ||
| 812 | st->nb_packet_buffer_size = (u32)nb_packet_buffer_size; | ||
| 813 | |||
| 814 | /* Disable polling mode on newer firmwares */ | ||
| 815 | if (st->fw_version >= 0x10200) | ||
| 816 | dev->props.rc.core.bulk_mode = true; | ||
| 817 | else | ||
| 818 | dev->props.rc.core.bulk_mode = false; | ||
| 819 | |||
| 820 | dib0700_rc_setup(dev); | ||
| 821 | |||
| 822 | return 0; | ||
| 823 | } | ||
| 824 | |||
| 825 | return -ENODEV; | ||
| 826 | } | ||
| 827 | |||
| 828 | static struct usb_driver dib0700_driver = { | ||
| 829 | .name = "dvb_usb_dib0700", | ||
| 830 | .probe = dib0700_probe, | ||
| 831 | .disconnect = dvb_usb_device_exit, | ||
| 832 | .id_table = dib0700_usb_id_table, | ||
| 833 | }; | ||
| 834 | |||
| 835 | /* module stuff */ | ||
| 836 | static int __init dib0700_module_init(void) | ||
| 837 | { | ||
| 838 | int result; | ||
| 839 | info("loaded with support for %d different device-types", dib0700_device_count); | ||
| 840 | if ((result = usb_register(&dib0700_driver))) { | ||
| 841 | err("usb_register failed. Error number %d",result); | ||
| 842 | return result; | ||
| 843 | } | ||
| 844 | |||
| 845 | return 0; | ||
| 846 | } | ||
| 847 | |||
| 848 | static void __exit dib0700_module_exit(void) | ||
| 849 | { | ||
| 850 | /* deregister this driver from the USB subsystem */ | ||
| 851 | usb_deregister(&dib0700_driver); | ||
| 852 | } | ||
| 853 | |||
| 854 | module_init (dib0700_module_init); | ||
| 855 | module_exit (dib0700_module_exit); | ||
| 856 | |||
| 857 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
| 858 | MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge"); | ||
| 859 | MODULE_VERSION("1.0"); | ||
| 860 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c new file mode 100644 index 00000000000..d0ea5b64f6b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
| @@ -0,0 +1,3966 @@ | |||
| 1 | /* Linux driver for devices based on the DiBcom DiB0700 USB bridge | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify it | ||
| 4 | * under the terms of the GNU General Public License as published by the Free | ||
| 5 | * Software Foundation, version 2. | ||
| 6 | * | ||
| 7 | * Copyright (C) 2005-9 DiBcom, SA et al | ||
| 8 | */ | ||
| 9 | #include "dib0700.h" | ||
| 10 | |||
| 11 | #include "dib3000mc.h" | ||
| 12 | #include "dib7000m.h" | ||
| 13 | #include "dib7000p.h" | ||
| 14 | #include "dib8000.h" | ||
| 15 | #include "dib9000.h" | ||
| 16 | #include "mt2060.h" | ||
| 17 | #include "mt2266.h" | ||
| 18 | #include "tuner-xc2028.h" | ||
| 19 | #include "xc5000.h" | ||
| 20 | #include "xc4000.h" | ||
| 21 | #include "s5h1411.h" | ||
| 22 | #include "dib0070.h" | ||
| 23 | #include "dib0090.h" | ||
| 24 | #include "lgdt3305.h" | ||
| 25 | #include "mxl5007t.h" | ||
| 26 | |||
| 27 | static int force_lna_activation; | ||
| 28 | module_param(force_lna_activation, int, 0644); | ||
| 29 | MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), " | ||
| 30 | "if applicable for the device (default: 0=automatic/off)."); | ||
| 31 | |||
| 32 | struct dib0700_adapter_state { | ||
| 33 | int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *); | ||
| 34 | const struct firmware *frontend_firmware; | ||
| 35 | }; | ||
| 36 | |||
| 37 | /* Hauppauge Nova-T 500 (aka Bristol) | ||
| 38 | * has a LNA on GPIO0 which is enabled by setting 1 */ | ||
| 39 | static struct mt2060_config bristol_mt2060_config[2] = { | ||
| 40 | { | ||
| 41 | .i2c_address = 0x60, | ||
| 42 | .clock_out = 3, | ||
| 43 | }, { | ||
| 44 | .i2c_address = 0x61, | ||
| 45 | } | ||
| 46 | }; | ||
| 47 | |||
| 48 | |||
| 49 | static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = { | ||
| 50 | .band_caps = BAND_VHF | BAND_UHF, | ||
| 51 | .setup = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0), | ||
| 52 | |||
| 53 | .agc1_max = 42598, | ||
| 54 | .agc1_min = 17694, | ||
| 55 | .agc2_max = 45875, | ||
| 56 | .agc2_min = 0, | ||
| 57 | |||
| 58 | .agc1_pt1 = 0, | ||
| 59 | .agc1_pt2 = 59, | ||
| 60 | |||
| 61 | .agc1_slope1 = 0, | ||
| 62 | .agc1_slope2 = 69, | ||
| 63 | |||
| 64 | .agc2_pt1 = 0, | ||
| 65 | .agc2_pt2 = 59, | ||
| 66 | |||
| 67 | .agc2_slope1 = 111, | ||
| 68 | .agc2_slope2 = 28, | ||
| 69 | }; | ||
| 70 | |||
| 71 | static struct dib3000mc_config bristol_dib3000mc_config[2] = { | ||
| 72 | { .agc = &bristol_dib3000p_mt2060_agc_config, | ||
| 73 | .max_time = 0x196, | ||
| 74 | .ln_adc_level = 0x1cc7, | ||
| 75 | .output_mpeg2_in_188_bytes = 1, | ||
| 76 | }, | ||
| 77 | { .agc = &bristol_dib3000p_mt2060_agc_config, | ||
| 78 | .max_time = 0x196, | ||
| 79 | .ln_adc_level = 0x1cc7, | ||
| 80 | .output_mpeg2_in_188_bytes = 1, | ||
| 81 | } | ||
| 82 | }; | ||
| 83 | |||
| 84 | static int bristol_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 85 | { | ||
| 86 | struct dib0700_state *st = adap->dev->priv; | ||
| 87 | if (adap->id == 0) { | ||
| 88 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); | ||
| 89 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); | ||
| 90 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); | ||
| 91 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); | ||
| 92 | |||
| 93 | if (force_lna_activation) | ||
| 94 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 95 | else | ||
| 96 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0); | ||
| 97 | |||
| 98 | if (dib3000mc_i2c_enumeration(&adap->dev->i2c_adap, 2, DEFAULT_DIB3000P_I2C_ADDRESS, bristol_dib3000mc_config) != 0) { | ||
| 99 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); | ||
| 100 | return -ENODEV; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | st->mt2060_if1[adap->id] = 1220; | ||
| 104 | return (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, | ||
| 105 | (10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | static int eeprom_read(struct i2c_adapter *adap,u8 adrs,u8 *pval) | ||
| 109 | { | ||
| 110 | struct i2c_msg msg[2] = { | ||
| 111 | { .addr = 0x50, .flags = 0, .buf = &adrs, .len = 1 }, | ||
| 112 | { .addr = 0x50, .flags = I2C_M_RD, .buf = pval, .len = 1 }, | ||
| 113 | }; | ||
| 114 | if (i2c_transfer(adap, msg, 2) != 2) return -EREMOTEIO; | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int bristol_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 119 | { | ||
| 120 | struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap; | ||
| 121 | struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1); | ||
| 122 | s8 a; | ||
| 123 | int if1=1220; | ||
| 124 | if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) && | ||
| 125 | adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_500_2)) { | ||
| 126 | if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a; | ||
| 127 | } | ||
| 128 | return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id], | ||
| 129 | if1) == NULL ? -ENODEV : 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */ | ||
| 133 | |||
| 134 | /* MT226x */ | ||
| 135 | static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = { | ||
| 136 | { | ||
| 137 | BAND_UHF, | ||
| 138 | |||
| 139 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1, | ||
| 140 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
| 141 | (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | ||
| 142 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
| 143 | |||
| 144 | 1130, | ||
| 145 | 21, | ||
| 146 | |||
| 147 | 0, | ||
| 148 | 118, | ||
| 149 | |||
| 150 | 0, | ||
| 151 | 3530, | ||
| 152 | 1, | ||
| 153 | 0, | ||
| 154 | |||
| 155 | 65535, | ||
| 156 | 33770, | ||
| 157 | 65535, | ||
| 158 | 23592, | ||
| 159 | |||
| 160 | 0, | ||
| 161 | 62, | ||
| 162 | 255, | ||
| 163 | 64, | ||
| 164 | 64, | ||
| 165 | 132, | ||
| 166 | 192, | ||
| 167 | 80, | ||
| 168 | 80, | ||
| 169 | |||
| 170 | 17, | ||
| 171 | 27, | ||
| 172 | 23, | ||
| 173 | 51, | ||
| 174 | |||
| 175 | 1, | ||
| 176 | }, { | ||
| 177 | BAND_VHF | BAND_LBAND, | ||
| 178 | |||
| 179 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1, | ||
| 180 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
| 181 | (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | ||
| 182 | | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), | ||
| 183 | |||
| 184 | 2372, | ||
| 185 | 21, | ||
| 186 | |||
| 187 | 0, | ||
| 188 | 118, | ||
| 189 | |||
| 190 | 0, | ||
| 191 | 3530, | ||
| 192 | 1, | ||
| 193 | 0, | ||
| 194 | |||
| 195 | 65535, | ||
| 196 | 0, | ||
| 197 | 65535, | ||
| 198 | 23592, | ||
| 199 | |||
| 200 | 0, | ||
| 201 | 128, | ||
| 202 | 128, | ||
| 203 | 128, | ||
| 204 | 0, | ||
| 205 | 128, | ||
| 206 | 253, | ||
| 207 | 81, | ||
| 208 | 0, | ||
| 209 | |||
| 210 | 17, | ||
| 211 | 27, | ||
| 212 | 23, | ||
| 213 | 51, | ||
| 214 | |||
| 215 | 1, | ||
| 216 | } | ||
| 217 | }; | ||
| 218 | |||
| 219 | static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = { | ||
| 220 | 60000, 30000, | ||
| 221 | 1, 8, 3, 1, 0, | ||
| 222 | 0, 0, 1, 1, 2, | ||
| 223 | (3 << 14) | (1 << 12) | (524 << 0), | ||
| 224 | 0, | ||
| 225 | 20452225, | ||
| 226 | }; | ||
| 227 | |||
| 228 | static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = { | ||
| 229 | { .output_mpeg2_in_188_bytes = 1, | ||
| 230 | .hostbus_diversity = 1, | ||
| 231 | .tuner_is_baseband = 1, | ||
| 232 | |||
| 233 | .agc_config_count = 2, | ||
| 234 | .agc = stk7700d_7000p_mt2266_agc_config, | ||
| 235 | .bw = &stk7700d_mt2266_pll_config, | ||
| 236 | |||
| 237 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
| 238 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
| 239 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 240 | }, | ||
| 241 | { .output_mpeg2_in_188_bytes = 1, | ||
| 242 | .hostbus_diversity = 1, | ||
| 243 | .tuner_is_baseband = 1, | ||
| 244 | |||
| 245 | .agc_config_count = 2, | ||
| 246 | .agc = stk7700d_7000p_mt2266_agc_config, | ||
| 247 | .bw = &stk7700d_mt2266_pll_config, | ||
| 248 | |||
| 249 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
| 250 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
| 251 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 252 | } | ||
| 253 | }; | ||
| 254 | |||
| 255 | static struct mt2266_config stk7700d_mt2266_config[2] = { | ||
| 256 | { .i2c_address = 0x60 | ||
| 257 | }, | ||
| 258 | { .i2c_address = 0x60 | ||
| 259 | } | ||
| 260 | }; | ||
| 261 | |||
| 262 | static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 263 | { | ||
| 264 | if (adap->id == 0) { | ||
| 265 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 266 | msleep(10); | ||
| 267 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 268 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 269 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 270 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 271 | msleep(10); | ||
| 272 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 273 | msleep(10); | ||
| 274 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | ||
| 275 | stk7700d_dib7000p_mt2266_config) | ||
| 276 | != 0) { | ||
| 277 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__); | ||
| 278 | return -ENODEV; | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1), | ||
| 283 | &stk7700d_dib7000p_mt2266_config[adap->id]); | ||
| 284 | |||
| 285 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 289 | { | ||
| 290 | if (adap->id == 0) { | ||
| 291 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 292 | msleep(10); | ||
| 293 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 294 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 295 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 296 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 297 | msleep(10); | ||
| 298 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 299 | msleep(10); | ||
| 300 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 301 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, | ||
| 302 | stk7700d_dib7000p_mt2266_config) | ||
| 303 | != 0) { | ||
| 304 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__); | ||
| 305 | return -ENODEV; | ||
| 306 | } | ||
| 307 | } | ||
| 308 | |||
| 309 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1), | ||
| 310 | &stk7700d_dib7000p_mt2266_config[adap->id]); | ||
| 311 | |||
| 312 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 316 | { | ||
| 317 | struct i2c_adapter *tun_i2c; | ||
| 318 | tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 319 | return dvb_attach(mt2266_attach, adap->fe, tun_i2c, | ||
| 320 | &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | /* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */ | ||
| 324 | static struct dibx000_agc_config xc3028_agc_config = { | ||
| 325 | BAND_VHF | BAND_UHF, /* band_caps */ | ||
| 326 | |||
| 327 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0, | ||
| 328 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | ||
| 329 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
| 330 | (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | | ||
| 331 | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */ | ||
| 332 | |||
| 333 | 712, /* inv_gain */ | ||
| 334 | 21, /* time_stabiliz */ | ||
| 335 | |||
| 336 | 0, /* alpha_level */ | ||
| 337 | 118, /* thlock */ | ||
| 338 | |||
| 339 | 0, /* wbd_inv */ | ||
| 340 | 2867, /* wbd_ref */ | ||
| 341 | 0, /* wbd_sel */ | ||
| 342 | 2, /* wbd_alpha */ | ||
| 343 | |||
| 344 | 0, /* agc1_max */ | ||
| 345 | 0, /* agc1_min */ | ||
| 346 | 39718, /* agc2_max */ | ||
| 347 | 9930, /* agc2_min */ | ||
| 348 | 0, /* agc1_pt1 */ | ||
| 349 | 0, /* agc1_pt2 */ | ||
| 350 | 0, /* agc1_pt3 */ | ||
| 351 | 0, /* agc1_slope1 */ | ||
| 352 | 0, /* agc1_slope2 */ | ||
| 353 | 0, /* agc2_pt1 */ | ||
| 354 | 128, /* agc2_pt2 */ | ||
| 355 | 29, /* agc2_slope1 */ | ||
| 356 | 29, /* agc2_slope2 */ | ||
| 357 | |||
| 358 | 17, /* alpha_mant */ | ||
| 359 | 27, /* alpha_exp */ | ||
| 360 | 23, /* beta_mant */ | ||
| 361 | 51, /* beta_exp */ | ||
| 362 | |||
| 363 | 1, /* perform_agc_softsplit */ | ||
| 364 | }; | ||
| 365 | |||
| 366 | /* PLL Configuration for COFDM BW_MHz = 8.00 with external clock = 30.00 */ | ||
| 367 | static struct dibx000_bandwidth_config xc3028_bw_config = { | ||
| 368 | 60000, 30000, /* internal, sampling */ | ||
| 369 | 1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */ | ||
| 370 | 0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, | ||
| 371 | modulo */ | ||
| 372 | (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */ | ||
| 373 | (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */ | ||
| 374 | 20452225, /* timf */ | ||
| 375 | 30000000, /* xtal_hz */ | ||
| 376 | }; | ||
| 377 | |||
| 378 | static struct dib7000p_config stk7700ph_dib7700_xc3028_config = { | ||
| 379 | .output_mpeg2_in_188_bytes = 1, | ||
| 380 | .tuner_is_baseband = 1, | ||
| 381 | |||
| 382 | .agc_config_count = 1, | ||
| 383 | .agc = &xc3028_agc_config, | ||
| 384 | .bw = &xc3028_bw_config, | ||
| 385 | |||
| 386 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
| 387 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
| 388 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 389 | }; | ||
| 390 | |||
| 391 | static int stk7700ph_xc3028_callback(void *ptr, int component, | ||
| 392 | int command, int arg) | ||
| 393 | { | ||
| 394 | struct dvb_usb_adapter *adap = ptr; | ||
| 395 | |||
| 396 | switch (command) { | ||
| 397 | case XC2028_TUNER_RESET: | ||
| 398 | /* Send the tuner in then out of reset */ | ||
| 399 | dib7000p_set_gpio(adap->fe, 8, 0, 0); msleep(10); | ||
| 400 | dib7000p_set_gpio(adap->fe, 8, 0, 1); | ||
| 401 | break; | ||
| 402 | case XC2028_RESET_CLK: | ||
| 403 | break; | ||
| 404 | default: | ||
| 405 | err("%s: unknown command %d, arg %d\n", __func__, | ||
| 406 | command, arg); | ||
| 407 | return -EINVAL; | ||
| 408 | } | ||
| 409 | return 0; | ||
| 410 | } | ||
| 411 | |||
| 412 | static struct xc2028_ctrl stk7700ph_xc3028_ctrl = { | ||
| 413 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
| 414 | .max_len = 64, | ||
| 415 | .demod = XC3028_FE_DIBCOM52, | ||
| 416 | }; | ||
| 417 | |||
| 418 | static struct xc2028_config stk7700ph_xc3028_config = { | ||
| 419 | .i2c_addr = 0x61, | ||
| 420 | .ctrl = &stk7700ph_xc3028_ctrl, | ||
| 421 | }; | ||
| 422 | |||
| 423 | static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 424 | { | ||
| 425 | struct usb_device_descriptor *desc = &adap->dev->udev->descriptor; | ||
| 426 | |||
| 427 | if (desc->idVendor == cpu_to_le16(USB_VID_PINNACLE) && | ||
| 428 | desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX)) | ||
| 429 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | ||
| 430 | else | ||
| 431 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 432 | msleep(20); | ||
| 433 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 434 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 435 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 436 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 437 | msleep(10); | ||
| 438 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 439 | msleep(20); | ||
| 440 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 441 | msleep(10); | ||
| 442 | |||
| 443 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | ||
| 444 | &stk7700ph_dib7700_xc3028_config) != 0) { | ||
| 445 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | ||
| 446 | __func__); | ||
| 447 | return -ENODEV; | ||
| 448 | } | ||
| 449 | |||
| 450 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | ||
| 451 | &stk7700ph_dib7700_xc3028_config); | ||
| 452 | |||
| 453 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 454 | } | ||
| 455 | |||
| 456 | static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 457 | { | ||
| 458 | struct i2c_adapter *tun_i2c; | ||
| 459 | |||
| 460 | tun_i2c = dib7000p_get_i2c_master(adap->fe, | ||
| 461 | DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 462 | |||
| 463 | stk7700ph_xc3028_config.i2c_adap = tun_i2c; | ||
| 464 | |||
| 465 | /* FIXME: generalize & move to common area */ | ||
| 466 | adap->fe->callback = stk7700ph_xc3028_callback; | ||
| 467 | |||
| 468 | return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config) | ||
| 469 | == NULL ? -ENODEV : 0; | ||
| 470 | } | ||
| 471 | |||
| 472 | #define DEFAULT_RC_INTERVAL 50 | ||
| 473 | |||
| 474 | static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; | ||
| 475 | |||
| 476 | /* Number of keypresses to ignore before start repeating */ | ||
| 477 | #define RC_REPEAT_DELAY 6 | ||
| 478 | |||
| 479 | /* | ||
| 480 | * This function is used only when firmware is < 1.20 version. Newer | ||
| 481 | * firmwares use bulk mode, with functions implemented at dib0700_core, | ||
| 482 | * at dib0700_rc_urb_completion() | ||
| 483 | */ | ||
| 484 | static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) | ||
| 485 | { | ||
| 486 | u8 key[4]; | ||
| 487 | u32 keycode; | ||
| 488 | u8 toggle; | ||
| 489 | int i; | ||
| 490 | struct dib0700_state *st = d->priv; | ||
| 491 | |||
| 492 | if (st->fw_version >= 0x10200) { | ||
| 493 | /* For 1.20 firmware , We need to keep the RC polling | ||
| 494 | callback so we can reuse the input device setup in | ||
| 495 | dvb-usb-remote.c. However, the actual work is being done | ||
| 496 | in the bulk URB completion handler. */ | ||
| 497 | return 0; | ||
| 498 | } | ||
| 499 | |||
| 500 | i = dib0700_ctrl_rd(d, rc_request, 2, key, 4); | ||
| 501 | if (i <= 0) { | ||
| 502 | err("RC Query Failed"); | ||
| 503 | return -1; | ||
| 504 | } | ||
| 505 | |||
| 506 | /* losing half of KEY_0 events from Philipps rc5 remotes.. */ | ||
| 507 | if (key[0] == 0 && key[1] == 0 && key[2] == 0 && key[3] == 0) | ||
| 508 | return 0; | ||
| 509 | |||
| 510 | /* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]); */ | ||
| 511 | |||
| 512 | dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */ | ||
| 513 | |||
| 514 | d->last_event = 0; | ||
| 515 | switch (d->props.rc.core.protocol) { | ||
| 516 | case RC_TYPE_NEC: | ||
| 517 | /* NEC protocol sends repeat code as 0 0 0 FF */ | ||
| 518 | if ((key[3-2] == 0x00) && (key[3-3] == 0x00) && | ||
| 519 | (key[3] == 0xff)) | ||
| 520 | keycode = d->last_event; | ||
| 521 | else { | ||
| 522 | keycode = key[3-2] << 8 | key[3-3]; | ||
| 523 | d->last_event = keycode; | ||
| 524 | } | ||
| 525 | |||
| 526 | rc_keydown(d->rc_dev, keycode, 0); | ||
| 527 | break; | ||
| 528 | default: | ||
| 529 | /* RC-5 protocol changes toggle bit on new keypress */ | ||
| 530 | keycode = key[3-2] << 8 | key[3-3]; | ||
| 531 | toggle = key[3-1]; | ||
| 532 | rc_keydown(d->rc_dev, keycode, toggle); | ||
| 533 | |||
| 534 | break; | ||
| 535 | } | ||
| 536 | return 0; | ||
| 537 | } | ||
| 538 | |||
| 539 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ | ||
| 540 | static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { | ||
| 541 | BAND_UHF | BAND_VHF, | ||
| 542 | |||
| 543 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
| 544 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
| 545 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | ||
| 546 | | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), | ||
| 547 | |||
| 548 | 712, | ||
| 549 | 41, | ||
| 550 | |||
| 551 | 0, | ||
| 552 | 118, | ||
| 553 | |||
| 554 | 0, | ||
| 555 | 4095, | ||
| 556 | 0, | ||
| 557 | 0, | ||
| 558 | |||
| 559 | 42598, | ||
| 560 | 17694, | ||
| 561 | 45875, | ||
| 562 | 2621, | ||
| 563 | 0, | ||
| 564 | 76, | ||
| 565 | 139, | ||
| 566 | 52, | ||
| 567 | 59, | ||
| 568 | 107, | ||
| 569 | 172, | ||
| 570 | 57, | ||
| 571 | 70, | ||
| 572 | |||
| 573 | 21, | ||
| 574 | 25, | ||
| 575 | 28, | ||
| 576 | 48, | ||
| 577 | |||
| 578 | 1, | ||
| 579 | { 0, | ||
| 580 | 107, | ||
| 581 | 51800, | ||
| 582 | 24700 | ||
| 583 | }, | ||
| 584 | }; | ||
| 585 | |||
| 586 | static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = { | ||
| 587 | BAND_UHF | BAND_VHF, | ||
| 588 | |||
| 589 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
| 590 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
| 591 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | ||
| 592 | | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), | ||
| 593 | |||
| 594 | 712, | ||
| 595 | 41, | ||
| 596 | |||
| 597 | 0, | ||
| 598 | 118, | ||
| 599 | |||
| 600 | 0, | ||
| 601 | 4095, | ||
| 602 | 0, | ||
| 603 | 0, | ||
| 604 | |||
| 605 | 42598, | ||
| 606 | 16384, | ||
| 607 | 42598, | ||
| 608 | 0, | ||
| 609 | |||
| 610 | 0, | ||
| 611 | 137, | ||
| 612 | 255, | ||
| 613 | |||
| 614 | 0, | ||
| 615 | 255, | ||
| 616 | |||
| 617 | 0, | ||
| 618 | 0, | ||
| 619 | |||
| 620 | 0, | ||
| 621 | 41, | ||
| 622 | |||
| 623 | 15, | ||
| 624 | 25, | ||
| 625 | |||
| 626 | 28, | ||
| 627 | 48, | ||
| 628 | |||
| 629 | 0, | ||
| 630 | }; | ||
| 631 | |||
| 632 | static struct dibx000_bandwidth_config stk7700p_pll_config = { | ||
| 633 | 60000, 30000, | ||
| 634 | 1, 8, 3, 1, 0, | ||
| 635 | 0, 0, 1, 1, 0, | ||
| 636 | (3 << 14) | (1 << 12) | (524 << 0), | ||
| 637 | 60258167, | ||
| 638 | 20452225, | ||
| 639 | 30000000, | ||
| 640 | }; | ||
| 641 | |||
| 642 | static struct dib7000m_config stk7700p_dib7000m_config = { | ||
| 643 | .dvbt_mode = 1, | ||
| 644 | .output_mpeg2_in_188_bytes = 1, | ||
| 645 | .quartz_direct = 1, | ||
| 646 | |||
| 647 | .agc_config_count = 1, | ||
| 648 | .agc = &stk7700p_7000m_mt2060_agc_config, | ||
| 649 | .bw = &stk7700p_pll_config, | ||
| 650 | |||
| 651 | .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, | ||
| 652 | .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, | ||
| 653 | .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, | ||
| 654 | }; | ||
| 655 | |||
| 656 | static struct dib7000p_config stk7700p_dib7000p_config = { | ||
| 657 | .output_mpeg2_in_188_bytes = 1, | ||
| 658 | |||
| 659 | .agc_config_count = 1, | ||
| 660 | .agc = &stk7700p_7000p_mt2060_agc_config, | ||
| 661 | .bw = &stk7700p_pll_config, | ||
| 662 | |||
| 663 | .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, | ||
| 664 | .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, | ||
| 665 | .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, | ||
| 666 | }; | ||
| 667 | |||
| 668 | static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 669 | { | ||
| 670 | struct dib0700_state *st = adap->dev->priv; | ||
| 671 | /* unless there is no real power management in DVB - we leave the device on GPIO6 */ | ||
| 672 | |||
| 673 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 674 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(50); | ||
| 675 | |||
| 676 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); | ||
| 677 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 678 | |||
| 679 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); | ||
| 680 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 681 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100); | ||
| 682 | |||
| 683 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 684 | |||
| 685 | st->mt2060_if1[0] = 1220; | ||
| 686 | |||
| 687 | if (dib7000pc_detection(&adap->dev->i2c_adap)) { | ||
| 688 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config); | ||
| 689 | st->is_dib7000pc = 1; | ||
| 690 | } else | ||
| 691 | adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config); | ||
| 692 | |||
| 693 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 694 | } | ||
| 695 | |||
| 696 | static struct mt2060_config stk7700p_mt2060_config = { | ||
| 697 | 0x60 | ||
| 698 | }; | ||
| 699 | |||
| 700 | static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 701 | { | ||
| 702 | struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap; | ||
| 703 | struct dib0700_state *st = adap->dev->priv; | ||
| 704 | struct i2c_adapter *tun_i2c; | ||
| 705 | s8 a; | ||
| 706 | int if1=1220; | ||
| 707 | if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) && | ||
| 708 | adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) { | ||
| 709 | if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a; | ||
| 710 | } | ||
| 711 | if (st->is_dib7000pc) | ||
| 712 | tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 713 | else | ||
| 714 | tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 715 | |||
| 716 | return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config, | ||
| 717 | if1) == NULL ? -ENODEV : 0; | ||
| 718 | } | ||
| 719 | |||
| 720 | /* DIB7070 generic */ | ||
| 721 | static struct dibx000_agc_config dib7070_agc_config = { | ||
| 722 | BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, | ||
| 723 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
| 724 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | ||
| 725 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | ||
| 726 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
| 727 | |||
| 728 | 600, | ||
| 729 | 10, | ||
| 730 | |||
| 731 | 0, | ||
| 732 | 118, | ||
| 733 | |||
| 734 | 0, | ||
| 735 | 3530, | ||
| 736 | 1, | ||
| 737 | 5, | ||
| 738 | |||
| 739 | 65535, | ||
| 740 | 0, | ||
| 741 | |||
| 742 | 65535, | ||
| 743 | 0, | ||
| 744 | |||
| 745 | 0, | ||
| 746 | 40, | ||
| 747 | 183, | ||
| 748 | 206, | ||
| 749 | 255, | ||
| 750 | 72, | ||
| 751 | 152, | ||
| 752 | 88, | ||
| 753 | 90, | ||
| 754 | |||
| 755 | 17, | ||
| 756 | 27, | ||
| 757 | 23, | ||
| 758 | 51, | ||
| 759 | |||
| 760 | 0, | ||
| 761 | }; | ||
| 762 | |||
| 763 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) | ||
| 764 | { | ||
| 765 | deb_info("reset: %d", onoff); | ||
| 766 | return dib7000p_set_gpio(fe, 8, 0, !onoff); | ||
| 767 | } | ||
| 768 | |||
| 769 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) | ||
| 770 | { | ||
| 771 | deb_info("sleep: %d", onoff); | ||
| 772 | return dib7000p_set_gpio(fe, 9, 0, onoff); | ||
| 773 | } | ||
| 774 | |||
| 775 | static struct dib0070_config dib7070p_dib0070_config[2] = { | ||
| 776 | { | ||
| 777 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
| 778 | .reset = dib7070_tuner_reset, | ||
| 779 | .sleep = dib7070_tuner_sleep, | ||
| 780 | .clock_khz = 12000, | ||
| 781 | .clock_pad_drive = 4, | ||
| 782 | .charge_pump = 2, | ||
| 783 | }, { | ||
| 784 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
| 785 | .reset = dib7070_tuner_reset, | ||
| 786 | .sleep = dib7070_tuner_sleep, | ||
| 787 | .clock_khz = 12000, | ||
| 788 | .charge_pump = 2, | ||
| 789 | } | ||
| 790 | }; | ||
| 791 | |||
| 792 | static struct dib0070_config dib7770p_dib0070_config = { | ||
| 793 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
| 794 | .reset = dib7070_tuner_reset, | ||
| 795 | .sleep = dib7070_tuner_sleep, | ||
| 796 | .clock_khz = 12000, | ||
| 797 | .clock_pad_drive = 0, | ||
| 798 | .flip_chip = 1, | ||
| 799 | .charge_pump = 2, | ||
| 800 | }; | ||
| 801 | |||
| 802 | static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | ||
| 803 | { | ||
| 804 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 805 | struct dib0700_adapter_state *state = adap->priv; | ||
| 806 | |||
| 807 | u16 offset; | ||
| 808 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
| 809 | switch (band) { | ||
| 810 | case BAND_VHF: offset = 950; break; | ||
| 811 | case BAND_UHF: | ||
| 812 | default: offset = 550; break; | ||
| 813 | } | ||
| 814 | deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe)); | ||
| 815 | dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); | ||
| 816 | return state->set_param_save(fe, fep); | ||
| 817 | } | ||
| 818 | |||
| 819 | static int dib7770_set_param_override(struct dvb_frontend *fe, | ||
| 820 | struct dvb_frontend_parameters *fep) | ||
| 821 | { | ||
| 822 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 823 | struct dib0700_adapter_state *state = adap->priv; | ||
| 824 | |||
| 825 | u16 offset; | ||
| 826 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
| 827 | switch (band) { | ||
| 828 | case BAND_VHF: | ||
| 829 | dib7000p_set_gpio(fe, 0, 0, 1); | ||
| 830 | offset = 850; | ||
| 831 | break; | ||
| 832 | case BAND_UHF: | ||
| 833 | default: | ||
| 834 | dib7000p_set_gpio(fe, 0, 0, 0); | ||
| 835 | offset = 250; | ||
| 836 | break; | ||
| 837 | } | ||
| 838 | deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe)); | ||
| 839 | dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); | ||
| 840 | return state->set_param_save(fe, fep); | ||
| 841 | } | ||
| 842 | |||
| 843 | static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 844 | { | ||
| 845 | struct dib0700_adapter_state *st = adap->priv; | ||
| 846 | struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, | ||
| 847 | DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 848 | |||
| 849 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, | ||
| 850 | &dib7770p_dib0070_config) == NULL) | ||
| 851 | return -ENODEV; | ||
| 852 | |||
| 853 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
| 854 | adap->fe->ops.tuner_ops.set_params = dib7770_set_param_override; | ||
| 855 | return 0; | ||
| 856 | } | ||
| 857 | |||
| 858 | static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 859 | { | ||
| 860 | struct dib0700_adapter_state *st = adap->priv; | ||
| 861 | struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 862 | |||
| 863 | if (adap->id == 0) { | ||
| 864 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL) | ||
| 865 | return -ENODEV; | ||
| 866 | } else { | ||
| 867 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL) | ||
| 868 | return -ENODEV; | ||
| 869 | } | ||
| 870 | |||
| 871 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
| 872 | adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override; | ||
| 873 | return 0; | ||
| 874 | } | ||
| 875 | |||
| 876 | static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index, | ||
| 877 | u16 pid, int onoff) | ||
| 878 | { | ||
| 879 | struct dib0700_state *st = adapter->dev->priv; | ||
| 880 | if (st->is_dib7000pc) | ||
| 881 | return dib7000p_pid_filter(adapter->fe, index, pid, onoff); | ||
| 882 | return dib7000m_pid_filter(adapter->fe, index, pid, onoff); | ||
| 883 | } | ||
| 884 | |||
| 885 | static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) | ||
| 886 | { | ||
| 887 | struct dib0700_state *st = adapter->dev->priv; | ||
| 888 | if (st->is_dib7000pc) | ||
| 889 | return dib7000p_pid_filter_ctrl(adapter->fe, onoff); | ||
| 890 | return dib7000m_pid_filter_ctrl(adapter->fe, onoff); | ||
| 891 | } | ||
| 892 | |||
| 893 | static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) | ||
| 894 | { | ||
| 895 | return dib7000p_pid_filter(adapter->fe, index, pid, onoff); | ||
| 896 | } | ||
| 897 | |||
| 898 | static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) | ||
| 899 | { | ||
| 900 | return dib7000p_pid_filter_ctrl(adapter->fe, onoff); | ||
| 901 | } | ||
| 902 | |||
| 903 | static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { | ||
| 904 | 60000, 15000, | ||
| 905 | 1, 20, 3, 1, 0, | ||
| 906 | 0, 0, 1, 1, 2, | ||
| 907 | (3 << 14) | (1 << 12) | (524 << 0), | ||
| 908 | (0 << 25) | 0, | ||
| 909 | 20452225, | ||
| 910 | 12000000, | ||
| 911 | }; | ||
| 912 | |||
| 913 | static struct dib7000p_config dib7070p_dib7000p_config = { | ||
| 914 | .output_mpeg2_in_188_bytes = 1, | ||
| 915 | |||
| 916 | .agc_config_count = 1, | ||
| 917 | .agc = &dib7070_agc_config, | ||
| 918 | .bw = &dib7070_bw_config_12_mhz, | ||
| 919 | .tuner_is_baseband = 1, | ||
| 920 | .spur_protect = 1, | ||
| 921 | |||
| 922 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
| 923 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
| 924 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 925 | |||
| 926 | .hostbus_diversity = 1, | ||
| 927 | }; | ||
| 928 | |||
| 929 | /* STK7070P */ | ||
| 930 | static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 931 | { | ||
| 932 | struct usb_device_descriptor *p = &adap->dev->udev->descriptor; | ||
| 933 | if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) && | ||
| 934 | p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E)) | ||
| 935 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | ||
| 936 | else | ||
| 937 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 938 | msleep(10); | ||
| 939 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 940 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 941 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 942 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 943 | |||
| 944 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 945 | |||
| 946 | msleep(10); | ||
| 947 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 948 | msleep(10); | ||
| 949 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 950 | |||
| 951 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | ||
| 952 | &dib7070p_dib7000p_config) != 0) { | ||
| 953 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | ||
| 954 | __func__); | ||
| 955 | return -ENODEV; | ||
| 956 | } | ||
| 957 | |||
| 958 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | ||
| 959 | &dib7070p_dib7000p_config); | ||
| 960 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 961 | } | ||
| 962 | |||
| 963 | /* STK7770P */ | ||
| 964 | static struct dib7000p_config dib7770p_dib7000p_config = { | ||
| 965 | .output_mpeg2_in_188_bytes = 1, | ||
| 966 | |||
| 967 | .agc_config_count = 1, | ||
| 968 | .agc = &dib7070_agc_config, | ||
| 969 | .bw = &dib7070_bw_config_12_mhz, | ||
| 970 | .tuner_is_baseband = 1, | ||
| 971 | .spur_protect = 1, | ||
| 972 | |||
| 973 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
| 974 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
| 975 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 976 | |||
| 977 | .hostbus_diversity = 1, | ||
| 978 | .enable_current_mirror = 1, | ||
| 979 | .disable_sample_and_hold = 0, | ||
| 980 | }; | ||
| 981 | |||
| 982 | static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 983 | { | ||
| 984 | struct usb_device_descriptor *p = &adap->dev->udev->descriptor; | ||
| 985 | if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) && | ||
| 986 | p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E)) | ||
| 987 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | ||
| 988 | else | ||
| 989 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 990 | msleep(10); | ||
| 991 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 992 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 993 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 994 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 995 | |||
| 996 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 997 | |||
| 998 | msleep(10); | ||
| 999 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 1000 | msleep(10); | ||
| 1001 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 1002 | |||
| 1003 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | ||
| 1004 | &dib7770p_dib7000p_config) != 0) { | ||
| 1005 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | ||
| 1006 | __func__); | ||
| 1007 | return -ENODEV; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | ||
| 1011 | &dib7770p_dib7000p_config); | ||
| 1012 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | /* DIB807x generic */ | ||
| 1016 | static struct dibx000_agc_config dib807x_agc_config[2] = { | ||
| 1017 | { | ||
| 1018 | BAND_VHF, | ||
| 1019 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, | ||
| 1020 | * P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, | ||
| 1021 | * P_agc_inv_pwm2=0,P_agc_inh_dc_rv_est=0, | ||
| 1022 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, | ||
| 1023 | * P_agc_write=0 */ | ||
| 1024 | (0 << 15) | (0 << 14) | (7 << 11) | (0 << 10) | (0 << 9) | | ||
| 1025 | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | | ||
| 1026 | (0 << 0), /* setup*/ | ||
| 1027 | |||
| 1028 | 600, /* inv_gain*/ | ||
| 1029 | 10, /* time_stabiliz*/ | ||
| 1030 | |||
| 1031 | 0, /* alpha_level*/ | ||
| 1032 | 118, /* thlock*/ | ||
| 1033 | |||
| 1034 | 0, /* wbd_inv*/ | ||
| 1035 | 3530, /* wbd_ref*/ | ||
| 1036 | 1, /* wbd_sel*/ | ||
| 1037 | 5, /* wbd_alpha*/ | ||
| 1038 | |||
| 1039 | 65535, /* agc1_max*/ | ||
| 1040 | 0, /* agc1_min*/ | ||
| 1041 | |||
| 1042 | 65535, /* agc2_max*/ | ||
| 1043 | 0, /* agc2_min*/ | ||
| 1044 | |||
| 1045 | 0, /* agc1_pt1*/ | ||
| 1046 | 40, /* agc1_pt2*/ | ||
| 1047 | 183, /* agc1_pt3*/ | ||
| 1048 | 206, /* agc1_slope1*/ | ||
| 1049 | 255, /* agc1_slope2*/ | ||
| 1050 | 72, /* agc2_pt1*/ | ||
| 1051 | 152, /* agc2_pt2*/ | ||
| 1052 | 88, /* agc2_slope1*/ | ||
| 1053 | 90, /* agc2_slope2*/ | ||
| 1054 | |||
| 1055 | 17, /* alpha_mant*/ | ||
| 1056 | 27, /* alpha_exp*/ | ||
| 1057 | 23, /* beta_mant*/ | ||
| 1058 | 51, /* beta_exp*/ | ||
| 1059 | |||
| 1060 | 0, /* perform_agc_softsplit*/ | ||
| 1061 | }, { | ||
| 1062 | BAND_UHF, | ||
| 1063 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, | ||
| 1064 | * P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, | ||
| 1065 | * P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | ||
| 1066 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, | ||
| 1067 | * P_agc_write=0 */ | ||
| 1068 | (0 << 15) | (0 << 14) | (1 << 11) | (0 << 10) | (0 << 9) | | ||
| 1069 | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | | ||
| 1070 | (0 << 0), /* setup */ | ||
| 1071 | |||
| 1072 | 600, /* inv_gain*/ | ||
| 1073 | 10, /* time_stabiliz*/ | ||
| 1074 | |||
| 1075 | 0, /* alpha_level*/ | ||
| 1076 | 118, /* thlock*/ | ||
| 1077 | |||
| 1078 | 0, /* wbd_inv*/ | ||
| 1079 | 3530, /* wbd_ref*/ | ||
| 1080 | 1, /* wbd_sel*/ | ||
| 1081 | 5, /* wbd_alpha*/ | ||
| 1082 | |||
| 1083 | 65535, /* agc1_max*/ | ||
| 1084 | 0, /* agc1_min*/ | ||
| 1085 | |||
| 1086 | 65535, /* agc2_max*/ | ||
| 1087 | 0, /* agc2_min*/ | ||
| 1088 | |||
| 1089 | 0, /* agc1_pt1*/ | ||
| 1090 | 40, /* agc1_pt2*/ | ||
| 1091 | 183, /* agc1_pt3*/ | ||
| 1092 | 206, /* agc1_slope1*/ | ||
| 1093 | 255, /* agc1_slope2*/ | ||
| 1094 | 72, /* agc2_pt1*/ | ||
| 1095 | 152, /* agc2_pt2*/ | ||
| 1096 | 88, /* agc2_slope1*/ | ||
| 1097 | 90, /* agc2_slope2*/ | ||
| 1098 | |||
| 1099 | 17, /* alpha_mant*/ | ||
| 1100 | 27, /* alpha_exp*/ | ||
| 1101 | 23, /* beta_mant*/ | ||
| 1102 | 51, /* beta_exp*/ | ||
| 1103 | |||
| 1104 | 0, /* perform_agc_softsplit*/ | ||
| 1105 | } | ||
| 1106 | }; | ||
| 1107 | |||
| 1108 | static struct dibx000_bandwidth_config dib807x_bw_config_12_mhz = { | ||
| 1109 | 60000, 15000, /* internal, sampling*/ | ||
| 1110 | 1, 20, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass*/ | ||
| 1111 | 0, 0, 1, 1, 2, /* misc: refdiv, bypclk_div, IO_CLK_en_core, | ||
| 1112 | ADClkSrc, modulo */ | ||
| 1113 | (3 << 14) | (1 << 12) | (599 << 0), /* sad_cfg: refsel, sel, freq_15k*/ | ||
| 1114 | (0 << 25) | 0, /* ifreq = 0.000000 MHz*/ | ||
| 1115 | 18179755, /* timf*/ | ||
| 1116 | 12000000, /* xtal_hz*/ | ||
| 1117 | }; | ||
| 1118 | |||
| 1119 | static struct dib8000_config dib807x_dib8000_config[2] = { | ||
| 1120 | { | ||
| 1121 | .output_mpeg2_in_188_bytes = 1, | ||
| 1122 | |||
| 1123 | .agc_config_count = 2, | ||
| 1124 | .agc = dib807x_agc_config, | ||
| 1125 | .pll = &dib807x_bw_config_12_mhz, | ||
| 1126 | .tuner_is_baseband = 1, | ||
| 1127 | |||
| 1128 | .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS, | ||
| 1129 | .gpio_val = DIB8000_GPIO_DEFAULT_VALUES, | ||
| 1130 | .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS, | ||
| 1131 | |||
| 1132 | .hostbus_diversity = 1, | ||
| 1133 | .div_cfg = 1, | ||
| 1134 | .agc_control = &dib0070_ctrl_agc_filter, | ||
| 1135 | .output_mode = OUTMODE_MPEG2_FIFO, | ||
| 1136 | .drives = 0x2d98, | ||
| 1137 | }, { | ||
| 1138 | .output_mpeg2_in_188_bytes = 1, | ||
| 1139 | |||
| 1140 | .agc_config_count = 2, | ||
| 1141 | .agc = dib807x_agc_config, | ||
| 1142 | .pll = &dib807x_bw_config_12_mhz, | ||
| 1143 | .tuner_is_baseband = 1, | ||
| 1144 | |||
| 1145 | .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS, | ||
| 1146 | .gpio_val = DIB8000_GPIO_DEFAULT_VALUES, | ||
| 1147 | .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS, | ||
| 1148 | |||
| 1149 | .hostbus_diversity = 1, | ||
| 1150 | .agc_control = &dib0070_ctrl_agc_filter, | ||
| 1151 | .output_mode = OUTMODE_MPEG2_FIFO, | ||
| 1152 | .drives = 0x2d98, | ||
| 1153 | } | ||
| 1154 | }; | ||
| 1155 | |||
| 1156 | static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff) | ||
| 1157 | { | ||
| 1158 | return dib8000_set_gpio(fe, 5, 0, !onoff); | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff) | ||
| 1162 | { | ||
| 1163 | return dib8000_set_gpio(fe, 0, 0, onoff); | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = { | ||
| 1167 | { 240, 7}, | ||
| 1168 | { 0xffff, 6}, | ||
| 1169 | }; | ||
| 1170 | |||
| 1171 | static struct dib0070_config dib807x_dib0070_config[2] = { | ||
| 1172 | { | ||
| 1173 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
| 1174 | .reset = dib80xx_tuner_reset, | ||
| 1175 | .sleep = dib80xx_tuner_sleep, | ||
| 1176 | .clock_khz = 12000, | ||
| 1177 | .clock_pad_drive = 4, | ||
| 1178 | .vga_filter = 1, | ||
| 1179 | .force_crystal_mode = 1, | ||
| 1180 | .enable_third_order_filter = 1, | ||
| 1181 | .charge_pump = 0, | ||
| 1182 | .wbd_gain = dib8070_wbd_gain_cfg, | ||
| 1183 | .osc_buffer_state = 0, | ||
| 1184 | .freq_offset_khz_uhf = -100, | ||
| 1185 | .freq_offset_khz_vhf = -100, | ||
| 1186 | }, { | ||
| 1187 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
| 1188 | .reset = dib80xx_tuner_reset, | ||
| 1189 | .sleep = dib80xx_tuner_sleep, | ||
| 1190 | .clock_khz = 12000, | ||
| 1191 | .clock_pad_drive = 2, | ||
| 1192 | .vga_filter = 1, | ||
| 1193 | .force_crystal_mode = 1, | ||
| 1194 | .enable_third_order_filter = 1, | ||
| 1195 | .charge_pump = 0, | ||
| 1196 | .wbd_gain = dib8070_wbd_gain_cfg, | ||
| 1197 | .osc_buffer_state = 0, | ||
| 1198 | .freq_offset_khz_uhf = -25, | ||
| 1199 | .freq_offset_khz_vhf = -25, | ||
| 1200 | } | ||
| 1201 | }; | ||
| 1202 | |||
| 1203 | static int dib807x_set_param_override(struct dvb_frontend *fe, | ||
| 1204 | struct dvb_frontend_parameters *fep) | ||
| 1205 | { | ||
| 1206 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 1207 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1208 | |||
| 1209 | u16 offset = dib0070_wbd_offset(fe); | ||
| 1210 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
| 1211 | switch (band) { | ||
| 1212 | case BAND_VHF: | ||
| 1213 | offset += 750; | ||
| 1214 | break; | ||
| 1215 | case BAND_UHF: /* fall-thru wanted */ | ||
| 1216 | default: | ||
| 1217 | offset += 250; break; | ||
| 1218 | } | ||
| 1219 | deb_info("WBD for DiB8000: %d\n", offset); | ||
| 1220 | dib8000_set_wbd_ref(fe, offset); | ||
| 1221 | |||
| 1222 | return state->set_param_save(fe, fep); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | static int dib807x_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1226 | { | ||
| 1227 | struct dib0700_adapter_state *st = adap->priv; | ||
| 1228 | struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, | ||
| 1229 | DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 1230 | |||
| 1231 | if (adap->id == 0) { | ||
| 1232 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, | ||
| 1233 | &dib807x_dib0070_config[0]) == NULL) | ||
| 1234 | return -ENODEV; | ||
| 1235 | } else { | ||
| 1236 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, | ||
| 1237 | &dib807x_dib0070_config[1]) == NULL) | ||
| 1238 | return -ENODEV; | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
| 1242 | adap->fe->ops.tuner_ops.set_params = dib807x_set_param_override; | ||
| 1243 | return 0; | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index, | ||
| 1247 | u16 pid, int onoff) | ||
| 1248 | { | ||
| 1249 | return dib8000_pid_filter(adapter->fe, index, pid, onoff); | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter, | ||
| 1253 | int onoff) | ||
| 1254 | { | ||
| 1255 | return dib8000_pid_filter_ctrl(adapter->fe, onoff); | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | /* STK807x */ | ||
| 1259 | static int stk807x_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1260 | { | ||
| 1261 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 1262 | msleep(10); | ||
| 1263 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 1264 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 1265 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 1266 | |||
| 1267 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 1268 | |||
| 1269 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 1270 | |||
| 1271 | msleep(10); | ||
| 1272 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 1273 | msleep(10); | ||
| 1274 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 1275 | |||
| 1276 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | ||
| 1277 | 0x80); | ||
| 1278 | |||
| 1279 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, | ||
| 1280 | &dib807x_dib8000_config[0]); | ||
| 1281 | |||
| 1282 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | /* STK807xPVR */ | ||
| 1286 | static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) | ||
| 1287 | { | ||
| 1288 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | ||
| 1289 | msleep(30); | ||
| 1290 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 1291 | msleep(500); | ||
| 1292 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 1293 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 1294 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 1295 | |||
| 1296 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 1297 | |||
| 1298 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 1299 | |||
| 1300 | msleep(10); | ||
| 1301 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 1302 | msleep(10); | ||
| 1303 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 1304 | |||
| 1305 | /* initialize IC 0 */ | ||
| 1306 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80); | ||
| 1307 | |||
| 1308 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, | ||
| 1309 | &dib807x_dib8000_config[0]); | ||
| 1310 | |||
| 1311 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) | ||
| 1315 | { | ||
| 1316 | /* initialize IC 1 */ | ||
| 1317 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82); | ||
| 1318 | |||
| 1319 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, | ||
| 1320 | &dib807x_dib8000_config[1]); | ||
| 1321 | |||
| 1322 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | /* STK8096GP */ | ||
| 1326 | struct dibx000_agc_config dib8090_agc_config[2] = { | ||
| 1327 | { | ||
| 1328 | BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, | ||
| 1329 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, | ||
| 1330 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | ||
| 1331 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | ||
| 1332 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | ||
| 1333 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
| 1334 | |||
| 1335 | 787, | ||
| 1336 | 10, | ||
| 1337 | |||
| 1338 | 0, | ||
| 1339 | 118, | ||
| 1340 | |||
| 1341 | 0, | ||
| 1342 | 3530, | ||
| 1343 | 1, | ||
| 1344 | 5, | ||
| 1345 | |||
| 1346 | 65535, | ||
| 1347 | 0, | ||
| 1348 | |||
| 1349 | 65535, | ||
| 1350 | 0, | ||
| 1351 | |||
| 1352 | 0, | ||
| 1353 | 32, | ||
| 1354 | 114, | ||
| 1355 | 143, | ||
| 1356 | 144, | ||
| 1357 | 114, | ||
| 1358 | 227, | ||
| 1359 | 116, | ||
| 1360 | 117, | ||
| 1361 | |||
| 1362 | 28, | ||
| 1363 | 26, | ||
| 1364 | 31, | ||
| 1365 | 51, | ||
| 1366 | |||
| 1367 | 0, | ||
| 1368 | }, | ||
| 1369 | { | ||
| 1370 | BAND_CBAND, | ||
| 1371 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, | ||
| 1372 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | ||
| 1373 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | ||
| 1374 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | ||
| 1375 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
| 1376 | |||
| 1377 | 787, | ||
| 1378 | 10, | ||
| 1379 | |||
| 1380 | 0, | ||
| 1381 | 118, | ||
| 1382 | |||
| 1383 | 0, | ||
| 1384 | 3530, | ||
| 1385 | 1, | ||
| 1386 | 5, | ||
| 1387 | |||
| 1388 | 0, | ||
| 1389 | 0, | ||
| 1390 | |||
| 1391 | 65535, | ||
| 1392 | 0, | ||
| 1393 | |||
| 1394 | 0, | ||
| 1395 | 32, | ||
| 1396 | 114, | ||
| 1397 | 143, | ||
| 1398 | 144, | ||
| 1399 | 114, | ||
| 1400 | 227, | ||
| 1401 | 116, | ||
| 1402 | 117, | ||
| 1403 | |||
| 1404 | 28, | ||
| 1405 | 26, | ||
| 1406 | 31, | ||
| 1407 | 51, | ||
| 1408 | |||
| 1409 | 0, | ||
| 1410 | } | ||
| 1411 | }; | ||
| 1412 | |||
| 1413 | static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = { | ||
| 1414 | 54000, 13500, | ||
| 1415 | 1, 18, 3, 1, 0, | ||
| 1416 | 0, 0, 1, 1, 2, | ||
| 1417 | (3 << 14) | (1 << 12) | (599 << 0), | ||
| 1418 | (0 << 25) | 0, | ||
| 1419 | 20199727, | ||
| 1420 | 12000000, | ||
| 1421 | }; | ||
| 1422 | |||
| 1423 | static int dib8090_get_adc_power(struct dvb_frontend *fe) | ||
| 1424 | { | ||
| 1425 | return dib8000_get_adc_power(fe, 1); | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | static struct dib8000_config dib809x_dib8000_config[2] = { | ||
| 1429 | { | ||
| 1430 | .output_mpeg2_in_188_bytes = 1, | ||
| 1431 | |||
| 1432 | .agc_config_count = 2, | ||
| 1433 | .agc = dib8090_agc_config, | ||
| 1434 | .agc_control = dib0090_dcc_freq, | ||
| 1435 | .pll = &dib8090_pll_config_12mhz, | ||
| 1436 | .tuner_is_baseband = 1, | ||
| 1437 | |||
| 1438 | .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS, | ||
| 1439 | .gpio_val = DIB8000_GPIO_DEFAULT_VALUES, | ||
| 1440 | .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS, | ||
| 1441 | |||
| 1442 | .hostbus_diversity = 1, | ||
| 1443 | .div_cfg = 0x31, | ||
| 1444 | .output_mode = OUTMODE_MPEG2_FIFO, | ||
| 1445 | .drives = 0x2d98, | ||
| 1446 | .diversity_delay = 48, | ||
| 1447 | .refclksel = 3, | ||
| 1448 | }, { | ||
| 1449 | .output_mpeg2_in_188_bytes = 1, | ||
| 1450 | |||
| 1451 | .agc_config_count = 2, | ||
| 1452 | .agc = dib8090_agc_config, | ||
| 1453 | .agc_control = dib0090_dcc_freq, | ||
| 1454 | .pll = &dib8090_pll_config_12mhz, | ||
| 1455 | .tuner_is_baseband = 1, | ||
| 1456 | |||
| 1457 | .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS, | ||
| 1458 | .gpio_val = DIB8000_GPIO_DEFAULT_VALUES, | ||
| 1459 | .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS, | ||
| 1460 | |||
| 1461 | .hostbus_diversity = 1, | ||
| 1462 | .div_cfg = 0x31, | ||
| 1463 | .output_mode = OUTMODE_DIVERSITY, | ||
| 1464 | .drives = 0x2d08, | ||
| 1465 | .diversity_delay = 1, | ||
| 1466 | .refclksel = 3, | ||
| 1467 | } | ||
| 1468 | }; | ||
| 1469 | |||
| 1470 | static struct dib0090_wbd_slope dib8090_wbd_table[] = { | ||
| 1471 | /* max freq ; cold slope ; cold offset ; warm slope ; warm offset ; wbd gain */ | ||
| 1472 | { 120, 0, 500, 0, 500, 4 }, /* CBAND */ | ||
| 1473 | { 170, 0, 450, 0, 450, 4 }, /* CBAND */ | ||
| 1474 | { 380, 48, 373, 28, 259, 6 }, /* VHF */ | ||
| 1475 | { 860, 34, 700, 36, 616, 6 }, /* high UHF */ | ||
| 1476 | { 0xFFFF, 34, 700, 36, 616, 6 }, /* default */ | ||
| 1477 | }; | ||
| 1478 | |||
| 1479 | static struct dib0090_config dib809x_dib0090_config = { | ||
| 1480 | .io.pll_bypass = 1, | ||
| 1481 | .io.pll_range = 1, | ||
| 1482 | .io.pll_prediv = 1, | ||
| 1483 | .io.pll_loopdiv = 20, | ||
| 1484 | .io.adc_clock_ratio = 8, | ||
| 1485 | .io.pll_int_loop_filt = 0, | ||
| 1486 | .io.clock_khz = 12000, | ||
| 1487 | .reset = dib80xx_tuner_reset, | ||
| 1488 | .sleep = dib80xx_tuner_sleep, | ||
| 1489 | .clkouttobamse = 1, | ||
| 1490 | .analog_output = 1, | ||
| 1491 | .i2c_address = DEFAULT_DIB0090_I2C_ADDRESS, | ||
| 1492 | .use_pwm_agc = 1, | ||
| 1493 | .clkoutdrive = 1, | ||
| 1494 | .get_adc_power = dib8090_get_adc_power, | ||
| 1495 | .freq_offset_khz_uhf = -63, | ||
| 1496 | .freq_offset_khz_vhf = -143, | ||
| 1497 | .wbd = dib8090_wbd_table, | ||
| 1498 | .fref_clock_ratio = 6, | ||
| 1499 | }; | ||
| 1500 | |||
| 1501 | static int dib8096_set_param_override(struct dvb_frontend *fe, | ||
| 1502 | struct dvb_frontend_parameters *fep) | ||
| 1503 | { | ||
| 1504 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 1505 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1506 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
| 1507 | u16 target; | ||
| 1508 | int ret = 0; | ||
| 1509 | enum frontend_tune_state tune_state = CT_SHUTDOWN; | ||
| 1510 | u16 ltgain, rf_gain_limit; | ||
| 1511 | |||
| 1512 | ret = state->set_param_save(fe, fep); | ||
| 1513 | if (ret < 0) | ||
| 1514 | return ret; | ||
| 1515 | |||
| 1516 | target = (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2; | ||
| 1517 | dib8000_set_wbd_ref(fe, target); | ||
| 1518 | |||
| 1519 | |||
| 1520 | if (band == BAND_CBAND) { | ||
| 1521 | deb_info("tuning in CBAND - soft-AGC startup\n"); | ||
| 1522 | dib0090_set_tune_state(fe, CT_AGC_START); | ||
| 1523 | do { | ||
| 1524 | ret = dib0090_gain_control(fe); | ||
| 1525 | msleep(ret); | ||
| 1526 | tune_state = dib0090_get_tune_state(fe); | ||
| 1527 | if (tune_state == CT_AGC_STEP_0) | ||
| 1528 | dib8000_set_gpio(fe, 6, 0, 1); | ||
| 1529 | else if (tune_state == CT_AGC_STEP_1) { | ||
| 1530 | dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, <gain); | ||
| 1531 | if (rf_gain_limit == 0) | ||
| 1532 | dib8000_set_gpio(fe, 6, 0, 0); | ||
| 1533 | } | ||
| 1534 | } while (tune_state < CT_AGC_STOP); | ||
| 1535 | dib0090_pwm_gain_reset(fe); | ||
| 1536 | dib8000_pwm_agc_reset(fe); | ||
| 1537 | dib8000_set_tune_state(fe, CT_DEMOD_START); | ||
| 1538 | } else { | ||
| 1539 | deb_info("not tuning in CBAND - standard AGC startup\n"); | ||
| 1540 | dib0090_pwm_gain_reset(fe); | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | return 0; | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | static int dib809x_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1547 | { | ||
| 1548 | struct dib0700_adapter_state *st = adap->priv; | ||
| 1549 | struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 1550 | |||
| 1551 | if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL) | ||
| 1552 | return -ENODEV; | ||
| 1553 | |||
| 1554 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
| 1555 | adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override; | ||
| 1556 | return 0; | ||
| 1557 | } | ||
| 1558 | |||
| 1559 | static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1560 | { | ||
| 1561 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 1562 | msleep(10); | ||
| 1563 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 1564 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 1565 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 1566 | |||
| 1567 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 1568 | |||
| 1569 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 1570 | |||
| 1571 | msleep(10); | ||
| 1572 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 1573 | msleep(10); | ||
| 1574 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 1575 | |||
| 1576 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80); | ||
| 1577 | |||
| 1578 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]); | ||
| 1579 | |||
| 1580 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1584 | { | ||
| 1585 | struct dib0700_adapter_state *st = adap->priv; | ||
| 1586 | struct i2c_adapter *tun_i2c; | ||
| 1587 | struct dvb_frontend *fe_slave = dib8000_get_slave_frontend(adap->fe, 1); | ||
| 1588 | |||
| 1589 | if (fe_slave) { | ||
| 1590 | tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 1591 | if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL) | ||
| 1592 | return -ENODEV; | ||
| 1593 | fe_slave->dvb = adap->fe->dvb; | ||
| 1594 | fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override; | ||
| 1595 | } | ||
| 1596 | tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 1597 | if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL) | ||
| 1598 | return -ENODEV; | ||
| 1599 | |||
| 1600 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
| 1601 | adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override; | ||
| 1602 | |||
| 1603 | return 0; | ||
| 1604 | } | ||
| 1605 | |||
| 1606 | static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1607 | { | ||
| 1608 | struct dvb_frontend *fe_slave; | ||
| 1609 | |||
| 1610 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | ||
| 1611 | msleep(20); | ||
| 1612 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 1613 | msleep(1000); | ||
| 1614 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 1615 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 1616 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 1617 | |||
| 1618 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 1619 | |||
| 1620 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 1621 | |||
| 1622 | msleep(20); | ||
| 1623 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 1624 | msleep(20); | ||
| 1625 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 1626 | |||
| 1627 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80); | ||
| 1628 | |||
| 1629 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]); | ||
| 1630 | if (adap->fe == NULL) | ||
| 1631 | return -ENODEV; | ||
| 1632 | |||
| 1633 | fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]); | ||
| 1634 | dib8000_set_slave_frontend(adap->fe, fe_slave); | ||
| 1635 | |||
| 1636 | return fe_slave == NULL ? -ENODEV : 0; | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | /* STK9090M */ | ||
| 1640 | static int dib90x0_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) | ||
| 1641 | { | ||
| 1642 | return dib9000_fw_pid_filter(adapter->fe, index, pid, onoff); | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | static int dib90x0_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) | ||
| 1646 | { | ||
| 1647 | return dib9000_fw_pid_filter_ctrl(adapter->fe, onoff); | ||
| 1648 | } | ||
| 1649 | |||
| 1650 | static int dib90x0_tuner_reset(struct dvb_frontend *fe, int onoff) | ||
| 1651 | { | ||
| 1652 | return dib9000_set_gpio(fe, 5, 0, !onoff); | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | static int dib90x0_tuner_sleep(struct dvb_frontend *fe, int onoff) | ||
| 1656 | { | ||
| 1657 | return dib9000_set_gpio(fe, 0, 0, onoff); | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | static int dib01x0_pmu_update(struct i2c_adapter *i2c, u16 *data, u8 len) | ||
| 1661 | { | ||
| 1662 | u8 wb[4] = { 0xc >> 8, 0xc & 0xff, 0, 0 }; | ||
| 1663 | u8 rb[2]; | ||
| 1664 | struct i2c_msg msg[2] = { | ||
| 1665 | {.addr = 0x1e >> 1, .flags = 0, .buf = wb, .len = 2}, | ||
| 1666 | {.addr = 0x1e >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2}, | ||
| 1667 | }; | ||
| 1668 | u8 index_data; | ||
| 1669 | |||
| 1670 | dibx000_i2c_set_speed(i2c, 250); | ||
| 1671 | |||
| 1672 | if (i2c_transfer(i2c, msg, 2) != 2) | ||
| 1673 | return -EIO; | ||
| 1674 | |||
| 1675 | switch (rb[0] << 8 | rb[1]) { | ||
| 1676 | case 0: | ||
| 1677 | deb_info("Found DiB0170 rev1: This version of DiB0170 is not supported any longer.\n"); | ||
| 1678 | return -EIO; | ||
| 1679 | case 1: | ||
| 1680 | deb_info("Found DiB0170 rev2"); | ||
| 1681 | break; | ||
| 1682 | case 2: | ||
| 1683 | deb_info("Found DiB0190 rev2"); | ||
| 1684 | break; | ||
| 1685 | default: | ||
| 1686 | deb_info("DiB01x0 not found"); | ||
| 1687 | return -EIO; | ||
| 1688 | } | ||
| 1689 | |||
| 1690 | for (index_data = 0; index_data < len; index_data += 2) { | ||
| 1691 | wb[2] = (data[index_data + 1] >> 8) & 0xff; | ||
| 1692 | wb[3] = (data[index_data + 1]) & 0xff; | ||
| 1693 | |||
| 1694 | if (data[index_data] == 0) { | ||
| 1695 | wb[0] = (data[index_data] >> 8) & 0xff; | ||
| 1696 | wb[1] = (data[index_data]) & 0xff; | ||
| 1697 | msg[0].len = 2; | ||
| 1698 | if (i2c_transfer(i2c, msg, 2) != 2) | ||
| 1699 | return -EIO; | ||
| 1700 | wb[2] |= rb[0]; | ||
| 1701 | wb[3] |= rb[1] & ~(3 << 4); | ||
| 1702 | } | ||
| 1703 | |||
| 1704 | wb[0] = (data[index_data] >> 8)&0xff; | ||
| 1705 | wb[1] = (data[index_data])&0xff; | ||
| 1706 | msg[0].len = 4; | ||
| 1707 | if (i2c_transfer(i2c, &msg[0], 1) != 1) | ||
| 1708 | return -EIO; | ||
| 1709 | } | ||
| 1710 | return 0; | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | static struct dib9000_config stk9090m_config = { | ||
| 1714 | .output_mpeg2_in_188_bytes = 1, | ||
| 1715 | .output_mode = OUTMODE_MPEG2_FIFO, | ||
| 1716 | .vcxo_timer = 279620, | ||
| 1717 | .timing_frequency = 20452225, | ||
| 1718 | .demod_clock_khz = 60000, | ||
| 1719 | .xtal_clock_khz = 30000, | ||
| 1720 | .if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0), | ||
| 1721 | .subband = { | ||
| 1722 | 2, | ||
| 1723 | { | ||
| 1724 | { 240, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0008, 0x0000, 0x0008 } }, /* GPIO 3 to 1 for VHF */ | ||
| 1725 | { 890, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0008, 0x0000, 0x0000 } }, /* GPIO 3 to 0 for UHF */ | ||
| 1726 | { 0 }, | ||
| 1727 | }, | ||
| 1728 | }, | ||
| 1729 | .gpio_function = { | ||
| 1730 | { .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_ON, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = (0x10 & ~0x1) | 0x20 }, | ||
| 1731 | { .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_OFF, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = 0 | 0x21 }, | ||
| 1732 | }, | ||
| 1733 | }; | ||
| 1734 | |||
| 1735 | static struct dib9000_config nim9090md_config[2] = { | ||
| 1736 | { | ||
| 1737 | .output_mpeg2_in_188_bytes = 1, | ||
| 1738 | .output_mode = OUTMODE_MPEG2_FIFO, | ||
| 1739 | .vcxo_timer = 279620, | ||
| 1740 | .timing_frequency = 20452225, | ||
| 1741 | .demod_clock_khz = 60000, | ||
| 1742 | .xtal_clock_khz = 30000, | ||
| 1743 | .if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0), | ||
| 1744 | }, { | ||
| 1745 | .output_mpeg2_in_188_bytes = 1, | ||
| 1746 | .output_mode = OUTMODE_DIVERSITY, | ||
| 1747 | .vcxo_timer = 279620, | ||
| 1748 | .timing_frequency = 20452225, | ||
| 1749 | .demod_clock_khz = 60000, | ||
| 1750 | .xtal_clock_khz = 30000, | ||
| 1751 | .if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0), | ||
| 1752 | .subband = { | ||
| 1753 | 2, | ||
| 1754 | { | ||
| 1755 | { 240, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0006, 0x0000, 0x0006 } }, /* GPIO 1 and 2 to 1 for VHF */ | ||
| 1756 | { 890, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0006, 0x0000, 0x0000 } }, /* GPIO 1 and 2 to 0 for UHF */ | ||
| 1757 | { 0 }, | ||
| 1758 | }, | ||
| 1759 | }, | ||
| 1760 | .gpio_function = { | ||
| 1761 | { .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_ON, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = (0x10 & ~0x1) | 0x20 }, | ||
| 1762 | { .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_OFF, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = 0 | 0x21 }, | ||
| 1763 | }, | ||
| 1764 | } | ||
| 1765 | }; | ||
| 1766 | |||
| 1767 | static struct dib0090_config dib9090_dib0090_config = { | ||
| 1768 | .io.pll_bypass = 0, | ||
| 1769 | .io.pll_range = 1, | ||
| 1770 | .io.pll_prediv = 1, | ||
| 1771 | .io.pll_loopdiv = 8, | ||
| 1772 | .io.adc_clock_ratio = 8, | ||
| 1773 | .io.pll_int_loop_filt = 0, | ||
| 1774 | .io.clock_khz = 30000, | ||
| 1775 | .reset = dib90x0_tuner_reset, | ||
| 1776 | .sleep = dib90x0_tuner_sleep, | ||
| 1777 | .clkouttobamse = 0, | ||
| 1778 | .analog_output = 0, | ||
| 1779 | .use_pwm_agc = 0, | ||
| 1780 | .clkoutdrive = 0, | ||
| 1781 | .freq_offset_khz_uhf = 0, | ||
| 1782 | .freq_offset_khz_vhf = 0, | ||
| 1783 | }; | ||
| 1784 | |||
| 1785 | static struct dib0090_config nim9090md_dib0090_config[2] = { | ||
| 1786 | { | ||
| 1787 | .io.pll_bypass = 0, | ||
| 1788 | .io.pll_range = 1, | ||
| 1789 | .io.pll_prediv = 1, | ||
| 1790 | .io.pll_loopdiv = 8, | ||
| 1791 | .io.adc_clock_ratio = 8, | ||
| 1792 | .io.pll_int_loop_filt = 0, | ||
| 1793 | .io.clock_khz = 30000, | ||
| 1794 | .reset = dib90x0_tuner_reset, | ||
| 1795 | .sleep = dib90x0_tuner_sleep, | ||
| 1796 | .clkouttobamse = 1, | ||
| 1797 | .analog_output = 0, | ||
| 1798 | .use_pwm_agc = 0, | ||
| 1799 | .clkoutdrive = 0, | ||
| 1800 | .freq_offset_khz_uhf = 0, | ||
| 1801 | .freq_offset_khz_vhf = 0, | ||
| 1802 | }, { | ||
| 1803 | .io.pll_bypass = 0, | ||
| 1804 | .io.pll_range = 1, | ||
| 1805 | .io.pll_prediv = 1, | ||
| 1806 | .io.pll_loopdiv = 8, | ||
| 1807 | .io.adc_clock_ratio = 8, | ||
| 1808 | .io.pll_int_loop_filt = 0, | ||
| 1809 | .io.clock_khz = 30000, | ||
| 1810 | .reset = dib90x0_tuner_reset, | ||
| 1811 | .sleep = dib90x0_tuner_sleep, | ||
| 1812 | .clkouttobamse = 0, | ||
| 1813 | .analog_output = 0, | ||
| 1814 | .use_pwm_agc = 0, | ||
| 1815 | .clkoutdrive = 0, | ||
| 1816 | .freq_offset_khz_uhf = 0, | ||
| 1817 | .freq_offset_khz_vhf = 0, | ||
| 1818 | } | ||
| 1819 | }; | ||
| 1820 | |||
| 1821 | |||
| 1822 | static int stk9090m_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1823 | { | ||
| 1824 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1825 | struct dib0700_state *st = adap->dev->priv; | ||
| 1826 | u32 fw_version; | ||
| 1827 | |||
| 1828 | /* Make use of the new i2c functions from FW 1.20 */ | ||
| 1829 | dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL); | ||
| 1830 | if (fw_version >= 0x10200) | ||
| 1831 | st->fw_use_new_i2c_api = 1; | ||
| 1832 | dib0700_set_i2c_speed(adap->dev, 340); | ||
| 1833 | |||
| 1834 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 1835 | msleep(20); | ||
| 1836 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 1837 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 1838 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 1839 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 1840 | |||
| 1841 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 1842 | |||
| 1843 | msleep(20); | ||
| 1844 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 1845 | msleep(20); | ||
| 1846 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 1847 | |||
| 1848 | dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80); | ||
| 1849 | |||
| 1850 | if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) { | ||
| 1851 | deb_info("%s: Upload failed. (file not found?)\n", __func__); | ||
| 1852 | return -ENODEV; | ||
| 1853 | } else { | ||
| 1854 | deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size); | ||
| 1855 | } | ||
| 1856 | stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size; | ||
| 1857 | stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data; | ||
| 1858 | |||
| 1859 | adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config); | ||
| 1860 | |||
| 1861 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 1862 | } | ||
| 1863 | |||
| 1864 | static int dib9090_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1865 | { | ||
| 1866 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1867 | struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe); | ||
| 1868 | u16 data_dib190[10] = { | ||
| 1869 | 1, 0x1374, | ||
| 1870 | 2, 0x01a2, | ||
| 1871 | 7, 0x0020, | ||
| 1872 | 0, 0x00ef, | ||
| 1873 | 8, 0x0486, | ||
| 1874 | }; | ||
| 1875 | |||
| 1876 | if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &dib9090_dib0090_config) == NULL) | ||
| 1877 | return -ENODEV; | ||
| 1878 | i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0); | ||
| 1879 | if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0) | ||
| 1880 | return -ENODEV; | ||
| 1881 | dib0700_set_i2c_speed(adap->dev, 2000); | ||
| 1882 | if (dib9000_firmware_post_pll_init(adap->fe) < 0) | ||
| 1883 | return -ENODEV; | ||
| 1884 | release_firmware(state->frontend_firmware); | ||
| 1885 | return 0; | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | static int nim9090md_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 1889 | { | ||
| 1890 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1891 | struct dib0700_state *st = adap->dev->priv; | ||
| 1892 | struct i2c_adapter *i2c; | ||
| 1893 | struct dvb_frontend *fe_slave; | ||
| 1894 | u32 fw_version; | ||
| 1895 | |||
| 1896 | /* Make use of the new i2c functions from FW 1.20 */ | ||
| 1897 | dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL); | ||
| 1898 | if (fw_version >= 0x10200) | ||
| 1899 | st->fw_use_new_i2c_api = 1; | ||
| 1900 | dib0700_set_i2c_speed(adap->dev, 340); | ||
| 1901 | |||
| 1902 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 1903 | msleep(20); | ||
| 1904 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 1905 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 1906 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 1907 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 1908 | |||
| 1909 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 1910 | |||
| 1911 | msleep(20); | ||
| 1912 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 1913 | msleep(20); | ||
| 1914 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 1915 | |||
| 1916 | if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) { | ||
| 1917 | deb_info("%s: Upload failed. (file not found?)\n", __func__); | ||
| 1918 | return -EIO; | ||
| 1919 | } else { | ||
| 1920 | deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size); | ||
| 1921 | } | ||
| 1922 | nim9090md_config[0].microcode_B_fe_size = state->frontend_firmware->size; | ||
| 1923 | nim9090md_config[0].microcode_B_fe_buffer = state->frontend_firmware->data; | ||
| 1924 | nim9090md_config[1].microcode_B_fe_size = state->frontend_firmware->size; | ||
| 1925 | nim9090md_config[1].microcode_B_fe_buffer = state->frontend_firmware->data; | ||
| 1926 | |||
| 1927 | dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, 0x80); | ||
| 1928 | adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]); | ||
| 1929 | |||
| 1930 | if (adap->fe == NULL) | ||
| 1931 | return -ENODEV; | ||
| 1932 | |||
| 1933 | i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0); | ||
| 1934 | dib9000_i2c_enumeration(i2c, 1, 0x12, 0x82); | ||
| 1935 | |||
| 1936 | fe_slave = dvb_attach(dib9000_attach, i2c, 0x82, &nim9090md_config[1]); | ||
| 1937 | dib9000_set_slave_frontend(adap->fe, fe_slave); | ||
| 1938 | |||
| 1939 | return fe_slave == NULL ? -ENODEV : 0; | ||
| 1940 | } | ||
| 1941 | |||
| 1942 | static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1943 | { | ||
| 1944 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1945 | struct i2c_adapter *i2c; | ||
| 1946 | struct dvb_frontend *fe_slave; | ||
| 1947 | u16 data_dib190[10] = { | ||
| 1948 | 1, 0x5374, | ||
| 1949 | 2, 0x01ae, | ||
| 1950 | 7, 0x0020, | ||
| 1951 | 0, 0x00ef, | ||
| 1952 | 8, 0x0406, | ||
| 1953 | }; | ||
| 1954 | i2c = dib9000_get_tuner_interface(adap->fe); | ||
| 1955 | if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &nim9090md_dib0090_config[0]) == NULL) | ||
| 1956 | return -ENODEV; | ||
| 1957 | i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0); | ||
| 1958 | if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0) | ||
| 1959 | return -ENODEV; | ||
| 1960 | dib0700_set_i2c_speed(adap->dev, 2000); | ||
| 1961 | if (dib9000_firmware_post_pll_init(adap->fe) < 0) | ||
| 1962 | return -ENODEV; | ||
| 1963 | |||
| 1964 | fe_slave = dib9000_get_slave_frontend(adap->fe, 1); | ||
| 1965 | if (fe_slave != NULL) { | ||
| 1966 | i2c = dib9000_get_component_bus_interface(adap->fe); | ||
| 1967 | dib9000_set_i2c_adapter(fe_slave, i2c); | ||
| 1968 | |||
| 1969 | i2c = dib9000_get_tuner_interface(fe_slave); | ||
| 1970 | if (dvb_attach(dib0090_fw_register, fe_slave, i2c, &nim9090md_dib0090_config[1]) == NULL) | ||
| 1971 | return -ENODEV; | ||
| 1972 | fe_slave->dvb = adap->fe->dvb; | ||
| 1973 | dib9000_fw_set_component_bus_speed(adap->fe, 2000); | ||
| 1974 | if (dib9000_firmware_post_pll_init(fe_slave) < 0) | ||
| 1975 | return -ENODEV; | ||
| 1976 | } | ||
| 1977 | release_firmware(state->frontend_firmware); | ||
| 1978 | |||
| 1979 | return 0; | ||
| 1980 | } | ||
| 1981 | |||
| 1982 | /* NIM7090 */ | ||
| 1983 | struct dib7090p_best_adc { | ||
| 1984 | u32 timf; | ||
| 1985 | u32 pll_loopdiv; | ||
| 1986 | u32 pll_prediv; | ||
| 1987 | }; | ||
| 1988 | |||
| 1989 | static int dib7090p_get_best_sampling(struct dvb_frontend *fe , struct dib7090p_best_adc *adc) | ||
| 1990 | { | ||
| 1991 | u8 spur = 0, prediv = 0, loopdiv = 0, min_prediv = 1, max_prediv = 1; | ||
| 1992 | |||
| 1993 | u16 xtal = 12000; | ||
| 1994 | u32 fcp_min = 1900; /* PLL Minimum Frequency comparator KHz */ | ||
| 1995 | u32 fcp_max = 20000; /* PLL Maximum Frequency comparator KHz */ | ||
| 1996 | u32 fdem_max = 76000; | ||
| 1997 | u32 fdem_min = 69500; | ||
| 1998 | u32 fcp = 0, fs = 0, fdem = 0; | ||
| 1999 | u32 harmonic_id = 0; | ||
| 2000 | |||
| 2001 | adc->pll_loopdiv = loopdiv; | ||
| 2002 | adc->pll_prediv = prediv; | ||
| 2003 | adc->timf = 0; | ||
| 2004 | |||
| 2005 | deb_info("bandwidth = %d fdem_min =%d", fe->dtv_property_cache.bandwidth_hz, fdem_min); | ||
| 2006 | |||
| 2007 | /* Find Min and Max prediv */ | ||
| 2008 | while ((xtal/max_prediv) >= fcp_min) | ||
| 2009 | max_prediv++; | ||
| 2010 | |||
| 2011 | max_prediv--; | ||
| 2012 | min_prediv = max_prediv; | ||
| 2013 | while ((xtal/min_prediv) <= fcp_max) { | ||
| 2014 | min_prediv--; | ||
| 2015 | if (min_prediv == 1) | ||
| 2016 | break; | ||
| 2017 | } | ||
| 2018 | deb_info("MIN prediv = %d : MAX prediv = %d", min_prediv, max_prediv); | ||
| 2019 | |||
| 2020 | min_prediv = 2; | ||
| 2021 | |||
| 2022 | for (prediv = min_prediv ; prediv < max_prediv; prediv++) { | ||
| 2023 | fcp = xtal / prediv; | ||
| 2024 | if (fcp > fcp_min && fcp < fcp_max) { | ||
| 2025 | for (loopdiv = 1 ; loopdiv < 64 ; loopdiv++) { | ||
| 2026 | fdem = ((xtal/prediv) * loopdiv); | ||
| 2027 | fs = fdem / 4; | ||
| 2028 | /* test min/max system restrictions */ | ||
| 2029 | |||
| 2030 | if ((fdem >= fdem_min) && (fdem <= fdem_max) && (fs >= fe->dtv_property_cache.bandwidth_hz/1000)) { | ||
| 2031 | spur = 0; | ||
| 2032 | /* test fs harmonics positions */ | ||
| 2033 | for (harmonic_id = (fe->dtv_property_cache.frequency / (1000*fs)) ; harmonic_id <= ((fe->dtv_property_cache.frequency / (1000*fs))+1) ; harmonic_id++) { | ||
| 2034 | if (((fs*harmonic_id) >= ((fe->dtv_property_cache.frequency/1000) - (fe->dtv_property_cache.bandwidth_hz/2000))) && ((fs*harmonic_id) <= ((fe->dtv_property_cache.frequency/1000) + (fe->dtv_property_cache.bandwidth_hz/2000)))) { | ||
| 2035 | spur = 1; | ||
| 2036 | break; | ||
| 2037 | } | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | if (!spur) { | ||
| 2041 | adc->pll_loopdiv = loopdiv; | ||
| 2042 | adc->pll_prediv = prediv; | ||
| 2043 | adc->timf = 2396745143UL/fdem*(1 << 9); | ||
| 2044 | adc->timf += ((2396745143UL%fdem) << 9)/fdem; | ||
| 2045 | deb_info("loopdiv=%i prediv=%i timf=%i", loopdiv, prediv, adc->timf); | ||
| 2046 | break; | ||
| 2047 | } | ||
| 2048 | } | ||
| 2049 | } | ||
| 2050 | } | ||
| 2051 | if (!spur) | ||
| 2052 | break; | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | |||
| 2056 | if (adc->pll_loopdiv == 0 && adc->pll_prediv == 0) | ||
| 2057 | return -EINVAL; | ||
| 2058 | else | ||
| 2059 | return 0; | ||
| 2060 | } | ||
| 2061 | |||
| 2062 | static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | ||
| 2063 | { | ||
| 2064 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 2065 | struct dib0700_adapter_state *state = adap->priv; | ||
| 2066 | struct dibx000_bandwidth_config pll; | ||
| 2067 | u16 target; | ||
| 2068 | struct dib7090p_best_adc adc; | ||
| 2069 | int ret; | ||
| 2070 | |||
| 2071 | ret = state->set_param_save(fe, fep); | ||
| 2072 | if (ret < 0) | ||
| 2073 | return ret; | ||
| 2074 | |||
| 2075 | memset(&pll, 0, sizeof(struct dibx000_bandwidth_config)); | ||
| 2076 | dib0090_pwm_gain_reset(fe); | ||
| 2077 | target = (dib0090_get_wbd_offset(fe) * 8 + 1) / 2; | ||
| 2078 | dib7000p_set_wbd_ref(fe, target); | ||
| 2079 | |||
| 2080 | if (dib7090p_get_best_sampling(fe, &adc) == 0) { | ||
| 2081 | pll.pll_ratio = adc.pll_loopdiv; | ||
| 2082 | pll.pll_prediv = adc.pll_prediv; | ||
| 2083 | |||
| 2084 | dib7000p_update_pll(fe, &pll); | ||
| 2085 | dib7000p_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf); | ||
| 2086 | } | ||
| 2087 | return 0; | ||
| 2088 | } | ||
| 2089 | |||
| 2090 | static struct dib0090_wbd_slope dib7090_wbd_table[] = { | ||
| 2091 | { 380, 81, 850, 64, 540, 4}, | ||
| 2092 | { 860, 51, 866, 21, 375, 4}, | ||
| 2093 | {1700, 0, 250, 0, 100, 6}, | ||
| 2094 | {2600, 0, 250, 0, 100, 6}, | ||
| 2095 | { 0xFFFF, 0, 0, 0, 0, 0}, | ||
| 2096 | }; | ||
| 2097 | |||
| 2098 | struct dibx000_agc_config dib7090_agc_config[2] = { | ||
| 2099 | { | ||
| 2100 | .band_caps = BAND_UHF, | ||
| 2101 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
| 2102 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | ||
| 2103 | .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
| 2104 | |||
| 2105 | .inv_gain = 687, | ||
| 2106 | .time_stabiliz = 10, | ||
| 2107 | |||
| 2108 | .alpha_level = 0, | ||
| 2109 | .thlock = 118, | ||
| 2110 | |||
| 2111 | .wbd_inv = 0, | ||
| 2112 | .wbd_ref = 1200, | ||
| 2113 | .wbd_sel = 3, | ||
| 2114 | .wbd_alpha = 5, | ||
| 2115 | |||
| 2116 | .agc1_max = 65535, | ||
| 2117 | .agc1_min = 0, | ||
| 2118 | |||
| 2119 | .agc2_max = 65535, | ||
| 2120 | .agc2_min = 0, | ||
| 2121 | |||
| 2122 | .agc1_pt1 = 0, | ||
| 2123 | .agc1_pt2 = 32, | ||
| 2124 | .agc1_pt3 = 114, | ||
| 2125 | .agc1_slope1 = 143, | ||
| 2126 | .agc1_slope2 = 144, | ||
| 2127 | .agc2_pt1 = 114, | ||
| 2128 | .agc2_pt2 = 227, | ||
| 2129 | .agc2_slope1 = 116, | ||
| 2130 | .agc2_slope2 = 117, | ||
| 2131 | |||
| 2132 | .alpha_mant = 18, | ||
| 2133 | .alpha_exp = 0, | ||
| 2134 | .beta_mant = 20, | ||
| 2135 | .beta_exp = 59, | ||
| 2136 | |||
| 2137 | .perform_agc_softsplit = 0, | ||
| 2138 | } , { | ||
| 2139 | .band_caps = BAND_FM | BAND_VHF | BAND_CBAND, | ||
| 2140 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
| 2141 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | ||
| 2142 | .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
| 2143 | |||
| 2144 | .inv_gain = 732, | ||
| 2145 | .time_stabiliz = 10, | ||
| 2146 | |||
| 2147 | .alpha_level = 0, | ||
| 2148 | .thlock = 118, | ||
| 2149 | |||
| 2150 | .wbd_inv = 0, | ||
| 2151 | .wbd_ref = 1200, | ||
| 2152 | .wbd_sel = 3, | ||
| 2153 | .wbd_alpha = 5, | ||
| 2154 | |||
| 2155 | .agc1_max = 65535, | ||
| 2156 | .agc1_min = 0, | ||
| 2157 | |||
| 2158 | .agc2_max = 65535, | ||
| 2159 | .agc2_min = 0, | ||
| 2160 | |||
| 2161 | .agc1_pt1 = 0, | ||
| 2162 | .agc1_pt2 = 0, | ||
| 2163 | .agc1_pt3 = 98, | ||
| 2164 | .agc1_slope1 = 0, | ||
| 2165 | .agc1_slope2 = 167, | ||
| 2166 | .agc2_pt1 = 98, | ||
| 2167 | .agc2_pt2 = 255, | ||
| 2168 | .agc2_slope1 = 104, | ||
| 2169 | .agc2_slope2 = 0, | ||
| 2170 | |||
| 2171 | .alpha_mant = 18, | ||
| 2172 | .alpha_exp = 0, | ||
| 2173 | .beta_mant = 20, | ||
| 2174 | .beta_exp = 59, | ||
| 2175 | |||
| 2176 | .perform_agc_softsplit = 0, | ||
| 2177 | } | ||
| 2178 | }; | ||
| 2179 | |||
| 2180 | static struct dibx000_bandwidth_config dib7090_clock_config_12_mhz = { | ||
| 2181 | 60000, 15000, | ||
| 2182 | 1, 5, 0, 0, 0, | ||
| 2183 | 0, 0, 1, 1, 2, | ||
| 2184 | (3 << 14) | (1 << 12) | (524 << 0), | ||
| 2185 | (0 << 25) | 0, | ||
| 2186 | 20452225, | ||
| 2187 | 15000000, | ||
| 2188 | }; | ||
| 2189 | |||
| 2190 | static struct dib7000p_config nim7090_dib7000p_config = { | ||
| 2191 | .output_mpeg2_in_188_bytes = 1, | ||
| 2192 | .hostbus_diversity = 1, | ||
| 2193 | .tuner_is_baseband = 1, | ||
| 2194 | .update_lna = NULL, | ||
| 2195 | |||
| 2196 | .agc_config_count = 2, | ||
| 2197 | .agc = dib7090_agc_config, | ||
| 2198 | |||
| 2199 | .bw = &dib7090_clock_config_12_mhz, | ||
| 2200 | |||
| 2201 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
| 2202 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
| 2203 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 2204 | |||
| 2205 | .pwm_freq_div = 0, | ||
| 2206 | |||
| 2207 | .agc_control = dib7090_agc_restart, | ||
| 2208 | |||
| 2209 | .spur_protect = 0, | ||
| 2210 | .disable_sample_and_hold = 0, | ||
| 2211 | .enable_current_mirror = 0, | ||
| 2212 | .diversity_delay = 0, | ||
| 2213 | |||
| 2214 | .output_mode = OUTMODE_MPEG2_FIFO, | ||
| 2215 | .enMpegOutput = 1, | ||
| 2216 | }; | ||
| 2217 | |||
| 2218 | static struct dib7000p_config tfe7090pvr_dib7000p_config[2] = { | ||
| 2219 | { | ||
| 2220 | .output_mpeg2_in_188_bytes = 1, | ||
| 2221 | .hostbus_diversity = 1, | ||
| 2222 | .tuner_is_baseband = 1, | ||
| 2223 | .update_lna = NULL, | ||
| 2224 | |||
| 2225 | .agc_config_count = 2, | ||
| 2226 | .agc = dib7090_agc_config, | ||
| 2227 | |||
| 2228 | .bw = &dib7090_clock_config_12_mhz, | ||
| 2229 | |||
| 2230 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
| 2231 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
| 2232 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 2233 | |||
| 2234 | .pwm_freq_div = 0, | ||
| 2235 | |||
| 2236 | .agc_control = dib7090_agc_restart, | ||
| 2237 | |||
| 2238 | .spur_protect = 0, | ||
| 2239 | .disable_sample_and_hold = 0, | ||
| 2240 | .enable_current_mirror = 0, | ||
| 2241 | .diversity_delay = 0, | ||
| 2242 | |||
| 2243 | .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, | ||
| 2244 | .default_i2c_addr = 0x90, | ||
| 2245 | .enMpegOutput = 1, | ||
| 2246 | }, { | ||
| 2247 | .output_mpeg2_in_188_bytes = 1, | ||
| 2248 | .hostbus_diversity = 1, | ||
| 2249 | .tuner_is_baseband = 1, | ||
| 2250 | .update_lna = NULL, | ||
| 2251 | |||
| 2252 | .agc_config_count = 2, | ||
| 2253 | .agc = dib7090_agc_config, | ||
| 2254 | |||
| 2255 | .bw = &dib7090_clock_config_12_mhz, | ||
| 2256 | |||
| 2257 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
| 2258 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
| 2259 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 2260 | |||
| 2261 | .pwm_freq_div = 0, | ||
| 2262 | |||
| 2263 | .agc_control = dib7090_agc_restart, | ||
| 2264 | |||
| 2265 | .spur_protect = 0, | ||
| 2266 | .disable_sample_and_hold = 0, | ||
| 2267 | .enable_current_mirror = 0, | ||
| 2268 | .diversity_delay = 0, | ||
| 2269 | |||
| 2270 | .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, | ||
| 2271 | .default_i2c_addr = 0x92, | ||
| 2272 | .enMpegOutput = 0, | ||
| 2273 | } | ||
| 2274 | }; | ||
| 2275 | |||
| 2276 | static const struct dib0090_config nim7090_dib0090_config = { | ||
| 2277 | .io.clock_khz = 12000, | ||
| 2278 | .io.pll_bypass = 0, | ||
| 2279 | .io.pll_range = 0, | ||
| 2280 | .io.pll_prediv = 3, | ||
| 2281 | .io.pll_loopdiv = 6, | ||
| 2282 | .io.adc_clock_ratio = 0, | ||
| 2283 | .io.pll_int_loop_filt = 0, | ||
| 2284 | .reset = dib7090_tuner_sleep, | ||
| 2285 | .sleep = dib7090_tuner_sleep, | ||
| 2286 | |||
| 2287 | .freq_offset_khz_uhf = 0, | ||
| 2288 | .freq_offset_khz_vhf = 0, | ||
| 2289 | |||
| 2290 | .get_adc_power = dib7090_get_adc_power, | ||
| 2291 | |||
| 2292 | .clkouttobamse = 1, | ||
| 2293 | .analog_output = 0, | ||
| 2294 | |||
| 2295 | .wbd_vhf_offset = 0, | ||
| 2296 | .wbd_cband_offset = 0, | ||
| 2297 | .use_pwm_agc = 1, | ||
| 2298 | .clkoutdrive = 0, | ||
| 2299 | |||
| 2300 | .fref_clock_ratio = 0, | ||
| 2301 | |||
| 2302 | .wbd = dib7090_wbd_table, | ||
| 2303 | |||
| 2304 | .ls_cfg_pad_drv = 0, | ||
| 2305 | .data_tx_drv = 0, | ||
| 2306 | .low_if = NULL, | ||
| 2307 | .in_soc = 1, | ||
| 2308 | }; | ||
| 2309 | |||
| 2310 | static const struct dib0090_config tfe7090pvr_dib0090_config[2] = { | ||
| 2311 | { | ||
| 2312 | .io.clock_khz = 12000, | ||
| 2313 | .io.pll_bypass = 0, | ||
| 2314 | .io.pll_range = 0, | ||
| 2315 | .io.pll_prediv = 3, | ||
| 2316 | .io.pll_loopdiv = 6, | ||
| 2317 | .io.adc_clock_ratio = 0, | ||
| 2318 | .io.pll_int_loop_filt = 0, | ||
| 2319 | .reset = dib7090_tuner_sleep, | ||
| 2320 | .sleep = dib7090_tuner_sleep, | ||
| 2321 | |||
| 2322 | .freq_offset_khz_uhf = 50, | ||
| 2323 | .freq_offset_khz_vhf = 70, | ||
| 2324 | |||
| 2325 | .get_adc_power = dib7090_get_adc_power, | ||
| 2326 | |||
| 2327 | .clkouttobamse = 1, | ||
| 2328 | .analog_output = 0, | ||
| 2329 | |||
| 2330 | .wbd_vhf_offset = 0, | ||
| 2331 | .wbd_cband_offset = 0, | ||
| 2332 | .use_pwm_agc = 1, | ||
| 2333 | .clkoutdrive = 0, | ||
| 2334 | |||
| 2335 | .fref_clock_ratio = 0, | ||
| 2336 | |||
| 2337 | .wbd = dib7090_wbd_table, | ||
| 2338 | |||
| 2339 | .ls_cfg_pad_drv = 0, | ||
| 2340 | .data_tx_drv = 0, | ||
| 2341 | .low_if = NULL, | ||
| 2342 | .in_soc = 1, | ||
| 2343 | }, { | ||
| 2344 | .io.clock_khz = 12000, | ||
| 2345 | .io.pll_bypass = 0, | ||
| 2346 | .io.pll_range = 0, | ||
| 2347 | .io.pll_prediv = 3, | ||
| 2348 | .io.pll_loopdiv = 6, | ||
| 2349 | .io.adc_clock_ratio = 0, | ||
| 2350 | .io.pll_int_loop_filt = 0, | ||
| 2351 | .reset = dib7090_tuner_sleep, | ||
| 2352 | .sleep = dib7090_tuner_sleep, | ||
| 2353 | |||
| 2354 | .freq_offset_khz_uhf = -50, | ||
| 2355 | .freq_offset_khz_vhf = -70, | ||
| 2356 | |||
| 2357 | .get_adc_power = dib7090_get_adc_power, | ||
| 2358 | |||
| 2359 | .clkouttobamse = 1, | ||
| 2360 | .analog_output = 0, | ||
| 2361 | |||
| 2362 | .wbd_vhf_offset = 0, | ||
| 2363 | .wbd_cband_offset = 0, | ||
| 2364 | .use_pwm_agc = 1, | ||
| 2365 | .clkoutdrive = 0, | ||
| 2366 | |||
| 2367 | .fref_clock_ratio = 0, | ||
| 2368 | |||
| 2369 | .wbd = dib7090_wbd_table, | ||
| 2370 | |||
| 2371 | .ls_cfg_pad_drv = 0, | ||
| 2372 | .data_tx_drv = 0, | ||
| 2373 | .low_if = NULL, | ||
| 2374 | .in_soc = 1, | ||
| 2375 | } | ||
| 2376 | }; | ||
| 2377 | |||
| 2378 | static int nim7090_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 2379 | { | ||
| 2380 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 2381 | msleep(20); | ||
| 2382 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 2383 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 2384 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 2385 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 2386 | |||
| 2387 | msleep(20); | ||
| 2388 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 2389 | msleep(20); | ||
| 2390 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 2391 | |||
| 2392 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) { | ||
| 2393 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__); | ||
| 2394 | return -ENODEV; | ||
| 2395 | } | ||
| 2396 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config); | ||
| 2397 | |||
| 2398 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 2399 | } | ||
| 2400 | |||
| 2401 | static int nim7090_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 2402 | { | ||
| 2403 | struct dib0700_adapter_state *st = adap->priv; | ||
| 2404 | struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe); | ||
| 2405 | |||
| 2406 | if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &nim7090_dib0090_config) == NULL) | ||
| 2407 | return -ENODEV; | ||
| 2408 | |||
| 2409 | dib7000p_set_gpio(adap->fe, 8, 0, 1); | ||
| 2410 | |||
| 2411 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
| 2412 | adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup; | ||
| 2413 | return 0; | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap) | ||
| 2417 | { | ||
| 2418 | struct dib0700_state *st = adap->dev->priv; | ||
| 2419 | |||
| 2420 | /* The TFE7090 requires the dib0700 to not be in master mode */ | ||
| 2421 | st->disable_streaming_master_mode = 1; | ||
| 2422 | |||
| 2423 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 2424 | msleep(20); | ||
| 2425 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 2426 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 2427 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 2428 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 2429 | |||
| 2430 | msleep(20); | ||
| 2431 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 2432 | msleep(20); | ||
| 2433 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 2434 | |||
| 2435 | /* initialize IC 0 */ | ||
| 2436 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) { | ||
| 2437 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__); | ||
| 2438 | return -ENODEV; | ||
| 2439 | } | ||
| 2440 | |||
| 2441 | dib0700_set_i2c_speed(adap->dev, 340); | ||
| 2442 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]); | ||
| 2443 | if (adap->fe == NULL) | ||
| 2444 | return -ENODEV; | ||
| 2445 | |||
| 2446 | dib7090_slave_reset(adap->fe); | ||
| 2447 | |||
| 2448 | return 0; | ||
| 2449 | } | ||
| 2450 | |||
| 2451 | static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap) | ||
| 2452 | { | ||
| 2453 | struct i2c_adapter *i2c; | ||
| 2454 | |||
| 2455 | if (adap->dev->adapter[0].fe == NULL) { | ||
| 2456 | err("the master dib7090 has to be initialized first"); | ||
| 2457 | return -ENODEV; /* the master device has not been initialized */ | ||
| 2458 | } | ||
| 2459 | |||
| 2460 | i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1); | ||
| 2461 | if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) { | ||
| 2462 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__); | ||
| 2463 | return -ENODEV; | ||
| 2464 | } | ||
| 2465 | |||
| 2466 | adap->fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]); | ||
| 2467 | dib0700_set_i2c_speed(adap->dev, 200); | ||
| 2468 | |||
| 2469 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 2470 | } | ||
| 2471 | |||
| 2472 | static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap) | ||
| 2473 | { | ||
| 2474 | struct dib0700_adapter_state *st = adap->priv; | ||
| 2475 | struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe); | ||
| 2476 | |||
| 2477 | if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL) | ||
| 2478 | return -ENODEV; | ||
| 2479 | |||
| 2480 | dib7000p_set_gpio(adap->fe, 8, 0, 1); | ||
| 2481 | |||
| 2482 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
| 2483 | adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup; | ||
| 2484 | return 0; | ||
| 2485 | } | ||
| 2486 | |||
| 2487 | static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap) | ||
| 2488 | { | ||
| 2489 | struct dib0700_adapter_state *st = adap->priv; | ||
| 2490 | struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe); | ||
| 2491 | |||
| 2492 | if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL) | ||
| 2493 | return -ENODEV; | ||
| 2494 | |||
| 2495 | dib7000p_set_gpio(adap->fe, 8, 0, 1); | ||
| 2496 | |||
| 2497 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
| 2498 | adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup; | ||
| 2499 | return 0; | ||
| 2500 | } | ||
| 2501 | |||
| 2502 | /* STK7070PD */ | ||
| 2503 | static struct dib7000p_config stk7070pd_dib7000p_config[2] = { | ||
| 2504 | { | ||
| 2505 | .output_mpeg2_in_188_bytes = 1, | ||
| 2506 | |||
| 2507 | .agc_config_count = 1, | ||
| 2508 | .agc = &dib7070_agc_config, | ||
| 2509 | .bw = &dib7070_bw_config_12_mhz, | ||
| 2510 | .tuner_is_baseband = 1, | ||
| 2511 | .spur_protect = 1, | ||
| 2512 | |||
| 2513 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
| 2514 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
| 2515 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 2516 | |||
| 2517 | .hostbus_diversity = 1, | ||
| 2518 | }, { | ||
| 2519 | .output_mpeg2_in_188_bytes = 1, | ||
| 2520 | |||
| 2521 | .agc_config_count = 1, | ||
| 2522 | .agc = &dib7070_agc_config, | ||
| 2523 | .bw = &dib7070_bw_config_12_mhz, | ||
| 2524 | .tuner_is_baseband = 1, | ||
| 2525 | .spur_protect = 1, | ||
| 2526 | |||
| 2527 | .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, | ||
| 2528 | .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, | ||
| 2529 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
| 2530 | |||
| 2531 | .hostbus_diversity = 1, | ||
| 2532 | } | ||
| 2533 | }; | ||
| 2534 | |||
| 2535 | static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap) | ||
| 2536 | { | ||
| 2537 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 2538 | msleep(10); | ||
| 2539 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 2540 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 2541 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 2542 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 2543 | |||
| 2544 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 2545 | |||
| 2546 | msleep(10); | ||
| 2547 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 2548 | msleep(10); | ||
| 2549 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 2550 | |||
| 2551 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, | ||
| 2552 | stk7070pd_dib7000p_config) != 0) { | ||
| 2553 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | ||
| 2554 | __func__); | ||
| 2555 | return -ENODEV; | ||
| 2556 | } | ||
| 2557 | |||
| 2558 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]); | ||
| 2559 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 2560 | } | ||
| 2561 | |||
| 2562 | static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap) | ||
| 2563 | { | ||
| 2564 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]); | ||
| 2565 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 2566 | } | ||
| 2567 | |||
| 2568 | /* S5H1411 */ | ||
| 2569 | static struct s5h1411_config pinnacle_801e_config = { | ||
| 2570 | .output_mode = S5H1411_PARALLEL_OUTPUT, | ||
| 2571 | .gpio = S5H1411_GPIO_OFF, | ||
| 2572 | .mpeg_timing = S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, | ||
| 2573 | .qam_if = S5H1411_IF_44000, | ||
| 2574 | .vsb_if = S5H1411_IF_44000, | ||
| 2575 | .inversion = S5H1411_INVERSION_OFF, | ||
| 2576 | .status_mode = S5H1411_DEMODLOCKING | ||
| 2577 | }; | ||
| 2578 | |||
| 2579 | /* Pinnacle PCTV HD Pro 801e GPIOs map: | ||
| 2580 | GPIO0 - currently unknown | ||
| 2581 | GPIO1 - xc5000 tuner reset | ||
| 2582 | GPIO2 - CX25843 sleep | ||
| 2583 | GPIO3 - currently unknown | ||
| 2584 | GPIO4 - currently unknown | ||
| 2585 | GPIO6 - currently unknown | ||
| 2586 | GPIO7 - currently unknown | ||
| 2587 | GPIO9 - currently unknown | ||
| 2588 | GPIO10 - CX25843 reset | ||
| 2589 | */ | ||
| 2590 | static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 2591 | { | ||
| 2592 | struct dib0700_state *st = adap->dev->priv; | ||
| 2593 | |||
| 2594 | /* Make use of the new i2c functions from FW 1.20 */ | ||
| 2595 | st->fw_use_new_i2c_api = 1; | ||
| 2596 | |||
| 2597 | /* The s5h1411 requires the dib0700 to not be in master mode */ | ||
| 2598 | st->disable_streaming_master_mode = 1; | ||
| 2599 | |||
| 2600 | /* All msleep values taken from Windows USB trace */ | ||
| 2601 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0); | ||
| 2602 | dib0700_set_gpio(adap->dev, GPIO3, GPIO_OUT, 0); | ||
| 2603 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 2604 | msleep(400); | ||
| 2605 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 2606 | msleep(60); | ||
| 2607 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 2608 | msleep(30); | ||
| 2609 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
| 2610 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
| 2611 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
| 2612 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
| 2613 | dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 0); | ||
| 2614 | msleep(30); | ||
| 2615 | |||
| 2616 | /* Put the CX25843 to sleep for now since we're in digital mode */ | ||
| 2617 | dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1); | ||
| 2618 | |||
| 2619 | /* GPIOs are initialized, do the attach */ | ||
| 2620 | adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config, | ||
| 2621 | &adap->dev->i2c_adap); | ||
| 2622 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 2623 | } | ||
| 2624 | |||
| 2625 | static int dib0700_xc5000_tuner_callback(void *priv, int component, | ||
| 2626 | int command, int arg) | ||
| 2627 | { | ||
| 2628 | struct dvb_usb_adapter *adap = priv; | ||
| 2629 | |||
| 2630 | if (command == XC5000_TUNER_RESET) { | ||
| 2631 | /* Reset the tuner */ | ||
| 2632 | dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0); | ||
| 2633 | msleep(10); | ||
| 2634 | dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1); | ||
| 2635 | msleep(10); | ||
| 2636 | } else { | ||
| 2637 | err("xc5000: unknown tuner callback command: %d\n", command); | ||
| 2638 | return -EINVAL; | ||
| 2639 | } | ||
| 2640 | |||
| 2641 | return 0; | ||
| 2642 | } | ||
| 2643 | |||
| 2644 | static struct xc5000_config s5h1411_xc5000_tunerconfig = { | ||
| 2645 | .i2c_address = 0x64, | ||
| 2646 | .if_khz = 5380, | ||
| 2647 | }; | ||
| 2648 | |||
| 2649 | static int xc5000_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 2650 | { | ||
| 2651 | /* FIXME: generalize & move to common area */ | ||
| 2652 | adap->fe->callback = dib0700_xc5000_tuner_callback; | ||
| 2653 | |||
| 2654 | return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 2655 | &s5h1411_xc5000_tunerconfig) | ||
| 2656 | == NULL ? -ENODEV : 0; | ||
| 2657 | } | ||
| 2658 | |||
| 2659 | static int dib0700_xc4000_tuner_callback(void *priv, int component, | ||
| 2660 | int command, int arg) | ||
| 2661 | { | ||
| 2662 | struct dvb_usb_adapter *adap = priv; | ||
| 2663 | |||
| 2664 | if (command == XC4000_TUNER_RESET) { | ||
| 2665 | /* Reset the tuner */ | ||
| 2666 | dib7000p_set_gpio(adap->fe, 8, 0, 0); | ||
| 2667 | msleep(10); | ||
| 2668 | dib7000p_set_gpio(adap->fe, 8, 0, 1); | ||
| 2669 | } else { | ||
| 2670 | err("xc4000: unknown tuner callback command: %d\n", command); | ||
| 2671 | return -EINVAL; | ||
| 2672 | } | ||
| 2673 | |||
| 2674 | return 0; | ||
| 2675 | } | ||
| 2676 | |||
| 2677 | static struct dibx000_agc_config stk7700p_7000p_xc4000_agc_config = { | ||
| 2678 | .band_caps = BAND_UHF | BAND_VHF, | ||
| 2679 | .setup = 0x64, | ||
| 2680 | .inv_gain = 0x02c8, | ||
| 2681 | .time_stabiliz = 0x15, | ||
| 2682 | .alpha_level = 0x00, | ||
| 2683 | .thlock = 0x76, | ||
| 2684 | .wbd_inv = 0x01, | ||
| 2685 | .wbd_ref = 0x0b33, | ||
| 2686 | .wbd_sel = 0x00, | ||
| 2687 | .wbd_alpha = 0x02, | ||
| 2688 | .agc1_max = 0x00, | ||
| 2689 | .agc1_min = 0x00, | ||
| 2690 | .agc2_max = 0x9b26, | ||
| 2691 | .agc2_min = 0x26ca, | ||
| 2692 | .agc1_pt1 = 0x00, | ||
| 2693 | .agc1_pt2 = 0x00, | ||
| 2694 | .agc1_pt3 = 0x00, | ||
| 2695 | .agc1_slope1 = 0x00, | ||
| 2696 | .agc1_slope2 = 0x00, | ||
| 2697 | .agc2_pt1 = 0x00, | ||
| 2698 | .agc2_pt2 = 0x80, | ||
| 2699 | .agc2_slope1 = 0x1d, | ||
| 2700 | .agc2_slope2 = 0x1d, | ||
| 2701 | .alpha_mant = 0x11, | ||
| 2702 | .alpha_exp = 0x1b, | ||
| 2703 | .beta_mant = 0x17, | ||
| 2704 | .beta_exp = 0x33, | ||
| 2705 | .perform_agc_softsplit = 0x00, | ||
| 2706 | }; | ||
| 2707 | |||
| 2708 | static struct dibx000_bandwidth_config stk7700p_xc4000_pll_config = { | ||
| 2709 | 60000, 30000, /* internal, sampling */ | ||
| 2710 | 1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */ | ||
| 2711 | 0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, */ | ||
| 2712 | /* ADClkSrc, modulo */ | ||
| 2713 | (3 << 14) | (1 << 12) | 524, /* sad_cfg: refsel, sel, freq_15k */ | ||
| 2714 | 39370534, /* ifreq */ | ||
| 2715 | 20452225, /* timf */ | ||
| 2716 | 30000000 /* xtal */ | ||
| 2717 | }; | ||
| 2718 | |||
| 2719 | /* FIXME: none of these inputs are validated yet */ | ||
| 2720 | static struct dib7000p_config pctv_340e_config = { | ||
| 2721 | .output_mpeg2_in_188_bytes = 1, | ||
| 2722 | |||
| 2723 | .agc_config_count = 1, | ||
| 2724 | .agc = &stk7700p_7000p_xc4000_agc_config, | ||
| 2725 | .bw = &stk7700p_xc4000_pll_config, | ||
| 2726 | |||
| 2727 | .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, | ||
| 2728 | .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, | ||
| 2729 | .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, | ||
| 2730 | }; | ||
| 2731 | |||
| 2732 | /* PCTV 340e GPIOs map: | ||
| 2733 | dib0700: | ||
| 2734 | GPIO2 - CX25843 sleep | ||
| 2735 | GPIO3 - CS5340 reset | ||
| 2736 | GPIO5 - IRD | ||
| 2737 | GPIO6 - Power Supply | ||
| 2738 | GPIO8 - LNA (1=off 0=on) | ||
| 2739 | GPIO10 - CX25843 reset | ||
| 2740 | dib7000: | ||
| 2741 | GPIO8 - xc4000 reset | ||
| 2742 | */ | ||
| 2743 | static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 2744 | { | ||
| 2745 | struct dib0700_state *st = adap->dev->priv; | ||
| 2746 | |||
| 2747 | /* Power Supply on */ | ||
| 2748 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | ||
| 2749 | msleep(50); | ||
| 2750 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 2751 | msleep(100); /* Allow power supply to settle before probing */ | ||
| 2752 | |||
| 2753 | /* cx25843 reset */ | ||
| 2754 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 2755 | msleep(1); /* cx25843 datasheet say 350us required */ | ||
| 2756 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 2757 | |||
| 2758 | /* LNA off for now */ | ||
| 2759 | dib0700_set_gpio(adap->dev, GPIO8, GPIO_OUT, 1); | ||
| 2760 | |||
| 2761 | /* Put the CX25843 to sleep for now since we're in digital mode */ | ||
| 2762 | dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1); | ||
| 2763 | |||
| 2764 | /* FIXME: not verified yet */ | ||
| 2765 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
| 2766 | |||
| 2767 | msleep(500); | ||
| 2768 | |||
| 2769 | if (dib7000pc_detection(&adap->dev->i2c_adap) == 0) { | ||
| 2770 | /* Demodulator not found for some reason? */ | ||
| 2771 | return -ENODEV; | ||
| 2772 | } | ||
| 2773 | |||
| 2774 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12, | ||
| 2775 | &pctv_340e_config); | ||
| 2776 | st->is_dib7000pc = 1; | ||
| 2777 | |||
| 2778 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 2779 | } | ||
| 2780 | |||
| 2781 | static struct xc4000_config dib7000p_xc4000_tunerconfig = { | ||
| 2782 | .i2c_address = 0x61, | ||
| 2783 | .default_pm = 1, | ||
| 2784 | .dvb_amplitude = 0, | ||
| 2785 | .set_smoothedcvbs = 0, | ||
| 2786 | .if_khz = 5400 | ||
| 2787 | }; | ||
| 2788 | |||
| 2789 | static int xc4000_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 2790 | { | ||
| 2791 | struct i2c_adapter *tun_i2c; | ||
| 2792 | |||
| 2793 | /* The xc4000 is not on the main i2c bus */ | ||
| 2794 | tun_i2c = dib7000p_get_i2c_master(adap->fe, | ||
| 2795 | DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 2796 | if (tun_i2c == NULL) { | ||
| 2797 | printk(KERN_ERR "Could not reach tuner i2c bus\n"); | ||
| 2798 | return 0; | ||
| 2799 | } | ||
| 2800 | |||
| 2801 | /* Setup the reset callback */ | ||
| 2802 | adap->fe->callback = dib0700_xc4000_tuner_callback; | ||
| 2803 | |||
| 2804 | return dvb_attach(xc4000_attach, adap->fe, tun_i2c, | ||
| 2805 | &dib7000p_xc4000_tunerconfig) | ||
| 2806 | == NULL ? -ENODEV : 0; | ||
| 2807 | } | ||
| 2808 | |||
| 2809 | static struct lgdt3305_config hcw_lgdt3305_config = { | ||
| 2810 | .i2c_addr = 0x0e, | ||
| 2811 | .mpeg_mode = LGDT3305_MPEG_PARALLEL, | ||
| 2812 | .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE, | ||
| 2813 | .tpvalid_polarity = LGDT3305_TP_VALID_LOW, | ||
| 2814 | .deny_i2c_rptr = 0, | ||
| 2815 | .spectral_inversion = 1, | ||
| 2816 | .qam_if_khz = 6000, | ||
| 2817 | .vsb_if_khz = 6000, | ||
| 2818 | .usref_8vsb = 0x0500, | ||
| 2819 | }; | ||
| 2820 | |||
| 2821 | static struct mxl5007t_config hcw_mxl5007t_config = { | ||
| 2822 | .xtal_freq_hz = MxL_XTAL_25_MHZ, | ||
| 2823 | .if_freq_hz = MxL_IF_6_MHZ, | ||
| 2824 | .invert_if = 1, | ||
| 2825 | }; | ||
| 2826 | |||
| 2827 | /* TIGER-ATSC map: | ||
| 2828 | GPIO0 - LNA_CTR (H: LNA power enabled, L: LNA power disabled) | ||
| 2829 | GPIO1 - ANT_SEL (H: VPA, L: MCX) | ||
| 2830 | GPIO4 - SCL2 | ||
| 2831 | GPIO6 - EN_TUNER | ||
| 2832 | GPIO7 - SDA2 | ||
| 2833 | GPIO10 - DEM_RST | ||
| 2834 | |||
| 2835 | MXL is behind LG's i2c repeater. LG is on SCL2/SDA2 gpios on the DIB | ||
| 2836 | */ | ||
| 2837 | static int lgdt3305_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 2838 | { | ||
| 2839 | struct dib0700_state *st = adap->dev->priv; | ||
| 2840 | |||
| 2841 | /* Make use of the new i2c functions from FW 1.20 */ | ||
| 2842 | st->fw_use_new_i2c_api = 1; | ||
| 2843 | |||
| 2844 | st->disable_streaming_master_mode = 1; | ||
| 2845 | |||
| 2846 | /* fe power enable */ | ||
| 2847 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | ||
| 2848 | msleep(30); | ||
| 2849 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
| 2850 | msleep(30); | ||
| 2851 | |||
| 2852 | /* demod reset */ | ||
| 2853 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 2854 | msleep(30); | ||
| 2855 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
| 2856 | msleep(30); | ||
| 2857 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
| 2858 | msleep(30); | ||
| 2859 | |||
| 2860 | adap->fe = dvb_attach(lgdt3305_attach, | ||
| 2861 | &hcw_lgdt3305_config, | ||
| 2862 | &adap->dev->i2c_adap); | ||
| 2863 | |||
| 2864 | return adap->fe == NULL ? -ENODEV : 0; | ||
| 2865 | } | ||
| 2866 | |||
| 2867 | static int mxl5007t_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 2868 | { | ||
| 2869 | return dvb_attach(mxl5007t_attach, adap->fe, | ||
| 2870 | &adap->dev->i2c_adap, 0x60, | ||
| 2871 | &hcw_mxl5007t_config) == NULL ? -ENODEV : 0; | ||
| 2872 | } | ||
| 2873 | |||
| 2874 | |||
| 2875 | /* DVB-USB and USB stuff follows */ | ||
| 2876 | struct usb_device_id dib0700_usb_id_table[] = { | ||
| 2877 | /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, | ||
| 2878 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, | ||
| 2879 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, | ||
| 2880 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, | ||
| 2881 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, | ||
| 2882 | /* 5 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, | ||
| 2883 | { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, | ||
| 2884 | { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, | ||
| 2885 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) }, | ||
| 2886 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) }, | ||
| 2887 | /* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) }, | ||
| 2888 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV2000E) }, | ||
| 2889 | { USB_DEVICE(USB_VID_TERRATEC, | ||
| 2890 | USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) }, | ||
| 2891 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) }, | ||
| 2892 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700D) }, | ||
| 2893 | /* 15 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070P) }, | ||
| 2894 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DVB_T_FLASH) }, | ||
| 2895 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070PD) }, | ||
| 2896 | { USB_DEVICE(USB_VID_PINNACLE, | ||
| 2897 | USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) }, | ||
| 2898 | { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500_PC) }, | ||
| 2899 | /* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) }, | ||
| 2900 | { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U7000) }, | ||
| 2901 | { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) }, | ||
| 2902 | { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000) }, | ||
| 2903 | { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100) }, | ||
| 2904 | /* 25 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) }, | ||
| 2905 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) }, | ||
| 2906 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_USB_XE) }, | ||
| 2907 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_EXPRESSCARD_320CX) }, | ||
| 2908 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV72E) }, | ||
| 2909 | /* 30 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73E) }, | ||
| 2910 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_EC372S) }, | ||
| 2911 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) }, | ||
| 2912 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) }, | ||
| 2913 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, | ||
| 2914 | /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, | ||
| 2915 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) }, | ||
| 2916 | { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U8000) }, | ||
| 2917 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700PH) }, | ||
| 2918 | { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, | ||
| 2919 | /* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) }, | ||
| 2920 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) }, | ||
| 2921 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_EXPRESS) }, | ||
| 2922 | { USB_DEVICE(USB_VID_TERRATEC, | ||
| 2923 | USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) }, | ||
| 2924 | { USB_DEVICE(USB_VID_SONY, USB_PID_SONY_PLAYTV) }, | ||
| 2925 | /* 45 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_PD378S) }, | ||
| 2926 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC) }, | ||
| 2927 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) }, | ||
| 2928 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_MC770) }, | ||
| 2929 | { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT) }, | ||
| 2930 | /* 50 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_Dlx) }, | ||
| 2931 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_H) }, | ||
| 2932 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T3) }, | ||
| 2933 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T5) }, | ||
| 2934 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) }, | ||
| 2935 | /* 55 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D_2) }, | ||
| 2936 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73A) }, | ||
| 2937 | { USB_DEVICE(USB_VID_PCTV, USB_PID_PINNACLE_PCTV73ESE) }, | ||
| 2938 | { USB_DEVICE(USB_VID_PCTV, USB_PID_PINNACLE_PCTV282E) }, | ||
| 2939 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7770P) }, | ||
| 2940 | /* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) }, | ||
| 2941 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) }, | ||
| 2942 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) }, | ||
| 2943 | { USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x000, 0x3f00) }, | ||
| 2944 | { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) }, | ||
| 2945 | /* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, | ||
| 2946 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, | ||
| 2947 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096GP) }, | ||
| 2948 | { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DIVERSITY) }, | ||
| 2949 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM9090M) }, | ||
| 2950 | /* 70 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM8096MD) }, | ||
| 2951 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM9090MD) }, | ||
| 2952 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_NIM7090) }, | ||
| 2953 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_TFE7090PVR) }, | ||
| 2954 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) }, | ||
| 2955 | /* 75 */{ USB_DEVICE(USB_VID_MEDION, USB_PID_CREATIX_CTX1921) }, | ||
| 2956 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E) }, | ||
| 2957 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV340E_SE) }, | ||
| 2958 | { 0 } /* Terminating entry */ | ||
| 2959 | }; | ||
| 2960 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | ||
| 2961 | |||
| 2962 | #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ | ||
| 2963 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ | ||
| 2964 | .usb_ctrl = DEVICE_SPECIFIC, \ | ||
| 2965 | .firmware = "dvb-usb-dib0700-1.20.fw", \ | ||
| 2966 | .download_firmware = dib0700_download_firmware, \ | ||
| 2967 | .no_reconnect = 1, \ | ||
| 2968 | .size_of_priv = sizeof(struct dib0700_state), \ | ||
| 2969 | .i2c_algo = &dib0700_i2c_algo, \ | ||
| 2970 | .identify_state = dib0700_identify_state | ||
| 2971 | |||
| 2972 | #define DIB0700_DEFAULT_STREAMING_CONFIG(ep) \ | ||
| 2973 | .streaming_ctrl = dib0700_streaming_ctrl, \ | ||
| 2974 | .stream = { \ | ||
| 2975 | .type = USB_BULK, \ | ||
| 2976 | .count = 4, \ | ||
| 2977 | .endpoint = ep, \ | ||
| 2978 | .u = { \ | ||
| 2979 | .bulk = { \ | ||
| 2980 | .buffersize = 39480, \ | ||
| 2981 | } \ | ||
| 2982 | } \ | ||
| 2983 | } | ||
| 2984 | |||
| 2985 | struct dvb_usb_device_properties dib0700_devices[] = { | ||
| 2986 | { | ||
| 2987 | DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 2988 | |||
| 2989 | .num_adapters = 1, | ||
| 2990 | .adapter = { | ||
| 2991 | { | ||
| 2992 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 2993 | .pid_filter_count = 32, | ||
| 2994 | .pid_filter = stk7700p_pid_filter, | ||
| 2995 | .pid_filter_ctrl = stk7700p_pid_filter_ctrl, | ||
| 2996 | .frontend_attach = stk7700p_frontend_attach, | ||
| 2997 | .tuner_attach = stk7700p_tuner_attach, | ||
| 2998 | |||
| 2999 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3000 | }, | ||
| 3001 | }, | ||
| 3002 | |||
| 3003 | .num_device_descs = 8, | ||
| 3004 | .devices = { | ||
| 3005 | { "DiBcom STK7700P reference design", | ||
| 3006 | { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, | ||
| 3007 | { NULL }, | ||
| 3008 | }, | ||
| 3009 | { "Hauppauge Nova-T Stick", | ||
| 3010 | { &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL }, | ||
| 3011 | { NULL }, | ||
| 3012 | }, | ||
| 3013 | { "AVerMedia AVerTV DVB-T Volar", | ||
| 3014 | { &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] }, | ||
| 3015 | { NULL }, | ||
| 3016 | }, | ||
| 3017 | { "Compro Videomate U500", | ||
| 3018 | { &dib0700_usb_id_table[6], &dib0700_usb_id_table[19] }, | ||
| 3019 | { NULL }, | ||
| 3020 | }, | ||
| 3021 | { "Uniwill STK7700P based (Hama and others)", | ||
| 3022 | { &dib0700_usb_id_table[7], NULL }, | ||
| 3023 | { NULL }, | ||
| 3024 | }, | ||
| 3025 | { "Leadtek Winfast DTV Dongle (STK7700P based)", | ||
| 3026 | { &dib0700_usb_id_table[8], &dib0700_usb_id_table[34] }, | ||
| 3027 | { NULL }, | ||
| 3028 | }, | ||
| 3029 | { "AVerMedia AVerTV DVB-T Express", | ||
| 3030 | { &dib0700_usb_id_table[20] }, | ||
| 3031 | { NULL }, | ||
| 3032 | }, | ||
| 3033 | { "Gigabyte U7000", | ||
| 3034 | { &dib0700_usb_id_table[21], NULL }, | ||
| 3035 | { NULL }, | ||
| 3036 | } | ||
| 3037 | }, | ||
| 3038 | |||
| 3039 | .rc.core = { | ||
| 3040 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3041 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3042 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3043 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3044 | RC_TYPE_RC6 | | ||
| 3045 | RC_TYPE_NEC, | ||
| 3046 | .change_protocol = dib0700_change_protocol, | ||
| 3047 | }, | ||
| 3048 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3049 | |||
| 3050 | .num_adapters = 2, | ||
| 3051 | .adapter = { | ||
| 3052 | { | ||
| 3053 | .frontend_attach = bristol_frontend_attach, | ||
| 3054 | .tuner_attach = bristol_tuner_attach, | ||
| 3055 | |||
| 3056 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3057 | }, { | ||
| 3058 | .frontend_attach = bristol_frontend_attach, | ||
| 3059 | .tuner_attach = bristol_tuner_attach, | ||
| 3060 | |||
| 3061 | DIB0700_DEFAULT_STREAMING_CONFIG(0x03), | ||
| 3062 | } | ||
| 3063 | }, | ||
| 3064 | |||
| 3065 | .num_device_descs = 1, | ||
| 3066 | .devices = { | ||
| 3067 | { "Hauppauge Nova-T 500 Dual DVB-T", | ||
| 3068 | { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL }, | ||
| 3069 | { NULL }, | ||
| 3070 | }, | ||
| 3071 | }, | ||
| 3072 | |||
| 3073 | .rc.core = { | ||
| 3074 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3075 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3076 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3077 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3078 | RC_TYPE_RC6 | | ||
| 3079 | RC_TYPE_NEC, | ||
| 3080 | .change_protocol = dib0700_change_protocol, | ||
| 3081 | }, | ||
| 3082 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3083 | |||
| 3084 | .num_adapters = 2, | ||
| 3085 | .adapter = { | ||
| 3086 | { | ||
| 3087 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3088 | .pid_filter_count = 32, | ||
| 3089 | .pid_filter = stk70x0p_pid_filter, | ||
| 3090 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3091 | .frontend_attach = stk7700d_frontend_attach, | ||
| 3092 | .tuner_attach = stk7700d_tuner_attach, | ||
| 3093 | |||
| 3094 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3095 | }, { | ||
| 3096 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3097 | .pid_filter_count = 32, | ||
| 3098 | .pid_filter = stk70x0p_pid_filter, | ||
| 3099 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3100 | .frontend_attach = stk7700d_frontend_attach, | ||
| 3101 | .tuner_attach = stk7700d_tuner_attach, | ||
| 3102 | |||
| 3103 | DIB0700_DEFAULT_STREAMING_CONFIG(0x03), | ||
| 3104 | } | ||
| 3105 | }, | ||
| 3106 | |||
| 3107 | .num_device_descs = 5, | ||
| 3108 | .devices = { | ||
| 3109 | { "Pinnacle PCTV 2000e", | ||
| 3110 | { &dib0700_usb_id_table[11], NULL }, | ||
| 3111 | { NULL }, | ||
| 3112 | }, | ||
| 3113 | { "Terratec Cinergy DT XS Diversity", | ||
| 3114 | { &dib0700_usb_id_table[12], NULL }, | ||
| 3115 | { NULL }, | ||
| 3116 | }, | ||
| 3117 | { "Hauppauge Nova-TD Stick/Elgato Eye-TV Diversity", | ||
| 3118 | { &dib0700_usb_id_table[13], NULL }, | ||
| 3119 | { NULL }, | ||
| 3120 | }, | ||
| 3121 | { "DiBcom STK7700D reference design", | ||
| 3122 | { &dib0700_usb_id_table[14], NULL }, | ||
| 3123 | { NULL }, | ||
| 3124 | }, | ||
| 3125 | { "YUAN High-Tech DiBcom STK7700D", | ||
| 3126 | { &dib0700_usb_id_table[55], NULL }, | ||
| 3127 | { NULL }, | ||
| 3128 | }, | ||
| 3129 | |||
| 3130 | }, | ||
| 3131 | |||
| 3132 | .rc.core = { | ||
| 3133 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3134 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3135 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3136 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3137 | RC_TYPE_RC6 | | ||
| 3138 | RC_TYPE_NEC, | ||
| 3139 | .change_protocol = dib0700_change_protocol, | ||
| 3140 | }, | ||
| 3141 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3142 | |||
| 3143 | .num_adapters = 1, | ||
| 3144 | .adapter = { | ||
| 3145 | { | ||
| 3146 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3147 | .pid_filter_count = 32, | ||
| 3148 | .pid_filter = stk70x0p_pid_filter, | ||
| 3149 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3150 | .frontend_attach = stk7700P2_frontend_attach, | ||
| 3151 | .tuner_attach = stk7700d_tuner_attach, | ||
| 3152 | |||
| 3153 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3154 | }, | ||
| 3155 | }, | ||
| 3156 | |||
| 3157 | .num_device_descs = 3, | ||
| 3158 | .devices = { | ||
| 3159 | { "ASUS My Cinema U3000 Mini DVBT Tuner", | ||
| 3160 | { &dib0700_usb_id_table[23], NULL }, | ||
| 3161 | { NULL }, | ||
| 3162 | }, | ||
| 3163 | { "Yuan EC372S", | ||
| 3164 | { &dib0700_usb_id_table[31], NULL }, | ||
| 3165 | { NULL }, | ||
| 3166 | }, | ||
| 3167 | { "Terratec Cinergy T Express", | ||
| 3168 | { &dib0700_usb_id_table[42], NULL }, | ||
| 3169 | { NULL }, | ||
| 3170 | } | ||
| 3171 | }, | ||
| 3172 | |||
| 3173 | .rc.core = { | ||
| 3174 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3175 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3176 | .module_name = "dib0700", | ||
| 3177 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3178 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3179 | RC_TYPE_RC6 | | ||
| 3180 | RC_TYPE_NEC, | ||
| 3181 | .change_protocol = dib0700_change_protocol, | ||
| 3182 | }, | ||
| 3183 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3184 | |||
| 3185 | .num_adapters = 1, | ||
| 3186 | .adapter = { | ||
| 3187 | { | ||
| 3188 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3189 | .pid_filter_count = 32, | ||
| 3190 | .pid_filter = stk70x0p_pid_filter, | ||
| 3191 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3192 | .frontend_attach = stk7070p_frontend_attach, | ||
| 3193 | .tuner_attach = dib7070p_tuner_attach, | ||
| 3194 | |||
| 3195 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3196 | |||
| 3197 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
| 3198 | }, | ||
| 3199 | }, | ||
| 3200 | |||
| 3201 | .num_device_descs = 11, | ||
| 3202 | .devices = { | ||
| 3203 | { "DiBcom STK7070P reference design", | ||
| 3204 | { &dib0700_usb_id_table[15], NULL }, | ||
| 3205 | { NULL }, | ||
| 3206 | }, | ||
| 3207 | { "Pinnacle PCTV DVB-T Flash Stick", | ||
| 3208 | { &dib0700_usb_id_table[16], NULL }, | ||
| 3209 | { NULL }, | ||
| 3210 | }, | ||
| 3211 | { "Artec T14BR DVB-T", | ||
| 3212 | { &dib0700_usb_id_table[22], NULL }, | ||
| 3213 | { NULL }, | ||
| 3214 | }, | ||
| 3215 | { "ASUS My Cinema U3100 Mini DVBT Tuner", | ||
| 3216 | { &dib0700_usb_id_table[24], NULL }, | ||
| 3217 | { NULL }, | ||
| 3218 | }, | ||
| 3219 | { "Hauppauge Nova-T Stick", | ||
| 3220 | { &dib0700_usb_id_table[25], NULL }, | ||
| 3221 | { NULL }, | ||
| 3222 | }, | ||
| 3223 | { "Hauppauge Nova-T MyTV.t", | ||
| 3224 | { &dib0700_usb_id_table[26], NULL }, | ||
| 3225 | { NULL }, | ||
| 3226 | }, | ||
| 3227 | { "Pinnacle PCTV 72e", | ||
| 3228 | { &dib0700_usb_id_table[29], NULL }, | ||
| 3229 | { NULL }, | ||
| 3230 | }, | ||
| 3231 | { "Pinnacle PCTV 73e", | ||
| 3232 | { &dib0700_usb_id_table[30], NULL }, | ||
| 3233 | { NULL }, | ||
| 3234 | }, | ||
| 3235 | { "Elgato EyeTV DTT", | ||
| 3236 | { &dib0700_usb_id_table[49], NULL }, | ||
| 3237 | { NULL }, | ||
| 3238 | }, | ||
| 3239 | { "Yuan PD378S", | ||
| 3240 | { &dib0700_usb_id_table[45], NULL }, | ||
| 3241 | { NULL }, | ||
| 3242 | }, | ||
| 3243 | { "Elgato EyeTV Dtt Dlx PD378S", | ||
| 3244 | { &dib0700_usb_id_table[50], NULL }, | ||
| 3245 | { NULL }, | ||
| 3246 | }, | ||
| 3247 | }, | ||
| 3248 | |||
| 3249 | .rc.core = { | ||
| 3250 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3251 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3252 | .module_name = "dib0700", | ||
| 3253 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3254 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3255 | RC_TYPE_RC6 | | ||
| 3256 | RC_TYPE_NEC, | ||
| 3257 | .change_protocol = dib0700_change_protocol, | ||
| 3258 | }, | ||
| 3259 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3260 | |||
| 3261 | .num_adapters = 1, | ||
| 3262 | .adapter = { | ||
| 3263 | { | ||
| 3264 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3265 | .pid_filter_count = 32, | ||
| 3266 | .pid_filter = stk70x0p_pid_filter, | ||
| 3267 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3268 | .frontend_attach = stk7070p_frontend_attach, | ||
| 3269 | .tuner_attach = dib7070p_tuner_attach, | ||
| 3270 | |||
| 3271 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3272 | |||
| 3273 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
| 3274 | }, | ||
| 3275 | }, | ||
| 3276 | |||
| 3277 | .num_device_descs = 3, | ||
| 3278 | .devices = { | ||
| 3279 | { "Pinnacle PCTV 73A", | ||
| 3280 | { &dib0700_usb_id_table[56], NULL }, | ||
| 3281 | { NULL }, | ||
| 3282 | }, | ||
| 3283 | { "Pinnacle PCTV 73e SE", | ||
| 3284 | { &dib0700_usb_id_table[57], &dib0700_usb_id_table[65], NULL }, | ||
| 3285 | { NULL }, | ||
| 3286 | }, | ||
| 3287 | { "Pinnacle PCTV 282e", | ||
| 3288 | { &dib0700_usb_id_table[58], &dib0700_usb_id_table[66], NULL }, | ||
| 3289 | { NULL }, | ||
| 3290 | }, | ||
| 3291 | }, | ||
| 3292 | |||
| 3293 | .rc.core = { | ||
| 3294 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3295 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3296 | .module_name = "dib0700", | ||
| 3297 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3298 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3299 | RC_TYPE_RC6 | | ||
| 3300 | RC_TYPE_NEC, | ||
| 3301 | .change_protocol = dib0700_change_protocol, | ||
| 3302 | }, | ||
| 3303 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3304 | |||
| 3305 | .num_adapters = 2, | ||
| 3306 | .adapter = { | ||
| 3307 | { | ||
| 3308 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3309 | .pid_filter_count = 32, | ||
| 3310 | .pid_filter = stk70x0p_pid_filter, | ||
| 3311 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3312 | .frontend_attach = stk7070pd_frontend_attach0, | ||
| 3313 | .tuner_attach = dib7070p_tuner_attach, | ||
| 3314 | |||
| 3315 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3316 | |||
| 3317 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
| 3318 | }, { | ||
| 3319 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3320 | .pid_filter_count = 32, | ||
| 3321 | .pid_filter = stk70x0p_pid_filter, | ||
| 3322 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3323 | .frontend_attach = stk7070pd_frontend_attach1, | ||
| 3324 | .tuner_attach = dib7070p_tuner_attach, | ||
| 3325 | |||
| 3326 | DIB0700_DEFAULT_STREAMING_CONFIG(0x03), | ||
| 3327 | |||
| 3328 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
| 3329 | } | ||
| 3330 | }, | ||
| 3331 | |||
| 3332 | .num_device_descs = 6, | ||
| 3333 | .devices = { | ||
| 3334 | { "DiBcom STK7070PD reference design", | ||
| 3335 | { &dib0700_usb_id_table[17], NULL }, | ||
| 3336 | { NULL }, | ||
| 3337 | }, | ||
| 3338 | { "Pinnacle PCTV Dual DVB-T Diversity Stick", | ||
| 3339 | { &dib0700_usb_id_table[18], NULL }, | ||
| 3340 | { NULL }, | ||
| 3341 | }, | ||
| 3342 | { "Hauppauge Nova-TD Stick (52009)", | ||
| 3343 | { &dib0700_usb_id_table[35], NULL }, | ||
| 3344 | { NULL }, | ||
| 3345 | }, | ||
| 3346 | { "Hauppauge Nova-TD-500 (84xxx)", | ||
| 3347 | { &dib0700_usb_id_table[36], NULL }, | ||
| 3348 | { NULL }, | ||
| 3349 | }, | ||
| 3350 | { "Terratec Cinergy DT USB XS Diversity/ T5", | ||
| 3351 | { &dib0700_usb_id_table[43], | ||
| 3352 | &dib0700_usb_id_table[53], NULL}, | ||
| 3353 | { NULL }, | ||
| 3354 | }, | ||
| 3355 | { "Sony PlayTV", | ||
| 3356 | { &dib0700_usb_id_table[44], NULL }, | ||
| 3357 | { NULL }, | ||
| 3358 | }, | ||
| 3359 | }, | ||
| 3360 | |||
| 3361 | .rc.core = { | ||
| 3362 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3363 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3364 | .module_name = "dib0700", | ||
| 3365 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3366 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3367 | RC_TYPE_RC6 | | ||
| 3368 | RC_TYPE_NEC, | ||
| 3369 | .change_protocol = dib0700_change_protocol, | ||
| 3370 | }, | ||
| 3371 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3372 | |||
| 3373 | .num_adapters = 2, | ||
| 3374 | .adapter = { | ||
| 3375 | { | ||
| 3376 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3377 | .pid_filter_count = 32, | ||
| 3378 | .pid_filter = stk70x0p_pid_filter, | ||
| 3379 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3380 | .frontend_attach = stk7070pd_frontend_attach0, | ||
| 3381 | .tuner_attach = dib7070p_tuner_attach, | ||
| 3382 | |||
| 3383 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3384 | |||
| 3385 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
| 3386 | }, { | ||
| 3387 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3388 | .pid_filter_count = 32, | ||
| 3389 | .pid_filter = stk70x0p_pid_filter, | ||
| 3390 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3391 | .frontend_attach = stk7070pd_frontend_attach1, | ||
| 3392 | .tuner_attach = dib7070p_tuner_attach, | ||
| 3393 | |||
| 3394 | DIB0700_DEFAULT_STREAMING_CONFIG(0x03), | ||
| 3395 | |||
| 3396 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
| 3397 | } | ||
| 3398 | }, | ||
| 3399 | |||
| 3400 | .num_device_descs = 1, | ||
| 3401 | .devices = { | ||
| 3402 | { "Elgato EyeTV Diversity", | ||
| 3403 | { &dib0700_usb_id_table[68], NULL }, | ||
| 3404 | { NULL }, | ||
| 3405 | }, | ||
| 3406 | }, | ||
| 3407 | |||
| 3408 | .rc.core = { | ||
| 3409 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3410 | .rc_codes = RC_MAP_DIB0700_NEC_TABLE, | ||
| 3411 | .module_name = "dib0700", | ||
| 3412 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3413 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3414 | RC_TYPE_RC6 | | ||
| 3415 | RC_TYPE_NEC, | ||
| 3416 | .change_protocol = dib0700_change_protocol, | ||
| 3417 | }, | ||
| 3418 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3419 | |||
| 3420 | .num_adapters = 1, | ||
| 3421 | .adapter = { | ||
| 3422 | { | ||
| 3423 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3424 | .pid_filter_count = 32, | ||
| 3425 | .pid_filter = stk70x0p_pid_filter, | ||
| 3426 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3427 | .frontend_attach = stk7700ph_frontend_attach, | ||
| 3428 | .tuner_attach = stk7700ph_tuner_attach, | ||
| 3429 | |||
| 3430 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3431 | |||
| 3432 | .size_of_priv = sizeof(struct | ||
| 3433 | dib0700_adapter_state), | ||
| 3434 | }, | ||
| 3435 | }, | ||
| 3436 | |||
| 3437 | .num_device_descs = 9, | ||
| 3438 | .devices = { | ||
| 3439 | { "Terratec Cinergy HT USB XE", | ||
| 3440 | { &dib0700_usb_id_table[27], NULL }, | ||
| 3441 | { NULL }, | ||
| 3442 | }, | ||
| 3443 | { "Pinnacle Expresscard 320cx", | ||
| 3444 | { &dib0700_usb_id_table[28], NULL }, | ||
| 3445 | { NULL }, | ||
| 3446 | }, | ||
| 3447 | { "Terratec Cinergy HT Express", | ||
| 3448 | { &dib0700_usb_id_table[32], NULL }, | ||
| 3449 | { NULL }, | ||
| 3450 | }, | ||
| 3451 | { "Gigabyte U8000-RH", | ||
| 3452 | { &dib0700_usb_id_table[37], NULL }, | ||
| 3453 | { NULL }, | ||
| 3454 | }, | ||
| 3455 | { "YUAN High-Tech STK7700PH", | ||
| 3456 | { &dib0700_usb_id_table[38], NULL }, | ||
| 3457 | { NULL }, | ||
| 3458 | }, | ||
| 3459 | { "Asus My Cinema-U3000Hybrid", | ||
| 3460 | { &dib0700_usb_id_table[39], NULL }, | ||
| 3461 | { NULL }, | ||
| 3462 | }, | ||
| 3463 | { "YUAN High-Tech MC770", | ||
| 3464 | { &dib0700_usb_id_table[48], NULL }, | ||
| 3465 | { NULL }, | ||
| 3466 | }, | ||
| 3467 | { "Leadtek WinFast DTV Dongle H", | ||
| 3468 | { &dib0700_usb_id_table[51], NULL }, | ||
| 3469 | { NULL }, | ||
| 3470 | }, | ||
| 3471 | { "YUAN High-Tech STK7700D", | ||
| 3472 | { &dib0700_usb_id_table[54], NULL }, | ||
| 3473 | { NULL }, | ||
| 3474 | }, | ||
| 3475 | }, | ||
| 3476 | |||
| 3477 | .rc.core = { | ||
| 3478 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3479 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3480 | .module_name = "dib0700", | ||
| 3481 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3482 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3483 | RC_TYPE_RC6 | | ||
| 3484 | RC_TYPE_NEC, | ||
| 3485 | .change_protocol = dib0700_change_protocol, | ||
| 3486 | }, | ||
| 3487 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3488 | .num_adapters = 1, | ||
| 3489 | .adapter = { | ||
| 3490 | { | ||
| 3491 | .frontend_attach = s5h1411_frontend_attach, | ||
| 3492 | .tuner_attach = xc5000_tuner_attach, | ||
| 3493 | |||
| 3494 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3495 | |||
| 3496 | .size_of_priv = sizeof(struct | ||
| 3497 | dib0700_adapter_state), | ||
| 3498 | }, | ||
| 3499 | }, | ||
| 3500 | |||
| 3501 | .num_device_descs = 2, | ||
| 3502 | .devices = { | ||
| 3503 | { "Pinnacle PCTV HD Pro USB Stick", | ||
| 3504 | { &dib0700_usb_id_table[40], NULL }, | ||
| 3505 | { NULL }, | ||
| 3506 | }, | ||
| 3507 | { "Pinnacle PCTV HD USB Stick", | ||
| 3508 | { &dib0700_usb_id_table[41], NULL }, | ||
| 3509 | { NULL }, | ||
| 3510 | }, | ||
| 3511 | }, | ||
| 3512 | |||
| 3513 | .rc.core = { | ||
| 3514 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3515 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3516 | .module_name = "dib0700", | ||
| 3517 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3518 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3519 | RC_TYPE_RC6 | | ||
| 3520 | RC_TYPE_NEC, | ||
| 3521 | .change_protocol = dib0700_change_protocol, | ||
| 3522 | }, | ||
| 3523 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3524 | .num_adapters = 1, | ||
| 3525 | .adapter = { | ||
| 3526 | { | ||
| 3527 | .frontend_attach = lgdt3305_frontend_attach, | ||
| 3528 | .tuner_attach = mxl5007t_tuner_attach, | ||
| 3529 | |||
| 3530 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3531 | |||
| 3532 | .size_of_priv = sizeof(struct | ||
| 3533 | dib0700_adapter_state), | ||
| 3534 | }, | ||
| 3535 | }, | ||
| 3536 | |||
| 3537 | .num_device_descs = 2, | ||
| 3538 | .devices = { | ||
| 3539 | { "Hauppauge ATSC MiniCard (B200)", | ||
| 3540 | { &dib0700_usb_id_table[46], NULL }, | ||
| 3541 | { NULL }, | ||
| 3542 | }, | ||
| 3543 | { "Hauppauge ATSC MiniCard (B210)", | ||
| 3544 | { &dib0700_usb_id_table[47], NULL }, | ||
| 3545 | { NULL }, | ||
| 3546 | }, | ||
| 3547 | }, | ||
| 3548 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3549 | |||
| 3550 | .num_adapters = 1, | ||
| 3551 | .adapter = { | ||
| 3552 | { | ||
| 3553 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3554 | .pid_filter_count = 32, | ||
| 3555 | .pid_filter = stk70x0p_pid_filter, | ||
| 3556 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3557 | .frontend_attach = stk7770p_frontend_attach, | ||
| 3558 | .tuner_attach = dib7770p_tuner_attach, | ||
| 3559 | |||
| 3560 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3561 | |||
| 3562 | .size_of_priv = | ||
| 3563 | sizeof(struct dib0700_adapter_state), | ||
| 3564 | }, | ||
| 3565 | }, | ||
| 3566 | |||
| 3567 | .num_device_descs = 4, | ||
| 3568 | .devices = { | ||
| 3569 | { "DiBcom STK7770P reference design", | ||
| 3570 | { &dib0700_usb_id_table[59], NULL }, | ||
| 3571 | { NULL }, | ||
| 3572 | }, | ||
| 3573 | { "Terratec Cinergy T USB XXS (HD)/ T3", | ||
| 3574 | { &dib0700_usb_id_table[33], | ||
| 3575 | &dib0700_usb_id_table[52], | ||
| 3576 | &dib0700_usb_id_table[60], NULL}, | ||
| 3577 | { NULL }, | ||
| 3578 | }, | ||
| 3579 | { "TechniSat AirStar TeleStick 2", | ||
| 3580 | { &dib0700_usb_id_table[74], NULL }, | ||
| 3581 | { NULL }, | ||
| 3582 | }, | ||
| 3583 | { "Medion CTX1921 DVB-T USB", | ||
| 3584 | { &dib0700_usb_id_table[75], NULL }, | ||
| 3585 | { NULL }, | ||
| 3586 | }, | ||
| 3587 | }, | ||
| 3588 | |||
| 3589 | .rc.core = { | ||
| 3590 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3591 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3592 | .module_name = "dib0700", | ||
| 3593 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3594 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3595 | RC_TYPE_RC6 | | ||
| 3596 | RC_TYPE_NEC, | ||
| 3597 | .change_protocol = dib0700_change_protocol, | ||
| 3598 | }, | ||
| 3599 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3600 | .num_adapters = 1, | ||
| 3601 | .adapter = { | ||
| 3602 | { | ||
| 3603 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3604 | .pid_filter_count = 32, | ||
| 3605 | .pid_filter = stk80xx_pid_filter, | ||
| 3606 | .pid_filter_ctrl = stk80xx_pid_filter_ctrl, | ||
| 3607 | .frontend_attach = stk807x_frontend_attach, | ||
| 3608 | .tuner_attach = dib807x_tuner_attach, | ||
| 3609 | |||
| 3610 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3611 | |||
| 3612 | .size_of_priv = | ||
| 3613 | sizeof(struct dib0700_adapter_state), | ||
| 3614 | }, | ||
| 3615 | }, | ||
| 3616 | |||
| 3617 | .num_device_descs = 3, | ||
| 3618 | .devices = { | ||
| 3619 | { "DiBcom STK807xP reference design", | ||
| 3620 | { &dib0700_usb_id_table[62], NULL }, | ||
| 3621 | { NULL }, | ||
| 3622 | }, | ||
| 3623 | { "Prolink Pixelview SBTVD", | ||
| 3624 | { &dib0700_usb_id_table[63], NULL }, | ||
| 3625 | { NULL }, | ||
| 3626 | }, | ||
| 3627 | { "EvolutePC TVWay+", | ||
| 3628 | { &dib0700_usb_id_table[64], NULL }, | ||
| 3629 | { NULL }, | ||
| 3630 | }, | ||
| 3631 | }, | ||
| 3632 | |||
| 3633 | .rc.core = { | ||
| 3634 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3635 | .rc_codes = RC_MAP_DIB0700_NEC_TABLE, | ||
| 3636 | .module_name = "dib0700", | ||
| 3637 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3638 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3639 | RC_TYPE_RC6 | | ||
| 3640 | RC_TYPE_NEC, | ||
| 3641 | .change_protocol = dib0700_change_protocol, | ||
| 3642 | }, | ||
| 3643 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3644 | .num_adapters = 2, | ||
| 3645 | .adapter = { | ||
| 3646 | { | ||
| 3647 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3648 | .pid_filter_count = 32, | ||
| 3649 | .pid_filter = stk80xx_pid_filter, | ||
| 3650 | .pid_filter_ctrl = stk80xx_pid_filter_ctrl, | ||
| 3651 | .frontend_attach = stk807xpvr_frontend_attach0, | ||
| 3652 | .tuner_attach = dib807x_tuner_attach, | ||
| 3653 | |||
| 3654 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3655 | |||
| 3656 | .size_of_priv = | ||
| 3657 | sizeof(struct dib0700_adapter_state), | ||
| 3658 | }, | ||
| 3659 | { | ||
| 3660 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3661 | .pid_filter_count = 32, | ||
| 3662 | .pid_filter = stk80xx_pid_filter, | ||
| 3663 | .pid_filter_ctrl = stk80xx_pid_filter_ctrl, | ||
| 3664 | .frontend_attach = stk807xpvr_frontend_attach1, | ||
| 3665 | .tuner_attach = dib807x_tuner_attach, | ||
| 3666 | |||
| 3667 | DIB0700_DEFAULT_STREAMING_CONFIG(0x03), | ||
| 3668 | |||
| 3669 | .size_of_priv = | ||
| 3670 | sizeof(struct dib0700_adapter_state), | ||
| 3671 | }, | ||
| 3672 | }, | ||
| 3673 | |||
| 3674 | .num_device_descs = 1, | ||
| 3675 | .devices = { | ||
| 3676 | { "DiBcom STK807xPVR reference design", | ||
| 3677 | { &dib0700_usb_id_table[61], NULL }, | ||
| 3678 | { NULL }, | ||
| 3679 | }, | ||
| 3680 | }, | ||
| 3681 | |||
| 3682 | .rc.core = { | ||
| 3683 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3684 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3685 | .module_name = "dib0700", | ||
| 3686 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3687 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3688 | RC_TYPE_RC6 | | ||
| 3689 | RC_TYPE_NEC, | ||
| 3690 | .change_protocol = dib0700_change_protocol, | ||
| 3691 | }, | ||
| 3692 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3693 | .num_adapters = 1, | ||
| 3694 | .adapter = { | ||
| 3695 | { | ||
| 3696 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 3697 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3698 | .pid_filter_count = 32, | ||
| 3699 | .pid_filter = stk80xx_pid_filter, | ||
| 3700 | .pid_filter_ctrl = stk80xx_pid_filter_ctrl, | ||
| 3701 | .frontend_attach = stk809x_frontend_attach, | ||
| 3702 | .tuner_attach = dib809x_tuner_attach, | ||
| 3703 | |||
| 3704 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3705 | |||
| 3706 | .size_of_priv = | ||
| 3707 | sizeof(struct dib0700_adapter_state), | ||
| 3708 | }, | ||
| 3709 | }, | ||
| 3710 | |||
| 3711 | .num_device_descs = 1, | ||
| 3712 | .devices = { | ||
| 3713 | { "DiBcom STK8096GP reference design", | ||
| 3714 | { &dib0700_usb_id_table[67], NULL }, | ||
| 3715 | { NULL }, | ||
| 3716 | }, | ||
| 3717 | }, | ||
| 3718 | |||
| 3719 | .rc.core = { | ||
| 3720 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3721 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3722 | .module_name = "dib0700", | ||
| 3723 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3724 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3725 | RC_TYPE_RC6 | | ||
| 3726 | RC_TYPE_NEC, | ||
| 3727 | .change_protocol = dib0700_change_protocol, | ||
| 3728 | }, | ||
| 3729 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3730 | .num_adapters = 1, | ||
| 3731 | .adapter = { | ||
| 3732 | { | ||
| 3733 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 3734 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3735 | .pid_filter_count = 32, | ||
| 3736 | .pid_filter = dib90x0_pid_filter, | ||
| 3737 | .pid_filter_ctrl = dib90x0_pid_filter_ctrl, | ||
| 3738 | .frontend_attach = stk9090m_frontend_attach, | ||
| 3739 | .tuner_attach = dib9090_tuner_attach, | ||
| 3740 | |||
| 3741 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3742 | |||
| 3743 | .size_of_priv = | ||
| 3744 | sizeof(struct dib0700_adapter_state), | ||
| 3745 | }, | ||
| 3746 | }, | ||
| 3747 | |||
| 3748 | .num_device_descs = 1, | ||
| 3749 | .devices = { | ||
| 3750 | { "DiBcom STK9090M reference design", | ||
| 3751 | { &dib0700_usb_id_table[69], NULL }, | ||
| 3752 | { NULL }, | ||
| 3753 | }, | ||
| 3754 | }, | ||
| 3755 | |||
| 3756 | .rc.core = { | ||
| 3757 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3758 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3759 | .module_name = "dib0700", | ||
| 3760 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3761 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3762 | RC_TYPE_RC6 | | ||
| 3763 | RC_TYPE_NEC, | ||
| 3764 | .change_protocol = dib0700_change_protocol, | ||
| 3765 | }, | ||
| 3766 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3767 | .num_adapters = 1, | ||
| 3768 | .adapter = { | ||
| 3769 | { | ||
| 3770 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 3771 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3772 | .pid_filter_count = 32, | ||
| 3773 | .pid_filter = stk80xx_pid_filter, | ||
| 3774 | .pid_filter_ctrl = stk80xx_pid_filter_ctrl, | ||
| 3775 | .frontend_attach = nim8096md_frontend_attach, | ||
| 3776 | .tuner_attach = nim8096md_tuner_attach, | ||
| 3777 | |||
| 3778 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3779 | |||
| 3780 | .size_of_priv = | ||
| 3781 | sizeof(struct dib0700_adapter_state), | ||
| 3782 | }, | ||
| 3783 | }, | ||
| 3784 | |||
| 3785 | .num_device_descs = 1, | ||
| 3786 | .devices = { | ||
| 3787 | { "DiBcom NIM8096MD reference design", | ||
| 3788 | { &dib0700_usb_id_table[70], NULL }, | ||
| 3789 | { NULL }, | ||
| 3790 | }, | ||
| 3791 | }, | ||
| 3792 | |||
| 3793 | .rc.core = { | ||
| 3794 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3795 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3796 | .module_name = "dib0700", | ||
| 3797 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3798 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3799 | RC_TYPE_RC6 | | ||
| 3800 | RC_TYPE_NEC, | ||
| 3801 | .change_protocol = dib0700_change_protocol, | ||
| 3802 | }, | ||
| 3803 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3804 | .num_adapters = 1, | ||
| 3805 | .adapter = { | ||
| 3806 | { | ||
| 3807 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 3808 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3809 | .pid_filter_count = 32, | ||
| 3810 | .pid_filter = dib90x0_pid_filter, | ||
| 3811 | .pid_filter_ctrl = dib90x0_pid_filter_ctrl, | ||
| 3812 | .frontend_attach = nim9090md_frontend_attach, | ||
| 3813 | .tuner_attach = nim9090md_tuner_attach, | ||
| 3814 | |||
| 3815 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3816 | |||
| 3817 | .size_of_priv = | ||
| 3818 | sizeof(struct dib0700_adapter_state), | ||
| 3819 | }, | ||
| 3820 | }, | ||
| 3821 | |||
| 3822 | .num_device_descs = 1, | ||
| 3823 | .devices = { | ||
| 3824 | { "DiBcom NIM9090MD reference design", | ||
| 3825 | { &dib0700_usb_id_table[71], NULL }, | ||
| 3826 | { NULL }, | ||
| 3827 | }, | ||
| 3828 | }, | ||
| 3829 | |||
| 3830 | .rc.core = { | ||
| 3831 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3832 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3833 | .module_name = "dib0700", | ||
| 3834 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3835 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3836 | RC_TYPE_RC6 | | ||
| 3837 | RC_TYPE_NEC, | ||
| 3838 | .change_protocol = dib0700_change_protocol, | ||
| 3839 | }, | ||
| 3840 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3841 | .num_adapters = 1, | ||
| 3842 | .adapter = { | ||
| 3843 | { | ||
| 3844 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 3845 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3846 | .pid_filter_count = 32, | ||
| 3847 | .pid_filter = stk70x0p_pid_filter, | ||
| 3848 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3849 | .frontend_attach = nim7090_frontend_attach, | ||
| 3850 | .tuner_attach = nim7090_tuner_attach, | ||
| 3851 | |||
| 3852 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3853 | |||
| 3854 | .size_of_priv = | ||
| 3855 | sizeof(struct dib0700_adapter_state), | ||
| 3856 | }, | ||
| 3857 | }, | ||
| 3858 | |||
| 3859 | .num_device_descs = 1, | ||
| 3860 | .devices = { | ||
| 3861 | { "DiBcom NIM7090 reference design", | ||
| 3862 | { &dib0700_usb_id_table[72], NULL }, | ||
| 3863 | { NULL }, | ||
| 3864 | }, | ||
| 3865 | }, | ||
| 3866 | |||
| 3867 | .rc.core = { | ||
| 3868 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3869 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3870 | .module_name = "dib0700", | ||
| 3871 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3872 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3873 | RC_TYPE_RC6 | | ||
| 3874 | RC_TYPE_NEC, | ||
| 3875 | .change_protocol = dib0700_change_protocol, | ||
| 3876 | }, | ||
| 3877 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3878 | .num_adapters = 2, | ||
| 3879 | .adapter = { | ||
| 3880 | { | ||
| 3881 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 3882 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3883 | .pid_filter_count = 32, | ||
| 3884 | .pid_filter = stk70x0p_pid_filter, | ||
| 3885 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3886 | .frontend_attach = tfe7090pvr_frontend0_attach, | ||
| 3887 | .tuner_attach = tfe7090pvr_tuner0_attach, | ||
| 3888 | |||
| 3889 | DIB0700_DEFAULT_STREAMING_CONFIG(0x03), | ||
| 3890 | |||
| 3891 | .size_of_priv = | ||
| 3892 | sizeof(struct dib0700_adapter_state), | ||
| 3893 | }, | ||
| 3894 | { | ||
| 3895 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 3896 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 3897 | .pid_filter_count = 32, | ||
| 3898 | .pid_filter = stk70x0p_pid_filter, | ||
| 3899 | .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, | ||
| 3900 | .frontend_attach = tfe7090pvr_frontend1_attach, | ||
| 3901 | .tuner_attach = tfe7090pvr_tuner1_attach, | ||
| 3902 | |||
| 3903 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3904 | |||
| 3905 | .size_of_priv = | ||
| 3906 | sizeof(struct dib0700_adapter_state), | ||
| 3907 | }, | ||
| 3908 | }, | ||
| 3909 | |||
| 3910 | .num_device_descs = 1, | ||
| 3911 | .devices = { | ||
| 3912 | { "DiBcom TFE7090PVR reference design", | ||
| 3913 | { &dib0700_usb_id_table[73], NULL }, | ||
| 3914 | { NULL }, | ||
| 3915 | }, | ||
| 3916 | }, | ||
| 3917 | |||
| 3918 | .rc.core = { | ||
| 3919 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3920 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3921 | .module_name = "dib0700", | ||
| 3922 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3923 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3924 | RC_TYPE_RC6 | | ||
| 3925 | RC_TYPE_NEC, | ||
| 3926 | .change_protocol = dib0700_change_protocol, | ||
| 3927 | }, | ||
| 3928 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
| 3929 | .num_adapters = 1, | ||
| 3930 | .adapter = { | ||
| 3931 | { | ||
| 3932 | .frontend_attach = pctv340e_frontend_attach, | ||
| 3933 | .tuner_attach = xc4000_tuner_attach, | ||
| 3934 | |||
| 3935 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
| 3936 | |||
| 3937 | .size_of_priv = sizeof(struct | ||
| 3938 | dib0700_adapter_state), | ||
| 3939 | }, | ||
| 3940 | }, | ||
| 3941 | |||
| 3942 | .num_device_descs = 2, | ||
| 3943 | .devices = { | ||
| 3944 | { "Pinnacle PCTV 340e HD Pro USB Stick", | ||
| 3945 | { &dib0700_usb_id_table[76], NULL }, | ||
| 3946 | { NULL }, | ||
| 3947 | }, | ||
| 3948 | { "Pinnacle PCTV Hybrid Stick Solo", | ||
| 3949 | { &dib0700_usb_id_table[77], NULL }, | ||
| 3950 | { NULL }, | ||
| 3951 | }, | ||
| 3952 | }, | ||
| 3953 | .rc.core = { | ||
| 3954 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 3955 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | ||
| 3956 | .module_name = "dib0700", | ||
| 3957 | .rc_query = dib0700_rc_query_old_firmware, | ||
| 3958 | .allowed_protos = RC_TYPE_RC5 | | ||
| 3959 | RC_TYPE_RC6 | | ||
| 3960 | RC_TYPE_NEC, | ||
| 3961 | .change_protocol = dib0700_change_protocol, | ||
| 3962 | }, | ||
| 3963 | }, | ||
| 3964 | }; | ||
| 3965 | |||
| 3966 | int dib0700_device_count = ARRAY_SIZE(dib0700_devices); | ||
diff --git a/drivers/media/dvb/dvb-usb/dib07x0.h b/drivers/media/dvb/dvb-usb/dib07x0.h new file mode 100644 index 00000000000..7e62c101852 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dib07x0.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | #ifndef _DIB07X0_H_ | ||
| 2 | #define _DIB07X0_H_ | ||
| 3 | |||
| 4 | enum dib07x0_gpios { | ||
| 5 | GPIO0 = 0, | ||
| 6 | GPIO1 = 2, | ||
| 7 | GPIO2 = 3, | ||
| 8 | GPIO3 = 4, | ||
| 9 | GPIO4 = 5, | ||
| 10 | GPIO5 = 6, | ||
| 11 | GPIO6 = 8, | ||
| 12 | GPIO7 = 10, | ||
| 13 | GPIO8 = 11, | ||
| 14 | GPIO9 = 14, | ||
| 15 | GPIO10 = 15, | ||
| 16 | }; | ||
| 17 | |||
| 18 | #define GPIO_IN 0 | ||
| 19 | #define GPIO_OUT 1 | ||
| 20 | |||
| 21 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c new file mode 100644 index 00000000000..4c2a689c820 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c | |||
| @@ -0,0 +1,470 @@ | |||
| 1 | /* Common methods for dibusb-based-receivers. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 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 Free | ||
| 7 | * Software Foundation, version 2. | ||
| 8 | * | ||
| 9 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 10 | */ | ||
| 11 | #include "dibusb.h" | ||
| 12 | |||
| 13 | static int debug; | ||
| 14 | module_param(debug, int, 0644); | ||
| 15 | MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS); | ||
| 16 | MODULE_LICENSE("GPL"); | ||
| 17 | |||
| 18 | #define deb_info(args...) dprintk(debug,0x01,args) | ||
| 19 | |||
| 20 | /* common stuff used by the different dibusb modules */ | ||
| 21 | int dibusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 22 | { | ||
| 23 | if (adap->priv != NULL) { | ||
| 24 | struct dibusb_state *st = adap->priv; | ||
| 25 | if (st->ops.fifo_ctrl != NULL) | ||
| 26 | if (st->ops.fifo_ctrl(adap->fe,onoff)) { | ||
| 27 | err("error while controlling the fifo of the demod."); | ||
| 28 | return -ENODEV; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | return 0; | ||
| 32 | } | ||
| 33 | EXPORT_SYMBOL(dibusb_streaming_ctrl); | ||
| 34 | |||
| 35 | int dibusb_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) | ||
| 36 | { | ||
| 37 | if (adap->priv != NULL) { | ||
| 38 | struct dibusb_state *st = adap->priv; | ||
| 39 | if (st->ops.pid_ctrl != NULL) | ||
| 40 | st->ops.pid_ctrl(adap->fe,index,pid,onoff); | ||
| 41 | } | ||
| 42 | return 0; | ||
| 43 | } | ||
| 44 | EXPORT_SYMBOL(dibusb_pid_filter); | ||
| 45 | |||
| 46 | int dibusb_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 47 | { | ||
| 48 | if (adap->priv != NULL) { | ||
| 49 | struct dibusb_state *st = adap->priv; | ||
| 50 | if (st->ops.pid_parse != NULL) | ||
| 51 | if (st->ops.pid_parse(adap->fe,onoff) < 0) | ||
| 52 | err("could not handle pid_parser"); | ||
| 53 | } | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | EXPORT_SYMBOL(dibusb_pid_filter_ctrl); | ||
| 57 | |||
| 58 | int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 59 | { | ||
| 60 | u8 b[3]; | ||
| 61 | int ret; | ||
| 62 | b[0] = DIBUSB_REQ_SET_IOCTL; | ||
| 63 | b[1] = DIBUSB_IOCTL_CMD_POWER_MODE; | ||
| 64 | b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP; | ||
| 65 | ret = dvb_usb_generic_write(d,b,3); | ||
| 66 | msleep(10); | ||
| 67 | return ret; | ||
| 68 | } | ||
| 69 | EXPORT_SYMBOL(dibusb_power_ctrl); | ||
| 70 | |||
| 71 | int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 72 | { | ||
| 73 | u8 b[3] = { 0 }; | ||
| 74 | int ret; | ||
| 75 | |||
| 76 | if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0) | ||
| 77 | return ret; | ||
| 78 | |||
| 79 | if (onoff) { | ||
| 80 | b[0] = DIBUSB_REQ_SET_STREAMING_MODE; | ||
| 81 | b[1] = 0x00; | ||
| 82 | if ((ret = dvb_usb_generic_write(adap->dev,b,2)) < 0) | ||
| 83 | return ret; | ||
| 84 | } | ||
| 85 | |||
| 86 | b[0] = DIBUSB_REQ_SET_IOCTL; | ||
| 87 | b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM; | ||
| 88 | return dvb_usb_generic_write(adap->dev,b,3); | ||
| 89 | } | ||
| 90 | EXPORT_SYMBOL(dibusb2_0_streaming_ctrl); | ||
| 91 | |||
| 92 | int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 93 | { | ||
| 94 | if (onoff) { | ||
| 95 | u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP }; | ||
| 96 | return dvb_usb_generic_write(d,b,3); | ||
| 97 | } else | ||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | EXPORT_SYMBOL(dibusb2_0_power_ctrl); | ||
| 101 | |||
| 102 | static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
| 103 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
| 104 | { | ||
| 105 | u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */ | ||
| 106 | /* write only ? */ | ||
| 107 | int wo = (rbuf == NULL || rlen == 0), | ||
| 108 | len = 2 + wlen + (wo ? 0 : 2); | ||
| 109 | |||
| 110 | sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; | ||
| 111 | sndbuf[1] = (addr << 1) | (wo ? 0 : 1); | ||
| 112 | |||
| 113 | memcpy(&sndbuf[2],wbuf,wlen); | ||
| 114 | |||
| 115 | if (!wo) { | ||
| 116 | sndbuf[wlen+2] = (rlen >> 8) & 0xff; | ||
| 117 | sndbuf[wlen+3] = rlen & 0xff; | ||
| 118 | } | ||
| 119 | |||
| 120 | return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0); | ||
| 121 | } | ||
| 122 | |||
| 123 | /* | ||
| 124 | * I2C master xfer function | ||
| 125 | */ | ||
| 126 | static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | ||
| 127 | { | ||
| 128 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 129 | int i; | ||
| 130 | |||
| 131 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 132 | return -EAGAIN; | ||
| 133 | |||
| 134 | for (i = 0; i < num; i++) { | ||
| 135 | /* write/read request */ | ||
| 136 | if (i+1 < num && (msg[i].flags & I2C_M_RD) == 0 | ||
| 137 | && (msg[i+1].flags & I2C_M_RD)) { | ||
| 138 | if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len, | ||
| 139 | msg[i+1].buf,msg[i+1].len) < 0) | ||
| 140 | break; | ||
| 141 | i++; | ||
| 142 | } else if ((msg[i].flags & I2C_M_RD) == 0) { | ||
| 143 | if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) | ||
| 144 | break; | ||
| 145 | } else if (msg[i].addr != 0x50) { | ||
| 146 | /* 0x50 is the address of the eeprom - we need to protect it | ||
| 147 | * from dibusb's bad i2c implementation: reads without | ||
| 148 | * writing the offset before are forbidden */ | ||
| 149 | if (dibusb_i2c_msg(d, msg[i].addr, NULL, 0, msg[i].buf, msg[i].len) < 0) | ||
| 150 | break; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | mutex_unlock(&d->i2c_mutex); | ||
| 155 | return i; | ||
| 156 | } | ||
| 157 | |||
| 158 | static u32 dibusb_i2c_func(struct i2c_adapter *adapter) | ||
| 159 | { | ||
| 160 | return I2C_FUNC_I2C; | ||
| 161 | } | ||
| 162 | |||
| 163 | struct i2c_algorithm dibusb_i2c_algo = { | ||
| 164 | .master_xfer = dibusb_i2c_xfer, | ||
| 165 | .functionality = dibusb_i2c_func, | ||
| 166 | }; | ||
| 167 | EXPORT_SYMBOL(dibusb_i2c_algo); | ||
| 168 | |||
| 169 | int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) | ||
| 170 | { | ||
| 171 | u8 wbuf[1] = { offs }; | ||
| 172 | return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1); | ||
| 173 | } | ||
| 174 | EXPORT_SYMBOL(dibusb_read_eeprom_byte); | ||
| 175 | |||
| 176 | /* 3000MC/P stuff */ | ||
| 177 | // Config Adjacent channels Perf -cal22 | ||
| 178 | static struct dibx000_agc_config dib3000p_mt2060_agc_config = { | ||
| 179 | .band_caps = BAND_VHF | BAND_UHF, | ||
| 180 | .setup = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0), | ||
| 181 | |||
| 182 | .agc1_max = 48497, | ||
| 183 | .agc1_min = 23593, | ||
| 184 | .agc2_max = 46531, | ||
| 185 | .agc2_min = 24904, | ||
| 186 | |||
| 187 | .agc1_pt1 = 0x65, | ||
| 188 | .agc1_pt2 = 0x69, | ||
| 189 | |||
| 190 | .agc1_slope1 = 0x51, | ||
| 191 | .agc1_slope2 = 0x27, | ||
| 192 | |||
| 193 | .agc2_pt1 = 0, | ||
| 194 | .agc2_pt2 = 0x33, | ||
| 195 | |||
| 196 | .agc2_slope1 = 0x35, | ||
| 197 | .agc2_slope2 = 0x37, | ||
| 198 | }; | ||
| 199 | |||
| 200 | static struct dib3000mc_config stk3000p_dib3000p_config = { | ||
| 201 | &dib3000p_mt2060_agc_config, | ||
| 202 | |||
| 203 | .max_time = 0x196, | ||
| 204 | .ln_adc_level = 0x1cc7, | ||
| 205 | |||
| 206 | .output_mpeg2_in_188_bytes = 1, | ||
| 207 | |||
| 208 | .agc_command1 = 1, | ||
| 209 | .agc_command2 = 1, | ||
| 210 | }; | ||
| 211 | |||
| 212 | static struct dibx000_agc_config dib3000p_panasonic_agc_config = { | ||
| 213 | .band_caps = BAND_VHF | BAND_UHF, | ||
| 214 | .setup = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0), | ||
| 215 | |||
| 216 | .agc1_max = 56361, | ||
| 217 | .agc1_min = 22282, | ||
| 218 | .agc2_max = 47841, | ||
| 219 | .agc2_min = 36045, | ||
| 220 | |||
| 221 | .agc1_pt1 = 0x3b, | ||
| 222 | .agc1_pt2 = 0x6b, | ||
| 223 | |||
| 224 | .agc1_slope1 = 0x55, | ||
| 225 | .agc1_slope2 = 0x1d, | ||
| 226 | |||
| 227 | .agc2_pt1 = 0, | ||
| 228 | .agc2_pt2 = 0x0a, | ||
| 229 | |||
| 230 | .agc2_slope1 = 0x95, | ||
| 231 | .agc2_slope2 = 0x1e, | ||
| 232 | }; | ||
| 233 | |||
| 234 | #if defined(CONFIG_DVB_DIB3000MC) || \ | ||
| 235 | (defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE)) | ||
| 236 | |||
| 237 | static struct dib3000mc_config mod3000p_dib3000p_config = { | ||
| 238 | &dib3000p_panasonic_agc_config, | ||
| 239 | |||
| 240 | .max_time = 0x51, | ||
| 241 | .ln_adc_level = 0x1cc7, | ||
| 242 | |||
| 243 | .output_mpeg2_in_188_bytes = 1, | ||
| 244 | |||
| 245 | .agc_command1 = 1, | ||
| 246 | .agc_command2 = 1, | ||
| 247 | }; | ||
| 248 | |||
| 249 | int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 250 | { | ||
| 251 | if (adap->dev->udev->descriptor.idVendor == USB_VID_LITEON && | ||
| 252 | adap->dev->udev->descriptor.idProduct == | ||
| 253 | USB_PID_LITEON_DVB_T_WARM) { | ||
| 254 | msleep(1000); | ||
| 255 | } | ||
| 256 | |||
| 257 | if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL || | ||
| 258 | (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) { | ||
| 259 | if (adap->priv != NULL) { | ||
| 260 | struct dibusb_state *st = adap->priv; | ||
| 261 | st->ops.pid_parse = dib3000mc_pid_parse; | ||
| 262 | st->ops.pid_ctrl = dib3000mc_pid_control; | ||
| 263 | } | ||
| 264 | return 0; | ||
| 265 | } | ||
| 266 | return -ENODEV; | ||
| 267 | } | ||
| 268 | EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach); | ||
| 269 | |||
| 270 | static struct mt2060_config stk3000p_mt2060_config = { | ||
| 271 | 0x60 | ||
| 272 | }; | ||
| 273 | |||
| 274 | int dibusb_dib3000mc_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 275 | { | ||
| 276 | struct dibusb_state *st = adap->priv; | ||
| 277 | u8 a,b; | ||
| 278 | u16 if1 = 1220; | ||
| 279 | struct i2c_adapter *tun_i2c; | ||
| 280 | |||
| 281 | // First IF calibration for Liteon Sticks | ||
| 282 | if (adap->dev->udev->descriptor.idVendor == USB_VID_LITEON && | ||
| 283 | adap->dev->udev->descriptor.idProduct == USB_PID_LITEON_DVB_T_WARM) { | ||
| 284 | |||
| 285 | dibusb_read_eeprom_byte(adap->dev,0x7E,&a); | ||
| 286 | dibusb_read_eeprom_byte(adap->dev,0x7F,&b); | ||
| 287 | |||
| 288 | if (a == 0x00) | ||
| 289 | if1 += b; | ||
| 290 | else if (a == 0x80) | ||
| 291 | if1 -= b; | ||
| 292 | else | ||
| 293 | warn("LITE-ON DVB-T: Strange IF1 calibration :%2X %2X\n", a, b); | ||
| 294 | |||
| 295 | } else if (adap->dev->udev->descriptor.idVendor == USB_VID_DIBCOM && | ||
| 296 | adap->dev->udev->descriptor.idProduct == USB_PID_DIBCOM_MOD3001_WARM) { | ||
| 297 | u8 desc; | ||
| 298 | dibusb_read_eeprom_byte(adap->dev, 7, &desc); | ||
| 299 | if (desc == 2) { | ||
| 300 | a = 127; | ||
| 301 | do { | ||
| 302 | dibusb_read_eeprom_byte(adap->dev, a, &desc); | ||
| 303 | a--; | ||
| 304 | } while (a > 7 && (desc == 0xff || desc == 0x00)); | ||
| 305 | if (desc & 0x80) | ||
| 306 | if1 -= (0xff - desc); | ||
| 307 | else | ||
| 308 | if1 += desc; | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1); | ||
| 313 | if (dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) { | ||
| 314 | /* not found - use panasonic pll parameters */ | ||
| 315 | if (dvb_attach(dvb_pll_attach, adap->fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL) | ||
| 316 | return -ENOMEM; | ||
| 317 | } else { | ||
| 318 | st->mt2060_present = 1; | ||
| 319 | /* set the correct parameters for the dib3000p */ | ||
| 320 | dib3000mc_set_config(adap->fe, &stk3000p_dib3000p_config); | ||
| 321 | } | ||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); | ||
| 325 | #endif | ||
| 326 | |||
| 327 | /* | ||
| 328 | * common remote control stuff | ||
| 329 | */ | ||
| 330 | struct rc_map_table rc_map_dibusb_table[] = { | ||
| 331 | /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ | ||
| 332 | { 0x0016, KEY_POWER }, | ||
| 333 | { 0x0010, KEY_MUTE }, | ||
| 334 | { 0x0003, KEY_1 }, | ||
| 335 | { 0x0001, KEY_2 }, | ||
| 336 | { 0x0006, KEY_3 }, | ||
| 337 | { 0x0009, KEY_4 }, | ||
| 338 | { 0x001d, KEY_5 }, | ||
| 339 | { 0x001f, KEY_6 }, | ||
| 340 | { 0x000d, KEY_7 }, | ||
| 341 | { 0x0019, KEY_8 }, | ||
| 342 | { 0x001b, KEY_9 }, | ||
| 343 | { 0x0015, KEY_0 }, | ||
| 344 | { 0x0005, KEY_CHANNELUP }, | ||
| 345 | { 0x0002, KEY_CHANNELDOWN }, | ||
| 346 | { 0x001e, KEY_VOLUMEUP }, | ||
| 347 | { 0x000a, KEY_VOLUMEDOWN }, | ||
| 348 | { 0x0011, KEY_RECORD }, | ||
| 349 | { 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */ | ||
| 350 | { 0x0014, KEY_PLAY }, | ||
| 351 | { 0x001a, KEY_STOP }, | ||
| 352 | { 0x0040, KEY_REWIND }, | ||
| 353 | { 0x0012, KEY_FASTFORWARD }, | ||
| 354 | { 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */ | ||
| 355 | { 0x004c, KEY_PAUSE }, | ||
| 356 | { 0x004d, KEY_SCREEN }, /* Full screen mode. */ | ||
| 357 | { 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ | ||
| 358 | /* additional keys TwinHan VisionPlus, the Artec seemingly not have */ | ||
| 359 | { 0x000c, KEY_CANCEL }, /* Cancel */ | ||
| 360 | { 0x001c, KEY_EPG }, /* EPG */ | ||
| 361 | { 0x0000, KEY_TAB }, /* Tab */ | ||
| 362 | { 0x0048, KEY_INFO }, /* Preview */ | ||
| 363 | { 0x0004, KEY_LIST }, /* RecordList */ | ||
| 364 | { 0x000f, KEY_TEXT }, /* Teletext */ | ||
| 365 | /* Key codes for the KWorld/ADSTech/JetWay remote. */ | ||
| 366 | { 0x8612, KEY_POWER }, | ||
| 367 | { 0x860f, KEY_SELECT }, /* source */ | ||
| 368 | { 0x860c, KEY_UNKNOWN }, /* scan */ | ||
| 369 | { 0x860b, KEY_EPG }, | ||
| 370 | { 0x8610, KEY_MUTE }, | ||
| 371 | { 0x8601, KEY_1 }, | ||
| 372 | { 0x8602, KEY_2 }, | ||
| 373 | { 0x8603, KEY_3 }, | ||
| 374 | { 0x8604, KEY_4 }, | ||
| 375 | { 0x8605, KEY_5 }, | ||
| 376 | { 0x8606, KEY_6 }, | ||
| 377 | { 0x8607, KEY_7 }, | ||
| 378 | { 0x8608, KEY_8 }, | ||
| 379 | { 0x8609, KEY_9 }, | ||
| 380 | { 0x860a, KEY_0 }, | ||
| 381 | { 0x8618, KEY_ZOOM }, | ||
| 382 | { 0x861c, KEY_UNKNOWN }, /* preview */ | ||
| 383 | { 0x8613, KEY_UNKNOWN }, /* snap */ | ||
| 384 | { 0x8600, KEY_UNDO }, | ||
| 385 | { 0x861d, KEY_RECORD }, | ||
| 386 | { 0x860d, KEY_STOP }, | ||
| 387 | { 0x860e, KEY_PAUSE }, | ||
| 388 | { 0x8616, KEY_PLAY }, | ||
| 389 | { 0x8611, KEY_BACK }, | ||
| 390 | { 0x8619, KEY_FORWARD }, | ||
| 391 | { 0x8614, KEY_UNKNOWN }, /* pip */ | ||
| 392 | { 0x8615, KEY_ESC }, | ||
| 393 | { 0x861a, KEY_UP }, | ||
| 394 | { 0x861e, KEY_DOWN }, | ||
| 395 | { 0x861f, KEY_LEFT }, | ||
| 396 | { 0x861b, KEY_RIGHT }, | ||
| 397 | |||
| 398 | /* Key codes for the DiBcom MOD3000 remote. */ | ||
| 399 | { 0x8000, KEY_MUTE }, | ||
| 400 | { 0x8001, KEY_TEXT }, | ||
| 401 | { 0x8002, KEY_HOME }, | ||
| 402 | { 0x8003, KEY_POWER }, | ||
| 403 | |||
| 404 | { 0x8004, KEY_RED }, | ||
| 405 | { 0x8005, KEY_GREEN }, | ||
| 406 | { 0x8006, KEY_YELLOW }, | ||
| 407 | { 0x8007, KEY_BLUE }, | ||
| 408 | |||
| 409 | { 0x8008, KEY_DVD }, | ||
| 410 | { 0x8009, KEY_AUDIO }, | ||
| 411 | { 0x800a, KEY_IMAGES }, /* Pictures */ | ||
| 412 | { 0x800b, KEY_VIDEO }, | ||
| 413 | |||
| 414 | { 0x800c, KEY_BACK }, | ||
| 415 | { 0x800d, KEY_UP }, | ||
| 416 | { 0x800e, KEY_RADIO }, | ||
| 417 | { 0x800f, KEY_EPG }, | ||
| 418 | |||
| 419 | { 0x8010, KEY_LEFT }, | ||
| 420 | { 0x8011, KEY_OK }, | ||
| 421 | { 0x8012, KEY_RIGHT }, | ||
| 422 | { 0x8013, KEY_UNKNOWN }, /* SAP */ | ||
| 423 | |||
| 424 | { 0x8014, KEY_TV }, | ||
| 425 | { 0x8015, KEY_DOWN }, | ||
| 426 | { 0x8016, KEY_MENU }, /* DVD Menu */ | ||
| 427 | { 0x8017, KEY_LAST }, | ||
| 428 | |||
| 429 | { 0x8018, KEY_RECORD }, | ||
| 430 | { 0x8019, KEY_STOP }, | ||
| 431 | { 0x801a, KEY_PAUSE }, | ||
| 432 | { 0x801b, KEY_PLAY }, | ||
| 433 | |||
| 434 | { 0x801c, KEY_PREVIOUS }, | ||
| 435 | { 0x801d, KEY_REWIND }, | ||
| 436 | { 0x801e, KEY_FASTFORWARD }, | ||
| 437 | { 0x801f, KEY_NEXT}, | ||
| 438 | |||
| 439 | { 0x8040, KEY_1 }, | ||
| 440 | { 0x8041, KEY_2 }, | ||
| 441 | { 0x8042, KEY_3 }, | ||
| 442 | { 0x8043, KEY_CHANNELUP }, | ||
| 443 | |||
| 444 | { 0x8044, KEY_4 }, | ||
| 445 | { 0x8045, KEY_5 }, | ||
| 446 | { 0x8046, KEY_6 }, | ||
| 447 | { 0x8047, KEY_CHANNELDOWN }, | ||
| 448 | |||
| 449 | { 0x8048, KEY_7 }, | ||
| 450 | { 0x8049, KEY_8 }, | ||
| 451 | { 0x804a, KEY_9 }, | ||
| 452 | { 0x804b, KEY_VOLUMEUP }, | ||
| 453 | |||
| 454 | { 0x804c, KEY_CLEAR }, | ||
| 455 | { 0x804d, KEY_0 }, | ||
| 456 | { 0x804e, KEY_ENTER }, | ||
| 457 | { 0x804f, KEY_VOLUMEDOWN }, | ||
| 458 | }; | ||
| 459 | EXPORT_SYMBOL(rc_map_dibusb_table); | ||
| 460 | |||
| 461 | int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 462 | { | ||
| 463 | u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE; | ||
| 464 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); | ||
| 465 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
| 466 | if (key[0] != 0) | ||
| 467 | deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
| 468 | return 0; | ||
| 469 | } | ||
| 470 | EXPORT_SYMBOL(dibusb_rc_query); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c new file mode 100644 index 00000000000..04d91bdd356 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c | |||
| @@ -0,0 +1,477 @@ | |||
| 1 | /* DVB USB compliant linux driver for mobile DVB-T USB devices based on | ||
| 2 | * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 5 | * | ||
| 6 | * based on GPL code from DiBcom, which has | ||
| 7 | * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the Free | ||
| 11 | * Software Foundation, version 2. | ||
| 12 | * | ||
| 13 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 14 | */ | ||
| 15 | #include "dibusb.h" | ||
| 16 | |||
| 17 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 18 | |||
| 19 | static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) | ||
| 20 | { | ||
| 21 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 22 | struct dibusb_state *st = adap->priv; | ||
| 23 | |||
| 24 | return st->ops.tuner_pass_ctrl(fe, enable, st->tuner_addr); | ||
| 25 | } | ||
| 26 | |||
| 27 | static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 28 | { | ||
| 29 | struct dib3000_config demod_cfg; | ||
| 30 | struct dibusb_state *st = adap->priv; | ||
| 31 | |||
| 32 | demod_cfg.demod_address = 0x8; | ||
| 33 | |||
| 34 | if ((adap->fe = dvb_attach(dib3000mb_attach, &demod_cfg, | ||
| 35 | &adap->dev->i2c_adap, &st->ops)) == NULL) | ||
| 36 | return -ENODEV; | ||
| 37 | |||
| 38 | adap->fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl; | ||
| 39 | |||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 44 | { | ||
| 45 | struct dibusb_state *st = adap->priv; | ||
| 46 | |||
| 47 | st->tuner_addr = 0x61; | ||
| 48 | |||
| 49 | dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap, | ||
| 50 | DVB_PLL_TUA6010XS); | ||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | static int dibusb_panasonic_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 55 | { | ||
| 56 | struct dibusb_state *st = adap->priv; | ||
| 57 | |||
| 58 | st->tuner_addr = 0x60; | ||
| 59 | |||
| 60 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, &adap->dev->i2c_adap, | ||
| 61 | DVB_PLL_TDA665X); | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* Some of the Artec 1.1 device aren't equipped with the default tuner | ||
| 66 | * (Thomson Cable), but with a Panasonic ENV77H11D5. This function figures | ||
| 67 | * this out. */ | ||
| 68 | static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap) | ||
| 69 | { | ||
| 70 | u8 b[2] = { 0,0 }, b2[1]; | ||
| 71 | int ret = 0; | ||
| 72 | struct i2c_msg msg[2] = { | ||
| 73 | { .flags = 0, .buf = b, .len = 2 }, | ||
| 74 | { .flags = I2C_M_RD, .buf = b2, .len = 1 }, | ||
| 75 | }; | ||
| 76 | struct dibusb_state *st = adap->priv; | ||
| 77 | |||
| 78 | /* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */ | ||
| 79 | msg[0].addr = msg[1].addr = st->tuner_addr = 0x60; | ||
| 80 | |||
| 81 | if (adap->fe->ops.i2c_gate_ctrl) | ||
| 82 | adap->fe->ops.i2c_gate_ctrl(adap->fe,1); | ||
| 83 | |||
| 84 | if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) { | ||
| 85 | err("tuner i2c write failed."); | ||
| 86 | ret = -EREMOTEIO; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (adap->fe->ops.i2c_gate_ctrl) | ||
| 90 | adap->fe->ops.i2c_gate_ctrl(adap->fe,0); | ||
| 91 | |||
| 92 | if (b2[0] == 0xfe) { | ||
| 93 | info("This device has the Thomson Cable onboard. Which is default."); | ||
| 94 | ret = dibusb_thomson_tuner_attach(adap); | ||
| 95 | } else { | ||
| 96 | info("This device has the Panasonic ENV77H11D5 onboard."); | ||
| 97 | ret = dibusb_panasonic_tuner_attach(adap); | ||
| 98 | } | ||
| 99 | |||
| 100 | return ret; | ||
| 101 | } | ||
| 102 | |||
| 103 | /* USB Driver stuff */ | ||
| 104 | static struct dvb_usb_device_properties dibusb1_1_properties; | ||
| 105 | static struct dvb_usb_device_properties dibusb1_1_an2235_properties; | ||
| 106 | static struct dvb_usb_device_properties dibusb2_0b_properties; | ||
| 107 | static struct dvb_usb_device_properties artec_t1_usb2_properties; | ||
| 108 | |||
| 109 | static int dibusb_probe(struct usb_interface *intf, | ||
| 110 | const struct usb_device_id *id) | ||
| 111 | { | ||
| 112 | if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties, | ||
| 113 | THIS_MODULE, NULL, adapter_nr) || | ||
| 114 | 0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties, | ||
| 115 | THIS_MODULE, NULL, adapter_nr) || | ||
| 116 | 0 == dvb_usb_device_init(intf, &dibusb2_0b_properties, | ||
| 117 | THIS_MODULE, NULL, adapter_nr) || | ||
| 118 | 0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties, | ||
| 119 | THIS_MODULE, NULL, adapter_nr)) | ||
| 120 | return 0; | ||
| 121 | |||
| 122 | return -EINVAL; | ||
| 123 | } | ||
| 124 | |||
| 125 | /* do not change the order of the ID table */ | ||
| 126 | static struct usb_device_id dibusb_dib3000mb_table [] = { | ||
| 127 | /* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD) }, | ||
| 128 | /* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM) }, | ||
| 129 | /* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) }, | ||
| 130 | /* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) }, | ||
| 131 | /* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) }, | ||
| 132 | /* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) }, | ||
| 133 | /* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) }, | ||
| 134 | /* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) }, | ||
| 135 | /* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) }, | ||
| 136 | /* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) }, | ||
| 137 | /* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) }, | ||
| 138 | /* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) }, | ||
| 139 | /* 12 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) }, | ||
| 140 | /* 13 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) }, | ||
| 141 | /* 14 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) }, | ||
| 142 | /* 15 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_COLD) }, | ||
| 143 | /* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) }, | ||
| 144 | /* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) }, | ||
| 145 | /* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) }, | ||
| 146 | /* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) }, | ||
| 147 | /* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) }, | ||
| 148 | /* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) }, | ||
| 149 | /* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) }, | ||
| 150 | /* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) }, | ||
| 151 | |||
| 152 | /* device ID with default DIBUSB2_0-firmware and with the hacked firmware */ | ||
| 153 | /* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) }, | ||
| 154 | /* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) }, | ||
| 155 | /* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) }, | ||
| 156 | |||
| 157 | /* 27 */ { USB_DEVICE(USB_VID_KWORLD, USB_PID_KWORLD_VSTREAM_COLD) }, | ||
| 158 | |||
| 159 | /* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, | ||
| 160 | /* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, | ||
| 161 | |||
| 162 | /* | ||
| 163 | * XXX: As Artec just 'forgot' to program the EEPROM on some Artec T1 devices | ||
| 164 | * we don't catch these faulty IDs (namely 'Cypress FX1 USB controller') that | ||
| 165 | * have been left on the device. If you don't have such a device but an Artec | ||
| 166 | * device that's supposed to work with this driver but is not detected by it, | ||
| 167 | * free to enable CONFIG_DVB_USB_DIBUSB_MB_FAULTY via your kernel config. | ||
| 168 | */ | ||
| 169 | |||
| 170 | #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY | ||
| 171 | /* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) }, | ||
| 172 | #endif | ||
| 173 | |||
| 174 | { } /* Terminating entry */ | ||
| 175 | }; | ||
| 176 | MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table); | ||
| 177 | |||
| 178 | static struct dvb_usb_device_properties dibusb1_1_properties = { | ||
| 179 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 180 | |||
| 181 | .usb_ctrl = CYPRESS_AN2135, | ||
| 182 | |||
| 183 | .firmware = "dvb-usb-dibusb-5.0.0.11.fw", | ||
| 184 | |||
| 185 | .num_adapters = 1, | ||
| 186 | .adapter = { | ||
| 187 | { | ||
| 188 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 189 | .pid_filter_count = 16, | ||
| 190 | |||
| 191 | .streaming_ctrl = dibusb_streaming_ctrl, | ||
| 192 | .pid_filter = dibusb_pid_filter, | ||
| 193 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
| 194 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | ||
| 195 | .tuner_attach = dibusb_tuner_probe_and_attach, | ||
| 196 | |||
| 197 | /* parameter for the MPEG2-data transfer */ | ||
| 198 | .stream = { | ||
| 199 | .type = USB_BULK, | ||
| 200 | .count = 7, | ||
| 201 | .endpoint = 0x02, | ||
| 202 | .u = { | ||
| 203 | .bulk = { | ||
| 204 | .buffersize = 4096, | ||
| 205 | } | ||
| 206 | } | ||
| 207 | }, | ||
| 208 | .size_of_priv = sizeof(struct dibusb_state), | ||
| 209 | } | ||
| 210 | }, | ||
| 211 | |||
| 212 | .power_ctrl = dibusb_power_ctrl, | ||
| 213 | |||
| 214 | .rc.legacy = { | ||
| 215 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 216 | .rc_map_table = rc_map_dibusb_table, | ||
| 217 | .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ | ||
| 218 | .rc_query = dibusb_rc_query, | ||
| 219 | }, | ||
| 220 | |||
| 221 | .i2c_algo = &dibusb_i2c_algo, | ||
| 222 | |||
| 223 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 224 | |||
| 225 | .num_device_descs = 9, | ||
| 226 | .devices = { | ||
| 227 | { "AVerMedia AverTV DVBT USB1.1", | ||
| 228 | { &dibusb_dib3000mb_table[0], NULL }, | ||
| 229 | { &dibusb_dib3000mb_table[1], NULL }, | ||
| 230 | }, | ||
| 231 | { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)", | ||
| 232 | { &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL}, | ||
| 233 | { &dibusb_dib3000mb_table[3], NULL }, | ||
| 234 | }, | ||
| 235 | { "DiBcom USB1.1 DVB-T reference design (MOD3000)", | ||
| 236 | { &dibusb_dib3000mb_table[5], NULL }, | ||
| 237 | { &dibusb_dib3000mb_table[6], NULL }, | ||
| 238 | }, | ||
| 239 | { "KWorld V-Stream XPERT DTV - DVB-T USB1.1", | ||
| 240 | { &dibusb_dib3000mb_table[7], NULL }, | ||
| 241 | { &dibusb_dib3000mb_table[8], NULL }, | ||
| 242 | }, | ||
| 243 | { "Grandtec USB1.1 DVB-T", | ||
| 244 | { &dibusb_dib3000mb_table[9], &dibusb_dib3000mb_table[11], NULL }, | ||
| 245 | { &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL }, | ||
| 246 | }, | ||
| 247 | { "Unknown USB1.1 DVB-T device ???? please report the name to the author", | ||
| 248 | { &dibusb_dib3000mb_table[13], NULL }, | ||
| 249 | { &dibusb_dib3000mb_table[14], NULL }, | ||
| 250 | }, | ||
| 251 | { "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device", | ||
| 252 | { &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL}, | ||
| 253 | { &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL}, | ||
| 254 | }, | ||
| 255 | { "Artec T1 USB1.1 TVBOX with AN2135", | ||
| 256 | { &dibusb_dib3000mb_table[19], NULL }, | ||
| 257 | { &dibusb_dib3000mb_table[20], NULL }, | ||
| 258 | }, | ||
| 259 | { "VideoWalker DVB-T USB", | ||
| 260 | { &dibusb_dib3000mb_table[25], NULL }, | ||
| 261 | { &dibusb_dib3000mb_table[26], NULL }, | ||
| 262 | }, | ||
| 263 | } | ||
| 264 | }; | ||
| 265 | |||
| 266 | static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { | ||
| 267 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 268 | .usb_ctrl = CYPRESS_AN2235, | ||
| 269 | |||
| 270 | .firmware = "dvb-usb-dibusb-an2235-01.fw", | ||
| 271 | |||
| 272 | .num_adapters = 1, | ||
| 273 | .adapter = { | ||
| 274 | { | ||
| 275 | .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, | ||
| 276 | .pid_filter_count = 16, | ||
| 277 | |||
| 278 | .streaming_ctrl = dibusb_streaming_ctrl, | ||
| 279 | .pid_filter = dibusb_pid_filter, | ||
| 280 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
| 281 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | ||
| 282 | .tuner_attach = dibusb_tuner_probe_and_attach, | ||
| 283 | |||
| 284 | /* parameter for the MPEG2-data transfer */ | ||
| 285 | .stream = { | ||
| 286 | .type = USB_BULK, | ||
| 287 | .count = 7, | ||
| 288 | .endpoint = 0x02, | ||
| 289 | .u = { | ||
| 290 | .bulk = { | ||
| 291 | .buffersize = 4096, | ||
| 292 | } | ||
| 293 | } | ||
| 294 | }, | ||
| 295 | .size_of_priv = sizeof(struct dibusb_state), | ||
| 296 | }, | ||
| 297 | }, | ||
| 298 | .power_ctrl = dibusb_power_ctrl, | ||
| 299 | |||
| 300 | .rc.legacy = { | ||
| 301 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 302 | .rc_map_table = rc_map_dibusb_table, | ||
| 303 | .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ | ||
| 304 | .rc_query = dibusb_rc_query, | ||
| 305 | }, | ||
| 306 | |||
| 307 | .i2c_algo = &dibusb_i2c_algo, | ||
| 308 | |||
| 309 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 310 | |||
| 311 | #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY | ||
| 312 | .num_device_descs = 2, | ||
| 313 | #else | ||
| 314 | .num_device_descs = 1, | ||
| 315 | #endif | ||
| 316 | .devices = { | ||
| 317 | { "Artec T1 USB1.1 TVBOX with AN2235", | ||
| 318 | { &dibusb_dib3000mb_table[21], NULL }, | ||
| 319 | { &dibusb_dib3000mb_table[22], NULL }, | ||
| 320 | }, | ||
| 321 | #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY | ||
| 322 | { "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)", | ||
| 323 | { &dibusb_dib3000mb_table[30], NULL }, | ||
| 324 | { NULL }, | ||
| 325 | }, | ||
| 326 | { NULL }, | ||
| 327 | #endif | ||
| 328 | } | ||
| 329 | }; | ||
| 330 | |||
| 331 | static struct dvb_usb_device_properties dibusb2_0b_properties = { | ||
| 332 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 333 | |||
| 334 | .usb_ctrl = CYPRESS_FX2, | ||
| 335 | |||
| 336 | .firmware = "dvb-usb-adstech-usb2-02.fw", | ||
| 337 | |||
| 338 | .num_adapters = 1, | ||
| 339 | .adapter = { | ||
| 340 | { | ||
| 341 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 342 | .pid_filter_count = 16, | ||
| 343 | |||
| 344 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
| 345 | .pid_filter = dibusb_pid_filter, | ||
| 346 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
| 347 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | ||
| 348 | .tuner_attach = dibusb_thomson_tuner_attach, | ||
| 349 | |||
| 350 | /* parameter for the MPEG2-data transfer */ | ||
| 351 | .stream = { | ||
| 352 | .type = USB_BULK, | ||
| 353 | .count = 7, | ||
| 354 | .endpoint = 0x06, | ||
| 355 | .u = { | ||
| 356 | .bulk = { | ||
| 357 | .buffersize = 4096, | ||
| 358 | } | ||
| 359 | } | ||
| 360 | }, | ||
| 361 | .size_of_priv = sizeof(struct dibusb_state), | ||
| 362 | } | ||
| 363 | }, | ||
| 364 | .power_ctrl = dibusb2_0_power_ctrl, | ||
| 365 | |||
| 366 | .rc.legacy = { | ||
| 367 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 368 | .rc_map_table = rc_map_dibusb_table, | ||
| 369 | .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ | ||
| 370 | .rc_query = dibusb_rc_query, | ||
| 371 | }, | ||
| 372 | |||
| 373 | .i2c_algo = &dibusb_i2c_algo, | ||
| 374 | |||
| 375 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 376 | |||
| 377 | .num_device_descs = 2, | ||
| 378 | .devices = { | ||
| 379 | { "KWorld/ADSTech Instant DVB-T USB2.0", | ||
| 380 | { &dibusb_dib3000mb_table[23], NULL }, | ||
| 381 | { &dibusb_dib3000mb_table[24], NULL }, | ||
| 382 | }, | ||
| 383 | { "KWorld Xpert DVB-T USB2.0", | ||
| 384 | { &dibusb_dib3000mb_table[27], NULL }, | ||
| 385 | { NULL } | ||
| 386 | }, | ||
| 387 | { NULL }, | ||
| 388 | } | ||
| 389 | }; | ||
| 390 | |||
| 391 | static struct dvb_usb_device_properties artec_t1_usb2_properties = { | ||
| 392 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 393 | |||
| 394 | .usb_ctrl = CYPRESS_FX2, | ||
| 395 | |||
| 396 | .firmware = "dvb-usb-dibusb-6.0.0.8.fw", | ||
| 397 | |||
| 398 | .num_adapters = 1, | ||
| 399 | .adapter = { | ||
| 400 | { | ||
| 401 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 402 | .pid_filter_count = 16, | ||
| 403 | |||
| 404 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
| 405 | .pid_filter = dibusb_pid_filter, | ||
| 406 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
| 407 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | ||
| 408 | .tuner_attach = dibusb_tuner_probe_and_attach, | ||
| 409 | /* parameter for the MPEG2-data transfer */ | ||
| 410 | .stream = { | ||
| 411 | .type = USB_BULK, | ||
| 412 | .count = 7, | ||
| 413 | .endpoint = 0x06, | ||
| 414 | .u = { | ||
| 415 | .bulk = { | ||
| 416 | .buffersize = 4096, | ||
| 417 | } | ||
| 418 | } | ||
| 419 | }, | ||
| 420 | .size_of_priv = sizeof(struct dibusb_state), | ||
| 421 | } | ||
| 422 | }, | ||
| 423 | .power_ctrl = dibusb2_0_power_ctrl, | ||
| 424 | |||
| 425 | .rc.legacy = { | ||
| 426 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 427 | .rc_map_table = rc_map_dibusb_table, | ||
| 428 | .rc_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ | ||
| 429 | .rc_query = dibusb_rc_query, | ||
| 430 | }, | ||
| 431 | |||
| 432 | .i2c_algo = &dibusb_i2c_algo, | ||
| 433 | |||
| 434 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 435 | |||
| 436 | .num_device_descs = 1, | ||
| 437 | .devices = { | ||
| 438 | { "Artec T1 USB2.0", | ||
| 439 | { &dibusb_dib3000mb_table[28], NULL }, | ||
| 440 | { &dibusb_dib3000mb_table[29], NULL }, | ||
| 441 | }, | ||
| 442 | { NULL }, | ||
| 443 | } | ||
| 444 | }; | ||
| 445 | |||
| 446 | static struct usb_driver dibusb_driver = { | ||
| 447 | .name = "dvb_usb_dibusb_mb", | ||
| 448 | .probe = dibusb_probe, | ||
| 449 | .disconnect = dvb_usb_device_exit, | ||
| 450 | .id_table = dibusb_dib3000mb_table, | ||
| 451 | }; | ||
| 452 | |||
| 453 | /* module stuff */ | ||
| 454 | static int __init dibusb_module_init(void) | ||
| 455 | { | ||
| 456 | int result; | ||
| 457 | if ((result = usb_register(&dibusb_driver))) { | ||
| 458 | err("usb_register failed. Error number %d",result); | ||
| 459 | return result; | ||
| 460 | } | ||
| 461 | |||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | |||
| 465 | static void __exit dibusb_module_exit(void) | ||
| 466 | { | ||
| 467 | /* deregister this driver from the USB subsystem */ | ||
| 468 | usb_deregister(&dibusb_driver); | ||
| 469 | } | ||
| 470 | |||
| 471 | module_init (dibusb_module_init); | ||
| 472 | module_exit (dibusb_module_exit); | ||
| 473 | |||
| 474 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 475 | MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)"); | ||
| 476 | MODULE_VERSION("1.0"); | ||
| 477 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c new file mode 100644 index 00000000000..c1d9094b61e --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | /* DVB USB compliant linux driver for mobile DVB-T USB devices based on | ||
| 2 | * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 5 | * | ||
| 6 | * based on GPL code from DiBcom, which has | ||
| 7 | * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the Free | ||
| 11 | * Software Foundation, version 2. | ||
| 12 | * | ||
| 13 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 14 | */ | ||
| 15 | #include "dibusb.h" | ||
| 16 | |||
| 17 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 18 | |||
| 19 | /* USB Driver stuff */ | ||
| 20 | static struct dvb_usb_device_properties dibusb_mc_properties; | ||
| 21 | |||
| 22 | static int dibusb_mc_probe(struct usb_interface *intf, | ||
| 23 | const struct usb_device_id *id) | ||
| 24 | { | ||
| 25 | return dvb_usb_device_init(intf, &dibusb_mc_properties, THIS_MODULE, | ||
| 26 | NULL, adapter_nr); | ||
| 27 | } | ||
| 28 | |||
| 29 | /* do not change the order of the ID table */ | ||
| 30 | static struct usb_device_id dibusb_dib3000mc_table [] = { | ||
| 31 | /* 00 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) }, | ||
| 32 | /* 01 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) }, | ||
| 33 | /* 02 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, | ||
| 34 | /* 03 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, // ( ? ) | ||
| 35 | /* 04 */ { USB_DEVICE(USB_VID_LITEON, USB_PID_LITEON_DVB_T_COLD) }, | ||
| 36 | /* 05 */ { USB_DEVICE(USB_VID_LITEON, USB_PID_LITEON_DVB_T_WARM) }, | ||
| 37 | /* 06 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_DIGIVOX_MINI_SL_COLD) }, | ||
| 38 | /* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_DIGIVOX_MINI_SL_WARM) }, | ||
| 39 | /* 08 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB2_COLD) }, | ||
| 40 | /* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB2_WARM) }, | ||
| 41 | /* 10 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_COLD) }, | ||
| 42 | /* 11 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_WARM) }, | ||
| 43 | /* 12 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_COLD) }, | ||
| 44 | /* 13 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_WARM) }, | ||
| 45 | /* 14 */ { USB_DEVICE(USB_VID_HUMAX_COEX, USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD) }, | ||
| 46 | /* 15 */ { USB_DEVICE(USB_VID_HUMAX_COEX, USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM) }, | ||
| 47 | { } /* Terminating entry */ | ||
| 48 | }; | ||
| 49 | MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table); | ||
| 50 | |||
| 51 | static struct dvb_usb_device_properties dibusb_mc_properties = { | ||
| 52 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 53 | |||
| 54 | .usb_ctrl = CYPRESS_FX2, | ||
| 55 | .firmware = "dvb-usb-dibusb-6.0.0.8.fw", | ||
| 56 | |||
| 57 | .num_adapters = 1, | ||
| 58 | .adapter = { | ||
| 59 | { | ||
| 60 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 61 | .pid_filter_count = 32, | ||
| 62 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
| 63 | .pid_filter = dibusb_pid_filter, | ||
| 64 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
| 65 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | ||
| 66 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | ||
| 67 | |||
| 68 | /* parameter for the MPEG2-data transfer */ | ||
| 69 | .stream = { | ||
| 70 | .type = USB_BULK, | ||
| 71 | .count = 8, | ||
| 72 | .endpoint = 0x06, | ||
| 73 | .u = { | ||
| 74 | .bulk = { | ||
| 75 | .buffersize = 4096, | ||
| 76 | } | ||
| 77 | } | ||
| 78 | }, | ||
| 79 | .size_of_priv = sizeof(struct dibusb_state), | ||
| 80 | } | ||
| 81 | }, | ||
| 82 | .power_ctrl = dibusb2_0_power_ctrl, | ||
| 83 | |||
| 84 | .rc.legacy = { | ||
| 85 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
| 86 | .rc_map_table = rc_map_dibusb_table, | ||
| 87 | .rc_map_size = 111, /* FIXME */ | ||
| 88 | .rc_query = dibusb_rc_query, | ||
| 89 | }, | ||
| 90 | |||
| 91 | .i2c_algo = &dibusb_i2c_algo, | ||
| 92 | |||
| 93 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 94 | |||
| 95 | .num_device_descs = 8, | ||
| 96 | .devices = { | ||
| 97 | { "DiBcom USB2.0 DVB-T reference design (MOD3000P)", | ||
| 98 | { &dibusb_dib3000mc_table[0], NULL }, | ||
| 99 | { &dibusb_dib3000mc_table[1], NULL }, | ||
| 100 | }, | ||
| 101 | { "Artec T1 USB2.0 TVBOX (please check the warm ID)", | ||
| 102 | { &dibusb_dib3000mc_table[2], NULL }, | ||
| 103 | { &dibusb_dib3000mc_table[3], NULL }, | ||
| 104 | }, | ||
| 105 | { "LITE-ON USB2.0 DVB-T Tuner", | ||
| 106 | /* Also rebranded as Intuix S800, Toshiba */ | ||
| 107 | { &dibusb_dib3000mc_table[4], NULL }, | ||
| 108 | { &dibusb_dib3000mc_table[5], NULL }, | ||
| 109 | }, | ||
| 110 | { "MSI Digivox Mini SL", | ||
| 111 | { &dibusb_dib3000mc_table[6], NULL }, | ||
| 112 | { &dibusb_dib3000mc_table[7], NULL }, | ||
| 113 | }, | ||
| 114 | { "GRAND - USB2.0 DVB-T adapter", | ||
| 115 | { &dibusb_dib3000mc_table[8], NULL }, | ||
| 116 | { &dibusb_dib3000mc_table[9], NULL }, | ||
| 117 | }, | ||
| 118 | { "Artec T14 - USB2.0 DVB-T", | ||
| 119 | { &dibusb_dib3000mc_table[10], NULL }, | ||
| 120 | { &dibusb_dib3000mc_table[11], NULL }, | ||
| 121 | }, | ||
| 122 | { "Leadtek - USB2.0 Winfast DTV dongle", | ||
| 123 | { &dibusb_dib3000mc_table[12], NULL }, | ||
| 124 | { &dibusb_dib3000mc_table[13], NULL }, | ||
| 125 | }, | ||
| 126 | { "Humax/Coex DVB-T USB Stick 2.0 High Speed", | ||
| 127 | { &dibusb_dib3000mc_table[14], NULL }, | ||
| 128 | { &dibusb_dib3000mc_table[15], NULL }, | ||
| 129 | }, | ||
| 130 | { NULL }, | ||
| 131 | } | ||
| 132 | }; | ||
| 133 | |||
| 134 | static struct usb_driver dibusb_mc_driver = { | ||
| 135 | .name = "dvb_usb_dibusb_mc", | ||
| 136 | .probe = dibusb_mc_probe, | ||
| 137 | .disconnect = dvb_usb_device_exit, | ||
| 138 | .id_table = dibusb_dib3000mc_table, | ||
| 139 | }; | ||
| 140 | |||
| 141 | /* module stuff */ | ||
| 142 | static int __init dibusb_mc_module_init(void) | ||
| 143 | { | ||
| 144 | int result; | ||
| 145 | if ((result = usb_register(&dibusb_mc_driver))) { | ||
| 146 | err("usb_register failed. Error number %d",result); | ||
| 147 | return result; | ||
| 148 | } | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static void __exit dibusb_mc_module_exit(void) | ||
| 154 | { | ||
| 155 | /* deregister this driver from the USB subsystem */ | ||
| 156 | usb_deregister(&dibusb_mc_driver); | ||
| 157 | } | ||
| 158 | |||
| 159 | module_init (dibusb_mc_module_init); | ||
| 160 | module_exit (dibusb_mc_module_exit); | ||
| 161 | |||
| 162 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 163 | MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices"); | ||
| 164 | MODULE_VERSION("1.0"); | ||
| 165 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h new file mode 100644 index 00000000000..e47c321b3ff --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb.h | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | /* Header file for all dibusb-based-receivers. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 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 Free | ||
| 7 | * Software Foundation, version 2. | ||
| 8 | * | ||
| 9 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 10 | */ | ||
| 11 | #ifndef _DVB_USB_DIBUSB_H_ | ||
| 12 | #define _DVB_USB_DIBUSB_H_ | ||
| 13 | |||
| 14 | #ifndef DVB_USB_LOG_PREFIX | ||
| 15 | #define DVB_USB_LOG_PREFIX "dibusb" | ||
| 16 | #endif | ||
| 17 | #include "dvb-usb.h" | ||
| 18 | |||
| 19 | #include "dib3000.h" | ||
| 20 | #include "dib3000mc.h" | ||
| 21 | #include "mt2060.h" | ||
| 22 | |||
| 23 | /* | ||
| 24 | * protocol of all dibusb related devices | ||
| 25 | */ | ||
| 26 | |||
| 27 | /* | ||
| 28 | * bulk msg to/from endpoint 0x01 | ||
| 29 | * | ||
| 30 | * general structure: | ||
| 31 | * request_byte parameter_bytes | ||
| 32 | */ | ||
| 33 | |||
| 34 | #define DIBUSB_REQ_START_READ 0x00 | ||
| 35 | #define DIBUSB_REQ_START_DEMOD 0x01 | ||
| 36 | |||
| 37 | /* | ||
| 38 | * i2c read | ||
| 39 | * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word | ||
| 40 | * bulk read: byte_buffer (length_word bytes) | ||
| 41 | */ | ||
| 42 | #define DIBUSB_REQ_I2C_READ 0x02 | ||
| 43 | |||
| 44 | /* | ||
| 45 | * i2c write | ||
| 46 | * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes | ||
| 47 | */ | ||
| 48 | #define DIBUSB_REQ_I2C_WRITE 0x03 | ||
| 49 | |||
| 50 | /* | ||
| 51 | * polling the value of the remote control | ||
| 52 | * bulk write: 0x04 | ||
| 53 | * bulk read: byte_buffer (5 bytes) | ||
| 54 | */ | ||
| 55 | #define DIBUSB_REQ_POLL_REMOTE 0x04 | ||
| 56 | |||
| 57 | /* additional status values for Hauppauge Remote Control Protocol */ | ||
| 58 | #define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED 0x01 | ||
| 59 | #define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY 0x03 | ||
| 60 | |||
| 61 | /* streaming mode: | ||
| 62 | * bulk write: 0x05 mode_byte | ||
| 63 | * | ||
| 64 | * mode_byte is mostly 0x00 | ||
| 65 | */ | ||
| 66 | #define DIBUSB_REQ_SET_STREAMING_MODE 0x05 | ||
| 67 | |||
| 68 | /* interrupt the internal read loop, when blocking */ | ||
| 69 | #define DIBUSB_REQ_INTR_READ 0x06 | ||
| 70 | |||
| 71 | /* io control | ||
| 72 | * 0x07 cmd_byte param_bytes | ||
| 73 | * | ||
| 74 | * param_bytes can be up to 32 bytes | ||
| 75 | * | ||
| 76 | * cmd_byte function parameter name | ||
| 77 | * 0x00 power mode | ||
| 78 | * 0x00 sleep | ||
| 79 | * 0x01 wakeup | ||
| 80 | * | ||
| 81 | * 0x01 enable streaming | ||
| 82 | * 0x02 disable streaming | ||
| 83 | * | ||
| 84 | * | ||
| 85 | */ | ||
| 86 | #define DIBUSB_REQ_SET_IOCTL 0x07 | ||
| 87 | |||
| 88 | /* IOCTL commands */ | ||
| 89 | |||
| 90 | /* change the power mode in firmware */ | ||
| 91 | #define DIBUSB_IOCTL_CMD_POWER_MODE 0x00 | ||
| 92 | #define DIBUSB_IOCTL_POWER_SLEEP 0x00 | ||
| 93 | #define DIBUSB_IOCTL_POWER_WAKEUP 0x01 | ||
| 94 | |||
| 95 | /* modify streaming of the FX2 */ | ||
| 96 | #define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01 | ||
| 97 | #define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02 | ||
| 98 | |||
| 99 | struct dibusb_state { | ||
| 100 | struct dib_fe_xfer_ops ops; | ||
| 101 | int mt2060_present; | ||
| 102 | u8 tuner_addr; | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct dibusb_device_state { | ||
| 106 | /* for RC5 remote control */ | ||
| 107 | int old_toggle; | ||
| 108 | int last_repeat_count; | ||
| 109 | }; | ||
| 110 | |||
| 111 | extern struct i2c_algorithm dibusb_i2c_algo; | ||
| 112 | |||
| 113 | extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *); | ||
| 114 | extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_adapter *); | ||
| 115 | |||
| 116 | extern int dibusb_streaming_ctrl(struct dvb_usb_adapter *, int); | ||
| 117 | extern int dibusb_pid_filter(struct dvb_usb_adapter *, int, u16, int); | ||
| 118 | extern int dibusb_pid_filter_ctrl(struct dvb_usb_adapter *, int); | ||
| 119 | extern int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *, int); | ||
| 120 | |||
| 121 | extern int dibusb_power_ctrl(struct dvb_usb_device *, int); | ||
| 122 | extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int); | ||
| 123 | |||
| 124 | #define DEFAULT_RC_INTERVAL 150 | ||
| 125 | //#define DEFAULT_RC_INTERVAL 100000 | ||
| 126 | |||
| 127 | extern struct rc_map_table rc_map_dibusb_table[]; | ||
| 128 | extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *); | ||
| 129 | extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *); | ||
| 130 | |||
| 131 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c new file mode 100644 index 00000000000..f6344cdd360 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/digitv.c | |||
| @@ -0,0 +1,365 @@ | |||
| 1 | /* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0 | ||
| 2 | * receiver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 5 | * | ||
| 6 | * partly based on the SDK published by Nebula Electronics | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation, version 2. | ||
| 11 | * | ||
| 12 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 13 | */ | ||
| 14 | #include "digitv.h" | ||
| 15 | |||
| 16 | #include "mt352.h" | ||
| 17 | #include "nxt6000.h" | ||
| 18 | |||
| 19 | /* debug */ | ||
| 20 | static int dvb_usb_digitv_debug; | ||
| 21 | module_param_named(debug,dvb_usb_digitv_debug, int, 0644); | ||
| 22 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 23 | |||
| 24 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 25 | |||
| 26 | #define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args) | ||
| 27 | |||
| 28 | static int digitv_ctrl_msg(struct dvb_usb_device *d, | ||
| 29 | u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
| 30 | { | ||
| 31 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
| 32 | u8 sndbuf[7],rcvbuf[7]; | ||
| 33 | memset(sndbuf,0,7); memset(rcvbuf,0,7); | ||
| 34 | |||
| 35 | sndbuf[0] = cmd; | ||
| 36 | sndbuf[1] = vv; | ||
| 37 | sndbuf[2] = wo ? wlen : rlen; | ||
| 38 | |||
| 39 | if (wo) { | ||
| 40 | memcpy(&sndbuf[3],wbuf,wlen); | ||
| 41 | dvb_usb_generic_write(d,sndbuf,7); | ||
| 42 | } else { | ||
| 43 | dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10); | ||
| 44 | memcpy(rbuf,&rcvbuf[3],rlen); | ||
| 45 | } | ||
| 46 | return 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | /* I2C */ | ||
| 50 | static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | ||
| 51 | { | ||
| 52 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 53 | int i; | ||
| 54 | |||
| 55 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 56 | return -EAGAIN; | ||
| 57 | |||
| 58 | if (num > 2) | ||
| 59 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
| 60 | |||
| 61 | for (i = 0; i < num; i++) { | ||
| 62 | /* write/read request */ | ||
| 63 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
| 64 | if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0, | ||
| 65 | msg[i+1].buf,msg[i+1].len) < 0) | ||
| 66 | break; | ||
| 67 | i++; | ||
| 68 | } else | ||
| 69 | if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0], | ||
| 70 | &msg[i].buf[1],msg[i].len-1,NULL,0) < 0) | ||
| 71 | break; | ||
| 72 | } | ||
| 73 | |||
| 74 | mutex_unlock(&d->i2c_mutex); | ||
| 75 | return i; | ||
| 76 | } | ||
| 77 | |||
| 78 | static u32 digitv_i2c_func(struct i2c_adapter *adapter) | ||
| 79 | { | ||
| 80 | return I2C_FUNC_I2C; | ||
| 81 | } | ||
| 82 | |||
| 83 | static struct i2c_algorithm digitv_i2c_algo = { | ||
| 84 | .master_xfer = digitv_i2c_xfer, | ||
| 85 | .functionality = digitv_i2c_func, | ||
| 86 | }; | ||
| 87 | |||
| 88 | /* Callbacks for DVB USB */ | ||
| 89 | static int digitv_identify_state (struct usb_device *udev, struct | ||
| 90 | dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, | ||
| 91 | int *cold) | ||
| 92 | { | ||
| 93 | *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0; | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | static int digitv_mt352_demod_init(struct dvb_frontend *fe) | ||
| 98 | { | ||
| 99 | static u8 reset_buf[] = { 0x89, 0x38, 0x8a, 0x2d, 0x50, 0x80 }; | ||
| 100 | static u8 init_buf[] = { 0x68, 0xa0, 0x8e, 0x40, 0x53, 0x50, | ||
| 101 | 0x67, 0x20, 0x7d, 0x01, 0x7c, 0x00, 0x7a, 0x00, | ||
| 102 | 0x79, 0x20, 0x57, 0x05, 0x56, 0x31, 0x88, 0x0f, | ||
| 103 | 0x75, 0x32 }; | ||
| 104 | int i; | ||
| 105 | |||
| 106 | for (i = 0; i < ARRAY_SIZE(reset_buf); i += 2) | ||
| 107 | mt352_write(fe, &reset_buf[i], 2); | ||
| 108 | |||
| 109 | msleep(1); | ||
| 110 | |||
| 111 | for (i = 0; i < ARRAY_SIZE(init_buf); i += 2) | ||
| 112 | mt352_write(fe, &init_buf[i], 2); | ||
| 113 | |||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | static struct mt352_config digitv_mt352_config = { | ||
| 118 | .demod_init = digitv_mt352_demod_init, | ||
| 119 | }; | ||
| 120 | |||
| 121 | static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | ||
| 122 | { | ||
| 123 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 124 | u8 b[5]; | ||
| 125 | |||
| 126 | fe->ops.tuner_ops.calc_regs(fe, fep, b, sizeof(b)); | ||
| 127 | if (fe->ops.i2c_gate_ctrl) | ||
| 128 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
| 129 | return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0); | ||
| 130 | } | ||
| 131 | |||
| 132 | static struct nxt6000_config digitv_nxt6000_config = { | ||
| 133 | .clock_inversion = 1, | ||
| 134 | }; | ||
| 135 | |||
| 136 | static int digitv_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 137 | { | ||
| 138 | struct digitv_state *st = adap->dev->priv; | ||
| 139 | |||
| 140 | if ((adap->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &adap->dev->i2c_adap)) != NULL) { | ||
| 141 | st->is_nxt6000 = 0; | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | if ((adap->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &adap->dev->i2c_adap)) != NULL) { | ||
| 145 | st->is_nxt6000 = 1; | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | return -EIO; | ||
| 149 | } | ||
| 150 | |||
| 151 | static int digitv_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 152 | { | ||
| 153 | struct digitv_state *st = adap->dev->priv; | ||
| 154 | |||
| 155 | if (!dvb_attach(dvb_pll_attach, adap->fe, 0x60, NULL, DVB_PLL_TDED4)) | ||
| 156 | return -ENODEV; | ||
| 157 | |||
| 158 | if (st->is_nxt6000) | ||
| 159 | adap->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params; | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static struct rc_map_table rc_map_digitv_table[] = { | ||
| 165 | { 0x5f55, KEY_0 }, | ||
| 166 | { 0x6f55, KEY_1 }, | ||
| 167 | { 0x9f55, KEY_2 }, | ||
| 168 | { 0xaf55, KEY_3 }, | ||
| 169 | { 0x5f56, KEY_4 }, | ||
| 170 | { 0x6f56, KEY_5 }, | ||
| 171 | { 0x9f56, KEY_6 }, | ||
| 172 | { 0xaf56, KEY_7 }, | ||
| 173 | { 0x5f59, KEY_8 }, | ||
| 174 | { 0x6f59, KEY_9 }, | ||
| 175 | { 0x9f59, KEY_TV }, | ||
| 176 | { 0xaf59, KEY_AUX }, | ||
| 177 | { 0x5f5a, KEY_DVD }, | ||
| 178 | { 0x6f5a, KEY_POWER }, | ||
| 179 | { 0x9f5a, KEY_CAMERA }, /* labelled 'Picture' */ | ||
| 180 | { 0xaf5a, KEY_AUDIO }, | ||
| 181 | { 0x5f65, KEY_INFO }, | ||
| 182 | { 0x6f65, KEY_F13 }, /* 16:9 */ | ||
| 183 | { 0x9f65, KEY_F14 }, /* 14:9 */ | ||
| 184 | { 0xaf65, KEY_EPG }, | ||
| 185 | { 0x5f66, KEY_EXIT }, | ||
| 186 | { 0x6f66, KEY_MENU }, | ||
| 187 | { 0x9f66, KEY_UP }, | ||
| 188 | { 0xaf66, KEY_DOWN }, | ||
| 189 | { 0x5f69, KEY_LEFT }, | ||
| 190 | { 0x6f69, KEY_RIGHT }, | ||
| 191 | { 0x9f69, KEY_ENTER }, | ||
| 192 | { 0xaf69, KEY_CHANNELUP }, | ||
| 193 | { 0x5f6a, KEY_CHANNELDOWN }, | ||
| 194 | { 0x6f6a, KEY_VOLUMEUP }, | ||
| 195 | { 0x9f6a, KEY_VOLUMEDOWN }, | ||
| 196 | { 0xaf6a, KEY_RED }, | ||
| 197 | { 0x5f95, KEY_GREEN }, | ||
| 198 | { 0x6f95, KEY_YELLOW }, | ||
| 199 | { 0x9f95, KEY_BLUE }, | ||
| 200 | { 0xaf95, KEY_SUBTITLE }, | ||
| 201 | { 0x5f96, KEY_F15 }, /* AD */ | ||
| 202 | { 0x6f96, KEY_TEXT }, | ||
| 203 | { 0x9f96, KEY_MUTE }, | ||
| 204 | { 0xaf96, KEY_REWIND }, | ||
| 205 | { 0x5f99, KEY_STOP }, | ||
| 206 | { 0x6f99, KEY_PLAY }, | ||
| 207 | { 0x9f99, KEY_FASTFORWARD }, | ||
| 208 | { 0xaf99, KEY_F16 }, /* chapter */ | ||
| 209 | { 0x5f9a, KEY_PAUSE }, | ||
| 210 | { 0x6f9a, KEY_PLAY }, | ||
| 211 | { 0x9f9a, KEY_RECORD }, | ||
| 212 | { 0xaf9a, KEY_F17 }, /* picture in picture */ | ||
| 213 | { 0x5fa5, KEY_KPPLUS }, /* zoom in */ | ||
| 214 | { 0x6fa5, KEY_KPMINUS }, /* zoom out */ | ||
| 215 | { 0x9fa5, KEY_F18 }, /* capture */ | ||
| 216 | { 0xafa5, KEY_F19 }, /* web */ | ||
| 217 | { 0x5fa6, KEY_EMAIL }, | ||
| 218 | { 0x6fa6, KEY_PHONE }, | ||
| 219 | { 0x9fa6, KEY_PC }, | ||
| 220 | }; | ||
| 221 | |||
| 222 | static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 223 | { | ||
| 224 | int i; | ||
| 225 | u8 key[5]; | ||
| 226 | u8 b[4] = { 0 }; | ||
| 227 | |||
| 228 | *event = 0; | ||
| 229 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 230 | |||
| 231 | digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4); | ||
| 232 | |||
| 233 | /* Tell the device we've read the remote. Not sure how necessary | ||
| 234 | this is, but the Nebula SDK does it. */ | ||
| 235 | digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0); | ||
| 236 | |||
| 237 | /* if something is inside the buffer, simulate key press */ | ||
| 238 | if (key[1] != 0) | ||
| 239 | { | ||
| 240 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { | ||
| 241 | if (rc5_custom(&d->props.rc.legacy.rc_map_table[i]) == key[1] && | ||
| 242 | rc5_data(&d->props.rc.legacy.rc_map_table[i]) == key[2]) { | ||
| 243 | *event = d->props.rc.legacy.rc_map_table[i].keycode; | ||
| 244 | *state = REMOTE_KEY_PRESSED; | ||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | if (key[0] != 0) | ||
| 251 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | /* DVB USB Driver stuff */ | ||
| 256 | static struct dvb_usb_device_properties digitv_properties; | ||
| 257 | |||
| 258 | static int digitv_probe(struct usb_interface *intf, | ||
| 259 | const struct usb_device_id *id) | ||
| 260 | { | ||
| 261 | struct dvb_usb_device *d; | ||
| 262 | int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d, | ||
| 263 | adapter_nr); | ||
| 264 | if (ret == 0) { | ||
| 265 | u8 b[4] = { 0 }; | ||
| 266 | |||
| 267 | if (d != NULL) { /* do that only when the firmware is loaded */ | ||
| 268 | b[0] = 1; | ||
| 269 | digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0); | ||
| 270 | |||
| 271 | b[0] = 0; | ||
| 272 | digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0); | ||
| 273 | } | ||
| 274 | } | ||
| 275 | return ret; | ||
| 276 | } | ||
| 277 | |||
| 278 | static struct usb_device_id digitv_table [] = { | ||
| 279 | { USB_DEVICE(USB_VID_ANCHOR, USB_PID_NEBULA_DIGITV) }, | ||
| 280 | { } /* Terminating entry */ | ||
| 281 | }; | ||
| 282 | MODULE_DEVICE_TABLE (usb, digitv_table); | ||
| 283 | |||
| 284 | static struct dvb_usb_device_properties digitv_properties = { | ||
| 285 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 286 | |||
| 287 | .usb_ctrl = CYPRESS_FX2, | ||
| 288 | .firmware = "dvb-usb-digitv-02.fw", | ||
| 289 | |||
| 290 | .size_of_priv = sizeof(struct digitv_state), | ||
| 291 | |||
| 292 | .num_adapters = 1, | ||
| 293 | .adapter = { | ||
| 294 | { | ||
| 295 | .frontend_attach = digitv_frontend_attach, | ||
| 296 | .tuner_attach = digitv_tuner_attach, | ||
| 297 | |||
| 298 | /* parameter for the MPEG2-data transfer */ | ||
| 299 | .stream = { | ||
| 300 | .type = USB_BULK, | ||
| 301 | .count = 7, | ||
| 302 | .endpoint = 0x02, | ||
| 303 | .u = { | ||
| 304 | .bulk = { | ||
| 305 | .buffersize = 4096, | ||
| 306 | } | ||
| 307 | } | ||
| 308 | }, | ||
| 309 | } | ||
| 310 | }, | ||
| 311 | .identify_state = digitv_identify_state, | ||
| 312 | |||
| 313 | .rc.legacy = { | ||
| 314 | .rc_interval = 1000, | ||
| 315 | .rc_map_table = rc_map_digitv_table, | ||
| 316 | .rc_map_size = ARRAY_SIZE(rc_map_digitv_table), | ||
| 317 | .rc_query = digitv_rc_query, | ||
| 318 | }, | ||
| 319 | |||
| 320 | .i2c_algo = &digitv_i2c_algo, | ||
| 321 | |||
| 322 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 323 | |||
| 324 | .num_device_descs = 1, | ||
| 325 | .devices = { | ||
| 326 | { "Nebula Electronics uDigiTV DVB-T USB2.0)", | ||
| 327 | { &digitv_table[0], NULL }, | ||
| 328 | { NULL }, | ||
| 329 | }, | ||
| 330 | { NULL }, | ||
| 331 | } | ||
| 332 | }; | ||
| 333 | |||
| 334 | static struct usb_driver digitv_driver = { | ||
| 335 | .name = "dvb_usb_digitv", | ||
| 336 | .probe = digitv_probe, | ||
| 337 | .disconnect = dvb_usb_device_exit, | ||
| 338 | .id_table = digitv_table, | ||
| 339 | }; | ||
| 340 | |||
| 341 | /* module stuff */ | ||
| 342 | static int __init digitv_module_init(void) | ||
| 343 | { | ||
| 344 | int result; | ||
| 345 | if ((result = usb_register(&digitv_driver))) { | ||
| 346 | err("usb_register failed. Error number %d",result); | ||
| 347 | return result; | ||
| 348 | } | ||
| 349 | |||
| 350 | return 0; | ||
| 351 | } | ||
| 352 | |||
| 353 | static void __exit digitv_module_exit(void) | ||
| 354 | { | ||
| 355 | /* deregister this driver from the USB subsystem */ | ||
| 356 | usb_deregister(&digitv_driver); | ||
| 357 | } | ||
| 358 | |||
| 359 | module_init (digitv_module_init); | ||
| 360 | module_exit (digitv_module_exit); | ||
| 361 | |||
| 362 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 363 | MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0"); | ||
| 364 | MODULE_VERSION("1.0-alpha"); | ||
| 365 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/digitv.h b/drivers/media/dvb/dvb-usb/digitv.h new file mode 100644 index 00000000000..908c09f4966 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/digitv.h | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | #ifndef _DVB_USB_DIGITV_H_ | ||
| 2 | #define _DVB_USB_DIGITV_H_ | ||
| 3 | |||
| 4 | #define DVB_USB_LOG_PREFIX "digitv" | ||
| 5 | #include "dvb-usb.h" | ||
| 6 | |||
| 7 | struct digitv_state { | ||
| 8 | int is_nxt6000; | ||
| 9 | }; | ||
| 10 | |||
| 11 | /* protocol (from usblogging and the SDK: | ||
| 12 | * | ||
| 13 | * Always 7 bytes bulk message(s) for controlling | ||
| 14 | * | ||
| 15 | * First byte describes the command. Reads are 2 consecutive transfer (as always). | ||
| 16 | * | ||
| 17 | * General structure: | ||
| 18 | * | ||
| 19 | * write or first message of a read: | ||
| 20 | * <cmdbyte> VV <len> B0 B1 B2 B3 | ||
| 21 | * | ||
| 22 | * second message of a read | ||
| 23 | * <cmdbyte> VV <len> R0 R1 R2 R3 | ||
| 24 | * | ||
| 25 | * whereas 0 < len <= 4 | ||
| 26 | * | ||
| 27 | * I2C address is stored somewhere inside the device. | ||
| 28 | * | ||
| 29 | * 0x01 read from EEPROM | ||
| 30 | * VV = offset; B* = 0; R* = value(s) | ||
| 31 | * | ||
| 32 | * 0x02 read register of the COFDM | ||
| 33 | * VV = register; B* = 0; R* = value(s) | ||
| 34 | * | ||
| 35 | * 0x05 write register of the COFDM | ||
| 36 | * VV = register; B* = value(s); | ||
| 37 | * | ||
| 38 | * 0x06 write to the tuner (only for NXT6000) | ||
| 39 | * VV = 0; B* = PLL data; len = 4; | ||
| 40 | * | ||
| 41 | * 0x03 read remote control | ||
| 42 | * VV = 0; B* = 0; len = 4; R* = key | ||
| 43 | * | ||
| 44 | * 0x07 write to the remote (don't know why one should this, resetting ?) | ||
| 45 | * VV = 0; B* = key; len = 4; | ||
| 46 | * | ||
| 47 | * 0x08 write remote type | ||
| 48 | * VV = 0; B[0] = 0x01, len = 4 | ||
| 49 | * | ||
| 50 | * 0x09 write device init | ||
| 51 | * TODO | ||
| 52 | */ | ||
| 53 | #define USB_READ_EEPROM 1 | ||
| 54 | |||
| 55 | #define USB_READ_COFDM 2 | ||
| 56 | #define USB_WRITE_COFDM 5 | ||
| 57 | |||
| 58 | #define USB_WRITE_TUNER 6 | ||
| 59 | |||
| 60 | #define USB_READ_REMOTE 3 | ||
| 61 | #define USB_WRITE_REMOTE 7 | ||
| 62 | #define USB_WRITE_REMOTE_TYPE 8 | ||
| 63 | |||
| 64 | #define USB_DEV_INIT 9 | ||
| 65 | |||
| 66 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c new file mode 100644 index 00000000000..17413adec7a --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c | |||
| @@ -0,0 +1,205 @@ | |||
| 1 | /* Frontend part of the Linux driver for the WideView/ Yakumo/ Hama/ | ||
| 2 | * Typhoon/ Yuan DVB-T USB2.0 receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the Free | ||
| 8 | * Software Foundation, version 2. | ||
| 9 | * | ||
| 10 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 11 | */ | ||
| 12 | #include "dtt200u.h" | ||
| 13 | |||
| 14 | struct dtt200u_fe_state { | ||
| 15 | struct dvb_usb_device *d; | ||
| 16 | |||
| 17 | fe_status_t stat; | ||
| 18 | |||
| 19 | struct dvb_frontend_parameters fep; | ||
| 20 | struct dvb_frontend frontend; | ||
| 21 | }; | ||
| 22 | |||
| 23 | static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat) | ||
| 24 | { | ||
| 25 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
| 26 | u8 st = GET_TUNE_STATUS, b[3]; | ||
| 27 | |||
| 28 | dvb_usb_generic_rw(state->d,&st,1,b,3,0); | ||
| 29 | |||
| 30 | switch (b[0]) { | ||
| 31 | case 0x01: | ||
| 32 | *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
| 33 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
| 34 | break; | ||
| 35 | case 0x00: /* pending */ | ||
| 36 | *stat = FE_TIMEDOUT; /* during set_frontend */ | ||
| 37 | break; | ||
| 38 | default: | ||
| 39 | case 0x02: /* failed */ | ||
| 40 | *stat = 0; | ||
| 41 | break; | ||
| 42 | } | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber) | ||
| 47 | { | ||
| 48 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
| 49 | u8 bw = GET_VIT_ERR_CNT,b[3]; | ||
| 50 | dvb_usb_generic_rw(state->d,&bw,1,b,3,0); | ||
| 51 | *ber = (b[0] << 16) | (b[1] << 8) | b[2]; | ||
| 52 | return 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | ||
| 56 | { | ||
| 57 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
| 58 | u8 bw = GET_RS_UNCOR_BLK_CNT,b[2]; | ||
| 59 | |||
| 60 | dvb_usb_generic_rw(state->d,&bw,1,b,2,0); | ||
| 61 | *unc = (b[0] << 8) | b[1]; | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) | ||
| 66 | { | ||
| 67 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
| 68 | u8 bw = GET_AGC, b; | ||
| 69 | dvb_usb_generic_rw(state->d,&bw,1,&b,1,0); | ||
| 70 | *strength = (b << 8) | b; | ||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
| 75 | { | ||
| 76 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
| 77 | u8 bw = GET_SNR,br; | ||
| 78 | dvb_usb_generic_rw(state->d,&bw,1,&br,1,0); | ||
| 79 | *snr = ~((br << 8) | br); | ||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | static int dtt200u_fe_init(struct dvb_frontend* fe) | ||
| 84 | { | ||
| 85 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
| 86 | u8 b = SET_INIT; | ||
| 87 | return dvb_usb_generic_write(state->d,&b,1); | ||
| 88 | } | ||
| 89 | |||
| 90 | static int dtt200u_fe_sleep(struct dvb_frontend* fe) | ||
| 91 | { | ||
| 92 | return dtt200u_fe_init(fe); | ||
| 93 | } | ||
| 94 | |||
| 95 | static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
| 96 | { | ||
| 97 | tune->min_delay_ms = 1500; | ||
| 98 | tune->step_size = 0; | ||
| 99 | tune->max_drift = 0; | ||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int dtt200u_fe_set_frontend(struct dvb_frontend* fe, | ||
| 104 | struct dvb_frontend_parameters *fep) | ||
| 105 | { | ||
| 106 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
| 107 | int i; | ||
| 108 | fe_status_t st; | ||
| 109 | u16 freq = fep->frequency / 250000; | ||
| 110 | u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 }; | ||
| 111 | |||
| 112 | switch (fep->u.ofdm.bandwidth) { | ||
| 113 | case BANDWIDTH_8_MHZ: bwbuf[1] = 8; break; | ||
| 114 | case BANDWIDTH_7_MHZ: bwbuf[1] = 7; break; | ||
| 115 | case BANDWIDTH_6_MHZ: bwbuf[1] = 6; break; | ||
| 116 | case BANDWIDTH_AUTO: return -EOPNOTSUPP; | ||
| 117 | default: | ||
| 118 | return -EINVAL; | ||
| 119 | } | ||
| 120 | |||
| 121 | dvb_usb_generic_write(state->d,bwbuf,2); | ||
| 122 | |||
| 123 | freqbuf[1] = freq & 0xff; | ||
| 124 | freqbuf[2] = (freq >> 8) & 0xff; | ||
| 125 | dvb_usb_generic_write(state->d,freqbuf,3); | ||
| 126 | |||
| 127 | for (i = 0; i < 30; i++) { | ||
| 128 | msleep(20); | ||
| 129 | dtt200u_fe_read_status(fe, &st); | ||
| 130 | if (st & FE_TIMEDOUT) | ||
| 131 | continue; | ||
| 132 | } | ||
| 133 | |||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | static int dtt200u_fe_get_frontend(struct dvb_frontend* fe, | ||
| 138 | struct dvb_frontend_parameters *fep) | ||
| 139 | { | ||
| 140 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
| 141 | memcpy(fep,&state->fep,sizeof(struct dvb_frontend_parameters)); | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static void dtt200u_fe_release(struct dvb_frontend* fe) | ||
| 146 | { | ||
| 147 | struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv; | ||
| 148 | kfree(state); | ||
| 149 | } | ||
| 150 | |||
| 151 | static struct dvb_frontend_ops dtt200u_fe_ops; | ||
| 152 | |||
| 153 | struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d) | ||
| 154 | { | ||
| 155 | struct dtt200u_fe_state* state = NULL; | ||
| 156 | |||
| 157 | /* allocate memory for the internal state */ | ||
| 158 | state = kzalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL); | ||
| 159 | if (state == NULL) | ||
| 160 | goto error; | ||
| 161 | |||
| 162 | deb_info("attaching frontend dtt200u\n"); | ||
| 163 | |||
| 164 | state->d = d; | ||
| 165 | |||
| 166 | memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops)); | ||
| 167 | state->frontend.demodulator_priv = state; | ||
| 168 | |||
| 169 | return &state->frontend; | ||
| 170 | error: | ||
| 171 | return NULL; | ||
| 172 | } | ||
| 173 | |||
| 174 | static struct dvb_frontend_ops dtt200u_fe_ops = { | ||
| 175 | .info = { | ||
| 176 | .name = "WideView USB DVB-T", | ||
| 177 | .type = FE_OFDM, | ||
| 178 | .frequency_min = 44250000, | ||
| 179 | .frequency_max = 867250000, | ||
| 180 | .frequency_stepsize = 250000, | ||
| 181 | .caps = FE_CAN_INVERSION_AUTO | | ||
| 182 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 183 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
| 184 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
| 185 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
| 186 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
| 187 | FE_CAN_RECOVER | | ||
| 188 | FE_CAN_HIERARCHY_AUTO, | ||
| 189 | }, | ||
| 190 | |||
| 191 | .release = dtt200u_fe_release, | ||
| 192 | |||
| 193 | .init = dtt200u_fe_init, | ||
| 194 | .sleep = dtt200u_fe_sleep, | ||
| 195 | |||
| 196 | .set_frontend = dtt200u_fe_set_frontend, | ||
| 197 | .get_frontend = dtt200u_fe_get_frontend, | ||
| 198 | .get_tune_settings = dtt200u_fe_get_tune_settings, | ||
| 199 | |||
| 200 | .read_status = dtt200u_fe_read_status, | ||
| 201 | .read_ber = dtt200u_fe_read_ber, | ||
| 202 | .read_signal_strength = dtt200u_fe_read_signal_strength, | ||
| 203 | .read_snr = dtt200u_fe_read_snr, | ||
| 204 | .read_ucblocks = dtt200u_fe_read_unc_blocks, | ||
| 205 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c new file mode 100644 index 00000000000..ecd86eca254 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtt200u.c | |||
| @@ -0,0 +1,375 @@ | |||
| 1 | /* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/ | ||
| 2 | * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 5 | * | ||
| 6 | * Thanks to Steve Chang from WideView for providing support for the WT-220U. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation, version 2. | ||
| 11 | * | ||
| 12 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 13 | */ | ||
| 14 | #include "dtt200u.h" | ||
| 15 | |||
| 16 | /* debug */ | ||
| 17 | int dvb_usb_dtt200u_debug; | ||
| 18 | module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644); | ||
| 19 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 20 | |||
| 21 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 22 | |||
| 23 | static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 24 | { | ||
| 25 | u8 b = SET_INIT; | ||
| 26 | |||
| 27 | if (onoff) | ||
| 28 | dvb_usb_generic_write(d,&b,2); | ||
| 29 | |||
| 30 | return 0; | ||
| 31 | } | ||
| 32 | |||
| 33 | static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 34 | { | ||
| 35 | u8 b_streaming[2] = { SET_STREAMING, onoff }; | ||
| 36 | u8 b_rst_pid = RESET_PID_FILTER; | ||
| 37 | |||
| 38 | dvb_usb_generic_write(adap->dev, b_streaming, 2); | ||
| 39 | |||
| 40 | if (onoff == 0) | ||
| 41 | dvb_usb_generic_write(adap->dev, &b_rst_pid, 1); | ||
| 42 | return 0; | ||
| 43 | } | ||
| 44 | |||
| 45 | static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) | ||
| 46 | { | ||
| 47 | u8 b_pid[4]; | ||
| 48 | pid = onoff ? pid : 0; | ||
| 49 | |||
| 50 | b_pid[0] = SET_PID_FILTER; | ||
| 51 | b_pid[1] = index; | ||
| 52 | b_pid[2] = pid & 0xff; | ||
| 53 | b_pid[3] = (pid >> 8) & 0x1f; | ||
| 54 | |||
| 55 | return dvb_usb_generic_write(adap->dev, b_pid, 4); | ||
| 56 | } | ||
| 57 | |||
| 58 | /* remote control */ | ||
| 59 | /* key list for the tiny remote control (Yakumo, don't know about the others) */ | ||
| 60 | static struct rc_map_table rc_map_dtt200u_table[] = { | ||
| 61 | { 0x8001, KEY_MUTE }, | ||
| 62 | { 0x8002, KEY_CHANNELDOWN }, | ||
| 63 | { 0x8003, KEY_VOLUMEDOWN }, | ||
| 64 | { 0x8004, KEY_1 }, | ||
| 65 | { 0x8005, KEY_2 }, | ||
| 66 | { 0x8006, KEY_3 }, | ||
| 67 | { 0x8007, KEY_4 }, | ||
| 68 | { 0x8008, KEY_5 }, | ||
| 69 | { 0x8009, KEY_6 }, | ||
| 70 | { 0x800a, KEY_7 }, | ||
| 71 | { 0x800c, KEY_ZOOM }, | ||
| 72 | { 0x800d, KEY_0 }, | ||
| 73 | { 0x800e, KEY_SELECT }, | ||
| 74 | { 0x8012, KEY_POWER }, | ||
| 75 | { 0x801a, KEY_CHANNELUP }, | ||
| 76 | { 0x801b, KEY_8 }, | ||
| 77 | { 0x801e, KEY_VOLUMEUP }, | ||
| 78 | { 0x801f, KEY_9 }, | ||
| 79 | }; | ||
| 80 | |||
| 81 | static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 82 | { | ||
| 83 | u8 key[5],cmd = GET_RC_CODE; | ||
| 84 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); | ||
| 85 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
| 86 | if (key[0] != 0) | ||
| 87 | deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 92 | { | ||
| 93 | adap->fe = dtt200u_fe_attach(adap->dev); | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | static struct dvb_usb_device_properties dtt200u_properties; | ||
| 98 | static struct dvb_usb_device_properties wt220u_fc_properties; | ||
| 99 | static struct dvb_usb_device_properties wt220u_properties; | ||
| 100 | static struct dvb_usb_device_properties wt220u_zl0353_properties; | ||
| 101 | static struct dvb_usb_device_properties wt220u_miglia_properties; | ||
| 102 | |||
| 103 | static int dtt200u_usb_probe(struct usb_interface *intf, | ||
| 104 | const struct usb_device_id *id) | ||
| 105 | { | ||
| 106 | if (0 == dvb_usb_device_init(intf, &dtt200u_properties, | ||
| 107 | THIS_MODULE, NULL, adapter_nr) || | ||
| 108 | 0 == dvb_usb_device_init(intf, &wt220u_properties, | ||
| 109 | THIS_MODULE, NULL, adapter_nr) || | ||
| 110 | 0 == dvb_usb_device_init(intf, &wt220u_fc_properties, | ||
| 111 | THIS_MODULE, NULL, adapter_nr) || | ||
| 112 | 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties, | ||
| 113 | THIS_MODULE, NULL, adapter_nr) || | ||
| 114 | 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties, | ||
| 115 | THIS_MODULE, NULL, adapter_nr)) | ||
| 116 | return 0; | ||
| 117 | |||
| 118 | return -ENODEV; | ||
| 119 | } | ||
| 120 | |||
| 121 | static struct usb_device_id dtt200u_usb_table [] = { | ||
| 122 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) }, | ||
| 123 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) }, | ||
| 124 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD) }, | ||
| 125 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM) }, | ||
| 126 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD) }, | ||
| 127 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM) }, | ||
| 128 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD) }, | ||
| 129 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM) }, | ||
| 130 | { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD) }, | ||
| 131 | { USB_DEVICE(USB_VID_MIGLIA, USB_PID_WT220U_ZAP250_COLD) }, | ||
| 132 | { 0 }, | ||
| 133 | }; | ||
| 134 | MODULE_DEVICE_TABLE(usb, dtt200u_usb_table); | ||
| 135 | |||
| 136 | static struct dvb_usb_device_properties dtt200u_properties = { | ||
| 137 | .usb_ctrl = CYPRESS_FX2, | ||
| 138 | .firmware = "dvb-usb-dtt200u-01.fw", | ||
| 139 | |||
| 140 | .num_adapters = 1, | ||
| 141 | .adapter = { | ||
| 142 | { | ||
| 143 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, | ||
| 144 | .pid_filter_count = 15, | ||
| 145 | |||
| 146 | .streaming_ctrl = dtt200u_streaming_ctrl, | ||
| 147 | .pid_filter = dtt200u_pid_filter, | ||
| 148 | .frontend_attach = dtt200u_frontend_attach, | ||
| 149 | /* parameter for the MPEG2-data transfer */ | ||
| 150 | .stream = { | ||
| 151 | .type = USB_BULK, | ||
| 152 | .count = 7, | ||
| 153 | .endpoint = 0x02, | ||
| 154 | .u = { | ||
| 155 | .bulk = { | ||
| 156 | .buffersize = 4096, | ||
| 157 | } | ||
| 158 | } | ||
| 159 | }, | ||
| 160 | } | ||
| 161 | }, | ||
| 162 | .power_ctrl = dtt200u_power_ctrl, | ||
| 163 | |||
| 164 | .rc.legacy = { | ||
| 165 | .rc_interval = 300, | ||
| 166 | .rc_map_table = rc_map_dtt200u_table, | ||
| 167 | .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), | ||
| 168 | .rc_query = dtt200u_rc_query, | ||
| 169 | }, | ||
| 170 | |||
| 171 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 172 | |||
| 173 | .num_device_descs = 1, | ||
| 174 | .devices = { | ||
| 175 | { .name = "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)", | ||
| 176 | .cold_ids = { &dtt200u_usb_table[0], NULL }, | ||
| 177 | .warm_ids = { &dtt200u_usb_table[1], NULL }, | ||
| 178 | }, | ||
| 179 | { NULL }, | ||
| 180 | } | ||
| 181 | }; | ||
| 182 | |||
| 183 | static struct dvb_usb_device_properties wt220u_properties = { | ||
| 184 | .usb_ctrl = CYPRESS_FX2, | ||
| 185 | .firmware = "dvb-usb-wt220u-02.fw", | ||
| 186 | |||
| 187 | .num_adapters = 1, | ||
| 188 | .adapter = { | ||
| 189 | { | ||
| 190 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, | ||
| 191 | .pid_filter_count = 15, | ||
| 192 | |||
| 193 | .streaming_ctrl = dtt200u_streaming_ctrl, | ||
| 194 | .pid_filter = dtt200u_pid_filter, | ||
| 195 | .frontend_attach = dtt200u_frontend_attach, | ||
| 196 | /* parameter for the MPEG2-data transfer */ | ||
| 197 | .stream = { | ||
| 198 | .type = USB_BULK, | ||
| 199 | .count = 7, | ||
| 200 | .endpoint = 0x02, | ||
| 201 | .u = { | ||
| 202 | .bulk = { | ||
| 203 | .buffersize = 4096, | ||
| 204 | } | ||
| 205 | } | ||
| 206 | }, | ||
| 207 | } | ||
| 208 | }, | ||
| 209 | .power_ctrl = dtt200u_power_ctrl, | ||
| 210 | |||
| 211 | .rc.legacy = { | ||
| 212 | .rc_interval = 300, | ||
| 213 | .rc_map_table = rc_map_dtt200u_table, | ||
| 214 | .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), | ||
| 215 | .rc_query = dtt200u_rc_query, | ||
| 216 | }, | ||
| 217 | |||
| 218 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 219 | |||
| 220 | .num_device_descs = 1, | ||
| 221 | .devices = { | ||
| 222 | { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)", | ||
| 223 | .cold_ids = { &dtt200u_usb_table[2], &dtt200u_usb_table[8], NULL }, | ||
| 224 | .warm_ids = { &dtt200u_usb_table[3], NULL }, | ||
| 225 | }, | ||
| 226 | { NULL }, | ||
| 227 | } | ||
| 228 | }; | ||
| 229 | |||
| 230 | static struct dvb_usb_device_properties wt220u_fc_properties = { | ||
| 231 | .usb_ctrl = CYPRESS_FX2, | ||
| 232 | .firmware = "dvb-usb-wt220u-fc03.fw", | ||
| 233 | |||
| 234 | .num_adapters = 1, | ||
| 235 | .adapter = { | ||
| 236 | { | ||
| 237 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, | ||
| 238 | .pid_filter_count = 15, | ||
| 239 | |||
| 240 | .streaming_ctrl = dtt200u_streaming_ctrl, | ||
| 241 | .pid_filter = dtt200u_pid_filter, | ||
| 242 | .frontend_attach = dtt200u_frontend_attach, | ||
| 243 | /* parameter for the MPEG2-data transfer */ | ||
| 244 | .stream = { | ||
| 245 | .type = USB_BULK, | ||
| 246 | .count = 7, | ||
| 247 | .endpoint = 0x06, | ||
| 248 | .u = { | ||
| 249 | .bulk = { | ||
| 250 | .buffersize = 4096, | ||
| 251 | } | ||
| 252 | } | ||
| 253 | }, | ||
| 254 | } | ||
| 255 | }, | ||
| 256 | .power_ctrl = dtt200u_power_ctrl, | ||
| 257 | |||
| 258 | .rc.legacy = { | ||
| 259 | .rc_interval = 300, | ||
| 260 | .rc_map_table = rc_map_dtt200u_table, | ||
| 261 | .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), | ||
| 262 | .rc_query = dtt200u_rc_query, | ||
| 263 | }, | ||
| 264 | |||
| 265 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 266 | |||
| 267 | .num_device_descs = 1, | ||
| 268 | .devices = { | ||
| 269 | { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)", | ||
| 270 | .cold_ids = { &dtt200u_usb_table[6], NULL }, | ||
| 271 | .warm_ids = { &dtt200u_usb_table[7], NULL }, | ||
| 272 | }, | ||
| 273 | { NULL }, | ||
| 274 | } | ||
| 275 | }; | ||
| 276 | |||
| 277 | static struct dvb_usb_device_properties wt220u_zl0353_properties = { | ||
| 278 | .usb_ctrl = CYPRESS_FX2, | ||
| 279 | .firmware = "dvb-usb-wt220u-zl0353-01.fw", | ||
| 280 | |||
| 281 | .num_adapters = 1, | ||
| 282 | .adapter = { | ||
| 283 | { | ||
| 284 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, | ||
| 285 | .pid_filter_count = 15, | ||
| 286 | |||
| 287 | .streaming_ctrl = dtt200u_streaming_ctrl, | ||
| 288 | .pid_filter = dtt200u_pid_filter, | ||
| 289 | .frontend_attach = dtt200u_frontend_attach, | ||
| 290 | /* parameter for the MPEG2-data transfer */ | ||
| 291 | .stream = { | ||
| 292 | .type = USB_BULK, | ||
| 293 | .count = 7, | ||
| 294 | .endpoint = 0x02, | ||
| 295 | .u = { | ||
| 296 | .bulk = { | ||
| 297 | .buffersize = 4096, | ||
| 298 | } | ||
| 299 | } | ||
| 300 | }, | ||
| 301 | } | ||
| 302 | }, | ||
| 303 | .power_ctrl = dtt200u_power_ctrl, | ||
| 304 | |||
| 305 | .rc.legacy = { | ||
| 306 | .rc_interval = 300, | ||
| 307 | .rc_map_table = rc_map_dtt200u_table, | ||
| 308 | .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), | ||
| 309 | .rc_query = dtt200u_rc_query, | ||
| 310 | }, | ||
| 311 | |||
| 312 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 313 | |||
| 314 | .num_device_descs = 1, | ||
| 315 | .devices = { | ||
| 316 | { .name = "WideView WT-220U PenType Receiver (based on ZL353)", | ||
| 317 | .cold_ids = { &dtt200u_usb_table[4], NULL }, | ||
| 318 | .warm_ids = { &dtt200u_usb_table[5], NULL }, | ||
| 319 | }, | ||
| 320 | { NULL }, | ||
| 321 | } | ||
| 322 | }; | ||
| 323 | |||
| 324 | static struct dvb_usb_device_properties wt220u_miglia_properties = { | ||
| 325 | .usb_ctrl = CYPRESS_FX2, | ||
| 326 | .firmware = "dvb-usb-wt220u-miglia-01.fw", | ||
| 327 | |||
| 328 | .num_adapters = 1, | ||
| 329 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 330 | |||
| 331 | .num_device_descs = 1, | ||
| 332 | .devices = { | ||
| 333 | { .name = "WideView WT-220U PenType Receiver (Miglia)", | ||
| 334 | .cold_ids = { &dtt200u_usb_table[9], NULL }, | ||
| 335 | /* This device turns into WT220U_ZL0353_WARM when fw | ||
| 336 | has been uploaded */ | ||
| 337 | .warm_ids = { NULL }, | ||
| 338 | }, | ||
| 339 | { NULL }, | ||
| 340 | } | ||
| 341 | }; | ||
| 342 | |||
| 343 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 344 | static struct usb_driver dtt200u_usb_driver = { | ||
| 345 | .name = "dvb_usb_dtt200u", | ||
| 346 | .probe = dtt200u_usb_probe, | ||
| 347 | .disconnect = dvb_usb_device_exit, | ||
| 348 | .id_table = dtt200u_usb_table, | ||
| 349 | }; | ||
| 350 | |||
| 351 | /* module stuff */ | ||
| 352 | static int __init dtt200u_usb_module_init(void) | ||
| 353 | { | ||
| 354 | int result; | ||
| 355 | if ((result = usb_register(&dtt200u_usb_driver))) { | ||
| 356 | err("usb_register failed. (%d)",result); | ||
| 357 | return result; | ||
| 358 | } | ||
| 359 | |||
| 360 | return 0; | ||
| 361 | } | ||
| 362 | |||
| 363 | static void __exit dtt200u_usb_module_exit(void) | ||
| 364 | { | ||
| 365 | /* deregister this driver from the USB subsystem */ | ||
| 366 | usb_deregister(&dtt200u_usb_driver); | ||
| 367 | } | ||
| 368 | |||
| 369 | module_init(dtt200u_usb_module_init); | ||
| 370 | module_exit(dtt200u_usb_module_exit); | ||
| 371 | |||
| 372 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 373 | MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices"); | ||
| 374 | MODULE_VERSION("1.0"); | ||
| 375 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h new file mode 100644 index 00000000000..005b0a7df35 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtt200u.h | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | /* Common header file of Linux driver for the WideView/ Yakumo/ Hama/ | ||
| 2 | * Typhoon/ Yuan DVB-T USB2.0 receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the Free | ||
| 8 | * Software Foundation, version 2. | ||
| 9 | * | ||
| 10 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 11 | */ | ||
| 12 | #ifndef _DVB_USB_DTT200U_H_ | ||
| 13 | #define _DVB_USB_DTT200U_H_ | ||
| 14 | |||
| 15 | #define DVB_USB_LOG_PREFIX "dtt200u" | ||
| 16 | |||
| 17 | #include "dvb-usb.h" | ||
| 18 | |||
| 19 | extern int dvb_usb_dtt200u_debug; | ||
| 20 | #define deb_info(args...) dprintk(dvb_usb_dtt200u_debug,0x01,args) | ||
| 21 | #define deb_xfer(args...) dprintk(dvb_usb_dtt200u_debug,0x02,args) | ||
| 22 | |||
| 23 | /* guessed protocol description (reverse engineered): | ||
| 24 | * read | ||
| 25 | * 00 - USB type 0x02 for usb2.0, 0x01 for usb1.1 | ||
| 26 | * 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal) | ||
| 27 | */ | ||
| 28 | |||
| 29 | #define GET_SPEED 0x00 | ||
| 30 | #define GET_TUNE_STATUS 0x81 | ||
| 31 | #define GET_RC_CODE 0x84 | ||
| 32 | #define GET_CONFIGURATION 0x88 | ||
| 33 | #define GET_AGC 0x89 | ||
| 34 | #define GET_SNR 0x8a | ||
| 35 | #define GET_VIT_ERR_CNT 0x8c | ||
| 36 | #define GET_RS_ERR_CNT 0x8d | ||
| 37 | #define GET_RS_UNCOR_BLK_CNT 0x8e | ||
| 38 | |||
| 39 | /* write | ||
| 40 | * 01 - init | ||
| 41 | * 02 - frequency (divided by 250000) | ||
| 42 | * 03 - bandwidth | ||
| 43 | * 04 - pid table (index pid(7:0) pid(12:8)) | ||
| 44 | * 05 - reset the pid table | ||
| 45 | * 08 - transfer switch | ||
| 46 | */ | ||
| 47 | |||
| 48 | #define SET_INIT 0x01 | ||
| 49 | #define SET_RF_FREQ 0x02 | ||
| 50 | #define SET_BANDWIDTH 0x03 | ||
| 51 | #define SET_PID_FILTER 0x04 | ||
| 52 | #define RESET_PID_FILTER 0x05 | ||
| 53 | #define SET_STREAMING 0x08 | ||
| 54 | |||
| 55 | extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d); | ||
| 56 | |||
| 57 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c new file mode 100644 index 00000000000..078ce92ca43 --- /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 00000000000..93e96e04a82 --- /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-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h new file mode 100644 index 00000000000..6b7b2a89242 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | /* dvb-usb-common.h is part of the DVB USB library. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 4 | * see dvb-usb-init.c for copyright information. | ||
| 5 | * | ||
| 6 | * a header file containing prototypes and types for internal use of the dvb-usb-lib | ||
| 7 | */ | ||
| 8 | #ifndef _DVB_USB_COMMON_H_ | ||
| 9 | #define _DVB_USB_COMMON_H_ | ||
| 10 | |||
| 11 | #define DVB_USB_LOG_PREFIX "dvb-usb" | ||
| 12 | #include "dvb-usb.h" | ||
| 13 | |||
| 14 | extern int dvb_usb_debug; | ||
| 15 | extern int dvb_usb_disable_rc_polling; | ||
| 16 | |||
| 17 | #define deb_info(args...) dprintk(dvb_usb_debug,0x001,args) | ||
| 18 | #define deb_xfer(args...) dprintk(dvb_usb_debug,0x002,args) | ||
| 19 | #define deb_pll(args...) dprintk(dvb_usb_debug,0x004,args) | ||
| 20 | #define deb_ts(args...) dprintk(dvb_usb_debug,0x008,args) | ||
| 21 | #define deb_err(args...) dprintk(dvb_usb_debug,0x010,args) | ||
| 22 | #define deb_rc(args...) dprintk(dvb_usb_debug,0x020,args) | ||
| 23 | #define deb_fw(args...) dprintk(dvb_usb_debug,0x040,args) | ||
| 24 | #define deb_mem(args...) dprintk(dvb_usb_debug,0x080,args) | ||
| 25 | #define deb_uxfer(args...) dprintk(dvb_usb_debug,0x100,args) | ||
| 26 | |||
| 27 | /* commonly used methods */ | ||
| 28 | extern int dvb_usb_download_firmware(struct usb_device *, struct dvb_usb_device_properties *); | ||
| 29 | |||
| 30 | extern int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff); | ||
| 31 | |||
| 32 | extern int usb_urb_init(struct usb_data_stream *stream, struct usb_data_stream_properties *props); | ||
| 33 | extern int usb_urb_exit(struct usb_data_stream *stream); | ||
| 34 | extern int usb_urb_submit(struct usb_data_stream *stream); | ||
| 35 | extern int usb_urb_kill(struct usb_data_stream *stream); | ||
| 36 | |||
| 37 | extern int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap); | ||
| 38 | extern int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap); | ||
| 39 | |||
| 40 | extern int dvb_usb_i2c_init(struct dvb_usb_device *); | ||
| 41 | extern int dvb_usb_i2c_exit(struct dvb_usb_device *); | ||
| 42 | |||
| 43 | extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, | ||
| 44 | short *adapter_nums); | ||
| 45 | extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap); | ||
| 46 | extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap); | ||
| 47 | extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap); | ||
| 48 | |||
| 49 | extern int dvb_usb_remote_init(struct dvb_usb_device *); | ||
| 50 | extern int dvb_usb_remote_exit(struct dvb_usb_device *); | ||
| 51 | |||
| 52 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c new file mode 100644 index 00000000000..b3cb626ed56 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c | |||
| @@ -0,0 +1,216 @@ | |||
| 1 | /* dvb-usb-dvb.c is part of the DVB USB library. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 4 | * see dvb-usb-init.c for copyright information. | ||
| 5 | * | ||
| 6 | * This file contains functions for initializing and handling the | ||
| 7 | * linux-dvb API. | ||
| 8 | */ | ||
| 9 | #include "dvb-usb-common.h" | ||
| 10 | |||
| 11 | /* does the complete input transfer handling */ | ||
| 12 | static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) | ||
| 13 | { | ||
| 14 | struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; | ||
| 15 | int newfeedcount, ret; | ||
| 16 | |||
| 17 | if (adap == NULL) | ||
| 18 | return -ENODEV; | ||
| 19 | |||
| 20 | newfeedcount = adap->feedcount + (onoff ? 1 : -1); | ||
| 21 | |||
| 22 | /* stop feed before setting a new pid if there will be no pid anymore */ | ||
| 23 | if (newfeedcount == 0) { | ||
| 24 | deb_ts("stop feeding\n"); | ||
| 25 | usb_urb_kill(&adap->stream); | ||
| 26 | |||
| 27 | if (adap->props.streaming_ctrl != NULL) { | ||
| 28 | ret = adap->props.streaming_ctrl(adap, 0); | ||
| 29 | if (ret < 0) { | ||
| 30 | err("error while stopping stream."); | ||
| 31 | return ret; | ||
| 32 | } | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | adap->feedcount = newfeedcount; | ||
| 37 | |||
| 38 | /* activate the pid on the device specific pid_filter */ | ||
| 39 | deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",adap->pid_filtering ? | ||
| 40 | "yes" : "no", dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? | ||
| 41 | "on" : "off"); | ||
| 42 | if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER && | ||
| 43 | adap->pid_filtering && | ||
| 44 | adap->props.pid_filter != NULL) | ||
| 45 | adap->props.pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid,onoff); | ||
| 46 | |||
| 47 | /* start the feed if this was the first feed and there is still a feed | ||
| 48 | * for reception. | ||
| 49 | */ | ||
| 50 | if (adap->feedcount == onoff && adap->feedcount > 0) { | ||
| 51 | deb_ts("submitting all URBs\n"); | ||
| 52 | usb_urb_submit(&adap->stream); | ||
| 53 | |||
| 54 | deb_ts("controlling pid parser\n"); | ||
| 55 | if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER && | ||
| 56 | adap->props.caps & | ||
| 57 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF && | ||
| 58 | adap->props.pid_filter_ctrl != NULL) { | ||
| 59 | ret = adap->props.pid_filter_ctrl(adap, | ||
| 60 | adap->pid_filtering); | ||
| 61 | if (ret < 0) { | ||
| 62 | err("could not handle pid_parser"); | ||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | deb_ts("start feeding\n"); | ||
| 67 | if (adap->props.streaming_ctrl != NULL) { | ||
| 68 | ret = adap->props.streaming_ctrl(adap, 1); | ||
| 69 | if (ret < 0) { | ||
| 70 | err("error while enabling fifo."); | ||
| 71 | return ret; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | } | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
| 80 | { | ||
| 81 | deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type); | ||
| 82 | return dvb_usb_ctrl_feed(dvbdmxfeed,1); | ||
| 83 | } | ||
| 84 | |||
| 85 | static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
| 86 | { | ||
| 87 | deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type); | ||
| 88 | return dvb_usb_ctrl_feed(dvbdmxfeed,0); | ||
| 89 | } | ||
| 90 | |||
| 91 | int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums) | ||
| 92 | { | ||
| 93 | int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name, | ||
| 94 | adap->dev->owner, &adap->dev->udev->dev, | ||
| 95 | adapter_nums); | ||
| 96 | |||
| 97 | if (ret < 0) { | ||
| 98 | deb_info("dvb_register_adapter failed: error %d", ret); | ||
| 99 | goto err; | ||
| 100 | } | ||
| 101 | adap->dvb_adap.priv = adap; | ||
| 102 | adap->dvb_adap.fe_ioctl_override = adap->props.fe_ioctl_override; | ||
| 103 | |||
| 104 | if (adap->dev->props.read_mac_address) { | ||
| 105 | if (adap->dev->props.read_mac_address(adap->dev,adap->dvb_adap.proposed_mac) == 0) | ||
| 106 | info("MAC address: %pM",adap->dvb_adap.proposed_mac); | ||
| 107 | else | ||
| 108 | err("MAC address reading failed."); | ||
| 109 | } | ||
| 110 | |||
| 111 | |||
| 112 | adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | ||
| 113 | adap->demux.priv = adap; | ||
| 114 | |||
| 115 | adap->demux.feednum = adap->demux.filternum = adap->max_feed_count; | ||
| 116 | adap->demux.start_feed = dvb_usb_start_feed; | ||
| 117 | adap->demux.stop_feed = dvb_usb_stop_feed; | ||
| 118 | adap->demux.write_to_decoder = NULL; | ||
| 119 | if ((ret = dvb_dmx_init(&adap->demux)) < 0) { | ||
| 120 | err("dvb_dmx_init failed: error %d",ret); | ||
| 121 | goto err_dmx; | ||
| 122 | } | ||
| 123 | |||
| 124 | adap->dmxdev.filternum = adap->demux.filternum; | ||
| 125 | adap->dmxdev.demux = &adap->demux.dmx; | ||
| 126 | adap->dmxdev.capabilities = 0; | ||
| 127 | if ((ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap)) < 0) { | ||
| 128 | err("dvb_dmxdev_init failed: error %d",ret); | ||
| 129 | goto err_dmx_dev; | ||
| 130 | } | ||
| 131 | |||
| 132 | dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx); | ||
| 133 | |||
| 134 | adap->state |= DVB_USB_ADAP_STATE_DVB; | ||
| 135 | return 0; | ||
| 136 | |||
| 137 | err_dmx_dev: | ||
| 138 | dvb_dmx_release(&adap->demux); | ||
| 139 | err_dmx: | ||
| 140 | dvb_unregister_adapter(&adap->dvb_adap); | ||
| 141 | err: | ||
| 142 | return ret; | ||
| 143 | } | ||
| 144 | |||
| 145 | int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap) | ||
| 146 | { | ||
| 147 | if (adap->state & DVB_USB_ADAP_STATE_DVB) { | ||
| 148 | deb_info("unregistering DVB part\n"); | ||
| 149 | dvb_net_release(&adap->dvb_net); | ||
| 150 | adap->demux.dmx.close(&adap->demux.dmx); | ||
| 151 | dvb_dmxdev_release(&adap->dmxdev); | ||
| 152 | dvb_dmx_release(&adap->demux); | ||
| 153 | dvb_unregister_adapter(&adap->dvb_adap); | ||
| 154 | adap->state &= ~DVB_USB_ADAP_STATE_DVB; | ||
| 155 | } | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | static int dvb_usb_fe_wakeup(struct dvb_frontend *fe) | ||
| 160 | { | ||
| 161 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 162 | |||
| 163 | dvb_usb_device_power_ctrl(adap->dev, 1); | ||
| 164 | |||
| 165 | if (adap->fe_init) | ||
| 166 | adap->fe_init(fe); | ||
| 167 | |||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | static int dvb_usb_fe_sleep(struct dvb_frontend *fe) | ||
| 172 | { | ||
| 173 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 174 | |||
| 175 | if (adap->fe_sleep) | ||
| 176 | adap->fe_sleep(fe); | ||
| 177 | |||
| 178 | return dvb_usb_device_power_ctrl(adap->dev, 0); | ||
| 179 | } | ||
| 180 | |||
| 181 | int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap) | ||
| 182 | { | ||
| 183 | if (adap->props.frontend_attach == NULL) { | ||
| 184 | err("strange: '%s' #%d doesn't want to attach a frontend.",adap->dev->desc->name, adap->id); | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | /* re-assign sleep and wakeup functions */ | ||
| 189 | if (adap->props.frontend_attach(adap) == 0 && adap->fe != NULL) { | ||
| 190 | adap->fe_init = adap->fe->ops.init; adap->fe->ops.init = dvb_usb_fe_wakeup; | ||
| 191 | adap->fe_sleep = adap->fe->ops.sleep; adap->fe->ops.sleep = dvb_usb_fe_sleep; | ||
| 192 | |||
| 193 | if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) { | ||
| 194 | err("Frontend registration failed."); | ||
| 195 | dvb_frontend_detach(adap->fe); | ||
| 196 | adap->fe = NULL; | ||
| 197 | return -ENODEV; | ||
| 198 | } | ||
| 199 | |||
| 200 | /* only attach the tuner if the demod is there */ | ||
| 201 | if (adap->props.tuner_attach != NULL) | ||
| 202 | adap->props.tuner_attach(adap); | ||
| 203 | } else | ||
| 204 | err("no frontend was attached by '%s'",adap->dev->desc->name); | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap) | ||
| 210 | { | ||
| 211 | if (adap->fe != NULL) { | ||
| 212 | dvb_unregister_frontend(adap->fe); | ||
| 213 | dvb_frontend_detach(adap->fe); | ||
| 214 | } | ||
| 215 | return 0; | ||
| 216 | } | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c new file mode 100644 index 00000000000..733a7ff7b20 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | /* dvb-usb-firmware.c is part of the DVB USB library. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 4 | * see dvb-usb-init.c for copyright information. | ||
| 5 | * | ||
| 6 | * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices. | ||
| 7 | * | ||
| 8 | * FIXME: This part does actually not belong to dvb-usb, but to the usb-subsystem. | ||
| 9 | */ | ||
| 10 | #include "dvb-usb-common.h" | ||
| 11 | |||
| 12 | #include <linux/usb.h> | ||
| 13 | |||
| 14 | struct usb_cypress_controller { | ||
| 15 | int id; | ||
| 16 | const char *name; /* name of the usb controller */ | ||
| 17 | u16 cpu_cs_register; /* needs to be restarted, when the firmware has been downloaded. */ | ||
| 18 | }; | ||
| 19 | |||
| 20 | static struct usb_cypress_controller cypress[] = { | ||
| 21 | { .id = DEVICE_SPECIFIC, .name = "Device specific", .cpu_cs_register = 0 }, | ||
| 22 | { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 }, | ||
| 23 | { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 }, | ||
| 24 | { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, | ||
| 25 | }; | ||
| 26 | |||
| 27 | /* | ||
| 28 | * load a firmware packet to the device | ||
| 29 | */ | ||
| 30 | static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len) | ||
| 31 | { | ||
| 32 | return usb_control_msg(udev, usb_sndctrlpipe(udev,0), | ||
| 33 | 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000); | ||
| 34 | } | ||
| 35 | |||
| 36 | int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type) | ||
| 37 | { | ||
| 38 | struct hexline hx; | ||
| 39 | u8 reset; | ||
| 40 | int ret,pos=0; | ||
| 41 | |||
| 42 | /* stop the CPU */ | ||
| 43 | reset = 1; | ||
| 44 | if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1) | ||
| 45 | err("could not stop the USB controller CPU."); | ||
| 46 | |||
| 47 | while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) { | ||
| 48 | deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk); | ||
| 49 | ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len); | ||
| 50 | |||
| 51 | if (ret != hx.len) { | ||
| 52 | err("error while transferring firmware " | ||
| 53 | "(transferred size: %d, block size: %d)", | ||
| 54 | ret,hx.len); | ||
| 55 | ret = -EINVAL; | ||
| 56 | break; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | if (ret < 0) { | ||
| 60 | err("firmware download failed at %d with %d",pos,ret); | ||
| 61 | return ret; | ||
| 62 | } | ||
| 63 | |||
| 64 | if (ret == 0) { | ||
| 65 | /* restart the CPU */ | ||
| 66 | reset = 0; | ||
| 67 | if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) { | ||
| 68 | err("could not restart the USB controller CPU."); | ||
| 69 | ret = -EINVAL; | ||
| 70 | } | ||
| 71 | } else | ||
| 72 | ret = -EIO; | ||
| 73 | |||
| 74 | return ret; | ||
| 75 | } | ||
| 76 | EXPORT_SYMBOL(usb_cypress_load_firmware); | ||
| 77 | |||
| 78 | int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_device_properties *props) | ||
| 79 | { | ||
| 80 | int ret; | ||
| 81 | const struct firmware *fw = NULL; | ||
| 82 | |||
| 83 | if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) { | ||
| 84 | err("did not find the firmware file. (%s) " | ||
| 85 | "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)", | ||
| 86 | props->firmware,ret); | ||
| 87 | return ret; | ||
| 88 | } | ||
| 89 | |||
| 90 | info("downloading firmware from file '%s'",props->firmware); | ||
| 91 | |||
| 92 | switch (props->usb_ctrl) { | ||
| 93 | case CYPRESS_AN2135: | ||
| 94 | case CYPRESS_AN2235: | ||
| 95 | case CYPRESS_FX2: | ||
| 96 | ret = usb_cypress_load_firmware(udev, fw, props->usb_ctrl); | ||
| 97 | break; | ||
| 98 | case DEVICE_SPECIFIC: | ||
| 99 | if (props->download_firmware) | ||
| 100 | ret = props->download_firmware(udev,fw); | ||
| 101 | else { | ||
| 102 | err("BUG: driver didn't specified a download_firmware-callback, although it claims to have a DEVICE_SPECIFIC one."); | ||
| 103 | ret = -EINVAL; | ||
| 104 | } | ||
| 105 | break; | ||
| 106 | default: | ||
| 107 | ret = -EINVAL; | ||
| 108 | break; | ||
| 109 | } | ||
| 110 | |||
| 111 | release_firmware(fw); | ||
| 112 | return ret; | ||
| 113 | } | ||
| 114 | |||
| 115 | int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, | ||
| 116 | int *pos) | ||
| 117 | { | ||
| 118 | u8 *b = (u8 *) &fw->data[*pos]; | ||
| 119 | int data_offs = 4; | ||
| 120 | if (*pos >= fw->size) | ||
| 121 | return 0; | ||
| 122 | |||
| 123 | memset(hx,0,sizeof(struct hexline)); | ||
| 124 | |||
| 125 | hx->len = b[0]; | ||
| 126 | |||
| 127 | if ((*pos + hx->len + 4) >= fw->size) | ||
| 128 | return -EINVAL; | ||
| 129 | |||
| 130 | hx->addr = b[1] | (b[2] << 8); | ||
| 131 | hx->type = b[3]; | ||
| 132 | |||
| 133 | if (hx->type == 0x04) { | ||
| 134 | /* b[4] and b[5] are the Extended linear address record data field */ | ||
| 135 | hx->addr |= (b[4] << 24) | (b[5] << 16); | ||
| 136 | /* hx->len -= 2; | ||
| 137 | data_offs += 2; */ | ||
| 138 | } | ||
| 139 | memcpy(hx->data,&b[data_offs],hx->len); | ||
| 140 | hx->chk = b[hx->len + data_offs]; | ||
| 141 | |||
| 142 | *pos += hx->len + 5; | ||
| 143 | |||
| 144 | return *pos; | ||
| 145 | } | ||
| 146 | EXPORT_SYMBOL(dvb_usb_get_hexline); | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c new file mode 100644 index 00000000000..88e4a62abc4 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* dvb-usb-i2c.c is part of the DVB USB library. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 4 | * see dvb-usb-init.c for copyright information. | ||
| 5 | * | ||
| 6 | * This file contains functions for (de-)initializing an I2C adapter. | ||
| 7 | */ | ||
| 8 | #include "dvb-usb-common.h" | ||
| 9 | |||
| 10 | int dvb_usb_i2c_init(struct dvb_usb_device *d) | ||
| 11 | { | ||
| 12 | int ret = 0; | ||
| 13 | |||
| 14 | if (!(d->props.caps & DVB_USB_IS_AN_I2C_ADAPTER)) | ||
| 15 | return 0; | ||
| 16 | |||
| 17 | if (d->props.i2c_algo == NULL) { | ||
| 18 | err("no i2c algorithm specified"); | ||
| 19 | return -EINVAL; | ||
| 20 | } | ||
| 21 | |||
| 22 | strlcpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); | ||
| 23 | d->i2c_adap.algo = d->props.i2c_algo; | ||
| 24 | d->i2c_adap.algo_data = NULL; | ||
| 25 | d->i2c_adap.dev.parent = &d->udev->dev; | ||
| 26 | |||
| 27 | i2c_set_adapdata(&d->i2c_adap, d); | ||
| 28 | |||
| 29 | if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0) | ||
| 30 | err("could not add i2c adapter"); | ||
| 31 | |||
| 32 | d->state |= DVB_USB_STATE_I2C; | ||
| 33 | |||
| 34 | return ret; | ||
| 35 | } | ||
| 36 | |||
| 37 | int dvb_usb_i2c_exit(struct dvb_usb_device *d) | ||
| 38 | { | ||
| 39 | if (d->state & DVB_USB_STATE_I2C) | ||
| 40 | i2c_del_adapter(&d->i2c_adap); | ||
| 41 | d->state &= ~DVB_USB_STATE_I2C; | ||
| 42 | return 0; | ||
| 43 | } | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h new file mode 100644 index 00000000000..2a79b8fb3e8 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
| @@ -0,0 +1,326 @@ | |||
| 1 | /* dvb-usb-ids.h is part of the DVB USB library. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see | ||
| 4 | * dvb-usb-init.c for copyright information. | ||
| 5 | * | ||
| 6 | * a header file containing define's for the USB device supported by the | ||
| 7 | * various drivers. | ||
| 8 | */ | ||
| 9 | #ifndef _DVB_USB_IDS_H_ | ||
| 10 | #define _DVB_USB_IDS_H_ | ||
| 11 | |||
| 12 | /* Vendor IDs */ | ||
| 13 | #define USB_VID_ADSTECH 0x06e1 | ||
| 14 | #define USB_VID_AFATECH 0x15a4 | ||
| 15 | #define USB_VID_ALCOR_MICRO 0x058f | ||
| 16 | #define USB_VID_ALINK 0x05e3 | ||
| 17 | #define USB_VID_AMT 0x1c73 | ||
| 18 | #define USB_VID_ANCHOR 0x0547 | ||
| 19 | #define USB_VID_ANSONIC 0x10b9 | ||
| 20 | #define USB_VID_ANUBIS_ELECTRONIC 0x10fd | ||
| 21 | #define USB_VID_ASUS 0x0b05 | ||
| 22 | #define USB_VID_AVERMEDIA 0x07ca | ||
| 23 | #define USB_VID_COMPRO 0x185b | ||
| 24 | #define USB_VID_COMPRO_UNK 0x145f | ||
| 25 | #define USB_VID_CONEXANT 0x0572 | ||
| 26 | #define USB_VID_CYPRESS 0x04b4 | ||
| 27 | #define USB_VID_DIBCOM 0x10b8 | ||
| 28 | #define USB_VID_DPOSH 0x1498 | ||
| 29 | #define USB_VID_DVICO 0x0fe9 | ||
| 30 | #define USB_VID_E3C 0x18b4 | ||
| 31 | #define USB_VID_ELGATO 0x0fd9 | ||
| 32 | #define USB_VID_EMPIA 0xeb1a | ||
| 33 | #define USB_VID_GENPIX 0x09c0 | ||
| 34 | #define USB_VID_GRANDTEC 0x5032 | ||
| 35 | #define USB_VID_GTEK 0x1f4d | ||
| 36 | #define USB_VID_HANFTEK 0x15f4 | ||
| 37 | #define USB_VID_HAUPPAUGE 0x2040 | ||
| 38 | #define USB_VID_HYPER_PALTEK 0x1025 | ||
| 39 | #define USB_VID_INTEL 0x8086 | ||
| 40 | #define USB_VID_KWORLD 0xeb2a | ||
| 41 | #define USB_VID_KWORLD_2 0x1b80 | ||
| 42 | #define USB_VID_KYE 0x0458 | ||
| 43 | #define USB_VID_LEADTEK 0x0413 | ||
| 44 | #define USB_VID_LITEON 0x04ca | ||
| 45 | #define USB_VID_MEDION 0x1660 | ||
| 46 | #define USB_VID_MIGLIA 0x18f3 | ||
| 47 | #define USB_VID_MSI 0x0db0 | ||
| 48 | #define USB_VID_MSI_2 0x1462 | ||
| 49 | #define USB_VID_OPERA1 0x695c | ||
| 50 | #define USB_VID_PINNACLE 0x2304 | ||
| 51 | #define USB_VID_PCTV 0x2013 | ||
| 52 | #define USB_VID_PIXELVIEW 0x1554 | ||
| 53 | #define USB_VID_TECHNOTREND 0x0b48 | ||
| 54 | #define USB_VID_TERRATEC 0x0ccd | ||
| 55 | #define USB_VID_TELESTAR 0x10b9 | ||
| 56 | #define USB_VID_VISIONPLUS 0x13d3 | ||
| 57 | #define USB_VID_SONY 0x1415 | ||
| 58 | #define USB_VID_TWINHAN 0x1822 | ||
| 59 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 | ||
| 60 | #define USB_VID_UNIWILL 0x1584 | ||
| 61 | #define USB_VID_WIDEVIEW 0x14aa | ||
| 62 | #define USB_VID_GIGABYTE 0x1044 | ||
| 63 | #define USB_VID_YUAN 0x1164 | ||
| 64 | #define USB_VID_XTENSIONS 0x1ae7 | ||
| 65 | #define USB_VID_HUMAX_COEX 0x10b9 | ||
| 66 | #define USB_VID_774 0x7a69 | ||
| 67 | #define USB_VID_EVOLUTEPC 0x1e59 | ||
| 68 | #define USB_VID_AZUREWAVE 0x13d3 | ||
| 69 | #define USB_VID_TECHNISAT 0x14f7 | ||
| 70 | |||
| 71 | /* Product IDs */ | ||
| 72 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 | ||
| 73 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 | ||
| 74 | #define USB_PID_AFATECH_AF9005 0x9020 | ||
| 75 | #define USB_PID_AFATECH_AF9015_9015 0x9015 | ||
| 76 | #define USB_PID_AFATECH_AF9015_9016 0x9016 | ||
| 77 | #define USB_PID_TREKSTOR_DVBT 0x901b | ||
| 78 | #define USB_VID_ALINK_DTU 0xf170 | ||
| 79 | #define USB_PID_ANSONIC_DVBT_USB 0x6000 | ||
| 80 | #define USB_PID_ANYSEE 0x861f | ||
| 81 | #define USB_PID_AZUREWAVE_AD_TU700 0x3237 | ||
| 82 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 | ||
| 83 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 | ||
| 84 | #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 | ||
| 85 | #define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801 | ||
| 86 | #define USB_PID_COMPRO_DVBU2000_COLD 0xd000 | ||
| 87 | #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 | ||
| 88 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c | ||
| 89 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | ||
| 90 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 | ||
| 91 | #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 | ||
| 92 | #define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397 | ||
| 93 | #define USB_PID_CONEXANT_D680_DMB 0x86d6 | ||
| 94 | #define USB_PID_CREATIX_CTX1921 0x1921 | ||
| 95 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 | ||
| 96 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 | ||
| 97 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | ||
| 98 | #define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9 | ||
| 99 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 | ||
| 100 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 | ||
| 101 | #define USB_PID_DIBCOM_STK7700P 0x1e14 | ||
| 102 | #define USB_PID_DIBCOM_STK7700P_PC 0x1e78 | ||
| 103 | #define USB_PID_DIBCOM_STK7700D 0x1ef0 | ||
| 104 | #define USB_PID_DIBCOM_STK7700_U7000 0x7001 | ||
| 105 | #define USB_PID_DIBCOM_STK7070P 0x1ebc | ||
| 106 | #define USB_PID_DIBCOM_STK7070PD 0x1ebe | ||
| 107 | #define USB_PID_DIBCOM_STK807XP 0x1f90 | ||
| 108 | #define USB_PID_DIBCOM_STK807XPVR 0x1f98 | ||
| 109 | #define USB_PID_DIBCOM_STK8096GP 0x1fa0 | ||
| 110 | #define USB_PID_DIBCOM_NIM8096MD 0x1fa8 | ||
| 111 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | ||
| 112 | #define USB_PID_DIBCOM_STK7770P 0x1e80 | ||
| 113 | #define USB_PID_DIBCOM_NIM7090 0x1bb2 | ||
| 114 | #define USB_PID_DIBCOM_TFE7090PVR 0x1bb4 | ||
| 115 | #define USB_PID_DIBCOM_NIM9090M 0x2383 | ||
| 116 | #define USB_PID_DIBCOM_NIM9090MD 0x2384 | ||
| 117 | #define USB_PID_DPOSH_M9206_COLD 0x9206 | ||
| 118 | #define USB_PID_DPOSH_M9206_WARM 0xa090 | ||
| 119 | #define USB_PID_E3C_EC168 0x1689 | ||
| 120 | #define USB_PID_E3C_EC168_2 0xfffa | ||
| 121 | #define USB_PID_E3C_EC168_3 0xfffb | ||
| 122 | #define USB_PID_E3C_EC168_4 0x1001 | ||
| 123 | #define USB_PID_E3C_EC168_5 0x1002 | ||
| 124 | #define USB_PID_UNIWILL_STK7700P 0x6003 | ||
| 125 | #define USB_PID_GENIUS_TVGO_DVB_T03 0x4012 | ||
| 126 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | ||
| 127 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 | ||
| 128 | #define USB_PID_INTEL_CE9500 0x9500 | ||
| 129 | #define USB_PID_KWORLD_399U 0xe399 | ||
| 130 | #define USB_PID_KWORLD_399U_2 0xe400 | ||
| 131 | #define USB_PID_KWORLD_395U 0xe396 | ||
| 132 | #define USB_PID_KWORLD_395U_2 0xe39b | ||
| 133 | #define USB_PID_KWORLD_395U_3 0xe395 | ||
| 134 | #define USB_PID_KWORLD_395U_4 0xe39a | ||
| 135 | #define USB_PID_KWORLD_MC810 0xc810 | ||
| 136 | #define USB_PID_KWORLD_PC160_2T 0xc160 | ||
| 137 | #define USB_PID_KWORLD_PC160_T 0xc161 | ||
| 138 | #define USB_PID_KWORLD_UB383_T 0xe383 | ||
| 139 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | ||
| 140 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df | ||
| 141 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 | ||
| 142 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069 | ||
| 143 | #define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097 | ||
| 144 | #define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099 | ||
| 145 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 | ||
| 146 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 | ||
| 147 | #define USB_PID_TWINHAN_VP7020_COLD 0x3203 | ||
| 148 | #define USB_PID_TWINHAN_VP7020_WARM 0x3204 | ||
| 149 | #define USB_PID_TWINHAN_VP7045_COLD 0x3205 | ||
| 150 | #define USB_PID_TWINHAN_VP7045_WARM 0x3206 | ||
| 151 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 | ||
| 152 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 | ||
| 153 | #define USB_PID_TINYTWIN 0x3226 | ||
| 154 | #define USB_PID_TINYTWIN_2 0xe402 | ||
| 155 | #define USB_PID_TINYTWIN_3 0x9016 | ||
| 156 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 | ||
| 157 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 | ||
| 158 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 | ||
| 159 | #define USB_PID_ULTIMA_TVBOX_WARM 0x8106 | ||
| 160 | #define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107 | ||
| 161 | #define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108 | ||
| 162 | #define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235 | ||
| 163 | #define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109 | ||
| 164 | #define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a | ||
| 165 | #define USB_PID_ARTEC_T14_COLD 0x810b | ||
| 166 | #define USB_PID_ARTEC_T14_WARM 0x810c | ||
| 167 | #define USB_PID_ARTEC_T14BR 0x810f | ||
| 168 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613 | ||
| 169 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002 | ||
| 170 | #define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e | ||
| 171 | #define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f | ||
| 172 | #define USB_PID_HANFTEK_UMT_010_COLD 0x0001 | ||
| 173 | #define USB_PID_HANFTEK_UMT_010_WARM 0x0015 | ||
| 174 | #define USB_PID_DTT200U_COLD 0x0201 | ||
| 175 | #define USB_PID_DTT200U_WARM 0x0301 | ||
| 176 | #define USB_PID_WT220U_ZAP250_COLD 0x0220 | ||
| 177 | #define USB_PID_WT220U_COLD 0x0222 | ||
| 178 | #define USB_PID_WT220U_WARM 0x0221 | ||
| 179 | #define USB_PID_WT220U_FC_COLD 0x0225 | ||
| 180 | #define USB_PID_WT220U_FC_WARM 0x0226 | ||
| 181 | #define USB_PID_WT220U_ZL0353_COLD 0x022a | ||
| 182 | #define USB_PID_WT220U_ZL0353_WARM 0x022b | ||
| 183 | #define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300 | ||
| 184 | #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 | ||
| 185 | #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 | ||
| 186 | #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 | ||
| 187 | #define USB_PID_HAUPPAUGE_NOVA_T_500_3 0x8400 | ||
| 188 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 | ||
| 189 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 | ||
| 190 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070 | ||
| 191 | #define USB_PID_HAUPPAUGE_MYTV_T 0x7080 | ||
| 192 | #define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580 | ||
| 193 | #define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009 0x5200 | ||
| 194 | #define USB_PID_HAUPPAUGE_TIGER_ATSC 0xb200 | ||
| 195 | #define USB_PID_HAUPPAUGE_TIGER_ATSC_B210 0xb210 | ||
| 196 | #define USB_PID_AVERMEDIA_EXPRESS 0xb568 | ||
| 197 | #define USB_PID_AVERMEDIA_VOLAR 0xa807 | ||
| 198 | #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 | ||
| 199 | #define USB_PID_AVERMEDIA_VOLAR_A868R 0xa868 | ||
| 200 | #define USB_PID_AVERMEDIA_MCE_USB_M038 0x1228 | ||
| 201 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039 | ||
| 202 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039 | ||
| 203 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039 | ||
| 204 | #define USB_PID_AVERMEDIA_VOLAR_X 0xa815 | ||
| 205 | #define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150 | ||
| 206 | #define USB_PID_AVERMEDIA_A309 0xa309 | ||
| 207 | #define USB_PID_AVERMEDIA_A310 0xa310 | ||
| 208 | #define USB_PID_AVERMEDIA_A850 0x850a | ||
| 209 | #define USB_PID_AVERMEDIA_A850T 0x850b | ||
| 210 | #define USB_PID_AVERMEDIA_A805 0xa805 | ||
| 211 | #define USB_PID_AVERMEDIA_A815M 0x815a | ||
| 212 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 | ||
| 213 | #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d | ||
| 214 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a | ||
| 215 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 | ||
| 216 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 | ||
| 217 | #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 | ||
| 218 | #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 | ||
| 219 | #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 | ||
| 220 | #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab | ||
| 221 | #define USB_PID_TERRATEC_T3 0x10a0 | ||
| 222 | #define USB_PID_TERRATEC_T5 0x10a1 | ||
| 223 | #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e | ||
| 224 | #define USB_PID_PINNACLE_PCTV2000E 0x022c | ||
| 225 | #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 | ||
| 226 | #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229 | ||
| 227 | #define USB_PID_PINNACLE_PCTV71E 0x022b | ||
| 228 | #define USB_PID_PINNACLE_PCTV72E 0x0236 | ||
| 229 | #define USB_PID_PINNACLE_PCTV73E 0x0237 | ||
| 230 | #define USB_PID_PINNACLE_PCTV310E 0x3211 | ||
| 231 | #define USB_PID_PINNACLE_PCTV801E 0x023a | ||
| 232 | #define USB_PID_PINNACLE_PCTV801E_SE 0x023b | ||
| 233 | #define USB_PID_PINNACLE_PCTV340E 0x023d | ||
| 234 | #define USB_PID_PINNACLE_PCTV340E_SE 0x023e | ||
| 235 | #define USB_PID_PINNACLE_PCTV73A 0x0243 | ||
| 236 | #define USB_PID_PINNACLE_PCTV73ESE 0x0245 | ||
| 237 | #define USB_PID_PINNACLE_PCTV74E 0x0246 | ||
| 238 | #define USB_PID_PINNACLE_PCTV282E 0x0248 | ||
| 239 | #define USB_PID_PIXELVIEW_SBTVD 0x5010 | ||
| 240 | #define USB_PID_PCTV_200E 0x020e | ||
| 241 | #define USB_PID_PCTV_400E 0x020f | ||
| 242 | #define USB_PID_PCTV_450E 0x0222 | ||
| 243 | #define USB_PID_NEBULA_DIGITV 0x0201 | ||
| 244 | #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 | ||
| 245 | #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 | ||
| 246 | #define USB_PID_DVICO_BLUEBIRD_LG064F_WARM 0xd501 | ||
| 247 | #define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD 0xdb00 | ||
| 248 | #define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM 0xdb01 | ||
| 249 | #define USB_PID_DVICO_BLUEBIRD_TH7579_COLD 0xdb10 | ||
| 250 | #define USB_PID_DVICO_BLUEBIRD_TH7579_WARM 0xdb11 | ||
| 251 | #define USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD 0xdb50 | ||
| 252 | #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51 | ||
| 253 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 | ||
| 254 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 | ||
| 255 | #define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78 | ||
| 256 | #define USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2 0xdb98 | ||
| 257 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70 | ||
| 258 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71 | ||
| 259 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 | ||
| 260 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 | ||
| 261 | #define USB_PID_MEDION_MD95700 0x0932 | ||
| 262 | #define USB_PID_MSI_MEGASKY580 0x5580 | ||
| 263 | #define USB_PID_MSI_MEGASKY580_55801 0x5581 | ||
| 264 | #define USB_PID_KYE_DVB_T_COLD 0x701e | ||
| 265 | #define USB_PID_KYE_DVB_T_WARM 0x701f | ||
| 266 | #define USB_PID_LITEON_DVB_T_COLD 0xf000 | ||
| 267 | #define USB_PID_LITEON_DVB_T_WARM 0xf001 | ||
| 268 | #define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360 | ||
| 269 | #define USB_PID_DIGIVOX_MINI_SL_WARM 0xe361 | ||
| 270 | #define USB_PID_GRANDTEC_DVBT_USB2_COLD 0x0bc6 | ||
| 271 | #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 | ||
| 272 | #define USB_PID_WINFAST_DTV2000DS 0x6a04 | ||
| 273 | #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 | ||
| 274 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 | ||
| 275 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 | ||
| 276 | #define USB_PID_WINFAST_DTV_DONGLE_H 0x60f6 | ||
| 277 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 | ||
| 278 | #define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029 | ||
| 279 | #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 | ||
| 280 | #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 | ||
| 281 | #define USB_PID_GENPIX_8PSK_REV_2 0x0202 | ||
| 282 | #define USB_PID_GENPIX_SKYWALKER_1 0x0203 | ||
| 283 | #define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204 | ||
| 284 | #define USB_PID_GENPIX_SKYWALKER_2 0x0206 | ||
| 285 | #define USB_PID_SIGMATEK_DVB_110 0x6610 | ||
| 286 | #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 | ||
| 287 | #define USB_PID_MSI_DIGIVOX_DUO 0x8801 | ||
| 288 | #define USB_PID_OPERA1_COLD 0x2830 | ||
| 289 | #define USB_PID_OPERA1_WARM 0x3829 | ||
| 290 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 | ||
| 291 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 | ||
| 292 | #define USB_PID_GIGABYTE_U7000 0x7001 | ||
| 293 | #define USB_PID_GIGABYTE_U8000 0x7002 | ||
| 294 | #define USB_PID_ASUS_U3000 0x171f | ||
| 295 | #define USB_PID_ASUS_U3000H 0x1736 | ||
| 296 | #define USB_PID_ASUS_U3100 0x173f | ||
| 297 | #define USB_PID_YUAN_EC372S 0x1edc | ||
| 298 | #define USB_PID_YUAN_STK7700PH 0x1f08 | ||
| 299 | #define USB_PID_YUAN_PD378S 0x2edc | ||
| 300 | #define USB_PID_YUAN_MC770 0x0871 | ||
| 301 | #define USB_PID_YUAN_STK7700D 0x1efc | ||
| 302 | #define USB_PID_YUAN_STK7700D_2 0x1e8c | ||
| 303 | #define USB_PID_DW2102 0x2102 | ||
| 304 | #define USB_PID_XTENSIONS_XD_380 0x0381 | ||
| 305 | #define USB_PID_TELESTAR_STARSTICK_2 0x8000 | ||
| 306 | #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 | ||
| 307 | #define USB_PID_SONY_PLAYTV 0x0003 | ||
| 308 | #define USB_PID_MYGICA_D689 0xd811 | ||
| 309 | #define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011 | ||
| 310 | #define USB_PID_ELGATO_EYETV_DTT 0x0021 | ||
| 311 | #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 | ||
| 312 | #define USB_PID_ELGATO_EYETV_SAT 0x002a | ||
| 313 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 | ||
| 314 | #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 | ||
| 315 | #define USB_PID_FRIIO_WHITE 0x0001 | ||
| 316 | #define USB_PID_TVWAY_PLUS 0x0002 | ||
| 317 | #define USB_PID_SVEON_STV20 0xe39d | ||
| 318 | #define USB_PID_SVEON_STV22 0xe401 | ||
| 319 | #define USB_PID_AZUREWAVE_AZ6027 0x3275 | ||
| 320 | #define USB_PID_TERRATEC_DVBS2CI_V1 0x10a4 | ||
| 321 | #define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac | ||
| 322 | #define USB_PID_TECHNISAT_USB2_HDCI_V1 0x0001 | ||
| 323 | #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002 | ||
| 324 | #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004 | ||
| 325 | #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 | ||
| 326 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c new file mode 100644 index 00000000000..2e3ea0fa28e --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c | |||
| @@ -0,0 +1,289 @@ | |||
| 1 | /* | ||
| 2 | * DVB USB library - provides a generic interface for a DVB USB device driver. | ||
| 3 | * | ||
| 4 | * dvb-usb-init.c | ||
| 5 | * | ||
| 6 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation, version 2. | ||
| 11 | * | ||
| 12 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 13 | */ | ||
| 14 | #include "dvb-usb-common.h" | ||
| 15 | |||
| 16 | /* debug */ | ||
| 17 | int dvb_usb_debug; | ||
| 18 | module_param_named(debug, dvb_usb_debug, int, 0644); | ||
| 19 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64,mem=128,uxfer=256 (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 20 | |||
| 21 | int dvb_usb_disable_rc_polling; | ||
| 22 | module_param_named(disable_rc_polling, dvb_usb_disable_rc_polling, int, 0644); | ||
| 23 | MODULE_PARM_DESC(disable_rc_polling, "disable remote control polling (default: 0)."); | ||
| 24 | |||
| 25 | static int dvb_usb_force_pid_filter_usage; | ||
| 26 | module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444); | ||
| 27 | MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0)."); | ||
| 28 | |||
| 29 | static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs) | ||
| 30 | { | ||
| 31 | struct dvb_usb_adapter *adap; | ||
| 32 | int ret, n; | ||
| 33 | |||
| 34 | for (n = 0; n < d->props.num_adapters; n++) { | ||
| 35 | adap = &d->adapter[n]; | ||
| 36 | adap->dev = d; | ||
| 37 | adap->id = n; | ||
| 38 | |||
| 39 | memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties)); | ||
| 40 | |||
| 41 | /* speed - when running at FULL speed we need a HW PID filter */ | ||
| 42 | if (d->udev->speed == USB_SPEED_FULL && !(adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER)) { | ||
| 43 | err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)"); | ||
| 44 | return -ENODEV; | ||
| 45 | } | ||
| 46 | |||
| 47 | if ((d->udev->speed == USB_SPEED_FULL && adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) || | ||
| 48 | (adap->props.caps & DVB_USB_ADAP_NEED_PID_FILTERING)) { | ||
| 49 | info("will use the device's hardware PID filter (table count: %d).", adap->props.pid_filter_count); | ||
| 50 | adap->pid_filtering = 1; | ||
| 51 | adap->max_feed_count = adap->props.pid_filter_count; | ||
| 52 | } else { | ||
| 53 | info("will pass the complete MPEG2 transport stream to the software demuxer."); | ||
| 54 | adap->pid_filtering = 0; | ||
| 55 | adap->max_feed_count = 255; | ||
| 56 | } | ||
| 57 | |||
| 58 | if (!adap->pid_filtering && | ||
| 59 | dvb_usb_force_pid_filter_usage && | ||
| 60 | adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) { | ||
| 61 | info("pid filter enabled by module option."); | ||
| 62 | adap->pid_filtering = 1; | ||
| 63 | adap->max_feed_count = adap->props.pid_filter_count; | ||
| 64 | } | ||
| 65 | |||
| 66 | if (adap->props.size_of_priv > 0) { | ||
| 67 | adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL); | ||
| 68 | if (adap->priv == NULL) { | ||
| 69 | err("no memory for priv for adapter %d.", n); | ||
| 70 | return -ENOMEM; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | if ((ret = dvb_usb_adapter_stream_init(adap)) || | ||
| 75 | (ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) || | ||
| 76 | (ret = dvb_usb_adapter_frontend_init(adap))) { | ||
| 77 | return ret; | ||
| 78 | } | ||
| 79 | |||
| 80 | d->num_adapters_initialized++; | ||
| 81 | d->state |= DVB_USB_STATE_DVB; | ||
| 82 | } | ||
| 83 | |||
| 84 | /* | ||
| 85 | * when reloading the driver w/o replugging the device | ||
| 86 | * sometimes a timeout occures, this helps | ||
| 87 | */ | ||
| 88 | if (d->props.generic_bulk_ctrl_endpoint != 0) { | ||
| 89 | usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | ||
| 90 | usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | ||
| 91 | } | ||
| 92 | |||
| 93 | return 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | static int dvb_usb_adapter_exit(struct dvb_usb_device *d) | ||
| 97 | { | ||
| 98 | int n; | ||
| 99 | |||
| 100 | for (n = 0; n < d->num_adapters_initialized; n++) { | ||
| 101 | dvb_usb_adapter_frontend_exit(&d->adapter[n]); | ||
| 102 | dvb_usb_adapter_dvb_exit(&d->adapter[n]); | ||
| 103 | dvb_usb_adapter_stream_exit(&d->adapter[n]); | ||
| 104 | kfree(d->adapter[n].priv); | ||
| 105 | } | ||
| 106 | d->num_adapters_initialized = 0; | ||
| 107 | d->state &= ~DVB_USB_STATE_DVB; | ||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | |||
| 112 | /* general initialization functions */ | ||
| 113 | static int dvb_usb_exit(struct dvb_usb_device *d) | ||
| 114 | { | ||
| 115 | deb_info("state before exiting everything: %x\n", d->state); | ||
| 116 | dvb_usb_remote_exit(d); | ||
| 117 | dvb_usb_adapter_exit(d); | ||
| 118 | dvb_usb_i2c_exit(d); | ||
| 119 | deb_info("state should be zero now: %x\n", d->state); | ||
| 120 | d->state = DVB_USB_STATE_INIT; | ||
| 121 | kfree(d->priv); | ||
| 122 | kfree(d); | ||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums) | ||
| 127 | { | ||
| 128 | int ret = 0; | ||
| 129 | |||
| 130 | mutex_init(&d->usb_mutex); | ||
| 131 | mutex_init(&d->i2c_mutex); | ||
| 132 | |||
| 133 | d->state = DVB_USB_STATE_INIT; | ||
| 134 | |||
| 135 | if (d->props.size_of_priv > 0) { | ||
| 136 | d->priv = kzalloc(d->props.size_of_priv, GFP_KERNEL); | ||
| 137 | if (d->priv == NULL) { | ||
| 138 | err("no memory for priv in 'struct dvb_usb_device'"); | ||
| 139 | return -ENOMEM; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | /* check the capabilities and set appropriate variables */ | ||
| 144 | dvb_usb_device_power_ctrl(d, 1); | ||
| 145 | |||
| 146 | if ((ret = dvb_usb_i2c_init(d)) || | ||
| 147 | (ret = dvb_usb_adapter_init(d, adapter_nums))) { | ||
| 148 | dvb_usb_exit(d); | ||
| 149 | return ret; | ||
| 150 | } | ||
| 151 | |||
| 152 | if ((ret = dvb_usb_remote_init(d))) | ||
| 153 | err("could not initialize remote control."); | ||
| 154 | |||
| 155 | dvb_usb_device_power_ctrl(d, 0); | ||
| 156 | |||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* determine the name and the state of the just found USB device */ | ||
| 161 | static struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device *udev, struct dvb_usb_device_properties *props, int *cold) | ||
| 162 | { | ||
| 163 | int i, j; | ||
| 164 | struct dvb_usb_device_description *desc = NULL; | ||
| 165 | |||
| 166 | *cold = -1; | ||
| 167 | |||
| 168 | for (i = 0; i < props->num_device_descs; i++) { | ||
| 169 | |||
| 170 | for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) { | ||
| 171 | deb_info("check for cold %x %x\n", props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct); | ||
| 172 | if (props->devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) && | ||
| 173 | props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) { | ||
| 174 | *cold = 1; | ||
| 175 | desc = &props->devices[i]; | ||
| 176 | break; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | if (desc != NULL) | ||
| 181 | break; | ||
| 182 | |||
| 183 | for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) { | ||
| 184 | deb_info("check for warm %x %x\n", props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct); | ||
| 185 | if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) && | ||
| 186 | props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) { | ||
| 187 | *cold = 0; | ||
| 188 | desc = &props->devices[i]; | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | if (desc != NULL && props->identify_state != NULL) | ||
| 195 | props->identify_state(udev, props, &desc, cold); | ||
| 196 | |||
| 197 | return desc; | ||
| 198 | } | ||
| 199 | |||
| 200 | int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 201 | { | ||
| 202 | if (onoff) | ||
| 203 | d->powered++; | ||
| 204 | else | ||
| 205 | d->powered--; | ||
| 206 | |||
| 207 | if (d->powered == 0 || (onoff && d->powered == 1)) { /* when switching from 1 to 0 or from 0 to 1 */ | ||
| 208 | deb_info("power control: %d\n", onoff); | ||
| 209 | if (d->props.power_ctrl) | ||
| 210 | return d->props.power_ctrl(d, onoff); | ||
| 211 | } | ||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 215 | /* | ||
| 216 | * USB | ||
| 217 | */ | ||
| 218 | int dvb_usb_device_init(struct usb_interface *intf, | ||
| 219 | struct dvb_usb_device_properties *props, | ||
| 220 | struct module *owner, struct dvb_usb_device **du, | ||
| 221 | short *adapter_nums) | ||
| 222 | { | ||
| 223 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 224 | struct dvb_usb_device *d = NULL; | ||
| 225 | struct dvb_usb_device_description *desc = NULL; | ||
| 226 | |||
| 227 | int ret = -ENOMEM, cold = 0; | ||
| 228 | |||
| 229 | if (du != NULL) | ||
| 230 | *du = NULL; | ||
| 231 | |||
| 232 | if ((desc = dvb_usb_find_device(udev, props, &cold)) == NULL) { | ||
| 233 | deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n"); | ||
| 234 | return -ENODEV; | ||
| 235 | } | ||
| 236 | |||
| 237 | if (cold) { | ||
| 238 | info("found a '%s' in cold state, will try to load a firmware", desc->name); | ||
| 239 | ret = dvb_usb_download_firmware(udev, props); | ||
| 240 | if (!props->no_reconnect || ret != 0) | ||
| 241 | return ret; | ||
| 242 | } | ||
| 243 | |||
| 244 | info("found a '%s' in warm state.", desc->name); | ||
| 245 | d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); | ||
| 246 | if (d == NULL) { | ||
| 247 | err("no memory for 'struct dvb_usb_device'"); | ||
| 248 | return -ENOMEM; | ||
| 249 | } | ||
| 250 | |||
| 251 | d->udev = udev; | ||
| 252 | memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties)); | ||
| 253 | d->desc = desc; | ||
| 254 | d->owner = owner; | ||
| 255 | |||
| 256 | usb_set_intfdata(intf, d); | ||
| 257 | |||
| 258 | if (du != NULL) | ||
| 259 | *du = d; | ||
| 260 | |||
| 261 | ret = dvb_usb_init(d, adapter_nums); | ||
| 262 | |||
| 263 | if (ret == 0) | ||
| 264 | info("%s successfully initialized and connected.", desc->name); | ||
| 265 | else | ||
| 266 | info("%s error while loading driver (%d)", desc->name, ret); | ||
| 267 | return ret; | ||
| 268 | } | ||
| 269 | EXPORT_SYMBOL(dvb_usb_device_init); | ||
| 270 | |||
| 271 | void dvb_usb_device_exit(struct usb_interface *intf) | ||
| 272 | { | ||
| 273 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
| 274 | const char *name = "generic DVB-USB module"; | ||
| 275 | |||
| 276 | usb_set_intfdata(intf, NULL); | ||
| 277 | if (d != NULL && d->desc != NULL) { | ||
| 278 | name = d->desc->name; | ||
| 279 | dvb_usb_exit(d); | ||
| 280 | } | ||
| 281 | info("%s successfully deinitialized and disconnected.", name); | ||
| 282 | |||
| 283 | } | ||
| 284 | EXPORT_SYMBOL(dvb_usb_device_exit); | ||
| 285 | |||
| 286 | MODULE_VERSION("1.0"); | ||
| 287 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 288 | MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices"); | ||
| 289 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c new file mode 100644 index 00000000000..41bacff2496 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | |||
| @@ -0,0 +1,391 @@ | |||
| 1 | /* dvb-usb-remote.c is part of the DVB USB library. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 4 | * see dvb-usb-init.c for copyright information. | ||
| 5 | * | ||
| 6 | * This file contains functions for initializing the input-device and for handling remote-control-queries. | ||
| 7 | */ | ||
| 8 | #include "dvb-usb-common.h" | ||
| 9 | #include <linux/usb/input.h> | ||
| 10 | |||
| 11 | static unsigned int | ||
| 12 | legacy_dvb_usb_get_keymap_index(const struct input_keymap_entry *ke, | ||
| 13 | struct rc_map_table *keymap, | ||
| 14 | unsigned int keymap_size) | ||
| 15 | { | ||
| 16 | unsigned int index; | ||
| 17 | unsigned int scancode; | ||
| 18 | |||
| 19 | if (ke->flags & INPUT_KEYMAP_BY_INDEX) { | ||
| 20 | index = ke->index; | ||
| 21 | } else { | ||
| 22 | if (input_scancode_to_scalar(ke, &scancode)) | ||
| 23 | return keymap_size; | ||
| 24 | |||
| 25 | /* See if we can match the raw key code. */ | ||
| 26 | for (index = 0; index < keymap_size; index++) | ||
| 27 | if (keymap[index].scancode == scancode) | ||
| 28 | break; | ||
| 29 | |||
| 30 | /* See if there is an unused hole in the map */ | ||
| 31 | if (index >= keymap_size) { | ||
| 32 | for (index = 0; index < keymap_size; index++) { | ||
| 33 | if (keymap[index].keycode == KEY_RESERVED || | ||
| 34 | keymap[index].keycode == KEY_UNKNOWN) { | ||
| 35 | break; | ||
| 36 | } | ||
| 37 | } | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | return index; | ||
| 42 | } | ||
| 43 | |||
| 44 | static int legacy_dvb_usb_getkeycode(struct input_dev *dev, | ||
| 45 | struct input_keymap_entry *ke) | ||
| 46 | { | ||
| 47 | struct dvb_usb_device *d = input_get_drvdata(dev); | ||
| 48 | struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; | ||
| 49 | unsigned int keymap_size = d->props.rc.legacy.rc_map_size; | ||
| 50 | unsigned int index; | ||
| 51 | |||
| 52 | index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size); | ||
| 53 | if (index >= keymap_size) | ||
| 54 | return -EINVAL; | ||
| 55 | |||
| 56 | ke->keycode = keymap[index].keycode; | ||
| 57 | if (ke->keycode == KEY_UNKNOWN) | ||
| 58 | ke->keycode = KEY_RESERVED; | ||
| 59 | ke->len = sizeof(keymap[index].scancode); | ||
| 60 | memcpy(&ke->scancode, &keymap[index].scancode, ke->len); | ||
| 61 | ke->index = index; | ||
| 62 | |||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | static int legacy_dvb_usb_setkeycode(struct input_dev *dev, | ||
| 67 | const struct input_keymap_entry *ke, | ||
| 68 | unsigned int *old_keycode) | ||
| 69 | { | ||
| 70 | struct dvb_usb_device *d = input_get_drvdata(dev); | ||
| 71 | struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; | ||
| 72 | unsigned int keymap_size = d->props.rc.legacy.rc_map_size; | ||
| 73 | unsigned int index; | ||
| 74 | |||
| 75 | index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size); | ||
| 76 | /* | ||
| 77 | * FIXME: Currently, it is not possible to increase the size of | ||
| 78 | * scancode table. For it to happen, one possibility | ||
| 79 | * would be to allocate a table with key_map_size + 1, | ||
| 80 | * copying data, appending the new key on it, and freeing | ||
| 81 | * the old one - or maybe just allocating some spare space | ||
| 82 | */ | ||
| 83 | if (index >= keymap_size) | ||
| 84 | return -EINVAL; | ||
| 85 | |||
| 86 | *old_keycode = keymap[index].keycode; | ||
| 87 | keymap->keycode = ke->keycode; | ||
| 88 | __set_bit(ke->keycode, dev->keybit); | ||
| 89 | |||
| 90 | if (*old_keycode != KEY_RESERVED) { | ||
| 91 | __clear_bit(*old_keycode, dev->keybit); | ||
| 92 | for (index = 0; index < keymap_size; index++) { | ||
| 93 | if (keymap[index].keycode == *old_keycode) { | ||
| 94 | __set_bit(*old_keycode, dev->keybit); | ||
| 95 | break; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | /* Remote-control poll function - called every dib->rc_query_interval ms to see | ||
| 104 | * whether the remote control has received anything. | ||
| 105 | * | ||
| 106 | * TODO: Fix the repeat rate of the input device. | ||
| 107 | */ | ||
| 108 | static void legacy_dvb_usb_read_remote_control(struct work_struct *work) | ||
| 109 | { | ||
| 110 | struct dvb_usb_device *d = | ||
| 111 | container_of(work, struct dvb_usb_device, rc_query_work.work); | ||
| 112 | u32 event; | ||
| 113 | int state; | ||
| 114 | |||
| 115 | /* TODO: need a lock here. We can simply skip checking for the remote control | ||
| 116 | if we're busy. */ | ||
| 117 | |||
| 118 | /* when the parameter has been set to 1 via sysfs while the driver was running */ | ||
| 119 | if (dvb_usb_disable_rc_polling) | ||
| 120 | return; | ||
| 121 | |||
| 122 | if (d->props.rc.legacy.rc_query(d,&event,&state)) { | ||
| 123 | err("error while querying for an remote control event."); | ||
| 124 | goto schedule; | ||
| 125 | } | ||
| 126 | |||
| 127 | |||
| 128 | switch (state) { | ||
| 129 | case REMOTE_NO_KEY_PRESSED: | ||
| 130 | break; | ||
| 131 | case REMOTE_KEY_PRESSED: | ||
| 132 | deb_rc("key pressed\n"); | ||
| 133 | d->last_event = event; | ||
| 134 | case REMOTE_KEY_REPEAT: | ||
| 135 | deb_rc("key repeated\n"); | ||
| 136 | input_event(d->input_dev, EV_KEY, event, 1); | ||
| 137 | input_sync(d->input_dev); | ||
| 138 | input_event(d->input_dev, EV_KEY, d->last_event, 0); | ||
| 139 | input_sync(d->input_dev); | ||
| 140 | break; | ||
| 141 | default: | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* improved repeat handling ??? | ||
| 146 | switch (state) { | ||
| 147 | case REMOTE_NO_KEY_PRESSED: | ||
| 148 | deb_rc("NO KEY PRESSED\n"); | ||
| 149 | if (d->last_state != REMOTE_NO_KEY_PRESSED) { | ||
| 150 | deb_rc("releasing event %d\n",d->last_event); | ||
| 151 | input_event(d->rc_input_dev, EV_KEY, d->last_event, 0); | ||
| 152 | input_sync(d->rc_input_dev); | ||
| 153 | } | ||
| 154 | d->last_state = REMOTE_NO_KEY_PRESSED; | ||
| 155 | d->last_event = 0; | ||
| 156 | break; | ||
| 157 | case REMOTE_KEY_PRESSED: | ||
| 158 | deb_rc("KEY PRESSED\n"); | ||
| 159 | deb_rc("pressing event %d\n",event); | ||
| 160 | |||
| 161 | input_event(d->rc_input_dev, EV_KEY, event, 1); | ||
| 162 | input_sync(d->rc_input_dev); | ||
| 163 | |||
| 164 | d->last_event = event; | ||
| 165 | d->last_state = REMOTE_KEY_PRESSED; | ||
| 166 | break; | ||
| 167 | case REMOTE_KEY_REPEAT: | ||
| 168 | deb_rc("KEY_REPEAT\n"); | ||
| 169 | if (d->last_state != REMOTE_NO_KEY_PRESSED) { | ||
| 170 | deb_rc("repeating event %d\n",d->last_event); | ||
| 171 | input_event(d->rc_input_dev, EV_KEY, d->last_event, 2); | ||
| 172 | input_sync(d->rc_input_dev); | ||
| 173 | d->last_state = REMOTE_KEY_REPEAT; | ||
| 174 | } | ||
| 175 | default: | ||
| 176 | break; | ||
| 177 | } | ||
| 178 | */ | ||
| 179 | |||
| 180 | schedule: | ||
| 181 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval)); | ||
| 182 | } | ||
| 183 | |||
| 184 | static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d) | ||
| 185 | { | ||
| 186 | int i, err, rc_interval; | ||
| 187 | struct input_dev *input_dev; | ||
| 188 | |||
| 189 | input_dev = input_allocate_device(); | ||
| 190 | if (!input_dev) | ||
| 191 | return -ENOMEM; | ||
| 192 | |||
| 193 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
| 194 | input_dev->name = "IR-receiver inside an USB DVB receiver"; | ||
| 195 | input_dev->phys = d->rc_phys; | ||
| 196 | usb_to_input_id(d->udev, &input_dev->id); | ||
| 197 | input_dev->dev.parent = &d->udev->dev; | ||
| 198 | d->input_dev = input_dev; | ||
| 199 | d->rc_dev = NULL; | ||
| 200 | |||
| 201 | input_dev->getkeycode = legacy_dvb_usb_getkeycode; | ||
| 202 | input_dev->setkeycode = legacy_dvb_usb_setkeycode; | ||
| 203 | |||
| 204 | /* set the bits for the keys */ | ||
| 205 | deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size); | ||
| 206 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) { | ||
| 207 | deb_rc("setting bit for event %d item %d\n", | ||
| 208 | d->props.rc.legacy.rc_map_table[i].keycode, i); | ||
| 209 | set_bit(d->props.rc.legacy.rc_map_table[i].keycode, input_dev->keybit); | ||
| 210 | } | ||
| 211 | |||
| 212 | /* setting these two values to non-zero, we have to manage key repeats */ | ||
| 213 | input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval; | ||
| 214 | input_dev->rep[REP_DELAY] = d->props.rc.legacy.rc_interval + 150; | ||
| 215 | |||
| 216 | input_set_drvdata(input_dev, d); | ||
| 217 | |||
| 218 | err = input_register_device(input_dev); | ||
| 219 | if (err) | ||
| 220 | input_free_device(input_dev); | ||
| 221 | |||
| 222 | rc_interval = d->props.rc.legacy.rc_interval; | ||
| 223 | |||
| 224 | INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control); | ||
| 225 | |||
| 226 | info("schedule remote query interval to %d msecs.", rc_interval); | ||
| 227 | schedule_delayed_work(&d->rc_query_work, | ||
| 228 | msecs_to_jiffies(rc_interval)); | ||
| 229 | |||
| 230 | d->state |= DVB_USB_STATE_REMOTE; | ||
| 231 | |||
| 232 | return err; | ||
| 233 | } | ||
| 234 | |||
| 235 | /* Remote-control poll function - called every dib->rc_query_interval ms to see | ||
| 236 | * whether the remote control has received anything. | ||
| 237 | * | ||
| 238 | * TODO: Fix the repeat rate of the input device. | ||
| 239 | */ | ||
| 240 | static void dvb_usb_read_remote_control(struct work_struct *work) | ||
| 241 | { | ||
| 242 | struct dvb_usb_device *d = | ||
| 243 | container_of(work, struct dvb_usb_device, rc_query_work.work); | ||
| 244 | int err; | ||
| 245 | |||
| 246 | /* TODO: need a lock here. We can simply skip checking for the remote control | ||
| 247 | if we're busy. */ | ||
| 248 | |||
| 249 | /* when the parameter has been set to 1 via sysfs while the | ||
| 250 | * driver was running, or when bulk mode is enabled after IR init | ||
| 251 | */ | ||
| 252 | if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode) | ||
| 253 | return; | ||
| 254 | |||
| 255 | err = d->props.rc.core.rc_query(d); | ||
| 256 | if (err) | ||
| 257 | err("error %d while querying for an remote control event.", err); | ||
| 258 | |||
| 259 | schedule_delayed_work(&d->rc_query_work, | ||
| 260 | msecs_to_jiffies(d->props.rc.core.rc_interval)); | ||
| 261 | } | ||
| 262 | |||
| 263 | static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d) | ||
| 264 | { | ||
| 265 | int err, rc_interval; | ||
| 266 | struct rc_dev *dev; | ||
| 267 | |||
| 268 | dev = rc_allocate_device(); | ||
| 269 | if (!dev) | ||
| 270 | return -ENOMEM; | ||
| 271 | |||
| 272 | dev->driver_name = d->props.rc.core.module_name; | ||
| 273 | dev->map_name = d->props.rc.core.rc_codes; | ||
| 274 | dev->change_protocol = d->props.rc.core.change_protocol; | ||
| 275 | dev->allowed_protos = d->props.rc.core.allowed_protos; | ||
| 276 | dev->driver_type = d->props.rc.core.driver_type; | ||
| 277 | usb_to_input_id(d->udev, &dev->input_id); | ||
| 278 | dev->input_name = "IR-receiver inside an USB DVB receiver"; | ||
| 279 | dev->input_phys = d->rc_phys; | ||
| 280 | dev->dev.parent = &d->udev->dev; | ||
| 281 | dev->priv = d; | ||
| 282 | |||
| 283 | err = rc_register_device(dev); | ||
| 284 | if (err < 0) { | ||
| 285 | rc_free_device(dev); | ||
| 286 | return err; | ||
| 287 | } | ||
| 288 | |||
| 289 | d->input_dev = NULL; | ||
| 290 | d->rc_dev = dev; | ||
| 291 | |||
| 292 | if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode) | ||
| 293 | return 0; | ||
| 294 | |||
| 295 | /* Polling mode - initialize a work queue for handling it */ | ||
| 296 | INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); | ||
| 297 | |||
| 298 | rc_interval = d->props.rc.core.rc_interval; | ||
| 299 | |||
| 300 | info("schedule remote query interval to %d msecs.", rc_interval); | ||
| 301 | schedule_delayed_work(&d->rc_query_work, | ||
| 302 | msecs_to_jiffies(rc_interval)); | ||
| 303 | |||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | |||
| 307 | int dvb_usb_remote_init(struct dvb_usb_device *d) | ||
| 308 | { | ||
| 309 | int err; | ||
| 310 | |||
| 311 | if (dvb_usb_disable_rc_polling) | ||
| 312 | return 0; | ||
| 313 | |||
| 314 | if (d->props.rc.legacy.rc_map_table && d->props.rc.legacy.rc_query) | ||
| 315 | d->props.rc.mode = DVB_RC_LEGACY; | ||
| 316 | else if (d->props.rc.core.rc_codes) | ||
| 317 | d->props.rc.mode = DVB_RC_CORE; | ||
| 318 | else | ||
| 319 | return 0; | ||
| 320 | |||
| 321 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); | ||
| 322 | strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); | ||
| 323 | |||
| 324 | /* Start the remote-control polling. */ | ||
| 325 | if (d->props.rc.legacy.rc_interval < 40) | ||
| 326 | d->props.rc.legacy.rc_interval = 100; /* default */ | ||
| 327 | |||
| 328 | if (d->props.rc.mode == DVB_RC_LEGACY) | ||
| 329 | err = legacy_dvb_usb_remote_init(d); | ||
| 330 | else | ||
| 331 | err = rc_core_dvb_usb_remote_init(d); | ||
| 332 | if (err) | ||
| 333 | return err; | ||
| 334 | |||
| 335 | d->state |= DVB_USB_STATE_REMOTE; | ||
| 336 | |||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | |||
| 340 | int dvb_usb_remote_exit(struct dvb_usb_device *d) | ||
| 341 | { | ||
| 342 | if (d->state & DVB_USB_STATE_REMOTE) { | ||
| 343 | cancel_delayed_work_sync(&d->rc_query_work); | ||
| 344 | if (d->props.rc.mode == DVB_RC_LEGACY) | ||
| 345 | input_unregister_device(d->input_dev); | ||
| 346 | else | ||
| 347 | rc_unregister_device(d->rc_dev); | ||
| 348 | } | ||
| 349 | d->state &= ~DVB_USB_STATE_REMOTE; | ||
| 350 | return 0; | ||
| 351 | } | ||
| 352 | |||
| 353 | #define DVB_USB_RC_NEC_EMPTY 0x00 | ||
| 354 | #define DVB_USB_RC_NEC_KEY_PRESSED 0x01 | ||
| 355 | #define DVB_USB_RC_NEC_KEY_REPEATED 0x02 | ||
| 356 | int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, | ||
| 357 | u8 keybuf[5], u32 *event, int *state) | ||
| 358 | { | ||
| 359 | int i; | ||
| 360 | struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; | ||
| 361 | *event = 0; | ||
| 362 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 363 | switch (keybuf[0]) { | ||
| 364 | case DVB_USB_RC_NEC_EMPTY: | ||
| 365 | break; | ||
| 366 | case DVB_USB_RC_NEC_KEY_PRESSED: | ||
| 367 | if ((u8) ~keybuf[1] != keybuf[2] || | ||
| 368 | (u8) ~keybuf[3] != keybuf[4]) { | ||
| 369 | deb_err("remote control checksum failed.\n"); | ||
| 370 | break; | ||
| 371 | } | ||
| 372 | /* See if we can match the raw key code. */ | ||
| 373 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) | ||
| 374 | if (rc5_custom(&keymap[i]) == keybuf[1] && | ||
| 375 | rc5_data(&keymap[i]) == keybuf[3]) { | ||
| 376 | *event = keymap[i].keycode; | ||
| 377 | *state = REMOTE_KEY_PRESSED; | ||
| 378 | return 0; | ||
| 379 | } | ||
| 380 | deb_err("key mapping failed - no appropriate key found in keymapping\n"); | ||
| 381 | break; | ||
| 382 | case DVB_USB_RC_NEC_KEY_REPEATED: | ||
| 383 | *state = REMOTE_KEY_REPEAT; | ||
| 384 | break; | ||
| 385 | default: | ||
| 386 | deb_err("unknown type of remote status: %d\n",keybuf[0]); | ||
| 387 | break; | ||
| 388 | } | ||
| 389 | return 0; | ||
| 390 | } | ||
| 391 | EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event); | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c new file mode 100644 index 00000000000..bb46ba6a357 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | /* dvb-usb-urb.c is part of the DVB USB library. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 4 | * see dvb-usb-init.c for copyright information. | ||
| 5 | * | ||
| 6 | * This file keeps functions for initializing and handling the | ||
| 7 | * USB and URB stuff. | ||
| 8 | */ | ||
| 9 | #include "dvb-usb-common.h" | ||
| 10 | |||
| 11 | int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, | ||
| 12 | u16 rlen, int delay_ms) | ||
| 13 | { | ||
| 14 | int actlen,ret = -ENOMEM; | ||
| 15 | |||
| 16 | if (!d || wbuf == NULL || wlen == 0) | ||
| 17 | return -EINVAL; | ||
| 18 | |||
| 19 | if (d->props.generic_bulk_ctrl_endpoint == 0) { | ||
| 20 | err("endpoint for generic control not specified."); | ||
| 21 | return -EINVAL; | ||
| 22 | } | ||
| 23 | |||
| 24 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) | ||
| 25 | return ret; | ||
| 26 | |||
| 27 | deb_xfer(">>> "); | ||
| 28 | debug_dump(wbuf,wlen,deb_xfer); | ||
| 29 | |||
| 30 | ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev, | ||
| 31 | d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen, | ||
| 32 | 2000); | ||
| 33 | |||
| 34 | if (ret) | ||
| 35 | err("bulk message failed: %d (%d/%d)",ret,wlen,actlen); | ||
| 36 | else | ||
| 37 | ret = actlen != wlen ? -1 : 0; | ||
| 38 | |||
| 39 | /* an answer is expected, and no error before */ | ||
| 40 | if (!ret && rbuf && rlen) { | ||
| 41 | if (delay_ms) | ||
| 42 | msleep(delay_ms); | ||
| 43 | |||
| 44 | ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev, | ||
| 45 | d->props.generic_bulk_ctrl_endpoint_response ? | ||
| 46 | d->props.generic_bulk_ctrl_endpoint_response : | ||
| 47 | d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen, | ||
| 48 | 2000); | ||
| 49 | |||
| 50 | if (ret) | ||
| 51 | err("recv bulk message failed: %d",ret); | ||
| 52 | else { | ||
| 53 | deb_xfer("<<< "); | ||
| 54 | debug_dump(rbuf,actlen,deb_xfer); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | mutex_unlock(&d->usb_mutex); | ||
| 59 | return ret; | ||
| 60 | } | ||
| 61 | EXPORT_SYMBOL(dvb_usb_generic_rw); | ||
| 62 | |||
| 63 | int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len) | ||
| 64 | { | ||
| 65 | return dvb_usb_generic_rw(d,buf,len,NULL,0,0); | ||
| 66 | } | ||
| 67 | EXPORT_SYMBOL(dvb_usb_generic_write); | ||
| 68 | |||
| 69 | static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buffer, size_t length) | ||
| 70 | { | ||
| 71 | struct dvb_usb_adapter *adap = stream->user_priv; | ||
| 72 | if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB) | ||
| 73 | dvb_dmx_swfilter(&adap->demux, buffer, length); | ||
| 74 | } | ||
| 75 | |||
| 76 | static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buffer, size_t length) | ||
| 77 | { | ||
| 78 | struct dvb_usb_adapter *adap = stream->user_priv; | ||
| 79 | if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB) | ||
| 80 | dvb_dmx_swfilter_204(&adap->demux, buffer, length); | ||
| 81 | } | ||
| 82 | |||
| 83 | int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap) | ||
| 84 | { | ||
| 85 | adap->stream.udev = adap->dev->udev; | ||
| 86 | if (adap->props.caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS) | ||
| 87 | adap->stream.complete = dvb_usb_data_complete_204; | ||
| 88 | else | ||
| 89 | adap->stream.complete = dvb_usb_data_complete; | ||
| 90 | adap->stream.user_priv = adap; | ||
| 91 | return usb_urb_init(&adap->stream, &adap->props.stream); | ||
| 92 | } | ||
| 93 | |||
| 94 | int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap) | ||
| 95 | { | ||
| 96 | return usb_urb_exit(&adap->stream); | ||
| 97 | } | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h new file mode 100644 index 00000000000..7d35d078342 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h | |||
| @@ -0,0 +1,463 @@ | |||
| 1 | /* dvb-usb.h is part of the DVB USB library. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 4 | * see dvb-usb-init.c for copyright information. | ||
| 5 | * | ||
| 6 | * the headerfile, all dvb-usb-drivers have to include. | ||
| 7 | * | ||
| 8 | * TODO: clean-up the structures for unused fields and update the comments | ||
| 9 | */ | ||
| 10 | #ifndef __DVB_USB_H__ | ||
| 11 | #define __DVB_USB_H__ | ||
| 12 | |||
| 13 | #include <linux/input.h> | ||
| 14 | #include <linux/usb.h> | ||
| 15 | #include <linux/firmware.h> | ||
| 16 | #include <linux/mutex.h> | ||
| 17 | #include <media/rc-core.h> | ||
| 18 | |||
| 19 | #include "dvb_frontend.h" | ||
| 20 | #include "dvb_demux.h" | ||
| 21 | #include "dvb_net.h" | ||
| 22 | #include "dmxdev.h" | ||
| 23 | |||
| 24 | #include "dvb-pll.h" | ||
| 25 | |||
| 26 | #include "dvb-usb-ids.h" | ||
| 27 | |||
| 28 | /* debug */ | ||
| 29 | #ifdef CONFIG_DVB_USB_DEBUG | ||
| 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_++) func("%02x ", b[loop_]); \ | ||
| 36 | func("\n");\ | ||
| 37 | } | ||
| 38 | #define DVB_USB_DEBUG_STATUS | ||
| 39 | #else | ||
| 40 | #define dprintk(args...) | ||
| 41 | #define debug_dump(b,l,func) | ||
| 42 | |||
| 43 | #define DVB_USB_DEBUG_STATUS " (debugging is not enabled)" | ||
| 44 | |||
| 45 | #endif | ||
| 46 | |||
| 47 | /* generic log methods - taken from usb.h */ | ||
| 48 | #ifndef DVB_USB_LOG_PREFIX | ||
| 49 | #define DVB_USB_LOG_PREFIX "dvb-usb (please define a log prefix)" | ||
| 50 | #endif | ||
| 51 | |||
| 52 | #undef err | ||
| 53 | #define err(format, arg...) printk(KERN_ERR DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
| 54 | #undef info | ||
| 55 | #define info(format, arg...) printk(KERN_INFO DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
| 56 | #undef warn | ||
| 57 | #define warn(format, arg...) printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
| 58 | |||
| 59 | /** | ||
| 60 | * struct dvb_usb_device_description - name and its according USB IDs | ||
| 61 | * @name: real name of the box, regardless which DVB USB device class is in use | ||
| 62 | * @cold_ids: array of struct usb_device_id which describe the device in | ||
| 63 | * pre-firmware state | ||
| 64 | * @warm_ids: array of struct usb_device_id which describe the device in | ||
| 65 | * post-firmware state | ||
| 66 | * | ||
| 67 | * Each DVB USB device class can have one or more actual devices, this struct | ||
| 68 | * assigns a name to it. | ||
| 69 | */ | ||
| 70 | struct dvb_usb_device_description { | ||
| 71 | const char *name; | ||
| 72 | |||
| 73 | #define DVB_USB_ID_MAX_NUM 15 | ||
| 74 | struct usb_device_id *cold_ids[DVB_USB_ID_MAX_NUM]; | ||
| 75 | struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM]; | ||
| 76 | }; | ||
| 77 | |||
| 78 | static inline u8 rc5_custom(struct rc_map_table *key) | ||
| 79 | { | ||
| 80 | return (key->scancode >> 8) & 0xff; | ||
| 81 | } | ||
| 82 | |||
| 83 | static inline u8 rc5_data(struct rc_map_table *key) | ||
| 84 | { | ||
| 85 | return key->scancode & 0xff; | ||
| 86 | } | ||
| 87 | |||
| 88 | static inline u16 rc5_scan(struct rc_map_table *key) | ||
| 89 | { | ||
| 90 | return key->scancode & 0xffff; | ||
| 91 | } | ||
| 92 | |||
| 93 | struct dvb_usb_device; | ||
| 94 | struct dvb_usb_adapter; | ||
| 95 | struct usb_data_stream; | ||
| 96 | |||
| 97 | /** | ||
| 98 | * Properties of USB streaming - TODO this structure should be somewhere else | ||
| 99 | * describes the kind of USB transfer used for data-streaming. | ||
| 100 | * (BULK or ISOC) | ||
| 101 | */ | ||
| 102 | struct usb_data_stream_properties { | ||
| 103 | #define USB_BULK 1 | ||
| 104 | #define USB_ISOC 2 | ||
| 105 | int type; | ||
| 106 | int count; | ||
| 107 | int endpoint; | ||
| 108 | |||
| 109 | union { | ||
| 110 | struct { | ||
| 111 | int buffersize; /* per URB */ | ||
| 112 | } bulk; | ||
| 113 | struct { | ||
| 114 | int framesperurb; | ||
| 115 | int framesize; | ||
| 116 | int interval; | ||
| 117 | } isoc; | ||
| 118 | } u; | ||
| 119 | }; | ||
| 120 | |||
| 121 | /** | ||
| 122 | * struct dvb_usb_adapter_properties - properties of a dvb-usb-adapter. | ||
| 123 | * A DVB-USB-Adapter is basically a dvb_adapter which is present on a USB-device. | ||
| 124 | * @caps: capabilities of the DVB USB device. | ||
| 125 | * @pid_filter_count: number of PID filter position in the optional hardware | ||
| 126 | * PID-filter. | ||
| 127 | * @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the | ||
| 128 | * device (not URB submitting/killing). | ||
| 129 | * @pid_filter_ctrl: called to en/disable the PID filter, if any. | ||
| 130 | * @pid_filter: called to set/unset a PID for filtering. | ||
| 131 | * @frontend_attach: called to attach the possible frontends (fill fe-field | ||
| 132 | * of struct dvb_usb_device). | ||
| 133 | * @tuner_attach: called to attach the correct tuner and to fill pll_addr, | ||
| 134 | * pll_desc and pll_init_buf of struct dvb_usb_device). | ||
| 135 | * @stream: configuration of the USB streaming | ||
| 136 | */ | ||
| 137 | struct dvb_usb_adapter_properties { | ||
| 138 | #define DVB_USB_ADAP_HAS_PID_FILTER 0x01 | ||
| 139 | #define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02 | ||
| 140 | #define DVB_USB_ADAP_NEED_PID_FILTERING 0x04 | ||
| 141 | #define DVB_USB_ADAP_RECEIVES_204_BYTE_TS 0x08 | ||
| 142 | int caps; | ||
| 143 | int pid_filter_count; | ||
| 144 | |||
| 145 | int (*streaming_ctrl) (struct dvb_usb_adapter *, int); | ||
| 146 | int (*pid_filter_ctrl) (struct dvb_usb_adapter *, int); | ||
| 147 | int (*pid_filter) (struct dvb_usb_adapter *, int, u16, int); | ||
| 148 | |||
| 149 | int (*frontend_attach) (struct dvb_usb_adapter *); | ||
| 150 | int (*tuner_attach) (struct dvb_usb_adapter *); | ||
| 151 | |||
| 152 | struct usb_data_stream_properties stream; | ||
| 153 | |||
| 154 | int size_of_priv; | ||
| 155 | |||
| 156 | int (*fe_ioctl_override) (struct dvb_frontend *, | ||
| 157 | unsigned int, void *, unsigned int); | ||
| 158 | }; | ||
| 159 | |||
| 160 | /** | ||
| 161 | * struct dvb_rc_legacy - old properties of remote controller | ||
| 162 | * @rc_map_table: a hard-wired array of struct rc_map_table (NULL to disable | ||
| 163 | * remote control handling). | ||
| 164 | * @rc_map_size: number of items in @rc_map_table. | ||
| 165 | * @rc_query: called to query an event event. | ||
| 166 | * @rc_interval: time in ms between two queries. | ||
| 167 | */ | ||
| 168 | struct dvb_rc_legacy { | ||
| 169 | /* remote control properties */ | ||
| 170 | #define REMOTE_NO_KEY_PRESSED 0x00 | ||
| 171 | #define REMOTE_KEY_PRESSED 0x01 | ||
| 172 | #define REMOTE_KEY_REPEAT 0x02 | ||
| 173 | struct rc_map_table *rc_map_table; | ||
| 174 | int rc_map_size; | ||
| 175 | int (*rc_query) (struct dvb_usb_device *, u32 *, int *); | ||
| 176 | int rc_interval; | ||
| 177 | }; | ||
| 178 | |||
| 179 | /** | ||
| 180 | * struct dvb_rc properties of remote controller, using rc-core | ||
| 181 | * @rc_codes: name of rc codes table | ||
| 182 | * @protocol: type of protocol(s) currently used by the driver | ||
| 183 | * @allowed_protos: protocol(s) supported by the driver | ||
| 184 | * @driver_type: Used to point if a device supports raw mode | ||
| 185 | * @change_protocol: callback to change protocol | ||
| 186 | * @rc_query: called to query an event event. | ||
| 187 | * @rc_interval: time in ms between two queries. | ||
| 188 | * @bulk_mode: device supports bulk mode for RC (disable polling mode) | ||
| 189 | */ | ||
| 190 | struct dvb_rc { | ||
| 191 | char *rc_codes; | ||
| 192 | u64 protocol; | ||
| 193 | u64 allowed_protos; | ||
| 194 | enum rc_driver_type driver_type; | ||
| 195 | int (*change_protocol)(struct rc_dev *dev, u64 rc_type); | ||
| 196 | char *module_name; | ||
| 197 | int (*rc_query) (struct dvb_usb_device *d); | ||
| 198 | int rc_interval; | ||
| 199 | bool bulk_mode; /* uses bulk mode */ | ||
| 200 | }; | ||
| 201 | |||
| 202 | /** | ||
| 203 | * enum dvb_usb_mode - Specifies if it is using a legacy driver or a new one | ||
| 204 | * based on rc-core | ||
| 205 | * This is initialized/used only inside dvb-usb-remote.c. | ||
| 206 | * It shouldn't be set by the drivers. | ||
| 207 | */ | ||
| 208 | enum dvb_usb_mode { | ||
| 209 | DVB_RC_LEGACY, | ||
| 210 | DVB_RC_CORE, | ||
| 211 | }; | ||
| 212 | |||
| 213 | /** | ||
| 214 | * struct dvb_usb_device_properties - properties of a dvb-usb-device | ||
| 215 | * @usb_ctrl: which USB device-side controller is in use. Needed for firmware | ||
| 216 | * download. | ||
| 217 | * @firmware: name of the firmware file. | ||
| 218 | * @download_firmware: called to download the firmware when the usb_ctrl is | ||
| 219 | * DEVICE_SPECIFIC. | ||
| 220 | * @no_reconnect: device doesn't do a reconnect after downloading the firmware, | ||
| 221 | * so do the warm initialization right after it | ||
| 222 | * | ||
| 223 | * @size_of_priv: how many bytes shall be allocated for the private field | ||
| 224 | * of struct dvb_usb_device. | ||
| 225 | * | ||
| 226 | * @power_ctrl: called to enable/disable power of the device. | ||
| 227 | * @read_mac_address: called to read the MAC address of the device. | ||
| 228 | * @identify_state: called to determine the state (cold or warm), when it | ||
| 229 | * is not distinguishable by the USB IDs. | ||
| 230 | * | ||
| 231 | * @rc: remote controller properties | ||
| 232 | * | ||
| 233 | * @i2c_algo: i2c_algorithm if the device has I2CoverUSB. | ||
| 234 | * | ||
| 235 | * @generic_bulk_ctrl_endpoint: most of the DVB USB devices have a generic | ||
| 236 | * endpoint which received control messages with bulk transfers. When this | ||
| 237 | * is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write- | ||
| 238 | * helper functions. | ||
| 239 | * | ||
| 240 | * @generic_bulk_ctrl_endpoint_response: some DVB USB devices use a separate | ||
| 241 | * endpoint for responses to control messages sent with bulk transfers via | ||
| 242 | * the generic_bulk_ctrl_endpoint. When this is non-zero, this will be used | ||
| 243 | * instead of the generic_bulk_ctrl_endpoint when reading usb responses in | ||
| 244 | * the dvb_usb_generic_rw helper function. | ||
| 245 | * | ||
| 246 | * @num_device_descs: number of struct dvb_usb_device_description in @devices | ||
| 247 | * @devices: array of struct dvb_usb_device_description compatibles with these | ||
| 248 | * properties. | ||
| 249 | */ | ||
| 250 | #define MAX_NO_OF_ADAPTER_PER_DEVICE 2 | ||
| 251 | struct dvb_usb_device_properties { | ||
| 252 | |||
| 253 | #define DVB_USB_IS_AN_I2C_ADAPTER 0x01 | ||
| 254 | int caps; | ||
| 255 | |||
| 256 | #define DEVICE_SPECIFIC 0 | ||
| 257 | #define CYPRESS_AN2135 1 | ||
| 258 | #define CYPRESS_AN2235 2 | ||
| 259 | #define CYPRESS_FX2 3 | ||
| 260 | int usb_ctrl; | ||
| 261 | int (*download_firmware) (struct usb_device *, const struct firmware *); | ||
| 262 | const char *firmware; | ||
| 263 | int no_reconnect; | ||
| 264 | |||
| 265 | int size_of_priv; | ||
| 266 | |||
| 267 | int num_adapters; | ||
| 268 | struct dvb_usb_adapter_properties adapter[MAX_NO_OF_ADAPTER_PER_DEVICE]; | ||
| 269 | |||
| 270 | int (*power_ctrl) (struct dvb_usb_device *, int); | ||
| 271 | int (*read_mac_address) (struct dvb_usb_device *, u8 []); | ||
| 272 | int (*identify_state) (struct usb_device *, struct dvb_usb_device_properties *, | ||
| 273 | struct dvb_usb_device_description **, int *); | ||
| 274 | |||
| 275 | struct { | ||
| 276 | enum dvb_usb_mode mode; /* Drivers shouldn't touch on it */ | ||
| 277 | struct dvb_rc_legacy legacy; | ||
| 278 | struct dvb_rc core; | ||
| 279 | } rc; | ||
| 280 | |||
| 281 | struct i2c_algorithm *i2c_algo; | ||
| 282 | |||
| 283 | int generic_bulk_ctrl_endpoint; | ||
| 284 | int generic_bulk_ctrl_endpoint_response; | ||
| 285 | |||
| 286 | int num_device_descs; | ||
| 287 | struct dvb_usb_device_description devices[12]; | ||
| 288 | }; | ||
| 289 | |||
| 290 | /** | ||
| 291 | * struct usb_data_stream - generic object of an USB stream | ||
| 292 | * @buf_num: number of buffer allocated. | ||
| 293 | * @buf_size: size of each buffer in buf_list. | ||
| 294 | * @buf_list: array containing all allocate buffers for streaming. | ||
| 295 | * @dma_addr: list of dma_addr_t for each buffer in buf_list. | ||
| 296 | * | ||
| 297 | * @urbs_initialized: number of URBs initialized. | ||
| 298 | * @urbs_submitted: number of URBs submitted. | ||
| 299 | */ | ||
| 300 | #define MAX_NO_URBS_FOR_DATA_STREAM 10 | ||
| 301 | struct usb_data_stream { | ||
| 302 | struct usb_device *udev; | ||
| 303 | struct usb_data_stream_properties props; | ||
| 304 | |||
| 305 | #define USB_STATE_INIT 0x00 | ||
| 306 | #define USB_STATE_URB_BUF 0x01 | ||
| 307 | int state; | ||
| 308 | |||
| 309 | void (*complete) (struct usb_data_stream *, u8 *, size_t); | ||
| 310 | |||
| 311 | struct urb *urb_list[MAX_NO_URBS_FOR_DATA_STREAM]; | ||
| 312 | int buf_num; | ||
| 313 | unsigned long buf_size; | ||
| 314 | u8 *buf_list[MAX_NO_URBS_FOR_DATA_STREAM]; | ||
| 315 | dma_addr_t dma_addr[MAX_NO_URBS_FOR_DATA_STREAM]; | ||
| 316 | |||
| 317 | int urbs_initialized; | ||
| 318 | int urbs_submitted; | ||
| 319 | |||
| 320 | void *user_priv; | ||
| 321 | }; | ||
| 322 | |||
| 323 | /** | ||
| 324 | * struct dvb_usb_adapter - a DVB adapter on a USB device | ||
| 325 | * @id: index of this adapter (starting with 0). | ||
| 326 | * | ||
| 327 | * @feedcount: number of reqested feeds (used for streaming-activation) | ||
| 328 | * @pid_filtering: is hardware pid_filtering used or not. | ||
| 329 | * | ||
| 330 | * @pll_addr: I2C address of the tuner for programming | ||
| 331 | * @pll_init: array containing the initialization buffer | ||
| 332 | * @pll_desc: pointer to the appropriate struct dvb_pll_desc | ||
| 333 | * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod or the board | ||
| 334 | * | ||
| 335 | * @dvb_adap: device's dvb_adapter. | ||
| 336 | * @dmxdev: device's dmxdev. | ||
| 337 | * @demux: device's software demuxer. | ||
| 338 | * @dvb_net: device's dvb_net interfaces. | ||
| 339 | * @dvb_frontend: device's frontend. | ||
| 340 | * @max_feed_count: how many feeds can be handled simultaneously by this | ||
| 341 | * device | ||
| 342 | * | ||
| 343 | * @fe_init: rerouted frontend-init (wakeup) function. | ||
| 344 | * @fe_sleep: rerouted frontend-sleep function. | ||
| 345 | * | ||
| 346 | * @stream: the usb data stream. | ||
| 347 | */ | ||
| 348 | struct dvb_usb_adapter { | ||
| 349 | struct dvb_usb_device *dev; | ||
| 350 | struct dvb_usb_adapter_properties props; | ||
| 351 | |||
| 352 | #define DVB_USB_ADAP_STATE_INIT 0x000 | ||
| 353 | #define DVB_USB_ADAP_STATE_DVB 0x001 | ||
| 354 | int state; | ||
| 355 | |||
| 356 | u8 id; | ||
| 357 | |||
| 358 | int feedcount; | ||
| 359 | int pid_filtering; | ||
| 360 | |||
| 361 | /* dvb */ | ||
| 362 | struct dvb_adapter dvb_adap; | ||
| 363 | struct dmxdev dmxdev; | ||
| 364 | struct dvb_demux demux; | ||
| 365 | struct dvb_net dvb_net; | ||
| 366 | struct dvb_frontend *fe; | ||
| 367 | int max_feed_count; | ||
| 368 | |||
| 369 | int (*fe_init) (struct dvb_frontend *); | ||
| 370 | int (*fe_sleep) (struct dvb_frontend *); | ||
| 371 | |||
| 372 | struct usb_data_stream stream; | ||
| 373 | |||
| 374 | void *priv; | ||
| 375 | }; | ||
| 376 | |||
| 377 | /** | ||
| 378 | * struct dvb_usb_device - object of a DVB USB device | ||
| 379 | * @props: copy of the struct dvb_usb_properties this device belongs to. | ||
| 380 | * @desc: pointer to the device's struct dvb_usb_device_description. | ||
| 381 | * @state: initialization and runtime state of the device. | ||
| 382 | * | ||
| 383 | * @powered: indicated whether the device is power or not. | ||
| 384 | * Powered is in/decremented for each call to modify the state. | ||
| 385 | * @udev: pointer to the device's struct usb_device. | ||
| 386 | * | ||
| 387 | * @usb_mutex: semaphore of USB control messages (reading needs two messages) | ||
| 388 | * @i2c_mutex: semaphore for i2c-transfers | ||
| 389 | * | ||
| 390 | * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB | ||
| 391 | * | ||
| 392 | * @rc_dev: rc device for the remote control (rc-core mode) | ||
| 393 | * @input_dev: input device for the remote control (legacy mode) | ||
| 394 | * @rc_query_work: struct work_struct frequent rc queries | ||
| 395 | * @last_event: last triggered event | ||
| 396 | * @last_state: last state (no, pressed, repeat) | ||
| 397 | * @owner: owner of the dvb_adapter | ||
| 398 | * @priv: private data of the actual driver (allocate by dvb-usb, size defined | ||
| 399 | * in size_of_priv of dvb_usb_properties). | ||
| 400 | */ | ||
| 401 | struct dvb_usb_device { | ||
| 402 | struct dvb_usb_device_properties props; | ||
| 403 | struct dvb_usb_device_description *desc; | ||
| 404 | |||
| 405 | struct usb_device *udev; | ||
| 406 | |||
| 407 | #define DVB_USB_STATE_INIT 0x000 | ||
| 408 | #define DVB_USB_STATE_I2C 0x001 | ||
| 409 | #define DVB_USB_STATE_DVB 0x002 | ||
| 410 | #define DVB_USB_STATE_REMOTE 0x004 | ||
| 411 | int state; | ||
| 412 | |||
| 413 | int powered; | ||
| 414 | |||
| 415 | /* locking */ | ||
| 416 | struct mutex usb_mutex; | ||
| 417 | |||
| 418 | /* i2c */ | ||
| 419 | struct mutex i2c_mutex; | ||
| 420 | struct i2c_adapter i2c_adap; | ||
| 421 | |||
| 422 | int num_adapters_initialized; | ||
| 423 | struct dvb_usb_adapter adapter[MAX_NO_OF_ADAPTER_PER_DEVICE]; | ||
| 424 | |||
| 425 | /* remote control */ | ||
| 426 | struct rc_dev *rc_dev; | ||
| 427 | struct input_dev *input_dev; | ||
| 428 | char rc_phys[64]; | ||
| 429 | struct delayed_work rc_query_work; | ||
| 430 | u32 last_event; | ||
| 431 | int last_state; | ||
| 432 | |||
| 433 | struct module *owner; | ||
| 434 | |||
| 435 | void *priv; | ||
| 436 | }; | ||
| 437 | |||
| 438 | extern int dvb_usb_device_init(struct usb_interface *, | ||
| 439 | struct dvb_usb_device_properties *, | ||
| 440 | struct module *, struct dvb_usb_device **, | ||
| 441 | short *adapter_nums); | ||
| 442 | extern void dvb_usb_device_exit(struct usb_interface *); | ||
| 443 | |||
| 444 | /* the generic read/write method for device control */ | ||
| 445 | extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16,int); | ||
| 446 | extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16); | ||
| 447 | |||
| 448 | /* commonly used remote control parsing */ | ||
| 449 | extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *); | ||
| 450 | |||
| 451 | /* commonly used firmware download types and function */ | ||
| 452 | struct hexline { | ||
| 453 | u8 len; | ||
| 454 | u32 addr; | ||
| 455 | u8 type; | ||
| 456 | u8 data[255]; | ||
| 457 | u8 chk; | ||
| 458 | }; | ||
| 459 | extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type); | ||
| 460 | extern int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos); | ||
| 461 | |||
| 462 | |||
| 463 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c new file mode 100644 index 00000000000..058b2318abe --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dw2102.c | |||
| @@ -0,0 +1,1940 @@ | |||
| 1 | /* DVB USB framework compliant Linux driver for the | ||
| 2 | * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, | ||
| 3 | * TeVii S600, S630, S650, S660, S480, | ||
| 4 | * Prof 1100, 7500, | ||
| 5 | * Geniatech SU3000 Cards | ||
| 6 | * Copyright (C) 2008-2011 Igor M. Liplianin (liplianin@me.by) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation, version 2. | ||
| 11 | * | ||
| 12 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 13 | */ | ||
| 14 | #include "dw2102.h" | ||
| 15 | #include "si21xx.h" | ||
| 16 | #include "stv0299.h" | ||
| 17 | #include "z0194a.h" | ||
| 18 | #include "stv0288.h" | ||
| 19 | #include "stb6000.h" | ||
| 20 | #include "eds1547.h" | ||
| 21 | #include "cx24116.h" | ||
| 22 | #include "tda1002x.h" | ||
| 23 | #include "mt312.h" | ||
| 24 | #include "zl10039.h" | ||
| 25 | #include "ds3000.h" | ||
| 26 | #include "stv0900.h" | ||
| 27 | #include "stv6110.h" | ||
| 28 | #include "stb6100.h" | ||
| 29 | #include "stb6100_proc.h" | ||
| 30 | |||
| 31 | #ifndef USB_PID_DW2102 | ||
| 32 | #define USB_PID_DW2102 0x2102 | ||
| 33 | #endif | ||
| 34 | |||
| 35 | #ifndef USB_PID_DW2104 | ||
| 36 | #define USB_PID_DW2104 0x2104 | ||
| 37 | #endif | ||
| 38 | |||
| 39 | #ifndef USB_PID_DW3101 | ||
| 40 | #define USB_PID_DW3101 0x3101 | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #ifndef USB_PID_CINERGY_S | ||
| 44 | #define USB_PID_CINERGY_S 0x0064 | ||
| 45 | #endif | ||
| 46 | |||
| 47 | #ifndef USB_PID_TEVII_S630 | ||
| 48 | #define USB_PID_TEVII_S630 0xd630 | ||
| 49 | #endif | ||
| 50 | |||
| 51 | #ifndef USB_PID_TEVII_S650 | ||
| 52 | #define USB_PID_TEVII_S650 0xd650 | ||
| 53 | #endif | ||
| 54 | |||
| 55 | #ifndef USB_PID_TEVII_S660 | ||
| 56 | #define USB_PID_TEVII_S660 0xd660 | ||
| 57 | #endif | ||
| 58 | |||
| 59 | #ifndef USB_PID_TEVII_S480_1 | ||
| 60 | #define USB_PID_TEVII_S480_1 0xd481 | ||
| 61 | #endif | ||
| 62 | |||
| 63 | #ifndef USB_PID_TEVII_S480_2 | ||
| 64 | #define USB_PID_TEVII_S480_2 0xd482 | ||
| 65 | #endif | ||
| 66 | |||
| 67 | #ifndef USB_PID_PROF_1100 | ||
| 68 | #define USB_PID_PROF_1100 0xb012 | ||
| 69 | #endif | ||
| 70 | |||
| 71 | #define DW210X_READ_MSG 0 | ||
| 72 | #define DW210X_WRITE_MSG 1 | ||
| 73 | |||
| 74 | #define REG_1F_SYMBOLRATE_BYTE0 0x1f | ||
| 75 | #define REG_20_SYMBOLRATE_BYTE1 0x20 | ||
| 76 | #define REG_21_SYMBOLRATE_BYTE2 0x21 | ||
| 77 | /* on my own*/ | ||
| 78 | #define DW2102_VOLTAGE_CTRL (0x1800) | ||
| 79 | #define SU3000_STREAM_CTRL (0x1900) | ||
| 80 | #define DW2102_RC_QUERY (0x1a00) | ||
| 81 | #define DW2102_LED_CTRL (0x1b00) | ||
| 82 | |||
| 83 | #define err_str "did not find the firmware file. (%s) " \ | ||
| 84 | "Please see linux/Documentation/dvb/ for more details " \ | ||
| 85 | "on firmware-problems." | ||
| 86 | |||
| 87 | struct rc_map_dvb_usb_table_table { | ||
| 88 | struct rc_map_table *rc_keys; | ||
| 89 | int rc_keys_size; | ||
| 90 | }; | ||
| 91 | |||
| 92 | struct su3000_state { | ||
| 93 | u8 initialized; | ||
| 94 | }; | ||
| 95 | |||
| 96 | struct s6x0_state { | ||
| 97 | int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v); | ||
| 98 | }; | ||
| 99 | |||
| 100 | /* debug */ | ||
| 101 | static int dvb_usb_dw2102_debug; | ||
| 102 | module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); | ||
| 103 | MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))." | ||
| 104 | DVB_USB_DEBUG_STATUS); | ||
| 105 | |||
| 106 | /* keymaps */ | ||
| 107 | static int ir_keymap; | ||
| 108 | module_param_named(keymap, ir_keymap, int, 0644); | ||
| 109 | MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ..." | ||
| 110 | " 256=none"); | ||
| 111 | |||
| 112 | /* demod probe */ | ||
| 113 | static int demod_probe = 1; | ||
| 114 | module_param_named(demod, demod_probe, int, 0644); | ||
| 115 | MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 " | ||
| 116 | "4=stv0903+stb6100(or-able))."); | ||
| 117 | |||
| 118 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 119 | |||
| 120 | static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, | ||
| 121 | u16 index, u8 * data, u16 len, int flags) | ||
| 122 | { | ||
| 123 | int ret; | ||
| 124 | u8 *u8buf; | ||
| 125 | unsigned int pipe = (flags == DW210X_READ_MSG) ? | ||
| 126 | usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); | ||
| 127 | u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; | ||
| 128 | |||
| 129 | u8buf = kmalloc(len, GFP_KERNEL); | ||
| 130 | if (!u8buf) | ||
| 131 | return -ENOMEM; | ||
| 132 | |||
| 133 | |||
| 134 | if (flags == DW210X_WRITE_MSG) | ||
| 135 | memcpy(u8buf, data, len); | ||
| 136 | ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, | ||
| 137 | value, index , u8buf, len, 2000); | ||
| 138 | |||
| 139 | if (flags == DW210X_READ_MSG) | ||
| 140 | memcpy(data, u8buf, len); | ||
| 141 | |||
| 142 | kfree(u8buf); | ||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* I2C */ | ||
| 147 | static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 148 | int num) | ||
| 149 | { | ||
| 150 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 151 | int i = 0, ret = 0; | ||
| 152 | u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; | ||
| 153 | u16 value; | ||
| 154 | |||
| 155 | if (!d) | ||
| 156 | return -ENODEV; | ||
| 157 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 158 | return -EAGAIN; | ||
| 159 | |||
| 160 | switch (num) { | ||
| 161 | case 2: | ||
| 162 | /* read stv0299 register */ | ||
| 163 | value = msg[0].buf[0];/* register */ | ||
| 164 | for (i = 0; i < msg[1].len; i++) { | ||
| 165 | ret = dw210x_op_rw(d->udev, 0xb5, value + i, 0, | ||
| 166 | buf6, 2, DW210X_READ_MSG); | ||
| 167 | msg[1].buf[i] = buf6[0]; | ||
| 168 | } | ||
| 169 | break; | ||
| 170 | case 1: | ||
| 171 | switch (msg[0].addr) { | ||
| 172 | case 0x68: | ||
| 173 | /* write to stv0299 register */ | ||
| 174 | buf6[0] = 0x2a; | ||
| 175 | buf6[1] = msg[0].buf[0]; | ||
| 176 | buf6[2] = msg[0].buf[1]; | ||
| 177 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
| 178 | buf6, 3, DW210X_WRITE_MSG); | ||
| 179 | break; | ||
| 180 | case 0x60: | ||
| 181 | if (msg[0].flags == 0) { | ||
| 182 | /* write to tuner pll */ | ||
| 183 | buf6[0] = 0x2c; | ||
| 184 | buf6[1] = 5; | ||
| 185 | buf6[2] = 0xc0; | ||
| 186 | buf6[3] = msg[0].buf[0]; | ||
| 187 | buf6[4] = msg[0].buf[1]; | ||
| 188 | buf6[5] = msg[0].buf[2]; | ||
| 189 | buf6[6] = msg[0].buf[3]; | ||
| 190 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
| 191 | buf6, 7, DW210X_WRITE_MSG); | ||
| 192 | } else { | ||
| 193 | /* read from tuner */ | ||
| 194 | ret = dw210x_op_rw(d->udev, 0xb5, 0, 0, | ||
| 195 | buf6, 1, DW210X_READ_MSG); | ||
| 196 | msg[0].buf[0] = buf6[0]; | ||
| 197 | } | ||
| 198 | break; | ||
| 199 | case (DW2102_RC_QUERY): | ||
| 200 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
| 201 | buf6, 2, DW210X_READ_MSG); | ||
| 202 | msg[0].buf[0] = buf6[0]; | ||
| 203 | msg[0].buf[1] = buf6[1]; | ||
| 204 | break; | ||
| 205 | case (DW2102_VOLTAGE_CTRL): | ||
| 206 | buf6[0] = 0x30; | ||
| 207 | buf6[1] = msg[0].buf[0]; | ||
| 208 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
| 209 | buf6, 2, DW210X_WRITE_MSG); | ||
| 210 | break; | ||
| 211 | } | ||
| 212 | |||
| 213 | break; | ||
| 214 | } | ||
| 215 | |||
| 216 | mutex_unlock(&d->i2c_mutex); | ||
| 217 | return num; | ||
| 218 | } | ||
| 219 | |||
| 220 | static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, | ||
| 221 | struct i2c_msg msg[], int num) | ||
| 222 | { | ||
| 223 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 224 | int ret = 0; | ||
| 225 | u8 buf6[] = {0, 0, 0, 0, 0, 0, 0}; | ||
| 226 | |||
| 227 | if (!d) | ||
| 228 | return -ENODEV; | ||
| 229 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 230 | return -EAGAIN; | ||
| 231 | |||
| 232 | switch (num) { | ||
| 233 | case 2: | ||
| 234 | /* read si2109 register by number */ | ||
| 235 | buf6[0] = msg[0].addr << 1; | ||
| 236 | buf6[1] = msg[0].len; | ||
| 237 | buf6[2] = msg[0].buf[0]; | ||
| 238 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 239 | buf6, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 240 | /* read si2109 register */ | ||
| 241 | ret = dw210x_op_rw(d->udev, 0xc3, 0xd0, 0, | ||
| 242 | buf6, msg[1].len + 2, DW210X_READ_MSG); | ||
| 243 | memcpy(msg[1].buf, buf6 + 2, msg[1].len); | ||
| 244 | |||
| 245 | break; | ||
| 246 | case 1: | ||
| 247 | switch (msg[0].addr) { | ||
| 248 | case 0x68: | ||
| 249 | /* write to si2109 register */ | ||
| 250 | buf6[0] = msg[0].addr << 1; | ||
| 251 | buf6[1] = msg[0].len; | ||
| 252 | memcpy(buf6 + 2, msg[0].buf, msg[0].len); | ||
| 253 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6, | ||
| 254 | msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 255 | break; | ||
| 256 | case(DW2102_RC_QUERY): | ||
| 257 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
| 258 | buf6, 2, DW210X_READ_MSG); | ||
| 259 | msg[0].buf[0] = buf6[0]; | ||
| 260 | msg[0].buf[1] = buf6[1]; | ||
| 261 | break; | ||
| 262 | case(DW2102_VOLTAGE_CTRL): | ||
| 263 | buf6[0] = 0x30; | ||
| 264 | buf6[1] = msg[0].buf[0]; | ||
| 265 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
| 266 | buf6, 2, DW210X_WRITE_MSG); | ||
| 267 | break; | ||
| 268 | } | ||
| 269 | break; | ||
| 270 | } | ||
| 271 | |||
| 272 | mutex_unlock(&d->i2c_mutex); | ||
| 273 | return num; | ||
| 274 | } | ||
| 275 | |||
| 276 | static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) | ||
| 277 | { | ||
| 278 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 279 | int ret = 0; | ||
| 280 | |||
| 281 | if (!d) | ||
| 282 | return -ENODEV; | ||
| 283 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 284 | return -EAGAIN; | ||
| 285 | |||
| 286 | switch (num) { | ||
| 287 | case 2: { | ||
| 288 | /* read */ | ||
| 289 | /* first write first register number */ | ||
| 290 | u8 ibuf[msg[1].len + 2], obuf[3]; | ||
| 291 | obuf[0] = msg[0].addr << 1; | ||
| 292 | obuf[1] = msg[0].len; | ||
| 293 | obuf[2] = msg[0].buf[0]; | ||
| 294 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 295 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 296 | /* second read registers */ | ||
| 297 | ret = dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0, | ||
| 298 | ibuf, msg[1].len + 2, DW210X_READ_MSG); | ||
| 299 | memcpy(msg[1].buf, ibuf + 2, msg[1].len); | ||
| 300 | |||
| 301 | break; | ||
| 302 | } | ||
| 303 | case 1: | ||
| 304 | switch (msg[0].addr) { | ||
| 305 | case 0x68: { | ||
| 306 | /* write to register */ | ||
| 307 | u8 obuf[msg[0].len + 2]; | ||
| 308 | obuf[0] = msg[0].addr << 1; | ||
| 309 | obuf[1] = msg[0].len; | ||
| 310 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
| 311 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 312 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 313 | break; | ||
| 314 | } | ||
| 315 | case 0x61: { | ||
| 316 | /* write to tuner */ | ||
| 317 | u8 obuf[msg[0].len + 2]; | ||
| 318 | obuf[0] = msg[0].addr << 1; | ||
| 319 | obuf[1] = msg[0].len; | ||
| 320 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
| 321 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 322 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 323 | break; | ||
| 324 | } | ||
| 325 | case(DW2102_RC_QUERY): { | ||
| 326 | u8 ibuf[2]; | ||
| 327 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
| 328 | ibuf, 2, DW210X_READ_MSG); | ||
| 329 | memcpy(msg[0].buf, ibuf , 2); | ||
| 330 | break; | ||
| 331 | } | ||
| 332 | case(DW2102_VOLTAGE_CTRL): { | ||
| 333 | u8 obuf[2]; | ||
| 334 | obuf[0] = 0x30; | ||
| 335 | obuf[1] = msg[0].buf[0]; | ||
| 336 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
| 337 | obuf, 2, DW210X_WRITE_MSG); | ||
| 338 | break; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | |||
| 342 | break; | ||
| 343 | } | ||
| 344 | |||
| 345 | mutex_unlock(&d->i2c_mutex); | ||
| 346 | return num; | ||
| 347 | } | ||
| 348 | |||
| 349 | static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) | ||
| 350 | { | ||
| 351 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 352 | int ret = 0; | ||
| 353 | int len, i, j; | ||
| 354 | |||
| 355 | if (!d) | ||
| 356 | return -ENODEV; | ||
| 357 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 358 | return -EAGAIN; | ||
| 359 | |||
| 360 | for (j = 0; j < num; j++) { | ||
| 361 | switch (msg[j].addr) { | ||
| 362 | case(DW2102_RC_QUERY): { | ||
| 363 | u8 ibuf[2]; | ||
| 364 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
| 365 | ibuf, 2, DW210X_READ_MSG); | ||
| 366 | memcpy(msg[j].buf, ibuf , 2); | ||
| 367 | break; | ||
| 368 | } | ||
| 369 | case(DW2102_VOLTAGE_CTRL): { | ||
| 370 | u8 obuf[2]; | ||
| 371 | obuf[0] = 0x30; | ||
| 372 | obuf[1] = msg[j].buf[0]; | ||
| 373 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
| 374 | obuf, 2, DW210X_WRITE_MSG); | ||
| 375 | break; | ||
| 376 | } | ||
| 377 | /*case 0x55: cx24116 | ||
| 378 | case 0x6a: stv0903 | ||
| 379 | case 0x68: ds3000, stv0903 | ||
| 380 | case 0x60: ts2020, stv6110, stb6100 */ | ||
| 381 | default: { | ||
| 382 | if (msg[j].flags == I2C_M_RD) { | ||
| 383 | /* read registers */ | ||
| 384 | u8 ibuf[msg[j].len + 2]; | ||
| 385 | ret = dw210x_op_rw(d->udev, 0xc3, | ||
| 386 | (msg[j].addr << 1) + 1, 0, | ||
| 387 | ibuf, msg[j].len + 2, | ||
| 388 | DW210X_READ_MSG); | ||
| 389 | memcpy(msg[j].buf, ibuf + 2, msg[j].len); | ||
| 390 | mdelay(10); | ||
| 391 | } else if (((msg[j].buf[0] == 0xb0) && | ||
| 392 | (msg[j].addr == 0x68)) || | ||
| 393 | ((msg[j].buf[0] == 0xf7) && | ||
| 394 | (msg[j].addr == 0x55))) { | ||
| 395 | /* write firmware */ | ||
| 396 | u8 obuf[19]; | ||
| 397 | obuf[0] = msg[j].addr << 1; | ||
| 398 | obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len); | ||
| 399 | obuf[2] = msg[j].buf[0]; | ||
| 400 | len = msg[j].len - 1; | ||
| 401 | i = 1; | ||
| 402 | do { | ||
| 403 | memcpy(obuf + 3, msg[j].buf + i, | ||
| 404 | (len > 16 ? 16 : len)); | ||
| 405 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 406 | obuf, (len > 16 ? 16 : len) + 3, | ||
| 407 | DW210X_WRITE_MSG); | ||
| 408 | i += 16; | ||
| 409 | len -= 16; | ||
| 410 | } while (len > 0); | ||
| 411 | } else { | ||
| 412 | /* write registers */ | ||
| 413 | u8 obuf[msg[j].len + 2]; | ||
| 414 | obuf[0] = msg[j].addr << 1; | ||
| 415 | obuf[1] = msg[j].len; | ||
| 416 | memcpy(obuf + 2, msg[j].buf, msg[j].len); | ||
| 417 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 418 | obuf, msg[j].len + 2, | ||
| 419 | DW210X_WRITE_MSG); | ||
| 420 | } | ||
| 421 | break; | ||
| 422 | } | ||
| 423 | } | ||
| 424 | |||
| 425 | } | ||
| 426 | |||
| 427 | mutex_unlock(&d->i2c_mutex); | ||
| 428 | return num; | ||
| 429 | } | ||
| 430 | |||
| 431 | static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 432 | int num) | ||
| 433 | { | ||
| 434 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 435 | int ret = 0, i; | ||
| 436 | |||
| 437 | if (!d) | ||
| 438 | return -ENODEV; | ||
| 439 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 440 | return -EAGAIN; | ||
| 441 | |||
| 442 | switch (num) { | ||
| 443 | case 2: { | ||
| 444 | /* read */ | ||
| 445 | /* first write first register number */ | ||
| 446 | u8 ibuf[msg[1].len + 2], obuf[3]; | ||
| 447 | obuf[0] = msg[0].addr << 1; | ||
| 448 | obuf[1] = msg[0].len; | ||
| 449 | obuf[2] = msg[0].buf[0]; | ||
| 450 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 451 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 452 | /* second read registers */ | ||
| 453 | ret = dw210x_op_rw(d->udev, 0xc3, 0x19 , 0, | ||
| 454 | ibuf, msg[1].len + 2, DW210X_READ_MSG); | ||
| 455 | memcpy(msg[1].buf, ibuf + 2, msg[1].len); | ||
| 456 | |||
| 457 | break; | ||
| 458 | } | ||
| 459 | case 1: | ||
| 460 | switch (msg[0].addr) { | ||
| 461 | case 0x60: | ||
| 462 | case 0x0c: { | ||
| 463 | /* write to register */ | ||
| 464 | u8 obuf[msg[0].len + 2]; | ||
| 465 | obuf[0] = msg[0].addr << 1; | ||
| 466 | obuf[1] = msg[0].len; | ||
| 467 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
| 468 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
| 469 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
| 470 | break; | ||
| 471 | } | ||
| 472 | case(DW2102_RC_QUERY): { | ||
| 473 | u8 ibuf[2]; | ||
| 474 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
| 475 | ibuf, 2, DW210X_READ_MSG); | ||
| 476 | memcpy(msg[0].buf, ibuf , 2); | ||
| 477 | break; | ||
| 478 | } | ||
| 479 | } | ||
| 480 | |||
| 481 | break; | ||
| 482 | } | ||
| 483 | |||
| 484 | for (i = 0; i < num; i++) { | ||
| 485 | deb_xfer("%02x:%02x: %s ", i, msg[i].addr, | ||
| 486 | msg[i].flags == 0 ? ">>>" : "<<<"); | ||
| 487 | debug_dump(msg[i].buf, msg[i].len, deb_xfer); | ||
| 488 | } | ||
| 489 | |||
| 490 | mutex_unlock(&d->i2c_mutex); | ||
| 491 | return num; | ||
| 492 | } | ||
| 493 | |||
| 494 | static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 495 | int num) | ||
| 496 | { | ||
| 497 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 498 | struct usb_device *udev; | ||
| 499 | int ret = 0; | ||
| 500 | int len, i, j; | ||
| 501 | |||
| 502 | if (!d) | ||
| 503 | return -ENODEV; | ||
| 504 | udev = d->udev; | ||
| 505 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 506 | return -EAGAIN; | ||
| 507 | |||
| 508 | for (j = 0; j < num; j++) { | ||
| 509 | switch (msg[j].addr) { | ||
| 510 | case (DW2102_RC_QUERY): { | ||
| 511 | u8 ibuf[5]; | ||
| 512 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
| 513 | ibuf, 5, DW210X_READ_MSG); | ||
| 514 | memcpy(msg[j].buf, ibuf + 3, 2); | ||
| 515 | break; | ||
| 516 | } | ||
| 517 | case (DW2102_VOLTAGE_CTRL): { | ||
| 518 | u8 obuf[2]; | ||
| 519 | |||
| 520 | obuf[0] = 1; | ||
| 521 | obuf[1] = msg[j].buf[1];/* off-on */ | ||
| 522 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, | ||
| 523 | obuf, 2, DW210X_WRITE_MSG); | ||
| 524 | obuf[0] = 3; | ||
| 525 | obuf[1] = msg[j].buf[0];/* 13v-18v */ | ||
| 526 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, | ||
| 527 | obuf, 2, DW210X_WRITE_MSG); | ||
| 528 | break; | ||
| 529 | } | ||
| 530 | case (DW2102_LED_CTRL): { | ||
| 531 | u8 obuf[2]; | ||
| 532 | |||
| 533 | obuf[0] = 5; | ||
| 534 | obuf[1] = msg[j].buf[0]; | ||
| 535 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, | ||
| 536 | obuf, 2, DW210X_WRITE_MSG); | ||
| 537 | break; | ||
| 538 | } | ||
| 539 | /*case 0x55: cx24116 | ||
| 540 | case 0x6a: stv0903 | ||
| 541 | case 0x68: ds3000, stv0903 | ||
| 542 | case 0x60: ts2020, stv6110, stb6100 | ||
| 543 | case 0xa0: eeprom */ | ||
| 544 | default: { | ||
| 545 | if (msg[j].flags == I2C_M_RD) { | ||
| 546 | /* read registers */ | ||
| 547 | u8 ibuf[msg[j].len]; | ||
| 548 | ret = dw210x_op_rw(d->udev, 0x91, 0, 0, | ||
| 549 | ibuf, msg[j].len, | ||
| 550 | DW210X_READ_MSG); | ||
| 551 | memcpy(msg[j].buf, ibuf, msg[j].len); | ||
| 552 | break; | ||
| 553 | } else if ((msg[j].buf[0] == 0xb0) && | ||
| 554 | (msg[j].addr == 0x68)) { | ||
| 555 | /* write firmware */ | ||
| 556 | u8 obuf[19]; | ||
| 557 | obuf[0] = (msg[j].len > 16 ? | ||
| 558 | 18 : msg[j].len + 1); | ||
| 559 | obuf[1] = msg[j].addr << 1; | ||
| 560 | obuf[2] = msg[j].buf[0]; | ||
| 561 | len = msg[j].len - 1; | ||
| 562 | i = 1; | ||
| 563 | do { | ||
| 564 | memcpy(obuf + 3, msg[j].buf + i, | ||
| 565 | (len > 16 ? 16 : len)); | ||
| 566 | ret = dw210x_op_rw(d->udev, 0x80, 0, 0, | ||
| 567 | obuf, (len > 16 ? 16 : len) + 3, | ||
| 568 | DW210X_WRITE_MSG); | ||
| 569 | i += 16; | ||
| 570 | len -= 16; | ||
| 571 | } while (len > 0); | ||
| 572 | } else if (j < (num - 1)) { | ||
| 573 | /* write register addr before read */ | ||
| 574 | u8 obuf[msg[j].len + 2]; | ||
| 575 | obuf[0] = msg[j + 1].len; | ||
| 576 | obuf[1] = (msg[j].addr << 1); | ||
| 577 | memcpy(obuf + 2, msg[j].buf, msg[j].len); | ||
| 578 | ret = dw210x_op_rw(d->udev, | ||
| 579 | udev->descriptor.idProduct == | ||
| 580 | 0x7500 ? 0x92 : 0x90, 0, 0, | ||
| 581 | obuf, msg[j].len + 2, | ||
| 582 | DW210X_WRITE_MSG); | ||
| 583 | break; | ||
| 584 | } else { | ||
| 585 | /* write registers */ | ||
| 586 | u8 obuf[msg[j].len + 2]; | ||
| 587 | obuf[0] = msg[j].len + 1; | ||
| 588 | obuf[1] = (msg[j].addr << 1); | ||
| 589 | memcpy(obuf + 2, msg[j].buf, msg[j].len); | ||
| 590 | ret = dw210x_op_rw(d->udev, 0x80, 0, 0, | ||
| 591 | obuf, msg[j].len + 2, | ||
| 592 | DW210X_WRITE_MSG); | ||
| 593 | break; | ||
| 594 | } | ||
| 595 | break; | ||
| 596 | } | ||
| 597 | } | ||
| 598 | } | ||
| 599 | |||
| 600 | mutex_unlock(&d->i2c_mutex); | ||
| 601 | return num; | ||
| 602 | } | ||
| 603 | |||
| 604 | static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 605 | int num) | ||
| 606 | { | ||
| 607 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 608 | u8 obuf[0x40], ibuf[0x40]; | ||
| 609 | |||
| 610 | if (!d) | ||
| 611 | return -ENODEV; | ||
| 612 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 613 | return -EAGAIN; | ||
| 614 | |||
| 615 | switch (num) { | ||
| 616 | case 1: | ||
| 617 | switch (msg[0].addr) { | ||
| 618 | case SU3000_STREAM_CTRL: | ||
| 619 | obuf[0] = msg[0].buf[0] + 0x36; | ||
| 620 | obuf[1] = 3; | ||
| 621 | obuf[2] = 0; | ||
| 622 | if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 0, 0) < 0) | ||
| 623 | err("i2c transfer failed."); | ||
| 624 | break; | ||
| 625 | case DW2102_RC_QUERY: | ||
| 626 | obuf[0] = 0x10; | ||
| 627 | if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 2, 0) < 0) | ||
| 628 | err("i2c transfer failed."); | ||
| 629 | msg[0].buf[1] = ibuf[0]; | ||
| 630 | msg[0].buf[0] = ibuf[1]; | ||
| 631 | break; | ||
| 632 | default: | ||
| 633 | /* always i2c write*/ | ||
| 634 | obuf[0] = 0x08; | ||
| 635 | obuf[1] = msg[0].addr; | ||
| 636 | obuf[2] = msg[0].len; | ||
| 637 | |||
| 638 | memcpy(&obuf[3], msg[0].buf, msg[0].len); | ||
| 639 | |||
| 640 | if (dvb_usb_generic_rw(d, obuf, msg[0].len + 3, | ||
| 641 | ibuf, 1, 0) < 0) | ||
| 642 | err("i2c transfer failed."); | ||
| 643 | |||
| 644 | } | ||
| 645 | break; | ||
| 646 | case 2: | ||
| 647 | /* always i2c read */ | ||
| 648 | obuf[0] = 0x09; | ||
| 649 | obuf[1] = msg[0].len; | ||
| 650 | obuf[2] = msg[1].len; | ||
| 651 | obuf[3] = msg[0].addr; | ||
| 652 | memcpy(&obuf[4], msg[0].buf, msg[0].len); | ||
| 653 | |||
| 654 | if (dvb_usb_generic_rw(d, obuf, msg[0].len + 4, | ||
| 655 | ibuf, msg[1].len + 1, 0) < 0) | ||
| 656 | err("i2c transfer failed."); | ||
| 657 | |||
| 658 | memcpy(msg[1].buf, &ibuf[1], msg[1].len); | ||
| 659 | break; | ||
| 660 | default: | ||
| 661 | warn("more than 2 i2c messages at a time is not handled yet."); | ||
| 662 | break; | ||
| 663 | } | ||
| 664 | mutex_unlock(&d->i2c_mutex); | ||
| 665 | return num; | ||
| 666 | } | ||
| 667 | |||
| 668 | static u32 dw210x_i2c_func(struct i2c_adapter *adapter) | ||
| 669 | { | ||
| 670 | return I2C_FUNC_I2C; | ||
| 671 | } | ||
| 672 | |||
| 673 | static struct i2c_algorithm dw2102_i2c_algo = { | ||
| 674 | .master_xfer = dw2102_i2c_transfer, | ||
| 675 | .functionality = dw210x_i2c_func, | ||
| 676 | }; | ||
| 677 | |||
| 678 | static struct i2c_algorithm dw2102_serit_i2c_algo = { | ||
| 679 | .master_xfer = dw2102_serit_i2c_transfer, | ||
| 680 | .functionality = dw210x_i2c_func, | ||
| 681 | }; | ||
| 682 | |||
| 683 | static struct i2c_algorithm dw2102_earda_i2c_algo = { | ||
| 684 | .master_xfer = dw2102_earda_i2c_transfer, | ||
| 685 | .functionality = dw210x_i2c_func, | ||
| 686 | }; | ||
| 687 | |||
| 688 | static struct i2c_algorithm dw2104_i2c_algo = { | ||
| 689 | .master_xfer = dw2104_i2c_transfer, | ||
| 690 | .functionality = dw210x_i2c_func, | ||
| 691 | }; | ||
| 692 | |||
| 693 | static struct i2c_algorithm dw3101_i2c_algo = { | ||
| 694 | .master_xfer = dw3101_i2c_transfer, | ||
| 695 | .functionality = dw210x_i2c_func, | ||
| 696 | }; | ||
| 697 | |||
| 698 | static struct i2c_algorithm s6x0_i2c_algo = { | ||
| 699 | .master_xfer = s6x0_i2c_transfer, | ||
| 700 | .functionality = dw210x_i2c_func, | ||
| 701 | }; | ||
| 702 | |||
| 703 | static struct i2c_algorithm su3000_i2c_algo = { | ||
| 704 | .master_xfer = su3000_i2c_transfer, | ||
| 705 | .functionality = dw210x_i2c_func, | ||
| 706 | }; | ||
| 707 | |||
| 708 | static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | ||
| 709 | { | ||
| 710 | int i; | ||
| 711 | u8 ibuf[] = {0, 0}; | ||
| 712 | u8 eeprom[256], eepromline[16]; | ||
| 713 | |||
| 714 | for (i = 0; i < 256; i++) { | ||
| 715 | if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) { | ||
| 716 | err("read eeprom failed."); | ||
| 717 | return -1; | ||
| 718 | } else { | ||
| 719 | eepromline[i%16] = ibuf[0]; | ||
| 720 | eeprom[i] = ibuf[0]; | ||
| 721 | } | ||
| 722 | if ((i % 16) == 15) { | ||
| 723 | deb_xfer("%02x: ", i - 15); | ||
| 724 | debug_dump(eepromline, 16, deb_xfer); | ||
| 725 | } | ||
| 726 | } | ||
| 727 | |||
| 728 | memcpy(mac, eeprom + 8, 6); | ||
| 729 | return 0; | ||
| 730 | }; | ||
| 731 | |||
| 732 | static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | ||
| 733 | { | ||
| 734 | int i, ret; | ||
| 735 | u8 ibuf[] = { 0 }, obuf[] = { 0 }; | ||
| 736 | u8 eeprom[256], eepromline[16]; | ||
| 737 | struct i2c_msg msg[] = { | ||
| 738 | { | ||
| 739 | .addr = 0xa0 >> 1, | ||
| 740 | .flags = 0, | ||
| 741 | .buf = obuf, | ||
| 742 | .len = 1, | ||
| 743 | }, { | ||
| 744 | .addr = 0xa0 >> 1, | ||
| 745 | .flags = I2C_M_RD, | ||
| 746 | .buf = ibuf, | ||
| 747 | .len = 1, | ||
| 748 | } | ||
| 749 | }; | ||
| 750 | |||
| 751 | for (i = 0; i < 256; i++) { | ||
| 752 | obuf[0] = i; | ||
| 753 | ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2); | ||
| 754 | if (ret != 2) { | ||
| 755 | err("read eeprom failed."); | ||
| 756 | return -1; | ||
| 757 | } else { | ||
| 758 | eepromline[i % 16] = ibuf[0]; | ||
| 759 | eeprom[i] = ibuf[0]; | ||
| 760 | } | ||
| 761 | |||
| 762 | if ((i % 16) == 15) { | ||
| 763 | deb_xfer("%02x: ", i - 15); | ||
| 764 | debug_dump(eepromline, 16, deb_xfer); | ||
| 765 | } | ||
| 766 | } | ||
| 767 | |||
| 768 | memcpy(mac, eeprom + 16, 6); | ||
| 769 | return 0; | ||
| 770 | }; | ||
| 771 | |||
| 772 | static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 773 | { | ||
| 774 | static u8 command_start[] = {0x00}; | ||
| 775 | static u8 command_stop[] = {0x01}; | ||
| 776 | struct i2c_msg msg = { | ||
| 777 | .addr = SU3000_STREAM_CTRL, | ||
| 778 | .flags = 0, | ||
| 779 | .buf = onoff ? command_start : command_stop, | ||
| 780 | .len = 1 | ||
| 781 | }; | ||
| 782 | |||
| 783 | i2c_transfer(&adap->dev->i2c_adap, &msg, 1); | ||
| 784 | |||
| 785 | return 0; | ||
| 786 | } | ||
| 787 | |||
| 788 | static int su3000_power_ctrl(struct dvb_usb_device *d, int i) | ||
| 789 | { | ||
| 790 | struct su3000_state *state = (struct su3000_state *)d->priv; | ||
| 791 | u8 obuf[] = {0xde, 0}; | ||
| 792 | |||
| 793 | info("%s: %d, initialized %d\n", __func__, i, state->initialized); | ||
| 794 | |||
| 795 | if (i && !state->initialized) { | ||
| 796 | state->initialized = 1; | ||
| 797 | /* reset board */ | ||
| 798 | dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0); | ||
| 799 | } | ||
| 800 | |||
| 801 | return 0; | ||
| 802 | } | ||
| 803 | |||
| 804 | static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | ||
| 805 | { | ||
| 806 | int i; | ||
| 807 | u8 obuf[] = { 0x1f, 0xf0 }; | ||
| 808 | u8 ibuf[] = { 0 }; | ||
| 809 | struct i2c_msg msg[] = { | ||
| 810 | { | ||
| 811 | .addr = 0x51, | ||
| 812 | .flags = 0, | ||
| 813 | .buf = obuf, | ||
| 814 | .len = 2, | ||
| 815 | }, { | ||
| 816 | .addr = 0x51, | ||
| 817 | .flags = I2C_M_RD, | ||
| 818 | .buf = ibuf, | ||
| 819 | .len = 1, | ||
| 820 | |||
| 821 | } | ||
| 822 | }; | ||
| 823 | |||
| 824 | for (i = 0; i < 6; i++) { | ||
| 825 | obuf[1] = 0xf0 + i; | ||
| 826 | if (i2c_transfer(&d->i2c_adap, msg, 2) != 2) | ||
| 827 | break; | ||
| 828 | else | ||
| 829 | mac[i] = ibuf[0]; | ||
| 830 | |||
| 831 | debug_dump(mac, 6, printk); | ||
| 832 | } | ||
| 833 | |||
| 834 | return 0; | ||
| 835 | } | ||
| 836 | |||
| 837 | static int su3000_identify_state(struct usb_device *udev, | ||
| 838 | struct dvb_usb_device_properties *props, | ||
| 839 | struct dvb_usb_device_description **desc, | ||
| 840 | int *cold) | ||
| 841 | { | ||
| 842 | info("%s\n", __func__); | ||
| 843 | |||
| 844 | *cold = 0; | ||
| 845 | return 0; | ||
| 846 | } | ||
| 847 | |||
| 848 | static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
| 849 | { | ||
| 850 | static u8 command_13v[] = {0x00, 0x01}; | ||
| 851 | static u8 command_18v[] = {0x01, 0x01}; | ||
| 852 | static u8 command_off[] = {0x00, 0x00}; | ||
| 853 | struct i2c_msg msg = { | ||
| 854 | .addr = DW2102_VOLTAGE_CTRL, | ||
| 855 | .flags = 0, | ||
| 856 | .buf = command_off, | ||
| 857 | .len = 2, | ||
| 858 | }; | ||
| 859 | |||
| 860 | struct dvb_usb_adapter *udev_adap = | ||
| 861 | (struct dvb_usb_adapter *)(fe->dvb->priv); | ||
| 862 | if (voltage == SEC_VOLTAGE_18) | ||
| 863 | msg.buf = command_18v; | ||
| 864 | else if (voltage == SEC_VOLTAGE_13) | ||
| 865 | msg.buf = command_13v; | ||
| 866 | |||
| 867 | i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); | ||
| 868 | |||
| 869 | return 0; | ||
| 870 | } | ||
| 871 | |||
| 872 | static int s660_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
| 873 | { | ||
| 874 | struct dvb_usb_adapter *d = | ||
| 875 | (struct dvb_usb_adapter *)(fe->dvb->priv); | ||
| 876 | struct s6x0_state *st = (struct s6x0_state *)d->dev->priv; | ||
| 877 | |||
| 878 | dw210x_set_voltage(fe, voltage); | ||
| 879 | if (st->old_set_voltage) | ||
| 880 | st->old_set_voltage(fe, voltage); | ||
| 881 | |||
| 882 | return 0; | ||
| 883 | } | ||
| 884 | |||
| 885 | static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon) | ||
| 886 | { | ||
| 887 | static u8 led_off[] = { 0 }; | ||
| 888 | static u8 led_on[] = { 1 }; | ||
| 889 | struct i2c_msg msg = { | ||
| 890 | .addr = DW2102_LED_CTRL, | ||
| 891 | .flags = 0, | ||
| 892 | .buf = led_off, | ||
| 893 | .len = 1 | ||
| 894 | }; | ||
| 895 | struct dvb_usb_adapter *udev_adap = | ||
| 896 | (struct dvb_usb_adapter *)(fe->dvb->priv); | ||
| 897 | |||
| 898 | if (offon) | ||
| 899 | msg.buf = led_on; | ||
| 900 | i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); | ||
| 901 | } | ||
| 902 | |||
| 903 | static struct stv0299_config sharp_z0194a_config = { | ||
| 904 | .demod_address = 0x68, | ||
| 905 | .inittab = sharp_z0194a_inittab, | ||
| 906 | .mclk = 88000000UL, | ||
| 907 | .invert = 1, | ||
| 908 | .skip_reinit = 0, | ||
| 909 | .lock_output = STV0299_LOCKOUTPUT_1, | ||
| 910 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
| 911 | .min_delay_ms = 100, | ||
| 912 | .set_symbol_rate = sharp_z0194a_set_symbol_rate, | ||
| 913 | }; | ||
| 914 | |||
| 915 | static struct cx24116_config dw2104_config = { | ||
| 916 | .demod_address = 0x55, | ||
| 917 | .mpg_clk_pos_pol = 0x01, | ||
| 918 | }; | ||
| 919 | |||
| 920 | static struct si21xx_config serit_sp1511lhb_config = { | ||
| 921 | .demod_address = 0x68, | ||
| 922 | .min_delay_ms = 100, | ||
| 923 | |||
| 924 | }; | ||
| 925 | |||
| 926 | static struct tda10023_config dw3101_tda10023_config = { | ||
| 927 | .demod_address = 0x0c, | ||
| 928 | .invert = 1, | ||
| 929 | }; | ||
| 930 | |||
| 931 | static struct mt312_config zl313_config = { | ||
| 932 | .demod_address = 0x0e, | ||
| 933 | }; | ||
| 934 | |||
| 935 | static struct ds3000_config dw2104_ds3000_config = { | ||
| 936 | .demod_address = 0x68, | ||
| 937 | }; | ||
| 938 | |||
| 939 | static struct stv0900_config dw2104a_stv0900_config = { | ||
| 940 | .demod_address = 0x6a, | ||
| 941 | .demod_mode = 0, | ||
| 942 | .xtal = 27000000, | ||
| 943 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | ||
| 944 | .diseqc_mode = 2,/* 2/3 PWM */ | ||
| 945 | .tun1_maddress = 0,/* 0x60 */ | ||
| 946 | .tun1_adc = 0,/* 2 Vpp */ | ||
| 947 | .path1_mode = 3, | ||
| 948 | }; | ||
| 949 | |||
| 950 | static struct stb6100_config dw2104a_stb6100_config = { | ||
| 951 | .tuner_address = 0x60, | ||
| 952 | .refclock = 27000000, | ||
| 953 | }; | ||
| 954 | |||
| 955 | static struct stv0900_config dw2104_stv0900_config = { | ||
| 956 | .demod_address = 0x68, | ||
| 957 | .demod_mode = 0, | ||
| 958 | .xtal = 8000000, | ||
| 959 | .clkmode = 3, | ||
| 960 | .diseqc_mode = 2, | ||
| 961 | .tun1_maddress = 0, | ||
| 962 | .tun1_adc = 1,/* 1 Vpp */ | ||
| 963 | .path1_mode = 3, | ||
| 964 | }; | ||
| 965 | |||
| 966 | static struct stv6110_config dw2104_stv6110_config = { | ||
| 967 | .i2c_address = 0x60, | ||
| 968 | .mclk = 16000000, | ||
| 969 | .clk_div = 1, | ||
| 970 | }; | ||
| 971 | |||
| 972 | static struct stv0900_config prof_7500_stv0900_config = { | ||
| 973 | .demod_address = 0x6a, | ||
| 974 | .demod_mode = 0, | ||
| 975 | .xtal = 27000000, | ||
| 976 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | ||
| 977 | .diseqc_mode = 2,/* 2/3 PWM */ | ||
| 978 | .tun1_maddress = 0,/* 0x60 */ | ||
| 979 | .tun1_adc = 0,/* 2 Vpp */ | ||
| 980 | .path1_mode = 3, | ||
| 981 | .tun1_type = 3, | ||
| 982 | .set_lock_led = dw210x_led_ctrl, | ||
| 983 | }; | ||
| 984 | |||
| 985 | static struct ds3000_config su3000_ds3000_config = { | ||
| 986 | .demod_address = 0x68, | ||
| 987 | .ci_mode = 1, | ||
| 988 | }; | ||
| 989 | |||
| 990 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) | ||
| 991 | { | ||
| 992 | struct dvb_tuner_ops *tuner_ops = NULL; | ||
| 993 | |||
| 994 | if (demod_probe & 4) { | ||
| 995 | d->fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config, | ||
| 996 | &d->dev->i2c_adap, 0); | ||
| 997 | if (d->fe != NULL) { | ||
| 998 | if (dvb_attach(stb6100_attach, d->fe, | ||
| 999 | &dw2104a_stb6100_config, | ||
| 1000 | &d->dev->i2c_adap)) { | ||
| 1001 | tuner_ops = &d->fe->ops.tuner_ops; | ||
| 1002 | tuner_ops->set_frequency = stb6100_set_freq; | ||
| 1003 | tuner_ops->get_frequency = stb6100_get_freq; | ||
| 1004 | tuner_ops->set_bandwidth = stb6100_set_bandw; | ||
| 1005 | tuner_ops->get_bandwidth = stb6100_get_bandw; | ||
| 1006 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 1007 | info("Attached STV0900+STB6100!\n"); | ||
| 1008 | return 0; | ||
| 1009 | } | ||
| 1010 | } | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | if (demod_probe & 2) { | ||
| 1014 | d->fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config, | ||
| 1015 | &d->dev->i2c_adap, 0); | ||
| 1016 | if (d->fe != NULL) { | ||
| 1017 | if (dvb_attach(stv6110_attach, d->fe, | ||
| 1018 | &dw2104_stv6110_config, | ||
| 1019 | &d->dev->i2c_adap)) { | ||
| 1020 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 1021 | info("Attached STV0900+STV6110A!\n"); | ||
| 1022 | return 0; | ||
| 1023 | } | ||
| 1024 | } | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | if (demod_probe & 1) { | ||
| 1028 | d->fe = dvb_attach(cx24116_attach, &dw2104_config, | ||
| 1029 | &d->dev->i2c_adap); | ||
| 1030 | if (d->fe != NULL) { | ||
| 1031 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 1032 | info("Attached cx24116!\n"); | ||
| 1033 | return 0; | ||
| 1034 | } | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config, | ||
| 1038 | &d->dev->i2c_adap); | ||
| 1039 | if (d->fe != NULL) { | ||
| 1040 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 1041 | info("Attached DS3000!\n"); | ||
| 1042 | return 0; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | return -EIO; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | static struct dvb_usb_device_properties dw2102_properties; | ||
| 1049 | static struct dvb_usb_device_properties dw2104_properties; | ||
| 1050 | static struct dvb_usb_device_properties s6x0_properties; | ||
| 1051 | |||
| 1052 | static int dw2102_frontend_attach(struct dvb_usb_adapter *d) | ||
| 1053 | { | ||
| 1054 | if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) { | ||
| 1055 | /*dw2102_properties.adapter->tuner_attach = NULL;*/ | ||
| 1056 | d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config, | ||
| 1057 | &d->dev->i2c_adap); | ||
| 1058 | if (d->fe != NULL) { | ||
| 1059 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 1060 | info("Attached si21xx!\n"); | ||
| 1061 | return 0; | ||
| 1062 | } | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) { | ||
| 1066 | d->fe = dvb_attach(stv0288_attach, &earda_config, | ||
| 1067 | &d->dev->i2c_adap); | ||
| 1068 | if (d->fe != NULL) { | ||
| 1069 | if (dvb_attach(stb6000_attach, d->fe, 0x61, | ||
| 1070 | &d->dev->i2c_adap)) { | ||
| 1071 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 1072 | info("Attached stv0288!\n"); | ||
| 1073 | return 0; | ||
| 1074 | } | ||
| 1075 | } | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) { | ||
| 1079 | /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ | ||
| 1080 | d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, | ||
| 1081 | &d->dev->i2c_adap); | ||
| 1082 | if (d->fe != NULL) { | ||
| 1083 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 1084 | info("Attached stv0299!\n"); | ||
| 1085 | return 0; | ||
| 1086 | } | ||
| 1087 | } | ||
| 1088 | return -EIO; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | static int dw3101_frontend_attach(struct dvb_usb_adapter *d) | ||
| 1092 | { | ||
| 1093 | d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config, | ||
| 1094 | &d->dev->i2c_adap, 0x48); | ||
| 1095 | if (d->fe != NULL) { | ||
| 1096 | info("Attached tda10023!\n"); | ||
| 1097 | return 0; | ||
| 1098 | } | ||
| 1099 | return -EIO; | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | static int zl100313_frontend_attach(struct dvb_usb_adapter *d) | ||
| 1103 | { | ||
| 1104 | d->fe = dvb_attach(mt312_attach, &zl313_config, | ||
| 1105 | &d->dev->i2c_adap); | ||
| 1106 | if (d->fe != NULL) { | ||
| 1107 | if (dvb_attach(zl10039_attach, d->fe, 0x60, | ||
| 1108 | &d->dev->i2c_adap)) { | ||
| 1109 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 1110 | info("Attached zl100313+zl10039!\n"); | ||
| 1111 | return 0; | ||
| 1112 | } | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | return -EIO; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | static int stv0288_frontend_attach(struct dvb_usb_adapter *d) | ||
| 1119 | { | ||
| 1120 | u8 obuf[] = {7, 1}; | ||
| 1121 | |||
| 1122 | d->fe = dvb_attach(stv0288_attach, &earda_config, | ||
| 1123 | &d->dev->i2c_adap); | ||
| 1124 | |||
| 1125 | if (d->fe == NULL) | ||
| 1126 | return -EIO; | ||
| 1127 | |||
| 1128 | if (NULL == dvb_attach(stb6000_attach, d->fe, 0x61, &d->dev->i2c_adap)) | ||
| 1129 | return -EIO; | ||
| 1130 | |||
| 1131 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 1132 | |||
| 1133 | dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); | ||
| 1134 | |||
| 1135 | info("Attached stv0288+stb6000!\n"); | ||
| 1136 | |||
| 1137 | return 0; | ||
| 1138 | |||
| 1139 | } | ||
| 1140 | |||
| 1141 | static int ds3000_frontend_attach(struct dvb_usb_adapter *d) | ||
| 1142 | { | ||
| 1143 | struct s6x0_state *st = (struct s6x0_state *)d->dev->priv; | ||
| 1144 | u8 obuf[] = {7, 1}; | ||
| 1145 | |||
| 1146 | d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config, | ||
| 1147 | &d->dev->i2c_adap); | ||
| 1148 | |||
| 1149 | if (d->fe == NULL) | ||
| 1150 | return -EIO; | ||
| 1151 | |||
| 1152 | st->old_set_voltage = d->fe->ops.set_voltage; | ||
| 1153 | d->fe->ops.set_voltage = s660_set_voltage; | ||
| 1154 | |||
| 1155 | dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); | ||
| 1156 | |||
| 1157 | info("Attached ds3000+ds2020!\n"); | ||
| 1158 | |||
| 1159 | return 0; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | static int prof_7500_frontend_attach(struct dvb_usb_adapter *d) | ||
| 1163 | { | ||
| 1164 | u8 obuf[] = {7, 1}; | ||
| 1165 | |||
| 1166 | d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config, | ||
| 1167 | &d->dev->i2c_adap, 0); | ||
| 1168 | if (d->fe == NULL) | ||
| 1169 | return -EIO; | ||
| 1170 | |||
| 1171 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
| 1172 | |||
| 1173 | dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); | ||
| 1174 | |||
| 1175 | info("Attached STV0900+STB6100A!\n"); | ||
| 1176 | |||
| 1177 | return 0; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | static int su3000_frontend_attach(struct dvb_usb_adapter *d) | ||
| 1181 | { | ||
| 1182 | u8 obuf[3] = { 0xe, 0x80, 0 }; | ||
| 1183 | u8 ibuf[] = { 0 }; | ||
| 1184 | |||
| 1185 | if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) | ||
| 1186 | err("command 0x0e transfer failed."); | ||
| 1187 | |||
| 1188 | obuf[0] = 0xe; | ||
| 1189 | obuf[1] = 0x83; | ||
| 1190 | obuf[2] = 0; | ||
| 1191 | |||
| 1192 | if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) | ||
| 1193 | err("command 0x0e transfer failed."); | ||
| 1194 | |||
| 1195 | obuf[0] = 0xe; | ||
| 1196 | obuf[1] = 0x83; | ||
| 1197 | obuf[2] = 1; | ||
| 1198 | |||
| 1199 | if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) | ||
| 1200 | err("command 0x0e transfer failed."); | ||
| 1201 | |||
| 1202 | obuf[0] = 0x51; | ||
| 1203 | |||
| 1204 | if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0) | ||
| 1205 | err("command 0x51 transfer failed."); | ||
| 1206 | |||
| 1207 | d->fe = dvb_attach(ds3000_attach, &su3000_ds3000_config, | ||
| 1208 | &d->dev->i2c_adap); | ||
| 1209 | if (d->fe == NULL) | ||
| 1210 | return -EIO; | ||
| 1211 | |||
| 1212 | info("Attached DS3000!\n"); | ||
| 1213 | |||
| 1214 | return 0; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1218 | { | ||
| 1219 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, | ||
| 1220 | &adap->dev->i2c_adap, DVB_PLL_OPERA1); | ||
| 1221 | return 0; | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 1225 | { | ||
| 1226 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, | ||
| 1227 | &adap->dev->i2c_adap, DVB_PLL_TUA6034); | ||
| 1228 | |||
| 1229 | return 0; | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | static struct rc_map_table rc_map_dw210x_table[] = { | ||
| 1233 | { 0xf80a, KEY_POWER2 }, /*power*/ | ||
| 1234 | { 0xf80c, KEY_MUTE }, /*mute*/ | ||
| 1235 | { 0xf811, KEY_1 }, | ||
| 1236 | { 0xf812, KEY_2 }, | ||
| 1237 | { 0xf813, KEY_3 }, | ||
| 1238 | { 0xf814, KEY_4 }, | ||
| 1239 | { 0xf815, KEY_5 }, | ||
| 1240 | { 0xf816, KEY_6 }, | ||
| 1241 | { 0xf817, KEY_7 }, | ||
| 1242 | { 0xf818, KEY_8 }, | ||
| 1243 | { 0xf819, KEY_9 }, | ||
| 1244 | { 0xf810, KEY_0 }, | ||
| 1245 | { 0xf81c, KEY_CHANNELUP }, /*ch+*/ | ||
| 1246 | { 0xf80f, KEY_CHANNELDOWN }, /*ch-*/ | ||
| 1247 | { 0xf81a, KEY_VOLUMEUP }, /*vol+*/ | ||
| 1248 | { 0xf80e, KEY_VOLUMEDOWN }, /*vol-*/ | ||
| 1249 | { 0xf804, KEY_RECORD }, /*rec*/ | ||
| 1250 | { 0xf809, KEY_FAVORITES }, /*fav*/ | ||
| 1251 | { 0xf808, KEY_REWIND }, /*rewind*/ | ||
| 1252 | { 0xf807, KEY_FASTFORWARD }, /*fast*/ | ||
| 1253 | { 0xf80b, KEY_PAUSE }, /*pause*/ | ||
| 1254 | { 0xf802, KEY_ESC }, /*cancel*/ | ||
| 1255 | { 0xf803, KEY_TAB }, /*tab*/ | ||
| 1256 | { 0xf800, KEY_UP }, /*up*/ | ||
| 1257 | { 0xf81f, KEY_OK }, /*ok*/ | ||
| 1258 | { 0xf801, KEY_DOWN }, /*down*/ | ||
| 1259 | { 0xf805, KEY_CAMERA }, /*cap*/ | ||
| 1260 | { 0xf806, KEY_STOP }, /*stop*/ | ||
| 1261 | { 0xf840, KEY_ZOOM }, /*full*/ | ||
| 1262 | { 0xf81e, KEY_TV }, /*tvmode*/ | ||
| 1263 | { 0xf81b, KEY_LAST }, /*recall*/ | ||
| 1264 | }; | ||
| 1265 | |||
| 1266 | static struct rc_map_table rc_map_tevii_table[] = { | ||
| 1267 | { 0xf80a, KEY_POWER }, | ||
| 1268 | { 0xf80c, KEY_MUTE }, | ||
| 1269 | { 0xf811, KEY_1 }, | ||
| 1270 | { 0xf812, KEY_2 }, | ||
| 1271 | { 0xf813, KEY_3 }, | ||
| 1272 | { 0xf814, KEY_4 }, | ||
| 1273 | { 0xf815, KEY_5 }, | ||
| 1274 | { 0xf816, KEY_6 }, | ||
| 1275 | { 0xf817, KEY_7 }, | ||
| 1276 | { 0xf818, KEY_8 }, | ||
| 1277 | { 0xf819, KEY_9 }, | ||
| 1278 | { 0xf810, KEY_0 }, | ||
| 1279 | { 0xf81c, KEY_MENU }, | ||
| 1280 | { 0xf80f, KEY_VOLUMEDOWN }, | ||
| 1281 | { 0xf81a, KEY_LAST }, | ||
| 1282 | { 0xf80e, KEY_OPEN }, | ||
| 1283 | { 0xf804, KEY_RECORD }, | ||
| 1284 | { 0xf809, KEY_VOLUMEUP }, | ||
| 1285 | { 0xf808, KEY_CHANNELUP }, | ||
| 1286 | { 0xf807, KEY_PVR }, | ||
| 1287 | { 0xf80b, KEY_TIME }, | ||
| 1288 | { 0xf802, KEY_RIGHT }, | ||
| 1289 | { 0xf803, KEY_LEFT }, | ||
| 1290 | { 0xf800, KEY_UP }, | ||
| 1291 | { 0xf81f, KEY_OK }, | ||
| 1292 | { 0xf801, KEY_DOWN }, | ||
| 1293 | { 0xf805, KEY_TUNER }, | ||
| 1294 | { 0xf806, KEY_CHANNELDOWN }, | ||
| 1295 | { 0xf840, KEY_PLAYPAUSE }, | ||
| 1296 | { 0xf81e, KEY_REWIND }, | ||
| 1297 | { 0xf81b, KEY_FAVORITES }, | ||
| 1298 | { 0xf81d, KEY_BACK }, | ||
| 1299 | { 0xf84d, KEY_FASTFORWARD }, | ||
| 1300 | { 0xf844, KEY_EPG }, | ||
| 1301 | { 0xf84c, KEY_INFO }, | ||
| 1302 | { 0xf841, KEY_AB }, | ||
| 1303 | { 0xf843, KEY_AUDIO }, | ||
| 1304 | { 0xf845, KEY_SUBTITLE }, | ||
| 1305 | { 0xf84a, KEY_LIST }, | ||
| 1306 | { 0xf846, KEY_F1 }, | ||
| 1307 | { 0xf847, KEY_F2 }, | ||
| 1308 | { 0xf85e, KEY_F3 }, | ||
| 1309 | { 0xf85c, KEY_F4 }, | ||
| 1310 | { 0xf852, KEY_F5 }, | ||
| 1311 | { 0xf85a, KEY_F6 }, | ||
| 1312 | { 0xf856, KEY_MODE }, | ||
| 1313 | { 0xf858, KEY_SWITCHVIDEOMODE }, | ||
| 1314 | }; | ||
| 1315 | |||
| 1316 | static struct rc_map_table rc_map_tbs_table[] = { | ||
| 1317 | { 0xf884, KEY_POWER }, | ||
| 1318 | { 0xf894, KEY_MUTE }, | ||
| 1319 | { 0xf887, KEY_1 }, | ||
| 1320 | { 0xf886, KEY_2 }, | ||
| 1321 | { 0xf885, KEY_3 }, | ||
| 1322 | { 0xf88b, KEY_4 }, | ||
| 1323 | { 0xf88a, KEY_5 }, | ||
| 1324 | { 0xf889, KEY_6 }, | ||
| 1325 | { 0xf88f, KEY_7 }, | ||
| 1326 | { 0xf88e, KEY_8 }, | ||
| 1327 | { 0xf88d, KEY_9 }, | ||
| 1328 | { 0xf892, KEY_0 }, | ||
| 1329 | { 0xf896, KEY_CHANNELUP }, | ||
| 1330 | { 0xf891, KEY_CHANNELDOWN }, | ||
| 1331 | { 0xf893, KEY_VOLUMEUP }, | ||
| 1332 | { 0xf88c, KEY_VOLUMEDOWN }, | ||
| 1333 | { 0xf883, KEY_RECORD }, | ||
| 1334 | { 0xf898, KEY_PAUSE }, | ||
| 1335 | { 0xf899, KEY_OK }, | ||
| 1336 | { 0xf89a, KEY_SHUFFLE }, | ||
| 1337 | { 0xf881, KEY_UP }, | ||
| 1338 | { 0xf890, KEY_LEFT }, | ||
| 1339 | { 0xf882, KEY_RIGHT }, | ||
| 1340 | { 0xf888, KEY_DOWN }, | ||
| 1341 | { 0xf895, KEY_FAVORITES }, | ||
| 1342 | { 0xf897, KEY_SUBTITLE }, | ||
| 1343 | { 0xf89d, KEY_ZOOM }, | ||
| 1344 | { 0xf89f, KEY_EXIT }, | ||
| 1345 | { 0xf89e, KEY_MENU }, | ||
| 1346 | { 0xf89c, KEY_EPG }, | ||
| 1347 | { 0xf880, KEY_PREVIOUS }, | ||
| 1348 | { 0xf89b, KEY_MODE } | ||
| 1349 | }; | ||
| 1350 | |||
| 1351 | static struct rc_map_table rc_map_su3000_table[] = { | ||
| 1352 | { 0x25, KEY_POWER }, /* right-bottom Red */ | ||
| 1353 | { 0x0a, KEY_MUTE }, /* -/-- */ | ||
| 1354 | { 0x01, KEY_1 }, | ||
| 1355 | { 0x02, KEY_2 }, | ||
| 1356 | { 0x03, KEY_3 }, | ||
| 1357 | { 0x04, KEY_4 }, | ||
| 1358 | { 0x05, KEY_5 }, | ||
| 1359 | { 0x06, KEY_6 }, | ||
| 1360 | { 0x07, KEY_7 }, | ||
| 1361 | { 0x08, KEY_8 }, | ||
| 1362 | { 0x09, KEY_9 }, | ||
| 1363 | { 0x00, KEY_0 }, | ||
| 1364 | { 0x20, KEY_UP }, /* CH+ */ | ||
| 1365 | { 0x21, KEY_DOWN }, /* CH+ */ | ||
| 1366 | { 0x12, KEY_VOLUMEUP }, /* Brightness Up */ | ||
| 1367 | { 0x13, KEY_VOLUMEDOWN },/* Brightness Down */ | ||
| 1368 | { 0x1f, KEY_RECORD }, | ||
| 1369 | { 0x17, KEY_PLAY }, | ||
| 1370 | { 0x16, KEY_PAUSE }, | ||
| 1371 | { 0x0b, KEY_STOP }, | ||
| 1372 | { 0x27, KEY_FASTFORWARD },/* >> */ | ||
| 1373 | { 0x26, KEY_REWIND }, /* << */ | ||
| 1374 | { 0x0d, KEY_OK }, /* Mute */ | ||
| 1375 | { 0x11, KEY_LEFT }, /* VOL- */ | ||
| 1376 | { 0x10, KEY_RIGHT }, /* VOL+ */ | ||
| 1377 | { 0x29, KEY_BACK }, /* button under 9 */ | ||
| 1378 | { 0x2c, KEY_MENU }, /* TTX */ | ||
| 1379 | { 0x2b, KEY_EPG }, /* EPG */ | ||
| 1380 | { 0x1e, KEY_RED }, /* OSD */ | ||
| 1381 | { 0x0e, KEY_GREEN }, /* Window */ | ||
| 1382 | { 0x2d, KEY_YELLOW }, /* button under << */ | ||
| 1383 | { 0x0f, KEY_BLUE }, /* bottom yellow button */ | ||
| 1384 | { 0x14, KEY_AUDIO }, /* Snapshot */ | ||
| 1385 | { 0x38, KEY_TV }, /* TV/Radio */ | ||
| 1386 | { 0x0c, KEY_ESC } /* upper Red button */ | ||
| 1387 | }; | ||
| 1388 | |||
| 1389 | static struct rc_map_dvb_usb_table_table keys_tables[] = { | ||
| 1390 | { rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) }, | ||
| 1391 | { rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) }, | ||
| 1392 | { rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) }, | ||
| 1393 | { rc_map_su3000_table, ARRAY_SIZE(rc_map_su3000_table) }, | ||
| 1394 | }; | ||
| 1395 | |||
| 1396 | static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 1397 | { | ||
| 1398 | struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table; | ||
| 1399 | int keymap_size = d->props.rc.legacy.rc_map_size; | ||
| 1400 | u8 key[2]; | ||
| 1401 | struct i2c_msg msg = { | ||
| 1402 | .addr = DW2102_RC_QUERY, | ||
| 1403 | .flags = I2C_M_RD, | ||
| 1404 | .buf = key, | ||
| 1405 | .len = 2 | ||
| 1406 | }; | ||
| 1407 | int i; | ||
| 1408 | /* override keymap */ | ||
| 1409 | if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) { | ||
| 1410 | keymap = keys_tables[ir_keymap - 1].rc_keys ; | ||
| 1411 | keymap_size = keys_tables[ir_keymap - 1].rc_keys_size; | ||
| 1412 | } else if (ir_keymap > ARRAY_SIZE(keys_tables)) | ||
| 1413 | return 0; /* none */ | ||
| 1414 | |||
| 1415 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 1416 | if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { | ||
| 1417 | for (i = 0; i < keymap_size ; i++) { | ||
| 1418 | if (rc5_data(&keymap[i]) == msg.buf[0]) { | ||
| 1419 | *state = REMOTE_KEY_PRESSED; | ||
| 1420 | *event = keymap[i].keycode; | ||
| 1421 | break; | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | } | ||
| 1425 | |||
| 1426 | if ((*state) == REMOTE_KEY_PRESSED) | ||
| 1427 | deb_rc("%s: found rc key: %x, %x, event: %x\n", | ||
| 1428 | __func__, key[0], key[1], (*event)); | ||
| 1429 | else if (key[0] != 0xff) | ||
| 1430 | deb_rc("%s: unknown rc key: %x, %x\n", | ||
| 1431 | __func__, key[0], key[1]); | ||
| 1432 | |||
| 1433 | } | ||
| 1434 | |||
| 1435 | return 0; | ||
| 1436 | } | ||
| 1437 | |||
| 1438 | static struct usb_device_id dw2102_table[] = { | ||
| 1439 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, | ||
| 1440 | {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, | ||
| 1441 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)}, | ||
| 1442 | {USB_DEVICE(0x9022, USB_PID_TEVII_S650)}, | ||
| 1443 | {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)}, | ||
| 1444 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)}, | ||
| 1445 | {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, | ||
| 1446 | {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, | ||
| 1447 | {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, | ||
| 1448 | {USB_DEVICE(0x3034, 0x7500)}, | ||
| 1449 | {USB_DEVICE(0x1f4d, 0x3000)}, | ||
| 1450 | {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)}, | ||
| 1451 | {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)}, | ||
| 1452 | {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)}, | ||
| 1453 | {USB_DEVICE(0x1f4d, 0x3100)}, | ||
| 1454 | { } | ||
| 1455 | }; | ||
| 1456 | |||
| 1457 | MODULE_DEVICE_TABLE(usb, dw2102_table); | ||
| 1458 | |||
| 1459 | static int dw2102_load_firmware(struct usb_device *dev, | ||
| 1460 | const struct firmware *frmwr) | ||
| 1461 | { | ||
| 1462 | u8 *b, *p; | ||
| 1463 | int ret = 0, i; | ||
| 1464 | u8 reset; | ||
| 1465 | u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; | ||
| 1466 | const struct firmware *fw; | ||
| 1467 | const char *fw_2101 = "dvb-usb-dw2101.fw"; | ||
| 1468 | |||
| 1469 | switch (dev->descriptor.idProduct) { | ||
| 1470 | case 0x2101: | ||
| 1471 | ret = request_firmware(&fw, fw_2101, &dev->dev); | ||
| 1472 | if (ret != 0) { | ||
| 1473 | err(err_str, fw_2101); | ||
| 1474 | return ret; | ||
| 1475 | } | ||
| 1476 | break; | ||
| 1477 | default: | ||
| 1478 | fw = frmwr; | ||
| 1479 | break; | ||
| 1480 | } | ||
| 1481 | info("start downloading DW210X firmware"); | ||
| 1482 | p = kmalloc(fw->size, GFP_KERNEL); | ||
| 1483 | reset = 1; | ||
| 1484 | /*stop the CPU*/ | ||
| 1485 | dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG); | ||
| 1486 | dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG); | ||
| 1487 | |||
| 1488 | if (p != NULL) { | ||
| 1489 | memcpy(p, fw->data, fw->size); | ||
| 1490 | for (i = 0; i < fw->size; i += 0x40) { | ||
| 1491 | b = (u8 *) p + i; | ||
| 1492 | if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40, | ||
| 1493 | DW210X_WRITE_MSG) != 0x40) { | ||
| 1494 | err("error while transferring firmware"); | ||
| 1495 | ret = -EINVAL; | ||
| 1496 | break; | ||
| 1497 | } | ||
| 1498 | } | ||
| 1499 | /* restart the CPU */ | ||
| 1500 | reset = 0; | ||
| 1501 | if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, | ||
| 1502 | DW210X_WRITE_MSG) != 1) { | ||
| 1503 | err("could not restart the USB controller CPU."); | ||
| 1504 | ret = -EINVAL; | ||
| 1505 | } | ||
| 1506 | if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, | ||
| 1507 | DW210X_WRITE_MSG) != 1) { | ||
| 1508 | err("could not restart the USB controller CPU."); | ||
| 1509 | ret = -EINVAL; | ||
| 1510 | } | ||
| 1511 | /* init registers */ | ||
| 1512 | switch (dev->descriptor.idProduct) { | ||
| 1513 | case USB_PID_TEVII_S650: | ||
| 1514 | dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table; | ||
| 1515 | dw2104_properties.rc.legacy.rc_map_size = | ||
| 1516 | ARRAY_SIZE(rc_map_tevii_table); | ||
| 1517 | case USB_PID_DW2104: | ||
| 1518 | reset = 1; | ||
| 1519 | dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, | ||
| 1520 | DW210X_WRITE_MSG); | ||
| 1521 | /* break omitted intentionally */ | ||
| 1522 | case USB_PID_DW3101: | ||
| 1523 | reset = 0; | ||
| 1524 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, | ||
| 1525 | DW210X_WRITE_MSG); | ||
| 1526 | break; | ||
| 1527 | case USB_PID_CINERGY_S: | ||
| 1528 | case USB_PID_DW2102: | ||
| 1529 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, | ||
| 1530 | DW210X_WRITE_MSG); | ||
| 1531 | dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, | ||
| 1532 | DW210X_READ_MSG); | ||
| 1533 | /* check STV0299 frontend */ | ||
| 1534 | dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2, | ||
| 1535 | DW210X_READ_MSG); | ||
| 1536 | if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) { | ||
| 1537 | dw2102_properties.i2c_algo = &dw2102_i2c_algo; | ||
| 1538 | dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach; | ||
| 1539 | break; | ||
| 1540 | } else { | ||
| 1541 | /* check STV0288 frontend */ | ||
| 1542 | reset16[0] = 0xd0; | ||
| 1543 | reset16[1] = 1; | ||
| 1544 | reset16[2] = 0; | ||
| 1545 | dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3, | ||
| 1546 | DW210X_WRITE_MSG); | ||
| 1547 | dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3, | ||
| 1548 | DW210X_READ_MSG); | ||
| 1549 | if (reset16[2] == 0x11) { | ||
| 1550 | dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo; | ||
| 1551 | break; | ||
| 1552 | } | ||
| 1553 | } | ||
| 1554 | case 0x2101: | ||
| 1555 | dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, | ||
| 1556 | DW210X_READ_MSG); | ||
| 1557 | dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, | ||
| 1558 | DW210X_READ_MSG); | ||
| 1559 | dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, | ||
| 1560 | DW210X_READ_MSG); | ||
| 1561 | dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, | ||
| 1562 | DW210X_READ_MSG); | ||
| 1563 | break; | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | msleep(100); | ||
| 1567 | kfree(p); | ||
| 1568 | } | ||
| 1569 | return ret; | ||
| 1570 | } | ||
| 1571 | |||
| 1572 | static struct dvb_usb_device_properties dw2102_properties = { | ||
| 1573 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1574 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1575 | .firmware = "dvb-usb-dw2102.fw", | ||
| 1576 | .no_reconnect = 1, | ||
| 1577 | |||
| 1578 | .i2c_algo = &dw2102_serit_i2c_algo, | ||
| 1579 | |||
| 1580 | .rc.legacy = { | ||
| 1581 | .rc_map_table = rc_map_dw210x_table, | ||
| 1582 | .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table), | ||
| 1583 | .rc_interval = 150, | ||
| 1584 | .rc_query = dw2102_rc_query, | ||
| 1585 | }, | ||
| 1586 | |||
| 1587 | .generic_bulk_ctrl_endpoint = 0x81, | ||
| 1588 | /* parameter for the MPEG2-data transfer */ | ||
| 1589 | .num_adapters = 1, | ||
| 1590 | .download_firmware = dw2102_load_firmware, | ||
| 1591 | .read_mac_address = dw210x_read_mac_address, | ||
| 1592 | .adapter = { | ||
| 1593 | { | ||
| 1594 | .frontend_attach = dw2102_frontend_attach, | ||
| 1595 | .stream = { | ||
| 1596 | .type = USB_BULK, | ||
| 1597 | .count = 8, | ||
| 1598 | .endpoint = 0x82, | ||
| 1599 | .u = { | ||
| 1600 | .bulk = { | ||
| 1601 | .buffersize = 4096, | ||
| 1602 | } | ||
| 1603 | } | ||
| 1604 | }, | ||
| 1605 | } | ||
| 1606 | }, | ||
| 1607 | .num_device_descs = 3, | ||
| 1608 | .devices = { | ||
| 1609 | {"DVBWorld DVB-S 2102 USB2.0", | ||
| 1610 | {&dw2102_table[0], NULL}, | ||
| 1611 | {NULL}, | ||
| 1612 | }, | ||
| 1613 | {"DVBWorld DVB-S 2101 USB2.0", | ||
| 1614 | {&dw2102_table[1], NULL}, | ||
| 1615 | {NULL}, | ||
| 1616 | }, | ||
| 1617 | {"TerraTec Cinergy S USB", | ||
| 1618 | {&dw2102_table[4], NULL}, | ||
| 1619 | {NULL}, | ||
| 1620 | }, | ||
| 1621 | } | ||
| 1622 | }; | ||
| 1623 | |||
| 1624 | static struct dvb_usb_device_properties dw2104_properties = { | ||
| 1625 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1626 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1627 | .firmware = "dvb-usb-dw2104.fw", | ||
| 1628 | .no_reconnect = 1, | ||
| 1629 | |||
| 1630 | .i2c_algo = &dw2104_i2c_algo, | ||
| 1631 | .rc.legacy = { | ||
| 1632 | .rc_map_table = rc_map_dw210x_table, | ||
| 1633 | .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table), | ||
| 1634 | .rc_interval = 150, | ||
| 1635 | .rc_query = dw2102_rc_query, | ||
| 1636 | }, | ||
| 1637 | |||
| 1638 | .generic_bulk_ctrl_endpoint = 0x81, | ||
| 1639 | /* parameter for the MPEG2-data transfer */ | ||
| 1640 | .num_adapters = 1, | ||
| 1641 | .download_firmware = dw2102_load_firmware, | ||
| 1642 | .read_mac_address = dw210x_read_mac_address, | ||
| 1643 | .adapter = { | ||
| 1644 | { | ||
| 1645 | .frontend_attach = dw2104_frontend_attach, | ||
| 1646 | .stream = { | ||
| 1647 | .type = USB_BULK, | ||
| 1648 | .count = 8, | ||
| 1649 | .endpoint = 0x82, | ||
| 1650 | .u = { | ||
| 1651 | .bulk = { | ||
| 1652 | .buffersize = 4096, | ||
| 1653 | } | ||
| 1654 | } | ||
| 1655 | }, | ||
| 1656 | } | ||
| 1657 | }, | ||
| 1658 | .num_device_descs = 2, | ||
| 1659 | .devices = { | ||
| 1660 | { "DVBWorld DW2104 USB2.0", | ||
| 1661 | {&dw2102_table[2], NULL}, | ||
| 1662 | {NULL}, | ||
| 1663 | }, | ||
| 1664 | { "TeVii S650 USB2.0", | ||
| 1665 | {&dw2102_table[3], NULL}, | ||
| 1666 | {NULL}, | ||
| 1667 | }, | ||
| 1668 | } | ||
| 1669 | }; | ||
| 1670 | |||
| 1671 | static struct dvb_usb_device_properties dw3101_properties = { | ||
| 1672 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1673 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1674 | .firmware = "dvb-usb-dw3101.fw", | ||
| 1675 | .no_reconnect = 1, | ||
| 1676 | |||
| 1677 | .i2c_algo = &dw3101_i2c_algo, | ||
| 1678 | .rc.legacy = { | ||
| 1679 | .rc_map_table = rc_map_dw210x_table, | ||
| 1680 | .rc_map_size = ARRAY_SIZE(rc_map_dw210x_table), | ||
| 1681 | .rc_interval = 150, | ||
| 1682 | .rc_query = dw2102_rc_query, | ||
| 1683 | }, | ||
| 1684 | |||
| 1685 | .generic_bulk_ctrl_endpoint = 0x81, | ||
| 1686 | /* parameter for the MPEG2-data transfer */ | ||
| 1687 | .num_adapters = 1, | ||
| 1688 | .download_firmware = dw2102_load_firmware, | ||
| 1689 | .read_mac_address = dw210x_read_mac_address, | ||
| 1690 | .adapter = { | ||
| 1691 | { | ||
| 1692 | .frontend_attach = dw3101_frontend_attach, | ||
| 1693 | .tuner_attach = dw3101_tuner_attach, | ||
| 1694 | .stream = { | ||
| 1695 | .type = USB_BULK, | ||
| 1696 | .count = 8, | ||
| 1697 | .endpoint = 0x82, | ||
| 1698 | .u = { | ||
| 1699 | .bulk = { | ||
| 1700 | .buffersize = 4096, | ||
| 1701 | } | ||
| 1702 | } | ||
| 1703 | }, | ||
| 1704 | } | ||
| 1705 | }, | ||
| 1706 | .num_device_descs = 1, | ||
| 1707 | .devices = { | ||
| 1708 | { "DVBWorld DVB-C 3101 USB2.0", | ||
| 1709 | {&dw2102_table[5], NULL}, | ||
| 1710 | {NULL}, | ||
| 1711 | }, | ||
| 1712 | } | ||
| 1713 | }; | ||
| 1714 | |||
| 1715 | static struct dvb_usb_device_properties s6x0_properties = { | ||
| 1716 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1717 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1718 | .size_of_priv = sizeof(struct s6x0_state), | ||
| 1719 | .firmware = "dvb-usb-s630.fw", | ||
| 1720 | .no_reconnect = 1, | ||
| 1721 | |||
| 1722 | .i2c_algo = &s6x0_i2c_algo, | ||
| 1723 | .rc.legacy = { | ||
| 1724 | .rc_map_table = rc_map_tevii_table, | ||
| 1725 | .rc_map_size = ARRAY_SIZE(rc_map_tevii_table), | ||
| 1726 | .rc_interval = 150, | ||
| 1727 | .rc_query = dw2102_rc_query, | ||
| 1728 | }, | ||
| 1729 | |||
| 1730 | .generic_bulk_ctrl_endpoint = 0x81, | ||
| 1731 | .num_adapters = 1, | ||
| 1732 | .download_firmware = dw2102_load_firmware, | ||
| 1733 | .read_mac_address = s6x0_read_mac_address, | ||
| 1734 | .adapter = { | ||
| 1735 | { | ||
| 1736 | .frontend_attach = zl100313_frontend_attach, | ||
| 1737 | .stream = { | ||
| 1738 | .type = USB_BULK, | ||
| 1739 | .count = 8, | ||
| 1740 | .endpoint = 0x82, | ||
| 1741 | .u = { | ||
| 1742 | .bulk = { | ||
| 1743 | .buffersize = 4096, | ||
| 1744 | } | ||
| 1745 | } | ||
| 1746 | }, | ||
| 1747 | } | ||
| 1748 | }, | ||
| 1749 | .num_device_descs = 1, | ||
| 1750 | .devices = { | ||
| 1751 | {"TeVii S630 USB", | ||
| 1752 | {&dw2102_table[6], NULL}, | ||
| 1753 | {NULL}, | ||
| 1754 | }, | ||
| 1755 | } | ||
| 1756 | }; | ||
| 1757 | |||
| 1758 | struct dvb_usb_device_properties *p1100; | ||
| 1759 | static struct dvb_usb_device_description d1100 = { | ||
| 1760 | "Prof 1100 USB ", | ||
| 1761 | {&dw2102_table[7], NULL}, | ||
| 1762 | {NULL}, | ||
| 1763 | }; | ||
| 1764 | |||
| 1765 | struct dvb_usb_device_properties *s660; | ||
| 1766 | static struct dvb_usb_device_description d660 = { | ||
| 1767 | "TeVii S660 USB", | ||
| 1768 | {&dw2102_table[8], NULL}, | ||
| 1769 | {NULL}, | ||
| 1770 | }; | ||
| 1771 | |||
| 1772 | static struct dvb_usb_device_description d480_1 = { | ||
| 1773 | "TeVii S480.1 USB", | ||
| 1774 | {&dw2102_table[12], NULL}, | ||
| 1775 | {NULL}, | ||
| 1776 | }; | ||
| 1777 | |||
| 1778 | static struct dvb_usb_device_description d480_2 = { | ||
| 1779 | "TeVii S480.2 USB", | ||
| 1780 | {&dw2102_table[13], NULL}, | ||
| 1781 | {NULL}, | ||
| 1782 | }; | ||
| 1783 | |||
| 1784 | struct dvb_usb_device_properties *p7500; | ||
| 1785 | static struct dvb_usb_device_description d7500 = { | ||
| 1786 | "Prof 7500 USB DVB-S2", | ||
| 1787 | {&dw2102_table[9], NULL}, | ||
| 1788 | {NULL}, | ||
| 1789 | }; | ||
| 1790 | |||
| 1791 | static struct dvb_usb_device_properties su3000_properties = { | ||
| 1792 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1793 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1794 | .size_of_priv = sizeof(struct su3000_state), | ||
| 1795 | .power_ctrl = su3000_power_ctrl, | ||
| 1796 | .num_adapters = 1, | ||
| 1797 | .identify_state = su3000_identify_state, | ||
| 1798 | .i2c_algo = &su3000_i2c_algo, | ||
| 1799 | |||
| 1800 | .rc.legacy = { | ||
| 1801 | .rc_map_table = rc_map_su3000_table, | ||
| 1802 | .rc_map_size = ARRAY_SIZE(rc_map_su3000_table), | ||
| 1803 | .rc_interval = 150, | ||
| 1804 | .rc_query = dw2102_rc_query, | ||
| 1805 | }, | ||
| 1806 | |||
| 1807 | .read_mac_address = su3000_read_mac_address, | ||
| 1808 | |||
| 1809 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 1810 | |||
| 1811 | .adapter = { | ||
| 1812 | { | ||
| 1813 | .streaming_ctrl = su3000_streaming_ctrl, | ||
| 1814 | .frontend_attach = su3000_frontend_attach, | ||
| 1815 | .stream = { | ||
| 1816 | .type = USB_BULK, | ||
| 1817 | .count = 8, | ||
| 1818 | .endpoint = 0x82, | ||
| 1819 | .u = { | ||
| 1820 | .bulk = { | ||
| 1821 | .buffersize = 4096, | ||
| 1822 | } | ||
| 1823 | } | ||
| 1824 | } | ||
| 1825 | } | ||
| 1826 | }, | ||
| 1827 | .num_device_descs = 3, | ||
| 1828 | .devices = { | ||
| 1829 | { "SU3000HD DVB-S USB2.0", | ||
| 1830 | { &dw2102_table[10], NULL }, | ||
| 1831 | { NULL }, | ||
| 1832 | }, | ||
| 1833 | { "Terratec Cinergy S2 USB HD", | ||
| 1834 | { &dw2102_table[11], NULL }, | ||
| 1835 | { NULL }, | ||
| 1836 | }, | ||
| 1837 | { "X3M TV SPC1400HD PCI", | ||
| 1838 | { &dw2102_table[14], NULL }, | ||
| 1839 | { NULL }, | ||
| 1840 | }, | ||
| 1841 | } | ||
| 1842 | }; | ||
| 1843 | |||
| 1844 | static int dw2102_probe(struct usb_interface *intf, | ||
| 1845 | const struct usb_device_id *id) | ||
| 1846 | { | ||
| 1847 | p1100 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL); | ||
| 1848 | if (!p1100) | ||
| 1849 | return -ENOMEM; | ||
| 1850 | /* copy default structure */ | ||
| 1851 | memcpy(p1100, &s6x0_properties, | ||
| 1852 | sizeof(struct dvb_usb_device_properties)); | ||
| 1853 | /* fill only different fields */ | ||
| 1854 | p1100->firmware = "dvb-usb-p1100.fw"; | ||
| 1855 | p1100->devices[0] = d1100; | ||
| 1856 | p1100->rc.legacy.rc_map_table = rc_map_tbs_table; | ||
| 1857 | p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table); | ||
| 1858 | p1100->adapter->frontend_attach = stv0288_frontend_attach; | ||
| 1859 | |||
| 1860 | s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL); | ||
| 1861 | if (!s660) { | ||
| 1862 | kfree(p1100); | ||
| 1863 | return -ENOMEM; | ||
| 1864 | } | ||
| 1865 | memcpy(s660, &s6x0_properties, | ||
| 1866 | sizeof(struct dvb_usb_device_properties)); | ||
| 1867 | s660->firmware = "dvb-usb-s660.fw"; | ||
| 1868 | s660->num_device_descs = 3; | ||
| 1869 | s660->devices[0] = d660; | ||
| 1870 | s660->devices[1] = d480_1; | ||
| 1871 | s660->devices[2] = d480_2; | ||
| 1872 | s660->adapter->frontend_attach = ds3000_frontend_attach; | ||
| 1873 | |||
| 1874 | p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL); | ||
| 1875 | if (!p7500) { | ||
| 1876 | kfree(p1100); | ||
| 1877 | kfree(s660); | ||
| 1878 | return -ENOMEM; | ||
| 1879 | } | ||
| 1880 | memcpy(p7500, &s6x0_properties, | ||
| 1881 | sizeof(struct dvb_usb_device_properties)); | ||
| 1882 | p7500->firmware = "dvb-usb-p7500.fw"; | ||
| 1883 | p7500->devices[0] = d7500; | ||
| 1884 | p7500->rc.legacy.rc_map_table = rc_map_tbs_table; | ||
| 1885 | p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table); | ||
| 1886 | p7500->adapter->frontend_attach = prof_7500_frontend_attach; | ||
| 1887 | |||
| 1888 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, | ||
| 1889 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1890 | 0 == dvb_usb_device_init(intf, &dw2104_properties, | ||
| 1891 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1892 | 0 == dvb_usb_device_init(intf, &dw3101_properties, | ||
| 1893 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1894 | 0 == dvb_usb_device_init(intf, &s6x0_properties, | ||
| 1895 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1896 | 0 == dvb_usb_device_init(intf, p1100, | ||
| 1897 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1898 | 0 == dvb_usb_device_init(intf, s660, | ||
| 1899 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1900 | 0 == dvb_usb_device_init(intf, p7500, | ||
| 1901 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1902 | 0 == dvb_usb_device_init(intf, &su3000_properties, | ||
| 1903 | THIS_MODULE, NULL, adapter_nr)) | ||
| 1904 | return 0; | ||
| 1905 | |||
| 1906 | return -ENODEV; | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | static struct usb_driver dw2102_driver = { | ||
| 1910 | .name = "dw2102", | ||
| 1911 | .probe = dw2102_probe, | ||
| 1912 | .disconnect = dvb_usb_device_exit, | ||
| 1913 | .id_table = dw2102_table, | ||
| 1914 | }; | ||
| 1915 | |||
| 1916 | static int __init dw2102_module_init(void) | ||
| 1917 | { | ||
| 1918 | int ret = usb_register(&dw2102_driver); | ||
| 1919 | if (ret) | ||
| 1920 | err("usb_register failed. Error number %d", ret); | ||
| 1921 | |||
| 1922 | return ret; | ||
| 1923 | } | ||
| 1924 | |||
| 1925 | static void __exit dw2102_module_exit(void) | ||
| 1926 | { | ||
| 1927 | usb_deregister(&dw2102_driver); | ||
| 1928 | } | ||
| 1929 | |||
| 1930 | module_init(dw2102_module_init); | ||
| 1931 | module_exit(dw2102_module_exit); | ||
| 1932 | |||
| 1933 | MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); | ||
| 1934 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," | ||
| 1935 | " DVB-C 3101 USB2.0," | ||
| 1936 | " TeVii S600, S630, S650, S660, S480," | ||
| 1937 | " Prof 1100, 7500 USB2.0," | ||
| 1938 | " Geniatech SU3000 devices"); | ||
| 1939 | MODULE_VERSION("0.1"); | ||
| 1940 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h new file mode 100644 index 00000000000..5cd0b0eb6ce --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dw2102.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #ifndef _DW2102_H_ | ||
| 2 | #define _DW2102_H_ | ||
| 3 | |||
| 4 | #define DVB_USB_LOG_PREFIX "dw2102" | ||
| 5 | #include "dvb-usb.h" | ||
| 6 | |||
| 7 | #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args) | ||
| 8 | #define deb_rc(args...) dprintk(dvb_usb_dw2102_debug, 0x04, args) | ||
| 9 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/ec168.c b/drivers/media/dvb/dvb-usb/ec168.c new file mode 100644 index 00000000000..1ba3e5dbee1 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ec168.c | |||
| @@ -0,0 +1,452 @@ | |||
| 1 | /* | ||
| 2 | * E3C EC168 DVB USB driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
| 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 "ec168.h" | ||
| 23 | #include "ec100.h" | ||
| 24 | #include "mxl5005s.h" | ||
| 25 | |||
| 26 | /* debug */ | ||
| 27 | static int dvb_usb_ec168_debug; | ||
| 28 | module_param_named(debug, dvb_usb_ec168_debug, int, 0644); | ||
| 29 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
| 30 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 31 | |||
| 32 | static struct ec100_config ec168_ec100_config; | ||
| 33 | |||
| 34 | static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req) | ||
| 35 | { | ||
| 36 | int ret; | ||
| 37 | unsigned int pipe; | ||
| 38 | u8 request, requesttype; | ||
| 39 | u8 *buf; | ||
| 40 | |||
| 41 | |||
| 42 | |||
| 43 | switch (req->cmd) { | ||
| 44 | case DOWNLOAD_FIRMWARE: | ||
| 45 | case GPIO: | ||
| 46 | case WRITE_I2C: | ||
| 47 | case STREAMING_CTRL: | ||
| 48 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | ||
| 49 | request = req->cmd; | ||
| 50 | break; | ||
| 51 | case READ_I2C: | ||
| 52 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | ||
| 53 | request = req->cmd; | ||
| 54 | break; | ||
| 55 | case GET_CONFIG: | ||
| 56 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | ||
| 57 | request = CONFIG; | ||
| 58 | break; | ||
| 59 | case SET_CONFIG: | ||
| 60 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | ||
| 61 | request = CONFIG; | ||
| 62 | break; | ||
| 63 | case WRITE_DEMOD: | ||
| 64 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | ||
| 65 | request = DEMOD_RW; | ||
| 66 | break; | ||
| 67 | case READ_DEMOD: | ||
| 68 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | ||
| 69 | request = DEMOD_RW; | ||
| 70 | break; | ||
| 71 | default: | ||
| 72 | err("unknown command:%02x", req->cmd); | ||
| 73 | ret = -EPERM; | ||
| 74 | goto error; | ||
| 75 | } | ||
| 76 | |||
| 77 | buf = kmalloc(req->size, GFP_KERNEL); | ||
| 78 | if (!buf) { | ||
| 79 | ret = -ENOMEM; | ||
| 80 | goto error; | ||
| 81 | } | ||
| 82 | |||
| 83 | if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { | ||
| 84 | /* write */ | ||
| 85 | memcpy(buf, req->data, req->size); | ||
| 86 | pipe = usb_sndctrlpipe(udev, 0); | ||
| 87 | } else { | ||
| 88 | /* read */ | ||
| 89 | pipe = usb_rcvctrlpipe(udev, 0); | ||
| 90 | } | ||
| 91 | |||
| 92 | msleep(1); /* avoid I2C errors */ | ||
| 93 | |||
| 94 | ret = usb_control_msg(udev, pipe, request, requesttype, req->value, | ||
| 95 | req->index, buf, req->size, EC168_USB_TIMEOUT); | ||
| 96 | |||
| 97 | ec168_debug_dump(request, requesttype, req->value, req->index, buf, | ||
| 98 | req->size, deb_xfer); | ||
| 99 | |||
| 100 | if (ret < 0) | ||
| 101 | goto err_dealloc; | ||
| 102 | else | ||
| 103 | ret = 0; | ||
| 104 | |||
| 105 | /* read request, copy returned data to return buf */ | ||
| 106 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) | ||
| 107 | memcpy(req->data, buf, req->size); | ||
| 108 | |||
| 109 | kfree(buf); | ||
| 110 | return ret; | ||
| 111 | |||
| 112 | err_dealloc: | ||
| 113 | kfree(buf); | ||
| 114 | error: | ||
| 115 | deb_info("%s: failed:%d\n", __func__, ret); | ||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req) | ||
| 120 | { | ||
| 121 | return ec168_rw_udev(d->udev, req); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* I2C */ | ||
| 125 | static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 126 | int num) | ||
| 127 | { | ||
| 128 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 129 | struct ec168_req req; | ||
| 130 | int i = 0; | ||
| 131 | int ret; | ||
| 132 | |||
| 133 | if (num > 2) | ||
| 134 | return -EINVAL; | ||
| 135 | |||
| 136 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 137 | return -EAGAIN; | ||
| 138 | |||
| 139 | while (i < num) { | ||
| 140 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
| 141 | if (msg[i].addr == ec168_ec100_config.demod_address) { | ||
| 142 | req.cmd = READ_DEMOD; | ||
| 143 | req.value = 0; | ||
| 144 | req.index = 0xff00 + msg[i].buf[0]; /* reg */ | ||
| 145 | req.size = msg[i+1].len; /* bytes to read */ | ||
| 146 | req.data = &msg[i+1].buf[0]; | ||
| 147 | ret = ec168_ctrl_msg(d, &req); | ||
| 148 | i += 2; | ||
| 149 | } else { | ||
| 150 | err("I2C read not implemented"); | ||
| 151 | ret = -ENOSYS; | ||
| 152 | i += 2; | ||
| 153 | } | ||
| 154 | } else { | ||
| 155 | if (msg[i].addr == ec168_ec100_config.demod_address) { | ||
| 156 | req.cmd = WRITE_DEMOD; | ||
| 157 | req.value = msg[i].buf[1]; /* val */ | ||
| 158 | req.index = 0xff00 + msg[i].buf[0]; /* reg */ | ||
| 159 | req.size = 0; | ||
| 160 | req.data = NULL; | ||
| 161 | ret = ec168_ctrl_msg(d, &req); | ||
| 162 | i += 1; | ||
| 163 | } else { | ||
| 164 | req.cmd = WRITE_I2C; | ||
| 165 | req.value = msg[i].buf[0]; /* val */ | ||
| 166 | req.index = 0x0100 + msg[i].addr; /* I2C addr */ | ||
| 167 | req.size = msg[i].len-1; | ||
| 168 | req.data = &msg[i].buf[1]; | ||
| 169 | ret = ec168_ctrl_msg(d, &req); | ||
| 170 | i += 1; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | if (ret) | ||
| 174 | goto error; | ||
| 175 | |||
| 176 | } | ||
| 177 | ret = i; | ||
| 178 | |||
| 179 | error: | ||
| 180 | mutex_unlock(&d->i2c_mutex); | ||
| 181 | return i; | ||
| 182 | } | ||
| 183 | |||
| 184 | |||
| 185 | static u32 ec168_i2c_func(struct i2c_adapter *adapter) | ||
| 186 | { | ||
| 187 | return I2C_FUNC_I2C; | ||
| 188 | } | ||
| 189 | |||
| 190 | static struct i2c_algorithm ec168_i2c_algo = { | ||
| 191 | .master_xfer = ec168_i2c_xfer, | ||
| 192 | .functionality = ec168_i2c_func, | ||
| 193 | }; | ||
| 194 | |||
| 195 | /* Callbacks for DVB USB */ | ||
| 196 | static struct ec100_config ec168_ec100_config = { | ||
| 197 | .demod_address = 0xff, /* not real address, demod is integrated */ | ||
| 198 | }; | ||
| 199 | |||
| 200 | static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 201 | { | ||
| 202 | deb_info("%s:\n", __func__); | ||
| 203 | adap->fe = dvb_attach(ec100_attach, &ec168_ec100_config, | ||
| 204 | &adap->dev->i2c_adap); | ||
| 205 | if (adap->fe == NULL) | ||
| 206 | return -ENODEV; | ||
| 207 | |||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | |||
| 211 | static struct mxl5005s_config ec168_mxl5003s_config = { | ||
| 212 | .i2c_address = 0xc6, | ||
| 213 | .if_freq = IF_FREQ_4570000HZ, | ||
| 214 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
| 215 | .agc_mode = MXL_SINGLE_AGC, | ||
| 216 | .tracking_filter = MXL_TF_OFF, | ||
| 217 | .rssi_enable = MXL_RSSI_ENABLE, | ||
| 218 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
| 219 | .div_out = MXL_DIV_OUT_4, | ||
| 220 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
| 221 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
| 222 | .top = MXL5005S_TOP_25P2, | ||
| 223 | .mod_mode = MXL_DIGITAL_MODE, | ||
| 224 | .if_mode = MXL_ZERO_IF, | ||
| 225 | .AgcMasterByte = 0x00, | ||
| 226 | }; | ||
| 227 | |||
| 228 | static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 229 | { | ||
| 230 | deb_info("%s:\n", __func__); | ||
| 231 | return dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap, | ||
| 232 | &ec168_mxl5003s_config) == NULL ? -ENODEV : 0; | ||
| 233 | } | ||
| 234 | |||
| 235 | static int ec168_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 236 | { | ||
| 237 | struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL}; | ||
| 238 | deb_info("%s: onoff:%d\n", __func__, onoff); | ||
| 239 | if (onoff) | ||
| 240 | req.index = 0x0102; | ||
| 241 | return ec168_ctrl_msg(adap->dev, &req); | ||
| 242 | } | ||
| 243 | |||
| 244 | static int ec168_download_firmware(struct usb_device *udev, | ||
| 245 | const struct firmware *fw) | ||
| 246 | { | ||
| 247 | int i, len, packets, remainder, ret; | ||
| 248 | u16 addr = 0x0000; /* firmware start address */ | ||
| 249 | struct ec168_req req = {DOWNLOAD_FIRMWARE, 0, 0, 0, NULL}; | ||
| 250 | deb_info("%s:\n", __func__); | ||
| 251 | |||
| 252 | #define FW_PACKET_MAX_DATA 2048 | ||
| 253 | packets = fw->size / FW_PACKET_MAX_DATA; | ||
| 254 | remainder = fw->size % FW_PACKET_MAX_DATA; | ||
| 255 | len = FW_PACKET_MAX_DATA; | ||
| 256 | for (i = 0; i <= packets; i++) { | ||
| 257 | if (i == packets) /* set size of the last packet */ | ||
| 258 | len = remainder; | ||
| 259 | |||
| 260 | req.size = len; | ||
| 261 | req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA); | ||
| 262 | req.index = addr; | ||
| 263 | addr += FW_PACKET_MAX_DATA; | ||
| 264 | |||
| 265 | ret = ec168_rw_udev(udev, &req); | ||
| 266 | if (ret) { | ||
| 267 | err("firmware download failed:%d packet:%d", ret, i); | ||
| 268 | goto error; | ||
| 269 | } | ||
| 270 | } | ||
| 271 | req.size = 0; | ||
| 272 | |||
| 273 | /* set "warm"? */ | ||
| 274 | req.cmd = SET_CONFIG; | ||
| 275 | req.value = 0; | ||
| 276 | req.index = 0x0001; | ||
| 277 | ret = ec168_rw_udev(udev, &req); | ||
| 278 | if (ret) | ||
| 279 | goto error; | ||
| 280 | |||
| 281 | /* really needed - no idea what does */ | ||
| 282 | req.cmd = GPIO; | ||
| 283 | req.value = 0; | ||
| 284 | req.index = 0x0206; | ||
| 285 | ret = ec168_rw_udev(udev, &req); | ||
| 286 | if (ret) | ||
| 287 | goto error; | ||
| 288 | |||
| 289 | /* activate tuner I2C? */ | ||
| 290 | req.cmd = WRITE_I2C; | ||
| 291 | req.value = 0; | ||
| 292 | req.index = 0x00c6; | ||
| 293 | ret = ec168_rw_udev(udev, &req); | ||
| 294 | if (ret) | ||
| 295 | goto error; | ||
| 296 | |||
| 297 | return ret; | ||
| 298 | error: | ||
| 299 | deb_info("%s: failed:%d\n", __func__, ret); | ||
| 300 | return ret; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int ec168_identify_state(struct usb_device *udev, | ||
| 304 | struct dvb_usb_device_properties *props, | ||
| 305 | struct dvb_usb_device_description **desc, int *cold) | ||
| 306 | { | ||
| 307 | int ret; | ||
| 308 | u8 reply; | ||
| 309 | struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply}; | ||
| 310 | deb_info("%s:\n", __func__); | ||
| 311 | |||
| 312 | ret = ec168_rw_udev(udev, &req); | ||
| 313 | if (ret) | ||
| 314 | goto error; | ||
| 315 | |||
| 316 | deb_info("%s: reply:%02x\n", __func__, reply); | ||
| 317 | |||
| 318 | if (reply == 0x01) | ||
| 319 | *cold = 0; | ||
| 320 | else | ||
| 321 | *cold = 1; | ||
| 322 | |||
| 323 | return ret; | ||
| 324 | error: | ||
| 325 | deb_info("%s: failed:%d\n", __func__, ret); | ||
| 326 | return ret; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* DVB USB Driver stuff */ | ||
| 330 | static struct dvb_usb_device_properties ec168_properties; | ||
| 331 | |||
| 332 | static int ec168_probe(struct usb_interface *intf, | ||
| 333 | const struct usb_device_id *id) | ||
| 334 | { | ||
| 335 | int ret; | ||
| 336 | deb_info("%s: interface:%d\n", __func__, | ||
| 337 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
| 338 | |||
| 339 | ret = dvb_usb_device_init(intf, &ec168_properties, THIS_MODULE, NULL, | ||
| 340 | adapter_nr); | ||
| 341 | if (ret) | ||
| 342 | goto error; | ||
| 343 | |||
| 344 | return ret; | ||
| 345 | error: | ||
| 346 | deb_info("%s: failed:%d\n", __func__, ret); | ||
| 347 | return ret; | ||
| 348 | } | ||
| 349 | |||
| 350 | #define E3C_EC168_1689 0 | ||
| 351 | #define E3C_EC168_FFFA 1 | ||
| 352 | #define E3C_EC168_FFFB 2 | ||
| 353 | #define E3C_EC168_1001 3 | ||
| 354 | #define E3C_EC168_1002 4 | ||
| 355 | |||
| 356 | static struct usb_device_id ec168_id[] = { | ||
| 357 | [E3C_EC168_1689] = | ||
| 358 | {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168)}, | ||
| 359 | [E3C_EC168_FFFA] = | ||
| 360 | {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2)}, | ||
| 361 | [E3C_EC168_FFFB] = | ||
| 362 | {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3)}, | ||
| 363 | [E3C_EC168_1001] = | ||
| 364 | {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4)}, | ||
| 365 | [E3C_EC168_1002] = | ||
| 366 | {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5)}, | ||
| 367 | {} /* terminating entry */ | ||
| 368 | }; | ||
| 369 | |||
| 370 | MODULE_DEVICE_TABLE(usb, ec168_id); | ||
| 371 | |||
| 372 | static struct dvb_usb_device_properties ec168_properties = { | ||
| 373 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 374 | |||
| 375 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 376 | .download_firmware = ec168_download_firmware, | ||
| 377 | .firmware = "dvb-usb-ec168.fw", | ||
| 378 | .no_reconnect = 1, | ||
| 379 | |||
| 380 | .size_of_priv = 0, | ||
| 381 | |||
| 382 | .num_adapters = 1, | ||
| 383 | .adapter = { | ||
| 384 | { | ||
| 385 | .streaming_ctrl = ec168_streaming_ctrl, | ||
| 386 | .frontend_attach = ec168_ec100_frontend_attach, | ||
| 387 | .tuner_attach = ec168_mxl5003s_tuner_attach, | ||
| 388 | .stream = { | ||
| 389 | .type = USB_BULK, | ||
| 390 | .count = 6, | ||
| 391 | .endpoint = 0x82, | ||
| 392 | .u = { | ||
| 393 | .bulk = { | ||
| 394 | .buffersize = (32*512), | ||
| 395 | } | ||
| 396 | } | ||
| 397 | }, | ||
| 398 | } | ||
| 399 | }, | ||
| 400 | |||
| 401 | .identify_state = ec168_identify_state, | ||
| 402 | |||
| 403 | .i2c_algo = &ec168_i2c_algo, | ||
| 404 | |||
| 405 | .num_device_descs = 1, | ||
| 406 | .devices = { | ||
| 407 | { | ||
| 408 | .name = "E3C EC168 DVB-T USB2.0 reference design", | ||
| 409 | .cold_ids = { | ||
| 410 | &ec168_id[E3C_EC168_1689], | ||
| 411 | &ec168_id[E3C_EC168_FFFA], | ||
| 412 | &ec168_id[E3C_EC168_FFFB], | ||
| 413 | &ec168_id[E3C_EC168_1001], | ||
| 414 | &ec168_id[E3C_EC168_1002], | ||
| 415 | NULL}, | ||
| 416 | .warm_ids = {NULL}, | ||
| 417 | }, | ||
| 418 | } | ||
| 419 | }; | ||
| 420 | |||
| 421 | static struct usb_driver ec168_driver = { | ||
| 422 | .name = "dvb_usb_ec168", | ||
| 423 | .probe = ec168_probe, | ||
| 424 | .disconnect = dvb_usb_device_exit, | ||
| 425 | .id_table = ec168_id, | ||
| 426 | }; | ||
| 427 | |||
| 428 | /* module stuff */ | ||
| 429 | static int __init ec168_module_init(void) | ||
| 430 | { | ||
| 431 | int ret; | ||
| 432 | deb_info("%s:\n", __func__); | ||
| 433 | ret = usb_register(&ec168_driver); | ||
| 434 | if (ret) | ||
| 435 | err("module init failed:%d", ret); | ||
| 436 | |||
| 437 | return ret; | ||
| 438 | } | ||
| 439 | |||
| 440 | static void __exit ec168_module_exit(void) | ||
| 441 | { | ||
| 442 | deb_info("%s:\n", __func__); | ||
| 443 | /* deregister this driver from the USB subsystem */ | ||
| 444 | usb_deregister(&ec168_driver); | ||
| 445 | } | ||
| 446 | |||
| 447 | module_init(ec168_module_init); | ||
| 448 | module_exit(ec168_module_exit); | ||
| 449 | |||
| 450 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 451 | MODULE_DESCRIPTION("E3C EC168 DVB-T USB2.0 driver"); | ||
| 452 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/ec168.h b/drivers/media/dvb/dvb-usb/ec168.h new file mode 100644 index 00000000000..e7e0b831314 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ec168.h | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | /* | ||
| 2 | * E3C EC168 DVB USB driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
| 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 | #ifndef EC168_H | ||
| 23 | #define EC168_H | ||
| 24 | |||
| 25 | #define DVB_USB_LOG_PREFIX "ec168" | ||
| 26 | #include "dvb-usb.h" | ||
| 27 | |||
| 28 | #define deb_info(args...) dprintk(dvb_usb_ec168_debug, 0x01, args) | ||
| 29 | #define deb_rc(args...) dprintk(dvb_usb_ec168_debug, 0x02, args) | ||
| 30 | #define deb_xfer(args...) dprintk(dvb_usb_ec168_debug, 0x04, args) | ||
| 31 | #define deb_reg(args...) dprintk(dvb_usb_ec168_debug, 0x08, args) | ||
| 32 | #define deb_i2c(args...) dprintk(dvb_usb_ec168_debug, 0x10, args) | ||
| 33 | #define deb_fw(args...) dprintk(dvb_usb_ec168_debug, 0x20, args) | ||
| 34 | |||
| 35 | #define ec168_debug_dump(r, t, v, i, b, l, func) { \ | ||
| 36 | int loop_; \ | ||
| 37 | func("%02x %02x %02x %02x %02x %02x %02x %02x", \ | ||
| 38 | t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \ | ||
| 39 | if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ | ||
| 40 | func(" >>> "); \ | ||
| 41 | else \ | ||
| 42 | func(" <<< "); \ | ||
| 43 | for (loop_ = 0; loop_ < l; loop_++) \ | ||
| 44 | func("%02x ", b[loop_]); \ | ||
| 45 | func("\n");\ | ||
| 46 | } | ||
| 47 | |||
| 48 | #define EC168_USB_TIMEOUT 1000 | ||
| 49 | |||
| 50 | struct ec168_req { | ||
| 51 | u8 cmd; /* [1] */ | ||
| 52 | u16 value; /* [2|3] */ | ||
| 53 | u16 index; /* [4|5] */ | ||
| 54 | u16 size; /* [6|7] */ | ||
| 55 | u8 *data; | ||
| 56 | }; | ||
| 57 | |||
| 58 | enum ec168_cmd { | ||
| 59 | DOWNLOAD_FIRMWARE = 0x00, | ||
| 60 | CONFIG = 0x01, | ||
| 61 | DEMOD_RW = 0x03, | ||
| 62 | GPIO = 0x04, | ||
| 63 | STREAMING_CTRL = 0x10, | ||
| 64 | READ_I2C = 0x20, | ||
| 65 | WRITE_I2C = 0x21, | ||
| 66 | HID_DOWNLOAD = 0x30, | ||
| 67 | GET_CONFIG, | ||
| 68 | SET_CONFIG, | ||
| 69 | READ_DEMOD, | ||
| 70 | WRITE_DEMOD, | ||
| 71 | }; | ||
| 72 | |||
| 73 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c new file mode 100644 index 00000000000..015b4e8af1a --- /dev/null +++ b/drivers/media/dvb/dvb-usb/friio-fe.c | |||
| @@ -0,0 +1,474 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp> | ||
| 4 | * | ||
| 5 | * This module is based off the the gl861 and vp702x modules. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation, version 2. | ||
| 10 | * | ||
| 11 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 12 | */ | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/string.h> | ||
| 15 | #include <linux/slab.h> | ||
| 16 | |||
| 17 | #include "friio.h" | ||
| 18 | |||
| 19 | struct jdvbt90502_state { | ||
| 20 | struct i2c_adapter *i2c; | ||
| 21 | struct dvb_frontend frontend; | ||
| 22 | struct jdvbt90502_config config; | ||
| 23 | }; | ||
| 24 | |||
| 25 | /* NOTE: TC90502 has 16bit register-address? */ | ||
| 26 | /* register 0x0100 is used for reading PLL status, so reg is u16 here */ | ||
| 27 | static int jdvbt90502_reg_read(struct jdvbt90502_state *state, | ||
| 28 | const u16 reg, u8 *buf, const size_t count) | ||
| 29 | { | ||
| 30 | int ret; | ||
| 31 | u8 wbuf[3]; | ||
| 32 | struct i2c_msg msg[2]; | ||
| 33 | |||
| 34 | wbuf[0] = reg & 0xFF; | ||
| 35 | wbuf[1] = 0; | ||
| 36 | wbuf[2] = reg >> 8; | ||
| 37 | |||
| 38 | msg[0].addr = state->config.demod_address; | ||
| 39 | msg[0].flags = 0; | ||
| 40 | msg[0].buf = wbuf; | ||
| 41 | msg[0].len = sizeof(wbuf); | ||
| 42 | |||
| 43 | msg[1].addr = msg[0].addr; | ||
| 44 | msg[1].flags = I2C_M_RD; | ||
| 45 | msg[1].buf = buf; | ||
| 46 | msg[1].len = count; | ||
| 47 | |||
| 48 | ret = i2c_transfer(state->i2c, msg, 2); | ||
| 49 | if (ret != 2) { | ||
| 50 | deb_fe(" reg read failed.\n"); | ||
| 51 | return -EREMOTEIO; | ||
| 52 | } | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | |||
| 56 | /* currently 16bit register-address is not used, so reg is u8 here */ | ||
| 57 | static int jdvbt90502_single_reg_write(struct jdvbt90502_state *state, | ||
| 58 | const u8 reg, const u8 val) | ||
| 59 | { | ||
| 60 | struct i2c_msg msg; | ||
| 61 | u8 wbuf[2]; | ||
| 62 | |||
| 63 | wbuf[0] = reg; | ||
| 64 | wbuf[1] = val; | ||
| 65 | |||
| 66 | msg.addr = state->config.demod_address; | ||
| 67 | msg.flags = 0; | ||
| 68 | msg.buf = wbuf; | ||
| 69 | msg.len = sizeof(wbuf); | ||
| 70 | |||
| 71 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | ||
| 72 | deb_fe(" reg write failed."); | ||
| 73 | return -EREMOTEIO; | ||
| 74 | } | ||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | static int _jdvbt90502_write(struct dvb_frontend *fe, const u8 buf[], int len) | ||
| 79 | { | ||
| 80 | struct jdvbt90502_state *state = fe->demodulator_priv; | ||
| 81 | int err, i; | ||
| 82 | for (i = 0; i < len - 1; i++) { | ||
| 83 | err = jdvbt90502_single_reg_write(state, | ||
| 84 | buf[0] + i, buf[i + 1]); | ||
| 85 | if (err) | ||
| 86 | return err; | ||
| 87 | } | ||
| 88 | |||
| 89 | return 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | /* read pll status byte via the demodulator's I2C register */ | ||
| 93 | /* note: Win box reads it by 8B block at the I2C addr 0x30 from reg:0x80 */ | ||
| 94 | static int jdvbt90502_pll_read(struct jdvbt90502_state *state, u8 *result) | ||
| 95 | { | ||
| 96 | int ret; | ||
| 97 | |||
| 98 | /* +1 for reading */ | ||
| 99 | u8 pll_addr_byte = (state->config.pll_address << 1) + 1; | ||
| 100 | |||
| 101 | *result = 0; | ||
| 102 | |||
| 103 | ret = jdvbt90502_single_reg_write(state, JDVBT90502_2ND_I2C_REG, | ||
| 104 | pll_addr_byte); | ||
| 105 | if (ret) | ||
| 106 | goto error; | ||
| 107 | |||
| 108 | ret = jdvbt90502_reg_read(state, 0x0100, result, 1); | ||
| 109 | if (ret) | ||
| 110 | goto error; | ||
| 111 | |||
| 112 | deb_fe("PLL read val:%02x\n", *result); | ||
| 113 | return 0; | ||
| 114 | |||
| 115 | error: | ||
| 116 | deb_fe("%s:ret == %d\n", __func__, ret); | ||
| 117 | return -EREMOTEIO; | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 121 | /* set pll frequency via the demodulator's I2C register */ | ||
| 122 | static int jdvbt90502_pll_set_freq(struct jdvbt90502_state *state, u32 freq) | ||
| 123 | { | ||
| 124 | int ret; | ||
| 125 | int retry; | ||
| 126 | u8 res1; | ||
| 127 | u8 res2[9]; | ||
| 128 | |||
| 129 | u8 pll_freq_cmd[PLL_CMD_LEN]; | ||
| 130 | u8 pll_agc_cmd[PLL_CMD_LEN]; | ||
| 131 | struct i2c_msg msg[2]; | ||
| 132 | u32 f; | ||
| 133 | |||
| 134 | deb_fe("%s: freq=%d, step=%d\n", __func__, freq, | ||
| 135 | state->frontend.ops.info.frequency_stepsize); | ||
| 136 | /* freq -> oscilator frequency conversion. */ | ||
| 137 | /* freq: 473,000,000 + n*6,000,000 [+ 142857 (center freq. shift)] */ | ||
| 138 | f = freq / state->frontend.ops.info.frequency_stepsize; | ||
| 139 | /* add 399[1/7 MHZ] = 57MHz for the IF */ | ||
| 140 | f += 399; | ||
| 141 | /* add center frequency shift if necessary */ | ||
| 142 | if (f % 7 == 0) | ||
| 143 | f++; | ||
| 144 | pll_freq_cmd[DEMOD_REDIRECT_REG] = JDVBT90502_2ND_I2C_REG; /* 0xFE */ | ||
| 145 | pll_freq_cmd[ADDRESS_BYTE] = state->config.pll_address << 1; | ||
| 146 | pll_freq_cmd[DIVIDER_BYTE1] = (f >> 8) & 0x7F; | ||
| 147 | pll_freq_cmd[DIVIDER_BYTE2] = f & 0xFF; | ||
| 148 | pll_freq_cmd[CONTROL_BYTE] = 0xB2; /* ref.divider:28, 4MHz/28=1/7MHz */ | ||
| 149 | pll_freq_cmd[BANDSWITCH_BYTE] = 0x08; /* UHF band */ | ||
| 150 | |||
| 151 | msg[0].addr = state->config.demod_address; | ||
| 152 | msg[0].flags = 0; | ||
| 153 | msg[0].buf = pll_freq_cmd; | ||
| 154 | msg[0].len = sizeof(pll_freq_cmd); | ||
| 155 | |||
| 156 | ret = i2c_transfer(state->i2c, &msg[0], 1); | ||
| 157 | if (ret != 1) | ||
| 158 | goto error; | ||
| 159 | |||
| 160 | udelay(50); | ||
| 161 | |||
| 162 | pll_agc_cmd[DEMOD_REDIRECT_REG] = pll_freq_cmd[DEMOD_REDIRECT_REG]; | ||
| 163 | pll_agc_cmd[ADDRESS_BYTE] = pll_freq_cmd[ADDRESS_BYTE]; | ||
| 164 | pll_agc_cmd[DIVIDER_BYTE1] = pll_freq_cmd[DIVIDER_BYTE1]; | ||
| 165 | pll_agc_cmd[DIVIDER_BYTE2] = pll_freq_cmd[DIVIDER_BYTE2]; | ||
| 166 | pll_agc_cmd[CONTROL_BYTE] = 0x9A; /* AGC_CTRL instead of BANDSWITCH */ | ||
| 167 | pll_agc_cmd[AGC_CTRL_BYTE] = 0x50; | ||
| 168 | /* AGC Time Constant 2s, AGC take-over point:103dBuV(lowest) */ | ||
| 169 | |||
| 170 | msg[1].addr = msg[0].addr; | ||
| 171 | msg[1].flags = 0; | ||
| 172 | msg[1].buf = pll_agc_cmd; | ||
| 173 | msg[1].len = sizeof(pll_agc_cmd); | ||
| 174 | |||
| 175 | ret = i2c_transfer(state->i2c, &msg[1], 1); | ||
| 176 | if (ret != 1) | ||
| 177 | goto error; | ||
| 178 | |||
| 179 | /* I don't know what these cmds are for, */ | ||
| 180 | /* but the USB log on a windows box contains them */ | ||
| 181 | ret = jdvbt90502_single_reg_write(state, 0x01, 0x40); | ||
| 182 | ret |= jdvbt90502_single_reg_write(state, 0x01, 0x00); | ||
| 183 | if (ret) | ||
| 184 | goto error; | ||
| 185 | udelay(100); | ||
| 186 | |||
| 187 | /* wait for the demod to be ready? */ | ||
| 188 | #define RETRY_COUNT 5 | ||
| 189 | for (retry = 0; retry < RETRY_COUNT; retry++) { | ||
| 190 | ret = jdvbt90502_reg_read(state, 0x0096, &res1, 1); | ||
| 191 | if (ret) | ||
| 192 | goto error; | ||
| 193 | /* if (res1 != 0x00) goto error; */ | ||
| 194 | ret = jdvbt90502_reg_read(state, 0x00B0, res2, sizeof(res2)); | ||
| 195 | if (ret) | ||
| 196 | goto error; | ||
| 197 | if (res2[0] >= 0xA7) | ||
| 198 | break; | ||
| 199 | msleep(100); | ||
| 200 | } | ||
| 201 | if (retry >= RETRY_COUNT) { | ||
| 202 | deb_fe("%s: FE does not get ready after freq setting.\n", | ||
| 203 | __func__); | ||
| 204 | return -EREMOTEIO; | ||
| 205 | } | ||
| 206 | |||
| 207 | return 0; | ||
| 208 | error: | ||
| 209 | deb_fe("%s:ret == %d\n", __func__, ret); | ||
| 210 | return -EREMOTEIO; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int jdvbt90502_read_status(struct dvb_frontend *fe, fe_status_t *state) | ||
| 214 | { | ||
| 215 | u8 result; | ||
| 216 | int ret; | ||
| 217 | |||
| 218 | *state = FE_HAS_SIGNAL; | ||
| 219 | |||
| 220 | ret = jdvbt90502_pll_read(fe->demodulator_priv, &result); | ||
| 221 | if (ret) { | ||
| 222 | deb_fe("%s:ret == %d\n", __func__, ret); | ||
| 223 | return -EREMOTEIO; | ||
| 224 | } | ||
| 225 | |||
| 226 | *state = FE_HAS_SIGNAL | ||
| 227 | | FE_HAS_CARRIER | ||
| 228 | | FE_HAS_VITERBI | ||
| 229 | | FE_HAS_SYNC; | ||
| 230 | |||
| 231 | if (result & PLL_STATUS_LOCKED) | ||
| 232 | *state |= FE_HAS_LOCK; | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int jdvbt90502_read_signal_strength(struct dvb_frontend *fe, | ||
| 238 | u16 *strength) | ||
| 239 | { | ||
| 240 | int ret; | ||
| 241 | u8 rbuf[37]; | ||
| 242 | |||
| 243 | *strength = 0; | ||
| 244 | |||
| 245 | /* status register (incl. signal strength) : 0x89 */ | ||
| 246 | /* TODO: read just the necessary registers [0x8B..0x8D]? */ | ||
| 247 | ret = jdvbt90502_reg_read(fe->demodulator_priv, 0x0089, | ||
| 248 | rbuf, sizeof(rbuf)); | ||
| 249 | |||
| 250 | if (ret) { | ||
| 251 | deb_fe("%s:ret == %d\n", __func__, ret); | ||
| 252 | return -EREMOTEIO; | ||
| 253 | } | ||
| 254 | |||
| 255 | /* signal_strength: rbuf[2-4] (24bit BE), use lower 16bit for now. */ | ||
| 256 | *strength = (rbuf[3] << 8) + rbuf[4]; | ||
| 257 | if (rbuf[2]) | ||
| 258 | *strength = 0xffff; | ||
| 259 | |||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | |||
| 264 | /* filter out un-supported properties to notify users */ | ||
| 265 | static int jdvbt90502_set_property(struct dvb_frontend *fe, | ||
| 266 | struct dtv_property *tvp) | ||
| 267 | { | ||
| 268 | int r = 0; | ||
| 269 | |||
| 270 | switch (tvp->cmd) { | ||
| 271 | case DTV_DELIVERY_SYSTEM: | ||
| 272 | if (tvp->u.data != SYS_ISDBT) | ||
| 273 | r = -EINVAL; | ||
| 274 | break; | ||
| 275 | case DTV_CLEAR: | ||
| 276 | case DTV_TUNE: | ||
| 277 | case DTV_FREQUENCY: | ||
| 278 | break; | ||
| 279 | default: | ||
| 280 | r = -EINVAL; | ||
| 281 | } | ||
| 282 | return r; | ||
| 283 | } | ||
| 284 | |||
| 285 | static int jdvbt90502_get_frontend(struct dvb_frontend *fe, | ||
| 286 | struct dvb_frontend_parameters *p) | ||
| 287 | { | ||
| 288 | p->inversion = INVERSION_AUTO; | ||
| 289 | p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; | ||
| 290 | p->u.ofdm.code_rate_HP = FEC_AUTO; | ||
| 291 | p->u.ofdm.code_rate_LP = FEC_AUTO; | ||
| 292 | p->u.ofdm.constellation = QAM_64; | ||
| 293 | p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; | ||
| 294 | p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; | ||
| 295 | p->u.ofdm.hierarchy_information = HIERARCHY_AUTO; | ||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | static int jdvbt90502_set_frontend(struct dvb_frontend *fe, | ||
| 300 | struct dvb_frontend_parameters *p) | ||
| 301 | { | ||
| 302 | /** | ||
| 303 | * NOTE: ignore all the parameters except frequency. | ||
| 304 | * others should be fixed to the proper value for ISDB-T, | ||
| 305 | * but don't check here. | ||
| 306 | */ | ||
| 307 | |||
| 308 | struct jdvbt90502_state *state = fe->demodulator_priv; | ||
| 309 | int ret; | ||
| 310 | |||
| 311 | deb_fe("%s: Freq:%d\n", __func__, p->frequency); | ||
| 312 | |||
| 313 | /* for recovery from DTV_CLEAN */ | ||
| 314 | fe->dtv_property_cache.delivery_system = SYS_ISDBT; | ||
| 315 | |||
| 316 | ret = jdvbt90502_pll_set_freq(state, p->frequency); | ||
| 317 | if (ret) { | ||
| 318 | deb_fe("%s:ret == %d\n", __func__, ret); | ||
| 319 | return -EREMOTEIO; | ||
| 320 | } | ||
| 321 | |||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | |||
| 326 | /** | ||
| 327 | * (reg, val) commad list to initialize this module. | ||
| 328 | * captured on a Windows box. | ||
| 329 | */ | ||
| 330 | static u8 init_code[][2] = { | ||
| 331 | {0x01, 0x40}, | ||
| 332 | {0x04, 0x38}, | ||
| 333 | {0x05, 0x40}, | ||
| 334 | {0x07, 0x40}, | ||
| 335 | {0x0F, 0x4F}, | ||
| 336 | {0x11, 0x21}, | ||
| 337 | {0x12, 0x0B}, | ||
| 338 | {0x13, 0x2F}, | ||
| 339 | {0x14, 0x31}, | ||
| 340 | {0x16, 0x02}, | ||
| 341 | {0x21, 0xC4}, | ||
| 342 | {0x22, 0x20}, | ||
| 343 | {0x2C, 0x79}, | ||
| 344 | {0x2D, 0x34}, | ||
| 345 | {0x2F, 0x00}, | ||
| 346 | {0x30, 0x28}, | ||
| 347 | {0x31, 0x31}, | ||
| 348 | {0x32, 0xDF}, | ||
| 349 | {0x38, 0x01}, | ||
| 350 | {0x39, 0x78}, | ||
| 351 | {0x3B, 0x33}, | ||
| 352 | {0x3C, 0x33}, | ||
| 353 | {0x48, 0x90}, | ||
| 354 | {0x51, 0x68}, | ||
| 355 | {0x5E, 0x38}, | ||
| 356 | {0x71, 0x00}, | ||
| 357 | {0x72, 0x08}, | ||
| 358 | {0x77, 0x00}, | ||
| 359 | {0xC0, 0x21}, | ||
| 360 | {0xC1, 0x10}, | ||
| 361 | {0xE4, 0x1A}, | ||
| 362 | {0xEA, 0x1F}, | ||
| 363 | {0x77, 0x00}, | ||
| 364 | {0x71, 0x00}, | ||
| 365 | {0x71, 0x00}, | ||
| 366 | {0x76, 0x0C}, | ||
| 367 | }; | ||
| 368 | |||
| 369 | static const int init_code_len = sizeof(init_code) / sizeof(u8[2]); | ||
| 370 | |||
| 371 | static int jdvbt90502_init(struct dvb_frontend *fe) | ||
| 372 | { | ||
| 373 | int i = -1; | ||
| 374 | int ret; | ||
| 375 | struct i2c_msg msg; | ||
| 376 | |||
| 377 | struct jdvbt90502_state *state = fe->demodulator_priv; | ||
| 378 | |||
| 379 | deb_fe("%s called.\n", __func__); | ||
| 380 | |||
| 381 | msg.addr = state->config.demod_address; | ||
| 382 | msg.flags = 0; | ||
| 383 | msg.len = 2; | ||
| 384 | for (i = 0; i < init_code_len; i++) { | ||
| 385 | msg.buf = init_code[i]; | ||
| 386 | ret = i2c_transfer(state->i2c, &msg, 1); | ||
| 387 | if (ret != 1) | ||
| 388 | goto error; | ||
| 389 | } | ||
| 390 | fe->dtv_property_cache.delivery_system = SYS_ISDBT; | ||
| 391 | msleep(100); | ||
| 392 | |||
| 393 | return 0; | ||
| 394 | |||
| 395 | error: | ||
| 396 | deb_fe("%s: init_code[%d] failed. ret==%d\n", __func__, i, ret); | ||
| 397 | return -EREMOTEIO; | ||
| 398 | } | ||
| 399 | |||
| 400 | |||
| 401 | static void jdvbt90502_release(struct dvb_frontend *fe) | ||
| 402 | { | ||
| 403 | struct jdvbt90502_state *state = fe->demodulator_priv; | ||
| 404 | kfree(state); | ||
| 405 | } | ||
| 406 | |||
| 407 | |||
| 408 | static struct dvb_frontend_ops jdvbt90502_ops; | ||
| 409 | |||
| 410 | struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d) | ||
| 411 | { | ||
| 412 | struct jdvbt90502_state *state = NULL; | ||
| 413 | |||
| 414 | deb_info("%s called.\n", __func__); | ||
| 415 | |||
| 416 | /* allocate memory for the internal state */ | ||
| 417 | state = kzalloc(sizeof(struct jdvbt90502_state), GFP_KERNEL); | ||
| 418 | if (state == NULL) | ||
| 419 | goto error; | ||
| 420 | |||
| 421 | /* setup the state */ | ||
| 422 | state->i2c = &d->i2c_adap; | ||
| 423 | memcpy(&state->config, &friio_fe_config, sizeof(friio_fe_config)); | ||
| 424 | |||
| 425 | /* create dvb_frontend */ | ||
| 426 | memcpy(&state->frontend.ops, &jdvbt90502_ops, | ||
| 427 | sizeof(jdvbt90502_ops)); | ||
| 428 | state->frontend.demodulator_priv = state; | ||
| 429 | |||
| 430 | if (jdvbt90502_init(&state->frontend) < 0) | ||
| 431 | goto error; | ||
| 432 | |||
| 433 | return &state->frontend; | ||
| 434 | |||
| 435 | error: | ||
| 436 | kfree(state); | ||
| 437 | return NULL; | ||
| 438 | } | ||
| 439 | |||
| 440 | static struct dvb_frontend_ops jdvbt90502_ops = { | ||
| 441 | |||
| 442 | .info = { | ||
| 443 | .name = "Comtech JDVBT90502 ISDB-T", | ||
| 444 | .type = FE_OFDM, | ||
| 445 | .frequency_min = 473000000, /* UHF 13ch, center */ | ||
| 446 | .frequency_max = 767142857, /* UHF 62ch, center */ | ||
| 447 | .frequency_stepsize = JDVBT90502_PLL_CLK / | ||
| 448 | JDVBT90502_PLL_DIVIDER, | ||
| 449 | .frequency_tolerance = 0, | ||
| 450 | |||
| 451 | /* NOTE: this driver ignores all parameters but frequency. */ | ||
| 452 | .caps = FE_CAN_INVERSION_AUTO | | ||
| 453 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 454 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | | ||
| 455 | FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | | ||
| 456 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
| 457 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
| 458 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
| 459 | FE_CAN_HIERARCHY_AUTO, | ||
| 460 | }, | ||
| 461 | |||
| 462 | .release = jdvbt90502_release, | ||
| 463 | |||
| 464 | .init = jdvbt90502_init, | ||
| 465 | .write = _jdvbt90502_write, | ||
| 466 | |||
| 467 | .set_property = jdvbt90502_set_property, | ||
| 468 | |||
| 469 | .set_frontend = jdvbt90502_set_frontend, | ||
| 470 | .get_frontend = jdvbt90502_get_frontend, | ||
| 471 | |||
| 472 | .read_status = jdvbt90502_read_status, | ||
| 473 | .read_signal_strength = jdvbt90502_read_signal_strength, | ||
| 474 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/friio.c b/drivers/media/dvb/dvb-usb/friio.c new file mode 100644 index 00000000000..76159aed9bb --- /dev/null +++ b/drivers/media/dvb/dvb-usb/friio.c | |||
| @@ -0,0 +1,540 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp> | ||
| 4 | * | ||
| 5 | * This module is based off the the gl861 and vp702x modules. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation, version 2. | ||
| 10 | * | ||
| 11 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 12 | */ | ||
| 13 | #include "friio.h" | ||
| 14 | |||
| 15 | /* debug */ | ||
| 16 | int dvb_usb_friio_debug; | ||
| 17 | module_param_named(debug, dvb_usb_friio_debug, int, 0644); | ||
| 18 | MODULE_PARM_DESC(debug, | ||
| 19 | "set debugging level (1=info,2=xfer,4=rc,8=fe (or-able))." | ||
| 20 | DVB_USB_DEBUG_STATUS); | ||
| 21 | |||
| 22 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 23 | |||
| 24 | /** | ||
| 25 | * Indirect I2C access to the PLL via FE. | ||
| 26 | * whole I2C protocol data to the PLL is sent via the FE's I2C register. | ||
| 27 | * This is done by a control msg to the FE with the I2C data accompanied, and | ||
| 28 | * a specific USB request number is assigned for that purpose. | ||
| 29 | * | ||
| 30 | * this func sends wbuf[1..] to the I2C register wbuf[0] at addr (= at FE). | ||
| 31 | * TODO: refoctored, smarter i2c functions. | ||
| 32 | */ | ||
| 33 | static int gl861_i2c_ctrlmsg_data(struct dvb_usb_device *d, u8 addr, | ||
| 34 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
| 35 | { | ||
| 36 | u16 index = wbuf[0]; /* must be JDVBT90502_2ND_I2C_REG(=0xFE) */ | ||
| 37 | u16 value = addr << (8 + 1); | ||
| 38 | int wo = (rbuf == NULL || rlen == 0); /* write only */ | ||
| 39 | u8 req, type; | ||
| 40 | |||
| 41 | deb_xfer("write to PLL:0x%02x via FE reg:0x%02x, len:%d\n", | ||
| 42 | wbuf[1], wbuf[0], wlen - 1); | ||
| 43 | |||
| 44 | if (wo && wlen >= 2) { | ||
| 45 | req = GL861_REQ_I2C_DATA_CTRL_WRITE; | ||
| 46 | type = GL861_WRITE; | ||
| 47 | udelay(20); | ||
| 48 | return usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), | ||
| 49 | req, type, value, index, | ||
| 50 | &wbuf[1], wlen - 1, 2000); | ||
| 51 | } | ||
| 52 | |||
| 53 | deb_xfer("not supported ctrl-msg, aborting."); | ||
| 54 | return -EINVAL; | ||
| 55 | } | ||
| 56 | |||
| 57 | /* normal I2C access (without extra data arguments). | ||
| 58 | * write to the register wbuf[0] at I2C address addr with the value wbuf[1], | ||
| 59 | * or read from the register wbuf[0]. | ||
| 60 | * register address can be 16bit (wbuf[2]<<8 | wbuf[0]) if wlen==3 | ||
| 61 | */ | ||
| 62 | static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
| 63 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
| 64 | { | ||
| 65 | u16 index; | ||
| 66 | u16 value = addr << (8 + 1); | ||
| 67 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
| 68 | u8 req, type; | ||
| 69 | unsigned int pipe; | ||
| 70 | |||
| 71 | /* special case for the indirect I2C access to the PLL via FE, */ | ||
| 72 | if (addr == friio_fe_config.demod_address && | ||
| 73 | wbuf[0] == JDVBT90502_2ND_I2C_REG) | ||
| 74 | return gl861_i2c_ctrlmsg_data(d, addr, wbuf, wlen, rbuf, rlen); | ||
| 75 | |||
| 76 | if (wo) { | ||
| 77 | req = GL861_REQ_I2C_WRITE; | ||
| 78 | type = GL861_WRITE; | ||
| 79 | pipe = usb_sndctrlpipe(d->udev, 0); | ||
| 80 | } else { /* rw */ | ||
| 81 | req = GL861_REQ_I2C_READ; | ||
| 82 | type = GL861_READ; | ||
| 83 | pipe = usb_rcvctrlpipe(d->udev, 0); | ||
| 84 | } | ||
| 85 | |||
| 86 | switch (wlen) { | ||
| 87 | case 1: | ||
| 88 | index = wbuf[0]; | ||
| 89 | break; | ||
| 90 | case 2: | ||
| 91 | index = wbuf[0]; | ||
| 92 | value = value + wbuf[1]; | ||
| 93 | break; | ||
| 94 | case 3: | ||
| 95 | /* special case for 16bit register-address */ | ||
| 96 | index = (wbuf[2] << 8) | wbuf[0]; | ||
| 97 | value = value + wbuf[1]; | ||
| 98 | break; | ||
| 99 | default: | ||
| 100 | deb_xfer("wlen = %x, aborting.", wlen); | ||
| 101 | return -EINVAL; | ||
| 102 | } | ||
| 103 | msleep(1); | ||
| 104 | return usb_control_msg(d->udev, pipe, req, type, | ||
| 105 | value, index, rbuf, rlen, 2000); | ||
| 106 | } | ||
| 107 | |||
| 108 | /* I2C */ | ||
| 109 | static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 110 | int num) | ||
| 111 | { | ||
| 112 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 113 | int i; | ||
| 114 | |||
| 115 | |||
| 116 | if (num > 2) | ||
| 117 | return -EINVAL; | ||
| 118 | |||
| 119 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 120 | return -EAGAIN; | ||
| 121 | |||
| 122 | for (i = 0; i < num; i++) { | ||
| 123 | /* write/read request */ | ||
| 124 | if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) { | ||
| 125 | if (gl861_i2c_msg(d, msg[i].addr, | ||
| 126 | msg[i].buf, msg[i].len, | ||
| 127 | msg[i + 1].buf, msg[i + 1].len) < 0) | ||
| 128 | break; | ||
| 129 | i++; | ||
| 130 | } else | ||
| 131 | if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
| 132 | msg[i].len, NULL, 0) < 0) | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | |||
| 136 | mutex_unlock(&d->i2c_mutex); | ||
| 137 | return i; | ||
| 138 | } | ||
| 139 | |||
| 140 | static u32 gl861_i2c_func(struct i2c_adapter *adapter) | ||
| 141 | { | ||
| 142 | return I2C_FUNC_I2C; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int friio_ext_ctl(struct dvb_usb_adapter *adap, | ||
| 146 | u32 sat_color, int lnb_on) | ||
| 147 | { | ||
| 148 | int i; | ||
| 149 | int ret; | ||
| 150 | struct i2c_msg msg; | ||
| 151 | u8 *buf; | ||
| 152 | u32 mask; | ||
| 153 | u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0; | ||
| 154 | |||
| 155 | buf = kmalloc(2, GFP_KERNEL); | ||
| 156 | if (!buf) | ||
| 157 | return -ENOMEM; | ||
| 158 | |||
| 159 | msg.addr = 0x00; | ||
| 160 | msg.flags = 0; | ||
| 161 | msg.len = 2; | ||
| 162 | msg.buf = buf; | ||
| 163 | |||
| 164 | buf[0] = 0x00; | ||
| 165 | |||
| 166 | /* send 2bit header (&B10) */ | ||
| 167 | buf[1] = lnb | FRIIO_CTL_LED | FRIIO_CTL_STROBE; | ||
| 168 | ret = gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
| 169 | buf[1] |= FRIIO_CTL_CLK; | ||
| 170 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
| 171 | |||
| 172 | buf[1] = lnb | FRIIO_CTL_STROBE; | ||
| 173 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
| 174 | buf[1] |= FRIIO_CTL_CLK; | ||
| 175 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
| 176 | |||
| 177 | /* send 32bit(satur, R, G, B) data in serial */ | ||
| 178 | mask = 1 << 31; | ||
| 179 | for (i = 0; i < 32; i++) { | ||
| 180 | buf[1] = lnb | FRIIO_CTL_STROBE; | ||
| 181 | if (sat_color & mask) | ||
| 182 | buf[1] |= FRIIO_CTL_LED; | ||
| 183 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
| 184 | buf[1] |= FRIIO_CTL_CLK; | ||
| 185 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
| 186 | mask >>= 1; | ||
| 187 | } | ||
| 188 | |||
| 189 | /* set the strobe off */ | ||
| 190 | buf[1] = lnb; | ||
| 191 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
| 192 | buf[1] |= FRIIO_CTL_CLK; | ||
| 193 | ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1); | ||
| 194 | |||
| 195 | kfree(buf); | ||
| 196 | return (ret == 70); | ||
| 197 | } | ||
| 198 | |||
| 199 | |||
| 200 | static int friio_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); | ||
| 201 | |||
| 202 | /* TODO: move these init cmds to the FE's init routine? */ | ||
| 203 | static u8 streaming_init_cmds[][2] = { | ||
| 204 | {0x33, 0x08}, | ||
| 205 | {0x37, 0x40}, | ||
| 206 | {0x3A, 0x1F}, | ||
| 207 | {0x3B, 0xFF}, | ||
| 208 | {0x3C, 0x1F}, | ||
| 209 | {0x3D, 0xFF}, | ||
| 210 | {0x38, 0x00}, | ||
| 211 | {0x35, 0x00}, | ||
| 212 | {0x39, 0x00}, | ||
| 213 | {0x36, 0x00}, | ||
| 214 | }; | ||
| 215 | static int cmdlen = sizeof(streaming_init_cmds) / 2; | ||
| 216 | |||
| 217 | /* | ||
| 218 | * Command sequence in this init function is a replay | ||
| 219 | * of the captured USB commands from the Windows proprietary driver. | ||
| 220 | */ | ||
| 221 | static int friio_initialize(struct dvb_usb_device *d) | ||
| 222 | { | ||
| 223 | int ret; | ||
| 224 | int i; | ||
| 225 | int retry = 0; | ||
| 226 | u8 *rbuf, *wbuf; | ||
| 227 | |||
| 228 | deb_info("%s called.\n", __func__); | ||
| 229 | |||
| 230 | wbuf = kmalloc(3, GFP_KERNEL); | ||
| 231 | if (!wbuf) | ||
| 232 | return -ENOMEM; | ||
| 233 | |||
| 234 | rbuf = kmalloc(2, GFP_KERNEL); | ||
| 235 | if (!rbuf) { | ||
| 236 | kfree(wbuf); | ||
| 237 | return -ENOMEM; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* use gl861_i2c_msg instead of gl861_i2c_xfer(), */ | ||
| 241 | /* because the i2c device is not set up yet. */ | ||
| 242 | wbuf[0] = 0x11; | ||
| 243 | wbuf[1] = 0x02; | ||
| 244 | ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); | ||
| 245 | if (ret < 0) | ||
| 246 | goto error; | ||
| 247 | msleep(2); | ||
| 248 | |||
| 249 | wbuf[0] = 0x11; | ||
| 250 | wbuf[1] = 0x00; | ||
| 251 | ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); | ||
| 252 | if (ret < 0) | ||
| 253 | goto error; | ||
| 254 | msleep(1); | ||
| 255 | |||
| 256 | /* following msgs should be in the FE's init code? */ | ||
| 257 | /* cmd sequence to identify the device type? (friio black/white) */ | ||
| 258 | wbuf[0] = 0x03; | ||
| 259 | wbuf[1] = 0x80; | ||
| 260 | /* can't use gl861_i2c_cmd, as the register-addr is 16bit(0x0100) */ | ||
| 261 | ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), | ||
| 262 | GL861_REQ_I2C_DATA_CTRL_WRITE, GL861_WRITE, | ||
| 263 | 0x1200, 0x0100, wbuf, 2, 2000); | ||
| 264 | if (ret < 0) | ||
| 265 | goto error; | ||
| 266 | |||
| 267 | msleep(2); | ||
| 268 | wbuf[0] = 0x00; | ||
| 269 | wbuf[2] = 0x01; /* reg.0x0100 */ | ||
| 270 | wbuf[1] = 0x00; | ||
| 271 | ret = gl861_i2c_msg(d, 0x12 >> 1, wbuf, 3, rbuf, 2); | ||
| 272 | /* my Friio White returns 0xffff. */ | ||
| 273 | if (ret < 0 || rbuf[0] != 0xff || rbuf[1] != 0xff) | ||
| 274 | goto error; | ||
| 275 | |||
| 276 | msleep(2); | ||
| 277 | wbuf[0] = 0x03; | ||
| 278 | wbuf[1] = 0x80; | ||
| 279 | ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), | ||
| 280 | GL861_REQ_I2C_DATA_CTRL_WRITE, GL861_WRITE, | ||
| 281 | 0x9000, 0x0100, wbuf, 2, 2000); | ||
| 282 | if (ret < 0) | ||
| 283 | goto error; | ||
| 284 | |||
| 285 | msleep(2); | ||
| 286 | wbuf[0] = 0x00; | ||
| 287 | wbuf[2] = 0x01; /* reg.0x0100 */ | ||
| 288 | wbuf[1] = 0x00; | ||
| 289 | ret = gl861_i2c_msg(d, 0x90 >> 1, wbuf, 3, rbuf, 2); | ||
| 290 | /* my Friio White returns 0xffff again. */ | ||
| 291 | if (ret < 0 || rbuf[0] != 0xff || rbuf[1] != 0xff) | ||
| 292 | goto error; | ||
| 293 | |||
| 294 | msleep(1); | ||
| 295 | |||
| 296 | restart: | ||
| 297 | /* ============ start DEMOD init cmds ================== */ | ||
| 298 | /* read PLL status to clear the POR bit */ | ||
| 299 | wbuf[0] = JDVBT90502_2ND_I2C_REG; | ||
| 300 | wbuf[1] = (FRIIO_PLL_ADDR << 1) + 1; /* +1 for reading */ | ||
| 301 | ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 2, NULL, 0); | ||
| 302 | if (ret < 0) | ||
| 303 | goto error; | ||
| 304 | |||
| 305 | msleep(5); | ||
| 306 | /* note: DEMODULATOR has 16bit register-address. */ | ||
| 307 | wbuf[0] = 0x00; | ||
| 308 | wbuf[2] = 0x01; /* reg addr: 0x0100 */ | ||
| 309 | wbuf[1] = 0x00; /* val: not used */ | ||
| 310 | ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 3, rbuf, 1); | ||
| 311 | if (ret < 0) | ||
| 312 | goto error; | ||
| 313 | /* | ||
| 314 | msleep(1); | ||
| 315 | wbuf[0] = 0x80; | ||
| 316 | wbuf[1] = 0x00; | ||
| 317 | ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 2, rbuf, 1); | ||
| 318 | if (ret < 0) | ||
| 319 | goto error; | ||
| 320 | */ | ||
| 321 | if (rbuf[0] & 0x80) { /* still in PowerOnReset state? */ | ||
| 322 | if (++retry > 3) { | ||
| 323 | deb_info("failed to get the correct" | ||
| 324 | " FE demod status:0x%02x\n", rbuf[0]); | ||
| 325 | goto error; | ||
| 326 | } | ||
| 327 | msleep(100); | ||
| 328 | goto restart; | ||
| 329 | } | ||
| 330 | |||
| 331 | /* TODO: check return value in rbuf */ | ||
| 332 | /* =========== end DEMOD init cmds ===================== */ | ||
| 333 | msleep(1); | ||
| 334 | |||
| 335 | wbuf[0] = 0x30; | ||
| 336 | wbuf[1] = 0x04; | ||
| 337 | ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); | ||
| 338 | if (ret < 0) | ||
| 339 | goto error; | ||
| 340 | |||
| 341 | msleep(2); | ||
| 342 | /* following 2 cmds unnecessary? */ | ||
| 343 | wbuf[0] = 0x00; | ||
| 344 | wbuf[1] = 0x01; | ||
| 345 | ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); | ||
| 346 | if (ret < 0) | ||
| 347 | goto error; | ||
| 348 | |||
| 349 | wbuf[0] = 0x06; | ||
| 350 | wbuf[1] = 0x0F; | ||
| 351 | ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0); | ||
| 352 | if (ret < 0) | ||
| 353 | goto error; | ||
| 354 | |||
| 355 | /* some streaming ctl cmds (maybe) */ | ||
| 356 | msleep(10); | ||
| 357 | for (i = 0; i < cmdlen; i++) { | ||
| 358 | ret = gl861_i2c_msg(d, 0x00, streaming_init_cmds[i], 2, | ||
| 359 | NULL, 0); | ||
| 360 | if (ret < 0) | ||
| 361 | goto error; | ||
| 362 | msleep(1); | ||
| 363 | } | ||
| 364 | msleep(20); | ||
| 365 | |||
| 366 | /* change the LED color etc. */ | ||
| 367 | ret = friio_streaming_ctrl(&d->adapter[0], 0); | ||
| 368 | if (ret < 0) | ||
| 369 | goto error; | ||
| 370 | |||
| 371 | return 0; | ||
| 372 | |||
| 373 | error: | ||
| 374 | kfree(wbuf); | ||
| 375 | kfree(rbuf); | ||
| 376 | deb_info("%s:ret == %d\n", __func__, ret); | ||
| 377 | return -EIO; | ||
| 378 | } | ||
| 379 | |||
| 380 | /* Callbacks for DVB USB */ | ||
| 381 | |||
| 382 | static int friio_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 383 | { | ||
| 384 | int ret; | ||
| 385 | |||
| 386 | deb_info("%s called.(%d)\n", __func__, onoff); | ||
| 387 | |||
| 388 | /* set the LED color and saturation (and LNB on) */ | ||
| 389 | if (onoff) | ||
| 390 | ret = friio_ext_ctl(adap, 0x6400ff64, 1); | ||
| 391 | else | ||
| 392 | ret = friio_ext_ctl(adap, 0x96ff00ff, 1); | ||
| 393 | |||
| 394 | if (ret != 1) { | ||
| 395 | deb_info("%s failed to send cmdx. ret==%d\n", __func__, ret); | ||
| 396 | return -EREMOTEIO; | ||
| 397 | } | ||
| 398 | return 0; | ||
| 399 | } | ||
| 400 | |||
| 401 | static int friio_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 402 | { | ||
| 403 | if (friio_initialize(adap->dev) < 0) | ||
| 404 | return -EIO; | ||
| 405 | |||
| 406 | adap->fe = jdvbt90502_attach(adap->dev); | ||
| 407 | if (adap->fe == NULL) | ||
| 408 | return -EIO; | ||
| 409 | |||
| 410 | return 0; | ||
| 411 | } | ||
| 412 | |||
| 413 | /* DVB USB Driver stuff */ | ||
| 414 | static struct dvb_usb_device_properties friio_properties; | ||
| 415 | |||
| 416 | static int friio_probe(struct usb_interface *intf, | ||
| 417 | const struct usb_device_id *id) | ||
| 418 | { | ||
| 419 | struct dvb_usb_device *d; | ||
| 420 | struct usb_host_interface *alt; | ||
| 421 | int ret; | ||
| 422 | |||
| 423 | if (intf->num_altsetting < GL861_ALTSETTING_COUNT) | ||
| 424 | return -ENODEV; | ||
| 425 | |||
| 426 | alt = usb_altnum_to_altsetting(intf, FRIIO_BULK_ALTSETTING); | ||
| 427 | if (alt == NULL) { | ||
| 428 | deb_rc("not alt found!\n"); | ||
| 429 | return -ENODEV; | ||
| 430 | } | ||
| 431 | ret = usb_set_interface(interface_to_usbdev(intf), | ||
| 432 | alt->desc.bInterfaceNumber, | ||
| 433 | alt->desc.bAlternateSetting); | ||
| 434 | if (ret != 0) { | ||
| 435 | deb_rc("failed to set alt-setting!\n"); | ||
| 436 | return ret; | ||
| 437 | } | ||
| 438 | |||
| 439 | ret = dvb_usb_device_init(intf, &friio_properties, | ||
| 440 | THIS_MODULE, &d, adapter_nr); | ||
| 441 | if (ret == 0) | ||
| 442 | friio_streaming_ctrl(&d->adapter[0], 1); | ||
| 443 | |||
| 444 | return ret; | ||
| 445 | } | ||
| 446 | |||
| 447 | |||
| 448 | struct jdvbt90502_config friio_fe_config = { | ||
| 449 | .demod_address = FRIIO_DEMOD_ADDR, | ||
| 450 | .pll_address = FRIIO_PLL_ADDR, | ||
| 451 | }; | ||
| 452 | |||
| 453 | static struct i2c_algorithm gl861_i2c_algo = { | ||
| 454 | .master_xfer = gl861_i2c_xfer, | ||
| 455 | .functionality = gl861_i2c_func, | ||
| 456 | }; | ||
| 457 | |||
| 458 | static struct usb_device_id friio_table[] = { | ||
| 459 | { USB_DEVICE(USB_VID_774, USB_PID_FRIIO_WHITE) }, | ||
| 460 | { } /* Terminating entry */ | ||
| 461 | }; | ||
| 462 | MODULE_DEVICE_TABLE(usb, friio_table); | ||
| 463 | |||
| 464 | |||
| 465 | static struct dvb_usb_device_properties friio_properties = { | ||
| 466 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 467 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 468 | |||
| 469 | .size_of_priv = 0, | ||
| 470 | |||
| 471 | .num_adapters = 1, | ||
| 472 | .adapter = { | ||
| 473 | /* caps:0 => no pid filter, 188B TS packet */ | ||
| 474 | /* GL861 has a HW pid filter, but no info available. */ | ||
| 475 | { | ||
| 476 | .caps = 0, | ||
| 477 | |||
| 478 | .frontend_attach = friio_frontend_attach, | ||
| 479 | .streaming_ctrl = friio_streaming_ctrl, | ||
| 480 | |||
| 481 | .stream = { | ||
| 482 | .type = USB_BULK, | ||
| 483 | /* count <= MAX_NO_URBS_FOR_DATA_STREAM(10) */ | ||
| 484 | .count = 8, | ||
| 485 | .endpoint = 0x01, | ||
| 486 | .u = { | ||
| 487 | /* GL861 has 6KB buf inside */ | ||
| 488 | .bulk = { | ||
| 489 | .buffersize = 16384, | ||
| 490 | } | ||
| 491 | } | ||
| 492 | }, | ||
| 493 | } | ||
| 494 | }, | ||
| 495 | .i2c_algo = &gl861_i2c_algo, | ||
| 496 | |||
| 497 | .num_device_descs = 1, | ||
| 498 | .devices = { | ||
| 499 | { | ||
| 500 | .name = "774 Friio ISDB-T USB2.0", | ||
| 501 | .cold_ids = { NULL }, | ||
| 502 | .warm_ids = { &friio_table[0], NULL }, | ||
| 503 | }, | ||
| 504 | } | ||
| 505 | }; | ||
| 506 | |||
| 507 | static struct usb_driver friio_driver = { | ||
| 508 | .name = "dvb_usb_friio", | ||
| 509 | .probe = friio_probe, | ||
| 510 | .disconnect = dvb_usb_device_exit, | ||
| 511 | .id_table = friio_table, | ||
| 512 | }; | ||
| 513 | |||
| 514 | |||
| 515 | /* module stuff */ | ||
| 516 | static int __init friio_module_init(void) | ||
| 517 | { | ||
| 518 | int ret; | ||
| 519 | |||
| 520 | ret = usb_register(&friio_driver); | ||
| 521 | if (ret) | ||
| 522 | err("usb_register failed. Error number %d", ret); | ||
| 523 | |||
| 524 | return ret; | ||
| 525 | } | ||
| 526 | |||
| 527 | |||
| 528 | static void __exit friio_module_exit(void) | ||
| 529 | { | ||
| 530 | /* deregister this driver from the USB subsystem */ | ||
| 531 | usb_deregister(&friio_driver); | ||
| 532 | } | ||
| 533 | |||
| 534 | module_init(friio_module_init); | ||
| 535 | module_exit(friio_module_exit); | ||
| 536 | |||
| 537 | MODULE_AUTHOR("Akihiro Tsukada <tskd2@yahoo.co.jp>"); | ||
| 538 | MODULE_DESCRIPTION("Driver for Friio ISDB-T USB2.0 Receiver"); | ||
| 539 | MODULE_VERSION("0.2"); | ||
| 540 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/friio.h b/drivers/media/dvb/dvb-usb/friio.h new file mode 100644 index 00000000000..0f461ca10cb --- /dev/null +++ b/drivers/media/dvb/dvb-usb/friio.h | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp> | ||
| 4 | * | ||
| 5 | * This module is based off the the gl861 and vp702x modules. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation, version 2. | ||
| 10 | * | ||
| 11 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 12 | */ | ||
| 13 | #ifndef _DVB_USB_FRIIO_H_ | ||
| 14 | #define _DVB_USB_FRIIO_H_ | ||
| 15 | |||
| 16 | /** | ||
| 17 | * Friio Components | ||
| 18 | * USB hub: AU4254 | ||
| 19 | * USB controller(+ TS dmx & streaming): GL861 | ||
| 20 | * Frontend: comtech JDVBT-90502 | ||
| 21 | * (tuner PLL: tua6034, I2C addr:(0xC0 >> 1)) | ||
| 22 | * (OFDM demodulator: TC90502, I2C addr:(0x30 >> 1)) | ||
| 23 | * LED x3 (+LNB) control: PIC 16F676 | ||
| 24 | * EEPROM: 24C08 | ||
| 25 | * | ||
| 26 | * (USB smart card reader: AU9522) | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | #define DVB_USB_LOG_PREFIX "friio" | ||
| 31 | #include "dvb-usb.h" | ||
| 32 | |||
| 33 | extern int dvb_usb_friio_debug; | ||
| 34 | #define deb_info(args...) dprintk(dvb_usb_friio_debug, 0x01, args) | ||
| 35 | #define deb_xfer(args...) dprintk(dvb_usb_friio_debug, 0x02, args) | ||
| 36 | #define deb_rc(args...) dprintk(dvb_usb_friio_debug, 0x04, args) | ||
| 37 | #define deb_fe(args...) dprintk(dvb_usb_friio_debug, 0x08, args) | ||
| 38 | |||
| 39 | /* Vendor requests */ | ||
| 40 | #define GL861_WRITE 0x40 | ||
| 41 | #define GL861_READ 0xc0 | ||
| 42 | |||
| 43 | /* command bytes */ | ||
| 44 | #define GL861_REQ_I2C_WRITE 0x01 | ||
| 45 | #define GL861_REQ_I2C_READ 0x02 | ||
| 46 | /* For control msg with data argument */ | ||
| 47 | /* Used for accessing the PLL on the secondary I2C bus of FE via GL861 */ | ||
| 48 | #define GL861_REQ_I2C_DATA_CTRL_WRITE 0x03 | ||
| 49 | |||
| 50 | #define GL861_ALTSETTING_COUNT 2 | ||
| 51 | #define FRIIO_BULK_ALTSETTING 0 | ||
| 52 | #define FRIIO_ISOC_ALTSETTING 1 | ||
| 53 | |||
| 54 | /* LED & LNB control via PIC. */ | ||
| 55 | /* basically, it's serial control with clock and strobe. */ | ||
| 56 | /* write the below 4bit control data to the reg 0x00 at the I2C addr 0x00 */ | ||
| 57 | /* when controlling the LEDs, 32bit(saturation, R, G, B) is sent on the bit3*/ | ||
| 58 | #define FRIIO_CTL_LNB (1 << 0) | ||
| 59 | #define FRIIO_CTL_STROBE (1 << 1) | ||
| 60 | #define FRIIO_CTL_CLK (1 << 2) | ||
| 61 | #define FRIIO_CTL_LED (1 << 3) | ||
| 62 | |||
| 63 | /* Front End related */ | ||
| 64 | |||
| 65 | #define FRIIO_DEMOD_ADDR (0x30 >> 1) | ||
| 66 | #define FRIIO_PLL_ADDR (0xC0 >> 1) | ||
| 67 | |||
| 68 | #define JDVBT90502_PLL_CLK 4000000 | ||
| 69 | #define JDVBT90502_PLL_DIVIDER 28 | ||
| 70 | |||
| 71 | #define JDVBT90502_2ND_I2C_REG 0xFE | ||
| 72 | |||
| 73 | /* byte index for pll i2c command data structure*/ | ||
| 74 | /* see datasheet for tua6034 */ | ||
| 75 | #define DEMOD_REDIRECT_REG 0 | ||
| 76 | #define ADDRESS_BYTE 1 | ||
| 77 | #define DIVIDER_BYTE1 2 | ||
| 78 | #define DIVIDER_BYTE2 3 | ||
| 79 | #define CONTROL_BYTE 4 | ||
| 80 | #define BANDSWITCH_BYTE 5 | ||
| 81 | #define AGC_CTRL_BYTE 5 | ||
| 82 | #define PLL_CMD_LEN 6 | ||
| 83 | |||
| 84 | /* bit masks for PLL STATUS response */ | ||
| 85 | #define PLL_STATUS_POR_MODE 0x80 /* 1: Power on Reset (test) Mode */ | ||
| 86 | #define PLL_STATUS_LOCKED 0x40 /* 1: locked */ | ||
| 87 | #define PLL_STATUS_AGC_ACTIVE 0x08 /* 1:active */ | ||
| 88 | #define PLL_STATUS_TESTMODE 0x07 /* digital output level (5 level) */ | ||
| 89 | /* 0.15Vcc step 0x00: < 0.15Vcc, ..., 0x04: >= 0.6Vcc (<= 1Vcc) */ | ||
| 90 | |||
| 91 | |||
| 92 | struct jdvbt90502_config { | ||
| 93 | u8 demod_address; /* i2c addr for demodulator IC */ | ||
| 94 | u8 pll_address; /* PLL addr on the secondary i2c*/ | ||
| 95 | }; | ||
| 96 | extern struct jdvbt90502_config friio_fe_config; | ||
| 97 | |||
| 98 | extern struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d); | ||
| 99 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c new file mode 100644 index 00000000000..6f596ed4176 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gl861.c | |||
| @@ -0,0 +1,233 @@ | |||
| 1 | /* DVB USB compliant linux driver for GL861 USB2.0 devices. | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify it | ||
| 4 | * under the terms of the GNU General Public License as published by the | ||
| 5 | * Free Software Foundation, version 2. | ||
| 6 | * | ||
| 7 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 8 | */ | ||
| 9 | #include "gl861.h" | ||
| 10 | |||
| 11 | #include "zl10353.h" | ||
| 12 | #include "qt1010.h" | ||
| 13 | |||
| 14 | /* debug */ | ||
| 15 | static int dvb_usb_gl861_debug; | ||
| 16 | module_param_named(debug, dvb_usb_gl861_debug, int, 0644); | ||
| 17 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." | ||
| 18 | DVB_USB_DEBUG_STATUS); | ||
| 19 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 20 | |||
| 21 | static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
| 22 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
| 23 | { | ||
| 24 | u16 index; | ||
| 25 | u16 value = addr << (8 + 1); | ||
| 26 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
| 27 | u8 req, type; | ||
| 28 | |||
| 29 | if (wo) { | ||
| 30 | req = GL861_REQ_I2C_WRITE; | ||
| 31 | type = GL861_WRITE; | ||
| 32 | } else { /* rw */ | ||
| 33 | req = GL861_REQ_I2C_READ; | ||
| 34 | type = GL861_READ; | ||
| 35 | } | ||
| 36 | |||
| 37 | switch (wlen) { | ||
| 38 | case 1: | ||
| 39 | index = wbuf[0]; | ||
| 40 | break; | ||
| 41 | case 2: | ||
| 42 | index = wbuf[0]; | ||
| 43 | value = value + wbuf[1]; | ||
| 44 | break; | ||
| 45 | default: | ||
| 46 | warn("wlen = %x, aborting.", wlen); | ||
| 47 | return -EINVAL; | ||
| 48 | } | ||
| 49 | |||
| 50 | msleep(1); /* avoid I2C errors */ | ||
| 51 | |||
| 52 | return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, | ||
| 53 | value, index, rbuf, rlen, 2000); | ||
| 54 | } | ||
| 55 | |||
| 56 | /* I2C */ | ||
| 57 | static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 58 | int num) | ||
| 59 | { | ||
| 60 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 61 | int i; | ||
| 62 | |||
| 63 | if (num > 2) | ||
| 64 | return -EINVAL; | ||
| 65 | |||
| 66 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 67 | return -EAGAIN; | ||
| 68 | |||
| 69 | for (i = 0; i < num; i++) { | ||
| 70 | /* write/read request */ | ||
| 71 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
| 72 | if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
| 73 | msg[i].len, msg[i+1].buf, msg[i+1].len) < 0) | ||
| 74 | break; | ||
| 75 | i++; | ||
| 76 | } else | ||
| 77 | if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
| 78 | msg[i].len, NULL, 0) < 0) | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | |||
| 82 | mutex_unlock(&d->i2c_mutex); | ||
| 83 | return i; | ||
| 84 | } | ||
| 85 | |||
| 86 | static u32 gl861_i2c_func(struct i2c_adapter *adapter) | ||
| 87 | { | ||
| 88 | return I2C_FUNC_I2C; | ||
| 89 | } | ||
| 90 | |||
| 91 | static struct i2c_algorithm gl861_i2c_algo = { | ||
| 92 | .master_xfer = gl861_i2c_xfer, | ||
| 93 | .functionality = gl861_i2c_func, | ||
| 94 | }; | ||
| 95 | |||
| 96 | /* Callbacks for DVB USB */ | ||
| 97 | static struct zl10353_config gl861_zl10353_config = { | ||
| 98 | .demod_address = 0x0f, | ||
| 99 | .no_tuner = 1, | ||
| 100 | .parallel_ts = 1, | ||
| 101 | }; | ||
| 102 | |||
| 103 | static int gl861_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 104 | { | ||
| 105 | |||
| 106 | adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config, | ||
| 107 | &adap->dev->i2c_adap); | ||
| 108 | if (adap->fe == NULL) | ||
| 109 | return -EIO; | ||
| 110 | |||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static struct qt1010_config gl861_qt1010_config = { | ||
| 115 | .i2c_address = 0x62 | ||
| 116 | }; | ||
| 117 | |||
| 118 | static int gl861_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 119 | { | ||
| 120 | return dvb_attach(qt1010_attach, | ||
| 121 | adap->fe, &adap->dev->i2c_adap, | ||
| 122 | &gl861_qt1010_config) == NULL ? -ENODEV : 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | /* DVB USB Driver stuff */ | ||
| 126 | static struct dvb_usb_device_properties gl861_properties; | ||
| 127 | |||
| 128 | static int gl861_probe(struct usb_interface *intf, | ||
| 129 | const struct usb_device_id *id) | ||
| 130 | { | ||
| 131 | struct dvb_usb_device *d; | ||
| 132 | struct usb_host_interface *alt; | ||
| 133 | int ret; | ||
| 134 | |||
| 135 | if (intf->num_altsetting < 2) | ||
| 136 | return -ENODEV; | ||
| 137 | |||
| 138 | ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d, | ||
| 139 | adapter_nr); | ||
| 140 | if (ret == 0) { | ||
| 141 | alt = usb_altnum_to_altsetting(intf, 0); | ||
| 142 | |||
| 143 | if (alt == NULL) { | ||
| 144 | deb_rc("not alt found!\n"); | ||
| 145 | return -ENODEV; | ||
| 146 | } | ||
| 147 | |||
| 148 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, | ||
| 149 | alt->desc.bAlternateSetting); | ||
| 150 | } | ||
| 151 | |||
| 152 | return ret; | ||
| 153 | } | ||
| 154 | |||
| 155 | static struct usb_device_id gl861_table [] = { | ||
| 156 | { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801) }, | ||
| 157 | { USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) }, | ||
| 158 | { } /* Terminating entry */ | ||
| 159 | }; | ||
| 160 | MODULE_DEVICE_TABLE(usb, gl861_table); | ||
| 161 | |||
| 162 | static struct dvb_usb_device_properties gl861_properties = { | ||
| 163 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 164 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 165 | |||
| 166 | .size_of_priv = 0, | ||
| 167 | |||
| 168 | .num_adapters = 1, | ||
| 169 | .adapter = {{ | ||
| 170 | |||
| 171 | .frontend_attach = gl861_frontend_attach, | ||
| 172 | .tuner_attach = gl861_tuner_attach, | ||
| 173 | |||
| 174 | .stream = { | ||
| 175 | .type = USB_BULK, | ||
| 176 | .count = 7, | ||
| 177 | .endpoint = 0x81, | ||
| 178 | .u = { | ||
| 179 | .bulk = { | ||
| 180 | .buffersize = 512, | ||
| 181 | } | ||
| 182 | } | ||
| 183 | }, | ||
| 184 | } }, | ||
| 185 | .i2c_algo = &gl861_i2c_algo, | ||
| 186 | |||
| 187 | .num_device_descs = 2, | ||
| 188 | .devices = { | ||
| 189 | { | ||
| 190 | .name = "MSI Mega Sky 55801 DVB-T USB2.0", | ||
| 191 | .cold_ids = { NULL }, | ||
| 192 | .warm_ids = { &gl861_table[0], NULL }, | ||
| 193 | }, | ||
| 194 | { | ||
| 195 | .name = "A-LINK DTU DVB-T USB2.0", | ||
| 196 | .cold_ids = { NULL }, | ||
| 197 | .warm_ids = { &gl861_table[1], NULL }, | ||
| 198 | }, | ||
| 199 | } | ||
| 200 | }; | ||
| 201 | |||
| 202 | static struct usb_driver gl861_driver = { | ||
| 203 | .name = "dvb_usb_gl861", | ||
| 204 | .probe = gl861_probe, | ||
| 205 | .disconnect = dvb_usb_device_exit, | ||
| 206 | .id_table = gl861_table, | ||
| 207 | }; | ||
| 208 | |||
| 209 | /* module stuff */ | ||
| 210 | static int __init gl861_module_init(void) | ||
| 211 | { | ||
| 212 | int ret; | ||
| 213 | |||
| 214 | ret = usb_register(&gl861_driver); | ||
| 215 | if (ret) | ||
| 216 | err("usb_register failed. Error number %d", ret); | ||
| 217 | |||
| 218 | return ret; | ||
| 219 | } | ||
| 220 | |||
| 221 | static void __exit gl861_module_exit(void) | ||
| 222 | { | ||
| 223 | /* deregister this driver from the USB subsystem */ | ||
| 224 | usb_deregister(&gl861_driver); | ||
| 225 | } | ||
| 226 | |||
| 227 | module_init(gl861_module_init); | ||
| 228 | module_exit(gl861_module_exit); | ||
| 229 | |||
| 230 | MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>"); | ||
| 231 | MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861"); | ||
| 232 | MODULE_VERSION("0.1"); | ||
| 233 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/gl861.h b/drivers/media/dvb/dvb-usb/gl861.h new file mode 100644 index 00000000000..c54855e2c23 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gl861.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #ifndef _DVB_USB_GL861_H_ | ||
| 2 | #define _DVB_USB_GL861_H_ | ||
| 3 | |||
| 4 | #define DVB_USB_LOG_PREFIX "gl861" | ||
| 5 | #include "dvb-usb.h" | ||
| 6 | |||
| 7 | #define deb_rc(args...) dprintk(dvb_usb_gl861_debug, 0x01, args) | ||
| 8 | |||
| 9 | #define GL861_WRITE 0x40 | ||
| 10 | #define GL861_READ 0xc0 | ||
| 11 | |||
| 12 | #define GL861_REQ_I2C_WRITE 0x01 | ||
| 13 | #define GL861_REQ_I2C_READ 0x02 | ||
| 14 | |||
| 15 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c new file mode 100644 index 00000000000..60d11e57e7d --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c | |||
| @@ -0,0 +1,378 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the | ||
| 2 | * - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com) | ||
| 5 | * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com) | ||
| 6 | * | ||
| 7 | * Thanks to GENPIX for the sample code used to implement this module. | ||
| 8 | * | ||
| 9 | * This module is based off the vp7045 and vp702x modules | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License as published by the Free | ||
| 13 | * Software Foundation, version 2. | ||
| 14 | * | ||
| 15 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 16 | */ | ||
| 17 | #include "gp8psk.h" | ||
| 18 | |||
| 19 | struct gp8psk_fe_state { | ||
| 20 | struct dvb_frontend fe; | ||
| 21 | struct dvb_usb_device *d; | ||
| 22 | u8 lock; | ||
| 23 | u16 snr; | ||
| 24 | unsigned long next_status_check; | ||
| 25 | unsigned long status_check_interval; | ||
| 26 | }; | ||
| 27 | |||
| 28 | static int gp8psk_tuned_to_DCII(struct dvb_frontend *fe) | ||
| 29 | { | ||
| 30 | struct gp8psk_fe_state *st = fe->demodulator_priv; | ||
| 31 | u8 status; | ||
| 32 | gp8psk_usb_in_op(st->d, GET_8PSK_CONFIG, 0, 0, &status, 1); | ||
| 33 | return status & bmDCtuned; | ||
| 34 | } | ||
| 35 | |||
| 36 | static int gp8psk_set_tuner_mode(struct dvb_frontend *fe, int mode) | ||
| 37 | { | ||
| 38 | struct gp8psk_fe_state *state = fe->demodulator_priv; | ||
| 39 | return gp8psk_usb_out_op(state->d, SET_8PSK_CONFIG, mode, 0, NULL, 0); | ||
| 40 | } | ||
| 41 | |||
| 42 | static int gp8psk_fe_update_status(struct gp8psk_fe_state *st) | ||
| 43 | { | ||
| 44 | u8 buf[6]; | ||
| 45 | if (time_after(jiffies,st->next_status_check)) { | ||
| 46 | gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0,0,&st->lock,1); | ||
| 47 | gp8psk_usb_in_op(st->d, GET_SIGNAL_STRENGTH, 0,0,buf,6); | ||
| 48 | st->snr = (buf[1]) << 8 | buf[0]; | ||
| 49 | st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000; | ||
| 50 | } | ||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) | ||
| 55 | { | ||
| 56 | struct gp8psk_fe_state *st = fe->demodulator_priv; | ||
| 57 | gp8psk_fe_update_status(st); | ||
| 58 | |||
| 59 | if (st->lock) | ||
| 60 | *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
| 61 | else | ||
| 62 | *status = 0; | ||
| 63 | |||
| 64 | if (*status & FE_HAS_LOCK) | ||
| 65 | st->status_check_interval = 1000; | ||
| 66 | else | ||
| 67 | st->status_check_interval = 100; | ||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | /* not supported by this Frontend */ | ||
| 72 | static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber) | ||
| 73 | { | ||
| 74 | (void) fe; | ||
| 75 | *ber = 0; | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | /* not supported by this Frontend */ | ||
| 80 | static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | ||
| 81 | { | ||
| 82 | (void) fe; | ||
| 83 | *unc = 0; | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
| 88 | { | ||
| 89 | struct gp8psk_fe_state *st = fe->demodulator_priv; | ||
| 90 | gp8psk_fe_update_status(st); | ||
| 91 | /* snr is reported in dBu*256 */ | ||
| 92 | *snr = st->snr; | ||
| 93 | return 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) | ||
| 97 | { | ||
| 98 | struct gp8psk_fe_state *st = fe->demodulator_priv; | ||
| 99 | gp8psk_fe_update_status(st); | ||
| 100 | /* snr is reported in dBu*256 */ | ||
| 101 | /* snr / 38.4 ~= 100% strength */ | ||
| 102 | /* snr * 17 returns 100% strength as 65535 */ | ||
| 103 | if (st->snr > 0xf00) | ||
| 104 | *strength = 0xffff; | ||
| 105 | else | ||
| 106 | *strength = (st->snr << 4) + st->snr; /* snr*17 */ | ||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
| 111 | { | ||
| 112 | tune->min_delay_ms = 800; | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int gp8psk_fe_set_property(struct dvb_frontend *fe, | ||
| 117 | struct dtv_property *tvp) | ||
| 118 | { | ||
| 119 | deb_fe("%s(..)\n", __func__); | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static int gp8psk_fe_get_property(struct dvb_frontend *fe, | ||
| 124 | struct dtv_property *tvp) | ||
| 125 | { | ||
| 126 | deb_fe("%s(..)\n", __func__); | ||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | |||
| 131 | static int gp8psk_fe_set_frontend(struct dvb_frontend* fe, | ||
| 132 | struct dvb_frontend_parameters *fep) | ||
| 133 | { | ||
| 134 | struct gp8psk_fe_state *state = fe->demodulator_priv; | ||
| 135 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 136 | u8 cmd[10]; | ||
| 137 | u32 freq = fep->frequency * 1000; | ||
| 138 | int gp_product_id = le16_to_cpu(state->d->udev->descriptor.idProduct); | ||
| 139 | |||
| 140 | deb_fe("%s()\n", __func__); | ||
| 141 | |||
| 142 | cmd[4] = freq & 0xff; | ||
| 143 | cmd[5] = (freq >> 8) & 0xff; | ||
| 144 | cmd[6] = (freq >> 16) & 0xff; | ||
| 145 | cmd[7] = (freq >> 24) & 0xff; | ||
| 146 | |||
| 147 | switch (c->delivery_system) { | ||
| 148 | case SYS_DVBS: | ||
| 149 | /* Allow QPSK and 8PSK (even for DVB-S) */ | ||
| 150 | if (c->modulation != QPSK && c->modulation != PSK_8) { | ||
| 151 | deb_fe("%s: unsupported modulation selected (%d)\n", | ||
| 152 | __func__, c->modulation); | ||
| 153 | return -EOPNOTSUPP; | ||
| 154 | } | ||
| 155 | c->fec_inner = FEC_AUTO; | ||
| 156 | break; | ||
| 157 | case SYS_DVBS2: | ||
| 158 | deb_fe("%s: DVB-S2 delivery system selected\n", __func__); | ||
| 159 | break; | ||
| 160 | |||
| 161 | default: | ||
| 162 | deb_fe("%s: unsupported delivery system selected (%d)\n", | ||
| 163 | __func__, c->delivery_system); | ||
| 164 | return -EOPNOTSUPP; | ||
| 165 | } | ||
| 166 | |||
| 167 | cmd[0] = c->symbol_rate & 0xff; | ||
| 168 | cmd[1] = (c->symbol_rate >> 8) & 0xff; | ||
| 169 | cmd[2] = (c->symbol_rate >> 16) & 0xff; | ||
| 170 | cmd[3] = (c->symbol_rate >> 24) & 0xff; | ||
| 171 | switch (c->modulation) { | ||
| 172 | case QPSK: | ||
| 173 | if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) | ||
| 174 | if (gp8psk_tuned_to_DCII(fe)) | ||
| 175 | gp8psk_bcm4500_reload(state->d); | ||
| 176 | switch (c->fec_inner) { | ||
| 177 | case FEC_1_2: | ||
| 178 | cmd[9] = 0; break; | ||
| 179 | case FEC_2_3: | ||
| 180 | cmd[9] = 1; break; | ||
| 181 | case FEC_3_4: | ||
| 182 | cmd[9] = 2; break; | ||
| 183 | case FEC_5_6: | ||
| 184 | cmd[9] = 3; break; | ||
| 185 | case FEC_7_8: | ||
| 186 | cmd[9] = 4; break; | ||
| 187 | case FEC_AUTO: | ||
| 188 | cmd[9] = 5; break; | ||
| 189 | default: | ||
| 190 | cmd[9] = 5; break; | ||
| 191 | } | ||
| 192 | cmd[8] = ADV_MOD_DVB_QPSK; | ||
| 193 | break; | ||
| 194 | case PSK_8: /* PSK_8 is for compatibility with DN */ | ||
| 195 | cmd[8] = ADV_MOD_TURBO_8PSK; | ||
| 196 | switch (c->fec_inner) { | ||
| 197 | case FEC_2_3: | ||
| 198 | cmd[9] = 0; break; | ||
| 199 | case FEC_3_4: | ||
| 200 | cmd[9] = 1; break; | ||
| 201 | case FEC_3_5: | ||
| 202 | cmd[9] = 2; break; | ||
| 203 | case FEC_5_6: | ||
| 204 | cmd[9] = 3; break; | ||
| 205 | case FEC_8_9: | ||
| 206 | cmd[9] = 4; break; | ||
| 207 | default: | ||
| 208 | cmd[9] = 0; break; | ||
| 209 | } | ||
| 210 | break; | ||
| 211 | case QAM_16: /* QAM_16 is for compatibility with DN */ | ||
| 212 | cmd[8] = ADV_MOD_TURBO_16QAM; | ||
| 213 | cmd[9] = 0; | ||
| 214 | break; | ||
| 215 | default: /* Unknown modulation */ | ||
| 216 | deb_fe("%s: unsupported modulation selected (%d)\n", | ||
| 217 | __func__, c->modulation); | ||
| 218 | return -EOPNOTSUPP; | ||
| 219 | } | ||
| 220 | |||
| 221 | if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) | ||
| 222 | gp8psk_set_tuner_mode(fe, 0); | ||
| 223 | gp8psk_usb_out_op(state->d, TUNE_8PSK, 0, 0, cmd, 10); | ||
| 224 | |||
| 225 | state->lock = 0; | ||
| 226 | state->next_status_check = jiffies; | ||
| 227 | state->status_check_interval = 200; | ||
| 228 | |||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe, | ||
| 233 | struct dvb_diseqc_master_cmd *m) | ||
| 234 | { | ||
| 235 | struct gp8psk_fe_state *st = fe->demodulator_priv; | ||
| 236 | |||
| 237 | deb_fe("%s\n",__func__); | ||
| 238 | |||
| 239 | if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0, | ||
| 240 | m->msg, m->msg_len)) { | ||
| 241 | return -EINVAL; | ||
| 242 | } | ||
| 243 | return 0; | ||
| 244 | } | ||
| 245 | |||
| 246 | static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe, | ||
| 247 | fe_sec_mini_cmd_t burst) | ||
| 248 | { | ||
| 249 | struct gp8psk_fe_state *st = fe->demodulator_priv; | ||
| 250 | u8 cmd; | ||
| 251 | |||
| 252 | deb_fe("%s\n",__func__); | ||
| 253 | |||
| 254 | /* These commands are certainly wrong */ | ||
| 255 | cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01; | ||
| 256 | |||
| 257 | if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0, | ||
| 258 | &cmd, 0)) { | ||
| 259 | return -EINVAL; | ||
| 260 | } | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | ||
| 265 | { | ||
| 266 | struct gp8psk_fe_state* state = fe->demodulator_priv; | ||
| 267 | |||
| 268 | if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE, | ||
| 269 | (tone == SEC_TONE_ON), 0, NULL, 0)) { | ||
| 270 | return -EINVAL; | ||
| 271 | } | ||
| 272 | return 0; | ||
| 273 | } | ||
| 274 | |||
| 275 | static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) | ||
| 276 | { | ||
| 277 | struct gp8psk_fe_state* state = fe->demodulator_priv; | ||
| 278 | |||
| 279 | if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, | ||
| 280 | voltage == SEC_VOLTAGE_18, 0, NULL, 0)) { | ||
| 281 | return -EINVAL; | ||
| 282 | } | ||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | static int gp8psk_fe_enable_high_lnb_voltage(struct dvb_frontend* fe, long onoff) | ||
| 287 | { | ||
| 288 | struct gp8psk_fe_state* state = fe->demodulator_priv; | ||
| 289 | return gp8psk_usb_out_op(state->d, USE_EXTRA_VOLT, onoff, 0,NULL,0); | ||
| 290 | } | ||
| 291 | |||
| 292 | static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd) | ||
| 293 | { | ||
| 294 | struct gp8psk_fe_state* state = fe->demodulator_priv; | ||
| 295 | u8 cmd = sw_cmd & 0x7f; | ||
| 296 | |||
| 297 | if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0, | ||
| 298 | NULL, 0)) { | ||
| 299 | return -EINVAL; | ||
| 300 | } | ||
| 301 | if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80), | ||
| 302 | 0, NULL, 0)) { | ||
| 303 | return -EINVAL; | ||
| 304 | } | ||
| 305 | |||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | static void gp8psk_fe_release(struct dvb_frontend* fe) | ||
| 310 | { | ||
| 311 | struct gp8psk_fe_state *state = fe->demodulator_priv; | ||
| 312 | kfree(state); | ||
| 313 | } | ||
| 314 | |||
| 315 | static struct dvb_frontend_ops gp8psk_fe_ops; | ||
| 316 | |||
| 317 | struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d) | ||
| 318 | { | ||
| 319 | struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL); | ||
| 320 | if (s == NULL) | ||
| 321 | goto error; | ||
| 322 | |||
| 323 | s->d = d; | ||
| 324 | memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops)); | ||
| 325 | s->fe.demodulator_priv = s; | ||
| 326 | |||
| 327 | goto success; | ||
| 328 | error: | ||
| 329 | return NULL; | ||
| 330 | success: | ||
| 331 | return &s->fe; | ||
| 332 | } | ||
| 333 | |||
| 334 | |||
| 335 | static struct dvb_frontend_ops gp8psk_fe_ops = { | ||
| 336 | .info = { | ||
| 337 | .name = "Genpix DVB-S", | ||
| 338 | .type = FE_QPSK, | ||
| 339 | .frequency_min = 800000, | ||
| 340 | .frequency_max = 2250000, | ||
| 341 | .frequency_stepsize = 100, | ||
| 342 | .symbol_rate_min = 1000000, | ||
| 343 | .symbol_rate_max = 45000000, | ||
| 344 | .symbol_rate_tolerance = 500, /* ppm */ | ||
| 345 | .caps = FE_CAN_INVERSION_AUTO | | ||
| 346 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 347 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
| 348 | /* | ||
| 349 | * FE_CAN_QAM_16 is for compatibility | ||
| 350 | * (Myth incorrectly detects Turbo-QPSK as plain QAM-16) | ||
| 351 | */ | ||
| 352 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_TURBO_FEC | ||
| 353 | }, | ||
| 354 | |||
| 355 | .release = gp8psk_fe_release, | ||
| 356 | |||
| 357 | .init = NULL, | ||
| 358 | .sleep = NULL, | ||
| 359 | |||
| 360 | .set_property = gp8psk_fe_set_property, | ||
| 361 | .get_property = gp8psk_fe_get_property, | ||
| 362 | .set_frontend = gp8psk_fe_set_frontend, | ||
| 363 | |||
| 364 | .get_tune_settings = gp8psk_fe_get_tune_settings, | ||
| 365 | |||
| 366 | .read_status = gp8psk_fe_read_status, | ||
| 367 | .read_ber = gp8psk_fe_read_ber, | ||
| 368 | .read_signal_strength = gp8psk_fe_read_signal_strength, | ||
| 369 | .read_snr = gp8psk_fe_read_snr, | ||
| 370 | .read_ucblocks = gp8psk_fe_read_unc_blocks, | ||
| 371 | |||
| 372 | .diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg, | ||
| 373 | .diseqc_send_burst = gp8psk_fe_send_diseqc_burst, | ||
| 374 | .set_tone = gp8psk_fe_set_tone, | ||
| 375 | .set_voltage = gp8psk_fe_set_voltage, | ||
| 376 | .dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd, | ||
| 377 | .enable_high_lnb_voltage = gp8psk_fe_enable_high_lnb_voltage | ||
| 378 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c new file mode 100644 index 00000000000..1cb3d9a66e0 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gp8psk.c | |||
| @@ -0,0 +1,344 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the | ||
| 2 | * - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com) | ||
| 5 | * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com) | ||
| 6 | * | ||
| 7 | * Thanks to GENPIX for the sample code used to implement this module. | ||
| 8 | * | ||
| 9 | * This module is based off the vp7045 and vp702x modules | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License as published by the Free | ||
| 13 | * Software Foundation, version 2. | ||
| 14 | * | ||
| 15 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 16 | */ | ||
| 17 | #include "gp8psk.h" | ||
| 18 | |||
| 19 | /* debug */ | ||
| 20 | static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw"; | ||
| 21 | int dvb_usb_gp8psk_debug; | ||
| 22 | module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644); | ||
| 23 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 24 | |||
| 25 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 26 | |||
| 27 | static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers) | ||
| 28 | { | ||
| 29 | return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6)); | ||
| 30 | } | ||
| 31 | |||
| 32 | static int gp8psk_get_fpga_version(struct dvb_usb_device *d, u8 *fpga_vers) | ||
| 33 | { | ||
| 34 | return (gp8psk_usb_in_op(d, GET_FPGA_VERS, 0, 0, fpga_vers, 1)); | ||
| 35 | } | ||
| 36 | |||
| 37 | static void gp8psk_info(struct dvb_usb_device *d) | ||
| 38 | { | ||
| 39 | u8 fpga_vers, fw_vers[6]; | ||
| 40 | |||
| 41 | if (!gp8psk_get_fw_version(d, fw_vers)) | ||
| 42 | info("FW Version = %i.%02i.%i (0x%x) Build %4i/%02i/%02i", | ||
| 43 | fw_vers[2], fw_vers[1], fw_vers[0], GP8PSK_FW_VERS(fw_vers), | ||
| 44 | 2000 + fw_vers[5], fw_vers[4], fw_vers[3]); | ||
| 45 | else | ||
| 46 | info("failed to get FW version"); | ||
| 47 | |||
| 48 | if (!gp8psk_get_fpga_version(d, &fpga_vers)) | ||
| 49 | info("FPGA Version = %i", fpga_vers); | ||
| 50 | else | ||
| 51 | info("failed to get FPGA version"); | ||
| 52 | } | ||
| 53 | |||
| 54 | int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) | ||
| 55 | { | ||
| 56 | int ret = 0,try = 0; | ||
| 57 | |||
| 58 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) | ||
| 59 | return ret; | ||
| 60 | |||
| 61 | while (ret >= 0 && ret != blen && try < 3) { | ||
| 62 | ret = usb_control_msg(d->udev, | ||
| 63 | usb_rcvctrlpipe(d->udev,0), | ||
| 64 | req, | ||
| 65 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
| 66 | value,index,b,blen, | ||
| 67 | 2000); | ||
| 68 | deb_info("reading number %d (ret: %d)\n",try,ret); | ||
| 69 | try++; | ||
| 70 | } | ||
| 71 | |||
| 72 | if (ret < 0 || ret != blen) { | ||
| 73 | warn("usb in %d operation failed.", req); | ||
| 74 | ret = -EIO; | ||
| 75 | } else | ||
| 76 | ret = 0; | ||
| 77 | |||
| 78 | deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index); | ||
| 79 | debug_dump(b,blen,deb_xfer); | ||
| 80 | |||
| 81 | mutex_unlock(&d->usb_mutex); | ||
| 82 | |||
| 83 | return ret; | ||
| 84 | } | ||
| 85 | |||
| 86 | int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, | ||
| 87 | u16 index, u8 *b, int blen) | ||
| 88 | { | ||
| 89 | int ret; | ||
| 90 | |||
| 91 | deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); | ||
| 92 | debug_dump(b,blen,deb_xfer); | ||
| 93 | |||
| 94 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) | ||
| 95 | return ret; | ||
| 96 | |||
| 97 | if (usb_control_msg(d->udev, | ||
| 98 | usb_sndctrlpipe(d->udev,0), | ||
| 99 | req, | ||
| 100 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 101 | value,index,b,blen, | ||
| 102 | 2000) != blen) { | ||
| 103 | warn("usb out operation failed."); | ||
| 104 | ret = -EIO; | ||
| 105 | } else | ||
| 106 | ret = 0; | ||
| 107 | mutex_unlock(&d->usb_mutex); | ||
| 108 | |||
| 109 | return ret; | ||
| 110 | } | ||
| 111 | |||
| 112 | static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) | ||
| 113 | { | ||
| 114 | int ret; | ||
| 115 | const struct firmware *fw = NULL; | ||
| 116 | const u8 *ptr; | ||
| 117 | u8 *buf; | ||
| 118 | if ((ret = request_firmware(&fw, bcm4500_firmware, | ||
| 119 | &d->udev->dev)) != 0) { | ||
| 120 | err("did not find the bcm4500 firmware file. (%s) " | ||
| 121 | "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)", | ||
| 122 | bcm4500_firmware,ret); | ||
| 123 | return ret; | ||
| 124 | } | ||
| 125 | |||
| 126 | ret = -EINVAL; | ||
| 127 | |||
| 128 | if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0)) | ||
| 129 | goto out_rel_fw; | ||
| 130 | |||
| 131 | info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware); | ||
| 132 | |||
| 133 | ptr = fw->data; | ||
| 134 | buf = kmalloc(64, GFP_KERNEL | GFP_DMA); | ||
| 135 | if (!buf) { | ||
| 136 | ret = -ENOMEM; | ||
| 137 | goto out_rel_fw; | ||
| 138 | } | ||
| 139 | |||
| 140 | while (ptr[0] != 0xff) { | ||
| 141 | u16 buflen = ptr[0] + 4; | ||
| 142 | if (ptr + buflen >= fw->data + fw->size) { | ||
| 143 | err("failed to load bcm4500 firmware."); | ||
| 144 | goto out_free; | ||
| 145 | } | ||
| 146 | memcpy(buf, ptr, buflen); | ||
| 147 | if (dvb_usb_generic_write(d, buf, buflen)) { | ||
| 148 | err("failed to load bcm4500 firmware."); | ||
| 149 | goto out_free; | ||
| 150 | } | ||
| 151 | ptr += buflen; | ||
| 152 | } | ||
| 153 | |||
| 154 | ret = 0; | ||
| 155 | |||
| 156 | out_free: | ||
| 157 | kfree(buf); | ||
| 158 | out_rel_fw: | ||
| 159 | release_firmware(fw); | ||
| 160 | |||
| 161 | return ret; | ||
| 162 | } | ||
| 163 | |||
| 164 | static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 165 | { | ||
| 166 | u8 status, buf; | ||
| 167 | int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct); | ||
| 168 | |||
| 169 | if (onoff) { | ||
| 170 | gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1); | ||
| 171 | if (! (status & bm8pskStarted)) { /* started */ | ||
| 172 | if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K) | ||
| 173 | gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0); | ||
| 174 | if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) | ||
| 175 | return -EINVAL; | ||
| 176 | gp8psk_info(d); | ||
| 177 | } | ||
| 178 | |||
| 179 | if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) | ||
| 180 | if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */ | ||
| 181 | if(gp8psk_load_bcm4500fw(d)) | ||
| 182 | return -EINVAL; | ||
| 183 | |||
| 184 | if (! (status & bmIntersilOn)) /* LNB Power */ | ||
| 185 | if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0, | ||
| 186 | &buf, 1)) | ||
| 187 | return -EINVAL; | ||
| 188 | |||
| 189 | /* Set DVB mode to 1 */ | ||
| 190 | if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) | ||
| 191 | if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0)) | ||
| 192 | return -EINVAL; | ||
| 193 | /* Abort possible TS (if previous tune crashed) */ | ||
| 194 | if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0)) | ||
| 195 | return -EINVAL; | ||
| 196 | } else { | ||
| 197 | /* Turn off LNB power */ | ||
| 198 | if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1)) | ||
| 199 | return -EINVAL; | ||
| 200 | /* Turn off 8psk power */ | ||
| 201 | if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) | ||
| 202 | return -EINVAL; | ||
| 203 | if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K) | ||
| 204 | gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0); | ||
| 205 | } | ||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | int gp8psk_bcm4500_reload(struct dvb_usb_device *d) | ||
| 210 | { | ||
| 211 | u8 buf; | ||
| 212 | int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct); | ||
| 213 | /* Turn off 8psk power */ | ||
| 214 | if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) | ||
| 215 | return -EINVAL; | ||
| 216 | /* Turn On 8psk power */ | ||
| 217 | if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) | ||
| 218 | return -EINVAL; | ||
| 219 | /* load BCM4500 firmware */ | ||
| 220 | if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) | ||
| 221 | if (gp8psk_load_bcm4500fw(d)) | ||
| 222 | return -EINVAL; | ||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 227 | { | ||
| 228 | return gp8psk_usb_out_op(adap->dev, ARM_TRANSFER, onoff, 0 , NULL, 0); | ||
| 229 | } | ||
| 230 | |||
| 231 | static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 232 | { | ||
| 233 | adap->fe = gp8psk_fe_attach(adap->dev); | ||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | static struct dvb_usb_device_properties gp8psk_properties; | ||
| 238 | |||
| 239 | static int gp8psk_usb_probe(struct usb_interface *intf, | ||
| 240 | const struct usb_device_id *id) | ||
| 241 | { | ||
| 242 | int ret; | ||
| 243 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 244 | ret = dvb_usb_device_init(intf, &gp8psk_properties, | ||
| 245 | THIS_MODULE, NULL, adapter_nr); | ||
| 246 | if (ret == 0) { | ||
| 247 | info("found Genpix USB device pID = %x (hex)", | ||
| 248 | le16_to_cpu(udev->descriptor.idProduct)); | ||
| 249 | } | ||
| 250 | return ret; | ||
| 251 | } | ||
| 252 | |||
| 253 | static struct usb_device_id gp8psk_usb_table [] = { | ||
| 254 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_COLD) }, | ||
| 255 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) }, | ||
| 256 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) }, | ||
| 257 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) }, | ||
| 258 | { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_2) }, | ||
| 259 | /* { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */ | ||
| 260 | { 0 }, | ||
| 261 | }; | ||
| 262 | MODULE_DEVICE_TABLE(usb, gp8psk_usb_table); | ||
| 263 | |||
| 264 | static struct dvb_usb_device_properties gp8psk_properties = { | ||
| 265 | .usb_ctrl = CYPRESS_FX2, | ||
| 266 | .firmware = "dvb-usb-gp8psk-01.fw", | ||
| 267 | |||
| 268 | .num_adapters = 1, | ||
| 269 | .adapter = { | ||
| 270 | { | ||
| 271 | .streaming_ctrl = gp8psk_streaming_ctrl, | ||
| 272 | .frontend_attach = gp8psk_frontend_attach, | ||
| 273 | /* parameter for the MPEG2-data transfer */ | ||
| 274 | .stream = { | ||
| 275 | .type = USB_BULK, | ||
| 276 | .count = 7, | ||
| 277 | .endpoint = 0x82, | ||
| 278 | .u = { | ||
| 279 | .bulk = { | ||
| 280 | .buffersize = 8192, | ||
| 281 | } | ||
| 282 | } | ||
| 283 | }, | ||
| 284 | } | ||
| 285 | }, | ||
| 286 | .power_ctrl = gp8psk_power_ctrl, | ||
| 287 | |||
| 288 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 289 | |||
| 290 | .num_device_descs = 4, | ||
| 291 | .devices = { | ||
| 292 | { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver", | ||
| 293 | .cold_ids = { &gp8psk_usb_table[0], NULL }, | ||
| 294 | .warm_ids = { &gp8psk_usb_table[1], NULL }, | ||
| 295 | }, | ||
| 296 | { .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver", | ||
| 297 | .cold_ids = { NULL }, | ||
| 298 | .warm_ids = { &gp8psk_usb_table[2], NULL }, | ||
| 299 | }, | ||
| 300 | { .name = "Genpix SkyWalker-1 DVB-S receiver", | ||
| 301 | .cold_ids = { NULL }, | ||
| 302 | .warm_ids = { &gp8psk_usb_table[3], NULL }, | ||
| 303 | }, | ||
| 304 | { .name = "Genpix SkyWalker-2 DVB-S receiver", | ||
| 305 | .cold_ids = { NULL }, | ||
| 306 | .warm_ids = { &gp8psk_usb_table[4], NULL }, | ||
| 307 | }, | ||
| 308 | { NULL }, | ||
| 309 | } | ||
| 310 | }; | ||
| 311 | |||
| 312 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 313 | static struct usb_driver gp8psk_usb_driver = { | ||
| 314 | .name = "dvb_usb_gp8psk", | ||
| 315 | .probe = gp8psk_usb_probe, | ||
| 316 | .disconnect = dvb_usb_device_exit, | ||
| 317 | .id_table = gp8psk_usb_table, | ||
| 318 | }; | ||
| 319 | |||
| 320 | /* module stuff */ | ||
| 321 | static int __init gp8psk_usb_module_init(void) | ||
| 322 | { | ||
| 323 | int result; | ||
| 324 | if ((result = usb_register(&gp8psk_usb_driver))) { | ||
| 325 | err("usb_register failed. (%d)",result); | ||
| 326 | return result; | ||
| 327 | } | ||
| 328 | |||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | static void __exit gp8psk_usb_module_exit(void) | ||
| 333 | { | ||
| 334 | /* deregister this driver from the USB subsystem */ | ||
| 335 | usb_deregister(&gp8psk_usb_driver); | ||
| 336 | } | ||
| 337 | |||
| 338 | module_init(gp8psk_usb_module_init); | ||
| 339 | module_exit(gp8psk_usb_module_exit); | ||
| 340 | |||
| 341 | MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>"); | ||
| 342 | MODULE_DESCRIPTION("Driver for Genpix DVB-S"); | ||
| 343 | MODULE_VERSION("1.1"); | ||
| 344 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h new file mode 100644 index 00000000000..ed32b9da484 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gp8psk.h | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the | ||
| 2 | * - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) | ||
| 5 | * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com) | ||
| 6 | * | ||
| 7 | * Thanks to GENPIX for the sample code used to implement this module. | ||
| 8 | * | ||
| 9 | * This module is based off the vp7045 and vp702x modules | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License as published by the Free | ||
| 13 | * Software Foundation, version 2. | ||
| 14 | * | ||
| 15 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 16 | */ | ||
| 17 | #ifndef _DVB_USB_GP8PSK_H_ | ||
| 18 | #define _DVB_USB_GP8PSK_H_ | ||
| 19 | |||
| 20 | #define DVB_USB_LOG_PREFIX "gp8psk" | ||
| 21 | #include "dvb-usb.h" | ||
| 22 | |||
| 23 | extern int dvb_usb_gp8psk_debug; | ||
| 24 | #define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args) | ||
| 25 | #define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args) | ||
| 26 | #define deb_rc(args...) dprintk(dvb_usb_gp8psk_debug,0x04,args) | ||
| 27 | #define deb_fe(args...) dprintk(dvb_usb_gp8psk_debug,0x08,args) | ||
| 28 | |||
| 29 | /* Twinhan Vendor requests */ | ||
| 30 | #define TH_COMMAND_IN 0xC0 | ||
| 31 | #define TH_COMMAND_OUT 0xC1 | ||
| 32 | |||
| 33 | /* gp8psk commands */ | ||
| 34 | |||
| 35 | #define GET_8PSK_CONFIG 0x80 /* in */ | ||
| 36 | #define SET_8PSK_CONFIG 0x81 | ||
| 37 | #define I2C_WRITE 0x83 | ||
| 38 | #define I2C_READ 0x84 | ||
| 39 | #define ARM_TRANSFER 0x85 | ||
| 40 | #define TUNE_8PSK 0x86 | ||
| 41 | #define GET_SIGNAL_STRENGTH 0x87 /* in */ | ||
| 42 | #define LOAD_BCM4500 0x88 | ||
| 43 | #define BOOT_8PSK 0x89 /* in */ | ||
| 44 | #define START_INTERSIL 0x8A /* in */ | ||
| 45 | #define SET_LNB_VOLTAGE 0x8B | ||
| 46 | #define SET_22KHZ_TONE 0x8C | ||
| 47 | #define SEND_DISEQC_COMMAND 0x8D | ||
| 48 | #define SET_DVB_MODE 0x8E | ||
| 49 | #define SET_DN_SWITCH 0x8F | ||
| 50 | #define GET_SIGNAL_LOCK 0x90 /* in */ | ||
| 51 | #define GET_FW_VERS 0x92 | ||
| 52 | #define GET_SERIAL_NUMBER 0x93 /* in */ | ||
| 53 | #define USE_EXTRA_VOLT 0x94 | ||
| 54 | #define GET_FPGA_VERS 0x95 | ||
| 55 | #define CW3K_INIT 0x9d | ||
| 56 | |||
| 57 | /* PSK_configuration bits */ | ||
| 58 | #define bm8pskStarted 0x01 | ||
| 59 | #define bm8pskFW_Loaded 0x02 | ||
| 60 | #define bmIntersilOn 0x04 | ||
| 61 | #define bmDVBmode 0x08 | ||
| 62 | #define bm22kHz 0x10 | ||
| 63 | #define bmSEL18V 0x20 | ||
| 64 | #define bmDCtuned 0x40 | ||
| 65 | #define bmArmed 0x80 | ||
| 66 | |||
| 67 | /* Satellite modulation modes */ | ||
| 68 | #define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */ | ||
| 69 | #define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */ | ||
| 70 | #define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */ | ||
| 71 | #define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */ | ||
| 72 | |||
| 73 | #define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */ | ||
| 74 | #define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */ | ||
| 75 | #define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */ | ||
| 76 | #define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */ | ||
| 77 | #define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */ | ||
| 78 | #define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */ | ||
| 79 | |||
| 80 | #define GET_USB_SPEED 0x07 | ||
| 81 | |||
| 82 | #define RESET_FX2 0x13 | ||
| 83 | |||
| 84 | #define FW_VERSION_READ 0x0B | ||
| 85 | #define VENDOR_STRING_READ 0x0C | ||
| 86 | #define PRODUCT_STRING_READ 0x0D | ||
| 87 | #define FW_BCD_VERSION_READ 0x14 | ||
| 88 | |||
| 89 | /* firmware revision id's */ | ||
| 90 | #define GP8PSK_FW_REV1 0x020604 | ||
| 91 | #define GP8PSK_FW_REV2 0x020704 | ||
| 92 | #define GP8PSK_FW_VERS(_fw_vers) ((_fw_vers)[2]<<0x10 | (_fw_vers)[1]<<0x08 | (_fw_vers)[0]) | ||
| 93 | |||
| 94 | extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d); | ||
| 95 | extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); | ||
| 96 | extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, | ||
| 97 | u16 index, u8 *b, int blen); | ||
| 98 | extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d); | ||
| 99 | |||
| 100 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c new file mode 100644 index 00000000000..37b146961ae --- /dev/null +++ b/drivers/media/dvb/dvb-usb/lmedm04.c | |||
| @@ -0,0 +1,1310 @@ | |||
| 1 | /* DVB USB compliant linux driver for | ||
| 2 | * | ||
| 3 | * DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395 | ||
| 4 | * LME2510C + LG TDQY-P001F | ||
| 5 | * LME2510C + BS2F7HZ0194 | ||
| 6 | * LME2510 + LG TDQY-P001F | ||
| 7 | * LME2510 + BS2F7HZ0194 | ||
| 8 | * | ||
| 9 | * MVB7395 (LME2510C+SHARP:BS2F7HZ7395) | ||
| 10 | * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V) | ||
| 11 | * | ||
| 12 | * MV001F (LME2510+LGTDQY-P001F) | ||
| 13 | * LG TDQY - P001F =(TDA8263 + TDA10086H) | ||
| 14 | * | ||
| 15 | * MVB0001F (LME2510C+LGTDQT-P001F) | ||
| 16 | * | ||
| 17 | * MV0194 (LME2510+SHARP:BS2F7HZ0194) | ||
| 18 | * SHARP:BS2F7HZ0194 = (STV0299+IX2410) | ||
| 19 | * | ||
| 20 | * MVB0194 (LME2510C+SHARP0194) | ||
| 21 | * | ||
| 22 | * For firmware see Documentation/dvb/lmedm04.txt | ||
| 23 | * | ||
| 24 | * I2C addresses: | ||
| 25 | * 0xd0 - STV0288 - Demodulator | ||
| 26 | * 0xc0 - Sharp IX2505V - Tuner | ||
| 27 | * -- | ||
| 28 | * 0x1c - TDA10086 - Demodulator | ||
| 29 | * 0xc0 - TDA8263 - Tuner | ||
| 30 | * -- | ||
| 31 | * 0xd0 - STV0299 - Demodulator | ||
| 32 | * 0xc0 - IX2410 - Tuner | ||
| 33 | * | ||
| 34 | * | ||
| 35 | * VID = 3344 PID LME2510=1122 LME2510C=1120 | ||
| 36 | * | ||
| 37 | * Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com) | ||
| 38 | * LME2510(C)(C) Leaguerme (Shenzhen) MicroElectronics Co., Ltd. | ||
| 39 | * | ||
| 40 | * This program is free software; you can redistribute it and/or modify | ||
| 41 | * it under the terms of the GNU General Public License Version 2, as | ||
| 42 | * published by the Free Software Foundation. | ||
| 43 | * | ||
| 44 | * This program is distributed in the hope that it will be useful, | ||
| 45 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 46 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 47 | * GNU General Public License for more details. | ||
| 48 | * | ||
| 49 | * You should have received a copy of the GNU General Public License | ||
| 50 | * along with this program; if not, write to the Free Software | ||
| 51 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 52 | * | ||
| 53 | * | ||
| 54 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 55 | * | ||
| 56 | * Known Issues : | ||
| 57 | * LME2510: Non Intel USB chipsets fail to maintain High Speed on | ||
| 58 | * Boot or Hot Plug. | ||
| 59 | * | ||
| 60 | * QQbox suffers from noise on LNB voltage. | ||
| 61 | * | ||
| 62 | * LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system | ||
| 63 | * with other tuners. After a cold reset streaming will not start. | ||
| 64 | * | ||
| 65 | */ | ||
| 66 | #define DVB_USB_LOG_PREFIX "LME2510(C)" | ||
| 67 | #include <linux/usb.h> | ||
| 68 | #include <linux/usb/input.h> | ||
| 69 | #include <media/rc-core.h> | ||
| 70 | |||
| 71 | #include "dvb-usb.h" | ||
| 72 | #include "lmedm04.h" | ||
| 73 | #include "tda826x.h" | ||
| 74 | #include "tda10086.h" | ||
| 75 | #include "stv0288.h" | ||
| 76 | #include "ix2505v.h" | ||
| 77 | #include "stv0299.h" | ||
| 78 | #include "dvb-pll.h" | ||
| 79 | #include "z0194a.h" | ||
| 80 | |||
| 81 | |||
| 82 | |||
| 83 | /* debug */ | ||
| 84 | static int dvb_usb_lme2510_debug; | ||
| 85 | #define l_dprintk(var, level, args...) do { \ | ||
| 86 | if ((var >= level)) \ | ||
| 87 | printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \ | ||
| 88 | } while (0) | ||
| 89 | |||
| 90 | #define deb_info(level, args...) l_dprintk(dvb_usb_lme2510_debug, level, args) | ||
| 91 | #define debug_data_snipet(level, name, p) \ | ||
| 92 | deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \ | ||
| 93 | *p, *(p+1), *(p+2), *(p+3), *(p+4), \ | ||
| 94 | *(p+5), *(p+6), *(p+7)); | ||
| 95 | |||
| 96 | |||
| 97 | module_param_named(debug, dvb_usb_lme2510_debug, int, 0644); | ||
| 98 | MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." | ||
| 99 | DVB_USB_DEBUG_STATUS); | ||
| 100 | |||
| 101 | static int dvb_usb_lme2510_firmware; | ||
| 102 | module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644); | ||
| 103 | MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG"); | ||
| 104 | |||
| 105 | static int pid_filter; | ||
| 106 | module_param_named(pid, pid_filter, int, 0644); | ||
| 107 | MODULE_PARM_DESC(pid, "set default 0=on 1=off"); | ||
| 108 | |||
| 109 | |||
| 110 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 111 | |||
| 112 | #define TUNER_DEFAULT 0x0 | ||
| 113 | #define TUNER_LG 0x1 | ||
| 114 | #define TUNER_S7395 0x2 | ||
| 115 | #define TUNER_S0194 0x3 | ||
| 116 | |||
| 117 | struct lme2510_state { | ||
| 118 | u8 id; | ||
| 119 | u8 tuner_config; | ||
| 120 | u8 signal_lock; | ||
| 121 | u8 signal_level; | ||
| 122 | u8 signal_sn; | ||
| 123 | u8 time_key; | ||
| 124 | u8 i2c_talk_onoff; | ||
| 125 | u8 i2c_gate; | ||
| 126 | u8 i2c_tuner_gate_w; | ||
| 127 | u8 i2c_tuner_gate_r; | ||
| 128 | u8 i2c_tuner_addr; | ||
| 129 | u8 stream_on; | ||
| 130 | u8 pid_size; | ||
| 131 | void *buffer; | ||
| 132 | struct urb *lme_urb; | ||
| 133 | void *usb_buffer; | ||
| 134 | |||
| 135 | }; | ||
| 136 | |||
| 137 | static int lme2510_bulk_write(struct usb_device *dev, | ||
| 138 | u8 *snd, int len, u8 pipe) | ||
| 139 | { | ||
| 140 | int ret, actual_l; | ||
| 141 | |||
| 142 | ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe), | ||
| 143 | snd, len , &actual_l, 100); | ||
| 144 | return ret; | ||
| 145 | } | ||
| 146 | |||
| 147 | static int lme2510_bulk_read(struct usb_device *dev, | ||
| 148 | u8 *rev, int len, u8 pipe) | ||
| 149 | { | ||
| 150 | int ret, actual_l; | ||
| 151 | |||
| 152 | ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe), | ||
| 153 | rev, len , &actual_l, 200); | ||
| 154 | return ret; | ||
| 155 | } | ||
| 156 | |||
| 157 | static int lme2510_usb_talk(struct dvb_usb_device *d, | ||
| 158 | u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
| 159 | { | ||
| 160 | struct lme2510_state *st = d->priv; | ||
| 161 | u8 *buff; | ||
| 162 | int ret = 0; | ||
| 163 | |||
| 164 | if (st->usb_buffer == NULL) { | ||
| 165 | st->usb_buffer = kmalloc(512, GFP_KERNEL); | ||
| 166 | if (st->usb_buffer == NULL) { | ||
| 167 | info("MEM Error no memory"); | ||
| 168 | return -ENOMEM; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | buff = st->usb_buffer; | ||
| 172 | |||
| 173 | ret = mutex_lock_interruptible(&d->usb_mutex); | ||
| 174 | |||
| 175 | if (ret < 0) | ||
| 176 | return -EAGAIN; | ||
| 177 | |||
| 178 | /* the read/write capped at 512 */ | ||
| 179 | memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen); | ||
| 180 | |||
| 181 | ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); | ||
| 182 | |||
| 183 | ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); | ||
| 184 | |||
| 185 | msleep(10); | ||
| 186 | |||
| 187 | ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01)); | ||
| 188 | |||
| 189 | ret |= lme2510_bulk_read(d->udev, buff, (rlen > 512) ? | ||
| 190 | 512 : rlen , 0x01); | ||
| 191 | |||
| 192 | if (rlen > 0) | ||
| 193 | memcpy(rbuf, buff, rlen); | ||
| 194 | |||
| 195 | mutex_unlock(&d->usb_mutex); | ||
| 196 | |||
| 197 | return (ret < 0) ? -ENODEV : 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | static int lme2510_stream_restart(struct dvb_usb_device *d) | ||
| 201 | { | ||
| 202 | static u8 stream_on[] = LME_ST_ON_W; | ||
| 203 | int ret; | ||
| 204 | u8 rbuff[10]; | ||
| 205 | /*Restart Stream Command*/ | ||
| 206 | ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on), | ||
| 207 | rbuff, sizeof(rbuff)); | ||
| 208 | return ret; | ||
| 209 | } | ||
| 210 | |||
| 211 | static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) | ||
| 212 | { | ||
| 213 | struct lme2510_state *st = d->priv; | ||
| 214 | static u8 pid_buff[] = LME_ZERO_PID; | ||
| 215 | static u8 rbuf[1]; | ||
| 216 | u8 pid_no = index * 2; | ||
| 217 | u8 pid_len = pid_no + 2; | ||
| 218 | int ret = 0; | ||
| 219 | deb_info(1, "PID Setting Pid %04x", pid_out); | ||
| 220 | |||
| 221 | if (st->pid_size == 0) | ||
| 222 | ret |= lme2510_stream_restart(d); | ||
| 223 | |||
| 224 | pid_buff[2] = pid_no; | ||
| 225 | pid_buff[3] = (u8)pid_out & 0xff; | ||
| 226 | pid_buff[4] = pid_no + 1; | ||
| 227 | pid_buff[5] = (u8)(pid_out >> 8); | ||
| 228 | |||
| 229 | if (pid_len > st->pid_size) | ||
| 230 | st->pid_size = pid_len; | ||
| 231 | pid_buff[7] = 0x80 + st->pid_size; | ||
| 232 | |||
| 233 | ret |= lme2510_usb_talk(d, pid_buff , | ||
| 234 | sizeof(pid_buff) , rbuf, sizeof(rbuf)); | ||
| 235 | |||
| 236 | if (st->stream_on) | ||
| 237 | ret |= lme2510_stream_restart(d); | ||
| 238 | |||
| 239 | return ret; | ||
| 240 | } | ||
| 241 | |||
| 242 | static void lme2510_int_response(struct urb *lme_urb) | ||
| 243 | { | ||
| 244 | struct dvb_usb_adapter *adap = lme_urb->context; | ||
| 245 | struct lme2510_state *st = adap->dev->priv; | ||
| 246 | static u8 *ibuf, *rbuf; | ||
| 247 | int i = 0, offset; | ||
| 248 | u32 key; | ||
| 249 | |||
| 250 | switch (lme_urb->status) { | ||
| 251 | case 0: | ||
| 252 | case -ETIMEDOUT: | ||
| 253 | break; | ||
| 254 | case -ECONNRESET: | ||
| 255 | case -ENOENT: | ||
| 256 | case -ESHUTDOWN: | ||
| 257 | return; | ||
| 258 | default: | ||
| 259 | info("Error %x", lme_urb->status); | ||
| 260 | break; | ||
| 261 | } | ||
| 262 | |||
| 263 | rbuf = (u8 *) lme_urb->transfer_buffer; | ||
| 264 | |||
| 265 | offset = ((lme_urb->actual_length/8) > 4) | ||
| 266 | ? 4 : (lme_urb->actual_length/8) ; | ||
| 267 | |||
| 268 | for (i = 0; i < offset; ++i) { | ||
| 269 | ibuf = (u8 *)&rbuf[i*8]; | ||
| 270 | deb_info(5, "INT O/S C =%02x C/O=%02x Type =%02x%02x", | ||
| 271 | offset, i, ibuf[0], ibuf[1]); | ||
| 272 | |||
| 273 | switch (ibuf[0]) { | ||
| 274 | case 0xaa: | ||
| 275 | debug_data_snipet(1, "INT Remote data snipet", ibuf); | ||
| 276 | if ((ibuf[4] + ibuf[5]) == 0xff) { | ||
| 277 | key = ibuf[5]; | ||
| 278 | key += (ibuf[3] > 0) | ||
| 279 | ? (ibuf[3] ^ 0xff) << 8 : 0; | ||
| 280 | key += (ibuf[2] ^ 0xff) << 16; | ||
| 281 | deb_info(1, "INT Key =%08x", key); | ||
| 282 | if (adap->dev->rc_dev != NULL) | ||
| 283 | rc_keydown(adap->dev->rc_dev, key, 0); | ||
| 284 | } | ||
| 285 | break; | ||
| 286 | case 0xbb: | ||
| 287 | switch (st->tuner_config) { | ||
| 288 | case TUNER_LG: | ||
| 289 | if (ibuf[2] > 0) | ||
| 290 | st->signal_lock = ibuf[2]; | ||
| 291 | st->signal_level = ibuf[4]; | ||
| 292 | st->signal_sn = ibuf[3]; | ||
| 293 | st->time_key = ibuf[7]; | ||
| 294 | break; | ||
| 295 | case TUNER_S7395: | ||
| 296 | case TUNER_S0194: | ||
| 297 | /* Tweak for earlier firmware*/ | ||
| 298 | if (ibuf[1] == 0x03) { | ||
| 299 | if (ibuf[2] > 1) | ||
| 300 | st->signal_lock = ibuf[2]; | ||
| 301 | st->signal_level = ibuf[3]; | ||
| 302 | st->signal_sn = ibuf[4]; | ||
| 303 | } else { | ||
| 304 | st->signal_level = ibuf[4]; | ||
| 305 | st->signal_sn = ibuf[5]; | ||
| 306 | st->signal_lock = | ||
| 307 | (st->signal_lock & 0xf7) + | ||
| 308 | ((ibuf[2] & 0x01) << 0x03); | ||
| 309 | } | ||
| 310 | break; | ||
| 311 | default: | ||
| 312 | break; | ||
| 313 | } | ||
| 314 | debug_data_snipet(5, "INT Remote data snipet in", ibuf); | ||
| 315 | break; | ||
| 316 | case 0xcc: | ||
| 317 | debug_data_snipet(1, "INT Control data snipet", ibuf); | ||
| 318 | break; | ||
| 319 | default: | ||
| 320 | debug_data_snipet(1, "INT Unknown data snipet", ibuf); | ||
| 321 | break; | ||
| 322 | } | ||
| 323 | } | ||
| 324 | usb_submit_urb(lme_urb, GFP_ATOMIC); | ||
| 325 | } | ||
| 326 | |||
| 327 | static int lme2510_int_read(struct dvb_usb_adapter *adap) | ||
| 328 | { | ||
| 329 | struct lme2510_state *lme_int = adap->dev->priv; | ||
| 330 | |||
| 331 | lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
| 332 | |||
| 333 | if (lme_int->lme_urb == NULL) | ||
| 334 | return -ENOMEM; | ||
| 335 | |||
| 336 | lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 5000, GFP_ATOMIC, | ||
| 337 | &lme_int->lme_urb->transfer_dma); | ||
| 338 | |||
| 339 | if (lme_int->buffer == NULL) | ||
| 340 | return -ENOMEM; | ||
| 341 | |||
| 342 | usb_fill_int_urb(lme_int->lme_urb, | ||
| 343 | adap->dev->udev, | ||
| 344 | usb_rcvintpipe(adap->dev->udev, 0xa), | ||
| 345 | lme_int->buffer, | ||
| 346 | 4096, | ||
| 347 | lme2510_int_response, | ||
| 348 | adap, | ||
| 349 | 11); | ||
| 350 | |||
| 351 | lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 352 | |||
| 353 | usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC); | ||
| 354 | info("INT Interrupt Service Started"); | ||
| 355 | |||
| 356 | return 0; | ||
| 357 | } | ||
| 358 | |||
| 359 | static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 360 | { | ||
| 361 | struct lme2510_state *st = adap->dev->priv; | ||
| 362 | static u8 clear_pid_reg[] = LME_CLEAR_PID; | ||
| 363 | static u8 rbuf[1]; | ||
| 364 | int ret; | ||
| 365 | |||
| 366 | deb_info(1, "PID Clearing Filter"); | ||
| 367 | |||
| 368 | ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); | ||
| 369 | if (ret < 0) | ||
| 370 | return -EAGAIN; | ||
| 371 | |||
| 372 | if (!onoff) | ||
| 373 | ret |= lme2510_usb_talk(adap->dev, clear_pid_reg, | ||
| 374 | sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); | ||
| 375 | |||
| 376 | st->pid_size = 0; | ||
| 377 | |||
| 378 | mutex_unlock(&adap->dev->i2c_mutex); | ||
| 379 | |||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 383 | static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | ||
| 384 | int onoff) | ||
| 385 | { | ||
| 386 | int ret = 0; | ||
| 387 | |||
| 388 | deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__, | ||
| 389 | pid, index, onoff); | ||
| 390 | |||
| 391 | if (onoff) | ||
| 392 | if (!pid_filter) { | ||
| 393 | ret = mutex_lock_interruptible(&adap->dev->i2c_mutex); | ||
| 394 | if (ret < 0) | ||
| 395 | return -EAGAIN; | ||
| 396 | ret |= lme2510_enable_pid(adap->dev, index, pid); | ||
| 397 | mutex_unlock(&adap->dev->i2c_mutex); | ||
| 398 | } | ||
| 399 | |||
| 400 | |||
| 401 | return ret; | ||
| 402 | } | ||
| 403 | |||
| 404 | |||
| 405 | static int lme2510_return_status(struct usb_device *dev) | ||
| 406 | { | ||
| 407 | int ret = 0; | ||
| 408 | u8 *data; | ||
| 409 | |||
| 410 | data = kzalloc(10, GFP_KERNEL); | ||
| 411 | if (!data) | ||
| 412 | return -ENOMEM; | ||
| 413 | |||
| 414 | ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
| 415 | 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); | ||
| 416 | info("Firmware Status: %x (%x)", ret , data[2]); | ||
| 417 | |||
| 418 | ret = (ret < 0) ? -ENODEV : data[2]; | ||
| 419 | kfree(data); | ||
| 420 | return ret; | ||
| 421 | } | ||
| 422 | |||
| 423 | static int lme2510_msg(struct dvb_usb_device *d, | ||
| 424 | u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
| 425 | { | ||
| 426 | int ret = 0; | ||
| 427 | struct lme2510_state *st = d->priv; | ||
| 428 | |||
| 429 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 430 | return -EAGAIN; | ||
| 431 | |||
| 432 | if (st->i2c_talk_onoff == 1) { | ||
| 433 | |||
| 434 | ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | ||
| 435 | |||
| 436 | switch (st->tuner_config) { | ||
| 437 | case TUNER_LG: | ||
| 438 | if (wbuf[2] == 0x1c) { | ||
| 439 | if (wbuf[3] == 0x0e) { | ||
| 440 | st->signal_lock = rbuf[1]; | ||
| 441 | if ((st->stream_on & 1) && | ||
| 442 | (st->signal_lock & 0x10)) { | ||
| 443 | lme2510_stream_restart(d); | ||
| 444 | st->i2c_talk_onoff = 0; | ||
| 445 | } | ||
| 446 | msleep(80); | ||
| 447 | } | ||
| 448 | } | ||
| 449 | break; | ||
| 450 | case TUNER_S7395: | ||
| 451 | if (wbuf[2] == 0xd0) { | ||
| 452 | if (wbuf[3] == 0x24) { | ||
| 453 | st->signal_lock = rbuf[1]; | ||
| 454 | if ((st->stream_on & 1) && | ||
| 455 | (st->signal_lock & 0x8)) { | ||
| 456 | lme2510_stream_restart(d); | ||
| 457 | st->i2c_talk_onoff = 0; | ||
| 458 | } | ||
| 459 | } | ||
| 460 | if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5)) | ||
| 461 | msleep(5); | ||
| 462 | } | ||
| 463 | break; | ||
| 464 | case TUNER_S0194: | ||
| 465 | if (wbuf[2] == 0xd0) { | ||
| 466 | if (wbuf[3] == 0x1b) { | ||
| 467 | st->signal_lock = rbuf[1]; | ||
| 468 | if ((st->stream_on & 1) && | ||
| 469 | (st->signal_lock & 0x8)) { | ||
| 470 | lme2510_stream_restart(d); | ||
| 471 | st->i2c_talk_onoff = 0; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | } | ||
| 475 | break; | ||
| 476 | default: | ||
| 477 | break; | ||
| 478 | } | ||
| 479 | } else { | ||
| 480 | switch (st->tuner_config) { | ||
| 481 | case TUNER_LG: | ||
| 482 | switch (wbuf[3]) { | ||
| 483 | case 0x0e: | ||
| 484 | rbuf[0] = 0x55; | ||
| 485 | rbuf[1] = st->signal_lock; | ||
| 486 | break; | ||
| 487 | case 0x43: | ||
| 488 | rbuf[0] = 0x55; | ||
| 489 | rbuf[1] = st->signal_level; | ||
| 490 | break; | ||
| 491 | case 0x1c: | ||
| 492 | rbuf[0] = 0x55; | ||
| 493 | rbuf[1] = st->signal_sn; | ||
| 494 | break; | ||
| 495 | case 0x15: | ||
| 496 | case 0x16: | ||
| 497 | case 0x17: | ||
| 498 | case 0x18: | ||
| 499 | rbuf[0] = 0x55; | ||
| 500 | rbuf[1] = 0x00; | ||
| 501 | break; | ||
| 502 | default: | ||
| 503 | lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | ||
| 504 | st->i2c_talk_onoff = 1; | ||
| 505 | break; | ||
| 506 | } | ||
| 507 | break; | ||
| 508 | case TUNER_S7395: | ||
| 509 | switch (wbuf[3]) { | ||
| 510 | case 0x10: | ||
| 511 | rbuf[0] = 0x55; | ||
| 512 | rbuf[1] = (st->signal_level & 0x80) | ||
| 513 | ? 0 : (st->signal_level * 2); | ||
| 514 | break; | ||
| 515 | case 0x2d: | ||
| 516 | rbuf[0] = 0x55; | ||
| 517 | rbuf[1] = st->signal_sn; | ||
| 518 | break; | ||
| 519 | case 0x24: | ||
| 520 | rbuf[0] = 0x55; | ||
| 521 | rbuf[1] = st->signal_lock; | ||
| 522 | break; | ||
| 523 | case 0x2e: | ||
| 524 | case 0x26: | ||
| 525 | case 0x27: | ||
| 526 | rbuf[0] = 0x55; | ||
| 527 | rbuf[1] = 0x00; | ||
| 528 | break; | ||
| 529 | default: | ||
| 530 | lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | ||
| 531 | st->i2c_talk_onoff = 1; | ||
| 532 | break; | ||
| 533 | } | ||
| 534 | break; | ||
| 535 | case TUNER_S0194: | ||
| 536 | switch (wbuf[3]) { | ||
| 537 | case 0x18: | ||
| 538 | rbuf[0] = 0x55; | ||
| 539 | rbuf[1] = (st->signal_level & 0x80) | ||
| 540 | ? 0 : (st->signal_level * 2); | ||
| 541 | break; | ||
| 542 | case 0x24: | ||
| 543 | rbuf[0] = 0x55; | ||
| 544 | rbuf[1] = st->signal_sn; | ||
| 545 | break; | ||
| 546 | case 0x1b: | ||
| 547 | rbuf[0] = 0x55; | ||
| 548 | rbuf[1] = st->signal_lock; | ||
| 549 | break; | ||
| 550 | case 0x19: | ||
| 551 | case 0x25: | ||
| 552 | case 0x1e: | ||
| 553 | case 0x1d: | ||
| 554 | rbuf[0] = 0x55; | ||
| 555 | rbuf[1] = 0x00; | ||
| 556 | break; | ||
| 557 | default: | ||
| 558 | lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | ||
| 559 | st->i2c_talk_onoff = 1; | ||
| 560 | break; | ||
| 561 | } | ||
| 562 | break; | ||
| 563 | default: | ||
| 564 | break; | ||
| 565 | } | ||
| 566 | |||
| 567 | deb_info(4, "I2C From Interrupt Message out(%02x) in(%02x)", | ||
| 568 | wbuf[3], rbuf[1]); | ||
| 569 | |||
| 570 | } | ||
| 571 | |||
| 572 | mutex_unlock(&d->i2c_mutex); | ||
| 573 | |||
| 574 | return ret; | ||
| 575 | } | ||
| 576 | |||
| 577 | |||
| 578 | static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 579 | int num) | ||
| 580 | { | ||
| 581 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 582 | struct lme2510_state *st = d->priv; | ||
| 583 | static u8 obuf[64], ibuf[512]; | ||
| 584 | int i, read, read_o; | ||
| 585 | u16 len; | ||
| 586 | u8 gate = st->i2c_gate; | ||
| 587 | |||
| 588 | if (gate == 0) | ||
| 589 | gate = 5; | ||
| 590 | |||
| 591 | if (num > 2) | ||
| 592 | warn("more than 2 i2c messages" | ||
| 593 | "at a time is not handled yet. TODO."); | ||
| 594 | |||
| 595 | for (i = 0; i < num; i++) { | ||
| 596 | read_o = 1 & (msg[i].flags & I2C_M_RD); | ||
| 597 | read = i+1 < num && (msg[i+1].flags & I2C_M_RD); | ||
| 598 | read |= read_o; | ||
| 599 | gate = (msg[i].addr == st->i2c_tuner_addr) | ||
| 600 | ? (read) ? st->i2c_tuner_gate_r | ||
| 601 | : st->i2c_tuner_gate_w | ||
| 602 | : st->i2c_gate; | ||
| 603 | obuf[0] = gate | (read << 7); | ||
| 604 | |||
| 605 | if (gate == 5) | ||
| 606 | obuf[1] = (read) ? 2 : msg[i].len + 1; | ||
| 607 | else | ||
| 608 | obuf[1] = msg[i].len + read + 1; | ||
| 609 | |||
| 610 | obuf[2] = msg[i].addr; | ||
| 611 | if (read) { | ||
| 612 | if (read_o) | ||
| 613 | len = 3; | ||
| 614 | else { | ||
| 615 | memcpy(&obuf[3], msg[i].buf, msg[i].len); | ||
| 616 | obuf[msg[i].len+3] = msg[i+1].len; | ||
| 617 | len = msg[i].len+4; | ||
| 618 | } | ||
| 619 | } else { | ||
| 620 | memcpy(&obuf[3], msg[i].buf, msg[i].len); | ||
| 621 | len = msg[i].len+3; | ||
| 622 | } | ||
| 623 | |||
| 624 | if (lme2510_msg(d, obuf, len, ibuf, 512) < 0) { | ||
| 625 | deb_info(1, "i2c transfer failed."); | ||
| 626 | return -EAGAIN; | ||
| 627 | } | ||
| 628 | |||
| 629 | if (read) { | ||
| 630 | if (read_o) | ||
| 631 | memcpy(msg[i].buf, &ibuf[1], msg[i].len); | ||
| 632 | else { | ||
| 633 | memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len); | ||
| 634 | i++; | ||
| 635 | } | ||
| 636 | } | ||
| 637 | } | ||
| 638 | return i; | ||
| 639 | } | ||
| 640 | |||
| 641 | static u32 lme2510_i2c_func(struct i2c_adapter *adapter) | ||
| 642 | { | ||
| 643 | return I2C_FUNC_I2C; | ||
| 644 | } | ||
| 645 | |||
| 646 | static struct i2c_algorithm lme2510_i2c_algo = { | ||
| 647 | .master_xfer = lme2510_i2c_xfer, | ||
| 648 | .functionality = lme2510_i2c_func, | ||
| 649 | }; | ||
| 650 | |||
| 651 | /* Callbacks for DVB USB */ | ||
| 652 | static int lme2510_identify_state(struct usb_device *udev, | ||
| 653 | struct dvb_usb_device_properties *props, | ||
| 654 | struct dvb_usb_device_description **desc, | ||
| 655 | int *cold) | ||
| 656 | { | ||
| 657 | *cold = 0; | ||
| 658 | return 0; | ||
| 659 | } | ||
| 660 | |||
| 661 | static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 662 | { | ||
| 663 | struct lme2510_state *st = adap->dev->priv; | ||
| 664 | static u8 clear_reg_3[] = LME_CLEAR_PID; | ||
| 665 | static u8 rbuf[1]; | ||
| 666 | int ret = 0, rlen = sizeof(rbuf); | ||
| 667 | |||
| 668 | deb_info(1, "STM (%02x)", onoff); | ||
| 669 | |||
| 670 | /* Streaming is started by FE_HAS_LOCK */ | ||
| 671 | if (onoff == 1) | ||
| 672 | st->stream_on = 1; | ||
| 673 | else { | ||
| 674 | deb_info(1, "STM Steam Off"); | ||
| 675 | /* mutex is here only to avoid collision with I2C */ | ||
| 676 | if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) | ||
| 677 | return -EAGAIN; | ||
| 678 | |||
| 679 | ret = lme2510_usb_talk(adap->dev, clear_reg_3, | ||
| 680 | sizeof(clear_reg_3), rbuf, rlen); | ||
| 681 | st->stream_on = 0; | ||
| 682 | st->i2c_talk_onoff = 1; | ||
| 683 | |||
| 684 | mutex_unlock(&adap->dev->i2c_mutex); | ||
| 685 | } | ||
| 686 | |||
| 687 | return (ret < 0) ? -ENODEV : 0; | ||
| 688 | } | ||
| 689 | |||
| 690 | static u8 check_sum(u8 *p, u8 len) | ||
| 691 | { | ||
| 692 | u8 sum = 0; | ||
| 693 | while (len--) | ||
| 694 | sum += *p++; | ||
| 695 | return sum; | ||
| 696 | } | ||
| 697 | |||
| 698 | static int lme2510_download_firmware(struct usb_device *dev, | ||
| 699 | const struct firmware *fw) | ||
| 700 | { | ||
| 701 | int ret = 0; | ||
| 702 | u8 *data; | ||
| 703 | u16 j, wlen, len_in, start, end; | ||
| 704 | u8 packet_size, dlen, i; | ||
| 705 | u8 *fw_data; | ||
| 706 | |||
| 707 | packet_size = 0x31; | ||
| 708 | len_in = 1; | ||
| 709 | |||
| 710 | data = kzalloc(512, GFP_KERNEL); | ||
| 711 | if (!data) { | ||
| 712 | info("FRM Could not start Firmware Download (Buffer allocation failed)"); | ||
| 713 | return -ENOMEM; | ||
| 714 | } | ||
| 715 | |||
| 716 | info("FRM Starting Firmware Download"); | ||
| 717 | |||
| 718 | for (i = 1; i < 3; i++) { | ||
| 719 | start = (i == 1) ? 0 : 512; | ||
| 720 | end = (i == 1) ? 512 : fw->size; | ||
| 721 | for (j = start; j < end; j += (packet_size+1)) { | ||
| 722 | fw_data = (u8 *)(fw->data + j); | ||
| 723 | if ((end - j) > packet_size) { | ||
| 724 | data[0] = i; | ||
| 725 | dlen = packet_size; | ||
| 726 | } else { | ||
| 727 | data[0] = i | 0x80; | ||
| 728 | dlen = (u8)(end - j)-1; | ||
| 729 | } | ||
| 730 | data[1] = dlen; | ||
| 731 | memcpy(&data[2], fw_data, dlen+1); | ||
| 732 | wlen = (u8) dlen + 4; | ||
| 733 | data[wlen-1] = check_sum(fw_data, dlen+1); | ||
| 734 | deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3], | ||
| 735 | data[dlen+2], data[dlen+3]); | ||
| 736 | ret |= lme2510_bulk_write(dev, data, wlen, 1); | ||
| 737 | ret |= lme2510_bulk_read(dev, data, len_in , 1); | ||
| 738 | ret |= (data[0] == 0x88) ? 0 : -1; | ||
| 739 | } | ||
| 740 | } | ||
| 741 | |||
| 742 | usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
| 743 | 0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000); | ||
| 744 | |||
| 745 | |||
| 746 | data[0] = 0x8a; | ||
| 747 | len_in = 1; | ||
| 748 | msleep(2000); | ||
| 749 | ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Resetting*/ | ||
| 750 | ret |= lme2510_bulk_read(dev, data, len_in, 1); | ||
| 751 | msleep(400); | ||
| 752 | |||
| 753 | if (ret < 0) | ||
| 754 | info("FRM Firmware Download Failed (%04x)" , ret); | ||
| 755 | else | ||
| 756 | info("FRM Firmware Download Completed - Resetting Device"); | ||
| 757 | |||
| 758 | kfree(data); | ||
| 759 | return (ret < 0) ? -ENODEV : 0; | ||
| 760 | } | ||
| 761 | |||
| 762 | static void lme_coldreset(struct usb_device *dev) | ||
| 763 | { | ||
| 764 | int ret = 0, len_in; | ||
| 765 | u8 data[512] = {0}; | ||
| 766 | |||
| 767 | data[0] = 0x0a; | ||
| 768 | len_in = 1; | ||
| 769 | info("FRM Firmware Cold Reset"); | ||
| 770 | ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/ | ||
| 771 | ret |= lme2510_bulk_read(dev, data, len_in, 1); | ||
| 772 | |||
| 773 | return; | ||
| 774 | } | ||
| 775 | |||
| 776 | static int lme_firmware_switch(struct usb_device *udev, int cold) | ||
| 777 | { | ||
| 778 | const struct firmware *fw = NULL; | ||
| 779 | const char fw_c_s7395[] = "dvb-usb-lme2510c-s7395.fw"; | ||
| 780 | const char fw_c_lg[] = "dvb-usb-lme2510c-lg.fw"; | ||
| 781 | const char fw_c_s0194[] = "dvb-usb-lme2510c-s0194.fw"; | ||
| 782 | const char fw_lg[] = "dvb-usb-lme2510-lg.fw"; | ||
| 783 | const char fw_s0194[] = "dvb-usb-lme2510-s0194.fw"; | ||
| 784 | const char *fw_lme; | ||
| 785 | int ret, cold_fw; | ||
| 786 | |||
| 787 | cold = (cold > 0) ? (cold & 1) : 0; | ||
| 788 | |||
| 789 | cold_fw = !cold; | ||
| 790 | |||
| 791 | if (le16_to_cpu(udev->descriptor.idProduct) == 0x1122) { | ||
| 792 | switch (dvb_usb_lme2510_firmware) { | ||
| 793 | default: | ||
| 794 | dvb_usb_lme2510_firmware = TUNER_S0194; | ||
| 795 | case TUNER_S0194: | ||
| 796 | fw_lme = fw_s0194; | ||
| 797 | ret = request_firmware(&fw, fw_lme, &udev->dev); | ||
| 798 | if (ret == 0) { | ||
| 799 | cold = 0; | ||
| 800 | break; | ||
| 801 | } | ||
| 802 | dvb_usb_lme2510_firmware = TUNER_LG; | ||
| 803 | case TUNER_LG: | ||
| 804 | fw_lme = fw_lg; | ||
| 805 | ret = request_firmware(&fw, fw_lme, &udev->dev); | ||
| 806 | if (ret == 0) | ||
| 807 | break; | ||
| 808 | info("FRM No Firmware Found - please install"); | ||
| 809 | dvb_usb_lme2510_firmware = TUNER_DEFAULT; | ||
| 810 | cold = 0; | ||
| 811 | cold_fw = 0; | ||
| 812 | break; | ||
| 813 | } | ||
| 814 | } else { | ||
| 815 | switch (dvb_usb_lme2510_firmware) { | ||
| 816 | default: | ||
| 817 | dvb_usb_lme2510_firmware = TUNER_S7395; | ||
| 818 | case TUNER_S7395: | ||
| 819 | fw_lme = fw_c_s7395; | ||
| 820 | ret = request_firmware(&fw, fw_lme, &udev->dev); | ||
| 821 | if (ret == 0) { | ||
| 822 | cold = 0; | ||
| 823 | break; | ||
| 824 | } | ||
| 825 | dvb_usb_lme2510_firmware = TUNER_LG; | ||
| 826 | case TUNER_LG: | ||
| 827 | fw_lme = fw_c_lg; | ||
| 828 | ret = request_firmware(&fw, fw_lme, &udev->dev); | ||
| 829 | if (ret == 0) | ||
| 830 | break; | ||
| 831 | dvb_usb_lme2510_firmware = TUNER_S0194; | ||
| 832 | case TUNER_S0194: | ||
| 833 | fw_lme = fw_c_s0194; | ||
| 834 | ret = request_firmware(&fw, fw_lme, &udev->dev); | ||
| 835 | if (ret == 0) | ||
| 836 | break; | ||
| 837 | info("FRM No Firmware Found - please install"); | ||
| 838 | dvb_usb_lme2510_firmware = TUNER_DEFAULT; | ||
| 839 | cold = 0; | ||
| 840 | cold_fw = 0; | ||
| 841 | break; | ||
| 842 | } | ||
| 843 | } | ||
| 844 | |||
| 845 | if (cold_fw) { | ||
| 846 | info("FRM Loading %s file", fw_lme); | ||
| 847 | ret = lme2510_download_firmware(udev, fw); | ||
| 848 | } | ||
| 849 | |||
| 850 | release_firmware(fw); | ||
| 851 | |||
| 852 | if (cold) { | ||
| 853 | info("FRM Changing to %s firmware", fw_lme); | ||
| 854 | lme_coldreset(udev); | ||
| 855 | return -ENODEV; | ||
| 856 | } | ||
| 857 | |||
| 858 | return ret; | ||
| 859 | } | ||
| 860 | |||
| 861 | static int lme2510_kill_urb(struct usb_data_stream *stream) | ||
| 862 | { | ||
| 863 | int i; | ||
| 864 | |||
| 865 | for (i = 0; i < stream->urbs_submitted; i++) { | ||
| 866 | deb_info(3, "killing URB no. %d.", i); | ||
| 867 | /* stop the URB */ | ||
| 868 | usb_kill_urb(stream->urb_list[i]); | ||
| 869 | } | ||
| 870 | stream->urbs_submitted = 0; | ||
| 871 | |||
| 872 | return 0; | ||
| 873 | } | ||
| 874 | |||
| 875 | static struct tda10086_config tda10086_config = { | ||
| 876 | .demod_address = 0x1c, | ||
| 877 | .invert = 0, | ||
| 878 | .diseqc_tone = 1, | ||
| 879 | .xtal_freq = TDA10086_XTAL_16M, | ||
| 880 | }; | ||
| 881 | |||
| 882 | static struct stv0288_config lme_config = { | ||
| 883 | .demod_address = 0xd0, | ||
| 884 | .min_delay_ms = 15, | ||
| 885 | .inittab = s7395_inittab, | ||
| 886 | }; | ||
| 887 | |||
| 888 | static struct ix2505v_config lme_tuner = { | ||
| 889 | .tuner_address = 0xc0, | ||
| 890 | .min_delay_ms = 100, | ||
| 891 | .tuner_gain = 0x0, | ||
| 892 | .tuner_chargepump = 0x3, | ||
| 893 | }; | ||
| 894 | |||
| 895 | static struct stv0299_config sharp_z0194_config = { | ||
| 896 | .demod_address = 0xd0, | ||
| 897 | .inittab = sharp_z0194a_inittab, | ||
| 898 | .mclk = 88000000UL, | ||
| 899 | .invert = 0, | ||
| 900 | .skip_reinit = 0, | ||
| 901 | .lock_output = STV0299_LOCKOUTPUT_1, | ||
| 902 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
| 903 | .min_delay_ms = 100, | ||
| 904 | .set_symbol_rate = sharp_z0194a_set_symbol_rate, | ||
| 905 | }; | ||
| 906 | |||
| 907 | static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, | ||
| 908 | fe_sec_voltage_t voltage) | ||
| 909 | { | ||
| 910 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 911 | static u8 voltage_low[] = LME_VOLTAGE_L; | ||
| 912 | static u8 voltage_high[] = LME_VOLTAGE_H; | ||
| 913 | static u8 rbuf[1]; | ||
| 914 | int ret = 0, len = 3, rlen = 1; | ||
| 915 | |||
| 916 | if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) | ||
| 917 | return -EAGAIN; | ||
| 918 | |||
| 919 | switch (voltage) { | ||
| 920 | case SEC_VOLTAGE_18: | ||
| 921 | ret |= lme2510_usb_talk(adap->dev, | ||
| 922 | voltage_high, len, rbuf, rlen); | ||
| 923 | break; | ||
| 924 | |||
| 925 | case SEC_VOLTAGE_OFF: | ||
| 926 | case SEC_VOLTAGE_13: | ||
| 927 | default: | ||
| 928 | ret |= lme2510_usb_talk(adap->dev, | ||
| 929 | voltage_low, len, rbuf, rlen); | ||
| 930 | break; | ||
| 931 | } | ||
| 932 | |||
| 933 | mutex_unlock(&adap->dev->i2c_mutex); | ||
| 934 | |||
| 935 | return (ret < 0) ? -ENODEV : 0; | ||
| 936 | } | ||
| 937 | |||
| 938 | static int lme_name(struct dvb_usb_adapter *adap) | ||
| 939 | { | ||
| 940 | struct lme2510_state *st = adap->dev->priv; | ||
| 941 | const char *desc = adap->dev->desc->name; | ||
| 942 | char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395", | ||
| 943 | " SHARP:BS2F7HZ0194"}; | ||
| 944 | char *name = adap->fe->ops.info.name; | ||
| 945 | |||
| 946 | strlcpy(name, desc, 128); | ||
| 947 | strlcat(name, fe_name[st->tuner_config], 128); | ||
| 948 | |||
| 949 | return 0; | ||
| 950 | } | ||
| 951 | |||
| 952 | static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 953 | { | ||
| 954 | struct lme2510_state *st = adap->dev->priv; | ||
| 955 | |||
| 956 | int ret = 0; | ||
| 957 | |||
| 958 | st->i2c_talk_onoff = 1; | ||
| 959 | |||
| 960 | st->i2c_gate = 4; | ||
| 961 | adap->fe = dvb_attach(tda10086_attach, &tda10086_config, | ||
| 962 | &adap->dev->i2c_adap); | ||
| 963 | |||
| 964 | if (adap->fe) { | ||
| 965 | info("TUN Found Frontend TDA10086"); | ||
| 966 | st->i2c_tuner_gate_w = 4; | ||
| 967 | st->i2c_tuner_gate_r = 4; | ||
| 968 | st->i2c_tuner_addr = 0xc0; | ||
| 969 | st->tuner_config = TUNER_LG; | ||
| 970 | if (dvb_usb_lme2510_firmware != TUNER_LG) { | ||
| 971 | dvb_usb_lme2510_firmware = TUNER_LG; | ||
| 972 | ret = lme_firmware_switch(adap->dev->udev, 1); | ||
| 973 | } | ||
| 974 | goto end; | ||
| 975 | } | ||
| 976 | |||
| 977 | st->i2c_gate = 4; | ||
| 978 | adap->fe = dvb_attach(stv0299_attach, &sharp_z0194_config, | ||
| 979 | &adap->dev->i2c_adap); | ||
| 980 | if (adap->fe) { | ||
| 981 | info("FE Found Stv0299"); | ||
| 982 | st->i2c_tuner_gate_w = 4; | ||
| 983 | st->i2c_tuner_gate_r = 5; | ||
| 984 | st->i2c_tuner_addr = 0xc0; | ||
| 985 | st->tuner_config = TUNER_S0194; | ||
| 986 | if (dvb_usb_lme2510_firmware != TUNER_S0194) { | ||
| 987 | dvb_usb_lme2510_firmware = TUNER_S0194; | ||
| 988 | ret = lme_firmware_switch(adap->dev->udev, 1); | ||
| 989 | } | ||
| 990 | goto end; | ||
| 991 | } | ||
| 992 | |||
| 993 | st->i2c_gate = 5; | ||
| 994 | adap->fe = dvb_attach(stv0288_attach, &lme_config, | ||
| 995 | &adap->dev->i2c_adap); | ||
| 996 | if (adap->fe) { | ||
| 997 | info("FE Found Stv0288"); | ||
| 998 | st->i2c_tuner_gate_w = 4; | ||
| 999 | st->i2c_tuner_gate_r = 5; | ||
| 1000 | st->i2c_tuner_addr = 0xc0; | ||
| 1001 | st->tuner_config = TUNER_S7395; | ||
| 1002 | if (dvb_usb_lme2510_firmware != TUNER_S7395) { | ||
| 1003 | dvb_usb_lme2510_firmware = TUNER_S7395; | ||
| 1004 | ret = lme_firmware_switch(adap->dev->udev, 1); | ||
| 1005 | } | ||
| 1006 | } else { | ||
| 1007 | info("DM04 Not Supported"); | ||
| 1008 | return -ENODEV; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | |||
| 1012 | end: if (ret) { | ||
| 1013 | if (adap->fe) { | ||
| 1014 | dvb_frontend_detach(adap->fe); | ||
| 1015 | adap->fe = NULL; | ||
| 1016 | } | ||
| 1017 | adap->dev->props.rc.core.rc_codes = NULL; | ||
| 1018 | return -ENODEV; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | adap->fe->ops.set_voltage = dm04_lme2510_set_voltage; | ||
| 1022 | ret = lme_name(adap); | ||
| 1023 | return ret; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) | ||
| 1027 | { | ||
| 1028 | struct lme2510_state *st = adap->dev->priv; | ||
| 1029 | char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA"}; | ||
| 1030 | int ret = 0; | ||
| 1031 | |||
| 1032 | switch (st->tuner_config) { | ||
| 1033 | case TUNER_LG: | ||
| 1034 | if (dvb_attach(tda826x_attach, adap->fe, 0xc0, | ||
| 1035 | &adap->dev->i2c_adap, 1)) | ||
| 1036 | ret = st->tuner_config; | ||
| 1037 | break; | ||
| 1038 | case TUNER_S7395: | ||
| 1039 | if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner, | ||
| 1040 | &adap->dev->i2c_adap)) | ||
| 1041 | ret = st->tuner_config; | ||
| 1042 | break; | ||
| 1043 | case TUNER_S0194: | ||
| 1044 | if (dvb_attach(dvb_pll_attach , adap->fe, 0xc0, | ||
| 1045 | &adap->dev->i2c_adap, DVB_PLL_OPERA1)) | ||
| 1046 | ret = st->tuner_config; | ||
| 1047 | break; | ||
| 1048 | default: | ||
| 1049 | break; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | if (ret) | ||
| 1053 | info("TUN Found %s tuner", tun_msg[ret]); | ||
| 1054 | else { | ||
| 1055 | info("TUN No tuner found --- reseting device"); | ||
| 1056 | lme_coldreset(adap->dev->udev); | ||
| 1057 | return -ENODEV; | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | /* Start the Interrupt*/ | ||
| 1061 | ret = lme2510_int_read(adap); | ||
| 1062 | if (ret < 0) { | ||
| 1063 | info("INT Unable to start Interrupt Service"); | ||
| 1064 | return -ENODEV; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | return ret; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | static int lme2510_powerup(struct dvb_usb_device *d, int onoff) | ||
| 1071 | { | ||
| 1072 | struct lme2510_state *st = d->priv; | ||
| 1073 | static u8 lnb_on[] = LNB_ON; | ||
| 1074 | static u8 lnb_off[] = LNB_OFF; | ||
| 1075 | static u8 rbuf[1]; | ||
| 1076 | int ret, len = 3, rlen = 1; | ||
| 1077 | |||
| 1078 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 1079 | return -EAGAIN; | ||
| 1080 | |||
| 1081 | if (onoff) | ||
| 1082 | ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); | ||
| 1083 | else | ||
| 1084 | ret = lme2510_usb_talk(d, lnb_off, len, rbuf, rlen); | ||
| 1085 | |||
| 1086 | st->i2c_talk_onoff = 1; | ||
| 1087 | |||
| 1088 | mutex_unlock(&d->i2c_mutex); | ||
| 1089 | |||
| 1090 | return ret; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | /* DVB USB Driver stuff */ | ||
| 1094 | static struct dvb_usb_device_properties lme2510_properties; | ||
| 1095 | static struct dvb_usb_device_properties lme2510c_properties; | ||
| 1096 | |||
| 1097 | static int lme2510_probe(struct usb_interface *intf, | ||
| 1098 | const struct usb_device_id *id) | ||
| 1099 | { | ||
| 1100 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 1101 | int ret = 0; | ||
| 1102 | |||
| 1103 | usb_reset_configuration(udev); | ||
| 1104 | |||
| 1105 | usb_set_interface(udev, intf->cur_altsetting->desc.bInterfaceNumber, 1); | ||
| 1106 | |||
| 1107 | if (udev->speed != USB_SPEED_HIGH) { | ||
| 1108 | ret = usb_reset_device(udev); | ||
| 1109 | info("DEV Failed to connect in HIGH SPEED mode"); | ||
| 1110 | return -ENODEV; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | if (lme2510_return_status(udev) == 0x44) { | ||
| 1114 | lme_firmware_switch(udev, 0); | ||
| 1115 | return -ENODEV; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | if (0 == dvb_usb_device_init(intf, &lme2510_properties, | ||
| 1119 | THIS_MODULE, NULL, adapter_nr)) { | ||
| 1120 | info("DEV registering device driver"); | ||
| 1121 | return 0; | ||
| 1122 | } | ||
| 1123 | if (0 == dvb_usb_device_init(intf, &lme2510c_properties, | ||
| 1124 | THIS_MODULE, NULL, adapter_nr)) { | ||
| 1125 | info("DEV registering device driver"); | ||
| 1126 | return 0; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | info("DEV lme2510 Error"); | ||
| 1130 | return -ENODEV; | ||
| 1131 | |||
| 1132 | } | ||
| 1133 | |||
| 1134 | static struct usb_device_id lme2510_table[] = { | ||
| 1135 | { USB_DEVICE(0x3344, 0x1122) }, /* LME2510 */ | ||
| 1136 | { USB_DEVICE(0x3344, 0x1120) }, /* LME2510C */ | ||
| 1137 | {} /* Terminating entry */ | ||
| 1138 | }; | ||
| 1139 | |||
| 1140 | MODULE_DEVICE_TABLE(usb, lme2510_table); | ||
| 1141 | |||
| 1142 | static struct dvb_usb_device_properties lme2510_properties = { | ||
| 1143 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1144 | .size_of_priv = sizeof(struct lme2510_state), | ||
| 1145 | .num_adapters = 1, | ||
| 1146 | .adapter = { | ||
| 1147 | { | ||
| 1148 | .caps = DVB_USB_ADAP_HAS_PID_FILTER| | ||
| 1149 | DVB_USB_ADAP_NEED_PID_FILTERING| | ||
| 1150 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1151 | .streaming_ctrl = lme2510_streaming_ctrl, | ||
| 1152 | .pid_filter_count = 15, | ||
| 1153 | .pid_filter = lme2510_pid_filter, | ||
| 1154 | .pid_filter_ctrl = lme2510_pid_filter_ctrl, | ||
| 1155 | .frontend_attach = dm04_lme2510_frontend_attach, | ||
| 1156 | .tuner_attach = dm04_lme2510_tuner, | ||
| 1157 | /* parameter for the MPEG2-data transfer */ | ||
| 1158 | .stream = { | ||
| 1159 | .type = USB_BULK, | ||
| 1160 | .count = 10, | ||
| 1161 | .endpoint = 0x06, | ||
| 1162 | .u = { | ||
| 1163 | .bulk = { | ||
| 1164 | .buffersize = 4096, | ||
| 1165 | |||
| 1166 | } | ||
| 1167 | } | ||
| 1168 | } | ||
| 1169 | } | ||
| 1170 | }, | ||
| 1171 | .rc.core = { | ||
| 1172 | .protocol = RC_TYPE_NEC, | ||
| 1173 | .module_name = "LME2510 Remote Control", | ||
| 1174 | .allowed_protos = RC_TYPE_NEC, | ||
| 1175 | .rc_codes = RC_MAP_LME2510, | ||
| 1176 | }, | ||
| 1177 | .power_ctrl = lme2510_powerup, | ||
| 1178 | .identify_state = lme2510_identify_state, | ||
| 1179 | .i2c_algo = &lme2510_i2c_algo, | ||
| 1180 | .generic_bulk_ctrl_endpoint = 0, | ||
| 1181 | .num_device_descs = 1, | ||
| 1182 | .devices = { | ||
| 1183 | { "DM04_LME2510_DVB-S", | ||
| 1184 | { &lme2510_table[0], NULL }, | ||
| 1185 | }, | ||
| 1186 | |||
| 1187 | } | ||
| 1188 | }; | ||
| 1189 | |||
| 1190 | static struct dvb_usb_device_properties lme2510c_properties = { | ||
| 1191 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1192 | .size_of_priv = sizeof(struct lme2510_state), | ||
| 1193 | .num_adapters = 1, | ||
| 1194 | .adapter = { | ||
| 1195 | { | ||
| 1196 | .caps = DVB_USB_ADAP_HAS_PID_FILTER| | ||
| 1197 | DVB_USB_ADAP_NEED_PID_FILTERING| | ||
| 1198 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1199 | .streaming_ctrl = lme2510_streaming_ctrl, | ||
| 1200 | .pid_filter_count = 15, | ||
| 1201 | .pid_filter = lme2510_pid_filter, | ||
| 1202 | .pid_filter_ctrl = lme2510_pid_filter_ctrl, | ||
| 1203 | .frontend_attach = dm04_lme2510_frontend_attach, | ||
| 1204 | .tuner_attach = dm04_lme2510_tuner, | ||
| 1205 | /* parameter for the MPEG2-data transfer */ | ||
| 1206 | .stream = { | ||
| 1207 | .type = USB_BULK, | ||
| 1208 | .count = 10, | ||
| 1209 | .endpoint = 0x8, | ||
| 1210 | .u = { | ||
| 1211 | .bulk = { | ||
| 1212 | .buffersize = 4096, | ||
| 1213 | |||
| 1214 | } | ||
| 1215 | } | ||
| 1216 | } | ||
| 1217 | } | ||
| 1218 | }, | ||
| 1219 | .rc.core = { | ||
| 1220 | .protocol = RC_TYPE_NEC, | ||
| 1221 | .module_name = "LME2510 Remote Control", | ||
| 1222 | .allowed_protos = RC_TYPE_NEC, | ||
| 1223 | .rc_codes = RC_MAP_LME2510, | ||
| 1224 | }, | ||
| 1225 | .power_ctrl = lme2510_powerup, | ||
| 1226 | .identify_state = lme2510_identify_state, | ||
| 1227 | .i2c_algo = &lme2510_i2c_algo, | ||
| 1228 | .generic_bulk_ctrl_endpoint = 0, | ||
| 1229 | .num_device_descs = 1, | ||
| 1230 | .devices = { | ||
| 1231 | { "DM04_LME2510C_DVB-S", | ||
| 1232 | { &lme2510_table[1], NULL }, | ||
| 1233 | }, | ||
| 1234 | } | ||
| 1235 | }; | ||
| 1236 | |||
| 1237 | static void *lme2510_exit_int(struct dvb_usb_device *d) | ||
| 1238 | { | ||
| 1239 | struct lme2510_state *st = d->priv; | ||
| 1240 | struct dvb_usb_adapter *adap = &d->adapter[0]; | ||
| 1241 | void *buffer = NULL; | ||
| 1242 | |||
| 1243 | if (adap != NULL) { | ||
| 1244 | lme2510_kill_urb(&adap->stream); | ||
| 1245 | adap->feedcount = 0; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | if (st->usb_buffer != NULL) { | ||
| 1249 | st->i2c_talk_onoff = 1; | ||
| 1250 | st->signal_lock = 0; | ||
| 1251 | st->signal_level = 0; | ||
| 1252 | st->signal_sn = 0; | ||
| 1253 | buffer = st->usb_buffer; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | if (st->lme_urb != NULL) { | ||
| 1257 | usb_kill_urb(st->lme_urb); | ||
| 1258 | usb_free_coherent(d->udev, 5000, st->buffer, | ||
| 1259 | st->lme_urb->transfer_dma); | ||
| 1260 | info("Interrupt Service Stopped"); | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | return buffer; | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | static void lme2510_exit(struct usb_interface *intf) | ||
| 1267 | { | ||
| 1268 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
| 1269 | void *usb_buffer; | ||
| 1270 | |||
| 1271 | if (d != NULL) { | ||
| 1272 | usb_buffer = lme2510_exit_int(d); | ||
| 1273 | dvb_usb_device_exit(intf); | ||
| 1274 | if (usb_buffer != NULL) | ||
| 1275 | kfree(usb_buffer); | ||
| 1276 | } | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | static struct usb_driver lme2510_driver = { | ||
| 1280 | .name = "LME2510C_DVB-S", | ||
| 1281 | .probe = lme2510_probe, | ||
| 1282 | .disconnect = lme2510_exit, | ||
| 1283 | .id_table = lme2510_table, | ||
| 1284 | }; | ||
| 1285 | |||
| 1286 | /* module stuff */ | ||
| 1287 | static int __init lme2510_module_init(void) | ||
| 1288 | { | ||
| 1289 | int result = usb_register(&lme2510_driver); | ||
| 1290 | if (result) { | ||
| 1291 | err("usb_register failed. Error number %d", result); | ||
| 1292 | return result; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | return 0; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | static void __exit lme2510_module_exit(void) | ||
| 1299 | { | ||
| 1300 | /* deregister this driver from the USB subsystem */ | ||
| 1301 | usb_deregister(&lme2510_driver); | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | module_init(lme2510_module_init); | ||
| 1305 | module_exit(lme2510_module_exit); | ||
| 1306 | |||
| 1307 | MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); | ||
| 1308 | MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); | ||
| 1309 | MODULE_VERSION("1.88"); | ||
| 1310 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.h b/drivers/media/dvb/dvb-usb/lmedm04.h new file mode 100644 index 00000000000..ab21e2ef53f --- /dev/null +++ b/drivers/media/dvb/dvb-usb/lmedm04.h | |||
| @@ -0,0 +1,174 @@ | |||
| 1 | /* DVB USB compliant linux driver for | ||
| 2 | * | ||
| 3 | * DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395 | ||
| 4 | * LME2510C + LG TDQY-P001F | ||
| 5 | * LME2510 + LG TDQY-P001F | ||
| 6 | * | ||
| 7 | * MVB7395 (LME2510C+SHARP:BS2F7HZ7395) | ||
| 8 | * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V) | ||
| 9 | * | ||
| 10 | * MVB001F (LME2510+LGTDQT-P001F) | ||
| 11 | * LG TDQY - P001F =(TDA8263 + TDA10086H) | ||
| 12 | * | ||
| 13 | * MVB0001F (LME2510C+LGTDQT-P001F) | ||
| 14 | * | ||
| 15 | * This program is free software; you can redistribute it and/or modify it | ||
| 16 | * under the terms of the GNU General Public License as published by the Free | ||
| 17 | * Software Foundation, version 2. | ||
| 18 | * * | ||
| 19 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 20 | */ | ||
| 21 | #ifndef _DVB_USB_LME2510_H_ | ||
| 22 | #define _DVB_USB_LME2510_H_ | ||
| 23 | |||
| 24 | /* Streamer & PID | ||
| 25 | * | ||
| 26 | * Note: These commands do not actually stop the streaming | ||
| 27 | * but form some kind of packet filtering/stream count | ||
| 28 | * or tuning related functions. | ||
| 29 | * 06 XX | ||
| 30 | * offset 1 = 00 Enable Streaming | ||
| 31 | * | ||
| 32 | * | ||
| 33 | * PID | ||
| 34 | * 03 XX XX ----> reg number ---> setting....20 XX | ||
| 35 | * offset 1 = length | ||
| 36 | * offset 2 = start of data | ||
| 37 | * end byte -1 = 20 | ||
| 38 | * end byte = clear pid always a0, other wise 9c, 9a ?? | ||
| 39 | * | ||
| 40 | */ | ||
| 41 | #define LME_ST_ON_W {0x06, 0x00} | ||
| 42 | #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} | ||
| 43 | #define LME_ZERO_PID {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c} | ||
| 44 | |||
| 45 | /* LNB Voltage | ||
| 46 | * 07 XX XX | ||
| 47 | * offset 1 = 01 | ||
| 48 | * offset 2 = 00=Voltage low 01=Voltage high | ||
| 49 | * | ||
| 50 | * LNB Power | ||
| 51 | * 03 01 XX | ||
| 52 | * offset 2 = 00=ON 01=OFF | ||
| 53 | */ | ||
| 54 | |||
| 55 | #define LME_VOLTAGE_L {0x07, 0x01, 0x00} | ||
| 56 | #define LME_VOLTAGE_H {0x07, 0x01, 0x01} | ||
| 57 | #define LNB_ON {0x3a, 0x01, 0x00} | ||
| 58 | #define LNB_OFF {0x3a, 0x01, 0x01} | ||
| 59 | |||
| 60 | /* Initial stv0288 settings for 7395 Frontend */ | ||
| 61 | static u8 s7395_inittab[] = { | ||
| 62 | 0x01, 0x15, | ||
| 63 | 0x02, 0x20, | ||
| 64 | 0x03, 0xa0, | ||
| 65 | 0x04, 0xa0, | ||
| 66 | 0x05, 0x12, | ||
| 67 | 0x06, 0x00, | ||
| 68 | 0x09, 0x00, | ||
| 69 | 0x0a, 0x04, | ||
| 70 | 0x0b, 0x00, | ||
| 71 | 0x0c, 0x00, | ||
| 72 | 0x0d, 0x00, | ||
| 73 | 0x0e, 0xc1, | ||
| 74 | 0x0f, 0x54, | ||
| 75 | 0x11, 0x7a, | ||
| 76 | 0x12, 0x03, | ||
| 77 | 0x13, 0x48, | ||
| 78 | 0x14, 0x84, | ||
| 79 | 0x15, 0xc5, | ||
| 80 | 0x16, 0xb8, | ||
| 81 | 0x17, 0x9c, | ||
| 82 | 0x18, 0x00, | ||
| 83 | 0x19, 0xa6, | ||
| 84 | 0x1a, 0x88, | ||
| 85 | 0x1b, 0x8f, | ||
| 86 | 0x1c, 0xf0, | ||
| 87 | 0x20, 0x0b, | ||
| 88 | 0x21, 0x54, | ||
| 89 | 0x22, 0xff, | ||
| 90 | 0x23, 0x01, | ||
| 91 | 0x28, 0x46, | ||
| 92 | 0x29, 0x66, | ||
| 93 | 0x2a, 0x90, | ||
| 94 | 0x2b, 0xfa, | ||
| 95 | 0x2c, 0xd9, | ||
| 96 | 0x30, 0x0, | ||
| 97 | 0x31, 0x1e, | ||
| 98 | 0x32, 0x14, | ||
| 99 | 0x33, 0x0f, | ||
| 100 | 0x34, 0x09, | ||
| 101 | 0x35, 0x0c, | ||
| 102 | 0x36, 0x05, | ||
| 103 | 0x37, 0x2f, | ||
| 104 | 0x38, 0x16, | ||
| 105 | 0x39, 0xbd, | ||
| 106 | 0x3a, 0x0, | ||
| 107 | 0x3b, 0x13, | ||
| 108 | 0x3c, 0x11, | ||
| 109 | 0x3d, 0x30, | ||
| 110 | 0x40, 0x63, | ||
| 111 | 0x41, 0x04, | ||
| 112 | 0x42, 0x20, | ||
| 113 | 0x43, 0x00, | ||
| 114 | 0x44, 0x00, | ||
| 115 | 0x45, 0x00, | ||
| 116 | 0x46, 0x00, | ||
| 117 | 0x47, 0x00, | ||
| 118 | 0x4a, 0x00, | ||
| 119 | 0x50, 0x10, | ||
| 120 | 0x51, 0x36, | ||
| 121 | 0x52, 0x21, | ||
| 122 | 0x53, 0x94, | ||
| 123 | 0x54, 0xb2, | ||
| 124 | 0x55, 0x29, | ||
| 125 | 0x56, 0x64, | ||
| 126 | 0x57, 0x2b, | ||
| 127 | 0x58, 0x54, | ||
| 128 | 0x59, 0x86, | ||
| 129 | 0x5a, 0x00, | ||
| 130 | 0x5b, 0x9b, | ||
| 131 | 0x5c, 0x08, | ||
| 132 | 0x5d, 0x7f, | ||
| 133 | 0x5e, 0xff, | ||
| 134 | 0x5f, 0x8d, | ||
| 135 | 0x70, 0x0, | ||
| 136 | 0x71, 0x0, | ||
| 137 | 0x72, 0x0, | ||
| 138 | 0x74, 0x0, | ||
| 139 | 0x75, 0x0, | ||
| 140 | 0x76, 0x0, | ||
| 141 | 0x81, 0x0, | ||
| 142 | 0x82, 0x3f, | ||
| 143 | 0x83, 0x3f, | ||
| 144 | 0x84, 0x0, | ||
| 145 | 0x85, 0x0, | ||
| 146 | 0x88, 0x0, | ||
| 147 | 0x89, 0x0, | ||
| 148 | 0x8a, 0x0, | ||
| 149 | 0x8b, 0x0, | ||
| 150 | 0x8c, 0x0, | ||
| 151 | 0x90, 0x0, | ||
| 152 | 0x91, 0x0, | ||
| 153 | 0x92, 0x0, | ||
| 154 | 0x93, 0x0, | ||
| 155 | 0x94, 0x1c, | ||
| 156 | 0x97, 0x0, | ||
| 157 | 0xa0, 0x48, | ||
| 158 | 0xa1, 0x0, | ||
| 159 | 0xb0, 0xb8, | ||
| 160 | 0xb1, 0x3a, | ||
| 161 | 0xb2, 0x10, | ||
| 162 | 0xb3, 0x82, | ||
| 163 | 0xb4, 0x80, | ||
| 164 | 0xb5, 0x82, | ||
| 165 | 0xb6, 0x82, | ||
| 166 | 0xb7, 0x82, | ||
| 167 | 0xb8, 0x20, | ||
| 168 | 0xb9, 0x0, | ||
| 169 | 0xf0, 0x0, | ||
| 170 | 0xf1, 0x0, | ||
| 171 | 0xf2, 0xc0, | ||
| 172 | 0xff, 0xff, | ||
| 173 | }; | ||
| 174 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c new file mode 100644 index 00000000000..9456792f219 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/m920x.c | |||
| @@ -0,0 +1,1093 @@ | |||
| 1 | /* DVB USB compliant linux driver for MSI Mega Sky 580 DVB-T USB2.0 receiver | ||
| 2 | * | ||
| 3 | * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.org) | ||
| 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 | #include "m920x.h" | ||
| 13 | |||
| 14 | #include "mt352.h" | ||
| 15 | #include "mt352_priv.h" | ||
| 16 | #include "qt1010.h" | ||
| 17 | #include "tda1004x.h" | ||
| 18 | #include "tda827x.h" | ||
| 19 | |||
| 20 | #include <media/tuner.h> | ||
| 21 | #include "tuner-simple.h" | ||
| 22 | #include <asm/unaligned.h> | ||
| 23 | |||
| 24 | /* debug */ | ||
| 25 | static int dvb_usb_m920x_debug; | ||
| 26 | module_param_named(debug,dvb_usb_m920x_debug, int, 0644); | ||
| 27 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 28 | |||
| 29 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 30 | |||
| 31 | static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid); | ||
| 32 | |||
| 33 | static inline int m920x_read(struct usb_device *udev, u8 request, u16 value, | ||
| 34 | u16 index, void *data, int size) | ||
| 35 | { | ||
| 36 | int ret; | ||
| 37 | |||
| 38 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 39 | request, USB_TYPE_VENDOR | USB_DIR_IN, | ||
| 40 | value, index, data, size, 2000); | ||
| 41 | if (ret < 0) { | ||
| 42 | printk(KERN_INFO "m920x_read = error: %d\n", ret); | ||
| 43 | return ret; | ||
| 44 | } | ||
| 45 | |||
| 46 | if (ret != size) { | ||
| 47 | deb("m920x_read = no data\n"); | ||
| 48 | return -EIO; | ||
| 49 | } | ||
| 50 | |||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | static inline int m920x_write(struct usb_device *udev, u8 request, | ||
| 55 | u16 value, u16 index) | ||
| 56 | { | ||
| 57 | int ret; | ||
| 58 | |||
| 59 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 60 | request, USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 61 | value, index, NULL, 0, 2000); | ||
| 62 | |||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq) | ||
| 67 | { | ||
| 68 | int ret = 0, i, epi, flags = 0; | ||
| 69 | int adap_enabled[M9206_MAX_ADAPTERS] = { 0 }; | ||
| 70 | |||
| 71 | /* Remote controller init. */ | ||
| 72 | if (d->props.rc.legacy.rc_query) { | ||
| 73 | deb("Initialising remote control\n"); | ||
| 74 | while (rc_seq->address) { | ||
| 75 | if ((ret = m920x_write(d->udev, M9206_CORE, | ||
| 76 | rc_seq->data, | ||
| 77 | rc_seq->address)) != 0) { | ||
| 78 | deb("Initialising remote control failed\n"); | ||
| 79 | return ret; | ||
| 80 | } | ||
| 81 | |||
| 82 | rc_seq++; | ||
| 83 | } | ||
| 84 | |||
| 85 | deb("Initialising remote control success\n"); | ||
| 86 | } | ||
| 87 | |||
| 88 | for (i = 0; i < d->props.num_adapters; i++) | ||
| 89 | flags |= d->adapter[i].props.caps; | ||
| 90 | |||
| 91 | /* Some devices(Dposh) might crash if we attempt touch at all. */ | ||
| 92 | if (flags & DVB_USB_ADAP_HAS_PID_FILTER) { | ||
| 93 | for (i = 0; i < d->props.num_adapters; i++) { | ||
| 94 | epi = d->adapter[i].props.stream.endpoint - 0x81; | ||
| 95 | |||
| 96 | if (epi < 0 || epi >= M9206_MAX_ADAPTERS) { | ||
| 97 | printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n"); | ||
| 98 | return -EINVAL; | ||
| 99 | } | ||
| 100 | |||
| 101 | adap_enabled[epi] = 1; | ||
| 102 | } | ||
| 103 | |||
| 104 | for (i = 0; i < M9206_MAX_ADAPTERS; i++) { | ||
| 105 | if (adap_enabled[i]) | ||
| 106 | continue; | ||
| 107 | |||
| 108 | if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x0)) != 0) | ||
| 109 | return ret; | ||
| 110 | |||
| 111 | if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x02f5)) != 0) | ||
| 112 | return ret; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int m920x_init_ep(struct usb_interface *intf) | ||
| 120 | { | ||
| 121 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 122 | struct usb_host_interface *alt; | ||
| 123 | |||
| 124 | if ((alt = usb_altnum_to_altsetting(intf, 1)) == NULL) { | ||
| 125 | deb("No alt found!\n"); | ||
| 126 | return -ENODEV; | ||
| 127 | } | ||
| 128 | |||
| 129 | return usb_set_interface(udev, alt->desc.bInterfaceNumber, | ||
| 130 | alt->desc.bAlternateSetting); | ||
| 131 | } | ||
| 132 | |||
| 133 | static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 134 | { | ||
| 135 | struct m920x_state *m = d->priv; | ||
| 136 | int i, ret = 0; | ||
| 137 | u8 *rc_state; | ||
| 138 | |||
| 139 | rc_state = kmalloc(2, GFP_KERNEL); | ||
| 140 | if (!rc_state) | ||
| 141 | return -ENOMEM; | ||
| 142 | |||
| 143 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) | ||
| 144 | goto out; | ||
| 145 | |||
| 146 | if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) | ||
| 147 | goto out; | ||
| 148 | |||
| 149 | for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) | ||
| 150 | if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) { | ||
| 151 | *event = d->props.rc.legacy.rc_map_table[i].keycode; | ||
| 152 | |||
| 153 | switch(rc_state[0]) { | ||
| 154 | case 0x80: | ||
| 155 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 156 | goto out; | ||
| 157 | |||
| 158 | case 0x88: /* framing error or "invalid code" */ | ||
| 159 | case 0x99: | ||
| 160 | case 0xc0: | ||
| 161 | case 0xd8: | ||
| 162 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 163 | m->rep_count = 0; | ||
| 164 | goto out; | ||
| 165 | |||
| 166 | case 0x93: | ||
| 167 | case 0x92: | ||
| 168 | case 0x83: /* pinnacle PCTV310e */ | ||
| 169 | case 0x82: | ||
| 170 | m->rep_count = 0; | ||
| 171 | *state = REMOTE_KEY_PRESSED; | ||
| 172 | goto out; | ||
| 173 | |||
| 174 | case 0x91: | ||
| 175 | case 0x81: /* pinnacle PCTV310e */ | ||
| 176 | /* prevent immediate auto-repeat */ | ||
| 177 | if (++m->rep_count > 2) | ||
| 178 | *state = REMOTE_KEY_REPEAT; | ||
| 179 | else | ||
| 180 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 181 | goto out; | ||
| 182 | |||
| 183 | default: | ||
| 184 | deb("Unexpected rc state %02x\n", rc_state[0]); | ||
| 185 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 186 | goto out; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | if (rc_state[1] != 0) | ||
| 191 | deb("Unknown rc key %02x\n", rc_state[1]); | ||
| 192 | |||
| 193 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 194 | |||
| 195 | out: | ||
| 196 | kfree(rc_state); | ||
| 197 | return ret; | ||
| 198 | } | ||
| 199 | |||
| 200 | /* I2C */ | ||
| 201 | static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) | ||
| 202 | { | ||
| 203 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 204 | int i, j; | ||
| 205 | int ret = 0; | ||
| 206 | |||
| 207 | if (!num) | ||
| 208 | return -EINVAL; | ||
| 209 | |||
| 210 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 211 | return -EAGAIN; | ||
| 212 | |||
| 213 | for (i = 0; i < num; i++) { | ||
| 214 | if (msg[i].flags & (I2C_M_NO_RD_ACK | I2C_M_IGNORE_NAK | I2C_M_TEN) || msg[i].len == 0) { | ||
| 215 | /* For a 0 byte message, I think sending the address | ||
| 216 | * to index 0x80|0x40 would be the correct thing to | ||
| 217 | * do. However, zero byte messages are only used for | ||
| 218 | * probing, and since we don't know how to get the | ||
| 219 | * slave's ack, we can't probe. */ | ||
| 220 | ret = -ENOTSUPP; | ||
| 221 | goto unlock; | ||
| 222 | } | ||
| 223 | /* Send START & address/RW bit */ | ||
| 224 | if (!(msg[i].flags & I2C_M_NOSTART)) { | ||
| 225 | if ((ret = m920x_write(d->udev, M9206_I2C, | ||
| 226 | (msg[i].addr << 1) | | ||
| 227 | (msg[i].flags & I2C_M_RD ? 0x01 : 0), 0x80)) != 0) | ||
| 228 | goto unlock; | ||
| 229 | /* Should check for ack here, if we knew how. */ | ||
| 230 | } | ||
| 231 | if (msg[i].flags & I2C_M_RD) { | ||
| 232 | for (j = 0; j < msg[i].len; j++) { | ||
| 233 | /* Last byte of transaction? | ||
| 234 | * Send STOP, otherwise send ACK. */ | ||
| 235 | int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x01; | ||
| 236 | |||
| 237 | if ((ret = m920x_read(d->udev, M9206_I2C, 0x0, | ||
| 238 | 0x20 | stop, | ||
| 239 | &msg[i].buf[j], 1)) != 0) | ||
| 240 | goto unlock; | ||
| 241 | } | ||
| 242 | } else { | ||
| 243 | for (j = 0; j < msg[i].len; j++) { | ||
| 244 | /* Last byte of transaction? Then send STOP. */ | ||
| 245 | int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x00; | ||
| 246 | |||
| 247 | if ((ret = m920x_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0) | ||
| 248 | goto unlock; | ||
| 249 | /* Should check for ack here too. */ | ||
| 250 | } | ||
| 251 | } | ||
| 252 | } | ||
| 253 | ret = num; | ||
| 254 | |||
| 255 | unlock: | ||
| 256 | mutex_unlock(&d->i2c_mutex); | ||
| 257 | |||
| 258 | return ret; | ||
| 259 | } | ||
| 260 | |||
| 261 | static u32 m920x_i2c_func(struct i2c_adapter *adapter) | ||
| 262 | { | ||
| 263 | return I2C_FUNC_I2C; | ||
| 264 | } | ||
| 265 | |||
| 266 | static struct i2c_algorithm m920x_i2c_algo = { | ||
| 267 | .master_xfer = m920x_i2c_xfer, | ||
| 268 | .functionality = m920x_i2c_func, | ||
| 269 | }; | ||
| 270 | |||
| 271 | /* pid filter */ | ||
| 272 | static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid) | ||
| 273 | { | ||
| 274 | int ret = 0; | ||
| 275 | |||
| 276 | if (pid >= 0x8000) | ||
| 277 | return -EINVAL; | ||
| 278 | |||
| 279 | pid |= 0x8000; | ||
| 280 | |||
| 281 | if ((ret = m920x_write(d->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0) | ||
| 282 | return ret; | ||
| 283 | |||
| 284 | if ((ret = m920x_write(d->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0) | ||
| 285 | return ret; | ||
| 286 | |||
| 287 | return ret; | ||
| 288 | } | ||
| 289 | |||
| 290 | static int m920x_update_filters(struct dvb_usb_adapter *adap) | ||
| 291 | { | ||
| 292 | struct m920x_state *m = adap->dev->priv; | ||
| 293 | int enabled = m->filtering_enabled[adap->id]; | ||
| 294 | int i, ret = 0, filter = 0; | ||
| 295 | int ep = adap->props.stream.endpoint; | ||
| 296 | |||
| 297 | for (i = 0; i < M9206_MAX_FILTERS; i++) | ||
| 298 | if (m->filters[adap->id][i] == 8192) | ||
| 299 | enabled = 0; | ||
| 300 | |||
| 301 | /* Disable all filters */ | ||
| 302 | if ((ret = m920x_set_filter(adap->dev, ep, 1, enabled)) != 0) | ||
| 303 | return ret; | ||
| 304 | |||
| 305 | for (i = 0; i < M9206_MAX_FILTERS; i++) | ||
| 306 | if ((ret = m920x_set_filter(adap->dev, ep, i + 2, 0)) != 0) | ||
| 307 | return ret; | ||
| 308 | |||
| 309 | /* Set */ | ||
| 310 | if (enabled) { | ||
| 311 | for (i = 0; i < M9206_MAX_FILTERS; i++) { | ||
| 312 | if (m->filters[adap->id][i] == 0) | ||
| 313 | continue; | ||
| 314 | |||
| 315 | if ((ret = m920x_set_filter(adap->dev, ep, filter + 2, m->filters[adap->id][i])) != 0) | ||
| 316 | return ret; | ||
| 317 | |||
| 318 | filter++; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | return ret; | ||
| 323 | } | ||
| 324 | |||
| 325 | static int m920x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 326 | { | ||
| 327 | struct m920x_state *m = adap->dev->priv; | ||
| 328 | |||
| 329 | m->filtering_enabled[adap->id] = onoff ? 1 : 0; | ||
| 330 | |||
| 331 | return m920x_update_filters(adap); | ||
| 332 | } | ||
| 333 | |||
| 334 | static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) | ||
| 335 | { | ||
| 336 | struct m920x_state *m = adap->dev->priv; | ||
| 337 | |||
| 338 | m->filters[adap->id][index] = onoff ? pid : 0; | ||
| 339 | |||
| 340 | return m920x_update_filters(adap); | ||
| 341 | } | ||
| 342 | |||
| 343 | static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw) | ||
| 344 | { | ||
| 345 | u16 value, index, size; | ||
| 346 | u8 *read, *buff; | ||
| 347 | int i, pass, ret = 0; | ||
| 348 | |||
| 349 | buff = kmalloc(65536, GFP_KERNEL); | ||
| 350 | if (buff == NULL) | ||
| 351 | return -ENOMEM; | ||
| 352 | |||
| 353 | read = kmalloc(4, GFP_KERNEL); | ||
| 354 | if (!read) { | ||
| 355 | kfree(buff); | ||
| 356 | return -ENOMEM; | ||
| 357 | } | ||
| 358 | |||
| 359 | if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) | ||
| 360 | goto done; | ||
| 361 | deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]); | ||
| 362 | |||
| 363 | if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0) | ||
| 364 | goto done; | ||
| 365 | deb("%x\n", read[0]); | ||
| 366 | |||
| 367 | for (pass = 0; pass < 2; pass++) { | ||
| 368 | for (i = 0; i + (sizeof(u16) * 3) < fw->size;) { | ||
| 369 | value = get_unaligned_le16(fw->data + i); | ||
| 370 | i += sizeof(u16); | ||
| 371 | |||
| 372 | index = get_unaligned_le16(fw->data + i); | ||
| 373 | i += sizeof(u16); | ||
| 374 | |||
| 375 | size = get_unaligned_le16(fw->data + i); | ||
| 376 | i += sizeof(u16); | ||
| 377 | |||
| 378 | if (pass == 1) { | ||
| 379 | /* Will stall if using fw->data ... */ | ||
| 380 | memcpy(buff, fw->data + i, size); | ||
| 381 | |||
| 382 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), | ||
| 383 | M9206_FW, | ||
| 384 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 385 | value, index, buff, size, 20); | ||
| 386 | if (ret != size) { | ||
| 387 | deb("error while uploading fw!\n"); | ||
| 388 | ret = -EIO; | ||
| 389 | goto done; | ||
| 390 | } | ||
| 391 | msleep(3); | ||
| 392 | } | ||
| 393 | i += size; | ||
| 394 | } | ||
| 395 | if (i != fw->size) { | ||
| 396 | deb("bad firmware file!\n"); | ||
| 397 | ret = -EINVAL; | ||
| 398 | goto done; | ||
| 399 | } | ||
| 400 | } | ||
| 401 | |||
| 402 | msleep(36); | ||
| 403 | |||
| 404 | /* m920x will disconnect itself from the bus after this. */ | ||
| 405 | (void) m920x_write(udev, M9206_CORE, 0x01, M9206_FW_GO); | ||
| 406 | deb("firmware uploaded!\n"); | ||
| 407 | |||
| 408 | done: | ||
| 409 | kfree(read); | ||
| 410 | kfree(buff); | ||
| 411 | |||
| 412 | return ret; | ||
| 413 | } | ||
| 414 | |||
| 415 | /* Callbacks for DVB USB */ | ||
| 416 | static int m920x_identify_state(struct usb_device *udev, | ||
| 417 | struct dvb_usb_device_properties *props, | ||
| 418 | struct dvb_usb_device_description **desc, | ||
| 419 | int *cold) | ||
| 420 | { | ||
| 421 | struct usb_host_interface *alt; | ||
| 422 | |||
| 423 | alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1); | ||
| 424 | *cold = (alt == NULL) ? 1 : 0; | ||
| 425 | |||
| 426 | return 0; | ||
| 427 | } | ||
| 428 | |||
| 429 | /* demod configurations */ | ||
| 430 | static int m920x_mt352_demod_init(struct dvb_frontend *fe) | ||
| 431 | { | ||
| 432 | int ret; | ||
| 433 | u8 config[] = { CONFIG, 0x3d }; | ||
| 434 | u8 clock[] = { CLOCK_CTL, 0x30 }; | ||
| 435 | u8 reset[] = { RESET, 0x80 }; | ||
| 436 | u8 adc_ctl[] = { ADC_CTL_1, 0x40 }; | ||
| 437 | u8 agc[] = { AGC_TARGET, 0x1c, 0x20 }; | ||
| 438 | u8 sec_agc[] = { 0x69, 0x00, 0xff, 0xff, 0x40, 0xff, 0x00, 0x40, 0x40 }; | ||
| 439 | u8 unk1[] = { 0x93, 0x1a }; | ||
| 440 | u8 unk2[] = { 0xb5, 0x7a }; | ||
| 441 | |||
| 442 | deb("Demod init!\n"); | ||
| 443 | |||
| 444 | if ((ret = mt352_write(fe, config, ARRAY_SIZE(config))) != 0) | ||
| 445 | return ret; | ||
| 446 | if ((ret = mt352_write(fe, clock, ARRAY_SIZE(clock))) != 0) | ||
| 447 | return ret; | ||
| 448 | if ((ret = mt352_write(fe, reset, ARRAY_SIZE(reset))) != 0) | ||
| 449 | return ret; | ||
| 450 | if ((ret = mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl))) != 0) | ||
| 451 | return ret; | ||
| 452 | if ((ret = mt352_write(fe, agc, ARRAY_SIZE(agc))) != 0) | ||
| 453 | return ret; | ||
| 454 | if ((ret = mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc))) != 0) | ||
| 455 | return ret; | ||
| 456 | if ((ret = mt352_write(fe, unk1, ARRAY_SIZE(unk1))) != 0) | ||
| 457 | return ret; | ||
| 458 | if ((ret = mt352_write(fe, unk2, ARRAY_SIZE(unk2))) != 0) | ||
| 459 | return ret; | ||
| 460 | |||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | |||
| 464 | static struct mt352_config m920x_mt352_config = { | ||
| 465 | .demod_address = 0x0f, | ||
| 466 | .no_tuner = 1, | ||
| 467 | .demod_init = m920x_mt352_demod_init, | ||
| 468 | }; | ||
| 469 | |||
| 470 | static struct tda1004x_config m920x_tda10046_08_config = { | ||
| 471 | .demod_address = 0x08, | ||
| 472 | .invert = 0, | ||
| 473 | .invert_oclk = 0, | ||
| 474 | .ts_mode = TDA10046_TS_SERIAL, | ||
| 475 | .xtal_freq = TDA10046_XTAL_16M, | ||
| 476 | .if_freq = TDA10046_FREQ_045, | ||
| 477 | .agc_config = TDA10046_AGC_TDA827X, | ||
| 478 | .gpio_config = TDA10046_GPTRI, | ||
| 479 | .request_firmware = NULL, | ||
| 480 | }; | ||
| 481 | |||
| 482 | static struct tda1004x_config m920x_tda10046_0b_config = { | ||
| 483 | .demod_address = 0x0b, | ||
| 484 | .invert = 0, | ||
| 485 | .invert_oclk = 0, | ||
| 486 | .ts_mode = TDA10046_TS_SERIAL, | ||
| 487 | .xtal_freq = TDA10046_XTAL_16M, | ||
| 488 | .if_freq = TDA10046_FREQ_045, | ||
| 489 | .agc_config = TDA10046_AGC_TDA827X, | ||
| 490 | .gpio_config = TDA10046_GPTRI, | ||
| 491 | .request_firmware = NULL, /* uses firmware EEPROM */ | ||
| 492 | }; | ||
| 493 | |||
| 494 | /* tuner configurations */ | ||
| 495 | static struct qt1010_config m920x_qt1010_config = { | ||
| 496 | .i2c_address = 0x62 | ||
| 497 | }; | ||
| 498 | |||
| 499 | /* Callbacks for DVB USB */ | ||
| 500 | static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 501 | { | ||
| 502 | deb("%s\n",__func__); | ||
| 503 | |||
| 504 | if ((adap->fe = dvb_attach(mt352_attach, | ||
| 505 | &m920x_mt352_config, | ||
| 506 | &adap->dev->i2c_adap)) == NULL) | ||
| 507 | return -EIO; | ||
| 508 | |||
| 509 | return 0; | ||
| 510 | } | ||
| 511 | |||
| 512 | static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 513 | { | ||
| 514 | deb("%s\n",__func__); | ||
| 515 | |||
| 516 | if ((adap->fe = dvb_attach(tda10046_attach, | ||
| 517 | &m920x_tda10046_08_config, | ||
| 518 | &adap->dev->i2c_adap)) == NULL) | ||
| 519 | return -EIO; | ||
| 520 | |||
| 521 | return 0; | ||
| 522 | } | ||
| 523 | |||
| 524 | static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 525 | { | ||
| 526 | deb("%s\n",__func__); | ||
| 527 | |||
| 528 | if ((adap->fe = dvb_attach(tda10046_attach, | ||
| 529 | &m920x_tda10046_0b_config, | ||
| 530 | &adap->dev->i2c_adap)) == NULL) | ||
| 531 | return -EIO; | ||
| 532 | |||
| 533 | return 0; | ||
| 534 | } | ||
| 535 | |||
| 536 | static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 537 | { | ||
| 538 | deb("%s\n",__func__); | ||
| 539 | |||
| 540 | if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL) | ||
| 541 | return -ENODEV; | ||
| 542 | |||
| 543 | return 0; | ||
| 544 | } | ||
| 545 | |||
| 546 | static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 547 | { | ||
| 548 | deb("%s\n",__func__); | ||
| 549 | |||
| 550 | if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL) | ||
| 551 | return -ENODEV; | ||
| 552 | |||
| 553 | return 0; | ||
| 554 | } | ||
| 555 | |||
| 556 | static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 557 | { | ||
| 558 | deb("%s\n",__func__); | ||
| 559 | |||
| 560 | if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) | ||
| 561 | return -ENODEV; | ||
| 562 | |||
| 563 | return 0; | ||
| 564 | } | ||
| 565 | |||
| 566 | static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 567 | { | ||
| 568 | dvb_attach(simple_tuner_attach, adap->fe, | ||
| 569 | &adap->dev->i2c_adap, 0x61, | ||
| 570 | TUNER_PHILIPS_FMD1216ME_MK3); | ||
| 571 | return 0; | ||
| 572 | } | ||
| 573 | |||
| 574 | /* device-specific initialization */ | ||
| 575 | static struct m920x_inits megasky_rc_init [] = { | ||
| 576 | { M9206_RC_INIT2, 0xa8 }, | ||
| 577 | { M9206_RC_INIT1, 0x51 }, | ||
| 578 | { } /* terminating entry */ | ||
| 579 | }; | ||
| 580 | |||
| 581 | static struct m920x_inits tvwalkertwin_rc_init [] = { | ||
| 582 | { M9206_RC_INIT2, 0x00 }, | ||
| 583 | { M9206_RC_INIT1, 0xef }, | ||
| 584 | { 0xff28, 0x00 }, | ||
| 585 | { 0xff23, 0x00 }, | ||
| 586 | { 0xff21, 0x30 }, | ||
| 587 | { } /* terminating entry */ | ||
| 588 | }; | ||
| 589 | |||
| 590 | static struct m920x_inits pinnacle310e_init[] = { | ||
| 591 | /* without these the tuner don't work */ | ||
| 592 | { 0xff20, 0x9b }, | ||
| 593 | { 0xff22, 0x70 }, | ||
| 594 | |||
| 595 | /* rc settings */ | ||
| 596 | { 0xff50, 0x80 }, | ||
| 597 | { M9206_RC_INIT1, 0x00 }, | ||
| 598 | { M9206_RC_INIT2, 0xff }, | ||
| 599 | { } /* terminating entry */ | ||
| 600 | }; | ||
| 601 | |||
| 602 | /* ir keymaps */ | ||
| 603 | static struct rc_map_table rc_map_megasky_table[] = { | ||
| 604 | { 0x0012, KEY_POWER }, | ||
| 605 | { 0x001e, KEY_CYCLEWINDOWS }, /* min/max */ | ||
| 606 | { 0x0002, KEY_CHANNELUP }, | ||
| 607 | { 0x0005, KEY_CHANNELDOWN }, | ||
| 608 | { 0x0003, KEY_VOLUMEUP }, | ||
| 609 | { 0x0006, KEY_VOLUMEDOWN }, | ||
| 610 | { 0x0004, KEY_MUTE }, | ||
| 611 | { 0x0007, KEY_OK }, /* TS */ | ||
| 612 | { 0x0008, KEY_STOP }, | ||
| 613 | { 0x0009, KEY_MENU }, /* swap */ | ||
| 614 | { 0x000a, KEY_REWIND }, | ||
| 615 | { 0x001b, KEY_PAUSE }, | ||
| 616 | { 0x001f, KEY_FASTFORWARD }, | ||
| 617 | { 0x000c, KEY_RECORD }, | ||
| 618 | { 0x000d, KEY_CAMERA }, /* screenshot */ | ||
| 619 | { 0x000e, KEY_COFFEE }, /* "MTS" */ | ||
| 620 | }; | ||
| 621 | |||
| 622 | static struct rc_map_table rc_map_tvwalkertwin_table[] = { | ||
| 623 | { 0x0001, KEY_ZOOM }, /* Full Screen */ | ||
| 624 | { 0x0002, KEY_CAMERA }, /* snapshot */ | ||
| 625 | { 0x0003, KEY_MUTE }, | ||
| 626 | { 0x0004, KEY_REWIND }, | ||
| 627 | { 0x0005, KEY_PLAYPAUSE }, /* Play/Pause */ | ||
| 628 | { 0x0006, KEY_FASTFORWARD }, | ||
| 629 | { 0x0007, KEY_RECORD }, | ||
| 630 | { 0x0008, KEY_STOP }, | ||
| 631 | { 0x0009, KEY_TIME }, /* Timeshift */ | ||
| 632 | { 0x000c, KEY_COFFEE }, /* Recall */ | ||
| 633 | { 0x000e, KEY_CHANNELUP }, | ||
| 634 | { 0x0012, KEY_POWER }, | ||
| 635 | { 0x0015, KEY_MENU }, /* source */ | ||
| 636 | { 0x0018, KEY_CYCLEWINDOWS }, /* TWIN PIP */ | ||
| 637 | { 0x001a, KEY_CHANNELDOWN }, | ||
| 638 | { 0x001b, KEY_VOLUMEDOWN }, | ||
| 639 | { 0x001e, KEY_VOLUMEUP }, | ||
| 640 | }; | ||
| 641 | |||
| 642 | static struct rc_map_table rc_map_pinnacle310e_table[] = { | ||
| 643 | { 0x16, KEY_POWER }, | ||
| 644 | { 0x17, KEY_FAVORITES }, | ||
| 645 | { 0x0f, KEY_TEXT }, | ||
| 646 | { 0x48, KEY_PROGRAM }, /* preview */ | ||
| 647 | { 0x1c, KEY_EPG }, | ||
| 648 | { 0x04, KEY_LIST }, /* record list */ | ||
| 649 | { 0x03, KEY_1 }, | ||
| 650 | { 0x01, KEY_2 }, | ||
| 651 | { 0x06, KEY_3 }, | ||
| 652 | { 0x09, KEY_4 }, | ||
| 653 | { 0x1d, KEY_5 }, | ||
| 654 | { 0x1f, KEY_6 }, | ||
| 655 | { 0x0d, KEY_7 }, | ||
| 656 | { 0x19, KEY_8 }, | ||
| 657 | { 0x1b, KEY_9 }, | ||
| 658 | { 0x15, KEY_0 }, | ||
| 659 | { 0x0c, KEY_CANCEL }, | ||
| 660 | { 0x4a, KEY_CLEAR }, | ||
| 661 | { 0x13, KEY_BACK }, | ||
| 662 | { 0x00, KEY_TAB }, | ||
| 663 | { 0x4b, KEY_UP }, | ||
| 664 | { 0x4e, KEY_LEFT }, | ||
| 665 | { 0x52, KEY_RIGHT }, | ||
| 666 | { 0x51, KEY_DOWN }, | ||
| 667 | { 0x4f, KEY_ENTER }, /* could also be KEY_OK */ | ||
| 668 | { 0x1e, KEY_VOLUMEUP }, | ||
| 669 | { 0x0a, KEY_VOLUMEDOWN }, | ||
| 670 | { 0x05, KEY_CHANNELUP }, | ||
| 671 | { 0x02, KEY_CHANNELDOWN }, | ||
| 672 | { 0x11, KEY_RECORD }, | ||
| 673 | { 0x14, KEY_PLAY }, | ||
| 674 | { 0x4c, KEY_PAUSE }, | ||
| 675 | { 0x1a, KEY_STOP }, | ||
| 676 | { 0x40, KEY_REWIND }, | ||
| 677 | { 0x12, KEY_FASTFORWARD }, | ||
| 678 | { 0x41, KEY_PREVIOUSSONG }, /* Replay */ | ||
| 679 | { 0x42, KEY_NEXTSONG }, /* Skip */ | ||
| 680 | { 0x54, KEY_CAMERA }, /* Capture */ | ||
| 681 | /* { 0x50, KEY_SAP }, */ /* Sap */ | ||
| 682 | { 0x47, KEY_CYCLEWINDOWS }, /* Pip */ | ||
| 683 | { 0x4d, KEY_SCREEN }, /* FullScreen */ | ||
| 684 | { 0x08, KEY_SUBTITLE }, | ||
| 685 | { 0x0e, KEY_MUTE }, | ||
| 686 | /* { 0x49, KEY_LR }, */ /* L/R */ | ||
| 687 | { 0x07, KEY_SLEEP }, /* Hibernate */ | ||
| 688 | { 0x08, KEY_VIDEO }, /* A/V */ | ||
| 689 | { 0x0e, KEY_MENU }, /* Recall */ | ||
| 690 | { 0x45, KEY_ZOOMIN }, | ||
| 691 | { 0x46, KEY_ZOOMOUT }, | ||
| 692 | { 0x18, KEY_RED }, /* Red */ | ||
| 693 | { 0x53, KEY_GREEN }, /* Green */ | ||
| 694 | { 0x5e, KEY_YELLOW }, /* Yellow */ | ||
| 695 | { 0x5f, KEY_BLUE }, /* Blue */ | ||
| 696 | }; | ||
| 697 | |||
| 698 | /* DVB USB Driver stuff */ | ||
| 699 | static struct dvb_usb_device_properties megasky_properties; | ||
| 700 | static struct dvb_usb_device_properties digivox_mini_ii_properties; | ||
| 701 | static struct dvb_usb_device_properties tvwalkertwin_properties; | ||
| 702 | static struct dvb_usb_device_properties dposh_properties; | ||
| 703 | static struct dvb_usb_device_properties pinnacle_pctv310e_properties; | ||
| 704 | |||
| 705 | static int m920x_probe(struct usb_interface *intf, | ||
| 706 | const struct usb_device_id *id) | ||
| 707 | { | ||
| 708 | struct dvb_usb_device *d = NULL; | ||
| 709 | int ret; | ||
| 710 | struct m920x_inits *rc_init_seq = NULL; | ||
| 711 | int bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber; | ||
| 712 | |||
| 713 | deb("Probing for m920x device at interface %d\n", bInterfaceNumber); | ||
| 714 | |||
| 715 | if (bInterfaceNumber == 0) { | ||
| 716 | /* Single-tuner device, or first interface on | ||
| 717 | * multi-tuner device | ||
| 718 | */ | ||
| 719 | |||
| 720 | ret = dvb_usb_device_init(intf, &megasky_properties, | ||
| 721 | THIS_MODULE, &d, adapter_nr); | ||
| 722 | if (ret == 0) { | ||
| 723 | rc_init_seq = megasky_rc_init; | ||
| 724 | goto found; | ||
| 725 | } | ||
| 726 | |||
| 727 | ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, | ||
| 728 | THIS_MODULE, &d, adapter_nr); | ||
| 729 | if (ret == 0) { | ||
| 730 | /* No remote control, so no rc_init_seq */ | ||
| 731 | goto found; | ||
| 732 | } | ||
| 733 | |||
| 734 | /* This configures both tuners on the TV Walker Twin */ | ||
| 735 | ret = dvb_usb_device_init(intf, &tvwalkertwin_properties, | ||
| 736 | THIS_MODULE, &d, adapter_nr); | ||
| 737 | if (ret == 0) { | ||
| 738 | rc_init_seq = tvwalkertwin_rc_init; | ||
| 739 | goto found; | ||
| 740 | } | ||
| 741 | |||
| 742 | ret = dvb_usb_device_init(intf, &dposh_properties, | ||
| 743 | THIS_MODULE, &d, adapter_nr); | ||
| 744 | if (ret == 0) { | ||
| 745 | /* Remote controller not supported yet. */ | ||
| 746 | goto found; | ||
| 747 | } | ||
| 748 | |||
| 749 | ret = dvb_usb_device_init(intf, &pinnacle_pctv310e_properties, | ||
| 750 | THIS_MODULE, &d, adapter_nr); | ||
| 751 | if (ret == 0) { | ||
| 752 | rc_init_seq = pinnacle310e_init; | ||
| 753 | goto found; | ||
| 754 | } | ||
| 755 | |||
| 756 | return ret; | ||
| 757 | } else { | ||
| 758 | /* Another interface on a multi-tuner device */ | ||
| 759 | |||
| 760 | /* The LifeView TV Walker Twin gets here, but struct | ||
| 761 | * tvwalkertwin_properties already configured both | ||
| 762 | * tuners, so there is nothing for us to do here | ||
| 763 | */ | ||
| 764 | } | ||
| 765 | |||
| 766 | found: | ||
| 767 | if ((ret = m920x_init_ep(intf)) < 0) | ||
| 768 | return ret; | ||
| 769 | |||
| 770 | if (d && (ret = m920x_init(d, rc_init_seq)) != 0) | ||
| 771 | return ret; | ||
| 772 | |||
| 773 | return ret; | ||
| 774 | } | ||
| 775 | |||
| 776 | static struct usb_device_id m920x_table [] = { | ||
| 777 | { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, | ||
| 778 | { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, | ||
| 779 | USB_PID_MSI_DIGI_VOX_MINI_II) }, | ||
| 780 | { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, | ||
| 781 | USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD) }, | ||
| 782 | { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, | ||
| 783 | USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) }, | ||
| 784 | { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) }, | ||
| 785 | { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) }, | ||
| 786 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_PINNACLE_PCTV310E) }, | ||
| 787 | { } /* Terminating entry */ | ||
| 788 | }; | ||
| 789 | MODULE_DEVICE_TABLE (usb, m920x_table); | ||
| 790 | |||
| 791 | static struct dvb_usb_device_properties megasky_properties = { | ||
| 792 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 793 | |||
| 794 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 795 | .firmware = "dvb-usb-megasky-02.fw", | ||
| 796 | .download_firmware = m920x_firmware_download, | ||
| 797 | |||
| 798 | .rc.legacy = { | ||
| 799 | .rc_interval = 100, | ||
| 800 | .rc_map_table = rc_map_megasky_table, | ||
| 801 | .rc_map_size = ARRAY_SIZE(rc_map_megasky_table), | ||
| 802 | .rc_query = m920x_rc_query, | ||
| 803 | }, | ||
| 804 | |||
| 805 | .size_of_priv = sizeof(struct m920x_state), | ||
| 806 | |||
| 807 | .identify_state = m920x_identify_state, | ||
| 808 | .num_adapters = 1, | ||
| 809 | .adapter = {{ | ||
| 810 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 811 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 812 | |||
| 813 | .pid_filter_count = 8, | ||
| 814 | .pid_filter = m920x_pid_filter, | ||
| 815 | .pid_filter_ctrl = m920x_pid_filter_ctrl, | ||
| 816 | |||
| 817 | .frontend_attach = m920x_mt352_frontend_attach, | ||
| 818 | .tuner_attach = m920x_qt1010_tuner_attach, | ||
| 819 | |||
| 820 | .stream = { | ||
| 821 | .type = USB_BULK, | ||
| 822 | .count = 8, | ||
| 823 | .endpoint = 0x81, | ||
| 824 | .u = { | ||
| 825 | .bulk = { | ||
| 826 | .buffersize = 512, | ||
| 827 | } | ||
| 828 | } | ||
| 829 | }, | ||
| 830 | }}, | ||
| 831 | .i2c_algo = &m920x_i2c_algo, | ||
| 832 | |||
| 833 | .num_device_descs = 1, | ||
| 834 | .devices = { | ||
| 835 | { "MSI Mega Sky 580 DVB-T USB2.0", | ||
| 836 | { &m920x_table[0], NULL }, | ||
| 837 | { NULL }, | ||
| 838 | } | ||
| 839 | } | ||
| 840 | }; | ||
| 841 | |||
| 842 | static struct dvb_usb_device_properties digivox_mini_ii_properties = { | ||
| 843 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 844 | |||
| 845 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 846 | .firmware = "dvb-usb-digivox-02.fw", | ||
| 847 | .download_firmware = m920x_firmware_download, | ||
| 848 | |||
| 849 | .size_of_priv = sizeof(struct m920x_state), | ||
| 850 | |||
| 851 | .identify_state = m920x_identify_state, | ||
| 852 | .num_adapters = 1, | ||
| 853 | .adapter = {{ | ||
| 854 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 855 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 856 | |||
| 857 | .pid_filter_count = 8, | ||
| 858 | .pid_filter = m920x_pid_filter, | ||
| 859 | .pid_filter_ctrl = m920x_pid_filter_ctrl, | ||
| 860 | |||
| 861 | .frontend_attach = m920x_tda10046_08_frontend_attach, | ||
| 862 | .tuner_attach = m920x_tda8275_60_tuner_attach, | ||
| 863 | |||
| 864 | .stream = { | ||
| 865 | .type = USB_BULK, | ||
| 866 | .count = 8, | ||
| 867 | .endpoint = 0x81, | ||
| 868 | .u = { | ||
| 869 | .bulk = { | ||
| 870 | .buffersize = 0x4000, | ||
| 871 | } | ||
| 872 | } | ||
| 873 | }, | ||
| 874 | }}, | ||
| 875 | .i2c_algo = &m920x_i2c_algo, | ||
| 876 | |||
| 877 | .num_device_descs = 1, | ||
| 878 | .devices = { | ||
| 879 | { "MSI DIGI VOX mini II DVB-T USB2.0", | ||
| 880 | { &m920x_table[1], NULL }, | ||
| 881 | { NULL }, | ||
| 882 | }, | ||
| 883 | } | ||
| 884 | }; | ||
| 885 | |||
| 886 | /* LifeView TV Walker Twin support by Nick Andrew <nick@nick-andrew.net> | ||
| 887 | * | ||
| 888 | * LifeView TV Walker Twin has 1 x M9206, 2 x TDA10046, 2 x TDA8275A | ||
| 889 | * TDA10046 #0 is located at i2c address 0x08 | ||
| 890 | * TDA10046 #1 is located at i2c address 0x0b | ||
| 891 | * TDA8275A #0 is located at i2c address 0x60 | ||
| 892 | * TDA8275A #1 is located at i2c address 0x61 | ||
| 893 | */ | ||
| 894 | static struct dvb_usb_device_properties tvwalkertwin_properties = { | ||
| 895 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 896 | |||
| 897 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 898 | .firmware = "dvb-usb-tvwalkert.fw", | ||
| 899 | .download_firmware = m920x_firmware_download, | ||
| 900 | |||
| 901 | .rc.legacy = { | ||
| 902 | .rc_interval = 100, | ||
| 903 | .rc_map_table = rc_map_tvwalkertwin_table, | ||
| 904 | .rc_map_size = ARRAY_SIZE(rc_map_tvwalkertwin_table), | ||
| 905 | .rc_query = m920x_rc_query, | ||
| 906 | }, | ||
| 907 | |||
| 908 | .size_of_priv = sizeof(struct m920x_state), | ||
| 909 | |||
| 910 | .identify_state = m920x_identify_state, | ||
| 911 | .num_adapters = 2, | ||
| 912 | .adapter = {{ | ||
| 913 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 914 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 915 | |||
| 916 | .pid_filter_count = 8, | ||
| 917 | .pid_filter = m920x_pid_filter, | ||
| 918 | .pid_filter_ctrl = m920x_pid_filter_ctrl, | ||
| 919 | |||
| 920 | .frontend_attach = m920x_tda10046_08_frontend_attach, | ||
| 921 | .tuner_attach = m920x_tda8275_60_tuner_attach, | ||
| 922 | |||
| 923 | .stream = { | ||
| 924 | .type = USB_BULK, | ||
| 925 | .count = 8, | ||
| 926 | .endpoint = 0x81, | ||
| 927 | .u = { | ||
| 928 | .bulk = { | ||
| 929 | .buffersize = 512, | ||
| 930 | } | ||
| 931 | } | ||
| 932 | }},{ | ||
| 933 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 934 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 935 | |||
| 936 | .pid_filter_count = 8, | ||
| 937 | .pid_filter = m920x_pid_filter, | ||
| 938 | .pid_filter_ctrl = m920x_pid_filter_ctrl, | ||
| 939 | |||
| 940 | .frontend_attach = m920x_tda10046_0b_frontend_attach, | ||
| 941 | .tuner_attach = m920x_tda8275_61_tuner_attach, | ||
| 942 | |||
| 943 | .stream = { | ||
| 944 | .type = USB_BULK, | ||
| 945 | .count = 8, | ||
| 946 | .endpoint = 0x82, | ||
| 947 | .u = { | ||
| 948 | .bulk = { | ||
| 949 | .buffersize = 512, | ||
| 950 | } | ||
| 951 | } | ||
| 952 | }, | ||
| 953 | }}, | ||
| 954 | .i2c_algo = &m920x_i2c_algo, | ||
| 955 | |||
| 956 | .num_device_descs = 1, | ||
| 957 | .devices = { | ||
| 958 | { .name = "LifeView TV Walker Twin DVB-T USB2.0", | ||
| 959 | .cold_ids = { &m920x_table[2], NULL }, | ||
| 960 | .warm_ids = { &m920x_table[3], NULL }, | ||
| 961 | }, | ||
| 962 | } | ||
| 963 | }; | ||
| 964 | |||
| 965 | static struct dvb_usb_device_properties dposh_properties = { | ||
| 966 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 967 | |||
| 968 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 969 | .firmware = "dvb-usb-dposh-01.fw", | ||
| 970 | .download_firmware = m920x_firmware_download, | ||
| 971 | |||
| 972 | .size_of_priv = sizeof(struct m920x_state), | ||
| 973 | |||
| 974 | .identify_state = m920x_identify_state, | ||
| 975 | .num_adapters = 1, | ||
| 976 | .adapter = {{ | ||
| 977 | /* Hardware pid filters don't work with this device/firmware */ | ||
| 978 | |||
| 979 | .frontend_attach = m920x_mt352_frontend_attach, | ||
| 980 | .tuner_attach = m920x_qt1010_tuner_attach, | ||
| 981 | |||
| 982 | .stream = { | ||
| 983 | .type = USB_BULK, | ||
| 984 | .count = 8, | ||
| 985 | .endpoint = 0x81, | ||
| 986 | .u = { | ||
| 987 | .bulk = { | ||
| 988 | .buffersize = 512, | ||
| 989 | } | ||
| 990 | } | ||
| 991 | }, | ||
| 992 | }}, | ||
| 993 | .i2c_algo = &m920x_i2c_algo, | ||
| 994 | |||
| 995 | .num_device_descs = 1, | ||
| 996 | .devices = { | ||
| 997 | { .name = "Dposh DVB-T USB2.0", | ||
| 998 | .cold_ids = { &m920x_table[4], NULL }, | ||
| 999 | .warm_ids = { &m920x_table[5], NULL }, | ||
| 1000 | }, | ||
| 1001 | } | ||
| 1002 | }; | ||
| 1003 | |||
| 1004 | static struct dvb_usb_device_properties pinnacle_pctv310e_properties = { | ||
| 1005 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 1006 | |||
| 1007 | .usb_ctrl = DEVICE_SPECIFIC, | ||
| 1008 | .download_firmware = NULL, | ||
| 1009 | |||
| 1010 | .rc.legacy = { | ||
| 1011 | .rc_interval = 100, | ||
| 1012 | .rc_map_table = rc_map_pinnacle310e_table, | ||
| 1013 | .rc_map_size = ARRAY_SIZE(rc_map_pinnacle310e_table), | ||
| 1014 | .rc_query = m920x_rc_query, | ||
| 1015 | }, | ||
| 1016 | |||
| 1017 | .size_of_priv = sizeof(struct m920x_state), | ||
| 1018 | |||
| 1019 | .identify_state = m920x_identify_state, | ||
| 1020 | .num_adapters = 1, | ||
| 1021 | .adapter = {{ | ||
| 1022 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 1023 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 1024 | |||
| 1025 | .pid_filter_count = 8, | ||
| 1026 | .pid_filter = m920x_pid_filter, | ||
| 1027 | .pid_filter_ctrl = m920x_pid_filter_ctrl, | ||
| 1028 | |||
| 1029 | .frontend_attach = m920x_mt352_frontend_attach, | ||
| 1030 | .tuner_attach = m920x_fmd1216me_tuner_attach, | ||
| 1031 | |||
| 1032 | .stream = { | ||
| 1033 | .type = USB_ISOC, | ||
| 1034 | .count = 5, | ||
| 1035 | .endpoint = 0x84, | ||
| 1036 | .u = { | ||
| 1037 | .isoc = { | ||
| 1038 | .framesperurb = 128, | ||
| 1039 | .framesize = 564, | ||
| 1040 | .interval = 1, | ||
| 1041 | } | ||
| 1042 | } | ||
| 1043 | }, | ||
| 1044 | } }, | ||
| 1045 | .i2c_algo = &m920x_i2c_algo, | ||
| 1046 | |||
| 1047 | .num_device_descs = 1, | ||
| 1048 | .devices = { | ||
| 1049 | { "Pinnacle PCTV 310e", | ||
| 1050 | { &m920x_table[6], NULL }, | ||
| 1051 | { NULL }, | ||
| 1052 | } | ||
| 1053 | } | ||
| 1054 | }; | ||
| 1055 | |||
| 1056 | static struct usb_driver m920x_driver = { | ||
| 1057 | .name = "dvb_usb_m920x", | ||
| 1058 | .probe = m920x_probe, | ||
| 1059 | .disconnect = dvb_usb_device_exit, | ||
| 1060 | .id_table = m920x_table, | ||
| 1061 | }; | ||
| 1062 | |||
| 1063 | /* module stuff */ | ||
| 1064 | static int __init m920x_module_init(void) | ||
| 1065 | { | ||
| 1066 | int ret; | ||
| 1067 | |||
| 1068 | if ((ret = usb_register(&m920x_driver))) { | ||
| 1069 | err("usb_register failed. Error number %d", ret); | ||
| 1070 | return ret; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | return 0; | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | static void __exit m920x_module_exit(void) | ||
| 1077 | { | ||
| 1078 | /* deregister this driver from the USB subsystem */ | ||
| 1079 | usb_deregister(&m920x_driver); | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | module_init (m920x_module_init); | ||
| 1083 | module_exit (m920x_module_exit); | ||
| 1084 | |||
| 1085 | MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>"); | ||
| 1086 | MODULE_DESCRIPTION("DVB Driver for ULI M920x"); | ||
| 1087 | MODULE_VERSION("0.1"); | ||
| 1088 | MODULE_LICENSE("GPL"); | ||
| 1089 | |||
| 1090 | /* | ||
| 1091 | * Local variables: | ||
| 1092 | * c-basic-offset: 8 | ||
| 1093 | */ | ||
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h new file mode 100644 index 00000000000..3c061518ffc --- /dev/null +++ b/drivers/media/dvb/dvb-usb/m920x.h | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | #ifndef _DVB_USB_M920X_H_ | ||
| 2 | #define _DVB_USB_M920X_H_ | ||
| 3 | |||
| 4 | #define DVB_USB_LOG_PREFIX "m920x" | ||
| 5 | #include "dvb-usb.h" | ||
| 6 | |||
| 7 | #define deb(args...) dprintk(dvb_usb_m920x_debug,0x01,args) | ||
| 8 | |||
| 9 | #define M9206_CORE 0x22 | ||
| 10 | #define M9206_RC_STATE 0xff51 | ||
| 11 | #define M9206_RC_KEY 0xff52 | ||
| 12 | #define M9206_RC_INIT1 0xff54 | ||
| 13 | #define M9206_RC_INIT2 0xff55 | ||
| 14 | #define M9206_FW_GO 0xff69 | ||
| 15 | |||
| 16 | #define M9206_I2C 0x23 | ||
| 17 | #define M9206_FILTER 0x25 | ||
| 18 | #define M9206_FW 0x30 | ||
| 19 | |||
| 20 | #define M9206_MAX_FILTERS 8 | ||
| 21 | #define M9206_MAX_ADAPTERS 4 | ||
| 22 | |||
| 23 | /* | ||
| 24 | sequences found in logs: | ||
| 25 | [index value] | ||
| 26 | 0x80 write addr | ||
| 27 | (0x00 out byte)* | ||
| 28 | 0x40 out byte | ||
| 29 | |||
| 30 | 0x80 write addr | ||
| 31 | (0x00 out byte)* | ||
| 32 | 0x80 read addr | ||
| 33 | (0x21 in byte)* | ||
| 34 | 0x60 in byte | ||
| 35 | |||
| 36 | this sequence works: | ||
| 37 | 0x80 read addr | ||
| 38 | (0x21 in byte)* | ||
| 39 | 0x60 in byte | ||
| 40 | |||
| 41 | Guess at API of the I2C function: | ||
| 42 | I2C operation is done one byte at a time with USB control messages. The | ||
| 43 | index the messages is sent to is made up of a set of flags that control | ||
| 44 | the I2C bus state: | ||
| 45 | 0x80: Send START condition. After a START condition, one would normally | ||
| 46 | always send the 7-bit slave I2C address as the 7 MSB, followed by | ||
| 47 | the read/write bit as the LSB. | ||
| 48 | 0x40: Send STOP condition. This should be set on the last byte of an | ||
| 49 | I2C transaction. | ||
| 50 | 0x20: Read a byte from the slave. As opposed to writing a byte to the | ||
| 51 | slave. The slave will normally not produce any data unless you | ||
| 52 | set the R/W bit to 1 when sending the slave's address after the | ||
| 53 | START condition. | ||
| 54 | 0x01: Respond with ACK, as opposed to a NACK. For a multi-byte read, | ||
| 55 | the master should send an ACK, that is pull SDA low during the 9th | ||
| 56 | clock cycle, after every byte but the last. This flags only makes | ||
| 57 | sense when bit 0x20 is set, indicating a read. | ||
| 58 | |||
| 59 | What any other bits might mean, or how to get the slave's ACK/NACK | ||
| 60 | response to a write, is unknown. | ||
| 61 | */ | ||
| 62 | |||
| 63 | struct m920x_state { | ||
| 64 | u16 filters[M9206_MAX_ADAPTERS][M9206_MAX_FILTERS]; | ||
| 65 | int filtering_enabled[M9206_MAX_ADAPTERS]; | ||
| 66 | int rep_count; | ||
| 67 | }; | ||
| 68 | |||
| 69 | /* Initialisation data for the m920x | ||
| 70 | */ | ||
| 71 | |||
| 72 | struct m920x_inits { | ||
| 73 | u16 address; | ||
| 74 | u8 data; | ||
| 75 | }; | ||
| 76 | |||
| 77 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c new file mode 100644 index 00000000000..bc350e982b7 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c | |||
| @@ -0,0 +1,250 @@ | |||
| 1 | /* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2 | ||
| 2 | * DVB-T receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the Free | ||
| 8 | * Software Foundation, version 2. | ||
| 9 | * | ||
| 10 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 11 | */ | ||
| 12 | #include "dibusb.h" | ||
| 13 | |||
| 14 | static int debug; | ||
| 15 | module_param(debug, int, 0644); | ||
| 16 | MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS); | ||
| 17 | |||
| 18 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 19 | |||
| 20 | #define deb_rc(args...) dprintk(debug,0x01,args) | ||
| 21 | #define deb_ee(args...) dprintk(debug,0x02,args) | ||
| 22 | |||
| 23 | /* Hauppauge NOVA-T USB2 keys */ | ||
| 24 | static struct rc_map_table rc_map_haupp_table[] = { | ||
| 25 | { 0x1e00, KEY_0 }, | ||
| 26 | { 0x1e01, KEY_1 }, | ||
| 27 | { 0x1e02, KEY_2 }, | ||
| 28 | { 0x1e03, KEY_3 }, | ||
| 29 | { 0x1e04, KEY_4 }, | ||
| 30 | { 0x1e05, KEY_5 }, | ||
| 31 | { 0x1e06, KEY_6 }, | ||
| 32 | { 0x1e07, KEY_7 }, | ||
| 33 | { 0x1e08, KEY_8 }, | ||
| 34 | { 0x1e09, KEY_9 }, | ||
| 35 | { 0x1e0a, KEY_KPASTERISK }, | ||
| 36 | { 0x1e0b, KEY_RED }, | ||
| 37 | { 0x1e0c, KEY_RADIO }, | ||
| 38 | { 0x1e0d, KEY_MENU }, | ||
| 39 | { 0x1e0e, KEY_GRAVE }, /* # */ | ||
| 40 | { 0x1e0f, KEY_MUTE }, | ||
| 41 | { 0x1e10, KEY_VOLUMEUP }, | ||
| 42 | { 0x1e11, KEY_VOLUMEDOWN }, | ||
| 43 | { 0x1e12, KEY_CHANNEL }, | ||
| 44 | { 0x1e14, KEY_UP }, | ||
| 45 | { 0x1e15, KEY_DOWN }, | ||
| 46 | { 0x1e16, KEY_LEFT }, | ||
| 47 | { 0x1e17, KEY_RIGHT }, | ||
| 48 | { 0x1e18, KEY_VIDEO }, | ||
| 49 | { 0x1e19, KEY_AUDIO }, | ||
| 50 | { 0x1e1a, KEY_IMAGES }, | ||
| 51 | { 0x1e1b, KEY_EPG }, | ||
| 52 | { 0x1e1c, KEY_TV }, | ||
| 53 | { 0x1e1e, KEY_NEXT }, | ||
| 54 | { 0x1e1f, KEY_BACK }, | ||
| 55 | { 0x1e20, KEY_CHANNELUP }, | ||
| 56 | { 0x1e21, KEY_CHANNELDOWN }, | ||
| 57 | { 0x1e24, KEY_LAST }, /* Skip backwards */ | ||
| 58 | { 0x1e25, KEY_OK }, | ||
| 59 | { 0x1e29, KEY_BLUE}, | ||
| 60 | { 0x1e2e, KEY_GREEN }, | ||
| 61 | { 0x1e30, KEY_PAUSE }, | ||
| 62 | { 0x1e32, KEY_REWIND }, | ||
| 63 | { 0x1e34, KEY_FASTFORWARD }, | ||
| 64 | { 0x1e35, KEY_PLAY }, | ||
| 65 | { 0x1e36, KEY_STOP }, | ||
| 66 | { 0x1e37, KEY_RECORD }, | ||
| 67 | { 0x1e38, KEY_YELLOW }, | ||
| 68 | { 0x1e3b, KEY_GOTO }, | ||
| 69 | { 0x1e3d, KEY_POWER }, | ||
| 70 | }; | ||
| 71 | |||
| 72 | /* Firmware bug? sometimes, when a new key is pressed, the previous pressed key | ||
| 73 | * is delivered. No workaround yet, maybe a new firmware. | ||
| 74 | */ | ||
| 75 | static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 76 | { | ||
| 77 | u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom; | ||
| 78 | u16 raw; | ||
| 79 | int i; | ||
| 80 | struct dibusb_device_state *st = d->priv; | ||
| 81 | |||
| 82 | dvb_usb_generic_rw(d,cmd,2,key,5,0); | ||
| 83 | |||
| 84 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 85 | switch (key[0]) { | ||
| 86 | case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED: | ||
| 87 | raw = ((key[1] << 8) | key[2]) >> 3; | ||
| 88 | toggle = !!(raw & 0x800); | ||
| 89 | data = raw & 0x3f; | ||
| 90 | custom = (raw >> 6) & 0x1f; | ||
| 91 | |||
| 92 | deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle); | ||
| 93 | |||
| 94 | for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) { | ||
| 95 | if (rc5_data(&rc_map_haupp_table[i]) == data && | ||
| 96 | rc5_custom(&rc_map_haupp_table[i]) == custom) { | ||
| 97 | |||
| 98 | deb_rc("c: %x, d: %x\n", rc5_data(&rc_map_haupp_table[i]), | ||
| 99 | rc5_custom(&rc_map_haupp_table[i])); | ||
| 100 | |||
| 101 | *event = rc_map_haupp_table[i].keycode; | ||
| 102 | *state = REMOTE_KEY_PRESSED; | ||
| 103 | if (st->old_toggle == toggle) { | ||
| 104 | if (st->last_repeat_count++ < 2) | ||
| 105 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 106 | } else { | ||
| 107 | st->last_repeat_count = 0; | ||
| 108 | st->old_toggle = toggle; | ||
| 109 | } | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | break; | ||
| 115 | case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY: | ||
| 116 | default: | ||
| 117 | break; | ||
| 118 | } | ||
| 119 | |||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6]) | ||
| 124 | { | ||
| 125 | int i; | ||
| 126 | u8 b; | ||
| 127 | |||
| 128 | mac[0] = 0x00; | ||
| 129 | mac[1] = 0x0d; | ||
| 130 | mac[2] = 0xfe; | ||
| 131 | |||
| 132 | /* this is a complete guess, but works for my box */ | ||
| 133 | for (i = 136; i < 139; i++) { | ||
| 134 | dibusb_read_eeprom_byte(d,i, &b); | ||
| 135 | |||
| 136 | mac[5 - (i - 136)] = b; | ||
| 137 | } | ||
| 138 | |||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* USB Driver stuff */ | ||
| 143 | static struct dvb_usb_device_properties nova_t_properties; | ||
| 144 | |||
| 145 | static int nova_t_probe(struct usb_interface *intf, | ||
| 146 | const struct usb_device_id *id) | ||
| 147 | { | ||
| 148 | return dvb_usb_device_init(intf, &nova_t_properties, | ||
| 149 | THIS_MODULE, NULL, adapter_nr); | ||
| 150 | } | ||
| 151 | |||
| 152 | /* do not change the order of the ID table */ | ||
| 153 | static struct usb_device_id nova_t_table [] = { | ||
| 154 | /* 00 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) }, | ||
| 155 | /* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) }, | ||
| 156 | { } /* Terminating entry */ | ||
| 157 | }; | ||
| 158 | MODULE_DEVICE_TABLE(usb, nova_t_table); | ||
| 159 | |||
| 160 | static struct dvb_usb_device_properties nova_t_properties = { | ||
| 161 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 162 | |||
| 163 | .usb_ctrl = CYPRESS_FX2, | ||
| 164 | .firmware = "dvb-usb-nova-t-usb2-02.fw", | ||
| 165 | |||
| 166 | .num_adapters = 1, | ||
| 167 | .adapter = { | ||
| 168 | { | ||
| 169 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 170 | .pid_filter_count = 32, | ||
| 171 | |||
| 172 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
| 173 | .pid_filter = dibusb_pid_filter, | ||
| 174 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
| 175 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | ||
| 176 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | ||
| 177 | |||
| 178 | /* parameter for the MPEG2-data transfer */ | ||
| 179 | .stream = { | ||
| 180 | .type = USB_BULK, | ||
| 181 | .count = 7, | ||
| 182 | .endpoint = 0x06, | ||
| 183 | .u = { | ||
| 184 | .bulk = { | ||
| 185 | .buffersize = 4096, | ||
| 186 | } | ||
| 187 | } | ||
| 188 | }, | ||
| 189 | |||
| 190 | .size_of_priv = sizeof(struct dibusb_state), | ||
| 191 | } | ||
| 192 | }, | ||
| 193 | .size_of_priv = sizeof(struct dibusb_device_state), | ||
| 194 | |||
| 195 | .power_ctrl = dibusb2_0_power_ctrl, | ||
| 196 | .read_mac_address = nova_t_read_mac_address, | ||
| 197 | |||
| 198 | .rc.legacy = { | ||
| 199 | .rc_interval = 100, | ||
| 200 | .rc_map_table = rc_map_haupp_table, | ||
| 201 | .rc_map_size = ARRAY_SIZE(rc_map_haupp_table), | ||
| 202 | .rc_query = nova_t_rc_query, | ||
| 203 | }, | ||
| 204 | |||
| 205 | .i2c_algo = &dibusb_i2c_algo, | ||
| 206 | |||
| 207 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 208 | |||
| 209 | .num_device_descs = 1, | ||
| 210 | .devices = { | ||
| 211 | { "Hauppauge WinTV-NOVA-T usb2", | ||
| 212 | { &nova_t_table[0], NULL }, | ||
| 213 | { &nova_t_table[1], NULL }, | ||
| 214 | }, | ||
| 215 | { NULL }, | ||
| 216 | } | ||
| 217 | }; | ||
| 218 | |||
| 219 | static struct usb_driver nova_t_driver = { | ||
| 220 | .name = "dvb_usb_nova_t_usb2", | ||
| 221 | .probe = nova_t_probe, | ||
| 222 | .disconnect = dvb_usb_device_exit, | ||
| 223 | .id_table = nova_t_table, | ||
| 224 | }; | ||
| 225 | |||
| 226 | /* module stuff */ | ||
| 227 | static int __init nova_t_module_init(void) | ||
| 228 | { | ||
| 229 | int result; | ||
| 230 | if ((result = usb_register(&nova_t_driver))) { | ||
| 231 | err("usb_register failed. Error number %d",result); | ||
| 232 | return result; | ||
| 233 | } | ||
| 234 | |||
| 235 | return 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | static void __exit nova_t_module_exit(void) | ||
| 239 | { | ||
| 240 | /* deregister this driver from the USB subsystem */ | ||
| 241 | usb_deregister(&nova_t_driver); | ||
| 242 | } | ||
| 243 | |||
| 244 | module_init (nova_t_module_init); | ||
| 245 | module_exit (nova_t_module_exit); | ||
| 246 | |||
| 247 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 248 | MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2"); | ||
| 249 | MODULE_VERSION("1.0"); | ||
| 250 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c new file mode 100644 index 00000000000..2e4fab7215f --- /dev/null +++ b/drivers/media/dvb/dvb-usb/opera1.c | |||
| @@ -0,0 +1,595 @@ | |||
| 1 | /* DVB USB framework compliant Linux driver for the Opera1 DVB-S Card | ||
| 2 | * | ||
| 3 | * Copyright (C) 2006 Mario Hlawitschka (dh1pa@amsat.org) | ||
| 4 | * Copyright (C) 2006 Marco Gittler (g.marco@freenet.de) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the Free | ||
| 8 | * Software Foundation, version 2. | ||
| 9 | * | ||
| 10 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 11 | */ | ||
| 12 | |||
| 13 | #define DVB_USB_LOG_PREFIX "opera" | ||
| 14 | |||
| 15 | #include "dvb-usb.h" | ||
| 16 | #include "stv0299.h" | ||
| 17 | |||
| 18 | #define OPERA_READ_MSG 0 | ||
| 19 | #define OPERA_WRITE_MSG 1 | ||
| 20 | #define OPERA_I2C_TUNER 0xd1 | ||
| 21 | |||
| 22 | #define READ_FX2_REG_REQ 0xba | ||
| 23 | #define READ_MAC_ADDR 0x08 | ||
| 24 | #define OPERA_WRITE_FX2 0xbb | ||
| 25 | #define OPERA_TUNER_REQ 0xb1 | ||
| 26 | #define REG_1F_SYMBOLRATE_BYTE0 0x1f | ||
| 27 | #define REG_20_SYMBOLRATE_BYTE1 0x20 | ||
| 28 | #define REG_21_SYMBOLRATE_BYTE2 0x21 | ||
| 29 | |||
| 30 | #define ADDR_B600_VOLTAGE_13V (0x02) | ||
| 31 | #define ADDR_B601_VOLTAGE_18V (0x03) | ||
| 32 | #define ADDR_B1A6_STREAM_CTRL (0x04) | ||
| 33 | #define ADDR_B880_READ_REMOTE (0x05) | ||
| 34 | |||
| 35 | struct opera1_state { | ||
| 36 | u32 last_key_pressed; | ||
| 37 | }; | ||
| 38 | struct rc_map_opera_table { | ||
| 39 | u32 keycode; | ||
| 40 | u32 event; | ||
| 41 | }; | ||
| 42 | |||
| 43 | static int dvb_usb_opera1_debug; | ||
| 44 | module_param_named(debug, dvb_usb_opera1_debug, int, 0644); | ||
| 45 | MODULE_PARM_DESC(debug, | ||
| 46 | "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." | ||
| 47 | DVB_USB_DEBUG_STATUS); | ||
| 48 | |||
| 49 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 50 | |||
| 51 | |||
| 52 | static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value, | ||
| 53 | u8 * data, u16 len, int flags) | ||
| 54 | { | ||
| 55 | int ret; | ||
| 56 | u8 tmp; | ||
| 57 | u8 *buf; | ||
| 58 | unsigned int pipe = (flags == OPERA_READ_MSG) ? | ||
| 59 | usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0); | ||
| 60 | u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; | ||
| 61 | |||
| 62 | buf = kmalloc(len, GFP_KERNEL); | ||
| 63 | if (!buf) | ||
| 64 | return -ENOMEM; | ||
| 65 | |||
| 66 | if (flags == OPERA_WRITE_MSG) | ||
| 67 | memcpy(buf, data, len); | ||
| 68 | ret = usb_control_msg(dev, pipe, request, | ||
| 69 | request_type | USB_TYPE_VENDOR, value, 0x0, | ||
| 70 | buf, len, 2000); | ||
| 71 | |||
| 72 | if (request == OPERA_TUNER_REQ) { | ||
| 73 | tmp = buf[0]; | ||
| 74 | if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
| 75 | OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR, | ||
| 76 | 0x01, 0x0, buf, 1, 2000) < 1 || buf[0] != 0x08) { | ||
| 77 | ret = 0; | ||
| 78 | goto out; | ||
| 79 | } | ||
| 80 | buf[0] = tmp; | ||
| 81 | } | ||
| 82 | if (flags == OPERA_READ_MSG) | ||
| 83 | memcpy(data, buf, len); | ||
| 84 | out: | ||
| 85 | kfree(buf); | ||
| 86 | return ret; | ||
| 87 | } | ||
| 88 | |||
| 89 | /* I2C */ | ||
| 90 | |||
| 91 | static int opera1_usb_i2c_msgxfer(struct dvb_usb_device *dev, u16 addr, | ||
| 92 | u8 * buf, u16 len) | ||
| 93 | { | ||
| 94 | int ret = 0; | ||
| 95 | u8 request; | ||
| 96 | u16 value; | ||
| 97 | |||
| 98 | if (!dev) { | ||
| 99 | info("no usb_device"); | ||
| 100 | return -EINVAL; | ||
| 101 | } | ||
| 102 | if (mutex_lock_interruptible(&dev->usb_mutex) < 0) | ||
| 103 | return -EAGAIN; | ||
| 104 | |||
| 105 | switch (addr>>1){ | ||
| 106 | case ADDR_B600_VOLTAGE_13V: | ||
| 107 | request=0xb6; | ||
| 108 | value=0x00; | ||
| 109 | break; | ||
| 110 | case ADDR_B601_VOLTAGE_18V: | ||
| 111 | request=0xb6; | ||
| 112 | value=0x01; | ||
| 113 | break; | ||
| 114 | case ADDR_B1A6_STREAM_CTRL: | ||
| 115 | request=0xb1; | ||
| 116 | value=0xa6; | ||
| 117 | break; | ||
| 118 | case ADDR_B880_READ_REMOTE: | ||
| 119 | request=0xb8; | ||
| 120 | value=0x80; | ||
| 121 | break; | ||
| 122 | default: | ||
| 123 | request=0xb1; | ||
| 124 | value=addr; | ||
| 125 | } | ||
| 126 | ret = opera1_xilinx_rw(dev->udev, request, | ||
| 127 | value, buf, len, | ||
| 128 | addr&0x01?OPERA_READ_MSG:OPERA_WRITE_MSG); | ||
| 129 | |||
| 130 | mutex_unlock(&dev->usb_mutex); | ||
| 131 | return ret; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
| 135 | int num) | ||
| 136 | { | ||
| 137 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 138 | int i = 0, tmp = 0; | ||
| 139 | |||
| 140 | if (!d) | ||
| 141 | return -ENODEV; | ||
| 142 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 143 | return -EAGAIN; | ||
| 144 | |||
| 145 | for (i = 0; i < num; i++) { | ||
| 146 | if ((tmp = opera1_usb_i2c_msgxfer(d, | ||
| 147 | (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), | ||
| 148 | msg[i].buf, | ||
| 149 | msg[i].len | ||
| 150 | )) != msg[i].len) { | ||
| 151 | break; | ||
| 152 | } | ||
| 153 | if (dvb_usb_opera1_debug & 0x10) | ||
| 154 | info("sending i2c mesage %d %d", tmp, msg[i].len); | ||
| 155 | } | ||
| 156 | mutex_unlock(&d->i2c_mutex); | ||
| 157 | return num; | ||
| 158 | } | ||
| 159 | |||
| 160 | static u32 opera1_i2c_func(struct i2c_adapter *adapter) | ||
| 161 | { | ||
| 162 | return I2C_FUNC_I2C; | ||
| 163 | } | ||
| 164 | |||
| 165 | static struct i2c_algorithm opera1_i2c_algo = { | ||
| 166 | .master_xfer = opera1_i2c_xfer, | ||
| 167 | .functionality = opera1_i2c_func, | ||
| 168 | }; | ||
| 169 | |||
| 170 | static int opera1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
| 171 | { | ||
| 172 | static u8 command_13v[1]={0x00}; | ||
| 173 | static u8 command_18v[1]={0x01}; | ||
| 174 | struct i2c_msg msg[] = { | ||
| 175 | {.addr = ADDR_B600_VOLTAGE_13V,.flags = 0,.buf = command_13v,.len = 1}, | ||
| 176 | }; | ||
| 177 | struct dvb_usb_adapter *udev_adap = | ||
| 178 | (struct dvb_usb_adapter *)(fe->dvb->priv); | ||
| 179 | if (voltage == SEC_VOLTAGE_18) { | ||
| 180 | msg[0].addr = ADDR_B601_VOLTAGE_18V; | ||
| 181 | msg[0].buf = command_18v; | ||
| 182 | } | ||
| 183 | i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); | ||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, | ||
| 188 | u32 ratio) | ||
| 189 | { | ||
| 190 | stv0299_writereg(fe, 0x13, 0x98); | ||
| 191 | stv0299_writereg(fe, 0x14, 0x95); | ||
| 192 | stv0299_writereg(fe, REG_1F_SYMBOLRATE_BYTE0, (ratio >> 16) & 0xff); | ||
| 193 | stv0299_writereg(fe, REG_20_SYMBOLRATE_BYTE1, (ratio >> 8) & 0xff); | ||
| 194 | stv0299_writereg(fe, REG_21_SYMBOLRATE_BYTE2, (ratio) & 0xf0); | ||
| 195 | return 0; | ||
| 196 | |||
| 197 | } | ||
| 198 | static u8 opera1_inittab[] = { | ||
| 199 | 0x00, 0xa1, | ||
| 200 | 0x01, 0x15, | ||
| 201 | 0x02, 0x30, | ||
| 202 | 0x03, 0x00, | ||
| 203 | 0x04, 0x7d, | ||
| 204 | 0x05, 0x05, | ||
| 205 | 0x06, 0x02, | ||
| 206 | 0x07, 0x00, | ||
| 207 | 0x0b, 0x00, | ||
| 208 | 0x0c, 0x01, | ||
| 209 | 0x0d, 0x81, | ||
| 210 | 0x0e, 0x44, | ||
| 211 | 0x0f, 0x19, | ||
| 212 | 0x10, 0x3f, | ||
| 213 | 0x11, 0x84, | ||
| 214 | 0x12, 0xda, | ||
| 215 | 0x13, 0x98, | ||
| 216 | 0x14, 0x95, | ||
| 217 | 0x15, 0xc9, | ||
| 218 | 0x16, 0xeb, | ||
| 219 | 0x17, 0x00, | ||
| 220 | 0x18, 0x19, | ||
| 221 | 0x19, 0x8b, | ||
| 222 | 0x1a, 0x00, | ||
| 223 | 0x1b, 0x82, | ||
| 224 | 0x1c, 0x7f, | ||
| 225 | 0x1d, 0x00, | ||
| 226 | 0x1e, 0x00, | ||
| 227 | REG_1F_SYMBOLRATE_BYTE0, 0x06, | ||
| 228 | REG_20_SYMBOLRATE_BYTE1, 0x50, | ||
| 229 | REG_21_SYMBOLRATE_BYTE2, 0x10, | ||
| 230 | 0x22, 0x00, | ||
| 231 | 0x23, 0x00, | ||
| 232 | 0x24, 0x37, | ||
| 233 | 0x25, 0xbc, | ||
| 234 | 0x26, 0x00, | ||
| 235 | 0x27, 0x00, | ||
| 236 | 0x28, 0x00, | ||
| 237 | 0x29, 0x1e, | ||
| 238 | 0x2a, 0x14, | ||
| 239 | 0x2b, 0x1f, | ||
| 240 | 0x2c, 0x09, | ||
| 241 | 0x2d, 0x0a, | ||
| 242 | 0x2e, 0x00, | ||
| 243 | 0x2f, 0x00, | ||
| 244 | 0x30, 0x00, | ||
| 245 | 0x31, 0x1f, | ||
| 246 | 0x32, 0x19, | ||
| 247 | 0x33, 0xfc, | ||
| 248 | 0x34, 0x13, | ||
| 249 | 0xff, 0xff, | ||
| 250 | }; | ||
| 251 | |||
| 252 | static struct stv0299_config opera1_stv0299_config = { | ||
| 253 | .demod_address = 0xd0>>1, | ||
| 254 | .min_delay_ms = 100, | ||
| 255 | .mclk = 88000000UL, | ||
| 256 | .invert = 1, | ||
| 257 | .skip_reinit = 0, | ||
| 258 | .lock_output = STV0299_LOCKOUTPUT_0, | ||
| 259 | .volt13_op0_op1 = STV0299_VOLT13_OP0, | ||
| 260 | .inittab = opera1_inittab, | ||
| 261 | .set_symbol_rate = opera1_stv0299_set_symbol_rate, | ||
| 262 | }; | ||
| 263 | |||
| 264 | static int opera1_frontend_attach(struct dvb_usb_adapter *d) | ||
| 265 | { | ||
| 266 | if ((d->fe = | ||
| 267 | dvb_attach(stv0299_attach, &opera1_stv0299_config, | ||
| 268 | &d->dev->i2c_adap)) != NULL) { | ||
| 269 | d->fe->ops.set_voltage = opera1_set_voltage; | ||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | info("not attached stv0299"); | ||
| 273 | return -EIO; | ||
| 274 | } | ||
| 275 | |||
| 276 | static int opera1_tuner_attach(struct dvb_usb_adapter *adap) | ||
| 277 | { | ||
| 278 | dvb_attach( | ||
| 279 | dvb_pll_attach, adap->fe, 0xc0>>1, | ||
| 280 | &adap->dev->i2c_adap, DVB_PLL_OPERA1 | ||
| 281 | ); | ||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | static int opera1_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 286 | { | ||
| 287 | u8 val = onoff ? 0x01 : 0x00; | ||
| 288 | |||
| 289 | if (dvb_usb_opera1_debug) | ||
| 290 | info("power %s", onoff ? "on" : "off"); | ||
| 291 | return opera1_xilinx_rw(d->udev, 0xb7, val, | ||
| 292 | &val, 1, OPERA_WRITE_MSG); | ||
| 293 | } | ||
| 294 | |||
| 295 | static int opera1_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 296 | { | ||
| 297 | static u8 buf_start[2] = { 0xff, 0x03 }; | ||
| 298 | static u8 buf_stop[2] = { 0xff, 0x00 }; | ||
| 299 | struct i2c_msg start_tuner[] = { | ||
| 300 | {.addr = ADDR_B1A6_STREAM_CTRL,.buf = onoff ? buf_start : buf_stop,.len = 2}, | ||
| 301 | }; | ||
| 302 | if (dvb_usb_opera1_debug) | ||
| 303 | info("streaming %s", onoff ? "on" : "off"); | ||
| 304 | i2c_transfer(&adap->dev->i2c_adap, start_tuner, 1); | ||
| 305 | return 0; | ||
| 306 | } | ||
| 307 | |||
| 308 | static int opera1_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | ||
| 309 | int onoff) | ||
| 310 | { | ||
| 311 | u8 b_pid[3]; | ||
| 312 | struct i2c_msg msg[] = { | ||
| 313 | {.addr = ADDR_B1A6_STREAM_CTRL,.buf = b_pid,.len = 3}, | ||
| 314 | }; | ||
| 315 | if (dvb_usb_opera1_debug) | ||
| 316 | info("pidfilter index: %d pid: %d %s", index, pid, | ||
| 317 | onoff ? "on" : "off"); | ||
| 318 | b_pid[0] = (2 * index) + 4; | ||
| 319 | b_pid[1] = onoff ? (pid & 0xff) : (0x00); | ||
| 320 | b_pid[2] = onoff ? ((pid >> 8) & 0xff) : (0x00); | ||
| 321 | i2c_transfer(&adap->dev->i2c_adap, msg, 1); | ||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff) | ||
| 326 | { | ||
| 327 | int u = 0x04; | ||
| 328 | u8 b_pid[3]; | ||
| 329 | struct i2c_msg msg[] = { | ||
| 330 | {.addr = ADDR_B1A6_STREAM_CTRL,.buf = b_pid,.len = 3}, | ||
| 331 | }; | ||
| 332 | if (dvb_usb_opera1_debug) | ||
| 333 | info("%s hw-pidfilter", onoff ? "enable" : "disable"); | ||
| 334 | for (; u < 0x7e; u += 2) { | ||
| 335 | b_pid[0] = u; | ||
| 336 | b_pid[1] = 0; | ||
| 337 | b_pid[2] = 0x80; | ||
| 338 | i2c_transfer(&adap->dev->i2c_adap, msg, 1); | ||
| 339 | } | ||
| 340 | return 0; | ||
| 341 | } | ||
| 342 | |||
| 343 | static struct rc_map_table rc_map_opera1_table[] = { | ||
| 344 | {0x5fa0, KEY_1}, | ||
| 345 | {0x51af, KEY_2}, | ||
| 346 | {0x5da2, KEY_3}, | ||
| 347 | {0x41be, KEY_4}, | ||
| 348 | {0x0bf5, KEY_5}, | ||
| 349 | {0x43bd, KEY_6}, | ||
| 350 | {0x47b8, KEY_7}, | ||
| 351 | {0x49b6, KEY_8}, | ||
| 352 | {0x05fa, KEY_9}, | ||
| 353 | {0x45ba, KEY_0}, | ||
| 354 | {0x09f6, KEY_CHANNELUP}, /*chanup */ | ||
| 355 | {0x1be5, KEY_CHANNELDOWN}, /*chandown */ | ||
| 356 | {0x5da3, KEY_VOLUMEDOWN}, /*voldown */ | ||
| 357 | {0x5fa1, KEY_VOLUMEUP}, /*volup */ | ||
| 358 | {0x07f8, KEY_SPACE}, /*tab */ | ||
| 359 | {0x1fe1, KEY_OK}, /*play ok */ | ||
| 360 | {0x1be4, KEY_ZOOM}, /*zoom */ | ||
| 361 | {0x59a6, KEY_MUTE}, /*mute */ | ||
| 362 | {0x5ba5, KEY_RADIO}, /*tv/f */ | ||
| 363 | {0x19e7, KEY_RECORD}, /*rec */ | ||
| 364 | {0x01fe, KEY_STOP}, /*Stop */ | ||
| 365 | {0x03fd, KEY_PAUSE}, /*pause */ | ||
| 366 | {0x03fc, KEY_SCREEN}, /*<- -> */ | ||
| 367 | {0x07f9, KEY_CAMERA}, /*capture */ | ||
| 368 | {0x47b9, KEY_ESC}, /*exit */ | ||
| 369 | {0x43bc, KEY_POWER2}, /*power */ | ||
| 370 | }; | ||
| 371 | |||
| 372 | static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state) | ||
| 373 | { | ||
| 374 | struct opera1_state *opst = dev->priv; | ||
| 375 | u8 rcbuffer[32]; | ||
| 376 | const u16 startmarker1 = 0x10ed; | ||
| 377 | const u16 startmarker2 = 0x11ec; | ||
| 378 | struct i2c_msg read_remote[] = { | ||
| 379 | {.addr = ADDR_B880_READ_REMOTE,.buf = rcbuffer,.flags = I2C_M_RD,.len = 32}, | ||
| 380 | }; | ||
| 381 | int i = 0; | ||
| 382 | u32 send_key = 0; | ||
| 383 | |||
| 384 | if (i2c_transfer(&dev->i2c_adap, read_remote, 1) == 1) { | ||
| 385 | for (i = 0; i < 32; i++) { | ||
| 386 | if (rcbuffer[i]) | ||
| 387 | send_key |= 1; | ||
| 388 | if (i < 31) | ||
| 389 | send_key = send_key << 1; | ||
| 390 | } | ||
| 391 | if (send_key & 0x8000) | ||
| 392 | send_key = (send_key << 1) | (send_key >> 15 & 0x01); | ||
| 393 | |||
| 394 | if (send_key == 0xffff && opst->last_key_pressed != 0) { | ||
| 395 | *state = REMOTE_KEY_REPEAT; | ||
| 396 | *event = opst->last_key_pressed; | ||
| 397 | return 0; | ||
| 398 | } | ||
| 399 | for (; send_key != 0;) { | ||
| 400 | if (send_key >> 16 == startmarker2) { | ||
| 401 | break; | ||
| 402 | } else if (send_key >> 16 == startmarker1) { | ||
| 403 | send_key = | ||
| 404 | (send_key & 0xfffeffff) | (startmarker1 << 16); | ||
| 405 | break; | ||
| 406 | } else | ||
| 407 | send_key >>= 1; | ||
| 408 | } | ||
| 409 | |||
| 410 | if (send_key == 0) | ||
| 411 | return 0; | ||
| 412 | |||
| 413 | send_key = (send_key & 0xffff) | 0x0100; | ||
| 414 | |||
| 415 | for (i = 0; i < ARRAY_SIZE(rc_map_opera1_table); i++) { | ||
| 416 | if (rc5_scan(&rc_map_opera1_table[i]) == (send_key & 0xffff)) { | ||
| 417 | *state = REMOTE_KEY_PRESSED; | ||
| 418 | *event = rc_map_opera1_table[i].keycode; | ||
| 419 | opst->last_key_pressed = | ||
| 420 | rc_map_opera1_table[i].keycode; | ||
| 421 | break; | ||
| 422 | } | ||
| 423 | opst->last_key_pressed = 0; | ||
| 424 | } | ||
| 425 | } else | ||
| 426 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | static struct usb_device_id opera1_table[] = { | ||
| 431 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_OPERA1_COLD)}, | ||
| 432 | {USB_DEVICE(USB_VID_OPERA1, USB_PID_OPERA1_WARM)}, | ||
| 433 | {} | ||
| 434 | }; | ||
| 435 | |||
| 436 | MODULE_DEVICE_TABLE(usb, opera1_table); | ||
| 437 | |||
| 438 | static int opera1_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | ||
| 439 | { | ||
| 440 | u8 command[] = { READ_MAC_ADDR }; | ||
| 441 | opera1_xilinx_rw(d->udev, 0xb1, 0xa0, command, 1, OPERA_WRITE_MSG); | ||
| 442 | opera1_xilinx_rw(d->udev, 0xb1, 0xa1, mac, 6, OPERA_READ_MSG); | ||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | static int opera1_xilinx_load_firmware(struct usb_device *dev, | ||
| 446 | const char *filename) | ||
| 447 | { | ||
| 448 | const struct firmware *fw = NULL; | ||
| 449 | u8 *b, *p; | ||
| 450 | int ret = 0, i,fpgasize=40; | ||
| 451 | u8 testval; | ||
| 452 | info("start downloading fpga firmware %s",filename); | ||
| 453 | |||
| 454 | if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) { | ||
| 455 | err("did not find the firmware file. (%s) " | ||
| 456 | "Please see linux/Documentation/dvb/ for more details on firmware-problems.", | ||
| 457 | filename); | ||
| 458 | return ret; | ||
| 459 | } else { | ||
| 460 | p = kmalloc(fw->size, GFP_KERNEL); | ||
| 461 | opera1_xilinx_rw(dev, 0xbc, 0x00, &testval, 1, OPERA_READ_MSG); | ||
| 462 | if (p != NULL && testval != 0x67) { | ||
| 463 | |||
| 464 | u8 reset = 0, fpga_command = 0; | ||
| 465 | memcpy(p, fw->data, fw->size); | ||
| 466 | /* clear fpga ? */ | ||
| 467 | opera1_xilinx_rw(dev, 0xbc, 0xaa, &fpga_command, 1, | ||
| 468 | OPERA_WRITE_MSG); | ||
| 469 | for (i = 0; i < fw->size;) { | ||
| 470 | if ( (fw->size - i) <fpgasize){ | ||
| 471 | fpgasize=fw->size-i; | ||
| 472 | } | ||
| 473 | b = (u8 *) p + i; | ||
| 474 | if (opera1_xilinx_rw | ||
| 475 | (dev, OPERA_WRITE_FX2, 0x0, b , fpgasize, | ||
| 476 | OPERA_WRITE_MSG) != fpgasize | ||
| 477 | ) { | ||
| 478 | err("error while transferring firmware"); | ||
| 479 | ret = -EINVAL; | ||
| 480 | break; | ||
| 481 | } | ||
| 482 | i = i + fpgasize; | ||
| 483 | } | ||
| 484 | /* restart the CPU */ | ||
| 485 | if (ret || opera1_xilinx_rw | ||
| 486 | (dev, 0xa0, 0xe600, &reset, 1, | ||
| 487 | OPERA_WRITE_MSG) != 1) { | ||
| 488 | err("could not restart the USB controller CPU."); | ||
| 489 | ret = -EINVAL; | ||
| 490 | } | ||
| 491 | } | ||
| 492 | } | ||
| 493 | kfree(p); | ||
| 494 | release_firmware(fw); | ||
| 495 | return ret; | ||
| 496 | } | ||
| 497 | |||
| 498 | static struct dvb_usb_device_properties opera1_properties = { | ||
| 499 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 500 | .usb_ctrl = CYPRESS_FX2, | ||
| 501 | .firmware = "dvb-usb-opera-01.fw", | ||
| 502 | .size_of_priv = sizeof(struct opera1_state), | ||
| 503 | |||
| 504 | .power_ctrl = opera1_power_ctrl, | ||
| 505 | .i2c_algo = &opera1_i2c_algo, | ||
| 506 | |||
| 507 | .rc.legacy = { | ||
| 508 | .rc_map_table = rc_map_opera1_table, | ||
| 509 | .rc_map_size = ARRAY_SIZE(rc_map_opera1_table), | ||
| 510 | .rc_interval = 200, | ||
| 511 | .rc_query = opera1_rc_query, | ||
| 512 | }, | ||
| 513 | .read_mac_address = opera1_read_mac_address, | ||
| 514 | .generic_bulk_ctrl_endpoint = 0x00, | ||
| 515 | /* parameter for the MPEG2-data transfer */ | ||
| 516 | .num_adapters = 1, | ||
| 517 | .adapter = { | ||
| 518 | { | ||
| 519 | .frontend_attach = opera1_frontend_attach, | ||
| 520 | .streaming_ctrl = opera1_streaming_ctrl, | ||
| 521 | .tuner_attach = opera1_tuner_attach, | ||
| 522 | .caps = | ||
| 523 | DVB_USB_ADAP_HAS_PID_FILTER | | ||
| 524 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
| 525 | .pid_filter = opera1_pid_filter, | ||
| 526 | .pid_filter_ctrl = opera1_pid_filter_control, | ||
| 527 | .pid_filter_count = 252, | ||
| 528 | .stream = { | ||
| 529 | .type = USB_BULK, | ||
| 530 | .count = 10, | ||
| 531 | .endpoint = 0x82, | ||
| 532 | .u = { | ||
| 533 | .bulk = { | ||
| 534 | .buffersize = 4096, | ||
| 535 | } | ||
| 536 | } | ||
| 537 | }, | ||
| 538 | } | ||
| 539 | }, | ||
| 540 | .num_device_descs = 1, | ||
| 541 | .devices = { | ||
| 542 | {"Opera1 DVB-S USB2.0", | ||
| 543 | {&opera1_table[0], NULL}, | ||
| 544 | {&opera1_table[1], NULL}, | ||
| 545 | }, | ||
| 546 | } | ||
| 547 | }; | ||
| 548 | |||
| 549 | static int opera1_probe(struct usb_interface *intf, | ||
| 550 | const struct usb_device_id *id) | ||
| 551 | { | ||
| 552 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 553 | |||
| 554 | if (udev->descriptor.idProduct == USB_PID_OPERA1_WARM && | ||
| 555 | udev->descriptor.idVendor == USB_VID_OPERA1 && | ||
| 556 | opera1_xilinx_load_firmware(udev, "dvb-usb-opera1-fpga-01.fw") != 0 | ||
| 557 | ) { | ||
| 558 | return -EINVAL; | ||
| 559 | } | ||
| 560 | |||
| 561 | if (0 != dvb_usb_device_init(intf, &opera1_properties, | ||
| 562 | THIS_MODULE, NULL, adapter_nr)) | ||
| 563 | return -EINVAL; | ||
| 564 | return 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | static struct usb_driver opera1_driver = { | ||
| 568 | .name = "opera1", | ||
| 569 | .probe = opera1_probe, | ||
| 570 | .disconnect = dvb_usb_device_exit, | ||
| 571 | .id_table = opera1_table, | ||
| 572 | }; | ||
| 573 | |||
| 574 | static int __init opera1_module_init(void) | ||
| 575 | { | ||
| 576 | int result = 0; | ||
| 577 | if ((result = usb_register(&opera1_driver))) { | ||
| 578 | err("usb_register failed. Error number %d", result); | ||
| 579 | } | ||
| 580 | return result; | ||
| 581 | } | ||
| 582 | |||
| 583 | static void __exit opera1_module_exit(void) | ||
| 584 | { | ||
| 585 | usb_deregister(&opera1_driver); | ||
| 586 | } | ||
| 587 | |||
| 588 | module_init(opera1_module_init); | ||
| 589 | module_exit(opera1_module_exit); | ||
| 590 | |||
| 591 | MODULE_AUTHOR("Mario Hlawitschka (c) dh1pa@amsat.org"); | ||
| 592 | MODULE_AUTHOR("Marco Gittler (c) g.marco@freenet.de"); | ||
| 593 | MODULE_DESCRIPTION("Driver for Opera1 DVB-S device"); | ||
| 594 | MODULE_VERSION("0.1"); | ||
| 595 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/technisat-usb2.c b/drivers/media/dvb/dvb-usb/technisat-usb2.c new file mode 100644 index 00000000000..473b95ed4d5 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/technisat-usb2.c | |||
| @@ -0,0 +1,805 @@ | |||
| 1 | /* | ||
| 2 | * Linux driver for Technisat DVB-S/S2 USB 2.0 device | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Patrick Boettcher, | ||
| 5 | * Kernel Labs Inc. PO Box 745, St James, NY 11780 | ||
| 6 | * | ||
| 7 | * Development was sponsored by Technisat Digital UK Limited, whose | ||
| 8 | * registered office is Witan Gate House 500 - 600 Witan Gate West, | ||
| 9 | * Milton Keynes, MK9 1SH | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or | ||
| 12 | * modify it under the terms of the GNU General Public License as | ||
| 13 | * published by the Free Software Foundation; either version 2 of the | ||
| 14 | * License, or (at your option) any later version. | ||
| 15 | * | ||
| 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 | * THIS PROGRAM IS PROVIDED "AS IS" AND BOTH THE COPYRIGHT HOLDER AND | ||
| 22 | * TECHNISAT DIGITAL UK LTD DISCLAIM ALL WARRANTIES WITH REGARD TO | ||
| 23 | * THIS PROGRAM INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY OR | ||
| 24 | * FITNESS FOR A PARTICULAR PURPOSE. NEITHER THE COPYRIGHT HOLDER | ||
| 25 | * NOR TECHNISAT DIGITAL UK LIMITED SHALL BE LIABLE FOR ANY SPECIAL, | ||
| 26 | * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER | ||
| 27 | * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 28 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR | ||
| 29 | * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS PROGRAM. See the | ||
| 30 | * GNU General Public License for more details. | ||
| 31 | */ | ||
| 32 | |||
| 33 | #define DVB_USB_LOG_PREFIX "technisat-usb2" | ||
| 34 | #include "dvb-usb.h" | ||
| 35 | |||
| 36 | #include "stv6110x.h" | ||
| 37 | #include "stv090x.h" | ||
| 38 | |||
| 39 | /* module parameters */ | ||
| 40 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 41 | |||
| 42 | static int debug; | ||
| 43 | module_param(debug, int, 0644); | ||
| 44 | MODULE_PARM_DESC(debug, | ||
| 45 | "set debugging level (bit-mask: 1=info,2=eeprom,4=i2c,8=rc)." \ | ||
| 46 | DVB_USB_DEBUG_STATUS); | ||
| 47 | |||
| 48 | /* disables all LED control command and | ||
| 49 | * also does not start the signal polling thread */ | ||
| 50 | static int disable_led_control; | ||
| 51 | module_param(disable_led_control, int, 0444); | ||
| 52 | MODULE_PARM_DESC(disable_led_control, | ||
| 53 | "disable LED control of the device " | ||
| 54 | "(default: 0 - LED control is active)."); | ||
| 55 | |||
| 56 | /* device private data */ | ||
| 57 | struct technisat_usb2_state { | ||
| 58 | struct dvb_usb_device *dev; | ||
| 59 | struct delayed_work green_led_work; | ||
| 60 | u8 power_state; | ||
| 61 | |||
| 62 | u16 last_scan_code; | ||
| 63 | }; | ||
| 64 | |||
| 65 | /* debug print helpers */ | ||
| 66 | #define deb_info(args...) dprintk(debug, 0x01, args) | ||
| 67 | #define deb_eeprom(args...) dprintk(debug, 0x02, args) | ||
| 68 | #define deb_i2c(args...) dprintk(debug, 0x04, args) | ||
| 69 | #define deb_rc(args...) dprintk(debug, 0x08, args) | ||
| 70 | |||
| 71 | /* vendor requests */ | ||
| 72 | #define SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST 0xB3 | ||
| 73 | #define SET_FRONT_END_RESET_VENDOR_REQUEST 0xB4 | ||
| 74 | #define GET_VERSION_INFO_VENDOR_REQUEST 0xB5 | ||
| 75 | #define SET_GREEN_LED_VENDOR_REQUEST 0xB6 | ||
| 76 | #define SET_RED_LED_VENDOR_REQUEST 0xB7 | ||
| 77 | #define GET_IR_DATA_VENDOR_REQUEST 0xB8 | ||
| 78 | #define SET_LED_TIMER_DIVIDER_VENDOR_REQUEST 0xB9 | ||
| 79 | #define SET_USB_REENUMERATION 0xBA | ||
| 80 | |||
| 81 | /* i2c-access methods */ | ||
| 82 | #define I2C_SPEED_100KHZ_BIT 0x40 | ||
| 83 | |||
| 84 | #define I2C_STATUS_NAK 7 | ||
| 85 | #define I2C_STATUS_OK 8 | ||
| 86 | |||
| 87 | static int technisat_usb2_i2c_access(struct usb_device *udev, | ||
| 88 | u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen) | ||
| 89 | { | ||
| 90 | u8 b[64]; | ||
| 91 | int ret, actual_length; | ||
| 92 | |||
| 93 | deb_i2c("i2c-access: %02x, tx: ", device_addr); | ||
| 94 | debug_dump(tx, txlen, deb_i2c); | ||
| 95 | deb_i2c(" "); | ||
| 96 | |||
| 97 | if (txlen > 62) { | ||
| 98 | err("i2c TX buffer can't exceed 62 bytes (dev 0x%02x)", | ||
| 99 | device_addr); | ||
| 100 | txlen = 62; | ||
| 101 | } | ||
| 102 | if (rxlen > 62) { | ||
| 103 | err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)", | ||
| 104 | device_addr); | ||
| 105 | txlen = 62; | ||
| 106 | } | ||
| 107 | |||
| 108 | b[0] = I2C_SPEED_100KHZ_BIT; | ||
| 109 | b[1] = device_addr << 1; | ||
| 110 | |||
| 111 | if (rx != NULL) { | ||
| 112 | b[0] |= rxlen; | ||
| 113 | b[1] |= 1; | ||
| 114 | } | ||
| 115 | |||
| 116 | memcpy(&b[2], tx, txlen); | ||
| 117 | ret = usb_bulk_msg(udev, | ||
| 118 | usb_sndbulkpipe(udev, 0x01), | ||
| 119 | b, 2 + txlen, | ||
| 120 | NULL, 1000); | ||
| 121 | |||
| 122 | if (ret < 0) { | ||
| 123 | err("i2c-error: out failed %02x = %d", device_addr, ret); | ||
| 124 | return -ENODEV; | ||
| 125 | } | ||
| 126 | |||
| 127 | ret = usb_bulk_msg(udev, | ||
| 128 | usb_rcvbulkpipe(udev, 0x01), | ||
| 129 | b, 64, &actual_length, 1000); | ||
| 130 | if (ret < 0) { | ||
| 131 | err("i2c-error: in failed %02x = %d", device_addr, ret); | ||
| 132 | return -ENODEV; | ||
| 133 | } | ||
| 134 | |||
| 135 | if (b[0] != I2C_STATUS_OK) { | ||
| 136 | err("i2c-error: %02x = %d", device_addr, b[0]); | ||
| 137 | /* handle tuner-i2c-nak */ | ||
| 138 | if (!(b[0] == I2C_STATUS_NAK && | ||
| 139 | device_addr == 0x60 | ||
| 140 | /* && device_is_technisat_usb2 */)) | ||
| 141 | return -ENODEV; | ||
| 142 | } | ||
| 143 | |||
| 144 | deb_i2c("status: %d, ", b[0]); | ||
| 145 | |||
| 146 | if (rx != NULL) { | ||
| 147 | memcpy(rx, &b[2], rxlen); | ||
| 148 | |||
| 149 | deb_i2c("rx (%d): ", rxlen); | ||
| 150 | debug_dump(rx, rxlen, deb_i2c); | ||
| 151 | } | ||
| 152 | |||
| 153 | deb_i2c("\n"); | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | ||
| 159 | int num) | ||
| 160 | { | ||
| 161 | int ret = 0, i; | ||
| 162 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 163 | |||
| 164 | /* Ensure nobody else hits the i2c bus while we're sending our | ||
| 165 | sequence of messages, (such as the remote control thread) */ | ||
| 166 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 167 | return -EAGAIN; | ||
| 168 | |||
| 169 | for (i = 0; i < num; i++) { | ||
| 170 | if (i+1 < num && msg[i+1].flags & I2C_M_RD) { | ||
| 171 | ret = technisat_usb2_i2c_access(d->udev, msg[i+1].addr, | ||
| 172 | msg[i].buf, msg[i].len, | ||
| 173 | msg[i+1].buf, msg[i+1].len); | ||
| 174 | if (ret != 0) | ||
| 175 | break; | ||
| 176 | i++; | ||
| 177 | } else { | ||
| 178 | ret = technisat_usb2_i2c_access(d->udev, msg[i].addr, | ||
| 179 | msg[i].buf, msg[i].len, | ||
| 180 | NULL, 0); | ||
| 181 | if (ret != 0) | ||
| 182 | break; | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | if (ret == 0) | ||
| 187 | ret = i; | ||
| 188 | |||
| 189 | mutex_unlock(&d->i2c_mutex); | ||
| 190 | |||
| 191 | return ret; | ||
| 192 | } | ||
| 193 | |||
| 194 | static u32 technisat_usb2_i2c_func(struct i2c_adapter *adapter) | ||
| 195 | { | ||
| 196 | return I2C_FUNC_I2C; | ||
| 197 | } | ||
| 198 | |||
| 199 | static struct i2c_algorithm technisat_usb2_i2c_algo = { | ||
| 200 | .master_xfer = technisat_usb2_i2c_xfer, | ||
| 201 | .functionality = technisat_usb2_i2c_func, | ||
| 202 | }; | ||
| 203 | |||
| 204 | #if 0 | ||
| 205 | static void technisat_usb2_frontend_reset(struct usb_device *udev) | ||
| 206 | { | ||
| 207 | usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 208 | SET_FRONT_END_RESET_VENDOR_REQUEST, | ||
| 209 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 210 | 10, 0, | ||
| 211 | NULL, 0, 500); | ||
| 212 | } | ||
| 213 | #endif | ||
| 214 | |||
| 215 | /* LED control */ | ||
| 216 | enum technisat_usb2_led_state { | ||
| 217 | LED_OFF, | ||
| 218 | LED_BLINK, | ||
| 219 | LED_ON, | ||
| 220 | LED_UNDEFINED | ||
| 221 | }; | ||
| 222 | |||
| 223 | static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum technisat_usb2_led_state state) | ||
| 224 | { | ||
| 225 | int ret; | ||
| 226 | |||
| 227 | u8 led[8] = { | ||
| 228 | red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST, | ||
| 229 | 0 | ||
| 230 | }; | ||
| 231 | |||
| 232 | if (disable_led_control && state != LED_OFF) | ||
| 233 | return 0; | ||
| 234 | |||
| 235 | switch (state) { | ||
| 236 | case LED_ON: | ||
| 237 | led[1] = 0x82; | ||
| 238 | break; | ||
| 239 | case LED_BLINK: | ||
| 240 | led[1] = 0x82; | ||
| 241 | if (red) { | ||
| 242 | led[2] = 0x02; | ||
| 243 | led[3] = 10; | ||
| 244 | led[4] = 10; | ||
| 245 | } else { | ||
| 246 | led[2] = 0xff; | ||
| 247 | led[3] = 50; | ||
| 248 | led[4] = 50; | ||
| 249 | } | ||
| 250 | led[5] = 1; | ||
| 251 | break; | ||
| 252 | |||
| 253 | default: | ||
| 254 | case LED_OFF: | ||
| 255 | led[1] = 0x80; | ||
| 256 | break; | ||
| 257 | } | ||
| 258 | |||
| 259 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 260 | return -EAGAIN; | ||
| 261 | |||
| 262 | ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), | ||
| 263 | red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST, | ||
| 264 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 265 | 0, 0, | ||
| 266 | led, sizeof(led), 500); | ||
| 267 | |||
| 268 | mutex_unlock(&d->i2c_mutex); | ||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | |||
| 272 | static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 green) | ||
| 273 | { | ||
| 274 | int ret; | ||
| 275 | u8 b = 0; | ||
| 276 | |||
| 277 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 278 | return -EAGAIN; | ||
| 279 | |||
| 280 | ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), | ||
| 281 | SET_LED_TIMER_DIVIDER_VENDOR_REQUEST, | ||
| 282 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 283 | (red << 8) | green, 0, | ||
| 284 | &b, 1, 500); | ||
| 285 | |||
| 286 | mutex_unlock(&d->i2c_mutex); | ||
| 287 | |||
| 288 | return ret; | ||
| 289 | } | ||
| 290 | |||
| 291 | static void technisat_usb2_green_led_control(struct work_struct *work) | ||
| 292 | { | ||
| 293 | struct technisat_usb2_state *state = | ||
| 294 | container_of(work, struct technisat_usb2_state, green_led_work.work); | ||
| 295 | struct dvb_frontend *fe = state->dev->adapter[0].fe; | ||
| 296 | |||
| 297 | if (state->power_state == 0) | ||
| 298 | goto schedule; | ||
| 299 | |||
| 300 | if (fe != NULL) { | ||
| 301 | enum fe_status status; | ||
| 302 | |||
| 303 | if (fe->ops.read_status(fe, &status) != 0) | ||
| 304 | goto schedule; | ||
| 305 | |||
| 306 | if (status & FE_HAS_LOCK) { | ||
| 307 | u32 ber; | ||
| 308 | |||
| 309 | if (fe->ops.read_ber(fe, &ber) != 0) | ||
| 310 | goto schedule; | ||
| 311 | |||
| 312 | if (ber > 1000) | ||
| 313 | technisat_usb2_set_led(state->dev, 0, LED_BLINK); | ||
| 314 | else | ||
| 315 | technisat_usb2_set_led(state->dev, 0, LED_ON); | ||
| 316 | } else | ||
| 317 | technisat_usb2_set_led(state->dev, 0, LED_OFF); | ||
| 318 | } | ||
| 319 | |||
| 320 | schedule: | ||
| 321 | schedule_delayed_work(&state->green_led_work, | ||
| 322 | msecs_to_jiffies(500)); | ||
| 323 | } | ||
| 324 | |||
| 325 | /* method to find out whether the firmware has to be downloaded or not */ | ||
| 326 | static int technisat_usb2_identify_state(struct usb_device *udev, | ||
| 327 | struct dvb_usb_device_properties *props, | ||
| 328 | struct dvb_usb_device_description **desc, int *cold) | ||
| 329 | { | ||
| 330 | int ret; | ||
| 331 | u8 version[3]; | ||
| 332 | |||
| 333 | /* first select the interface */ | ||
| 334 | if (usb_set_interface(udev, 0, 1) != 0) | ||
| 335 | err("could not set alternate setting to 0"); | ||
| 336 | else | ||
| 337 | info("set alternate setting"); | ||
| 338 | |||
| 339 | *cold = 0; /* by default do not download a firmware - just in case something is wrong */ | ||
| 340 | |||
| 341 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 342 | GET_VERSION_INFO_VENDOR_REQUEST, | ||
| 343 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
| 344 | 0, 0, | ||
| 345 | version, sizeof(version), 500); | ||
| 346 | |||
| 347 | if (ret < 0) | ||
| 348 | *cold = 1; | ||
| 349 | else { | ||
| 350 | info("firmware version: %d.%d", version[1], version[2]); | ||
| 351 | *cold = 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | /* power control */ | ||
| 358 | static int technisat_usb2_power_ctrl(struct dvb_usb_device *d, int level) | ||
| 359 | { | ||
| 360 | struct technisat_usb2_state *state = d->priv; | ||
| 361 | |||
| 362 | state->power_state = level; | ||
| 363 | |||
| 364 | if (disable_led_control) | ||
| 365 | return 0; | ||
| 366 | |||
| 367 | /* green led is turned off in any case - will be turned on when tuning */ | ||
| 368 | technisat_usb2_set_led(d, 0, LED_OFF); | ||
| 369 | /* red led is turned on all the time */ | ||
| 370 | technisat_usb2_set_led(d, 1, LED_ON); | ||
| 371 | return 0; | ||
| 372 | } | ||
| 373 | |||
| 374 | /* mac address reading - from the eeprom */ | ||
| 375 | #if 0 | ||
| 376 | static void technisat_usb2_eeprom_dump(struct dvb_usb_device *d) | ||
| 377 | { | ||
| 378 | u8 reg; | ||
| 379 | u8 b[16]; | ||
| 380 | int i, j; | ||
| 381 | |||
| 382 | /* full EEPROM dump */ | ||
| 383 | for (j = 0; j < 256 * 4; j += 16) { | ||
| 384 | reg = j; | ||
| 385 | if (technisat_usb2_i2c_access(d->udev, 0x50 + j / 256, ®, 1, b, 16) != 0) | ||
| 386 | break; | ||
| 387 | |||
| 388 | deb_eeprom("EEPROM: %01x%02x: ", j / 256, reg); | ||
| 389 | for (i = 0; i < 16; i++) | ||
| 390 | deb_eeprom("%02x ", b[i]); | ||
| 391 | deb_eeprom("\n"); | ||
| 392 | } | ||
| 393 | } | ||
| 394 | #endif | ||
| 395 | |||
| 396 | static u8 technisat_usb2_calc_lrc(const u8 *b, u16 length) | ||
| 397 | { | ||
| 398 | u8 lrc = 0; | ||
| 399 | while (--length) | ||
| 400 | lrc ^= *b++; | ||
| 401 | return lrc; | ||
| 402 | } | ||
| 403 | |||
| 404 | static int technisat_usb2_eeprom_lrc_read(struct dvb_usb_device *d, | ||
| 405 | u16 offset, u8 *b, u16 length, u8 tries) | ||
| 406 | { | ||
| 407 | u8 bo = offset & 0xff; | ||
| 408 | struct i2c_msg msg[] = { | ||
| 409 | { | ||
| 410 | .addr = 0x50 | ((offset >> 8) & 0x3), | ||
| 411 | .buf = &bo, | ||
| 412 | .len = 1 | ||
| 413 | }, { | ||
| 414 | .addr = 0x50 | ((offset >> 8) & 0x3), | ||
| 415 | .flags = I2C_M_RD, | ||
| 416 | .buf = b, | ||
| 417 | .len = length | ||
| 418 | } | ||
| 419 | }; | ||
| 420 | |||
| 421 | while (tries--) { | ||
| 422 | int status; | ||
| 423 | |||
| 424 | if (i2c_transfer(&d->i2c_adap, msg, 2) != 2) | ||
| 425 | break; | ||
| 426 | |||
| 427 | status = | ||
| 428 | technisat_usb2_calc_lrc(b, length - 1) == b[length - 1]; | ||
| 429 | |||
| 430 | if (status) | ||
| 431 | return 0; | ||
| 432 | } | ||
| 433 | |||
| 434 | return -EREMOTEIO; | ||
| 435 | } | ||
| 436 | |||
| 437 | #define EEPROM_MAC_START 0x3f8 | ||
| 438 | #define EEPROM_MAC_TOTAL 8 | ||
| 439 | static int technisat_usb2_read_mac_address(struct dvb_usb_device *d, | ||
| 440 | u8 mac[]) | ||
| 441 | { | ||
| 442 | u8 buf[EEPROM_MAC_TOTAL]; | ||
| 443 | |||
| 444 | if (technisat_usb2_eeprom_lrc_read(d, EEPROM_MAC_START, | ||
| 445 | buf, EEPROM_MAC_TOTAL, 4) != 0) | ||
| 446 | return -ENODEV; | ||
| 447 | |||
| 448 | memcpy(mac, buf, 6); | ||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | |||
| 452 | /* frontend attach */ | ||
| 453 | static int technisat_usb2_set_voltage(struct dvb_frontend *fe, | ||
| 454 | fe_sec_voltage_t voltage) | ||
| 455 | { | ||
| 456 | int i; | ||
| 457 | u8 gpio[3] = { 0 }; /* 0 = 2, 1 = 3, 2 = 4 */ | ||
| 458 | |||
| 459 | gpio[2] = 1; /* high - voltage ? */ | ||
| 460 | |||
| 461 | switch (voltage) { | ||
| 462 | case SEC_VOLTAGE_13: | ||
| 463 | gpio[0] = 1; | ||
| 464 | break; | ||
| 465 | case SEC_VOLTAGE_18: | ||
| 466 | gpio[0] = 1; | ||
| 467 | gpio[1] = 1; | ||
| 468 | break; | ||
| 469 | default: | ||
| 470 | case SEC_VOLTAGE_OFF: | ||
| 471 | break; | ||
| 472 | } | ||
| 473 | |||
| 474 | for (i = 0; i < 3; i++) | ||
| 475 | if (stv090x_set_gpio(fe, i+2, 0, gpio[i], 0) != 0) | ||
| 476 | return -EREMOTEIO; | ||
| 477 | return 0; | ||
| 478 | } | ||
| 479 | |||
| 480 | static struct stv090x_config technisat_usb2_stv090x_config = { | ||
| 481 | .device = STV0903, | ||
| 482 | .demod_mode = STV090x_SINGLE, | ||
| 483 | .clk_mode = STV090x_CLK_EXT, | ||
| 484 | |||
| 485 | .xtal = 8000000, | ||
| 486 | .address = 0x68, | ||
| 487 | |||
| 488 | .ts1_mode = STV090x_TSMODE_DVBCI, | ||
| 489 | .ts1_clk = 13400000, | ||
| 490 | .ts1_tei = 1, | ||
| 491 | |||
| 492 | .repeater_level = STV090x_RPTLEVEL_64, | ||
| 493 | |||
| 494 | .tuner_bbgain = 6, | ||
| 495 | }; | ||
| 496 | |||
| 497 | static struct stv6110x_config technisat_usb2_stv6110x_config = { | ||
| 498 | .addr = 0x60, | ||
| 499 | .refclk = 16000000, | ||
| 500 | .clk_div = 2, | ||
| 501 | }; | ||
| 502 | |||
| 503 | static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) | ||
| 504 | { | ||
| 505 | struct usb_device *udev = a->dev->udev; | ||
| 506 | int ret; | ||
| 507 | |||
| 508 | a->fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config, | ||
| 509 | &a->dev->i2c_adap, STV090x_DEMODULATOR_0); | ||
| 510 | |||
| 511 | if (a->fe) { | ||
| 512 | struct stv6110x_devctl *ctl; | ||
| 513 | |||
| 514 | ctl = dvb_attach(stv6110x_attach, | ||
| 515 | a->fe, | ||
| 516 | &technisat_usb2_stv6110x_config, | ||
| 517 | &a->dev->i2c_adap); | ||
| 518 | |||
| 519 | if (ctl) { | ||
| 520 | technisat_usb2_stv090x_config.tuner_init = ctl->tuner_init; | ||
| 521 | technisat_usb2_stv090x_config.tuner_sleep = ctl->tuner_sleep; | ||
| 522 | technisat_usb2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; | ||
| 523 | technisat_usb2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; | ||
| 524 | technisat_usb2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; | ||
| 525 | technisat_usb2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; | ||
| 526 | technisat_usb2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; | ||
| 527 | technisat_usb2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; | ||
| 528 | technisat_usb2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; | ||
| 529 | technisat_usb2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; | ||
| 530 | technisat_usb2_stv090x_config.tuner_get_status = ctl->tuner_get_status; | ||
| 531 | |||
| 532 | /* call the init function once to initialize | ||
| 533 | tuner's clock output divider and demod's | ||
| 534 | master clock */ | ||
| 535 | if (a->fe->ops.init) | ||
| 536 | a->fe->ops.init(a->fe); | ||
| 537 | |||
| 538 | if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0) | ||
| 539 | return -EAGAIN; | ||
| 540 | |||
| 541 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 542 | SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST, | ||
| 543 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 544 | 0, 0, | ||
| 545 | NULL, 0, 500); | ||
| 546 | mutex_unlock(&a->dev->i2c_mutex); | ||
| 547 | |||
| 548 | if (ret != 0) | ||
| 549 | err("could not set IF_CLK to external"); | ||
| 550 | |||
| 551 | a->fe->ops.set_voltage = technisat_usb2_set_voltage; | ||
| 552 | |||
| 553 | /* if everything was successful assign a nice name to the frontend */ | ||
| 554 | strlcpy(a->fe->ops.info.name, a->dev->desc->name, | ||
| 555 | sizeof(a->fe->ops.info.name)); | ||
| 556 | } else { | ||
| 557 | dvb_frontend_detach(a->fe); | ||
| 558 | a->fe = NULL; | ||
| 559 | } | ||
| 560 | } | ||
| 561 | |||
| 562 | technisat_usb2_set_led_timer(a->dev, 1, 1); | ||
| 563 | |||
| 564 | return a->fe == NULL ? -ENODEV : 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | /* Remote control */ | ||
| 568 | |||
| 569 | /* the device is giving providing raw IR-signals to the host mapping | ||
| 570 | * it only to one remote control is just the default implementation | ||
| 571 | */ | ||
| 572 | #define NOMINAL_IR_BIT_TRANSITION_TIME_US 889 | ||
| 573 | #define NOMINAL_IR_BIT_TIME_US (2 * NOMINAL_IR_BIT_TRANSITION_TIME_US) | ||
| 574 | |||
| 575 | #define FIRMWARE_CLOCK_TICK 83333 | ||
| 576 | #define FIRMWARE_CLOCK_DIVISOR 256 | ||
| 577 | |||
| 578 | #define IR_PERCENT_TOLERANCE 15 | ||
| 579 | |||
| 580 | #define NOMINAL_IR_BIT_TRANSITION_TICKS ((NOMINAL_IR_BIT_TRANSITION_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK) | ||
| 581 | #define NOMINAL_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICKS / FIRMWARE_CLOCK_DIVISOR) | ||
| 582 | |||
| 583 | #define NOMINAL_IR_BIT_TIME_TICKS ((NOMINAL_IR_BIT_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK) | ||
| 584 | #define NOMINAL_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICKS / FIRMWARE_CLOCK_DIVISOR) | ||
| 585 | |||
| 586 | #define MINIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT - ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100)) | ||
| 587 | #define MAXIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT + ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100)) | ||
| 588 | |||
| 589 | #define MINIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT - ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100)) | ||
| 590 | #define MAXIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT + ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100)) | ||
| 591 | |||
| 592 | static int technisat_usb2_get_ir(struct dvb_usb_device *d) | ||
| 593 | { | ||
| 594 | u8 buf[62], *b; | ||
| 595 | int ret; | ||
| 596 | struct ir_raw_event ev; | ||
| 597 | |||
| 598 | buf[0] = GET_IR_DATA_VENDOR_REQUEST; | ||
| 599 | buf[1] = 0x08; | ||
| 600 | buf[2] = 0x8f; | ||
| 601 | buf[3] = MINIMUM_IR_BIT_TRANSITION_TICK_COUNT; | ||
| 602 | buf[4] = MAXIMUM_IR_BIT_TIME_TICK_COUNT; | ||
| 603 | |||
| 604 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 605 | return -EAGAIN; | ||
| 606 | ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), | ||
| 607 | GET_IR_DATA_VENDOR_REQUEST, | ||
| 608 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 609 | 0, 0, | ||
| 610 | buf, 5, 500); | ||
| 611 | if (ret < 0) | ||
| 612 | goto unlock; | ||
| 613 | |||
| 614 | buf[1] = 0; | ||
| 615 | buf[2] = 0; | ||
| 616 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), | ||
| 617 | GET_IR_DATA_VENDOR_REQUEST, | ||
| 618 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
| 619 | 0x8080, 0, | ||
| 620 | buf, sizeof(buf), 500); | ||
| 621 | |||
| 622 | unlock: | ||
| 623 | mutex_unlock(&d->i2c_mutex); | ||
| 624 | |||
| 625 | if (ret < 0) | ||
| 626 | return ret; | ||
| 627 | |||
| 628 | if (ret == 1) | ||
| 629 | return 0; /* no key pressed */ | ||
| 630 | |||
| 631 | /* decoding */ | ||
| 632 | b = buf+1; | ||
| 633 | |||
| 634 | #if 0 | ||
| 635 | deb_rc("RC: %d ", ret); | ||
| 636 | debug_dump(b, ret, deb_rc); | ||
| 637 | #endif | ||
| 638 | |||
| 639 | ev.pulse = 0; | ||
| 640 | while (1) { | ||
| 641 | ev.pulse = !ev.pulse; | ||
| 642 | ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000; | ||
| 643 | ir_raw_event_store(d->rc_dev, &ev); | ||
| 644 | |||
| 645 | b++; | ||
| 646 | if (*b == 0xff) { | ||
| 647 | ev.pulse = 0; | ||
| 648 | ev.duration = 888888*2; | ||
| 649 | ir_raw_event_store(d->rc_dev, &ev); | ||
| 650 | break; | ||
| 651 | } | ||
| 652 | } | ||
| 653 | |||
| 654 | ir_raw_event_handle(d->rc_dev); | ||
| 655 | |||
| 656 | return 1; | ||
| 657 | } | ||
| 658 | |||
| 659 | static int technisat_usb2_rc_query(struct dvb_usb_device *d) | ||
| 660 | { | ||
| 661 | int ret = technisat_usb2_get_ir(d); | ||
| 662 | |||
| 663 | if (ret < 0) | ||
| 664 | return ret; | ||
| 665 | |||
| 666 | if (ret == 0) | ||
| 667 | return 0; | ||
| 668 | |||
| 669 | if (!disable_led_control) | ||
| 670 | technisat_usb2_set_led(d, 1, LED_BLINK); | ||
| 671 | |||
| 672 | return 0; | ||
| 673 | } | ||
| 674 | |||
| 675 | /* DVB-USB and USB stuff follows */ | ||
| 676 | static struct usb_device_id technisat_usb2_id_table[] = { | ||
| 677 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) }, | ||
| 678 | { 0 } /* Terminating entry */ | ||
| 679 | }; | ||
| 680 | |||
| 681 | /* device description */ | ||
| 682 | static struct dvb_usb_device_properties technisat_usb2_devices = { | ||
| 683 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 684 | |||
| 685 | .usb_ctrl = CYPRESS_FX2, | ||
| 686 | |||
| 687 | .identify_state = technisat_usb2_identify_state, | ||
| 688 | .firmware = "dvb-usb-SkyStar_USB_HD_FW_v17_63.HEX.fw", | ||
| 689 | |||
| 690 | .size_of_priv = sizeof(struct technisat_usb2_state), | ||
| 691 | |||
| 692 | .i2c_algo = &technisat_usb2_i2c_algo, | ||
| 693 | |||
| 694 | .power_ctrl = technisat_usb2_power_ctrl, | ||
| 695 | .read_mac_address = technisat_usb2_read_mac_address, | ||
| 696 | |||
| 697 | .num_adapters = 1, | ||
| 698 | .adapter = { | ||
| 699 | { | ||
| 700 | .frontend_attach = technisat_usb2_frontend_attach, | ||
| 701 | |||
| 702 | .stream = { | ||
| 703 | .type = USB_ISOC, | ||
| 704 | .count = 8, | ||
| 705 | .endpoint = 0x2, | ||
| 706 | .u = { | ||
| 707 | .isoc = { | ||
| 708 | .framesperurb = 32, | ||
| 709 | .framesize = 2048, | ||
| 710 | .interval = 3, | ||
| 711 | } | ||
| 712 | } | ||
| 713 | }, | ||
| 714 | |||
| 715 | .size_of_priv = 0, | ||
| 716 | }, | ||
| 717 | }, | ||
| 718 | |||
| 719 | .num_device_descs = 1, | ||
| 720 | .devices = { | ||
| 721 | { "Technisat SkyStar USB HD (DVB-S/S2)", | ||
| 722 | { &technisat_usb2_id_table[0], NULL }, | ||
| 723 | { NULL }, | ||
| 724 | }, | ||
| 725 | }, | ||
| 726 | |||
| 727 | .rc.core = { | ||
| 728 | .rc_interval = 100, | ||
| 729 | .rc_codes = RC_MAP_TECHNISAT_USB2, | ||
| 730 | .module_name = "technisat-usb2", | ||
| 731 | .rc_query = technisat_usb2_rc_query, | ||
| 732 | .allowed_protos = RC_TYPE_ALL, | ||
| 733 | .driver_type = RC_DRIVER_IR_RAW, | ||
| 734 | } | ||
| 735 | }; | ||
| 736 | |||
| 737 | static int technisat_usb2_probe(struct usb_interface *intf, | ||
| 738 | const struct usb_device_id *id) | ||
| 739 | { | ||
| 740 | struct dvb_usb_device *dev; | ||
| 741 | |||
| 742 | if (dvb_usb_device_init(intf, &technisat_usb2_devices, THIS_MODULE, | ||
| 743 | &dev, adapter_nr) != 0) | ||
| 744 | return -ENODEV; | ||
| 745 | |||
| 746 | if (dev) { | ||
| 747 | struct technisat_usb2_state *state = dev->priv; | ||
| 748 | state->dev = dev; | ||
| 749 | |||
| 750 | if (!disable_led_control) { | ||
| 751 | INIT_DELAYED_WORK(&state->green_led_work, | ||
| 752 | technisat_usb2_green_led_control); | ||
| 753 | schedule_delayed_work(&state->green_led_work, | ||
| 754 | msecs_to_jiffies(500)); | ||
| 755 | } | ||
| 756 | } | ||
| 757 | |||
| 758 | return 0; | ||
| 759 | } | ||
| 760 | |||
| 761 | static void technisat_usb2_disconnect(struct usb_interface *intf) | ||
| 762 | { | ||
| 763 | struct dvb_usb_device *dev = usb_get_intfdata(intf); | ||
| 764 | |||
| 765 | /* work and stuff was only created when the device is is hot-state */ | ||
| 766 | if (dev != NULL) { | ||
| 767 | struct technisat_usb2_state *state = dev->priv; | ||
| 768 | if (state != NULL) | ||
| 769 | cancel_delayed_work_sync(&state->green_led_work); | ||
| 770 | } | ||
| 771 | |||
| 772 | dvb_usb_device_exit(intf); | ||
| 773 | } | ||
| 774 | |||
| 775 | static struct usb_driver technisat_usb2_driver = { | ||
| 776 | .name = "dvb_usb_technisat_usb2", | ||
| 777 | .probe = technisat_usb2_probe, | ||
| 778 | .disconnect = technisat_usb2_disconnect, | ||
| 779 | .id_table = technisat_usb2_id_table, | ||
| 780 | }; | ||
| 781 | |||
| 782 | /* module stuff */ | ||
| 783 | static int __init technisat_usb2_module_init(void) | ||
| 784 | { | ||
| 785 | int result = usb_register(&technisat_usb2_driver); | ||
| 786 | if (result) { | ||
| 787 | err("usb_register failed. Code %d", result); | ||
| 788 | return result; | ||
| 789 | } | ||
| 790 | |||
| 791 | return 0; | ||
| 792 | } | ||
| 793 | |||
| 794 | static void __exit technisat_usb2_module_exit(void) | ||
| 795 | { | ||
| 796 | usb_deregister(&technisat_usb2_driver); | ||
| 797 | } | ||
| 798 | |||
| 799 | module_init(technisat_usb2_module_init); | ||
| 800 | module_exit(technisat_usb2_module_exit); | ||
| 801 | |||
| 802 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@kernellabs.com>"); | ||
| 803 | MODULE_DESCRIPTION("Driver for Technisat DVB-S/S2 USB 2.0 device"); | ||
| 804 | MODULE_VERSION("1.0"); | ||
| 805 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c new file mode 100644 index 00000000000..0d4709ff9cb --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ttusb2.c | |||
| @@ -0,0 +1,453 @@ | |||
| 1 | /* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones | ||
| 2 | * (e.g. Pinnacle 400e DVB-S USB2.0). | ||
| 3 | * | ||
| 4 | * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes. | ||
| 5 | * | ||
| 6 | * TDA8263 + TDA10086 | ||
| 7 | * | ||
| 8 | * I2C addresses: | ||
| 9 | * 0x08 - LNBP21PD - LNB power supply | ||
| 10 | * 0x0e - TDA10086 - Demodulator | ||
| 11 | * 0x50 - FX2 eeprom | ||
| 12 | * 0x60 - TDA8263 - Tuner | ||
| 13 | * 0x78 ??? | ||
| 14 | * | ||
| 15 | * Copyright (c) 2002 Holger Waechtler <holger@convergence.de> | ||
| 16 | * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net> | ||
| 17 | * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.org> | ||
| 18 | * | ||
| 19 | * This program is free software; you can redistribute it and/or modify it | ||
| 20 | * under the terms of the GNU General Public License as published by the Free | ||
| 21 | * Software Foundation, version 2. | ||
| 22 | * | ||
| 23 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 24 | */ | ||
| 25 | #define DVB_USB_LOG_PREFIX "ttusb2" | ||
| 26 | #include "dvb-usb.h" | ||
| 27 | |||
| 28 | #include "ttusb2.h" | ||
| 29 | |||
| 30 | #include "tda826x.h" | ||
| 31 | #include "tda10086.h" | ||
| 32 | #include "tda1002x.h" | ||
| 33 | #include "tda827x.h" | ||
| 34 | #include "lnbp21.h" | ||
| 35 | |||
| 36 | /* debug */ | ||
| 37 | static int dvb_usb_ttusb2_debug; | ||
| 38 | #define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args) | ||
| 39 | module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644); | ||
| 40 | MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 41 | |||
| 42 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 43 | |||
| 44 | struct ttusb2_state { | ||
| 45 | u8 id; | ||
| 46 | u16 last_rc_key; | ||
| 47 | }; | ||
| 48 | |||
| 49 | static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, | ||
| 50 | u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
| 51 | { | ||
| 52 | struct ttusb2_state *st = d->priv; | ||
| 53 | u8 s[wlen+4],r[64] = { 0 }; | ||
| 54 | int ret = 0; | ||
| 55 | |||
| 56 | memset(s,0,wlen+4); | ||
| 57 | |||
| 58 | s[0] = 0xaa; | ||
| 59 | s[1] = ++st->id; | ||
| 60 | s[2] = cmd; | ||
| 61 | s[3] = wlen; | ||
| 62 | memcpy(&s[4],wbuf,wlen); | ||
| 63 | |||
| 64 | ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0); | ||
| 65 | |||
| 66 | if (ret != 0 || | ||
| 67 | r[0] != 0x55 || | ||
| 68 | r[1] != s[1] || | ||
| 69 | r[2] != cmd || | ||
| 70 | (rlen > 0 && r[3] != rlen)) { | ||
| 71 | warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]); | ||
| 72 | return -EIO; | ||
| 73 | } | ||
| 74 | |||
| 75 | if (rlen > 0) | ||
| 76 | memcpy(rbuf, &r[4], rlen); | ||
| 77 | |||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | ||
| 82 | { | ||
| 83 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
| 84 | static u8 obuf[60], ibuf[60]; | ||
| 85 | int i,read; | ||
| 86 | |||
| 87 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
| 88 | return -EAGAIN; | ||
| 89 | |||
| 90 | if (num > 2) | ||
| 91 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
| 92 | |||
| 93 | for (i = 0; i < num; i++) { | ||
| 94 | read = i+1 < num && (msg[i+1].flags & I2C_M_RD); | ||
| 95 | |||
| 96 | obuf[0] = (msg[i].addr << 1) | read; | ||
| 97 | obuf[1] = msg[i].len; | ||
| 98 | |||
| 99 | /* read request */ | ||
| 100 | if (read) | ||
| 101 | obuf[2] = msg[i+1].len; | ||
| 102 | else | ||
| 103 | obuf[2] = 0; | ||
| 104 | |||
| 105 | memcpy(&obuf[3],msg[i].buf,msg[i].len); | ||
| 106 | |||
| 107 | if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) { | ||
| 108 | err("i2c transfer failed."); | ||
| 109 | break; | ||
| 110 | } | ||
| 111 | |||
| 112 | if (read) { | ||
| 113 | memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len); | ||
| 114 | i++; | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | mutex_unlock(&d->i2c_mutex); | ||
| 119 | return i; | ||
| 120 | } | ||
| 121 | |||
| 122 | static u32 ttusb2_i2c_func(struct i2c_adapter *adapter) | ||
| 123 | { | ||
| 124 | return I2C_FUNC_I2C; | ||
| 125 | } | ||
| 126 | |||
| 127 | static struct i2c_algorithm ttusb2_i2c_algo = { | ||
| 128 | .master_xfer = ttusb2_i2c_xfer, | ||
| 129 | .functionality = ttusb2_i2c_func, | ||
| 130 | }; | ||
| 131 | |||
| 132 | /* command to poll IR receiver (copied from pctv452e.c) */ | ||
| 133 | #define CMD_GET_IR_CODE 0x1b | ||
| 134 | |||
| 135 | /* IR */ | ||
| 136 | static int tt3650_rc_query(struct dvb_usb_device *d) | ||
| 137 | { | ||
| 138 | int ret; | ||
| 139 | u8 rx[9]; /* A CMD_GET_IR_CODE reply is 9 bytes long */ | ||
| 140 | struct ttusb2_state *st = d->priv; | ||
| 141 | ret = ttusb2_msg(d, CMD_GET_IR_CODE, NULL, 0, rx, sizeof(rx)); | ||
| 142 | if (ret != 0) | ||
| 143 | return ret; | ||
| 144 | |||
| 145 | if (rx[8] & 0x01) { | ||
| 146 | /* got a "press" event */ | ||
| 147 | st->last_rc_key = (rx[3] << 8) | rx[2]; | ||
| 148 | deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]); | ||
| 149 | rc_keydown(d->rc_dev, st->last_rc_key, 0); | ||
| 150 | } else if (st->last_rc_key) { | ||
| 151 | rc_keyup(d->rc_dev); | ||
| 152 | st->last_rc_key = 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | |||
| 159 | /* Callbacks for DVB USB */ | ||
| 160 | static int ttusb2_identify_state (struct usb_device *udev, struct | ||
| 161 | dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, | ||
| 162 | int *cold) | ||
| 163 | { | ||
| 164 | *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0; | ||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 169 | { | ||
| 170 | u8 b = onoff; | ||
| 171 | ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0); | ||
| 172 | return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0); | ||
| 173 | } | ||
| 174 | |||
| 175 | |||
| 176 | static struct tda10086_config tda10086_config = { | ||
| 177 | .demod_address = 0x0e, | ||
| 178 | .invert = 0, | ||
| 179 | .diseqc_tone = 1, | ||
| 180 | .xtal_freq = TDA10086_XTAL_16M, | ||
| 181 | }; | ||
| 182 | |||
| 183 | static struct tda10023_config tda10023_config = { | ||
| 184 | .demod_address = 0x0c, | ||
| 185 | .invert = 0, | ||
| 186 | .xtal = 16000000, | ||
| 187 | .pll_m = 11, | ||
| 188 | .pll_p = 3, | ||
| 189 | .pll_n = 1, | ||
| 190 | .deltaf = 0xa511, | ||
| 191 | }; | ||
| 192 | |||
| 193 | static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap) | ||
| 194 | { | ||
| 195 | if (usb_set_interface(adap->dev->udev,0,3) < 0) | ||
| 196 | err("set interface to alts=3 failed"); | ||
| 197 | |||
| 198 | if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) { | ||
| 199 | deb_info("TDA10086 attach failed\n"); | ||
| 200 | return -ENODEV; | ||
| 201 | } | ||
| 202 | |||
| 203 | return 0; | ||
| 204 | } | ||
| 205 | |||
| 206 | static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap) | ||
| 207 | { | ||
| 208 | if (usb_set_interface(adap->dev->udev, 0, 3) < 0) | ||
| 209 | err("set interface to alts=3 failed"); | ||
| 210 | if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) { | ||
| 211 | deb_info("TDA10023 attach failed\n"); | ||
| 212 | return -ENODEV; | ||
| 213 | } | ||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap) | ||
| 218 | { | ||
| 219 | if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) { | ||
| 220 | printk(KERN_ERR "%s: No tda827x found!\n", __func__); | ||
| 221 | return -ENODEV; | ||
| 222 | } | ||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap) | ||
| 227 | { | ||
| 228 | if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) { | ||
| 229 | deb_info("TDA8263 attach failed\n"); | ||
| 230 | return -ENODEV; | ||
| 231 | } | ||
| 232 | |||
| 233 | if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) { | ||
| 234 | deb_info("LNBP21 attach failed\n"); | ||
| 235 | return -ENODEV; | ||
| 236 | } | ||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* DVB USB Driver stuff */ | ||
| 241 | static struct dvb_usb_device_properties ttusb2_properties; | ||
| 242 | static struct dvb_usb_device_properties ttusb2_properties_s2400; | ||
| 243 | static struct dvb_usb_device_properties ttusb2_properties_ct3650; | ||
| 244 | |||
| 245 | static int ttusb2_probe(struct usb_interface *intf, | ||
| 246 | const struct usb_device_id *id) | ||
| 247 | { | ||
| 248 | if (0 == dvb_usb_device_init(intf, &ttusb2_properties, | ||
| 249 | THIS_MODULE, NULL, adapter_nr) || | ||
| 250 | 0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400, | ||
| 251 | THIS_MODULE, NULL, adapter_nr) || | ||
| 252 | 0 == dvb_usb_device_init(intf, &ttusb2_properties_ct3650, | ||
| 253 | THIS_MODULE, NULL, adapter_nr)) | ||
| 254 | return 0; | ||
| 255 | return -ENODEV; | ||
| 256 | } | ||
| 257 | |||
| 258 | static struct usb_device_id ttusb2_table [] = { | ||
| 259 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) }, | ||
| 260 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) }, | ||
| 261 | { USB_DEVICE(USB_VID_TECHNOTREND, | ||
| 262 | USB_PID_TECHNOTREND_CONNECT_S2400) }, | ||
| 263 | { USB_DEVICE(USB_VID_TECHNOTREND, | ||
| 264 | USB_PID_TECHNOTREND_CONNECT_CT3650) }, | ||
| 265 | {} /* Terminating entry */ | ||
| 266 | }; | ||
| 267 | MODULE_DEVICE_TABLE (usb, ttusb2_table); | ||
| 268 | |||
| 269 | static struct dvb_usb_device_properties ttusb2_properties = { | ||
| 270 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 271 | |||
| 272 | .usb_ctrl = CYPRESS_FX2, | ||
| 273 | .firmware = "dvb-usb-pctv-400e-01.fw", | ||
| 274 | |||
| 275 | .size_of_priv = sizeof(struct ttusb2_state), | ||
| 276 | |||
| 277 | .num_adapters = 1, | ||
| 278 | .adapter = { | ||
| 279 | { | ||
| 280 | .streaming_ctrl = NULL, // ttusb2_streaming_ctrl, | ||
| 281 | |||
| 282 | .frontend_attach = ttusb2_frontend_tda10086_attach, | ||
| 283 | .tuner_attach = ttusb2_tuner_tda826x_attach, | ||
| 284 | |||
| 285 | /* parameter for the MPEG2-data transfer */ | ||
| 286 | .stream = { | ||
| 287 | .type = USB_ISOC, | ||
| 288 | .count = 5, | ||
| 289 | .endpoint = 0x02, | ||
| 290 | .u = { | ||
| 291 | .isoc = { | ||
| 292 | .framesperurb = 4, | ||
| 293 | .framesize = 940, | ||
| 294 | .interval = 1, | ||
| 295 | } | ||
| 296 | } | ||
| 297 | } | ||
| 298 | } | ||
| 299 | }, | ||
| 300 | |||
| 301 | .power_ctrl = ttusb2_power_ctrl, | ||
| 302 | .identify_state = ttusb2_identify_state, | ||
| 303 | |||
| 304 | .i2c_algo = &ttusb2_i2c_algo, | ||
| 305 | |||
| 306 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 307 | |||
| 308 | .num_device_descs = 2, | ||
| 309 | .devices = { | ||
| 310 | { "Pinnacle 400e DVB-S USB2.0", | ||
| 311 | { &ttusb2_table[0], NULL }, | ||
| 312 | { NULL }, | ||
| 313 | }, | ||
| 314 | { "Pinnacle 450e DVB-S USB2.0", | ||
| 315 | { &ttusb2_table[1], NULL }, | ||
| 316 | { NULL }, | ||
| 317 | }, | ||
| 318 | } | ||
| 319 | }; | ||
| 320 | |||
| 321 | static struct dvb_usb_device_properties ttusb2_properties_s2400 = { | ||
| 322 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 323 | |||
| 324 | .usb_ctrl = CYPRESS_FX2, | ||
| 325 | .firmware = "dvb-usb-tt-s2400-01.fw", | ||
| 326 | |||
| 327 | .size_of_priv = sizeof(struct ttusb2_state), | ||
| 328 | |||
| 329 | .num_adapters = 1, | ||
| 330 | .adapter = { | ||
| 331 | { | ||
| 332 | .streaming_ctrl = NULL, | ||
| 333 | |||
| 334 | .frontend_attach = ttusb2_frontend_tda10086_attach, | ||
| 335 | .tuner_attach = ttusb2_tuner_tda826x_attach, | ||
| 336 | |||
| 337 | /* parameter for the MPEG2-data transfer */ | ||
| 338 | .stream = { | ||
| 339 | .type = USB_ISOC, | ||
| 340 | .count = 5, | ||
| 341 | .endpoint = 0x02, | ||
| 342 | .u = { | ||
| 343 | .isoc = { | ||
| 344 | .framesperurb = 4, | ||
| 345 | .framesize = 940, | ||
| 346 | .interval = 1, | ||
| 347 | } | ||
| 348 | } | ||
| 349 | } | ||
| 350 | } | ||
| 351 | }, | ||
| 352 | |||
| 353 | .power_ctrl = ttusb2_power_ctrl, | ||
| 354 | .identify_state = ttusb2_identify_state, | ||
| 355 | |||
| 356 | .i2c_algo = &ttusb2_i2c_algo, | ||
| 357 | |||
| 358 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 359 | |||
| 360 | .num_device_descs = 1, | ||
| 361 | .devices = { | ||
| 362 | { "Technotrend TT-connect S-2400", | ||
| 363 | { &ttusb2_table[2], NULL }, | ||
| 364 | { NULL }, | ||
| 365 | }, | ||
| 366 | } | ||
| 367 | }; | ||
| 368 | |||
| 369 | static struct dvb_usb_device_properties ttusb2_properties_ct3650 = { | ||
| 370 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 371 | |||
| 372 | .usb_ctrl = CYPRESS_FX2, | ||
| 373 | |||
| 374 | .size_of_priv = sizeof(struct ttusb2_state), | ||
| 375 | |||
| 376 | .rc.core = { | ||
| 377 | .rc_interval = 150, /* Less than IR_KEYPRESS_TIMEOUT */ | ||
| 378 | .rc_codes = RC_MAP_TT_1500, | ||
| 379 | .rc_query = tt3650_rc_query, | ||
| 380 | .allowed_protos = RC_TYPE_UNKNOWN, | ||
| 381 | }, | ||
| 382 | |||
| 383 | .num_adapters = 1, | ||
| 384 | .adapter = { | ||
| 385 | { | ||
| 386 | .streaming_ctrl = NULL, | ||
| 387 | |||
| 388 | .frontend_attach = ttusb2_frontend_tda10023_attach, | ||
| 389 | .tuner_attach = ttusb2_tuner_tda827x_attach, | ||
| 390 | |||
| 391 | /* parameter for the MPEG2-data transfer */ | ||
| 392 | .stream = { | ||
| 393 | .type = USB_ISOC, | ||
| 394 | .count = 5, | ||
| 395 | .endpoint = 0x02, | ||
| 396 | .u = { | ||
| 397 | .isoc = { | ||
| 398 | .framesperurb = 4, | ||
| 399 | .framesize = 940, | ||
| 400 | .interval = 1, | ||
| 401 | } | ||
| 402 | } | ||
| 403 | } | ||
| 404 | }, | ||
| 405 | }, | ||
| 406 | |||
| 407 | .power_ctrl = ttusb2_power_ctrl, | ||
| 408 | .identify_state = ttusb2_identify_state, | ||
| 409 | |||
| 410 | .i2c_algo = &ttusb2_i2c_algo, | ||
| 411 | |||
| 412 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 413 | |||
| 414 | .num_device_descs = 1, | ||
| 415 | .devices = { | ||
| 416 | { "Technotrend TT-connect CT-3650", | ||
| 417 | .warm_ids = { &ttusb2_table[3], NULL }, | ||
| 418 | }, | ||
| 419 | } | ||
| 420 | }; | ||
| 421 | |||
| 422 | static struct usb_driver ttusb2_driver = { | ||
| 423 | .name = "dvb_usb_ttusb2", | ||
| 424 | .probe = ttusb2_probe, | ||
| 425 | .disconnect = dvb_usb_device_exit, | ||
| 426 | .id_table = ttusb2_table, | ||
| 427 | }; | ||
| 428 | |||
| 429 | /* module stuff */ | ||
| 430 | static int __init ttusb2_module_init(void) | ||
| 431 | { | ||
| 432 | int result; | ||
| 433 | if ((result = usb_register(&ttusb2_driver))) { | ||
| 434 | err("usb_register failed. Error number %d",result); | ||
| 435 | return result; | ||
| 436 | } | ||
| 437 | |||
| 438 | return 0; | ||
| 439 | } | ||
| 440 | |||
| 441 | static void __exit ttusb2_module_exit(void) | ||
| 442 | { | ||
| 443 | /* deregister this driver from the USB subsystem */ | ||
| 444 | usb_deregister(&ttusb2_driver); | ||
| 445 | } | ||
| 446 | |||
| 447 | module_init (ttusb2_module_init); | ||
| 448 | module_exit (ttusb2_module_exit); | ||
| 449 | |||
| 450 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 451 | MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0"); | ||
| 452 | MODULE_VERSION("1.0"); | ||
| 453 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.h b/drivers/media/dvb/dvb-usb/ttusb2.h new file mode 100644 index 00000000000..52a63af4089 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/ttusb2.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones | ||
| 2 | * (e.g. Pinnacle 400e DVB-S USB2.0). | ||
| 3 | * | ||
| 4 | * Copyright (c) 2002 Holger Waechtler <holger@convergence.de> | ||
| 5 | * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net> | ||
| 6 | * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.de> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation, version 2. | ||
| 11 | * | ||
| 12 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 13 | */ | ||
| 14 | #ifndef _DVB_USB_TTUSB2_H_ | ||
| 15 | #define _DVB_USB_TTUSB2_H_ | ||
| 16 | |||
| 17 | /* TTUSB protocol | ||
| 18 | * | ||
| 19 | * always to messages (out/in) | ||
| 20 | * out message: | ||
| 21 | * 0xaa <id> <cmdbyte> <datalen> <data...> | ||
| 22 | * | ||
| 23 | * in message (complete block is always 0x40 bytes long) | ||
| 24 | * 0x55 <id> <cmdbyte> <datalen> <data...> | ||
| 25 | * | ||
| 26 | * id is incremented for each transaction | ||
| 27 | */ | ||
| 28 | |||
| 29 | #define CMD_DSP_DOWNLOAD 0x13 | ||
| 30 | /* out data: <byte>[28] | ||
| 31 | * last block must be empty */ | ||
| 32 | |||
| 33 | #define CMD_DSP_BOOT 0x14 | ||
| 34 | /* out data: nothing */ | ||
| 35 | |||
| 36 | #define CMD_POWER 0x15 | ||
| 37 | /* out data: <on=1/off=0> */ | ||
| 38 | |||
| 39 | #define CMD_LNB 0x16 | ||
| 40 | /* out data: <power=1> <18V=0,13V=1> <tone> <??=1> <??=1> */ | ||
| 41 | |||
| 42 | #define CMD_GET_VERSION 0x17 | ||
| 43 | /* in data: <version_byte>[5] */ | ||
| 44 | |||
| 45 | #define CMD_DISEQC 0x18 | ||
| 46 | /* out data: <master=0xff/burst=??> <cmdlen> <cmdbytes>[cmdlen] */ | ||
| 47 | |||
| 48 | #define CMD_PID_ENABLE 0x22 | ||
| 49 | /* out data: <index> <type: ts=1/sec=2> <pid msb> <pid lsb> */ | ||
| 50 | |||
| 51 | #define CMD_PID_DISABLE 0x23 | ||
| 52 | /* out data: <index> */ | ||
| 53 | |||
| 54 | #define CMD_FILTER_ENABLE 0x24 | ||
| 55 | /* out data: <index> <pid_idx> <filter>[12] <mask>[12] */ | ||
| 56 | |||
| 57 | #define CMD_FILTER_DISABLE 0x25 | ||
| 58 | /* out data: <index> */ | ||
| 59 | |||
| 60 | #define CMD_GET_DSP_VERSION 0x26 | ||
| 61 | /* in data: <version_byte>[28] */ | ||
| 62 | |||
| 63 | #define CMD_I2C_XFER 0x31 | ||
| 64 | /* out data: <addr << 1> <sndlen> <rcvlen> <data>[sndlen] | ||
| 65 | * in data: <addr << 1> <sndlen> <rcvlen> <data>[rcvlen] */ | ||
| 66 | |||
| 67 | #define CMD_I2C_BITRATE 0x32 | ||
| 68 | /* out data: <default=0> */ | ||
| 69 | |||
| 70 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c new file mode 100644 index 00000000000..118aab1a3e5 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/umt-010.c | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | /* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0 | ||
| 2 | * DVB-T receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the Free | ||
| 8 | * Software Foundation, version 2. | ||
| 9 | * | ||
| 10 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 11 | */ | ||
| 12 | #include "dibusb.h" | ||
| 13 | |||
| 14 | #include "mt352.h" | ||
| 15 | |||
| 16 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 17 | |||
| 18 | static int umt_mt352_demod_init(struct dvb_frontend *fe) | ||
| 19 | { | ||
| 20 | static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d }; | ||
| 21 | static u8 mt352_reset[] = { 0x50, 0x80 }; | ||
| 22 | static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 }; | ||
| 23 | static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 }; | ||
| 24 | static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 }; | ||
| 25 | |||
| 26 | static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff }; | ||
| 27 | static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff }; | ||
| 28 | static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 }; | ||
| 29 | static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 }; | ||
| 30 | static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f }; | ||
| 31 | |||
| 32 | static u8 mt352_acq_ctl[] = { 0x53, 0x50 }; | ||
| 33 | static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 }; | ||
| 34 | |||
| 35 | mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); | ||
| 36 | udelay(2000); | ||
| 37 | mt352_write(fe, mt352_reset, sizeof(mt352_reset)); | ||
| 38 | mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio)); | ||
| 39 | |||
| 40 | mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); | ||
| 41 | mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); | ||
| 42 | |||
| 43 | mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1)); | ||
| 44 | mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2)); | ||
| 45 | mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3)); | ||
| 46 | mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4)); | ||
| 47 | mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5)); | ||
| 48 | |||
| 49 | mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl)); | ||
| 50 | mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1)); | ||
| 51 | |||
| 52 | return 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | static int umt_mt352_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 56 | { | ||
| 57 | struct mt352_config umt_config; | ||
| 58 | |||
| 59 | memset(&umt_config,0,sizeof(struct mt352_config)); | ||
| 60 | umt_config.demod_init = umt_mt352_demod_init; | ||
| 61 | umt_config.demod_address = 0xf; | ||
| 62 | |||
| 63 | adap->fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap); | ||
| 64 | |||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | static int umt_tuner_attach (struct dvb_usb_adapter *adap) | ||
| 69 | { | ||
| 70 | dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_TUA6034); | ||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | /* USB Driver stuff */ | ||
| 75 | static struct dvb_usb_device_properties umt_properties; | ||
| 76 | |||
| 77 | static int umt_probe(struct usb_interface *intf, | ||
| 78 | const struct usb_device_id *id) | ||
| 79 | { | ||
| 80 | if (0 == dvb_usb_device_init(intf, &umt_properties, | ||
| 81 | THIS_MODULE, NULL, adapter_nr)) | ||
| 82 | return 0; | ||
| 83 | return -EINVAL; | ||
| 84 | } | ||
| 85 | |||
| 86 | /* do not change the order of the ID table */ | ||
| 87 | static struct usb_device_id umt_table [] = { | ||
| 88 | /* 00 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) }, | ||
| 89 | /* 01 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) }, | ||
| 90 | { } /* Terminating entry */ | ||
| 91 | }; | ||
| 92 | MODULE_DEVICE_TABLE (usb, umt_table); | ||
| 93 | |||
| 94 | static struct dvb_usb_device_properties umt_properties = { | ||
| 95 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 96 | |||
| 97 | .usb_ctrl = CYPRESS_FX2, | ||
| 98 | .firmware = "dvb-usb-umt-010-02.fw", | ||
| 99 | |||
| 100 | .num_adapters = 1, | ||
| 101 | .adapter = { | ||
| 102 | { | ||
| 103 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
| 104 | .frontend_attach = umt_mt352_frontend_attach, | ||
| 105 | .tuner_attach = umt_tuner_attach, | ||
| 106 | |||
| 107 | /* parameter for the MPEG2-data transfer */ | ||
| 108 | .stream = { | ||
| 109 | .type = USB_BULK, | ||
| 110 | .count = MAX_NO_URBS_FOR_DATA_STREAM, | ||
| 111 | .endpoint = 0x06, | ||
| 112 | .u = { | ||
| 113 | .bulk = { | ||
| 114 | .buffersize = 512, | ||
| 115 | } | ||
| 116 | } | ||
| 117 | }, | ||
| 118 | |||
| 119 | .size_of_priv = sizeof(struct dibusb_state), | ||
| 120 | } | ||
| 121 | }, | ||
| 122 | .power_ctrl = dibusb_power_ctrl, | ||
| 123 | |||
| 124 | .i2c_algo = &dibusb_i2c_algo, | ||
| 125 | |||
| 126 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 127 | |||
| 128 | .num_device_descs = 1, | ||
| 129 | .devices = { | ||
| 130 | { "Hanftek UMT-010 DVB-T USB2.0", | ||
| 131 | { &umt_table[0], NULL }, | ||
| 132 | { &umt_table[1], NULL }, | ||
| 133 | }, | ||
| 134 | } | ||
| 135 | }; | ||
| 136 | |||
| 137 | static struct usb_driver umt_driver = { | ||
| 138 | .name = "dvb_usb_umt_010", | ||
| 139 | .probe = umt_probe, | ||
| 140 | .disconnect = dvb_usb_device_exit, | ||
| 141 | .id_table = umt_table, | ||
| 142 | }; | ||
| 143 | |||
| 144 | /* module stuff */ | ||
| 145 | static int __init umt_module_init(void) | ||
| 146 | { | ||
| 147 | int result; | ||
| 148 | if ((result = usb_register(&umt_driver))) { | ||
| 149 | err("usb_register failed. Error number %d",result); | ||
| 150 | return result; | ||
| 151 | } | ||
| 152 | |||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static void __exit umt_module_exit(void) | ||
| 157 | { | ||
| 158 | /* deregister this driver from the USB subsystem */ | ||
| 159 | usb_deregister(&umt_driver); | ||
| 160 | } | ||
| 161 | |||
| 162 | module_init (umt_module_init); | ||
| 163 | module_exit (umt_module_exit); | ||
| 164 | |||
| 165 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 166 | MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device"); | ||
| 167 | MODULE_VERSION("1.0"); | ||
| 168 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/dvb/dvb-usb/usb-urb.c new file mode 100644 index 00000000000..86d68933b6b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/usb-urb.c | |||
| @@ -0,0 +1,254 @@ | |||
| 1 | /* usb-urb.c is part of the DVB USB library. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 4 | * see dvb-usb-init.c for copyright information. | ||
| 5 | * | ||
| 6 | * This file keeps functions for initializing and handling the | ||
| 7 | * BULK and ISOC USB data transfers in a generic way. | ||
| 8 | * Can be used for DVB-only and also, that's the plan, for | ||
| 9 | * Hybrid USB devices (analog and DVB). | ||
| 10 | */ | ||
| 11 | #include "dvb-usb-common.h" | ||
| 12 | |||
| 13 | /* URB stuff for streaming */ | ||
| 14 | static void usb_urb_complete(struct urb *urb) | ||
| 15 | { | ||
| 16 | struct usb_data_stream *stream = urb->context; | ||
| 17 | int ptype = usb_pipetype(urb->pipe); | ||
| 18 | int i; | ||
| 19 | u8 *b; | ||
| 20 | |||
| 21 | deb_uxfer("'%s' urb completed. status: %d, length: %d/%d, pack_num: %d, errors: %d\n", | ||
| 22 | ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk", | ||
| 23 | urb->status,urb->actual_length,urb->transfer_buffer_length, | ||
| 24 | urb->number_of_packets,urb->error_count); | ||
| 25 | |||
| 26 | switch (urb->status) { | ||
| 27 | case 0: /* success */ | ||
| 28 | case -ETIMEDOUT: /* NAK */ | ||
| 29 | break; | ||
| 30 | case -ECONNRESET: /* kill */ | ||
| 31 | case -ENOENT: | ||
| 32 | case -ESHUTDOWN: | ||
| 33 | return; | ||
| 34 | default: /* error */ | ||
| 35 | deb_ts("urb completition error %d.\n", urb->status); | ||
| 36 | break; | ||
| 37 | } | ||
| 38 | |||
| 39 | b = (u8 *) urb->transfer_buffer; | ||
| 40 | switch (ptype) { | ||
| 41 | case PIPE_ISOCHRONOUS: | ||
| 42 | for (i = 0; i < urb->number_of_packets; i++) { | ||
| 43 | |||
| 44 | if (urb->iso_frame_desc[i].status != 0) | ||
| 45 | deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status); | ||
| 46 | else if (urb->iso_frame_desc[i].actual_length > 0) | ||
| 47 | stream->complete(stream, b + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length); | ||
| 48 | |||
| 49 | urb->iso_frame_desc[i].status = 0; | ||
| 50 | urb->iso_frame_desc[i].actual_length = 0; | ||
| 51 | } | ||
| 52 | debug_dump(b,20,deb_uxfer); | ||
| 53 | break; | ||
| 54 | case PIPE_BULK: | ||
| 55 | if (urb->actual_length > 0) | ||
| 56 | stream->complete(stream, b, urb->actual_length); | ||
| 57 | break; | ||
| 58 | default: | ||
| 59 | err("unknown endpoint type in completition handler."); | ||
| 60 | return; | ||
| 61 | } | ||
| 62 | usb_submit_urb(urb,GFP_ATOMIC); | ||
| 63 | } | ||
| 64 | |||
| 65 | int usb_urb_kill(struct usb_data_stream *stream) | ||
| 66 | { | ||
| 67 | int i; | ||
| 68 | for (i = 0; i < stream->urbs_submitted; i++) { | ||
| 69 | deb_ts("killing URB no. %d.\n",i); | ||
| 70 | |||
| 71 | /* stop the URB */ | ||
| 72 | usb_kill_urb(stream->urb_list[i]); | ||
| 73 | } | ||
| 74 | stream->urbs_submitted = 0; | ||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | int usb_urb_submit(struct usb_data_stream *stream) | ||
| 79 | { | ||
| 80 | int i,ret; | ||
| 81 | for (i = 0; i < stream->urbs_initialized; i++) { | ||
| 82 | deb_ts("submitting URB no. %d\n",i); | ||
| 83 | if ((ret = usb_submit_urb(stream->urb_list[i],GFP_ATOMIC))) { | ||
| 84 | err("could not submit URB no. %d - get them all back",i); | ||
| 85 | usb_urb_kill(stream); | ||
| 86 | return ret; | ||
| 87 | } | ||
| 88 | stream->urbs_submitted++; | ||
| 89 | } | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | static int usb_free_stream_buffers(struct usb_data_stream *stream) | ||
| 94 | { | ||
| 95 | if (stream->state & USB_STATE_URB_BUF) { | ||
| 96 | while (stream->buf_num) { | ||
| 97 | stream->buf_num--; | ||
| 98 | deb_mem("freeing buffer %d\n",stream->buf_num); | ||
| 99 | usb_free_coherent(stream->udev, stream->buf_size, | ||
| 100 | stream->buf_list[stream->buf_num], | ||
| 101 | stream->dma_addr[stream->buf_num]); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | stream->state &= ~USB_STATE_URB_BUF; | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num, unsigned long size) | ||
| 111 | { | ||
| 112 | stream->buf_num = 0; | ||
| 113 | stream->buf_size = size; | ||
| 114 | |||
| 115 | deb_mem("all in all I will use %lu bytes for streaming\n",num*size); | ||
| 116 | |||
| 117 | for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) { | ||
| 118 | deb_mem("allocating buffer %d\n",stream->buf_num); | ||
| 119 | if (( stream->buf_list[stream->buf_num] = | ||
| 120 | usb_alloc_coherent(stream->udev, size, GFP_ATOMIC, | ||
| 121 | &stream->dma_addr[stream->buf_num]) ) == NULL) { | ||
| 122 | deb_mem("not enough memory for urb-buffer allocation.\n"); | ||
| 123 | usb_free_stream_buffers(stream); | ||
| 124 | return -ENOMEM; | ||
| 125 | } | ||
| 126 | deb_mem("buffer %d: %p (dma: %Lu)\n", | ||
| 127 | stream->buf_num, | ||
| 128 | stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num]); | ||
| 129 | memset(stream->buf_list[stream->buf_num],0,size); | ||
| 130 | stream->state |= USB_STATE_URB_BUF; | ||
| 131 | } | ||
| 132 | deb_mem("allocation successful\n"); | ||
| 133 | |||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | static int usb_bulk_urb_init(struct usb_data_stream *stream) | ||
| 138 | { | ||
| 139 | int i, j; | ||
| 140 | |||
| 141 | if ((i = usb_allocate_stream_buffers(stream,stream->props.count, | ||
| 142 | stream->props.u.bulk.buffersize)) < 0) | ||
| 143 | return i; | ||
| 144 | |||
| 145 | /* allocate the URBs */ | ||
| 146 | for (i = 0; i < stream->props.count; i++) { | ||
| 147 | stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); | ||
| 148 | if (!stream->urb_list[i]) { | ||
| 149 | deb_mem("not enough memory for urb_alloc_urb!.\n"); | ||
| 150 | for (j = 0; j < i; j++) | ||
| 151 | usb_free_urb(stream->urb_list[i]); | ||
| 152 | return -ENOMEM; | ||
| 153 | } | ||
| 154 | usb_fill_bulk_urb( stream->urb_list[i], stream->udev, | ||
| 155 | usb_rcvbulkpipe(stream->udev,stream->props.endpoint), | ||
| 156 | stream->buf_list[i], | ||
| 157 | stream->props.u.bulk.buffersize, | ||
| 158 | usb_urb_complete, stream); | ||
| 159 | |||
| 160 | stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
| 161 | stream->urb_list[i]->transfer_dma = stream->dma_addr[i]; | ||
| 162 | stream->urbs_initialized++; | ||
| 163 | } | ||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | static int usb_isoc_urb_init(struct usb_data_stream *stream) | ||
| 168 | { | ||
| 169 | int i,j; | ||
| 170 | |||
| 171 | if ((i = usb_allocate_stream_buffers(stream,stream->props.count, | ||
| 172 | stream->props.u.isoc.framesize*stream->props.u.isoc.framesperurb)) < 0) | ||
| 173 | return i; | ||
| 174 | |||
| 175 | /* allocate the URBs */ | ||
| 176 | for (i = 0; i < stream->props.count; i++) { | ||
| 177 | struct urb *urb; | ||
| 178 | int frame_offset = 0; | ||
| 179 | |||
| 180 | stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_ATOMIC); | ||
| 181 | if (!stream->urb_list[i]) { | ||
| 182 | deb_mem("not enough memory for urb_alloc_urb!\n"); | ||
| 183 | for (j = 0; j < i; j++) | ||
| 184 | usb_free_urb(stream->urb_list[i]); | ||
| 185 | return -ENOMEM; | ||
| 186 | } | ||
| 187 | |||
| 188 | urb = stream->urb_list[i]; | ||
| 189 | |||
| 190 | urb->dev = stream->udev; | ||
| 191 | urb->context = stream; | ||
| 192 | urb->complete = usb_urb_complete; | ||
| 193 | urb->pipe = usb_rcvisocpipe(stream->udev,stream->props.endpoint); | ||
| 194 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
| 195 | urb->interval = stream->props.u.isoc.interval; | ||
| 196 | urb->number_of_packets = stream->props.u.isoc.framesperurb; | ||
| 197 | urb->transfer_buffer_length = stream->buf_size; | ||
| 198 | urb->transfer_buffer = stream->buf_list[i]; | ||
| 199 | urb->transfer_dma = stream->dma_addr[i]; | ||
| 200 | |||
| 201 | for (j = 0; j < stream->props.u.isoc.framesperurb; j++) { | ||
| 202 | urb->iso_frame_desc[j].offset = frame_offset; | ||
| 203 | urb->iso_frame_desc[j].length = stream->props.u.isoc.framesize; | ||
| 204 | frame_offset += stream->props.u.isoc.framesize; | ||
| 205 | } | ||
| 206 | |||
| 207 | stream->urbs_initialized++; | ||
| 208 | } | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | int usb_urb_init(struct usb_data_stream *stream, struct usb_data_stream_properties *props) | ||
| 213 | { | ||
| 214 | if (stream == NULL || props == NULL) | ||
| 215 | return -EINVAL; | ||
| 216 | |||
| 217 | memcpy(&stream->props, props, sizeof(*props)); | ||
| 218 | |||
| 219 | usb_clear_halt(stream->udev,usb_rcvbulkpipe(stream->udev,stream->props.endpoint)); | ||
| 220 | |||
| 221 | if (stream->complete == NULL) { | ||
| 222 | err("there is no data callback - this doesn't make sense."); | ||
| 223 | return -EINVAL; | ||
| 224 | } | ||
| 225 | |||
| 226 | switch (stream->props.type) { | ||
| 227 | case USB_BULK: | ||
| 228 | return usb_bulk_urb_init(stream); | ||
| 229 | case USB_ISOC: | ||
| 230 | return usb_isoc_urb_init(stream); | ||
| 231 | default: | ||
| 232 | err("unknown URB-type for data transfer."); | ||
| 233 | return -EINVAL; | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | int usb_urb_exit(struct usb_data_stream *stream) | ||
| 238 | { | ||
| 239 | int i; | ||
| 240 | |||
| 241 | usb_urb_kill(stream); | ||
| 242 | |||
| 243 | for (i = 0; i < stream->urbs_initialized; i++) { | ||
| 244 | if (stream->urb_list[i] != NULL) { | ||
| 245 | deb_mem("freeing URB no. %d.\n",i); | ||
| 246 | /* free the URBs */ | ||
| 247 | usb_free_urb(stream->urb_list[i]); | ||
| 248 | } | ||
| 249 | } | ||
| 250 | stream->urbs_initialized = 0; | ||
| 251 | |||
| 252 | usb_free_stream_buffers(stream); | ||
| 253 | return 0; | ||
| 254 | } | ||
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c new file mode 100644 index 00000000000..2bb8d4cc8d8 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c | |||
| @@ -0,0 +1,387 @@ | |||
| 1 | /* DVB frontend part of the Linux driver for the TwinhanDTV StarBox USB2.0 | ||
| 2 | * DVB-S receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de> | ||
| 5 | * Metzler Brothers Systementwicklung GbR | ||
| 6 | * | ||
| 7 | * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de> | ||
| 8 | * | ||
| 9 | * Thanks to Twinhan who kindly provided hardware and information. | ||
| 10 | * | ||
| 11 | * This file can be removed soon, after the DST-driver is rewritten to provice | ||
| 12 | * the frontend-controlling separately. | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or modify it | ||
| 15 | * under the terms of the GNU General Public License as published by the Free | ||
| 16 | * Software Foundation, version 2. | ||
| 17 | * | ||
| 18 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | #include "vp702x.h" | ||
| 22 | |||
| 23 | struct vp702x_fe_state { | ||
| 24 | struct dvb_frontend fe; | ||
| 25 | struct dvb_usb_device *d; | ||
| 26 | |||
| 27 | struct dvb_frontend_ops ops; | ||
| 28 | |||
| 29 | fe_sec_voltage_t voltage; | ||
| 30 | fe_sec_tone_mode_t tone_mode; | ||
| 31 | |||
| 32 | u8 lnb_buf[8]; | ||
| 33 | |||
| 34 | u8 lock; | ||
| 35 | u8 sig; | ||
| 36 | u8 snr; | ||
| 37 | |||
| 38 | unsigned long next_status_check; | ||
| 39 | unsigned long status_check_interval; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static int vp702x_fe_refresh_state(struct vp702x_fe_state *st) | ||
| 43 | { | ||
| 44 | struct vp702x_device_state *dst = st->d->priv; | ||
| 45 | u8 *buf; | ||
| 46 | |||
| 47 | if (time_after(jiffies, st->next_status_check)) { | ||
| 48 | mutex_lock(&dst->buf_mutex); | ||
| 49 | buf = dst->buf; | ||
| 50 | |||
| 51 | vp702x_usb_in_op(st->d, READ_STATUS, 0, 0, buf, 10); | ||
| 52 | st->lock = buf[4]; | ||
| 53 | |||
| 54 | vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x11, 0, buf, 1); | ||
| 55 | st->snr = buf[0]; | ||
| 56 | |||
| 57 | vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x15, 0, buf, 1); | ||
| 58 | st->sig = buf[0]; | ||
| 59 | |||
| 60 | mutex_unlock(&dst->buf_mutex); | ||
| 61 | st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000; | ||
| 62 | } | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | static u8 vp702x_chksum(u8 *buf,int f, int count) | ||
| 67 | { | ||
| 68 | u8 s = 0; | ||
| 69 | int i; | ||
| 70 | for (i = f; i < f+count; i++) | ||
| 71 | s += buf[i]; | ||
| 72 | return ~s+1; | ||
| 73 | } | ||
| 74 | |||
| 75 | static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) | ||
| 76 | { | ||
| 77 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 78 | vp702x_fe_refresh_state(st); | ||
| 79 | deb_fe("%s\n",__func__); | ||
| 80 | |||
| 81 | if (st->lock == 0) | ||
| 82 | *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
| 83 | else | ||
| 84 | *status = 0; | ||
| 85 | |||
| 86 | if (*status & FE_HAS_LOCK) | ||
| 87 | st->status_check_interval = 1000; | ||
| 88 | else | ||
| 89 | st->status_check_interval = 250; | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | /* not supported by this Frontend */ | ||
| 94 | static int vp702x_fe_read_ber(struct dvb_frontend* fe, u32 *ber) | ||
| 95 | { | ||
| 96 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 97 | vp702x_fe_refresh_state(st); | ||
| 98 | *ber = 0; | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | /* not supported by this Frontend */ | ||
| 103 | static int vp702x_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | ||
| 104 | { | ||
| 105 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 106 | vp702x_fe_refresh_state(st); | ||
| 107 | *unc = 0; | ||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | static int vp702x_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) | ||
| 112 | { | ||
| 113 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 114 | vp702x_fe_refresh_state(st); | ||
| 115 | |||
| 116 | *strength = (st->sig << 8) | st->sig; | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
| 121 | { | ||
| 122 | u8 _snr; | ||
| 123 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 124 | vp702x_fe_refresh_state(st); | ||
| 125 | |||
| 126 | _snr = (st->snr & 0x1f) * 0xff / 0x1f; | ||
| 127 | *snr = (_snr << 8) | _snr; | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
| 132 | { | ||
| 133 | deb_fe("%s\n",__func__); | ||
| 134 | tune->min_delay_ms = 2000; | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int vp702x_fe_set_frontend(struct dvb_frontend* fe, | ||
| 139 | struct dvb_frontend_parameters *fep) | ||
| 140 | { | ||
| 141 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 142 | struct vp702x_device_state *dst = st->d->priv; | ||
| 143 | u32 freq = fep->frequency/1000; | ||
| 144 | /*CalFrequency*/ | ||
| 145 | /* u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */ | ||
| 146 | u64 sr; | ||
| 147 | u8 *cmd; | ||
| 148 | |||
| 149 | mutex_lock(&dst->buf_mutex); | ||
| 150 | |||
| 151 | cmd = dst->buf; | ||
| 152 | memset(cmd, 0, 10); | ||
| 153 | |||
| 154 | cmd[0] = (freq >> 8) & 0x7f; | ||
| 155 | cmd[1] = freq & 0xff; | ||
| 156 | cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */ | ||
| 157 | |||
| 158 | sr = (u64) (fep->u.qpsk.symbol_rate/1000) << 20; | ||
| 159 | do_div(sr,88000); | ||
| 160 | cmd[3] = (sr >> 12) & 0xff; | ||
| 161 | cmd[4] = (sr >> 4) & 0xff; | ||
| 162 | cmd[5] = (sr << 4) & 0xf0; | ||
| 163 | |||
| 164 | deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n", | ||
| 165 | fep->frequency,freq,freq, fep->u.qpsk.symbol_rate, | ||
| 166 | (unsigned long) sr, (unsigned long) sr); | ||
| 167 | |||
| 168 | /* if (fep->inversion == INVERSION_ON) | ||
| 169 | cmd[6] |= 0x80; */ | ||
| 170 | |||
| 171 | if (st->voltage == SEC_VOLTAGE_18) | ||
| 172 | cmd[6] |= 0x40; | ||
| 173 | |||
| 174 | /* if (fep->u.qpsk.symbol_rate > 8000000) | ||
| 175 | cmd[6] |= 0x20; | ||
| 176 | |||
| 177 | if (fep->frequency < 1531000) | ||
| 178 | cmd[6] |= 0x04; | ||
| 179 | |||
| 180 | if (st->tone_mode == SEC_TONE_ON) | ||
| 181 | cmd[6] |= 0x01;*/ | ||
| 182 | |||
| 183 | cmd[7] = vp702x_chksum(cmd,0,7); | ||
| 184 | |||
| 185 | st->status_check_interval = 250; | ||
| 186 | st->next_status_check = jiffies; | ||
| 187 | |||
| 188 | vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100); | ||
| 189 | |||
| 190 | if (cmd[2] == 0 && cmd[3] == 0) | ||
| 191 | deb_fe("tuning failed.\n"); | ||
| 192 | else | ||
| 193 | deb_fe("tuning succeeded.\n"); | ||
| 194 | |||
| 195 | mutex_unlock(&dst->buf_mutex); | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | static int vp702x_fe_init(struct dvb_frontend *fe) | ||
| 201 | { | ||
| 202 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 203 | deb_fe("%s\n",__func__); | ||
| 204 | vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0); | ||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int vp702x_fe_sleep(struct dvb_frontend *fe) | ||
| 209 | { | ||
| 210 | deb_fe("%s\n",__func__); | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | static int vp702x_fe_get_frontend(struct dvb_frontend* fe, | ||
| 215 | struct dvb_frontend_parameters *fep) | ||
| 216 | { | ||
| 217 | deb_fe("%s\n",__func__); | ||
| 218 | return 0; | ||
| 219 | } | ||
| 220 | |||
| 221 | static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, | ||
| 222 | struct dvb_diseqc_master_cmd *m) | ||
| 223 | { | ||
| 224 | u8 *cmd; | ||
| 225 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 226 | struct vp702x_device_state *dst = st->d->priv; | ||
| 227 | |||
| 228 | deb_fe("%s\n",__func__); | ||
| 229 | |||
| 230 | if (m->msg_len > 4) | ||
| 231 | return -EINVAL; | ||
| 232 | |||
| 233 | mutex_lock(&dst->buf_mutex); | ||
| 234 | |||
| 235 | cmd = dst->buf; | ||
| 236 | cmd[1] = SET_DISEQC_CMD; | ||
| 237 | cmd[2] = m->msg_len; | ||
| 238 | memcpy(&cmd[3], m->msg, m->msg_len); | ||
| 239 | cmd[7] = vp702x_chksum(cmd, 0, 7); | ||
| 240 | |||
| 241 | vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100); | ||
| 242 | |||
| 243 | if (cmd[2] == 0 && cmd[3] == 0) | ||
| 244 | deb_fe("diseqc cmd failed.\n"); | ||
| 245 | else | ||
| 246 | deb_fe("diseqc cmd succeeded.\n"); | ||
| 247 | |||
| 248 | mutex_unlock(&dst->buf_mutex); | ||
| 249 | |||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | |||
| 253 | static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) | ||
| 254 | { | ||
| 255 | deb_fe("%s\n",__func__); | ||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | ||
| 260 | { | ||
| 261 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 262 | struct vp702x_device_state *dst = st->d->priv; | ||
| 263 | u8 *buf; | ||
| 264 | |||
| 265 | deb_fe("%s\n",__func__); | ||
| 266 | |||
| 267 | st->tone_mode = tone; | ||
| 268 | |||
| 269 | if (tone == SEC_TONE_ON) | ||
| 270 | st->lnb_buf[2] = 0x02; | ||
| 271 | else | ||
| 272 | st->lnb_buf[2] = 0x00; | ||
| 273 | |||
| 274 | st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7); | ||
| 275 | |||
| 276 | mutex_lock(&dst->buf_mutex); | ||
| 277 | |||
| 278 | buf = dst->buf; | ||
| 279 | memcpy(buf, st->lnb_buf, 8); | ||
| 280 | |||
| 281 | vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100); | ||
| 282 | if (buf[2] == 0 && buf[3] == 0) | ||
| 283 | deb_fe("set_tone cmd failed.\n"); | ||
| 284 | else | ||
| 285 | deb_fe("set_tone cmd succeeded.\n"); | ||
| 286 | |||
| 287 | mutex_unlock(&dst->buf_mutex); | ||
| 288 | |||
| 289 | return 0; | ||
| 290 | } | ||
| 291 | |||
| 292 | static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t | ||
| 293 | voltage) | ||
| 294 | { | ||
| 295 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 296 | struct vp702x_device_state *dst = st->d->priv; | ||
| 297 | u8 *buf; | ||
| 298 | deb_fe("%s\n",__func__); | ||
| 299 | |||
| 300 | st->voltage = voltage; | ||
| 301 | |||
| 302 | if (voltage != SEC_VOLTAGE_OFF) | ||
| 303 | st->lnb_buf[4] = 0x01; | ||
| 304 | else | ||
| 305 | st->lnb_buf[4] = 0x00; | ||
| 306 | |||
| 307 | st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7); | ||
| 308 | |||
| 309 | mutex_lock(&dst->buf_mutex); | ||
| 310 | |||
| 311 | buf = dst->buf; | ||
| 312 | memcpy(buf, st->lnb_buf, 8); | ||
| 313 | |||
| 314 | vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100); | ||
| 315 | if (buf[2] == 0 && buf[3] == 0) | ||
| 316 | deb_fe("set_voltage cmd failed.\n"); | ||
| 317 | else | ||
| 318 | deb_fe("set_voltage cmd succeeded.\n"); | ||
| 319 | |||
| 320 | mutex_unlock(&dst->buf_mutex); | ||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | static void vp702x_fe_release(struct dvb_frontend* fe) | ||
| 325 | { | ||
| 326 | struct vp702x_fe_state *st = fe->demodulator_priv; | ||
| 327 | kfree(st); | ||
| 328 | } | ||
| 329 | |||
| 330 | static struct dvb_frontend_ops vp702x_fe_ops; | ||
| 331 | |||
| 332 | struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d) | ||
| 333 | { | ||
| 334 | struct vp702x_fe_state *s = kzalloc(sizeof(struct vp702x_fe_state), GFP_KERNEL); | ||
| 335 | if (s == NULL) | ||
| 336 | goto error; | ||
| 337 | |||
| 338 | s->d = d; | ||
| 339 | |||
| 340 | memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops)); | ||
| 341 | s->fe.demodulator_priv = s; | ||
| 342 | |||
| 343 | s->lnb_buf[1] = SET_LNB_POWER; | ||
| 344 | s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */ | ||
| 345 | |||
| 346 | return &s->fe; | ||
| 347 | error: | ||
| 348 | return NULL; | ||
| 349 | } | ||
| 350 | |||
| 351 | |||
| 352 | static struct dvb_frontend_ops vp702x_fe_ops = { | ||
| 353 | .info = { | ||
| 354 | .name = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S", | ||
| 355 | .type = FE_QPSK, | ||
| 356 | .frequency_min = 950000, | ||
| 357 | .frequency_max = 2150000, | ||
| 358 | .frequency_stepsize = 1000, /* kHz for QPSK frontends */ | ||
| 359 | .frequency_tolerance = 0, | ||
| 360 | .symbol_rate_min = 1000000, | ||
| 361 | .symbol_rate_max = 45000000, | ||
| 362 | .symbol_rate_tolerance = 500, /* ppm */ | ||
| 363 | .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 364 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | | ||
| 365 | FE_CAN_QPSK | | ||
| 366 | FE_CAN_FEC_AUTO | ||
| 367 | }, | ||
| 368 | .release = vp702x_fe_release, | ||
| 369 | |||
| 370 | .init = vp702x_fe_init, | ||
| 371 | .sleep = vp702x_fe_sleep, | ||
| 372 | |||
| 373 | .set_frontend = vp702x_fe_set_frontend, | ||
| 374 | .get_frontend = vp702x_fe_get_frontend, | ||
| 375 | .get_tune_settings = vp702x_fe_get_tune_settings, | ||
| 376 | |||
| 377 | .read_status = vp702x_fe_read_status, | ||
| 378 | .read_ber = vp702x_fe_read_ber, | ||
| 379 | .read_signal_strength = vp702x_fe_read_signal_strength, | ||
| 380 | .read_snr = vp702x_fe_read_snr, | ||
| 381 | .read_ucblocks = vp702x_fe_read_unc_blocks, | ||
| 382 | |||
| 383 | .diseqc_send_master_cmd = vp702x_fe_send_diseqc_msg, | ||
| 384 | .diseqc_send_burst = vp702x_fe_send_diseqc_burst, | ||
| 385 | .set_tone = vp702x_fe_set_tone, | ||
| 386 | .set_voltage = vp702x_fe_set_voltage, | ||
| 387 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c new file mode 100644 index 00000000000..54355f84a98 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp702x.c | |||
| @@ -0,0 +1,460 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the TwinhanDTV StarBox USB2.0 DVB-S | ||
| 2 | * receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de> | ||
| 5 | * Metzler Brothers Systementwicklung GbR | ||
| 6 | * | ||
| 7 | * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de> | ||
| 8 | * | ||
| 9 | * Thanks to Twinhan who kindly provided hardware and information. | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License as published by the Free | ||
| 13 | * Software Foundation, version 2. | ||
| 14 | * | ||
| 15 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 16 | */ | ||
| 17 | #include "vp702x.h" | ||
| 18 | #include <linux/mutex.h> | ||
| 19 | |||
| 20 | /* debug */ | ||
| 21 | int dvb_usb_vp702x_debug; | ||
| 22 | module_param_named(debug,dvb_usb_vp702x_debug, int, 0644); | ||
| 23 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 24 | |||
| 25 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 26 | |||
| 27 | struct vp702x_adapter_state { | ||
| 28 | int pid_filter_count; | ||
| 29 | int pid_filter_can_bypass; | ||
| 30 | u8 pid_filter_state; | ||
| 31 | }; | ||
| 32 | |||
| 33 | static int vp702x_usb_in_op_unlocked(struct dvb_usb_device *d, u8 req, | ||
| 34 | u16 value, u16 index, u8 *b, int blen) | ||
| 35 | { | ||
| 36 | int ret; | ||
| 37 | |||
| 38 | ret = usb_control_msg(d->udev, | ||
| 39 | usb_rcvctrlpipe(d->udev, 0), | ||
| 40 | req, | ||
| 41 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
| 42 | value, index, b, blen, | ||
| 43 | 2000); | ||
| 44 | |||
| 45 | if (ret < 0) { | ||
| 46 | warn("usb in operation failed. (%d)", ret); | ||
| 47 | ret = -EIO; | ||
| 48 | } else | ||
| 49 | ret = 0; | ||
| 50 | |||
| 51 | |||
| 52 | deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); | ||
| 53 | debug_dump(b,blen,deb_xfer); | ||
| 54 | |||
| 55 | return ret; | ||
| 56 | } | ||
| 57 | |||
| 58 | int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, | ||
| 59 | u16 index, u8 *b, int blen) | ||
| 60 | { | ||
| 61 | int ret; | ||
| 62 | |||
| 63 | mutex_lock(&d->usb_mutex); | ||
| 64 | ret = vp702x_usb_in_op_unlocked(d, req, value, index, b, blen); | ||
| 65 | mutex_unlock(&d->usb_mutex); | ||
| 66 | |||
| 67 | return ret; | ||
| 68 | } | ||
| 69 | |||
| 70 | int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value, | ||
| 71 | u16 index, u8 *b, int blen) | ||
| 72 | { | ||
| 73 | int ret; | ||
| 74 | deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); | ||
| 75 | debug_dump(b,blen,deb_xfer); | ||
| 76 | |||
| 77 | if ((ret = usb_control_msg(d->udev, | ||
| 78 | usb_sndctrlpipe(d->udev,0), | ||
| 79 | req, | ||
| 80 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
| 81 | value,index,b,blen, | ||
| 82 | 2000)) != blen) { | ||
| 83 | warn("usb out operation failed. (%d)",ret); | ||
| 84 | return -EIO; | ||
| 85 | } else | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, | ||
| 90 | u16 index, u8 *b, int blen) | ||
| 91 | { | ||
| 92 | int ret; | ||
| 93 | |||
| 94 | mutex_lock(&d->usb_mutex); | ||
| 95 | ret = vp702x_usb_out_op_unlocked(d, req, value, index, b, blen); | ||
| 96 | mutex_unlock(&d->usb_mutex); | ||
| 97 | |||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 101 | int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec) | ||
| 102 | { | ||
| 103 | int ret; | ||
| 104 | |||
| 105 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) | ||
| 106 | return ret; | ||
| 107 | |||
| 108 | ret = vp702x_usb_out_op_unlocked(d, REQUEST_OUT, 0, 0, o, olen); | ||
| 109 | msleep(msec); | ||
| 110 | ret = vp702x_usb_in_op_unlocked(d, REQUEST_IN, 0, 0, i, ilen); | ||
| 111 | |||
| 112 | mutex_unlock(&d->usb_mutex); | ||
| 113 | return ret; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, | ||
| 117 | int olen, u8 *i, int ilen, int msec) | ||
| 118 | { | ||
| 119 | struct vp702x_device_state *st = d->priv; | ||
| 120 | int ret = 0; | ||
| 121 | u8 *buf; | ||
| 122 | int buflen = max(olen + 2, ilen + 1); | ||
| 123 | |||
| 124 | ret = mutex_lock_interruptible(&st->buf_mutex); | ||
| 125 | if (ret < 0) | ||
| 126 | return ret; | ||
| 127 | |||
| 128 | if (buflen > st->buf_len) { | ||
| 129 | buf = kmalloc(buflen, GFP_KERNEL); | ||
| 130 | if (!buf) { | ||
| 131 | mutex_unlock(&st->buf_mutex); | ||
| 132 | return -ENOMEM; | ||
| 133 | } | ||
| 134 | info("successfully reallocated a bigger buffer"); | ||
| 135 | kfree(st->buf); | ||
| 136 | st->buf = buf; | ||
| 137 | st->buf_len = buflen; | ||
| 138 | } else { | ||
| 139 | buf = st->buf; | ||
| 140 | } | ||
| 141 | |||
| 142 | buf[0] = 0x00; | ||
| 143 | buf[1] = cmd; | ||
| 144 | memcpy(&buf[2], o, olen); | ||
| 145 | |||
| 146 | ret = vp702x_usb_inout_op(d, buf, olen+2, buf, ilen+1, msec); | ||
| 147 | |||
| 148 | if (ret == 0) | ||
| 149 | memcpy(i, &buf[1], ilen); | ||
| 150 | mutex_unlock(&st->buf_mutex); | ||
| 151 | |||
| 152 | return ret; | ||
| 153 | } | ||
| 154 | |||
| 155 | static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass) | ||
| 156 | { | ||
| 157 | int ret; | ||
| 158 | struct vp702x_device_state *st = adap->dev->priv; | ||
| 159 | u8 *buf; | ||
| 160 | |||
| 161 | mutex_lock(&st->buf_mutex); | ||
| 162 | |||
| 163 | buf = st->buf; | ||
| 164 | memset(buf, 0, 16); | ||
| 165 | |||
| 166 | ret = vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, | ||
| 167 | 0, buf, 16); | ||
| 168 | mutex_unlock(&st->buf_mutex); | ||
| 169 | return ret; | ||
| 170 | } | ||
| 171 | |||
| 172 | static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state) | ||
| 173 | { | ||
| 174 | int ret; | ||
| 175 | struct vp702x_device_state *st = adap->dev->priv; | ||
| 176 | u8 *buf; | ||
| 177 | |||
| 178 | mutex_lock(&st->buf_mutex); | ||
| 179 | |||
| 180 | buf = st->buf; | ||
| 181 | memset(buf, 0, 16); | ||
| 182 | ret = vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, | ||
| 183 | 0, buf, 16); | ||
| 184 | |||
| 185 | mutex_unlock(&st->buf_mutex); | ||
| 186 | |||
| 187 | return ret; | ||
| 188 | } | ||
| 189 | |||
| 190 | static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff) | ||
| 191 | { | ||
| 192 | struct vp702x_adapter_state *st = adap->priv; | ||
| 193 | struct vp702x_device_state *dst = adap->dev->priv; | ||
| 194 | u8 *buf; | ||
| 195 | |||
| 196 | if (onoff) | ||
| 197 | st->pid_filter_state |= (1 << id); | ||
| 198 | else { | ||
| 199 | st->pid_filter_state &= ~(1 << id); | ||
| 200 | pid = 0xffff; | ||
| 201 | } | ||
| 202 | |||
| 203 | id = 0x10 + id*2; | ||
| 204 | |||
| 205 | vp702x_set_pld_state(adap, st->pid_filter_state); | ||
| 206 | |||
| 207 | mutex_lock(&dst->buf_mutex); | ||
| 208 | |||
| 209 | buf = dst->buf; | ||
| 210 | memset(buf, 0, 16); | ||
| 211 | vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16); | ||
| 212 | vp702x_usb_in_op(adap->dev, 0xe0, (((pid ) & 0xff) << 8) | (id+1), 0, buf, 16); | ||
| 213 | |||
| 214 | mutex_unlock(&dst->buf_mutex); | ||
| 215 | |||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | |||
| 220 | static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap) | ||
| 221 | { | ||
| 222 | struct vp702x_adapter_state *st = adap->priv; | ||
| 223 | struct vp702x_device_state *dst = adap->dev->priv; | ||
| 224 | int i; | ||
| 225 | u8 *b; | ||
| 226 | |||
| 227 | st->pid_filter_count = 8; | ||
| 228 | st->pid_filter_can_bypass = 1; | ||
| 229 | st->pid_filter_state = 0x00; | ||
| 230 | |||
| 231 | vp702x_set_pld_mode(adap, 1); /* bypass */ | ||
| 232 | |||
| 233 | for (i = 0; i < st->pid_filter_count; i++) | ||
| 234 | vp702x_set_pid(adap, 0xffff, i, 1); | ||
| 235 | |||
| 236 | mutex_lock(&dst->buf_mutex); | ||
| 237 | b = dst->buf; | ||
| 238 | memset(b, 0, 10); | ||
| 239 | vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10); | ||
| 240 | vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10); | ||
| 241 | vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10); | ||
| 242 | mutex_unlock(&dst->buf_mutex); | ||
| 243 | /*vp702x_set_pld_mode(d, 0); // filter */ | ||
| 244 | |||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | |||
| 248 | static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
| 249 | { | ||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* keys for the enclosed remote control */ | ||
| 254 | static struct rc_map_table rc_map_vp702x_table[] = { | ||
| 255 | { 0x0001, KEY_1 }, | ||
| 256 | { 0x0002, KEY_2 }, | ||
| 257 | }; | ||
| 258 | |||
| 259 | /* remote control stuff (does not work with my box) */ | ||
| 260 | static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 261 | { | ||
| 262 | u8 *key; | ||
| 263 | int i; | ||
| 264 | |||
| 265 | /* remove the following return to enabled remote querying */ | ||
| 266 | return 0; | ||
| 267 | |||
| 268 | key = kmalloc(10, GFP_KERNEL); | ||
| 269 | if (!key) | ||
| 270 | return -ENOMEM; | ||
| 271 | |||
| 272 | vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10); | ||
| 273 | |||
| 274 | deb_rc("remote query key: %x %d\n",key[1],key[1]); | ||
| 275 | |||
| 276 | if (key[1] == 0x44) { | ||
| 277 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 278 | kfree(key); | ||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | for (i = 0; i < ARRAY_SIZE(rc_map_vp702x_table); i++) | ||
| 283 | if (rc5_custom(&rc_map_vp702x_table[i]) == key[1]) { | ||
| 284 | *state = REMOTE_KEY_PRESSED; | ||
| 285 | *event = rc_map_vp702x_table[i].keycode; | ||
| 286 | break; | ||
| 287 | } | ||
| 288 | kfree(key); | ||
| 289 | return 0; | ||
| 290 | } | ||
| 291 | |||
| 292 | |||
| 293 | static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) | ||
| 294 | { | ||
| 295 | u8 i, *buf; | ||
| 296 | struct vp702x_device_state *st = d->priv; | ||
| 297 | |||
| 298 | mutex_lock(&st->buf_mutex); | ||
| 299 | buf = st->buf; | ||
| 300 | for (i = 6; i < 12; i++) | ||
| 301 | vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1); | ||
| 302 | |||
| 303 | memcpy(mac, buf, 6); | ||
| 304 | mutex_unlock(&st->buf_mutex); | ||
| 305 | return 0; | ||
| 306 | } | ||
| 307 | |||
| 308 | static int vp702x_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 309 | { | ||
| 310 | u8 buf[10] = { 0 }; | ||
| 311 | |||
| 312 | vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0); | ||
| 313 | |||
| 314 | if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, | ||
| 315 | buf, 10, 10)) | ||
| 316 | return -EIO; | ||
| 317 | |||
| 318 | buf[9] = '\0'; | ||
| 319 | info("system string: %s",&buf[1]); | ||
| 320 | |||
| 321 | vp702x_init_pid_filter(adap); | ||
| 322 | |||
| 323 | adap->fe = vp702x_fe_attach(adap->dev); | ||
| 324 | vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0); | ||
| 325 | |||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static struct dvb_usb_device_properties vp702x_properties; | ||
| 330 | |||
| 331 | static int vp702x_usb_probe(struct usb_interface *intf, | ||
| 332 | const struct usb_device_id *id) | ||
| 333 | { | ||
| 334 | struct dvb_usb_device *d; | ||
| 335 | struct vp702x_device_state *st; | ||
| 336 | int ret; | ||
| 337 | |||
| 338 | ret = dvb_usb_device_init(intf, &vp702x_properties, | ||
| 339 | THIS_MODULE, &d, adapter_nr); | ||
| 340 | if (ret) | ||
| 341 | goto out; | ||
| 342 | |||
| 343 | st = d->priv; | ||
| 344 | st->buf_len = 16; | ||
| 345 | st->buf = kmalloc(st->buf_len, GFP_KERNEL); | ||
| 346 | if (!st->buf) { | ||
| 347 | ret = -ENOMEM; | ||
| 348 | dvb_usb_device_exit(intf); | ||
| 349 | goto out; | ||
| 350 | } | ||
| 351 | mutex_init(&st->buf_mutex); | ||
| 352 | |||
| 353 | out: | ||
| 354 | return ret; | ||
| 355 | |||
| 356 | } | ||
| 357 | |||
| 358 | static void vp702x_usb_disconnect(struct usb_interface *intf) | ||
| 359 | { | ||
| 360 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
| 361 | struct vp702x_device_state *st = d->priv; | ||
| 362 | mutex_lock(&st->buf_mutex); | ||
| 363 | kfree(st->buf); | ||
| 364 | mutex_unlock(&st->buf_mutex); | ||
| 365 | dvb_usb_device_exit(intf); | ||
| 366 | } | ||
| 367 | |||
| 368 | static struct usb_device_id vp702x_usb_table [] = { | ||
| 369 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_COLD) }, | ||
| 370 | // { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) }, | ||
| 371 | // { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) }, | ||
| 372 | { 0 }, | ||
| 373 | }; | ||
| 374 | MODULE_DEVICE_TABLE(usb, vp702x_usb_table); | ||
| 375 | |||
| 376 | static struct dvb_usb_device_properties vp702x_properties = { | ||
| 377 | .usb_ctrl = CYPRESS_FX2, | ||
| 378 | .firmware = "dvb-usb-vp702x-02.fw", | ||
| 379 | .no_reconnect = 1, | ||
| 380 | |||
| 381 | .size_of_priv = sizeof(struct vp702x_device_state), | ||
| 382 | |||
| 383 | .num_adapters = 1, | ||
| 384 | .adapter = { | ||
| 385 | { | ||
| 386 | .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, | ||
| 387 | |||
| 388 | .streaming_ctrl = vp702x_streaming_ctrl, | ||
| 389 | .frontend_attach = vp702x_frontend_attach, | ||
| 390 | |||
| 391 | /* parameter for the MPEG2-data transfer */ | ||
| 392 | .stream = { | ||
| 393 | .type = USB_BULK, | ||
| 394 | .count = 10, | ||
| 395 | .endpoint = 0x02, | ||
| 396 | .u = { | ||
| 397 | .bulk = { | ||
| 398 | .buffersize = 4096, | ||
| 399 | } | ||
| 400 | } | ||
| 401 | }, | ||
| 402 | .size_of_priv = sizeof(struct vp702x_adapter_state), | ||
| 403 | } | ||
| 404 | }, | ||
| 405 | .read_mac_address = vp702x_read_mac_addr, | ||
| 406 | |||
| 407 | .rc.legacy = { | ||
| 408 | .rc_map_table = rc_map_vp702x_table, | ||
| 409 | .rc_map_size = ARRAY_SIZE(rc_map_vp702x_table), | ||
| 410 | .rc_interval = 400, | ||
| 411 | .rc_query = vp702x_rc_query, | ||
| 412 | }, | ||
| 413 | |||
| 414 | .num_device_descs = 1, | ||
| 415 | .devices = { | ||
| 416 | { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7021)", | ||
| 417 | .cold_ids = { &vp702x_usb_table[0], NULL }, | ||
| 418 | .warm_ids = { NULL }, | ||
| 419 | }, | ||
| 420 | /* { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)", | ||
| 421 | .cold_ids = { &vp702x_usb_table[2], NULL }, | ||
| 422 | .warm_ids = { &vp702x_usb_table[3], NULL }, | ||
| 423 | }, | ||
| 424 | */ { NULL }, | ||
| 425 | } | ||
| 426 | }; | ||
| 427 | |||
| 428 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 429 | static struct usb_driver vp702x_usb_driver = { | ||
| 430 | .name = "dvb_usb_vp702x", | ||
| 431 | .probe = vp702x_usb_probe, | ||
| 432 | .disconnect = vp702x_usb_disconnect, | ||
| 433 | .id_table = vp702x_usb_table, | ||
| 434 | }; | ||
| 435 | |||
| 436 | /* module stuff */ | ||
| 437 | static int __init vp702x_usb_module_init(void) | ||
| 438 | { | ||
| 439 | int result; | ||
| 440 | if ((result = usb_register(&vp702x_usb_driver))) { | ||
| 441 | err("usb_register failed. (%d)",result); | ||
| 442 | return result; | ||
| 443 | } | ||
| 444 | |||
| 445 | return 0; | ||
| 446 | } | ||
| 447 | |||
| 448 | static void __exit vp702x_usb_module_exit(void) | ||
| 449 | { | ||
| 450 | /* deregister this driver from the USB subsystem */ | ||
| 451 | usb_deregister(&vp702x_usb_driver); | ||
| 452 | } | ||
| 453 | |||
| 454 | module_init(vp702x_usb_module_init); | ||
| 455 | module_exit(vp702x_usb_module_exit); | ||
| 456 | |||
| 457 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 458 | MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones"); | ||
| 459 | MODULE_VERSION("1.0"); | ||
| 460 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h new file mode 100644 index 00000000000..20b90055e7a --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp702x.h | |||
| @@ -0,0 +1,113 @@ | |||
| 1 | #ifndef _DVB_USB_VP7021_H_ | ||
| 2 | #define _DVB_USB_VP7021_H_ | ||
| 3 | |||
| 4 | #define DVB_USB_LOG_PREFIX "vp702x" | ||
| 5 | #include "dvb-usb.h" | ||
| 6 | |||
| 7 | extern int dvb_usb_vp702x_debug; | ||
| 8 | #define deb_info(args...) dprintk(dvb_usb_vp702x_debug,0x01,args) | ||
| 9 | #define deb_xfer(args...) dprintk(dvb_usb_vp702x_debug,0x02,args) | ||
| 10 | #define deb_rc(args...) dprintk(dvb_usb_vp702x_debug,0x04,args) | ||
| 11 | #define deb_fe(args...) dprintk(dvb_usb_vp702x_debug,0x08,args) | ||
| 12 | |||
| 13 | /* commands are read and written with USB control messages */ | ||
| 14 | |||
| 15 | /* consecutive read/write operation */ | ||
| 16 | #define REQUEST_OUT 0xB2 | ||
| 17 | #define REQUEST_IN 0xB3 | ||
| 18 | |||
| 19 | /* the out-buffer of these consecutive operations contain sub-commands when b[0] = 0 | ||
| 20 | * request: 0xB2; i: 0; v: 0; b[0] = 0, b[1] = subcmd, additional buffer | ||
| 21 | * the returning buffer looks as follows | ||
| 22 | * request: 0xB3; i: 0; v: 0; b[0] = 0xB3, additional buffer */ | ||
| 23 | |||
| 24 | #define GET_TUNER_STATUS 0x05 | ||
| 25 | /* additional in buffer: | ||
| 26 | * 0 1 2 3 4 5 6 7 8 | ||
| 27 | * N/A N/A 0x05 signal-quality N/A N/A signal-strength lock==0 N/A */ | ||
| 28 | |||
| 29 | #define GET_SYSTEM_STRING 0x06 | ||
| 30 | /* additional in buffer: | ||
| 31 | * 0 1 2 3 4 5 6 7 8 | ||
| 32 | * N/A 'U' 'S' 'B' '7' '0' '2' 'X' N/A */ | ||
| 33 | |||
| 34 | #define SET_DISEQC_CMD 0x08 | ||
| 35 | /* additional out buffer: | ||
| 36 | * 0 1 2 3 4 | ||
| 37 | * len X1 X2 X3 X4 | ||
| 38 | * additional in buffer: | ||
| 39 | * 0 1 2 | ||
| 40 | * N/A 0 0 b[1] == b[2] == 0 -> success, failure otherwise */ | ||
| 41 | |||
| 42 | #define SET_LNB_POWER 0x09 | ||
| 43 | /* additional out buffer: | ||
| 44 | * 0 1 2 | ||
| 45 | * 0x00 0xff 1 = on, 0 = off | ||
| 46 | * additional in buffer: | ||
| 47 | * 0 1 2 | ||
| 48 | * N/A 0 0 b[1] == b[2] == 0 -> success failure otherwise */ | ||
| 49 | |||
| 50 | #define GET_MAC_ADDRESS 0x0A | ||
| 51 | /* #define GET_MAC_ADDRESS 0x0B */ | ||
| 52 | /* additional in buffer: | ||
| 53 | * 0 1 2 3 4 5 6 7 8 | ||
| 54 | * N/A N/A 0x0A or 0x0B MAC0 MAC1 MAC2 MAC3 MAC4 MAC5 */ | ||
| 55 | |||
| 56 | #define SET_PID_FILTER 0x11 | ||
| 57 | /* additional in buffer: | ||
| 58 | * 0 1 ... 14 15 16 | ||
| 59 | * PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */ | ||
| 60 | |||
| 61 | /* request: 0xB2; i: 0; v: 0; | ||
| 62 | * b[0] != 0 -> tune and lock a channel | ||
| 63 | * 0 1 2 3 4 5 6 7 | ||
| 64 | * freq0 freq1 divstep srate0 srate1 srate2 flag chksum | ||
| 65 | */ | ||
| 66 | |||
| 67 | /* one direction requests */ | ||
| 68 | #define READ_REMOTE_REQ 0xB4 | ||
| 69 | /* IN i: 0; v: 0; b[0] == request, b[1] == key */ | ||
| 70 | |||
| 71 | #define READ_PID_NUMBER_REQ 0xB5 | ||
| 72 | /* IN i: 0; v: 0; b[0] == request, b[1] == 0, b[2] = pid number */ | ||
| 73 | |||
| 74 | #define WRITE_EEPROM_REQ 0xB6 | ||
| 75 | /* OUT i: offset; v: value to write; no extra buffer */ | ||
| 76 | |||
| 77 | #define READ_EEPROM_REQ 0xB7 | ||
| 78 | /* IN i: bufferlen; v: offset; buffer with bufferlen bytes */ | ||
| 79 | |||
| 80 | #define READ_STATUS 0xB8 | ||
| 81 | /* IN i: 0; v: 0; bufferlen 10 */ | ||
| 82 | |||
| 83 | #define READ_TUNER_REG_REQ 0xB9 | ||
| 84 | /* IN i: 0; v: register; b[0] = value */ | ||
| 85 | |||
| 86 | #define READ_FX2_REG_REQ 0xBA | ||
| 87 | /* IN i: offset; v: 0; b[0] = value */ | ||
| 88 | |||
| 89 | #define WRITE_FX2_REG_REQ 0xBB | ||
| 90 | /* OUT i: offset; v: value to write; 1 byte extra buffer */ | ||
| 91 | |||
| 92 | #define SET_TUNER_POWER_REQ 0xBC | ||
| 93 | /* IN i: 0 = power off, 1 = power on */ | ||
| 94 | |||
| 95 | #define WRITE_TUNER_REG_REQ 0xBD | ||
| 96 | /* IN i: register, v: value to write, no extra buffer */ | ||
| 97 | |||
| 98 | #define RESET_TUNER 0xBE | ||
| 99 | /* IN i: 0, v: 0, no extra buffer */ | ||
| 100 | |||
| 101 | struct vp702x_device_state { | ||
| 102 | struct mutex buf_mutex; | ||
| 103 | int buf_len; | ||
| 104 | u8 *buf; | ||
| 105 | }; | ||
| 106 | |||
| 107 | |||
| 108 | extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d); | ||
| 109 | |||
| 110 | extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); | ||
| 111 | extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); | ||
| 112 | |||
| 113 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c new file mode 100644 index 00000000000..8452eef9032 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c | |||
| @@ -0,0 +1,192 @@ | |||
| 1 | /* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0 | ||
| 2 | * DVB-T receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 5 | * | ||
| 6 | * Thanks to Twinhan who kindly provided hardware and information. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation, version 2. | ||
| 11 | * | ||
| 12 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | #include "vp7045.h" | ||
| 16 | |||
| 17 | /* It is a Zarlink MT352 within a Samsung Tuner (DNOS404ZH102A) - 040929 - AAT | ||
| 18 | * | ||
| 19 | * Programming is hidden inside the firmware, so set_frontend is very easy. | ||
| 20 | * Even though there is a Firmware command that one can use to access the demod | ||
| 21 | * via its registers. This is used for status information. | ||
| 22 | */ | ||
| 23 | |||
| 24 | struct vp7045_fe_state { | ||
| 25 | struct dvb_frontend fe; | ||
| 26 | struct dvb_usb_device *d; | ||
| 27 | }; | ||
| 28 | |||
| 29 | static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) | ||
| 30 | { | ||
| 31 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
| 32 | u8 s0 = vp7045_read_reg(state->d,0x00), | ||
| 33 | s1 = vp7045_read_reg(state->d,0x01), | ||
| 34 | s3 = vp7045_read_reg(state->d,0x03); | ||
| 35 | |||
| 36 | *status = 0; | ||
| 37 | if (s0 & (1 << 4)) | ||
| 38 | *status |= FE_HAS_CARRIER; | ||
| 39 | if (s0 & (1 << 1)) | ||
| 40 | *status |= FE_HAS_VITERBI; | ||
| 41 | if (s0 & (1 << 5)) | ||
| 42 | *status |= FE_HAS_LOCK; | ||
| 43 | if (s1 & (1 << 1)) | ||
| 44 | *status |= FE_HAS_SYNC; | ||
| 45 | if (s3 & (1 << 6)) | ||
| 46 | *status |= FE_HAS_SIGNAL; | ||
| 47 | |||
| 48 | if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != | ||
| 49 | (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) | ||
| 50 | *status &= ~FE_HAS_LOCK; | ||
| 51 | |||
| 52 | return 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | static int vp7045_fe_read_ber(struct dvb_frontend* fe, u32 *ber) | ||
| 56 | { | ||
| 57 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
| 58 | *ber = (vp7045_read_reg(state->d, 0x0D) << 16) | | ||
| 59 | (vp7045_read_reg(state->d, 0x0E) << 8) | | ||
| 60 | vp7045_read_reg(state->d, 0x0F); | ||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int vp7045_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | ||
| 65 | { | ||
| 66 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
| 67 | *unc = (vp7045_read_reg(state->d, 0x10) << 8) | | ||
| 68 | vp7045_read_reg(state->d, 0x11); | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | static int vp7045_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) | ||
| 73 | { | ||
| 74 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
| 75 | u16 signal = (vp7045_read_reg(state->d, 0x14) << 8) | | ||
| 76 | vp7045_read_reg(state->d, 0x15); | ||
| 77 | |||
| 78 | *strength = ~signal; | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int vp7045_fe_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
| 83 | { | ||
| 84 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
| 85 | u8 _snr = vp7045_read_reg(state->d, 0x09); | ||
| 86 | *snr = (_snr << 8) | _snr; | ||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int vp7045_fe_init(struct dvb_frontend* fe) | ||
| 91 | { | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int vp7045_fe_sleep(struct dvb_frontend* fe) | ||
| 96 | { | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
| 101 | { | ||
| 102 | tune->min_delay_ms = 800; | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | static int vp7045_fe_set_frontend(struct dvb_frontend* fe, | ||
| 107 | struct dvb_frontend_parameters *fep) | ||
| 108 | { | ||
| 109 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
| 110 | u8 buf[5]; | ||
| 111 | u32 freq = fep->frequency / 1000; | ||
| 112 | |||
| 113 | buf[0] = (freq >> 16) & 0xff; | ||
| 114 | buf[1] = (freq >> 8) & 0xff; | ||
| 115 | buf[2] = freq & 0xff; | ||
| 116 | buf[3] = 0; | ||
| 117 | |||
| 118 | switch (fep->u.ofdm.bandwidth) { | ||
| 119 | case BANDWIDTH_8_MHZ: buf[4] = 8; break; | ||
| 120 | case BANDWIDTH_7_MHZ: buf[4] = 7; break; | ||
| 121 | case BANDWIDTH_6_MHZ: buf[4] = 6; break; | ||
| 122 | case BANDWIDTH_AUTO: return -EOPNOTSUPP; | ||
| 123 | default: | ||
| 124 | return -EINVAL; | ||
| 125 | } | ||
| 126 | |||
| 127 | vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200); | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int vp7045_fe_get_frontend(struct dvb_frontend* fe, | ||
| 132 | struct dvb_frontend_parameters *fep) | ||
| 133 | { | ||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | static void vp7045_fe_release(struct dvb_frontend* fe) | ||
| 138 | { | ||
| 139 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
| 140 | kfree(state); | ||
| 141 | } | ||
| 142 | |||
| 143 | static struct dvb_frontend_ops vp7045_fe_ops; | ||
| 144 | |||
| 145 | struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d) | ||
| 146 | { | ||
| 147 | struct vp7045_fe_state *s = kzalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL); | ||
| 148 | if (s == NULL) | ||
| 149 | goto error; | ||
| 150 | |||
| 151 | s->d = d; | ||
| 152 | memcpy(&s->fe.ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops)); | ||
| 153 | s->fe.demodulator_priv = s; | ||
| 154 | |||
| 155 | return &s->fe; | ||
| 156 | error: | ||
| 157 | return NULL; | ||
| 158 | } | ||
| 159 | |||
| 160 | |||
| 161 | static struct dvb_frontend_ops vp7045_fe_ops = { | ||
| 162 | .info = { | ||
| 163 | .name = "Twinhan VP7045/46 USB DVB-T", | ||
| 164 | .type = FE_OFDM, | ||
| 165 | .frequency_min = 44250000, | ||
| 166 | .frequency_max = 867250000, | ||
| 167 | .frequency_stepsize = 1000, | ||
| 168 | .caps = FE_CAN_INVERSION_AUTO | | ||
| 169 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 170 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
| 171 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
| 172 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
| 173 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
| 174 | FE_CAN_RECOVER | | ||
| 175 | FE_CAN_HIERARCHY_AUTO, | ||
| 176 | }, | ||
| 177 | |||
| 178 | .release = vp7045_fe_release, | ||
| 179 | |||
| 180 | .init = vp7045_fe_init, | ||
| 181 | .sleep = vp7045_fe_sleep, | ||
| 182 | |||
| 183 | .set_frontend = vp7045_fe_set_frontend, | ||
| 184 | .get_frontend = vp7045_fe_get_frontend, | ||
| 185 | .get_tune_settings = vp7045_fe_get_tune_settings, | ||
| 186 | |||
| 187 | .read_status = vp7045_fe_read_status, | ||
| 188 | .read_ber = vp7045_fe_read_ber, | ||
| 189 | .read_signal_strength = vp7045_fe_read_signal_strength, | ||
| 190 | .read_snr = vp7045_fe_read_snr, | ||
| 191 | .read_ucblocks = vp7045_fe_read_unc_blocks, | ||
| 192 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c new file mode 100644 index 00000000000..536c16c943b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp7045.c | |||
| @@ -0,0 +1,318 @@ | |||
| 1 | /* DVB USB compliant Linux driver for the | ||
| 2 | * - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver | ||
| 3 | * - DigitalNow TinyUSB2 DVB-t receiver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 6 | * | ||
| 7 | * Thanks to Twinhan who kindly provided hardware and information. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the Free | ||
| 11 | * Software Foundation, version 2. | ||
| 12 | * | ||
| 13 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 14 | */ | ||
| 15 | #include "vp7045.h" | ||
| 16 | |||
| 17 | /* debug */ | ||
| 18 | static int dvb_usb_vp7045_debug; | ||
| 19 | module_param_named(debug,dvb_usb_vp7045_debug, int, 0644); | ||
| 20 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); | ||
| 21 | |||
| 22 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 23 | |||
| 24 | #define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args) | ||
| 25 | #define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args) | ||
| 26 | #define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args) | ||
| 27 | |||
| 28 | int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec) | ||
| 29 | { | ||
| 30 | int ret = 0; | ||
| 31 | u8 *buf = d->priv; | ||
| 32 | |||
| 33 | buf[0] = cmd; | ||
| 34 | |||
| 35 | if (outlen > 19) | ||
| 36 | outlen = 19; | ||
| 37 | |||
| 38 | if (inlen > 11) | ||
| 39 | inlen = 11; | ||
| 40 | |||
| 41 | ret = mutex_lock_interruptible(&d->usb_mutex); | ||
| 42 | if (ret) | ||
| 43 | return ret; | ||
| 44 | |||
| 45 | if (out != NULL && outlen > 0) | ||
| 46 | memcpy(&buf[1], out, outlen); | ||
| 47 | |||
| 48 | deb_xfer("out buffer: "); | ||
| 49 | debug_dump(buf, outlen+1, deb_xfer); | ||
| 50 | |||
| 51 | |||
| 52 | if (usb_control_msg(d->udev, | ||
| 53 | usb_sndctrlpipe(d->udev,0), | ||
| 54 | TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, | ||
| 55 | buf, 20, 2000) != 20) { | ||
| 56 | err("USB control message 'out' went wrong."); | ||
| 57 | ret = -EIO; | ||
| 58 | goto unlock; | ||
| 59 | } | ||
| 60 | |||
| 61 | msleep(msec); | ||
| 62 | |||
| 63 | if (usb_control_msg(d->udev, | ||
| 64 | usb_rcvctrlpipe(d->udev,0), | ||
| 65 | TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | ||
| 66 | buf, 12, 2000) != 12) { | ||
| 67 | err("USB control message 'in' went wrong."); | ||
| 68 | ret = -EIO; | ||
| 69 | goto unlock; | ||
| 70 | } | ||
| 71 | |||
| 72 | deb_xfer("in buffer: "); | ||
| 73 | debug_dump(buf, 12, deb_xfer); | ||
| 74 | |||
| 75 | if (in != NULL && inlen > 0) | ||
| 76 | memcpy(in, &buf[1], inlen); | ||
| 77 | |||
| 78 | unlock: | ||
| 79 | mutex_unlock(&d->usb_mutex); | ||
| 80 | |||
| 81 | return ret; | ||
| 82 | } | ||
| 83 | |||
| 84 | u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg) | ||
| 85 | { | ||
| 86 | u8 obuf[2] = { 0 },v; | ||
| 87 | obuf[1] = reg; | ||
| 88 | |||
| 89 | vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30); | ||
| 90 | |||
| 91 | return v; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
| 95 | { | ||
| 96 | u8 v = onoff; | ||
| 97 | return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150); | ||
| 98 | } | ||
| 99 | |||
| 100 | /* remote control stuff */ | ||
| 101 | |||
| 102 | /* The keymapping struct. Somehow this should be loaded to the driver, but | ||
| 103 | * currently it is hardcoded. */ | ||
| 104 | static struct rc_map_table rc_map_vp7045_table[] = { | ||
| 105 | { 0x0016, KEY_POWER }, | ||
| 106 | { 0x0010, KEY_MUTE }, | ||
| 107 | { 0x0003, KEY_1 }, | ||
| 108 | { 0x0001, KEY_2 }, | ||
| 109 | { 0x0006, KEY_3 }, | ||
| 110 | { 0x0009, KEY_4 }, | ||
| 111 | { 0x001d, KEY_5 }, | ||
| 112 | { 0x001f, KEY_6 }, | ||
| 113 | { 0x000d, KEY_7 }, | ||
| 114 | { 0x0019, KEY_8 }, | ||
| 115 | { 0x001b, KEY_9 }, | ||
| 116 | { 0x0015, KEY_0 }, | ||
| 117 | { 0x0005, KEY_CHANNELUP }, | ||
| 118 | { 0x0002, KEY_CHANNELDOWN }, | ||
| 119 | { 0x001e, KEY_VOLUMEUP }, | ||
| 120 | { 0x000a, KEY_VOLUMEDOWN }, | ||
| 121 | { 0x0011, KEY_RECORD }, | ||
| 122 | { 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */ | ||
| 123 | { 0x0014, KEY_PLAY }, | ||
| 124 | { 0x001a, KEY_STOP }, | ||
| 125 | { 0x0040, KEY_REWIND }, | ||
| 126 | { 0x0012, KEY_FASTFORWARD }, | ||
| 127 | { 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */ | ||
| 128 | { 0x004c, KEY_PAUSE }, | ||
| 129 | { 0x004d, KEY_SCREEN }, /* Full screen mode. */ | ||
| 130 | { 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ | ||
| 131 | { 0x000c, KEY_CANCEL }, /* Cancel */ | ||
| 132 | { 0x001c, KEY_EPG }, /* EPG */ | ||
| 133 | { 0x0000, KEY_TAB }, /* Tab */ | ||
| 134 | { 0x0048, KEY_INFO }, /* Preview */ | ||
| 135 | { 0x0004, KEY_LIST }, /* RecordList */ | ||
| 136 | { 0x000f, KEY_TEXT }, /* Teletext */ | ||
| 137 | { 0x0041, KEY_PREVIOUSSONG }, | ||
| 138 | { 0x0042, KEY_NEXTSONG }, | ||
| 139 | { 0x004b, KEY_UP }, | ||
| 140 | { 0x0051, KEY_DOWN }, | ||
| 141 | { 0x004e, KEY_LEFT }, | ||
| 142 | { 0x0052, KEY_RIGHT }, | ||
| 143 | { 0x004f, KEY_ENTER }, | ||
| 144 | { 0x0013, KEY_CANCEL }, | ||
| 145 | { 0x004a, KEY_CLEAR }, | ||
| 146 | { 0x0054, KEY_PRINT }, /* Capture */ | ||
| 147 | { 0x0043, KEY_SUBTITLE }, /* Subtitle/CC */ | ||
| 148 | { 0x0008, KEY_VIDEO }, /* A/V */ | ||
| 149 | { 0x0007, KEY_SLEEP }, /* Hibernate */ | ||
| 150 | { 0x0045, KEY_ZOOM }, /* Zoom+ */ | ||
| 151 | { 0x0018, KEY_RED}, | ||
| 152 | { 0x0053, KEY_GREEN}, | ||
| 153 | { 0x005e, KEY_YELLOW}, | ||
| 154 | { 0x005f, KEY_BLUE} | ||
| 155 | }; | ||
| 156 | |||
| 157 | static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
| 158 | { | ||
| 159 | u8 key; | ||
| 160 | int i; | ||
| 161 | vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20); | ||
| 162 | |||
| 163 | deb_rc("remote query key: %x %d\n",key,key); | ||
| 164 | |||
| 165 | if (key == 0x44) { | ||
| 166 | *state = REMOTE_NO_KEY_PRESSED; | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | for (i = 0; i < ARRAY_SIZE(rc_map_vp7045_table); i++) | ||
| 171 | if (rc5_data(&rc_map_vp7045_table[i]) == key) { | ||
| 172 | *state = REMOTE_KEY_PRESSED; | ||
| 173 | *event = rc_map_vp7045_table[i].keycode; | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset) | ||
| 180 | { | ||
| 181 | int i = 0; | ||
| 182 | u8 v,br[2]; | ||
| 183 | for (i=0; i < len; i++) { | ||
| 184 | v = offset + i; | ||
| 185 | vp7045_usb_op(d,GET_EE_VALUE,&v,1,br,2,5); | ||
| 186 | buf[i] = br[1]; | ||
| 187 | } | ||
| 188 | deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ",offset, i); | ||
| 189 | debug_dump(buf,i,deb_info); | ||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) | ||
| 194 | { | ||
| 195 | return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR); | ||
| 196 | } | ||
| 197 | |||
| 198 | static int vp7045_frontend_attach(struct dvb_usb_adapter *adap) | ||
| 199 | { | ||
| 200 | u8 buf[255] = { 0 }; | ||
| 201 | |||
| 202 | vp7045_usb_op(adap->dev,VENDOR_STRING_READ,NULL,0,buf,20,0); | ||
| 203 | buf[10] = '\0'; | ||
| 204 | deb_info("firmware says: %s ",buf); | ||
| 205 | |||
| 206 | vp7045_usb_op(adap->dev,PRODUCT_STRING_READ,NULL,0,buf,20,0); | ||
| 207 | buf[10] = '\0'; | ||
| 208 | deb_info("%s ",buf); | ||
| 209 | |||
| 210 | vp7045_usb_op(adap->dev,FW_VERSION_READ,NULL,0,buf,20,0); | ||
| 211 | buf[10] = '\0'; | ||
| 212 | deb_info("v%s\n",buf); | ||
| 213 | |||
| 214 | /* Dump the EEPROM */ | ||
| 215 | /* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */ | ||
| 216 | |||
| 217 | adap->fe = vp7045_fe_attach(adap->dev); | ||
| 218 | |||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 222 | static struct dvb_usb_device_properties vp7045_properties; | ||
| 223 | |||
| 224 | static int vp7045_usb_probe(struct usb_interface *intf, | ||
| 225 | const struct usb_device_id *id) | ||
| 226 | { | ||
| 227 | return dvb_usb_device_init(intf, &vp7045_properties, | ||
| 228 | THIS_MODULE, NULL, adapter_nr); | ||
| 229 | } | ||
| 230 | |||
| 231 | static struct usb_device_id vp7045_usb_table [] = { | ||
| 232 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_COLD) }, | ||
| 233 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_WARM) }, | ||
| 234 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_COLD) }, | ||
| 235 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_WARM) }, | ||
| 236 | { 0 }, | ||
| 237 | }; | ||
| 238 | MODULE_DEVICE_TABLE(usb, vp7045_usb_table); | ||
| 239 | |||
| 240 | static struct dvb_usb_device_properties vp7045_properties = { | ||
| 241 | .usb_ctrl = CYPRESS_FX2, | ||
| 242 | .firmware = "dvb-usb-vp7045-01.fw", | ||
| 243 | .size_of_priv = 20, | ||
| 244 | |||
| 245 | .num_adapters = 1, | ||
| 246 | .adapter = { | ||
| 247 | { | ||
| 248 | .frontend_attach = vp7045_frontend_attach, | ||
| 249 | /* parameter for the MPEG2-data transfer */ | ||
| 250 | .stream = { | ||
| 251 | .type = USB_BULK, | ||
| 252 | .count = 7, | ||
| 253 | .endpoint = 0x02, | ||
| 254 | .u = { | ||
| 255 | .bulk = { | ||
| 256 | .buffersize = 4096, | ||
| 257 | } | ||
| 258 | } | ||
| 259 | }, | ||
| 260 | } | ||
| 261 | }, | ||
| 262 | .power_ctrl = vp7045_power_ctrl, | ||
| 263 | .read_mac_address = vp7045_read_mac_addr, | ||
| 264 | |||
| 265 | .rc.legacy = { | ||
| 266 | .rc_interval = 400, | ||
| 267 | .rc_map_table = rc_map_vp7045_table, | ||
| 268 | .rc_map_size = ARRAY_SIZE(rc_map_vp7045_table), | ||
| 269 | .rc_query = vp7045_rc_query, | ||
| 270 | }, | ||
| 271 | |||
| 272 | .num_device_descs = 2, | ||
| 273 | .devices = { | ||
| 274 | { .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)", | ||
| 275 | .cold_ids = { &vp7045_usb_table[0], NULL }, | ||
| 276 | .warm_ids = { &vp7045_usb_table[1], NULL }, | ||
| 277 | }, | ||
| 278 | { .name = "DigitalNow TinyUSB 2 DVB-t Receiver", | ||
| 279 | .cold_ids = { &vp7045_usb_table[2], NULL }, | ||
| 280 | .warm_ids = { &vp7045_usb_table[3], NULL }, | ||
| 281 | }, | ||
| 282 | { NULL }, | ||
| 283 | } | ||
| 284 | }; | ||
| 285 | |||
| 286 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 287 | static struct usb_driver vp7045_usb_driver = { | ||
| 288 | .name = "dvb_usb_vp7045", | ||
| 289 | .probe = vp7045_usb_probe, | ||
| 290 | .disconnect = dvb_usb_device_exit, | ||
| 291 | .id_table = vp7045_usb_table, | ||
| 292 | }; | ||
| 293 | |||
| 294 | /* module stuff */ | ||
| 295 | static int __init vp7045_usb_module_init(void) | ||
| 296 | { | ||
| 297 | int result; | ||
| 298 | if ((result = usb_register(&vp7045_usb_driver))) { | ||
| 299 | err("usb_register failed. (%d)",result); | ||
| 300 | return result; | ||
| 301 | } | ||
| 302 | |||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | static void __exit vp7045_usb_module_exit(void) | ||
| 307 | { | ||
| 308 | /* deregister this driver from the USB subsystem */ | ||
| 309 | usb_deregister(&vp7045_usb_driver); | ||
| 310 | } | ||
| 311 | |||
| 312 | module_init(vp7045_usb_module_init); | ||
| 313 | module_exit(vp7045_usb_module_exit); | ||
| 314 | |||
| 315 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
| 316 | MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0"); | ||
| 317 | MODULE_VERSION("1.0"); | ||
| 318 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/vp7045.h b/drivers/media/dvb/dvb-usb/vp7045.h new file mode 100644 index 00000000000..cf5ec46f8bb --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp7045.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII | ||
| 2 | * USB2.0 DVB-T receiver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
| 5 | * | ||
| 6 | * Thanks to Twinhan who kindly provided hardware and information. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation, version 2. | ||
| 11 | * | ||
| 12 | * see Documentation/dvb/README.dvb-usb for more information | ||
| 13 | */ | ||
| 14 | #ifndef _DVB_USB_VP7045_H_ | ||
| 15 | #define _DVB_USB_VP7045_H_ | ||
| 16 | |||
| 17 | #define DVB_USB_LOG_PREFIX "vp7045" | ||
| 18 | #include "dvb-usb.h" | ||
| 19 | |||
| 20 | /* vp7045 commands */ | ||
| 21 | |||
| 22 | /* Twinhan Vendor requests */ | ||
| 23 | #define TH_COMMAND_IN 0xC0 | ||
| 24 | #define TH_COMMAND_OUT 0xC1 | ||
| 25 | |||
| 26 | /* command bytes */ | ||
| 27 | #define TUNER_REG_READ 0x03 | ||
| 28 | #define TUNER_REG_WRITE 0x04 | ||
| 29 | |||
| 30 | #define RC_VAL_READ 0x05 | ||
| 31 | #define RC_NO_KEY 0x44 | ||
| 32 | |||
| 33 | #define SET_TUNER_POWER 0x06 | ||
| 34 | #define CHECK_TUNER_POWER 0x12 | ||
| 35 | #define Tuner_Power_ON 1 | ||
| 36 | #define Tuner_Power_OFF 0 | ||
| 37 | |||
| 38 | #define GET_USB_SPEED 0x07 | ||
| 39 | |||
| 40 | #define LOCK_TUNER_COMMAND 0x09 | ||
| 41 | |||
| 42 | #define TUNER_SIGNAL_READ 0x0A | ||
| 43 | |||
| 44 | /* FX2 eeprom */ | ||
| 45 | #define SET_EE_VALUE 0x10 | ||
| 46 | #define GET_EE_VALUE 0x11 | ||
| 47 | #define FX2_ID_ADDR 0x00 | ||
| 48 | #define VID_MSB_ADDR 0x02 | ||
| 49 | #define VID_LSB_ADDR 0x01 | ||
| 50 | #define PID_MSB_ADDR 0x04 | ||
| 51 | #define PID_LSB_ADDR 0x03 | ||
| 52 | #define MAC_0_ADDR 0x07 | ||
| 53 | #define MAC_1_ADDR 0x08 | ||
| 54 | #define MAC_2_ADDR 0x09 | ||
| 55 | #define MAC_3_ADDR 0x0a | ||
| 56 | #define MAC_4_ADDR 0x0b | ||
| 57 | #define MAC_5_ADDR 0x0c | ||
| 58 | |||
| 59 | #define RESET_FX2 0x13 | ||
| 60 | |||
| 61 | #define FW_VERSION_READ 0x0B | ||
| 62 | #define VENDOR_STRING_READ 0x0C | ||
| 63 | #define PRODUCT_STRING_READ 0x0D | ||
| 64 | #define FW_BCD_VERSION_READ 0x14 | ||
| 65 | |||
| 66 | extern struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d); | ||
| 67 | extern int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen,int msec); | ||
| 68 | extern u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg); | ||
| 69 | |||
| 70 | #endif | ||
