blob: 6e96c11a0c19e1978f847c29cb596d8bea02a197 [file] [log] [blame]
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -03001/* DVB USB compliant linux driver for MSI Mega Sky 580 DVB-T USB2.0 receiver
2 *
3 * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.org)
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation, version 2.
8 *
9 * see Documentation/dvb/README.dvb-usb for more information
10 */
Michael Krufkybaa2ed02006-09-23 20:01:29 -030011
Michael Krufky2aef7d02006-09-23 20:00:42 -030012#include "m920x.h"
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030013
14#include "mt352.h"
15#include "mt352_priv.h"
16
17/* debug */
Michael Krufkybaa2ed02006-09-23 20:01:29 -030018int dvb_usb_m920x_debug;
19module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030020MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
21
22static struct dvb_usb_rc_key megasky_rc_keys [] = {
23 { 0x0, 0x12, KEY_POWER },
24 { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */
25 { 0x0, 0x02, KEY_CHANNELUP },
26 { 0x0, 0x05, KEY_CHANNELDOWN },
27 { 0x0, 0x03, KEY_VOLUMEUP },
28 { 0x0, 0x06, KEY_VOLUMEDOWN },
29 { 0x0, 0x04, KEY_MUTE },
30 { 0x0, 0x07, KEY_OK }, /* TS */
31 { 0x0, 0x08, KEY_STOP },
32 { 0x0, 0x09, KEY_MENU }, /* swap */
33 { 0x0, 0x0a, KEY_REWIND },
34 { 0x0, 0x1b, KEY_PAUSE },
35 { 0x0, 0x1f, KEY_FASTFORWARD },
36 { 0x0, 0x0c, KEY_RECORD },
37 { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */
38 { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */
39};
40
41static inline int m9206_read(struct usb_device *udev, u8 request, u16 value, u16 index, void *data, int size)
42{
43 int ret;
44
45 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
46 request, USB_TYPE_VENDOR | USB_DIR_IN,
47 value, index, data, size, 2000);
48 if (ret < 0)
49 return ret;
50
51 if (ret != size)
52 return -EIO;
53
54 return 0;
55}
56
57static inline int m9206_write(struct usb_device *udev, u8 request, u16 value, u16 index)
58{
59 int ret;
60
61 ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
62 request, USB_TYPE_VENDOR | USB_DIR_OUT,
63 value, index, NULL, 0, 2000);
64 msleep(3);
65
66 return ret;
67}
68
69static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
70{
71 int i, ret = 0;
72 u8 rc_state[2];
73
74 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
75 return -EAGAIN;
76
77 if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff51, rc_state, 1)) != 0)
78 goto unlock;
79
80 if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff52, rc_state + 1, 1)) != 0)
81 goto unlock;
82
83 for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++)
84 if (megasky_rc_keys[i].data == rc_state[1]) {
85 *event = megasky_rc_keys[i].event;
86
87 switch(rc_state[0]) {
88 case 0x80:
89 *state = REMOTE_NO_KEY_PRESSED;
90 goto unlock;
91
92 case 0x93:
93 case 0x92:
94 *state = REMOTE_KEY_PRESSED;
95 goto unlock;
96
97 case 0x91:
98 *state = REMOTE_KEY_REPEAT;
99 goto unlock;
100
101 default:
102 deb_rc("Unexpected rc response %x\n", rc_state[0]);
103 *state = REMOTE_NO_KEY_PRESSED;
104 goto unlock;
105 }
106 }
107
108 if (rc_state[1] != 0)
109 deb_rc("Unknown rc key %x\n", rc_state[1]);
110
111 *state = REMOTE_NO_KEY_PRESSED;
112
113 unlock:
114 mutex_unlock(&d->i2c_mutex);
115
116 return ret;
117}
118
119/* I2C */
120
121static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
122{
123 struct dvb_usb_device *d = i2c_get_adapdata(adap);
124 int i;
125 int ret = 0;
126
127 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
128 return -EAGAIN;
129
130 if (num > 2)
131 return -EINVAL;
132
133 for (i = 0; i < num; i++) {
134 u8 w_len;
135
136 if ((ret = m9206_write(d->udev, 0x23, msg[i].addr, 0x80)) != 0)
137 goto unlock;
138
139 if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[0], 0x0)) != 0)
140 goto unlock;
141
142 if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) {
143 if (msg[i].addr == 0x1e)
144 w_len = 0x1f;
145 else
146 w_len = 0xc5;
147
148 if ((ret = m9206_write(d->udev, 0x23, w_len, 0x80)) != 0)
149 goto unlock;
150
151 if ((ret = m9206_read(d->udev, 0x23, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0)
152 goto unlock;
153
154 i++;
155 } else {
156 if (msg[i].len != 2)
157 return -EINVAL;
158
159 if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[1], 0x40)) != 0)
160 goto unlock;
161 }
162 }
163 ret = i;
164 unlock:
165 mutex_unlock(&d->i2c_mutex);
166
167 return ret;
168}
169
170static u32 m9206_i2c_func(struct i2c_adapter *adapter)
171{
172 return I2C_FUNC_I2C;
173}
174
175static struct i2c_algorithm m9206_i2c_algo = {
176 .master_xfer = m9206_i2c_xfer,
177 .functionality = m9206_i2c_func,
178};
179
180/* Callbacks for DVB USB */
181static int megasky_identify_state (struct usb_device *udev,
Michael Krufky01cb34d2006-09-23 20:01:29 -0300182 struct dvb_usb_device_properties *props,
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300183 struct dvb_usb_device_description **desc,
184 int *cold)
185{
186 struct usb_host_interface *alt;
187
188 alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1);
189 *cold = (alt == NULL) ? 1 : 0;
190
191 return 0;
192}
193
194static int megasky_mt352_demod_init(struct dvb_frontend *fe)
195{
196 int i;
197 static u8 buf1[] = {
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300198 CONFIG, 0x3d,
199 CLOCK_CTL, 0x30,
200 RESET, 0x80,
201 ADC_CTL_1, 0x40,
202 AGC_TARGET, 0x1c,
203 AGC_CTL, 0x20,
204 0x69, 0x00,
205 0x6a, 0xff,
206 0x6b, 0xff,
207 0x6c, 0x40,
208 0x6d, 0xff,
209 0x6e, 0x00,
210 0x6f, 0x40,
211 0x70, 0x40,
212 0x93, 0x1a,
213 0xb5, 0x7a,
214 ACQ_CTL, 0x50,
215 INPUT_FREQ_1, 0x31,
216 INPUT_FREQ_0, 0x05,
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300217 };
218
219 for (i = 0; i < ARRAY_SIZE(buf1); i += 2)
220 mt352_write(fe, &buf1[i], 2);
221
222 deb_rc("Demod init!\n");
223
224 return 0;
225}
226
227struct mt352_state;
228
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300229#define W 0
230#define R 1
231/* Not actual hw limits. */
232#define QT1010_MIN_STEP 2000000
233#define QT1010_MIN_FREQ 48000000
234
235int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len)
236{
237 int i;
238 int div, mod;
239 struct {
240 u8 read, reg, value;
241 } rd[46] = { { W, 0x01, 0x80 },
242 { W, 0x02, 0x3f },
243 { W, 0x05, 0xff }, /* c */
244 { W, 0x06, 0x44 },
245 { W, 0x07, 0xff }, /* c */
246 { W, 0x08, 0x08 },
247 { W, 0x09, 0xff }, /* c */
248 { W, 0x0a, 0xff }, /* c */
249 { W, 0x0b, 0xff }, /* c */
250 { W, 0x0c, 0xe1 },
251 { W, 0x1a, 0xff }, /* 10 c */
252 { W, 0x1b, 0x00 },
253 { W, 0x1c, 0x89 },
254 { W, 0x11, 0xff }, /* c */
255 { W, 0x12, 0x91 },
256 { W, 0x22, 0xff }, /* c */
257 { W, 0x1e, 0x00 },
258 { W, 0x1e, 0xd0 },
259 { R, 0x22, 0xff }, /* c read */
260 { W, 0x1e, 0x00 },
261 { R, 0x05, 0xff }, /* 20 c read */
262 { R, 0x22, 0xff }, /* c read */
263 { W, 0x23, 0xd0 },
264 { W, 0x1e, 0x00 },
265 { W, 0x1e, 0xe0 },
266 { R, 0x23, 0xff }, /* c read */
267 { W, 0x1e, 0x00 },
268 { W, 0x24, 0xd0 },
269 { W, 0x1e, 0x00 },
270 { W, 0x1e, 0xf0 },
271 { R, 0x24, 0xff }, /* 30 c read */
272 { W, 0x1e, 0x00 },
273 { W, 0x14, 0x7f },
274 { W, 0x15, 0x7f },
275 { W, 0x05, 0xff }, /* c */
276 { W, 0x06, 0x00 },
277 { W, 0x15, 0x1f },
278 { W, 0x16, 0xff },
279 { W, 0x18, 0xff },
280 { W, 0x1f, 0xff }, /* c */
281 { W, 0x20, 0xff }, /* 40 c */
282 { W, 0x21, 0x53 },
283 { W, 0x25, 0xbd },
284 { W, 0x26, 0x15 },
285 { W, 0x02, 0x00 },
286 { W, 0x01, 0x00 },
287 };
288 struct i2c_msg msg;
289 struct dvb_usb_device *d = fe->dvb->priv;
290 unsigned long freq = params->frequency;
291
292 if (freq % QT1010_MIN_STEP)
293 deb_rc("frequency not supported.\n");
294
295 (void) buf;
296 (void) buf_len;
297
298 div = (freq - QT1010_MIN_FREQ) / QT1010_MIN_STEP;
299 mod = (div + 16 - 9) % 16;
300
301 /* 0x5 */
302 if (div >= 377)
303 rd[2].value = 0x74;
304 else if (div >= 265)
305 rd[2].value = 0x54;
306 else if (div >= 121)
307 rd[2].value = 0x34;
308 else
309 rd[2].value = 0x14;
310
311 /* 0x7 */
312 rd[4].value = (((freq - QT1010_MIN_FREQ) / 1000000) * 9975 + 12960000) / 320000;
313
314 /* 09 */
315 if (mod < 4)
316 rd[6].value = 0x1d;
317 else
318 rd[6].value = 0x1c;
319
320 /* 0a */
321 if (mod < 2)
322 rd[7].value = 0x09;
323 else if (mod < 4)
324 rd[7].value = 0x08;
325 else if (mod < 6)
326 rd[7].value = 0x0f;
327 else if (mod < 8)
328 rd[7].value = 0x0e;
329 else if (mod < 10)
330 rd[7].value = 0x0d;
331 else if (mod < 12)
332 rd[7].value = 0x0c;
333 else if (mod < 14)
334 rd[7].value = 0x0b;
335 else
336 rd[7].value = 0x0a;
337
338 /* 0b */
339 if (div & 1)
340 rd[8].value = 0x45;
341 else
342 rd[8].value = 0x44;
343
344 /* 1a */
345 if (div & 1)
346 rd[10].value = 0x78;
347 else
348 rd[10].value = 0xf8;
349
350 /* 11 */
351 if (div >= 265)
352 rd[13].value = 0xf9;
353 else if (div >= 121)
354 rd[13].value = 0xfd;
355 else
356 rd[13].value = 0xf9;
357
358 /* 22 */
359 if (div < 201)
360 rd[15].value = 0xd0;
361 else if (div < 217)
362 rd[15].value = 0xd3;
363 else if (div < 233)
364 rd[15].value = 0xd6;
365 else if (div < 249)
366 rd[15].value = 0xd9;
367 else if (div < 265)
368 rd[15].value = 0xda;
369 else
370 rd[15].value = 0xd0;
371
372 /* 05 */
373 if (div >= 377)
374 rd[34].value = 0x70;
375 else if (div >= 265)
376 rd[34].value = 0x50;
377 else if (div >= 121)
378 rd[34].value = 0x30;
379 else
380 rd[34].value = 0x10;
381
382 /* 1f */
383 if (mod < 4)
384 rd[39].value = 0x64;
385 else if (mod < 6)
386 rd[39].value = 0x66;
387 else if (mod < 8)
388 rd[39].value = 0x67;
389 else if (mod < 12)
390 rd[39].value = 0x68;
391 else if (mod < 14)
392 rd[39].value = 0x69;
393 else
394 rd[39].value = 0x6a;
395
396 /* 20 */
397 if (mod < 4)
398 rd[40].value = 0x10;
399 else if (mod < 6)
400 rd[40].value = 0x11;
401 else if (mod < 10)
402 rd[40].value = 0x12;
403 else if (mod < 12)
404 rd[40].value = 0x13;
405 else if (mod < 14)
406 rd[40].value = 0x14;
407 else
408 rd[40].value = 0x15;
409
410 deb_rc("Now tuning... ");
411 for (i = 0; i < sizeof(rd) / sizeof(*rd); i++) {
412 if (rd[i].read)
413 continue;
414
415 msg.flags = 0;
416 msg.len = 2;
417 msg.addr = 0xc4;
418 msg.buf = &rd[i].reg;
419
420 if (i2c_transfer(&d->i2c_adap, &msg, 1) != 1) {
421 deb_rc("tuner write failed\n");
422 return -EIO;
423 }
424 }
425 deb_rc("done\n");
426
427 return 0;
428}
429#undef W
430#undef R
431
432static struct mt352_config megasky_mt352_config = {
433 .demod_address = 0x1e,
434 .demod_init = megasky_mt352_demod_init,
435};
436
Michael Krufky01cb34d2006-09-23 20:01:29 -0300437static int megasky_frontend_attach(struct dvb_usb_adapter *adap)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300438{
439 deb_rc("megasky_frontend_attach!\n");
440
Michael Krufky01cb34d2006-09-23 20:01:29 -0300441 if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) != NULL) {
442 adap->fe->ops.tuner_ops.calc_regs = qt1010_set_params;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300443 return 0;
444 }
445 return -EIO;
446}
447
448/* DVB USB Driver stuff */
Michael Krufky01cb34d2006-09-23 20:01:29 -0300449static struct dvb_usb_device_properties megasky_properties;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300450
451static int megasky_probe(struct usb_interface *intf, const struct usb_device_id *id)
452{
453 struct dvb_usb_device *d;
454 struct usb_host_interface *alt;
455 int ret;
456
457 if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) {
458 deb_rc("probed!\n");
459
460 alt = usb_altnum_to_altsetting(intf, 1);
461 if (alt == NULL) {
462 deb_rc("not alt found!\n");
463 return -ENODEV;
464 }
465
466 ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting);
467 if (ret < 0)
468 return ret;
469
470 deb_rc("Changed to alternate setting!\n");
471
472 /* Remote controller init. */
473 if ((ret = m9206_write(d->udev, 0x22, 0xa8, 0xff55)) != 0)
474 return ret;
475
476 if ((ret = m9206_write(d->udev, 0x22, 0x51, 0xff54)) != 0)
477 return ret;
478 }
479 return ret;
480}
481
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300482static struct usb_device_id m920x_table [] = {
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300483 { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) },
484 { } /* Terminating entry */
485};
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300486MODULE_DEVICE_TABLE (usb, m920x_table);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300487
Michael Krufky01cb34d2006-09-23 20:01:29 -0300488static int set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300489{
490 int ret = 0;
491
492 if (pid >= 0x8000)
493 return -EINVAL;
494
495 pid |= 0x8000;
496
Michael Krufky01cb34d2006-09-23 20:01:29 -0300497 if ((ret = m9206_write(adap->dev->udev, 0x25, pid, (type << 8) | (idx * 4) )) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300498 return ret;
499
Michael Krufky01cb34d2006-09-23 20:01:29 -0300500 if ((ret = m9206_write(adap->dev->udev, 0x25, 0, (type << 8) | (idx * 4) )) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300501 return ret;
502
503 return ret;
504}
505
Michael Krufky01cb34d2006-09-23 20:01:29 -0300506static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300507{
508 int ret = 0;
509
Michael Krufky01cb34d2006-09-23 20:01:29 -0300510 if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300511 return -EAGAIN;
512
513 deb_rc("filtering %s\n", onoff ? "on" : "off");
514 if (onoff == 0) {
Michael Krufky01cb34d2006-09-23 20:01:29 -0300515 if ((ret = set_filter(adap, 0x81, 1, 0x00)) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300516 goto unlock;
517
Michael Krufky01cb34d2006-09-23 20:01:29 -0300518 if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300519 goto unlock;
520 }
521 unlock:
Michael Krufky01cb34d2006-09-23 20:01:29 -0300522 mutex_unlock(&adap->dev->i2c_mutex);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300523
524 return ret;
525}
526
Michael Krufky01cb34d2006-09-23 20:01:29 -0300527static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300528{
529 int ret = 0;
530
531 if (pid == 8192)
Michael Krufky01cb34d2006-09-23 20:01:29 -0300532 return m9206_pid_filter_ctrl(adap, !onoff);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300533
Michael Krufky01cb34d2006-09-23 20:01:29 -0300534 if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300535 return -EAGAIN;
536
537 deb_rc("filter %d, pid %x, %s\n", index, pid, onoff ? "on" : "off");
538 if (onoff == 0)
539 pid = 0;
540
Michael Krufky01cb34d2006-09-23 20:01:29 -0300541 if ((ret = set_filter(adap, 0x81, 1, 0x01)) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300542 goto unlock;
543
Michael Krufky01cb34d2006-09-23 20:01:29 -0300544 if ((ret = set_filter(adap, 0x81, index + 2, pid)) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300545 goto unlock;
546
Michael Krufky01cb34d2006-09-23 20:01:29 -0300547 if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300548 goto unlock;
549
550 unlock:
Michael Krufky01cb34d2006-09-23 20:01:29 -0300551 mutex_unlock(&adap->dev->i2c_mutex);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300552
553 return ret;
554}
555
556static int m9206_firmware_download(struct usb_device *udev, const struct firmware *fw)
557{
558 u16 value, index, size;
559 u8 read[4], *buff;
560 int i, pass, ret = 0;
561
562 buff = kmalloc(65536, GFP_KERNEL);
563
564 if ((ret = m9206_read(udev, 0x25, 0x0, 0x8000, read, 4)) != 0)
565 goto done;
566 deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
567
568 if ((ret = m9206_read(udev, 0x30, 0x0, 0x0, read, 1)) != 0)
569 goto done;
570 deb_rc("%x\n", read[0]);
571
572 for (pass = 0; pass < 2; pass++) {
573 for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
574 value = le16_to_cpu(*(u16 *)(fw->data + i));
575 i += sizeof(u16);
576
577 index = le16_to_cpu(*(u16 *)(fw->data + i));
578 i += sizeof(u16);
579
580 size = le16_to_cpu(*(u16 *)(fw->data + i));
581 i += sizeof(u16);
582
583 if (pass == 1) {
584 /* Will stall if using fw->data ... */
585 memcpy(buff, fw->data + i, size);
586
587 ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
588 0x30, USB_TYPE_VENDOR | USB_DIR_OUT,
589 value, index, buff, size, 20);
590 if (ret != size) {
591 deb_rc("error while uploading fw!\n");
592 ret = -EIO;
593 goto done;
594 }
595 msleep(3);
596 }
597 i += size;
598 }
599 if (i != fw->size) {
600 ret = -EINVAL;
601 goto done;
602 }
603 }
604
605 msleep(36);
606
607 /* m9206 will disconnect itself from the bus after this. */
608 (void) m9206_write(udev, 0x22, 0x01, 0xff69);
609 deb_rc("firmware uploaded!\n");
610
611 done:
612 kfree(buff);
613
614 return ret;
615}
616
Michael Krufky01cb34d2006-09-23 20:01:29 -0300617static struct dvb_usb_device_properties megasky_properties = {
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300618 .usb_ctrl = DEVICE_SPECIFIC,
619 .firmware = "dvb-usb-megasky-02.fw",
620 .download_firmware = m9206_firmware_download,
621
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300622 .rc_interval = 200,
623 .rc_key_map = megasky_rc_keys,
624 .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys),
625 .rc_query = m9206_rc_query,
626
627 .size_of_priv = 0,
628
629 .identify_state = megasky_identify_state,
Michael Krufky01cb34d2006-09-23 20:01:29 -0300630 .num_adapters = 1,
631 .adapter = {{
632 .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_ADAP_HAS_PID_FILTER |
633 DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF |
634 DVB_USB_ADAP_NEED_PID_FILTERING,
635 .pid_filter_count = 8,
636 .pid_filter = m9206_pid_filter,
637 .pid_filter_ctrl = m9206_pid_filter_ctrl,
638
639 .frontend_attach = megasky_frontend_attach,
640
641 .stream = {
642 .type = USB_BULK,
643 .count = 8,
644 .endpoint = 0x81,
645 .u = {
646 .bulk = {
647 .buffersize = 512,
648 }
649 }
650 },
651 }},
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300652 .i2c_algo = &m9206_i2c_algo,
653
654 .generic_bulk_ctrl_endpoint = 0x01,
Michael Krufky01cb34d2006-09-23 20:01:29 -0300655
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300656 .num_device_descs = 1,
657 .devices = {
658 { "MSI Mega Sky 580 DVB-T USB2.0",
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300659 { &m920x_table[0], NULL },
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300660 { NULL },
661 },
662 { NULL },
663 }
664};
665
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300666static struct usb_driver m920x_driver = {
667 .name = "dvb_usb_m920x",
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300668 .probe = megasky_probe,
669 .disconnect = dvb_usb_device_exit,
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300670 .id_table = m920x_table,
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300671};
672
673/* module stuff */
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300674static int __init m920x_module_init(void)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300675{
676 int ret;
677
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300678 if ((ret = usb_register(&m920x_driver))) {
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300679 err("usb_register failed. Error number %d", ret);
680 return ret;
681 }
682
683 return 0;
684}
685
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300686static void __exit m920x_module_exit(void)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300687{
688 /* deregister this driver from the USB subsystem */
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300689 usb_deregister(&m920x_driver);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300690}
691
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300692module_init (m920x_module_init);
693module_exit (m920x_module_exit);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300694
695MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300696MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x");
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300697MODULE_VERSION("0.1");
698MODULE_LICENSE("GPL");