diff options
Diffstat (limited to 'drivers/media/dvb/dvb-usb')
27 files changed, 5888 insertions, 105 deletions
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index f00a0eb40420..3c13bcfa6385 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -1,8 +1,6 @@ | |||
1 | config DVB_USB | 1 | config DVB_USB |
2 | tristate "Support for various USB DVB devices" | 2 | tristate "Support for various USB DVB devices" |
3 | depends on DVB_CORE && USB && I2C && INPUT | 3 | depends on DVB_CORE && USB && I2C && INPUT |
4 | depends on HOTPLUG # due to FW_LOADER | ||
5 | select FW_LOADER | ||
6 | help | 4 | help |
7 | By enabling this you will be able to choose the various supported | 5 | By enabling this you will be able to choose the various supported |
8 | USB1.1 and USB2.0 DVB devices. | 6 | USB1.1 and USB2.0 DVB devices. |
@@ -74,8 +72,11 @@ config DVB_USB_DIB0700 | |||
74 | select DVB_DIB7000P | 72 | select DVB_DIB7000P |
75 | select DVB_DIB7000M | 73 | select DVB_DIB7000M |
76 | select DVB_DIB3000MC | 74 | select DVB_DIB3000MC |
75 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | ||
77 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 76 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE |
78 | select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE | 77 | select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE |
78 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE | ||
79 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE | ||
79 | select DVB_TUNER_DIB0070 | 80 | select DVB_TUNER_DIB0070 |
80 | help | 81 | help |
81 | 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 |
@@ -107,6 +108,10 @@ config DVB_USB_CXUSB | |||
107 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 108 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
108 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 109 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
109 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | 110 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE |
111 | select MEDIA_TUNER_XC2028 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 | ||
110 | help | 115 | help |
111 | 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. |
112 | Currently, only DVB and ATSC modes are supported, analog mode | 117 | Currently, only DVB and ATSC modes are supported, analog mode |
@@ -120,6 +125,8 @@ config DVB_USB_M920X | |||
120 | depends on DVB_USB | 125 | depends on DVB_USB |
121 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 126 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
122 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | 127 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE |
128 | select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE | ||
129 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE | ||
123 | help | 130 | help |
124 | Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. | 131 | Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. |
125 | Currently, only devices with a product id of | 132 | Currently, only devices with a product id of |
@@ -241,3 +248,53 @@ config DVB_USB_AF9005_REMOTE | |||
241 | Say Y here to support the default remote control decoding for the | 248 | Say Y here to support the default remote control decoding for the |
242 | Afatech AF9005 based receiver. | 249 | Afatech AF9005 based receiver. |
243 | 250 | ||
251 | config DVB_USB_DW2102 | ||
252 | tristate "DvbWorld DVB-S/S2 USB2.0 support" | ||
253 | depends on DVB_USB | ||
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 | ||
260 | help | ||
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. | ||
271 | |||
272 | config DVB_USB_ANYSEE | ||
273 | tristate "Anysee DVB-T/C USB2.0 support" | ||
274 | depends on DVB_USB | ||
275 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
276 | select DVB_MT352 if !DVB_FE_CUSTOMISE | ||
277 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
278 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE | ||
279 | help | ||
280 | Say Y here to support the Anysee E30, Anysee E30 Plus or | ||
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 c6511a6c0ab8..3122b7cc2c23 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -61,6 +61,22 @@ obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o | |||
61 | dvb-usb-af9005-remote-objs = af9005-remote.o | 61 | dvb-usb-af9005-remote-objs = af9005-remote.o |
62 | obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o | 62 | obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o |
63 | 63 | ||
64 | dvb-usb-anysee-objs = anysee.o | ||
65 | obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o | ||
66 | |||
67 | dvb-usb-dw2102-objs = dw2102.o | ||
68 | obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o | ||
69 | |||
70 | dvb-usb-dtv5100-objs = dtv5100.o | ||
71 | obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o | ||
72 | |||
73 | dvb-usb-af9015-objs = af9015.o | ||
74 | obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o | ||
75 | |||
76 | dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o | ||
77 | obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o | ||
78 | |||
79 | |||
64 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | 80 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ |
65 | # due to tuner-xc3028 | 81 | # due to tuner-xc3028 |
66 | 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 new file mode 100644 index 000000000000..c786359fba03 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/anysee.c | |||
@@ -0,0 +1,573 @@ | |||
1 | /* | ||
2 | * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver | ||
3 | * | ||
4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | * | ||
20 | * TODO: | ||
21 | * - add smart card reader support for Conditional Access (CA) | ||
22 | * | ||
23 | * Card reader in Anysee is nothing more than ISO 7816 card reader. | ||
24 | * There is no hardware CAM in any Anysee device sold. | ||
25 | * In my understanding it should be implemented by making own module | ||
26 | * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This | ||
27 | * module registers serial interface that can be used to communicate | ||
28 | * with any ISO 7816 smart card. | ||
29 | * | ||
30 | * Any help according to implement serial smart card reader support | ||
31 | * is highly welcome! | ||
32 | */ | ||
33 | |||
34 | #include "anysee.h" | ||
35 | #include "tda1002x.h" | ||
36 | #include "mt352.h" | ||
37 | #include "mt352_priv.h" | ||
38 | #include "zl10353.h" | ||
39 | |||
40 | /* debug */ | ||
41 | static int dvb_usb_anysee_debug; | ||
42 | module_param_named(debug, dvb_usb_anysee_debug, int, 0644); | ||
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)"); | ||
47 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
48 | |||
49 | static struct mutex anysee_usb_mutex; | ||
50 | |||
51 | static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, | ||
52 | u8 *rbuf, u8 rlen) | ||
53 | { | ||
54 | struct anysee_state *state = d->priv; | ||
55 | int act_len, ret; | ||
56 | u8 buf[64]; | ||
57 | |||
58 | if (slen > sizeof(buf)) | ||
59 | slen = sizeof(buf); | ||
60 | memcpy(&buf[0], sbuf, slen); | ||
61 | buf[60] = state->seq++; | ||
62 | |||
63 | if (mutex_lock_interruptible(&anysee_usb_mutex) < 0) | ||
64 | return -EAGAIN; | ||
65 | |||
66 | /* We need receive one message more after dvb_usb_generic_rw due | ||
67 | to weird transaction flow, which is 1 x send + 2 x receive. */ | ||
68 | ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); | ||
69 | |||
70 | if (!ret) { | ||
71 | /* receive 2nd answer */ | ||
72 | ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, | ||
73 | d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), | ||
74 | &act_len, 2000); | ||
75 | if (ret) | ||
76 | err("%s: recv bulk message failed: %d", __func__, ret); | ||
77 | else { | ||
78 | deb_xfer("<<< "); | ||
79 | debug_dump(buf, act_len, deb_xfer); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | /* read request, copy returned data to return buf */ | ||
84 | if (!ret && rbuf && rlen) | ||
85 | memcpy(rbuf, buf, rlen); | ||
86 | |||
87 | mutex_unlock(&anysee_usb_mutex); | ||
88 | |||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val) | ||
93 | { | ||
94 | u8 buf[] = {CMD_REG_READ, reg >> 8, reg & 0xff, 0x01}; | ||
95 | int ret; | ||
96 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1); | ||
97 | deb_info("%s: reg:%04x val:%02x\n", __func__, reg, *val); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val) | ||
102 | { | ||
103 | u8 buf[] = {CMD_REG_WRITE, reg >> 8, reg & 0xff, 0x01, val}; | ||
104 | deb_info("%s: reg:%04x val:%02x\n", __func__, reg, val); | ||
105 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
106 | } | ||
107 | |||
108 | static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id) | ||
109 | { | ||
110 | u8 buf[] = {CMD_GET_HW_INFO}; | ||
111 | return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3); | ||
112 | } | ||
113 | |||
114 | static int anysee_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
115 | { | ||
116 | u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00}; | ||
117 | deb_info("%s: onoff:%02x\n", __func__, onoff); | ||
118 | return anysee_ctrl_msg(adap->dev, buf, sizeof(buf), NULL, 0); | ||
119 | } | ||
120 | |||
121 | static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval) | ||
122 | { | ||
123 | u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval}; | ||
124 | deb_info("%s: state:%02x interval:%02x\n", __func__, mode, interval); | ||
125 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
126 | } | ||
127 | |||
128 | static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff) | ||
129 | { | ||
130 | u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff}; | ||
131 | deb_info("%s: onoff:%02x\n", __func__, onoff); | ||
132 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
133 | } | ||
134 | |||
135 | static int anysee_init(struct dvb_usb_device *d) | ||
136 | { | ||
137 | int ret; | ||
138 | /* LED light */ | ||
139 | ret = anysee_led_ctrl(d, 0x01, 0x03); | ||
140 | if (ret) | ||
141 | return ret; | ||
142 | |||
143 | /* enable IR */ | ||
144 | ret = anysee_ir_ctrl(d, 1); | ||
145 | if (ret) | ||
146 | return ret; | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | /* I2C */ | ||
152 | static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | ||
153 | int num) | ||
154 | { | ||
155 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
156 | int ret, inc, i = 0; | ||
157 | |||
158 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
159 | return -EAGAIN; | ||
160 | |||
161 | while (i < num) { | ||
162 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
163 | u8 buf[6]; | ||
164 | buf[0] = CMD_I2C_READ; | ||
165 | buf[1] = msg[i].addr + 1; | ||
166 | buf[2] = msg[i].buf[0]; | ||
167 | buf[3] = 0x00; | ||
168 | buf[4] = 0x00; | ||
169 | buf[5] = 0x01; | ||
170 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf, | ||
171 | msg[i+1].len); | ||
172 | inc = 2; | ||
173 | } else { | ||
174 | u8 buf[4+msg[i].len]; | ||
175 | buf[0] = CMD_I2C_WRITE; | ||
176 | buf[1] = msg[i].addr; | ||
177 | buf[2] = msg[i].len; | ||
178 | buf[3] = 0x01; | ||
179 | memcpy(&buf[4], msg[i].buf, msg[i].len); | ||
180 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
181 | inc = 1; | ||
182 | } | ||
183 | if (ret) | ||
184 | break; | ||
185 | |||
186 | i += inc; | ||
187 | } | ||
188 | |||
189 | mutex_unlock(&d->i2c_mutex); | ||
190 | |||
191 | return ret ? ret : i; | ||
192 | } | ||
193 | |||
194 | static u32 anysee_i2c_func(struct i2c_adapter *adapter) | ||
195 | { | ||
196 | return I2C_FUNC_I2C; | ||
197 | } | ||
198 | |||
199 | static struct i2c_algorithm anysee_i2c_algo = { | ||
200 | .master_xfer = anysee_master_xfer, | ||
201 | .functionality = anysee_i2c_func, | ||
202 | }; | ||
203 | |||
204 | static int anysee_mt352_demod_init(struct dvb_frontend *fe) | ||
205 | { | ||
206 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; | ||
207 | static u8 reset [] = { RESET, 0x80 }; | ||
208 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | ||
209 | static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; | ||
210 | static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; | ||
211 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | ||
212 | |||
213 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
214 | udelay(200); | ||
215 | mt352_write(fe, reset, sizeof(reset)); | ||
216 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
217 | |||
218 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
219 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | ||
220 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | /* Callbacks for DVB USB */ | ||
226 | static struct tda10023_config anysee_tda10023_config = { | ||
227 | .demod_address = 0x1a, | ||
228 | .invert = 0, | ||
229 | .xtal = 16000000, | ||
230 | .pll_m = 11, | ||
231 | .pll_p = 3, | ||
232 | .pll_n = 1, | ||
233 | .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C, | ||
234 | .deltaf = 0xfeeb, | ||
235 | }; | ||
236 | |||
237 | static struct mt352_config anysee_mt352_config = { | ||
238 | .demod_address = 0x1e, | ||
239 | .demod_init = anysee_mt352_demod_init, | ||
240 | }; | ||
241 | |||
242 | static struct zl10353_config anysee_zl10353_config = { | ||
243 | .demod_address = 0x1e, | ||
244 | .parallel_ts = 1, | ||
245 | }; | ||
246 | |||
247 | static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | ||
248 | { | ||
249 | int ret; | ||
250 | struct anysee_state *state = adap->dev->priv; | ||
251 | u8 hw_info[3]; | ||
252 | u8 io_d; /* IO port D */ | ||
253 | |||
254 | /* check which hardware we have | ||
255 | We must do this call two times to get reliable values (hw bug). */ | ||
256 | ret = anysee_get_hw_info(adap->dev, hw_info); | ||
257 | if (ret) | ||
258 | return ret; | ||
259 | ret = anysee_get_hw_info(adap->dev, hw_info); | ||
260 | if (ret) | ||
261 | return ret; | ||
262 | |||
263 | /* Meaning of these info bytes are guessed. */ | ||
264 | info("firmware version:%d.%d.%d hardware id:%d", | ||
265 | 0, hw_info[1], hw_info[2], hw_info[0]); | ||
266 | |||
267 | ret = anysee_read_reg(adap->dev, 0xb0, &io_d); /* IO port D */ | ||
268 | if (ret) | ||
269 | return ret; | ||
270 | deb_info("%s: IO port D:%02x\n", __func__, io_d); | ||
271 | |||
272 | /* Select demod using trial and error method. */ | ||
273 | |||
274 | /* Try to attach demodulator in following order: | ||
275 | model demod hw firmware | ||
276 | 1. E30 MT352 02 0.2.1 | ||
277 | 2. E30 ZL10353 02 0.2.1 | ||
278 | 3. E30 Combo ZL10353 0f 0.1.2 DVB-T/C combo | ||
279 | 4. E30 Plus ZL10353 06 0.1.0 | ||
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 | ||
283 | */ | ||
284 | |||
285 | /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */ | ||
286 | adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config, | ||
287 | &adap->dev->i2c_adap); | ||
288 | if (adap->fe != NULL) { | ||
289 | state->tuner = DVB_PLL_THOMSON_DTT7579; | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */ | ||
294 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | ||
295 | &adap->dev->i2c_adap); | ||
296 | if (adap->fe != NULL) { | ||
297 | state->tuner = DVB_PLL_THOMSON_DTT7579; | ||
298 | return 0; | ||
299 | } | ||
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 | |||
316 | /* connect demod on IO port D for TDA10023 & ZL10353 */ | ||
317 | ret = anysee_write_reg(adap->dev, 0xb0, 0x25); | ||
318 | if (ret) | ||
319 | return ret; | ||
320 | |||
321 | /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */ | ||
322 | adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config, | ||
323 | &adap->dev->i2c_adap); | ||
324 | if (adap->fe != NULL) { | ||
325 | state->tuner = DVB_PLL_THOMSON_DTT7579; | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | /* IO port E - E30C rev 0.4 board requires this */ | ||
330 | ret = anysee_write_reg(adap->dev, 0xb1, 0xa7); | ||
331 | if (ret) | ||
332 | return ret; | ||
333 | |||
334 | /* Philips TDA10023 DVB-C demod */ | ||
335 | adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config, | ||
336 | &adap->dev->i2c_adap, 0x48); | ||
337 | if (adap->fe != NULL) { | ||
338 | state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A; | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | /* return IO port D to init value for safe */ | ||
343 | ret = anysee_write_reg(adap->dev, 0xb0, io_d); | ||
344 | if (ret) | ||
345 | return ret; | ||
346 | |||
347 | err("Unkown Anysee version: %02x %02x %02x. "\ | ||
348 | "Please report the <linux-dvb@linuxtv.org>.", | ||
349 | hw_info[0], hw_info[1], hw_info[2]); | ||
350 | |||
351 | return -ENODEV; | ||
352 | } | ||
353 | |||
354 | static int anysee_tuner_attach(struct dvb_usb_adapter *adap) | ||
355 | { | ||
356 | struct anysee_state *state = adap->dev->priv; | ||
357 | deb_info("%s: \n", __func__); | ||
358 | |||
359 | switch (state->tuner) { | ||
360 | case DVB_PLL_THOMSON_DTT7579: | ||
361 | /* Thomson dtt7579 (not sure) PLL inside of: | ||
362 | Samsung DNOS404ZH102A NIM | ||
363 | Samsung DNOS404ZH103A NIM */ | ||
364 | dvb_attach(dvb_pll_attach, adap->fe, 0x61, | ||
365 | NULL, DVB_PLL_THOMSON_DTT7579); | ||
366 | break; | ||
367 | case DVB_PLL_SAMSUNG_DTOS403IH102A: | ||
368 | /* Unknown PLL inside of Samsung DTOS403IH102A tuner module */ | ||
369 | dvb_attach(dvb_pll_attach, adap->fe, 0xc0, | ||
370 | &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | ||
371 | break; | ||
372 | } | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
378 | { | ||
379 | u8 buf[] = {CMD_GET_IR_CODE}; | ||
380 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | ||
381 | u8 ircode[2]; | ||
382 | int i, ret; | ||
383 | |||
384 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), &ircode[0], 2); | ||
385 | if (ret) | ||
386 | return ret; | ||
387 | |||
388 | *event = 0; | ||
389 | *state = REMOTE_NO_KEY_PRESSED; | ||
390 | |||
391 | for (i = 0; i < d->props.rc_key_map_size; i++) { | ||
392 | if (keymap[i].custom == ircode[0] && | ||
393 | keymap[i].data == ircode[1]) { | ||
394 | *event = keymap[i].event; | ||
395 | *state = REMOTE_KEY_PRESSED; | ||
396 | return 0; | ||
397 | } | ||
398 | } | ||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static struct dvb_usb_rc_key anysee_rc_keys[] = { | ||
403 | { 0x01, 0x00, KEY_0 }, | ||
404 | { 0x01, 0x01, KEY_1 }, | ||
405 | { 0x01, 0x02, KEY_2 }, | ||
406 | { 0x01, 0x03, KEY_3 }, | ||
407 | { 0x01, 0x04, KEY_4 }, | ||
408 | { 0x01, 0x05, KEY_5 }, | ||
409 | { 0x01, 0x06, KEY_6 }, | ||
410 | { 0x01, 0x07, KEY_7 }, | ||
411 | { 0x01, 0x08, KEY_8 }, | ||
412 | { 0x01, 0x09, KEY_9 }, | ||
413 | { 0x01, 0x0a, KEY_POWER }, | ||
414 | { 0x01, 0x0b, KEY_DOCUMENTS }, /* * */ | ||
415 | { 0x01, 0x19, KEY_FAVORITES }, | ||
416 | { 0x01, 0x20, KEY_SLEEP }, | ||
417 | { 0x01, 0x21, KEY_MODE }, /* 4:3 / 16:9 select */ | ||
418 | { 0x01, 0x22, KEY_ZOOM }, | ||
419 | { 0x01, 0x47, KEY_TEXT }, | ||
420 | { 0x01, 0x16, KEY_TV }, /* TV / radio select */ | ||
421 | { 0x01, 0x1e, KEY_LANGUAGE }, /* Second Audio Program */ | ||
422 | { 0x01, 0x1a, KEY_SUBTITLE }, | ||
423 | { 0x01, 0x1b, KEY_CAMERA }, /* screenshot */ | ||
424 | { 0x01, 0x42, KEY_MUTE }, | ||
425 | { 0x01, 0x0e, KEY_MENU }, | ||
426 | { 0x01, 0x0f, KEY_EPG }, | ||
427 | { 0x01, 0x17, KEY_INFO }, | ||
428 | { 0x01, 0x10, KEY_EXIT }, | ||
429 | { 0x01, 0x13, KEY_VOLUMEUP }, | ||
430 | { 0x01, 0x12, KEY_VOLUMEDOWN }, | ||
431 | { 0x01, 0x11, KEY_CHANNELUP }, | ||
432 | { 0x01, 0x14, KEY_CHANNELDOWN }, | ||
433 | { 0x01, 0x15, KEY_OK }, | ||
434 | { 0x01, 0x1d, KEY_RED }, | ||
435 | { 0x01, 0x1f, KEY_GREEN }, | ||
436 | { 0x01, 0x1c, KEY_YELLOW }, | ||
437 | { 0x01, 0x44, KEY_BLUE }, | ||
438 | { 0x01, 0x0c, KEY_SHUFFLE }, /* snapshot */ | ||
439 | { 0x01, 0x48, KEY_STOP }, | ||
440 | { 0x01, 0x50, KEY_PLAY }, | ||
441 | { 0x01, 0x51, KEY_PAUSE }, | ||
442 | { 0x01, 0x49, KEY_RECORD }, | ||
443 | { 0x01, 0x18, KEY_PREVIOUS }, /* |<< */ | ||
444 | { 0x01, 0x0d, KEY_NEXT }, /* >>| */ | ||
445 | { 0x01, 0x24, KEY_PROG1 }, /* F1 */ | ||
446 | { 0x01, 0x25, KEY_PROG2 }, /* F2 */ | ||
447 | }; | ||
448 | |||
449 | /* DVB USB Driver stuff */ | ||
450 | static struct dvb_usb_device_properties anysee_properties; | ||
451 | |||
452 | static int anysee_probe(struct usb_interface *intf, | ||
453 | const struct usb_device_id *id) | ||
454 | { | ||
455 | struct dvb_usb_device *d; | ||
456 | struct usb_host_interface *alt; | ||
457 | int ret; | ||
458 | |||
459 | mutex_init(&anysee_usb_mutex); | ||
460 | |||
461 | /* There is one interface with two alternate settings. | ||
462 | Alternate setting 0 is for bulk transfer. | ||
463 | Alternate setting 1 is for isochronous transfer. | ||
464 | We use bulk transfer (alternate setting 0). */ | ||
465 | if (intf->num_altsetting < 1) | ||
466 | return -ENODEV; | ||
467 | |||
468 | ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d, | ||
469 | adapter_nr); | ||
470 | if (ret) | ||
471 | return ret; | ||
472 | |||
473 | alt = usb_altnum_to_altsetting(intf, 0); | ||
474 | if (alt == NULL) { | ||
475 | deb_info("%s: no alt found!\n", __func__); | ||
476 | return -ENODEV; | ||
477 | } | ||
478 | |||
479 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, | ||
480 | alt->desc.bAlternateSetting); | ||
481 | if (ret) | ||
482 | return ret; | ||
483 | |||
484 | if (d) | ||
485 | ret = anysee_init(d); | ||
486 | |||
487 | return ret; | ||
488 | } | ||
489 | |||
490 | static struct usb_device_id anysee_table [] = { | ||
491 | { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) }, | ||
492 | { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) }, | ||
493 | { } /* Terminating entry */ | ||
494 | }; | ||
495 | MODULE_DEVICE_TABLE(usb, anysee_table); | ||
496 | |||
497 | static struct dvb_usb_device_properties anysee_properties = { | ||
498 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
499 | |||
500 | .usb_ctrl = DEVICE_SPECIFIC, | ||
501 | |||
502 | .size_of_priv = sizeof(struct anysee_state), | ||
503 | |||
504 | .num_adapters = 1, | ||
505 | .adapter = { | ||
506 | { | ||
507 | .streaming_ctrl = anysee_streaming_ctrl, | ||
508 | .frontend_attach = anysee_frontend_attach, | ||
509 | .tuner_attach = anysee_tuner_attach, | ||
510 | .stream = { | ||
511 | .type = USB_BULK, | ||
512 | .count = 8, | ||
513 | .endpoint = 0x82, | ||
514 | .u = { | ||
515 | .bulk = { | ||
516 | .buffersize = 512, | ||
517 | } | ||
518 | } | ||
519 | }, | ||
520 | } | ||
521 | }, | ||
522 | |||
523 | .rc_key_map = anysee_rc_keys, | ||
524 | .rc_key_map_size = ARRAY_SIZE(anysee_rc_keys), | ||
525 | .rc_query = anysee_rc_query, | ||
526 | .rc_interval = 200, /* windows driver uses 500ms */ | ||
527 | |||
528 | .i2c_algo = &anysee_i2c_algo, | ||
529 | |||
530 | .generic_bulk_ctrl_endpoint = 1, | ||
531 | |||
532 | .num_device_descs = 1, | ||
533 | .devices = { | ||
534 | { | ||
535 | .name = "Anysee DVB USB2.0", | ||
536 | .cold_ids = {NULL}, | ||
537 | .warm_ids = {&anysee_table[0], | ||
538 | &anysee_table[1], NULL}, | ||
539 | }, | ||
540 | } | ||
541 | }; | ||
542 | |||
543 | static struct usb_driver anysee_driver = { | ||
544 | .name = "dvb_usb_anysee", | ||
545 | .probe = anysee_probe, | ||
546 | .disconnect = dvb_usb_device_exit, | ||
547 | .id_table = anysee_table, | ||
548 | }; | ||
549 | |||
550 | /* module stuff */ | ||
551 | static int __init anysee_module_init(void) | ||
552 | { | ||
553 | int ret; | ||
554 | |||
555 | ret = usb_register(&anysee_driver); | ||
556 | if (ret) | ||
557 | err("%s: usb_register failed. Error number %d", __func__, ret); | ||
558 | |||
559 | return ret; | ||
560 | } | ||
561 | |||
562 | static void __exit anysee_module_exit(void) | ||
563 | { | ||
564 | /* deregister this driver from the USB subsystem */ | ||
565 | usb_deregister(&anysee_driver); | ||
566 | } | ||
567 | |||
568 | module_init(anysee_module_init); | ||
569 | module_exit(anysee_module_exit); | ||
570 | |||
571 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
572 | MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0"); | ||
573 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h new file mode 100644 index 000000000000..7ca01ff6e13c --- /dev/null +++ b/drivers/media/dvb/dvb-usb/anysee.h | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver | ||
3 | * | ||
4 | * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | * | ||
20 | * TODO: | ||
21 | * - add smart card reader support for Conditional Access (CA) | ||
22 | * | ||
23 | * Card reader in Anysee is nothing more than ISO 7816 card reader. | ||
24 | * There is no hardware CAM in any Anysee device sold. | ||
25 | * In my understanding it should be implemented by making own module | ||
26 | * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This | ||
27 | * module registers serial interface that can be used to communicate | ||
28 | * with any ISO 7816 smart card. | ||
29 | * | ||
30 | * Any help according to implement serial smart card reader support | ||
31 | * is highly welcome! | ||
32 | */ | ||
33 | |||
34 | #ifndef _DVB_USB_ANYSEE_H_ | ||
35 | #define _DVB_USB_ANYSEE_H_ | ||
36 | |||
37 | #define DVB_USB_LOG_PREFIX "anysee" | ||
38 | #include "dvb-usb.h" | ||
39 | |||
40 | #define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args) | ||
41 | #define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args) | ||
42 | #define deb_rc(args...) dprintk(dvb_usb_anysee_debug, 0x04, args) | ||
43 | #define deb_reg(args...) dprintk(dvb_usb_anysee_debug, 0x08, args) | ||
44 | #define deb_i2c(args...) dprintk(dvb_usb_anysee_debug, 0x10, args) | ||
45 | #define deb_fw(args...) dprintk(dvb_usb_anysee_debug, 0x20, args) | ||
46 | |||
47 | enum cmd { | ||
48 | CMD_I2C_READ = 0x33, | ||
49 | CMD_I2C_WRITE = 0x31, | ||
50 | CMD_REG_READ = 0xb0, | ||
51 | CMD_REG_WRITE = 0xb1, | ||
52 | CMD_STREAMING_CTRL = 0x12, | ||
53 | CMD_LED_AND_IR_CTRL = 0x16, | ||
54 | CMD_GET_IR_CODE = 0x41, | ||
55 | CMD_GET_HW_INFO = 0x19, | ||
56 | CMD_SMARTCARD = 0x34, | ||
57 | }; | ||
58 | |||
59 | struct anysee_state { | ||
60 | u8 tuner; | ||
61 | u8 seq; | ||
62 | }; | ||
63 | |||
64 | #endif | ||
65 | |||
66 | /*************************************************************************** | ||
67 | * USB API description (reverse engineered) | ||
68 | *************************************************************************** | ||
69 | |||
70 | Transaction flow: | ||
71 | ================= | ||
72 | BULK[00001] >>> REQUEST PACKET 64 bytes | ||
73 | BULK[00081] <<< REPLY PACKET #1 64 bytes (PREVIOUS TRANSACTION REPLY) | ||
74 | BULK[00081] <<< REPLY PACKET #2 64 bytes (CURRENT TRANSACTION REPLY) | ||
75 | |||
76 | General reply packet(s) are always used if not own reply defined. | ||
77 | |||
78 | ============================================================================ | ||
79 | | 00-63 | GENERAL REPLY PACKET #1 (PREVIOUS REPLY) | ||
80 | ============================================================================ | ||
81 | | 00 | reply data (if any) from previous transaction | ||
82 | | | Just same reply packet as returned during previous transaction. | ||
83 | | | Needed only if reply is missed in previous transaction. | ||
84 | | | Just skip normally. | ||
85 | ---------------------------------------------------------------------------- | ||
86 | | 01-59 | don't care | ||
87 | ---------------------------------------------------------------------------- | ||
88 | | 60 | packet sequence number | ||
89 | ---------------------------------------------------------------------------- | ||
90 | | 61-63 | don't care | ||
91 | ---------------------------------------------------------------------------- | ||
92 | |||
93 | ============================================================================ | ||
94 | | 00-63 | GENERAL REPLY PACKET #2 (CURRENT REPLY) | ||
95 | ============================================================================ | ||
96 | | 00 | reply data (if any) | ||
97 | ---------------------------------------------------------------------------- | ||
98 | | 01-59 | don't care | ||
99 | ---------------------------------------------------------------------------- | ||
100 | | 60 | packet sequence number | ||
101 | ---------------------------------------------------------------------------- | ||
102 | | 61-63 | don't care | ||
103 | ---------------------------------------------------------------------------- | ||
104 | |||
105 | ============================================================================ | ||
106 | | 00-63 | I2C WRITE REQUEST PACKET | ||
107 | ============================================================================ | ||
108 | | 00 | 0x31 I2C write command | ||
109 | ---------------------------------------------------------------------------- | ||
110 | | 01 | i2c address | ||
111 | ---------------------------------------------------------------------------- | ||
112 | | 02 | data length | ||
113 | | | 0x02 (for typical I2C reg / val pair) | ||
114 | ---------------------------------------------------------------------------- | ||
115 | | 03 | 0x01 | ||
116 | ---------------------------------------------------------------------------- | ||
117 | | 04- | data | ||
118 | ---------------------------------------------------------------------------- | ||
119 | | -59 | don't care | ||
120 | ---------------------------------------------------------------------------- | ||
121 | | 60 | packet sequence number | ||
122 | ---------------------------------------------------------------------------- | ||
123 | | 61-63 | don't care | ||
124 | ---------------------------------------------------------------------------- | ||
125 | |||
126 | ============================================================================ | ||
127 | | 00-63 | I2C READ REQUEST PACKET | ||
128 | ============================================================================ | ||
129 | | 00 | 0x33 I2C read command | ||
130 | ---------------------------------------------------------------------------- | ||
131 | | 01 | i2c address + 1 | ||
132 | ---------------------------------------------------------------------------- | ||
133 | | 02 | register | ||
134 | ---------------------------------------------------------------------------- | ||
135 | | 03 | 0x00 | ||
136 | ---------------------------------------------------------------------------- | ||
137 | | 04 | 0x00 | ||
138 | ---------------------------------------------------------------------------- | ||
139 | | 05 | 0x01 | ||
140 | ---------------------------------------------------------------------------- | ||
141 | | 06-59 | don't care | ||
142 | ---------------------------------------------------------------------------- | ||
143 | | 60 | packet sequence number | ||
144 | ---------------------------------------------------------------------------- | ||
145 | | 61-63 | don't care | ||
146 | ---------------------------------------------------------------------------- | ||
147 | |||
148 | ============================================================================ | ||
149 | | 00-63 | USB CONTROLLER REGISTER WRITE REQUEST PACKET | ||
150 | ============================================================================ | ||
151 | | 00 | 0xb1 register write command | ||
152 | ---------------------------------------------------------------------------- | ||
153 | | 01-02 | register | ||
154 | ---------------------------------------------------------------------------- | ||
155 | | 03 | 0x01 | ||
156 | ---------------------------------------------------------------------------- | ||
157 | | 04 | value | ||
158 | ---------------------------------------------------------------------------- | ||
159 | | 05-59 | don't care | ||
160 | ---------------------------------------------------------------------------- | ||
161 | | 60 | packet sequence number | ||
162 | ---------------------------------------------------------------------------- | ||
163 | | 61-63 | don't care | ||
164 | ---------------------------------------------------------------------------- | ||
165 | |||
166 | ============================================================================ | ||
167 | | 00-63 | USB CONTROLLER REGISTER READ REQUEST PACKET | ||
168 | ============================================================================ | ||
169 | | 00 | 0xb0 register read command | ||
170 | ---------------------------------------------------------------------------- | ||
171 | | 01-02 | register | ||
172 | ---------------------------------------------------------------------------- | ||
173 | | 03 | 0x01 | ||
174 | ---------------------------------------------------------------------------- | ||
175 | | 04-59 | don't care | ||
176 | ---------------------------------------------------------------------------- | ||
177 | | 60 | packet sequence number | ||
178 | ---------------------------------------------------------------------------- | ||
179 | | 61-63 | don't care | ||
180 | ---------------------------------------------------------------------------- | ||
181 | |||
182 | ============================================================================ | ||
183 | | 00-63 | LED CONTROL REQUEST PACKET | ||
184 | ============================================================================ | ||
185 | | 00 | 0x16 LED and IR control command | ||
186 | ---------------------------------------------------------------------------- | ||
187 | | 01 | 0x01 (LED) | ||
188 | ---------------------------------------------------------------------------- | ||
189 | | 03 | 0x00 blink | ||
190 | | | 0x01 lights continuously | ||
191 | ---------------------------------------------------------------------------- | ||
192 | | 04 | blink interval | ||
193 | | | 0x00 fastest (looks like LED lights continuously) | ||
194 | | | 0xff slowest | ||
195 | ---------------------------------------------------------------------------- | ||
196 | | 05-59 | don't care | ||
197 | ---------------------------------------------------------------------------- | ||
198 | | 60 | packet sequence number | ||
199 | ---------------------------------------------------------------------------- | ||
200 | | 61-63 | don't care | ||
201 | ---------------------------------------------------------------------------- | ||
202 | |||
203 | ============================================================================ | ||
204 | | 00-63 | IR CONTROL REQUEST PACKET | ||
205 | ============================================================================ | ||
206 | | 00 | 0x16 LED and IR control command | ||
207 | ---------------------------------------------------------------------------- | ||
208 | | 01 | 0x02 (IR) | ||
209 | ---------------------------------------------------------------------------- | ||
210 | | 03 | 0x00 IR disabled | ||
211 | | | 0x01 IR enabled | ||
212 | ---------------------------------------------------------------------------- | ||
213 | | 04-59 | don't care | ||
214 | ---------------------------------------------------------------------------- | ||
215 | | 60 | packet sequence number | ||
216 | ---------------------------------------------------------------------------- | ||
217 | | 61-63 | don't care | ||
218 | ---------------------------------------------------------------------------- | ||
219 | |||
220 | ============================================================================ | ||
221 | | 00-63 | STREAMING CONTROL REQUEST PACKET | ||
222 | ============================================================================ | ||
223 | | 00 | 0x12 streaming control command | ||
224 | ---------------------------------------------------------------------------- | ||
225 | | 01 | 0x00 streaming disabled | ||
226 | | | 0x01 streaming enabled | ||
227 | ---------------------------------------------------------------------------- | ||
228 | | 02 | 0x00 | ||
229 | ---------------------------------------------------------------------------- | ||
230 | | 03-59 | don't care | ||
231 | ---------------------------------------------------------------------------- | ||
232 | | 60 | packet sequence number | ||
233 | ---------------------------------------------------------------------------- | ||
234 | | 61-63 | don't care | ||
235 | ---------------------------------------------------------------------------- | ||
236 | |||
237 | ============================================================================ | ||
238 | | 00-63 | REMOTE CONTROL REQUEST PACKET | ||
239 | ============================================================================ | ||
240 | | 00 | 0x41 remote control command | ||
241 | ---------------------------------------------------------------------------- | ||
242 | | 01-59 | don't care | ||
243 | ---------------------------------------------------------------------------- | ||
244 | | 60 | packet sequence number | ||
245 | ---------------------------------------------------------------------------- | ||
246 | | 61-63 | don't care | ||
247 | ---------------------------------------------------------------------------- | ||
248 | |||
249 | ============================================================================ | ||
250 | | 00-63 | REMOTE CONTROL REPLY PACKET | ||
251 | ============================================================================ | ||
252 | | 00 | 0x00 code not received | ||
253 | | | 0x01 code received | ||
254 | ---------------------------------------------------------------------------- | ||
255 | | 01 | remote control code | ||
256 | ---------------------------------------------------------------------------- | ||
257 | | 02-59 | don't care | ||
258 | ---------------------------------------------------------------------------- | ||
259 | | 60 | packet sequence number | ||
260 | ---------------------------------------------------------------------------- | ||
261 | | 61-63 | don't care | ||
262 | ---------------------------------------------------------------------------- | ||
263 | |||
264 | ============================================================================ | ||
265 | | 00-63 | GET HARDWARE INFO REQUEST PACKET | ||
266 | ============================================================================ | ||
267 | | 00 | 0x19 get hardware info command | ||
268 | ---------------------------------------------------------------------------- | ||
269 | | 01-59 | don't care | ||
270 | ---------------------------------------------------------------------------- | ||
271 | | 60 | packet sequence number | ||
272 | ---------------------------------------------------------------------------- | ||
273 | | 61-63 | don't care | ||
274 | ---------------------------------------------------------------------------- | ||
275 | |||
276 | ============================================================================ | ||
277 | | 00-63 | GET HARDWARE INFO REPLY PACKET | ||
278 | ============================================================================ | ||
279 | | 00 | hardware id | ||
280 | ---------------------------------------------------------------------------- | ||
281 | | 01-02 | firmware version | ||
282 | ---------------------------------------------------------------------------- | ||
283 | | 03-59 | don't care | ||
284 | ---------------------------------------------------------------------------- | ||
285 | | 60 | packet sequence number | ||
286 | ---------------------------------------------------------------------------- | ||
287 | | 61-63 | don't care | ||
288 | ---------------------------------------------------------------------------- | ||
289 | |||
290 | ============================================================================ | ||
291 | | 00-63 | SMART CARD READER PACKET | ||
292 | ============================================================================ | ||
293 | | 00 | 0x34 smart card reader command | ||
294 | ---------------------------------------------------------------------------- | ||
295 | | xx | | ||
296 | ---------------------------------------------------------------------------- | ||
297 | | xx-59 | don't care | ||
298 | ---------------------------------------------------------------------------- | ||
299 | | 60 | packet sequence number | ||
300 | ---------------------------------------------------------------------------- | ||
301 | | 61-63 | don't care | ||
302 | ---------------------------------------------------------------------------- | ||
303 | |||
304 | */ | ||
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c index 2ccb90fa60c8..eb34cc3894e0 100644 --- a/drivers/media/dvb/dvb-usb/au6610.c +++ b/drivers/media/dvb/dvb-usb/au6610.c | |||
@@ -1,24 +1,31 @@ | |||
1 | /* DVB USB compliant linux driver for Sigmatek DVB-110 DVB-T USB2.0 receiver | 1 | /* |
2 | * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0. | ||
2 | * | 3 | * |
3 | * Copyright (C) 2006 Antti Palosaari <crope@iki.fi> | 4 | * Copyright (C) 2006 Antti Palosaari <crope@iki.fi> |
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify |
6 | * under the terms of the GNU General Public License as published by the Free | 7 | * it under the terms of the GNU General Public License as published by |
7 | * Software Foundation, version 2. | 8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. | ||
8 | * | 10 | * |
9 | * see Documentation/dvb/README.dvb-usb for more information | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
10 | */ | 19 | */ |
11 | 20 | ||
12 | #include "au6610.h" | 21 | #include "au6610.h" |
13 | |||
14 | #include "zl10353.h" | 22 | #include "zl10353.h" |
15 | #include "qt1010.h" | 23 | #include "qt1010.h" |
16 | 24 | ||
17 | /* debug */ | 25 | /* debug */ |
18 | static int dvb_usb_au6610_debug; | 26 | static int dvb_usb_au6610_debug; |
19 | module_param_named(debug, dvb_usb_au6610_debug, int, 0644); | 27 | module_param_named(debug, dvb_usb_au6610_debug, int, 0644); |
20 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | 28 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); |
21 | |||
22 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 29 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
23 | 30 | ||
24 | static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, | 31 | static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, |
@@ -42,9 +49,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, | |||
42 | } | 49 | } |
43 | 50 | ||
44 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, | 51 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, |
45 | USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, usb_buf, | 52 | USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, |
46 | sizeof(usb_buf), AU6610_USB_TIMEOUT); | 53 | usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT); |
47 | |||
48 | if (ret < 0) | 54 | if (ret < 0) |
49 | return ret; | 55 | return ret; |
50 | 56 | ||
@@ -116,15 +122,6 @@ static struct i2c_algorithm au6610_i2c_algo = { | |||
116 | }; | 122 | }; |
117 | 123 | ||
118 | /* Callbacks for DVB USB */ | 124 | /* Callbacks for DVB USB */ |
119 | static int au6610_identify_state(struct usb_device *udev, | ||
120 | struct dvb_usb_device_properties *props, | ||
121 | struct dvb_usb_device_description **desc, | ||
122 | int *cold) | ||
123 | { | ||
124 | *cold = 0; | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static struct zl10353_config au6610_zl10353_config = { | 125 | static struct zl10353_config au6610_zl10353_config = { |
129 | .demod_address = 0x0f, | 126 | .demod_address = 0x0f, |
130 | .no_tuner = 1, | 127 | .no_tuner = 1, |
@@ -133,12 +130,12 @@ static struct zl10353_config au6610_zl10353_config = { | |||
133 | 130 | ||
134 | static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap) | 131 | static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap) |
135 | { | 132 | { |
136 | if ((adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config, | 133 | adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config, |
137 | &adap->dev->i2c_adap)) != NULL) { | 134 | &adap->dev->i2c_adap); |
138 | return 0; | 135 | if (adap->fe == NULL) |
139 | } | 136 | return -ENODEV; |
140 | 137 | ||
141 | return -EIO; | 138 | return 0; |
142 | } | 139 | } |
143 | 140 | ||
144 | static struct qt1010_config au6610_qt1010_config = { | 141 | static struct qt1010_config au6610_qt1010_config = { |
@@ -171,7 +168,7 @@ static int au6610_probe(struct usb_interface *intf, | |||
171 | alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING); | 168 | alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING); |
172 | 169 | ||
173 | if (alt == NULL) { | 170 | if (alt == NULL) { |
174 | deb_rc("no alt found!\n"); | 171 | deb_info("%s: no alt found!\n", __func__); |
175 | return -ENODEV; | 172 | return -ENODEV; |
176 | } | 173 | } |
177 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, | 174 | ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, |
@@ -181,18 +178,19 @@ static int au6610_probe(struct usb_interface *intf, | |||
181 | return ret; | 178 | return ret; |
182 | } | 179 | } |
183 | 180 | ||
184 | |||
185 | static struct usb_device_id au6610_table [] = { | 181 | static struct usb_device_id au6610_table [] = { |
186 | { USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) }, | 182 | { USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) }, |
187 | { } /* Terminating entry */ | 183 | { } /* Terminating entry */ |
188 | }; | 184 | }; |
189 | MODULE_DEVICE_TABLE (usb, au6610_table); | 185 | MODULE_DEVICE_TABLE(usb, au6610_table); |
190 | 186 | ||
191 | static struct dvb_usb_device_properties au6610_properties = { | 187 | static struct dvb_usb_device_properties au6610_properties = { |
192 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | 188 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
189 | |||
193 | .usb_ctrl = DEVICE_SPECIFIC, | 190 | .usb_ctrl = DEVICE_SPECIFIC, |
194 | .size_of_priv = 0, | 191 | |
195 | .identify_state = au6610_identify_state, | 192 | .size_of_priv = 0, |
193 | |||
196 | .num_adapters = 1, | 194 | .num_adapters = 1, |
197 | .adapter = { | 195 | .adapter = { |
198 | { | 196 | { |
@@ -206,20 +204,22 @@ static struct dvb_usb_device_properties au6610_properties = { | |||
206 | .u = { | 204 | .u = { |
207 | .isoc = { | 205 | .isoc = { |
208 | .framesperurb = 40, | 206 | .framesperurb = 40, |
209 | .framesize = 942, /* maximum packet size */ | 207 | .framesize = 942, |
210 | .interval = 1.25, /* 125 us */ | 208 | .interval = 1, |
211 | } | 209 | } |
212 | } | 210 | } |
213 | }, | 211 | }, |
214 | } | 212 | } |
215 | }, | 213 | }, |
214 | |||
216 | .i2c_algo = &au6610_i2c_algo, | 215 | .i2c_algo = &au6610_i2c_algo, |
216 | |||
217 | .num_device_descs = 1, | 217 | .num_device_descs = 1, |
218 | .devices = { | 218 | .devices = { |
219 | { | 219 | { |
220 | "Sigmatek DVB-110 DVB-T USB2.0", | 220 | .name = "Sigmatek DVB-110 DVB-T USB2.0", |
221 | { &au6610_table[0], NULL }, | 221 | .cold_ids = {NULL}, |
222 | { NULL }, | 222 | .warm_ids = {&au6610_table[0], NULL}, |
223 | }, | 223 | }, |
224 | } | 224 | } |
225 | }; | 225 | }; |
@@ -236,12 +236,11 @@ static int __init au6610_module_init(void) | |||
236 | { | 236 | { |
237 | int ret; | 237 | int ret; |
238 | 238 | ||
239 | if ((ret = usb_register(&au6610_driver))) { | 239 | ret = usb_register(&au6610_driver); |
240 | if (ret) | ||
240 | err("usb_register failed. Error number %d", ret); | 241 | err("usb_register failed. Error number %d", ret); |
241 | return ret; | ||
242 | } | ||
243 | 242 | ||
244 | return 0; | 243 | return ret; |
245 | } | 244 | } |
246 | 245 | ||
247 | static void __exit au6610_module_exit(void) | 246 | static void __exit au6610_module_exit(void) |
@@ -250,10 +249,10 @@ static void __exit au6610_module_exit(void) | |||
250 | usb_deregister(&au6610_driver); | 249 | usb_deregister(&au6610_driver); |
251 | } | 250 | } |
252 | 251 | ||
253 | module_init (au6610_module_init); | 252 | module_init(au6610_module_init); |
254 | module_exit (au6610_module_exit); | 253 | module_exit(au6610_module_exit); |
255 | 254 | ||
256 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | 255 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); |
257 | MODULE_DESCRIPTION("Driver Sigmatek DVB-110 DVB-T USB2.0 / AU6610"); | 256 | MODULE_DESCRIPTION("Driver for Alcor Micro AU6610 DVB-T USB2.0"); |
258 | MODULE_VERSION("0.1"); | 257 | MODULE_VERSION("0.1"); |
259 | MODULE_LICENSE("GPL"); | 258 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/dvb-usb/au6610.h b/drivers/media/dvb/dvb-usb/au6610.h index 4161b054c713..7849abe2c614 100644 --- a/drivers/media/dvb/dvb-usb/au6610.h +++ b/drivers/media/dvb/dvb-usb/au6610.h | |||
@@ -1,10 +1,30 @@ | |||
1 | /* | ||
2 | * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0. | ||
3 | * | ||
4 | * Copyright (C) 2006 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
1 | #ifndef _DVB_USB_AU6610_H_ | 21 | #ifndef _DVB_USB_AU6610_H_ |
2 | #define _DVB_USB_AU6610_H_ | 22 | #define _DVB_USB_AU6610_H_ |
3 | 23 | ||
4 | #define DVB_USB_LOG_PREFIX "au6610" | 24 | #define DVB_USB_LOG_PREFIX "au6610" |
5 | #include "dvb-usb.h" | 25 | #include "dvb-usb.h" |
6 | 26 | ||
7 | #define deb_rc(args...) dprintk(dvb_usb_au6610_debug,0x01,args) | 27 | #define deb_info(args...) dprintk(dvb_usb_au6610_debug, 0x01, args) |
8 | 28 | ||
9 | #define AU6610_REQ_I2C_WRITE 0x14 | 29 | #define AU6610_REQ_I2C_WRITE 0x14 |
10 | #define AU6610_REQ_I2C_READ 0x13 | 30 | #define AU6610_REQ_I2C_READ 0x13 |
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 0286156704f2..406d7fba369d 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c | |||
@@ -35,6 +35,10 @@ | |||
35 | #include "zl10353.h" | 35 | #include "zl10353.h" |
36 | #include "tuner-xc2028.h" | 36 | #include "tuner-xc2028.h" |
37 | #include "tuner-simple.h" | 37 | #include "tuner-simple.h" |
38 | #include "mxl5005s.h" | ||
39 | #include "dib7000p.h" | ||
40 | #include "dib0070.h" | ||
41 | #include "lgs8gl5.h" | ||
38 | 42 | ||
39 | /* debug */ | 43 | /* debug */ |
40 | static int dvb_usb_cxusb_debug; | 44 | static int dvb_usb_cxusb_debug; |
@@ -43,9 +47,8 @@ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_ST | |||
43 | 47 | ||
44 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 48 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
45 | 49 | ||
46 | #define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args) | 50 | #define deb_info(args...) dprintk(dvb_usb_cxusb_debug, 0x03, args) |
47 | #define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \ | 51 | #define deb_i2c(args...) dprintk(dvb_usb_cxusb_debug, 0x02, args) |
48 | dprintk(dvb_usb_cxusb_debug,0x01,args) | ||
49 | 52 | ||
50 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, | 53 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, |
51 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | 54 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) |
@@ -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) |
@@ -202,6 +224,46 @@ static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff) | |||
202 | return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0); | 224 | return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0); |
203 | } | 225 | } |
204 | 226 | ||
227 | static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
228 | { | ||
229 | int ret; | ||
230 | if (!onoff) | ||
231 | return cxusb_ctrl_msg(d, CMD_POWER_OFF, NULL, 0, NULL, 0); | ||
232 | if (d->state == DVB_USB_STATE_INIT && | ||
233 | usb_set_interface(d->udev, 0, 0) < 0) | ||
234 | err("set interface failed"); | ||
235 | do {} while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) && | ||
236 | !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) && | ||
237 | !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0); | ||
238 | if (!ret) { | ||
239 | /* FIXME: We don't know why, but we need to configure the | ||
240 | * lgdt3303 with the register settings below on resume */ | ||
241 | int i; | ||
242 | u8 buf, bufs[] = { | ||
243 | 0x0e, 0x2, 0x00, 0x7f, | ||
244 | 0x0e, 0x2, 0x02, 0xfe, | ||
245 | 0x0e, 0x2, 0x02, 0x01, | ||
246 | 0x0e, 0x2, 0x00, 0x03, | ||
247 | 0x0e, 0x2, 0x0d, 0x40, | ||
248 | 0x0e, 0x2, 0x0e, 0x87, | ||
249 | 0x0e, 0x2, 0x0f, 0x8e, | ||
250 | 0x0e, 0x2, 0x10, 0x01, | ||
251 | 0x0e, 0x2, 0x14, 0xd7, | ||
252 | 0x0e, 0x2, 0x47, 0x88, | ||
253 | }; | ||
254 | msleep(20); | ||
255 | for (i = 0; i < sizeof(bufs)/sizeof(u8); i += 4/sizeof(u8)) { | ||
256 | ret = cxusb_ctrl_msg(d, CMD_I2C_WRITE, | ||
257 | bufs+i, 4, &buf, 1); | ||
258 | if (ret) | ||
259 | break; | ||
260 | if (buf != 0x8) | ||
261 | return -EREMOTEIO; | ||
262 | } | ||
263 | } | ||
264 | return ret; | ||
265 | } | ||
266 | |||
205 | static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff) | 267 | static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff) |
206 | { | 268 | { |
207 | u8 b = 0; | 269 | u8 b = 0; |
@@ -222,6 +284,20 @@ static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff) | |||
222 | return rc; | 284 | return rc; |
223 | } | 285 | } |
224 | 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 | |||
225 | 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) |
226 | { | 302 | { |
227 | u8 buf[2] = { 0x03, 0x00 }; | 303 | u8 buf[2] = { 0x03, 0x00 }; |
@@ -233,6 +309,77 @@ static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
233 | return 0; | 309 | return 0; |
234 | } | 310 | } |
235 | 311 | ||
312 | static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
313 | { | ||
314 | if (onoff) | ||
315 | cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_ON, NULL, 0, NULL, 0); | ||
316 | else | ||
317 | cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_OFF, | ||
318 | NULL, 0, NULL, 0); | ||
319 | return 0; | ||
320 | } | ||
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 | |||
236 | 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) |
237 | { | 384 | { |
238 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | 385 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; |
@@ -285,6 +432,32 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event, | |||
285 | return 0; | 432 | return 0; |
286 | } | 433 | } |
287 | 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 | |||
288 | static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { | 461 | static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { |
289 | { 0xfe, 0x02, KEY_TV }, | 462 | { 0xfe, 0x02, KEY_TV }, |
290 | { 0xfe, 0x0e, KEY_MP3 }, | 463 | { 0xfe, 0x0e, KEY_MP3 }, |
@@ -372,6 +545,44 @@ static struct dvb_usb_rc_key dvico_portable_rc_keys[] = { | |||
372 | { 0xfc, 0x00, KEY_UNKNOWN }, /* HD */ | 545 | { 0xfc, 0x00, KEY_UNKNOWN }, /* HD */ |
373 | }; | 546 | }; |
374 | 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 | |||
375 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) | 586 | static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) |
376 | { | 587 | { |
377 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; | 588 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 }; |
@@ -423,6 +634,12 @@ static struct lgdt330x_config cxusb_lgdt3303_config = { | |||
423 | .demod_chip = LGDT3303, | 634 | .demod_chip = LGDT3303, |
424 | }; | 635 | }; |
425 | 636 | ||
637 | static struct lgdt330x_config cxusb_aver_lgdt3303_config = { | ||
638 | .demod_address = 0x0e, | ||
639 | .demod_chip = LGDT3303, | ||
640 | .clock_polarity_flip = 2, | ||
641 | }; | ||
642 | |||
426 | static struct mt352_config cxusb_dee1601_config = { | 643 | static struct mt352_config cxusb_dee1601_config = { |
427 | .demod_address = 0x0f, | 644 | .demod_address = 0x0f, |
428 | .demod_init = cxusb_dee1601_demod_init, | 645 | .demod_init = cxusb_dee1601_demod_init, |
@@ -453,6 +670,42 @@ static struct mt352_config cxusb_mt352_xc3028_config = { | |||
453 | .demod_init = cxusb_mt352_demod_init, | 670 | .demod_init = cxusb_mt352_demod_init, |
454 | }; | 671 | }; |
455 | 672 | ||
673 | /* FIXME: needs tweaking */ | ||
674 | static struct mxl5005s_config aver_a868r_tuner = { | ||
675 | .i2c_address = 0x63, | ||
676 | .if_freq = 6000000UL, | ||
677 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
678 | .agc_mode = MXL_SINGLE_AGC, | ||
679 | .tracking_filter = MXL_TF_C, | ||
680 | .rssi_enable = MXL_RSSI_ENABLE, | ||
681 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
682 | .div_out = MXL_DIV_OUT_4, | ||
683 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
684 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
685 | .top = MXL5005S_TOP_25P2, | ||
686 | .mod_mode = MXL_DIGITAL_MODE, | ||
687 | .if_mode = MXL_ZERO_IF, | ||
688 | .AgcMasterByte = 0x00, | ||
689 | }; | ||
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 | |||
456 | /* Callbacks for DVB USB */ | 709 | /* Callbacks for DVB USB */ |
457 | static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) | 710 | static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) |
458 | { | 711 | { |
@@ -489,9 +742,11 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) | |||
489 | return 0; | 742 | return 0; |
490 | } | 743 | } |
491 | 744 | ||
492 | 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) | ||
493 | { | 747 | { |
494 | struct dvb_usb_device *d = ptr; | 748 | struct dvb_usb_adapter *adap = ptr; |
749 | struct dvb_usb_device *d = adap->dev; | ||
495 | 750 | ||
496 | switch (command) { | 751 | switch (command) { |
497 | case XC2028_TUNER_RESET: | 752 | case XC2028_TUNER_RESET: |
@@ -516,14 +771,16 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) | |||
516 | struct xc2028_config cfg = { | 771 | struct xc2028_config cfg = { |
517 | .i2c_adap = &adap->dev->i2c_adap, | 772 | .i2c_adap = &adap->dev->i2c_adap, |
518 | .i2c_addr = 0x61, | 773 | .i2c_addr = 0x61, |
519 | .callback = dvico_bluebird_xc2028_callback, | ||
520 | }; | 774 | }; |
521 | static struct xc2028_ctrl ctl = { | 775 | static struct xc2028_ctrl ctl = { |
522 | .fname = "xc3028-dvico-au-01.fw", | 776 | .fname = XC2028_DEFAULT_FIRMWARE, |
523 | .max_len = 64, | 777 | .max_len = 64, |
524 | .scode_table = XC3028_FE_ZARLINK456, | 778 | .demod = XC3028_FE_ZARLINK456, |
525 | }; | 779 | }; |
526 | 780 | ||
781 | /* FIXME: generalize & move to common area */ | ||
782 | adap->fe->callback = dvico_bluebird_xc2028_callback; | ||
783 | |||
527 | fe = dvb_attach(xc2028_attach, adap->fe, &cfg); | 784 | fe = dvb_attach(xc2028_attach, adap->fe, &cfg); |
528 | if (fe == NULL || fe->ops.tuner_ops.set_config == NULL) | 785 | if (fe == NULL || fe->ops.tuner_ops.set_config == NULL) |
529 | return -EIO; | 786 | return -EIO; |
@@ -533,6 +790,21 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) | |||
533 | return 0; | 790 | return 0; |
534 | } | 791 | } |
535 | 792 | ||
793 | static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) | ||
794 | { | ||
795 | dvb_attach(mxl5005s_attach, adap->fe, | ||
796 | &adap->dev->i2c_adap, &aver_a868r_tuner); | ||
797 | return 0; | ||
798 | } | ||
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 | |||
536 | static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) | 808 | static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) |
537 | { | 809 | { |
538 | u8 b; | 810 | u8 b; |
@@ -562,6 +834,16 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) | |||
562 | return -EIO; | 834 | return -EIO; |
563 | } | 835 | } |
564 | 836 | ||
837 | static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap) | ||
838 | { | ||
839 | adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config, | ||
840 | &adap->dev->i2c_adap); | ||
841 | if (adap->fe != NULL) | ||
842 | return 0; | ||
843 | |||
844 | return -EIO; | ||
845 | } | ||
846 | |||
565 | static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) | 847 | static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) |
566 | { | 848 | { |
567 | /* used in both lgz201 and th7579 */ | 849 | /* used in both lgz201 and th7579 */ |
@@ -634,6 +916,159 @@ no_IR: | |||
634 | return 0; | 916 | return 0; |
635 | } | 917 | } |
636 | 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 | |||
637 | static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) | 1072 | static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) |
638 | { | 1073 | { |
639 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) | 1074 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) |
@@ -659,6 +1094,54 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) | |||
659 | return -EIO; | 1094 | return -EIO; |
660 | } | 1095 | } |
661 | 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 | |||
662 | /* | 1145 | /* |
663 | * 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 |
664 | * 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 |
@@ -734,8 +1217,11 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties; | |||
734 | static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; | 1217 | static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties; |
735 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; | 1218 | static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties; |
736 | 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; | ||
737 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; | 1221 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; |
738 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; | 1222 | static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; |
1223 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; | ||
1224 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties; | ||
739 | 1225 | ||
740 | static int cxusb_probe(struct usb_interface *intf, | 1226 | static int cxusb_probe(struct usb_interface *intf, |
741 | const struct usb_device_id *id) | 1227 | const struct usb_device_id *id) |
@@ -756,7 +1242,15 @@ static int cxusb_probe(struct usb_interface *intf, | |||
756 | THIS_MODULE, NULL, adapter_nr) || | 1242 | THIS_MODULE, NULL, adapter_nr) || |
757 | 0 == dvb_usb_device_init(intf, | 1243 | 0 == dvb_usb_device_init(intf, |
758 | &cxusb_bluebird_nano2_needsfirmware_properties, | 1244 | &cxusb_bluebird_nano2_needsfirmware_properties, |
759 | THIS_MODULE, NULL, adapter_nr)) | 1245 | THIS_MODULE, NULL, adapter_nr) || |
1246 | 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, | ||
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) || | ||
1253 | 0) | ||
760 | return 0; | 1254 | return 0; |
761 | 1255 | ||
762 | return -EINVAL; | 1256 | return -EINVAL; |
@@ -779,6 +1273,9 @@ static struct usb_device_id cxusb_table [] = { | |||
779 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) }, | 1273 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) }, |
780 | { 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) }, |
781 | { 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) }, |
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) }, | ||
782 | {} /* Terminating entry */ | 1279 | {} /* Terminating entry */ |
783 | }; | 1280 | }; |
784 | MODULE_DEVICE_TABLE (usb, cxusb_table); | 1281 | MODULE_DEVICE_TABLE (usb, cxusb_table); |
@@ -1182,6 +1679,146 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope | |||
1182 | } | 1679 | } |
1183 | }; | 1680 | }; |
1184 | 1681 | ||
1682 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties = { | ||
1683 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
1684 | |||
1685 | .usb_ctrl = CYPRESS_FX2, | ||
1686 | |||
1687 | .size_of_priv = sizeof(struct cxusb_state), | ||
1688 | |||
1689 | .num_adapters = 1, | ||
1690 | .adapter = { | ||
1691 | { | ||
1692 | .streaming_ctrl = cxusb_aver_streaming_ctrl, | ||
1693 | .frontend_attach = cxusb_aver_lgdt3303_frontend_attach, | ||
1694 | .tuner_attach = cxusb_mxl5003s_tuner_attach, | ||
1695 | /* parameter for the MPEG2-data transfer */ | ||
1696 | .stream = { | ||
1697 | .type = USB_BULK, | ||
1698 | .count = 5, | ||
1699 | .endpoint = 0x04, | ||
1700 | .u = { | ||
1701 | .bulk = { | ||
1702 | .buffersize = 8192, | ||
1703 | } | ||
1704 | } | ||
1705 | }, | ||
1706 | |||
1707 | }, | ||
1708 | }, | ||
1709 | .power_ctrl = cxusb_aver_power_ctrl, | ||
1710 | |||
1711 | .i2c_algo = &cxusb_i2c_algo, | ||
1712 | |||
1713 | .generic_bulk_ctrl_endpoint = 0x01, | ||
1714 | |||
1715 | .num_device_descs = 1, | ||
1716 | .devices = { | ||
1717 | { "AVerMedia AVerTVHD Volar (A868R)", | ||
1718 | { NULL }, | ||
1719 | { &cxusb_table[16], NULL }, | ||
1720 | }, | ||
1721 | } | ||
1722 | }; | ||
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 | |||
1185 | static struct usb_driver cxusb_driver = { | 1822 | static struct usb_driver cxusb_driver = { |
1186 | .name = "dvb_usb_cxusb", | 1823 | .name = "dvb_usb_cxusb", |
1187 | .probe = cxusb_probe, | 1824 | .probe = cxusb_probe, |
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h index 4768a2c35517..1a51eafd31b9 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.h +++ b/drivers/media/dvb/dvb-usb/cxusb.h | |||
@@ -20,6 +20,9 @@ | |||
20 | #define CMD_STREAMING_ON 0x36 | 20 | #define CMD_STREAMING_ON 0x36 |
21 | #define CMD_STREAMING_OFF 0x37 | 21 | #define CMD_STREAMING_OFF 0x37 |
22 | 22 | ||
23 | #define CMD_AVER_STREAM_ON 0x18 | ||
24 | #define CMD_AVER_STREAM_OFF 0x19 | ||
25 | |||
23 | #define CMD_GET_IR_CODE 0x47 | 26 | #define CMD_GET_IR_CODE 0x47 |
24 | 27 | ||
25 | #define CMD_ANALOG 0x50 | 28 | #define CMD_ANALOG 0x50 |
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 c4d40fe01d57..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) }, |
@@ -1117,6 +1249,13 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
1117 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) }, | 1249 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) }, |
1118 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) }, | 1250 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) }, |
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) }, |
1252 | /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, | ||
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) }, | ||
1120 | { 0 } /* Terminating entry */ | 1259 | { 0 } /* Terminating entry */ |
1121 | }; | 1260 | }; |
1122 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 1261 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
@@ -1124,7 +1263,7 @@ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | |||
1124 | #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ | 1263 | #define DIB0700_DEFAULT_DEVICE_PROPERTIES \ |
1125 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ | 1264 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, \ |
1126 | .usb_ctrl = DEVICE_SPECIFIC, \ | 1265 | .usb_ctrl = DEVICE_SPECIFIC, \ |
1127 | .firmware = "dvb-usb-dib0700-1.10.fw", \ | 1266 | .firmware = "dvb-usb-dib0700-1.20.fw", \ |
1128 | .download_firmware = dib0700_download_firmware, \ | 1267 | .download_firmware = dib0700_download_firmware, \ |
1129 | .no_reconnect = 1, \ | 1268 | .no_reconnect = 1, \ |
1130 | .size_of_priv = sizeof(struct dib0700_state), \ | 1269 | .size_of_priv = sizeof(struct dib0700_state), \ |
@@ -1291,7 +1430,12 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1291 | { &dib0700_usb_id_table[31], NULL }, | 1430 | { &dib0700_usb_id_table[31], NULL }, |
1292 | { NULL }, | 1431 | { NULL }, |
1293 | } | 1432 | } |
1294 | } | 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 | ||
1295 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 1439 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
1296 | 1440 | ||
1297 | .num_adapters = 1, | 1441 | .num_adapters = 1, |
@@ -1372,7 +1516,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1372 | } | 1516 | } |
1373 | }, | 1517 | }, |
1374 | 1518 | ||
1375 | .num_device_descs = 2, | 1519 | .num_device_descs = 4, |
1376 | .devices = { | 1520 | .devices = { |
1377 | { "DiBcom STK7070PD reference design", | 1521 | { "DiBcom STK7070PD reference design", |
1378 | { &dib0700_usb_id_table[17], NULL }, | 1522 | { &dib0700_usb_id_table[17], NULL }, |
@@ -1381,6 +1525,14 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1381 | { "Pinnacle PCTV Dual DVB-T Diversity Stick", | 1525 | { "Pinnacle PCTV Dual DVB-T Diversity Stick", |
1382 | { &dib0700_usb_id_table[18], NULL }, | 1526 | { &dib0700_usb_id_table[18], NULL }, |
1383 | { NULL }, | 1527 | { NULL }, |
1528 | }, | ||
1529 | { "Hauppauge Nova-TD Stick (52009)", | ||
1530 | { &dib0700_usb_id_table[35], NULL }, | ||
1531 | { NULL }, | ||
1532 | }, | ||
1533 | { "Hauppauge Nova-TD-500 (84xxx)", | ||
1534 | { &dib0700_usb_id_table[36], NULL }, | ||
1535 | { NULL }, | ||
1384 | } | 1536 | } |
1385 | } | 1537 | } |
1386 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 1538 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
@@ -1398,7 +1550,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1398 | }, | 1550 | }, |
1399 | }, | 1551 | }, |
1400 | 1552 | ||
1401 | .num_device_descs = 3, | 1553 | .num_device_descs = 5, |
1402 | .devices = { | 1554 | .devices = { |
1403 | { "Terratec Cinergy HT USB XE", | 1555 | { "Terratec Cinergy HT USB XE", |
1404 | { &dib0700_usb_id_table[27], NULL }, | 1556 | { &dib0700_usb_id_table[27], NULL }, |
@@ -1412,6 +1564,47 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1412 | { &dib0700_usb_id_table[32], NULL }, | 1564 | { &dib0700_usb_id_table[32], NULL }, |
1413 | { NULL }, | 1565 | { NULL }, |
1414 | }, | 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 | }, | ||
1415 | }, | 1608 | }, |
1416 | .rc_interval = DEFAULT_RC_INTERVAL, | 1609 | .rc_interval = DEFAULT_RC_INTERVAL, |
1417 | .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-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c index 23428cd30756..326f7608954b 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c | |||
@@ -20,11 +20,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d) | |||
20 | } | 20 | } |
21 | 21 | ||
22 | strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); | 22 | strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); |
23 | #ifdef I2C_ADAP_CLASS_TV_DIGITAL | ||
24 | d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL, | ||
25 | #else | ||
26 | d->i2c_adap.class = I2C_CLASS_TV_DIGITAL, | 23 | d->i2c_adap.class = I2C_CLASS_TV_DIGITAL, |
27 | #endif | ||
28 | d->i2c_adap.algo = d->props.i2c_algo; | 24 | d->i2c_adap.algo = d->props.i2c_algo; |
29 | d->i2c_adap.algo_data = NULL; | 25 | d->i2c_adap.algo_data = NULL; |
30 | d->i2c_adap.dev.parent = &d->udev->dev; | 26 | d->i2c_adap.dev.parent = &d->udev->dev; |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 34245d1b7dd9..7380b94b3b36 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #define USB_VID_AFATECH 0x15a4 | 14 | #define USB_VID_AFATECH 0x15a4 |
15 | #define USB_VID_ALCOR_MICRO 0x058f | 15 | #define USB_VID_ALCOR_MICRO 0x058f |
16 | #define USB_VID_ALINK 0x05e3 | 16 | #define USB_VID_ALINK 0x05e3 |
17 | #define USB_VID_AMT 0x1c73 | ||
17 | #define USB_VID_ANCHOR 0x0547 | 18 | #define USB_VID_ANCHOR 0x0547 |
18 | #define USB_VID_ANSONIC 0x10b9 | 19 | #define USB_VID_ANSONIC 0x10b9 |
19 | #define USB_VID_ANUBIS_ELECTRONIC 0x10fd | 20 | #define USB_VID_ANUBIS_ELECTRONIC 0x10fd |
@@ -21,6 +22,7 @@ | |||
21 | #define USB_VID_AVERMEDIA 0x07ca | 22 | #define USB_VID_AVERMEDIA 0x07ca |
22 | #define USB_VID_COMPRO 0x185b | 23 | #define USB_VID_COMPRO 0x185b |
23 | #define USB_VID_COMPRO_UNK 0x145f | 24 | #define USB_VID_COMPRO_UNK 0x145f |
25 | #define USB_VID_CONEXANT 0x0572 | ||
24 | #define USB_VID_CYPRESS 0x04b4 | 26 | #define USB_VID_CYPRESS 0x04b4 |
25 | #define USB_VID_DIBCOM 0x10b8 | 27 | #define USB_VID_DIBCOM 0x10b8 |
26 | #define USB_VID_DPOSH 0x1498 | 28 | #define USB_VID_DPOSH 0x1498 |
@@ -32,16 +34,19 @@ | |||
32 | #define USB_VID_HAUPPAUGE 0x2040 | 34 | #define USB_VID_HAUPPAUGE 0x2040 |
33 | #define USB_VID_HYPER_PALTEK 0x1025 | 35 | #define USB_VID_HYPER_PALTEK 0x1025 |
34 | #define USB_VID_KWORLD 0xeb2a | 36 | #define USB_VID_KWORLD 0xeb2a |
37 | #define USB_VID_KWORLD_2 0x1b80 | ||
35 | #define USB_VID_KYE 0x0458 | 38 | #define USB_VID_KYE 0x0458 |
36 | #define USB_VID_LEADTEK 0x0413 | 39 | #define USB_VID_LEADTEK 0x0413 |
37 | #define USB_VID_LITEON 0x04ca | 40 | #define USB_VID_LITEON 0x04ca |
38 | #define USB_VID_MEDION 0x1660 | 41 | #define USB_VID_MEDION 0x1660 |
39 | #define USB_VID_MIGLIA 0x18f3 | 42 | #define USB_VID_MIGLIA 0x18f3 |
40 | #define USB_VID_MSI 0x0db0 | 43 | #define USB_VID_MSI 0x0db0 |
44 | #define USB_VID_MSI_2 0x1462 | ||
41 | #define USB_VID_OPERA1 0x695c | 45 | #define USB_VID_OPERA1 0x695c |
42 | #define USB_VID_PINNACLE 0x2304 | 46 | #define USB_VID_PINNACLE 0x2304 |
43 | #define USB_VID_TECHNOTREND 0x0b48 | 47 | #define USB_VID_TECHNOTREND 0x0b48 |
44 | #define USB_VID_TERRATEC 0x0ccd | 48 | #define USB_VID_TERRATEC 0x0ccd |
49 | #define USB_VID_TELESTAR 0x10b9 | ||
45 | #define USB_VID_VISIONPLUS 0x13d3 | 50 | #define USB_VID_VISIONPLUS 0x13d3 |
46 | #define USB_VID_TWINHAN 0x1822 | 51 | #define USB_VID_TWINHAN 0x1822 |
47 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 | 52 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 |
@@ -49,14 +54,18 @@ | |||
49 | #define USB_VID_WIDEVIEW 0x14aa | 54 | #define USB_VID_WIDEVIEW 0x14aa |
50 | #define USB_VID_GIGABYTE 0x1044 | 55 | #define USB_VID_GIGABYTE 0x1044 |
51 | #define USB_VID_YUAN 0x1164 | 56 | #define USB_VID_YUAN 0x1164 |
52 | 57 | #define USB_VID_XTENSIONS 0x1ae7 | |
53 | 58 | ||
54 | /* Product IDs */ | 59 | /* Product IDs */ |
55 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 | 60 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 |
56 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 | 61 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 |
57 | #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 | ||
58 | #define USB_VID_ALINK_DTU 0xf170 | 65 | #define USB_VID_ALINK_DTU 0xf170 |
59 | #define USB_PID_ANSONIC_DVBT_USB 0x6000 | 66 | #define USB_PID_ANSONIC_DVBT_USB 0x6000 |
67 | #define USB_PID_ANYSEE 0x861f | ||
68 | #define USB_PID_AZUREWAVE_AD_TU700 0x3237 | ||
60 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 | 69 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 |
61 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 | 70 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 |
62 | #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 | 71 | #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 |
@@ -67,6 +76,7 @@ | |||
67 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | 76 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d |
68 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 | 77 | #define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 |
69 | #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 | ||
70 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 | 80 | #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 |
71 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 | 81 | #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 |
72 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | 82 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 |
@@ -85,9 +95,12 @@ | |||
85 | #define USB_PID_UNIWILL_STK7700P 0x6003 | 95 | #define USB_PID_UNIWILL_STK7700P 0x6003 |
86 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | 96 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 |
87 | #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 | ||
88 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | 100 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de |
89 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df | 101 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df |
90 | #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 | ||
91 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 | 104 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 |
92 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 | 105 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 |
93 | #define USB_PID_TWINHAN_VP7020_COLD 0x3203 | 106 | #define USB_PID_TWINHAN_VP7020_COLD 0x3203 |
@@ -96,6 +109,7 @@ | |||
96 | #define USB_PID_TWINHAN_VP7045_WARM 0x3206 | 109 | #define USB_PID_TWINHAN_VP7045_WARM 0x3206 |
97 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 | 110 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 |
98 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 | 111 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 |
112 | #define USB_PID_TINYTWIN 0x3226 | ||
99 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 | 113 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 |
100 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 | 114 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 |
101 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 | 115 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 |
@@ -127,14 +141,24 @@ | |||
127 | #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 | 141 | #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 |
128 | #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 | 142 | #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 |
129 | #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 | 143 | #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 |
144 | #define USB_PID_HAUPPAUGE_NOVA_T_500_3 0x8400 | ||
130 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 | 145 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 |
131 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 | 146 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 |
132 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070 | 147 | #define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070 |
133 | #define USB_PID_HAUPPAUGE_MYTV_T 0x7080 | 148 | #define USB_PID_HAUPPAUGE_MYTV_T 0x7080 |
134 | #define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580 | 149 | #define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580 |
150 | #define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009 0x5200 | ||
135 | #define USB_PID_AVERMEDIA_EXPRESS 0xb568 | 151 | #define USB_PID_AVERMEDIA_EXPRESS 0xb568 |
136 | #define USB_PID_AVERMEDIA_VOLAR 0xa807 | 152 | #define USB_PID_AVERMEDIA_VOLAR 0xa807 |
137 | #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 | 153 | #define USB_PID_AVERMEDIA_VOLAR_2 0xb808 |
154 | #define USB_PID_AVERMEDIA_VOLAR_A868R 0xa868 | ||
155 | #define USB_PID_AVERMEDIA_MCE_USB_M038 0x1228 | ||
156 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039 | ||
157 | #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039 | ||
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 | ||
138 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 | 162 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 |
139 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a | 163 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a |
140 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 | 164 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 |
@@ -144,8 +168,11 @@ | |||
144 | #define USB_PID_PINNACLE_PCTV2000E 0x022c | 168 | #define USB_PID_PINNACLE_PCTV2000E 0x022c |
145 | #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 | 169 | #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 |
146 | #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 | ||
147 | #define USB_PID_PINNACLE_PCTV72E 0x0236 | 172 | #define USB_PID_PINNACLE_PCTV72E 0x0236 |
148 | #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 | ||
149 | #define USB_PID_PCTV_200E 0x020e | 176 | #define USB_PID_PCTV_200E 0x020e |
150 | #define USB_PID_PCTV_400E 0x020f | 177 | #define USB_PID_PCTV_400E 0x020f |
151 | #define USB_PID_PCTV_450E 0x0222 | 178 | #define USB_PID_PCTV_450E 0x0222 |
@@ -162,6 +189,7 @@ | |||
162 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 | 189 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 |
163 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 | 190 | #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 |
164 | #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 | ||
165 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70 | 193 | #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70 |
166 | #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 |
167 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 | 195 | #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 |
@@ -181,6 +209,7 @@ | |||
181 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 | 209 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 |
182 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 | 210 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 |
183 | #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 | ||
184 | #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 | 213 | #define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200 |
185 | #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 | 214 | #define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201 |
186 | #define USB_PID_GENPIX_8PSK_REV_2 0x0202 | 215 | #define USB_PID_GENPIX_8PSK_REV_2 0x0202 |
@@ -188,13 +217,21 @@ | |||
188 | #define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204 | 217 | #define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204 |
189 | #define USB_PID_SIGMATEK_DVB_110 0x6610 | 218 | #define USB_PID_SIGMATEK_DVB_110 0x6610 |
190 | #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 | ||
191 | #define USB_PID_OPERA1_COLD 0x2830 | 221 | #define USB_PID_OPERA1_COLD 0x2830 |
192 | #define USB_PID_OPERA1_WARM 0x3829 | 222 | #define USB_PID_OPERA1_WARM 0x3829 |
193 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 | 223 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 |
194 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 | 224 | #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 |
195 | #define USB_PID_GIGABYTE_U7000 0x7001 | 225 | #define USB_PID_GIGABYTE_U7000 0x7001 |
226 | #define USB_PID_GIGABYTE_U8000 0x7002 | ||
196 | #define USB_PID_ASUS_U3000 0x171f | 227 | #define USB_PID_ASUS_U3000 0x171f |
228 | #define USB_PID_ASUS_U3000H 0x1736 | ||
197 | #define USB_PID_ASUS_U3100 0x173f | 229 | #define USB_PID_ASUS_U3100 0x173f |
198 | #define USB_PID_YUAN_EC372S 0x1edc | 230 | #define USB_PID_YUAN_EC372S 0x1edc |
231 | #define USB_PID_YUAN_STK7700PH 0x1f08 | ||
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 | ||
199 | 236 | ||
200 | #endif | 237 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c new file mode 100644 index 000000000000..6286fbbe7fb5 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dw2102.c | |||
@@ -0,0 +1,829 @@ | |||
1 | /* DVB USB framework compliant Linux driver for the | ||
2 | * DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card | ||
3 | * | ||
4 | * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #include <linux/version.h> | ||
13 | #include "dw2102.h" | ||
14 | #include "si21xx.h" | ||
15 | #include "stv0299.h" | ||
16 | #include "z0194a.h" | ||
17 | #include "stv0288.h" | ||
18 | #include "stb6000.h" | ||
19 | #include "eds1547.h" | ||
20 | #include "cx24116.h" | ||
21 | |||
22 | #ifndef USB_PID_DW2102 | ||
23 | #define USB_PID_DW2102 0x2102 | ||
24 | #endif | ||
25 | |||
26 | #ifndef USB_PID_DW2104 | ||
27 | #define USB_PID_DW2104 0x2104 | ||
28 | #endif | ||
29 | |||
30 | #define DW210X_READ_MSG 0 | ||
31 | #define DW210X_WRITE_MSG 1 | ||
32 | |||
33 | #define REG_1F_SYMBOLRATE_BYTE0 0x1f | ||
34 | #define REG_20_SYMBOLRATE_BYTE1 0x20 | ||
35 | #define REG_21_SYMBOLRATE_BYTE2 0x21 | ||
36 | /* on my own*/ | ||
37 | #define DW2102_VOLTAGE_CTRL (0x1800) | ||
38 | #define DW2102_RC_QUERY (0x1a00) | ||
39 | |||
40 | struct dw210x_state { | ||
41 | u32 last_key_pressed; | ||
42 | }; | ||
43 | struct dw210x_rc_keys { | ||
44 | u32 keycode; | ||
45 | u32 event; | ||
46 | }; | ||
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 | |||
53 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
54 | |||
55 | static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, | ||
56 | u16 index, u8 * data, u16 len, int flags) | ||
57 | { | ||
58 | int ret; | ||
59 | u8 u8buf[len]; | ||
60 | |||
61 | unsigned int pipe = (flags == DW210X_READ_MSG) ? | ||
62 | usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0); | ||
63 | u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT; | ||
64 | |||
65 | if (flags == DW210X_WRITE_MSG) | ||
66 | memcpy(u8buf, data, len); | ||
67 | ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR, | ||
68 | value, index , u8buf, len, 2000); | ||
69 | |||
70 | if (flags == DW210X_READ_MSG) | ||
71 | memcpy(data, u8buf, len); | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | /* I2C */ | ||
76 | static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
77 | int num) | ||
78 | { | ||
79 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
80 | int i = 0, ret = 0; | ||
81 | u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0}; | ||
82 | u16 value; | ||
83 | |||
84 | if (!d) | ||
85 | return -ENODEV; | ||
86 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
87 | return -EAGAIN; | ||
88 | |||
89 | switch (num) { | ||
90 | case 2: | ||
91 | /* read stv0299 register */ | ||
92 | value = msg[0].buf[0];/* register */ | ||
93 | for (i = 0; i < msg[1].len; i++) { | ||
94 | value = value + i; | ||
95 | ret = dw210x_op_rw(d->udev, 0xb5, value, 0, | ||
96 | buf6, 2, DW210X_READ_MSG); | ||
97 | msg[1].buf[i] = buf6[0]; | ||
98 | } | ||
99 | break; | ||
100 | case 1: | ||
101 | switch (msg[0].addr) { | ||
102 | case 0x68: | ||
103 | /* write to stv0299 register */ | ||
104 | buf6[0] = 0x2a; | ||
105 | buf6[1] = msg[0].buf[0]; | ||
106 | buf6[2] = msg[0].buf[1]; | ||
107 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
108 | buf6, 3, DW210X_WRITE_MSG); | ||
109 | break; | ||
110 | case 0x60: | ||
111 | if (msg[0].flags == 0) { | ||
112 | /* write to tuner pll */ | ||
113 | buf6[0] = 0x2c; | ||
114 | buf6[1] = 5; | ||
115 | buf6[2] = 0xc0; | ||
116 | buf6[3] = msg[0].buf[0]; | ||
117 | buf6[4] = msg[0].buf[1]; | ||
118 | buf6[5] = msg[0].buf[2]; | ||
119 | buf6[6] = msg[0].buf[3]; | ||
120 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
121 | buf6, 7, DW210X_WRITE_MSG); | ||
122 | } else { | ||
123 | /* read from tuner */ | ||
124 | ret = dw210x_op_rw(d->udev, 0xb5, 0, 0, | ||
125 | buf6, 1, DW210X_READ_MSG); | ||
126 | msg[0].buf[0] = buf6[0]; | ||
127 | } | ||
128 | break; | ||
129 | case (DW2102_RC_QUERY): | ||
130 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | ||
131 | buf6, 2, DW210X_READ_MSG); | ||
132 | msg[0].buf[0] = buf6[0]; | ||
133 | msg[0].buf[1] = buf6[1]; | ||
134 | break; | ||
135 | case (DW2102_VOLTAGE_CTRL): | ||
136 | buf6[0] = 0x30; | ||
137 | buf6[1] = msg[0].buf[0]; | ||
138 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | ||
139 | buf6, 2, DW210X_WRITE_MSG); | ||
140 | break; | ||
141 | } | ||
142 | |||
143 | break; | ||
144 | } | ||
145 | |||
146 | mutex_unlock(&d->i2c_mutex); | ||
147 | return num; | ||
148 | } | ||
149 | |||
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) | ||
361 | { | ||
362 | return I2C_FUNC_I2C; | ||
363 | } | ||
364 | |||
365 | static struct i2c_algorithm dw2102_i2c_algo = { | ||
366 | .master_xfer = dw2102_i2c_transfer, | ||
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, | ||
383 | }; | ||
384 | |||
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) | ||
409 | { | ||
410 | static u8 command_13v[1] = {0x00}; | ||
411 | static u8 command_18v[1] = {0x01}; | ||
412 | struct i2c_msg msg[] = { | ||
413 | {.addr = DW2102_VOLTAGE_CTRL, .flags = 0, | ||
414 | .buf = command_13v, .len = 1}, | ||
415 | }; | ||
416 | |||
417 | struct dvb_usb_adapter *udev_adap = | ||
418 | (struct dvb_usb_adapter *)(fe->dvb->priv); | ||
419 | if (voltage == SEC_VOLTAGE_18) | ||
420 | msg[0].buf = command_18v; | ||
421 | i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static struct stv0299_config sharp_z0194a_config = { | ||
426 | .demod_address = 0x68, | ||
427 | .inittab = sharp_z0194a_inittab, | ||
428 | .mclk = 88000000UL, | ||
429 | .invert = 1, | ||
430 | .skip_reinit = 0, | ||
431 | .lock_output = STV0299_LOCKOUTPUT_1, | ||
432 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
433 | .min_delay_ms = 100, | ||
434 | .set_symbol_rate = sharp_z0194a_set_symbol_rate, | ||
435 | }; | ||
436 | |||
437 | static struct cx24116_config dw2104_config = { | ||
438 | .demod_address = 0x55, | ||
439 | .mpg_clk_pos_pol = 0x01, | ||
440 | }; | ||
441 | |||
442 | static struct si21xx_config serit_sp1511lhb_config = { | ||
443 | .demod_address = 0x68, | ||
444 | .min_delay_ms = 100, | ||
445 | |||
446 | }; | ||
447 | |||
448 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) | ||
449 | { | ||
450 | if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, | ||
451 | &d->dev->i2c_adap)) != NULL) { | ||
452 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
453 | info("Attached cx24116!\n"); | ||
454 | return 0; | ||
455 | } | ||
456 | return -EIO; | ||
457 | } | ||
458 | |||
459 | static struct dvb_usb_device_properties dw2102_properties; | ||
460 | |||
461 | static int dw2102_frontend_attach(struct dvb_usb_adapter *d) | ||
462 | { | ||
463 | if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) { | ||
464 | /*dw2102_properties.adapter->tuner_attach = NULL;*/ | ||
465 | d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config, | ||
466 | &d->dev->i2c_adap); | ||
467 | if (d->fe != NULL) { | ||
468 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
469 | info("Attached si21xx!\n"); | ||
470 | return 0; | ||
471 | } | ||
472 | } | ||
473 | if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) { | ||
474 | /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ | ||
475 | d->fe = dvb_attach(stv0288_attach, &earda_config, | ||
476 | &d->dev->i2c_adap); | ||
477 | if (d->fe != NULL) { | ||
478 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
479 | info("Attached stv0288!\n"); | ||
480 | return 0; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) { | ||
485 | /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ | ||
486 | d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config, | ||
487 | &d->dev->i2c_adap); | ||
488 | if (d->fe != NULL) { | ||
489 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
490 | info("Attached stv0299!\n"); | ||
491 | return 0; | ||
492 | } | ||
493 | } | ||
494 | return -EIO; | ||
495 | } | ||
496 | |||
497 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) | ||
498 | { | ||
499 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, | ||
500 | &adap->dev->i2c_adap, DVB_PLL_OPERA1); | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap) | ||
505 | { | ||
506 | dvb_attach(stb6000_attach, adap->fe, 0x61, | ||
507 | &adap->dev->i2c_adap); | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static struct dvb_usb_rc_key dw210x_rc_keys[] = { | ||
513 | { 0xf8, 0x0a, KEY_Q }, /*power*/ | ||
514 | { 0xf8, 0x0c, KEY_M }, /*mute*/ | ||
515 | { 0xf8, 0x11, KEY_1 }, | ||
516 | { 0xf8, 0x12, KEY_2 }, | ||
517 | { 0xf8, 0x13, KEY_3 }, | ||
518 | { 0xf8, 0x14, KEY_4 }, | ||
519 | { 0xf8, 0x15, KEY_5 }, | ||
520 | { 0xf8, 0x16, KEY_6 }, | ||
521 | { 0xf8, 0x17, KEY_7 }, | ||
522 | { 0xf8, 0x18, KEY_8 }, | ||
523 | { 0xf8, 0x19, KEY_9 }, | ||
524 | { 0xf8, 0x10, KEY_0 }, | ||
525 | { 0xf8, 0x1c, KEY_PAGEUP }, /*ch+*/ | ||
526 | { 0xf8, 0x0f, KEY_PAGEDOWN }, /*ch-*/ | ||
527 | { 0xf8, 0x1a, KEY_O }, /*vol+*/ | ||
528 | { 0xf8, 0x0e, KEY_Z }, /*vol-*/ | ||
529 | { 0xf8, 0x04, KEY_R }, /*rec*/ | ||
530 | { 0xf8, 0x09, KEY_D }, /*fav*/ | ||
531 | { 0xf8, 0x08, KEY_BACKSPACE }, /*rewind*/ | ||
532 | { 0xf8, 0x07, KEY_A }, /*fast*/ | ||
533 | { 0xf8, 0x0b, KEY_P }, /*pause*/ | ||
534 | { 0xf8, 0x02, KEY_ESC }, /*cancel*/ | ||
535 | { 0xf8, 0x03, KEY_G }, /*tab*/ | ||
536 | { 0xf8, 0x00, KEY_UP }, /*up*/ | ||
537 | { 0xf8, 0x1f, KEY_ENTER }, /*ok*/ | ||
538 | { 0xf8, 0x01, KEY_DOWN }, /*down*/ | ||
539 | { 0xf8, 0x05, KEY_C }, /*cap*/ | ||
540 | { 0xf8, 0x06, KEY_S }, /*stop*/ | ||
541 | { 0xf8, 0x40, KEY_F }, /*full*/ | ||
542 | { 0xf8, 0x1e, KEY_W }, /*tvmode*/ | ||
543 | { 0xf8, 0x1b, KEY_B }, /*recall*/ | ||
544 | |||
545 | }; | ||
546 | |||
547 | |||
548 | |||
549 | static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
550 | { | ||
551 | struct dw210x_state *st = d->priv; | ||
552 | u8 key[2]; | ||
553 | struct i2c_msg msg[] = { | ||
554 | {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key, | ||
555 | .len = 2}, | ||
556 | }; | ||
557 | int i; | ||
558 | |||
559 | *state = REMOTE_NO_KEY_PRESSED; | ||
560 | if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) { | ||
561 | for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) { | ||
562 | if (dw210x_rc_keys[i].data == msg[0].buf[0]) { | ||
563 | *state = REMOTE_KEY_PRESSED; | ||
564 | *event = dw210x_rc_keys[i].event; | ||
565 | st->last_key_pressed = | ||
566 | dw210x_rc_keys[i].event; | ||
567 | break; | ||
568 | } | ||
569 | st->last_key_pressed = 0; | ||
570 | } | ||
571 | } | ||
572 | /* info("key: %x %x\n",key[0],key[1]); */ | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static struct usb_device_id dw2102_table[] = { | ||
577 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)}, | ||
578 | {USB_DEVICE(USB_VID_CYPRESS, 0x2101)}, | ||
579 | {USB_DEVICE(USB_VID_CYPRESS, 0x2104)}, | ||
580 | {USB_DEVICE(0x9022, 0xd650)}, | ||
581 | { } | ||
582 | }; | ||
583 | |||
584 | MODULE_DEVICE_TABLE(usb, dw2102_table); | ||
585 | |||
586 | static int dw2102_load_firmware(struct usb_device *dev, | ||
587 | const struct firmware *frmwr) | ||
588 | { | ||
589 | u8 *b, *p; | ||
590 | int ret = 0, i; | ||
591 | u8 reset; | ||
592 | u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; | ||
593 | const struct firmware *fw; | ||
594 | const char *filename = "dvb-usb-dw2101.fw"; | ||
595 | switch (dev->descriptor.idProduct) { | ||
596 | case 0x2101: | ||
597 | ret = request_firmware(&fw, filename, &dev->dev); | ||
598 | if (ret != 0) { | ||
599 | err("did not find the firmware file. (%s) " | ||
600 | "Please see linux/Documentation/dvb/ for more details " | ||
601 | "on firmware-problems.", filename); | ||
602 | return ret; | ||
603 | } | ||
604 | break; | ||
605 | default: | ||
606 | fw = frmwr; | ||
607 | break; | ||
608 | } | ||
609 | info("start downloading DW210X firmware"); | ||
610 | p = kmalloc(fw->size, GFP_KERNEL); | ||
611 | reset = 1; | ||
612 | /*stop the CPU*/ | ||
613 | dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG); | ||
614 | dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG); | ||
615 | |||
616 | if (p != NULL) { | ||
617 | memcpy(p, fw->data, fw->size); | ||
618 | for (i = 0; i < fw->size; i += 0x40) { | ||
619 | b = (u8 *) p + i; | ||
620 | if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40, | ||
621 | DW210X_WRITE_MSG) != 0x40) { | ||
622 | err("error while transferring firmware"); | ||
623 | ret = -EINVAL; | ||
624 | break; | ||
625 | } | ||
626 | } | ||
627 | /* restart the CPU */ | ||
628 | reset = 0; | ||
629 | if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, | ||
630 | DW210X_WRITE_MSG) != 1) { | ||
631 | err("could not restart the USB controller CPU."); | ||
632 | ret = -EINVAL; | ||
633 | } | ||
634 | if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, | ||
635 | DW210X_WRITE_MSG) != 1) { | ||
636 | err("could not restart the USB controller CPU."); | ||
637 | ret = -EINVAL; | ||
638 | } | ||
639 | /* init registers */ | ||
640 | switch (dev->descriptor.idProduct) { | ||
641 | case USB_PID_DW2104: | ||
642 | case 0xd650: | ||
643 | reset = 1; | ||
644 | dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, | ||
645 | DW210X_WRITE_MSG); | ||
646 | reset = 0; | ||
647 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, | ||
648 | DW210X_WRITE_MSG); | ||
649 | break; | ||
650 | case USB_PID_DW2102: | ||
651 | dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, | ||
652 | DW210X_WRITE_MSG); | ||
653 | dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, | ||
654 | DW210X_READ_MSG); | ||
655 | /* check STV0299 frontend */ | ||
656 | dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2, | ||
657 | DW210X_READ_MSG); | ||
658 | if (reset16[0] == 0xa1) { | ||
659 | dw2102_properties.i2c_algo = &dw2102_i2c_algo; | ||
660 | dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach; | ||
661 | break; | ||
662 | } else { | ||
663 | /* check STV0288 frontend */ | ||
664 | reset16[0] = 0xd0; | ||
665 | reset16[1] = 1; | ||
666 | reset16[2] = 0; | ||
667 | dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3, | ||
668 | DW210X_WRITE_MSG); | ||
669 | dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3, | ||
670 | DW210X_READ_MSG); | ||
671 | if (reset16[2] == 0x11) { | ||
672 | dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo; | ||
673 | dw2102_properties.adapter->tuner_attach = &dw2102_earda_tuner_attach; | ||
674 | break; | ||
675 | } | ||
676 | } | ||
677 | case 0x2101: | ||
678 | dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, | ||
679 | DW210X_READ_MSG); | ||
680 | dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, | ||
681 | DW210X_READ_MSG); | ||
682 | dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7, | ||
683 | DW210X_READ_MSG); | ||
684 | dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2, | ||
685 | DW210X_READ_MSG); | ||
686 | break; | ||
687 | } | ||
688 | msleep(100); | ||
689 | kfree(p); | ||
690 | } | ||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | static struct dvb_usb_device_properties dw2102_properties = { | ||
695 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
696 | .usb_ctrl = DEVICE_SPECIFIC, | ||
697 | .firmware = "dvb-usb-dw2102.fw", | ||
698 | .size_of_priv = sizeof(struct dw210x_state), | ||
699 | .no_reconnect = 1, | ||
700 | |||
701 | .i2c_algo = &dw2102_serit_i2c_algo, | ||
702 | .rc_key_map = dw210x_rc_keys, | ||
703 | .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), | ||
704 | .rc_interval = 150, | ||
705 | .rc_query = dw2102_rc_query, | ||
706 | |||
707 | .generic_bulk_ctrl_endpoint = 0x81, | ||
708 | /* parameter for the MPEG2-data transfer */ | ||
709 | .num_adapters = 1, | ||
710 | .download_firmware = dw2102_load_firmware, | ||
711 | .read_mac_address = dw210x_read_mac_address, | ||
712 | .adapter = { | ||
713 | { | ||
714 | .frontend_attach = dw2102_frontend_attach, | ||
715 | .streaming_ctrl = NULL, | ||
716 | .tuner_attach = NULL, | ||
717 | .stream = { | ||
718 | .type = USB_BULK, | ||
719 | .count = 8, | ||
720 | .endpoint = 0x82, | ||
721 | .u = { | ||
722 | .bulk = { | ||
723 | .buffersize = 4096, | ||
724 | } | ||
725 | } | ||
726 | }, | ||
727 | } | ||
728 | }, | ||
729 | .num_device_descs = 2, | ||
730 | .devices = { | ||
731 | {"DVBWorld DVB-S 2102 USB2.0", | ||
732 | {&dw2102_table[0], NULL}, | ||
733 | {NULL}, | ||
734 | }, | ||
735 | {"DVBWorld DVB-S 2101 USB2.0", | ||
736 | {&dw2102_table[1], NULL}, | ||
737 | {NULL}, | ||
738 | }, | ||
739 | } | ||
740 | }; | ||
741 | |||
742 | static struct dvb_usb_device_properties dw2104_properties = { | ||
743 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
744 | .usb_ctrl = DEVICE_SPECIFIC, | ||
745 | .firmware = "dvb-usb-dw2104.fw", | ||
746 | .size_of_priv = sizeof(struct dw210x_state), | ||
747 | .no_reconnect = 1, | ||
748 | |||
749 | .i2c_algo = &dw2104_i2c_algo, | ||
750 | .rc_key_map = dw210x_rc_keys, | ||
751 | .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys), | ||
752 | .rc_interval = 150, | ||
753 | .rc_query = dw2102_rc_query, | ||
754 | |||
755 | .generic_bulk_ctrl_endpoint = 0x81, | ||
756 | /* parameter for the MPEG2-data transfer */ | ||
757 | .num_adapters = 1, | ||
758 | .download_firmware = dw2102_load_firmware, | ||
759 | .read_mac_address = dw210x_read_mac_address, | ||
760 | .adapter = { | ||
761 | { | ||
762 | .frontend_attach = dw2104_frontend_attach, | ||
763 | .streaming_ctrl = NULL, | ||
764 | /*.tuner_attach = dw2104_tuner_attach,*/ | ||
765 | .stream = { | ||
766 | .type = USB_BULK, | ||
767 | .count = 8, | ||
768 | .endpoint = 0x82, | ||
769 | .u = { | ||
770 | .bulk = { | ||
771 | .buffersize = 4096, | ||
772 | } | ||
773 | } | ||
774 | }, | ||
775 | } | ||
776 | }, | ||
777 | .num_device_descs = 2, | ||
778 | .devices = { | ||
779 | { "DVBWorld DW2104 USB2.0", | ||
780 | {&dw2102_table[2], NULL}, | ||
781 | {NULL}, | ||
782 | }, | ||
783 | { "TeVii S650 USB2.0", | ||
784 | {&dw2102_table[3], NULL}, | ||
785 | {NULL}, | ||
786 | }, | ||
787 | } | ||
788 | }; | ||
789 | |||
790 | static int dw2102_probe(struct usb_interface *intf, | ||
791 | const struct usb_device_id *id) | ||
792 | { | ||
793 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, | ||
794 | THIS_MODULE, NULL, adapter_nr) || | ||
795 | 0 == dvb_usb_device_init(intf, &dw2104_properties, | ||
796 | THIS_MODULE, NULL, adapter_nr)) { | ||
797 | return 0; | ||
798 | } | ||
799 | return -ENODEV; | ||
800 | } | ||
801 | |||
802 | static struct usb_driver dw2102_driver = { | ||
803 | .name = "dw2102", | ||
804 | .probe = dw2102_probe, | ||
805 | .disconnect = dvb_usb_device_exit, | ||
806 | .id_table = dw2102_table, | ||
807 | }; | ||
808 | |||
809 | static int __init dw2102_module_init(void) | ||
810 | { | ||
811 | int ret = usb_register(&dw2102_driver); | ||
812 | if (ret) | ||
813 | err("usb_register failed. Error number %d", ret); | ||
814 | |||
815 | return ret; | ||
816 | } | ||
817 | |||
818 | static void __exit dw2102_module_exit(void) | ||
819 | { | ||
820 | usb_deregister(&dw2102_driver); | ||
821 | } | ||
822 | |||
823 | module_init(dw2102_module_init); | ||
824 | module_exit(dw2102_module_exit); | ||
825 | |||
826 | MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); | ||
827 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device"); | ||
828 | MODULE_VERSION("0.1"); | ||
829 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h new file mode 100644 index 000000000000..e3370734e95a --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dw2102.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _DW2102_H_ | ||
2 | #define _DW2102_H_ | ||
3 | |||
4 | #define DVB_USB_LOG_PREFIX "dw2102" | ||
5 | #include "dvb-usb.h" | ||
6 | |||
7 | #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args) | ||
8 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c index 037f7ffb47b2..6f596ed41761 100644 --- a/drivers/media/dvb/dvb-usb/gl861.c +++ b/drivers/media/dvb/dvb-usb/gl861.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* DVB USB compliant linux driver for GL861 USB2.0 devices. | 1 | /* DVB USB compliant linux driver for GL861 USB2.0 devices. |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify it | 3 | * This program is free software; you can redistribute it and/or modify it |
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the |
5 | * Software Foundation, version 2. | 5 | * Free Software Foundation, version 2. |
6 | * | 6 | * |
7 | * see Documentation/dvb/README.dvb-usb for more information | 7 | * see Documentation/dvb/README.dvb-usb for more information |
8 | */ | 8 | */ |
@@ -13,9 +13,9 @@ | |||
13 | 13 | ||
14 | /* debug */ | 14 | /* debug */ |
15 | static int dvb_usb_gl861_debug; | 15 | static int dvb_usb_gl861_debug; |
16 | module_param_named(debug,dvb_usb_gl861_debug, int, 0644); | 16 | module_param_named(debug, dvb_usb_gl861_debug, int, 0644); |
17 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | 17 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." |
18 | 18 | DVB_USB_DEBUG_STATUS); | |
19 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 19 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
20 | 20 | ||
21 | static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, | 21 | static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, |
@@ -70,7 +70,7 @@ static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
70 | /* write/read request */ | 70 | /* write/read request */ |
71 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | 71 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { |
72 | if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, | 72 | if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, |
73 | msg[i].len, msg[i+1].buf, msg[i+1].len) < 0) | 73 | msg[i].len, msg[i+1].buf, msg[i+1].len) < 0) |
74 | break; | 74 | break; |
75 | i++; | 75 | i++; |
76 | } else | 76 | } else |
@@ -102,12 +102,13 @@ static struct zl10353_config gl861_zl10353_config = { | |||
102 | 102 | ||
103 | static int gl861_frontend_attach(struct dvb_usb_adapter *adap) | 103 | static int gl861_frontend_attach(struct dvb_usb_adapter *adap) |
104 | { | 104 | { |
105 | if ((adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config, | ||
106 | &adap->dev->i2c_adap)) != NULL) { | ||
107 | return 0; | ||
108 | } | ||
109 | 105 | ||
110 | return -EIO; | 106 | adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config, |
107 | &adap->dev->i2c_adap); | ||
108 | if (adap->fe == NULL) | ||
109 | return -EIO; | ||
110 | |||
111 | return 0; | ||
111 | } | 112 | } |
112 | 113 | ||
113 | static struct qt1010_config gl861_qt1010_config = { | 114 | static struct qt1010_config gl861_qt1010_config = { |
@@ -156,7 +157,7 @@ static struct usb_device_id gl861_table [] = { | |||
156 | { USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) }, | 157 | { USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) }, |
157 | { } /* Terminating entry */ | 158 | { } /* Terminating entry */ |
158 | }; | 159 | }; |
159 | MODULE_DEVICE_TABLE (usb, gl861_table); | 160 | MODULE_DEVICE_TABLE(usb, gl861_table); |
160 | 161 | ||
161 | static struct dvb_usb_device_properties gl861_properties = { | 162 | static struct dvb_usb_device_properties gl861_properties = { |
162 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | 163 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
@@ -180,7 +181,7 @@ static struct dvb_usb_device_properties gl861_properties = { | |||
180 | } | 181 | } |
181 | } | 182 | } |
182 | }, | 183 | }, |
183 | }}, | 184 | } }, |
184 | .i2c_algo = &gl861_i2c_algo, | 185 | .i2c_algo = &gl861_i2c_algo, |
185 | 186 | ||
186 | .num_device_descs = 2, | 187 | .num_device_descs = 2, |
@@ -210,12 +211,11 @@ static int __init gl861_module_init(void) | |||
210 | { | 211 | { |
211 | int ret; | 212 | int ret; |
212 | 213 | ||
213 | if ((ret = usb_register(&gl861_driver))) { | 214 | ret = usb_register(&gl861_driver); |
215 | if (ret) | ||
214 | err("usb_register failed. Error number %d", ret); | 216 | err("usb_register failed. Error number %d", ret); |
215 | return ret; | ||
216 | } | ||
217 | 217 | ||
218 | return 0; | 218 | return ret; |
219 | } | 219 | } |
220 | 220 | ||
221 | static void __exit gl861_module_exit(void) | 221 | static void __exit gl861_module_exit(void) |
@@ -224,8 +224,8 @@ static void __exit gl861_module_exit(void) | |||
224 | usb_deregister(&gl861_driver); | 224 | usb_deregister(&gl861_driver); |
225 | } | 225 | } |
226 | 226 | ||
227 | module_init (gl861_module_init); | 227 | module_init(gl861_module_init); |
228 | module_exit (gl861_module_exit); | 228 | module_exit(gl861_module_exit); |
229 | 229 | ||
230 | MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>"); | 230 | MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>"); |
231 | MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861"); | 231 | MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861"); |
diff --git a/drivers/media/dvb/dvb-usb/gl861.h b/drivers/media/dvb/dvb-usb/gl861.h index 72a51afd5ee3..c54855e2c233 100644 --- a/drivers/media/dvb/dvb-usb/gl861.h +++ b/drivers/media/dvb/dvb-usb/gl861.h | |||
@@ -4,7 +4,7 @@ | |||
4 | #define DVB_USB_LOG_PREFIX "gl861" | 4 | #define DVB_USB_LOG_PREFIX "gl861" |
5 | #include "dvb-usb.h" | 5 | #include "dvb-usb.h" |
6 | 6 | ||
7 | #define deb_rc(args...) dprintk(dvb_usb_gl861_debug,0x01,args) | 7 | #define deb_rc(args...) dprintk(dvb_usb_gl861_debug, 0x01, args) |
8 | 8 | ||
9 | #define GL861_WRITE 0x40 | 9 | #define GL861_WRITE 0x40 |
10 | #define GL861_READ 0xc0 | 10 | #define GL861_READ 0xc0 |