Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (213 commits)
  V4L/DVB (12720): em28xx-cards: Add vendor/product id for Kworld DVD Maker 2
  V4L/DVB (12713): em28xx: Cleanups at ir_i2c handler
  V4L/DVB (12712): em28xx: properly load ir-kbd-i2c when needed
  V4L/DVB (12701): saa7134: ir-kbd-i2c init data needs a persistent object
  V4L/DVB (12699): cx18: ir-kbd-i2c initialization data should point to a persistent object
  V4L/DVB (12698): em28xx: ir-kbd-i2c init data needs a persistent object
  V4L/DVB (12707): gspca - sn9c20x: Add SXGA support to MT9M111
  V4L/DVB (12706): gspca - sn9c20x: disable exposure/gain controls for MT9M111 sensors.
  V4L/DVB (12705): gspca - sn9c20x: Add SXGA support to SOI968
  V4L/DVB (12703): gspca - sn9c20x: Reduces size of object
  V4L/DVB (12704): gspca - sn9c20x: Fix exposure on SOI968 sensors
  V4L/DVB (12696): gspca - sonixj / sn9c102: Two drivers for 0c45:60fc and 0c45:613e.
  V4L/DVB (12695): gspca - vc032x: Do the LED work with the sensor hv7131r.
  V4L/DVB (12694): gspca - vc032x: Change the start exchanges of the sensor hv7131r.
  V4L/DVB (12693): gspca - sunplus: The brightness is signed.
  V4L/DVB (12692): gspca - sunplus: Optimize code.
  V4L/DVB (12691): gspca - sonixj: Don't use mdelay().
  V4L/DVB (12690): gspca - pac7311: Webcam 06f8:3009 added.
  V4L/DVB (12686): dvb-core: check supported QAM modulations
  V4L/DVB (12685): dvb-core: check fe->ops.set_frontend return value
  ...
This commit is contained in:
Linus Torvalds 2009-09-15 09:22:18 -07:00
commit 043fe50f80
201 changed files with 17042 additions and 8532 deletions

View file

@ -21,3 +21,5 @@
20 -> Hauppauge WinTV-HVR1255 [0070:2251] 20 -> Hauppauge WinTV-HVR1255 [0070:2251]
21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295] 21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295]
22 -> Mygica X8506 DMB-TH [14f1:8651] 22 -> Mygica X8506 DMB-TH [14f1:8651]
23 -> Magic-Pro ProHDTV Extreme 2 [14f1:8657]
24 -> Hauppauge WinTV-HVR1850 [0070:8541]

View file

@ -80,3 +80,4 @@
79 -> Terratec Cinergy HT PCI MKII [153b:1177] 79 -> Terratec Cinergy HT PCI MKII [153b:1177]
80 -> Hauppauge WinTV-IR Only [0070:9290] 80 -> Hauppauge WinTV-IR Only [0070:9290]
81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654] 81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654]
82 -> WinFast DTV2000 H rev. J [107d:6f2b]

View file

@ -7,7 +7,7 @@
6 -> Terratec Cinergy 200 USB (em2800) 6 -> Terratec Cinergy 200 USB (em2800)
7 -> Leadtek Winfast USB II (em2800) [0413:6023] 7 -> Leadtek Winfast USB II (em2800) [0413:6023]
8 -> Kworld USB2800 (em2800) 8 -> Kworld USB2800 (em2800)
9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,2304:0207,2304:021a] 9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,1b80:e304,2304:0207,2304:021a]
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
12 -> Kworld PVR TV 2800 RF (em2820/em2840) 12 -> Kworld PVR TV 2800 RF (em2820/em2840)
@ -33,7 +33,7 @@
34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f] 34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f]
35 -> Typhoon DVD Maker (em2860) 35 -> Typhoon DVD Maker (em2860)
36 -> NetGMBH Cam (em2860) 36 -> NetGMBH Cam (em2860)
37 -> Gadmei UTV330 (em2860) 37 -> Gadmei UTV330 (em2860) [eb1a:50a6]
38 -> Yakumo MovieMixer (em2861) 38 -> Yakumo MovieMixer (em2861)
39 -> KWorld PVRTV 300U (em2861) [eb1a:e300] 39 -> KWorld PVRTV 300U (em2861) [eb1a:e300]
40 -> Plextor ConvertX PX-TV100U (em2861) [093b:a005] 40 -> Plextor ConvertX PX-TV100U (em2861) [093b:a005]
@ -67,3 +67,4 @@
69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313] 69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313]
70 -> Evga inDtube (em2882) 70 -> Evga inDtube (em2882)
71 -> Silvercrest Webcam 1.3mpix (em2820/em2840) 71 -> Silvercrest Webcam 1.3mpix (em2820/em2840)
72 -> Gadmei UTV330+ (em2861)

View file

@ -167,3 +167,7 @@
166 -> Beholder BeholdTV 607 RDS [5ace:6073] 166 -> Beholder BeholdTV 607 RDS [5ace:6073]
167 -> Beholder BeholdTV 609 RDS [5ace:6092] 167 -> Beholder BeholdTV 609 RDS [5ace:6092]
168 -> Beholder BeholdTV 609 RDS [5ace:6093] 168 -> Beholder BeholdTV 609 RDS [5ace:6093]
169 -> Compro VideoMate S350/S300 [185b:c900]
170 -> AverMedia AverTV Studio 505 [1461:a115]
171 -> Beholder BeholdTV X7 [5ace:7595]
172 -> RoverMedia TV Link Pro FM [19d1:0138]

View file

@ -78,3 +78,4 @@ tuner=77 - TCL tuner MF02GIP-5N-E
tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner
tuner=79 - Philips PAL/SECAM multi (FM1216 MK5) tuner=79 - Philips PAL/SECAM multi (FM1216 MK5)
tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
tuner=81 - Partsnic (Daewoo) PTI-5NF05

View file

@ -18,8 +18,8 @@ Table of Contents
1.0 Introduction 1.0 Introduction
The file ../drivers/char/c-qcam.c is a device driver for the The file ../../drivers/media/video/c-qcam.c is a device driver for
Logitech (nee Connectix) parallel port interface color CCD camera. the Logitech (nee Connectix) parallel port interface color CCD camera.
This is a fairly inexpensive device for capturing images. Logitech This is a fairly inexpensive device for capturing images. Logitech
does not currently provide information for developers, but many people does not currently provide information for developers, but many people
have engineered several solutions for non-Microsoft use of the Color have engineered several solutions for non-Microsoft use of the Color

View file

@ -140,6 +140,7 @@ spca500 04fc:7333 PalmPixDC85
sunplus 04fc:ffff Pure DigitalDakota sunplus 04fc:ffff Pure DigitalDakota
spca501 0506:00df 3Com HomeConnect Lite spca501 0506:00df 3Com HomeConnect Lite
sunplus 052b:1513 Megapix V4 sunplus 052b:1513 Megapix V4
sunplus 052b:1803 MegaImage VI
tv8532 0545:808b Veo Stingray tv8532 0545:808b Veo Stingray
tv8532 0545:8333 Veo Stingray tv8532 0545:8333 Veo Stingray
sunplus 0546:3155 Polaroid PDC3070 sunplus 0546:3155 Polaroid PDC3070
@ -182,6 +183,7 @@ ov534 06f8:3002 Hercules Blog Webcam
ov534 06f8:3003 Hercules Dualpix HD Weblog ov534 06f8:3003 Hercules Dualpix HD Weblog
sonixj 06f8:3004 Hercules Classic Silver sonixj 06f8:3004 Hercules Classic Silver
sonixj 06f8:3008 Hercules Deluxe Optical Glass sonixj 06f8:3008 Hercules Deluxe Optical Glass
pac7311 06f8:3009 Hercules Classic Link
spca508 0733:0110 ViewQuest VQ110 spca508 0733:0110 ViewQuest VQ110
spca508 0130:0130 Clone Digital Webcam 11043 spca508 0130:0130 Clone Digital Webcam 11043
spca501 0733:0401 Intel Create and Share spca501 0733:0401 Intel Create and Share
@ -235,8 +237,10 @@ pac7311 093a:2621 PAC731x
pac7311 093a:2622 Genius Eye 312 pac7311 093a:2622 Genius Eye 312
pac7311 093a:2624 PAC7302 pac7311 093a:2624 PAC7302
pac7311 093a:2626 Labtec 2200 pac7311 093a:2626 Labtec 2200
pac7311 093a:2629 Genious iSlim 300
pac7311 093a:262a Webcam 300k pac7311 093a:262a Webcam 300k
pac7311 093a:262c Philips SPC 230 NC pac7311 093a:262c Philips SPC 230 NC
jeilinj 0979:0280 Sakar 57379
zc3xx 0ac8:0302 Z-star Vimicro zc0302 zc3xx 0ac8:0302 Z-star Vimicro zc0302
vc032x 0ac8:0321 Vimicro generic vc0321 vc032x 0ac8:0321 Vimicro generic vc0321
vc032x 0ac8:0323 Vimicro Vc0323 vc032x 0ac8:0323 Vimicro Vc0323
@ -247,6 +251,7 @@ zc3xx 0ac8:305b Z-star Vimicro zc0305b
zc3xx 0ac8:307b Ldlc VC302+Ov7620 zc3xx 0ac8:307b Ldlc VC302+Ov7620
vc032x 0ac8:c001 Sony embedded vimicro vc032x 0ac8:c001 Sony embedded vimicro
vc032x 0ac8:c002 Sony embedded vimicro vc032x 0ac8:c002 Sony embedded vimicro
vc032x 0ac8:c301 Samsung Q1 Ultra Premium
spca508 0af9:0010 Hama USB Sightcam 100 spca508 0af9:0010 Hama USB Sightcam 100
spca508 0af9:0011 Hama USB Sightcam 100 spca508 0af9:0011 Hama USB Sightcam 100
sonixb 0c45:6001 Genius VideoCAM NB sonixb 0c45:6001 Genius VideoCAM NB
@ -284,6 +289,7 @@ sonixj 0c45:613a Microdia Sonix PC Camera
sonixj 0c45:613b Surfer SN-206 sonixj 0c45:613b Surfer SN-206
sonixj 0c45:613c Sonix Pccam168 sonixj 0c45:613c Sonix Pccam168
sonixj 0c45:6143 Sonix Pccam168 sonixj 0c45:6143 Sonix Pccam168
sonixj 0c45:6148 Digitus DA-70811/ZSMC USB PC Camera ZS211/Microdia
sn9c20x 0c45:6240 PC Camera (SN9C201 + MT9M001) sn9c20x 0c45:6240 PC Camera (SN9C201 + MT9M001)
sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111) sn9c20x 0c45:6242 PC Camera (SN9C201 + MT9M111)
sn9c20x 0c45:6248 PC Camera (SN9C201 + OV9655) sn9c20x 0c45:6248 PC Camera (SN9C201 + OV9655)

View file

@ -0,0 +1,176 @@
Driver for I2C radios for the Silicon Labs Si4713 FM Radio Transmitters
Copyright (c) 2009 Nokia Corporation
Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
Information about the Device
============================
This chip is a Silicon Labs product. It is a I2C device, currently on 0x63 address.
Basically, it has transmission and signal noise level measurement features.
The Si4713 integrates transmit functions for FM broadcast stereo transmission.
The chip also allows integrated receive power scanning to identify low signal
power FM channels.
The chip is programmed using commands and responses. There are also several
properties which can change the behavior of this chip.
Users must comply with local regulations on radio frequency (RF) transmission.
Device driver description
=========================
There are two modules to handle this device. One is a I2C device driver
and the other is a platform driver.
The I2C device driver exports a v4l2-subdev interface to the kernel.
All properties can also be accessed by v4l2 extended controls interface, by
using the v4l2-subdev calls (g_ext_ctrls, s_ext_ctrls).
The platform device driver exports a v4l2 radio device interface to user land.
So, it uses the I2C device driver as a sub device in order to send the user
commands to the actual device. Basically it is a wrapper to the I2C device driver.
Applications can use v4l2 radio API to specify frequency of operation, mute state,
etc. But mostly of its properties will be present in the extended controls.
When the v4l2 mute property is set to 1 (true), the driver will turn the chip off.
Properties description
======================
The properties can be accessed using v4l2 extended controls.
Here is an output from v4l2-ctl util:
/ # v4l2-ctl -d /dev/radio0 --all -L
Driver Info:
Driver name : radio-si4713
Card type : Silicon Labs Si4713 Modulator
Bus info :
Driver version: 0
Capabilities : 0x00080800
RDS Output
Modulator
Audio output: 0 (FM Modulator Audio Out)
Frequency: 1408000 (88.000000 MHz)
Video Standard = 0x00000000
Modulator:
Name : FM Modulator
Capabilities : 62.5 Hz stereo rds
Frequency range : 76.0 MHz - 108.0 MHz
Subchannel modulation: stereo+rds
User Controls
mute (bool) : default=1 value=0
FM Radio Modulator Controls
rds_signal_deviation (int) : min=0 max=90000 step=10 default=200 value=200 flags=slider
rds_program_id (int) : min=0 max=65535 step=1 default=0 value=0
rds_program_type (int) : min=0 max=31 step=1 default=0 value=0
rds_ps_name (str) : min=0 max=96 step=8 value='si4713 '
rds_radio_text (str) : min=0 max=384 step=32 value=''
audio_limiter_feature_enabled (bool) : default=1 value=1
audio_limiter_release_time (int) : min=250 max=102390 step=50 default=5010 value=5010 flags=slider
audio_limiter_deviation (int) : min=0 max=90000 step=10 default=66250 value=66250 flags=slider
audio_compression_feature_enabl (bool) : default=1 value=1
audio_compression_gain (int) : min=0 max=20 step=1 default=15 value=15 flags=slider
audio_compression_threshold (int) : min=-40 max=0 step=1 default=-40 value=-40 flags=slider
audio_compression_attack_time (int) : min=0 max=5000 step=500 default=0 value=0 flags=slider
audio_compression_release_time (int) : min=100000 max=1000000 step=100000 default=1000000 value=1000000 flags=slider
pilot_tone_feature_enabled (bool) : default=1 value=1
pilot_tone_deviation (int) : min=0 max=90000 step=10 default=6750 value=6750 flags=slider
pilot_tone_frequency (int) : min=0 max=19000 step=1 default=19000 value=19000 flags=slider
pre_emphasis_settings (menu) : min=0 max=2 default=1 value=1
tune_power_level (int) : min=0 max=120 step=1 default=88 value=88 flags=slider
tune_antenna_capacitor (int) : min=0 max=191 step=1 default=0 value=110 flags=slider
/ #
Here is a summary of them:
* Pilot is an audible tone sent by the device.
pilot_frequency - Configures the frequency of the stereo pilot tone.
pilot_deviation - Configures pilot tone frequency deviation level.
pilot_enabled - Enables or disables the pilot tone feature.
* The si4713 device is capable of applying audio compression to the transmitted signal.
acomp_enabled - Enables or disables the audio dynamic range control feature.
acomp_gain - Sets the gain for audio dynamic range control.
acomp_threshold - Sets the threshold level for audio dynamic range control.
acomp_attack_time - Sets the attack time for audio dynamic range control.
acomp_release_time - Sets the release time for audio dynamic range control.
* Limiter setups audio deviation limiter feature. Once a over deviation occurs,
it is possible to adjust the front-end gain of the audio input and always
prevent over deviation.
limiter_enabled - Enables or disables the limiter feature.
limiter_deviation - Configures audio frequency deviation level.
limiter_release_time - Sets the limiter release time.
* Tuning power
power_level - Sets the output power level for signal transmission.
antenna_capacitor - This selects the value of antenna tuning capacitor manually
or automatically if set to zero.
* RDS related
rds_ps_name - Sets the RDS ps name field for transmission.
rds_radio_text - Sets the RDS radio text for transmission.
rds_pi - Sets the RDS PI field for transmission.
rds_pty - Sets the RDS PTY field for transmission.
* Region related
preemphasis - sets the preemphasis to be applied for transmission.
RNL
===
This device also has an interface to measure received noise level. To do that, you should
ioctl the device node. Here is an code of example:
int main (int argc, char *argv[])
{
struct si4713_rnl rnl;
int fd = open("/dev/radio0", O_RDWR);
int rval;
if (argc < 2)
return -EINVAL;
if (fd < 0)
return fd;
sscanf(argv[1], "%d", &rnl.frequency);
rval = ioctl(fd, SI4713_IOC_MEASURE_RNL, &rnl);
if (rval < 0)
return rval;
printf("received noise level: %d\n", rnl.rnl);
close(fd);
}
The struct si4713_rnl and SI4713_IOC_MEASURE_RNL are defined under
include/media/si4713.h.
Stereo/Mono and RDS subchannels
===============================
The device can also be configured using the available sub channels for
transmission. To do that use S/G_MODULATOR ioctl and configure txsubchans properly.
Refer to v4l2-spec for proper use of this ioctl.
Testing
=======
Testing is usually done with v4l2-ctl utility for managing FM tuner cards.
The tool can be found in v4l-dvb repository under v4l2-apps/util directory.
Example for setting rds ps name:
# v4l2-ctl -d /dev/radio0 --set-ctrl=rds_ps_name="Dummy"

View file

@ -58,13 +58,24 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
int ir_type, IR_KEYTAB_TYPE *ir_codes) int ir_type, struct ir_scancode_table *ir_codes)
{ {
int i; int i;
ir->ir_type = ir_type; ir->ir_type = ir_type;
memset(ir->ir_codes, sizeof(ir->ir_codes), 0);
/*
* FIXME: This is a temporary workaround to use the new IR tables
* with the old approach. Later patches will replace this to a
* proper method
*/
if (ir_codes) if (ir_codes)
memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes)); for (i = 0; i < ir_codes->size; i++)
if (ir_codes->scan[i].scancode < IR_KEYTAB_SIZE)
ir->ir_codes[ir_codes->scan[i].scancode] = ir_codes->scan[i].keycode;
dev->keycode = ir->ir_codes; dev->keycode = ir->ir_codes;
dev->keycodesize = sizeof(IR_KEYTAB_TYPE); dev->keycodesize = sizeof(IR_KEYTAB_TYPE);

File diff suppressed because it is too large Load diff

View file

@ -27,7 +27,7 @@ module_param_named(debug, tda18271_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debug level " MODULE_PARM_DESC(debug, "set debug level "
"(info=1, map=2, reg=4, adv=8, cal=16 (or-able))"); "(info=1, map=2, reg=4, adv=8, cal=16 (or-able))");
static int tda18271_cal_on_startup; static int tda18271_cal_on_startup = -1;
module_param_named(cal, tda18271_cal_on_startup, int, 0644); module_param_named(cal, tda18271_cal_on_startup, int, 0644);
MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup"); MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup");
@ -1192,10 +1192,25 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
case 0: case 0:
goto fail; goto fail;
case 1: case 1:
{
/* new tuner instance */ /* new tuner instance */
int rf_cal_on_startup;
priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
priv->role = (cfg) ? cfg->role : TDA18271_MASTER; priv->role = (cfg) ? cfg->role : TDA18271_MASTER;
priv->config = (cfg) ? cfg->config : 0; priv->config = (cfg) ? cfg->config : 0;
/* tda18271_cal_on_startup == -1 when cal
* module option is unset */
if (tda18271_cal_on_startup == -1) {
/* honor attach-time configuration */
rf_cal_on_startup =
((cfg) && (cfg->rf_cal_on_startup)) ? 1 : 0;
} else {
/* module option overrides attach configuration */
rf_cal_on_startup = tda18271_cal_on_startup;
}
priv->cal_initialized = false; priv->cal_initialized = false;
mutex_init(&priv->lock); mutex_init(&priv->lock);
@ -1213,11 +1228,12 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
mutex_lock(&priv->lock); mutex_lock(&priv->lock);
tda18271_init_regs(fe); tda18271_init_regs(fe);
if ((tda18271_cal_on_startup) && (priv->id == TDA18271HDC2)) if ((rf_cal_on_startup) && (priv->id == TDA18271HDC2))
tda18271c2_rf_cal_init(fe); tda18271c2_rf_cal_init(fe);
mutex_unlock(&priv->lock); mutex_unlock(&priv->lock);
break; break;
}
default: default:
/* existing tuner instance */ /* existing tuner instance */
fe->tuner_priv = priv; fe->tuner_priv = priv;

View file

@ -137,17 +137,17 @@ extern int tda18271_debug;
#define tda_printk(kern, fmt, arg...) \ #define tda_printk(kern, fmt, arg...) \
printk(kern "%s: " fmt, __func__, ##arg) printk(kern "%s: " fmt, __func__, ##arg)
#define dprintk(kern, lvl, fmt, arg...) do {\ #define tda_dprintk(lvl, fmt, arg...) do {\
if (tda18271_debug & lvl) \ if (tda18271_debug & lvl) \
tda_printk(kern, fmt, ##arg); } while (0) tda_printk(KERN_DEBUG, fmt, ##arg); } while (0)
#define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg) #define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
#define tda_warn(fmt, arg...) tda_printk(KERN_WARNING, fmt, ##arg) #define tda_warn(fmt, arg...) tda_printk(KERN_WARNING, fmt, ##arg)
#define tda_err(fmt, arg...) tda_printk(KERN_ERR, fmt, ##arg) #define tda_err(fmt, arg...) tda_printk(KERN_ERR, fmt, ##arg)
#define tda_dbg(fmt, arg...) dprintk(KERN_DEBUG, DBG_INFO, fmt, ##arg) #define tda_dbg(fmt, arg...) tda_dprintk(DBG_INFO, fmt, ##arg)
#define tda_map(fmt, arg...) dprintk(KERN_DEBUG, DBG_MAP, fmt, ##arg) #define tda_map(fmt, arg...) tda_dprintk(DBG_MAP, fmt, ##arg)
#define tda_reg(fmt, arg...) dprintk(KERN_DEBUG, DBG_REG, fmt, ##arg) #define tda_reg(fmt, arg...) tda_dprintk(DBG_REG, fmt, ##arg)
#define tda_cal(fmt, arg...) dprintk(KERN_DEBUG, DBG_CAL, fmt, ##arg) #define tda_cal(fmt, arg...) tda_dprintk(DBG_CAL, fmt, ##arg)
#define tda_fail(ret) \ #define tda_fail(ret) \
({ \ ({ \

View file

@ -77,6 +77,9 @@ struct tda18271_config {
/* use i2c gate provided by analog or digital demod */ /* use i2c gate provided by analog or digital demod */
enum tda18271_i2c_gate gate; enum tda18271_i2c_gate gate;
/* force rf tracking filter calibration on startup */
unsigned int rf_cal_on_startup:1;
/* some i2c providers cant write all 39 registers at once */ /* some i2c providers cant write all 39 registers at once */
unsigned int small_i2c:1; unsigned int small_i2c:1;

View file

@ -144,6 +144,8 @@ static inline int tuner_stereo(const int type, const int status)
case TUNER_LG_NTSC_TAPE: case TUNER_LG_NTSC_TAPE:
case TUNER_TCL_MF02GIP_5N: case TUNER_TCL_MF02GIP_5N:
return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
case TUNER_PHILIPS_FM1216MK5:
return status | TUNER_STEREO;
default: default:
return status & TUNER_STEREO; return status & TUNER_STEREO;
} }
@ -508,6 +510,10 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
case TUNER_TCL_MF02GIP_5N: case TUNER_TCL_MF02GIP_5N:
buffer[3] = 0x19; buffer[3] = 0x19;
break; break;
case TUNER_PHILIPS_FM1216MK5:
buffer[2] = 0x88;
buffer[3] = 0x09;
break;
case TUNER_TNF_5335MF: case TUNER_TNF_5335MF:
buffer[3] = 0x11; buffer[3] = 0x11;
break; break;

View file

@ -1301,6 +1301,25 @@ static struct tuner_params tuner_fq1216lme_mk3_params[] = {
}, },
}; };
/* ----- TUNER_PARTSNIC_PTI_5NF05 - Partsnic (Daewoo) PTI-5NF05 NTSC ----- */
static struct tuner_range tuner_partsnic_pti_5nf05_ranges[] = {
/* The datasheet specified channel ranges and the bandswitch byte */
/* The control byte value of 0x8e is just a guess */
{ 16 * 133.25 /*MHz*/, 0x8e, 0x01, }, /* Channels 2 - B */
{ 16 * 367.25 /*MHz*/, 0x8e, 0x02, }, /* Channels C - W+11 */
{ 16 * 999.99 , 0x8e, 0x08, }, /* Channels W+12 - 69 */
};
static struct tuner_params tuner_partsnic_pti_5nf05_params[] = {
{
.type = TUNER_PARAM_TYPE_NTSC,
.ranges = tuner_partsnic_pti_5nf05_ranges,
.count = ARRAY_SIZE(tuner_partsnic_pti_5nf05_ranges),
.cb_first_if_lower_freq = 1, /* not specified but safe to do */
},
};
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
struct tunertype tuners[] = { struct tunertype tuners[] = {
@ -1753,6 +1772,12 @@ struct tunertype tuners[] = {
.params = tuner_fq1216lme_mk3_params, .params = tuner_fq1216lme_mk3_params,
.count = ARRAY_SIZE(tuner_fq1216lme_mk3_params), .count = ARRAY_SIZE(tuner_fq1216lme_mk3_params),
}, },
[TUNER_PARTSNIC_PTI_5NF05] = {
.name = "Partsnic (Daewoo) PTI-5NF05",
.params = tuner_partsnic_pti_5nf05_params,
.count = ARRAY_SIZE(tuner_partsnic_pti_5nf05_params),
},
}; };
EXPORT_SYMBOL(tuners); EXPORT_SYMBOL(tuners);

View file

@ -2,6 +2,19 @@
# DVB device configuration # DVB device configuration
# #
config DVB_MAX_ADAPTERS
int "maximum number of DVB/ATSC adapters"
depends on DVB_CORE
default 8
range 1 255
help
Maximum number of DVB/ATSC adapters. Increasing this number
increases the memory consumption of the DVB subsystem even
if a much lower number of DVB/ATSC adapters is present.
Only values in the range 4-32 are tested.
If you are unsure about this, use the default value 8
config DVB_DYNAMIC_MINORS config DVB_DYNAMIC_MINORS
bool "Dynamic DVB minor allocation" bool "Dynamic DVB minor allocation"
depends on DVB_CORE depends on DVB_CORE

View file

@ -66,7 +66,7 @@ static int flexcop_sleep(struct dvb_frontend* fe)
#endif #endif
/* SkyStar2 DVB-S rev 2.3 */ /* SkyStar2 DVB-S rev 2.3 */
#if FE_SUPPORTED(MT312) #if FE_SUPPORTED(MT312) && FE_SUPPORTED(PLL)
static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
{ {
/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */ /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
@ -155,55 +155,34 @@ static struct mt312_config skystar23_samsung_tbdu18132_config = {
.demod_address = 0x0e, .demod_address = 0x0e,
}; };
static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
u8 buf[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf,
.len = sizeof(buf) };
struct flexcop_device *fc = fe->dvb->priv;
div = (params->frequency + (125/2)) / 125;
buf[0] = (div >> 8) & 0x7f;
buf[1] = (div >> 0) & 0xff;
buf[2] = 0x84 | ((div >> 10) & 0x60);
buf[3] = 0x80;
if (params->frequency < 1550000)
buf[3] |= 0x02;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static int skystar2_rev23_attach(struct flexcop_device *fc, static int skystar2_rev23_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c) struct i2c_adapter *i2c)
{ {
struct dvb_frontend_ops *ops;
fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c); fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c);
if (fc->fe != NULL) { if (!fc->fe)
struct dvb_frontend_ops *ops = &fc->fe->ops; return 0;
ops->tuner_ops.set_params =
skystar23_samsung_tbdu18132_tuner_set_params; if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c,
ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; DVB_PLL_SAMSUNG_TBDU18132))
ops->diseqc_send_burst = flexcop_diseqc_send_burst; return 0;
ops->set_tone = flexcop_set_tone;
ops->set_voltage = flexcop_set_voltage; ops = &fc->fe->ops;
fc->fe_sleep = ops->sleep; ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
ops->sleep = flexcop_sleep; ops->diseqc_send_burst = flexcop_diseqc_send_burst;
return 1; ops->set_tone = flexcop_set_tone;
} ops->set_voltage = flexcop_set_voltage;
return 0; fc->fe_sleep = ops->sleep;
ops->sleep = flexcop_sleep;
return 1;
} }
#else #else
#define skystar2_rev23_attach NULL #define skystar2_rev23_attach NULL
#endif #endif
/* SkyStar2 DVB-S rev 2.6 */ /* SkyStar2 DVB-S rev 2.6 */
#if FE_SUPPORTED(STV0299) #if FE_SUPPORTED(STV0299) && FE_SUPPORTED(PLL)
static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe, static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
u32 srate, u32 ratio) u32 srate, u32 ratio)
{ {
@ -232,31 +211,6 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
return 0; return 0;
} }
static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
u8 buf[4];
u32 div;
struct i2c_msg msg = {
.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
struct flexcop_device *fc = fe->dvb->priv;
div = params->frequency / 125;
buf[0] = (div >> 8) & 0x7f;
buf[1] = div & 0xff;
buf[2] = 0x84; /* 0xC4 */
buf[3] = 0x08;
if (params->frequency < 1500000)
buf[3] |= 0x10;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&fc->fc_i2c_adap[0].i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
static u8 samsung_tbmu24112_inittab[] = { static u8 samsung_tbmu24112_inittab[] = {
0x01, 0x15, 0x01, 0x15,
0x02, 0x30, 0x02, 0x30,
@ -318,15 +272,18 @@ static int skystar2_rev26_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c) struct i2c_adapter *i2c)
{ {
fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c); fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
if (fc->fe != NULL) { if (!fc->fe)
struct dvb_frontend_ops *ops = &fc->fe->ops; return 0;
ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
ops->set_voltage = flexcop_set_voltage; if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c,
fc->fe_sleep = ops->sleep; DVB_PLL_SAMSUNG_TBMU24112))
ops->sleep = flexcop_sleep; return 0;
return 1;
} fc->fe->ops.set_voltage = flexcop_set_voltage;
return 0; fc->fe_sleep = fc->fe->ops.sleep;
fc->fe->ops.sleep = flexcop_sleep;
return 1;
} }
#else #else
#define skystar2_rev26_attach NULL #define skystar2_rev26_attach NULL
@ -421,7 +378,7 @@ static int skystar2_rev28_attach(struct flexcop_device *fc,
if (!fc->fe) if (!fc->fe)
return 0; return 0;
i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);; i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
if (!i2c_tuner) if (!i2c_tuner)
return 0; return 0;
@ -449,7 +406,7 @@ static int skystar2_rev28_attach(struct flexcop_device *fc,
#endif #endif
/* AirStar DVB-T */ /* AirStar DVB-T */
#if FE_SUPPORTED(MT352) #if FE_SUPPORTED(MT352) && FE_SUPPORTED(PLL)
static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe) static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
{ {
static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d }; static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
@ -467,32 +424,6 @@ static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
return 0; return 0;
} }
static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
{
u32 div;
unsigned char bs = 0;
if (buf_len < 5)
return -EINVAL;
#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
if (params->frequency >= 48000000 && params->frequency <= 154000000) \
bs = 0x09;
if (params->frequency >= 161000000 && params->frequency <= 439000000) \
bs = 0x0a;
if (params->frequency >= 447000000 && params->frequency <= 863000000) \
bs = 0x08;
pllbuf[0] = 0x61;
pllbuf[1] = div >> 8;
pllbuf[2] = div & 0xff;
pllbuf[3] = 0xcc;
pllbuf[4] = bs;
return 5;
}
static struct mt352_config samsung_tdtc9251dh0_config = { static struct mt352_config samsung_tdtc9251dh0_config = {
.demod_address = 0x0f, .demod_address = 0x0f,
.demod_init = samsung_tdtc9251dh0_demod_init, .demod_init = samsung_tdtc9251dh0_demod_init,
@ -502,11 +433,11 @@ static int airstar_dvbt_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c) struct i2c_adapter *i2c)
{ {
fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
if (fc->fe != NULL) { if (!fc->fe)
fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; return 0;
return 1;
} return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
return 0; DVB_PLL_SAMSUNG_TDTC9251DH0);
} }
#else #else
#define airstar_dvbt_attach NULL #define airstar_dvbt_attach NULL
@ -580,54 +511,7 @@ static int airstar_atsc3_attach(struct flexcop_device *fc,
#endif #endif
/* CableStar2 DVB-C */ /* CableStar2 DVB-C */
#if FE_SUPPORTED(STV0297) #if FE_SUPPORTED(STV0297) && FE_SUPPORTED(PLL)
static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct flexcop_device *fc = fe->dvb->priv;
u8 buf[4];
u16 div;
int ret;
/* 62.5 kHz * 10 */
#define REF_FREQ 625
#define FREQ_OFFSET 36125
div = ((fep->frequency/1000 + FREQ_OFFSET) * 10) / REF_FREQ;
/* 4 MHz = 4000 KHz */
buf[0] = (u8)( div >> 8) & 0x7f;
buf[1] = (u8) div & 0xff;
/* F(osc) = N * Reference Freq. (62.5 kHz)
* byte 2 : 0 N14 N13 N12 N11 N10 N9 N8
* byte 3 : N7 N6 N5 N4 N3 N2 N1 N0
* byte 4 : 1 * * AGD R3 R2 R1 R0
* byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1
* AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
buf[2] = 0x95;
/* Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5
* 47 - 153 0 * 0 0 0 0 0 1 0x01
* 153 - 430 0 * 0 0 0 0 1 0 0x02
* 430 - 822 0 * 0 0 1 0 0 0 0x08
* 822 - 862 1 * 0 0 1 0 0 0 0x88 */
if (fep->frequency <= 153000000) buf[3] = 0x01;
else if (fep->frequency <= 430000000) buf[3] = 0x02;
else if (fep->frequency <= 822000000) buf[3] = 0x08;
else buf[3] = 0x88;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n", fep->frequency,
buf[0], buf[1], buf[2], buf[3]);
ret = fc->i2c_request(&fc->fc_i2c_adap[2],
FC_WRITE, 0x61, buf[0], &buf[1], 3);
deb_tuner("tuner write returned: %d\n",ret);
return ret;
}
static u8 alps_tdee4_stv0297_inittab[] = { static u8 alps_tdee4_stv0297_inittab[] = {
0x80, 0x01, 0x80, 0x01,
0x80, 0x00, 0x80, 0x00,
@ -711,13 +595,25 @@ static int cablestar2_attach(struct flexcop_device *fc,
{ {
fc->fc_i2c_adap[0].no_base_addr = 1; fc->fc_i2c_adap[0].no_base_addr = 1;
fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
if (!fc->fe) { if (!fc->fe)
/* Reset for next frontend to try */ goto fail;
fc->fc_i2c_adap[0].no_base_addr = 0;
return 0; /* This tuner doesn't use the stv0297's I2C gate, but instead the
} * tuner is connected to a different flexcop I2C adapter. */
fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; if (fc->fe->ops.i2c_gate_ctrl)
fc->fe->ops.i2c_gate_ctrl(fc->fe, 0);
fc->fe->ops.i2c_gate_ctrl = NULL;
if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61,
&fc->fc_i2c_adap[2].i2c_adap, DVB_PLL_TDEE4))
goto fail;
return 1; return 1;
fail:
/* Reset for next frontend to try */
fc->fc_i2c_adap[0].no_base_addr = 0;
return 0;
} }
#else #else
#define cablestar2_attach NULL #define cablestar2_attach NULL

View file

@ -1059,7 +1059,7 @@ static int dst_get_tuner_info(struct dst_state *state)
dprintk(verbose, DST_ERROR, 1, "DST type has TS=188"); dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
} }
if (state->board_info[0] == 0xbc) { if (state->board_info[0] == 0xbc) {
if (state->type_flags != DST_TYPE_IS_ATSC) if (state->dst_type != DST_TYPE_IS_ATSC)
state->type_flags |= DST_TYPE_HAS_TS188; state->type_flags |= DST_TYPE_HAS_TS188;
else else
state->type_flags |= DST_TYPE_HAS_NEWTUNE_2; state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;

View file

@ -44,6 +44,14 @@
#include "cx24116.h" #include "cx24116.h"
#include "z0194a.h" #include "z0194a.h"
#define UNSET (-1U)
#define DM1105_BOARD_NOAUTO UNSET
#define DM1105_BOARD_UNKNOWN 0
#define DM1105_BOARD_DVBWORLD_2002 1
#define DM1105_BOARD_DVBWORLD_2004 2
#define DM1105_BOARD_AXESS_DM05 3
/* ----------------------------------------------- */ /* ----------------------------------------------- */
/* /*
* PCI ID's * PCI ID's
@ -153,20 +161,105 @@
/* GPIO's for LNB power control */ /* GPIO's for LNB power control */
#define DM1105_LNB_MASK 0x00000000 #define DM1105_LNB_MASK 0x00000000
#define DM1105_LNB_OFF 0x00020000
#define DM1105_LNB_13V 0x00010100 #define DM1105_LNB_13V 0x00010100
#define DM1105_LNB_18V 0x00000100 #define DM1105_LNB_18V 0x00000100
/* GPIO's for LNB power control for Axess DM05 */ /* GPIO's for LNB power control for Axess DM05 */
#define DM05_LNB_MASK 0x00000000 #define DM05_LNB_MASK 0x00000000
#define DM05_LNB_OFF 0x00020000/* actually 13v */
#define DM05_LNB_13V 0x00020000 #define DM05_LNB_13V 0x00020000
#define DM05_LNB_18V 0x00030000 #define DM05_LNB_18V 0x00030000
static unsigned int card[] = {[0 ... 3] = UNSET };
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(card, "card type");
static int ir_debug; static int ir_debug;
module_param(ir_debug, int, 0644); module_param(ir_debug, int, 0644);
MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
static unsigned int dm1105_devcount;
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
struct dm1105_board {
char *name;
};
struct dm1105_subid {
u16 subvendor;
u16 subdevice;
u32 card;
};
static const struct dm1105_board dm1105_boards[] = {
[DM1105_BOARD_UNKNOWN] = {
.name = "UNKNOWN/GENERIC",
},
[DM1105_BOARD_DVBWORLD_2002] = {
.name = "DVBWorld PCI 2002",
},
[DM1105_BOARD_DVBWORLD_2004] = {
.name = "DVBWorld PCI 2004",
},
[DM1105_BOARD_AXESS_DM05] = {
.name = "Axess/EasyTv DM05",
},
};
static const struct dm1105_subid dm1105_subids[] = {
{
.subvendor = 0x0000,
.subdevice = 0x2002,
.card = DM1105_BOARD_DVBWORLD_2002,
}, {
.subvendor = 0x0001,
.subdevice = 0x2002,
.card = DM1105_BOARD_DVBWORLD_2002,
}, {
.subvendor = 0x0000,
.subdevice = 0x2004,
.card = DM1105_BOARD_DVBWORLD_2004,
}, {
.subvendor = 0x0001,
.subdevice = 0x2004,
.card = DM1105_BOARD_DVBWORLD_2004,
}, {
.subvendor = 0x195d,
.subdevice = 0x1105,
.card = DM1105_BOARD_AXESS_DM05,
},
};
static void dm1105_card_list(struct pci_dev *pci)
{
int i;
if (0 == pci->subsystem_vendor &&
0 == pci->subsystem_device) {
printk(KERN_ERR
"dm1105: Your board has no valid PCI Subsystem ID\n"
"dm1105: and thus can't be autodetected\n"
"dm1105: Please pass card=<n> insmod option to\n"
"dm1105: workaround that. Redirect complaints to\n"
"dm1105: the vendor of the TV card. Best regards,\n"
"dm1105: -- tux\n");
} else {
printk(KERN_ERR
"dm1105: Your board isn't known (yet) to the driver.\n"
"dm1105: You can try to pick one of the existing\n"
"dm1105: card configs via card=<n> insmod option.\n"
"dm1105: Updating to the latest version might help\n"
"dm1105: as well.\n");
}
printk(KERN_ERR "Here is a list of valid choices for the card=<n> "
"insmod option:\n");
for (i = 0; i < ARRAY_SIZE(dm1105_boards); i++)
printk(KERN_ERR "dm1105: card=%d -> %s\n",
i, dm1105_boards[i].name);
}
/* infrared remote control */ /* infrared remote control */
struct infrared { struct infrared {
struct input_dev *input_dev; struct input_dev *input_dev;
@ -193,6 +286,8 @@ struct dm1105dvb {
struct dvb_frontend *fe; struct dvb_frontend *fe;
struct dvb_net dvbnet; struct dvb_net dvbnet;
unsigned int full_ts_users; unsigned int full_ts_users;
unsigned int boardnr;
int nr;
/* i2c */ /* i2c */
struct i2c_adapter i2c_adap; struct i2c_adapter i2c_adap;
@ -211,7 +306,6 @@ struct dm1105dvb {
unsigned int PacketErrorCount; unsigned int PacketErrorCount;
unsigned int dmarst; unsigned int dmarst;
spinlock_t lock; spinlock_t lock;
}; };
#define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg])) #define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg]))
@ -326,16 +420,20 @@ static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe)
static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{ {
struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe); struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe);
u32 lnb_mask, lnb_13v, lnb_18v; u32 lnb_mask, lnb_13v, lnb_18v, lnb_off;
switch (dm1105dvb->pdev->subsystem_device) { switch (dm1105dvb->boardnr) {
case PCI_DEVICE_ID_DM05: case DM1105_BOARD_AXESS_DM05:
lnb_mask = DM05_LNB_MASK; lnb_mask = DM05_LNB_MASK;
lnb_off = DM05_LNB_OFF;
lnb_13v = DM05_LNB_13V; lnb_13v = DM05_LNB_13V;
lnb_18v = DM05_LNB_18V; lnb_18v = DM05_LNB_18V;
break; break;
case DM1105_BOARD_DVBWORLD_2002:
case DM1105_BOARD_DVBWORLD_2004:
default: default:
lnb_mask = DM1105_LNB_MASK; lnb_mask = DM1105_LNB_MASK;
lnb_off = DM1105_LNB_OFF;
lnb_13v = DM1105_LNB_13V; lnb_13v = DM1105_LNB_13V;
lnb_18v = DM1105_LNB_18V; lnb_18v = DM1105_LNB_18V;
} }
@ -343,8 +441,10 @@ static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volta
outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR)); outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR));
if (voltage == SEC_VOLTAGE_18) if (voltage == SEC_VOLTAGE_18)
outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL)); outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL));
else else if (voltage == SEC_VOLTAGE_13)
outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL)); outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL));
else
outl(lnb_off, dm_io_mem(DM1105_GPIOVAL));
return 0; return 0;
} }
@ -477,7 +577,7 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
{ {
struct input_dev *input_dev; struct input_dev *input_dev;
IR_KEYTAB_TYPE *ir_codes = ir_codes_dm1105_nec; struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table;
int ir_type = IR_TYPE_OTHER; int ir_type = IR_TYPE_OTHER;
int err = -ENOMEM; int err = -ENOMEM;
@ -589,8 +689,8 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb)
{ {
int ret; int ret;
switch (dm1105dvb->pdev->subsystem_device) { switch (dm1105dvb->boardnr) {
case PCI_DEVICE_ID_DW2004: case DM1105_BOARD_DVBWORLD_2004:
dm1105dvb->fe = dvb_attach( dm1105dvb->fe = dvb_attach(
cx24116_attach, &serit_sp2633_config, cx24116_attach, &serit_sp2633_config,
&dm1105dvb->i2c_adap); &dm1105dvb->i2c_adap);
@ -598,6 +698,8 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb)
dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
break; break;
case DM1105_BOARD_DVBWORLD_2002:
case DM1105_BOARD_AXESS_DM05:
default: default:
dm1105dvb->fe = dvb_attach( dm1105dvb->fe = dvb_attach(
stv0299_attach, &sharp_z0194a_config, stv0299_attach, &sharp_z0194a_config,
@ -676,11 +778,31 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
struct dvb_demux *dvbdemux; struct dvb_demux *dvbdemux;
struct dmx_demux *dmx; struct dmx_demux *dmx;
int ret = -ENOMEM; int ret = -ENOMEM;
int i;
dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL); dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
if (!dm1105dvb) if (!dm1105dvb)
return -ENOMEM; return -ENOMEM;
/* board config */
dm1105dvb->nr = dm1105_devcount;
dm1105dvb->boardnr = UNSET;
if (card[dm1105dvb->nr] < ARRAY_SIZE(dm1105_boards))
dm1105dvb->boardnr = card[dm1105dvb->nr];
for (i = 0; UNSET == dm1105dvb->boardnr &&
i < ARRAY_SIZE(dm1105_subids); i++)
if (pdev->subsystem_vendor ==
dm1105_subids[i].subvendor &&
pdev->subsystem_device ==
dm1105_subids[i].subdevice)
dm1105dvb->boardnr = dm1105_subids[i].card;
if (UNSET == dm1105dvb->boardnr) {
dm1105dvb->boardnr = DM1105_BOARD_UNKNOWN;
dm1105_card_list(pdev);
}
dm1105_devcount++;
dm1105dvb->pdev = pdev; dm1105dvb->pdev = pdev;
dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES; dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
dm1105dvb->PacketErrorCount = 0; dm1105dvb->PacketErrorCount = 0;
@ -853,6 +975,7 @@ static void __devexit dm1105_remove(struct pci_dev *pdev)
pci_release_regions(pdev); pci_release_regions(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
dm1105_devcount--;
kfree(dm1105dvb); kfree(dm1105dvb);
} }
@ -861,17 +984,12 @@ static struct pci_device_id dm1105_id_table[] __devinitdata = {
.vendor = PCI_VENDOR_ID_TRIGEM, .vendor = PCI_VENDOR_ID_TRIGEM,
.device = PCI_DEVICE_ID_DM1105, .device = PCI_DEVICE_ID_DM1105,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_DEVICE_ID_DW2002, .subdevice = PCI_ANY_ID,
}, {
.vendor = PCI_VENDOR_ID_TRIGEM,
.device = PCI_DEVICE_ID_DM1105,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_DEVICE_ID_DW2004,
}, { }, {
.vendor = PCI_VENDOR_ID_AXESS, .vendor = PCI_VENDOR_ID_AXESS,
.device = PCI_DEVICE_ID_DM05, .device = PCI_DEVICE_ID_DM05,
.subvendor = PCI_VENDOR_ID_AXESS, .subvendor = PCI_ANY_ID,
.subdevice = PCI_DEVICE_ID_DM05, .subdevice = PCI_ANY_ID,
}, { }, {
/* empty */ /* empty */
}, },

View file

@ -430,6 +430,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
/* stop feed but only mark the specified filter as stopped (state set) */ /* stop feed but only mark the specified filter as stopped (state set) */
static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter)
{ {
struct dmxdev_feed *feed;
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
switch (dmxdevfilter->type) { switch (dmxdevfilter->type) {
@ -438,7 +440,8 @@ static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter)
dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec); dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec);
break; break;
case DMXDEV_TYPE_PES: case DMXDEV_TYPE_PES:
dmxdevfilter->feed.ts->stop_filtering(dmxdevfilter->feed.ts); list_for_each_entry(feed, &dmxdevfilter->feed.ts, next)
feed->ts->stop_filtering(feed->ts);
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -449,13 +452,23 @@ static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter)
/* start feed associated with the specified filter */ /* start feed associated with the specified filter */
static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter) static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter)
{ {
struct dmxdev_feed *feed;
int ret;
dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO); dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
switch (filter->type) { switch (filter->type) {
case DMXDEV_TYPE_SEC: case DMXDEV_TYPE_SEC:
return filter->feed.sec->start_filtering(filter->feed.sec); return filter->feed.sec->start_filtering(filter->feed.sec);
case DMXDEV_TYPE_PES: case DMXDEV_TYPE_PES:
return filter->feed.ts->start_filtering(filter->feed.ts); list_for_each_entry(feed, &filter->feed.ts, next) {
ret = feed->ts->start_filtering(feed->ts);
if (ret < 0) {
dvb_dmxdev_feed_stop(filter);
return ret;
}
}
break;
default: default:
return -EINVAL; return -EINVAL;
} }
@ -487,6 +500,9 @@ static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter)
static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
{ {
struct dmxdev_feed *feed;
struct dmx_demux *demux;
if (dmxdevfilter->state < DMXDEV_STATE_GO) if (dmxdevfilter->state < DMXDEV_STATE_GO)
return 0; return 0;
@ -503,13 +519,12 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
dmxdevfilter->feed.sec = NULL; dmxdevfilter->feed.sec = NULL;
break; break;
case DMXDEV_TYPE_PES: case DMXDEV_TYPE_PES:
if (!dmxdevfilter->feed.ts)
break;
dvb_dmxdev_feed_stop(dmxdevfilter); dvb_dmxdev_feed_stop(dmxdevfilter);
dmxdevfilter->dev->demux-> demux = dmxdevfilter->dev->demux;
release_ts_feed(dmxdevfilter->dev->demux, list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) {
dmxdevfilter->feed.ts); demux->release_ts_feed(demux, feed->ts);
dmxdevfilter->feed.ts = NULL; feed->ts = NULL;
}
break; break;
default: default:
if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED) if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED)
@ -521,19 +536,88 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
return 0; return 0;
} }
static void dvb_dmxdev_delete_pids(struct dmxdev_filter *dmxdevfilter)
{
struct dmxdev_feed *feed, *tmp;
/* delete all PIDs */
list_for_each_entry_safe(feed, tmp, &dmxdevfilter->feed.ts, next) {
list_del(&feed->next);
kfree(feed);
}
BUG_ON(!list_empty(&dmxdevfilter->feed.ts));
}
static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter) static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter)
{ {
if (dmxdevfilter->state < DMXDEV_STATE_SET) if (dmxdevfilter->state < DMXDEV_STATE_SET)
return 0; return 0;
if (dmxdevfilter->type == DMXDEV_TYPE_PES)
dvb_dmxdev_delete_pids(dmxdevfilter);
dmxdevfilter->type = DMXDEV_TYPE_NONE; dmxdevfilter->type = DMXDEV_TYPE_NONE;
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
return 0; return 0;
} }
static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
struct dmxdev_filter *filter,
struct dmxdev_feed *feed)
{
struct timespec timeout = { 0 };
struct dmx_pes_filter_params *para = &filter->params.pes;
dmx_output_t otype;
int ret;
int ts_type;
enum dmx_ts_pes ts_pes;
struct dmx_ts_feed *tsfeed;
feed->ts = NULL;
otype = para->output;
ts_pes = (enum dmx_ts_pes)para->pes_type;
if (ts_pes < DMX_PES_OTHER)
ts_type = TS_DECODER;
else
ts_type = 0;
if (otype == DMX_OUT_TS_TAP)
ts_type |= TS_PACKET;
else if (otype == DMX_OUT_TSDEMUX_TAP)
ts_type |= TS_PACKET | TS_DEMUX;
else if (otype == DMX_OUT_TAP)
ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY;
ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, &feed->ts,
dvb_dmxdev_ts_callback);
if (ret < 0)
return ret;
tsfeed = feed->ts;
tsfeed->priv = filter;
ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, 32768, timeout);
if (ret < 0) {
dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
return ret;
}
ret = tsfeed->start_filtering(tsfeed);
if (ret < 0) {
dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
return ret;
}
return 0;
}
static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
{ {
struct dmxdev *dmxdev = filter->dev; struct dmxdev *dmxdev = filter->dev;
struct dmxdev_feed *feed;
void *mem; void *mem;
int ret, i; int ret, i;
@ -631,56 +715,14 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
break; break;
} }
case DMXDEV_TYPE_PES: case DMXDEV_TYPE_PES:
{ list_for_each_entry(feed, &filter->feed.ts, next) {
struct timespec timeout = { 0 }; ret = dvb_dmxdev_start_feed(dmxdev, filter, feed);
struct dmx_pes_filter_params *para = &filter->params.pes; if (ret < 0) {
dmx_output_t otype; dvb_dmxdev_filter_stop(filter);
int ts_type; return ret;
enum dmx_ts_pes ts_pes; }
struct dmx_ts_feed **tsfeed = &filter->feed.ts;
filter->feed.ts = NULL;
otype = para->output;
ts_pes = (enum dmx_ts_pes)para->pes_type;
if (ts_pes < DMX_PES_OTHER)
ts_type = TS_DECODER;
else
ts_type = 0;
if (otype == DMX_OUT_TS_TAP)
ts_type |= TS_PACKET;
else if (otype == DMX_OUT_TSDEMUX_TAP)
ts_type |= TS_PACKET | TS_DEMUX;
else if (otype == DMX_OUT_TAP)
ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY;
ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux,
tsfeed,
dvb_dmxdev_ts_callback);
if (ret < 0)
return ret;
(*tsfeed)->priv = filter;
ret = (*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes,
32768, timeout);
if (ret < 0) {
dmxdev->demux->release_ts_feed(dmxdev->demux,
*tsfeed);
return ret;
} }
ret = filter->feed.ts->start_filtering(filter->feed.ts);
if (ret < 0) {
dmxdev->demux->release_ts_feed(dmxdev->demux,
*tsfeed);
return ret;
}
break; break;
}
default: default:
return -EINVAL; return -EINVAL;
} }
@ -718,7 +760,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192); dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
dmxdevfilter->type = DMXDEV_TYPE_NONE; dmxdevfilter->type = DMXDEV_TYPE_NONE;
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
dmxdevfilter->feed.ts = NULL; INIT_LIST_HEAD(&dmxdevfilter->feed.ts);
init_timer(&dmxdevfilter->timer); init_timer(&dmxdevfilter->timer);
dvbdev->users++; dvbdev->users++;
@ -760,6 +802,55 @@ static inline void invert_mode(dmx_filter_t *filter)
filter->mode[i] ^= 0xff; filter->mode[i] ^= 0xff;
} }
static int dvb_dmxdev_add_pid(struct dmxdev *dmxdev,
struct dmxdev_filter *filter, u16 pid)
{
struct dmxdev_feed *feed;
if ((filter->type != DMXDEV_TYPE_PES) ||
(filter->state < DMXDEV_STATE_SET))
return -EINVAL;
/* only TS packet filters may have multiple PIDs */
if ((filter->params.pes.output != DMX_OUT_TSDEMUX_TAP) &&
(!list_empty(&filter->feed.ts)))
return -EINVAL;
feed = kzalloc(sizeof(struct dmxdev_feed), GFP_KERNEL);
if (feed == NULL)
return -ENOMEM;
feed->pid = pid;
list_add(&feed->next, &filter->feed.ts);
if (filter->state >= DMXDEV_STATE_GO)
return dvb_dmxdev_start_feed(dmxdev, filter, feed);
return 0;
}
static int dvb_dmxdev_remove_pid(struct dmxdev *dmxdev,
struct dmxdev_filter *filter, u16 pid)
{
struct dmxdev_feed *feed, *tmp;
if ((filter->type != DMXDEV_TYPE_PES) ||
(filter->state < DMXDEV_STATE_SET))
return -EINVAL;
list_for_each_entry_safe(feed, tmp, &filter->feed.ts, next) {
if ((feed->pid == pid) && (feed->ts != NULL)) {
feed->ts->stop_filtering(feed->ts);
filter->dev->demux->release_ts_feed(filter->dev->demux,
feed->ts);
list_del(&feed->next);
kfree(feed);
}
}
return 0;
}
static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
struct dmxdev_filter *dmxdevfilter, struct dmxdev_filter *dmxdevfilter,
struct dmx_sct_filter_params *params) struct dmx_sct_filter_params *params)
@ -784,7 +875,10 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
struct dmxdev_filter *dmxdevfilter, struct dmxdev_filter *dmxdevfilter,
struct dmx_pes_filter_params *params) struct dmx_pes_filter_params *params)
{ {
int ret;
dvb_dmxdev_filter_stop(dmxdevfilter); dvb_dmxdev_filter_stop(dmxdevfilter);
dvb_dmxdev_filter_reset(dmxdevfilter);
if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0) if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0)
return -EINVAL; return -EINVAL;
@ -795,6 +889,11 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter,
dmxdevfilter->params.pes.pid);
if (ret < 0)
return ret;
if (params->flags & DMX_IMMEDIATE_START) if (params->flags & DMX_IMMEDIATE_START)
return dvb_dmxdev_filter_start(dmxdevfilter); return dvb_dmxdev_filter_start(dmxdevfilter);
@ -958,6 +1057,24 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
&((struct dmx_stc *)parg)->base); &((struct dmx_stc *)parg)->base);
break; break;
case DMX_ADD_PID:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
ret = -ERESTARTSYS;
break;
}
ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, *(u16 *)parg);
mutex_unlock(&dmxdevfilter->mutex);
break;
case DMX_REMOVE_PID:
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
ret = -ERESTARTSYS;
break;
}
ret = dvb_dmxdev_remove_pid(dmxdev, dmxdevfilter, *(u16 *)parg);
mutex_unlock(&dmxdevfilter->mutex);
break;
default: default:
ret = -EINVAL; ret = -EINVAL;
break; break;

View file

@ -53,13 +53,20 @@ enum dmxdev_state {
DMXDEV_STATE_TIMEDOUT DMXDEV_STATE_TIMEDOUT
}; };
struct dmxdev_feed {
u16 pid;
struct dmx_ts_feed *ts;
struct list_head next;
};
struct dmxdev_filter { struct dmxdev_filter {
union { union {
struct dmx_section_filter *sec; struct dmx_section_filter *sec;
} filter; } filter;
union { union {
struct dmx_ts_feed *ts; /* list of TS and PES feeds (struct dmxdev_feed) */
struct list_head ts;
struct dmx_section_feed *sec; struct dmx_section_feed *sec;
} feed; } feed;

View file

@ -425,13 +425,9 @@ no_dvb_demux_tscheck:
if ((DVR_FEED(feed)) && (dvr_done++)) if ((DVR_FEED(feed)) && (dvr_done++))
continue; continue;
if (feed->pid == pid) { if (feed->pid == pid)
dvb_dmx_swfilter_packet_type(feed, buf); dvb_dmx_swfilter_packet_type(feed, buf);
if (DVR_FEED(feed)) else if (feed->pid == 0x2000)
continue;
}
if (feed->pid == 0x2000)
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK); feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
} }
} }

View file

@ -72,6 +72,7 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open(
#define FESTATE_ZIGZAG_FAST 32 #define FESTATE_ZIGZAG_FAST 32
#define FESTATE_ZIGZAG_SLOW 64 #define FESTATE_ZIGZAG_SLOW 64
#define FESTATE_DISEQC 128 #define FESTATE_DISEQC 128
#define FESTATE_ERROR 256
#define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC) #define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC)
#define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST) #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
#define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW) #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
@ -269,6 +270,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
{ {
int autoinversion; int autoinversion;
int ready = 0; int ready = 0;
int fe_set_err = 0;
struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_private *fepriv = fe->frontend_priv;
int original_inversion = fepriv->parameters.inversion; int original_inversion = fepriv->parameters.inversion;
u32 original_frequency = fepriv->parameters.frequency; u32 original_frequency = fepriv->parameters.frequency;
@ -345,7 +347,11 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
if (autoinversion) if (autoinversion)
fepriv->parameters.inversion = fepriv->inversion; fepriv->parameters.inversion = fepriv->inversion;
if (fe->ops.set_frontend) if (fe->ops.set_frontend)
fe->ops.set_frontend(fe, &fepriv->parameters); fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters);
if (fe_set_err < 0) {
fepriv->state = FESTATE_ERROR;
return fe_set_err;
}
fepriv->parameters.frequency = original_frequency; fepriv->parameters.frequency = original_frequency;
fepriv->parameters.inversion = original_inversion; fepriv->parameters.inversion = original_inversion;
@ -357,6 +363,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
static void dvb_frontend_swzigzag(struct dvb_frontend *fe) static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
{ {
fe_status_t s = 0; fe_status_t s = 0;
int retval = 0;
struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_private *fepriv = fe->frontend_priv;
/* if we've got no parameters, just keep idling */ /* if we've got no parameters, just keep idling */
@ -370,8 +377,12 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
if (fepriv->state & FESTATE_RETUNE) { if (fepriv->state & FESTATE_RETUNE) {
if (fe->ops.set_frontend) if (fe->ops.set_frontend)
fe->ops.set_frontend(fe, &fepriv->parameters); retval = fe->ops.set_frontend(fe,
fepriv->state = FESTATE_TUNED; &fepriv->parameters);
if (retval < 0)
fepriv->state = FESTATE_ERROR;
else
fepriv->state = FESTATE_TUNED;
} }
fepriv->delay = 3*HZ; fepriv->delay = 3*HZ;
fepriv->quality = 0; fepriv->quality = 0;
@ -449,7 +460,11 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
fepriv->delay = fepriv->min_delay; fepriv->delay = fepriv->min_delay;
/* peform a tune */ /* peform a tune */
if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) { retval = dvb_frontend_swzigzag_autotune(fe,
fepriv->check_wrapped);
if (retval < 0) {
return;
} else if (retval) {
/* OK, if we've run out of trials at the fast speed. /* OK, if we've run out of trials at the fast speed.
* Drop back to slow for the _next_ attempt */ * Drop back to slow for the _next_ attempt */
fepriv->state = FESTATE_SEARCHING_SLOW; fepriv->state = FESTATE_SEARCHING_SLOW;
@ -823,6 +838,15 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
} }
} }
/* check for supported modulation */
if (fe->ops.info.type == FE_QAM &&
(parms->u.qam.modulation > QAM_AUTO ||
!((1 << (parms->u.qam.modulation + 10)) & fe->ops.info.caps))) {
printk(KERN_WARNING "DVB: adapter %i frontend %i modulation %u not supported\n",
fe->dvb->num, fe->id, parms->u.qam.modulation);
return -EINVAL;
}
return 0; return 0;
} }
@ -1499,7 +1523,8 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
/* if retune was requested but hasn't occured yet, prevent /* if retune was requested but hasn't occured yet, prevent
* that user get signal state from previous tuning */ * that user get signal state from previous tuning */
if(fepriv->state == FESTATE_RETUNE) { if (fepriv->state == FESTATE_RETUNE ||
fepriv->state == FESTATE_ERROR) {
err=0; err=0;
*status = 0; *status = 0;
break; break;

View file

@ -30,7 +30,12 @@
#define DVB_MAJOR 212 #define DVB_MAJOR 212
#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0
#define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS
#else
#warning invalid CONFIG_DVB_MAX_ADAPTERS value
#define DVB_MAX_ADAPTERS 8 #define DVB_MAX_ADAPTERS 8
#endif
#define DVB_UNSET (-1) #define DVB_UNSET (-1)

View file

@ -253,7 +253,7 @@ config DVB_USB_AF9005_REMOTE
Afatech AF9005 based receiver. Afatech AF9005 based receiver.
config DVB_USB_DW2102 config DVB_USB_DW2102
tristate "DvbWorld DVB-S/S2 USB2.0 support" tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support"
depends on DVB_USB depends on DVB_USB
select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE
@ -262,9 +262,11 @@ config DVB_USB_DW2102
select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE
select DVB_SI21XX if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE
select DVB_TDA10021 if !DVB_FE_CUSTOMISE select DVB_TDA10021 if !DVB_FE_CUSTOMISE
select DVB_MT312 if !DVB_FE_CUSTOMISE
select DVB_ZL10039 if !DVB_FE_CUSTOMISE
help help
Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers
and the TeVii S650. and the TeVii S650, S630.
config DVB_USB_CINERGY_T2 config DVB_USB_CINERGY_T2
tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver"

View file

@ -38,41 +38,41 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr
} }
static struct dvb_usb_rc_key a800_rc_keys[] = { static struct dvb_usb_rc_key a800_rc_keys[] = {
{ 0x02, 0x01, KEY_PROG1 }, /* SOURCE */ { 0x0201, KEY_PROG1 }, /* SOURCE */
{ 0x02, 0x00, KEY_POWER }, /* POWER */ { 0x0200, KEY_POWER }, /* POWER */
{ 0x02, 0x05, KEY_1 }, /* 1 */ { 0x0205, KEY_1 }, /* 1 */
{ 0x02, 0x06, KEY_2 }, /* 2 */ { 0x0206, KEY_2 }, /* 2 */
{ 0x02, 0x07, KEY_3 }, /* 3 */ { 0x0207, KEY_3 }, /* 3 */
{ 0x02, 0x09, KEY_4 }, /* 4 */ { 0x0209, KEY_4 }, /* 4 */
{ 0x02, 0x0a, KEY_5 }, /* 5 */ { 0x020a, KEY_5 }, /* 5 */
{ 0x02, 0x0b, KEY_6 }, /* 6 */ { 0x020b, KEY_6 }, /* 6 */
{ 0x02, 0x0d, KEY_7 }, /* 7 */ { 0x020d, KEY_7 }, /* 7 */
{ 0x02, 0x0e, KEY_8 }, /* 8 */ { 0x020e, KEY_8 }, /* 8 */
{ 0x02, 0x0f, KEY_9 }, /* 9 */ { 0x020f, KEY_9 }, /* 9 */
{ 0x02, 0x12, KEY_LEFT }, /* L / DISPLAY */ { 0x0212, KEY_LEFT }, /* L / DISPLAY */
{ 0x02, 0x11, KEY_0 }, /* 0 */ { 0x0211, KEY_0 }, /* 0 */
{ 0x02, 0x13, KEY_RIGHT }, /* R / CH RTN */ { 0x0213, KEY_RIGHT }, /* R / CH RTN */
{ 0x02, 0x17, KEY_PROG2 }, /* SNAP SHOT */ { 0x0217, KEY_PROG2 }, /* SNAP SHOT */
{ 0x02, 0x10, KEY_PROG3 }, /* 16-CH PREV */ { 0x0210, KEY_PROG3 }, /* 16-CH PREV */
{ 0x02, 0x1e, KEY_VOLUMEDOWN }, /* VOL DOWN */ { 0x021e, KEY_VOLUMEDOWN }, /* VOL DOWN */
{ 0x02, 0x0c, KEY_ZOOM }, /* FULL SCREEN */ { 0x020c, KEY_ZOOM }, /* FULL SCREEN */
{ 0x02, 0x1f, KEY_VOLUMEUP }, /* VOL UP */ { 0x021f, KEY_VOLUMEUP }, /* VOL UP */
{ 0x02, 0x14, KEY_MUTE }, /* MUTE */ { 0x0214, KEY_MUTE }, /* MUTE */
{ 0x02, 0x08, KEY_AUDIO }, /* AUDIO */ { 0x0208, KEY_AUDIO }, /* AUDIO */
{ 0x02, 0x19, KEY_RECORD }, /* RECORD */ { 0x0219, KEY_RECORD }, /* RECORD */
{ 0x02, 0x18, KEY_PLAY }, /* PLAY */ { 0x0218, KEY_PLAY }, /* PLAY */
{ 0x02, 0x1b, KEY_STOP }, /* STOP */ { 0x021b, KEY_STOP }, /* STOP */
{ 0x02, 0x1a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */ { 0x021a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */
{ 0x02, 0x1d, KEY_BACK }, /* << / RED */ { 0x021d, KEY_BACK }, /* << / RED */
{ 0x02, 0x1c, KEY_FORWARD }, /* >> / YELLOW */ { 0x021c, KEY_FORWARD }, /* >> / YELLOW */
{ 0x02, 0x03, KEY_TEXT }, /* TELETEXT */ { 0x0203, KEY_TEXT }, /* TELETEXT */
{ 0x02, 0x04, KEY_EPG }, /* EPG */ { 0x0204, KEY_EPG }, /* EPG */
{ 0x02, 0x15, KEY_MENU }, /* MENU */ { 0x0215, KEY_MENU }, /* MENU */
{ 0x03, 0x03, KEY_CHANNELUP }, /* CH UP */ { 0x0303, KEY_CHANNELUP }, /* CH UP */
{ 0x03, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */ { 0x0302, KEY_CHANNELDOWN }, /* CH DOWN */
{ 0x03, 0x01, KEY_FIRST }, /* |<< / GREEN */ { 0x0301, KEY_FIRST }, /* |<< / GREEN */
{ 0x03, 0x00, KEY_LAST }, /* >>| / BLUE */ { 0x0300, KEY_LAST }, /* >>| / BLUE */
}; };

View file

@ -35,43 +35,43 @@ MODULE_PARM_DESC(debug,
struct dvb_usb_rc_key af9005_rc_keys[] = { struct dvb_usb_rc_key af9005_rc_keys[] = {
{0x01, 0xb7, KEY_POWER}, {0x01b7, KEY_POWER},
{0x01, 0xa7, KEY_VOLUMEUP}, {0x01a7, KEY_VOLUMEUP},
{0x01, 0x87, KEY_CHANNELUP}, {0x0187, KEY_CHANNELUP},
{0x01, 0x7f, KEY_MUTE}, {0x017f, KEY_MUTE},
{0x01, 0xbf, KEY_VOLUMEDOWN}, {0x01bf, KEY_VOLUMEDOWN},
{0x01, 0x3f, KEY_CHANNELDOWN}, {0x013f, KEY_CHANNELDOWN},
{0x01, 0xdf, KEY_1}, {0x01df, KEY_1},
{0x01, 0x5f, KEY_2}, {0x015f, KEY_2},
{0x01, 0x9f, KEY_3}, {0x019f, KEY_3},
{0x01, 0x1f, KEY_4}, {0x011f, KEY_4},
{0x01, 0xef, KEY_5}, {0x01ef, KEY_5},
{0x01, 0x6f, KEY_6}, {0x016f, KEY_6},
{0x01, 0xaf, KEY_7}, {0x01af, KEY_7},
{0x01, 0x27, KEY_8}, {0x0127, KEY_8},
{0x01, 0x07, KEY_9}, {0x0107, KEY_9},
{0x01, 0xcf, KEY_ZOOM}, {0x01cf, KEY_ZOOM},
{0x01, 0x4f, KEY_0}, {0x014f, KEY_0},
{0x01, 0x8f, KEY_GOTO}, /* marked jump on the remote */ {0x018f, KEY_GOTO}, /* marked jump on the remote */
{0x00, 0xbd, KEY_POWER}, {0x00bd, KEY_POWER},
{0x00, 0x7d, KEY_VOLUMEUP}, {0x007d, KEY_VOLUMEUP},
{0x00, 0xfd, KEY_CHANNELUP}, {0x00fd, KEY_CHANNELUP},
{0x00, 0x9d, KEY_MUTE}, {0x009d, KEY_MUTE},
{0x00, 0x5d, KEY_VOLUMEDOWN}, {0x005d, KEY_VOLUMEDOWN},
{0x00, 0xdd, KEY_CHANNELDOWN}, {0x00dd, KEY_CHANNELDOWN},
{0x00, 0xad, KEY_1}, {0x00ad, KEY_1},
{0x00, 0x6d, KEY_2}, {0x006d, KEY_2},
{0x00, 0xed, KEY_3}, {0x00ed, KEY_3},
{0x00, 0x8d, KEY_4}, {0x008d, KEY_4},
{0x00, 0x4d, KEY_5}, {0x004d, KEY_5},
{0x00, 0xcd, KEY_6}, {0x00cd, KEY_6},
{0x00, 0xb5, KEY_7}, {0x00b5, KEY_7},
{0x00, 0x75, KEY_8}, {0x0075, KEY_8},
{0x00, 0xf5, KEY_9}, {0x00f5, KEY_9},
{0x00, 0x95, KEY_ZOOM}, {0x0095, KEY_ZOOM},
{0x00, 0x55, KEY_0}, {0x0055, KEY_0},
{0x00, 0xd5, KEY_GOTO}, /* marked jump on the remote */ {0x00d5, KEY_GOTO}, /* marked jump on the remote */
}; };
int af9005_rc_keys_size = ARRAY_SIZE(af9005_rc_keys); int af9005_rc_keys_size = ARRAY_SIZE(af9005_rc_keys);
@ -131,8 +131,8 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event,
return 0; return 0;
} }
for (i = 0; i < af9005_rc_keys_size; i++) { for (i = 0; i < af9005_rc_keys_size; i++) {
if (af9005_rc_keys[i].custom == cust if (rc5_custom(&af9005_rc_keys[i]) == cust
&& af9005_rc_keys[i].data == dat) { && rc5_data(&af9005_rc_keys[i]) == dat) {
*event = af9005_rc_keys[i].event; *event = af9005_rc_keys[i].event;
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
deb_decode deb_decode

View file

@ -538,24 +538,22 @@ exit:
/* dump eeprom */ /* dump eeprom */
static int af9015_eeprom_dump(struct dvb_usb_device *d) static int af9015_eeprom_dump(struct dvb_usb_device *d)
{ {
char buf[4+3*16+1], buf2[4];
u8 reg, val; u8 reg, val;
for (reg = 0; ; reg++) { for (reg = 0; ; reg++) {
if (reg % 16 == 0) { if (reg % 16 == 0) {
if (reg) if (reg)
deb_info("%s\n", buf); deb_info(KERN_CONT "\n");
sprintf(buf, "%02x: ", reg); deb_info(KERN_DEBUG "%02x:", reg);
} }
if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0) if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0)
sprintf(buf2, "%02x ", val); deb_info(KERN_CONT " %02x", val);
else else
strcpy(buf2, "-- "); deb_info(KERN_CONT " --");
strcat(buf, buf2);
if (reg == 0xff) if (reg == 0xff)
break; break;
} }
deb_info("%s\n", buf); deb_info(KERN_CONT "\n");
return 0; return 0;
} }
@ -1045,8 +1043,8 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
*state = REMOTE_NO_KEY_PRESSED; *state = REMOTE_NO_KEY_PRESSED;
for (i = 0; i < d->props.rc_key_map_size; i++) { for (i = 0; i < d->props.rc_key_map_size; i++) {
if (!buf[1] && keymap[i].custom == buf[0] && if (!buf[1] && rc5_custom(&keymap[i]) == buf[0] &&
keymap[i].data == buf[2]) { rc5_data(&keymap[i]) == buf[2]) {
*event = keymap[i].event; *event = keymap[i].event;
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
break; break;
@ -1266,6 +1264,7 @@ static struct usb_device_id af9015_usb_table[] = {
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)},
{USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)}, {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
/* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
{0}, {0},
}; };
MODULE_DEVICE_TABLE(usb, af9015_usb_table); MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@ -1346,7 +1345,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
{ {
.name = "KWorld PlusTV Dual DVB-T Stick " \ .name = "KWorld PlusTV Dual DVB-T Stick " \
"(DVB-T 399U)", "(DVB-T 399U)",
.cold_ids = {&af9015_usb_table[4], NULL}, .cold_ids = {&af9015_usb_table[4],
&af9015_usb_table[25], NULL},
.warm_ids = {NULL}, .warm_ids = {NULL},
}, },
{ {

View file

@ -121,21 +121,21 @@ enum af9015_remote {
/* Leadtek WinFast DTV Dongle Gold */ /* Leadtek WinFast DTV Dongle Gold */
static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = { static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = {
{ 0x00, 0x1e, KEY_1 }, { 0x001e, KEY_1 },
{ 0x00, 0x1f, KEY_2 }, { 0x001f, KEY_2 },
{ 0x00, 0x20, KEY_3 }, { 0x0020, KEY_3 },
{ 0x00, 0x21, KEY_4 }, { 0x0021, KEY_4 },
{ 0x00, 0x22, KEY_5 }, { 0x0022, KEY_5 },
{ 0x00, 0x23, KEY_6 }, { 0x0023, KEY_6 },
{ 0x00, 0x24, KEY_7 }, { 0x0024, KEY_7 },
{ 0x00, 0x25, KEY_8 }, { 0x0025, KEY_8 },
{ 0x00, 0x26, KEY_9 }, { 0x0026, KEY_9 },
{ 0x00, 0x27, KEY_0 }, { 0x0027, KEY_0 },
{ 0x00, 0x28, KEY_ENTER }, { 0x0028, KEY_ENTER },
{ 0x00, 0x4f, KEY_VOLUMEUP }, { 0x004f, KEY_VOLUMEUP },
{ 0x00, 0x50, KEY_VOLUMEDOWN }, { 0x0050, KEY_VOLUMEDOWN },
{ 0x00, 0x51, KEY_CHANNELDOWN }, { 0x0051, KEY_CHANNELDOWN },
{ 0x00, 0x52, KEY_CHANNELUP }, { 0x0052, KEY_CHANNELUP },
}; };
static u8 af9015_ir_table_leadtek[] = { static u8 af9015_ir_table_leadtek[] = {
@ -193,60 +193,60 @@ static u8 af9015_ir_table_leadtek[] = {
/* TwinHan AzureWave AD-TU700(704J) */ /* TwinHan AzureWave AD-TU700(704J) */
static struct dvb_usb_rc_key af9015_rc_keys_twinhan[] = { static struct dvb_usb_rc_key af9015_rc_keys_twinhan[] = {
{ 0x05, 0x3f, KEY_POWER }, { 0x053f, KEY_POWER },
{ 0x00, 0x19, KEY_FAVORITES }, /* Favorite List */ { 0x0019, KEY_FAVORITES }, /* Favorite List */
{ 0x00, 0x04, KEY_TEXT }, /* Teletext */ { 0x0004, KEY_TEXT }, /* Teletext */
{ 0x00, 0x0e, KEY_POWER }, { 0x000e, KEY_POWER },
{ 0x00, 0x0e, KEY_INFO }, /* Preview */ { 0x000e, KEY_INFO }, /* Preview */
{ 0x00, 0x08, KEY_EPG }, /* Info/EPG */ { 0x0008, KEY_EPG }, /* Info/EPG */
{ 0x00, 0x0f, KEY_LIST }, /* Record List */ { 0x000f, KEY_LIST }, /* Record List */
{ 0x00, 0x1e, KEY_1 }, { 0x001e, KEY_1 },
{ 0x00, 0x1f, KEY_2 }, { 0x001f, KEY_2 },
{ 0x00, 0x20, KEY_3 }, { 0x0020, KEY_3 },
{ 0x00, 0x21, KEY_4 }, { 0x0021, KEY_4 },
{ 0x00, 0x22, KEY_5 }, { 0x0022, KEY_5 },
{ 0x00, 0x23, KEY_6 }, { 0x0023, KEY_6 },
{ 0x00, 0x24, KEY_7 }, { 0x0024, KEY_7 },
{ 0x00, 0x25, KEY_8 }, { 0x0025, KEY_8 },
{ 0x00, 0x26, KEY_9 }, { 0x0026, KEY_9 },
{ 0x00, 0x27, KEY_0 }, { 0x0027, KEY_0 },
{ 0x00, 0x29, KEY_CANCEL }, /* Cancel */ { 0x0029, KEY_CANCEL }, /* Cancel */
{ 0x00, 0x4c, KEY_CLEAR }, /* Clear */ { 0x004c, KEY_CLEAR }, /* Clear */
{ 0x00, 0x2a, KEY_BACK }, /* Back */ { 0x002a, KEY_BACK }, /* Back */
{ 0x00, 0x2b, KEY_TAB }, /* Tab */ { 0x002b, KEY_TAB }, /* Tab */
{ 0x00, 0x52, KEY_UP }, /* up arrow */ { 0x0052, KEY_UP }, /* up arrow */
{ 0x00, 0x51, KEY_DOWN }, /* down arrow */ { 0x0051, KEY_DOWN }, /* down arrow */
{ 0x00, 0x4f, KEY_RIGHT }, /* right arrow */ { 0x004f, KEY_RIGHT }, /* right arrow */
{ 0x00, 0x50, KEY_LEFT }, /* left arrow */ { 0x0050, KEY_LEFT }, /* left arrow */
{ 0x00, 0x28, KEY_ENTER }, /* Enter / ok */ { 0x0028, KEY_ENTER }, /* Enter / ok */
{ 0x02, 0x52, KEY_VOLUMEUP }, { 0x0252, KEY_VOLUMEUP },
{ 0x02, 0x51, KEY_VOLUMEDOWN }, { 0x0251, KEY_VOLUMEDOWN },
{ 0x00, 0x4e, KEY_CHANNELDOWN }, { 0x004e, KEY_CHANNELDOWN },
{ 0x00, 0x4b, KEY_CHANNELUP }, { 0x004b, KEY_CHANNELUP },
{ 0x00, 0x4a, KEY_RECORD }, { 0x004a, KEY_RECORD },
{ 0x01, 0x11, KEY_PLAY }, { 0x0111, KEY_PLAY },
{ 0x00, 0x17, KEY_PAUSE }, { 0x0017, KEY_PAUSE },
{ 0x00, 0x0c, KEY_REWIND }, /* FR << */ { 0x000c, KEY_REWIND }, /* FR << */
{ 0x00, 0x11, KEY_FASTFORWARD }, /* FF >> */ { 0x0011, KEY_FASTFORWARD }, /* FF >> */
{ 0x01, 0x15, KEY_PREVIOUS }, /* Replay */ { 0x0115, KEY_PREVIOUS }, /* Replay */
{ 0x01, 0x0e, KEY_NEXT }, /* Skip */ { 0x010e, KEY_NEXT }, /* Skip */
{ 0x00, 0x13, KEY_CAMERA }, /* Capture */ { 0x0013, KEY_CAMERA }, /* Capture */
{ 0x01, 0x0f, KEY_LANGUAGE }, /* SAP */ { 0x010f, KEY_LANGUAGE }, /* SAP */
{ 0x01, 0x13, KEY_TV2 }, /* PIP */ { 0x0113, KEY_TV2 }, /* PIP */
{ 0x00, 0x1d, KEY_ZOOM }, /* Full Screen */ { 0x001d, KEY_ZOOM }, /* Full Screen */
{ 0x01, 0x17, KEY_SUBTITLE }, /* Subtitle / CC */ { 0x0117, KEY_SUBTITLE }, /* Subtitle / CC */
{ 0x00, 0x10, KEY_MUTE }, { 0x0010, KEY_MUTE },
{ 0x01, 0x19, KEY_AUDIO }, /* L/R */ /* TODO better event */ { 0x0119, KEY_AUDIO }, /* L/R */ /* TODO better event */
{ 0x01, 0x16, KEY_SLEEP }, /* Hibernate */ { 0x0116, KEY_SLEEP }, /* Hibernate */
{ 0x01, 0x16, KEY_SWITCHVIDEOMODE }, { 0x0116, KEY_SWITCHVIDEOMODE },
/* A/V */ /* TODO does not work */ /* A/V */ /* TODO does not work */
{ 0x00, 0x06, KEY_AGAIN }, /* Recall */ { 0x0006, KEY_AGAIN }, /* Recall */
{ 0x01, 0x16, KEY_KPPLUS }, /* Zoom+ */ /* TODO does not work */ { 0x0116, KEY_KPPLUS }, /* Zoom+ */ /* TODO does not work */
{ 0x01, 0x16, KEY_KPMINUS }, /* Zoom- */ /* TODO does not work */ { 0x0116, KEY_KPMINUS }, /* Zoom- */ /* TODO does not work */
{ 0x02, 0x15, KEY_RED }, { 0x0215, KEY_RED },
{ 0x02, 0x0a, KEY_GREEN }, { 0x020a, KEY_GREEN },
{ 0x02, 0x1c, KEY_YELLOW }, { 0x021c, KEY_YELLOW },
{ 0x02, 0x05, KEY_BLUE }, { 0x0205, KEY_BLUE },
}; };
static u8 af9015_ir_table_twinhan[] = { static u8 af9015_ir_table_twinhan[] = {
@ -304,24 +304,24 @@ static u8 af9015_ir_table_twinhan[] = {
/* A-Link DTU(m) */ /* A-Link DTU(m) */
static struct dvb_usb_rc_key af9015_rc_keys_a_link[] = { static struct dvb_usb_rc_key af9015_rc_keys_a_link[] = {
{ 0x00, 0x1e, KEY_1 }, { 0x001e, KEY_1 },
{ 0x00, 0x1f, KEY_2 }, { 0x001f, KEY_2 },
{ 0x00, 0x20, KEY_3 }, { 0x0020, KEY_3 },
{ 0x00, 0x21, KEY_4 }, { 0x0021, KEY_4 },
{ 0x00, 0x22, KEY_5 }, { 0x0022, KEY_5 },
{ 0x00, 0x23, KEY_6 }, { 0x0023, KEY_6 },
{ 0x00, 0x24, KEY_7 }, { 0x0024, KEY_7 },
{ 0x00, 0x25, KEY_8 }, { 0x0025, KEY_8 },
{ 0x00, 0x26, KEY_9 }, { 0x0026, KEY_9 },
{ 0x00, 0x27, KEY_0 }, { 0x0027, KEY_0 },
{ 0x00, 0x2e, KEY_CHANNELUP }, { 0x002e, KEY_CHANNELUP },
{ 0x00, 0x2d, KEY_CHANNELDOWN }, { 0x002d, KEY_CHANNELDOWN },
{ 0x04, 0x28, KEY_ZOOM }, { 0x0428, KEY_ZOOM },
{ 0x00, 0x41, KEY_MUTE }, { 0x0041, KEY_MUTE },
{ 0x00, 0x42, KEY_VOLUMEDOWN }, { 0x0042, KEY_VOLUMEDOWN },
{ 0x00, 0x43, KEY_VOLUMEUP }, { 0x0043, KEY_VOLUMEUP },
{ 0x00, 0x44, KEY_GOTO }, /* jump */ { 0x0044, KEY_GOTO }, /* jump */
{ 0x05, 0x45, KEY_POWER }, { 0x0545, KEY_POWER },
}; };
static u8 af9015_ir_table_a_link[] = { static u8 af9015_ir_table_a_link[] = {
@ -347,24 +347,24 @@ static u8 af9015_ir_table_a_link[] = {
/* MSI DIGIVOX mini II V3.0 */ /* MSI DIGIVOX mini II V3.0 */
static struct dvb_usb_rc_key af9015_rc_keys_msi[] = { static struct dvb_usb_rc_key af9015_rc_keys_msi[] = {
{ 0x00, 0x1e, KEY_1 }, { 0x001e, KEY_1 },
{ 0x00, 0x1f, KEY_2 }, { 0x001f, KEY_2 },
{ 0x00, 0x20, KEY_3 }, { 0x0020, KEY_3 },
{ 0x00, 0x21, KEY_4 }, { 0x0021, KEY_4 },
{ 0x00, 0x22, KEY_5 }, { 0x0022, KEY_5 },
{ 0x00, 0x23, KEY_6 }, { 0x0023, KEY_6 },
{ 0x00, 0x24, KEY_7 }, { 0x0024, KEY_7 },
{ 0x00, 0x25, KEY_8 }, { 0x0025, KEY_8 },
{ 0x00, 0x26, KEY_9 }, { 0x0026, KEY_9 },
{ 0x00, 0x27, KEY_0 }, { 0x0027, KEY_0 },
{ 0x03, 0x0f, KEY_CHANNELUP }, { 0x030f, KEY_CHANNELUP },
{ 0x03, 0x0e, KEY_CHANNELDOWN }, { 0x030e, KEY_CHANNELDOWN },
{ 0x00, 0x42, KEY_VOLUMEDOWN }, { 0x0042, KEY_VOLUMEDOWN },
{ 0x00, 0x43, KEY_VOLUMEUP }, { 0x0043, KEY_VOLUMEUP },
{ 0x05, 0x45, KEY_POWER }, { 0x0545, KEY_POWER },
{ 0x00, 0x52, KEY_UP }, /* up */ { 0x0052, KEY_UP }, /* up */
{ 0x00, 0x51, KEY_DOWN }, /* down */ { 0x0051, KEY_DOWN }, /* down */
{ 0x00, 0x28, KEY_ENTER }, { 0x0028, KEY_ENTER },
}; };
static u8 af9015_ir_table_msi[] = { static u8 af9015_ir_table_msi[] = {
@ -390,42 +390,42 @@ static u8 af9015_ir_table_msi[] = {
/* MYGICTV U718 */ /* MYGICTV U718 */
static struct dvb_usb_rc_key af9015_rc_keys_mygictv[] = { static struct dvb_usb_rc_key af9015_rc_keys_mygictv[] = {
{ 0x00, 0x3d, KEY_SWITCHVIDEOMODE }, { 0x003d, KEY_SWITCHVIDEOMODE },
/* TV / AV */ /* TV / AV */
{ 0x05, 0x45, KEY_POWER }, { 0x0545, KEY_POWER },
{ 0x00, 0x1e, KEY_1 }, { 0x001e, KEY_1 },
{ 0x00, 0x1f, KEY_2 }, { 0x001f, KEY_2 },
{ 0x00, 0x20, KEY_3 }, { 0x0020, KEY_3 },
{ 0x00, 0x21, KEY_4 }, { 0x0021, KEY_4 },
{ 0x00, 0x22, KEY_5 }, { 0x0022, KEY_5 },
{ 0x00, 0x23, KEY_6 }, { 0x0023, KEY_6 },
{ 0x00, 0x24, KEY_7 }, { 0x0024, KEY_7 },
{ 0x00, 0x25, KEY_8 }, { 0x0025, KEY_8 },
{ 0x00, 0x26, KEY_9 }, { 0x0026, KEY_9 },
{ 0x00, 0x27, KEY_0 }, { 0x0027, KEY_0 },
{ 0x00, 0x41, KEY_MUTE }, { 0x0041, KEY_MUTE },
{ 0x00, 0x2a, KEY_ESC }, /* Esc */ { 0x002a, KEY_ESC }, /* Esc */
{ 0x00, 0x2e, KEY_CHANNELUP }, { 0x002e, KEY_CHANNELUP },
{ 0x00, 0x2d, KEY_CHANNELDOWN }, { 0x002d, KEY_CHANNELDOWN },
{ 0x00, 0x42, KEY_VOLUMEDOWN }, { 0x0042, KEY_VOLUMEDOWN },
{ 0x00, 0x43, KEY_VOLUMEUP }, { 0x0043, KEY_VOLUMEUP },
{ 0x00, 0x52, KEY_UP }, /* up arrow */ { 0x0052, KEY_UP }, /* up arrow */
{ 0x00, 0x51, KEY_DOWN }, /* down arrow */ { 0x0051, KEY_DOWN }, /* down arrow */
{ 0x00, 0x4f, KEY_RIGHT }, /* right arrow */ { 0x004f, KEY_RIGHT }, /* right arrow */
{ 0x00, 0x50, KEY_LEFT }, /* left arrow */ { 0x0050, KEY_LEFT }, /* left arrow */
{ 0x00, 0x28, KEY_ENTER }, /* ok */ { 0x0028, KEY_ENTER }, /* ok */
{ 0x01, 0x15, KEY_RECORD }, { 0x0115, KEY_RECORD },
{ 0x03, 0x13, KEY_PLAY }, { 0x0313, KEY_PLAY },
{ 0x01, 0x13, KEY_PAUSE }, { 0x0113, KEY_PAUSE },
{ 0x01, 0x16, KEY_STOP }, { 0x0116, KEY_STOP },
{ 0x03, 0x07, KEY_REWIND }, /* FR << */ { 0x0307, KEY_REWIND }, /* FR << */
{ 0x03, 0x09, KEY_FASTFORWARD }, /* FF >> */ { 0x0309, KEY_FASTFORWARD }, /* FF >> */
{ 0x00, 0x3b, KEY_TIME }, /* TimeShift */ { 0x003b, KEY_TIME }, /* TimeShift */
{ 0x00, 0x3e, KEY_CAMERA }, /* Snapshot */ { 0x003e, KEY_CAMERA }, /* Snapshot */
{ 0x03, 0x16, KEY_CYCLEWINDOWS }, /* yellow, min / max */ { 0x0316, KEY_CYCLEWINDOWS }, /* yellow, min / max */
{ 0x00, 0x00, KEY_ZOOM }, /* 'select' (?) */ { 0x0000, KEY_ZOOM }, /* 'select' (?) */
{ 0x03, 0x16, KEY_SHUFFLE }, /* Shuffle */ { 0x0316, KEY_SHUFFLE }, /* Shuffle */
{ 0x03, 0x45, KEY_POWER }, { 0x0345, KEY_POWER },
}; };
static u8 af9015_ir_table_mygictv[] = { static u8 af9015_ir_table_mygictv[] = {
@ -516,41 +516,41 @@ static u8 af9015_ir_table_kworld[] = {
/* AverMedia Volar X */ /* AverMedia Volar X */
static struct dvb_usb_rc_key af9015_rc_keys_avermedia[] = { static struct dvb_usb_rc_key af9015_rc_keys_avermedia[] = {
{ 0x05, 0x3d, KEY_PROG1 }, /* SOURCE */ { 0x053d, KEY_PROG1 }, /* SOURCE */
{ 0x05, 0x12, KEY_POWER }, /* POWER */ { 0x0512, KEY_POWER }, /* POWER */
{ 0x05, 0x1e, KEY_1 }, /* 1 */ { 0x051e, KEY_1 }, /* 1 */
{ 0x05, 0x1f, KEY_2 }, /* 2 */ { 0x051f, KEY_2 }, /* 2 */
{ 0x05, 0x20, KEY_3 }, /* 3 */ { 0x0520, KEY_3 }, /* 3 */
{ 0x05, 0x21, KEY_4 }, /* 4 */ { 0x0521, KEY_4 }, /* 4 */
{ 0x05, 0x22, KEY_5 }, /* 5 */ { 0x0522, KEY_5 }, /* 5 */
{ 0x05, 0x23, KEY_6 }, /* 6 */ { 0x0523, KEY_6 }, /* 6 */
{ 0x05, 0x24, KEY_7 }, /* 7 */ { 0x0524, KEY_7 }, /* 7 */
{ 0x05, 0x25, KEY_8 }, /* 8 */ { 0x0525, KEY_8 }, /* 8 */
{ 0x05, 0x26, KEY_9 }, /* 9 */ { 0x0526, KEY_9 }, /* 9 */
{ 0x05, 0x3f, KEY_LEFT }, /* L / DISPLAY */ { 0x053f, KEY_LEFT }, /* L / DISPLAY */
{ 0x05, 0x27, KEY_0 }, /* 0 */ { 0x0527, KEY_0 }, /* 0 */
{ 0x05, 0x0f, KEY_RIGHT }, /* R / CH RTN */ { 0x050f, KEY_RIGHT }, /* R / CH RTN */
{ 0x05, 0x18, KEY_PROG2 }, /* SNAP SHOT */ { 0x0518, KEY_PROG2 }, /* SNAP SHOT */
{ 0x05, 0x1c, KEY_PROG3 }, /* 16-CH PREV */ { 0x051c, KEY_PROG3 }, /* 16-CH PREV */
{ 0x05, 0x2d, KEY_VOLUMEDOWN }, /* VOL DOWN */ { 0x052d, KEY_VOLUMEDOWN }, /* VOL DOWN */
{ 0x05, 0x3e, KEY_ZOOM }, /* FULL SCREEN */ { 0x053e, KEY_ZOOM }, /* FULL SCREEN */
{ 0x05, 0x2e, KEY_VOLUMEUP }, /* VOL UP */ { 0x052e, KEY_VOLUMEUP }, /* VOL UP */
{ 0x05, 0x10, KEY_MUTE }, /* MUTE */ { 0x0510, KEY_MUTE }, /* MUTE */
{ 0x05, 0x04, KEY_AUDIO }, /* AUDIO */ { 0x0504, KEY_AUDIO }, /* AUDIO */
{ 0x05, 0x15, KEY_RECORD }, /* RECORD */ { 0x0515, KEY_RECORD }, /* RECORD */
{ 0x05, 0x11, KEY_PLAY }, /* PLAY */ { 0x0511, KEY_PLAY }, /* PLAY */
{ 0x05, 0x16, KEY_STOP }, /* STOP */ { 0x0516, KEY_STOP }, /* STOP */
{ 0x05, 0x0c, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */ { 0x050c, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */
{ 0x05, 0x05, KEY_BACK }, /* << / RED */ { 0x0505, KEY_BACK }, /* << / RED */
{ 0x05, 0x09, KEY_FORWARD }, /* >> / YELLOW */ { 0x0509, KEY_FORWARD }, /* >> / YELLOW */
{ 0x05, 0x17, KEY_TEXT }, /* TELETEXT */ { 0x0517, KEY_TEXT }, /* TELETEXT */
{ 0x05, 0x0a, KEY_EPG }, /* EPG */ { 0x050a, KEY_EPG }, /* EPG */
{ 0x05, 0x13, KEY_MENU }, /* MENU */ { 0x0513, KEY_MENU }, /* MENU */
{ 0x05, 0x0e, KEY_CHANNELUP }, /* CH UP */ { 0x050e, KEY_CHANNELUP }, /* CH UP */
{ 0x05, 0x0d, KEY_CHANNELDOWN }, /* CH DOWN */ { 0x050d, KEY_CHANNELDOWN }, /* CH DOWN */
{ 0x05, 0x19, KEY_FIRST }, /* |<< / GREEN */ { 0x0519, KEY_FIRST }, /* |<< / GREEN */
{ 0x05, 0x08, KEY_LAST }, /* >>| / BLUE */ { 0x0508, KEY_LAST }, /* >>| / BLUE */
}; };
static u8 af9015_ir_table_avermedia[] = { static u8 af9015_ir_table_avermedia[] = {
@ -622,34 +622,34 @@ static u8 af9015_ir_table_avermedia_ks[] = {
/* Digittrade DVB-T USB Stick */ /* Digittrade DVB-T USB Stick */
static struct dvb_usb_rc_key af9015_rc_keys_digittrade[] = { static struct dvb_usb_rc_key af9015_rc_keys_digittrade[] = {
{ 0x01, 0x0f, KEY_LAST }, /* RETURN */ { 0x010f, KEY_LAST }, /* RETURN */
{ 0x05, 0x17, KEY_TEXT }, /* TELETEXT */ { 0x0517, KEY_TEXT }, /* TELETEXT */
{ 0x01, 0x08, KEY_EPG }, /* EPG */ { 0x0108, KEY_EPG }, /* EPG */
{ 0x05, 0x13, KEY_POWER }, /* POWER */ { 0x0513, KEY_POWER }, /* POWER */
{ 0x01, 0x09, KEY_ZOOM }, /* FULLSCREEN */ { 0x0109, KEY_ZOOM }, /* FULLSCREEN */
{ 0x00, 0x40, KEY_AUDIO }, /* DUAL SOUND */ { 0x0040, KEY_AUDIO }, /* DUAL SOUND */
{ 0x00, 0x2c, KEY_PRINT }, /* SNAPSHOT */ { 0x002c, KEY_PRINT }, /* SNAPSHOT */
{ 0x05, 0x16, KEY_SUBTITLE }, /* SUBTITLE */ { 0x0516, KEY_SUBTITLE }, /* SUBTITLE */
{ 0x00, 0x52, KEY_CHANNELUP }, /* CH Up */ { 0x0052, KEY_CHANNELUP }, /* CH Up */
{ 0x00, 0x51, KEY_CHANNELDOWN },/* Ch Dn */ { 0x0051, KEY_CHANNELDOWN },/* Ch Dn */
{ 0x00, 0x57, KEY_VOLUMEUP }, /* Vol Up */ { 0x0057, KEY_VOLUMEUP }, /* Vol Up */
{ 0x00, 0x56, KEY_VOLUMEDOWN }, /* Vol Dn */ { 0x0056, KEY_VOLUMEDOWN }, /* Vol Dn */
{ 0x01, 0x10, KEY_MUTE }, /* MUTE */ { 0x0110, KEY_MUTE }, /* MUTE */
{ 0x00, 0x27, KEY_0 }, { 0x0027, KEY_0 },
{ 0x00, 0x1e, KEY_1 }, { 0x001e, KEY_1 },
{ 0x00, 0x1f, KEY_2 }, { 0x001f, KEY_2 },
{ 0x00, 0x20, KEY_3 }, { 0x0020, KEY_3 },
{ 0x00, 0x21, KEY_4 }, { 0x0021, KEY_4 },
{ 0x00, 0x22, KEY_5 }, { 0x0022, KEY_5 },
{ 0x00, 0x23, KEY_6 }, { 0x0023, KEY_6 },
{ 0x00, 0x24, KEY_7 }, { 0x0024, KEY_7 },
{ 0x00, 0x25, KEY_8 }, { 0x0025, KEY_8 },
{ 0x00, 0x26, KEY_9 }, { 0x0026, KEY_9 },
{ 0x01, 0x17, KEY_PLAYPAUSE }, /* TIMESHIFT */ { 0x0117, KEY_PLAYPAUSE }, /* TIMESHIFT */
{ 0x01, 0x15, KEY_RECORD }, /* RECORD */ { 0x0115, KEY_RECORD }, /* RECORD */
{ 0x03, 0x13, KEY_PLAY }, /* PLAY */ { 0x0313, KEY_PLAY }, /* PLAY */
{ 0x01, 0x16, KEY_STOP }, /* STOP */ { 0x0116, KEY_STOP }, /* STOP */
{ 0x01, 0x13, KEY_PAUSE }, /* PAUSE */ { 0x0113, KEY_PAUSE }, /* PAUSE */
}; };
static u8 af9015_ir_table_digittrade[] = { static u8 af9015_ir_table_digittrade[] = {
@ -685,34 +685,34 @@ static u8 af9015_ir_table_digittrade[] = {
/* TREKSTOR DVB-T USB Stick */ /* TREKSTOR DVB-T USB Stick */
static struct dvb_usb_rc_key af9015_rc_keys_trekstor[] = { static struct dvb_usb_rc_key af9015_rc_keys_trekstor[] = {
{ 0x07, 0x04, KEY_AGAIN }, /* Home */ { 0x0704, KEY_AGAIN }, /* Home */
{ 0x07, 0x05, KEY_MUTE }, /* Mute */ { 0x0705, KEY_MUTE }, /* Mute */
{ 0x07, 0x06, KEY_UP }, /* Up */ { 0x0706, KEY_UP }, /* Up */
{ 0x07, 0x07, KEY_DOWN }, /* Down */ { 0x0707, KEY_DOWN }, /* Down */
{ 0x07, 0x09, KEY_RIGHT }, /* Right */ { 0x0709, KEY_RIGHT }, /* Right */
{ 0x07, 0x0a, KEY_ENTER }, /* OK */ { 0x070a, KEY_ENTER }, /* OK */
{ 0x07, 0x0b, KEY_FASTFORWARD }, /* Fast forward */ { 0x070b, KEY_FASTFORWARD }, /* Fast forward */
{ 0x07, 0x0c, KEY_REWIND }, /* Rewind */ { 0x070c, KEY_REWIND }, /* Rewind */
{ 0x07, 0x0d, KEY_PLAY }, /* Play/Pause */ { 0x070d, KEY_PLAY }, /* Play/Pause */
{ 0x07, 0x0e, KEY_VOLUMEUP }, /* Volume + */ { 0x070e, KEY_VOLUMEUP }, /* Volume + */
{ 0x07, 0x0f, KEY_VOLUMEDOWN }, /* Volume - */ { 0x070f, KEY_VOLUMEDOWN }, /* Volume - */
{ 0x07, 0x10, KEY_RECORD }, /* Record */ { 0x0710, KEY_RECORD }, /* Record */
{ 0x07, 0x11, KEY_STOP }, /* Stop */ { 0x0711, KEY_STOP }, /* Stop */
{ 0x07, 0x12, KEY_ZOOM }, /* TV */ { 0x0712, KEY_ZOOM }, /* TV */
{ 0x07, 0x13, KEY_EPG }, /* Info/EPG */ { 0x0713, KEY_EPG }, /* Info/EPG */
{ 0x07, 0x14, KEY_CHANNELDOWN }, /* Channel - */ { 0x0714, KEY_CHANNELDOWN }, /* Channel - */
{ 0x07, 0x15, KEY_CHANNELUP }, /* Channel + */ { 0x0715, KEY_CHANNELUP }, /* Channel + */
{ 0x07, 0x1e, KEY_1 }, { 0x071e, KEY_1 },
{ 0x07, 0x1f, KEY_2 }, { 0x071f, KEY_2 },
{ 0x07, 0x20, KEY_3 }, { 0x0720, KEY_3 },
{ 0x07, 0x21, KEY_4 }, { 0x0721, KEY_4 },
{ 0x07, 0x22, KEY_5 }, { 0x0722, KEY_5 },
{ 0x07, 0x23, KEY_6 }, { 0x0723, KEY_6 },
{ 0x07, 0x24, KEY_7 }, { 0x0724, KEY_7 },
{ 0x07, 0x25, KEY_8 }, { 0x0725, KEY_8 },
{ 0x07, 0x26, KEY_9 }, { 0x0726, KEY_9 },
{ 0x07, 0x08, KEY_LEFT }, /* LEFT */ { 0x0708, KEY_LEFT }, /* LEFT */
{ 0x07, 0x27, KEY_0 }, { 0x0727, KEY_0 },
}; };
static u8 af9015_ir_table_trekstor[] = { static u8 af9015_ir_table_trekstor[] = {

View file

@ -389,8 +389,8 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
*state = REMOTE_NO_KEY_PRESSED; *state = REMOTE_NO_KEY_PRESSED;
for (i = 0; i < d->props.rc_key_map_size; i++) { for (i = 0; i < d->props.rc_key_map_size; i++) {
if (keymap[i].custom == ircode[0] && if (rc5_custom(&keymap[i]) == ircode[0] &&
keymap[i].data == ircode[1]) { rc5_data(&keymap[i]) == ircode[1]) {
*event = keymap[i].event; *event = keymap[i].event;
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
return 0; return 0;
@ -400,50 +400,50 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
} }
static struct dvb_usb_rc_key anysee_rc_keys[] = { static struct dvb_usb_rc_key anysee_rc_keys[] = {
{ 0x01, 0x00, KEY_0 }, { 0x0100, KEY_0 },
{ 0x01, 0x01, KEY_1 }, { 0x0101, KEY_1 },
{ 0x01, 0x02, KEY_2 }, { 0x0102, KEY_2 },
{ 0x01, 0x03, KEY_3 }, { 0x0103, KEY_3 },
{ 0x01, 0x04, KEY_4 }, { 0x0104, KEY_4 },
{ 0x01, 0x05, KEY_5 }, { 0x0105, KEY_5 },
{ 0x01, 0x06, KEY_6 }, { 0x0106, KEY_6 },
{ 0x01, 0x07, KEY_7 }, { 0x0107, KEY_7 },
{ 0x01, 0x08, KEY_8 }, { 0x0108, KEY_8 },
{ 0x01, 0x09, KEY_9 }, { 0x0109, KEY_9 },
{ 0x01, 0x0a, KEY_POWER }, { 0x010a, KEY_POWER },
{ 0x01, 0x0b, KEY_DOCUMENTS }, /* * */ { 0x010b, KEY_DOCUMENTS }, /* * */
{ 0x01, 0x19, KEY_FAVORITES }, { 0x0119, KEY_FAVORITES },
{ 0x01, 0x20, KEY_SLEEP }, { 0x0120, KEY_SLEEP },
{ 0x01, 0x21, KEY_MODE }, /* 4:3 / 16:9 select */ { 0x0121, KEY_MODE }, /* 4:3 / 16:9 select */
{ 0x01, 0x22, KEY_ZOOM }, { 0x0122, KEY_ZOOM },
{ 0x01, 0x47, KEY_TEXT }, { 0x0147, KEY_TEXT },
{ 0x01, 0x16, KEY_TV }, /* TV / radio select */ { 0x0116, KEY_TV }, /* TV / radio select */
{ 0x01, 0x1e, KEY_LANGUAGE }, /* Second Audio Program */ { 0x011e, KEY_LANGUAGE }, /* Second Audio Program */
{ 0x01, 0x1a, KEY_SUBTITLE }, { 0x011a, KEY_SUBTITLE },
{ 0x01, 0x1b, KEY_CAMERA }, /* screenshot */ { 0x011b, KEY_CAMERA }, /* screenshot */
{ 0x01, 0x42, KEY_MUTE }, { 0x0142, KEY_MUTE },
{ 0x01, 0x0e, KEY_MENU }, { 0x010e, KEY_MENU },
{ 0x01, 0x0f, KEY_EPG }, { 0x010f, KEY_EPG },
{ 0x01, 0x17, KEY_INFO }, { 0x0117, KEY_INFO },
{ 0x01, 0x10, KEY_EXIT }, { 0x0110, KEY_EXIT },
{ 0x01, 0x13, KEY_VOLUMEUP }, { 0x0113, KEY_VOLUMEUP },
{ 0x01, 0x12, KEY_VOLUMEDOWN }, { 0x0112, KEY_VOLUMEDOWN },
{ 0x01, 0x11, KEY_CHANNELUP }, { 0x0111, KEY_CHANNELUP },
{ 0x01, 0x14, KEY_CHANNELDOWN }, { 0x0114, KEY_CHANNELDOWN },
{ 0x01, 0x15, KEY_OK }, { 0x0115, KEY_OK },
{ 0x01, 0x1d, KEY_RED }, { 0x011d, KEY_RED },
{ 0x01, 0x1f, KEY_GREEN }, { 0x011f, KEY_GREEN },
{ 0x01, 0x1c, KEY_YELLOW }, { 0x011c, KEY_YELLOW },
{ 0x01, 0x44, KEY_BLUE }, { 0x0144, KEY_BLUE },
{ 0x01, 0x0c, KEY_SHUFFLE }, /* snapshot */ { 0x010c, KEY_SHUFFLE }, /* snapshot */
{ 0x01, 0x48, KEY_STOP }, { 0x0148, KEY_STOP },
{ 0x01, 0x50, KEY_PLAY }, { 0x0150, KEY_PLAY },
{ 0x01, 0x51, KEY_PAUSE }, { 0x0151, KEY_PAUSE },
{ 0x01, 0x49, KEY_RECORD }, { 0x0149, KEY_RECORD },
{ 0x01, 0x18, KEY_PREVIOUS }, /* |<< */ { 0x0118, KEY_PREVIOUS }, /* |<< */
{ 0x01, 0x0d, KEY_NEXT }, /* >>| */ { 0x010d, KEY_NEXT }, /* >>| */
{ 0x01, 0x24, KEY_PROG1 }, /* F1 */ { 0x0124, KEY_PROG1 }, /* F1 */
{ 0x01, 0x25, KEY_PROG2 }, /* F2 */ { 0x0125, KEY_PROG2 }, /* F2 */
}; };
/* DVB USB Driver stuff */ /* DVB USB Driver stuff */

View file

@ -85,43 +85,43 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
} }
static struct dvb_usb_rc_key cinergyt2_rc_keys[] = { static struct dvb_usb_rc_key cinergyt2_rc_keys[] = {
{ 0x04, 0x01, KEY_POWER }, { 0x0401, KEY_POWER },
{ 0x04, 0x02, KEY_1 }, { 0x0402, KEY_1 },
{ 0x04, 0x03, KEY_2 }, { 0x0403, KEY_2 },
{ 0x04, 0x04, KEY_3 }, { 0x0404, KEY_3 },
{ 0x04, 0x05, KEY_4 }, { 0x0405, KEY_4 },
{ 0x04, 0x06, KEY_5 }, { 0x0406, KEY_5 },
{ 0x04, 0x07, KEY_6 }, { 0x0407, KEY_6 },
{ 0x04, 0x08, KEY_7 }, { 0x0408, KEY_7 },
{ 0x04, 0x09, KEY_8 }, { 0x0409, KEY_8 },
{ 0x04, 0x0a, KEY_9 }, { 0x040a, KEY_9 },
{ 0x04, 0x0c, KEY_0 }, { 0x040c, KEY_0 },
{ 0x04, 0x0b, KEY_VIDEO }, { 0x040b, KEY_VIDEO },
{ 0x04, 0x0d, KEY_REFRESH }, { 0x040d, KEY_REFRESH },
{ 0x04, 0x0e, KEY_SELECT }, { 0x040e, KEY_SELECT },
{ 0x04, 0x0f, KEY_EPG }, { 0x040f, KEY_EPG },
{ 0x04, 0x10, KEY_UP }, { 0x0410, KEY_UP },
{ 0x04, 0x14, KEY_DOWN }, { 0x0414, KEY_DOWN },
{ 0x04, 0x11, KEY_LEFT }, { 0x0411, KEY_LEFT },
{ 0x04, 0x13, KEY_RIGHT }, { 0x0413, KEY_RIGHT },
{ 0x04, 0x12, KEY_OK }, { 0x0412, KEY_OK },
{ 0x04, 0x15, KEY_TEXT }, { 0x0415, KEY_TEXT },
{ 0x04, 0x16, KEY_INFO }, { 0x0416, KEY_INFO },
{ 0x04, 0x17, KEY_RED }, { 0x0417, KEY_RED },
{ 0x04, 0x18, KEY_GREEN }, { 0x0418, KEY_GREEN },
{ 0x04, 0x19, KEY_YELLOW }, { 0x0419, KEY_YELLOW },
{ 0x04, 0x1a, KEY_BLUE }, { 0x041a, KEY_BLUE },
{ 0x04, 0x1c, KEY_VOLUMEUP }, { 0x041c, KEY_VOLUMEUP },
{ 0x04, 0x1e, KEY_VOLUMEDOWN }, { 0x041e, KEY_VOLUMEDOWN },
{ 0x04, 0x1d, KEY_MUTE }, { 0x041d, KEY_MUTE },
{ 0x04, 0x1b, KEY_CHANNELUP }, { 0x041b, KEY_CHANNELUP },
{ 0x04, 0x1f, KEY_CHANNELDOWN }, { 0x041f, KEY_CHANNELDOWN },
{ 0x04, 0x40, KEY_PAUSE }, { 0x0440, KEY_PAUSE },
{ 0x04, 0x4c, KEY_PLAY }, { 0x044c, KEY_PLAY },
{ 0x04, 0x58, KEY_RECORD }, { 0x0458, KEY_RECORD },
{ 0x04, 0x54, KEY_PREVIOUS }, { 0x0454, KEY_PREVIOUS },
{ 0x04, 0x48, KEY_STOP }, { 0x0448, KEY_STOP },
{ 0x04, 0x5c, KEY_NEXT } { 0x045c, KEY_NEXT }
}; };
/* Number of keypresses to ignore before detect repeating */ /* Number of keypresses to ignore before detect repeating */

View file

@ -275,6 +275,7 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe,
param.tps = cpu_to_le16(compute_tps(fep)); param.tps = cpu_to_le16(compute_tps(fep));
param.freq = cpu_to_le32(fep->frequency / 1000); param.freq = cpu_to_le32(fep->frequency / 1000);
param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ; param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
param.flags = 0;
err = dvb_usb_generic_rw(state->d, err = dvb_usb_generic_rw(state->d,
(char *)&param, sizeof(param), (char *)&param, sizeof(param),

View file

@ -38,7 +38,7 @@
#include "mxl5005s.h" #include "mxl5005s.h"
#include "dib7000p.h" #include "dib7000p.h"
#include "dib0070.h" #include "dib0070.h"
#include "lgs8gl5.h" #include "lgs8gxx.h"
/* debug */ /* debug */
static int dvb_usb_cxusb_debug; static int dvb_usb_cxusb_debug;
@ -392,8 +392,8 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
*state = REMOTE_NO_KEY_PRESSED; *state = REMOTE_NO_KEY_PRESSED;
for (i = 0; i < d->props.rc_key_map_size; i++) { for (i = 0; i < d->props.rc_key_map_size; i++) {
if (keymap[i].custom == ircode[2] && if (rc5_custom(&keymap[i]) == ircode[2] &&
keymap[i].data == ircode[3]) { rc5_data(&keymap[i]) == ircode[3]) {
*event = keymap[i].event; *event = keymap[i].event;
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
@ -420,8 +420,8 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
return 0; return 0;
for (i = 0; i < d->props.rc_key_map_size; i++) { for (i = 0; i < d->props.rc_key_map_size; i++) {
if (keymap[i].custom == ircode[1] && if (rc5_custom(&keymap[i]) == ircode[1] &&
keymap[i].data == ircode[2]) { rc5_data(&keymap[i]) == ircode[2]) {
*event = keymap[i].event; *event = keymap[i].event;
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
@ -446,8 +446,8 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
return 0; return 0;
for (i = 0; i < d->props.rc_key_map_size; i++) { for (i = 0; i < d->props.rc_key_map_size; i++) {
if (keymap[i].custom == ircode[0] && if (rc5_custom(&keymap[i]) == ircode[0] &&
keymap[i].data == ircode[1]) { rc5_data(&keymap[i]) == ircode[1]) {
*event = keymap[i].event; *event = keymap[i].event;
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
@ -459,128 +459,128 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
} }
static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
{ 0xfe, 0x02, KEY_TV }, { 0xfe02, KEY_TV },
{ 0xfe, 0x0e, KEY_MP3 }, { 0xfe0e, KEY_MP3 },
{ 0xfe, 0x1a, KEY_DVD }, { 0xfe1a, KEY_DVD },
{ 0xfe, 0x1e, KEY_FAVORITES }, { 0xfe1e, KEY_FAVORITES },
{ 0xfe, 0x16, KEY_SETUP }, { 0xfe16, KEY_SETUP },
{ 0xfe, 0x46, KEY_POWER2 }, { 0xfe46, KEY_POWER2 },
{ 0xfe, 0x0a, KEY_EPG }, { 0xfe0a, KEY_EPG },
{ 0xfe, 0x49, KEY_BACK }, { 0xfe49, KEY_BACK },
{ 0xfe, 0x4d, KEY_MENU }, { 0xfe4d, KEY_MENU },
{ 0xfe, 0x51, KEY_UP }, { 0xfe51, KEY_UP },
{ 0xfe, 0x5b, KEY_LEFT }, { 0xfe5b, KEY_LEFT },
{ 0xfe, 0x5f, KEY_RIGHT }, { 0xfe5f, KEY_RIGHT },
{ 0xfe, 0x53, KEY_DOWN }, { 0xfe53, KEY_DOWN },
{ 0xfe, 0x5e, KEY_OK }, { 0xfe5e, KEY_OK },
{ 0xfe, 0x59, KEY_INFO }, { 0xfe59, KEY_INFO },
{ 0xfe, 0x55, KEY_TAB }, { 0xfe55, KEY_TAB },
{ 0xfe, 0x0f, KEY_PREVIOUSSONG },/* Replay */ { 0xfe0f, KEY_PREVIOUSSONG },/* Replay */
{ 0xfe, 0x12, KEY_NEXTSONG }, /* Skip */ { 0xfe12, KEY_NEXTSONG }, /* Skip */
{ 0xfe, 0x42, KEY_ENTER }, /* Windows/Start */ { 0xfe42, KEY_ENTER }, /* Windows/Start */
{ 0xfe, 0x15, KEY_VOLUMEUP }, { 0xfe15, KEY_VOLUMEUP },
{ 0xfe, 0x05, KEY_VOLUMEDOWN }, { 0xfe05, KEY_VOLUMEDOWN },
{ 0xfe, 0x11, KEY_CHANNELUP }, { 0xfe11, KEY_CHANNELUP },
{ 0xfe, 0x09, KEY_CHANNELDOWN }, { 0xfe09, KEY_CHANNELDOWN },
{ 0xfe, 0x52, KEY_CAMERA }, { 0xfe52, KEY_CAMERA },
{ 0xfe, 0x5a, KEY_TUNER }, /* Live */ { 0xfe5a, KEY_TUNER }, /* Live */
{ 0xfe, 0x19, KEY_OPEN }, { 0xfe19, KEY_OPEN },
{ 0xfe, 0x0b, KEY_1 }, { 0xfe0b, KEY_1 },
{ 0xfe, 0x17, KEY_2 }, { 0xfe17, KEY_2 },
{ 0xfe, 0x1b, KEY_3 }, { 0xfe1b, KEY_3 },
{ 0xfe, 0x07, KEY_4 }, { 0xfe07, KEY_4 },
{ 0xfe, 0x50, KEY_5 }, { 0xfe50, KEY_5 },
{ 0xfe, 0x54, KEY_6 }, { 0xfe54, KEY_6 },
{ 0xfe, 0x48, KEY_7 }, { 0xfe48, KEY_7 },
{ 0xfe, 0x4c, KEY_8 }, { 0xfe4c, KEY_8 },
{ 0xfe, 0x58, KEY_9 }, { 0xfe58, KEY_9 },
{ 0xfe, 0x13, KEY_ANGLE }, /* Aspect */ { 0xfe13, KEY_ANGLE }, /* Aspect */
{ 0xfe, 0x03, KEY_0 }, { 0xfe03, KEY_0 },
{ 0xfe, 0x1f, KEY_ZOOM }, { 0xfe1f, KEY_ZOOM },
{ 0xfe, 0x43, KEY_REWIND }, { 0xfe43, KEY_REWIND },
{ 0xfe, 0x47, KEY_PLAYPAUSE }, { 0xfe47, KEY_PLAYPAUSE },
{ 0xfe, 0x4f, KEY_FASTFORWARD }, { 0xfe4f, KEY_FASTFORWARD },
{ 0xfe, 0x57, KEY_MUTE }, { 0xfe57, KEY_MUTE },
{ 0xfe, 0x0d, KEY_STOP }, { 0xfe0d, KEY_STOP },
{ 0xfe, 0x01, KEY_RECORD }, { 0xfe01, KEY_RECORD },
{ 0xfe, 0x4e, KEY_POWER }, { 0xfe4e, KEY_POWER },
}; };
static struct dvb_usb_rc_key dvico_portable_rc_keys[] = { static struct dvb_usb_rc_key dvico_portable_rc_keys[] = {
{ 0xfc, 0x02, KEY_SETUP }, /* Profile */ { 0xfc02, KEY_SETUP }, /* Profile */
{ 0xfc, 0x43, KEY_POWER2 }, { 0xfc43, KEY_POWER2 },
{ 0xfc, 0x06, KEY_EPG }, { 0xfc06, KEY_EPG },
{ 0xfc, 0x5a, KEY_BACK }, { 0xfc5a, KEY_BACK },
{ 0xfc, 0x05, KEY_MENU }, { 0xfc05, KEY_MENU },
{ 0xfc, 0x47, KEY_INFO }, { 0xfc47, KEY_INFO },
{ 0xfc, 0x01, KEY_TAB }, { 0xfc01, KEY_TAB },
{ 0xfc, 0x42, KEY_PREVIOUSSONG },/* Replay */ { 0xfc42, KEY_PREVIOUSSONG },/* Replay */
{ 0xfc, 0x49, KEY_VOLUMEUP }, { 0xfc49, KEY_VOLUMEUP },
{ 0xfc, 0x09, KEY_VOLUMEDOWN }, { 0xfc09, KEY_VOLUMEDOWN },
{ 0xfc, 0x54, KEY_CHANNELUP }, { 0xfc54, KEY_CHANNELUP },
{ 0xfc, 0x0b, KEY_CHANNELDOWN }, { 0xfc0b, KEY_CHANNELDOWN },
{ 0xfc, 0x16, KEY_CAMERA }, { 0xfc16, KEY_CAMERA },
{ 0xfc, 0x40, KEY_TUNER }, /* ATV/DTV */ { 0xfc40, KEY_TUNER }, /* ATV/DTV */
{ 0xfc, 0x45, KEY_OPEN }, { 0xfc45, KEY_OPEN },
{ 0xfc, 0x19, KEY_1 }, { 0xfc19, KEY_1 },
{ 0xfc, 0x18, KEY_2 }, { 0xfc18, KEY_2 },
{ 0xfc, 0x1b, KEY_3 }, { 0xfc1b, KEY_3 },
{ 0xfc, 0x1a, KEY_4 }, { 0xfc1a, KEY_4 },
{ 0xfc, 0x58, KEY_5 }, { 0xfc58, KEY_5 },
{ 0xfc, 0x59, KEY_6 }, { 0xfc59, KEY_6 },
{ 0xfc, 0x15, KEY_7 }, { 0xfc15, KEY_7 },
{ 0xfc, 0x14, KEY_8 }, { 0xfc14, KEY_8 },
{ 0xfc, 0x17, KEY_9 }, { 0xfc17, KEY_9 },
{ 0xfc, 0x44, KEY_ANGLE }, /* Aspect */ { 0xfc44, KEY_ANGLE }, /* Aspect */
{ 0xfc, 0x55, KEY_0 }, { 0xfc55, KEY_0 },
{ 0xfc, 0x07, KEY_ZOOM }, { 0xfc07, KEY_ZOOM },
{ 0xfc, 0x0a, KEY_REWIND }, { 0xfc0a, KEY_REWIND },
{ 0xfc, 0x08, KEY_PLAYPAUSE }, { 0xfc08, KEY_PLAYPAUSE },
{ 0xfc, 0x4b, KEY_FASTFORWARD }, { 0xfc4b, KEY_FASTFORWARD },
{ 0xfc, 0x5b, KEY_MUTE }, { 0xfc5b, KEY_MUTE },
{ 0xfc, 0x04, KEY_STOP }, { 0xfc04, KEY_STOP },
{ 0xfc, 0x56, KEY_RECORD }, { 0xfc56, KEY_RECORD },
{ 0xfc, 0x57, KEY_POWER }, { 0xfc57, KEY_POWER },
{ 0xfc, 0x41, KEY_UNKNOWN }, /* INPUT */ { 0xfc41, KEY_UNKNOWN }, /* INPUT */
{ 0xfc, 0x00, KEY_UNKNOWN }, /* HD */ { 0xfc00, KEY_UNKNOWN }, /* HD */
}; };
static struct dvb_usb_rc_key d680_dmb_rc_keys[] = { static struct dvb_usb_rc_key d680_dmb_rc_keys[] = {
{ 0x00, 0x38, KEY_UNKNOWN }, /* TV/AV */ { 0x0038, KEY_UNKNOWN }, /* TV/AV */
{ 0x08, 0x0c, KEY_ZOOM }, { 0x080c, KEY_ZOOM },
{ 0x08, 0x00, KEY_0 }, { 0x0800, KEY_0 },
{ 0x00, 0x01, KEY_1 }, { 0x0001, KEY_1 },
{ 0x08, 0x02, KEY_2 }, { 0x0802, KEY_2 },
{ 0x00, 0x03, KEY_3 }, { 0x0003, KEY_3 },
{ 0x08, 0x04, KEY_4 }, { 0x0804, KEY_4 },
{ 0x00, 0x05, KEY_5 }, { 0x0005, KEY_5 },
{ 0x08, 0x06, KEY_6 }, { 0x0806, KEY_6 },
{ 0x00, 0x07, KEY_7 }, { 0x0007, KEY_7 },
{ 0x08, 0x08, KEY_8 }, { 0x0808, KEY_8 },
{ 0x00, 0x09, KEY_9 }, { 0x0009, KEY_9 },
{ 0x00, 0x0a, KEY_MUTE }, { 0x000a, KEY_MUTE },
{ 0x08, 0x29, KEY_BACK }, { 0x0829, KEY_BACK },
{ 0x00, 0x12, KEY_CHANNELUP }, { 0x0012, KEY_CHANNELUP },
{ 0x08, 0x13, KEY_CHANNELDOWN }, { 0x0813, KEY_CHANNELDOWN },
{ 0x00, 0x2b, KEY_VOLUMEUP }, { 0x002b, KEY_VOLUMEUP },
{ 0x08, 0x2c, KEY_VOLUMEDOWN }, { 0x082c, KEY_VOLUMEDOWN },
{ 0x00, 0x20, KEY_UP }, { 0x0020, KEY_UP },
{ 0x08, 0x21, KEY_DOWN }, { 0x0821, KEY_DOWN },
{ 0x00, 0x11, KEY_LEFT }, { 0x0011, KEY_LEFT },
{ 0x08, 0x10, KEY_RIGHT }, { 0x0810, KEY_RIGHT },
{ 0x00, 0x0d, KEY_OK }, { 0x000d, KEY_OK },
{ 0x08, 0x1f, KEY_RECORD }, { 0x081f, KEY_RECORD },
{ 0x00, 0x17, KEY_PLAYPAUSE }, { 0x0017, KEY_PLAYPAUSE },
{ 0x08, 0x16, KEY_PLAYPAUSE }, { 0x0816, KEY_PLAYPAUSE },
{ 0x00, 0x0b, KEY_STOP }, { 0x000b, KEY_STOP },
{ 0x08, 0x27, KEY_FASTFORWARD }, { 0x0827, KEY_FASTFORWARD },
{ 0x00, 0x26, KEY_REWIND }, { 0x0026, KEY_REWIND },
{ 0x08, 0x1e, KEY_UNKNOWN }, /* Time Shift */ { 0x081e, KEY_UNKNOWN }, /* Time Shift */
{ 0x00, 0x0e, KEY_UNKNOWN }, /* Snapshot */ { 0x000e, KEY_UNKNOWN }, /* Snapshot */
{ 0x08, 0x2d, KEY_UNKNOWN }, /* Mouse Cursor */ { 0x082d, KEY_UNKNOWN }, /* Mouse Cursor */
{ 0x00, 0x0f, KEY_UNKNOWN }, /* Minimize/Maximize */ { 0x000f, KEY_UNKNOWN }, /* Minimize/Maximize */
{ 0x08, 0x14, KEY_UNKNOWN }, /* Shuffle */ { 0x0814, KEY_UNKNOWN }, /* Shuffle */
{ 0x00, 0x25, KEY_POWER }, { 0x0025, KEY_POWER },
}; };
static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
@ -1094,8 +1094,18 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
return -EIO; return -EIO;
} }
static struct lgs8gl5_config lgs8gl5_cfg = { static struct lgs8gxx_config d680_lgs8gl5_cfg = {
.prod = LGS8GXX_PROD_LGS8GL5,
.demod_address = 0x19, .demod_address = 0x19,
.serial_ts = 0,
.ts_clk_pol = 0,
.ts_clk_gated = 1,
.if_clk_freq = 30400, /* 30.4 MHz */
.if_freq = 5725, /* 5.725 MHz */
.if_neg_center = 0,
.ext_adc = 0,
.adc_signed = 0,
.if_neg_edge = 0,
}; };
static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
@ -1135,7 +1145,7 @@ static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
msleep(100); msleep(100);
/* Attach frontend */ /* Attach frontend */
adap->fe = dvb_attach(lgs8gl5_attach, &lgs8gl5_cfg, &d->i2c_adap); adap->fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
if (adap->fe == NULL) if (adap->fe == NULL)
return -EIO; return -EIO;

View file

@ -310,7 +310,7 @@ static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
struct i2c_adapter *tun_i2c; struct i2c_adapter *tun_i2c;
tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
return dvb_attach(mt2266_attach, adap->fe, tun_i2c, return dvb_attach(mt2266_attach, adap->fe, tun_i2c,
&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;; &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;
} }
/* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */ /* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */
@ -509,7 +509,8 @@ static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event,
return 0; return 0;
} }
for (i=0;i<d->props.rc_key_map_size; i++) { for (i=0;i<d->props.rc_key_map_size; i++) {
if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) { if (rc5_custom(&keymap[i]) == key[3-2] &&
rc5_data(&keymap[i]) == key[3-3]) {
st->rc_counter = 0; st->rc_counter = 0;
*event = keymap[i].event; *event = keymap[i].event;
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
@ -522,7 +523,8 @@ static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event,
default: { default: {
/* RC-5 protocol changes toggle bit on new keypress */ /* RC-5 protocol changes toggle bit on new keypress */
for (i = 0; i < d->props.rc_key_map_size; i++) { for (i = 0; i < d->props.rc_key_map_size; i++) {
if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) { if (rc5_custom(&keymap[i]) == key[3-2] &&
rc5_data(&keymap[i]) == key[3-3]) {
if (d->last_event == keymap[i].event && if (d->last_event == keymap[i].event &&
key[3-1] == st->rc_toggle) { key[3-1] == st->rc_toggle) {
st->rc_counter++; st->rc_counter++;
@ -616,8 +618,8 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event,
/* Find the key in the map */ /* Find the key in the map */
for (i = 0; i < d->props.rc_key_map_size; i++) { for (i = 0; i < d->props.rc_key_map_size; i++) {
if (keymap[i].custom == poll_reply.system_lsb && if (rc5_custom(&keymap[i]) == poll_reply.system_lsb &&
keymap[i].data == poll_reply.data) { rc5_data(&keymap[i]) == poll_reply.data) {
*event = keymap[i].event; *event = keymap[i].event;
found = 1; found = 1;
break; break;
@ -684,193 +686,193 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
static struct dvb_usb_rc_key dib0700_rc_keys[] = { static struct dvb_usb_rc_key dib0700_rc_keys[] = {
/* Key codes for the tiny Pinnacle remote*/ /* Key codes for the tiny Pinnacle remote*/
{ 0x07, 0x00, KEY_MUTE }, { 0x0700, KEY_MUTE },
{ 0x07, 0x01, KEY_MENU }, // Pinnacle logo { 0x0701, KEY_MENU }, /* Pinnacle logo */
{ 0x07, 0x39, KEY_POWER }, { 0x0739, KEY_POWER },
{ 0x07, 0x03, KEY_VOLUMEUP }, { 0x0703, KEY_VOLUMEUP },
{ 0x07, 0x09, KEY_VOLUMEDOWN }, { 0x0709, KEY_VOLUMEDOWN },
{ 0x07, 0x06, KEY_CHANNELUP }, { 0x0706, KEY_CHANNELUP },
{ 0x07, 0x0c, KEY_CHANNELDOWN }, { 0x070c, KEY_CHANNELDOWN },
{ 0x07, 0x0f, KEY_1 }, { 0x070f, KEY_1 },
{ 0x07, 0x15, KEY_2 }, { 0x0715, KEY_2 },
{ 0x07, 0x10, KEY_3 }, { 0x0710, KEY_3 },
{ 0x07, 0x18, KEY_4 }, { 0x0718, KEY_4 },
{ 0x07, 0x1b, KEY_5 }, { 0x071b, KEY_5 },
{ 0x07, 0x1e, KEY_6 }, { 0x071e, KEY_6 },
{ 0x07, 0x11, KEY_7 }, { 0x0711, KEY_7 },
{ 0x07, 0x21, KEY_8 }, { 0x0721, KEY_8 },
{ 0x07, 0x12, KEY_9 }, { 0x0712, KEY_9 },
{ 0x07, 0x27, KEY_0 }, { 0x0727, KEY_0 },
{ 0x07, 0x24, KEY_SCREEN }, // 'Square' key { 0x0724, KEY_SCREEN }, /* 'Square' key */
{ 0x07, 0x2a, KEY_TEXT }, // 'T' key { 0x072a, KEY_TEXT }, /* 'T' key */
{ 0x07, 0x2d, KEY_REWIND }, { 0x072d, KEY_REWIND },
{ 0x07, 0x30, KEY_PLAY }, { 0x0730, KEY_PLAY },
{ 0x07, 0x33, KEY_FASTFORWARD }, { 0x0733, KEY_FASTFORWARD },
{ 0x07, 0x36, KEY_RECORD }, { 0x0736, KEY_RECORD },
{ 0x07, 0x3c, KEY_STOP }, { 0x073c, KEY_STOP },
{ 0x07, 0x3f, KEY_CANCEL }, // '?' key { 0x073f, KEY_CANCEL }, /* '?' key */
/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */ /* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
{ 0xeb, 0x01, KEY_POWER }, { 0xeb01, KEY_POWER },
{ 0xeb, 0x02, KEY_1 }, { 0xeb02, KEY_1 },
{ 0xeb, 0x03, KEY_2 }, { 0xeb03, KEY_2 },
{ 0xeb, 0x04, KEY_3 }, { 0xeb04, KEY_3 },
{ 0xeb, 0x05, KEY_4 }, { 0xeb05, KEY_4 },
{ 0xeb, 0x06, KEY_5 }, { 0xeb06, KEY_5 },
{ 0xeb, 0x07, KEY_6 }, { 0xeb07, KEY_6 },
{ 0xeb, 0x08, KEY_7 }, { 0xeb08, KEY_7 },
{ 0xeb, 0x09, KEY_8 }, { 0xeb09, KEY_8 },
{ 0xeb, 0x0a, KEY_9 }, { 0xeb0a, KEY_9 },
{ 0xeb, 0x0b, KEY_VIDEO }, { 0xeb0b, KEY_VIDEO },
{ 0xeb, 0x0c, KEY_0 }, { 0xeb0c, KEY_0 },
{ 0xeb, 0x0d, KEY_REFRESH }, { 0xeb0d, KEY_REFRESH },
{ 0xeb, 0x0f, KEY_EPG }, { 0xeb0f, KEY_EPG },
{ 0xeb, 0x10, KEY_UP }, { 0xeb10, KEY_UP },
{ 0xeb, 0x11, KEY_LEFT }, { 0xeb11, KEY_LEFT },
{ 0xeb, 0x12, KEY_OK }, { 0xeb12, KEY_OK },
{ 0xeb, 0x13, KEY_RIGHT }, { 0xeb13, KEY_RIGHT },
{ 0xeb, 0x14, KEY_DOWN }, { 0xeb14, KEY_DOWN },
{ 0xeb, 0x16, KEY_INFO }, { 0xeb16, KEY_INFO },
{ 0xeb, 0x17, KEY_RED }, { 0xeb17, KEY_RED },
{ 0xeb, 0x18, KEY_GREEN }, { 0xeb18, KEY_GREEN },
{ 0xeb, 0x19, KEY_YELLOW }, { 0xeb19, KEY_YELLOW },
{ 0xeb, 0x1a, KEY_BLUE }, { 0xeb1a, KEY_BLUE },
{ 0xeb, 0x1b, KEY_CHANNELUP }, { 0xeb1b, KEY_CHANNELUP },
{ 0xeb, 0x1c, KEY_VOLUMEUP }, { 0xeb1c, KEY_VOLUMEUP },
{ 0xeb, 0x1d, KEY_MUTE }, { 0xeb1d, KEY_MUTE },
{ 0xeb, 0x1e, KEY_VOLUMEDOWN }, { 0xeb1e, KEY_VOLUMEDOWN },
{ 0xeb, 0x1f, KEY_CHANNELDOWN }, { 0xeb1f, KEY_CHANNELDOWN },
{ 0xeb, 0x40, KEY_PAUSE }, { 0xeb40, KEY_PAUSE },
{ 0xeb, 0x41, KEY_HOME }, { 0xeb41, KEY_HOME },
{ 0xeb, 0x42, KEY_MENU }, /* DVD Menu */ { 0xeb42, KEY_MENU }, /* DVD Menu */
{ 0xeb, 0x43, KEY_SUBTITLE }, { 0xeb43, KEY_SUBTITLE },
{ 0xeb, 0x44, KEY_TEXT }, /* Teletext */ { 0xeb44, KEY_TEXT }, /* Teletext */
{ 0xeb, 0x45, KEY_DELETE }, { 0xeb45, KEY_DELETE },
{ 0xeb, 0x46, KEY_TV }, { 0xeb46, KEY_TV },
{ 0xeb, 0x47, KEY_DVD }, { 0xeb47, KEY_DVD },
{ 0xeb, 0x48, KEY_STOP }, { 0xeb48, KEY_STOP },
{ 0xeb, 0x49, KEY_VIDEO }, { 0xeb49, KEY_VIDEO },
{ 0xeb, 0x4a, KEY_AUDIO }, /* Music */ { 0xeb4a, KEY_AUDIO }, /* Music */
{ 0xeb, 0x4b, KEY_SCREEN }, /* Pic */ { 0xeb4b, KEY_SCREEN }, /* Pic */
{ 0xeb, 0x4c, KEY_PLAY }, { 0xeb4c, KEY_PLAY },
{ 0xeb, 0x4d, KEY_BACK }, { 0xeb4d, KEY_BACK },
{ 0xeb, 0x4e, KEY_REWIND }, { 0xeb4e, KEY_REWIND },
{ 0xeb, 0x4f, KEY_FASTFORWARD }, { 0xeb4f, KEY_FASTFORWARD },
{ 0xeb, 0x54, KEY_PREVIOUS }, { 0xeb54, KEY_PREVIOUS },
{ 0xeb, 0x58, KEY_RECORD }, { 0xeb58, KEY_RECORD },
{ 0xeb, 0x5c, KEY_NEXT }, { 0xeb5c, KEY_NEXT },
/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */ /* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
{ 0x1e, 0x00, KEY_0 }, { 0x1e00, KEY_0 },
{ 0x1e, 0x01, KEY_1 }, { 0x1e01, KEY_1 },
{ 0x1e, 0x02, KEY_2 }, { 0x1e02, KEY_2 },
{ 0x1e, 0x03, KEY_3 }, { 0x1e03, KEY_3 },
{ 0x1e, 0x04, KEY_4 }, { 0x1e04, KEY_4 },
{ 0x1e, 0x05, KEY_5 }, { 0x1e05, KEY_5 },
{ 0x1e, 0x06, KEY_6 }, { 0x1e06, KEY_6 },
{ 0x1e, 0x07, KEY_7 }, { 0x1e07, KEY_7 },
{ 0x1e, 0x08, KEY_8 }, { 0x1e08, KEY_8 },
{ 0x1e, 0x09, KEY_9 }, { 0x1e09, KEY_9 },
{ 0x1e, 0x0a, KEY_KPASTERISK }, { 0x1e0a, KEY_KPASTERISK },
{ 0x1e, 0x0b, KEY_RED }, { 0x1e0b, KEY_RED },
{ 0x1e, 0x0c, KEY_RADIO }, { 0x1e0c, KEY_RADIO },
{ 0x1e, 0x0d, KEY_MENU }, { 0x1e0d, KEY_MENU },
{ 0x1e, 0x0e, KEY_GRAVE }, /* # */ { 0x1e0e, KEY_GRAVE }, /* # */
{ 0x1e, 0x0f, KEY_MUTE }, { 0x1e0f, KEY_MUTE },
{ 0x1e, 0x10, KEY_VOLUMEUP }, { 0x1e10, KEY_VOLUMEUP },
{ 0x1e, 0x11, KEY_VOLUMEDOWN }, { 0x1e11, KEY_VOLUMEDOWN },
{ 0x1e, 0x12, KEY_CHANNEL }, { 0x1e12, KEY_CHANNEL },
{ 0x1e, 0x14, KEY_UP }, { 0x1e14, KEY_UP },
{ 0x1e, 0x15, KEY_DOWN }, { 0x1e15, KEY_DOWN },
{ 0x1e, 0x16, KEY_LEFT }, { 0x1e16, KEY_LEFT },
{ 0x1e, 0x17, KEY_RIGHT }, { 0x1e17, KEY_RIGHT },
{ 0x1e, 0x18, KEY_VIDEO }, { 0x1e18, KEY_VIDEO },
{ 0x1e, 0x19, KEY_AUDIO }, { 0x1e19, KEY_AUDIO },
{ 0x1e, 0x1a, KEY_MEDIA }, { 0x1e1a, KEY_MEDIA },
{ 0x1e, 0x1b, KEY_EPG }, { 0x1e1b, KEY_EPG },
{ 0x1e, 0x1c, KEY_TV }, { 0x1e1c, KEY_TV },
{ 0x1e, 0x1e, KEY_NEXT }, { 0x1e1e, KEY_NEXT },
{ 0x1e, 0x1f, KEY_BACK }, { 0x1e1f, KEY_BACK },
{ 0x1e, 0x20, KEY_CHANNELUP }, { 0x1e20, KEY_CHANNELUP },
{ 0x1e, 0x21, KEY_CHANNELDOWN }, { 0x1e21, KEY_CHANNELDOWN },
{ 0x1e, 0x24, KEY_LAST }, /* Skip backwards */ { 0x1e24, KEY_LAST }, /* Skip backwards */
{ 0x1e, 0x25, KEY_OK }, { 0x1e25, KEY_OK },
{ 0x1e, 0x29, KEY_BLUE}, { 0x1e29, KEY_BLUE},
{ 0x1e, 0x2e, KEY_GREEN }, { 0x1e2e, KEY_GREEN },
{ 0x1e, 0x30, KEY_PAUSE }, { 0x1e30, KEY_PAUSE },
{ 0x1e, 0x32, KEY_REWIND }, { 0x1e32, KEY_REWIND },
{ 0x1e, 0x34, KEY_FASTFORWARD }, { 0x1e34, KEY_FASTFORWARD },
{ 0x1e, 0x35, KEY_PLAY }, { 0x1e35, KEY_PLAY },
{ 0x1e, 0x36, KEY_STOP }, { 0x1e36, KEY_STOP },
{ 0x1e, 0x37, KEY_RECORD }, { 0x1e37, KEY_RECORD },
{ 0x1e, 0x38, KEY_YELLOW }, { 0x1e38, KEY_YELLOW },
{ 0x1e, 0x3b, KEY_GOTO }, { 0x1e3b, KEY_GOTO },
{ 0x1e, 0x3d, KEY_POWER }, { 0x1e3d, KEY_POWER },
/* Key codes for the Leadtek Winfast DTV Dongle */ /* Key codes for the Leadtek Winfast DTV Dongle */
{ 0x00, 0x42, KEY_POWER }, { 0x0042, KEY_POWER },
{ 0x07, 0x7c, KEY_TUNER }, { 0x077c, KEY_TUNER },
{ 0x0f, 0x4e, KEY_PRINT }, /* PREVIEW */ { 0x0f4e, KEY_PRINT }, /* PREVIEW */
{ 0x08, 0x40, KEY_SCREEN }, /* full screen toggle*/ { 0x0840, KEY_SCREEN }, /* full screen toggle*/
{ 0x0f, 0x71, KEY_DOT }, /* frequency */ { 0x0f71, KEY_DOT }, /* frequency */
{ 0x07, 0x43, KEY_0 }, { 0x0743, KEY_0 },
{ 0x0c, 0x41, KEY_1 }, { 0x0c41, KEY_1 },
{ 0x04, 0x43, KEY_2 }, { 0x0443, KEY_2 },
{ 0x0b, 0x7f, KEY_3 }, { 0x0b7f, KEY_3 },
{ 0x0e, 0x41, KEY_4 }, { 0x0e41, KEY_4 },
{ 0x06, 0x43, KEY_5 }, { 0x0643, KEY_5 },
{ 0x09, 0x7f, KEY_6 }, { 0x097f, KEY_6 },
{ 0x0d, 0x7e, KEY_7 }, { 0x0d7e, KEY_7 },
{ 0x05, 0x7c, KEY_8 }, { 0x057c, KEY_8 },
{ 0x0a, 0x40, KEY_9 }, { 0x0a40, KEY_9 },
{ 0x0e, 0x4e, KEY_CLEAR }, { 0x0e4e, KEY_CLEAR },
{ 0x04, 0x7c, KEY_CHANNEL }, /* show channel number */ { 0x047c, KEY_CHANNEL }, /* show channel number */
{ 0x0f, 0x41, KEY_LAST }, /* recall */ { 0x0f41, KEY_LAST }, /* recall */
{ 0x03, 0x42, KEY_MUTE }, { 0x0342, KEY_MUTE },
{ 0x06, 0x4c, KEY_RESERVED }, /* PIP button*/ { 0x064c, KEY_RESERVED }, /* PIP button*/
{ 0x01, 0x72, KEY_SHUFFLE }, /* SNAPSHOT */ { 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
{ 0x0c, 0x4e, KEY_PLAYPAUSE }, /* TIMESHIFT */ { 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
{ 0x0b, 0x70, KEY_RECORD }, { 0x0b70, KEY_RECORD },
{ 0x03, 0x7d, KEY_VOLUMEUP }, { 0x037d, KEY_VOLUMEUP },
{ 0x01, 0x7d, KEY_VOLUMEDOWN }, { 0x017d, KEY_VOLUMEDOWN },
{ 0x02, 0x42, KEY_CHANNELUP }, { 0x0242, KEY_CHANNELUP },
{ 0x00, 0x7d, KEY_CHANNELDOWN }, { 0x007d, KEY_CHANNELDOWN },
/* Key codes for Nova-TD "credit card" remote control. */ /* Key codes for Nova-TD "credit card" remote control. */
{ 0x1d, 0x00, KEY_0 }, { 0x1d00, KEY_0 },
{ 0x1d, 0x01, KEY_1 }, { 0x1d01, KEY_1 },
{ 0x1d, 0x02, KEY_2 }, { 0x1d02, KEY_2 },
{ 0x1d, 0x03, KEY_3 }, { 0x1d03, KEY_3 },
{ 0x1d, 0x04, KEY_4 }, { 0x1d04, KEY_4 },
{ 0x1d, 0x05, KEY_5 }, { 0x1d05, KEY_5 },
{ 0x1d, 0x06, KEY_6 }, { 0x1d06, KEY_6 },
{ 0x1d, 0x07, KEY_7 }, { 0x1d07, KEY_7 },
{ 0x1d, 0x08, KEY_8 }, { 0x1d08, KEY_8 },
{ 0x1d, 0x09, KEY_9 }, { 0x1d09, KEY_9 },
{ 0x1d, 0x0a, KEY_TEXT }, { 0x1d0a, KEY_TEXT },
{ 0x1d, 0x0d, KEY_MENU }, { 0x1d0d, KEY_MENU },
{ 0x1d, 0x0f, KEY_MUTE }, { 0x1d0f, KEY_MUTE },
{ 0x1d, 0x10, KEY_VOLUMEUP }, { 0x1d10, KEY_VOLUMEUP },
{ 0x1d, 0x11, KEY_VOLUMEDOWN }, { 0x1d11, KEY_VOLUMEDOWN },
{ 0x1d, 0x12, KEY_CHANNEL }, { 0x1d12, KEY_CHANNEL },
{ 0x1d, 0x14, KEY_UP }, { 0x1d14, KEY_UP },
{ 0x1d, 0x15, KEY_DOWN }, { 0x1d15, KEY_DOWN },
{ 0x1d, 0x16, KEY_LEFT }, { 0x1d16, KEY_LEFT },
{ 0x1d, 0x17, KEY_RIGHT }, { 0x1d17, KEY_RIGHT },
{ 0x1d, 0x1c, KEY_TV }, { 0x1d1c, KEY_TV },
{ 0x1d, 0x1e, KEY_NEXT }, { 0x1d1e, KEY_NEXT },
{ 0x1d, 0x1f, KEY_BACK }, { 0x1d1f, KEY_BACK },
{ 0x1d, 0x20, KEY_CHANNELUP }, { 0x1d20, KEY_CHANNELUP },
{ 0x1d, 0x21, KEY_CHANNELDOWN }, { 0x1d21, KEY_CHANNELDOWN },
{ 0x1d, 0x24, KEY_LAST }, { 0x1d24, KEY_LAST },
{ 0x1d, 0x25, KEY_OK }, { 0x1d25, KEY_OK },
{ 0x1d, 0x30, KEY_PAUSE }, { 0x1d30, KEY_PAUSE },
{ 0x1d, 0x32, KEY_REWIND }, { 0x1d32, KEY_REWIND },
{ 0x1d, 0x34, KEY_FASTFORWARD }, { 0x1d34, KEY_FASTFORWARD },
{ 0x1d, 0x35, KEY_PLAY }, { 0x1d35, KEY_PLAY },
{ 0x1d, 0x36, KEY_STOP }, { 0x1d36, KEY_STOP },
{ 0x1d, 0x37, KEY_RECORD }, { 0x1d37, KEY_RECORD },
{ 0x1d, 0x3b, KEY_GOTO }, { 0x1d3b, KEY_GOTO },
{ 0x1d, 0x3d, KEY_POWER }, { 0x1d3d, KEY_POWER },
}; };
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
@ -1497,6 +1499,8 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_H) }, { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_H) },
{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T3) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T3) },
{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T5) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T5) },
{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) },
{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D_2) },
{ 0 } /* Terminating entry */ { 0 } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@ -1624,7 +1628,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
} }
}, },
.num_device_descs = 4, .num_device_descs = 5,
.devices = { .devices = {
{ "Pinnacle PCTV 2000e", { "Pinnacle PCTV 2000e",
{ &dib0700_usb_id_table[11], NULL }, { &dib0700_usb_id_table[11], NULL },
@ -1642,6 +1646,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[14], NULL }, { &dib0700_usb_id_table[14], NULL },
{ NULL }, { NULL },
}, },
{ "YUAN High-Tech DiBcom STK7700D",
{ &dib0700_usb_id_table[55], NULL },
{ NULL },
},
}, },
@ -1822,7 +1830,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}, },
}, },
.num_device_descs = 8, .num_device_descs = 9,
.devices = { .devices = {
{ "Terratec Cinergy HT USB XE", { "Terratec Cinergy HT USB XE",
{ &dib0700_usb_id_table[27], NULL }, { &dib0700_usb_id_table[27], NULL },
@ -1856,7 +1864,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[51], NULL }, { &dib0700_usb_id_table[51], NULL },
{ NULL }, { NULL },
}, },
{ "YUAN High-Tech STK7700D",
{ &dib0700_usb_id_table[54], NULL },
{ NULL },
},
}, },
.rc_interval = DEFAULT_RC_INTERVAL, .rc_interval = DEFAULT_RC_INTERVAL,
.rc_key_map = dib0700_rc_keys, .rc_key_map = dib0700_rc_keys,

View file

@ -318,132 +318,132 @@ EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
*/ */
struct dvb_usb_rc_key dibusb_rc_keys[] = { struct dvb_usb_rc_key dibusb_rc_keys[] = {
/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
{ 0x00, 0x16, KEY_POWER }, { 0x0016, KEY_POWER },
{ 0x00, 0x10, KEY_MUTE }, { 0x0010, KEY_MUTE },
{ 0x00, 0x03, KEY_1 }, { 0x0003, KEY_1 },
{ 0x00, 0x01, KEY_2 }, { 0x0001, KEY_2 },
{ 0x00, 0x06, KEY_3 }, { 0x0006, KEY_3 },
{ 0x00, 0x09, KEY_4 }, { 0x0009, KEY_4 },
{ 0x00, 0x1d, KEY_5 }, { 0x001d, KEY_5 },
{ 0x00, 0x1f, KEY_6 }, { 0x001f, KEY_6 },
{ 0x00, 0x0d, KEY_7 }, { 0x000d, KEY_7 },
{ 0x00, 0x19, KEY_8 }, { 0x0019, KEY_8 },
{ 0x00, 0x1b, KEY_9 }, { 0x001b, KEY_9 },
{ 0x00, 0x15, KEY_0 }, { 0x0015, KEY_0 },
{ 0x00, 0x05, KEY_CHANNELUP }, { 0x0005, KEY_CHANNELUP },
{ 0x00, 0x02, KEY_CHANNELDOWN }, { 0x0002, KEY_CHANNELDOWN },
{ 0x00, 0x1e, KEY_VOLUMEUP }, { 0x001e, KEY_VOLUMEUP },
{ 0x00, 0x0a, KEY_VOLUMEDOWN }, { 0x000a, KEY_VOLUMEDOWN },
{ 0x00, 0x11, KEY_RECORD }, { 0x0011, KEY_RECORD },
{ 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */ { 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */
{ 0x00, 0x14, KEY_PLAY }, { 0x0014, KEY_PLAY },
{ 0x00, 0x1a, KEY_STOP }, { 0x001a, KEY_STOP },
{ 0x00, 0x40, KEY_REWIND }, { 0x0040, KEY_REWIND },
{ 0x00, 0x12, KEY_FASTFORWARD }, { 0x0012, KEY_FASTFORWARD },
{ 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */ { 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */
{ 0x00, 0x4c, KEY_PAUSE }, { 0x004c, KEY_PAUSE },
{ 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */ { 0x004d, KEY_SCREEN }, /* Full screen mode. */
{ 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ { 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
/* additional keys TwinHan VisionPlus, the Artec seemingly not have */ /* additional keys TwinHan VisionPlus, the Artec seemingly not have */
{ 0x00, 0x0c, KEY_CANCEL }, /* Cancel */ { 0x000c, KEY_CANCEL }, /* Cancel */
{ 0x00, 0x1c, KEY_EPG }, /* EPG */ { 0x001c, KEY_EPG }, /* EPG */
{ 0x00, 0x00, KEY_TAB }, /* Tab */ { 0x0000, KEY_TAB }, /* Tab */
{ 0x00, 0x48, KEY_INFO }, /* Preview */ { 0x0048, KEY_INFO }, /* Preview */
{ 0x00, 0x04, KEY_LIST }, /* RecordList */ { 0x0004, KEY_LIST }, /* RecordList */
{ 0x00, 0x0f, KEY_TEXT }, /* Teletext */ { 0x000f, KEY_TEXT }, /* Teletext */
/* Key codes for the KWorld/ADSTech/JetWay remote. */ /* Key codes for the KWorld/ADSTech/JetWay remote. */
{ 0x86, 0x12, KEY_POWER }, { 0x8612, KEY_POWER },
{ 0x86, 0x0f, KEY_SELECT }, /* source */ { 0x860f, KEY_SELECT }, /* source */
{ 0x86, 0x0c, KEY_UNKNOWN }, /* scan */ { 0x860c, KEY_UNKNOWN }, /* scan */
{ 0x86, 0x0b, KEY_EPG }, { 0x860b, KEY_EPG },
{ 0x86, 0x10, KEY_MUTE }, { 0x8610, KEY_MUTE },
{ 0x86, 0x01, KEY_1 }, { 0x8601, KEY_1 },
{ 0x86, 0x02, KEY_2 }, { 0x8602, KEY_2 },
{ 0x86, 0x03, KEY_3 }, { 0x8603, KEY_3 },
{ 0x86, 0x04, KEY_4 }, { 0x8604, KEY_4 },
{ 0x86, 0x05, KEY_5 }, { 0x8605, KEY_5 },
{ 0x86, 0x06, KEY_6 }, { 0x8606, KEY_6 },
{ 0x86, 0x07, KEY_7 }, { 0x8607, KEY_7 },
{ 0x86, 0x08, KEY_8 }, { 0x8608, KEY_8 },
{ 0x86, 0x09, KEY_9 }, { 0x8609, KEY_9 },
{ 0x86, 0x0a, KEY_0 }, { 0x860a, KEY_0 },
{ 0x86, 0x18, KEY_ZOOM }, { 0x8618, KEY_ZOOM },
{ 0x86, 0x1c, KEY_UNKNOWN }, /* preview */ { 0x861c, KEY_UNKNOWN }, /* preview */
{ 0x86, 0x13, KEY_UNKNOWN }, /* snap */ { 0x8613, KEY_UNKNOWN }, /* snap */
{ 0x86, 0x00, KEY_UNDO }, { 0x8600, KEY_UNDO },
{ 0x86, 0x1d, KEY_RECORD }, { 0x861d, KEY_RECORD },
{ 0x86, 0x0d, KEY_STOP }, { 0x860d, KEY_STOP },
{ 0x86, 0x0e, KEY_PAUSE }, { 0x860e, KEY_PAUSE },
{ 0x86, 0x16, KEY_PLAY }, { 0x8616, KEY_PLAY },
{ 0x86, 0x11, KEY_BACK }, { 0x8611, KEY_BACK },
{ 0x86, 0x19, KEY_FORWARD }, { 0x8619, KEY_FORWARD },
{ 0x86, 0x14, KEY_UNKNOWN }, /* pip */ { 0x8614, KEY_UNKNOWN }, /* pip */
{ 0x86, 0x15, KEY_ESC }, { 0x8615, KEY_ESC },
{ 0x86, 0x1a, KEY_UP }, { 0x861a, KEY_UP },
{ 0x86, 0x1e, KEY_DOWN }, { 0x861e, KEY_DOWN },
{ 0x86, 0x1f, KEY_LEFT }, { 0x861f, KEY_LEFT },
{ 0x86, 0x1b, KEY_RIGHT }, { 0x861b, KEY_RIGHT },
/* Key codes for the DiBcom MOD3000 remote. */ /* Key codes for the DiBcom MOD3000 remote. */
{ 0x80, 0x00, KEY_MUTE }, { 0x8000, KEY_MUTE },
{ 0x80, 0x01, KEY_TEXT }, { 0x8001, KEY_TEXT },
{ 0x80, 0x02, KEY_HOME }, { 0x8002, KEY_HOME },
{ 0x80, 0x03, KEY_POWER }, { 0x8003, KEY_POWER },
{ 0x80, 0x04, KEY_RED }, { 0x8004, KEY_RED },
{ 0x80, 0x05, KEY_GREEN }, { 0x8005, KEY_GREEN },
{ 0x80, 0x06, KEY_YELLOW }, { 0x8006, KEY_YELLOW },
{ 0x80, 0x07, KEY_BLUE }, { 0x8007, KEY_BLUE },
{ 0x80, 0x08, KEY_DVD }, { 0x8008, KEY_DVD },
{ 0x80, 0x09, KEY_AUDIO }, { 0x8009, KEY_AUDIO },
{ 0x80, 0x0a, KEY_MEDIA }, /* Pictures */ { 0x800a, KEY_MEDIA }, /* Pictures */
{ 0x80, 0x0b, KEY_VIDEO }, { 0x800b, KEY_VIDEO },
{ 0x80, 0x0c, KEY_BACK }, { 0x800c, KEY_BACK },
{ 0x80, 0x0d, KEY_UP }, { 0x800d, KEY_UP },
{ 0x80, 0x0e, KEY_RADIO }, { 0x800e, KEY_RADIO },
{ 0x80, 0x0f, KEY_EPG }, { 0x800f, KEY_EPG },
{ 0x80, 0x10, KEY_LEFT }, { 0x8010, KEY_LEFT },
{ 0x80, 0x11, KEY_OK }, { 0x8011, KEY_OK },
{ 0x80, 0x12, KEY_RIGHT }, { 0x8012, KEY_RIGHT },
{ 0x80, 0x13, KEY_UNKNOWN }, /* SAP */ { 0x8013, KEY_UNKNOWN }, /* SAP */
{ 0x80, 0x14, KEY_TV }, { 0x8014, KEY_TV },
{ 0x80, 0x15, KEY_DOWN }, { 0x8015, KEY_DOWN },
{ 0x80, 0x16, KEY_MENU }, /* DVD Menu */ { 0x8016, KEY_MENU }, /* DVD Menu */
{ 0x80, 0x17, KEY_LAST }, { 0x8017, KEY_LAST },
{ 0x80, 0x18, KEY_RECORD }, { 0x8018, KEY_RECORD },
{ 0x80, 0x19, KEY_STOP }, { 0x8019, KEY_STOP },
{ 0x80, 0x1a, KEY_PAUSE }, { 0x801a, KEY_PAUSE },
{ 0x80, 0x1b, KEY_PLAY }, { 0x801b, KEY_PLAY },
{ 0x80, 0x1c, KEY_PREVIOUS }, { 0x801c, KEY_PREVIOUS },
{ 0x80, 0x1d, KEY_REWIND }, { 0x801d, KEY_REWIND },
{ 0x80, 0x1e, KEY_FASTFORWARD }, { 0x801e, KEY_FASTFORWARD },
{ 0x80, 0x1f, KEY_NEXT}, { 0x801f, KEY_NEXT},
{ 0x80, 0x40, KEY_1 }, { 0x8040, KEY_1 },
{ 0x80, 0x41, KEY_2 }, { 0x8041, KEY_2 },
{ 0x80, 0x42, KEY_3 }, { 0x8042, KEY_3 },
{ 0x80, 0x43, KEY_CHANNELUP }, { 0x8043, KEY_CHANNELUP },
{ 0x80, 0x44, KEY_4 }, { 0x8044, KEY_4 },
{ 0x80, 0x45, KEY_5 }, { 0x8045, KEY_5 },
{ 0x80, 0x46, KEY_6 }, { 0x8046, KEY_6 },
{ 0x80, 0x47, KEY_CHANNELDOWN }, { 0x8047, KEY_CHANNELDOWN },
{ 0x80, 0x48, KEY_7 }, { 0x8048, KEY_7 },
{ 0x80, 0x49, KEY_8 }, { 0x8049, KEY_8 },
{ 0x80, 0x4a, KEY_9 }, { 0x804a, KEY_9 },
{ 0x80, 0x4b, KEY_VOLUMEUP }, { 0x804b, KEY_VOLUMEUP },
{ 0x80, 0x4c, KEY_CLEAR }, { 0x804c, KEY_CLEAR },
{ 0x80, 0x4d, KEY_0 }, { 0x804d, KEY_0 },
{ 0x80, 0x4e, KEY_ENTER }, { 0x804e, KEY_ENTER },
{ 0x80, 0x4f, KEY_VOLUMEDOWN }, { 0x804f, KEY_VOLUMEDOWN },
}; };
EXPORT_SYMBOL(dibusb_rc_keys); EXPORT_SYMBOL(dibusb_rc_keys);

View file

@ -42,6 +42,8 @@ static struct usb_device_id dibusb_dib3000mc_table [] = {
/* 11 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_WARM) }, /* 11 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_WARM) },
/* 12 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_COLD) }, /* 12 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_COLD) },
/* 13 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_WARM) }, /* 13 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_WARM) },
/* 14 */ { USB_DEVICE(USB_VID_HUMAX_COEX, USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD) },
/* 15 */ { USB_DEVICE(USB_VID_HUMAX_COEX, USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table); MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
@ -66,7 +68,7 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
/* parameter for the MPEG2-data transfer */ /* parameter for the MPEG2-data transfer */
.stream = { .stream = {
.type = USB_BULK, .type = USB_BULK,
.count = 7, .count = 8,
.endpoint = 0x06, .endpoint = 0x06,
.u = { .u = {
.bulk = { .bulk = {
@ -88,7 +90,7 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
.generic_bulk_ctrl_endpoint = 0x01, .generic_bulk_ctrl_endpoint = 0x01,
.num_device_descs = 7, .num_device_descs = 8,
.devices = { .devices = {
{ "DiBcom USB2.0 DVB-T reference design (MOD3000P)", { "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
{ &dibusb_dib3000mc_table[0], NULL }, { &dibusb_dib3000mc_table[0], NULL },
@ -119,6 +121,10 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
{ &dibusb_dib3000mc_table[12], NULL }, { &dibusb_dib3000mc_table[12], NULL },
{ &dibusb_dib3000mc_table[13], NULL }, { &dibusb_dib3000mc_table[13], NULL },
}, },
{ "Humax/Coex DVB-T USB Stick 2.0 High Speed",
{ &dibusb_dib3000mc_table[14], NULL },
{ &dibusb_dib3000mc_table[15], NULL },
},
{ NULL }, { NULL },
} }
}; };

View file

@ -162,61 +162,61 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
} }
static struct dvb_usb_rc_key digitv_rc_keys[] = { static struct dvb_usb_rc_key digitv_rc_keys[] = {
{ 0x5f, 0x55, KEY_0 }, { 0x5f55, KEY_0 },
{ 0x6f, 0x55, KEY_1 }, { 0x6f55, KEY_1 },
{ 0x9f, 0x55, KEY_2 }, { 0x9f55, KEY_2 },
{ 0xaf, 0x55, KEY_3 }, { 0xaf55, KEY_3 },
{ 0x5f, 0x56, KEY_4 }, { 0x5f56, KEY_4 },
{ 0x6f, 0x56, KEY_5 }, { 0x6f56, KEY_5 },
{ 0x9f, 0x56, KEY_6 }, { 0x9f56, KEY_6 },
{ 0xaf, 0x56, KEY_7 }, { 0xaf56, KEY_7 },
{ 0x5f, 0x59, KEY_8 }, { 0x5f59, KEY_8 },
{ 0x6f, 0x59, KEY_9 }, { 0x6f59, KEY_9 },
{ 0x9f, 0x59, KEY_TV }, { 0x9f59, KEY_TV },
{ 0xaf, 0x59, KEY_AUX }, { 0xaf59, KEY_AUX },
{ 0x5f, 0x5a, KEY_DVD }, { 0x5f5a, KEY_DVD },
{ 0x6f, 0x5a, KEY_POWER }, { 0x6f5a, KEY_POWER },
{ 0x9f, 0x5a, KEY_MHP }, /* labelled 'Picture' */ { 0x9f5a, KEY_MHP }, /* labelled 'Picture' */
{ 0xaf, 0x5a, KEY_AUDIO }, { 0xaf5a, KEY_AUDIO },
{ 0x5f, 0x65, KEY_INFO }, { 0x5f65, KEY_INFO },
{ 0x6f, 0x65, KEY_F13 }, /* 16:9 */ { 0x6f65, KEY_F13 }, /* 16:9 */
{ 0x9f, 0x65, KEY_F14 }, /* 14:9 */ { 0x9f65, KEY_F14 }, /* 14:9 */
{ 0xaf, 0x65, KEY_EPG }, { 0xaf65, KEY_EPG },
{ 0x5f, 0x66, KEY_EXIT }, { 0x5f66, KEY_EXIT },
{ 0x6f, 0x66, KEY_MENU }, { 0x6f66, KEY_MENU },
{ 0x9f, 0x66, KEY_UP }, { 0x9f66, KEY_UP },
{ 0xaf, 0x66, KEY_DOWN }, { 0xaf66, KEY_DOWN },
{ 0x5f, 0x69, KEY_LEFT }, { 0x5f69, KEY_LEFT },
{ 0x6f, 0x69, KEY_RIGHT }, { 0x6f69, KEY_RIGHT },
{ 0x9f, 0x69, KEY_ENTER }, { 0x9f69, KEY_ENTER },
{ 0xaf, 0x69, KEY_CHANNELUP }, { 0xaf69, KEY_CHANNELUP },
{ 0x5f, 0x6a, KEY_CHANNELDOWN }, { 0x5f6a, KEY_CHANNELDOWN },
{ 0x6f, 0x6a, KEY_VOLUMEUP }, { 0x6f6a, KEY_VOLUMEUP },
{ 0x9f, 0x6a, KEY_VOLUMEDOWN }, { 0x9f6a, KEY_VOLUMEDOWN },
{ 0xaf, 0x6a, KEY_RED }, { 0xaf6a, KEY_RED },
{ 0x5f, 0x95, KEY_GREEN }, { 0x5f95, KEY_GREEN },
{ 0x6f, 0x95, KEY_YELLOW }, { 0x6f95, KEY_YELLOW },
{ 0x9f, 0x95, KEY_BLUE }, { 0x9f95, KEY_BLUE },
{ 0xaf, 0x95, KEY_SUBTITLE }, { 0xaf95, KEY_SUBTITLE },
{ 0x5f, 0x96, KEY_F15 }, /* AD */ { 0x5f96, KEY_F15 }, /* AD */
{ 0x6f, 0x96, KEY_TEXT }, { 0x6f96, KEY_TEXT },
{ 0x9f, 0x96, KEY_MUTE }, { 0x9f96, KEY_MUTE },
{ 0xaf, 0x96, KEY_REWIND }, { 0xaf96, KEY_REWIND },
{ 0x5f, 0x99, KEY_STOP }, { 0x5f99, KEY_STOP },
{ 0x6f, 0x99, KEY_PLAY }, { 0x6f99, KEY_PLAY },
{ 0x9f, 0x99, KEY_FASTFORWARD }, { 0x9f99, KEY_FASTFORWARD },
{ 0xaf, 0x99, KEY_F16 }, /* chapter */ { 0xaf99, KEY_F16 }, /* chapter */
{ 0x5f, 0x9a, KEY_PAUSE }, { 0x5f9a, KEY_PAUSE },
{ 0x6f, 0x9a, KEY_PLAY }, { 0x6f9a, KEY_PLAY },
{ 0x9f, 0x9a, KEY_RECORD }, { 0x9f9a, KEY_RECORD },
{ 0xaf, 0x9a, KEY_F17 }, /* picture in picture */ { 0xaf9a, KEY_F17 }, /* picture in picture */
{ 0x5f, 0xa5, KEY_KPPLUS }, /* zoom in */ { 0x5fa5, KEY_KPPLUS }, /* zoom in */
{ 0x6f, 0xa5, KEY_KPMINUS }, /* zoom out */ { 0x6fa5, KEY_KPMINUS }, /* zoom out */
{ 0x9f, 0xa5, KEY_F18 }, /* capture */ { 0x9fa5, KEY_F18 }, /* capture */
{ 0xaf, 0xa5, KEY_F19 }, /* web */ { 0xafa5, KEY_F19 }, /* web */
{ 0x5f, 0xa6, KEY_EMAIL }, { 0x5fa6, KEY_EMAIL },
{ 0x6f, 0xa6, KEY_PHONE }, { 0x6fa6, KEY_PHONE },
{ 0x9f, 0xa6, KEY_PC }, { 0x9fa6, KEY_PC },
}; };
static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
@ -238,8 +238,8 @@ static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
if (key[1] != 0) if (key[1] != 0)
{ {
for (i = 0; i < d->props.rc_key_map_size; i++) { for (i = 0; i < d->props.rc_key_map_size; i++) {
if (d->props.rc_key_map[i].custom == key[1] && if (rc5_custom(&d->props.rc_key_map[i]) == key[1] &&
d->props.rc_key_map[i].data == key[2]) { rc5_data(&d->props.rc_key_map[i]) == key[2]) {
*event = d->props.rc_key_map[i].event; *event = d->props.rc_key_map[i].event;
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
return 0; return 0;

View file

@ -58,24 +58,24 @@ static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
/* remote control */ /* remote control */
/* key list for the tiny remote control (Yakumo, don't know about the others) */ /* key list for the tiny remote control (Yakumo, don't know about the others) */
static struct dvb_usb_rc_key dtt200u_rc_keys[] = { static struct dvb_usb_rc_key dtt200u_rc_keys[] = {
{ 0x80, 0x01, KEY_MUTE }, { 0x8001, KEY_MUTE },
{ 0x80, 0x02, KEY_CHANNELDOWN }, { 0x8002, KEY_CHANNELDOWN },
{ 0x80, 0x03, KEY_VOLUMEDOWN }, { 0x8003, KEY_VOLUMEDOWN },
{ 0x80, 0x04, KEY_1 }, { 0x8004, KEY_1 },
{ 0x80, 0x05, KEY_2 }, { 0x8005, KEY_2 },
{ 0x80, 0x06, KEY_3 }, { 0x8006, KEY_3 },
{ 0x80, 0x07, KEY_4 }, { 0x8007, KEY_4 },
{ 0x80, 0x08, KEY_5 }, { 0x8008, KEY_5 },
{ 0x80, 0x09, KEY_6 }, { 0x8009, KEY_6 },
{ 0x80, 0x0a, KEY_7 }, { 0x800a, KEY_7 },
{ 0x80, 0x0c, KEY_ZOOM }, { 0x800c, KEY_ZOOM },
{ 0x80, 0x0d, KEY_0 }, { 0x800d, KEY_0 },
{ 0x80, 0x0e, KEY_SELECT }, { 0x800e, KEY_SELECT },
{ 0x80, 0x12, KEY_POWER }, { 0x8012, KEY_POWER },
{ 0x80, 0x1a, KEY_CHANNELUP }, { 0x801a, KEY_CHANNELUP },
{ 0x80, 0x1b, KEY_8 }, { 0x801b, KEY_8 },
{ 0x80, 0x1e, KEY_VOLUMEUP }, { 0x801e, KEY_VOLUMEUP },
{ 0x80, 0x1f, KEY_9 }, { 0x801f, KEY_9 },
}; };
static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)

View file

@ -19,7 +19,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
return -EINVAL; return -EINVAL;
} }
strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); strlcpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
d->i2c_adap.class = I2C_CLASS_TV_DIGITAL, d->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
d->i2c_adap.algo = d->props.i2c_algo; d->i2c_adap.algo = d->props.i2c_algo;
d->i2c_adap.algo_data = NULL; d->i2c_adap.algo_data = NULL;

View file

@ -58,6 +58,7 @@
#define USB_VID_GIGABYTE 0x1044 #define USB_VID_GIGABYTE 0x1044
#define USB_VID_YUAN 0x1164 #define USB_VID_YUAN 0x1164
#define USB_VID_XTENSIONS 0x1ae7 #define USB_VID_XTENSIONS 0x1ae7
#define USB_VID_HUMAX_COEX 0x10b9
/* Product IDs */ /* Product IDs */
#define USB_PID_ADSTECH_USB2_COLD 0xa333 #define USB_PID_ADSTECH_USB2_COLD 0xa333
@ -103,6 +104,7 @@
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
#define USB_PID_INTEL_CE9500 0x9500 #define USB_PID_INTEL_CE9500 0x9500
#define USB_PID_KWORLD_399U 0xe399 #define USB_PID_KWORLD_399U 0xe399
#define USB_PID_KWORLD_399U_2 0xe400
#define USB_PID_KWORLD_395U 0xe396 #define USB_PID_KWORLD_395U 0xe396
#define USB_PID_KWORLD_395U_2 0xe39b #define USB_PID_KWORLD_395U_2 0xe39b
#define USB_PID_KWORLD_395U_3 0xe395 #define USB_PID_KWORLD_395U_3 0xe395
@ -252,6 +254,8 @@
#define USB_PID_YUAN_STK7700PH 0x1f08 #define USB_PID_YUAN_STK7700PH 0x1f08
#define USB_PID_YUAN_PD378S 0x2edc #define USB_PID_YUAN_PD378S 0x2edc
#define USB_PID_YUAN_MC770 0x0871 #define USB_PID_YUAN_MC770 0x0871
#define USB_PID_YUAN_STK7700D 0x1efc
#define USB_PID_YUAN_STK7700D_2 0x1e8c
#define USB_PID_DW2102 0x2102 #define USB_PID_DW2102 0x2102
#define USB_PID_XTENSIONS_XD_380 0x0381 #define USB_PID_XTENSIONS_XD_380 0x0381
#define USB_PID_TELESTAR_STARSTICK_2 0x8000 #define USB_PID_TELESTAR_STARSTICK_2 0x8000
@ -259,5 +263,7 @@
#define USB_PID_SONY_PLAYTV 0x0003 #define USB_PID_SONY_PLAYTV 0x0003
#define USB_PID_ELGATO_EYETV_DTT 0x0021 #define USB_PID_ELGATO_EYETV_DTT 0x0021
#define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020
#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000
#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001
#endif #endif

View file

@ -8,6 +8,71 @@
#include "dvb-usb-common.h" #include "dvb-usb-common.h"
#include <linux/usb/input.h> #include <linux/usb/input.h>
static int dvb_usb_getkeycode(struct input_dev *dev,
int scancode, int *keycode)
{
struct dvb_usb_device *d = input_get_drvdata(dev);
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
int i;
/* See if we can match the raw key code. */
for (i = 0; i < d->props.rc_key_map_size; i++)
if (keymap[i].scan == scancode) {
*keycode = keymap[i].event;
return 0;
}
/*
* If is there extra space, returns KEY_RESERVED,
* otherwise, input core won't let dvb_usb_setkeycode
* to work
*/
for (i = 0; i < d->props.rc_key_map_size; i++)
if (keymap[i].event == KEY_RESERVED ||
keymap[i].event == KEY_UNKNOWN) {
*keycode = KEY_RESERVED;
return 0;
}
return -EINVAL;
}
static int dvb_usb_setkeycode(struct input_dev *dev,
int scancode, int keycode)
{
struct dvb_usb_device *d = input_get_drvdata(dev);
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
int i;
/* Search if it is replacing an existing keycode */
for (i = 0; i < d->props.rc_key_map_size; i++)
if (keymap[i].scan == scancode) {
keymap[i].event = keycode;
return 0;
}
/* Search if is there a clean entry. If so, use it */
for (i = 0; i < d->props.rc_key_map_size; i++)
if (keymap[i].event == KEY_RESERVED ||
keymap[i].event == KEY_UNKNOWN) {
keymap[i].scan = scancode;
keymap[i].event = keycode;
return 0;
}
/*
* FIXME: Currently, it is not possible to increase the size of
* scancode table. For it to happen, one possibility
* would be to allocate a table with key_map_size + 1,
* copying data, appending the new key on it, and freeing
* the old one - or maybe just allocating some spare space
*/
return -EINVAL;
}
/* Remote-control poll function - called every dib->rc_query_interval ms to see /* Remote-control poll function - called every dib->rc_query_interval ms to see
* whether the remote control has received anything. * whether the remote control has received anything.
* *
@ -111,6 +176,8 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
input_dev->phys = d->rc_phys; input_dev->phys = d->rc_phys;
usb_to_input_id(d->udev, &input_dev->id); usb_to_input_id(d->udev, &input_dev->id);
input_dev->dev.parent = &d->udev->dev; input_dev->dev.parent = &d->udev->dev;
input_dev->getkeycode = dvb_usb_getkeycode;
input_dev->setkeycode = dvb_usb_setkeycode;
/* set the bits for the keys */ /* set the bits for the keys */
deb_rc("key map size: %d\n", d->props.rc_key_map_size); deb_rc("key map size: %d\n", d->props.rc_key_map_size);
@ -128,6 +195,8 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
input_dev->rep[REP_PERIOD] = d->props.rc_interval; input_dev->rep[REP_PERIOD] = d->props.rc_interval;
input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; input_dev->rep[REP_DELAY] = d->props.rc_interval + 150;
input_set_drvdata(input_dev, d);
err = input_register_device(input_dev); err = input_register_device(input_dev);
if (err) { if (err) {
input_free_device(input_dev); input_free_device(input_dev);
@ -178,8 +247,8 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
} }
/* See if we can match the raw key code. */ /* See if we can match the raw key code. */
for (i = 0; i < d->props.rc_key_map_size; i++) for (i = 0; i < d->props.rc_key_map_size; i++)
if (keymap[i].custom == keybuf[1] && if (rc5_custom(&keymap[i]) == keybuf[1] &&
keymap[i].data == keybuf[3]) { rc5_data(&keymap[i]) == keybuf[3]) {
*event = keymap[i].event; *event = keymap[i].event;
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
return 0; return 0;

View file

@ -81,10 +81,25 @@ struct dvb_usb_device_description {
* @event: the input event assigned to key identified by custom and data * @event: the input event assigned to key identified by custom and data
*/ */
struct dvb_usb_rc_key { struct dvb_usb_rc_key {
u8 custom,data; u16 scan;
u32 event; u32 event;
}; };
static inline u8 rc5_custom(struct dvb_usb_rc_key *key)
{
return (key->scan >> 8) & 0xff;
}
static inline u8 rc5_data(struct dvb_usb_rc_key *key)
{
return key->scan & 0xff;
}
static inline u8 rc5_scan(struct dvb_usb_rc_key *key)
{
return key->scan & 0xffff;
}
struct dvb_usb_device; struct dvb_usb_device;
struct dvb_usb_adapter; struct dvb_usb_adapter;
struct usb_data_stream; struct usb_data_stream;

View file

@ -1,6 +1,6 @@
/* DVB USB framework compliant Linux driver for the /* DVB USB framework compliant Linux driver for the
* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
* TeVii S600, S650 Cards * TeVii S600, S630, S650 Cards
* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) * Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by)
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@ -18,6 +18,8 @@
#include "eds1547.h" #include "eds1547.h"
#include "cx24116.h" #include "cx24116.h"
#include "tda1002x.h" #include "tda1002x.h"
#include "mt312.h"
#include "zl10039.h"
#ifndef USB_PID_DW2102 #ifndef USB_PID_DW2102
#define USB_PID_DW2102 0x2102 #define USB_PID_DW2102 0x2102
@ -39,6 +41,10 @@
#define USB_PID_TEVII_S650 0xd650 #define USB_PID_TEVII_S650 0xd650
#endif #endif
#ifndef USB_PID_TEVII_S630
#define USB_PID_TEVII_S630 0xd630
#endif
#define DW210X_READ_MSG 0 #define DW210X_READ_MSG 0
#define DW210X_WRITE_MSG 1 #define DW210X_WRITE_MSG 1
@ -436,6 +442,69 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
return num; return num;
} }
static int s630_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int ret = 0;
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2: { /* read */
u8 ibuf[msg[1].len], obuf[3];
obuf[0] = msg[1].len;
obuf[1] = (msg[0].addr << 1);
obuf[2] = msg[0].buf[0];
ret = dw210x_op_rw(d->udev, 0x90, 0, 0,
obuf, 3, DW210X_WRITE_MSG);
msleep(5);
ret = dw210x_op_rw(d->udev, 0x91, 0, 0,
ibuf, msg[1].len, DW210X_READ_MSG);
memcpy(msg[1].buf, ibuf, msg[1].len);
break;
}
case 1:
switch (msg[0].addr) {
case 0x60:
case 0x0e: {
/* write to zl10313, zl10039 register, */
u8 obuf[msg[0].len + 2];
obuf[0] = msg[0].len + 1;
obuf[1] = (msg[0].addr << 1);
memcpy(obuf + 2, msg[0].buf, msg[0].len);
ret = dw210x_op_rw(d->udev, 0x80, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
break;
}
case (DW2102_RC_QUERY): {
u8 ibuf[4];
ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 4, DW210X_READ_MSG);
msg[0].buf[0] = ibuf[3];
break;
}
case (DW2102_VOLTAGE_CTRL): {
u8 obuf[2];
obuf[0] = 0x03;
obuf[1] = msg[0].buf[0];
ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
obuf, 2, DW210X_WRITE_MSG);
break;
}
}
break;
}
mutex_unlock(&d->i2c_mutex);
return num;
}
static u32 dw210x_i2c_func(struct i2c_adapter *adapter) static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
{ {
return I2C_FUNC_I2C; return I2C_FUNC_I2C;
@ -466,6 +535,11 @@ static struct i2c_algorithm dw3101_i2c_algo = {
.functionality = dw210x_i2c_func, .functionality = dw210x_i2c_func,
}; };
static struct i2c_algorithm s630_i2c_algo = {
.master_xfer = s630_i2c_transfer,
.functionality = dw210x_i2c_func,
};
static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{ {
int i; int i;
@ -490,6 +564,37 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
return 0; return 0;
}; };
static int s630_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i, ret;
u8 buf[3], eeprom[256], eepromline[16];
for (i = 0; i < 256; i++) {
buf[0] = 1;
buf[1] = 0xa0;
buf[2] = i;
ret = dw210x_op_rw(d->udev, 0x90, 0, 0,
buf, 3, DW210X_WRITE_MSG);
ret = dw210x_op_rw(d->udev, 0x91, 0, 0,
buf, 1, DW210X_READ_MSG);
if (ret < 0) {
err("read eeprom failed.");
return -1;
} else {
eepromline[i % 16] = buf[0];
eeprom[i] = buf[0];
}
if ((i % 16) == 15) {
deb_xfer("%02x: ", i - 15);
debug_dump(eepromline, 16, deb_xfer);
}
}
memcpy(mac, eeprom + 16, 6);
return 0;
};
static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{ {
static u8 command_13v[1] = {0x00}; static u8 command_13v[1] = {0x00};
@ -535,6 +640,10 @@ static struct tda10023_config dw3101_tda10023_config = {
.invert = 1, .invert = 1,
}; };
static struct mt312_config zl313_config = {
.demod_address = 0x0e,
};
static int dw2104_frontend_attach(struct dvb_usb_adapter *d) static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
{ {
if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,
@ -596,6 +705,18 @@ static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
return -EIO; return -EIO;
} }
static int s630_frontend_attach(struct dvb_usb_adapter *d)
{
d->fe = dvb_attach(mt312_attach, &zl313_config,
&d->dev->i2c_adap);
if (d->fe != NULL) {
d->fe->ops.set_voltage = dw210x_set_voltage;
info("Attached zl10313!\n");
return 0;
}
return -EIO;
}
static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
{ {
dvb_attach(dvb_pll_attach, adap->fe, 0x60, dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@ -619,123 +740,131 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
return 0; return 0;
} }
static int s630_zl10039_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(zl10039_attach, adap->fe, 0x60,
&adap->dev->i2c_adap);
return 0;
}
static struct dvb_usb_rc_key dw210x_rc_keys[] = { static struct dvb_usb_rc_key dw210x_rc_keys[] = {
{ 0xf8, 0x0a, KEY_Q }, /*power*/ { 0xf80a, KEY_Q }, /*power*/
{ 0xf8, 0x0c, KEY_M }, /*mute*/ { 0xf80c, KEY_M }, /*mute*/
{ 0xf8, 0x11, KEY_1 }, { 0xf811, KEY_1 },
{ 0xf8, 0x12, KEY_2 }, { 0xf812, KEY_2 },
{ 0xf8, 0x13, KEY_3 }, { 0xf813, KEY_3 },
{ 0xf8, 0x14, KEY_4 }, { 0xf814, KEY_4 },
{ 0xf8, 0x15, KEY_5 }, { 0xf815, KEY_5 },
{ 0xf8, 0x16, KEY_6 }, { 0xf816, KEY_6 },
{ 0xf8, 0x17, KEY_7 }, { 0xf817, KEY_7 },
{ 0xf8, 0x18, KEY_8 }, { 0xf818, KEY_8 },
{ 0xf8, 0x19, KEY_9 }, { 0xf819, KEY_9 },
{ 0xf8, 0x10, KEY_0 }, { 0xf810, KEY_0 },
{ 0xf8, 0x1c, KEY_PAGEUP }, /*ch+*/ { 0xf81c, KEY_PAGEUP }, /*ch+*/
{ 0xf8, 0x0f, KEY_PAGEDOWN }, /*ch-*/ { 0xf80f, KEY_PAGEDOWN }, /*ch-*/
{ 0xf8, 0x1a, KEY_O }, /*vol+*/ { 0xf81a, KEY_O }, /*vol+*/
{ 0xf8, 0x0e, KEY_Z }, /*vol-*/ { 0xf80e, KEY_Z }, /*vol-*/
{ 0xf8, 0x04, KEY_R }, /*rec*/ { 0xf804, KEY_R }, /*rec*/
{ 0xf8, 0x09, KEY_D }, /*fav*/ { 0xf809, KEY_D }, /*fav*/
{ 0xf8, 0x08, KEY_BACKSPACE }, /*rewind*/ { 0xf808, KEY_BACKSPACE }, /*rewind*/
{ 0xf8, 0x07, KEY_A }, /*fast*/ { 0xf807, KEY_A }, /*fast*/
{ 0xf8, 0x0b, KEY_P }, /*pause*/ { 0xf80b, KEY_P }, /*pause*/
{ 0xf8, 0x02, KEY_ESC }, /*cancel*/ { 0xf802, KEY_ESC }, /*cancel*/
{ 0xf8, 0x03, KEY_G }, /*tab*/ { 0xf803, KEY_G }, /*tab*/
{ 0xf8, 0x00, KEY_UP }, /*up*/ { 0xf800, KEY_UP }, /*up*/
{ 0xf8, 0x1f, KEY_ENTER }, /*ok*/ { 0xf81f, KEY_ENTER }, /*ok*/
{ 0xf8, 0x01, KEY_DOWN }, /*down*/ { 0xf801, KEY_DOWN }, /*down*/
{ 0xf8, 0x05, KEY_C }, /*cap*/ { 0xf805, KEY_C }, /*cap*/
{ 0xf8, 0x06, KEY_S }, /*stop*/ { 0xf806, KEY_S }, /*stop*/
{ 0xf8, 0x40, KEY_F }, /*full*/ { 0xf840, KEY_F }, /*full*/
{ 0xf8, 0x1e, KEY_W }, /*tvmode*/ { 0xf81e, KEY_W }, /*tvmode*/
{ 0xf8, 0x1b, KEY_B }, /*recall*/ { 0xf81b, KEY_B }, /*recall*/
}; };
static struct dvb_usb_rc_key tevii_rc_keys[] = { static struct dvb_usb_rc_key tevii_rc_keys[] = {
{ 0xf8, 0x0a, KEY_POWER }, { 0xf80a, KEY_POWER },
{ 0xf8, 0x0c, KEY_MUTE }, { 0xf80c, KEY_MUTE },
{ 0xf8, 0x11, KEY_1 }, { 0xf811, KEY_1 },
{ 0xf8, 0x12, KEY_2 }, { 0xf812, KEY_2 },
{ 0xf8, 0x13, KEY_3 }, { 0xf813, KEY_3 },
{ 0xf8, 0x14, KEY_4 }, { 0xf814, KEY_4 },
{ 0xf8, 0x15, KEY_5 }, { 0xf815, KEY_5 },
{ 0xf8, 0x16, KEY_6 }, { 0xf816, KEY_6 },
{ 0xf8, 0x17, KEY_7 }, { 0xf817, KEY_7 },
{ 0xf8, 0x18, KEY_8 }, { 0xf818, KEY_8 },
{ 0xf8, 0x19, KEY_9 }, { 0xf819, KEY_9 },
{ 0xf8, 0x10, KEY_0 }, { 0xf810, KEY_0 },
{ 0xf8, 0x1c, KEY_MENU }, { 0xf81c, KEY_MENU },
{ 0xf8, 0x0f, KEY_VOLUMEDOWN }, { 0xf80f, KEY_VOLUMEDOWN },
{ 0xf8, 0x1a, KEY_LAST }, { 0xf81a, KEY_LAST },
{ 0xf8, 0x0e, KEY_OPEN }, { 0xf80e, KEY_OPEN },
{ 0xf8, 0x04, KEY_RECORD }, { 0xf804, KEY_RECORD },
{ 0xf8, 0x09, KEY_VOLUMEUP }, { 0xf809, KEY_VOLUMEUP },
{ 0xf8, 0x08, KEY_CHANNELUP }, { 0xf808, KEY_CHANNELUP },
{ 0xf8, 0x07, KEY_PVR }, { 0xf807, KEY_PVR },
{ 0xf8, 0x0b, KEY_TIME }, { 0xf80b, KEY_TIME },
{ 0xf8, 0x02, KEY_RIGHT }, { 0xf802, KEY_RIGHT },
{ 0xf8, 0x03, KEY_LEFT }, { 0xf803, KEY_LEFT },
{ 0xf8, 0x00, KEY_UP }, { 0xf800, KEY_UP },
{ 0xf8, 0x1f, KEY_OK }, { 0xf81f, KEY_OK },
{ 0xf8, 0x01, KEY_DOWN }, { 0xf801, KEY_DOWN },
{ 0xf8, 0x05, KEY_TUNER }, { 0xf805, KEY_TUNER },
{ 0xf8, 0x06, KEY_CHANNELDOWN }, { 0xf806, KEY_CHANNELDOWN },
{ 0xf8, 0x40, KEY_PLAYPAUSE }, { 0xf840, KEY_PLAYPAUSE },
{ 0xf8, 0x1e, KEY_REWIND }, { 0xf81e, KEY_REWIND },
{ 0xf8, 0x1b, KEY_FAVORITES }, { 0xf81b, KEY_FAVORITES },
{ 0xf8, 0x1d, KEY_BACK }, { 0xf81d, KEY_BACK },
{ 0xf8, 0x4d, KEY_FASTFORWARD }, { 0xf84d, KEY_FASTFORWARD },
{ 0xf8, 0x44, KEY_EPG }, { 0xf844, KEY_EPG },
{ 0xf8, 0x4c, KEY_INFO }, { 0xf84c, KEY_INFO },
{ 0xf8, 0x41, KEY_AB }, { 0xf841, KEY_AB },
{ 0xf8, 0x43, KEY_AUDIO }, { 0xf843, KEY_AUDIO },
{ 0xf8, 0x45, KEY_SUBTITLE }, { 0xf845, KEY_SUBTITLE },
{ 0xf8, 0x4a, KEY_LIST }, { 0xf84a, KEY_LIST },
{ 0xf8, 0x46, KEY_F1 }, { 0xf846, KEY_F1 },
{ 0xf8, 0x47, KEY_F2 }, { 0xf847, KEY_F2 },
{ 0xf8, 0x5e, KEY_F3 }, { 0xf85e, KEY_F3 },
{ 0xf8, 0x5c, KEY_F4 }, { 0xf85c, KEY_F4 },
{ 0xf8, 0x52, KEY_F5 }, { 0xf852, KEY_F5 },
{ 0xf8, 0x5a, KEY_F6 }, { 0xf85a, KEY_F6 },
{ 0xf8, 0x56, KEY_MODE }, { 0xf856, KEY_MODE },
{ 0xf8, 0x58, KEY_SWITCHVIDEOMODE }, { 0xf858, KEY_SWITCHVIDEOMODE },
}; };
static struct dvb_usb_rc_key tbs_rc_keys[] = { static struct dvb_usb_rc_key tbs_rc_keys[] = {
{ 0xf8, 0x84, KEY_POWER }, { 0xf884, KEY_POWER },
{ 0xf8, 0x94, KEY_MUTE }, { 0xf894, KEY_MUTE },
{ 0xf8, 0x87, KEY_1 }, { 0xf887, KEY_1 },
{ 0xf8, 0x86, KEY_2 }, { 0xf886, KEY_2 },
{ 0xf8, 0x85, KEY_3 }, { 0xf885, KEY_3 },
{ 0xf8, 0x8b, KEY_4 }, { 0xf88b, KEY_4 },
{ 0xf8, 0x8a, KEY_5 }, { 0xf88a, KEY_5 },
{ 0xf8, 0x89, KEY_6 }, { 0xf889, KEY_6 },
{ 0xf8, 0x8f, KEY_7 }, { 0xf88f, KEY_7 },
{ 0xf8, 0x8e, KEY_8 }, { 0xf88e, KEY_8 },
{ 0xf8, 0x8d, KEY_9 }, { 0xf88d, KEY_9 },
{ 0xf8, 0x92, KEY_0 }, { 0xf892, KEY_0 },
{ 0xf8, 0x96, KEY_CHANNELUP }, { 0xf896, KEY_CHANNELUP },
{ 0xf8, 0x91, KEY_CHANNELDOWN }, { 0xf891, KEY_CHANNELDOWN },
{ 0xf8, 0x93, KEY_VOLUMEUP }, { 0xf893, KEY_VOLUMEUP },
{ 0xf8, 0x8c, KEY_VOLUMEDOWN }, { 0xf88c, KEY_VOLUMEDOWN },
{ 0xf8, 0x83, KEY_RECORD }, { 0xf883, KEY_RECORD },
{ 0xf8, 0x98, KEY_PAUSE }, { 0xf898, KEY_PAUSE },
{ 0xf8, 0x99, KEY_OK }, { 0xf899, KEY_OK },
{ 0xf8, 0x9a, KEY_SHUFFLE }, { 0xf89a, KEY_SHUFFLE },
{ 0xf8, 0x81, KEY_UP }, { 0xf881, KEY_UP },
{ 0xf8, 0x90, KEY_LEFT }, { 0xf890, KEY_LEFT },
{ 0xf8, 0x82, KEY_RIGHT }, { 0xf882, KEY_RIGHT },
{ 0xf8, 0x88, KEY_DOWN }, { 0xf888, KEY_DOWN },
{ 0xf8, 0x95, KEY_FAVORITES }, { 0xf895, KEY_FAVORITES },
{ 0xf8, 0x97, KEY_SUBTITLE }, { 0xf897, KEY_SUBTITLE },
{ 0xf8, 0x9d, KEY_ZOOM }, { 0xf89d, KEY_ZOOM },
{ 0xf8, 0x9f, KEY_EXIT }, { 0xf89f, KEY_EXIT },
{ 0xf8, 0x9e, KEY_MENU }, { 0xf89e, KEY_MENU },
{ 0xf8, 0x9c, KEY_EPG }, { 0xf89c, KEY_EPG },
{ 0xf8, 0x80, KEY_PREVIOUS }, { 0xf880, KEY_PREVIOUS },
{ 0xf8, 0x9b, KEY_MODE } { 0xf89b, KEY_MODE }
}; };
static struct dvb_usb_rc_keys_table keys_tables[] = { static struct dvb_usb_rc_keys_table keys_tables[] = {
@ -763,9 +892,9 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
} }
*state = REMOTE_NO_KEY_PRESSED; *state = REMOTE_NO_KEY_PRESSED;
if (dw2102_i2c_transfer(&d->i2c_adap, &msg, 1) == 1) { if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
for (i = 0; i < keymap_size ; i++) { for (i = 0; i < keymap_size ; i++) {
if (keymap[i].data == msg.buf[0]) { if (rc5_data(&keymap[i]) == msg.buf[0]) {
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
*event = keymap[i].event; *event = keymap[i].event;
break; break;
@ -792,6 +921,7 @@ static struct usb_device_id dw2102_table[] = {
{USB_DEVICE(0x9022, USB_PID_TEVII_S650)}, {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
{USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)}, {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)}, {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
{USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
{ } { }
}; };
@ -806,6 +936,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
const struct firmware *fw; const struct firmware *fw;
const char *filename = "dvb-usb-dw2101.fw"; const char *filename = "dvb-usb-dw2101.fw";
switch (dev->descriptor.idProduct) { switch (dev->descriptor.idProduct) {
case 0x2101: case 0x2101:
ret = request_firmware(&fw, filename, &dev->dev); ret = request_firmware(&fw, filename, &dev->dev);
@ -1053,6 +1184,48 @@ static struct dvb_usb_device_properties dw3101_properties = {
} }
}; };
static struct dvb_usb_device_properties s630_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-s630.fw",
.no_reconnect = 1,
.i2c_algo = &s630_i2c_algo,
.rc_key_map = tevii_rc_keys,
.rc_key_map_size = ARRAY_SIZE(tevii_rc_keys),
.rc_interval = 150,
.rc_query = dw2102_rc_query,
.generic_bulk_ctrl_endpoint = 0x81,
.num_adapters = 1,
.download_firmware = dw2102_load_firmware,
.read_mac_address = s630_read_mac_address,
.adapter = {
{
.frontend_attach = s630_frontend_attach,
.streaming_ctrl = NULL,
.tuner_attach = s630_zl10039_tuner_attach,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
}
},
.num_device_descs = 1,
.devices = {
{"TeVii S630 USB",
{&dw2102_table[6], NULL},
{NULL},
},
}
};
static int dw2102_probe(struct usb_interface *intf, static int dw2102_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
@ -1061,6 +1234,8 @@ static int dw2102_probe(struct usb_interface *intf,
0 == dvb_usb_device_init(intf, &dw2104_properties, 0 == dvb_usb_device_init(intf, &dw2104_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &dw3101_properties, 0 == dvb_usb_device_init(intf, &dw3101_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &s630_properties,
THIS_MODULE, NULL, adapter_nr)) { THIS_MODULE, NULL, adapter_nr)) {
return 0; return 0;
} }
@ -1094,6 +1269,6 @@ module_exit(dw2102_module_exit);
MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
" DVB-C 3101 USB2.0," " DVB-C 3101 USB2.0,"
" TeVii S600, S650 USB2.0 devices"); " TeVii S600, S630, S650 USB2.0 devices");
MODULE_VERSION("0.1"); MODULE_VERSION("0.1");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View file

@ -140,7 +140,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
goto unlock; goto unlock;
for (i = 0; i < d->props.rc_key_map_size; i++) for (i = 0; i < d->props.rc_key_map_size; i++)
if (d->props.rc_key_map[i].data == rc_state[1]) { if (rc5_data(&d->props.rc_key_map[i]) == rc_state[1]) {
*event = d->props.rc_key_map[i].event; *event = d->props.rc_key_map[i].event;
switch(rc_state[0]) { switch(rc_state[0]) {
@ -562,42 +562,42 @@ static struct m920x_inits tvwalkertwin_rc_init [] = {
/* ir keymaps */ /* ir keymaps */
static struct dvb_usb_rc_key megasky_rc_keys [] = { static struct dvb_usb_rc_key megasky_rc_keys [] = {
{ 0x0, 0x12, KEY_POWER }, { 0x0012, KEY_POWER },
{ 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */ { 0x001e, KEY_CYCLEWINDOWS }, /* min/max */
{ 0x0, 0x02, KEY_CHANNELUP }, { 0x0002, KEY_CHANNELUP },
{ 0x0, 0x05, KEY_CHANNELDOWN }, { 0x0005, KEY_CHANNELDOWN },
{ 0x0, 0x03, KEY_VOLUMEUP }, { 0x0003, KEY_VOLUMEUP },
{ 0x0, 0x06, KEY_VOLUMEDOWN }, { 0x0006, KEY_VOLUMEDOWN },
{ 0x0, 0x04, KEY_MUTE }, { 0x0004, KEY_MUTE },
{ 0x0, 0x07, KEY_OK }, /* TS */ { 0x0007, KEY_OK }, /* TS */
{ 0x0, 0x08, KEY_STOP }, { 0x0008, KEY_STOP },
{ 0x0, 0x09, KEY_MENU }, /* swap */ { 0x0009, KEY_MENU }, /* swap */
{ 0x0, 0x0a, KEY_REWIND }, { 0x000a, KEY_REWIND },
{ 0x0, 0x1b, KEY_PAUSE }, { 0x001b, KEY_PAUSE },
{ 0x0, 0x1f, KEY_FASTFORWARD }, { 0x001f, KEY_FASTFORWARD },
{ 0x0, 0x0c, KEY_RECORD }, { 0x000c, KEY_RECORD },
{ 0x0, 0x0d, KEY_CAMERA }, /* screenshot */ { 0x000d, KEY_CAMERA }, /* screenshot */
{ 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ { 0x000e, KEY_COFFEE }, /* "MTS" */
}; };
static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = { static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = {
{ 0x0, 0x01, KEY_ZOOM }, /* Full Screen */ { 0x0001, KEY_ZOOM }, /* Full Screen */
{ 0x0, 0x02, KEY_CAMERA }, /* snapshot */ { 0x0002, KEY_CAMERA }, /* snapshot */
{ 0x0, 0x03, KEY_MUTE }, { 0x0003, KEY_MUTE },
{ 0x0, 0x04, KEY_REWIND }, { 0x0004, KEY_REWIND },
{ 0x0, 0x05, KEY_PLAYPAUSE }, /* Play/Pause */ { 0x0005, KEY_PLAYPAUSE }, /* Play/Pause */
{ 0x0, 0x06, KEY_FASTFORWARD }, { 0x0006, KEY_FASTFORWARD },
{ 0x0, 0x07, KEY_RECORD }, { 0x0007, KEY_RECORD },
{ 0x0, 0x08, KEY_STOP }, { 0x0008, KEY_STOP },
{ 0x0, 0x09, KEY_TIME }, /* Timeshift */ { 0x0009, KEY_TIME }, /* Timeshift */
{ 0x0, 0x0c, KEY_COFFEE }, /* Recall */ { 0x000c, KEY_COFFEE }, /* Recall */
{ 0x0, 0x0e, KEY_CHANNELUP }, { 0x000e, KEY_CHANNELUP },
{ 0x0, 0x12, KEY_POWER }, { 0x0012, KEY_POWER },
{ 0x0, 0x15, KEY_MENU }, /* source */ { 0x0015, KEY_MENU }, /* source */
{ 0x0, 0x18, KEY_CYCLEWINDOWS }, /* TWIN PIP */ { 0x0018, KEY_CYCLEWINDOWS }, /* TWIN PIP */
{ 0x0, 0x1a, KEY_CHANNELDOWN }, { 0x001a, KEY_CHANNELDOWN },
{ 0x0, 0x1b, KEY_VOLUMEDOWN }, { 0x001b, KEY_VOLUMEDOWN },
{ 0x0, 0x1e, KEY_VOLUMEUP }, { 0x001e, KEY_VOLUMEUP },
}; };
/* DVB USB Driver stuff */ /* DVB USB Driver stuff */

View file

@ -22,51 +22,51 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/* Hauppauge NOVA-T USB2 keys */ /* Hauppauge NOVA-T USB2 keys */
static struct dvb_usb_rc_key haupp_rc_keys [] = { static struct dvb_usb_rc_key haupp_rc_keys [] = {
{ 0x1e, 0x00, KEY_0 }, { 0x1e00, KEY_0 },
{ 0x1e, 0x01, KEY_1 }, { 0x1e01, KEY_1 },
{ 0x1e, 0x02, KEY_2 }, { 0x1e02, KEY_2 },
{ 0x1e, 0x03, KEY_3 }, { 0x1e03, KEY_3 },
{ 0x1e, 0x04, KEY_4 }, { 0x1e04, KEY_4 },
{ 0x1e, 0x05, KEY_5 }, { 0x1e05, KEY_5 },
{ 0x1e, 0x06, KEY_6 }, { 0x1e06, KEY_6 },
{ 0x1e, 0x07, KEY_7 }, { 0x1e07, KEY_7 },
{ 0x1e, 0x08, KEY_8 }, { 0x1e08, KEY_8 },
{ 0x1e, 0x09, KEY_9 }, { 0x1e09, KEY_9 },
{ 0x1e, 0x0a, KEY_KPASTERISK }, { 0x1e0a, KEY_KPASTERISK },
{ 0x1e, 0x0b, KEY_RED }, { 0x1e0b, KEY_RED },
{ 0x1e, 0x0c, KEY_RADIO }, { 0x1e0c, KEY_RADIO },
{ 0x1e, 0x0d, KEY_MENU }, { 0x1e0d, KEY_MENU },
{ 0x1e, 0x0e, KEY_GRAVE }, /* # */ { 0x1e0e, KEY_GRAVE }, /* # */
{ 0x1e, 0x0f, KEY_MUTE }, { 0x1e0f, KEY_MUTE },
{ 0x1e, 0x10, KEY_VOLUMEUP }, { 0x1e10, KEY_VOLUMEUP },
{ 0x1e, 0x11, KEY_VOLUMEDOWN }, { 0x1e11, KEY_VOLUMEDOWN },
{ 0x1e, 0x12, KEY_CHANNEL }, { 0x1e12, KEY_CHANNEL },
{ 0x1e, 0x14, KEY_UP }, { 0x1e14, KEY_UP },
{ 0x1e, 0x15, KEY_DOWN }, { 0x1e15, KEY_DOWN },
{ 0x1e, 0x16, KEY_LEFT }, { 0x1e16, KEY_LEFT },
{ 0x1e, 0x17, KEY_RIGHT }, { 0x1e17, KEY_RIGHT },
{ 0x1e, 0x18, KEY_VIDEO }, { 0x1e18, KEY_VIDEO },
{ 0x1e, 0x19, KEY_AUDIO }, { 0x1e19, KEY_AUDIO },
{ 0x1e, 0x1a, KEY_MEDIA }, { 0x1e1a, KEY_MEDIA },
{ 0x1e, 0x1b, KEY_EPG }, { 0x1e1b, KEY_EPG },
{ 0x1e, 0x1c, KEY_TV }, { 0x1e1c, KEY_TV },
{ 0x1e, 0x1e, KEY_NEXT }, { 0x1e1e, KEY_NEXT },
{ 0x1e, 0x1f, KEY_BACK }, { 0x1e1f, KEY_BACK },
{ 0x1e, 0x20, KEY_CHANNELUP }, { 0x1e20, KEY_CHANNELUP },
{ 0x1e, 0x21, KEY_CHANNELDOWN }, { 0x1e21, KEY_CHANNELDOWN },
{ 0x1e, 0x24, KEY_LAST }, /* Skip backwards */ { 0x1e24, KEY_LAST }, /* Skip backwards */
{ 0x1e, 0x25, KEY_OK }, { 0x1e25, KEY_OK },
{ 0x1e, 0x29, KEY_BLUE}, { 0x1e29, KEY_BLUE},
{ 0x1e, 0x2e, KEY_GREEN }, { 0x1e2e, KEY_GREEN },
{ 0x1e, 0x30, KEY_PAUSE }, { 0x1e30, KEY_PAUSE },
{ 0x1e, 0x32, KEY_REWIND }, { 0x1e32, KEY_REWIND },
{ 0x1e, 0x34, KEY_FASTFORWARD }, { 0x1e34, KEY_FASTFORWARD },
{ 0x1e, 0x35, KEY_PLAY }, { 0x1e35, KEY_PLAY },
{ 0x1e, 0x36, KEY_STOP }, { 0x1e36, KEY_STOP },
{ 0x1e, 0x37, KEY_RECORD }, { 0x1e37, KEY_RECORD },
{ 0x1e, 0x38, KEY_YELLOW }, { 0x1e38, KEY_YELLOW },
{ 0x1e, 0x3b, KEY_GOTO }, { 0x1e3b, KEY_GOTO },
{ 0x1e, 0x3d, KEY_POWER }, { 0x1e3d, KEY_POWER },
}; };
/* Firmware bug? sometimes, when a new key is pressed, the previous pressed key /* Firmware bug? sometimes, when a new key is pressed, the previous pressed key
@ -92,10 +92,11 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
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); 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++) { for (i = 0; i < ARRAY_SIZE(haupp_rc_keys); i++) {
if (haupp_rc_keys[i].data == data && if (rc5_data(&haupp_rc_keys[i]) == data &&
haupp_rc_keys[i].custom == custom) { rc5_custom(&haupp_rc_keys[i]) == custom) {
deb_rc("c: %x, d: %x\n",haupp_rc_keys[i].data,haupp_rc_keys[i].custom); deb_rc("c: %x, d: %x\n", rc5_data(&haupp_rc_keys[i]),
rc5_custom(&haupp_rc_keys[i]));
*event = haupp_rc_keys[i].event; *event = haupp_rc_keys[i].event;
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;

View file

@ -332,32 +332,32 @@ static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)
} }
static struct dvb_usb_rc_key opera1_rc_keys[] = { static struct dvb_usb_rc_key opera1_rc_keys[] = {
{0x5f, 0xa0, KEY_1}, {0x5fa0, KEY_1},
{0x51, 0xaf, KEY_2}, {0x51af, KEY_2},
{0x5d, 0xa2, KEY_3}, {0x5da2, KEY_3},
{0x41, 0xbe, KEY_4}, {0x41be, KEY_4},
{0x0b, 0xf5, KEY_5}, {0x0bf5, KEY_5},
{0x43, 0xbd, KEY_6}, {0x43bd, KEY_6},
{0x47, 0xb8, KEY_7}, {0x47b8, KEY_7},
{0x49, 0xb6, KEY_8}, {0x49b6, KEY_8},
{0x05, 0xfa, KEY_9}, {0x05fa, KEY_9},
{0x45, 0xba, KEY_0}, {0x45ba, KEY_0},
{0x09, 0xf6, KEY_UP}, /*chanup */ {0x09f6, KEY_UP}, /*chanup */
{0x1b, 0xe5, KEY_DOWN}, /*chandown */ {0x1be5, KEY_DOWN}, /*chandown */
{0x5d, 0xa3, KEY_LEFT}, /*voldown */ {0x5da3, KEY_LEFT}, /*voldown */
{0x5f, 0xa1, KEY_RIGHT}, /*volup */ {0x5fa1, KEY_RIGHT}, /*volup */
{0x07, 0xf8, KEY_SPACE}, /*tab */ {0x07f8, KEY_SPACE}, /*tab */
{0x1f, 0xe1, KEY_ENTER}, /*play ok */ {0x1fe1, KEY_ENTER}, /*play ok */
{0x1b, 0xe4, KEY_Z}, /*zoom */ {0x1be4, KEY_Z}, /*zoom */
{0x59, 0xa6, KEY_M}, /*mute */ {0x59a6, KEY_M}, /*mute */
{0x5b, 0xa5, KEY_F}, /*tv/f */ {0x5ba5, KEY_F}, /*tv/f */
{0x19, 0xe7, KEY_R}, /*rec */ {0x19e7, KEY_R}, /*rec */
{0x01, 0xfe, KEY_S}, /*Stop */ {0x01fe, KEY_S}, /*Stop */
{0x03, 0xfd, KEY_P}, /*pause */ {0x03fd, KEY_P}, /*pause */
{0x03, 0xfc, KEY_W}, /*<- -> */ {0x03fc, KEY_W}, /*<- -> */
{0x07, 0xf9, KEY_C}, /*capture */ {0x07f9, KEY_C}, /*capture */
{0x47, 0xb9, KEY_Q}, /*exit */ {0x47b9, KEY_Q}, /*exit */
{0x43, 0xbc, KEY_O}, /*power */ {0x43bc, KEY_O}, /*power */
}; };
@ -405,8 +405,7 @@ static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
send_key = (send_key & 0xffff) | 0x0100; send_key = (send_key & 0xffff) | 0x0100;
for (i = 0; i < ARRAY_SIZE(opera1_rc_keys); i++) { for (i = 0; i < ARRAY_SIZE(opera1_rc_keys); i++) {
if ((opera1_rc_keys[i].custom * 256 + if (rc5_scan(&opera1_rc_keys[i]) == (send_key & 0xffff)) {
opera1_rc_keys[i].data) == (send_key & 0xffff)) {
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
*event = opera1_rc_keys[i].event; *event = opera1_rc_keys[i].event;
opst->last_key_pressed = opst->last_key_pressed =

View file

@ -175,8 +175,8 @@ static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
/* keys for the enclosed remote control */ /* keys for the enclosed remote control */
static struct dvb_usb_rc_key vp702x_rc_keys[] = { static struct dvb_usb_rc_key vp702x_rc_keys[] = {
{ 0x00, 0x01, KEY_1 }, { 0x0001, KEY_1 },
{ 0x00, 0x02, KEY_2 }, { 0x0002, KEY_2 },
}; };
/* remote control stuff (does not work with my box) */ /* remote control stuff (does not work with my box) */
@ -198,7 +198,7 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
} }
for (i = 0; i < ARRAY_SIZE(vp702x_rc_keys); i++) for (i = 0; i < ARRAY_SIZE(vp702x_rc_keys); i++)
if (vp702x_rc_keys[i].custom == key[1]) { if (rc5_custom(&vp702x_rc_keys[i]) == key[1]) {
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
*event = vp702x_rc_keys[i].event; *event = vp702x_rc_keys[i].event;
break; break;

View file

@ -100,56 +100,56 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
/* The keymapping struct. Somehow this should be loaded to the driver, but /* The keymapping struct. Somehow this should be loaded to the driver, but
* currently it is hardcoded. */ * currently it is hardcoded. */
static struct dvb_usb_rc_key vp7045_rc_keys[] = { static struct dvb_usb_rc_key vp7045_rc_keys[] = {
{ 0x00, 0x16, KEY_POWER }, { 0x0016, KEY_POWER },
{ 0x00, 0x10, KEY_MUTE }, { 0x0010, KEY_MUTE },
{ 0x00, 0x03, KEY_1 }, { 0x0003, KEY_1 },
{ 0x00, 0x01, KEY_2 }, { 0x0001, KEY_2 },
{ 0x00, 0x06, KEY_3 }, { 0x0006, KEY_3 },
{ 0x00, 0x09, KEY_4 }, { 0x0009, KEY_4 },
{ 0x00, 0x1d, KEY_5 }, { 0x001d, KEY_5 },
{ 0x00, 0x1f, KEY_6 }, { 0x001f, KEY_6 },
{ 0x00, 0x0d, KEY_7 }, { 0x000d, KEY_7 },
{ 0x00, 0x19, KEY_8 }, { 0x0019, KEY_8 },
{ 0x00, 0x1b, KEY_9 }, { 0x001b, KEY_9 },
{ 0x00, 0x15, KEY_0 }, { 0x0015, KEY_0 },
{ 0x00, 0x05, KEY_CHANNELUP }, { 0x0005, KEY_CHANNELUP },
{ 0x00, 0x02, KEY_CHANNELDOWN }, { 0x0002, KEY_CHANNELDOWN },
{ 0x00, 0x1e, KEY_VOLUMEUP }, { 0x001e, KEY_VOLUMEUP },
{ 0x00, 0x0a, KEY_VOLUMEDOWN }, { 0x000a, KEY_VOLUMEDOWN },
{ 0x00, 0x11, KEY_RECORD }, { 0x0011, KEY_RECORD },
{ 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */ { 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */
{ 0x00, 0x14, KEY_PLAY }, { 0x0014, KEY_PLAY },
{ 0x00, 0x1a, KEY_STOP }, { 0x001a, KEY_STOP },
{ 0x00, 0x40, KEY_REWIND }, { 0x0040, KEY_REWIND },
{ 0x00, 0x12, KEY_FASTFORWARD }, { 0x0012, KEY_FASTFORWARD },
{ 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */ { 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */
{ 0x00, 0x4c, KEY_PAUSE }, { 0x004c, KEY_PAUSE },
{ 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */ { 0x004d, KEY_SCREEN }, /* Full screen mode. */
{ 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ { 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
{ 0x00, 0x0c, KEY_CANCEL }, /* Cancel */ { 0x000c, KEY_CANCEL }, /* Cancel */
{ 0x00, 0x1c, KEY_EPG }, /* EPG */ { 0x001c, KEY_EPG }, /* EPG */
{ 0x00, 0x00, KEY_TAB }, /* Tab */ { 0x0000, KEY_TAB }, /* Tab */
{ 0x00, 0x48, KEY_INFO }, /* Preview */ { 0x0048, KEY_INFO }, /* Preview */
{ 0x00, 0x04, KEY_LIST }, /* RecordList */ { 0x0004, KEY_LIST }, /* RecordList */
{ 0x00, 0x0f, KEY_TEXT }, /* Teletext */ { 0x000f, KEY_TEXT }, /* Teletext */
{ 0x00, 0x41, KEY_PREVIOUSSONG }, { 0x0041, KEY_PREVIOUSSONG },
{ 0x00, 0x42, KEY_NEXTSONG }, { 0x0042, KEY_NEXTSONG },
{ 0x00, 0x4b, KEY_UP }, { 0x004b, KEY_UP },
{ 0x00, 0x51, KEY_DOWN }, { 0x0051, KEY_DOWN },
{ 0x00, 0x4e, KEY_LEFT }, { 0x004e, KEY_LEFT },
{ 0x00, 0x52, KEY_RIGHT }, { 0x0052, KEY_RIGHT },
{ 0x00, 0x4f, KEY_ENTER }, { 0x004f, KEY_ENTER },
{ 0x00, 0x13, KEY_CANCEL }, { 0x0013, KEY_CANCEL },
{ 0x00, 0x4a, KEY_CLEAR }, { 0x004a, KEY_CLEAR },
{ 0x00, 0x54, KEY_PRINT }, /* Capture */ { 0x0054, KEY_PRINT }, /* Capture */
{ 0x00, 0x43, KEY_SUBTITLE }, /* Subtitle/CC */ { 0x0043, KEY_SUBTITLE }, /* Subtitle/CC */
{ 0x00, 0x08, KEY_VIDEO }, /* A/V */ { 0x0008, KEY_VIDEO }, /* A/V */
{ 0x00, 0x07, KEY_SLEEP }, /* Hibernate */ { 0x0007, KEY_SLEEP }, /* Hibernate */
{ 0x00, 0x45, KEY_ZOOM }, /* Zoom+ */ { 0x0045, KEY_ZOOM }, /* Zoom+ */
{ 0x00, 0x18, KEY_RED}, { 0x0018, KEY_RED},
{ 0x00, 0x53, KEY_GREEN}, { 0x0053, KEY_GREEN},
{ 0x00, 0x5e, KEY_YELLOW}, { 0x005e, KEY_YELLOW},
{ 0x00, 0x5f, KEY_BLUE} { 0x005f, KEY_BLUE}
}; };
static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
@ -166,7 +166,7 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
} }
for (i = 0; i < ARRAY_SIZE(vp7045_rc_keys); i++) for (i = 0; i < ARRAY_SIZE(vp7045_rc_keys); i++)
if (vp7045_rc_keys[i].data == key) { if (rc5_data(&vp7045_rc_keys[i]) == key) {
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
*event = vp7045_rc_keys[i].event; *event = vp7045_rc_keys[i].event;
break; break;

View file

@ -89,15 +89,33 @@ struct avc_response_frame {
u8 operand[509]; u8 operand[509];
}; };
#define AVC_DEBUG_FCP_SUBACTIONS 1 #define AVC_DEBUG_READ_DESCRIPTOR 0x0001
#define AVC_DEBUG_FCP_PAYLOADS 2 #define AVC_DEBUG_DSIT 0x0002
#define AVC_DEBUG_DSD 0x0004
#define AVC_DEBUG_REGISTER_REMOTE_CONTROL 0x0008
#define AVC_DEBUG_LNB_CONTROL 0x0010
#define AVC_DEBUG_TUNE_QPSK 0x0020
#define AVC_DEBUG_TUNE_QPSK2 0x0040
#define AVC_DEBUG_HOST2CA 0x0080
#define AVC_DEBUG_CA2HOST 0x0100
#define AVC_DEBUG_APPLICATION_PMT 0x4000
#define AVC_DEBUG_FCP_PAYLOADS 0x8000
static int avc_debug; static int avc_debug;
module_param_named(debug, avc_debug, int, 0644); module_param_named(debug, avc_debug, int, 0644);
MODULE_PARM_DESC(debug, "Verbose logging (default = 0" MODULE_PARM_DESC(debug, "Verbose logging (none = 0"
", FCP subactions = " __stringify(AVC_DEBUG_FCP_SUBACTIONS) ", FCP subactions"
", FCP payloads = " __stringify(AVC_DEBUG_FCP_PAYLOADS) ": READ DESCRIPTOR = " __stringify(AVC_DEBUG_READ_DESCRIPTOR)
", or all = -1)"); ", DSIT = " __stringify(AVC_DEBUG_DSIT)
", REGISTER_REMOTE_CONTROL = " __stringify(AVC_DEBUG_REGISTER_REMOTE_CONTROL)
", LNB CONTROL = " __stringify(AVC_DEBUG_LNB_CONTROL)
", TUNE QPSK = " __stringify(AVC_DEBUG_TUNE_QPSK)
", TUNE QPSK2 = " __stringify(AVC_DEBUG_TUNE_QPSK2)
", HOST2CA = " __stringify(AVC_DEBUG_HOST2CA)
", CA2HOST = " __stringify(AVC_DEBUG_CA2HOST)
"; Application sent PMT = " __stringify(AVC_DEBUG_APPLICATION_PMT)
", FCP payloads = " __stringify(AVC_DEBUG_FCP_PAYLOADS)
", or a combination, or all = -1)");
static const char *debug_fcp_ctype(unsigned int ctype) static const char *debug_fcp_ctype(unsigned int ctype)
{ {
@ -118,48 +136,70 @@ static const char *debug_fcp_opcode(unsigned int opcode,
const u8 *data, int length) const u8 *data, int length)
{ {
switch (opcode) { switch (opcode) {
case AVC_OPCODE_VENDOR: break; case AVC_OPCODE_VENDOR:
case AVC_OPCODE_READ_DESCRIPTOR: return "ReadDescriptor"; break;
case AVC_OPCODE_DSIT: return "DirectSelectInfo.Type"; case AVC_OPCODE_READ_DESCRIPTOR:
case AVC_OPCODE_DSD: return "DirectSelectData"; return avc_debug & AVC_DEBUG_READ_DESCRIPTOR ?
default: return "?"; "ReadDescriptor" : NULL;
case AVC_OPCODE_DSIT:
return avc_debug & AVC_DEBUG_DSIT ?
"DirectSelectInfo.Type" : NULL;
case AVC_OPCODE_DSD:
return avc_debug & AVC_DEBUG_DSD ? "DirectSelectData" : NULL;
default:
return "Unknown";
} }
if (length < 7 || if (length < 7 ||
data[3] != SFE_VENDOR_DE_COMPANYID_0 || data[3] != SFE_VENDOR_DE_COMPANYID_0 ||
data[4] != SFE_VENDOR_DE_COMPANYID_1 || data[4] != SFE_VENDOR_DE_COMPANYID_1 ||
data[5] != SFE_VENDOR_DE_COMPANYID_2) data[5] != SFE_VENDOR_DE_COMPANYID_2)
return "Vendor"; return "Vendor/Unknown";
switch (data[6]) { switch (data[6]) {
case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC"; case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL:
case SFE_VENDOR_OPCODE_LNB_CONTROL: return "LNBControl"; return avc_debug & AVC_DEBUG_REGISTER_REMOTE_CONTROL ?
case SFE_VENDOR_OPCODE_TUNE_QPSK: return "TuneQPSK"; "RegisterRC" : NULL;
case SFE_VENDOR_OPCODE_TUNE_QPSK2: return "TuneQPSK2"; case SFE_VENDOR_OPCODE_LNB_CONTROL:
case SFE_VENDOR_OPCODE_HOST2CA: return "Host2CA"; return avc_debug & AVC_DEBUG_LNB_CONTROL ? "LNBControl" : NULL;
case SFE_VENDOR_OPCODE_CA2HOST: return "CA2Host"; case SFE_VENDOR_OPCODE_TUNE_QPSK:
return avc_debug & AVC_DEBUG_TUNE_QPSK ? "TuneQPSK" : NULL;
case SFE_VENDOR_OPCODE_TUNE_QPSK2:
return avc_debug & AVC_DEBUG_TUNE_QPSK2 ? "TuneQPSK2" : NULL;
case SFE_VENDOR_OPCODE_HOST2CA:
return avc_debug & AVC_DEBUG_HOST2CA ? "Host2CA" : NULL;
case SFE_VENDOR_OPCODE_CA2HOST:
return avc_debug & AVC_DEBUG_CA2HOST ? "CA2Host" : NULL;
} }
return "Vendor"; return "Vendor/Unknown";
} }
static void debug_fcp(const u8 *data, int length) static void debug_fcp(const u8 *data, int length)
{ {
unsigned int subunit_type, subunit_id, op; unsigned int subunit_type, subunit_id, opcode;
const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> "; const char *op, *prefix;
if (avc_debug & AVC_DEBUG_FCP_SUBACTIONS) { prefix = data[0] > 7 ? "FCP <- " : "FCP -> ";
subunit_type = data[1] >> 3; subunit_type = data[1] >> 3;
subunit_id = data[1] & 7; subunit_id = data[1] & 7;
op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; opcode = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
op = debug_fcp_opcode(opcode, data, length);
if (op) {
printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n", printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
prefix, subunit_type, subunit_id, length, prefix, subunit_type, subunit_id, length,
debug_fcp_ctype(data[0]), debug_fcp_ctype(data[0]), op);
debug_fcp_opcode(op, data, length)); if (avc_debug & AVC_DEBUG_FCP_PAYLOADS)
print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE,
16, 1, data, length, false);
} }
}
if (avc_debug & AVC_DEBUG_FCP_PAYLOADS) static void debug_pmt(char *msg, int length)
print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1, {
data, length, false); printk(KERN_INFO "APP PMT -> l=%d\n", length);
print_hex_dump(KERN_INFO, "APP PMT -> ", DUMP_PREFIX_NONE,
16, 1, msg, length, false);
} }
static int __avc_write(struct firedtv *fdtv, static int __avc_write(struct firedtv *fdtv,
@ -254,6 +294,26 @@ int avc_recv(struct firedtv *fdtv, void *data, size_t length)
return 0; return 0;
} }
static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
{
int i, n, pos = 1;
for (i = 0, n = 0; i < 16; i++) {
if (test_bit(i, &fdtv->channel_active)) {
operand[pos++] = 0x13; /* flowfunction relay */
operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
operand[pos++] = (fdtv->channel_pid[i] >> 8) & 0x1f;
operand[pos++] = fdtv->channel_pid[i] & 0xff;
operand[pos++] = 0x00; /* tableID */
operand[pos++] = 0x00; /* filter_length */
n++;
}
}
operand[0] = n;
return pos;
}
/* /*
* tuning command for setting the relative LNB frequency * tuning command for setting the relative LNB frequency
* (not supported by the AVC standard) * (not supported by the AVC standard)
@ -316,7 +376,8 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
} }
} }
static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params, static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
struct dvb_frontend_parameters *params,
struct avc_command_frame *c) struct avc_command_frame *c)
{ {
c->opcode = AVC_OPCODE_DSD; c->opcode = AVC_OPCODE_DSD;
@ -378,13 +439,13 @@ static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params,
c->operand[20] = 0x00; c->operand[20] = 0x00;
c->operand[21] = 0x00; c->operand[21] = 0x00;
/* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
c->operand[22] = 0x00;
c->length = 28; /* Add PIDs to filter */
c->length = ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4);
} }
static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params, static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
struct dvb_frontend_parameters *params,
struct avc_command_frame *c) struct avc_command_frame *c)
{ {
struct dvb_ofdm_parameters *ofdm = &params->u.ofdm; struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
@ -481,10 +542,9 @@ static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params,
c->operand[15] = 0x00; /* network_ID[0] */ c->operand[15] = 0x00; /* network_ID[0] */
c->operand[16] = 0x00; /* network_ID[1] */ c->operand[16] = 0x00; /* network_ID[1] */
/* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
c->operand[17] = 0x00;
c->length = 24; /* Add PIDs to filter */
c->length = ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4);
} }
int avc_tuner_dsd(struct firedtv *fdtv, int avc_tuner_dsd(struct firedtv *fdtv,
@ -502,8 +562,8 @@ int avc_tuner_dsd(struct firedtv *fdtv,
switch (fdtv->type) { switch (fdtv->type) {
case FIREDTV_DVB_S: case FIREDTV_DVB_S:
case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break; case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break;
case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(params, c); break; case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params, c); break;
case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(params, c); break; case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params, c); break;
default: default:
BUG(); BUG();
} }
@ -963,6 +1023,9 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
int es_info_length; int es_info_length;
int crc32_csum; int crc32_csum;
if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
debug_pmt(msg, length);
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
c->ctype = AVC_CTYPE_CONTROL; c->ctype = AVC_CTYPE_CONTROL;

View file

@ -81,6 +81,13 @@ config DVB_ZL10036
help help
A DVB-S tuner module. Say Y when you want to support this frontend. A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_ZL10039
tristate "Zarlink ZL10039 silicon tuner"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_S5H1420 config DVB_S5H1420
tristate "Samsung S5H1420 based" tristate "Samsung S5H1420 based"
depends on DVB_CORE && I2C depends on DVB_CORE && I2C

View file

@ -31,6 +31,7 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o
obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
obj-$(CONFIG_DVB_MT352) += mt352.o obj-$(CONFIG_DVB_MT352) += mt352.o
obj-$(CONFIG_DVB_ZL10036) += zl10036.o obj-$(CONFIG_DVB_ZL10036) += zl10036.o
obj-$(CONFIG_DVB_ZL10039) += zl10039.o
obj-$(CONFIG_DVB_ZL10353) += zl10353.o obj-$(CONFIG_DVB_ZL10353) += zl10353.o
obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_CX22702) += cx22702.o
obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o

View file

@ -155,7 +155,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet
p->hierarchy_information > HIERARCHY_4) p->hierarchy_information > HIERARCHY_4)
return -EINVAL; return -EINVAL;
if (p->bandwidth < BANDWIDTH_8_MHZ && p->bandwidth > BANDWIDTH_6_MHZ) if (p->bandwidth < BANDWIDTH_8_MHZ || p->bandwidth > BANDWIDTH_6_MHZ)
return -EINVAL; return -EINVAL;
if (p->bandwidth == BANDWIDTH_7_MHZ) if (p->bandwidth == BANDWIDTH_7_MHZ)

View file

@ -303,6 +303,7 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f)
{ {
s32 N; s32 N;
s64 F; s64 F;
u64 dividend;
u8 R, r; u8 R, r;
u8 vcodiv; u8 vcodiv;
u8 factor; u8 factor;
@ -346,7 +347,10 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f)
F = freq_hz; F = freq_hz;
F *= (u64) (R * vcodiv * 262144); F *= (u64) (R * vcodiv * 262144);
dprintk("1 N: %d, F: %lld, R: %d\n", N, (long long)F, R); dprintk("1 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
do_div(F, state->config->xtal_khz*1000 * factor * 2); /* do_div needs an u64 as first argument */
dividend = F;
do_div(dividend, state->config->xtal_khz * 1000 * factor * 2);
F = dividend;
dprintk("2 N: %d, F: %lld, R: %d\n", N, (long long)F, R); dprintk("2 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
F -= (N + 32) * 262144; F -= (N + 32) * 262144;

View file

@ -458,7 +458,7 @@ static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
/* check if symbol rate is within limits */ /* check if symbol rate is within limits */
if ((srate > state->frontend.ops.info.symbol_rate_max) || if ((srate > state->frontend.ops.info.symbol_rate_max) ||
(srate < state->frontend.ops.info.symbol_rate_min)) (srate < state->frontend.ops.info.symbol_rate_min))
return -EOPNOTSUPP;; return -EOPNOTSUPP;
/* choose the sampling rate high enough for the required operation, /* choose the sampling rate high enough for the required operation,
while optimizing the power consumed by the demodulator */ while optimizing the power consumed by the demodulator */

View file

@ -167,7 +167,7 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
break; break;
case BAND_SBAND: case BAND_SBAND:
LO4_SET_VCO_HFDIV(lo4, 0, 0); LO4_SET_VCO_HFDIV(lo4, 0, 0);
LO4_SET_CTRIM(lo4, 1);; LO4_SET_CTRIM(lo4, 1);
c = 1; c = 1;
break; break;
case BAND_UHF: case BAND_UHF:

View file

@ -883,7 +883,7 @@ static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32
255, 255, 255, 255, 255, 255}; 255, 255, 255, 255, 255, 255};
u32 xtal = state->cfg.bw->xtal_hz / 1000; u32 xtal = state->cfg.bw->xtal_hz / 1000;
int f_rel = ( (rf_khz + xtal/2) / xtal) * xtal - rf_khz; int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz;
int k; int k;
int coef_re[8],coef_im[8]; int coef_re[8],coef_im[8];
int bw_khz = bw; int bw_khz = bw;

View file

@ -389,6 +389,77 @@ static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
} }
}; };
/* Samsung TDTC9251DH0 DVB-T NIM, as used on AirStar 2 */
static struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
.name = "Samsung TDTC9251DH0",
.min = 48000000,
.max = 863000000,
.iffreq = 36166667,
.count = 3,
.entries = {
{ 157500000, 166667, 0xcc, 0x09 },
{ 443000000, 166667, 0xcc, 0x0a },
{ 863000000, 166667, 0xcc, 0x08 },
}
};
/* Samsung TBDU18132 DVB-S NIM with TSA5059 PLL, used in SkyStar2 DVB-S 2.3 */
static struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
.name = "Samsung TBDU18132",
.min = 950000,
.max = 2150000, /* guesses */
.iffreq = 0,
.count = 2,
.entries = {
{ 1550000, 125, 0x84, 0x82 },
{ 4095937, 125, 0x84, 0x80 },
}
/* TSA5059 PLL has a 17 bit divisor rather than the 15 bits supported
* by this driver. The two extra bits are 0x60 in the third byte. 15
* bits is enough for over 4 GHz, which is enough to cover the range
* of this tuner. We could use the additional divisor bits by adding
* more entries, e.g.
{ 0x0ffff * 125 + 125/2, 125, 0x84 | 0x20, },
{ 0x17fff * 125 + 125/2, 125, 0x84 | 0x40, },
{ 0x1ffff * 125 + 125/2, 125, 0x84 | 0x60, }, */
};
/* Samsung TBMU24112 DVB-S NIM with SL1935 zero-IF tuner */
static struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
.name = "Samsung TBMU24112",
.min = 950000,
.max = 2150000, /* guesses */
.iffreq = 0,
.count = 2,
.entries = {
{ 1500000, 125, 0x84, 0x18 },
{ 9999999, 125, 0x84, 0x08 },
}
};
/* Alps TDEE4 DVB-C NIM, used on Cablestar 2 */
/* byte 4 : 1 * * AGD R3 R2 R1 R0
* byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1
* AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95
* Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5
* 47 - 153 0 * 0 0 0 0 0 1 0x01
* 153 - 430 0 * 0 0 0 0 1 0 0x02
* 430 - 822 0 * 0 0 1 0 0 0 0x08
* 822 - 862 1 * 0 0 1 0 0 0 0x88 */
static struct dvb_pll_desc dvb_pll_alps_tdee4 = {
.name = "ALPS TDEE4",
.min = 47000000,
.max = 862000000,
.iffreq = 36125000,
.count = 4,
.entries = {
{ 153000000, 62500, 0x95, 0x01 },
{ 430000000, 62500, 0x95, 0x02 },
{ 822000000, 62500, 0x95, 0x08 },
{ 999999999, 62500, 0x95, 0x88 },
}
};
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
static struct dvb_pll_desc *pll_list[] = { static struct dvb_pll_desc *pll_list[] = {
@ -402,11 +473,15 @@ static struct dvb_pll_desc *pll_list[] = {
[DVB_PLL_TUA6034] = &dvb_pll_tua6034, [DVB_PLL_TUA6034] = &dvb_pll_tua6034,
[DVB_PLL_TDA665X] = &dvb_pll_tda665x, [DVB_PLL_TDA665X] = &dvb_pll_tda665x,
[DVB_PLL_TDED4] = &dvb_pll_tded4, [DVB_PLL_TDED4] = &dvb_pll_tded4,
[DVB_PLL_TDEE4] = &dvb_pll_alps_tdee4,
[DVB_PLL_TDHU2] = &dvb_pll_tdhu2, [DVB_PLL_TDHU2] = &dvb_pll_tdhu2,
[DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv, [DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv,
[DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261, [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
[DVB_PLL_OPERA1] = &dvb_pll_opera1, [DVB_PLL_OPERA1] = &dvb_pll_opera1,
[DVB_PLL_SAMSUNG_DTOS403IH102A] = &dvb_pll_samsung_dtos403ih102a, [DVB_PLL_SAMSUNG_DTOS403IH102A] = &dvb_pll_samsung_dtos403ih102a,
[DVB_PLL_SAMSUNG_TDTC9251DH0] = &dvb_pll_samsung_tdtc9251dh0,
[DVB_PLL_SAMSUNG_TBDU18132] = &dvb_pll_samsung_tbdu18132,
[DVB_PLL_SAMSUNG_TBMU24112] = &dvb_pll_samsung_tbmu24112,
}; };
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */

View file

@ -23,6 +23,10 @@
#define DVB_PLL_PHILIPS_SD1878_TDA8261 12 #define DVB_PLL_PHILIPS_SD1878_TDA8261 12
#define DVB_PLL_OPERA1 13 #define DVB_PLL_OPERA1 13
#define DVB_PLL_SAMSUNG_DTOS403IH102A 14 #define DVB_PLL_SAMSUNG_DTOS403IH102A 14
#define DVB_PLL_SAMSUNG_TDTC9251DH0 15
#define DVB_PLL_SAMSUNG_TBDU18132 16
#define DVB_PLL_SAMSUNG_TBMU24112 17
#define DVB_PLL_TDEE4 18
/** /**
* Attach a dvb-pll to the supplied frontend structure. * Attach a dvb-pll to the supplied frontend structure.

View file

@ -1,9 +1,9 @@
/* /*
* Support for Legend Silicon DMB-TH demodulator * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
* LGS8913, LGS8GL5 * LGS8913, LGS8GL5, LGS8G75
* experimental support LGS8G42, LGS8G52 * experimental support LGS8G42, LGS8G52
* *
* Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> * Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
* Copyright (C) 2008 Sirius International (Hong Kong) Limited * Copyright (C) 2008 Sirius International (Hong Kong) Limited
* Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
* *
@ -46,6 +46,42 @@ module_param(fake_signal_str, int, 0644);
MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
"Signal strength calculation is slow.(default:on)."); "Signal strength calculation is slow.(default:on).");
static const u8 lgs8g75_initdat[] = {
0x01, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE4, 0xF5, 0xA8, 0xF5, 0xB8, 0xF5, 0x88, 0xF5,
0x89, 0xF5, 0x87, 0x75, 0xD0, 0x00, 0x11, 0x50,
0x11, 0x50, 0xF4, 0xF5, 0x80, 0xF5, 0x90, 0xF5,
0xA0, 0xF5, 0xB0, 0x75, 0x81, 0x30, 0x80, 0x01,
0x32, 0x90, 0x80, 0x12, 0x74, 0xFF, 0xF0, 0x90,
0x80, 0x13, 0x74, 0x1F, 0xF0, 0x90, 0x80, 0x23,
0x74, 0x01, 0xF0, 0x90, 0x80, 0x22, 0xF0, 0x90,
0x00, 0x48, 0x74, 0x00, 0xF0, 0x90, 0x80, 0x4D,
0x74, 0x05, 0xF0, 0x90, 0x80, 0x09, 0xE0, 0x60,
0x21, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x1B, 0x12,
0x00, 0xDD, 0x14, 0x60, 0x15, 0x12, 0x00, 0xDD,
0x14, 0x60, 0x0F, 0x12, 0x00, 0xDD, 0x14, 0x60,
0x09, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x03, 0x12,
0x00, 0xDD, 0x90, 0x80, 0x42, 0xE0, 0x60, 0x0B,
0x14, 0x60, 0x0C, 0x14, 0x60, 0x0D, 0x14, 0x60,
0x0E, 0x01, 0xB3, 0x74, 0x04, 0x01, 0xB9, 0x74,
0x05, 0x01, 0xB9, 0x74, 0x07, 0x01, 0xB9, 0x74,
0x0A, 0xC0, 0xE0, 0x74, 0xC8, 0x12, 0x00, 0xE2,
0xD0, 0xE0, 0x14, 0x70, 0xF4, 0x90, 0x80, 0x09,
0xE0, 0x70, 0xAE, 0x12, 0x00, 0xF6, 0x12, 0x00,
0xFE, 0x90, 0x00, 0x48, 0xE0, 0x04, 0xF0, 0x90,
0x80, 0x4E, 0xF0, 0x01, 0x73, 0x90, 0x80, 0x08,
0xF0, 0x22, 0xF8, 0x7A, 0x0C, 0x79, 0xFD, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9,
0xF6, 0xDA, 0xF2, 0xD8, 0xEE, 0x22, 0x90, 0x80,
0x65, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, 0x80,
0x65, 0xE0, 0x44, 0xC2, 0xF0, 0x22
};
/* LGS8GXX internal helper functions */ /* LGS8GXX internal helper functions */
static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
@ -55,7 +91,7 @@ static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
msg.addr = priv->config->demod_address; msg.addr = priv->config->demod_address;
if (reg >= 0xC0) if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
msg.addr += 0x02; msg.addr += 0x02;
if (debug >= 2) if (debug >= 2)
@ -84,7 +120,7 @@ static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data)
}; };
dev_addr = priv->config->demod_address; dev_addr = priv->config->demod_address;
if (reg >= 0xC0) if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
dev_addr += 0x02; dev_addr += 0x02;
msg[1].addr = msg[0].addr = dev_addr; msg[1].addr = msg[0].addr = dev_addr;
@ -112,19 +148,36 @@ static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv)
return 0; return 0;
} }
static int wait_reg_mask(struct lgs8gxx_state *priv, u8 reg, u8 mask,
u8 val, u8 delay, u8 tries)
{
u8 t;
int i;
for (i = 0; i < tries; i++) {
lgs8gxx_read_reg(priv, reg, &t);
if ((t & mask) == val)
return 0;
msleep(delay);
}
return 1;
}
static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv) static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv)
{ {
const struct lgs8gxx_config *config = priv->config; const struct lgs8gxx_config *config = priv->config;
u8 if_conf; u8 if_conf;
if_conf = 0x10; /* AGC output on; */ if_conf = 0x10; /* AGC output on, RF_AGC output off; */
if_conf |= if_conf |=
((config->ext_adc) ? 0x80 : 0x00) | ((config->ext_adc) ? 0x80 : 0x00) |
((config->if_neg_center) ? 0x04 : 0x00) | ((config->if_neg_center) ? 0x04 : 0x00) |
((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */ ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */
((config->ext_adc && config->adc_signed) ? 0x02 : 0x00) | ((config->adc_signed) ? 0x02 : 0x00) |
((config->ext_adc && config->if_neg_edge) ? 0x01 : 0x00); ((config->if_neg_edge) ? 0x01 : 0x00);
if (config->ext_adc && if (config->ext_adc &&
(config->prod == LGS8GXX_PROD_LGS8G52)) { (config->prod == LGS8GXX_PROD_LGS8G52)) {
@ -157,39 +210,82 @@ static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/)
} }
dprintk("AFC_INIT_FREQ = 0x%08X\n", v32); dprintk("AFC_INIT_FREQ = 0x%08X\n", v32);
lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); lgs8gxx_write_reg(priv, 0x08, 0xFF & (v32));
lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32 >> 8));
lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 16));
lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 24));
} else {
lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32));
lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8));
lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16));
lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24));
}
return 0; return 0;
} }
static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv)
{
u64 val;
u32 v32 = 0;
u8 reg_addr, t;
int i;
if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
reg_addr = 0x23;
else
reg_addr = 0x48;
for (i = 0; i < 4; i++) {
lgs8gxx_read_reg(priv, reg_addr, &t);
v32 <<= 8;
v32 |= t;
reg_addr--;
}
val = v32;
val *= priv->config->if_clk_freq;
val /= (u64)1 << 32;
dprintk("AFC = %u kHz\n", (u32)val);
return 0;
}
static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv) static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv)
{ {
u8 t; u8 t;
u8 prod = priv->config->prod;
if (priv->config->prod == LGS8GXX_PROD_LGS8913) if (prod == LGS8GXX_PROD_LGS8913)
lgs8gxx_write_reg(priv, 0xC6, 0x01); lgs8gxx_write_reg(priv, 0xC6, 0x01);
lgs8gxx_read_reg(priv, 0x7E, &t); if (prod == LGS8GXX_PROD_LGS8G75) {
lgs8gxx_write_reg(priv, 0x7E, t | 0x01); lgs8gxx_read_reg(priv, 0x0C, &t);
t &= (~0x04);
lgs8gxx_write_reg(priv, 0x0C, t | 0x80);
lgs8gxx_write_reg(priv, 0x39, 0x00);
lgs8gxx_write_reg(priv, 0x3D, 0x04);
} else if (prod == LGS8GXX_PROD_LGS8913 ||
prod == LGS8GXX_PROD_LGS8GL5 ||
prod == LGS8GXX_PROD_LGS8G42 ||
prod == LGS8GXX_PROD_LGS8G52 ||
prod == LGS8GXX_PROD_LGS8G54) {
lgs8gxx_read_reg(priv, 0x7E, &t);
lgs8gxx_write_reg(priv, 0x7E, t | 0x01);
/* clear FEC self reset */ /* clear FEC self reset */
lgs8gxx_read_reg(priv, 0xC5, &t); lgs8gxx_read_reg(priv, 0xC5, &t);
lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); lgs8gxx_write_reg(priv, 0xC5, t & 0xE0);
}
if (priv->config->prod == LGS8GXX_PROD_LGS8913) { if (prod == LGS8GXX_PROD_LGS8913) {
/* FEC auto detect */ /* FEC auto detect */
lgs8gxx_write_reg(priv, 0xC1, 0x03); lgs8gxx_write_reg(priv, 0xC1, 0x03);
lgs8gxx_read_reg(priv, 0x7C, &t); lgs8gxx_read_reg(priv, 0x7C, &t);
t = (t & 0x8C) | 0x03; t = (t & 0x8C) | 0x03;
lgs8gxx_write_reg(priv, 0x7C, t); lgs8gxx_write_reg(priv, 0x7C, t);
}
if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
/* BER test mode */ /* BER test mode */
lgs8gxx_read_reg(priv, 0xC3, &t); lgs8gxx_read_reg(priv, 0xC3, &t);
t = (t & 0xEF) | 0x10; t = (t & 0xEF) | 0x10;
@ -207,6 +303,32 @@ static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv)
int ret = 0; int ret = 0;
u8 t; u8 t;
if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
u8 t2;
lgs8gxx_read_reg(priv, 0x0C, &t);
t &= (~0x80);
lgs8gxx_write_reg(priv, 0x0C, t);
lgs8gxx_read_reg(priv, 0x0C, &t);
lgs8gxx_read_reg(priv, 0x19, &t2);
if (((t&0x03) == 0x01) && (t2&0x01)) {
lgs8gxx_write_reg(priv, 0x6E, 0x05);
lgs8gxx_write_reg(priv, 0x39, 0x02);
lgs8gxx_write_reg(priv, 0x39, 0x03);
lgs8gxx_write_reg(priv, 0x3D, 0x05);
lgs8gxx_write_reg(priv, 0x3E, 0x28);
lgs8gxx_write_reg(priv, 0x53, 0x80);
} else {
lgs8gxx_write_reg(priv, 0x6E, 0x3F);
lgs8gxx_write_reg(priv, 0x39, 0x00);
lgs8gxx_write_reg(priv, 0x3D, 0x04);
}
lgs8gxx_soft_reset(priv);
return 0;
}
/* turn off auto-detect; manual settings */ /* turn off auto-detect; manual settings */
lgs8gxx_write_reg(priv, 0x7E, 0); lgs8gxx_write_reg(priv, 0x7E, 0);
if (priv->config->prod == LGS8GXX_PROD_LGS8913) if (priv->config->prod == LGS8GXX_PROD_LGS8913)
@ -226,11 +348,39 @@ static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked)
int ret = 0; int ret = 0;
u8 t; u8 t;
ret = lgs8gxx_read_reg(priv, 0x4B, &t); if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
ret = lgs8gxx_read_reg(priv, 0x13, &t);
else
ret = lgs8gxx_read_reg(priv, 0x4B, &t);
if (ret != 0) if (ret != 0)
return ret; return ret;
*locked = ((t & 0xC0) == 0xC0) ? 1 : 0; if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
*locked = ((t & 0x80) == 0x80) ? 1 : 0;
else
*locked = ((t & 0xC0) == 0xC0) ? 1 : 0;
return 0;
}
/* Wait for Code Acquisition Lock */
static int lgs8gxx_wait_ca_lock(struct lgs8gxx_state *priv, u8 *locked)
{
int ret = 0;
u8 reg, mask, val;
if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
reg = 0x13;
mask = 0x80;
val = 0x80;
} else {
reg = 0x4B;
mask = 0xC0;
val = 0xC0;
}
ret = wait_reg_mask(priv, reg, mask, val, 50, 40);
*locked = (ret == 0) ? 1 : 0;
return 0; return 0;
} }
@ -238,21 +388,30 @@ static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv,
u8 *finished) u8 *finished)
{ {
int ret = 0; int ret = 0;
u8 t; u8 reg, mask, val;
ret = lgs8gxx_read_reg(priv, 0xA4, &t); if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
if (ret != 0) reg = 0x1f;
return ret; mask = 0xC0;
val = 0x80;
} else {
reg = 0xA4;
mask = 0x03;
val = 0x01;
}
*finished = ((t & 0x3) == 0x1) ? 1 : 0; ret = wait_reg_mask(priv, reg, mask, val, 10, 20);
*finished = (ret == 0) ? 1 : 0;
return 0; return 0;
} }
static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked) static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 cpn,
u8 *locked)
{ {
int err; int err = 0;
u8 ad_fini = 0; u8 ad_fini = 0;
u8 t1, t2;
if (gi == GI_945) if (gi == GI_945)
dprintk("try GI 945\n"); dprintk("try GI 945\n");
@ -260,17 +419,29 @@ static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked)
dprintk("try GI 595\n"); dprintk("try GI 595\n");
else if (gi == GI_420) else if (gi == GI_420)
dprintk("try GI 420\n"); dprintk("try GI 420\n");
lgs8gxx_write_reg(priv, 0x04, gi); if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
lgs8gxx_read_reg(priv, 0x0C, &t1);
lgs8gxx_read_reg(priv, 0x18, &t2);
t1 &= ~(GI_MASK);
t1 |= gi;
t2 &= 0xFE;
t2 |= cpn ? 0x01 : 0x00;
lgs8gxx_write_reg(priv, 0x0C, t1);
lgs8gxx_write_reg(priv, 0x18, t2);
} else {
lgs8gxx_write_reg(priv, 0x04, gi);
}
lgs8gxx_soft_reset(priv); lgs8gxx_soft_reset(priv);
msleep(50); err = lgs8gxx_wait_ca_lock(priv, locked);
if (err || !(*locked))
return err;
err = lgs8gxx_is_autodetect_finished(priv, &ad_fini); err = lgs8gxx_is_autodetect_finished(priv, &ad_fini);
if (err != 0) if (err != 0)
return err; return err;
if (ad_fini) { if (ad_fini) {
err = lgs8gxx_is_locked(priv, locked); dprintk("auto detect finished\n");
if (err != 0) } else
return err; *locked = 0;
}
return 0; return 0;
} }
@ -285,13 +456,18 @@ static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv,
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
lgs8gxx_set_mode_auto(priv); lgs8gxx_set_mode_auto(priv);
/* Guard Interval */ if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
lgs8gxx_write_reg(priv, 0x03, 00); lgs8gxx_write_reg(priv, 0x67, 0xAA);
lgs8gxx_write_reg(priv, 0x6E, 0x3F);
} else {
/* Guard Interval */
lgs8gxx_write_reg(priv, 0x03, 00);
}
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
tmp_gi = GI_945; tmp_gi = GI_945;
err = lgs8gxx_autolock_gi(priv, GI_945, &locked); err = lgs8gxx_autolock_gi(priv, GI_945, j, &locked);
if (err) if (err)
goto out; goto out;
if (locked) if (locked)
@ -299,14 +475,14 @@ static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv,
} }
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
tmp_gi = GI_420; tmp_gi = GI_420;
err = lgs8gxx_autolock_gi(priv, GI_420, &locked); err = lgs8gxx_autolock_gi(priv, GI_420, j, &locked);
if (err) if (err)
goto out; goto out;
if (locked) if (locked)
goto locked; goto locked;
} }
tmp_gi = GI_595; tmp_gi = GI_595;
err = lgs8gxx_autolock_gi(priv, GI_595, &locked); err = lgs8gxx_autolock_gi(priv, GI_595, 1, &locked);
if (err) if (err)
goto out; goto out;
if (locked) if (locked)
@ -317,8 +493,13 @@ locked:
if ((err == 0) && (locked == 1)) { if ((err == 0) && (locked == 1)) {
u8 t; u8 t;
lgs8gxx_read_reg(priv, 0xA2, &t); if (priv->config->prod != LGS8GXX_PROD_LGS8G75) {
*detected_param = t; lgs8gxx_read_reg(priv, 0xA2, &t);
*detected_param = t;
} else {
lgs8gxx_read_reg(priv, 0x1F, &t);
*detected_param = t & 0x3F;
}
if (tmp_gi == GI_945) if (tmp_gi == GI_945)
dprintk("GI 945 locked\n"); dprintk("GI 945 locked\n");
@ -345,18 +526,28 @@ static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv)
if (err != 0) { if (err != 0) {
dprintk("lgs8gxx_auto_detect failed\n"); dprintk("lgs8gxx_auto_detect failed\n");
} } else
dprintk("detected param = 0x%02X\n", detected_param);
/* Apply detected parameters */ /* Apply detected parameters */
if (priv->config->prod == LGS8GXX_PROD_LGS8913) { if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
u8 inter_leave_len = detected_param & TIM_MASK ; u8 inter_leave_len = detected_param & TIM_MASK ;
inter_leave_len = (inter_leave_len == TIM_LONG) ? 0x60 : 0x40; /* Fix 8913 time interleaver detection bug */
inter_leave_len = (inter_leave_len == TIM_MIDDLE) ? 0x60 : 0x40;
detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK; detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK;
detected_param |= inter_leave_len; detected_param |= inter_leave_len;
} }
lgs8gxx_write_reg(priv, 0x7D, detected_param); if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
if (priv->config->prod == LGS8GXX_PROD_LGS8913) u8 t;
lgs8gxx_write_reg(priv, 0xC0, detected_param); lgs8gxx_read_reg(priv, 0x19, &t);
t &= 0x81;
t |= detected_param << 1;
lgs8gxx_write_reg(priv, 0x19, t);
} else {
lgs8gxx_write_reg(priv, 0x7D, detected_param);
if (priv->config->prod == LGS8GXX_PROD_LGS8913)
lgs8gxx_write_reg(priv, 0xC0, detected_param);
}
/* lgs8gxx_soft_reset(priv); */ /* lgs8gxx_soft_reset(priv); */
/* Enter manual mode */ /* Enter manual mode */
@ -378,9 +569,10 @@ static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv,
u8 serial, u8 clk_pol, u8 clk_gated) u8 serial, u8 clk_pol, u8 clk_gated)
{ {
int ret = 0; int ret = 0;
u8 t; u8 t, reg_addr;
ret = lgs8gxx_read_reg(priv, 0xC2, &t); reg_addr = (priv->config->prod == LGS8GXX_PROD_LGS8G75) ? 0x30 : 0xC2;
ret = lgs8gxx_read_reg(priv, reg_addr, &t);
if (ret != 0) if (ret != 0)
return ret; return ret;
@ -389,13 +581,29 @@ static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv,
t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL; t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL;
t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN; t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN;
ret = lgs8gxx_write_reg(priv, 0xC2, t); ret = lgs8gxx_write_reg(priv, reg_addr, t);
if (ret != 0) if (ret != 0)
return ret; return ret;
return 0; return 0;
} }
/* A/D input peak-to-peak voltage range */
static int lgs8g75_set_adc_vpp(struct lgs8gxx_state *priv,
u8 sel)
{
u8 r26 = 0x73, r27 = 0x90;
if (priv->config->prod != LGS8GXX_PROD_LGS8G75)
return 0;
r26 |= (sel & 0x01) << 7;
r27 |= (sel & 0x02) >> 1;
lgs8gxx_write_reg(priv, 0x26, r26);
lgs8gxx_write_reg(priv, 0x27, r27);
return 0;
}
/* LGS8913 demod frontend functions */ /* LGS8913 demod frontend functions */
@ -417,6 +625,34 @@ static int lgs8913_init(struct lgs8gxx_state *priv)
return 0; return 0;
} }
static int lgs8g75_init_data(struct lgs8gxx_state *priv)
{
const u8 *p = lgs8g75_initdat;
int i;
lgs8gxx_write_reg(priv, 0xC6, 0x40);
lgs8gxx_write_reg(priv, 0x3D, 0x04);
lgs8gxx_write_reg(priv, 0x39, 0x00);
lgs8gxx_write_reg(priv, 0x3A, 0x00);
lgs8gxx_write_reg(priv, 0x38, 0x00);
lgs8gxx_write_reg(priv, 0x3B, 0x00);
lgs8gxx_write_reg(priv, 0x38, 0x00);
for (i = 0; i < sizeof(lgs8g75_initdat); i++) {
lgs8gxx_write_reg(priv, 0x38, 0x00);
lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff));
lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8));
lgs8gxx_write_reg(priv, 0x3C, *p);
p++;
}
lgs8gxx_write_reg(priv, 0x38, 0x00);
return 0;
}
static int lgs8gxx_init(struct dvb_frontend *fe) static int lgs8gxx_init(struct dvb_frontend *fe)
{ {
struct lgs8gxx_state *priv = struct lgs8gxx_state *priv =
@ -429,6 +665,9 @@ static int lgs8gxx_init(struct dvb_frontend *fe)
lgs8gxx_read_reg(priv, 0, &data); lgs8gxx_read_reg(priv, 0, &data);
dprintk("reg 0 = 0x%02X\n", data); dprintk("reg 0 = 0x%02X\n", data);
if (config->prod == LGS8GXX_PROD_LGS8G75)
lgs8g75_set_adc_vpp(priv, config->adc_vpp);
/* Setup MPEG output format */ /* Setup MPEG output format */
err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts, err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts,
config->ts_clk_pol, config->ts_clk_pol,
@ -439,8 +678,7 @@ static int lgs8gxx_init(struct dvb_frontend *fe)
if (config->prod == LGS8GXX_PROD_LGS8913) if (config->prod == LGS8GXX_PROD_LGS8913)
lgs8913_init(priv); lgs8913_init(priv);
lgs8gxx_set_if_freq(priv, priv->config->if_freq); lgs8gxx_set_if_freq(priv, priv->config->if_freq);
if (config->prod != LGS8GXX_PROD_LGS8913) lgs8gxx_set_ad_mode(priv);
lgs8gxx_set_ad_mode(priv);
return 0; return 0;
} }
@ -489,9 +727,6 @@ static int lgs8gxx_set_fe(struct dvb_frontend *fe,
static int lgs8gxx_get_fe(struct dvb_frontend *fe, static int lgs8gxx_get_fe(struct dvb_frontend *fe,
struct dvb_frontend_parameters *fe_params) struct dvb_frontend_parameters *fe_params)
{ {
struct lgs8gxx_state *priv = fe->demodulator_priv;
u8 t;
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
/* TODO: get real readings from device */ /* TODO: get real readings from device */
@ -501,29 +736,10 @@ static int lgs8gxx_get_fe(struct dvb_frontend *fe,
/* bandwidth */ /* bandwidth */
fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
lgs8gxx_read_reg(priv, 0x7D, &t);
fe_params->u.ofdm.code_rate_HP = FEC_AUTO; fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
fe_params->u.ofdm.code_rate_LP = FEC_AUTO; fe_params->u.ofdm.code_rate_LP = FEC_AUTO;
/* constellation */ fe_params->u.ofdm.constellation = QAM_AUTO;
switch (t & SC_MASK) {
case SC_QAM64:
fe_params->u.ofdm.constellation = QAM_64;
break;
case SC_QAM32:
fe_params->u.ofdm.constellation = QAM_32;
break;
case SC_QAM16:
fe_params->u.ofdm.constellation = QAM_16;
break;
case SC_QAM4:
case SC_QAM4NR:
fe_params->u.ofdm.constellation = QPSK;
break;
default:
fe_params->u.ofdm.constellation = QAM_64;
}
/* transmission mode */ /* transmission mode */
fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
@ -552,9 +768,19 @@ static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
{ {
struct lgs8gxx_state *priv = fe->demodulator_priv; struct lgs8gxx_state *priv = fe->demodulator_priv;
s8 ret; s8 ret;
u8 t; u8 t, locked = 0;
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
*fe_status = 0;
lgs8gxx_get_afc_phase(priv);
lgs8gxx_is_locked(priv, &locked);
if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
if (locked)
*fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
return 0;
}
ret = lgs8gxx_read_reg(priv, 0x4B, &t); ret = lgs8gxx_read_reg(priv, 0x4B, &t);
if (ret != 0) if (ret != 0)
@ -658,12 +884,33 @@ static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
return 0; return 0;
} }
static int lgs8g75_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
{
u8 t;
s16 v = 0;
dprintk("%s\n", __func__);
lgs8gxx_read_reg(priv, 0xB1, &t);
v |= t;
v <<= 8;
lgs8gxx_read_reg(priv, 0xB0, &t);
v |= t;
*signal = v;
dprintk("%s: signal=0x%02X\n", __func__, *signal);
return 0;
}
static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal) static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal)
{ {
struct lgs8gxx_state *priv = fe->demodulator_priv; struct lgs8gxx_state *priv = fe->demodulator_priv;
if (priv->config->prod == LGS8GXX_PROD_LGS8913) if (priv->config->prod == LGS8GXX_PROD_LGS8913)
return lgs8913_read_signal_strength(priv, signal); return lgs8913_read_signal_strength(priv, signal);
else if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
return lgs8g75_read_signal_strength(priv, signal);
else else
return lgs8gxx_read_signal_agc(priv, signal); return lgs8gxx_read_signal_agc(priv, signal);
} }
@ -674,7 +921,10 @@ static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr)
u8 t; u8 t;
*snr = 0; *snr = 0;
lgs8gxx_read_reg(priv, 0x95, &t); if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
lgs8gxx_read_reg(priv, 0x34, &t);
else
lgs8gxx_read_reg(priv, 0x95, &t);
dprintk("AVG Noise=0x%02X\n", t); dprintk("AVG Noise=0x%02X\n", t);
*snr = 256 - t; *snr = 256 - t;
*snr <<= 8; *snr <<= 8;
@ -690,31 +940,68 @@ static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
return 0; return 0;
} }
static void packet_counter_start(struct lgs8gxx_state *priv)
{
u8 orig, t;
if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
lgs8gxx_read_reg(priv, 0x30, &orig);
orig &= 0xE7;
t = orig | 0x10;
lgs8gxx_write_reg(priv, 0x30, t);
t = orig | 0x18;
lgs8gxx_write_reg(priv, 0x30, t);
t = orig | 0x10;
lgs8gxx_write_reg(priv, 0x30, t);
} else {
lgs8gxx_write_reg(priv, 0xC6, 0x01);
lgs8gxx_write_reg(priv, 0xC6, 0x41);
lgs8gxx_write_reg(priv, 0xC6, 0x01);
}
}
static void packet_counter_stop(struct lgs8gxx_state *priv)
{
u8 t;
if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
lgs8gxx_read_reg(priv, 0x30, &t);
t &= 0xE7;
lgs8gxx_write_reg(priv, 0x30, t);
} else {
lgs8gxx_write_reg(priv, 0xC6, 0x81);
}
}
static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber) static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber)
{ {
struct lgs8gxx_state *priv = fe->demodulator_priv; struct lgs8gxx_state *priv = fe->demodulator_priv;
u8 r0, r1, r2, r3; u8 reg_err, reg_total, t;
u32 total_cnt, err_cnt; u32 total_cnt = 0, err_cnt = 0;
int i;
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
lgs8gxx_write_reg(priv, 0xc6, 0x01); packet_counter_start(priv);
lgs8gxx_write_reg(priv, 0xc6, 0x41);
lgs8gxx_write_reg(priv, 0xc6, 0x01);
msleep(200); msleep(200);
packet_counter_stop(priv);
lgs8gxx_write_reg(priv, 0xc6, 0x81); if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
lgs8gxx_read_reg(priv, 0xd0, &r0); reg_total = 0x28; reg_err = 0x2C;
lgs8gxx_read_reg(priv, 0xd1, &r1); } else {
lgs8gxx_read_reg(priv, 0xd2, &r2); reg_total = 0xD0; reg_err = 0xD4;
lgs8gxx_read_reg(priv, 0xd3, &r3); }
total_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0);
lgs8gxx_read_reg(priv, 0xd4, &r0); for (i = 0; i < 4; i++) {
lgs8gxx_read_reg(priv, 0xd5, &r1); total_cnt <<= 8;
lgs8gxx_read_reg(priv, 0xd6, &r2); lgs8gxx_read_reg(priv, reg_total+3-i, &t);
lgs8gxx_read_reg(priv, 0xd7, &r3); total_cnt |= t;
err_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); }
for (i = 0; i < 4; i++) {
err_cnt <<= 8;
lgs8gxx_read_reg(priv, reg_err+3-i, &t);
err_cnt |= t;
}
dprintk("error=%d total=%d\n", err_cnt, total_cnt); dprintk("error=%d total=%d\n", err_cnt, total_cnt);
if (total_cnt == 0) if (total_cnt == 0)
@ -801,6 +1088,9 @@ struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
sizeof(struct dvb_frontend_ops)); sizeof(struct dvb_frontend_ops));
priv->frontend.demodulator_priv = priv; priv->frontend.demodulator_priv = priv;
if (config->prod == LGS8GXX_PROD_LGS8G75)
lgs8g75_init_data(priv);
return &priv->frontend; return &priv->frontend;
error_out: error_out:

View file

@ -1,9 +1,9 @@
/* /*
* Support for Legend Silicon DMB-TH demodulator * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
* LGS8913, LGS8GL5 * LGS8913, LGS8GL5, LGS8G75
* experimental support LGS8G42, LGS8G52 * experimental support LGS8G42, LGS8G52
* *
* Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> * Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
* Copyright (C) 2008 Sirius International (Hong Kong) Limited * Copyright (C) 2008 Sirius International (Hong Kong) Limited
* Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
* *
@ -34,6 +34,7 @@
#define LGS8GXX_PROD_LGS8G42 3 #define LGS8GXX_PROD_LGS8G42 3
#define LGS8GXX_PROD_LGS8G52 4 #define LGS8GXX_PROD_LGS8G52 4
#define LGS8GXX_PROD_LGS8G54 5 #define LGS8GXX_PROD_LGS8G54 5
#define LGS8GXX_PROD_LGS8G75 6
struct lgs8gxx_config { struct lgs8gxx_config {
@ -70,6 +71,10 @@ struct lgs8gxx_config {
/*IF use Negative center frequency*/ /*IF use Negative center frequency*/
u8 if_neg_center; u8 if_neg_center;
/*8G75 internal ADC input range selection*/
/*0: 0.8Vpp, 1: 1.0Vpp, 2: 1.6Vpp, 3: 2.0Vpp*/
u8 adc_vpp;
/* slave address and configuration of the tuner */ /* slave address and configuration of the tuner */
u8 tuner_address; u8 tuner_address;
}; };

View file

@ -1,9 +1,9 @@
/* /*
* Support for Legend Silicon DMB-TH demodulator * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
* LGS8913, LGS8GL5 * LGS8913, LGS8GL5, LGS8G75
* experimental support LGS8G42, LGS8G52 * experimental support LGS8G42, LGS8G52
* *
* Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> * Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
* Copyright (C) 2008 Sirius International (Hong Kong) Limited * Copyright (C) 2008 Sirius International (Hong Kong) Limited
* Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
* *
@ -38,7 +38,7 @@ struct lgs8gxx_state {
#define SC_QAM64 0x10 /* 64QAM modulation */ #define SC_QAM64 0x10 /* 64QAM modulation */
#define SC_QAM32 0x0C /* 32QAM modulation */ #define SC_QAM32 0x0C /* 32QAM modulation */
#define SC_QAM16 0x08 /* 16QAM modulation */ #define SC_QAM16 0x08 /* 16QAM modulation */
#define SC_QAM4NR 0x04 /* 4QAM modulation */ #define SC_QAM4NR 0x04 /* 4QAM-NR modulation */
#define SC_QAM4 0x00 /* 4QAM modulation */ #define SC_QAM4 0x00 /* 4QAM modulation */
#define LGS_FEC_MASK 0x03 /* FEC Rate Mask */ #define LGS_FEC_MASK 0x03 /* FEC Rate Mask */
@ -47,8 +47,8 @@ struct lgs8gxx_state {
#define LGS_FEC_0_8 0x02 /* FEC Rate 0.8 */ #define LGS_FEC_0_8 0x02 /* FEC Rate 0.8 */
#define TIM_MASK 0x20 /* Time Interleave Length Mask */ #define TIM_MASK 0x20 /* Time Interleave Length Mask */
#define TIM_LONG 0x00 /* Time Interleave Length = 720 */ #define TIM_LONG 0x20 /* Time Interleave Length = 720 */
#define TIM_MIDDLE 0x20 /* Time Interleave Length = 240 */ #define TIM_MIDDLE 0x00 /* Time Interleave Length = 240 */
#define CF_MASK 0x80 /* Control Frame Mask */ #define CF_MASK 0x80 /* Control Frame Mask */
#define CF_EN 0x80 /* Control Frame On */ #define CF_EN 0x80 /* Control Frame On */

View file

@ -85,7 +85,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
int i; int i;
dprintk("R(%d):", reg & 0x7f); dprintk("R(%d):", reg & 0x7f);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
printk(" %02x", buf[i]); printk(KERN_CONT " %02x", buf[i]);
printk("\n"); printk("\n");
} }
@ -103,7 +103,7 @@ static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
int i; int i;
dprintk("W(%d):", reg & 0x7f); dprintk("W(%d):", reg & 0x7f);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
printk(" %02x", src[i]); printk(KERN_CONT " %02x", src[i]);
printk("\n"); printk("\n");
} }
@ -744,7 +744,8 @@ static struct dvb_frontend_ops mt312_ops = {
.type = FE_QPSK, .type = FE_QPSK,
.frequency_min = 950000, .frequency_min = 950000,
.frequency_max = 2150000, .frequency_max = 2150000,
.frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, /* FIXME: adjust freq to real used xtal */ /* FIXME: adjust freq to real used xtal */
.frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
.symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */ .symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */
.symbol_rate_max = MT312_SYS_CLK / 2, .symbol_rate_max = MT312_SYS_CLK / 2,
.caps = .caps =

View file

@ -367,7 +367,9 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
/* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1))) */ /* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1))) */
nint = fvco / (state->reference << psd2); nint = fvco / (state->reference << psd2);
/* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9 */ /* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9 */
nfrac = (((fvco - (nint * state->reference << psd2)) << (9 - psd2)) + state->reference / 2) / state->reference; nfrac = DIV_ROUND_CLOSEST((fvco - (nint * state->reference << psd2))
<< (9 - psd2),
state->reference);
dprintk(verbose, FE_DEBUG, 1, dprintk(verbose, FE_DEBUG, 1,
"frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u", "frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u",
frequency, srate, (unsigned int)g, (unsigned int)odiv, frequency, srate, (unsigned int)g, (unsigned int)odiv,

View file

@ -230,8 +230,8 @@ enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *i_params)
stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5c); stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5c);
stv0900_write_reg(i_params, R0900_P1_TNRCFG, 0x6c); stv0900_write_reg(i_params, R0900_P1_TNRCFG, 0x6c);
stv0900_write_reg(i_params, R0900_P2_TNRCFG, 0x6f); stv0900_write_reg(i_params, R0900_P2_TNRCFG, 0x6f);
stv0900_write_reg(i_params, R0900_P1_I2CRPT, 0x24); stv0900_write_reg(i_params, R0900_P1_I2CRPT, 0x20);
stv0900_write_reg(i_params, R0900_P2_I2CRPT, 0x24); stv0900_write_reg(i_params, R0900_P2_I2CRPT, 0x20);
stv0900_write_reg(i_params, R0900_NCOARSE, 0x13); stv0900_write_reg(i_params, R0900_NCOARSE, 0x13);
msleep(3); msleep(3);
stv0900_write_reg(i_params, R0900_I2CCFG, 0x08); stv0900_write_reg(i_params, R0900_I2CCFG, 0x08);
@ -370,8 +370,8 @@ static int stv0900_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
u32 fi2c; u32 fi2c;
dmd_reg(fi2c, F0900_P1_I2CT_ON, F0900_P2_I2CT_ON); dmd_reg(fi2c, F0900_P1_I2CT_ON, F0900_P2_I2CT_ON);
if (enable)
stv0900_write_bits(i_params, fi2c, 1); stv0900_write_bits(i_params, fi2c, enable);
return 0; return 0;
} }

View file

@ -1721,7 +1721,7 @@ static enum fe_stv0900_signal_type stv0900_dvbs1_acq_workaround(struct dvb_front
s32 srate, demod_timeout, s32 srate, demod_timeout,
fec_timeout, freq1, freq0; fec_timeout, freq1, freq0;
enum fe_stv0900_signal_type signal_type = STV0900_NODATA;; enum fe_stv0900_signal_type signal_type = STV0900_NODATA;
switch (demod) { switch (demod) {
case STV0900_DEMOD_1: case STV0900_DEMOD_1:

View file

@ -36,6 +36,7 @@ struct stv6110_priv {
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
u32 mclk; u32 mclk;
u8 clk_div;
u8 regs[8]; u8 regs[8];
}; };
@ -100,35 +101,25 @@ static int stv6110_read_regs(struct dvb_frontend *fe, u8 regs[],
struct stv6110_priv *priv = fe->tuner_priv; struct stv6110_priv *priv = fe->tuner_priv;
int rc; int rc;
u8 reg[] = { start }; u8 reg[] = { start };
struct i2c_msg msg_wr = { struct i2c_msg msg[] = {
.addr = priv->i2c_address, {
.flags = 0, .addr = priv->i2c_address,
.buf = reg, .flags = 0,
.len = 1, .buf = reg,
.len = 1,
}, {
.addr = priv->i2c_address,
.flags = I2C_M_RD,
.buf = regs,
.len = len,
},
}; };
struct i2c_msg msg_rd = {
.addr = priv->i2c_address,
.flags = I2C_M_RD,
.buf = regs,
.len = len,
};
/* write subaddr */
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.i2c_gate_ctrl(fe, 1);
rc = i2c_transfer(priv->i2c, &msg_wr, 1); rc = i2c_transfer(priv->i2c, msg, 2);
if (rc != 1) if (rc != 2)
dprintk("%s: i2c error\n", __func__);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
/* read registers */
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
rc = i2c_transfer(priv->i2c, &msg_rd, 1);
if (rc != 1)
dprintk("%s: i2c error\n", __func__); dprintk("%s: i2c error\n", __func__);
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
@ -221,6 +212,10 @@ static int stv6110_init(struct dvb_frontend *fe)
priv->regs[RSTV6110_CTRL1] |= priv->regs[RSTV6110_CTRL1] |=
((((priv->mclk / 1000000) - 16) & 0x1f) << 3); ((((priv->mclk / 1000000) - 16) & 0x1f) << 3);
/* divisor value for the output clock */
priv->regs[RSTV6110_CTRL2] &= ~0xc0;
priv->regs[RSTV6110_CTRL2] |= (priv->clk_div << 6);
stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL1], RSTV6110_CTRL1, 8); stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL1], RSTV6110_CTRL1, 8);
msleep(1); msleep(1);
stv6110_set_bandwidth(fe, 72000000); stv6110_set_bandwidth(fe, 72000000);
@ -418,6 +413,10 @@ struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe,
}; };
int ret; int ret;
/* divisor value for the output clock */
reg0[2] &= ~0xc0;
reg0[2] |= (config->clk_div << 6);
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.i2c_gate_ctrl(fe, 1);
@ -436,6 +435,7 @@ struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe,
priv->i2c_address = config->i2c_address; priv->i2c_address = config->i2c_address;
priv->i2c = i2c; priv->i2c = i2c;
priv->mclk = config->mclk; priv->mclk = config->mclk;
priv->clk_div = config->clk_div;
memcpy(&priv->regs, &reg0[1], 8); memcpy(&priv->regs, &reg0[1], 8);

View file

@ -41,7 +41,7 @@
struct stv6110_config { struct stv6110_config {
u8 i2c_address; u8 i2c_address;
u32 mclk; u32 mclk;
int iq_wiring; u8 clk_div; /* divisor value for the output clock */
}; };
#if defined(CONFIG_DVB_STV6110) || (defined(CONFIG_DVB_STV6110_MODULE) \ #if defined(CONFIG_DVB_STV6110) || (defined(CONFIG_DVB_STV6110_MODULE) \

View file

@ -176,7 +176,7 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate
tmp = ((symbolrate << 4) % FIN) << 8; tmp = ((symbolrate << 4) % FIN) << 8;
ratio = (ratio << 8) + tmp / FIN; ratio = (ratio << 8) + tmp / FIN;
tmp = (tmp % FIN) << 8; tmp = (tmp % FIN) << 8;
ratio = (ratio << 8) + (tmp + FIN/2) / FIN; ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, FIN);
BDR = ratio; BDR = ratio;
BDRI = (((XIN << 5) / symbolrate) + 1) / 2; BDRI = (((XIN << 5) / symbolrate) + 1) / 2;

View file

@ -136,9 +136,9 @@ static int tda8261_set_state(struct dvb_frontend *fe,
if (frequency < 1450000) if (frequency < 1450000)
buf[3] = 0x00; buf[3] = 0x00;
if (frequency < 2000000) else if (frequency < 2000000)
buf[3] = 0x40; buf[3] = 0x40;
if (frequency < 2150000) else if (frequency < 2150000)
buf[3] = 0x80; buf[3] = 0x80;
/* Set params */ /* Set params */

View file

@ -165,7 +165,7 @@ static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate)
tmp = ((symbolrate << 4) % fin) << 8; tmp = ((symbolrate << 4) % fin) << 8;
ratio = (ratio << 8) + tmp / fin; ratio = (ratio << 8) + tmp / fin;
tmp = (tmp % fin) << 8; tmp = (tmp % fin) << 8;
ratio = (ratio << 8) + (tmp + fin / 2) / fin; ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, fin);
BDR = ratio; BDR = ratio;
BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2; BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2;

View file

@ -29,7 +29,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/dvb/frontend.h> #include <linux/dvb/frontend.h>
#include <asm/types.h> #include <linux/types.h>
#include "zl10036.h" #include "zl10036.h"

View file

@ -0,0 +1,308 @@
/*
* Driver for Zarlink ZL10039 DVB-S tuner
*
* Copyright 2007 Jan D. Louw <jd.louw@mweb.co.za>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
#include "zl10039.h"
static int debug;
#define dprintk(args...) \
do { \
if (debug) \
printk(KERN_DEBUG args); \
} while (0)
enum zl10039_model_id {
ID_ZL10039 = 1
};
struct zl10039_state {
struct i2c_adapter *i2c;
u8 i2c_addr;
u8 id;
};
enum zl10039_reg_addr {
PLL0 = 0,
PLL1,
PLL2,
PLL3,
RFFE,
BASE0,
BASE1,
BASE2,
LO0,
LO1,
LO2,
LO3,
LO4,
LO5,
LO6,
GENERAL
};
static int zl10039_read(const struct zl10039_state *state,
const enum zl10039_reg_addr reg, u8 *buf,
const size_t count)
{
u8 regbuf[] = { reg };
struct i2c_msg msg[] = {
{/* Write register address */
.addr = state->i2c_addr,
.flags = 0,
.buf = regbuf,
.len = 1,
}, {/* Read count bytes */
.addr = state->i2c_addr,
.flags = I2C_M_RD,
.buf = buf,
.len = count,
},
};
dprintk("%s\n", __func__);
if (i2c_transfer(state->i2c, msg, 2) != 2) {
dprintk("%s: i2c read error\n", __func__);
return -EREMOTEIO;
}
return 0; /* Success */
}
static int zl10039_write(struct zl10039_state *state,
const enum zl10039_reg_addr reg, const u8 *src,
const size_t count)
{
u8 buf[count + 1];
struct i2c_msg msg = {
.addr = state->i2c_addr,
.flags = 0,
.buf = buf,
.len = count + 1,
};
dprintk("%s\n", __func__);
/* Write register address and data in one go */
buf[0] = reg;
memcpy(&buf[1], src, count);
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
dprintk("%s: i2c write error\n", __func__);
return -EREMOTEIO;
}
return 0; /* Success */
}
static inline int zl10039_readreg(struct zl10039_state *state,
const enum zl10039_reg_addr reg, u8 *val)
{
return zl10039_read(state, reg, val, 1);
}
static inline int zl10039_writereg(struct zl10039_state *state,
const enum zl10039_reg_addr reg,
const u8 val)
{
return zl10039_write(state, reg, &val, 1);
}
static int zl10039_init(struct dvb_frontend *fe)
{
struct zl10039_state *state = fe->tuner_priv;
int ret;
dprintk("%s\n", __func__);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
/* Reset logic */
ret = zl10039_writereg(state, GENERAL, 0x40);
if (ret < 0) {
dprintk("Note: i2c write error normal when resetting the "
"tuner\n");
}
/* Wake up */
ret = zl10039_writereg(state, GENERAL, 0x01);
if (ret < 0) {
dprintk("Tuner power up failed\n");
return ret;
}
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
return 0;
}
static int zl10039_sleep(struct dvb_frontend *fe)
{
struct zl10039_state *state = fe->tuner_priv;
int ret;
dprintk("%s\n", __func__);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
ret = zl10039_writereg(state, GENERAL, 0x80);
if (ret < 0) {
dprintk("Tuner sleep failed\n");
return ret;
}
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
return 0;
}
static int zl10039_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
struct zl10039_state *state = fe->tuner_priv;
u8 buf[6];
u8 bf;
u32 fbw;
u32 div;
int ret;
dprintk("%s\n", __func__);
dprintk("Set frequency = %d, symbol rate = %d\n",
params->frequency, params->u.qpsk.symbol_rate);
/* Assumed 10.111 MHz crystal oscillator */
/* Cancelled num/den 80 to prevent overflow */
div = (params->frequency * 1000) / 126387;
fbw = (params->u.qpsk.symbol_rate * 27) / 32000;
/* Cancelled num/den 10 to prevent overflow */
bf = ((fbw * 5088) / 1011100) - 1;
/*PLL divider*/
buf[0] = (div >> 8) & 0x7f;
buf[1] = (div >> 0) & 0xff;
/*Reference divider*/
/* Select reference ratio of 80 */
buf[2] = 0x1D;
/*PLL test modes*/
buf[3] = 0x40;
/*RF Control register*/
buf[4] = 0x6E; /* Bypass enable */
/*Baseband filter cutoff */
buf[5] = bf;
/* Open i2c gate */
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
/* BR = 10, Enable filter adjustment */
ret = zl10039_writereg(state, BASE1, 0x0A);
if (ret < 0)
goto error;
/* Write new config values */
ret = zl10039_write(state, PLL0, buf, sizeof(buf));
if (ret < 0)
goto error;
/* BR = 10, Disable filter adjustment */
ret = zl10039_writereg(state, BASE1, 0x6A);
if (ret < 0)
goto error;
/* Close i2c gate */
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
return 0;
error:
dprintk("Error setting tuner\n");
return ret;
}
static int zl10039_release(struct dvb_frontend *fe)
{
struct zl10039_state *state = fe->tuner_priv;
dprintk("%s\n", __func__);
kfree(state);
fe->tuner_priv = NULL;
return 0;
}
static struct dvb_tuner_ops zl10039_ops = {
.release = zl10039_release,
.init = zl10039_init,
.sleep = zl10039_sleep,
.set_params = zl10039_set_params,
};
struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
u8 i2c_addr, struct i2c_adapter *i2c)
{
struct zl10039_state *state = NULL;
dprintk("%s\n", __func__);
state = kmalloc(sizeof(struct zl10039_state), GFP_KERNEL);
if (state == NULL)
goto error;
state->i2c = i2c;
state->i2c_addr = i2c_addr;
/* Open i2c gate */
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
/* check if this is a valid tuner */
if (zl10039_readreg(state, GENERAL, &state->id) < 0) {
/* Close i2c gate */
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
goto error;
}
/* Close i2c gate */
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
state->id = state->id & 0x0f;
switch (state->id) {
case ID_ZL10039:
strcpy(fe->ops.tuner_ops.info.name,
"Zarlink ZL10039 DVB-S tuner");
break;
default:
dprintk("Chip ID=%x does not match a known type\n", state->id);
break;
goto error;
}
memcpy(&fe->ops.tuner_ops, &zl10039_ops, sizeof(struct dvb_tuner_ops));
fe->tuner_priv = state;
dprintk("Tuner attached @ i2c address 0x%02x\n", i2c_addr);
return fe;
error:
kfree(state);
return NULL;
}
EXPORT_SYMBOL(zl10039_attach);
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("Zarlink ZL10039 DVB-S tuner driver");
MODULE_AUTHOR("Jan D. Louw <jd.louw@mweb.co.za>");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,40 @@
/*
Driver for Zarlink ZL10039 DVB-S tuner
Copyright (C) 2007 Jan D. Louw <jd.louw@mweb.co.za>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef ZL10039_H
#define ZL10039_H
#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \
&& defined(MODULE))
struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
u8 i2c_addr,
struct i2c_adapter *i2c);
#else
static inline struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
u8 i2c_addr,
struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_ZL10039 */
#endif /* ZL10039_H */

View file

@ -38,6 +38,8 @@ struct zl10353_state {
struct zl10353_config config; struct zl10353_config config;
enum fe_bandwidth bandwidth; enum fe_bandwidth bandwidth;
u32 ucblocks;
u32 frequency;
}; };
static int debug; static int debug;
@ -199,6 +201,8 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
u16 tps = 0; u16 tps = 0;
struct dvb_ofdm_parameters *op = &param->u.ofdm; struct dvb_ofdm_parameters *op = &param->u.ofdm;
state->frequency = param->frequency;
zl10353_single_write(fe, RESET, 0x80); zl10353_single_write(fe, RESET, 0x80);
udelay(200); udelay(200);
zl10353_single_write(fe, 0xEA, 0x01); zl10353_single_write(fe, 0xEA, 0x01);
@ -464,7 +468,7 @@ static int zl10353_get_parameters(struct dvb_frontend *fe,
break; break;
} }
param->frequency = 0; param->frequency = state->frequency;
op->bandwidth = state->bandwidth; op->bandwidth = state->bandwidth;
param->inversion = INVERSION_AUTO; param->inversion = INVERSION_AUTO;
@ -542,9 +546,13 @@ static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{ {
struct zl10353_state *state = fe->demodulator_priv; struct zl10353_state *state = fe->demodulator_priv;
u32 ubl = 0;
*ucblocks = zl10353_read_register(state, RS_UBC_1) << 8 | ubl = zl10353_read_register(state, RS_UBC_1) << 8 |
zl10353_read_register(state, RS_UBC_0); zl10353_read_register(state, RS_UBC_0);
state->ucblocks += ubl;
*ucblocks = state->ucblocks;
return 0; return 0;
} }

View file

@ -439,7 +439,7 @@ static inline u32 divide(u32 numerator, u32 denominator)
if (denominator == 0) if (denominator == 0)
return ~0; return ~0;
return (numerator + denominator / 2) / denominator; return DIV_ROUND_CLOSEST(numerator, denominator);
} }
/* LG Innotek TDTE-E001P (Infineon TUA6034) */ /* LG Innotek TDTE-E001P (Infineon TUA6034) */

View file

@ -490,7 +490,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
if (!av7110->analog_tuner_flags) if (!av7110->analog_tuner_flags)
return 0; return 0;
if (input < 0 || input >= 4) if (input >= 4)
return -EINVAL; return -EINVAL;
av7110->current_input = input; av7110->current_input = input;

View file

@ -225,7 +225,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
case 0x1012: case 0x1012:
/* The hauppauge keymap is a superset of these remotes */ /* The hauppauge keymap is a superset of these remotes */
ir_input_init(input_dev, &budget_ci->ir.state, ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, ir_codes_hauppauge_new); IR_TYPE_RC5, &ir_codes_hauppauge_new_table);
if (rc5_device < 0) if (rc5_device < 0)
budget_ci->ir.rc5_device = 0x1f; budget_ci->ir.rc5_device = 0x1f;
@ -237,7 +237,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
case 0x101a: case 0x101a:
/* for the Technotrend 1500 bundled remote */ /* for the Technotrend 1500 bundled remote */
ir_input_init(input_dev, &budget_ci->ir.state, ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, ir_codes_tt_1500); IR_TYPE_RC5, &ir_codes_tt_1500_table);
if (rc5_device < 0) if (rc5_device < 0)
budget_ci->ir.rc5_device = IR_DEVICE_ANY; budget_ci->ir.rc5_device = IR_DEVICE_ANY;
@ -247,7 +247,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
default: default:
/* unknown remote */ /* unknown remote */
ir_input_init(input_dev, &budget_ci->ir.state, ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, ir_codes_budget_ci_old); IR_TYPE_RC5, &ir_codes_budget_ci_old_table);
if (rc5_device < 0) if (rc5_device < 0)
budget_ci->ir.rc5_device = IR_DEVICE_ANY; budget_ci->ir.rc5_device = IR_DEVICE_ANY;

View file

@ -288,16 +288,6 @@ config RADIO_TYPHOON
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called radio-typhoon. module will be called radio-typhoon.
config RADIO_TYPHOON_PROC_FS
bool "Support for /proc/radio-typhoon"
depends on PROC_FS && RADIO_TYPHOON
help
Say Y here if you want the typhoon radio card driver to write
status information (frequency, volume, muted, mute frequency,
base address) to /proc/radio-typhoon. The file can be viewed with
your favorite pager (i.e. use "more /proc/radio-typhoon" or "less
/proc/radio-typhoon" or simply "cat /proc/radio-typhoon").
config RADIO_TYPHOON_PORT config RADIO_TYPHOON_PORT
hex "Typhoon I/O port (0x316 or 0x336)" hex "Typhoon I/O port (0x316 or 0x336)"
depends on RADIO_TYPHOON=y depends on RADIO_TYPHOON=y
@ -339,6 +329,29 @@ config RADIO_ZOLTRIX_PORT
help help
Enter the I/O port of your Zoltrix radio card. Enter the I/O port of your Zoltrix radio card.
config I2C_SI4713
tristate "I2C driver for Silicon Labs Si4713 device"
depends on I2C && VIDEO_V4L2
---help---
Say Y here if you want support to Si4713 I2C device.
This device driver supports only i2c bus.
To compile this driver as a module, choose M here: the
module will be called si4713.
config RADIO_SI4713
tristate "Silicon Labs Si4713 FM Radio Transmitter support"
depends on I2C && VIDEO_V4L2
select I2C_SI4713
---help---
Say Y here if you want support to Si4713 FM Radio Transmitter.
This device can transmit audio through FM. It can transmit
EDS and EBDS signals as well. This module is the v4l2 radio
interface for the i2c driver of this device.
To compile this driver as a module, choose M here: the
module will be called radio-si4713.
config USB_DSBR config USB_DSBR
tristate "D-Link/GemTek USB FM radio support" tristate "D-Link/GemTek USB FM radio support"
depends on USB && VIDEO_V4L2 depends on USB && VIDEO_V4L2
@ -351,29 +364,11 @@ config USB_DSBR
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called dsbr100. module will be called dsbr100.
config USB_SI470X config RADIO_SI470X
tristate "Silicon Labs Si470x FM Radio Receiver support" bool "Silicon Labs Si470x FM Radio Receiver support"
depends on USB && VIDEO_V4L2 depends on VIDEO_V4L2
---help---
This is a driver for USB devices with the Silicon Labs SI470x
chip. Currently these devices are known to work:
- 10c4:818a: Silicon Labs USB FM Radio Reference Design
- 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music)
- 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700)
Sound is provided by the ALSA USB Audio/MIDI driver. Therefore source "drivers/media/radio/si470x/Kconfig"
if you don't want to use the device solely for RDS receiving,
it is recommended to also select SND_USB_AUDIO.
Please have a look at the documentation, especially on how
to redirect the audio stream from the radio to your sound device:
Documentation/video4linux/si470x.txt
Say Y here if you want to connect this type of radio to your
computer's USB port.
To compile this driver as a module, choose M here: the
module will be called radio-si470x.
config USB_MR800 config USB_MR800
tristate "AverMedia MR 800 USB FM radio support" tristate "AverMedia MR 800 USB FM radio support"

View file

@ -15,9 +15,11 @@ obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o
obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o
obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o
obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_USB_SI470X) += radio-si470x.o obj-$(CONFIG_RADIO_SI470X) += si470x/
obj-$(CONFIG_USB_MR800) += radio-mr800.o obj-$(CONFIG_USB_MR800) += radio-mr800.o
obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o

View file

@ -359,7 +359,8 @@ static int vidioc_querycap(struct file *file, void *priv,
strlcpy(v->card, "ADS Cadet", sizeof(v->card)); strlcpy(v->card, "ADS Cadet", sizeof(v->card));
strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
v->version = CADET_VERSION; v->version = CADET_VERSION;
v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_READWRITE; v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO |
V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE;
return 0; return 0;
} }
@ -372,7 +373,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
switch (v->index) { switch (v->index) {
case 0: case 0:
strlcpy(v->name, "FM", sizeof(v->name)); strlcpy(v->name, "FM", sizeof(v->name));
v->capability = V4L2_TUNER_CAP_STEREO; v->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS;
v->rangelow = 1400; /* 87.5 MHz */ v->rangelow = 1400; /* 87.5 MHz */
v->rangehigh = 1728; /* 108.0 MHz */ v->rangehigh = 1728; /* 108.0 MHz */
v->rxsubchans = cadet_getstereo(dev); v->rxsubchans = cadet_getstereo(dev);
@ -386,6 +387,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
default: default:
break; break;
} }
v->rxsubchans |= V4L2_TUNER_SUB_RDS;
break; break;
case 1: case 1:
strlcpy(v->name, "AM", sizeof(v->name)); strlcpy(v->name, "AM", sizeof(v->name));

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,367 @@
/*
* drivers/media/radio/radio-si4713.c
*
* Platform Driver for Silicon Labs Si4713 FM Radio Transmitter:
*
* Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT
* Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/v4l2-device.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/radio-si4713.h>
/* module parameters */
static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */
module_param(radio_nr, int, 0);
MODULE_PARM_DESC(radio_nr,
"Minor number for radio device (-1 ==> auto assign)");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@nokia.com>");
MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter");
MODULE_VERSION("0.0.1");
/* Driver state struct */
struct radio_si4713_device {
struct v4l2_device v4l2_dev;
struct video_device *radio_dev;
};
/* radio_si4713_fops - file operations interface */
static const struct v4l2_file_operations radio_si4713_fops = {
.owner = THIS_MODULE,
.ioctl = video_ioctl2,
};
/* Video4Linux Interface */
static int radio_si4713_fill_audout(struct v4l2_audioout *vao)
{
/* TODO: check presence of audio output */
strlcpy(vao->name, "FM Modulator Audio Out", 32);
return 0;
}
static int radio_si4713_enumaudout(struct file *file, void *priv,
struct v4l2_audioout *vao)
{
return radio_si4713_fill_audout(vao);
}
static int radio_si4713_g_audout(struct file *file, void *priv,
struct v4l2_audioout *vao)
{
int rval = radio_si4713_fill_audout(vao);
vao->index = 0;
return rval;
}
static int radio_si4713_s_audout(struct file *file, void *priv,
struct v4l2_audioout *vao)
{
return vao->index ? -EINVAL : 0;
}
/* radio_si4713_querycap - query device capabilities */
static int radio_si4713_querycap(struct file *file, void *priv,
struct v4l2_capability *capability)
{
struct radio_si4713_device *rsdev;
rsdev = video_get_drvdata(video_devdata(file));
strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver));
strlcpy(capability->card, "Silicon Labs Si4713 Modulator",
sizeof(capability->card));
capability->capabilities = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT;
return 0;
}
/* radio_si4713_queryctrl - enumerate control items */
static int radio_si4713_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc)
{
/* Must be sorted from low to high control ID! */
static const u32 user_ctrls[] = {
V4L2_CID_USER_CLASS,
V4L2_CID_AUDIO_MUTE,
0
};
/* Must be sorted from low to high control ID! */
static const u32 fmtx_ctrls[] = {
V4L2_CID_FM_TX_CLASS,
V4L2_CID_RDS_TX_DEVIATION,
V4L2_CID_RDS_TX_PI,
V4L2_CID_RDS_TX_PTY,
V4L2_CID_RDS_TX_PS_NAME,
V4L2_CID_RDS_TX_RADIO_TEXT,
V4L2_CID_AUDIO_LIMITER_ENABLED,
V4L2_CID_AUDIO_LIMITER_RELEASE_TIME,
V4L2_CID_AUDIO_LIMITER_DEVIATION,
V4L2_CID_AUDIO_COMPRESSION_ENABLED,
V4L2_CID_AUDIO_COMPRESSION_GAIN,
V4L2_CID_AUDIO_COMPRESSION_THRESHOLD,
V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME,
V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME,
V4L2_CID_PILOT_TONE_ENABLED,
V4L2_CID_PILOT_TONE_DEVIATION,
V4L2_CID_PILOT_TONE_FREQUENCY,
V4L2_CID_TUNE_PREEMPHASIS,
V4L2_CID_TUNE_POWER_LEVEL,
V4L2_CID_TUNE_ANTENNA_CAPACITOR,
0
};
static const u32 *ctrl_classes[] = {
user_ctrls,
fmtx_ctrls,
NULL
};
struct radio_si4713_device *rsdev;
rsdev = video_get_drvdata(video_devdata(file));
qc->id = v4l2_ctrl_next(ctrl_classes, qc->id);
if (qc->id == 0)
return -EINVAL;
if (qc->id == V4L2_CID_USER_CLASS || qc->id == V4L2_CID_FM_TX_CLASS)
return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0);
return v4l2_device_call_until_err(&rsdev->v4l2_dev, 0, core,
queryctrl, qc);
}
/*
* v4l2 ioctl call backs.
* we are just a wrapper for v4l2_sub_devs.
*/
static inline struct v4l2_device *get_v4l2_dev(struct file *file)
{
return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev;
}
static int radio_si4713_g_ext_ctrls(struct file *file, void *p,
struct v4l2_ext_controls *vecs)
{
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
g_ext_ctrls, vecs);
}
static int radio_si4713_s_ext_ctrls(struct file *file, void *p,
struct v4l2_ext_controls *vecs)
{
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
s_ext_ctrls, vecs);
}
static int radio_si4713_g_ctrl(struct file *file, void *p,
struct v4l2_control *vc)
{
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
g_ctrl, vc);
}
static int radio_si4713_s_ctrl(struct file *file, void *p,
struct v4l2_control *vc)
{
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
s_ctrl, vc);
}
static int radio_si4713_g_modulator(struct file *file, void *p,
struct v4l2_modulator *vm)
{
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
g_modulator, vm);
}
static int radio_si4713_s_modulator(struct file *file, void *p,
struct v4l2_modulator *vm)
{
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
s_modulator, vm);
}
static int radio_si4713_g_frequency(struct file *file, void *p,
struct v4l2_frequency *vf)
{
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
g_frequency, vf);
}
static int radio_si4713_s_frequency(struct file *file, void *p,
struct v4l2_frequency *vf)
{
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
s_frequency, vf);
}
static long radio_si4713_default(struct file *file, void *p, int cmd, void *arg)
{
return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
ioctl, cmd, arg);
}
static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = {
.vidioc_enumaudout = radio_si4713_enumaudout,
.vidioc_g_audout = radio_si4713_g_audout,
.vidioc_s_audout = radio_si4713_s_audout,
.vidioc_querycap = radio_si4713_querycap,
.vidioc_queryctrl = radio_si4713_queryctrl,
.vidioc_g_ext_ctrls = radio_si4713_g_ext_ctrls,
.vidioc_s_ext_ctrls = radio_si4713_s_ext_ctrls,
.vidioc_g_ctrl = radio_si4713_g_ctrl,
.vidioc_s_ctrl = radio_si4713_s_ctrl,
.vidioc_g_modulator = radio_si4713_g_modulator,
.vidioc_s_modulator = radio_si4713_s_modulator,
.vidioc_g_frequency = radio_si4713_g_frequency,
.vidioc_s_frequency = radio_si4713_s_frequency,
.vidioc_default = radio_si4713_default,
};
/* radio_si4713_vdev_template - video device interface */
static struct video_device radio_si4713_vdev_template = {
.fops = &radio_si4713_fops,
.name = "radio-si4713",
.release = video_device_release,
.ioctl_ops = &radio_si4713_ioctl_ops,
};
/* Platform driver interface */
/* radio_si4713_pdriver_probe - probe for the device */
static int radio_si4713_pdriver_probe(struct platform_device *pdev)
{
struct radio_si4713_platform_data *pdata = pdev->dev.platform_data;
struct radio_si4713_device *rsdev;
struct i2c_adapter *adapter;
struct v4l2_subdev *sd;
int rval = 0;
if (!pdata) {
dev_err(&pdev->dev, "Cannot proceed without platform data.\n");
rval = -EINVAL;
goto exit;
}
rsdev = kzalloc(sizeof *rsdev, GFP_KERNEL);
if (!rsdev) {
dev_err(&pdev->dev, "Failed to alloc video device.\n");
rval = -ENOMEM;
goto exit;
}
rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev);
if (rval) {
dev_err(&pdev->dev, "Failed to register v4l2 device.\n");
goto free_rsdev;
}
adapter = i2c_get_adapter(pdata->i2c_bus);
if (!adapter) {
dev_err(&pdev->dev, "Cannot get i2c adapter %d\n",
pdata->i2c_bus);
rval = -ENODEV;
goto unregister_v4l2_dev;
}
sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter, "si4713_i2c",
pdata->subdev_board_info, NULL);
if (!sd) {
dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
rval = -ENODEV;
goto unregister_v4l2_dev;
}
rsdev->radio_dev = video_device_alloc();
if (!rsdev->radio_dev) {
dev_err(&pdev->dev, "Failed to alloc video device.\n");
rval = -ENOMEM;
goto unregister_v4l2_dev;
}
memcpy(rsdev->radio_dev, &radio_si4713_vdev_template,
sizeof(radio_si4713_vdev_template));
video_set_drvdata(rsdev->radio_dev, rsdev);
if (video_register_device(rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
dev_err(&pdev->dev, "Could not register video device.\n");
rval = -EIO;
goto free_vdev;
}
dev_info(&pdev->dev, "New device successfully probed\n");
goto exit;
free_vdev:
video_device_release(rsdev->radio_dev);
unregister_v4l2_dev:
v4l2_device_unregister(&rsdev->v4l2_dev);
free_rsdev:
kfree(rsdev);
exit:
return rval;
}
/* radio_si4713_pdriver_remove - remove the device */
static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev)
{
struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
struct radio_si4713_device *rsdev = container_of(v4l2_dev,
struct radio_si4713_device,
v4l2_dev);
video_unregister_device(rsdev->radio_dev);
v4l2_device_unregister(&rsdev->v4l2_dev);
kfree(rsdev);
return 0;
}
static struct platform_driver radio_si4713_pdriver = {
.driver = {
.name = "radio-si4713",
},
.probe = radio_si4713_pdriver_probe,
.remove = __exit_p(radio_si4713_pdriver_remove),
};
/* Module Interface */
static int __init radio_si4713_module_init(void)
{
return platform_driver_register(&radio_si4713_pdriver);
}
static void __exit radio_si4713_module_exit(void)
{
platform_driver_unregister(&radio_si4713_pdriver);
}
module_init(radio_si4713_module_init);
module_exit(radio_si4713_module_exit);

View file

@ -0,0 +1,37 @@
config USB_SI470X
tristate "Silicon Labs Si470x FM Radio Receiver support with USB"
depends on USB && RADIO_SI470X
---help---
This is a driver for USB devices with the Silicon Labs SI470x
chip. Currently these devices are known to work:
- 10c4:818a: Silicon Labs USB FM Radio Reference Design
- 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music)
- 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700)
- 10c5:819a: Sanei Electric FM USB Radio (aka DealExtreme.com PCear)
Sound is provided by the ALSA USB Audio/MIDI driver. Therefore
if you don't want to use the device solely for RDS receiving,
it is recommended to also select SND_USB_AUDIO.
Please have a look at the documentation, especially on how
to redirect the audio stream from the radio to your sound device:
Documentation/video4linux/si470x.txt
Say Y here if you want to connect this type of radio to your
computer's USB port.
To compile this driver as a module, choose M here: the
module will be called radio-usb-si470x.
config I2C_SI470X
tristate "Silicon Labs Si470x FM Radio Receiver support with I2C"
depends on I2C && RADIO_SI470X && !USB_SI470X
---help---
This is a driver for I2C devices with the Silicon Labs SI470x
chip.
Say Y here if you want to connect this type of radio to your
computer's I2C port.
To compile this driver as a module, choose M here: the
module will be called radio-i2c-si470x.

View file

@ -0,0 +1,9 @@
#
# Makefile for radios with Silicon Labs Si470x FM Radio Receivers
#
radio-usb-si470x-objs := radio-si470x-usb.o radio-si470x-common.o
radio-i2c-si470x-objs := radio-si470x-i2c.o radio-si470x-common.o
obj-$(CONFIG_USB_SI470X) += radio-usb-si470x.o
obj-$(CONFIG_I2C_SI470X) += radio-i2c-si470x.o

View file

@ -0,0 +1,798 @@
/*
* drivers/media/radio/si470x/radio-si470x-common.c
*
* Driver for radios with Silicon Labs Si470x FM Radio Receivers
*
* Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* History:
* 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net>
* Version 1.0.0
* - First working version
* 2008-01-13 Tobias Lorenz <tobias.lorenz@gmx.net>
* Version 1.0.1
* - Improved error handling, every function now returns errno
* - Improved multi user access (start/mute/stop)
* - Channel doesn't get lost anymore after start/mute/stop
* - RDS support added (polling mode via interrupt EP 1)
* - marked default module parameters with *value*
* - switched from bit structs to bit masks
* - header file cleaned and integrated
* 2008-01-14 Tobias Lorenz <tobias.lorenz@gmx.net>
* Version 1.0.2
* - hex values are now lower case
* - commented USB ID for ADS/Tech moved on todo list
* - blacklisted si470x in hid-quirks.c
* - rds buffer handling functions integrated into *_work, *_read
* - rds_command in si470x_poll exchanged against simple retval
* - check for firmware version 15
* - code order and prototypes still remain the same
* - spacing and bottom of band codes remain the same
* 2008-01-16 Tobias Lorenz <tobias.lorenz@gmx.net>
* Version 1.0.3
* - code reordered to avoid function prototypes
* - switch/case defaults are now more user-friendly
* - unified comment style
* - applied all checkpatch.pl v1.12 suggestions
* except the warning about the too long lines with bit comments
* - renamed FMRADIO to RADIO to cut line length (checkpatch.pl)
* 2008-01-22 Tobias Lorenz <tobias.lorenz@gmx.net>
* Version 1.0.4
* - avoid poss. locking when doing copy_to_user which may sleep
* - RDS is automatically activated on read now
* - code cleaned of unnecessary rds_commands
* - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified
* (thanks to Guillaume RAMOUSSE)
* 2008-01-27 Tobias Lorenz <tobias.lorenz@gmx.net>
* Version 1.0.5
* - number of seek_retries changed to tune_timeout
* - fixed problem with incomplete tune operations by own buffers
* - optimization of variables and printf types
* - improved error logging
* 2008-01-31 Tobias Lorenz <tobias.lorenz@gmx.net>
* Oliver Neukum <oliver@neukum.org>
* Version 1.0.6
* - fixed coverity checker warnings in *_usb_driver_disconnect
* - probe()/open() race by correct ordering in probe()
* - DMA coherency rules by separate allocation of all buffers
* - use of endianness macros
* - abuse of spinlock, replaced by mutex
* - racy handling of timer in disconnect,
* replaced by delayed_work
* - racy interruptible_sleep_on(),
* replaced with wait_event_interruptible()
* - handle signals in read()
* 2008-02-08 Tobias Lorenz <tobias.lorenz@gmx.net>
* Oliver Neukum <oliver@neukum.org>
* Version 1.0.7
* - usb autosuspend support
* - unplugging fixed
* 2008-05-07 Tobias Lorenz <tobias.lorenz@gmx.net>
* Version 1.0.8
* - hardware frequency seek support
* - afc indication
* - more safety checks, let si470x_get_freq return errno
* - vidioc behavior corrected according to v4l2 spec
* 2008-10-20 Alexey Klimov <klimov.linux@gmail.com>
* - add support for KWorld USB FM Radio FM700
* - blacklisted KWorld radio in hid-core.c and hid-ids.h
* 2008-12-03 Mark Lord <mlord@pobox.com>
* - add support for DealExtreme USB Radio
* 2009-01-31 Bob Ross <pigiron@gmx.com>
* - correction of stereo detection/setting
* - correction of signal strength indicator scaling
* 2009-01-31 Rick Bronson <rick@efn.org>
* Tobias Lorenz <tobias.lorenz@gmx.net>
* - add LED status output
* - get HW/SW version from scratchpad
* 2009-06-16 Edouard Lafargue <edouard@lafargue.name>
* Version 1.0.10
* - add support for interrupt mode for RDS endpoint,
* instead of polling.
* Improves RDS reception significantly
*/
/* kernel includes */
#include "radio-si470x.h"
/**************************************************************************
* Module Parameters
**************************************************************************/
/* Spacing (kHz) */
/* 0: 200 kHz (USA, Australia) */
/* 1: 100 kHz (Europe, Japan) */
/* 2: 50 kHz */
static unsigned short space = 2;
module_param(space, ushort, 0444);
MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
/* Bottom of Band (MHz) */
/* 0: 87.5 - 108 MHz (USA, Europe)*/
/* 1: 76 - 108 MHz (Japan wide band) */
/* 2: 76 - 90 MHz (Japan) */
static unsigned short band = 1;
module_param(band, ushort, 0444);
MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
/* De-emphasis */
/* 0: 75 us (USA) */
/* 1: 50 us (Europe, Australia, Japan) */
static unsigned short de = 1;
module_param(de, ushort, 0444);
MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*");
/* Tune timeout */
static unsigned int tune_timeout = 3000;
module_param(tune_timeout, uint, 0644);
MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
/* Seek timeout */
static unsigned int seek_timeout = 5000;
module_param(seek_timeout, uint, 0644);
MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
/**************************************************************************
* Generic Functions
**************************************************************************/
/*
* si470x_set_chan - set the channel
*/
static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
{
int retval;
unsigned long timeout;
bool timed_out = 0;
/* start tuning */
radio->registers[CHANNEL] &= ~CHANNEL_CHAN;
radio->registers[CHANNEL] |= CHANNEL_TUNE | chan;
retval = si470x_set_register(radio, CHANNEL);
if (retval < 0)
goto done;
/* wait till tune operation has completed */
timeout = jiffies + msecs_to_jiffies(tune_timeout);
do {
retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0)
goto stop;
timed_out = time_after(jiffies, timeout);
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
(!timed_out));
if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
dev_warn(&radio->videodev->dev, "tune does not complete\n");
if (timed_out)
dev_warn(&radio->videodev->dev,
"tune timed out after %u ms\n", tune_timeout);
stop:
/* stop tuning */
radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
retval = si470x_set_register(radio, CHANNEL);
done:
return retval;
}
/*
* si470x_get_freq - get the frequency
*/
static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
{
unsigned int spacing, band_bottom;
unsigned short chan;
int retval;
/* Spacing (kHz) */
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
/* 0: 200 kHz (USA, Australia) */
case 0:
spacing = 0.200 * FREQ_MUL; break;
/* 1: 100 kHz (Europe, Japan) */
case 1:
spacing = 0.100 * FREQ_MUL; break;
/* 2: 50 kHz */
default:
spacing = 0.050 * FREQ_MUL; break;
};
/* Bottom of Band (MHz) */
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
/* 0: 87.5 - 108 MHz (USA, Europe) */
case 0:
band_bottom = 87.5 * FREQ_MUL; break;
/* 1: 76 - 108 MHz (Japan wide band) */
default:
band_bottom = 76 * FREQ_MUL; break;
/* 2: 76 - 90 MHz (Japan) */
case 2:
band_bottom = 76 * FREQ_MUL; break;
};
/* read channel */
retval = si470x_get_register(radio, READCHAN);
chan = radio->registers[READCHAN] & READCHAN_READCHAN;
/* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */
*freq = chan * spacing + band_bottom;
return retval;
}
/*
* si470x_set_freq - set the frequency
*/
int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
{
unsigned int spacing, band_bottom;
unsigned short chan;
/* Spacing (kHz) */
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
/* 0: 200 kHz (USA, Australia) */
case 0:
spacing = 0.200 * FREQ_MUL; break;
/* 1: 100 kHz (Europe, Japan) */
case 1:
spacing = 0.100 * FREQ_MUL; break;
/* 2: 50 kHz */
default:
spacing = 0.050 * FREQ_MUL; break;
};
/* Bottom of Band (MHz) */
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
/* 0: 87.5 - 108 MHz (USA, Europe) */
case 0:
band_bottom = 87.5 * FREQ_MUL; break;
/* 1: 76 - 108 MHz (Japan wide band) */
default:
band_bottom = 76 * FREQ_MUL; break;
/* 2: 76 - 90 MHz (Japan) */
case 2:
band_bottom = 76 * FREQ_MUL; break;
};
/* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
chan = (freq - band_bottom) / spacing;
return si470x_set_chan(radio, chan);
}
/*
* si470x_set_seek - set seek
*/
static int si470x_set_seek(struct si470x_device *radio,
unsigned int wrap_around, unsigned int seek_upward)
{
int retval = 0;
unsigned long timeout;
bool timed_out = 0;
/* start seeking */
radio->registers[POWERCFG] |= POWERCFG_SEEK;
if (wrap_around == 1)
radio->registers[POWERCFG] &= ~POWERCFG_SKMODE;
else
radio->registers[POWERCFG] |= POWERCFG_SKMODE;
if (seek_upward == 1)
radio->registers[POWERCFG] |= POWERCFG_SEEKUP;
else
radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
retval = si470x_set_register(radio, POWERCFG);
if (retval < 0)
goto done;
/* wait till seek operation has completed */
timeout = jiffies + msecs_to_jiffies(seek_timeout);
do {
retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0)
goto stop;
timed_out = time_after(jiffies, timeout);
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
(!timed_out));
if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
dev_warn(&radio->videodev->dev, "seek does not complete\n");
if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
dev_warn(&radio->videodev->dev,
"seek failed / band limit reached\n");
if (timed_out)
dev_warn(&radio->videodev->dev,
"seek timed out after %u ms\n", seek_timeout);
stop:
/* stop seeking */
radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
retval = si470x_set_register(radio, POWERCFG);
done:
/* try again, if timed out */
if ((retval == 0) && timed_out)
retval = -EAGAIN;
return retval;
}
/*
* si470x_start - switch on radio
*/
int si470x_start(struct si470x_device *radio)
{
int retval;
/* powercfg */
radio->registers[POWERCFG] =
POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
retval = si470x_set_register(radio, POWERCFG);
if (retval < 0)
goto done;
/* sysconfig 1 */
radio->registers[SYSCONFIG1] = SYSCONFIG1_DE;
retval = si470x_set_register(radio, SYSCONFIG1);
if (retval < 0)
goto done;
/* sysconfig 2 */
radio->registers[SYSCONFIG2] =
(0x3f << 8) | /* SEEKTH */
((band << 6) & SYSCONFIG2_BAND) | /* BAND */
((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */
15; /* VOLUME (max) */
retval = si470x_set_register(radio, SYSCONFIG2);
if (retval < 0)
goto done;
/* reset last channel */
retval = si470x_set_chan(radio,
radio->registers[CHANNEL] & CHANNEL_CHAN);
done:
return retval;
}
/*
* si470x_stop - switch off radio
*/
int si470x_stop(struct si470x_device *radio)
{
int retval;
/* sysconfig 1 */
radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
retval = si470x_set_register(radio, SYSCONFIG1);
if (retval < 0)
goto done;
/* powercfg */
radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
/* POWERCFG_ENABLE has to automatically go low */
radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE;
retval = si470x_set_register(radio, POWERCFG);
done:
return retval;
}
/*
* si470x_rds_on - switch on rds reception
*/
int si470x_rds_on(struct si470x_device *radio)
{
int retval;
/* sysconfig 1 */
mutex_lock(&radio->lock);
radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS;
retval = si470x_set_register(radio, SYSCONFIG1);
if (retval < 0)
radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
mutex_unlock(&radio->lock);
return retval;
}
/**************************************************************************
* Video4Linux Interface
**************************************************************************/
/*
* si470x_vidioc_queryctrl - enumerate control items
*/
static int si470x_vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc)
{
struct si470x_device *radio = video_drvdata(file);
int retval = -EINVAL;
/* abort if qc->id is below V4L2_CID_BASE */
if (qc->id < V4L2_CID_BASE)
goto done;
/* search video control */
switch (qc->id) {
case V4L2_CID_AUDIO_VOLUME:
return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15);
case V4L2_CID_AUDIO_MUTE:
return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
}
/* disable unsupported base controls */
/* to satisfy kradio and such apps */
if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) {
qc->flags = V4L2_CTRL_FLAG_DISABLED;
retval = 0;
}
done:
if (retval < 0)
dev_warn(&radio->videodev->dev,
"query controls failed with %d\n", retval);
return retval;
}
/*
* si470x_vidioc_g_ctrl - get the value of a control
*/
static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
retval = si470x_disconnect_check(radio);
if (retval)
goto done;
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME:
ctrl->value = radio->registers[SYSCONFIG2] &
SYSCONFIG2_VOLUME;
break;
case V4L2_CID_AUDIO_MUTE:
ctrl->value = ((radio->registers[POWERCFG] &
POWERCFG_DMUTE) == 0) ? 1 : 0;
break;
default:
retval = -EINVAL;
}
done:
if (retval < 0)
dev_warn(&radio->videodev->dev,
"get control failed with %d\n", retval);
return retval;
}
/*
* si470x_vidioc_s_ctrl - set the value of a control
*/
static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
retval = si470x_disconnect_check(radio);
if (retval)
goto done;
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME:
radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
radio->registers[SYSCONFIG2] |= ctrl->value;
retval = si470x_set_register(radio, SYSCONFIG2);
break;
case V4L2_CID_AUDIO_MUTE:
if (ctrl->value == 1)
radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
else
radio->registers[POWERCFG] |= POWERCFG_DMUTE;
retval = si470x_set_register(radio, POWERCFG);
break;
default:
retval = -EINVAL;
}
done:
if (retval < 0)
dev_warn(&radio->videodev->dev,
"set control failed with %d\n", retval);
return retval;
}
/*
* si470x_vidioc_g_audio - get audio attributes
*/
static int si470x_vidioc_g_audio(struct file *file, void *priv,
struct v4l2_audio *audio)
{
/* driver constants */
audio->index = 0;
strcpy(audio->name, "Radio");
audio->capability = V4L2_AUDCAP_STEREO;
audio->mode = 0;
return 0;
}
/*
* si470x_vidioc_g_tuner - get tuner attributes
*/
static int si470x_vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
retval = si470x_disconnect_check(radio);
if (retval)
goto done;
if (tuner->index != 0) {
retval = -EINVAL;
goto done;
}
retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0)
goto done;
/* driver constants */
strcpy(tuner->name, "FM");
tuner->type = V4L2_TUNER_RADIO;
#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_RDS;
#else
tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
#endif
/* range limits */
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
/* 0: 87.5 - 108 MHz (USA, Europe, default) */
default:
tuner->rangelow = 87.5 * FREQ_MUL;
tuner->rangehigh = 108 * FREQ_MUL;
break;
/* 1: 76 - 108 MHz (Japan wide band) */
case 1:
tuner->rangelow = 76 * FREQ_MUL;
tuner->rangehigh = 108 * FREQ_MUL;
break;
/* 2: 76 - 90 MHz (Japan) */
case 2:
tuner->rangelow = 76 * FREQ_MUL;
tuner->rangehigh = 90 * FREQ_MUL;
break;
};
/* stereo indicator == stereo (instead of mono) */
if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
else
tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
/* If there is a reliable method of detecting an RDS channel,
then this code should check for that before setting this
RDS subchannel. */
tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;
#endif
/* mono/stereo selector */
if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
tuner->audmode = V4L2_TUNER_MODE_STEREO;
else
tuner->audmode = V4L2_TUNER_MODE_MONO;
/* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
/* measured in units of db쨉V in 1 db increments (max at ~75 db쨉V) */
tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
/* the ideal factor is 0xffff/75 = 873,8 */
tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
/* automatic frequency control: -1: freq to low, 1 freq to high */
/* AFCRL does only indicate that freq. differs, not if too low/high */
tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0;
done:
if (retval < 0)
dev_warn(&radio->videodev->dev,
"get tuner failed with %d\n", retval);
return retval;
}
/*
* si470x_vidioc_s_tuner - set tuner attributes
*/
static int si470x_vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner)
{
struct si470x_device *radio = video_drvdata(file);
int retval = -EINVAL;
/* safety checks */
retval = si470x_disconnect_check(radio);
if (retval)
goto done;
if (tuner->index != 0)
goto done;
/* mono/stereo selector */
switch (tuner->audmode) {
case V4L2_TUNER_MODE_MONO:
radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
break;
case V4L2_TUNER_MODE_STEREO:
radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
break;
default:
goto done;
}
retval = si470x_set_register(radio, POWERCFG);
done:
if (retval < 0)
dev_warn(&radio->videodev->dev,
"set tuner failed with %d\n", retval);
return retval;
}
/*
* si470x_vidioc_g_frequency - get tuner or modulator radio frequency
*/
static int si470x_vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *freq)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
retval = si470x_disconnect_check(radio);
if (retval)
goto done;
if (freq->tuner != 0) {
retval = -EINVAL;
goto done;
}
freq->type = V4L2_TUNER_RADIO;
retval = si470x_get_freq(radio, &freq->frequency);
done:
if (retval < 0)
dev_warn(&radio->videodev->dev,
"get frequency failed with %d\n", retval);
return retval;
}
/*
* si470x_vidioc_s_frequency - set tuner or modulator radio frequency
*/
static int si470x_vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *freq)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
retval = si470x_disconnect_check(radio);
if (retval)
goto done;
if (freq->tuner != 0) {
retval = -EINVAL;
goto done;
}
retval = si470x_set_freq(radio, freq->frequency);
done:
if (retval < 0)
dev_warn(&radio->videodev->dev,
"set frequency failed with %d\n", retval);
return retval;
}
/*
* si470x_vidioc_s_hw_freq_seek - set hardware frequency seek
*/
static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
struct v4l2_hw_freq_seek *seek)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
retval = si470x_disconnect_check(radio);
if (retval)
goto done;
if (seek->tuner != 0) {
retval = -EINVAL;
goto done;
}
retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward);
done:
if (retval < 0)
dev_warn(&radio->videodev->dev,
"set hardware frequency seek failed with %d\n", retval);
return retval;
}
/*
* si470x_ioctl_ops - video device ioctl operations
*/
static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
.vidioc_querycap = si470x_vidioc_querycap,
.vidioc_queryctrl = si470x_vidioc_queryctrl,
.vidioc_g_ctrl = si470x_vidioc_g_ctrl,
.vidioc_s_ctrl = si470x_vidioc_s_ctrl,
.vidioc_g_audio = si470x_vidioc_g_audio,
.vidioc_g_tuner = si470x_vidioc_g_tuner,
.vidioc_s_tuner = si470x_vidioc_s_tuner,
.vidioc_g_frequency = si470x_vidioc_g_frequency,
.vidioc_s_frequency = si470x_vidioc_s_frequency,
.vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
};
/*
* si470x_viddev_template - video device interface
*/
struct video_device si470x_viddev_template = {
.fops = &si470x_fops,
.name = DRIVER_NAME,
.release = video_device_release,
.ioctl_ops = &si470x_ioctl_ops,
};

View file

@ -0,0 +1,401 @@
/*
* drivers/media/radio/si470x/radio-si470x-i2c.c
*
* I2C driver for radios with Silicon Labs Si470x FM Radio Receivers
*
* Copyright (c) 2009 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* ToDo:
* - RDS support
*/
/* driver definitions */
#define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>";
#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0)
#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
#define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers"
#define DRIVER_VERSION "1.0.0"
/* kernel includes */
#include <linux/i2c.h>
#include <linux/delay.h>
#include "radio-si470x.h"
/* I2C Device ID List */
static const struct i2c_device_id si470x_i2c_id[] = {
/* Generic Entry */
{ "si470x", 0 },
/* Terminating entry */
{ }
};
MODULE_DEVICE_TABLE(i2c, si470x_i2c_id);
/**************************************************************************
* Module Parameters
**************************************************************************/
/* Radio Nr */
static int radio_nr = -1;
module_param(radio_nr, int, 0444);
MODULE_PARM_DESC(radio_nr, "Radio Nr");
/**************************************************************************
* I2C Definitions
**************************************************************************/
/* Write starts with the upper byte of register 0x02 */
#define WRITE_REG_NUM 8
#define WRITE_INDEX(i) (i + 0x02)
/* Read starts with the upper byte of register 0x0a */
#define READ_REG_NUM RADIO_REGISTER_NUM
#define READ_INDEX(i) ((i + RADIO_REGISTER_NUM - 0x0a) % READ_REG_NUM)
/**************************************************************************
* General Driver Functions - REGISTERs
**************************************************************************/
/*
* si470x_get_register - read register
*/
int si470x_get_register(struct si470x_device *radio, int regnr)
{
u16 buf[READ_REG_NUM];
struct i2c_msg msgs[1] = {
{ radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM,
(void *)buf },
};
if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
return -EIO;
radio->registers[regnr] = __be16_to_cpu(buf[READ_INDEX(regnr)]);
return 0;
}
/*
* si470x_set_register - write register
*/
int si470x_set_register(struct si470x_device *radio, int regnr)
{
int i;
u16 buf[WRITE_REG_NUM];
struct i2c_msg msgs[1] = {
{ radio->client->addr, 0, sizeof(u16) * WRITE_REG_NUM,
(void *)buf },
};
for (i = 0; i < WRITE_REG_NUM; i++)
buf[i] = __cpu_to_be16(radio->registers[WRITE_INDEX(i)]);
if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
return -EIO;
return 0;
}
/**************************************************************************
* General Driver Functions - ENTIRE REGISTERS
**************************************************************************/
/*
* si470x_get_all_registers - read entire registers
*/
static int si470x_get_all_registers(struct si470x_device *radio)
{
int i;
u16 buf[READ_REG_NUM];
struct i2c_msg msgs[1] = {
{ radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM,
(void *)buf },
};
if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
return -EIO;
for (i = 0; i < READ_REG_NUM; i++)
radio->registers[i] = __be16_to_cpu(buf[READ_INDEX(i)]);
return 0;
}
/**************************************************************************
* General Driver Functions - DISCONNECT_CHECK
**************************************************************************/
/*
* si470x_disconnect_check - check whether radio disconnects
*/
int si470x_disconnect_check(struct si470x_device *radio)
{
return 0;
}
/**************************************************************************
* File Operations Interface
**************************************************************************/
/*
* si470x_fops_open - file open
*/
static int si470x_fops_open(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
mutex_lock(&radio->lock);
radio->users++;
if (radio->users == 1)
/* start radio */
retval = si470x_start(radio);
mutex_unlock(&radio->lock);
return retval;
}
/*
* si470x_fops_release - file release
*/
static int si470x_fops_release(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety check */
if (!radio)
return -ENODEV;
mutex_lock(&radio->lock);
radio->users--;
if (radio->users == 0)
/* stop radio */
retval = si470x_stop(radio);
mutex_unlock(&radio->lock);
return retval;
}
/*
* si470x_fops - file operations interface
*/
const struct v4l2_file_operations si470x_fops = {
.owner = THIS_MODULE,
.ioctl = video_ioctl2,
.open = si470x_fops_open,
.release = si470x_fops_release,
};
/**************************************************************************
* Video4Linux Interface
**************************************************************************/
/*
* si470x_vidioc_querycap - query device capabilities
*/
int si470x_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *capability)
{
strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
capability->version = DRIVER_KERNEL_VERSION;
capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
V4L2_CAP_TUNER | V4L2_CAP_RADIO;
return 0;
}
/**************************************************************************
* I2C Interface
**************************************************************************/
/*
* si470x_i2c_probe - probe for the device
*/
static int __devinit si470x_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct si470x_device *radio;
int retval = 0;
unsigned char version_warning = 0;
/* private data allocation and initialization */
radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
if (!radio) {
retval = -ENOMEM;
goto err_initial;
}
radio->users = 0;
radio->client = client;
mutex_init(&radio->lock);
/* video device allocation and initialization */
radio->videodev = video_device_alloc();
if (!radio->videodev) {
retval = -ENOMEM;
goto err_radio;
}
memcpy(radio->videodev, &si470x_viddev_template,
sizeof(si470x_viddev_template));
video_set_drvdata(radio->videodev, radio);
/* power up : need 110ms */
radio->registers[POWERCFG] = POWERCFG_ENABLE;
if (si470x_set_register(radio, POWERCFG) < 0) {
retval = -EIO;
goto err_all;
}
msleep(110);
/* get device and chip versions */
if (si470x_get_all_registers(radio) < 0) {
retval = -EIO;
goto err_video;
}
dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
radio->registers[DEVICEID], radio->registers[CHIPID]);
if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_FW_VERSION) {
dev_warn(&client->dev,
"This driver is known to work with "
"firmware version %hu,\n", RADIO_FW_VERSION);
dev_warn(&client->dev,
"but the device has firmware version %hu.\n",
radio->registers[CHIPID] & CHIPID_FIRMWARE);
version_warning = 1;
}
/* give out version warning */
if (version_warning == 1) {
dev_warn(&client->dev,
"If you have some trouble using this driver,\n");
dev_warn(&client->dev,
"please report to V4L ML at "
"linux-media@vger.kernel.org\n");
}
/* set initial frequency */
si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
/* register video device */
retval = video_register_device(radio->videodev, VFL_TYPE_RADIO,
radio_nr);
if (retval) {
dev_warn(&client->dev, "Could not register video device\n");
goto err_all;
}
i2c_set_clientdata(client, radio);
return 0;
err_all:
err_video:
video_device_release(radio->videodev);
err_radio:
kfree(radio);
err_initial:
return retval;
}
/*
* si470x_i2c_remove - remove the device
*/
static __devexit int si470x_i2c_remove(struct i2c_client *client)
{
struct si470x_device *radio = i2c_get_clientdata(client);
video_unregister_device(radio->videodev);
kfree(radio);
i2c_set_clientdata(client, NULL);
return 0;
}
/*
* si470x_i2c_driver - i2c driver interface
*/
static struct i2c_driver si470x_i2c_driver = {
.driver = {
.name = "si470x",
.owner = THIS_MODULE,
},
.probe = si470x_i2c_probe,
.remove = __devexit_p(si470x_i2c_remove),
.id_table = si470x_i2c_id,
};
/**************************************************************************
* Module Interface
**************************************************************************/
/*
* si470x_i2c_init - module init
*/
static int __init si470x_i2c_init(void)
{
printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n");
return i2c_add_driver(&si470x_i2c_driver);
}
/*
* si470x_i2c_exit - module exit
*/
static void __exit si470x_i2c_exit(void)
{
i2c_del_driver(&si470x_i2c_driver);
}
module_init(si470x_i2c_init);
module_exit(si470x_i2c_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);

View file

@ -0,0 +1,988 @@
/*
* drivers/media/radio/si470x/radio-si470x-usb.c
*
* USB driver for radios with Silicon Labs Si470x FM Radio Receivers
*
* Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* ToDo:
* - add firmware download/update support
*/
/* driver definitions */
#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 10)
#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
#define DRIVER_VERSION "1.0.10"
/* kernel includes */
#include <linux/usb.h>
#include <linux/hid.h>
#include "radio-si470x.h"
/* USB Device ID List */
static struct usb_device_id si470x_usb_driver_id_table[] = {
/* Silicon Labs USB FM Radio Reference Design */
{ USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
/* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
/* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) },
/* Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) },
/* Terminating entry */
{ }
};
MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table);
/**************************************************************************
* Module Parameters
**************************************************************************/
/* Radio Nr */
static int radio_nr = -1;
module_param(radio_nr, int, 0444);
MODULE_PARM_DESC(radio_nr, "Radio Nr");
/* USB timeout */
static unsigned int usb_timeout = 500;
module_param(usb_timeout, uint, 0644);
MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*");
/* RDS buffer blocks */
static unsigned int rds_buf = 100;
module_param(rds_buf, uint, 0444);
MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
/* RDS maximum block errors */
static unsigned short max_rds_errors = 1;
/* 0 means 0 errors requiring correction */
/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */
/* 2 means 3-5 errors requiring correction */
/* 3 means 6+ errors or errors in checkword, correction not possible */
module_param(max_rds_errors, ushort, 0644);
MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
/**************************************************************************
* USB HID Reports
**************************************************************************/
/* Reports 1-16 give direct read/write access to the 16 Si470x registers */
/* with the (REPORT_ID - 1) corresponding to the register address across USB */
/* endpoint 0 using GET_REPORT and SET_REPORT */
#define REGISTER_REPORT_SIZE (RADIO_REGISTER_SIZE + 1)
#define REGISTER_REPORT(reg) ((reg) + 1)
/* Report 17 gives direct read/write access to the entire Si470x register */
/* map across endpoint 0 using GET_REPORT and SET_REPORT */
#define ENTIRE_REPORT_SIZE (RADIO_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)
#define ENTIRE_REPORT 17
/* Report 18 is used to send the lowest 6 Si470x registers up the HID */
/* interrupt endpoint 1 to Windows every 20 milliseconds for status */
#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)
#define RDS_REPORT 18
/* Report 19: LED state */
#define LED_REPORT_SIZE 3
#define LED_REPORT 19
/* Report 19: stream */
#define STREAM_REPORT_SIZE 3
#define STREAM_REPORT 19
/* Report 20: scratch */
#define SCRATCH_PAGE_SIZE 63
#define SCRATCH_REPORT_SIZE (SCRATCH_PAGE_SIZE + 1)
#define SCRATCH_REPORT 20
/* Reports 19-22: flash upgrade of the C8051F321 */
#define WRITE_REPORT_SIZE 4
#define WRITE_REPORT 19
#define FLASH_REPORT_SIZE 64
#define FLASH_REPORT 20
#define CRC_REPORT_SIZE 3
#define CRC_REPORT 21
#define RESPONSE_REPORT_SIZE 2
#define RESPONSE_REPORT 22
/* Report 23: currently unused, but can accept 60 byte reports on the HID */
/* interrupt out endpoint 2 every 1 millisecond */
#define UNUSED_REPORT 23
/**************************************************************************
* Software/Hardware Versions from Scratch Page
**************************************************************************/
#define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6
#define RADIO_SW_VERSION 7
#define RADIO_HW_VERSION 1
/**************************************************************************
* LED State Definitions
**************************************************************************/
#define LED_COMMAND 0x35
#define NO_CHANGE_LED 0x00
#define ALL_COLOR_LED 0x01 /* streaming state */
#define BLINK_GREEN_LED 0x02 /* connect state */
#define BLINK_RED_LED 0x04
#define BLINK_ORANGE_LED 0x10 /* disconnect state */
#define SOLID_GREEN_LED 0x20 /* tuning/seeking state */
#define SOLID_RED_LED 0x40 /* bootload state */
#define SOLID_ORANGE_LED 0x80
/**************************************************************************
* Stream State Definitions
**************************************************************************/
#define STREAM_COMMAND 0x36
#define STREAM_VIDPID 0x00
#define STREAM_AUDIO 0xff
/**************************************************************************
* Bootloader / Flash Commands
**************************************************************************/
/* unique id sent to bootloader and required to put into a bootload state */
#define UNIQUE_BL_ID 0x34
/* mask for the flash data */
#define FLASH_DATA_MASK 0x55
/* bootloader commands */
#define GET_SW_VERSION_COMMAND 0x00
#define SET_PAGE_COMMAND 0x01
#define ERASE_PAGE_COMMAND 0x02
#define WRITE_PAGE_COMMAND 0x03
#define CRC_ON_PAGE_COMMAND 0x04
#define READ_FLASH_BYTE_COMMAND 0x05
#define RESET_DEVICE_COMMAND 0x06
#define GET_HW_VERSION_COMMAND 0x07
#define BLANK 0xff
/* bootloader command responses */
#define COMMAND_OK 0x01
#define COMMAND_FAILED 0x02
#define COMMAND_PENDING 0x03
/**************************************************************************
* General Driver Functions - REGISTER_REPORTs
**************************************************************************/
/*
* si470x_get_report - receive a HID report
*/
static int si470x_get_report(struct si470x_device *radio, void *buf, int size)
{
unsigned char *report = (unsigned char *) buf;
int retval;
retval = usb_control_msg(radio->usbdev,
usb_rcvctrlpipe(radio->usbdev, 0),
HID_REQ_GET_REPORT,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
report[0], 2,
buf, size, usb_timeout);
if (retval < 0)
dev_warn(&radio->intf->dev,
"si470x_get_report: usb_control_msg returned %d\n",
retval);
return retval;
}
/*
* si470x_set_report - send a HID report
*/
static int si470x_set_report(struct si470x_device *radio, void *buf, int size)
{
unsigned char *report = (unsigned char *) buf;
int retval;
retval = usb_control_msg(radio->usbdev,
usb_sndctrlpipe(radio->usbdev, 0),
HID_REQ_SET_REPORT,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
report[0], 2,
buf, size, usb_timeout);
if (retval < 0)
dev_warn(&radio->intf->dev,
"si470x_set_report: usb_control_msg returned %d\n",
retval);
return retval;
}
/*
* si470x_get_register - read register
*/
int si470x_get_register(struct si470x_device *radio, int regnr)
{
unsigned char buf[REGISTER_REPORT_SIZE];
int retval;
buf[0] = REGISTER_REPORT(regnr);
retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
if (retval >= 0)
radio->registers[regnr] = get_unaligned_be16(&buf[1]);
return (retval < 0) ? -EINVAL : 0;
}
/*
* si470x_set_register - write register
*/
int si470x_set_register(struct si470x_device *radio, int regnr)
{
unsigned char buf[REGISTER_REPORT_SIZE];
int retval;
buf[0] = REGISTER_REPORT(regnr);
put_unaligned_be16(radio->registers[regnr], &buf[1]);
retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
return (retval < 0) ? -EINVAL : 0;
}
/**************************************************************************
* General Driver Functions - ENTIRE_REPORT
**************************************************************************/
/*
* si470x_get_all_registers - read entire registers
*/
static int si470x_get_all_registers(struct si470x_device *radio)
{
unsigned char buf[ENTIRE_REPORT_SIZE];
int retval;
unsigned char regnr;
buf[0] = ENTIRE_REPORT;
retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
if (retval >= 0)
for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
radio->registers[regnr] = get_unaligned_be16(
&buf[regnr * RADIO_REGISTER_SIZE + 1]);
return (retval < 0) ? -EINVAL : 0;
}
/**************************************************************************
* General Driver Functions - LED_REPORT
**************************************************************************/
/*
* si470x_set_led_state - sets the led state
*/
static int si470x_set_led_state(struct si470x_device *radio,
unsigned char led_state)
{
unsigned char buf[LED_REPORT_SIZE];
int retval;
buf[0] = LED_REPORT;
buf[1] = LED_COMMAND;
buf[2] = led_state;
retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
return (retval < 0) ? -EINVAL : 0;
}
/**************************************************************************
* General Driver Functions - SCRATCH_REPORT
**************************************************************************/
/*
* si470x_get_scratch_versions - gets the scratch page and version infos
*/
static int si470x_get_scratch_page_versions(struct si470x_device *radio)
{
unsigned char buf[SCRATCH_REPORT_SIZE];
int retval;
buf[0] = SCRATCH_REPORT;
retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
if (retval < 0)
dev_warn(&radio->intf->dev, "si470x_get_scratch: "
"si470x_get_report returned %d\n", retval);
else {
radio->software_version = buf[1];
radio->hardware_version = buf[2];
}
return (retval < 0) ? -EINVAL : 0;
}
/**************************************************************************
* General Driver Functions - DISCONNECT_CHECK
**************************************************************************/
/*
* si470x_disconnect_check - check whether radio disconnects
*/
int si470x_disconnect_check(struct si470x_device *radio)
{
if (radio->disconnected)
return -EIO;
else
return 0;
}
/**************************************************************************
* RDS Driver Functions
**************************************************************************/
/*
* si470x_int_in_callback - rds callback and processing function
*
* TODO: do we need to use mutex locks in some sections?
*/
static void si470x_int_in_callback(struct urb *urb)
{
struct si470x_device *radio = urb->context;
unsigned char buf[RDS_REPORT_SIZE];
int retval;
unsigned char regnr;
unsigned char blocknum;
unsigned short bler; /* rds block errors */
unsigned short rds;
unsigned char tmpbuf[3];
if (urb->status) {
if (urb->status == -ENOENT ||
urb->status == -ECONNRESET ||
urb->status == -ESHUTDOWN) {
return;
} else {
dev_warn(&radio->intf->dev,
"non-zero urb status (%d)\n", urb->status);
goto resubmit; /* Maybe we can recover. */
}
}
/* safety checks */
if (radio->disconnected)
return;
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
goto resubmit;
if (urb->actual_length > 0) {
/* Update RDS registers with URB data */
buf[0] = RDS_REPORT;
for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
radio->registers[STATUSRSSI + regnr] =
get_unaligned_be16(&radio->int_in_buffer[
regnr * RADIO_REGISTER_SIZE + 1]);
/* get rds blocks */
if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) {
/* No RDS group ready, better luck next time */
goto resubmit;
}
if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSS) == 0) {
/* RDS decoder not synchronized */
goto resubmit;
}
for (blocknum = 0; blocknum < 4; blocknum++) {
switch (blocknum) {
default:
bler = (radio->registers[STATUSRSSI] &
STATUSRSSI_BLERA) >> 9;
rds = radio->registers[RDSA];
break;
case 1:
bler = (radio->registers[READCHAN] &
READCHAN_BLERB) >> 14;
rds = radio->registers[RDSB];
break;
case 2:
bler = (radio->registers[READCHAN] &
READCHAN_BLERC) >> 12;
rds = radio->registers[RDSC];
break;
case 3:
bler = (radio->registers[READCHAN] &
READCHAN_BLERD) >> 10;
rds = radio->registers[RDSD];
break;
};
/* Fill the V4L2 RDS buffer */
put_unaligned_le16(rds, &tmpbuf);
tmpbuf[2] = blocknum; /* offset name */
tmpbuf[2] |= blocknum << 3; /* received offset */
if (bler > max_rds_errors)
tmpbuf[2] |= 0x80; /* uncorrectable errors */
else if (bler > 0)
tmpbuf[2] |= 0x40; /* corrected error(s) */
/* copy RDS block to internal buffer */
memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);
radio->wr_index += 3;
/* wrap write pointer */
if (radio->wr_index >= radio->buf_size)
radio->wr_index = 0;
/* check for overflow */
if (radio->wr_index == radio->rd_index) {
/* increment and wrap read pointer */
radio->rd_index += 3;
if (radio->rd_index >= radio->buf_size)
radio->rd_index = 0;
}
}
if (radio->wr_index != radio->rd_index)
wake_up_interruptible(&radio->read_queue);
}
resubmit:
/* Resubmit if we're still running. */
if (radio->int_in_running && radio->usbdev) {
retval = usb_submit_urb(radio->int_in_urb, GFP_ATOMIC);
if (retval) {
dev_warn(&radio->intf->dev,
"resubmitting urb failed (%d)", retval);
radio->int_in_running = 0;
}
}
}
/**************************************************************************
* File Operations Interface
**************************************************************************/
/*
* si470x_fops_read - read RDS data
*/
static ssize_t si470x_fops_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
unsigned int block_count = 0;
/* switch on rds reception */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
si470x_rds_on(radio);
/* block if no new data available */
while (radio->wr_index == radio->rd_index) {
if (file->f_flags & O_NONBLOCK) {
retval = -EWOULDBLOCK;
goto done;
}
if (wait_event_interruptible(radio->read_queue,
radio->wr_index != radio->rd_index) < 0) {
retval = -EINTR;
goto done;
}
}
/* calculate block count from byte count */
count /= 3;
/* copy RDS block out of internal buffer and to user buffer */
mutex_lock(&radio->lock);
while (block_count < count) {
if (radio->rd_index == radio->wr_index)
break;
/* always transfer rds complete blocks */
if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
/* retval = -EFAULT; */
break;
/* increment and wrap read pointer */
radio->rd_index += 3;
if (radio->rd_index >= radio->buf_size)
radio->rd_index = 0;
/* increment counters */
block_count++;
buf += 3;
retval += 3;
}
mutex_unlock(&radio->lock);
done:
return retval;
}
/*
* si470x_fops_poll - poll RDS data
*/
static unsigned int si470x_fops_poll(struct file *file,
struct poll_table_struct *pts)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* switch on rds reception */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
si470x_rds_on(radio);
poll_wait(file, &radio->read_queue, pts);
if (radio->rd_index != radio->wr_index)
retval = POLLIN | POLLRDNORM;
return retval;
}
/*
* si470x_fops_open - file open
*/
static int si470x_fops_open(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval;
lock_kernel();
radio->users++;
retval = usb_autopm_get_interface(radio->intf);
if (retval < 0) {
radio->users--;
retval = -EIO;
goto done;
}
if (radio->users == 1) {
/* start radio */
retval = si470x_start(radio);
if (retval < 0) {
usb_autopm_put_interface(radio->intf);
goto done;
}
/* initialize interrupt urb */
usb_fill_int_urb(radio->int_in_urb, radio->usbdev,
usb_rcvintpipe(radio->usbdev,
radio->int_in_endpoint->bEndpointAddress),
radio->int_in_buffer,
le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize),
si470x_int_in_callback,
radio,
radio->int_in_endpoint->bInterval);
radio->int_in_running = 1;
mb();
retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL);
if (retval) {
dev_info(&radio->intf->dev,
"submitting int urb failed (%d)\n", retval);
radio->int_in_running = 0;
usb_autopm_put_interface(radio->intf);
}
}
done:
unlock_kernel();
return retval;
}
/*
* si470x_fops_release - file release
*/
static int si470x_fops_release(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety check */
if (!radio) {
retval = -ENODEV;
goto done;
}
mutex_lock(&radio->disconnect_lock);
radio->users--;
if (radio->users == 0) {
/* shutdown interrupt handler */
if (radio->int_in_running) {
radio->int_in_running = 0;
if (radio->int_in_urb)
usb_kill_urb(radio->int_in_urb);
}
if (radio->disconnected) {
video_unregister_device(radio->videodev);
kfree(radio->int_in_buffer);
kfree(radio->buffer);
kfree(radio);
goto unlock;
}
/* cancel read processes */
wake_up_interruptible(&radio->read_queue);
/* stop radio */
retval = si470x_stop(radio);
usb_autopm_put_interface(radio->intf);
}
unlock:
mutex_unlock(&radio->disconnect_lock);
done:
return retval;
}
/*
* si470x_fops - file operations interface
*/
const struct v4l2_file_operations si470x_fops = {
.owner = THIS_MODULE,
.read = si470x_fops_read,
.poll = si470x_fops_poll,
.ioctl = video_ioctl2,
.open = si470x_fops_open,
.release = si470x_fops_release,
};
/**************************************************************************
* Video4Linux Interface
**************************************************************************/
/*
* si470x_vidioc_querycap - query device capabilities
*/
int si470x_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *capability)
{
struct si470x_device *radio = video_drvdata(file);
strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
usb_make_path(radio->usbdev, capability->bus_info,
sizeof(capability->bus_info));
capability->version = DRIVER_KERNEL_VERSION;
capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
return 0;
}
/**************************************************************************
* USB Interface
**************************************************************************/
/*
* si470x_usb_driver_probe - probe for the device
*/
static int si470x_usb_driver_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct si470x_device *radio;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int i, int_end_size, retval = 0;
unsigned char version_warning = 0;
/* private data allocation and initialization */
radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
if (!radio) {
retval = -ENOMEM;
goto err_initial;
}
radio->users = 0;
radio->disconnected = 0;
radio->usbdev = interface_to_usbdev(intf);
radio->intf = intf;
mutex_init(&radio->disconnect_lock);
mutex_init(&radio->lock);
iface_desc = intf->cur_altsetting;
/* Set up interrupt endpoint information. */
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
USB_DIR_IN) && ((endpoint->bmAttributes &
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT))
radio->int_in_endpoint = endpoint;
}
if (!radio->int_in_endpoint) {
dev_info(&intf->dev, "could not find interrupt in endpoint\n");
retval = -EIO;
goto err_radio;
}
int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize);
radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL);
if (!radio->int_in_buffer) {
dev_info(&intf->dev, "could not allocate int_in_buffer");
retval = -ENOMEM;
goto err_radio;
}
radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!radio->int_in_urb) {
dev_info(&intf->dev, "could not allocate int_in_urb");
retval = -ENOMEM;
goto err_intbuffer;
}
/* video device allocation and initialization */
radio->videodev = video_device_alloc();
if (!radio->videodev) {
retval = -ENOMEM;
goto err_intbuffer;
}
memcpy(radio->videodev, &si470x_viddev_template,
sizeof(si470x_viddev_template));
video_set_drvdata(radio->videodev, radio);
/* get device and chip versions */
if (si470x_get_all_registers(radio) < 0) {
retval = -EIO;
goto err_video;
}
dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
radio->registers[DEVICEID], radio->registers[CHIPID]);
if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_FW_VERSION) {
dev_warn(&intf->dev,
"This driver is known to work with "
"firmware version %hu,\n", RADIO_FW_VERSION);
dev_warn(&intf->dev,
"but the device has firmware version %hu.\n",
radio->registers[CHIPID] & CHIPID_FIRMWARE);
version_warning = 1;
}
/* get software and hardware versions */
if (si470x_get_scratch_page_versions(radio) < 0) {
retval = -EIO;
goto err_video;
}
dev_info(&intf->dev, "software version %d, hardware version %d\n",
radio->software_version, radio->hardware_version);
if (radio->software_version < RADIO_SW_VERSION) {
dev_warn(&intf->dev,
"This driver is known to work with "
"software version %hu,\n", RADIO_SW_VERSION);
dev_warn(&intf->dev,
"but the device has software version %hu.\n",
radio->software_version);
version_warning = 1;
}
if (radio->hardware_version < RADIO_HW_VERSION) {
dev_warn(&intf->dev,
"This driver is known to work with "
"hardware version %hu,\n", RADIO_HW_VERSION);
dev_warn(&intf->dev,
"but the device has hardware version %hu.\n",
radio->hardware_version);
version_warning = 1;
}
/* give out version warning */
if (version_warning == 1) {
dev_warn(&intf->dev,
"If you have some trouble using this driver,\n");
dev_warn(&intf->dev,
"please report to V4L ML at "
"linux-media@vger.kernel.org\n");
}
/* set initial frequency */
si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
/* set led to connect state */
si470x_set_led_state(radio, BLINK_GREEN_LED);
/* rds buffer allocation */
radio->buf_size = rds_buf * 3;
radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
if (!radio->buffer) {
retval = -EIO;
goto err_video;
}
/* rds buffer configuration */
radio->wr_index = 0;
radio->rd_index = 0;
init_waitqueue_head(&radio->read_queue);
/* register video device */
retval = video_register_device(radio->videodev, VFL_TYPE_RADIO,
radio_nr);
if (retval) {
dev_warn(&intf->dev, "Could not register video device\n");
goto err_all;
}
usb_set_intfdata(intf, radio);
return 0;
err_all:
kfree(radio->buffer);
err_video:
video_device_release(radio->videodev);
err_intbuffer:
kfree(radio->int_in_buffer);
err_radio:
kfree(radio);
err_initial:
return retval;
}
/*
* si470x_usb_driver_suspend - suspend the device
*/
static int si470x_usb_driver_suspend(struct usb_interface *intf,
pm_message_t message)
{
dev_info(&intf->dev, "suspending now...\n");
return 0;
}
/*
* si470x_usb_driver_resume - resume the device
*/
static int si470x_usb_driver_resume(struct usb_interface *intf)
{
dev_info(&intf->dev, "resuming now...\n");
return 0;
}
/*
* si470x_usb_driver_disconnect - disconnect the device
*/
static void si470x_usb_driver_disconnect(struct usb_interface *intf)
{
struct si470x_device *radio = usb_get_intfdata(intf);
mutex_lock(&radio->disconnect_lock);
radio->disconnected = 1;
usb_set_intfdata(intf, NULL);
if (radio->users == 0) {
/* set led to disconnect state */
si470x_set_led_state(radio, BLINK_ORANGE_LED);
/* Free data structures. */
usb_free_urb(radio->int_in_urb);
kfree(radio->int_in_buffer);
video_unregister_device(radio->videodev);
kfree(radio->buffer);
kfree(radio);
}
mutex_unlock(&radio->disconnect_lock);
}
/*
* si470x_usb_driver - usb driver interface
*/
static struct usb_driver si470x_usb_driver = {
.name = DRIVER_NAME,
.probe = si470x_usb_driver_probe,
.disconnect = si470x_usb_driver_disconnect,
.suspend = si470x_usb_driver_suspend,
.resume = si470x_usb_driver_resume,
.id_table = si470x_usb_driver_id_table,
.supports_autosuspend = 1,
};
/**************************************************************************
* Module Interface
**************************************************************************/
/*
* si470x_module_init - module init
*/
static int __init si470x_module_init(void)
{
printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n");
return usb_register(&si470x_usb_driver);
}
/*
* si470x_module_exit - module exit
*/
static void __exit si470x_module_exit(void)
{
usb_deregister(&si470x_usb_driver);
}
module_init(si470x_module_init);
module_exit(si470x_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);

View file

@ -0,0 +1,225 @@
/*
* drivers/media/radio/si470x/radio-si470x.h
*
* Driver for radios with Silicon Labs Si470x FM Radio Receivers
*
* Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* driver definitions */
#define DRIVER_NAME "radio-si470x"
/* kernel includes */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/input.h>
#include <linux/version.h>
#include <linux/videodev2.h>
#include <linux/mutex.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/rds.h>
#include <asm/unaligned.h>
/**************************************************************************
* Register Definitions
**************************************************************************/
#define RADIO_REGISTER_SIZE 2 /* 16 register bit width */
#define RADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */
#define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */
#define DEVICEID 0 /* Device ID */
#define DEVICEID_PN 0xf000 /* bits 15..12: Part Number */
#define DEVICEID_MFGID 0x0fff /* bits 11..00: Manufacturer ID */
#define CHIPID 1 /* Chip ID */
#define CHIPID_REV 0xfc00 /* bits 15..10: Chip Version */
#define CHIPID_DEV 0x0200 /* bits 09..09: Device */
#define CHIPID_FIRMWARE 0x01ff /* bits 08..00: Firmware Version */
#define POWERCFG 2 /* Power Configuration */
#define POWERCFG_DSMUTE 0x8000 /* bits 15..15: Softmute Disable */
#define POWERCFG_DMUTE 0x4000 /* bits 14..14: Mute Disable */
#define POWERCFG_MONO 0x2000 /* bits 13..13: Mono Select */
#define POWERCFG_RDSM 0x0800 /* bits 11..11: RDS Mode (Si4701 only) */
#define POWERCFG_SKMODE 0x0400 /* bits 10..10: Seek Mode */
#define POWERCFG_SEEKUP 0x0200 /* bits 09..09: Seek Direction */
#define POWERCFG_SEEK 0x0100 /* bits 08..08: Seek */
#define POWERCFG_DISABLE 0x0040 /* bits 06..06: Powerup Disable */
#define POWERCFG_ENABLE 0x0001 /* bits 00..00: Powerup Enable */
#define CHANNEL 3 /* Channel */
#define CHANNEL_TUNE 0x8000 /* bits 15..15: Tune */
#define CHANNEL_CHAN 0x03ff /* bits 09..00: Channel Select */
#define SYSCONFIG1 4 /* System Configuration 1 */
#define SYSCONFIG1_RDSIEN 0x8000 /* bits 15..15: RDS Interrupt Enable (Si4701 only) */
#define SYSCONFIG1_STCIEN 0x4000 /* bits 14..14: Seek/Tune Complete Interrupt Enable */
#define SYSCONFIG1_RDS 0x1000 /* bits 12..12: RDS Enable (Si4701 only) */
#define SYSCONFIG1_DE 0x0800 /* bits 11..11: De-emphasis (0=75us 1=50us) */
#define SYSCONFIG1_AGCD 0x0400 /* bits 10..10: AGC Disable */
#define SYSCONFIG1_BLNDADJ 0x00c0 /* bits 07..06: Stereo/Mono Blend Level Adjustment */
#define SYSCONFIG1_GPIO3 0x0030 /* bits 05..04: General Purpose I/O 3 */
#define SYSCONFIG1_GPIO2 0x000c /* bits 03..02: General Purpose I/O 2 */
#define SYSCONFIG1_GPIO1 0x0003 /* bits 01..00: General Purpose I/O 1 */
#define SYSCONFIG2 5 /* System Configuration 2 */
#define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */
#define SYSCONFIG2_BAND 0x0080 /* bits 07..06: Band Select */
#define SYSCONFIG2_SPACE 0x0030 /* bits 05..04: Channel Spacing */
#define SYSCONFIG2_VOLUME 0x000f /* bits 03..00: Volume */
#define SYSCONFIG3 6 /* System Configuration 3 */
#define SYSCONFIG3_SMUTER 0xc000 /* bits 15..14: Softmute Attack/Recover Rate */
#define SYSCONFIG3_SMUTEA 0x3000 /* bits 13..12: Softmute Attenuation */
#define SYSCONFIG3_SKSNR 0x00f0 /* bits 07..04: Seek SNR Threshold */
#define SYSCONFIG3_SKCNT 0x000f /* bits 03..00: Seek FM Impulse Detection Threshold */
#define TEST1 7 /* Test 1 */
#define TEST1_AHIZEN 0x4000 /* bits 14..14: Audio High-Z Enable */
#define TEST2 8 /* Test 2 */
/* TEST2 only contains reserved bits */
#define BOOTCONFIG 9 /* Boot Configuration */
/* BOOTCONFIG only contains reserved bits */
#define STATUSRSSI 10 /* Status RSSI */
#define STATUSRSSI_RDSR 0x8000 /* bits 15..15: RDS Ready (Si4701 only) */
#define STATUSRSSI_STC 0x4000 /* bits 14..14: Seek/Tune Complete */
#define STATUSRSSI_SF 0x2000 /* bits 13..13: Seek Fail/Band Limit */
#define STATUSRSSI_AFCRL 0x1000 /* bits 12..12: AFC Rail */
#define STATUSRSSI_RDSS 0x0800 /* bits 11..11: RDS Synchronized (Si4701 only) */
#define STATUSRSSI_BLERA 0x0600 /* bits 10..09: RDS Block A Errors (Si4701 only) */
#define STATUSRSSI_ST 0x0100 /* bits 08..08: Stereo Indicator */
#define STATUSRSSI_RSSI 0x00ff /* bits 07..00: RSSI (Received Signal Strength Indicator) */
#define READCHAN 11 /* Read Channel */
#define READCHAN_BLERB 0xc000 /* bits 15..14: RDS Block D Errors (Si4701 only) */
#define READCHAN_BLERC 0x3000 /* bits 13..12: RDS Block C Errors (Si4701 only) */
#define READCHAN_BLERD 0x0c00 /* bits 11..10: RDS Block B Errors (Si4701 only) */
#define READCHAN_READCHAN 0x03ff /* bits 09..00: Read Channel */
#define RDSA 12 /* RDSA */
#define RDSA_RDSA 0xffff /* bits 15..00: RDS Block A Data (Si4701 only) */
#define RDSB 13 /* RDSB */
#define RDSB_RDSB 0xffff /* bits 15..00: RDS Block B Data (Si4701 only) */
#define RDSC 14 /* RDSC */
#define RDSC_RDSC 0xffff /* bits 15..00: RDS Block C Data (Si4701 only) */
#define RDSD 15 /* RDSD */
#define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) */
/**************************************************************************
* General Driver Definitions
**************************************************************************/
/*
* si470x_device - private data
*/
struct si470x_device {
struct video_device *videodev;
/* driver management */
unsigned int users;
/* Silabs internal registers (0..15) */
unsigned short registers[RADIO_REGISTER_NUM];
/* RDS receive buffer */
wait_queue_head_t read_queue;
struct mutex lock; /* buffer locking */
unsigned char *buffer; /* size is always multiple of three */
unsigned int buf_size;
unsigned int rd_index;
unsigned int wr_index;
#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
/* reference to USB and video device */
struct usb_device *usbdev;
struct usb_interface *intf;
/* Interrupt endpoint handling */
char *int_in_buffer;
struct usb_endpoint_descriptor *int_in_endpoint;
struct urb *int_in_urb;
int int_in_running;
/* scratch page */
unsigned char software_version;
unsigned char hardware_version;
/* driver management */
unsigned char disconnected;
struct mutex disconnect_lock;
#endif
#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE)
struct i2c_client *client;
#endif
};
/**************************************************************************
* Firmware Versions
**************************************************************************/
#define RADIO_FW_VERSION 15
/**************************************************************************
* Frequency Multiplicator
**************************************************************************/
/*
* The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
* 62.5 kHz otherwise.
* The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
* tuner->capability is therefore set to V4L2_TUNER_CAP_LOW
* The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000
*/
#define FREQ_MUL (1000000 / 62.5)
/**************************************************************************
* Common Functions
**************************************************************************/
extern const struct v4l2_file_operations si470x_fops;
extern struct video_device si470x_viddev_template;
int si470x_get_register(struct si470x_device *radio, int regnr);
int si470x_set_register(struct si470x_device *radio, int regnr);
int si470x_disconnect_check(struct si470x_device *radio);
int si470x_set_freq(struct si470x_device *radio, unsigned int freq);
int si470x_start(struct si470x_device *radio);
int si470x_stop(struct si470x_device *radio);
int si470x_rds_on(struct si470x_device *radio);
int si470x_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *capability);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,237 @@
/*
* drivers/media/radio/si4713-i2c.h
*
* Property and commands definitions for Si4713 radio transmitter chip.
*
* Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT
* Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#ifndef SI4713_I2C_H
#define SI4713_I2C_H
#include <media/v4l2-subdev.h>
#include <media/si4713.h>
#define SI4713_PRODUCT_NUMBER 0x0D
/* Command Timeouts */
#define DEFAULT_TIMEOUT 500
#define TIMEOUT_SET_PROPERTY 20
#define TIMEOUT_TX_TUNE_POWER 30000
#define TIMEOUT_TX_TUNE 110000
#define TIMEOUT_POWER_UP 200000
/*
* Command and its arguments definitions
*/
#define SI4713_PWUP_CTSIEN (1<<7)
#define SI4713_PWUP_GPO2OEN (1<<6)
#define SI4713_PWUP_PATCH (1<<5)
#define SI4713_PWUP_XOSCEN (1<<4)
#define SI4713_PWUP_FUNC_TX 0x02
#define SI4713_PWUP_FUNC_PATCH 0x0F
#define SI4713_PWUP_OPMOD_ANALOG 0x50
#define SI4713_PWUP_OPMOD_DIGITAL 0x0F
#define SI4713_PWUP_NARGS 2
#define SI4713_PWUP_NRESP 1
#define SI4713_CMD_POWER_UP 0x01
#define SI4713_GETREV_NRESP 9
#define SI4713_CMD_GET_REV 0x10
#define SI4713_PWDN_NRESP 1
#define SI4713_CMD_POWER_DOWN 0x11
#define SI4713_SET_PROP_NARGS 5
#define SI4713_SET_PROP_NRESP 1
#define SI4713_CMD_SET_PROPERTY 0x12
#define SI4713_GET_PROP_NARGS 3
#define SI4713_GET_PROP_NRESP 4
#define SI4713_CMD_GET_PROPERTY 0x13
#define SI4713_GET_STATUS_NRESP 1
#define SI4713_CMD_GET_INT_STATUS 0x14
#define SI4713_CMD_PATCH_ARGS 0x15
#define SI4713_CMD_PATCH_DATA 0x16
#define SI4713_MAX_FREQ 10800
#define SI4713_MIN_FREQ 7600
#define SI4713_TXFREQ_NARGS 3
#define SI4713_TXFREQ_NRESP 1
#define SI4713_CMD_TX_TUNE_FREQ 0x30
#define SI4713_MAX_POWER 120
#define SI4713_MIN_POWER 88
#define SI4713_MAX_ANTCAP 191
#define SI4713_MIN_ANTCAP 0
#define SI4713_TXPWR_NARGS 4
#define SI4713_TXPWR_NRESP 1
#define SI4713_CMD_TX_TUNE_POWER 0x31
#define SI4713_TXMEA_NARGS 4
#define SI4713_TXMEA_NRESP 1
#define SI4713_CMD_TX_TUNE_MEASURE 0x32
#define SI4713_INTACK_MASK 0x01
#define SI4713_TXSTATUS_NARGS 1
#define SI4713_TXSTATUS_NRESP 8
#define SI4713_CMD_TX_TUNE_STATUS 0x33
#define SI4713_OVERMOD_BIT (1 << 2)
#define SI4713_IALH_BIT (1 << 1)
#define SI4713_IALL_BIT (1 << 0)
#define SI4713_ASQSTATUS_NARGS 1
#define SI4713_ASQSTATUS_NRESP 5
#define SI4713_CMD_TX_ASQ_STATUS 0x34
#define SI4713_RDSBUFF_MODE_MASK 0x87
#define SI4713_RDSBUFF_NARGS 7
#define SI4713_RDSBUFF_NRESP 6
#define SI4713_CMD_TX_RDS_BUFF 0x35
#define SI4713_RDSPS_PSID_MASK 0x1F
#define SI4713_RDSPS_NARGS 5
#define SI4713_RDSPS_NRESP 1
#define SI4713_CMD_TX_RDS_PS 0x36
#define SI4713_CMD_GPO_CTL 0x80
#define SI4713_CMD_GPO_SET 0x81
/*
* Bits from status response
*/
#define SI4713_CTS (1<<7)
#define SI4713_ERR (1<<6)
#define SI4713_RDS_INT (1<<2)
#define SI4713_ASQ_INT (1<<1)
#define SI4713_STC_INT (1<<0)
/*
* Property definitions
*/
#define SI4713_GPO_IEN 0x0001
#define SI4713_DIG_INPUT_FORMAT 0x0101
#define SI4713_DIG_INPUT_SAMPLE_RATE 0x0103
#define SI4713_REFCLK_FREQ 0x0201
#define SI4713_REFCLK_PRESCALE 0x0202
#define SI4713_TX_COMPONENT_ENABLE 0x2100
#define SI4713_TX_AUDIO_DEVIATION 0x2101
#define SI4713_TX_PILOT_DEVIATION 0x2102
#define SI4713_TX_RDS_DEVIATION 0x2103
#define SI4713_TX_LINE_INPUT_LEVEL 0x2104
#define SI4713_TX_LINE_INPUT_MUTE 0x2105
#define SI4713_TX_PREEMPHASIS 0x2106
#define SI4713_TX_PILOT_FREQUENCY 0x2107
#define SI4713_TX_ACOMP_ENABLE 0x2200
#define SI4713_TX_ACOMP_THRESHOLD 0x2201
#define SI4713_TX_ACOMP_ATTACK_TIME 0x2202
#define SI4713_TX_ACOMP_RELEASE_TIME 0x2203
#define SI4713_TX_ACOMP_GAIN 0x2204
#define SI4713_TX_LIMITER_RELEASE_TIME 0x2205
#define SI4713_TX_ASQ_INTERRUPT_SOURCE 0x2300
#define SI4713_TX_ASQ_LEVEL_LOW 0x2301
#define SI4713_TX_ASQ_DURATION_LOW 0x2302
#define SI4713_TX_ASQ_LEVEL_HIGH 0x2303
#define SI4713_TX_ASQ_DURATION_HIGH 0x2304
#define SI4713_TX_RDS_INTERRUPT_SOURCE 0x2C00
#define SI4713_TX_RDS_PI 0x2C01
#define SI4713_TX_RDS_PS_MIX 0x2C02
#define SI4713_TX_RDS_PS_MISC 0x2C03
#define SI4713_TX_RDS_PS_REPEAT_COUNT 0x2C04
#define SI4713_TX_RDS_PS_MESSAGE_COUNT 0x2C05
#define SI4713_TX_RDS_PS_AF 0x2C06
#define SI4713_TX_RDS_FIFO_SIZE 0x2C07
#define PREEMPHASIS_USA 75
#define PREEMPHASIS_EU 50
#define PREEMPHASIS_DISABLED 0
#define FMPE_USA 0x00
#define FMPE_EU 0x01
#define FMPE_DISABLED 0x02
#define POWER_UP 0x01
#define POWER_DOWN 0x00
struct rds_info {
u32 pi;
#define MAX_RDS_PTY 31
u32 pty;
#define MAX_RDS_DEVIATION 90000
u32 deviation;
/*
* PSNAME is known to be defined as 8 character sized (RDS Spec).
* However, there is receivers which scroll PSNAME 8xN sized.
*/
#define MAX_RDS_PS_NAME 96
u8 ps_name[MAX_RDS_PS_NAME + 1];
/*
* MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group)
* character sized (RDS Spec).
* However, there is receivers which scroll them as well.
*/
#define MAX_RDS_RADIO_TEXT 384
u8 radio_text[MAX_RDS_RADIO_TEXT + 1];
u32 enabled;
};
struct limiter_info {
#define MAX_LIMITER_RELEASE_TIME 102390
u32 release_time;
#define MAX_LIMITER_DEVIATION 90000
u32 deviation;
u32 enabled;
};
struct pilot_info {
#define MAX_PILOT_DEVIATION 90000
u32 deviation;
#define MAX_PILOT_FREQUENCY 19000
u32 frequency;
u32 enabled;
};
struct acomp_info {
#define MAX_ACOMP_RELEASE_TIME 1000000
u32 release_time;
#define MAX_ACOMP_ATTACK_TIME 5000
u32 attack_time;
#define MAX_ACOMP_THRESHOLD 0
#define MIN_ACOMP_THRESHOLD (-40)
s32 threshold;
#define MAX_ACOMP_GAIN 20
u32 gain;
u32 enabled;
};
/*
* si4713_device - private data
*/
struct si4713_device {
/* v4l2_subdev and i2c reference (v4l2_subdev priv data) */
struct v4l2_subdev sd;
/* private data structures */
struct mutex mutex;
struct completion work;
struct si4713_platform_data *platform_data;
struct rds_info rds_info;
struct limiter_info limiter_info;
struct pilot_info pilot_info;
struct acomp_info acomp_info;
u32 frequency;
u32 preemphasis;
u32 mute;
u32 power_level;
u32 power_state;
u32 antenna_capacitor;
u32 stereo;
u32 tune_rnl;
};
#endif /* ifndef SI4713_I2C_H */

View file

@ -203,9 +203,9 @@ config VIDEO_CS53L32A
module will be called cs53l32a. module will be called cs53l32a.
config VIDEO_M52790 config VIDEO_M52790
tristate "Mitsubishi M52790 A/V switch" tristate "Mitsubishi M52790 A/V switch"
depends on VIDEO_V4L2 && I2C depends on VIDEO_V4L2 && I2C
---help--- ---help---
Support for the Mitsubishi M52790 A/V switch. Support for the Mitsubishi M52790 A/V switch.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the

View file

@ -151,7 +151,7 @@ static int start_urb_transfer(struct au0828_dev *dev)
dprintk(2, "%s()\n", __func__); dprintk(2, "%s()\n", __func__);
if (dev->urb_streaming) { if (dev->urb_streaming) {
dprintk(2, "%s: iso xfer already running!\n", __func__); dprintk(2, "%s: bulk xfer already running!\n", __func__);
return 0; return 0;
} }

View file

@ -320,7 +320,6 @@ static struct i2c_algorithm au0828_i2c_algo_template = {
static struct i2c_adapter au0828_i2c_adap_template = { static struct i2c_adapter au0828_i2c_adap_template = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id = I2C_HW_B_AU0828,
.algo = &au0828_i2c_algo_template, .algo = &au0828_i2c_algo_template,
}; };

View file

@ -1274,6 +1274,7 @@ struct tvcard bttv_tvcards[] = {
.pll = PLL_28, .pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL, .tuner_type = TUNER_TEMIC_PAL,
.tuner_addr = ADDR_UNSET, .tuner_addr = ADDR_UNSET,
.has_remote = 1,
}, },
/* ---- card 0x3c ---------------------------------- */ /* ---- card 0x3c ---------------------------------- */

View file

@ -2652,6 +2652,8 @@ static int bttv_querycap(struct file *file, void *priv,
V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING; V4L2_CAP_STREAMING;
if (btv->has_saa6588)
cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
if (no_overlay <= 0) if (no_overlay <= 0)
cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
@ -4593,14 +4595,10 @@ static int bttv_resume(struct pci_dev *pci_dev)
#endif #endif
static struct pci_device_id bttv_pci_tbl[] = { static struct pci_device_id bttv_pci_tbl[] = {
{PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
{PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
{PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0,} {0,}
}; };

View file

@ -352,7 +352,6 @@ int __devinit init_bttv_i2c(struct bttv *btv)
/* bt878 */ /* bt878 */
strlcpy(btv->c.i2c_adap.name, "bt878", strlcpy(btv->c.i2c_adap.name, "bt878",
sizeof(btv->c.i2c_adap.name)); sizeof(btv->c.i2c_adap.name));
btv->c.i2c_adap.id = I2C_HW_B_BT848; /* FIXME */
btv->c.i2c_adap.algo = &bttv_algo; btv->c.i2c_adap.algo = &bttv_algo;
} else { } else {
/* bt848 */ /* bt848 */
@ -362,7 +361,6 @@ int __devinit init_bttv_i2c(struct bttv *btv)
strlcpy(btv->c.i2c_adap.name, "bttv", strlcpy(btv->c.i2c_adap.name, "bttv",
sizeof(btv->c.i2c_adap.name)); sizeof(btv->c.i2c_adap.name));
btv->c.i2c_adap.id = I2C_HW_B_BT848;
memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template, memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template,
sizeof(bttv_i2c_algo_bit_template)); sizeof(bttv_i2c_algo_bit_template));
btv->i2c_algo.udelay = i2c_udelay; btv->i2c_algo.udelay = i2c_udelay;

View file

@ -245,7 +245,7 @@ static void bttv_ir_stop(struct bttv *btv)
int bttv_input_init(struct bttv *btv) int bttv_input_init(struct bttv *btv)
{ {
struct card_ir *ir; struct card_ir *ir;
IR_KEYTAB_TYPE *ir_codes = NULL; struct ir_scancode_table *ir_codes = NULL;
struct input_dev *input_dev; struct input_dev *input_dev;
int ir_type = IR_TYPE_OTHER; int ir_type = IR_TYPE_OTHER;
int err = -ENOMEM; int err = -ENOMEM;
@ -263,7 +263,7 @@ int bttv_input_init(struct bttv *btv)
case BTTV_BOARD_AVERMEDIA: case BTTV_BOARD_AVERMEDIA:
case BTTV_BOARD_AVPHONE98: case BTTV_BOARD_AVPHONE98:
case BTTV_BOARD_AVERMEDIA98: case BTTV_BOARD_AVERMEDIA98:
ir_codes = ir_codes_avermedia; ir_codes = &ir_codes_avermedia_table;
ir->mask_keycode = 0xf88000; ir->mask_keycode = 0xf88000;
ir->mask_keydown = 0x010000; ir->mask_keydown = 0x010000;
ir->polling = 50; // ms ir->polling = 50; // ms
@ -271,14 +271,14 @@ int bttv_input_init(struct bttv *btv)
case BTTV_BOARD_AVDVBT_761: case BTTV_BOARD_AVDVBT_761:
case BTTV_BOARD_AVDVBT_771: case BTTV_BOARD_AVDVBT_771:
ir_codes = ir_codes_avermedia_dvbt; ir_codes = &ir_codes_avermedia_dvbt_table;
ir->mask_keycode = 0x0f00c0; ir->mask_keycode = 0x0f00c0;
ir->mask_keydown = 0x000020; ir->mask_keydown = 0x000020;
ir->polling = 50; // ms ir->polling = 50; // ms
break; break;
case BTTV_BOARD_PXELVWPLTVPAK: case BTTV_BOARD_PXELVWPLTVPAK:
ir_codes = ir_codes_pixelview; ir_codes = &ir_codes_pixelview_table;
ir->mask_keycode = 0x003e00; ir->mask_keycode = 0x003e00;
ir->mask_keyup = 0x010000; ir->mask_keyup = 0x010000;
ir->polling = 50; // ms ir->polling = 50; // ms
@ -286,54 +286,55 @@ int bttv_input_init(struct bttv *btv)
case BTTV_BOARD_PV_M4900: case BTTV_BOARD_PV_M4900:
case BTTV_BOARD_PV_BT878P_9B: case BTTV_BOARD_PV_BT878P_9B:
case BTTV_BOARD_PV_BT878P_PLUS: case BTTV_BOARD_PV_BT878P_PLUS:
ir_codes = ir_codes_pixelview; ir_codes = &ir_codes_pixelview_table;
ir->mask_keycode = 0x001f00; ir->mask_keycode = 0x001f00;
ir->mask_keyup = 0x008000; ir->mask_keyup = 0x008000;
ir->polling = 50; // ms ir->polling = 50; // ms
break; break;
case BTTV_BOARD_WINFAST2000: case BTTV_BOARD_WINFAST2000:
ir_codes = ir_codes_winfast; ir_codes = &ir_codes_winfast_table;
ir->mask_keycode = 0x1f8; ir->mask_keycode = 0x1f8;
break; break;
case BTTV_BOARD_MAGICTVIEW061: case BTTV_BOARD_MAGICTVIEW061:
case BTTV_BOARD_MAGICTVIEW063: case BTTV_BOARD_MAGICTVIEW063:
ir_codes = ir_codes_winfast; ir_codes = &ir_codes_winfast_table;
ir->mask_keycode = 0x0008e000; ir->mask_keycode = 0x0008e000;
ir->mask_keydown = 0x00200000; ir->mask_keydown = 0x00200000;
break; break;
case BTTV_BOARD_APAC_VIEWCOMP: case BTTV_BOARD_APAC_VIEWCOMP:
ir_codes = ir_codes_apac_viewcomp; ir_codes = &ir_codes_apac_viewcomp_table;
ir->mask_keycode = 0x001f00; ir->mask_keycode = 0x001f00;
ir->mask_keyup = 0x008000; ir->mask_keyup = 0x008000;
ir->polling = 50; // ms ir->polling = 50; // ms
break; break;
case BTTV_BOARD_ASKEY_CPH03X:
case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: case BTTV_BOARD_CONCEPTRONIC_CTVFMI2:
case BTTV_BOARD_CONTVFMI: case BTTV_BOARD_CONTVFMI:
ir_codes = ir_codes_pixelview; ir_codes = &ir_codes_pixelview_table;
ir->mask_keycode = 0x001F00; ir->mask_keycode = 0x001F00;
ir->mask_keyup = 0x006000; ir->mask_keyup = 0x006000;
ir->polling = 50; // ms ir->polling = 50; // ms
break; break;
case BTTV_BOARD_NEBULA_DIGITV: case BTTV_BOARD_NEBULA_DIGITV:
ir_codes = ir_codes_nebula; ir_codes = &ir_codes_nebula_table;
btv->custom_irq = bttv_rc5_irq; btv->custom_irq = bttv_rc5_irq;
ir->rc5_gpio = 1; ir->rc5_gpio = 1;
break; break;
case BTTV_BOARD_MACHTV_MAGICTV: case BTTV_BOARD_MACHTV_MAGICTV:
ir_codes = ir_codes_apac_viewcomp; ir_codes = &ir_codes_apac_viewcomp_table;
ir->mask_keycode = 0x001F00; ir->mask_keycode = 0x001F00;
ir->mask_keyup = 0x004000; ir->mask_keyup = 0x004000;
ir->polling = 50; /* ms */ ir->polling = 50; /* ms */
break; break;
case BTTV_BOARD_KOZUMI_KTV_01C: case BTTV_BOARD_KOZUMI_KTV_01C:
ir_codes = ir_codes_pctv_sedna; ir_codes = &ir_codes_pctv_sedna_table;
ir->mask_keycode = 0x001f00; ir->mask_keycode = 0x001f00;
ir->mask_keyup = 0x006000; ir->mask_keyup = 0x006000;
ir->polling = 50; /* ms */ ir->polling = 50; /* ms */
break; break;
case BTTV_BOARD_ENLTV_FM_2: case BTTV_BOARD_ENLTV_FM_2:
ir_codes = ir_codes_encore_enltv2; ir_codes = &ir_codes_encore_enltv2_table;
ir->mask_keycode = 0x00fd00; ir->mask_keycode = 0x00fd00;
ir->mask_keyup = 0x000080; ir->mask_keyup = 0x000080;
ir->polling = 1; /* ms */ ir->polling = 1; /* ms */

View file

@ -490,7 +490,6 @@ static int cafe_smbus_setup(struct cafe_camera *cam)
int ret; int ret;
cafe_smbus_enable_irq(cam); cafe_smbus_enable_irq(cam);
adap->id = I2C_HW_SMBUS_CAFE;
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
adap->algo = &cafe_smbus_algo; adap->algo = &cafe_smbus_algo;
strcpy(adap->name, "cafe_ccic"); strcpy(adap->name, "cafe_ccic");

View file

@ -56,7 +56,8 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
.hw_audio_ctrl = CX18_HW_418_AV, .hw_audio_ctrl = CX18_HW_418_AV,
.hw_muxer = CX18_HW_CS5345, .hw_muxer = CX18_HW_CS5345,
.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
CX18_HW_Z8F0811_IR_HAUP,
.video_inputs = { .video_inputs = {
{ CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 },
{ CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 },
@ -102,7 +103,8 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
.hw_audio_ctrl = CX18_HW_418_AV, .hw_audio_ctrl = CX18_HW_418_AV,
.hw_muxer = CX18_HW_CS5345, .hw_muxer = CX18_HW_CS5345,
.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER | .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
CX18_HW_Z8F0811_IR_HAUP,
.video_inputs = { .video_inputs = {
{ CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 },
{ CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 },
@ -204,7 +206,7 @@ static const struct cx18_card cx18_card_mpc718 = {
.v4l2_capabilities = CX18_CAP_ENCODER, .v4l2_capabilities = CX18_CAP_ENCODER,
.hw_audio_ctrl = CX18_HW_418_AV, .hw_audio_ctrl = CX18_HW_418_AV,
.hw_muxer = CX18_HW_GPIO_MUX, .hw_muxer = CX18_HW_GPIO_MUX,
.hw_all = CX18_HW_418_AV | CX18_HW_TUNER | .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL, CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
.video_inputs = { .video_inputs = {
{ CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 },

View file

@ -22,13 +22,17 @@
*/ */
/* hardware flags */ /* hardware flags */
#define CX18_HW_TUNER (1 << 0) #define CX18_HW_TUNER (1 << 0)
#define CX18_HW_TVEEPROM (1 << 1) #define CX18_HW_TVEEPROM (1 << 1)
#define CX18_HW_CS5345 (1 << 2) #define CX18_HW_CS5345 (1 << 2)
#define CX18_HW_DVB (1 << 3) #define CX18_HW_DVB (1 << 3)
#define CX18_HW_418_AV (1 << 4) #define CX18_HW_418_AV (1 << 4)
#define CX18_HW_GPIO_MUX (1 << 5) #define CX18_HW_GPIO_MUX (1 << 5)
#define CX18_HW_GPIO_RESET_CTRL (1 << 6) #define CX18_HW_GPIO_RESET_CTRL (1 << 6)
#define CX18_HW_Z8F0811_IR_TX_HAUP (1 << 7)
#define CX18_HW_Z8F0811_IR_RX_HAUP (1 << 8)
#define CX18_HW_Z8F0811_IR_HAUP (CX18_HW_Z8F0811_IR_RX_HAUP | \
CX18_HW_Z8F0811_IR_TX_HAUP)
/* video inputs */ /* video inputs */
#define CX18_CARD_INPUT_VID_TUNER 1 #define CX18_CARD_INPUT_VID_TUNER 1

Some files were not shown because too many files have changed in this diff Show more