diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb-v2')
42 files changed, 17826 insertions, 0 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig new file mode 100644 index 000000000000..276374fbaf4f --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/Kconfig | |||
@@ -0,0 +1,146 @@ | |||
1 | config DVB_USB_V2 | ||
2 | tristate "Support for various USB DVB devices v2" | ||
3 | depends on DVB_CORE && USB && I2C && RC_CORE | ||
4 | help | ||
5 | By enabling this you will be able to choose the various supported | ||
6 | USB1.1 and USB2.0 DVB devices. | ||
7 | |||
8 | Almost every USB device needs a firmware, please look into | ||
9 | <file:Documentation/dvb/README.dvb-usb>. | ||
10 | |||
11 | For a complete list of supported USB devices see the LinuxTV DVB Wiki: | ||
12 | <http://www.linuxtv.org/wiki/index.php/DVB_USB> | ||
13 | |||
14 | Say Y if you own a USB DVB device. | ||
15 | |||
16 | config DVB_USB_CYPRESS_FIRMWARE | ||
17 | tristate "Cypress firmware helper routines" | ||
18 | depends on DVB_USB_V2 | ||
19 | |||
20 | config DVB_USB_AF9015 | ||
21 | tristate "Afatech AF9015 DVB-T USB2.0 support" | ||
22 | depends on DVB_USB_V2 | ||
23 | select DVB_AF9013 | ||
24 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
25 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE | ||
26 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE | ||
27 | select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE | ||
28 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | ||
29 | select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE | ||
30 | select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE | ||
31 | select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE | ||
32 | help | ||
33 | Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver | ||
34 | |||
35 | config DVB_USB_AF9035 | ||
36 | tristate "Afatech AF9035 DVB-T USB2.0 support" | ||
37 | depends on DVB_USB_V2 | ||
38 | select DVB_AF9033 | ||
39 | select MEDIA_TUNER_TUA9001 if !MEDIA_TUNER_CUSTOMISE | ||
40 | select MEDIA_TUNER_FC0011 if !MEDIA_TUNER_CUSTOMISE | ||
41 | select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE | ||
42 | select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE | ||
43 | help | ||
44 | Say Y here to support the Afatech AF9035 based DVB USB receiver. | ||
45 | |||
46 | config DVB_USB_ANYSEE | ||
47 | tristate "Anysee DVB-T/C USB2.0 support" | ||
48 | depends on DVB_USB_V2 | ||
49 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
50 | select DVB_MT352 if !DVB_FE_CUSTOMISE | ||
51 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
52 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE | ||
53 | select MEDIA_TUNER_TDA18212 if !MEDIA_TUNER_CUSTOMISE | ||
54 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | ||
55 | select DVB_STV0900 if !DVB_FE_CUSTOMISE | ||
56 | select DVB_STV6110 if !DVB_FE_CUSTOMISE | ||
57 | select DVB_ISL6423 if !DVB_FE_CUSTOMISE | ||
58 | select DVB_CXD2820R if !DVB_FE_CUSTOMISE | ||
59 | help | ||
60 | Say Y here to support the Anysee E30, Anysee E30 Plus or | ||
61 | Anysee E30 C Plus DVB USB2.0 receiver. | ||
62 | |||
63 | config DVB_USB_AU6610 | ||
64 | tristate "Alcor Micro AU6610 USB2.0 support" | ||
65 | depends on DVB_USB_V2 | ||
66 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
67 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE | ||
68 | help | ||
69 | Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. | ||
70 | |||
71 | config DVB_USB_AZ6007 | ||
72 | tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support" | ||
73 | depends on DVB_USB_V2 | ||
74 | select DVB_USB_CYPRESS_FIRMWARE | ||
75 | select DVB_DRXK if !DVB_FE_CUSTOMISE | ||
76 | select MEDIA_TUNER_MT2063 if !DVB_FE_CUSTOMISE | ||
77 | help | ||
78 | Say Y here to support the AZ6007 receivers like Terratec H7. | ||
79 | |||
80 | config DVB_USB_CE6230 | ||
81 | tristate "Intel CE6230 DVB-T USB2.0 support" | ||
82 | depends on DVB_USB_V2 | ||
83 | select DVB_ZL10353 | ||
84 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | ||
85 | help | ||
86 | Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver | ||
87 | |||
88 | config DVB_USB_EC168 | ||
89 | tristate "E3C EC168 DVB-T USB2.0 support" | ||
90 | depends on DVB_USB_V2 | ||
91 | select DVB_EC100 | ||
92 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | ||
93 | help | ||
94 | Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. | ||
95 | |||
96 | config DVB_USB_GL861 | ||
97 | tristate "Genesys Logic GL861 USB2.0 support" | ||
98 | depends on DVB_USB_V2 | ||
99 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | ||
100 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE | ||
101 | help | ||
102 | Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 | ||
103 | receiver with USB ID 0db0:5581. | ||
104 | |||
105 | config DVB_USB_IT913X | ||
106 | tristate "ITE IT913X DVB-T USB2.0 support" | ||
107 | depends on DVB_USB_V2 | ||
108 | select DVB_IT913X_FE | ||
109 | help | ||
110 | Say Y here to support the ITE IT913X DVB-T USB2.0 | ||
111 | |||
112 | config DVB_USB_LME2510 | ||
113 | tristate "LME DM04/QQBOX DVB-S USB2.0 support" | ||
114 | depends on DVB_USB_V2 | ||
115 | select DVB_TDA10086 if !DVB_FE_CUSTOMISE | ||
116 | select DVB_TDA826X if !DVB_FE_CUSTOMISE | ||
117 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | ||
118 | select DVB_IX2505V if !DVB_FE_CUSTOMISE | ||
119 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | ||
120 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
121 | select DVB_M88RS2000 if !DVB_FE_CUSTOMISE | ||
122 | help | ||
123 | Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 | ||
124 | |||
125 | config DVB_USB_MXL111SF | ||
126 | tristate "MxL111SF DTV USB2.0 support" | ||
127 | depends on DVB_USB_V2 | ||
128 | select DVB_LGDT3305 if !DVB_FE_CUSTOMISE | ||
129 | select DVB_LG2160 if !DVB_FE_CUSTOMISE | ||
130 | select VIDEO_TVEEPROM | ||
131 | help | ||
132 | Say Y here to support the MxL111SF USB2.0 DTV receiver. | ||
133 | |||
134 | config DVB_USB_RTL28XXU | ||
135 | tristate "Realtek RTL28xxU DVB USB support" | ||
136 | depends on DVB_USB_V2 && EXPERIMENTAL | ||
137 | select DVB_RTL2830 | ||
138 | select DVB_RTL2832 | ||
139 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE | ||
140 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE | ||
141 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | ||
142 | select MEDIA_TUNER_FC0012 if !MEDIA_TUNER_CUSTOMISE | ||
143 | select MEDIA_TUNER_FC0013 if !MEDIA_TUNER_CUSTOMISE | ||
144 | help | ||
145 | Say Y here to support the Realtek RTL28xxU DVB USB receiver. | ||
146 | |||
diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile new file mode 100644 index 000000000000..24248b3acd4f --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/Makefile | |||
@@ -0,0 +1,48 @@ | |||
1 | dvb_usbv2-objs = dvb_usb_core.o dvb_usb_urb.o usb_urb.o | ||
2 | obj-$(CONFIG_DVB_USB_V2) += dvb_usbv2.o | ||
3 | |||
4 | dvb_usb_cypress_firmware-objs = cypress_firmware.o | ||
5 | obj-$(CONFIG_DVB_USB_CYPRESS_FIRMWARE) += dvb_usb_cypress_firmware.o | ||
6 | |||
7 | dvb-usb-af9015-objs = af9015.o | ||
8 | obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o | ||
9 | |||
10 | dvb-usb-af9035-objs = af9035.o | ||
11 | obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o | ||
12 | |||
13 | dvb-usb-anysee-objs = anysee.o | ||
14 | obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o | ||
15 | |||
16 | dvb-usb-au6610-objs = au6610.o | ||
17 | obj-$(CONFIG_DVB_USB_AU6610) += dvb-usb-au6610.o | ||
18 | |||
19 | dvb-usb-az6007-objs = az6007.o | ||
20 | obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o | ||
21 | |||
22 | dvb-usb-ce6230-objs = ce6230.o | ||
23 | obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o | ||
24 | |||
25 | dvb-usb-ec168-objs = ec168.o | ||
26 | obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o | ||
27 | |||
28 | dvb-usb-it913x-objs = it913x.o | ||
29 | obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o | ||
30 | |||
31 | dvb-usb-lmedm04-objs = lmedm04.o | ||
32 | obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o | ||
33 | |||
34 | dvb-usb-gl861-objs = gl861.o | ||
35 | obj-$(CONFIG_DVB_USB_GL861) += dvb-usb-gl861.o | ||
36 | |||
37 | dvb-usb-mxl111sf-objs = mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o mxl111sf-gpio.o | ||
38 | obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o | ||
39 | obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o | ||
40 | obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o | ||
41 | |||
42 | dvb-usb-rtl28xxu-objs = rtl28xxu.o | ||
43 | obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o | ||
44 | |||
45 | ccflags-y += -I$(srctree)/drivers/media/dvb-core | ||
46 | ccflags-y += -I$(srctree)/drivers/media/dvb-frontends | ||
47 | ccflags-y += -I$(srctree)/drivers/media/common/tuners | ||
48 | |||
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c new file mode 100644 index 000000000000..e77429b37a7d --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/af9015.c | |||
@@ -0,0 +1,1434 @@ | |||
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 | |||
26 | static int dvb_usb_af9015_debug; | ||
27 | module_param_named(debug, dvb_usb_af9015_debug, int, 0644); | ||
28 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
29 | static int dvb_usb_af9015_remote; | ||
30 | module_param_named(remote, dvb_usb_af9015_remote, int, 0644); | ||
31 | MODULE_PARM_DESC(remote, "select remote"); | ||
32 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
33 | |||
34 | static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) | ||
35 | { | ||
36 | #define BUF_LEN 63 | ||
37 | #define REQ_HDR_LEN 8 /* send header size */ | ||
38 | #define ACK_HDR_LEN 2 /* rece header size */ | ||
39 | struct af9015_state *state = d_to_priv(d); | ||
40 | int ret, wlen, rlen; | ||
41 | u8 buf[BUF_LEN]; | ||
42 | u8 write = 1; | ||
43 | |||
44 | buf[0] = req->cmd; | ||
45 | buf[1] = state->seq++; | ||
46 | buf[2] = req->i2c_addr; | ||
47 | buf[3] = req->addr >> 8; | ||
48 | buf[4] = req->addr & 0xff; | ||
49 | buf[5] = req->mbox; | ||
50 | buf[6] = req->addr_len; | ||
51 | buf[7] = req->data_len; | ||
52 | |||
53 | switch (req->cmd) { | ||
54 | case GET_CONFIG: | ||
55 | case READ_MEMORY: | ||
56 | case RECONNECT_USB: | ||
57 | write = 0; | ||
58 | break; | ||
59 | case READ_I2C: | ||
60 | write = 0; | ||
61 | buf[2] |= 0x01; /* set I2C direction */ | ||
62 | case WRITE_I2C: | ||
63 | buf[0] = READ_WRITE_I2C; | ||
64 | break; | ||
65 | case WRITE_MEMORY: | ||
66 | if (((req->addr & 0xff00) == 0xff00) || | ||
67 | ((req->addr & 0xff00) == 0xae00)) | ||
68 | buf[0] = WRITE_VIRTUAL_MEMORY; | ||
69 | case WRITE_VIRTUAL_MEMORY: | ||
70 | case COPY_FIRMWARE: | ||
71 | case DOWNLOAD_FIRMWARE: | ||
72 | case BOOT: | ||
73 | break; | ||
74 | default: | ||
75 | err("unknown command:%d", req->cmd); | ||
76 | ret = -1; | ||
77 | goto error; | ||
78 | } | ||
79 | |||
80 | /* buffer overflow check */ | ||
81 | if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) || | ||
82 | (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) { | ||
83 | err("too much data; cmd:%d len:%d", req->cmd, req->data_len); | ||
84 | ret = -EINVAL; | ||
85 | goto error; | ||
86 | } | ||
87 | |||
88 | /* write receives seq + status = 2 bytes | ||
89 | read receives seq + status + data = 2 + N bytes */ | ||
90 | wlen = REQ_HDR_LEN; | ||
91 | rlen = ACK_HDR_LEN; | ||
92 | if (write) { | ||
93 | wlen += req->data_len; | ||
94 | memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len); | ||
95 | } else { | ||
96 | rlen += req->data_len; | ||
97 | } | ||
98 | |||
99 | /* no ack for these packets */ | ||
100 | if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) | ||
101 | rlen = 0; | ||
102 | |||
103 | ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen); | ||
104 | if (ret) | ||
105 | goto error; | ||
106 | |||
107 | /* check status */ | ||
108 | if (rlen && buf[1]) { | ||
109 | err("command failed:%d", buf[1]); | ||
110 | ret = -1; | ||
111 | goto error; | ||
112 | } | ||
113 | |||
114 | /* read request, copy returned data to return buf */ | ||
115 | if (!write) | ||
116 | memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len); | ||
117 | error: | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val, | ||
122 | u8 len) | ||
123 | { | ||
124 | struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, | ||
125 | val}; | ||
126 | return af9015_ctrl_msg(d, &req); | ||
127 | } | ||
128 | |||
129 | static int af9015_read_regs(struct dvb_usb_device *d, u16 addr, u8 *val, u8 len) | ||
130 | { | ||
131 | struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, | ||
132 | val}; | ||
133 | return af9015_ctrl_msg(d, &req); | ||
134 | } | ||
135 | |||
136 | static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val) | ||
137 | { | ||
138 | return af9015_write_regs(d, addr, &val, 1); | ||
139 | } | ||
140 | |||
141 | static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val) | ||
142 | { | ||
143 | return af9015_read_regs(d, addr, val, 1); | ||
144 | } | ||
145 | |||
146 | static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, | ||
147 | u8 val) | ||
148 | { | ||
149 | struct af9015_state *state = d_to_priv(d); | ||
150 | struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val}; | ||
151 | |||
152 | if (addr == state->af9013_config[0].i2c_addr || | ||
153 | addr == state->af9013_config[1].i2c_addr) | ||
154 | req.addr_len = 3; | ||
155 | |||
156 | return af9015_ctrl_msg(d, &req); | ||
157 | } | ||
158 | |||
159 | static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, | ||
160 | u8 *val) | ||
161 | { | ||
162 | struct af9015_state *state = d_to_priv(d); | ||
163 | struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val}; | ||
164 | |||
165 | if (addr == state->af9013_config[0].i2c_addr || | ||
166 | addr == state->af9013_config[1].i2c_addr) | ||
167 | req.addr_len = 3; | ||
168 | |||
169 | return af9015_ctrl_msg(d, &req); | ||
170 | } | ||
171 | |||
172 | static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op) | ||
173 | { | ||
174 | int ret; | ||
175 | u8 val, mask = 0x01; | ||
176 | |||
177 | ret = af9015_read_reg(d, addr, &val); | ||
178 | if (ret) | ||
179 | return ret; | ||
180 | |||
181 | mask <<= bit; | ||
182 | if (op) { | ||
183 | /* set bit */ | ||
184 | val |= mask; | ||
185 | } else { | ||
186 | /* clear bit */ | ||
187 | mask ^= 0xff; | ||
188 | val &= mask; | ||
189 | } | ||
190 | |||
191 | return af9015_write_reg(d, addr, val); | ||
192 | } | ||
193 | |||
194 | static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) | ||
195 | { | ||
196 | return af9015_do_reg_bit(d, addr, bit, 1); | ||
197 | } | ||
198 | |||
199 | static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) | ||
200 | { | ||
201 | return af9015_do_reg_bit(d, addr, bit, 0); | ||
202 | } | ||
203 | |||
204 | static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
205 | int num) | ||
206 | { | ||
207 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
208 | struct af9015_state *state = d_to_priv(d); | ||
209 | int ret = 0, i = 0; | ||
210 | u16 addr; | ||
211 | u8 uninitialized_var(mbox), addr_len; | ||
212 | struct req_t req; | ||
213 | |||
214 | /* | ||
215 | The bus lock is needed because there is two tuners both using same I2C-address. | ||
216 | Due to that the only way to select correct tuner is use demodulator I2C-gate. | ||
217 | |||
218 | ................................................ | ||
219 | . AF9015 includes integrated AF9013 demodulator. | ||
220 | . ____________ ____________ . ____________ | ||
221 | .| uC | | demod | . | tuner | | ||
222 | .|------------| |------------| . |------------| | ||
223 | .| AF9015 | | AF9013/5 | . | MXL5003 | | ||
224 | .| |--+----I2C-------|-----/ -----|-.-----I2C-------| | | ||
225 | .| | | | addr 0x38 | . | addr 0xc6 | | ||
226 | .|____________| | |____________| . |____________| | ||
227 | .................|.............................. | ||
228 | | ____________ ____________ | ||
229 | | | demod | | tuner | | ||
230 | | |------------| |------------| | ||
231 | | | AF9013 | | MXL5003 | | ||
232 | +----I2C-------|-----/ -----|-------I2C-------| | | ||
233 | | addr 0x3a | | addr 0xc6 | | ||
234 | |____________| |____________| | ||
235 | */ | ||
236 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
237 | return -EAGAIN; | ||
238 | |||
239 | while (i < num) { | ||
240 | if (msg[i].addr == state->af9013_config[0].i2c_addr || | ||
241 | msg[i].addr == state->af9013_config[1].i2c_addr) { | ||
242 | addr = msg[i].buf[0] << 8; | ||
243 | addr += msg[i].buf[1]; | ||
244 | mbox = msg[i].buf[2]; | ||
245 | addr_len = 3; | ||
246 | } else { | ||
247 | addr = msg[i].buf[0]; | ||
248 | addr_len = 1; | ||
249 | /* mbox is don't care in that case */ | ||
250 | } | ||
251 | |||
252 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
253 | if (msg[i].len > 3 || msg[i+1].len > 61) { | ||
254 | ret = -EOPNOTSUPP; | ||
255 | goto error; | ||
256 | } | ||
257 | if (msg[i].addr == state->af9013_config[0].i2c_addr) | ||
258 | req.cmd = READ_MEMORY; | ||
259 | else | ||
260 | req.cmd = READ_I2C; | ||
261 | req.i2c_addr = msg[i].addr; | ||
262 | req.addr = addr; | ||
263 | req.mbox = mbox; | ||
264 | req.addr_len = addr_len; | ||
265 | req.data_len = msg[i+1].len; | ||
266 | req.data = &msg[i+1].buf[0]; | ||
267 | ret = af9015_ctrl_msg(d, &req); | ||
268 | i += 2; | ||
269 | } else if (msg[i].flags & I2C_M_RD) { | ||
270 | if (msg[i].len > 61) { | ||
271 | ret = -EOPNOTSUPP; | ||
272 | goto error; | ||
273 | } | ||
274 | if (msg[i].addr == state->af9013_config[0].i2c_addr) { | ||
275 | ret = -EINVAL; | ||
276 | goto error; | ||
277 | } | ||
278 | req.cmd = READ_I2C; | ||
279 | req.i2c_addr = msg[i].addr; | ||
280 | req.addr = addr; | ||
281 | req.mbox = mbox; | ||
282 | req.addr_len = addr_len; | ||
283 | req.data_len = msg[i].len; | ||
284 | req.data = &msg[i].buf[0]; | ||
285 | ret = af9015_ctrl_msg(d, &req); | ||
286 | i += 1; | ||
287 | } else { | ||
288 | if (msg[i].len > 21) { | ||
289 | ret = -EOPNOTSUPP; | ||
290 | goto error; | ||
291 | } | ||
292 | if (msg[i].addr == state->af9013_config[0].i2c_addr) | ||
293 | req.cmd = WRITE_MEMORY; | ||
294 | else | ||
295 | req.cmd = WRITE_I2C; | ||
296 | req.i2c_addr = msg[i].addr; | ||
297 | req.addr = addr; | ||
298 | req.mbox = mbox; | ||
299 | req.addr_len = addr_len; | ||
300 | req.data_len = msg[i].len-addr_len; | ||
301 | req.data = &msg[i].buf[addr_len]; | ||
302 | ret = af9015_ctrl_msg(d, &req); | ||
303 | i += 1; | ||
304 | } | ||
305 | if (ret) | ||
306 | goto error; | ||
307 | |||
308 | } | ||
309 | ret = i; | ||
310 | |||
311 | error: | ||
312 | mutex_unlock(&d->i2c_mutex); | ||
313 | |||
314 | return ret; | ||
315 | } | ||
316 | |||
317 | static u32 af9015_i2c_func(struct i2c_adapter *adapter) | ||
318 | { | ||
319 | return I2C_FUNC_I2C; | ||
320 | } | ||
321 | |||
322 | static struct i2c_algorithm af9015_i2c_algo = { | ||
323 | .master_xfer = af9015_i2c_xfer, | ||
324 | .functionality = af9015_i2c_func, | ||
325 | }; | ||
326 | |||
327 | static int af9015_identify_state(struct dvb_usb_device *d, const char **name) | ||
328 | { | ||
329 | int ret; | ||
330 | u8 reply; | ||
331 | struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply}; | ||
332 | |||
333 | ret = af9015_ctrl_msg(d, &req); | ||
334 | if (ret) | ||
335 | return ret; | ||
336 | |||
337 | deb_info("%s: reply:%02x\n", __func__, reply); | ||
338 | if (reply == 0x02) | ||
339 | ret = WARM; | ||
340 | else | ||
341 | ret = COLD; | ||
342 | |||
343 | return ret; | ||
344 | } | ||
345 | |||
346 | static int af9015_download_firmware(struct dvb_usb_device *d, | ||
347 | const struct firmware *fw) | ||
348 | { | ||
349 | struct af9015_state *state = d_to_priv(d); | ||
350 | int i, len, remaining, ret; | ||
351 | struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL}; | ||
352 | u16 checksum = 0; | ||
353 | |||
354 | deb_info("%s:\n", __func__); | ||
355 | |||
356 | /* calc checksum */ | ||
357 | for (i = 0; i < fw->size; i++) | ||
358 | checksum += fw->data[i]; | ||
359 | |||
360 | state->firmware_size = fw->size; | ||
361 | state->firmware_checksum = checksum; | ||
362 | |||
363 | #define FW_ADDR 0x5100 /* firmware start address */ | ||
364 | #define LEN_MAX 55 /* max packet size */ | ||
365 | for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) { | ||
366 | len = remaining; | ||
367 | if (len > LEN_MAX) | ||
368 | len = LEN_MAX; | ||
369 | |||
370 | req.data_len = len; | ||
371 | req.data = (u8 *) &fw->data[fw->size - remaining]; | ||
372 | req.addr = FW_ADDR + fw->size - remaining; | ||
373 | |||
374 | ret = af9015_ctrl_msg(d, &req); | ||
375 | if (ret) { | ||
376 | err("firmware download failed:%d", ret); | ||
377 | goto error; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | /* firmware loaded, request boot */ | ||
382 | req.cmd = BOOT; | ||
383 | req.data_len = 0; | ||
384 | ret = af9015_ctrl_msg(d, &req); | ||
385 | if (ret) { | ||
386 | err("firmware boot failed:%d", ret); | ||
387 | goto error; | ||
388 | } | ||
389 | |||
390 | error: | ||
391 | return ret; | ||
392 | } | ||
393 | |||
394 | /* hash (and dump) eeprom */ | ||
395 | static int af9015_eeprom_hash(struct dvb_usb_device *d) | ||
396 | { | ||
397 | struct af9015_state *state = d_to_priv(d); | ||
398 | int ret; | ||
399 | static const unsigned int eeprom_size = 256; | ||
400 | unsigned int reg; | ||
401 | u8 val, *eeprom; | ||
402 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; | ||
403 | |||
404 | eeprom = kmalloc(eeprom_size, GFP_KERNEL); | ||
405 | if (eeprom == NULL) | ||
406 | return -ENOMEM; | ||
407 | |||
408 | for (reg = 0; reg < eeprom_size; reg++) { | ||
409 | req.addr = reg; | ||
410 | ret = af9015_ctrl_msg(d, &req); | ||
411 | if (ret) | ||
412 | goto free; | ||
413 | |||
414 | eeprom[reg] = val; | ||
415 | } | ||
416 | |||
417 | if (dvb_usb_af9015_debug & 0x01) | ||
418 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom, | ||
419 | eeprom_size); | ||
420 | |||
421 | BUG_ON(eeprom_size % 4); | ||
422 | |||
423 | state->eeprom_sum = 0; | ||
424 | for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) { | ||
425 | state->eeprom_sum *= GOLDEN_RATIO_PRIME_32; | ||
426 | state->eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]); | ||
427 | } | ||
428 | |||
429 | deb_info("%s: eeprom sum=%.8x\n", __func__, state->eeprom_sum); | ||
430 | |||
431 | ret = 0; | ||
432 | free: | ||
433 | kfree(eeprom); | ||
434 | return ret; | ||
435 | } | ||
436 | |||
437 | static int af9015_read_config(struct dvb_usb_device *d) | ||
438 | { | ||
439 | struct af9015_state *state = d_to_priv(d); | ||
440 | int ret; | ||
441 | u8 val, i, offset = 0; | ||
442 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; | ||
443 | |||
444 | deb_info("%s:\n", __func__); | ||
445 | |||
446 | /* IR remote controller */ | ||
447 | req.addr = AF9015_EEPROM_IR_MODE; | ||
448 | /* first message will timeout often due to possible hw bug */ | ||
449 | for (i = 0; i < 4; i++) { | ||
450 | ret = af9015_ctrl_msg(d, &req); | ||
451 | if (!ret) | ||
452 | break; | ||
453 | } | ||
454 | if (ret) | ||
455 | goto error; | ||
456 | |||
457 | ret = af9015_eeprom_hash(d); | ||
458 | if (ret) | ||
459 | goto error; | ||
460 | |||
461 | deb_info("%s: IR mode=%d\n", __func__, val); | ||
462 | state->ir_mode = val; | ||
463 | |||
464 | /* TS mode - one or two receivers */ | ||
465 | req.addr = AF9015_EEPROM_TS_MODE; | ||
466 | ret = af9015_ctrl_msg(d, &req); | ||
467 | if (ret) | ||
468 | goto error; | ||
469 | |||
470 | state->dual_mode = val; | ||
471 | deb_info("%s: TS mode=%d\n", __func__, state->dual_mode); | ||
472 | |||
473 | /* disable 2nd adapter because we don't have PID-filters */ | ||
474 | if (d->udev->speed == USB_SPEED_FULL) | ||
475 | state->dual_mode = 0; | ||
476 | |||
477 | if (state->dual_mode) { | ||
478 | /* read 2nd demodulator I2C address */ | ||
479 | req.addr = AF9015_EEPROM_DEMOD2_I2C; | ||
480 | ret = af9015_ctrl_msg(d, &req); | ||
481 | if (ret) | ||
482 | goto error; | ||
483 | |||
484 | state->af9013_config[1].i2c_addr = val; | ||
485 | } | ||
486 | |||
487 | for (i = 0; i < state->dual_mode + 1; i++) { | ||
488 | if (i == 1) | ||
489 | offset = AF9015_EEPROM_OFFSET; | ||
490 | /* xtal */ | ||
491 | req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset; | ||
492 | ret = af9015_ctrl_msg(d, &req); | ||
493 | if (ret) | ||
494 | goto error; | ||
495 | switch (val) { | ||
496 | case 0: | ||
497 | state->af9013_config[i].clock = 28800000; | ||
498 | break; | ||
499 | case 1: | ||
500 | state->af9013_config[i].clock = 20480000; | ||
501 | break; | ||
502 | case 2: | ||
503 | state->af9013_config[i].clock = 28000000; | ||
504 | break; | ||
505 | case 3: | ||
506 | state->af9013_config[i].clock = 25000000; | ||
507 | break; | ||
508 | }; | ||
509 | deb_info("%s: [%d] xtal=%d set clock=%d\n", __func__, i, | ||
510 | val, state->af9013_config[i].clock); | ||
511 | |||
512 | /* IF frequency */ | ||
513 | req.addr = AF9015_EEPROM_IF1H + offset; | ||
514 | ret = af9015_ctrl_msg(d, &req); | ||
515 | if (ret) | ||
516 | goto error; | ||
517 | |||
518 | state->af9013_config[i].if_frequency = val << 8; | ||
519 | |||
520 | req.addr = AF9015_EEPROM_IF1L + offset; | ||
521 | ret = af9015_ctrl_msg(d, &req); | ||
522 | if (ret) | ||
523 | goto error; | ||
524 | |||
525 | state->af9013_config[i].if_frequency += val; | ||
526 | state->af9013_config[i].if_frequency *= 1000; | ||
527 | deb_info("%s: [%d] IF frequency=%d\n", __func__, i, | ||
528 | state->af9013_config[i].if_frequency); | ||
529 | |||
530 | /* MT2060 IF1 */ | ||
531 | req.addr = AF9015_EEPROM_MT2060_IF1H + offset; | ||
532 | ret = af9015_ctrl_msg(d, &req); | ||
533 | if (ret) | ||
534 | goto error; | ||
535 | state->mt2060_if1[i] = val << 8; | ||
536 | req.addr = AF9015_EEPROM_MT2060_IF1L + offset; | ||
537 | ret = af9015_ctrl_msg(d, &req); | ||
538 | if (ret) | ||
539 | goto error; | ||
540 | state->mt2060_if1[i] += val; | ||
541 | deb_info("%s: [%d] MT2060 IF1=%d\n", __func__, i, | ||
542 | state->mt2060_if1[i]); | ||
543 | |||
544 | /* tuner */ | ||
545 | req.addr = AF9015_EEPROM_TUNER_ID1 + offset; | ||
546 | ret = af9015_ctrl_msg(d, &req); | ||
547 | if (ret) | ||
548 | goto error; | ||
549 | switch (val) { | ||
550 | case AF9013_TUNER_ENV77H11D5: | ||
551 | case AF9013_TUNER_MT2060: | ||
552 | case AF9013_TUNER_QT1010: | ||
553 | case AF9013_TUNER_UNKNOWN: | ||
554 | case AF9013_TUNER_MT2060_2: | ||
555 | case AF9013_TUNER_TDA18271: | ||
556 | case AF9013_TUNER_QT1010A: | ||
557 | case AF9013_TUNER_TDA18218: | ||
558 | state->af9013_config[i].spec_inv = 1; | ||
559 | break; | ||
560 | case AF9013_TUNER_MXL5003D: | ||
561 | case AF9013_TUNER_MXL5005D: | ||
562 | case AF9013_TUNER_MXL5005R: | ||
563 | case AF9013_TUNER_MXL5007T: | ||
564 | state->af9013_config[i].spec_inv = 0; | ||
565 | break; | ||
566 | case AF9013_TUNER_MC44S803: | ||
567 | state->af9013_config[i].gpio[1] = AF9013_GPIO_LO; | ||
568 | state->af9013_config[i].spec_inv = 1; | ||
569 | break; | ||
570 | default: | ||
571 | warn("tuner id=%d not supported, please report!", val); | ||
572 | return -ENODEV; | ||
573 | }; | ||
574 | |||
575 | state->af9013_config[i].tuner = val; | ||
576 | deb_info("%s: [%d] tuner id=%d\n", __func__, i, val); | ||
577 | } | ||
578 | |||
579 | error: | ||
580 | if (ret) | ||
581 | err("eeprom read failed=%d", ret); | ||
582 | |||
583 | /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM | ||
584 | content :-( Override some wrong values here. Ditto for the | ||
585 | AVerTV Red HD+ (A850T) device. */ | ||
586 | if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA && | ||
587 | ((le16_to_cpu(d->udev->descriptor.idProduct) == | ||
588 | USB_PID_AVERMEDIA_A850) || | ||
589 | (le16_to_cpu(d->udev->descriptor.idProduct) == | ||
590 | USB_PID_AVERMEDIA_A850T))) { | ||
591 | deb_info("%s: AverMedia A850: overriding config\n", __func__); | ||
592 | /* disable dual mode */ | ||
593 | state->dual_mode = 0; | ||
594 | |||
595 | /* set correct IF */ | ||
596 | state->af9013_config[0].if_frequency = 4570000; | ||
597 | } | ||
598 | |||
599 | return ret; | ||
600 | } | ||
601 | |||
602 | static int af9015_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, | ||
603 | struct usb_data_stream_properties *stream) | ||
604 | { | ||
605 | deb_info("%s: adap=%d\n", __func__, fe_to_adap(fe)->id); | ||
606 | |||
607 | if (fe_to_d(fe)->udev->speed == USB_SPEED_FULL) | ||
608 | stream->u.bulk.buffersize = TS_USB11_FRAME_SIZE; | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | static int af9015_get_adapter_count(struct dvb_usb_device *d) | ||
614 | { | ||
615 | struct af9015_state *state = d_to_priv(d); | ||
616 | return state->dual_mode + 1; | ||
617 | } | ||
618 | |||
619 | /* override demod callbacks for resource locking */ | ||
620 | static int af9015_af9013_set_frontend(struct dvb_frontend *fe) | ||
621 | { | ||
622 | int ret; | ||
623 | struct af9015_state *state = fe_to_priv(fe); | ||
624 | |||
625 | if (mutex_lock_interruptible(&state->fe_mutex)) | ||
626 | return -EAGAIN; | ||
627 | |||
628 | ret = state->set_frontend[fe_to_adap(fe)->id](fe); | ||
629 | |||
630 | mutex_unlock(&state->fe_mutex); | ||
631 | |||
632 | return ret; | ||
633 | } | ||
634 | |||
635 | /* override demod callbacks for resource locking */ | ||
636 | static int af9015_af9013_read_status(struct dvb_frontend *fe, | ||
637 | fe_status_t *status) | ||
638 | { | ||
639 | int ret; | ||
640 | struct af9015_state *state = fe_to_priv(fe); | ||
641 | |||
642 | if (mutex_lock_interruptible(&state->fe_mutex)) | ||
643 | return -EAGAIN; | ||
644 | |||
645 | ret = state->read_status[fe_to_adap(fe)->id](fe, status); | ||
646 | |||
647 | mutex_unlock(&state->fe_mutex); | ||
648 | |||
649 | return ret; | ||
650 | } | ||
651 | |||
652 | /* override demod callbacks for resource locking */ | ||
653 | static int af9015_af9013_init(struct dvb_frontend *fe) | ||
654 | { | ||
655 | int ret; | ||
656 | struct af9015_state *state = fe_to_priv(fe); | ||
657 | |||
658 | if (mutex_lock_interruptible(&state->fe_mutex)) | ||
659 | return -EAGAIN; | ||
660 | |||
661 | ret = state->init[fe_to_adap(fe)->id](fe); | ||
662 | |||
663 | mutex_unlock(&state->fe_mutex); | ||
664 | |||
665 | return ret; | ||
666 | } | ||
667 | |||
668 | /* override demod callbacks for resource locking */ | ||
669 | static int af9015_af9013_sleep(struct dvb_frontend *fe) | ||
670 | { | ||
671 | int ret; | ||
672 | struct af9015_state *state = fe_to_priv(fe); | ||
673 | |||
674 | if (mutex_lock_interruptible(&state->fe_mutex)) | ||
675 | return -EAGAIN; | ||
676 | |||
677 | ret = state->sleep[fe_to_adap(fe)->id](fe); | ||
678 | |||
679 | mutex_unlock(&state->fe_mutex); | ||
680 | |||
681 | return ret; | ||
682 | } | ||
683 | |||
684 | /* override tuner callbacks for resource locking */ | ||
685 | static int af9015_tuner_init(struct dvb_frontend *fe) | ||
686 | { | ||
687 | int ret; | ||
688 | struct af9015_state *state = fe_to_priv(fe); | ||
689 | |||
690 | if (mutex_lock_interruptible(&state->fe_mutex)) | ||
691 | return -EAGAIN; | ||
692 | |||
693 | ret = state->tuner_init[fe_to_adap(fe)->id](fe); | ||
694 | |||
695 | mutex_unlock(&state->fe_mutex); | ||
696 | |||
697 | return ret; | ||
698 | } | ||
699 | |||
700 | /* override tuner callbacks for resource locking */ | ||
701 | static int af9015_tuner_sleep(struct dvb_frontend *fe) | ||
702 | { | ||
703 | int ret; | ||
704 | struct af9015_state *state = fe_to_priv(fe); | ||
705 | |||
706 | if (mutex_lock_interruptible(&state->fe_mutex)) | ||
707 | return -EAGAIN; | ||
708 | |||
709 | ret = state->tuner_sleep[fe_to_adap(fe)->id](fe); | ||
710 | |||
711 | mutex_unlock(&state->fe_mutex); | ||
712 | |||
713 | return ret; | ||
714 | } | ||
715 | |||
716 | static int af9015_copy_firmware(struct dvb_usb_device *d) | ||
717 | { | ||
718 | struct af9015_state *state = d_to_priv(d); | ||
719 | int ret; | ||
720 | u8 fw_params[4]; | ||
721 | u8 val, i; | ||
722 | struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params), | ||
723 | fw_params }; | ||
724 | deb_info("%s:\n", __func__); | ||
725 | |||
726 | fw_params[0] = state->firmware_size >> 8; | ||
727 | fw_params[1] = state->firmware_size & 0xff; | ||
728 | fw_params[2] = state->firmware_checksum >> 8; | ||
729 | fw_params[3] = state->firmware_checksum & 0xff; | ||
730 | |||
731 | /* wait 2nd demodulator ready */ | ||
732 | msleep(100); | ||
733 | |||
734 | ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr, | ||
735 | 0x98be, &val); | ||
736 | if (ret) | ||
737 | goto error; | ||
738 | else | ||
739 | deb_info("%s: firmware status:%02x\n", __func__, val); | ||
740 | |||
741 | if (val == 0x0c) /* fw is running, no need for download */ | ||
742 | goto exit; | ||
743 | |||
744 | /* set I2C master clock to fast (to speed up firmware copy) */ | ||
745 | ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */ | ||
746 | if (ret) | ||
747 | goto error; | ||
748 | |||
749 | msleep(50); | ||
750 | |||
751 | /* copy firmware */ | ||
752 | ret = af9015_ctrl_msg(d, &req); | ||
753 | if (ret) | ||
754 | err("firmware copy cmd failed:%d", ret); | ||
755 | deb_info("%s: firmware copy done\n", __func__); | ||
756 | |||
757 | /* set I2C master clock back to normal */ | ||
758 | ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */ | ||
759 | if (ret) | ||
760 | goto error; | ||
761 | |||
762 | /* request boot firmware */ | ||
763 | ret = af9015_write_reg_i2c(d, state->af9013_config[1].i2c_addr, | ||
764 | 0xe205, 1); | ||
765 | deb_info("%s: firmware boot cmd status:%d\n", __func__, ret); | ||
766 | if (ret) | ||
767 | goto error; | ||
768 | |||
769 | for (i = 0; i < 15; i++) { | ||
770 | msleep(100); | ||
771 | |||
772 | /* check firmware status */ | ||
773 | ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr, | ||
774 | 0x98be, &val); | ||
775 | deb_info("%s: firmware status cmd status:%d fw status:%02x\n", | ||
776 | __func__, ret, val); | ||
777 | if (ret) | ||
778 | goto error; | ||
779 | |||
780 | if (val == 0x0c || val == 0x04) /* success or fail */ | ||
781 | break; | ||
782 | } | ||
783 | |||
784 | if (val == 0x04) { | ||
785 | err("firmware did not run"); | ||
786 | ret = -1; | ||
787 | } else if (val != 0x0c) { | ||
788 | err("firmware boot timeout"); | ||
789 | ret = -1; | ||
790 | } | ||
791 | |||
792 | error: | ||
793 | exit: | ||
794 | return ret; | ||
795 | } | ||
796 | |||
797 | static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) | ||
798 | { | ||
799 | int ret; | ||
800 | struct af9015_state *state = adap_to_priv(adap); | ||
801 | |||
802 | if (adap->id == 0) { | ||
803 | state->af9013_config[0].ts_mode = AF9013_TS_USB; | ||
804 | memcpy(state->af9013_config[0].api_version, "\x0\x1\x9\x0", 4); | ||
805 | state->af9013_config[0].gpio[0] = AF9013_GPIO_HI; | ||
806 | state->af9013_config[0].gpio[3] = AF9013_GPIO_TUNER_ON; | ||
807 | } else if (adap->id == 1) { | ||
808 | state->af9013_config[1].ts_mode = AF9013_TS_SERIAL; | ||
809 | memcpy(state->af9013_config[1].api_version, "\x0\x1\x9\x0", 4); | ||
810 | state->af9013_config[1].gpio[0] = AF9013_GPIO_TUNER_ON; | ||
811 | state->af9013_config[1].gpio[1] = AF9013_GPIO_LO; | ||
812 | |||
813 | /* copy firmware to 2nd demodulator */ | ||
814 | if (state->dual_mode) { | ||
815 | ret = af9015_copy_firmware(adap_to_d(adap)); | ||
816 | if (ret) { | ||
817 | err("firmware copy to 2nd frontend " \ | ||
818 | "failed, will disable it"); | ||
819 | state->dual_mode = 0; | ||
820 | return -ENODEV; | ||
821 | } | ||
822 | } else { | ||
823 | return -ENODEV; | ||
824 | } | ||
825 | } | ||
826 | |||
827 | /* attach demodulator */ | ||
828 | adap->fe[0] = dvb_attach(af9013_attach, | ||
829 | &state->af9013_config[adap->id], &adap_to_d(adap)->i2c_adap); | ||
830 | |||
831 | /* | ||
832 | * AF9015 firmware does not like if it gets interrupted by I2C adapter | ||
833 | * request on some critical phases. During normal operation I2C adapter | ||
834 | * is used only 2nd demodulator and tuner on dual tuner devices. | ||
835 | * Override demodulator callbacks and use mutex for limit access to | ||
836 | * those "critical" paths to keep AF9015 happy. | ||
837 | */ | ||
838 | if (adap->fe[0]) { | ||
839 | state->set_frontend[adap->id] = | ||
840 | adap->fe[0]->ops.set_frontend; | ||
841 | adap->fe[0]->ops.set_frontend = | ||
842 | af9015_af9013_set_frontend; | ||
843 | |||
844 | state->read_status[adap->id] = | ||
845 | adap->fe[0]->ops.read_status; | ||
846 | adap->fe[0]->ops.read_status = | ||
847 | af9015_af9013_read_status; | ||
848 | |||
849 | state->init[adap->id] = adap->fe[0]->ops.init; | ||
850 | adap->fe[0]->ops.init = af9015_af9013_init; | ||
851 | |||
852 | state->sleep[adap->id] = adap->fe[0]->ops.sleep; | ||
853 | adap->fe[0]->ops.sleep = af9015_af9013_sleep; | ||
854 | } | ||
855 | |||
856 | return adap->fe[0] == NULL ? -ENODEV : 0; | ||
857 | } | ||
858 | |||
859 | static struct mt2060_config af9015_mt2060_config = { | ||
860 | .i2c_address = 0xc0, | ||
861 | .clock_out = 0, | ||
862 | }; | ||
863 | |||
864 | static struct qt1010_config af9015_qt1010_config = { | ||
865 | .i2c_address = 0xc4, | ||
866 | }; | ||
867 | |||
868 | static struct tda18271_config af9015_tda18271_config = { | ||
869 | .gate = TDA18271_GATE_DIGITAL, | ||
870 | .small_i2c = TDA18271_16_BYTE_CHUNK_INIT, | ||
871 | }; | ||
872 | |||
873 | static struct mxl5005s_config af9015_mxl5003_config = { | ||
874 | .i2c_address = 0xc6, | ||
875 | .if_freq = IF_FREQ_4570000HZ, | ||
876 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
877 | .agc_mode = MXL_SINGLE_AGC, | ||
878 | .tracking_filter = MXL_TF_DEFAULT, | ||
879 | .rssi_enable = MXL_RSSI_ENABLE, | ||
880 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
881 | .div_out = MXL_DIV_OUT_4, | ||
882 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
883 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
884 | .top = MXL5005S_TOP_25P2, | ||
885 | .mod_mode = MXL_DIGITAL_MODE, | ||
886 | .if_mode = MXL_ZERO_IF, | ||
887 | .AgcMasterByte = 0x00, | ||
888 | }; | ||
889 | |||
890 | static struct mxl5005s_config af9015_mxl5005_config = { | ||
891 | .i2c_address = 0xc6, | ||
892 | .if_freq = IF_FREQ_4570000HZ, | ||
893 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
894 | .agc_mode = MXL_SINGLE_AGC, | ||
895 | .tracking_filter = MXL_TF_OFF, | ||
896 | .rssi_enable = MXL_RSSI_ENABLE, | ||
897 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
898 | .div_out = MXL_DIV_OUT_4, | ||
899 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
900 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
901 | .top = MXL5005S_TOP_25P2, | ||
902 | .mod_mode = MXL_DIGITAL_MODE, | ||
903 | .if_mode = MXL_ZERO_IF, | ||
904 | .AgcMasterByte = 0x00, | ||
905 | }; | ||
906 | |||
907 | static struct mc44s803_config af9015_mc44s803_config = { | ||
908 | .i2c_address = 0xc0, | ||
909 | .dig_out = 1, | ||
910 | }; | ||
911 | |||
912 | static struct tda18218_config af9015_tda18218_config = { | ||
913 | .i2c_address = 0xc0, | ||
914 | .i2c_wr_max = 21, /* max wr bytes AF9015 I2C adap can handle at once */ | ||
915 | }; | ||
916 | |||
917 | static struct mxl5007t_config af9015_mxl5007t_config = { | ||
918 | .xtal_freq_hz = MxL_XTAL_24_MHZ, | ||
919 | .if_freq_hz = MxL_IF_4_57_MHZ, | ||
920 | }; | ||
921 | |||
922 | static int af9015_tuner_attach(struct dvb_usb_adapter *adap) | ||
923 | { | ||
924 | struct af9015_state *state = adap_to_priv(adap); | ||
925 | int ret; | ||
926 | deb_info("%s:\n", __func__); | ||
927 | |||
928 | switch (state->af9013_config[adap->id].tuner) { | ||
929 | case AF9013_TUNER_MT2060: | ||
930 | case AF9013_TUNER_MT2060_2: | ||
931 | ret = dvb_attach(mt2060_attach, adap->fe[0], | ||
932 | &adap_to_d(adap)->i2c_adap, &af9015_mt2060_config, | ||
933 | state->mt2060_if1[adap->id]) | ||
934 | == NULL ? -ENODEV : 0; | ||
935 | break; | ||
936 | case AF9013_TUNER_QT1010: | ||
937 | case AF9013_TUNER_QT1010A: | ||
938 | ret = dvb_attach(qt1010_attach, adap->fe[0], | ||
939 | &adap_to_d(adap)->i2c_adap, | ||
940 | &af9015_qt1010_config) == NULL ? -ENODEV : 0; | ||
941 | break; | ||
942 | case AF9013_TUNER_TDA18271: | ||
943 | ret = dvb_attach(tda18271_attach, adap->fe[0], 0xc0, | ||
944 | &adap_to_d(adap)->i2c_adap, | ||
945 | &af9015_tda18271_config) == NULL ? -ENODEV : 0; | ||
946 | break; | ||
947 | case AF9013_TUNER_TDA18218: | ||
948 | ret = dvb_attach(tda18218_attach, adap->fe[0], | ||
949 | &adap_to_d(adap)->i2c_adap, | ||
950 | &af9015_tda18218_config) == NULL ? -ENODEV : 0; | ||
951 | break; | ||
952 | case AF9013_TUNER_MXL5003D: | ||
953 | ret = dvb_attach(mxl5005s_attach, adap->fe[0], | ||
954 | &adap_to_d(adap)->i2c_adap, | ||
955 | &af9015_mxl5003_config) == NULL ? -ENODEV : 0; | ||
956 | break; | ||
957 | case AF9013_TUNER_MXL5005D: | ||
958 | case AF9013_TUNER_MXL5005R: | ||
959 | ret = dvb_attach(mxl5005s_attach, adap->fe[0], | ||
960 | &adap_to_d(adap)->i2c_adap, | ||
961 | &af9015_mxl5005_config) == NULL ? -ENODEV : 0; | ||
962 | break; | ||
963 | case AF9013_TUNER_ENV77H11D5: | ||
964 | ret = dvb_attach(dvb_pll_attach, adap->fe[0], 0xc0, | ||
965 | &adap_to_d(adap)->i2c_adap, | ||
966 | DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; | ||
967 | break; | ||
968 | case AF9013_TUNER_MC44S803: | ||
969 | ret = dvb_attach(mc44s803_attach, adap->fe[0], | ||
970 | &adap_to_d(adap)->i2c_adap, | ||
971 | &af9015_mc44s803_config) == NULL ? -ENODEV : 0; | ||
972 | break; | ||
973 | case AF9013_TUNER_MXL5007T: | ||
974 | ret = dvb_attach(mxl5007t_attach, adap->fe[0], | ||
975 | &adap_to_d(adap)->i2c_adap, | ||
976 | 0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0; | ||
977 | break; | ||
978 | case AF9013_TUNER_UNKNOWN: | ||
979 | default: | ||
980 | ret = -ENODEV; | ||
981 | err("Unknown tuner id:%d", | ||
982 | state->af9013_config[adap->id].tuner); | ||
983 | } | ||
984 | |||
985 | if (adap->fe[0]->ops.tuner_ops.init) { | ||
986 | state->tuner_init[adap->id] = | ||
987 | adap->fe[0]->ops.tuner_ops.init; | ||
988 | adap->fe[0]->ops.tuner_ops.init = af9015_tuner_init; | ||
989 | } | ||
990 | |||
991 | if (adap->fe[0]->ops.tuner_ops.sleep) { | ||
992 | state->tuner_sleep[adap->id] = | ||
993 | adap->fe[0]->ops.tuner_ops.sleep; | ||
994 | adap->fe[0]->ops.tuner_ops.sleep = af9015_tuner_sleep; | ||
995 | } | ||
996 | |||
997 | return ret; | ||
998 | } | ||
999 | |||
1000 | static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
1001 | { | ||
1002 | int ret; | ||
1003 | deb_info("%s: onoff:%d\n", __func__, onoff); | ||
1004 | |||
1005 | if (onoff) | ||
1006 | ret = af9015_set_reg_bit(adap_to_d(adap), 0xd503, 0); | ||
1007 | else | ||
1008 | ret = af9015_clear_reg_bit(adap_to_d(adap), 0xd503, 0); | ||
1009 | |||
1010 | return ret; | ||
1011 | } | ||
1012 | |||
1013 | static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | ||
1014 | int onoff) | ||
1015 | { | ||
1016 | int ret; | ||
1017 | u8 idx; | ||
1018 | |||
1019 | deb_info("%s: set pid filter, index %d, pid %x, onoff %d\n", | ||
1020 | __func__, index, pid, onoff); | ||
1021 | |||
1022 | ret = af9015_write_reg(adap_to_d(adap), 0xd505, (pid & 0xff)); | ||
1023 | if (ret) | ||
1024 | goto error; | ||
1025 | |||
1026 | ret = af9015_write_reg(adap_to_d(adap), 0xd506, (pid >> 8)); | ||
1027 | if (ret) | ||
1028 | goto error; | ||
1029 | |||
1030 | idx = ((index & 0x1f) | (1 << 5)); | ||
1031 | ret = af9015_write_reg(adap_to_d(adap), 0xd504, idx); | ||
1032 | |||
1033 | error: | ||
1034 | return ret; | ||
1035 | } | ||
1036 | |||
1037 | static int af9015_init_endpoint(struct dvb_usb_device *d) | ||
1038 | { | ||
1039 | struct af9015_state *state = d_to_priv(d); | ||
1040 | int ret; | ||
1041 | u16 frame_size; | ||
1042 | u8 packet_size; | ||
1043 | deb_info("%s: USB speed:%d\n", __func__, d->udev->speed); | ||
1044 | |||
1045 | if (d->udev->speed == USB_SPEED_FULL) { | ||
1046 | frame_size = TS_USB11_FRAME_SIZE/4; | ||
1047 | packet_size = TS_USB11_MAX_PACKET_SIZE/4; | ||
1048 | } else { | ||
1049 | frame_size = TS_USB20_FRAME_SIZE/4; | ||
1050 | packet_size = TS_USB20_MAX_PACKET_SIZE/4; | ||
1051 | } | ||
1052 | |||
1053 | ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */ | ||
1054 | if (ret) | ||
1055 | goto error; | ||
1056 | ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */ | ||
1057 | if (ret) | ||
1058 | goto error; | ||
1059 | ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */ | ||
1060 | if (ret) | ||
1061 | goto error; | ||
1062 | ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */ | ||
1063 | if (ret) | ||
1064 | goto error; | ||
1065 | ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */ | ||
1066 | if (ret) | ||
1067 | goto error; | ||
1068 | if (state->dual_mode) { | ||
1069 | ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */ | ||
1070 | if (ret) | ||
1071 | goto error; | ||
1072 | } | ||
1073 | ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */ | ||
1074 | if (ret) | ||
1075 | goto error; | ||
1076 | if (state->dual_mode) { | ||
1077 | ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */ | ||
1078 | if (ret) | ||
1079 | goto error; | ||
1080 | } | ||
1081 | /* EP4 xfer length */ | ||
1082 | ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff); | ||
1083 | if (ret) | ||
1084 | goto error; | ||
1085 | ret = af9015_write_reg(d, 0xdd89, frame_size >> 8); | ||
1086 | if (ret) | ||
1087 | goto error; | ||
1088 | /* EP5 xfer length */ | ||
1089 | ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff); | ||
1090 | if (ret) | ||
1091 | goto error; | ||
1092 | ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8); | ||
1093 | if (ret) | ||
1094 | goto error; | ||
1095 | ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */ | ||
1096 | if (ret) | ||
1097 | goto error; | ||
1098 | ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */ | ||
1099 | if (ret) | ||
1100 | goto error; | ||
1101 | ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */ | ||
1102 | if (ret) | ||
1103 | goto error; | ||
1104 | if (state->dual_mode) { | ||
1105 | ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */ | ||
1106 | if (ret) | ||
1107 | goto error; | ||
1108 | } | ||
1109 | |||
1110 | /* enable / disable mp2if2 */ | ||
1111 | if (state->dual_mode) | ||
1112 | ret = af9015_set_reg_bit(d, 0xd50b, 0); | ||
1113 | else | ||
1114 | ret = af9015_clear_reg_bit(d, 0xd50b, 0); | ||
1115 | |||
1116 | error: | ||
1117 | if (ret) | ||
1118 | err("endpoint init failed:%d", ret); | ||
1119 | return ret; | ||
1120 | } | ||
1121 | |||
1122 | static int af9015_init(struct dvb_usb_device *d) | ||
1123 | { | ||
1124 | struct af9015_state *state = d_to_priv(d); | ||
1125 | int ret; | ||
1126 | deb_info("%s:\n", __func__); | ||
1127 | |||
1128 | mutex_init(&state->fe_mutex); | ||
1129 | |||
1130 | /* init RC canary */ | ||
1131 | ret = af9015_write_reg(d, 0x98e9, 0xff); | ||
1132 | if (ret) | ||
1133 | goto error; | ||
1134 | |||
1135 | ret = af9015_init_endpoint(d); | ||
1136 | if (ret) | ||
1137 | goto error; | ||
1138 | |||
1139 | error: | ||
1140 | return ret; | ||
1141 | } | ||
1142 | |||
1143 | struct af9015_rc_setup { | ||
1144 | unsigned int id; | ||
1145 | char *rc_codes; | ||
1146 | }; | ||
1147 | |||
1148 | static char *af9015_rc_setup_match(unsigned int id, | ||
1149 | const struct af9015_rc_setup *table) | ||
1150 | { | ||
1151 | for (; table->rc_codes; table++) | ||
1152 | if (table->id == id) | ||
1153 | return table->rc_codes; | ||
1154 | return NULL; | ||
1155 | } | ||
1156 | |||
1157 | static const struct af9015_rc_setup af9015_rc_setup_modparam[] = { | ||
1158 | { AF9015_REMOTE_A_LINK_DTU_M, RC_MAP_ALINK_DTU_M }, | ||
1159 | { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, RC_MAP_MSI_DIGIVOX_II }, | ||
1160 | { AF9015_REMOTE_MYGICTV_U718, RC_MAP_TOTAL_MEDIA_IN_HAND }, | ||
1161 | { AF9015_REMOTE_DIGITTRADE_DVB_T, RC_MAP_DIGITTRADE }, | ||
1162 | { AF9015_REMOTE_AVERMEDIA_KS, RC_MAP_AVERMEDIA_RM_KS }, | ||
1163 | { } | ||
1164 | }; | ||
1165 | |||
1166 | static const struct af9015_rc_setup af9015_rc_setup_hashes[] = { | ||
1167 | { 0xb8feb708, RC_MAP_MSI_DIGIVOX_II }, | ||
1168 | { 0xa3703d00, RC_MAP_ALINK_DTU_M }, | ||
1169 | { 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */ | ||
1170 | { 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */ | ||
1171 | { } | ||
1172 | }; | ||
1173 | |||
1174 | static int af9015_rc_query(struct dvb_usb_device *d) | ||
1175 | { | ||
1176 | struct af9015_state *state = d_to_priv(d); | ||
1177 | int ret; | ||
1178 | u8 buf[17]; | ||
1179 | |||
1180 | deb_info("%s:\n", __func__); | ||
1181 | |||
1182 | /* read registers needed to detect remote controller code */ | ||
1183 | ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf)); | ||
1184 | if (ret) | ||
1185 | goto error; | ||
1186 | |||
1187 | /* If any of these are non-zero, assume invalid data */ | ||
1188 | if (buf[1] || buf[2] || buf[3]) | ||
1189 | return ret; | ||
1190 | |||
1191 | /* Check for repeat of previous code */ | ||
1192 | if ((state->rc_repeat != buf[6] || buf[0]) && | ||
1193 | !memcmp(&buf[12], state->rc_last, 4)) { | ||
1194 | deb_rc("%s: key repeated\n", __func__); | ||
1195 | rc_keydown(d->rc_dev, state->rc_keycode, 0); | ||
1196 | state->rc_repeat = buf[6]; | ||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1200 | /* Only process key if canary killed */ | ||
1201 | if (buf[16] != 0xff && buf[0] != 0x01) { | ||
1202 | deb_rc("%s: key pressed %*ph\n", __func__, 4, buf + 12); | ||
1203 | |||
1204 | /* Reset the canary */ | ||
1205 | ret = af9015_write_reg(d, 0x98e9, 0xff); | ||
1206 | if (ret) | ||
1207 | goto error; | ||
1208 | |||
1209 | /* Remember this key */ | ||
1210 | memcpy(state->rc_last, &buf[12], 4); | ||
1211 | if (buf[14] == (u8) ~buf[15]) { | ||
1212 | if (buf[12] == (u8) ~buf[13]) { | ||
1213 | /* NEC */ | ||
1214 | state->rc_keycode = buf[12] << 8 | buf[14]; | ||
1215 | } else { | ||
1216 | /* NEC extended*/ | ||
1217 | state->rc_keycode = buf[12] << 16 | | ||
1218 | buf[13] << 8 | buf[14]; | ||
1219 | } | ||
1220 | } else { | ||
1221 | /* 32 bit NEC */ | ||
1222 | state->rc_keycode = buf[12] << 24 | buf[13] << 16 | | ||
1223 | buf[14] << 8 | buf[15]; | ||
1224 | } | ||
1225 | rc_keydown(d->rc_dev, state->rc_keycode, 0); | ||
1226 | } else { | ||
1227 | deb_rc("%s: no key press\n", __func__); | ||
1228 | /* Invalidate last keypress */ | ||
1229 | /* Not really needed, but helps with debug */ | ||
1230 | state->rc_last[2] = state->rc_last[3]; | ||
1231 | } | ||
1232 | |||
1233 | state->rc_repeat = buf[6]; | ||
1234 | state->rc_failed = false; | ||
1235 | |||
1236 | error: | ||
1237 | if (ret) { | ||
1238 | err("%s: failed:%d", __func__, ret); | ||
1239 | |||
1240 | /* allow random errors as dvb-usb will stop polling on error */ | ||
1241 | if (!state->rc_failed) | ||
1242 | ret = 0; | ||
1243 | |||
1244 | state->rc_failed = true; | ||
1245 | } | ||
1246 | |||
1247 | return ret; | ||
1248 | } | ||
1249 | |||
1250 | static int af9015_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) | ||
1251 | { | ||
1252 | struct af9015_state *state = d_to_priv(d); | ||
1253 | u16 vid = le16_to_cpu(d->udev->descriptor.idVendor); | ||
1254 | |||
1255 | if (state->ir_mode == AF9015_IR_MODE_DISABLED) | ||
1256 | return 0; | ||
1257 | |||
1258 | /* try to load remote based module param */ | ||
1259 | if (!rc->map_name) | ||
1260 | rc->map_name = af9015_rc_setup_match(dvb_usb_af9015_remote, | ||
1261 | af9015_rc_setup_modparam); | ||
1262 | |||
1263 | /* try to load remote based eeprom hash */ | ||
1264 | if (!rc->map_name) | ||
1265 | rc->map_name = af9015_rc_setup_match(state->eeprom_sum, | ||
1266 | af9015_rc_setup_hashes); | ||
1267 | |||
1268 | /* try to load remote based USB iManufacturer string */ | ||
1269 | if (!rc->map_name && vid == USB_VID_AFATECH) { | ||
1270 | /* Check USB manufacturer and product strings and try | ||
1271 | to determine correct remote in case of chip vendor | ||
1272 | reference IDs are used. | ||
1273 | DO NOT ADD ANYTHING NEW HERE. Use hashes instead. */ | ||
1274 | char manufacturer[10]; | ||
1275 | memset(manufacturer, 0, sizeof(manufacturer)); | ||
1276 | usb_string(d->udev, d->udev->descriptor.iManufacturer, | ||
1277 | manufacturer, sizeof(manufacturer)); | ||
1278 | if (!strcmp("MSI", manufacturer)) { | ||
1279 | /* iManufacturer 1 MSI | ||
1280 | iProduct 2 MSI K-VOX */ | ||
1281 | rc->map_name = af9015_rc_setup_match( | ||
1282 | AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, | ||
1283 | af9015_rc_setup_modparam); | ||
1284 | } | ||
1285 | } | ||
1286 | |||
1287 | /* load empty to enable rc */ | ||
1288 | if (!rc->map_name) | ||
1289 | rc->map_name = RC_MAP_EMPTY; | ||
1290 | |||
1291 | rc->allowed_protos = RC_TYPE_NEC; | ||
1292 | rc->query = af9015_rc_query; | ||
1293 | rc->interval = 500; | ||
1294 | |||
1295 | return 0; | ||
1296 | } | ||
1297 | |||
1298 | /* interface 0 is used by DVB-T receiver and | ||
1299 | interface 1 is for remote controller (HID) */ | ||
1300 | static struct dvb_usb_device_properties af9015_props = { | ||
1301 | .driver_name = KBUILD_MODNAME, | ||
1302 | .owner = THIS_MODULE, | ||
1303 | .adapter_nr = adapter_nr, | ||
1304 | .size_of_priv = sizeof(struct af9015_state), | ||
1305 | |||
1306 | .generic_bulk_ctrl_endpoint = 0x02, | ||
1307 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
1308 | |||
1309 | .identify_state = af9015_identify_state, | ||
1310 | .firmware = "dvb-usb-af9015.fw", | ||
1311 | .download_firmware = af9015_download_firmware, | ||
1312 | |||
1313 | .i2c_algo = &af9015_i2c_algo, | ||
1314 | .read_config = af9015_read_config, | ||
1315 | .frontend_attach = af9015_af9013_frontend_attach, | ||
1316 | .tuner_attach = af9015_tuner_attach, | ||
1317 | .init = af9015_init, | ||
1318 | .get_rc_config = af9015_get_rc_config, | ||
1319 | .get_stream_config = af9015_get_stream_config, | ||
1320 | |||
1321 | .get_adapter_count = af9015_get_adapter_count, | ||
1322 | .adapter = { | ||
1323 | { | ||
1324 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
1325 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
1326 | .pid_filter_count = 32, | ||
1327 | .pid_filter = af9015_pid_filter, | ||
1328 | .pid_filter_ctrl = af9015_pid_filter_ctrl, | ||
1329 | |||
1330 | .stream = DVB_USB_STREAM_BULK(0x84, 8, TS_USB20_FRAME_SIZE), | ||
1331 | }, { | ||
1332 | .stream = DVB_USB_STREAM_BULK(0x85, 8, TS_USB20_FRAME_SIZE), | ||
1333 | }, | ||
1334 | }, | ||
1335 | }; | ||
1336 | |||
1337 | static const struct usb_device_id af9015_id_table[] = { | ||
1338 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015, | ||
1339 | &af9015_props, "Afatech AF9015 reference design", NULL) }, | ||
1340 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016, | ||
1341 | &af9015_props, "Afatech AF9015 reference design", NULL) }, | ||
1342 | { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD, | ||
1343 | &af9015_props, "Leadtek WinFast DTV Dongle Gold", RC_MAP_LEADTEK_Y04G0051) }, | ||
1344 | { DVB_USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E, | ||
1345 | &af9015_props, "Pinnacle PCTV 71e", NULL) }, | ||
1346 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U, | ||
1347 | &af9015_props, "KWorld PlusTV Dual DVB-T Stick (DVB-T 399U)", NULL) }, | ||
1348 | { DVB_USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TINYTWIN, | ||
1349 | &af9015_props, "DigitalNow TinyTwin", RC_MAP_AZUREWAVE_AD_TU700) }, | ||
1350 | { DVB_USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_AD_TU700, | ||
1351 | &af9015_props, "TwinHan AzureWave AD-TU700(704J)", RC_MAP_AZUREWAVE_AD_TU700) }, | ||
1352 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2, | ||
1353 | &af9015_props, "TerraTec Cinergy T USB XE", NULL) }, | ||
1354 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T, | ||
1355 | &af9015_props, "KWorld PlusTV Dual DVB-T PCI (DVB-T PC160-2T)", NULL) }, | ||
1356 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X, | ||
1357 | &af9015_props, "AVerMedia AVerTV DVB-T Volar X", RC_MAP_AVERMEDIA_M135A) }, | ||
1358 | { DVB_USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380, | ||
1359 | &af9015_props, "Xtensions XD-380", NULL) }, | ||
1360 | { DVB_USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO, | ||
1361 | &af9015_props, "MSI DIGIVOX Duo", RC_MAP_MSI_DIGIVOX_III) }, | ||
1362 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2, | ||
1363 | &af9015_props, "Fujitsu-Siemens Slim Mobile USB DVB-T", NULL) }, | ||
1364 | { DVB_USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2, | ||
1365 | &af9015_props, "Telestar Starstick 2", NULL) }, | ||
1366 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309, | ||
1367 | &af9015_props, "AVerMedia A309", NULL) }, | ||
1368 | { DVB_USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III, | ||
1369 | &af9015_props, "MSI Digi VOX mini III", RC_MAP_MSI_DIGIVOX_III) }, | ||
1370 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U, | ||
1371 | &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, | ||
1372 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2, | ||
1373 | &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, | ||
1374 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3, | ||
1375 | &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, | ||
1376 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT, | ||
1377 | &af9015_props, "TrekStor DVB-T USB Stick", RC_MAP_TREKSTOR) }, | ||
1378 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850, | ||
1379 | &af9015_props, "AverMedia AVerTV Volar Black HD (A850)", NULL) }, | ||
1380 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805, | ||
1381 | &af9015_props, "AverMedia AVerTV Volar GPS 805 (A805)", NULL) }, | ||
1382 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU, | ||
1383 | &af9015_props, "Conceptronic USB2.0 DVB-T CTVDIGRCU V3.0", NULL) }, | ||
1384 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810, | ||
1385 | &af9015_props, "KWorld Digial MC-810", NULL) }, | ||
1386 | { DVB_USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03, | ||
1387 | &af9015_props, "Genius TVGo DVB-T03", NULL) }, | ||
1388 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2, | ||
1389 | &af9015_props, "KWorld PlusTV Dual DVB-T Stick (DVB-T 399U)", NULL) }, | ||
1390 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T, | ||
1391 | &af9015_props, "KWorld PlusTV DVB-T PCI Pro Card (DVB-T PC160-T)", NULL) }, | ||
1392 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20, | ||
1393 | &af9015_props, "Sveon STV20 Tuner USB DVB-T HDTV", NULL) }, | ||
1394 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2, | ||
1395 | &af9015_props, "DigitalNow TinyTwin v2", RC_MAP_DIGITALNOW_TINYTWIN) }, | ||
1396 | { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS, | ||
1397 | &af9015_props, "Leadtek WinFast DTV2000DS", RC_MAP_LEADTEK_Y04G0051) }, | ||
1398 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T, | ||
1399 | &af9015_props, "KWorld USB DVB-T Stick Mobile (UB383-T)", NULL) }, | ||
1400 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4, | ||
1401 | &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, | ||
1402 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M, | ||
1403 | &af9015_props, "AverMedia AVerTV Volar M (A815Mac)", NULL) }, | ||
1404 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC, | ||
1405 | &af9015_props, "TerraTec Cinergy T Stick RC", RC_MAP_TERRATEC_SLIM_2) }, | ||
1406 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC, | ||
1407 | &af9015_props, "TerraTec Cinergy T Stick Dual RC", RC_MAP_TERRATEC_SLIM) }, | ||
1408 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T, | ||
1409 | &af9015_props, "AverMedia AVerTV Red HD+ (A850T)", NULL) }, | ||
1410 | { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3, | ||
1411 | &af9015_props, "DigitalNow TinyTwin v3", RC_MAP_DIGITALNOW_TINYTWIN) }, | ||
1412 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22, | ||
1413 | &af9015_props, "Sveon STV22 Dual USB DVB-T Tuner HDTV", RC_MAP_MSI_DIGIVOX_III) }, | ||
1414 | { } | ||
1415 | }; | ||
1416 | MODULE_DEVICE_TABLE(usb, af9015_id_table); | ||
1417 | |||
1418 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
1419 | static struct usb_driver af9015_usb_driver = { | ||
1420 | .name = KBUILD_MODNAME, | ||
1421 | .id_table = af9015_id_table, | ||
1422 | .probe = dvb_usbv2_probe, | ||
1423 | .disconnect = dvb_usbv2_disconnect, | ||
1424 | .suspend = dvb_usbv2_suspend, | ||
1425 | .resume = dvb_usbv2_resume, | ||
1426 | .no_dynamic_id = 1, | ||
1427 | .soft_unbind = 1, | ||
1428 | }; | ||
1429 | |||
1430 | module_usb_driver(af9015_usb_driver); | ||
1431 | |||
1432 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
1433 | MODULE_DESCRIPTION("Afatech AF9015 driver"); | ||
1434 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.h b/drivers/media/usb/dvb-usb-v2/af9015.h new file mode 100644 index 000000000000..c6b304d962ad --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/af9015.h | |||
@@ -0,0 +1,170 @@ | |||
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 AF9015_H | ||
25 | #define AF9015_H | ||
26 | |||
27 | #include <linux/hash.h> | ||
28 | #include "dvb_usb.h" | ||
29 | #include "af9013.h" | ||
30 | #include "dvb-pll.h" | ||
31 | #include "mt2060.h" | ||
32 | #include "qt1010.h" | ||
33 | #include "tda18271.h" | ||
34 | #include "mxl5005s.h" | ||
35 | #include "mc44s803.h" | ||
36 | #include "tda18218.h" | ||
37 | #include "mxl5007t.h" | ||
38 | |||
39 | #define DVB_USB_LOG_PREFIX "af9015" | ||
40 | |||
41 | #ifdef CONFIG_DVB_USB_DEBUG | ||
42 | #define dprintk(var, level, args...) \ | ||
43 | do { if ((var & level)) printk(args); } while (0) | ||
44 | #define DVB_USB_DEBUG_STATUS | ||
45 | #else | ||
46 | #define dprintk(args...) | ||
47 | #define DVB_USB_DEBUG_STATUS " (debugging is not enabled)" | ||
48 | #endif | ||
49 | |||
50 | #define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args) | ||
51 | #define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args) | ||
52 | |||
53 | #undef err | ||
54 | #define err(format, arg...) \ | ||
55 | printk(KERN_ERR DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
56 | #undef warn | ||
57 | #define warn(format, arg...) \ | ||
58 | printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
59 | |||
60 | /* Windows driver uses packet count 21 for USB1.1 and 348 for USB2.0. | ||
61 | We use smaller - about 1/4 from the original, 5 and 87. */ | ||
62 | #define TS_PACKET_SIZE 188 | ||
63 | |||
64 | #define TS_USB20_PACKET_COUNT 87 | ||
65 | #define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT) | ||
66 | |||
67 | #define TS_USB11_PACKET_COUNT 5 | ||
68 | #define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT) | ||
69 | |||
70 | #define TS_USB20_MAX_PACKET_SIZE 512 | ||
71 | #define TS_USB11_MAX_PACKET_SIZE 64 | ||
72 | |||
73 | #define AF9015_I2C_EEPROM 0xa0 | ||
74 | #define AF9015_I2C_DEMOD 0x38 | ||
75 | #define AF9015_USB_TIMEOUT 2000 | ||
76 | |||
77 | /* EEPROM locations */ | ||
78 | #define AF9015_EEPROM_IR_MODE 0x18 | ||
79 | #define AF9015_EEPROM_IR_REMOTE_TYPE 0x34 | ||
80 | #define AF9015_EEPROM_TS_MODE 0x31 | ||
81 | #define AF9015_EEPROM_DEMOD2_I2C 0x32 | ||
82 | |||
83 | #define AF9015_EEPROM_SAW_BW1 0x35 | ||
84 | #define AF9015_EEPROM_XTAL_TYPE1 0x36 | ||
85 | #define AF9015_EEPROM_SPEC_INV1 0x37 | ||
86 | #define AF9015_EEPROM_IF1L 0x38 | ||
87 | #define AF9015_EEPROM_IF1H 0x39 | ||
88 | #define AF9015_EEPROM_MT2060_IF1L 0x3a | ||
89 | #define AF9015_EEPROM_MT2060_IF1H 0x3b | ||
90 | #define AF9015_EEPROM_TUNER_ID1 0x3c | ||
91 | |||
92 | #define AF9015_EEPROM_SAW_BW2 0x45 | ||
93 | #define AF9015_EEPROM_XTAL_TYPE2 0x46 | ||
94 | #define AF9015_EEPROM_SPEC_INV2 0x47 | ||
95 | #define AF9015_EEPROM_IF2L 0x48 | ||
96 | #define AF9015_EEPROM_IF2H 0x49 | ||
97 | #define AF9015_EEPROM_MT2060_IF2L 0x4a | ||
98 | #define AF9015_EEPROM_MT2060_IF2H 0x4b | ||
99 | #define AF9015_EEPROM_TUNER_ID2 0x4c | ||
100 | |||
101 | #define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1) | ||
102 | |||
103 | struct req_t { | ||
104 | u8 cmd; /* [0] */ | ||
105 | /* seq */ /* [1] */ | ||
106 | u8 i2c_addr; /* [2] */ | ||
107 | u16 addr; /* [3|4] */ | ||
108 | u8 mbox; /* [5] */ | ||
109 | u8 addr_len; /* [6] */ | ||
110 | u8 data_len; /* [7] */ | ||
111 | u8 *data; | ||
112 | }; | ||
113 | |||
114 | enum af9015_cmd { | ||
115 | GET_CONFIG = 0x10, | ||
116 | DOWNLOAD_FIRMWARE = 0x11, | ||
117 | BOOT = 0x13, | ||
118 | READ_MEMORY = 0x20, | ||
119 | WRITE_MEMORY = 0x21, | ||
120 | READ_WRITE_I2C = 0x22, | ||
121 | COPY_FIRMWARE = 0x23, | ||
122 | RECONNECT_USB = 0x5a, | ||
123 | WRITE_VIRTUAL_MEMORY = 0x26, | ||
124 | GET_IR_CODE = 0x27, | ||
125 | READ_I2C, | ||
126 | WRITE_I2C, | ||
127 | }; | ||
128 | |||
129 | enum af9015_ir_mode { | ||
130 | AF9015_IR_MODE_DISABLED = 0, | ||
131 | AF9015_IR_MODE_HID, | ||
132 | AF9015_IR_MODE_RLC, | ||
133 | AF9015_IR_MODE_RC6, | ||
134 | AF9015_IR_MODE_POLLING, /* just guess */ | ||
135 | }; | ||
136 | |||
137 | struct af9015_state { | ||
138 | u8 ir_mode; | ||
139 | u8 rc_repeat; | ||
140 | u32 rc_keycode; | ||
141 | u8 rc_last[4]; | ||
142 | bool rc_failed; | ||
143 | u8 dual_mode; | ||
144 | u8 seq; /* packet sequence number */ | ||
145 | u16 mt2060_if1[2]; | ||
146 | u16 firmware_size; | ||
147 | u16 firmware_checksum; | ||
148 | u32 eeprom_sum; | ||
149 | struct af9013_config af9013_config[2]; | ||
150 | |||
151 | /* for demod callback override */ | ||
152 | int (*set_frontend[2]) (struct dvb_frontend *fe); | ||
153 | int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status); | ||
154 | int (*init[2]) (struct dvb_frontend *fe); | ||
155 | int (*sleep[2]) (struct dvb_frontend *fe); | ||
156 | int (*tuner_init[2]) (struct dvb_frontend *fe); | ||
157 | int (*tuner_sleep[2]) (struct dvb_frontend *fe); | ||
158 | struct mutex fe_mutex; | ||
159 | }; | ||
160 | |||
161 | enum af9015_remote { | ||
162 | AF9015_REMOTE_NONE = 0, | ||
163 | /* 1 */ AF9015_REMOTE_A_LINK_DTU_M, | ||
164 | AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, | ||
165 | AF9015_REMOTE_MYGICTV_U718, | ||
166 | AF9015_REMOTE_DIGITTRADE_DVB_T, | ||
167 | /* 5 */ AF9015_REMOTE_AVERMEDIA_KS, | ||
168 | }; | ||
169 | |||
170 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c new file mode 100644 index 000000000000..bb90b877d07b --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/af9035.c | |||
@@ -0,0 +1,1086 @@ | |||
1 | /* | ||
2 | * Afatech AF9035 DVB USB driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
5 | * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | |||
22 | #include "af9035.h" | ||
23 | |||
24 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
25 | |||
26 | static u16 af9035_checksum(const u8 *buf, size_t len) | ||
27 | { | ||
28 | size_t i; | ||
29 | u16 checksum = 0; | ||
30 | |||
31 | for (i = 1; i < len; i++) { | ||
32 | if (i % 2) | ||
33 | checksum += buf[i] << 8; | ||
34 | else | ||
35 | checksum += buf[i]; | ||
36 | } | ||
37 | checksum = ~checksum; | ||
38 | |||
39 | return checksum; | ||
40 | } | ||
41 | |||
42 | static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) | ||
43 | { | ||
44 | #define BUF_LEN 64 | ||
45 | #define REQ_HDR_LEN 4 /* send header size */ | ||
46 | #define ACK_HDR_LEN 3 /* rece header size */ | ||
47 | #define CHECKSUM_LEN 2 | ||
48 | #define USB_TIMEOUT 2000 | ||
49 | struct state *state = d_to_priv(d); | ||
50 | int ret, wlen, rlen; | ||
51 | u8 buf[BUF_LEN]; | ||
52 | u16 checksum, tmp_checksum; | ||
53 | |||
54 | /* buffer overflow check */ | ||
55 | if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || | ||
56 | req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { | ||
57 | pr_debug("%s: too much data wlen=%d rlen=%d\n", __func__, | ||
58 | req->wlen, req->rlen); | ||
59 | return -EINVAL; | ||
60 | } | ||
61 | |||
62 | buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; | ||
63 | buf[1] = req->mbox; | ||
64 | buf[2] = req->cmd; | ||
65 | buf[3] = state->seq++; | ||
66 | memcpy(&buf[REQ_HDR_LEN], req->wbuf, req->wlen); | ||
67 | |||
68 | wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN; | ||
69 | rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; | ||
70 | |||
71 | /* calc and add checksum */ | ||
72 | checksum = af9035_checksum(buf, buf[0] - 1); | ||
73 | buf[buf[0] - 1] = (checksum >> 8); | ||
74 | buf[buf[0] - 0] = (checksum & 0xff); | ||
75 | |||
76 | /* no ack for these packets */ | ||
77 | if (req->cmd == CMD_FW_DL) | ||
78 | rlen = 0; | ||
79 | |||
80 | ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen); | ||
81 | if (ret) | ||
82 | goto err; | ||
83 | |||
84 | /* no ack for those packets */ | ||
85 | if (req->cmd == CMD_FW_DL) | ||
86 | goto exit; | ||
87 | |||
88 | /* verify checksum */ | ||
89 | checksum = af9035_checksum(buf, rlen - 2); | ||
90 | tmp_checksum = (buf[rlen - 2] << 8) | buf[rlen - 1]; | ||
91 | if (tmp_checksum != checksum) { | ||
92 | pr_err("%s: command=%02x checksum mismatch (%04x != %04x)\n", | ||
93 | KBUILD_MODNAME, req->cmd, tmp_checksum, | ||
94 | checksum); | ||
95 | ret = -EIO; | ||
96 | goto err; | ||
97 | } | ||
98 | |||
99 | /* check status */ | ||
100 | if (buf[2]) { | ||
101 | pr_debug("%s: command=%02x failed fw error=%d\n", __func__, | ||
102 | req->cmd, buf[2]); | ||
103 | ret = -EIO; | ||
104 | goto err; | ||
105 | } | ||
106 | |||
107 | /* read request, copy returned data to return buf */ | ||
108 | if (req->rlen) | ||
109 | memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen); | ||
110 | |||
111 | exit: | ||
112 | return 0; | ||
113 | |||
114 | err: | ||
115 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | /* write multiple registers */ | ||
121 | static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) | ||
122 | { | ||
123 | u8 wbuf[6 + len]; | ||
124 | u8 mbox = (reg >> 16) & 0xff; | ||
125 | struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL }; | ||
126 | |||
127 | wbuf[0] = len; | ||
128 | wbuf[1] = 2; | ||
129 | wbuf[2] = 0; | ||
130 | wbuf[3] = 0; | ||
131 | wbuf[4] = (reg >> 8) & 0xff; | ||
132 | wbuf[5] = (reg >> 0) & 0xff; | ||
133 | memcpy(&wbuf[6], val, len); | ||
134 | |||
135 | return af9035_ctrl_msg(d, &req); | ||
136 | } | ||
137 | |||
138 | /* read multiple registers */ | ||
139 | static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) | ||
140 | { | ||
141 | u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff }; | ||
142 | u8 mbox = (reg >> 16) & 0xff; | ||
143 | struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val }; | ||
144 | |||
145 | return af9035_ctrl_msg(d, &req); | ||
146 | } | ||
147 | |||
148 | /* write single register */ | ||
149 | static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val) | ||
150 | { | ||
151 | return af9035_wr_regs(d, reg, &val, 1); | ||
152 | } | ||
153 | |||
154 | /* read single register */ | ||
155 | static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val) | ||
156 | { | ||
157 | return af9035_rd_regs(d, reg, val, 1); | ||
158 | } | ||
159 | |||
160 | /* write single register with mask */ | ||
161 | static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val, | ||
162 | u8 mask) | ||
163 | { | ||
164 | int ret; | ||
165 | u8 tmp; | ||
166 | |||
167 | /* no need for read if whole reg is written */ | ||
168 | if (mask != 0xff) { | ||
169 | ret = af9035_rd_regs(d, reg, &tmp, 1); | ||
170 | if (ret) | ||
171 | return ret; | ||
172 | |||
173 | val &= mask; | ||
174 | tmp &= ~mask; | ||
175 | val |= tmp; | ||
176 | } | ||
177 | |||
178 | return af9035_wr_regs(d, reg, &val, 1); | ||
179 | } | ||
180 | |||
181 | static int af9035_i2c_master_xfer(struct i2c_adapter *adap, | ||
182 | struct i2c_msg msg[], int num) | ||
183 | { | ||
184 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
185 | struct state *state = d_to_priv(d); | ||
186 | int ret; | ||
187 | |||
188 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
189 | return -EAGAIN; | ||
190 | |||
191 | /* | ||
192 | * I2C sub header is 5 bytes long. Meaning of those bytes are: | ||
193 | * 0: data len | ||
194 | * 1: I2C addr << 1 | ||
195 | * 2: reg addr len | ||
196 | * byte 3 and 4 can be used as reg addr | ||
197 | * 3: reg addr MSB | ||
198 | * used when reg addr len is set to 2 | ||
199 | * 4: reg addr LSB | ||
200 | * used when reg addr len is set to 1 or 2 | ||
201 | * | ||
202 | * For the simplify we do not use register addr at all. | ||
203 | * NOTE: As a firmware knows tuner type there is very small possibility | ||
204 | * there could be some tuner I2C hacks done by firmware and this may | ||
205 | * lead problems if firmware expects those bytes are used. | ||
206 | */ | ||
207 | if (num == 2 && !(msg[0].flags & I2C_M_RD) && | ||
208 | (msg[1].flags & I2C_M_RD)) { | ||
209 | if (msg[0].len > 40 || msg[1].len > 40) { | ||
210 | /* TODO: correct limits > 40 */ | ||
211 | ret = -EOPNOTSUPP; | ||
212 | } else if (msg[0].addr == state->af9033_config[0].i2c_addr) { | ||
213 | /* integrated demod */ | ||
214 | u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | | ||
215 | msg[0].buf[2]; | ||
216 | ret = af9035_rd_regs(d, reg, &msg[1].buf[0], | ||
217 | msg[1].len); | ||
218 | } else { | ||
219 | /* I2C */ | ||
220 | u8 buf[5 + msg[0].len]; | ||
221 | struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), | ||
222 | buf, msg[1].len, msg[1].buf }; | ||
223 | buf[0] = msg[1].len; | ||
224 | buf[1] = msg[0].addr << 1; | ||
225 | buf[2] = 0x00; /* reg addr len */ | ||
226 | buf[3] = 0x00; /* reg addr MSB */ | ||
227 | buf[4] = 0x00; /* reg addr LSB */ | ||
228 | memcpy(&buf[5], msg[0].buf, msg[0].len); | ||
229 | ret = af9035_ctrl_msg(d, &req); | ||
230 | } | ||
231 | } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { | ||
232 | if (msg[0].len > 40) { | ||
233 | /* TODO: correct limits > 40 */ | ||
234 | ret = -EOPNOTSUPP; | ||
235 | } else if (msg[0].addr == state->af9033_config[0].i2c_addr) { | ||
236 | /* integrated demod */ | ||
237 | u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | | ||
238 | msg[0].buf[2]; | ||
239 | ret = af9035_wr_regs(d, reg, &msg[0].buf[3], | ||
240 | msg[0].len - 3); | ||
241 | } else { | ||
242 | /* I2C */ | ||
243 | u8 buf[5 + msg[0].len]; | ||
244 | struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, | ||
245 | 0, NULL }; | ||
246 | buf[0] = msg[0].len; | ||
247 | buf[1] = msg[0].addr << 1; | ||
248 | buf[2] = 0x00; /* reg addr len */ | ||
249 | buf[3] = 0x00; /* reg addr MSB */ | ||
250 | buf[4] = 0x00; /* reg addr LSB */ | ||
251 | memcpy(&buf[5], msg[0].buf, msg[0].len); | ||
252 | ret = af9035_ctrl_msg(d, &req); | ||
253 | } | ||
254 | } else { | ||
255 | /* | ||
256 | * We support only two kind of I2C transactions: | ||
257 | * 1) 1 x read + 1 x write | ||
258 | * 2) 1 x write | ||
259 | */ | ||
260 | ret = -EOPNOTSUPP; | ||
261 | } | ||
262 | |||
263 | mutex_unlock(&d->i2c_mutex); | ||
264 | |||
265 | if (ret < 0) | ||
266 | return ret; | ||
267 | else | ||
268 | return num; | ||
269 | } | ||
270 | |||
271 | static u32 af9035_i2c_functionality(struct i2c_adapter *adapter) | ||
272 | { | ||
273 | return I2C_FUNC_I2C; | ||
274 | } | ||
275 | |||
276 | static struct i2c_algorithm af9035_i2c_algo = { | ||
277 | .master_xfer = af9035_i2c_master_xfer, | ||
278 | .functionality = af9035_i2c_functionality, | ||
279 | }; | ||
280 | |||
281 | static int af9035_identify_state(struct dvb_usb_device *d, const char **name) | ||
282 | { | ||
283 | int ret; | ||
284 | u8 wbuf[1] = { 1 }; | ||
285 | u8 rbuf[4]; | ||
286 | struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, | ||
287 | sizeof(rbuf), rbuf }; | ||
288 | |||
289 | ret = af9035_ctrl_msg(d, &req); | ||
290 | if (ret < 0) | ||
291 | goto err; | ||
292 | |||
293 | pr_debug("%s: reply=%*ph\n", __func__, 4, rbuf); | ||
294 | if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3]) | ||
295 | ret = WARM; | ||
296 | else | ||
297 | ret = COLD; | ||
298 | |||
299 | return ret; | ||
300 | |||
301 | err: | ||
302 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
303 | |||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | static int af9035_download_firmware(struct dvb_usb_device *d, | ||
308 | const struct firmware *fw) | ||
309 | { | ||
310 | int ret, i, j, len; | ||
311 | u8 wbuf[1]; | ||
312 | u8 rbuf[4]; | ||
313 | struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; | ||
314 | struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL }; | ||
315 | struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; | ||
316 | u8 hdr_core; | ||
317 | u16 hdr_addr, hdr_data_len, hdr_checksum; | ||
318 | #define MAX_DATA 58 | ||
319 | #define HDR_SIZE 7 | ||
320 | |||
321 | /* | ||
322 | * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info! | ||
323 | * | ||
324 | * byte 0: MCS 51 core | ||
325 | * There are two inside the AF9035 (1=Link and 2=OFDM) with separate | ||
326 | * address spaces | ||
327 | * byte 1-2: Big endian destination address | ||
328 | * byte 3-4: Big endian number of data bytes following the header | ||
329 | * byte 5-6: Big endian header checksum, apparently ignored by the chip | ||
330 | * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256) | ||
331 | */ | ||
332 | |||
333 | for (i = fw->size; i > HDR_SIZE;) { | ||
334 | hdr_core = fw->data[fw->size - i + 0]; | ||
335 | hdr_addr = fw->data[fw->size - i + 1] << 8; | ||
336 | hdr_addr |= fw->data[fw->size - i + 2] << 0; | ||
337 | hdr_data_len = fw->data[fw->size - i + 3] << 8; | ||
338 | hdr_data_len |= fw->data[fw->size - i + 4] << 0; | ||
339 | hdr_checksum = fw->data[fw->size - i + 5] << 8; | ||
340 | hdr_checksum |= fw->data[fw->size - i + 6] << 0; | ||
341 | |||
342 | pr_debug("%s: core=%d addr=%04x data_len=%d checksum=%04x\n", | ||
343 | __func__, hdr_core, hdr_addr, hdr_data_len, | ||
344 | hdr_checksum); | ||
345 | |||
346 | if (((hdr_core != 1) && (hdr_core != 2)) || | ||
347 | (hdr_data_len > i)) { | ||
348 | pr_debug("%s: bad firmware\n", __func__); | ||
349 | break; | ||
350 | } | ||
351 | |||
352 | /* download begin packet */ | ||
353 | req.cmd = CMD_FW_DL_BEGIN; | ||
354 | ret = af9035_ctrl_msg(d, &req); | ||
355 | if (ret < 0) | ||
356 | goto err; | ||
357 | |||
358 | /* download firmware packet(s) */ | ||
359 | for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) { | ||
360 | len = j; | ||
361 | if (len > MAX_DATA) | ||
362 | len = MAX_DATA; | ||
363 | req_fw_dl.wlen = len; | ||
364 | req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + | ||
365 | HDR_SIZE + hdr_data_len - j]; | ||
366 | ret = af9035_ctrl_msg(d, &req_fw_dl); | ||
367 | if (ret < 0) | ||
368 | goto err; | ||
369 | } | ||
370 | |||
371 | /* download end packet */ | ||
372 | req.cmd = CMD_FW_DL_END; | ||
373 | ret = af9035_ctrl_msg(d, &req); | ||
374 | if (ret < 0) | ||
375 | goto err; | ||
376 | |||
377 | i -= hdr_data_len + HDR_SIZE; | ||
378 | |||
379 | pr_debug("%s: data uploaded=%zu\n", __func__, fw->size - i); | ||
380 | } | ||
381 | |||
382 | /* firmware loaded, request boot */ | ||
383 | req.cmd = CMD_FW_BOOT; | ||
384 | ret = af9035_ctrl_msg(d, &req); | ||
385 | if (ret < 0) | ||
386 | goto err; | ||
387 | |||
388 | /* ensure firmware starts */ | ||
389 | wbuf[0] = 1; | ||
390 | ret = af9035_ctrl_msg(d, &req_fw_ver); | ||
391 | if (ret < 0) | ||
392 | goto err; | ||
393 | |||
394 | if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { | ||
395 | pr_err("%s: firmware did not run\n", KBUILD_MODNAME); | ||
396 | ret = -ENODEV; | ||
397 | goto err; | ||
398 | } | ||
399 | |||
400 | pr_info("%s: firmware version=%d.%d.%d.%d", KBUILD_MODNAME, | ||
401 | rbuf[0], rbuf[1], rbuf[2], rbuf[3]); | ||
402 | |||
403 | return 0; | ||
404 | |||
405 | err: | ||
406 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
407 | |||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | static int af9035_download_firmware_it9135(struct dvb_usb_device *d, | ||
412 | const struct firmware *fw) | ||
413 | { | ||
414 | int ret, i, i_prev; | ||
415 | u8 wbuf[1]; | ||
416 | u8 rbuf[4]; | ||
417 | struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; | ||
418 | struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; | ||
419 | struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; | ||
420 | #define HDR_SIZE 7 | ||
421 | |||
422 | /* | ||
423 | * There seems to be following firmware header. Meaning of bytes 0-3 | ||
424 | * is unknown. | ||
425 | * | ||
426 | * 0: 3 | ||
427 | * 1: 0, 1 | ||
428 | * 2: 0 | ||
429 | * 3: 1, 2, 3 | ||
430 | * 4: addr MSB | ||
431 | * 5: addr LSB | ||
432 | * 6: count of data bytes ? | ||
433 | */ | ||
434 | |||
435 | for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { | ||
436 | if (i == fw->size || | ||
437 | (fw->data[i + 0] == 0x03 && | ||
438 | (fw->data[i + 1] == 0x00 || | ||
439 | fw->data[i + 1] == 0x01) && | ||
440 | fw->data[i + 2] == 0x00)) { | ||
441 | req_fw_dl.wlen = i - i_prev; | ||
442 | req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; | ||
443 | i_prev = i; | ||
444 | ret = af9035_ctrl_msg(d, &req_fw_dl); | ||
445 | if (ret < 0) | ||
446 | goto err; | ||
447 | |||
448 | pr_debug("%s: data uploaded=%d\n", __func__, i); | ||
449 | } | ||
450 | } | ||
451 | |||
452 | /* firmware loaded, request boot */ | ||
453 | req.cmd = CMD_FW_BOOT; | ||
454 | ret = af9035_ctrl_msg(d, &req); | ||
455 | if (ret < 0) | ||
456 | goto err; | ||
457 | |||
458 | /* ensure firmware starts */ | ||
459 | wbuf[0] = 1; | ||
460 | ret = af9035_ctrl_msg(d, &req_fw_ver); | ||
461 | if (ret < 0) | ||
462 | goto err; | ||
463 | |||
464 | if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { | ||
465 | pr_err("%s: firmware did not run\n", KBUILD_MODNAME); | ||
466 | ret = -ENODEV; | ||
467 | goto err; | ||
468 | } | ||
469 | |||
470 | pr_info("%s: firmware version=%d.%d.%d.%d", KBUILD_MODNAME, | ||
471 | rbuf[0], rbuf[1], rbuf[2], rbuf[3]); | ||
472 | |||
473 | return 0; | ||
474 | |||
475 | err: | ||
476 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
477 | |||
478 | return ret; | ||
479 | } | ||
480 | |||
481 | static int af9035_read_config(struct dvb_usb_device *d) | ||
482 | { | ||
483 | struct state *state = d_to_priv(d); | ||
484 | int ret, i, eeprom_shift = 0; | ||
485 | u8 tmp; | ||
486 | u16 tmp16; | ||
487 | |||
488 | /* check if there is dual tuners */ | ||
489 | ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp); | ||
490 | if (ret < 0) | ||
491 | goto err; | ||
492 | |||
493 | state->dual_mode = tmp; | ||
494 | pr_debug("%s: dual mode=%d\n", __func__, state->dual_mode); | ||
495 | |||
496 | for (i = 0; i < state->dual_mode + 1; i++) { | ||
497 | /* tuner */ | ||
498 | ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp); | ||
499 | if (ret < 0) | ||
500 | goto err; | ||
501 | |||
502 | state->af9033_config[i].tuner = tmp; | ||
503 | pr_debug("%s: [%d]tuner=%02x\n", __func__, i, tmp); | ||
504 | |||
505 | switch (tmp) { | ||
506 | case AF9033_TUNER_TUA9001: | ||
507 | case AF9033_TUNER_FC0011: | ||
508 | case AF9033_TUNER_MXL5007T: | ||
509 | case AF9033_TUNER_TDA18218: | ||
510 | state->af9033_config[i].spec_inv = 1; | ||
511 | break; | ||
512 | default: | ||
513 | pr_info("%s: tuner ID=%02x not supported, please " \ | ||
514 | "report!", KBUILD_MODNAME, tmp); | ||
515 | }; | ||
516 | |||
517 | /* tuner IF frequency */ | ||
518 | ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp); | ||
519 | if (ret < 0) | ||
520 | goto err; | ||
521 | |||
522 | tmp16 = tmp; | ||
523 | |||
524 | ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp); | ||
525 | if (ret < 0) | ||
526 | goto err; | ||
527 | |||
528 | tmp16 |= tmp << 8; | ||
529 | |||
530 | pr_debug("%s: [%d]IF=%d\n", __func__, i, tmp16); | ||
531 | |||
532 | eeprom_shift = 0x10; /* shift for the 2nd tuner params */ | ||
533 | } | ||
534 | |||
535 | /* get demod clock */ | ||
536 | ret = af9035_rd_reg(d, 0x00d800, &tmp); | ||
537 | if (ret < 0) | ||
538 | goto err; | ||
539 | |||
540 | tmp = (tmp >> 0) & 0x0f; | ||
541 | |||
542 | for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) | ||
543 | state->af9033_config[i].clock = clock_lut[tmp]; | ||
544 | |||
545 | return 0; | ||
546 | |||
547 | err: | ||
548 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
549 | |||
550 | return ret; | ||
551 | } | ||
552 | |||
553 | static int af9035_read_config_it9135(struct dvb_usb_device *d) | ||
554 | { | ||
555 | struct state *state = d_to_priv(d); | ||
556 | int ret, i; | ||
557 | u8 tmp; | ||
558 | |||
559 | state->dual_mode = false; | ||
560 | |||
561 | /* get demod clock */ | ||
562 | ret = af9035_rd_reg(d, 0x00d800, &tmp); | ||
563 | if (ret < 0) | ||
564 | goto err; | ||
565 | |||
566 | tmp = (tmp >> 0) & 0x0f; | ||
567 | |||
568 | for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++) | ||
569 | state->af9033_config[i].clock = clock_lut_it9135[tmp]; | ||
570 | |||
571 | return 0; | ||
572 | |||
573 | err: | ||
574 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
575 | |||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, | ||
580 | int cmd, int arg) | ||
581 | { | ||
582 | int ret; | ||
583 | |||
584 | switch (cmd) { | ||
585 | case FC0011_FE_CALLBACK_POWER: | ||
586 | /* Tuner enable */ | ||
587 | ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1); | ||
588 | if (ret < 0) | ||
589 | goto err; | ||
590 | |||
591 | ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1); | ||
592 | if (ret < 0) | ||
593 | goto err; | ||
594 | |||
595 | ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1); | ||
596 | if (ret < 0) | ||
597 | goto err; | ||
598 | |||
599 | /* LED */ | ||
600 | ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1); | ||
601 | if (ret < 0) | ||
602 | goto err; | ||
603 | |||
604 | ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1); | ||
605 | if (ret < 0) | ||
606 | goto err; | ||
607 | |||
608 | usleep_range(10000, 50000); | ||
609 | break; | ||
610 | case FC0011_FE_CALLBACK_RESET: | ||
611 | ret = af9035_wr_reg(d, 0xd8e9, 1); | ||
612 | if (ret < 0) | ||
613 | goto err; | ||
614 | |||
615 | ret = af9035_wr_reg(d, 0xd8e8, 1); | ||
616 | if (ret < 0) | ||
617 | goto err; | ||
618 | |||
619 | ret = af9035_wr_reg(d, 0xd8e7, 1); | ||
620 | if (ret < 0) | ||
621 | goto err; | ||
622 | |||
623 | usleep_range(10000, 20000); | ||
624 | |||
625 | ret = af9035_wr_reg(d, 0xd8e7, 0); | ||
626 | if (ret < 0) | ||
627 | goto err; | ||
628 | |||
629 | usleep_range(10000, 20000); | ||
630 | break; | ||
631 | default: | ||
632 | ret = -EINVAL; | ||
633 | goto err; | ||
634 | } | ||
635 | |||
636 | return 0; | ||
637 | |||
638 | err: | ||
639 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
640 | |||
641 | return ret; | ||
642 | } | ||
643 | |||
644 | static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) | ||
645 | { | ||
646 | struct state *state = d_to_priv(d); | ||
647 | |||
648 | switch (state->af9033_config[0].tuner) { | ||
649 | case AF9033_TUNER_FC0011: | ||
650 | return af9035_fc0011_tuner_callback(d, cmd, arg); | ||
651 | default: | ||
652 | break; | ||
653 | } | ||
654 | |||
655 | return -ENODEV; | ||
656 | } | ||
657 | |||
658 | static int af9035_frontend_callback(void *adapter_priv, int component, | ||
659 | int cmd, int arg) | ||
660 | { | ||
661 | struct i2c_adapter *adap = adapter_priv; | ||
662 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
663 | |||
664 | switch (component) { | ||
665 | case DVB_FRONTEND_COMPONENT_TUNER: | ||
666 | return af9035_tuner_callback(d, cmd, arg); | ||
667 | default: | ||
668 | break; | ||
669 | } | ||
670 | |||
671 | return -EINVAL; | ||
672 | } | ||
673 | |||
674 | static int af9035_frontend_attach(struct dvb_usb_adapter *adap) | ||
675 | { | ||
676 | struct state *state = adap_to_priv(adap); | ||
677 | struct dvb_usb_device *d = adap_to_d(adap); | ||
678 | int ret; | ||
679 | |||
680 | if (!state->af9033_config[adap->id].tuner) { | ||
681 | /* unsupported tuner */ | ||
682 | ret = -ENODEV; | ||
683 | goto err; | ||
684 | } | ||
685 | |||
686 | if (adap->id == 0) { | ||
687 | state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB; | ||
688 | state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL; | ||
689 | |||
690 | ret = af9035_wr_reg(d, 0x00417f, | ||
691 | state->af9033_config[1].i2c_addr); | ||
692 | if (ret < 0) | ||
693 | goto err; | ||
694 | |||
695 | ret = af9035_wr_reg(d, 0x00d81a, | ||
696 | state->dual_mode); | ||
697 | if (ret < 0) | ||
698 | goto err; | ||
699 | } | ||
700 | |||
701 | /* attach demodulator */ | ||
702 | adap->fe[0] = dvb_attach(af9033_attach, | ||
703 | &state->af9033_config[adap->id], &d->i2c_adap); | ||
704 | if (adap->fe[0] == NULL) { | ||
705 | ret = -ENODEV; | ||
706 | goto err; | ||
707 | } | ||
708 | |||
709 | /* disable I2C-gate */ | ||
710 | adap->fe[0]->ops.i2c_gate_ctrl = NULL; | ||
711 | adap->fe[0]->callback = af9035_frontend_callback; | ||
712 | |||
713 | return 0; | ||
714 | |||
715 | err: | ||
716 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
717 | |||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | static struct tua9001_config af9035_tua9001_config = { | ||
722 | .i2c_addr = 0x60, | ||
723 | }; | ||
724 | |||
725 | static const struct fc0011_config af9035_fc0011_config = { | ||
726 | .i2c_address = 0x60, | ||
727 | }; | ||
728 | |||
729 | static struct mxl5007t_config af9035_mxl5007t_config = { | ||
730 | .xtal_freq_hz = MxL_XTAL_24_MHZ, | ||
731 | .if_freq_hz = MxL_IF_4_57_MHZ, | ||
732 | .invert_if = 0, | ||
733 | .loop_thru_enable = 0, | ||
734 | .clk_out_enable = 0, | ||
735 | .clk_out_amp = MxL_CLKOUT_AMP_0_94V, | ||
736 | }; | ||
737 | |||
738 | static struct tda18218_config af9035_tda18218_config = { | ||
739 | .i2c_address = 0x60, | ||
740 | .i2c_wr_max = 21, | ||
741 | }; | ||
742 | |||
743 | static int af9035_tuner_attach(struct dvb_usb_adapter *adap) | ||
744 | { | ||
745 | struct state *state = adap_to_priv(adap); | ||
746 | struct dvb_usb_device *d = adap_to_d(adap); | ||
747 | int ret; | ||
748 | struct dvb_frontend *fe; | ||
749 | |||
750 | switch (state->af9033_config[adap->id].tuner) { | ||
751 | case AF9033_TUNER_TUA9001: | ||
752 | /* AF9035 gpiot3 = TUA9001 RESETN | ||
753 | AF9035 gpiot2 = TUA9001 RXEN */ | ||
754 | |||
755 | /* configure gpiot2 and gpiot2 as output */ | ||
756 | ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01); | ||
757 | if (ret < 0) | ||
758 | goto err; | ||
759 | |||
760 | ret = af9035_wr_reg_mask(d, 0x00d8ed, 0x01, 0x01); | ||
761 | if (ret < 0) | ||
762 | goto err; | ||
763 | |||
764 | ret = af9035_wr_reg_mask(d, 0x00d8e8, 0x01, 0x01); | ||
765 | if (ret < 0) | ||
766 | goto err; | ||
767 | |||
768 | ret = af9035_wr_reg_mask(d, 0x00d8e9, 0x01, 0x01); | ||
769 | if (ret < 0) | ||
770 | goto err; | ||
771 | |||
772 | /* reset tuner */ | ||
773 | ret = af9035_wr_reg_mask(d, 0x00d8e7, 0x00, 0x01); | ||
774 | if (ret < 0) | ||
775 | goto err; | ||
776 | |||
777 | usleep_range(2000, 20000); | ||
778 | |||
779 | ret = af9035_wr_reg_mask(d, 0x00d8e7, 0x01, 0x01); | ||
780 | if (ret < 0) | ||
781 | goto err; | ||
782 | |||
783 | /* activate tuner RX */ | ||
784 | /* TODO: use callback for TUA9001 RXEN */ | ||
785 | ret = af9035_wr_reg_mask(d, 0x00d8eb, 0x01, 0x01); | ||
786 | if (ret < 0) | ||
787 | goto err; | ||
788 | |||
789 | /* attach tuner */ | ||
790 | fe = dvb_attach(tua9001_attach, adap->fe[0], | ||
791 | &d->i2c_adap, &af9035_tua9001_config); | ||
792 | break; | ||
793 | case AF9033_TUNER_FC0011: | ||
794 | fe = dvb_attach(fc0011_attach, adap->fe[0], | ||
795 | &d->i2c_adap, &af9035_fc0011_config); | ||
796 | break; | ||
797 | case AF9033_TUNER_MXL5007T: | ||
798 | ret = af9035_wr_reg(d, 0x00d8e0, 1); | ||
799 | if (ret < 0) | ||
800 | goto err; | ||
801 | ret = af9035_wr_reg(d, 0x00d8e1, 1); | ||
802 | if (ret < 0) | ||
803 | goto err; | ||
804 | ret = af9035_wr_reg(d, 0x00d8df, 0); | ||
805 | if (ret < 0) | ||
806 | goto err; | ||
807 | |||
808 | msleep(30); | ||
809 | |||
810 | ret = af9035_wr_reg(d, 0x00d8df, 1); | ||
811 | if (ret < 0) | ||
812 | goto err; | ||
813 | |||
814 | msleep(300); | ||
815 | |||
816 | ret = af9035_wr_reg(d, 0x00d8c0, 1); | ||
817 | if (ret < 0) | ||
818 | goto err; | ||
819 | ret = af9035_wr_reg(d, 0x00d8c1, 1); | ||
820 | if (ret < 0) | ||
821 | goto err; | ||
822 | ret = af9035_wr_reg(d, 0x00d8bf, 0); | ||
823 | if (ret < 0) | ||
824 | goto err; | ||
825 | ret = af9035_wr_reg(d, 0x00d8b4, 1); | ||
826 | if (ret < 0) | ||
827 | goto err; | ||
828 | ret = af9035_wr_reg(d, 0x00d8b5, 1); | ||
829 | if (ret < 0) | ||
830 | goto err; | ||
831 | ret = af9035_wr_reg(d, 0x00d8b3, 1); | ||
832 | if (ret < 0) | ||
833 | goto err; | ||
834 | |||
835 | /* attach tuner */ | ||
836 | fe = dvb_attach(mxl5007t_attach, adap->fe[0], | ||
837 | &d->i2c_adap, 0x60, &af9035_mxl5007t_config); | ||
838 | break; | ||
839 | case AF9033_TUNER_TDA18218: | ||
840 | /* attach tuner */ | ||
841 | fe = dvb_attach(tda18218_attach, adap->fe[0], | ||
842 | &d->i2c_adap, &af9035_tda18218_config); | ||
843 | break; | ||
844 | default: | ||
845 | fe = NULL; | ||
846 | } | ||
847 | |||
848 | if (fe == NULL) { | ||
849 | ret = -ENODEV; | ||
850 | goto err; | ||
851 | } | ||
852 | |||
853 | return 0; | ||
854 | |||
855 | err: | ||
856 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
857 | |||
858 | return ret; | ||
859 | } | ||
860 | |||
861 | static int af9035_init(struct dvb_usb_device *d) | ||
862 | { | ||
863 | struct state *state = d_to_priv(d); | ||
864 | int ret, i; | ||
865 | u16 frame_size = 87 * 188 / 4; | ||
866 | u8 packet_size = 512 / 4; | ||
867 | struct reg_val_mask tab[] = { | ||
868 | { 0x80f99d, 0x01, 0x01 }, | ||
869 | { 0x80f9a4, 0x01, 0x01 }, | ||
870 | { 0x00dd11, 0x00, 0x20 }, | ||
871 | { 0x00dd11, 0x00, 0x40 }, | ||
872 | { 0x00dd13, 0x00, 0x20 }, | ||
873 | { 0x00dd13, 0x00, 0x40 }, | ||
874 | { 0x00dd11, 0x20, 0x20 }, | ||
875 | { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, | ||
876 | { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, | ||
877 | { 0x00dd0c, packet_size, 0xff}, | ||
878 | { 0x00dd11, state->dual_mode << 6, 0x40 }, | ||
879 | { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, | ||
880 | { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, | ||
881 | { 0x00dd0d, packet_size, 0xff }, | ||
882 | { 0x80f9a3, 0x00, 0x01 }, | ||
883 | { 0x80f9cd, 0x00, 0x01 }, | ||
884 | { 0x80f99d, 0x00, 0x01 }, | ||
885 | { 0x80f9a4, 0x00, 0x01 }, | ||
886 | }; | ||
887 | |||
888 | pr_debug("%s: USB speed=%d frame_size=%04x packet_size=%02x\n", | ||
889 | __func__, d->udev->speed, frame_size, packet_size); | ||
890 | |||
891 | /* init endpoints */ | ||
892 | for (i = 0; i < ARRAY_SIZE(tab); i++) { | ||
893 | ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, | ||
894 | tab[i].mask); | ||
895 | if (ret < 0) | ||
896 | goto err; | ||
897 | } | ||
898 | |||
899 | return 0; | ||
900 | |||
901 | err: | ||
902 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
903 | |||
904 | return ret; | ||
905 | } | ||
906 | |||
907 | static int af9035_rc_query(struct dvb_usb_device *d) | ||
908 | { | ||
909 | unsigned int key; | ||
910 | unsigned char b[4]; | ||
911 | int ret; | ||
912 | struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b }; | ||
913 | |||
914 | ret = af9035_ctrl_msg(d, &req); | ||
915 | if (ret < 0) | ||
916 | goto err; | ||
917 | |||
918 | if ((b[2] + b[3]) == 0xff) { | ||
919 | if ((b[0] + b[1]) == 0xff) { | ||
920 | /* NEC */ | ||
921 | key = b[0] << 8 | b[2]; | ||
922 | } else { | ||
923 | /* ext. NEC */ | ||
924 | key = b[0] << 16 | b[1] << 8 | b[2]; | ||
925 | } | ||
926 | } else { | ||
927 | key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; | ||
928 | } | ||
929 | |||
930 | rc_keydown(d->rc_dev, key, 0); | ||
931 | |||
932 | err: | ||
933 | /* ignore errors */ | ||
934 | return 0; | ||
935 | } | ||
936 | |||
937 | static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) | ||
938 | { | ||
939 | int ret; | ||
940 | u8 tmp; | ||
941 | |||
942 | ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp); | ||
943 | if (ret < 0) | ||
944 | goto err; | ||
945 | |||
946 | pr_debug("%s: ir_mode=%02x\n", __func__, tmp); | ||
947 | |||
948 | /* don't activate rc if in HID mode or if not available */ | ||
949 | if (tmp == 5) { | ||
950 | ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp); | ||
951 | if (ret < 0) | ||
952 | goto err; | ||
953 | |||
954 | pr_debug("%s: ir_type=%02x\n", __func__, tmp); | ||
955 | |||
956 | switch (tmp) { | ||
957 | case 0: /* NEC */ | ||
958 | default: | ||
959 | rc->allowed_protos = RC_TYPE_NEC; | ||
960 | break; | ||
961 | case 1: /* RC6 */ | ||
962 | rc->allowed_protos = RC_TYPE_RC6; | ||
963 | break; | ||
964 | } | ||
965 | |||
966 | rc->query = af9035_rc_query; | ||
967 | rc->interval = 500; | ||
968 | |||
969 | /* load empty to enable rc */ | ||
970 | if (!rc->map_name) | ||
971 | rc->map_name = RC_MAP_EMPTY; | ||
972 | } | ||
973 | |||
974 | return 0; | ||
975 | |||
976 | err: | ||
977 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
978 | |||
979 | return ret; | ||
980 | } | ||
981 | |||
982 | /* interface 0 is used by DVB-T receiver and | ||
983 | interface 1 is for remote controller (HID) */ | ||
984 | static const struct dvb_usb_device_properties af9035_props = { | ||
985 | .driver_name = KBUILD_MODNAME, | ||
986 | .owner = THIS_MODULE, | ||
987 | .adapter_nr = adapter_nr, | ||
988 | .size_of_priv = sizeof(struct state), | ||
989 | |||
990 | .generic_bulk_ctrl_endpoint = 0x02, | ||
991 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
992 | |||
993 | .identify_state = af9035_identify_state, | ||
994 | .firmware = "dvb-usb-af9035-02.fw", | ||
995 | .download_firmware = af9035_download_firmware, | ||
996 | |||
997 | .i2c_algo = &af9035_i2c_algo, | ||
998 | .read_config = af9035_read_config, | ||
999 | .frontend_attach = af9035_frontend_attach, | ||
1000 | .tuner_attach = af9035_tuner_attach, | ||
1001 | .init = af9035_init, | ||
1002 | .get_rc_config = af9035_get_rc_config, | ||
1003 | |||
1004 | .num_adapters = 1, | ||
1005 | .adapter = { | ||
1006 | { | ||
1007 | .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), | ||
1008 | }, { | ||
1009 | .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), | ||
1010 | }, | ||
1011 | }, | ||
1012 | }; | ||
1013 | |||
1014 | static const struct dvb_usb_device_properties it9135_props = { | ||
1015 | .driver_name = KBUILD_MODNAME, | ||
1016 | .owner = THIS_MODULE, | ||
1017 | .adapter_nr = adapter_nr, | ||
1018 | .size_of_priv = sizeof(struct state), | ||
1019 | |||
1020 | .generic_bulk_ctrl_endpoint = 0x02, | ||
1021 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
1022 | |||
1023 | .identify_state = af9035_identify_state, | ||
1024 | .firmware = "dvb-usb-it9135-01.fw", | ||
1025 | .download_firmware = af9035_download_firmware_it9135, | ||
1026 | |||
1027 | .i2c_algo = &af9035_i2c_algo, | ||
1028 | .read_config = af9035_read_config_it9135, | ||
1029 | .frontend_attach = af9035_frontend_attach, | ||
1030 | .tuner_attach = af9035_tuner_attach, | ||
1031 | .init = af9035_init, | ||
1032 | .get_rc_config = af9035_get_rc_config, | ||
1033 | |||
1034 | .num_adapters = 1, | ||
1035 | .adapter = { | ||
1036 | { | ||
1037 | .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188), | ||
1038 | }, { | ||
1039 | .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188), | ||
1040 | }, | ||
1041 | }, | ||
1042 | }; | ||
1043 | |||
1044 | static const struct usb_device_id af9035_id_table[] = { | ||
1045 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035, | ||
1046 | &af9035_props, "Afatech AF9035 reference design", NULL) }, | ||
1047 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000, | ||
1048 | &af9035_props, "Afatech AF9035 reference design", NULL) }, | ||
1049 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001, | ||
1050 | &af9035_props, "Afatech AF9035 reference design", NULL) }, | ||
1051 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002, | ||
1052 | &af9035_props, "Afatech AF9035 reference design", NULL) }, | ||
1053 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003, | ||
1054 | &af9035_props, "Afatech AF9035 reference design", NULL) }, | ||
1055 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK, | ||
1056 | &af9035_props, "TerraTec Cinergy T Stick", NULL) }, | ||
1057 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835, | ||
1058 | &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, | ||
1059 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835, | ||
1060 | &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) }, | ||
1061 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867, | ||
1062 | &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, | ||
1063 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867, | ||
1064 | &af9035_props, "AVerMedia HD Volar (A867)", NULL) }, | ||
1065 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR, | ||
1066 | &af9035_props, "AVerMedia Twinstar (A825)", NULL) }, | ||
1067 | { } | ||
1068 | }; | ||
1069 | MODULE_DEVICE_TABLE(usb, af9035_id_table); | ||
1070 | |||
1071 | static struct usb_driver af9035_usb_driver = { | ||
1072 | .name = KBUILD_MODNAME, | ||
1073 | .id_table = af9035_id_table, | ||
1074 | .probe = dvb_usbv2_probe, | ||
1075 | .disconnect = dvb_usbv2_disconnect, | ||
1076 | .suspend = dvb_usbv2_suspend, | ||
1077 | .resume = dvb_usbv2_resume, | ||
1078 | .no_dynamic_id = 1, | ||
1079 | .soft_unbind = 1, | ||
1080 | }; | ||
1081 | |||
1082 | module_usb_driver(af9035_usb_driver); | ||
1083 | |||
1084 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
1085 | MODULE_DESCRIPTION("Afatech AF9035 driver"); | ||
1086 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h new file mode 100644 index 000000000000..59ff69ede0f0 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/af9035.h | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * Afatech AF9035 DVB USB driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
5 | * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef AF9035_H | ||
23 | #define AF9035_H | ||
24 | |||
25 | #include "dvb_usb.h" | ||
26 | #include "af9033.h" | ||
27 | #include "tua9001.h" | ||
28 | #include "fc0011.h" | ||
29 | #include "mxl5007t.h" | ||
30 | #include "tda18218.h" | ||
31 | |||
32 | struct reg_val { | ||
33 | u32 reg; | ||
34 | u8 val; | ||
35 | }; | ||
36 | |||
37 | struct reg_val_mask { | ||
38 | u32 reg; | ||
39 | u8 val; | ||
40 | u8 mask; | ||
41 | }; | ||
42 | |||
43 | struct usb_req { | ||
44 | u8 cmd; | ||
45 | u8 mbox; | ||
46 | u8 wlen; | ||
47 | u8 *wbuf; | ||
48 | u8 rlen; | ||
49 | u8 *rbuf; | ||
50 | }; | ||
51 | |||
52 | struct state { | ||
53 | u8 seq; /* packet sequence number */ | ||
54 | bool dual_mode; | ||
55 | |||
56 | struct af9033_config af9033_config[2]; | ||
57 | }; | ||
58 | |||
59 | u32 clock_lut[] = { | ||
60 | 20480000, /* FPGA */ | ||
61 | 16384000, /* 16.38 MHz */ | ||
62 | 20480000, /* 20.48 MHz */ | ||
63 | 36000000, /* 36.00 MHz */ | ||
64 | 30000000, /* 30.00 MHz */ | ||
65 | 26000000, /* 26.00 MHz */ | ||
66 | 28000000, /* 28.00 MHz */ | ||
67 | 32000000, /* 32.00 MHz */ | ||
68 | 34000000, /* 34.00 MHz */ | ||
69 | 24000000, /* 24.00 MHz */ | ||
70 | 22000000, /* 22.00 MHz */ | ||
71 | 12000000, /* 12.00 MHz */ | ||
72 | }; | ||
73 | |||
74 | u32 clock_lut_it9135[] = { | ||
75 | 12000000, /* 12.00 MHz */ | ||
76 | 20480000, /* 20.48 MHz */ | ||
77 | 36000000, /* 36.00 MHz */ | ||
78 | 30000000, /* 30.00 MHz */ | ||
79 | 26000000, /* 26.00 MHz */ | ||
80 | 28000000, /* 28.00 MHz */ | ||
81 | 32000000, /* 32.00 MHz */ | ||
82 | 34000000, /* 34.00 MHz */ | ||
83 | 24000000, /* 24.00 MHz */ | ||
84 | 22000000, /* 22.00 MHz */ | ||
85 | }; | ||
86 | |||
87 | /* EEPROM locations */ | ||
88 | #define EEPROM_IR_MODE 0x430d | ||
89 | #define EEPROM_DUAL_MODE 0x4326 | ||
90 | #define EEPROM_IR_TYPE 0x4329 | ||
91 | #define EEPROM_1_IFFREQ_L 0x432d | ||
92 | #define EEPROM_1_IFFREQ_H 0x432e | ||
93 | #define EEPROM_1_TUNER_ID 0x4331 | ||
94 | #define EEPROM_2_IFFREQ_L 0x433d | ||
95 | #define EEPROM_2_IFFREQ_H 0x433e | ||
96 | #define EEPROM_2_TUNER_ID 0x4341 | ||
97 | |||
98 | /* USB commands */ | ||
99 | #define CMD_MEM_RD 0x00 | ||
100 | #define CMD_MEM_WR 0x01 | ||
101 | #define CMD_I2C_RD 0x02 | ||
102 | #define CMD_I2C_WR 0x03 | ||
103 | #define CMD_IR_GET 0x18 | ||
104 | #define CMD_FW_DL 0x21 | ||
105 | #define CMD_FW_QUERYINFO 0x22 | ||
106 | #define CMD_FW_BOOT 0x23 | ||
107 | #define CMD_FW_DL_BEGIN 0x24 | ||
108 | #define CMD_FW_DL_END 0x25 | ||
109 | #define CMD_FW_SCATTER_WR 0x29 | ||
110 | |||
111 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c new file mode 100644 index 000000000000..fb3829a73d2d --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/anysee.c | |||
@@ -0,0 +1,1324 @@ | |||
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 "dvb-pll.h" | ||
36 | #include "tda1002x.h" | ||
37 | #include "mt352.h" | ||
38 | #include "mt352_priv.h" | ||
39 | #include "zl10353.h" | ||
40 | #include "tda18212.h" | ||
41 | #include "cx24116.h" | ||
42 | #include "stv0900.h" | ||
43 | #include "stv6110.h" | ||
44 | #include "isl6423.h" | ||
45 | #include "cxd2820r.h" | ||
46 | |||
47 | /* debug */ | ||
48 | static int dvb_usb_anysee_debug; | ||
49 | module_param_named(debug, dvb_usb_anysee_debug, int, 0644); | ||
50 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
51 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
52 | |||
53 | static DEFINE_MUTEX(anysee_usb_mutex); | ||
54 | |||
55 | static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, | ||
56 | u8 *rbuf, u8 rlen) | ||
57 | { | ||
58 | struct anysee_state *state = d_to_priv(d); | ||
59 | int act_len, ret, i; | ||
60 | u8 buf[64]; | ||
61 | |||
62 | memcpy(&buf[0], sbuf, slen); | ||
63 | buf[60] = state->seq++; | ||
64 | |||
65 | mutex_lock(&anysee_usb_mutex); | ||
66 | |||
67 | deb_xfer(">>> "); | ||
68 | debug_dump(buf, slen, deb_xfer); | ||
69 | |||
70 | /* We need receive one message more after dvb_usb_generic_rw due | ||
71 | to weird transaction flow, which is 1 x send + 2 x receive. */ | ||
72 | ret = dvb_usbv2_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf)); | ||
73 | if (ret) | ||
74 | goto error_unlock; | ||
75 | |||
76 | /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32 | ||
77 | * (EPIPE, Broken pipe). Function supports currently msleep() as a | ||
78 | * parameter but I would not like to use it, since according to | ||
79 | * Documentation/timers/timers-howto.txt it should not be used such | ||
80 | * short, under < 20ms, sleeps. Repeating failed message would be | ||
81 | * better choice as not to add unwanted delays... | ||
82 | * Fixing that correctly is one of those or both; | ||
83 | * 1) use repeat if possible | ||
84 | * 2) add suitable delay | ||
85 | */ | ||
86 | |||
87 | /* get answer, retry few times if error returned */ | ||
88 | for (i = 0; i < 3; i++) { | ||
89 | /* receive 2nd answer */ | ||
90 | ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, | ||
91 | d->props->generic_bulk_ctrl_endpoint), buf, sizeof(buf), | ||
92 | &act_len, 2000); | ||
93 | |||
94 | if (ret) { | ||
95 | deb_info("%s: recv bulk message failed: %d", | ||
96 | __func__, ret); | ||
97 | } else { | ||
98 | deb_xfer("<<< "); | ||
99 | debug_dump(buf, rlen, deb_xfer); | ||
100 | |||
101 | if (buf[63] != 0x4f) | ||
102 | deb_info("%s: cmd failed\n", __func__); | ||
103 | |||
104 | break; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | if (ret) { | ||
109 | /* all retries failed, it is fatal */ | ||
110 | err("%s: recv bulk message failed: %d", __func__, ret); | ||
111 | goto error_unlock; | ||
112 | } | ||
113 | |||
114 | /* read request, copy returned data to return buf */ | ||
115 | if (rbuf && rlen) | ||
116 | memcpy(rbuf, buf, rlen); | ||
117 | |||
118 | error_unlock: | ||
119 | mutex_unlock(&anysee_usb_mutex); | ||
120 | |||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val) | ||
125 | { | ||
126 | u8 buf[] = {CMD_REG_READ, reg >> 8, reg & 0xff, 0x01}; | ||
127 | int ret; | ||
128 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1); | ||
129 | deb_info("%s: reg:%04x val:%02x\n", __func__, reg, *val); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val) | ||
134 | { | ||
135 | u8 buf[] = {CMD_REG_WRITE, reg >> 8, reg & 0xff, 0x01, val}; | ||
136 | deb_info("%s: reg:%04x val:%02x\n", __func__, reg, val); | ||
137 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
138 | } | ||
139 | |||
140 | /* write single register with mask */ | ||
141 | static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val, | ||
142 | u8 mask) | ||
143 | { | ||
144 | int ret; | ||
145 | u8 tmp; | ||
146 | |||
147 | /* no need for read if whole reg is written */ | ||
148 | if (mask != 0xff) { | ||
149 | ret = anysee_read_reg(d, reg, &tmp); | ||
150 | if (ret) | ||
151 | return ret; | ||
152 | |||
153 | val &= mask; | ||
154 | tmp &= ~mask; | ||
155 | val |= tmp; | ||
156 | } | ||
157 | |||
158 | return anysee_write_reg(d, reg, val); | ||
159 | } | ||
160 | |||
161 | /* read single register with mask */ | ||
162 | static int anysee_rd_reg_mask(struct dvb_usb_device *d, u16 reg, u8 *val, | ||
163 | u8 mask) | ||
164 | { | ||
165 | int ret, i; | ||
166 | u8 tmp; | ||
167 | |||
168 | ret = anysee_read_reg(d, reg, &tmp); | ||
169 | if (ret) | ||
170 | return ret; | ||
171 | |||
172 | tmp &= mask; | ||
173 | |||
174 | /* find position of the first bit */ | ||
175 | for (i = 0; i < 8; i++) { | ||
176 | if ((mask >> i) & 0x01) | ||
177 | break; | ||
178 | } | ||
179 | *val = tmp >> i; | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id) | ||
185 | { | ||
186 | u8 buf[] = {CMD_GET_HW_INFO}; | ||
187 | return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3); | ||
188 | } | ||
189 | |||
190 | static int anysee_streaming_ctrl(struct dvb_frontend *fe, int onoff) | ||
191 | { | ||
192 | u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00}; | ||
193 | deb_info("%s: onoff:%02x\n", __func__, onoff); | ||
194 | return anysee_ctrl_msg(fe_to_d(fe), buf, sizeof(buf), NULL, 0); | ||
195 | } | ||
196 | |||
197 | static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval) | ||
198 | { | ||
199 | u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval}; | ||
200 | deb_info("%s: state:%02x interval:%02x\n", __func__, mode, interval); | ||
201 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
202 | } | ||
203 | |||
204 | static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff) | ||
205 | { | ||
206 | u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff}; | ||
207 | deb_info("%s: onoff:%02x\n", __func__, onoff); | ||
208 | return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
209 | } | ||
210 | |||
211 | /* I2C */ | ||
212 | static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | ||
213 | int num) | ||
214 | { | ||
215 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
216 | int ret = 0, inc, i = 0; | ||
217 | u8 buf[52]; /* 4 + 48 (I2C WR USB command header + I2C WR max) */ | ||
218 | |||
219 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
220 | return -EAGAIN; | ||
221 | |||
222 | while (i < num) { | ||
223 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
224 | if (msg[i].len > 2 || msg[i+1].len > 60) { | ||
225 | ret = -EOPNOTSUPP; | ||
226 | break; | ||
227 | } | ||
228 | buf[0] = CMD_I2C_READ; | ||
229 | buf[1] = (msg[i].addr << 1) | 0x01; | ||
230 | buf[2] = msg[i].buf[0]; | ||
231 | buf[3] = msg[i].buf[1]; | ||
232 | buf[4] = msg[i].len-1; | ||
233 | buf[5] = msg[i+1].len; | ||
234 | ret = anysee_ctrl_msg(d, buf, 6, msg[i+1].buf, | ||
235 | msg[i+1].len); | ||
236 | inc = 2; | ||
237 | } else { | ||
238 | if (msg[i].len > 48) { | ||
239 | ret = -EOPNOTSUPP; | ||
240 | break; | ||
241 | } | ||
242 | buf[0] = CMD_I2C_WRITE; | ||
243 | buf[1] = (msg[i].addr << 1); | ||
244 | buf[2] = msg[i].len; | ||
245 | buf[3] = 0x01; | ||
246 | memcpy(&buf[4], msg[i].buf, msg[i].len); | ||
247 | ret = anysee_ctrl_msg(d, buf, 4 + msg[i].len, NULL, 0); | ||
248 | inc = 1; | ||
249 | } | ||
250 | if (ret) | ||
251 | break; | ||
252 | |||
253 | i += inc; | ||
254 | } | ||
255 | |||
256 | mutex_unlock(&d->i2c_mutex); | ||
257 | |||
258 | return ret ? ret : i; | ||
259 | } | ||
260 | |||
261 | static u32 anysee_i2c_func(struct i2c_adapter *adapter) | ||
262 | { | ||
263 | return I2C_FUNC_I2C; | ||
264 | } | ||
265 | |||
266 | static struct i2c_algorithm anysee_i2c_algo = { | ||
267 | .master_xfer = anysee_master_xfer, | ||
268 | .functionality = anysee_i2c_func, | ||
269 | }; | ||
270 | |||
271 | static int anysee_mt352_demod_init(struct dvb_frontend *fe) | ||
272 | { | ||
273 | static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x28 }; | ||
274 | static u8 reset[] = { RESET, 0x80 }; | ||
275 | static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 }; | ||
276 | static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0x20 }; | ||
277 | static u8 gpp_ctl_cfg[] = { GPP_CTL, 0x33 }; | ||
278 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; | ||
279 | |||
280 | mt352_write(fe, clock_config, sizeof(clock_config)); | ||
281 | udelay(200); | ||
282 | mt352_write(fe, reset, sizeof(reset)); | ||
283 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | ||
284 | |||
285 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | ||
286 | mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); | ||
287 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | /* Callbacks for DVB USB */ | ||
293 | static struct tda10023_config anysee_tda10023_config = { | ||
294 | .demod_address = (0x1a >> 1), | ||
295 | .invert = 0, | ||
296 | .xtal = 16000000, | ||
297 | .pll_m = 11, | ||
298 | .pll_p = 3, | ||
299 | .pll_n = 1, | ||
300 | .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C, | ||
301 | .deltaf = 0xfeeb, | ||
302 | }; | ||
303 | |||
304 | static struct mt352_config anysee_mt352_config = { | ||
305 | .demod_address = (0x1e >> 1), | ||
306 | .demod_init = anysee_mt352_demod_init, | ||
307 | }; | ||
308 | |||
309 | static struct zl10353_config anysee_zl10353_config = { | ||
310 | .demod_address = (0x1e >> 1), | ||
311 | .parallel_ts = 1, | ||
312 | }; | ||
313 | |||
314 | static struct zl10353_config anysee_zl10353_tda18212_config2 = { | ||
315 | .demod_address = (0x1e >> 1), | ||
316 | .parallel_ts = 1, | ||
317 | .disable_i2c_gate_ctrl = 1, | ||
318 | .no_tuner = 1, | ||
319 | .if2 = 41500, | ||
320 | }; | ||
321 | |||
322 | static struct zl10353_config anysee_zl10353_tda18212_config = { | ||
323 | .demod_address = (0x18 >> 1), | ||
324 | .parallel_ts = 1, | ||
325 | .disable_i2c_gate_ctrl = 1, | ||
326 | .no_tuner = 1, | ||
327 | .if2 = 41500, | ||
328 | }; | ||
329 | |||
330 | static struct tda10023_config anysee_tda10023_tda18212_config = { | ||
331 | .demod_address = (0x1a >> 1), | ||
332 | .xtal = 16000000, | ||
333 | .pll_m = 12, | ||
334 | .pll_p = 3, | ||
335 | .pll_n = 1, | ||
336 | .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_B, | ||
337 | .deltaf = 0xba02, | ||
338 | }; | ||
339 | |||
340 | static struct tda18212_config anysee_tda18212_config = { | ||
341 | .i2c_address = (0xc0 >> 1), | ||
342 | .if_dvbt_6 = 4150, | ||
343 | .if_dvbt_7 = 4150, | ||
344 | .if_dvbt_8 = 4150, | ||
345 | .if_dvbc = 5000, | ||
346 | }; | ||
347 | |||
348 | static struct tda18212_config anysee_tda18212_config2 = { | ||
349 | .i2c_address = 0x60 /* (0xc0 >> 1) */, | ||
350 | .if_dvbt_6 = 3550, | ||
351 | .if_dvbt_7 = 3700, | ||
352 | .if_dvbt_8 = 4150, | ||
353 | .if_dvbt2_6 = 3250, | ||
354 | .if_dvbt2_7 = 4000, | ||
355 | .if_dvbt2_8 = 4000, | ||
356 | .if_dvbc = 5000, | ||
357 | }; | ||
358 | |||
359 | static struct cx24116_config anysee_cx24116_config = { | ||
360 | .demod_address = (0xaa >> 1), | ||
361 | .mpg_clk_pos_pol = 0x00, | ||
362 | .i2c_wr_max = 48, | ||
363 | }; | ||
364 | |||
365 | static struct stv0900_config anysee_stv0900_config = { | ||
366 | .demod_address = (0xd0 >> 1), | ||
367 | .demod_mode = 0, | ||
368 | .xtal = 8000000, | ||
369 | .clkmode = 3, | ||
370 | .diseqc_mode = 2, | ||
371 | .tun1_maddress = 0, | ||
372 | .tun1_adc = 1, /* 1 Vpp */ | ||
373 | .path1_mode = 3, | ||
374 | }; | ||
375 | |||
376 | static struct stv6110_config anysee_stv6110_config = { | ||
377 | .i2c_address = (0xc0 >> 1), | ||
378 | .mclk = 16000000, | ||
379 | .clk_div = 1, | ||
380 | }; | ||
381 | |||
382 | static struct isl6423_config anysee_isl6423_config = { | ||
383 | .current_max = SEC_CURRENT_800m, | ||
384 | .curlim = SEC_CURRENT_LIM_OFF, | ||
385 | .mod_extern = 1, | ||
386 | .addr = (0x10 >> 1), | ||
387 | }; | ||
388 | |||
389 | static struct cxd2820r_config anysee_cxd2820r_config = { | ||
390 | .i2c_address = 0x6d, /* (0xda >> 1) */ | ||
391 | .ts_mode = 0x38, | ||
392 | }; | ||
393 | |||
394 | /* | ||
395 | * New USB device strings: Mfr=1, Product=2, SerialNumber=0 | ||
396 | * Manufacturer: AMT.CO.KR | ||
397 | * | ||
398 | * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=???????? | ||
399 | * PCB: ? | ||
400 | * parts: DNOS404ZH102A(MT352, DTT7579(?)) | ||
401 | * | ||
402 | * E30 VID=04b4 PID=861f HW=2 FW=2.1 "anysee-T(LP)" | ||
403 | * PCB: PCB 507T (rev1.61) | ||
404 | * parts: DNOS404ZH103A(ZL10353, DTT7579(?)) | ||
405 | * OEA=0a OEB=00 OEC=00 OED=ff OEE=00 | ||
406 | * IOA=45 IOB=ff IOC=00 IOD=ff IOE=00 | ||
407 | * | ||
408 | * E30 Plus VID=04b4 PID=861f HW=6 FW=1.0 "anysee" | ||
409 | * PCB: 507CD (rev1.1) | ||
410 | * parts: DNOS404ZH103A(ZL10353, DTT7579(?)), CST56I01 | ||
411 | * OEA=80 OEB=00 OEC=00 OED=ff OEE=fe | ||
412 | * IOA=4f IOB=ff IOC=00 IOD=06 IOE=01 | ||
413 | * IOD[0] ZL10353 1=enabled | ||
414 | * IOA[7] TS 0=enabled | ||
415 | * tuner is not behind ZL10353 I2C-gate (no care if gate disabled or not) | ||
416 | * | ||
417 | * E30 C Plus VID=04b4 PID=861f HW=10 FW=1.0 "anysee-DC(LP)" | ||
418 | * PCB: 507DC (rev0.2) | ||
419 | * parts: TDA10023, DTOS403IH102B TM, CST56I01 | ||
420 | * OEA=80 OEB=00 OEC=00 OED=ff OEE=fe | ||
421 | * IOA=4f IOB=ff IOC=00 IOD=26 IOE=01 | ||
422 | * IOD[0] TDA10023 1=enabled | ||
423 | * | ||
424 | * E30 S2 Plus VID=04b4 PID=861f HW=11 FW=0.1 "anysee-S2(LP)" | ||
425 | * PCB: 507SI (rev2.1) | ||
426 | * parts: BS2N10WCC01(CX24116, CX24118), ISL6423, TDA8024 | ||
427 | * OEA=80 OEB=00 OEC=ff OED=ff OEE=fe | ||
428 | * IOA=4d IOB=ff IOC=00 IOD=26 IOE=01 | ||
429 | * IOD[0] CX24116 1=enabled | ||
430 | * | ||
431 | * E30 C Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)" | ||
432 | * PCB: 507FA (rev0.4) | ||
433 | * parts: TDA10023, DTOS403IH102B TM, TDA8024 | ||
434 | * OEA=80 OEB=00 OEC=ff OED=ff OEE=ff | ||
435 | * IOA=4d IOB=ff IOC=00 IOD=00 IOE=c0 | ||
436 | * IOD[5] TDA10023 1=enabled | ||
437 | * IOE[0] tuner 1=enabled | ||
438 | * | ||
439 | * E30 Combo Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)" | ||
440 | * PCB: 507FA (rev1.1) | ||
441 | * parts: ZL10353, TDA10023, DTOS403IH102B TM, TDA8024 | ||
442 | * OEA=80 OEB=00 OEC=ff OED=ff OEE=ff | ||
443 | * IOA=4d IOB=ff IOC=00 IOD=00 IOE=c0 | ||
444 | * DVB-C: | ||
445 | * IOD[5] TDA10023 1=enabled | ||
446 | * IOE[0] tuner 1=enabled | ||
447 | * DVB-T: | ||
448 | * IOD[0] ZL10353 1=enabled | ||
449 | * IOE[0] tuner 0=enabled | ||
450 | * tuner is behind ZL10353 I2C-gate | ||
451 | * | ||
452 | * E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)" | ||
453 | * PCB: 508TC (rev0.6) | ||
454 | * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212) | ||
455 | * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff | ||
456 | * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4 | ||
457 | * IOA[7] TS 1=enabled | ||
458 | * IOE[4] TDA18212 1=enabled | ||
459 | * DVB-C: | ||
460 | * IOD[6] ZL10353 0=disabled | ||
461 | * IOD[5] TDA10023 1=enabled | ||
462 | * IOE[0] IF 1=enabled | ||
463 | * DVB-T: | ||
464 | * IOD[5] TDA10023 0=disabled | ||
465 | * IOD[6] ZL10353 1=enabled | ||
466 | * IOE[0] IF 0=enabled | ||
467 | * | ||
468 | * E7 S2 VID=1c73 PID=861f HW=19 FW=0.4 AMTCI=0.5 "anysee-E7S2(LP)" | ||
469 | * PCB: 508S2 (rev0.7) | ||
470 | * parts: DNBU10512IST(STV0903, STV6110), ISL6423 | ||
471 | * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff | ||
472 | * IOA=4d IOB=00 IOC=c4 IOD=08 IOE=e4 | ||
473 | * IOA[7] TS 1=enabled | ||
474 | * IOE[5] STV0903 1=enabled | ||
475 | * | ||
476 | * E7 T2C VID=1c73 PID=861f HW=20 FW=0.1 AMTCI=0.5 "anysee-E7T2C(LP)" | ||
477 | * PCB: 508T2C (rev0.3) | ||
478 | * parts: DNOQ44QCH106A(CXD2820R, TDA18212), TDA8024 | ||
479 | * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff | ||
480 | * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4 | ||
481 | * IOA[7] TS 1=enabled | ||
482 | * IOE[5] CXD2820R 1=enabled | ||
483 | * | ||
484 | * E7 PTC VID=1c73 PID=861f HW=21 FW=0.1 AMTCI=?? "anysee-E7PTC(LP)" | ||
485 | * PCB: 508PTC (rev0.5) | ||
486 | * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212) | ||
487 | * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff | ||
488 | * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4 | ||
489 | * IOA[7] TS 1=enabled | ||
490 | * IOE[4] TDA18212 1=enabled | ||
491 | * DVB-C: | ||
492 | * IOD[6] ZL10353 0=disabled | ||
493 | * IOD[5] TDA10023 1=enabled | ||
494 | * IOE[0] IF 1=enabled | ||
495 | * DVB-T: | ||
496 | * IOD[5] TDA10023 0=disabled | ||
497 | * IOD[6] ZL10353 1=enabled | ||
498 | * IOE[0] IF 0=enabled | ||
499 | * | ||
500 | * E7 PS2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)" | ||
501 | * PCB: 508PS2 (rev0.4) | ||
502 | * parts: DNBU10512IST(STV0903, STV6110), ISL6423 | ||
503 | * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff | ||
504 | * IOA=4d IOB=00 IOC=c4 IOD=08 IOE=e4 | ||
505 | * IOA[7] TS 1=enabled | ||
506 | * IOE[5] STV0903 1=enabled | ||
507 | */ | ||
508 | |||
509 | static int anysee_read_config(struct dvb_usb_device *d) | ||
510 | { | ||
511 | struct anysee_state *state = d_to_priv(d); | ||
512 | int ret; | ||
513 | u8 hw_info[3]; | ||
514 | |||
515 | /* | ||
516 | * Check which hardware we have. | ||
517 | * We must do this call two times to get reliable values (hw/fw bug). | ||
518 | */ | ||
519 | ret = anysee_get_hw_info(d, hw_info); | ||
520 | if (ret) | ||
521 | goto error; | ||
522 | |||
523 | ret = anysee_get_hw_info(d, hw_info); | ||
524 | if (ret) | ||
525 | goto error; | ||
526 | |||
527 | /* Meaning of these info bytes are guessed. */ | ||
528 | info("firmware version:%d.%d hardware id:%d", | ||
529 | hw_info[1], hw_info[2], hw_info[0]); | ||
530 | |||
531 | state->hw = hw_info[0]; | ||
532 | error: | ||
533 | return ret; | ||
534 | } | ||
535 | |||
536 | /* external I2C gate used for DNOD44CDH086A(TDA18212) tuner module */ | ||
537 | static int anysee_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | ||
538 | { | ||
539 | /* enable / disable tuner access on IOE[4] */ | ||
540 | return anysee_wr_reg_mask(fe_to_d(fe), REG_IOE, (enable << 4), 0x10); | ||
541 | } | ||
542 | |||
543 | static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff) | ||
544 | { | ||
545 | struct anysee_state *state = fe_to_priv(fe); | ||
546 | struct dvb_usb_device *d = fe_to_d(fe); | ||
547 | int ret; | ||
548 | |||
549 | deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); | ||
550 | |||
551 | /* no frontend sleep control */ | ||
552 | if (onoff == 0) | ||
553 | return 0; | ||
554 | |||
555 | switch (state->hw) { | ||
556 | case ANYSEE_HW_507FA: /* 15 */ | ||
557 | /* E30 Combo Plus */ | ||
558 | /* E30 C Plus */ | ||
559 | |||
560 | if (fe->id == 0) { | ||
561 | /* disable DVB-T demod on IOD[0] */ | ||
562 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 0), 0x01); | ||
563 | if (ret) | ||
564 | goto error; | ||
565 | |||
566 | /* enable DVB-C demod on IOD[5] */ | ||
567 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20); | ||
568 | if (ret) | ||
569 | goto error; | ||
570 | |||
571 | /* enable DVB-C tuner on IOE[0] */ | ||
572 | ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 0), 0x01); | ||
573 | if (ret) | ||
574 | goto error; | ||
575 | } else { | ||
576 | /* disable DVB-C demod on IOD[5] */ | ||
577 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20); | ||
578 | if (ret) | ||
579 | goto error; | ||
580 | |||
581 | /* enable DVB-T demod on IOD[0] */ | ||
582 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01); | ||
583 | if (ret) | ||
584 | goto error; | ||
585 | |||
586 | /* enable DVB-T tuner on IOE[0] */ | ||
587 | ret = anysee_wr_reg_mask(d, REG_IOE, (0 << 0), 0x01); | ||
588 | if (ret) | ||
589 | goto error; | ||
590 | } | ||
591 | |||
592 | break; | ||
593 | case ANYSEE_HW_508TC: /* 18 */ | ||
594 | case ANYSEE_HW_508PTC: /* 21 */ | ||
595 | /* E7 TC */ | ||
596 | /* E7 PTC */ | ||
597 | |||
598 | if (fe->id == 0) { | ||
599 | /* disable DVB-T demod on IOD[6] */ | ||
600 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 6), 0x40); | ||
601 | if (ret) | ||
602 | goto error; | ||
603 | |||
604 | /* enable DVB-C demod on IOD[5] */ | ||
605 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20); | ||
606 | if (ret) | ||
607 | goto error; | ||
608 | |||
609 | /* enable IF route on IOE[0] */ | ||
610 | ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 0), 0x01); | ||
611 | if (ret) | ||
612 | goto error; | ||
613 | } else { | ||
614 | /* disable DVB-C demod on IOD[5] */ | ||
615 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20); | ||
616 | if (ret) | ||
617 | goto error; | ||
618 | |||
619 | /* enable DVB-T demod on IOD[6] */ | ||
620 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 6), 0x40); | ||
621 | if (ret) | ||
622 | goto error; | ||
623 | |||
624 | /* enable IF route on IOE[0] */ | ||
625 | ret = anysee_wr_reg_mask(d, REG_IOE, (0 << 0), 0x01); | ||
626 | if (ret) | ||
627 | goto error; | ||
628 | } | ||
629 | |||
630 | break; | ||
631 | default: | ||
632 | ret = 0; | ||
633 | } | ||
634 | |||
635 | error: | ||
636 | return ret; | ||
637 | } | ||
638 | |||
639 | static int anysee_frontend_attach(struct dvb_usb_adapter *adap) | ||
640 | { | ||
641 | struct anysee_state *state = adap_to_priv(adap); | ||
642 | struct dvb_usb_device *d = adap_to_d(adap); | ||
643 | int ret; | ||
644 | u8 tmp; | ||
645 | struct i2c_msg msg[2] = { | ||
646 | { | ||
647 | .addr = anysee_tda18212_config.i2c_address, | ||
648 | .flags = 0, | ||
649 | .len = 1, | ||
650 | .buf = "\x00", | ||
651 | }, { | ||
652 | .addr = anysee_tda18212_config.i2c_address, | ||
653 | .flags = I2C_M_RD, | ||
654 | .len = 1, | ||
655 | .buf = &tmp, | ||
656 | } | ||
657 | }; | ||
658 | |||
659 | switch (state->hw) { | ||
660 | case ANYSEE_HW_507T: /* 2 */ | ||
661 | /* E30 */ | ||
662 | |||
663 | /* attach demod */ | ||
664 | adap->fe[0] = dvb_attach(mt352_attach, &anysee_mt352_config, | ||
665 | &d->i2c_adap); | ||
666 | if (adap->fe[0]) | ||
667 | break; | ||
668 | |||
669 | /* attach demod */ | ||
670 | adap->fe[0] = dvb_attach(zl10353_attach, &anysee_zl10353_config, | ||
671 | &d->i2c_adap); | ||
672 | |||
673 | break; | ||
674 | case ANYSEE_HW_507CD: /* 6 */ | ||
675 | /* E30 Plus */ | ||
676 | |||
677 | /* enable DVB-T demod on IOD[0] */ | ||
678 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01); | ||
679 | if (ret) | ||
680 | goto error; | ||
681 | |||
682 | /* enable transport stream on IOA[7] */ | ||
683 | ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80); | ||
684 | if (ret) | ||
685 | goto error; | ||
686 | |||
687 | /* attach demod */ | ||
688 | adap->fe[0] = dvb_attach(zl10353_attach, &anysee_zl10353_config, | ||
689 | &d->i2c_adap); | ||
690 | |||
691 | break; | ||
692 | case ANYSEE_HW_507DC: /* 10 */ | ||
693 | /* E30 C Plus */ | ||
694 | |||
695 | /* enable DVB-C demod on IOD[0] */ | ||
696 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01); | ||
697 | if (ret) | ||
698 | goto error; | ||
699 | |||
700 | /* attach demod */ | ||
701 | adap->fe[0] = dvb_attach(tda10023_attach, | ||
702 | &anysee_tda10023_config, &d->i2c_adap, 0x48); | ||
703 | |||
704 | break; | ||
705 | case ANYSEE_HW_507SI: /* 11 */ | ||
706 | /* E30 S2 Plus */ | ||
707 | |||
708 | /* enable DVB-S/S2 demod on IOD[0] */ | ||
709 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01); | ||
710 | if (ret) | ||
711 | goto error; | ||
712 | |||
713 | /* attach demod */ | ||
714 | adap->fe[0] = dvb_attach(cx24116_attach, &anysee_cx24116_config, | ||
715 | &d->i2c_adap); | ||
716 | |||
717 | break; | ||
718 | case ANYSEE_HW_507FA: /* 15 */ | ||
719 | /* E30 Combo Plus */ | ||
720 | /* E30 C Plus */ | ||
721 | |||
722 | /* enable tuner on IOE[4] */ | ||
723 | ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 4), 0x10); | ||
724 | if (ret) | ||
725 | goto error; | ||
726 | |||
727 | /* probe TDA18212 */ | ||
728 | tmp = 0; | ||
729 | ret = i2c_transfer(&d->i2c_adap, msg, 2); | ||
730 | if (ret == 2 && tmp == 0xc7) | ||
731 | deb_info("%s: TDA18212 found\n", __func__); | ||
732 | else | ||
733 | tmp = 0; | ||
734 | |||
735 | /* disable tuner on IOE[4] */ | ||
736 | ret = anysee_wr_reg_mask(d, REG_IOE, (0 << 4), 0x10); | ||
737 | if (ret) | ||
738 | goto error; | ||
739 | |||
740 | /* disable DVB-T demod on IOD[0] */ | ||
741 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 0), 0x01); | ||
742 | if (ret) | ||
743 | goto error; | ||
744 | |||
745 | /* enable DVB-C demod on IOD[5] */ | ||
746 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20); | ||
747 | if (ret) | ||
748 | goto error; | ||
749 | |||
750 | /* attach demod */ | ||
751 | if (tmp == 0xc7) { | ||
752 | /* TDA18212 config */ | ||
753 | adap->fe[0] = dvb_attach(tda10023_attach, | ||
754 | &anysee_tda10023_tda18212_config, | ||
755 | &d->i2c_adap, 0x48); | ||
756 | |||
757 | /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ | ||
758 | if (adap->fe[0]) | ||
759 | adap->fe[0]->ops.i2c_gate_ctrl = | ||
760 | anysee_i2c_gate_ctrl; | ||
761 | } else { | ||
762 | /* PLL config */ | ||
763 | adap->fe[0] = dvb_attach(tda10023_attach, | ||
764 | &anysee_tda10023_config, | ||
765 | &d->i2c_adap, 0x48); | ||
766 | } | ||
767 | |||
768 | /* break out if first frontend attaching fails */ | ||
769 | if (!adap->fe[0]) | ||
770 | break; | ||
771 | |||
772 | /* disable DVB-C demod on IOD[5] */ | ||
773 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20); | ||
774 | if (ret) | ||
775 | goto error; | ||
776 | |||
777 | /* enable DVB-T demod on IOD[0] */ | ||
778 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01); | ||
779 | if (ret) | ||
780 | goto error; | ||
781 | |||
782 | /* attach demod */ | ||
783 | if (tmp == 0xc7) { | ||
784 | /* TDA18212 config */ | ||
785 | adap->fe[1] = dvb_attach(zl10353_attach, | ||
786 | &anysee_zl10353_tda18212_config2, | ||
787 | &d->i2c_adap); | ||
788 | |||
789 | /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ | ||
790 | if (adap->fe[1]) | ||
791 | adap->fe[1]->ops.i2c_gate_ctrl = | ||
792 | anysee_i2c_gate_ctrl; | ||
793 | } else { | ||
794 | /* PLL config */ | ||
795 | adap->fe[1] = dvb_attach(zl10353_attach, | ||
796 | &anysee_zl10353_config, | ||
797 | &d->i2c_adap); | ||
798 | } | ||
799 | |||
800 | break; | ||
801 | case ANYSEE_HW_508TC: /* 18 */ | ||
802 | case ANYSEE_HW_508PTC: /* 21 */ | ||
803 | /* E7 TC */ | ||
804 | /* E7 PTC */ | ||
805 | |||
806 | /* disable DVB-T demod on IOD[6] */ | ||
807 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 6), 0x40); | ||
808 | if (ret) | ||
809 | goto error; | ||
810 | |||
811 | /* enable DVB-C demod on IOD[5] */ | ||
812 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20); | ||
813 | if (ret) | ||
814 | goto error; | ||
815 | |||
816 | /* attach demod */ | ||
817 | adap->fe[0] = dvb_attach(tda10023_attach, | ||
818 | &anysee_tda10023_tda18212_config, | ||
819 | &d->i2c_adap, 0x48); | ||
820 | |||
821 | /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ | ||
822 | if (adap->fe[0]) | ||
823 | adap->fe[0]->ops.i2c_gate_ctrl = anysee_i2c_gate_ctrl; | ||
824 | |||
825 | /* break out if first frontend attaching fails */ | ||
826 | if (!adap->fe[0]) | ||
827 | break; | ||
828 | |||
829 | /* disable DVB-C demod on IOD[5] */ | ||
830 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20); | ||
831 | if (ret) | ||
832 | goto error; | ||
833 | |||
834 | /* enable DVB-T demod on IOD[6] */ | ||
835 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 6), 0x40); | ||
836 | if (ret) | ||
837 | goto error; | ||
838 | |||
839 | /* attach demod */ | ||
840 | adap->fe[1] = dvb_attach(zl10353_attach, | ||
841 | &anysee_zl10353_tda18212_config, | ||
842 | &d->i2c_adap); | ||
843 | |||
844 | /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */ | ||
845 | if (adap->fe[1]) | ||
846 | adap->fe[1]->ops.i2c_gate_ctrl = anysee_i2c_gate_ctrl; | ||
847 | |||
848 | state->has_ci = true; | ||
849 | |||
850 | break; | ||
851 | case ANYSEE_HW_508S2: /* 19 */ | ||
852 | case ANYSEE_HW_508PS2: /* 22 */ | ||
853 | /* E7 S2 */ | ||
854 | /* E7 PS2 */ | ||
855 | |||
856 | /* enable DVB-S/S2 demod on IOE[5] */ | ||
857 | ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 5), 0x20); | ||
858 | if (ret) | ||
859 | goto error; | ||
860 | |||
861 | /* attach demod */ | ||
862 | adap->fe[0] = dvb_attach(stv0900_attach, | ||
863 | &anysee_stv0900_config, &d->i2c_adap, 0); | ||
864 | |||
865 | state->has_ci = true; | ||
866 | |||
867 | break; | ||
868 | case ANYSEE_HW_508T2C: /* 20 */ | ||
869 | /* E7 T2C */ | ||
870 | |||
871 | /* enable DVB-T/T2/C demod on IOE[5] */ | ||
872 | ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 5), 0x20); | ||
873 | if (ret) | ||
874 | goto error; | ||
875 | |||
876 | /* attach demod */ | ||
877 | adap->fe[0] = dvb_attach(cxd2820r_attach, | ||
878 | &anysee_cxd2820r_config, &d->i2c_adap); | ||
879 | |||
880 | state->has_ci = true; | ||
881 | |||
882 | break; | ||
883 | } | ||
884 | |||
885 | if (!adap->fe[0]) { | ||
886 | /* we have no frontend :-( */ | ||
887 | ret = -ENODEV; | ||
888 | err("Unsupported Anysee version. " \ | ||
889 | "Please report the <linux-media@vger.kernel.org>."); | ||
890 | } | ||
891 | error: | ||
892 | return ret; | ||
893 | } | ||
894 | |||
895 | static int anysee_tuner_attach(struct dvb_usb_adapter *adap) | ||
896 | { | ||
897 | struct anysee_state *state = adap_to_priv(adap); | ||
898 | struct dvb_usb_device *d = adap_to_d(adap); | ||
899 | struct dvb_frontend *fe; | ||
900 | int ret; | ||
901 | deb_info("%s: adap=%d\n", __func__, adap->id); | ||
902 | |||
903 | switch (state->hw) { | ||
904 | case ANYSEE_HW_507T: /* 2 */ | ||
905 | /* E30 */ | ||
906 | |||
907 | /* attach tuner */ | ||
908 | fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc2 >> 1), NULL, | ||
909 | DVB_PLL_THOMSON_DTT7579); | ||
910 | |||
911 | break; | ||
912 | case ANYSEE_HW_507CD: /* 6 */ | ||
913 | /* E30 Plus */ | ||
914 | |||
915 | /* attach tuner */ | ||
916 | fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc2 >> 1), | ||
917 | &d->i2c_adap, DVB_PLL_THOMSON_DTT7579); | ||
918 | |||
919 | break; | ||
920 | case ANYSEE_HW_507DC: /* 10 */ | ||
921 | /* E30 C Plus */ | ||
922 | |||
923 | /* attach tuner */ | ||
924 | fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc0 >> 1), | ||
925 | &d->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | ||
926 | |||
927 | break; | ||
928 | case ANYSEE_HW_507SI: /* 11 */ | ||
929 | /* E30 S2 Plus */ | ||
930 | |||
931 | /* attach LNB controller */ | ||
932 | fe = dvb_attach(isl6423_attach, adap->fe[0], &d->i2c_adap, | ||
933 | &anysee_isl6423_config); | ||
934 | |||
935 | break; | ||
936 | case ANYSEE_HW_507FA: /* 15 */ | ||
937 | /* E30 Combo Plus */ | ||
938 | /* E30 C Plus */ | ||
939 | |||
940 | /* Try first attach TDA18212 silicon tuner on IOE[4], if that | ||
941 | * fails attach old simple PLL. */ | ||
942 | |||
943 | /* attach tuner */ | ||
944 | fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, | ||
945 | &anysee_tda18212_config); | ||
946 | |||
947 | if (fe && adap->fe[1]) { | ||
948 | /* attach tuner for 2nd FE */ | ||
949 | fe = dvb_attach(tda18212_attach, adap->fe[1], | ||
950 | &d->i2c_adap, &anysee_tda18212_config); | ||
951 | break; | ||
952 | } else if (fe) { | ||
953 | break; | ||
954 | } | ||
955 | |||
956 | /* attach tuner */ | ||
957 | fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc0 >> 1), | ||
958 | &d->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A); | ||
959 | |||
960 | if (fe && adap->fe[1]) { | ||
961 | /* attach tuner for 2nd FE */ | ||
962 | fe = dvb_attach(dvb_pll_attach, adap->fe[0], | ||
963 | (0xc0 >> 1), &d->i2c_adap, | ||
964 | DVB_PLL_SAMSUNG_DTOS403IH102A); | ||
965 | } | ||
966 | |||
967 | break; | ||
968 | case ANYSEE_HW_508TC: /* 18 */ | ||
969 | case ANYSEE_HW_508PTC: /* 21 */ | ||
970 | /* E7 TC */ | ||
971 | /* E7 PTC */ | ||
972 | |||
973 | /* attach tuner */ | ||
974 | fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, | ||
975 | &anysee_tda18212_config); | ||
976 | |||
977 | if (fe) { | ||
978 | /* attach tuner for 2nd FE */ | ||
979 | fe = dvb_attach(tda18212_attach, adap->fe[1], | ||
980 | &d->i2c_adap, &anysee_tda18212_config); | ||
981 | } | ||
982 | |||
983 | break; | ||
984 | case ANYSEE_HW_508S2: /* 19 */ | ||
985 | case ANYSEE_HW_508PS2: /* 22 */ | ||
986 | /* E7 S2 */ | ||
987 | /* E7 PS2 */ | ||
988 | |||
989 | /* attach tuner */ | ||
990 | fe = dvb_attach(stv6110_attach, adap->fe[0], | ||
991 | &anysee_stv6110_config, &d->i2c_adap); | ||
992 | |||
993 | if (fe) { | ||
994 | /* attach LNB controller */ | ||
995 | fe = dvb_attach(isl6423_attach, adap->fe[0], | ||
996 | &d->i2c_adap, &anysee_isl6423_config); | ||
997 | } | ||
998 | |||
999 | break; | ||
1000 | |||
1001 | case ANYSEE_HW_508T2C: /* 20 */ | ||
1002 | /* E7 T2C */ | ||
1003 | |||
1004 | /* attach tuner */ | ||
1005 | fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap, | ||
1006 | &anysee_tda18212_config2); | ||
1007 | |||
1008 | break; | ||
1009 | default: | ||
1010 | fe = NULL; | ||
1011 | } | ||
1012 | |||
1013 | if (fe) | ||
1014 | ret = 0; | ||
1015 | else | ||
1016 | ret = -ENODEV; | ||
1017 | |||
1018 | return ret; | ||
1019 | } | ||
1020 | |||
1021 | static int anysee_rc_query(struct dvb_usb_device *d) | ||
1022 | { | ||
1023 | u8 buf[] = {CMD_GET_IR_CODE}; | ||
1024 | u8 ircode[2]; | ||
1025 | int ret; | ||
1026 | |||
1027 | /* Remote controller is basic NEC using address byte 0x08. | ||
1028 | Anysee device RC query returns only two bytes, status and code, | ||
1029 | address byte is dropped. Also it does not return any value for | ||
1030 | NEC RCs having address byte other than 0x08. Due to that, we | ||
1031 | cannot use that device as standard NEC receiver. | ||
1032 | It could be possible make hack which reads whole code directly | ||
1033 | from device memory... */ | ||
1034 | |||
1035 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), ircode, sizeof(ircode)); | ||
1036 | if (ret) | ||
1037 | return ret; | ||
1038 | |||
1039 | if (ircode[0]) { | ||
1040 | deb_rc("%s: key pressed %02x\n", __func__, ircode[1]); | ||
1041 | rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0); | ||
1042 | } | ||
1043 | |||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | static int anysee_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) | ||
1048 | { | ||
1049 | rc->allowed_protos = RC_TYPE_NEC; | ||
1050 | rc->query = anysee_rc_query; | ||
1051 | rc->interval = 250; /* windows driver uses 500ms */ | ||
1052 | |||
1053 | return 0; | ||
1054 | } | ||
1055 | |||
1056 | static int anysee_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, int slot, | ||
1057 | int addr) | ||
1058 | { | ||
1059 | struct dvb_usb_device *d = ci->data; | ||
1060 | int ret; | ||
1061 | u8 buf[] = {CMD_CI, 0x02, 0x40 | addr >> 8, addr & 0xff, 0x00, 1}; | ||
1062 | u8 val; | ||
1063 | |||
1064 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1); | ||
1065 | if (ret) | ||
1066 | return ret; | ||
1067 | |||
1068 | return val; | ||
1069 | } | ||
1070 | |||
1071 | static int anysee_ci_write_attribute_mem(struct dvb_ca_en50221 *ci, int slot, | ||
1072 | int addr, u8 val) | ||
1073 | { | ||
1074 | struct dvb_usb_device *d = ci->data; | ||
1075 | int ret; | ||
1076 | u8 buf[] = {CMD_CI, 0x03, 0x40 | addr >> 8, addr & 0xff, 0x00, 1, val}; | ||
1077 | |||
1078 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
1079 | if (ret) | ||
1080 | return ret; | ||
1081 | |||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1085 | static int anysee_ci_read_cam_control(struct dvb_ca_en50221 *ci, int slot, | ||
1086 | u8 addr) | ||
1087 | { | ||
1088 | struct dvb_usb_device *d = ci->data; | ||
1089 | int ret; | ||
1090 | u8 buf[] = {CMD_CI, 0x04, 0x40, addr, 0x00, 1}; | ||
1091 | u8 val; | ||
1092 | |||
1093 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1); | ||
1094 | if (ret) | ||
1095 | return ret; | ||
1096 | |||
1097 | return val; | ||
1098 | } | ||
1099 | |||
1100 | static int anysee_ci_write_cam_control(struct dvb_ca_en50221 *ci, int slot, | ||
1101 | u8 addr, u8 val) | ||
1102 | { | ||
1103 | struct dvb_usb_device *d = ci->data; | ||
1104 | int ret; | ||
1105 | u8 buf[] = {CMD_CI, 0x05, 0x40, addr, 0x00, 1, val}; | ||
1106 | |||
1107 | ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0); | ||
1108 | if (ret) | ||
1109 | return ret; | ||
1110 | |||
1111 | return 0; | ||
1112 | } | ||
1113 | |||
1114 | static int anysee_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot) | ||
1115 | { | ||
1116 | struct dvb_usb_device *d = ci->data; | ||
1117 | int ret; | ||
1118 | struct anysee_state *state = d_to_priv(d); | ||
1119 | |||
1120 | state->ci_cam_ready = jiffies + msecs_to_jiffies(1000); | ||
1121 | |||
1122 | ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80); | ||
1123 | if (ret) | ||
1124 | return ret; | ||
1125 | |||
1126 | msleep(300); | ||
1127 | |||
1128 | ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80); | ||
1129 | if (ret) | ||
1130 | return ret; | ||
1131 | |||
1132 | return 0; | ||
1133 | } | ||
1134 | |||
1135 | static int anysee_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot) | ||
1136 | { | ||
1137 | struct dvb_usb_device *d = ci->data; | ||
1138 | int ret; | ||
1139 | |||
1140 | ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80); | ||
1141 | if (ret) | ||
1142 | return ret; | ||
1143 | |||
1144 | msleep(30); | ||
1145 | |||
1146 | ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80); | ||
1147 | if (ret) | ||
1148 | return ret; | ||
1149 | |||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | static int anysee_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot) | ||
1154 | { | ||
1155 | struct dvb_usb_device *d = ci->data; | ||
1156 | int ret; | ||
1157 | |||
1158 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 1), 0x02); | ||
1159 | if (ret) | ||
1160 | return ret; | ||
1161 | |||
1162 | return 0; | ||
1163 | } | ||
1164 | |||
1165 | static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot, | ||
1166 | int open) | ||
1167 | { | ||
1168 | struct dvb_usb_device *d = ci->data; | ||
1169 | struct anysee_state *state = d_to_priv(d); | ||
1170 | int ret; | ||
1171 | u8 tmp; | ||
1172 | |||
1173 | ret = anysee_rd_reg_mask(d, REG_IOC, &tmp, 0x40); | ||
1174 | if (ret) | ||
1175 | return ret; | ||
1176 | |||
1177 | if (tmp == 0) { | ||
1178 | ret = DVB_CA_EN50221_POLL_CAM_PRESENT; | ||
1179 | if (time_after(jiffies, state->ci_cam_ready)) | ||
1180 | ret |= DVB_CA_EN50221_POLL_CAM_READY; | ||
1181 | } | ||
1182 | |||
1183 | return ret; | ||
1184 | } | ||
1185 | |||
1186 | static int anysee_ci_init(struct dvb_usb_device *d) | ||
1187 | { | ||
1188 | struct anysee_state *state = d_to_priv(d); | ||
1189 | int ret; | ||
1190 | |||
1191 | state->ci.owner = THIS_MODULE; | ||
1192 | state->ci.read_attribute_mem = anysee_ci_read_attribute_mem; | ||
1193 | state->ci.write_attribute_mem = anysee_ci_write_attribute_mem; | ||
1194 | state->ci.read_cam_control = anysee_ci_read_cam_control; | ||
1195 | state->ci.write_cam_control = anysee_ci_write_cam_control; | ||
1196 | state->ci.slot_reset = anysee_ci_slot_reset; | ||
1197 | state->ci.slot_shutdown = anysee_ci_slot_shutdown; | ||
1198 | state->ci.slot_ts_enable = anysee_ci_slot_ts_enable; | ||
1199 | state->ci.poll_slot_status = anysee_ci_poll_slot_status; | ||
1200 | state->ci.data = d; | ||
1201 | |||
1202 | ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80); | ||
1203 | if (ret) | ||
1204 | return ret; | ||
1205 | |||
1206 | ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 2)|(0 << 1)|(0 << 0), 0x07); | ||
1207 | if (ret) | ||
1208 | return ret; | ||
1209 | |||
1210 | ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 2)|(1 << 1)|(1 << 0), 0x07); | ||
1211 | if (ret) | ||
1212 | return ret; | ||
1213 | |||
1214 | ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1); | ||
1215 | if (ret) | ||
1216 | return ret; | ||
1217 | |||
1218 | return 0; | ||
1219 | } | ||
1220 | |||
1221 | static void anysee_ci_release(struct dvb_usb_device *d) | ||
1222 | { | ||
1223 | struct anysee_state *state = d_to_priv(d); | ||
1224 | |||
1225 | /* detach CI */ | ||
1226 | if (state->has_ci) | ||
1227 | dvb_ca_en50221_release(&state->ci); | ||
1228 | |||
1229 | return; | ||
1230 | } | ||
1231 | |||
1232 | static int anysee_init(struct dvb_usb_device *d) | ||
1233 | { | ||
1234 | struct anysee_state *state = d_to_priv(d); | ||
1235 | int ret; | ||
1236 | |||
1237 | /* There is one interface with two alternate settings. | ||
1238 | Alternate setting 0 is for bulk transfer. | ||
1239 | Alternate setting 1 is for isochronous transfer. | ||
1240 | We use bulk transfer (alternate setting 0). */ | ||
1241 | ret = usb_set_interface(d->udev, 0, 0); | ||
1242 | if (ret) | ||
1243 | return ret; | ||
1244 | |||
1245 | /* LED light */ | ||
1246 | ret = anysee_led_ctrl(d, 0x01, 0x03); | ||
1247 | if (ret) | ||
1248 | return ret; | ||
1249 | |||
1250 | /* enable IR */ | ||
1251 | ret = anysee_ir_ctrl(d, 1); | ||
1252 | if (ret) | ||
1253 | return ret; | ||
1254 | |||
1255 | /* attach CI */ | ||
1256 | if (state->has_ci) { | ||
1257 | ret = anysee_ci_init(d); | ||
1258 | if (ret) { | ||
1259 | state->has_ci = false; | ||
1260 | return ret; | ||
1261 | } | ||
1262 | } | ||
1263 | |||
1264 | return 0; | ||
1265 | } | ||
1266 | |||
1267 | static void anysee_exit(struct dvb_usb_device *d) | ||
1268 | { | ||
1269 | return anysee_ci_release(d); | ||
1270 | } | ||
1271 | |||
1272 | /* DVB USB Driver stuff */ | ||
1273 | static struct dvb_usb_device_properties anysee_props = { | ||
1274 | .driver_name = KBUILD_MODNAME, | ||
1275 | .owner = THIS_MODULE, | ||
1276 | .adapter_nr = adapter_nr, | ||
1277 | .size_of_priv = sizeof(struct anysee_state), | ||
1278 | |||
1279 | .generic_bulk_ctrl_endpoint = 0x01, | ||
1280 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
1281 | |||
1282 | .i2c_algo = &anysee_i2c_algo, | ||
1283 | .read_config = anysee_read_config, | ||
1284 | .frontend_attach = anysee_frontend_attach, | ||
1285 | .tuner_attach = anysee_tuner_attach, | ||
1286 | .init = anysee_init, | ||
1287 | .get_rc_config = anysee_get_rc_config, | ||
1288 | .frontend_ctrl = anysee_frontend_ctrl, | ||
1289 | .streaming_ctrl = anysee_streaming_ctrl, | ||
1290 | .exit = anysee_exit, | ||
1291 | |||
1292 | .num_adapters = 1, | ||
1293 | .adapter = { | ||
1294 | { | ||
1295 | .stream = DVB_USB_STREAM_BULK(0x82, 8, 16 * 512), | ||
1296 | } | ||
1297 | } | ||
1298 | }; | ||
1299 | |||
1300 | static const struct usb_device_id anysee_id_table[] = { | ||
1301 | { DVB_USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE, | ||
1302 | &anysee_props, "Anysee", RC_MAP_ANYSEE) }, | ||
1303 | { DVB_USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE, | ||
1304 | &anysee_props, "Anysee", RC_MAP_ANYSEE) }, | ||
1305 | { } | ||
1306 | }; | ||
1307 | MODULE_DEVICE_TABLE(usb, anysee_id_table); | ||
1308 | |||
1309 | static struct usb_driver anysee_usb_driver = { | ||
1310 | .name = KBUILD_MODNAME, | ||
1311 | .id_table = anysee_id_table, | ||
1312 | .probe = dvb_usbv2_probe, | ||
1313 | .disconnect = dvb_usbv2_disconnect, | ||
1314 | .suspend = dvb_usbv2_suspend, | ||
1315 | .resume = dvb_usbv2_resume, | ||
1316 | .no_dynamic_id = 1, | ||
1317 | .soft_unbind = 1, | ||
1318 | }; | ||
1319 | |||
1320 | module_usb_driver(anysee_usb_driver); | ||
1321 | |||
1322 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
1323 | MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0"); | ||
1324 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.h b/drivers/media/usb/dvb-usb-v2/anysee.h new file mode 100644 index 000000000000..dc40dcf7c328 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/anysee.h | |||
@@ -0,0 +1,356 @@ | |||
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 | #include "dvb_ca_en50221.h" | ||
40 | |||
41 | #ifdef CONFIG_DVB_USB_DEBUG | ||
42 | #define dprintk(var, level, args...) \ | ||
43 | do { if ((var & level)) printk(args); } while (0) | ||
44 | #define DVB_USB_DEBUG_STATUS | ||
45 | #else | ||
46 | #define dprintk(args...) | ||
47 | #define debug_dump(b, l, func) | ||
48 | #define DVB_USB_DEBUG_STATUS " (debugging is not enabled)" | ||
49 | #endif | ||
50 | |||
51 | #define debug_dump(b, l, func) {\ | ||
52 | int loop_; \ | ||
53 | for (loop_ = 0; loop_ < l; loop_++) \ | ||
54 | func("%02x ", b[loop_]); \ | ||
55 | func("\n");\ | ||
56 | } | ||
57 | |||
58 | #define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args) | ||
59 | #define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args) | ||
60 | #define deb_rc(args...) dprintk(dvb_usb_anysee_debug, 0x04, args) | ||
61 | #define deb_reg(args...) dprintk(dvb_usb_anysee_debug, 0x08, args) | ||
62 | #define deb_i2c(args...) dprintk(dvb_usb_anysee_debug, 0x10, args) | ||
63 | #define deb_fw(args...) dprintk(dvb_usb_anysee_debug, 0x20, args) | ||
64 | |||
65 | #undef err | ||
66 | #define err(format, arg...) printk(KERN_ERR DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
67 | #undef info | ||
68 | #define info(format, arg...) printk(KERN_INFO DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
69 | #undef warn | ||
70 | #define warn(format, arg...) printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
71 | |||
72 | enum cmd { | ||
73 | CMD_I2C_READ = 0x33, | ||
74 | CMD_I2C_WRITE = 0x31, | ||
75 | CMD_REG_READ = 0xb0, | ||
76 | CMD_REG_WRITE = 0xb1, | ||
77 | CMD_STREAMING_CTRL = 0x12, | ||
78 | CMD_LED_AND_IR_CTRL = 0x16, | ||
79 | CMD_GET_IR_CODE = 0x41, | ||
80 | CMD_GET_HW_INFO = 0x19, | ||
81 | CMD_SMARTCARD = 0x34, | ||
82 | CMD_CI = 0x37, | ||
83 | }; | ||
84 | |||
85 | struct anysee_state { | ||
86 | u8 hw; /* PCB ID */ | ||
87 | u8 seq; | ||
88 | u8 fe_id:1; /* frondend ID */ | ||
89 | u8 has_ci:1; | ||
90 | struct dvb_ca_en50221 ci; | ||
91 | unsigned long ci_cam_ready; /* jiffies */ | ||
92 | }; | ||
93 | |||
94 | #define ANYSEE_HW_507T 2 /* E30 */ | ||
95 | #define ANYSEE_HW_507CD 6 /* E30 Plus */ | ||
96 | #define ANYSEE_HW_507DC 10 /* E30 C Plus */ | ||
97 | #define ANYSEE_HW_507SI 11 /* E30 S2 Plus */ | ||
98 | #define ANYSEE_HW_507FA 15 /* E30 Combo Plus / E30 C Plus */ | ||
99 | #define ANYSEE_HW_508TC 18 /* E7 TC */ | ||
100 | #define ANYSEE_HW_508S2 19 /* E7 S2 */ | ||
101 | #define ANYSEE_HW_508T2C 20 /* E7 T2C */ | ||
102 | #define ANYSEE_HW_508PTC 21 /* E7 PTC Plus */ | ||
103 | #define ANYSEE_HW_508PS2 22 /* E7 PS2 Plus */ | ||
104 | |||
105 | #define REG_IOA 0x80 /* Port A (bit addressable) */ | ||
106 | #define REG_IOB 0x90 /* Port B (bit addressable) */ | ||
107 | #define REG_IOC 0xa0 /* Port C (bit addressable) */ | ||
108 | #define REG_IOD 0xb0 /* Port D (bit addressable) */ | ||
109 | #define REG_IOE 0xb1 /* Port E (NOT bit addressable) */ | ||
110 | #define REG_OEA 0xb2 /* Port A Output Enable */ | ||
111 | #define REG_OEB 0xb3 /* Port B Output Enable */ | ||
112 | #define REG_OEC 0xb4 /* Port C Output Enable */ | ||
113 | #define REG_OED 0xb5 /* Port D Output Enable */ | ||
114 | #define REG_OEE 0xb6 /* Port E Output Enable */ | ||
115 | |||
116 | #endif | ||
117 | |||
118 | /*************************************************************************** | ||
119 | * USB API description (reverse engineered) | ||
120 | *************************************************************************** | ||
121 | |||
122 | Transaction flow: | ||
123 | ================= | ||
124 | BULK[00001] >>> REQUEST PACKET 64 bytes | ||
125 | BULK[00081] <<< REPLY PACKET #1 64 bytes (PREVIOUS TRANSACTION REPLY) | ||
126 | BULK[00081] <<< REPLY PACKET #2 64 bytes (CURRENT TRANSACTION REPLY) | ||
127 | |||
128 | General reply packet(s) are always used if not own reply defined. | ||
129 | |||
130 | ============================================================================ | ||
131 | | 00-63 | GENERAL REPLY PACKET #1 (PREVIOUS REPLY) | ||
132 | ============================================================================ | ||
133 | | 00 | reply data (if any) from previous transaction | ||
134 | | | Just same reply packet as returned during previous transaction. | ||
135 | | | Needed only if reply is missed in previous transaction. | ||
136 | | | Just skip normally. | ||
137 | ---------------------------------------------------------------------------- | ||
138 | | 01-59 | don't care | ||
139 | ---------------------------------------------------------------------------- | ||
140 | | 60 | packet sequence number | ||
141 | ---------------------------------------------------------------------------- | ||
142 | | 61-63 | don't care | ||
143 | ---------------------------------------------------------------------------- | ||
144 | |||
145 | ============================================================================ | ||
146 | | 00-63 | GENERAL REPLY PACKET #2 (CURRENT REPLY) | ||
147 | ============================================================================ | ||
148 | | 00 | reply data (if any) | ||
149 | ---------------------------------------------------------------------------- | ||
150 | | 01-59 | don't care | ||
151 | ---------------------------------------------------------------------------- | ||
152 | | 60 | packet sequence number | ||
153 | ---------------------------------------------------------------------------- | ||
154 | | 61-63 | don't care | ||
155 | ---------------------------------------------------------------------------- | ||
156 | |||
157 | ============================================================================ | ||
158 | | 00-63 | I2C WRITE REQUEST PACKET | ||
159 | ============================================================================ | ||
160 | | 00 | 0x31 I2C write command | ||
161 | ---------------------------------------------------------------------------- | ||
162 | | 01 | i2c address | ||
163 | ---------------------------------------------------------------------------- | ||
164 | | 02 | data length | ||
165 | | | 0x02 (for typical I2C reg / val pair) | ||
166 | ---------------------------------------------------------------------------- | ||
167 | | 03 | 0x01 | ||
168 | ---------------------------------------------------------------------------- | ||
169 | | 04- | data | ||
170 | ---------------------------------------------------------------------------- | ||
171 | | -59 | don't care | ||
172 | ---------------------------------------------------------------------------- | ||
173 | | 60 | packet sequence number | ||
174 | ---------------------------------------------------------------------------- | ||
175 | | 61-63 | don't care | ||
176 | ---------------------------------------------------------------------------- | ||
177 | |||
178 | ============================================================================ | ||
179 | | 00-63 | I2C READ REQUEST PACKET | ||
180 | ============================================================================ | ||
181 | | 00 | 0x33 I2C read command | ||
182 | ---------------------------------------------------------------------------- | ||
183 | | 01 | i2c address + 1 | ||
184 | ---------------------------------------------------------------------------- | ||
185 | | 02 | register | ||
186 | ---------------------------------------------------------------------------- | ||
187 | | 03 | 0x00 | ||
188 | ---------------------------------------------------------------------------- | ||
189 | | 04 | 0x00 | ||
190 | ---------------------------------------------------------------------------- | ||
191 | | 05 | data length | ||
192 | ---------------------------------------------------------------------------- | ||
193 | | 06-59 | don't care | ||
194 | ---------------------------------------------------------------------------- | ||
195 | | 60 | packet sequence number | ||
196 | ---------------------------------------------------------------------------- | ||
197 | | 61-63 | don't care | ||
198 | ---------------------------------------------------------------------------- | ||
199 | |||
200 | ============================================================================ | ||
201 | | 00-63 | USB CONTROLLER REGISTER WRITE REQUEST PACKET | ||
202 | ============================================================================ | ||
203 | | 00 | 0xb1 register write command | ||
204 | ---------------------------------------------------------------------------- | ||
205 | | 01-02 | register | ||
206 | ---------------------------------------------------------------------------- | ||
207 | | 03 | 0x01 | ||
208 | ---------------------------------------------------------------------------- | ||
209 | | 04 | value | ||
210 | ---------------------------------------------------------------------------- | ||
211 | | 05-59 | don't care | ||
212 | ---------------------------------------------------------------------------- | ||
213 | | 60 | packet sequence number | ||
214 | ---------------------------------------------------------------------------- | ||
215 | | 61-63 | don't care | ||
216 | ---------------------------------------------------------------------------- | ||
217 | |||
218 | ============================================================================ | ||
219 | | 00-63 | USB CONTROLLER REGISTER READ REQUEST PACKET | ||
220 | ============================================================================ | ||
221 | | 00 | 0xb0 register read command | ||
222 | ---------------------------------------------------------------------------- | ||
223 | | 01-02 | register | ||
224 | ---------------------------------------------------------------------------- | ||
225 | | 03 | 0x01 | ||
226 | ---------------------------------------------------------------------------- | ||
227 | | 04-59 | don't care | ||
228 | ---------------------------------------------------------------------------- | ||
229 | | 60 | packet sequence number | ||
230 | ---------------------------------------------------------------------------- | ||
231 | | 61-63 | don't care | ||
232 | ---------------------------------------------------------------------------- | ||
233 | |||
234 | ============================================================================ | ||
235 | | 00-63 | LED CONTROL REQUEST PACKET | ||
236 | ============================================================================ | ||
237 | | 00 | 0x16 LED and IR control command | ||
238 | ---------------------------------------------------------------------------- | ||
239 | | 01 | 0x01 (LED) | ||
240 | ---------------------------------------------------------------------------- | ||
241 | | 03 | 0x00 blink | ||
242 | | | 0x01 lights continuously | ||
243 | ---------------------------------------------------------------------------- | ||
244 | | 04 | blink interval | ||
245 | | | 0x00 fastest (looks like LED lights continuously) | ||
246 | | | 0xff slowest | ||
247 | ---------------------------------------------------------------------------- | ||
248 | | 05-59 | don't care | ||
249 | ---------------------------------------------------------------------------- | ||
250 | | 60 | packet sequence number | ||
251 | ---------------------------------------------------------------------------- | ||
252 | | 61-63 | don't care | ||
253 | ---------------------------------------------------------------------------- | ||
254 | |||
255 | ============================================================================ | ||
256 | | 00-63 | IR CONTROL REQUEST PACKET | ||
257 | ============================================================================ | ||
258 | | 00 | 0x16 LED and IR control command | ||
259 | ---------------------------------------------------------------------------- | ||
260 | | 01 | 0x02 (IR) | ||
261 | ---------------------------------------------------------------------------- | ||
262 | | 03 | 0x00 IR disabled | ||
263 | | | 0x01 IR enabled | ||
264 | ---------------------------------------------------------------------------- | ||
265 | | 04-59 | don't care | ||
266 | ---------------------------------------------------------------------------- | ||
267 | | 60 | packet sequence number | ||
268 | ---------------------------------------------------------------------------- | ||
269 | | 61-63 | don't care | ||
270 | ---------------------------------------------------------------------------- | ||
271 | |||
272 | ============================================================================ | ||
273 | | 00-63 | STREAMING CONTROL REQUEST PACKET | ||
274 | ============================================================================ | ||
275 | | 00 | 0x12 streaming control command | ||
276 | ---------------------------------------------------------------------------- | ||
277 | | 01 | 0x00 streaming disabled | ||
278 | | | 0x01 streaming enabled | ||
279 | ---------------------------------------------------------------------------- | ||
280 | | 02 | 0x00 | ||
281 | ---------------------------------------------------------------------------- | ||
282 | | 03-59 | don't care | ||
283 | ---------------------------------------------------------------------------- | ||
284 | | 60 | packet sequence number | ||
285 | ---------------------------------------------------------------------------- | ||
286 | | 61-63 | don't care | ||
287 | ---------------------------------------------------------------------------- | ||
288 | |||
289 | ============================================================================ | ||
290 | | 00-63 | REMOTE CONTROL REQUEST PACKET | ||
291 | ============================================================================ | ||
292 | | 00 | 0x41 remote control command | ||
293 | ---------------------------------------------------------------------------- | ||
294 | | 01-59 | don't care | ||
295 | ---------------------------------------------------------------------------- | ||
296 | | 60 | packet sequence number | ||
297 | ---------------------------------------------------------------------------- | ||
298 | | 61-63 | don't care | ||
299 | ---------------------------------------------------------------------------- | ||
300 | |||
301 | ============================================================================ | ||
302 | | 00-63 | REMOTE CONTROL REPLY PACKET | ||
303 | ============================================================================ | ||
304 | | 00 | 0x00 code not received | ||
305 | | | 0x01 code received | ||
306 | ---------------------------------------------------------------------------- | ||
307 | | 01 | remote control code | ||
308 | ---------------------------------------------------------------------------- | ||
309 | | 02-59 | don't care | ||
310 | ---------------------------------------------------------------------------- | ||
311 | | 60 | packet sequence number | ||
312 | ---------------------------------------------------------------------------- | ||
313 | | 61-63 | don't care | ||
314 | ---------------------------------------------------------------------------- | ||
315 | |||
316 | ============================================================================ | ||
317 | | 00-63 | GET HARDWARE INFO REQUEST PACKET | ||
318 | ============================================================================ | ||
319 | | 00 | 0x19 get hardware info command | ||
320 | ---------------------------------------------------------------------------- | ||
321 | | 01-59 | don't care | ||
322 | ---------------------------------------------------------------------------- | ||
323 | | 60 | packet sequence number | ||
324 | ---------------------------------------------------------------------------- | ||
325 | | 61-63 | don't care | ||
326 | ---------------------------------------------------------------------------- | ||
327 | |||
328 | ============================================================================ | ||
329 | | 00-63 | GET HARDWARE INFO REPLY PACKET | ||
330 | ============================================================================ | ||
331 | | 00 | hardware id | ||
332 | ---------------------------------------------------------------------------- | ||
333 | | 01-02 | firmware version | ||
334 | ---------------------------------------------------------------------------- | ||
335 | | 03-59 | don't care | ||
336 | ---------------------------------------------------------------------------- | ||
337 | | 60 | packet sequence number | ||
338 | ---------------------------------------------------------------------------- | ||
339 | | 61-63 | don't care | ||
340 | ---------------------------------------------------------------------------- | ||
341 | |||
342 | ============================================================================ | ||
343 | | 00-63 | SMART CARD READER PACKET | ||
344 | ============================================================================ | ||
345 | | 00 | 0x34 smart card reader command | ||
346 | ---------------------------------------------------------------------------- | ||
347 | | xx | | ||
348 | ---------------------------------------------------------------------------- | ||
349 | | xx-59 | don't care | ||
350 | ---------------------------------------------------------------------------- | ||
351 | | 60 | packet sequence number | ||
352 | ---------------------------------------------------------------------------- | ||
353 | | 61-63 | don't care | ||
354 | ---------------------------------------------------------------------------- | ||
355 | |||
356 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/au6610.c b/drivers/media/usb/dvb-usb-v2/au6610.c new file mode 100644 index 000000000000..05f2a8628142 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/au6610.c | |||
@@ -0,0 +1,206 @@ | |||
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 | |||
21 | #include "au6610.h" | ||
22 | #include "zl10353.h" | ||
23 | #include "qt1010.h" | ||
24 | |||
25 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
26 | |||
27 | static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, | ||
28 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
29 | { | ||
30 | int ret; | ||
31 | u16 index; | ||
32 | u8 *usb_buf; | ||
33 | |||
34 | /* | ||
35 | * allocate enough for all known requests, | ||
36 | * read returns 5 and write 6 bytes | ||
37 | */ | ||
38 | usb_buf = kmalloc(6, GFP_KERNEL); | ||
39 | if (!usb_buf) | ||
40 | return -ENOMEM; | ||
41 | |||
42 | switch (wlen) { | ||
43 | case 1: | ||
44 | index = wbuf[0] << 8; | ||
45 | break; | ||
46 | case 2: | ||
47 | index = wbuf[0] << 8; | ||
48 | index += wbuf[1]; | ||
49 | break; | ||
50 | default: | ||
51 | pr_err("%s: wlen = %d, aborting\n", KBUILD_MODNAME, wlen); | ||
52 | ret = -EINVAL; | ||
53 | goto error; | ||
54 | } | ||
55 | |||
56 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, | ||
57 | USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, | ||
58 | usb_buf, 6, AU6610_USB_TIMEOUT); | ||
59 | if (ret < 0) | ||
60 | goto error; | ||
61 | |||
62 | switch (operation) { | ||
63 | case AU6610_REQ_I2C_READ: | ||
64 | case AU6610_REQ_USB_READ: | ||
65 | /* requested value is always 5th byte in buffer */ | ||
66 | rbuf[0] = usb_buf[4]; | ||
67 | } | ||
68 | error: | ||
69 | kfree(usb_buf); | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | static int au6610_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
74 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
75 | { | ||
76 | u8 request; | ||
77 | u8 wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
78 | |||
79 | if (wo) { | ||
80 | request = AU6610_REQ_I2C_WRITE; | ||
81 | } else { /* rw */ | ||
82 | request = AU6610_REQ_I2C_READ; | ||
83 | } | ||
84 | |||
85 | return au6610_usb_msg(d, request, addr, wbuf, wlen, rbuf, rlen); | ||
86 | } | ||
87 | |||
88 | |||
89 | /* I2C */ | ||
90 | static int au6610_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
91 | int num) | ||
92 | { | ||
93 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
94 | int i; | ||
95 | |||
96 | if (num > 2) | ||
97 | return -EINVAL; | ||
98 | |||
99 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
100 | return -EAGAIN; | ||
101 | |||
102 | for (i = 0; i < num; i++) { | ||
103 | /* write/read request */ | ||
104 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
105 | if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
106 | msg[i].len, msg[i+1].buf, | ||
107 | msg[i+1].len) < 0) | ||
108 | break; | ||
109 | i++; | ||
110 | } else if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
111 | msg[i].len, NULL, 0) < 0) | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | mutex_unlock(&d->i2c_mutex); | ||
116 | return i; | ||
117 | } | ||
118 | |||
119 | |||
120 | static u32 au6610_i2c_func(struct i2c_adapter *adapter) | ||
121 | { | ||
122 | return I2C_FUNC_I2C; | ||
123 | } | ||
124 | |||
125 | static struct i2c_algorithm au6610_i2c_algo = { | ||
126 | .master_xfer = au6610_i2c_xfer, | ||
127 | .functionality = au6610_i2c_func, | ||
128 | }; | ||
129 | |||
130 | /* Callbacks for DVB USB */ | ||
131 | static struct zl10353_config au6610_zl10353_config = { | ||
132 | .demod_address = 0x0f, | ||
133 | .no_tuner = 1, | ||
134 | .parallel_ts = 1, | ||
135 | }; | ||
136 | |||
137 | static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap) | ||
138 | { | ||
139 | adap->fe[0] = dvb_attach(zl10353_attach, &au6610_zl10353_config, | ||
140 | &adap_to_d(adap)->i2c_adap); | ||
141 | if (adap->fe[0] == NULL) | ||
142 | return -ENODEV; | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static struct qt1010_config au6610_qt1010_config = { | ||
148 | .i2c_address = 0x62 | ||
149 | }; | ||
150 | |||
151 | static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap) | ||
152 | { | ||
153 | return dvb_attach(qt1010_attach, adap->fe[0], | ||
154 | &adap_to_d(adap)->i2c_adap, | ||
155 | &au6610_qt1010_config) == NULL ? -ENODEV : 0; | ||
156 | } | ||
157 | |||
158 | static int au6610_init(struct dvb_usb_device *d) | ||
159 | { | ||
160 | /* TODO: this functionality belongs likely to the streaming control */ | ||
161 | /* bInterfaceNumber 0, bAlternateSetting 5 */ | ||
162 | return usb_set_interface(d->udev, 0, 5); | ||
163 | } | ||
164 | |||
165 | static struct dvb_usb_device_properties au6610_props = { | ||
166 | .driver_name = KBUILD_MODNAME, | ||
167 | .owner = THIS_MODULE, | ||
168 | .adapter_nr = adapter_nr, | ||
169 | |||
170 | .i2c_algo = &au6610_i2c_algo, | ||
171 | .frontend_attach = au6610_zl10353_frontend_attach, | ||
172 | .tuner_attach = au6610_qt1010_tuner_attach, | ||
173 | .init = au6610_init, | ||
174 | |||
175 | .num_adapters = 1, | ||
176 | .adapter = { | ||
177 | { | ||
178 | .stream = DVB_USB_STREAM_ISOC(0x82, 5, 40, 942, 1), | ||
179 | }, | ||
180 | }, | ||
181 | }; | ||
182 | |||
183 | static const struct usb_device_id au6610_id_table[] = { | ||
184 | { DVB_USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110, | ||
185 | &au6610_props, "Sigmatek DVB-110", NULL) }, | ||
186 | { } | ||
187 | }; | ||
188 | MODULE_DEVICE_TABLE(usb, au6610_id_table); | ||
189 | |||
190 | static struct usb_driver au6610_driver = { | ||
191 | .name = KBUILD_MODNAME, | ||
192 | .id_table = au6610_id_table, | ||
193 | .probe = dvb_usbv2_probe, | ||
194 | .disconnect = dvb_usbv2_disconnect, | ||
195 | .suspend = dvb_usbv2_suspend, | ||
196 | .resume = dvb_usbv2_resume, | ||
197 | .no_dynamic_id = 1, | ||
198 | .soft_unbind = 1, | ||
199 | }; | ||
200 | |||
201 | module_usb_driver(au6610_driver); | ||
202 | |||
203 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
204 | MODULE_DESCRIPTION("Driver for Alcor Micro AU6610 DVB-T USB2.0"); | ||
205 | MODULE_VERSION("0.1"); | ||
206 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/au6610.h b/drivers/media/usb/dvb-usb-v2/au6610.h new file mode 100644 index 000000000000..ea337bfc00b1 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/au6610.h | |||
@@ -0,0 +1,32 @@ | |||
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 | |||
21 | #ifndef AU6610_H | ||
22 | #define AU6610_H | ||
23 | #include "dvb_usb.h" | ||
24 | |||
25 | #define AU6610_REQ_I2C_WRITE 0x14 | ||
26 | #define AU6610_REQ_I2C_READ 0x13 | ||
27 | #define AU6610_REQ_USB_WRITE 0x16 | ||
28 | #define AU6610_REQ_USB_READ 0x15 | ||
29 | |||
30 | #define AU6610_USB_TIMEOUT 1000 | ||
31 | |||
32 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c new file mode 100644 index 000000000000..54f1221d930d --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/az6007.c | |||
@@ -0,0 +1,919 @@ | |||
1 | /* | ||
2 | * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones | ||
3 | * | ||
4 | * Copyright (c) Henry Wang <Henry.wang@AzureWave.com> | ||
5 | * | ||
6 | * This driver was made publicly available by Terratec, at: | ||
7 | * http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz | ||
8 | * The original driver's license is GPL, as declared with MODULE_LICENSE() | ||
9 | * | ||
10 | * Copyright (c) 2010-2012 Mauro Carvalho Chehab <mchehab@redhat.com> | ||
11 | * Driver modified by in order to work with upstream drxk driver, and | ||
12 | * tons of bugs got fixed, and converted to use dvb-usb-v2. | ||
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 under version 2 of the License. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | */ | ||
23 | |||
24 | #include "drxk.h" | ||
25 | #include "mt2063.h" | ||
26 | #include "dvb_ca_en50221.h" | ||
27 | #include "dvb_usb.h" | ||
28 | #include "cypress_firmware.h" | ||
29 | |||
30 | #define AZ6007_FIRMWARE "dvb-usb-terratec-h7-az6007.fw" | ||
31 | |||
32 | static int az6007_xfer_debug; | ||
33 | module_param_named(xfer_debug, az6007_xfer_debug, int, 0644); | ||
34 | MODULE_PARM_DESC(xfer_debug, "Enable xfer debug"); | ||
35 | |||
36 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
37 | |||
38 | /* Known requests (Cypress FX2 firmware + az6007 "private" ones*/ | ||
39 | |||
40 | #define FX2_OED 0xb5 | ||
41 | #define AZ6007_READ_DATA 0xb7 | ||
42 | #define AZ6007_I2C_RD 0xb9 | ||
43 | #define AZ6007_POWER 0xbc | ||
44 | #define AZ6007_I2C_WR 0xbd | ||
45 | #define FX2_SCON1 0xc0 | ||
46 | #define AZ6007_TS_THROUGH 0xc7 | ||
47 | #define AZ6007_READ_IR 0xb4 | ||
48 | |||
49 | struct az6007_device_state { | ||
50 | struct mutex mutex; | ||
51 | struct mutex ca_mutex; | ||
52 | struct dvb_ca_en50221 ca; | ||
53 | unsigned warm:1; | ||
54 | int (*gate_ctrl) (struct dvb_frontend *, int); | ||
55 | unsigned char data[4096]; | ||
56 | }; | ||
57 | |||
58 | static struct drxk_config terratec_h7_drxk = { | ||
59 | .adr = 0x29, | ||
60 | .parallel_ts = true, | ||
61 | .dynamic_clk = true, | ||
62 | .single_master = true, | ||
63 | .enable_merr_cfg = true, | ||
64 | .no_i2c_bridge = false, | ||
65 | .chunk_size = 64, | ||
66 | .mpeg_out_clk_strength = 0x02, | ||
67 | .qam_demod_parameter_count = 2, | ||
68 | .microcode_name = "dvb-usb-terratec-h7-drxk.fw", | ||
69 | }; | ||
70 | |||
71 | static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) | ||
72 | { | ||
73 | struct az6007_device_state *st = fe_to_priv(fe); | ||
74 | struct dvb_usb_adapter *adap = fe->sec_priv; | ||
75 | int status = 0; | ||
76 | |||
77 | pr_debug("%s: %s\n", __func__, enable ? "enable" : "disable"); | ||
78 | |||
79 | if (!adap || !st) | ||
80 | return -EINVAL; | ||
81 | |||
82 | if (enable) | ||
83 | status = st->gate_ctrl(fe, 1); | ||
84 | else | ||
85 | status = st->gate_ctrl(fe, 0); | ||
86 | |||
87 | return status; | ||
88 | } | ||
89 | |||
90 | static struct mt2063_config az6007_mt2063_config = { | ||
91 | .tuner_address = 0x60, | ||
92 | .refclock = 36125000, | ||
93 | }; | ||
94 | |||
95 | static int __az6007_read(struct usb_device *udev, u8 req, u16 value, | ||
96 | u16 index, u8 *b, int blen) | ||
97 | { | ||
98 | int ret; | ||
99 | |||
100 | ret = usb_control_msg(udev, | ||
101 | usb_rcvctrlpipe(udev, 0), | ||
102 | req, | ||
103 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
104 | value, index, b, blen, 5000); | ||
105 | if (ret < 0) { | ||
106 | pr_warn("usb read operation failed. (%d)\n", ret); | ||
107 | return -EIO; | ||
108 | } | ||
109 | |||
110 | if (az6007_xfer_debug) { | ||
111 | printk(KERN_DEBUG "az6007: IN req: %02x, value: %04x, index: %04x\n", | ||
112 | req, value, index); | ||
113 | print_hex_dump_bytes("az6007: payload: ", | ||
114 | DUMP_PREFIX_NONE, b, blen); | ||
115 | } | ||
116 | |||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | static int az6007_read(struct dvb_usb_device *d, u8 req, u16 value, | ||
121 | u16 index, u8 *b, int blen) | ||
122 | { | ||
123 | struct az6007_device_state *st = d->priv; | ||
124 | int ret; | ||
125 | |||
126 | if (mutex_lock_interruptible(&st->mutex) < 0) | ||
127 | return -EAGAIN; | ||
128 | |||
129 | ret = __az6007_read(d->udev, req, value, index, b, blen); | ||
130 | |||
131 | mutex_unlock(&st->mutex); | ||
132 | |||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | static int __az6007_write(struct usb_device *udev, u8 req, u16 value, | ||
137 | u16 index, u8 *b, int blen) | ||
138 | { | ||
139 | int ret; | ||
140 | |||
141 | if (az6007_xfer_debug) { | ||
142 | printk(KERN_DEBUG "az6007: OUT req: %02x, value: %04x, index: %04x\n", | ||
143 | req, value, index); | ||
144 | print_hex_dump_bytes("az6007: payload: ", | ||
145 | DUMP_PREFIX_NONE, b, blen); | ||
146 | } | ||
147 | |||
148 | if (blen > 64) { | ||
149 | pr_err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n", | ||
150 | blen); | ||
151 | return -EOPNOTSUPP; | ||
152 | } | ||
153 | |||
154 | ret = usb_control_msg(udev, | ||
155 | usb_sndctrlpipe(udev, 0), | ||
156 | req, | ||
157 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
158 | value, index, b, blen, 5000); | ||
159 | if (ret != blen) { | ||
160 | pr_err("usb write operation failed. (%d)\n", ret); | ||
161 | return -EIO; | ||
162 | } | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value, | ||
168 | u16 index, u8 *b, int blen) | ||
169 | { | ||
170 | struct az6007_device_state *st = d->priv; | ||
171 | int ret; | ||
172 | |||
173 | if (mutex_lock_interruptible(&st->mutex) < 0) | ||
174 | return -EAGAIN; | ||
175 | |||
176 | ret = __az6007_write(d->udev, req, value, index, b, blen); | ||
177 | |||
178 | mutex_unlock(&st->mutex); | ||
179 | |||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | static int az6007_streaming_ctrl(struct dvb_frontend *fe, int onoff) | ||
184 | { | ||
185 | struct dvb_usb_device *d = fe_to_d(fe); | ||
186 | |||
187 | pr_debug("%s: %s\n", __func__, onoff ? "enable" : "disable"); | ||
188 | |||
189 | return az6007_write(d, 0xbc, onoff, 0, NULL, 0); | ||
190 | } | ||
191 | |||
192 | /* remote control stuff (does not work with my box) */ | ||
193 | static int az6007_rc_query(struct dvb_usb_device *d) | ||
194 | { | ||
195 | struct az6007_device_state *st = d_to_priv(d); | ||
196 | unsigned code = 0; | ||
197 | |||
198 | az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); | ||
199 | |||
200 | if (st->data[1] == 0x44) | ||
201 | return 0; | ||
202 | |||
203 | if ((st->data[1] ^ st->data[2]) == 0xff) | ||
204 | code = st->data[1]; | ||
205 | else | ||
206 | code = st->data[1] << 8 | st->data[2]; | ||
207 | |||
208 | if ((st->data[3] ^ st->data[4]) == 0xff) | ||
209 | code = code << 8 | st->data[3]; | ||
210 | else | ||
211 | code = code << 16 | st->data[3] << 8 | st->data[4]; | ||
212 | |||
213 | rc_keydown(d->rc_dev, code, st->data[5]); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, | ||
219 | int slot, | ||
220 | int address) | ||
221 | { | ||
222 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
223 | struct az6007_device_state *state = d_to_priv(d); | ||
224 | |||
225 | int ret; | ||
226 | u8 req; | ||
227 | u16 value; | ||
228 | u16 index; | ||
229 | int blen; | ||
230 | u8 *b; | ||
231 | |||
232 | if (slot != 0) | ||
233 | return -EINVAL; | ||
234 | |||
235 | b = kmalloc(12, GFP_KERNEL); | ||
236 | if (!b) | ||
237 | return -ENOMEM; | ||
238 | |||
239 | mutex_lock(&state->ca_mutex); | ||
240 | |||
241 | req = 0xC1; | ||
242 | value = address; | ||
243 | index = 0; | ||
244 | blen = 1; | ||
245 | |||
246 | ret = az6007_read(d, req, value, index, b, blen); | ||
247 | if (ret < 0) { | ||
248 | pr_warn("usb in operation failed. (%d)\n", ret); | ||
249 | ret = -EINVAL; | ||
250 | } else { | ||
251 | ret = b[0]; | ||
252 | } | ||
253 | |||
254 | mutex_unlock(&state->ca_mutex); | ||
255 | kfree(b); | ||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, | ||
260 | int slot, | ||
261 | int address, | ||
262 | u8 value) | ||
263 | { | ||
264 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
265 | struct az6007_device_state *state = d_to_priv(d); | ||
266 | |||
267 | int ret; | ||
268 | u8 req; | ||
269 | u16 value1; | ||
270 | u16 index; | ||
271 | int blen; | ||
272 | |||
273 | pr_debug("%s(), slot %d\n", __func__, slot); | ||
274 | if (slot != 0) | ||
275 | return -EINVAL; | ||
276 | |||
277 | mutex_lock(&state->ca_mutex); | ||
278 | req = 0xC2; | ||
279 | value1 = address; | ||
280 | index = value; | ||
281 | blen = 0; | ||
282 | |||
283 | ret = az6007_write(d, req, value1, index, NULL, blen); | ||
284 | if (ret != 0) | ||
285 | pr_warn("usb out operation failed. (%d)\n", ret); | ||
286 | |||
287 | mutex_unlock(&state->ca_mutex); | ||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca, | ||
292 | int slot, | ||
293 | u8 address) | ||
294 | { | ||
295 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
296 | struct az6007_device_state *state = d_to_priv(d); | ||
297 | |||
298 | int ret; | ||
299 | u8 req; | ||
300 | u16 value; | ||
301 | u16 index; | ||
302 | int blen; | ||
303 | u8 *b; | ||
304 | |||
305 | if (slot != 0) | ||
306 | return -EINVAL; | ||
307 | |||
308 | b = kmalloc(12, GFP_KERNEL); | ||
309 | if (!b) | ||
310 | return -ENOMEM; | ||
311 | |||
312 | mutex_lock(&state->ca_mutex); | ||
313 | |||
314 | req = 0xC3; | ||
315 | value = address; | ||
316 | index = 0; | ||
317 | blen = 2; | ||
318 | |||
319 | ret = az6007_read(d, req, value, index, b, blen); | ||
320 | if (ret < 0) { | ||
321 | pr_warn("usb in operation failed. (%d)\n", ret); | ||
322 | ret = -EINVAL; | ||
323 | } else { | ||
324 | if (b[0] == 0) | ||
325 | pr_warn("Read CI IO error\n"); | ||
326 | |||
327 | ret = b[1]; | ||
328 | pr_debug("read cam data = %x from 0x%x\n", b[1], value); | ||
329 | } | ||
330 | |||
331 | mutex_unlock(&state->ca_mutex); | ||
332 | kfree(b); | ||
333 | return ret; | ||
334 | } | ||
335 | |||
336 | static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca, | ||
337 | int slot, | ||
338 | u8 address, | ||
339 | u8 value) | ||
340 | { | ||
341 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
342 | struct az6007_device_state *state = d_to_priv(d); | ||
343 | |||
344 | int ret; | ||
345 | u8 req; | ||
346 | u16 value1; | ||
347 | u16 index; | ||
348 | int blen; | ||
349 | |||
350 | if (slot != 0) | ||
351 | return -EINVAL; | ||
352 | |||
353 | mutex_lock(&state->ca_mutex); | ||
354 | req = 0xC4; | ||
355 | value1 = address; | ||
356 | index = value; | ||
357 | blen = 0; | ||
358 | |||
359 | ret = az6007_write(d, req, value1, index, NULL, blen); | ||
360 | if (ret != 0) { | ||
361 | pr_warn("usb out operation failed. (%d)\n", ret); | ||
362 | goto failed; | ||
363 | } | ||
364 | |||
365 | failed: | ||
366 | mutex_unlock(&state->ca_mutex); | ||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) | ||
371 | { | ||
372 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
373 | |||
374 | int ret; | ||
375 | u8 req; | ||
376 | u16 value; | ||
377 | u16 index; | ||
378 | int blen; | ||
379 | u8 *b; | ||
380 | |||
381 | b = kmalloc(12, GFP_KERNEL); | ||
382 | if (!b) | ||
383 | return -ENOMEM; | ||
384 | |||
385 | req = 0xC8; | ||
386 | value = 0; | ||
387 | index = 0; | ||
388 | blen = 1; | ||
389 | |||
390 | ret = az6007_read(d, req, value, index, b, blen); | ||
391 | if (ret < 0) { | ||
392 | pr_warn("usb in operation failed. (%d)\n", ret); | ||
393 | ret = -EIO; | ||
394 | } else{ | ||
395 | ret = b[0]; | ||
396 | } | ||
397 | kfree(b); | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) | ||
402 | { | ||
403 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
404 | struct az6007_device_state *state = d_to_priv(d); | ||
405 | |||
406 | int ret, i; | ||
407 | u8 req; | ||
408 | u16 value; | ||
409 | u16 index; | ||
410 | int blen; | ||
411 | |||
412 | mutex_lock(&state->ca_mutex); | ||
413 | |||
414 | req = 0xC6; | ||
415 | value = 1; | ||
416 | index = 0; | ||
417 | blen = 0; | ||
418 | |||
419 | ret = az6007_write(d, req, value, index, NULL, blen); | ||
420 | if (ret != 0) { | ||
421 | pr_warn("usb out operation failed. (%d)\n", ret); | ||
422 | goto failed; | ||
423 | } | ||
424 | |||
425 | msleep(500); | ||
426 | req = 0xC6; | ||
427 | value = 0; | ||
428 | index = 0; | ||
429 | blen = 0; | ||
430 | |||
431 | ret = az6007_write(d, req, value, index, NULL, blen); | ||
432 | if (ret != 0) { | ||
433 | pr_warn("usb out operation failed. (%d)\n", ret); | ||
434 | goto failed; | ||
435 | } | ||
436 | |||
437 | for (i = 0; i < 15; i++) { | ||
438 | msleep(100); | ||
439 | |||
440 | if (CI_CamReady(ca, slot)) { | ||
441 | pr_debug("CAM Ready\n"); | ||
442 | break; | ||
443 | } | ||
444 | } | ||
445 | msleep(5000); | ||
446 | |||
447 | failed: | ||
448 | mutex_unlock(&state->ca_mutex); | ||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) | ||
453 | { | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) | ||
458 | { | ||
459 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
460 | struct az6007_device_state *state = d_to_priv(d); | ||
461 | |||
462 | int ret; | ||
463 | u8 req; | ||
464 | u16 value; | ||
465 | u16 index; | ||
466 | int blen; | ||
467 | |||
468 | pr_debug("%s()\n", __func__); | ||
469 | mutex_lock(&state->ca_mutex); | ||
470 | req = 0xC7; | ||
471 | value = 1; | ||
472 | index = 0; | ||
473 | blen = 0; | ||
474 | |||
475 | ret = az6007_write(d, req, value, index, NULL, blen); | ||
476 | if (ret != 0) { | ||
477 | pr_warn("usb out operation failed. (%d)\n", ret); | ||
478 | goto failed; | ||
479 | } | ||
480 | |||
481 | failed: | ||
482 | mutex_unlock(&state->ca_mutex); | ||
483 | return ret; | ||
484 | } | ||
485 | |||
486 | static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) | ||
487 | { | ||
488 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
489 | struct az6007_device_state *state = d_to_priv(d); | ||
490 | int ret; | ||
491 | u8 req; | ||
492 | u16 value; | ||
493 | u16 index; | ||
494 | int blen; | ||
495 | u8 *b; | ||
496 | |||
497 | b = kmalloc(12, GFP_KERNEL); | ||
498 | if (!b) | ||
499 | return -ENOMEM; | ||
500 | mutex_lock(&state->ca_mutex); | ||
501 | |||
502 | req = 0xC5; | ||
503 | value = 0; | ||
504 | index = 0; | ||
505 | blen = 1; | ||
506 | |||
507 | ret = az6007_read(d, req, value, index, b, blen); | ||
508 | if (ret < 0) { | ||
509 | pr_warn("usb in operation failed. (%d)\n", ret); | ||
510 | ret = -EIO; | ||
511 | } else | ||
512 | ret = 0; | ||
513 | |||
514 | if (!ret && b[0] == 1) { | ||
515 | ret = DVB_CA_EN50221_POLL_CAM_PRESENT | | ||
516 | DVB_CA_EN50221_POLL_CAM_READY; | ||
517 | } | ||
518 | |||
519 | mutex_unlock(&state->ca_mutex); | ||
520 | kfree(b); | ||
521 | return ret; | ||
522 | } | ||
523 | |||
524 | |||
525 | static void az6007_ci_uninit(struct dvb_usb_device *d) | ||
526 | { | ||
527 | struct az6007_device_state *state; | ||
528 | |||
529 | pr_debug("%s()\n", __func__); | ||
530 | |||
531 | if (NULL == d) | ||
532 | return; | ||
533 | |||
534 | state = d_to_priv(d); | ||
535 | if (NULL == state) | ||
536 | return; | ||
537 | |||
538 | if (NULL == state->ca.data) | ||
539 | return; | ||
540 | |||
541 | dvb_ca_en50221_release(&state->ca); | ||
542 | |||
543 | memset(&state->ca, 0, sizeof(state->ca)); | ||
544 | } | ||
545 | |||
546 | |||
547 | static int az6007_ci_init(struct dvb_usb_adapter *adap) | ||
548 | { | ||
549 | struct dvb_usb_device *d = adap_to_d(adap); | ||
550 | struct az6007_device_state *state = adap_to_priv(adap); | ||
551 | int ret; | ||
552 | |||
553 | pr_debug("%s()\n", __func__); | ||
554 | |||
555 | mutex_init(&state->ca_mutex); | ||
556 | state->ca.owner = THIS_MODULE; | ||
557 | state->ca.read_attribute_mem = az6007_ci_read_attribute_mem; | ||
558 | state->ca.write_attribute_mem = az6007_ci_write_attribute_mem; | ||
559 | state->ca.read_cam_control = az6007_ci_read_cam_control; | ||
560 | state->ca.write_cam_control = az6007_ci_write_cam_control; | ||
561 | state->ca.slot_reset = az6007_ci_slot_reset; | ||
562 | state->ca.slot_shutdown = az6007_ci_slot_shutdown; | ||
563 | state->ca.slot_ts_enable = az6007_ci_slot_ts_enable; | ||
564 | state->ca.poll_slot_status = az6007_ci_poll_slot_status; | ||
565 | state->ca.data = d; | ||
566 | |||
567 | ret = dvb_ca_en50221_init(&adap->dvb_adap, | ||
568 | &state->ca, | ||
569 | 0, /* flags */ | ||
570 | 1);/* n_slots */ | ||
571 | if (ret != 0) { | ||
572 | pr_err("Cannot initialize CI: Error %d.\n", ret); | ||
573 | memset(&state->ca, 0, sizeof(state->ca)); | ||
574 | return ret; | ||
575 | } | ||
576 | |||
577 | pr_debug("CI initialized.\n"); | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static int az6007_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6]) | ||
583 | { | ||
584 | struct dvb_usb_device *d = adap_to_d(adap); | ||
585 | struct az6007_device_state *st = adap_to_priv(adap); | ||
586 | int ret; | ||
587 | |||
588 | ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6); | ||
589 | memcpy(mac, st->data, 6); | ||
590 | |||
591 | if (ret > 0) | ||
592 | pr_debug("%s: mac is %pM\n", __func__, mac); | ||
593 | |||
594 | return ret; | ||
595 | } | ||
596 | |||
597 | static int az6007_frontend_attach(struct dvb_usb_adapter *adap) | ||
598 | { | ||
599 | struct az6007_device_state *st = adap_to_priv(adap); | ||
600 | struct dvb_usb_device *d = adap_to_d(adap); | ||
601 | |||
602 | pr_debug("attaching demod drxk\n"); | ||
603 | |||
604 | adap->fe[0] = dvb_attach(drxk_attach, &terratec_h7_drxk, | ||
605 | &d->i2c_adap); | ||
606 | if (!adap->fe[0]) | ||
607 | return -EINVAL; | ||
608 | |||
609 | adap->fe[0]->sec_priv = adap; | ||
610 | st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl; | ||
611 | adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; | ||
612 | |||
613 | az6007_ci_init(adap); | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int az6007_tuner_attach(struct dvb_usb_adapter *adap) | ||
619 | { | ||
620 | struct dvb_usb_device *d = adap_to_d(adap); | ||
621 | |||
622 | pr_debug("attaching tuner mt2063\n"); | ||
623 | |||
624 | /* Attach mt2063 to DVB-C frontend */ | ||
625 | if (adap->fe[0]->ops.i2c_gate_ctrl) | ||
626 | adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 1); | ||
627 | if (!dvb_attach(mt2063_attach, adap->fe[0], | ||
628 | &az6007_mt2063_config, | ||
629 | &d->i2c_adap)) | ||
630 | return -EINVAL; | ||
631 | |||
632 | if (adap->fe[0]->ops.i2c_gate_ctrl) | ||
633 | adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 0); | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
639 | { | ||
640 | struct az6007_device_state *state = d_to_priv(d); | ||
641 | int ret; | ||
642 | |||
643 | pr_debug("%s()\n", __func__); | ||
644 | |||
645 | if (!state->warm) { | ||
646 | mutex_init(&state->mutex); | ||
647 | |||
648 | ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0); | ||
649 | if (ret < 0) | ||
650 | return ret; | ||
651 | msleep(60); | ||
652 | ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); | ||
653 | if (ret < 0) | ||
654 | return ret; | ||
655 | msleep(100); | ||
656 | ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0); | ||
657 | if (ret < 0) | ||
658 | return ret; | ||
659 | msleep(20); | ||
660 | ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0); | ||
661 | if (ret < 0) | ||
662 | return ret; | ||
663 | |||
664 | msleep(400); | ||
665 | ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0); | ||
666 | if (ret < 0) | ||
667 | return ret; | ||
668 | msleep(150); | ||
669 | ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0); | ||
670 | if (ret < 0) | ||
671 | return ret; | ||
672 | msleep(430); | ||
673 | ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); | ||
674 | if (ret < 0) | ||
675 | return ret; | ||
676 | |||
677 | state->warm = true; | ||
678 | |||
679 | return 0; | ||
680 | } | ||
681 | |||
682 | if (!onoff) | ||
683 | return 0; | ||
684 | |||
685 | az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0); | ||
686 | az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0); | ||
687 | |||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | /* I2C */ | ||
692 | static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | ||
693 | int num) | ||
694 | { | ||
695 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
696 | struct az6007_device_state *st = d_to_priv(d); | ||
697 | int i, j, len; | ||
698 | int ret = 0; | ||
699 | u16 index; | ||
700 | u16 value; | ||
701 | int length; | ||
702 | u8 req, addr; | ||
703 | |||
704 | if (mutex_lock_interruptible(&st->mutex) < 0) | ||
705 | return -EAGAIN; | ||
706 | |||
707 | for (i = 0; i < num; i++) { | ||
708 | addr = msgs[i].addr << 1; | ||
709 | if (((i + 1) < num) | ||
710 | && (msgs[i].len == 1) | ||
711 | && ((msgs[i].flags & I2C_M_RD) != I2C_M_RD) | ||
712 | && (msgs[i + 1].flags & I2C_M_RD) | ||
713 | && (msgs[i].addr == msgs[i + 1].addr)) { | ||
714 | /* | ||
715 | * A write + read xfer for the same address, where | ||
716 | * the first xfer has just 1 byte length. | ||
717 | * Need to join both into one operation | ||
718 | */ | ||
719 | if (az6007_xfer_debug) | ||
720 | printk(KERN_DEBUG "az6007: I2C W/R addr=0x%x len=%d/%d\n", | ||
721 | addr, msgs[i].len, msgs[i + 1].len); | ||
722 | req = AZ6007_I2C_RD; | ||
723 | index = msgs[i].buf[0]; | ||
724 | value = addr | (1 << 8); | ||
725 | length = 6 + msgs[i + 1].len; | ||
726 | len = msgs[i + 1].len; | ||
727 | ret = __az6007_read(d->udev, req, value, index, | ||
728 | st->data, length); | ||
729 | if (ret >= len) { | ||
730 | for (j = 0; j < len; j++) | ||
731 | msgs[i + 1].buf[j] = st->data[j + 5]; | ||
732 | } else | ||
733 | ret = -EIO; | ||
734 | i++; | ||
735 | } else if (!(msgs[i].flags & I2C_M_RD)) { | ||
736 | /* write bytes */ | ||
737 | if (az6007_xfer_debug) | ||
738 | printk(KERN_DEBUG "az6007: I2C W addr=0x%x len=%d\n", | ||
739 | addr, msgs[i].len); | ||
740 | req = AZ6007_I2C_WR; | ||
741 | index = msgs[i].buf[0]; | ||
742 | value = addr | (1 << 8); | ||
743 | length = msgs[i].len - 1; | ||
744 | len = msgs[i].len - 1; | ||
745 | for (j = 0; j < len; j++) | ||
746 | st->data[j] = msgs[i].buf[j + 1]; | ||
747 | ret = __az6007_write(d->udev, req, value, index, | ||
748 | st->data, length); | ||
749 | } else { | ||
750 | /* read bytes */ | ||
751 | if (az6007_xfer_debug) | ||
752 | printk(KERN_DEBUG "az6007: I2C R addr=0x%x len=%d\n", | ||
753 | addr, msgs[i].len); | ||
754 | req = AZ6007_I2C_RD; | ||
755 | index = msgs[i].buf[0]; | ||
756 | value = addr; | ||
757 | length = msgs[i].len + 6; | ||
758 | len = msgs[i].len; | ||
759 | ret = __az6007_read(d->udev, req, value, index, | ||
760 | st->data, length); | ||
761 | for (j = 0; j < len; j++) | ||
762 | msgs[i].buf[j] = st->data[j + 5]; | ||
763 | } | ||
764 | if (ret < 0) | ||
765 | goto err; | ||
766 | } | ||
767 | err: | ||
768 | mutex_unlock(&st->mutex); | ||
769 | |||
770 | if (ret < 0) { | ||
771 | pr_info("%s ERROR: %i\n", __func__, ret); | ||
772 | return ret; | ||
773 | } | ||
774 | return num; | ||
775 | } | ||
776 | |||
777 | static u32 az6007_i2c_func(struct i2c_adapter *adapter) | ||
778 | { | ||
779 | return I2C_FUNC_I2C; | ||
780 | } | ||
781 | |||
782 | static struct i2c_algorithm az6007_i2c_algo = { | ||
783 | .master_xfer = az6007_i2c_xfer, | ||
784 | .functionality = az6007_i2c_func, | ||
785 | }; | ||
786 | |||
787 | static int az6007_identify_state(struct dvb_usb_device *d, const char **name) | ||
788 | { | ||
789 | int ret; | ||
790 | u8 *mac; | ||
791 | |||
792 | pr_debug("Identifying az6007 state\n"); | ||
793 | |||
794 | mac = kmalloc(6, GFP_ATOMIC); | ||
795 | if (!mac) | ||
796 | return -ENOMEM; | ||
797 | |||
798 | /* Try to read the mac address */ | ||
799 | ret = __az6007_read(d->udev, AZ6007_READ_DATA, 6, 0, mac, 6); | ||
800 | if (ret == 6) | ||
801 | ret = WARM; | ||
802 | else | ||
803 | ret = COLD; | ||
804 | |||
805 | kfree(mac); | ||
806 | |||
807 | if (ret == COLD) { | ||
808 | __az6007_write(d->udev, 0x09, 1, 0, NULL, 0); | ||
809 | __az6007_write(d->udev, 0x00, 0, 0, NULL, 0); | ||
810 | __az6007_write(d->udev, 0x00, 0, 0, NULL, 0); | ||
811 | } | ||
812 | |||
813 | pr_debug("Device is on %s state\n", | ||
814 | ret == WARM ? "warm" : "cold"); | ||
815 | return ret; | ||
816 | } | ||
817 | |||
818 | static void az6007_usb_disconnect(struct usb_interface *intf) | ||
819 | { | ||
820 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
821 | az6007_ci_uninit(d); | ||
822 | dvb_usbv2_disconnect(intf); | ||
823 | } | ||
824 | |||
825 | static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) | ||
826 | { | ||
827 | pr_debug("Getting az6007 Remote Control properties\n"); | ||
828 | |||
829 | rc->allowed_protos = RC_TYPE_NEC; | ||
830 | rc->query = az6007_rc_query; | ||
831 | rc->interval = 400; | ||
832 | |||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | static int az6007_download_firmware(struct dvb_usb_device *d, | ||
837 | const struct firmware *fw) | ||
838 | { | ||
839 | pr_debug("Loading az6007 firmware\n"); | ||
840 | |||
841 | return usbv2_cypress_load_firmware(d->udev, fw, CYPRESS_FX2); | ||
842 | } | ||
843 | |||
844 | /* DVB USB Driver stuff */ | ||
845 | static struct dvb_usb_device_properties az6007_props = { | ||
846 | .driver_name = KBUILD_MODNAME, | ||
847 | .owner = THIS_MODULE, | ||
848 | .firmware = AZ6007_FIRMWARE, | ||
849 | |||
850 | .adapter_nr = adapter_nr, | ||
851 | .size_of_priv = sizeof(struct az6007_device_state), | ||
852 | .i2c_algo = &az6007_i2c_algo, | ||
853 | .tuner_attach = az6007_tuner_attach, | ||
854 | .frontend_attach = az6007_frontend_attach, | ||
855 | .streaming_ctrl = az6007_streaming_ctrl, | ||
856 | .get_rc_config = az6007_get_rc_config, | ||
857 | .read_mac_address = az6007_read_mac_addr, | ||
858 | .download_firmware = az6007_download_firmware, | ||
859 | .identify_state = az6007_identify_state, | ||
860 | .power_ctrl = az6007_power_ctrl, | ||
861 | .num_adapters = 1, | ||
862 | .adapter = { | ||
863 | { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), } | ||
864 | } | ||
865 | }; | ||
866 | |||
867 | static struct usb_device_id az6007_usb_table[] = { | ||
868 | {DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007, | ||
869 | &az6007_props, "Azurewave 6007", RC_MAP_EMPTY)}, | ||
870 | {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7, | ||
871 | &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, | ||
872 | {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2, | ||
873 | &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, | ||
874 | {0}, | ||
875 | }; | ||
876 | |||
877 | MODULE_DEVICE_TABLE(usb, az6007_usb_table); | ||
878 | |||
879 | static int az6007_suspend(struct usb_interface *intf, pm_message_t msg) | ||
880 | { | ||
881 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
882 | |||
883 | az6007_ci_uninit(d); | ||
884 | return dvb_usbv2_suspend(intf, msg); | ||
885 | } | ||
886 | |||
887 | static int az6007_resume(struct usb_interface *intf) | ||
888 | { | ||
889 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
890 | struct dvb_usb_adapter *adap = &d->adapter[0]; | ||
891 | |||
892 | az6007_ci_init(adap); | ||
893 | return dvb_usbv2_resume(intf); | ||
894 | } | ||
895 | |||
896 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
897 | static struct usb_driver az6007_usb_driver = { | ||
898 | .name = KBUILD_MODNAME, | ||
899 | .id_table = az6007_usb_table, | ||
900 | .probe = dvb_usbv2_probe, | ||
901 | .disconnect = az6007_usb_disconnect, | ||
902 | .no_dynamic_id = 1, | ||
903 | .soft_unbind = 1, | ||
904 | /* | ||
905 | * FIXME: need to implement reset_resume, likely with | ||
906 | * dvb-usb-v2 core support | ||
907 | */ | ||
908 | .suspend = az6007_suspend, | ||
909 | .resume = az6007_resume, | ||
910 | }; | ||
911 | |||
912 | module_usb_driver(az6007_usb_driver); | ||
913 | |||
914 | MODULE_AUTHOR("Henry Wang <Henry.wang@AzureWave.com>"); | ||
915 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
916 | MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones"); | ||
917 | MODULE_VERSION("2.0"); | ||
918 | MODULE_LICENSE("GPL"); | ||
919 | MODULE_FIRMWARE(AZ6007_FIRMWARE); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/ce6230.c b/drivers/media/usb/dvb-usb-v2/ce6230.c new file mode 100644 index 000000000000..84ff4a96ca4e --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/ce6230.c | |||
@@ -0,0 +1,287 @@ | |||
1 | /* | ||
2 | * Intel CE6230 DVB USB driver | ||
3 | * | ||
4 | * Copyright (C) 2009 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 | */ | ||
21 | |||
22 | #include "ce6230.h" | ||
23 | |||
24 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
25 | |||
26 | static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) | ||
27 | { | ||
28 | int ret; | ||
29 | unsigned int pipe; | ||
30 | u8 request; | ||
31 | u8 requesttype; | ||
32 | u16 value; | ||
33 | u16 index; | ||
34 | u8 *buf; | ||
35 | |||
36 | request = req->cmd; | ||
37 | value = req->value; | ||
38 | index = req->index; | ||
39 | |||
40 | switch (req->cmd) { | ||
41 | case I2C_READ: | ||
42 | case DEMOD_READ: | ||
43 | case REG_READ: | ||
44 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | ||
45 | break; | ||
46 | case I2C_WRITE: | ||
47 | case DEMOD_WRITE: | ||
48 | case REG_WRITE: | ||
49 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | ||
50 | break; | ||
51 | default: | ||
52 | pr_debug("%s: unknown command=%02x\n", __func__, req->cmd); | ||
53 | ret = -EINVAL; | ||
54 | goto error; | ||
55 | } | ||
56 | |||
57 | buf = kmalloc(req->data_len, GFP_KERNEL); | ||
58 | if (!buf) { | ||
59 | ret = -ENOMEM; | ||
60 | goto error; | ||
61 | } | ||
62 | |||
63 | if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { | ||
64 | /* write */ | ||
65 | memcpy(buf, req->data, req->data_len); | ||
66 | pipe = usb_sndctrlpipe(d->udev, 0); | ||
67 | } else { | ||
68 | /* read */ | ||
69 | pipe = usb_rcvctrlpipe(d->udev, 0); | ||
70 | } | ||
71 | |||
72 | msleep(1); /* avoid I2C errors */ | ||
73 | |||
74 | ret = usb_control_msg(d->udev, pipe, request, requesttype, value, index, | ||
75 | buf, req->data_len, CE6230_USB_TIMEOUT); | ||
76 | |||
77 | ce6230_debug_dump(request, requesttype, value, index, buf, | ||
78 | req->data_len); | ||
79 | |||
80 | if (ret < 0) | ||
81 | pr_err("%s: usb_control_msg() failed=%d\n", KBUILD_MODNAME, | ||
82 | ret); | ||
83 | else | ||
84 | ret = 0; | ||
85 | |||
86 | /* read request, copy returned data to return buf */ | ||
87 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) | ||
88 | memcpy(req->data, buf, req->data_len); | ||
89 | |||
90 | kfree(buf); | ||
91 | error: | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | /* I2C */ | ||
96 | static struct zl10353_config ce6230_zl10353_config; | ||
97 | |||
98 | static int ce6230_i2c_master_xfer(struct i2c_adapter *adap, | ||
99 | struct i2c_msg msg[], int num) | ||
100 | { | ||
101 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
102 | int ret = 0, i = 0; | ||
103 | struct usb_req req; | ||
104 | |||
105 | if (num > 2) | ||
106 | return -EOPNOTSUPP; | ||
107 | |||
108 | memset(&req, 0, sizeof(req)); | ||
109 | |||
110 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
111 | return -EAGAIN; | ||
112 | |||
113 | while (i < num) { | ||
114 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
115 | if (msg[i].addr == | ||
116 | ce6230_zl10353_config.demod_address) { | ||
117 | req.cmd = DEMOD_READ; | ||
118 | req.value = msg[i].addr >> 1; | ||
119 | req.index = msg[i].buf[0]; | ||
120 | req.data_len = msg[i+1].len; | ||
121 | req.data = &msg[i+1].buf[0]; | ||
122 | ret = ce6230_ctrl_msg(d, &req); | ||
123 | } else { | ||
124 | pr_err("%s: I2C read not implemented\n", | ||
125 | KBUILD_MODNAME); | ||
126 | ret = -EOPNOTSUPP; | ||
127 | } | ||
128 | i += 2; | ||
129 | } else { | ||
130 | if (msg[i].addr == | ||
131 | ce6230_zl10353_config.demod_address) { | ||
132 | req.cmd = DEMOD_WRITE; | ||
133 | req.value = msg[i].addr >> 1; | ||
134 | req.index = msg[i].buf[0]; | ||
135 | req.data_len = msg[i].len-1; | ||
136 | req.data = &msg[i].buf[1]; | ||
137 | ret = ce6230_ctrl_msg(d, &req); | ||
138 | } else { | ||
139 | req.cmd = I2C_WRITE; | ||
140 | req.value = 0x2000 + (msg[i].addr >> 1); | ||
141 | req.index = 0x0000; | ||
142 | req.data_len = msg[i].len; | ||
143 | req.data = &msg[i].buf[0]; | ||
144 | ret = ce6230_ctrl_msg(d, &req); | ||
145 | } | ||
146 | i += 1; | ||
147 | } | ||
148 | if (ret) | ||
149 | break; | ||
150 | } | ||
151 | |||
152 | mutex_unlock(&d->i2c_mutex); | ||
153 | return ret ? ret : i; | ||
154 | } | ||
155 | |||
156 | static u32 ce6230_i2c_functionality(struct i2c_adapter *adapter) | ||
157 | { | ||
158 | return I2C_FUNC_I2C; | ||
159 | } | ||
160 | |||
161 | static struct i2c_algorithm ce6230_i2c_algorithm = { | ||
162 | .master_xfer = ce6230_i2c_master_xfer, | ||
163 | .functionality = ce6230_i2c_functionality, | ||
164 | }; | ||
165 | |||
166 | /* Callbacks for DVB USB */ | ||
167 | static struct zl10353_config ce6230_zl10353_config = { | ||
168 | .demod_address = 0x1e, | ||
169 | .adc_clock = 450000, | ||
170 | .if2 = 45700, | ||
171 | .no_tuner = 1, | ||
172 | .parallel_ts = 1, | ||
173 | .clock_ctl_1 = 0x34, | ||
174 | .pll_0 = 0x0e, | ||
175 | }; | ||
176 | |||
177 | static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap) | ||
178 | { | ||
179 | pr_debug("%s:\n", __func__); | ||
180 | |||
181 | adap->fe[0] = dvb_attach(zl10353_attach, &ce6230_zl10353_config, | ||
182 | &adap_to_d(adap)->i2c_adap); | ||
183 | if (adap->fe[0] == NULL) | ||
184 | return -ENODEV; | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static struct mxl5005s_config ce6230_mxl5003s_config = { | ||
190 | .i2c_address = 0xc6, | ||
191 | .if_freq = IF_FREQ_4570000HZ, | ||
192 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
193 | .agc_mode = MXL_SINGLE_AGC, | ||
194 | .tracking_filter = MXL_TF_DEFAULT, | ||
195 | .rssi_enable = MXL_RSSI_ENABLE, | ||
196 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
197 | .div_out = MXL_DIV_OUT_4, | ||
198 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
199 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
200 | .top = MXL5005S_TOP_25P2, | ||
201 | .mod_mode = MXL_DIGITAL_MODE, | ||
202 | .if_mode = MXL_ZERO_IF, | ||
203 | .AgcMasterByte = 0x00, | ||
204 | }; | ||
205 | |||
206 | static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) | ||
207 | { | ||
208 | int ret; | ||
209 | |||
210 | pr_debug("%s:\n", __func__); | ||
211 | |||
212 | ret = dvb_attach(mxl5005s_attach, adap->fe[0], | ||
213 | &adap_to_d(adap)->i2c_adap, | ||
214 | &ce6230_mxl5003s_config) == NULL ? -ENODEV : 0; | ||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | static int ce6230_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
219 | { | ||
220 | int ret; | ||
221 | |||
222 | pr_debug("%s: onoff=%d\n", __func__, onoff); | ||
223 | |||
224 | /* InterfaceNumber 1 / AlternateSetting 0 idle | ||
225 | InterfaceNumber 1 / AlternateSetting 1 streaming */ | ||
226 | ret = usb_set_interface(d->udev, 1, onoff); | ||
227 | if (ret) | ||
228 | pr_err("%s: usb_set_interface() failed=%d\n", KBUILD_MODNAME, | ||
229 | ret); | ||
230 | |||
231 | return ret; | ||
232 | } | ||
233 | |||
234 | /* DVB USB Driver stuff */ | ||
235 | static struct dvb_usb_device_properties ce6230_props = { | ||
236 | .driver_name = KBUILD_MODNAME, | ||
237 | .owner = THIS_MODULE, | ||
238 | .adapter_nr = adapter_nr, | ||
239 | .bInterfaceNumber = 1, | ||
240 | |||
241 | .i2c_algo = &ce6230_i2c_algorithm, | ||
242 | .power_ctrl = ce6230_power_ctrl, | ||
243 | .frontend_attach = ce6230_zl10353_frontend_attach, | ||
244 | .tuner_attach = ce6230_mxl5003s_tuner_attach, | ||
245 | |||
246 | .num_adapters = 1, | ||
247 | .adapter = { | ||
248 | { | ||
249 | .stream = { | ||
250 | .type = USB_BULK, | ||
251 | .count = 6, | ||
252 | .endpoint = 0x82, | ||
253 | .u = { | ||
254 | .bulk = { | ||
255 | .buffersize = (16 * 512), | ||
256 | } | ||
257 | } | ||
258 | }, | ||
259 | } | ||
260 | }, | ||
261 | }; | ||
262 | |||
263 | static const struct usb_device_id ce6230_id_table[] = { | ||
264 | { DVB_USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500, | ||
265 | &ce6230_props, "Intel CE9500 reference design", NULL) }, | ||
266 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310, | ||
267 | &ce6230_props, "AVerMedia A310 USB 2.0 DVB-T tuner", NULL) }, | ||
268 | { } | ||
269 | }; | ||
270 | MODULE_DEVICE_TABLE(usb, ce6230_id_table); | ||
271 | |||
272 | static struct usb_driver ce6230_usb_driver = { | ||
273 | .name = KBUILD_MODNAME, | ||
274 | .id_table = ce6230_id_table, | ||
275 | .probe = dvb_usbv2_probe, | ||
276 | .disconnect = dvb_usbv2_disconnect, | ||
277 | .suspend = dvb_usbv2_suspend, | ||
278 | .resume = dvb_usbv2_resume, | ||
279 | .no_dynamic_id = 1, | ||
280 | .soft_unbind = 1, | ||
281 | }; | ||
282 | |||
283 | module_usb_driver(ce6230_usb_driver); | ||
284 | |||
285 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
286 | MODULE_DESCRIPTION("Intel CE6230 driver"); | ||
287 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/ce6230.h b/drivers/media/usb/dvb-usb-v2/ce6230.h new file mode 100644 index 000000000000..42d754494a3a --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/ce6230.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Intel CE6230 DVB USB driver | ||
3 | * | ||
4 | * Copyright (C) 2009 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 | */ | ||
21 | |||
22 | #ifndef CE6230_H | ||
23 | #define CE6230_H | ||
24 | |||
25 | #include "dvb_usb.h" | ||
26 | #include "zl10353.h" | ||
27 | #include "mxl5005s.h" | ||
28 | |||
29 | #define ce6230_debug_dump(r, t, v, i, b, l) { \ | ||
30 | char *direction; \ | ||
31 | if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ | ||
32 | direction = ">>>"; \ | ||
33 | else \ | ||
34 | direction = "<<<"; \ | ||
35 | pr_debug("%s: %02x %02x %02x %02x %02x %02x %02x %02x %s [%d bytes]\n", \ | ||
36 | __func__, t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, \ | ||
37 | l & 0xff, l >> 8, direction, l); \ | ||
38 | } | ||
39 | |||
40 | #define CE6230_USB_TIMEOUT 1000 | ||
41 | |||
42 | struct usb_req { | ||
43 | u8 cmd; /* [1] */ | ||
44 | u16 value; /* [2|3] */ | ||
45 | u16 index; /* [4|5] */ | ||
46 | u16 data_len; /* [6|7] */ | ||
47 | u8 *data; | ||
48 | }; | ||
49 | |||
50 | enum ce6230_cmd { | ||
51 | CONFIG_READ = 0xd0, /* rd 0 (unclear) */ | ||
52 | UNKNOWN_WRITE = 0xc7, /* wr 7 (unclear) */ | ||
53 | I2C_READ = 0xd9, /* rd 9 (unclear) */ | ||
54 | I2C_WRITE = 0xca, /* wr a */ | ||
55 | DEMOD_READ = 0xdb, /* rd b */ | ||
56 | DEMOD_WRITE = 0xcc, /* wr c */ | ||
57 | REG_READ = 0xde, /* rd e */ | ||
58 | REG_WRITE = 0xcf, /* wr f */ | ||
59 | }; | ||
60 | |||
61 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/cypress_firmware.c b/drivers/media/usb/dvb-usb-v2/cypress_firmware.c new file mode 100644 index 000000000000..9f7c970c6424 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/cypress_firmware.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* cypress_firmware.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for downloading the firmware to Cypress FX 1 | ||
7 | * and 2 based devices. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include "dvb_usb.h" | ||
12 | #include "cypress_firmware.h" | ||
13 | |||
14 | struct usb_cypress_controller { | ||
15 | u8 id; | ||
16 | const char *name; /* name of the usb controller */ | ||
17 | u16 cs_reg; /* needs to be restarted, | ||
18 | * when the firmware has been downloaded */ | ||
19 | }; | ||
20 | |||
21 | static const struct usb_cypress_controller cypress[] = { | ||
22 | { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cs_reg = 0x7f92 }, | ||
23 | { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cs_reg = 0x7f92 }, | ||
24 | { .id = CYPRESS_FX2, .name = "Cypress FX2", .cs_reg = 0xe600 }, | ||
25 | }; | ||
26 | |||
27 | /* | ||
28 | * load a firmware packet to the device | ||
29 | */ | ||
30 | static int usb_cypress_writemem(struct usb_device *udev, u16 addr, u8 *data, | ||
31 | u8 len) | ||
32 | { | ||
33 | return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
34 | 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000); | ||
35 | } | ||
36 | |||
37 | int usbv2_cypress_load_firmware(struct usb_device *udev, | ||
38 | const struct firmware *fw, int type) | ||
39 | { | ||
40 | struct hexline hx; | ||
41 | u8 reset; | ||
42 | int ret, pos = 0; | ||
43 | |||
44 | /* stop the CPU */ | ||
45 | reset = 1; | ||
46 | ret = usb_cypress_writemem(udev, cypress[type].cs_reg, &reset, 1); | ||
47 | if (ret != 1) | ||
48 | pr_err("%s: could not stop the USB controller CPU", | ||
49 | KBUILD_MODNAME); | ||
50 | |||
51 | while ((ret = dvb_usbv2_get_hexline(fw, &hx, &pos)) > 0) { | ||
52 | pr_debug("%s: writing to address %04x (buffer: %02x %02x)\n", | ||
53 | __func__, hx.addr, hx.len, hx.chk); | ||
54 | |||
55 | ret = usb_cypress_writemem(udev, hx.addr, hx.data, hx.len); | ||
56 | if (ret != hx.len) { | ||
57 | pr_err("%s: error while transferring firmware " \ | ||
58 | "(transferred size=%d, block size=%d)", | ||
59 | KBUILD_MODNAME, ret, hx.len); | ||
60 | ret = -EINVAL; | ||
61 | break; | ||
62 | } | ||
63 | } | ||
64 | if (ret < 0) { | ||
65 | pr_err("%s: firmware download failed at %d with %d", | ||
66 | KBUILD_MODNAME, pos, ret); | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | if (ret == 0) { | ||
71 | /* restart the CPU */ | ||
72 | reset = 0; | ||
73 | if (ret || usb_cypress_writemem( | ||
74 | udev, cypress[type].cs_reg, &reset, 1) != 1) { | ||
75 | pr_err("%s: could not restart the USB controller CPU", | ||
76 | KBUILD_MODNAME); | ||
77 | ret = -EINVAL; | ||
78 | } | ||
79 | } else | ||
80 | ret = -EIO; | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | EXPORT_SYMBOL(usbv2_cypress_load_firmware); | ||
85 | |||
86 | int dvb_usbv2_get_hexline(const struct firmware *fw, struct hexline *hx, | ||
87 | int *pos) | ||
88 | { | ||
89 | u8 *b = (u8 *) &fw->data[*pos]; | ||
90 | int data_offs = 4; | ||
91 | |||
92 | if (*pos >= fw->size) | ||
93 | return 0; | ||
94 | |||
95 | memset(hx, 0, sizeof(struct hexline)); | ||
96 | |||
97 | hx->len = b[0]; | ||
98 | |||
99 | if ((*pos + hx->len + 4) >= fw->size) | ||
100 | return -EINVAL; | ||
101 | |||
102 | hx->addr = b[1] | (b[2] << 8); | ||
103 | hx->type = b[3]; | ||
104 | |||
105 | if (hx->type == 0x04) { | ||
106 | /* b[4] and b[5] are the Extended linear address record data | ||
107 | * field */ | ||
108 | hx->addr |= (b[4] << 24) | (b[5] << 16); | ||
109 | /* | ||
110 | hx->len -= 2; | ||
111 | data_offs += 2; | ||
112 | */ | ||
113 | } | ||
114 | memcpy(hx->data, &b[data_offs], hx->len); | ||
115 | hx->chk = b[hx->len + data_offs]; | ||
116 | |||
117 | *pos += hx->len + 5; | ||
118 | |||
119 | return *pos; | ||
120 | } | ||
121 | EXPORT_SYMBOL(dvb_usbv2_get_hexline); | ||
122 | |||
123 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
124 | MODULE_DESCRIPTION("Cypress firmware download"); | ||
125 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/cypress_firmware.h b/drivers/media/usb/dvb-usb-v2/cypress_firmware.h new file mode 100644 index 000000000000..80085fd4132c --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/cypress_firmware.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* cypress_firmware.h is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for downloading the firmware to Cypress FX 1 | ||
7 | * and 2 based devices. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #ifndef CYPRESS_FIRMWARE_H | ||
12 | #define CYPRESS_FIRMWARE_H | ||
13 | |||
14 | #define CYPRESS_AN2135 0 | ||
15 | #define CYPRESS_AN2235 1 | ||
16 | #define CYPRESS_FX2 2 | ||
17 | |||
18 | /* commonly used firmware download types and function */ | ||
19 | struct hexline { | ||
20 | u8 len; | ||
21 | u32 addr; | ||
22 | u8 type; | ||
23 | u8 data[255]; | ||
24 | u8 chk; | ||
25 | }; | ||
26 | extern int usbv2_cypress_load_firmware(struct usb_device *, | ||
27 | const struct firmware *, int); | ||
28 | extern int dvb_usbv2_get_hexline(const struct firmware *, | ||
29 | struct hexline *, int *); | ||
30 | |||
31 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h new file mode 100644 index 000000000000..79b3b8b6750d --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h | |||
@@ -0,0 +1,389 @@ | |||
1 | /* | ||
2 | * DVB USB framework | ||
3 | * | ||
4 | * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de> | ||
5 | * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef DVB_USB_H | ||
23 | #define DVB_USB_H | ||
24 | |||
25 | #include <linux/usb/input.h> | ||
26 | #include <linux/firmware.h> | ||
27 | #include <media/rc-core.h> | ||
28 | |||
29 | #include "dvb_frontend.h" | ||
30 | #include "dvb_demux.h" | ||
31 | #include "dvb_net.h" | ||
32 | #include "dmxdev.h" | ||
33 | #include "dvb-usb-ids.h" | ||
34 | |||
35 | /* | ||
36 | * device file: /dev/dvb/adapter[0-1]/frontend[0-2] | ||
37 | * | ||
38 | * |-- device | ||
39 | * | |-- adapter0 | ||
40 | * | | |-- frontend0 | ||
41 | * | | |-- frontend1 | ||
42 | * | | `-- frontend2 | ||
43 | * | `-- adapter1 | ||
44 | * | |-- frontend0 | ||
45 | * | |-- frontend1 | ||
46 | * | `-- frontend2 | ||
47 | * | ||
48 | * | ||
49 | * Commonly used variable names: | ||
50 | * d = pointer to device (struct dvb_usb_device *) | ||
51 | * adap = pointer to adapter (struct dvb_usb_adapter *) | ||
52 | * fe = pointer to frontend (struct dvb_frontend *) | ||
53 | * | ||
54 | * Use macros defined in that file to resolve needed pointers. | ||
55 | */ | ||
56 | |||
57 | /* helper macros for every DVB USB driver use */ | ||
58 | #define adap_to_d(adap) (container_of(adap, struct dvb_usb_device, \ | ||
59 | adapter[adap->id])) | ||
60 | #define adap_to_priv(adap) (adap_to_d(adap)->priv) | ||
61 | #define fe_to_adap(fe) ((struct dvb_usb_adapter *) ((fe)->dvb->priv)) | ||
62 | #define fe_to_d(fe) (adap_to_d(fe_to_adap(fe))) | ||
63 | #define fe_to_priv(fe) (fe_to_d(fe)->priv) | ||
64 | #define d_to_priv(d) (d->priv) | ||
65 | |||
66 | #define DVB_USB_STREAM_BULK(endpoint_, count_, size_) { \ | ||
67 | .type = USB_BULK, \ | ||
68 | .count = count_, \ | ||
69 | .endpoint = endpoint_, \ | ||
70 | .u = { \ | ||
71 | .bulk = { \ | ||
72 | .buffersize = size_, \ | ||
73 | } \ | ||
74 | } \ | ||
75 | } | ||
76 | |||
77 | #define DVB_USB_STREAM_ISOC(endpoint_, count_, frames_, size_, interval_) { \ | ||
78 | .type = USB_ISOC, \ | ||
79 | .count = count_, \ | ||
80 | .endpoint = endpoint_, \ | ||
81 | .u = { \ | ||
82 | .isoc = { \ | ||
83 | .framesperurb = frames_, \ | ||
84 | .framesize = size_,\ | ||
85 | .interval = interval_, \ | ||
86 | } \ | ||
87 | } \ | ||
88 | } | ||
89 | |||
90 | #define DVB_USB_DEVICE(vend, prod, props_, name_, rc) \ | ||
91 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \ | ||
92 | .idVendor = (vend), \ | ||
93 | .idProduct = (prod), \ | ||
94 | .driver_info = (kernel_ulong_t) &((const struct dvb_usb_driver_info) { \ | ||
95 | .props = (props_), \ | ||
96 | .name = (name_), \ | ||
97 | .rc_map = (rc), \ | ||
98 | }) | ||
99 | |||
100 | struct dvb_usb_device; | ||
101 | struct dvb_usb_adapter; | ||
102 | |||
103 | /** | ||
104 | * structure for carrying all needed data from the device driver to the general | ||
105 | * dvb usb routines | ||
106 | * @name: device name | ||
107 | * @rc_map: name of rc codes table | ||
108 | * @props: structure containing all device properties | ||
109 | */ | ||
110 | struct dvb_usb_driver_info { | ||
111 | const char *name; | ||
112 | const char *rc_map; | ||
113 | const struct dvb_usb_device_properties *props; | ||
114 | }; | ||
115 | |||
116 | /** | ||
117 | * structure for remote controller configuration | ||
118 | * @map_name: name of rc codes table | ||
119 | * @allowed_protos: protocol(s) supported by the driver | ||
120 | * @change_protocol: callback to change protocol | ||
121 | * @query: called to query an event from the device | ||
122 | * @interval: time in ms between two queries | ||
123 | * @driver_type: used to point if a device supports raw mode | ||
124 | * @bulk_mode: device supports bulk mode for rc (disable polling mode) | ||
125 | */ | ||
126 | struct dvb_usb_rc { | ||
127 | const char *map_name; | ||
128 | u64 allowed_protos; | ||
129 | int (*change_protocol)(struct rc_dev *dev, u64 rc_type); | ||
130 | int (*query) (struct dvb_usb_device *d); | ||
131 | unsigned int interval; | ||
132 | const enum rc_driver_type driver_type; | ||
133 | bool bulk_mode; | ||
134 | }; | ||
135 | |||
136 | /** | ||
137 | * usb streaming configration for adapter | ||
138 | * @type: urb type | ||
139 | * @count: count of used urbs | ||
140 | * @endpoint: stream usb endpoint number | ||
141 | */ | ||
142 | struct usb_data_stream_properties { | ||
143 | #define USB_BULK 1 | ||
144 | #define USB_ISOC 2 | ||
145 | u8 type; | ||
146 | u8 count; | ||
147 | u8 endpoint; | ||
148 | |||
149 | union { | ||
150 | struct { | ||
151 | unsigned int buffersize; /* per URB */ | ||
152 | } bulk; | ||
153 | struct { | ||
154 | int framesperurb; | ||
155 | int framesize; | ||
156 | int interval; | ||
157 | } isoc; | ||
158 | } u; | ||
159 | }; | ||
160 | |||
161 | /** | ||
162 | * properties of dvb usb device adapter | ||
163 | * @caps: adapter capabilities | ||
164 | * @pid_filter_count: pid count of adapter pid-filter | ||
165 | * @pid_filter_ctrl: called to enable/disable pid-filter | ||
166 | * @pid_filter: called to set/unset pid for filtering | ||
167 | * @stream: adapter usb stream configuration | ||
168 | */ | ||
169 | #define MAX_NO_OF_FE_PER_ADAP 3 | ||
170 | struct dvb_usb_adapter_properties { | ||
171 | #define DVB_USB_ADAP_HAS_PID_FILTER 0x01 | ||
172 | #define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02 | ||
173 | #define DVB_USB_ADAP_NEED_PID_FILTERING 0x04 | ||
174 | u8 caps; | ||
175 | |||
176 | u8 pid_filter_count; | ||
177 | int (*pid_filter_ctrl) (struct dvb_usb_adapter *, int); | ||
178 | int (*pid_filter) (struct dvb_usb_adapter *, int, u16, int); | ||
179 | |||
180 | struct usb_data_stream_properties stream; | ||
181 | }; | ||
182 | |||
183 | /** | ||
184 | * struct dvb_usb_device_properties - properties of a dvb-usb-device | ||
185 | * @driver_name: name of the owning driver module | ||
186 | * @owner: owner of the dvb_adapter | ||
187 | * @adapter_nr: values from the DVB_DEFINE_MOD_OPT_ADAPTER_NR() macro | ||
188 | * @bInterfaceNumber: usb interface number driver binds | ||
189 | * @size_of_priv: bytes allocated for the driver private data | ||
190 | * @generic_bulk_ctrl_endpoint: bulk control endpoint number for sent | ||
191 | * @generic_bulk_ctrl_endpoint_response: bulk control endpoint number for | ||
192 | * receive | ||
193 | * @generic_bulk_ctrl_delay: delay between bulk control sent and receive message | ||
194 | * @identify_state: called to determine the firmware state (cold or warm) and | ||
195 | * return possible firmware file name to be loaded | ||
196 | * @firmware: name of the firmware file to be loaded | ||
197 | * @download_firmware: called to download the firmware | ||
198 | * @i2c_algo: i2c_algorithm if the device has i2c-adapter | ||
199 | * @num_adapters: dvb usb device adapter count | ||
200 | * @get_adapter_count: called to resolve adapter count | ||
201 | * @adapter: array of all adapter properties of device | ||
202 | * @power_ctrl: called to enable/disable power of the device | ||
203 | * @read_config: called to resolve device configuration | ||
204 | * @read_mac_address: called to resolve adapter mac-address | ||
205 | * @frontend_attach: called to attach the possible frontends | ||
206 | * @tuner_attach: called to attach the possible tuners | ||
207 | * @frontend_ctrl: called to power on/off active frontend | ||
208 | * @streaming_ctrl: called to start/stop the usb streaming of adapter | ||
209 | * @init: called after adapters are created in order to finalize device | ||
210 | * configuration | ||
211 | * @exit: called when driver is unloaded | ||
212 | * @get_rc_config: called to resolve used remote controller configuration | ||
213 | * @get_stream_config: called to resolve input and output stream configuration | ||
214 | * of the adapter just before streaming is started. input stream is transport | ||
215 | * stream from the demodulator and output stream is usb stream to host. | ||
216 | */ | ||
217 | #define MAX_NO_OF_ADAPTER_PER_DEVICE 2 | ||
218 | struct dvb_usb_device_properties { | ||
219 | const char *driver_name; | ||
220 | struct module *owner; | ||
221 | short *adapter_nr; | ||
222 | |||
223 | u8 bInterfaceNumber; | ||
224 | unsigned int size_of_priv; | ||
225 | u8 generic_bulk_ctrl_endpoint; | ||
226 | u8 generic_bulk_ctrl_endpoint_response; | ||
227 | unsigned int generic_bulk_ctrl_delay; | ||
228 | |||
229 | #define WARM 0 | ||
230 | #define COLD 1 | ||
231 | int (*identify_state) (struct dvb_usb_device *, const char **); | ||
232 | const char *firmware; | ||
233 | #define RECONNECTS_USB 1 | ||
234 | int (*download_firmware) (struct dvb_usb_device *, | ||
235 | const struct firmware *); | ||
236 | |||
237 | struct i2c_algorithm *i2c_algo; | ||
238 | |||
239 | unsigned int num_adapters; | ||
240 | int (*get_adapter_count) (struct dvb_usb_device *); | ||
241 | struct dvb_usb_adapter_properties adapter[MAX_NO_OF_ADAPTER_PER_DEVICE]; | ||
242 | int (*power_ctrl) (struct dvb_usb_device *, int); | ||
243 | int (*read_config) (struct dvb_usb_device *d); | ||
244 | int (*read_mac_address) (struct dvb_usb_adapter *, u8 []); | ||
245 | int (*frontend_attach) (struct dvb_usb_adapter *); | ||
246 | int (*tuner_attach) (struct dvb_usb_adapter *); | ||
247 | int (*frontend_ctrl) (struct dvb_frontend *, int); | ||
248 | int (*streaming_ctrl) (struct dvb_frontend *, int); | ||
249 | int (*init) (struct dvb_usb_device *); | ||
250 | void (*exit) (struct dvb_usb_device *); | ||
251 | int (*get_rc_config) (struct dvb_usb_device *, struct dvb_usb_rc *); | ||
252 | #define DVB_USB_FE_TS_TYPE_188 0 | ||
253 | #define DVB_USB_FE_TS_TYPE_204 1 | ||
254 | #define DVB_USB_FE_TS_TYPE_RAW 2 | ||
255 | int (*get_stream_config) (struct dvb_frontend *, u8 *, | ||
256 | struct usb_data_stream_properties *); | ||
257 | }; | ||
258 | |||
259 | /** | ||
260 | * generic object of an usb stream | ||
261 | * @buf_num: number of buffer allocated | ||
262 | * @buf_size: size of each buffer in buf_list | ||
263 | * @buf_list: array containing all allocate buffers for streaming | ||
264 | * @dma_addr: list of dma_addr_t for each buffer in buf_list | ||
265 | * | ||
266 | * @urbs_initialized: number of URBs initialized | ||
267 | * @urbs_submitted: number of URBs submitted | ||
268 | */ | ||
269 | #define MAX_NO_URBS_FOR_DATA_STREAM 10 | ||
270 | struct usb_data_stream { | ||
271 | struct usb_device *udev; | ||
272 | struct usb_data_stream_properties props; | ||
273 | |||
274 | #define USB_STATE_INIT 0x00 | ||
275 | #define USB_STATE_URB_BUF 0x01 | ||
276 | u8 state; | ||
277 | |||
278 | void (*complete) (struct usb_data_stream *, u8 *, size_t); | ||
279 | |||
280 | struct urb *urb_list[MAX_NO_URBS_FOR_DATA_STREAM]; | ||
281 | int buf_num; | ||
282 | unsigned long buf_size; | ||
283 | u8 *buf_list[MAX_NO_URBS_FOR_DATA_STREAM]; | ||
284 | dma_addr_t dma_addr[MAX_NO_URBS_FOR_DATA_STREAM]; | ||
285 | |||
286 | int urbs_initialized; | ||
287 | int urbs_submitted; | ||
288 | |||
289 | void *user_priv; | ||
290 | }; | ||
291 | |||
292 | /** | ||
293 | * dvb adapter object on dvb usb device | ||
294 | * @props: pointer to adapter properties | ||
295 | * @stream: adapter the usb data stream | ||
296 | * @id: index of this adapter (starting with 0) | ||
297 | * @ts_type: transport stream, input stream, type | ||
298 | * @pid_filtering: is hardware pid_filtering used or not | ||
299 | * @feed_count: current feed count | ||
300 | * @max_feed_count: maimum feed count device can handle | ||
301 | * @dvb_adap: adapter dvb_adapter | ||
302 | * @dmxdev: adapter dmxdev | ||
303 | * @demux: adapter software demuxer | ||
304 | * @dvb_net: adapter dvb_net interfaces | ||
305 | * @sync_mutex: mutex used to sync control and streaming of the adapter | ||
306 | * @fe: adapter frontends | ||
307 | * @fe_init: rerouted frontend-init function | ||
308 | * @fe_sleep: rerouted frontend-sleep function | ||
309 | */ | ||
310 | struct dvb_usb_adapter { | ||
311 | const struct dvb_usb_adapter_properties *props; | ||
312 | struct usb_data_stream stream; | ||
313 | u8 id; | ||
314 | u8 ts_type; | ||
315 | bool pid_filtering; | ||
316 | u8 feed_count; | ||
317 | u8 max_feed_count; | ||
318 | s8 active_fe; | ||
319 | |||
320 | /* dvb */ | ||
321 | struct dvb_adapter dvb_adap; | ||
322 | struct dmxdev dmxdev; | ||
323 | struct dvb_demux demux; | ||
324 | struct dvb_net dvb_net; | ||
325 | struct mutex sync_mutex; | ||
326 | |||
327 | struct dvb_frontend *fe[MAX_NO_OF_FE_PER_ADAP]; | ||
328 | int (*fe_init[MAX_NO_OF_FE_PER_ADAP]) (struct dvb_frontend *); | ||
329 | int (*fe_sleep[MAX_NO_OF_FE_PER_ADAP]) (struct dvb_frontend *); | ||
330 | }; | ||
331 | |||
332 | /** | ||
333 | * dvb usb device object | ||
334 | * @props: device properties | ||
335 | * @name: device name | ||
336 | * @rc_map: name of rc codes table | ||
337 | * @udev: pointer to the device's struct usb_device | ||
338 | * @intf: pointer to the device's usb interface | ||
339 | * @rc: remote controller configuration | ||
340 | * @probe_work: work to defer .probe() | ||
341 | * @powered: indicated whether the device is power or not | ||
342 | * @usb_mutex: mutex for usb control messages | ||
343 | * @i2c_mutex: mutex for i2c-transfers | ||
344 | * @i2c_adap: device's i2c-adapter | ||
345 | * @rc_dev: rc device for the remote control | ||
346 | * @rc_query_work: work for polling remote | ||
347 | * @priv: private data of the actual driver (allocate by dvb usb, size defined | ||
348 | * in size_of_priv of dvb_usb_properties). | ||
349 | */ | ||
350 | struct dvb_usb_device { | ||
351 | const struct dvb_usb_device_properties *props; | ||
352 | const char *name; | ||
353 | const char *rc_map; | ||
354 | |||
355 | struct usb_device *udev; | ||
356 | struct usb_interface *intf; | ||
357 | struct dvb_usb_rc rc; | ||
358 | struct work_struct probe_work; | ||
359 | pid_t work_pid; | ||
360 | int powered; | ||
361 | |||
362 | /* locking */ | ||
363 | struct mutex usb_mutex; | ||
364 | |||
365 | /* i2c */ | ||
366 | struct mutex i2c_mutex; | ||
367 | struct i2c_adapter i2c_adap; | ||
368 | |||
369 | struct dvb_usb_adapter adapter[MAX_NO_OF_ADAPTER_PER_DEVICE]; | ||
370 | |||
371 | /* remote control */ | ||
372 | struct rc_dev *rc_dev; | ||
373 | char rc_phys[64]; | ||
374 | struct delayed_work rc_query_work; | ||
375 | |||
376 | void *priv; | ||
377 | }; | ||
378 | |||
379 | extern int dvb_usbv2_probe(struct usb_interface *, | ||
380 | const struct usb_device_id *); | ||
381 | extern void dvb_usbv2_disconnect(struct usb_interface *); | ||
382 | extern int dvb_usbv2_suspend(struct usb_interface *, pm_message_t); | ||
383 | extern int dvb_usbv2_resume(struct usb_interface *); | ||
384 | |||
385 | /* the generic read/write method for device control */ | ||
386 | extern int dvb_usbv2_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16); | ||
387 | extern int dvb_usbv2_generic_write(struct dvb_usb_device *, u8 *, u16); | ||
388 | |||
389 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h new file mode 100644 index 000000000000..45f07090d431 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * DVB USB framework | ||
3 | * | ||
4 | * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de> | ||
5 | * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef DVB_USB_COMMON_H | ||
23 | #define DVB_USB_COMMON_H | ||
24 | |||
25 | #include "dvb_usb.h" | ||
26 | |||
27 | /* commonly used methods */ | ||
28 | extern int usb_urb_initv2(struct usb_data_stream *stream, | ||
29 | const struct usb_data_stream_properties *props); | ||
30 | extern int usb_urb_exitv2(struct usb_data_stream *stream); | ||
31 | extern int usb_urb_submitv2(struct usb_data_stream *stream, | ||
32 | struct usb_data_stream_properties *props); | ||
33 | extern int usb_urb_killv2(struct usb_data_stream *stream); | ||
34 | |||
35 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c new file mode 100644 index 000000000000..a72f9c7de682 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | |||
@@ -0,0 +1,997 @@ | |||
1 | /* | ||
2 | * DVB USB framework | ||
3 | * | ||
4 | * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de> | ||
5 | * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | |||
22 | #include "dvb_usb_common.h" | ||
23 | |||
24 | int dvb_usbv2_disable_rc_polling; | ||
25 | module_param_named(disable_rc_polling, dvb_usbv2_disable_rc_polling, int, 0644); | ||
26 | MODULE_PARM_DESC(disable_rc_polling, | ||
27 | "disable remote control polling (default: 0)"); | ||
28 | static int dvb_usb_force_pid_filter_usage; | ||
29 | module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, | ||
30 | int, 0444); | ||
31 | MODULE_PARM_DESC(force_pid_filter_usage, "force all DVB USB devices to use a " \ | ||
32 | "PID filter, if any (default: 0)"); | ||
33 | |||
34 | static int dvb_usbv2_download_firmware(struct dvb_usb_device *d, const char *name) | ||
35 | { | ||
36 | int ret; | ||
37 | const struct firmware *fw; | ||
38 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
39 | |||
40 | if (!d->props->download_firmware) { | ||
41 | ret = -EINVAL; | ||
42 | goto err; | ||
43 | } | ||
44 | |||
45 | ret = request_firmware(&fw, name, &d->udev->dev); | ||
46 | if (ret < 0) { | ||
47 | dev_err(&d->udev->dev, "%s: Did not find the firmware file "\ | ||
48 | "'%s'. Please see linux/Documentation/dvb/ " \ | ||
49 | "for more details on firmware-problems. " \ | ||
50 | "Status %d\n", KBUILD_MODNAME, name, ret); | ||
51 | goto err; | ||
52 | } | ||
53 | |||
54 | dev_info(&d->udev->dev, "%s: downloading firmware from file '%s'\n", | ||
55 | KBUILD_MODNAME, name); | ||
56 | |||
57 | ret = d->props->download_firmware(d, fw); | ||
58 | release_firmware(fw); | ||
59 | if (ret < 0) | ||
60 | goto err; | ||
61 | |||
62 | return ret; | ||
63 | err: | ||
64 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | static int dvb_usbv2_i2c_init(struct dvb_usb_device *d) | ||
69 | { | ||
70 | int ret; | ||
71 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
72 | |||
73 | if (!d->props->i2c_algo) | ||
74 | return 0; | ||
75 | |||
76 | strlcpy(d->i2c_adap.name, d->name, sizeof(d->i2c_adap.name)); | ||
77 | d->i2c_adap.algo = d->props->i2c_algo; | ||
78 | d->i2c_adap.dev.parent = &d->udev->dev; | ||
79 | i2c_set_adapdata(&d->i2c_adap, d); | ||
80 | |||
81 | ret = i2c_add_adapter(&d->i2c_adap); | ||
82 | if (ret < 0) { | ||
83 | d->i2c_adap.algo = NULL; | ||
84 | dev_err(&d->udev->dev, "%s: i2c_add_adapter() failed=%d\n", | ||
85 | KBUILD_MODNAME, ret); | ||
86 | goto err; | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | err: | ||
91 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | static int dvb_usbv2_i2c_exit(struct dvb_usb_device *d) | ||
96 | { | ||
97 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
98 | |||
99 | if (d->i2c_adap.algo) | ||
100 | i2c_del_adapter(&d->i2c_adap); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static void dvb_usb_read_remote_control(struct work_struct *work) | ||
106 | { | ||
107 | struct dvb_usb_device *d = container_of(work, | ||
108 | struct dvb_usb_device, rc_query_work.work); | ||
109 | int ret; | ||
110 | |||
111 | /* | ||
112 | * When the parameter has been set to 1 via sysfs while the | ||
113 | * driver was running, or when bulk mode is enabled after IR init. | ||
114 | */ | ||
115 | if (dvb_usbv2_disable_rc_polling || d->rc.bulk_mode) | ||
116 | return; | ||
117 | |||
118 | ret = d->rc.query(d); | ||
119 | if (ret < 0) { | ||
120 | dev_err(&d->udev->dev, "%s: rc.query() failed=%d\n", | ||
121 | KBUILD_MODNAME, ret); | ||
122 | return; /* stop polling */ | ||
123 | } | ||
124 | |||
125 | schedule_delayed_work(&d->rc_query_work, | ||
126 | msecs_to_jiffies(d->rc.interval)); | ||
127 | } | ||
128 | |||
129 | static int dvb_usbv2_remote_init(struct dvb_usb_device *d) | ||
130 | { | ||
131 | int ret; | ||
132 | struct rc_dev *dev; | ||
133 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
134 | |||
135 | if (dvb_usbv2_disable_rc_polling || !d->props->get_rc_config) | ||
136 | return 0; | ||
137 | |||
138 | d->rc.map_name = d->rc_map; | ||
139 | ret = d->props->get_rc_config(d, &d->rc); | ||
140 | if (ret < 0) | ||
141 | goto err; | ||
142 | |||
143 | /* disable rc when there is no keymap defined */ | ||
144 | if (!d->rc.map_name) | ||
145 | return 0; | ||
146 | |||
147 | dev = rc_allocate_device(); | ||
148 | if (!dev) { | ||
149 | ret = -ENOMEM; | ||
150 | goto err; | ||
151 | } | ||
152 | |||
153 | dev->dev.parent = &d->udev->dev; | ||
154 | dev->input_name = d->name; | ||
155 | usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys)); | ||
156 | strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys)); | ||
157 | dev->input_phys = d->rc_phys; | ||
158 | usb_to_input_id(d->udev, &dev->input_id); | ||
159 | /* TODO: likely RC-core should took const char * */ | ||
160 | dev->driver_name = (char *) d->props->driver_name; | ||
161 | dev->map_name = d->rc.map_name; | ||
162 | dev->driver_type = d->rc.driver_type; | ||
163 | dev->allowed_protos = d->rc.allowed_protos; | ||
164 | dev->change_protocol = d->rc.change_protocol; | ||
165 | dev->priv = d; | ||
166 | |||
167 | ret = rc_register_device(dev); | ||
168 | if (ret < 0) { | ||
169 | rc_free_device(dev); | ||
170 | goto err; | ||
171 | } | ||
172 | |||
173 | d->rc_dev = dev; | ||
174 | |||
175 | /* start polling if needed */ | ||
176 | if (d->rc.query && !d->rc.bulk_mode) { | ||
177 | /* initialize a work queue for handling polling */ | ||
178 | INIT_DELAYED_WORK(&d->rc_query_work, | ||
179 | dvb_usb_read_remote_control); | ||
180 | dev_info(&d->udev->dev, "%s: schedule remote query interval " \ | ||
181 | "to %d msecs\n", KBUILD_MODNAME, | ||
182 | d->rc.interval); | ||
183 | schedule_delayed_work(&d->rc_query_work, | ||
184 | msecs_to_jiffies(d->rc.interval)); | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | err: | ||
189 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | static int dvb_usbv2_remote_exit(struct dvb_usb_device *d) | ||
194 | { | ||
195 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
196 | |||
197 | if (d->rc_dev) { | ||
198 | cancel_delayed_work_sync(&d->rc_query_work); | ||
199 | rc_unregister_device(d->rc_dev); | ||
200 | d->rc_dev = NULL; | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buf, | ||
207 | size_t len) | ||
208 | { | ||
209 | struct dvb_usb_adapter *adap = stream->user_priv; | ||
210 | dvb_dmx_swfilter(&adap->demux, buf, len); | ||
211 | } | ||
212 | |||
213 | static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buf, | ||
214 | size_t len) | ||
215 | { | ||
216 | struct dvb_usb_adapter *adap = stream->user_priv; | ||
217 | dvb_dmx_swfilter_204(&adap->demux, buf, len); | ||
218 | } | ||
219 | |||
220 | static void dvb_usb_data_complete_raw(struct usb_data_stream *stream, u8 *buf, | ||
221 | size_t len) | ||
222 | { | ||
223 | struct dvb_usb_adapter *adap = stream->user_priv; | ||
224 | dvb_dmx_swfilter_raw(&adap->demux, buf, len); | ||
225 | } | ||
226 | |||
227 | int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap) | ||
228 | { | ||
229 | dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, | ||
230 | adap->id); | ||
231 | |||
232 | adap->stream.udev = adap_to_d(adap)->udev; | ||
233 | adap->stream.user_priv = adap; | ||
234 | adap->stream.complete = dvb_usb_data_complete; | ||
235 | |||
236 | return usb_urb_initv2(&adap->stream, &adap->props->stream); | ||
237 | } | ||
238 | |||
239 | int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap) | ||
240 | { | ||
241 | dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, | ||
242 | adap->id); | ||
243 | |||
244 | return usb_urb_exitv2(&adap->stream); | ||
245 | } | ||
246 | |||
247 | static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, | ||
248 | int count) | ||
249 | { | ||
250 | struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; | ||
251 | struct dvb_usb_device *d = adap_to_d(adap); | ||
252 | int ret; | ||
253 | dev_dbg(&d->udev->dev, "%s: adap=%d active_fe=%d feed_type=%d " \ | ||
254 | "setting pid [%s]: %04x (%04d) at index %d '%s'\n", | ||
255 | __func__, adap->id, adap->active_fe, dvbdmxfeed->type, | ||
256 | adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid, | ||
257 | dvbdmxfeed->pid, dvbdmxfeed->index, | ||
258 | (count == 1) ? "on" : "off"); | ||
259 | |||
260 | if (adap->active_fe == -1) | ||
261 | return -EINVAL; | ||
262 | |||
263 | adap->feed_count += count; | ||
264 | |||
265 | /* stop feeding if it is last pid */ | ||
266 | if (adap->feed_count == 0) { | ||
267 | dev_dbg(&d->udev->dev, "%s: stop feeding\n", __func__); | ||
268 | usb_urb_killv2(&adap->stream); | ||
269 | |||
270 | if (d->props->streaming_ctrl) { | ||
271 | ret = d->props->streaming_ctrl( | ||
272 | adap->fe[adap->active_fe], 0); | ||
273 | if (ret < 0) { | ||
274 | dev_err(&d->udev->dev, "%s: streaming_ctrl() " \ | ||
275 | "failed=%d\n", KBUILD_MODNAME, | ||
276 | ret); | ||
277 | goto err_mutex_unlock; | ||
278 | } | ||
279 | } | ||
280 | mutex_unlock(&adap->sync_mutex); | ||
281 | } | ||
282 | |||
283 | /* activate the pid on the device pid filter */ | ||
284 | if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER && | ||
285 | adap->pid_filtering && | ||
286 | adap->props->pid_filter) | ||
287 | ret = adap->props->pid_filter(adap, dvbdmxfeed->index, | ||
288 | dvbdmxfeed->pid, (count == 1) ? 1 : 0); | ||
289 | if (ret < 0) | ||
290 | dev_err(&d->udev->dev, "%s: pid_filter() " \ | ||
291 | "failed=%d\n", KBUILD_MODNAME, | ||
292 | ret); | ||
293 | |||
294 | /* start feeding if it is first pid */ | ||
295 | if (adap->feed_count == 1 && count == 1) { | ||
296 | struct usb_data_stream_properties stream_props; | ||
297 | mutex_lock(&adap->sync_mutex); | ||
298 | dev_dbg(&d->udev->dev, "%s: start feeding\n", __func__); | ||
299 | |||
300 | /* resolve input and output streaming paramters */ | ||
301 | if (d->props->get_stream_config) { | ||
302 | memcpy(&stream_props, &adap->props->stream, | ||
303 | sizeof(struct usb_data_stream_properties)); | ||
304 | ret = d->props->get_stream_config( | ||
305 | adap->fe[adap->active_fe], | ||
306 | &adap->ts_type, &stream_props); | ||
307 | if (ret < 0) | ||
308 | goto err_mutex_unlock; | ||
309 | } else { | ||
310 | stream_props = adap->props->stream; | ||
311 | } | ||
312 | |||
313 | switch (adap->ts_type) { | ||
314 | case DVB_USB_FE_TS_TYPE_204: | ||
315 | adap->stream.complete = dvb_usb_data_complete_204; | ||
316 | break; | ||
317 | case DVB_USB_FE_TS_TYPE_RAW: | ||
318 | adap->stream.complete = dvb_usb_data_complete_raw; | ||
319 | break; | ||
320 | case DVB_USB_FE_TS_TYPE_188: | ||
321 | default: | ||
322 | adap->stream.complete = dvb_usb_data_complete; | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | usb_urb_submitv2(&adap->stream, &stream_props); | ||
327 | |||
328 | if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER && | ||
329 | adap->props->caps & | ||
330 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF && | ||
331 | adap->props->pid_filter_ctrl) { | ||
332 | ret = adap->props->pid_filter_ctrl(adap, | ||
333 | adap->pid_filtering); | ||
334 | if (ret < 0) { | ||
335 | dev_err(&d->udev->dev, "%s: " \ | ||
336 | "pid_filter_ctrl() failed=%d\n", | ||
337 | KBUILD_MODNAME, ret); | ||
338 | goto err_mutex_unlock; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | if (d->props->streaming_ctrl) { | ||
343 | ret = d->props->streaming_ctrl( | ||
344 | adap->fe[adap->active_fe], 1); | ||
345 | if (ret < 0) { | ||
346 | dev_err(&d->udev->dev, "%s: streaming_ctrl() " \ | ||
347 | "failed=%d\n", KBUILD_MODNAME, | ||
348 | ret); | ||
349 | goto err_mutex_unlock; | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | |||
354 | return 0; | ||
355 | err_mutex_unlock: | ||
356 | mutex_unlock(&adap->sync_mutex); | ||
357 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
358 | return ret; | ||
359 | } | ||
360 | |||
361 | static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
362 | { | ||
363 | return dvb_usb_ctrl_feed(dvbdmxfeed, 1); | ||
364 | } | ||
365 | |||
366 | static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
367 | { | ||
368 | return dvb_usb_ctrl_feed(dvbdmxfeed, -1); | ||
369 | } | ||
370 | |||
371 | int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap) | ||
372 | { | ||
373 | int ret; | ||
374 | struct dvb_usb_device *d = adap_to_d(adap); | ||
375 | dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); | ||
376 | |||
377 | ret = dvb_register_adapter(&adap->dvb_adap, d->name, d->props->owner, | ||
378 | &d->udev->dev, d->props->adapter_nr); | ||
379 | if (ret < 0) { | ||
380 | dev_dbg(&d->udev->dev, "%s: dvb_register_adapter() failed=%d\n", | ||
381 | __func__, ret); | ||
382 | goto err_dvb_register_adapter; | ||
383 | } | ||
384 | |||
385 | adap->dvb_adap.priv = adap; | ||
386 | |||
387 | if (d->props->read_mac_address) { | ||
388 | ret = d->props->read_mac_address(adap, | ||
389 | adap->dvb_adap.proposed_mac); | ||
390 | if (ret < 0) | ||
391 | goto err_dvb_dmx_init; | ||
392 | |||
393 | dev_info(&d->udev->dev, "%s: MAC address: %pM\n", | ||
394 | KBUILD_MODNAME, adap->dvb_adap.proposed_mac); | ||
395 | } | ||
396 | |||
397 | adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | ||
398 | adap->demux.priv = adap; | ||
399 | adap->demux.filternum = 0; | ||
400 | adap->demux.filternum = adap->max_feed_count; | ||
401 | adap->demux.feednum = adap->demux.filternum; | ||
402 | adap->demux.start_feed = dvb_usb_start_feed; | ||
403 | adap->demux.stop_feed = dvb_usb_stop_feed; | ||
404 | adap->demux.write_to_decoder = NULL; | ||
405 | ret = dvb_dmx_init(&adap->demux); | ||
406 | if (ret < 0) { | ||
407 | dev_err(&d->udev->dev, "%s: dvb_dmx_init() failed=%d\n", | ||
408 | KBUILD_MODNAME, ret); | ||
409 | goto err_dvb_dmx_init; | ||
410 | } | ||
411 | |||
412 | adap->dmxdev.filternum = adap->demux.filternum; | ||
413 | adap->dmxdev.demux = &adap->demux.dmx; | ||
414 | adap->dmxdev.capabilities = 0; | ||
415 | ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap); | ||
416 | if (ret < 0) { | ||
417 | dev_err(&d->udev->dev, "%s: dvb_dmxdev_init() failed=%d\n", | ||
418 | KBUILD_MODNAME, ret); | ||
419 | goto err_dvb_dmxdev_init; | ||
420 | } | ||
421 | |||
422 | ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx); | ||
423 | if (ret < 0) { | ||
424 | dev_err(&d->udev->dev, "%s: dvb_net_init() failed=%d\n", | ||
425 | KBUILD_MODNAME, ret); | ||
426 | goto err_dvb_net_init; | ||
427 | } | ||
428 | |||
429 | mutex_init(&adap->sync_mutex); | ||
430 | |||
431 | return 0; | ||
432 | err_dvb_net_init: | ||
433 | dvb_dmxdev_release(&adap->dmxdev); | ||
434 | err_dvb_dmxdev_init: | ||
435 | dvb_dmx_release(&adap->demux); | ||
436 | err_dvb_dmx_init: | ||
437 | dvb_unregister_adapter(&adap->dvb_adap); | ||
438 | err_dvb_register_adapter: | ||
439 | adap->dvb_adap.priv = NULL; | ||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap) | ||
444 | { | ||
445 | dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, | ||
446 | adap->id); | ||
447 | |||
448 | if (adap->dvb_adap.priv) { | ||
449 | dvb_net_release(&adap->dvb_net); | ||
450 | adap->demux.dmx.close(&adap->demux.dmx); | ||
451 | dvb_dmxdev_release(&adap->dmxdev); | ||
452 | dvb_dmx_release(&adap->demux); | ||
453 | dvb_unregister_adapter(&adap->dvb_adap); | ||
454 | } | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
460 | { | ||
461 | int ret; | ||
462 | |||
463 | if (onoff) | ||
464 | d->powered++; | ||
465 | else | ||
466 | d->powered--; | ||
467 | |||
468 | if (d->powered == 0 || (onoff && d->powered == 1)) { | ||
469 | /* when switching from 1 to 0 or from 0 to 1 */ | ||
470 | dev_dbg(&d->udev->dev, "%s: power=%d\n", __func__, onoff); | ||
471 | if (d->props->power_ctrl) { | ||
472 | ret = d->props->power_ctrl(d, onoff); | ||
473 | if (ret < 0) | ||
474 | goto err; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | return 0; | ||
479 | err: | ||
480 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
481 | return ret; | ||
482 | } | ||
483 | |||
484 | static int dvb_usb_fe_init(struct dvb_frontend *fe) | ||
485 | { | ||
486 | int ret; | ||
487 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
488 | struct dvb_usb_device *d = adap_to_d(adap); | ||
489 | mutex_lock(&adap->sync_mutex); | ||
490 | dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, | ||
491 | fe->id); | ||
492 | |||
493 | ret = dvb_usbv2_device_power_ctrl(d, 1); | ||
494 | if (ret < 0) | ||
495 | goto err; | ||
496 | |||
497 | if (d->props->frontend_ctrl) { | ||
498 | ret = d->props->frontend_ctrl(fe, 1); | ||
499 | if (ret < 0) | ||
500 | goto err; | ||
501 | } | ||
502 | |||
503 | if (adap->fe_init[fe->id]) { | ||
504 | ret = adap->fe_init[fe->id](fe); | ||
505 | if (ret < 0) | ||
506 | goto err; | ||
507 | } | ||
508 | |||
509 | adap->active_fe = fe->id; | ||
510 | mutex_unlock(&adap->sync_mutex); | ||
511 | |||
512 | return 0; | ||
513 | err: | ||
514 | mutex_unlock(&adap->sync_mutex); | ||
515 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | static int dvb_usb_fe_sleep(struct dvb_frontend *fe) | ||
520 | { | ||
521 | int ret; | ||
522 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
523 | struct dvb_usb_device *d = adap_to_d(adap); | ||
524 | mutex_lock(&adap->sync_mutex); | ||
525 | dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id, | ||
526 | fe->id); | ||
527 | |||
528 | if (adap->fe_sleep[fe->id]) { | ||
529 | ret = adap->fe_sleep[fe->id](fe); | ||
530 | if (ret < 0) | ||
531 | goto err; | ||
532 | } | ||
533 | |||
534 | if (d->props->frontend_ctrl) { | ||
535 | ret = d->props->frontend_ctrl(fe, 0); | ||
536 | if (ret < 0) | ||
537 | goto err; | ||
538 | } | ||
539 | |||
540 | ret = dvb_usbv2_device_power_ctrl(d, 0); | ||
541 | if (ret < 0) | ||
542 | goto err; | ||
543 | |||
544 | adap->active_fe = -1; | ||
545 | mutex_unlock(&adap->sync_mutex); | ||
546 | |||
547 | return 0; | ||
548 | err: | ||
549 | mutex_unlock(&adap->sync_mutex); | ||
550 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap) | ||
555 | { | ||
556 | int ret, i, count_registered = 0; | ||
557 | struct dvb_usb_device *d = adap_to_d(adap); | ||
558 | dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); | ||
559 | |||
560 | memset(adap->fe, 0, sizeof(adap->fe)); | ||
561 | adap->active_fe = -1; | ||
562 | |||
563 | if (d->props->frontend_attach) { | ||
564 | ret = d->props->frontend_attach(adap); | ||
565 | if (ret < 0) { | ||
566 | dev_dbg(&d->udev->dev, "%s: frontend_attach() " \ | ||
567 | "failed=%d\n", __func__, ret); | ||
568 | goto err_dvb_frontend_detach; | ||
569 | } | ||
570 | } else { | ||
571 | dev_dbg(&d->udev->dev, "%s: frontend_attach() do not exists\n", | ||
572 | __func__); | ||
573 | ret = 0; | ||
574 | goto err; | ||
575 | } | ||
576 | |||
577 | for (i = 0; i < MAX_NO_OF_FE_PER_ADAP && adap->fe[i]; i++) { | ||
578 | adap->fe[i]->id = i; | ||
579 | /* re-assign sleep and wakeup functions */ | ||
580 | adap->fe_init[i] = adap->fe[i]->ops.init; | ||
581 | adap->fe[i]->ops.init = dvb_usb_fe_init; | ||
582 | adap->fe_sleep[i] = adap->fe[i]->ops.sleep; | ||
583 | adap->fe[i]->ops.sleep = dvb_usb_fe_sleep; | ||
584 | |||
585 | ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]); | ||
586 | if (ret < 0) { | ||
587 | dev_err(&d->udev->dev, "%s: frontend%d registration " \ | ||
588 | "failed\n", KBUILD_MODNAME, i); | ||
589 | goto err_dvb_unregister_frontend; | ||
590 | } | ||
591 | |||
592 | count_registered++; | ||
593 | } | ||
594 | |||
595 | if (d->props->tuner_attach) { | ||
596 | ret = d->props->tuner_attach(adap); | ||
597 | if (ret < 0) { | ||
598 | dev_dbg(&d->udev->dev, "%s: tuner_attach() failed=%d\n", | ||
599 | __func__, ret); | ||
600 | goto err_dvb_unregister_frontend; | ||
601 | } | ||
602 | } | ||
603 | |||
604 | return 0; | ||
605 | |||
606 | err_dvb_unregister_frontend: | ||
607 | for (i = count_registered - 1; i >= 0; i--) | ||
608 | dvb_unregister_frontend(adap->fe[i]); | ||
609 | |||
610 | err_dvb_frontend_detach: | ||
611 | for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) { | ||
612 | if (adap->fe[i]) | ||
613 | dvb_frontend_detach(adap->fe[i]); | ||
614 | } | ||
615 | |||
616 | err: | ||
617 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap) | ||
622 | { | ||
623 | int i; | ||
624 | dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__, | ||
625 | adap->id); | ||
626 | |||
627 | for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) { | ||
628 | if (adap->fe[i]) { | ||
629 | dvb_unregister_frontend(adap->fe[i]); | ||
630 | dvb_frontend_detach(adap->fe[i]); | ||
631 | } | ||
632 | } | ||
633 | |||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int dvb_usbv2_adapter_init(struct dvb_usb_device *d) | ||
638 | { | ||
639 | struct dvb_usb_adapter *adap; | ||
640 | int ret, i, adapter_count; | ||
641 | |||
642 | /* resolve adapter count */ | ||
643 | adapter_count = d->props->num_adapters; | ||
644 | if (d->props->get_adapter_count) { | ||
645 | ret = d->props->get_adapter_count(d); | ||
646 | if (ret < 0) | ||
647 | goto err; | ||
648 | |||
649 | adapter_count = ret; | ||
650 | } | ||
651 | |||
652 | for (i = 0; i < adapter_count; i++) { | ||
653 | adap = &d->adapter[i]; | ||
654 | adap->id = i; | ||
655 | adap->props = &d->props->adapter[i]; | ||
656 | |||
657 | /* speed - when running at FULL speed we need a HW PID filter */ | ||
658 | if (d->udev->speed == USB_SPEED_FULL && | ||
659 | !(adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) { | ||
660 | dev_err(&d->udev->dev, "%s: this USB2.0 device " \ | ||
661 | "cannot be run on a USB1.1 port (it " \ | ||
662 | "lacks a hardware PID filter)\n", | ||
663 | KBUILD_MODNAME); | ||
664 | ret = -ENODEV; | ||
665 | goto err; | ||
666 | } else if ((d->udev->speed == USB_SPEED_FULL && | ||
667 | adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) || | ||
668 | (adap->props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) { | ||
669 | dev_info(&d->udev->dev, "%s: will use the device's " \ | ||
670 | "hardware PID filter " \ | ||
671 | "(table count: %d)\n", KBUILD_MODNAME, | ||
672 | adap->props->pid_filter_count); | ||
673 | adap->pid_filtering = 1; | ||
674 | adap->max_feed_count = adap->props->pid_filter_count; | ||
675 | } else { | ||
676 | dev_info(&d->udev->dev, "%s: will pass the complete " \ | ||
677 | "MPEG2 transport stream to the " \ | ||
678 | "software demuxer\n", KBUILD_MODNAME); | ||
679 | adap->pid_filtering = 0; | ||
680 | adap->max_feed_count = 255; | ||
681 | } | ||
682 | |||
683 | if (!adap->pid_filtering && dvb_usb_force_pid_filter_usage && | ||
684 | adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) { | ||
685 | dev_info(&d->udev->dev, "%s: PID filter enabled by " \ | ||
686 | "module option\n", KBUILD_MODNAME); | ||
687 | adap->pid_filtering = 1; | ||
688 | adap->max_feed_count = adap->props->pid_filter_count; | ||
689 | } | ||
690 | |||
691 | ret = dvb_usbv2_adapter_stream_init(adap); | ||
692 | if (ret) | ||
693 | goto err; | ||
694 | |||
695 | ret = dvb_usbv2_adapter_dvb_init(adap); | ||
696 | if (ret) | ||
697 | goto err; | ||
698 | |||
699 | ret = dvb_usbv2_adapter_frontend_init(adap); | ||
700 | if (ret) | ||
701 | goto err; | ||
702 | |||
703 | /* use exclusive FE lock if there is multiple shared FEs */ | ||
704 | if (adap->fe[1]) | ||
705 | adap->dvb_adap.mfe_shared = 1; | ||
706 | } | ||
707 | |||
708 | return 0; | ||
709 | err: | ||
710 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
711 | return ret; | ||
712 | } | ||
713 | |||
714 | static int dvb_usbv2_adapter_exit(struct dvb_usb_device *d) | ||
715 | { | ||
716 | int i; | ||
717 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
718 | |||
719 | for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { | ||
720 | if (d->adapter[i].props) { | ||
721 | dvb_usbv2_adapter_frontend_exit(&d->adapter[i]); | ||
722 | dvb_usbv2_adapter_dvb_exit(&d->adapter[i]); | ||
723 | dvb_usbv2_adapter_stream_exit(&d->adapter[i]); | ||
724 | } | ||
725 | } | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | /* general initialization functions */ | ||
731 | static int dvb_usbv2_exit(struct dvb_usb_device *d) | ||
732 | { | ||
733 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
734 | |||
735 | dvb_usbv2_remote_exit(d); | ||
736 | dvb_usbv2_adapter_exit(d); | ||
737 | dvb_usbv2_i2c_exit(d); | ||
738 | kfree(d->priv); | ||
739 | kfree(d); | ||
740 | |||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static int dvb_usbv2_init(struct dvb_usb_device *d) | ||
745 | { | ||
746 | int ret; | ||
747 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
748 | |||
749 | dvb_usbv2_device_power_ctrl(d, 1); | ||
750 | |||
751 | if (d->props->read_config) { | ||
752 | ret = d->props->read_config(d); | ||
753 | if (ret < 0) | ||
754 | goto err; | ||
755 | } | ||
756 | |||
757 | ret = dvb_usbv2_i2c_init(d); | ||
758 | if (ret < 0) | ||
759 | goto err; | ||
760 | |||
761 | ret = dvb_usbv2_adapter_init(d); | ||
762 | if (ret < 0) | ||
763 | goto err; | ||
764 | |||
765 | if (d->props->init) { | ||
766 | ret = d->props->init(d); | ||
767 | if (ret < 0) | ||
768 | goto err; | ||
769 | } | ||
770 | |||
771 | ret = dvb_usbv2_remote_init(d); | ||
772 | if (ret < 0) | ||
773 | goto err; | ||
774 | |||
775 | dvb_usbv2_device_power_ctrl(d, 0); | ||
776 | |||
777 | return 0; | ||
778 | err: | ||
779 | dvb_usbv2_device_power_ctrl(d, 0); | ||
780 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
781 | return ret; | ||
782 | } | ||
783 | |||
784 | /* | ||
785 | * udev, which is used for the firmware downloading, requires we cannot | ||
786 | * block during module_init(). module_init() calls USB probe() which | ||
787 | * is this routine. Due to that we delay actual operation using workqueue | ||
788 | * and return always success here. | ||
789 | */ | ||
790 | static void dvb_usbv2_init_work(struct work_struct *work) | ||
791 | { | ||
792 | int ret; | ||
793 | struct dvb_usb_device *d = | ||
794 | container_of(work, struct dvb_usb_device, probe_work); | ||
795 | |||
796 | d->work_pid = current->pid; | ||
797 | dev_dbg(&d->udev->dev, "%s: work_pid=%d\n", __func__, d->work_pid); | ||
798 | |||
799 | if (d->props->size_of_priv) { | ||
800 | d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL); | ||
801 | if (!d->priv) { | ||
802 | dev_err(&d->udev->dev, "%s: kzalloc() failed\n", | ||
803 | KBUILD_MODNAME); | ||
804 | ret = -ENOMEM; | ||
805 | goto err_usb_driver_release_interface; | ||
806 | } | ||
807 | } | ||
808 | |||
809 | if (d->props->identify_state) { | ||
810 | const char *name = NULL; | ||
811 | ret = d->props->identify_state(d, &name); | ||
812 | if (ret == 0) { | ||
813 | ; | ||
814 | } else if (ret == COLD) { | ||
815 | dev_info(&d->udev->dev, "%s: found a '%s' in cold " \ | ||
816 | "state\n", KBUILD_MODNAME, d->name); | ||
817 | |||
818 | if (!name) | ||
819 | name = d->props->firmware; | ||
820 | |||
821 | ret = dvb_usbv2_download_firmware(d, name); | ||
822 | if (ret == 0) { | ||
823 | /* device is warm, continue initialization */ | ||
824 | ; | ||
825 | } else if (ret == RECONNECTS_USB) { | ||
826 | /* | ||
827 | * USB core will call disconnect() and then | ||
828 | * probe() as device reconnects itself from the | ||
829 | * USB bus. disconnect() will release all driver | ||
830 | * resources and probe() is called for 'new' | ||
831 | * device. As 'new' device is warm we should | ||
832 | * never go here again. | ||
833 | */ | ||
834 | return; | ||
835 | } else { | ||
836 | /* | ||
837 | * Unexpected error. We must unregister driver | ||
838 | * manually from the device, because device is | ||
839 | * already register by returning from probe() | ||
840 | * with success. usb_driver_release_interface() | ||
841 | * finally calls disconnect() in order to free | ||
842 | * resources. | ||
843 | */ | ||
844 | goto err_usb_driver_release_interface; | ||
845 | } | ||
846 | } else { | ||
847 | goto err_usb_driver_release_interface; | ||
848 | } | ||
849 | } | ||
850 | |||
851 | dev_info(&d->udev->dev, "%s: found a '%s' in warm state\n", | ||
852 | KBUILD_MODNAME, d->name); | ||
853 | |||
854 | ret = dvb_usbv2_init(d); | ||
855 | if (ret < 0) | ||
856 | goto err_usb_driver_release_interface; | ||
857 | |||
858 | dev_info(&d->udev->dev, "%s: '%s' successfully initialized and " \ | ||
859 | "connected\n", KBUILD_MODNAME, d->name); | ||
860 | |||
861 | return; | ||
862 | err_usb_driver_release_interface: | ||
863 | dev_info(&d->udev->dev, "%s: '%s' error while loading driver (%d)\n", | ||
864 | KBUILD_MODNAME, d->name, ret); | ||
865 | usb_driver_release_interface(to_usb_driver(d->intf->dev.driver), | ||
866 | d->intf); | ||
867 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
868 | return; | ||
869 | } | ||
870 | |||
871 | int dvb_usbv2_probe(struct usb_interface *intf, | ||
872 | const struct usb_device_id *id) | ||
873 | { | ||
874 | int ret; | ||
875 | struct dvb_usb_device *d; | ||
876 | struct usb_device *udev = interface_to_usbdev(intf); | ||
877 | struct dvb_usb_driver_info *driver_info = | ||
878 | (struct dvb_usb_driver_info *) id->driver_info; | ||
879 | |||
880 | dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__, | ||
881 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
882 | |||
883 | if (!id->driver_info) { | ||
884 | dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME); | ||
885 | ret = -ENODEV; | ||
886 | goto err; | ||
887 | } | ||
888 | |||
889 | d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL); | ||
890 | if (!d) { | ||
891 | dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); | ||
892 | ret = -ENOMEM; | ||
893 | goto err; | ||
894 | } | ||
895 | |||
896 | d->name = driver_info->name; | ||
897 | d->rc_map = driver_info->rc_map; | ||
898 | d->udev = udev; | ||
899 | d->intf = intf; | ||
900 | d->props = driver_info->props; | ||
901 | |||
902 | if (d->intf->cur_altsetting->desc.bInterfaceNumber != | ||
903 | d->props->bInterfaceNumber) { | ||
904 | ret = -ENODEV; | ||
905 | goto err_kfree; | ||
906 | } | ||
907 | |||
908 | mutex_init(&d->usb_mutex); | ||
909 | mutex_init(&d->i2c_mutex); | ||
910 | INIT_WORK(&d->probe_work, dvb_usbv2_init_work); | ||
911 | usb_set_intfdata(intf, d); | ||
912 | ret = schedule_work(&d->probe_work); | ||
913 | if (ret < 0) { | ||
914 | dev_err(&d->udev->dev, "%s: schedule_work() failed\n", | ||
915 | KBUILD_MODNAME); | ||
916 | goto err_kfree; | ||
917 | } | ||
918 | |||
919 | return 0; | ||
920 | err_kfree: | ||
921 | kfree(d); | ||
922 | err: | ||
923 | dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret); | ||
924 | return ret; | ||
925 | } | ||
926 | EXPORT_SYMBOL(dvb_usbv2_probe); | ||
927 | |||
928 | void dvb_usbv2_disconnect(struct usb_interface *intf) | ||
929 | { | ||
930 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
931 | const char *name = d->name; | ||
932 | struct device dev = d->udev->dev; | ||
933 | dev_dbg(&d->udev->dev, "%s: pid=%d work_pid=%d\n", __func__, | ||
934 | current->pid, d->work_pid); | ||
935 | |||
936 | /* ensure initialization work is finished until release resources */ | ||
937 | if (d->work_pid != current->pid) | ||
938 | cancel_work_sync(&d->probe_work); | ||
939 | |||
940 | if (d->props->exit) | ||
941 | d->props->exit(d); | ||
942 | |||
943 | dvb_usbv2_exit(d); | ||
944 | |||
945 | dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n", | ||
946 | KBUILD_MODNAME, name); | ||
947 | } | ||
948 | EXPORT_SYMBOL(dvb_usbv2_disconnect); | ||
949 | |||
950 | int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg) | ||
951 | { | ||
952 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
953 | int i; | ||
954 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
955 | |||
956 | /* stop remote controller poll */ | ||
957 | if (d->rc.query && !d->rc.bulk_mode) | ||
958 | cancel_delayed_work_sync(&d->rc_query_work); | ||
959 | |||
960 | /* stop streaming */ | ||
961 | for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) { | ||
962 | if (d->adapter[i].dvb_adap.priv && | ||
963 | d->adapter[i].active_fe != -1) | ||
964 | usb_urb_killv2(&d->adapter[i].stream); | ||
965 | } | ||
966 | |||
967 | return 0; | ||
968 | } | ||
969 | EXPORT_SYMBOL(dvb_usbv2_suspend); | ||
970 | |||
971 | int dvb_usbv2_resume(struct usb_interface *intf) | ||
972 | { | ||
973 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
974 | int i; | ||
975 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
976 | |||
977 | /* start streaming */ | ||
978 | for (i = 0; i < MAX_NO_OF_ADAPTER_PER_DEVICE; i++) { | ||
979 | if (d->adapter[i].dvb_adap.priv && | ||
980 | d->adapter[i].active_fe != -1) | ||
981 | usb_urb_submitv2(&d->adapter[i].stream, NULL); | ||
982 | } | ||
983 | |||
984 | /* start remote controller poll */ | ||
985 | if (d->rc.query && !d->rc.bulk_mode) | ||
986 | schedule_delayed_work(&d->rc_query_work, | ||
987 | msecs_to_jiffies(d->rc.interval)); | ||
988 | |||
989 | return 0; | ||
990 | } | ||
991 | EXPORT_SYMBOL(dvb_usbv2_resume); | ||
992 | |||
993 | MODULE_VERSION("2.0"); | ||
994 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
995 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
996 | MODULE_DESCRIPTION("DVB USB common"); | ||
997 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c new file mode 100644 index 000000000000..0431beed0ef4 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * DVB USB framework | ||
3 | * | ||
4 | * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de> | ||
5 | * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | |||
22 | #include "dvb_usb_common.h" | ||
23 | |||
24 | int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, | ||
25 | u16 rlen) | ||
26 | { | ||
27 | int ret, actual_length; | ||
28 | |||
29 | if (!d || !wbuf || !wlen || !d->props->generic_bulk_ctrl_endpoint || | ||
30 | !d->props->generic_bulk_ctrl_endpoint_response) { | ||
31 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, -EINVAL); | ||
32 | return -EINVAL; | ||
33 | } | ||
34 | |||
35 | ret = mutex_lock_interruptible(&d->usb_mutex); | ||
36 | if (ret < 0) | ||
37 | return ret; | ||
38 | |||
39 | dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf); | ||
40 | |||
41 | ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev, | ||
42 | d->props->generic_bulk_ctrl_endpoint), wbuf, wlen, | ||
43 | &actual_length, 2000); | ||
44 | if (ret < 0) | ||
45 | dev_err(&d->udev->dev, "%s: usb_bulk_msg() failed=%d\n", | ||
46 | KBUILD_MODNAME, ret); | ||
47 | else | ||
48 | ret = actual_length != wlen ? -EIO : 0; | ||
49 | |||
50 | /* an answer is expected, and no error before */ | ||
51 | if (!ret && rbuf && rlen) { | ||
52 | if (d->props->generic_bulk_ctrl_delay) | ||
53 | usleep_range(d->props->generic_bulk_ctrl_delay, | ||
54 | d->props->generic_bulk_ctrl_delay | ||
55 | + 20000); | ||
56 | |||
57 | ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, | ||
58 | d->props->generic_bulk_ctrl_endpoint_response), | ||
59 | rbuf, rlen, &actual_length, 2000); | ||
60 | if (ret) | ||
61 | dev_err(&d->udev->dev, "%s: 2nd usb_bulk_msg() " \ | ||
62 | "failed=%d\n", KBUILD_MODNAME, ret); | ||
63 | |||
64 | dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__, | ||
65 | actual_length, rbuf); | ||
66 | } | ||
67 | |||
68 | mutex_unlock(&d->usb_mutex); | ||
69 | return ret; | ||
70 | } | ||
71 | EXPORT_SYMBOL(dvb_usbv2_generic_rw); | ||
72 | |||
73 | int dvb_usbv2_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len) | ||
74 | { | ||
75 | return dvb_usbv2_generic_rw(d, buf, len, NULL, 0); | ||
76 | } | ||
77 | EXPORT_SYMBOL(dvb_usbv2_generic_write); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/ec168.c b/drivers/media/usb/dvb-usb-v2/ec168.c new file mode 100644 index 000000000000..ab77622c383d --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/ec168.c | |||
@@ -0,0 +1,376 @@ | |||
1 | /* | ||
2 | * E3C EC168 DVB USB driver | ||
3 | * | ||
4 | * Copyright (C) 2009 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 | */ | ||
21 | |||
22 | #include "ec168.h" | ||
23 | #include "ec100.h" | ||
24 | #include "mxl5005s.h" | ||
25 | |||
26 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
27 | |||
28 | static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req) | ||
29 | { | ||
30 | int ret; | ||
31 | unsigned int pipe; | ||
32 | u8 request, requesttype; | ||
33 | u8 *buf; | ||
34 | |||
35 | switch (req->cmd) { | ||
36 | case DOWNLOAD_FIRMWARE: | ||
37 | case GPIO: | ||
38 | case WRITE_I2C: | ||
39 | case STREAMING_CTRL: | ||
40 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | ||
41 | request = req->cmd; | ||
42 | break; | ||
43 | case READ_I2C: | ||
44 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | ||
45 | request = req->cmd; | ||
46 | break; | ||
47 | case GET_CONFIG: | ||
48 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | ||
49 | request = CONFIG; | ||
50 | break; | ||
51 | case SET_CONFIG: | ||
52 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | ||
53 | request = CONFIG; | ||
54 | break; | ||
55 | case WRITE_DEMOD: | ||
56 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | ||
57 | request = DEMOD_RW; | ||
58 | break; | ||
59 | case READ_DEMOD: | ||
60 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | ||
61 | request = DEMOD_RW; | ||
62 | break; | ||
63 | default: | ||
64 | pr_err("%s: unknown command=%02x\n", KBUILD_MODNAME, req->cmd); | ||
65 | ret = -EINVAL; | ||
66 | goto error; | ||
67 | } | ||
68 | |||
69 | buf = kmalloc(req->size, GFP_KERNEL); | ||
70 | if (!buf) { | ||
71 | ret = -ENOMEM; | ||
72 | goto error; | ||
73 | } | ||
74 | |||
75 | if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) { | ||
76 | /* write */ | ||
77 | memcpy(buf, req->data, req->size); | ||
78 | pipe = usb_sndctrlpipe(d->udev, 0); | ||
79 | } else { | ||
80 | /* read */ | ||
81 | pipe = usb_rcvctrlpipe(d->udev, 0); | ||
82 | } | ||
83 | |||
84 | msleep(1); /* avoid I2C errors */ | ||
85 | |||
86 | ret = usb_control_msg(d->udev, pipe, request, requesttype, req->value, | ||
87 | req->index, buf, req->size, EC168_USB_TIMEOUT); | ||
88 | |||
89 | ec168_debug_dump(request, requesttype, req->value, req->index, buf, | ||
90 | req->size); | ||
91 | |||
92 | if (ret < 0) | ||
93 | goto err_dealloc; | ||
94 | else | ||
95 | ret = 0; | ||
96 | |||
97 | /* read request, copy returned data to return buf */ | ||
98 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) | ||
99 | memcpy(req->data, buf, req->size); | ||
100 | |||
101 | kfree(buf); | ||
102 | return ret; | ||
103 | |||
104 | err_dealloc: | ||
105 | kfree(buf); | ||
106 | error: | ||
107 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | /* I2C */ | ||
112 | static struct ec100_config ec168_ec100_config; | ||
113 | |||
114 | static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
115 | int num) | ||
116 | { | ||
117 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
118 | struct ec168_req req; | ||
119 | int i = 0; | ||
120 | int ret; | ||
121 | |||
122 | if (num > 2) | ||
123 | return -EINVAL; | ||
124 | |||
125 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
126 | return -EAGAIN; | ||
127 | |||
128 | while (i < num) { | ||
129 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | ||
130 | if (msg[i].addr == ec168_ec100_config.demod_address) { | ||
131 | req.cmd = READ_DEMOD; | ||
132 | req.value = 0; | ||
133 | req.index = 0xff00 + msg[i].buf[0]; /* reg */ | ||
134 | req.size = msg[i+1].len; /* bytes to read */ | ||
135 | req.data = &msg[i+1].buf[0]; | ||
136 | ret = ec168_ctrl_msg(d, &req); | ||
137 | i += 2; | ||
138 | } else { | ||
139 | pr_err("%s: I2C read not implemented\n", | ||
140 | KBUILD_MODNAME); | ||
141 | ret = -EOPNOTSUPP; | ||
142 | i += 2; | ||
143 | } | ||
144 | } else { | ||
145 | if (msg[i].addr == ec168_ec100_config.demod_address) { | ||
146 | req.cmd = WRITE_DEMOD; | ||
147 | req.value = msg[i].buf[1]; /* val */ | ||
148 | req.index = 0xff00 + msg[i].buf[0]; /* reg */ | ||
149 | req.size = 0; | ||
150 | req.data = NULL; | ||
151 | ret = ec168_ctrl_msg(d, &req); | ||
152 | i += 1; | ||
153 | } else { | ||
154 | req.cmd = WRITE_I2C; | ||
155 | req.value = msg[i].buf[0]; /* val */ | ||
156 | req.index = 0x0100 + msg[i].addr; /* I2C addr */ | ||
157 | req.size = msg[i].len-1; | ||
158 | req.data = &msg[i].buf[1]; | ||
159 | ret = ec168_ctrl_msg(d, &req); | ||
160 | i += 1; | ||
161 | } | ||
162 | } | ||
163 | if (ret) | ||
164 | goto error; | ||
165 | |||
166 | } | ||
167 | ret = i; | ||
168 | |||
169 | error: | ||
170 | mutex_unlock(&d->i2c_mutex); | ||
171 | return i; | ||
172 | } | ||
173 | |||
174 | static u32 ec168_i2c_func(struct i2c_adapter *adapter) | ||
175 | { | ||
176 | return I2C_FUNC_I2C; | ||
177 | } | ||
178 | |||
179 | static struct i2c_algorithm ec168_i2c_algo = { | ||
180 | .master_xfer = ec168_i2c_xfer, | ||
181 | .functionality = ec168_i2c_func, | ||
182 | }; | ||
183 | |||
184 | /* Callbacks for DVB USB */ | ||
185 | static int ec168_identify_state(struct dvb_usb_device *d, const char **name) | ||
186 | { | ||
187 | int ret; | ||
188 | u8 reply; | ||
189 | struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply}; | ||
190 | pr_debug("%s:\n", __func__); | ||
191 | |||
192 | ret = ec168_ctrl_msg(d, &req); | ||
193 | if (ret) | ||
194 | goto error; | ||
195 | |||
196 | pr_debug("%s: reply=%02x\n", __func__, reply); | ||
197 | |||
198 | if (reply == 0x01) | ||
199 | ret = WARM; | ||
200 | else | ||
201 | ret = COLD; | ||
202 | |||
203 | return ret; | ||
204 | error: | ||
205 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | static int ec168_download_firmware(struct dvb_usb_device *d, | ||
210 | const struct firmware *fw) | ||
211 | { | ||
212 | int ret, len, remaining; | ||
213 | struct ec168_req req = {DOWNLOAD_FIRMWARE, 0, 0, 0, NULL}; | ||
214 | pr_debug("%s:\n", __func__); | ||
215 | |||
216 | #define LEN_MAX 2048 /* max packet size */ | ||
217 | for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) { | ||
218 | len = remaining; | ||
219 | if (len > LEN_MAX) | ||
220 | len = LEN_MAX; | ||
221 | |||
222 | req.size = len; | ||
223 | req.data = (u8 *) &fw->data[fw->size - remaining]; | ||
224 | req.index = fw->size - remaining; | ||
225 | |||
226 | ret = ec168_ctrl_msg(d, &req); | ||
227 | if (ret) { | ||
228 | pr_err("%s: firmware download failed=%d\n", | ||
229 | KBUILD_MODNAME, ret); | ||
230 | goto error; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | req.size = 0; | ||
235 | |||
236 | /* set "warm"? */ | ||
237 | req.cmd = SET_CONFIG; | ||
238 | req.value = 0; | ||
239 | req.index = 0x0001; | ||
240 | ret = ec168_ctrl_msg(d, &req); | ||
241 | if (ret) | ||
242 | goto error; | ||
243 | |||
244 | /* really needed - no idea what does */ | ||
245 | req.cmd = GPIO; | ||
246 | req.value = 0; | ||
247 | req.index = 0x0206; | ||
248 | ret = ec168_ctrl_msg(d, &req); | ||
249 | if (ret) | ||
250 | goto error; | ||
251 | |||
252 | /* activate tuner I2C? */ | ||
253 | req.cmd = WRITE_I2C; | ||
254 | req.value = 0; | ||
255 | req.index = 0x00c6; | ||
256 | ret = ec168_ctrl_msg(d, &req); | ||
257 | if (ret) | ||
258 | goto error; | ||
259 | |||
260 | return ret; | ||
261 | error: | ||
262 | pr_debug("%s: failed=%d\n", __func__, ret); | ||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | static struct ec100_config ec168_ec100_config = { | ||
267 | .demod_address = 0xff, /* not real address, demod is integrated */ | ||
268 | }; | ||
269 | |||
270 | static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap) | ||
271 | { | ||
272 | pr_debug("%s:\n", __func__); | ||
273 | adap->fe[0] = dvb_attach(ec100_attach, &ec168_ec100_config, | ||
274 | &adap_to_d(adap)->i2c_adap); | ||
275 | if (adap->fe[0] == NULL) | ||
276 | return -ENODEV; | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static struct mxl5005s_config ec168_mxl5003s_config = { | ||
282 | .i2c_address = 0xc6, | ||
283 | .if_freq = IF_FREQ_4570000HZ, | ||
284 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
285 | .agc_mode = MXL_SINGLE_AGC, | ||
286 | .tracking_filter = MXL_TF_OFF, | ||
287 | .rssi_enable = MXL_RSSI_ENABLE, | ||
288 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
289 | .div_out = MXL_DIV_OUT_4, | ||
290 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
291 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
292 | .top = MXL5005S_TOP_25P2, | ||
293 | .mod_mode = MXL_DIGITAL_MODE, | ||
294 | .if_mode = MXL_ZERO_IF, | ||
295 | .AgcMasterByte = 0x00, | ||
296 | }; | ||
297 | |||
298 | static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap) | ||
299 | { | ||
300 | pr_debug("%s:\n", __func__); | ||
301 | return dvb_attach(mxl5005s_attach, adap->fe[0], | ||
302 | &adap_to_d(adap)->i2c_adap, | ||
303 | &ec168_mxl5003s_config) == NULL ? -ENODEV : 0; | ||
304 | } | ||
305 | |||
306 | static int ec168_streaming_ctrl(struct dvb_frontend *fe, int onoff) | ||
307 | { | ||
308 | struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL}; | ||
309 | pr_debug("%s: onoff=%d\n", __func__, onoff); | ||
310 | if (onoff) | ||
311 | req.index = 0x0102; | ||
312 | return ec168_ctrl_msg(fe_to_d(fe), &req); | ||
313 | } | ||
314 | |||
315 | /* DVB USB Driver stuff */ | ||
316 | /* bInterfaceNumber 0 is HID | ||
317 | * bInterfaceNumber 1 is DVB-T */ | ||
318 | static struct dvb_usb_device_properties ec168_props = { | ||
319 | .driver_name = KBUILD_MODNAME, | ||
320 | .owner = THIS_MODULE, | ||
321 | .adapter_nr = adapter_nr, | ||
322 | .bInterfaceNumber = 1, | ||
323 | |||
324 | .identify_state = ec168_identify_state, | ||
325 | .firmware = "dvb-usb-ec168.fw", | ||
326 | .download_firmware = ec168_download_firmware, | ||
327 | |||
328 | .i2c_algo = &ec168_i2c_algo, | ||
329 | .frontend_attach = ec168_ec100_frontend_attach, | ||
330 | .tuner_attach = ec168_mxl5003s_tuner_attach, | ||
331 | .streaming_ctrl = ec168_streaming_ctrl, | ||
332 | |||
333 | .num_adapters = 1, | ||
334 | .adapter = { | ||
335 | { | ||
336 | .stream = DVB_USB_STREAM_BULK(0x82, 6, 32 * 512), | ||
337 | } | ||
338 | }, | ||
339 | }; | ||
340 | |||
341 | static const struct dvb_usb_driver_info ec168_driver_info = { | ||
342 | .name = "E3C EC168 reference design", | ||
343 | .props = &ec168_props, | ||
344 | }; | ||
345 | |||
346 | static const struct usb_device_id ec168_id[] = { | ||
347 | { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168), | ||
348 | .driver_info = (kernel_ulong_t) &ec168_driver_info }, | ||
349 | { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2), | ||
350 | .driver_info = (kernel_ulong_t) &ec168_driver_info }, | ||
351 | { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3), | ||
352 | .driver_info = (kernel_ulong_t) &ec168_driver_info }, | ||
353 | { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4), | ||
354 | .driver_info = (kernel_ulong_t) &ec168_driver_info }, | ||
355 | { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5), | ||
356 | .driver_info = (kernel_ulong_t) &ec168_driver_info }, | ||
357 | {} | ||
358 | }; | ||
359 | MODULE_DEVICE_TABLE(usb, ec168_id); | ||
360 | |||
361 | static struct usb_driver ec168_driver = { | ||
362 | .name = KBUILD_MODNAME, | ||
363 | .id_table = ec168_id, | ||
364 | .probe = dvb_usbv2_probe, | ||
365 | .disconnect = dvb_usbv2_disconnect, | ||
366 | .suspend = dvb_usbv2_suspend, | ||
367 | .resume = dvb_usbv2_resume, | ||
368 | .no_dynamic_id = 1, | ||
369 | .soft_unbind = 1, | ||
370 | }; | ||
371 | |||
372 | module_usb_driver(ec168_driver); | ||
373 | |||
374 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
375 | MODULE_DESCRIPTION("E3C EC168 driver"); | ||
376 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/ec168.h b/drivers/media/usb/dvb-usb-v2/ec168.h new file mode 100644 index 000000000000..9181236f6ebc --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/ec168.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * E3C EC168 DVB USB driver | ||
3 | * | ||
4 | * Copyright (C) 2009 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 | */ | ||
21 | |||
22 | #ifndef EC168_H | ||
23 | #define EC168_H | ||
24 | |||
25 | #include "dvb_usb.h" | ||
26 | |||
27 | #define ec168_debug_dump(r, t, v, i, b, l) { \ | ||
28 | char *direction; \ | ||
29 | if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ | ||
30 | direction = ">>>"; \ | ||
31 | else \ | ||
32 | direction = "<<<"; \ | ||
33 | pr_debug("%s: %02x %02x %02x %02x %02x %02x %02x %02x %s\n", \ | ||
34 | __func__, t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, \ | ||
35 | l & 0xff, l >> 8, direction); \ | ||
36 | } | ||
37 | |||
38 | #define EC168_USB_TIMEOUT 1000 | ||
39 | |||
40 | struct ec168_req { | ||
41 | u8 cmd; /* [1] */ | ||
42 | u16 value; /* [2|3] */ | ||
43 | u16 index; /* [4|5] */ | ||
44 | u16 size; /* [6|7] */ | ||
45 | u8 *data; | ||
46 | }; | ||
47 | |||
48 | enum ec168_cmd { | ||
49 | DOWNLOAD_FIRMWARE = 0x00, | ||
50 | CONFIG = 0x01, | ||
51 | DEMOD_RW = 0x03, | ||
52 | GPIO = 0x04, | ||
53 | STREAMING_CTRL = 0x10, | ||
54 | READ_I2C = 0x20, | ||
55 | WRITE_I2C = 0x21, | ||
56 | HID_DOWNLOAD = 0x30, | ||
57 | GET_CONFIG, | ||
58 | SET_CONFIG, | ||
59 | READ_DEMOD, | ||
60 | WRITE_DEMOD, | ||
61 | }; | ||
62 | |||
63 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c new file mode 100644 index 000000000000..cf29f43e3598 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/gl861.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* DVB USB compliant linux driver for GL861 USB2.0 devices. | ||
2 | * | ||
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 | ||
5 | * Free Software Foundation, version 2. | ||
6 | * | ||
7 | * see Documentation/dvb/README.dvb-usb for more information | ||
8 | */ | ||
9 | #include "gl861.h" | ||
10 | |||
11 | #include "zl10353.h" | ||
12 | #include "qt1010.h" | ||
13 | |||
14 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
15 | |||
16 | static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
17 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
18 | { | ||
19 | u16 index; | ||
20 | u16 value = addr << (8 + 1); | ||
21 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
22 | u8 req, type; | ||
23 | |||
24 | if (wo) { | ||
25 | req = GL861_REQ_I2C_WRITE; | ||
26 | type = GL861_WRITE; | ||
27 | } else { /* rw */ | ||
28 | req = GL861_REQ_I2C_READ; | ||
29 | type = GL861_READ; | ||
30 | } | ||
31 | |||
32 | switch (wlen) { | ||
33 | case 1: | ||
34 | index = wbuf[0]; | ||
35 | break; | ||
36 | case 2: | ||
37 | index = wbuf[0]; | ||
38 | value = value + wbuf[1]; | ||
39 | break; | ||
40 | default: | ||
41 | pr_err("%s: wlen=%d, aborting\n", KBUILD_MODNAME, wlen); | ||
42 | return -EINVAL; | ||
43 | } | ||
44 | |||
45 | msleep(1); /* avoid I2C errors */ | ||
46 | |||
47 | return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, | ||
48 | value, index, rbuf, rlen, 2000); | ||
49 | } | ||
50 | |||
51 | /* I2C */ | ||
52 | static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
53 | int num) | ||
54 | { | ||
55 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
56 | int i; | ||
57 | |||
58 | if (num > 2) | ||
59 | return -EINVAL; | ||
60 | |||
61 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
62 | return -EAGAIN; | ||
63 | |||
64 | for (i = 0; i < num; i++) { | ||
65 | /* write/read request */ | ||
66 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
67 | if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
68 | msg[i].len, msg[i+1].buf, msg[i+1].len) < 0) | ||
69 | break; | ||
70 | i++; | ||
71 | } else | ||
72 | if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, | ||
73 | msg[i].len, NULL, 0) < 0) | ||
74 | break; | ||
75 | } | ||
76 | |||
77 | mutex_unlock(&d->i2c_mutex); | ||
78 | return i; | ||
79 | } | ||
80 | |||
81 | static u32 gl861_i2c_func(struct i2c_adapter *adapter) | ||
82 | { | ||
83 | return I2C_FUNC_I2C; | ||
84 | } | ||
85 | |||
86 | static struct i2c_algorithm gl861_i2c_algo = { | ||
87 | .master_xfer = gl861_i2c_xfer, | ||
88 | .functionality = gl861_i2c_func, | ||
89 | }; | ||
90 | |||
91 | /* Callbacks for DVB USB */ | ||
92 | static struct zl10353_config gl861_zl10353_config = { | ||
93 | .demod_address = 0x0f, | ||
94 | .no_tuner = 1, | ||
95 | .parallel_ts = 1, | ||
96 | }; | ||
97 | |||
98 | static int gl861_frontend_attach(struct dvb_usb_adapter *adap) | ||
99 | { | ||
100 | |||
101 | adap->fe[0] = dvb_attach(zl10353_attach, &gl861_zl10353_config, | ||
102 | &adap_to_d(adap)->i2c_adap); | ||
103 | if (adap->fe[0] == NULL) | ||
104 | return -EIO; | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static struct qt1010_config gl861_qt1010_config = { | ||
110 | .i2c_address = 0x62 | ||
111 | }; | ||
112 | |||
113 | static int gl861_tuner_attach(struct dvb_usb_adapter *adap) | ||
114 | { | ||
115 | return dvb_attach(qt1010_attach, | ||
116 | adap->fe[0], &adap_to_d(adap)->i2c_adap, | ||
117 | &gl861_qt1010_config) == NULL ? -ENODEV : 0; | ||
118 | } | ||
119 | |||
120 | static int gl861_init(struct dvb_usb_device *d) | ||
121 | { | ||
122 | /* | ||
123 | * There is 2 interfaces. Interface 0 is for TV and interface 1 is | ||
124 | * for HID remote controller. Interface 0 has 2 alternate settings. | ||
125 | * For some reason we need to set interface explicitly, defaulted | ||
126 | * as alternate setting 1? | ||
127 | */ | ||
128 | return usb_set_interface(d->udev, 0, 0); | ||
129 | } | ||
130 | |||
131 | /* DVB USB Driver stuff */ | ||
132 | static struct dvb_usb_device_properties gl861_props = { | ||
133 | .driver_name = KBUILD_MODNAME, | ||
134 | .owner = THIS_MODULE, | ||
135 | .adapter_nr = adapter_nr, | ||
136 | |||
137 | .i2c_algo = &gl861_i2c_algo, | ||
138 | .frontend_attach = gl861_frontend_attach, | ||
139 | .tuner_attach = gl861_tuner_attach, | ||
140 | .init = gl861_init, | ||
141 | |||
142 | .num_adapters = 1, | ||
143 | .adapter = { | ||
144 | { | ||
145 | .stream = DVB_USB_STREAM_BULK(0x81, 7, 512), | ||
146 | } | ||
147 | } | ||
148 | }; | ||
149 | |||
150 | static const struct usb_device_id gl861_id_table[] = { | ||
151 | { DVB_USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801, | ||
152 | &gl861_props, "MSI Mega Sky 55801 DVB-T USB2.0", NULL) }, | ||
153 | { DVB_USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU, | ||
154 | &gl861_props, "A-LINK DTU DVB-T USB2.0", NULL) }, | ||
155 | { } | ||
156 | }; | ||
157 | MODULE_DEVICE_TABLE(usb, gl861_id_table); | ||
158 | |||
159 | static struct usb_driver gl861_usb_driver = { | ||
160 | .name = KBUILD_MODNAME, | ||
161 | .id_table = gl861_id_table, | ||
162 | .probe = dvb_usbv2_probe, | ||
163 | .disconnect = dvb_usbv2_disconnect, | ||
164 | .suspend = dvb_usbv2_suspend, | ||
165 | .resume = dvb_usbv2_resume, | ||
166 | .no_dynamic_id = 1, | ||
167 | .soft_unbind = 1, | ||
168 | }; | ||
169 | |||
170 | module_usb_driver(gl861_usb_driver); | ||
171 | |||
172 | MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>"); | ||
173 | MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861"); | ||
174 | MODULE_VERSION("0.1"); | ||
175 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/gl861.h b/drivers/media/usb/dvb-usb-v2/gl861.h new file mode 100644 index 000000000000..b0b80d87bb7e --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/gl861.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _DVB_USB_GL861_H_ | ||
2 | #define _DVB_USB_GL861_H_ | ||
3 | |||
4 | #include "dvb_usb.h" | ||
5 | |||
6 | #define GL861_WRITE 0x40 | ||
7 | #define GL861_READ 0xc0 | ||
8 | |||
9 | #define GL861_REQ_I2C_WRITE 0x01 | ||
10 | #define GL861_REQ_I2C_READ 0x02 | ||
11 | |||
12 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c new file mode 100644 index 000000000000..695f9106bc54 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/it913x.c | |||
@@ -0,0 +1,799 @@ | |||
1 | /* | ||
2 | * DVB USB compliant linux driver for ITE IT9135 and IT9137 | ||
3 | * | ||
4 | * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com) | ||
5 | * IT9135 (C) ITE Tech Inc. | ||
6 | * IT9137 (C) ITE Tech Inc. | ||
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 Version 2, as | ||
10 | * published by the Free Software Foundation. | ||
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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | * | ||
22 | * see Documentation/dvb/README.dvb-usb for more information | ||
23 | * see Documentation/dvb/it9137.txt for firmware information | ||
24 | * | ||
25 | */ | ||
26 | #define DVB_USB_LOG_PREFIX "it913x" | ||
27 | |||
28 | #include <linux/usb.h> | ||
29 | #include <linux/usb/input.h> | ||
30 | #include <media/rc-core.h> | ||
31 | |||
32 | #include "dvb_usb.h" | ||
33 | #include "it913x-fe.h" | ||
34 | |||
35 | /* debug */ | ||
36 | static int dvb_usb_it913x_debug; | ||
37 | #define it_debug(var, level, args...) \ | ||
38 | do { if ((var & level)) pr_debug(DVB_USB_LOG_PREFIX": " args); \ | ||
39 | } while (0) | ||
40 | #define deb_info(level, args...) it_debug(dvb_usb_it913x_debug, level, args) | ||
41 | #define info(args...) pr_info(DVB_USB_LOG_PREFIX": " args) | ||
42 | |||
43 | module_param_named(debug, dvb_usb_it913x_debug, int, 0644); | ||
44 | MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); | ||
45 | |||
46 | static int dvb_usb_it913x_firmware; | ||
47 | module_param_named(firmware, dvb_usb_it913x_firmware, int, 0644); | ||
48 | MODULE_PARM_DESC(firmware, "set firmware 0=auto"\ | ||
49 | "1=IT9137 2=IT9135 V1 3=IT9135 V2"); | ||
50 | #define FW_IT9137 "dvb-usb-it9137-01.fw" | ||
51 | #define FW_IT9135_V1 "dvb-usb-it9135-01.fw" | ||
52 | #define FW_IT9135_V2 "dvb-usb-it9135-02.fw" | ||
53 | |||
54 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
55 | |||
56 | struct it913x_state { | ||
57 | struct ite_config it913x_config; | ||
58 | u8 pid_filter_onoff; | ||
59 | bool proprietary_ir; | ||
60 | int cmd_counter; | ||
61 | }; | ||
62 | |||
63 | static u16 check_sum(u8 *p, u8 len) | ||
64 | { | ||
65 | u16 sum = 0; | ||
66 | u8 i = 1; | ||
67 | while (i < len) | ||
68 | sum += (i++ & 1) ? (*p++) << 8 : *p++; | ||
69 | return ~sum; | ||
70 | } | ||
71 | |||
72 | static int it913x_io(struct dvb_usb_device *d, u8 mode, u8 pro, | ||
73 | u8 cmd, u32 reg, u8 addr, u8 *data, u8 len) | ||
74 | { | ||
75 | struct it913x_state *st = d->priv; | ||
76 | int ret = 0, i, buf_size = 1; | ||
77 | u8 *buff; | ||
78 | u8 rlen; | ||
79 | u16 chk_sum; | ||
80 | |||
81 | buff = kzalloc(256, GFP_KERNEL); | ||
82 | if (!buff) { | ||
83 | info("USB Buffer Failed"); | ||
84 | return -ENOMEM; | ||
85 | } | ||
86 | |||
87 | buff[buf_size++] = pro; | ||
88 | buff[buf_size++] = cmd; | ||
89 | buff[buf_size++] = st->cmd_counter; | ||
90 | |||
91 | switch (mode) { | ||
92 | case READ_LONG: | ||
93 | case WRITE_LONG: | ||
94 | buff[buf_size++] = len; | ||
95 | buff[buf_size++] = 2; | ||
96 | buff[buf_size++] = (reg >> 24); | ||
97 | buff[buf_size++] = (reg >> 16) & 0xff; | ||
98 | buff[buf_size++] = (reg >> 8) & 0xff; | ||
99 | buff[buf_size++] = reg & 0xff; | ||
100 | break; | ||
101 | case READ_SHORT: | ||
102 | buff[buf_size++] = addr; | ||
103 | break; | ||
104 | case WRITE_SHORT: | ||
105 | buff[buf_size++] = len; | ||
106 | buff[buf_size++] = addr; | ||
107 | buff[buf_size++] = (reg >> 8) & 0xff; | ||
108 | buff[buf_size++] = reg & 0xff; | ||
109 | break; | ||
110 | case READ_DATA: | ||
111 | case WRITE_DATA: | ||
112 | break; | ||
113 | case WRITE_CMD: | ||
114 | mode = 7; | ||
115 | break; | ||
116 | default: | ||
117 | kfree(buff); | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | |||
121 | if (mode & 1) { | ||
122 | for (i = 0; i < len ; i++) | ||
123 | buff[buf_size++] = data[i]; | ||
124 | } | ||
125 | chk_sum = check_sum(&buff[1], buf_size); | ||
126 | |||
127 | buff[buf_size++] = chk_sum >> 8; | ||
128 | buff[0] = buf_size; | ||
129 | buff[buf_size++] = (chk_sum & 0xff); | ||
130 | |||
131 | ret = dvb_usbv2_generic_rw(d, buff, buf_size, buff, (mode & 1) ? | ||
132 | 5 : len + 5); | ||
133 | if (ret < 0) | ||
134 | goto error; | ||
135 | |||
136 | rlen = (mode & 0x1) ? 0x1 : len; | ||
137 | |||
138 | if (mode & 1) | ||
139 | ret = buff[2]; | ||
140 | else | ||
141 | memcpy(data, &buff[3], rlen); | ||
142 | |||
143 | st->cmd_counter++; | ||
144 | |||
145 | error: kfree(buff); | ||
146 | |||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static int it913x_wr_reg(struct dvb_usb_device *d, u8 pro, u32 reg , u8 data) | ||
151 | { | ||
152 | int ret; | ||
153 | u8 b[1]; | ||
154 | b[0] = data; | ||
155 | ret = it913x_io(d, WRITE_LONG, pro, | ||
156 | CMD_DEMOD_WRITE, reg, 0, b, sizeof(b)); | ||
157 | |||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | static int it913x_read_reg(struct dvb_usb_device *d, u32 reg) | ||
162 | { | ||
163 | int ret; | ||
164 | u8 data[1]; | ||
165 | |||
166 | ret = it913x_io(d, READ_LONG, DEV_0, | ||
167 | CMD_DEMOD_READ, reg, 0, &data[0], sizeof(data)); | ||
168 | |||
169 | return (ret < 0) ? ret : data[0]; | ||
170 | } | ||
171 | |||
172 | static int it913x_query(struct dvb_usb_device *d, u8 pro) | ||
173 | { | ||
174 | struct it913x_state *st = d->priv; | ||
175 | int ret, i; | ||
176 | u8 data[4]; | ||
177 | u8 ver; | ||
178 | |||
179 | for (i = 0; i < 5; i++) { | ||
180 | ret = it913x_io(d, READ_LONG, pro, CMD_DEMOD_READ, | ||
181 | 0x1222, 0, &data[0], 3); | ||
182 | ver = data[0]; | ||
183 | if (ver > 0 && ver < 3) | ||
184 | break; | ||
185 | msleep(100); | ||
186 | } | ||
187 | |||
188 | if (ver < 1 || ver > 2) { | ||
189 | info("Failed to identify chip version applying 1"); | ||
190 | st->it913x_config.chip_ver = 0x1; | ||
191 | st->it913x_config.chip_type = 0x9135; | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | st->it913x_config.chip_ver = ver; | ||
196 | st->it913x_config.chip_type = (u16)(data[2] << 8) + data[1]; | ||
197 | |||
198 | info("Chip Version=%02x Chip Type=%04x", st->it913x_config.chip_ver, | ||
199 | st->it913x_config.chip_type); | ||
200 | |||
201 | ret = it913x_io(d, READ_SHORT, pro, | ||
202 | CMD_QUERYINFO, 0, 0x1, &data[0], 4); | ||
203 | |||
204 | st->it913x_config.firmware = (data[0] << 24) | (data[1] << 16) | | ||
205 | (data[2] << 8) | data[3]; | ||
206 | |||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
211 | { | ||
212 | struct dvb_usb_device *d = adap_to_d(adap); | ||
213 | struct it913x_state *st = adap_to_priv(adap); | ||
214 | int ret; | ||
215 | u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; | ||
216 | |||
217 | mutex_lock(&d->i2c_mutex); | ||
218 | |||
219 | deb_info(1, "PID_C (%02x)", onoff); | ||
220 | |||
221 | ret = it913x_wr_reg(d, pro, PID_EN, st->pid_filter_onoff); | ||
222 | |||
223 | mutex_unlock(&d->i2c_mutex); | ||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | static int it913x_pid_filter(struct dvb_usb_adapter *adap, | ||
228 | int index, u16 pid, int onoff) | ||
229 | { | ||
230 | struct dvb_usb_device *d = adap_to_d(adap); | ||
231 | struct it913x_state *st = adap_to_priv(adap); | ||
232 | int ret; | ||
233 | u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; | ||
234 | |||
235 | mutex_lock(&d->i2c_mutex); | ||
236 | |||
237 | deb_info(1, "PID_F (%02x)", onoff); | ||
238 | |||
239 | ret = it913x_wr_reg(d, pro, PID_LSB, (u8)(pid & 0xff)); | ||
240 | |||
241 | ret |= it913x_wr_reg(d, pro, PID_MSB, (u8)(pid >> 8)); | ||
242 | |||
243 | ret |= it913x_wr_reg(d, pro, PID_INX_EN, (u8)onoff); | ||
244 | |||
245 | ret |= it913x_wr_reg(d, pro, PID_INX, (u8)(index & 0x1f)); | ||
246 | |||
247 | if (d->udev->speed == USB_SPEED_HIGH && pid == 0x2000) { | ||
248 | ret |= it913x_wr_reg(d , pro, PID_EN, !onoff); | ||
249 | st->pid_filter_onoff = !onoff; | ||
250 | } else | ||
251 | st->pid_filter_onoff = | ||
252 | adap->pid_filtering; | ||
253 | |||
254 | mutex_unlock(&d->i2c_mutex); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | |||
259 | static int it913x_return_status(struct dvb_usb_device *d) | ||
260 | { | ||
261 | struct it913x_state *st = d->priv; | ||
262 | int ret = it913x_query(d, DEV_0); | ||
263 | if (st->it913x_config.firmware > 0) | ||
264 | info("Firmware Version %d", st->it913x_config.firmware); | ||
265 | |||
266 | return ret; | ||
267 | } | ||
268 | |||
269 | static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
270 | int num) | ||
271 | { | ||
272 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
273 | static u8 data[256]; | ||
274 | int ret; | ||
275 | u32 reg; | ||
276 | u8 pro; | ||
277 | |||
278 | mutex_lock(&d->i2c_mutex); | ||
279 | |||
280 | deb_info(2, "num of messages %d address %02x", num, msg[0].addr); | ||
281 | |||
282 | pro = (msg[0].addr & 0x2) ? DEV_0_DMOD : 0x0; | ||
283 | pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0; | ||
284 | memcpy(data, msg[0].buf, msg[0].len); | ||
285 | reg = (data[0] << 24) + (data[1] << 16) + | ||
286 | (data[2] << 8) + data[3]; | ||
287 | if (num == 2) { | ||
288 | ret = it913x_io(d, READ_LONG, pro, | ||
289 | CMD_DEMOD_READ, reg, 0, data, msg[1].len); | ||
290 | memcpy(msg[1].buf, data, msg[1].len); | ||
291 | } else | ||
292 | ret = it913x_io(d, WRITE_LONG, pro, CMD_DEMOD_WRITE, | ||
293 | reg, 0, &data[4], msg[0].len - 4); | ||
294 | |||
295 | mutex_unlock(&d->i2c_mutex); | ||
296 | |||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static u32 it913x_i2c_func(struct i2c_adapter *adapter) | ||
301 | { | ||
302 | return I2C_FUNC_I2C; | ||
303 | } | ||
304 | |||
305 | static struct i2c_algorithm it913x_i2c_algo = { | ||
306 | .master_xfer = it913x_i2c_xfer, | ||
307 | .functionality = it913x_i2c_func, | ||
308 | }; | ||
309 | |||
310 | /* Callbacks for DVB USB */ | ||
311 | #define IT913X_POLL 250 | ||
312 | static int it913x_rc_query(struct dvb_usb_device *d) | ||
313 | { | ||
314 | u8 ibuf[4]; | ||
315 | int ret; | ||
316 | u32 key; | ||
317 | /* Avoid conflict with frontends*/ | ||
318 | mutex_lock(&d->i2c_mutex); | ||
319 | |||
320 | ret = it913x_io(d, READ_LONG, PRO_LINK, CMD_IR_GET, | ||
321 | 0, 0, &ibuf[0], sizeof(ibuf)); | ||
322 | |||
323 | if ((ibuf[2] + ibuf[3]) == 0xff) { | ||
324 | key = ibuf[2]; | ||
325 | key += ibuf[0] << 16; | ||
326 | key += ibuf[1] << 8; | ||
327 | deb_info(1, "NEC Extended Key =%08x", key); | ||
328 | if (d->rc_dev != NULL) | ||
329 | rc_keydown(d->rc_dev, key, 0); | ||
330 | } | ||
331 | |||
332 | mutex_unlock(&d->i2c_mutex); | ||
333 | |||
334 | return ret; | ||
335 | } | ||
336 | |||
337 | /* Firmware sets raw */ | ||
338 | static const char fw_it9135_v1[] = FW_IT9135_V1; | ||
339 | static const char fw_it9135_v2[] = FW_IT9135_V2; | ||
340 | static const char fw_it9137[] = FW_IT9137; | ||
341 | |||
342 | static void ite_get_firmware_name(struct dvb_usb_device *d, | ||
343 | const char **name) | ||
344 | { | ||
345 | struct it913x_state *st = d->priv; | ||
346 | int sw; | ||
347 | /* auto switch */ | ||
348 | if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_KWORLD_2) | ||
349 | sw = IT9137_FW; | ||
350 | else if (st->it913x_config.chip_ver == 1) | ||
351 | sw = IT9135_V1_FW; | ||
352 | else | ||
353 | sw = IT9135_V2_FW; | ||
354 | |||
355 | /* force switch */ | ||
356 | if (dvb_usb_it913x_firmware != IT9135_AUTO) | ||
357 | sw = dvb_usb_it913x_firmware; | ||
358 | |||
359 | switch (sw) { | ||
360 | case IT9135_V1_FW: | ||
361 | st->it913x_config.firmware_ver = 1; | ||
362 | st->it913x_config.adc_x2 = 1; | ||
363 | st->it913x_config.read_slevel = false; | ||
364 | *name = fw_it9135_v1; | ||
365 | break; | ||
366 | case IT9135_V2_FW: | ||
367 | st->it913x_config.firmware_ver = 1; | ||
368 | st->it913x_config.adc_x2 = 1; | ||
369 | st->it913x_config.read_slevel = false; | ||
370 | *name = fw_it9135_v2; | ||
371 | switch (st->it913x_config.tuner_id_0) { | ||
372 | case IT9135_61: | ||
373 | case IT9135_62: | ||
374 | break; | ||
375 | default: | ||
376 | info("Unknown tuner ID applying default 0x60"); | ||
377 | case IT9135_60: | ||
378 | st->it913x_config.tuner_id_0 = IT9135_60; | ||
379 | } | ||
380 | break; | ||
381 | case IT9137_FW: | ||
382 | default: | ||
383 | st->it913x_config.firmware_ver = 0; | ||
384 | st->it913x_config.adc_x2 = 0; | ||
385 | st->it913x_config.read_slevel = true; | ||
386 | *name = fw_it9137; | ||
387 | } | ||
388 | |||
389 | return; | ||
390 | } | ||
391 | |||
392 | #define TS_MPEG_PKT_SIZE 188 | ||
393 | #define EP_LOW 21 | ||
394 | #define TS_BUFFER_SIZE_PID (EP_LOW*TS_MPEG_PKT_SIZE) | ||
395 | #define EP_HIGH 348 | ||
396 | #define TS_BUFFER_SIZE_MAX (EP_HIGH*TS_MPEG_PKT_SIZE) | ||
397 | |||
398 | static int it913x_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, | ||
399 | struct usb_data_stream_properties *stream) | ||
400 | { | ||
401 | struct dvb_usb_adapter *adap = fe_to_adap(fe); | ||
402 | if (adap->pid_filtering) | ||
403 | stream->u.bulk.buffersize = TS_BUFFER_SIZE_PID; | ||
404 | else | ||
405 | stream->u.bulk.buffersize = TS_BUFFER_SIZE_MAX; | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | static int it913x_select_config(struct dvb_usb_device *d) | ||
411 | { | ||
412 | struct it913x_state *st = d->priv; | ||
413 | int ret, reg; | ||
414 | |||
415 | ret = it913x_return_status(d); | ||
416 | if (ret < 0) | ||
417 | return ret; | ||
418 | |||
419 | if (st->it913x_config.chip_ver == 0x02 | ||
420 | && st->it913x_config.chip_type == 0x9135) | ||
421 | reg = it913x_read_reg(d, 0x461d); | ||
422 | else | ||
423 | reg = it913x_read_reg(d, 0x461b); | ||
424 | |||
425 | if (reg < 0) | ||
426 | return reg; | ||
427 | |||
428 | if (reg == 0) { | ||
429 | st->it913x_config.dual_mode = 0; | ||
430 | st->it913x_config.tuner_id_0 = IT9135_38; | ||
431 | st->proprietary_ir = true; | ||
432 | } else { | ||
433 | /* TS mode */ | ||
434 | reg = it913x_read_reg(d, 0x49c5); | ||
435 | if (reg < 0) | ||
436 | return reg; | ||
437 | st->it913x_config.dual_mode = reg; | ||
438 | |||
439 | /* IR mode type */ | ||
440 | reg = it913x_read_reg(d, 0x49ac); | ||
441 | if (reg < 0) | ||
442 | return reg; | ||
443 | if (reg == 5) { | ||
444 | info("Remote propriety (raw) mode"); | ||
445 | st->proprietary_ir = true; | ||
446 | } else if (reg == 1) { | ||
447 | info("Remote HID mode NOT SUPPORTED"); | ||
448 | st->proprietary_ir = false; | ||
449 | } | ||
450 | |||
451 | /* Tuner_id */ | ||
452 | reg = it913x_read_reg(d, 0x49d0); | ||
453 | if (reg < 0) | ||
454 | return reg; | ||
455 | st->it913x_config.tuner_id_0 = reg; | ||
456 | } | ||
457 | |||
458 | info("Dual mode=%x Tuner Type=%x", st->it913x_config.dual_mode, | ||
459 | st->it913x_config.tuner_id_0); | ||
460 | |||
461 | return ret; | ||
462 | } | ||
463 | |||
464 | static int it913x_streaming_ctrl(struct dvb_frontend *fe, int onoff) | ||
465 | { | ||
466 | struct dvb_usb_adapter *adap = fe_to_adap(fe); | ||
467 | struct dvb_usb_device *d = adap_to_d(adap); | ||
468 | struct it913x_state *st = fe_to_priv(fe); | ||
469 | int ret = 0; | ||
470 | u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD; | ||
471 | |||
472 | deb_info(1, "STM (%02x)", onoff); | ||
473 | |||
474 | if (!onoff) { | ||
475 | mutex_lock(&d->i2c_mutex); | ||
476 | |||
477 | ret = it913x_wr_reg(d, pro, PID_RST, 0x1); | ||
478 | |||
479 | mutex_unlock(&d->i2c_mutex); | ||
480 | st->pid_filter_onoff = | ||
481 | adap->pid_filtering; | ||
482 | |||
483 | } | ||
484 | |||
485 | return ret; | ||
486 | } | ||
487 | |||
488 | static int it913x_identify_state(struct dvb_usb_device *d, const char **name) | ||
489 | { | ||
490 | struct it913x_state *st = d->priv; | ||
491 | int ret; | ||
492 | u8 reg; | ||
493 | |||
494 | /* Read and select config */ | ||
495 | ret = it913x_select_config(d); | ||
496 | if (ret < 0) | ||
497 | return ret; | ||
498 | |||
499 | ite_get_firmware_name(d, name); | ||
500 | |||
501 | if (st->it913x_config.firmware > 0) | ||
502 | return WARM; | ||
503 | |||
504 | if (st->it913x_config.dual_mode) { | ||
505 | st->it913x_config.tuner_id_1 = it913x_read_reg(d, 0x49e0); | ||
506 | ret = it913x_wr_reg(d, DEV_0, GPIOH1_EN, 0x1); | ||
507 | ret |= it913x_wr_reg(d, DEV_0, GPIOH1_ON, 0x1); | ||
508 | ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x1); | ||
509 | msleep(50); | ||
510 | ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x0); | ||
511 | msleep(50); | ||
512 | reg = it913x_read_reg(d, GPIOH1_O); | ||
513 | if (reg == 0) { | ||
514 | ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x1); | ||
515 | ret |= it913x_return_status(d); | ||
516 | if (ret != 0) | ||
517 | ret = it913x_wr_reg(d, DEV_0, | ||
518 | GPIOH1_O, 0x0); | ||
519 | } | ||
520 | } | ||
521 | |||
522 | reg = it913x_read_reg(d, IO_MUX_POWER_CLK); | ||
523 | |||
524 | if (st->it913x_config.dual_mode) { | ||
525 | ret |= it913x_wr_reg(d, DEV_0, 0x4bfb, CHIP2_I2C_ADDR); | ||
526 | if (st->it913x_config.firmware_ver == 1) | ||
527 | ret |= it913x_wr_reg(d, DEV_0, 0xcfff, 0x1); | ||
528 | else | ||
529 | ret |= it913x_wr_reg(d, DEV_0, CLK_O_EN, 0x1); | ||
530 | } else { | ||
531 | ret |= it913x_wr_reg(d, DEV_0, 0x4bfb, 0x0); | ||
532 | if (st->it913x_config.firmware_ver == 1) | ||
533 | ret |= it913x_wr_reg(d, DEV_0, 0xcfff, 0x0); | ||
534 | else | ||
535 | ret |= it913x_wr_reg(d, DEV_0, CLK_O_EN, 0x0); | ||
536 | } | ||
537 | |||
538 | ret |= it913x_wr_reg(d, DEV_0, I2C_CLK, I2C_CLK_100); | ||
539 | |||
540 | return (ret < 0) ? ret : COLD; | ||
541 | } | ||
542 | |||
543 | static int it913x_download_firmware(struct dvb_usb_device *d, | ||
544 | const struct firmware *fw) | ||
545 | { | ||
546 | struct it913x_state *st = d->priv; | ||
547 | int ret = 0, i = 0, pos = 0; | ||
548 | u8 packet_size, min_pkt; | ||
549 | u8 *fw_data; | ||
550 | |||
551 | ret = it913x_wr_reg(d, DEV_0, I2C_CLK, I2C_CLK_100); | ||
552 | |||
553 | info("FRM Starting Firmware Download"); | ||
554 | |||
555 | /* Multi firmware loader */ | ||
556 | /* This uses scatter write firmware headers */ | ||
557 | /* The firmware must start with 03 XX 00 */ | ||
558 | /* and be the extact firmware length */ | ||
559 | |||
560 | if (st->it913x_config.chip_ver == 2) | ||
561 | min_pkt = 0x11; | ||
562 | else | ||
563 | min_pkt = 0x19; | ||
564 | |||
565 | while (i <= fw->size) { | ||
566 | if (((fw->data[i] == 0x3) && (fw->data[i + 2] == 0x0)) | ||
567 | || (i == fw->size)) { | ||
568 | packet_size = i - pos; | ||
569 | if ((packet_size > min_pkt) || (i == fw->size)) { | ||
570 | fw_data = (u8 *)(fw->data + pos); | ||
571 | pos += packet_size; | ||
572 | if (packet_size > 0) { | ||
573 | ret = it913x_io(d, WRITE_DATA, | ||
574 | DEV_0, CMD_SCATTER_WRITE, 0, | ||
575 | 0, fw_data, packet_size); | ||
576 | if (ret < 0) | ||
577 | break; | ||
578 | } | ||
579 | udelay(1000); | ||
580 | } | ||
581 | } | ||
582 | i++; | ||
583 | } | ||
584 | |||
585 | if (ret < 0) | ||
586 | info("FRM Firmware Download Failed (%d)" , ret); | ||
587 | else | ||
588 | info("FRM Firmware Download Completed - Resetting Device"); | ||
589 | |||
590 | msleep(30); | ||
591 | |||
592 | ret = it913x_io(d, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0); | ||
593 | if (ret < 0) | ||
594 | info("FRM Device not responding to reboot"); | ||
595 | |||
596 | ret = it913x_return_status(d); | ||
597 | if (st->it913x_config.firmware == 0) { | ||
598 | info("FRM Failed to reboot device"); | ||
599 | return -ENODEV; | ||
600 | } | ||
601 | |||
602 | msleep(30); | ||
603 | |||
604 | ret = it913x_wr_reg(d, DEV_0, I2C_CLK, I2C_CLK_400); | ||
605 | |||
606 | msleep(30); | ||
607 | |||
608 | /* Tuner function */ | ||
609 | if (st->it913x_config.dual_mode) | ||
610 | ret |= it913x_wr_reg(d, DEV_0_DMOD , 0xec4c, 0xa0); | ||
611 | else | ||
612 | ret |= it913x_wr_reg(d, DEV_0_DMOD , 0xec4c, 0x68); | ||
613 | |||
614 | if ((st->it913x_config.chip_ver == 1) && | ||
615 | (st->it913x_config.chip_type == 0x9135)) { | ||
616 | ret |= it913x_wr_reg(d, DEV_0, PADODPU, 0x0); | ||
617 | ret |= it913x_wr_reg(d, DEV_0, AGC_O_D, 0x0); | ||
618 | if (st->it913x_config.dual_mode) { | ||
619 | ret |= it913x_wr_reg(d, DEV_1, PADODPU, 0x0); | ||
620 | ret |= it913x_wr_reg(d, DEV_1, AGC_O_D, 0x0); | ||
621 | } | ||
622 | } | ||
623 | |||
624 | return (ret < 0) ? -ENODEV : 0; | ||
625 | } | ||
626 | |||
627 | static int it913x_name(struct dvb_usb_adapter *adap) | ||
628 | { | ||
629 | struct dvb_usb_device *d = adap_to_d(adap); | ||
630 | const char *desc = d->name; | ||
631 | char *fe_name[] = {"_1", "_2", "_3", "_4"}; | ||
632 | char *name = adap->fe[0]->ops.info.name; | ||
633 | |||
634 | strlcpy(name, desc, 128); | ||
635 | strlcat(name, fe_name[adap->id], 128); | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | static int it913x_frontend_attach(struct dvb_usb_adapter *adap) | ||
641 | { | ||
642 | struct dvb_usb_device *d = adap_to_d(adap); | ||
643 | struct it913x_state *st = d->priv; | ||
644 | int ret = 0; | ||
645 | u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5); | ||
646 | u16 ep_size = adap->stream.buf_size / 4; | ||
647 | u8 pkt_size = 0x80; | ||
648 | |||
649 | if (d->udev->speed != USB_SPEED_HIGH) | ||
650 | pkt_size = 0x10; | ||
651 | |||
652 | st->it913x_config.adf = it913x_read_reg(d, IO_MUX_POWER_CLK); | ||
653 | |||
654 | adap->fe[0] = dvb_attach(it913x_fe_attach, | ||
655 | &d->i2c_adap, adap_addr, &st->it913x_config); | ||
656 | |||
657 | if (adap->id == 0 && adap->fe[0]) { | ||
658 | it913x_wr_reg(d, DEV_0_DMOD, MP2_SW_RST, 0x1); | ||
659 | it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_SW_RST, 0x1); | ||
660 | it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x0f); | ||
661 | it913x_wr_reg(d, DEV_0, EP0_TX_NAK, 0x1b); | ||
662 | it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x2f); | ||
663 | it913x_wr_reg(d, DEV_0, EP4_TX_LEN_LSB, | ||
664 | ep_size & 0xff); | ||
665 | it913x_wr_reg(d, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8); | ||
666 | ret = it913x_wr_reg(d, DEV_0, EP4_MAX_PKT, pkt_size); | ||
667 | } else if (adap->id == 1 && adap->fe[0]) { | ||
668 | it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x6f); | ||
669 | it913x_wr_reg(d, DEV_0, EP5_TX_LEN_LSB, | ||
670 | ep_size & 0xff); | ||
671 | it913x_wr_reg(d, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8); | ||
672 | it913x_wr_reg(d, DEV_0, EP5_MAX_PKT, pkt_size); | ||
673 | it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_EN, 0x1); | ||
674 | it913x_wr_reg(d, DEV_1_DMOD, MP2IF_SERIAL, 0x1); | ||
675 | it913x_wr_reg(d, DEV_1, TOP_HOSTB_SER_MODE, 0x1); | ||
676 | it913x_wr_reg(d, DEV_0_DMOD, TSIS_ENABLE, 0x1); | ||
677 | it913x_wr_reg(d, DEV_0_DMOD, MP2_SW_RST, 0x0); | ||
678 | it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_SW_RST, 0x0); | ||
679 | it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0); | ||
680 | it913x_wr_reg(d, DEV_0_DMOD, MP2IF_STOP_EN, 0x1); | ||
681 | it913x_wr_reg(d, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0); | ||
682 | ret = it913x_wr_reg(d, DEV_1_DMOD, MP2IF_STOP_EN, 0x0); | ||
683 | } else | ||
684 | return -ENODEV; | ||
685 | |||
686 | ret |= it913x_name(adap); | ||
687 | |||
688 | return ret; | ||
689 | } | ||
690 | |||
691 | /* DVB USB Driver */ | ||
692 | static int it913x_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) | ||
693 | { | ||
694 | struct it913x_state *st = d->priv; | ||
695 | |||
696 | if (st->proprietary_ir == false) { | ||
697 | rc->map_name = NULL; | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | rc->allowed_protos = RC_TYPE_NEC; | ||
702 | rc->query = it913x_rc_query; | ||
703 | rc->interval = 250; | ||
704 | |||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | static int it913x_get_adapter_count(struct dvb_usb_device *d) | ||
709 | { | ||
710 | struct it913x_state *st = d->priv; | ||
711 | if (st->it913x_config.dual_mode) | ||
712 | return 2; | ||
713 | return 1; | ||
714 | } | ||
715 | |||
716 | static struct dvb_usb_device_properties it913x_properties = { | ||
717 | .driver_name = KBUILD_MODNAME, | ||
718 | .owner = THIS_MODULE, | ||
719 | .bInterfaceNumber = 0, | ||
720 | .generic_bulk_ctrl_endpoint = 0x02, | ||
721 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
722 | |||
723 | .adapter_nr = adapter_nr, | ||
724 | .size_of_priv = sizeof(struct it913x_state), | ||
725 | |||
726 | .identify_state = it913x_identify_state, | ||
727 | .i2c_algo = &it913x_i2c_algo, | ||
728 | |||
729 | .download_firmware = it913x_download_firmware, | ||
730 | |||
731 | .frontend_attach = it913x_frontend_attach, | ||
732 | .get_rc_config = it913x_get_rc_config, | ||
733 | .get_stream_config = it913x_get_stream_config, | ||
734 | .get_adapter_count = it913x_get_adapter_count, | ||
735 | .streaming_ctrl = it913x_streaming_ctrl, | ||
736 | |||
737 | |||
738 | .adapter = { | ||
739 | { | ||
740 | .caps = DVB_USB_ADAP_HAS_PID_FILTER| | ||
741 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
742 | .pid_filter_count = 32, | ||
743 | .pid_filter = it913x_pid_filter, | ||
744 | .pid_filter_ctrl = it913x_pid_filter_ctrl, | ||
745 | .stream = | ||
746 | DVB_USB_STREAM_BULK(0x84, 10, TS_BUFFER_SIZE_MAX), | ||
747 | }, | ||
748 | { | ||
749 | .caps = DVB_USB_ADAP_HAS_PID_FILTER| | ||
750 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
751 | .pid_filter_count = 32, | ||
752 | .pid_filter = it913x_pid_filter, | ||
753 | .pid_filter_ctrl = it913x_pid_filter_ctrl, | ||
754 | .stream = | ||
755 | DVB_USB_STREAM_BULK(0x85, 10, TS_BUFFER_SIZE_MAX), | ||
756 | } | ||
757 | } | ||
758 | }; | ||
759 | |||
760 | static const struct usb_device_id it913x_id_table[] = { | ||
761 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09, | ||
762 | &it913x_properties, "Kworld UB499-2T T09(IT9137)", | ||
763 | RC_MAP_IT913X_V1) }, | ||
764 | { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135, | ||
765 | &it913x_properties, "ITE 9135 Generic", | ||
766 | RC_MAP_IT913X_V1) }, | ||
767 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137, | ||
768 | &it913x_properties, "Sveon STV22 Dual DVB-T HDTV(IT9137)", | ||
769 | RC_MAP_IT913X_V1) }, | ||
770 | { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005, | ||
771 | &it913x_properties, "ITE 9135(9005) Generic", | ||
772 | RC_MAP_IT913X_V2) }, | ||
773 | { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006, | ||
774 | &it913x_properties, "ITE 9135(9006) Generic", | ||
775 | RC_MAP_IT913X_V1) }, | ||
776 | {} /* Terminating entry */ | ||
777 | }; | ||
778 | |||
779 | MODULE_DEVICE_TABLE(usb, it913x_id_table); | ||
780 | |||
781 | static struct usb_driver it913x_driver = { | ||
782 | .name = KBUILD_MODNAME, | ||
783 | .probe = dvb_usbv2_probe, | ||
784 | .disconnect = dvb_usbv2_disconnect, | ||
785 | .suspend = dvb_usbv2_suspend, | ||
786 | .resume = dvb_usbv2_resume, | ||
787 | .id_table = it913x_id_table, | ||
788 | }; | ||
789 | |||
790 | module_usb_driver(it913x_driver); | ||
791 | |||
792 | MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); | ||
793 | MODULE_DESCRIPTION("it913x USB 2 Driver"); | ||
794 | MODULE_VERSION("1.32"); | ||
795 | MODULE_LICENSE("GPL"); | ||
796 | MODULE_FIRMWARE(FW_IT9135_V1); | ||
797 | MODULE_FIRMWARE(FW_IT9135_V2); | ||
798 | MODULE_FIRMWARE(FW_IT9137); | ||
799 | |||
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c new file mode 100644 index 000000000000..c41d9d9ec7b5 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c | |||
@@ -0,0 +1,1369 @@ | |||
1 | /* DVB USB compliant linux driver for | ||
2 | * | ||
3 | * DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395 | ||
4 | * LME2510C + LG TDQY-P001F | ||
5 | * LME2510C + BS2F7HZ0194 | ||
6 | * LME2510 + LG TDQY-P001F | ||
7 | * LME2510 + BS2F7HZ0194 | ||
8 | * | ||
9 | * MVB7395 (LME2510C+SHARP:BS2F7HZ7395) | ||
10 | * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V) | ||
11 | * | ||
12 | * MV001F (LME2510+LGTDQY-P001F) | ||
13 | * LG TDQY - P001F =(TDA8263 + TDA10086H) | ||
14 | * | ||
15 | * MVB0001F (LME2510C+LGTDQT-P001F) | ||
16 | * | ||
17 | * MV0194 (LME2510+SHARP:BS2F7HZ0194) | ||
18 | * SHARP:BS2F7HZ0194 = (STV0299+IX2410) | ||
19 | * | ||
20 | * MVB0194 (LME2510C+SHARP0194) | ||
21 | * | ||
22 | * LME2510C + M88RS2000 | ||
23 | * | ||
24 | * For firmware see Documentation/dvb/lmedm04.txt | ||
25 | * | ||
26 | * I2C addresses: | ||
27 | * 0xd0 - STV0288 - Demodulator | ||
28 | * 0xc0 - Sharp IX2505V - Tuner | ||
29 | * -- | ||
30 | * 0x1c - TDA10086 - Demodulator | ||
31 | * 0xc0 - TDA8263 - Tuner | ||
32 | * -- | ||
33 | * 0xd0 - STV0299 - Demodulator | ||
34 | * 0xc0 - IX2410 - Tuner | ||
35 | * | ||
36 | * | ||
37 | * VID = 3344 PID LME2510=1122 LME2510C=1120 | ||
38 | * | ||
39 | * Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com) | ||
40 | * LME2510(C)(C) Leaguerme (Shenzhen) MicroElectronics Co., Ltd. | ||
41 | * | ||
42 | * This program is free software; you can redistribute it and/or modify | ||
43 | * it under the terms of the GNU General Public License Version 2, as | ||
44 | * published by the Free Software Foundation. | ||
45 | * | ||
46 | * This program is distributed in the hope that it will be useful, | ||
47 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
48 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
49 | * GNU General Public License for more details. | ||
50 | * | ||
51 | * You should have received a copy of the GNU General Public License | ||
52 | * along with this program; if not, write to the Free Software | ||
53 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
54 | * | ||
55 | * | ||
56 | * see Documentation/dvb/README.dvb-usb for more information | ||
57 | * | ||
58 | * Known Issues : | ||
59 | * LME2510: Non Intel USB chipsets fail to maintain High Speed on | ||
60 | * Boot or Hot Plug. | ||
61 | * | ||
62 | * QQbox suffers from noise on LNB voltage. | ||
63 | * | ||
64 | * LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system | ||
65 | * with other tuners. After a cold reset streaming will not start. | ||
66 | * | ||
67 | * M88RS2000 suffers from loss of lock. | ||
68 | */ | ||
69 | #define DVB_USB_LOG_PREFIX "LME2510(C)" | ||
70 | #include <linux/usb.h> | ||
71 | #include <linux/usb/input.h> | ||
72 | #include <media/rc-core.h> | ||
73 | |||
74 | #include "dvb_usb.h" | ||
75 | #include "lmedm04.h" | ||
76 | #include "tda826x.h" | ||
77 | #include "tda10086.h" | ||
78 | #include "stv0288.h" | ||
79 | #include "ix2505v.h" | ||
80 | #include "stv0299.h" | ||
81 | #include "dvb-pll.h" | ||
82 | #include "z0194a.h" | ||
83 | #include "m88rs2000.h" | ||
84 | |||
85 | |||
86 | #define LME2510_C_S7395 "dvb-usb-lme2510c-s7395.fw"; | ||
87 | #define LME2510_C_LG "dvb-usb-lme2510c-lg.fw"; | ||
88 | #define LME2510_C_S0194 "dvb-usb-lme2510c-s0194.fw"; | ||
89 | #define LME2510_C_RS2000 "dvb-usb-lme2510c-rs2000.fw"; | ||
90 | #define LME2510_LG "dvb-usb-lme2510-lg.fw"; | ||
91 | #define LME2510_S0194 "dvb-usb-lme2510-s0194.fw"; | ||
92 | |||
93 | /* debug */ | ||
94 | static int dvb_usb_lme2510_debug; | ||
95 | #define lme_debug(var, level, args...) do { \ | ||
96 | if ((var >= level)) \ | ||
97 | pr_debug(DVB_USB_LOG_PREFIX": " args); \ | ||
98 | } while (0) | ||
99 | #define deb_info(level, args...) lme_debug(dvb_usb_lme2510_debug, level, args) | ||
100 | #define debug_data_snipet(level, name, p) \ | ||
101 | deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \ | ||
102 | *p, *(p+1), *(p+2), *(p+3), *(p+4), \ | ||
103 | *(p+5), *(p+6), *(p+7)); | ||
104 | #define info(args...) pr_info(DVB_USB_LOG_PREFIX": "args) | ||
105 | |||
106 | module_param_named(debug, dvb_usb_lme2510_debug, int, 0644); | ||
107 | MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); | ||
108 | |||
109 | static int dvb_usb_lme2510_firmware; | ||
110 | module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644); | ||
111 | MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG"); | ||
112 | |||
113 | static int pid_filter; | ||
114 | module_param_named(pid, pid_filter, int, 0644); | ||
115 | MODULE_PARM_DESC(pid, "set default 0=default 1=off 2=on"); | ||
116 | |||
117 | |||
118 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
119 | |||
120 | #define TUNER_DEFAULT 0x0 | ||
121 | #define TUNER_LG 0x1 | ||
122 | #define TUNER_S7395 0x2 | ||
123 | #define TUNER_S0194 0x3 | ||
124 | #define TUNER_RS2000 0x4 | ||
125 | |||
126 | struct lme2510_state { | ||
127 | u8 id; | ||
128 | u8 tuner_config; | ||
129 | u8 signal_lock; | ||
130 | u8 signal_level; | ||
131 | u8 signal_sn; | ||
132 | u8 time_key; | ||
133 | u8 last_key; | ||
134 | u8 key_timeout; | ||
135 | u8 i2c_talk_onoff; | ||
136 | u8 i2c_gate; | ||
137 | u8 i2c_tuner_gate_w; | ||
138 | u8 i2c_tuner_gate_r; | ||
139 | u8 i2c_tuner_addr; | ||
140 | u8 stream_on; | ||
141 | u8 pid_size; | ||
142 | u8 pid_off; | ||
143 | void *buffer; | ||
144 | struct urb *lme_urb; | ||
145 | void *usb_buffer; | ||
146 | int (*fe_set_voltage)(struct dvb_frontend *, fe_sec_voltage_t); | ||
147 | u8 dvb_usb_lme2510_firmware; | ||
148 | }; | ||
149 | |||
150 | static int lme2510_bulk_write(struct usb_device *dev, | ||
151 | u8 *snd, int len, u8 pipe) | ||
152 | { | ||
153 | int ret, actual_l; | ||
154 | |||
155 | ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe), | ||
156 | snd, len , &actual_l, 100); | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static int lme2510_bulk_read(struct usb_device *dev, | ||
161 | u8 *rev, int len, u8 pipe) | ||
162 | { | ||
163 | int ret, actual_l; | ||
164 | |||
165 | ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe), | ||
166 | rev, len , &actual_l, 200); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int lme2510_usb_talk(struct dvb_usb_device *d, | ||
171 | u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
172 | { | ||
173 | struct lme2510_state *st = d->priv; | ||
174 | u8 *buff; | ||
175 | int ret = 0; | ||
176 | |||
177 | if (st->usb_buffer == NULL) { | ||
178 | st->usb_buffer = kmalloc(64, GFP_KERNEL); | ||
179 | if (st->usb_buffer == NULL) { | ||
180 | info("MEM Error no memory"); | ||
181 | return -ENOMEM; | ||
182 | } | ||
183 | } | ||
184 | buff = st->usb_buffer; | ||
185 | |||
186 | ret = mutex_lock_interruptible(&d->usb_mutex); | ||
187 | |||
188 | if (ret < 0) | ||
189 | return -EAGAIN; | ||
190 | |||
191 | /* the read/write capped at 64 */ | ||
192 | memcpy(buff, wbuf, (wlen < 64) ? wlen : 64); | ||
193 | |||
194 | ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); | ||
195 | |||
196 | ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ? | ||
197 | rlen : 64 , 0x01); | ||
198 | |||
199 | if (rlen > 0) | ||
200 | memcpy(rbuf, buff, rlen); | ||
201 | |||
202 | mutex_unlock(&d->usb_mutex); | ||
203 | |||
204 | return (ret < 0) ? -ENODEV : 0; | ||
205 | } | ||
206 | |||
207 | static int lme2510_stream_restart(struct dvb_usb_device *d) | ||
208 | { | ||
209 | struct lme2510_state *st = d->priv; | ||
210 | u8 all_pids[] = LME_ALL_PIDS; | ||
211 | u8 stream_on[] = LME_ST_ON_W; | ||
212 | int ret; | ||
213 | u8 rbuff[1]; | ||
214 | if (st->pid_off) | ||
215 | ret = lme2510_usb_talk(d, all_pids, sizeof(all_pids), | ||
216 | rbuff, sizeof(rbuff)); | ||
217 | /*Restart Stream Command*/ | ||
218 | ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on), | ||
219 | rbuff, sizeof(rbuff)); | ||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) | ||
224 | { | ||
225 | struct lme2510_state *st = d->priv; | ||
226 | static u8 pid_buff[] = LME_ZERO_PID; | ||
227 | static u8 rbuf[1]; | ||
228 | u8 pid_no = index * 2; | ||
229 | u8 pid_len = pid_no + 2; | ||
230 | int ret = 0; | ||
231 | deb_info(1, "PID Setting Pid %04x", pid_out); | ||
232 | |||
233 | if (st->pid_size == 0) | ||
234 | ret |= lme2510_stream_restart(d); | ||
235 | |||
236 | pid_buff[2] = pid_no; | ||
237 | pid_buff[3] = (u8)pid_out & 0xff; | ||
238 | pid_buff[4] = pid_no + 1; | ||
239 | pid_buff[5] = (u8)(pid_out >> 8); | ||
240 | |||
241 | if (pid_len > st->pid_size) | ||
242 | st->pid_size = pid_len; | ||
243 | pid_buff[7] = 0x80 + st->pid_size; | ||
244 | |||
245 | ret |= lme2510_usb_talk(d, pid_buff , | ||
246 | sizeof(pid_buff) , rbuf, sizeof(rbuf)); | ||
247 | |||
248 | if (st->stream_on) | ||
249 | ret |= lme2510_stream_restart(d); | ||
250 | |||
251 | return ret; | ||
252 | } | ||
253 | |||
254 | static void lme2510_int_response(struct urb *lme_urb) | ||
255 | { | ||
256 | struct dvb_usb_adapter *adap = lme_urb->context; | ||
257 | struct lme2510_state *st = adap_to_priv(adap); | ||
258 | static u8 *ibuf, *rbuf; | ||
259 | int i = 0, offset; | ||
260 | u32 key; | ||
261 | |||
262 | switch (lme_urb->status) { | ||
263 | case 0: | ||
264 | case -ETIMEDOUT: | ||
265 | break; | ||
266 | case -ECONNRESET: | ||
267 | case -ENOENT: | ||
268 | case -ESHUTDOWN: | ||
269 | return; | ||
270 | default: | ||
271 | info("Error %x", lme_urb->status); | ||
272 | break; | ||
273 | } | ||
274 | |||
275 | rbuf = (u8 *) lme_urb->transfer_buffer; | ||
276 | |||
277 | offset = ((lme_urb->actual_length/8) > 4) | ||
278 | ? 4 : (lme_urb->actual_length/8) ; | ||
279 | |||
280 | for (i = 0; i < offset; ++i) { | ||
281 | ibuf = (u8 *)&rbuf[i*8]; | ||
282 | deb_info(5, "INT O/S C =%02x C/O=%02x Type =%02x%02x", | ||
283 | offset, i, ibuf[0], ibuf[1]); | ||
284 | |||
285 | switch (ibuf[0]) { | ||
286 | case 0xaa: | ||
287 | debug_data_snipet(1, "INT Remote data snipet", ibuf); | ||
288 | if ((ibuf[4] + ibuf[5]) == 0xff) { | ||
289 | key = ibuf[5]; | ||
290 | key += (ibuf[3] > 0) | ||
291 | ? (ibuf[3] ^ 0xff) << 8 : 0; | ||
292 | key += (ibuf[2] ^ 0xff) << 16; | ||
293 | deb_info(1, "INT Key =%08x", key); | ||
294 | if (adap_to_d(adap)->rc_dev != NULL) | ||
295 | rc_keydown(adap_to_d(adap)->rc_dev, | ||
296 | key, 0); | ||
297 | } | ||
298 | break; | ||
299 | case 0xbb: | ||
300 | switch (st->tuner_config) { | ||
301 | case TUNER_LG: | ||
302 | if (ibuf[2] > 0) | ||
303 | st->signal_lock = ibuf[2]; | ||
304 | st->signal_level = ibuf[4]; | ||
305 | st->signal_sn = ibuf[3]; | ||
306 | st->time_key = ibuf[7]; | ||
307 | break; | ||
308 | case TUNER_S7395: | ||
309 | case TUNER_S0194: | ||
310 | /* Tweak for earlier firmware*/ | ||
311 | if (ibuf[1] == 0x03) { | ||
312 | if (ibuf[2] > 1) | ||
313 | st->signal_lock = ibuf[2]; | ||
314 | st->signal_level = ibuf[3]; | ||
315 | st->signal_sn = ibuf[4]; | ||
316 | } else { | ||
317 | st->signal_level = ibuf[4]; | ||
318 | st->signal_sn = ibuf[5]; | ||
319 | st->signal_lock = | ||
320 | (st->signal_lock & 0xf7) + | ||
321 | ((ibuf[2] & 0x01) << 0x03); | ||
322 | } | ||
323 | break; | ||
324 | case TUNER_RS2000: | ||
325 | if (ibuf[1] == 0x3 && ibuf[6] == 0xff) | ||
326 | st->signal_lock = 0xff; | ||
327 | else | ||
328 | st->signal_lock = 0x00; | ||
329 | st->signal_level = ibuf[5]; | ||
330 | st->signal_sn = ibuf[4]; | ||
331 | st->time_key = ibuf[7]; | ||
332 | default: | ||
333 | break; | ||
334 | } | ||
335 | debug_data_snipet(5, "INT Remote data snipet in", ibuf); | ||
336 | break; | ||
337 | case 0xcc: | ||
338 | debug_data_snipet(1, "INT Control data snipet", ibuf); | ||
339 | break; | ||
340 | default: | ||
341 | debug_data_snipet(1, "INT Unknown data snipet", ibuf); | ||
342 | break; | ||
343 | } | ||
344 | } | ||
345 | usb_submit_urb(lme_urb, GFP_ATOMIC); | ||
346 | } | ||
347 | |||
348 | static int lme2510_int_read(struct dvb_usb_adapter *adap) | ||
349 | { | ||
350 | struct dvb_usb_device *d = adap_to_d(adap); | ||
351 | struct lme2510_state *lme_int = adap_to_priv(adap); | ||
352 | |||
353 | lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
354 | |||
355 | if (lme_int->lme_urb == NULL) | ||
356 | return -ENOMEM; | ||
357 | |||
358 | lme_int->buffer = usb_alloc_coherent(d->udev, 128, GFP_ATOMIC, | ||
359 | &lme_int->lme_urb->transfer_dma); | ||
360 | |||
361 | if (lme_int->buffer == NULL) | ||
362 | return -ENOMEM; | ||
363 | |||
364 | usb_fill_int_urb(lme_int->lme_urb, | ||
365 | d->udev, | ||
366 | usb_rcvintpipe(d->udev, 0xa), | ||
367 | lme_int->buffer, | ||
368 | 128, | ||
369 | lme2510_int_response, | ||
370 | adap, | ||
371 | 8); | ||
372 | |||
373 | lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
374 | |||
375 | usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC); | ||
376 | info("INT Interrupt Service Started"); | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
382 | { | ||
383 | struct dvb_usb_device *d = adap_to_d(adap); | ||
384 | struct lme2510_state *st = adap_to_priv(adap); | ||
385 | static u8 clear_pid_reg[] = LME_ALL_PIDS; | ||
386 | static u8 rbuf[1]; | ||
387 | int ret = 0; | ||
388 | |||
389 | deb_info(1, "PID Clearing Filter"); | ||
390 | |||
391 | mutex_lock(&d->i2c_mutex); | ||
392 | |||
393 | if (!onoff) { | ||
394 | ret |= lme2510_usb_talk(d, clear_pid_reg, | ||
395 | sizeof(clear_pid_reg), rbuf, sizeof(rbuf)); | ||
396 | st->pid_off = true; | ||
397 | } else | ||
398 | st->pid_off = false; | ||
399 | |||
400 | st->pid_size = 0; | ||
401 | |||
402 | mutex_unlock(&d->i2c_mutex); | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | ||
408 | int onoff) | ||
409 | { | ||
410 | struct dvb_usb_device *d = adap_to_d(adap); | ||
411 | int ret = 0; | ||
412 | |||
413 | deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__, | ||
414 | pid, index, onoff); | ||
415 | |||
416 | if (onoff) { | ||
417 | mutex_lock(&d->i2c_mutex); | ||
418 | ret |= lme2510_enable_pid(d, index, pid); | ||
419 | mutex_unlock(&d->i2c_mutex); | ||
420 | } | ||
421 | |||
422 | |||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | |||
427 | static int lme2510_return_status(struct dvb_usb_device *d) | ||
428 | { | ||
429 | int ret = 0; | ||
430 | u8 *data; | ||
431 | |||
432 | data = kzalloc(10, GFP_KERNEL); | ||
433 | if (!data) | ||
434 | return -ENOMEM; | ||
435 | |||
436 | ret |= usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), | ||
437 | 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); | ||
438 | info("Firmware Status: %x (%x)", ret , data[2]); | ||
439 | |||
440 | ret = (ret < 0) ? -ENODEV : data[2]; | ||
441 | kfree(data); | ||
442 | return ret; | ||
443 | } | ||
444 | |||
445 | static int lme2510_msg(struct dvb_usb_device *d, | ||
446 | u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
447 | { | ||
448 | int ret = 0; | ||
449 | struct lme2510_state *st = d->priv; | ||
450 | |||
451 | if (st->i2c_talk_onoff == 1) { | ||
452 | |||
453 | ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | ||
454 | |||
455 | switch (st->tuner_config) { | ||
456 | case TUNER_LG: | ||
457 | if (wbuf[2] == 0x1c) { | ||
458 | if (wbuf[3] == 0x0e) { | ||
459 | st->signal_lock = rbuf[1]; | ||
460 | if ((st->stream_on & 1) && | ||
461 | (st->signal_lock & 0x10)) { | ||
462 | lme2510_stream_restart(d); | ||
463 | st->i2c_talk_onoff = 0; | ||
464 | } | ||
465 | msleep(80); | ||
466 | } | ||
467 | } | ||
468 | break; | ||
469 | case TUNER_S7395: | ||
470 | if (wbuf[2] == 0xd0) { | ||
471 | if (wbuf[3] == 0x24) { | ||
472 | st->signal_lock = rbuf[1]; | ||
473 | if ((st->stream_on & 1) && | ||
474 | (st->signal_lock & 0x8)) { | ||
475 | lme2510_stream_restart(d); | ||
476 | st->i2c_talk_onoff = 0; | ||
477 | } | ||
478 | } | ||
479 | } | ||
480 | break; | ||
481 | case TUNER_S0194: | ||
482 | if (wbuf[2] == 0xd0) { | ||
483 | if (wbuf[3] == 0x1b) { | ||
484 | st->signal_lock = rbuf[1]; | ||
485 | if ((st->stream_on & 1) && | ||
486 | (st->signal_lock & 0x8)) { | ||
487 | lme2510_stream_restart(d); | ||
488 | st->i2c_talk_onoff = 0; | ||
489 | } | ||
490 | } | ||
491 | } | ||
492 | break; | ||
493 | case TUNER_RS2000: | ||
494 | default: | ||
495 | break; | ||
496 | } | ||
497 | } else { | ||
498 | /* TODO rewrite this section */ | ||
499 | switch (st->tuner_config) { | ||
500 | case TUNER_LG: | ||
501 | switch (wbuf[3]) { | ||
502 | case 0x0e: | ||
503 | rbuf[0] = 0x55; | ||
504 | rbuf[1] = st->signal_lock; | ||
505 | break; | ||
506 | case 0x43: | ||
507 | rbuf[0] = 0x55; | ||
508 | rbuf[1] = st->signal_level; | ||
509 | break; | ||
510 | case 0x1c: | ||
511 | rbuf[0] = 0x55; | ||
512 | rbuf[1] = st->signal_sn; | ||
513 | break; | ||
514 | case 0x15: | ||
515 | case 0x16: | ||
516 | case 0x17: | ||
517 | case 0x18: | ||
518 | rbuf[0] = 0x55; | ||
519 | rbuf[1] = 0x00; | ||
520 | break; | ||
521 | default: | ||
522 | lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | ||
523 | st->i2c_talk_onoff = 1; | ||
524 | break; | ||
525 | } | ||
526 | break; | ||
527 | case TUNER_S7395: | ||
528 | switch (wbuf[3]) { | ||
529 | case 0x10: | ||
530 | rbuf[0] = 0x55; | ||
531 | rbuf[1] = (st->signal_level & 0x80) | ||
532 | ? 0 : (st->signal_level * 2); | ||
533 | break; | ||
534 | case 0x2d: | ||
535 | rbuf[0] = 0x55; | ||
536 | rbuf[1] = st->signal_sn; | ||
537 | break; | ||
538 | case 0x24: | ||
539 | rbuf[0] = 0x55; | ||
540 | rbuf[1] = st->signal_lock; | ||
541 | break; | ||
542 | case 0x2e: | ||
543 | case 0x26: | ||
544 | case 0x27: | ||
545 | rbuf[0] = 0x55; | ||
546 | rbuf[1] = 0x00; | ||
547 | break; | ||
548 | default: | ||
549 | lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | ||
550 | st->i2c_talk_onoff = 1; | ||
551 | break; | ||
552 | } | ||
553 | break; | ||
554 | case TUNER_S0194: | ||
555 | switch (wbuf[3]) { | ||
556 | case 0x18: | ||
557 | rbuf[0] = 0x55; | ||
558 | rbuf[1] = (st->signal_level & 0x80) | ||
559 | ? 0 : (st->signal_level * 2); | ||
560 | break; | ||
561 | case 0x24: | ||
562 | rbuf[0] = 0x55; | ||
563 | rbuf[1] = st->signal_sn; | ||
564 | break; | ||
565 | case 0x1b: | ||
566 | rbuf[0] = 0x55; | ||
567 | rbuf[1] = st->signal_lock; | ||
568 | break; | ||
569 | case 0x19: | ||
570 | case 0x25: | ||
571 | case 0x1e: | ||
572 | case 0x1d: | ||
573 | rbuf[0] = 0x55; | ||
574 | rbuf[1] = 0x00; | ||
575 | break; | ||
576 | default: | ||
577 | lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | ||
578 | st->i2c_talk_onoff = 1; | ||
579 | break; | ||
580 | } | ||
581 | break; | ||
582 | case TUNER_RS2000: | ||
583 | switch (wbuf[3]) { | ||
584 | case 0x8c: | ||
585 | rbuf[0] = 0x55; | ||
586 | rbuf[1] = 0xff; | ||
587 | if (st->last_key == st->time_key) { | ||
588 | st->key_timeout++; | ||
589 | if (st->key_timeout > 5) | ||
590 | rbuf[1] = 0; | ||
591 | } else | ||
592 | st->key_timeout = 0; | ||
593 | st->last_key = st->time_key; | ||
594 | break; | ||
595 | default: | ||
596 | lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | ||
597 | st->i2c_talk_onoff = 1; | ||
598 | break; | ||
599 | } | ||
600 | default: | ||
601 | break; | ||
602 | } | ||
603 | |||
604 | deb_info(4, "I2C From Interrupt Message out(%02x) in(%02x)", | ||
605 | wbuf[3], rbuf[1]); | ||
606 | |||
607 | } | ||
608 | |||
609 | return ret; | ||
610 | } | ||
611 | |||
612 | |||
613 | static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
614 | int num) | ||
615 | { | ||
616 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
617 | struct lme2510_state *st = d->priv; | ||
618 | static u8 obuf[64], ibuf[64]; | ||
619 | int i, read, read_o; | ||
620 | u16 len; | ||
621 | u8 gate = st->i2c_gate; | ||
622 | |||
623 | mutex_lock(&d->i2c_mutex); | ||
624 | |||
625 | if (gate == 0) | ||
626 | gate = 5; | ||
627 | |||
628 | for (i = 0; i < num; i++) { | ||
629 | read_o = 1 & (msg[i].flags & I2C_M_RD); | ||
630 | read = i+1 < num && (msg[i+1].flags & I2C_M_RD); | ||
631 | read |= read_o; | ||
632 | gate = (msg[i].addr == st->i2c_tuner_addr) | ||
633 | ? (read) ? st->i2c_tuner_gate_r | ||
634 | : st->i2c_tuner_gate_w | ||
635 | : st->i2c_gate; | ||
636 | obuf[0] = gate | (read << 7); | ||
637 | |||
638 | if (gate == 5) | ||
639 | obuf[1] = (read) ? 2 : msg[i].len + 1; | ||
640 | else | ||
641 | obuf[1] = msg[i].len + read + 1; | ||
642 | |||
643 | obuf[2] = msg[i].addr; | ||
644 | if (read) { | ||
645 | if (read_o) | ||
646 | len = 3; | ||
647 | else { | ||
648 | memcpy(&obuf[3], msg[i].buf, msg[i].len); | ||
649 | obuf[msg[i].len+3] = msg[i+1].len; | ||
650 | len = msg[i].len+4; | ||
651 | } | ||
652 | } else { | ||
653 | memcpy(&obuf[3], msg[i].buf, msg[i].len); | ||
654 | len = msg[i].len+3; | ||
655 | } | ||
656 | |||
657 | if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) { | ||
658 | deb_info(1, "i2c transfer failed."); | ||
659 | mutex_unlock(&d->i2c_mutex); | ||
660 | return -EAGAIN; | ||
661 | } | ||
662 | |||
663 | if (read) { | ||
664 | if (read_o) | ||
665 | memcpy(msg[i].buf, &ibuf[1], msg[i].len); | ||
666 | else { | ||
667 | memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len); | ||
668 | i++; | ||
669 | } | ||
670 | } | ||
671 | } | ||
672 | |||
673 | mutex_unlock(&d->i2c_mutex); | ||
674 | return i; | ||
675 | } | ||
676 | |||
677 | static u32 lme2510_i2c_func(struct i2c_adapter *adapter) | ||
678 | { | ||
679 | return I2C_FUNC_I2C; | ||
680 | } | ||
681 | |||
682 | static struct i2c_algorithm lme2510_i2c_algo = { | ||
683 | .master_xfer = lme2510_i2c_xfer, | ||
684 | .functionality = lme2510_i2c_func, | ||
685 | }; | ||
686 | |||
687 | static int lme2510_streaming_ctrl(struct dvb_frontend *fe, int onoff) | ||
688 | { | ||
689 | struct dvb_usb_adapter *adap = fe_to_adap(fe); | ||
690 | struct dvb_usb_device *d = adap_to_d(adap); | ||
691 | struct lme2510_state *st = adap_to_priv(adap); | ||
692 | static u8 clear_reg_3[] = LME_ALL_PIDS; | ||
693 | static u8 rbuf[1]; | ||
694 | int ret = 0, rlen = sizeof(rbuf); | ||
695 | |||
696 | deb_info(1, "STM (%02x)", onoff); | ||
697 | |||
698 | /* Streaming is started by FE_HAS_LOCK */ | ||
699 | if (onoff == 1) | ||
700 | st->stream_on = 1; | ||
701 | else { | ||
702 | deb_info(1, "STM Steam Off"); | ||
703 | /* mutex is here only to avoid collision with I2C */ | ||
704 | mutex_lock(&d->i2c_mutex); | ||
705 | |||
706 | ret = lme2510_usb_talk(d, clear_reg_3, | ||
707 | sizeof(clear_reg_3), rbuf, rlen); | ||
708 | st->stream_on = 0; | ||
709 | st->i2c_talk_onoff = 1; | ||
710 | |||
711 | mutex_unlock(&d->i2c_mutex); | ||
712 | } | ||
713 | |||
714 | return (ret < 0) ? -ENODEV : 0; | ||
715 | } | ||
716 | |||
717 | static u8 check_sum(u8 *p, u8 len) | ||
718 | { | ||
719 | u8 sum = 0; | ||
720 | while (len--) | ||
721 | sum += *p++; | ||
722 | return sum; | ||
723 | } | ||
724 | |||
725 | static int lme2510_download_firmware(struct dvb_usb_device *d, | ||
726 | const struct firmware *fw) | ||
727 | { | ||
728 | int ret = 0; | ||
729 | u8 *data; | ||
730 | u16 j, wlen, len_in, start, end; | ||
731 | u8 packet_size, dlen, i; | ||
732 | u8 *fw_data; | ||
733 | |||
734 | packet_size = 0x31; | ||
735 | len_in = 1; | ||
736 | |||
737 | data = kzalloc(128, GFP_KERNEL); | ||
738 | if (!data) { | ||
739 | info("FRM Could not start Firmware Download"\ | ||
740 | "(Buffer allocation failed)"); | ||
741 | return -ENOMEM; | ||
742 | } | ||
743 | |||
744 | info("FRM Starting Firmware Download"); | ||
745 | |||
746 | for (i = 1; i < 3; i++) { | ||
747 | start = (i == 1) ? 0 : 512; | ||
748 | end = (i == 1) ? 512 : fw->size; | ||
749 | for (j = start; j < end; j += (packet_size+1)) { | ||
750 | fw_data = (u8 *)(fw->data + j); | ||
751 | if ((end - j) > packet_size) { | ||
752 | data[0] = i; | ||
753 | dlen = packet_size; | ||
754 | } else { | ||
755 | data[0] = i | 0x80; | ||
756 | dlen = (u8)(end - j)-1; | ||
757 | } | ||
758 | data[1] = dlen; | ||
759 | memcpy(&data[2], fw_data, dlen+1); | ||
760 | wlen = (u8) dlen + 4; | ||
761 | data[wlen-1] = check_sum(fw_data, dlen+1); | ||
762 | deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3], | ||
763 | data[dlen+2], data[dlen+3]); | ||
764 | lme2510_usb_talk(d, data, wlen, data, len_in); | ||
765 | ret |= (data[0] == 0x88) ? 0 : -1; | ||
766 | } | ||
767 | } | ||
768 | |||
769 | data[0] = 0x8a; | ||
770 | len_in = 1; | ||
771 | msleep(2000); | ||
772 | lme2510_usb_talk(d, data, len_in, data, len_in); | ||
773 | msleep(400); | ||
774 | |||
775 | if (ret < 0) | ||
776 | info("FRM Firmware Download Failed (%04x)" , ret); | ||
777 | else | ||
778 | info("FRM Firmware Download Completed - Resetting Device"); | ||
779 | |||
780 | kfree(data); | ||
781 | return RECONNECTS_USB; | ||
782 | } | ||
783 | |||
784 | static void lme_coldreset(struct dvb_usb_device *d) | ||
785 | { | ||
786 | u8 data[1] = {0}; | ||
787 | data[0] = 0x0a; | ||
788 | info("FRM Firmware Cold Reset"); | ||
789 | |||
790 | lme2510_usb_talk(d, data, sizeof(data), data, sizeof(data)); | ||
791 | |||
792 | return; | ||
793 | } | ||
794 | |||
795 | static const char fw_c_s7395[] = LME2510_C_S7395; | ||
796 | static const char fw_c_lg[] = LME2510_C_LG; | ||
797 | static const char fw_c_s0194[] = LME2510_C_S0194; | ||
798 | static const char fw_c_rs2000[] = LME2510_C_RS2000; | ||
799 | static const char fw_lg[] = LME2510_LG; | ||
800 | static const char fw_s0194[] = LME2510_S0194; | ||
801 | |||
802 | const char *lme_firmware_switch(struct dvb_usb_device *d, int cold) | ||
803 | { | ||
804 | struct lme2510_state *st = d->priv; | ||
805 | struct usb_device *udev = d->udev; | ||
806 | const struct firmware *fw = NULL; | ||
807 | const char *fw_lme; | ||
808 | int ret = 0; | ||
809 | |||
810 | cold = (cold > 0) ? (cold & 1) : 0; | ||
811 | |||
812 | switch (le16_to_cpu(udev->descriptor.idProduct)) { | ||
813 | case 0x1122: | ||
814 | switch (st->dvb_usb_lme2510_firmware) { | ||
815 | default: | ||
816 | st->dvb_usb_lme2510_firmware = TUNER_S0194; | ||
817 | case TUNER_S0194: | ||
818 | fw_lme = fw_s0194; | ||
819 | ret = request_firmware(&fw, fw_lme, &udev->dev); | ||
820 | if (ret == 0) { | ||
821 | cold = 0; | ||
822 | break; | ||
823 | } | ||
824 | st->dvb_usb_lme2510_firmware = TUNER_LG; | ||
825 | case TUNER_LG: | ||
826 | fw_lme = fw_lg; | ||
827 | ret = request_firmware(&fw, fw_lme, &udev->dev); | ||
828 | if (ret == 0) | ||
829 | break; | ||
830 | st->dvb_usb_lme2510_firmware = TUNER_DEFAULT; | ||
831 | break; | ||
832 | } | ||
833 | break; | ||
834 | case 0x1120: | ||
835 | switch (st->dvb_usb_lme2510_firmware) { | ||
836 | default: | ||
837 | st->dvb_usb_lme2510_firmware = TUNER_S7395; | ||
838 | case TUNER_S7395: | ||
839 | fw_lme = fw_c_s7395; | ||
840 | ret = request_firmware(&fw, fw_lme, &udev->dev); | ||
841 | if (ret == 0) { | ||
842 | cold = 0; | ||
843 | break; | ||
844 | } | ||
845 | st->dvb_usb_lme2510_firmware = TUNER_LG; | ||
846 | case TUNER_LG: | ||
847 | fw_lme = fw_c_lg; | ||
848 | ret = request_firmware(&fw, fw_lme, &udev->dev); | ||
849 | if (ret == 0) | ||
850 | break; | ||
851 | st->dvb_usb_lme2510_firmware = TUNER_S0194; | ||
852 | case TUNER_S0194: | ||
853 | fw_lme = fw_c_s0194; | ||
854 | ret = request_firmware(&fw, fw_lme, &udev->dev); | ||
855 | if (ret == 0) | ||
856 | break; | ||
857 | st->dvb_usb_lme2510_firmware = TUNER_DEFAULT; | ||
858 | cold = 0; | ||
859 | break; | ||
860 | } | ||
861 | break; | ||
862 | case 0x22f0: | ||
863 | fw_lme = fw_c_rs2000; | ||
864 | st->dvb_usb_lme2510_firmware = TUNER_RS2000; | ||
865 | break; | ||
866 | default: | ||
867 | fw_lme = fw_c_s7395; | ||
868 | } | ||
869 | |||
870 | release_firmware(fw); | ||
871 | |||
872 | if (cold) { | ||
873 | dvb_usb_lme2510_firmware = st->dvb_usb_lme2510_firmware; | ||
874 | info("FRM Changing to %s firmware", fw_lme); | ||
875 | lme_coldreset(d); | ||
876 | return NULL; | ||
877 | } | ||
878 | |||
879 | return fw_lme; | ||
880 | } | ||
881 | |||
882 | static int lme2510_kill_urb(struct usb_data_stream *stream) | ||
883 | { | ||
884 | int i; | ||
885 | |||
886 | for (i = 0; i < stream->urbs_submitted; i++) { | ||
887 | deb_info(3, "killing URB no. %d.", i); | ||
888 | /* stop the URB */ | ||
889 | usb_kill_urb(stream->urb_list[i]); | ||
890 | } | ||
891 | stream->urbs_submitted = 0; | ||
892 | |||
893 | return 0; | ||
894 | } | ||
895 | |||
896 | static struct tda10086_config tda10086_config = { | ||
897 | .demod_address = 0x1c, | ||
898 | .invert = 0, | ||
899 | .diseqc_tone = 1, | ||
900 | .xtal_freq = TDA10086_XTAL_16M, | ||
901 | }; | ||
902 | |||
903 | static struct stv0288_config lme_config = { | ||
904 | .demod_address = 0xd0, | ||
905 | .min_delay_ms = 15, | ||
906 | .inittab = s7395_inittab, | ||
907 | }; | ||
908 | |||
909 | static struct ix2505v_config lme_tuner = { | ||
910 | .tuner_address = 0xc0, | ||
911 | .min_delay_ms = 100, | ||
912 | .tuner_gain = 0x0, | ||
913 | .tuner_chargepump = 0x3, | ||
914 | }; | ||
915 | |||
916 | static struct stv0299_config sharp_z0194_config = { | ||
917 | .demod_address = 0xd0, | ||
918 | .inittab = sharp_z0194a_inittab, | ||
919 | .mclk = 88000000UL, | ||
920 | .invert = 0, | ||
921 | .skip_reinit = 0, | ||
922 | .lock_output = STV0299_LOCKOUTPUT_1, | ||
923 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
924 | .min_delay_ms = 100, | ||
925 | .set_symbol_rate = sharp_z0194a_set_symbol_rate, | ||
926 | }; | ||
927 | |||
928 | static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe, | ||
929 | int caller) | ||
930 | { | ||
931 | struct dvb_usb_adapter *adap = fe_to_adap(fe); | ||
932 | struct dvb_usb_device *d = adap_to_d(adap); | ||
933 | struct lme2510_state *st = d->priv; | ||
934 | |||
935 | mutex_lock(&d->i2c_mutex); | ||
936 | if ((st->i2c_talk_onoff == 1) && (st->stream_on & 1)) { | ||
937 | st->i2c_talk_onoff = 0; | ||
938 | lme2510_stream_restart(d); | ||
939 | } | ||
940 | mutex_unlock(&d->i2c_mutex); | ||
941 | |||
942 | return 0; | ||
943 | } | ||
944 | |||
945 | static struct m88rs2000_config m88rs2000_config = { | ||
946 | .demod_addr = 0xd0, | ||
947 | .tuner_addr = 0xc0, | ||
948 | .set_ts_params = dm04_rs2000_set_ts_param, | ||
949 | }; | ||
950 | |||
951 | static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, | ||
952 | fe_sec_voltage_t voltage) | ||
953 | { | ||
954 | struct dvb_usb_device *d = fe_to_d(fe); | ||
955 | struct lme2510_state *st = fe_to_priv(fe); | ||
956 | static u8 voltage_low[] = LME_VOLTAGE_L; | ||
957 | static u8 voltage_high[] = LME_VOLTAGE_H; | ||
958 | static u8 rbuf[1]; | ||
959 | int ret = 0, len = 3, rlen = 1; | ||
960 | |||
961 | mutex_lock(&d->i2c_mutex); | ||
962 | |||
963 | switch (voltage) { | ||
964 | case SEC_VOLTAGE_18: | ||
965 | ret |= lme2510_usb_talk(d, | ||
966 | voltage_high, len, rbuf, rlen); | ||
967 | break; | ||
968 | |||
969 | case SEC_VOLTAGE_OFF: | ||
970 | case SEC_VOLTAGE_13: | ||
971 | default: | ||
972 | ret |= lme2510_usb_talk(d, | ||
973 | voltage_low, len, rbuf, rlen); | ||
974 | break; | ||
975 | } | ||
976 | |||
977 | mutex_unlock(&d->i2c_mutex); | ||
978 | |||
979 | if (st->tuner_config == TUNER_RS2000) | ||
980 | if (st->fe_set_voltage) | ||
981 | st->fe_set_voltage(fe, voltage); | ||
982 | |||
983 | |||
984 | return (ret < 0) ? -ENODEV : 0; | ||
985 | } | ||
986 | |||
987 | static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe, | ||
988 | u16 *strength) | ||
989 | { | ||
990 | struct lme2510_state *st = fe_to_priv(fe); | ||
991 | |||
992 | *strength = (u16)((u32)st->signal_level * 0xffff / 0xff); | ||
993 | |||
994 | return 0; | ||
995 | } | ||
996 | |||
997 | static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
998 | { | ||
999 | struct lme2510_state *st = fe_to_priv(fe); | ||
1000 | |||
1001 | *snr = (u16)((u32)st->signal_sn * 0xffff / 0x7f); | ||
1002 | |||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | static int dm04_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
1007 | { | ||
1008 | *ber = 0; | ||
1009 | |||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | static int dm04_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
1014 | { | ||
1015 | *ucblocks = 0; | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | static int lme_name(struct dvb_usb_adapter *adap) | ||
1021 | { | ||
1022 | struct dvb_usb_device *d = adap_to_d(adap); | ||
1023 | struct lme2510_state *st = adap_to_priv(adap); | ||
1024 | const char *desc = d->name; | ||
1025 | char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395", | ||
1026 | " SHARP:BS2F7HZ0194", " RS2000"}; | ||
1027 | char *name = adap->fe[0]->ops.info.name; | ||
1028 | |||
1029 | strlcpy(name, desc, 128); | ||
1030 | strlcat(name, fe_name[st->tuner_config], 128); | ||
1031 | |||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) | ||
1036 | { | ||
1037 | struct dvb_usb_device *d = adap_to_d(adap); | ||
1038 | struct lme2510_state *st = d->priv; | ||
1039 | int ret = 0; | ||
1040 | |||
1041 | st->i2c_talk_onoff = 1; | ||
1042 | switch (le16_to_cpu(d->udev->descriptor.idProduct)) { | ||
1043 | case 0x1122: | ||
1044 | case 0x1120: | ||
1045 | st->i2c_gate = 4; | ||
1046 | adap->fe[0] = dvb_attach(tda10086_attach, | ||
1047 | &tda10086_config, &d->i2c_adap); | ||
1048 | if (adap->fe[0]) { | ||
1049 | info("TUN Found Frontend TDA10086"); | ||
1050 | st->i2c_tuner_gate_w = 4; | ||
1051 | st->i2c_tuner_gate_r = 4; | ||
1052 | st->i2c_tuner_addr = 0xc0; | ||
1053 | st->tuner_config = TUNER_LG; | ||
1054 | if (st->dvb_usb_lme2510_firmware != TUNER_LG) { | ||
1055 | st->dvb_usb_lme2510_firmware = TUNER_LG; | ||
1056 | ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV; | ||
1057 | } | ||
1058 | break; | ||
1059 | } | ||
1060 | |||
1061 | st->i2c_gate = 4; | ||
1062 | adap->fe[0] = dvb_attach(stv0299_attach, | ||
1063 | &sharp_z0194_config, &d->i2c_adap); | ||
1064 | if (adap->fe[0]) { | ||
1065 | info("FE Found Stv0299"); | ||
1066 | st->i2c_tuner_gate_w = 4; | ||
1067 | st->i2c_tuner_gate_r = 5; | ||
1068 | st->i2c_tuner_addr = 0xc0; | ||
1069 | st->tuner_config = TUNER_S0194; | ||
1070 | if (st->dvb_usb_lme2510_firmware != TUNER_S0194) { | ||
1071 | st->dvb_usb_lme2510_firmware = TUNER_S0194; | ||
1072 | ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV; | ||
1073 | } | ||
1074 | break; | ||
1075 | } | ||
1076 | |||
1077 | st->i2c_gate = 5; | ||
1078 | adap->fe[0] = dvb_attach(stv0288_attach, &lme_config, | ||
1079 | &d->i2c_adap); | ||
1080 | |||
1081 | if (adap->fe[0]) { | ||
1082 | info("FE Found Stv0288"); | ||
1083 | st->i2c_tuner_gate_w = 4; | ||
1084 | st->i2c_tuner_gate_r = 5; | ||
1085 | st->i2c_tuner_addr = 0xc0; | ||
1086 | st->tuner_config = TUNER_S7395; | ||
1087 | if (st->dvb_usb_lme2510_firmware != TUNER_S7395) { | ||
1088 | st->dvb_usb_lme2510_firmware = TUNER_S7395; | ||
1089 | ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV; | ||
1090 | } | ||
1091 | break; | ||
1092 | } | ||
1093 | case 0x22f0: | ||
1094 | st->i2c_gate = 5; | ||
1095 | adap->fe[0] = dvb_attach(m88rs2000_attach, | ||
1096 | &m88rs2000_config, &d->i2c_adap); | ||
1097 | |||
1098 | if (adap->fe[0]) { | ||
1099 | info("FE Found M88RS2000"); | ||
1100 | st->i2c_tuner_gate_w = 5; | ||
1101 | st->i2c_tuner_gate_r = 5; | ||
1102 | st->i2c_tuner_addr = 0xc0; | ||
1103 | st->tuner_config = TUNER_RS2000; | ||
1104 | st->fe_set_voltage = | ||
1105 | adap->fe[0]->ops.set_voltage; | ||
1106 | |||
1107 | adap->fe[0]->ops.read_signal_strength = | ||
1108 | dm04_rs2000_read_signal_strength; | ||
1109 | adap->fe[0]->ops.read_snr = | ||
1110 | dm04_rs2000_read_snr; | ||
1111 | adap->fe[0]->ops.read_ber = | ||
1112 | dm04_read_ber; | ||
1113 | adap->fe[0]->ops.read_ucblocks = | ||
1114 | dm04_read_ucblocks; | ||
1115 | } | ||
1116 | break; | ||
1117 | } | ||
1118 | |||
1119 | if (adap->fe[0] == NULL) { | ||
1120 | info("DM04/QQBOX Not Powered up or not Supported"); | ||
1121 | return -ENODEV; | ||
1122 | } | ||
1123 | |||
1124 | if (ret) { | ||
1125 | if (adap->fe[0]) { | ||
1126 | dvb_frontend_detach(adap->fe[0]); | ||
1127 | adap->fe[0] = NULL; | ||
1128 | } | ||
1129 | d->rc_map = NULL; | ||
1130 | return -ENODEV; | ||
1131 | } | ||
1132 | |||
1133 | adap->fe[0]->ops.set_voltage = dm04_lme2510_set_voltage; | ||
1134 | ret = lme_name(adap); | ||
1135 | return ret; | ||
1136 | } | ||
1137 | |||
1138 | static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) | ||
1139 | { | ||
1140 | struct dvb_usb_device *d = adap_to_d(adap); | ||
1141 | struct lme2510_state *st = adap_to_priv(adap); | ||
1142 | char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"}; | ||
1143 | int ret = 0; | ||
1144 | |||
1145 | switch (st->tuner_config) { | ||
1146 | case TUNER_LG: | ||
1147 | if (dvb_attach(tda826x_attach, adap->fe[0], 0xc0, | ||
1148 | &d->i2c_adap, 1)) | ||
1149 | ret = st->tuner_config; | ||
1150 | break; | ||
1151 | case TUNER_S7395: | ||
1152 | if (dvb_attach(ix2505v_attach , adap->fe[0], &lme_tuner, | ||
1153 | &d->i2c_adap)) | ||
1154 | ret = st->tuner_config; | ||
1155 | break; | ||
1156 | case TUNER_S0194: | ||
1157 | if (dvb_attach(dvb_pll_attach , adap->fe[0], 0xc0, | ||
1158 | &d->i2c_adap, DVB_PLL_OPERA1)) | ||
1159 | ret = st->tuner_config; | ||
1160 | break; | ||
1161 | case TUNER_RS2000: | ||
1162 | ret = st->tuner_config; | ||
1163 | break; | ||
1164 | default: | ||
1165 | break; | ||
1166 | } | ||
1167 | |||
1168 | if (ret) | ||
1169 | info("TUN Found %s tuner", tun_msg[ret]); | ||
1170 | else { | ||
1171 | info("TUN No tuner found --- resetting device"); | ||
1172 | lme_coldreset(d); | ||
1173 | return -ENODEV; | ||
1174 | } | ||
1175 | |||
1176 | /* Start the Interrupt*/ | ||
1177 | ret = lme2510_int_read(adap); | ||
1178 | if (ret < 0) { | ||
1179 | info("INT Unable to start Interrupt Service"); | ||
1180 | return -ENODEV; | ||
1181 | } | ||
1182 | |||
1183 | return ret; | ||
1184 | } | ||
1185 | |||
1186 | static int lme2510_powerup(struct dvb_usb_device *d, int onoff) | ||
1187 | { | ||
1188 | struct lme2510_state *st = d->priv; | ||
1189 | static u8 lnb_on[] = LNB_ON; | ||
1190 | static u8 lnb_off[] = LNB_OFF; | ||
1191 | static u8 rbuf[1]; | ||
1192 | int ret = 0, len = 3, rlen = 1; | ||
1193 | |||
1194 | mutex_lock(&d->i2c_mutex); | ||
1195 | |||
1196 | if (onoff) | ||
1197 | ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen); | ||
1198 | else | ||
1199 | ret = lme2510_usb_talk(d, lnb_off, len, rbuf, rlen); | ||
1200 | |||
1201 | st->i2c_talk_onoff = 1; | ||
1202 | |||
1203 | mutex_unlock(&d->i2c_mutex); | ||
1204 | |||
1205 | return ret; | ||
1206 | } | ||
1207 | |||
1208 | static int lme2510_get_adapter_count(struct dvb_usb_device *d) | ||
1209 | { | ||
1210 | return 1; | ||
1211 | } | ||
1212 | |||
1213 | static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) | ||
1214 | { | ||
1215 | struct lme2510_state *st = d->priv; | ||
1216 | |||
1217 | usb_reset_configuration(d->udev); | ||
1218 | |||
1219 | usb_set_interface(d->udev, | ||
1220 | d->intf->cur_altsetting->desc.bInterfaceNumber, 1); | ||
1221 | |||
1222 | st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware; | ||
1223 | |||
1224 | if (lme2510_return_status(d) == 0x44) { | ||
1225 | *name = lme_firmware_switch(d, 0); | ||
1226 | return COLD; | ||
1227 | } | ||
1228 | |||
1229 | return 0; | ||
1230 | } | ||
1231 | |||
1232 | static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, | ||
1233 | struct usb_data_stream_properties *stream) | ||
1234 | { | ||
1235 | struct dvb_usb_adapter *adap = fe_to_adap(fe); | ||
1236 | struct dvb_usb_device *d = adap_to_d(adap); | ||
1237 | |||
1238 | if (adap == NULL) | ||
1239 | return 0; | ||
1240 | /* Turn PID filter on the fly by module option */ | ||
1241 | if (pid_filter == 2) { | ||
1242 | adap->pid_filtering = 1; | ||
1243 | adap->max_feed_count = 15; | ||
1244 | } | ||
1245 | |||
1246 | if (!(le16_to_cpu(d->udev->descriptor.idProduct) | ||
1247 | == 0x1122)) | ||
1248 | stream->endpoint = 0x8; | ||
1249 | |||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | static int lme2510_get_rc_config(struct dvb_usb_device *d, | ||
1254 | struct dvb_usb_rc *rc) | ||
1255 | { | ||
1256 | rc->allowed_protos = RC_TYPE_NEC; | ||
1257 | return 0; | ||
1258 | } | ||
1259 | |||
1260 | static void *lme2510_exit_int(struct dvb_usb_device *d) | ||
1261 | { | ||
1262 | struct lme2510_state *st = d->priv; | ||
1263 | struct dvb_usb_adapter *adap = &d->adapter[0]; | ||
1264 | void *buffer = NULL; | ||
1265 | |||
1266 | if (adap != NULL) { | ||
1267 | lme2510_kill_urb(&adap->stream); | ||
1268 | } | ||
1269 | |||
1270 | if (st->usb_buffer != NULL) { | ||
1271 | st->i2c_talk_onoff = 1; | ||
1272 | st->signal_lock = 0; | ||
1273 | st->signal_level = 0; | ||
1274 | st->signal_sn = 0; | ||
1275 | buffer = st->usb_buffer; | ||
1276 | } | ||
1277 | |||
1278 | if (st->lme_urb != NULL) { | ||
1279 | usb_kill_urb(st->lme_urb); | ||
1280 | usb_free_coherent(d->udev, 128, st->buffer, | ||
1281 | st->lme_urb->transfer_dma); | ||
1282 | info("Interrupt Service Stopped"); | ||
1283 | } | ||
1284 | |||
1285 | return buffer; | ||
1286 | } | ||
1287 | |||
1288 | static void lme2510_exit(struct dvb_usb_device *d) | ||
1289 | { | ||
1290 | void *usb_buffer; | ||
1291 | |||
1292 | if (d != NULL) { | ||
1293 | usb_buffer = lme2510_exit_int(d); | ||
1294 | if (usb_buffer != NULL) | ||
1295 | kfree(usb_buffer); | ||
1296 | } | ||
1297 | } | ||
1298 | |||
1299 | static struct dvb_usb_device_properties lme2510_props = { | ||
1300 | .driver_name = KBUILD_MODNAME, | ||
1301 | .owner = THIS_MODULE, | ||
1302 | .bInterfaceNumber = 0, | ||
1303 | .adapter_nr = adapter_nr, | ||
1304 | .size_of_priv = sizeof(struct lme2510_state), | ||
1305 | |||
1306 | .download_firmware = lme2510_download_firmware, | ||
1307 | |||
1308 | .power_ctrl = lme2510_powerup, | ||
1309 | .identify_state = lme2510_identify_state, | ||
1310 | .i2c_algo = &lme2510_i2c_algo, | ||
1311 | |||
1312 | .frontend_attach = dm04_lme2510_frontend_attach, | ||
1313 | .tuner_attach = dm04_lme2510_tuner, | ||
1314 | .get_stream_config = lme2510_get_stream_config, | ||
1315 | .get_adapter_count = lme2510_get_adapter_count, | ||
1316 | .streaming_ctrl = lme2510_streaming_ctrl, | ||
1317 | |||
1318 | .get_rc_config = lme2510_get_rc_config, | ||
1319 | |||
1320 | .exit = lme2510_exit, | ||
1321 | .adapter = { | ||
1322 | { | ||
1323 | .caps = DVB_USB_ADAP_HAS_PID_FILTER| | ||
1324 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
1325 | .pid_filter_count = 15, | ||
1326 | .pid_filter = lme2510_pid_filter, | ||
1327 | .pid_filter_ctrl = lme2510_pid_filter_ctrl, | ||
1328 | .stream = | ||
1329 | DVB_USB_STREAM_BULK(0x86, 10, 4096), | ||
1330 | }, | ||
1331 | { | ||
1332 | } | ||
1333 | }, | ||
1334 | }; | ||
1335 | |||
1336 | static const struct usb_device_id lme2510_id_table[] = { | ||
1337 | { DVB_USB_DEVICE(0x3344, 0x1122, &lme2510_props, | ||
1338 | "DM04_LME2510_DVB-S", RC_MAP_LME2510) }, | ||
1339 | { DVB_USB_DEVICE(0x3344, 0x1120, &lme2510_props, | ||
1340 | "DM04_LME2510C_DVB-S", RC_MAP_LME2510) }, | ||
1341 | { DVB_USB_DEVICE(0x3344, 0x22f0, &lme2510_props, | ||
1342 | "DM04_LME2510C_DVB-S RS2000", RC_MAP_LME2510) }, | ||
1343 | {} /* Terminating entry */ | ||
1344 | }; | ||
1345 | |||
1346 | MODULE_DEVICE_TABLE(usb, lme2510_id_table); | ||
1347 | |||
1348 | static struct usb_driver lme2510_driver = { | ||
1349 | .name = KBUILD_MODNAME, | ||
1350 | .probe = dvb_usbv2_probe, | ||
1351 | .disconnect = dvb_usbv2_disconnect, | ||
1352 | .id_table = lme2510_id_table, | ||
1353 | .no_dynamic_id = 1, | ||
1354 | .soft_unbind = 1, | ||
1355 | }; | ||
1356 | |||
1357 | module_usb_driver(lme2510_driver); | ||
1358 | |||
1359 | MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); | ||
1360 | MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0"); | ||
1361 | MODULE_VERSION("2.06"); | ||
1362 | MODULE_LICENSE("GPL"); | ||
1363 | MODULE_FIRMWARE(LME2510_C_S7395); | ||
1364 | MODULE_FIRMWARE(LME2510_C_LG); | ||
1365 | MODULE_FIRMWARE(LME2510_C_S0194); | ||
1366 | MODULE_FIRMWARE(LME2510_C_RS2000); | ||
1367 | MODULE_FIRMWARE(LME2510_LG); | ||
1368 | MODULE_FIRMWARE(LME2510_S0194); | ||
1369 | |||
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.h b/drivers/media/usb/dvb-usb-v2/lmedm04.h new file mode 100644 index 000000000000..e9c207205c2f --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.h | |||
@@ -0,0 +1,175 @@ | |||
1 | /* DVB USB compliant linux driver for | ||
2 | * | ||
3 | * DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395 | ||
4 | * LME2510C + LG TDQY-P001F | ||
5 | * LME2510 + LG TDQY-P001F | ||
6 | * | ||
7 | * MVB7395 (LME2510C+SHARP:BS2F7HZ7395) | ||
8 | * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V) | ||
9 | * | ||
10 | * MVB001F (LME2510+LGTDQT-P001F) | ||
11 | * LG TDQY - P001F =(TDA8263 + TDA10086H) | ||
12 | * | ||
13 | * MVB0001F (LME2510C+LGTDQT-P001F) | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the Free | ||
17 | * Software Foundation, version 2. | ||
18 | * * | ||
19 | * see Documentation/dvb/README.dvb-usb for more information | ||
20 | */ | ||
21 | #ifndef _DVB_USB_LME2510_H_ | ||
22 | #define _DVB_USB_LME2510_H_ | ||
23 | |||
24 | /* Streamer & PID | ||
25 | * | ||
26 | * Note: These commands do not actually stop the streaming | ||
27 | * but form some kind of packet filtering/stream count | ||
28 | * or tuning related functions. | ||
29 | * 06 XX | ||
30 | * offset 1 = 00 Enable Streaming | ||
31 | * | ||
32 | * | ||
33 | * PID | ||
34 | * 03 XX XX ----> reg number ---> setting....20 XX | ||
35 | * offset 1 = length | ||
36 | * offset 2 = start of data | ||
37 | * end byte -1 = 20 | ||
38 | * end byte = clear pid always a0, other wise 9c, 9a ?? | ||
39 | * | ||
40 | */ | ||
41 | #define LME_ST_ON_W {0x06, 0x00} | ||
42 | #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} | ||
43 | #define LME_ZERO_PID {0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c} | ||
44 | #define LME_ALL_PIDS {0x03, 0x06, 0x00, 0xff, 0x01, 0x1f, 0x20, 0x81} | ||
45 | |||
46 | /* LNB Voltage | ||
47 | * 07 XX XX | ||
48 | * offset 1 = 01 | ||
49 | * offset 2 = 00=Voltage low 01=Voltage high | ||
50 | * | ||
51 | * LNB Power | ||
52 | * 03 01 XX | ||
53 | * offset 2 = 00=ON 01=OFF | ||
54 | */ | ||
55 | |||
56 | #define LME_VOLTAGE_L {0x07, 0x01, 0x00} | ||
57 | #define LME_VOLTAGE_H {0x07, 0x01, 0x01} | ||
58 | #define LNB_ON {0x3a, 0x01, 0x00} | ||
59 | #define LNB_OFF {0x3a, 0x01, 0x01} | ||
60 | |||
61 | /* Initial stv0288 settings for 7395 Frontend */ | ||
62 | static u8 s7395_inittab[] = { | ||
63 | 0x01, 0x15, | ||
64 | 0x02, 0x20, | ||
65 | 0x03, 0xa0, | ||
66 | 0x04, 0xa0, | ||
67 | 0x05, 0x12, | ||
68 | 0x06, 0x00, | ||
69 | 0x09, 0x00, | ||
70 | 0x0a, 0x04, | ||
71 | 0x0b, 0x00, | ||
72 | 0x0c, 0x00, | ||
73 | 0x0d, 0x00, | ||
74 | 0x0e, 0xc1, | ||
75 | 0x0f, 0x54, | ||
76 | 0x11, 0x7a, | ||
77 | 0x12, 0x03, | ||
78 | 0x13, 0x48, | ||
79 | 0x14, 0x84, | ||
80 | 0x15, 0xc5, | ||
81 | 0x16, 0xb8, | ||
82 | 0x17, 0x9c, | ||
83 | 0x18, 0x00, | ||
84 | 0x19, 0xa6, | ||
85 | 0x1a, 0x88, | ||
86 | 0x1b, 0x8f, | ||
87 | 0x1c, 0xf0, | ||
88 | 0x20, 0x0b, | ||
89 | 0x21, 0x54, | ||
90 | 0x22, 0xff, | ||
91 | 0x23, 0x01, | ||
92 | 0x28, 0x46, | ||
93 | 0x29, 0x66, | ||
94 | 0x2a, 0x90, | ||
95 | 0x2b, 0xfa, | ||
96 | 0x2c, 0xd9, | ||
97 | 0x30, 0x0, | ||
98 | 0x31, 0x1e, | ||
99 | 0x32, 0x14, | ||
100 | 0x33, 0x0f, | ||
101 | 0x34, 0x09, | ||
102 | 0x35, 0x0c, | ||
103 | 0x36, 0x05, | ||
104 | 0x37, 0x2f, | ||
105 | 0x38, 0x16, | ||
106 | 0x39, 0xbd, | ||
107 | 0x3a, 0x0, | ||
108 | 0x3b, 0x13, | ||
109 | 0x3c, 0x11, | ||
110 | 0x3d, 0x30, | ||
111 | 0x40, 0x63, | ||
112 | 0x41, 0x04, | ||
113 | 0x42, 0x20, | ||
114 | 0x43, 0x00, | ||
115 | 0x44, 0x00, | ||
116 | 0x45, 0x00, | ||
117 | 0x46, 0x00, | ||
118 | 0x47, 0x00, | ||
119 | 0x4a, 0x00, | ||
120 | 0x50, 0x10, | ||
121 | 0x51, 0x36, | ||
122 | 0x52, 0x21, | ||
123 | 0x53, 0x94, | ||
124 | 0x54, 0xb2, | ||
125 | 0x55, 0x29, | ||
126 | 0x56, 0x64, | ||
127 | 0x57, 0x2b, | ||
128 | 0x58, 0x54, | ||
129 | 0x59, 0x86, | ||
130 | 0x5a, 0x00, | ||
131 | 0x5b, 0x9b, | ||
132 | 0x5c, 0x08, | ||
133 | 0x5d, 0x7f, | ||
134 | 0x5e, 0xff, | ||
135 | 0x5f, 0x8d, | ||
136 | 0x70, 0x0, | ||
137 | 0x71, 0x0, | ||
138 | 0x72, 0x0, | ||
139 | 0x74, 0x0, | ||
140 | 0x75, 0x0, | ||
141 | 0x76, 0x0, | ||
142 | 0x81, 0x0, | ||
143 | 0x82, 0x3f, | ||
144 | 0x83, 0x3f, | ||
145 | 0x84, 0x0, | ||
146 | 0x85, 0x0, | ||
147 | 0x88, 0x0, | ||
148 | 0x89, 0x0, | ||
149 | 0x8a, 0x0, | ||
150 | 0x8b, 0x0, | ||
151 | 0x8c, 0x0, | ||
152 | 0x90, 0x0, | ||
153 | 0x91, 0x0, | ||
154 | 0x92, 0x0, | ||
155 | 0x93, 0x0, | ||
156 | 0x94, 0x1c, | ||
157 | 0x97, 0x0, | ||
158 | 0xa0, 0x48, | ||
159 | 0xa1, 0x0, | ||
160 | 0xb0, 0xb8, | ||
161 | 0xb1, 0x3a, | ||
162 | 0xb2, 0x10, | ||
163 | 0xb3, 0x82, | ||
164 | 0xb4, 0x80, | ||
165 | 0xb5, 0x82, | ||
166 | 0xb6, 0x82, | ||
167 | 0xb7, 0x82, | ||
168 | 0xb8, 0x20, | ||
169 | 0xb9, 0x0, | ||
170 | 0xf0, 0x0, | ||
171 | 0xf1, 0x0, | ||
172 | 0xf2, 0xc0, | ||
173 | 0xff, 0xff, | ||
174 | }; | ||
175 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c new file mode 100644 index 000000000000..d83df4bb72d3 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c | |||
@@ -0,0 +1,612 @@ | |||
1 | /* | ||
2 | * mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #include "mxl111sf-demod.h" | ||
22 | #include "mxl111sf-reg.h" | ||
23 | |||
24 | /* debug */ | ||
25 | static int mxl111sf_demod_debug; | ||
26 | module_param_named(debug, mxl111sf_demod_debug, int, 0644); | ||
27 | MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); | ||
28 | |||
29 | #define mxl_dbg(fmt, arg...) \ | ||
30 | if (mxl111sf_demod_debug) \ | ||
31 | mxl_printk(KERN_DEBUG, fmt, ##arg) | ||
32 | |||
33 | /* ------------------------------------------------------------------------ */ | ||
34 | |||
35 | struct mxl111sf_demod_state { | ||
36 | struct mxl111sf_state *mxl_state; | ||
37 | |||
38 | struct mxl111sf_demod_config *cfg; | ||
39 | |||
40 | struct dvb_frontend fe; | ||
41 | }; | ||
42 | |||
43 | /* ------------------------------------------------------------------------ */ | ||
44 | |||
45 | static int mxl111sf_demod_read_reg(struct mxl111sf_demod_state *state, | ||
46 | u8 addr, u8 *data) | ||
47 | { | ||
48 | return (state->cfg->read_reg) ? | ||
49 | state->cfg->read_reg(state->mxl_state, addr, data) : | ||
50 | -EINVAL; | ||
51 | } | ||
52 | |||
53 | static int mxl111sf_demod_write_reg(struct mxl111sf_demod_state *state, | ||
54 | u8 addr, u8 data) | ||
55 | { | ||
56 | return (state->cfg->write_reg) ? | ||
57 | state->cfg->write_reg(state->mxl_state, addr, data) : | ||
58 | -EINVAL; | ||
59 | } | ||
60 | |||
61 | static | ||
62 | int mxl111sf_demod_program_regs(struct mxl111sf_demod_state *state, | ||
63 | struct mxl111sf_reg_ctrl_info *ctrl_reg_info) | ||
64 | { | ||
65 | return (state->cfg->program_regs) ? | ||
66 | state->cfg->program_regs(state->mxl_state, ctrl_reg_info) : | ||
67 | -EINVAL; | ||
68 | } | ||
69 | |||
70 | /* ------------------------------------------------------------------------ */ | ||
71 | /* TPS */ | ||
72 | |||
73 | static | ||
74 | int mxl1x1sf_demod_get_tps_code_rate(struct mxl111sf_demod_state *state, | ||
75 | fe_code_rate_t *code_rate) | ||
76 | { | ||
77 | u8 val; | ||
78 | int ret = mxl111sf_demod_read_reg(state, V6_CODE_RATE_TPS_REG, &val); | ||
79 | /* bit<2:0> - 000:1/2, 001:2/3, 010:3/4, 011:5/6, 100:7/8 */ | ||
80 | if (mxl_fail(ret)) | ||
81 | goto fail; | ||
82 | |||
83 | switch (val & V6_CODE_RATE_TPS_MASK) { | ||
84 | case 0: | ||
85 | *code_rate = FEC_1_2; | ||
86 | break; | ||
87 | case 1: | ||
88 | *code_rate = FEC_2_3; | ||
89 | break; | ||
90 | case 2: | ||
91 | *code_rate = FEC_3_4; | ||
92 | break; | ||
93 | case 3: | ||
94 | *code_rate = FEC_5_6; | ||
95 | break; | ||
96 | case 4: | ||
97 | *code_rate = FEC_7_8; | ||
98 | break; | ||
99 | } | ||
100 | fail: | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static | ||
105 | int mxl1x1sf_demod_get_tps_modulation(struct mxl111sf_demod_state *state, | ||
106 | fe_modulation_t *modulation) | ||
107 | { | ||
108 | u8 val; | ||
109 | int ret = mxl111sf_demod_read_reg(state, V6_MODORDER_TPS_REG, &val); | ||
110 | /* Constellation, 00 : QPSK, 01 : 16QAM, 10:64QAM */ | ||
111 | if (mxl_fail(ret)) | ||
112 | goto fail; | ||
113 | |||
114 | switch ((val & V6_PARAM_CONSTELLATION_MASK) >> 4) { | ||
115 | case 0: | ||
116 | *modulation = QPSK; | ||
117 | break; | ||
118 | case 1: | ||
119 | *modulation = QAM_16; | ||
120 | break; | ||
121 | case 2: | ||
122 | *modulation = QAM_64; | ||
123 | break; | ||
124 | } | ||
125 | fail: | ||
126 | return ret; | ||
127 | } | ||
128 | |||
129 | static | ||
130 | int mxl1x1sf_demod_get_tps_guard_fft_mode(struct mxl111sf_demod_state *state, | ||
131 | fe_transmit_mode_t *fft_mode) | ||
132 | { | ||
133 | u8 val; | ||
134 | int ret = mxl111sf_demod_read_reg(state, V6_MODE_TPS_REG, &val); | ||
135 | /* FFT Mode, 00:2K, 01:8K, 10:4K */ | ||
136 | if (mxl_fail(ret)) | ||
137 | goto fail; | ||
138 | |||
139 | switch ((val & V6_PARAM_FFT_MODE_MASK) >> 2) { | ||
140 | case 0: | ||
141 | *fft_mode = TRANSMISSION_MODE_2K; | ||
142 | break; | ||
143 | case 1: | ||
144 | *fft_mode = TRANSMISSION_MODE_8K; | ||
145 | break; | ||
146 | case 2: | ||
147 | *fft_mode = TRANSMISSION_MODE_4K; | ||
148 | break; | ||
149 | } | ||
150 | fail: | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static | ||
155 | int mxl1x1sf_demod_get_tps_guard_interval(struct mxl111sf_demod_state *state, | ||
156 | fe_guard_interval_t *guard) | ||
157 | { | ||
158 | u8 val; | ||
159 | int ret = mxl111sf_demod_read_reg(state, V6_CP_TPS_REG, &val); | ||
160 | /* 00:1/32, 01:1/16, 10:1/8, 11:1/4 */ | ||
161 | if (mxl_fail(ret)) | ||
162 | goto fail; | ||
163 | |||
164 | switch ((val & V6_PARAM_GI_MASK) >> 4) { | ||
165 | case 0: | ||
166 | *guard = GUARD_INTERVAL_1_32; | ||
167 | break; | ||
168 | case 1: | ||
169 | *guard = GUARD_INTERVAL_1_16; | ||
170 | break; | ||
171 | case 2: | ||
172 | *guard = GUARD_INTERVAL_1_8; | ||
173 | break; | ||
174 | case 3: | ||
175 | *guard = GUARD_INTERVAL_1_4; | ||
176 | break; | ||
177 | } | ||
178 | fail: | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | static | ||
183 | int mxl1x1sf_demod_get_tps_hierarchy(struct mxl111sf_demod_state *state, | ||
184 | fe_hierarchy_t *hierarchy) | ||
185 | { | ||
186 | u8 val; | ||
187 | int ret = mxl111sf_demod_read_reg(state, V6_TPS_HIERACHY_REG, &val); | ||
188 | /* bit<6:4> - 000:Non hierarchy, 001:1, 010:2, 011:4 */ | ||
189 | if (mxl_fail(ret)) | ||
190 | goto fail; | ||
191 | |||
192 | switch ((val & V6_TPS_HIERARCHY_INFO_MASK) >> 6) { | ||
193 | case 0: | ||
194 | *hierarchy = HIERARCHY_NONE; | ||
195 | break; | ||
196 | case 1: | ||
197 | *hierarchy = HIERARCHY_1; | ||
198 | break; | ||
199 | case 2: | ||
200 | *hierarchy = HIERARCHY_2; | ||
201 | break; | ||
202 | case 3: | ||
203 | *hierarchy = HIERARCHY_4; | ||
204 | break; | ||
205 | } | ||
206 | fail: | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | /* ------------------------------------------------------------------------ */ | ||
211 | /* LOCKS */ | ||
212 | |||
213 | static | ||
214 | int mxl1x1sf_demod_get_sync_lock_status(struct mxl111sf_demod_state *state, | ||
215 | int *sync_lock) | ||
216 | { | ||
217 | u8 val = 0; | ||
218 | int ret = mxl111sf_demod_read_reg(state, V6_SYNC_LOCK_REG, &val); | ||
219 | if (mxl_fail(ret)) | ||
220 | goto fail; | ||
221 | *sync_lock = (val & SYNC_LOCK_MASK) >> 4; | ||
222 | fail: | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static | ||
227 | int mxl1x1sf_demod_get_rs_lock_status(struct mxl111sf_demod_state *state, | ||
228 | int *rs_lock) | ||
229 | { | ||
230 | u8 val = 0; | ||
231 | int ret = mxl111sf_demod_read_reg(state, V6_RS_LOCK_DET_REG, &val); | ||
232 | if (mxl_fail(ret)) | ||
233 | goto fail; | ||
234 | *rs_lock = (val & RS_LOCK_DET_MASK) >> 3; | ||
235 | fail: | ||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | static | ||
240 | int mxl1x1sf_demod_get_tps_lock_status(struct mxl111sf_demod_state *state, | ||
241 | int *tps_lock) | ||
242 | { | ||
243 | u8 val = 0; | ||
244 | int ret = mxl111sf_demod_read_reg(state, V6_TPS_LOCK_REG, &val); | ||
245 | if (mxl_fail(ret)) | ||
246 | goto fail; | ||
247 | *tps_lock = (val & V6_PARAM_TPS_LOCK_MASK) >> 6; | ||
248 | fail: | ||
249 | return ret; | ||
250 | } | ||
251 | |||
252 | static | ||
253 | int mxl1x1sf_demod_get_fec_lock_status(struct mxl111sf_demod_state *state, | ||
254 | int *fec_lock) | ||
255 | { | ||
256 | u8 val = 0; | ||
257 | int ret = mxl111sf_demod_read_reg(state, V6_IRQ_STATUS_REG, &val); | ||
258 | if (mxl_fail(ret)) | ||
259 | goto fail; | ||
260 | *fec_lock = (val & IRQ_MASK_FEC_LOCK) >> 4; | ||
261 | fail: | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | #if 0 | ||
266 | static | ||
267 | int mxl1x1sf_demod_get_cp_lock_status(struct mxl111sf_demod_state *state, | ||
268 | int *cp_lock) | ||
269 | { | ||
270 | u8 val = 0; | ||
271 | int ret = mxl111sf_demod_read_reg(state, V6_CP_LOCK_DET_REG, &val); | ||
272 | if (mxl_fail(ret)) | ||
273 | goto fail; | ||
274 | *cp_lock = (val & V6_CP_LOCK_DET_MASK) >> 2; | ||
275 | fail: | ||
276 | return ret; | ||
277 | } | ||
278 | #endif | ||
279 | |||
280 | static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state *state) | ||
281 | { | ||
282 | return mxl111sf_demod_write_reg(state, 0x0e, 0xff); | ||
283 | } | ||
284 | |||
285 | /* ------------------------------------------------------------------------ */ | ||
286 | |||
287 | static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe) | ||
288 | { | ||
289 | struct mxl111sf_demod_state *state = fe->demodulator_priv; | ||
290 | int ret = 0; | ||
291 | |||
292 | struct mxl111sf_reg_ctrl_info phy_pll_patch[] = { | ||
293 | {0x00, 0xff, 0x01}, /* change page to 1 */ | ||
294 | {0x40, 0xff, 0x05}, | ||
295 | {0x40, 0xff, 0x01}, | ||
296 | {0x41, 0xff, 0xca}, | ||
297 | {0x41, 0xff, 0xc0}, | ||
298 | {0x00, 0xff, 0x00}, /* change page to 0 */ | ||
299 | {0, 0, 0} | ||
300 | }; | ||
301 | |||
302 | mxl_dbg("()"); | ||
303 | |||
304 | if (fe->ops.tuner_ops.set_params) { | ||
305 | ret = fe->ops.tuner_ops.set_params(fe); | ||
306 | if (mxl_fail(ret)) | ||
307 | goto fail; | ||
308 | msleep(50); | ||
309 | } | ||
310 | ret = mxl111sf_demod_program_regs(state, phy_pll_patch); | ||
311 | mxl_fail(ret); | ||
312 | msleep(50); | ||
313 | ret = mxl1x1sf_demod_reset_irq_status(state); | ||
314 | mxl_fail(ret); | ||
315 | msleep(100); | ||
316 | fail: | ||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | /* ------------------------------------------------------------------------ */ | ||
321 | |||
322 | #if 0 | ||
323 | /* resets TS Packet error count */ | ||
324 | /* After setting 7th bit of V5_PER_COUNT_RESET_REG, it should be reset to 0. */ | ||
325 | static | ||
326 | int mxl1x1sf_demod_reset_packet_error_count(struct mxl111sf_demod_state *state) | ||
327 | { | ||
328 | struct mxl111sf_reg_ctrl_info reset_per_count[] = { | ||
329 | {0x20, 0x01, 0x01}, | ||
330 | {0x20, 0x01, 0x00}, | ||
331 | {0, 0, 0} | ||
332 | }; | ||
333 | return mxl111sf_demod_program_regs(state, reset_per_count); | ||
334 | } | ||
335 | #endif | ||
336 | |||
337 | /* returns TS Packet error count */ | ||
338 | /* PER Count = FEC_PER_COUNT * (2 ** (FEC_PER_SCALE * 4)) */ | ||
339 | static int mxl111sf_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
340 | { | ||
341 | struct mxl111sf_demod_state *state = fe->demodulator_priv; | ||
342 | u32 fec_per_count, fec_per_scale; | ||
343 | u8 val; | ||
344 | int ret; | ||
345 | |||
346 | *ucblocks = 0; | ||
347 | |||
348 | /* FEC_PER_COUNT Register */ | ||
349 | ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_COUNT_REG, &val); | ||
350 | if (mxl_fail(ret)) | ||
351 | goto fail; | ||
352 | |||
353 | fec_per_count = val; | ||
354 | |||
355 | /* FEC_PER_SCALE Register */ | ||
356 | ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_SCALE_REG, &val); | ||
357 | if (mxl_fail(ret)) | ||
358 | goto fail; | ||
359 | |||
360 | val &= V6_FEC_PER_SCALE_MASK; | ||
361 | val *= 4; | ||
362 | |||
363 | fec_per_scale = 1 << val; | ||
364 | |||
365 | fec_per_count *= fec_per_scale; | ||
366 | |||
367 | *ucblocks = fec_per_count; | ||
368 | fail: | ||
369 | return ret; | ||
370 | } | ||
371 | |||
372 | #ifdef MXL111SF_DEMOD_ENABLE_CALCULATIONS | ||
373 | /* FIXME: leaving this enabled breaks the build on some architectures, | ||
374 | * and we shouldn't have any floating point math in the kernel, anyway. | ||
375 | * | ||
376 | * These macros need to be re-written, but it's harmless to simply | ||
377 | * return zero for now. */ | ||
378 | #define CALCULATE_BER(avg_errors, count) \ | ||
379 | ((u32)(avg_errors * 4)/(count*64*188*8)) | ||
380 | #define CALCULATE_SNR(data) \ | ||
381 | ((u32)((10 * (u32)data / 64) - 2.5)) | ||
382 | #else | ||
383 | #define CALCULATE_BER(avg_errors, count) 0 | ||
384 | #define CALCULATE_SNR(data) 0 | ||
385 | #endif | ||
386 | |||
387 | static int mxl111sf_demod_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
388 | { | ||
389 | struct mxl111sf_demod_state *state = fe->demodulator_priv; | ||
390 | u8 val1, val2, val3; | ||
391 | int ret; | ||
392 | |||
393 | *ber = 0; | ||
394 | |||
395 | ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_LSB_REG, &val1); | ||
396 | if (mxl_fail(ret)) | ||
397 | goto fail; | ||
398 | ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_MSB_REG, &val2); | ||
399 | if (mxl_fail(ret)) | ||
400 | goto fail; | ||
401 | ret = mxl111sf_demod_read_reg(state, V6_N_ACCUMULATE_REG, &val3); | ||
402 | if (mxl_fail(ret)) | ||
403 | goto fail; | ||
404 | |||
405 | *ber = CALCULATE_BER((val1 | (val2 << 8)), val3); | ||
406 | fail: | ||
407 | return ret; | ||
408 | } | ||
409 | |||
410 | static int mxl111sf_demod_calc_snr(struct mxl111sf_demod_state *state, | ||
411 | u16 *snr) | ||
412 | { | ||
413 | u8 val1, val2; | ||
414 | int ret; | ||
415 | |||
416 | *snr = 0; | ||
417 | |||
418 | ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_LSB_REG, &val1); | ||
419 | if (mxl_fail(ret)) | ||
420 | goto fail; | ||
421 | ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_MSB_REG, &val2); | ||
422 | if (mxl_fail(ret)) | ||
423 | goto fail; | ||
424 | |||
425 | *snr = CALCULATE_SNR(val1 | ((val2 & 0x03) << 8)); | ||
426 | fail: | ||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | static int mxl111sf_demod_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
431 | { | ||
432 | struct mxl111sf_demod_state *state = fe->demodulator_priv; | ||
433 | |||
434 | int ret = mxl111sf_demod_calc_snr(state, snr); | ||
435 | if (mxl_fail(ret)) | ||
436 | goto fail; | ||
437 | |||
438 | *snr /= 10; /* 0.1 dB */ | ||
439 | fail: | ||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | static int mxl111sf_demod_read_status(struct dvb_frontend *fe, | ||
444 | fe_status_t *status) | ||
445 | { | ||
446 | struct mxl111sf_demod_state *state = fe->demodulator_priv; | ||
447 | int ret, locked, cr_lock, sync_lock, fec_lock; | ||
448 | |||
449 | *status = 0; | ||
450 | |||
451 | ret = mxl1x1sf_demod_get_rs_lock_status(state, &locked); | ||
452 | if (mxl_fail(ret)) | ||
453 | goto fail; | ||
454 | ret = mxl1x1sf_demod_get_tps_lock_status(state, &cr_lock); | ||
455 | if (mxl_fail(ret)) | ||
456 | goto fail; | ||
457 | ret = mxl1x1sf_demod_get_sync_lock_status(state, &sync_lock); | ||
458 | if (mxl_fail(ret)) | ||
459 | goto fail; | ||
460 | ret = mxl1x1sf_demod_get_fec_lock_status(state, &fec_lock); | ||
461 | if (mxl_fail(ret)) | ||
462 | goto fail; | ||
463 | |||
464 | if (locked) | ||
465 | *status |= FE_HAS_SIGNAL; | ||
466 | if (cr_lock) | ||
467 | *status |= FE_HAS_CARRIER; | ||
468 | if (sync_lock) | ||
469 | *status |= FE_HAS_SYNC; | ||
470 | if (fec_lock) /* false positives? */ | ||
471 | *status |= FE_HAS_VITERBI; | ||
472 | |||
473 | if ((locked) && (cr_lock) && (sync_lock)) | ||
474 | *status |= FE_HAS_LOCK; | ||
475 | fail: | ||
476 | return ret; | ||
477 | } | ||
478 | |||
479 | static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe, | ||
480 | u16 *signal_strength) | ||
481 | { | ||
482 | struct mxl111sf_demod_state *state = fe->demodulator_priv; | ||
483 | fe_modulation_t modulation; | ||
484 | u16 snr; | ||
485 | |||
486 | mxl111sf_demod_calc_snr(state, &snr); | ||
487 | mxl1x1sf_demod_get_tps_modulation(state, &modulation); | ||
488 | |||
489 | switch (modulation) { | ||
490 | case QPSK: | ||
491 | *signal_strength = (snr >= 1300) ? | ||
492 | min(65535, snr * 44) : snr * 38; | ||
493 | break; | ||
494 | case QAM_16: | ||
495 | *signal_strength = (snr >= 1500) ? | ||
496 | min(65535, snr * 38) : snr * 33; | ||
497 | break; | ||
498 | case QAM_64: | ||
499 | *signal_strength = (snr >= 2000) ? | ||
500 | min(65535, snr * 29) : snr * 25; | ||
501 | break; | ||
502 | default: | ||
503 | *signal_strength = 0; | ||
504 | return -EINVAL; | ||
505 | } | ||
506 | |||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe) | ||
511 | { | ||
512 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||
513 | struct mxl111sf_demod_state *state = fe->demodulator_priv; | ||
514 | |||
515 | mxl_dbg("()"); | ||
516 | #if 0 | ||
517 | p->inversion = /* FIXME */ ? INVERSION_ON : INVERSION_OFF; | ||
518 | #endif | ||
519 | if (fe->ops.tuner_ops.get_bandwidth) | ||
520 | fe->ops.tuner_ops.get_bandwidth(fe, &p->bandwidth_hz); | ||
521 | if (fe->ops.tuner_ops.get_frequency) | ||
522 | fe->ops.tuner_ops.get_frequency(fe, &p->frequency); | ||
523 | mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_HP); | ||
524 | mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_LP); | ||
525 | mxl1x1sf_demod_get_tps_modulation(state, &p->modulation); | ||
526 | mxl1x1sf_demod_get_tps_guard_fft_mode(state, | ||
527 | &p->transmission_mode); | ||
528 | mxl1x1sf_demod_get_tps_guard_interval(state, | ||
529 | &p->guard_interval); | ||
530 | mxl1x1sf_demod_get_tps_hierarchy(state, | ||
531 | &p->hierarchy); | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static | ||
537 | int mxl111sf_demod_get_tune_settings(struct dvb_frontend *fe, | ||
538 | struct dvb_frontend_tune_settings *tune) | ||
539 | { | ||
540 | tune->min_delay_ms = 1000; | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static void mxl111sf_demod_release(struct dvb_frontend *fe) | ||
545 | { | ||
546 | struct mxl111sf_demod_state *state = fe->demodulator_priv; | ||
547 | mxl_dbg("()"); | ||
548 | kfree(state); | ||
549 | fe->demodulator_priv = NULL; | ||
550 | } | ||
551 | |||
552 | static struct dvb_frontend_ops mxl111sf_demod_ops = { | ||
553 | .delsys = { SYS_DVBT }, | ||
554 | .info = { | ||
555 | .name = "MaxLinear MxL111SF DVB-T demodulator", | ||
556 | .frequency_min = 177000000, | ||
557 | .frequency_max = 858000000, | ||
558 | .frequency_stepsize = 166666, | ||
559 | .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
560 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
561 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | | ||
562 | FE_CAN_QAM_AUTO | | ||
563 | FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | | ||
564 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER | ||
565 | }, | ||
566 | .release = mxl111sf_demod_release, | ||
567 | #if 0 | ||
568 | .init = mxl111sf_init, | ||
569 | .i2c_gate_ctrl = mxl111sf_i2c_gate_ctrl, | ||
570 | #endif | ||
571 | .set_frontend = mxl111sf_demod_set_frontend, | ||
572 | .get_frontend = mxl111sf_demod_get_frontend, | ||
573 | .get_tune_settings = mxl111sf_demod_get_tune_settings, | ||
574 | .read_status = mxl111sf_demod_read_status, | ||
575 | .read_signal_strength = mxl111sf_demod_read_signal_strength, | ||
576 | .read_ber = mxl111sf_demod_read_ber, | ||
577 | .read_snr = mxl111sf_demod_read_snr, | ||
578 | .read_ucblocks = mxl111sf_demod_read_ucblocks, | ||
579 | }; | ||
580 | |||
581 | struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state, | ||
582 | struct mxl111sf_demod_config *cfg) | ||
583 | { | ||
584 | struct mxl111sf_demod_state *state = NULL; | ||
585 | |||
586 | mxl_dbg("()"); | ||
587 | |||
588 | state = kzalloc(sizeof(struct mxl111sf_demod_state), GFP_KERNEL); | ||
589 | if (state == NULL) | ||
590 | return NULL; | ||
591 | |||
592 | state->mxl_state = mxl_state; | ||
593 | state->cfg = cfg; | ||
594 | |||
595 | memcpy(&state->fe.ops, &mxl111sf_demod_ops, | ||
596 | sizeof(struct dvb_frontend_ops)); | ||
597 | |||
598 | state->fe.demodulator_priv = state; | ||
599 | return &state->fe; | ||
600 | } | ||
601 | EXPORT_SYMBOL_GPL(mxl111sf_demod_attach); | ||
602 | |||
603 | MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver"); | ||
604 | MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>"); | ||
605 | MODULE_LICENSE("GPL"); | ||
606 | MODULE_VERSION("0.1"); | ||
607 | |||
608 | /* | ||
609 | * Local variables: | ||
610 | * c-basic-offset: 8 | ||
611 | * End: | ||
612 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h new file mode 100644 index 000000000000..432706ae5274 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * mxl111sf-demod.h - driver for the MaxLinear MXL111SF DVB-T demodulator | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #ifndef __MXL111SF_DEMOD_H__ | ||
22 | #define __MXL111SF_DEMOD_H__ | ||
23 | |||
24 | #include "dvb_frontend.h" | ||
25 | #include "mxl111sf.h" | ||
26 | |||
27 | struct mxl111sf_demod_config { | ||
28 | int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data); | ||
29 | int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data); | ||
30 | int (*program_regs)(struct mxl111sf_state *state, | ||
31 | struct mxl111sf_reg_ctrl_info *ctrl_reg_info); | ||
32 | }; | ||
33 | |||
34 | #if defined(CONFIG_DVB_USB_MXL111SF) || \ | ||
35 | (defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE)) | ||
36 | extern | ||
37 | struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state, | ||
38 | struct mxl111sf_demod_config *cfg); | ||
39 | #else | ||
40 | static inline | ||
41 | struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state, | ||
42 | struct mxl111sf_demod_config *cfg) | ||
43 | { | ||
44 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
45 | return NULL; | ||
46 | } | ||
47 | #endif /* CONFIG_DVB_USB_MXL111SF */ | ||
48 | |||
49 | #endif /* __MXL111SF_DEMOD_H__ */ | ||
50 | |||
51 | /* | ||
52 | * Local variables: | ||
53 | * c-basic-offset: 8 | ||
54 | * End: | ||
55 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c new file mode 100644 index 000000000000..e4121cb8f5ef --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c | |||
@@ -0,0 +1,763 @@ | |||
1 | /* | ||
2 | * mxl111sf-gpio.c - driver for the MaxLinear MXL111SF | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #include "mxl111sf-gpio.h" | ||
22 | #include "mxl111sf-i2c.h" | ||
23 | #include "mxl111sf.h" | ||
24 | |||
25 | /* ------------------------------------------------------------------------- */ | ||
26 | |||
27 | #define MXL_GPIO_MUX_REG_0 0x84 | ||
28 | #define MXL_GPIO_MUX_REG_1 0x89 | ||
29 | #define MXL_GPIO_MUX_REG_2 0x82 | ||
30 | |||
31 | #define MXL_GPIO_DIR_INPUT 0 | ||
32 | #define MXL_GPIO_DIR_OUTPUT 1 | ||
33 | |||
34 | |||
35 | static int mxl111sf_set_gpo_state(struct mxl111sf_state *state, u8 pin, u8 val) | ||
36 | { | ||
37 | int ret; | ||
38 | u8 tmp; | ||
39 | |||
40 | mxl_debug_adv("(%d, %d)", pin, val); | ||
41 | |||
42 | if ((pin > 0) && (pin < 8)) { | ||
43 | ret = mxl111sf_read_reg(state, 0x19, &tmp); | ||
44 | if (mxl_fail(ret)) | ||
45 | goto fail; | ||
46 | tmp &= ~(1 << (pin - 1)); | ||
47 | tmp |= (val << (pin - 1)); | ||
48 | ret = mxl111sf_write_reg(state, 0x19, tmp); | ||
49 | if (mxl_fail(ret)) | ||
50 | goto fail; | ||
51 | } else if (pin <= 10) { | ||
52 | if (pin == 0) | ||
53 | pin += 7; | ||
54 | ret = mxl111sf_read_reg(state, 0x30, &tmp); | ||
55 | if (mxl_fail(ret)) | ||
56 | goto fail; | ||
57 | tmp &= ~(1 << (pin - 3)); | ||
58 | tmp |= (val << (pin - 3)); | ||
59 | ret = mxl111sf_write_reg(state, 0x30, tmp); | ||
60 | if (mxl_fail(ret)) | ||
61 | goto fail; | ||
62 | } else | ||
63 | ret = -EINVAL; | ||
64 | fail: | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | static int mxl111sf_get_gpi_state(struct mxl111sf_state *state, u8 pin, u8 *val) | ||
69 | { | ||
70 | int ret; | ||
71 | u8 tmp; | ||
72 | |||
73 | mxl_debug("(0x%02x)", pin); | ||
74 | |||
75 | *val = 0; | ||
76 | |||
77 | switch (pin) { | ||
78 | case 0: | ||
79 | case 1: | ||
80 | case 2: | ||
81 | case 3: | ||
82 | ret = mxl111sf_read_reg(state, 0x23, &tmp); | ||
83 | if (mxl_fail(ret)) | ||
84 | goto fail; | ||
85 | *val = (tmp >> (pin + 4)) & 0x01; | ||
86 | break; | ||
87 | case 4: | ||
88 | case 5: | ||
89 | case 6: | ||
90 | case 7: | ||
91 | ret = mxl111sf_read_reg(state, 0x2f, &tmp); | ||
92 | if (mxl_fail(ret)) | ||
93 | goto fail; | ||
94 | *val = (tmp >> pin) & 0x01; | ||
95 | break; | ||
96 | case 8: | ||
97 | case 9: | ||
98 | case 10: | ||
99 | ret = mxl111sf_read_reg(state, 0x22, &tmp); | ||
100 | if (mxl_fail(ret)) | ||
101 | goto fail; | ||
102 | *val = (tmp >> (pin - 3)) & 0x01; | ||
103 | break; | ||
104 | default: | ||
105 | return -EINVAL; /* invalid pin */ | ||
106 | } | ||
107 | fail: | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | struct mxl_gpio_cfg { | ||
112 | u8 pin; | ||
113 | u8 dir; | ||
114 | u8 val; | ||
115 | }; | ||
116 | |||
117 | static int mxl111sf_config_gpio_pins(struct mxl111sf_state *state, | ||
118 | struct mxl_gpio_cfg *gpio_cfg) | ||
119 | { | ||
120 | int ret; | ||
121 | u8 tmp; | ||
122 | |||
123 | mxl_debug_adv("(%d, %d)", gpio_cfg->pin, gpio_cfg->dir); | ||
124 | |||
125 | switch (gpio_cfg->pin) { | ||
126 | case 0: | ||
127 | case 1: | ||
128 | case 2: | ||
129 | case 3: | ||
130 | ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_0, &tmp); | ||
131 | if (mxl_fail(ret)) | ||
132 | goto fail; | ||
133 | tmp &= ~(1 << (gpio_cfg->pin + 4)); | ||
134 | tmp |= (gpio_cfg->dir << (gpio_cfg->pin + 4)); | ||
135 | ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_0, tmp); | ||
136 | if (mxl_fail(ret)) | ||
137 | goto fail; | ||
138 | break; | ||
139 | case 4: | ||
140 | case 5: | ||
141 | case 6: | ||
142 | case 7: | ||
143 | ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_1, &tmp); | ||
144 | if (mxl_fail(ret)) | ||
145 | goto fail; | ||
146 | tmp &= ~(1 << gpio_cfg->pin); | ||
147 | tmp |= (gpio_cfg->dir << gpio_cfg->pin); | ||
148 | ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_1, tmp); | ||
149 | if (mxl_fail(ret)) | ||
150 | goto fail; | ||
151 | break; | ||
152 | case 8: | ||
153 | case 9: | ||
154 | case 10: | ||
155 | ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_2, &tmp); | ||
156 | if (mxl_fail(ret)) | ||
157 | goto fail; | ||
158 | tmp &= ~(1 << (gpio_cfg->pin - 3)); | ||
159 | tmp |= (gpio_cfg->dir << (gpio_cfg->pin - 3)); | ||
160 | ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_2, tmp); | ||
161 | if (mxl_fail(ret)) | ||
162 | goto fail; | ||
163 | break; | ||
164 | default: | ||
165 | return -EINVAL; /* invalid pin */ | ||
166 | } | ||
167 | |||
168 | ret = (MXL_GPIO_DIR_OUTPUT == gpio_cfg->dir) ? | ||
169 | mxl111sf_set_gpo_state(state, | ||
170 | gpio_cfg->pin, gpio_cfg->val) : | ||
171 | mxl111sf_get_gpi_state(state, | ||
172 | gpio_cfg->pin, &gpio_cfg->val); | ||
173 | mxl_fail(ret); | ||
174 | fail: | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | static int mxl111sf_hw_do_set_gpio(struct mxl111sf_state *state, | ||
179 | int gpio, int direction, int val) | ||
180 | { | ||
181 | struct mxl_gpio_cfg gpio_config = { | ||
182 | .pin = gpio, | ||
183 | .dir = direction, | ||
184 | .val = val, | ||
185 | }; | ||
186 | |||
187 | mxl_debug("(%d, %d, %d)", gpio, direction, val); | ||
188 | |||
189 | return mxl111sf_config_gpio_pins(state, &gpio_config); | ||
190 | } | ||
191 | |||
192 | /* ------------------------------------------------------------------------- */ | ||
193 | |||
194 | #define PIN_MUX_MPEG_MODE_MASK 0x40 /* 0x17 <6> */ | ||
195 | #define PIN_MUX_MPEG_PAR_EN_MASK 0x01 /* 0x18 <0> */ | ||
196 | #define PIN_MUX_MPEG_SER_EN_MASK 0x02 /* 0x18 <1> */ | ||
197 | #define PIN_MUX_MPG_IN_MUX_MASK 0x80 /* 0x3D <7> */ | ||
198 | #define PIN_MUX_BT656_ENABLE_MASK 0x04 /* 0x12 <2> */ | ||
199 | #define PIN_MUX_I2S_ENABLE_MASK 0x40 /* 0x15 <6> */ | ||
200 | #define PIN_MUX_SPI_MODE_MASK 0x10 /* 0x3D <4> */ | ||
201 | #define PIN_MUX_MCLK_EN_CTRL_MASK 0x10 /* 0x82 <4> */ | ||
202 | #define PIN_MUX_MPSYN_EN_CTRL_MASK 0x20 /* 0x82 <5> */ | ||
203 | #define PIN_MUX_MDVAL_EN_CTRL_MASK 0x40 /* 0x82 <6> */ | ||
204 | #define PIN_MUX_MPERR_EN_CTRL_MASK 0x80 /* 0x82 <7> */ | ||
205 | #define PIN_MUX_MDAT_EN_0_MASK 0x10 /* 0x84 <4> */ | ||
206 | #define PIN_MUX_MDAT_EN_1_MASK 0x20 /* 0x84 <5> */ | ||
207 | #define PIN_MUX_MDAT_EN_2_MASK 0x40 /* 0x84 <6> */ | ||
208 | #define PIN_MUX_MDAT_EN_3_MASK 0x80 /* 0x84 <7> */ | ||
209 | #define PIN_MUX_MDAT_EN_4_MASK 0x10 /* 0x89 <4> */ | ||
210 | #define PIN_MUX_MDAT_EN_5_MASK 0x20 /* 0x89 <5> */ | ||
211 | #define PIN_MUX_MDAT_EN_6_MASK 0x40 /* 0x89 <6> */ | ||
212 | #define PIN_MUX_MDAT_EN_7_MASK 0x80 /* 0x89 <7> */ | ||
213 | |||
214 | int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state, | ||
215 | enum mxl111sf_mux_config pin_mux_config) | ||
216 | { | ||
217 | u8 r12, r15, r17, r18, r3D, r82, r84, r89; | ||
218 | int ret; | ||
219 | |||
220 | mxl_debug("(%d)", pin_mux_config); | ||
221 | |||
222 | ret = mxl111sf_read_reg(state, 0x17, &r17); | ||
223 | if (mxl_fail(ret)) | ||
224 | goto fail; | ||
225 | ret = mxl111sf_read_reg(state, 0x18, &r18); | ||
226 | if (mxl_fail(ret)) | ||
227 | goto fail; | ||
228 | ret = mxl111sf_read_reg(state, 0x12, &r12); | ||
229 | if (mxl_fail(ret)) | ||
230 | goto fail; | ||
231 | ret = mxl111sf_read_reg(state, 0x15, &r15); | ||
232 | if (mxl_fail(ret)) | ||
233 | goto fail; | ||
234 | ret = mxl111sf_read_reg(state, 0x82, &r82); | ||
235 | if (mxl_fail(ret)) | ||
236 | goto fail; | ||
237 | ret = mxl111sf_read_reg(state, 0x84, &r84); | ||
238 | if (mxl_fail(ret)) | ||
239 | goto fail; | ||
240 | ret = mxl111sf_read_reg(state, 0x89, &r89); | ||
241 | if (mxl_fail(ret)) | ||
242 | goto fail; | ||
243 | ret = mxl111sf_read_reg(state, 0x3D, &r3D); | ||
244 | if (mxl_fail(ret)) | ||
245 | goto fail; | ||
246 | |||
247 | switch (pin_mux_config) { | ||
248 | case PIN_MUX_TS_OUT_PARALLEL: | ||
249 | /* mpeg_mode = 1 */ | ||
250 | r17 |= PIN_MUX_MPEG_MODE_MASK; | ||
251 | /* mpeg_par_en = 1 */ | ||
252 | r18 |= PIN_MUX_MPEG_PAR_EN_MASK; | ||
253 | /* mpeg_ser_en = 0 */ | ||
254 | r18 &= ~PIN_MUX_MPEG_SER_EN_MASK; | ||
255 | /* mpg_in_mux = 0 */ | ||
256 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | ||
257 | /* bt656_enable = 0 */ | ||
258 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | ||
259 | /* i2s_enable = 0 */ | ||
260 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | ||
261 | /* spi_mode = 0 */ | ||
262 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | ||
263 | /* mclk_en_ctrl = 1 */ | ||
264 | r82 |= PIN_MUX_MCLK_EN_CTRL_MASK; | ||
265 | /* mperr_en_ctrl = 1 */ | ||
266 | r82 |= PIN_MUX_MPERR_EN_CTRL_MASK; | ||
267 | /* mdval_en_ctrl = 1 */ | ||
268 | r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK; | ||
269 | /* mpsyn_en_ctrl = 1 */ | ||
270 | r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK; | ||
271 | /* mdat_en_ctrl[3:0] = 0xF */ | ||
272 | r84 |= 0xF0; | ||
273 | /* mdat_en_ctrl[7:4] = 0xF */ | ||
274 | r89 |= 0xF0; | ||
275 | break; | ||
276 | case PIN_MUX_TS_OUT_SERIAL: | ||
277 | /* mpeg_mode = 1 */ | ||
278 | r17 |= PIN_MUX_MPEG_MODE_MASK; | ||
279 | /* mpeg_par_en = 0 */ | ||
280 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | ||
281 | /* mpeg_ser_en = 1 */ | ||
282 | r18 |= PIN_MUX_MPEG_SER_EN_MASK; | ||
283 | /* mpg_in_mux = 0 */ | ||
284 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | ||
285 | /* bt656_enable = 0 */ | ||
286 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | ||
287 | /* i2s_enable = 0 */ | ||
288 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | ||
289 | /* spi_mode = 0 */ | ||
290 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | ||
291 | /* mclk_en_ctrl = 1 */ | ||
292 | r82 |= PIN_MUX_MCLK_EN_CTRL_MASK; | ||
293 | /* mperr_en_ctrl = 1 */ | ||
294 | r82 |= PIN_MUX_MPERR_EN_CTRL_MASK; | ||
295 | /* mdval_en_ctrl = 1 */ | ||
296 | r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK; | ||
297 | /* mpsyn_en_ctrl = 1 */ | ||
298 | r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK; | ||
299 | /* mdat_en_ctrl[3:0] = 0xF */ | ||
300 | r84 |= 0xF0; | ||
301 | /* mdat_en_ctrl[7:4] = 0xF */ | ||
302 | r89 |= 0xF0; | ||
303 | break; | ||
304 | case PIN_MUX_GPIO_MODE: | ||
305 | /* mpeg_mode = 0 */ | ||
306 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | ||
307 | /* mpeg_par_en = 0 */ | ||
308 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | ||
309 | /* mpeg_ser_en = 0 */ | ||
310 | r18 &= ~PIN_MUX_MPEG_SER_EN_MASK; | ||
311 | /* mpg_in_mux = 0 */ | ||
312 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | ||
313 | /* bt656_enable = 0 */ | ||
314 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | ||
315 | /* i2s_enable = 0 */ | ||
316 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | ||
317 | /* spi_mode = 0 */ | ||
318 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | ||
319 | /* mclk_en_ctrl = 0 */ | ||
320 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | ||
321 | /* mperr_en_ctrl = 0 */ | ||
322 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | ||
323 | /* mdval_en_ctrl = 0 */ | ||
324 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | ||
325 | /* mpsyn_en_ctrl = 0 */ | ||
326 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | ||
327 | /* mdat_en_ctrl[3:0] = 0x0 */ | ||
328 | r84 &= 0x0F; | ||
329 | /* mdat_en_ctrl[7:4] = 0x0 */ | ||
330 | r89 &= 0x0F; | ||
331 | break; | ||
332 | case PIN_MUX_TS_SERIAL_IN_MODE_0: | ||
333 | /* mpeg_mode = 0 */ | ||
334 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | ||
335 | /* mpeg_par_en = 0 */ | ||
336 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | ||
337 | /* mpeg_ser_en = 1 */ | ||
338 | r18 |= PIN_MUX_MPEG_SER_EN_MASK; | ||
339 | /* mpg_in_mux = 0 */ | ||
340 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | ||
341 | /* bt656_enable = 0 */ | ||
342 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | ||
343 | /* i2s_enable = 0 */ | ||
344 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | ||
345 | /* spi_mode = 0 */ | ||
346 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | ||
347 | /* mclk_en_ctrl = 0 */ | ||
348 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | ||
349 | /* mperr_en_ctrl = 0 */ | ||
350 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | ||
351 | /* mdval_en_ctrl = 0 */ | ||
352 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | ||
353 | /* mpsyn_en_ctrl = 0 */ | ||
354 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | ||
355 | /* mdat_en_ctrl[3:0] = 0x0 */ | ||
356 | r84 &= 0x0F; | ||
357 | /* mdat_en_ctrl[7:4] = 0x0 */ | ||
358 | r89 &= 0x0F; | ||
359 | break; | ||
360 | case PIN_MUX_TS_SERIAL_IN_MODE_1: | ||
361 | /* mpeg_mode = 0 */ | ||
362 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | ||
363 | /* mpeg_par_en = 0 */ | ||
364 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | ||
365 | /* mpeg_ser_en = 1 */ | ||
366 | r18 |= PIN_MUX_MPEG_SER_EN_MASK; | ||
367 | /* mpg_in_mux = 1 */ | ||
368 | r3D |= PIN_MUX_MPG_IN_MUX_MASK; | ||
369 | /* bt656_enable = 0 */ | ||
370 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | ||
371 | /* i2s_enable = 0 */ | ||
372 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | ||
373 | /* spi_mode = 0 */ | ||
374 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | ||
375 | /* mclk_en_ctrl = 0 */ | ||
376 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | ||
377 | /* mperr_en_ctrl = 0 */ | ||
378 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | ||
379 | /* mdval_en_ctrl = 0 */ | ||
380 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | ||
381 | /* mpsyn_en_ctrl = 0 */ | ||
382 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | ||
383 | /* mdat_en_ctrl[3:0] = 0x0 */ | ||
384 | r84 &= 0x0F; | ||
385 | /* mdat_en_ctrl[7:4] = 0x0 */ | ||
386 | r89 &= 0x0F; | ||
387 | break; | ||
388 | case PIN_MUX_TS_SPI_IN_MODE_1: | ||
389 | /* mpeg_mode = 0 */ | ||
390 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | ||
391 | /* mpeg_par_en = 0 */ | ||
392 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | ||
393 | /* mpeg_ser_en = 1 */ | ||
394 | r18 |= PIN_MUX_MPEG_SER_EN_MASK; | ||
395 | /* mpg_in_mux = 1 */ | ||
396 | r3D |= PIN_MUX_MPG_IN_MUX_MASK; | ||
397 | /* bt656_enable = 0 */ | ||
398 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | ||
399 | /* i2s_enable = 1 */ | ||
400 | r15 |= PIN_MUX_I2S_ENABLE_MASK; | ||
401 | /* spi_mode = 1 */ | ||
402 | r3D |= PIN_MUX_SPI_MODE_MASK; | ||
403 | /* mclk_en_ctrl = 0 */ | ||
404 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | ||
405 | /* mperr_en_ctrl = 0 */ | ||
406 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | ||
407 | /* mdval_en_ctrl = 0 */ | ||
408 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | ||
409 | /* mpsyn_en_ctrl = 0 */ | ||
410 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | ||
411 | /* mdat_en_ctrl[3:0] = 0x0 */ | ||
412 | r84 &= 0x0F; | ||
413 | /* mdat_en_ctrl[7:4] = 0x0 */ | ||
414 | r89 &= 0x0F; | ||
415 | break; | ||
416 | case PIN_MUX_TS_SPI_IN_MODE_0: | ||
417 | /* mpeg_mode = 0 */ | ||
418 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | ||
419 | /* mpeg_par_en = 0 */ | ||
420 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | ||
421 | /* mpeg_ser_en = 1 */ | ||
422 | r18 |= PIN_MUX_MPEG_SER_EN_MASK; | ||
423 | /* mpg_in_mux = 0 */ | ||
424 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | ||
425 | /* bt656_enable = 0 */ | ||
426 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | ||
427 | /* i2s_enable = 1 */ | ||
428 | r15 |= PIN_MUX_I2S_ENABLE_MASK; | ||
429 | /* spi_mode = 1 */ | ||
430 | r3D |= PIN_MUX_SPI_MODE_MASK; | ||
431 | /* mclk_en_ctrl = 0 */ | ||
432 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | ||
433 | /* mperr_en_ctrl = 0 */ | ||
434 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | ||
435 | /* mdval_en_ctrl = 0 */ | ||
436 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | ||
437 | /* mpsyn_en_ctrl = 0 */ | ||
438 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | ||
439 | /* mdat_en_ctrl[3:0] = 0x0 */ | ||
440 | r84 &= 0x0F; | ||
441 | /* mdat_en_ctrl[7:4] = 0x0 */ | ||
442 | r89 &= 0x0F; | ||
443 | break; | ||
444 | case PIN_MUX_TS_PARALLEL_IN: | ||
445 | /* mpeg_mode = 0 */ | ||
446 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | ||
447 | /* mpeg_par_en = 1 */ | ||
448 | r18 |= PIN_MUX_MPEG_PAR_EN_MASK; | ||
449 | /* mpeg_ser_en = 0 */ | ||
450 | r18 &= ~PIN_MUX_MPEG_SER_EN_MASK; | ||
451 | /* mpg_in_mux = 0 */ | ||
452 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | ||
453 | /* bt656_enable = 0 */ | ||
454 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | ||
455 | /* i2s_enable = 0 */ | ||
456 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | ||
457 | /* spi_mode = 0 */ | ||
458 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | ||
459 | /* mclk_en_ctrl = 0 */ | ||
460 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | ||
461 | /* mperr_en_ctrl = 0 */ | ||
462 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | ||
463 | /* mdval_en_ctrl = 0 */ | ||
464 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | ||
465 | /* mpsyn_en_ctrl = 0 */ | ||
466 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | ||
467 | /* mdat_en_ctrl[3:0] = 0x0 */ | ||
468 | r84 &= 0x0F; | ||
469 | /* mdat_en_ctrl[7:4] = 0x0 */ | ||
470 | r89 &= 0x0F; | ||
471 | break; | ||
472 | case PIN_MUX_BT656_I2S_MODE: | ||
473 | /* mpeg_mode = 0 */ | ||
474 | r17 &= ~PIN_MUX_MPEG_MODE_MASK; | ||
475 | /* mpeg_par_en = 0 */ | ||
476 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | ||
477 | /* mpeg_ser_en = 0 */ | ||
478 | r18 &= ~PIN_MUX_MPEG_SER_EN_MASK; | ||
479 | /* mpg_in_mux = 0 */ | ||
480 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | ||
481 | /* bt656_enable = 1 */ | ||
482 | r12 |= PIN_MUX_BT656_ENABLE_MASK; | ||
483 | /* i2s_enable = 1 */ | ||
484 | r15 |= PIN_MUX_I2S_ENABLE_MASK; | ||
485 | /* spi_mode = 0 */ | ||
486 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | ||
487 | /* mclk_en_ctrl = 0 */ | ||
488 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | ||
489 | /* mperr_en_ctrl = 0 */ | ||
490 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | ||
491 | /* mdval_en_ctrl = 0 */ | ||
492 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | ||
493 | /* mpsyn_en_ctrl = 0 */ | ||
494 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | ||
495 | /* mdat_en_ctrl[3:0] = 0x0 */ | ||
496 | r84 &= 0x0F; | ||
497 | /* mdat_en_ctrl[7:4] = 0x0 */ | ||
498 | r89 &= 0x0F; | ||
499 | break; | ||
500 | case PIN_MUX_DEFAULT: | ||
501 | default: | ||
502 | /* mpeg_mode = 1 */ | ||
503 | r17 |= PIN_MUX_MPEG_MODE_MASK; | ||
504 | /* mpeg_par_en = 0 */ | ||
505 | r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK; | ||
506 | /* mpeg_ser_en = 0 */ | ||
507 | r18 &= ~PIN_MUX_MPEG_SER_EN_MASK; | ||
508 | /* mpg_in_mux = 0 */ | ||
509 | r3D &= ~PIN_MUX_MPG_IN_MUX_MASK; | ||
510 | /* bt656_enable = 0 */ | ||
511 | r12 &= ~PIN_MUX_BT656_ENABLE_MASK; | ||
512 | /* i2s_enable = 0 */ | ||
513 | r15 &= ~PIN_MUX_I2S_ENABLE_MASK; | ||
514 | /* spi_mode = 0 */ | ||
515 | r3D &= ~PIN_MUX_SPI_MODE_MASK; | ||
516 | /* mclk_en_ctrl = 0 */ | ||
517 | r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK; | ||
518 | /* mperr_en_ctrl = 0 */ | ||
519 | r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK; | ||
520 | /* mdval_en_ctrl = 0 */ | ||
521 | r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK; | ||
522 | /* mpsyn_en_ctrl = 0 */ | ||
523 | r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK; | ||
524 | /* mdat_en_ctrl[3:0] = 0x0 */ | ||
525 | r84 &= 0x0F; | ||
526 | /* mdat_en_ctrl[7:4] = 0x0 */ | ||
527 | r89 &= 0x0F; | ||
528 | break; | ||
529 | } | ||
530 | |||
531 | ret = mxl111sf_write_reg(state, 0x17, r17); | ||
532 | if (mxl_fail(ret)) | ||
533 | goto fail; | ||
534 | ret = mxl111sf_write_reg(state, 0x18, r18); | ||
535 | if (mxl_fail(ret)) | ||
536 | goto fail; | ||
537 | ret = mxl111sf_write_reg(state, 0x12, r12); | ||
538 | if (mxl_fail(ret)) | ||
539 | goto fail; | ||
540 | ret = mxl111sf_write_reg(state, 0x15, r15); | ||
541 | if (mxl_fail(ret)) | ||
542 | goto fail; | ||
543 | ret = mxl111sf_write_reg(state, 0x82, r82); | ||
544 | if (mxl_fail(ret)) | ||
545 | goto fail; | ||
546 | ret = mxl111sf_write_reg(state, 0x84, r84); | ||
547 | if (mxl_fail(ret)) | ||
548 | goto fail; | ||
549 | ret = mxl111sf_write_reg(state, 0x89, r89); | ||
550 | if (mxl_fail(ret)) | ||
551 | goto fail; | ||
552 | ret = mxl111sf_write_reg(state, 0x3D, r3D); | ||
553 | if (mxl_fail(ret)) | ||
554 | goto fail; | ||
555 | fail: | ||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | /* ------------------------------------------------------------------------- */ | ||
560 | |||
561 | static int mxl111sf_hw_set_gpio(struct mxl111sf_state *state, int gpio, int val) | ||
562 | { | ||
563 | return mxl111sf_hw_do_set_gpio(state, gpio, MXL_GPIO_DIR_OUTPUT, val); | ||
564 | } | ||
565 | |||
566 | static int mxl111sf_hw_gpio_initialize(struct mxl111sf_state *state) | ||
567 | { | ||
568 | u8 gpioval = 0x07; /* write protect enabled, signal LEDs off */ | ||
569 | int i, ret; | ||
570 | |||
571 | mxl_debug("()"); | ||
572 | |||
573 | for (i = 3; i < 8; i++) { | ||
574 | ret = mxl111sf_hw_set_gpio(state, i, (gpioval >> i) & 0x01); | ||
575 | if (mxl_fail(ret)) | ||
576 | break; | ||
577 | } | ||
578 | |||
579 | return ret; | ||
580 | } | ||
581 | |||
582 | #define PCA9534_I2C_ADDR (0x40 >> 1) | ||
583 | static int pca9534_set_gpio(struct mxl111sf_state *state, int gpio, int val) | ||
584 | { | ||
585 | u8 w[2] = { 1, 0 }; | ||
586 | u8 r = 0; | ||
587 | struct i2c_msg msg[] = { | ||
588 | { .addr = PCA9534_I2C_ADDR, | ||
589 | .flags = 0, .buf = w, .len = 1 }, | ||
590 | { .addr = PCA9534_I2C_ADDR, | ||
591 | .flags = I2C_M_RD, .buf = &r, .len = 1 }, | ||
592 | }; | ||
593 | |||
594 | mxl_debug("(%d, %d)", gpio, val); | ||
595 | |||
596 | /* read current GPIO levels from flip-flop */ | ||
597 | i2c_transfer(&state->d->i2c_adap, msg, 2); | ||
598 | |||
599 | /* prepare write buffer with current GPIO levels */ | ||
600 | msg[0].len = 2; | ||
601 | #if 0 | ||
602 | w[0] = 1; | ||
603 | #endif | ||
604 | w[1] = r; | ||
605 | |||
606 | /* clear the desired GPIO */ | ||
607 | w[1] &= ~(1 << gpio); | ||
608 | |||
609 | /* set the desired GPIO value */ | ||
610 | w[1] |= ((val ? 1 : 0) << gpio); | ||
611 | |||
612 | /* write new GPIO levels to flip-flop */ | ||
613 | i2c_transfer(&state->d->i2c_adap, &msg[0], 1); | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | static int pca9534_init_port_expander(struct mxl111sf_state *state) | ||
619 | { | ||
620 | u8 w[2] = { 1, 0x07 }; /* write protect enabled, signal LEDs off */ | ||
621 | |||
622 | struct i2c_msg msg = { | ||
623 | .addr = PCA9534_I2C_ADDR, | ||
624 | .flags = 0, .buf = w, .len = 2 | ||
625 | }; | ||
626 | |||
627 | mxl_debug("()"); | ||
628 | |||
629 | i2c_transfer(&state->d->i2c_adap, &msg, 1); | ||
630 | |||
631 | /* configure all pins as outputs */ | ||
632 | w[0] = 3; | ||
633 | w[1] = 0; | ||
634 | |||
635 | i2c_transfer(&state->d->i2c_adap, &msg, 1); | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val) | ||
641 | { | ||
642 | mxl_debug("(%d, %d)", gpio, val); | ||
643 | |||
644 | switch (state->gpio_port_expander) { | ||
645 | default: | ||
646 | mxl_printk(KERN_ERR, | ||
647 | "gpio_port_expander undefined, assuming PCA9534"); | ||
648 | /* fall-thru */ | ||
649 | case mxl111sf_PCA9534: | ||
650 | return pca9534_set_gpio(state, gpio, val); | ||
651 | case mxl111sf_gpio_hw: | ||
652 | return mxl111sf_hw_set_gpio(state, gpio, val); | ||
653 | } | ||
654 | } | ||
655 | |||
656 | static int mxl111sf_probe_port_expander(struct mxl111sf_state *state) | ||
657 | { | ||
658 | int ret; | ||
659 | u8 w = 1; | ||
660 | u8 r = 0; | ||
661 | struct i2c_msg msg[] = { | ||
662 | { .flags = 0, .buf = &w, .len = 1 }, | ||
663 | { .flags = I2C_M_RD, .buf = &r, .len = 1 }, | ||
664 | }; | ||
665 | |||
666 | mxl_debug("()"); | ||
667 | |||
668 | msg[0].addr = 0x70 >> 1; | ||
669 | msg[1].addr = 0x70 >> 1; | ||
670 | |||
671 | /* read current GPIO levels from flip-flop */ | ||
672 | ret = i2c_transfer(&state->d->i2c_adap, msg, 2); | ||
673 | if (ret == 2) { | ||
674 | state->port_expander_addr = msg[0].addr; | ||
675 | state->gpio_port_expander = mxl111sf_PCA9534; | ||
676 | mxl_debug("found port expander at 0x%02x", | ||
677 | state->port_expander_addr); | ||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | msg[0].addr = 0x40 >> 1; | ||
682 | msg[1].addr = 0x40 >> 1; | ||
683 | |||
684 | ret = i2c_transfer(&state->d->i2c_adap, msg, 2); | ||
685 | if (ret == 2) { | ||
686 | state->port_expander_addr = msg[0].addr; | ||
687 | state->gpio_port_expander = mxl111sf_PCA9534; | ||
688 | mxl_debug("found port expander at 0x%02x", | ||
689 | state->port_expander_addr); | ||
690 | return 0; | ||
691 | } | ||
692 | state->port_expander_addr = 0xff; | ||
693 | state->gpio_port_expander = mxl111sf_gpio_hw; | ||
694 | mxl_debug("using hardware gpio"); | ||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | int mxl111sf_init_port_expander(struct mxl111sf_state *state) | ||
699 | { | ||
700 | mxl_debug("()"); | ||
701 | |||
702 | if (0x00 == state->port_expander_addr) | ||
703 | mxl111sf_probe_port_expander(state); | ||
704 | |||
705 | switch (state->gpio_port_expander) { | ||
706 | default: | ||
707 | mxl_printk(KERN_ERR, | ||
708 | "gpio_port_expander undefined, assuming PCA9534"); | ||
709 | /* fall-thru */ | ||
710 | case mxl111sf_PCA9534: | ||
711 | return pca9534_init_port_expander(state); | ||
712 | case mxl111sf_gpio_hw: | ||
713 | return mxl111sf_hw_gpio_initialize(state); | ||
714 | } | ||
715 | } | ||
716 | |||
717 | /* ------------------------------------------------------------------------ */ | ||
718 | |||
719 | int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode) | ||
720 | { | ||
721 | /* GPO: | ||
722 | * 3 - ATSC/MH# | 1 = ATSC transport, 0 = MH transport | default 0 | ||
723 | * 4 - ATSC_RST## | 1 = ATSC enable, 0 = ATSC Reset | default 0 | ||
724 | * 5 - ATSC_EN | 1 = ATSC power enable, 0 = ATSC power off | default 0 | ||
725 | * 6 - MH_RESET# | 1 = MH enable, 0 = MH Reset | default 0 | ||
726 | * 7 - MH_EN | 1 = MH power enable, 0 = MH power off | default 0 | ||
727 | */ | ||
728 | mxl_debug("(%d)", mode); | ||
729 | |||
730 | switch (mode) { | ||
731 | case MXL111SF_GPIO_MOD_MH: | ||
732 | mxl111sf_set_gpio(state, 4, 0); | ||
733 | mxl111sf_set_gpio(state, 5, 0); | ||
734 | msleep(50); | ||
735 | mxl111sf_set_gpio(state, 7, 1); | ||
736 | msleep(50); | ||
737 | mxl111sf_set_gpio(state, 6, 1); | ||
738 | msleep(50); | ||
739 | |||
740 | mxl111sf_set_gpio(state, 3, 0); | ||
741 | break; | ||
742 | case MXL111SF_GPIO_MOD_ATSC: | ||
743 | mxl111sf_set_gpio(state, 6, 0); | ||
744 | mxl111sf_set_gpio(state, 7, 0); | ||
745 | msleep(50); | ||
746 | mxl111sf_set_gpio(state, 5, 1); | ||
747 | msleep(50); | ||
748 | mxl111sf_set_gpio(state, 4, 1); | ||
749 | msleep(50); | ||
750 | mxl111sf_set_gpio(state, 3, 1); | ||
751 | break; | ||
752 | default: /* DVBT / STANDBY */ | ||
753 | mxl111sf_init_port_expander(state); | ||
754 | break; | ||
755 | } | ||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * Local variables: | ||
761 | * c-basic-offset: 8 | ||
762 | * End: | ||
763 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h new file mode 100644 index 000000000000..0220f54299a5 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * mxl111sf-gpio.h - driver for the MaxLinear MXL111SF | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #ifndef _DVB_USB_MXL111SF_GPIO_H_ | ||
22 | #define _DVB_USB_MXL111SF_GPIO_H_ | ||
23 | |||
24 | #include "mxl111sf.h" | ||
25 | |||
26 | int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val); | ||
27 | int mxl111sf_init_port_expander(struct mxl111sf_state *state); | ||
28 | |||
29 | #define MXL111SF_GPIO_MOD_DVBT 0 | ||
30 | #define MXL111SF_GPIO_MOD_MH 1 | ||
31 | #define MXL111SF_GPIO_MOD_ATSC 2 | ||
32 | int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode); | ||
33 | |||
34 | enum mxl111sf_mux_config { | ||
35 | PIN_MUX_DEFAULT = 0, | ||
36 | PIN_MUX_TS_OUT_PARALLEL, | ||
37 | PIN_MUX_TS_OUT_SERIAL, | ||
38 | PIN_MUX_GPIO_MODE, | ||
39 | PIN_MUX_TS_SERIAL_IN_MODE_0, | ||
40 | PIN_MUX_TS_SERIAL_IN_MODE_1, | ||
41 | PIN_MUX_TS_SPI_IN_MODE_0, | ||
42 | PIN_MUX_TS_SPI_IN_MODE_1, | ||
43 | PIN_MUX_TS_PARALLEL_IN, | ||
44 | PIN_MUX_BT656_I2S_MODE, | ||
45 | }; | ||
46 | |||
47 | int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state, | ||
48 | enum mxl111sf_mux_config pin_mux_config); | ||
49 | |||
50 | #endif /* _DVB_USB_MXL111SF_GPIO_H_ */ | ||
51 | |||
52 | /* | ||
53 | * Local variables: | ||
54 | * c-basic-offset: 8 | ||
55 | * End: | ||
56 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c new file mode 100644 index 000000000000..34434557ef65 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c | |||
@@ -0,0 +1,850 @@ | |||
1 | /* | ||
2 | * mxl111sf-i2c.c - driver for the MaxLinear MXL111SF | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #include "mxl111sf-i2c.h" | ||
22 | #include "mxl111sf.h" | ||
23 | |||
24 | /* SW-I2C ----------------------------------------------------------------- */ | ||
25 | |||
26 | #define SW_I2C_ADDR 0x1a | ||
27 | #define SW_I2C_EN 0x02 | ||
28 | #define SW_SCL_OUT 0x04 | ||
29 | #define SW_SDA_OUT 0x08 | ||
30 | #define SW_SDA_IN 0x04 | ||
31 | |||
32 | #define SW_I2C_BUSY_ADDR 0x2f | ||
33 | #define SW_I2C_BUSY 0x02 | ||
34 | |||
35 | static int mxl111sf_i2c_bitbang_sendbyte(struct mxl111sf_state *state, | ||
36 | u8 byte) | ||
37 | { | ||
38 | int i, ret; | ||
39 | u8 data = 0; | ||
40 | |||
41 | mxl_i2c("(0x%02x)", byte); | ||
42 | |||
43 | ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data); | ||
44 | if (mxl_fail(ret)) | ||
45 | goto fail; | ||
46 | |||
47 | for (i = 0; i < 8; i++) { | ||
48 | |||
49 | data = (byte & (0x80 >> i)) ? SW_SDA_OUT : 0; | ||
50 | |||
51 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
52 | 0x10 | SW_I2C_EN | data); | ||
53 | if (mxl_fail(ret)) | ||
54 | goto fail; | ||
55 | |||
56 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
57 | 0x10 | SW_I2C_EN | data | SW_SCL_OUT); | ||
58 | if (mxl_fail(ret)) | ||
59 | goto fail; | ||
60 | |||
61 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
62 | 0x10 | SW_I2C_EN | data); | ||
63 | if (mxl_fail(ret)) | ||
64 | goto fail; | ||
65 | } | ||
66 | |||
67 | /* last bit was 0 so we need to release SDA */ | ||
68 | if (!(byte & 1)) { | ||
69 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
70 | 0x10 | SW_I2C_EN | SW_SDA_OUT); | ||
71 | if (mxl_fail(ret)) | ||
72 | goto fail; | ||
73 | } | ||
74 | |||
75 | /* CLK high for ACK readback */ | ||
76 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
77 | 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); | ||
78 | if (mxl_fail(ret)) | ||
79 | goto fail; | ||
80 | |||
81 | ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data); | ||
82 | if (mxl_fail(ret)) | ||
83 | goto fail; | ||
84 | |||
85 | /* drop the CLK after getting ACK, SDA will go high right away */ | ||
86 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
87 | 0x10 | SW_I2C_EN | SW_SDA_OUT); | ||
88 | if (mxl_fail(ret)) | ||
89 | goto fail; | ||
90 | |||
91 | if (data & SW_SDA_IN) | ||
92 | ret = -EIO; | ||
93 | fail: | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static int mxl111sf_i2c_bitbang_recvbyte(struct mxl111sf_state *state, | ||
98 | u8 *pbyte) | ||
99 | { | ||
100 | int i, ret; | ||
101 | u8 byte = 0; | ||
102 | u8 data = 0; | ||
103 | |||
104 | mxl_i2c("()"); | ||
105 | |||
106 | *pbyte = 0; | ||
107 | |||
108 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
109 | 0x10 | SW_I2C_EN | SW_SDA_OUT); | ||
110 | if (mxl_fail(ret)) | ||
111 | goto fail; | ||
112 | |||
113 | for (i = 0; i < 8; i++) { | ||
114 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
115 | 0x10 | SW_I2C_EN | | ||
116 | SW_SCL_OUT | SW_SDA_OUT); | ||
117 | if (mxl_fail(ret)) | ||
118 | goto fail; | ||
119 | |||
120 | ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data); | ||
121 | if (mxl_fail(ret)) | ||
122 | goto fail; | ||
123 | |||
124 | if (data & SW_SDA_IN) | ||
125 | byte |= (0x80 >> i); | ||
126 | |||
127 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
128 | 0x10 | SW_I2C_EN | SW_SDA_OUT); | ||
129 | if (mxl_fail(ret)) | ||
130 | goto fail; | ||
131 | } | ||
132 | *pbyte = byte; | ||
133 | fail: | ||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | static int mxl111sf_i2c_start(struct mxl111sf_state *state) | ||
138 | { | ||
139 | int ret; | ||
140 | |||
141 | mxl_i2c("()"); | ||
142 | |||
143 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
144 | 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); | ||
145 | if (mxl_fail(ret)) | ||
146 | goto fail; | ||
147 | |||
148 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
149 | 0x10 | SW_I2C_EN | SW_SCL_OUT); | ||
150 | if (mxl_fail(ret)) | ||
151 | goto fail; | ||
152 | |||
153 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
154 | 0x10 | SW_I2C_EN); /* start */ | ||
155 | mxl_fail(ret); | ||
156 | fail: | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static int mxl111sf_i2c_stop(struct mxl111sf_state *state) | ||
161 | { | ||
162 | int ret; | ||
163 | |||
164 | mxl_i2c("()"); | ||
165 | |||
166 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
167 | 0x10 | SW_I2C_EN); /* stop */ | ||
168 | if (mxl_fail(ret)) | ||
169 | goto fail; | ||
170 | |||
171 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
172 | 0x10 | SW_I2C_EN | SW_SCL_OUT); | ||
173 | if (mxl_fail(ret)) | ||
174 | goto fail; | ||
175 | |||
176 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
177 | 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); | ||
178 | if (mxl_fail(ret)) | ||
179 | goto fail; | ||
180 | |||
181 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
182 | 0x10 | SW_SCL_OUT | SW_SDA_OUT); | ||
183 | mxl_fail(ret); | ||
184 | fail: | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | static int mxl111sf_i2c_ack(struct mxl111sf_state *state) | ||
189 | { | ||
190 | int ret; | ||
191 | u8 b = 0; | ||
192 | |||
193 | mxl_i2c("()"); | ||
194 | |||
195 | ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &b); | ||
196 | if (mxl_fail(ret)) | ||
197 | goto fail; | ||
198 | |||
199 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
200 | 0x10 | SW_I2C_EN); | ||
201 | if (mxl_fail(ret)) | ||
202 | goto fail; | ||
203 | |||
204 | /* pull SDA low */ | ||
205 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
206 | 0x10 | SW_I2C_EN | SW_SCL_OUT); | ||
207 | if (mxl_fail(ret)) | ||
208 | goto fail; | ||
209 | |||
210 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
211 | 0x10 | SW_I2C_EN | SW_SDA_OUT); | ||
212 | mxl_fail(ret); | ||
213 | fail: | ||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | static int mxl111sf_i2c_nack(struct mxl111sf_state *state) | ||
218 | { | ||
219 | int ret; | ||
220 | |||
221 | mxl_i2c("()"); | ||
222 | |||
223 | /* SDA high to signal last byte read from slave */ | ||
224 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
225 | 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); | ||
226 | if (mxl_fail(ret)) | ||
227 | goto fail; | ||
228 | |||
229 | ret = mxl111sf_write_reg(state, SW_I2C_ADDR, | ||
230 | 0x10 | SW_I2C_EN | SW_SDA_OUT); | ||
231 | mxl_fail(ret); | ||
232 | fail: | ||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | /* ------------------------------------------------------------------------ */ | ||
237 | |||
238 | static int mxl111sf_i2c_sw_xfer_msg(struct mxl111sf_state *state, | ||
239 | struct i2c_msg *msg) | ||
240 | { | ||
241 | int i, ret; | ||
242 | |||
243 | mxl_i2c("()"); | ||
244 | |||
245 | if (msg->flags & I2C_M_RD) { | ||
246 | |||
247 | ret = mxl111sf_i2c_start(state); | ||
248 | if (mxl_fail(ret)) | ||
249 | goto fail; | ||
250 | |||
251 | ret = mxl111sf_i2c_bitbang_sendbyte(state, | ||
252 | (msg->addr << 1) | 0x01); | ||
253 | if (mxl_fail(ret)) { | ||
254 | mxl111sf_i2c_stop(state); | ||
255 | goto fail; | ||
256 | } | ||
257 | |||
258 | for (i = 0; i < msg->len; i++) { | ||
259 | ret = mxl111sf_i2c_bitbang_recvbyte(state, | ||
260 | &msg->buf[i]); | ||
261 | if (mxl_fail(ret)) { | ||
262 | mxl111sf_i2c_stop(state); | ||
263 | goto fail; | ||
264 | } | ||
265 | |||
266 | if (i < msg->len - 1) | ||
267 | mxl111sf_i2c_ack(state); | ||
268 | } | ||
269 | |||
270 | mxl111sf_i2c_nack(state); | ||
271 | |||
272 | ret = mxl111sf_i2c_stop(state); | ||
273 | if (mxl_fail(ret)) | ||
274 | goto fail; | ||
275 | |||
276 | } else { | ||
277 | |||
278 | ret = mxl111sf_i2c_start(state); | ||
279 | if (mxl_fail(ret)) | ||
280 | goto fail; | ||
281 | |||
282 | ret = mxl111sf_i2c_bitbang_sendbyte(state, | ||
283 | (msg->addr << 1) & 0xfe); | ||
284 | if (mxl_fail(ret)) { | ||
285 | mxl111sf_i2c_stop(state); | ||
286 | goto fail; | ||
287 | } | ||
288 | |||
289 | for (i = 0; i < msg->len; i++) { | ||
290 | ret = mxl111sf_i2c_bitbang_sendbyte(state, | ||
291 | msg->buf[i]); | ||
292 | if (mxl_fail(ret)) { | ||
293 | mxl111sf_i2c_stop(state); | ||
294 | goto fail; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | /* FIXME: we only want to do this on the last transaction */ | ||
299 | mxl111sf_i2c_stop(state); | ||
300 | } | ||
301 | fail: | ||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | /* HW-I2C ----------------------------------------------------------------- */ | ||
306 | |||
307 | #define USB_WRITE_I2C_CMD 0x99 | ||
308 | #define USB_READ_I2C_CMD 0xdd | ||
309 | #define USB_END_I2C_CMD 0xfe | ||
310 | |||
311 | #define USB_WRITE_I2C_CMD_LEN 26 | ||
312 | #define USB_READ_I2C_CMD_LEN 24 | ||
313 | |||
314 | #define I2C_MUX_REG 0x30 | ||
315 | #define I2C_CONTROL_REG 0x00 | ||
316 | #define I2C_SLAVE_ADDR_REG 0x08 | ||
317 | #define I2C_DATA_REG 0x0c | ||
318 | #define I2C_INT_STATUS_REG 0x10 | ||
319 | |||
320 | static int mxl111sf_i2c_send_data(struct mxl111sf_state *state, | ||
321 | u8 index, u8 *wdata) | ||
322 | { | ||
323 | int ret = mxl111sf_ctrl_msg(state->d, wdata[0], | ||
324 | &wdata[1], 25, NULL, 0); | ||
325 | mxl_fail(ret); | ||
326 | |||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | static int mxl111sf_i2c_get_data(struct mxl111sf_state *state, | ||
331 | u8 index, u8 *wdata, u8 *rdata) | ||
332 | { | ||
333 | int ret = mxl111sf_ctrl_msg(state->d, wdata[0], | ||
334 | &wdata[1], 25, rdata, 24); | ||
335 | mxl_fail(ret); | ||
336 | |||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | static u8 mxl111sf_i2c_check_status(struct mxl111sf_state *state) | ||
341 | { | ||
342 | u8 status = 0; | ||
343 | u8 buf[26]; | ||
344 | |||
345 | mxl_i2c_adv("()"); | ||
346 | |||
347 | buf[0] = USB_READ_I2C_CMD; | ||
348 | buf[1] = 0x00; | ||
349 | |||
350 | buf[2] = I2C_INT_STATUS_REG; | ||
351 | buf[3] = 0x00; | ||
352 | buf[4] = 0x00; | ||
353 | |||
354 | buf[5] = USB_END_I2C_CMD; | ||
355 | |||
356 | mxl111sf_i2c_get_data(state, 0, buf, buf); | ||
357 | |||
358 | if (buf[1] & 0x04) | ||
359 | status = 1; | ||
360 | |||
361 | return status; | ||
362 | } | ||
363 | |||
364 | static u8 mxl111sf_i2c_check_fifo(struct mxl111sf_state *state) | ||
365 | { | ||
366 | u8 status = 0; | ||
367 | u8 buf[26]; | ||
368 | |||
369 | mxl_i2c("()"); | ||
370 | |||
371 | buf[0] = USB_READ_I2C_CMD; | ||
372 | buf[1] = 0x00; | ||
373 | |||
374 | buf[2] = I2C_MUX_REG; | ||
375 | buf[3] = 0x00; | ||
376 | buf[4] = 0x00; | ||
377 | |||
378 | buf[5] = I2C_INT_STATUS_REG; | ||
379 | buf[6] = 0x00; | ||
380 | buf[7] = 0x00; | ||
381 | buf[8] = USB_END_I2C_CMD; | ||
382 | |||
383 | mxl111sf_i2c_get_data(state, 0, buf, buf); | ||
384 | |||
385 | if (0x08 == (buf[1] & 0x08)) | ||
386 | status = 1; | ||
387 | |||
388 | if ((buf[5] & 0x02) == 0x02) | ||
389 | mxl_i2c("(buf[5] & 0x02) == 0x02"); /* FIXME */ | ||
390 | |||
391 | return status; | ||
392 | } | ||
393 | |||
394 | static int mxl111sf_i2c_readagain(struct mxl111sf_state *state, | ||
395 | u8 count, u8 *rbuf) | ||
396 | { | ||
397 | u8 i2c_w_data[26]; | ||
398 | u8 i2c_r_data[24]; | ||
399 | u8 i = 0; | ||
400 | u8 fifo_status = 0; | ||
401 | int status = 0; | ||
402 | |||
403 | mxl_i2c("read %d bytes", count); | ||
404 | |||
405 | while ((fifo_status == 0) && (i++ < 5)) | ||
406 | fifo_status = mxl111sf_i2c_check_fifo(state); | ||
407 | |||
408 | i2c_w_data[0] = 0xDD; | ||
409 | i2c_w_data[1] = 0x00; | ||
410 | |||
411 | for (i = 2; i < 26; i++) | ||
412 | i2c_w_data[i] = 0xFE; | ||
413 | |||
414 | for (i = 0; i < count; i++) { | ||
415 | i2c_w_data[2+(i*3)] = 0x0C; | ||
416 | i2c_w_data[3+(i*3)] = 0x00; | ||
417 | i2c_w_data[4+(i*3)] = 0x00; | ||
418 | } | ||
419 | |||
420 | mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data); | ||
421 | |||
422 | /* Check for I2C NACK status */ | ||
423 | if (mxl111sf_i2c_check_status(state) == 1) { | ||
424 | mxl_i2c("error!"); | ||
425 | } else { | ||
426 | for (i = 0; i < count; i++) { | ||
427 | rbuf[i] = i2c_r_data[(i*3)+1]; | ||
428 | mxl_i2c("%02x\t %02x", | ||
429 | i2c_r_data[(i*3)+1], | ||
430 | i2c_r_data[(i*3)+2]); | ||
431 | } | ||
432 | |||
433 | status = 1; | ||
434 | } | ||
435 | |||
436 | return status; | ||
437 | } | ||
438 | |||
439 | #define HWI2C400 1 | ||
440 | static int mxl111sf_i2c_hw_xfer_msg(struct mxl111sf_state *state, | ||
441 | struct i2c_msg *msg) | ||
442 | { | ||
443 | int i, k, ret = 0; | ||
444 | u16 index = 0; | ||
445 | u8 buf[26]; | ||
446 | u8 i2c_r_data[24]; | ||
447 | u16 block_len; | ||
448 | u16 left_over_len; | ||
449 | u8 rd_status[8]; | ||
450 | u8 ret_status; | ||
451 | u8 readbuff[26]; | ||
452 | |||
453 | mxl_i2c("addr: 0x%02x, read buff len: %d, write buff len: %d", | ||
454 | msg->addr, (msg->flags & I2C_M_RD) ? msg->len : 0, | ||
455 | (!(msg->flags & I2C_M_RD)) ? msg->len : 0); | ||
456 | |||
457 | for (index = 0; index < 26; index++) | ||
458 | buf[index] = USB_END_I2C_CMD; | ||
459 | |||
460 | /* command to indicate data payload is destined for I2C interface */ | ||
461 | buf[0] = USB_WRITE_I2C_CMD; | ||
462 | buf[1] = 0x00; | ||
463 | |||
464 | /* enable I2C interface */ | ||
465 | buf[2] = I2C_MUX_REG; | ||
466 | buf[3] = 0x80; | ||
467 | buf[4] = 0x00; | ||
468 | |||
469 | /* enable I2C interface */ | ||
470 | buf[5] = I2C_MUX_REG; | ||
471 | buf[6] = 0x81; | ||
472 | buf[7] = 0x00; | ||
473 | |||
474 | /* set Timeout register on I2C interface */ | ||
475 | buf[8] = 0x14; | ||
476 | buf[9] = 0xff; | ||
477 | buf[10] = 0x00; | ||
478 | #if 0 | ||
479 | /* enable Interrupts on I2C interface */ | ||
480 | buf[8] = 0x24; | ||
481 | buf[9] = 0xF7; | ||
482 | buf[10] = 0x00; | ||
483 | #endif | ||
484 | buf[11] = 0x24; | ||
485 | buf[12] = 0xF7; | ||
486 | buf[13] = 0x00; | ||
487 | |||
488 | ret = mxl111sf_i2c_send_data(state, 0, buf); | ||
489 | |||
490 | /* write data on I2C bus */ | ||
491 | if (!(msg->flags & I2C_M_RD) && (msg->len > 0)) { | ||
492 | mxl_i2c("%d\t%02x", msg->len, msg->buf[0]); | ||
493 | |||
494 | /* control register on I2C interface to initialize I2C bus */ | ||
495 | buf[2] = I2C_CONTROL_REG; | ||
496 | buf[3] = 0x5E; | ||
497 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
498 | |||
499 | /* I2C Slave device Address */ | ||
500 | buf[5] = I2C_SLAVE_ADDR_REG; | ||
501 | buf[6] = (msg->addr); | ||
502 | buf[7] = 0x00; | ||
503 | buf[8] = USB_END_I2C_CMD; | ||
504 | ret = mxl111sf_i2c_send_data(state, 0, buf); | ||
505 | |||
506 | /* check for slave device status */ | ||
507 | if (mxl111sf_i2c_check_status(state) == 1) { | ||
508 | mxl_i2c("NACK writing slave address %02x", | ||
509 | msg->addr); | ||
510 | /* if NACK, stop I2C bus and exit */ | ||
511 | buf[2] = I2C_CONTROL_REG; | ||
512 | buf[3] = 0x4E; | ||
513 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
514 | ret = -EIO; | ||
515 | goto exit; | ||
516 | } | ||
517 | |||
518 | /* I2C interface can do I2C operations in block of 8 bytes of | ||
519 | I2C data. calculation to figure out number of blocks of i2c | ||
520 | data required to program */ | ||
521 | block_len = (msg->len / 8); | ||
522 | left_over_len = (msg->len % 8); | ||
523 | index = 0; | ||
524 | |||
525 | mxl_i2c("block_len %d, left_over_len %d", | ||
526 | block_len, left_over_len); | ||
527 | |||
528 | for (index = 0; index < block_len; index++) { | ||
529 | for (i = 0; i < 8; i++) { | ||
530 | /* write data on I2C interface */ | ||
531 | buf[2+(i*3)] = I2C_DATA_REG; | ||
532 | buf[3+(i*3)] = msg->buf[(index*8)+i]; | ||
533 | buf[4+(i*3)] = 0x00; | ||
534 | } | ||
535 | |||
536 | ret = mxl111sf_i2c_send_data(state, 0, buf); | ||
537 | |||
538 | /* check for I2C NACK status */ | ||
539 | if (mxl111sf_i2c_check_status(state) == 1) { | ||
540 | mxl_i2c("NACK writing slave address %02x", | ||
541 | msg->addr); | ||
542 | |||
543 | /* if NACK, stop I2C bus and exit */ | ||
544 | buf[2] = I2C_CONTROL_REG; | ||
545 | buf[3] = 0x4E; | ||
546 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
547 | ret = -EIO; | ||
548 | goto exit; | ||
549 | } | ||
550 | |||
551 | } | ||
552 | |||
553 | if (left_over_len) { | ||
554 | for (k = 0; k < 26; k++) | ||
555 | buf[k] = USB_END_I2C_CMD; | ||
556 | |||
557 | buf[0] = 0x99; | ||
558 | buf[1] = 0x00; | ||
559 | |||
560 | for (i = 0; i < left_over_len; i++) { | ||
561 | buf[2+(i*3)] = I2C_DATA_REG; | ||
562 | buf[3+(i*3)] = msg->buf[(index*8)+i]; | ||
563 | mxl_i2c("index = %d %d data %d", | ||
564 | index, i, msg->buf[(index*8)+i]); | ||
565 | buf[4+(i*3)] = 0x00; | ||
566 | } | ||
567 | ret = mxl111sf_i2c_send_data(state, 0, buf); | ||
568 | |||
569 | /* check for I2C NACK status */ | ||
570 | if (mxl111sf_i2c_check_status(state) == 1) { | ||
571 | mxl_i2c("NACK writing slave address %02x", | ||
572 | msg->addr); | ||
573 | |||
574 | /* if NACK, stop I2C bus and exit */ | ||
575 | buf[2] = I2C_CONTROL_REG; | ||
576 | buf[3] = 0x4E; | ||
577 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
578 | ret = -EIO; | ||
579 | goto exit; | ||
580 | } | ||
581 | |||
582 | } | ||
583 | |||
584 | /* issue I2C STOP after write */ | ||
585 | buf[2] = I2C_CONTROL_REG; | ||
586 | buf[3] = 0x4E; | ||
587 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
588 | |||
589 | } | ||
590 | |||
591 | /* read data from I2C bus */ | ||
592 | if ((msg->flags & I2C_M_RD) && (msg->len > 0)) { | ||
593 | mxl_i2c("read buf len %d", msg->len); | ||
594 | |||
595 | /* command to indicate data payload is | ||
596 | destined for I2C interface */ | ||
597 | buf[2] = I2C_CONTROL_REG; | ||
598 | buf[3] = 0xDF; | ||
599 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
600 | |||
601 | /* I2C xfer length */ | ||
602 | buf[5] = 0x14; | ||
603 | buf[6] = (msg->len & 0xFF); | ||
604 | buf[7] = 0; | ||
605 | |||
606 | /* I2C slave device Address */ | ||
607 | buf[8] = I2C_SLAVE_ADDR_REG; | ||
608 | buf[9] = msg->addr; | ||
609 | buf[10] = 0x00; | ||
610 | buf[11] = USB_END_I2C_CMD; | ||
611 | ret = mxl111sf_i2c_send_data(state, 0, buf); | ||
612 | |||
613 | /* check for I2C NACK status */ | ||
614 | if (mxl111sf_i2c_check_status(state) == 1) { | ||
615 | mxl_i2c("NACK reading slave address %02x", | ||
616 | msg->addr); | ||
617 | |||
618 | /* if NACK, stop I2C bus and exit */ | ||
619 | buf[2] = I2C_CONTROL_REG; | ||
620 | buf[3] = 0xC7; | ||
621 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
622 | ret = -EIO; | ||
623 | goto exit; | ||
624 | } | ||
625 | |||
626 | /* I2C interface can do I2C operations in block of 8 bytes of | ||
627 | I2C data. calculation to figure out number of blocks of | ||
628 | i2c data required to program */ | ||
629 | block_len = ((msg->len) / 8); | ||
630 | left_over_len = ((msg->len) % 8); | ||
631 | index = 0; | ||
632 | |||
633 | mxl_i2c("block_len %d, left_over_len %d", | ||
634 | block_len, left_over_len); | ||
635 | |||
636 | /* command to read data from I2C interface */ | ||
637 | buf[0] = USB_READ_I2C_CMD; | ||
638 | buf[1] = 0x00; | ||
639 | |||
640 | for (index = 0; index < block_len; index++) { | ||
641 | /* setup I2C read request packet on I2C interface */ | ||
642 | for (i = 0; i < 8; i++) { | ||
643 | buf[2+(i*3)] = I2C_DATA_REG; | ||
644 | buf[3+(i*3)] = 0x00; | ||
645 | buf[4+(i*3)] = 0x00; | ||
646 | } | ||
647 | |||
648 | ret = mxl111sf_i2c_get_data(state, 0, buf, i2c_r_data); | ||
649 | |||
650 | /* check for I2C NACK status */ | ||
651 | if (mxl111sf_i2c_check_status(state) == 1) { | ||
652 | mxl_i2c("NACK reading slave address %02x", | ||
653 | msg->addr); | ||
654 | |||
655 | /* if NACK, stop I2C bus and exit */ | ||
656 | buf[2] = I2C_CONTROL_REG; | ||
657 | buf[3] = 0xC7; | ||
658 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
659 | ret = -EIO; | ||
660 | goto exit; | ||
661 | } | ||
662 | |||
663 | /* copy data from i2c data payload to read buffer */ | ||
664 | for (i = 0; i < 8; i++) { | ||
665 | rd_status[i] = i2c_r_data[(i*3)+2]; | ||
666 | |||
667 | if (rd_status[i] == 0x04) { | ||
668 | if (i < 7) { | ||
669 | mxl_i2c("i2c fifo empty!" | ||
670 | " @ %d", i); | ||
671 | msg->buf[(index*8)+i] = | ||
672 | i2c_r_data[(i*3)+1]; | ||
673 | /* read again */ | ||
674 | ret_status = | ||
675 | mxl111sf_i2c_readagain( | ||
676 | state, 8-(i+1), | ||
677 | readbuff); | ||
678 | if (ret_status == 1) { | ||
679 | for (k = 0; | ||
680 | k < 8-(i+1); | ||
681 | k++) { | ||
682 | |||
683 | msg->buf[(index*8)+(k+i+1)] = | ||
684 | readbuff[k]; | ||
685 | mxl_i2c("read data: %02x\t %02x", | ||
686 | msg->buf[(index*8)+(k+i)], | ||
687 | (index*8)+(k+i)); | ||
688 | mxl_i2c("read data: %02x\t %02x", | ||
689 | msg->buf[(index*8)+(k+i+1)], | ||
690 | readbuff[k]); | ||
691 | |||
692 | } | ||
693 | goto stop_copy; | ||
694 | } else { | ||
695 | mxl_i2c("readagain " | ||
696 | "ERROR!"); | ||
697 | } | ||
698 | } else { | ||
699 | msg->buf[(index*8)+i] = | ||
700 | i2c_r_data[(i*3)+1]; | ||
701 | } | ||
702 | } else { | ||
703 | msg->buf[(index*8)+i] = | ||
704 | i2c_r_data[(i*3)+1]; | ||
705 | } | ||
706 | } | ||
707 | stop_copy: | ||
708 | ; | ||
709 | |||
710 | } | ||
711 | |||
712 | if (left_over_len) { | ||
713 | for (k = 0; k < 26; k++) | ||
714 | buf[k] = USB_END_I2C_CMD; | ||
715 | |||
716 | buf[0] = 0xDD; | ||
717 | buf[1] = 0x00; | ||
718 | |||
719 | for (i = 0; i < left_over_len; i++) { | ||
720 | buf[2+(i*3)] = I2C_DATA_REG; | ||
721 | buf[3+(i*3)] = 0x00; | ||
722 | buf[4+(i*3)] = 0x00; | ||
723 | } | ||
724 | ret = mxl111sf_i2c_get_data(state, 0, buf, | ||
725 | i2c_r_data); | ||
726 | |||
727 | /* check for I2C NACK status */ | ||
728 | if (mxl111sf_i2c_check_status(state) == 1) { | ||
729 | mxl_i2c("NACK reading slave address %02x", | ||
730 | msg->addr); | ||
731 | |||
732 | /* if NACK, stop I2C bus and exit */ | ||
733 | buf[2] = I2C_CONTROL_REG; | ||
734 | buf[3] = 0xC7; | ||
735 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
736 | ret = -EIO; | ||
737 | goto exit; | ||
738 | } | ||
739 | |||
740 | for (i = 0; i < left_over_len; i++) { | ||
741 | msg->buf[(block_len*8)+i] = | ||
742 | i2c_r_data[(i*3)+1]; | ||
743 | mxl_i2c("read data: %02x\t %02x", | ||
744 | i2c_r_data[(i*3)+1], | ||
745 | i2c_r_data[(i*3)+2]); | ||
746 | } | ||
747 | } | ||
748 | |||
749 | /* indicate I2C interface to issue NACK | ||
750 | after next I2C read op */ | ||
751 | buf[0] = USB_WRITE_I2C_CMD; | ||
752 | buf[1] = 0x00; | ||
753 | |||
754 | /* control register */ | ||
755 | buf[2] = I2C_CONTROL_REG; | ||
756 | buf[3] = 0x17; | ||
757 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
758 | |||
759 | buf[5] = USB_END_I2C_CMD; | ||
760 | ret = mxl111sf_i2c_send_data(state, 0, buf); | ||
761 | |||
762 | /* control register */ | ||
763 | buf[2] = I2C_CONTROL_REG; | ||
764 | buf[3] = 0xC7; | ||
765 | buf[4] = (HWI2C400) ? 0x03 : 0x0D; | ||
766 | |||
767 | } | ||
768 | exit: | ||
769 | /* STOP and disable I2C MUX */ | ||
770 | buf[0] = USB_WRITE_I2C_CMD; | ||
771 | buf[1] = 0x00; | ||
772 | |||
773 | /* de-initilize I2C BUS */ | ||
774 | buf[5] = USB_END_I2C_CMD; | ||
775 | mxl111sf_i2c_send_data(state, 0, buf); | ||
776 | |||
777 | /* Control Register */ | ||
778 | buf[2] = I2C_CONTROL_REG; | ||
779 | buf[3] = 0xDF; | ||
780 | buf[4] = 0x03; | ||
781 | |||
782 | /* disable I2C interface */ | ||
783 | buf[5] = I2C_MUX_REG; | ||
784 | buf[6] = 0x00; | ||
785 | buf[7] = 0x00; | ||
786 | |||
787 | /* de-initilize I2C BUS */ | ||
788 | buf[8] = USB_END_I2C_CMD; | ||
789 | mxl111sf_i2c_send_data(state, 0, buf); | ||
790 | |||
791 | /* disable I2C interface */ | ||
792 | buf[2] = I2C_MUX_REG; | ||
793 | buf[3] = 0x81; | ||
794 | buf[4] = 0x00; | ||
795 | |||
796 | /* disable I2C interface */ | ||
797 | buf[5] = I2C_MUX_REG; | ||
798 | buf[6] = 0x00; | ||
799 | buf[7] = 0x00; | ||
800 | |||
801 | /* disable I2C interface */ | ||
802 | buf[8] = I2C_MUX_REG; | ||
803 | buf[9] = 0x00; | ||
804 | buf[10] = 0x00; | ||
805 | |||
806 | buf[11] = USB_END_I2C_CMD; | ||
807 | mxl111sf_i2c_send_data(state, 0, buf); | ||
808 | |||
809 | return ret; | ||
810 | } | ||
811 | |||
812 | /* ------------------------------------------------------------------------ */ | ||
813 | |||
814 | int mxl111sf_i2c_xfer(struct i2c_adapter *adap, | ||
815 | struct i2c_msg msg[], int num) | ||
816 | { | ||
817 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
818 | struct mxl111sf_state *state = d->priv; | ||
819 | int hwi2c = (state->chip_rev > MXL111SF_V6); | ||
820 | int i, ret; | ||
821 | |||
822 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
823 | return -EAGAIN; | ||
824 | |||
825 | for (i = 0; i < num; i++) { | ||
826 | ret = (hwi2c) ? | ||
827 | mxl111sf_i2c_hw_xfer_msg(state, &msg[i]) : | ||
828 | mxl111sf_i2c_sw_xfer_msg(state, &msg[i]); | ||
829 | if (mxl_fail(ret)) { | ||
830 | mxl_debug_adv("failed with error %d on i2c " | ||
831 | "transaction %d of %d, %sing %d bytes " | ||
832 | "to/from 0x%02x", ret, i+1, num, | ||
833 | (msg[i].flags & I2C_M_RD) ? | ||
834 | "read" : "writ", | ||
835 | msg[i].len, msg[i].addr); | ||
836 | |||
837 | break; | ||
838 | } | ||
839 | } | ||
840 | |||
841 | mutex_unlock(&d->i2c_mutex); | ||
842 | |||
843 | return i == num ? num : -EREMOTEIO; | ||
844 | } | ||
845 | |||
846 | /* | ||
847 | * Local variables: | ||
848 | * c-basic-offset: 8 | ||
849 | * End: | ||
850 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h new file mode 100644 index 000000000000..a57a45ffb9e4 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * mxl111sf-i2c.h - driver for the MaxLinear MXL111SF | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #ifndef _DVB_USB_MXL111SF_I2C_H_ | ||
22 | #define _DVB_USB_MXL111SF_I2C_H_ | ||
23 | |||
24 | #include <linux/i2c.h> | ||
25 | |||
26 | int mxl111sf_i2c_xfer(struct i2c_adapter *adap, | ||
27 | struct i2c_msg msg[], int num); | ||
28 | |||
29 | #endif /* _DVB_USB_MXL111SF_I2C_H_ */ | ||
30 | |||
31 | /* | ||
32 | * Local variables: | ||
33 | * c-basic-offset: 8 | ||
34 | * End: | ||
35 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c new file mode 100644 index 000000000000..b741b3a7a325 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c | |||
@@ -0,0 +1,343 @@ | |||
1 | /* | ||
2 | * mxl111sf-phy.c - driver for the MaxLinear MXL111SF | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #include "mxl111sf-phy.h" | ||
22 | #include "mxl111sf-reg.h" | ||
23 | |||
24 | int mxl111sf_init_tuner_demod(struct mxl111sf_state *state) | ||
25 | { | ||
26 | struct mxl111sf_reg_ctrl_info mxl_111_overwrite_default[] = { | ||
27 | {0x07, 0xff, 0x0c}, | ||
28 | {0x58, 0xff, 0x9d}, | ||
29 | {0x09, 0xff, 0x00}, | ||
30 | {0x06, 0xff, 0x06}, | ||
31 | {0xc8, 0xff, 0x40}, /* ED_LE_WIN_OLD = 0 */ | ||
32 | {0x8d, 0x01, 0x01}, /* NEGATE_Q */ | ||
33 | {0x32, 0xff, 0xac}, /* DIG_RFREFSELECT = 12 */ | ||
34 | {0x42, 0xff, 0x43}, /* DIG_REG_AMP = 4 */ | ||
35 | {0x74, 0xff, 0xc4}, /* SSPUR_FS_PRIO = 4 */ | ||
36 | {0x71, 0xff, 0xe6}, /* SPUR_ROT_PRIO_VAL = 1 */ | ||
37 | {0x83, 0xff, 0x64}, /* INF_FILT1_THD_SC = 100 */ | ||
38 | {0x85, 0xff, 0x64}, /* INF_FILT2_THD_SC = 100 */ | ||
39 | {0x88, 0xff, 0xf0}, /* INF_THD = 240 */ | ||
40 | {0x6f, 0xf0, 0xb0}, /* DFE_DLY = 11 */ | ||
41 | {0x00, 0xff, 0x01}, /* Change to page 1 */ | ||
42 | {0x81, 0xff, 0x11}, /* DSM_FERR_BYPASS = 1 */ | ||
43 | {0xf4, 0xff, 0x07}, /* DIG_FREQ_CORR = 1 */ | ||
44 | {0xd4, 0x1f, 0x0f}, /* SPUR_TEST_NOISE_TH = 15 */ | ||
45 | {0xd6, 0xff, 0x0c}, /* SPUR_TEST_NOISE_PAPR = 12 */ | ||
46 | {0x00, 0xff, 0x00}, /* Change to page 0 */ | ||
47 | {0, 0, 0} | ||
48 | }; | ||
49 | |||
50 | mxl_debug("()"); | ||
51 | |||
52 | return mxl111sf_ctrl_program_regs(state, mxl_111_overwrite_default); | ||
53 | } | ||
54 | |||
55 | int mxl1x1sf_soft_reset(struct mxl111sf_state *state) | ||
56 | { | ||
57 | int ret; | ||
58 | mxl_debug("()"); | ||
59 | |||
60 | ret = mxl111sf_write_reg(state, 0xff, 0x00); /* AIC */ | ||
61 | if (mxl_fail(ret)) | ||
62 | goto fail; | ||
63 | ret = mxl111sf_write_reg(state, 0x02, 0x01); /* get out of reset */ | ||
64 | mxl_fail(ret); | ||
65 | fail: | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode) | ||
70 | { | ||
71 | int ret; | ||
72 | |||
73 | mxl_debug("(%s)", MXL_SOC_MODE == mode ? | ||
74 | "MXL_SOC_MODE" : "MXL_TUNER_MODE"); | ||
75 | |||
76 | /* set device mode */ | ||
77 | ret = mxl111sf_write_reg(state, 0x03, | ||
78 | MXL_SOC_MODE == mode ? 0x01 : 0x00); | ||
79 | if (mxl_fail(ret)) | ||
80 | goto fail; | ||
81 | |||
82 | ret = mxl111sf_write_reg_mask(state, | ||
83 | 0x7d, 0x40, MXL_SOC_MODE == mode ? | ||
84 | 0x00 : /* enable impulse noise filter, | ||
85 | INF_BYP = 0 */ | ||
86 | 0x40); /* disable impulse noise filter, | ||
87 | INF_BYP = 1 */ | ||
88 | if (mxl_fail(ret)) | ||
89 | goto fail; | ||
90 | |||
91 | state->device_mode = mode; | ||
92 | fail: | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | /* power up tuner */ | ||
97 | int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff) | ||
98 | { | ||
99 | mxl_debug("(%d)", onoff); | ||
100 | |||
101 | return mxl111sf_write_reg(state, 0x01, onoff ? 0x01 : 0x00); | ||
102 | } | ||
103 | |||
104 | int mxl111sf_disable_656_port(struct mxl111sf_state *state) | ||
105 | { | ||
106 | mxl_debug("()"); | ||
107 | |||
108 | return mxl111sf_write_reg_mask(state, 0x12, 0x04, 0x00); | ||
109 | } | ||
110 | |||
111 | int mxl111sf_enable_usb_output(struct mxl111sf_state *state) | ||
112 | { | ||
113 | mxl_debug("()"); | ||
114 | |||
115 | return mxl111sf_write_reg_mask(state, 0x17, 0x40, 0x00); | ||
116 | } | ||
117 | |||
118 | /* initialize TSIF as input port of MxL1X1SF for MPEG2 data transfer */ | ||
119 | int mxl111sf_config_mpeg_in(struct mxl111sf_state *state, | ||
120 | unsigned int parallel_serial, | ||
121 | unsigned int msb_lsb_1st, | ||
122 | unsigned int clock_phase, | ||
123 | unsigned int mpeg_valid_pol, | ||
124 | unsigned int mpeg_sync_pol) | ||
125 | { | ||
126 | int ret; | ||
127 | u8 mode, tmp; | ||
128 | |||
129 | mxl_debug("(%u,%u,%u,%u,%u)", parallel_serial, msb_lsb_1st, | ||
130 | clock_phase, mpeg_valid_pol, mpeg_sync_pol); | ||
131 | |||
132 | /* Enable PIN MUX */ | ||
133 | ret = mxl111sf_write_reg(state, V6_PIN_MUX_MODE_REG, V6_ENABLE_PIN_MUX); | ||
134 | mxl_fail(ret); | ||
135 | |||
136 | /* Configure MPEG Clock phase */ | ||
137 | mxl111sf_read_reg(state, V6_MPEG_IN_CLK_INV_REG, &mode); | ||
138 | |||
139 | if (clock_phase == TSIF_NORMAL) | ||
140 | mode &= ~V6_INVERTED_CLK_PHASE; | ||
141 | else | ||
142 | mode |= V6_INVERTED_CLK_PHASE; | ||
143 | |||
144 | ret = mxl111sf_write_reg(state, V6_MPEG_IN_CLK_INV_REG, mode); | ||
145 | mxl_fail(ret); | ||
146 | |||
147 | /* Configure data input mode, MPEG Valid polarity, MPEG Sync polarity | ||
148 | * Get current configuration */ | ||
149 | ret = mxl111sf_read_reg(state, V6_MPEG_IN_CTRL_REG, &mode); | ||
150 | mxl_fail(ret); | ||
151 | |||
152 | /* Data Input mode */ | ||
153 | if (parallel_serial == TSIF_INPUT_PARALLEL) { | ||
154 | /* Disable serial mode */ | ||
155 | mode &= ~V6_MPEG_IN_DATA_SERIAL; | ||
156 | |||
157 | /* Enable Parallel mode */ | ||
158 | mode |= V6_MPEG_IN_DATA_PARALLEL; | ||
159 | } else { | ||
160 | /* Disable Parallel mode */ | ||
161 | mode &= ~V6_MPEG_IN_DATA_PARALLEL; | ||
162 | |||
163 | /* Enable Serial Mode */ | ||
164 | mode |= V6_MPEG_IN_DATA_SERIAL; | ||
165 | |||
166 | /* If serial interface is chosen, configure | ||
167 | MSB or LSB order in transmission */ | ||
168 | ret = mxl111sf_read_reg(state, | ||
169 | V6_MPEG_INOUT_BIT_ORDER_CTRL_REG, | ||
170 | &tmp); | ||
171 | mxl_fail(ret); | ||
172 | |||
173 | if (msb_lsb_1st == MPEG_SER_MSB_FIRST_ENABLED) | ||
174 | tmp |= V6_MPEG_SER_MSB_FIRST; | ||
175 | else | ||
176 | tmp &= ~V6_MPEG_SER_MSB_FIRST; | ||
177 | |||
178 | ret = mxl111sf_write_reg(state, | ||
179 | V6_MPEG_INOUT_BIT_ORDER_CTRL_REG, | ||
180 | tmp); | ||
181 | mxl_fail(ret); | ||
182 | } | ||
183 | |||
184 | /* MPEG Sync polarity */ | ||
185 | if (mpeg_sync_pol == TSIF_NORMAL) | ||
186 | mode &= ~V6_INVERTED_MPEG_SYNC; | ||
187 | else | ||
188 | mode |= V6_INVERTED_MPEG_SYNC; | ||
189 | |||
190 | /* MPEG Valid polarity */ | ||
191 | if (mpeg_valid_pol == 0) | ||
192 | mode &= ~V6_INVERTED_MPEG_VALID; | ||
193 | else | ||
194 | mode |= V6_INVERTED_MPEG_VALID; | ||
195 | |||
196 | ret = mxl111sf_write_reg(state, V6_MPEG_IN_CTRL_REG, mode); | ||
197 | mxl_fail(ret); | ||
198 | |||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size) | ||
203 | { | ||
204 | static struct mxl111sf_reg_ctrl_info init_i2s[] = { | ||
205 | {0x1b, 0xff, 0x1e}, /* pin mux mode, Choose 656/I2S input */ | ||
206 | {0x15, 0x60, 0x60}, /* Enable I2S */ | ||
207 | {0x17, 0xe0, 0x20}, /* Input, MPEG MODE USB, | ||
208 | Inverted 656 Clock, I2S_SOFT_RESET, | ||
209 | 0 : Normal operation, 1 : Reset State */ | ||
210 | #if 0 | ||
211 | {0x12, 0x01, 0x00}, /* AUDIO_IRQ_CLR (Overflow Indicator) */ | ||
212 | #endif | ||
213 | {0x00, 0xff, 0x02}, /* Change to Control Page */ | ||
214 | {0x26, 0x0d, 0x0d}, /* I2S_MODE & BT656_SRC_SEL for FPGA only */ | ||
215 | {0x00, 0xff, 0x00}, | ||
216 | {0, 0, 0} | ||
217 | }; | ||
218 | int ret; | ||
219 | |||
220 | mxl_debug("(0x%02x)", sample_size); | ||
221 | |||
222 | ret = mxl111sf_ctrl_program_regs(state, init_i2s); | ||
223 | if (mxl_fail(ret)) | ||
224 | goto fail; | ||
225 | |||
226 | ret = mxl111sf_write_reg(state, V6_I2S_NUM_SAMPLES_REG, sample_size); | ||
227 | mxl_fail(ret); | ||
228 | fail: | ||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | int mxl111sf_disable_i2s_port(struct mxl111sf_state *state) | ||
233 | { | ||
234 | static struct mxl111sf_reg_ctrl_info disable_i2s[] = { | ||
235 | {0x15, 0x40, 0x00}, | ||
236 | {0, 0, 0} | ||
237 | }; | ||
238 | |||
239 | mxl_debug("()"); | ||
240 | |||
241 | return mxl111sf_ctrl_program_regs(state, disable_i2s); | ||
242 | } | ||
243 | |||
244 | int mxl111sf_config_i2s(struct mxl111sf_state *state, | ||
245 | u8 msb_start_pos, u8 data_width) | ||
246 | { | ||
247 | int ret; | ||
248 | u8 tmp; | ||
249 | |||
250 | mxl_debug("(0x%02x, 0x%02x)", msb_start_pos, data_width); | ||
251 | |||
252 | ret = mxl111sf_read_reg(state, V6_I2S_STREAM_START_BIT_REG, &tmp); | ||
253 | if (mxl_fail(ret)) | ||
254 | goto fail; | ||
255 | |||
256 | tmp &= 0xe0; | ||
257 | tmp |= msb_start_pos; | ||
258 | ret = mxl111sf_write_reg(state, V6_I2S_STREAM_START_BIT_REG, tmp); | ||
259 | if (mxl_fail(ret)) | ||
260 | goto fail; | ||
261 | |||
262 | ret = mxl111sf_read_reg(state, V6_I2S_STREAM_END_BIT_REG, &tmp); | ||
263 | if (mxl_fail(ret)) | ||
264 | goto fail; | ||
265 | |||
266 | tmp &= 0xe0; | ||
267 | tmp |= data_width; | ||
268 | ret = mxl111sf_write_reg(state, V6_I2S_STREAM_END_BIT_REG, tmp); | ||
269 | mxl_fail(ret); | ||
270 | fail: | ||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff) | ||
275 | { | ||
276 | u8 val; | ||
277 | int ret; | ||
278 | |||
279 | mxl_debug("(%d)", onoff); | ||
280 | |||
281 | ret = mxl111sf_write_reg(state, 0x00, 0x02); | ||
282 | if (mxl_fail(ret)) | ||
283 | goto fail; | ||
284 | |||
285 | ret = mxl111sf_read_reg(state, V8_SPI_MODE_REG, &val); | ||
286 | if (mxl_fail(ret)) | ||
287 | goto fail; | ||
288 | |||
289 | if (onoff) | ||
290 | val |= 0x04; | ||
291 | else | ||
292 | val &= ~0x04; | ||
293 | |||
294 | ret = mxl111sf_write_reg(state, V8_SPI_MODE_REG, val); | ||
295 | if (mxl_fail(ret)) | ||
296 | goto fail; | ||
297 | |||
298 | ret = mxl111sf_write_reg(state, 0x00, 0x00); | ||
299 | mxl_fail(ret); | ||
300 | fail: | ||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | int mxl111sf_idac_config(struct mxl111sf_state *state, | ||
305 | u8 control_mode, u8 current_setting, | ||
306 | u8 current_value, u8 hysteresis_value) | ||
307 | { | ||
308 | int ret; | ||
309 | u8 val; | ||
310 | /* current value will be set for both automatic & manual IDAC control */ | ||
311 | val = current_value; | ||
312 | |||
313 | if (control_mode == IDAC_MANUAL_CONTROL) { | ||
314 | /* enable manual control of IDAC */ | ||
315 | val |= IDAC_MANUAL_CONTROL_BIT_MASK; | ||
316 | |||
317 | if (current_setting == IDAC_CURRENT_SINKING_ENABLE) | ||
318 | /* enable current sinking in manual mode */ | ||
319 | val |= IDAC_CURRENT_SINKING_BIT_MASK; | ||
320 | else | ||
321 | /* disable current sinking in manual mode */ | ||
322 | val &= ~IDAC_CURRENT_SINKING_BIT_MASK; | ||
323 | } else { | ||
324 | /* disable manual control of IDAC */ | ||
325 | val &= ~IDAC_MANUAL_CONTROL_BIT_MASK; | ||
326 | |||
327 | /* set hysteresis value reg: 0x0B<5:0> */ | ||
328 | ret = mxl111sf_write_reg(state, V6_IDAC_HYSTERESIS_REG, | ||
329 | (hysteresis_value & 0x3F)); | ||
330 | mxl_fail(ret); | ||
331 | } | ||
332 | |||
333 | ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val); | ||
334 | mxl_fail(ret); | ||
335 | |||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * Local variables: | ||
341 | * c-basic-offset: 8 | ||
342 | * End: | ||
343 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h new file mode 100644 index 000000000000..f0756071d347 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * mxl111sf-phy.h - driver for the MaxLinear MXL111SF | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #ifndef _DVB_USB_MXL111SF_PHY_H_ | ||
22 | #define _DVB_USB_MXL111SF_PHY_H_ | ||
23 | |||
24 | #include "mxl111sf.h" | ||
25 | |||
26 | int mxl1x1sf_soft_reset(struct mxl111sf_state *state); | ||
27 | int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode); | ||
28 | int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff); | ||
29 | int mxl111sf_disable_656_port(struct mxl111sf_state *state); | ||
30 | int mxl111sf_init_tuner_demod(struct mxl111sf_state *state); | ||
31 | int mxl111sf_enable_usb_output(struct mxl111sf_state *state); | ||
32 | int mxl111sf_config_mpeg_in(struct mxl111sf_state *state, | ||
33 | unsigned int parallel_serial, | ||
34 | unsigned int msb_lsb_1st, | ||
35 | unsigned int clock_phase, | ||
36 | unsigned int mpeg_valid_pol, | ||
37 | unsigned int mpeg_sync_pol); | ||
38 | int mxl111sf_config_i2s(struct mxl111sf_state *state, | ||
39 | u8 msb_start_pos, u8 data_width); | ||
40 | int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size); | ||
41 | int mxl111sf_disable_i2s_port(struct mxl111sf_state *state); | ||
42 | int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff); | ||
43 | int mxl111sf_idac_config(struct mxl111sf_state *state, | ||
44 | u8 control_mode, u8 current_setting, | ||
45 | u8 current_value, u8 hysteresis_value); | ||
46 | |||
47 | #endif /* _DVB_USB_MXL111SF_PHY_H_ */ | ||
48 | |||
49 | /* | ||
50 | * Local variables: | ||
51 | * c-basic-offset: 8 | ||
52 | * End: | ||
53 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h new file mode 100644 index 000000000000..17831b0fb9db --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | * mxl111sf-reg.h - driver for the MaxLinear MXL111SF | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #ifndef _DVB_USB_MXL111SF_REG_H_ | ||
22 | #define _DVB_USB_MXL111SF_REG_H_ | ||
23 | |||
24 | #define CHIP_ID_REG 0xFC | ||
25 | #define TOP_CHIP_REV_ID_REG 0xFA | ||
26 | |||
27 | #define V6_SNR_RB_LSB_REG 0x27 | ||
28 | #define V6_SNR_RB_MSB_REG 0x28 | ||
29 | |||
30 | #define V6_N_ACCUMULATE_REG 0x11 | ||
31 | #define V6_RS_AVG_ERRORS_LSB_REG 0x2C | ||
32 | #define V6_RS_AVG_ERRORS_MSB_REG 0x2D | ||
33 | |||
34 | #define V6_IRQ_STATUS_REG 0x24 | ||
35 | #define IRQ_MASK_FEC_LOCK 0x10 | ||
36 | |||
37 | #define V6_SYNC_LOCK_REG 0x28 | ||
38 | #define SYNC_LOCK_MASK 0x10 | ||
39 | |||
40 | #define V6_RS_LOCK_DET_REG 0x28 | ||
41 | #define RS_LOCK_DET_MASK 0x08 | ||
42 | |||
43 | #define V6_INITACQ_NODETECT_REG 0x20 | ||
44 | #define V6_FORCE_NFFT_CPSIZE_REG 0x20 | ||
45 | |||
46 | #define V6_CODE_RATE_TPS_REG 0x29 | ||
47 | #define V6_CODE_RATE_TPS_MASK 0x07 | ||
48 | |||
49 | |||
50 | #define V6_CP_LOCK_DET_REG 0x28 | ||
51 | #define V6_CP_LOCK_DET_MASK 0x04 | ||
52 | |||
53 | #define V6_TPS_HIERACHY_REG 0x29 | ||
54 | #define V6_TPS_HIERARCHY_INFO_MASK 0x40 | ||
55 | |||
56 | #define V6_MODORDER_TPS_REG 0x2A | ||
57 | #define V6_PARAM_CONSTELLATION_MASK 0x30 | ||
58 | |||
59 | #define V6_MODE_TPS_REG 0x2A | ||
60 | #define V6_PARAM_FFT_MODE_MASK 0x0C | ||
61 | |||
62 | |||
63 | #define V6_CP_TPS_REG 0x29 | ||
64 | #define V6_PARAM_GI_MASK 0x30 | ||
65 | |||
66 | #define V6_TPS_LOCK_REG 0x2A | ||
67 | #define V6_PARAM_TPS_LOCK_MASK 0x40 | ||
68 | |||
69 | #define V6_FEC_PER_COUNT_REG 0x2E | ||
70 | #define V6_FEC_PER_SCALE_REG 0x2B | ||
71 | #define V6_FEC_PER_SCALE_MASK 0x03 | ||
72 | #define V6_FEC_PER_CLR_REG 0x20 | ||
73 | #define V6_FEC_PER_CLR_MASK 0x01 | ||
74 | |||
75 | #define V6_PIN_MUX_MODE_REG 0x1B | ||
76 | #define V6_ENABLE_PIN_MUX 0x1E | ||
77 | |||
78 | #define V6_I2S_NUM_SAMPLES_REG 0x16 | ||
79 | |||
80 | #define V6_MPEG_IN_CLK_INV_REG 0x17 | ||
81 | #define V6_MPEG_IN_CTRL_REG 0x18 | ||
82 | |||
83 | #define V6_INVERTED_CLK_PHASE 0x20 | ||
84 | #define V6_MPEG_IN_DATA_PARALLEL 0x01 | ||
85 | #define V6_MPEG_IN_DATA_SERIAL 0x02 | ||
86 | |||
87 | #define V6_INVERTED_MPEG_SYNC 0x04 | ||
88 | #define V6_INVERTED_MPEG_VALID 0x08 | ||
89 | |||
90 | #define TSIF_INPUT_PARALLEL 0 | ||
91 | #define TSIF_INPUT_SERIAL 1 | ||
92 | #define TSIF_NORMAL 0 | ||
93 | |||
94 | #define V6_MPEG_INOUT_BIT_ORDER_CTRL_REG 0x19 | ||
95 | #define V6_MPEG_SER_MSB_FIRST 0x80 | ||
96 | #define MPEG_SER_MSB_FIRST_ENABLED 0x01 | ||
97 | |||
98 | #define V6_656_I2S_BUFF_STATUS_REG 0x2F | ||
99 | #define V6_656_OVERFLOW_MASK_BIT 0x08 | ||
100 | #define V6_I2S_OVERFLOW_MASK_BIT 0x01 | ||
101 | |||
102 | #define V6_I2S_STREAM_START_BIT_REG 0x14 | ||
103 | #define V6_I2S_STREAM_END_BIT_REG 0x15 | ||
104 | #define I2S_RIGHT_JUSTIFIED 0 | ||
105 | #define I2S_LEFT_JUSTIFIED 1 | ||
106 | #define I2S_DATA_FORMAT 2 | ||
107 | |||
108 | #define V6_TUNER_LOOP_THRU_CONTROL_REG 0x09 | ||
109 | #define V6_ENABLE_LOOP_THRU 0x01 | ||
110 | |||
111 | #define TOTAL_NUM_IF_OUTPUT_FREQ 16 | ||
112 | |||
113 | #define TUNER_NORMAL_IF_SPECTRUM 0x0 | ||
114 | #define TUNER_INVERT_IF_SPECTRUM 0x10 | ||
115 | |||
116 | #define V6_TUNER_IF_SEL_REG 0x06 | ||
117 | #define V6_TUNER_IF_FCW_REG 0x3C | ||
118 | #define V6_TUNER_IF_FCW_BYP_REG 0x3D | ||
119 | #define V6_RF_LOCK_STATUS_REG 0x23 | ||
120 | |||
121 | #define NUM_DIG_TV_CHANNEL 1000 | ||
122 | |||
123 | #define V6_DIG_CLK_FREQ_SEL_REG 0x07 | ||
124 | #define V6_REF_SYNTH_INT_REG 0x5C | ||
125 | #define V6_REF_SYNTH_REMAIN_REG 0x58 | ||
126 | #define V6_DIG_RFREFSELECT_REG 0x32 | ||
127 | #define V6_XTAL_CLK_OUT_GAIN_REG 0x31 | ||
128 | #define V6_TUNER_LOOP_THRU_CTRL_REG 0x09 | ||
129 | #define V6_DIG_XTAL_ENABLE_REG 0x06 | ||
130 | #define V6_DIG_XTAL_BIAS_REG 0x66 | ||
131 | #define V6_XTAL_CAP_REG 0x08 | ||
132 | |||
133 | #define V6_GPO_CTRL_REG 0x18 | ||
134 | #define MXL_GPO_0 0x00 | ||
135 | #define MXL_GPO_1 0x01 | ||
136 | #define V6_GPO_0_MASK 0x10 | ||
137 | #define V6_GPO_1_MASK 0x20 | ||
138 | |||
139 | #define V6_111SF_GPO_CTRL_REG 0x19 | ||
140 | #define MXL_111SF_GPO_1 0x00 | ||
141 | #define MXL_111SF_GPO_2 0x01 | ||
142 | #define MXL_111SF_GPO_3 0x02 | ||
143 | #define MXL_111SF_GPO_4 0x03 | ||
144 | #define MXL_111SF_GPO_5 0x04 | ||
145 | #define MXL_111SF_GPO_6 0x05 | ||
146 | #define MXL_111SF_GPO_7 0x06 | ||
147 | |||
148 | #define MXL_111SF_GPO_0_MASK 0x01 | ||
149 | #define MXL_111SF_GPO_1_MASK 0x02 | ||
150 | #define MXL_111SF_GPO_2_MASK 0x04 | ||
151 | #define MXL_111SF_GPO_3_MASK 0x08 | ||
152 | #define MXL_111SF_GPO_4_MASK 0x10 | ||
153 | #define MXL_111SF_GPO_5_MASK 0x20 | ||
154 | #define MXL_111SF_GPO_6_MASK 0x40 | ||
155 | |||
156 | #define V6_ATSC_CONFIG_REG 0x0A | ||
157 | |||
158 | #define MXL_MODE_REG 0x03 | ||
159 | #define START_TUNE_REG 0x1C | ||
160 | |||
161 | #define V6_IDAC_HYSTERESIS_REG 0x0B | ||
162 | #define V6_IDAC_SETTINGS_REG 0x0C | ||
163 | #define IDAC_MANUAL_CONTROL 1 | ||
164 | #define IDAC_CURRENT_SINKING_ENABLE 1 | ||
165 | #define IDAC_MANUAL_CONTROL_BIT_MASK 0x80 | ||
166 | #define IDAC_CURRENT_SINKING_BIT_MASK 0x40 | ||
167 | |||
168 | #define V8_SPI_MODE_REG 0xE9 | ||
169 | |||
170 | #define V6_DIG_RF_PWR_LSB_REG 0x46 | ||
171 | #define V6_DIG_RF_PWR_MSB_REG 0x47 | ||
172 | |||
173 | #endif /* _DVB_USB_MXL111SF_REG_H_ */ | ||
174 | |||
175 | /* | ||
176 | * Local variables: | ||
177 | * c-basic-offset: 8 | ||
178 | * End: | ||
179 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c new file mode 100644 index 000000000000..ef4c65fcbb73 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c | |||
@@ -0,0 +1,527 @@ | |||
1 | /* | ||
2 | * mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #include "mxl111sf-tuner.h" | ||
22 | #include "mxl111sf-phy.h" | ||
23 | #include "mxl111sf-reg.h" | ||
24 | |||
25 | /* debug */ | ||
26 | static int mxl111sf_tuner_debug; | ||
27 | module_param_named(debug, mxl111sf_tuner_debug, int, 0644); | ||
28 | MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); | ||
29 | |||
30 | #define mxl_dbg(fmt, arg...) \ | ||
31 | if (mxl111sf_tuner_debug) \ | ||
32 | mxl_printk(KERN_DEBUG, fmt, ##arg) | ||
33 | |||
34 | #define err pr_err | ||
35 | |||
36 | /* ------------------------------------------------------------------------ */ | ||
37 | |||
38 | struct mxl111sf_tuner_state { | ||
39 | struct mxl111sf_state *mxl_state; | ||
40 | |||
41 | struct mxl111sf_tuner_config *cfg; | ||
42 | |||
43 | enum mxl_if_freq if_freq; | ||
44 | |||
45 | u32 frequency; | ||
46 | u32 bandwidth; | ||
47 | }; | ||
48 | |||
49 | static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state, | ||
50 | u8 addr, u8 *data) | ||
51 | { | ||
52 | return (state->cfg->read_reg) ? | ||
53 | state->cfg->read_reg(state->mxl_state, addr, data) : | ||
54 | -EINVAL; | ||
55 | } | ||
56 | |||
57 | static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state, | ||
58 | u8 addr, u8 data) | ||
59 | { | ||
60 | return (state->cfg->write_reg) ? | ||
61 | state->cfg->write_reg(state->mxl_state, addr, data) : | ||
62 | -EINVAL; | ||
63 | } | ||
64 | |||
65 | static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state, | ||
66 | struct mxl111sf_reg_ctrl_info *ctrl_reg_info) | ||
67 | { | ||
68 | return (state->cfg->program_regs) ? | ||
69 | state->cfg->program_regs(state->mxl_state, ctrl_reg_info) : | ||
70 | -EINVAL; | ||
71 | } | ||
72 | |||
73 | static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state, | ||
74 | int onoff) | ||
75 | { | ||
76 | return (state->cfg->top_master_ctrl) ? | ||
77 | state->cfg->top_master_ctrl(state->mxl_state, onoff) : | ||
78 | -EINVAL; | ||
79 | } | ||
80 | |||
81 | /* ------------------------------------------------------------------------ */ | ||
82 | |||
83 | static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = { | ||
84 | {0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3, | ||
85 | DIG_MODEINDEX, _A, _CSF, */ | ||
86 | {0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */ | ||
87 | {0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */ | ||
88 | {0, 0, 0} | ||
89 | }; | ||
90 | |||
91 | /* ------------------------------------------------------------------------ */ | ||
92 | |||
93 | static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq, | ||
94 | u8 bw) | ||
95 | { | ||
96 | u8 filt_bw; | ||
97 | |||
98 | /* set channel bandwidth */ | ||
99 | switch (bw) { | ||
100 | case 0: /* ATSC */ | ||
101 | filt_bw = 25; | ||
102 | break; | ||
103 | case 1: /* QAM */ | ||
104 | filt_bw = 69; | ||
105 | break; | ||
106 | case 6: | ||
107 | filt_bw = 21; | ||
108 | break; | ||
109 | case 7: | ||
110 | filt_bw = 42; | ||
111 | break; | ||
112 | case 8: | ||
113 | filt_bw = 63; | ||
114 | break; | ||
115 | default: | ||
116 | err("%s: invalid bandwidth setting!", __func__); | ||
117 | return NULL; | ||
118 | } | ||
119 | |||
120 | /* calculate RF channel */ | ||
121 | freq /= 1000000; | ||
122 | |||
123 | freq *= 64; | ||
124 | #if 0 | ||
125 | /* do round */ | ||
126 | freq += 0.5; | ||
127 | #endif | ||
128 | /* set bandwidth */ | ||
129 | mxl_phy_tune_rf[0].data = filt_bw; | ||
130 | |||
131 | /* set RF */ | ||
132 | mxl_phy_tune_rf[1].data = (freq & 0xff); | ||
133 | mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff; | ||
134 | |||
135 | /* start tune */ | ||
136 | return mxl_phy_tune_rf; | ||
137 | } | ||
138 | |||
139 | static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state) | ||
140 | { | ||
141 | int ret; | ||
142 | u8 ctrl; | ||
143 | #if 0 | ||
144 | u16 iffcw; | ||
145 | u32 if_freq; | ||
146 | #endif | ||
147 | mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)", | ||
148 | state->cfg->invert_spectrum, state->cfg->if_freq); | ||
149 | |||
150 | /* set IF polarity */ | ||
151 | ctrl = state->cfg->invert_spectrum; | ||
152 | |||
153 | ctrl |= state->cfg->if_freq; | ||
154 | |||
155 | ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl); | ||
156 | if (mxl_fail(ret)) | ||
157 | goto fail; | ||
158 | |||
159 | #if 0 | ||
160 | if_freq /= 1000000; | ||
161 | |||
162 | /* do round */ | ||
163 | if_freq += 0.5; | ||
164 | |||
165 | if (MXL_IF_LO == state->cfg->if_freq) { | ||
166 | ctrl = 0x08; | ||
167 | iffcw = (u16)(if_freq / (108 * 4096)); | ||
168 | } else if (MXL_IF_HI == state->cfg->if_freq) { | ||
169 | ctrl = 0x08; | ||
170 | iffcw = (u16)(if_freq / (216 * 4096)); | ||
171 | } else { | ||
172 | ctrl = 0; | ||
173 | iffcw = 0; | ||
174 | } | ||
175 | |||
176 | ctrl |= (iffcw >> 8); | ||
177 | #endif | ||
178 | ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl); | ||
179 | if (mxl_fail(ret)) | ||
180 | goto fail; | ||
181 | |||
182 | ctrl &= 0xf0; | ||
183 | ctrl |= 0x90; | ||
184 | |||
185 | ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl); | ||
186 | if (mxl_fail(ret)) | ||
187 | goto fail; | ||
188 | |||
189 | #if 0 | ||
190 | ctrl = iffcw & 0x00ff; | ||
191 | #endif | ||
192 | ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl); | ||
193 | if (mxl_fail(ret)) | ||
194 | goto fail; | ||
195 | |||
196 | state->if_freq = state->cfg->if_freq; | ||
197 | fail: | ||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw) | ||
202 | { | ||
203 | struct mxl111sf_tuner_state *state = fe->tuner_priv; | ||
204 | static struct mxl111sf_reg_ctrl_info *reg_ctrl_array; | ||
205 | int ret; | ||
206 | u8 mxl_mode; | ||
207 | |||
208 | mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw); | ||
209 | |||
210 | /* stop tune */ | ||
211 | ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0); | ||
212 | if (mxl_fail(ret)) | ||
213 | goto fail; | ||
214 | |||
215 | /* check device mode */ | ||
216 | ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode); | ||
217 | if (mxl_fail(ret)) | ||
218 | goto fail; | ||
219 | |||
220 | /* Fill out registers for channel tune */ | ||
221 | reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw); | ||
222 | if (!reg_ctrl_array) | ||
223 | return -EINVAL; | ||
224 | |||
225 | ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array); | ||
226 | if (mxl_fail(ret)) | ||
227 | goto fail; | ||
228 | |||
229 | if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) { | ||
230 | /* IF tuner mode only */ | ||
231 | mxl1x1sf_tuner_top_master_ctrl(state, 0); | ||
232 | mxl1x1sf_tuner_top_master_ctrl(state, 1); | ||
233 | mxl1x1sf_tuner_set_if_output_freq(state); | ||
234 | } | ||
235 | |||
236 | ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1); | ||
237 | if (mxl_fail(ret)) | ||
238 | goto fail; | ||
239 | |||
240 | if (state->cfg->ant_hunt) | ||
241 | state->cfg->ant_hunt(fe); | ||
242 | fail: | ||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state, | ||
247 | int *rf_synth_lock, | ||
248 | int *ref_synth_lock) | ||
249 | { | ||
250 | int ret; | ||
251 | u8 data; | ||
252 | |||
253 | *rf_synth_lock = 0; | ||
254 | *ref_synth_lock = 0; | ||
255 | |||
256 | ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data); | ||
257 | if (mxl_fail(ret)) | ||
258 | goto fail; | ||
259 | |||
260 | *ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0; | ||
261 | *rf_synth_lock = ((data & 0x0c) == 0x0c) ? 1 : 0; | ||
262 | fail: | ||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | #if 0 | ||
267 | static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state, | ||
268 | int onoff) | ||
269 | { | ||
270 | return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG, | ||
271 | onoff ? 1 : 0); | ||
272 | } | ||
273 | #endif | ||
274 | |||
275 | /* ------------------------------------------------------------------------ */ | ||
276 | |||
277 | static int mxl111sf_tuner_set_params(struct dvb_frontend *fe) | ||
278 | { | ||
279 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
280 | u32 delsys = c->delivery_system; | ||
281 | struct mxl111sf_tuner_state *state = fe->tuner_priv; | ||
282 | int ret; | ||
283 | u8 bw; | ||
284 | |||
285 | mxl_dbg("()"); | ||
286 | |||
287 | switch (delsys) { | ||
288 | case SYS_ATSC: | ||
289 | case SYS_ATSCMH: | ||
290 | bw = 0; /* ATSC */ | ||
291 | break; | ||
292 | case SYS_DVBC_ANNEX_B: | ||
293 | bw = 1; /* US CABLE */ | ||
294 | break; | ||
295 | case SYS_DVBT: | ||
296 | switch (c->bandwidth_hz) { | ||
297 | case 6000000: | ||
298 | bw = 6; | ||
299 | break; | ||
300 | case 7000000: | ||
301 | bw = 7; | ||
302 | break; | ||
303 | case 8000000: | ||
304 | bw = 8; | ||
305 | break; | ||
306 | default: | ||
307 | err("%s: bandwidth not set!", __func__); | ||
308 | return -EINVAL; | ||
309 | } | ||
310 | break; | ||
311 | default: | ||
312 | err("%s: modulation type not supported!", __func__); | ||
313 | return -EINVAL; | ||
314 | } | ||
315 | ret = mxl1x1sf_tune_rf(fe, c->frequency, bw); | ||
316 | if (mxl_fail(ret)) | ||
317 | goto fail; | ||
318 | |||
319 | state->frequency = c->frequency; | ||
320 | state->bandwidth = c->bandwidth_hz; | ||
321 | fail: | ||
322 | return ret; | ||
323 | } | ||
324 | |||
325 | /* ------------------------------------------------------------------------ */ | ||
326 | |||
327 | #if 0 | ||
328 | static int mxl111sf_tuner_init(struct dvb_frontend *fe) | ||
329 | { | ||
330 | struct mxl111sf_tuner_state *state = fe->tuner_priv; | ||
331 | int ret; | ||
332 | |||
333 | /* wake from standby handled by usb driver */ | ||
334 | |||
335 | return ret; | ||
336 | } | ||
337 | |||
338 | static int mxl111sf_tuner_sleep(struct dvb_frontend *fe) | ||
339 | { | ||
340 | struct mxl111sf_tuner_state *state = fe->tuner_priv; | ||
341 | int ret; | ||
342 | |||
343 | /* enter standby mode handled by usb driver */ | ||
344 | |||
345 | return ret; | ||
346 | } | ||
347 | #endif | ||
348 | |||
349 | /* ------------------------------------------------------------------------ */ | ||
350 | |||
351 | static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status) | ||
352 | { | ||
353 | struct mxl111sf_tuner_state *state = fe->tuner_priv; | ||
354 | int rf_locked, ref_locked, ret; | ||
355 | |||
356 | *status = 0; | ||
357 | |||
358 | ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked); | ||
359 | if (mxl_fail(ret)) | ||
360 | goto fail; | ||
361 | mxl_info("%s%s", rf_locked ? "rf locked " : "", | ||
362 | ref_locked ? "ref locked" : ""); | ||
363 | |||
364 | if ((rf_locked) || (ref_locked)) | ||
365 | *status |= TUNER_STATUS_LOCKED; | ||
366 | fail: | ||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength) | ||
371 | { | ||
372 | struct mxl111sf_tuner_state *state = fe->tuner_priv; | ||
373 | u8 val1, val2; | ||
374 | int ret; | ||
375 | |||
376 | *strength = 0; | ||
377 | |||
378 | ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02); | ||
379 | if (mxl_fail(ret)) | ||
380 | goto fail; | ||
381 | ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1); | ||
382 | if (mxl_fail(ret)) | ||
383 | goto fail; | ||
384 | ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2); | ||
385 | if (mxl_fail(ret)) | ||
386 | goto fail; | ||
387 | |||
388 | *strength = val1 | ((val2 & 0x07) << 8); | ||
389 | fail: | ||
390 | ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00); | ||
391 | mxl_fail(ret); | ||
392 | |||
393 | return ret; | ||
394 | } | ||
395 | |||
396 | /* ------------------------------------------------------------------------ */ | ||
397 | |||
398 | static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
399 | { | ||
400 | struct mxl111sf_tuner_state *state = fe->tuner_priv; | ||
401 | *frequency = state->frequency; | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | ||
406 | { | ||
407 | struct mxl111sf_tuner_state *state = fe->tuner_priv; | ||
408 | *bandwidth = state->bandwidth; | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe, | ||
413 | u32 *frequency) | ||
414 | { | ||
415 | struct mxl111sf_tuner_state *state = fe->tuner_priv; | ||
416 | |||
417 | *frequency = 0; | ||
418 | |||
419 | switch (state->if_freq) { | ||
420 | case MXL_IF_4_0: /* 4.0 MHz */ | ||
421 | *frequency = 4000000; | ||
422 | break; | ||
423 | case MXL_IF_4_5: /* 4.5 MHz */ | ||
424 | *frequency = 4500000; | ||
425 | break; | ||
426 | case MXL_IF_4_57: /* 4.57 MHz */ | ||
427 | *frequency = 4570000; | ||
428 | break; | ||
429 | case MXL_IF_5_0: /* 5.0 MHz */ | ||
430 | *frequency = 5000000; | ||
431 | break; | ||
432 | case MXL_IF_5_38: /* 5.38 MHz */ | ||
433 | *frequency = 5380000; | ||
434 | break; | ||
435 | case MXL_IF_6_0: /* 6.0 MHz */ | ||
436 | *frequency = 6000000; | ||
437 | break; | ||
438 | case MXL_IF_6_28: /* 6.28 MHz */ | ||
439 | *frequency = 6280000; | ||
440 | break; | ||
441 | case MXL_IF_7_2: /* 7.2 MHz */ | ||
442 | *frequency = 7200000; | ||
443 | break; | ||
444 | case MXL_IF_35_25: /* 35.25 MHz */ | ||
445 | *frequency = 35250000; | ||
446 | break; | ||
447 | case MXL_IF_36: /* 36 MHz */ | ||
448 | *frequency = 36000000; | ||
449 | break; | ||
450 | case MXL_IF_36_15: /* 36.15 MHz */ | ||
451 | *frequency = 36150000; | ||
452 | break; | ||
453 | case MXL_IF_44: /* 44 MHz */ | ||
454 | *frequency = 44000000; | ||
455 | break; | ||
456 | } | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int mxl111sf_tuner_release(struct dvb_frontend *fe) | ||
461 | { | ||
462 | struct mxl111sf_tuner_state *state = fe->tuner_priv; | ||
463 | mxl_dbg("()"); | ||
464 | kfree(state); | ||
465 | fe->tuner_priv = NULL; | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | /* ------------------------------------------------------------------------- */ | ||
470 | |||
471 | static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = { | ||
472 | .info = { | ||
473 | .name = "MaxLinear MxL111SF", | ||
474 | #if 0 | ||
475 | .frequency_min = , | ||
476 | .frequency_max = , | ||
477 | .frequency_step = , | ||
478 | #endif | ||
479 | }, | ||
480 | #if 0 | ||
481 | .init = mxl111sf_tuner_init, | ||
482 | .sleep = mxl111sf_tuner_sleep, | ||
483 | #endif | ||
484 | .set_params = mxl111sf_tuner_set_params, | ||
485 | .get_status = mxl111sf_tuner_get_status, | ||
486 | .get_rf_strength = mxl111sf_get_rf_strength, | ||
487 | .get_frequency = mxl111sf_tuner_get_frequency, | ||
488 | .get_bandwidth = mxl111sf_tuner_get_bandwidth, | ||
489 | .get_if_frequency = mxl111sf_tuner_get_if_frequency, | ||
490 | .release = mxl111sf_tuner_release, | ||
491 | }; | ||
492 | |||
493 | struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, | ||
494 | struct mxl111sf_state *mxl_state, | ||
495 | struct mxl111sf_tuner_config *cfg) | ||
496 | { | ||
497 | struct mxl111sf_tuner_state *state = NULL; | ||
498 | |||
499 | mxl_dbg("()"); | ||
500 | |||
501 | state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL); | ||
502 | if (state == NULL) | ||
503 | return NULL; | ||
504 | |||
505 | state->mxl_state = mxl_state; | ||
506 | state->cfg = cfg; | ||
507 | |||
508 | memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops, | ||
509 | sizeof(struct dvb_tuner_ops)); | ||
510 | |||
511 | fe->tuner_priv = state; | ||
512 | return fe; | ||
513 | } | ||
514 | EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach); | ||
515 | |||
516 | MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver"); | ||
517 | MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>"); | ||
518 | MODULE_LICENSE("GPL"); | ||
519 | MODULE_VERSION("0.1"); | ||
520 | |||
521 | /* | ||
522 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
523 | * --------------------------------------------------------------------------- | ||
524 | * Local variables: | ||
525 | * c-basic-offset: 8 | ||
526 | * End: | ||
527 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h new file mode 100644 index 000000000000..ff333960b184 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * mxl111sf-tuner.h - driver for the MaxLinear MXL111SF CMOS tuner | ||
3 | * | ||
4 | * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> | ||
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 | |||
21 | #ifndef __MXL111SF_TUNER_H__ | ||
22 | #define __MXL111SF_TUNER_H__ | ||
23 | |||
24 | #include "dvb_frontend.h" | ||
25 | |||
26 | #include "mxl111sf.h" | ||
27 | |||
28 | enum mxl_if_freq { | ||
29 | #if 0 | ||
30 | MXL_IF_LO = 0x00, /* other IF < 9MHz */ | ||
31 | #endif | ||
32 | MXL_IF_4_0 = 0x01, /* 4.0 MHz */ | ||
33 | MXL_IF_4_5 = 0x02, /* 4.5 MHz */ | ||
34 | MXL_IF_4_57 = 0x03, /* 4.57 MHz */ | ||
35 | MXL_IF_5_0 = 0x04, /* 5.0 MHz */ | ||
36 | MXL_IF_5_38 = 0x05, /* 5.38 MHz */ | ||
37 | MXL_IF_6_0 = 0x06, /* 6.0 MHz */ | ||
38 | MXL_IF_6_28 = 0x07, /* 6.28 MHz */ | ||
39 | MXL_IF_7_2 = 0x08, /* 7.2 MHz */ | ||
40 | MXL_IF_35_25 = 0x09, /* 35.25 MHz */ | ||
41 | MXL_IF_36 = 0x0a, /* 36 MHz */ | ||
42 | MXL_IF_36_15 = 0x0b, /* 36.15 MHz */ | ||
43 | MXL_IF_44 = 0x0c, /* 44 MHz */ | ||
44 | #if 0 | ||
45 | MXL_IF_HI = 0x0f, /* other IF > 35 MHz and < 45 MHz */ | ||
46 | #endif | ||
47 | }; | ||
48 | |||
49 | struct mxl111sf_tuner_config { | ||
50 | enum mxl_if_freq if_freq; | ||
51 | unsigned int invert_spectrum:1; | ||
52 | |||
53 | int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data); | ||
54 | int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data); | ||
55 | int (*program_regs)(struct mxl111sf_state *state, | ||
56 | struct mxl111sf_reg_ctrl_info *ctrl_reg_info); | ||
57 | int (*top_master_ctrl)(struct mxl111sf_state *state, int onoff); | ||
58 | int (*ant_hunt)(struct dvb_frontend *fe); | ||
59 | }; | ||
60 | |||
61 | /* ------------------------------------------------------------------------ */ | ||
62 | |||
63 | #if defined(CONFIG_DVB_USB_MXL111SF) || \ | ||
64 | (defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE)) | ||
65 | extern | ||
66 | struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, | ||
67 | struct mxl111sf_state *mxl_state, | ||
68 | struct mxl111sf_tuner_config *cfg); | ||
69 | #else | ||
70 | static inline | ||
71 | struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, | ||
72 | struct mxl111sf_state *mxl_state | ||
73 | struct mxl111sf_tuner_config *cfg) | ||
74 | { | ||
75 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
76 | return NULL; | ||
77 | } | ||
78 | #endif | ||
79 | |||
80 | #endif /* __MXL111SF_TUNER_H__ */ | ||
81 | |||
82 | /* | ||
83 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
84 | * --------------------------------------------------------------------------- | ||
85 | * Local variables: | ||
86 | * c-basic-offset: 8 | ||
87 | * End: | ||
88 | */ | ||
89 | |||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c new file mode 100644 index 000000000000..efdcb15358f1 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c | |||
@@ -0,0 +1,1431 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the Free | ||
6 | * Software Foundation, version 2. | ||
7 | * | ||
8 | * see Documentation/dvb/README.dvb-usb for more information | ||
9 | */ | ||
10 | |||
11 | #include <linux/vmalloc.h> | ||
12 | #include <linux/i2c.h> | ||
13 | |||
14 | #include "mxl111sf.h" | ||
15 | #include "mxl111sf-reg.h" | ||
16 | #include "mxl111sf-phy.h" | ||
17 | #include "mxl111sf-i2c.h" | ||
18 | #include "mxl111sf-gpio.h" | ||
19 | |||
20 | #include "mxl111sf-demod.h" | ||
21 | #include "mxl111sf-tuner.h" | ||
22 | |||
23 | #include "lgdt3305.h" | ||
24 | #include "lg2160.h" | ||
25 | |||
26 | int dvb_usb_mxl111sf_debug; | ||
27 | module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644); | ||
28 | MODULE_PARM_DESC(debug, "set debugging level " | ||
29 | "(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able))."); | ||
30 | |||
31 | int dvb_usb_mxl111sf_isoc; | ||
32 | module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644); | ||
33 | MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc)."); | ||
34 | |||
35 | int dvb_usb_mxl111sf_spi; | ||
36 | module_param_named(spi, dvb_usb_mxl111sf_spi, int, 0644); | ||
37 | MODULE_PARM_DESC(spi, "use spi rather than tp for data xfer (0=tp, 1=spi)."); | ||
38 | |||
39 | #define ANT_PATH_AUTO 0 | ||
40 | #define ANT_PATH_EXTERNAL 1 | ||
41 | #define ANT_PATH_INTERNAL 2 | ||
42 | |||
43 | int dvb_usb_mxl111sf_rfswitch = | ||
44 | #if 0 | ||
45 | ANT_PATH_AUTO; | ||
46 | #else | ||
47 | ANT_PATH_EXTERNAL; | ||
48 | #endif | ||
49 | |||
50 | module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644); | ||
51 | MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int)."); | ||
52 | |||
53 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
54 | |||
55 | #define deb_info pr_debug | ||
56 | #define deb_reg pr_debug | ||
57 | #define deb_adv pr_debug | ||
58 | #define err pr_err | ||
59 | #define info pr_info | ||
60 | |||
61 | int mxl111sf_ctrl_msg(struct dvb_usb_device *d, | ||
62 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
63 | { | ||
64 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
65 | int ret; | ||
66 | u8 sndbuf[1+wlen]; | ||
67 | |||
68 | deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); | ||
69 | |||
70 | memset(sndbuf, 0, 1+wlen); | ||
71 | |||
72 | sndbuf[0] = cmd; | ||
73 | memcpy(&sndbuf[1], wbuf, wlen); | ||
74 | |||
75 | ret = (wo) ? dvb_usbv2_generic_write(d, sndbuf, 1+wlen) : | ||
76 | dvb_usbv2_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen); | ||
77 | mxl_fail(ret); | ||
78 | |||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | /* ------------------------------------------------------------------------ */ | ||
83 | |||
84 | #define MXL_CMD_REG_READ 0xaa | ||
85 | #define MXL_CMD_REG_WRITE 0x55 | ||
86 | |||
87 | int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data) | ||
88 | { | ||
89 | u8 buf[2]; | ||
90 | int ret; | ||
91 | |||
92 | ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2); | ||
93 | if (mxl_fail(ret)) { | ||
94 | mxl_debug("error reading reg: 0x%02x", addr); | ||
95 | goto fail; | ||
96 | } | ||
97 | |||
98 | if (buf[0] == addr) | ||
99 | *data = buf[1]; | ||
100 | else { | ||
101 | err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x", | ||
102 | addr, buf[0], buf[1]); | ||
103 | ret = -EINVAL; | ||
104 | } | ||
105 | |||
106 | deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data); | ||
107 | fail: | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data) | ||
112 | { | ||
113 | u8 buf[] = { addr, data }; | ||
114 | int ret; | ||
115 | |||
116 | deb_reg("W: (0x%02x, 0x%02x)\n", addr, data); | ||
117 | |||
118 | ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); | ||
119 | if (mxl_fail(ret)) | ||
120 | err("error writing reg: 0x%02x, val: 0x%02x", addr, data); | ||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | /* ------------------------------------------------------------------------ */ | ||
125 | |||
126 | int mxl111sf_write_reg_mask(struct mxl111sf_state *state, | ||
127 | u8 addr, u8 mask, u8 data) | ||
128 | { | ||
129 | int ret; | ||
130 | u8 val; | ||
131 | |||
132 | if (mask != 0xff) { | ||
133 | ret = mxl111sf_read_reg(state, addr, &val); | ||
134 | #if 1 | ||
135 | /* dont know why this usually errors out on the first try */ | ||
136 | if (mxl_fail(ret)) | ||
137 | err("error writing addr: 0x%02x, mask: 0x%02x, " | ||
138 | "data: 0x%02x, retrying...", addr, mask, data); | ||
139 | |||
140 | ret = mxl111sf_read_reg(state, addr, &val); | ||
141 | #endif | ||
142 | if (mxl_fail(ret)) | ||
143 | goto fail; | ||
144 | } | ||
145 | val &= ~mask; | ||
146 | val |= data; | ||
147 | |||
148 | ret = mxl111sf_write_reg(state, addr, val); | ||
149 | mxl_fail(ret); | ||
150 | fail: | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | /* ------------------------------------------------------------------------ */ | ||
155 | |||
156 | int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state, | ||
157 | struct mxl111sf_reg_ctrl_info *ctrl_reg_info) | ||
158 | { | ||
159 | int i, ret = 0; | ||
160 | |||
161 | for (i = 0; ctrl_reg_info[i].addr | | ||
162 | ctrl_reg_info[i].mask | | ||
163 | ctrl_reg_info[i].data; i++) { | ||
164 | |||
165 | ret = mxl111sf_write_reg_mask(state, | ||
166 | ctrl_reg_info[i].addr, | ||
167 | ctrl_reg_info[i].mask, | ||
168 | ctrl_reg_info[i].data); | ||
169 | if (mxl_fail(ret)) { | ||
170 | err("failed on reg #%d (0x%02x)", i, | ||
171 | ctrl_reg_info[i].addr); | ||
172 | break; | ||
173 | } | ||
174 | } | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | /* ------------------------------------------------------------------------ */ | ||
179 | |||
180 | static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state) | ||
181 | { | ||
182 | int ret; | ||
183 | u8 id, ver; | ||
184 | char *mxl_chip, *mxl_rev; | ||
185 | |||
186 | if ((state->chip_id) && (state->chip_ver)) | ||
187 | return 0; | ||
188 | |||
189 | ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id); | ||
190 | if (mxl_fail(ret)) | ||
191 | goto fail; | ||
192 | state->chip_id = id; | ||
193 | |||
194 | ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver); | ||
195 | if (mxl_fail(ret)) | ||
196 | goto fail; | ||
197 | state->chip_ver = ver; | ||
198 | |||
199 | switch (id) { | ||
200 | case 0x61: | ||
201 | mxl_chip = "MxL101SF"; | ||
202 | break; | ||
203 | case 0x63: | ||
204 | mxl_chip = "MxL111SF"; | ||
205 | break; | ||
206 | default: | ||
207 | mxl_chip = "UNKNOWN MxL1X1"; | ||
208 | break; | ||
209 | } | ||
210 | switch (ver) { | ||
211 | case 0x36: | ||
212 | state->chip_rev = MXL111SF_V6; | ||
213 | mxl_rev = "v6"; | ||
214 | break; | ||
215 | case 0x08: | ||
216 | state->chip_rev = MXL111SF_V8_100; | ||
217 | mxl_rev = "v8_100"; | ||
218 | break; | ||
219 | case 0x18: | ||
220 | state->chip_rev = MXL111SF_V8_200; | ||
221 | mxl_rev = "v8_200"; | ||
222 | break; | ||
223 | default: | ||
224 | state->chip_rev = 0; | ||
225 | mxl_rev = "UNKNOWN REVISION"; | ||
226 | break; | ||
227 | } | ||
228 | info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver); | ||
229 | fail: | ||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | #define get_chip_info(state) \ | ||
234 | ({ \ | ||
235 | int ___ret; \ | ||
236 | ___ret = mxl1x1sf_get_chip_info(state); \ | ||
237 | if (mxl_fail(___ret)) { \ | ||
238 | mxl_debug("failed to get chip info" \ | ||
239 | " on first probe attempt"); \ | ||
240 | ___ret = mxl1x1sf_get_chip_info(state); \ | ||
241 | if (mxl_fail(___ret)) \ | ||
242 | err("failed to get chip info during probe"); \ | ||
243 | else \ | ||
244 | mxl_debug("probe needed a retry " \ | ||
245 | "in order to succeed."); \ | ||
246 | } \ | ||
247 | ___ret; \ | ||
248 | }) | ||
249 | |||
250 | /* ------------------------------------------------------------------------ */ | ||
251 | #if 0 | ||
252 | static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
253 | { | ||
254 | /* power control depends on which adapter is being woken: | ||
255 | * save this for init, instead, via mxl111sf_adap_fe_init */ | ||
256 | return 0; | ||
257 | } | ||
258 | #endif | ||
259 | |||
260 | static int mxl111sf_adap_fe_init(struct dvb_frontend *fe) | ||
261 | { | ||
262 | struct dvb_usb_device *d = fe_to_d(fe); | ||
263 | struct mxl111sf_state *state = fe_to_priv(fe); | ||
264 | struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; | ||
265 | int err; | ||
266 | |||
267 | /* exit if we didnt initialize the driver yet */ | ||
268 | if (!state->chip_id) { | ||
269 | mxl_debug("driver not yet initialized, exit."); | ||
270 | goto fail; | ||
271 | } | ||
272 | |||
273 | deb_info("%s()\n", __func__); | ||
274 | |||
275 | mutex_lock(&state->fe_lock); | ||
276 | |||
277 | state->alt_mode = adap_state->alt_mode; | ||
278 | |||
279 | if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) | ||
280 | err("set interface failed"); | ||
281 | |||
282 | err = mxl1x1sf_soft_reset(state); | ||
283 | mxl_fail(err); | ||
284 | err = mxl111sf_init_tuner_demod(state); | ||
285 | mxl_fail(err); | ||
286 | err = mxl1x1sf_set_device_mode(state, adap_state->device_mode); | ||
287 | |||
288 | mxl_fail(err); | ||
289 | mxl111sf_enable_usb_output(state); | ||
290 | mxl_fail(err); | ||
291 | mxl1x1sf_top_master_ctrl(state, 1); | ||
292 | mxl_fail(err); | ||
293 | |||
294 | if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) && | ||
295 | (state->chip_rev > MXL111SF_V6)) { | ||
296 | mxl111sf_config_pin_mux_modes(state, | ||
297 | PIN_MUX_TS_SPI_IN_MODE_1); | ||
298 | mxl_fail(err); | ||
299 | } | ||
300 | err = mxl111sf_init_port_expander(state); | ||
301 | if (!mxl_fail(err)) { | ||
302 | state->gpio_mode = adap_state->gpio_mode; | ||
303 | err = mxl111sf_gpio_mode_switch(state, state->gpio_mode); | ||
304 | mxl_fail(err); | ||
305 | #if 0 | ||
306 | err = fe->ops.init(fe); | ||
307 | #endif | ||
308 | msleep(100); /* add short delay after enabling | ||
309 | * the demod before touching it */ | ||
310 | } | ||
311 | |||
312 | return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0; | ||
313 | fail: | ||
314 | return -ENODEV; | ||
315 | } | ||
316 | |||
317 | static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe) | ||
318 | { | ||
319 | struct mxl111sf_state *state = fe_to_priv(fe); | ||
320 | struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; | ||
321 | int err; | ||
322 | |||
323 | /* exit if we didnt initialize the driver yet */ | ||
324 | if (!state->chip_id) { | ||
325 | mxl_debug("driver not yet initialized, exit."); | ||
326 | goto fail; | ||
327 | } | ||
328 | |||
329 | deb_info("%s()\n", __func__); | ||
330 | |||
331 | err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0; | ||
332 | |||
333 | mutex_unlock(&state->fe_lock); | ||
334 | |||
335 | return err; | ||
336 | fail: | ||
337 | return -ENODEV; | ||
338 | } | ||
339 | |||
340 | |||
341 | static int mxl111sf_ep6_streaming_ctrl(struct dvb_frontend *fe, int onoff) | ||
342 | { | ||
343 | struct mxl111sf_state *state = fe_to_priv(fe); | ||
344 | struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; | ||
345 | int ret = 0; | ||
346 | |||
347 | deb_info("%s(%d)\n", __func__, onoff); | ||
348 | |||
349 | if (onoff) { | ||
350 | ret = mxl111sf_enable_usb_output(state); | ||
351 | mxl_fail(ret); | ||
352 | ret = mxl111sf_config_mpeg_in(state, 1, 1, | ||
353 | adap_state->ep6_clockphase, | ||
354 | 0, 0); | ||
355 | mxl_fail(ret); | ||
356 | #if 0 | ||
357 | } else { | ||
358 | ret = mxl111sf_disable_656_port(state); | ||
359 | mxl_fail(ret); | ||
360 | #endif | ||
361 | } | ||
362 | |||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | static int mxl111sf_ep5_streaming_ctrl(struct dvb_frontend *fe, int onoff) | ||
367 | { | ||
368 | struct mxl111sf_state *state = fe_to_priv(fe); | ||
369 | int ret = 0; | ||
370 | |||
371 | deb_info("%s(%d)\n", __func__, onoff); | ||
372 | |||
373 | if (onoff) { | ||
374 | ret = mxl111sf_enable_usb_output(state); | ||
375 | mxl_fail(ret); | ||
376 | |||
377 | ret = mxl111sf_init_i2s_port(state, 200); | ||
378 | mxl_fail(ret); | ||
379 | ret = mxl111sf_config_i2s(state, 0, 15); | ||
380 | mxl_fail(ret); | ||
381 | } else { | ||
382 | ret = mxl111sf_disable_i2s_port(state); | ||
383 | mxl_fail(ret); | ||
384 | } | ||
385 | if (state->chip_rev > MXL111SF_V6) | ||
386 | ret = mxl111sf_config_spi(state, onoff); | ||
387 | mxl_fail(ret); | ||
388 | |||
389 | return ret; | ||
390 | } | ||
391 | |||
392 | static int mxl111sf_ep4_streaming_ctrl(struct dvb_frontend *fe, int onoff) | ||
393 | { | ||
394 | struct mxl111sf_state *state = fe_to_priv(fe); | ||
395 | int ret = 0; | ||
396 | |||
397 | deb_info("%s(%d)\n", __func__, onoff); | ||
398 | |||
399 | if (onoff) { | ||
400 | ret = mxl111sf_enable_usb_output(state); | ||
401 | mxl_fail(ret); | ||
402 | } | ||
403 | |||
404 | return ret; | ||
405 | } | ||
406 | |||
407 | /* ------------------------------------------------------------------------ */ | ||
408 | |||
409 | static struct lgdt3305_config hauppauge_lgdt3305_config = { | ||
410 | .i2c_addr = 0xb2 >> 1, | ||
411 | .mpeg_mode = LGDT3305_MPEG_SERIAL, | ||
412 | .tpclk_edge = LGDT3305_TPCLK_RISING_EDGE, | ||
413 | .tpvalid_polarity = LGDT3305_TP_VALID_HIGH, | ||
414 | .deny_i2c_rptr = 1, | ||
415 | .spectral_inversion = 0, | ||
416 | .qam_if_khz = 6000, | ||
417 | .vsb_if_khz = 6000, | ||
418 | }; | ||
419 | |||
420 | static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id) | ||
421 | { | ||
422 | struct dvb_usb_device *d = adap_to_d(adap); | ||
423 | struct mxl111sf_state *state = d_to_priv(d); | ||
424 | struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; | ||
425 | int ret; | ||
426 | |||
427 | deb_adv("%s()\n", __func__); | ||
428 | |||
429 | /* save a pointer to the dvb_usb_device in device state */ | ||
430 | state->d = d; | ||
431 | adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; | ||
432 | state->alt_mode = adap_state->alt_mode; | ||
433 | |||
434 | if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) | ||
435 | err("set interface failed"); | ||
436 | |||
437 | state->gpio_mode = MXL111SF_GPIO_MOD_ATSC; | ||
438 | adap_state->gpio_mode = state->gpio_mode; | ||
439 | adap_state->device_mode = MXL_TUNER_MODE; | ||
440 | adap_state->ep6_clockphase = 1; | ||
441 | |||
442 | ret = mxl1x1sf_soft_reset(state); | ||
443 | if (mxl_fail(ret)) | ||
444 | goto fail; | ||
445 | ret = mxl111sf_init_tuner_demod(state); | ||
446 | if (mxl_fail(ret)) | ||
447 | goto fail; | ||
448 | |||
449 | ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); | ||
450 | if (mxl_fail(ret)) | ||
451 | goto fail; | ||
452 | |||
453 | ret = mxl111sf_enable_usb_output(state); | ||
454 | if (mxl_fail(ret)) | ||
455 | goto fail; | ||
456 | ret = mxl1x1sf_top_master_ctrl(state, 1); | ||
457 | if (mxl_fail(ret)) | ||
458 | goto fail; | ||
459 | |||
460 | ret = mxl111sf_init_port_expander(state); | ||
461 | if (mxl_fail(ret)) | ||
462 | goto fail; | ||
463 | ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); | ||
464 | if (mxl_fail(ret)) | ||
465 | goto fail; | ||
466 | |||
467 | adap->fe[fe_id] = dvb_attach(lgdt3305_attach, | ||
468 | &hauppauge_lgdt3305_config, | ||
469 | &d->i2c_adap); | ||
470 | if (adap->fe[fe_id]) { | ||
471 | state->num_frontends++; | ||
472 | adap_state->fe_init = adap->fe[fe_id]->ops.init; | ||
473 | adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init; | ||
474 | adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep; | ||
475 | adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep; | ||
476 | return 0; | ||
477 | } | ||
478 | ret = -EIO; | ||
479 | fail: | ||
480 | return ret; | ||
481 | } | ||
482 | |||
483 | static struct lg2160_config hauppauge_lg2160_config = { | ||
484 | .lg_chip = LG2160, | ||
485 | .i2c_addr = 0x1c >> 1, | ||
486 | .deny_i2c_rptr = 1, | ||
487 | .spectral_inversion = 0, | ||
488 | .if_khz = 6000, | ||
489 | }; | ||
490 | |||
491 | static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id) | ||
492 | { | ||
493 | struct dvb_usb_device *d = adap_to_d(adap); | ||
494 | struct mxl111sf_state *state = d_to_priv(d); | ||
495 | struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; | ||
496 | int ret; | ||
497 | |||
498 | deb_adv("%s()\n", __func__); | ||
499 | |||
500 | /* save a pointer to the dvb_usb_device in device state */ | ||
501 | state->d = d; | ||
502 | adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; | ||
503 | state->alt_mode = adap_state->alt_mode; | ||
504 | |||
505 | if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) | ||
506 | err("set interface failed"); | ||
507 | |||
508 | state->gpio_mode = MXL111SF_GPIO_MOD_MH; | ||
509 | adap_state->gpio_mode = state->gpio_mode; | ||
510 | adap_state->device_mode = MXL_TUNER_MODE; | ||
511 | adap_state->ep6_clockphase = 1; | ||
512 | |||
513 | ret = mxl1x1sf_soft_reset(state); | ||
514 | if (mxl_fail(ret)) | ||
515 | goto fail; | ||
516 | ret = mxl111sf_init_tuner_demod(state); | ||
517 | if (mxl_fail(ret)) | ||
518 | goto fail; | ||
519 | |||
520 | ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); | ||
521 | if (mxl_fail(ret)) | ||
522 | goto fail; | ||
523 | |||
524 | ret = mxl111sf_enable_usb_output(state); | ||
525 | if (mxl_fail(ret)) | ||
526 | goto fail; | ||
527 | ret = mxl1x1sf_top_master_ctrl(state, 1); | ||
528 | if (mxl_fail(ret)) | ||
529 | goto fail; | ||
530 | |||
531 | ret = mxl111sf_init_port_expander(state); | ||
532 | if (mxl_fail(ret)) | ||
533 | goto fail; | ||
534 | ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); | ||
535 | if (mxl_fail(ret)) | ||
536 | goto fail; | ||
537 | |||
538 | ret = get_chip_info(state); | ||
539 | if (mxl_fail(ret)) | ||
540 | goto fail; | ||
541 | |||
542 | adap->fe[fe_id] = dvb_attach(lg2160_attach, | ||
543 | &hauppauge_lg2160_config, | ||
544 | &d->i2c_adap); | ||
545 | if (adap->fe[fe_id]) { | ||
546 | state->num_frontends++; | ||
547 | adap_state->fe_init = adap->fe[fe_id]->ops.init; | ||
548 | adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init; | ||
549 | adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep; | ||
550 | adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep; | ||
551 | return 0; | ||
552 | } | ||
553 | ret = -EIO; | ||
554 | fail: | ||
555 | return ret; | ||
556 | } | ||
557 | |||
558 | static struct lg2160_config hauppauge_lg2161_1019_config = { | ||
559 | .lg_chip = LG2161_1019, | ||
560 | .i2c_addr = 0x1c >> 1, | ||
561 | .deny_i2c_rptr = 1, | ||
562 | .spectral_inversion = 0, | ||
563 | .if_khz = 6000, | ||
564 | .output_if = 2, /* LG2161_OIF_SPI_MAS */ | ||
565 | }; | ||
566 | |||
567 | static struct lg2160_config hauppauge_lg2161_1040_config = { | ||
568 | .lg_chip = LG2161_1040, | ||
569 | .i2c_addr = 0x1c >> 1, | ||
570 | .deny_i2c_rptr = 1, | ||
571 | .spectral_inversion = 0, | ||
572 | .if_khz = 6000, | ||
573 | .output_if = 4, /* LG2161_OIF_SPI_MAS */ | ||
574 | }; | ||
575 | |||
576 | static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id) | ||
577 | { | ||
578 | struct dvb_usb_device *d = adap_to_d(adap); | ||
579 | struct mxl111sf_state *state = d_to_priv(d); | ||
580 | struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; | ||
581 | int ret; | ||
582 | |||
583 | deb_adv("%s()\n", __func__); | ||
584 | |||
585 | /* save a pointer to the dvb_usb_device in device state */ | ||
586 | state->d = d; | ||
587 | adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; | ||
588 | state->alt_mode = adap_state->alt_mode; | ||
589 | |||
590 | if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) | ||
591 | err("set interface failed"); | ||
592 | |||
593 | state->gpio_mode = MXL111SF_GPIO_MOD_MH; | ||
594 | adap_state->gpio_mode = state->gpio_mode; | ||
595 | adap_state->device_mode = MXL_TUNER_MODE; | ||
596 | adap_state->ep6_clockphase = 1; | ||
597 | |||
598 | ret = mxl1x1sf_soft_reset(state); | ||
599 | if (mxl_fail(ret)) | ||
600 | goto fail; | ||
601 | ret = mxl111sf_init_tuner_demod(state); | ||
602 | if (mxl_fail(ret)) | ||
603 | goto fail; | ||
604 | |||
605 | ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); | ||
606 | if (mxl_fail(ret)) | ||
607 | goto fail; | ||
608 | |||
609 | ret = mxl111sf_enable_usb_output(state); | ||
610 | if (mxl_fail(ret)) | ||
611 | goto fail; | ||
612 | ret = mxl1x1sf_top_master_ctrl(state, 1); | ||
613 | if (mxl_fail(ret)) | ||
614 | goto fail; | ||
615 | |||
616 | ret = mxl111sf_init_port_expander(state); | ||
617 | if (mxl_fail(ret)) | ||
618 | goto fail; | ||
619 | ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); | ||
620 | if (mxl_fail(ret)) | ||
621 | goto fail; | ||
622 | |||
623 | ret = get_chip_info(state); | ||
624 | if (mxl_fail(ret)) | ||
625 | goto fail; | ||
626 | |||
627 | adap->fe[fe_id] = dvb_attach(lg2160_attach, | ||
628 | (MXL111SF_V8_200 == state->chip_rev) ? | ||
629 | &hauppauge_lg2161_1040_config : | ||
630 | &hauppauge_lg2161_1019_config, | ||
631 | &d->i2c_adap); | ||
632 | if (adap->fe[fe_id]) { | ||
633 | state->num_frontends++; | ||
634 | adap_state->fe_init = adap->fe[fe_id]->ops.init; | ||
635 | adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init; | ||
636 | adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep; | ||
637 | adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep; | ||
638 | return 0; | ||
639 | } | ||
640 | ret = -EIO; | ||
641 | fail: | ||
642 | return ret; | ||
643 | } | ||
644 | |||
645 | static struct lg2160_config hauppauge_lg2161_1019_ep6_config = { | ||
646 | .lg_chip = LG2161_1019, | ||
647 | .i2c_addr = 0x1c >> 1, | ||
648 | .deny_i2c_rptr = 1, | ||
649 | .spectral_inversion = 0, | ||
650 | .if_khz = 6000, | ||
651 | .output_if = 1, /* LG2161_OIF_SERIAL_TS */ | ||
652 | }; | ||
653 | |||
654 | static struct lg2160_config hauppauge_lg2161_1040_ep6_config = { | ||
655 | .lg_chip = LG2161_1040, | ||
656 | .i2c_addr = 0x1c >> 1, | ||
657 | .deny_i2c_rptr = 1, | ||
658 | .spectral_inversion = 0, | ||
659 | .if_khz = 6000, | ||
660 | .output_if = 7, /* LG2161_OIF_SERIAL_TS */ | ||
661 | }; | ||
662 | |||
663 | static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id) | ||
664 | { | ||
665 | struct dvb_usb_device *d = adap_to_d(adap); | ||
666 | struct mxl111sf_state *state = d_to_priv(d); | ||
667 | struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; | ||
668 | int ret; | ||
669 | |||
670 | deb_adv("%s()\n", __func__); | ||
671 | |||
672 | /* save a pointer to the dvb_usb_device in device state */ | ||
673 | state->d = d; | ||
674 | adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; | ||
675 | state->alt_mode = adap_state->alt_mode; | ||
676 | |||
677 | if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) | ||
678 | err("set interface failed"); | ||
679 | |||
680 | state->gpio_mode = MXL111SF_GPIO_MOD_MH; | ||
681 | adap_state->gpio_mode = state->gpio_mode; | ||
682 | adap_state->device_mode = MXL_TUNER_MODE; | ||
683 | adap_state->ep6_clockphase = 0; | ||
684 | |||
685 | ret = mxl1x1sf_soft_reset(state); | ||
686 | if (mxl_fail(ret)) | ||
687 | goto fail; | ||
688 | ret = mxl111sf_init_tuner_demod(state); | ||
689 | if (mxl_fail(ret)) | ||
690 | goto fail; | ||
691 | |||
692 | ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); | ||
693 | if (mxl_fail(ret)) | ||
694 | goto fail; | ||
695 | |||
696 | ret = mxl111sf_enable_usb_output(state); | ||
697 | if (mxl_fail(ret)) | ||
698 | goto fail; | ||
699 | ret = mxl1x1sf_top_master_ctrl(state, 1); | ||
700 | if (mxl_fail(ret)) | ||
701 | goto fail; | ||
702 | |||
703 | ret = mxl111sf_init_port_expander(state); | ||
704 | if (mxl_fail(ret)) | ||
705 | goto fail; | ||
706 | ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode); | ||
707 | if (mxl_fail(ret)) | ||
708 | goto fail; | ||
709 | |||
710 | ret = get_chip_info(state); | ||
711 | if (mxl_fail(ret)) | ||
712 | goto fail; | ||
713 | |||
714 | adap->fe[fe_id] = dvb_attach(lg2160_attach, | ||
715 | (MXL111SF_V8_200 == state->chip_rev) ? | ||
716 | &hauppauge_lg2161_1040_ep6_config : | ||
717 | &hauppauge_lg2161_1019_ep6_config, | ||
718 | &d->i2c_adap); | ||
719 | if (adap->fe[fe_id]) { | ||
720 | state->num_frontends++; | ||
721 | adap_state->fe_init = adap->fe[fe_id]->ops.init; | ||
722 | adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init; | ||
723 | adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep; | ||
724 | adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep; | ||
725 | return 0; | ||
726 | } | ||
727 | ret = -EIO; | ||
728 | fail: | ||
729 | return ret; | ||
730 | } | ||
731 | |||
732 | static struct mxl111sf_demod_config mxl_demod_config = { | ||
733 | .read_reg = mxl111sf_read_reg, | ||
734 | .write_reg = mxl111sf_write_reg, | ||
735 | .program_regs = mxl111sf_ctrl_program_regs, | ||
736 | }; | ||
737 | |||
738 | static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap, u8 fe_id) | ||
739 | { | ||
740 | struct dvb_usb_device *d = adap_to_d(adap); | ||
741 | struct mxl111sf_state *state = d_to_priv(d); | ||
742 | struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; | ||
743 | int ret; | ||
744 | |||
745 | deb_adv("%s()\n", __func__); | ||
746 | |||
747 | /* save a pointer to the dvb_usb_device in device state */ | ||
748 | state->d = d; | ||
749 | adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2; | ||
750 | state->alt_mode = adap_state->alt_mode; | ||
751 | |||
752 | if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) | ||
753 | err("set interface failed"); | ||
754 | |||
755 | state->gpio_mode = MXL111SF_GPIO_MOD_DVBT; | ||
756 | adap_state->gpio_mode = state->gpio_mode; | ||
757 | adap_state->device_mode = MXL_SOC_MODE; | ||
758 | adap_state->ep6_clockphase = 1; | ||
759 | |||
760 | ret = mxl1x1sf_soft_reset(state); | ||
761 | if (mxl_fail(ret)) | ||
762 | goto fail; | ||
763 | ret = mxl111sf_init_tuner_demod(state); | ||
764 | if (mxl_fail(ret)) | ||
765 | goto fail; | ||
766 | |||
767 | ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode); | ||
768 | if (mxl_fail(ret)) | ||
769 | goto fail; | ||
770 | |||
771 | ret = mxl111sf_enable_usb_output(state); | ||
772 | if (mxl_fail(ret)) | ||
773 | goto fail; | ||
774 | ret = mxl1x1sf_top_master_ctrl(state, 1); | ||
775 | if (mxl_fail(ret)) | ||
776 | goto fail; | ||
777 | |||
778 | /* dont care if this fails */ | ||
779 | mxl111sf_init_port_expander(state); | ||
780 | |||
781 | adap->fe[fe_id] = dvb_attach(mxl111sf_demod_attach, state, | ||
782 | &mxl_demod_config); | ||
783 | if (adap->fe[fe_id]) { | ||
784 | state->num_frontends++; | ||
785 | adap_state->fe_init = adap->fe[fe_id]->ops.init; | ||
786 | adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init; | ||
787 | adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep; | ||
788 | adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep; | ||
789 | return 0; | ||
790 | } | ||
791 | ret = -EIO; | ||
792 | fail: | ||
793 | return ret; | ||
794 | } | ||
795 | |||
796 | static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state, | ||
797 | int antpath) | ||
798 | { | ||
799 | return mxl111sf_idac_config(state, 1, 1, | ||
800 | (antpath == ANT_PATH_INTERNAL) ? | ||
801 | 0x3f : 0x00, 0); | ||
802 | } | ||
803 | |||
804 | #define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \ | ||
805 | err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \ | ||
806 | __func__, __LINE__, \ | ||
807 | (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \ | ||
808 | pwr0, pwr1, pwr2, pwr3) | ||
809 | |||
810 | #define ANT_HUNT_SLEEP 90 | ||
811 | #define ANT_EXT_TWEAK 0 | ||
812 | |||
813 | static int mxl111sf_ant_hunt(struct dvb_frontend *fe) | ||
814 | { | ||
815 | struct mxl111sf_state *state = fe_to_priv(fe); | ||
816 | int antctrl = dvb_usb_mxl111sf_rfswitch; | ||
817 | |||
818 | u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2; | ||
819 | |||
820 | /* FIXME: must force EXTERNAL for QAM - done elsewhere */ | ||
821 | mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ? | ||
822 | ANT_PATH_EXTERNAL : antctrl); | ||
823 | |||
824 | if (antctrl == ANT_PATH_AUTO) { | ||
825 | #if 0 | ||
826 | msleep(ANT_HUNT_SLEEP); | ||
827 | #endif | ||
828 | fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA); | ||
829 | |||
830 | mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL); | ||
831 | msleep(ANT_HUNT_SLEEP); | ||
832 | fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0); | ||
833 | |||
834 | mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL); | ||
835 | msleep(ANT_HUNT_SLEEP); | ||
836 | fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1); | ||
837 | |||
838 | mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL); | ||
839 | msleep(ANT_HUNT_SLEEP); | ||
840 | fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2); | ||
841 | |||
842 | if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) { | ||
843 | /* return with EXTERNAL enabled */ | ||
844 | mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL); | ||
845 | DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA, | ||
846 | rxPwr0, rxPwr1, rxPwr2); | ||
847 | } else { | ||
848 | /* return with INTERNAL enabled */ | ||
849 | DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA, | ||
850 | rxPwr0, rxPwr1, rxPwr2); | ||
851 | } | ||
852 | } | ||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | static struct mxl111sf_tuner_config mxl_tuner_config = { | ||
857 | .if_freq = MXL_IF_6_0, /* applies to external IF output, only */ | ||
858 | .invert_spectrum = 0, | ||
859 | .read_reg = mxl111sf_read_reg, | ||
860 | .write_reg = mxl111sf_write_reg, | ||
861 | .program_regs = mxl111sf_ctrl_program_regs, | ||
862 | .top_master_ctrl = mxl1x1sf_top_master_ctrl, | ||
863 | .ant_hunt = mxl111sf_ant_hunt, | ||
864 | }; | ||
865 | |||
866 | static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) | ||
867 | { | ||
868 | struct mxl111sf_state *state = adap_to_priv(adap); | ||
869 | int i; | ||
870 | |||
871 | deb_adv("%s()\n", __func__); | ||
872 | |||
873 | for (i = 0; i < state->num_frontends; i++) { | ||
874 | if (dvb_attach(mxl111sf_tuner_attach, adap->fe[i], state, | ||
875 | &mxl_tuner_config) == NULL) | ||
876 | return -EIO; | ||
877 | adap->fe[i]->ops.read_signal_strength = adap->fe[i]->ops.tuner_ops.get_rf_strength; | ||
878 | } | ||
879 | |||
880 | return 0; | ||
881 | } | ||
882 | |||
883 | static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter) | ||
884 | { | ||
885 | return I2C_FUNC_I2C; | ||
886 | } | ||
887 | |||
888 | struct i2c_algorithm mxl111sf_i2c_algo = { | ||
889 | .master_xfer = mxl111sf_i2c_xfer, | ||
890 | .functionality = mxl111sf_i2c_func, | ||
891 | #ifdef NEED_ALGO_CONTROL | ||
892 | .algo_control = dummy_algo_control, | ||
893 | #endif | ||
894 | }; | ||
895 | |||
896 | static int mxl111sf_init(struct dvb_usb_device *d) | ||
897 | { | ||
898 | struct mxl111sf_state *state = d_to_priv(d); | ||
899 | int ret; | ||
900 | static u8 eeprom[256]; | ||
901 | struct i2c_client c; | ||
902 | |||
903 | ret = get_chip_info(state); | ||
904 | if (mxl_fail(ret)) | ||
905 | err("failed to get chip info during probe"); | ||
906 | |||
907 | mutex_init(&state->fe_lock); | ||
908 | |||
909 | if (state->chip_rev > MXL111SF_V6) | ||
910 | mxl111sf_config_pin_mux_modes(state, PIN_MUX_TS_SPI_IN_MODE_1); | ||
911 | |||
912 | c.adapter = &d->i2c_adap; | ||
913 | c.addr = 0xa0 >> 1; | ||
914 | |||
915 | ret = tveeprom_read(&c, eeprom, sizeof(eeprom)); | ||
916 | if (mxl_fail(ret)) | ||
917 | return 0; | ||
918 | tveeprom_hauppauge_analog(&c, &state->tv, (0x84 == eeprom[0xa0]) ? | ||
919 | eeprom + 0xa0 : eeprom + 0x80); | ||
920 | #if 0 | ||
921 | switch (state->tv.model) { | ||
922 | case 117001: | ||
923 | case 126001: | ||
924 | case 138001: | ||
925 | break; | ||
926 | default: | ||
927 | printk(KERN_WARNING "%s: warning: " | ||
928 | "unknown hauppauge model #%d\n", | ||
929 | __func__, state->tv.model); | ||
930 | } | ||
931 | #endif | ||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | static int mxl111sf_frontend_attach_dvbt(struct dvb_usb_adapter *adap) | ||
936 | { | ||
937 | return mxl111sf_attach_demod(adap, 0); | ||
938 | } | ||
939 | |||
940 | static int mxl111sf_frontend_attach_atsc(struct dvb_usb_adapter *adap) | ||
941 | { | ||
942 | return mxl111sf_lgdt3305_frontend_attach(adap, 0); | ||
943 | } | ||
944 | |||
945 | static int mxl111sf_frontend_attach_mh(struct dvb_usb_adapter *adap) | ||
946 | { | ||
947 | return mxl111sf_lg2160_frontend_attach(adap, 0); | ||
948 | } | ||
949 | |||
950 | static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap) | ||
951 | { | ||
952 | int ret; | ||
953 | deb_info("%s\n", __func__); | ||
954 | |||
955 | ret = mxl111sf_lgdt3305_frontend_attach(adap, 0); | ||
956 | if (ret < 0) | ||
957 | return ret; | ||
958 | |||
959 | ret = mxl111sf_attach_demod(adap, 1); | ||
960 | if (ret < 0) | ||
961 | return ret; | ||
962 | |||
963 | ret = mxl111sf_lg2160_frontend_attach(adap, 2); | ||
964 | if (ret < 0) | ||
965 | return ret; | ||
966 | |||
967 | return ret; | ||
968 | } | ||
969 | |||
970 | static int mxl111sf_frontend_attach_mercury(struct dvb_usb_adapter *adap) | ||
971 | { | ||
972 | int ret; | ||
973 | deb_info("%s\n", __func__); | ||
974 | |||
975 | ret = mxl111sf_lgdt3305_frontend_attach(adap, 0); | ||
976 | if (ret < 0) | ||
977 | return ret; | ||
978 | |||
979 | ret = mxl111sf_attach_demod(adap, 1); | ||
980 | if (ret < 0) | ||
981 | return ret; | ||
982 | |||
983 | ret = mxl111sf_lg2161_ep6_frontend_attach(adap, 2); | ||
984 | if (ret < 0) | ||
985 | return ret; | ||
986 | |||
987 | return ret; | ||
988 | } | ||
989 | |||
990 | static int mxl111sf_frontend_attach_mercury_mh(struct dvb_usb_adapter *adap) | ||
991 | { | ||
992 | int ret; | ||
993 | deb_info("%s\n", __func__); | ||
994 | |||
995 | ret = mxl111sf_attach_demod(adap, 0); | ||
996 | if (ret < 0) | ||
997 | return ret; | ||
998 | |||
999 | if (dvb_usb_mxl111sf_spi) | ||
1000 | ret = mxl111sf_lg2161_frontend_attach(adap, 1); | ||
1001 | else | ||
1002 | ret = mxl111sf_lg2161_ep6_frontend_attach(adap, 1); | ||
1003 | |||
1004 | return ret; | ||
1005 | } | ||
1006 | |||
1007 | static void mxl111sf_stream_config_bulk(struct usb_data_stream_properties *stream, u8 endpoint) | ||
1008 | { | ||
1009 | deb_info("%s: endpoint=%d size=8192\n", __func__, endpoint); | ||
1010 | stream->type = USB_BULK; | ||
1011 | stream->count = 5; | ||
1012 | stream->endpoint = endpoint; | ||
1013 | stream->u.bulk.buffersize = 8192; | ||
1014 | } | ||
1015 | |||
1016 | static void mxl111sf_stream_config_isoc(struct usb_data_stream_properties *stream, | ||
1017 | u8 endpoint, int framesperurb, int framesize) | ||
1018 | { | ||
1019 | deb_info("%s: endpoint=%d size=%d\n", __func__, endpoint, | ||
1020 | framesperurb * framesize); | ||
1021 | stream->type = USB_ISOC; | ||
1022 | stream->count = 5; | ||
1023 | stream->endpoint = endpoint; | ||
1024 | stream->u.isoc.framesperurb = framesperurb; | ||
1025 | stream->u.isoc.framesize = framesize; | ||
1026 | stream->u.isoc.interval = 1; | ||
1027 | } | ||
1028 | |||
1029 | /* DVB USB Driver stuff */ | ||
1030 | |||
1031 | /* dvbt mxl111sf | ||
1032 | * bulk EP4/BULK/5/8192 | ||
1033 | * isoc EP4/ISOC/5/96/564 | ||
1034 | */ | ||
1035 | static int mxl111sf_get_stream_config_dvbt(struct dvb_frontend *fe, | ||
1036 | u8 *ts_type, struct usb_data_stream_properties *stream) | ||
1037 | { | ||
1038 | deb_info("%s: fe=%d\n", __func__, fe->id); | ||
1039 | |||
1040 | *ts_type = DVB_USB_FE_TS_TYPE_188; | ||
1041 | if (dvb_usb_mxl111sf_isoc) | ||
1042 | mxl111sf_stream_config_isoc(stream, 4, 96, 564); | ||
1043 | else | ||
1044 | mxl111sf_stream_config_bulk(stream, 4); | ||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | static struct dvb_usb_device_properties mxl111sf_props_dvbt = { | ||
1049 | .driver_name = KBUILD_MODNAME, | ||
1050 | .owner = THIS_MODULE, | ||
1051 | .adapter_nr = adapter_nr, | ||
1052 | .size_of_priv = sizeof(struct mxl111sf_state), | ||
1053 | |||
1054 | .generic_bulk_ctrl_endpoint = 0x02, | ||
1055 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
1056 | |||
1057 | .i2c_algo = &mxl111sf_i2c_algo, | ||
1058 | .frontend_attach = mxl111sf_frontend_attach_dvbt, | ||
1059 | .tuner_attach = mxl111sf_attach_tuner, | ||
1060 | .init = mxl111sf_init, | ||
1061 | .streaming_ctrl = mxl111sf_ep4_streaming_ctrl, | ||
1062 | .get_stream_config = mxl111sf_get_stream_config_dvbt, | ||
1063 | |||
1064 | .num_adapters = 1, | ||
1065 | .adapter = { | ||
1066 | { | ||
1067 | .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), | ||
1068 | } | ||
1069 | } | ||
1070 | }; | ||
1071 | |||
1072 | /* atsc lgdt3305 | ||
1073 | * bulk EP6/BULK/5/8192 | ||
1074 | * isoc EP6/ISOC/5/24/3072 | ||
1075 | */ | ||
1076 | static int mxl111sf_get_stream_config_atsc(struct dvb_frontend *fe, | ||
1077 | u8 *ts_type, struct usb_data_stream_properties *stream) | ||
1078 | { | ||
1079 | deb_info("%s: fe=%d\n", __func__, fe->id); | ||
1080 | |||
1081 | *ts_type = DVB_USB_FE_TS_TYPE_188; | ||
1082 | if (dvb_usb_mxl111sf_isoc) | ||
1083 | mxl111sf_stream_config_isoc(stream, 6, 24, 3072); | ||
1084 | else | ||
1085 | mxl111sf_stream_config_bulk(stream, 6); | ||
1086 | return 0; | ||
1087 | } | ||
1088 | |||
1089 | static struct dvb_usb_device_properties mxl111sf_props_atsc = { | ||
1090 | .driver_name = KBUILD_MODNAME, | ||
1091 | .owner = THIS_MODULE, | ||
1092 | .adapter_nr = adapter_nr, | ||
1093 | .size_of_priv = sizeof(struct mxl111sf_state), | ||
1094 | |||
1095 | .generic_bulk_ctrl_endpoint = 0x02, | ||
1096 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
1097 | |||
1098 | .i2c_algo = &mxl111sf_i2c_algo, | ||
1099 | .frontend_attach = mxl111sf_frontend_attach_atsc, | ||
1100 | .tuner_attach = mxl111sf_attach_tuner, | ||
1101 | .init = mxl111sf_init, | ||
1102 | .streaming_ctrl = mxl111sf_ep6_streaming_ctrl, | ||
1103 | .get_stream_config = mxl111sf_get_stream_config_atsc, | ||
1104 | |||
1105 | .num_adapters = 1, | ||
1106 | .adapter = { | ||
1107 | { | ||
1108 | .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), | ||
1109 | } | ||
1110 | } | ||
1111 | }; | ||
1112 | |||
1113 | /* mh lg2160 | ||
1114 | * bulk EP5/BULK/5/8192/RAW | ||
1115 | * isoc EP5/ISOC/5/96/200/RAW | ||
1116 | */ | ||
1117 | static int mxl111sf_get_stream_config_mh(struct dvb_frontend *fe, | ||
1118 | u8 *ts_type, struct usb_data_stream_properties *stream) | ||
1119 | { | ||
1120 | deb_info("%s: fe=%d\n", __func__, fe->id); | ||
1121 | |||
1122 | *ts_type = DVB_USB_FE_TS_TYPE_RAW; | ||
1123 | if (dvb_usb_mxl111sf_isoc) | ||
1124 | mxl111sf_stream_config_isoc(stream, 5, 96, 200); | ||
1125 | else | ||
1126 | mxl111sf_stream_config_bulk(stream, 5); | ||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1130 | static struct dvb_usb_device_properties mxl111sf_props_mh = { | ||
1131 | .driver_name = KBUILD_MODNAME, | ||
1132 | .owner = THIS_MODULE, | ||
1133 | .adapter_nr = adapter_nr, | ||
1134 | .size_of_priv = sizeof(struct mxl111sf_state), | ||
1135 | |||
1136 | .generic_bulk_ctrl_endpoint = 0x02, | ||
1137 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
1138 | |||
1139 | .i2c_algo = &mxl111sf_i2c_algo, | ||
1140 | .frontend_attach = mxl111sf_frontend_attach_mh, | ||
1141 | .tuner_attach = mxl111sf_attach_tuner, | ||
1142 | .init = mxl111sf_init, | ||
1143 | .streaming_ctrl = mxl111sf_ep5_streaming_ctrl, | ||
1144 | .get_stream_config = mxl111sf_get_stream_config_mh, | ||
1145 | |||
1146 | .num_adapters = 1, | ||
1147 | .adapter = { | ||
1148 | { | ||
1149 | .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), | ||
1150 | } | ||
1151 | } | ||
1152 | }; | ||
1153 | |||
1154 | /* atsc mh lgdt3305 mxl111sf lg2160 | ||
1155 | * bulk EP6/BULK/5/8192 EP4/BULK/5/8192 EP5/BULK/5/8192/RAW | ||
1156 | * isoc EP6/ISOC/5/24/3072 EP4/ISOC/5/96/564 EP5/ISOC/5/96/200/RAW | ||
1157 | */ | ||
1158 | static int mxl111sf_get_stream_config_atsc_mh(struct dvb_frontend *fe, | ||
1159 | u8 *ts_type, struct usb_data_stream_properties *stream) | ||
1160 | { | ||
1161 | deb_info("%s: fe=%d\n", __func__, fe->id); | ||
1162 | |||
1163 | if (fe->id == 0) { | ||
1164 | *ts_type = DVB_USB_FE_TS_TYPE_188; | ||
1165 | if (dvb_usb_mxl111sf_isoc) | ||
1166 | mxl111sf_stream_config_isoc(stream, 6, 24, 3072); | ||
1167 | else | ||
1168 | mxl111sf_stream_config_bulk(stream, 6); | ||
1169 | } else if (fe->id == 1) { | ||
1170 | *ts_type = DVB_USB_FE_TS_TYPE_188; | ||
1171 | if (dvb_usb_mxl111sf_isoc) | ||
1172 | mxl111sf_stream_config_isoc(stream, 4, 96, 564); | ||
1173 | else | ||
1174 | mxl111sf_stream_config_bulk(stream, 4); | ||
1175 | } else if (fe->id == 2) { | ||
1176 | *ts_type = DVB_USB_FE_TS_TYPE_RAW; | ||
1177 | if (dvb_usb_mxl111sf_isoc) | ||
1178 | mxl111sf_stream_config_isoc(stream, 5, 96, 200); | ||
1179 | else | ||
1180 | mxl111sf_stream_config_bulk(stream, 5); | ||
1181 | } | ||
1182 | return 0; | ||
1183 | } | ||
1184 | |||
1185 | static int mxl111sf_streaming_ctrl_atsc_mh(struct dvb_frontend *fe, int onoff) | ||
1186 | { | ||
1187 | deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); | ||
1188 | |||
1189 | if (fe->id == 0) | ||
1190 | return mxl111sf_ep6_streaming_ctrl(fe, onoff); | ||
1191 | else if (fe->id == 1) | ||
1192 | return mxl111sf_ep4_streaming_ctrl(fe, onoff); | ||
1193 | else if (fe->id == 2) | ||
1194 | return mxl111sf_ep5_streaming_ctrl(fe, onoff); | ||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | static struct dvb_usb_device_properties mxl111sf_props_atsc_mh = { | ||
1199 | .driver_name = KBUILD_MODNAME, | ||
1200 | .owner = THIS_MODULE, | ||
1201 | .adapter_nr = adapter_nr, | ||
1202 | .size_of_priv = sizeof(struct mxl111sf_state), | ||
1203 | |||
1204 | .generic_bulk_ctrl_endpoint = 0x02, | ||
1205 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
1206 | |||
1207 | .i2c_algo = &mxl111sf_i2c_algo, | ||
1208 | .frontend_attach = mxl111sf_frontend_attach_atsc_mh, | ||
1209 | .tuner_attach = mxl111sf_attach_tuner, | ||
1210 | .init = mxl111sf_init, | ||
1211 | .streaming_ctrl = mxl111sf_streaming_ctrl_atsc_mh, | ||
1212 | .get_stream_config = mxl111sf_get_stream_config_atsc_mh, | ||
1213 | |||
1214 | .num_adapters = 1, | ||
1215 | .adapter = { | ||
1216 | { | ||
1217 | .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), | ||
1218 | } | ||
1219 | } | ||
1220 | }; | ||
1221 | |||
1222 | /* mercury lgdt3305 mxl111sf lg2161 | ||
1223 | * tp bulk EP6/BULK/5/8192 EP4/BULK/5/8192 EP6/BULK/5/8192/RAW | ||
1224 | * tp isoc EP6/ISOC/5/24/3072 EP4/ISOC/5/96/564 EP6/ISOC/5/24/3072/RAW | ||
1225 | * spi bulk EP6/BULK/5/8192 EP4/BULK/5/8192 EP5/BULK/5/8192/RAW | ||
1226 | * spi isoc EP6/ISOC/5/24/3072 EP4/ISOC/5/96/564 EP5/ISOC/5/96/200/RAW | ||
1227 | */ | ||
1228 | static int mxl111sf_get_stream_config_mercury(struct dvb_frontend *fe, | ||
1229 | u8 *ts_type, struct usb_data_stream_properties *stream) | ||
1230 | { | ||
1231 | deb_info("%s: fe=%d\n", __func__, fe->id); | ||
1232 | |||
1233 | if (fe->id == 0) { | ||
1234 | *ts_type = DVB_USB_FE_TS_TYPE_188; | ||
1235 | if (dvb_usb_mxl111sf_isoc) | ||
1236 | mxl111sf_stream_config_isoc(stream, 6, 24, 3072); | ||
1237 | else | ||
1238 | mxl111sf_stream_config_bulk(stream, 6); | ||
1239 | } else if (fe->id == 1) { | ||
1240 | *ts_type = DVB_USB_FE_TS_TYPE_188; | ||
1241 | if (dvb_usb_mxl111sf_isoc) | ||
1242 | mxl111sf_stream_config_isoc(stream, 4, 96, 564); | ||
1243 | else | ||
1244 | mxl111sf_stream_config_bulk(stream, 4); | ||
1245 | } else if (fe->id == 2 && dvb_usb_mxl111sf_spi) { | ||
1246 | *ts_type = DVB_USB_FE_TS_TYPE_RAW; | ||
1247 | if (dvb_usb_mxl111sf_isoc) | ||
1248 | mxl111sf_stream_config_isoc(stream, 5, 96, 200); | ||
1249 | else | ||
1250 | mxl111sf_stream_config_bulk(stream, 5); | ||
1251 | } else if (fe->id == 2 && !dvb_usb_mxl111sf_spi) { | ||
1252 | *ts_type = DVB_USB_FE_TS_TYPE_RAW; | ||
1253 | if (dvb_usb_mxl111sf_isoc) | ||
1254 | mxl111sf_stream_config_isoc(stream, 6, 24, 3072); | ||
1255 | else | ||
1256 | mxl111sf_stream_config_bulk(stream, 6); | ||
1257 | } | ||
1258 | return 0; | ||
1259 | } | ||
1260 | |||
1261 | static int mxl111sf_streaming_ctrl_mercury(struct dvb_frontend *fe, int onoff) | ||
1262 | { | ||
1263 | deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); | ||
1264 | |||
1265 | if (fe->id == 0) | ||
1266 | return mxl111sf_ep6_streaming_ctrl(fe, onoff); | ||
1267 | else if (fe->id == 1) | ||
1268 | return mxl111sf_ep4_streaming_ctrl(fe, onoff); | ||
1269 | else if (fe->id == 2 && dvb_usb_mxl111sf_spi) | ||
1270 | return mxl111sf_ep5_streaming_ctrl(fe, onoff); | ||
1271 | else if (fe->id == 2 && !dvb_usb_mxl111sf_spi) | ||
1272 | return mxl111sf_ep6_streaming_ctrl(fe, onoff); | ||
1273 | return 0; | ||
1274 | } | ||
1275 | |||
1276 | static struct dvb_usb_device_properties mxl111sf_props_mercury = { | ||
1277 | .driver_name = KBUILD_MODNAME, | ||
1278 | .owner = THIS_MODULE, | ||
1279 | .adapter_nr = adapter_nr, | ||
1280 | .size_of_priv = sizeof(struct mxl111sf_state), | ||
1281 | |||
1282 | .generic_bulk_ctrl_endpoint = 0x02, | ||
1283 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
1284 | |||
1285 | .i2c_algo = &mxl111sf_i2c_algo, | ||
1286 | .frontend_attach = mxl111sf_frontend_attach_mercury, | ||
1287 | .tuner_attach = mxl111sf_attach_tuner, | ||
1288 | .init = mxl111sf_init, | ||
1289 | .streaming_ctrl = mxl111sf_streaming_ctrl_mercury, | ||
1290 | .get_stream_config = mxl111sf_get_stream_config_mercury, | ||
1291 | |||
1292 | .num_adapters = 1, | ||
1293 | .adapter = { | ||
1294 | { | ||
1295 | .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), | ||
1296 | } | ||
1297 | } | ||
1298 | }; | ||
1299 | |||
1300 | /* mercury mh mxl111sf lg2161 | ||
1301 | * tp bulk EP4/BULK/5/8192 EP6/BULK/5/8192/RAW | ||
1302 | * tp isoc EP4/ISOC/5/96/564 EP6/ISOC/5/24/3072/RAW | ||
1303 | * spi bulk EP4/BULK/5/8192 EP5/BULK/5/8192/RAW | ||
1304 | * spi isoc EP4/ISOC/5/96/564 EP5/ISOC/5/96/200/RAW | ||
1305 | */ | ||
1306 | static int mxl111sf_get_stream_config_mercury_mh(struct dvb_frontend *fe, | ||
1307 | u8 *ts_type, struct usb_data_stream_properties *stream) | ||
1308 | { | ||
1309 | deb_info("%s: fe=%d\n", __func__, fe->id); | ||
1310 | |||
1311 | if (fe->id == 0) { | ||
1312 | *ts_type = DVB_USB_FE_TS_TYPE_188; | ||
1313 | if (dvb_usb_mxl111sf_isoc) | ||
1314 | mxl111sf_stream_config_isoc(stream, 4, 96, 564); | ||
1315 | else | ||
1316 | mxl111sf_stream_config_bulk(stream, 4); | ||
1317 | } else if (fe->id == 1 && dvb_usb_mxl111sf_spi) { | ||
1318 | *ts_type = DVB_USB_FE_TS_TYPE_RAW; | ||
1319 | if (dvb_usb_mxl111sf_isoc) | ||
1320 | mxl111sf_stream_config_isoc(stream, 5, 96, 200); | ||
1321 | else | ||
1322 | mxl111sf_stream_config_bulk(stream, 5); | ||
1323 | } else if (fe->id == 1 && !dvb_usb_mxl111sf_spi) { | ||
1324 | *ts_type = DVB_USB_FE_TS_TYPE_RAW; | ||
1325 | if (dvb_usb_mxl111sf_isoc) | ||
1326 | mxl111sf_stream_config_isoc(stream, 6, 24, 3072); | ||
1327 | else | ||
1328 | mxl111sf_stream_config_bulk(stream, 6); | ||
1329 | } | ||
1330 | return 0; | ||
1331 | } | ||
1332 | |||
1333 | static int mxl111sf_streaming_ctrl_mercury_mh(struct dvb_frontend *fe, int onoff) | ||
1334 | { | ||
1335 | deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); | ||
1336 | |||
1337 | if (fe->id == 0) | ||
1338 | return mxl111sf_ep4_streaming_ctrl(fe, onoff); | ||
1339 | else if (fe->id == 1 && dvb_usb_mxl111sf_spi) | ||
1340 | return mxl111sf_ep5_streaming_ctrl(fe, onoff); | ||
1341 | else if (fe->id == 1 && !dvb_usb_mxl111sf_spi) | ||
1342 | return mxl111sf_ep6_streaming_ctrl(fe, onoff); | ||
1343 | return 0; | ||
1344 | } | ||
1345 | |||
1346 | static struct dvb_usb_device_properties mxl111sf_props_mercury_mh = { | ||
1347 | .driver_name = KBUILD_MODNAME, | ||
1348 | .owner = THIS_MODULE, | ||
1349 | .adapter_nr = adapter_nr, | ||
1350 | .size_of_priv = sizeof(struct mxl111sf_state), | ||
1351 | |||
1352 | .generic_bulk_ctrl_endpoint = 0x02, | ||
1353 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
1354 | |||
1355 | .i2c_algo = &mxl111sf_i2c_algo, | ||
1356 | .frontend_attach = mxl111sf_frontend_attach_mercury_mh, | ||
1357 | .tuner_attach = mxl111sf_attach_tuner, | ||
1358 | .init = mxl111sf_init, | ||
1359 | .streaming_ctrl = mxl111sf_streaming_ctrl_mercury_mh, | ||
1360 | .get_stream_config = mxl111sf_get_stream_config_mercury_mh, | ||
1361 | |||
1362 | .num_adapters = 1, | ||
1363 | .adapter = { | ||
1364 | { | ||
1365 | .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1), | ||
1366 | } | ||
1367 | } | ||
1368 | }; | ||
1369 | |||
1370 | static const struct usb_device_id mxl111sf_id_table[] = { | ||
1371 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) }, | ||
1372 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601, &mxl111sf_props_atsc, "Hauppauge 126xxx ATSC", NULL) }, | ||
1373 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602, &mxl111sf_props_mh, "HCW 126xxx", NULL) }, | ||
1374 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) }, | ||
1375 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604, &mxl111sf_props_dvbt, "Hauppauge 126xxx DVBT", NULL) }, | ||
1376 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609, &mxl111sf_props_atsc, "Hauppauge 126xxx ATSC", NULL) }, | ||
1377 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a, &mxl111sf_props_mh, "HCW 126xxx", NULL) }, | ||
1378 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) }, | ||
1379 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c, &mxl111sf_props_dvbt, "Hauppauge 126xxx DVBT", NULL) }, | ||
1380 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) }, | ||
1381 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) }, | ||
1382 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, | ||
1383 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701, &mxl111sf_props_atsc, "Hauppauge 126xxx ATSC", NULL) }, | ||
1384 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702, &mxl111sf_props_mh, "HCW 117xxx", NULL) }, | ||
1385 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, | ||
1386 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704, &mxl111sf_props_dvbt, "Hauppauge 117xxx DVBT", NULL) }, | ||
1387 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, | ||
1388 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, | ||
1389 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764, &mxl111sf_props_dvbt, "Hauppauge 117xxx DVBT", NULL) }, | ||
1390 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) }, | ||
1391 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) }, | ||
1392 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) }, | ||
1393 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) }, | ||
1394 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) }, | ||
1395 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) }, | ||
1396 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) }, | ||
1397 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) }, | ||
1398 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) }, | ||
1399 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612, &mxl111sf_props_mercury_mh, "Hauppauge 126xxx", NULL) }, | ||
1400 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613, &mxl111sf_props_mercury, "Hauppauge WinTV-Aero-M", NULL) }, | ||
1401 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a, &mxl111sf_props_mercury_mh, "Hauppauge 126xxx", NULL) }, | ||
1402 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b, &mxl111sf_props_mercury, "Hauppauge WinTV-Aero-M", NULL) }, | ||
1403 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, | ||
1404 | { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) }, | ||
1405 | { } | ||
1406 | }; | ||
1407 | MODULE_DEVICE_TABLE(usb, mxl111sf_id_table); | ||
1408 | |||
1409 | static struct usb_driver mxl111sf_usb_driver = { | ||
1410 | .name = KBUILD_MODNAME, | ||
1411 | .id_table = mxl111sf_id_table, | ||
1412 | .probe = dvb_usbv2_probe, | ||
1413 | .disconnect = dvb_usbv2_disconnect, | ||
1414 | .suspend = dvb_usbv2_suspend, | ||
1415 | .resume = dvb_usbv2_resume, | ||
1416 | .no_dynamic_id = 1, | ||
1417 | .soft_unbind = 1, | ||
1418 | }; | ||
1419 | |||
1420 | module_usb_driver(mxl111sf_usb_driver); | ||
1421 | |||
1422 | MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>"); | ||
1423 | MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF"); | ||
1424 | MODULE_VERSION("1.0"); | ||
1425 | MODULE_LICENSE("GPL"); | ||
1426 | |||
1427 | /* | ||
1428 | * Local variables: | ||
1429 | * c-basic-offset: 8 | ||
1430 | * End: | ||
1431 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h new file mode 100644 index 000000000000..9816de86e48c --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the Free | ||
6 | * Software Foundation, version 2. | ||
7 | * | ||
8 | * see Documentation/dvb/README.dvb-usb for more information | ||
9 | */ | ||
10 | |||
11 | #ifndef _DVB_USB_MXL111SF_H_ | ||
12 | #define _DVB_USB_MXL111SF_H_ | ||
13 | |||
14 | #ifdef DVB_USB_LOG_PREFIX | ||
15 | #undef DVB_USB_LOG_PREFIX | ||
16 | #endif | ||
17 | #define DVB_USB_LOG_PREFIX "mxl111sf" | ||
18 | #include "dvb_usb.h" | ||
19 | #include <media/tveeprom.h> | ||
20 | |||
21 | #define MXL_EP1_REG_READ 1 | ||
22 | #define MXL_EP2_REG_WRITE 2 | ||
23 | #define MXL_EP3_INTERRUPT 3 | ||
24 | #define MXL_EP4_MPEG2 4 | ||
25 | #define MXL_EP5_I2S 5 | ||
26 | #define MXL_EP6_656 6 | ||
27 | #define MXL_EP6_MPEG2 6 | ||
28 | |||
29 | #ifdef USING_ENUM_mxl111sf_current_mode | ||
30 | enum mxl111sf_current_mode { | ||
31 | mxl_mode_dvbt = MXL_EP4_MPEG2, | ||
32 | mxl_mode_mh = MXL_EP5_I2S, | ||
33 | mxl_mode_atsc = MXL_EP6_MPEG2, | ||
34 | }; | ||
35 | #endif | ||
36 | |||
37 | enum mxl111sf_gpio_port_expander { | ||
38 | mxl111sf_gpio_hw, | ||
39 | mxl111sf_PCA9534, | ||
40 | }; | ||
41 | |||
42 | struct mxl111sf_adap_state { | ||
43 | int alt_mode; | ||
44 | int gpio_mode; | ||
45 | int device_mode; | ||
46 | int ep6_clockphase; | ||
47 | int (*fe_init)(struct dvb_frontend *); | ||
48 | int (*fe_sleep)(struct dvb_frontend *); | ||
49 | }; | ||
50 | |||
51 | struct mxl111sf_state { | ||
52 | struct dvb_usb_device *d; | ||
53 | |||
54 | enum mxl111sf_gpio_port_expander gpio_port_expander; | ||
55 | u8 port_expander_addr; | ||
56 | |||
57 | u8 chip_id; | ||
58 | u8 chip_ver; | ||
59 | #define MXL111SF_V6 1 | ||
60 | #define MXL111SF_V8_100 2 | ||
61 | #define MXL111SF_V8_200 3 | ||
62 | u8 chip_rev; | ||
63 | |||
64 | #ifdef USING_ENUM_mxl111sf_current_mode | ||
65 | enum mxl111sf_current_mode current_mode; | ||
66 | #endif | ||
67 | |||
68 | #define MXL_TUNER_MODE 0 | ||
69 | #define MXL_SOC_MODE 1 | ||
70 | #define MXL_DEV_MODE_MASK 0x01 | ||
71 | #if 1 | ||
72 | int device_mode; | ||
73 | #endif | ||
74 | /* use usb alt setting 1 for EP4 ISOC transfer (dvb-t), | ||
75 | EP5 BULK transfer (atsc-mh), | ||
76 | EP6 BULK transfer (atsc/qam), | ||
77 | use usb alt setting 2 for EP4 BULK transfer (dvb-t), | ||
78 | EP5 ISOC transfer (atsc-mh), | ||
79 | EP6 ISOC transfer (atsc/qam), | ||
80 | */ | ||
81 | int alt_mode; | ||
82 | int gpio_mode; | ||
83 | struct tveeprom tv; | ||
84 | |||
85 | struct mutex fe_lock; | ||
86 | u8 num_frontends; | ||
87 | struct mxl111sf_adap_state adap_state[3]; | ||
88 | }; | ||
89 | |||
90 | int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data); | ||
91 | int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data); | ||
92 | |||
93 | struct mxl111sf_reg_ctrl_info { | ||
94 | u8 addr; | ||
95 | u8 mask; | ||
96 | u8 data; | ||
97 | }; | ||
98 | |||
99 | int mxl111sf_write_reg_mask(struct mxl111sf_state *state, | ||
100 | u8 addr, u8 mask, u8 data); | ||
101 | int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state, | ||
102 | struct mxl111sf_reg_ctrl_info *ctrl_reg_info); | ||
103 | |||
104 | /* needed for hardware i2c functions in mxl111sf-i2c.c: | ||
105 | * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */ | ||
106 | int mxl111sf_ctrl_msg(struct dvb_usb_device *d, | ||
107 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen); | ||
108 | |||
109 | #define mxl_printk(kern, fmt, arg...) \ | ||
110 | printk(kern "%s: " fmt "\n", __func__, ##arg) | ||
111 | |||
112 | #define mxl_info(fmt, arg...) \ | ||
113 | mxl_printk(KERN_INFO, fmt, ##arg) | ||
114 | |||
115 | extern int dvb_usb_mxl111sf_debug; | ||
116 | #define mxl_debug(fmt, arg...) \ | ||
117 | if (dvb_usb_mxl111sf_debug) \ | ||
118 | mxl_printk(KERN_DEBUG, fmt, ##arg) | ||
119 | |||
120 | #define MXL_I2C_DBG 0x04 | ||
121 | #define MXL_ADV_DBG 0x10 | ||
122 | #define mxl_debug_adv(fmt, arg...) \ | ||
123 | if (dvb_usb_mxl111sf_debug & MXL_ADV_DBG) \ | ||
124 | mxl_printk(KERN_DEBUG, fmt, ##arg) | ||
125 | |||
126 | #define mxl_i2c(fmt, arg...) \ | ||
127 | if (dvb_usb_mxl111sf_debug & MXL_I2C_DBG) \ | ||
128 | mxl_printk(KERN_DEBUG, fmt, ##arg) | ||
129 | |||
130 | #define mxl_i2c_adv(fmt, arg...) \ | ||
131 | if ((dvb_usb_mxl111sf_debug & (MXL_I2C_DBG | MXL_ADV_DBG)) == \ | ||
132 | (MXL_I2C_DBG | MXL_ADV_DBG)) \ | ||
133 | mxl_printk(KERN_DEBUG, fmt, ##arg) | ||
134 | |||
135 | /* The following allows the mxl_fail() macro defined below to work | ||
136 | * in externel modules, such as mxl111sf-tuner.ko, even though | ||
137 | * dvb_usb_mxl111sf_debug is not defined within those modules */ | ||
138 | #if (defined(__MXL111SF_TUNER_H__)) || (defined(__MXL111SF_DEMOD_H__)) | ||
139 | #define MXL_ADV_DEBUG_ENABLED MXL_ADV_DBG | ||
140 | #else | ||
141 | #define MXL_ADV_DEBUG_ENABLED dvb_usb_mxl111sf_debug | ||
142 | #endif | ||
143 | |||
144 | #define mxl_fail(ret) \ | ||
145 | ({ \ | ||
146 | int __ret; \ | ||
147 | __ret = (ret < 0); \ | ||
148 | if ((__ret) && (MXL_ADV_DEBUG_ENABLED & MXL_ADV_DBG)) \ | ||
149 | mxl_printk(KERN_ERR, "error %d on line %d", \ | ||
150 | ret, __LINE__); \ | ||
151 | __ret; \ | ||
152 | }) | ||
153 | |||
154 | #endif /* _DVB_USB_MXL111SF_H_ */ | ||
155 | |||
156 | /* | ||
157 | * Local variables: | ||
158 | * c-basic-offset: 8 | ||
159 | * End: | ||
160 | */ | ||
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c new file mode 100644 index 000000000000..a2d1e5b9d9d4 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c | |||
@@ -0,0 +1,1259 @@ | |||
1 | /* | ||
2 | * Realtek RTL28xxU DVB USB driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
5 | * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | ||
6 | * Copyright (C) 2012 Thomas Mair <thomas.mair86@googlemail.com> | ||
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 along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | */ | ||
22 | |||
23 | #include "rtl28xxu.h" | ||
24 | |||
25 | #include "rtl2830.h" | ||
26 | #include "rtl2832.h" | ||
27 | |||
28 | #include "qt1010.h" | ||
29 | #include "mt2060.h" | ||
30 | #include "mxl5005s.h" | ||
31 | #include "fc0012.h" | ||
32 | #include "fc0013.h" | ||
33 | |||
34 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
35 | |||
36 | static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req) | ||
37 | { | ||
38 | int ret; | ||
39 | unsigned int pipe; | ||
40 | u8 requesttype; | ||
41 | u8 *buf; | ||
42 | |||
43 | buf = kmalloc(req->size, GFP_KERNEL); | ||
44 | if (!buf) { | ||
45 | ret = -ENOMEM; | ||
46 | goto err; | ||
47 | } | ||
48 | |||
49 | if (req->index & CMD_WR_FLAG) { | ||
50 | /* write */ | ||
51 | memcpy(buf, req->data, req->size); | ||
52 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | ||
53 | pipe = usb_sndctrlpipe(d->udev, 0); | ||
54 | } else { | ||
55 | /* read */ | ||
56 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | ||
57 | pipe = usb_rcvctrlpipe(d->udev, 0); | ||
58 | } | ||
59 | |||
60 | ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value, | ||
61 | req->index, buf, req->size, 1000); | ||
62 | if (ret > 0) | ||
63 | ret = 0; | ||
64 | |||
65 | deb_dump(0, requesttype, req->value, req->index, buf, req->size); | ||
66 | |||
67 | /* read request, copy returned data to return buf */ | ||
68 | if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN)) | ||
69 | memcpy(req->data, buf, req->size); | ||
70 | |||
71 | kfree(buf); | ||
72 | |||
73 | if (ret) | ||
74 | goto err; | ||
75 | |||
76 | return ret; | ||
77 | err: | ||
78 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | static int rtl28xx_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) | ||
83 | { | ||
84 | struct rtl28xxu_req req; | ||
85 | |||
86 | if (reg < 0x3000) | ||
87 | req.index = CMD_USB_WR; | ||
88 | else if (reg < 0x4000) | ||
89 | req.index = CMD_SYS_WR; | ||
90 | else | ||
91 | req.index = CMD_IR_WR; | ||
92 | |||
93 | req.value = reg; | ||
94 | req.size = len; | ||
95 | req.data = val; | ||
96 | |||
97 | return rtl28xxu_ctrl_msg(d, &req); | ||
98 | } | ||
99 | |||
100 | static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) | ||
101 | { | ||
102 | struct rtl28xxu_req req; | ||
103 | |||
104 | if (reg < 0x3000) | ||
105 | req.index = CMD_USB_RD; | ||
106 | else if (reg < 0x4000) | ||
107 | req.index = CMD_SYS_RD; | ||
108 | else | ||
109 | req.index = CMD_IR_RD; | ||
110 | |||
111 | req.value = reg; | ||
112 | req.size = len; | ||
113 | req.data = val; | ||
114 | |||
115 | return rtl28xxu_ctrl_msg(d, &req); | ||
116 | } | ||
117 | |||
118 | static int rtl28xx_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) | ||
119 | { | ||
120 | return rtl28xx_wr_regs(d, reg, &val, 1); | ||
121 | } | ||
122 | |||
123 | static int rtl28xx_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) | ||
124 | { | ||
125 | return rtl2831_rd_regs(d, reg, val, 1); | ||
126 | } | ||
127 | |||
128 | /* I2C */ | ||
129 | static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
130 | int num) | ||
131 | { | ||
132 | int ret; | ||
133 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
134 | struct rtl28xxu_priv *priv = d->priv; | ||
135 | struct rtl28xxu_req req; | ||
136 | |||
137 | /* | ||
138 | * It is not known which are real I2C bus xfer limits, but testing | ||
139 | * with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes. | ||
140 | * TODO: find out RTL2832U lens | ||
141 | */ | ||
142 | |||
143 | /* | ||
144 | * I2C adapter logic looks rather complicated due to fact it handles | ||
145 | * three different access methods. Those methods are; | ||
146 | * 1) integrated demod access | ||
147 | * 2) old I2C access | ||
148 | * 3) new I2C access | ||
149 | * | ||
150 | * Used method is selected in order 1, 2, 3. Method 3 can handle all | ||
151 | * requests but there is two reasons why not use it always; | ||
152 | * 1) It is most expensive, usually two USB messages are needed | ||
153 | * 2) At least RTL2831U does not support it | ||
154 | * | ||
155 | * Method 3 is needed in case of I2C write+read (typical register read) | ||
156 | * where write is more than one byte. | ||
157 | */ | ||
158 | |||
159 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
160 | return -EAGAIN; | ||
161 | |||
162 | if (num == 2 && !(msg[0].flags & I2C_M_RD) && | ||
163 | (msg[1].flags & I2C_M_RD)) { | ||
164 | if (msg[0].len > 24 || msg[1].len > 24) { | ||
165 | /* TODO: check msg[0].len max */ | ||
166 | ret = -EOPNOTSUPP; | ||
167 | goto err_mutex_unlock; | ||
168 | } else if (msg[0].addr == 0x10) { | ||
169 | /* method 1 - integrated demod */ | ||
170 | req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); | ||
171 | req.index = CMD_DEMOD_RD | priv->page; | ||
172 | req.size = msg[1].len; | ||
173 | req.data = &msg[1].buf[0]; | ||
174 | ret = rtl28xxu_ctrl_msg(d, &req); | ||
175 | } else if (msg[0].len < 2) { | ||
176 | /* method 2 - old I2C */ | ||
177 | req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); | ||
178 | req.index = CMD_I2C_RD; | ||
179 | req.size = msg[1].len; | ||
180 | req.data = &msg[1].buf[0]; | ||
181 | ret = rtl28xxu_ctrl_msg(d, &req); | ||
182 | } else { | ||
183 | /* method 3 - new I2C */ | ||
184 | req.value = (msg[0].addr << 1); | ||
185 | req.index = CMD_I2C_DA_WR; | ||
186 | req.size = msg[0].len; | ||
187 | req.data = msg[0].buf; | ||
188 | ret = rtl28xxu_ctrl_msg(d, &req); | ||
189 | if (ret) | ||
190 | goto err_mutex_unlock; | ||
191 | |||
192 | req.value = (msg[0].addr << 1); | ||
193 | req.index = CMD_I2C_DA_RD; | ||
194 | req.size = msg[1].len; | ||
195 | req.data = msg[1].buf; | ||
196 | ret = rtl28xxu_ctrl_msg(d, &req); | ||
197 | } | ||
198 | } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { | ||
199 | if (msg[0].len > 22) { | ||
200 | /* TODO: check msg[0].len max */ | ||
201 | ret = -EOPNOTSUPP; | ||
202 | goto err_mutex_unlock; | ||
203 | } else if (msg[0].addr == 0x10) { | ||
204 | /* method 1 - integrated demod */ | ||
205 | if (msg[0].buf[0] == 0x00) { | ||
206 | /* save demod page for later demod access */ | ||
207 | priv->page = msg[0].buf[1]; | ||
208 | ret = 0; | ||
209 | } else { | ||
210 | req.value = (msg[0].buf[0] << 8) | | ||
211 | (msg[0].addr << 1); | ||
212 | req.index = CMD_DEMOD_WR | priv->page; | ||
213 | req.size = msg[0].len-1; | ||
214 | req.data = &msg[0].buf[1]; | ||
215 | ret = rtl28xxu_ctrl_msg(d, &req); | ||
216 | } | ||
217 | } else if (msg[0].len < 23) { | ||
218 | /* method 2 - old I2C */ | ||
219 | req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1); | ||
220 | req.index = CMD_I2C_WR; | ||
221 | req.size = msg[0].len-1; | ||
222 | req.data = &msg[0].buf[1]; | ||
223 | ret = rtl28xxu_ctrl_msg(d, &req); | ||
224 | } else { | ||
225 | /* method 3 - new I2C */ | ||
226 | req.value = (msg[0].addr << 1); | ||
227 | req.index = CMD_I2C_DA_WR; | ||
228 | req.size = msg[0].len; | ||
229 | req.data = msg[0].buf; | ||
230 | ret = rtl28xxu_ctrl_msg(d, &req); | ||
231 | } | ||
232 | } else { | ||
233 | ret = -EINVAL; | ||
234 | } | ||
235 | |||
236 | err_mutex_unlock: | ||
237 | mutex_unlock(&d->i2c_mutex); | ||
238 | |||
239 | return ret ? ret : num; | ||
240 | } | ||
241 | |||
242 | static u32 rtl28xxu_i2c_func(struct i2c_adapter *adapter) | ||
243 | { | ||
244 | return I2C_FUNC_I2C; | ||
245 | } | ||
246 | |||
247 | static struct i2c_algorithm rtl28xxu_i2c_algo = { | ||
248 | .master_xfer = rtl28xxu_i2c_xfer, | ||
249 | .functionality = rtl28xxu_i2c_func, | ||
250 | }; | ||
251 | |||
252 | static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = { | ||
253 | .i2c_addr = 0x10, /* 0x20 */ | ||
254 | .xtal = 28800000, | ||
255 | .ts_mode = 0, | ||
256 | .spec_inv = 1, | ||
257 | .if_dvbt = 36150000, | ||
258 | .vtop = 0x20, | ||
259 | .krf = 0x04, | ||
260 | .agc_targ_val = 0x2d, | ||
261 | |||
262 | }; | ||
263 | |||
264 | static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = { | ||
265 | .i2c_addr = 0x10, /* 0x20 */ | ||
266 | .xtal = 28800000, | ||
267 | .ts_mode = 0, | ||
268 | .spec_inv = 1, | ||
269 | .if_dvbt = 36125000, | ||
270 | .vtop = 0x20, | ||
271 | .krf = 0x04, | ||
272 | .agc_targ_val = 0x2d, | ||
273 | }; | ||
274 | |||
275 | static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = { | ||
276 | .i2c_addr = 0x10, /* 0x20 */ | ||
277 | .xtal = 28800000, | ||
278 | .ts_mode = 0, | ||
279 | .spec_inv = 0, | ||
280 | .if_dvbt = 4570000, | ||
281 | .vtop = 0x3f, | ||
282 | .krf = 0x04, | ||
283 | .agc_targ_val = 0x3e, | ||
284 | }; | ||
285 | |||
286 | static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) | ||
287 | { | ||
288 | int ret; | ||
289 | struct dvb_usb_device *d = adap_to_d(adap); | ||
290 | struct rtl28xxu_priv *priv = d_to_priv(d); | ||
291 | u8 buf[1]; | ||
292 | struct rtl2830_config *rtl2830_config; | ||
293 | /* open RTL2831U/RTL2830 I2C gate */ | ||
294 | struct rtl28xxu_req req_gate = { 0x0120, 0x0011, 0x0001, "\x08" }; | ||
295 | /* for MT2060 tuner probe */ | ||
296 | struct rtl28xxu_req req_mt2060 = { 0x00c0, CMD_I2C_RD, 1, buf }; | ||
297 | /* for QT1010 tuner probe */ | ||
298 | struct rtl28xxu_req req_qt1010 = { 0x0fc4, CMD_I2C_RD, 1, buf }; | ||
299 | |||
300 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
301 | |||
302 | /* | ||
303 | * RTL2831U GPIOs | ||
304 | * ========================================================= | ||
305 | * GPIO0 | tuner#0 | 0 off | 1 on | MXL5005S (?) | ||
306 | * GPIO2 | LED | 0 off | 1 on | | ||
307 | * GPIO4 | tuner#1 | 0 on | 1 off | MT2060 | ||
308 | */ | ||
309 | |||
310 | /* GPIO direction */ | ||
311 | ret = rtl28xx_wr_reg(d, SYS_GPIO_DIR, 0x0a); | ||
312 | if (ret) | ||
313 | goto err; | ||
314 | |||
315 | /* enable as output GPIO0, GPIO2, GPIO4 */ | ||
316 | ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_EN, 0x15); | ||
317 | if (ret) | ||
318 | goto err; | ||
319 | |||
320 | /* | ||
321 | * Probe used tuner. We need to know used tuner before demod attach | ||
322 | * since there is some demod params needed to set according to tuner. | ||
323 | */ | ||
324 | |||
325 | /* demod needs some time to wake up */ | ||
326 | msleep(20); | ||
327 | |||
328 | /* open demod I2C gate */ | ||
329 | ret = rtl28xxu_ctrl_msg(d, &req_gate); | ||
330 | if (ret) | ||
331 | goto err; | ||
332 | |||
333 | /* check QT1010 ID(?) register; reg=0f val=2c */ | ||
334 | ret = rtl28xxu_ctrl_msg(d, &req_qt1010); | ||
335 | if (ret == 0 && buf[0] == 0x2c) { | ||
336 | priv->tuner = TUNER_RTL2830_QT1010; | ||
337 | rtl2830_config = &rtl28xxu_rtl2830_qt1010_config; | ||
338 | dev_dbg(&d->udev->dev, "%s: QT1010\n", __func__); | ||
339 | goto found; | ||
340 | } else { | ||
341 | dev_dbg(&d->udev->dev, "%s: QT1010 probe failed=%d - %02x\n", | ||
342 | __func__, ret, buf[0]); | ||
343 | } | ||
344 | |||
345 | /* open demod I2C gate */ | ||
346 | ret = rtl28xxu_ctrl_msg(d, &req_gate); | ||
347 | if (ret) | ||
348 | goto err; | ||
349 | |||
350 | /* check MT2060 ID register; reg=00 val=63 */ | ||
351 | ret = rtl28xxu_ctrl_msg(d, &req_mt2060); | ||
352 | if (ret == 0 && buf[0] == 0x63) { | ||
353 | priv->tuner = TUNER_RTL2830_MT2060; | ||
354 | rtl2830_config = &rtl28xxu_rtl2830_mt2060_config; | ||
355 | dev_dbg(&d->udev->dev, "%s: MT2060\n", __func__); | ||
356 | goto found; | ||
357 | } else { | ||
358 | dev_dbg(&d->udev->dev, "%s: MT2060 probe failed=%d - %02x\n", | ||
359 | __func__, ret, buf[0]); | ||
360 | } | ||
361 | |||
362 | /* assume MXL5005S */ | ||
363 | ret = 0; | ||
364 | priv->tuner = TUNER_RTL2830_MXL5005S; | ||
365 | rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config; | ||
366 | dev_dbg(&d->udev->dev, "%s: MXL5005S\n", __func__); | ||
367 | goto found; | ||
368 | |||
369 | found: | ||
370 | /* attach demodulator */ | ||
371 | adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config, | ||
372 | &d->i2c_adap); | ||
373 | if (adap->fe[0] == NULL) { | ||
374 | ret = -ENODEV; | ||
375 | goto err; | ||
376 | } | ||
377 | |||
378 | return ret; | ||
379 | err: | ||
380 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = { | ||
385 | .i2c_addr = 0x10, /* 0x20 */ | ||
386 | .xtal = 28800000, | ||
387 | .if_dvbt = 0, | ||
388 | .tuner = TUNER_RTL2832_FC0012 | ||
389 | }; | ||
390 | |||
391 | static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = { | ||
392 | .i2c_addr = 0x10, /* 0x20 */ | ||
393 | .xtal = 28800000, | ||
394 | .if_dvbt = 0, | ||
395 | .tuner = TUNER_RTL2832_FC0013 | ||
396 | }; | ||
397 | |||
398 | static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d, | ||
399 | int cmd, int arg) | ||
400 | { | ||
401 | int ret; | ||
402 | u8 val; | ||
403 | |||
404 | dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg); | ||
405 | |||
406 | switch (cmd) { | ||
407 | case FC_FE_CALLBACK_VHF_ENABLE: | ||
408 | /* set output values */ | ||
409 | ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); | ||
410 | if (ret) | ||
411 | goto err; | ||
412 | |||
413 | if (arg) | ||
414 | val &= 0xbf; /* set GPIO6 low */ | ||
415 | else | ||
416 | val |= 0x40; /* set GPIO6 high */ | ||
417 | |||
418 | |||
419 | ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); | ||
420 | if (ret) | ||
421 | goto err; | ||
422 | break; | ||
423 | default: | ||
424 | ret = -EINVAL; | ||
425 | goto err; | ||
426 | } | ||
427 | return 0; | ||
428 | |||
429 | err: | ||
430 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
431 | return ret; | ||
432 | } | ||
433 | |||
434 | |||
435 | static int rtl2832u_fc0013_tuner_callback(struct dvb_usb_device *d, | ||
436 | int cmd, int arg) | ||
437 | { | ||
438 | /* TODO implement*/ | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) | ||
443 | { | ||
444 | struct rtl28xxu_priv *priv = d->priv; | ||
445 | |||
446 | switch (priv->tuner) { | ||
447 | case TUNER_RTL2832_FC0012: | ||
448 | return rtl2832u_fc0012_tuner_callback(d, cmd, arg); | ||
449 | |||
450 | case TUNER_RTL2832_FC0013: | ||
451 | return rtl2832u_fc0013_tuner_callback(d, cmd, arg); | ||
452 | default: | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | return -ENODEV; | ||
457 | } | ||
458 | |||
459 | static int rtl2832u_frontend_callback(void *adapter_priv, int component, | ||
460 | int cmd, int arg) | ||
461 | { | ||
462 | struct i2c_adapter *adap = adapter_priv; | ||
463 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
464 | |||
465 | switch (component) { | ||
466 | case DVB_FRONTEND_COMPONENT_TUNER: | ||
467 | return rtl2832u_tuner_callback(d, cmd, arg); | ||
468 | default: | ||
469 | break; | ||
470 | } | ||
471 | |||
472 | return -EINVAL; | ||
473 | } | ||
474 | |||
475 | static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) | ||
476 | { | ||
477 | int ret; | ||
478 | struct dvb_usb_device *d = adap_to_d(adap); | ||
479 | struct rtl28xxu_priv *priv = d_to_priv(d); | ||
480 | struct rtl2832_config *rtl2832_config; | ||
481 | u8 buf[2], val; | ||
482 | /* open RTL2832U/RTL2832 I2C gate */ | ||
483 | struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"}; | ||
484 | /* close RTL2832U/RTL2832 I2C gate */ | ||
485 | struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"}; | ||
486 | /* for FC0012 tuner probe */ | ||
487 | struct rtl28xxu_req req_fc0012 = {0x00c6, CMD_I2C_RD, 1, buf}; | ||
488 | /* for FC0013 tuner probe */ | ||
489 | struct rtl28xxu_req req_fc0013 = {0x00c6, CMD_I2C_RD, 1, buf}; | ||
490 | /* for MT2266 tuner probe */ | ||
491 | struct rtl28xxu_req req_mt2266 = {0x00c0, CMD_I2C_RD, 1, buf}; | ||
492 | /* for FC2580 tuner probe */ | ||
493 | struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf}; | ||
494 | /* for MT2063 tuner probe */ | ||
495 | struct rtl28xxu_req req_mt2063 = {0x00c0, CMD_I2C_RD, 1, buf}; | ||
496 | /* for MAX3543 tuner probe */ | ||
497 | struct rtl28xxu_req req_max3543 = {0x00c0, CMD_I2C_RD, 1, buf}; | ||
498 | /* for TUA9001 tuner probe */ | ||
499 | struct rtl28xxu_req req_tua9001 = {0x7ec0, CMD_I2C_RD, 2, buf}; | ||
500 | /* for MXL5007T tuner probe */ | ||
501 | struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf}; | ||
502 | /* for E4000 tuner probe */ | ||
503 | struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf}; | ||
504 | /* for TDA18272 tuner probe */ | ||
505 | struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf}; | ||
506 | |||
507 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
508 | |||
509 | ret = rtl28xx_rd_reg(d, SYS_GPIO_DIR, &val); | ||
510 | if (ret) | ||
511 | goto err; | ||
512 | |||
513 | val &= 0xbf; | ||
514 | |||
515 | ret = rtl28xx_wr_reg(d, SYS_GPIO_DIR, val); | ||
516 | if (ret) | ||
517 | goto err; | ||
518 | |||
519 | /* enable as output GPIO3 and GPIO6*/ | ||
520 | ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_EN, &val); | ||
521 | if (ret) | ||
522 | goto err; | ||
523 | |||
524 | val |= 0x48; | ||
525 | |||
526 | ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_EN, val); | ||
527 | if (ret) | ||
528 | goto err; | ||
529 | |||
530 | /* | ||
531 | * Probe used tuner. We need to know used tuner before demod attach | ||
532 | * since there is some demod params needed to set according to tuner. | ||
533 | */ | ||
534 | |||
535 | /* open demod I2C gate */ | ||
536 | ret = rtl28xxu_ctrl_msg(d, &req_gate_open); | ||
537 | if (ret) | ||
538 | goto err; | ||
539 | |||
540 | priv->tuner = TUNER_NONE; | ||
541 | |||
542 | /* check FC0012 ID register; reg=00 val=a1 */ | ||
543 | ret = rtl28xxu_ctrl_msg(d, &req_fc0012); | ||
544 | if (ret == 0 && buf[0] == 0xa1) { | ||
545 | priv->tuner = TUNER_RTL2832_FC0012; | ||
546 | rtl2832_config = &rtl28xxu_rtl2832_fc0012_config; | ||
547 | dev_info(&d->udev->dev, "%s: FC0012 tuner found", | ||
548 | KBUILD_MODNAME); | ||
549 | goto found; | ||
550 | } | ||
551 | |||
552 | /* check FC0013 ID register; reg=00 val=a3 */ | ||
553 | ret = rtl28xxu_ctrl_msg(d, &req_fc0013); | ||
554 | if (ret == 0 && buf[0] == 0xa3) { | ||
555 | priv->tuner = TUNER_RTL2832_FC0013; | ||
556 | rtl2832_config = &rtl28xxu_rtl2832_fc0013_config; | ||
557 | dev_info(&d->udev->dev, "%s: FC0013 tuner found", | ||
558 | KBUILD_MODNAME); | ||
559 | goto found; | ||
560 | } | ||
561 | |||
562 | /* check MT2266 ID register; reg=00 val=85 */ | ||
563 | ret = rtl28xxu_ctrl_msg(d, &req_mt2266); | ||
564 | if (ret == 0 && buf[0] == 0x85) { | ||
565 | priv->tuner = TUNER_RTL2832_MT2266; | ||
566 | /* TODO implement tuner */ | ||
567 | dev_info(&d->udev->dev, "%s: MT2266 tuner found", | ||
568 | KBUILD_MODNAME); | ||
569 | goto unsupported; | ||
570 | } | ||
571 | |||
572 | /* check FC2580 ID register; reg=01 val=56 */ | ||
573 | ret = rtl28xxu_ctrl_msg(d, &req_fc2580); | ||
574 | if (ret == 0 && buf[0] == 0x56) { | ||
575 | priv->tuner = TUNER_RTL2832_FC2580; | ||
576 | /* TODO implement tuner */ | ||
577 | dev_info(&d->udev->dev, "%s: FC2580 tuner found", | ||
578 | KBUILD_MODNAME); | ||
579 | goto unsupported; | ||
580 | } | ||
581 | |||
582 | /* check MT2063 ID register; reg=00 val=9e || 9c */ | ||
583 | ret = rtl28xxu_ctrl_msg(d, &req_mt2063); | ||
584 | if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) { | ||
585 | priv->tuner = TUNER_RTL2832_MT2063; | ||
586 | /* TODO implement tuner */ | ||
587 | dev_info(&d->udev->dev, "%s: MT2063 tuner found", | ||
588 | KBUILD_MODNAME); | ||
589 | goto unsupported; | ||
590 | } | ||
591 | |||
592 | /* check MAX3543 ID register; reg=00 val=38 */ | ||
593 | ret = rtl28xxu_ctrl_msg(d, &req_max3543); | ||
594 | if (ret == 0 && buf[0] == 0x38) { | ||
595 | priv->tuner = TUNER_RTL2832_MAX3543; | ||
596 | /* TODO implement tuner */ | ||
597 | dev_info(&d->udev->dev, "%s: MAX3534 tuner found", | ||
598 | KBUILD_MODNAME); | ||
599 | goto unsupported; | ||
600 | } | ||
601 | |||
602 | /* check TUA9001 ID register; reg=7e val=2328 */ | ||
603 | ret = rtl28xxu_ctrl_msg(d, &req_tua9001); | ||
604 | if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) { | ||
605 | priv->tuner = TUNER_RTL2832_TUA9001; | ||
606 | /* TODO implement tuner */ | ||
607 | dev_info(&d->udev->dev, "%s: TUA9001 tuner found", | ||
608 | KBUILD_MODNAME); | ||
609 | goto unsupported; | ||
610 | } | ||
611 | |||
612 | /* check MXL5007R ID register; reg=d9 val=14 */ | ||
613 | ret = rtl28xxu_ctrl_msg(d, &req_mxl5007t); | ||
614 | if (ret == 0 && buf[0] == 0x14) { | ||
615 | priv->tuner = TUNER_RTL2832_MXL5007T; | ||
616 | /* TODO implement tuner */ | ||
617 | dev_info(&d->udev->dev, "%s: MXL5007T tuner found", | ||
618 | KBUILD_MODNAME); | ||
619 | goto unsupported; | ||
620 | } | ||
621 | |||
622 | /* check E4000 ID register; reg=02 val=40 */ | ||
623 | ret = rtl28xxu_ctrl_msg(d, &req_e4000); | ||
624 | if (ret == 0 && buf[0] == 0x40) { | ||
625 | priv->tuner = TUNER_RTL2832_E4000; | ||
626 | /* TODO implement tuner */ | ||
627 | dev_info(&d->udev->dev, "%s: E4000 tuner found", | ||
628 | KBUILD_MODNAME); | ||
629 | goto unsupported; | ||
630 | } | ||
631 | |||
632 | /* check TDA18272 ID register; reg=00 val=c760 */ | ||
633 | ret = rtl28xxu_ctrl_msg(d, &req_tda18272); | ||
634 | if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) { | ||
635 | priv->tuner = TUNER_RTL2832_TDA18272; | ||
636 | /* TODO implement tuner */ | ||
637 | dev_info(&d->udev->dev, "%s: TDA18272 tuner found", | ||
638 | KBUILD_MODNAME); | ||
639 | goto unsupported; | ||
640 | } | ||
641 | |||
642 | unsupported: | ||
643 | /* close demod I2C gate */ | ||
644 | ret = rtl28xxu_ctrl_msg(d, &req_gate_close); | ||
645 | if (ret) | ||
646 | goto err; | ||
647 | |||
648 | /* tuner not found */ | ||
649 | dev_dbg(&d->udev->dev, "%s: No compatible tuner found\n", __func__); | ||
650 | ret = -ENODEV; | ||
651 | return ret; | ||
652 | |||
653 | found: | ||
654 | /* close demod I2C gate */ | ||
655 | ret = rtl28xxu_ctrl_msg(d, &req_gate_close); | ||
656 | if (ret) | ||
657 | goto err; | ||
658 | |||
659 | /* attach demodulator */ | ||
660 | adap->fe[0] = dvb_attach(rtl2832_attach, rtl2832_config, | ||
661 | &d->i2c_adap); | ||
662 | if (adap->fe[0] == NULL) { | ||
663 | ret = -ENODEV; | ||
664 | goto err; | ||
665 | } | ||
666 | |||
667 | /* set fe callbacks */ | ||
668 | adap->fe[0]->callback = rtl2832u_frontend_callback; | ||
669 | |||
670 | return ret; | ||
671 | |||
672 | err: | ||
673 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
674 | return ret; | ||
675 | } | ||
676 | |||
677 | static struct qt1010_config rtl28xxu_qt1010_config = { | ||
678 | .i2c_address = 0x62, /* 0xc4 */ | ||
679 | }; | ||
680 | |||
681 | static struct mt2060_config rtl28xxu_mt2060_config = { | ||
682 | .i2c_address = 0x60, /* 0xc0 */ | ||
683 | .clock_out = 0, | ||
684 | }; | ||
685 | |||
686 | static struct mxl5005s_config rtl28xxu_mxl5005s_config = { | ||
687 | .i2c_address = 0x63, /* 0xc6 */ | ||
688 | .if_freq = IF_FREQ_4570000HZ, | ||
689 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | ||
690 | .agc_mode = MXL_SINGLE_AGC, | ||
691 | .tracking_filter = MXL_TF_C_H, | ||
692 | .rssi_enable = MXL_RSSI_ENABLE, | ||
693 | .cap_select = MXL_CAP_SEL_ENABLE, | ||
694 | .div_out = MXL_DIV_OUT_4, | ||
695 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
696 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
697 | .top = MXL5005S_TOP_25P2, | ||
698 | .mod_mode = MXL_DIGITAL_MODE, | ||
699 | .if_mode = MXL_ZERO_IF, | ||
700 | .AgcMasterByte = 0x00, | ||
701 | }; | ||
702 | |||
703 | static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap) | ||
704 | { | ||
705 | int ret; | ||
706 | struct dvb_usb_device *d = adap_to_d(adap); | ||
707 | struct rtl28xxu_priv *priv = d_to_priv(d); | ||
708 | struct i2c_adapter *rtl2830_tuner_i2c; | ||
709 | struct dvb_frontend *fe; | ||
710 | |||
711 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
712 | |||
713 | /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */ | ||
714 | rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe[0]); | ||
715 | |||
716 | switch (priv->tuner) { | ||
717 | case TUNER_RTL2830_QT1010: | ||
718 | fe = dvb_attach(qt1010_attach, adap->fe[0], | ||
719 | rtl2830_tuner_i2c, &rtl28xxu_qt1010_config); | ||
720 | break; | ||
721 | case TUNER_RTL2830_MT2060: | ||
722 | fe = dvb_attach(mt2060_attach, adap->fe[0], | ||
723 | rtl2830_tuner_i2c, &rtl28xxu_mt2060_config, | ||
724 | 1220); | ||
725 | break; | ||
726 | case TUNER_RTL2830_MXL5005S: | ||
727 | fe = dvb_attach(mxl5005s_attach, adap->fe[0], | ||
728 | rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config); | ||
729 | break; | ||
730 | default: | ||
731 | fe = NULL; | ||
732 | dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, | ||
733 | priv->tuner); | ||
734 | } | ||
735 | |||
736 | if (fe == NULL) { | ||
737 | ret = -ENODEV; | ||
738 | goto err; | ||
739 | } | ||
740 | |||
741 | return 0; | ||
742 | err: | ||
743 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
744 | return ret; | ||
745 | } | ||
746 | |||
747 | static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) | ||
748 | { | ||
749 | int ret; | ||
750 | struct dvb_usb_device *d = adap_to_d(adap); | ||
751 | struct rtl28xxu_priv *priv = d_to_priv(d); | ||
752 | struct dvb_frontend *fe; | ||
753 | |||
754 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
755 | |||
756 | switch (priv->tuner) { | ||
757 | case TUNER_RTL2832_FC0012: | ||
758 | fe = dvb_attach(fc0012_attach, adap->fe[0], | ||
759 | &d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); | ||
760 | |||
761 | /* since fc0012 includs reading the signal strength delegate | ||
762 | * that to the tuner driver */ | ||
763 | adap->fe[0]->ops.read_signal_strength = | ||
764 | adap->fe[0]->ops.tuner_ops.get_rf_strength; | ||
765 | return 0; | ||
766 | break; | ||
767 | case TUNER_RTL2832_FC0013: | ||
768 | fe = dvb_attach(fc0013_attach, adap->fe[0], | ||
769 | &d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ); | ||
770 | |||
771 | /* fc0013 also supports signal strength reading */ | ||
772 | adap->fe[0]->ops.read_signal_strength = | ||
773 | adap->fe[0]->ops.tuner_ops.get_rf_strength; | ||
774 | return 0; | ||
775 | default: | ||
776 | fe = NULL; | ||
777 | dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME, | ||
778 | priv->tuner); | ||
779 | } | ||
780 | |||
781 | if (fe == NULL) { | ||
782 | ret = -ENODEV; | ||
783 | goto err; | ||
784 | } | ||
785 | |||
786 | return 0; | ||
787 | err: | ||
788 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
789 | return ret; | ||
790 | } | ||
791 | |||
792 | static int rtl28xxu_init(struct dvb_usb_device *d) | ||
793 | { | ||
794 | int ret; | ||
795 | u8 val; | ||
796 | |||
797 | dev_dbg(&d->udev->dev, "%s:\n", __func__); | ||
798 | |||
799 | /* init USB endpoints */ | ||
800 | ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val); | ||
801 | if (ret) | ||
802 | goto err; | ||
803 | |||
804 | /* enable DMA and Full Packet Mode*/ | ||
805 | val |= 0x09; | ||
806 | ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val); | ||
807 | if (ret) | ||
808 | goto err; | ||
809 | |||
810 | /* set EPA maximum packet size to 0x0200 */ | ||
811 | ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); | ||
812 | if (ret) | ||
813 | goto err; | ||
814 | |||
815 | /* change EPA FIFO length */ | ||
816 | ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); | ||
817 | if (ret) | ||
818 | goto err; | ||
819 | |||
820 | return ret; | ||
821 | err: | ||
822 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
823 | return ret; | ||
824 | } | ||
825 | |||
826 | static int rtl28xxu_streaming_ctrl(struct dvb_frontend *fe , int onoff) | ||
827 | { | ||
828 | int ret; | ||
829 | u8 buf[2]; | ||
830 | struct dvb_usb_device *d = fe_to_d(fe); | ||
831 | |||
832 | dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); | ||
833 | |||
834 | if (onoff) { | ||
835 | buf[0] = 0x00; | ||
836 | buf[1] = 0x00; | ||
837 | } else { | ||
838 | buf[0] = 0x10; /* stall EPA */ | ||
839 | buf[1] = 0x02; /* reset EPA */ | ||
840 | } | ||
841 | |||
842 | ret = rtl28xx_wr_regs(d, USB_EPA_CTL, buf, 2); | ||
843 | if (ret) | ||
844 | goto err; | ||
845 | |||
846 | return ret; | ||
847 | err: | ||
848 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
849 | return ret; | ||
850 | } | ||
851 | |||
852 | static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
853 | { | ||
854 | int ret; | ||
855 | u8 gpio, sys0; | ||
856 | |||
857 | dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); | ||
858 | |||
859 | /* demod adc */ | ||
860 | ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0); | ||
861 | if (ret) | ||
862 | goto err; | ||
863 | |||
864 | /* tuner power, read GPIOs */ | ||
865 | ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); | ||
866 | if (ret) | ||
867 | goto err; | ||
868 | |||
869 | dev_dbg(&d->udev->dev, "%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, | ||
870 | sys0, gpio); | ||
871 | |||
872 | if (onoff) { | ||
873 | gpio |= 0x01; /* GPIO0 = 1 */ | ||
874 | gpio &= (~0x10); /* GPIO4 = 0 */ | ||
875 | gpio |= 0x04; /* GPIO2 = 1, LED on */ | ||
876 | sys0 = sys0 & 0x0f; | ||
877 | sys0 |= 0xe0; | ||
878 | } else { | ||
879 | gpio &= (~0x01); /* GPIO0 = 0 */ | ||
880 | gpio |= 0x10; /* GPIO4 = 1 */ | ||
881 | gpio &= (~0x04); /* GPIO2 = 1, LED off */ | ||
882 | sys0 = sys0 & (~0xc0); | ||
883 | } | ||
884 | |||
885 | dev_dbg(&d->udev->dev, "%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, | ||
886 | sys0, gpio); | ||
887 | |||
888 | /* demod adc */ | ||
889 | ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0); | ||
890 | if (ret) | ||
891 | goto err; | ||
892 | |||
893 | /* tuner power, write GPIOs */ | ||
894 | ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); | ||
895 | if (ret) | ||
896 | goto err; | ||
897 | |||
898 | return ret; | ||
899 | err: | ||
900 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
901 | return ret; | ||
902 | } | ||
903 | |||
904 | static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
905 | { | ||
906 | int ret; | ||
907 | u8 val; | ||
908 | |||
909 | dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); | ||
910 | |||
911 | if (onoff) { | ||
912 | /* set output values */ | ||
913 | ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); | ||
914 | if (ret) | ||
915 | goto err; | ||
916 | |||
917 | val |= 0x08; | ||
918 | val &= 0xef; | ||
919 | |||
920 | ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); | ||
921 | if (ret) | ||
922 | goto err; | ||
923 | |||
924 | /* demod_ctl_1 */ | ||
925 | ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); | ||
926 | if (ret) | ||
927 | goto err; | ||
928 | |||
929 | val &= 0xef; | ||
930 | |||
931 | ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); | ||
932 | if (ret) | ||
933 | goto err; | ||
934 | |||
935 | /* demod control */ | ||
936 | /* PLL enable */ | ||
937 | ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); | ||
938 | if (ret) | ||
939 | goto err; | ||
940 | |||
941 | /* bit 7 to 1 */ | ||
942 | val |= 0x80; | ||
943 | |||
944 | ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); | ||
945 | if (ret) | ||
946 | goto err; | ||
947 | |||
948 | /* demod HW reset */ | ||
949 | ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); | ||
950 | if (ret) | ||
951 | goto err; | ||
952 | /* bit 5 to 0 */ | ||
953 | val &= 0xdf; | ||
954 | |||
955 | ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); | ||
956 | if (ret) | ||
957 | goto err; | ||
958 | |||
959 | ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); | ||
960 | if (ret) | ||
961 | goto err; | ||
962 | |||
963 | val |= 0x20; | ||
964 | |||
965 | ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); | ||
966 | if (ret) | ||
967 | goto err; | ||
968 | |||
969 | mdelay(5); | ||
970 | |||
971 | /*enable ADC_Q and ADC_I */ | ||
972 | ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); | ||
973 | if (ret) | ||
974 | goto err; | ||
975 | |||
976 | val |= 0x48; | ||
977 | |||
978 | ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); | ||
979 | if (ret) | ||
980 | goto err; | ||
981 | |||
982 | |||
983 | } else { | ||
984 | /* demod_ctl_1 */ | ||
985 | ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); | ||
986 | if (ret) | ||
987 | goto err; | ||
988 | |||
989 | val |= 0x0c; | ||
990 | |||
991 | ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); | ||
992 | if (ret) | ||
993 | goto err; | ||
994 | |||
995 | /* set output values */ | ||
996 | ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); | ||
997 | if (ret) | ||
998 | goto err; | ||
999 | |||
1000 | val |= 0x10; | ||
1001 | |||
1002 | ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); | ||
1003 | if (ret) | ||
1004 | goto err; | ||
1005 | |||
1006 | /* demod control */ | ||
1007 | ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); | ||
1008 | if (ret) | ||
1009 | goto err; | ||
1010 | |||
1011 | val &= 0x37; | ||
1012 | |||
1013 | ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); | ||
1014 | if (ret) | ||
1015 | goto err; | ||
1016 | |||
1017 | } | ||
1018 | |||
1019 | return ret; | ||
1020 | err: | ||
1021 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
1022 | return ret; | ||
1023 | } | ||
1024 | |||
1025 | |||
1026 | static int rtl2831u_rc_query(struct dvb_usb_device *d) | ||
1027 | { | ||
1028 | int ret, i; | ||
1029 | struct rtl28xxu_priv *priv = d->priv; | ||
1030 | u8 buf[5]; | ||
1031 | u32 rc_code; | ||
1032 | struct rtl28xxu_reg_val rc_nec_tab[] = { | ||
1033 | { 0x3033, 0x80 }, | ||
1034 | { 0x3020, 0x43 }, | ||
1035 | { 0x3021, 0x16 }, | ||
1036 | { 0x3022, 0x16 }, | ||
1037 | { 0x3023, 0x5a }, | ||
1038 | { 0x3024, 0x2d }, | ||
1039 | { 0x3025, 0x16 }, | ||
1040 | { 0x3026, 0x01 }, | ||
1041 | { 0x3028, 0xb0 }, | ||
1042 | { 0x3029, 0x04 }, | ||
1043 | { 0x302c, 0x88 }, | ||
1044 | { 0x302e, 0x13 }, | ||
1045 | { 0x3030, 0xdf }, | ||
1046 | { 0x3031, 0x05 }, | ||
1047 | }; | ||
1048 | |||
1049 | /* init remote controller */ | ||
1050 | if (!priv->rc_active) { | ||
1051 | for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { | ||
1052 | ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, | ||
1053 | rc_nec_tab[i].val); | ||
1054 | if (ret) | ||
1055 | goto err; | ||
1056 | } | ||
1057 | priv->rc_active = true; | ||
1058 | } | ||
1059 | |||
1060 | ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5); | ||
1061 | if (ret) | ||
1062 | goto err; | ||
1063 | |||
1064 | if (buf[4] & 0x01) { | ||
1065 | if (buf[2] == (u8) ~buf[3]) { | ||
1066 | if (buf[0] == (u8) ~buf[1]) { | ||
1067 | /* NEC standard (16 bit) */ | ||
1068 | rc_code = buf[0] << 8 | buf[2]; | ||
1069 | } else { | ||
1070 | /* NEC extended (24 bit) */ | ||
1071 | rc_code = buf[0] << 16 | | ||
1072 | buf[1] << 8 | buf[2]; | ||
1073 | } | ||
1074 | } else { | ||
1075 | /* NEC full (32 bit) */ | ||
1076 | rc_code = buf[0] << 24 | buf[1] << 16 | | ||
1077 | buf[2] << 8 | buf[3]; | ||
1078 | } | ||
1079 | |||
1080 | rc_keydown(d->rc_dev, rc_code, 0); | ||
1081 | |||
1082 | ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1); | ||
1083 | if (ret) | ||
1084 | goto err; | ||
1085 | |||
1086 | /* repeated intentionally to avoid extra keypress */ | ||
1087 | ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1); | ||
1088 | if (ret) | ||
1089 | goto err; | ||
1090 | } | ||
1091 | |||
1092 | return ret; | ||
1093 | err: | ||
1094 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
1095 | return ret; | ||
1096 | } | ||
1097 | |||
1098 | static int rtl2831u_get_rc_config(struct dvb_usb_device *d, | ||
1099 | struct dvb_usb_rc *rc) | ||
1100 | { | ||
1101 | rc->map_name = RC_MAP_EMPTY; | ||
1102 | rc->allowed_protos = RC_TYPE_NEC; | ||
1103 | rc->query = rtl2831u_rc_query; | ||
1104 | rc->interval = 400; | ||
1105 | |||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | static int rtl2832u_rc_query(struct dvb_usb_device *d) | ||
1110 | { | ||
1111 | int ret, i; | ||
1112 | struct rtl28xxu_priv *priv = d->priv; | ||
1113 | u8 buf[128]; | ||
1114 | int len; | ||
1115 | struct rtl28xxu_reg_val rc_nec_tab[] = { | ||
1116 | { IR_RX_CTRL, 0x20 }, | ||
1117 | { IR_RX_BUF_CTRL, 0x80 }, | ||
1118 | { IR_RX_IF, 0xff }, | ||
1119 | { IR_RX_IE, 0xff }, | ||
1120 | { IR_MAX_DURATION0, 0xd0 }, | ||
1121 | { IR_MAX_DURATION1, 0x07 }, | ||
1122 | { IR_IDLE_LEN0, 0xc0 }, | ||
1123 | { IR_IDLE_LEN1, 0x00 }, | ||
1124 | { IR_GLITCH_LEN, 0x03 }, | ||
1125 | { IR_RX_CLK, 0x09 }, | ||
1126 | { IR_RX_CFG, 0x1c }, | ||
1127 | { IR_MAX_H_TOL_LEN, 0x1e }, | ||
1128 | { IR_MAX_L_TOL_LEN, 0x1e }, | ||
1129 | { IR_RX_CTRL, 0x80 }, | ||
1130 | }; | ||
1131 | |||
1132 | /* init remote controller */ | ||
1133 | if (!priv->rc_active) { | ||
1134 | for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { | ||
1135 | ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, | ||
1136 | rc_nec_tab[i].val); | ||
1137 | if (ret) | ||
1138 | goto err; | ||
1139 | } | ||
1140 | priv->rc_active = true; | ||
1141 | } | ||
1142 | |||
1143 | ret = rtl28xx_rd_reg(d, IR_RX_IF, &buf[0]); | ||
1144 | if (ret) | ||
1145 | goto err; | ||
1146 | |||
1147 | if (buf[0] != 0x83) | ||
1148 | goto exit; | ||
1149 | |||
1150 | ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]); | ||
1151 | if (ret) | ||
1152 | goto err; | ||
1153 | |||
1154 | len = buf[0]; | ||
1155 | ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); | ||
1156 | |||
1157 | /* TODO: pass raw IR to Kernel IR decoder */ | ||
1158 | |||
1159 | ret = rtl28xx_wr_reg(d, IR_RX_IF, 0x03); | ||
1160 | ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80); | ||
1161 | ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80); | ||
1162 | |||
1163 | exit: | ||
1164 | return ret; | ||
1165 | err: | ||
1166 | dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
1167 | return ret; | ||
1168 | } | ||
1169 | |||
1170 | static int rtl2832u_get_rc_config(struct dvb_usb_device *d, | ||
1171 | struct dvb_usb_rc *rc) | ||
1172 | { | ||
1173 | rc->map_name = RC_MAP_EMPTY; | ||
1174 | rc->allowed_protos = RC_TYPE_NEC; | ||
1175 | rc->query = rtl2832u_rc_query; | ||
1176 | rc->interval = 400; | ||
1177 | |||
1178 | return 0; | ||
1179 | } | ||
1180 | |||
1181 | static const struct dvb_usb_device_properties rtl2831u_props = { | ||
1182 | .driver_name = KBUILD_MODNAME, | ||
1183 | .owner = THIS_MODULE, | ||
1184 | .adapter_nr = adapter_nr, | ||
1185 | .size_of_priv = sizeof(struct rtl28xxu_priv), | ||
1186 | |||
1187 | .power_ctrl = rtl2831u_power_ctrl, | ||
1188 | .i2c_algo = &rtl28xxu_i2c_algo, | ||
1189 | .frontend_attach = rtl2831u_frontend_attach, | ||
1190 | .tuner_attach = rtl2831u_tuner_attach, | ||
1191 | .init = rtl28xxu_init, | ||
1192 | .get_rc_config = rtl2831u_get_rc_config, | ||
1193 | .streaming_ctrl = rtl28xxu_streaming_ctrl, | ||
1194 | |||
1195 | .num_adapters = 1, | ||
1196 | .adapter = { | ||
1197 | { | ||
1198 | .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), | ||
1199 | }, | ||
1200 | }, | ||
1201 | }; | ||
1202 | |||
1203 | static const struct dvb_usb_device_properties rtl2832u_props = { | ||
1204 | .driver_name = KBUILD_MODNAME, | ||
1205 | .owner = THIS_MODULE, | ||
1206 | .adapter_nr = adapter_nr, | ||
1207 | .size_of_priv = sizeof(struct rtl28xxu_priv), | ||
1208 | |||
1209 | .power_ctrl = rtl2832u_power_ctrl, | ||
1210 | .i2c_algo = &rtl28xxu_i2c_algo, | ||
1211 | .frontend_attach = rtl2832u_frontend_attach, | ||
1212 | .tuner_attach = rtl2832u_tuner_attach, | ||
1213 | .init = rtl28xxu_init, | ||
1214 | .get_rc_config = rtl2832u_get_rc_config, | ||
1215 | .streaming_ctrl = rtl28xxu_streaming_ctrl, | ||
1216 | |||
1217 | .num_adapters = 1, | ||
1218 | .adapter = { | ||
1219 | { | ||
1220 | .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512), | ||
1221 | }, | ||
1222 | }, | ||
1223 | }; | ||
1224 | |||
1225 | static const struct usb_device_id rtl28xxu_id_table[] = { | ||
1226 | { DVB_USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U, | ||
1227 | &rtl2831u_props, "Realtek RTL2831U reference design", NULL) }, | ||
1228 | { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT, | ||
1229 | &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) }, | ||
1230 | { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2, | ||
1231 | &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) }, | ||
1232 | |||
1233 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1, | ||
1234 | &rtl2832u_props, "Terratec Cinergy T Stick Black", NULL) }, | ||
1235 | { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT, | ||
1236 | &rtl2832u_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) }, | ||
1237 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK, | ||
1238 | &rtl2832u_props, "NOXON DAB/DAB+ USB dongle", NULL) }, | ||
1239 | { } | ||
1240 | }; | ||
1241 | MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); | ||
1242 | |||
1243 | static struct usb_driver rtl28xxu_usb_driver = { | ||
1244 | .name = KBUILD_MODNAME, | ||
1245 | .id_table = rtl28xxu_id_table, | ||
1246 | .probe = dvb_usbv2_probe, | ||
1247 | .disconnect = dvb_usbv2_disconnect, | ||
1248 | .suspend = dvb_usbv2_suspend, | ||
1249 | .resume = dvb_usbv2_resume, | ||
1250 | .no_dynamic_id = 1, | ||
1251 | .soft_unbind = 1, | ||
1252 | }; | ||
1253 | |||
1254 | module_usb_driver(rtl28xxu_usb_driver); | ||
1255 | |||
1256 | MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver"); | ||
1257 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
1258 | MODULE_AUTHOR("Thomas Mair <thomas.mair86@googlemail.com>"); | ||
1259 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h new file mode 100644 index 000000000000..575edbf13a92 --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h | |||
@@ -0,0 +1,254 @@ | |||
1 | /* | ||
2 | * Realtek RTL28xxU DVB USB driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> | ||
5 | * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | ||
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 along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef RTL28XXU_H | ||
23 | #define RTL28XXU_H | ||
24 | |||
25 | #include "dvb_usb.h" | ||
26 | |||
27 | #define deb_dump(r, t, v, i, b, l) { \ | ||
28 | char *direction; \ | ||
29 | if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \ | ||
30 | direction = ">>>"; \ | ||
31 | else \ | ||
32 | direction = "<<<"; \ | ||
33 | dev_dbg(&d->udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \ | ||
34 | "%s [%d bytes]\n", __func__, t, r, v & 0xff, v >> 8, \ | ||
35 | i & 0xff, i >> 8, l & 0xff, l >> 8, direction, l); \ | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * USB commands | ||
40 | * (usb_control_msg() index parameter) | ||
41 | */ | ||
42 | |||
43 | #define DEMOD 0x0000 | ||
44 | #define USB 0x0100 | ||
45 | #define SYS 0x0200 | ||
46 | #define I2C 0x0300 | ||
47 | #define I2C_DA 0x0600 | ||
48 | |||
49 | #define CMD_WR_FLAG 0x0010 | ||
50 | #define CMD_DEMOD_RD 0x0000 | ||
51 | #define CMD_DEMOD_WR 0x0010 | ||
52 | #define CMD_USB_RD 0x0100 | ||
53 | #define CMD_USB_WR 0x0110 | ||
54 | #define CMD_SYS_RD 0x0200 | ||
55 | #define CMD_IR_RD 0x0201 | ||
56 | #define CMD_IR_WR 0x0211 | ||
57 | #define CMD_SYS_WR 0x0210 | ||
58 | #define CMD_I2C_RD 0x0300 | ||
59 | #define CMD_I2C_WR 0x0310 | ||
60 | #define CMD_I2C_DA_RD 0x0600 | ||
61 | #define CMD_I2C_DA_WR 0x0610 | ||
62 | |||
63 | |||
64 | struct rtl28xxu_priv { | ||
65 | u8 chip_id; | ||
66 | u8 tuner; | ||
67 | u8 page; /* integrated demod active register page */ | ||
68 | bool rc_active; | ||
69 | }; | ||
70 | |||
71 | enum rtl28xxu_chip_id { | ||
72 | CHIP_ID_NONE, | ||
73 | CHIP_ID_RTL2831U, | ||
74 | CHIP_ID_RTL2832U, | ||
75 | }; | ||
76 | |||
77 | enum rtl28xxu_tuner { | ||
78 | TUNER_NONE, | ||
79 | |||
80 | TUNER_RTL2830_QT1010, | ||
81 | TUNER_RTL2830_MT2060, | ||
82 | TUNER_RTL2830_MXL5005S, | ||
83 | |||
84 | TUNER_RTL2832_MT2266, | ||
85 | TUNER_RTL2832_FC2580, | ||
86 | TUNER_RTL2832_MT2063, | ||
87 | TUNER_RTL2832_MAX3543, | ||
88 | TUNER_RTL2832_TUA9001, | ||
89 | TUNER_RTL2832_MXL5007T, | ||
90 | TUNER_RTL2832_FC0012, | ||
91 | TUNER_RTL2832_E4000, | ||
92 | TUNER_RTL2832_TDA18272, | ||
93 | TUNER_RTL2832_FC0013, | ||
94 | }; | ||
95 | |||
96 | struct rtl28xxu_req { | ||
97 | u16 value; | ||
98 | u16 index; | ||
99 | u16 size; | ||
100 | u8 *data; | ||
101 | }; | ||
102 | |||
103 | struct rtl28xxu_reg_val { | ||
104 | u16 reg; | ||
105 | u8 val; | ||
106 | }; | ||
107 | |||
108 | /* | ||
109 | * memory map | ||
110 | * | ||
111 | * 0x0000 DEMOD : demodulator | ||
112 | * 0x2000 USB : SIE, USB endpoint, debug, DMA | ||
113 | * 0x3000 SYS : system | ||
114 | * 0xfc00 RC : remote controller (not RTL2831U) | ||
115 | */ | ||
116 | |||
117 | /* | ||
118 | * USB registers | ||
119 | */ | ||
120 | /* SIE Control Registers */ | ||
121 | #define USB_SYSCTL 0x2000 /* USB system control */ | ||
122 | #define USB_SYSCTL_0 0x2000 /* USB system control */ | ||
123 | #define USB_SYSCTL_1 0x2001 /* USB system control */ | ||
124 | #define USB_SYSCTL_2 0x2002 /* USB system control */ | ||
125 | #define USB_SYSCTL_3 0x2003 /* USB system control */ | ||
126 | #define USB_IRQSTAT 0x2008 /* SIE interrupt status */ | ||
127 | #define USB_IRQEN 0x200C /* SIE interrupt enable */ | ||
128 | #define USB_CTRL 0x2010 /* USB control */ | ||
129 | #define USB_STAT 0x2014 /* USB status */ | ||
130 | #define USB_DEVADDR 0x2018 /* USB device address */ | ||
131 | #define USB_TEST 0x201C /* USB test mode */ | ||
132 | #define USB_FRAME_NUMBER 0x2020 /* frame number */ | ||
133 | #define USB_FIFO_ADDR 0x2028 /* address of SIE FIFO RAM */ | ||
134 | #define USB_FIFO_CMD 0x202A /* SIE FIFO RAM access command */ | ||
135 | #define USB_FIFO_DATA 0x2030 /* SIE FIFO RAM data */ | ||
136 | /* Endpoint Registers */ | ||
137 | #define EP0_SETUPA 0x20F8 /* EP 0 setup packet lower byte */ | ||
138 | #define EP0_SETUPB 0x20FC /* EP 0 setup packet higher byte */ | ||
139 | #define USB_EP0_CFG 0x2104 /* EP 0 configure */ | ||
140 | #define USB_EP0_CTL 0x2108 /* EP 0 control */ | ||
141 | #define USB_EP0_STAT 0x210C /* EP 0 status */ | ||
142 | #define USB_EP0_IRQSTAT 0x2110 /* EP 0 interrupt status */ | ||
143 | #define USB_EP0_IRQEN 0x2114 /* EP 0 interrupt enable */ | ||
144 | #define USB_EP0_MAXPKT 0x2118 /* EP 0 max packet size */ | ||
145 | #define USB_EP0_BC 0x2120 /* EP 0 FIFO byte counter */ | ||
146 | #define USB_EPA_CFG 0x2144 /* EP A configure */ | ||
147 | #define USB_EPA_CFG_0 0x2144 /* EP A configure */ | ||
148 | #define USB_EPA_CFG_1 0x2145 /* EP A configure */ | ||
149 | #define USB_EPA_CFG_2 0x2146 /* EP A configure */ | ||
150 | #define USB_EPA_CFG_3 0x2147 /* EP A configure */ | ||
151 | #define USB_EPA_CTL 0x2148 /* EP A control */ | ||
152 | #define USB_EPA_CTL_0 0x2148 /* EP A control */ | ||
153 | #define USB_EPA_CTL_1 0x2149 /* EP A control */ | ||
154 | #define USB_EPA_CTL_2 0x214A /* EP A control */ | ||
155 | #define USB_EPA_CTL_3 0x214B /* EP A control */ | ||
156 | #define USB_EPA_STAT 0x214C /* EP A status */ | ||
157 | #define USB_EPA_IRQSTAT 0x2150 /* EP A interrupt status */ | ||
158 | #define USB_EPA_IRQEN 0x2154 /* EP A interrupt enable */ | ||
159 | #define USB_EPA_MAXPKT 0x2158 /* EP A max packet size */ | ||
160 | #define USB_EPA_MAXPKT_0 0x2158 /* EP A max packet size */ | ||
161 | #define USB_EPA_MAXPKT_1 0x2159 /* EP A max packet size */ | ||
162 | #define USB_EPA_MAXPKT_2 0x215A /* EP A max packet size */ | ||
163 | #define USB_EPA_MAXPKT_3 0x215B /* EP A max packet size */ | ||
164 | #define USB_EPA_FIFO_CFG 0x2160 /* EP A FIFO configure */ | ||
165 | #define USB_EPA_FIFO_CFG_0 0x2160 /* EP A FIFO configure */ | ||
166 | #define USB_EPA_FIFO_CFG_1 0x2161 /* EP A FIFO configure */ | ||
167 | #define USB_EPA_FIFO_CFG_2 0x2162 /* EP A FIFO configure */ | ||
168 | #define USB_EPA_FIFO_CFG_3 0x2163 /* EP A FIFO configure */ | ||
169 | /* Debug Registers */ | ||
170 | #define USB_PHYTSTDIS 0x2F04 /* PHY test disable */ | ||
171 | #define USB_TOUT_VAL 0x2F08 /* USB time-out time */ | ||
172 | #define USB_VDRCTRL 0x2F10 /* UTMI vendor signal control */ | ||
173 | #define USB_VSTAIN 0x2F14 /* UTMI vendor signal status in */ | ||
174 | #define USB_VLOADM 0x2F18 /* UTMI load vendor signal status in */ | ||
175 | #define USB_VSTAOUT 0x2F1C /* UTMI vendor signal status out */ | ||
176 | #define USB_UTMI_TST 0x2F80 /* UTMI test */ | ||
177 | #define USB_UTMI_STATUS 0x2F84 /* UTMI status */ | ||
178 | #define USB_TSTCTL 0x2F88 /* test control */ | ||
179 | #define USB_TSTCTL2 0x2F8C /* test control 2 */ | ||
180 | #define USB_PID_FORCE 0x2F90 /* force PID */ | ||
181 | #define USB_PKTERR_CNT 0x2F94 /* packet error counter */ | ||
182 | #define USB_RXERR_CNT 0x2F98 /* RX error counter */ | ||
183 | #define USB_MEM_BIST 0x2F9C /* MEM BIST test */ | ||
184 | #define USB_SLBBIST 0x2FA0 /* self-loop-back BIST */ | ||
185 | #define USB_CNTTEST 0x2FA4 /* counter test */ | ||
186 | #define USB_PHYTST 0x2FC0 /* USB PHY test */ | ||
187 | #define USB_DBGIDX 0x2FF0 /* select individual block debug signal */ | ||
188 | #define USB_DBGMUX 0x2FF4 /* debug signal module mux */ | ||
189 | |||
190 | /* | ||
191 | * SYS registers | ||
192 | */ | ||
193 | /* demod control registers */ | ||
194 | #define SYS_SYS0 0x3000 /* include DEMOD_CTL, GPO, GPI, GPOE */ | ||
195 | #define SYS_DEMOD_CTL 0x3000 /* control register for DVB-T demodulator */ | ||
196 | /* GPIO registers */ | ||
197 | #define SYS_GPIO_OUT_VAL 0x3001 /* output value of GPIO */ | ||
198 | #define SYS_GPIO_IN_VAL 0x3002 /* input value of GPIO */ | ||
199 | #define SYS_GPIO_OUT_EN 0x3003 /* output enable of GPIO */ | ||
200 | #define SYS_SYS1 0x3004 /* include GPD, SYSINTE, SYSINTS, GP_CFG0 */ | ||
201 | #define SYS_GPIO_DIR 0x3004 /* direction control for GPIO */ | ||
202 | #define SYS_SYSINTE 0x3005 /* system interrupt enable */ | ||
203 | #define SYS_SYSINTS 0x3006 /* system interrupt status */ | ||
204 | #define SYS_GPIO_CFG0 0x3007 /* PAD configuration for GPIO0-GPIO3 */ | ||
205 | #define SYS_SYS2 0x3008 /* include GP_CFG1 and 3 reserved bytes */ | ||
206 | #define SYS_GPIO_CFG1 0x3008 /* PAD configuration for GPIO4 */ | ||
207 | #define SYS_DEMOD_CTL1 0x300B | ||
208 | |||
209 | /* IrDA registers */ | ||
210 | #define SYS_IRRC_PSR 0x3020 /* IR protocol selection */ | ||
211 | #define SYS_IRRC_PER 0x3024 /* IR protocol extension */ | ||
212 | #define SYS_IRRC_SF 0x3028 /* IR sampling frequency */ | ||
213 | #define SYS_IRRC_DPIR 0x302C /* IR data package interval */ | ||
214 | #define SYS_IRRC_CR 0x3030 /* IR control */ | ||
215 | #define SYS_IRRC_RP 0x3034 /* IR read port */ | ||
216 | #define SYS_IRRC_SR 0x3038 /* IR status */ | ||
217 | /* I2C master registers */ | ||
218 | #define SYS_I2CCR 0x3040 /* I2C clock */ | ||
219 | #define SYS_I2CMCR 0x3044 /* I2C master control */ | ||
220 | #define SYS_I2CMSTR 0x3048 /* I2C master SCL timing */ | ||
221 | #define SYS_I2CMSR 0x304C /* I2C master status */ | ||
222 | #define SYS_I2CMFR 0x3050 /* I2C master FIFO */ | ||
223 | |||
224 | /* | ||
225 | * IR registers | ||
226 | */ | ||
227 | #define IR_RX_BUF 0xFC00 | ||
228 | #define IR_RX_IE 0xFD00 | ||
229 | #define IR_RX_IF 0xFD01 | ||
230 | #define IR_RX_CTRL 0xFD02 | ||
231 | #define IR_RX_CFG 0xFD03 | ||
232 | #define IR_MAX_DURATION0 0xFD04 | ||
233 | #define IR_MAX_DURATION1 0xFD05 | ||
234 | #define IR_IDLE_LEN0 0xFD06 | ||
235 | #define IR_IDLE_LEN1 0xFD07 | ||
236 | #define IR_GLITCH_LEN 0xFD08 | ||
237 | #define IR_RX_BUF_CTRL 0xFD09 | ||
238 | #define IR_RX_BUF_DATA 0xFD0A | ||
239 | #define IR_RX_BC 0xFD0B | ||
240 | #define IR_RX_CLK 0xFD0C | ||
241 | #define IR_RX_C_COUNT_L 0xFD0D | ||
242 | #define IR_RX_C_COUNT_H 0xFD0E | ||
243 | #define IR_SUSPEND_CTRL 0xFD10 | ||
244 | #define IR_ERR_TOL_CTRL 0xFD11 | ||
245 | #define IR_UNIT_LEN 0xFD12 | ||
246 | #define IR_ERR_TOL_LEN 0xFD13 | ||
247 | #define IR_MAX_H_TOL_LEN 0xFD14 | ||
248 | #define IR_MAX_L_TOL_LEN 0xFD15 | ||
249 | #define IR_MASK_CTRL 0xFD16 | ||
250 | #define IR_MASK_DATA 0xFD17 | ||
251 | #define IR_RES_MASK_ADDR 0xFD18 | ||
252 | #define IR_RES_MASK_T_LEN 0xFD19 | ||
253 | |||
254 | #endif | ||
diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c b/drivers/media/usb/dvb-usb-v2/usb_urb.c new file mode 100644 index 000000000000..eaf673a3978d --- /dev/null +++ b/drivers/media/usb/dvb-usb-v2/usb_urb.c | |||
@@ -0,0 +1,357 @@ | |||
1 | /* usb-urb.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file keeps functions for initializing and handling the | ||
7 | * BULK and ISOC USB data transfers in a generic way. | ||
8 | * Can be used for DVB-only and also, that's the plan, for | ||
9 | * Hybrid USB devices (analog and DVB). | ||
10 | */ | ||
11 | #include "dvb_usb_common.h" | ||
12 | |||
13 | /* URB stuff for streaming */ | ||
14 | |||
15 | int usb_urb_reconfig(struct usb_data_stream *stream, | ||
16 | struct usb_data_stream_properties *props); | ||
17 | |||
18 | static void usb_urb_complete(struct urb *urb) | ||
19 | { | ||
20 | struct usb_data_stream *stream = urb->context; | ||
21 | int ptype = usb_pipetype(urb->pipe); | ||
22 | int i; | ||
23 | u8 *b; | ||
24 | |||
25 | dev_dbg(&stream->udev->dev, "%s: %s urb completed status=%d " \ | ||
26 | "length=%d/%d pack_num=%d errors=%d\n", __func__, | ||
27 | ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk", | ||
28 | urb->status, urb->actual_length, | ||
29 | urb->transfer_buffer_length, | ||
30 | urb->number_of_packets, urb->error_count); | ||
31 | |||
32 | switch (urb->status) { | ||
33 | case 0: /* success */ | ||
34 | case -ETIMEDOUT: /* NAK */ | ||
35 | break; | ||
36 | case -ECONNRESET: /* kill */ | ||
37 | case -ENOENT: | ||
38 | case -ESHUTDOWN: | ||
39 | return; | ||
40 | default: /* error */ | ||
41 | dev_dbg(&stream->udev->dev, "%s: urb completition failed=%d\n", | ||
42 | __func__, urb->status); | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | b = (u8 *) urb->transfer_buffer; | ||
47 | switch (ptype) { | ||
48 | case PIPE_ISOCHRONOUS: | ||
49 | for (i = 0; i < urb->number_of_packets; i++) { | ||
50 | if (urb->iso_frame_desc[i].status != 0) | ||
51 | dev_dbg(&stream->udev->dev, "%s: iso frame " \ | ||
52 | "descriptor has an error=%d\n", | ||
53 | __func__, | ||
54 | urb->iso_frame_desc[i].status); | ||
55 | else if (urb->iso_frame_desc[i].actual_length > 0) | ||
56 | stream->complete(stream, | ||
57 | b + urb->iso_frame_desc[i].offset, | ||
58 | urb->iso_frame_desc[i].actual_length); | ||
59 | |||
60 | urb->iso_frame_desc[i].status = 0; | ||
61 | urb->iso_frame_desc[i].actual_length = 0; | ||
62 | } | ||
63 | break; | ||
64 | case PIPE_BULK: | ||
65 | if (urb->actual_length > 0) | ||
66 | stream->complete(stream, b, urb->actual_length); | ||
67 | break; | ||
68 | default: | ||
69 | dev_err(&stream->udev->dev, "%s: unknown endpoint type in " \ | ||
70 | "completition handler\n", KBUILD_MODNAME); | ||
71 | return; | ||
72 | } | ||
73 | usb_submit_urb(urb, GFP_ATOMIC); | ||
74 | } | ||
75 | |||
76 | int usb_urb_killv2(struct usb_data_stream *stream) | ||
77 | { | ||
78 | int i; | ||
79 | for (i = 0; i < stream->urbs_submitted; i++) { | ||
80 | dev_dbg(&stream->udev->dev, "%s: kill urb=%d\n", __func__, i); | ||
81 | /* stop the URB */ | ||
82 | usb_kill_urb(stream->urb_list[i]); | ||
83 | } | ||
84 | stream->urbs_submitted = 0; | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | int usb_urb_submitv2(struct usb_data_stream *stream, | ||
89 | struct usb_data_stream_properties *props) | ||
90 | { | ||
91 | int i, ret; | ||
92 | |||
93 | if (props) { | ||
94 | ret = usb_urb_reconfig(stream, props); | ||
95 | if (ret < 0) | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | for (i = 0; i < stream->urbs_initialized; i++) { | ||
100 | dev_dbg(&stream->udev->dev, "%s: submit urb=%d\n", __func__, i); | ||
101 | ret = usb_submit_urb(stream->urb_list[i], GFP_ATOMIC); | ||
102 | if (ret) { | ||
103 | dev_err(&stream->udev->dev, "%s: could not submit " \ | ||
104 | "urb no. %d - get them all back\n", | ||
105 | KBUILD_MODNAME, i); | ||
106 | usb_urb_killv2(stream); | ||
107 | return ret; | ||
108 | } | ||
109 | stream->urbs_submitted++; | ||
110 | } | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | int usb_urb_free_urbs(struct usb_data_stream *stream) | ||
115 | { | ||
116 | int i; | ||
117 | |||
118 | usb_urb_killv2(stream); | ||
119 | |||
120 | for (i = stream->urbs_initialized - 1; i >= 0; i--) { | ||
121 | if (stream->urb_list[i]) { | ||
122 | dev_dbg(&stream->udev->dev, "%s: free urb=%d\n", | ||
123 | __func__, i); | ||
124 | /* free the URBs */ | ||
125 | usb_free_urb(stream->urb_list[i]); | ||
126 | } | ||
127 | } | ||
128 | stream->urbs_initialized = 0; | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int usb_urb_alloc_bulk_urbs(struct usb_data_stream *stream) | ||
134 | { | ||
135 | int i, j; | ||
136 | |||
137 | /* allocate the URBs */ | ||
138 | for (i = 0; i < stream->props.count; i++) { | ||
139 | dev_dbg(&stream->udev->dev, "%s: alloc urb=%d\n", __func__, i); | ||
140 | stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); | ||
141 | if (!stream->urb_list[i]) { | ||
142 | dev_dbg(&stream->udev->dev, "%s: failed\n", __func__); | ||
143 | for (j = 0; j < i; j++) | ||
144 | usb_free_urb(stream->urb_list[j]); | ||
145 | return -ENOMEM; | ||
146 | } | ||
147 | usb_fill_bulk_urb(stream->urb_list[i], | ||
148 | stream->udev, | ||
149 | usb_rcvbulkpipe(stream->udev, | ||
150 | stream->props.endpoint), | ||
151 | stream->buf_list[i], | ||
152 | stream->props.u.bulk.buffersize, | ||
153 | usb_urb_complete, stream); | ||
154 | |||
155 | stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
156 | stream->urb_list[i]->transfer_dma = stream->dma_addr[i]; | ||
157 | stream->urbs_initialized++; | ||
158 | } | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream) | ||
163 | { | ||
164 | int i, j; | ||
165 | |||
166 | /* allocate the URBs */ | ||
167 | for (i = 0; i < stream->props.count; i++) { | ||
168 | struct urb *urb; | ||
169 | int frame_offset = 0; | ||
170 | dev_dbg(&stream->udev->dev, "%s: alloc urb=%d\n", __func__, i); | ||
171 | stream->urb_list[i] = usb_alloc_urb( | ||
172 | stream->props.u.isoc.framesperurb, GFP_ATOMIC); | ||
173 | if (!stream->urb_list[i]) { | ||
174 | dev_dbg(&stream->udev->dev, "%s: failed\n", __func__); | ||
175 | for (j = 0; j < i; j++) | ||
176 | usb_free_urb(stream->urb_list[j]); | ||
177 | return -ENOMEM; | ||
178 | } | ||
179 | |||
180 | urb = stream->urb_list[i]; | ||
181 | |||
182 | urb->dev = stream->udev; | ||
183 | urb->context = stream; | ||
184 | urb->complete = usb_urb_complete; | ||
185 | urb->pipe = usb_rcvisocpipe(stream->udev, | ||
186 | stream->props.endpoint); | ||
187 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
188 | urb->interval = stream->props.u.isoc.interval; | ||
189 | urb->number_of_packets = stream->props.u.isoc.framesperurb; | ||
190 | urb->transfer_buffer_length = stream->props.u.isoc.framesize * | ||
191 | stream->props.u.isoc.framesperurb; | ||
192 | urb->transfer_buffer = stream->buf_list[i]; | ||
193 | urb->transfer_dma = stream->dma_addr[i]; | ||
194 | |||
195 | for (j = 0; j < stream->props.u.isoc.framesperurb; j++) { | ||
196 | urb->iso_frame_desc[j].offset = frame_offset; | ||
197 | urb->iso_frame_desc[j].length = | ||
198 | stream->props.u.isoc.framesize; | ||
199 | frame_offset += stream->props.u.isoc.framesize; | ||
200 | } | ||
201 | |||
202 | stream->urbs_initialized++; | ||
203 | } | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | int usb_free_stream_buffers(struct usb_data_stream *stream) | ||
208 | { | ||
209 | if (stream->state & USB_STATE_URB_BUF) { | ||
210 | while (stream->buf_num) { | ||
211 | stream->buf_num--; | ||
212 | dev_dbg(&stream->udev->dev, "%s: free buf=%d\n", | ||
213 | __func__, stream->buf_num); | ||
214 | usb_free_coherent(stream->udev, stream->buf_size, | ||
215 | stream->buf_list[stream->buf_num], | ||
216 | stream->dma_addr[stream->buf_num]); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | stream->state &= ~USB_STATE_URB_BUF; | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num, | ||
226 | unsigned long size) | ||
227 | { | ||
228 | stream->buf_num = 0; | ||
229 | stream->buf_size = size; | ||
230 | |||
231 | dev_dbg(&stream->udev->dev, "%s: all in all I will use %lu bytes for " \ | ||
232 | "streaming\n", __func__, num * size); | ||
233 | |||
234 | for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) { | ||
235 | stream->buf_list[stream->buf_num] = usb_alloc_coherent( | ||
236 | stream->udev, size, GFP_ATOMIC, | ||
237 | &stream->dma_addr[stream->buf_num]); | ||
238 | if (!stream->buf_list[stream->buf_num]) { | ||
239 | dev_dbg(&stream->udev->dev, "%s: alloc buf=%d failed\n", | ||
240 | __func__, stream->buf_num); | ||
241 | usb_free_stream_buffers(stream); | ||
242 | return -ENOMEM; | ||
243 | } | ||
244 | |||
245 | dev_dbg(&stream->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n", | ||
246 | __func__, stream->buf_num, | ||
247 | stream->buf_list[stream->buf_num], | ||
248 | (long long)stream->dma_addr[stream->buf_num]); | ||
249 | memset(stream->buf_list[stream->buf_num], 0, size); | ||
250 | stream->state |= USB_STATE_URB_BUF; | ||
251 | } | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | int usb_urb_reconfig(struct usb_data_stream *stream, | ||
257 | struct usb_data_stream_properties *props) | ||
258 | { | ||
259 | int buf_size; | ||
260 | |||
261 | if (!props) | ||
262 | return 0; | ||
263 | |||
264 | /* check allocated buffers are large enough for the request */ | ||
265 | if (props->type == USB_BULK) { | ||
266 | buf_size = stream->props.u.bulk.buffersize; | ||
267 | } else if (props->type == USB_ISOC) { | ||
268 | buf_size = props->u.isoc.framesize * props->u.isoc.framesperurb; | ||
269 | } else { | ||
270 | dev_err(&stream->udev->dev, "%s: invalid endpoint type=%d\n", | ||
271 | KBUILD_MODNAME, props->type); | ||
272 | return -EINVAL; | ||
273 | } | ||
274 | |||
275 | if (stream->buf_num < props->count || stream->buf_size < buf_size) { | ||
276 | dev_err(&stream->udev->dev, "%s: cannot reconfigure as " \ | ||
277 | "allocated buffers are too small\n", | ||
278 | KBUILD_MODNAME); | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | |||
282 | /* check if all fields are same */ | ||
283 | if (stream->props.type == props->type && | ||
284 | stream->props.count == props->count && | ||
285 | stream->props.endpoint == props->endpoint) { | ||
286 | if (props->type == USB_BULK && | ||
287 | props->u.bulk.buffersize == | ||
288 | stream->props.u.bulk.buffersize) | ||
289 | return 0; | ||
290 | else if (props->type == USB_ISOC && | ||
291 | props->u.isoc.framesperurb == | ||
292 | stream->props.u.isoc.framesperurb && | ||
293 | props->u.isoc.framesize == | ||
294 | stream->props.u.isoc.framesize && | ||
295 | props->u.isoc.interval == | ||
296 | stream->props.u.isoc.interval) | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | dev_dbg(&stream->udev->dev, "%s: re-alloc urbs\n", __func__); | ||
301 | |||
302 | usb_urb_free_urbs(stream); | ||
303 | memcpy(&stream->props, props, sizeof(*props)); | ||
304 | if (props->type == USB_BULK) | ||
305 | return usb_urb_alloc_bulk_urbs(stream); | ||
306 | else if (props->type == USB_ISOC) | ||
307 | return usb_urb_alloc_isoc_urbs(stream); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | int usb_urb_initv2(struct usb_data_stream *stream, | ||
313 | const struct usb_data_stream_properties *props) | ||
314 | { | ||
315 | int ret; | ||
316 | |||
317 | if (!stream || !props) | ||
318 | return -EINVAL; | ||
319 | |||
320 | memcpy(&stream->props, props, sizeof(*props)); | ||
321 | |||
322 | if (!stream->complete) { | ||
323 | dev_err(&stream->udev->dev, "%s: there is no data callback - " \ | ||
324 | "this doesn't make sense\n", KBUILD_MODNAME); | ||
325 | return -EINVAL; | ||
326 | } | ||
327 | |||
328 | switch (stream->props.type) { | ||
329 | case USB_BULK: | ||
330 | ret = usb_alloc_stream_buffers(stream, stream->props.count, | ||
331 | stream->props.u.bulk.buffersize); | ||
332 | if (ret < 0) | ||
333 | return ret; | ||
334 | |||
335 | return usb_urb_alloc_bulk_urbs(stream); | ||
336 | case USB_ISOC: | ||
337 | ret = usb_alloc_stream_buffers(stream, stream->props.count, | ||
338 | stream->props.u.isoc.framesize * | ||
339 | stream->props.u.isoc.framesperurb); | ||
340 | if (ret < 0) | ||
341 | return ret; | ||
342 | |||
343 | return usb_urb_alloc_isoc_urbs(stream); | ||
344 | default: | ||
345 | dev_err(&stream->udev->dev, "%s: unknown urb-type for data " \ | ||
346 | "transfer\n", KBUILD_MODNAME); | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | int usb_urb_exitv2(struct usb_data_stream *stream) | ||
352 | { | ||
353 | usb_urb_free_urbs(stream); | ||
354 | usb_free_stream_buffers(stream); | ||
355 | |||
356 | return 0; | ||
357 | } | ||