[PATCH] dvb: Add generalized dvb-usb driver
Add generalized dvb-usb driver which supports a wide variety of devices. Signed-off-by: Patrick Boettcher <pb@linuxtv.org> Signed-off-by: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Randy Dunlap <rdunlap@xenotime.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
b6a235b118
commit
776338e121
36 changed files with 4743 additions and 52 deletions
308
Documentation/dvb/README.dvb-usb
Normal file
308
Documentation/dvb/README.dvb-usb
Normal file
|
@ -0,0 +1,308 @@
|
||||||
|
Documentation for dvb-usb-framework module and its devices
|
||||||
|
|
||||||
|
Idea behind the dvb-usb-framework
|
||||||
|
=================================
|
||||||
|
|
||||||
|
In March 2005 I got the new Twinhan USB2.0 DVB-T device. They provided specs and a firmware.
|
||||||
|
|
||||||
|
Quite keen I wanted to put the driver (with some quirks of course) into dibusb.
|
||||||
|
After reading some specs and doing some USB snooping, it realized, that the
|
||||||
|
dibusb-driver would be a complete mess afterwards. So I decided to do it in a
|
||||||
|
different way: With the help of a dvb-usb-framework.
|
||||||
|
|
||||||
|
The framework provides generic functions (mostly kernel API calls), such as:
|
||||||
|
|
||||||
|
- Transport Stream URB handling in conjunction with dvb-demux-feed-control
|
||||||
|
(bulk and isoc (TODO) are supported)
|
||||||
|
- registering the device for the DVB-API
|
||||||
|
- registering an I2C-adapter if applicable
|
||||||
|
- remote-control/input-device handling
|
||||||
|
- firmware requesting and loading (currently just for the Cypress USB
|
||||||
|
controller)
|
||||||
|
- other functions/methods which can be shared by several drivers (such as
|
||||||
|
functions for bulk-control-commands)
|
||||||
|
|
||||||
|
The source code of the particular DVB USB devices does just the communication
|
||||||
|
with the device via the bus. The connection between the DVB-API-functionality
|
||||||
|
is done via callbacks, assigned in a static device-description (struct
|
||||||
|
dvb_usb_device) each device-driver has to have.
|
||||||
|
|
||||||
|
For an example have a look in drivers/media/dvb/dvb-usb/vp7045*.
|
||||||
|
|
||||||
|
Objective is to migrate all the usb-devices (dibusb, cinergyT2, maybe the
|
||||||
|
ttusb; flexcop-usb already benefits from the generic flexcop-device) to use
|
||||||
|
the dvb-usb-lib.
|
||||||
|
|
||||||
|
TODO: dynamic enabling and disabling of the pid-filter in regard to number of
|
||||||
|
feeds requested.
|
||||||
|
|
||||||
|
Supported devices USB1.1
|
||||||
|
========================
|
||||||
|
|
||||||
|
Produced and reselled by Twinhan:
|
||||||
|
---------------------------------
|
||||||
|
- TwinhanDTV USB-Ter DVB-T Device (VP7041)
|
||||||
|
http://www.twinhan.com/product_terrestrial_3.asp
|
||||||
|
|
||||||
|
- TwinhanDTV Magic Box (VP7041e)
|
||||||
|
http://www.twinhan.com/product_terrestrial_4.asp
|
||||||
|
|
||||||
|
- HAMA DVB-T USB device
|
||||||
|
http://www.hama.de/portal/articleId*110620/action*2598
|
||||||
|
|
||||||
|
- CTS Portable (Chinese Television System) (2)
|
||||||
|
http://www.2cts.tv/ctsportable/
|
||||||
|
|
||||||
|
- Unknown USB DVB-T device with vendor ID Hyper-Paltek
|
||||||
|
|
||||||
|
|
||||||
|
Produced and reselled by KWorld:
|
||||||
|
--------------------------------
|
||||||
|
- KWorld V-Stream XPERT DTV DVB-T USB
|
||||||
|
http://www.kworld.com.tw/en/product/DVBT-USB/DVBT-USB.html
|
||||||
|
|
||||||
|
- JetWay DTV DVB-T USB
|
||||||
|
http://www.jetway.com.tw/evisn/product/lcd-tv/DVT-USB/dtv-usb.htm
|
||||||
|
|
||||||
|
- ADSTech Instant TV DVB-T USB
|
||||||
|
http://www.adstech.com/products/PTV-333/intro/PTV-333_intro.asp?pid=PTV-333
|
||||||
|
|
||||||
|
|
||||||
|
Others:
|
||||||
|
-------
|
||||||
|
- Ultima Electronic/Artec T1 USB TVBOX (AN2135, AN2235, AN2235 with Panasonic Tuner)
|
||||||
|
http://82.161.246.249/products-tvbox.html
|
||||||
|
|
||||||
|
- Compro Videomate DVB-U2000 - DVB-T USB (2)
|
||||||
|
http://www.comprousa.com/products/vmu2000.htm
|
||||||
|
|
||||||
|
- Grandtec USB DVB-T
|
||||||
|
http://www.grand.com.tw/
|
||||||
|
|
||||||
|
- AVerMedia AverTV DVBT USB
|
||||||
|
http://www.avermedia.com/
|
||||||
|
|
||||||
|
- DiBcom USB DVB-T reference device (non-public)
|
||||||
|
|
||||||
|
|
||||||
|
Supported devices USB2.0-only
|
||||||
|
=============================
|
||||||
|
- Twinhan MagicBox II
|
||||||
|
http://www.twinhan.com/product_terrestrial_7.asp
|
||||||
|
|
||||||
|
- TwinhanDTV Alpha
|
||||||
|
http://www.twinhan.com/product_terrestrial_8.asp
|
||||||
|
|
||||||
|
- DigitalNow TinyUSB 2 DVB-t Receiver
|
||||||
|
http://www.digitalnow.com.au/DigitalNow%20tinyUSB2%20Specifications.html
|
||||||
|
|
||||||
|
- Hanftek UMT-010
|
||||||
|
http://www.globalsources.com/si/6008819757082/ProductDetail/Digital-TV/product_id-100046529
|
||||||
|
|
||||||
|
|
||||||
|
Supported devices USB2.0 and USB1.1
|
||||||
|
=============================
|
||||||
|
- Typhoon/Yakumo/HAMA/Yuan DVB-T mobile USB2.0
|
||||||
|
http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T
|
||||||
|
http://www.yuan.com.tw/en/products/vdo_ub300.html
|
||||||
|
http://www.hama.de/portal/articleId*114663/action*2563
|
||||||
|
http://www.anubisline.com/english/articlec.asp?id=50502&catid=002
|
||||||
|
|
||||||
|
- Artec T1 USB TVBOX (FX2) (2)
|
||||||
|
|
||||||
|
- Hauppauge WinTV NOVA-T USB2
|
||||||
|
http://www.hauppauge.com/
|
||||||
|
|
||||||
|
- KWorld/ADSTech Instant DVB-T USB2.0 (DiB3000M-B)
|
||||||
|
|
||||||
|
- DiBcom USB2.0 DVB-T reference device (non-public)
|
||||||
|
|
||||||
|
- AVerMedia AverTV A800 DVB-T USB2.0
|
||||||
|
|
||||||
|
1) It is working almost - work-in-progress.
|
||||||
|
2) No test reports received yet.
|
||||||
|
|
||||||
|
0. History & News:
|
||||||
|
2005-04-17 - all dibusb devices ported to make use of the dvb-usb-framework
|
||||||
|
2005-04-02 - re-enabled and improved remote control code.
|
||||||
|
2005-03-31 - ported the Yakumo/Hama/Typhoon DVB-T USB2.0 device to dvb-usb.
|
||||||
|
2005-03-30 - first commit of the dvb-usb-module based on the dibusb-source. First device is a new driver for the
|
||||||
|
TwinhanDTV Alpha / MagicBox II USB2.0-only DVB-T device.
|
||||||
|
|
||||||
|
(change from dvb-dibusb to dvb-usb)
|
||||||
|
2005-03-28 - added support for the AVerMedia AverTV DVB-T USB2.0 device (Thanks to Glen Harris and Jiun-Kuei Jung, AVerMedia)
|
||||||
|
2005-03-14 - added support for the Typhoon/Yakumo/HAMA DVB-T mobile USB2.0
|
||||||
|
2005-02-11 - added support for the KWorld/ADSTech Instant DVB-T USB2.0. Thanks a lot to Joachim von Caron
|
||||||
|
2005-02-02 - added support for the Hauppauge Win-TV Nova-T USB2
|
||||||
|
2005-01-31 - distorted streaming is gone for USB1.1 devices
|
||||||
|
2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
|
||||||
|
- first almost working version for HanfTek UMT-010
|
||||||
|
- found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek UMT-010
|
||||||
|
2005-01-10 - refactoring completed, now everything is very delightful
|
||||||
|
- tuner quirks for some weird devices (Artec T1 AN2235 device has sometimes a
|
||||||
|
Panasonic Tuner assembled). Tunerprobing implemented. Thanks a lot to Gunnar Wittich.
|
||||||
|
2004-12-29 - after several days of struggling around bug of no returning URBs fixed.
|
||||||
|
2004-12-26 - refactored the dibusb-driver, splitted into separate files
|
||||||
|
- i2c-probing enabled
|
||||||
|
2004-12-06 - possibility for demod i2c-address probing
|
||||||
|
- new usb IDs (Compro, Artec)
|
||||||
|
2004-11-23 - merged changes from DiB3000MC_ver2.1
|
||||||
|
- revised the debugging
|
||||||
|
- possibility to deliver the complete TS for USB2.0
|
||||||
|
2004-11-21 - first working version of the dib3000mc/p frontend driver.
|
||||||
|
2004-11-12 - added additional remote control keys. Thanks to Uwe Hanke.
|
||||||
|
2004-11-07 - added remote control support. Thanks to David Matthews.
|
||||||
|
2004-11-05 - added support for a new devices (Grandtec/Avermedia/Artec)
|
||||||
|
- merged my changes (for dib3000mb/dibusb) to the FE_REFACTORING, because it became HEAD
|
||||||
|
- moved transfer control (pid filter, fifo control) from usb driver to frontend, it seems
|
||||||
|
better settled there (added xfer_ops-struct)
|
||||||
|
- created a common files for frontends (mc/p/mb)
|
||||||
|
2004-09-28 - added support for a new device (Unkown, vendor ID is Hyper-Paltek)
|
||||||
|
2004-09-20 - added support for a new device (Compro DVB-U2000), thanks
|
||||||
|
to Amaury Demol for reporting
|
||||||
|
- changed usb TS transfer method (several urbs, stopping transfer
|
||||||
|
before setting a new pid)
|
||||||
|
2004-09-13 - added support for a new device (Artec T1 USB TVBOX), thanks
|
||||||
|
to Christian Motschke for reporting
|
||||||
|
2004-09-05 - released the dibusb device and dib3000mb-frontend driver
|
||||||
|
|
||||||
|
(old news for vp7041.c)
|
||||||
|
2004-07-15 - found out, by accident, that the device has a TUA6010XS for
|
||||||
|
PLL
|
||||||
|
2004-07-12 - figured out, that the driver should also work with the
|
||||||
|
CTS Portable (Chinese Television System)
|
||||||
|
2004-07-08 - firmware-extraction-2.422-problem solved, driver is now working
|
||||||
|
properly with firmware extracted from 2.422
|
||||||
|
- #if for 2.6.4 (dvb), compile issue
|
||||||
|
- changed firmware handling, see vp7041.txt sec 1.1
|
||||||
|
2004-07-02 - some tuner modifications, v0.1, cleanups, first public
|
||||||
|
2004-06-28 - now using the dvb_dmx_swfilter_packets, everything
|
||||||
|
runs fine now
|
||||||
|
2004-06-27 - able to watch and switching channels (pre-alpha)
|
||||||
|
- no section filtering yet
|
||||||
|
2004-06-06 - first TS received, but kernel oops :/
|
||||||
|
2004-05-14 - firmware loader is working
|
||||||
|
2004-05-11 - start writing the driver
|
||||||
|
|
||||||
|
1. How to use?
|
||||||
|
1.1. Firmware
|
||||||
|
|
||||||
|
Most of the USB drivers need to download a firmware to start working.
|
||||||
|
|
||||||
|
for USB1.1 (AN2135) you need: dvb-usb-dibusb-5.0.0.11.fw
|
||||||
|
for USB2.0 HanfTek: dvb-usb-umt-010-02.fw
|
||||||
|
for USB2.0 DiBcom: dvb-usb-dibusb-6.0.0.8.fw
|
||||||
|
for USB2.0 AVerMedia AverTV DVB-T USB2: dvb-usb-avertv-a800-01.fw
|
||||||
|
for USB2.0 TwinhanDTV Alpha/MagicBox II: dvb-usb-vp7045-01.fw
|
||||||
|
|
||||||
|
The files can be found on http://www.linuxtv.org/download/firmware/ .
|
||||||
|
|
||||||
|
We do not have the permission (yet) to publish the following firmware-files.
|
||||||
|
You'll need to extract them from the windows drivers.
|
||||||
|
|
||||||
|
You should be able to use "get_dvb_firmware dvb-usb" to get the firmware:
|
||||||
|
|
||||||
|
for USB1.1 (AN2235) (a few Artec T1 devices): dvb-usb-dibusb-an2235-01.fw
|
||||||
|
for USB2.0 Hauppauge: dvb-usb-nova-t-usb2-01.fw
|
||||||
|
for USB2.0 ADSTech/Kworld USB2.0: dvb-usb-adstech-usb2-01.fw
|
||||||
|
for USB2.0 Yakumo/Typhoon/Hama: dvb-usb-dtt200u-01.fw
|
||||||
|
|
||||||
|
1.2. Compiling
|
||||||
|
|
||||||
|
Since the driver is in the linux kernel, activating the driver in
|
||||||
|
your favorite config-environment should sufficient. I recommend
|
||||||
|
to compile the driver as module. Hotplug does the rest.
|
||||||
|
|
||||||
|
If you use dvb-kernel enter the build-2.6 directory run 'make' and 'insmod.sh
|
||||||
|
load' afterwards.
|
||||||
|
|
||||||
|
1.3. Loading the drivers
|
||||||
|
|
||||||
|
Hotplug is able to load the driver, when it is needed (because you plugged
|
||||||
|
in the device).
|
||||||
|
|
||||||
|
If you want to enable debug output, you have to load the driver manually and
|
||||||
|
from withing the dvb-kernel cvs repository.
|
||||||
|
|
||||||
|
first have a look, which debug level are available:
|
||||||
|
|
||||||
|
modinfo dvb-usb
|
||||||
|
modinfo dvb-usb-vp7045
|
||||||
|
etc.
|
||||||
|
|
||||||
|
modprobe dvb-usb debug=<level>
|
||||||
|
modprobe dvb-usb-vp7045 debug=<level>
|
||||||
|
etc.
|
||||||
|
|
||||||
|
should do the trick.
|
||||||
|
|
||||||
|
When the driver is loaded successfully, the firmware file was in
|
||||||
|
the right place and the device is connected, the "Power"-LED should be
|
||||||
|
turned on.
|
||||||
|
|
||||||
|
At this point you should be able to start a dvb-capable application. I'm use
|
||||||
|
(t|s)zap, mplayer and dvbscan to test the basics. VDR-xine provides the
|
||||||
|
long-term test scenario.
|
||||||
|
|
||||||
|
2. Known problems and bugs
|
||||||
|
|
||||||
|
- Don't remove the USB device while running an DVB application, your system
|
||||||
|
will go crazy or die most likely.
|
||||||
|
|
||||||
|
2.1. Adding support for devices
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
2.2. USB1.1 Bandwidth limitation
|
||||||
|
|
||||||
|
A lot of the currently supported devices are USB1.1 and thus they have a
|
||||||
|
maximum bandwidth of about 5-6 MBit/s when connected to a USB2.0 hub.
|
||||||
|
This is not enough for receiving the complete transport stream of a
|
||||||
|
DVB-T channel (which is about 16 MBit/s). Normally this is not a
|
||||||
|
problem, if you only want to watch TV (this does not apply for HDTV),
|
||||||
|
but watching a channel while recording another channel on the same
|
||||||
|
frequency simply does not work very well. This applies to all USB1.1
|
||||||
|
DVB-T devices, not just the dvb-usb-devices)
|
||||||
|
|
||||||
|
The bug, where the TS is distorted by a heavy usage of the device is gone
|
||||||
|
definitely. All dvb-usb-devices I was using (Twinhan, Kworld, DiBcom) are
|
||||||
|
working like charm now with VDR. Sometimes I even was able to record a channel
|
||||||
|
and watch another one.
|
||||||
|
|
||||||
|
2.3. Comments
|
||||||
|
|
||||||
|
Patches, comments and suggestions are very very welcome.
|
||||||
|
|
||||||
|
3. Acknowledgements
|
||||||
|
Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for
|
||||||
|
providing specs, code and help, on which the dvb-dibusb, dib3000mb and
|
||||||
|
dib3000mc are based.
|
||||||
|
|
||||||
|
David Matthews for identifying a new device type (Artec T1 with AN2235)
|
||||||
|
and for extending dibusb with remote control event handling. Thank you.
|
||||||
|
|
||||||
|
Alex Woods for frequently answering question about usb and dvb
|
||||||
|
stuff, a big thank you.
|
||||||
|
|
||||||
|
Bernd Wagner for helping with huge bug reports and discussions.
|
||||||
|
|
||||||
|
Gunnar Wittich and Joachim von Caron for their trust for providing
|
||||||
|
root-shells on their machines to implement support for new devices.
|
||||||
|
|
||||||
|
Glen Harris for bringing up, that there is a new dibusb-device and Jiun-Kuei
|
||||||
|
Jung from AVerMedia who kindly provided a special firmware to get the device
|
||||||
|
up and running in Linux.
|
||||||
|
|
||||||
|
Jennifer Chen, Jeff and Jack from Twinhan for kindly supporting by
|
||||||
|
writing the vp7045-driver.
|
||||||
|
|
||||||
|
Some guys on the linux-dvb mailing list for encouraging me
|
||||||
|
|
||||||
|
Peter Schildmann >peter.schildmann-nospam-at-web.de< for his
|
||||||
|
user-level firmware loader, which saves a lot of time
|
||||||
|
(when writing the vp7041 driver)
|
||||||
|
|
||||||
|
Ulf Hermenau for helping me out with traditional chinese.
|
||||||
|
|
||||||
|
André Smoktun and Christian Frömmel for supporting me with
|
||||||
|
hardware and listening to my problems very patient.
|
|
@ -27,6 +27,7 @@ source "drivers/media/dvb/ttpci/Kconfig"
|
||||||
|
|
||||||
comment "Supported USB Adapters"
|
comment "Supported USB Adapters"
|
||||||
depends on DVB_CORE && USB
|
depends on DVB_CORE && USB
|
||||||
|
source "drivers/media/dvb/dvb-usb/Kconfig"
|
||||||
source "drivers/media/dvb/ttusb-budget/Kconfig"
|
source "drivers/media/dvb/ttusb-budget/Kconfig"
|
||||||
source "drivers/media/dvb/ttusb-dec/Kconfig"
|
source "drivers/media/dvb/ttusb-dec/Kconfig"
|
||||||
source "drivers/media/dvb/cinergyT2/Kconfig"
|
source "drivers/media/dvb/cinergyT2/Kconfig"
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
# Makefile for the kernel multimedia device drivers.
|
# Makefile for the kernel multimedia device drivers.
|
||||||
#
|
#
|
||||||
|
|
||||||
obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/
|
obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/
|
||||||
|
|
99
drivers/media/dvb/dvb-usb/Kconfig
Normal file
99
drivers/media/dvb/dvb-usb/Kconfig
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
config DVB_USB
|
||||||
|
tristate "Support for various USB DVB devices"
|
||||||
|
depends on DVB_CORE && USB
|
||||||
|
select FW_LOADER
|
||||||
|
help
|
||||||
|
By enabling this you will be able to choose the various USB 1.1 and
|
||||||
|
USB2.0 DVB devices.
|
||||||
|
|
||||||
|
Almost every USB device needs a firmware, please look into
|
||||||
|
<file:Documentation/dvb/README.dvb-usb>
|
||||||
|
|
||||||
|
Say Y if you own an USB DVB device.
|
||||||
|
|
||||||
|
config DVB_USB_DEBUG
|
||||||
|
bool "Enable extended debug support for all DVB-USB devices"
|
||||||
|
depends on DVB_USB
|
||||||
|
help
|
||||||
|
Say Y if you want to enable debuging. See modinfo dvb-usb (and the
|
||||||
|
appropriate drivers) for debug levels.
|
||||||
|
|
||||||
|
config DVB_USB_A800
|
||||||
|
tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
|
||||||
|
depends on DVB_USB
|
||||||
|
help
|
||||||
|
Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
|
||||||
|
|
||||||
|
config DVB_USB_DIBUSB_MB
|
||||||
|
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
|
||||||
|
depends on DVB_USB
|
||||||
|
help
|
||||||
|
Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
|
||||||
|
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
|
||||||
|
|
||||||
|
Devices supported by this driver:
|
||||||
|
TwinhanDTV USB-Ter (VP7041)
|
||||||
|
TwinhanDTV Magic Box (VP7041e)
|
||||||
|
KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
|
||||||
|
Hama DVB-T USB1.1-Box
|
||||||
|
DiBcom USB1.1 reference devices (non-public)
|
||||||
|
Ultima Electronic/Artec T1 USB TVBOX
|
||||||
|
Compro Videomate DVB-U2000 - DVB-T USB
|
||||||
|
Grandtec DVB-T USB
|
||||||
|
Avermedia AverTV DVBT USB1.1
|
||||||
|
Artec T1 USB1.1 boxes
|
||||||
|
|
||||||
|
The VP7041 seems to be identical to "CTS Portable" (Chinese
|
||||||
|
Television System).
|
||||||
|
|
||||||
|
Say Y if you own such a device and want to use it. You should build it as
|
||||||
|
a module.
|
||||||
|
|
||||||
|
config DVB_USB_DIBUSB_MC
|
||||||
|
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
|
||||||
|
depends on DVB_USB
|
||||||
|
help
|
||||||
|
Support for 2.0 DVB-T receivers based on reference designs made by
|
||||||
|
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
|
||||||
|
|
||||||
|
Devices supported by this driver:
|
||||||
|
DiBcom USB2.0 reference devices (non-public)
|
||||||
|
Artec T1 USB2.0 boxes
|
||||||
|
|
||||||
|
Say Y if you own such a device and want to use it. You should build it as
|
||||||
|
a module.
|
||||||
|
|
||||||
|
config DVB_USB_UMT_010
|
||||||
|
tristate "HanfTek UMT-010 DVB-T USB2.0 support"
|
||||||
|
depends on DVB_USB
|
||||||
|
help
|
||||||
|
Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
|
||||||
|
|
||||||
|
config DVB_USB_DIGITV
|
||||||
|
tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
|
||||||
|
depends on DVB_USB
|
||||||
|
help
|
||||||
|
Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
|
||||||
|
|
||||||
|
config DVB_USB_VP7045
|
||||||
|
tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support"
|
||||||
|
depends on DVB_USB
|
||||||
|
help
|
||||||
|
Say Y here to support the
|
||||||
|
TwinhanDTV Alpha (stick) (VP-7045),
|
||||||
|
TwinhanDTV MagicBox II (VP-7046) and
|
||||||
|
DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers.
|
||||||
|
|
||||||
|
config DVB_USB_NOVA_T_USB2
|
||||||
|
tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
|
||||||
|
depends on DVB_USB
|
||||||
|
help
|
||||||
|
Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
|
||||||
|
|
||||||
|
config DVB_USB_DTT200U
|
||||||
|
tristate "Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 support"
|
||||||
|
depends on DVB_USB
|
||||||
|
help
|
||||||
|
Say Y here to support the Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver.
|
||||||
|
|
||||||
|
The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan).
|
30
drivers/media/dvb/dvb-usb/Makefile
Normal file
30
drivers/media/dvb/dvb-usb/Makefile
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
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
|
||||||
|
obj-$(CONFIG_DVB_USB) += dvb-usb.o
|
||||||
|
|
||||||
|
dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
|
||||||
|
obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
|
||||||
|
|
||||||
|
dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
|
||||||
|
obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
|
||||||
|
|
||||||
|
dvb-usb-dibusb-common-objs = dibusb-common.o
|
||||||
|
|
||||||
|
dvb-usb-a800-objs = a800.o
|
||||||
|
obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o
|
||||||
|
|
||||||
|
dvb-usb-dibusb-mb-objs = dibusb-mb.o
|
||||||
|
obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o
|
||||||
|
|
||||||
|
dvb-usb-dibusb-mc-objs = dibusb-mc.o
|
||||||
|
obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o
|
||||||
|
|
||||||
|
dvb-usb-nova-t-usb2-objs = nova-t-usb2.o
|
||||||
|
obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o
|
||||||
|
|
||||||
|
dvb-usb-umt-010-objs = umt-010.o
|
||||||
|
obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
|
||||||
|
|
||||||
|
dvb-usb-digitv-objs = digitv.o
|
||||||
|
obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
|
||||||
|
|
||||||
|
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
|
176
drivers/media/dvb/dvb-usb/a800.c
Normal file
176
drivers/media/dvb/dvb-usb/a800.c
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
/* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T
|
||||||
|
* USB2.0 (A800) DVB-T receiver.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* Thanks to
|
||||||
|
* - AVerMedia who kindly provided information and
|
||||||
|
* - Glen Harris who suffered from my mistakes during development.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "dibusb.h"
|
||||||
|
|
||||||
|
static int debug;
|
||||||
|
module_param(debug, int, 0644);
|
||||||
|
MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
|
||||||
|
#define deb_rc(args...) dprintk(debug,0x01,args)
|
||||||
|
|
||||||
|
static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
/* do nothing for the AVerMedia */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dvb_usb_rc_key a800_rc_keys[] = {
|
||||||
|
{ 0x02, 0x01, KEY_PROG1 }, /* SOURCE */
|
||||||
|
{ 0x02, 0x00, KEY_POWER }, /* POWER */
|
||||||
|
{ 0x02, 0x05, KEY_1 }, /* 1 */
|
||||||
|
{ 0x02, 0x06, KEY_2 }, /* 2 */
|
||||||
|
{ 0x02, 0x07, KEY_3 }, /* 3 */
|
||||||
|
{ 0x02, 0x09, KEY_4 }, /* 4 */
|
||||||
|
{ 0x02, 0x0a, KEY_5 }, /* 5 */
|
||||||
|
{ 0x02, 0x0b, KEY_6 }, /* 6 */
|
||||||
|
{ 0x02, 0x0d, KEY_7 }, /* 7 */
|
||||||
|
{ 0x02, 0x0e, KEY_8 }, /* 8 */
|
||||||
|
{ 0x02, 0x0f, KEY_9 }, /* 9 */
|
||||||
|
{ 0x02, 0x12, KEY_LEFT }, /* L / DISPLAY */
|
||||||
|
{ 0x02, 0x11, KEY_0 }, /* 0 */
|
||||||
|
{ 0x02, 0x13, KEY_RIGHT }, /* R / CH RTN */
|
||||||
|
{ 0x02, 0x17, KEY_PROG2 }, /* SNAP SHOT */
|
||||||
|
{ 0x02, 0x10, KEY_PROG3 }, /* 16-CH PREV */
|
||||||
|
{ 0x02, 0x03, KEY_CHANNELUP }, /* CH UP */
|
||||||
|
{ 0x02, 0x1e, KEY_VOLUMEDOWN }, /* VOL DOWN */
|
||||||
|
{ 0x02, 0x0c, KEY_ZOOM }, /* FULL SCREEN */
|
||||||
|
{ 0x02, 0x1f, KEY_VOLUMEUP }, /* VOL UP */
|
||||||
|
{ 0x02, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */
|
||||||
|
{ 0x02, 0x14, KEY_MUTE }, /* MUTE */
|
||||||
|
{ 0x02, 0x08, KEY_AUDIO }, /* AUDIO */
|
||||||
|
{ 0x02, 0x19, KEY_RECORD }, /* RECORD */
|
||||||
|
{ 0x02, 0x18, KEY_PLAY }, /* PLAY */
|
||||||
|
{ 0x02, 0x1b, KEY_STOP }, /* STOP */
|
||||||
|
{ 0x02, 0x1a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */
|
||||||
|
{ 0x02, 0x1d, KEY_BACK }, /* << / RED */
|
||||||
|
{ 0x02, 0x1c, KEY_FORWARD }, /* >> / YELLOW */
|
||||||
|
{ 0x02, 0x03, KEY_TEXT }, /* TELETEXT */
|
||||||
|
{ 0x02, 0x01, KEY_FIRST }, /* |<< / GREEN */
|
||||||
|
{ 0x02, 0x00, KEY_LAST }, /* >>| / BLUE */
|
||||||
|
{ 0x02, 0x04, KEY_EPG }, /* EPG */
|
||||||
|
{ 0x02, 0x15, KEY_MENU }, /* MENU */
|
||||||
|
};
|
||||||
|
|
||||||
|
int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||||
|
{
|
||||||
|
u8 key[5];
|
||||||
|
if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
|
||||||
|
0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
|
||||||
|
2*HZ) != 5)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/* call the universal NEC remote processor, to find out the key's state and event */
|
||||||
|
dvb_usb_nec_rc_key_to_event(d,key,event,state);
|
||||||
|
if (key[0] != 0)
|
||||||
|
deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* USB Driver stuff */
|
||||||
|
static struct dvb_usb_properties a800_properties;
|
||||||
|
|
||||||
|
static int a800_probe(struct usb_interface *intf,
|
||||||
|
const struct usb_device_id *id)
|
||||||
|
{
|
||||||
|
return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do not change the order of the ID table */
|
||||||
|
static struct usb_device_id a800_table [] = {
|
||||||
|
/* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_COLD) },
|
||||||
|
/* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_WARM) },
|
||||||
|
{ } /* Terminating entry */
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE (usb, a800_table);
|
||||||
|
|
||||||
|
static struct dvb_usb_properties a800_properties = {
|
||||||
|
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
|
.pid_filter_count = 32,
|
||||||
|
|
||||||
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
|
|
||||||
|
.firmware = "dvb-usb-avertv-a800-02.fw",
|
||||||
|
|
||||||
|
.size_of_priv = sizeof(struct dibusb_state),
|
||||||
|
|
||||||
|
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||||
|
.pid_filter = dibusb_pid_filter,
|
||||||
|
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||||
|
.power_ctrl = a800_power_ctrl,
|
||||||
|
.frontend_attach = dibusb_dib3000mc_frontend_attach,
|
||||||
|
.tuner_attach = dibusb_dib3000mc_tuner_attach,
|
||||||
|
|
||||||
|
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||||
|
.rc_key_map = a800_rc_keys,
|
||||||
|
.rc_key_map_size = ARRAY_SIZE(a800_rc_keys),
|
||||||
|
.rc_query = a800_rc_query,
|
||||||
|
|
||||||
|
.i2c_algo = &dibusb_i2c_algo,
|
||||||
|
|
||||||
|
.generic_bulk_ctrl_endpoint = 0x01,
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 7,
|
||||||
|
.endpoint = 0x06,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 4096,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 1,
|
||||||
|
.devices = {
|
||||||
|
{ "AVerMedia AverTV DVB-T USB 2.0 (A800)",
|
||||||
|
{ &a800_table[0], NULL },
|
||||||
|
{ &a800_table[1], NULL },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usb_driver a800_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "AVerMedia AverTV DVB-T USB 2.0 (A800)",
|
||||||
|
.probe = a800_probe,
|
||||||
|
.disconnect = dvb_usb_device_exit,
|
||||||
|
.id_table = a800_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* module stuff */
|
||||||
|
static int __init a800_module_init(void)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if ((result = usb_register(&a800_driver))) {
|
||||||
|
err("usb_register failed. Error number %d",result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit a800_module_exit(void)
|
||||||
|
{
|
||||||
|
/* deregister this driver from the USB subsystem */
|
||||||
|
usb_deregister(&a800_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init (a800_module_init);
|
||||||
|
module_exit (a800_module_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||||
|
MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)");
|
||||||
|
MODULE_VERSION("1.0");
|
||||||
|
MODULE_LICENSE("GPL");
|
272
drivers/media/dvb/dvb-usb/dibusb-common.c
Normal file
272
drivers/media/dvb/dvb-usb/dibusb-common.c
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
/* Common methods for dibusb-based-receivers.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "dibusb.h"
|
||||||
|
|
||||||
|
static int debug;
|
||||||
|
module_param(debug, int, 0644);
|
||||||
|
MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS);
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
#define deb_info(args...) dprintk(debug,0x01,args)
|
||||||
|
|
||||||
|
/* common stuff used by the different dibusb modules */
|
||||||
|
int dibusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
if (d->priv != NULL) {
|
||||||
|
struct dib_fe_xfer_ops *ops = d->priv;
|
||||||
|
if (ops->fifo_ctrl != NULL)
|
||||||
|
if (ops->fifo_ctrl(d->fe,onoff)) {
|
||||||
|
err("error while controlling the fifo of the demod.");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dibusb_streaming_ctrl);
|
||||||
|
|
||||||
|
int dibusb_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
|
||||||
|
{
|
||||||
|
if (d->priv != NULL) {
|
||||||
|
struct dib_fe_xfer_ops *ops = d->priv;
|
||||||
|
if (d->pid_filtering && ops->pid_ctrl != NULL)
|
||||||
|
ops->pid_ctrl(d->fe,index,pid,onoff);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dibusb_pid_filter);
|
||||||
|
|
||||||
|
int dibusb_pid_filter_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
if (d->priv != NULL) {
|
||||||
|
struct dib_fe_xfer_ops *ops = d->priv;
|
||||||
|
if (ops->pid_parse != NULL)
|
||||||
|
if (ops->pid_parse(d->fe,onoff) < 0)
|
||||||
|
err("could not handle pid_parser");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dibusb_pid_filter_ctrl);
|
||||||
|
|
||||||
|
int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
u8 b[3];
|
||||||
|
int ret;
|
||||||
|
b[0] = DIBUSB_REQ_SET_IOCTL;
|
||||||
|
b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
|
||||||
|
b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP;
|
||||||
|
ret = dvb_usb_generic_write(d,b,3);
|
||||||
|
msleep(10);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dibusb_power_ctrl);
|
||||||
|
|
||||||
|
int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
u8 b[2];
|
||||||
|
b[0] = DIBUSB_REQ_SET_IOCTL;
|
||||||
|
b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
|
||||||
|
|
||||||
|
dvb_usb_generic_write(d,b,3);
|
||||||
|
|
||||||
|
return dibusb_streaming_ctrl(d,onoff);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
|
||||||
|
|
||||||
|
int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
if (onoff) {
|
||||||
|
u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP };
|
||||||
|
return dvb_usb_generic_write(d,b,3);
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dibusb2_0_power_ctrl);
|
||||||
|
|
||||||
|
static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
|
||||||
|
u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
|
||||||
|
{
|
||||||
|
u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
|
||||||
|
/* write only ? */
|
||||||
|
int wo = (rbuf == NULL || rlen == 0),
|
||||||
|
len = 2 + wlen + (wo ? 0 : 2);
|
||||||
|
|
||||||
|
sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
|
||||||
|
sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
|
||||||
|
|
||||||
|
memcpy(&sndbuf[2],wbuf,wlen);
|
||||||
|
|
||||||
|
if (!wo) {
|
||||||
|
sndbuf[wlen+2] = (rlen >> 8) & 0xff;
|
||||||
|
sndbuf[wlen+3] = rlen & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I2C master xfer function
|
||||||
|
*/
|
||||||
|
static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (down_interruptible(&d->i2c_sem) < 0)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
|
if (num > 2)
|
||||||
|
warn("more than 2 i2c messages at a time is not handled yet. TODO.");
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
/* write/read request */
|
||||||
|
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
|
||||||
|
if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,
|
||||||
|
msg[i+1].buf,msg[i+1].len) < 0)
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
} else
|
||||||
|
if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
up(&d->i2c_sem);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
|
||||||
|
{
|
||||||
|
return I2C_FUNC_I2C;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct i2c_algorithm dibusb_i2c_algo = {
|
||||||
|
.name = "DiBcom USB I2C algorithm",
|
||||||
|
.id = I2C_ALGO_BIT,
|
||||||
|
.master_xfer = dibusb_i2c_xfer,
|
||||||
|
.functionality = dibusb_i2c_func,
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL(dibusb_i2c_algo);
|
||||||
|
|
||||||
|
int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
|
||||||
|
{
|
||||||
|
u8 wbuf[1] = { offs };
|
||||||
|
return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dibusb_read_eeprom_byte);
|
||||||
|
|
||||||
|
int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
struct dib3000_config demod_cfg;
|
||||||
|
struct dibusb_state *st = d->priv;
|
||||||
|
|
||||||
|
demod_cfg.pll_set = dvb_usb_pll_set_i2c;
|
||||||
|
demod_cfg.pll_init = dvb_usb_pll_init_i2c;
|
||||||
|
|
||||||
|
for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
|
||||||
|
if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
|
||||||
|
d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
|
||||||
|
|
||||||
|
int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
d->pll_addr = 0x60;
|
||||||
|
d->pll_desc = &dvb_pll_env57h1xd5;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* common remote control stuff
|
||||||
|
*/
|
||||||
|
struct dvb_usb_rc_key dibusb_rc_keys[] = {
|
||||||
|
/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
|
||||||
|
{ 0x00, 0x16, KEY_POWER },
|
||||||
|
{ 0x00, 0x10, KEY_MUTE },
|
||||||
|
{ 0x00, 0x03, KEY_1 },
|
||||||
|
{ 0x00, 0x01, KEY_2 },
|
||||||
|
{ 0x00, 0x06, KEY_3 },
|
||||||
|
{ 0x00, 0x09, KEY_4 },
|
||||||
|
{ 0x00, 0x1d, KEY_5 },
|
||||||
|
{ 0x00, 0x1f, KEY_6 },
|
||||||
|
{ 0x00, 0x0d, KEY_7 },
|
||||||
|
{ 0x00, 0x19, KEY_8 },
|
||||||
|
{ 0x00, 0x1b, KEY_9 },
|
||||||
|
{ 0x00, 0x15, KEY_0 },
|
||||||
|
{ 0x00, 0x05, KEY_CHANNELUP },
|
||||||
|
{ 0x00, 0x02, KEY_CHANNELDOWN },
|
||||||
|
{ 0x00, 0x1e, KEY_VOLUMEUP },
|
||||||
|
{ 0x00, 0x0a, KEY_VOLUMEDOWN },
|
||||||
|
{ 0x00, 0x11, KEY_RECORD },
|
||||||
|
{ 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */
|
||||||
|
{ 0x00, 0x14, KEY_PLAY },
|
||||||
|
{ 0x00, 0x1a, KEY_STOP },
|
||||||
|
{ 0x00, 0x40, KEY_REWIND },
|
||||||
|
{ 0x00, 0x12, KEY_FASTFORWARD },
|
||||||
|
{ 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */
|
||||||
|
{ 0x00, 0x4c, KEY_PAUSE },
|
||||||
|
{ 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */
|
||||||
|
{ 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
|
||||||
|
/* additional keys TwinHan VisionPlus, the Artec seemingly not have */
|
||||||
|
{ 0x00, 0x0c, KEY_CANCEL }, /* Cancel */
|
||||||
|
{ 0x00, 0x1c, KEY_EPG }, /* EPG */
|
||||||
|
{ 0x00, 0x00, KEY_TAB }, /* Tab */
|
||||||
|
{ 0x00, 0x48, KEY_INFO }, /* Preview */
|
||||||
|
{ 0x00, 0x04, KEY_LIST }, /* RecordList */
|
||||||
|
{ 0x00, 0x0f, KEY_TEXT }, /* Teletext */
|
||||||
|
/* Key codes for the KWorld/ADSTech/JetWay remote. */
|
||||||
|
{ 0x86, 0x12, KEY_POWER },
|
||||||
|
{ 0x86, 0x0f, KEY_SELECT }, /* source */
|
||||||
|
{ 0x86, 0x0c, KEY_UNKNOWN }, /* scan */
|
||||||
|
{ 0x86, 0x0b, KEY_EPG },
|
||||||
|
{ 0x86, 0x10, KEY_MUTE },
|
||||||
|
{ 0x86, 0x01, KEY_1 },
|
||||||
|
{ 0x86, 0x02, KEY_2 },
|
||||||
|
{ 0x86, 0x03, KEY_3 },
|
||||||
|
{ 0x86, 0x04, KEY_4 },
|
||||||
|
{ 0x86, 0x05, KEY_5 },
|
||||||
|
{ 0x86, 0x06, KEY_6 },
|
||||||
|
{ 0x86, 0x07, KEY_7 },
|
||||||
|
{ 0x86, 0x08, KEY_8 },
|
||||||
|
{ 0x86, 0x09, KEY_9 },
|
||||||
|
{ 0x86, 0x0a, KEY_0 },
|
||||||
|
{ 0x86, 0x18, KEY_ZOOM },
|
||||||
|
{ 0x86, 0x1c, KEY_UNKNOWN }, /* preview */
|
||||||
|
{ 0x86, 0x13, KEY_UNKNOWN }, /* snap */
|
||||||
|
{ 0x86, 0x00, KEY_UNDO },
|
||||||
|
{ 0x86, 0x1d, KEY_RECORD },
|
||||||
|
{ 0x86, 0x0d, KEY_STOP },
|
||||||
|
{ 0x86, 0x0e, KEY_PAUSE },
|
||||||
|
{ 0x86, 0x16, KEY_PLAY },
|
||||||
|
{ 0x86, 0x11, KEY_BACK },
|
||||||
|
{ 0x86, 0x19, KEY_FORWARD },
|
||||||
|
{ 0x86, 0x14, KEY_UNKNOWN }, /* pip */
|
||||||
|
{ 0x86, 0x15, KEY_ESC },
|
||||||
|
{ 0x86, 0x1a, KEY_UP },
|
||||||
|
{ 0x86, 0x1e, KEY_DOWN },
|
||||||
|
{ 0x86, 0x1f, KEY_LEFT },
|
||||||
|
{ 0x86, 0x1b, KEY_RIGHT },
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL(dibusb_rc_keys);
|
||||||
|
|
||||||
|
int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||||
|
{
|
||||||
|
u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE;
|
||||||
|
dvb_usb_generic_rw(d,&cmd,1,key,5,0);
|
||||||
|
dvb_usb_nec_rc_key_to_event(d,key,event,state);
|
||||||
|
if (key[0] != 0)
|
||||||
|
deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dibusb_rc_query);
|
316
drivers/media/dvb/dvb-usb/dibusb-mb.c
Normal file
316
drivers/media/dvb/dvb-usb/dibusb-mb.c
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
|
||||||
|
* reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* based on GPL code from DiBcom, which has
|
||||||
|
* Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "dibusb.h"
|
||||||
|
|
||||||
|
static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
struct dib3000_config demod_cfg;
|
||||||
|
struct dibusb_state *st = d->priv;
|
||||||
|
|
||||||
|
demod_cfg.demod_address = 0x8;
|
||||||
|
demod_cfg.pll_set = dvb_usb_pll_set_i2c;
|
||||||
|
demod_cfg.pll_init = dvb_usb_pll_init_i2c;
|
||||||
|
|
||||||
|
if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* some of the dibusb 1.1 device aren't equipped with the default tuner
|
||||||
|
* (Thomson Cable), but with a Panasonic ENV77H11D5. This function figures
|
||||||
|
* this out. */
|
||||||
|
static int dibusb_dib3000mb_tuner_attach (struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
u8 b[2] = { 0,0 }, b2[1];
|
||||||
|
int ret = 0;
|
||||||
|
struct i2c_msg msg[2] = {
|
||||||
|
{ .flags = 0, .buf = b, .len = 2 },
|
||||||
|
{ .flags = I2C_M_RD, .buf = b2, .len = 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
|
||||||
|
msg[0].addr = msg[1].addr = 0x60;
|
||||||
|
|
||||||
|
if (d->tuner_pass_ctrl)
|
||||||
|
d->tuner_pass_ctrl(d->fe,1,msg[0].addr);
|
||||||
|
|
||||||
|
if (i2c_transfer (&d->i2c_adap, msg, 2) != 2) {
|
||||||
|
err("tuner i2c write failed.");
|
||||||
|
ret = -EREMOTEIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->tuner_pass_ctrl)
|
||||||
|
d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
|
||||||
|
|
||||||
|
if (b2[0] == 0xfe) {
|
||||||
|
info("this device has the Thomson Cable onboard. Which is default.");
|
||||||
|
d->pll_addr = 0x61;
|
||||||
|
d->pll_desc = &dvb_pll_tua6010xs;
|
||||||
|
} else {
|
||||||
|
u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
|
||||||
|
info("this device has the Panasonic ENV77H11D5 onboard.");
|
||||||
|
d->pll_addr = 0x60;
|
||||||
|
memcpy(d->pll_init,bpll,4);
|
||||||
|
d->pll_desc = &dvb_pll_tda665x;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* USB Driver stuff */
|
||||||
|
static struct dvb_usb_properties dibusb1_1_properties;
|
||||||
|
static struct dvb_usb_properties dibusb1_1_an2235_properties;
|
||||||
|
static struct dvb_usb_properties dibusb2_0b_properties;
|
||||||
|
|
||||||
|
static int dibusb_probe(struct usb_interface *intf,
|
||||||
|
const struct usb_device_id *id)
|
||||||
|
{
|
||||||
|
if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE) == 0 ||
|
||||||
|
dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE) ||
|
||||||
|
dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do not change the order of the ID table */
|
||||||
|
static struct usb_device_id dibusb_dib3000mb_table [] = {
|
||||||
|
/* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_AVERMEDIA_DVBT_USB_COLD)},
|
||||||
|
/* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_AVERMEDIA_DVBT_USB_WARM)},
|
||||||
|
/* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) },
|
||||||
|
/* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) },
|
||||||
|
/* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) },
|
||||||
|
/* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) },
|
||||||
|
/* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) },
|
||||||
|
/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
|
||||||
|
/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
|
||||||
|
/* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) },
|
||||||
|
/* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) },
|
||||||
|
/* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) },
|
||||||
|
/* 12 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) },
|
||||||
|
/* 13 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) },
|
||||||
|
/* 14 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) },
|
||||||
|
/* 15 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_COLD) },
|
||||||
|
/* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) },
|
||||||
|
/* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) },
|
||||||
|
/* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) },
|
||||||
|
/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
|
||||||
|
/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
|
||||||
|
/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
|
||||||
|
/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
|
||||||
|
/* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) },
|
||||||
|
/* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) },
|
||||||
|
{ } /* Terminating entry */
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
|
||||||
|
|
||||||
|
static struct dvb_usb_properties dibusb1_1_properties = {
|
||||||
|
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
|
.pid_filter_count = 16,
|
||||||
|
|
||||||
|
.usb_ctrl = CYPRESS_AN2135,
|
||||||
|
|
||||||
|
.firmware = "dvb-usb-dibusb-5.0.0.11.fw",
|
||||||
|
|
||||||
|
.size_of_priv = sizeof(struct dibusb_state),
|
||||||
|
|
||||||
|
.streaming_ctrl = dibusb_streaming_ctrl,
|
||||||
|
.pid_filter = dibusb_pid_filter,
|
||||||
|
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||||
|
.power_ctrl = dibusb_power_ctrl,
|
||||||
|
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||||
|
.tuner_attach = dibusb_dib3000mb_tuner_attach,
|
||||||
|
|
||||||
|
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||||
|
.rc_key_map = dibusb_rc_keys,
|
||||||
|
.rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||||
|
.rc_query = dibusb_rc_query,
|
||||||
|
|
||||||
|
.i2c_algo = &dibusb_i2c_algo,
|
||||||
|
|
||||||
|
.generic_bulk_ctrl_endpoint = 0x01,
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 7,
|
||||||
|
.endpoint = 0x02,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 4096,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 8,
|
||||||
|
.devices = {
|
||||||
|
{ "AVerMedia AverTV DVBT USB1.1",
|
||||||
|
{ &dibusb_dib3000mb_table[0], NULL },
|
||||||
|
{ &dibusb_dib3000mb_table[1], NULL },
|
||||||
|
},
|
||||||
|
{ "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",
|
||||||
|
{ &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL},
|
||||||
|
{ &dibusb_dib3000mb_table[3], NULL },
|
||||||
|
},
|
||||||
|
{ "DiBcom USB1.1 DVB-T reference design (MOD3000)",
|
||||||
|
{ &dibusb_dib3000mb_table[5], NULL },
|
||||||
|
{ &dibusb_dib3000mb_table[6], NULL },
|
||||||
|
},
|
||||||
|
{ "KWorld V-Stream XPERT DTV - DVB-T USB1.1",
|
||||||
|
{ &dibusb_dib3000mb_table[7], NULL },
|
||||||
|
{ &dibusb_dib3000mb_table[8], NULL },
|
||||||
|
},
|
||||||
|
{ "Grandtec USB1.1 DVB-T",
|
||||||
|
{ &dibusb_dib3000mb_table[9], &dibusb_dib3000mb_table[11], NULL },
|
||||||
|
{ &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL },
|
||||||
|
},
|
||||||
|
{ "Unkown USB1.1 DVB-T device ???? please report the name to the author",
|
||||||
|
{ &dibusb_dib3000mb_table[13], NULL },
|
||||||
|
{ &dibusb_dib3000mb_table[14], NULL },
|
||||||
|
},
|
||||||
|
{ "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device",
|
||||||
|
{ &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL},
|
||||||
|
{ &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL},
|
||||||
|
},
|
||||||
|
{ "Artec T1 USB1.1 TVBOX with AN2135",
|
||||||
|
{ &dibusb_dib3000mb_table[19], NULL },
|
||||||
|
{ &dibusb_dib3000mb_table[20], NULL },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dvb_usb_properties dibusb1_1_an2235_properties = {
|
||||||
|
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
|
.usb_ctrl = CYPRESS_AN2235,
|
||||||
|
|
||||||
|
.firmware = "dvb-usb-dibusb-an2235-01.fw",
|
||||||
|
|
||||||
|
.size_of_priv = sizeof(struct dibusb_state),
|
||||||
|
|
||||||
|
.streaming_ctrl = dibusb_streaming_ctrl,
|
||||||
|
.pid_filter = dibusb_pid_filter,
|
||||||
|
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||||
|
.power_ctrl = dibusb_power_ctrl,
|
||||||
|
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||||
|
.tuner_attach = dibusb_dib3000mb_tuner_attach,
|
||||||
|
|
||||||
|
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||||
|
.rc_key_map = dibusb_rc_keys,
|
||||||
|
.rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||||
|
.rc_query = dibusb_rc_query,
|
||||||
|
|
||||||
|
.i2c_algo = &dibusb_i2c_algo,
|
||||||
|
|
||||||
|
.generic_bulk_ctrl_endpoint = 0x01,
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 7,
|
||||||
|
.endpoint = 0x02,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 4096,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 1,
|
||||||
|
.devices = {
|
||||||
|
{ "Artec T1 USB1.1 TVBOX with AN2235",
|
||||||
|
{ &dibusb_dib3000mb_table[20], NULL },
|
||||||
|
{ &dibusb_dib3000mb_table[21], NULL },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dvb_usb_properties dibusb2_0b_properties = {
|
||||||
|
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
|
|
||||||
|
.firmware = "dvb-usb-adstech-usb2-01.fw",
|
||||||
|
|
||||||
|
.size_of_priv = sizeof(struct dibusb_state),
|
||||||
|
|
||||||
|
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||||
|
.pid_filter = dibusb_pid_filter,
|
||||||
|
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||||
|
.power_ctrl = dibusb2_0_power_ctrl,
|
||||||
|
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||||
|
.tuner_attach = dibusb_dib3000mb_tuner_attach,
|
||||||
|
|
||||||
|
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||||
|
.rc_key_map = dibusb_rc_keys,
|
||||||
|
.rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||||
|
.rc_query = dibusb_rc_query,
|
||||||
|
|
||||||
|
.i2c_algo = &dibusb_i2c_algo,
|
||||||
|
|
||||||
|
.generic_bulk_ctrl_endpoint = 0x01,
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 7,
|
||||||
|
.endpoint = 0x06,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 4096,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 2,
|
||||||
|
.devices = {
|
||||||
|
{ "KWorld/ADSTech Instant DVB-T USB 2.0",
|
||||||
|
{ &dibusb_dib3000mb_table[23], NULL },
|
||||||
|
{ &dibusb_dib3000mb_table[24], NULL }, /* device ID with default DIBUSB2_0-firmware */
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usb_driver dibusb_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "DiBcom based USB DVB-T devices (DiB3000M-B based)",
|
||||||
|
.probe = dibusb_probe,
|
||||||
|
.disconnect = dvb_usb_device_exit,
|
||||||
|
.id_table = dibusb_dib3000mb_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* module stuff */
|
||||||
|
static int __init dibusb_module_init(void)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if ((result = usb_register(&dibusb_driver))) {
|
||||||
|
err("usb_register failed. Error number %d",result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit dibusb_module_exit(void)
|
||||||
|
{
|
||||||
|
/* deregister this driver from the USB subsystem */
|
||||||
|
usb_deregister(&dibusb_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init (dibusb_module_init);
|
||||||
|
module_exit (dibusb_module_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||||
|
MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)");
|
||||||
|
MODULE_VERSION("1.0");
|
||||||
|
MODULE_LICENSE("GPL");
|
116
drivers/media/dvb/dvb-usb/dibusb-mc.c
Normal file
116
drivers/media/dvb/dvb-usb/dibusb-mc.c
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
|
||||||
|
* reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* based on GPL code from DiBcom, which has
|
||||||
|
* Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "dibusb.h"
|
||||||
|
|
||||||
|
/* USB Driver stuff */
|
||||||
|
static struct dvb_usb_properties dibusb_mc_properties;
|
||||||
|
|
||||||
|
static int dibusb_mc_probe(struct usb_interface *intf,
|
||||||
|
const struct usb_device_id *id)
|
||||||
|
{
|
||||||
|
return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do not change the order of the ID table */
|
||||||
|
static struct usb_device_id dibusb_dib3000mc_table [] = {
|
||||||
|
/* 00 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) },
|
||||||
|
/* 01 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) },
|
||||||
|
/* 02 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
|
||||||
|
{ } /* Terminating entry */
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
|
||||||
|
|
||||||
|
static struct dvb_usb_properties dibusb_mc_properties = {
|
||||||
|
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
|
.pid_filter_count = 32,
|
||||||
|
|
||||||
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
|
.firmware = "dvb-usb-dibusb-6.0.0.8.fw",
|
||||||
|
|
||||||
|
.size_of_priv = sizeof(struct dibusb_state),
|
||||||
|
|
||||||
|
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||||
|
.pid_filter = dibusb_pid_filter,
|
||||||
|
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||||
|
.power_ctrl = dibusb2_0_power_ctrl,
|
||||||
|
.frontend_attach = dibusb_dib3000mc_frontend_attach,
|
||||||
|
.tuner_attach = dibusb_dib3000mc_tuner_attach,
|
||||||
|
|
||||||
|
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||||
|
.rc_key_map = dibusb_rc_keys,
|
||||||
|
.rc_key_map_size = 63, /* FIXME */
|
||||||
|
.rc_query = dibusb_rc_query,
|
||||||
|
|
||||||
|
.i2c_algo = &dibusb_i2c_algo,
|
||||||
|
|
||||||
|
.generic_bulk_ctrl_endpoint = 0x01,
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 7,
|
||||||
|
.endpoint = 0x06,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 4096,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 2,
|
||||||
|
.devices = {
|
||||||
|
{ "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
|
||||||
|
{ &dibusb_dib3000mc_table[0], NULL },
|
||||||
|
{ &dibusb_dib3000mc_table[1], NULL },
|
||||||
|
},
|
||||||
|
{ "Artec T1 USB2.0 TVBOX (please report the warm ID)",
|
||||||
|
{ &dibusb_dib3000mc_table[2], NULL },
|
||||||
|
{ NULL },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usb_driver dibusb_mc_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "DiBcom based USB2.0 DVB-T (DiB3000M-C/P based) devices",
|
||||||
|
.probe = dibusb_mc_probe,
|
||||||
|
.disconnect = dvb_usb_device_exit,
|
||||||
|
.id_table = dibusb_dib3000mc_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* module stuff */
|
||||||
|
static int __init dibusb_mc_module_init(void)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if ((result = usb_register(&dibusb_mc_driver))) {
|
||||||
|
err("usb_register failed. Error number %d",result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit dibusb_mc_module_exit(void)
|
||||||
|
{
|
||||||
|
/* deregister this driver from the USB subsystem */
|
||||||
|
usb_deregister(&dibusb_mc_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init (dibusb_mc_module_init);
|
||||||
|
module_exit (dibusb_mc_module_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||||
|
MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices");
|
||||||
|
MODULE_VERSION("1.0");
|
||||||
|
MODULE_LICENSE("GPL");
|
122
drivers/media/dvb/dvb-usb/dibusb.h
Normal file
122
drivers/media/dvb/dvb-usb/dibusb.h
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/* Header file for all dibusb-based-receivers.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#ifndef _DVB_USB_DIBUSB_H_
|
||||||
|
#define _DVB_USB_DIBUSB_H_
|
||||||
|
|
||||||
|
#define DVB_USB_LOG_PREFIX "dibusb"
|
||||||
|
#include "dvb-usb.h"
|
||||||
|
|
||||||
|
#include "dib3000.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* protocol of all dibusb related devices
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bulk msg to/from endpoint 0x01
|
||||||
|
*
|
||||||
|
* general structure:
|
||||||
|
* request_byte parameter_bytes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DIBUSB_REQ_START_READ 0x00
|
||||||
|
#define DIBUSB_REQ_START_DEMOD 0x01
|
||||||
|
|
||||||
|
/*
|
||||||
|
* i2c read
|
||||||
|
* bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
|
||||||
|
* bulk read: byte_buffer (length_word bytes)
|
||||||
|
*/
|
||||||
|
#define DIBUSB_REQ_I2C_READ 0x02
|
||||||
|
|
||||||
|
/*
|
||||||
|
* i2c write
|
||||||
|
* bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes
|
||||||
|
*/
|
||||||
|
#define DIBUSB_REQ_I2C_WRITE 0x03
|
||||||
|
|
||||||
|
/*
|
||||||
|
* polling the value of the remote control
|
||||||
|
* bulk write: 0x04
|
||||||
|
* bulk read: byte_buffer (5 bytes)
|
||||||
|
*/
|
||||||
|
#define DIBUSB_REQ_POLL_REMOTE 0x04
|
||||||
|
|
||||||
|
/* additional status values for Hauppauge Remote Control Protocol */
|
||||||
|
#define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED 0x01
|
||||||
|
#define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY 0x03
|
||||||
|
|
||||||
|
/* streaming mode:
|
||||||
|
* bulk write: 0x05 mode_byte
|
||||||
|
*
|
||||||
|
* mode_byte is mostly 0x00
|
||||||
|
*/
|
||||||
|
#define DIBUSB_REQ_SET_STREAMING_MODE 0x05
|
||||||
|
|
||||||
|
/* interrupt the internal read loop, when blocking */
|
||||||
|
#define DIBUSB_REQ_INTR_READ 0x06
|
||||||
|
|
||||||
|
/* io control
|
||||||
|
* 0x07 cmd_byte param_bytes
|
||||||
|
*
|
||||||
|
* param_bytes can be up to 32 bytes
|
||||||
|
*
|
||||||
|
* cmd_byte function parameter name
|
||||||
|
* 0x00 power mode
|
||||||
|
* 0x00 sleep
|
||||||
|
* 0x01 wakeup
|
||||||
|
*
|
||||||
|
* 0x01 enable streaming
|
||||||
|
* 0x02 disable streaming
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define DIBUSB_REQ_SET_IOCTL 0x07
|
||||||
|
|
||||||
|
/* IOCTL commands */
|
||||||
|
|
||||||
|
/* change the power mode in firmware */
|
||||||
|
#define DIBUSB_IOCTL_CMD_POWER_MODE 0x00
|
||||||
|
#define DIBUSB_IOCTL_POWER_SLEEP 0x00
|
||||||
|
#define DIBUSB_IOCTL_POWER_WAKEUP 0x01
|
||||||
|
|
||||||
|
/* modify streaming of the FX2 */
|
||||||
|
#define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01
|
||||||
|
#define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02
|
||||||
|
|
||||||
|
struct dibusb_state {
|
||||||
|
struct dib_fe_xfer_ops ops;
|
||||||
|
|
||||||
|
/* for RC5 remote control */
|
||||||
|
int old_toggle;
|
||||||
|
int last_repeat_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct i2c_algorithm dibusb_i2c_algo;
|
||||||
|
|
||||||
|
extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *);
|
||||||
|
extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *);
|
||||||
|
|
||||||
|
extern int dibusb_streaming_ctrl(struct dvb_usb_device *, int);
|
||||||
|
extern int dibusb_pid_filter(struct dvb_usb_device *, int, u16, int);
|
||||||
|
extern int dibusb_pid_filter_ctrl(struct dvb_usb_device *, int);
|
||||||
|
extern int dibusb_power_ctrl(struct dvb_usb_device *, int);
|
||||||
|
extern int dibusb2_0_streaming_ctrl(struct dvb_usb_device *, int);
|
||||||
|
extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
|
||||||
|
|
||||||
|
#define DEFAULT_RC_INTERVAL 150
|
||||||
|
//#define DEFAULT_RC_INTERVAL 100000
|
||||||
|
|
||||||
|
extern struct dvb_usb_rc_key dibusb_rc_keys[];
|
||||||
|
extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
|
||||||
|
extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
|
||||||
|
|
||||||
|
#endif
|
282
drivers/media/dvb/dvb-usb/digitv.c
Normal file
282
drivers/media/dvb/dvb-usb/digitv.c
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
/* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0
|
||||||
|
* receiver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) and
|
||||||
|
* Allan Third (allan.third@cs.man.ac.uk)
|
||||||
|
*
|
||||||
|
* partly based on the SDK published by Nebula Electronics (TODO do we want this line ?)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "digitv.h"
|
||||||
|
|
||||||
|
#include "mt352.h"
|
||||||
|
#include "nxt6000.h"
|
||||||
|
|
||||||
|
/* debug */
|
||||||
|
int dvb_usb_digitv_debug;
|
||||||
|
module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
|
||||||
|
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
|
||||||
|
|
||||||
|
static int digitv_ctrl_msg(struct dvb_usb_device *d,
|
||||||
|
u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
|
||||||
|
{
|
||||||
|
int wo = (rbuf == NULL || rlen == 0); /* write-only */
|
||||||
|
u8 sndbuf[7],rcvbuf[7];
|
||||||
|
memset(sndbuf,0,7); memset(rcvbuf,0,7);
|
||||||
|
|
||||||
|
sndbuf[0] = cmd;
|
||||||
|
sndbuf[1] = vv;
|
||||||
|
sndbuf[2] = wo ? wlen : rlen;
|
||||||
|
|
||||||
|
if (!wo) {
|
||||||
|
memcpy(&sndbuf[3],wbuf,wlen);
|
||||||
|
dvb_usb_generic_write(d,sndbuf,7);
|
||||||
|
} else {
|
||||||
|
dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10);
|
||||||
|
memcpy(&rbuf,&rcvbuf[3],rlen);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* I2C */
|
||||||
|
static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (down_interruptible(&d->i2c_sem) < 0)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
|
if (num > 2)
|
||||||
|
warn("more than 2 i2c messages at a time is not handled yet. TODO.");
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
/* write/read request */
|
||||||
|
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
|
||||||
|
if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
|
||||||
|
msg[i+1].buf,msg[i+1].len) < 0)
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
} else
|
||||||
|
if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0],
|
||||||
|
&msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
up(&d->i2c_sem);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 digitv_i2c_func(struct i2c_adapter *adapter)
|
||||||
|
{
|
||||||
|
return I2C_FUNC_I2C;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct i2c_algorithm digitv_i2c_algo = {
|
||||||
|
.name = "Nebula DigiTV USB I2C algorithm",
|
||||||
|
.id = I2C_ALGO_BIT,
|
||||||
|
.master_xfer = digitv_i2c_xfer,
|
||||||
|
.functionality = digitv_i2c_func,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Callbacks for DVB USB */
|
||||||
|
static int digitv_identify_state (struct usb_device *udev, struct
|
||||||
|
dvb_usb_properties *props, struct dvb_usb_device_description **desc,
|
||||||
|
int *cold)
|
||||||
|
{
|
||||||
|
*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int digitv_mt352_demod_init(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
static u8 mt352_clock_config[] = { 0x89, 0x38, 0x2d };
|
||||||
|
static u8 mt352_reset[] = { 0x50, 0x80 };
|
||||||
|
static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
|
||||||
|
|
||||||
|
static u8 mt352_agc_cfg[] = { 0x68, 0xa0 };
|
||||||
|
static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0xa0 };
|
||||||
|
static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
|
||||||
|
static u8 mt352_agc_target[] = { 0x67, 0x20 };
|
||||||
|
|
||||||
|
static u8 mt352_rs_err_per[] = { 0x7c, 0x00, 0x01 };
|
||||||
|
static u8 mt352_snr_select[] = { 0x79, 0x00, 0x20 };
|
||||||
|
|
||||||
|
static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x05 };
|
||||||
|
|
||||||
|
static u8 mt352_scan_ctl[] = { 0x88, 0x0f };
|
||||||
|
static u8 mt352_capt_range[] = { 0x75, 0x32 };
|
||||||
|
|
||||||
|
mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
|
||||||
|
mt352_write(fe, mt352_reset, sizeof(mt352_reset));
|
||||||
|
msleep(1);
|
||||||
|
mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
|
||||||
|
|
||||||
|
mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
|
||||||
|
mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
|
||||||
|
mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
|
||||||
|
mt352_write(fe, mt352_agc_target, sizeof(mt352_agc_target));
|
||||||
|
|
||||||
|
|
||||||
|
mt352_write(fe, mt352_rs_err_per, sizeof(mt352_rs_err_per));
|
||||||
|
mt352_write(fe, mt352_snr_select, sizeof(mt352_snr_select));
|
||||||
|
|
||||||
|
mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
|
||||||
|
|
||||||
|
mt352_write(fe, mt352_scan_ctl, sizeof(mt352_scan_ctl));
|
||||||
|
mt352_write(fe, mt352_capt_range, sizeof(mt352_capt_range));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mt352_config digitv_mt352_config = {
|
||||||
|
.demod_address = 0x0, /* ignored by the digitv anyway */
|
||||||
|
.demod_init = digitv_mt352_demod_init,
|
||||||
|
.pll_set = NULL, /* TODO */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct nxt6000_config digitv_nxt6000_config = {
|
||||||
|
.demod_address = 0x0, /* ignored by the digitv anyway */
|
||||||
|
.clock_inversion = 0x0,
|
||||||
|
|
||||||
|
.pll_init = NULL,
|
||||||
|
.pll_set = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int digitv_frontend_attach(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) == NULL)
|
||||||
|
return 0;
|
||||||
|
if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) == NULL) {
|
||||||
|
|
||||||
|
warn("nxt6000 support is not done yet, in fact you are one of the first "
|
||||||
|
"person who wants to use this device in Linux. Please report to "
|
||||||
|
"linux-dvb@linuxtv.org");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dvb_usb_rc_key digitv_rc_keys[] = {
|
||||||
|
{ 0x00, 0x16, KEY_POWER }, /* dummy key */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TODO is it really the NEC protocol ? */
|
||||||
|
int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||||
|
{
|
||||||
|
u8 key[5];
|
||||||
|
|
||||||
|
digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
|
||||||
|
/* TODO state, maybe it is VV ? */
|
||||||
|
if (key[1] != 0)
|
||||||
|
key[0] = 0x01; /* if something is inside the buffer, simulate key press */
|
||||||
|
|
||||||
|
/* call the universal NEC remote processor, to find out the key's state and event */
|
||||||
|
dvb_usb_nec_rc_key_to_event(d,key,event,state);
|
||||||
|
if (key[0] != 0)
|
||||||
|
deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* DVB USB Driver stuff */
|
||||||
|
static struct dvb_usb_properties digitv_properties;
|
||||||
|
|
||||||
|
static int digitv_probe(struct usb_interface *intf,
|
||||||
|
const struct usb_device_id *id)
|
||||||
|
{
|
||||||
|
return dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usb_device_id digitv_table [] = {
|
||||||
|
{ USB_DEVICE(USB_VID_ANCHOR, USB_PID_NEBULA_DIGITV) },
|
||||||
|
{ } /* Terminating entry */
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE (usb, digitv_table);
|
||||||
|
|
||||||
|
static struct dvb_usb_properties digitv_properties = {
|
||||||
|
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
|
|
||||||
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
|
.firmware = "dvb-usb-digitv-01.fw",
|
||||||
|
|
||||||
|
.size_of_priv = 0,
|
||||||
|
|
||||||
|
.streaming_ctrl = NULL,
|
||||||
|
.pid_filter = NULL,
|
||||||
|
.pid_filter_ctrl = NULL,
|
||||||
|
.power_ctrl = NULL,
|
||||||
|
.frontend_attach = digitv_frontend_attach,
|
||||||
|
.tuner_attach = NULL, // digitv_tuner_attach,
|
||||||
|
.read_mac_address = NULL,
|
||||||
|
|
||||||
|
.rc_interval = 1000,
|
||||||
|
.rc_key_map = digitv_rc_keys,
|
||||||
|
.rc_key_map_size = ARRAY_SIZE(digitv_rc_keys),
|
||||||
|
.rc_query = digitv_rc_query,
|
||||||
|
|
||||||
|
.identify_state = digitv_identify_state,
|
||||||
|
|
||||||
|
.i2c_algo = &digitv_i2c_algo,
|
||||||
|
|
||||||
|
.generic_bulk_ctrl_endpoint = 0x01,
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 7,
|
||||||
|
.endpoint = 0x02,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 4096,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 2,
|
||||||
|
.devices = {
|
||||||
|
{ "Nebula Electronics uDigiTV DVB-T USB2.0)",
|
||||||
|
{ &digitv_table[0], NULL },
|
||||||
|
{ NULL },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usb_driver digitv_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "Nebula Electronics uDigiTV DVB-T USB2.0 device",
|
||||||
|
.probe = digitv_probe,
|
||||||
|
.disconnect = dvb_usb_device_exit,
|
||||||
|
.id_table = digitv_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* module stuff */
|
||||||
|
static int __init digitv_module_init(void)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if ((result = usb_register(&digitv_driver))) {
|
||||||
|
err("usb_register failed. Error number %d",result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit digitv_module_exit(void)
|
||||||
|
{
|
||||||
|
/* deregister this driver from the USB subsystem */
|
||||||
|
usb_deregister(&digitv_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init (digitv_module_init);
|
||||||
|
module_exit (digitv_module_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||||
|
MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0");
|
||||||
|
MODULE_VERSION("1.0-alpha");
|
||||||
|
MODULE_LICENSE("GPL");
|
65
drivers/media/dvb/dvb-usb/digitv.h
Normal file
65
drivers/media/dvb/dvb-usb/digitv.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef _DVB_USB_DIGITV_H_
|
||||||
|
#define _DVB_USB_DIGITV_H_
|
||||||
|
|
||||||
|
#define DVB_USB_LOG_PREFIX "digitv"
|
||||||
|
#include "dvb-usb.h"
|
||||||
|
|
||||||
|
extern int dvb_usb_digitv_debug;
|
||||||
|
#define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
|
||||||
|
|
||||||
|
/* protocol (from usblogging and the SDK:
|
||||||
|
*
|
||||||
|
* Always 7 bytes bulk message(s) for controlling
|
||||||
|
*
|
||||||
|
* First byte describes the command. Reads are 2 consecutive transfer (as always).
|
||||||
|
*
|
||||||
|
* General structure:
|
||||||
|
*
|
||||||
|
* write or first message of a read:
|
||||||
|
* <cmdbyte> VV <len> B0 B1 B2 B3
|
||||||
|
*
|
||||||
|
* second message of a read
|
||||||
|
* <cmdbyte> VV <len> R0 R1 R2 R3
|
||||||
|
*
|
||||||
|
* whereas 0 < len <= 4
|
||||||
|
*
|
||||||
|
* I2C address is stored somewhere inside the device.
|
||||||
|
*
|
||||||
|
* 0x01 read from EEPROM
|
||||||
|
* VV = offset; B* = 0; R* = value(s)
|
||||||
|
*
|
||||||
|
* 0x02 read register of the COFDM
|
||||||
|
* VV = register; B* = 0; R* = value(s)
|
||||||
|
*
|
||||||
|
* 0x05 write register of the COFDM
|
||||||
|
* VV = register; B* = value(s);
|
||||||
|
*
|
||||||
|
* 0x06 write to the tuner (only for NXT6000)
|
||||||
|
* VV = 0; B* = PLL data; len = 4;
|
||||||
|
*
|
||||||
|
* 0x03 read remote control
|
||||||
|
* VV = 0; B* = 0; len = 4; R* = key
|
||||||
|
*
|
||||||
|
* 0x07 write to the remote (don't know why one should this, resetting ?)
|
||||||
|
* VV = 0; B* = key; len = 4;
|
||||||
|
*
|
||||||
|
* 0x08 write remote type
|
||||||
|
* VV = 0; B[0] = 0x01, len = 4
|
||||||
|
*
|
||||||
|
* 0x09 write device init
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
#define USB_READ_EEPROM 1
|
||||||
|
|
||||||
|
#define USB_READ_COFDM 2
|
||||||
|
#define USB_WRITE_COFDM 5
|
||||||
|
|
||||||
|
#define USB_WRITE_TUNER 6
|
||||||
|
|
||||||
|
#define USB_READ_REMOTE 3
|
||||||
|
#define USB_WRITE_REMOTE 7
|
||||||
|
#define USB_WRITE_REMOTE_TYPE 8
|
||||||
|
|
||||||
|
#define USB_DEV_INIT 9
|
||||||
|
|
||||||
|
#endif
|
206
drivers/media/dvb/dvb-usb/dtt200u-fe.c
Normal file
206
drivers/media/dvb/dvb-usb/dtt200u-fe.c
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
/* Frontend part of the Linux driver for the Yakumo/Hama/Typhoon DVB-T
|
||||||
|
* USB2.0 receiver.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "dtt200u.h"
|
||||||
|
|
||||||
|
struct dtt200u_fe_state {
|
||||||
|
struct dvb_usb_device *d;
|
||||||
|
|
||||||
|
struct dvb_frontend_parameters fep;
|
||||||
|
struct dvb_frontend frontend;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define moan(which,what) info("unexpected value in '%s' for cmd '%02x' - please report to linux-dvb@linuxtv.org",which,what)
|
||||||
|
|
||||||
|
static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
|
||||||
|
{
|
||||||
|
struct dtt200u_fe_state *state = fe->demodulator_priv;
|
||||||
|
u8 bw = GET_TUNE_STAT;
|
||||||
|
u8 br[3] = { 0 };
|
||||||
|
// u8 bdeb[5] = { 0 };
|
||||||
|
|
||||||
|
dvb_usb_generic_rw(state->d,&bw,1,br,3,0);
|
||||||
|
switch (br[0]) {
|
||||||
|
case 0x01:
|
||||||
|
*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
|
||||||
|
break;
|
||||||
|
case 0x00:
|
||||||
|
*stat = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
moan("br[0]",GET_TUNE_STAT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bw[0] = 0x88;
|
||||||
|
// dvb_usb_generic_rw(state->d,bw,1,bdeb,5,0);
|
||||||
|
|
||||||
|
// deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
|
||||||
|
{
|
||||||
|
struct dtt200u_fe_state *state = fe->demodulator_priv;
|
||||||
|
u8 bw = GET_BER;
|
||||||
|
*ber = 0;
|
||||||
|
dvb_usb_generic_rw(state->d,&bw,1,(u8*) ber,3,0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
|
||||||
|
{
|
||||||
|
struct dtt200u_fe_state *state = fe->demodulator_priv;
|
||||||
|
u8 bw = GET_UNK;
|
||||||
|
*unc = 0;
|
||||||
|
dvb_usb_generic_rw(state->d,&bw,1,(u8*) unc,3,0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
|
||||||
|
{
|
||||||
|
struct dtt200u_fe_state *state = fe->demodulator_priv;
|
||||||
|
u8 bw = GET_SIG_STRENGTH, b;
|
||||||
|
dvb_usb_generic_rw(state->d,&bw,1,&b,1,0);
|
||||||
|
*strength = (b << 8) | b;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
|
||||||
|
{
|
||||||
|
struct dtt200u_fe_state *state = fe->demodulator_priv;
|
||||||
|
u8 bw = GET_SNR,br;
|
||||||
|
dvb_usb_generic_rw(state->d,&bw,1,&br,1,0);
|
||||||
|
*snr = ~((br << 8) | br);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dtt200u_fe_init(struct dvb_frontend* fe)
|
||||||
|
{
|
||||||
|
struct dtt200u_fe_state *state = fe->demodulator_priv;
|
||||||
|
u8 b = RESET_DEMOD;
|
||||||
|
return dvb_usb_generic_write(state->d,&b,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dtt200u_fe_sleep(struct dvb_frontend* fe)
|
||||||
|
{
|
||||||
|
return dtt200u_fe_init(fe);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
|
||||||
|
{
|
||||||
|
tune->min_delay_ms = 1500;
|
||||||
|
tune->step_size = 166667;
|
||||||
|
tune->max_drift = 166667 * 2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
|
||||||
|
struct dvb_frontend_parameters *fep)
|
||||||
|
{
|
||||||
|
struct dtt200u_fe_state *state = fe->demodulator_priv;
|
||||||
|
u16 freq = fep->frequency / 250000;
|
||||||
|
u8 bw,bwbuf[2] = { SET_BANDWIDTH, 0 }, freqbuf[3] = { SET_FREQUENCY, 0, 0 };
|
||||||
|
|
||||||
|
switch (fep->u.ofdm.bandwidth) {
|
||||||
|
case BANDWIDTH_8_MHZ: bw = 8; break;
|
||||||
|
case BANDWIDTH_7_MHZ: bw = 7; break;
|
||||||
|
case BANDWIDTH_6_MHZ: bw = 6; break;
|
||||||
|
case BANDWIDTH_AUTO: return -EOPNOTSUPP;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
deb_info("set_frontend\n");
|
||||||
|
|
||||||
|
bwbuf[1] = bw;
|
||||||
|
dvb_usb_generic_write(state->d,bwbuf,2);
|
||||||
|
|
||||||
|
freqbuf[1] = freq & 0xff;
|
||||||
|
freqbuf[2] = (freq >> 8) & 0xff;
|
||||||
|
dvb_usb_generic_write(state->d,freqbuf,3);
|
||||||
|
|
||||||
|
memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
|
||||||
|
struct dvb_frontend_parameters *fep)
|
||||||
|
{
|
||||||
|
struct dtt200u_fe_state *state = fe->demodulator_priv;
|
||||||
|
memcpy(fep,&state->fep,sizeof(struct dvb_frontend_parameters));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dtt200u_fe_release(struct dvb_frontend* fe)
|
||||||
|
{
|
||||||
|
struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
|
||||||
|
kfree(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dvb_frontend_ops dtt200u_fe_ops;
|
||||||
|
|
||||||
|
struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
struct dtt200u_fe_state* state = NULL;
|
||||||
|
|
||||||
|
/* allocate memory for the internal state */
|
||||||
|
state = (struct dtt200u_fe_state*) kmalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
|
||||||
|
if (state == NULL)
|
||||||
|
goto error;
|
||||||
|
memset(state,0,sizeof(struct dtt200u_fe_state));
|
||||||
|
|
||||||
|
deb_info("attaching frontend dtt200u\n");
|
||||||
|
|
||||||
|
state->d = d;
|
||||||
|
|
||||||
|
state->frontend.ops = &dtt200u_fe_ops;
|
||||||
|
state->frontend.demodulator_priv = state;
|
||||||
|
|
||||||
|
goto success;
|
||||||
|
error:
|
||||||
|
return NULL;
|
||||||
|
success:
|
||||||
|
return &state->frontend;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dvb_frontend_ops dtt200u_fe_ops = {
|
||||||
|
.info = {
|
||||||
|
.name = "DTT200U (Yakumo/Typhoon/Hama) DVB-T",
|
||||||
|
.type = FE_OFDM,
|
||||||
|
.frequency_min = 44250000,
|
||||||
|
.frequency_max = 867250000,
|
||||||
|
.frequency_stepsize = 250000,
|
||||||
|
.caps = FE_CAN_INVERSION_AUTO |
|
||||||
|
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||||
|
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||||
|
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
|
||||||
|
FE_CAN_TRANSMISSION_MODE_AUTO |
|
||||||
|
FE_CAN_GUARD_INTERVAL_AUTO |
|
||||||
|
FE_CAN_RECOVER |
|
||||||
|
FE_CAN_HIERARCHY_AUTO,
|
||||||
|
},
|
||||||
|
|
||||||
|
.release = dtt200u_fe_release,
|
||||||
|
|
||||||
|
.init = dtt200u_fe_init,
|
||||||
|
.sleep = dtt200u_fe_sleep,
|
||||||
|
|
||||||
|
.set_frontend = dtt200u_fe_set_frontend,
|
||||||
|
.get_frontend = dtt200u_fe_get_frontend,
|
||||||
|
.get_tune_settings = dtt200u_fe_get_tune_settings,
|
||||||
|
|
||||||
|
.read_status = dtt200u_fe_read_status,
|
||||||
|
.read_ber = dtt200u_fe_read_ber,
|
||||||
|
.read_signal_strength = dtt200u_fe_read_signal_strength,
|
||||||
|
.read_snr = dtt200u_fe_read_snr,
|
||||||
|
.read_ucblocks = dtt200u_fe_read_unc_blocks,
|
||||||
|
};
|
171
drivers/media/dvb/dvb-usb/dtt200u.c
Normal file
171
drivers/media/dvb/dvb-usb/dtt200u.c
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
/* DVB USB library compliant Linux driver for the Yakumo/Hama/Typhoon DVB-T
|
||||||
|
* USB2.0 receiver.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "dtt200u.h"
|
||||||
|
|
||||||
|
/* debug */
|
||||||
|
int dvb_usb_dtt200u_debug;
|
||||||
|
module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
|
||||||
|
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
|
||||||
|
|
||||||
|
static int dtt200u_streaming_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
u8 b_streaming[2] = { SET_TS_CTRL, onoff };
|
||||||
|
u8 b_rst_pid = RESET_PID_FILTER;
|
||||||
|
|
||||||
|
dvb_usb_generic_write(d,b_streaming,2);
|
||||||
|
|
||||||
|
if (!onoff)
|
||||||
|
dvb_usb_generic_write(d,&b_rst_pid,1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dtt200u_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
|
||||||
|
{
|
||||||
|
u8 b_pid[4];
|
||||||
|
pid = onoff ? pid : 0;
|
||||||
|
|
||||||
|
b_pid[0] = SET_PID_FILTER;
|
||||||
|
b_pid[1] = index;
|
||||||
|
b_pid[2] = pid & 0xff;
|
||||||
|
b_pid[3] = (pid >> 8) & 0xff;
|
||||||
|
|
||||||
|
return dvb_usb_generic_write(d,b_pid,4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remote control */
|
||||||
|
/* key list for the tiny remote control (Yakumo, don't know about the others) */
|
||||||
|
static struct dvb_usb_rc_key dtt200u_rc_keys[] = {
|
||||||
|
{ 0x80, 0x01, KEY_MUTE },
|
||||||
|
{ 0x80, 0x02, KEY_CHANNELDOWN },
|
||||||
|
{ 0x80, 0x03, KEY_VOLUMEDOWN },
|
||||||
|
{ 0x80, 0x04, KEY_1 },
|
||||||
|
{ 0x80, 0x05, KEY_2 },
|
||||||
|
{ 0x80, 0x06, KEY_3 },
|
||||||
|
{ 0x80, 0x07, KEY_4 },
|
||||||
|
{ 0x80, 0x08, KEY_5 },
|
||||||
|
{ 0x80, 0x09, KEY_6 },
|
||||||
|
{ 0x80, 0x0a, KEY_7 },
|
||||||
|
{ 0x00, 0x0c, KEY_ZOOM },
|
||||||
|
{ 0x80, 0x0d, KEY_0 },
|
||||||
|
{ 0x00, 0x0e, KEY_SELECT },
|
||||||
|
{ 0x80, 0x12, KEY_POWER },
|
||||||
|
{ 0x80, 0x1a, KEY_CHANNELUP },
|
||||||
|
{ 0x80, 0x1b, KEY_8 },
|
||||||
|
{ 0x80, 0x1e, KEY_VOLUMEUP },
|
||||||
|
{ 0x80, 0x1f, KEY_9 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||||
|
{
|
||||||
|
u8 key[5],cmd = GET_RC_KEY;
|
||||||
|
dvb_usb_generic_rw(d,&cmd,1,key,5,0);
|
||||||
|
dvb_usb_nec_rc_key_to_event(d,key,event,state);
|
||||||
|
if (key[0] != 0)
|
||||||
|
deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dtt200u_frontend_attach(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
d->fe = dtt200u_fe_attach(d);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dvb_usb_properties dtt200u_properties;
|
||||||
|
|
||||||
|
static int dtt200u_usb_probe(struct usb_interface *intf,
|
||||||
|
const struct usb_device_id *id)
|
||||||
|
{
|
||||||
|
return dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usb_device_id dtt200u_usb_table [] = {
|
||||||
|
{ USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_COLD) },
|
||||||
|
{ USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_WARM) },
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
|
||||||
|
|
||||||
|
static struct dvb_usb_properties dtt200u_properties = {
|
||||||
|
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
|
||||||
|
.pid_filter_count = 255, /* It is a guess, but there are at least 10 */
|
||||||
|
|
||||||
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
|
.firmware = "dvb-usb-dtt200u-01.fw",
|
||||||
|
|
||||||
|
.streaming_ctrl = dtt200u_streaming_ctrl,
|
||||||
|
.pid_filter = dtt200u_pid_filter,
|
||||||
|
.frontend_attach = dtt200u_frontend_attach,
|
||||||
|
|
||||||
|
.rc_interval = 200,
|
||||||
|
.rc_key_map = dtt200u_rc_keys,
|
||||||
|
.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
|
||||||
|
.rc_query = dtt200u_rc_query,
|
||||||
|
|
||||||
|
.generic_bulk_ctrl_endpoint = 0x01,
|
||||||
|
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 7,
|
||||||
|
.endpoint = 0x02,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 4096,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 1,
|
||||||
|
.devices = {
|
||||||
|
{ .name = "Yakumo/Hama/Typhoon DVB-T USB2.0)",
|
||||||
|
.cold_ids = { &dtt200u_usb_table[0], &dtt200u_usb_table[2] },
|
||||||
|
.warm_ids = { &dtt200u_usb_table[1], NULL },
|
||||||
|
},
|
||||||
|
{ 0 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* usb specific object needed to register this driver with the usb subsystem */
|
||||||
|
static struct usb_driver dtt200u_usb_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "Yakumo/Hama/Typhoon DVB-T USB2.0",
|
||||||
|
.probe = dtt200u_usb_probe,
|
||||||
|
.disconnect = dvb_usb_device_exit,
|
||||||
|
.id_table = dtt200u_usb_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* module stuff */
|
||||||
|
static int __init dtt200u_usb_module_init(void)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if ((result = usb_register(&dtt200u_usb_driver))) {
|
||||||
|
err("usb_register failed. (%d)",result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit dtt200u_usb_module_exit(void)
|
||||||
|
{
|
||||||
|
/* deregister this driver from the USB subsystem */
|
||||||
|
usb_deregister(&dtt200u_usb_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(dtt200u_usb_module_init);
|
||||||
|
module_exit(dtt200u_usb_module_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||||
|
MODULE_DESCRIPTION("Driver for the Yakumo/Hama/Typhoon DVB-T USB2.0 device");
|
||||||
|
MODULE_VERSION("1.0");
|
||||||
|
MODULE_LICENSE("GPL");
|
66
drivers/media/dvb/dvb-usb/dtt200u.h
Normal file
66
drivers/media/dvb/dvb-usb/dtt200u.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* Common header file of Linux driver for the Yakumo/Hama/Typhoon DVB-T
|
||||||
|
* USB2.0 receiver.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#ifndef _DVB_USB_DTT200U_H_
|
||||||
|
#define _DVB_USB_DTT200U_H_
|
||||||
|
|
||||||
|
#define DVB_USB_LOG_PREFIX "dtt200u"
|
||||||
|
#include "dvb-usb.h"
|
||||||
|
|
||||||
|
extern int dvb_usb_dtt200u_debug;
|
||||||
|
#define deb_info(args...) dprintk(dvb_usb_dtt200u_debug,0x01,args)
|
||||||
|
#define deb_xfer(args...) dprintk(dvb_usb_dtt200u_debug,0x02,args)
|
||||||
|
|
||||||
|
/* guessed protocol description (reverse engineered):
|
||||||
|
* read
|
||||||
|
* 00 - USB type 0x02 for usb2.0, 0x01 for usb1.1
|
||||||
|
* 81 - <TS_LOCK> <current frequency divided by 250000>
|
||||||
|
* 82 - crash - do not touch
|
||||||
|
* 83 - crash - do not touch
|
||||||
|
* 84 - remote control
|
||||||
|
* 85 - crash - do not touch (OK, stop testing here)
|
||||||
|
* 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
|
||||||
|
* 89 - noise-to-signal
|
||||||
|
* 8a - unkown 1 byte - signal_strength
|
||||||
|
* 8c - ber ???
|
||||||
|
* 8d - ber
|
||||||
|
* 8e - unc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GET_SPEED 0x00
|
||||||
|
#define GET_TUNE_STAT 0x81
|
||||||
|
#define GET_RC_KEY 0x84
|
||||||
|
#define GET_STATUS 0x88
|
||||||
|
#define GET_SNR 0x89
|
||||||
|
#define GET_SIG_STRENGTH 0x8a
|
||||||
|
#define GET_UNK 0x8c
|
||||||
|
#define GET_BER 0x8d
|
||||||
|
#define GET_UNC 0x8e
|
||||||
|
|
||||||
|
/* write
|
||||||
|
* 01 - reset the demod
|
||||||
|
* 02 - frequency (divided by 250000)
|
||||||
|
* 03 - bandwidth
|
||||||
|
* 04 - pid table (index pid(7:0) pid(12:8))
|
||||||
|
* 05 - reset the pid table
|
||||||
|
* 08 - demod transfer enabled or not (FX2 transfer is enabled by default)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RESET_DEMOD 0x01
|
||||||
|
#define SET_FREQUENCY 0x02
|
||||||
|
#define SET_BANDWIDTH 0x03
|
||||||
|
#define SET_PID_FILTER 0x04
|
||||||
|
#define RESET_PID_FILTER 0x05
|
||||||
|
#define SET_TS_CTRL 0x08
|
||||||
|
|
||||||
|
extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d);
|
||||||
|
|
||||||
|
#endif
|
44
drivers/media/dvb/dvb-usb/dvb-usb-common.h
Normal file
44
drivers/media/dvb/dvb-usb/dvb-usb-common.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* dvb-usb-common.h is part of the DVB USB library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
* see dvb-usb-init.c for copyright information.
|
||||||
|
*
|
||||||
|
* a header file containing prototypes and types for internal use of the dvb-usb-lib
|
||||||
|
*/
|
||||||
|
#ifndef _DVB_USB_COMMON_H_
|
||||||
|
#define _DVB_USB_COMMON_H_
|
||||||
|
|
||||||
|
#define DVB_USB_LOG_PREFIX "dvb-usb"
|
||||||
|
#include "dvb-usb.h"
|
||||||
|
|
||||||
|
extern int dvb_usb_debug;
|
||||||
|
|
||||||
|
#define deb_info(args...) dprintk(dvb_usb_debug,0x01,args)
|
||||||
|
#define deb_xfer(args...) dprintk(dvb_usb_debug,0x02,args)
|
||||||
|
#define deb_pll(args...) dprintk(dvb_usb_debug,0x04,args)
|
||||||
|
#define deb_ts(args...) dprintk(dvb_usb_debug,0x08,args)
|
||||||
|
#define deb_err(args...) dprintk(dvb_usb_debug,0x10,args)
|
||||||
|
#define deb_rc(args...) dprintk(dvb_usb_debug,0x20,args)
|
||||||
|
#define deb_fw(args...) dprintk(dvb_usb_debug,0x40,args)
|
||||||
|
|
||||||
|
/* commonly used methods */
|
||||||
|
extern int usb_cypress_load_firmware(struct usb_device *, const char *, int);
|
||||||
|
|
||||||
|
extern int dvb_usb_urb_submit(struct dvb_usb_device *);
|
||||||
|
extern int dvb_usb_urb_kill(struct dvb_usb_device *);
|
||||||
|
extern int dvb_usb_urb_init(struct dvb_usb_device *);
|
||||||
|
extern int dvb_usb_urb_exit(struct dvb_usb_device *);
|
||||||
|
|
||||||
|
extern int dvb_usb_i2c_init(struct dvb_usb_device *);
|
||||||
|
extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
|
||||||
|
|
||||||
|
extern int dvb_usb_dvb_init(struct dvb_usb_device *);
|
||||||
|
extern int dvb_usb_dvb_exit(struct dvb_usb_device *);
|
||||||
|
|
||||||
|
extern int dvb_usb_fe_init(struct dvb_usb_device *);
|
||||||
|
extern int dvb_usb_fe_exit(struct dvb_usb_device *);
|
||||||
|
|
||||||
|
extern int dvb_usb_remote_init(struct dvb_usb_device *);
|
||||||
|
extern int dvb_usb_remote_exit(struct dvb_usb_device *);
|
||||||
|
|
||||||
|
#endif
|
210
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
Normal file
210
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/* dvb-usb-dvb.c is part of the DVB USB library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
* see dvb-usb-init.c for copyright information.
|
||||||
|
*
|
||||||
|
* This file contains functions for initializing and handling the
|
||||||
|
* linux-dvb API.
|
||||||
|
*/
|
||||||
|
#include "dvb-usb-common.h"
|
||||||
|
|
||||||
|
static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = dvbdmxfeed->demux->priv;
|
||||||
|
int newfeedcount,ret;
|
||||||
|
|
||||||
|
if (d == NULL)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
newfeedcount = d->feedcount + (onoff ? 1 : -1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* stop feed before setting a new pid if there will be no pid anymore
|
||||||
|
*/
|
||||||
|
if (newfeedcount == 0) {
|
||||||
|
deb_ts("stop feeding\n");
|
||||||
|
|
||||||
|
if (d->props.streaming_ctrl != NULL)
|
||||||
|
if ((ret = d->props.streaming_ctrl(d,0)))
|
||||||
|
err("error while stopping stream.");
|
||||||
|
|
||||||
|
dvb_usb_urb_kill(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
d->feedcount = newfeedcount;
|
||||||
|
|
||||||
|
/* activate the pid on the device specific pid_filter */
|
||||||
|
deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off");
|
||||||
|
if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
|
||||||
|
d->pid_filtering &&
|
||||||
|
d->props.pid_filter != NULL)
|
||||||
|
d->props.pid_filter(d,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
|
||||||
|
|
||||||
|
/* start the feed if this was the first feed and there is still a feed
|
||||||
|
* for reception.
|
||||||
|
*/
|
||||||
|
if (d->feedcount == onoff && d->feedcount > 0) {
|
||||||
|
|
||||||
|
deb_ts("controlling pid parser\n");
|
||||||
|
if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
|
||||||
|
d->props.caps & DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF &&
|
||||||
|
d->props.pid_filter_ctrl != NULL)
|
||||||
|
if (d->props.pid_filter_ctrl(d,d->pid_filtering) < 0)
|
||||||
|
err("could not handle pid_parser");
|
||||||
|
|
||||||
|
deb_ts("start feeding\n");
|
||||||
|
if (d->props.streaming_ctrl != NULL)
|
||||||
|
if (d->props.streaming_ctrl(d,1)) {
|
||||||
|
err("error while enabling fifo.");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
dvb_usb_urb_submit(d);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
|
||||||
|
{
|
||||||
|
deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
|
||||||
|
return dvb_usb_ctrl_feed(dvbdmxfeed,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
|
||||||
|
{
|
||||||
|
deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type);
|
||||||
|
return dvb_usb_ctrl_feed(dvbdmxfeed,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_dvb_init(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
|
||||||
|
d->owner)) < 0) {
|
||||||
|
deb_info("dvb_register_adapter failed: error %d", ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
d->dvb_adap.priv = d;
|
||||||
|
|
||||||
|
if (d->props.read_mac_address) {
|
||||||
|
if (d->props.read_mac_address(d,d->dvb_adap.proposed_mac) == 0)
|
||||||
|
info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",d->dvb_adap.proposed_mac[0],
|
||||||
|
d->dvb_adap.proposed_mac[1],d->dvb_adap.proposed_mac[2],
|
||||||
|
d->dvb_adap.proposed_mac[3],d->dvb_adap.proposed_mac[4],
|
||||||
|
d->dvb_adap.proposed_mac[5]);
|
||||||
|
else
|
||||||
|
err("MAC address reading failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
d->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
|
||||||
|
d->demux.priv = d;
|
||||||
|
|
||||||
|
d->demux.feednum = d->demux.filternum = d->max_feed_count;
|
||||||
|
d->demux.start_feed = dvb_usb_start_feed;
|
||||||
|
d->demux.stop_feed = dvb_usb_stop_feed;
|
||||||
|
d->demux.write_to_decoder = NULL;
|
||||||
|
if ((ret = dvb_dmx_init(&d->demux)) < 0) {
|
||||||
|
err("dvb_dmx_init failed: error %d",ret);
|
||||||
|
goto err_dmx;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->dmxdev.filternum = d->demux.filternum;
|
||||||
|
d->dmxdev.demux = &d->demux.dmx;
|
||||||
|
d->dmxdev.capabilities = 0;
|
||||||
|
if ((ret = dvb_dmxdev_init(&d->dmxdev, &d->dvb_adap)) < 0) {
|
||||||
|
err("dvb_dmxdev_init failed: error %d",ret);
|
||||||
|
goto err_dmx_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
|
||||||
|
|
||||||
|
goto success;
|
||||||
|
err_dmx_dev:
|
||||||
|
dvb_dmx_release(&d->demux);
|
||||||
|
err_dmx:
|
||||||
|
dvb_unregister_adapter(&d->dvb_adap);
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
success:
|
||||||
|
d->state |= DVB_USB_STATE_DVB;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_dvb_exit(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
if (d->state & DVB_USB_STATE_DVB) {
|
||||||
|
deb_info("unregistering DVB part\n");
|
||||||
|
dvb_net_release(&d->dvb_net);
|
||||||
|
d->demux.dmx.close(&d->demux.dmx);
|
||||||
|
dvb_dmxdev_release(&d->dmxdev);
|
||||||
|
dvb_dmx_release(&d->demux);
|
||||||
|
dvb_unregister_adapter(&d->dvb_adap);
|
||||||
|
d->state &= ~DVB_USB_STATE_DVB;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = fe->dvb->priv;
|
||||||
|
|
||||||
|
if (d->props.power_ctrl)
|
||||||
|
d->props.power_ctrl(d,1);
|
||||||
|
|
||||||
|
if (d->fe_init)
|
||||||
|
d->fe_init(fe);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = fe->dvb->priv;
|
||||||
|
|
||||||
|
if (d->fe_sleep)
|
||||||
|
d->fe_sleep(fe);
|
||||||
|
|
||||||
|
if (d->props.power_ctrl)
|
||||||
|
d->props.power_ctrl(d,0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_fe_init(struct dvb_usb_device* d)
|
||||||
|
{
|
||||||
|
if (d->props.frontend_attach == NULL) {
|
||||||
|
err("strange '%s' don't want to attach a frontend.",d->desc->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->props.frontend_attach(d);
|
||||||
|
|
||||||
|
/* re-assign sleep and wakeup functions */
|
||||||
|
if (d->fe != NULL) {
|
||||||
|
d->fe_init = d->fe->ops->init; d->fe->ops->init = dvb_usb_fe_wakeup;
|
||||||
|
d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep;
|
||||||
|
|
||||||
|
if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
|
||||||
|
err("Frontend registration failed.");
|
||||||
|
if (d->fe->ops->release)
|
||||||
|
d->fe->ops->release(d->fe);
|
||||||
|
d->fe = NULL;
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
err("no frontend was attached by '%s'",d->desc->name);
|
||||||
|
|
||||||
|
if (d->props.tuner_attach != NULL)
|
||||||
|
d->props.tuner_attach(d);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_fe_exit(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
if (d->fe != NULL)
|
||||||
|
dvb_unregister_frontend(d->fe);
|
||||||
|
return 0;
|
||||||
|
}
|
100
drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
Normal file
100
drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/* dvb-usb-firmware.c is part of the DVB USB library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
* see dvb-usb-init.c for copyright information.
|
||||||
|
*
|
||||||
|
* This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices.
|
||||||
|
*
|
||||||
|
* FIXME: This part does actually not belong to dvb-usb, but to the usb-subsystem.
|
||||||
|
*/
|
||||||
|
#include "dvb-usb-common.h"
|
||||||
|
|
||||||
|
#include <linux/firmware.h>
|
||||||
|
#include <linux/usb.h>
|
||||||
|
|
||||||
|
struct usb_cypress_controller {
|
||||||
|
int id;
|
||||||
|
const char *name; /* name of the usb controller */
|
||||||
|
u16 cpu_cs_register; /* needs to be restarted, when the firmware has been downloaded. */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usb_cypress_controller cypress[] = {
|
||||||
|
{ .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
|
||||||
|
{ .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
|
||||||
|
{ .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* load a firmware packet to the device
|
||||||
|
*/
|
||||||
|
static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
|
||||||
|
{
|
||||||
|
return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
|
||||||
|
0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type)
|
||||||
|
{
|
||||||
|
const struct firmware *fw = NULL;
|
||||||
|
u16 addr;
|
||||||
|
u8 *b,*p;
|
||||||
|
int ret = 0,i;
|
||||||
|
|
||||||
|
if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) {
|
||||||
|
err("did not find the firmware file. (%s) "
|
||||||
|
"Please see linux/Documentation/dvb/ for more details on firmware-problems.",
|
||||||
|
filename);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name);
|
||||||
|
|
||||||
|
p = kmalloc(fw->size,GFP_KERNEL);
|
||||||
|
if (p != NULL) {
|
||||||
|
u8 reset;
|
||||||
|
/*
|
||||||
|
* you cannot use the fw->data as buffer for
|
||||||
|
* usb_control_msg, a new buffer has to be
|
||||||
|
* created
|
||||||
|
*/
|
||||||
|
memcpy(p,fw->data,fw->size);
|
||||||
|
|
||||||
|
/* stop the CPU */
|
||||||
|
reset = 1;
|
||||||
|
if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
|
||||||
|
err("could not stop the USB controller CPU.");
|
||||||
|
for(i = 0; p[i+3] == 0 && i < fw->size; ) {
|
||||||
|
b = (u8 *) &p[i];
|
||||||
|
addr = cpu_to_le16( *((u16 *) &b[1]) );
|
||||||
|
|
||||||
|
deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]);
|
||||||
|
|
||||||
|
ret = usb_cypress_writemem(udev,addr,&b[4],b[0]);
|
||||||
|
|
||||||
|
if (ret != b[0]) {
|
||||||
|
err("error while transferring firmware "
|
||||||
|
"(transferred size: %d, block size: %d)",
|
||||||
|
ret,b[0]);
|
||||||
|
ret = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i += 5 + b[0];
|
||||||
|
}
|
||||||
|
/* length in ret */
|
||||||
|
if (ret > 0)
|
||||||
|
ret = 0;
|
||||||
|
/* restart the CPU */
|
||||||
|
reset = 0;
|
||||||
|
if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
|
||||||
|
err("could not restart the USB controller CPU.");
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(p);
|
||||||
|
} else {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
}
|
||||||
|
release_firmware(fw);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
118
drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
Normal file
118
drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/* dvb-usb-i2c.c is part of the DVB USB library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
* see dvb-usb-init.c for copyright information.
|
||||||
|
*
|
||||||
|
* This file contains functions for (de-)initializing an I2C adapter.
|
||||||
|
*/
|
||||||
|
#include "dvb-usb-common.h"
|
||||||
|
|
||||||
|
int dvb_usb_i2c_init(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!(d->props.caps & DVB_USB_IS_AN_I2C_ADAPTER))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (d->props.i2c_algo == NULL) {
|
||||||
|
err("no i2c algorithm specified");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE);
|
||||||
|
#ifdef I2C_ADAP_CLASS_TV_DIGITAL
|
||||||
|
d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
|
||||||
|
#else
|
||||||
|
d->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
|
||||||
|
#endif
|
||||||
|
d->i2c_adap.algo = d->props.i2c_algo;
|
||||||
|
d->i2c_adap.algo_data = NULL;
|
||||||
|
d->i2c_adap.id = I2C_ALGO_BIT;
|
||||||
|
|
||||||
|
i2c_set_adapdata(&d->i2c_adap, d);
|
||||||
|
|
||||||
|
if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0)
|
||||||
|
err("could not add i2c adapter");
|
||||||
|
|
||||||
|
d->state |= DVB_USB_STATE_I2C;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_i2c_exit(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
if (d->state & DVB_USB_STATE_I2C)
|
||||||
|
i2c_del_adapter(&d->i2c_adap);
|
||||||
|
d->state &= ~DVB_USB_STATE_I2C;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = fe->dvb->priv;
|
||||||
|
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* if there is nothing to initialize */
|
||||||
|
if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 &&
|
||||||
|
d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (d->tuner_pass_ctrl)
|
||||||
|
d->tuner_pass_ctrl(fe,1,d->pll_addr);
|
||||||
|
|
||||||
|
deb_pll("pll init: %x\n",d->pll_addr);
|
||||||
|
deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1],
|
||||||
|
d->pll_init[2],d->pll_init[3]);
|
||||||
|
|
||||||
|
if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
|
||||||
|
err("tuner i2c write failed for pll_init.");
|
||||||
|
ret = -EREMOTEIO;
|
||||||
|
}
|
||||||
|
msleep(1);
|
||||||
|
|
||||||
|
if (d->tuner_pass_ctrl)
|
||||||
|
d->tuner_pass_ctrl(fe,0,d->pll_addr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dvb_usb_pll_init_i2c);
|
||||||
|
|
||||||
|
int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5])
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = fe->dvb->priv;
|
||||||
|
|
||||||
|
deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
|
||||||
|
|
||||||
|
b[0] = d->pll_addr << 1;
|
||||||
|
dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth);
|
||||||
|
|
||||||
|
deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dvb_usb_pll_set);
|
||||||
|
|
||||||
|
int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = fe->dvb->priv;
|
||||||
|
int ret = 0;
|
||||||
|
u8 b[5];
|
||||||
|
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
|
||||||
|
|
||||||
|
dvb_usb_pll_set(fe,fep,b);
|
||||||
|
|
||||||
|
if (d->tuner_pass_ctrl)
|
||||||
|
d->tuner_pass_ctrl(fe,1,d->pll_addr);
|
||||||
|
|
||||||
|
if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
|
||||||
|
err("tuner i2c write failed for pll_set.");
|
||||||
|
ret = -EREMOTEIO;
|
||||||
|
}
|
||||||
|
msleep(1);
|
||||||
|
|
||||||
|
if (d->tuner_pass_ctrl)
|
||||||
|
d->tuner_pass_ctrl(fe,0,d->pll_addr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dvb_usb_pll_set_i2c);
|
83
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
Normal file
83
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/* dvb-usb-ids.h is part of the DVB USB library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see
|
||||||
|
* dvb-usb-init.c for copyright information.
|
||||||
|
*
|
||||||
|
* a header file containing define's for the USB device supported by the
|
||||||
|
* various drivers.
|
||||||
|
*/
|
||||||
|
#ifndef _DVB_USB_IDS_H_
|
||||||
|
#define _DVB_USB_IDS_H_
|
||||||
|
|
||||||
|
/* Vendor IDs */
|
||||||
|
#define USB_VID_ADSTECH 0x06e1
|
||||||
|
#define USB_VID_ANCHOR 0x0547
|
||||||
|
#define USB_VID_AVERMEDIA_UNK 0x14aa
|
||||||
|
#define USB_VID_AVERMEDIA 0x07ca
|
||||||
|
#define USB_VID_COMPRO 0x185b
|
||||||
|
#define USB_VID_COMPRO_UNK 0x145f
|
||||||
|
#define USB_VID_CYPRESS 0x04b4
|
||||||
|
#define USB_VID_DIBCOM 0x10b8
|
||||||
|
#define USB_VID_DVICO 0x0fe9
|
||||||
|
#define USB_VID_EMPIA 0xeb1a
|
||||||
|
#define USB_VID_GRANDTEC 0x5032
|
||||||
|
#define USB_VID_HANFTEK 0x15f4
|
||||||
|
#define USB_VID_HAUPPAUGE 0x2040
|
||||||
|
#define USB_VID_HYPER_PALTEK 0x1025
|
||||||
|
#define USB_VID_VISIONPLUS 0x13d3
|
||||||
|
#define USB_VID_TWINHAN 0x1822
|
||||||
|
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
|
||||||
|
|
||||||
|
/* Product IDs */
|
||||||
|
#define USB_PID_ADSTECH_USB2_COLD 0xa333
|
||||||
|
#define USB_PID_ADSTECH_USB2_WARM 0xa334
|
||||||
|
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
|
||||||
|
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
|
||||||
|
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
|
||||||
|
#define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801
|
||||||
|
#define USB_PID_COMPRO_DVBU2000_COLD 0xd000
|
||||||
|
#define USB_PID_COMPRO_DVBU2000_WARM 0xd001
|
||||||
|
#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
|
||||||
|
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
|
||||||
|
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
|
||||||
|
#define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9
|
||||||
|
#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6
|
||||||
|
#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
|
||||||
|
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
|
||||||
|
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
|
||||||
|
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
|
||||||
|
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
|
||||||
|
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
|
||||||
|
#define USB_PID_TWINHAN_VP7041_COLD 0x3201
|
||||||
|
#define USB_PID_TWINHAN_VP7041_WARM 0x3202
|
||||||
|
#define USB_PID_TWINHAN_VP7045_COLD 0x3205
|
||||||
|
#define USB_PID_TWINHAN_VP7045_WARM 0x3206
|
||||||
|
#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
|
||||||
|
#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
|
||||||
|
#define USB_PID_TWINHAN_VP7021_COLD 0x3207
|
||||||
|
#define USB_PID_TWINHAN_VP7021_WARM 0x3208
|
||||||
|
#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
|
||||||
|
#define USB_PID_ULTIMA_TVBOX_WARM 0x8106
|
||||||
|
#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
|
||||||
|
#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108
|
||||||
|
#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235
|
||||||
|
#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109
|
||||||
|
#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
|
||||||
|
#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
|
||||||
|
#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
|
||||||
|
#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f
|
||||||
|
#define USB_PID_HANFTEK_UMT_010_COLD 0x0001
|
||||||
|
#define USB_PID_HANFTEK_UMT_010_WARM 0x0015
|
||||||
|
#define USB_PID_DTT200U_COLD 0x0201
|
||||||
|
#define USB_PID_DTT200U_WARM 0x0301
|
||||||
|
#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
|
||||||
|
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
|
||||||
|
#define USB_PID_NEBULA_DIGITV 0x0201
|
||||||
|
#define USB_PID_DVICO_BLUEBIRD_LGZ201 0xdb00
|
||||||
|
#define USB_PID_DVICO_BLUEBIRD_TH7579 0xdb10
|
||||||
|
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
|
||||||
|
#define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01
|
||||||
|
#define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
211
drivers/media/dvb/dvb-usb/dvb-usb-init.c
Normal file
211
drivers/media/dvb/dvb-usb/dvb-usb-init.c
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
* DVB USB library - provides a generic interface for a DVB USB device driver.
|
||||||
|
*
|
||||||
|
* dvb-usb-init.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "dvb-usb-common.h"
|
||||||
|
|
||||||
|
/* debug */
|
||||||
|
int dvb_usb_debug;
|
||||||
|
module_param_named(debug,dvb_usb_debug, int, 0644);
|
||||||
|
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." DVB_USB_DEBUG_STATUS);
|
||||||
|
|
||||||
|
/* general initialization functions */
|
||||||
|
int dvb_usb_exit(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
deb_info("state before exiting everything: %x\n",d->state);
|
||||||
|
dvb_usb_remote_exit(d);
|
||||||
|
dvb_usb_fe_exit(d);
|
||||||
|
dvb_usb_i2c_exit(d);
|
||||||
|
dvb_usb_dvb_exit(d);
|
||||||
|
dvb_usb_urb_exit(d);
|
||||||
|
deb_info("state should be zero now: %x\n",d->state);
|
||||||
|
d->state = DVB_USB_STATE_INIT;
|
||||||
|
kfree(d->priv);
|
||||||
|
kfree(d);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dvb_usb_init(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
sema_init(&d->usb_sem, 1);
|
||||||
|
sema_init(&d->i2c_sem, 1);
|
||||||
|
|
||||||
|
d->state = DVB_USB_STATE_INIT;
|
||||||
|
|
||||||
|
/* check the capabilites and set appropriate variables */
|
||||||
|
|
||||||
|
/* speed - when running at FULL speed we need a HW PID filter */
|
||||||
|
if (d->udev->speed == USB_SPEED_FULL && !(d->props.caps & DVB_USB_HAS_PID_FILTER)) {
|
||||||
|
err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a HW PID filter)");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((d->udev->speed == USB_SPEED_FULL && d->props.caps & DVB_USB_HAS_PID_FILTER) ||
|
||||||
|
(d->props.caps & DVB_USB_NEED_PID_FILTERING)) {
|
||||||
|
info("will use the device's hw PID filter.");
|
||||||
|
d->pid_filtering = 1;
|
||||||
|
d->max_feed_count = d->props.pid_filter_count;
|
||||||
|
} else {
|
||||||
|
info("will pass the complete MPEG2 transport stream to the demuxer.");
|
||||||
|
d->pid_filtering = 0;
|
||||||
|
d->max_feed_count = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->props.power_ctrl)
|
||||||
|
d->props.power_ctrl(d,1);
|
||||||
|
|
||||||
|
if ((ret = dvb_usb_urb_init(d)) ||
|
||||||
|
(ret = dvb_usb_dvb_init(d)) ||
|
||||||
|
(ret = dvb_usb_i2c_init(d)) ||
|
||||||
|
(ret = dvb_usb_fe_init(d))) {
|
||||||
|
dvb_usb_exit(d);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = dvb_usb_remote_init(d)))
|
||||||
|
err("could not initialize remote control.");
|
||||||
|
|
||||||
|
if (d->props.power_ctrl)
|
||||||
|
d->props.power_ctrl(d,0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* determine the name and the state of the just found USB device */
|
||||||
|
static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_properties *props, int *cold)
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
struct dvb_usb_device_description *desc = NULL;
|
||||||
|
*cold = -1;
|
||||||
|
|
||||||
|
for (i = 0; i < props->num_device_descs; i++) {
|
||||||
|
|
||||||
|
for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) {
|
||||||
|
deb_info("check for cold %x %x\n",props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
|
||||||
|
if (props->devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
|
||||||
|
props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
|
||||||
|
*cold = 1;
|
||||||
|
desc = &props->devices[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc != NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) {
|
||||||
|
deb_info("check for warm %x %x\n",props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
|
||||||
|
if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
|
||||||
|
props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
|
||||||
|
*cold = 0;
|
||||||
|
desc = &props->devices[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc != NULL && props->identify_state != NULL)
|
||||||
|
props->identify_state(udev,props,&desc,cold);
|
||||||
|
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB
|
||||||
|
*/
|
||||||
|
int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *props, struct module *owner)
|
||||||
|
{
|
||||||
|
struct usb_device *udev = interface_to_usbdev(intf);
|
||||||
|
struct dvb_usb_device *d = NULL;
|
||||||
|
struct dvb_usb_device_description *desc = NULL;
|
||||||
|
|
||||||
|
int ret = -ENOMEM,cold=0;
|
||||||
|
|
||||||
|
if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
|
||||||
|
deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cold) {
|
||||||
|
info("found a '%s' in cold state, will try to load a firmware",desc->name);
|
||||||
|
ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl);
|
||||||
|
} else {
|
||||||
|
info("found a '%s' in warm state.",desc->name);
|
||||||
|
d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
|
||||||
|
if (d == NULL) {
|
||||||
|
err("no memory for 'struct dvb_usb_device'");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
memset(d,0,sizeof(struct dvb_usb_device));
|
||||||
|
|
||||||
|
d->udev = udev;
|
||||||
|
memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
|
||||||
|
d->desc = desc;
|
||||||
|
d->owner = owner;
|
||||||
|
|
||||||
|
if (d->props.size_of_priv > 0) {
|
||||||
|
d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL);
|
||||||
|
if (d->priv == NULL) {
|
||||||
|
err("no memory for priv in 'struct dvb_usb_device'");
|
||||||
|
kfree(d);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
memset(d->priv,0,d->props.size_of_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_set_intfdata(intf, d);
|
||||||
|
|
||||||
|
ret = dvb_usb_init(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
info("%s successfully initialized and connected.",desc->name);
|
||||||
|
else
|
||||||
|
info("%s error while loading driver (%d)",desc->name,ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dvb_usb_device_init);
|
||||||
|
|
||||||
|
void dvb_usb_device_exit(struct usb_interface *intf)
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = usb_get_intfdata(intf);
|
||||||
|
const char *name = "generic DVB-USB module";
|
||||||
|
|
||||||
|
usb_set_intfdata(intf,NULL);
|
||||||
|
if (d != NULL && d->desc != NULL) {
|
||||||
|
name = d->desc->name;
|
||||||
|
dvb_usb_exit(d);
|
||||||
|
}
|
||||||
|
info("%s successfully deinitialized and disconnected.",name);
|
||||||
|
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dvb_usb_device_exit);
|
||||||
|
|
||||||
|
/* module stuff */
|
||||||
|
static int __init dvb_usb_module_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit dvb_usb_module_exit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init (dvb_usb_module_init);
|
||||||
|
module_exit (dvb_usb_module_exit);
|
||||||
|
|
||||||
|
MODULE_VERSION("0.3");
|
||||||
|
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||||
|
MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices");
|
||||||
|
MODULE_LICENSE("GPL");
|
175
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
Normal file
175
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
/* dvb-usb-remote.c is part of the DVB USB library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
* see dvb-usb-init.c for copyright information.
|
||||||
|
*
|
||||||
|
* This file contains functions for initializing the the input-device and for handling remote-control-queries.
|
||||||
|
*/
|
||||||
|
#include "dvb-usb-common.h"
|
||||||
|
|
||||||
|
/* Remote-control poll function - called every dib->rc_query_interval ms to see
|
||||||
|
* whether the remote control has received anything.
|
||||||
|
*
|
||||||
|
* TODO: Fix the repeat rate of the input device.
|
||||||
|
*/
|
||||||
|
static void dvb_usb_read_remote_control(void *data)
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = data;
|
||||||
|
u32 event;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
/* TODO: need a lock here. We can simply skip checking for the remote control
|
||||||
|
if we're busy. */
|
||||||
|
|
||||||
|
if (d->props.rc_query(d,&event,&state)) {
|
||||||
|
err("error while querying for an remote control event.");
|
||||||
|
goto schedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case REMOTE_NO_KEY_PRESSED:
|
||||||
|
break;
|
||||||
|
case REMOTE_KEY_PRESSED:
|
||||||
|
deb_rc("key pressed\n");
|
||||||
|
d->last_event = event;
|
||||||
|
case REMOTE_KEY_REPEAT:
|
||||||
|
deb_rc("key repeated\n");
|
||||||
|
input_event(&d->rc_input_dev, EV_KEY, event, 1);
|
||||||
|
input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
|
||||||
|
input_sync(&d->rc_input_dev);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* improved repeat handling ???
|
||||||
|
switch (state) {
|
||||||
|
case REMOTE_NO_KEY_PRESSED:
|
||||||
|
deb_rc("NO KEY PRESSED\n");
|
||||||
|
if (d->last_state != REMOTE_NO_KEY_PRESSED) {
|
||||||
|
deb_rc("releasing event %d\n",d->last_event);
|
||||||
|
input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
|
||||||
|
input_sync(&d->rc_input_dev);
|
||||||
|
}
|
||||||
|
d->last_state = REMOTE_NO_KEY_PRESSED;
|
||||||
|
d->last_event = 0;
|
||||||
|
break;
|
||||||
|
case REMOTE_KEY_PRESSED:
|
||||||
|
deb_rc("KEY PRESSED\n");
|
||||||
|
deb_rc("pressing event %d\n",event);
|
||||||
|
|
||||||
|
input_event(&d->rc_input_dev, EV_KEY, event, 1);
|
||||||
|
input_sync(&d->rc_input_dev);
|
||||||
|
|
||||||
|
d->last_event = event;
|
||||||
|
d->last_state = REMOTE_KEY_PRESSED;
|
||||||
|
break;
|
||||||
|
case REMOTE_KEY_REPEAT:
|
||||||
|
deb_rc("KEY_REPEAT\n");
|
||||||
|
if (d->last_state != REMOTE_NO_KEY_PRESSED) {
|
||||||
|
deb_rc("repeating event %d\n",d->last_event);
|
||||||
|
input_event(&d->rc_input_dev, EV_KEY, d->last_event, 2);
|
||||||
|
input_sync(&d->rc_input_dev);
|
||||||
|
d->last_state = REMOTE_KEY_REPEAT;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
schedule:
|
||||||
|
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_remote_init(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (d->props.rc_key_map == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Initialise the remote-control structures.*/
|
||||||
|
init_input_dev(&d->rc_input_dev);
|
||||||
|
|
||||||
|
d->rc_input_dev.evbit[0] = BIT(EV_KEY);
|
||||||
|
d->rc_input_dev.keycodesize = sizeof(unsigned char);
|
||||||
|
d->rc_input_dev.keycodemax = KEY_MAX;
|
||||||
|
d->rc_input_dev.name = "IR-receiver inside an USB DVB receiver";
|
||||||
|
|
||||||
|
/* set the bits for the keys */
|
||||||
|
deb_rc("key map size: %d\n",d->props.rc_key_map_size);
|
||||||
|
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||||
|
deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
|
||||||
|
set_bit(d->props.rc_key_map[i].event, d->rc_input_dev.keybit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the remote-control polling. */
|
||||||
|
if (d->props.rc_interval < 40)
|
||||||
|
d->props.rc_interval = 100; /* default */
|
||||||
|
|
||||||
|
/* setting these two values to non-zero, we have to manage key repeats */
|
||||||
|
d->rc_input_dev.rep[REP_PERIOD] = d->props.rc_interval;
|
||||||
|
d->rc_input_dev.rep[REP_DELAY] = d->props.rc_interval + 150;
|
||||||
|
|
||||||
|
input_register_device(&d->rc_input_dev);
|
||||||
|
|
||||||
|
INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d);
|
||||||
|
|
||||||
|
info("schedule remote query interval to %d msecs.",d->props.rc_interval);
|
||||||
|
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
|
||||||
|
|
||||||
|
d->state |= DVB_USB_STATE_REMOTE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_remote_exit(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
if (d->state & DVB_USB_STATE_REMOTE) {
|
||||||
|
cancel_delayed_work(&d->rc_query_work);
|
||||||
|
flush_scheduled_work();
|
||||||
|
input_unregister_device(&d->rc_input_dev);
|
||||||
|
}
|
||||||
|
d->state &= ~DVB_USB_STATE_REMOTE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DVB_USB_RC_NEC_EMPTY 0x00
|
||||||
|
#define DVB_USB_RC_NEC_KEY_PRESSED 0x01
|
||||||
|
#define DVB_USB_RC_NEC_KEY_REPEATED 0x02
|
||||||
|
int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
|
||||||
|
u8 keybuf[5], u32 *event, int *state)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||||
|
*event = 0;
|
||||||
|
*state = REMOTE_NO_KEY_PRESSED;
|
||||||
|
switch (keybuf[0]) {
|
||||||
|
case DVB_USB_RC_NEC_EMPTY:
|
||||||
|
break;
|
||||||
|
case DVB_USB_RC_NEC_KEY_PRESSED:
|
||||||
|
if ((u8) ~keybuf[1] != keybuf[2] ||
|
||||||
|
(u8) ~keybuf[3] != keybuf[4]) {
|
||||||
|
deb_err("remote control checksum failed.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* See if we can match the raw key code. */
|
||||||
|
for (i = 0; i < sizeof(keymap)/sizeof(struct dvb_usb_rc_key); i++)
|
||||||
|
if (keymap[i].custom == keybuf[1] &&
|
||||||
|
keymap[i].data == keybuf[3]) {
|
||||||
|
*event = keymap[i].event;
|
||||||
|
*state = REMOTE_KEY_PRESSED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
deb_err("key mapping failed - no appropriate key found in keymapping\n");
|
||||||
|
break;
|
||||||
|
case DVB_USB_RC_NEC_KEY_REPEATED:
|
||||||
|
*state = REMOTE_KEY_REPEAT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
deb_err("unkown type of remote status: %d\n",keybuf[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event);
|
211
drivers/media/dvb/dvb-usb/dvb-usb-urb.c
Normal file
211
drivers/media/dvb/dvb-usb/dvb-usb-urb.c
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
/* dvb-usb-urb.c is part of the DVB USB library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
* see dvb-usb-init.c for copyright information.
|
||||||
|
*
|
||||||
|
* This file contains functions for initializing and handling the
|
||||||
|
* USB and URB stuff.
|
||||||
|
*/
|
||||||
|
#include "dvb-usb-common.h"
|
||||||
|
|
||||||
|
int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
|
||||||
|
u16 rlen, int delay_ms)
|
||||||
|
{
|
||||||
|
int actlen,ret = -ENOMEM;
|
||||||
|
|
||||||
|
if (d->props.generic_bulk_ctrl_endpoint == 0) {
|
||||||
|
err("endpoint for generic control not specified.");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wbuf == NULL || wlen == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ((ret = down_interruptible(&d->usb_sem)))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
debug_dump(wbuf,wlen,deb_xfer);
|
||||||
|
|
||||||
|
ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev,
|
||||||
|
d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen,
|
||||||
|
2*HZ);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
|
||||||
|
else
|
||||||
|
ret = actlen != wlen ? -1 : 0;
|
||||||
|
|
||||||
|
/* an answer is expected, and no error before */
|
||||||
|
if (!ret && rbuf && rlen) {
|
||||||
|
if (delay_ms)
|
||||||
|
msleep(delay_ms);
|
||||||
|
|
||||||
|
ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev,
|
||||||
|
d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen,
|
||||||
|
2*HZ);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
err("recv bulk message failed: %d",ret);
|
||||||
|
else
|
||||||
|
debug_dump(rbuf,actlen,deb_xfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
up(&d->usb_sem);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dvb_usb_generic_rw);
|
||||||
|
|
||||||
|
int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
|
||||||
|
{
|
||||||
|
return dvb_usb_generic_rw(d,buf,len,NULL,0,0);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(dvb_usb_generic_write);
|
||||||
|
|
||||||
|
static void dvb_usb_bulk_urb_complete(struct urb *urb, struct pt_regs *ptregs)
|
||||||
|
{
|
||||||
|
struct dvb_usb_device *d = urb->context;
|
||||||
|
|
||||||
|
deb_ts("bulk urb completed. feedcount: %d, status: %d, length: %d\n",d->feedcount,urb->status,
|
||||||
|
urb->actual_length);
|
||||||
|
|
||||||
|
switch (urb->status) {
|
||||||
|
case 0: /* success */
|
||||||
|
case -ETIMEDOUT: /* NAK */
|
||||||
|
break;
|
||||||
|
case -ECONNRESET: /* kill */
|
||||||
|
case -ENOENT:
|
||||||
|
case -ESHUTDOWN:
|
||||||
|
return;
|
||||||
|
default: /* error */
|
||||||
|
deb_ts("urb completition error %d.", urb->status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->feedcount > 0 && urb->actual_length > 0) {
|
||||||
|
if (d->state & DVB_USB_STATE_DVB)
|
||||||
|
dvb_dmx_swfilter(&d->demux, (u8*) urb->transfer_buffer,urb->actual_length);
|
||||||
|
} else
|
||||||
|
deb_ts("URB dropped because of feedcount.\n");
|
||||||
|
|
||||||
|
usb_submit_urb(urb,GFP_ATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_urb_kill(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < d->urbs_submitted; i++) {
|
||||||
|
deb_info("killing URB no. %d.\n",i);
|
||||||
|
|
||||||
|
/* stop the URB */
|
||||||
|
usb_kill_urb(d->urb_list[i]);
|
||||||
|
}
|
||||||
|
d->urbs_submitted = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_urb_submit(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
int i,ret;
|
||||||
|
for (i = 0; i < d->urbs_initialized; i++) {
|
||||||
|
deb_info("submitting URB no. %d\n",i);
|
||||||
|
if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) {
|
||||||
|
err("could not submit URB no. %d - get them all back\n",i);
|
||||||
|
dvb_usb_urb_kill(d);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
d->urbs_submitted++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
int i,bufsize = d->props.urb.count * d->props.urb.u.bulk.buffersize;
|
||||||
|
|
||||||
|
deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
|
||||||
|
/* allocate the actual buffer for the URBs */
|
||||||
|
if ((d->buffer = usb_buffer_alloc(d->udev, bufsize, SLAB_ATOMIC, &d->dma_handle)) == NULL) {
|
||||||
|
deb_info("not enough memory for urb-buffer allocation.\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
deb_info("allocation successful\n");
|
||||||
|
memset(d->buffer,0,bufsize);
|
||||||
|
|
||||||
|
d->state |= DVB_USB_STATE_URB_BUF;
|
||||||
|
|
||||||
|
/* allocate the URBs */
|
||||||
|
for (i = 0; i < d->props.urb.count; i++) {
|
||||||
|
if (!(d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_fill_bulk_urb( d->urb_list[i], d->udev,
|
||||||
|
usb_rcvbulkpipe(d->udev,d->props.urb.endpoint),
|
||||||
|
&d->buffer[i*d->props.urb.u.bulk.buffersize],
|
||||||
|
d->props.urb.u.bulk.buffersize,
|
||||||
|
dvb_usb_bulk_urb_complete, d);
|
||||||
|
|
||||||
|
d->urb_list[i]->transfer_flags = 0;
|
||||||
|
d->urbs_initialized++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_urb_init(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* when reloading the driver w/o replugging the device
|
||||||
|
* sometimes a timeout occures, this helps
|
||||||
|
*/
|
||||||
|
if (d->props.generic_bulk_ctrl_endpoint != 0) {
|
||||||
|
usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
|
||||||
|
usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
|
||||||
|
}
|
||||||
|
usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint));
|
||||||
|
|
||||||
|
/* allocate the array for the data transfer URBs */
|
||||||
|
d->urb_list = kmalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
|
||||||
|
if (d->urb_list == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
memset(d->urb_list,0,d->props.urb.count * sizeof(struct urb *));
|
||||||
|
d->state |= DVB_USB_STATE_URB_LIST;
|
||||||
|
|
||||||
|
switch (d->props.urb.type) {
|
||||||
|
case DVB_USB_BULK:
|
||||||
|
return dvb_usb_bulk_urb_init(d);
|
||||||
|
case DVB_USB_ISOC:
|
||||||
|
err("isochronous transfer not yet implemented in dvb-usb.");
|
||||||
|
return -EINVAL;
|
||||||
|
default:
|
||||||
|
err("unkown URB-type for data transfer.");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dvb_usb_urb_exit(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dvb_usb_urb_kill(d);
|
||||||
|
|
||||||
|
if (d->state & DVB_USB_STATE_URB_LIST) {
|
||||||
|
for (i = 0; i < d->urbs_initialized; i++) {
|
||||||
|
if (d->urb_list[i] != NULL) {
|
||||||
|
deb_info("freeing URB no. %d.\n",i);
|
||||||
|
/* free the URBs */
|
||||||
|
usb_free_urb(d->urb_list[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d->urbs_initialized = 0;
|
||||||
|
/* free the urb array */
|
||||||
|
kfree(d->urb_list);
|
||||||
|
d->state &= ~DVB_USB_STATE_URB_LIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->state & DVB_USB_STATE_URB_BUF)
|
||||||
|
usb_buffer_free(d->udev, d->props.urb.u.bulk.buffersize * d->props.urb.count,
|
||||||
|
d->buffer, d->dma_handle);
|
||||||
|
|
||||||
|
d->state &= ~DVB_USB_STATE_URB_BUF;
|
||||||
|
return 0;
|
||||||
|
}
|
315
drivers/media/dvb/dvb-usb/dvb-usb.h
Normal file
315
drivers/media/dvb/dvb-usb/dvb-usb.h
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
/* dvb-usb.h is part of the DVB USB library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
* see dvb-usb-init.c for copyright information.
|
||||||
|
*
|
||||||
|
* the headerfile, all dvb-usb-drivers have to include.
|
||||||
|
*/
|
||||||
|
#ifndef __DVB_USB_H__
|
||||||
|
#define __DVB_USB_H__
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/usb.h>
|
||||||
|
|
||||||
|
#include "dvb_frontend.h"
|
||||||
|
#include "dvb_demux.h"
|
||||||
|
#include "dvb_net.h"
|
||||||
|
#include "dmxdev.h"
|
||||||
|
|
||||||
|
#include "dvb-pll.h"
|
||||||
|
|
||||||
|
#include "dvb-usb-ids.h"
|
||||||
|
|
||||||
|
/* debug */
|
||||||
|
#ifdef CONFIG_DVB_USB_DEBUG
|
||||||
|
#define dprintk(var,level,args...) \
|
||||||
|
do { if ((var & level)) { printk(args); } } while (0)
|
||||||
|
|
||||||
|
#define debug_dump(b,l,func) {\
|
||||||
|
int loop_; \
|
||||||
|
for (loop_ = 0; loop_ < l; loop_++) func("%02x ", b[loop_]); \
|
||||||
|
func("\n");\
|
||||||
|
}
|
||||||
|
#define DVB_USB_DEBUG_STATUS
|
||||||
|
#else
|
||||||
|
#define dprintk(args...)
|
||||||
|
#define debug_dump(b,l,func)
|
||||||
|
|
||||||
|
#define DVB_USB_DEBUG_STATUS " (debugging is not enabled)"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* generic log methods - taken from usb.h */
|
||||||
|
#ifndef DVB_USB_LOG_PREFIX
|
||||||
|
#define DVB_USB_LOG_PREFIX "dvb-usb (please define a log prefix)"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef err
|
||||||
|
#define err(format, arg...) printk(KERN_ERR DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
|
||||||
|
#undef info
|
||||||
|
#define info(format, arg...) printk(KERN_INFO DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
|
||||||
|
#undef warn
|
||||||
|
#define warn(format, arg...) printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct dvb_usb_device_description - name and its according USB IDs
|
||||||
|
* @name: real name of the box, regardless which DVB USB device class is in use
|
||||||
|
* @cold_ids: array of struct usb_device_id which describe the device in
|
||||||
|
* pre-firmware state
|
||||||
|
* @warm_ids: array of struct usb_device_id which describe the device in
|
||||||
|
* post-firmware state
|
||||||
|
*
|
||||||
|
* Each DVB USB device class can have one or more actual devices, this struct
|
||||||
|
* assigns a name to it.
|
||||||
|
*/
|
||||||
|
struct dvb_usb_device_description {
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
#define DVB_USB_ID_MAX_NUM 15
|
||||||
|
struct usb_device_id *cold_ids[DVB_USB_ID_MAX_NUM];
|
||||||
|
struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct dvb_usb_rc_key - a remote control key and its input-event
|
||||||
|
* @custom: the vendor/custom part of the key
|
||||||
|
* @data: the actual key part
|
||||||
|
* @event: the input event assigned to key identified by custom and data
|
||||||
|
*/
|
||||||
|
struct dvb_usb_rc_key {
|
||||||
|
u8 custom,data;
|
||||||
|
u32 event;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dvb_usb_device;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct dvb_usb_properties - properties of a dvb-usb-device
|
||||||
|
* @caps: capabilites of the DVB USB device.
|
||||||
|
* @pid_filter_count: number of PID filter position in the optional hardware
|
||||||
|
* PID-filter.
|
||||||
|
*
|
||||||
|
* @usb_ctrl: which USB device-side controller is in use. Needed for firmware
|
||||||
|
* download.
|
||||||
|
* @firmware: name of the firmware file.
|
||||||
|
*
|
||||||
|
* @size_of_priv: how many bytes shall be allocated for the private field
|
||||||
|
* of struct dvb_usb_device.
|
||||||
|
*
|
||||||
|
* @power_ctrl: called to enable/disable power of the device.
|
||||||
|
* @streaming_crtl: called to start and stop the MPEG2-TS streaming of the
|
||||||
|
* device (not URB submitting/killing).
|
||||||
|
* @pid_filter_ctrl: called to en/disable the PID filter, if any.
|
||||||
|
* @pid_filter: called to set/unset a PID for filtering.
|
||||||
|
*
|
||||||
|
* @read_mac_address: called to read the MAC address of the device.
|
||||||
|
*
|
||||||
|
* @frontend_attach: called to attach the possible frontends (fill fe-field
|
||||||
|
* of struct dvb_usb_device).
|
||||||
|
* @tuner_attach: called to attach the correct tuner and to fill pll_addr,
|
||||||
|
* pll_desc and pll_init_buf of struct dvb_usb_device).
|
||||||
|
* @identify_state: called to determine the state (cold or warm), when it
|
||||||
|
* is not distinguishable by the USB IDs.
|
||||||
|
*
|
||||||
|
* @rc_key_map: a hard-wired array of struct dvb_usb_rc_key (NULL to disable
|
||||||
|
* remote control handling).
|
||||||
|
* @rc_key_map_size: number of items in @rc_key_map.
|
||||||
|
* @rc_query: called to query an event event.
|
||||||
|
* @rc_interval: time in ms between two queries.
|
||||||
|
*
|
||||||
|
* @i2c_algo: i2c_algorithm if the device has I2CoverUSB.
|
||||||
|
*
|
||||||
|
* @generic_bulk_ctrl_endpoint: most of the DVB USB devices have a generic
|
||||||
|
* endpoint which received control messages with bulk transfers. When this
|
||||||
|
* is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write-
|
||||||
|
* helper functions.
|
||||||
|
*
|
||||||
|
* @urb: describes the kind of USB transfer used for MPEG2-TS-streaming.
|
||||||
|
* Currently only BULK is implemented
|
||||||
|
*
|
||||||
|
* @num_device_descs: number of struct dvb_usb_device_description in @devices
|
||||||
|
* @devices: array of struct dvb_usb_device_description compatibles with these
|
||||||
|
* properties.
|
||||||
|
*/
|
||||||
|
struct dvb_usb_properties {
|
||||||
|
|
||||||
|
#define DVB_USB_HAS_PID_FILTER 0x01
|
||||||
|
#define DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF 0x02
|
||||||
|
#define DVB_USB_NEED_PID_FILTERING 0x04
|
||||||
|
#define DVB_USB_IS_AN_I2C_ADAPTER 0x08
|
||||||
|
int caps;
|
||||||
|
int pid_filter_count;
|
||||||
|
|
||||||
|
#define CYPRESS_AN2135 0
|
||||||
|
#define CYPRESS_AN2235 1
|
||||||
|
#define CYPRESS_FX2 2
|
||||||
|
int usb_ctrl;
|
||||||
|
const char *firmware;
|
||||||
|
|
||||||
|
int size_of_priv;
|
||||||
|
|
||||||
|
int (*power_ctrl) (struct dvb_usb_device *, int);
|
||||||
|
int (*streaming_ctrl) (struct dvb_usb_device *, int);
|
||||||
|
int (*pid_filter_ctrl) (struct dvb_usb_device *, int);
|
||||||
|
int (*pid_filter) (struct dvb_usb_device *, int, u16, int);
|
||||||
|
|
||||||
|
int (*read_mac_address) (struct dvb_usb_device *, u8 []);
|
||||||
|
int (*frontend_attach) (struct dvb_usb_device *);
|
||||||
|
int (*tuner_attach) (struct dvb_usb_device *);
|
||||||
|
|
||||||
|
int (*identify_state) (struct usb_device *, struct dvb_usb_properties *,
|
||||||
|
struct dvb_usb_device_description **, int *);
|
||||||
|
|
||||||
|
/* remote control properties */
|
||||||
|
#define REMOTE_NO_KEY_PRESSED 0x00
|
||||||
|
#define REMOTE_KEY_PRESSED 0x01
|
||||||
|
#define REMOTE_KEY_REPEAT 0x02
|
||||||
|
struct dvb_usb_rc_key *rc_key_map;
|
||||||
|
int rc_key_map_size;
|
||||||
|
int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
|
||||||
|
int rc_interval;
|
||||||
|
|
||||||
|
struct i2c_algorithm *i2c_algo;
|
||||||
|
|
||||||
|
int generic_bulk_ctrl_endpoint;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
#define DVB_USB_BULK 1
|
||||||
|
#define DVB_USB_ISOC 2
|
||||||
|
int type;
|
||||||
|
int count;
|
||||||
|
int endpoint;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
int buffersize; /* per URB */
|
||||||
|
} bulk;
|
||||||
|
struct {
|
||||||
|
int framesperurb;
|
||||||
|
int framesize;
|
||||||
|
} isoc;
|
||||||
|
} u;
|
||||||
|
} urb;
|
||||||
|
|
||||||
|
int num_device_descs;
|
||||||
|
struct dvb_usb_device_description devices[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct dvb_usb_device - object of a DVB USB device
|
||||||
|
* @props: copy of the struct dvb_usb_properties this device belongs to.
|
||||||
|
* @desc: pointer to the device's struct dvb_usb_device_description.
|
||||||
|
* @state: initialization and runtime state of the device.
|
||||||
|
*
|
||||||
|
* @udev: pointer to the device's struct usb_device.
|
||||||
|
* @urb_list: array of dynamically allocated struct urb for the MPEG2-TS-
|
||||||
|
* streaming.
|
||||||
|
* @buffer: buffer used to streaming.
|
||||||
|
* @dma_handle: dma_addr_t for buffer.
|
||||||
|
* @urbs_initialized: number of URBs initialized.
|
||||||
|
* @urbs_submitted: number of URBs submitted.
|
||||||
|
* @feedcount: number of reqested feeds (used for streaming-activation)
|
||||||
|
* @pid_filtering: is hardware pid_filtering used or not.
|
||||||
|
* @usb_sem: semaphore of USB control messages (reading needs two messages)
|
||||||
|
* @i2c_sem: semaphore for i2c-transfers
|
||||||
|
* @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
|
||||||
|
* @pll_addr: I2C address of the tuner for programming
|
||||||
|
* @pll_init: array containing the initialization buffer
|
||||||
|
* @pll_desc: pointer to the appropriate struct dvb_pll_desc
|
||||||
|
* @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod
|
||||||
|
* @dvb_adap: device's dvb_adapter.
|
||||||
|
* @dmxdev: device's dmxdev.
|
||||||
|
* @demux: device's software demuxer.
|
||||||
|
* @dvb_net: device's dvb_net interfaces.
|
||||||
|
* @dvb_frontend: device's frontend.
|
||||||
|
* @max_feed_count: how many feeds can be handled simultaneously by this
|
||||||
|
* device
|
||||||
|
* @fe_sleep: rerouted frontend-sleep function.
|
||||||
|
* @fe_init: rerouted frontend-init (wakeup) function.
|
||||||
|
* @rc_input_dev: input device for the remote control.
|
||||||
|
* @rc_query_work: struct work_struct frequent rc queries
|
||||||
|
* @last_event: last triggered event
|
||||||
|
* @last_state: last state (no, pressed, repeat)
|
||||||
|
* @owner: owner of the dvb_adapter
|
||||||
|
* @priv: private data of the actual driver (allocate by dvb-usb, size defined
|
||||||
|
* in size_of_priv of dvb_usb_properties).
|
||||||
|
*/
|
||||||
|
struct dvb_usb_device {
|
||||||
|
struct dvb_usb_properties props;
|
||||||
|
struct dvb_usb_device_description *desc;
|
||||||
|
|
||||||
|
#define DVB_USB_STATE_INIT 0x000
|
||||||
|
#define DVB_USB_STATE_URB_LIST 0x001
|
||||||
|
#define DVB_USB_STATE_URB_BUF 0x002
|
||||||
|
#define DVB_USB_STATE_DVB 0x004
|
||||||
|
#define DVB_USB_STATE_I2C 0x008
|
||||||
|
#define DVB_USB_STATE_REMOTE 0x010
|
||||||
|
#define DVB_USB_STATE_URB_SUBMIT 0x020
|
||||||
|
int state;
|
||||||
|
|
||||||
|
/* usb */
|
||||||
|
struct usb_device *udev;
|
||||||
|
struct urb **urb_list;
|
||||||
|
u8 *buffer;
|
||||||
|
dma_addr_t dma_handle;
|
||||||
|
int urbs_initialized;
|
||||||
|
int urbs_submitted;
|
||||||
|
|
||||||
|
int feedcount;
|
||||||
|
int pid_filtering;
|
||||||
|
|
||||||
|
/* locking */
|
||||||
|
struct semaphore usb_sem;
|
||||||
|
|
||||||
|
/* i2c */
|
||||||
|
struct semaphore i2c_sem;
|
||||||
|
struct i2c_adapter i2c_adap;
|
||||||
|
|
||||||
|
/* tuner programming information */
|
||||||
|
u8 pll_addr;
|
||||||
|
u8 pll_init[4];
|
||||||
|
struct dvb_pll_desc *pll_desc;
|
||||||
|
int (*tuner_pass_ctrl)(struct dvb_frontend *, int, u8);
|
||||||
|
|
||||||
|
/* dvb */
|
||||||
|
struct dvb_adapter dvb_adap;
|
||||||
|
struct dmxdev dmxdev;
|
||||||
|
struct dvb_demux demux;
|
||||||
|
struct dvb_net dvb_net;
|
||||||
|
struct dvb_frontend* fe;
|
||||||
|
int max_feed_count;
|
||||||
|
|
||||||
|
int (*fe_sleep) (struct dvb_frontend *);
|
||||||
|
int (*fe_init) (struct dvb_frontend *);
|
||||||
|
|
||||||
|
/* remote control */
|
||||||
|
struct input_dev rc_input_dev;
|
||||||
|
struct work_struct rc_query_work;
|
||||||
|
u32 last_event;
|
||||||
|
int last_state;
|
||||||
|
|
||||||
|
struct module *owner;
|
||||||
|
|
||||||
|
void *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *);
|
||||||
|
extern void dvb_usb_device_exit(struct usb_interface *);
|
||||||
|
|
||||||
|
/* the generic read/write method for device control */
|
||||||
|
extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16,int);
|
||||||
|
extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
|
||||||
|
|
||||||
|
/* commonly used remote control parsing */
|
||||||
|
extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
|
||||||
|
|
||||||
|
/* commonly used pll init and set functions */
|
||||||
|
extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
|
||||||
|
extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
|
||||||
|
extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
236
drivers/media/dvb/dvb-usb/nova-t-usb2.c
Normal file
236
drivers/media/dvb/dvb-usb/nova-t-usb2.c
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
/* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2
|
||||||
|
* DVB-T receiver.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "dibusb.h"
|
||||||
|
|
||||||
|
static int debug;
|
||||||
|
module_param(debug, int, 0644);
|
||||||
|
MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS);
|
||||||
|
|
||||||
|
#define deb_rc(args...) dprintk(debug,0x01,args)
|
||||||
|
#define deb_ee(args...) dprintk(debug,0x02,args)
|
||||||
|
|
||||||
|
/* Hauppauge NOVA-T USB2 keys */
|
||||||
|
static struct dvb_usb_rc_key haupp_rc_keys [] = {
|
||||||
|
{ 0x1e, 0x00, KEY_0 },
|
||||||
|
{ 0x1e, 0x01, KEY_1 },
|
||||||
|
{ 0x1e, 0x02, KEY_2 },
|
||||||
|
{ 0x1e, 0x03, KEY_3 },
|
||||||
|
{ 0x1e, 0x04, KEY_4 },
|
||||||
|
{ 0x1e, 0x05, KEY_5 },
|
||||||
|
{ 0x1e, 0x06, KEY_6 },
|
||||||
|
{ 0x1e, 0x07, KEY_7 },
|
||||||
|
{ 0x1e, 0x08, KEY_8 },
|
||||||
|
{ 0x1e, 0x09, KEY_9 },
|
||||||
|
{ 0x1e, 0x0a, KEY_KPASTERISK },
|
||||||
|
{ 0x1e, 0x0b, KEY_RED },
|
||||||
|
{ 0x1e, 0x0c, KEY_RADIO },
|
||||||
|
{ 0x1e, 0x0d, KEY_MENU },
|
||||||
|
{ 0x1e, 0x0e, KEY_GRAVE }, /* # */
|
||||||
|
{ 0x1e, 0x0f, KEY_MUTE },
|
||||||
|
{ 0x1e, 0x10, KEY_VOLUMEUP },
|
||||||
|
{ 0x1e, 0x11, KEY_VOLUMEDOWN },
|
||||||
|
{ 0x1e, 0x12, KEY_CHANNEL },
|
||||||
|
{ 0x1e, 0x14, KEY_UP },
|
||||||
|
{ 0x1e, 0x15, KEY_DOWN },
|
||||||
|
{ 0x1e, 0x16, KEY_LEFT },
|
||||||
|
{ 0x1e, 0x17, KEY_RIGHT },
|
||||||
|
{ 0x1e, 0x18, KEY_VIDEO },
|
||||||
|
{ 0x1e, 0x19, KEY_AUDIO },
|
||||||
|
{ 0x1e, 0x1a, KEY_MEDIA },
|
||||||
|
{ 0x1e, 0x1b, KEY_EPG },
|
||||||
|
{ 0x1e, 0x1c, KEY_TV },
|
||||||
|
{ 0x1e, 0x1e, KEY_NEXT },
|
||||||
|
{ 0x1e, 0x1f, KEY_BACK },
|
||||||
|
{ 0x1e, 0x20, KEY_CHANNELUP },
|
||||||
|
{ 0x1e, 0x21, KEY_CHANNELDOWN },
|
||||||
|
{ 0x1e, 0x24, KEY_LAST }, /* Skip backwards */
|
||||||
|
{ 0x1e, 0x25, KEY_OK },
|
||||||
|
{ 0x1e, 0x29, KEY_BLUE},
|
||||||
|
{ 0x1e, 0x2e, KEY_GREEN },
|
||||||
|
{ 0x1e, 0x30, KEY_PAUSE },
|
||||||
|
{ 0x1e, 0x32, KEY_REWIND },
|
||||||
|
{ 0x1e, 0x34, KEY_FASTFORWARD },
|
||||||
|
{ 0x1e, 0x35, KEY_PLAY },
|
||||||
|
{ 0x1e, 0x36, KEY_STOP },
|
||||||
|
{ 0x1e, 0x37, KEY_RECORD },
|
||||||
|
{ 0x1e, 0x38, KEY_YELLOW },
|
||||||
|
{ 0x1e, 0x3b, KEY_GOTO },
|
||||||
|
{ 0x1e, 0x3d, KEY_POWER },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Firmware bug? sometimes, when a new key is pressed, the previous pressed key
|
||||||
|
* is delivered. No workaround yet, maybe a new firmware.
|
||||||
|
*/
|
||||||
|
static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||||
|
{
|
||||||
|
u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom;
|
||||||
|
u16 raw;
|
||||||
|
int i;
|
||||||
|
struct dibusb_state *st = d->priv;
|
||||||
|
|
||||||
|
dvb_usb_generic_rw(d,cmd,2,key,5,0);
|
||||||
|
|
||||||
|
*state = REMOTE_NO_KEY_PRESSED;
|
||||||
|
switch (key[0]) {
|
||||||
|
case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
|
||||||
|
raw = ((key[1] << 8) | key[2]) >> 3;
|
||||||
|
toggle = !!(raw & 0x800);
|
||||||
|
data = raw & 0x3f;
|
||||||
|
custom = (raw >> 6) & 0x1f;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(haupp_rc_keys); i++) {
|
||||||
|
deb_rc("c: %x, d: %x\n",haupp_rc_keys[i].data,haupp_rc_keys[i].custom);
|
||||||
|
if (haupp_rc_keys[i].data == data &&
|
||||||
|
haupp_rc_keys[i].custom == custom) {
|
||||||
|
*event = haupp_rc_keys[i].event;
|
||||||
|
*state = REMOTE_KEY_PRESSED;
|
||||||
|
if (st->old_toggle == toggle) {
|
||||||
|
if (st->last_repeat_count++ < 2)
|
||||||
|
*state = REMOTE_NO_KEY_PRESSED;
|
||||||
|
} else {
|
||||||
|
st->last_repeat_count = 0;
|
||||||
|
st->old_toggle = toggle;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u8 b;
|
||||||
|
|
||||||
|
mac[0] = 0x00;
|
||||||
|
mac[1] = 0x0d;
|
||||||
|
mac[2] = 0xfe;
|
||||||
|
|
||||||
|
/* this is a complete guess, but works for my box */
|
||||||
|
for (i = 136; i < 139; i++) {
|
||||||
|
dibusb_read_eeprom_byte(d,i, &b);
|
||||||
|
|
||||||
|
mac[5 - (i - 136)] = b;
|
||||||
|
|
||||||
|
/* deb_ee("%02x ",b);
|
||||||
|
if ((i+1) % 16 == 0)
|
||||||
|
deb_ee("\n");*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* USB Driver stuff */
|
||||||
|
static struct dvb_usb_properties nova_t_properties;
|
||||||
|
|
||||||
|
static int nova_t_probe(struct usb_interface *intf,
|
||||||
|
const struct usb_device_id *id)
|
||||||
|
{
|
||||||
|
return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do not change the order of the ID table */
|
||||||
|
static struct usb_device_id nova_t_table [] = {
|
||||||
|
/* 00 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) },
|
||||||
|
/* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) },
|
||||||
|
{ } /* Terminating entry */
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE (usb, nova_t_table);
|
||||||
|
|
||||||
|
static struct dvb_usb_properties nova_t_properties = {
|
||||||
|
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
|
.pid_filter_count = 32,
|
||||||
|
|
||||||
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
|
.firmware = "dvb-usb-nova-t-usb2-01.fw",
|
||||||
|
|
||||||
|
.size_of_priv = sizeof(struct dibusb_state),
|
||||||
|
|
||||||
|
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||||
|
.pid_filter = dibusb_pid_filter,
|
||||||
|
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||||
|
.power_ctrl = dibusb2_0_power_ctrl,
|
||||||
|
.frontend_attach = dibusb_dib3000mc_frontend_attach,
|
||||||
|
.tuner_attach = dibusb_dib3000mc_tuner_attach,
|
||||||
|
.read_mac_address = nova_t_read_mac_address,
|
||||||
|
|
||||||
|
.rc_interval = 100,
|
||||||
|
.rc_key_map = haupp_rc_keys,
|
||||||
|
.rc_key_map_size = ARRAY_SIZE(haupp_rc_keys),
|
||||||
|
.rc_query = nova_t_rc_query,
|
||||||
|
|
||||||
|
.i2c_algo = &dibusb_i2c_algo,
|
||||||
|
|
||||||
|
.generic_bulk_ctrl_endpoint = 0x01,
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 7,
|
||||||
|
.endpoint = 0x06,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 4096,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 1,
|
||||||
|
.devices = {
|
||||||
|
{ "Hauppauge WinTV-NOVA-T usb2",
|
||||||
|
{ &nova_t_table[0], NULL },
|
||||||
|
{ &nova_t_table[1], NULL },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usb_driver nova_t_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "Hauppauge WinTV-NOVA-T usb2",
|
||||||
|
.probe = nova_t_probe,
|
||||||
|
.disconnect = dvb_usb_device_exit,
|
||||||
|
.id_table = nova_t_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* module stuff */
|
||||||
|
static int __init nova_t_module_init(void)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if ((result = usb_register(&nova_t_driver))) {
|
||||||
|
err("usb_register failed. Error number %d",result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit nova_t_module_exit(void)
|
||||||
|
{
|
||||||
|
/* deregister this driver from the USB subsystem */
|
||||||
|
usb_deregister(&nova_t_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init (nova_t_module_init);
|
||||||
|
module_exit (nova_t_module_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||||
|
MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2");
|
||||||
|
MODULE_VERSION("1.0");
|
||||||
|
MODULE_LICENSE("GPL");
|
162
drivers/media/dvb/dvb-usb/umt-010.c
Normal file
162
drivers/media/dvb/dvb-usb/umt-010.c
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
/* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0
|
||||||
|
* DVB-T receiver.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "dibusb.h"
|
||||||
|
|
||||||
|
#include "mt352.h"
|
||||||
|
|
||||||
|
static int umt_mt352_demod_init(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
|
||||||
|
static u8 mt352_reset[] = { 0x50, 0x80 };
|
||||||
|
static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
|
||||||
|
static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
|
||||||
|
static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 };
|
||||||
|
|
||||||
|
static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff };
|
||||||
|
static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff };
|
||||||
|
static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 };
|
||||||
|
static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 };
|
||||||
|
static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f };
|
||||||
|
|
||||||
|
static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
|
||||||
|
static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 };
|
||||||
|
|
||||||
|
mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
|
||||||
|
udelay(2000);
|
||||||
|
mt352_write(fe, mt352_reset, sizeof(mt352_reset));
|
||||||
|
mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
|
||||||
|
|
||||||
|
mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
|
||||||
|
mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
|
||||||
|
|
||||||
|
mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1));
|
||||||
|
mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2));
|
||||||
|
mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3));
|
||||||
|
mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4));
|
||||||
|
mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5));
|
||||||
|
|
||||||
|
mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
|
||||||
|
mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
struct mt352_config umt_config;
|
||||||
|
|
||||||
|
memset(&umt_config,0,sizeof(struct mt352_config));
|
||||||
|
umt_config.demod_init = umt_mt352_demod_init;
|
||||||
|
umt_config.demod_address = 0xf;
|
||||||
|
umt_config.pll_set = dvb_usb_pll_set;
|
||||||
|
|
||||||
|
d->fe = mt352_attach(&umt_config, &d->i2c_adap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int umt_tuner_attach (struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
d->pll_addr = 0x61;
|
||||||
|
d->pll_desc = &dvb_pll_tua6034;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* USB Driver stuff */
|
||||||
|
static struct dvb_usb_properties umt_properties;
|
||||||
|
|
||||||
|
static int umt_probe(struct usb_interface *intf,
|
||||||
|
const struct usb_device_id *id)
|
||||||
|
{
|
||||||
|
if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE) == 0)
|
||||||
|
return 0;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do not change the order of the ID table */
|
||||||
|
static struct usb_device_id umt_table [] = {
|
||||||
|
/* 00 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) },
|
||||||
|
/* 01 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) },
|
||||||
|
{ } /* Terminating entry */
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE (usb, umt_table);
|
||||||
|
|
||||||
|
static struct dvb_usb_properties umt_properties = {
|
||||||
|
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
|
|
||||||
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
|
.firmware = "dvb-usb-umt-010-02.fw",
|
||||||
|
|
||||||
|
.size_of_priv = sizeof(struct dibusb_state),
|
||||||
|
|
||||||
|
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||||
|
.power_ctrl = dibusb_power_ctrl,
|
||||||
|
.frontend_attach = umt_mt352_frontend_attach,
|
||||||
|
.tuner_attach = umt_tuner_attach,
|
||||||
|
|
||||||
|
.i2c_algo = &dibusb_i2c_algo,
|
||||||
|
|
||||||
|
.generic_bulk_ctrl_endpoint = 0x01,
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 20,
|
||||||
|
.endpoint = 0x06,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 512,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 1,
|
||||||
|
.devices = {
|
||||||
|
{ "Hanftek UMT-010 DVB-T USB2.0",
|
||||||
|
{ &umt_table[0], NULL },
|
||||||
|
{ &umt_table[1], NULL },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct usb_driver umt_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "HanfTek UMT-010 USB2.0 DVB-T devices",
|
||||||
|
.probe = umt_probe,
|
||||||
|
.disconnect = dvb_usb_device_exit,
|
||||||
|
.id_table = umt_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* module stuff */
|
||||||
|
static int __init umt_module_init(void)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if ((result = usb_register(&umt_driver))) {
|
||||||
|
err("usb_register failed. Error number %d",result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit umt_module_exit(void)
|
||||||
|
{
|
||||||
|
/* deregister this driver from the USB subsystem */
|
||||||
|
usb_deregister(&umt_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init (umt_module_init);
|
||||||
|
module_exit (umt_module_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||||
|
MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device");
|
||||||
|
MODULE_VERSION("1.0");
|
||||||
|
MODULE_LICENSE("GPL");
|
196
drivers/media/dvb/dvb-usb/vp7045-fe.c
Normal file
196
drivers/media/dvb/dvb-usb/vp7045-fe.c
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
/* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0
|
||||||
|
* DVB-T receiver.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* Thanks to Twinhan who kindly provided hardware and information.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "vp7045.h"
|
||||||
|
|
||||||
|
/* It is a Zarlink MT352 within a Samsung Tuner (DNOS404ZH102A) - 040929 - AAT
|
||||||
|
*
|
||||||
|
* Programming is hidden inside the firmware, so set_frontend is very easy.
|
||||||
|
* Even though there is a Firmware command that one can use to access the demod
|
||||||
|
* via its registers. This is used for status information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct vp7045_fe_state {
|
||||||
|
struct dvb_frontend fe;
|
||||||
|
struct dvb_usb_device *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
|
||||||
|
{
|
||||||
|
struct vp7045_fe_state *state = fe->demodulator_priv;
|
||||||
|
u8 s0 = vp7045_read_reg(state->d,0x00),
|
||||||
|
s1 = vp7045_read_reg(state->d,0x01),
|
||||||
|
s3 = vp7045_read_reg(state->d,0x03);
|
||||||
|
|
||||||
|
*status = 0;
|
||||||
|
if (s0 & (1 << 4))
|
||||||
|
*status |= FE_HAS_CARRIER;
|
||||||
|
if (s0 & (1 << 1))
|
||||||
|
*status |= FE_HAS_VITERBI;
|
||||||
|
if (s0 & (1 << 5))
|
||||||
|
*status |= FE_HAS_LOCK;
|
||||||
|
if (s1 & (1 << 1))
|
||||||
|
*status |= FE_HAS_SYNC;
|
||||||
|
if (s3 & (1 << 6))
|
||||||
|
*status |= FE_HAS_SIGNAL;
|
||||||
|
|
||||||
|
if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
|
||||||
|
(FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
|
||||||
|
*status &= ~FE_HAS_LOCK;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
|
||||||
|
{
|
||||||
|
struct vp7045_fe_state *state = fe->demodulator_priv;
|
||||||
|
*ber = (vp7045_read_reg(state->d, 0x0D) << 16) |
|
||||||
|
(vp7045_read_reg(state->d, 0x0E) << 8) |
|
||||||
|
vp7045_read_reg(state->d, 0x0F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
|
||||||
|
{
|
||||||
|
struct vp7045_fe_state *state = fe->demodulator_priv;
|
||||||
|
*unc = (vp7045_read_reg(state->d, 0x10) << 8) |
|
||||||
|
vp7045_read_reg(state->d, 0x11);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
|
||||||
|
{
|
||||||
|
struct vp7045_fe_state *state = fe->demodulator_priv;
|
||||||
|
u16 signal = (vp7045_read_reg(state->d, 0x14) << 8) |
|
||||||
|
vp7045_read_reg(state->d, 0x15);
|
||||||
|
|
||||||
|
*strength = ~signal;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
|
||||||
|
{
|
||||||
|
struct vp7045_fe_state *state = fe->demodulator_priv;
|
||||||
|
u8 _snr = vp7045_read_reg(state->d, 0x09);
|
||||||
|
*snr = (_snr << 8) | _snr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_fe_init(struct dvb_frontend* fe)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_fe_sleep(struct dvb_frontend* fe)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
|
||||||
|
{
|
||||||
|
tune->min_delay_ms = 800;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_fe_set_frontend(struct dvb_frontend* fe,
|
||||||
|
struct dvb_frontend_parameters *fep)
|
||||||
|
{
|
||||||
|
struct vp7045_fe_state *state = fe->demodulator_priv;
|
||||||
|
u8 buf[5];
|
||||||
|
u32 freq = fep->frequency / 1000;
|
||||||
|
|
||||||
|
buf[0] = (freq >> 16) & 0xff;
|
||||||
|
buf[1] = (freq >> 8) & 0xff;
|
||||||
|
buf[2] = freq & 0xff;
|
||||||
|
buf[3] = 0;
|
||||||
|
|
||||||
|
switch (fep->u.ofdm.bandwidth) {
|
||||||
|
case BANDWIDTH_8_MHZ: buf[4] = 8; break;
|
||||||
|
case BANDWIDTH_7_MHZ: buf[4] = 7; break;
|
||||||
|
case BANDWIDTH_6_MHZ: buf[4] = 6; break;
|
||||||
|
case BANDWIDTH_AUTO: return -EOPNOTSUPP;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_fe_get_frontend(struct dvb_frontend* fe,
|
||||||
|
struct dvb_frontend_parameters *fep)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vp7045_fe_release(struct dvb_frontend* fe)
|
||||||
|
{
|
||||||
|
struct vp7045_fe_state *state = fe->demodulator_priv;
|
||||||
|
kfree(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dvb_frontend_ops vp7045_fe_ops;
|
||||||
|
|
||||||
|
struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
struct vp7045_fe_state *s = kmalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
|
||||||
|
if (s == NULL)
|
||||||
|
goto error;
|
||||||
|
memset(s,0,sizeof(struct vp7045_fe_state));
|
||||||
|
|
||||||
|
s->d = d;
|
||||||
|
s->fe.ops = &vp7045_fe_ops;
|
||||||
|
s->fe.demodulator_priv = s;
|
||||||
|
|
||||||
|
goto success;
|
||||||
|
error:
|
||||||
|
return NULL;
|
||||||
|
success:
|
||||||
|
return &s->fe;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct dvb_frontend_ops vp7045_fe_ops = {
|
||||||
|
.info = {
|
||||||
|
.name = "Twinhan VP7045/46 USB DVB-T",
|
||||||
|
.type = FE_OFDM,
|
||||||
|
.frequency_min = 44250000,
|
||||||
|
.frequency_max = 867250000,
|
||||||
|
.frequency_stepsize = 1000,
|
||||||
|
.caps = FE_CAN_INVERSION_AUTO |
|
||||||
|
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||||
|
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||||
|
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
|
||||||
|
FE_CAN_TRANSMISSION_MODE_AUTO |
|
||||||
|
FE_CAN_GUARD_INTERVAL_AUTO |
|
||||||
|
FE_CAN_RECOVER |
|
||||||
|
FE_CAN_HIERARCHY_AUTO,
|
||||||
|
},
|
||||||
|
|
||||||
|
.release = vp7045_fe_release,
|
||||||
|
|
||||||
|
.init = vp7045_fe_init,
|
||||||
|
.sleep = vp7045_fe_sleep,
|
||||||
|
|
||||||
|
.set_frontend = vp7045_fe_set_frontend,
|
||||||
|
.get_frontend = vp7045_fe_get_frontend,
|
||||||
|
.get_tune_settings = vp7045_fe_get_tune_settings,
|
||||||
|
|
||||||
|
.read_status = vp7045_fe_read_status,
|
||||||
|
.read_ber = vp7045_fe_read_ber,
|
||||||
|
.read_signal_strength = vp7045_fe_read_signal_strength,
|
||||||
|
.read_snr = vp7045_fe_read_snr,
|
||||||
|
.read_ucblocks = vp7045_fe_read_unc_blocks,
|
||||||
|
};
|
263
drivers/media/dvb/dvb-usb/vp7045.c
Normal file
263
drivers/media/dvb/dvb-usb/vp7045.c
Normal file
|
@ -0,0 +1,263 @@
|
||||||
|
/* DVB USB compliant Linux driver for the
|
||||||
|
* - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver
|
||||||
|
* - DigitalNow TinyUSB2 DVB-t receiver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* Thanks to Twinhan who kindly provided hardware and information.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "vp7045.h"
|
||||||
|
|
||||||
|
/* debug */
|
||||||
|
int dvb_usb_vp7045_debug;
|
||||||
|
module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
|
||||||
|
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
|
||||||
|
|
||||||
|
int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
u8 inbuf[12] = { 0 }, outbuf[20] = { 0 };
|
||||||
|
|
||||||
|
outbuf[0] = cmd;
|
||||||
|
|
||||||
|
if (outlen > 19)
|
||||||
|
outlen = 19;
|
||||||
|
|
||||||
|
if (inlen > 11)
|
||||||
|
inlen = 11;
|
||||||
|
|
||||||
|
if (out != NULL && outlen > 0)
|
||||||
|
memcpy(&outbuf[1], out, outlen);
|
||||||
|
|
||||||
|
deb_xfer("out buffer: ");
|
||||||
|
debug_dump(outbuf,outlen+1,deb_xfer);
|
||||||
|
|
||||||
|
if ((ret = down_interruptible(&d->usb_sem)))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (usb_control_msg(d->udev,
|
||||||
|
usb_sndctrlpipe(d->udev,0),
|
||||||
|
TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
|
||||||
|
outbuf, 20, 2*HZ) != 20) {
|
||||||
|
err("USB control message 'out' went wrong.");
|
||||||
|
ret = -EIO;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
msleep(msec);
|
||||||
|
|
||||||
|
if (usb_control_msg(d->udev,
|
||||||
|
usb_rcvctrlpipe(d->udev,0),
|
||||||
|
TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
|
||||||
|
inbuf, 12, 2*HZ) != 12) {
|
||||||
|
err("USB control message 'in' went wrong.");
|
||||||
|
ret = -EIO;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
deb_xfer("in buffer: ");
|
||||||
|
debug_dump(inbuf,12,deb_xfer);
|
||||||
|
|
||||||
|
if (in != NULL && inlen > 0)
|
||||||
|
memcpy(in,&inbuf[1],inlen);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
up(&d->usb_sem);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg)
|
||||||
|
{
|
||||||
|
u8 obuf[2] = { 0 },v;
|
||||||
|
obuf[1] = reg;
|
||||||
|
|
||||||
|
vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
u8 v = onoff;
|
||||||
|
return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remote control stuff */
|
||||||
|
|
||||||
|
/* The keymapping struct. Somehow this should be loaded to the driver, but
|
||||||
|
* currently it is hardcoded. */
|
||||||
|
static struct dvb_usb_rc_key vp7045_rc_keys[] = {
|
||||||
|
/* insert the keys like this. to make the raw keys visible, enable
|
||||||
|
* debug=0x04 when loading dvb-usb-vp7045. */
|
||||||
|
|
||||||
|
/* these keys are probably wrong. I don't have a working IR-receiver on my
|
||||||
|
* vp7045, so I can't test it. Patches are welcome. */
|
||||||
|
{ 0x00, 0x01, KEY_1 },
|
||||||
|
{ 0x00, 0x02, KEY_2 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int vp7045_rc_query(struct dvb_usb_device *d, u32 *key_buf, int *state)
|
||||||
|
{
|
||||||
|
u8 key;
|
||||||
|
int i;
|
||||||
|
vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20);
|
||||||
|
|
||||||
|
deb_rc("remote query key: %x %d\n",key,key);
|
||||||
|
|
||||||
|
if (key == 0x44) {
|
||||||
|
*state = REMOTE_NO_KEY_PRESSED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(vp7045_rc_keys)/sizeof(struct dvb_usb_rc_key); i++)
|
||||||
|
if (vp7045_rc_keys[i].data == key) {
|
||||||
|
*state = REMOTE_KEY_PRESSED;
|
||||||
|
*key_buf = vp7045_rc_keys[i].event;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
u8 v,br[2];
|
||||||
|
for (i=0; i < len; i++) {
|
||||||
|
v = offset + i;
|
||||||
|
vp7045_usb_op(d,GET_EE_VALUE,&v,1,br,2,5);
|
||||||
|
buf[i] = br[1];
|
||||||
|
}
|
||||||
|
deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ",offset, i);
|
||||||
|
debug_dump(buf,i,deb_info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
|
||||||
|
{
|
||||||
|
return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vp7045_frontend_attach(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
u8 buf[255] = { 0 };
|
||||||
|
|
||||||
|
vp7045_usb_op(d,VENDOR_STRING_READ,NULL,0,buf,20,0);
|
||||||
|
buf[10] = '\0';
|
||||||
|
deb_info("firmware says: %s ",buf);
|
||||||
|
|
||||||
|
vp7045_usb_op(d,PRODUCT_STRING_READ,NULL,0,buf,20,0);
|
||||||
|
buf[10] = '\0';
|
||||||
|
deb_info("%s ",buf);
|
||||||
|
|
||||||
|
vp7045_usb_op(d,FW_VERSION_READ,NULL,0,buf,20,0);
|
||||||
|
buf[10] = '\0';
|
||||||
|
deb_info("v%s\n",buf);
|
||||||
|
|
||||||
|
/* Dump the EEPROM */
|
||||||
|
/* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
|
||||||
|
|
||||||
|
d->fe = vp7045_fe_attach(d);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dvb_usb_properties vp7045_properties;
|
||||||
|
|
||||||
|
static int vp7045_usb_probe(struct usb_interface *intf,
|
||||||
|
const struct usb_device_id *id)
|
||||||
|
{
|
||||||
|
return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usb_device_id vp7045_usb_table [] = {
|
||||||
|
{ USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_COLD) },
|
||||||
|
{ USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_WARM) },
|
||||||
|
{ USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_COLD) },
|
||||||
|
{ USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_WARM) },
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
|
||||||
|
|
||||||
|
static struct dvb_usb_properties vp7045_properties = {
|
||||||
|
.caps = 0,
|
||||||
|
|
||||||
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
|
.firmware = "dvb-usb-vp7045-01.fw",
|
||||||
|
|
||||||
|
.power_ctrl = vp7045_power_ctrl,
|
||||||
|
.frontend_attach = vp7045_frontend_attach,
|
||||||
|
.read_mac_address = vp7045_read_mac_addr,
|
||||||
|
|
||||||
|
.rc_interval = 400,
|
||||||
|
.rc_key_map = vp7045_rc_keys,
|
||||||
|
.rc_key_map_size = ARRAY_SIZE(vp7045_rc_keys),
|
||||||
|
.rc_query = vp7045_rc_query,
|
||||||
|
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 7,
|
||||||
|
.endpoint = 0x02,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 4096,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 2,
|
||||||
|
.devices = {
|
||||||
|
{ .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)",
|
||||||
|
.cold_ids = { &vp7045_usb_table[0], NULL },
|
||||||
|
.warm_ids = { &vp7045_usb_table[1], NULL },
|
||||||
|
},
|
||||||
|
{ .name = "DigitalNow TinyUSB 2 DVB-t Receiver",
|
||||||
|
.cold_ids = { &vp7045_usb_table[2], NULL },
|
||||||
|
.warm_ids = { &vp7045_usb_table[3], NULL },
|
||||||
|
},
|
||||||
|
{ 0 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* usb specific object needed to register this driver with the usb subsystem */
|
||||||
|
static struct usb_driver vp7045_usb_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "dvb-usb-vp7045",
|
||||||
|
.probe = vp7045_usb_probe,
|
||||||
|
.disconnect = dvb_usb_device_exit,
|
||||||
|
.id_table = vp7045_usb_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* module stuff */
|
||||||
|
static int __init vp7045_usb_module_init(void)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if ((result = usb_register(&vp7045_usb_driver))) {
|
||||||
|
err("usb_register failed. (%d)",result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit vp7045_usb_module_exit(void)
|
||||||
|
{
|
||||||
|
/* deregister this driver from the USB subsystem */
|
||||||
|
usb_deregister(&vp7045_usb_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(vp7045_usb_module_init);
|
||||||
|
module_exit(vp7045_usb_module_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||||
|
MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0");
|
||||||
|
MODULE_VERSION("1.0");
|
||||||
|
MODULE_LICENSE("GPL");
|
78
drivers/media/dvb/dvb-usb/vp7045.h
Normal file
78
drivers/media/dvb/dvb-usb/vp7045.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII
|
||||||
|
* USB2.0 DVB-T receiver.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||||
|
*
|
||||||
|
* Thanks to Twinhan who kindly provided hardware and information.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#ifndef _DVB_USB_VP7045_H_
|
||||||
|
#define _DVB_USB_VP7045_H_
|
||||||
|
|
||||||
|
#define DVB_USB_LOG_PREFIX "vp7045"
|
||||||
|
#include "dvb-usb.h"
|
||||||
|
|
||||||
|
extern int dvb_usb_vp7045_debug;
|
||||||
|
#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
|
||||||
|
#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
|
||||||
|
#define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args)
|
||||||
|
|
||||||
|
/* vp7045 commands */
|
||||||
|
|
||||||
|
/* Twinhan Vendor requests */
|
||||||
|
#define TH_COMMAND_IN 0xC0
|
||||||
|
#define TH_COMMAND_OUT 0xC1
|
||||||
|
|
||||||
|
/* command bytes */
|
||||||
|
#define TUNER_REG_READ 0x03
|
||||||
|
#define TUNER_REG_WRITE 0x04
|
||||||
|
|
||||||
|
#define RC_VAL_READ 0x05
|
||||||
|
#define RC_NO_KEY 0x44
|
||||||
|
|
||||||
|
#define SET_TUNER_POWER 0x06
|
||||||
|
#define CHECK_TUNER_POWER 0x12
|
||||||
|
#define Tuner_Power_ON 1
|
||||||
|
#define Tuner_Power_OFF 0
|
||||||
|
|
||||||
|
#define GET_USB_SPEED 0x07
|
||||||
|
#define USB_SPEED_LOW 0
|
||||||
|
#define USB_SPEED_FULL 1
|
||||||
|
#define USB_SPEED_HIGH 2
|
||||||
|
|
||||||
|
#define LOCK_TUNER_COMMAND 0x09
|
||||||
|
|
||||||
|
#define TUNER_SIGNAL_READ 0x0A
|
||||||
|
|
||||||
|
/* FX2 eeprom */
|
||||||
|
#define SET_EE_VALUE 0x10
|
||||||
|
#define GET_EE_VALUE 0x11
|
||||||
|
#define FX2_ID_ADDR 0x00
|
||||||
|
#define VID_MSB_ADDR 0x02
|
||||||
|
#define VID_LSB_ADDR 0x01
|
||||||
|
#define PID_MSB_ADDR 0x04
|
||||||
|
#define PID_LSB_ADDR 0x03
|
||||||
|
#define MAC_0_ADDR 0x07
|
||||||
|
#define MAC_1_ADDR 0x08
|
||||||
|
#define MAC_2_ADDR 0x09
|
||||||
|
#define MAC_3_ADDR 0x0a
|
||||||
|
#define MAC_4_ADDR 0x0b
|
||||||
|
#define MAC_5_ADDR 0x0c
|
||||||
|
|
||||||
|
#define RESET_FX2 0x13
|
||||||
|
|
||||||
|
#define FW_VERSION_READ 0x0B
|
||||||
|
#define VENDOR_STRING_READ 0x0C
|
||||||
|
#define PRODUCT_STRING_READ 0x0D
|
||||||
|
#define FW_BCD_VERSION_READ 0x14
|
||||||
|
|
||||||
|
extern struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d);
|
||||||
|
extern int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen,int msec);
|
||||||
|
extern u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg);
|
||||||
|
|
||||||
|
#endif
|
|
@ -73,7 +73,7 @@ u16 dib3000_seq[2][2][2] = /* fft,gua, inv */
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
|
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
|
||||||
MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb-frontend drivers");
|
MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
EXPORT_SYMBOL(dib3000_seq);
|
EXPORT_SYMBOL(dib3000_seq);
|
||||||
|
|
|
@ -32,9 +32,8 @@ struct dib3000_config
|
||||||
u8 demod_address;
|
u8 demod_address;
|
||||||
|
|
||||||
/* PLL maintenance and the i2c address of the PLL */
|
/* PLL maintenance and the i2c address of the PLL */
|
||||||
u8 (*pll_addr)(struct dvb_frontend *fe);
|
int (*pll_init)(struct dvb_frontend *fe);
|
||||||
int (*pll_init)(struct dvb_frontend *fe, u8 pll_buf[5]);
|
int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params);
|
||||||
int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params, u8 pll_buf[5]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dib_fe_xfer_ops
|
struct dib_fe_xfer_ops
|
||||||
|
|
|
@ -48,8 +48,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a
|
||||||
#define deb_setf(args...) dprintk(0x04,args)
|
#define deb_setf(args...) dprintk(0x04,args)
|
||||||
#define deb_getf(args...) dprintk(0x08,args)
|
#define deb_getf(args...) dprintk(0x08,args)
|
||||||
|
|
||||||
static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr);
|
|
||||||
|
|
||||||
static int dib3000mb_get_frontend(struct dvb_frontend* fe,
|
static int dib3000mb_get_frontend(struct dvb_frontend* fe,
|
||||||
struct dvb_frontend_parameters *fep);
|
struct dvb_frontend_parameters *fep);
|
||||||
|
|
||||||
|
@ -61,10 +59,8 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
|
||||||
fe_code_rate_t fe_cr = FEC_NONE;
|
fe_code_rate_t fe_cr = FEC_NONE;
|
||||||
int search_state, seq;
|
int search_state, seq;
|
||||||
|
|
||||||
if (tuner && state->config.pll_addr && state->config.pll_set) {
|
if (tuner && state->config.pll_set) {
|
||||||
dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
|
state->config.pll_set(fe, fep);
|
||||||
state->config.pll_set(fe, fep, NULL);
|
|
||||||
dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
|
|
||||||
|
|
||||||
deb_setf("bandwidth: ");
|
deb_setf("bandwidth: ");
|
||||||
switch (ofdm->bandwidth) {
|
switch (ofdm->bandwidth) {
|
||||||
|
@ -389,11 +385,8 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
|
||||||
|
|
||||||
wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
|
wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
|
||||||
|
|
||||||
if (state->config.pll_init) {
|
if (state->config.pll_init)
|
||||||
dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
|
state->config.pll_init(fe);
|
||||||
state->config.pll_init(fe,NULL);
|
|
||||||
dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -623,7 +616,7 @@ static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
|
||||||
{
|
{
|
||||||
struct dib3000_state* state = fe->demodulator_priv;
|
struct dib3000_state* state = fe->demodulator_priv;
|
||||||
|
|
||||||
*unc = rd(DIB3000MB_REG_UNC);
|
*unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,9 +631,6 @@ static int dib3000mb_sleep(struct dvb_frontend* fe)
|
||||||
static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
|
static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
|
||||||
{
|
{
|
||||||
tune->min_delay_ms = 800;
|
tune->min_delay_ms = 800;
|
||||||
tune->step_size = 166667;
|
|
||||||
tune->max_drift = 166667 * 2;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe,16=s
|
||||||
#define deb_getf(args...) dprintk(0x08,args)
|
#define deb_getf(args...) dprintk(0x08,args)
|
||||||
#define deb_stat(args...) dprintk(0x10,args)
|
#define deb_stat(args...) dprintk(0x10,args)
|
||||||
|
|
||||||
static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr);
|
|
||||||
|
|
||||||
static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode,
|
static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode,
|
||||||
fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth)
|
fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth)
|
||||||
{
|
{
|
||||||
|
@ -463,10 +461,8 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
|
||||||
int search_state,auto_val;
|
int search_state,auto_val;
|
||||||
u16 val;
|
u16 val;
|
||||||
|
|
||||||
if (tuner && state->config.pll_addr && state->config.pll_set) { /* initial call from dvb */
|
if (tuner && state->config.pll_set) { /* initial call from dvb */
|
||||||
dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
|
state->config.pll_set(fe,fep);
|
||||||
state->config.pll_set(fe,fep,NULL);
|
|
||||||
dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
|
|
||||||
|
|
||||||
state->last_tuned_freq = fep->frequency;
|
state->last_tuned_freq = fep->frequency;
|
||||||
// if (!scanboost) {
|
// if (!scanboost) {
|
||||||
|
@ -554,19 +550,15 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
|
||||||
dib3000mc_set_adp_cfg(state,ofdm->constellation);
|
dib3000mc_set_adp_cfg(state,ofdm->constellation);
|
||||||
wr_foreach(dib3000mc_reg_offset,
|
wr_foreach(dib3000mc_reg_offset,
|
||||||
dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
|
dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
|
static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
|
||||||
{
|
{
|
||||||
struct dib3000_state *state;
|
struct dib3000_state *state = fe->demodulator_priv;
|
||||||
|
|
||||||
deb_info("init start\n");
|
deb_info("init start\n");
|
||||||
|
|
||||||
state = fe->demodulator_priv;
|
|
||||||
state->timing_offset = 0;
|
state->timing_offset = 0;
|
||||||
state->timing_offset_comp_done = 0;
|
state->timing_offset_comp_done = 0;
|
||||||
|
|
||||||
|
@ -649,11 +641,9 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
|
||||||
|
|
||||||
set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
|
set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
|
||||||
|
|
||||||
/* if (state->config->pll_init) {
|
if (state->config.pll_init)
|
||||||
dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
|
state->config.pll_init(fe);
|
||||||
state->config->pll_init(fe,NULL);
|
|
||||||
dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
|
|
||||||
}*/
|
|
||||||
deb_info("init end\n");
|
deb_info("init end\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -688,7 +678,7 @@ static int dib3000mc_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
|
||||||
{
|
{
|
||||||
struct dib3000_state* state = fe->demodulator_priv;
|
struct dib3000_state* state = fe->demodulator_priv;
|
||||||
|
|
||||||
*unc = rd(DIB3000MC_REG_PACKET_ERROR_COUNT);
|
*unc = rd(DIB3000MC_REG_PACKET_ERRORS);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,10 +727,7 @@ static int dib3000mc_sleep(struct dvb_frontend* fe)
|
||||||
|
|
||||||
static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
|
static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
|
||||||
{
|
{
|
||||||
tune->min_delay_ms = 2000;
|
tune->min_delay_ms = 1000;
|
||||||
tune->step_size = 166667;
|
|
||||||
tune->max_drift = 166667 * 2;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* $Id: dvb-pll.c,v 1.7 2005/02/10 11:52:02 kraxel Exp $
|
|
||||||
*
|
|
||||||
* descriptions + helper functions for simple dvb plls.
|
* descriptions + helper functions for simple dvb plls.
|
||||||
*
|
*
|
||||||
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
|
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
|
||||||
|
@ -114,6 +112,92 @@ struct dvb_pll_desc dvb_pll_unknown_1 = {
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(dvb_pll_unknown_1);
|
EXPORT_SYMBOL(dvb_pll_unknown_1);
|
||||||
|
|
||||||
|
/* Infineon TUA6010XS
|
||||||
|
* used in Thomson Cable Tuner
|
||||||
|
*/
|
||||||
|
struct dvb_pll_desc dvb_pll_tua6010xs = {
|
||||||
|
.name = "Infineon TUA6010XS",
|
||||||
|
.min = 44250000,
|
||||||
|
.max = 858000000,
|
||||||
|
.count = 3,
|
||||||
|
.entries = {
|
||||||
|
{ 115750000, 36125000, 62500, 0x8e, 0x03 },
|
||||||
|
{ 403250000, 36125000, 62500, 0x8e, 0x06 },
|
||||||
|
{ 999999999, 36125000, 62500, 0x8e, 0x85 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL(dvb_pll_tua6010xs);
|
||||||
|
|
||||||
|
/* Panasonic env57h1xd5 (some Philips PLL ?) */
|
||||||
|
struct dvb_pll_desc dvb_pll_env57h1xd5 = {
|
||||||
|
.name = "Panasonic ENV57H1XD5",
|
||||||
|
.min = 44250000,
|
||||||
|
.max = 858000000,
|
||||||
|
.count = 4,
|
||||||
|
.entries = {
|
||||||
|
{ 153000000, 36291666, 166666, 0xc2, 0x41 },
|
||||||
|
{ 470000000, 36291666, 166666, 0xc2, 0x42 },
|
||||||
|
{ 526000000, 36291666, 166666, 0xc2, 0x84 },
|
||||||
|
{ 999999999, 36291666, 166666, 0xc2, 0xa4 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL(dvb_pll_env57h1xd5);
|
||||||
|
|
||||||
|
/* Philips TDA6650/TDA6651
|
||||||
|
* used in Panasonic ENV77H11D5
|
||||||
|
*/
|
||||||
|
static void tda665x_bw(u8 *buf, int bandwidth)
|
||||||
|
{
|
||||||
|
if (bandwidth == BANDWIDTH_8_MHZ)
|
||||||
|
buf[3] |= 0x08;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dvb_pll_desc dvb_pll_tda665x = {
|
||||||
|
.name = "Philips TDA6650/TDA6651",
|
||||||
|
.min = 44250000,
|
||||||
|
.max = 858000000,
|
||||||
|
.setbw = tda665x_bw,
|
||||||
|
.count = 12,
|
||||||
|
.entries = {
|
||||||
|
{ 93834000, 36249333, 166667, 0xca, 0x61 /* 011 0 0 0 01 */ },
|
||||||
|
{ 123834000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ },
|
||||||
|
{ 161000000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ },
|
||||||
|
{ 163834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ },
|
||||||
|
{ 253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ },
|
||||||
|
{ 383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ },
|
||||||
|
{ 443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ },
|
||||||
|
{ 444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ },
|
||||||
|
{ 583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0 11 */ },
|
||||||
|
{ 793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0 11 */ },
|
||||||
|
{ 444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ },
|
||||||
|
{ 861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0 11 */ },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL(dvb_pll_tda665x);
|
||||||
|
|
||||||
|
/* Infineon TUA6034
|
||||||
|
* used in LG TDTP E102P
|
||||||
|
*/
|
||||||
|
static void tua6034_bw(u8 *buf, int bandwidth)
|
||||||
|
{
|
||||||
|
if (BANDWIDTH_7_MHZ != bandwidth)
|
||||||
|
buf[3] |= 0x08;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dvb_pll_desc dvb_pll_tua6034 = {
|
||||||
|
.name = "Infineon TUA6034",
|
||||||
|
.min = 44250000,
|
||||||
|
.max = 858000000,
|
||||||
|
.count = 3,
|
||||||
|
.setbw = tua6034_bw,
|
||||||
|
.entries = {
|
||||||
|
{ 174500000, 36166667, 62500, 0xce, 0x01 },
|
||||||
|
{ 230000000, 36166667, 62500, 0xce, 0x02 },
|
||||||
|
{ 999999999, 36166667, 62500, 0xce, 0x04 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL(dvb_pll_tua6034);
|
||||||
|
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
/* code */
|
/* code */
|
||||||
|
|
||||||
|
@ -160,9 +244,3 @@ EXPORT_SYMBOL(dvb_pll_configure);
|
||||||
MODULE_DESCRIPTION("dvb pll library");
|
MODULE_DESCRIPTION("dvb pll library");
|
||||||
MODULE_AUTHOR("Gerd Knorr");
|
MODULE_AUTHOR("Gerd Knorr");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* $Id: dvb-pll.h,v 1.2 2005/02/10 11:43:41 kraxel Exp $
|
* descriptions + helper functions for simple dvb plls.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DVB_PLL_H__
|
#ifndef __DVB_PLL_H__
|
||||||
|
@ -17,7 +17,7 @@ struct dvb_pll_desc {
|
||||||
u32 stepsize;
|
u32 stepsize;
|
||||||
u8 cb1;
|
u8 cb1;
|
||||||
u8 cb2;
|
u8 cb2;
|
||||||
} entries[9];
|
} entries[12];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct dvb_pll_desc dvb_pll_thomson_dtt7579;
|
extern struct dvb_pll_desc dvb_pll_thomson_dtt7579;
|
||||||
|
@ -26,6 +26,11 @@ extern struct dvb_pll_desc dvb_pll_thomson_dtt7610;
|
||||||
extern struct dvb_pll_desc dvb_pll_lg_z201;
|
extern struct dvb_pll_desc dvb_pll_lg_z201;
|
||||||
extern struct dvb_pll_desc dvb_pll_unknown_1;
|
extern struct dvb_pll_desc dvb_pll_unknown_1;
|
||||||
|
|
||||||
|
extern struct dvb_pll_desc dvb_pll_tua6010xs;
|
||||||
|
extern struct dvb_pll_desc dvb_pll_env57h1xd5;
|
||||||
|
extern struct dvb_pll_desc dvb_pll_tua6034;
|
||||||
|
extern struct dvb_pll_desc dvb_pll_tda665x;
|
||||||
|
|
||||||
int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
||||||
u32 freq, int bandwidth);
|
u32 freq, int bandwidth);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue