]> Pileus Git - ~andy/linux/blob - drivers/media/dvb/dvb-usb/m920x.c
V4L/DVB (5129): M920x: break out qt1010 tuner code into a separate file
[~andy/linux] / drivers / media / dvb / dvb-usb / m920x.c
1 /* 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  */
11
12 #include "m920x.h"
13
14 #include "mt352.h"
15 #include "mt352_priv.h"
16 #include "qt1010.h"
17
18 /* debug */
19 int dvb_usb_m920x_debug;
20 module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
21 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
22
23 static struct dvb_usb_rc_key megasky_rc_keys [] = {
24         { 0x0, 0x12, KEY_POWER },
25         { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */
26         { 0x0, 0x02, KEY_CHANNELUP },
27         { 0x0, 0x05, KEY_CHANNELDOWN },
28         { 0x0, 0x03, KEY_VOLUMEUP },
29         { 0x0, 0x06, KEY_VOLUMEDOWN },
30         { 0x0, 0x04, KEY_MUTE },
31         { 0x0, 0x07, KEY_OK }, /* TS */
32         { 0x0, 0x08, KEY_STOP },
33         { 0x0, 0x09, KEY_MENU }, /* swap */
34         { 0x0, 0x0a, KEY_REWIND },
35         { 0x0, 0x1b, KEY_PAUSE },
36         { 0x0, 0x1f, KEY_FASTFORWARD },
37         { 0x0, 0x0c, KEY_RECORD },
38         { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */
39         { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */
40 };
41
42 static inline int m9206_read(struct usb_device *udev, u8 request, u16 value, u16 index, void *data, int size)
43 {
44         int ret;
45
46         ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
47                               request, USB_TYPE_VENDOR | USB_DIR_IN,
48                               value, index, data, size, 2000);
49         if (ret < 0)
50                 return ret;
51
52         if (ret != size)
53                 return -EIO;
54
55         return 0;
56 }
57
58 static inline int m9206_write(struct usb_device *udev, u8 request, u16 value, u16 index)
59 {
60         int ret;
61
62         ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
63                               request, USB_TYPE_VENDOR | USB_DIR_OUT,
64                               value, index, NULL, 0, 2000);
65         msleep(3);
66
67         return ret;
68 }
69
70 static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
71 {
72         int i, ret = 0;
73         u8 rc_state[2];
74
75         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
76                 return -EAGAIN;
77
78         if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff51, rc_state, 1)) != 0)
79                 goto unlock;
80
81         if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff52, rc_state + 1, 1)) != 0)
82                 goto unlock;
83
84         for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++)
85                 if (megasky_rc_keys[i].data == rc_state[1]) {
86                         *event = megasky_rc_keys[i].event;
87
88                         switch(rc_state[0]) {
89                         case 0x80:
90                                 *state = REMOTE_NO_KEY_PRESSED;
91                                 goto unlock;
92
93                         case 0x93:
94                         case 0x92:
95                                 *state = REMOTE_KEY_PRESSED;
96                                 goto unlock;
97
98                         case 0x91:
99                                 *state = REMOTE_KEY_REPEAT;
100                                 goto unlock;
101
102                         default:
103                                 deb_rc("Unexpected rc response %x\n", rc_state[0]);
104                                 *state = REMOTE_NO_KEY_PRESSED;
105                                 goto unlock;
106                         }
107                 }
108
109         if (rc_state[1] != 0)
110                 deb_rc("Unknown rc key %x\n", rc_state[1]);
111
112         *state = REMOTE_NO_KEY_PRESSED;
113
114         unlock:
115         mutex_unlock(&d->i2c_mutex);
116
117         return ret;
118 }
119
120 /* I2C */
121
122 static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
123 {
124         struct dvb_usb_device *d = i2c_get_adapdata(adap);
125         int i;
126         int ret = 0;
127
128         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
129                 return -EAGAIN;
130
131         if (num > 2)
132                 return -EINVAL;
133
134         for (i = 0; i < num; i++) {
135                 u8 w_len;
136
137                 if ((ret = m9206_write(d->udev, 0x23, msg[i].addr, 0x80)) != 0)
138                         goto unlock;
139
140                 if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[0], 0x0)) != 0)
141                         goto unlock;
142
143                 if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) {
144                         if (msg[i].addr == 0x1e)
145                                 w_len = 0x1f;
146                         else
147                                 w_len = 0xc5;
148
149                         if ((ret = m9206_write(d->udev, 0x23, w_len, 0x80)) != 0)
150                                 goto unlock;
151
152                         if ((ret = m9206_read(d->udev, 0x23, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0)
153                                 goto unlock;
154
155                         i++;
156                 } else {
157                         if (msg[i].len != 2)
158                                 return -EINVAL;
159
160                         if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[1], 0x40)) != 0)
161                                 goto unlock;
162                 }
163         }
164         ret = i;
165         unlock:
166         mutex_unlock(&d->i2c_mutex);
167
168         return ret;
169 }
170
171 static u32 m9206_i2c_func(struct i2c_adapter *adapter)
172 {
173         return I2C_FUNC_I2C;
174 }
175
176 static struct i2c_algorithm m9206_i2c_algo = {
177         .master_xfer   = m9206_i2c_xfer,
178         .functionality = m9206_i2c_func,
179 };
180
181 /* Callbacks for DVB USB */
182 static int megasky_identify_state(struct usb_device *udev,
183                                   struct dvb_usb_device_properties *props,
184                                   struct dvb_usb_device_description **desc,
185                                   int *cold)
186 {
187         struct usb_host_interface *alt;
188
189         alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1);
190         *cold = (alt == NULL) ? 1 : 0;
191
192         return 0;
193 }
194
195 static int megasky_mt352_demod_init(struct dvb_frontend *fe)
196 {
197         int i;
198         static u8 buf1[] = {
199                 CONFIG, 0x3d,
200                 CLOCK_CTL, 0x30,
201                 RESET, 0x80,
202                 ADC_CTL_1, 0x40,
203                 AGC_TARGET, 0x1c,
204                 AGC_CTL, 0x20,
205                 0x69, 0x00,
206                 0x6a, 0xff,
207                 0x6b, 0xff,
208                 0x6c, 0x40,
209                 0x6d, 0xff,
210                 0x6e, 0x00,
211                 0x6f, 0x40,
212                 0x70, 0x40,
213                 0x93, 0x1a,
214                 0xb5, 0x7a,
215                 ACQ_CTL, 0x50,
216                 INPUT_FREQ_1, 0x31,
217                 INPUT_FREQ_0, 0x05,
218         };
219
220         for (i = 0; i < ARRAY_SIZE(buf1); i += 2)
221                 mt352_write(fe, &buf1[i], 2);
222
223         deb_rc("Demod init!\n");
224
225         return 0;
226 }
227
228 struct mt352_state;
229
230 static struct mt352_config megasky_mt352_config = {
231         .demod_address = 0x1e,
232         .demod_init = megasky_mt352_demod_init,
233 };
234
235 static int megasky_frontend_attach(struct dvb_usb_adapter *adap)
236 {
237         deb_rc("megasky_frontend_attach!\n");
238
239         if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) != NULL) {
240                 adap->fe->ops.tuner_ops.calc_regs = qt1010_set_params;
241                 return 0;
242         }
243         return -EIO;
244 }
245
246 /* DVB USB Driver stuff */
247 static struct dvb_usb_device_properties megasky_properties;
248
249 static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *id)
250 {
251         struct dvb_usb_device *d;
252         struct usb_host_interface *alt;
253         int ret;
254
255         if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) {
256                 deb_rc("probed!\n");
257
258                 alt = usb_altnum_to_altsetting(intf, 1);
259                 if (alt == NULL) {
260                         deb_rc("not alt found!\n");
261                         return -ENODEV;
262                 }
263
264                 ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting);
265                 if (ret < 0)
266                         return ret;
267
268                 deb_rc("Changed to alternate setting!\n");
269
270                 /* Remote controller init. */
271                 if ((ret = m9206_write(d->udev, 0x22, 0xa8, 0xff55)) != 0)
272                         return ret;
273
274                 if ((ret = m9206_write(d->udev, 0x22, 0x51, 0xff54)) != 0)
275                         return ret;
276         }
277         return ret;
278 }
279
280 static struct usb_device_id m920x_table [] = {
281                 { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) },
282                 { }             /* Terminating entry */
283 };
284 MODULE_DEVICE_TABLE (usb, m920x_table);
285
286 static int set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid)
287 {
288         int ret = 0;
289
290         if (pid >= 0x8000)
291                 return -EINVAL;
292
293         pid |= 0x8000;
294
295         if ((ret = m9206_write(adap->dev->udev, 0x25, pid, (type << 8) | (idx * 4) )) != 0)
296                 return ret;
297
298         if ((ret = m9206_write(adap->dev->udev, 0x25, 0, (type << 8) | (idx * 4) )) != 0)
299                 return ret;
300
301         return ret;
302 }
303
304 static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
305 {
306         int ret = 0;
307
308         if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
309                 return -EAGAIN;
310
311         deb_rc("filtering %s\n", onoff ? "on" : "off");
312         if (onoff == 0) {
313                 if ((ret = set_filter(adap, 0x81, 1, 0x00)) != 0)
314                         goto unlock;
315
316                 if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0)
317                         goto unlock;
318         }
319         unlock:
320         mutex_unlock(&adap->dev->i2c_mutex);
321
322         return ret;
323 }
324
325 static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
326 {
327         int ret = 0;
328
329         if (pid == 8192)
330                 return m9206_pid_filter_ctrl(adap, !onoff);
331
332         if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
333                 return -EAGAIN;
334
335         deb_rc("filter %d, pid %x, %s\n", index, pid, onoff ? "on" : "off");
336         if (onoff == 0)
337                 pid = 0;
338
339         if ((ret = set_filter(adap, 0x81, 1, 0x01)) != 0)
340                 goto unlock;
341
342         if ((ret = set_filter(adap, 0x81, index + 2, pid)) != 0)
343                 goto unlock;
344
345         if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0)
346                 goto unlock;
347
348         unlock:
349         mutex_unlock(&adap->dev->i2c_mutex);
350
351         return ret;
352 }
353
354 static int m9206_firmware_download(struct usb_device *udev, const struct firmware *fw)
355 {
356         u16 value, index, size;
357         u8 read[4], *buff;
358         int i, pass, ret = 0;
359
360         buff = kmalloc(65536, GFP_KERNEL);
361
362         if ((ret = m9206_read(udev, 0x25, 0x0, 0x8000, read, 4)) != 0)
363                 goto done;
364         deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
365
366         if ((ret = m9206_read(udev, 0x30, 0x0, 0x0, read, 1)) != 0)
367                 goto done;
368         deb_rc("%x\n", read[0]);
369
370         for (pass = 0; pass < 2; pass++) {
371                 for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
372                         value = le16_to_cpu(*(u16 *)(fw->data + i));
373                         i += sizeof(u16);
374
375                         index = le16_to_cpu(*(u16 *)(fw->data + i));
376                         i += sizeof(u16);
377
378                         size = le16_to_cpu(*(u16 *)(fw->data + i));
379                         i += sizeof(u16);
380
381                         if (pass == 1) {
382                                 /* Will stall if using fw->data ... */
383                                 memcpy(buff, fw->data + i, size);
384
385                                 ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
386                                             0x30, USB_TYPE_VENDOR | USB_DIR_OUT,
387                                             value, index, buff, size, 20);
388                                 if (ret != size) {
389                                         deb_rc("error while uploading fw!\n");
390                                         ret = -EIO;
391                                         goto done;
392                                 }
393                                 msleep(3);
394                         }
395                         i += size;
396                 }
397                 if (i != fw->size) {
398                         ret = -EINVAL;
399                         goto done;
400                 }
401         }
402
403         msleep(36);
404
405         /* m9206 will disconnect itself from the bus after this. */
406         (void) m9206_write(udev, 0x22, 0x01, 0xff69);
407         deb_rc("firmware uploaded!\n");
408
409         done:
410         kfree(buff);
411
412         return ret;
413 }
414
415 static struct dvb_usb_device_properties megasky_properties = {
416         .usb_ctrl = DEVICE_SPECIFIC,
417         .firmware = "dvb-usb-megasky-02.fw",
418         .download_firmware = m9206_firmware_download,
419
420         .rc_interval      = 200,
421         .rc_key_map       = megasky_rc_keys,
422         .rc_key_map_size  = ARRAY_SIZE(megasky_rc_keys),
423         .rc_query         = m9206_rc_query,
424
425         .size_of_priv     = 0,
426
427         .identify_state   = megasky_identify_state,
428         .num_adapters = 1,
429         .adapter = {{
430                 .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_ADAP_HAS_PID_FILTER |
431                         DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF |
432                         DVB_USB_ADAP_NEED_PID_FILTERING,
433                 .pid_filter_count = 8,
434                 .pid_filter       = m9206_pid_filter,
435                 .pid_filter_ctrl  = m9206_pid_filter_ctrl,
436
437                 .frontend_attach  = megasky_frontend_attach,
438
439                 .stream = {
440                         .type = USB_BULK,
441                         .count = 8,
442                         .endpoint = 0x81,
443                         .u = {
444                                 .bulk = {
445                                         .buffersize = 512,
446                                 }
447                         }
448                 },
449         }},
450         .i2c_algo         = &m9206_i2c_algo,
451
452         .generic_bulk_ctrl_endpoint = 0x01,
453
454         .num_device_descs = 1,
455         .devices = {
456                 {   "MSI Mega Sky 580 DVB-T USB2.0",
457                         { &m920x_table[0], NULL },
458                         { NULL },
459                 },
460                 { NULL },
461         }
462 };
463
464 static struct usb_driver m920x_driver = {
465         .name           = "dvb_usb_m920x",
466         .probe          = m920x_probe,
467         .disconnect     = dvb_usb_device_exit,
468         .id_table       = m920x_table,
469 };
470
471 /* module stuff */
472 static int __init m920x_module_init(void)
473 {
474         int ret;
475
476         if ((ret = usb_register(&m920x_driver))) {
477                 err("usb_register failed. Error number %d", ret);
478                 return ret;
479         }
480
481         return 0;
482 }
483
484 static void __exit m920x_module_exit(void)
485 {
486         /* deregister this driver from the USB subsystem */
487         usb_deregister(&m920x_driver);
488 }
489
490 module_init (m920x_module_init);
491 module_exit (m920x_module_exit);
492
493 MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
494 MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x");
495 MODULE_VERSION("0.1");
496 MODULE_LICENSE("GPL");