diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb-v2/af9035.c')
-rw-r--r-- | drivers/media/usb/dvb-usb-v2/af9035.c | 1086 |
1 files changed, 1086 insertions, 0 deletions
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"); | ||