blob: 45d7bc214c18eb6e0e6f110079f0ba27209ea7cb [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"
Michael Krufky017cf012006-09-23 20:40:20 -030016#include "qt1010.h"
Pierre Willenbrockd4ca23b2007-03-18 19:54:07 -030017#include "tda1004x.h"
18#include "tda827x.h"
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030019
20/* debug */
Michael Krufky26f48ea2006-09-28 01:46:49 -030021static int dvb_usb_m920x_debug;
Michael Krufkybaa2ed02006-09-23 20:01:29 -030022module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030023MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
24
25static struct dvb_usb_rc_key megasky_rc_keys [] = {
26 { 0x0, 0x12, KEY_POWER },
27 { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */
28 { 0x0, 0x02, KEY_CHANNELUP },
29 { 0x0, 0x05, KEY_CHANNELDOWN },
30 { 0x0, 0x03, KEY_VOLUMEUP },
31 { 0x0, 0x06, KEY_VOLUMEDOWN },
32 { 0x0, 0x04, KEY_MUTE },
33 { 0x0, 0x07, KEY_OK }, /* TS */
34 { 0x0, 0x08, KEY_STOP },
35 { 0x0, 0x09, KEY_MENU }, /* swap */
36 { 0x0, 0x0a, KEY_REWIND },
37 { 0x0, 0x1b, KEY_PAUSE },
38 { 0x0, 0x1f, KEY_FASTFORWARD },
39 { 0x0, 0x0c, KEY_RECORD },
40 { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */
41 { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */
42};
43
Michael Krufkyfa948052007-01-21 15:57:48 -030044static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\
45 u16 index, void *data, int size)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030046{
47 int ret;
48
49 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
50 request, USB_TYPE_VENDOR | USB_DIR_IN,
51 value, index, data, size, 2000);
Pierre Willenbrock59069e52007-03-15 13:24:29 -030052 if (ret < 0) {
53 printk(KERN_INFO "m920x_read = error: %d\n", ret);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030054 return ret;
Pierre Willenbrock59069e52007-03-15 13:24:29 -030055 }
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030056
Pierre Willenbrock59069e52007-03-15 13:24:29 -030057 if (ret != size) {
58 deb_rc("m920x_read = no data\n");
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030059 return -EIO;
Pierre Willenbrock59069e52007-03-15 13:24:29 -030060 }
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030061
62 return 0;
63}
64
Michael Krufkyfa948052007-01-21 15:57:48 -030065static inline int m9206_write(struct usb_device *udev, u8 request,
66 u16 value, u16 index)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030067{
68 int ret;
69
70 ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
71 request, USB_TYPE_VENDOR | USB_DIR_OUT,
72 value, index, NULL, 0, 2000);
Pierre Willenbrock59069e52007-03-15 13:24:29 -030073
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -030074 return ret;
75}
76
Aapo Tahkola480ac762007-03-05 18:54:27 -030077static int m9206_init(struct dvb_usb_device *d)
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -030078{
79 int ret = 0;
80
81 /* Remote controller init. */
Aapo Tahkola480ac762007-03-05 18:54:27 -030082 if (d->props.rc_query) {
83 if ((ret = m9206_write(d->udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0)
84 return ret;
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -030085
Aapo Tahkola480ac762007-03-05 18:54:27 -030086 if ((ret = m9206_write(d->udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0)
87 return ret;
88 }
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030089
90 return ret;
91}
92
93static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
94{
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -030095 struct m9206_state *m = d->priv;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -030096 int i, ret = 0;
97 u8 rc_state[2];
98
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -030099 if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300100 goto unlock;
101
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300102 if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300103 goto unlock;
104
Aapo Tahkola480ac762007-03-05 18:54:27 -0300105 for (i = 0; i < d->props.rc_key_map_size; i++)
106 if (d->props.rc_key_map[i].data == rc_state[1]) {
107 *event = d->props.rc_key_map[i].event;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300108
109 switch(rc_state[0]) {
110 case 0x80:
111 *state = REMOTE_NO_KEY_PRESSED;
112 goto unlock;
113
114 case 0x93:
115 case 0x92:
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300116 m->rep_count = 0;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300117 *state = REMOTE_KEY_PRESSED;
118 goto unlock;
119
120 case 0x91:
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300121 /* For comfort. */
122 if (++m->rep_count > 2)
123 *state = REMOTE_KEY_REPEAT;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300124 goto unlock;
125
126 default:
127 deb_rc("Unexpected rc response %x\n", rc_state[0]);
128 *state = REMOTE_NO_KEY_PRESSED;
129 goto unlock;
130 }
131 }
132
133 if (rc_state[1] != 0)
134 deb_rc("Unknown rc key %x\n", rc_state[1]);
135
136 *state = REMOTE_NO_KEY_PRESSED;
137
138 unlock:
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300139
140 return ret;
141}
142
143/* I2C */
Michael Krufkyfa948052007-01-21 15:57:48 -0300144static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
145 int num)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300146{
147 struct dvb_usb_device *d = i2c_get_adapdata(adap);
Aapo Tahkola26247012007-03-05 18:23:19 -0300148 int i, j;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300149 int ret = 0;
150
Trent Piephod40860f2007-03-05 23:55:00 -0300151 if (!num)
152 return -EINVAL;
153
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300154 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
155 return -EAGAIN;
156
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300157 for (i = 0; i < num; i++) {
Trent Piepho57f8dcf2007-03-12 12:13:12 -0300158 if (msg[i].flags & (I2C_M_NO_RD_ACK|I2C_M_IGNORE_NAK|I2C_M_TEN) ||
159 msg[i].len == 0) {
160 /* For a 0 byte message, I think sending the address to index 0x80|0x40
161 * would be the correct thing to do. However, zero byte messages are
162 * only used for probing, and since we don't know how to get the slave's
163 * ack, we can't probe. */
Trent Piephod40860f2007-03-05 23:55:00 -0300164 ret = -ENOTSUPP;
165 goto unlock;
166 }
167 /* Send START & address/RW bit */
168 if (!(msg[i].flags & I2C_M_NOSTART)) {
Trent Piepho57f8dcf2007-03-12 12:13:12 -0300169 if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), 0x80)) != 0)
Trent Piephod40860f2007-03-05 23:55:00 -0300170 goto unlock;
171 /* Should check for ack here, if we knew how. */
172 }
Aapo Tahkola26247012007-03-05 18:23:19 -0300173 if (msg[i].flags & I2C_M_RD) {
Trent Piephod40860f2007-03-05 23:55:00 -0300174 for (j = 0; j < msg[i].len; j++) {
175 /* Last byte of transaction? Send STOP, otherwise send ACK. */
176 int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x01;
177 if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x20|stop, &msg[i].buf[j], 1)) != 0)
178 goto unlock;
Aapo Tahkola84ad7572007-01-21 15:57:20 -0300179 }
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300180 } else {
Trent Piephod40860f2007-03-05 23:55:00 -0300181 for (j = 0; j < msg[i].len; j++) {
182 /* Last byte of transaction? Then send STOP. */
183 int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x00;
184 if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0)
185 goto unlock;
186 /* Should check for ack here too. */
Aapo Tahkola26247012007-03-05 18:23:19 -0300187 }
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300188 }
189 }
Aapo Tahkola26247012007-03-05 18:23:19 -0300190 ret = num;
Trent Piephod40860f2007-03-05 23:55:00 -0300191
192unlock:
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300193 mutex_unlock(&d->i2c_mutex);
194
195 return ret;
196}
197
198static u32 m9206_i2c_func(struct i2c_adapter *adapter)
199{
200 return I2C_FUNC_I2C;
201}
202
203static struct i2c_algorithm m9206_i2c_algo = {
204 .master_xfer = m9206_i2c_xfer,
205 .functionality = m9206_i2c_func,
206};
207
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300208
Michael Krufkyfa948052007-01-21 15:57:48 -0300209static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx,
210 int pid)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300211{
212 int ret = 0;
213
214 if (pid >= 0x8000)
215 return -EINVAL;
216
217 pid |= 0x8000;
218
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300219 if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300220 return ret;
221
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300222 if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
223 return ret;
224
225 return ret;
226}
227
228static int m9206_update_filters(struct dvb_usb_adapter *adap)
229{
230 struct m9206_state *m = adap->dev->priv;
231 int enabled = m->filtering_enabled;
232 int i, ret = 0, filter = 0;
233
234 for (i = 0; i < M9206_MAX_FILTERS; i++)
235 if (m->filters[i] == 8192)
236 enabled = 0;
237
238 /* Disable all filters */
Michael Krufky26f48ea2006-09-28 01:46:49 -0300239 if ((ret = m9206_set_filter(adap, 0x81, 1, enabled)) != 0)
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300240 return ret;
241
242 for (i = 0; i < M9206_MAX_FILTERS; i++)
Michael Krufky26f48ea2006-09-28 01:46:49 -0300243 if ((ret = m9206_set_filter(adap, 0x81, i + 2, 0)) != 0)
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300244 return ret;
245
Michael Krufky26f48ea2006-09-28 01:46:49 -0300246 if ((ret = m9206_set_filter(adap, 0x82, 0, 0x0)) != 0)
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300247 return ret;
248
249 /* Set */
250 if (enabled) {
251 for (i = 0; i < M9206_MAX_FILTERS; i++) {
252 if (m->filters[i] == 0)
253 continue;
254
Michael Krufky26f48ea2006-09-28 01:46:49 -0300255 if ((ret = m9206_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0)
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300256 return ret;
257
258 filter++;
259 }
260 }
261
Michael Krufky26f48ea2006-09-28 01:46:49 -0300262 if ((ret = m9206_set_filter(adap, 0x82, 0, 0x02f5)) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300263 return ret;
264
265 return ret;
266}
267
Michael Krufky01cb34d2006-09-23 20:01:29 -0300268static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300269{
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300270 struct m9206_state *m = adap->dev->priv;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300271
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300272 m->filtering_enabled = onoff ? 1 : 0;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300273
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300274 return m9206_update_filters(adap);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300275}
276
Michael Krufkyfa948052007-01-21 15:57:48 -0300277static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
278 int onoff)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300279{
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300280 struct m9206_state *m = adap->dev->priv;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300281
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300282 m->filters[index] = onoff ? pid : 0;
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300283
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300284 return m9206_update_filters(adap);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300285}
286
Michael Krufkyfa948052007-01-21 15:57:48 -0300287static int m9206_firmware_download(struct usb_device *udev,
288 const struct firmware *fw)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300289{
290 u16 value, index, size;
291 u8 read[4], *buff;
292 int i, pass, ret = 0;
293
294 buff = kmalloc(65536, GFP_KERNEL);
295
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300296 if ((ret = m9206_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300297 goto done;
298 deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
299
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300300 if ((ret = m9206_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300301 goto done;
302 deb_rc("%x\n", read[0]);
303
304 for (pass = 0; pass < 2; pass++) {
305 for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
306 value = le16_to_cpu(*(u16 *)(fw->data + i));
307 i += sizeof(u16);
308
309 index = le16_to_cpu(*(u16 *)(fw->data + i));
310 i += sizeof(u16);
311
312 size = le16_to_cpu(*(u16 *)(fw->data + i));
313 i += sizeof(u16);
314
315 if (pass == 1) {
316 /* Will stall if using fw->data ... */
317 memcpy(buff, fw->data + i, size);
318
319 ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300320 M9206_FW,
321 USB_TYPE_VENDOR | USB_DIR_OUT,
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300322 value, index, buff, size, 20);
323 if (ret != size) {
324 deb_rc("error while uploading fw!\n");
325 ret = -EIO;
326 goto done;
327 }
328 msleep(3);
329 }
330 i += size;
331 }
332 if (i != fw->size) {
Pierre Willenbrock59069e52007-03-15 13:24:29 -0300333 deb_rc("bad firmware file!\n");
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300334 ret = -EINVAL;
335 goto done;
336 }
337 }
338
339 msleep(36);
340
341 /* m9206 will disconnect itself from the bus after this. */
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300342 (void) m9206_write(udev, M9206_CORE, 0x01, M9206_FW_GO);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300343 deb_rc("firmware uploaded!\n");
344
345 done:
346 kfree(buff);
347
348 return ret;
349}
350
Michael Krufkye16c1f52007-01-23 15:00:42 -0300351/* Callbacks for DVB USB */
Aapo Tahkola7d1d4e62007-03-15 13:01:46 -0300352static int m920x_identify_state(struct usb_device *udev,
353 struct dvb_usb_device_properties *props,
354 struct dvb_usb_device_description **desc,
355 int *cold)
Michael Krufkye16c1f52007-01-23 15:00:42 -0300356{
357 struct usb_host_interface *alt;
358
359 alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1);
360 *cold = (alt == NULL) ? 1 : 0;
361
362 return 0;
363}
364
365static int megasky_mt352_demod_init(struct dvb_frontend *fe)
366{
367 u8 config[] = { CONFIG, 0x3d };
368 u8 clock[] = { CLOCK_CTL, 0x30 };
369 u8 reset[] = { RESET, 0x80 };
370 u8 adc_ctl[] = { ADC_CTL_1, 0x40 };
371 u8 agc[] = { AGC_TARGET, 0x1c, 0x20 };
372 u8 sec_agc[] = { 0x69, 0x00, 0xff, 0xff, 0x40, 0xff, 0x00, 0x40, 0x40 };
373 u8 unk1[] = { 0x93, 0x1a };
374 u8 unk2[] = { 0xb5, 0x7a };
375
376 mt352_write(fe, config, ARRAY_SIZE(config));
377 mt352_write(fe, clock, ARRAY_SIZE(clock));
378 mt352_write(fe, reset, ARRAY_SIZE(reset));
379 mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl));
380 mt352_write(fe, agc, ARRAY_SIZE(agc));
381 mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc));
382 mt352_write(fe, unk1, ARRAY_SIZE(unk1));
383 mt352_write(fe, unk2, ARRAY_SIZE(unk2));
384
385 deb_rc("Demod init!\n");
386
387 return 0;
388}
389
390static struct mt352_config megasky_mt352_config = {
Aapo Tahkola26247012007-03-05 18:23:19 -0300391 .demod_address = 0x0f,
Michael Krufkye16c1f52007-01-23 15:00:42 -0300392 .no_tuner = 1,
393 .demod_init = megasky_mt352_demod_init,
394};
395
396static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap)
397{
Michael Krufkye16c1f52007-01-23 15:00:42 -0300398 deb_rc("megasky_frontend_attach!\n");
399
Michael Krufkye16c1f52007-01-23 15:00:42 -0300400 if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL)
401 return -EIO;
402
403 return 0;
404}
405
Antti Palosaaricbdc80e2007-01-21 15:56:10 -0300406static struct qt1010_config megasky_qt1010_config = {
Aapo Tahkola26247012007-03-05 18:23:19 -0300407 .i2c_address = 0x62
Antti Palosaaricbdc80e2007-01-21 15:56:10 -0300408};
409
Michael Krufkye16c1f52007-01-23 15:00:42 -0300410static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
Antti Palosaaricbdc80e2007-01-21 15:56:10 -0300411{
Aapo Tahkola84ad7572007-01-21 15:57:20 -0300412 if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
413 &megasky_qt1010_config) == NULL)
414 return -ENODEV;
415
416 return 0;
Antti Palosaaricbdc80e2007-01-21 15:56:10 -0300417}
418
Pierre Willenbrockd4ca23b2007-03-18 19:54:07 -0300419static struct tda1004x_config digivox_tda10046_config = {
420 .demod_address = 0x08,
421 .invert = 0,
422 .invert_oclk = 0,
423 .ts_mode = TDA10046_TS_SERIAL,
424 .xtal_freq = TDA10046_XTAL_16M,
425 .if_freq = TDA10046_FREQ_045,
426 .agc_config = TDA10046_AGC_TDA827X,
427 .gpio_config = TDA10046_GPTRI,
428 .request_firmware = NULL,
429};
430
431static int digivox_tda10046_frontend_attach(struct dvb_usb_adapter *adap)
432{
433 deb_rc("digivox_tda10046_frontend_attach!\n");
434
435 if ((adap->fe = dvb_attach(tda10046_attach, &digivox_tda10046_config,
436 &adap->dev->i2c_adap)) == NULL)
437 return -EIO;
438
439 return 0;
440}
441
442static int digivox_tda8275_tuner_attach(struct dvb_usb_adapter *adap)
443{
444 if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap,
445 NULL) == NULL)
446 return -ENODEV;
447 return 0;
448}
449
Michael Krufky26f48ea2006-09-28 01:46:49 -0300450/* DVB USB Driver stuff */
451static struct dvb_usb_device_properties megasky_properties;
Pierre Willenbrockd4ca23b2007-03-18 19:54:07 -0300452static struct dvb_usb_device_properties digivox_mini_ii_properties;
Michael Krufky26f48ea2006-09-28 01:46:49 -0300453
Michael Krufkyfa948052007-01-21 15:57:48 -0300454static int m920x_probe(struct usb_interface *intf,
455 const struct usb_device_id *id)
Michael Krufky26f48ea2006-09-28 01:46:49 -0300456{
457 struct dvb_usb_device *d;
458 struct usb_host_interface *alt;
459 int ret;
460
Aapo Tahkola480ac762007-03-05 18:54:27 -0300461 deb_rc("Probed!\n");
Michael Krufky26f48ea2006-09-28 01:46:49 -0300462
Pierre Willenbrockd4ca23b2007-03-18 19:54:07 -0300463 if (((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) ||
464 ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, THIS_MODULE, &d)) == 0))
Aapo Tahkola480ac762007-03-05 18:54:27 -0300465 goto found;
Michael Krufky26f48ea2006-09-28 01:46:49 -0300466
Aapo Tahkola480ac762007-03-05 18:54:27 -0300467 return ret;
Michael Krufky26f48ea2006-09-28 01:46:49 -0300468
Aapo Tahkola480ac762007-03-05 18:54:27 -0300469found:
470 alt = usb_altnum_to_altsetting(intf, 1);
471 if (alt == NULL) {
472 deb_rc("No alt found!\n");
473 return -ENODEV;
Michael Krufky26f48ea2006-09-28 01:46:49 -0300474 }
Aapo Tahkola480ac762007-03-05 18:54:27 -0300475
476 ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
477 alt->desc.bAlternateSetting);
478 if (ret < 0)
479 return ret;
480
481 if ((ret = m9206_init(d)) != 0)
482 return ret;
483
Michael Krufky26f48ea2006-09-28 01:46:49 -0300484 return ret;
485}
486
487static struct usb_device_id m920x_table [] = {
488 { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) },
Pierre Willenbrockd4ca23b2007-03-18 19:54:07 -0300489 { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC,
490 USB_PID_MSI_DIGI_VOX_MINI_II) },
Michael Krufky26f48ea2006-09-28 01:46:49 -0300491 { } /* Terminating entry */
492};
493MODULE_DEVICE_TABLE (usb, m920x_table);
494
Michael Krufky01cb34d2006-09-23 20:01:29 -0300495static struct dvb_usb_device_properties megasky_properties = {
Michael Krufky758117c2007-01-23 15:34:10 -0300496 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
Michael Krufky1f61f3b2006-10-07 15:03:04 -0300497
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300498 .usb_ctrl = DEVICE_SPECIFIC,
499 .firmware = "dvb-usb-megasky-02.fw",
500 .download_firmware = m9206_firmware_download,
501
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300502 .rc_interval = 100,
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300503 .rc_key_map = megasky_rc_keys,
504 .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys),
505 .rc_query = m9206_rc_query,
506
Aapo Tahkolae2adbecf72006-09-28 00:47:51 -0300507 .size_of_priv = sizeof(struct m9206_state),
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300508
Aapo Tahkola7d1d4e62007-03-15 13:01:46 -0300509 .identify_state = m920x_identify_state,
Michael Krufky01cb34d2006-09-23 20:01:29 -0300510 .num_adapters = 1,
511 .adapter = {{
Michael Krufky758117c2007-01-23 15:34:10 -0300512 .caps = DVB_USB_ADAP_HAS_PID_FILTER |
513 DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
514
Michael Krufky01cb34d2006-09-23 20:01:29 -0300515 .pid_filter_count = 8,
516 .pid_filter = m9206_pid_filter,
517 .pid_filter_ctrl = m9206_pid_filter_ctrl,
518
Michael Krufkye16c1f52007-01-23 15:00:42 -0300519 .frontend_attach = megasky_mt352_frontend_attach,
520 .tuner_attach = megasky_qt1010_tuner_attach,
Michael Krufky01cb34d2006-09-23 20:01:29 -0300521
522 .stream = {
523 .type = USB_BULK,
524 .count = 8,
525 .endpoint = 0x81,
526 .u = {
527 .bulk = {
528 .buffersize = 512,
529 }
530 }
531 },
532 }},
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300533 .i2c_algo = &m9206_i2c_algo,
534
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300535 .num_device_descs = 1,
536 .devices = {
537 { "MSI Mega Sky 580 DVB-T USB2.0",
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300538 { &m920x_table[0], NULL },
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300539 { NULL },
Pierre Willenbrockd4ca23b2007-03-18 19:54:07 -0300540 }
541 }
542};
543
544static struct dvb_usb_device_properties digivox_mini_ii_properties = {
545 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
546
547 .usb_ctrl = DEVICE_SPECIFIC,
548 .firmware = "dvb-usb-digivox-02.fw",
549 .download_firmware = m9206_firmware_download,
550
551 .size_of_priv = sizeof(struct m9206_state),
552
553 .identify_state = m920x_identify_state,
554 .num_adapters = 1,
555 .adapter = {{
556 .caps = DVB_USB_ADAP_HAS_PID_FILTER |
557 DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
558
559 .pid_filter_count = 8,
560 .pid_filter = m9206_pid_filter,
561 .pid_filter_ctrl = m9206_pid_filter_ctrl,
562
563 .frontend_attach = digivox_tda10046_frontend_attach,
564 .tuner_attach = digivox_tda8275_tuner_attach,
565
566 .stream = {
567 .type = USB_BULK,
568 .count = 8,
569 .endpoint = 0x81,
570 .u = {
571 .bulk = {
572 .buffersize = 0x4000,
573 }
574 }
575 },
576 }},
577 .i2c_algo = &m9206_i2c_algo,
578
579 .num_device_descs = 1,
580 .devices = {
581 { "MSI DIGI VOX mini II DVB-T USB2.0",
582 { &m920x_table[1], NULL },
583 { NULL },
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300584 },
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300585 }
586};
587
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300588static struct usb_driver m920x_driver = {
589 .name = "dvb_usb_m920x",
Michael Krufky2a2bfa72006-09-23 20:13:12 -0300590 .probe = m920x_probe,
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300591 .disconnect = dvb_usb_device_exit,
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300592 .id_table = m920x_table,
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300593};
594
595/* module stuff */
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300596static int __init m920x_module_init(void)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300597{
598 int ret;
599
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300600 if ((ret = usb_register(&m920x_driver))) {
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300601 err("usb_register failed. Error number %d", ret);
602 return ret;
603 }
604
605 return 0;
606}
607
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300608static void __exit m920x_module_exit(void)
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300609{
610 /* deregister this driver from the USB subsystem */
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300611 usb_deregister(&m920x_driver);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300612}
613
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300614module_init (m920x_module_init);
615module_exit (m920x_module_exit);
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300616
617MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
Michael Krufkybaa2ed02006-09-23 20:01:29 -0300618MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x");
Aapo Tahkola5fecd9f2006-09-23 20:00:41 -0300619MODULE_VERSION("0.1");
620MODULE_LICENSE("GPL");