[media] drxk: Don't assume a default firmware name
[deliverable/linux.git] / drivers / media / dvb / dvb-usb / az6007.c
CommitLineData
25c16466
MCC
1/*
2 * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones
3 *
4 * Copyright (c) Henry Wang <Henry.wang@AzureWave.com>
5 *
6 * This driver was made publicly available by Terratec, at:
7 * http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
8 * The original driver's license is GPL, as declared with MODULE_LICENSE()
9 *
10 * Driver modifiyed by Mauro Carvalho Chehab <mchehab@redhat.com> in order
11 * to work with upstream drxk driver, and to fix some bugs.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation under version 2 of the License.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
71d67634
MCC
21 */
22
71d67634
MCC
23#include "drxk.h"
24#include "mt2063.h"
25#include "dvb_ca_en50221.h"
70fa444d
MCC
26#include "dvb-usb.h"
27
28#define DVB_USB_LOG_PREFIX "az6007"
71d67634
MCC
29
30/* debug */
31int dvb_usb_az6007_debug;
93b32126
MCC
32module_param_named(debug, dvb_usb_az6007_debug, int, 0644);
33MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))."
34 DVB_USB_DEBUG_STATUS);
71d67634 35
70fa444d
MCC
36#define deb_info(args...) dprintk(dvb_usb_az6007_debug, 0x01, args)
37#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug, 0x02, args)
38#define deb_rc(args...) dprintk(dvb_usb_az6007_debug, 0x04, args)
39#define deb_fe(args...) dprintk(dvb_usb_az6007_debug, 0x08, args)
40
71d67634
MCC
41DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
42
71d67634 43struct az6007_device_state {
93b32126
MCC
44 struct dvb_ca_en50221 ca;
45 struct mutex ca_mutex;
46 u8 power_state;
71d67634 47
6da34706 48 /* Due to DRX-K - probably need changes */
93b32126
MCC
49 int (*gate_ctrl) (struct dvb_frontend *, int);
50 struct semaphore pll_mutex;
6da34706 51 bool dont_attach_fe1;
71d67634
MCC
52};
53
93b32126 54static struct drxk_config terratec_h7_drxk = {
6da34706
MCC
55 .adr = 0x29,
56 .single_master = 1,
d20a7f72 57 .no_i2c_bridge = 0,
da989e0b
MCC
58 .max_size = 64,
59// .microcode_name = "dvb-usb-terratec-h5-drxk.fw",
71d67634
MCC
60};
61
6da34706
MCC
62static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
63{
64 struct dvb_usb_adapter *adap = fe->sec_priv;
caa1a700 65 struct az6007_device_state *st;
f2ba9e5d 66 int status = 0;
6da34706 67
f2ba9e5d 68 deb_info("%s: %s\n", __func__, enable ? "enable" : "disable");
caa1a700
MCC
69
70 if (!adap)
71 return -EINVAL;
72
73 st = adap->priv;
74
75 if (!st)
6da34706
MCC
76 return -EINVAL;
77
78 if (enable) {
2212501f 79#if 0
6da34706 80 down(&st->pll_mutex);
2212501f 81#endif
6da34706
MCC
82 status = st->gate_ctrl(fe, 1);
83 } else {
2212501f 84#if 0
6da34706 85 status = st->gate_ctrl(fe, 0);
2212501f 86#endif
6da34706
MCC
87 up(&st->pll_mutex);
88 }
89 return status;
90}
91
93b32126 92static struct mt2063_config az6007_mt2063_config = {
caa1a700 93 .tuner_address = 0x60,
71d67634
MCC
94 .refclock = 36125000,
95};
96
97/* check for mutex FIXME */
93b32126
MCC
98static int az6007_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
99 u16 index, u8 *b, int blen)
71d67634
MCC
100{
101 int ret = -1;
102
93b32126
MCC
103 ret = usb_control_msg(d->udev,
104 usb_rcvctrlpipe(d->udev, 0),
105 req,
106 USB_TYPE_VENDOR | USB_DIR_IN,
107 value, index, b, blen, 5000);
71d67634
MCC
108
109 if (ret < 0) {
110 warn("usb in operation failed. (%d)", ret);
caa1a700
MCC
111 return -EIO;
112 }
71d67634 113
93b32126
MCC
114 deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value,
115 index);
116 debug_dump(b, blen, deb_xfer);
71d67634
MCC
117
118 return ret;
119}
120
121static int az6007_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
122 u16 index, u8 *b, int blen)
123{
124 int ret;
125
93b32126
MCC
126 deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value,
127 index);
128 debug_dump(b, blen, deb_xfer);
71d67634 129
35753580 130 if (blen > 64) {
da989e0b
MCC
131 err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n",
132 blen);
35753580 133 return -EOPNOTSUPP;
71d67634 134 }
35753580 135
93b32126
MCC
136 ret = usb_control_msg(d->udev,
137 usb_sndctrlpipe(d->udev, 0),
138 req,
139 USB_TYPE_VENDOR | USB_DIR_OUT,
140 value, index, b, blen, 5000);
141 if (ret != blen) {
f2ba9e5d 142 err("usb out operation failed. (%d)", ret);
35753580 143 return -EIO;
71d67634 144 }
6da34706 145
71d67634
MCC
146 return 0;
147}
148
149static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
150{
151 return 0;
152}
153
154/* keys for the enclosed remote control */
93b32126
MCC
155static struct rc_map_table rc_map_az6007_table[] = {
156 {0x0001, KEY_1},
157 {0x0002, KEY_2},
71d67634
MCC
158};
159
160/* remote control stuff (does not work with my box) */
93b32126 161static int az6007_rc_query(struct dvb_usb_device *d, u32 * event, int *state)
71d67634
MCC
162{
163 return 0;
164#if 0
165 u8 key[10];
166 int i;
167
93b32126 168 /* remove the following return to enabled remote querying */
71d67634 169
93b32126 170 az6007_usb_in_op(d, READ_REMOTE_REQ, 0, 0, key, 10);
71d67634 171
93b32126 172 deb_rc("remote query key: %x %d\n", key[1], key[1]);
71d67634
MCC
173
174 if (key[1] == 0x44) {
175 *state = REMOTE_NO_KEY_PRESSED;
176 return 0;
177 }
178
179 for (i = 0; i < ARRAY_SIZE(az6007_rc_keys); i++)
180 if (az6007_rc_keys[i].custom == key[1]) {
181 *state = REMOTE_KEY_PRESSED;
182 *event = az6007_rc_keys[i].event;
183 break;
184 }
185 return 0;
186#endif
187}
188
189/*
190int az6007_power_ctrl(struct dvb_usb_device *d, int onoff)
191{
192 u8 v = onoff;
193 return az6007_usb_out_op(d,0xBC,v,3,NULL,1);
194}
195*/
196
93b32126 197static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
71d67634
MCC
198{
199 az6007_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6);
200 return 0;
201}
202
203static int az6007_frontend_poweron(struct dvb_usb_adapter *adap)
204{
205 int ret;
206 u8 req;
207 u16 value;
208 u16 index;
209 int blen;
210
f2ba9e5d
MCC
211 deb_info("az6007_frontend_poweron adap=%p adap->dev=%p\n",
212 adap, adap->dev);
71d67634
MCC
213
214 req = 0xBC;
35753580 215 value = 1; /* power on */
71d67634 216 index = 3;
93b32126 217 blen = 0;
71d67634 218
93b32126
MCC
219 ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen);
220 if (ret != 0) {
71d67634 221 err("az6007_frontend_poweron failed!!!");
93b32126 222 return -EIO;
71d67634
MCC
223 }
224
225 msleep_interruptible(200);
226
227 req = 0xBC;
35753580 228 value = 0; /* power off */
71d67634 229 index = 3;
93b32126 230 blen = 0;
71d67634 231
93b32126
MCC
232 ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen);
233 if (ret != 0) {
71d67634 234 err("az6007_frontend_poweron failed!!!");
93b32126 235 return -EIO;
71d67634
MCC
236 }
237
238 msleep_interruptible(200);
239
240 req = 0xBC;
35753580 241 value = 1; /* power on */
71d67634 242 index = 3;
93b32126 243 blen = 0;
71d67634 244
93b32126
MCC
245 ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen);
246 if (ret != 0) {
71d67634 247 err("az6007_frontend_poweron failed!!!");
93b32126 248 return -EIO;
71d67634 249 }
f2ba9e5d 250 deb_info("az6007_frontend_poweron: OK\n");
caa1a700 251
71d67634
MCC
252 return 0;
253}
254
255static int az6007_frontend_reset(struct dvb_usb_adapter *adap)
256{
257 int ret;
258 u8 req;
259 u16 value;
260 u16 index;
261 int blen;
262
f2ba9e5d 263 deb_info("az6007_frontend_reset adap=%p adap->dev=%p\n", adap, adap->dev);
6da34706 264
93b32126 265 /* reset demodulator */
71d67634 266 req = 0xC0;
93b32126 267 value = 1; /* high */
71d67634 268 index = 3;
93b32126
MCC
269 blen = 0;
270 ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen);
271 if (ret != 0) {
71d67634 272 err("az6007_frontend_reset failed 1 !!!");
93b32126 273 return -EIO;
71d67634 274 }
6da34706 275
71d67634 276 req = 0xC0;
93b32126 277 value = 0; /* low */
71d67634 278 index = 3;
93b32126 279 blen = 0;
71d67634 280 msleep_interruptible(200);
93b32126
MCC
281 ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen);
282 if (ret != 0) {
71d67634 283 err("az6007_frontend_reset failed 2 !!!");
93b32126 284 return -EIO;
71d67634
MCC
285 }
286 msleep_interruptible(200);
287 req = 0xC0;
93b32126 288 value = 1; /* high */
71d67634 289 index = 3;
93b32126 290 blen = 0;
71d67634 291
93b32126
MCC
292 ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen);
293 if (ret != 0) {
71d67634 294 err("az6007_frontend_reset failed 3 !!!");
93b32126 295 return -EIO;
71d67634 296 }
6da34706 297
71d67634 298 msleep_interruptible(200);
6da34706 299
f2ba9e5d 300 deb_info("reset az6007 frontend\n");
6da34706 301
71d67634
MCC
302 return 0;
303}
304
305static int az6007_led_on_off(struct usb_interface *intf, int onoff)
306{
307 int ret = -1;
308 u8 req;
309 u16 value;
310 u16 index;
311 int blen;
93b32126 312 /* TS through */
71d67634
MCC
313 req = 0xBC;
314 value = onoff;
315 index = 0;
93b32126 316 blen = 0;
71d67634
MCC
317
318 ret = usb_control_msg(interface_to_usbdev(intf),
93b32126
MCC
319 usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
320 req,
321 USB_TYPE_VENDOR | USB_DIR_OUT,
322 value, index, NULL, blen, 2000);
71d67634
MCC
323
324 if (ret < 0) {
325 warn("usb in operation failed. (%d)", ret);
326 ret = -EIO;
327 } else
328 ret = 0;
329
93b32126
MCC
330 deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value,
331 index);
71d67634
MCC
332
333 return ret;
334}
335
93b32126 336static int az6007_frontend_tsbypass(struct dvb_usb_adapter *adap, int onoff)
71d67634
MCC
337{
338 int ret;
339 u8 req;
340 u16 value;
341 u16 index;
342 int blen;
93b32126 343 /* TS through */
71d67634
MCC
344 req = 0xC7;
345 value = onoff;
346 index = 0;
93b32126 347 blen = 0;
71d67634 348
93b32126
MCC
349 ret = az6007_usb_out_op(adap->dev, req, value, index, NULL, blen);
350 if (ret != 0)
351 return -EIO;
71d67634
MCC
352 return 0;
353}
354
355static int az6007_frontend_attach(struct dvb_usb_adapter *adap)
356{
6da34706
MCC
357 struct az6007_device_state *st = adap->priv;
358
359 int result;
360
caa1a700
MCC
361 BUG_ON(!st);
362
71d67634
MCC
363 az6007_frontend_poweron(adap);
364 az6007_frontend_reset(adap);
365
f2ba9e5d 366 info("az6007: attaching demod drxk");
6da34706
MCC
367 adap->fe = dvb_attach(drxk_attach, &terratec_h7_drxk,
368 &adap->dev->i2c_adap, &adap->fe2);
369 if (!adap->fe) {
370 result = -EINVAL;
371 goto out_free;
71d67634 372 }
6da34706 373
f2ba9e5d 374 deb_info("Setting hacks\n");
caa1a700 375
6da34706
MCC
376 /* FIXME: do we need a pll semaphore? */
377 adap->fe->sec_priv = adap;
378 sema_init(&st->pll_mutex, 1);
379 st->gate_ctrl = adap->fe->ops.i2c_gate_ctrl;
380 adap->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
381 adap->fe2->id = 1;
382
f2ba9e5d 383 info("az6007: attaching tuner mt2063");
6da34706
MCC
384 /* Attach mt2063 to DVB-C frontend */
385 if (adap->fe->ops.i2c_gate_ctrl)
386 adap->fe->ops.i2c_gate_ctrl(adap->fe, 1);
387 if (!dvb_attach(mt2063_attach, adap->fe, &az6007_mt2063_config,
388 &adap->dev->i2c_adap)) {
389 result = -EINVAL;
390
391 goto out_free;
71d67634 392 }
6da34706
MCC
393 if (adap->fe->ops.i2c_gate_ctrl)
394 adap->fe->ops.i2c_gate_ctrl(adap->fe, 0);
395
396 /* Hack - needed due to drxk */
397 adap->fe2->tuner_priv = adap->fe->tuner_priv;
398 memcpy(&adap->fe2->ops.tuner_ops,
93b32126 399 &adap->fe->ops.tuner_ops, sizeof(adap->fe->ops.tuner_ops));
da989e0b 400
71d67634 401 return 0;
6da34706
MCC
402
403out_free:
404 if (adap->fe)
405 dvb_frontend_detach(adap->fe);
406 adap->fe = NULL;
407 adap->fe2 = NULL;
408
409 return result;
71d67634
MCC
410}
411
412static struct dvb_usb_device_properties az6007_properties;
413
93b32126 414static void az6007_usb_disconnect(struct usb_interface *intf)
71d67634 415{
93b32126 416 dvb_usb_device_exit(intf);
71d67634
MCC
417}
418
419/* I2C */
93b32126
MCC
420static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
421 int num)
71d67634
MCC
422{
423 struct dvb_usb_device *d = i2c_get_adapdata(adap);
caa1a700
MCC
424 int i, j, len;
425 int ret = 0;
71d67634
MCC
426 u16 index;
427 u16 value;
428 int length;
caa1a700 429 u8 req, addr;
71d67634 430 u8 data[512];
6da34706 431
71d67634
MCC
432 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
433 return -EAGAIN;
71d67634 434
caa1a700
MCC
435 for (i = 0; i < num; i++) {
436 addr = msgs[i].addr << 1;
caa1a700
MCC
437 if (((i + 1) < num)
438 && (msgs[i].len == 1)
439 && (!msgs[i].flags & I2C_M_RD)
440 && (msgs[i + 1].flags & I2C_M_RD)
441 && (msgs[i].addr == msgs[i + 1].addr)) {
442 /*
443 * A write + read xfer for the same address, where
444 * the first xfer has just 1 byte length.
445 * Need to join both into one operation
446 */
d20a7f72
MCC
447 if (dvb_usb_az6007_debug & 2)
448 printk(KERN_DEBUG
449 "az6007 I2C xfer write+read addr=0x%x len=%d/%d: ",
450 addr, msgs[i].len, msgs[i + 1].len);
caa1a700 451 req = 0xb9;
d20a7f72
MCC
452 index = msgs[i].buf[0];
453 value = addr | (1 << 8);
caa1a700
MCC
454 length = 6 + msgs[i + 1].len;
455 len = msgs[i + 1].len;
93b32126
MCC
456 ret = az6007_usb_in_op(d, req, value, index, data,
457 length);
caa1a700
MCC
458 if (ret >= len) {
459 for (j = 0; j < len; j++) {
460 msgs[i + 1].buf[j] = data[j + 5];
d20a7f72
MCC
461 if (dvb_usb_az6007_debug & 2)
462 printk(KERN_CONT
463 "0x%02x ",
464 msgs[i + 1].buf[j]);
caa1a700
MCC
465 }
466 } else
467 ret = -EIO;
468 i++;
469 } else if (!(msgs[i].flags & I2C_M_RD)) {
470 /* write bytes */
d20a7f72
MCC
471 if (dvb_usb_az6007_debug & 2)
472 printk(KERN_DEBUG
473 "az6007 I2C xfer write addr=0x%x len=%d: ",
474 addr, msgs[i].len);
caa1a700
MCC
475 req = 0xbd;
476 index = msgs[i].buf[0];
477 value = addr | (1 << 8);
478 length = msgs[i].len - 1;
479 len = msgs[i].len - 1;
d20a7f72 480 if (dvb_usb_az6007_debug & 2)
93b32126
MCC
481 printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]);
482 for (j = 0; j < len; j++) {
caa1a700 483 data[j] = msgs[i].buf[j + 1];
d20a7f72 484 if (dvb_usb_az6007_debug & 2)
93b32126 485 printk(KERN_CONT "0x%02x ", data[j]);
71d67634 486 }
93b32126
MCC
487 ret = az6007_usb_out_op(d, req, value, index, data,
488 length);
caa1a700
MCC
489 } else {
490 /* read bytes */
d20a7f72
MCC
491 if (dvb_usb_az6007_debug & 2)
492 printk(KERN_DEBUG
493 "az6007 I2C xfer read addr=0x%x len=%d: ",
494 addr, msgs[i].len);
caa1a700
MCC
495 req = 0xb9;
496 index = msgs[i].buf[0];
497 value = addr;
498 length = msgs[i].len + 6;
499 len = msgs[i].len;
93b32126
MCC
500 ret = az6007_usb_in_op(d, req, value, index, data,
501 length);
502 for (j = 0; j < len; j++) {
caa1a700 503 msgs[i].buf[j] = data[j + 5];
d20a7f72
MCC
504 if (dvb_usb_az6007_debug & 2)
505 printk(KERN_CONT
506 "0x%02x ", data[j + 5]);
71d67634 507 }
71d67634 508 }
d20a7f72
MCC
509 if (dvb_usb_az6007_debug & 2)
510 printk(KERN_CONT "\n");
caa1a700
MCC
511 if (ret < 0)
512 goto err;
71d67634 513 }
caa1a700 514err:
71d67634 515 mutex_unlock(&d->i2c_mutex);
caa1a700
MCC
516
517 if (ret < 0) {
f2ba9e5d 518 info("%s ERROR: %i", __func__, ret);
caa1a700
MCC
519 return ret;
520 }
521 return num;
71d67634
MCC
522}
523
71d67634
MCC
524static u32 az6007_i2c_func(struct i2c_adapter *adapter)
525{
526 return I2C_FUNC_I2C;
527}
528
529static struct i2c_algorithm az6007_i2c_algo = {
93b32126 530 .master_xfer = az6007_i2c_xfer,
71d67634 531 .functionality = az6007_i2c_func,
71d67634
MCC
532};
533
93b32126
MCC
534int az6007_identify_state(struct usb_device *udev,
535 struct dvb_usb_device_properties *props,
536 struct dvb_usb_device_description **desc, int *cold)
71d67634
MCC
537{
538 u8 b[16];
93b32126
MCC
539 s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
540 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b,
541 6, USB_CTRL_GET_TIMEOUT);
71d67634 542
f2ba9e5d 543 deb_info("FW GET_VERSION length: %d\n", ret);
71d67634
MCC
544
545 *cold = ret <= 0;
546
f2ba9e5d 547 deb_info("cold: %d\n", *cold);
71d67634
MCC
548 return 0;
549}
550
551static int az6007_usb_probe(struct usb_interface *intf,
93b32126 552 const struct usb_device_id *id)
71d67634 553{
6da34706
MCC
554 az6007_led_on_off(intf, 0);
555
71d67634 556 return dvb_usb_device_init(intf, &az6007_properties,
6da34706 557 THIS_MODULE, NULL, adapter_nr);
71d67634
MCC
558}
559
93b32126
MCC
560static struct usb_device_id az6007_usb_table[] = {
561 {USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007)},
562 {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7)},
563 {0},
71d67634
MCC
564};
565
566MODULE_DEVICE_TABLE(usb, az6007_usb_table);
567
568static struct dvb_usb_device_properties az6007_properties = {
569 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
570 .usb_ctrl = CYPRESS_FX2,
71d67634
MCC
571 .firmware = "dvb-usb-az6007-03.fw",
572 .no_reconnect = 1,
573
71d67634
MCC
574 .identify_state = az6007_identify_state,
575 .num_adapters = 1,
576 .adapter = {
577 {
71d67634
MCC
578 .streaming_ctrl = az6007_streaming_ctrl,
579 .frontend_attach = az6007_frontend_attach,
580
581 /* parameter for the MPEG2-data transfer */
582 .stream = {
583 .type = USB_BULK,
584 .count = 10,
585 .endpoint = 0x02,
586 .u = {
587 .bulk = {
588 .buffersize = 4096,
589 }
590 }
591 },
caa1a700 592 .size_of_priv = sizeof(struct az6007_device_state),
71d67634
MCC
593 }
594 },
93b32126 595 /* .power_ctrl = az6007_power_ctrl, */
71d67634
MCC
596 .read_mac_address = az6007_read_mac_addr,
597
6da34706
MCC
598 .rc.legacy = {
599 .rc_map_table = rc_map_az6007_table,
600 .rc_map_size = ARRAY_SIZE(rc_map_az6007_table),
601 .rc_interval = 400,
602 .rc_query = az6007_rc_query,
603 },
71d67634
MCC
604 .i2c_algo = &az6007_i2c_algo,
605
606 .num_device_descs = 2,
607 .devices = {
608 { .name = "AzureWave DTV StarBox DVB-T/C USB2.0 (az6007)",
609 .cold_ids = { &az6007_usb_table[0], NULL },
610 .warm_ids = { NULL },
611 },
612 { .name = "TerraTec DTV StarBox DVB-T/C USB2.0 (az6007)",
613 .cold_ids = { &az6007_usb_table[1], NULL },
614 .warm_ids = { NULL },
615 },
6da34706 616 { NULL },
71d67634
MCC
617 }
618};
6da34706 619
71d67634
MCC
620/* usb specific object needed to register this driver with the usb subsystem */
621static struct usb_driver az6007_usb_driver = {
622 .name = "dvb_usb_az6007",
93b32126 623 .probe = az6007_usb_probe,
71d67634 624 .disconnect = dvb_usb_device_exit,
93b32126
MCC
625 /* .disconnect = az6007_usb_disconnect, */
626 .id_table = az6007_usb_table,
71d67634
MCC
627};
628
629/* module stuff */
630static int __init az6007_usb_module_init(void)
631{
632 int result;
f2ba9e5d 633 deb_info("az6007 usb module init\n");
93b32126
MCC
634
635 result = usb_register(&az6007_usb_driver);
636 if (result) {
637 err("usb_register failed. (%d)", result);
71d67634
MCC
638 return result;
639 }
640
641 return 0;
642}
643
644static void __exit az6007_usb_module_exit(void)
645{
646 /* deregister this driver from the USB subsystem */
f2ba9e5d 647 deb_info("az6007 usb module exit\n");
71d67634
MCC
648 usb_deregister(&az6007_usb_driver);
649}
650
651module_init(az6007_usb_module_init);
652module_exit(az6007_usb_module_exit);
653
654MODULE_AUTHOR("Henry Wang <Henry.wang@AzureWave.com>");
655MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones");
35753580 656MODULE_VERSION("1.1");
71d67634 657MODULE_LICENSE("GPL");
This page took 0.073087 seconds and 5 git commands to generate.