提交 0dd51986 编写于 作者: L Linus Torvalds

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: (425 commits)
  V4L/DVB (11870): gspca - main: VIDIOC_ENUM_FRAMESIZES ioctl added.
  V4L/DVB (12004): poll method lose race condition
  V4L/DVB (11894): flexcop-pci: dmesg visible names broken
  V4L/DVB (11892): Siano: smsendian - declare function as extern
  V4L/DVB (11891): Siano: smscore - bind the GPIO SMS protocol
  V4L/DVB (11890): Siano: smscore - remove redundant code
  V4L/DVB (11889): Siano: smsdvb - add DVB v3 events
  V4L/DVB (11888): Siano: smsusb - remove redundant ifdef
  V4L/DVB (11887): Siano: smscards - add board (target) events
  V4L/DVB (11886): Siano: smscore - fix some new GPIO definitions names
  V4L/DVB (11885): Siano: Add new GPIO management interface
  V4L/DVB (11884): Siano: smssdio - revert to stand alone module
  V4L/DVB (11883): Siano: cards - add two additional (USB) devices
  V4L/DVB (11824): Siano: smsusb - change exit func debug msg
  V4L/DVB (11823): Siano: smsusb - fix typo in module description
  V4L/DVB (11822): Siano: smscore - bug fix at get_device_mode
  V4L/DVB (11821): Siano: smscore - fix isdb-t firmware name
  V4L/DVB (11820): Siano: smscore - fix byte ordering bug
  V4L/DVB (11819): Siano: smscore - fix get_common_buffer bug
  V4L/DVB (11818): Siano: smscards - assign gpio to HPG targets
  ...
...@@ -112,7 +112,7 @@ sub tda10045 { ...@@ -112,7 +112,7 @@ sub tda10045 {
sub tda10046 { sub tda10046 {
my $sourcefile = "TT_PCI_2.19h_28_11_2006.zip"; my $sourcefile = "TT_PCI_2.19h_28_11_2006.zip";
my $url = "http://technotrend-online.com/download/software/219/$sourcefile"; my $url = "http://www.tt-download.com/download/updates/219/$sourcefile";
my $hash = "6a7e1e2f2644b162ff0502367553c72d"; my $hash = "6a7e1e2f2644b162ff0502367553c72d";
my $outfile = "dvb-fe-tda10046.fw"; my $outfile = "dvb-fe-tda10046.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
...@@ -129,8 +129,8 @@ sub tda10046 { ...@@ -129,8 +129,8 @@ sub tda10046 {
} }
sub tda10046lifeview { sub tda10046lifeview {
my $sourcefile = "Drv_2.11.02.zip"; my $sourcefile = "7%5Cdrv_2.11.02.zip";
my $url = "http://www.lifeview.com.tw/drivers/pci_card/FlyDVB-T/$sourcefile"; my $url = "http://www.lifeview.hk/dbimages/document/$sourcefile";
my $hash = "1ea24dee4eea8fe971686981f34fd2e0"; my $hash = "1ea24dee4eea8fe971686981f34fd2e0";
my $outfile = "dvb-fe-tda10046.fw"; my $outfile = "dvb-fe-tda10046.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
...@@ -317,7 +317,7 @@ sub nxt2002 { ...@@ -317,7 +317,7 @@ sub nxt2002 {
sub nxt2004 { sub nxt2004 {
my $sourcefile = "AVerTVHD_MCE_A180_Drv_v1.2.2.16.zip"; my $sourcefile = "AVerTVHD_MCE_A180_Drv_v1.2.2.16.zip";
my $url = "http://www.aver.com/support/Drivers/$sourcefile"; my $url = "http://www.avermedia-usa.com/support/Drivers/$sourcefile";
my $hash = "111cb885b1e009188346d72acfed024c"; my $hash = "111cb885b1e009188346d72acfed024c";
my $outfile = "dvb-fe-nxt2004.fw"; my $outfile = "dvb-fe-nxt2004.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
......
...@@ -16,3 +16,8 @@ ...@@ -16,3 +16,8 @@
15 -> TeVii S470 [d470:9022] 15 -> TeVii S470 [d470:9022]
16 -> DVBWorld DVB-S2 2005 [0001:2005] 16 -> DVBWorld DVB-S2 2005 [0001:2005]
17 -> NetUP Dual DVB-S2 CI [1b55:2a2c] 17 -> NetUP Dual DVB-S2 CI [1b55:2a2c]
18 -> Hauppauge WinTV-HVR1270 [0070:2211]
19 -> Hauppauge WinTV-HVR1275 [0070:2215]
20 -> Hauppauge WinTV-HVR1255 [0070:2251]
21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295]
22 -> Mygica X8506 DMB-TH [14f1:8651]
...@@ -78,3 +78,5 @@ ...@@ -78,3 +78,5 @@
77 -> TBS 8910 DVB-S [8910:8888] 77 -> TBS 8910 DVB-S [8910:8888]
78 -> Prof 6200 DVB-S [b022:3022] 78 -> Prof 6200 DVB-S [b022:3022]
79 -> Terratec Cinergy HT PCI MKII [153b:1177] 79 -> Terratec Cinergy HT PCI MKII [153b:1177]
80 -> Hauppauge WinTV-IR Only [0070:9290]
81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654]
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b] 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b]
17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227] 17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227]
18 -> Hauppauge WinTV HVR 900 (R2) (em2880) [2040:6502] 18 -> Hauppauge WinTV HVR 900 (R2) (em2880) [2040:6502]
19 -> PointNix Intra-Oral Camera (em2860) 19 -> EM2860/SAA711X Reference Design (em2860)
20 -> AMD ATI TV Wonder HD 600 (em2880) [0438:b002] 20 -> AMD ATI TV Wonder HD 600 (em2880) [0438:b002]
21 -> eMPIA Technology, Inc. GrabBeeX+ Video Encoder (em2800) [eb1a:2801] 21 -> eMPIA Technology, Inc. GrabBeeX+ Video Encoder (em2800) [eb1a:2801]
22 -> Unknown EM2750/EM2751 webcam grabber (em2750) [eb1a:2750,eb1a:2751] 22 -> Unknown EM2750/EM2751 webcam grabber (em2750) [eb1a:2750,eb1a:2751]
...@@ -61,3 +61,7 @@ ...@@ -61,3 +61,7 @@
63 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303] 63 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303]
64 -> Easy Cap Capture DC-60 (em2860) 64 -> Easy Cap Capture DC-60 (em2860)
65 -> IO-DATA GV-MVP/SZ (em2820/em2840) [04bb:0515] 65 -> IO-DATA GV-MVP/SZ (em2820/em2840) [04bb:0515]
66 -> Empire dual TV (em2880)
67 -> Terratec Grabby (em2860) [0ccd:0096]
68 -> Terratec AV350 (em2860) [0ccd:0084]
69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313]
...@@ -124,10 +124,10 @@ ...@@ -124,10 +124,10 @@
123 -> Beholder BeholdTV 407 [0000:4070] 123 -> Beholder BeholdTV 407 [0000:4070]
124 -> Beholder BeholdTV 407 FM [0000:4071] 124 -> Beholder BeholdTV 407 FM [0000:4071]
125 -> Beholder BeholdTV 409 [0000:4090] 125 -> Beholder BeholdTV 409 [0000:4090]
126 -> Beholder BeholdTV 505 FM/RDS [0000:5051,0000:505B,5ace:5050] 126 -> Beholder BeholdTV 505 FM [5ace:5050]
127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090] 127 -> Beholder BeholdTV 507 FM / BeholdTV 509 FM [5ace:5070,5ace:5090]
128 -> Beholder BeholdTV Columbus TVFM [0000:5201] 128 -> Beholder BeholdTV Columbus TVFM [0000:5201]
129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093] 129 -> Beholder BeholdTV 607 FM [5ace:6070]
130 -> Beholder BeholdTV M6 [5ace:6190] 130 -> Beholder BeholdTV M6 [5ace:6190]
131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022] 131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022]
132 -> Genius TVGO AM11MCE 132 -> Genius TVGO AM11MCE
...@@ -143,7 +143,7 @@ ...@@ -143,7 +143,7 @@
142 -> Beholder BeholdTV H6 [5ace:6290] 142 -> Beholder BeholdTV H6 [5ace:6290]
143 -> Beholder BeholdTV M63 [5ace:6191] 143 -> Beholder BeholdTV M63 [5ace:6191]
144 -> Beholder BeholdTV M6 Extra [5ace:6193] 144 -> Beholder BeholdTV M6 Extra [5ace:6193]
145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636] 145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636,1461:f736]
146 -> ASUSTeK P7131 Analog 146 -> ASUSTeK P7131 Analog
147 -> Asus Tiger 3in1 [1043:4878] 147 -> Asus Tiger 3in1 [1043:4878]
148 -> Encore ENLTV-FM v5.3 [1a7f:2008] 148 -> Encore ENLTV-FM v5.3 [1a7f:2008]
...@@ -154,4 +154,16 @@ ...@@ -154,4 +154,16 @@
153 -> Kworld Plus TV Analog Lite PCI [17de:7128] 153 -> Kworld Plus TV Analog Lite PCI [17de:7128]
154 -> Avermedia AVerTV GO 007 FM Plus [1461:f31d] 154 -> Avermedia AVerTV GO 007 FM Plus [1461:f31d]
155 -> Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid [0070:6706,0070:6708] 155 -> Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid [0070:6706,0070:6708]
156 -> Hauppauge WinTV-HVR1110r3 [0070:6707,0070:6709,0070:670a] 156 -> Hauppauge WinTV-HVR1110r3 DVB-T/Hybrid [0070:6707,0070:6709,0070:670a]
157 -> Avermedia AVerTV Studio 507UA [1461:a11b]
158 -> AVerMedia Cardbus TV/Radio (E501R) [1461:b7e9]
159 -> Beholder BeholdTV 505 RDS [0000:505B]
160 -> Beholder BeholdTV 507 RDS [0000:5071]
161 -> Beholder BeholdTV 507 RDS [0000:507B]
162 -> Beholder BeholdTV 607 FM [5ace:6071]
163 -> Beholder BeholdTV 609 FM [5ace:6090]
164 -> Beholder BeholdTV 609 FM [5ace:6091]
165 -> Beholder BeholdTV 607 RDS [5ace:6072]
166 -> Beholder BeholdTV 607 RDS [5ace:6073]
167 -> Beholder BeholdTV 609 RDS [5ace:6092]
168 -> Beholder BeholdTV 609 RDS [5ace:6093]
...@@ -76,3 +76,5 @@ tuner=75 - Philips TEA5761 FM Radio ...@@ -76,3 +76,5 @@ tuner=75 - Philips TEA5761 FM Radio
tuner=76 - Xceive 5000 tuner tuner=76 - Xceive 5000 tuner
tuner=77 - TCL tuner MF02GIP-5N-E 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=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
...@@ -163,10 +163,11 @@ sunplus 055f:c650 Mustek MDC5500Z ...@@ -163,10 +163,11 @@ sunplus 055f:c650 Mustek MDC5500Z
zc3xx 055f:d003 Mustek WCam300A zc3xx 055f:d003 Mustek WCam300A
zc3xx 055f:d004 Mustek WCam300 AN zc3xx 055f:d004 Mustek WCam300 AN
conex 0572:0041 Creative Notebook cx11646 conex 0572:0041 Creative Notebook cx11646
ov519 05a9:0519 OmniVision ov519 05a9:0519 OV519 Microphone
ov519 05a9:0530 OmniVision ov519 05a9:0530 OmniVision
ov519 05a9:4519 OmniVision ov519 05a9:4519 Webcam Classic
ov519 05a9:8519 OmniVision ov519 05a9:8519 OmniVision
ov519 05a9:a518 D-Link DSB-C310 Webcam
sunplus 05da:1018 Digital Dream Enigma 1.3 sunplus 05da:1018 Digital Dream Enigma 1.3
stk014 05e1:0893 Syntek DV4000 stk014 05e1:0893 Syntek DV4000
spca561 060b:a001 Maxell Compact Pc PM3 spca561 060b:a001 Maxell Compact Pc PM3
...@@ -178,6 +179,7 @@ spca506 06e1:a190 ADS Instant VCD ...@@ -178,6 +179,7 @@ spca506 06e1:a190 ADS Instant VCD
ov534 06f8:3002 Hercules Blog Webcam 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
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
...@@ -209,6 +211,7 @@ sunplus 08ca:2050 Medion MD 41437 ...@@ -209,6 +211,7 @@ sunplus 08ca:2050 Medion MD 41437
sunplus 08ca:2060 Aiptek PocketDV5300 sunplus 08ca:2060 Aiptek PocketDV5300
tv8532 0923:010f ICM532 cams tv8532 0923:010f ICM532 cams
mars 093a:050f Mars-Semi Pc-Camera mars 093a:050f Mars-Semi Pc-Camera
mr97310a 093a:010f Sakar Digital no. 77379
pac207 093a:2460 Qtec Webcam 100 pac207 093a:2460 Qtec Webcam 100
pac207 093a:2461 HP Webcam pac207 093a:2461 HP Webcam
pac207 093a:2463 Philips SPC 220 NC pac207 093a:2463 Philips SPC 220 NC
...@@ -265,6 +268,11 @@ sonixj 0c45:60ec SN9C105+MO4000 ...@@ -265,6 +268,11 @@ sonixj 0c45:60ec SN9C105+MO4000
sonixj 0c45:60fb Surfer NoName sonixj 0c45:60fb Surfer NoName
sonixj 0c45:60fc LG-LIC300 sonixj 0c45:60fc LG-LIC300
sonixj 0c45:60fe Microdia Audio sonixj 0c45:60fe Microdia Audio
sonixj 0c45:6100 PC Camera (SN9C128)
sonixj 0c45:610a PC Camera (SN9C128)
sonixj 0c45:610b PC Camera (SN9C128)
sonixj 0c45:610c PC Camera (SN9C128)
sonixj 0c45:610e PC Camera (SN9C128)
sonixj 0c45:6128 Microdia/Sonix SNP325 sonixj 0c45:6128 Microdia/Sonix SNP325
sonixj 0c45:612a Avant Camera sonixj 0c45:612a Avant Camera
sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix
......
...@@ -26,6 +26,55 @@ Global video workflow ...@@ -26,6 +26,55 @@ Global video workflow
Once the last buffer is filled in, the QCI interface stops. Once the last buffer is filled in, the QCI interface stops.
c) Capture global finite state machine schema
+----+ +---+ +----+
| DQ | | Q | | DQ |
| v | v | v
+-----------+ +------------------------+
| STOP | | Wait for capture start |
+-----------+ Q +------------------------+
+-> | QCI: stop | ------------------> | QCI: run | <------------+
| | DMA: stop | | DMA: stop | |
| +-----------+ +-----> +------------------------+ |
| / | |
| / +---+ +----+ | |
|capture list empty / | Q | | DQ | | QCI Irq EOF |
| / | v | v v |
| +--------------------+ +----------------------+ |
| | DMA hotlink missed | | Capture running | |
| +--------------------+ +----------------------+ |
| | QCI: run | +-----> | QCI: run | <-+ |
| | DMA: stop | / | DMA: run | | |
| +--------------------+ / +----------------------+ | Other |
| ^ /DMA still | | channels |
| | capture list / running | DMA Irq End | not |
| | not empty / | | finished |
| | / v | yet |
| +----------------------+ +----------------------+ | |
| | Videobuf released | | Channel completed | | |
| +----------------------+ +----------------------+ | |
+-- | QCI: run | | QCI: run | --+ |
| DMA: run | | DMA: run | |
+----------------------+ +----------------------+ |
^ / | |
| no overrun / | overrun |
| / v |
+--------------------+ / +----------------------+ |
| Frame completed | / | Frame overran | |
+--------------------+ <-----+ +----------------------+ restart frame |
| QCI: run | | QCI: stop | --------------+
| DMA: run | | DMA: stop |
+--------------------+ +----------------------+
Legend: - each box is a FSM state
- each arrow is the condition to transition to another state
- an arrow with a comment is a mandatory transition (no condition)
- arrow "Q" means : a buffer was enqueued
- arrow "DQ" means : a buffer was dequeued
- "QCI: stop" means the QCI interface is not enabled
- "DMA: stop" means all 3 DMA channels are stopped
- "DMA: run" means at least 1 DMA channel is still running
DMA usage DMA usage
--------- ---------
......
...@@ -89,6 +89,11 @@ from dev (driver name followed by the bus_id, to be precise). If you set it ...@@ -89,6 +89,11 @@ from dev (driver name followed by the bus_id, to be precise). If you set it
up before calling v4l2_device_register then it will be untouched. If dev is up before calling v4l2_device_register then it will be untouched. If dev is
NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register. NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register.
You can use v4l2_device_set_name() to set the name based on a driver name and
a driver-global atomic_t instance. This will generate names like ivtv0, ivtv1,
etc. If the name ends with a digit, then it will insert a dash: cx18-0,
cx18-1, etc. This function returns the instance number.
The first 'dev' argument is normally the struct device pointer of a pci_dev, The first 'dev' argument is normally the struct device pointer of a pci_dev,
usb_interface or platform_device. It is rare for dev to be NULL, but it happens usb_interface or platform_device. It is rare for dev to be NULL, but it happens
with ISA devices or when one device creates multiple PCI devices, thus making with ISA devices or when one device creates multiple PCI devices, thus making
......
...@@ -380,12 +380,12 @@ static struct pca953x_platform_data pca9536_data = { ...@@ -380,12 +380,12 @@ static struct pca953x_platform_data pca9536_data = {
.gpio_base = NR_BUILTIN_GPIO, .gpio_base = NR_BUILTIN_GPIO,
}; };
static int gpio_bus_switch; static int gpio_bus_switch = -EINVAL;
static int pcm990_camera_set_bus_param(struct soc_camera_link *link, static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
unsigned long flags) unsigned long flags)
{ {
if (gpio_bus_switch <= 0) { if (gpio_bus_switch < 0) {
if (flags == SOCAM_DATAWIDTH_10) if (flags == SOCAM_DATAWIDTH_10)
return 0; return 0;
else else
...@@ -404,25 +404,34 @@ static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link) ...@@ -404,25 +404,34 @@ static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
{ {
int ret; int ret;
if (!gpio_bus_switch) { if (gpio_bus_switch < 0) {
ret = gpio_request(NR_BUILTIN_GPIO, "camera"); ret = gpio_request(NR_BUILTIN_GPIO, "camera");
if (!ret) { if (!ret) {
gpio_bus_switch = NR_BUILTIN_GPIO; gpio_bus_switch = NR_BUILTIN_GPIO;
gpio_direction_output(gpio_bus_switch, 0); gpio_direction_output(gpio_bus_switch, 0);
} else }
gpio_bus_switch = -EINVAL;
} }
if (gpio_bus_switch > 0) if (gpio_bus_switch >= 0)
return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10; return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
else else
return SOCAM_DATAWIDTH_10; return SOCAM_DATAWIDTH_10;
} }
static void pcm990_camera_free_bus(struct soc_camera_link *link)
{
if (gpio_bus_switch < 0)
return;
gpio_free(gpio_bus_switch);
gpio_bus_switch = -EINVAL;
}
static struct soc_camera_link iclink = { static struct soc_camera_link iclink = {
.bus_id = 0, /* Must match with the camera ID above */ .bus_id = 0, /* Must match with the camera ID above */
.query_bus_param = pcm990_camera_query_bus_param, .query_bus_param = pcm990_camera_query_bus_param,
.set_bus_param = pcm990_camera_set_bus_param, .set_bus_param = pcm990_camera_set_bus_param,
.free_bus = pcm990_camera_free_bus,
}; };
/* Board I2C devices. */ /* Board I2C devices. */
......
...@@ -2,8 +2,14 @@ ...@@ -2,8 +2,14 @@
# Multimedia device configuration # Multimedia device configuration
# #
menu "Multimedia devices" menuconfig MEDIA_SUPPORT
tristate "Multimedia support"
depends on HAS_IOMEM depends on HAS_IOMEM
help
If you want to use Video for Linux, DVB for Linux, or DAB adapters,
enable this option and other options below.
if MEDIA_SUPPORT
comment "Multimedia core support" comment "Multimedia core support"
...@@ -136,4 +142,4 @@ config USB_DABUSB ...@@ -136,4 +142,4 @@ config USB_DABUSB
module will be called dabusb. module will be called dabusb.
endif # DAB endif # DAB
endmenu endif # MEDIA_SUPPORT
...@@ -416,6 +416,24 @@ static int simple_std_setup(struct dvb_frontend *fe, ...@@ -416,6 +416,24 @@ static int simple_std_setup(struct dvb_frontend *fe,
return 0; return 0;
} }
static int simple_set_aux_byte(struct dvb_frontend *fe, u8 config, u8 aux)
{
struct tuner_simple_priv *priv = fe->tuner_priv;
int rc;
u8 buffer[2];
buffer[0] = (config & ~0x38) | 0x18;
buffer[1] = aux;
tuner_dbg("setting aux byte: 0x%02x 0x%02x\n", buffer[0], buffer[1]);
rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
if (2 != rc)
tuner_warn("i2c i/o error: rc == %d (should be 2)\n", rc);
return rc == 2 ? 0 : rc;
}
static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer, static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
u16 div, u8 config, u8 cb) u16 div, u8 config, u8 cb)
{ {
...@@ -424,17 +442,10 @@ static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer, ...@@ -424,17 +442,10 @@ static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
switch (priv->type) { switch (priv->type) {
case TUNER_LG_TDVS_H06XF: case TUNER_LG_TDVS_H06XF:
/* Set the Auxiliary Byte. */ simple_set_aux_byte(fe, config, 0x20);
buffer[0] = buffer[2]; break;
buffer[0] &= ~0x20; case TUNER_PHILIPS_FQ1216LME_MK3:
buffer[0] |= 0x18; simple_set_aux_byte(fe, config, 0x60); /* External AGC */
buffer[1] = 0x20;
tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]);
rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
if (2 != rc)
tuner_warn("i2c i/o error: rc == %d "
"(should be 2)\n", rc);
break; break;
case TUNER_MICROTUNE_4042FI5: case TUNER_MICROTUNE_4042FI5:
{ {
...@@ -506,6 +517,11 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) ...@@ -506,6 +517,11 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
case TUNER_THOMSON_DTT761X: case TUNER_THOMSON_DTT761X:
buffer[3] = 0x39; buffer[3] = 0x39;
break; break;
case TUNER_PHILIPS_FQ1216LME_MK3:
tuner_err("This tuner doesn't have FM\n");
/* Set the low band for sanity, since it covers 88-108 MHz */
buffer[3] = 0x01;
break;
case TUNER_MICROTUNE_4049FM5: case TUNER_MICROTUNE_4049FM5:
default: default:
buffer[3] = 0xa4; buffer[3] = 0xa4;
...@@ -678,12 +694,12 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, ...@@ -678,12 +694,12 @@ static int simple_set_radio_freq(struct dvb_frontend *fe,
return 0; return 0;
} }
/* Bandswitch byte */
simple_radio_bandswitch(fe, &buffer[0]);
buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) | buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
TUNER_RATIO_SELECT_50; /* 50 kHz step */ TUNER_RATIO_SELECT_50; /* 50 kHz step */
/* Bandswitch byte */
simple_radio_bandswitch(fe, &buffer[0]);
/* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps /* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) = freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
freq * (1/800) */ freq * (1/800) */
......
...@@ -578,6 +578,31 @@ static struct tuner_params tuner_fm1216me_mk3_params[] = { ...@@ -578,6 +578,31 @@ static struct tuner_params tuner_fm1216me_mk3_params[] = {
}, },
}; };
/* ------------ TUNER_PHILIPS_FM1216MK5 - Philips PAL ------------ */
static struct tuner_range tuner_fm1216mk5_pal_ranges[] = {
{ 16 * 158.00 /*MHz*/, 0xce, 0x01, },
{ 16 * 441.00 /*MHz*/, 0xce, 0x02, },
{ 16 * 864.00 , 0xce, 0x04, },
};
static struct tuner_params tuner_fm1216mk5_params[] = {
{
.type = TUNER_PARAM_TYPE_PAL,
.ranges = tuner_fm1216mk5_pal_ranges,
.count = ARRAY_SIZE(tuner_fm1216mk5_pal_ranges),
.cb_first_if_lower_freq = 1,
.has_tda9887 = 1,
.port1_active = 1,
.port2_active = 1,
.port2_invert_for_secam_lc = 1,
.port1_fm_high_sensitivity = 1,
.default_top_mid = -2,
.default_top_secam_mid = -2,
.default_top_secam_high = -2,
},
};
/* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */ /* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */
static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = { static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = {
...@@ -1254,6 +1279,28 @@ static struct tuner_params tuner_tcl_mf02gip_5n_params[] = { ...@@ -1254,6 +1279,28 @@ static struct tuner_params tuner_tcl_mf02gip_5n_params[] = {
}, },
}; };
/* 80-89 */
/* --------- TUNER_PHILIPS_FQ1216LME_MK3 -- active loopthrough, no FM ------- */
static struct tuner_params tuner_fq1216lme_mk3_params[] = {
{
.type = TUNER_PARAM_TYPE_PAL,
.ranges = tuner_fm1216me_mk3_pal_ranges,
.count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
.cb_first_if_lower_freq = 1, /* not specified, but safe to do */
.has_tda9887 = 1, /* TDA9886 */
.port1_active = 1,
.port2_active = 1,
.port2_invert_for_secam_lc = 1,
.default_top_low = 4,
.default_top_mid = 4,
.default_top_high = 4,
.default_top_secam_low = 4,
.default_top_secam_mid = 4,
.default_top_secam_high = 4,
},
};
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
struct tunertype tuners[] = { struct tunertype tuners[] = {
...@@ -1694,6 +1741,18 @@ struct tunertype tuners[] = { ...@@ -1694,6 +1741,18 @@ struct tunertype tuners[] = {
.initdata = tua603x_agc112, .initdata = tua603x_agc112,
.sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 }, .sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
}, },
[TUNER_PHILIPS_FM1216MK5] = { /* Philips PAL */
.name = "Philips PAL/SECAM multi (FM1216 MK5)",
.params = tuner_fm1216mk5_params,
.count = ARRAY_SIZE(tuner_fm1216mk5_params),
},
/* 80-89 */
[TUNER_PHILIPS_FQ1216LME_MK3] = { /* PAL/SECAM, Loop-thru, no FM */
.name = "Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough",
.params = tuner_fq1216lme_mk3_params,
.count = ARRAY_SIZE(tuner_fq1216lme_mk3_params),
},
}; };
EXPORT_SYMBOL(tuners); EXPORT_SYMBOL(tuners);
......
...@@ -30,7 +30,7 @@ MODULE_PARM_DESC(debug, "enable verbose debug messages"); ...@@ -30,7 +30,7 @@ MODULE_PARM_DESC(debug, "enable verbose debug messages");
static int no_poweroff; static int no_poweroff;
module_param(no_poweroff, int, 0644); module_param(no_poweroff, int, 0644);
MODULE_PARM_DESC(debug, "0 (default) powers device off when not used.\n" MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n"
"1 keep device energized and with tuner ready all the times.\n" "1 keep device energized and with tuner ready all the times.\n"
" Faster, but consumes more power and keeps the device hotter\n"); " Faster, but consumes more power and keeps the device hotter\n");
...@@ -272,7 +272,7 @@ static int load_all_firmwares(struct dvb_frontend *fe) ...@@ -272,7 +272,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
fname = firmware_name; fname = firmware_name;
tuner_dbg("Reading firmware %s\n", fname); tuner_dbg("Reading firmware %s\n", fname);
rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev); rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
if (rc < 0) { if (rc < 0) {
if (rc == -ENOENT) if (rc == -ENOENT)
tuner_err("Error: firmware %s not found.\n", tuner_err("Error: firmware %s not found.\n",
...@@ -917,22 +917,29 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, ...@@ -917,22 +917,29 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
* that xc2028 will be in a safe state. * that xc2028 will be in a safe state.
* Maybe this might also be needed for DTV. * Maybe this might also be needed for DTV.
*/ */
if (new_mode == T_ANALOG_TV) { if (new_mode == T_ANALOG_TV)
rc = send_seq(priv, {0x00, 0x00}); rc = send_seq(priv, {0x00, 0x00});
} else if (priv->cur_fw.type & ATSC) {
offset = 1750000; /*
} else { * Digital modes require an offset to adjust to the
offset = 2750000; * proper frequency.
* Analog modes require offset = 0
*/
if (new_mode == T_DIGITAL_TV) {
/* Sets the offset according with firmware */
if (priv->cur_fw.type & DTV6)
offset = 1750000;
else if (priv->cur_fw.type & DTV7)
offset = 2250000;
else /* DTV8 or DTV78 */
offset = 2750000;
/* /*
* We must adjust the offset by 500kHz in two cases in order * We must adjust the offset by 500kHz when
* to correctly center the IF output: * tuning a 7MHz VHF channel with DTV78 firmware
* 1) When the ZARLINK456 or DIBCOM52 tables were explicitly * (used in Australia, Italy and Germany)
* selected and a 7MHz channel is tuned;
* 2) When tuning a VHF channel with DTV78 firmware.
*/ */
if (((priv->cur_fw.type & DTV7) && if ((priv->cur_fw.type & DTV78) && freq < 470000000)
(priv->cur_fw.scode_table & (ZARLINK456 | DIBCOM52))) ||
((priv->cur_fw.type & DTV78) && freq < 470000000))
offset -= 500000; offset -= 500000;
} }
...@@ -991,7 +998,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe, ...@@ -991,7 +998,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
if (priv->ctrl.input1) if (priv->ctrl.input1)
type |= INPUT1; type |= INPUT1;
return generic_set_freq(fe, (625l * p->frequency) / 10, return generic_set_freq(fe, (625l * p->frequency) / 10,
T_ANALOG_TV, type, 0, 0); T_RADIO, type, 0, 0);
} }
/* if std is not defined, choose one */ /* if std is not defined, choose one */
...@@ -1022,21 +1029,20 @@ static int xc2028_set_params(struct dvb_frontend *fe, ...@@ -1022,21 +1029,20 @@ static int xc2028_set_params(struct dvb_frontend *fe,
switch(fe->ops.info.type) { switch(fe->ops.info.type) {
case FE_OFDM: case FE_OFDM:
bw = p->u.ofdm.bandwidth; bw = p->u.ofdm.bandwidth;
break; /*
case FE_QAM: * The only countries with 6MHz seem to be Taiwan/Uruguay.
tuner_info("WARN: There are some reports that " * Both seem to require QAM firmware for OFDM decoding
"QAM 6 MHz doesn't work.\n" * Tested in Taiwan by Terry Wu <terrywu2009@gmail.com>
"If this works for you, please report by " */
"e-mail to: v4l-dvb-maintainer@linuxtv.org\n"); if (bw == BANDWIDTH_6_MHZ)
bw = BANDWIDTH_6_MHZ; type |= QAM;
type |= QAM;
break; break;
case FE_ATSC: case FE_ATSC:
bw = BANDWIDTH_6_MHZ; bw = BANDWIDTH_6_MHZ;
/* The only ATSC firmware (at least on v2.7) is D2633 */ /* The only ATSC firmware (at least on v2.7) is D2633 */
type |= ATSC | D2633; type |= ATSC | D2633;
break; break;
/* DVB-S is not supported */ /* DVB-S and pure QAM (FE_QAM) are not supported */
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Copyright (c) 2007 Xceive Corporation * Copyright (c) 2007 Xceive Corporation
* Copyright (c) 2007 Steven Toth <stoth@linuxtv.org> * Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
* Copyright (c) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -36,14 +37,20 @@ static int debug; ...@@ -36,14 +37,20 @@ static int debug;
module_param(debug, int, 0644); module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
static int no_poweroff;
module_param(no_poweroff, int, 0644);
MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n"
"\t\t1 keep device energized and with tuner ready all the times.\n"
"\t\tFaster, but consumes more power and keeps the device hotter");
static DEFINE_MUTEX(xc5000_list_mutex); static DEFINE_MUTEX(xc5000_list_mutex);
static LIST_HEAD(hybrid_tuner_instance_list); static LIST_HEAD(hybrid_tuner_instance_list);
#define dprintk(level, fmt, arg...) if (debug >= level) \ #define dprintk(level, fmt, arg...) if (debug >= level) \
printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw" #define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.6.114.fw"
#define XC5000_DEFAULT_FIRMWARE_SIZE 12332 #define XC5000_DEFAULT_FIRMWARE_SIZE 12401
struct xc5000_priv { struct xc5000_priv {
struct tuner_i2c_props i2c_props; struct tuner_i2c_props i2c_props;
...@@ -83,11 +90,11 @@ struct xc5000_priv { ...@@ -83,11 +90,11 @@ struct xc5000_priv {
#define XREG_D_CODE 0x04 #define XREG_D_CODE 0x04
#define XREG_IF_OUT 0x05 #define XREG_IF_OUT 0x05
#define XREG_SEEK_MODE 0x07 #define XREG_SEEK_MODE 0x07
#define XREG_POWER_DOWN 0x0A #define XREG_POWER_DOWN 0x0A /* Obsolete */
#define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */ #define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
#define XREG_SMOOTHEDCVBS 0x0E #define XREG_SMOOTHEDCVBS 0x0E
#define XREG_XTALFREQ 0x0F #define XREG_XTALFREQ 0x0F
#define XREG_FINERFFREQ 0x10 #define XREG_FINERFREQ 0x10
#define XREG_DDIMODE 0x11 #define XREG_DDIMODE 0x11
#define XREG_ADC_ENV 0x00 #define XREG_ADC_ENV 0x00
...@@ -100,6 +107,7 @@ struct xc5000_priv { ...@@ -100,6 +107,7 @@ struct xc5000_priv {
#define XREG_VERSION 0x07 #define XREG_VERSION 0x07
#define XREG_PRODUCT_ID 0x08 #define XREG_PRODUCT_ID 0x08
#define XREG_BUSY 0x09 #define XREG_BUSY 0x09
#define XREG_BUILD 0x0D
/* /*
Basic firmware description. This will remain with Basic firmware description. This will remain with
...@@ -191,27 +199,36 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { ...@@ -191,27 +199,36 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
{"FM Radio-INPUT1", 0x0208, 0x9002} {"FM Radio-INPUT1", 0x0208, 0x9002}
}; };
static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len); static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len); static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val);
static void xc5000_TunerReset(struct dvb_frontend *fe); static int xc5000_TunerReset(struct dvb_frontend *fe);
static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
{ {
return xc5000_writeregs(priv, buf, len) struct i2c_msg msg = { .addr = priv->i2c_props.addr,
? XC_RESULT_I2C_WRITE_FAILURE : XC_RESULT_SUCCESS; .flags = 0, .buf = buf, .len = len };
if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", len);
return XC_RESULT_I2C_WRITE_FAILURE;
}
return XC_RESULT_SUCCESS;
} }
/* This routine is never used because the only time we read data from the
i2c bus is when we read registers, and we want that to be an atomic i2c
transaction in case we are on a multi-master bus */
static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
{ {
return xc5000_readregs(priv, buf, len) struct i2c_msg msg = { .addr = priv->i2c_props.addr,
? XC_RESULT_I2C_READ_FAILURE : XC_RESULT_SUCCESS; .flags = I2C_M_RD, .buf = buf, .len = len };
}
static int xc_reset(struct dvb_frontend *fe) if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
{ printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", len);
xc5000_TunerReset(fe); return -EREMOTEIO;
return XC_RESULT_SUCCESS; }
return 0;
} }
static void xc_wait(int wait_ms) static void xc_wait(int wait_ms)
...@@ -219,7 +236,7 @@ static void xc_wait(int wait_ms) ...@@ -219,7 +236,7 @@ static void xc_wait(int wait_ms)
msleep(wait_ms); msleep(wait_ms);
} }
static void xc5000_TunerReset(struct dvb_frontend *fe) static int xc5000_TunerReset(struct dvb_frontend *fe)
{ {
struct xc5000_priv *priv = fe->tuner_priv; struct xc5000_priv *priv = fe->tuner_priv;
int ret; int ret;
...@@ -232,16 +249,21 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) ...@@ -232,16 +249,21 @@ static void xc5000_TunerReset(struct dvb_frontend *fe)
priv->i2c_props.adap->algo_data, priv->i2c_props.adap->algo_data,
DVB_FRONTEND_COMPONENT_TUNER, DVB_FRONTEND_COMPONENT_TUNER,
XC5000_TUNER_RESET, 0); XC5000_TUNER_RESET, 0);
if (ret) if (ret) {
printk(KERN_ERR "xc5000: reset failed\n"); printk(KERN_ERR "xc5000: reset failed\n");
} else return XC_RESULT_RESET_FAILURE;
}
} else {
printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n"); printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n");
return XC_RESULT_RESET_FAILURE;
}
return XC_RESULT_SUCCESS;
} }
static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
{ {
u8 buf[4]; u8 buf[4];
int WatchDogTimer = 5; int WatchDogTimer = 100;
int result; int result;
buf[0] = (regAddr >> 8) & 0xFF; buf[0] = (regAddr >> 8) & 0xFF;
...@@ -263,7 +285,7 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) ...@@ -263,7 +285,7 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
/* busy flag cleared */ /* busy flag cleared */
break; break;
} else { } else {
xc_wait(100); /* wait 5 ms */ xc_wait(5); /* wait 5 ms */
WatchDogTimer--; WatchDogTimer--;
} }
} }
...@@ -276,25 +298,6 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) ...@@ -276,25 +298,6 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
return result; return result;
} }
static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData)
{
u8 buf[2];
int result;
buf[0] = (regAddr >> 8) & 0xFF;
buf[1] = regAddr & 0xFF;
result = xc_send_i2c_data(priv, buf, 2);
if (result != XC_RESULT_SUCCESS)
return result;
result = xc_read_i2c_data(priv, buf, 2);
if (result != XC_RESULT_SUCCESS)
return result;
*i2cData = buf[0] * 256 + buf[1];
return result;
}
static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence) static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
{ {
struct xc5000_priv *priv = fe->tuner_priv; struct xc5000_priv *priv = fe->tuner_priv;
...@@ -309,7 +312,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence) ...@@ -309,7 +312,7 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
len = i2c_sequence[index] * 256 + i2c_sequence[index+1]; len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
if (len == 0x0000) { if (len == 0x0000) {
/* RESET command */ /* RESET command */
result = xc_reset(fe); result = xc5000_TunerReset(fe);
index += 2; index += 2;
if (result != XC_RESULT_SUCCESS) if (result != XC_RESULT_SUCCESS)
return result; return result;
...@@ -371,15 +374,6 @@ static int xc_SetTVStandard(struct xc5000_priv *priv, ...@@ -371,15 +374,6 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
return ret; return ret;
} }
static int xc_shutdown(struct xc5000_priv *priv)
{
return XC_RESULT_SUCCESS;
/* Fixme: cannot bring tuner back alive once shutdown
* without reloading the driver modules.
* return xc_write_reg(priv, XREG_POWER_DOWN, 0);
*/
}
static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
{ {
dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode, dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
...@@ -408,7 +402,10 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) ...@@ -408,7 +402,10 @@ static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
freq_code = (u16)(freq_hz / 15625); freq_code = (u16)(freq_hz / 15625);
return xc_write_reg(priv, XREG_RF_FREQ, freq_code); /* Starting in firmware version 1.1.44, Xceive recommends using the
FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
only be used for fast scanning for channel lock) */
return xc_write_reg(priv, XREG_FINERFREQ, freq_code);
} }
...@@ -424,7 +421,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz) ...@@ -424,7 +421,7 @@ static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope) static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope)
{ {
return xc_read_reg(priv, XREG_ADC_ENV, adc_envelope); return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope);
} }
static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
...@@ -433,8 +430,8 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) ...@@ -433,8 +430,8 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
u16 regData; u16 regData;
u32 tmp; u32 tmp;
result = xc_read_reg(priv, XREG_FREQ_ERROR, &regData); result = xc5000_readreg(priv, XREG_FREQ_ERROR, &regData);
if (result) if (result != XC_RESULT_SUCCESS)
return result; return result;
tmp = (u32)regData; tmp = (u32)regData;
...@@ -444,7 +441,7 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) ...@@ -444,7 +441,7 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status) static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
{ {
return xc_read_reg(priv, XREG_LOCK, lock_status); return xc5000_readreg(priv, XREG_LOCK, lock_status);
} }
static int xc_get_version(struct xc5000_priv *priv, static int xc_get_version(struct xc5000_priv *priv,
...@@ -454,8 +451,8 @@ static int xc_get_version(struct xc5000_priv *priv, ...@@ -454,8 +451,8 @@ static int xc_get_version(struct xc5000_priv *priv,
u16 data; u16 data;
int result; int result;
result = xc_read_reg(priv, XREG_VERSION, &data); result = xc5000_readreg(priv, XREG_VERSION, &data);
if (result) if (result != XC_RESULT_SUCCESS)
return result; return result;
(*hw_majorversion) = (data >> 12) & 0x0F; (*hw_majorversion) = (data >> 12) & 0x0F;
...@@ -466,13 +463,18 @@ static int xc_get_version(struct xc5000_priv *priv, ...@@ -466,13 +463,18 @@ static int xc_get_version(struct xc5000_priv *priv,
return 0; return 0;
} }
static int xc_get_buildversion(struct xc5000_priv *priv, u16 *buildrev)
{
return xc5000_readreg(priv, XREG_BUILD, buildrev);
}
static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
{ {
u16 regData; u16 regData;
int result; int result;
result = xc_read_reg(priv, XREG_HSYNC_FREQ, &regData); result = xc5000_readreg(priv, XREG_HSYNC_FREQ, &regData);
if (result) if (result != XC_RESULT_SUCCESS)
return result; return result;
(*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100; (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
...@@ -481,12 +483,12 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) ...@@ -481,12 +483,12 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines) static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
{ {
return xc_read_reg(priv, XREG_FRAME_LINES, frame_lines); return xc5000_readreg(priv, XREG_FRAME_LINES, frame_lines);
} }
static int xc_get_quality(struct xc5000_priv *priv, u16 *quality) static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
{ {
return xc_read_reg(priv, XREG_QUALITY, quality); return xc5000_readreg(priv, XREG_QUALITY, quality);
} }
static u16 WaitForLock(struct xc5000_priv *priv) static u16 WaitForLock(struct xc5000_priv *priv)
...@@ -504,7 +506,9 @@ static u16 WaitForLock(struct xc5000_priv *priv) ...@@ -504,7 +506,9 @@ static u16 WaitForLock(struct xc5000_priv *priv)
return lockState; return lockState;
} }
static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz) #define XC_TUNE_ANALOG 0
#define XC_TUNE_DIGITAL 1
static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode)
{ {
int found = 0; int found = 0;
...@@ -513,8 +517,10 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz) ...@@ -513,8 +517,10 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz)
if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
return 0; return 0;
if (WaitForLock(priv) == 1) if (mode == XC_TUNE_ANALOG) {
found = 1; if (WaitForLock(priv) == 1)
found = 1;
}
return found; return found;
} }
...@@ -536,32 +542,7 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val) ...@@ -536,32 +542,7 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
} }
*val = (bval[0] << 8) | bval[1]; *val = (bval[0] << 8) | bval[1];
return 0; return XC_RESULT_SUCCESS;
}
static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
{
struct i2c_msg msg = { .addr = priv->i2c_props.addr,
.flags = 0, .buf = buf, .len = len };
if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n",
(int)len);
return -EREMOTEIO;
}
return 0;
}
static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len)
{
struct i2c_msg msg = { .addr = priv->i2c_props.addr,
.flags = I2C_M_RD, .buf = buf, .len = len };
if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", (int)len);
return -EREMOTEIO;
}
return 0;
} }
static int xc5000_fwupload(struct dvb_frontend *fe) static int xc5000_fwupload(struct dvb_frontend *fe)
...@@ -575,13 +556,13 @@ static int xc5000_fwupload(struct dvb_frontend *fe) ...@@ -575,13 +556,13 @@ static int xc5000_fwupload(struct dvb_frontend *fe)
XC5000_DEFAULT_FIRMWARE); XC5000_DEFAULT_FIRMWARE);
ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE,
&priv->i2c_props.adap->dev); priv->i2c_props.adap->dev.parent);
if (ret) { if (ret) {
printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
ret = XC_RESULT_RESET_FAILURE; ret = XC_RESULT_RESET_FAILURE;
goto out; goto out;
} else { } else {
printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n", printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n",
fw->size); fw->size);
ret = XC_RESULT_SUCCESS; ret = XC_RESULT_SUCCESS;
} }
...@@ -590,8 +571,9 @@ static int xc5000_fwupload(struct dvb_frontend *fe) ...@@ -590,8 +571,9 @@ static int xc5000_fwupload(struct dvb_frontend *fe)
printk(KERN_ERR "xc5000: firmware incorrect size\n"); printk(KERN_ERR "xc5000: firmware incorrect size\n");
ret = XC_RESULT_RESET_FAILURE; ret = XC_RESULT_RESET_FAILURE;
} else { } else {
printk(KERN_INFO "xc5000: firmware upload\n"); printk(KERN_INFO "xc5000: firmware uploading...\n");
ret = xc_load_i2c_sequence(fe, fw->data); ret = xc_load_i2c_sequence(fe, fw->data);
printk(KERN_INFO "xc5000: firmware upload complete...\n");
} }
out: out:
...@@ -609,6 +591,7 @@ static void xc_debug_dump(struct xc5000_priv *priv) ...@@ -609,6 +591,7 @@ static void xc_debug_dump(struct xc5000_priv *priv)
u16 quality; u16 quality;
u8 hw_majorversion = 0, hw_minorversion = 0; u8 hw_majorversion = 0, hw_minorversion = 0;
u8 fw_majorversion = 0, fw_minorversion = 0; u8 fw_majorversion = 0, fw_minorversion = 0;
u16 fw_buildversion = 0;
/* Wait for stats to stabilize. /* Wait for stats to stabilize.
* Frame Lines needs two frame times after initial lock * Frame Lines needs two frame times after initial lock
...@@ -628,9 +611,10 @@ static void xc_debug_dump(struct xc5000_priv *priv) ...@@ -628,9 +611,10 @@ static void xc_debug_dump(struct xc5000_priv *priv)
xc_get_version(priv, &hw_majorversion, &hw_minorversion, xc_get_version(priv, &hw_majorversion, &hw_minorversion,
&fw_majorversion, &fw_minorversion); &fw_majorversion, &fw_minorversion);
dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n", xc_get_buildversion(priv, &fw_buildversion);
dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x.%04x\n",
hw_majorversion, hw_minorversion, hw_majorversion, hw_minorversion,
fw_majorversion, fw_minorversion); fw_majorversion, fw_minorversion, fw_buildversion);
xc_get_hsync_freq(priv, &hsync_freq_hz); xc_get_hsync_freq(priv, &hsync_freq_hz);
dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz); dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
...@@ -648,27 +632,57 @@ static int xc5000_set_params(struct dvb_frontend *fe, ...@@ -648,27 +632,57 @@ static int xc5000_set_params(struct dvb_frontend *fe,
struct xc5000_priv *priv = fe->tuner_priv; struct xc5000_priv *priv = fe->tuner_priv;
int ret; int ret;
if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
xc_load_fw_and_init_tuner(fe);
dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
switch (params->u.vsb.modulation) { if (fe->ops.info.type == FE_ATSC) {
case VSB_8: dprintk(1, "%s() ATSC\n", __func__);
case VSB_16: switch (params->u.vsb.modulation) {
dprintk(1, "%s() VSB modulation\n", __func__); case VSB_8:
case VSB_16:
dprintk(1, "%s() VSB modulation\n", __func__);
priv->rf_mode = XC_RF_MODE_AIR;
priv->freq_hz = params->frequency - 1750000;
priv->bandwidth = BANDWIDTH_6_MHZ;
priv->video_standard = DTV6;
break;
case QAM_64:
case QAM_256:
case QAM_AUTO:
dprintk(1, "%s() QAM modulation\n", __func__);
priv->rf_mode = XC_RF_MODE_CABLE;
priv->freq_hz = params->frequency - 1750000;
priv->bandwidth = BANDWIDTH_6_MHZ;
priv->video_standard = DTV6;
break;
default:
return -EINVAL;
}
} else if (fe->ops.info.type == FE_OFDM) {
dprintk(1, "%s() OFDM\n", __func__);
switch (params->u.ofdm.bandwidth) {
case BANDWIDTH_6_MHZ:
priv->bandwidth = BANDWIDTH_6_MHZ;
priv->video_standard = DTV6;
priv->freq_hz = params->frequency - 1750000;
break;
case BANDWIDTH_7_MHZ:
printk(KERN_ERR "xc5000 bandwidth 7MHz not supported\n");
return -EINVAL;
case BANDWIDTH_8_MHZ:
priv->bandwidth = BANDWIDTH_8_MHZ;
priv->video_standard = DTV8;
priv->freq_hz = params->frequency - 2750000;
break;
default:
printk(KERN_ERR "xc5000 bandwidth not set!\n");
return -EINVAL;
}
priv->rf_mode = XC_RF_MODE_AIR; priv->rf_mode = XC_RF_MODE_AIR;
priv->freq_hz = params->frequency - 1750000; } else {
priv->bandwidth = BANDWIDTH_6_MHZ; printk(KERN_ERR "xc5000 modulation type not supported!\n");
priv->video_standard = DTV6;
break;
case QAM_64:
case QAM_256:
case QAM_AUTO:
dprintk(1, "%s() QAM modulation\n", __func__);
priv->rf_mode = XC_RF_MODE_CABLE;
priv->freq_hz = params->frequency - 1750000;
priv->bandwidth = BANDWIDTH_6_MHZ;
priv->video_standard = DTV6;
break;
default:
return -EINVAL; return -EINVAL;
} }
...@@ -698,7 +712,7 @@ static int xc5000_set_params(struct dvb_frontend *fe, ...@@ -698,7 +712,7 @@ static int xc5000_set_params(struct dvb_frontend *fe,
return -EIO; return -EIO;
} }
xc_tune_channel(priv, priv->freq_hz); xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
if (debug) if (debug)
xc_debug_dump(priv); xc_debug_dump(priv);
...@@ -725,8 +739,6 @@ static int xc5000_is_firmware_loaded(struct dvb_frontend *fe) ...@@ -725,8 +739,6 @@ static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
return ret; return ret;
} }
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
static int xc5000_set_analog_params(struct dvb_frontend *fe, static int xc5000_set_analog_params(struct dvb_frontend *fe,
struct analog_parameters *params) struct analog_parameters *params)
{ {
...@@ -807,7 +819,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, ...@@ -807,7 +819,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
return -EREMOTEIO; return -EREMOTEIO;
} }
xc_tune_channel(priv, priv->freq_hz); xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
if (debug) if (debug)
xc_debug_dump(priv); xc_debug_dump(priv);
...@@ -875,18 +887,18 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) ...@@ -875,18 +887,18 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
static int xc5000_sleep(struct dvb_frontend *fe) static int xc5000_sleep(struct dvb_frontend *fe)
{ {
struct xc5000_priv *priv = fe->tuner_priv;
int ret; int ret;
dprintk(1, "%s()\n", __func__); dprintk(1, "%s()\n", __func__);
/* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized /* Avoid firmware reload on slow devices */
* once shutdown without reloading the driver. Maybe I am not if (no_poweroff)
* doing something right. return 0;
*
*/
ret = xc_shutdown(priv); /* According to Xceive technical support, the "powerdown" register
was removed in newer versions of the firmware. The "supported"
way to sleep the tuner is to pull the reset pin low for 10ms */
ret = xc5000_TunerReset(fe);
if (ret != XC_RESULT_SUCCESS) { if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR printk(KERN_ERR
"xc5000: %s() unable to shutdown tuner\n", "xc5000: %s() unable to shutdown tuner\n",
...@@ -991,7 +1003,7 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, ...@@ -991,7 +1003,7 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
/* Check if firmware has been loaded. It is possible that another /* Check if firmware has been loaded. It is possible that another
instance of the driver has loaded the firmware. instance of the driver has loaded the firmware.
*/ */
if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS)
goto fail; goto fail;
switch (id) { switch (id) {
......
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* * flexcop-common.h - common header file for device-specific source files
* flexcop-common.h - common header file for device-specific source files also. * see flexcop.c for copyright information
*
* see flexcop.c for copyright information.
*/ */
#ifndef __FLEXCOP_COMMON_H__ #ifndef __FLEXCOP_COMMON_H__
#define __FLEXCOP_COMMON_H__ #define __FLEXCOP_COMMON_H__
......
...@@ -200,7 +200,7 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, ...@@ -200,7 +200,7 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap,
msgs[i].buf[0], &msgs[i].buf[1], msgs[i].buf[0], &msgs[i].buf[1],
msgs[i].len - 1); msgs[i].len - 1);
if (ret < 0) { if (ret < 0) {
err("i2c master_xfer failed"); deb_i2c("i2c master_xfer failed");
break; break;
} }
} }
......
...@@ -46,16 +46,16 @@ static const char *flexcop_revision_names[] = { ...@@ -46,16 +46,16 @@ static const char *flexcop_revision_names[] = {
}; };
static const char *flexcop_device_names[] = { static const char *flexcop_device_names[] = {
"Unknown device", [FC_UNK] = "Unknown device",
"Air2PC/AirStar 2 DVB-T", [FC_CABLE] = "Cable2PC/CableStar 2 DVB-C",
"Air2PC/AirStar 2 ATSC 1st generation", [FC_AIR_DVBT] = "Air2PC/AirStar 2 DVB-T",
"Air2PC/AirStar 2 ATSC 2nd generation", [FC_AIR_ATSC1] = "Air2PC/AirStar 2 ATSC 1st generation",
"Sky2PC/SkyStar 2 DVB-S", [FC_AIR_ATSC2] = "Air2PC/AirStar 2 ATSC 2nd generation",
"Sky2PC/SkyStar 2 DVB-S (old version)", [FC_AIR_ATSC3] = "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
"Cable2PC/CableStar 2 DVB-C", [FC_SKY_REV23] = "Sky2PC/SkyStar 2 DVB-S rev 2.3 (old version)",
"Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6",
"Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
"Sky2PC/SkyStar 2 DVB-S rev 2.8", [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8",
}; };
static const char *flexcop_bus_names[] = { static const char *flexcop_bus_names[] = {
......
...@@ -508,12 +508,6 @@ static int __devinit bt878_probe(struct pci_dev *dev, ...@@ -508,12 +508,6 @@ static int __devinit bt878_probe(struct pci_dev *dev,
pci_set_master(dev); pci_set_master(dev);
pci_set_drvdata(dev, bt); pci_set_drvdata(dev, bt);
/* if(init_bt878(btv) < 0) {
bt878_remove(dev);
return -EIO;
}
*/
if ((result = bt878_mem_alloc(bt))) { if ((result = bt878_mem_alloc(bt))) {
printk(KERN_ERR "bt878: failed to allocate memory!\n"); printk(KERN_ERR "bt878: failed to allocate memory!\n");
goto fail2; goto fail2;
...@@ -579,7 +573,7 @@ static struct pci_driver bt878_pci_driver = { ...@@ -579,7 +573,7 @@ static struct pci_driver bt878_pci_driver = {
.name = "bt878", .name = "bt878",
.id_table = bt878_pci_tbl, .id_table = bt878_pci_tbl,
.probe = bt878_probe, .probe = bt878_probe,
.remove = bt878_remove, .remove = __devexit_p(bt878_remove),
}; };
static int bt878_pci_driver_registered; static int bt878_pci_driver_registered;
......
...@@ -51,6 +51,9 @@ ...@@ -51,6 +51,9 @@
#ifndef PCI_VENDOR_ID_TRIGEM #ifndef PCI_VENDOR_ID_TRIGEM
#define PCI_VENDOR_ID_TRIGEM 0x109f #define PCI_VENDOR_ID_TRIGEM 0x109f
#endif #endif
#ifndef PCI_VENDOR_ID_AXESS
#define PCI_VENDOR_ID_AXESS 0x195d
#endif
#ifndef PCI_DEVICE_ID_DM1105 #ifndef PCI_DEVICE_ID_DM1105
#define PCI_DEVICE_ID_DM1105 0x036f #define PCI_DEVICE_ID_DM1105 0x036f
#endif #endif
...@@ -60,6 +63,9 @@ ...@@ -60,6 +63,9 @@
#ifndef PCI_DEVICE_ID_DW2004 #ifndef PCI_DEVICE_ID_DW2004
#define PCI_DEVICE_ID_DW2004 0x2004 #define PCI_DEVICE_ID_DW2004 0x2004
#endif #endif
#ifndef PCI_DEVICE_ID_DM05
#define PCI_DEVICE_ID_DM05 0x1105
#endif
/* ----------------------------------------------- */ /* ----------------------------------------------- */
/* sdmc dm1105 registers */ /* sdmc dm1105 registers */
...@@ -150,6 +156,11 @@ ...@@ -150,6 +156,11 @@
#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 */
#define DM05_LNB_MASK 0x00000000
#define DM05_LNB_13V 0x00020000
#define DM05_LNB_18V 0x00030000
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");
...@@ -188,6 +199,8 @@ struct dm1105dvb { ...@@ -188,6 +199,8 @@ struct dm1105dvb {
/* irq */ /* irq */
struct work_struct work; struct work_struct work;
struct workqueue_struct *wq;
char wqn[16];
/* dma */ /* dma */
dma_addr_t dma_addr; dma_addr_t dma_addr;
...@@ -313,15 +326,25 @@ static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe) ...@@ -313,15 +326,25 @@ 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;
if (voltage == SEC_VOLTAGE_18) { switch (dm1105dvb->pdev->subsystem_device) {
outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR)); case PCI_DEVICE_ID_DM05:
outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL)); lnb_mask = DM05_LNB_MASK;
} else { lnb_13v = DM05_LNB_13V;
/*LNB ON-13V by default!*/ lnb_18v = DM05_LNB_18V;
outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR)); break;
outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL)); default:
} lnb_mask = DM1105_LNB_MASK;
lnb_13v = DM1105_LNB_13V;
lnb_18v = DM1105_LNB_18V;
}
outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR));
if (voltage == SEC_VOLTAGE_18)
outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL));
else
outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL));
return 0; return 0;
} }
...@@ -440,7 +463,7 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) ...@@ -440,7 +463,7 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
case (INTSTS_TSIRQ | INTSTS_IR): case (INTSTS_TSIRQ | INTSTS_IR):
dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) - dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
inl(dm_io_mem(DM1105_STADR)); inl(dm_io_mem(DM1105_STADR));
schedule_work(&dm1105dvb->work); queue_work(dm1105dvb->wq, &dm1105dvb->work);
break; break;
case INTSTS_IR: case INTSTS_IR:
dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE)); dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
...@@ -567,46 +590,44 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) ...@@ -567,46 +590,44 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb)
int ret; int ret;
switch (dm1105dvb->pdev->subsystem_device) { switch (dm1105dvb->pdev->subsystem_device) {
case PCI_DEVICE_ID_DW2002: case PCI_DEVICE_ID_DW2004:
dm1105dvb->fe = dvb_attach( dm1105dvb->fe = dvb_attach(
stv0299_attach, &sharp_z0194a_config, cx24116_attach, &serit_sp2633_config,
&dm1105dvb->i2c_adap); &dm1105dvb->i2c_adap);
if (dm1105dvb->fe)
dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
break;
default:
dm1105dvb->fe = dvb_attach(
stv0299_attach, &sharp_z0194a_config,
&dm1105dvb->i2c_adap);
if (dm1105dvb->fe) { if (dm1105dvb->fe) {
dm1105dvb->fe->ops.set_voltage = dm1105dvb->fe->ops.set_voltage =
dm1105dvb_set_voltage; dm1105dvb_set_voltage;
dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60, dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60,
&dm1105dvb->i2c_adap, DVB_PLL_OPERA1); &dm1105dvb->i2c_adap, DVB_PLL_OPERA1);
break;
} }
if (!dm1105dvb->fe) { dm1105dvb->fe = dvb_attach(
dm1105dvb->fe = dvb_attach( stv0288_attach, &earda_config,
stv0288_attach, &earda_config, &dm1105dvb->i2c_adap);
&dm1105dvb->i2c_adap); if (dm1105dvb->fe) {
if (dm1105dvb->fe) { dm1105dvb->fe->ops.set_voltage =
dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
dm1105dvb_set_voltage; dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61, &dm1105dvb->i2c_adap);
&dm1105dvb->i2c_adap); break;
}
} }
if (!dm1105dvb->fe) {
dm1105dvb->fe = dvb_attach(
si21xx_attach, &serit_config,
&dm1105dvb->i2c_adap);
if (dm1105dvb->fe)
dm1105dvb->fe->ops.set_voltage =
dm1105dvb_set_voltage;
}
break;
case PCI_DEVICE_ID_DW2004:
dm1105dvb->fe = dvb_attach( dm1105dvb->fe = dvb_attach(
cx24116_attach, &serit_sp2633_config, si21xx_attach, &serit_config,
&dm1105dvb->i2c_adap); &dm1105dvb->i2c_adap);
if (dm1105dvb->fe) if (dm1105dvb->fe)
dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; dm1105dvb->fe->ops.set_voltage =
break; dm1105dvb_set_voltage;
} }
if (!dm1105dvb->fe) { if (!dm1105dvb->fe) {
...@@ -630,10 +651,17 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac) ...@@ -630,10 +651,17 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac)
static u8 command[1] = { 0x28 }; static u8 command[1] = { 0x28 };
struct i2c_msg msg[] = { struct i2c_msg msg[] = {
{ .addr = IIC_24C01_addr >> 1, .flags = 0, {
.buf = command, .len = 1 }, .addr = IIC_24C01_addr >> 1,
{ .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD, .flags = 0,
.buf = mac, .len = 6 }, .buf = command,
.len = 1
}, {
.addr = IIC_24C01_addr >> 1,
.flags = I2C_M_RD,
.buf = mac,
.len = 6
},
}; };
dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2); dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2);
...@@ -752,14 +780,22 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, ...@@ -752,14 +780,22 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
dm1105_ir_init(dm1105dvb); dm1105_ir_init(dm1105dvb);
INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer); INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
sprintf(dm1105dvb->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
dm1105dvb->wq = create_singlethread_workqueue(dm1105dvb->wqn);
if (!dm1105dvb->wq)
goto err_dvb_net;
ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
DRIVER_NAME, dm1105dvb); DRIVER_NAME, dm1105dvb);
if (ret < 0) if (ret < 0)
goto err_free_irq; goto err_workqueue;
return 0; return 0;
err_workqueue:
destroy_workqueue(dm1105dvb->wq);
err_dvb_net:
dvb_net_release(&dm1105dvb->dvbnet);
err_disconnect_frontend: err_disconnect_frontend:
dmx->disconnect_frontend(dmx); dmx->disconnect_frontend(dmx);
err_remove_mem_frontend: err_remove_mem_frontend:
...@@ -776,8 +812,6 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, ...@@ -776,8 +812,6 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
i2c_del_adapter(&dm1105dvb->i2c_adap); i2c_del_adapter(&dm1105dvb->i2c_adap);
err_dm1105dvb_hw_exit: err_dm1105dvb_hw_exit:
dm1105dvb_hw_exit(dm1105dvb); dm1105dvb_hw_exit(dm1105dvb);
err_free_irq:
free_irq(pdev->irq, dm1105dvb);
err_pci_iounmap: err_pci_iounmap:
pci_iounmap(pdev, dm1105dvb->io_mem); pci_iounmap(pdev, dm1105dvb->io_mem);
err_pci_release_regions: err_pci_release_regions:
...@@ -833,6 +867,11 @@ static struct pci_device_id dm1105_id_table[] __devinitdata = { ...@@ -833,6 +867,11 @@ static struct pci_device_id dm1105_id_table[] __devinitdata = {
.device = PCI_DEVICE_ID_DM1105, .device = PCI_DEVICE_ID_DM1105,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_DEVICE_ID_DW2004, .subdevice = PCI_DEVICE_ID_DW2004,
}, {
.vendor = PCI_VENDOR_ID_AXESS,
.device = PCI_DEVICE_ID_DM05,
.subvendor = PCI_VENDOR_ID_AXESS,
.subdevice = PCI_DEVICE_ID_DM05,
}, { }, {
/* empty */ /* empty */
}, },
......
...@@ -244,19 +244,13 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, ...@@ -244,19 +244,13 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
{ {
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv; struct dmxdev *dmxdev = dvbdev->priv;
int ret;
if (dmxdev->exit) { if (dmxdev->exit)
mutex_unlock(&dmxdev->mutex);
return -ENODEV; return -ENODEV;
}
//mutex_lock(&dmxdev->mutex); return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
ret = dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, file->f_flags & O_NONBLOCK,
file->f_flags & O_NONBLOCK, buf, count, ppos);
buf, count, ppos);
//mutex_unlock(&dmxdev->mutex);
return ret;
} }
static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
......
...@@ -38,6 +38,16 @@ ...@@ -38,6 +38,16 @@
*/ */
// #define DVB_DEMUX_SECTION_LOSS_LOG // #define DVB_DEMUX_SECTION_LOSS_LOG
static int dvb_demux_tscheck;
module_param(dvb_demux_tscheck, int, 0644);
MODULE_PARM_DESC(dvb_demux_tscheck,
"enable transport stream continuity and TEI check");
#define dprintk_tscheck(x...) do { \
if (dvb_demux_tscheck && printk_ratelimit()) \
printk(x); \
} while (0)
/****************************************************************************** /******************************************************************************
* static inlined helper functions * static inlined helper functions
******************************************************************************/ ******************************************************************************/
...@@ -376,6 +386,36 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) ...@@ -376,6 +386,36 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
u16 pid = ts_pid(buf); u16 pid = ts_pid(buf);
int dvr_done = 0; int dvr_done = 0;
if (dvb_demux_tscheck) {
if (!demux->cnt_storage)
demux->cnt_storage = vmalloc(MAX_PID + 1);
if (!demux->cnt_storage) {
printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n");
dvb_demux_tscheck = 0;
goto no_dvb_demux_tscheck;
}
/* check pkt counter */
if (pid < MAX_PID) {
if (buf[1] & 0x80)
dprintk_tscheck("TEI detected. "
"PID=0x%x data1=0x%x\n",
pid, buf[1]);
if ((buf[3] & 0xf) != demux->cnt_storage[pid])
dprintk_tscheck("TS packet counter mismatch. "
"PID=0x%x expected 0x%x "
"got 0x%x\n",
pid, demux->cnt_storage[pid],
buf[3] & 0xf);
demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf;
};
/* end check */
};
no_dvb_demux_tscheck:
list_for_each_entry(feed, &demux->feed_list, list_head) { list_for_each_entry(feed, &demux->feed_list, list_head) {
if ((feed->pid != pid) && (feed->pid != 0x2000)) if ((feed->pid != pid) && (feed->pid != 0x2000))
continue; continue;
...@@ -1160,6 +1200,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) ...@@ -1160,6 +1200,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
int i; int i;
struct dmx_demux *dmx = &dvbdemux->dmx; struct dmx_demux *dmx = &dvbdemux->dmx;
dvbdemux->cnt_storage = NULL;
dvbdemux->users = 0; dvbdemux->users = 0;
dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter)); dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
...@@ -1226,6 +1267,7 @@ EXPORT_SYMBOL(dvb_dmx_init); ...@@ -1226,6 +1267,7 @@ EXPORT_SYMBOL(dvb_dmx_init);
void dvb_dmx_release(struct dvb_demux *dvbdemux) void dvb_dmx_release(struct dvb_demux *dvbdemux)
{ {
vfree(dvbdemux->cnt_storage);
vfree(dvbdemux->filter); vfree(dvbdemux->filter);
vfree(dvbdemux->feed); vfree(dvbdemux->feed);
} }
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#define DVB_DEMUX_MASK_MAX 18 #define DVB_DEMUX_MASK_MAX 18
#define MAX_PID 0x1fff
struct dvb_demux_filter { struct dvb_demux_filter {
struct dmx_section_filter filter; struct dmx_section_filter filter;
u8 maskandmode[DMX_MAX_FILTER_SIZE]; u8 maskandmode[DMX_MAX_FILTER_SIZE];
...@@ -127,6 +129,8 @@ struct dvb_demux { ...@@ -127,6 +129,8 @@ struct dvb_demux {
struct mutex mutex; struct mutex mutex;
spinlock_t lock; spinlock_t lock;
uint8_t *cnt_storage; /* for TS continuity check */
}; };
int dvb_dmx_init(struct dvb_demux *dvbdemux); int dvb_dmx_init(struct dvb_demux *dvbdemux);
......
...@@ -543,6 +543,7 @@ static int dvb_frontend_thread(void *data) ...@@ -543,6 +543,7 @@ static int dvb_frontend_thread(void *data)
if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
/* got signal or quitting */ /* got signal or quitting */
fepriv->exit = 1;
break; break;
} }
...@@ -656,6 +657,7 @@ static int dvb_frontend_thread(void *data) ...@@ -656,6 +657,7 @@ static int dvb_frontend_thread(void *data)
} }
fepriv->thread = NULL; fepriv->thread = NULL;
fepriv->exit = 0;
mb(); mb();
dvb_frontend_wakeup(fe); dvb_frontend_wakeup(fe);
......
...@@ -261,6 +261,7 @@ config DVB_USB_DW2102 ...@@ -261,6 +261,7 @@ config DVB_USB_DW2102
select DVB_STB6000 if !DVB_FE_CUSTOMISE select DVB_STB6000 if !DVB_FE_CUSTOMISE
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
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.
......
...@@ -40,7 +40,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ...@@ -40,7 +40,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static DEFINE_MUTEX(af9015_usb_mutex); static DEFINE_MUTEX(af9015_usb_mutex);
static struct af9015_config af9015_config; static struct af9015_config af9015_config;
static struct dvb_usb_device_properties af9015_properties[2]; static struct dvb_usb_device_properties af9015_properties[3];
static int af9015_properties_count = ARRAY_SIZE(af9015_properties); static int af9015_properties_count = ARRAY_SIZE(af9015_properties);
static struct af9013_config af9015_af9013_config[] = { static struct af9013_config af9015_af9013_config[] = {
...@@ -538,7 +538,7 @@ static int af9015_copy_firmware(struct dvb_usb_device *d) ...@@ -538,7 +538,7 @@ static int af9015_copy_firmware(struct dvb_usb_device *d)
/* 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[52], buf2[4]; char buf[4+3*16+1], buf2[4];
u8 reg, val; u8 reg, val;
for (reg = 0; ; reg++) { for (reg = 0; ; reg++) {
...@@ -1261,7 +1261,11 @@ static struct usb_device_id af9015_usb_table[] = { ...@@ -1261,7 +1261,11 @@ static struct usb_device_id af9015_usb_table[] = {
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)},
{USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)}, {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)},
{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)}, /* 20 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)},
{USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
{0}, {0},
}; };
MODULE_DEVICE_TABLE(usb, af9015_usb_table); MODULE_DEVICE_TABLE(usb, af9015_usb_table);
...@@ -1321,7 +1325,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { ...@@ -1321,7 +1325,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.i2c_algo = &af9015_i2c_algo, .i2c_algo = &af9015_i2c_algo,
.num_device_descs = 9, .num_device_descs = 9, /* max 9 */
.devices = { .devices = {
{ {
.name = "Afatech AF9015 DVB-T USB2.0 stick", .name = "Afatech AF9015 DVB-T USB2.0 stick",
...@@ -1426,7 +1430,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { ...@@ -1426,7 +1430,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.i2c_algo = &af9015_i2c_algo, .i2c_algo = &af9015_i2c_algo,
.num_device_descs = 9, .num_device_descs = 9, /* max 9 */
.devices = { .devices = {
{ {
.name = "Xtensions XD-380", .name = "Xtensions XD-380",
...@@ -1478,7 +1482,85 @@ static struct dvb_usb_device_properties af9015_properties[] = { ...@@ -1478,7 +1482,85 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.warm_ids = {NULL}, .warm_ids = {NULL},
}, },
} }
} }, {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.download_firmware = af9015_download_firmware,
.firmware = "dvb-usb-af9015.fw",
.no_reconnect = 1,
.size_of_priv = sizeof(struct af9015_state), \
.num_adapters = 2,
.adapter = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = af9015_pid_filter,
.pid_filter_ctrl = af9015_pid_filter_ctrl,
.frontend_attach =
af9015_af9013_frontend_attach,
.tuner_attach = af9015_tuner_attach,
.stream = {
.type = USB_BULK,
.count = 6,
.endpoint = 0x84,
},
},
{
.frontend_attach =
af9015_af9013_frontend_attach,
.tuner_attach = af9015_tuner_attach,
.stream = {
.type = USB_BULK,
.count = 6,
.endpoint = 0x85,
.u = {
.bulk = {
.buffersize =
TS_USB20_MAX_PACKET_SIZE,
}
}
},
}
},
.identify_state = af9015_identify_state,
.rc_query = af9015_rc_query,
.rc_interval = 150,
.i2c_algo = &af9015_i2c_algo,
.num_device_descs = 4, /* max 9 */
.devices = {
{
.name = "AverMedia AVerTV Volar GPS 805 (A805)",
.cold_ids = {&af9015_usb_table[21], NULL},
.warm_ids = {NULL},
},
{
.name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \
"V3.0",
.cold_ids = {&af9015_usb_table[22], NULL},
.warm_ids = {NULL},
},
{
.name = "KWorld Digial MC-810",
.cold_ids = {&af9015_usb_table[23], NULL},
.warm_ids = {NULL},
},
{
.name = "Genius TVGo DVB-T03",
.cold_ids = {&af9015_usb_table[24], NULL},
.warm_ids = {NULL},
},
}
},
}; };
static int af9015_usb_probe(struct usb_interface *intf, static int af9015_usb_probe(struct usb_interface *intf,
......
...@@ -1346,9 +1346,9 @@ static int dib0700_xc5000_tuner_callback(void *priv, int component, ...@@ -1346,9 +1346,9 @@ static int dib0700_xc5000_tuner_callback(void *priv, int component,
if (command == XC5000_TUNER_RESET) { if (command == XC5000_TUNER_RESET) {
/* Reset the tuner */ /* Reset the tuner */
dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0); dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0);
msleep(330); /* from Windows USB trace */ msleep(10);
dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1);
msleep(330); /* from Windows USB trace */ msleep(10);
} else { } else {
err("xc5000: unknown tuner callback command: %d\n", command); err("xc5000: unknown tuner callback command: %d\n", command);
return -EINVAL; return -EINVAL;
...@@ -1493,6 +1493,10 @@ struct usb_device_id dib0700_usb_id_table[] = { ...@@ -1493,6 +1493,10 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) },
{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_MC770) }, { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_MC770) },
{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT) }, { USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT) },
/* 50 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_Dlx) },
{ 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_T5) },
{ 0 } /* Terminating entry */ { 0 } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
...@@ -1692,7 +1696,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1692,7 +1696,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}, },
}, },
.num_device_descs = 11, .num_device_descs = 12,
.devices = { .devices = {
{ "DiBcom STK7070P reference design", { "DiBcom STK7070P reference design",
{ &dib0700_usb_id_table[15], NULL }, { &dib0700_usb_id_table[15], NULL },
...@@ -1726,8 +1730,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1726,8 +1730,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[30], NULL }, { &dib0700_usb_id_table[30], NULL },
{ NULL }, { NULL },
}, },
{ "Terratec Cinergy T USB XXS", { "Terratec Cinergy T USB XXS/ T3",
{ &dib0700_usb_id_table[33], NULL }, { &dib0700_usb_id_table[33],
&dib0700_usb_id_table[52], NULL },
{ NULL }, { NULL },
}, },
{ "Elgato EyeTV DTT", { "Elgato EyeTV DTT",
...@@ -1738,6 +1743,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1738,6 +1743,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[45], NULL }, { &dib0700_usb_id_table[45], NULL },
{ NULL }, { NULL },
}, },
{ "Elgato EyeTV Dtt Dlx PD378S",
{ &dib0700_usb_id_table[50], NULL },
{ NULL },
},
}, },
.rc_interval = DEFAULT_RC_INTERVAL, .rc_interval = DEFAULT_RC_INTERVAL,
...@@ -1784,8 +1793,9 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1784,8 +1793,9 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[36], NULL }, { &dib0700_usb_id_table[36], NULL },
{ NULL }, { NULL },
}, },
{ "Terratec Cinergy DT USB XS Diversity", { "Terratec Cinergy DT USB XS Diversity/ T5",
{ &dib0700_usb_id_table[43], NULL }, { &dib0700_usb_id_table[43],
&dib0700_usb_id_table[53], NULL},
{ NULL }, { NULL },
}, },
{ "Sony PlayTV", { "Sony PlayTV",
...@@ -1812,7 +1822,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1812,7 +1822,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}, },
}, },
.num_device_descs = 7, .num_device_descs = 8,
.devices = { .devices = {
{ "Terratec Cinergy HT USB XE", { "Terratec Cinergy HT USB XE",
{ &dib0700_usb_id_table[27], NULL }, { &dib0700_usb_id_table[27], NULL },
...@@ -1842,6 +1852,11 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1842,6 +1852,11 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[48], NULL }, { &dib0700_usb_id_table[48], NULL },
{ NULL }, { NULL },
}, },
{ "Leadtek WinFast DTV Dongle H",
{ &dib0700_usb_id_table[51], NULL },
{ NULL },
},
}, },
.rc_interval = DEFAULT_RC_INTERVAL, .rc_interval = DEFAULT_RC_INTERVAL,
.rc_key_map = dib0700_rc_keys, .rc_key_map = dib0700_rc_keys,
......
...@@ -133,14 +133,17 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num ...@@ -133,14 +133,17 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
/* write/read request */ /* write/read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { if (i+1 < num && (msg[i].flags & I2C_M_RD) == 0
&& (msg[i+1].flags & I2C_M_RD)) {
if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len, if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,
msg[i+1].buf,msg[i+1].len) < 0) msg[i+1].buf,msg[i+1].len) < 0)
break; break;
i++; i++;
} else } else if ((msg[i].flags & I2C_M_RD) == 0) {
if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
break; break;
} else
break;
} }
mutex_unlock(&d->i2c_mutex); mutex_unlock(&d->i2c_mutex);
......
...@@ -80,6 +80,7 @@ ...@@ -80,6 +80,7 @@
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78
#define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80
#define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397
#define USB_PID_CONEXANT_D680_DMB 0x86d6 #define USB_PID_CONEXANT_D680_DMB 0x86d6
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
...@@ -97,6 +98,7 @@ ...@@ -97,6 +98,7 @@
#define USB_PID_DPOSH_M9206_COLD 0x9206 #define USB_PID_DPOSH_M9206_COLD 0x9206
#define USB_PID_DPOSH_M9206_WARM 0xa090 #define USB_PID_DPOSH_M9206_WARM 0xa090
#define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_UNIWILL_STK7700P 0x6003
#define USB_PID_GENIUS_TVGO_DVB_T03 0x4012
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
#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
...@@ -104,6 +106,7 @@ ...@@ -104,6 +106,7 @@
#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
#define USB_PID_KWORLD_MC810 0xc810
#define USB_PID_KWORLD_PC160_2T 0xc160 #define USB_PID_KWORLD_PC160_2T 0xc160
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de #define USB_PID_KWORLD_VSTREAM_COLD 0x17de
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df #define USB_PID_KWORLD_VSTREAM_WARM 0x17df
...@@ -171,6 +174,7 @@ ...@@ -171,6 +174,7 @@
#define USB_PID_AVERMEDIA_A309 0xa309 #define USB_PID_AVERMEDIA_A309 0xa309
#define USB_PID_AVERMEDIA_A310 0xa310 #define USB_PID_AVERMEDIA_A310 0xa310
#define USB_PID_AVERMEDIA_A850 0x850a #define USB_PID_AVERMEDIA_A850 0x850a
#define USB_PID_AVERMEDIA_A805 0xa805
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
...@@ -178,6 +182,8 @@ ...@@ -178,6 +182,8 @@
#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060
#define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062
#define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078
#define USB_PID_TERRATEC_T3 0x10a0
#define USB_PID_TERRATEC_T5 0x10a1
#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
#define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV2000E 0x022c
#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228
...@@ -222,6 +228,7 @@ ...@@ -222,6 +228,7 @@
#define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025
#define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00
#define USB_PID_WINFAST_DTV_DONGLE_H 0x60f6
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01
#define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029 #define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029
#define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200
...@@ -251,5 +258,6 @@ ...@@ -251,5 +258,6 @@
#define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807
#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
#endif #endif
...@@ -223,7 +223,7 @@ struct dvb_usb_device_properties { ...@@ -223,7 +223,7 @@ struct dvb_usb_device_properties {
int generic_bulk_ctrl_endpoint; int generic_bulk_ctrl_endpoint;
int num_device_descs; int num_device_descs;
struct dvb_usb_device_description devices[11]; struct dvb_usb_device_description devices[12];
}; };
/** /**
......
/* DVB USB framework compliant Linux driver for the /* DVB USB framework compliant Linux driver for the
* DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
* * TeVii S600, S650 Cards
* Copyright (C) 2008 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
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "stb6000.h" #include "stb6000.h"
#include "eds1547.h" #include "eds1547.h"
#include "cx24116.h" #include "cx24116.h"
#include "tda1002x.h"
#ifndef USB_PID_DW2102 #ifndef USB_PID_DW2102
#define USB_PID_DW2102 0x2102 #define USB_PID_DW2102 0x2102
...@@ -26,10 +27,18 @@ ...@@ -26,10 +27,18 @@
#define USB_PID_DW2104 0x2104 #define USB_PID_DW2104 0x2104
#endif #endif
#ifndef USB_PID_DW3101
#define USB_PID_DW3101 0x3101
#endif
#ifndef USB_PID_CINERGY_S #ifndef USB_PID_CINERGY_S
#define USB_PID_CINERGY_S 0x0064 #define USB_PID_CINERGY_S 0x0064
#endif #endif
#ifndef USB_PID_TEVII_S650
#define USB_PID_TEVII_S650 0xd650
#endif
#define DW210X_READ_MSG 0 #define DW210X_READ_MSG 0
#define DW210X_WRITE_MSG 1 #define DW210X_WRITE_MSG 1
...@@ -40,18 +49,21 @@ ...@@ -40,18 +49,21 @@
#define DW2102_VOLTAGE_CTRL (0x1800) #define DW2102_VOLTAGE_CTRL (0x1800)
#define DW2102_RC_QUERY (0x1a00) #define DW2102_RC_QUERY (0x1a00)
struct dw210x_state { struct dvb_usb_rc_keys_table {
u32 last_key_pressed; struct dvb_usb_rc_key *rc_keys;
}; int rc_keys_size;
struct dw210x_rc_keys {
u32 keycode;
u32 event;
}; };
/* debug */ /* debug */
static int dvb_usb_dw2102_debug; static int dvb_usb_dw2102_debug;
module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS); MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."
DVB_USB_DEBUG_STATUS);
/* keymaps */
static int ir_keymap;
module_param_named(keymap, ir_keymap, int, 0644);
MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ...");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
...@@ -79,7 +91,7 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, ...@@ -79,7 +91,7 @@ static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num) int num)
{ {
struct dvb_usb_device *d = i2c_get_adapdata(adap); struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0, ret = 0; int i = 0, ret = 0;
u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
u16 value; u16 value;
...@@ -205,6 +217,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, ...@@ -205,6 +217,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
mutex_unlock(&d->i2c_mutex); mutex_unlock(&d->i2c_mutex);
return num; return num;
} }
static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
{ {
struct dvb_usb_device *d = i2c_get_adapdata(adap); struct dvb_usb_device *d = i2c_get_adapdata(adap);
...@@ -219,7 +232,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms ...@@ -219,7 +232,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
case 2: { case 2: {
/* read */ /* read */
/* first write first register number */ /* first write first register number */
u8 ibuf [msg[1].len + 2], obuf[3]; u8 ibuf[msg[1].len + 2], obuf[3];
obuf[0] = 0xd0; obuf[0] = 0xd0;
obuf[1] = msg[0].len; obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0]; obuf[2] = msg[0].buf[0];
...@@ -293,7 +306,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i ...@@ -293,7 +306,7 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
case 2: { case 2: {
/* read */ /* read */
/* first write first register number */ /* first write first register number */
u8 ibuf [msg[1].len + 2], obuf[3]; u8 ibuf[msg[1].len + 2], obuf[3];
obuf[0] = 0xaa; obuf[0] = 0xaa;
obuf[1] = msg[0].len; obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0]; obuf[2] = msg[0].buf[0];
...@@ -360,6 +373,69 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i ...@@ -360,6 +373,69 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
return num; return num;
} }
static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int ret = 0, i;
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2: {
/* read */
/* first write first register number */
u8 ibuf[msg[1].len + 2], obuf[3];
obuf[0] = msg[0].addr << 1;
obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0];
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
/* second read registers */
ret = dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
ibuf, msg[1].len + 2, DW210X_READ_MSG);
memcpy(msg[1].buf, ibuf + 2, msg[1].len);
break;
}
case 1:
switch (msg[0].addr) {
case 0x60:
case 0x0c: {
/* write to register */
u8 obuf[msg[0].len + 2];
obuf[0] = msg[0].addr << 1;
obuf[1] = msg[0].len;
memcpy(obuf + 2, msg[0].buf, msg[0].len);
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
break;
}
case(DW2102_RC_QUERY): {
u8 ibuf[2];
ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 2, DW210X_READ_MSG);
memcpy(msg[0].buf, ibuf , 2);
break;
}
}
break;
}
for (i = 0; i < num; i++) {
deb_xfer("%02x:%02x: %s ", i, msg[i].addr,
msg[i].flags == 0 ? ">>>" : "<<<");
debug_dump(msg[i].buf, msg[i].len, deb_xfer);
}
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;
...@@ -385,6 +461,11 @@ static struct i2c_algorithm dw2104_i2c_algo = { ...@@ -385,6 +461,11 @@ static struct i2c_algorithm dw2104_i2c_algo = {
.functionality = dw210x_i2c_func, .functionality = dw210x_i2c_func,
}; };
static struct i2c_algorithm dw3101_i2c_algo = {
.master_xfer = dw3101_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;
...@@ -404,6 +485,7 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ...@@ -404,6 +485,7 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
debug_dump(eepromline, 16, deb_xfer); debug_dump(eepromline, 16, deb_xfer);
} }
} }
memcpy(mac, eeprom + 8, 6); memcpy(mac, eeprom + 8, 6);
return 0; return 0;
}; };
...@@ -448,6 +530,11 @@ static struct si21xx_config serit_sp1511lhb_config = { ...@@ -448,6 +530,11 @@ static struct si21xx_config serit_sp1511lhb_config = {
}; };
static struct tda10023_config dw3101_tda10023_config = {
.demod_address = 0x0c,
.invert = 1,
};
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,
...@@ -460,6 +547,7 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d) ...@@ -460,6 +547,7 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
} }
static struct dvb_usb_device_properties dw2102_properties; static struct dvb_usb_device_properties dw2102_properties;
static struct dvb_usb_device_properties dw2104_properties;
static int dw2102_frontend_attach(struct dvb_usb_adapter *d) static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
{ {
...@@ -497,6 +585,17 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d) ...@@ -497,6 +585,17 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
return -EIO; return -EIO;
} }
static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
{
d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
&d->dev->i2c_adap, 0x48);
if (d->fe != NULL) {
info("Attached tda10023!\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,
...@@ -512,6 +611,14 @@ static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap) ...@@ -512,6 +611,14 @@ static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap)
return 0; return 0;
} }
static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
&adap->dev->i2c_adap, DVB_PLL_TUA6034);
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*/ { 0xf8, 0x0a, KEY_Q }, /*power*/
{ 0xf8, 0x0c, KEY_M }, /*mute*/ { 0xf8, 0x0c, KEY_M }, /*mute*/
...@@ -544,44 +651,147 @@ static struct dvb_usb_rc_key dw210x_rc_keys[] = { ...@@ -544,44 +651,147 @@ static struct dvb_usb_rc_key dw210x_rc_keys[] = {
{ 0xf8, 0x40, KEY_F }, /*full*/ { 0xf8, 0x40, KEY_F }, /*full*/
{ 0xf8, 0x1e, KEY_W }, /*tvmode*/ { 0xf8, 0x1e, KEY_W }, /*tvmode*/
{ 0xf8, 0x1b, KEY_B }, /*recall*/ { 0xf8, 0x1b, KEY_B }, /*recall*/
};
static struct dvb_usb_rc_key tevii_rc_keys[] = {
{ 0xf8, 0x0a, KEY_POWER },
{ 0xf8, 0x0c, KEY_MUTE },
{ 0xf8, 0x11, KEY_1 },
{ 0xf8, 0x12, KEY_2 },
{ 0xf8, 0x13, KEY_3 },
{ 0xf8, 0x14, KEY_4 },
{ 0xf8, 0x15, KEY_5 },
{ 0xf8, 0x16, KEY_6 },
{ 0xf8, 0x17, KEY_7 },
{ 0xf8, 0x18, KEY_8 },
{ 0xf8, 0x19, KEY_9 },
{ 0xf8, 0x10, KEY_0 },
{ 0xf8, 0x1c, KEY_MENU },
{ 0xf8, 0x0f, KEY_VOLUMEDOWN },
{ 0xf8, 0x1a, KEY_LAST },
{ 0xf8, 0x0e, KEY_OPEN },
{ 0xf8, 0x04, KEY_RECORD },
{ 0xf8, 0x09, KEY_VOLUMEUP },
{ 0xf8, 0x08, KEY_CHANNELUP },
{ 0xf8, 0x07, KEY_PVR },
{ 0xf8, 0x0b, KEY_TIME },
{ 0xf8, 0x02, KEY_RIGHT },
{ 0xf8, 0x03, KEY_LEFT },
{ 0xf8, 0x00, KEY_UP },
{ 0xf8, 0x1f, KEY_OK },
{ 0xf8, 0x01, KEY_DOWN },
{ 0xf8, 0x05, KEY_TUNER },
{ 0xf8, 0x06, KEY_CHANNELDOWN },
{ 0xf8, 0x40, KEY_PLAYPAUSE },
{ 0xf8, 0x1e, KEY_REWIND },
{ 0xf8, 0x1b, KEY_FAVORITES },
{ 0xf8, 0x1d, KEY_BACK },
{ 0xf8, 0x4d, KEY_FASTFORWARD },
{ 0xf8, 0x44, KEY_EPG },
{ 0xf8, 0x4c, KEY_INFO },
{ 0xf8, 0x41, KEY_AB },
{ 0xf8, 0x43, KEY_AUDIO },
{ 0xf8, 0x45, KEY_SUBTITLE },
{ 0xf8, 0x4a, KEY_LIST },
{ 0xf8, 0x46, KEY_F1 },
{ 0xf8, 0x47, KEY_F2 },
{ 0xf8, 0x5e, KEY_F3 },
{ 0xf8, 0x5c, KEY_F4 },
{ 0xf8, 0x52, KEY_F5 },
{ 0xf8, 0x5a, KEY_F6 },
{ 0xf8, 0x56, KEY_MODE },
{ 0xf8, 0x58, KEY_SWITCHVIDEOMODE },
}; };
static struct dvb_usb_rc_key tbs_rc_keys[] = {
{ 0xf8, 0x84, KEY_POWER },
{ 0xf8, 0x94, KEY_MUTE },
{ 0xf8, 0x87, KEY_1 },
{ 0xf8, 0x86, KEY_2 },
{ 0xf8, 0x85, KEY_3 },
{ 0xf8, 0x8b, KEY_4 },
{ 0xf8, 0x8a, KEY_5 },
{ 0xf8, 0x89, KEY_6 },
{ 0xf8, 0x8f, KEY_7 },
{ 0xf8, 0x8e, KEY_8 },
{ 0xf8, 0x8d, KEY_9 },
{ 0xf8, 0x92, KEY_0 },
{ 0xf8, 0x96, KEY_CHANNELUP },
{ 0xf8, 0x91, KEY_CHANNELDOWN },
{ 0xf8, 0x93, KEY_VOLUMEUP },
{ 0xf8, 0x8c, KEY_VOLUMEDOWN },
{ 0xf8, 0x83, KEY_RECORD },
{ 0xf8, 0x98, KEY_PAUSE },
{ 0xf8, 0x99, KEY_OK },
{ 0xf8, 0x9a, KEY_SHUFFLE },
{ 0xf8, 0x81, KEY_UP },
{ 0xf8, 0x90, KEY_LEFT },
{ 0xf8, 0x82, KEY_RIGHT },
{ 0xf8, 0x88, KEY_DOWN },
{ 0xf8, 0x95, KEY_FAVORITES },
{ 0xf8, 0x97, KEY_SUBTITLE },
{ 0xf8, 0x9d, KEY_ZOOM },
{ 0xf8, 0x9f, KEY_EXIT },
{ 0xf8, 0x9e, KEY_MENU },
{ 0xf8, 0x9c, KEY_EPG },
{ 0xf8, 0x80, KEY_PREVIOUS },
{ 0xf8, 0x9b, KEY_MODE }
};
static struct dvb_usb_rc_keys_table keys_tables[] = {
{ dw210x_rc_keys, ARRAY_SIZE(dw210x_rc_keys) },
{ tevii_rc_keys, ARRAY_SIZE(tevii_rc_keys) },
{ tbs_rc_keys, ARRAY_SIZE(tbs_rc_keys) },
};
static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{ {
struct dw210x_state *st = d->priv; struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
int keymap_size = d->props.rc_key_map_size;
u8 key[2]; u8 key[2];
struct i2c_msg msg[] = { struct i2c_msg msg = {
{.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key, .addr = DW2102_RC_QUERY,
.len = 2}, .flags = I2C_M_RD,
.buf = key,
.len = 2
}; };
int i; int i;
/* override keymap */
if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) {
keymap = keys_tables[ir_keymap - 1].rc_keys ;
keymap_size = keys_tables[ir_keymap - 1].rc_keys_size;
}
*state = REMOTE_NO_KEY_PRESSED; *state = REMOTE_NO_KEY_PRESSED;
if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { if (dw2102_i2c_transfer(&d->i2c_adap, &msg, 1) == 1) {
for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) { for (i = 0; i < keymap_size ; i++) {
if (dw210x_rc_keys[i].data == msg[0].buf[0]) { if (keymap[i].data == msg.buf[0]) {
*state = REMOTE_KEY_PRESSED; *state = REMOTE_KEY_PRESSED;
*event = dw210x_rc_keys[i].event; *event = keymap[i].event;
st->last_key_pressed =
dw210x_rc_keys[i].event;
break; break;
} }
st->last_key_pressed = 0;
} }
if ((*state) == REMOTE_KEY_PRESSED)
deb_rc("%s: found rc key: %x, %x, event: %x\n",
__func__, key[0], key[1], (*event));
else if (key[0] != 0xff)
deb_rc("%s: unknown rc key: %x, %x\n",
__func__, key[0], key[1]);
} }
/* info("key: %x %x\n",key[0],key[1]); */
return 0; return 0;
} }
static struct usb_device_id dw2102_table[] = { static struct usb_device_id dw2102_table[] = {
{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
{USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
{USB_DEVICE(USB_VID_CYPRESS, 0x2104)}, {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
{USB_DEVICE(0x9022, 0xd650)}, {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)},
{ } { }
}; };
...@@ -642,11 +852,16 @@ static int dw2102_load_firmware(struct usb_device *dev, ...@@ -642,11 +852,16 @@ static int dw2102_load_firmware(struct usb_device *dev,
} }
/* init registers */ /* init registers */
switch (dev->descriptor.idProduct) { switch (dev->descriptor.idProduct) {
case USB_PID_TEVII_S650:
dw2104_properties.rc_key_map = tevii_rc_keys;
dw2104_properties.rc_key_map_size =
ARRAY_SIZE(tevii_rc_keys);
case USB_PID_DW2104: case USB_PID_DW2104:
case 0xd650:
reset = 1; reset = 1;
dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
DW210X_WRITE_MSG); DW210X_WRITE_MSG);
/* break omitted intentionally */
case USB_PID_DW3101:
reset = 0; reset = 0;
dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
DW210X_WRITE_MSG); DW210X_WRITE_MSG);
...@@ -690,6 +905,7 @@ static int dw2102_load_firmware(struct usb_device *dev, ...@@ -690,6 +905,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
DW210X_READ_MSG); DW210X_READ_MSG);
break; break;
} }
msleep(100); msleep(100);
kfree(p); kfree(p);
} }
...@@ -700,7 +916,6 @@ static struct dvb_usb_device_properties dw2102_properties = { ...@@ -700,7 +916,6 @@ static struct dvb_usb_device_properties dw2102_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER, .caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC, .usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-dw2102.fw", .firmware = "dvb-usb-dw2102.fw",
.size_of_priv = sizeof(struct dw210x_state),
.no_reconnect = 1, .no_reconnect = 1,
.i2c_algo = &dw2102_serit_i2c_algo, .i2c_algo = &dw2102_serit_i2c_algo,
...@@ -714,7 +929,7 @@ static struct dvb_usb_device_properties dw2102_properties = { ...@@ -714,7 +929,7 @@ static struct dvb_usb_device_properties dw2102_properties = {
.num_adapters = 1, .num_adapters = 1,
.download_firmware = dw2102_load_firmware, .download_firmware = dw2102_load_firmware,
.read_mac_address = dw210x_read_mac_address, .read_mac_address = dw210x_read_mac_address,
.adapter = { .adapter = {
{ {
.frontend_attach = dw2102_frontend_attach, .frontend_attach = dw2102_frontend_attach,
.streaming_ctrl = NULL, .streaming_ctrl = NULL,
...@@ -752,7 +967,6 @@ static struct dvb_usb_device_properties dw2104_properties = { ...@@ -752,7 +967,6 @@ static struct dvb_usb_device_properties dw2104_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER, .caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC, .usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-dw2104.fw", .firmware = "dvb-usb-dw2104.fw",
.size_of_priv = sizeof(struct dw210x_state),
.no_reconnect = 1, .no_reconnect = 1,
.i2c_algo = &dw2104_i2c_algo, .i2c_algo = &dw2104_i2c_algo,
...@@ -796,12 +1010,57 @@ static struct dvb_usb_device_properties dw2104_properties = { ...@@ -796,12 +1010,57 @@ static struct dvb_usb_device_properties dw2104_properties = {
} }
}; };
static struct dvb_usb_device_properties dw3101_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-dw3101.fw",
.no_reconnect = 1,
.i2c_algo = &dw3101_i2c_algo,
.rc_key_map = dw210x_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
.rc_interval = 150,
.rc_query = dw2102_rc_query,
.generic_bulk_ctrl_endpoint = 0x81,
/* parameter for the MPEG2-data transfer */
.num_adapters = 1,
.download_firmware = dw2102_load_firmware,
.read_mac_address = dw210x_read_mac_address,
.adapter = {
{
.frontend_attach = dw3101_frontend_attach,
.streaming_ctrl = NULL,
.tuner_attach = dw3101_tuner_attach,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
}
},
.num_device_descs = 1,
.devices = {
{ "DVBWorld DVB-C 3101 USB2.0",
{&dw2102_table[5], 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)
{ {
if (0 == dvb_usb_device_init(intf, &dw2102_properties, if (0 == dvb_usb_device_init(intf, &dw2102_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &dw2104_properties, 0 == dvb_usb_device_init(intf, &dw2104_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &dw3101_properties,
THIS_MODULE, NULL, adapter_nr)) { THIS_MODULE, NULL, adapter_nr)) {
return 0; return 0;
} }
...@@ -833,6 +1092,8 @@ module_init(dw2102_module_init); ...@@ -833,6 +1092,8 @@ module_init(dw2102_module_init);
module_exit(dw2102_module_exit); 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 USB2.0 device"); MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
" DVB-C 3101 USB2.0,"
" TeVii S600, S650 USB2.0 devices");
MODULE_VERSION("0.1"); MODULE_VERSION("0.1");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -5,4 +5,5 @@ ...@@ -5,4 +5,5 @@
#include "dvb-usb.h" #include "dvb-usb.h"
#define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args) #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args)
#define deb_rc(args...) dprintk(dvb_usb_dw2102_debug, 0x04, args)
#endif #endif
...@@ -223,7 +223,7 @@ static struct usb_device_id gp8psk_usb_table [] = { ...@@ -223,7 +223,7 @@ static struct usb_device_id gp8psk_usb_table [] = {
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) },
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) },
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) }, { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) },
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, /* { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */
{ 0 }, { 0 },
}; };
MODULE_DEVICE_TABLE(usb, gp8psk_usb_table); MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
...@@ -254,7 +254,7 @@ static struct dvb_usb_device_properties gp8psk_properties = { ...@@ -254,7 +254,7 @@ static struct dvb_usb_device_properties gp8psk_properties = {
.generic_bulk_ctrl_endpoint = 0x01, .generic_bulk_ctrl_endpoint = 0x01,
.num_device_descs = 4, .num_device_descs = 3,
.devices = { .devices = {
{ .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver", { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
.cold_ids = { &gp8psk_usb_table[0], NULL }, .cold_ids = { &gp8psk_usb_table[0], NULL },
...@@ -268,10 +268,6 @@ static struct dvb_usb_device_properties gp8psk_properties = { ...@@ -268,10 +268,6 @@ static struct dvb_usb_device_properties gp8psk_properties = {
.cold_ids = { NULL }, .cold_ids = { NULL },
.warm_ids = { &gp8psk_usb_table[3], NULL }, .warm_ids = { &gp8psk_usb_table[3], NULL },
}, },
{ .name = "Genpix SkyWalker-CW3K DVB-S receiver",
.cold_ids = { NULL },
.warm_ids = { &gp8psk_usb_table[4], NULL },
},
{ NULL }, { NULL },
} }
}; };
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include "firedtv.h" #include "firedtv.h"
/* fixed table with older keycodes, geared towards MythTV */ /* fixed table with older keycodes, geared towards MythTV */
const static u16 oldtable[] = { static const u16 oldtable[] = {
/* code from device: 0x4501...0x451f */ /* code from device: 0x4501...0x451f */
...@@ -62,7 +62,7 @@ const static u16 oldtable[] = { ...@@ -62,7 +62,7 @@ const static u16 oldtable[] = {
}; };
/* user-modifiable table for a remote as sold in 2008 */ /* user-modifiable table for a remote as sold in 2008 */
const static u16 keytable[] = { static const u16 keytable[] = {
/* code from device: 0x0300...0x031f */ /* code from device: 0x0300...0x031f */
......
...@@ -35,6 +35,21 @@ config DVB_STB6100 ...@@ -35,6 +35,21 @@ config DVB_STB6100
A Silicon tuner from ST used in conjunction with the STB0899 A Silicon tuner from ST used in conjunction with the STB0899
demodulator. Say Y when you want to support this tuner. demodulator. Say Y when you want to support this tuner.
config DVB_STV090x
tristate "STV0900/STV0903(A/B) based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators.
Say Y when you want to support these frontends.
config DVB_STV6110x
tristate "STV6110/(A) based tuners"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A Silicon tuner that supports DVB-S and DVB-S2 modes
comment "DVB-S (satellite) frontends" comment "DVB-S (satellite) frontends"
depends on DVB_CORE depends on DVB_CORE
...@@ -506,6 +521,13 @@ config DVB_ISL6421 ...@@ -506,6 +521,13 @@ config DVB_ISL6421
help help
An SEC control chip. An SEC control chip.
config DVB_ISL6423
tristate "ISL6423 SEC controller"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A SEC controller chip from Intersil
config DVB_LGS8GL5 config DVB_LGS8GL5
tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)" tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
depends on DVB_CORE && I2C depends on DVB_CORE && I2C
......
...@@ -71,4 +71,6 @@ obj-$(CONFIG_DVB_STB6000) += stb6000.o ...@@ -71,4 +71,6 @@ obj-$(CONFIG_DVB_STB6000) += stb6000.o
obj-$(CONFIG_DVB_S921) += s921.o obj-$(CONFIG_DVB_S921) += s921.o
obj-$(CONFIG_DVB_STV6110) += stv6110.o obj-$(CONFIG_DVB_STV6110) += stv6110.o
obj-$(CONFIG_DVB_STV0900) += stv0900.o obj-$(CONFIG_DVB_STV0900) += stv0900.o
obj-$(CONFIG_DVB_STV090x) += stv090x.o
obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
obj-$(CONFIG_DVB_ISL6423) += isl6423.o
...@@ -1455,7 +1455,7 @@ static int af9013_download_firmware(struct af9013_state *state) ...@@ -1455,7 +1455,7 @@ static int af9013_download_firmware(struct af9013_state *state)
af9013_ops.info.name); af9013_ops.info.name);
/* request the firmware, this will block and timeout */ /* request the firmware, this will block and timeout */
ret = request_firmware(&fw, fw_file, &state->i2c->dev); ret = request_firmware(&fw, fw_file, state->i2c->dev.parent);
if (ret) { if (ret) {
err("did not find the firmware file. (%s) " err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details" \ "Please see linux/Documentation/dvb/ for more details" \
......
...@@ -367,11 +367,90 @@ static struct { ...@@ -367,11 +367,90 @@ static struct {
{ 0x8231, 0x13 }, { 0x8231, 0x13 },
}; };
/* QAM Modulation table */ /* QAM64 Modulation table */
static struct { static struct {
u16 reg; u16 reg;
u16 data; u16 data;
} QAM_mod_tab[] = { } QAM64_mod_tab[] = {
{ 0x00a3, 0x09 },
{ 0x00a4, 0x00 },
{ 0x0081, 0xc4 },
{ 0x00a5, 0x40 },
{ 0x00aa, 0x77 },
{ 0x00ad, 0x77 },
{ 0x00a6, 0x67 },
{ 0x0262, 0x20 },
{ 0x021c, 0x30 },
{ 0x00b8, 0x3e },
{ 0x00b9, 0xf0 },
{ 0x00ba, 0x01 },
{ 0x00bb, 0x18 },
{ 0x00bc, 0x50 },
{ 0x00bd, 0x00 },
{ 0x00be, 0xea },
{ 0x00bf, 0xef },
{ 0x00c0, 0xfc },
{ 0x00c1, 0xbd },
{ 0x00c2, 0x1f },
{ 0x00c3, 0xfc },
{ 0x00c4, 0xdd },
{ 0x00c5, 0xaf },
{ 0x00c6, 0x00 },
{ 0x00c7, 0x38 },
{ 0x00c8, 0x30 },
{ 0x00c9, 0x05 },
{ 0x00ca, 0x4a },
{ 0x00cb, 0xd0 },
{ 0x00cc, 0x01 },
{ 0x00cd, 0xd9 },
{ 0x00ce, 0x6f },
{ 0x00cf, 0xf9 },
{ 0x00d0, 0x70 },
{ 0x00d1, 0xdf },
{ 0x00d2, 0xf7 },
{ 0x00d3, 0xc2 },
{ 0x00d4, 0xdf },
{ 0x00d5, 0x02 },
{ 0x00d6, 0x9a },
{ 0x00d7, 0xd0 },
{ 0x0250, 0x0d },
{ 0x0251, 0xcd },
{ 0x0252, 0xe0 },
{ 0x0253, 0x05 },
{ 0x0254, 0xa7 },
{ 0x0255, 0xff },
{ 0x0256, 0xed },
{ 0x0257, 0x5b },
{ 0x0258, 0xae },
{ 0x0259, 0xe6 },
{ 0x025a, 0x3d },
{ 0x025b, 0x0f },
{ 0x025c, 0x0d },
{ 0x025d, 0xea },
{ 0x025e, 0xf2 },
{ 0x025f, 0x51 },
{ 0x0260, 0xf5 },
{ 0x0261, 0x06 },
{ 0x021a, 0x00 },
{ 0x0546, 0x40 },
{ 0x0210, 0xc7 },
{ 0x0211, 0xaa },
{ 0x0212, 0xab },
{ 0x0213, 0x02 },
{ 0x0502, 0x00 },
{ 0x0121, 0x04 },
{ 0x0122, 0x04 },
{ 0x052e, 0x10 },
{ 0x00a4, 0xca },
{ 0x00a7, 0x40 },
{ 0x0526, 0x01 },
};
/* QAM256 Modulation table */
static struct {
u16 reg;
u16 data;
} QAM256_mod_tab[] = {
{ 0x80a3, 0x09 }, { 0x80a3, 0x09 },
{ 0x80a4, 0x00 }, { 0x80a4, 0x00 },
{ 0x8081, 0xc4 }, { 0x8081, 0xc4 },
...@@ -464,12 +543,19 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, ...@@ -464,12 +543,19 @@ static int au8522_enable_modulation(struct dvb_frontend *fe,
au8522_set_if(fe, state->config->vsb_if); au8522_set_if(fe, state->config->vsb_if);
break; break;
case QAM_64: case QAM_64:
dprintk("%s() QAM 64\n", __func__);
for (i = 0; i < ARRAY_SIZE(QAM64_mod_tab); i++)
au8522_writereg(state,
QAM64_mod_tab[i].reg,
QAM64_mod_tab[i].data);
au8522_set_if(fe, state->config->qam_if);
break;
case QAM_256: case QAM_256:
dprintk("%s() QAM 64/256\n", __func__); dprintk("%s() QAM 256\n", __func__);
for (i = 0; i < ARRAY_SIZE(QAM_mod_tab); i++) for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++)
au8522_writereg(state, au8522_writereg(state,
QAM_mod_tab[i].reg, QAM256_mod_tab[i].reg,
QAM_mod_tab[i].data); QAM256_mod_tab[i].data);
au8522_set_if(fe, state->config->qam_if); au8522_set_if(fe, state->config->qam_if);
break; break;
default: default:
......
...@@ -492,7 +492,7 @@ static int cx24116_firmware_ondemand(struct dvb_frontend *fe) ...@@ -492,7 +492,7 @@ static int cx24116_firmware_ondemand(struct dvb_frontend *fe)
printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
__func__, CX24116_DEFAULT_FIRMWARE); __func__, CX24116_DEFAULT_FIRMWARE);
ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
&state->i2c->dev); state->i2c->dev.parent);
printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
__func__); __func__);
if (ret) { if (ret) {
......
...@@ -123,10 +123,10 @@ static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix) ...@@ -123,10 +123,10 @@ static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix)
} }
memset(&fw[ix].data[0], 0, sizeof(fw[0].data)); memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
if (request_firmware(&fw[ix].file, fw[ix].name, &s->i2c->dev) != 0) { rc = request_firmware(&fw[ix].file, fw[ix].name, s->i2c->dev.parent);
if (rc != 0) {
printk(KERN_ERR "%s: Firmware \"%s\" not available\n", printk(KERN_ERR "%s: Firmware \"%s\" not available\n",
mod_name, fw[ix].name); mod_name, fw[ix].name);
rc = -ENOENT;
goto exit_err; goto exit_err;
} }
......
/*
Intersil ISL6423 SEC and LNB Power supply controller
Copyright (C) Manu Abraham <abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
#include "dvb_frontend.h"
#include "isl6423.h"
static unsigned int verbose;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "Set Verbosity level");
#define FE_ERROR 0
#define FE_NOTICE 1
#define FE_INFO 2
#define FE_DEBUG 3
#define FE_DEBUGREG 4
#define dprintk(__y, __z, format, arg...) do { \
if (__z) { \
if ((verbose > FE_ERROR) && (verbose > __y)) \
printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_NOTICE) && (verbose > __y)) \
printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_INFO) && (verbose > __y)) \
printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_DEBUG) && (verbose > __y)) \
printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
} else { \
if (verbose > __y) \
printk(format, ##arg); \
} \
} while (0)
struct isl6423_dev {
const struct isl6423_config *config;
struct i2c_adapter *i2c;
u8 reg_3;
u8 reg_4;
unsigned int verbose;
};
static int isl6423_write(struct isl6423_dev *isl6423, u8 reg)
{
struct i2c_adapter *i2c = isl6423->i2c;
u8 addr = isl6423->config->addr;
int err = 0;
struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = &reg, .len = 1 };
dprintk(FE_DEBUG, 1, "write reg %02X", reg);
err = i2c_transfer(i2c, &msg, 1);
if (err < 0)
goto exit;
return 0;
exit:
dprintk(FE_ERROR, 1, "I/O error <%d>", err);
return err;
}
static int isl6423_set_modulation(struct dvb_frontend *fe)
{
struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
const struct isl6423_config *config = isl6423->config;
int err = 0;
u8 reg_2 = 0;
reg_2 = 0x01 << 5;
if (config->mod_extern)
reg_2 |= (1 << 3);
else
reg_2 |= (1 << 4);
err = isl6423_write(isl6423, reg_2);
if (err < 0)
goto exit;
return 0;
exit:
dprintk(FE_ERROR, 1, "I/O error <%d>", err);
return err;
}
static int isl6423_voltage_boost(struct dvb_frontend *fe, long arg)
{
struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
u8 reg_3 = isl6423->reg_3;
u8 reg_4 = isl6423->reg_4;
int err = 0;
if (arg) {
/* EN = 1, VSPEN = 1, VBOT = 1 */
reg_4 |= (1 << 4);
reg_4 |= 0x1;
reg_3 |= (1 << 3);
} else {
/* EN = 1, VSPEN = 1, VBOT = 0 */
reg_4 |= (1 << 4);
reg_4 &= ~0x1;
reg_3 |= (1 << 3);
}
err = isl6423_write(isl6423, reg_3);
if (err < 0)
goto exit;
err = isl6423_write(isl6423, reg_4);
if (err < 0)
goto exit;
isl6423->reg_3 = reg_3;
isl6423->reg_4 = reg_4;
return 0;
exit:
dprintk(FE_ERROR, 1, "I/O error <%d>", err);
return err;
}
static int isl6423_set_voltage(struct dvb_frontend *fe,
enum fe_sec_voltage voltage)
{
struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
u8 reg_3 = isl6423->reg_3;
u8 reg_4 = isl6423->reg_4;
int err = 0;
switch (voltage) {
case SEC_VOLTAGE_OFF:
/* EN = 0 */
reg_4 &= ~(1 << 4);
break;
case SEC_VOLTAGE_13:
/* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */
reg_4 |= (1 << 4);
reg_4 &= ~0x3;
reg_3 |= (1 << 3);
break;
case SEC_VOLTAGE_18:
/* EN = 1, VSPEN = 1, VTOP = 1, VBOT = 0 */
reg_4 |= (1 << 4);
reg_4 |= 0x2;
reg_4 &= ~0x1;
reg_3 |= (1 << 3);
break;
default:
break;
}
err = isl6423_write(isl6423, reg_3);
if (err < 0)
goto exit;
err = isl6423_write(isl6423, reg_4);
if (err < 0)
goto exit;
isl6423->reg_3 = reg_3;
isl6423->reg_4 = reg_4;
return 0;
exit:
dprintk(FE_ERROR, 1, "I/O error <%d>", err);
return err;
}
static int isl6423_set_current(struct dvb_frontend *fe)
{
struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
u8 reg_3 = isl6423->reg_3;
const struct isl6423_config *config = isl6423->config;
int err = 0;
switch (config->current_max) {
case SEC_CURRENT_275m:
/* 275mA */
/* ISELH = 0, ISELL = 0 */
reg_3 &= ~0x3;
break;
case SEC_CURRENT_515m:
/* 515mA */
/* ISELH = 0, ISELL = 1 */
reg_3 &= ~0x2;
reg_3 |= 0x1;
break;
case SEC_CURRENT_635m:
/* 635mA */
/* ISELH = 1, ISELL = 0 */
reg_3 &= ~0x1;
reg_3 |= 0x2;
break;
case SEC_CURRENT_800m:
/* 800mA */
/* ISELH = 1, ISELL = 1 */
reg_3 |= 0x3;
break;
}
err = isl6423_write(isl6423, reg_3);
if (err < 0)
goto exit;
switch (config->curlim) {
case SEC_CURRENT_LIM_ON:
/* DCL = 0 */
reg_3 &= ~0x10;
break;
case SEC_CURRENT_LIM_OFF:
/* DCL = 1 */
reg_3 |= 0x10;
break;
}
err = isl6423_write(isl6423, reg_3);
if (err < 0)
goto exit;
isl6423->reg_3 = reg_3;
return 0;
exit:
dprintk(FE_ERROR, 1, "I/O error <%d>", err);
return err;
}
static void isl6423_release(struct dvb_frontend *fe)
{
isl6423_set_voltage(fe, SEC_VOLTAGE_OFF);
kfree(fe->sec_priv);
fe->sec_priv = NULL;
}
struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
const struct isl6423_config *config)
{
struct isl6423_dev *isl6423;
isl6423 = kzalloc(sizeof(struct isl6423_dev), GFP_KERNEL);
if (!isl6423)
return NULL;
isl6423->config = config;
isl6423->i2c = i2c;
fe->sec_priv = isl6423;
/* SR3H = 0, SR3M = 1, SR3L = 0 */
isl6423->reg_3 = 0x02 << 5;
/* SR4H = 0, SR4M = 1, SR4L = 1 */
isl6423->reg_4 = 0x03 << 5;
if (isl6423_set_current(fe))
goto exit;
if (isl6423_set_modulation(fe))
goto exit;
fe->ops.release_sec = isl6423_release;
fe->ops.set_voltage = isl6423_set_voltage;
fe->ops.enable_high_lnb_voltage = isl6423_voltage_boost;
isl6423->verbose = verbose;
return fe;
exit:
kfree(isl6423);
fe->sec_priv = NULL;
return NULL;
}
EXPORT_SYMBOL(isl6423_attach);
MODULE_DESCRIPTION("ISL6423 SEC");
MODULE_AUTHOR("Manu Abraham");
MODULE_LICENSE("GPL");
/*
Intersil ISL6423 SEC and LNB Power supply controller
Copyright (C) Manu Abraham <abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ISL_6423_H
#define __ISL_6423_H
#include <linux/dvb/frontend.h>
enum isl6423_current {
SEC_CURRENT_275m = 0,
SEC_CURRENT_515m,
SEC_CURRENT_635m,
SEC_CURRENT_800m,
};
enum isl6423_curlim {
SEC_CURRENT_LIM_ON = 1,
SEC_CURRENT_LIM_OFF
};
struct isl6423_config {
enum isl6423_current current_max;
enum isl6423_curlim curlim;
u8 addr;
u8 mod_extern;
};
#if defined(CONFIG_DVB_ISL6423) || (defined(CONFIG_DVB_ISL6423_MODULE) && defined(MODULE))
extern struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
const struct isl6423_config *config);
#else
static inline struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
const struct isl6423_config *config)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_ISL6423 */
#endif /* __ISL_6423_H */
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* *
*/ */
#include <asm/div64.h>
#include <linux/dvb/frontend.h> #include <linux/dvb/frontend.h>
#include "dvb_math.h" #include "dvb_math.h"
#include "lgdt3305.h" #include "lgdt3305.h"
...@@ -496,27 +497,15 @@ static int lgdt3305_set_if(struct lgdt3305_state *state, ...@@ -496,27 +497,15 @@ static int lgdt3305_set_if(struct lgdt3305_state *state,
nco = if_freq_khz / 10; nco = if_freq_khz / 10;
#define LGDT3305_64BIT_DIVISION_ENABLED 0
/* FIXME: 64bit division disabled to avoid linking error:
* WARNING: "__udivdi3" [lgdt3305.ko] undefined!
*/
switch (param->u.vsb.modulation) { switch (param->u.vsb.modulation) {
case VSB_8: case VSB_8:
#if LGDT3305_64BIT_DIVISION_ENABLED
nco <<= 24; nco <<= 24;
nco /= 625; do_div(nco, 625);
#else
nco *= ((1 << 24) / 625);
#endif
break; break;
case QAM_64: case QAM_64:
case QAM_256: case QAM_256:
#if LGDT3305_64BIT_DIVISION_ENABLED
nco <<= 28; nco <<= 28;
nco /= 625; do_div(nco, 625);
#else
nco *= ((1 << 28) / 625);
#endif
break; break;
default: default:
return -EINVAL; return -EINVAL;
......
...@@ -37,14 +37,14 @@ ...@@ -37,14 +37,14 @@
} while (0) } while (0)
static int debug; static int debug;
static int fake_signal_str; static int fake_signal_str = 1;
module_param(debug, int, 0644); module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
module_param(fake_signal_str, int, 0644); 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:off)."); "Signal strength calculation is slow.(default:on).");
/* LGS8GXX internal helper functions */ /* LGS8GXX internal helper functions */
...@@ -610,7 +610,7 @@ static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal) ...@@ -610,7 +610,7 @@ static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal)
else else
cat = 0; cat = 0;
*signal = cat; *signal = cat * 65535 / 5;
return 0; return 0;
} }
...@@ -630,8 +630,8 @@ static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) ...@@ -630,8 +630,8 @@ static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
if (fake_signal_str) { if (fake_signal_str) {
if ((t & 0xC0) == 0xC0) { if ((t & 0xC0) == 0xC0) {
dprintk("Fake signal strength as 50\n"); dprintk("Fake signal strength\n");
*signal = 0x32; *signal = 0x7FFF;
} else } else
*signal = 0; *signal = 0;
return 0; return 0;
......
...@@ -133,7 +133,7 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe, ...@@ -133,7 +133,7 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe,
/* override frontend ops */ /* override frontend ops */
fe->ops.set_voltage = lnbp21_set_voltage; fe->ops.set_voltage = lnbp21_set_voltage;
fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
printk(KERN_INFO "LNBx2x attached on addr=%x", lnbp21->i2c_addr); printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr);
return fe; return fe;
} }
......
...@@ -77,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg, ...@@ -77,7 +77,7 @@ static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
ret = i2c_transfer(state->i2c, msg, 2); ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) { if (ret != 2) {
printk(KERN_ERR "%s: ret == %d\n", __func__, ret); printk(KERN_DEBUG "%s: ret == %d\n", __func__, ret);
return -EREMOTEIO; return -EREMOTEIO;
} }
......
...@@ -879,7 +879,8 @@ static int nxt2002_init(struct dvb_frontend* fe) ...@@ -879,7 +879,8 @@ static int nxt2002_init(struct dvb_frontend* fe)
/* request the firmware, this will block until someone uploads it */ /* request the firmware, this will block until someone uploads it */
printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE); printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE);
ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE, &state->i2c->dev); ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE,
state->i2c->dev.parent);
printk("nxt2002: Waiting for firmware upload(2)...\n"); printk("nxt2002: Waiting for firmware upload(2)...\n");
if (ret) { if (ret) {
printk("nxt2002: No firmware uploaded (timeout or file not found?)\n"); printk("nxt2002: No firmware uploaded (timeout or file not found?)\n");
...@@ -943,7 +944,8 @@ static int nxt2004_init(struct dvb_frontend* fe) ...@@ -943,7 +944,8 @@ static int nxt2004_init(struct dvb_frontend* fe)
/* request the firmware, this will block until someone uploads it */ /* request the firmware, this will block until someone uploads it */
printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE); printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE);
ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE, &state->i2c->dev); ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE,
state->i2c->dev.parent);
printk("nxt2004: Waiting for firmware upload(2)...\n"); printk("nxt2004: Waiting for firmware upload(2)...\n");
if (ret) { if (ret) {
printk("nxt2004: No firmware uploaded (timeout or file not found?)\n"); printk("nxt2004: No firmware uploaded (timeout or file not found?)\n");
......
...@@ -340,7 +340,7 @@ static int or51132_set_parameters(struct dvb_frontend* fe, ...@@ -340,7 +340,7 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
} }
printk("or51132: Waiting for firmware upload(%s)...\n", printk("or51132: Waiting for firmware upload(%s)...\n",
fwname); fwname);
ret = request_firmware(&fw, fwname, &state->i2c->dev); ret = request_firmware(&fw, fwname, state->i2c->dev.parent);
if (ret) { if (ret) {
printk(KERN_WARNING "or51132: No firmware up" printk(KERN_WARNING "or51132: No firmware up"
"loaded(timeout or file not found?)\n"); "loaded(timeout or file not found?)\n");
......
...@@ -60,8 +60,6 @@ ...@@ -60,8 +60,6 @@
} \ } \
} while (0) } while (0)
#define dmd_choose(a, b) (demod = STV0900_DEMOD_2 ? b : a))
static int stvdebug; static int stvdebug;
#define dprintk(args...) \ #define dprintk(args...) \
......
此差异已折叠。
/*
STV0900/0903 Multistandard Broadcast Frontend driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
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 __STV090x_H
#define __STV090x_H
enum stv090x_demodulator {
STV090x_DEMODULATOR_0 = 1,
STV090x_DEMODULATOR_1
};
enum stv090x_device {
STV0903 = 0,
STV0900,
};
enum stv090x_mode {
STV090x_DUAL = 0,
STV090x_SINGLE
};
enum stv090x_tsmode {
STV090x_TSMODE_SERIAL_PUNCTURED = 1,
STV090x_TSMODE_SERIAL_CONTINUOUS,
STV090x_TSMODE_PARALLEL_PUNCTURED,
STV090x_TSMODE_DVBCI
};
enum stv090x_clkmode {
STV090x_CLK_INT = 0, /* Clk i/p = CLKI */
STV090x_CLK_EXT = 2 /* Clk i/p = XTALI */
};
enum stv090x_i2crpt {
STV090x_RPTLEVEL_256 = 0,
STV090x_RPTLEVEL_128 = 1,
STV090x_RPTLEVEL_64 = 2,
STV090x_RPTLEVEL_32 = 3,
STV090x_RPTLEVEL_16 = 4,
STV090x_RPTLEVEL_8 = 5,
STV090x_RPTLEVEL_4 = 6,
STV090x_RPTLEVEL_2 = 7,
};
struct stv090x_config {
enum stv090x_device device;
enum stv090x_mode demod_mode;
enum stv090x_clkmode clk_mode;
u32 xtal; /* default: 8000000 */
u8 address; /* default: 0x68 */
u32 ref_clk; /* default: 16000000 FIXME to tuner config */
u8 ts1_mode;
u8 ts2_mode;
enum stv090x_i2crpt repeater_level;
int (*tuner_init) (struct dvb_frontend *fe);
int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk);
int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
};
#if defined(CONFIG_DVB_STV090x) || (defined(CONFIG_DVB_STV090x_MODULE) && defined(MODULE))
extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
struct i2c_adapter *i2c,
enum stv090x_demodulator demod);
#else
static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
struct i2c_adapter *i2c,
enum stv090x_demodulator demod)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_STV090x */
#endif /* __STV090x_H */
/*
STV0900/0903 Multistandard Broadcast Frontend driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
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 __STV090x_PRIV_H
#define __STV090x_PRIV_H
#include "dvb_frontend.h"
#define FE_ERROR 0
#define FE_NOTICE 1
#define FE_INFO 2
#define FE_DEBUG 3
#define FE_DEBUGREG 4
#define dprintk(__y, __z, format, arg...) do { \
if (__z) { \
if ((verbose > FE_ERROR) && (verbose > __y)) \
printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_NOTICE) && (verbose > __y)) \
printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_INFO) && (verbose > __y)) \
printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_DEBUG) && (verbose > __y)) \
printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
} else { \
if (verbose > __y) \
printk(format, ##arg); \
} \
} while (0)
#define STV090x_READ_DEMOD(__state, __reg) (( \
(__state)->demod == STV090x_DEMODULATOR_1) ? \
stv090x_read_reg(__state, STV090x_P2_##__reg) : \
stv090x_read_reg(__state, STV090x_P1_##__reg))
#define STV090x_WRITE_DEMOD(__state, __reg, __data) (( \
(__state)->demod == STV090x_DEMODULATOR_1) ? \
stv090x_write_reg(__state, STV090x_P2_##__reg, __data) :\
stv090x_write_reg(__state, STV090x_P1_##__reg, __data))
#define STV090x_ADDR_OFFST(__state, __x) (( \
(__state->demod) == STV090x_DEMODULATOR_1) ? \
STV090x_P1_##__x : \
STV090x_P2_##__x)
#define STV090x_SETFIELD(mask, bitf, val) (mask = (mask & (~(((1 << STV090x_WIDTH_##bitf) - 1) <<\
STV090x_OFFST_##bitf))) | \
(val << STV090x_OFFST_##bitf))
#define STV090x_GETFIELD(val, bitf) ((val >> STV090x_OFFST_##bitf) & ((1 << STV090x_WIDTH_##bitf) - 1))
#define STV090x_SETFIELD_Px(mask, bitf, val) (mask = (mask & (~(((1 << STV090x_WIDTH_Px_##bitf) - 1) <<\
STV090x_OFFST_Px_##bitf))) | \
(val << STV090x_OFFST_Px_##bitf))
#define STV090x_GETFIELD_Px(val, bitf) ((val >> STV090x_OFFST_Px_##bitf) & ((1 << STV090x_WIDTH_Px_##bitf) - 1))
#define MAKEWORD16(__a, __b) (((__a) << 8) | (__b))
#define MSB(__x) ((__x >> 8) & 0xff)
#define LSB(__x) (__x & 0xff)
#define STV090x_IQPOWER_THRESHOLD 30
#define STV090x_SEARCH_AGC2_TH_CUT20 700
#define STV090x_SEARCH_AGC2_TH_CUT30 1200
#define STV090x_SEARCH_AGC2_TH(__ver) \
((__ver <= 0x20) ? \
STV090x_SEARCH_AGC2_TH_CUT20 : \
STV090x_SEARCH_AGC2_TH_CUT30)
enum stv090x_signal_state {
STV090x_NOCARRIER,
STV090x_NODATA,
STV090x_DATAOK,
STV090x_RANGEOK,
STV090x_OUTOFRANGE
};
enum stv090x_fec {
STV090x_PR12 = 0,
STV090x_PR23,
STV090x_PR34,
STV090x_PR45,
STV090x_PR56,
STV090x_PR67,
STV090x_PR78,
STV090x_PR89,
STV090x_PR910,
STV090x_PRERR
};
enum stv090x_modulation {
STV090x_QPSK,
STV090x_8PSK,
STV090x_16APSK,
STV090x_32APSK,
STV090x_UNKNOWN
};
enum stv090x_frame {
STV090x_LONG_FRAME,
STV090x_SHORT_FRAME
};
enum stv090x_pilot {
STV090x_PILOTS_OFF,
STV090x_PILOTS_ON
};
enum stv090x_rolloff {
STV090x_RO_35,
STV090x_RO_25,
STV090x_RO_20
};
enum stv090x_inversion {
STV090x_IQ_AUTO,
STV090x_IQ_NORMAL,
STV090x_IQ_SWAP
};
enum stv090x_modcod {
STV090x_DUMMY_PLF = 0,
STV090x_QPSK_14,
STV090x_QPSK_13,
STV090x_QPSK_25,
STV090x_QPSK_12,
STV090x_QPSK_35,
STV090x_QPSK_23,
STV090x_QPSK_34,
STV090x_QPSK_45,
STV090x_QPSK_56,
STV090x_QPSK_89,
STV090x_QPSK_910,
STV090x_8PSK_35,
STV090x_8PSK_23,
STV090x_8PSK_34,
STV090x_8PSK_56,
STV090x_8PSK_89,
STV090x_8PSK_910,
STV090x_16APSK_23,
STV090x_16APSK_34,
STV090x_16APSK_45,
STV090x_16APSK_56,
STV090x_16APSK_89,
STV090x_16APSK_910,
STV090x_32APSK_34,
STV090x_32APSK_45,
STV090x_32APSK_56,
STV090x_32APSK_89,
STV090x_32APSK_910,
STV090x_MODCODE_UNKNOWN
};
enum stv090x_search {
STV090x_SEARCH_DSS = 0,
STV090x_SEARCH_DVBS1,
STV090x_SEARCH_DVBS2,
STV090x_SEARCH_AUTO
};
enum stv090x_algo {
STV090x_BLIND_SEARCH,
STV090x_COLD_SEARCH,
STV090x_WARM_SEARCH
};
enum stv090x_delsys {
STV090x_ERROR = 0,
STV090x_DVBS1 = 1,
STV090x_DVBS2,
STV090x_DSS
};
struct stv090x_long_frame_crloop {
enum stv090x_modcod modcod;
u8 crl_pilots_on_2;
u8 crl_pilots_off_2;
u8 crl_pilots_on_5;
u8 crl_pilots_off_5;
u8 crl_pilots_on_10;
u8 crl_pilots_off_10;
u8 crl_pilots_on_20;
u8 crl_pilots_off_20;
u8 crl_pilots_on_30;
u8 crl_pilots_off_30;
};
struct stv090x_short_frame_crloop {
enum stv090x_modulation modulation;
u8 crl_2; /* SR < 3M */
u8 crl_5; /* 3 < SR <= 7M */
u8 crl_10; /* 7 < SR <= 15M */
u8 crl_20; /* 10 < SR <= 25M */
u8 crl_30; /* 10 < SR <= 45M */
};
struct stv090x_reg {
u16 addr;
u8 data;
};
struct stv090x_tab {
s32 real;
s32 read;
};
struct stv090x_state {
enum stv090x_device device;
enum stv090x_demodulator demod;
enum stv090x_mode demod_mode;
u32 dev_ver;
struct i2c_adapter *i2c;
const struct stv090x_config *config;
struct dvb_frontend frontend;
u32 *verbose; /* Cached module verbosity */
enum stv090x_delsys delsys;
enum stv090x_fec fec;
enum stv090x_modulation modulation;
enum stv090x_modcod modcod;
enum stv090x_search search_mode;
enum stv090x_frame frame_len;
enum stv090x_pilot pilots;
enum stv090x_rolloff rolloff;
enum stv090x_inversion inversion;
enum stv090x_algo algo;
u32 frequency;
u32 srate;
s32 mclk; /* Masterclock Divider factor */
s32 tuner_bw;
u32 tuner_refclk;
s32 search_range;
s32 DemodTimeout;
s32 FecTimeout;
};
#endif /* __STV090x_PRIV_H */
此差异已折叠。
/*
STV6110(A) Silicon tuner driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
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/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include "dvb_frontend.h"
#include "stv6110x_reg.h"
#include "stv6110x.h"
#include "stv6110x_priv.h"
static unsigned int verbose;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "Set Verbosity level");
static u8 stv6110x_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
{
int ret;
const struct stv6110x_config *config = stv6110x->config;
u8 b0[] = { reg };
u8 b1[] = { 0 };
struct i2c_msg msg[] = {
{ .addr = config->addr, .flags = 0, .buf = b0, .len = 1 },
{ .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }
};
ret = i2c_transfer(stv6110x->i2c, msg, 2);
if (ret != 2) {
dprintk(FE_ERROR, 1, "I/O Error");
return -EREMOTEIO;
}
*data = b1[0];
return 0;
}
static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
{
int ret;
const struct stv6110x_config *config = stv6110x->config;
u8 buf[] = { reg, data };
struct i2c_msg msg = { .addr = config->addr, .flags = 0, . buf = buf, .len = 2 };
ret = i2c_transfer(stv6110x->i2c, &msg, 1);
if (ret != 1) {
dprintk(FE_ERROR, 1, "I/O Error");
return -EREMOTEIO;
}
return 0;
}
static int stv6110x_init(struct dvb_frontend *fe)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
int ret;
u8 i;
for (i = 0; i < ARRAY_SIZE(stv6110x_regs); i++) {
ret = stv6110x_write_reg(stv6110x, i, stv6110x_regs[i]);
if (ret < 0) {
dprintk(FE_ERROR, 1, "Initialization failed");
return -1;
}
}
return 0;
}
static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
u32 rDiv, divider;
s32 pVal, pCalc, rDivOpt = 0;
u8 i;
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
if (frequency <= 1023000) {
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
pVal = 40;
} else if (frequency <= 1300000) {
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
pVal = 40;
} else if (frequency <= 2046000) {
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
pVal = 20;
} else {
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
pVal = 20;
}
for (rDiv = 0; rDiv <= 3; rDiv++) {
pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv);
if ((abs((s32)(pCalc - pVal))) < (abs((s32)(1000 - pVal))))
rDivOpt = rDiv;
}
divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz;
divider = (divider + 5) / 10;
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
/* VCO Auto calibration */
STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x_regs[STV6110x_TNG1]);
stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x_regs[STV6110x_TNG0]);
stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
for (i = 0; i < TRIALS; i++) {
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x_regs[STV6110x_STAT1]))
break;
msleep(1);
}
return 0;
}
static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x_regs[STV6110x_TNG1]);
stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x_regs[STV6110x_TNG0]);
*frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x_regs[STV6110x_TNG1]),
STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x_regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
*frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x_regs[STV6110x_TNG1]) +
STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x_regs[STV6110x_TNG1])));
*frequency >>= 2;
return 0;
}
static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
u32 halfbw;
u8 i;
halfbw = bandwidth >> 1;
if (halfbw > 36000000)
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
else if (halfbw < 5000000)
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
else
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
for (i = 0; i < TRIALS; i++) {
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x_regs[STV6110x_STAT1]))
break;
msleep(1);
}
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
return 0;
}
static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x_regs[STV6110x_CTRL3]);
*bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x_regs[STV6110x_CTRL3]) + 5) * 2000000;
return 0;
}
static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
/* setup divider */
switch (refclock) {
default:
case 1:
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
break;
case 2:
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
break;
case 4:
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
break;
case 8:
case 0:
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
break;
}
stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
return 0;
}
static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x_regs[STV6110x_CTRL2]);
*gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x_regs[STV6110x_CTRL2]);
return 0;
}
static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
return 0;
}
static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
int ret;
switch (mode) {
case TUNER_SLEEP:
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 0);
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 0);
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 0);
break;
case TUNER_WAKE:
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 1);
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 1);
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 1);
break;
}
ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
if (ret < 0) {
dprintk(FE_ERROR, 1, "I/O Error");
return -EIO;
}
return 0;
}
static int stv6110x_sleep(struct dvb_frontend *fe)
{
return stv6110x_set_mode(fe, TUNER_SLEEP);
}
static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x_regs[STV6110x_STAT1]))
*status = TUNER_PHASELOCKED;
else
*status = 0;
return 0;
}
static int stv6110x_release(struct dvb_frontend *fe)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
fe->tuner_priv = NULL;
kfree(stv6110x);
return 0;
}
static struct dvb_tuner_ops stv6110x_ops = {
.info = {
.name = "STV6110(A) Silicon Tuner",
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_step = 0,
},
.init = stv6110x_init,
.sleep = stv6110x_sleep,
.release = stv6110x_release
};
static struct stv6110x_devctl stv6110x_ctl = {
.tuner_init = stv6110x_init,
.tuner_set_mode = stv6110x_set_mode,
.tuner_set_frequency = stv6110x_set_frequency,
.tuner_get_frequency = stv6110x_get_frequency,
.tuner_set_bandwidth = stv6110x_set_bandwidth,
.tuner_get_bandwidth = stv6110x_get_bandwidth,
.tuner_set_bbgain = stv6110x_set_bbgain,
.tuner_get_bbgain = stv6110x_get_bbgain,
.tuner_set_refclk = stv6110x_set_refclock,
.tuner_get_status = stv6110x_get_status,
};
struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
const struct stv6110x_config *config,
struct i2c_adapter *i2c)
{
struct stv6110x_state *stv6110x;
stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
if (stv6110x == NULL)
goto error;
stv6110x->i2c = i2c;
stv6110x->config = config;
stv6110x->devctl = &stv6110x_ctl;
fe->tuner_priv = stv6110x;
fe->ops.tuner_ops = stv6110x_ops;
printk("%s: Attaching STV6110x \n", __func__);
return stv6110x->devctl;
error:
kfree(stv6110x);
return NULL;
}
EXPORT_SYMBOL(stv6110x_attach);
MODULE_AUTHOR("Manu Abraham");
MODULE_DESCRIPTION("STV6110x Silicon tuner");
MODULE_LICENSE("GPL");
/*
STV6110(A) Silicon tuner driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
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 __STV6110x_H
#define __STV6110x_H
struct stv6110x_config {
u8 addr;
u32 refclk;
};
enum tuner_mode {
TUNER_SLEEP = 1,
TUNER_WAKE,
};
enum tuner_status {
TUNER_PHASELOCKED = 1,
};
struct stv6110x_devctl {
int (*tuner_init) (struct dvb_frontend *fe);
int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk);
int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
};
#if defined(CONFIG_DVB_STV6110x) || (defined(CONFIG_DVB_STV6110x_MODULE) && defined(MODULE))
extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
const struct stv6110x_config *config,
struct i2c_adapter *i2c);
#else
static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
const struct stv6110x_config *config,
struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_STV6110x */
#endif /* __STV6110x_H */
/*
STV6110(A) Silicon tuner driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
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 __STV6110x_PRIV_H
#define __STV6110x_PRIV_H
#define FE_ERROR 0
#define FE_NOTICE 1
#define FE_INFO 2
#define FE_DEBUG 3
#define FE_DEBUGREG 4
#define dprintk(__y, __z, format, arg...) do { \
if (__z) { \
if ((verbose > FE_ERROR) && (verbose > __y)) \
printk(KERN_ERR "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_NOTICE) && (verbose > __y)) \
printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_INFO) && (verbose > __y)) \
printk(KERN_INFO "%s: " format "\n", __func__ , ##arg); \
else if ((verbose > FE_DEBUG) && (verbose > __y)) \
printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg); \
} else { \
if (verbose > __y) \
printk(format, ##arg); \
} \
} while (0)
#define STV6110x_SETFIELD(mask, bitf, val) \
(mask = (mask & (~(((1 << STV6110x_WIDTH_##bitf) - 1) << \
STV6110x_OFFST_##bitf))) | \
(val << STV6110x_OFFST_##bitf))
#define STV6110x_GETFIELD(bitf, val) \
((val >> STV6110x_OFFST_##bitf) & \
((1 << STV6110x_WIDTH_##bitf) - 1))
#define MAKEWORD16(a, b) (((a) << 8) | (b))
#define LSB(x) ((x & 0xff))
#define MSB(y) ((y >> 8) & 0xff)
#define TRIALS 10
#define R_DIV(__div) (1 << (__div + 1))
#define REFCLOCK_kHz (stv6110x->config->refclk / 1000)
#define REFCLOCK_MHz (stv6110x->config->refclk / 1000000)
struct stv6110x_state {
struct i2c_adapter *i2c;
const struct stv6110x_config *config;
struct stv6110x_devctl *devctl;
};
#endif /* __STV6110x_PRIV_H */
/*
STV6110(A) Silicon tuner driver
Copyright (C) Manu Abraham <abraham.manu@gmail.com>
Copyright (C) ST Microelectronics
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 __STV6110x_REG_H
#define __STV6110x_REG_H
#define STV6110x_CTRL1 0x00
#define STV6110x_OFFST_CTRL1_K 3
#define STV6110x_WIDTH_CTRL1_K 5
#define STV6110x_OFFST_CTRL1_LPT 2
#define STV6110x_WIDTH_CTRL1_LPT 1
#define STV6110x_OFFST_CTRL1_RX 1
#define STV6110x_WIDTH_CTRL1_RX 1
#define STV6110x_OFFST_CTRL1_SYN 0
#define STV6110x_WIDTH_CTRL1_SYN 1
#define STV6110x_CTRL2 0x01
#define STV6110x_OFFST_CTRL2_CO_DIV 6
#define STV6110x_WIDTH_CTRL2_CO_DIV 2
#define STV6110x_OFFST_CTRL2_RSVD 5
#define STV6110x_WIDTH_CTRL2_RSVD 1
#define STV6110x_OFFST_CTRL2_REFOUT_SEL 4
#define STV6110x_WIDTH_CTRL2_REFOUT_SEL 1
#define STV6110x_OFFST_CTRL2_BBGAIN 0
#define STV6110x_WIDTH_CTRL2_BBGAIN 4
#define STV6110x_TNG0 0x02
#define STV6110x_OFFST_TNG0_N_DIV_7_0 0
#define STV6110x_WIDTH_TNG0_N_DIV_7_0 8
#define STV6110x_TNG1 0x03
#define STV6110x_OFFST_TNG1_R_DIV 6
#define STV6110x_WIDTH_TNG1_R_DIV 2
#define STV6110x_OFFST_TNG1_PRESC32_ON 5
#define STV6110x_WIDTH_TNG1_PRESC32_ON 1
#define STV6110x_OFFST_TNG1_DIV4SEL 4
#define STV6110x_WIDTH_TNG1_DIV4SEL 1
#define STV6110x_OFFST_TNG1_N_DIV_11_8 0
#define STV6110x_WIDTH_TNG1_N_DIV_11_8 4
#define STV6110x_CTRL3 0x04
#define STV6110x_OFFST_CTRL3_DCLOOP_OFF 7
#define STV6110x_WIDTH_CTRL3_DCLOOP_OFF 1
#define STV6110x_OFFST_CTRL3_RCCLK_OFF 6
#define STV6110x_WIDTH_CTRL3_RCCLK_OFF 1
#define STV6110x_OFFST_CTRL3_ICP 5
#define STV6110x_WIDTH_CTRL3_ICP 1
#define STV6110x_OFFST_CTRL3_CF 0
#define STV6110x_WIDTH_CTRL3_CF 5
#define STV6110x_STAT1 0x05
#define STV6110x_OFFST_STAT1_CALVCO_STRT 2
#define STV6110x_WIDTH_STAT1_CALVCO_STRT 1
#define STV6110x_OFFST_STAT1_CALRC_STRT 1
#define STV6110x_WIDTH_STAT1_CALRC_STRT 1
#define STV6110x_OFFST_STAT1_LOCK 0
#define STV6110x_WIDTH_STAT1_LOCK 1
#define STV6110x_STAT2 0x06
#define STV6110x_STAT3 0x07
#endif /* __STV6110x_REG_H */
/* /*
NXP TDA10048HN DVB OFDM demodulator driver NXP TDA10048HN DVB OFDM demodulator driver
Copyright (C) 2008 Steven Toth <stoth@linuxtv.org> Copyright (C) 2009 Steven Toth <stoth@kernellabs.com>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -43,6 +43,25 @@ struct tda10048_config { ...@@ -43,6 +43,25 @@ struct tda10048_config {
#define TDA10048_INVERSION_OFF 0 #define TDA10048_INVERSION_OFF 0
#define TDA10048_INVERSION_ON 1 #define TDA10048_INVERSION_ON 1
u8 inversion; u8 inversion;
#define TDA10048_IF_3300 3300
#define TDA10048_IF_3500 3500
#define TDA10048_IF_3800 3800
#define TDA10048_IF_4000 4000
#define TDA10048_IF_4300 4300
#define TDA10048_IF_4500 4500
#define TDA10048_IF_4750 4750
#define TDA10048_IF_36130 36130
u16 dtv6_if_freq_khz;
u16 dtv7_if_freq_khz;
u16 dtv8_if_freq_khz;
#define TDA10048_CLK_4000 4000
#define TDA10048_CLK_16000 16000
u16 clk_freq_khz;
/* Disable I2C gate access */
u8 disable_gate_access;
}; };
#if defined(CONFIG_DVB_TDA10048) || \ #if defined(CONFIG_DVB_TDA10048) || \
......
sms1xxx-objs := smscoreapi.o sms-cards.o sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o
obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/****************************************************************
Siano Mobile Silicon, Inc.
MDTV receiver kernel modules.
Copyright (C) 2006-2009, Uri Shkolnik
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, see <http://www.gnu.org/licenses/>.
****************************************************************/
#ifndef __SMS_ENDIAN_H__
#define __SMS_ENDIAN_H__
#include <asm/byteorder.h>
extern void smsendian_handle_tx_message(void *buffer);
extern void smsendian_handle_rx_message(void *buffer);
extern void smsendian_handle_message_header(void *msg);
#endif /* __SMS_ENDIAN_H__ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -1089,7 +1089,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) ...@@ -1089,7 +1089,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
else { else {
int i, len = dc->x0-dc->color+1; int i, len = dc->x0-dc->color+1;
u8 __user *colors = (u8 __user *)dc->data; u8 __user *colors = (u8 __user *)dc->data;
u8 r, g, b, blend; u8 r, g = 0, b = 0, blend = 0;
ret = 0; ret = 0;
for (i = 0; i<len; i++) { for (i = 0; i<len; i++) {
if (get_user(r, colors + i * 4) || if (get_user(r, colors + i * 4) ||
......
...@@ -458,7 +458,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) ...@@ -458,7 +458,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index); dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
if (av7110->analog_tuner_flags) { if (av7110->analog_tuner_flags) {
if (i->index < 0 || i->index >= 4) if (i->index >= 4)
return -EINVAL; return -EINVAL;
} else { } else {
if (i->index != 0) if (i->index != 0)
......
...@@ -1413,7 +1413,7 @@ static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { ...@@ -1413,7 +1413,7 @@ static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{ {
dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index); dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
if (i->index < 0 || i->index >= KNC1_INPUTS) if (i->index >= KNC1_INPUTS)
return -EINVAL; return -EINVAL;
memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
return 0; return 0;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册