V4L/DVB (5129): M920x: break out qt1010 tuner code into a separate file
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / dvb / dvb-usb / m920x.c
blob292805aad69a9aff68e691f21b885cb900f56333
1 /* DVB USB compliant linux driver for MSI Mega Sky 580 DVB-T USB2.0 receiver
3 * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.org)
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.
9 * see Documentation/dvb/README.dvb-usb for more information
12 #include "m920x.h"
14 #include "mt352.h"
15 #include "mt352_priv.h"
16 #include "qt1010.h"
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);
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" */
42 static inline int m9206_read(struct usb_device *udev, u8 request, u16 value, u16 index, void *data, int size)
44 int ret;
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;
52 if (ret != size)
53 return -EIO;
55 return 0;
58 static inline int m9206_write(struct usb_device *udev, u8 request, u16 value, u16 index)
60 int ret;
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);
67 return ret;
70 static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
72 int i, ret = 0;
73 u8 rc_state[2];
75 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
76 return -EAGAIN;
78 if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff51, rc_state, 1)) != 0)
79 goto unlock;
81 if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff52, rc_state + 1, 1)) != 0)
82 goto unlock;
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;
88 switch(rc_state[0]) {
89 case 0x80:
90 *state = REMOTE_NO_KEY_PRESSED;
91 goto unlock;
93 case 0x93:
94 case 0x92:
95 *state = REMOTE_KEY_PRESSED;
96 goto unlock;
98 case 0x91:
99 *state = REMOTE_KEY_REPEAT;
100 goto unlock;
102 default:
103 deb_rc("Unexpected rc response %x\n", rc_state[0]);
104 *state = REMOTE_NO_KEY_PRESSED;
105 goto unlock;
109 if (rc_state[1] != 0)
110 deb_rc("Unknown rc key %x\n", rc_state[1]);
112 *state = REMOTE_NO_KEY_PRESSED;
114 unlock:
115 mutex_unlock(&d->i2c_mutex);
117 return ret;
120 /* I2C */
122 static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
124 struct dvb_usb_device *d = i2c_get_adapdata(adap);
125 int i;
126 int ret = 0;
128 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
129 return -EAGAIN;
131 if (num > 2)
132 return -EINVAL;
134 for (i = 0; i < num; i++) {
135 u8 w_len;
137 if ((ret = m9206_write(d->udev, 0x23, msg[i].addr, 0x80)) != 0)
138 goto unlock;
140 if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[0], 0x0)) != 0)
141 goto unlock;
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;
149 if ((ret = m9206_write(d->udev, 0x23, w_len, 0x80)) != 0)
150 goto unlock;
152 if ((ret = m9206_read(d->udev, 0x23, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0)
153 goto unlock;
155 i++;
156 } else {
157 if (msg[i].len != 2)
158 return -EINVAL;
160 if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[1], 0x40)) != 0)
161 goto unlock;
164 ret = i;
165 unlock:
166 mutex_unlock(&d->i2c_mutex);
168 return ret;
171 static u32 m9206_i2c_func(struct i2c_adapter *adapter)
173 return I2C_FUNC_I2C;
176 static struct i2c_algorithm m9206_i2c_algo = {
177 .master_xfer = m9206_i2c_xfer,
178 .functionality = m9206_i2c_func,
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)
187 struct usb_host_interface *alt;
189 alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1);
190 *cold = (alt == NULL) ? 1 : 0;
192 return 0;
195 static int megasky_mt352_demod_init(struct dvb_frontend *fe)
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,
220 for (i = 0; i < ARRAY_SIZE(buf1); i += 2)
221 mt352_write(fe, &buf1[i], 2);
223 deb_rc("Demod init!\n");
225 return 0;
228 struct mt352_state;
230 static struct mt352_config megasky_mt352_config = {
231 .demod_address = 0x1e,
232 .demod_init = megasky_mt352_demod_init,
235 static int megasky_frontend_attach(struct dvb_usb_adapter *adap)
237 deb_rc("megasky_frontend_attach!\n");
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;
243 return -EIO;
246 /* DVB USB Driver stuff */
247 static struct dvb_usb_device_properties megasky_properties;
249 static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *id)
251 struct dvb_usb_device *d;
252 struct usb_host_interface *alt;
253 int ret;
255 if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) {
256 deb_rc("probed!\n");
258 alt = usb_altnum_to_altsetting(intf, 1);
259 if (alt == NULL) {
260 deb_rc("not alt found!\n");
261 return -ENODEV;
264 ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting);
265 if (ret < 0)
266 return ret;
268 deb_rc("Changed to alternate setting!\n");
270 /* Remote controller init. */
271 if ((ret = m9206_write(d->udev, 0x22, 0xa8, 0xff55)) != 0)
272 return ret;
274 if ((ret = m9206_write(d->udev, 0x22, 0x51, 0xff54)) != 0)
275 return ret;
277 return ret;
280 static struct usb_device_id m920x_table [] = {
281 { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) },
282 { } /* Terminating entry */
284 MODULE_DEVICE_TABLE (usb, m920x_table);
286 static int set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid)
288 int ret = 0;
290 if (pid >= 0x8000)
291 return -EINVAL;
293 pid |= 0x8000;
295 if ((ret = m9206_write(adap->dev->udev, 0x25, pid, (type << 8) | (idx * 4) )) != 0)
296 return ret;
298 if ((ret = m9206_write(adap->dev->udev, 0x25, 0, (type << 8) | (idx * 4) )) != 0)
299 return ret;
301 return ret;
304 static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
306 int ret = 0;
308 if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
309 return -EAGAIN;
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;
316 if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0)
317 goto unlock;
319 unlock:
320 mutex_unlock(&adap->dev->i2c_mutex);
322 return ret;
325 static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
327 int ret = 0;
329 if (pid == 8192)
330 return m9206_pid_filter_ctrl(adap, !onoff);
332 if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
333 return -EAGAIN;
335 deb_rc("filter %d, pid %x, %s\n", index, pid, onoff ? "on" : "off");
336 if (onoff == 0)
337 pid = 0;
339 if ((ret = set_filter(adap, 0x81, 1, 0x01)) != 0)
340 goto unlock;
342 if ((ret = set_filter(adap, 0x81, index + 2, pid)) != 0)
343 goto unlock;
345 if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0)
346 goto unlock;
348 unlock:
349 mutex_unlock(&adap->dev->i2c_mutex);
351 return ret;
354 static int m9206_firmware_download(struct usb_device *udev, const struct firmware *fw)
356 u16 value, index, size;
357 u8 read[4], *buff;
358 int i, pass, ret = 0;
360 buff = kmalloc(65536, GFP_KERNEL);
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]);
366 if ((ret = m9206_read(udev, 0x30, 0x0, 0x0, read, 1)) != 0)
367 goto done;
368 deb_rc("%x\n", read[0]);
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);
375 index = le16_to_cpu(*(u16 *)(fw->data + i));
376 i += sizeof(u16);
378 size = le16_to_cpu(*(u16 *)(fw->data + i));
379 i += sizeof(u16);
381 if (pass == 1) {
382 /* Will stall if using fw->data ... */
383 memcpy(buff, fw->data + i, size);
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;
393 msleep(3);
395 i += size;
397 if (i != fw->size) {
398 ret = -EINVAL;
399 goto done;
403 msleep(36);
405 /* m9206 will disconnect itself from the bus after this. */
406 (void) m9206_write(udev, 0x22, 0x01, 0xff69);
407 deb_rc("firmware uploaded!\n");
409 done:
410 kfree(buff);
412 return ret;
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,
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,
425 .size_of_priv = 0,
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,
437 .frontend_attach = megasky_frontend_attach,
439 .stream = {
440 .type = USB_BULK,
441 .count = 8,
442 .endpoint = 0x81,
443 .u = {
444 .bulk = {
445 .buffersize = 512,
450 .i2c_algo = &m9206_i2c_algo,
452 .generic_bulk_ctrl_endpoint = 0x01,
454 .num_device_descs = 1,
455 .devices = {
456 { "MSI Mega Sky 580 DVB-T USB2.0",
457 { &m920x_table[0], NULL },
458 { NULL },
460 { NULL },
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,
471 /* module stuff */
472 static int __init m920x_module_init(void)
474 int ret;
476 if ((ret = usb_register(&m920x_driver))) {
477 err("usb_register failed. Error number %d", ret);
478 return ret;
481 return 0;
484 static void __exit m920x_module_exit(void)
486 /* deregister this driver from the USB subsystem */
487 usb_deregister(&m920x_driver);
490 module_init (m920x_module_init);
491 module_exit (m920x_module_exit);
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");