diff options
Diffstat (limited to 'drivers/media/dvb/dvb-usb')
-rw-r--r-- | drivers/media/dvb/dvb-usb/Kconfig | 42 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/Makefile | 10 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9005-remote.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9005-script.h | 2 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9005.c | 23 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9015.c | 1474 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9015.h | 524 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/anysee.c | 30 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/cinergyT2-core.c | 268 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/cinergyT2-fe.c | 351 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/cinergyT2.h | 95 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/cxusb.c | 504 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dib0700.h | 4 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dib0700_core.c | 115 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dib0700_devices.c | 195 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dtv5100.c | 240 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dtv5100.h | 51 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 29 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dw2102.c | 572 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dw2102.h | 1 |
20 files changed, 4404 insertions, 128 deletions
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index e84152b7576d..3c13bcfa6385 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -72,9 +72,11 @@ config DVB_USB_DIB0700 | |||
72 | select DVB_DIB7000P | 72 | select DVB_DIB7000P |
73 | select DVB_DIB7000M | 73 | select DVB_DIB7000M |
74 | select DVB_DIB3000MC | 74 | select DVB_DIB3000MC |
75 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | ||
75 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 76 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE |
76 | select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE | 77 | select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE |
77 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE | 78 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE |
79 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE | ||
78 | select DVB_TUNER_DIB0070 | 80 | select DVB_TUNER_DIB0070 |
79 | help | 81 | help |
80 | Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The | 82 | Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The |
@@ -108,6 +110,8 @@ config DVB_USB_CXUSB | |||
108 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | 110 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE |
109 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE | 111 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE |
110 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE | 112 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE |
113 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE | ||
114 | select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE | ||
111 | help | 115 | help |
112 | Say Y here to support the Conexant USB2.0 hybrid reference design. | 116 | Say Y here to support the Conexant USB2.0 hybrid reference design. |
113 | Currently, only DVB and ATSC modes are supported, analog mode | 117 | Currently, only DVB and ATSC modes are supported, analog mode |
@@ -245,12 +249,25 @@ config DVB_USB_AF9005_REMOTE | |||
245 | Afatech AF9005 based receiver. | 249 | Afatech AF9005 based receiver. |
246 | 250 | ||
247 | config DVB_USB_DW2102 | 251 | config DVB_USB_DW2102 |
248 | tristate "DvbWorld 2102 DVB-S USB2.0 receiver" | 252 | tristate "DvbWorld DVB-S/S2 USB2.0 support" |
249 | depends on DVB_USB | 253 | depends on DVB_USB |
250 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
251 | select DVB_PLL if !DVB_FE_CUSTOMISE | 254 | select DVB_PLL if !DVB_FE_CUSTOMISE |
255 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
256 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | ||
257 | select DVB_STB6000 if !DVB_FE_CUSTOMISE | ||
258 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | ||
259 | select DVB_SI21XX if !DVB_FE_CUSTOMISE | ||
252 | help | 260 | help |
253 | Say Y here to support the DvbWorld 2102 DVB-S USB2.0 receiver. | 261 | Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers |
262 | and the TeVii S650. | ||
263 | |||
264 | config DVB_USB_CINERGY_T2 | ||
265 | tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" | ||
266 | depends on DVB_USB | ||
267 | help | ||
268 | Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers | ||
269 | |||
270 | Say Y if you own such a device and want to use it. | ||
254 | 271 | ||
255 | config DVB_USB_ANYSEE | 272 | config DVB_USB_ANYSEE |
256 | tristate "Anysee DVB-T/C USB2.0 support" | 273 | tristate "Anysee DVB-T/C USB2.0 support" |
@@ -262,3 +279,22 @@ config DVB_USB_ANYSEE | |||
262 | help | 279 | help |
263 | Say Y here to support the Anysee E30, Anysee E30 Plus or | 280 | Say Y here to support the Anysee E30, Anysee E30 Plus or |
264 | Anysee E30 C Plus DVB USB2.0 receiver. | 281 | Anysee E30 C Plus DVB USB2.0 receiver. |
282 | |||
283 | config DVB_USB_DTV5100 | ||
284 | tristate "AME DTV-5100 USB2.0 DVB-T support" | ||
285 | depends on DVB_USB | ||
286 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | ||
287 | help | ||
288 | Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. | ||
289 | |||
290 | config DVB_USB_AF9015 | ||
291 | tristate "Afatech AF9015 DVB-T USB2.0 support" | ||
292 | depends on DVB_USB && EXPERIMENTAL | ||
293 | select DVB_AF9013 | ||
294 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
295 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | ||
296 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | ||
297 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE | ||
298 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE | ||
299 | help | ||
300 | Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver | ||
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index e206f1ea0027..3122b7cc2c23 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -67,6 +67,16 @@ obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o | |||
67 | dvb-usb-dw2102-objs = dw2102.o | 67 | dvb-usb-dw2102-objs = dw2102.o |
68 | obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o | 68 | obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o |
69 | 69 | ||
70 | dvb-usb-dtv5100-objs = dtv5100.o | ||
71 | obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o | ||
72 | |||
73 | dvb-usb-af9015-objs = af9015.o | ||
74 | obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o | ||
75 | |||
76 | dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o | ||
77 | obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o | ||
78 | |||
79 | |||
70 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | 80 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ |
71 | # due to tuner-xc3028 | 81 | # due to tuner-xc3028 |
72 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | 82 | EXTRA_CFLAGS += -Idrivers/media/common/tuners |
diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c index ff00c0e8f4a1..7c596f926764 100644 --- a/drivers/media/dvb/dvb-usb/af9005-remote.c +++ b/drivers/media/dvb/dvb-usb/af9005-remote.c | |||
@@ -25,7 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | #include "af9005.h" | 26 | #include "af9005.h" |
27 | /* debug */ | 27 | /* debug */ |
28 | int dvb_usb_af9005_remote_debug; | 28 | static int dvb_usb_af9005_remote_debug; |
29 | module_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644); | 29 | module_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644); |
30 | MODULE_PARM_DESC(debug, | 30 | MODULE_PARM_DESC(debug, |
31 | "enable (1) or disable (0) debug messages." | 31 | "enable (1) or disable (0) debug messages." |
diff --git a/drivers/media/dvb/dvb-usb/af9005-script.h b/drivers/media/dvb/dvb-usb/af9005-script.h index 6eeaae51b1ca..4d69045426dd 100644 --- a/drivers/media/dvb/dvb-usb/af9005-script.h +++ b/drivers/media/dvb/dvb-usb/af9005-script.h | |||
@@ -14,7 +14,7 @@ typedef struct { | |||
14 | u8 val; | 14 | u8 val; |
15 | } RegDesc; | 15 | } RegDesc; |
16 | 16 | ||
17 | RegDesc script[] = { | 17 | static RegDesc script[] = { |
18 | {0xa180, 0x0, 0x8, 0xa}, | 18 | {0xa180, 0x0, 0x8, 0xa}, |
19 | {0xa181, 0x0, 0x8, 0xd7}, | 19 | {0xa181, 0x0, 0x8, 0xd7}, |
20 | {0xa182, 0x0, 0x8, 0xa3}, | 20 | {0xa182, 0x0, 0x8, 0xa3}, |
diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c index cfe71feefcad..ca5a0a4d2a47 100644 --- a/drivers/media/dvb/dvb-usb/af9005.c +++ b/drivers/media/dvb/dvb-usb/af9005.c | |||
@@ -35,17 +35,17 @@ module_param_named(led, dvb_usb_af9005_led, bool, 0644); | |||
35 | MODULE_PARM_DESC(led, "enable led (default: 1)."); | 35 | MODULE_PARM_DESC(led, "enable led (default: 1)."); |
36 | 36 | ||
37 | /* eeprom dump */ | 37 | /* eeprom dump */ |
38 | int dvb_usb_af9005_dump_eeprom = 0; | 38 | static int dvb_usb_af9005_dump_eeprom; |
39 | module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0); | 39 | module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0); |
40 | MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom."); | 40 | MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom."); |
41 | 41 | ||
42 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 42 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
43 | 43 | ||
44 | /* remote control decoder */ | 44 | /* remote control decoder */ |
45 | int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event, | 45 | static int (*rc_decode) (struct dvb_usb_device *d, u8 *data, int len, |
46 | int *state); | 46 | u32 *event, int *state); |
47 | void *rc_keys; | 47 | static void *rc_keys; |
48 | int *rc_keys_size; | 48 | static int *rc_keys_size; |
49 | 49 | ||
50 | u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; | 50 | u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; |
51 | 51 | ||
@@ -54,8 +54,8 @@ struct af9005_device_state { | |||
54 | int led_state; | 54 | int led_state; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen, | 57 | static int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, |
58 | u8 * rbuf, u16 rlen, int delay_ms) | 58 | u8 *rbuf, u16 rlen, int delay_ms) |
59 | { | 59 | { |
60 | int actlen, ret = -ENOMEM; | 60 | int actlen, ret = -ENOMEM; |
61 | 61 | ||
@@ -98,12 +98,7 @@ int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen, | |||
98 | return ret; | 98 | return ret; |
99 | } | 99 | } |
100 | 100 | ||
101 | int af9005_usb_generic_write(struct dvb_usb_device *d, u8 * buf, u16 len) | 101 | static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, |
102 | { | ||
103 | return af9005_usb_generic_rw(d, buf, len, NULL, 0, 0); | ||
104 | } | ||
105 | |||
106 | int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, | ||
107 | int readwrite, int type, u8 * values, int len) | 102 | int readwrite, int type, u8 * values, int len) |
108 | { | 103 | { |
109 | struct af9005_device_state *st = d->priv; | 104 | struct af9005_device_state *st = d->priv; |
@@ -765,7 +760,7 @@ static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply) | |||
765 | return 0; | 760 | return 0; |
766 | } | 761 | } |
767 | 762 | ||
768 | int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw) | 763 | static int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw) |
769 | { | 764 | { |
770 | int i, packets, ret, act_len; | 765 | int i, packets, ret, act_len; |
771 | 766 | ||
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c new file mode 100644 index 000000000000..cb0829c038ce --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9015.c | |||
@@ -0,0 +1,1474 @@ | |||
1 | /* | ||
2 | * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver | ||
3 | * | ||
4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * Thanks to Afatech who kindly provided information. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include "af9015.h" | ||
25 | #include "af9013.h" | ||
26 | #include "mt2060.h" | ||
27 | #include "qt1010.h" | ||
28 | #include "tda18271.h" | ||
29 | #include "mxl5005s.h" | ||
30 | #if 0 | ||
31 | #include "mc44s80x.h" | ||
32 | #endif | ||
33 | |||
34 | int dvb_usb_af9015_debug; | ||
35 | module_param_named(debug, dvb_usb_af9015_debug, int, 0644); | ||
36 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
37 | int dvb_usb_af9015_remote; | ||
38 | module_param_named(remote, dvb_usb_af9015_remote, int, 0644); | ||
39 | MODULE_PARM_DESC(remote, "select remote"); | ||
40 | int dvb_usb_af9015_dual_mode; | ||
41 | module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644); | ||
42 | MODULE_PARM_DESC(dual_mode, "enable dual mode"); | ||
43 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
44 | |||
45 | static DEFINE_MUTEX(af9015_usb_mutex); | ||
46 | |||
47 | static struct af9015_config af9015_config; | ||
48 | static struct dvb_usb_device_properties af9015_properties[2]; | ||
49 | int af9015_properties_count = ARRAY_SIZE(af9015_properties); | ||
50 | |||
51 | static struct af9013_config af9015_af9013_config[] = { | ||
52 | { | ||
53 | .demod_address = AF9015_I2C_DEMOD, | ||
54 | .output_mode = AF9013_OUTPUT_MODE_USB, | ||
55 | .api_version = { 0, 1, 9, 0 }, | ||
56 | .gpio[0] = AF9013_GPIO_HI, | ||
57 | .gpio[3] = AF9013_GPIO_TUNER_ON, | ||
58 | |||
59 | }, { | ||
60 | .output_mode = AF9013_OUTPUT_MODE_SERIAL, | ||
61 | .api_version = { 0, 1, 9, 0 }, | ||
62 | .gpio[0] = AF9013_GPIO_TUNER_ON, | ||
63 | .gpio[1] = AF9013_GPIO_LO, | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) | ||
68 | { | ||
69 | int act_len, ret; | ||
70 | u8 buf[64]; | ||
71 | u8 write = 1; | ||
72 | u8 msg_len = 8; | ||
73 | static u8 seq; /* packet sequence number */ | ||
74 | |||
75 | if (mutex_lock_interruptible(&af9015_usb_mutex) < 0) | ||
76 | return -EAGAIN; | ||
77 | |||
78 | buf[0] = req->cmd; | ||
79 | buf[1] = seq++; | ||
80 | buf[2] = req->i2c_addr; | ||
81 | buf[3] = req->addr >> 8; | ||
82 | buf[4] = req->addr & 0xff; | ||
83 | buf[5] = req->mbox; | ||
84 | buf[6] = req->addr_len; | ||
85 | buf[7] = req->data_len; | ||
86 | |||
87 | switch (req->cmd) { | ||
88 | case GET_CONFIG: | ||
89 | case BOOT: | ||
90 | case READ_MEMORY: | ||
91 | case RECONNECT_USB: | ||
92 | case GET_IR_CODE: | ||
93 | write = 0; | ||
94 | break; | ||
95 | case READ_I2C: | ||
96 | write = 0; | ||
97 | buf[2] |= 0x01; /* set I2C direction */ | ||
98 | case WRITE_I2C: | ||
99 | buf[0] = READ_WRITE_I2C; | ||
100 | break; | ||
101 | case WRITE_MEMORY: | ||
102 | if (((req->addr & 0xff00) == 0xff00) || | ||
103 | ((req->addr & 0xae00) == 0xae00)) | ||
104 | buf[0] = WRITE_VIRTUAL_MEMORY; | ||
105 | case WRITE_VIRTUAL_MEMORY: | ||
106 | case COPY_FIRMWARE: | ||
107 | case DOWNLOAD_FIRMWARE: | ||
108 | break; | ||
109 | default: | ||
110 | err("unknown command:%d", req->cmd); | ||
111 | ret = -1; | ||
112 | goto error_unlock; | ||
113 | } | ||
114 | |||
115 | /* write requested */ | ||
116 | if (write) { | ||
117 | memcpy(&buf[8], req->data, req->data_len); | ||
118 | msg_len += req->data_len; | ||
119 | } | ||
120 | deb_xfer(">>> "); | ||
121 | debug_dump(buf, msg_len, deb_xfer); | ||
122 | |||
123 | /* send req */ | ||
124 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, | ||
125 | &act_len, AF9015_USB_TIMEOUT); | ||
126 | if (ret) | ||
127 | err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len); | ||
128 | else | ||
129 | if (act_len != msg_len) | ||
130 | ret = -1; /* all data is not send */ | ||
131 | if (ret) | ||
132 | goto error_unlock; | ||
133 | |||
134 | /* no ack for those packets */ | ||
135 | if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) | ||
136 | goto exit_unlock; | ||
137 | |||
138 | /* receive ack and data if read req */ | ||
139 | msg_len = 1 + 1 + req->data_len; /* seq + status + data len */ | ||
140 | ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, | ||
141 | &act_len, AF9015_USB_TIMEOUT); | ||
142 | if (ret) { | ||
143 | err("recv bulk message failed:%d", ret); | ||
144 | ret = -1; | ||
145 | goto error_unlock; | ||
146 | } | ||
147 | |||
148 | deb_xfer("<<< "); | ||
149 | debug_dump(buf, act_len, deb_xfer); | ||
150 | |||
151 | /* remote controller query status is 1 if remote code is not received */ | ||
152 | if (req->cmd == GET_IR_CODE && buf[1] == 1) { | ||
153 | buf[1] = 0; /* clear command "error" status */ | ||
154 | memset(&buf[2], 0, req->data_len); | ||
155 | buf[3] = 1; /* no remote code received mark */ | ||
156 | } | ||
157 | |||
158 | /* check status */ | ||
159 | if (buf[1]) { | ||
160 | err("command failed:%d", buf[1]); | ||
161 | ret = -1; | ||
162 | goto error_unlock; | ||
163 | } | ||
164 | |||
165 | /* read request, copy returned data to return buf */ | ||
166 | if (!write) | ||
167 | memcpy(req->data, &buf[2], req->data_len); | ||
168 | |||
169 | error_unlock: | ||
170 | exit_unlock: | ||
171 | mutex_unlock(&af9015_usb_mutex); | ||
172 | |||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) | ||
177 | { | ||
178 | return af9015_rw_udev(d->udev, req); | ||
179 | } | ||
180 | |||
181 | static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val, | ||
182 | u8 len) | ||
183 | { | ||
184 | struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, | ||
185 | val}; | ||
186 | return af9015_ctrl_msg(d, &req); | ||
187 | } | ||
188 | |||
189 | static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val) | ||
190 | { | ||
191 | return af9015_write_regs(d, addr, &val, 1); | ||
192 | } | ||
193 | |||
194 | static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val) | ||
195 | { | ||
196 | struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, 1, val}; | ||
197 | return af9015_ctrl_msg(d, &req); | ||
198 | } | ||
199 | |||
200 | static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, | ||
201 | u8 val) | ||
202 | { | ||
203 | struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val}; | ||
204 | |||
205 | if (addr == af9015_af9013_config[0].demod_address || | ||
206 | addr == af9015_af9013_config[1].demod_address) | ||
207 | req.addr_len = 3; | ||
208 | |||
209 | return af9015_ctrl_msg(d, &req); | ||
210 | } | ||
211 | |||
212 | static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, | ||
213 | u8 *val) | ||
214 | { | ||
215 | struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val}; | ||
216 | |||
217 | if (addr == af9015_af9013_config[0].demod_address || | ||
218 | addr == af9015_af9013_config[1].demod_address) | ||
219 | req.addr_len = 3; | ||
220 | |||
221 | return af9015_ctrl_msg(d, &req); | ||
222 | } | ||
223 | |||
224 | static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
225 | int num) | ||
226 | { | ||
227 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
228 | int ret = 0, i = 0; | ||
229 | u16 addr; | ||
230 | u8 mbox, addr_len; | ||
231 | struct req_t req; | ||
232 | |||
233 | /* TODO: implement bus lock | ||
234 | |||
235 | The bus lock is needed because there is two tuners both using same I2C-address. | ||
236 | Due to that the only way to select correct tuner is use demodulator I2C-gate. | ||
237 | |||
238 | ................................................ | ||
239 | . AF9015 includes integrated AF9013 demodulator. | ||
240 | . ____________ ____________ . ____________ | ||
241 | .| uC | | demod | . | tuner | | ||
242 | .|------------| |------------| . |------------| | ||
243 | .| AF9015 | | AF9013/5 | . | MXL5003 | | ||
244 | .| |--+----I2C-------|-----/ -----|-.-----I2C-------| | | ||
245 | .| | | | addr 0x38 | . | addr 0xc6 | | ||
246 | .|____________| | |____________| . |____________| | ||
247 | .................|.............................. | ||
248 | | ____________ ____________ | ||
249 | | | demod | | tuner | | ||
250 | | |------------| |------------| | ||
251 | | | AF9013 | | MXL5003 | | ||
252 | +----I2C-------|-----/ -----|-------I2C-------| | | ||
253 | | addr 0x3a | | addr 0xc6 | | ||
254 | |____________| |____________| | ||
255 | */ | ||
256 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
257 | return -EAGAIN; | ||
258 | |||
259 | while (i < num) { | ||
260 | if (msg[i].addr == af9015_af9013_config[0].demod_address || | ||
261 | msg[i].addr == af9015_af9013_config[1].demod_address) { | ||
262 | addr = msg[i].buf[0] << 8; | ||
263 | addr += msg[i].buf[1]; | ||
264 | mbox = msg[i].buf[2]; | ||
265 | addr_len = 3; | ||
266 | } else { | ||
267 | addr = msg[i].buf[0]; | ||
268 | addr_len = 1; | ||
269 | mbox = 0; | ||
270 | } | ||
271 | |||
272 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
273 | if (msg[i].addr == | ||
274 | af9015_af9013_config[0].demod_address) | ||
275 | req.cmd = READ_MEMORY; | ||
276 | else | ||
277 | req.cmd = READ_I2C; | ||
278 | req.i2c_addr = msg[i].addr; | ||
279 | req.addr = addr; | ||
280 | req.mbox = mbox; | ||
281 | req.addr_len = addr_len; | ||
282 | req.data_len = msg[i+1].len; | ||
283 | req.data = &msg[i+1].buf[0]; | ||
284 | ret = af9015_ctrl_msg(d, &req); | ||
285 | i += 2; | ||
286 | } else { | ||
287 | if (msg[i].addr == | ||
288 | af9015_af9013_config[0].demod_address) | ||
289 | req.cmd = WRITE_MEMORY; | ||
290 | else | ||
291 | req.cmd = WRITE_I2C; | ||
292 | req.i2c_addr = msg[i].addr; | ||
293 | req.addr = addr; | ||
294 | req.mbox = mbox; | ||
295 | req.addr_len = addr_len; | ||
296 | req.data_len = msg[i].len-addr_len; | ||
297 | req.data = &msg[i].buf[addr_len]; | ||
298 | ret = af9015_ctrl_msg(d, &req); | ||
299 | i += 1; | ||
300 | } | ||
301 | if (ret) | ||
302 | goto error; | ||
303 | |||
304 | } | ||
305 | ret = i; | ||
306 | |||
307 | error: | ||
308 | mutex_unlock(&d->i2c_mutex); | ||
309 | |||
310 | return ret; | ||
311 | } | ||
312 | |||
313 | static u32 af9015_i2c_func(struct i2c_adapter *adapter) | ||
314 | { | ||
315 | return I2C_FUNC_I2C; | ||
316 | } | ||
317 | |||
318 | static struct i2c_algorithm af9015_i2c_algo = { | ||
319 | .master_xfer = af9015_i2c_xfer, | ||
320 | .functionality = af9015_i2c_func, | ||
321 | }; | ||
322 | |||
323 | static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op) | ||
324 | { | ||
325 | int ret; | ||
326 | u8 val, mask = 0x01; | ||
327 | |||
328 | ret = af9015_read_reg(d, addr, &val); | ||
329 | if (ret) | ||
330 | return ret; | ||
331 | |||
332 | mask <<= bit; | ||
333 | if (op) { | ||
334 | /* set bit */ | ||
335 | val |= mask; | ||
336 | } else { | ||
337 | /* clear bit */ | ||
338 | mask ^= 0xff; | ||
339 | val &= mask; | ||
340 | } | ||
341 | |||
342 | return af9015_write_reg(d, addr, val); | ||
343 | } | ||
344 | |||
345 | static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) | ||
346 | { | ||
347 | return af9015_do_reg_bit(d, addr, bit, 1); | ||
348 | } | ||
349 | |||
350 | static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) | ||
351 | { | ||
352 | return af9015_do_reg_bit(d, addr, bit, 0); | ||
353 | } | ||
354 | |||
355 | static int af9015_init_endpoint(struct dvb_usb_device *d) | ||
356 | { | ||
357 | int ret; | ||
358 | u16 frame_size; | ||
359 | u8 packet_size; | ||
360 | deb_info("%s: USB speed:%d\n", __func__, d->udev->speed); | ||
361 | |||
362 | #define TS_PACKET_SIZE 188 | ||
363 | |||
364 | #define TS_USB20_PACKET_COUNT 348 | ||
365 | #define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT) | ||
366 | |||
367 | #define TS_USB11_PACKET_COUNT 21 | ||
368 | #define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT) | ||
369 | |||
370 | #define TS_USB20_MAX_PACKET_SIZE 512 | ||
371 | #define TS_USB11_MAX_PACKET_SIZE 64 | ||
372 | |||
373 | if (d->udev->speed == USB_SPEED_FULL) { | ||
374 | frame_size = TS_USB11_FRAME_SIZE/4; | ||
375 | packet_size = TS_USB11_MAX_PACKET_SIZE/4; | ||
376 | } else { | ||
377 | frame_size = TS_USB20_FRAME_SIZE/4; | ||
378 | packet_size = TS_USB20_MAX_PACKET_SIZE/4; | ||
379 | } | ||
380 | |||
381 | ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */ | ||
382 | if (ret) | ||
383 | goto error; | ||
384 | ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */ | ||
385 | if (ret) | ||
386 | goto error; | ||
387 | ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */ | ||
388 | if (ret) | ||
389 | goto error; | ||
390 | ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */ | ||
391 | if (ret) | ||
392 | goto error; | ||
393 | ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */ | ||
394 | if (ret) | ||
395 | goto error; | ||
396 | if (af9015_config.dual_mode) { | ||
397 | ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */ | ||
398 | if (ret) | ||
399 | goto error; | ||
400 | } | ||
401 | ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */ | ||
402 | if (ret) | ||
403 | goto error; | ||
404 | if (af9015_config.dual_mode) { | ||
405 | ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */ | ||
406 | if (ret) | ||
407 | goto error; | ||
408 | } | ||
409 | /* EP4 xfer length */ | ||
410 | ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff); | ||
411 | if (ret) | ||
412 | goto error; | ||
413 | ret = af9015_write_reg(d, 0xdd89, frame_size >> 8); | ||
414 | if (ret) | ||
415 | goto error; | ||
416 | /* EP5 xfer length */ | ||
417 | ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff); | ||
418 | if (ret) | ||
419 | goto error; | ||
420 | ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8); | ||
421 | if (ret) | ||
422 | goto error; | ||
423 | ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */ | ||
424 | if (ret) | ||
425 | goto error; | ||
426 | ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */ | ||
427 | if (ret) | ||
428 | goto error; | ||
429 | ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */ | ||
430 | if (ret) | ||
431 | goto error; | ||
432 | if (af9015_config.dual_mode) { | ||
433 | ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */ | ||
434 | if (ret) | ||
435 | goto error; | ||
436 | } | ||
437 | |||
438 | /* enable / disable mp2if2 */ | ||
439 | if (af9015_config.dual_mode) | ||
440 | ret = af9015_set_reg_bit(d, 0xd50b, 0); | ||
441 | else | ||
442 | ret = af9015_clear_reg_bit(d, 0xd50b, 0); | ||
443 | error: | ||
444 | if (ret) | ||
445 | err("endpoint init failed:%d", ret); | ||
446 | return ret; | ||
447 | } | ||
448 | |||
449 | static int af9015_copy_firmware(struct dvb_usb_device *d) | ||
450 | { | ||
451 | int ret; | ||
452 | u8 fw_params[4]; | ||
453 | u8 val, i; | ||
454 | struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params), | ||
455 | fw_params }; | ||
456 | deb_info("%s:\n", __func__); | ||
457 | |||
458 | fw_params[0] = af9015_config.firmware_size >> 8; | ||
459 | fw_params[1] = af9015_config.firmware_size & 0xff; | ||
460 | fw_params[2] = af9015_config.firmware_checksum >> 8; | ||
461 | fw_params[3] = af9015_config.firmware_checksum & 0xff; | ||
462 | |||
463 | /* wait 2nd demodulator ready */ | ||
464 | msleep(100); | ||
465 | |||
466 | ret = af9015_read_reg_i2c(d, 0x3a, 0x98be, &val); | ||
467 | if (ret) | ||
468 | goto error; | ||
469 | else | ||
470 | deb_info("%s: firmware status:%02x\n", __func__, val); | ||
471 | |||
472 | if (val == 0x0c) /* fw is running, no need for download */ | ||
473 | goto exit; | ||
474 | |||
475 | /* set I2C master clock to fast (to speed up firmware copy) */ | ||
476 | ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */ | ||
477 | if (ret) | ||
478 | goto error; | ||
479 | |||
480 | msleep(50); | ||
481 | |||
482 | /* copy firmware */ | ||
483 | ret = af9015_ctrl_msg(d, &req); | ||
484 | if (ret) | ||
485 | err("firmware copy cmd failed:%d", ret); | ||
486 | deb_info("%s: firmware copy done\n", __func__); | ||
487 | |||
488 | /* set I2C master clock back to normal */ | ||
489 | ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */ | ||
490 | if (ret) | ||
491 | goto error; | ||
492 | |||
493 | /* request boot firmware */ | ||
494 | ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].demod_address, | ||
495 | 0xe205, 1); | ||
496 | deb_info("%s: firmware boot cmd status:%d\n", __func__, ret); | ||
497 | if (ret) | ||
498 | goto error; | ||
499 | |||
500 | for (i = 0; i < 15; i++) { | ||
501 | msleep(100); | ||
502 | |||
503 | /* check firmware status */ | ||
504 | ret = af9015_read_reg_i2c(d, | ||
505 | af9015_af9013_config[1].demod_address, 0x98be, &val); | ||
506 | deb_info("%s: firmware status cmd status:%d fw status:%02x\n", | ||
507 | __func__, ret, val); | ||
508 | if (ret) | ||
509 | goto error; | ||
510 | |||
511 | if (val == 0x0c || val == 0x04) /* success or fail */ | ||
512 | break; | ||
513 | } | ||
514 | |||
515 | if (val == 0x04) { | ||
516 | err("firmware did not run"); | ||
517 | ret = -1; | ||
518 | } else if (val != 0x0c) { | ||
519 | err("firmware boot timeout"); | ||
520 | ret = -1; | ||
521 | } | ||
522 | |||
523 | error: | ||
524 | exit: | ||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | /* dump eeprom */ | ||
529 | static int af9015_eeprom_dump(struct dvb_usb_device *d) | ||
530 | { | ||
531 | char buf[52], buf2[4]; | ||
532 | u8 reg, val; | ||
533 | |||
534 | for (reg = 0; ; reg++) { | ||
535 | if (reg % 16 == 0) { | ||
536 | if (reg) | ||
537 | deb_info("%s\n", buf); | ||
538 | sprintf(buf, "%02x: ", reg); | ||
539 | } | ||
540 | if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0) | ||
541 | sprintf(buf2, "%02x ", val); | ||
542 | else | ||
543 | strcpy(buf2, "-- "); | ||
544 | strcat(buf, buf2); | ||
545 | if (reg == 0xff) | ||
546 | break; | ||
547 | } | ||
548 | deb_info("%s\n", buf); | ||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | int af9015_download_ir_table(struct dvb_usb_device *d) | ||
553 | { | ||
554 | int i, packets = 0, ret; | ||
555 | u16 addr = 0x9a56; /* ir-table start address */ | ||
556 | struct req_t req = {WRITE_MEMORY, 0, 0, 0, 0, 1, NULL}; | ||
557 | u8 *data = NULL; | ||
558 | deb_info("%s:\n", __func__); | ||
559 | |||
560 | data = af9015_config.ir_table; | ||
561 | packets = af9015_config.ir_table_size; | ||
562 | |||
563 | /* no remote */ | ||
564 | if (!packets) | ||
565 | goto exit; | ||
566 | |||
567 | /* load remote ir-table */ | ||
568 | for (i = 0; i < packets; i++) { | ||
569 | req.addr = addr + i; | ||
570 | req.data = &data[i]; | ||
571 | ret = af9015_ctrl_msg(d, &req); | ||
572 | if (ret) { | ||
573 | err("ir-table download failed at packet %d with " \ | ||
574 | "code %d", i, ret); | ||
575 | return ret; | ||
576 | } | ||
577 | } | ||
578 | |||
579 | exit: | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static int af9015_init(struct dvb_usb_device *d) | ||
584 | { | ||
585 | int ret; | ||
586 | deb_info("%s:\n", __func__); | ||
587 | |||
588 | ret = af9015_init_endpoint(d); | ||
589 | if (ret) | ||
590 | goto error; | ||
591 | |||
592 | ret = af9015_download_ir_table(d); | ||
593 | if (ret) | ||
594 | goto error; | ||
595 | |||
596 | error: | ||
597 | return ret; | ||
598 | } | ||
599 | |||
600 | static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
601 | { | ||
602 | int ret; | ||
603 | deb_info("%s: onoff:%d\n", __func__, onoff); | ||
604 | |||
605 | if (onoff) | ||
606 | ret = af9015_set_reg_bit(adap->dev, 0xd503, 0); | ||
607 | else | ||
608 | ret = af9015_clear_reg_bit(adap->dev, 0xd503, 0); | ||
609 | |||
610 | return ret; | ||
611 | } | ||
612 | |||
613 | static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | ||
614 | int onoff) | ||
615 | { | ||
616 | int ret; | ||
617 | u8 idx; | ||
618 | |||
619 | deb_info("%s: set pid filter, index %d, pid %x, onoff %d\n", | ||
620 | __func__, index, pid, onoff); | ||
621 | |||
622 | ret = af9015_write_reg(adap->dev, 0xd505, (pid & 0xff)); | ||
623 | if (ret) | ||
624 | goto error; | ||
625 | |||
626 | ret = af9015_write_reg(adap->dev, 0xd506, (pid >> 8)); | ||
627 | if (ret) | ||
628 | goto error; | ||
629 | |||
630 | idx = ((index & 0x1f) | (1 << 5)); | ||
631 | ret = af9015_write_reg(adap->dev, 0xd504, idx); | ||
632 | |||
633 | error: | ||
634 | return ret; | ||
635 | } | ||
636 | |||
637 | static int af9015_download_firmware(struct usb_device *udev, | ||
638 | const struct firmware *fw) | ||
639 | { | ||
640 | int i, len, packets, remainder, ret; | ||
641 | struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL}; | ||
642 | u16 addr = 0x5100; /* firmware start address */ | ||
643 | u16 checksum = 0; | ||
644 | |||
645 | deb_info("%s:\n", __func__); | ||
646 | |||
647 | /* calc checksum */ | ||
648 | for (i = 0; i < fw->size; i++) | ||
649 | checksum += fw->data[i]; | ||
650 | |||
651 | af9015_config.firmware_size = fw->size; | ||
652 | af9015_config.firmware_checksum = checksum; | ||
653 | |||
654 | #define FW_PACKET_MAX_DATA 55 | ||
655 | |||
656 | packets = fw->size / FW_PACKET_MAX_DATA; | ||
657 | remainder = fw->size % FW_PACKET_MAX_DATA; | ||
658 | len = FW_PACKET_MAX_DATA; | ||
659 | for (i = 0; i <= packets; i++) { | ||
660 | if (i == packets) /* set size of the last packet */ | ||
661 | len = remainder; | ||
662 | |||
663 | req.data_len = len; | ||
664 | req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA); | ||
665 | req.addr = addr; | ||
666 | addr += FW_PACKET_MAX_DATA; | ||
667 | |||
668 | ret = af9015_rw_udev(udev, &req); | ||
669 | if (ret) { | ||
670 | err("firmware download failed at packet %d with " \ | ||
671 | "code %d", i, ret); | ||
672 | goto error; | ||
673 | } | ||
674 | } | ||
675 | |||
676 | /* firmware loaded, request boot */ | ||
677 | req.cmd = BOOT; | ||
678 | ret = af9015_rw_udev(udev, &req); | ||
679 | if (ret) { | ||
680 | err("firmware boot failed:%d", ret); | ||
681 | goto error; | ||
682 | } | ||
683 | |||
684 | /* firmware is running, reconnect device in the usb bus */ | ||
685 | req.cmd = RECONNECT_USB; | ||
686 | ret = af9015_rw_udev(udev, &req); | ||
687 | if (ret) | ||
688 | err("reconnect failed: %d", ret); | ||
689 | |||
690 | error: | ||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | static int af9015_read_config(struct usb_device *udev) | ||
695 | { | ||
696 | int ret; | ||
697 | u8 val, i, offset = 0; | ||
698 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; | ||
699 | char manufacturer[10]; | ||
700 | |||
701 | /* IR remote controller */ | ||
702 | req.addr = AF9015_EEPROM_IR_MODE; | ||
703 | ret = af9015_rw_udev(udev, &req); | ||
704 | if (ret) | ||
705 | goto error; | ||
706 | deb_info("%s: IR mode:%d\n", __func__, val); | ||
707 | for (i = 0; i < af9015_properties_count; i++) { | ||
708 | if (val == AF9015_IR_MODE_DISABLED || val == 0x04) { | ||
709 | af9015_properties[i].rc_key_map = NULL; | ||
710 | af9015_properties[i].rc_key_map_size = 0; | ||
711 | } else if (dvb_usb_af9015_remote) { | ||
712 | /* load remote defined as module param */ | ||
713 | switch (dvb_usb_af9015_remote) { | ||
714 | case AF9015_REMOTE_A_LINK_DTU_M: | ||
715 | af9015_properties[i].rc_key_map = | ||
716 | af9015_rc_keys_a_link; | ||
717 | af9015_properties[i].rc_key_map_size = | ||
718 | ARRAY_SIZE(af9015_rc_keys_a_link); | ||
719 | af9015_config.ir_table = af9015_ir_table_a_link; | ||
720 | af9015_config.ir_table_size = | ||
721 | ARRAY_SIZE(af9015_ir_table_a_link); | ||
722 | break; | ||
723 | case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3: | ||
724 | af9015_properties[i].rc_key_map = | ||
725 | af9015_rc_keys_msi; | ||
726 | af9015_properties[i].rc_key_map_size = | ||
727 | ARRAY_SIZE(af9015_rc_keys_msi); | ||
728 | af9015_config.ir_table = af9015_ir_table_msi; | ||
729 | af9015_config.ir_table_size = | ||
730 | ARRAY_SIZE(af9015_ir_table_msi); | ||
731 | break; | ||
732 | case AF9015_REMOTE_MYGICTV_U718: | ||
733 | af9015_properties[i].rc_key_map = | ||
734 | af9015_rc_keys_mygictv; | ||
735 | af9015_properties[i].rc_key_map_size = | ||
736 | ARRAY_SIZE(af9015_rc_keys_mygictv); | ||
737 | af9015_config.ir_table = | ||
738 | af9015_ir_table_mygictv; | ||
739 | af9015_config.ir_table_size = | ||
740 | ARRAY_SIZE(af9015_ir_table_mygictv); | ||
741 | break; | ||
742 | } | ||
743 | } else { | ||
744 | switch (udev->descriptor.idVendor) { | ||
745 | case USB_VID_LEADTEK: | ||
746 | af9015_properties[i].rc_key_map = | ||
747 | af9015_rc_keys_leadtek; | ||
748 | af9015_properties[i].rc_key_map_size = | ||
749 | ARRAY_SIZE(af9015_rc_keys_leadtek); | ||
750 | af9015_config.ir_table = | ||
751 | af9015_ir_table_leadtek; | ||
752 | af9015_config.ir_table_size = | ||
753 | ARRAY_SIZE(af9015_ir_table_leadtek); | ||
754 | break; | ||
755 | case USB_VID_VISIONPLUS: | ||
756 | if (udev->descriptor.idProduct == | ||
757 | USB_PID_AZUREWAVE_AD_TU700) { | ||
758 | af9015_properties[i].rc_key_map = | ||
759 | af9015_rc_keys_twinhan; | ||
760 | af9015_properties[i].rc_key_map_size = | ||
761 | ARRAY_SIZE(af9015_rc_keys_twinhan); | ||
762 | af9015_config.ir_table = | ||
763 | af9015_ir_table_twinhan; | ||
764 | af9015_config.ir_table_size = | ||
765 | ARRAY_SIZE(af9015_ir_table_twinhan); | ||
766 | } | ||
767 | break; | ||
768 | case USB_VID_KWORLD_2: | ||
769 | /* TODO: use correct rc keys */ | ||
770 | af9015_properties[i].rc_key_map = | ||
771 | af9015_rc_keys_twinhan; | ||
772 | af9015_properties[i].rc_key_map_size = | ||
773 | ARRAY_SIZE(af9015_rc_keys_twinhan); | ||
774 | af9015_config.ir_table = af9015_ir_table_kworld; | ||
775 | af9015_config.ir_table_size = | ||
776 | ARRAY_SIZE(af9015_ir_table_kworld); | ||
777 | break; | ||
778 | /* Check USB manufacturer and product strings and try | ||
779 | to determine correct remote in case of chip vendor | ||
780 | reference IDs are used. */ | ||
781 | case USB_VID_AFATECH: | ||
782 | memset(manufacturer, 0, sizeof(manufacturer)); | ||
783 | usb_string(udev, udev->descriptor.iManufacturer, | ||
784 | manufacturer, sizeof(manufacturer)); | ||
785 | if (!strcmp("Geniatech", manufacturer)) { | ||
786 | /* iManufacturer 1 Geniatech | ||
787 | iProduct 2 AF9015 */ | ||
788 | af9015_properties[i].rc_key_map = | ||
789 | af9015_rc_keys_mygictv; | ||
790 | af9015_properties[i].rc_key_map_size = | ||
791 | ARRAY_SIZE(af9015_rc_keys_mygictv); | ||
792 | af9015_config.ir_table = | ||
793 | af9015_ir_table_mygictv; | ||
794 | af9015_config.ir_table_size = | ||
795 | ARRAY_SIZE(af9015_ir_table_mygictv); | ||
796 | } else if (!strcmp("MSI", manufacturer)) { | ||
797 | /* iManufacturer 1 MSI | ||
798 | iProduct 2 MSI K-VOX */ | ||
799 | af9015_properties[i].rc_key_map = | ||
800 | af9015_rc_keys_msi; | ||
801 | af9015_properties[i].rc_key_map_size = | ||
802 | ARRAY_SIZE(af9015_rc_keys_msi); | ||
803 | af9015_config.ir_table = | ||
804 | af9015_ir_table_msi; | ||
805 | af9015_config.ir_table_size = | ||
806 | ARRAY_SIZE(af9015_ir_table_msi); | ||
807 | } | ||
808 | break; | ||
809 | } | ||
810 | } | ||
811 | } | ||
812 | |||
813 | /* TS mode - one or two receivers */ | ||
814 | req.addr = AF9015_EEPROM_TS_MODE; | ||
815 | ret = af9015_rw_udev(udev, &req); | ||
816 | if (ret) | ||
817 | goto error; | ||
818 | af9015_config.dual_mode = val; | ||
819 | deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode); | ||
820 | /* disable dual mode by default because it is buggy */ | ||
821 | if (!dvb_usb_af9015_dual_mode) | ||
822 | af9015_config.dual_mode = 0; | ||
823 | |||
824 | /* set buffer size according to USB port speed */ | ||
825 | for (i = 0; i < af9015_properties_count; i++) { | ||
826 | /* USB1.1 set smaller buffersize and disable 2nd adapter */ | ||
827 | if (udev->speed == USB_SPEED_FULL) { | ||
828 | af9015_properties[i].adapter->stream.u.bulk.buffersize = | ||
829 | TS_USB11_MAX_PACKET_SIZE; | ||
830 | /* disable 2nd adapter because we don't have | ||
831 | PID-filters */ | ||
832 | af9015_config.dual_mode = 0; | ||
833 | } else { | ||
834 | af9015_properties[i].adapter->stream.u.bulk.buffersize = | ||
835 | TS_USB20_MAX_PACKET_SIZE; | ||
836 | } | ||
837 | } | ||
838 | |||
839 | if (af9015_config.dual_mode) { | ||
840 | /* read 2nd demodulator I2C address */ | ||
841 | req.addr = AF9015_EEPROM_DEMOD2_I2C; | ||
842 | ret = af9015_rw_udev(udev, &req); | ||
843 | if (ret) | ||
844 | goto error; | ||
845 | af9015_af9013_config[1].demod_address = val; | ||
846 | |||
847 | /* enable 2nd adapter */ | ||
848 | for (i = 0; i < af9015_properties_count; i++) | ||
849 | af9015_properties[i].num_adapters = 2; | ||
850 | |||
851 | } else { | ||
852 | /* disable 2nd adapter */ | ||
853 | for (i = 0; i < af9015_properties_count; i++) | ||
854 | af9015_properties[i].num_adapters = 1; | ||
855 | } | ||
856 | |||
857 | for (i = 0; i < af9015_properties[0].num_adapters; i++) { | ||
858 | if (i == 1) | ||
859 | offset = AF9015_EEPROM_OFFSET; | ||
860 | /* xtal */ | ||
861 | req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset; | ||
862 | ret = af9015_rw_udev(udev, &req); | ||
863 | if (ret) | ||
864 | goto error; | ||
865 | switch (val) { | ||
866 | case 0: | ||
867 | af9015_af9013_config[i].adc_clock = 28800; | ||
868 | break; | ||
869 | case 1: | ||
870 | af9015_af9013_config[i].adc_clock = 20480; | ||
871 | break; | ||
872 | case 2: | ||
873 | af9015_af9013_config[i].adc_clock = 28000; | ||
874 | break; | ||
875 | case 3: | ||
876 | af9015_af9013_config[i].adc_clock = 25000; | ||
877 | break; | ||
878 | }; | ||
879 | deb_info("%s: [%d] xtal:%d set adc_clock:%d\n", __func__, i, | ||
880 | val, af9015_af9013_config[i].adc_clock); | ||
881 | |||
882 | /* tuner IF */ | ||
883 | req.addr = AF9015_EEPROM_IF1H + offset; | ||
884 | ret = af9015_rw_udev(udev, &req); | ||
885 | if (ret) | ||
886 | goto error; | ||
887 | af9015_af9013_config[i].tuner_if = val << 8; | ||
888 | req.addr = AF9015_EEPROM_IF1L + offset; | ||
889 | ret = af9015_rw_udev(udev, &req); | ||
890 | if (ret) | ||
891 | goto error; | ||
892 | af9015_af9013_config[i].tuner_if += val; | ||
893 | deb_info("%s: [%d] IF1:%d\n", __func__, i, | ||
894 | af9015_af9013_config[0].tuner_if); | ||
895 | |||
896 | /* MT2060 IF1 */ | ||
897 | req.addr = AF9015_EEPROM_MT2060_IF1H + offset; | ||
898 | ret = af9015_rw_udev(udev, &req); | ||
899 | if (ret) | ||
900 | goto error; | ||
901 | af9015_config.mt2060_if1[i] = val << 8; | ||
902 | req.addr = AF9015_EEPROM_MT2060_IF1L + offset; | ||
903 | ret = af9015_rw_udev(udev, &req); | ||
904 | if (ret) | ||
905 | goto error; | ||
906 | af9015_config.mt2060_if1[i] += val; | ||
907 | deb_info("%s: [%d] MT2060 IF1:%d\n", __func__, i, | ||
908 | af9015_config.mt2060_if1[i]); | ||
909 | |||
910 | /* tuner */ | ||
911 | req.addr = AF9015_EEPROM_TUNER_ID1 + offset; | ||
912 | ret = af9015_rw_udev(udev, &req); | ||
913 | if (ret) | ||
914 | goto error; | ||
915 | switch (val) { | ||
916 | case AF9013_TUNER_ENV77H11D5: | ||
917 | case AF9013_TUNER_MT2060: | ||
918 | case AF9013_TUNER_MC44S803: | ||
919 | case AF9013_TUNER_QT1010: | ||
920 | case AF9013_TUNER_UNKNOWN: | ||
921 | case AF9013_TUNER_MT2060_2: | ||
922 | case AF9013_TUNER_TDA18271: | ||
923 | case AF9013_TUNER_QT1010A: | ||
924 | af9015_af9013_config[i].rf_spec_inv = 1; | ||
925 | break; | ||
926 | case AF9013_TUNER_MXL5003D: | ||
927 | case AF9013_TUNER_MXL5005D: | ||
928 | case AF9013_TUNER_MXL5005R: | ||
929 | af9015_af9013_config[i].rf_spec_inv = 0; | ||
930 | break; | ||
931 | default: | ||
932 | warn("tuner id:%d not supported, please report!", val); | ||
933 | return -ENODEV; | ||
934 | }; | ||
935 | |||
936 | af9015_af9013_config[i].tuner = val; | ||
937 | deb_info("%s: [%d] tuner id:%d\n", __func__, i, val); | ||
938 | } | ||
939 | |||
940 | error: | ||
941 | if (ret) | ||
942 | err("eeprom read failed:%d", ret); | ||
943 | |||
944 | return ret; | ||
945 | } | ||
946 | |||
947 | static int af9015_identify_state(struct usb_device *udev, | ||
948 | struct dvb_usb_device_properties *props, | ||
949 | struct dvb_usb_device_description **desc, | ||
950 | int *cold) | ||
951 | { | ||
952 | int ret; | ||
953 | u8 reply; | ||
954 | struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply}; | ||
955 | |||
956 | ret = af9015_rw_udev(udev, &req); | ||
957 | if (ret) | ||
958 | return ret; | ||
959 | |||
960 | deb_info("%s: reply:%02x\n", __func__, reply); | ||
961 | if (reply == 0x02) | ||
962 | *cold = 0; | ||
963 | else | ||
964 | *cold = 1; | ||
965 | |||
966 | return ret; | ||
967 | } | ||
968 | |||
969 | static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
970 | { | ||
971 | u8 buf[8]; | ||
972 | struct req_t req = {GET_IR_CODE, 0, 0, 0, 0, sizeof(buf), buf}; | ||
973 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | ||
974 | int i, ret; | ||
975 | |||
976 | memset(buf, 0, sizeof(buf)); | ||
977 | |||
978 | ret = af9015_ctrl_msg(d, &req); | ||
979 | if (ret) | ||
980 | return ret; | ||
981 | |||
982 | *event = 0; | ||
983 | *state = REMOTE_NO_KEY_PRESSED; | ||
984 | |||
985 | for (i = 0; i < d->props.rc_key_map_size; i++) { | ||
986 | if (!buf[1] && keymap[i].custom == buf[0] && | ||
987 | keymap[i].data == buf[2]) { | ||
988 | *event = keymap[i].event; | ||
989 | *state = REMOTE_KEY_PRESSED; | ||
990 | break; | ||
991 | } | ||
992 | } | ||
993 | if (!buf[1]) | ||
994 | deb_rc("%s: %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
995 | __func__, buf[0], buf[1], buf[2], buf[3], buf[4], | ||
996 | buf[5], buf[6], buf[7]); | ||
997 | |||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | /* init 2nd I2C adapter */ | ||
1002 | int af9015_i2c_init(struct dvb_usb_device *d) | ||
1003 | { | ||
1004 | int ret; | ||
1005 | struct af9015_state *state = d->priv; | ||
1006 | deb_info("%s:\n", __func__); | ||
1007 | |||
1008 | strncpy(state->i2c_adap.name, d->desc->name, | ||
1009 | sizeof(state->i2c_adap.name)); | ||
1010 | #ifdef I2C_ADAP_CLASS_TV_DIGITAL | ||
1011 | state->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL, | ||
1012 | #else | ||
1013 | state->i2c_adap.class = I2C_CLASS_TV_DIGITAL, | ||
1014 | #endif | ||
1015 | state->i2c_adap.algo = d->props.i2c_algo; | ||
1016 | state->i2c_adap.algo_data = NULL; | ||
1017 | state->i2c_adap.dev.parent = &d->udev->dev; | ||
1018 | |||
1019 | i2c_set_adapdata(&state->i2c_adap, d); | ||
1020 | |||
1021 | ret = i2c_add_adapter(&state->i2c_adap); | ||
1022 | if (ret < 0) | ||
1023 | err("could not add i2c adapter"); | ||
1024 | |||
1025 | return ret; | ||
1026 | } | ||
1027 | |||
1028 | static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) | ||
1029 | { | ||
1030 | int ret; | ||
1031 | struct af9015_state *state = adap->dev->priv; | ||
1032 | struct i2c_adapter *i2c_adap; | ||
1033 | |||
1034 | if (adap->id == 0) { | ||
1035 | /* select I2C adapter */ | ||
1036 | i2c_adap = &adap->dev->i2c_adap; | ||
1037 | |||
1038 | deb_info("%s: init I2C\n", __func__); | ||
1039 | ret = af9015_i2c_init(adap->dev); | ||
1040 | |||
1041 | /* dump eeprom (debug) */ | ||
1042 | ret = af9015_eeprom_dump(adap->dev); | ||
1043 | if (ret) | ||
1044 | return ret; | ||
1045 | } else { | ||
1046 | /* select I2C adapter */ | ||
1047 | i2c_adap = &state->i2c_adap; | ||
1048 | |||
1049 | /* copy firmware to 2nd demodulator */ | ||
1050 | if (af9015_config.dual_mode) { | ||
1051 | ret = af9015_copy_firmware(adap->dev); | ||
1052 | if (ret) { | ||
1053 | err("firmware copy to 2nd frontend " \ | ||
1054 | "failed, will disable it"); | ||
1055 | af9015_config.dual_mode = 0; | ||
1056 | return -ENODEV; | ||
1057 | } | ||
1058 | } else { | ||
1059 | return -ENODEV; | ||
1060 | } | ||
1061 | } | ||
1062 | |||
1063 | /* attach demodulator */ | ||
1064 | adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id], | ||
1065 | i2c_adap); | ||
1066 | |||
1067 | return adap->fe == NULL ? -ENODEV : 0; | ||
1068 | } | ||
1069 | |||
1070 | static struct mt2060_config af9015_mt2060_config = { | ||
1071 | .i2c_address = 0xc0, | ||
1072 | .clock_out = 0, | ||
1073 | }; | ||
1074 | |||
1075 | static struct qt1010_config af9015_qt1010_config = { | ||
1076 | .i2c_address = 0xc4, | ||
1077 | }; | ||
1078 | |||
1079 | static struct tda18271_config af9015_tda18271_config = { | ||
1080 | .gate = TDA18271_GATE_DIGITAL, | ||
1081 | .small_i2c = 1, | ||
1082 | }; | ||
1083 | |||
1084 | static struct mxl5005s_config af9015_mxl5003_config = { | ||
1085 | .i2c_address = 0xc6, | ||
1086 | .if_freq = IF_FREQ_4570000HZ, | ||
1087 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
1088 | .agc_mode = MXL_SINGLE_AGC, | ||
1089 | .tracking_filter = MXL_TF_DEFAULT, | ||
1090 | .rssi_enable = MXL_RSSI_ENABLE, | ||
1091 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
1092 | .div_out = MXL_DIV_OUT_4, | ||
1093 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
1094 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
1095 | .top = MXL5005S_TOP_25P2, | ||
1096 | .mod_mode = MXL_DIGITAL_MODE, | ||
1097 | .if_mode = MXL_ZERO_IF, | ||
1098 | .AgcMasterByte = 0x00, | ||
1099 | }; | ||
1100 | |||
1101 | static struct mxl5005s_config af9015_mxl5005_config = { | ||
1102 | .i2c_address = 0xc6, | ||
1103 | .if_freq = IF_FREQ_4570000HZ, | ||
1104 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
1105 | .agc_mode = MXL_SINGLE_AGC, | ||
1106 | .tracking_filter = MXL_TF_OFF, | ||
1107 | .rssi_enable = MXL_RSSI_ENABLE, | ||
1108 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
1109 | .div_out = MXL_DIV_OUT_4, | ||
1110 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
1111 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
1112 | .top = MXL5005S_TOP_25P2, | ||
1113 | .mod_mode = MXL_DIGITAL_MODE, | ||
1114 | .if_mode = MXL_ZERO_IF, | ||
1115 | .AgcMasterByte = 0x00, | ||
1116 | }; | ||
1117 | |||
1118 | static int af9015_tuner_attach(struct dvb_usb_adapter *adap) | ||
1119 | { | ||
1120 | struct af9015_state *state = adap->dev->priv; | ||
1121 | struct i2c_adapter *i2c_adap; | ||
1122 | int ret; | ||
1123 | deb_info("%s: \n", __func__); | ||
1124 | |||
1125 | /* select I2C adapter */ | ||
1126 | if (adap->id == 0) | ||
1127 | i2c_adap = &adap->dev->i2c_adap; | ||
1128 | else | ||
1129 | i2c_adap = &state->i2c_adap; | ||
1130 | |||
1131 | switch (af9015_af9013_config[adap->id].tuner) { | ||
1132 | case AF9013_TUNER_MT2060: | ||
1133 | case AF9013_TUNER_MT2060_2: | ||
1134 | ret = dvb_attach(mt2060_attach, adap->fe, i2c_adap, | ||
1135 | &af9015_mt2060_config, | ||
1136 | af9015_config.mt2060_if1[adap->id]) | ||
1137 | == NULL ? -ENODEV : 0; | ||
1138 | break; | ||
1139 | case AF9013_TUNER_QT1010: | ||
1140 | case AF9013_TUNER_QT1010A: | ||
1141 | ret = dvb_attach(qt1010_attach, adap->fe, i2c_adap, | ||
1142 | &af9015_qt1010_config) == NULL ? -ENODEV : 0; | ||
1143 | break; | ||
1144 | case AF9013_TUNER_TDA18271: | ||
1145 | ret = dvb_attach(tda18271_attach, adap->fe, 0xc0, i2c_adap, | ||
1146 | &af9015_tda18271_config) == NULL ? -ENODEV : 0; | ||
1147 | break; | ||
1148 | case AF9013_TUNER_MXL5003D: | ||
1149 | ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap, | ||
1150 | &af9015_mxl5003_config) == NULL ? -ENODEV : 0; | ||
1151 | break; | ||
1152 | case AF9013_TUNER_MXL5005D: | ||
1153 | case AF9013_TUNER_MXL5005R: | ||
1154 | ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap, | ||
1155 | &af9015_mxl5005_config) == NULL ? -ENODEV : 0; | ||
1156 | break; | ||
1157 | case AF9013_TUNER_ENV77H11D5: | ||
1158 | ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0, i2c_adap, | ||
1159 | DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; | ||
1160 | break; | ||
1161 | case AF9013_TUNER_MC44S803: | ||
1162 | #if 0 | ||
1163 | ret = dvb_attach(mc44s80x_attach, adap->fe, i2c_adap) | ||
1164 | == NULL ? -ENODEV : 0; | ||
1165 | #else | ||
1166 | ret = -ENODEV; | ||
1167 | info("Freescale MC44S803 tuner found but no driver for that" \ | ||
1168 | "tuner. Look at the Linuxtv.org for tuner driver" \ | ||
1169 | "status."); | ||
1170 | #endif | ||
1171 | break; | ||
1172 | case AF9013_TUNER_UNKNOWN: | ||
1173 | default: | ||
1174 | ret = -ENODEV; | ||
1175 | err("Unknown tuner id:%d", | ||
1176 | af9015_af9013_config[adap->id].tuner); | ||
1177 | } | ||
1178 | return ret; | ||
1179 | } | ||
1180 | |||
1181 | static struct usb_device_id af9015_usb_table[] = { | ||
1182 | /* 0 */{USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)}, | ||
1183 | {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)}, | ||
1184 | {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)}, | ||
1185 | {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)}, | ||
1186 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)}, | ||
1187 | /* 5 */{USB_DEVICE(USB_VID_VISIONPLUS, | ||
1188 | USB_PID_TINYTWIN)}, | ||
1189 | {USB_DEVICE(USB_VID_VISIONPLUS, | ||
1190 | USB_PID_AZUREWAVE_AD_TU700)}, | ||
1191 | {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)}, | ||
1192 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)}, | ||
1193 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)}, | ||
1194 | /* 10 */{USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)}, | ||
1195 | {USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)}, | ||
1196 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)}, | ||
1197 | {USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2)}, | ||
1198 | {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)}, | ||
1199 | /* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)}, | ||
1200 | {0}, | ||
1201 | }; | ||
1202 | MODULE_DEVICE_TABLE(usb, af9015_usb_table); | ||
1203 | |||
1204 | static struct dvb_usb_device_properties af9015_properties[] = { | ||
1205 | { | ||
1206 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
1207 | |||
1208 | .usb_ctrl = DEVICE_SPECIFIC, | ||
1209 | .download_firmware = af9015_download_firmware, | ||
1210 | .firmware = "dvb-usb-af9015.fw", | ||
1211 | |||
1212 | .size_of_priv = sizeof(struct af9015_state), \ | ||
1213 | |||
1214 | .num_adapters = 2, | ||
1215 | .adapter = { | ||
1216 | { | ||
1217 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
1218 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
1219 | |||
1220 | .pid_filter_count = 32, | ||
1221 | .pid_filter = af9015_pid_filter, | ||
1222 | .pid_filter_ctrl = af9015_pid_filter_ctrl, | ||
1223 | |||
1224 | .frontend_attach = | ||
1225 | af9015_af9013_frontend_attach, | ||
1226 | .tuner_attach = af9015_tuner_attach, | ||
1227 | .stream = { | ||
1228 | .type = USB_BULK, | ||
1229 | .count = 6, | ||
1230 | .endpoint = 0x84, | ||
1231 | }, | ||
1232 | }, | ||
1233 | { | ||
1234 | .frontend_attach = | ||
1235 | af9015_af9013_frontend_attach, | ||
1236 | .tuner_attach = af9015_tuner_attach, | ||
1237 | .stream = { | ||
1238 | .type = USB_BULK, | ||
1239 | .count = 6, | ||
1240 | .endpoint = 0x85, | ||
1241 | }, | ||
1242 | } | ||
1243 | }, | ||
1244 | |||
1245 | .identify_state = af9015_identify_state, | ||
1246 | |||
1247 | .rc_query = af9015_rc_query, | ||
1248 | .rc_interval = 150, | ||
1249 | |||
1250 | .i2c_algo = &af9015_i2c_algo, | ||
1251 | |||
1252 | .num_device_descs = 9, | ||
1253 | .devices = { | ||
1254 | { | ||
1255 | .name = "Afatech AF9015 DVB-T USB2.0 stick", | ||
1256 | .cold_ids = {&af9015_usb_table[0], | ||
1257 | &af9015_usb_table[1], NULL}, | ||
1258 | .warm_ids = {NULL}, | ||
1259 | }, | ||
1260 | { | ||
1261 | .name = "Leadtek WinFast DTV Dongle Gold", | ||
1262 | .cold_ids = {&af9015_usb_table[2], NULL}, | ||
1263 | .warm_ids = {NULL}, | ||
1264 | }, | ||
1265 | { | ||
1266 | .name = "Pinnacle PCTV 71e", | ||
1267 | .cold_ids = {&af9015_usb_table[3], NULL}, | ||
1268 | .warm_ids = {NULL}, | ||
1269 | }, | ||
1270 | { | ||
1271 | .name = "KWorld PlusTV Dual DVB-T Stick " \ | ||
1272 | "(DVB-T 399U)", | ||
1273 | .cold_ids = {&af9015_usb_table[4], NULL}, | ||
1274 | .warm_ids = {NULL}, | ||
1275 | }, | ||
1276 | { | ||
1277 | .name = "DigitalNow TinyTwin DVB-T Receiver", | ||
1278 | .cold_ids = {&af9015_usb_table[5], NULL}, | ||
1279 | .warm_ids = {NULL}, | ||
1280 | }, | ||
1281 | { | ||
1282 | .name = "TwinHan AzureWave AD-TU700(704J)", | ||
1283 | .cold_ids = {&af9015_usb_table[6], NULL}, | ||
1284 | .warm_ids = {NULL}, | ||
1285 | }, | ||
1286 | { | ||
1287 | .name = "TerraTec Cinergy T USB XE", | ||
1288 | .cold_ids = {&af9015_usb_table[7], NULL}, | ||
1289 | .warm_ids = {NULL}, | ||
1290 | }, | ||
1291 | { | ||
1292 | .name = "KWorld PlusTV Dual DVB-T PCI " \ | ||
1293 | "(DVB-T PC160-2T)", | ||
1294 | .cold_ids = {&af9015_usb_table[8], NULL}, | ||
1295 | .warm_ids = {NULL}, | ||
1296 | }, | ||
1297 | { | ||
1298 | .name = "AVerMedia AVerTV DVB-T Volar X", | ||
1299 | .cold_ids = {&af9015_usb_table[9], NULL}, | ||
1300 | .warm_ids = {NULL}, | ||
1301 | }, | ||
1302 | } | ||
1303 | }, { | ||
1304 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
1305 | |||
1306 | .usb_ctrl = DEVICE_SPECIFIC, | ||
1307 | .download_firmware = af9015_download_firmware, | ||
1308 | .firmware = "dvb-usb-af9015.fw", | ||
1309 | |||
1310 | .size_of_priv = sizeof(struct af9015_state), \ | ||
1311 | |||
1312 | .num_adapters = 2, | ||
1313 | .adapter = { | ||
1314 | { | ||
1315 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
1316 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
1317 | |||
1318 | .pid_filter_count = 32, | ||
1319 | .pid_filter = af9015_pid_filter, | ||
1320 | .pid_filter_ctrl = af9015_pid_filter_ctrl, | ||
1321 | |||
1322 | .frontend_attach = | ||
1323 | af9015_af9013_frontend_attach, | ||
1324 | .tuner_attach = af9015_tuner_attach, | ||
1325 | .stream = { | ||
1326 | .type = USB_BULK, | ||
1327 | .count = 6, | ||
1328 | .endpoint = 0x84, | ||
1329 | }, | ||
1330 | }, | ||
1331 | { | ||
1332 | .frontend_attach = | ||
1333 | af9015_af9013_frontend_attach, | ||
1334 | .tuner_attach = af9015_tuner_attach, | ||
1335 | .stream = { | ||
1336 | .type = USB_BULK, | ||
1337 | .count = 6, | ||
1338 | .endpoint = 0x85, | ||
1339 | }, | ||
1340 | } | ||
1341 | }, | ||
1342 | |||
1343 | .identify_state = af9015_identify_state, | ||
1344 | |||
1345 | .rc_query = af9015_rc_query, | ||
1346 | .rc_interval = 150, | ||
1347 | |||
1348 | .i2c_algo = &af9015_i2c_algo, | ||
1349 | |||
1350 | .num_device_descs = 6, | ||
1351 | .devices = { | ||
1352 | { | ||
1353 | .name = "Xtensions XD-380", | ||
1354 | .cold_ids = {&af9015_usb_table[10], NULL}, | ||
1355 | .warm_ids = {NULL}, | ||
1356 | }, | ||
1357 | { | ||
1358 | .name = "MSI DIGIVOX Duo", | ||
1359 | .cold_ids = {&af9015_usb_table[11], NULL}, | ||
1360 | .warm_ids = {NULL}, | ||
1361 | }, | ||
1362 | { | ||
1363 | .name = "Fujitsu-Siemens Slim Mobile USB DVB-T", | ||
1364 | .cold_ids = {&af9015_usb_table[12], NULL}, | ||
1365 | .warm_ids = {NULL}, | ||
1366 | }, | ||
1367 | { | ||
1368 | .name = "Telestar Starstick 2", | ||
1369 | .cold_ids = {&af9015_usb_table[13], NULL}, | ||
1370 | .warm_ids = {NULL}, | ||
1371 | }, | ||
1372 | { | ||
1373 | .name = "AVerMedia A309", | ||
1374 | .cold_ids = {&af9015_usb_table[14], NULL}, | ||
1375 | .warm_ids = {NULL}, | ||
1376 | }, | ||
1377 | { | ||
1378 | .name = "MSI Digi VOX mini III", | ||
1379 | .cold_ids = {&af9015_usb_table[15], NULL}, | ||
1380 | .warm_ids = {NULL}, | ||
1381 | }, | ||
1382 | } | ||
1383 | } | ||
1384 | }; | ||
1385 | |||
1386 | static int af9015_usb_probe(struct usb_interface *intf, | ||
1387 | const struct usb_device_id *id) | ||
1388 | { | ||
1389 | int ret = 0; | ||
1390 | struct dvb_usb_device *d = NULL; | ||
1391 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1392 | u8 i; | ||
1393 | |||
1394 | deb_info("%s: interface:%d\n", __func__, | ||
1395 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
1396 | |||
1397 | /* interface 0 is used by DVB-T receiver and | ||
1398 | interface 1 is for remote controller (HID) */ | ||
1399 | if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { | ||
1400 | ret = af9015_read_config(udev); | ||
1401 | if (ret) | ||
1402 | return ret; | ||
1403 | |||
1404 | for (i = 0; i < af9015_properties_count; i++) { | ||
1405 | ret = dvb_usb_device_init(intf, &af9015_properties[i], | ||
1406 | THIS_MODULE, &d, adapter_nr); | ||
1407 | if (!ret) | ||
1408 | break; | ||
1409 | if (ret != -ENODEV) | ||
1410 | return ret; | ||
1411 | } | ||
1412 | if (ret) | ||
1413 | return ret; | ||
1414 | |||
1415 | if (d) | ||
1416 | ret = af9015_init(d); | ||
1417 | } | ||
1418 | |||
1419 | return ret; | ||
1420 | } | ||
1421 | |||
1422 | void af9015_i2c_exit(struct dvb_usb_device *d) | ||
1423 | { | ||
1424 | struct af9015_state *state = d->priv; | ||
1425 | deb_info("%s: \n", __func__); | ||
1426 | |||
1427 | /* remove 2nd I2C adapter */ | ||
1428 | if (d->state & DVB_USB_STATE_I2C) | ||
1429 | i2c_del_adapter(&state->i2c_adap); | ||
1430 | } | ||
1431 | |||
1432 | static void af9015_usb_device_exit(struct usb_interface *intf) | ||
1433 | { | ||
1434 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
1435 | deb_info("%s: \n", __func__); | ||
1436 | |||
1437 | /* remove 2nd I2C adapter */ | ||
1438 | if (d != NULL && d->desc != NULL) | ||
1439 | af9015_i2c_exit(d); | ||
1440 | |||
1441 | dvb_usb_device_exit(intf); | ||
1442 | } | ||
1443 | |||
1444 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
1445 | static struct usb_driver af9015_usb_driver = { | ||
1446 | .name = "dvb_usb_af9015", | ||
1447 | .probe = af9015_usb_probe, | ||
1448 | .disconnect = af9015_usb_device_exit, | ||
1449 | .id_table = af9015_usb_table, | ||
1450 | }; | ||
1451 | |||
1452 | /* module stuff */ | ||
1453 | static int __init af9015_usb_module_init(void) | ||
1454 | { | ||
1455 | int ret; | ||
1456 | ret = usb_register(&af9015_usb_driver); | ||
1457 | if (ret) | ||
1458 | err("module init failed:%d", ret); | ||
1459 | |||
1460 | return ret; | ||
1461 | } | ||
1462 | |||
1463 | static void __exit af9015_usb_module_exit(void) | ||
1464 | { | ||
1465 | /* deregister this driver from the USB subsystem */ | ||
1466 | usb_deregister(&af9015_usb_driver); | ||
1467 | } | ||
1468 | |||
1469 | module_init(af9015_usb_module_init); | ||
1470 | module_exit(af9015_usb_module_exit); | ||
1471 | |||
1472 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
1473 | MODULE_DESCRIPTION("Driver for Afatech AF9015 DVB-T"); | ||
1474 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h new file mode 100644 index 000000000000..882e8a4b3681 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9015.h | |||
@@ -0,0 +1,524 @@ | |||
1 | /* | ||
2 | * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver | ||
3 | * | ||
4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * Thanks to Afatech who kindly provided information. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef _DVB_USB_AF9015_H_ | ||
25 | #define _DVB_USB_AF9015_H_ | ||
26 | |||
27 | #define DVB_USB_LOG_PREFIX "af9015" | ||
28 | #include "dvb-usb.h" | ||
29 | |||
30 | extern int dvb_usb_af9015_debug; | ||
31 | #define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args) | ||
32 | #define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args) | ||
33 | #define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args) | ||
34 | #define deb_reg(args...) dprintk(dvb_usb_af9015_debug, 0x08, args) | ||
35 | #define deb_i2c(args...) dprintk(dvb_usb_af9015_debug, 0x10, args) | ||
36 | #define deb_fw(args...) dprintk(dvb_usb_af9015_debug, 0x20, args) | ||
37 | |||
38 | #define AF9015_I2C_EEPROM 0xa0 | ||
39 | #define AF9015_I2C_DEMOD 0x38 | ||
40 | #define AF9015_USB_TIMEOUT 2000 | ||
41 | |||
42 | /* EEPROM locations */ | ||
43 | #define AF9015_EEPROM_IR_MODE 0x18 | ||
44 | #define AF9015_EEPROM_IR_REMOTE_TYPE 0x34 | ||
45 | #define AF9015_EEPROM_TS_MODE 0x31 | ||
46 | #define AF9015_EEPROM_DEMOD2_I2C 0x32 | ||
47 | |||
48 | #define AF9015_EEPROM_SAW_BW1 0x35 | ||
49 | #define AF9015_EEPROM_XTAL_TYPE1 0x36 | ||
50 | #define AF9015_EEPROM_SPEC_INV1 0x37 | ||
51 | #define AF9015_EEPROM_IF1L 0x38 | ||
52 | #define AF9015_EEPROM_IF1H 0x39 | ||
53 | #define AF9015_EEPROM_MT2060_IF1L 0x3a | ||
54 | #define AF9015_EEPROM_MT2060_IF1H 0x3b | ||
55 | #define AF9015_EEPROM_TUNER_ID1 0x3c | ||
56 | |||
57 | #define AF9015_EEPROM_SAW_BW2 0x45 | ||
58 | #define AF9015_EEPROM_XTAL_TYPE2 0x46 | ||
59 | #define AF9015_EEPROM_SPEC_INV2 0x47 | ||
60 | #define AF9015_EEPROM_IF2L 0x48 | ||
61 | #define AF9015_EEPROM_IF2H 0x49 | ||
62 | #define AF9015_EEPROM_MT2060_IF2L 0x4a | ||
63 | #define AF9015_EEPROM_MT2060_IF2H 0x4b | ||
64 | #define AF9015_EEPROM_TUNER_ID2 0x4c | ||
65 | |||
66 | #define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1) | ||
67 | |||
68 | #define AF9015_GPIO_ON (1 << 0) | ||
69 | #define AF9015_GPIO_EN (1 << 1) | ||
70 | #define AF9015_GPIO_O (1 << 2) | ||
71 | #define AF9015_GPIO_I (1 << 3) | ||
72 | |||
73 | #define AF9015_GPIO_TUNER_ON (AF9015_GPIO_ON|AF9015_GPIO_EN) | ||
74 | #define AF9015_GPIO_TUNER_OFF (AF9015_GPIO_ON|AF9015_GPIO_EN|AF9015_GPIO_O) | ||
75 | |||
76 | struct req_t { | ||
77 | u8 cmd; /* [0] */ | ||
78 | /* seq */ /* [1] */ | ||
79 | u8 i2c_addr; /* [2] */ | ||
80 | u16 addr; /* [3|4] */ | ||
81 | u8 mbox; /* [5] */ | ||
82 | u8 addr_len; /* [6] */ | ||
83 | u8 data_len; /* [7] */ | ||
84 | u8 *data; | ||
85 | }; | ||
86 | |||
87 | enum af9015_cmd { | ||
88 | GET_CONFIG = 0x10, | ||
89 | DOWNLOAD_FIRMWARE = 0x11, | ||
90 | BOOT = 0x13, | ||
91 | READ_MEMORY = 0x20, | ||
92 | WRITE_MEMORY = 0x21, | ||
93 | READ_WRITE_I2C = 0x22, | ||
94 | COPY_FIRMWARE = 0x23, | ||
95 | RECONNECT_USB = 0x5a, | ||
96 | WRITE_VIRTUAL_MEMORY = 0x26, | ||
97 | GET_IR_CODE = 0x27, | ||
98 | READ_I2C, | ||
99 | WRITE_I2C, | ||
100 | }; | ||
101 | |||
102 | enum af9015_ir_mode { | ||
103 | AF9015_IR_MODE_DISABLED = 0, | ||
104 | AF9015_IR_MODE_HID, | ||
105 | AF9015_IR_MODE_RLC, | ||
106 | AF9015_IR_MODE_RC6, | ||
107 | }; | ||
108 | |||
109 | struct af9015_state { | ||
110 | struct i2c_adapter i2c_adap; /* I2C adapter for 2nd FE */ | ||
111 | }; | ||
112 | |||
113 | struct af9015_config { | ||
114 | u8 dual_mode:1; | ||
115 | u16 mt2060_if1[2]; | ||
116 | u16 firmware_size; | ||
117 | u16 firmware_checksum; | ||
118 | u8 *ir_table; | ||
119 | u16 ir_table_size; | ||
120 | }; | ||
121 | |||
122 | enum af9015_remote { | ||
123 | AF9015_REMOTE_NONE = 0, | ||
124 | AF9015_REMOTE_A_LINK_DTU_M, | ||
125 | AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, | ||
126 | AF9015_REMOTE_MYGICTV_U718, | ||
127 | }; | ||
128 | |||
129 | /* Leadtek WinFast DTV Dongle Gold */ | ||
130 | static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = { | ||
131 | { 0x00, 0x1e, KEY_1 }, | ||
132 | { 0x00, 0x1f, KEY_2 }, | ||
133 | { 0x00, 0x20, KEY_3 }, | ||
134 | { 0x00, 0x21, KEY_4 }, | ||
135 | { 0x00, 0x22, KEY_5 }, | ||
136 | { 0x00, 0x23, KEY_6 }, | ||
137 | { 0x00, 0x24, KEY_7 }, | ||
138 | { 0x00, 0x25, KEY_8 }, | ||
139 | { 0x00, 0x26, KEY_9 }, | ||
140 | { 0x00, 0x27, KEY_0 }, | ||
141 | { 0x00, 0x28, KEY_ENTER }, | ||
142 | { 0x00, 0x4f, KEY_VOLUMEUP }, | ||
143 | { 0x00, 0x50, KEY_VOLUMEDOWN }, | ||
144 | { 0x00, 0x51, KEY_CHANNELDOWN }, | ||
145 | { 0x00, 0x52, KEY_CHANNELUP }, | ||
146 | }; | ||
147 | |||
148 | static u8 af9015_ir_table_leadtek[] = { | ||
149 | 0x03, 0xfc, 0x00, 0xff, 0x1a, 0x01, 0x00, | ||
150 | 0x03, 0xfc, 0x56, 0xa9, 0x00, 0x00, 0x00, | ||
151 | 0x03, 0xfc, 0x4b, 0xb4, 0x00, 0x00, 0x00, | ||
152 | 0x03, 0xfc, 0x4c, 0xb3, 0xb2, 0x04, 0x00, | ||
153 | 0x03, 0xfc, 0x4d, 0xb2, 0x00, 0x00, 0x00, | ||
154 | 0x03, 0xfc, 0x4e, 0xb1, 0x00, 0x00, 0x00, | ||
155 | 0x03, 0xfc, 0x1f, 0xe0, 0x3d, 0x00, 0x00, | ||
156 | 0x03, 0xfc, 0x40, 0xbf, 0x13, 0x01, 0x00, | ||
157 | 0x03, 0xfc, 0x14, 0xeb, 0x10, 0x00, 0x00, | ||
158 | 0x03, 0xfc, 0x49, 0xb6, 0x05, 0x01, 0x00, | ||
159 | 0x03, 0xfc, 0x50, 0xaf, 0x29, 0x00, 0x00, | ||
160 | 0x03, 0xfc, 0x0c, 0xf3, 0x52, 0x00, 0x00, | ||
161 | 0x03, 0xfc, 0x03, 0xfc, 0x09, 0x00, 0x00, | ||
162 | 0x03, 0xfc, 0x08, 0xf7, 0x50, 0x00, 0x00, | ||
163 | 0x03, 0xfc, 0x13, 0xec, 0x28, 0x00, 0x00, | ||
164 | 0x03, 0xfc, 0x04, 0xfb, 0x4f, 0x00, 0x00, | ||
165 | 0x03, 0xfc, 0x4f, 0xb0, 0x0f, 0x01, 0x00, | ||
166 | 0x03, 0xfc, 0x10, 0xef, 0x51, 0x00, 0x00, | ||
167 | 0x03, 0xfc, 0x51, 0xae, 0x3f, 0x00, 0x00, | ||
168 | 0x03, 0xfc, 0x42, 0xbd, 0x13, 0x00, 0x00, | ||
169 | 0x03, 0xfc, 0x43, 0xbc, 0x00, 0x00, 0x00, | ||
170 | 0x03, 0xfc, 0x44, 0xbb, 0x11, 0x00, 0x00, | ||
171 | 0x03, 0xfc, 0x52, 0xad, 0x19, 0x00, 0x00, | ||
172 | 0x03, 0xfc, 0x54, 0xab, 0x05, 0x00, 0x00, | ||
173 | 0x03, 0xfc, 0x46, 0xb9, 0x29, 0x00, 0x00, | ||
174 | 0x03, 0xfc, 0x55, 0xaa, 0x2b, 0x00, 0x00, | ||
175 | 0x03, 0xfc, 0x53, 0xac, 0x41, 0x00, 0x00, | ||
176 | 0x03, 0xfc, 0x05, 0xfa, 0x1e, 0x00, 0x00, | ||
177 | 0x03, 0xfc, 0x06, 0xf9, 0x1f, 0x00, 0x00, | ||
178 | 0x03, 0xfc, 0x07, 0xf8, 0x20, 0x00, 0x00, | ||
179 | 0x03, 0xfc, 0x1e, 0xe1, 0x19, 0x00, 0x00, | ||
180 | 0x03, 0xfc, 0x09, 0xf6, 0x21, 0x00, 0x00, | ||
181 | 0x03, 0xfc, 0x0a, 0xf5, 0x22, 0x00, 0x00, | ||
182 | 0x03, 0xfc, 0x0b, 0xf4, 0x23, 0x00, 0x00, | ||
183 | 0x03, 0xfc, 0x1b, 0xe4, 0x16, 0x00, 0x00, | ||
184 | 0x03, 0xfc, 0x0d, 0xf2, 0x24, 0x00, 0x00, | ||
185 | 0x03, 0xfc, 0x0e, 0xf1, 0x25, 0x00, 0x00, | ||
186 | 0x03, 0xfc, 0x0f, 0xf0, 0x26, 0x00, 0x00, | ||
187 | 0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00, | ||
188 | 0x03, 0xfc, 0x41, 0xbe, 0x37, 0x00, 0x00, | ||
189 | 0x03, 0xfc, 0x12, 0xed, 0x27, 0x00, 0x00, | ||
190 | 0x03, 0xfc, 0x11, 0xee, 0x2a, 0x00, 0x00, | ||
191 | 0x03, 0xfc, 0x48, 0xb7, 0x2c, 0x00, 0x00, | ||
192 | 0x03, 0xfc, 0x4a, 0xb5, 0x3c, 0x00, 0x00, | ||
193 | 0x03, 0xfc, 0x47, 0xb8, 0x15, 0x01, 0x00, | ||
194 | 0x03, 0xfc, 0x45, 0xba, 0x0b, 0x01, 0x00, | ||
195 | 0x03, 0xfc, 0x5e, 0xa1, 0x43, 0x00, 0x00, | ||
196 | 0x03, 0xfc, 0x5a, 0xa5, 0x42, 0x00, 0x00, | ||
197 | 0x03, 0xfc, 0x5b, 0xa4, 0x4b, 0x00, 0x00, | ||
198 | 0x03, 0xfc, 0x5f, 0xa0, 0x4e, 0x00, 0x00, | ||
199 | }; | ||
200 | |||
201 | /* TwinHan AzureWave AD-TU700(704J) */ | ||
202 | static struct dvb_usb_rc_key af9015_rc_keys_twinhan[] = { | ||
203 | { 0x05, 0x3f, KEY_POWER }, | ||
204 | { 0x00, 0x19, KEY_FAVORITES }, /* Favorite List */ | ||
205 | { 0x00, 0x04, KEY_TEXT }, /* Teletext */ | ||
206 | { 0x00, 0x0e, KEY_POWER }, | ||
207 | { 0x00, 0x0e, KEY_INFO }, /* Preview */ | ||
208 | { 0x00, 0x08, KEY_EPG }, /* Info/EPG */ | ||
209 | { 0x00, 0x0f, KEY_LIST }, /* Record List */ | ||
210 | { 0x00, 0x1e, KEY_1 }, | ||
211 | { 0x00, 0x1f, KEY_2 }, | ||
212 | { 0x00, 0x20, KEY_3 }, | ||
213 | { 0x00, 0x21, KEY_4 }, | ||
214 | { 0x00, 0x22, KEY_5 }, | ||
215 | { 0x00, 0x23, KEY_6 }, | ||
216 | { 0x00, 0x24, KEY_7 }, | ||
217 | { 0x00, 0x25, KEY_8 }, | ||
218 | { 0x00, 0x26, KEY_9 }, | ||
219 | { 0x00, 0x27, KEY_0 }, | ||
220 | { 0x00, 0x29, KEY_CANCEL }, /* Cancel */ | ||
221 | { 0x00, 0x4c, KEY_CLEAR }, /* Clear */ | ||
222 | { 0x00, 0x2a, KEY_BACK }, /* Back */ | ||
223 | { 0x00, 0x2b, KEY_TAB }, /* Tab */ | ||
224 | { 0x00, 0x52, KEY_UP }, /* up arrow */ | ||
225 | { 0x00, 0x51, KEY_DOWN }, /* down arrow */ | ||
226 | { 0x00, 0x4f, KEY_RIGHT }, /* right arrow */ | ||
227 | { 0x00, 0x50, KEY_LEFT }, /* left arrow */ | ||
228 | { 0x00, 0x28, KEY_ENTER }, /* Enter / ok */ | ||
229 | { 0x02, 0x52, KEY_VOLUMEUP }, | ||
230 | { 0x02, 0x51, KEY_VOLUMEDOWN }, | ||
231 | { 0x00, 0x4e, KEY_CHANNELDOWN }, | ||
232 | { 0x00, 0x4b, KEY_CHANNELUP }, | ||
233 | { 0x00, 0x4a, KEY_RECORD }, | ||
234 | { 0x01, 0x11, KEY_PLAY }, | ||
235 | { 0x00, 0x17, KEY_PAUSE }, | ||
236 | { 0x00, 0x0c, KEY_REWIND }, /* FR << */ | ||
237 | { 0x00, 0x11, KEY_FASTFORWARD }, /* FF >> */ | ||
238 | { 0x01, 0x15, KEY_PREVIOUS }, /* Replay */ | ||
239 | { 0x01, 0x0e, KEY_NEXT }, /* Skip */ | ||
240 | { 0x00, 0x13, KEY_CAMERA }, /* Capture */ | ||
241 | { 0x01, 0x0f, KEY_LANGUAGE }, /* SAP */ | ||
242 | { 0x01, 0x13, KEY_TV2 }, /* PIP */ | ||
243 | { 0x00, 0x1d, KEY_ZOOM }, /* Full Screen */ | ||
244 | { 0x01, 0x17, KEY_SUBTITLE }, /* Subtitle / CC */ | ||
245 | { 0x00, 0x10, KEY_MUTE }, | ||
246 | { 0x01, 0x19, KEY_AUDIO }, /* L/R */ /* TODO better event */ | ||
247 | { 0x01, 0x16, KEY_SLEEP }, /* Hibernate */ | ||
248 | { 0x01, 0x16, KEY_SWITCHVIDEOMODE }, | ||
249 | /* A/V */ /* TODO does not work */ | ||
250 | { 0x00, 0x06, KEY_AGAIN }, /* Recall */ | ||
251 | { 0x01, 0x16, KEY_KPPLUS }, /* Zoom+ */ /* TODO does not work */ | ||
252 | { 0x01, 0x16, KEY_KPMINUS }, /* Zoom- */ /* TODO does not work */ | ||
253 | { 0x02, 0x15, KEY_RED }, | ||
254 | { 0x02, 0x0a, KEY_GREEN }, | ||
255 | { 0x02, 0x1c, KEY_YELLOW }, | ||
256 | { 0x02, 0x05, KEY_BLUE }, | ||
257 | }; | ||
258 | |||
259 | static u8 af9015_ir_table_twinhan[] = { | ||
260 | 0x00, 0xff, 0x16, 0xe9, 0x3f, 0x05, 0x00, | ||
261 | 0x00, 0xff, 0x07, 0xf8, 0x16, 0x01, 0x00, | ||
262 | 0x00, 0xff, 0x14, 0xeb, 0x11, 0x01, 0x00, | ||
263 | 0x00, 0xff, 0x1a, 0xe5, 0x4d, 0x00, 0x00, | ||
264 | 0x00, 0xff, 0x4c, 0xb3, 0x17, 0x00, 0x00, | ||
265 | 0x00, 0xff, 0x12, 0xed, 0x11, 0x00, 0x00, | ||
266 | 0x00, 0xff, 0x40, 0xbf, 0x0c, 0x00, 0x00, | ||
267 | 0x00, 0xff, 0x11, 0xee, 0x4a, 0x00, 0x00, | ||
268 | 0x00, 0xff, 0x54, 0xab, 0x13, 0x00, 0x00, | ||
269 | 0x00, 0xff, 0x41, 0xbe, 0x15, 0x01, 0x00, | ||
270 | 0x00, 0xff, 0x42, 0xbd, 0x0e, 0x01, 0x00, | ||
271 | 0x00, 0xff, 0x43, 0xbc, 0x17, 0x01, 0x00, | ||
272 | 0x00, 0xff, 0x50, 0xaf, 0x0f, 0x01, 0x00, | ||
273 | 0x00, 0xff, 0x4d, 0xb2, 0x1d, 0x00, 0x00, | ||
274 | 0x00, 0xff, 0x47, 0xb8, 0x13, 0x01, 0x00, | ||
275 | 0x00, 0xff, 0x05, 0xfa, 0x4b, 0x00, 0x00, | ||
276 | 0x00, 0xff, 0x02, 0xfd, 0x4e, 0x00, 0x00, | ||
277 | 0x00, 0xff, 0x0e, 0xf1, 0x06, 0x00, 0x00, | ||
278 | 0x00, 0xff, 0x1e, 0xe1, 0x52, 0x02, 0x00, | ||
279 | 0x00, 0xff, 0x0a, 0xf5, 0x51, 0x02, 0x00, | ||
280 | 0x00, 0xff, 0x10, 0xef, 0x10, 0x00, 0x00, | ||
281 | 0x00, 0xff, 0x49, 0xb6, 0x19, 0x01, 0x00, | ||
282 | 0x00, 0xff, 0x15, 0xea, 0x27, 0x00, 0x00, | ||
283 | 0x00, 0xff, 0x03, 0xfc, 0x1e, 0x00, 0x00, | ||
284 | 0x00, 0xff, 0x01, 0xfe, 0x1f, 0x00, 0x00, | ||
285 | 0x00, 0xff, 0x06, 0xf9, 0x20, 0x00, 0x00, | ||
286 | 0x00, 0xff, 0x09, 0xf6, 0x21, 0x00, 0x00, | ||
287 | 0x00, 0xff, 0x1d, 0xe2, 0x22, 0x00, 0x00, | ||
288 | 0x00, 0xff, 0x1f, 0xe0, 0x23, 0x00, 0x00, | ||
289 | 0x00, 0xff, 0x0d, 0xf2, 0x24, 0x00, 0x00, | ||
290 | 0x00, 0xff, 0x19, 0xe6, 0x25, 0x00, 0x00, | ||
291 | 0x00, 0xff, 0x1b, 0xe4, 0x26, 0x00, 0x00, | ||
292 | 0x00, 0xff, 0x00, 0xff, 0x2b, 0x00, 0x00, | ||
293 | 0x00, 0xff, 0x4a, 0xb5, 0x4c, 0x00, 0x00, | ||
294 | 0x00, 0xff, 0x4b, 0xb4, 0x52, 0x00, 0x00, | ||
295 | 0x00, 0xff, 0x51, 0xae, 0x51, 0x00, 0x00, | ||
296 | 0x00, 0xff, 0x52, 0xad, 0x4f, 0x00, 0x00, | ||
297 | 0x00, 0xff, 0x4e, 0xb1, 0x50, 0x00, 0x00, | ||
298 | 0x00, 0xff, 0x0c, 0xf3, 0x29, 0x00, 0x00, | ||
299 | 0x00, 0xff, 0x4f, 0xb0, 0x28, 0x00, 0x00, | ||
300 | 0x00, 0xff, 0x13, 0xec, 0x2a, 0x00, 0x00, | ||
301 | 0x00, 0xff, 0x17, 0xe8, 0x19, 0x00, 0x00, | ||
302 | 0x00, 0xff, 0x04, 0xfb, 0x0f, 0x00, 0x00, | ||
303 | 0x00, 0xff, 0x48, 0xb7, 0x0e, 0x00, 0x00, | ||
304 | 0x00, 0xff, 0x0f, 0xf0, 0x04, 0x00, 0x00, | ||
305 | 0x00, 0xff, 0x1c, 0xe3, 0x08, 0x00, 0x00, | ||
306 | 0x00, 0xff, 0x18, 0xe7, 0x15, 0x02, 0x00, | ||
307 | 0x00, 0xff, 0x53, 0xac, 0x0a, 0x02, 0x00, | ||
308 | 0x00, 0xff, 0x5e, 0xa1, 0x1c, 0x02, 0x00, | ||
309 | 0x00, 0xff, 0x5f, 0xa0, 0x05, 0x02, 0x00, | ||
310 | }; | ||
311 | |||
312 | /* A-Link DTU(m) */ | ||
313 | static struct dvb_usb_rc_key af9015_rc_keys_a_link[] = { | ||
314 | { 0x00, 0x1e, KEY_1 }, | ||
315 | { 0x00, 0x1f, KEY_2 }, | ||
316 | { 0x00, 0x20, KEY_3 }, | ||
317 | { 0x00, 0x21, KEY_4 }, | ||
318 | { 0x00, 0x22, KEY_5 }, | ||
319 | { 0x00, 0x23, KEY_6 }, | ||
320 | { 0x00, 0x24, KEY_7 }, | ||
321 | { 0x00, 0x25, KEY_8 }, | ||
322 | { 0x00, 0x26, KEY_9 }, | ||
323 | { 0x00, 0x27, KEY_0 }, | ||
324 | { 0x00, 0x2e, KEY_CHANNELUP }, | ||
325 | { 0x00, 0x2d, KEY_CHANNELDOWN }, | ||
326 | { 0x04, 0x28, KEY_ZOOM }, | ||
327 | { 0x00, 0x41, KEY_MUTE }, | ||
328 | { 0x00, 0x42, KEY_VOLUMEDOWN }, | ||
329 | { 0x00, 0x43, KEY_VOLUMEUP }, | ||
330 | { 0x00, 0x44, KEY_GOTO }, /* jump */ | ||
331 | { 0x05, 0x45, KEY_POWER }, | ||
332 | }; | ||
333 | |||
334 | static u8 af9015_ir_table_a_link[] = { | ||
335 | 0x08, 0xf7, 0x12, 0xed, 0x45, 0x05, 0x00, /* power */ | ||
336 | 0x08, 0xf7, 0x1a, 0xe5, 0x41, 0x00, 0x00, /* mute */ | ||
337 | 0x08, 0xf7, 0x01, 0xfe, 0x1e, 0x00, 0x00, /* 1 */ | ||
338 | 0x08, 0xf7, 0x1c, 0xe3, 0x21, 0x00, 0x00, /* 4 */ | ||
339 | 0x08, 0xf7, 0x03, 0xfc, 0x24, 0x00, 0x00, /* 7 */ | ||
340 | 0x08, 0xf7, 0x05, 0xfa, 0x28, 0x04, 0x00, /* zoom */ | ||
341 | 0x08, 0xf7, 0x00, 0xff, 0x43, 0x00, 0x00, /* volume up */ | ||
342 | 0x08, 0xf7, 0x16, 0xe9, 0x42, 0x00, 0x00, /* volume down */ | ||
343 | 0x08, 0xf7, 0x0f, 0xf0, 0x1f, 0x00, 0x00, /* 2 */ | ||
344 | 0x08, 0xf7, 0x0d, 0xf2, 0x22, 0x00, 0x00, /* 5 */ | ||
345 | 0x08, 0xf7, 0x1b, 0xe4, 0x25, 0x00, 0x00, /* 8 */ | ||
346 | 0x08, 0xf7, 0x06, 0xf9, 0x27, 0x00, 0x00, /* 0 */ | ||
347 | 0x08, 0xf7, 0x14, 0xeb, 0x2e, 0x00, 0x00, /* channel up */ | ||
348 | 0x08, 0xf7, 0x1d, 0xe2, 0x2d, 0x00, 0x00, /* channel down */ | ||
349 | 0x08, 0xf7, 0x02, 0xfd, 0x20, 0x00, 0x00, /* 3 */ | ||
350 | 0x08, 0xf7, 0x18, 0xe7, 0x23, 0x00, 0x00, /* 6 */ | ||
351 | 0x08, 0xf7, 0x04, 0xfb, 0x26, 0x00, 0x00, /* 9 */ | ||
352 | 0x08, 0xf7, 0x07, 0xf8, 0x44, 0x00, 0x00, /* jump */ | ||
353 | }; | ||
354 | |||
355 | /* MSI DIGIVOX mini II V3.0 */ | ||
356 | static struct dvb_usb_rc_key af9015_rc_keys_msi[] = { | ||
357 | { 0x00, 0x1e, KEY_1 }, | ||
358 | { 0x00, 0x1f, KEY_2 }, | ||
359 | { 0x00, 0x20, KEY_3 }, | ||
360 | { 0x00, 0x21, KEY_4 }, | ||
361 | { 0x00, 0x22, KEY_5 }, | ||
362 | { 0x00, 0x23, KEY_6 }, | ||
363 | { 0x00, 0x24, KEY_7 }, | ||
364 | { 0x00, 0x25, KEY_8 }, | ||
365 | { 0x00, 0x26, KEY_9 }, | ||
366 | { 0x00, 0x27, KEY_0 }, | ||
367 | { 0x03, 0x0f, KEY_CHANNELUP }, | ||
368 | { 0x03, 0x0e, KEY_CHANNELDOWN }, | ||
369 | { 0x00, 0x42, KEY_VOLUMEDOWN }, | ||
370 | { 0x00, 0x43, KEY_VOLUMEUP }, | ||
371 | { 0x05, 0x45, KEY_POWER }, | ||
372 | { 0x00, 0x52, KEY_UP }, /* up */ | ||
373 | { 0x00, 0x51, KEY_DOWN }, /* down */ | ||
374 | { 0x00, 0x28, KEY_ENTER }, | ||
375 | }; | ||
376 | |||
377 | static u8 af9015_ir_table_msi[] = { | ||
378 | 0x03, 0xfc, 0x17, 0xe8, 0x45, 0x05, 0x00, /* power */ | ||
379 | 0x03, 0xfc, 0x0d, 0xf2, 0x51, 0x00, 0x00, /* down */ | ||
380 | 0x03, 0xfc, 0x03, 0xfc, 0x52, 0x00, 0x00, /* up */ | ||
381 | 0x03, 0xfc, 0x1a, 0xe5, 0x1e, 0x00, 0x00, /* 1 */ | ||
382 | 0x03, 0xfc, 0x02, 0xfd, 0x1f, 0x00, 0x00, /* 2 */ | ||
383 | 0x03, 0xfc, 0x04, 0xfb, 0x20, 0x00, 0x00, /* 3 */ | ||
384 | 0x03, 0xfc, 0x1c, 0xe3, 0x21, 0x00, 0x00, /* 4 */ | ||
385 | 0x03, 0xfc, 0x08, 0xf7, 0x22, 0x00, 0x00, /* 5 */ | ||
386 | 0x03, 0xfc, 0x1d, 0xe2, 0x23, 0x00, 0x00, /* 6 */ | ||
387 | 0x03, 0xfc, 0x11, 0xee, 0x24, 0x00, 0x00, /* 7 */ | ||
388 | 0x03, 0xfc, 0x0b, 0xf4, 0x25, 0x00, 0x00, /* 8 */ | ||
389 | 0x03, 0xfc, 0x10, 0xef, 0x26, 0x00, 0x00, /* 9 */ | ||
390 | 0x03, 0xfc, 0x09, 0xf6, 0x27, 0x00, 0x00, /* 0 */ | ||
391 | 0x03, 0xfc, 0x14, 0xeb, 0x43, 0x00, 0x00, /* volume up */ | ||
392 | 0x03, 0xfc, 0x1f, 0xe0, 0x42, 0x00, 0x00, /* volume down */ | ||
393 | 0x03, 0xfc, 0x15, 0xea, 0x0f, 0x03, 0x00, /* channel up */ | ||
394 | 0x03, 0xfc, 0x05, 0xfa, 0x0e, 0x03, 0x00, /* channel down */ | ||
395 | 0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00, /* enter */ | ||
396 | }; | ||
397 | |||
398 | /* MYGICTV U718 */ | ||
399 | static struct dvb_usb_rc_key af9015_rc_keys_mygictv[] = { | ||
400 | { 0x00, 0x3d, KEY_SWITCHVIDEOMODE }, | ||
401 | /* TV / AV */ | ||
402 | { 0x05, 0x45, KEY_POWER }, | ||
403 | { 0x00, 0x1e, KEY_1 }, | ||
404 | { 0x00, 0x1f, KEY_2 }, | ||
405 | { 0x00, 0x20, KEY_3 }, | ||
406 | { 0x00, 0x21, KEY_4 }, | ||
407 | { 0x00, 0x22, KEY_5 }, | ||
408 | { 0x00, 0x23, KEY_6 }, | ||
409 | { 0x00, 0x24, KEY_7 }, | ||
410 | { 0x00, 0x25, KEY_8 }, | ||
411 | { 0x00, 0x26, KEY_9 }, | ||
412 | { 0x00, 0x27, KEY_0 }, | ||
413 | { 0x00, 0x41, KEY_MUTE }, | ||
414 | { 0x00, 0x2a, KEY_ESC }, /* Esc */ | ||
415 | { 0x00, 0x2e, KEY_CHANNELUP }, | ||
416 | { 0x00, 0x2d, KEY_CHANNELDOWN }, | ||
417 | { 0x00, 0x42, KEY_VOLUMEDOWN }, | ||
418 | { 0x00, 0x43, KEY_VOLUMEUP }, | ||
419 | { 0x00, 0x52, KEY_UP }, /* up arrow */ | ||
420 | { 0x00, 0x51, KEY_DOWN }, /* down arrow */ | ||
421 | { 0x00, 0x4f, KEY_RIGHT }, /* right arrow */ | ||
422 | { 0x00, 0x50, KEY_LEFT }, /* left arrow */ | ||
423 | { 0x00, 0x28, KEY_ENTER }, /* ok */ | ||
424 | { 0x01, 0x15, KEY_RECORD }, | ||
425 | { 0x03, 0x13, KEY_PLAY }, | ||
426 | { 0x01, 0x13, KEY_PAUSE }, | ||
427 | { 0x01, 0x16, KEY_STOP }, | ||
428 | { 0x03, 0x07, KEY_REWIND }, /* FR << */ | ||
429 | { 0x03, 0x09, KEY_FASTFORWARD }, /* FF >> */ | ||
430 | { 0x00, 0x3b, KEY_TIME }, /* TimeShift */ | ||
431 | { 0x00, 0x3e, KEY_CAMERA }, /* Snapshot */ | ||
432 | { 0x03, 0x16, KEY_CYCLEWINDOWS }, /* yellow, min / max */ | ||
433 | { 0x00, 0x00, KEY_ZOOM }, /* 'select' (?) */ | ||
434 | { 0x03, 0x16, KEY_SHUFFLE }, /* Shuffle */ | ||
435 | { 0x03, 0x45, KEY_POWER }, | ||
436 | }; | ||
437 | |||
438 | static u8 af9015_ir_table_mygictv[] = { | ||
439 | 0x02, 0xbd, 0x0c, 0xf3, 0x3d, 0x00, 0x00, /* TV / AV */ | ||
440 | 0x02, 0xbd, 0x14, 0xeb, 0x45, 0x05, 0x00, /* power */ | ||
441 | 0x02, 0xbd, 0x00, 0xff, 0x1e, 0x00, 0x00, /* 1 */ | ||
442 | 0x02, 0xbd, 0x01, 0xfe, 0x1f, 0x00, 0x00, /* 2 */ | ||
443 | 0x02, 0xbd, 0x02, 0xfd, 0x20, 0x00, 0x00, /* 3 */ | ||
444 | 0x02, 0xbd, 0x03, 0xfc, 0x21, 0x00, 0x00, /* 4 */ | ||
445 | 0x02, 0xbd, 0x04, 0xfb, 0x22, 0x00, 0x00, /* 5 */ | ||
446 | 0x02, 0xbd, 0x05, 0xfa, 0x23, 0x00, 0x00, /* 6 */ | ||
447 | 0x02, 0xbd, 0x06, 0xf9, 0x24, 0x00, 0x00, /* 7 */ | ||
448 | 0x02, 0xbd, 0x07, 0xf8, 0x25, 0x00, 0x00, /* 8 */ | ||
449 | 0x02, 0xbd, 0x08, 0xf7, 0x26, 0x00, 0x00, /* 9 */ | ||
450 | 0x02, 0xbd, 0x09, 0xf6, 0x27, 0x00, 0x00, /* 0 */ | ||
451 | 0x02, 0xbd, 0x0a, 0xf5, 0x41, 0x00, 0x00, /* mute */ | ||
452 | 0x02, 0xbd, 0x1c, 0xe3, 0x2a, 0x00, 0x00, /* esc */ | ||
453 | 0x02, 0xbd, 0x1f, 0xe0, 0x43, 0x00, 0x00, /* volume up */ | ||
454 | 0x02, 0xbd, 0x12, 0xed, 0x52, 0x00, 0x00, /* up arrow */ | ||
455 | 0x02, 0xbd, 0x11, 0xee, 0x50, 0x00, 0x00, /* left arrow */ | ||
456 | 0x02, 0xbd, 0x15, 0xea, 0x28, 0x00, 0x00, /* ok */ | ||
457 | 0x02, 0xbd, 0x10, 0xef, 0x4f, 0x00, 0x00, /* right arrow */ | ||
458 | 0x02, 0xbd, 0x13, 0xec, 0x51, 0x00, 0x00, /* down arrow */ | ||
459 | 0x02, 0xbd, 0x0e, 0xf1, 0x42, 0x00, 0x00, /* volume down */ | ||
460 | 0x02, 0xbd, 0x19, 0xe6, 0x15, 0x01, 0x00, /* record */ | ||
461 | 0x02, 0xbd, 0x1e, 0xe1, 0x13, 0x03, 0x00, /* play */ | ||
462 | 0x02, 0xbd, 0x16, 0xe9, 0x16, 0x01, 0x00, /* stop */ | ||
463 | 0x02, 0xbd, 0x0b, 0xf4, 0x28, 0x04, 0x00, /* yellow, min / max */ | ||
464 | 0x02, 0xbd, 0x0f, 0xf0, 0x3b, 0x00, 0x00, /* time shift */ | ||
465 | 0x02, 0xbd, 0x18, 0xe7, 0x2e, 0x00, 0x00, /* channel up */ | ||
466 | 0x02, 0xbd, 0x1a, 0xe5, 0x2d, 0x00, 0x00, /* channel down */ | ||
467 | 0x02, 0xbd, 0x17, 0xe8, 0x3e, 0x00, 0x00, /* snapshot */ | ||
468 | 0x02, 0xbd, 0x40, 0xbf, 0x13, 0x01, 0x00, /* pause */ | ||
469 | 0x02, 0xbd, 0x41, 0xbe, 0x09, 0x03, 0x00, /* FF >> */ | ||
470 | 0x02, 0xbd, 0x42, 0xbd, 0x07, 0x03, 0x00, /* FR << */ | ||
471 | 0x02, 0xbd, 0x43, 0xbc, 0x00, 0x00, 0x00, /* 'select' (?) */ | ||
472 | 0x02, 0xbd, 0x44, 0xbb, 0x16, 0x03, 0x00, /* shuffle */ | ||
473 | 0x02, 0xbd, 0x45, 0xba, 0x45, 0x03, 0x00, /* power */ | ||
474 | }; | ||
475 | |||
476 | /* KWorld PlusTV Dual DVB-T Stick (DVB-T 399U) */ | ||
477 | static u8 af9015_ir_table_kworld[] = { | ||
478 | 0x86, 0x6b, 0x0c, 0xf3, 0x2e, 0x07, 0x00, | ||
479 | 0x86, 0x6b, 0x16, 0xe9, 0x2d, 0x07, 0x00, | ||
480 | 0x86, 0x6b, 0x1d, 0xe2, 0x37, 0x07, 0x00, | ||
481 | 0x86, 0x6b, 0x00, 0xff, 0x1e, 0x07, 0x00, | ||
482 | 0x86, 0x6b, 0x01, 0xfe, 0x1f, 0x07, 0x00, | ||
483 | 0x86, 0x6b, 0x02, 0xfd, 0x20, 0x07, 0x00, | ||
484 | 0x86, 0x6b, 0x03, 0xfc, 0x21, 0x07, 0x00, | ||
485 | 0x86, 0x6b, 0x04, 0xfb, 0x22, 0x07, 0x00, | ||
486 | 0x86, 0x6b, 0x05, 0xfa, 0x23, 0x07, 0x00, | ||
487 | 0x86, 0x6b, 0x06, 0xf9, 0x24, 0x07, 0x00, | ||
488 | 0x86, 0x6b, 0x07, 0xf8, 0x25, 0x07, 0x00, | ||
489 | 0x86, 0x6b, 0x08, 0xf7, 0x26, 0x07, 0x00, | ||
490 | 0x86, 0x6b, 0x09, 0xf6, 0x4d, 0x07, 0x00, | ||
491 | 0x86, 0x6b, 0x0a, 0xf5, 0x4e, 0x07, 0x00, | ||
492 | 0x86, 0x6b, 0x14, 0xeb, 0x4f, 0x07, 0x00, | ||
493 | 0x86, 0x6b, 0x1e, 0xe1, 0x50, 0x07, 0x00, | ||
494 | 0x86, 0x6b, 0x17, 0xe8, 0x52, 0x07, 0x00, | ||
495 | 0x86, 0x6b, 0x1f, 0xe0, 0x51, 0x07, 0x00, | ||
496 | 0x86, 0x6b, 0x0e, 0xf1, 0x0b, 0x07, 0x00, | ||
497 | 0x86, 0x6b, 0x20, 0xdf, 0x0c, 0x07, 0x00, | ||
498 | 0x86, 0x6b, 0x42, 0xbd, 0x0d, 0x07, 0x00, | ||
499 | 0x86, 0x6b, 0x0b, 0xf4, 0x0e, 0x07, 0x00, | ||
500 | 0x86, 0x6b, 0x43, 0xbc, 0x0f, 0x07, 0x00, | ||
501 | 0x86, 0x6b, 0x10, 0xef, 0x10, 0x07, 0x00, | ||
502 | 0x86, 0x6b, 0x21, 0xde, 0x11, 0x07, 0x00, | ||
503 | 0x86, 0x6b, 0x13, 0xec, 0x12, 0x07, 0x00, | ||
504 | 0x86, 0x6b, 0x11, 0xee, 0x13, 0x07, 0x00, | ||
505 | 0x86, 0x6b, 0x12, 0xed, 0x14, 0x07, 0x00, | ||
506 | 0x86, 0x6b, 0x19, 0xe6, 0x15, 0x07, 0x00, | ||
507 | 0x86, 0x6b, 0x1a, 0xe5, 0x16, 0x07, 0x00, | ||
508 | 0x86, 0x6b, 0x1b, 0xe4, 0x17, 0x07, 0x00, | ||
509 | 0x86, 0x6b, 0x4b, 0xb4, 0x18, 0x07, 0x00, | ||
510 | 0x86, 0x6b, 0x40, 0xbf, 0x19, 0x07, 0x00, | ||
511 | 0x86, 0x6b, 0x44, 0xbb, 0x1a, 0x07, 0x00, | ||
512 | 0x86, 0x6b, 0x41, 0xbe, 0x1b, 0x07, 0x00, | ||
513 | 0x86, 0x6b, 0x22, 0xdd, 0x1c, 0x07, 0x00, | ||
514 | 0x86, 0x6b, 0x15, 0xea, 0x1d, 0x07, 0x00, | ||
515 | 0x86, 0x6b, 0x0f, 0xf0, 0x3f, 0x07, 0x00, | ||
516 | 0x86, 0x6b, 0x1c, 0xe3, 0x40, 0x07, 0x00, | ||
517 | 0x86, 0x6b, 0x4a, 0xb5, 0x41, 0x07, 0x00, | ||
518 | 0x86, 0x6b, 0x48, 0xb7, 0x42, 0x07, 0x00, | ||
519 | 0x86, 0x6b, 0x49, 0xb6, 0x43, 0x07, 0x00, | ||
520 | 0x86, 0x6b, 0x18, 0xe7, 0x44, 0x07, 0x00, | ||
521 | 0x86, 0x6b, 0x23, 0xdc, 0x45, 0x07, 0x00, | ||
522 | }; | ||
523 | |||
524 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 2f408d2e1ef3..c786359fba03 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c | |||
@@ -41,6 +41,9 @@ | |||
41 | static int dvb_usb_anysee_debug; | 41 | static int dvb_usb_anysee_debug; |
42 | module_param_named(debug, dvb_usb_anysee_debug, int, 0644); | 42 | module_param_named(debug, dvb_usb_anysee_debug, int, 0644); |
43 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | 43 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); |
44 | int dvb_usb_anysee_delsys; | ||
45 | module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644); | ||
46 | MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)"); | ||
44 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 47 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
45 | 48 | ||
46 | static struct mutex anysee_usb_mutex; | 49 | static struct mutex anysee_usb_mutex; |
@@ -178,14 +181,14 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
178 | inc = 1; | 181 | inc = 1; |
179 | } | 182 | } |
180 | if (ret) | 183 | if (ret) |
181 | return ret; | 184 | break; |
182 | 185 | ||
183 | i += inc; | 186 | i += inc; |
184 | } | 187 | } |
185 | 188 | ||
186 | mutex_unlock(&d->i2c_mutex); | 189 | mutex_unlock(&d->i2c_mutex); |
187 | 190 | ||
188 | return i; | 191 | return ret ? ret : i; |
189 | } | 192 | } |
190 | 193 | ||
191 | static u32 anysee_i2c_func(struct i2c_adapter *adapter) | 194 | static u32 anysee_i2c_func(struct i2c_adapter *adapter) |
@@ -272,9 +275,11 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
272 | model demod hw firmware | 275 | model demod hw firmware |
273 | 1. E30 MT352 02 0.2.1 | 276 | 1. E30 MT352 02 0.2.1 |
274 | 2. E30 ZL10353 02 0.2.1 | 277 | 2. E30 ZL10353 02 0.2.1 |
275 | 3. E30 Plus ZL10353 06 0.1.0 | 278 | 3. E30 Combo ZL10353 0f 0.1.2 DVB-T/C combo |
276 | 4. E30C Plus TDA10023 0a 0.1.0 rev 0.2 | 279 | 4. E30 Plus ZL10353 06 0.1.0 |
277 | 4. E30C Plus TDA10023 0f 0.1.2 rev 0.4 | 280 | 5. E30C Plus TDA10023 0a 0.1.0 rev 0.2 |
281 | E30C Plus TDA10023 0f 0.1.2 rev 0.4 | ||
282 | E30 Combo TDA10023 0f 0.1.2 DVB-T/C combo | ||
278 | */ | 283 | */ |
279 | 284 | ||
280 | /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */ | 285 | /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */ |
@@ -293,6 +298,21 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | |||
293 | return 0; | 298 | return 0; |
294 | } | 299 | } |
295 | 300 | ||
301 | /* for E30 Combo Plus DVB-T demodulator */ | ||
302 | if (dvb_usb_anysee_delsys) { | ||
303 | ret = anysee_write_reg(adap->dev, 0xb0, 0x01); | ||
304 | if (ret) | ||
305 | return ret; | ||
306 | |||
307 | /* Zarlink ZL10353 DVB-T demod */ | ||
308 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | ||
309 | &adap->dev->i2c_adap); | ||
310 | if (adap->fe != NULL) { | ||
311 | state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A; | ||
312 | return 0; | ||
313 | } | ||
314 | } | ||
315 | |||
296 | /* connect demod on IO port D for TDA10023 & ZL10353 */ | 316 | /* connect demod on IO port D for TDA10023 & ZL10353 */ |
297 | ret = anysee_write_reg(adap->dev, 0xb0, 0x25); | 317 | ret = anysee_write_reg(adap->dev, 0xb0, 0x25); |
298 | if (ret) | 318 | if (ret) |
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c new file mode 100644 index 000000000000..3ac9f74e9fbf --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2-core.c | |||
@@ -0,0 +1,268 @@ | |||
1 | /* | ||
2 | * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. | ||
3 | * | ||
4 | * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) | ||
5 | * | ||
6 | * Based on the dvb-usb-framework code and the | ||
7 | * original Terratec Cinergy T2 driver by: | ||
8 | * | ||
9 | * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and | ||
10 | * Holger Waechtler <holger@qanu.de> | ||
11 | * | ||
12 | * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include "cinergyT2.h" | ||
31 | |||
32 | |||
33 | /* debug */ | ||
34 | int dvb_usb_cinergyt2_debug; | ||
35 | int disable_remote; | ||
36 | |||
37 | module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644); | ||
38 | MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 " | ||
39 | "(or-able))."); | ||
40 | |||
41 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
42 | |||
43 | struct cinergyt2_state { | ||
44 | u8 rc_counter; | ||
45 | }; | ||
46 | |||
47 | /* We are missing a release hook with usb_device data */ | ||
48 | struct dvb_usb_device *cinergyt2_usb_device; | ||
49 | |||
50 | static struct dvb_usb_device_properties cinergyt2_properties; | ||
51 | |||
52 | static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) | ||
53 | { | ||
54 | char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; | ||
55 | char result[64]; | ||
56 | return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result, | ||
57 | sizeof(result), 0); | ||
58 | } | ||
59 | |||
60 | static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable) | ||
61 | { | ||
62 | char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 }; | ||
63 | char state[3]; | ||
64 | return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0); | ||
65 | } | ||
66 | |||
67 | static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) | ||
68 | { | ||
69 | char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION }; | ||
70 | char state[3]; | ||
71 | int ret; | ||
72 | |||
73 | adap->fe = cinergyt2_fe_attach(adap->dev); | ||
74 | |||
75 | ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state, | ||
76 | sizeof(state), 0); | ||
77 | if (ret < 0) { | ||
78 | deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep " | ||
79 | "state info\n"); | ||
80 | } | ||
81 | |||
82 | /* Copy this pointer as we are gonna need it in the release phase */ | ||
83 | cinergyt2_usb_device = adap->dev; | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static struct dvb_usb_rc_key cinergyt2_rc_keys[] = { | ||
89 | { 0x04, 0x01, KEY_POWER }, | ||
90 | { 0x04, 0x02, KEY_1 }, | ||
91 | { 0x04, 0x03, KEY_2 }, | ||
92 | { 0x04, 0x04, KEY_3 }, | ||
93 | { 0x04, 0x05, KEY_4 }, | ||
94 | { 0x04, 0x06, KEY_5 }, | ||
95 | { 0x04, 0x07, KEY_6 }, | ||
96 | { 0x04, 0x08, KEY_7 }, | ||
97 | { 0x04, 0x09, KEY_8 }, | ||
98 | { 0x04, 0x0a, KEY_9 }, | ||
99 | { 0x04, 0x0c, KEY_0 }, | ||
100 | { 0x04, 0x0b, KEY_VIDEO }, | ||
101 | { 0x04, 0x0d, KEY_REFRESH }, | ||
102 | { 0x04, 0x0e, KEY_SELECT }, | ||
103 | { 0x04, 0x0f, KEY_EPG }, | ||
104 | { 0x04, 0x10, KEY_UP }, | ||
105 | { 0x04, 0x14, KEY_DOWN }, | ||
106 | { 0x04, 0x11, KEY_LEFT }, | ||
107 | { 0x04, 0x13, KEY_RIGHT }, | ||
108 | { 0x04, 0x12, KEY_OK }, | ||
109 | { 0x04, 0x15, KEY_TEXT }, | ||
110 | { 0x04, 0x16, KEY_INFO }, | ||
111 | { 0x04, 0x17, KEY_RED }, | ||
112 | { 0x04, 0x18, KEY_GREEN }, | ||
113 | { 0x04, 0x19, KEY_YELLOW }, | ||
114 | { 0x04, 0x1a, KEY_BLUE }, | ||
115 | { 0x04, 0x1c, KEY_VOLUMEUP }, | ||
116 | { 0x04, 0x1e, KEY_VOLUMEDOWN }, | ||
117 | { 0x04, 0x1d, KEY_MUTE }, | ||
118 | { 0x04, 0x1b, KEY_CHANNELUP }, | ||
119 | { 0x04, 0x1f, KEY_CHANNELDOWN }, | ||
120 | { 0x04, 0x40, KEY_PAUSE }, | ||
121 | { 0x04, 0x4c, KEY_PLAY }, | ||
122 | { 0x04, 0x58, KEY_RECORD }, | ||
123 | { 0x04, 0x54, KEY_PREVIOUS }, | ||
124 | { 0x04, 0x48, KEY_STOP }, | ||
125 | { 0x04, 0x5c, KEY_NEXT } | ||
126 | }; | ||
127 | |||
128 | /* Number of keypresses to ignore before detect repeating */ | ||
129 | #define RC_REPEAT_DELAY 3 | ||
130 | |||
131 | static int repeatable_keys[] = { | ||
132 | KEY_UP, | ||
133 | KEY_DOWN, | ||
134 | KEY_LEFT, | ||
135 | KEY_RIGHT, | ||
136 | KEY_VOLUMEUP, | ||
137 | KEY_VOLUMEDOWN, | ||
138 | KEY_CHANNELUP, | ||
139 | KEY_CHANNELDOWN | ||
140 | }; | ||
141 | |||
142 | static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
143 | { | ||
144 | struct cinergyt2_state *st = d->priv; | ||
145 | u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS; | ||
146 | int i; | ||
147 | |||
148 | *state = REMOTE_NO_KEY_PRESSED; | ||
149 | |||
150 | dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0); | ||
151 | if (key[4] == 0xff) { | ||
152 | /* key repeat */ | ||
153 | st->rc_counter++; | ||
154 | if (st->rc_counter > RC_REPEAT_DELAY) { | ||
155 | for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) { | ||
156 | if (d->last_event == repeatable_keys[i]) { | ||
157 | *state = REMOTE_KEY_REPEAT; | ||
158 | *event = d->last_event; | ||
159 | deb_rc("repeat key, event %x\n", | ||
160 | *event); | ||
161 | return 0; | ||
162 | } | ||
163 | } | ||
164 | deb_rc("repeated key (non repeatable)\n"); | ||
165 | } | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | /* hack to pass checksum on the custom field */ | ||
170 | key[2] = ~key[1]; | ||
171 | dvb_usb_nec_rc_key_to_event(d, key, event, state); | ||
172 | if (key[0] != 0) { | ||
173 | if (*event != d->last_event) | ||
174 | st->rc_counter = 0; | ||
175 | |||
176 | deb_rc("key: %x %x %x %x %x\n", | ||
177 | key[0], key[1], key[2], key[3], key[4]); | ||
178 | } | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int cinergyt2_usb_probe(struct usb_interface *intf, | ||
183 | const struct usb_device_id *id) | ||
184 | { | ||
185 | return dvb_usb_device_init(intf, &cinergyt2_properties, | ||
186 | THIS_MODULE, NULL, adapter_nr); | ||
187 | } | ||
188 | |||
189 | |||
190 | static struct usb_device_id cinergyt2_usb_table[] = { | ||
191 | { USB_DEVICE(USB_VID_TERRATEC, 0x0038) }, | ||
192 | { 0 } | ||
193 | }; | ||
194 | |||
195 | MODULE_DEVICE_TABLE(usb, cinergyt2_usb_table); | ||
196 | |||
197 | static struct dvb_usb_device_properties cinergyt2_properties = { | ||
198 | .size_of_priv = sizeof(struct cinergyt2_state), | ||
199 | .num_adapters = 1, | ||
200 | .adapter = { | ||
201 | { | ||
202 | .streaming_ctrl = cinergyt2_streaming_ctrl, | ||
203 | .frontend_attach = cinergyt2_frontend_attach, | ||
204 | |||
205 | /* parameter for the MPEG2-data transfer */ | ||
206 | .stream = { | ||
207 | .type = USB_BULK, | ||
208 | .count = 5, | ||
209 | .endpoint = 0x02, | ||
210 | .u = { | ||
211 | .bulk = { | ||
212 | .buffersize = 512, | ||
213 | } | ||
214 | } | ||
215 | }, | ||
216 | } | ||
217 | }, | ||
218 | |||
219 | .power_ctrl = cinergyt2_power_ctrl, | ||
220 | |||
221 | .rc_interval = 50, | ||
222 | .rc_key_map = cinergyt2_rc_keys, | ||
223 | .rc_key_map_size = ARRAY_SIZE(cinergyt2_rc_keys), | ||
224 | .rc_query = cinergyt2_rc_query, | ||
225 | |||
226 | .generic_bulk_ctrl_endpoint = 1, | ||
227 | |||
228 | .num_device_descs = 1, | ||
229 | .devices = { | ||
230 | { .name = "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver", | ||
231 | .cold_ids = {NULL}, | ||
232 | .warm_ids = { &cinergyt2_usb_table[0], NULL }, | ||
233 | }, | ||
234 | { NULL }, | ||
235 | } | ||
236 | }; | ||
237 | |||
238 | |||
239 | static struct usb_driver cinergyt2_driver = { | ||
240 | .name = "cinergyT2", | ||
241 | .probe = cinergyt2_usb_probe, | ||
242 | .disconnect = dvb_usb_device_exit, | ||
243 | .id_table = cinergyt2_usb_table | ||
244 | }; | ||
245 | |||
246 | static int __init cinergyt2_usb_init(void) | ||
247 | { | ||
248 | int err; | ||
249 | |||
250 | err = usb_register(&cinergyt2_driver); | ||
251 | if (err) { | ||
252 | err("usb_register() failed! (err %i)\n", err); | ||
253 | return err; | ||
254 | } | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static void __exit cinergyt2_usb_exit(void) | ||
259 | { | ||
260 | usb_deregister(&cinergyt2_driver); | ||
261 | } | ||
262 | |||
263 | module_init(cinergyt2_usb_init); | ||
264 | module_exit(cinergyt2_usb_exit); | ||
265 | |||
266 | MODULE_DESCRIPTION("Terratec Cinergy T2 DVB-T driver"); | ||
267 | MODULE_LICENSE("GPL"); | ||
268 | MODULE_AUTHOR("Tomi Orava"); | ||
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c new file mode 100644 index 000000000000..649f25cca49e --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c | |||
@@ -0,0 +1,351 @@ | |||
1 | /* | ||
2 | * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. | ||
3 | * | ||
4 | * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) | ||
5 | * | ||
6 | * Based on the dvb-usb-framework code and the | ||
7 | * original Terratec Cinergy T2 driver by: | ||
8 | * | ||
9 | * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and | ||
10 | * Holger Waechtler <holger@qanu.de> | ||
11 | * | ||
12 | * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include "cinergyT2.h" | ||
31 | |||
32 | |||
33 | /** | ||
34 | * convert linux-dvb frontend parameter set into TPS. | ||
35 | * See ETSI ETS-300744, section 4.6.2, table 9 for details. | ||
36 | * | ||
37 | * This function is probably reusable and may better get placed in a support | ||
38 | * library. | ||
39 | * | ||
40 | * We replace errornous fields by default TPS fields (the ones with value 0). | ||
41 | */ | ||
42 | |||
43 | static uint16_t compute_tps(struct dvb_frontend_parameters *p) | ||
44 | { | ||
45 | struct dvb_ofdm_parameters *op = &p->u.ofdm; | ||
46 | uint16_t tps = 0; | ||
47 | |||
48 | switch (op->code_rate_HP) { | ||
49 | case FEC_2_3: | ||
50 | tps |= (1 << 7); | ||
51 | break; | ||
52 | case FEC_3_4: | ||
53 | tps |= (2 << 7); | ||
54 | break; | ||
55 | case FEC_5_6: | ||
56 | tps |= (3 << 7); | ||
57 | break; | ||
58 | case FEC_7_8: | ||
59 | tps |= (4 << 7); | ||
60 | break; | ||
61 | case FEC_1_2: | ||
62 | case FEC_AUTO: | ||
63 | default: | ||
64 | /* tps |= (0 << 7) */; | ||
65 | } | ||
66 | |||
67 | switch (op->code_rate_LP) { | ||
68 | case FEC_2_3: | ||
69 | tps |= (1 << 4); | ||
70 | break; | ||
71 | case FEC_3_4: | ||
72 | tps |= (2 << 4); | ||
73 | break; | ||
74 | case FEC_5_6: | ||
75 | tps |= (3 << 4); | ||
76 | break; | ||
77 | case FEC_7_8: | ||
78 | tps |= (4 << 4); | ||
79 | break; | ||
80 | case FEC_1_2: | ||
81 | case FEC_AUTO: | ||
82 | default: | ||
83 | /* tps |= (0 << 4) */; | ||
84 | } | ||
85 | |||
86 | switch (op->constellation) { | ||
87 | case QAM_16: | ||
88 | tps |= (1 << 13); | ||
89 | break; | ||
90 | case QAM_64: | ||
91 | tps |= (2 << 13); | ||
92 | break; | ||
93 | case QPSK: | ||
94 | default: | ||
95 | /* tps |= (0 << 13) */; | ||
96 | } | ||
97 | |||
98 | switch (op->transmission_mode) { | ||
99 | case TRANSMISSION_MODE_8K: | ||
100 | tps |= (1 << 0); | ||
101 | break; | ||
102 | case TRANSMISSION_MODE_2K: | ||
103 | default: | ||
104 | /* tps |= (0 << 0) */; | ||
105 | } | ||
106 | |||
107 | switch (op->guard_interval) { | ||
108 | case GUARD_INTERVAL_1_16: | ||
109 | tps |= (1 << 2); | ||
110 | break; | ||
111 | case GUARD_INTERVAL_1_8: | ||
112 | tps |= (2 << 2); | ||
113 | break; | ||
114 | case GUARD_INTERVAL_1_4: | ||
115 | tps |= (3 << 2); | ||
116 | break; | ||
117 | case GUARD_INTERVAL_1_32: | ||
118 | default: | ||
119 | /* tps |= (0 << 2) */; | ||
120 | } | ||
121 | |||
122 | switch (op->hierarchy_information) { | ||
123 | case HIERARCHY_1: | ||
124 | tps |= (1 << 10); | ||
125 | break; | ||
126 | case HIERARCHY_2: | ||
127 | tps |= (2 << 10); | ||
128 | break; | ||
129 | case HIERARCHY_4: | ||
130 | tps |= (3 << 10); | ||
131 | break; | ||
132 | case HIERARCHY_NONE: | ||
133 | default: | ||
134 | /* tps |= (0 << 10) */; | ||
135 | } | ||
136 | |||
137 | return tps; | ||
138 | } | ||
139 | |||
140 | struct cinergyt2_fe_state { | ||
141 | struct dvb_frontend fe; | ||
142 | struct dvb_usb_device *d; | ||
143 | }; | ||
144 | |||
145 | static int cinergyt2_fe_read_status(struct dvb_frontend *fe, | ||
146 | fe_status_t *status) | ||
147 | { | ||
148 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
149 | struct dvbt_get_status_msg result; | ||
150 | u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
151 | int ret; | ||
152 | |||
153 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result, | ||
154 | sizeof(result), 0); | ||
155 | if (ret < 0) | ||
156 | return ret; | ||
157 | |||
158 | *status = 0; | ||
159 | |||
160 | if (0xffff - le16_to_cpu(result.gain) > 30) | ||
161 | *status |= FE_HAS_SIGNAL; | ||
162 | if (result.lock_bits & (1 << 6)) | ||
163 | *status |= FE_HAS_LOCK; | ||
164 | if (result.lock_bits & (1 << 5)) | ||
165 | *status |= FE_HAS_SYNC; | ||
166 | if (result.lock_bits & (1 << 4)) | ||
167 | *status |= FE_HAS_CARRIER; | ||
168 | if (result.lock_bits & (1 << 1)) | ||
169 | *status |= FE_HAS_VITERBI; | ||
170 | |||
171 | if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != | ||
172 | (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) | ||
173 | *status &= ~FE_HAS_LOCK; | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
179 | { | ||
180 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
181 | struct dvbt_get_status_msg status; | ||
182 | char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
183 | int ret; | ||
184 | |||
185 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, | ||
186 | sizeof(status), 0); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | |||
190 | *ber = le32_to_cpu(status.viterbi_error_rate); | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) | ||
195 | { | ||
196 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
197 | struct dvbt_get_status_msg status; | ||
198 | u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
199 | int ret; | ||
200 | |||
201 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status, | ||
202 | sizeof(status), 0); | ||
203 | if (ret < 0) { | ||
204 | err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n", | ||
205 | ret); | ||
206 | return ret; | ||
207 | } | ||
208 | *unc = le32_to_cpu(status.uncorrected_block_count); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe, | ||
213 | u16 *strength) | ||
214 | { | ||
215 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
216 | struct dvbt_get_status_msg status; | ||
217 | char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
218 | int ret; | ||
219 | |||
220 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, | ||
221 | sizeof(status), 0); | ||
222 | if (ret < 0) { | ||
223 | err("cinergyt2_fe_read_signal_strength() Failed!" | ||
224 | " (Error=%d)\n", ret); | ||
225 | return ret; | ||
226 | } | ||
227 | *strength = (0xffff - le16_to_cpu(status.gain)); | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
232 | { | ||
233 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
234 | struct dvbt_get_status_msg status; | ||
235 | char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
236 | int ret; | ||
237 | |||
238 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, | ||
239 | sizeof(status), 0); | ||
240 | if (ret < 0) { | ||
241 | err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret); | ||
242 | return ret; | ||
243 | } | ||
244 | *snr = (status.snr << 8) | status.snr; | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int cinergyt2_fe_init(struct dvb_frontend *fe) | ||
249 | { | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int cinergyt2_fe_sleep(struct dvb_frontend *fe) | ||
254 | { | ||
255 | deb_info("cinergyt2_fe_sleep() Called\n"); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int cinergyt2_fe_get_tune_settings(struct dvb_frontend *fe, | ||
260 | struct dvb_frontend_tune_settings *tune) | ||
261 | { | ||
262 | tune->min_delay_ms = 800; | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe, | ||
267 | struct dvb_frontend_parameters *fep) | ||
268 | { | ||
269 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
270 | struct dvbt_set_parameters_msg param; | ||
271 | char result[2]; | ||
272 | int err; | ||
273 | |||
274 | param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; | ||
275 | param.tps = cpu_to_le16(compute_tps(fep)); | ||
276 | param.freq = cpu_to_le32(fep->frequency / 1000); | ||
277 | param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ; | ||
278 | |||
279 | err = dvb_usb_generic_rw(state->d, | ||
280 | (char *)¶m, sizeof(param), | ||
281 | result, sizeof(result), 0); | ||
282 | if (err < 0) | ||
283 | err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); | ||
284 | |||
285 | return (err < 0) ? err : 0; | ||
286 | } | ||
287 | |||
288 | static int cinergyt2_fe_get_frontend(struct dvb_frontend *fe, | ||
289 | struct dvb_frontend_parameters *fep) | ||
290 | { | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static void cinergyt2_fe_release(struct dvb_frontend *fe) | ||
295 | { | ||
296 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | ||
297 | if (state != NULL) | ||
298 | kfree(state); | ||
299 | } | ||
300 | |||
301 | static struct dvb_frontend_ops cinergyt2_fe_ops; | ||
302 | |||
303 | struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d) | ||
304 | { | ||
305 | struct cinergyt2_fe_state *s = kzalloc(sizeof( | ||
306 | struct cinergyt2_fe_state), GFP_KERNEL); | ||
307 | if (s == NULL) | ||
308 | return NULL; | ||
309 | |||
310 | s->d = d; | ||
311 | memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops)); | ||
312 | s->fe.demodulator_priv = s; | ||
313 | return &s->fe; | ||
314 | } | ||
315 | |||
316 | |||
317 | static struct dvb_frontend_ops cinergyt2_fe_ops = { | ||
318 | .info = { | ||
319 | .name = DRIVER_NAME, | ||
320 | .type = FE_OFDM, | ||
321 | .frequency_min = 174000000, | ||
322 | .frequency_max = 862000000, | ||
323 | .frequency_stepsize = 166667, | ||
324 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | ||
325 | | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ||
326 | | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | ||
327 | | FE_CAN_FEC_AUTO | FE_CAN_QPSK | ||
328 | | FE_CAN_QAM_16 | FE_CAN_QAM_64 | ||
329 | | FE_CAN_QAM_AUTO | ||
330 | | FE_CAN_TRANSMISSION_MODE_AUTO | ||
331 | | FE_CAN_GUARD_INTERVAL_AUTO | ||
332 | | FE_CAN_HIERARCHY_AUTO | ||
333 | | FE_CAN_RECOVER | ||
334 | | FE_CAN_MUTE_TS | ||
335 | }, | ||
336 | |||
337 | .release = cinergyt2_fe_release, | ||
338 | |||
339 | .init = cinergyt2_fe_init, | ||
340 | .sleep = cinergyt2_fe_sleep, | ||
341 | |||
342 | .set_frontend = cinergyt2_fe_set_frontend, | ||
343 | .get_frontend = cinergyt2_fe_get_frontend, | ||
344 | .get_tune_settings = cinergyt2_fe_get_tune_settings, | ||
345 | |||
346 | .read_status = cinergyt2_fe_read_status, | ||
347 | .read_ber = cinergyt2_fe_read_ber, | ||
348 | .read_signal_strength = cinergyt2_fe_read_signal_strength, | ||
349 | .read_snr = cinergyt2_fe_read_snr, | ||
350 | .read_ucblocks = cinergyt2_fe_read_unc_blocks, | ||
351 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2.h b/drivers/media/dvb/dvb-usb/cinergyT2.h new file mode 100644 index 000000000000..11d79eb384c8 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/cinergyT2.h | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * TerraTec Cinergy T2/qanu USB2 DVB-T adapter. | ||
3 | * | ||
4 | * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi) | ||
5 | * | ||
6 | * Based on the dvb-usb-framework code and the | ||
7 | * original Terratec Cinergy T2 driver by: | ||
8 | * | ||
9 | * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and | ||
10 | * Holger Waechtler <holger@qanu.de> | ||
11 | * | ||
12 | * Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #ifndef _DVB_USB_CINERGYT2_H_ | ||
31 | #define _DVB_USB_CINERGYT2_H_ | ||
32 | |||
33 | #include <linux/usb/input.h> | ||
34 | |||
35 | #define DVB_USB_LOG_PREFIX "cinergyT2" | ||
36 | #include "dvb-usb.h" | ||
37 | |||
38 | #define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver" | ||
39 | |||
40 | extern int dvb_usb_cinergyt2_debug; | ||
41 | |||
42 | #define deb_info(args...) dprintk(dvb_usb_cinergyt2_debug, 0x001, args) | ||
43 | #define deb_xfer(args...) dprintk(dvb_usb_cinergyt2_debug, 0x002, args) | ||
44 | #define deb_pll(args...) dprintk(dvb_usb_cinergyt2_debug, 0x004, args) | ||
45 | #define deb_ts(args...) dprintk(dvb_usb_cinergyt2_debug, 0x008, args) | ||
46 | #define deb_err(args...) dprintk(dvb_usb_cinergyt2_debug, 0x010, args) | ||
47 | #define deb_rc(args...) dprintk(dvb_usb_cinergyt2_debug, 0x020, args) | ||
48 | #define deb_fw(args...) dprintk(dvb_usb_cinergyt2_debug, 0x040, args) | ||
49 | #define deb_mem(args...) dprintk(dvb_usb_cinergyt2_debug, 0x080, args) | ||
50 | #define deb_uxfer(args...) dprintk(dvb_usb_cinergyt2_debug, 0x100, args) | ||
51 | |||
52 | |||
53 | |||
54 | enum cinergyt2_ep1_cmd { | ||
55 | CINERGYT2_EP1_PID_TABLE_RESET = 0x01, | ||
56 | CINERGYT2_EP1_PID_SETUP = 0x02, | ||
57 | CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03, | ||
58 | CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04, | ||
59 | CINERGYT2_EP1_GET_TUNER_STATUS = 0x05, | ||
60 | CINERGYT2_EP1_START_SCAN = 0x06, | ||
61 | CINERGYT2_EP1_CONTINUE_SCAN = 0x07, | ||
62 | CINERGYT2_EP1_GET_RC_EVENTS = 0x08, | ||
63 | CINERGYT2_EP1_SLEEP_MODE = 0x09, | ||
64 | CINERGYT2_EP1_GET_FIRMWARE_VERSION = 0x0A | ||
65 | }; | ||
66 | |||
67 | |||
68 | struct dvbt_get_status_msg { | ||
69 | uint32_t freq; | ||
70 | uint8_t bandwidth; | ||
71 | uint16_t tps; | ||
72 | uint8_t flags; | ||
73 | uint16_t gain; | ||
74 | uint8_t snr; | ||
75 | uint32_t viterbi_error_rate; | ||
76 | uint32_t rs_error_rate; | ||
77 | uint32_t uncorrected_block_count; | ||
78 | uint8_t lock_bits; | ||
79 | uint8_t prev_lock_bits; | ||
80 | } __attribute__((packed)); | ||
81 | |||
82 | |||
83 | struct dvbt_set_parameters_msg { | ||
84 | uint8_t cmd; | ||
85 | uint32_t freq; | ||
86 | uint8_t bandwidth; | ||
87 | uint16_t tps; | ||
88 | uint8_t flags; | ||
89 | } __attribute__((packed)); | ||
90 | |||
91 | |||
92 | extern struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d); | ||
93 | |||
94 | #endif /* _DVB_USB_CINERGYT2_H_ */ | ||
95 | |||
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 563400277a42..406d7fba369d 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c | |||
@@ -36,6 +36,9 @@ | |||
36 | #include "tuner-xc2028.h" | 36 | #include "tuner-xc2028.h" |
37 | #include "tuner-simple.h" | 37 | #include "tuner-simple.h" |
38 | #include "mxl5005s.h" | 38 | #include "mxl5005s.h" |
39 | #include "dib7000p.h" | ||
40 | #include "dib0070.h" | ||
41 | #include "lgs8gl5.h" | ||
39 | 42 | ||
40 | /* debug */ | 43 | /* debug */ |
41 | static int dvb_usb_cxusb_debug; | 44 | static int dvb_usb_cxusb_debug; |
@@ -109,6 +112,25 @@ static void cxusb_nano2_led(struct dvb_usb_device *d, int onoff) | |||
109 | cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40); | 112 | cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40); |
110 | } | 113 | } |
111 | 114 | ||
115 | static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d, | ||
116 | u8 addr, int onoff) | ||
117 | { | ||
118 | u8 o[2] = {addr, onoff}; | ||
119 | u8 i; | ||
120 | int rc; | ||
121 | |||
122 | rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); | ||
123 | |||
124 | if (rc < 0) | ||
125 | return rc; | ||
126 | if (i == 0x01) | ||
127 | return 0; | ||
128 | else { | ||
129 | deb_info("gpio_write failed.\n"); | ||
130 | return -EIO; | ||
131 | } | ||
132 | } | ||
133 | |||
112 | /* I2C */ | 134 | /* I2C */ |
113 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | 135 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
114 | int num) | 136 | int num) |
@@ -262,6 +284,20 @@ static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff) | |||
262 | return rc; | 284 | return rc; |
263 | } | 285 | } |
264 | 286 | ||
287 | static int cxusb_d680_dmb_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
288 | { | ||
289 | int ret; | ||
290 | u8 b; | ||
291 | ret = cxusb_power_ctrl(d, onoff); | ||
292 | if (!onoff) | ||
293 | return ret; | ||
294 | |||
295 | msleep(128); | ||
296 | cxusb_ctrl_msg(d, CMD_DIGITAL, NULL, 0, &b, 1); | ||
297 | msleep(100); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
265 | static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | 301 | static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
266 | { | 302 | { |
267 | u8 buf[2] = { 0x03, 0x00 }; | 303 | u8 buf[2] = { 0x03, 0x00 }; |
@@ -283,6 +319,67 @@ static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
283 | return 0; | 319 | return 0; |
284 | } | 320 | } |
285 | 321 | ||
322 | static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d) | ||
323 | { | ||
324 | int ep = d->props.generic_bulk_ctrl_endpoint; | ||
325 | const int timeout = 100; | ||
326 | const int junk_len = 32; | ||
327 | u8 *junk; | ||
328 | int rd_count; | ||
329 | |||
330 | /* Discard remaining data in video pipe */ | ||
331 | junk = kmalloc(junk_len, GFP_KERNEL); | ||
332 | if (!junk) | ||
333 | return; | ||
334 | while (1) { | ||
335 | if (usb_bulk_msg(d->udev, | ||
336 | usb_rcvbulkpipe(d->udev, ep), | ||
337 | junk, junk_len, &rd_count, timeout) < 0) | ||
338 | break; | ||
339 | if (!rd_count) | ||
340 | break; | ||
341 | } | ||
342 | kfree(junk); | ||
343 | } | ||
344 | |||
345 | static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d) | ||
346 | { | ||
347 | struct usb_data_stream_properties *p = &d->props.adapter[0].stream; | ||
348 | const int timeout = 100; | ||
349 | const int junk_len = p->u.bulk.buffersize; | ||
350 | u8 *junk; | ||
351 | int rd_count; | ||
352 | |||
353 | /* Discard remaining data in video pipe */ | ||
354 | junk = kmalloc(junk_len, GFP_KERNEL); | ||
355 | if (!junk) | ||
356 | return; | ||
357 | while (1) { | ||
358 | if (usb_bulk_msg(d->udev, | ||
359 | usb_rcvbulkpipe(d->udev, p->endpoint), | ||
360 | junk, junk_len, &rd_count, timeout) < 0) | ||
361 | break; | ||
362 | if (!rd_count) | ||
363 | break; | ||
364 | } | ||
365 | kfree(junk); | ||
366 | } | ||
367 | |||
368 | static int cxusb_d680_dmb_streaming_ctrl( | ||
369 | struct dvb_usb_adapter *adap, int onoff) | ||
370 | { | ||
371 | if (onoff) { | ||
372 | u8 buf[2] = { 0x03, 0x00 }; | ||
373 | cxusb_d680_dmb_drain_video(adap->dev); | ||
374 | return cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON, | ||
375 | buf, sizeof(buf), NULL, 0); | ||
376 | } else { | ||
377 | int ret = cxusb_ctrl_msg(adap->dev, | ||
378 | CMD_STREAMING_OFF, NULL, 0, NULL, 0); | ||
379 | return ret; | ||
380 | } | ||
381 | } | ||
382 | |||
286 | static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 383 | static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
287 | { | 384 | { |
288 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | 385 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; |
@@ -335,6 +432,32 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event, | |||
335 | return 0; | 432 | return 0; |
336 | } | 433 | } |
337 | 434 | ||
435 | static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, | ||
436 | int *state) | ||
437 | { | ||
438 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | ||
439 | u8 ircode[2]; | ||
440 | int i; | ||
441 | |||
442 | *event = 0; | ||
443 | *state = REMOTE_NO_KEY_PRESSED; | ||
444 | |||
445 | if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0) | ||
446 | return 0; | ||
447 | |||
448 | for (i = 0; i < d->props.rc_key_map_size; i++) { | ||
449 | if (keymap[i].custom == ircode[0] && | ||
450 | keymap[i].data == ircode[1]) { | ||
451 | *event = keymap[i].event; | ||
452 | *state = REMOTE_KEY_PRESSED; | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | return 0; | ||
459 | } | ||
460 | |||
338 | static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { | 461 | static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { |
339 | { 0xfe, 0x02, KEY_TV }, | 462 | { 0xfe, 0x02, KEY_TV }, |
340 | { 0xfe, 0x0e, KEY_MP3 }, | 463 | { 0xfe, 0x0e, KEY_MP3 }, |
@@ -422,6 +545,44 @@ static struct dvb_usb_rc_key dvico_portable_rc_keys[] = { | |||
422 | { 0xfc, 0x00, KEY_UNKNOWN }, /* HD */ | 545 | { 0xfc, 0x00, KEY_UNKNOWN }, /* HD */ |
423 | }; | 546 | }; |
424 | 547 | ||
548 | static struct dvb_usb_rc_key d680_dmb_rc_keys[] = { | ||
549 | { 0x00, 0x38, KEY_UNKNOWN }, /* TV/AV */ | ||
550 | { 0x08, 0x0c, KEY_ZOOM }, | ||
551 | { 0x08, 0x00, KEY_0 }, | ||
552 | { 0x00, 0x01, KEY_1 }, | ||
553 | { 0x08, 0x02, KEY_2 }, | ||
554 | { 0x00, 0x03, KEY_3 }, | ||
555 | { 0x08, 0x04, KEY_4 }, | ||
556 | { 0x00, 0x05, KEY_5 }, | ||
557 | { 0x08, 0x06, KEY_6 }, | ||
558 | { 0x00, 0x07, KEY_7 }, | ||
559 | { 0x08, 0x08, KEY_8 }, | ||
560 | { 0x00, 0x09, KEY_9 }, | ||
561 | { 0x00, 0x0a, KEY_MUTE }, | ||
562 | { 0x08, 0x29, KEY_BACK }, | ||
563 | { 0x00, 0x12, KEY_CHANNELUP }, | ||
564 | { 0x08, 0x13, KEY_CHANNELDOWN }, | ||
565 | { 0x00, 0x2b, KEY_VOLUMEUP }, | ||
566 | { 0x08, 0x2c, KEY_VOLUMEDOWN }, | ||
567 | { 0x00, 0x20, KEY_UP }, | ||
568 | { 0x08, 0x21, KEY_DOWN }, | ||
569 | { 0x00, 0x11, KEY_LEFT }, | ||
570 | { 0x08, 0x10, KEY_RIGHT }, | ||
571 | { 0x00, 0x0d, KEY_OK }, | ||
572 | { 0x08, 0x1f, KEY_RECORD }, | ||
573 | { 0x00, 0x17, KEY_PLAYPAUSE }, | ||
574 | { 0x08, 0x16, KEY_PLAYPAUSE }, | ||
575 | { 0x00, 0x0b, KEY_STOP }, | ||
576 | { 0x08, 0x27, KEY_FASTFORWARD }, | ||
577 | { 0x00, 0x26, KEY_REWIND }, | ||
578 | { 0x08, 0x1e, KEY_UNKNOWN }, /* Time Shift */ | ||
579 | { 0x00, 0x0e, KEY_UNKNOWN }, /* Snapshot */ | ||
580 | { 0x08, 0x2d, KEY_UNKNOWN }, /* Mouse Cursor */ | ||
581 | { 0x00, 0x0f, KEY_UNKNOWN }, /* Minimize/Maximize */ | ||
582 | { 0x08, 0x14, KEY_UNKNOWN }, /* Shuffle */ | ||
583 | { 0x00, 0x25, KEY_POWER }, | ||
584 | }; | ||
585 | |||
425 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) | 586 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) |
426 | { | 587 | { |
427 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; | 588 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; |
@@ -527,6 +688,24 @@ static struct mxl5005s_config aver_a868r_tuner = { | |||
527 | .AgcMasterByte = 0x00, | 688 | .AgcMasterByte = 0x00, |
528 | }; | 689 | }; |
529 | 690 | ||
691 | /* FIXME: needs tweaking */ | ||
692 | static struct mxl5005s_config d680_dmb_tuner = { | ||
693 | .i2c_address = 0x63, | ||
694 | .if_freq = 36125000UL, | ||
695 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
696 | .agc_mode = MXL_SINGLE_AGC, | ||
697 | .tracking_filter = MXL_TF_C, | ||
698 | .rssi_enable = MXL_RSSI_ENABLE, | ||
699 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
700 | .div_out = MXL_DIV_OUT_4, | ||
701 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
702 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
703 | .top = MXL5005S_TOP_25P2, | ||
704 | .mod_mode = MXL_DIGITAL_MODE, | ||
705 | .if_mode = MXL_ZERO_IF, | ||
706 | .AgcMasterByte = 0x00, | ||
707 | }; | ||
708 | |||
530 | /* Callbacks for DVB USB */ | 709 | /* Callbacks for DVB USB */ |
531 | static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) | 710 | static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) |
532 | { | 711 | { |
@@ -563,7 +742,8 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) | |||
563 | return 0; | 742 | return 0; |
564 | } | 743 | } |
565 | 744 | ||
566 | static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg) | 745 | static int dvico_bluebird_xc2028_callback(void *ptr, int component, |
746 | int command, int arg) | ||
567 | { | 747 | { |
568 | struct dvb_usb_adapter *adap = ptr; | 748 | struct dvb_usb_adapter *adap = ptr; |
569 | struct dvb_usb_device *d = adap->dev; | 749 | struct dvb_usb_device *d = adap->dev; |
@@ -591,14 +771,16 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) | |||
591 | struct xc2028_config cfg = { | 771 | struct xc2028_config cfg = { |
592 | .i2c_adap = &adap->dev->i2c_adap, | 772 | .i2c_adap = &adap->dev->i2c_adap, |
593 | .i2c_addr = 0x61, | 773 | .i2c_addr = 0x61, |
594 | .callback = dvico_bluebird_xc2028_callback, | ||
595 | }; | 774 | }; |
596 | static struct xc2028_ctrl ctl = { | 775 | static struct xc2028_ctrl ctl = { |
597 | .fname = "xc3028-v27.fw", | 776 | .fname = XC2028_DEFAULT_FIRMWARE, |
598 | .max_len = 64, | 777 | .max_len = 64, |
599 | .demod = XC3028_FE_ZARLINK456, | 778 | .demod = XC3028_FE_ZARLINK456, |
600 | }; | 779 | }; |
601 | 780 | ||
781 | /* FIXME: generalize & move to common area */ | ||
782 | adap->fe->callback = dvico_bluebird_xc2028_callback; | ||
783 | |||
602 | fe = dvb_attach(xc2028_attach, adap->fe, &cfg); | 784 | fe = dvb_attach(xc2028_attach, adap->fe, &cfg); |
603 | if (fe == NULL || fe->ops.tuner_ops.set_config == NULL) | 785 | if (fe == NULL || fe->ops.tuner_ops.set_config == NULL) |
604 | return -EIO; | 786 | return -EIO; |
@@ -615,6 +797,14 @@ static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) | |||
615 | return 0; | 797 | return 0; |
616 | } | 798 | } |
617 | 799 | ||
800 | static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap) | ||
801 | { | ||
802 | struct dvb_frontend *fe; | ||
803 | fe = dvb_attach(mxl5005s_attach, adap->fe, | ||
804 | &adap->dev->i2c_adap, &d680_dmb_tuner); | ||
805 | return (fe == NULL) ? -EIO : 0; | ||
806 | } | ||
807 | |||
618 | static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) | 808 | static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) |
619 | { | 809 | { |
620 | u8 b; | 810 | u8 b; |
@@ -726,6 +916,159 @@ no_IR: | |||
726 | return 0; | 916 | return 0; |
727 | } | 917 | } |
728 | 918 | ||
919 | static struct dibx000_agc_config dib7070_agc_config = { | ||
920 | .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, | ||
921 | |||
922 | /* | ||
923 | * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, | ||
924 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | ||
925 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 | ||
926 | */ | ||
927 | .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | | ||
928 | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
929 | .inv_gain = 600, | ||
930 | .time_stabiliz = 10, | ||
931 | .alpha_level = 0, | ||
932 | .thlock = 118, | ||
933 | .wbd_inv = 0, | ||
934 | .wbd_ref = 3530, | ||
935 | .wbd_sel = 1, | ||
936 | .wbd_alpha = 5, | ||
937 | .agc1_max = 65535, | ||
938 | .agc1_min = 0, | ||
939 | .agc2_max = 65535, | ||
940 | .agc2_min = 0, | ||
941 | .agc1_pt1 = 0, | ||
942 | .agc1_pt2 = 40, | ||
943 | .agc1_pt3 = 183, | ||
944 | .agc1_slope1 = 206, | ||
945 | .agc1_slope2 = 255, | ||
946 | .agc2_pt1 = 72, | ||
947 | .agc2_pt2 = 152, | ||
948 | .agc2_slope1 = 88, | ||
949 | .agc2_slope2 = 90, | ||
950 | .alpha_mant = 17, | ||
951 | .alpha_exp = 27, | ||
952 | .beta_mant = 23, | ||
953 | .beta_exp = 51, | ||
954 | .perform_agc_softsplit = 0, | ||
955 | }; | ||
956 | |||
957 | static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { | ||
958 | .internal = 60000, | ||
959 | .sampling = 15000, | ||
960 | .pll_prediv = 1, | ||
961 | .pll_ratio = 20, | ||
962 | .pll_range = 3, | ||
963 | .pll_reset = 1, | ||
964 | .pll_bypass = 0, | ||
965 | .enable_refdiv = 0, | ||
966 | .bypclk_div = 0, | ||
967 | .IO_CLK_en_core = 1, | ||
968 | .ADClkSrc = 1, | ||
969 | .modulo = 2, | ||
970 | /* refsel, sel, freq_15k */ | ||
971 | .sad_cfg = (3 << 14) | (1 << 12) | (524 << 0), | ||
972 | .ifreq = (0 << 25) | 0, | ||
973 | .timf = 20452225, | ||
974 | .xtal_hz = 12000000, | ||
975 | }; | ||
976 | |||
977 | static struct dib7000p_config cxusb_dualdig4_rev2_config = { | ||
978 | .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK, | ||
979 | .output_mpeg2_in_188_bytes = 1, | ||
980 | |||
981 | .agc_config_count = 1, | ||
982 | .agc = &dib7070_agc_config, | ||
983 | .bw = &dib7070_bw_config_12_mhz, | ||
984 | .tuner_is_baseband = 1, | ||
985 | .spur_protect = 1, | ||
986 | |||
987 | .gpio_dir = 0xfcef, | ||
988 | .gpio_val = 0x0110, | ||
989 | |||
990 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | ||
991 | |||
992 | .hostbus_diversity = 1, | ||
993 | }; | ||
994 | |||
995 | static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) | ||
996 | { | ||
997 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) | ||
998 | err("set interface failed"); | ||
999 | |||
1000 | cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0); | ||
1001 | |||
1002 | cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); | ||
1003 | |||
1004 | dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | ||
1005 | &cxusb_dualdig4_rev2_config); | ||
1006 | |||
1007 | adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | ||
1008 | &cxusb_dualdig4_rev2_config); | ||
1009 | if (adap->fe == NULL) | ||
1010 | return -EIO; | ||
1011 | |||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) | ||
1016 | { | ||
1017 | return dib7000p_set_gpio(fe, 8, 0, !onoff); | ||
1018 | } | ||
1019 | |||
1020 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) | ||
1021 | { | ||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1025 | static struct dib0070_config dib7070p_dib0070_config = { | ||
1026 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | ||
1027 | .reset = dib7070_tuner_reset, | ||
1028 | .sleep = dib7070_tuner_sleep, | ||
1029 | .clock_khz = 12000, | ||
1030 | }; | ||
1031 | |||
1032 | struct dib0700_adapter_state { | ||
1033 | int (*set_param_save) (struct dvb_frontend *, | ||
1034 | struct dvb_frontend_parameters *); | ||
1035 | }; | ||
1036 | |||
1037 | static int dib7070_set_param_override(struct dvb_frontend *fe, | ||
1038 | struct dvb_frontend_parameters *fep) | ||
1039 | { | ||
1040 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
1041 | struct dib0700_adapter_state *state = adap->priv; | ||
1042 | |||
1043 | u16 offset; | ||
1044 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
1045 | switch (band) { | ||
1046 | case BAND_VHF: offset = 950; break; | ||
1047 | default: | ||
1048 | case BAND_UHF: offset = 550; break; | ||
1049 | } | ||
1050 | |||
1051 | dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); | ||
1052 | |||
1053 | return state->set_param_save(fe, fep); | ||
1054 | } | ||
1055 | |||
1056 | static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap) | ||
1057 | { | ||
1058 | struct dib0700_adapter_state *st = adap->priv; | ||
1059 | struct i2c_adapter *tun_i2c = | ||
1060 | dib7000p_get_i2c_master(adap->fe, | ||
1061 | DIBX000_I2C_INTERFACE_TUNER, 1); | ||
1062 | |||
1063 | if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, | ||
1064 | &dib7070p_dib0070_config) == NULL) | ||
1065 | return -ENODEV; | ||
1066 | |||
1067 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
1068 | adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override; | ||
1069 | return 0; | ||
1070 | } | ||
1071 | |||
729 | static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) | 1072 | static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) |
730 | { | 1073 | { |
731 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) | 1074 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) |
@@ -751,6 +1094,54 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) | |||
751 | return -EIO; | 1094 | return -EIO; |
752 | } | 1095 | } |
753 | 1096 | ||
1097 | static struct lgs8gl5_config lgs8gl5_cfg = { | ||
1098 | .demod_address = 0x19, | ||
1099 | }; | ||
1100 | |||
1101 | static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) | ||
1102 | { | ||
1103 | struct dvb_usb_device *d = adap->dev; | ||
1104 | int n; | ||
1105 | |||
1106 | /* Select required USB configuration */ | ||
1107 | if (usb_set_interface(d->udev, 0, 0) < 0) | ||
1108 | err("set interface failed"); | ||
1109 | |||
1110 | /* Unblock all USB pipes */ | ||
1111 | usb_clear_halt(d->udev, | ||
1112 | usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | ||
1113 | usb_clear_halt(d->udev, | ||
1114 | usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); | ||
1115 | usb_clear_halt(d->udev, | ||
1116 | usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint)); | ||
1117 | |||
1118 | /* Drain USB pipes to avoid hang after reboot */ | ||
1119 | for (n = 0; n < 5; n++) { | ||
1120 | cxusb_d680_dmb_drain_message(d); | ||
1121 | cxusb_d680_dmb_drain_video(d); | ||
1122 | msleep(200); | ||
1123 | } | ||
1124 | |||
1125 | /* Reset the tuner */ | ||
1126 | if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) { | ||
1127 | err("clear tuner gpio failed"); | ||
1128 | return -EIO; | ||
1129 | } | ||
1130 | msleep(100); | ||
1131 | if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) { | ||
1132 | err("set tuner gpio failed"); | ||
1133 | return -EIO; | ||
1134 | } | ||
1135 | msleep(100); | ||
1136 | |||
1137 | /* Attach frontend */ | ||
1138 | adap->fe = dvb_attach(lgs8gl5_attach, &lgs8gl5_cfg, &d->i2c_adap); | ||
1139 | if (adap->fe == NULL) | ||
1140 | return -EIO; | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
754 | /* | 1145 | /* |
755 | * DViCO has shipped two devices with the same USB ID, but only one of them | 1146 | * DViCO has shipped two devices with the same USB ID, but only one of them |
756 | * needs a firmware download. Check the device class details to see if they | 1147 | * needs a firmware download. Check the device class details to see if they |
@@ -826,9 +1217,11 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties; | |||
826 | static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; | 1217 | static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; |
827 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; | 1218 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; |
828 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; | 1219 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; |
1220 | static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties; | ||
829 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; | 1221 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; |
830 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; | 1222 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; |
831 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; | 1223 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; |
1224 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties; | ||
832 | 1225 | ||
833 | static int cxusb_probe(struct usb_interface *intf, | 1226 | static int cxusb_probe(struct usb_interface *intf, |
834 | const struct usb_device_id *id) | 1227 | const struct usb_device_id *id) |
@@ -852,6 +1245,11 @@ static int cxusb_probe(struct usb_interface *intf, | |||
852 | THIS_MODULE, NULL, adapter_nr) || | 1245 | THIS_MODULE, NULL, adapter_nr) || |
853 | 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, | 1246 | 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, |
854 | THIS_MODULE, NULL, adapter_nr) || | 1247 | THIS_MODULE, NULL, adapter_nr) || |
1248 | 0 == dvb_usb_device_init(intf, | ||
1249 | &cxusb_bluebird_dualdig4_rev2_properties, | ||
1250 | THIS_MODULE, NULL, adapter_nr) || | ||
1251 | 0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties, | ||
1252 | THIS_MODULE, NULL, adapter_nr) || | ||
855 | 0) | 1253 | 0) |
856 | return 0; | 1254 | return 0; |
857 | 1255 | ||
@@ -876,6 +1274,8 @@ static struct usb_device_id cxusb_table [] = { | |||
876 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) }, | 1274 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) }, |
877 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) }, | 1275 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) }, |
878 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) }, | 1276 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) }, |
1277 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) }, | ||
1278 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, | ||
879 | {} /* Terminating entry */ | 1279 | {} /* Terminating entry */ |
880 | }; | 1280 | }; |
881 | MODULE_DEVICE_TABLE (usb, cxusb_table); | 1281 | MODULE_DEVICE_TABLE (usb, cxusb_table); |
@@ -1321,6 +1721,104 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = { | |||
1321 | } | 1721 | } |
1322 | }; | 1722 | }; |
1323 | 1723 | ||
1724 | static | ||
1725 | struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { | ||
1726 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
1727 | |||
1728 | .usb_ctrl = CYPRESS_FX2, | ||
1729 | |||
1730 | .size_of_priv = sizeof(struct cxusb_state), | ||
1731 | |||
1732 | .num_adapters = 1, | ||
1733 | .adapter = { | ||
1734 | { | ||
1735 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
1736 | .frontend_attach = cxusb_dualdig4_rev2_frontend_attach, | ||
1737 | .tuner_attach = cxusb_dualdig4_rev2_tuner_attach, | ||
1738 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
1739 | /* parameter for the MPEG2-data transfer */ | ||
1740 | .stream = { | ||
1741 | .type = USB_BULK, | ||
1742 | .count = 7, | ||
1743 | .endpoint = 0x02, | ||
1744 | .u = { | ||
1745 | .bulk = { | ||
1746 | .buffersize = 4096, | ||
1747 | } | ||
1748 | } | ||
1749 | }, | ||
1750 | }, | ||
1751 | }, | ||
1752 | |||
1753 | .power_ctrl = cxusb_bluebird_power_ctrl, | ||
1754 | |||
1755 | .i2c_algo = &cxusb_i2c_algo, | ||
1756 | |||
1757 | .generic_bulk_ctrl_endpoint = 0x01, | ||
1758 | |||
1759 | .rc_interval = 100, | ||
1760 | .rc_key_map = dvico_mce_rc_keys, | ||
1761 | .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys), | ||
1762 | .rc_query = cxusb_rc_query, | ||
1763 | |||
1764 | .num_device_descs = 1, | ||
1765 | .devices = { | ||
1766 | { "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)", | ||
1767 | { NULL }, | ||
1768 | { &cxusb_table[17], NULL }, | ||
1769 | }, | ||
1770 | } | ||
1771 | }; | ||
1772 | |||
1773 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties = { | ||
1774 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
1775 | |||
1776 | .usb_ctrl = CYPRESS_FX2, | ||
1777 | |||
1778 | .size_of_priv = sizeof(struct cxusb_state), | ||
1779 | |||
1780 | .num_adapters = 1, | ||
1781 | .adapter = { | ||
1782 | { | ||
1783 | .streaming_ctrl = cxusb_d680_dmb_streaming_ctrl, | ||
1784 | .frontend_attach = cxusb_d680_dmb_frontend_attach, | ||
1785 | .tuner_attach = cxusb_d680_dmb_tuner_attach, | ||
1786 | |||
1787 | /* parameter for the MPEG2-data transfer */ | ||
1788 | .stream = { | ||
1789 | .type = USB_BULK, | ||
1790 | .count = 5, | ||
1791 | .endpoint = 0x02, | ||
1792 | .u = { | ||
1793 | .bulk = { | ||
1794 | .buffersize = 8192, | ||
1795 | } | ||
1796 | } | ||
1797 | }, | ||
1798 | }, | ||
1799 | }, | ||
1800 | |||
1801 | .power_ctrl = cxusb_d680_dmb_power_ctrl, | ||
1802 | |||
1803 | .i2c_algo = &cxusb_i2c_algo, | ||
1804 | |||
1805 | .generic_bulk_ctrl_endpoint = 0x01, | ||
1806 | |||
1807 | .rc_interval = 100, | ||
1808 | .rc_key_map = d680_dmb_rc_keys, | ||
1809 | .rc_key_map_size = ARRAY_SIZE(d680_dmb_rc_keys), | ||
1810 | .rc_query = cxusb_d680_dmb_rc_query, | ||
1811 | |||
1812 | .num_device_descs = 1, | ||
1813 | .devices = { | ||
1814 | { | ||
1815 | "Conexant DMB-TH Stick", | ||
1816 | { NULL }, | ||
1817 | { &cxusb_table[18], NULL }, | ||
1818 | }, | ||
1819 | } | ||
1820 | }; | ||
1821 | |||
1324 | static struct usb_driver cxusb_driver = { | 1822 | static struct usb_driver cxusb_driver = { |
1325 | .name = "dvb_usb_cxusb", | 1823 | .name = "dvb_usb_cxusb", |
1326 | .probe = cxusb_probe, | 1824 | .probe = cxusb_probe, |
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 66d4dc6ba46f..739193943c17 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h | |||
@@ -31,6 +31,8 @@ extern int dvb_usb_dib0700_debug; | |||
31 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) | 31 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) |
32 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) | 32 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) |
33 | #define REQUEST_SET_RC 0x11 | 33 | #define REQUEST_SET_RC 0x11 |
34 | #define REQUEST_NEW_I2C_READ 0x12 | ||
35 | #define REQUEST_NEW_I2C_WRITE 0x13 | ||
34 | #define REQUEST_GET_VERSION 0x15 | 36 | #define REQUEST_GET_VERSION 0x15 |
35 | 37 | ||
36 | struct dib0700_state { | 38 | struct dib0700_state { |
@@ -39,6 +41,8 @@ struct dib0700_state { | |||
39 | u8 rc_toggle; | 41 | u8 rc_toggle; |
40 | u8 rc_counter; | 42 | u8 rc_counter; |
41 | u8 is_dib7000pc; | 43 | u8 is_dib7000pc; |
44 | u8 fw_use_new_i2c_api; | ||
45 | u8 disable_streaming_master_mode; | ||
42 | }; | 46 | }; |
43 | 47 | ||
44 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); | 48 | extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 595a04696c87..dd53cee3896d 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c | |||
@@ -82,9 +82,98 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ | |||
82 | } | 82 | } |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * I2C master xfer function | 85 | * I2C master xfer function (supported in 1.20 firmware) |
86 | */ | 86 | */ |
87 | static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num) | 87 | static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, |
88 | int num) | ||
89 | { | ||
90 | /* The new i2c firmware messages are more reliable and in particular | ||
91 | properly support i2c read calls not preceded by a write */ | ||
92 | |||
93 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
94 | uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */ | ||
95 | uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */ | ||
96 | uint8_t en_start = 0; | ||
97 | uint8_t en_stop = 0; | ||
98 | uint8_t buf[255]; /* TBV: malloc ? */ | ||
99 | int result, i; | ||
100 | |||
101 | /* Ensure nobody else hits the i2c bus while we're sending our | ||
102 | sequence of messages, (such as the remote control thread) */ | ||
103 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
104 | return -EAGAIN; | ||
105 | |||
106 | for (i = 0; i < num; i++) { | ||
107 | if (i == 0) { | ||
108 | /* First message in the transaction */ | ||
109 | en_start = 1; | ||
110 | } else if (!(msg[i].flags & I2C_M_NOSTART)) { | ||
111 | /* Device supports repeated-start */ | ||
112 | en_start = 1; | ||
113 | } else { | ||
114 | /* Not the first packet and device doesn't support | ||
115 | repeated start */ | ||
116 | en_start = 0; | ||
117 | } | ||
118 | if (i == (num - 1)) { | ||
119 | /* Last message in the transaction */ | ||
120 | en_stop = 1; | ||
121 | } | ||
122 | |||
123 | if (msg[i].flags & I2C_M_RD) { | ||
124 | /* Read request */ | ||
125 | u16 index, value; | ||
126 | uint8_t i2c_dest; | ||
127 | |||
128 | i2c_dest = (msg[i].addr << 1); | ||
129 | value = ((en_start << 7) | (en_stop << 6) | | ||
130 | (msg[i].len & 0x3F)) << 8 | i2c_dest; | ||
131 | /* I2C ctrl + FE bus; */ | ||
132 | index = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30); | ||
133 | |||
134 | result = usb_control_msg(d->udev, | ||
135 | usb_rcvctrlpipe(d->udev, 0), | ||
136 | REQUEST_NEW_I2C_READ, | ||
137 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
138 | value, index, msg[i].buf, | ||
139 | msg[i].len, | ||
140 | USB_CTRL_GET_TIMEOUT); | ||
141 | if (result < 0) { | ||
142 | err("i2c read error (status = %d)\n", result); | ||
143 | break; | ||
144 | } | ||
145 | } else { | ||
146 | /* Write request */ | ||
147 | buf[0] = REQUEST_NEW_I2C_WRITE; | ||
148 | buf[1] = (msg[i].addr << 1); | ||
149 | buf[2] = (en_start << 7) | (en_stop << 6) | | ||
150 | (msg[i].len & 0x3F); | ||
151 | /* I2C ctrl + FE bus; */ | ||
152 | buf[3] = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30); | ||
153 | /* The Actual i2c payload */ | ||
154 | memcpy(&buf[4], msg[i].buf, msg[i].len); | ||
155 | |||
156 | result = usb_control_msg(d->udev, | ||
157 | usb_sndctrlpipe(d->udev, 0), | ||
158 | REQUEST_NEW_I2C_WRITE, | ||
159 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
160 | 0, 0, buf, msg[i].len + 4, | ||
161 | USB_CTRL_GET_TIMEOUT); | ||
162 | if (result < 0) { | ||
163 | err("i2c write error (status = %d)\n", result); | ||
164 | break; | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | mutex_unlock(&d->i2c_mutex); | ||
169 | return i; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * I2C master xfer function (pre-1.20 firmware) | ||
174 | */ | ||
175 | static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, | ||
176 | struct i2c_msg *msg, int num) | ||
88 | { | 177 | { |
89 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 178 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
90 | int i,len; | 179 | int i,len; |
@@ -124,6 +213,21 @@ static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num | |||
124 | return i; | 213 | return i; |
125 | } | 214 | } |
126 | 215 | ||
216 | static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | ||
217 | int num) | ||
218 | { | ||
219 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
220 | struct dib0700_state *st = d->priv; | ||
221 | |||
222 | if (st->fw_use_new_i2c_api == 1) { | ||
223 | /* User running at least fw 1.20 */ | ||
224 | return dib0700_i2c_xfer_new(adap, msg, num); | ||
225 | } else { | ||
226 | /* Use legacy calls */ | ||
227 | return dib0700_i2c_xfer_legacy(adap, msg, num); | ||
228 | } | ||
229 | } | ||
230 | |||
127 | static u32 dib0700_i2c_func(struct i2c_adapter *adapter) | 231 | static u32 dib0700_i2c_func(struct i2c_adapter *adapter) |
128 | { | 232 | { |
129 | return I2C_FUNC_I2C; | 233 | return I2C_FUNC_I2C; |
@@ -246,7 +350,12 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
246 | 350 | ||
247 | b[0] = REQUEST_ENABLE_VIDEO; | 351 | b[0] = REQUEST_ENABLE_VIDEO; |
248 | b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ | 352 | b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ |
249 | b[2] = (0x01 << 4); /* Master mode */ | 353 | |
354 | if (st->disable_streaming_master_mode == 1) | ||
355 | b[2] = 0x00; | ||
356 | else | ||
357 | b[2] = (0x01 << 4); /* Master mode */ | ||
358 | |||
250 | b[3] = 0x00; | 359 | b[3] = 0x00; |
251 | 360 | ||
252 | deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); | 361 | deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 6c0e5c5f4362..0cfccc24b190 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include "mt2060.h" | 14 | #include "mt2060.h" |
15 | #include "mt2266.h" | 15 | #include "mt2266.h" |
16 | #include "tuner-xc2028.h" | 16 | #include "tuner-xc2028.h" |
17 | #include "xc5000.h" | ||
18 | #include "s5h1411.h" | ||
17 | #include "dib0070.h" | 19 | #include "dib0070.h" |
18 | 20 | ||
19 | static int force_lna_activation; | 21 | static int force_lna_activation; |
@@ -366,7 +368,8 @@ static struct dib7000p_config stk7700ph_dib7700_xc3028_config = { | |||
366 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, | 368 | .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, |
367 | }; | 369 | }; |
368 | 370 | ||
369 | static int stk7700ph_xc3028_callback(void *ptr, int command, int arg) | 371 | static int stk7700ph_xc3028_callback(void *ptr, int component, |
372 | int command, int arg) | ||
370 | { | 373 | { |
371 | struct dvb_usb_adapter *adap = ptr; | 374 | struct dvb_usb_adapter *adap = ptr; |
372 | 375 | ||
@@ -394,7 +397,6 @@ static struct xc2028_ctrl stk7700ph_xc3028_ctrl = { | |||
394 | 397 | ||
395 | static struct xc2028_config stk7700ph_xc3028_config = { | 398 | static struct xc2028_config stk7700ph_xc3028_config = { |
396 | .i2c_addr = 0x61, | 399 | .i2c_addr = 0x61, |
397 | .callback = stk7700ph_xc3028_callback, | ||
398 | .ctrl = &stk7700ph_xc3028_ctrl, | 400 | .ctrl = &stk7700ph_xc3028_ctrl, |
399 | }; | 401 | }; |
400 | 402 | ||
@@ -435,7 +437,9 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) | |||
435 | DIBX000_I2C_INTERFACE_TUNER, 1); | 437 | DIBX000_I2C_INTERFACE_TUNER, 1); |
436 | 438 | ||
437 | stk7700ph_xc3028_config.i2c_adap = tun_i2c; | 439 | stk7700ph_xc3028_config.i2c_adap = tun_i2c; |
438 | stk7700ph_xc3028_config.video_dev = adap; | 440 | |
441 | /* FIXME: generalize & move to common area */ | ||
442 | adap->fe->callback = stk7700ph_xc3028_callback; | ||
439 | 443 | ||
440 | return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config) | 444 | return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config) |
441 | == NULL ? -ENODEV : 0; | 445 | == NULL ? -ENODEV : 0; |
@@ -677,6 +681,43 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = { | |||
677 | { 0x01, 0x7d, KEY_VOLUMEDOWN }, | 681 | { 0x01, 0x7d, KEY_VOLUMEDOWN }, |
678 | { 0x02, 0x42, KEY_CHANNELUP }, | 682 | { 0x02, 0x42, KEY_CHANNELUP }, |
679 | { 0x00, 0x7d, KEY_CHANNELDOWN }, | 683 | { 0x00, 0x7d, KEY_CHANNELDOWN }, |
684 | |||
685 | /* Key codes for Nova-TD "credit card" remote control. */ | ||
686 | { 0x1d, 0x00, KEY_0 }, | ||
687 | { 0x1d, 0x01, KEY_1 }, | ||
688 | { 0x1d, 0x02, KEY_2 }, | ||
689 | { 0x1d, 0x03, KEY_3 }, | ||
690 | { 0x1d, 0x04, KEY_4 }, | ||
691 | { 0x1d, 0x05, KEY_5 }, | ||
692 | { 0x1d, 0x06, KEY_6 }, | ||
693 | { 0x1d, 0x07, KEY_7 }, | ||
694 | { 0x1d, 0x08, KEY_8 }, | ||
695 | { 0x1d, 0x09, KEY_9 }, | ||
696 | { 0x1d, 0x0a, KEY_TEXT }, | ||
697 | { 0x1d, 0x0d, KEY_MENU }, | ||
698 | { 0x1d, 0x0f, KEY_MUTE }, | ||
699 | { 0x1d, 0x10, KEY_VOLUMEUP }, | ||
700 | { 0x1d, 0x11, KEY_VOLUMEDOWN }, | ||
701 | { 0x1d, 0x12, KEY_CHANNEL }, | ||
702 | { 0x1d, 0x14, KEY_UP }, | ||
703 | { 0x1d, 0x15, KEY_DOWN }, | ||
704 | { 0x1d, 0x16, KEY_LEFT }, | ||
705 | { 0x1d, 0x17, KEY_RIGHT }, | ||
706 | { 0x1d, 0x1c, KEY_TV }, | ||
707 | { 0x1d, 0x1e, KEY_NEXT }, | ||
708 | { 0x1d, 0x1f, KEY_BACK }, | ||
709 | { 0x1d, 0x20, KEY_CHANNELUP }, | ||
710 | { 0x1d, 0x21, KEY_CHANNELDOWN }, | ||
711 | { 0x1d, 0x24, KEY_LAST }, | ||
712 | { 0x1d, 0x25, KEY_OK }, | ||
713 | { 0x1d, 0x30, KEY_PAUSE }, | ||
714 | { 0x1d, 0x32, KEY_REWIND }, | ||
715 | { 0x1d, 0x34, KEY_FASTFORWARD }, | ||
716 | { 0x1d, 0x35, KEY_PLAY }, | ||
717 | { 0x1d, 0x36, KEY_STOP }, | ||
718 | { 0x1d, 0x37, KEY_RECORD }, | ||
719 | { 0x1d, 0x3b, KEY_GOTO }, | ||
720 | { 0x1d, 0x3d, KEY_POWER }, | ||
680 | }; | 721 | }; |
681 | 722 | ||
682 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ | 723 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ |
@@ -1078,6 +1119,97 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap) | |||
1078 | return adap->fe == NULL ? -ENODEV : 0; | 1119 | return adap->fe == NULL ? -ENODEV : 0; |
1079 | } | 1120 | } |
1080 | 1121 | ||
1122 | /* S5H1411 */ | ||
1123 | static struct s5h1411_config pinnacle_801e_config = { | ||
1124 | .output_mode = S5H1411_PARALLEL_OUTPUT, | ||
1125 | .gpio = S5H1411_GPIO_OFF, | ||
1126 | .mpeg_timing = S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, | ||
1127 | .qam_if = S5H1411_IF_44000, | ||
1128 | .vsb_if = S5H1411_IF_44000, | ||
1129 | .inversion = S5H1411_INVERSION_OFF, | ||
1130 | .status_mode = S5H1411_DEMODLOCKING | ||
1131 | }; | ||
1132 | |||
1133 | /* Pinnacle PCTV HD Pro 801e GPIOs map: | ||
1134 | GPIO0 - currently unknown | ||
1135 | GPIO1 - xc5000 tuner reset | ||
1136 | GPIO2 - CX25843 sleep | ||
1137 | GPIO3 - currently unknown | ||
1138 | GPIO4 - currently unknown | ||
1139 | GPIO6 - currently unknown | ||
1140 | GPIO7 - currently unknown | ||
1141 | GPIO9 - currently unknown | ||
1142 | GPIO10 - CX25843 reset | ||
1143 | */ | ||
1144 | static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap) | ||
1145 | { | ||
1146 | struct dib0700_state *st = adap->dev->priv; | ||
1147 | |||
1148 | /* Make use of the new i2c functions from FW 1.20 */ | ||
1149 | st->fw_use_new_i2c_api = 1; | ||
1150 | |||
1151 | /* The s5h1411 requires the dib0700 to not be in master mode */ | ||
1152 | st->disable_streaming_master_mode = 1; | ||
1153 | |||
1154 | /* All msleep values taken from Windows USB trace */ | ||
1155 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0); | ||
1156 | dib0700_set_gpio(adap->dev, GPIO3, GPIO_OUT, 0); | ||
1157 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
1158 | msleep(400); | ||
1159 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
1160 | msleep(60); | ||
1161 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
1162 | msleep(30); | ||
1163 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
1164 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
1165 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
1166 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
1167 | dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 0); | ||
1168 | msleep(30); | ||
1169 | |||
1170 | /* Put the CX25843 to sleep for now since we're in digital mode */ | ||
1171 | dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1); | ||
1172 | |||
1173 | /* GPIOs are initialized, do the attach */ | ||
1174 | adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config, | ||
1175 | &adap->dev->i2c_adap); | ||
1176 | return adap->fe == NULL ? -ENODEV : 0; | ||
1177 | } | ||
1178 | |||
1179 | static int dib0700_xc5000_tuner_callback(void *priv, int component, | ||
1180 | int command, int arg) | ||
1181 | { | ||
1182 | struct dvb_usb_adapter *adap = priv; | ||
1183 | |||
1184 | if (command == XC5000_TUNER_RESET) { | ||
1185 | /* Reset the tuner */ | ||
1186 | dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0); | ||
1187 | msleep(330); /* from Windows USB trace */ | ||
1188 | dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1); | ||
1189 | msleep(330); /* from Windows USB trace */ | ||
1190 | } else { | ||
1191 | err("xc5000: unknown tuner callback command: %d\n", command); | ||
1192 | return -EINVAL; | ||
1193 | } | ||
1194 | |||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | static struct xc5000_config s5h1411_xc5000_tunerconfig = { | ||
1199 | .i2c_address = 0x64, | ||
1200 | .if_khz = 5380, | ||
1201 | }; | ||
1202 | |||
1203 | static int xc5000_tuner_attach(struct dvb_usb_adapter *adap) | ||
1204 | { | ||
1205 | /* FIXME: generalize & move to common area */ | ||
1206 | adap->fe->callback = dib0700_xc5000_tuner_callback; | ||
1207 | |||
1208 | return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap, | ||
1209 | &s5h1411_xc5000_tunerconfig) | ||
1210 | == NULL ? -ENODEV : 0; | ||
1211 | } | ||
1212 | |||
1081 | /* DVB-USB and USB stuff follows */ | 1213 | /* DVB-USB and USB stuff follows */ |
1082 | struct usb_device_id dib0700_usb_id_table[] = { | 1214 | struct usb_device_id dib0700_usb_id_table[] = { |
1083 | /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, | 1215 | /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, |
@@ -1119,6 +1251,11 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
1119 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, | 1251 | { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, |
1120 | /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, | 1252 | /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, |
1121 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) }, | 1253 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) }, |
1254 | { USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U8000) }, | ||
1255 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700PH) }, | ||
1256 | { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, | ||
1257 | /* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) }, | ||
1258 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) }, | ||
1122 | { 0 } /* Terminating entry */ | 1259 | { 0 } /* Terminating entry */ |
1123 | }; | 1260 | }; |
1124 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 1261 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
@@ -1126,7 +1263,7 @@ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | |||
1126 | #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ | 1263 | #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ |
1127 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ | 1264 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ |
1128 | .usb_ctrl = DEVICE_SPECIFIC, \ | 1265 | .usb_ctrl = DEVICE_SPECIFIC, \ |
1129 | .firmware = "dvb-usb-dib0700-1.10.fw", \ | 1266 | .firmware = "dvb-usb-dib0700-1.20.fw", \ |
1130 | .download_firmware = dib0700_download_firmware, \ | 1267 | .download_firmware = dib0700_download_firmware, \ |
1131 | .no_reconnect = 1, \ | 1268 | .no_reconnect = 1, \ |
1132 | .size_of_priv = sizeof(struct dib0700_state), \ | 1269 | .size_of_priv = sizeof(struct dib0700_state), \ |
@@ -1293,7 +1430,12 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1293 | { &dib0700_usb_id_table[31], NULL }, | 1430 | { &dib0700_usb_id_table[31], NULL }, |
1294 | { NULL }, | 1431 | { NULL }, |
1295 | } | 1432 | } |
1296 | } | 1433 | }, |
1434 | |||
1435 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
1436 | .rc_key_map = dib0700_rc_keys, | ||
1437 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
1438 | .rc_query = dib0700_rc_query | ||
1297 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 1439 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
1298 | 1440 | ||
1299 | .num_adapters = 1, | 1441 | .num_adapters = 1, |
@@ -1408,7 +1550,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1408 | }, | 1550 | }, |
1409 | }, | 1551 | }, |
1410 | 1552 | ||
1411 | .num_device_descs = 3, | 1553 | .num_device_descs = 5, |
1412 | .devices = { | 1554 | .devices = { |
1413 | { "Terratec Cinergy HT USB XE", | 1555 | { "Terratec Cinergy HT USB XE", |
1414 | { &dib0700_usb_id_table[27], NULL }, | 1556 | { &dib0700_usb_id_table[27], NULL }, |
@@ -1422,6 +1564,47 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1422 | { &dib0700_usb_id_table[32], NULL }, | 1564 | { &dib0700_usb_id_table[32], NULL }, |
1423 | { NULL }, | 1565 | { NULL }, |
1424 | }, | 1566 | }, |
1567 | { "Gigabyte U8000-RH", | ||
1568 | { &dib0700_usb_id_table[37], NULL }, | ||
1569 | { NULL }, | ||
1570 | }, | ||
1571 | { "YUAN High-Tech STK7700PH", | ||
1572 | { &dib0700_usb_id_table[38], NULL }, | ||
1573 | { NULL }, | ||
1574 | }, | ||
1575 | { "Asus My Cinema-U3000Hybrid", | ||
1576 | { &dib0700_usb_id_table[39], NULL }, | ||
1577 | { NULL }, | ||
1578 | }, | ||
1579 | }, | ||
1580 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
1581 | .rc_key_map = dib0700_rc_keys, | ||
1582 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
1583 | .rc_query = dib0700_rc_query | ||
1584 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
1585 | .num_adapters = 1, | ||
1586 | .adapter = { | ||
1587 | { | ||
1588 | .frontend_attach = s5h1411_frontend_attach, | ||
1589 | .tuner_attach = xc5000_tuner_attach, | ||
1590 | |||
1591 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
1592 | |||
1593 | .size_of_priv = sizeof(struct | ||
1594 | dib0700_adapter_state), | ||
1595 | }, | ||
1596 | }, | ||
1597 | |||
1598 | .num_device_descs = 2, | ||
1599 | .devices = { | ||
1600 | { "Pinnacle PCTV HD Pro USB Stick", | ||
1601 | { &dib0700_usb_id_table[40], NULL }, | ||
1602 | { NULL }, | ||
1603 | }, | ||
1604 | { "Pinnacle PCTV HD USB Stick", | ||
1605 | { &dib0700_usb_id_table[41], NULL }, | ||
1606 | { NULL }, | ||
1607 | }, | ||
1425 | }, | 1608 | }, |
1426 | .rc_interval = DEFAULT_RC_INTERVAL, | 1609 | .rc_interval = DEFAULT_RC_INTERVAL, |
1427 | .rc_key_map = dib0700_rc_keys, | 1610 | .rc_key_map = dib0700_rc_keys, |
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c new file mode 100644 index 000000000000..078ce92ca436 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtv5100.c | |||
@@ -0,0 +1,240 @@ | |||
1 | /* | ||
2 | * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T | ||
3 | * | ||
4 | * Copyright (C) 2008 Antoine Jacquet <royale@zerezo.com> | ||
5 | * http://royale.zerezo.com/dtv5100/ | ||
6 | * | ||
7 | * Inspired by gl861.c and au6610.c drivers | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include "dtv5100.h" | ||
25 | #include "zl10353.h" | ||
26 | #include "qt1010.h" | ||
27 | |||
28 | /* debug */ | ||
29 | static int dvb_usb_dtv5100_debug; | ||
30 | module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644); | ||
31 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
32 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
33 | |||
34 | static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
35 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
36 | { | ||
37 | u8 request; | ||
38 | u8 type; | ||
39 | u16 value; | ||
40 | u16 index; | ||
41 | |||
42 | switch (wlen) { | ||
43 | case 1: | ||
44 | /* write { reg }, read { value } */ | ||
45 | request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ : | ||
46 | DTV5100_TUNER_READ); | ||
47 | type = USB_TYPE_VENDOR | USB_DIR_IN; | ||
48 | value = 0; | ||
49 | break; | ||
50 | case 2: | ||
51 | /* write { reg, value } */ | ||
52 | request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE : | ||
53 | DTV5100_TUNER_WRITE); | ||
54 | type = USB_TYPE_VENDOR | USB_DIR_OUT; | ||
55 | value = wbuf[1]; | ||
56 | break; | ||
57 | default: | ||
58 | warn("wlen = %x, aborting.", wlen); | ||
59 | return -EINVAL; | ||
60 | } | ||
61 | index = (addr << 8) + wbuf[0]; | ||
62 | |||
63 | msleep(1); /* avoid I2C errors */ | ||
64 | return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request, | ||
65 | type, value, index, rbuf, rlen, | ||
66 | DTV5100_USB_TIMEOUT); | ||
67 | } | ||
68 | |||
69 | /* I2C */ | ||
70 | static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
71 | int num) | ||
72 | { | ||
73 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
74 | int i; | ||
75 | |||
76 | if (num > 2) | ||
77 | return -EINVAL; | ||
78 | |||
79 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
80 | return -EAGAIN; | ||
81 | |||
82 | for (i = 0; i < num; i++) { | ||
83 | /* write/read request */ | ||
84 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
85 | if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
86 | msg[i].len, msg[i+1].buf, | ||
87 | msg[i+1].len) < 0) | ||
88 | break; | ||
89 | i++; | ||
90 | } else if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
91 | msg[i].len, NULL, 0) < 0) | ||
92 | break; | ||
93 | } | ||
94 | |||
95 | mutex_unlock(&d->i2c_mutex); | ||
96 | return i; | ||
97 | } | ||
98 | |||
99 | static u32 dtv5100_i2c_func(struct i2c_adapter *adapter) | ||
100 | { | ||
101 | return I2C_FUNC_I2C; | ||
102 | } | ||
103 | |||
104 | static struct i2c_algorithm dtv5100_i2c_algo = { | ||
105 | .master_xfer = dtv5100_i2c_xfer, | ||
106 | .functionality = dtv5100_i2c_func, | ||
107 | }; | ||
108 | |||
109 | /* Callbacks for DVB USB */ | ||
110 | static struct zl10353_config dtv5100_zl10353_config = { | ||
111 | .demod_address = DTV5100_DEMOD_ADDR, | ||
112 | .no_tuner = 1, | ||
113 | .parallel_ts = 1, | ||
114 | }; | ||
115 | |||
116 | static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap) | ||
117 | { | ||
118 | adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config, | ||
119 | &adap->dev->i2c_adap); | ||
120 | if (adap->fe == NULL) | ||
121 | return -EIO; | ||
122 | |||
123 | /* disable i2c gate, or it won't work... is this safe? */ | ||
124 | adap->fe->ops.i2c_gate_ctrl = NULL; | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static struct qt1010_config dtv5100_qt1010_config = { | ||
130 | .i2c_address = DTV5100_TUNER_ADDR | ||
131 | }; | ||
132 | |||
133 | static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap) | ||
134 | { | ||
135 | return dvb_attach(qt1010_attach, | ||
136 | adap->fe, &adap->dev->i2c_adap, | ||
137 | &dtv5100_qt1010_config) == NULL ? -ENODEV : 0; | ||
138 | } | ||
139 | |||
140 | /* DVB USB Driver stuff */ | ||
141 | static struct dvb_usb_device_properties dtv5100_properties; | ||
142 | |||
143 | static int dtv5100_probe(struct usb_interface *intf, | ||
144 | const struct usb_device_id *id) | ||
145 | { | ||
146 | int i, ret; | ||
147 | struct usb_device *udev = interface_to_usbdev(intf); | ||
148 | |||
149 | /* initialize non qt1010/zl10353 part? */ | ||
150 | for (i = 0; dtv5100_init[i].request; i++) { | ||
151 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
152 | dtv5100_init[i].request, | ||
153 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
154 | dtv5100_init[i].value, | ||
155 | dtv5100_init[i].index, NULL, 0, | ||
156 | DTV5100_USB_TIMEOUT); | ||
157 | if (ret) | ||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | ret = dvb_usb_device_init(intf, &dtv5100_properties, | ||
162 | THIS_MODULE, NULL, adapter_nr); | ||
163 | if (ret) | ||
164 | return ret; | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static struct usb_device_id dtv5100_table[] = { | ||
170 | { USB_DEVICE(0x06be, 0xa232) }, | ||
171 | { } /* Terminating entry */ | ||
172 | }; | ||
173 | MODULE_DEVICE_TABLE(usb, dtv5100_table); | ||
174 | |||
175 | static struct dvb_usb_device_properties dtv5100_properties = { | ||
176 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
177 | .usb_ctrl = DEVICE_SPECIFIC, | ||
178 | |||
179 | .size_of_priv = 0, | ||
180 | |||
181 | .num_adapters = 1, | ||
182 | .adapter = {{ | ||
183 | .frontend_attach = dtv5100_frontend_attach, | ||
184 | .tuner_attach = dtv5100_tuner_attach, | ||
185 | |||
186 | .stream = { | ||
187 | .type = USB_BULK, | ||
188 | .count = 8, | ||
189 | .endpoint = 0x82, | ||
190 | .u = { | ||
191 | .bulk = { | ||
192 | .buffersize = 4096, | ||
193 | } | ||
194 | } | ||
195 | }, | ||
196 | } }, | ||
197 | |||
198 | .i2c_algo = &dtv5100_i2c_algo, | ||
199 | |||
200 | .num_device_descs = 1, | ||
201 | .devices = { | ||
202 | { | ||
203 | .name = "AME DTV-5100 USB2.0 DVB-T", | ||
204 | .cold_ids = { NULL }, | ||
205 | .warm_ids = { &dtv5100_table[0], NULL }, | ||
206 | }, | ||
207 | } | ||
208 | }; | ||
209 | |||
210 | static struct usb_driver dtv5100_driver = { | ||
211 | .name = "dvb_usb_dtv5100", | ||
212 | .probe = dtv5100_probe, | ||
213 | .disconnect = dvb_usb_device_exit, | ||
214 | .id_table = dtv5100_table, | ||
215 | }; | ||
216 | |||
217 | /* module stuff */ | ||
218 | static int __init dtv5100_module_init(void) | ||
219 | { | ||
220 | int ret; | ||
221 | |||
222 | ret = usb_register(&dtv5100_driver); | ||
223 | if (ret) | ||
224 | err("usb_register failed. Error number %d", ret); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | static void __exit dtv5100_module_exit(void) | ||
230 | { | ||
231 | /* deregister this driver from the USB subsystem */ | ||
232 | usb_deregister(&dtv5100_driver); | ||
233 | } | ||
234 | |||
235 | module_init(dtv5100_module_init); | ||
236 | module_exit(dtv5100_module_exit); | ||
237 | |||
238 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
239 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
240 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.h b/drivers/media/dvb/dvb-usb/dtv5100.h new file mode 100644 index 000000000000..93e96e04a82a --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtv5100.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T | ||
3 | * | ||
4 | * Copyright (C) 2008 Antoine Jacquet <royale@zerezo.com> | ||
5 | * http://royale.zerezo.com/dtv5100/ | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #ifndef _DVB_USB_DTV5100_H_ | ||
23 | #define _DVB_USB_DTV5100_H_ | ||
24 | |||
25 | #define DVB_USB_LOG_PREFIX "dtv5100" | ||
26 | #include "dvb-usb.h" | ||
27 | |||
28 | #define DTV5100_USB_TIMEOUT 500 | ||
29 | |||
30 | #define DTV5100_DEMOD_ADDR 0x00 | ||
31 | #define DTV5100_DEMOD_WRITE 0xc0 | ||
32 | #define DTV5100_DEMOD_READ 0xc1 | ||
33 | |||
34 | #define DTV5100_TUNER_ADDR 0xc4 | ||
35 | #define DTV5100_TUNER_WRITE 0xc7 | ||
36 | #define DTV5100_TUNER_READ 0xc8 | ||
37 | |||
38 | #define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/" | ||
39 | #define DRIVER_DESC "AME DTV-5100 USB2.0 DVB-T" | ||
40 | |||
41 | static struct { | ||
42 | u8 request; | ||
43 | u8 value; | ||
44 | u16 index; | ||
45 | } dtv5100_init[] = { | ||
46 | { 0x000000c5, 0x00000000, 0x00000001 }, | ||
47 | { 0x000000c5, 0x00000001, 0x00000001 }, | ||
48 | { } /* Terminating entry */ | ||
49 | }; | ||
50 | |||
51 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 03dfb9f2fe30..7380b94b3b36 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define USB_VID_AVERMEDIA 0x07ca | 22 | #define USB_VID_AVERMEDIA 0x07ca |
23 | #define USB_VID_COMPRO 0x185b | 23 | #define USB_VID_COMPRO 0x185b |
24 | #define USB_VID_COMPRO_UNK 0x145f | 24 | #define USB_VID_COMPRO_UNK 0x145f |
25 | #define USB_VID_CONEXANT 0x0572 | ||
25 | #define USB_VID_CYPRESS 0x04b4 | 26 | #define USB_VID_CYPRESS 0x04b4 |
26 | #define USB_VID_DIBCOM 0x10b8 | 27 | #define USB_VID_DIBCOM 0x10b8 |
27 | #define USB_VID_DPOSH 0x1498 | 28 | #define USB_VID_DPOSH 0x1498 |
@@ -33,16 +34,19 @@ | |||
33 | #define USB_VID_HAUPPAUGE 0x2040 | 34 | #define USB_VID_HAUPPAUGE 0x2040 |
34 | #define USB_VID_HYPER_PALTEK 0x1025 | 35 | #define USB_VID_HYPER_PALTEK 0x1025 |
35 | #define USB_VID_KWORLD 0xeb2a | 36 | #define USB_VID_KWORLD 0xeb2a |
37 | #define USB_VID_KWORLD_2 0x1b80 | ||
36 | #define USB_VID_KYE 0x0458 | 38 | #define USB_VID_KYE 0x0458 |
37 | #define USB_VID_LEADTEK 0x0413 | 39 | #define USB_VID_LEADTEK 0x0413 |
38 | #define USB_VID_LITEON 0x04ca | 40 | #define USB_VID_LITEON 0x04ca |
39 | #define USB_VID_MEDION 0x1660 | 41 | #define USB_VID_MEDION 0x1660 |
40 | #define USB_VID_MIGLIA 0x18f3 | 42 | #define USB_VID_MIGLIA 0x18f3 |
41 | #define USB_VID_MSI 0x0db0 | 43 | #define USB_VID_MSI 0x0db0 |
44 | #define USB_VID_MSI_2 0x1462 | ||
42 | #define USB_VID_OPERA1 0x695c | 45 | #define USB_VID_OPERA1 0x695c |
43 | #define USB_VID_PINNACLE 0x2304 | 46 | #define USB_VID_PINNACLE 0x2304 |
44 | #define USB_VID_TECHNOTREND 0x0b48 | 47 | #define USB_VID_TECHNOTREND 0x0b48 |
45 | #define USB_VID_TERRATEC 0x0ccd | 48 | #define USB_VID_TERRATEC 0x0ccd |
49 | #define USB_VID_TELESTAR 0x10b9 | ||
46 | #define USB_VID_VISIONPLUS 0x13d3 | 50 | #define USB_VID_VISIONPLUS 0x13d3 |
47 | #define USB_VID_TWINHAN 0x1822 | 51 | #define USB_VID_TWINHAN 0x1822 |
48 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 | 52 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 |
@@ -50,15 +54,18 @@ | |||
50 | #define USB_VID_WIDEVIEW 0x14aa | 54 | #define USB_VID_WIDEVIEW 0x14aa |
51 | #define USB_VID_GIGABYTE 0x1044 | 55 | #define USB_VID_GIGABYTE 0x1044 |
52 | #define USB_VID_YUAN 0x1164 | 56 | #define USB_VID_YUAN 0x1164 |
53 | 57 | #define USB_VID_XTENSIONS 0x1ae7 | |
54 | 58 | ||
55 | /* Product IDs */ | 59 | /* Product IDs */ |
56 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 | 60 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 |
57 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 | 61 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 |
58 | #define USB_PID_AFATECH_AF9005 0x9020 | 62 | #define USB_PID_AFATECH_AF9005 0x9020 |
63 | #define USB_PID_AFATECH_AF9015_9015 0x9015 | ||
64 | #define USB_PID_AFATECH_AF9015_9016 0x9016 | ||
59 | #define USB_VID_ALINK_DTU 0xf170 | 65 | #define USB_VID_ALINK_DTU 0xf170 |
60 | #define USB_PID_ANSONIC_DVBT_USB 0x6000 | 66 | #define USB_PID_ANSONIC_DVBT_USB 0x6000 |
61 | #define USB_PID_ANYSEE 0x861f | 67 | #define USB_PID_ANYSEE 0x861f |
68 | #define USB_PID_AZUREWAVE_AD_TU700 0x3237 | ||
62 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 | 69 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 |
63 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 | 70 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 |
64 | #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 | 71 | #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 |
@@ -69,6 +76,7 @@ | |||
69 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | 76 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d |
70 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 | 77 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 |
71 | #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 | 78 | #define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80 |
79 | #define USB_PID_CONEXANT_D680_DMB 0x86d6 | ||
72 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 | 80 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 |
73 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 | 81 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 |
74 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | 82 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 |
@@ -87,9 +95,12 @@ | |||
87 | #define USB_PID_UNIWILL_STK7700P 0x6003 | 95 | #define USB_PID_UNIWILL_STK7700P 0x6003 |
88 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | 96 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 |
89 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 | 97 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 |
98 | #define USB_PID_KWORLD_399U 0xe399 | ||
99 | #define USB_PID_KWORLD_PC160_2T 0xc160 | ||
90 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | 100 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de |
91 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df | 101 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df |
92 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 | 102 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 |
103 | #define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069 | ||
93 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 | 104 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 |
94 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 | 105 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 |
95 | #define USB_PID_TWINHAN_VP7020_COLD 0x3203 | 106 | #define USB_PID_TWINHAN_VP7020_COLD 0x3203 |
@@ -98,6 +109,7 @@ | |||
98 | #define USB_PID_TWINHAN_VP7045_WARM 0x3206 | 109 | #define USB_PID_TWINHAN_VP7045_WARM 0x3206 |
99 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 | 110 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 |
100 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 | 111 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 |
112 | #define USB_PID_TINYTWIN 0x3226 | ||
101 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 | 113 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 |
102 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 | 114 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 |
103 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 | 115 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 |
@@ -144,6 +156,9 @@ | |||
144 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039 | 156 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039 |
145 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039 | 157 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039 |
146 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039 | 158 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039 |
159 | #define USB_PID_AVERMEDIA_VOLAR_X 0xa815 | ||
160 | #define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150 | ||
161 | #define USB_PID_AVERMEDIA_A309 0xa309 | ||
147 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 | 162 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 |
148 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a | 163 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a |
149 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 | 164 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 |
@@ -153,8 +168,11 @@ | |||
153 | #define USB_PID_PINNACLE_PCTV2000E 0x022c | 168 | #define USB_PID_PINNACLE_PCTV2000E 0x022c |
154 | #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 | 169 | #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 |
155 | #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229 | 170 | #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229 |
171 | #define USB_PID_PINNACLE_PCTV71E 0x022b | ||
156 | #define USB_PID_PINNACLE_PCTV72E 0x0236 | 172 | #define USB_PID_PINNACLE_PCTV72E 0x0236 |
157 | #define USB_PID_PINNACLE_PCTV73E 0x0237 | 173 | #define USB_PID_PINNACLE_PCTV73E 0x0237 |
174 | #define USB_PID_PINNACLE_PCTV801E 0x023a | ||
175 | #define USB_PID_PINNACLE_PCTV801E_SE 0x023b | ||
158 | #define USB_PID_PCTV_200E 0x020e | 176 | #define USB_PID_PCTV_200E 0x020e |
159 | #define USB_PID_PCTV_400E 0x020f | 177 | #define USB_PID_PCTV_400E 0x020f |
160 | #define USB_PID_PCTV_450E 0x0222 | 178 | #define USB_PID_PCTV_450E 0x0222 |
@@ -171,6 +189,7 @@ | |||
171 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 | 189 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 |
172 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 | 190 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 |
173 | #define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78 | 191 | #define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78 |
192 | #define USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2 0xdb98 | ||
174 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70 | 193 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70 |
175 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71 | 194 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71 |
176 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 | 195 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 |
@@ -190,6 +209,7 @@ | |||
190 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 | 209 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 |
191 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 | 210 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 |
192 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 | 211 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2 0x6f01 |
212 | #define USB_PID_WINFAST_DTV_DONGLE_GOLD 0x6029 | ||
193 | #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 | 213 | #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 |
194 | #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 | 214 | #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 |
195 | #define USB_PID_GENPIX_8PSK_REV_2 0x0202 | 215 | #define USB_PID_GENPIX_8PSK_REV_2 0x0202 |
@@ -197,14 +217,21 @@ | |||
197 | #define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204 | 217 | #define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204 |
198 | #define USB_PID_SIGMATEK_DVB_110 0x6610 | 218 | #define USB_PID_SIGMATEK_DVB_110 0x6610 |
199 | #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 | 219 | #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 |
220 | #define USB_PID_MSI_DIGIVOX_DUO 0x8801 | ||
200 | #define USB_PID_OPERA1_COLD 0x2830 | 221 | #define USB_PID_OPERA1_COLD 0x2830 |
201 | #define USB_PID_OPERA1_WARM 0x3829 | 222 | #define USB_PID_OPERA1_WARM 0x3829 |
202 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 | 223 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 |
203 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 | 224 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 |
204 | #define USB_PID_GIGABYTE_U7000 0x7001 | 225 | #define USB_PID_GIGABYTE_U7000 0x7001 |
226 | #define USB_PID_GIGABYTE_U8000 0x7002 | ||
205 | #define USB_PID_ASUS_U3000 0x171f | 227 | #define USB_PID_ASUS_U3000 0x171f |
228 | #define USB_PID_ASUS_U3000H 0x1736 | ||
206 | #define USB_PID_ASUS_U3100 0x173f | 229 | #define USB_PID_ASUS_U3100 0x173f |
207 | #define USB_PID_YUAN_EC372S 0x1edc | 230 | #define USB_PID_YUAN_EC372S 0x1edc |
231 | #define USB_PID_YUAN_STK7700PH 0x1f08 | ||
208 | #define USB_PID_DW2102 0x2102 | 232 | #define USB_PID_DW2102 0x2102 |
233 | #define USB_PID_XTENSIONS_XD_380 0x0381 | ||
234 | #define USB_PID_TELESTAR_STARSTICK_2 0x8000 | ||
235 | #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 | ||
209 | 236 | ||
210 | #endif | 237 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index a4d898b44e55..ca53df61caa8 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* DVB USB framework compliant Linux driver for the DVBWorld DVB-S 2102 Card | 1 | /* DVB USB framework compliant Linux driver for the |
2 | * DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card | ||
2 | * | 3 | * |
3 | * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) | 4 | * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) |
4 | * | 5 | * |
@@ -10,62 +11,74 @@ | |||
10 | */ | 11 | */ |
11 | #include <linux/version.h> | 12 | #include <linux/version.h> |
12 | #include "dw2102.h" | 13 | #include "dw2102.h" |
14 | #include "si21xx.h" | ||
13 | #include "stv0299.h" | 15 | #include "stv0299.h" |
14 | #include "z0194a.h" | 16 | #include "z0194a.h" |
17 | #include "stv0288.h" | ||
18 | #include "stb6000.h" | ||
19 | #include "eds1547.h" | ||
20 | #include "cx24116.h" | ||
15 | 21 | ||
16 | #ifndef USB_PID_DW2102 | 22 | #ifndef USB_PID_DW2102 |
17 | #define USB_PID_DW2102 0x2102 | 23 | #define USB_PID_DW2102 0x2102 |
18 | #endif | 24 | #endif |
19 | 25 | ||
20 | #define DW2102_READ_MSG 0 | 26 | #ifndef USB_PID_DW2104 |
21 | #define DW2102_WRITE_MSG 1 | 27 | #define USB_PID_DW2104 0x2104 |
28 | #endif | ||
29 | |||
30 | #define DW210X_READ_MSG 0 | ||
31 | #define DW210X_WRITE_MSG 1 | ||
22 | 32 | ||
23 | #define REG_1F_SYMBOLRATE_BYTE0 0x1f | 33 | #define REG_1F_SYMBOLRATE_BYTE0 0x1f |
24 | #define REG_20_SYMBOLRATE_BYTE1 0x20 | 34 | #define REG_20_SYMBOLRATE_BYTE1 0x20 |
25 | #define REG_21_SYMBOLRATE_BYTE2 0x21 | 35 | #define REG_21_SYMBOLRATE_BYTE2 0x21 |
26 | 36 | /* on my own*/ | |
27 | #define DW2102_VOLTAGE_CTRL (0x1800) | 37 | #define DW2102_VOLTAGE_CTRL (0x1800) |
28 | #define DW2102_RC_QUERY (0x1a00) | 38 | #define DW2102_RC_QUERY (0x1a00) |
29 | 39 | ||
30 | struct dw2102_state { | 40 | struct dw210x_state { |
31 | u32 last_key_pressed; | 41 | u32 last_key_pressed; |
32 | }; | 42 | }; |
33 | struct dw2102_rc_keys { | 43 | struct dw210x_rc_keys { |
34 | u32 keycode; | 44 | u32 keycode; |
35 | u32 event; | 45 | u32 event; |
36 | }; | 46 | }; |
37 | 47 | ||
48 | /* debug */ | ||
49 | static int dvb_usb_dw2102_debug; | ||
50 | module_param_named(debug, dvb_usb_dw2102_debug, int, 0644); | ||
51 | MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS); | ||
52 | |||
38 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 53 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
39 | 54 | ||
40 | static int dw2102_op_rw(struct usb_device *dev, u8 request, u16 value, | 55 | static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, |
41 | u8 *data, u16 len, int flags) | 56 | u16 index, u8 * data, u16 len, int flags) |
42 | { | 57 | { |
43 | int ret; | 58 | int ret; |
44 | u8 u8buf[len]; | 59 | u8 u8buf[len]; |
45 | 60 | ||
46 | unsigned int pipe = (flags == DW2102_READ_MSG) ? | 61 | unsigned int pipe = (flags == DW210X_READ_MSG) ? |
47 | usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); | 62 | usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); |
48 | u8 request_type = (flags == DW2102_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; | 63 | u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; |
49 | 64 | ||
50 | if (flags == DW2102_WRITE_MSG) | 65 | if (flags == DW210X_WRITE_MSG) |
51 | memcpy(u8buf, data, len); | 66 | memcpy(u8buf, data, len); |
52 | ret = usb_control_msg(dev, pipe, request, | 67 | ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, |
53 | request_type | USB_TYPE_VENDOR, value, 0 , u8buf, len, 2000); | 68 | value, index , u8buf, len, 2000); |
54 | 69 | ||
55 | if (flags == DW2102_READ_MSG) | 70 | if (flags == DW210X_READ_MSG) |
56 | memcpy(data, u8buf, len); | 71 | memcpy(data, u8buf, len); |
57 | return ret; | 72 | return ret; |
58 | } | 73 | } |
59 | 74 | ||
60 | /* I2C */ | 75 | /* I2C */ |
61 | |||
62 | static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | 76 | static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
63 | int num) | 77 | int num) |
64 | { | 78 | { |
65 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 79 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
66 | int i = 0, ret = 0; | 80 | int i = 0, ret = 0; |
67 | u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; | 81 | u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; |
68 | u8 request; | ||
69 | u16 value; | 82 | u16 value; |
70 | 83 | ||
71 | if (!d) | 84 | if (!d) |
@@ -76,14 +89,12 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); | |||
76 | switch (num) { | 89 | switch (num) { |
77 | case 2: | 90 | case 2: |
78 | /* read stv0299 register */ | 91 | /* read stv0299 register */ |
79 | request = 0xb5; | ||
80 | value = msg[0].buf[0];/* register */ | 92 | value = msg[0].buf[0];/* register */ |
81 | for (i = 0; i < msg[1].len; i++) { | 93 | for (i = 0; i < msg[1].len; i++) { |
82 | value = value + i; | 94 | value = value + i; |
83 | ret = dw2102_op_rw(d->udev, 0xb5, | 95 | ret = dw210x_op_rw(d->udev, 0xb5, value, 0, |
84 | value, buf6, 2, DW2102_READ_MSG); | 96 | buf6, 2, DW210X_READ_MSG); |
85 | msg[1].buf[i] = buf6[0]; | 97 | msg[1].buf[i] = buf6[0]; |
86 | |||
87 | } | 98 | } |
88 | break; | 99 | break; |
89 | case 1: | 100 | case 1: |
@@ -93,8 +104,8 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); | |||
93 | buf6[0] = 0x2a; | 104 | buf6[0] = 0x2a; |
94 | buf6[1] = msg[0].buf[0]; | 105 | buf6[1] = msg[0].buf[0]; |
95 | buf6[2] = msg[0].buf[1]; | 106 | buf6[2] = msg[0].buf[1]; |
96 | ret = dw2102_op_rw(d->udev, 0xb2, | 107 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, |
97 | 0, buf6, 3, DW2102_WRITE_MSG); | 108 | buf6, 3, DW210X_WRITE_MSG); |
98 | break; | 109 | break; |
99 | case 0x60: | 110 | case 0x60: |
100 | if (msg[0].flags == 0) { | 111 | if (msg[0].flags == 0) { |
@@ -106,26 +117,26 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); | |||
106 | buf6[4] = msg[0].buf[1]; | 117 | buf6[4] = msg[0].buf[1]; |
107 | buf6[5] = msg[0].buf[2]; | 118 | buf6[5] = msg[0].buf[2]; |
108 | buf6[6] = msg[0].buf[3]; | 119 | buf6[6] = msg[0].buf[3]; |
109 | ret = dw2102_op_rw(d->udev, 0xb2, | 120 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, |
110 | 0, buf6, 7, DW2102_WRITE_MSG); | 121 | buf6, 7, DW210X_WRITE_MSG); |
111 | } else { | 122 | } else { |
112 | /* write to tuner pll */ | 123 | /* read from tuner */ |
113 | ret = dw2102_op_rw(d->udev, 0xb5, | 124 | ret = dw210x_op_rw(d->udev, 0xb5, 0, 0, |
114 | 0, buf6, 1, DW2102_READ_MSG); | 125 | buf6, 1, DW210X_READ_MSG); |
115 | msg[0].buf[0] = buf6[0]; | 126 | msg[0].buf[0] = buf6[0]; |
116 | } | 127 | } |
117 | break; | 128 | break; |
118 | case (DW2102_RC_QUERY): | 129 | case (DW2102_RC_QUERY): |
119 | ret = dw2102_op_rw(d->udev, 0xb8, | 130 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, |
120 | 0, buf6, 2, DW2102_READ_MSG); | 131 | buf6, 2, DW210X_READ_MSG); |
121 | msg[0].buf[0] = buf6[0]; | 132 | msg[0].buf[0] = buf6[0]; |
122 | msg[0].buf[1] = buf6[1]; | 133 | msg[0].buf[1] = buf6[1]; |
123 | break; | 134 | break; |
124 | case (DW2102_VOLTAGE_CTRL): | 135 | case (DW2102_VOLTAGE_CTRL): |
125 | buf6[0] = 0x30; | 136 | buf6[0] = 0x30; |
126 | buf6[1] = msg[0].buf[0]; | 137 | buf6[1] = msg[0].buf[0]; |
127 | ret = dw2102_op_rw(d->udev, 0xb2, | 138 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, |
128 | 0, buf6, 2, DW2102_WRITE_MSG); | 139 | buf6, 2, DW210X_WRITE_MSG); |
129 | break; | 140 | break; |
130 | } | 141 | } |
131 | 142 | ||
@@ -136,17 +147,265 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap); | |||
136 | return num; | 147 | return num; |
137 | } | 148 | } |
138 | 149 | ||
139 | static u32 dw2102_i2c_func(struct i2c_adapter *adapter) | 150 | static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, |
151 | struct i2c_msg msg[], int num) | ||
152 | { | ||
153 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
154 | int ret = 0; | ||
155 | u8 buf6[] = {0, 0, 0, 0, 0, 0, 0}; | ||
156 | |||
157 | if (!d) | ||
158 | return -ENODEV; | ||
159 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
160 | return -EAGAIN; | ||
161 | |||
162 | switch (num) { | ||
163 | case 2: | ||
164 | /* read si2109 register by number */ | ||
165 | buf6[0] = 0xd0; | ||
166 | buf6[1] = msg[0].len; | ||
167 | buf6[2] = msg[0].buf[0]; | ||
168 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
169 | buf6, msg[0].len + 2, DW210X_WRITE_MSG); | ||
170 | /* read si2109 register */ | ||
171 | ret = dw210x_op_rw(d->udev, 0xc3, 0xd0, 0, | ||
172 | buf6, msg[1].len + 2, DW210X_READ_MSG); | ||
173 | memcpy(msg[1].buf, buf6 + 2, msg[1].len); | ||
174 | |||
175 | break; | ||
176 | case 1: | ||
177 | switch (msg[0].addr) { | ||
178 | case 0x68: | ||
179 | /* write to si2109 register */ | ||
180 | buf6[0] = 0xd0; | ||
181 | buf6[1] = msg[0].len; | ||
182 | memcpy(buf6 + 2, msg[0].buf, msg[0].len); | ||
183 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6, | ||
184 | msg[0].len + 2, DW210X_WRITE_MSG); | ||
185 | break; | ||
186 | case(DW2102_RC_QUERY): | ||
187 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
188 | buf6, 2, DW210X_READ_MSG); | ||
189 | msg[0].buf[0] = buf6[0]; | ||
190 | msg[0].buf[1] = buf6[1]; | ||
191 | break; | ||
192 | case(DW2102_VOLTAGE_CTRL): | ||
193 | buf6[0] = 0x30; | ||
194 | buf6[1] = msg[0].buf[0]; | ||
195 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
196 | buf6, 2, DW210X_WRITE_MSG); | ||
197 | break; | ||
198 | } | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | mutex_unlock(&d->i2c_mutex); | ||
203 | return num; | ||
204 | } | ||
205 | static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) | ||
206 | { | ||
207 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
208 | int ret = 0; | ||
209 | |||
210 | if (!d) | ||
211 | return -ENODEV; | ||
212 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
213 | return -EAGAIN; | ||
214 | |||
215 | switch (num) { | ||
216 | case 2: { | ||
217 | /* read */ | ||
218 | /* first write first register number */ | ||
219 | u8 ibuf [msg[1].len + 2], obuf[3]; | ||
220 | obuf[0] = 0xd0; | ||
221 | obuf[1] = msg[0].len; | ||
222 | obuf[2] = msg[0].buf[0]; | ||
223 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
224 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
225 | /* second read registers */ | ||
226 | ret = dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0, | ||
227 | ibuf, msg[1].len + 2, DW210X_READ_MSG); | ||
228 | memcpy(msg[1].buf, ibuf + 2, msg[1].len); | ||
229 | |||
230 | break; | ||
231 | } | ||
232 | case 1: | ||
233 | switch (msg[0].addr) { | ||
234 | case 0x68: { | ||
235 | /* write to register */ | ||
236 | u8 obuf[msg[0].len + 2]; | ||
237 | obuf[0] = 0xd0; | ||
238 | obuf[1] = msg[0].len; | ||
239 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
240 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
241 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
242 | break; | ||
243 | } | ||
244 | case 0x61: { | ||
245 | /* write to tuner */ | ||
246 | u8 obuf[msg[0].len + 2]; | ||
247 | obuf[0] = 0xc2; | ||
248 | obuf[1] = msg[0].len; | ||
249 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
250 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
251 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
252 | break; | ||
253 | } | ||
254 | case(DW2102_RC_QUERY): { | ||
255 | u8 ibuf[2]; | ||
256 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
257 | ibuf, 2, DW210X_READ_MSG); | ||
258 | memcpy(msg[0].buf, ibuf , 2); | ||
259 | break; | ||
260 | } | ||
261 | case(DW2102_VOLTAGE_CTRL): { | ||
262 | u8 obuf[2]; | ||
263 | obuf[0] = 0x30; | ||
264 | obuf[1] = msg[0].buf[0]; | ||
265 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
266 | obuf, 2, DW210X_WRITE_MSG); | ||
267 | break; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | break; | ||
272 | } | ||
273 | |||
274 | mutex_unlock(&d->i2c_mutex); | ||
275 | return num; | ||
276 | } | ||
277 | |||
278 | static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) | ||
279 | { | ||
280 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
281 | int ret = 0; | ||
282 | int len, i; | ||
283 | |||
284 | if (!d) | ||
285 | return -ENODEV; | ||
286 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
287 | return -EAGAIN; | ||
288 | |||
289 | switch (num) { | ||
290 | case 2: { | ||
291 | /* read */ | ||
292 | /* first write first register number */ | ||
293 | u8 ibuf [msg[1].len + 2], obuf[3]; | ||
294 | obuf[0] = 0xaa; | ||
295 | obuf[1] = msg[0].len; | ||
296 | obuf[2] = msg[0].buf[0]; | ||
297 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
298 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
299 | /* second read registers */ | ||
300 | ret = dw210x_op_rw(d->udev, 0xc3, 0xab , 0, | ||
301 | ibuf, msg[1].len + 2, DW210X_READ_MSG); | ||
302 | memcpy(msg[1].buf, ibuf + 2, msg[1].len); | ||
303 | |||
304 | break; | ||
305 | } | ||
306 | case 1: | ||
307 | switch (msg[0].addr) { | ||
308 | case 0x55: { | ||
309 | if (msg[0].buf[0] == 0xf7) { | ||
310 | /* firmware */ | ||
311 | /* Write in small blocks */ | ||
312 | u8 obuf[19]; | ||
313 | obuf[0] = 0xaa; | ||
314 | obuf[1] = 0x11; | ||
315 | obuf[2] = 0xf7; | ||
316 | len = msg[0].len - 1; | ||
317 | i = 1; | ||
318 | do { | ||
319 | memcpy(obuf + 3, msg[0].buf + i, (len > 16 ? 16 : len)); | ||
320 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
321 | obuf, (len > 16 ? 16 : len) + 3, DW210X_WRITE_MSG); | ||
322 | i += 16; | ||
323 | len -= 16; | ||
324 | } while (len > 0); | ||
325 | } else { | ||
326 | /* write to register */ | ||
327 | u8 obuf[msg[0].len + 2]; | ||
328 | obuf[0] = 0xaa; | ||
329 | obuf[1] = msg[0].len; | ||
330 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
331 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
332 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
333 | } | ||
334 | break; | ||
335 | } | ||
336 | case(DW2102_RC_QUERY): { | ||
337 | u8 ibuf[2]; | ||
338 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
339 | ibuf, 2, DW210X_READ_MSG); | ||
340 | memcpy(msg[0].buf, ibuf , 2); | ||
341 | break; | ||
342 | } | ||
343 | case(DW2102_VOLTAGE_CTRL): { | ||
344 | u8 obuf[2]; | ||
345 | obuf[0] = 0x30; | ||
346 | obuf[1] = msg[0].buf[0]; | ||
347 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
348 | obuf, 2, DW210X_WRITE_MSG); | ||
349 | break; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | break; | ||
354 | } | ||
355 | |||
356 | mutex_unlock(&d->i2c_mutex); | ||
357 | return num; | ||
358 | } | ||
359 | |||
360 | static u32 dw210x_i2c_func(struct i2c_adapter *adapter) | ||
140 | { | 361 | { |
141 | return I2C_FUNC_I2C; | 362 | return I2C_FUNC_I2C; |
142 | } | 363 | } |
143 | 364 | ||
144 | static struct i2c_algorithm dw2102_i2c_algo = { | 365 | static struct i2c_algorithm dw2102_i2c_algo = { |
145 | .master_xfer = dw2102_i2c_transfer, | 366 | .master_xfer = dw2102_i2c_transfer, |
146 | .functionality = dw2102_i2c_func, | 367 | .functionality = dw210x_i2c_func, |
368 | }; | ||
369 | |||
370 | static struct i2c_algorithm dw2102_serit_i2c_algo = { | ||
371 | .master_xfer = dw2102_serit_i2c_transfer, | ||
372 | .functionality = dw210x_i2c_func, | ||
373 | }; | ||
374 | |||
375 | static struct i2c_algorithm dw2102_earda_i2c_algo = { | ||
376 | .master_xfer = dw2102_earda_i2c_transfer, | ||
377 | .functionality = dw210x_i2c_func, | ||
378 | }; | ||
379 | |||
380 | static struct i2c_algorithm dw2104_i2c_algo = { | ||
381 | .master_xfer = dw2104_i2c_transfer, | ||
382 | .functionality = dw210x_i2c_func, | ||
147 | }; | 383 | }; |
148 | 384 | ||
149 | static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | 385 | static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) |
386 | { | ||
387 | int i; | ||
388 | u8 ibuf[] = {0, 0}; | ||
389 | u8 eeprom[256], eepromline[16]; | ||
390 | |||
391 | for (i = 0; i < 256; i++) { | ||
392 | if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) { | ||
393 | err("read eeprom failed."); | ||
394 | return -1; | ||
395 | } else { | ||
396 | eepromline[i%16] = ibuf[0]; | ||
397 | eeprom[i] = ibuf[0]; | ||
398 | } | ||
399 | if ((i % 16) == 15) { | ||
400 | deb_xfer("%02x: ", i - 15); | ||
401 | debug_dump(eepromline, 16, deb_xfer); | ||
402 | } | ||
403 | } | ||
404 | memcpy(mac, eeprom + 8, 6); | ||
405 | return 0; | ||
406 | }; | ||
407 | |||
408 | static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
150 | { | 409 | { |
151 | static u8 command_13v[1] = {0x00}; | 410 | static u8 command_13v[1] = {0x00}; |
152 | static u8 command_18v[1] = {0x01}; | 411 | static u8 command_18v[1] = {0x01}; |
@@ -163,18 +422,66 @@ static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | |||
163 | return 0; | 422 | return 0; |
164 | } | 423 | } |
165 | 424 | ||
166 | static int dw2102_frontend_attach(struct dvb_usb_adapter *d) | 425 | static struct cx24116_config dw2104_config = { |
426 | .demod_address = 0x55, | ||
427 | .mpg_clk_pos_pol = 0x01, | ||
428 | }; | ||
429 | |||
430 | static struct si21xx_config serit_sp1511lhb_config = { | ||
431 | .demod_address = 0x68, | ||
432 | .min_delay_ms = 100, | ||
433 | |||
434 | }; | ||
435 | |||
436 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) | ||
167 | { | 437 | { |
168 | d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, | 438 | if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, |
169 | &d->dev->i2c_adap); | 439 | &d->dev->i2c_adap)) != NULL) { |
170 | if (d->fe != NULL) { | 440 | d->fe->ops.set_voltage = dw210x_set_voltage; |
171 | d->fe->ops.set_voltage = dw2102_set_voltage; | 441 | info("Attached cx24116!\n"); |
172 | info("Attached stv0299!\n"); | ||
173 | return 0; | 442 | return 0; |
174 | } | 443 | } |
175 | return -EIO; | 444 | return -EIO; |
176 | } | 445 | } |
177 | 446 | ||
447 | static struct dvb_usb_device_properties dw2102_properties; | ||
448 | |||
449 | static int dw2102_frontend_attach(struct dvb_usb_adapter *d) | ||
450 | { | ||
451 | if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) { | ||
452 | /*dw2102_properties.adapter->tuner_attach = NULL;*/ | ||
453 | d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config, | ||
454 | &d->dev->i2c_adap); | ||
455 | if (d->fe != NULL) { | ||
456 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
457 | info("Attached si21xx!\n"); | ||
458 | return 0; | ||
459 | } | ||
460 | } | ||
461 | if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) { | ||
462 | /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ | ||
463 | d->fe = dvb_attach(stv0288_attach, &earda_config, | ||
464 | &d->dev->i2c_adap); | ||
465 | if (d->fe != NULL) { | ||
466 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
467 | info("Attached stv0288!\n"); | ||
468 | return 0; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) { | ||
473 | /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ | ||
474 | d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, | ||
475 | &d->dev->i2c_adap); | ||
476 | if (d->fe != NULL) { | ||
477 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
478 | info("Attached stv0299!\n"); | ||
479 | return 0; | ||
480 | } | ||
481 | } | ||
482 | return -EIO; | ||
483 | } | ||
484 | |||
178 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) | 485 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) |
179 | { | 486 | { |
180 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, | 487 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, |
@@ -182,7 +489,15 @@ static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) | |||
182 | return 0; | 489 | return 0; |
183 | } | 490 | } |
184 | 491 | ||
185 | static struct dvb_usb_rc_key dw2102_rc_keys[] = { | 492 | static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap) |
493 | { | ||
494 | dvb_attach(stb6000_attach, adap->fe, 0x61, | ||
495 | &adap->dev->i2c_adap); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static struct dvb_usb_rc_key dw210x_rc_keys[] = { | ||
186 | { 0xf8, 0x0a, KEY_Q }, /*power*/ | 501 | { 0xf8, 0x0a, KEY_Q }, /*power*/ |
187 | { 0xf8, 0x0c, KEY_M }, /*mute*/ | 502 | { 0xf8, 0x0c, KEY_M }, /*mute*/ |
188 | { 0xf8, 0x11, KEY_1 }, | 503 | { 0xf8, 0x11, KEY_1 }, |
@@ -221,7 +536,7 @@ static struct dvb_usb_rc_key dw2102_rc_keys[] = { | |||
221 | 536 | ||
222 | static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 537 | static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
223 | { | 538 | { |
224 | struct dw2102_state *st = d->priv; | 539 | struct dw210x_state *st = d->priv; |
225 | u8 key[2]; | 540 | u8 key[2]; |
226 | struct i2c_msg msg[] = { | 541 | struct i2c_msg msg[] = { |
227 | {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key, | 542 | {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key, |
@@ -231,12 +546,12 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
231 | 546 | ||
232 | *state = REMOTE_NO_KEY_PRESSED; | 547 | *state = REMOTE_NO_KEY_PRESSED; |
233 | if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { | 548 | if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { |
234 | for (i = 0; i < ARRAY_SIZE(dw2102_rc_keys); i++) { | 549 | for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) { |
235 | if (dw2102_rc_keys[i].data == msg[0].buf[0]) { | 550 | if (dw210x_rc_keys[i].data == msg[0].buf[0]) { |
236 | *state = REMOTE_KEY_PRESSED; | 551 | *state = REMOTE_KEY_PRESSED; |
237 | *event = dw2102_rc_keys[i].event; | 552 | *event = dw210x_rc_keys[i].event; |
238 | st->last_key_pressed = | 553 | st->last_key_pressed = |
239 | dw2102_rc_keys[i].event; | 554 | dw210x_rc_keys[i].event; |
240 | break; | 555 | break; |
241 | } | 556 | } |
242 | st->last_key_pressed = 0; | 557 | st->last_key_pressed = 0; |
@@ -249,6 +564,8 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
249 | static struct usb_device_id dw2102_table[] = { | 564 | static struct usb_device_id dw2102_table[] = { |
250 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, | 565 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, |
251 | {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, | 566 | {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, |
567 | {USB_DEVICE(USB_VID_CYPRESS, 0x2104)}, | ||
568 | {USB_DEVICE(0x9022, 0xd650)}, | ||
252 | { } | 569 | { } |
253 | }; | 570 | }; |
254 | 571 | ||
@@ -260,7 +577,7 @@ static int dw2102_load_firmware(struct usb_device *dev, | |||
260 | u8 *b, *p; | 577 | u8 *b, *p; |
261 | int ret = 0, i; | 578 | int ret = 0, i; |
262 | u8 reset; | 579 | u8 reset; |
263 | u8 reset16 [] = {0, 0, 0, 0, 0, 0, 0}; | 580 | u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; |
264 | const struct firmware *fw; | 581 | const struct firmware *fw; |
265 | const char *filename = "dvb-usb-dw2101.fw"; | 582 | const char *filename = "dvb-usb-dw2101.fw"; |
266 | switch (dev->descriptor.idProduct) { | 583 | switch (dev->descriptor.idProduct) { |
@@ -273,25 +590,23 @@ static int dw2102_load_firmware(struct usb_device *dev, | |||
273 | return ret; | 590 | return ret; |
274 | } | 591 | } |
275 | break; | 592 | break; |
276 | case USB_PID_DW2102: | 593 | default: |
277 | fw = frmwr; | 594 | fw = frmwr; |
278 | break; | 595 | break; |
279 | } | 596 | } |
280 | info("start downloading DW2102 firmware"); | 597 | info("start downloading DW210X firmware"); |
281 | p = kmalloc(fw->size, GFP_KERNEL); | 598 | p = kmalloc(fw->size, GFP_KERNEL); |
282 | reset = 1; | 599 | reset = 1; |
283 | /*stop the CPU*/ | 600 | /*stop the CPU*/ |
284 | dw2102_op_rw(dev, 0xa0, 0x7f92, &reset, 1, DW2102_WRITE_MSG); | 601 | dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG); |
285 | dw2102_op_rw(dev, 0xa0, 0xe600, &reset, 1, DW2102_WRITE_MSG); | 602 | dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG); |
286 | 603 | ||
287 | if (p != NULL) { | 604 | if (p != NULL) { |
288 | memcpy(p, fw->data, fw->size); | 605 | memcpy(p, fw->data, fw->size); |
289 | for (i = 0; i < fw->size; i += 0x40) { | 606 | for (i = 0; i < fw->size; i += 0x40) { |
290 | b = (u8 *) p + i; | 607 | b = (u8 *) p + i; |
291 | if (dw2102_op_rw | 608 | if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40, |
292 | (dev, 0xa0, i, b , 0x40, | 609 | DW210X_WRITE_MSG) != 0x40) { |
293 | DW2102_WRITE_MSG) != 0x40 | ||
294 | ) { | ||
295 | err("error while transferring firmware"); | 610 | err("error while transferring firmware"); |
296 | ret = -EINVAL; | 611 | ret = -EINVAL; |
297 | break; | 612 | break; |
@@ -299,43 +614,66 @@ static int dw2102_load_firmware(struct usb_device *dev, | |||
299 | } | 614 | } |
300 | /* restart the CPU */ | 615 | /* restart the CPU */ |
301 | reset = 0; | 616 | reset = 0; |
302 | if (ret || dw2102_op_rw | 617 | if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, |
303 | (dev, 0xa0, 0x7f92, &reset, 1, | 618 | DW210X_WRITE_MSG) != 1) { |
304 | DW2102_WRITE_MSG) != 1) { | ||
305 | err("could not restart the USB controller CPU."); | 619 | err("could not restart the USB controller CPU."); |
306 | ret = -EINVAL; | 620 | ret = -EINVAL; |
307 | } | 621 | } |
308 | if (ret || dw2102_op_rw | 622 | if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, |
309 | (dev, 0xa0, 0xe600, &reset, 1, | 623 | DW210X_WRITE_MSG) != 1) { |
310 | DW2102_WRITE_MSG) != 1) { | ||
311 | err("could not restart the USB controller CPU."); | 624 | err("could not restart the USB controller CPU."); |
312 | ret = -EINVAL; | 625 | ret = -EINVAL; |
313 | } | 626 | } |
314 | /* init registers */ | 627 | /* init registers */ |
315 | switch (dev->descriptor.idProduct) { | 628 | switch (dev->descriptor.idProduct) { |
316 | case USB_PID_DW2102: | 629 | case USB_PID_DW2104: |
317 | dw2102_op_rw | 630 | case 0xd650: |
318 | (dev, 0xbf, 0x0040, &reset, 0, | 631 | reset = 1; |
319 | DW2102_WRITE_MSG); | 632 | dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, |
320 | dw2102_op_rw | 633 | DW210X_WRITE_MSG); |
321 | (dev, 0xb9, 0x0000, &reset16[0], 2, | 634 | reset = 0; |
322 | DW2102_READ_MSG); | 635 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, |
636 | DW210X_WRITE_MSG); | ||
323 | break; | 637 | break; |
638 | case USB_PID_DW2102: | ||
639 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, | ||
640 | DW210X_WRITE_MSG); | ||
641 | dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, | ||
642 | DW210X_READ_MSG); | ||
643 | /* check STV0299 frontend */ | ||
644 | dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2, | ||
645 | DW210X_READ_MSG); | ||
646 | if (reset16[0] == 0xa1) { | ||
647 | dw2102_properties.i2c_algo = &dw2102_i2c_algo; | ||
648 | dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach; | ||
649 | break; | ||
650 | } else { | ||
651 | /* check STV0288 frontend */ | ||
652 | reset16[0] = 0xd0; | ||
653 | reset16[1] = 1; | ||
654 | reset16[2] = 0; | ||
655 | dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3, | ||
656 | DW210X_WRITE_MSG); | ||
657 | dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3, | ||
658 | DW210X_READ_MSG); | ||
659 | if (reset16[2] == 0x11) { | ||
660 | dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo; | ||
661 | dw2102_properties.adapter->tuner_attach = &dw2102_earda_tuner_attach; | ||
662 | break; | ||
663 | } | ||
664 | } | ||
324 | case 0x2101: | 665 | case 0x2101: |
325 | dw2102_op_rw | 666 | dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, |
326 | (dev, 0xbc, 0x0030, &reset16[0], 2, | 667 | DW210X_READ_MSG); |
327 | DW2102_READ_MSG); | 668 | dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, |
328 | dw2102_op_rw | 669 | DW210X_READ_MSG); |
329 | (dev, 0xba, 0x0000, &reset16[0], 7, | 670 | dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, |
330 | DW2102_READ_MSG); | 671 | DW210X_READ_MSG); |
331 | dw2102_op_rw | 672 | dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, |
332 | (dev, 0xba, 0x0000, &reset16[0], 7, | 673 | DW210X_READ_MSG); |
333 | DW2102_READ_MSG); | ||
334 | dw2102_op_rw | ||
335 | (dev, 0xb9, 0x0000, &reset16[0], 2, | ||
336 | DW2102_READ_MSG); | ||
337 | break; | 674 | break; |
338 | } | 675 | } |
676 | msleep(100); | ||
339 | kfree(p); | 677 | kfree(p); |
340 | } | 678 | } |
341 | return ret; | 679 | return ret; |
@@ -345,12 +683,12 @@ static struct dvb_usb_device_properties dw2102_properties = { | |||
345 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | 683 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
346 | .usb_ctrl = DEVICE_SPECIFIC, | 684 | .usb_ctrl = DEVICE_SPECIFIC, |
347 | .firmware = "dvb-usb-dw2102.fw", | 685 | .firmware = "dvb-usb-dw2102.fw", |
348 | .size_of_priv = sizeof(struct dw2102_state), | 686 | .size_of_priv = sizeof(struct dw210x_state), |
349 | .no_reconnect = 1, | 687 | .no_reconnect = 1, |
350 | 688 | ||
351 | .i2c_algo = &dw2102_i2c_algo, | 689 | .i2c_algo = &dw2102_serit_i2c_algo, |
352 | .rc_key_map = dw2102_rc_keys, | 690 | .rc_key_map = dw210x_rc_keys, |
353 | .rc_key_map_size = ARRAY_SIZE(dw2102_rc_keys), | 691 | .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), |
354 | .rc_interval = 150, | 692 | .rc_interval = 150, |
355 | .rc_query = dw2102_rc_query, | 693 | .rc_query = dw2102_rc_query, |
356 | 694 | ||
@@ -358,11 +696,12 @@ static struct dvb_usb_device_properties dw2102_properties = { | |||
358 | /* parameter for the MPEG2-data transfer */ | 696 | /* parameter for the MPEG2-data transfer */ |
359 | .num_adapters = 1, | 697 | .num_adapters = 1, |
360 | .download_firmware = dw2102_load_firmware, | 698 | .download_firmware = dw2102_load_firmware, |
361 | .adapter = { | 699 | .read_mac_address = dw210x_read_mac_address, |
700 | .adapter = { | ||
362 | { | 701 | { |
363 | .frontend_attach = dw2102_frontend_attach, | 702 | .frontend_attach = dw2102_frontend_attach, |
364 | .streaming_ctrl = NULL, | 703 | .streaming_ctrl = NULL, |
365 | .tuner_attach = dw2102_tuner_attach, | 704 | .tuner_attach = NULL, |
366 | .stream = { | 705 | .stream = { |
367 | .type = USB_BULK, | 706 | .type = USB_BULK, |
368 | .count = 8, | 707 | .count = 8, |
@@ -388,11 +727,64 @@ static struct dvb_usb_device_properties dw2102_properties = { | |||
388 | } | 727 | } |
389 | }; | 728 | }; |
390 | 729 | ||
730 | static struct dvb_usb_device_properties dw2104_properties = { | ||
731 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
732 | .usb_ctrl = DEVICE_SPECIFIC, | ||
733 | .firmware = "dvb-usb-dw2104.fw", | ||
734 | .size_of_priv = sizeof(struct dw210x_state), | ||
735 | .no_reconnect = 1, | ||
736 | |||
737 | .i2c_algo = &dw2104_i2c_algo, | ||
738 | .rc_key_map = dw210x_rc_keys, | ||
739 | .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), | ||
740 | .rc_interval = 150, | ||
741 | .rc_query = dw2102_rc_query, | ||
742 | |||
743 | .generic_bulk_ctrl_endpoint = 0x81, | ||
744 | /* parameter for the MPEG2-data transfer */ | ||
745 | .num_adapters = 1, | ||
746 | .download_firmware = dw2102_load_firmware, | ||
747 | .read_mac_address = dw210x_read_mac_address, | ||
748 | .adapter = { | ||
749 | { | ||
750 | .frontend_attach = dw2104_frontend_attach, | ||
751 | .streaming_ctrl = NULL, | ||
752 | /*.tuner_attach = dw2104_tuner_attach,*/ | ||
753 | .stream = { | ||
754 | .type = USB_BULK, | ||
755 | .count = 8, | ||
756 | .endpoint = 0x82, | ||
757 | .u = { | ||
758 | .bulk = { | ||
759 | .buffersize = 4096, | ||
760 | } | ||
761 | } | ||
762 | }, | ||
763 | } | ||
764 | }, | ||
765 | .num_device_descs = 2, | ||
766 | .devices = { | ||
767 | { "DVBWorld DW2104 USB2.0", | ||
768 | {&dw2102_table[2], NULL}, | ||
769 | {NULL}, | ||
770 | }, | ||
771 | { "TeVii S650 USB2.0", | ||
772 | {&dw2102_table[3], NULL}, | ||
773 | {NULL}, | ||
774 | }, | ||
775 | } | ||
776 | }; | ||
777 | |||
391 | static int dw2102_probe(struct usb_interface *intf, | 778 | static int dw2102_probe(struct usb_interface *intf, |
392 | const struct usb_device_id *id) | 779 | const struct usb_device_id *id) |
393 | { | 780 | { |
394 | return dvb_usb_device_init(intf, &dw2102_properties, | 781 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, |
395 | THIS_MODULE, NULL, adapter_nr); | 782 | THIS_MODULE, NULL, adapter_nr) || |
783 | 0 == dvb_usb_device_init(intf, &dw2104_properties, | ||
784 | THIS_MODULE, NULL, adapter_nr)) { | ||
785 | return 0; | ||
786 | } | ||
787 | return -ENODEV; | ||
396 | } | 788 | } |
397 | 789 | ||
398 | static struct usb_driver dw2102_driver = { | 790 | static struct usb_driver dw2102_driver = { |
@@ -420,6 +812,6 @@ module_init(dw2102_module_init); | |||
420 | module_exit(dw2102_module_exit); | 812 | module_exit(dw2102_module_exit); |
421 | 813 | ||
422 | MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); | 814 | MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); |
423 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101 2102 USB2.0 device"); | 815 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device"); |
424 | MODULE_VERSION("0.1"); | 816 | MODULE_VERSION("0.1"); |
425 | MODULE_LICENSE("GPL"); | 817 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h index 7a310f906837..e3370734e95a 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.h +++ b/drivers/media/dvb/dvb-usb/dw2102.h | |||
@@ -4,6 +4,5 @@ | |||
4 | #define DVB_USB_LOG_PREFIX "dw2102" | 4 | #define DVB_USB_LOG_PREFIX "dw2102" |
5 | #include "dvb-usb.h" | 5 | #include "dvb-usb.h" |
6 | 6 | ||
7 | extern int dvb_usb_dw2102_debug; | ||
8 | #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args) | 7 | #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args) |
9 | #endif | 8 | #endif |