]>
Commit | Line | Data |
---|---|---|
80619de8 AP |
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" | |
80619de8 | 25 | |
349d042f | 26 | static int dvb_usb_af9015_remote; |
80619de8 AP |
27 | module_param_named(remote, dvb_usb_af9015_remote, int, 0644); |
28 | MODULE_PARM_DESC(remote, "select remote"); | |
80619de8 AP |
29 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
30 | ||
a3645e54 | 31 | static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req) |
80619de8 | 32 | { |
06565d7a AP |
33 | #define REQ_HDR_LEN 8 /* send header size */ |
34 | #define ACK_HDR_LEN 2 /* rece header size */ | |
e8089661 | 35 | struct af9015_state *state = d_to_priv(d); |
a3645e54 | 36 | int ret, wlen, rlen; |
80619de8 | 37 | u8 write = 1; |
80619de8 | 38 | |
aff8c2d4 AP |
39 | mutex_lock(&d->usb_mutex); |
40 | ||
41 | state->buf[0] = req->cmd; | |
42 | state->buf[1] = state->seq++; | |
43 | state->buf[2] = req->i2c_addr; | |
44 | state->buf[3] = req->addr >> 8; | |
45 | state->buf[4] = req->addr & 0xff; | |
46 | state->buf[5] = req->mbox; | |
47 | state->buf[6] = req->addr_len; | |
48 | state->buf[7] = req->data_len; | |
80619de8 AP |
49 | |
50 | switch (req->cmd) { | |
51 | case GET_CONFIG: | |
80619de8 AP |
52 | case READ_MEMORY: |
53 | case RECONNECT_USB: | |
80619de8 AP |
54 | write = 0; |
55 | break; | |
56 | case READ_I2C: | |
57 | write = 0; | |
aff8c2d4 | 58 | state->buf[2] |= 0x01; /* set I2C direction */ |
80619de8 | 59 | case WRITE_I2C: |
aff8c2d4 | 60 | state->buf[0] = READ_WRITE_I2C; |
80619de8 AP |
61 | break; |
62 | case WRITE_MEMORY: | |
63 | if (((req->addr & 0xff00) == 0xff00) || | |
f4e96deb | 64 | ((req->addr & 0xff00) == 0xae00)) |
aff8c2d4 | 65 | state->buf[0] = WRITE_VIRTUAL_MEMORY; |
80619de8 AP |
66 | case WRITE_VIRTUAL_MEMORY: |
67 | case COPY_FIRMWARE: | |
68 | case DOWNLOAD_FIRMWARE: | |
ba1bc642 | 69 | case BOOT: |
80619de8 AP |
70 | break; |
71 | default: | |
f224749b AP |
72 | dev_err(&d->udev->dev, "%s: unknown command=%d\n", |
73 | KBUILD_MODNAME, req->cmd); | |
e1e9e510 | 74 | ret = -EIO; |
a3645e54 | 75 | goto error; |
80619de8 AP |
76 | } |
77 | ||
06565d7a AP |
78 | /* buffer overflow check */ |
79 | if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) || | |
f224749b AP |
80 | (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) { |
81 | dev_err(&d->udev->dev, "%s: too much data; cmd=%d len=%d\n", | |
82 | KBUILD_MODNAME, req->cmd, req->data_len); | |
06565d7a | 83 | ret = -EINVAL; |
a3645e54 | 84 | goto error; |
06565d7a AP |
85 | } |
86 | ||
a3645e54 AP |
87 | /* write receives seq + status = 2 bytes |
88 | read receives seq + status + data = 2 + N bytes */ | |
89 | wlen = REQ_HDR_LEN; | |
90 | rlen = ACK_HDR_LEN; | |
80619de8 | 91 | if (write) { |
a3645e54 | 92 | wlen += req->data_len; |
aff8c2d4 | 93 | memcpy(&state->buf[REQ_HDR_LEN], req->data, req->data_len); |
a3645e54 AP |
94 | } else { |
95 | rlen += req->data_len; | |
80619de8 | 96 | } |
06565d7a | 97 | |
a3645e54 | 98 | /* no ack for these packets */ |
80619de8 | 99 | if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) |
a3645e54 | 100 | rlen = 0; |
80619de8 | 101 | |
aff8c2d4 AP |
102 | ret = dvb_usbv2_generic_rw_locked(d, |
103 | state->buf, wlen, state->buf, rlen); | |
a3645e54 AP |
104 | if (ret) |
105 | goto error; | |
80619de8 | 106 | |
80619de8 | 107 | /* check status */ |
aff8c2d4 | 108 | if (rlen && state->buf[1]) { |
f224749b | 109 | dev_err(&d->udev->dev, "%s: command failed=%d\n", |
aff8c2d4 | 110 | KBUILD_MODNAME, state->buf[1]); |
e1e9e510 | 111 | ret = -EIO; |
a3645e54 | 112 | goto error; |
80619de8 AP |
113 | } |
114 | ||
115 | /* read request, copy returned data to return buf */ | |
116 | if (!write) | |
aff8c2d4 | 117 | memcpy(req->data, &state->buf[ACK_HDR_LEN], req->data_len); |
a3645e54 | 118 | error: |
aff8c2d4 AP |
119 | mutex_unlock(&d->usb_mutex); |
120 | ||
80619de8 AP |
121 | return ret; |
122 | } | |
123 | ||
80619de8 AP |
124 | static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val, |
125 | u8 len) | |
126 | { | |
127 | struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, | |
128 | val}; | |
129 | return af9015_ctrl_msg(d, &req); | |
130 | } | |
131 | ||
74c8e3ad | 132 | static int af9015_read_regs(struct dvb_usb_device *d, u16 addr, u8 *val, u8 len) |
80619de8 | 133 | { |
74c8e3ad AP |
134 | struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len, |
135 | val}; | |
80619de8 AP |
136 | return af9015_ctrl_msg(d, &req); |
137 | } | |
138 | ||
a3645e54 AP |
139 | static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val) |
140 | { | |
141 | return af9015_write_regs(d, addr, &val, 1); | |
142 | } | |
143 | ||
74c8e3ad AP |
144 | static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val) |
145 | { | |
146 | return af9015_read_regs(d, addr, val, 1); | |
147 | } | |
148 | ||
80619de8 AP |
149 | static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, |
150 | u8 val) | |
151 | { | |
e8089661 | 152 | struct af9015_state *state = d_to_priv(d); |
80619de8 AP |
153 | struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val}; |
154 | ||
a3645e54 AP |
155 | if (addr == state->af9013_config[0].i2c_addr || |
156 | addr == state->af9013_config[1].i2c_addr) | |
80619de8 AP |
157 | req.addr_len = 3; |
158 | ||
159 | return af9015_ctrl_msg(d, &req); | |
160 | } | |
161 | ||
162 | static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg, | |
163 | u8 *val) | |
164 | { | |
e8089661 | 165 | struct af9015_state *state = d_to_priv(d); |
80619de8 AP |
166 | struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val}; |
167 | ||
a3645e54 AP |
168 | if (addr == state->af9013_config[0].i2c_addr || |
169 | addr == state->af9013_config[1].i2c_addr) | |
80619de8 AP |
170 | req.addr_len = 3; |
171 | ||
172 | return af9015_ctrl_msg(d, &req); | |
173 | } | |
174 | ||
a3645e54 AP |
175 | static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op) |
176 | { | |
177 | int ret; | |
178 | u8 val, mask = 0x01; | |
179 | ||
180 | ret = af9015_read_reg(d, addr, &val); | |
181 | if (ret) | |
182 | return ret; | |
183 | ||
184 | mask <<= bit; | |
185 | if (op) { | |
186 | /* set bit */ | |
187 | val |= mask; | |
188 | } else { | |
189 | /* clear bit */ | |
190 | mask ^= 0xff; | |
191 | val &= mask; | |
192 | } | |
193 | ||
194 | return af9015_write_reg(d, addr, val); | |
195 | } | |
196 | ||
197 | static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) | |
198 | { | |
199 | return af9015_do_reg_bit(d, addr, bit, 1); | |
200 | } | |
201 | ||
202 | static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit) | |
203 | { | |
204 | return af9015_do_reg_bit(d, addr, bit, 0); | |
205 | } | |
206 | ||
80619de8 AP |
207 | static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
208 | int num) | |
209 | { | |
210 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
e8089661 | 211 | struct af9015_state *state = d_to_priv(d); |
80619de8 AP |
212 | int ret = 0, i = 0; |
213 | u16 addr; | |
675375d7 | 214 | u8 uninitialized_var(mbox), addr_len; |
80619de8 AP |
215 | struct req_t req; |
216 | ||
bc050e67 | 217 | /* |
80619de8 AP |
218 | The bus lock is needed because there is two tuners both using same I2C-address. |
219 | Due to that the only way to select correct tuner is use demodulator I2C-gate. | |
220 | ||
221 | ................................................ | |
222 | . AF9015 includes integrated AF9013 demodulator. | |
223 | . ____________ ____________ . ____________ | |
224 | .| uC | | demod | . | tuner | | |
225 | .|------------| |------------| . |------------| | |
226 | .| AF9015 | | AF9013/5 | . | MXL5003 | | |
227 | .| |--+----I2C-------|-----/ -----|-.-----I2C-------| | | |
228 | .| | | | addr 0x38 | . | addr 0xc6 | | |
229 | .|____________| | |____________| . |____________| | |
230 | .................|.............................. | |
231 | | ____________ ____________ | |
232 | | | demod | | tuner | | |
233 | | |------------| |------------| | |
234 | | | AF9013 | | MXL5003 | | |
235 | +----I2C-------|-----/ -----|-------I2C-------| | | |
236 | | addr 0x3a | | addr 0xc6 | | |
237 | |____________| |____________| | |
238 | */ | |
239 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | |
240 | return -EAGAIN; | |
241 | ||
242 | while (i < num) { | |
a3645e54 AP |
243 | if (msg[i].addr == state->af9013_config[0].i2c_addr || |
244 | msg[i].addr == state->af9013_config[1].i2c_addr) { | |
80619de8 AP |
245 | addr = msg[i].buf[0] << 8; |
246 | addr += msg[i].buf[1]; | |
247 | mbox = msg[i].buf[2]; | |
248 | addr_len = 3; | |
249 | } else { | |
250 | addr = msg[i].buf[0]; | |
251 | addr_len = 1; | |
675375d7 | 252 | /* mbox is don't care in that case */ |
80619de8 AP |
253 | } |
254 | ||
255 | if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) { | |
709d9208 AP |
256 | if (msg[i].len > 3 || msg[i+1].len > 61) { |
257 | ret = -EOPNOTSUPP; | |
258 | goto error; | |
259 | } | |
a3645e54 | 260 | if (msg[i].addr == state->af9013_config[0].i2c_addr) |
80619de8 AP |
261 | req.cmd = READ_MEMORY; |
262 | else | |
263 | req.cmd = READ_I2C; | |
264 | req.i2c_addr = msg[i].addr; | |
265 | req.addr = addr; | |
266 | req.mbox = mbox; | |
267 | req.addr_len = addr_len; | |
268 | req.data_len = msg[i+1].len; | |
269 | req.data = &msg[i+1].buf[0]; | |
270 | ret = af9015_ctrl_msg(d, &req); | |
271 | i += 2; | |
d5633998 | 272 | } else if (msg[i].flags & I2C_M_RD) { |
709d9208 AP |
273 | if (msg[i].len > 61) { |
274 | ret = -EOPNOTSUPP; | |
275 | goto error; | |
276 | } | |
a3645e54 | 277 | if (msg[i].addr == state->af9013_config[0].i2c_addr) { |
16b2dc2a | 278 | ret = -EINVAL; |
d5633998 | 279 | goto error; |
16b2dc2a AP |
280 | } |
281 | req.cmd = READ_I2C; | |
d5633998 JF |
282 | req.i2c_addr = msg[i].addr; |
283 | req.addr = addr; | |
284 | req.mbox = mbox; | |
285 | req.addr_len = addr_len; | |
286 | req.data_len = msg[i].len; | |
287 | req.data = &msg[i].buf[0]; | |
288 | ret = af9015_ctrl_msg(d, &req); | |
289 | i += 1; | |
80619de8 | 290 | } else { |
709d9208 AP |
291 | if (msg[i].len > 21) { |
292 | ret = -EOPNOTSUPP; | |
293 | goto error; | |
294 | } | |
a3645e54 | 295 | if (msg[i].addr == state->af9013_config[0].i2c_addr) |
80619de8 AP |
296 | req.cmd = WRITE_MEMORY; |
297 | else | |
298 | req.cmd = WRITE_I2C; | |
299 | req.i2c_addr = msg[i].addr; | |
300 | req.addr = addr; | |
301 | req.mbox = mbox; | |
302 | req.addr_len = addr_len; | |
303 | req.data_len = msg[i].len-addr_len; | |
304 | req.data = &msg[i].buf[addr_len]; | |
305 | ret = af9015_ctrl_msg(d, &req); | |
306 | i += 1; | |
307 | } | |
308 | if (ret) | |
309 | goto error; | |
310 | ||
311 | } | |
312 | ret = i; | |
313 | ||
314 | error: | |
315 | mutex_unlock(&d->i2c_mutex); | |
316 | ||
317 | return ret; | |
318 | } | |
319 | ||
320 | static u32 af9015_i2c_func(struct i2c_adapter *adapter) | |
321 | { | |
322 | return I2C_FUNC_I2C; | |
323 | } | |
324 | ||
325 | static struct i2c_algorithm af9015_i2c_algo = { | |
326 | .master_xfer = af9015_i2c_xfer, | |
327 | .functionality = af9015_i2c_func, | |
328 | }; | |
329 | ||
a0921af7 | 330 | static int af9015_identify_state(struct dvb_usb_device *d, const char **name) |
80619de8 AP |
331 | { |
332 | int ret; | |
a3645e54 AP |
333 | u8 reply; |
334 | struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply}; | |
80619de8 | 335 | |
a3645e54 | 336 | ret = af9015_ctrl_msg(d, &req); |
80619de8 AP |
337 | if (ret) |
338 | return ret; | |
339 | ||
f224749b AP |
340 | dev_dbg(&d->udev->dev, "%s: reply=%02x\n", __func__, reply); |
341 | ||
a3645e54 AP |
342 | if (reply == 0x02) |
343 | ret = WARM; | |
344 | else | |
345 | ret = COLD; | |
80619de8 | 346 | |
a3645e54 | 347 | return ret; |
80619de8 AP |
348 | } |
349 | ||
a3645e54 AP |
350 | static int af9015_download_firmware(struct dvb_usb_device *d, |
351 | const struct firmware *fw) | |
80619de8 | 352 | { |
e8089661 | 353 | struct af9015_state *state = d_to_priv(d); |
a3645e54 AP |
354 | int i, len, remaining, ret; |
355 | struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL}; | |
356 | u16 checksum = 0; | |
f224749b | 357 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
80619de8 | 358 | |
a3645e54 AP |
359 | /* calc checksum */ |
360 | for (i = 0; i < fw->size; i++) | |
361 | checksum += fw->data[i]; | |
80619de8 | 362 | |
a3645e54 AP |
363 | state->firmware_size = fw->size; |
364 | state->firmware_checksum = checksum; | |
80619de8 | 365 | |
a3645e54 AP |
366 | #define FW_ADDR 0x5100 /* firmware start address */ |
367 | #define LEN_MAX 55 /* max packet size */ | |
368 | for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) { | |
369 | len = remaining; | |
370 | if (len > LEN_MAX) | |
371 | len = LEN_MAX; | |
80619de8 | 372 | |
a3645e54 AP |
373 | req.data_len = len; |
374 | req.data = (u8 *) &fw->data[fw->size - remaining]; | |
375 | req.addr = FW_ADDR + fw->size - remaining; | |
80619de8 | 376 | |
a3645e54 AP |
377 | ret = af9015_ctrl_msg(d, &req); |
378 | if (ret) { | |
f224749b AP |
379 | dev_err(&d->udev->dev, |
380 | "%s: firmware download failed=%d\n", | |
381 | KBUILD_MODNAME, ret); | |
a3645e54 AP |
382 | goto error; |
383 | } | |
80619de8 AP |
384 | } |
385 | ||
a3645e54 AP |
386 | /* firmware loaded, request boot */ |
387 | req.cmd = BOOT; | |
388 | req.data_len = 0; | |
389 | ret = af9015_ctrl_msg(d, &req); | |
390 | if (ret) { | |
f224749b AP |
391 | dev_err(&d->udev->dev, "%s: firmware boot failed=%d\n", |
392 | KBUILD_MODNAME, ret); | |
80619de8 | 393 | goto error; |
80619de8 | 394 | } |
a3645e54 AP |
395 | |
396 | error: | |
397 | return ret; | |
398 | } | |
399 | ||
65e2f1cb | 400 | #define AF9015_EEPROM_SIZE 256 |
ef703f49 GS |
401 | /* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */ |
402 | #define GOLDEN_RATIO_PRIME_32 0x9e370001UL | |
65e2f1cb | 403 | |
a3645e54 AP |
404 | /* hash (and dump) eeprom */ |
405 | static int af9015_eeprom_hash(struct dvb_usb_device *d) | |
406 | { | |
e8089661 | 407 | struct af9015_state *state = d_to_priv(d); |
2e35c66f | 408 | int ret, i; |
2e35c66f AP |
409 | u8 buf[AF9015_EEPROM_SIZE]; |
410 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, NULL}; | |
411 | ||
412 | /* read eeprom */ | |
413 | for (i = 0; i < AF9015_EEPROM_SIZE; i++) { | |
414 | req.addr = i; | |
415 | req.data = &buf[i]; | |
a3645e54 | 416 | ret = af9015_ctrl_msg(d, &req); |
2e35c66f AP |
417 | if (ret < 0) |
418 | goto err; | |
80619de8 | 419 | } |
a3645e54 | 420 | |
2e35c66f AP |
421 | /* calculate checksum */ |
422 | for (i = 0; i < AF9015_EEPROM_SIZE / sizeof(u32); i++) { | |
a3645e54 | 423 | state->eeprom_sum *= GOLDEN_RATIO_PRIME_32; |
74426324 | 424 | state->eeprom_sum += le32_to_cpu(((__le32 *)buf)[i]); |
80619de8 AP |
425 | } |
426 | ||
2e35c66f AP |
427 | for (i = 0; i < AF9015_EEPROM_SIZE; i += 16) |
428 | dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 16, buf + i); | |
429 | ||
f224749b AP |
430 | dev_dbg(&d->udev->dev, "%s: eeprom sum=%.8x\n", |
431 | __func__, state->eeprom_sum); | |
2e35c66f AP |
432 | return 0; |
433 | err: | |
434 | dev_err(&d->udev->dev, "%s: eeprom failed=%d\n", KBUILD_MODNAME, ret); | |
80619de8 AP |
435 | return ret; |
436 | } | |
437 | ||
a3645e54 | 438 | static int af9015_read_config(struct dvb_usb_device *d) |
80619de8 | 439 | { |
e8089661 | 440 | struct af9015_state *state = d_to_priv(d); |
80619de8 | 441 | int ret; |
a3645e54 AP |
442 | u8 val, i, offset = 0; |
443 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; | |
80619de8 | 444 | |
f224749b | 445 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
80619de8 | 446 | |
a3645e54 AP |
447 | /* IR remote controller */ |
448 | req.addr = AF9015_EEPROM_IR_MODE; | |
449 | /* first message will timeout often due to possible hw bug */ | |
450 | for (i = 0; i < 4; i++) { | |
451 | ret = af9015_ctrl_msg(d, &req); | |
452 | if (!ret) | |
453 | break; | |
454 | } | |
455 | if (ret) | |
456 | goto error; | |
80619de8 | 457 | |
a3645e54 | 458 | ret = af9015_eeprom_hash(d); |
80619de8 AP |
459 | if (ret) |
460 | goto error; | |
80619de8 | 461 | |
a3645e54 | 462 | state->ir_mode = val; |
f224749b | 463 | dev_dbg(&d->udev->dev, "%s: IR mode=%d\n", __func__, val); |
80619de8 | 464 | |
a3645e54 AP |
465 | /* TS mode - one or two receivers */ |
466 | req.addr = AF9015_EEPROM_TS_MODE; | |
80619de8 | 467 | ret = af9015_ctrl_msg(d, &req); |
80619de8 AP |
468 | if (ret) |
469 | goto error; | |
6c614044 | 470 | |
a3645e54 | 471 | state->dual_mode = val; |
f224749b | 472 | dev_dbg(&d->udev->dev, "%s: TS mode=%d\n", __func__, state->dual_mode); |
6c614044 | 473 | |
a3645e54 AP |
474 | /* disable 2nd adapter because we don't have PID-filters */ |
475 | if (d->udev->speed == USB_SPEED_FULL) | |
476 | state->dual_mode = 0; | |
80619de8 | 477 | |
a3645e54 | 478 | if (state->dual_mode) { |
80619de8 AP |
479 | /* read 2nd demodulator I2C address */ |
480 | req.addr = AF9015_EEPROM_DEMOD2_I2C; | |
a3645e54 | 481 | ret = af9015_ctrl_msg(d, &req); |
80619de8 AP |
482 | if (ret) |
483 | goto error; | |
80619de8 | 484 | |
a3645e54 | 485 | state->af9013_config[1].i2c_addr = val; |
80619de8 AP |
486 | } |
487 | ||
a3645e54 | 488 | for (i = 0; i < state->dual_mode + 1; i++) { |
80619de8 AP |
489 | if (i == 1) |
490 | offset = AF9015_EEPROM_OFFSET; | |
491 | /* xtal */ | |
492 | req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset; | |
a3645e54 | 493 | ret = af9015_ctrl_msg(d, &req); |
80619de8 AP |
494 | if (ret) |
495 | goto error; | |
496 | switch (val) { | |
497 | case 0: | |
a3645e54 | 498 | state->af9013_config[i].clock = 28800000; |
80619de8 AP |
499 | break; |
500 | case 1: | |
a3645e54 | 501 | state->af9013_config[i].clock = 20480000; |
80619de8 AP |
502 | break; |
503 | case 2: | |
a3645e54 | 504 | state->af9013_config[i].clock = 28000000; |
80619de8 AP |
505 | break; |
506 | case 3: | |
a3645e54 | 507 | state->af9013_config[i].clock = 25000000; |
80619de8 | 508 | break; |
c2c1b415 | 509 | } |
f224749b AP |
510 | dev_dbg(&d->udev->dev, "%s: [%d] xtal=%d set clock=%d\n", |
511 | __func__, i, val, | |
512 | state->af9013_config[i].clock); | |
80619de8 | 513 | |
f571e004 | 514 | /* IF frequency */ |
80619de8 | 515 | req.addr = AF9015_EEPROM_IF1H + offset; |
a3645e54 | 516 | ret = af9015_ctrl_msg(d, &req); |
80619de8 AP |
517 | if (ret) |
518 | goto error; | |
f571e004 | 519 | |
a3645e54 | 520 | state->af9013_config[i].if_frequency = val << 8; |
f571e004 | 521 | |
80619de8 | 522 | req.addr = AF9015_EEPROM_IF1L + offset; |
a3645e54 | 523 | ret = af9015_ctrl_msg(d, &req); |
80619de8 AP |
524 | if (ret) |
525 | goto error; | |
f571e004 | 526 | |
a3645e54 AP |
527 | state->af9013_config[i].if_frequency += val; |
528 | state->af9013_config[i].if_frequency *= 1000; | |
f224749b AP |
529 | dev_dbg(&d->udev->dev, "%s: [%d] IF frequency=%d\n", __func__, |
530 | i, state->af9013_config[i].if_frequency); | |
80619de8 AP |
531 | |
532 | /* MT2060 IF1 */ | |
533 | req.addr = AF9015_EEPROM_MT2060_IF1H + offset; | |
a3645e54 | 534 | ret = af9015_ctrl_msg(d, &req); |
80619de8 AP |
535 | if (ret) |
536 | goto error; | |
a3645e54 | 537 | state->mt2060_if1[i] = val << 8; |
80619de8 | 538 | req.addr = AF9015_EEPROM_MT2060_IF1L + offset; |
a3645e54 | 539 | ret = af9015_ctrl_msg(d, &req); |
80619de8 AP |
540 | if (ret) |
541 | goto error; | |
a3645e54 | 542 | state->mt2060_if1[i] += val; |
f224749b | 543 | dev_dbg(&d->udev->dev, "%s: [%d] MT2060 IF1=%d\n", __func__, i, |
a3645e54 | 544 | state->mt2060_if1[i]); |
80619de8 AP |
545 | |
546 | /* tuner */ | |
547 | req.addr = AF9015_EEPROM_TUNER_ID1 + offset; | |
a3645e54 | 548 | ret = af9015_ctrl_msg(d, &req); |
80619de8 AP |
549 | if (ret) |
550 | goto error; | |
551 | switch (val) { | |
552 | case AF9013_TUNER_ENV77H11D5: | |
553 | case AF9013_TUNER_MT2060: | |
80619de8 AP |
554 | case AF9013_TUNER_QT1010: |
555 | case AF9013_TUNER_UNKNOWN: | |
556 | case AF9013_TUNER_MT2060_2: | |
557 | case AF9013_TUNER_TDA18271: | |
558 | case AF9013_TUNER_QT1010A: | |
ee3d440c | 559 | case AF9013_TUNER_TDA18218: |
a3645e54 | 560 | state->af9013_config[i].spec_inv = 1; |
80619de8 AP |
561 | break; |
562 | case AF9013_TUNER_MXL5003D: | |
563 | case AF9013_TUNER_MXL5005D: | |
564 | case AF9013_TUNER_MXL5005R: | |
ab07fdd6 | 565 | case AF9013_TUNER_MXL5007T: |
a3645e54 | 566 | state->af9013_config[i].spec_inv = 0; |
80619de8 | 567 | break; |
d5633998 | 568 | case AF9013_TUNER_MC44S803: |
a3645e54 AP |
569 | state->af9013_config[i].gpio[1] = AF9013_GPIO_LO; |
570 | state->af9013_config[i].spec_inv = 1; | |
d5633998 | 571 | break; |
80619de8 | 572 | default: |
f224749b AP |
573 | dev_err(&d->udev->dev, "%s: tuner id=%d not " \ |
574 | "supported, please report!\n", | |
575 | KBUILD_MODNAME, val); | |
80619de8 | 576 | return -ENODEV; |
c2c1b415 | 577 | } |
80619de8 | 578 | |
a3645e54 | 579 | state->af9013_config[i].tuner = val; |
f224749b AP |
580 | dev_dbg(&d->udev->dev, "%s: [%d] tuner id=%d\n", |
581 | __func__, i, val); | |
80619de8 AP |
582 | } |
583 | ||
584 | error: | |
585 | if (ret) | |
f224749b AP |
586 | dev_err(&d->udev->dev, "%s: eeprom read failed=%d\n", |
587 | KBUILD_MODNAME, ret); | |
80619de8 | 588 | |
3956fefc | 589 | /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM |
8ccdf1ae YM |
590 | content :-( Override some wrong values here. Ditto for the |
591 | AVerTV Red HD+ (A850T) device. */ | |
a3645e54 AP |
592 | if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA && |
593 | ((le16_to_cpu(d->udev->descriptor.idProduct) == | |
9a3ecc73 | 594 | USB_PID_AVERMEDIA_A850) || |
a3645e54 | 595 | (le16_to_cpu(d->udev->descriptor.idProduct) == |
9a3ecc73 | 596 | USB_PID_AVERMEDIA_A850T))) { |
f224749b AP |
597 | dev_dbg(&d->udev->dev, |
598 | "%s: AverMedia A850: overriding config\n", | |
599 | __func__); | |
3956fefc | 600 | /* disable dual mode */ |
a3645e54 | 601 | state->dual_mode = 0; |
3956fefc AP |
602 | |
603 | /* set correct IF */ | |
a3645e54 | 604 | state->af9013_config[0].if_frequency = 4570000; |
3956fefc AP |
605 | } |
606 | ||
80619de8 AP |
607 | return ret; |
608 | } | |
609 | ||
b905a2a1 | 610 | static int af9015_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, |
a3645e54 | 611 | struct usb_data_stream_properties *stream) |
80619de8 | 612 | { |
f224749b AP |
613 | struct dvb_usb_device *d = fe_to_d(fe); |
614 | dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, fe_to_adap(fe)->id); | |
d3bb73de | 615 | |
f224749b | 616 | if (d->udev->speed == USB_SPEED_FULL) |
a3645e54 | 617 | stream->u.bulk.buffersize = TS_USB11_FRAME_SIZE; |
1e8750c2 | 618 | |
a3645e54 AP |
619 | return 0; |
620 | } | |
d3bb73de | 621 | |
a3645e54 AP |
622 | static int af9015_get_adapter_count(struct dvb_usb_device *d) |
623 | { | |
e8089661 | 624 | struct af9015_state *state = d_to_priv(d); |
a3645e54 | 625 | return state->dual_mode + 1; |
80619de8 AP |
626 | } |
627 | ||
e90ab840 | 628 | /* override demod callbacks for resource locking */ |
0009e0e3 | 629 | static int af9015_af9013_set_frontend(struct dvb_frontend *fe) |
e90ab840 AP |
630 | { |
631 | int ret; | |
e8089661 | 632 | struct af9015_state *state = fe_to_priv(fe); |
e90ab840 | 633 | |
a3645e54 | 634 | if (mutex_lock_interruptible(&state->fe_mutex)) |
e90ab840 AP |
635 | return -EAGAIN; |
636 | ||
e8089661 | 637 | ret = state->set_frontend[fe_to_adap(fe)->id](fe); |
e90ab840 | 638 | |
a3645e54 | 639 | mutex_unlock(&state->fe_mutex); |
e90ab840 AP |
640 | |
641 | return ret; | |
642 | } | |
643 | ||
644 | /* override demod callbacks for resource locking */ | |
645 | static int af9015_af9013_read_status(struct dvb_frontend *fe, | |
0df289a2 | 646 | enum fe_status *status) |
e90ab840 AP |
647 | { |
648 | int ret; | |
e8089661 | 649 | struct af9015_state *state = fe_to_priv(fe); |
e90ab840 | 650 | |
a3645e54 | 651 | if (mutex_lock_interruptible(&state->fe_mutex)) |
e90ab840 AP |
652 | return -EAGAIN; |
653 | ||
e8089661 | 654 | ret = state->read_status[fe_to_adap(fe)->id](fe, status); |
e90ab840 | 655 | |
a3645e54 | 656 | mutex_unlock(&state->fe_mutex); |
e90ab840 AP |
657 | |
658 | return ret; | |
659 | } | |
660 | ||
661 | /* override demod callbacks for resource locking */ | |
662 | static int af9015_af9013_init(struct dvb_frontend *fe) | |
663 | { | |
664 | int ret; | |
e8089661 | 665 | struct af9015_state *state = fe_to_priv(fe); |
e90ab840 | 666 | |
a3645e54 | 667 | if (mutex_lock_interruptible(&state->fe_mutex)) |
e90ab840 AP |
668 | return -EAGAIN; |
669 | ||
e8089661 | 670 | ret = state->init[fe_to_adap(fe)->id](fe); |
e90ab840 | 671 | |
a3645e54 | 672 | mutex_unlock(&state->fe_mutex); |
e90ab840 AP |
673 | |
674 | return ret; | |
675 | } | |
676 | ||
677 | /* override demod callbacks for resource locking */ | |
678 | static int af9015_af9013_sleep(struct dvb_frontend *fe) | |
679 | { | |
680 | int ret; | |
e8089661 | 681 | struct af9015_state *state = fe_to_priv(fe); |
e90ab840 | 682 | |
a3645e54 | 683 | if (mutex_lock_interruptible(&state->fe_mutex)) |
e90ab840 AP |
684 | return -EAGAIN; |
685 | ||
e8089661 | 686 | ret = state->sleep[fe_to_adap(fe)->id](fe); |
e90ab840 | 687 | |
a3645e54 | 688 | mutex_unlock(&state->fe_mutex); |
e90ab840 AP |
689 | |
690 | return ret; | |
691 | } | |
692 | ||
6d535bd8 AP |
693 | /* override tuner callbacks for resource locking */ |
694 | static int af9015_tuner_init(struct dvb_frontend *fe) | |
695 | { | |
696 | int ret; | |
e8089661 | 697 | struct af9015_state *state = fe_to_priv(fe); |
6d535bd8 | 698 | |
a3645e54 | 699 | if (mutex_lock_interruptible(&state->fe_mutex)) |
6d535bd8 AP |
700 | return -EAGAIN; |
701 | ||
e8089661 | 702 | ret = state->tuner_init[fe_to_adap(fe)->id](fe); |
6d535bd8 | 703 | |
a3645e54 | 704 | mutex_unlock(&state->fe_mutex); |
6d535bd8 AP |
705 | |
706 | return ret; | |
707 | } | |
708 | ||
709 | /* override tuner callbacks for resource locking */ | |
710 | static int af9015_tuner_sleep(struct dvb_frontend *fe) | |
711 | { | |
712 | int ret; | |
e8089661 | 713 | struct af9015_state *state = fe_to_priv(fe); |
6d535bd8 | 714 | |
a3645e54 | 715 | if (mutex_lock_interruptible(&state->fe_mutex)) |
6d535bd8 AP |
716 | return -EAGAIN; |
717 | ||
e8089661 | 718 | ret = state->tuner_sleep[fe_to_adap(fe)->id](fe); |
a3645e54 AP |
719 | |
720 | mutex_unlock(&state->fe_mutex); | |
721 | ||
722 | return ret; | |
723 | } | |
724 | ||
725 | static int af9015_copy_firmware(struct dvb_usb_device *d) | |
726 | { | |
e8089661 | 727 | struct af9015_state *state = d_to_priv(d); |
a3645e54 AP |
728 | int ret; |
729 | u8 fw_params[4]; | |
730 | u8 val, i; | |
731 | struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params), | |
732 | fw_params }; | |
f224749b | 733 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
a3645e54 AP |
734 | |
735 | fw_params[0] = state->firmware_size >> 8; | |
736 | fw_params[1] = state->firmware_size & 0xff; | |
737 | fw_params[2] = state->firmware_checksum >> 8; | |
738 | fw_params[3] = state->firmware_checksum & 0xff; | |
739 | ||
740 | /* wait 2nd demodulator ready */ | |
741 | msleep(100); | |
742 | ||
743 | ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr, | |
744 | 0x98be, &val); | |
745 | if (ret) | |
746 | goto error; | |
747 | else | |
f224749b AP |
748 | dev_dbg(&d->udev->dev, "%s: firmware status=%02x\n", |
749 | __func__, val); | |
a3645e54 AP |
750 | |
751 | if (val == 0x0c) /* fw is running, no need for download */ | |
752 | goto exit; | |
753 | ||
754 | /* set I2C master clock to fast (to speed up firmware copy) */ | |
755 | ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */ | |
756 | if (ret) | |
757 | goto error; | |
758 | ||
759 | msleep(50); | |
760 | ||
761 | /* copy firmware */ | |
762 | ret = af9015_ctrl_msg(d, &req); | |
763 | if (ret) | |
f224749b AP |
764 | dev_err(&d->udev->dev, "%s: firmware copy cmd failed=%d\n", |
765 | KBUILD_MODNAME, ret); | |
766 | ||
767 | dev_dbg(&d->udev->dev, "%s: firmware copy done\n", __func__); | |
a3645e54 AP |
768 | |
769 | /* set I2C master clock back to normal */ | |
770 | ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */ | |
771 | if (ret) | |
772 | goto error; | |
773 | ||
774 | /* request boot firmware */ | |
775 | ret = af9015_write_reg_i2c(d, state->af9013_config[1].i2c_addr, | |
776 | 0xe205, 1); | |
f224749b AP |
777 | dev_dbg(&d->udev->dev, "%s: firmware boot cmd status=%d\n", |
778 | __func__, ret); | |
a3645e54 AP |
779 | if (ret) |
780 | goto error; | |
781 | ||
782 | for (i = 0; i < 15; i++) { | |
783 | msleep(100); | |
6d535bd8 | 784 | |
a3645e54 AP |
785 | /* check firmware status */ |
786 | ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr, | |
787 | 0x98be, &val); | |
f224749b AP |
788 | dev_dbg(&d->udev->dev, "%s: firmware status cmd status=%d " \ |
789 | "firmware status=%02x\n", __func__, ret, val); | |
a3645e54 AP |
790 | if (ret) |
791 | goto error; | |
6d535bd8 | 792 | |
a3645e54 AP |
793 | if (val == 0x0c || val == 0x04) /* success or fail */ |
794 | break; | |
795 | } | |
796 | ||
797 | if (val == 0x04) { | |
f224749b AP |
798 | dev_err(&d->udev->dev, "%s: firmware did not run\n", |
799 | KBUILD_MODNAME); | |
e1e9e510 | 800 | ret = -ETIMEDOUT; |
a3645e54 | 801 | } else if (val != 0x0c) { |
f224749b AP |
802 | dev_err(&d->udev->dev, "%s: firmware boot timeout\n", |
803 | KBUILD_MODNAME); | |
e1e9e510 | 804 | ret = -ETIMEDOUT; |
a3645e54 AP |
805 | } |
806 | ||
807 | error: | |
808 | exit: | |
6d535bd8 AP |
809 | return ret; |
810 | } | |
811 | ||
80619de8 AP |
812 | static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) |
813 | { | |
814 | int ret; | |
e8089661 | 815 | struct af9015_state *state = adap_to_priv(adap); |
80619de8 | 816 | |
a3645e54 AP |
817 | if (adap->id == 0) { |
818 | state->af9013_config[0].ts_mode = AF9013_TS_USB; | |
819 | memcpy(state->af9013_config[0].api_version, "\x0\x1\x9\x0", 4); | |
820 | state->af9013_config[0].gpio[0] = AF9013_GPIO_HI; | |
821 | state->af9013_config[0].gpio[3] = AF9013_GPIO_TUNER_ON; | |
822 | } else if (adap->id == 1) { | |
823 | state->af9013_config[1].ts_mode = AF9013_TS_SERIAL; | |
824 | memcpy(state->af9013_config[1].api_version, "\x0\x1\x9\x0", 4); | |
825 | state->af9013_config[1].gpio[0] = AF9013_GPIO_TUNER_ON; | |
826 | state->af9013_config[1].gpio[1] = AF9013_GPIO_LO; | |
827 | ||
80619de8 | 828 | /* copy firmware to 2nd demodulator */ |
a3645e54 | 829 | if (state->dual_mode) { |
e8089661 | 830 | ret = af9015_copy_firmware(adap_to_d(adap)); |
80619de8 | 831 | if (ret) { |
f224749b AP |
832 | dev_err(&adap_to_d(adap)->udev->dev, |
833 | "%s: firmware copy to 2nd " \ | |
834 | "frontend failed, will " \ | |
835 | "disable it\n", KBUILD_MODNAME); | |
a3645e54 | 836 | state->dual_mode = 0; |
80619de8 AP |
837 | return -ENODEV; |
838 | } | |
839 | } else { | |
840 | return -ENODEV; | |
841 | } | |
842 | } | |
843 | ||
844 | /* attach demodulator */ | |
a3645e54 | 845 | adap->fe[0] = dvb_attach(af9013_attach, |
e8089661 | 846 | &state->af9013_config[adap->id], &adap_to_d(adap)->i2c_adap); |
80619de8 | 847 | |
e90ab840 AP |
848 | /* |
849 | * AF9015 firmware does not like if it gets interrupted by I2C adapter | |
850 | * request on some critical phases. During normal operation I2C adapter | |
851 | * is used only 2nd demodulator and tuner on dual tuner devices. | |
852 | * Override demodulator callbacks and use mutex for limit access to | |
853 | * those "critical" paths to keep AF9015 happy. | |
e90ab840 | 854 | */ |
a3645e54 | 855 | if (adap->fe[0]) { |
e90ab840 | 856 | state->set_frontend[adap->id] = |
a3645e54 AP |
857 | adap->fe[0]->ops.set_frontend; |
858 | adap->fe[0]->ops.set_frontend = | |
e90ab840 AP |
859 | af9015_af9013_set_frontend; |
860 | ||
861 | state->read_status[adap->id] = | |
a3645e54 AP |
862 | adap->fe[0]->ops.read_status; |
863 | adap->fe[0]->ops.read_status = | |
e90ab840 AP |
864 | af9015_af9013_read_status; |
865 | ||
a3645e54 AP |
866 | state->init[adap->id] = adap->fe[0]->ops.init; |
867 | adap->fe[0]->ops.init = af9015_af9013_init; | |
e90ab840 | 868 | |
a3645e54 AP |
869 | state->sleep[adap->id] = adap->fe[0]->ops.sleep; |
870 | adap->fe[0]->ops.sleep = af9015_af9013_sleep; | |
e90ab840 AP |
871 | } |
872 | ||
a3645e54 | 873 | return adap->fe[0] == NULL ? -ENODEV : 0; |
80619de8 AP |
874 | } |
875 | ||
876 | static struct mt2060_config af9015_mt2060_config = { | |
877 | .i2c_address = 0xc0, | |
878 | .clock_out = 0, | |
879 | }; | |
880 | ||
881 | static struct qt1010_config af9015_qt1010_config = { | |
882 | .i2c_address = 0xc4, | |
883 | }; | |
884 | ||
885 | static struct tda18271_config af9015_tda18271_config = { | |
886 | .gate = TDA18271_GATE_DIGITAL, | |
7655e594 | 887 | .small_i2c = TDA18271_16_BYTE_CHUNK_INIT, |
80619de8 AP |
888 | }; |
889 | ||
890 | static struct mxl5005s_config af9015_mxl5003_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_DEFAULT, | |
a131077d | 896 | .rssi_enable = MXL_RSSI_ENABLE, |
80619de8 AP |
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 mxl5005s_config af9015_mxl5005_config = { | |
908 | .i2c_address = 0xc6, | |
909 | .if_freq = IF_FREQ_4570000HZ, | |
910 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, | |
911 | .agc_mode = MXL_SINGLE_AGC, | |
912 | .tracking_filter = MXL_TF_OFF, | |
a131077d | 913 | .rssi_enable = MXL_RSSI_ENABLE, |
80619de8 AP |
914 | .cap_select = MXL_CAP_SEL_ENABLE, |
915 | .div_out = MXL_DIV_OUT_4, | |
916 | .clock_out = MXL_CLOCK_OUT_DISABLE, | |
917 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | |
918 | .top = MXL5005S_TOP_25P2, | |
919 | .mod_mode = MXL_DIGITAL_MODE, | |
920 | .if_mode = MXL_ZERO_IF, | |
921 | .AgcMasterByte = 0x00, | |
922 | }; | |
923 | ||
d5633998 JF |
924 | static struct mc44s803_config af9015_mc44s803_config = { |
925 | .i2c_address = 0xc0, | |
926 | .dig_out = 1, | |
927 | }; | |
928 | ||
ee3d440c AP |
929 | static struct tda18218_config af9015_tda18218_config = { |
930 | .i2c_address = 0xc0, | |
931 | .i2c_wr_max = 21, /* max wr bytes AF9015 I2C adap can handle at once */ | |
932 | }; | |
933 | ||
ab07fdd6 AP |
934 | static struct mxl5007t_config af9015_mxl5007t_config = { |
935 | .xtal_freq_hz = MxL_XTAL_24_MHZ, | |
936 | .if_freq_hz = MxL_IF_4_57_MHZ, | |
937 | }; | |
938 | ||
80619de8 AP |
939 | static int af9015_tuner_attach(struct dvb_usb_adapter *adap) |
940 | { | |
f224749b AP |
941 | struct dvb_usb_device *d = adap_to_d(adap); |
942 | struct af9015_state *state = d_to_priv(d); | |
a3645e54 | 943 | int ret; |
f224749b | 944 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
80619de8 | 945 | |
a3645e54 | 946 | switch (state->af9013_config[adap->id].tuner) { |
80619de8 AP |
947 | case AF9013_TUNER_MT2060: |
948 | case AF9013_TUNER_MT2060_2: | |
a3645e54 | 949 | ret = dvb_attach(mt2060_attach, adap->fe[0], |
e8089661 | 950 | &adap_to_d(adap)->i2c_adap, &af9015_mt2060_config, |
a3645e54 | 951 | state->mt2060_if1[adap->id]) |
80619de8 AP |
952 | == NULL ? -ENODEV : 0; |
953 | break; | |
954 | case AF9013_TUNER_QT1010: | |
955 | case AF9013_TUNER_QT1010A: | |
a3645e54 | 956 | ret = dvb_attach(qt1010_attach, adap->fe[0], |
e8089661 | 957 | &adap_to_d(adap)->i2c_adap, |
80619de8 AP |
958 | &af9015_qt1010_config) == NULL ? -ENODEV : 0; |
959 | break; | |
960 | case AF9013_TUNER_TDA18271: | |
a3645e54 | 961 | ret = dvb_attach(tda18271_attach, adap->fe[0], 0xc0, |
e8089661 | 962 | &adap_to_d(adap)->i2c_adap, |
80619de8 AP |
963 | &af9015_tda18271_config) == NULL ? -ENODEV : 0; |
964 | break; | |
ee3d440c | 965 | case AF9013_TUNER_TDA18218: |
a3645e54 | 966 | ret = dvb_attach(tda18218_attach, adap->fe[0], |
e8089661 | 967 | &adap_to_d(adap)->i2c_adap, |
ee3d440c AP |
968 | &af9015_tda18218_config) == NULL ? -ENODEV : 0; |
969 | break; | |
80619de8 | 970 | case AF9013_TUNER_MXL5003D: |
a3645e54 | 971 | ret = dvb_attach(mxl5005s_attach, adap->fe[0], |
e8089661 | 972 | &adap_to_d(adap)->i2c_adap, |
80619de8 AP |
973 | &af9015_mxl5003_config) == NULL ? -ENODEV : 0; |
974 | break; | |
975 | case AF9013_TUNER_MXL5005D: | |
976 | case AF9013_TUNER_MXL5005R: | |
a3645e54 | 977 | ret = dvb_attach(mxl5005s_attach, adap->fe[0], |
e8089661 | 978 | &adap_to_d(adap)->i2c_adap, |
80619de8 AP |
979 | &af9015_mxl5005_config) == NULL ? -ENODEV : 0; |
980 | break; | |
981 | case AF9013_TUNER_ENV77H11D5: | |
a3645e54 | 982 | ret = dvb_attach(dvb_pll_attach, adap->fe[0], 0xc0, |
e8089661 | 983 | &adap_to_d(adap)->i2c_adap, |
80619de8 AP |
984 | DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; |
985 | break; | |
986 | case AF9013_TUNER_MC44S803: | |
a3645e54 | 987 | ret = dvb_attach(mc44s803_attach, adap->fe[0], |
e8089661 | 988 | &adap_to_d(adap)->i2c_adap, |
d5633998 | 989 | &af9015_mc44s803_config) == NULL ? -ENODEV : 0; |
80619de8 | 990 | break; |
ab07fdd6 | 991 | case AF9013_TUNER_MXL5007T: |
a3645e54 | 992 | ret = dvb_attach(mxl5007t_attach, adap->fe[0], |
e8089661 | 993 | &adap_to_d(adap)->i2c_adap, |
ab07fdd6 AP |
994 | 0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0; |
995 | break; | |
80619de8 AP |
996 | case AF9013_TUNER_UNKNOWN: |
997 | default: | |
f224749b AP |
998 | dev_err(&d->udev->dev, "%s: unknown tuner id=%d\n", |
999 | KBUILD_MODNAME, | |
1000 | state->af9013_config[adap->id].tuner); | |
80619de8 | 1001 | ret = -ENODEV; |
80619de8 | 1002 | } |
be4a5e7f | 1003 | |
a3645e54 | 1004 | if (adap->fe[0]->ops.tuner_ops.init) { |
6d535bd8 | 1005 | state->tuner_init[adap->id] = |
a3645e54 AP |
1006 | adap->fe[0]->ops.tuner_ops.init; |
1007 | adap->fe[0]->ops.tuner_ops.init = af9015_tuner_init; | |
6d535bd8 AP |
1008 | } |
1009 | ||
a3645e54 | 1010 | if (adap->fe[0]->ops.tuner_ops.sleep) { |
6d535bd8 | 1011 | state->tuner_sleep[adap->id] = |
a3645e54 AP |
1012 | adap->fe[0]->ops.tuner_ops.sleep; |
1013 | adap->fe[0]->ops.tuner_ops.sleep = af9015_tuner_sleep; | |
1014 | } | |
1015 | ||
1016 | return ret; | |
1017 | } | |
1018 | ||
1019 | static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) | |
1020 | { | |
f224749b | 1021 | struct dvb_usb_device *d = adap_to_d(adap); |
a3645e54 | 1022 | int ret; |
f224749b | 1023 | dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); |
a3645e54 AP |
1024 | |
1025 | if (onoff) | |
f224749b | 1026 | ret = af9015_set_reg_bit(d, 0xd503, 0); |
a3645e54 | 1027 | else |
f224749b | 1028 | ret = af9015_clear_reg_bit(d, 0xd503, 0); |
a3645e54 AP |
1029 | |
1030 | return ret; | |
1031 | } | |
1032 | ||
1033 | static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, | |
1034 | int onoff) | |
1035 | { | |
f224749b | 1036 | struct dvb_usb_device *d = adap_to_d(adap); |
a3645e54 AP |
1037 | int ret; |
1038 | u8 idx; | |
f224749b AP |
1039 | dev_dbg(&d->udev->dev, "%s: index=%d pid=%04x onoff=%d\n", |
1040 | __func__, index, pid, onoff); | |
a3645e54 | 1041 | |
f224749b | 1042 | ret = af9015_write_reg(d, 0xd505, (pid & 0xff)); |
a3645e54 AP |
1043 | if (ret) |
1044 | goto error; | |
1045 | ||
f224749b | 1046 | ret = af9015_write_reg(d, 0xd506, (pid >> 8)); |
a3645e54 AP |
1047 | if (ret) |
1048 | goto error; | |
1049 | ||
1050 | idx = ((index & 0x1f) | (1 << 5)); | |
f224749b | 1051 | ret = af9015_write_reg(d, 0xd504, idx); |
a3645e54 AP |
1052 | |
1053 | error: | |
1054 | return ret; | |
1055 | } | |
1056 | ||
1057 | static int af9015_init_endpoint(struct dvb_usb_device *d) | |
1058 | { | |
e8089661 | 1059 | struct af9015_state *state = d_to_priv(d); |
a3645e54 AP |
1060 | int ret; |
1061 | u16 frame_size; | |
1062 | u8 packet_size; | |
f224749b | 1063 | dev_dbg(&d->udev->dev, "%s: USB speed=%d\n", __func__, d->udev->speed); |
a3645e54 AP |
1064 | |
1065 | if (d->udev->speed == USB_SPEED_FULL) { | |
1066 | frame_size = TS_USB11_FRAME_SIZE/4; | |
1067 | packet_size = TS_USB11_MAX_PACKET_SIZE/4; | |
1068 | } else { | |
1069 | frame_size = TS_USB20_FRAME_SIZE/4; | |
1070 | packet_size = TS_USB20_MAX_PACKET_SIZE/4; | |
1071 | } | |
1072 | ||
1073 | ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */ | |
1074 | if (ret) | |
1075 | goto error; | |
1076 | ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */ | |
1077 | if (ret) | |
1078 | goto error; | |
1079 | ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */ | |
1080 | if (ret) | |
1081 | goto error; | |
1082 | ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */ | |
1083 | if (ret) | |
1084 | goto error; | |
1085 | ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */ | |
1086 | if (ret) | |
1087 | goto error; | |
1088 | if (state->dual_mode) { | |
1089 | ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */ | |
1090 | if (ret) | |
1091 | goto error; | |
1092 | } | |
1093 | ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */ | |
1094 | if (ret) | |
1095 | goto error; | |
1096 | if (state->dual_mode) { | |
1097 | ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */ | |
1098 | if (ret) | |
1099 | goto error; | |
1100 | } | |
1101 | /* EP4 xfer length */ | |
1102 | ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff); | |
1103 | if (ret) | |
1104 | goto error; | |
1105 | ret = af9015_write_reg(d, 0xdd89, frame_size >> 8); | |
1106 | if (ret) | |
1107 | goto error; | |
1108 | /* EP5 xfer length */ | |
1109 | ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff); | |
1110 | if (ret) | |
1111 | goto error; | |
1112 | ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8); | |
1113 | if (ret) | |
1114 | goto error; | |
1115 | ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */ | |
1116 | if (ret) | |
1117 | goto error; | |
1118 | ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */ | |
1119 | if (ret) | |
1120 | goto error; | |
1121 | ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */ | |
1122 | if (ret) | |
1123 | goto error; | |
1124 | if (state->dual_mode) { | |
1125 | ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */ | |
1126 | if (ret) | |
1127 | goto error; | |
6d535bd8 | 1128 | } |
be4a5e7f | 1129 | |
a3645e54 AP |
1130 | /* enable / disable mp2if2 */ |
1131 | if (state->dual_mode) | |
1132 | ret = af9015_set_reg_bit(d, 0xd50b, 0); | |
1133 | else | |
1134 | ret = af9015_clear_reg_bit(d, 0xd50b, 0); | |
1135 | ||
1136 | error: | |
1137 | if (ret) | |
f224749b AP |
1138 | dev_err(&d->udev->dev, "%s: endpoint init failed=%d\n", |
1139 | KBUILD_MODNAME, ret); | |
1140 | ||
a3645e54 AP |
1141 | return ret; |
1142 | } | |
1143 | ||
1144 | static int af9015_init(struct dvb_usb_device *d) | |
1145 | { | |
e8089661 | 1146 | struct af9015_state *state = d_to_priv(d); |
a3645e54 | 1147 | int ret; |
f224749b | 1148 | dev_dbg(&d->udev->dev, "%s:\n", __func__); |
a3645e54 AP |
1149 | |
1150 | mutex_init(&state->fe_mutex); | |
1151 | ||
1152 | /* init RC canary */ | |
1153 | ret = af9015_write_reg(d, 0x98e9, 0xff); | |
1154 | if (ret) | |
1155 | goto error; | |
1156 | ||
1157 | ret = af9015_init_endpoint(d); | |
1158 | if (ret) | |
1159 | goto error; | |
1160 | ||
1161 | error: | |
80619de8 AP |
1162 | return ret; |
1163 | } | |
1164 | ||
37b44a0f | 1165 | #if IS_ENABLED(CONFIG_RC_CORE) |
a3645e54 AP |
1166 | struct af9015_rc_setup { |
1167 | unsigned int id; | |
1168 | char *rc_codes; | |
d07b901f JN |
1169 | }; |
1170 | ||
a3645e54 AP |
1171 | static char *af9015_rc_setup_match(unsigned int id, |
1172 | const struct af9015_rc_setup *table) | |
1173 | { | |
1174 | for (; table->rc_codes; table++) | |
1175 | if (table->id == id) | |
1176 | return table->rc_codes; | |
1177 | return NULL; | |
1178 | } | |
1179 | ||
1180 | static const struct af9015_rc_setup af9015_rc_setup_modparam[] = { | |
1181 | { AF9015_REMOTE_A_LINK_DTU_M, RC_MAP_ALINK_DTU_M }, | |
1182 | { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, RC_MAP_MSI_DIGIVOX_II }, | |
1183 | { AF9015_REMOTE_MYGICTV_U718, RC_MAP_TOTAL_MEDIA_IN_HAND }, | |
1184 | { AF9015_REMOTE_DIGITTRADE_DVB_T, RC_MAP_DIGITTRADE }, | |
1185 | { AF9015_REMOTE_AVERMEDIA_KS, RC_MAP_AVERMEDIA_RM_KS }, | |
d07b901f | 1186 | { } |
80619de8 | 1187 | }; |
80619de8 | 1188 | |
a3645e54 AP |
1189 | static const struct af9015_rc_setup af9015_rc_setup_hashes[] = { |
1190 | { 0xb8feb708, RC_MAP_MSI_DIGIVOX_II }, | |
1191 | { 0xa3703d00, RC_MAP_ALINK_DTU_M }, | |
1192 | { 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */ | |
1193 | { 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */ | |
1194 | { } | |
1195 | }; | |
80619de8 | 1196 | |
a3645e54 AP |
1197 | static int af9015_rc_query(struct dvb_usb_device *d) |
1198 | { | |
e8089661 | 1199 | struct af9015_state *state = d_to_priv(d); |
a3645e54 AP |
1200 | int ret; |
1201 | u8 buf[17]; | |
80619de8 | 1202 | |
a3645e54 AP |
1203 | /* read registers needed to detect remote controller code */ |
1204 | ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf)); | |
1205 | if (ret) | |
1206 | goto error; | |
80619de8 | 1207 | |
a3645e54 | 1208 | /* If any of these are non-zero, assume invalid data */ |
f224749b AP |
1209 | if (buf[1] || buf[2] || buf[3]) { |
1210 | dev_dbg(&d->udev->dev, "%s: invalid data\n", __func__); | |
a3645e54 | 1211 | return ret; |
f224749b | 1212 | } |
80619de8 | 1213 | |
a3645e54 AP |
1214 | /* Check for repeat of previous code */ |
1215 | if ((state->rc_repeat != buf[6] || buf[0]) && | |
1216 | !memcmp(&buf[12], state->rc_last, 4)) { | |
f224749b | 1217 | dev_dbg(&d->udev->dev, "%s: key repeated\n", __func__); |
120703f9 | 1218 | rc_repeat(d->rc_dev); |
a3645e54 AP |
1219 | state->rc_repeat = buf[6]; |
1220 | return ret; | |
1221 | } | |
85d7d7ca | 1222 | |
a3645e54 AP |
1223 | /* Only process key if canary killed */ |
1224 | if (buf[16] != 0xff && buf[0] != 0x01) { | |
2ceeca04 | 1225 | enum rc_type proto; |
f224749b AP |
1226 | dev_dbg(&d->udev->dev, "%s: key pressed %*ph\n", |
1227 | __func__, 4, buf + 12); | |
85d7d7ca | 1228 | |
a3645e54 AP |
1229 | /* Reset the canary */ |
1230 | ret = af9015_write_reg(d, 0x98e9, 0xff); | |
1231 | if (ret) | |
1232 | goto error; | |
85d7d7ca | 1233 | |
a3645e54 AP |
1234 | /* Remember this key */ |
1235 | memcpy(state->rc_last, &buf[12], 4); | |
1236 | if (buf[14] == (u8) ~buf[15]) { | |
1237 | if (buf[12] == (u8) ~buf[13]) { | |
1238 | /* NEC */ | |
120703f9 DH |
1239 | state->rc_keycode = RC_SCANCODE_NEC(buf[12], |
1240 | buf[14]); | |
2ceeca04 | 1241 | proto = RC_TYPE_NEC; |
a3645e54 AP |
1242 | } else { |
1243 | /* NEC extended*/ | |
120703f9 DH |
1244 | state->rc_keycode = RC_SCANCODE_NECX(buf[12] << 8 | |
1245 | buf[13], | |
1246 | buf[14]); | |
2ceeca04 | 1247 | proto = RC_TYPE_NECX; |
a3645e54 AP |
1248 | } |
1249 | } else { | |
1250 | /* 32 bit NEC */ | |
120703f9 DH |
1251 | state->rc_keycode = RC_SCANCODE_NEC32(buf[12] << 24 | |
1252 | buf[13] << 16 | | |
1253 | buf[14] << 8 | | |
1254 | buf[15]); | |
2ceeca04 | 1255 | proto = RC_TYPE_NEC32; |
85d7d7ca | 1256 | } |
2ceeca04 | 1257 | rc_keydown(d->rc_dev, proto, state->rc_keycode, 0); |
a3645e54 | 1258 | } else { |
f224749b | 1259 | dev_dbg(&d->udev->dev, "%s: no key press\n", __func__); |
a3645e54 AP |
1260 | /* Invalidate last keypress */ |
1261 | /* Not really needed, but helps with debug */ | |
1262 | state->rc_last[2] = state->rc_last[3]; | |
1263 | } | |
1264 | ||
1265 | state->rc_repeat = buf[6]; | |
eb29fbea | 1266 | state->rc_failed = false; |
a3645e54 AP |
1267 | |
1268 | error: | |
eb29fbea | 1269 | if (ret) { |
f224749b AP |
1270 | dev_warn(&d->udev->dev, "%s: rc query failed=%d\n", |
1271 | KBUILD_MODNAME, ret); | |
a3645e54 | 1272 | |
eb29fbea AP |
1273 | /* allow random errors as dvb-usb will stop polling on error */ |
1274 | if (!state->rc_failed) | |
1275 | ret = 0; | |
1276 | ||
1277 | state->rc_failed = true; | |
1278 | } | |
1279 | ||
a3645e54 AP |
1280 | return ret; |
1281 | } | |
80619de8 | 1282 | |
a3645e54 | 1283 | static int af9015_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) |
80619de8 | 1284 | { |
e8089661 | 1285 | struct af9015_state *state = d_to_priv(d); |
a3645e54 AP |
1286 | u16 vid = le16_to_cpu(d->udev->descriptor.idVendor); |
1287 | ||
1288 | if (state->ir_mode == AF9015_IR_MODE_DISABLED) | |
1289 | return 0; | |
1290 | ||
1291 | /* try to load remote based module param */ | |
eb29fbea AP |
1292 | if (!rc->map_name) |
1293 | rc->map_name = af9015_rc_setup_match(dvb_usb_af9015_remote, | |
1294 | af9015_rc_setup_modparam); | |
80619de8 | 1295 | |
a3645e54 AP |
1296 | /* try to load remote based eeprom hash */ |
1297 | if (!rc->map_name) | |
1298 | rc->map_name = af9015_rc_setup_match(state->eeprom_sum, | |
1299 | af9015_rc_setup_hashes); | |
1300 | ||
1301 | /* try to load remote based USB iManufacturer string */ | |
1302 | if (!rc->map_name && vid == USB_VID_AFATECH) { | |
1303 | /* Check USB manufacturer and product strings and try | |
1304 | to determine correct remote in case of chip vendor | |
1305 | reference IDs are used. | |
1306 | DO NOT ADD ANYTHING NEW HERE. Use hashes instead. */ | |
1307 | char manufacturer[10]; | |
1308 | memset(manufacturer, 0, sizeof(manufacturer)); | |
1309 | usb_string(d->udev, d->udev->descriptor.iManufacturer, | |
1310 | manufacturer, sizeof(manufacturer)); | |
1311 | if (!strcmp("MSI", manufacturer)) { | |
1312 | /* iManufacturer 1 MSI | |
1313 | iProduct 2 MSI K-VOX */ | |
1314 | rc->map_name = af9015_rc_setup_match( | |
1315 | AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, | |
1316 | af9015_rc_setup_modparam); | |
1317 | } | |
80619de8 AP |
1318 | } |
1319 | ||
de73beee AP |
1320 | /* load empty to enable rc */ |
1321 | if (!rc->map_name) | |
1322 | rc->map_name = RC_MAP_EMPTY; | |
1323 | ||
2ceeca04 | 1324 | rc->allowed_protos = RC_BIT_NEC | RC_BIT_NECX | RC_BIT_NEC32; |
a3645e54 AP |
1325 | rc->query = af9015_rc_query; |
1326 | rc->interval = 500; | |
1327 | ||
1328 | return 0; | |
80619de8 | 1329 | } |
b6215596 AP |
1330 | #else |
1331 | #define af9015_get_rc_config NULL | |
1332 | #endif | |
80619de8 | 1333 | |
e8c7aab5 AP |
1334 | static int af9015_probe(struct usb_interface *intf, |
1335 | const struct usb_device_id *id) | |
1336 | { | |
1337 | struct usb_device *udev = interface_to_usbdev(intf); | |
1338 | char manufacturer[sizeof("ITE Technologies, Inc.")]; | |
1339 | ||
1340 | memset(manufacturer, 0, sizeof(manufacturer)); | |
1341 | usb_string(udev, udev->descriptor.iManufacturer, | |
1342 | manufacturer, sizeof(manufacturer)); | |
1343 | /* | |
1344 | * There is two devices having same ID but different chipset. One uses | |
1345 | * AF9015 and the other IT9135 chipset. Only difference seen on lsusb | |
1346 | * is iManufacturer string. | |
1347 | * | |
1348 | * idVendor 0x0ccd TerraTec Electronic GmbH | |
1349 | * idProduct 0x0099 | |
1350 | * bcdDevice 2.00 | |
1351 | * iManufacturer 1 Afatech | |
1352 | * iProduct 2 DVB-T 2 | |
1353 | * | |
1354 | * idVendor 0x0ccd TerraTec Electronic GmbH | |
1355 | * idProduct 0x0099 | |
1356 | * bcdDevice 2.00 | |
1357 | * iManufacturer 1 ITE Technologies, Inc. | |
1358 | * iProduct 2 DVB-T TV Stick | |
1359 | */ | |
1360 | if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VID_TERRATEC) && | |
1361 | (le16_to_cpu(udev->descriptor.idProduct) == 0x0099)) { | |
1362 | if (!strcmp("ITE Technologies, Inc.", manufacturer)) { | |
1363 | dev_dbg(&udev->dev, "%s: rejecting device\n", __func__); | |
1364 | return -ENODEV; | |
1365 | } | |
1366 | } | |
1367 | ||
1368 | return dvb_usbv2_probe(intf, id); | |
1369 | } | |
1370 | ||
a3645e54 AP |
1371 | /* interface 0 is used by DVB-T receiver and |
1372 | interface 1 is for remote controller (HID) */ | |
1373 | static struct dvb_usb_device_properties af9015_props = { | |
1374 | .driver_name = KBUILD_MODNAME, | |
1375 | .owner = THIS_MODULE, | |
1376 | .adapter_nr = adapter_nr, | |
1377 | .size_of_priv = sizeof(struct af9015_state), | |
1378 | ||
1379 | .generic_bulk_ctrl_endpoint = 0x02, | |
1380 | .generic_bulk_ctrl_endpoint_response = 0x81, | |
1381 | ||
1382 | .identify_state = af9015_identify_state, | |
bab9b4fe | 1383 | .firmware = AF9015_FIRMWARE, |
a3645e54 AP |
1384 | .download_firmware = af9015_download_firmware, |
1385 | ||
a3645e54 | 1386 | .i2c_algo = &af9015_i2c_algo, |
2d2b37c7 AP |
1387 | .read_config = af9015_read_config, |
1388 | .frontend_attach = af9015_af9013_frontend_attach, | |
1389 | .tuner_attach = af9015_tuner_attach, | |
a3645e54 AP |
1390 | .init = af9015_init, |
1391 | .get_rc_config = af9015_get_rc_config, | |
b905a2a1 | 1392 | .get_stream_config = af9015_get_stream_config, |
a3645e54 AP |
1393 | |
1394 | .get_adapter_count = af9015_get_adapter_count, | |
1395 | .adapter = { | |
1396 | { | |
1397 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | |
1398 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | |
1399 | .pid_filter_count = 32, | |
1400 | .pid_filter = af9015_pid_filter, | |
1401 | .pid_filter_ctrl = af9015_pid_filter_ctrl, | |
1a590010 AP |
1402 | |
1403 | .stream = DVB_USB_STREAM_BULK(0x84, 8, TS_USB20_FRAME_SIZE), | |
1404 | }, { | |
1405 | .stream = DVB_USB_STREAM_BULK(0x85, 8, TS_USB20_FRAME_SIZE), | |
a3645e54 | 1406 | }, |
a3645e54 AP |
1407 | }, |
1408 | }; | |
1409 | ||
1410 | static const struct usb_device_id af9015_id_table[] = { | |
1411 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015, | |
1412 | &af9015_props, "Afatech AF9015 reference design", NULL) }, | |
1413 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016, | |
1414 | &af9015_props, "Afatech AF9015 reference design", NULL) }, | |
1415 | { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD, | |
1416 | &af9015_props, "Leadtek WinFast DTV Dongle Gold", RC_MAP_LEADTEK_Y04G0051) }, | |
1417 | { DVB_USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E, | |
1418 | &af9015_props, "Pinnacle PCTV 71e", NULL) }, | |
1419 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U, | |
1420 | &af9015_props, "KWorld PlusTV Dual DVB-T Stick (DVB-T 399U)", NULL) }, | |
1421 | { DVB_USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TINYTWIN, | |
1422 | &af9015_props, "DigitalNow TinyTwin", RC_MAP_AZUREWAVE_AD_TU700) }, | |
1423 | { DVB_USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_AD_TU700, | |
1424 | &af9015_props, "TwinHan AzureWave AD-TU700(704J)", RC_MAP_AZUREWAVE_AD_TU700) }, | |
1425 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2, | |
1426 | &af9015_props, "TerraTec Cinergy T USB XE", NULL) }, | |
1427 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T, | |
1428 | &af9015_props, "KWorld PlusTV Dual DVB-T PCI (DVB-T PC160-2T)", NULL) }, | |
1429 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X, | |
1430 | &af9015_props, "AVerMedia AVerTV DVB-T Volar X", RC_MAP_AVERMEDIA_M135A) }, | |
1431 | { DVB_USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380, | |
1432 | &af9015_props, "Xtensions XD-380", NULL) }, | |
1433 | { DVB_USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO, | |
1434 | &af9015_props, "MSI DIGIVOX Duo", RC_MAP_MSI_DIGIVOX_III) }, | |
1435 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2, | |
1436 | &af9015_props, "Fujitsu-Siemens Slim Mobile USB DVB-T", NULL) }, | |
1437 | { DVB_USB_DEVICE(USB_VID_TELESTAR, USB_PID_TELESTAR_STARSTICK_2, | |
1438 | &af9015_props, "Telestar Starstick 2", NULL) }, | |
1439 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309, | |
1440 | &af9015_props, "AVerMedia A309", NULL) }, | |
1441 | { DVB_USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III, | |
1442 | &af9015_props, "MSI Digi VOX mini III", RC_MAP_MSI_DIGIVOX_III) }, | |
1443 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U, | |
1444 | &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, | |
1445 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2, | |
1446 | &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, | |
1447 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3, | |
1448 | &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, | |
1449 | { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT, | |
1450 | &af9015_props, "TrekStor DVB-T USB Stick", RC_MAP_TREKSTOR) }, | |
1451 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850, | |
1452 | &af9015_props, "AverMedia AVerTV Volar Black HD (A850)", NULL) }, | |
1453 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805, | |
1454 | &af9015_props, "AverMedia AVerTV Volar GPS 805 (A805)", NULL) }, | |
1455 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU, | |
1456 | &af9015_props, "Conceptronic USB2.0 DVB-T CTVDIGRCU V3.0", NULL) }, | |
1457 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810, | |
9165dabb | 1458 | &af9015_props, "KWorld Digital MC-810", NULL) }, |
a3645e54 AP |
1459 | { DVB_USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03, |
1460 | &af9015_props, "Genius TVGo DVB-T03", NULL) }, | |
1461 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2, | |
1462 | &af9015_props, "KWorld PlusTV Dual DVB-T Stick (DVB-T 399U)", NULL) }, | |
1463 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T, | |
1464 | &af9015_props, "KWorld PlusTV DVB-T PCI Pro Card (DVB-T PC160-T)", NULL) }, | |
1465 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20, | |
1466 | &af9015_props, "Sveon STV20 Tuner USB DVB-T HDTV", NULL) }, | |
1467 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2, | |
1468 | &af9015_props, "DigitalNow TinyTwin v2", RC_MAP_DIGITALNOW_TINYTWIN) }, | |
1469 | { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS, | |
1470 | &af9015_props, "Leadtek WinFast DTV2000DS", RC_MAP_LEADTEK_Y04G0051) }, | |
1471 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T, | |
1472 | &af9015_props, "KWorld USB DVB-T Stick Mobile (UB383-T)", NULL) }, | |
1473 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4, | |
1474 | &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) }, | |
1475 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M, | |
1476 | &af9015_props, "AverMedia AVerTV Volar M (A815Mac)", NULL) }, | |
1477 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC, | |
1478 | &af9015_props, "TerraTec Cinergy T Stick RC", RC_MAP_TERRATEC_SLIM_2) }, | |
e8c7aab5 | 1479 | /* XXX: that same ID [0ccd:0099] is used by af9035 driver too */ |
a3645e54 AP |
1480 | { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC, |
1481 | &af9015_props, "TerraTec Cinergy T Stick Dual RC", RC_MAP_TERRATEC_SLIM) }, | |
1482 | { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T, | |
1483 | &af9015_props, "AverMedia AVerTV Red HD+ (A850T)", NULL) }, | |
1484 | { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3, | |
1485 | &af9015_props, "DigitalNow TinyTwin v3", RC_MAP_DIGITALNOW_TINYTWIN) }, | |
1486 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22, | |
1487 | &af9015_props, "Sveon STV22 Dual USB DVB-T Tuner HDTV", RC_MAP_MSI_DIGIVOX_III) }, | |
1488 | { } | |
1489 | }; | |
1490 | MODULE_DEVICE_TABLE(usb, af9015_id_table); | |
1491 | ||
80619de8 AP |
1492 | /* usb specific object needed to register this driver with the usb subsystem */ |
1493 | static struct usb_driver af9015_usb_driver = { | |
a3645e54 | 1494 | .name = KBUILD_MODNAME, |
2d2b37c7 | 1495 | .id_table = af9015_id_table, |
e8c7aab5 | 1496 | .probe = af9015_probe, |
a3645e54 | 1497 | .disconnect = dvb_usbv2_disconnect, |
53dc194f AP |
1498 | .suspend = dvb_usbv2_suspend, |
1499 | .resume = dvb_usbv2_resume, | |
04966aa8 | 1500 | .reset_resume = dvb_usbv2_reset_resume, |
a3645e54 | 1501 | .no_dynamic_id = 1, |
77f54517 | 1502 | .soft_unbind = 1, |
80619de8 AP |
1503 | }; |
1504 | ||
ecb3b2b3 | 1505 | module_usb_driver(af9015_usb_driver); |
80619de8 AP |
1506 | |
1507 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | |
bc050e67 | 1508 | MODULE_DESCRIPTION("Afatech AF9015 driver"); |
80619de8 | 1509 | MODULE_LICENSE("GPL"); |
bab9b4fe | 1510 | MODULE_FIRMWARE(AF9015_FIRMWARE); |