/* DVB USB compliant linux driver for MSI Mega Sky 580 DVB-T USB2.0 receiver
*
* Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.org)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
* see Documentation/dvb/README.dvb-usb for more information
*/
#include "m920x.h"
#include "mt352.h"
#include "mt352_priv.h"
#include "qt1010.h"
#include "tda1004x.h"
#include "tda827x.h"
#include <media/tuner.h>
#include "tuner-simple.h"
#include <asm/unaligned.h>
/* debug */
static int dvb_usb_m920x_debug;
module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
u16 index, void *data, int size)
{
int ret;
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
request, USB_TYPE_VENDOR | USB_DIR_IN,
value, index, data, size, 2000);
if (ret < 0) {
printk(KERN_INFO "m920x_read = error: %d\n", ret);
return ret;
}
if (ret != size) {
deb("m920x_read = no data\n");
return -EIO;
}
return 0;
}
static inline int m920x_write(struct usb_device *udev, u8 request,
u16 value, u16 index)
{
int ret;
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
request, USB_TYPE_VENDOR | USB_DIR_OUT,
value, index, NULL, 0, 2000);
return ret;
}
static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
{
int ret = 0, i, epi, flags = 0;
int adap_enabled[M9206_MAX_ADAPTERS] = { 0 };
/* Remote controller init. */
if (d->props.rc.legacy.rc_query) {
deb("Initialising remote control\n");
while (rc_seq->address) {
if ((ret = m920x_write(d->udev, M9206_CORE,
rc_seq->data,
rc_seq->address)) != 0) {
deb("Initialising remote control failed\n");
return ret;
}
rc_seq++;
}
deb("Initialising remote control success\n");
}
for (i = 0; i < d->props.num_adapters; i++)
flags |= d->adapter[i].props.fe[0].caps;
/* Some devices(Dposh) might crash if we attempt touch at all. */
if (flags & DVB_USB_ADAP_HAS_PID_FILTER) {
for (i = 0; i < d->props.num_adapters; i++) {
epi = d->adapter[i].props.fe[0].stream.endpoint - 0x81;
if (epi < 0 || epi >= M9206_MAX_ADAPTERS) {
printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n");
return -EINVAL;
}
adap_enabled[epi] = 1;
}
for (i = 0; i < M9206_MAX_ADAPTERS; i++) {
if (adap_enabled[i])
continue;
if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x0)) != 0)
return ret;
if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x02f5)) != 0)
return ret;
}
}
return ret;
}
static int m920x_init_ep(struct usb_interface *intf)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_interface *alt;
if ((alt = usb_altnum_to_altsetting(intf, 1)) == NULL) {
deb("No alt found!\n");
return -ENODEV;
}
return usb_set_interface(udev, alt->desc.bInterfaceNumber,
alt->desc.bAlternateSetting);
}
static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
struct m920x_state *m = d->priv;
int i, ret = 0;
u8 *rc_state;
rc_state = kmalloc(2, GFP_KERNEL);
if (!rc_state)
return -ENOMEM;
if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
goto out;
if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
goto out;
for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) {
*event = d->props.rc.legacy.rc_map_table[i].keycode;
switch(rc_state[0]) {
case 0x80:
*state = REMOTE_NO_KEY_PRESSED;
goto out;
case 0x88: /* framing error or "invalid code" */
case 0x99:
case 0xc0:
case 0xd8:
*state = REMOTE_NO_KEY_PRESSED;
m->rep_count = 0;
goto out;
case 0x93:
case 0x92:
case 0x83: /* pinnacle PCTV310e */
case 0x82:
m->rep_count = 0;
*state = REMOTE_KEY_PRESSED;
goto out;
case 0x91:
case 0x81: /* pinnacle PCTV310e */
/* prevent immediate auto-repeat */
if (++m->rep_count > 2)
*state = REMOTE_KEY_REPEAT;
else
*state = REMOTE_NO_KEY_PRESSED;
goto out;
default:
deb("Unexpected rc state %02x\n", rc_state[0]);
*state = REMOTE_NO_KEY_PRESSED;
goto out;
}
}
if (rc_state[1] != 0)
deb("Unknown rc key %02x\n", rc_state[1]);
*state = REMOTE_NO_KEY_PRESSED;
out:
kfree(rc_state);
return ret;
}
/* I2C */
static int m920x_i2c_xfer
|