From 77011ec8224d6aed14d6c68980dbda0b2fe3540c Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 23 Sep 2006 19:00:41 -0400 Subject: dvb-usb: Initial support for MSI Mega Sky 580 based on Uli m9206 From: Aapo Tahkola Currently, the driver works in bulk mode supporting both USB 2.0 and 1.0 with and without hardware pid filters. The ULi m9205 also supports isochronous transfer mode, but I have dropped support for it because it depends on firmware and does not work on all USB host chips. Further, I have no firmware with remote controller support for this mode. Signed-off-by: Aapo Tahkola Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/Kconfig | 10 + linux/drivers/media/dvb/dvb-usb/Makefile | 3 + linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 2 + linux/drivers/media/dvb/dvb-usb/megasky.c | 696 ++++++++++++++++++++++++++ linux/drivers/media/dvb/dvb-usb/megasky.h | 10 + v4l/versions.txt | 1 + 6 files changed, 722 insertions(+) create mode 100644 linux/drivers/media/dvb/dvb-usb/megasky.c create mode 100644 linux/drivers/media/dvb/dvb-usb/megasky.h diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index ad5214360..5f2a0c1dc 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -109,6 +109,16 @@ config DVB_USB_CXUSB Medion MD95700 hybrid USB2.0 device. DViCO FusionHDTV (Bluebird) USB2.0 devices +config DVB_USB_MEGASKY + tristate "MSI Mega Sky 580 DVB-T USB2.0 support" + depends on DVB_USB + select DVB_MT352 + help + Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. + Currently, only devices with a product id of + "DTV USB MINI" (in cold state) are supported. + Firmware required. + config DVB_USB_DIGITV tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" depends on DVB_USB diff --git a/linux/drivers/media/dvb/dvb-usb/Makefile b/linux/drivers/media/dvb/dvb-usb/Makefile index 154d593bb..d1e4f1cd8 100644 --- a/linux/drivers/media/dvb/dvb-usb/Makefile +++ b/linux/drivers/media/dvb/dvb-usb/Makefile @@ -30,6 +30,9 @@ obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2 dvb-usb-umt-010-objs = umt-010.o obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o +dvb-usb-megasky-objs = megasky.o +obj-$(CONFIG_DVB_USB_MEGASKY) += dvb-usb-megasky.o + dvb-usb-digitv-objs = digitv.o obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 299382dcb..713ec5a82 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -29,6 +29,7 @@ #define USB_VID_LEADTEK 0x0413 #define USB_VID_LITEON 0x04ca #define USB_VID_MEDION 0x1660 +#define USB_VID_MSI 0x0db0 #define USB_VID_PINNACLE 0x2304 #define USB_VID_VISIONPLUS 0x13d3 #define USB_VID_TWINHAN 0x1822 @@ -119,6 +120,7 @@ #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 #define USB_PID_MEDION_MD95700 0x0932 +#define USB_PID_MSI_MEGASKY580 0x5580 #define USB_PID_KYE_DVB_T_COLD 0x701e #define USB_PID_KYE_DVB_T_WARM 0x701f #define USB_PID_PCTV_200E 0x020e diff --git a/linux/drivers/media/dvb/dvb-usb/megasky.c b/linux/drivers/media/dvb/dvb-usb/megasky.c new file mode 100644 index 000000000..73e309cb8 --- /dev/null +++ b/linux/drivers/media/dvb/dvb-usb/megasky.c @@ -0,0 +1,696 @@ +/* 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 "megasky.h" + +#include "mt352.h" +#include "mt352_priv.h" + +/* debug */ +int dvb_usb_megasky_debug; +module_param_named(debug,dvb_usb_megasky_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); + +static struct dvb_usb_rc_key megasky_rc_keys [] = { + { 0x0, 0x12, KEY_POWER }, + { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */ + { 0x0, 0x02, KEY_CHANNELUP }, + { 0x0, 0x05, KEY_CHANNELDOWN }, + { 0x0, 0x03, KEY_VOLUMEUP }, + { 0x0, 0x06, KEY_VOLUMEDOWN }, + { 0x0, 0x04, KEY_MUTE }, + { 0x0, 0x07, KEY_OK }, /* TS */ + { 0x0, 0x08, KEY_STOP }, + { 0x0, 0x09, KEY_MENU }, /* swap */ + { 0x0, 0x0a, KEY_REWIND }, + { 0x0, 0x1b, KEY_PAUSE }, + { 0x0, 0x1f, KEY_FASTFORWARD }, + { 0x0, 0x0c, KEY_RECORD }, + { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */ + { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ +}; + +static inline int m9206_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) + return ret; + + if (ret != size) + return -EIO; + + return 0; +} + +static inline int m9206_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); + msleep(3); + + return ret; +} + +static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +{ + int i, ret = 0; + u8 rc_state[2]; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff51, rc_state, 1)) != 0) + goto unlock; + + if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff52, rc_state + 1, 1)) != 0) + goto unlock; + + for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++) + if (megasky_rc_keys[i].data == rc_state[1]) { + *event = megasky_rc_keys[i].event; + + switch(rc_state[0]) { + case 0x80: + *state = REMOTE_NO_KEY_PRESSED; + goto unlock; + + case 0x93: + case 0x92: + *state = REMOTE_KEY_PRESSED; + goto unlock; + + case 0x91: + *state = REMOTE_KEY_REPEAT; + goto unlock; + + default: + deb_rc("Unexpected rc response %x\n", rc_state[0]); + *state = REMOTE_NO_KEY_PRESSED; + goto unlock; + } + } + + if (rc_state[1] != 0) + deb_rc("Unknown rc key %x\n", rc_state[1]); + + *state = REMOTE_NO_KEY_PRESSED; + + unlock: + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +/* I2C */ + +static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int i; + int ret = 0; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + if (num > 2) + return -EINVAL; + + for (i = 0; i < num; i++) { + u8 w_len; + + if ((ret = m9206_write(d->udev, 0x23, msg[i].addr, 0x80)) != 0) + goto unlock; + + if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[0], 0x0)) != 0) + goto unlock; + + if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) { + if (msg[i].addr == 0x1e) + w_len = 0x1f; + else + w_len = 0xc5; + + if ((ret = m9206_write(d->udev, 0x23, w_len, 0x80)) != 0) + goto unlock; + + if ((ret = m9206_read(d->udev, 0x23, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0) + goto unlock; + + i++; + } else { + if (msg[i].len != 2) + return -EINVAL; + + if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[1], 0x40)) != 0) + goto unlock; + } + } + ret = i; + unlock: + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +static u32 m9206_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm m9206_i2c_algo = { + .master_xfer = m9206_i2c_xfer, + .functionality = m9206_i2c_func, +}; + +/* Callbacks for DVB USB */ +static int megasky_identify_state (struct usb_device *udev, + struct dvb_usb_properties *props, + struct dvb_usb_device_description **desc, + int *cold) +{ + struct usb_host_interface *alt; + + alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1); + *cold = (alt == NULL) ? 1 : 0; + + return 0; +} + +static int megasky_mt352_demod_init(struct dvb_frontend *fe) +{ + int i; + static u8 buf1[] = { + CONFIG, 0x3d, + CLOCK_CTL, 0x30, + RESET, 0x80, + ADC_CTL_1, 0x40, + AGC_TARGET, 0x1c, + AGC_CTL, 0x20, + 0x69, 0x00, + 0x6a, 0xff, + 0x6b, 0xff, + 0x6c, 0x40, + 0x6d, 0xff, + 0x6e, 0x00, + 0x6f, 0x40, + 0x70, 0x40, + 0x93, 0x1a, + 0xb5, 0x7a, + ACQ_CTL, 0x50, + INPUT_FREQ_1, 0x31, + INPUT_FREQ_0, 0x05, + }; + + for (i = 0; i < ARRAY_SIZE(buf1); i += 2) + mt352_write(fe, &buf1[i], 2); + + deb_rc("Demod init!\n"); + + return 0; +} + +struct mt352_state; + + +#define W 0 +#define R 1 +/* Not actual hw limits. */ +#define QT1010_MIN_STEP 2000000 +#define QT1010_MIN_FREQ 48000000 + +int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) +{ + int i; + int div, mod; + struct { + u8 read, reg, value; + } rd[46] = { { W, 0x01, 0x80 }, + { W, 0x02, 0x3f }, + { W, 0x05, 0xff }, /* c */ + { W, 0x06, 0x44 }, + { W, 0x07, 0xff }, /* c */ + { W, 0x08, 0x08 }, + { W, 0x09, 0xff }, /* c */ + { W, 0x0a, 0xff }, /* c */ + { W, 0x0b, 0xff }, /* c */ + { W, 0x0c, 0xe1 }, + { W, 0x1a, 0xff }, /* 10 c */ + { W, 0x1b, 0x00 }, + { W, 0x1c, 0x89 }, + { W, 0x11, 0xff }, /* c */ + { W, 0x12, 0x91 }, + { W, 0x22, 0xff }, /* c */ + { W, 0x1e, 0x00 }, + { W, 0x1e, 0xd0 }, + { R, 0x22, 0xff }, /* c read */ + { W, 0x1e, 0x00 }, + { R, 0x05, 0xff }, /* 20 c read */ + { R, 0x22, 0xff }, /* c read */ + { W, 0x23, 0xd0 }, + { W, 0x1e, 0x00 }, + { W, 0x1e, 0xe0 }, + { R, 0x23, 0xff }, /* c read */ + { W, 0x1e, 0x00 }, + { W, 0x24, 0xd0 }, + { W, 0x1e, 0x00 }, + { W, 0x1e, 0xf0 }, + { R, 0x24, 0xff }, /* 30 c read */ + { W, 0x1e, 0x00 }, + { W, 0x14, 0x7f }, + { W, 0x15, 0x7f }, + { W, 0x05, 0xff }, /* c */ + { W, 0x06, 0x00 }, + { W, 0x15, 0x1f }, + { W, 0x16, 0xff }, + { W, 0x18, 0xff }, + { W, 0x1f, 0xff }, /* c */ + { W, 0x20, 0xff }, /* 40 c */ + { W, 0x21, 0x53 }, + { W, 0x25, 0xbd }, + { W, 0x26, 0x15 }, + { W, 0x02, 0x00 }, + { W, 0x01, 0x00 }, + }; + struct i2c_msg msg; + struct dvb_usb_device *d = fe->dvb->priv; + unsigned long freq = params->frequency; + + if (freq % QT1010_MIN_STEP) + deb_rc("frequency not supported.\n"); + + (void) buf; + (void) buf_len; + + div = (freq - QT1010_MIN_FREQ) / QT1010_MIN_STEP; + mod = (div + 16 - 9) % 16; + + /* 0x5 */ + if (div >= 377) + rd[2].value = 0x74; + else if (div >= 265) + rd[2].value = 0x54; + else if (div >= 121) + rd[2].value = 0x34; + else + rd[2].value = 0x14; + + /* 0x7 */ + rd[4].value = (((freq - QT1010_MIN_FREQ) / 1000000) * 9975 + 12960000) / 320000; + + /* 09 */ + if (mod < 4) + rd[6].value = 0x1d; + else + rd[6].value = 0x1c; + + /* 0a */ + if (mod < 2) + rd[7].value = 0x09; + else if (mod < 4) + rd[7].value = 0x08; + else if (mod < 6) + rd[7].value = 0x0f; + else if (mod < 8) + rd[7].value = 0x0e; + else if (mod < 10) + rd[7].value = 0x0d; + else if (mod < 12) + rd[7].value = 0x0c; + else if (mod < 14) + rd[7].value = 0x0b; + else + rd[7].value = 0x0a; + + /* 0b */ + if (div & 1) + rd[8].value = 0x45; + else + rd[8].value = 0x44; + + /* 1a */ + if (div & 1) + rd[10].value = 0x78; + else + rd[10].value = 0xf8; + + /* 11 */ + if (div >= 265) + rd[13].value = 0xf9; + else if (div >= 121) + rd[13].value = 0xfd; + else + rd[13].value = 0xf9; + + /* 22 */ + if (div < 201) + rd[15].value = 0xd0; + else if (div < 217) + rd[15].value = 0xd3; + else if (div < 233) + rd[15].value = 0xd6; + else if (div < 249) + rd[15].value = 0xd9; + else if (div < 265) + rd[15].value = 0xda; + else + rd[15].value = 0xd0; + + /* 05 */ + if (div >= 377) + rd[34].value = 0x70; + else if (div >= 265) + rd[34].value = 0x50; + else if (div >= 121) + rd[34].value = 0x30; + else + rd[34].value = 0x10; + + /* 1f */ + if (mod < 4) + rd[39].value = 0x64; + else if (mod < 6) + rd[39].value = 0x66; + else if (mod < 8) + rd[39].value = 0x67; + else if (mod < 12) + rd[39].value = 0x68; + else if (mod < 14) + rd[39].value = 0x69; + else + rd[39].value = 0x6a; + + /* 20 */ + if (mod < 4) + rd[40].value = 0x10; + else if (mod < 6) + rd[40].value = 0x11; + else if (mod < 10) + rd[40].value = 0x12; + else if (mod < 12) + rd[40].value = 0x13; + else if (mod < 14) + rd[40].value = 0x14; + else + rd[40].value = 0x15; + + deb_rc("Now tuning... "); + for (i = 0; i < sizeof(rd) / sizeof(*rd); i++) { + if (rd[i].read) + continue; + + msg.flags = 0; + msg.len = 2; + msg.addr = 0xc4; + msg.buf = &rd[i].reg; + + if (i2c_transfer(&d->i2c_adap, &msg, 1) != 1) { + deb_rc("tuner write failed\n"); + return -EIO; + } + } + deb_rc("done\n"); + + return 0; +} +#undef W +#undef R + +static struct mt352_config megasky_mt352_config = { + .demod_address = 0x1e, + .demod_init = megasky_mt352_demod_init, +}; + +static int megasky_frontend_attach(struct dvb_usb_device *d) +{ + deb_rc("megasky_frontend_attach!\n"); + + if ((d->fe = mt352_attach(&megasky_mt352_config, &d->i2c_adap)) != NULL) { + d->fe->ops.tuner_ops.calc_regs = qt1010_set_params; + return 0; + } + return -EIO; +} + +/* DVB USB Driver stuff */ +static struct dvb_usb_properties megasky_properties; + +static int megasky_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct dvb_usb_device *d; + struct usb_host_interface *alt; + int ret; + + if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) { + deb_rc("probed!\n"); + + alt = usb_altnum_to_altsetting(intf, 1); + if (alt == NULL) { + deb_rc("not alt found!\n"); + return -ENODEV; + } + + ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); + if (ret < 0) + return ret; + + deb_rc("Changed to alternate setting!\n"); + + /* Remote controller init. */ + if ((ret = m9206_write(d->udev, 0x22, 0xa8, 0xff55)) != 0) + return ret; + + if ((ret = m9206_write(d->udev, 0x22, 0x51, 0xff54)) != 0) + return ret; + } + return ret; +} + +static struct usb_device_id megasky_table [] = { + { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE (usb, megasky_table); + +static int set_filter(struct dvb_usb_device *d, int type, int idx, int pid) +{ + int ret = 0; + + if (pid >= 0x8000) + return -EINVAL; + + pid |= 0x8000; + + if ((ret = m9206_write(d->udev, 0x25, pid, (type << 8) | (idx * 4) )) != 0) + return ret; + + if ((ret = m9206_write(d->udev, 0x25, 0, (type << 8) | (idx * 4) )) != 0) + return ret; + + return ret; +} + +static int m9206_pid_filter_ctrl(struct dvb_usb_device *d, int onoff) +{ + int ret = 0; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + deb_rc("filtering %s\n", onoff ? "on" : "off"); + if (onoff == 0) { + if ((ret = set_filter(d, 0x81, 1, 0x00)) != 0) + goto unlock; + + if ((ret = set_filter(d, 0x82, 0, 0x02f5)) != 0) + goto unlock; + } + unlock: + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +static int m9206_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff) +{ + int ret = 0; + + if (pid == 8192) + return m9206_pid_filter_ctrl(d, !onoff); + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + deb_rc("filter %d, pid %x, %s\n", index, pid, onoff ? "on" : "off"); + if (onoff == 0) + pid = 0; + + if ((ret = set_filter(d, 0x81, 1, 0x01)) != 0) + goto unlock; + + if ((ret = set_filter(d, 0x81, index + 2, pid)) != 0) + goto unlock; + + if ((ret = set_filter(d, 0x82, 0, 0x02f5)) != 0) + goto unlock; + + unlock: + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +static int m9206_firmware_download(struct usb_device *udev, const struct firmware *fw) +{ + u16 value, index, size; + u8 read[4], *buff; + int i, pass, ret = 0; + + buff = kmalloc(65536, GFP_KERNEL); + + if ((ret = m9206_read(udev, 0x25, 0x0, 0x8000, read, 4)) != 0) + goto done; + deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]); + + if ((ret = m9206_read(udev, 0x30, 0x0, 0x0, read, 1)) != 0) + goto done; + deb_rc("%x\n", read[0]); + + for (pass = 0; pass < 2; pass++) { + for (i = 0; i + (sizeof(u16) * 3) < fw->size;) { + value = le16_to_cpu(*(u16 *)(fw->data + i)); + i += sizeof(u16); + + index = le16_to_cpu(*(u16 *)(fw->data + i)); + i += sizeof(u16); + + size = le16_to_cpu(*(u16 *)(fw->data + i)); + i += sizeof(u16); + + if (pass == 1) { + /* Will stall if using fw->data ... */ + memcpy(buff, fw->data + i, size); + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), + 0x30, USB_TYPE_VENDOR | USB_DIR_OUT, + value, index, buff, size, 20); + if (ret != size) { + deb_rc("error while uploading fw!\n"); + ret = -EIO; + goto done; + } + msleep(3); + } + i += size; + } + if (i != fw->size) { + ret = -EINVAL; + goto done; + } + } + + msleep(36); + + /* m9206 will disconnect itself from the bus after this. */ + (void) m9206_write(udev, 0x22, 0x01, 0xff69); + deb_rc("firmware uploaded!\n"); + + done: + kfree(buff); + + return ret; +} + +static struct dvb_usb_properties megasky_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_HAS_PID_FILTER | + DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_NEED_PID_FILTERING, + .pid_filter_count = 8, + + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-megasky-02.fw", + .download_firmware = m9206_firmware_download, + + .pid_filter = m9206_pid_filter, + .pid_filter_ctrl = m9206_pid_filter_ctrl, + .frontend_attach = megasky_frontend_attach, + + .rc_interval = 200, + .rc_key_map = megasky_rc_keys, + .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys), + .rc_query = m9206_rc_query, + + .size_of_priv = 0, + + .identify_state = megasky_identify_state, + .i2c_algo = &m9206_i2c_algo, + + .generic_bulk_ctrl_endpoint = 0x01, + .urb = { + .type = DVB_USB_BULK, + .count = 8, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, + .num_device_descs = 1, + .devices = { + { "MSI Mega Sky 580 DVB-T USB2.0", + { &megasky_table[0], NULL }, + { NULL }, + }, + { NULL }, + } +}; + +static struct usb_driver megasky_driver = { +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) + .owner = THIS_MODULE, +#endif + .name = "dvb_usb_megasky", + .probe = megasky_probe, + .disconnect = dvb_usb_device_exit, + .id_table = megasky_table, +}; + +/* module stuff */ +static int __init megasky_module_init(void) +{ + int ret; + + if ((ret = usb_register(&megasky_driver))) { + err("usb_register failed. Error number %d", ret); + return ret; + } + + return 0; +} + +static void __exit megasky_module_exit(void) +{ + /* deregister this driver from the USB subsystem */ + usb_deregister(&megasky_driver); +} + +module_init (megasky_module_init); +module_exit (megasky_module_exit); + +MODULE_AUTHOR("Aapo Tahkola "); +MODULE_DESCRIPTION("Driver for MSI Mega Sky 580 DVB-T USB2.0"); +MODULE_VERSION("0.1"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/dvb-usb/megasky.h b/linux/drivers/media/dvb/dvb-usb/megasky.h new file mode 100644 index 000000000..6f14ae74e --- /dev/null +++ b/linux/drivers/media/dvb/dvb-usb/megasky.h @@ -0,0 +1,10 @@ +#ifndef _DVB_USB_MEGASKY_H_ +#define _DVB_USB_MEGASKY_H_ + +#define DVB_USB_LOG_PREFIX "megasky" +#include "dvb-usb.h" + +extern int dvb_usb_megasky_debug; +#define deb_rc(args...) dprintk(dvb_usb_megasky_debug,0x01,args) + +#endif diff --git a/v4l/versions.txt b/v4l/versions.txt index 3d1a14a7e..2d7ad4ee4 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -111,6 +111,7 @@ DVB_USB_DIBUSB_MB_FAULTY DVB_USB_DIBUSB_MC DVB_USB_UMT_010 DVB_USB_CXUSB +DVB_USB_MEGASKY DVB_USB_DIGITV DVB_USB_VP7045 DVB_USB_VP702X -- cgit v1.2.3 From 4130b2e25e1fcf65e8213ae458fd4788114632ea Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 23 Sep 2006 19:00:42 -0400 Subject: dvb-usb: rename megasky.[ch] to m920x.[ch] From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/Makefile | 4 +- linux/drivers/media/dvb/dvb-usb/m920x.c | 696 ++++++++++++++++++++++++++++++ linux/drivers/media/dvb/dvb-usb/m920x.h | 10 + linux/drivers/media/dvb/dvb-usb/megasky.c | 696 ------------------------------ linux/drivers/media/dvb/dvb-usb/megasky.h | 10 - 5 files changed, 708 insertions(+), 708 deletions(-) create mode 100644 linux/drivers/media/dvb/dvb-usb/m920x.c create mode 100644 linux/drivers/media/dvb/dvb-usb/m920x.h delete mode 100644 linux/drivers/media/dvb/dvb-usb/megasky.c delete mode 100644 linux/drivers/media/dvb/dvb-usb/megasky.h diff --git a/linux/drivers/media/dvb/dvb-usb/Makefile b/linux/drivers/media/dvb/dvb-usb/Makefile index d1e4f1cd8..e2eed102e 100644 --- a/linux/drivers/media/dvb/dvb-usb/Makefile +++ b/linux/drivers/media/dvb/dvb-usb/Makefile @@ -30,8 +30,8 @@ obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2 dvb-usb-umt-010-objs = umt-010.o obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o -dvb-usb-megasky-objs = megasky.o -obj-$(CONFIG_DVB_USB_MEGASKY) += dvb-usb-megasky.o +dvb-usb-m920x-objs = m920x.o +obj-$(CONFIG_DVB_USB_MEGASKY) += dvb-usb-m920x.o dvb-usb-digitv-objs = digitv.o obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c new file mode 100644 index 000000000..915b6453a --- /dev/null +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -0,0 +1,696 @@ +/* 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" + +/* debug */ +int dvb_usb_megasky_debug; +module_param_named(debug,dvb_usb_megasky_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); + +static struct dvb_usb_rc_key megasky_rc_keys [] = { + { 0x0, 0x12, KEY_POWER }, + { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */ + { 0x0, 0x02, KEY_CHANNELUP }, + { 0x0, 0x05, KEY_CHANNELDOWN }, + { 0x0, 0x03, KEY_VOLUMEUP }, + { 0x0, 0x06, KEY_VOLUMEDOWN }, + { 0x0, 0x04, KEY_MUTE }, + { 0x0, 0x07, KEY_OK }, /* TS */ + { 0x0, 0x08, KEY_STOP }, + { 0x0, 0x09, KEY_MENU }, /* swap */ + { 0x0, 0x0a, KEY_REWIND }, + { 0x0, 0x1b, KEY_PAUSE }, + { 0x0, 0x1f, KEY_FASTFORWARD }, + { 0x0, 0x0c, KEY_RECORD }, + { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */ + { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ +}; + +static inline int m9206_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) + return ret; + + if (ret != size) + return -EIO; + + return 0; +} + +static inline int m9206_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); + msleep(3); + + return ret; +} + +static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +{ + int i, ret = 0; + u8 rc_state[2]; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff51, rc_state, 1)) != 0) + goto unlock; + + if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff52, rc_state + 1, 1)) != 0) + goto unlock; + + for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++) + if (megasky_rc_keys[i].data == rc_state[1]) { + *event = megasky_rc_keys[i].event; + + switch(rc_state[0]) { + case 0x80: + *state = REMOTE_NO_KEY_PRESSED; + goto unlock; + + case 0x93: + case 0x92: + *state = REMOTE_KEY_PRESSED; + goto unlock; + + case 0x91: + *state = REMOTE_KEY_REPEAT; + goto unlock; + + default: + deb_rc("Unexpected rc response %x\n", rc_state[0]); + *state = REMOTE_NO_KEY_PRESSED; + goto unlock; + } + } + + if (rc_state[1] != 0) + deb_rc("Unknown rc key %x\n", rc_state[1]); + + *state = REMOTE_NO_KEY_PRESSED; + + unlock: + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +/* I2C */ + +static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int i; + int ret = 0; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + if (num > 2) + return -EINVAL; + + for (i = 0; i < num; i++) { + u8 w_len; + + if ((ret = m9206_write(d->udev, 0x23, msg[i].addr, 0x80)) != 0) + goto unlock; + + if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[0], 0x0)) != 0) + goto unlock; + + if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) { + if (msg[i].addr == 0x1e) + w_len = 0x1f; + else + w_len = 0xc5; + + if ((ret = m9206_write(d->udev, 0x23, w_len, 0x80)) != 0) + goto unlock; + + if ((ret = m9206_read(d->udev, 0x23, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0) + goto unlock; + + i++; + } else { + if (msg[i].len != 2) + return -EINVAL; + + if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[1], 0x40)) != 0) + goto unlock; + } + } + ret = i; + unlock: + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +static u32 m9206_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm m9206_i2c_algo = { + .master_xfer = m9206_i2c_xfer, + .functionality = m9206_i2c_func, +}; + +/* Callbacks for DVB USB */ +static int megasky_identify_state (struct usb_device *udev, + struct dvb_usb_properties *props, + struct dvb_usb_device_description **desc, + int *cold) +{ + struct usb_host_interface *alt; + + alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1); + *cold = (alt == NULL) ? 1 : 0; + + return 0; +} + +static int megasky_mt352_demod_init(struct dvb_frontend *fe) +{ + int i; + static u8 buf1[] = { + CONFIG, 0x3d, + CLOCK_CTL, 0x30, + RESET, 0x80, + ADC_CTL_1, 0x40, + AGC_TARGET, 0x1c, + AGC_CTL, 0x20, + 0x69, 0x00, + 0x6a, 0xff, + 0x6b, 0xff, + 0x6c, 0x40, + 0x6d, 0xff, + 0x6e, 0x00, + 0x6f, 0x40, + 0x70, 0x40, + 0x93, 0x1a, + 0xb5, 0x7a, + ACQ_CTL, 0x50, + INPUT_FREQ_1, 0x31, + INPUT_FREQ_0, 0x05, + }; + + for (i = 0; i < ARRAY_SIZE(buf1); i += 2) + mt352_write(fe, &buf1[i], 2); + + deb_rc("Demod init!\n"); + + return 0; +} + +struct mt352_state; + + +#define W 0 +#define R 1 +/* Not actual hw limits. */ +#define QT1010_MIN_STEP 2000000 +#define QT1010_MIN_FREQ 48000000 + +int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) +{ + int i; + int div, mod; + struct { + u8 read, reg, value; + } rd[46] = { { W, 0x01, 0x80 }, + { W, 0x02, 0x3f }, + { W, 0x05, 0xff }, /* c */ + { W, 0x06, 0x44 }, + { W, 0x07, 0xff }, /* c */ + { W, 0x08, 0x08 }, + { W, 0x09, 0xff }, /* c */ + { W, 0x0a, 0xff }, /* c */ + { W, 0x0b, 0xff }, /* c */ + { W, 0x0c, 0xe1 }, + { W, 0x1a, 0xff }, /* 10 c */ + { W, 0x1b, 0x00 }, + { W, 0x1c, 0x89 }, + { W, 0x11, 0xff }, /* c */ + { W, 0x12, 0x91 }, + { W, 0x22, 0xff }, /* c */ + { W, 0x1e, 0x00 }, + { W, 0x1e, 0xd0 }, + { R, 0x22, 0xff }, /* c read */ + { W, 0x1e, 0x00 }, + { R, 0x05, 0xff }, /* 20 c read */ + { R, 0x22, 0xff }, /* c read */ + { W, 0x23, 0xd0 }, + { W, 0x1e, 0x00 }, + { W, 0x1e, 0xe0 }, + { R, 0x23, 0xff }, /* c read */ + { W, 0x1e, 0x00 }, + { W, 0x24, 0xd0 }, + { W, 0x1e, 0x00 }, + { W, 0x1e, 0xf0 }, + { R, 0x24, 0xff }, /* 30 c read */ + { W, 0x1e, 0x00 }, + { W, 0x14, 0x7f }, + { W, 0x15, 0x7f }, + { W, 0x05, 0xff }, /* c */ + { W, 0x06, 0x00 }, + { W, 0x15, 0x1f }, + { W, 0x16, 0xff }, + { W, 0x18, 0xff }, + { W, 0x1f, 0xff }, /* c */ + { W, 0x20, 0xff }, /* 40 c */ + { W, 0x21, 0x53 }, + { W, 0x25, 0xbd }, + { W, 0x26, 0x15 }, + { W, 0x02, 0x00 }, + { W, 0x01, 0x00 }, + }; + struct i2c_msg msg; + struct dvb_usb_device *d = fe->dvb->priv; + unsigned long freq = params->frequency; + + if (freq % QT1010_MIN_STEP) + deb_rc("frequency not supported.\n"); + + (void) buf; + (void) buf_len; + + div = (freq - QT1010_MIN_FREQ) / QT1010_MIN_STEP; + mod = (div + 16 - 9) % 16; + + /* 0x5 */ + if (div >= 377) + rd[2].value = 0x74; + else if (div >= 265) + rd[2].value = 0x54; + else if (div >= 121) + rd[2].value = 0x34; + else + rd[2].value = 0x14; + + /* 0x7 */ + rd[4].value = (((freq - QT1010_MIN_FREQ) / 1000000) * 9975 + 12960000) / 320000; + + /* 09 */ + if (mod < 4) + rd[6].value = 0x1d; + else + rd[6].value = 0x1c; + + /* 0a */ + if (mod < 2) + rd[7].value = 0x09; + else if (mod < 4) + rd[7].value = 0x08; + else if (mod < 6) + rd[7].value = 0x0f; + else if (mod < 8) + rd[7].value = 0x0e; + else if (mod < 10) + rd[7].value = 0x0d; + else if (mod < 12) + rd[7].value = 0x0c; + else if (mod < 14) + rd[7].value = 0x0b; + else + rd[7].value = 0x0a; + + /* 0b */ + if (div & 1) + rd[8].value = 0x45; + else + rd[8].value = 0x44; + + /* 1a */ + if (div & 1) + rd[10].value = 0x78; + else + rd[10].value = 0xf8; + + /* 11 */ + if (div >= 265) + rd[13].value = 0xf9; + else if (div >= 121) + rd[13].value = 0xfd; + else + rd[13].value = 0xf9; + + /* 22 */ + if (div < 201) + rd[15].value = 0xd0; + else if (div < 217) + rd[15].value = 0xd3; + else if (div < 233) + rd[15].value = 0xd6; + else if (div < 249) + rd[15].value = 0xd9; + else if (div < 265) + rd[15].value = 0xda; + else + rd[15].value = 0xd0; + + /* 05 */ + if (div >= 377) + rd[34].value = 0x70; + else if (div >= 265) + rd[34].value = 0x50; + else if (div >= 121) + rd[34].value = 0x30; + else + rd[34].value = 0x10; + + /* 1f */ + if (mod < 4) + rd[39].value = 0x64; + else if (mod < 6) + rd[39].value = 0x66; + else if (mod < 8) + rd[39].value = 0x67; + else if (mod < 12) + rd[39].value = 0x68; + else if (mod < 14) + rd[39].value = 0x69; + else + rd[39].value = 0x6a; + + /* 20 */ + if (mod < 4) + rd[40].value = 0x10; + else if (mod < 6) + rd[40].value = 0x11; + else if (mod < 10) + rd[40].value = 0x12; + else if (mod < 12) + rd[40].value = 0x13; + else if (mod < 14) + rd[40].value = 0x14; + else + rd[40].value = 0x15; + + deb_rc("Now tuning... "); + for (i = 0; i < sizeof(rd) / sizeof(*rd); i++) { + if (rd[i].read) + continue; + + msg.flags = 0; + msg.len = 2; + msg.addr = 0xc4; + msg.buf = &rd[i].reg; + + if (i2c_transfer(&d->i2c_adap, &msg, 1) != 1) { + deb_rc("tuner write failed\n"); + return -EIO; + } + } + deb_rc("done\n"); + + return 0; +} +#undef W +#undef R + +static struct mt352_config megasky_mt352_config = { + .demod_address = 0x1e, + .demod_init = megasky_mt352_demod_init, +}; + +static int megasky_frontend_attach(struct dvb_usb_device *d) +{ + deb_rc("megasky_frontend_attach!\n"); + + if ((d->fe = mt352_attach(&megasky_mt352_config, &d->i2c_adap)) != NULL) { + d->fe->ops.tuner_ops.calc_regs = qt1010_set_params; + return 0; + } + return -EIO; +} + +/* DVB USB Driver stuff */ +static struct dvb_usb_properties megasky_properties; + +static int megasky_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct dvb_usb_device *d; + struct usb_host_interface *alt; + int ret; + + if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) { + deb_rc("probed!\n"); + + alt = usb_altnum_to_altsetting(intf, 1); + if (alt == NULL) { + deb_rc("not alt found!\n"); + return -ENODEV; + } + + ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); + if (ret < 0) + return ret; + + deb_rc("Changed to alternate setting!\n"); + + /* Remote controller init. */ + if ((ret = m9206_write(d->udev, 0x22, 0xa8, 0xff55)) != 0) + return ret; + + if ((ret = m9206_write(d->udev, 0x22, 0x51, 0xff54)) != 0) + return ret; + } + return ret; +} + +static struct usb_device_id megasky_table [] = { + { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE (usb, megasky_table); + +static int set_filter(struct dvb_usb_device *d, int type, int idx, int pid) +{ + int ret = 0; + + if (pid >= 0x8000) + return -EINVAL; + + pid |= 0x8000; + + if ((ret = m9206_write(d->udev, 0x25, pid, (type << 8) | (idx * 4) )) != 0) + return ret; + + if ((ret = m9206_write(d->udev, 0x25, 0, (type << 8) | (idx * 4) )) != 0) + return ret; + + return ret; +} + +static int m9206_pid_filter_ctrl(struct dvb_usb_device *d, int onoff) +{ + int ret = 0; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + deb_rc("filtering %s\n", onoff ? "on" : "off"); + if (onoff == 0) { + if ((ret = set_filter(d, 0x81, 1, 0x00)) != 0) + goto unlock; + + if ((ret = set_filter(d, 0x82, 0, 0x02f5)) != 0) + goto unlock; + } + unlock: + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +static int m9206_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff) +{ + int ret = 0; + + if (pid == 8192) + return m9206_pid_filter_ctrl(d, !onoff); + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + deb_rc("filter %d, pid %x, %s\n", index, pid, onoff ? "on" : "off"); + if (onoff == 0) + pid = 0; + + if ((ret = set_filter(d, 0x81, 1, 0x01)) != 0) + goto unlock; + + if ((ret = set_filter(d, 0x81, index + 2, pid)) != 0) + goto unlock; + + if ((ret = set_filter(d, 0x82, 0, 0x02f5)) != 0) + goto unlock; + + unlock: + mutex_unlock(&d->i2c_mutex); + + return ret; +} + +static int m9206_firmware_download(struct usb_device *udev, const struct firmware *fw) +{ + u16 value, index, size; + u8 read[4], *buff; + int i, pass, ret = 0; + + buff = kmalloc(65536, GFP_KERNEL); + + if ((ret = m9206_read(udev, 0x25, 0x0, 0x8000, read, 4)) != 0) + goto done; + deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]); + + if ((ret = m9206_read(udev, 0x30, 0x0, 0x0, read, 1)) != 0) + goto done; + deb_rc("%x\n", read[0]); + + for (pass = 0; pass < 2; pass++) { + for (i = 0; i + (sizeof(u16) * 3) < fw->size;) { + value = le16_to_cpu(*(u16 *)(fw->data + i)); + i += sizeof(u16); + + index = le16_to_cpu(*(u16 *)(fw->data + i)); + i += sizeof(u16); + + size = le16_to_cpu(*(u16 *)(fw->data + i)); + i += sizeof(u16); + + if (pass == 1) { + /* Will stall if using fw->data ... */ + memcpy(buff, fw->data + i, size); + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), + 0x30, USB_TYPE_VENDOR | USB_DIR_OUT, + value, index, buff, size, 20); + if (ret != size) { + deb_rc("error while uploading fw!\n"); + ret = -EIO; + goto done; + } + msleep(3); + } + i += size; + } + if (i != fw->size) { + ret = -EINVAL; + goto done; + } + } + + msleep(36); + + /* m9206 will disconnect itself from the bus after this. */ + (void) m9206_write(udev, 0x22, 0x01, 0xff69); + deb_rc("firmware uploaded!\n"); + + done: + kfree(buff); + + return ret; +} + +static struct dvb_usb_properties megasky_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_HAS_PID_FILTER | + DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_NEED_PID_FILTERING, + .pid_filter_count = 8, + + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-megasky-02.fw", + .download_firmware = m9206_firmware_download, + + .pid_filter = m9206_pid_filter, + .pid_filter_ctrl = m9206_pid_filter_ctrl, + .frontend_attach = megasky_frontend_attach, + + .rc_interval = 200, + .rc_key_map = megasky_rc_keys, + .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys), + .rc_query = m9206_rc_query, + + .size_of_priv = 0, + + .identify_state = megasky_identify_state, + .i2c_algo = &m9206_i2c_algo, + + .generic_bulk_ctrl_endpoint = 0x01, + .urb = { + .type = DVB_USB_BULK, + .count = 8, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, + .num_device_descs = 1, + .devices = { + { "MSI Mega Sky 580 DVB-T USB2.0", + { &megasky_table[0], NULL }, + { NULL }, + }, + { NULL }, + } +}; + +static struct usb_driver megasky_driver = { +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) + .owner = THIS_MODULE, +#endif + .name = "dvb_usb_megasky", + .probe = megasky_probe, + .disconnect = dvb_usb_device_exit, + .id_table = megasky_table, +}; + +/* module stuff */ +static int __init megasky_module_init(void) +{ + int ret; + + if ((ret = usb_register(&megasky_driver))) { + err("usb_register failed. Error number %d", ret); + return ret; + } + + return 0; +} + +static void __exit megasky_module_exit(void) +{ + /* deregister this driver from the USB subsystem */ + usb_deregister(&megasky_driver); +} + +module_init (megasky_module_init); +module_exit (megasky_module_exit); + +MODULE_AUTHOR("Aapo Tahkola "); +MODULE_DESCRIPTION("Driver for MSI Mega Sky 580 DVB-T USB2.0"); +MODULE_VERSION("0.1"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.h b/linux/drivers/media/dvb/dvb-usb/m920x.h new file mode 100644 index 000000000..6f14ae74e --- /dev/null +++ b/linux/drivers/media/dvb/dvb-usb/m920x.h @@ -0,0 +1,10 @@ +#ifndef _DVB_USB_MEGASKY_H_ +#define _DVB_USB_MEGASKY_H_ + +#define DVB_USB_LOG_PREFIX "megasky" +#include "dvb-usb.h" + +extern int dvb_usb_megasky_debug; +#define deb_rc(args...) dprintk(dvb_usb_megasky_debug,0x01,args) + +#endif diff --git a/linux/drivers/media/dvb/dvb-usb/megasky.c b/linux/drivers/media/dvb/dvb-usb/megasky.c deleted file mode 100644 index 73e309cb8..000000000 --- a/linux/drivers/media/dvb/dvb-usb/megasky.c +++ /dev/null @@ -1,696 +0,0 @@ -/* 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 "megasky.h" - -#include "mt352.h" -#include "mt352_priv.h" - -/* debug */ -int dvb_usb_megasky_debug; -module_param_named(debug,dvb_usb_megasky_debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); - -static struct dvb_usb_rc_key megasky_rc_keys [] = { - { 0x0, 0x12, KEY_POWER }, - { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */ - { 0x0, 0x02, KEY_CHANNELUP }, - { 0x0, 0x05, KEY_CHANNELDOWN }, - { 0x0, 0x03, KEY_VOLUMEUP }, - { 0x0, 0x06, KEY_VOLUMEDOWN }, - { 0x0, 0x04, KEY_MUTE }, - { 0x0, 0x07, KEY_OK }, /* TS */ - { 0x0, 0x08, KEY_STOP }, - { 0x0, 0x09, KEY_MENU }, /* swap */ - { 0x0, 0x0a, KEY_REWIND }, - { 0x0, 0x1b, KEY_PAUSE }, - { 0x0, 0x1f, KEY_FASTFORWARD }, - { 0x0, 0x0c, KEY_RECORD }, - { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */ - { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ -}; - -static inline int m9206_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) - return ret; - - if (ret != size) - return -EIO; - - return 0; -} - -static inline int m9206_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); - msleep(3); - - return ret; -} - -static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) -{ - int i, ret = 0; - u8 rc_state[2]; - - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - - if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff51, rc_state, 1)) != 0) - goto unlock; - - if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff52, rc_state + 1, 1)) != 0) - goto unlock; - - for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++) - if (megasky_rc_keys[i].data == rc_state[1]) { - *event = megasky_rc_keys[i].event; - - switch(rc_state[0]) { - case 0x80: - *state = REMOTE_NO_KEY_PRESSED; - goto unlock; - - case 0x93: - case 0x92: - *state = REMOTE_KEY_PRESSED; - goto unlock; - - case 0x91: - *state = REMOTE_KEY_REPEAT; - goto unlock; - - default: - deb_rc("Unexpected rc response %x\n", rc_state[0]); - *state = REMOTE_NO_KEY_PRESSED; - goto unlock; - } - } - - if (rc_state[1] != 0) - deb_rc("Unknown rc key %x\n", rc_state[1]); - - *state = REMOTE_NO_KEY_PRESSED; - - unlock: - mutex_unlock(&d->i2c_mutex); - - return ret; -} - -/* I2C */ - -static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) -{ - struct dvb_usb_device *d = i2c_get_adapdata(adap); - int i; - int ret = 0; - - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - - if (num > 2) - return -EINVAL; - - for (i = 0; i < num; i++) { - u8 w_len; - - if ((ret = m9206_write(d->udev, 0x23, msg[i].addr, 0x80)) != 0) - goto unlock; - - if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[0], 0x0)) != 0) - goto unlock; - - if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) { - if (msg[i].addr == 0x1e) - w_len = 0x1f; - else - w_len = 0xc5; - - if ((ret = m9206_write(d->udev, 0x23, w_len, 0x80)) != 0) - goto unlock; - - if ((ret = m9206_read(d->udev, 0x23, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0) - goto unlock; - - i++; - } else { - if (msg[i].len != 2) - return -EINVAL; - - if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[1], 0x40)) != 0) - goto unlock; - } - } - ret = i; - unlock: - mutex_unlock(&d->i2c_mutex); - - return ret; -} - -static u32 m9206_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C; -} - -static struct i2c_algorithm m9206_i2c_algo = { - .master_xfer = m9206_i2c_xfer, - .functionality = m9206_i2c_func, -}; - -/* Callbacks for DVB USB */ -static int megasky_identify_state (struct usb_device *udev, - struct dvb_usb_properties *props, - struct dvb_usb_device_description **desc, - int *cold) -{ - struct usb_host_interface *alt; - - alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1); - *cold = (alt == NULL) ? 1 : 0; - - return 0; -} - -static int megasky_mt352_demod_init(struct dvb_frontend *fe) -{ - int i; - static u8 buf1[] = { - CONFIG, 0x3d, - CLOCK_CTL, 0x30, - RESET, 0x80, - ADC_CTL_1, 0x40, - AGC_TARGET, 0x1c, - AGC_CTL, 0x20, - 0x69, 0x00, - 0x6a, 0xff, - 0x6b, 0xff, - 0x6c, 0x40, - 0x6d, 0xff, - 0x6e, 0x00, - 0x6f, 0x40, - 0x70, 0x40, - 0x93, 0x1a, - 0xb5, 0x7a, - ACQ_CTL, 0x50, - INPUT_FREQ_1, 0x31, - INPUT_FREQ_0, 0x05, - }; - - for (i = 0; i < ARRAY_SIZE(buf1); i += 2) - mt352_write(fe, &buf1[i], 2); - - deb_rc("Demod init!\n"); - - return 0; -} - -struct mt352_state; - - -#define W 0 -#define R 1 -/* Not actual hw limits. */ -#define QT1010_MIN_STEP 2000000 -#define QT1010_MIN_FREQ 48000000 - -int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) -{ - int i; - int div, mod; - struct { - u8 read, reg, value; - } rd[46] = { { W, 0x01, 0x80 }, - { W, 0x02, 0x3f }, - { W, 0x05, 0xff }, /* c */ - { W, 0x06, 0x44 }, - { W, 0x07, 0xff }, /* c */ - { W, 0x08, 0x08 }, - { W, 0x09, 0xff }, /* c */ - { W, 0x0a, 0xff }, /* c */ - { W, 0x0b, 0xff }, /* c */ - { W, 0x0c, 0xe1 }, - { W, 0x1a, 0xff }, /* 10 c */ - { W, 0x1b, 0x00 }, - { W, 0x1c, 0x89 }, - { W, 0x11, 0xff }, /* c */ - { W, 0x12, 0x91 }, - { W, 0x22, 0xff }, /* c */ - { W, 0x1e, 0x00 }, - { W, 0x1e, 0xd0 }, - { R, 0x22, 0xff }, /* c read */ - { W, 0x1e, 0x00 }, - { R, 0x05, 0xff }, /* 20 c read */ - { R, 0x22, 0xff }, /* c read */ - { W, 0x23, 0xd0 }, - { W, 0x1e, 0x00 }, - { W, 0x1e, 0xe0 }, - { R, 0x23, 0xff }, /* c read */ - { W, 0x1e, 0x00 }, - { W, 0x24, 0xd0 }, - { W, 0x1e, 0x00 }, - { W, 0x1e, 0xf0 }, - { R, 0x24, 0xff }, /* 30 c read */ - { W, 0x1e, 0x00 }, - { W, 0x14, 0x7f }, - { W, 0x15, 0x7f }, - { W, 0x05, 0xff }, /* c */ - { W, 0x06, 0x00 }, - { W, 0x15, 0x1f }, - { W, 0x16, 0xff }, - { W, 0x18, 0xff }, - { W, 0x1f, 0xff }, /* c */ - { W, 0x20, 0xff }, /* 40 c */ - { W, 0x21, 0x53 }, - { W, 0x25, 0xbd }, - { W, 0x26, 0x15 }, - { W, 0x02, 0x00 }, - { W, 0x01, 0x00 }, - }; - struct i2c_msg msg; - struct dvb_usb_device *d = fe->dvb->priv; - unsigned long freq = params->frequency; - - if (freq % QT1010_MIN_STEP) - deb_rc("frequency not supported.\n"); - - (void) buf; - (void) buf_len; - - div = (freq - QT1010_MIN_FREQ) / QT1010_MIN_STEP; - mod = (div + 16 - 9) % 16; - - /* 0x5 */ - if (div >= 377) - rd[2].value = 0x74; - else if (div >= 265) - rd[2].value = 0x54; - else if (div >= 121) - rd[2].value = 0x34; - else - rd[2].value = 0x14; - - /* 0x7 */ - rd[4].value = (((freq - QT1010_MIN_FREQ) / 1000000) * 9975 + 12960000) / 320000; - - /* 09 */ - if (mod < 4) - rd[6].value = 0x1d; - else - rd[6].value = 0x1c; - - /* 0a */ - if (mod < 2) - rd[7].value = 0x09; - else if (mod < 4) - rd[7].value = 0x08; - else if (mod < 6) - rd[7].value = 0x0f; - else if (mod < 8) - rd[7].value = 0x0e; - else if (mod < 10) - rd[7].value = 0x0d; - else if (mod < 12) - rd[7].value = 0x0c; - else if (mod < 14) - rd[7].value = 0x0b; - else - rd[7].value = 0x0a; - - /* 0b */ - if (div & 1) - rd[8].value = 0x45; - else - rd[8].value = 0x44; - - /* 1a */ - if (div & 1) - rd[10].value = 0x78; - else - rd[10].value = 0xf8; - - /* 11 */ - if (div >= 265) - rd[13].value = 0xf9; - else if (div >= 121) - rd[13].value = 0xfd; - else - rd[13].value = 0xf9; - - /* 22 */ - if (div < 201) - rd[15].value = 0xd0; - else if (div < 217) - rd[15].value = 0xd3; - else if (div < 233) - rd[15].value = 0xd6; - else if (div < 249) - rd[15].value = 0xd9; - else if (div < 265) - rd[15].value = 0xda; - else - rd[15].value = 0xd0; - - /* 05 */ - if (div >= 377) - rd[34].value = 0x70; - else if (div >= 265) - rd[34].value = 0x50; - else if (div >= 121) - rd[34].value = 0x30; - else - rd[34].value = 0x10; - - /* 1f */ - if (mod < 4) - rd[39].value = 0x64; - else if (mod < 6) - rd[39].value = 0x66; - else if (mod < 8) - rd[39].value = 0x67; - else if (mod < 12) - rd[39].value = 0x68; - else if (mod < 14) - rd[39].value = 0x69; - else - rd[39].value = 0x6a; - - /* 20 */ - if (mod < 4) - rd[40].value = 0x10; - else if (mod < 6) - rd[40].value = 0x11; - else if (mod < 10) - rd[40].value = 0x12; - else if (mod < 12) - rd[40].value = 0x13; - else if (mod < 14) - rd[40].value = 0x14; - else - rd[40].value = 0x15; - - deb_rc("Now tuning... "); - for (i = 0; i < sizeof(rd) / sizeof(*rd); i++) { - if (rd[i].read) - continue; - - msg.flags = 0; - msg.len = 2; - msg.addr = 0xc4; - msg.buf = &rd[i].reg; - - if (i2c_transfer(&d->i2c_adap, &msg, 1) != 1) { - deb_rc("tuner write failed\n"); - return -EIO; - } - } - deb_rc("done\n"); - - return 0; -} -#undef W -#undef R - -static struct mt352_config megasky_mt352_config = { - .demod_address = 0x1e, - .demod_init = megasky_mt352_demod_init, -}; - -static int megasky_frontend_attach(struct dvb_usb_device *d) -{ - deb_rc("megasky_frontend_attach!\n"); - - if ((d->fe = mt352_attach(&megasky_mt352_config, &d->i2c_adap)) != NULL) { - d->fe->ops.tuner_ops.calc_regs = qt1010_set_params; - return 0; - } - return -EIO; -} - -/* DVB USB Driver stuff */ -static struct dvb_usb_properties megasky_properties; - -static int megasky_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct dvb_usb_device *d; - struct usb_host_interface *alt; - int ret; - - if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) { - deb_rc("probed!\n"); - - alt = usb_altnum_to_altsetting(intf, 1); - if (alt == NULL) { - deb_rc("not alt found!\n"); - return -ENODEV; - } - - ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); - if (ret < 0) - return ret; - - deb_rc("Changed to alternate setting!\n"); - - /* Remote controller init. */ - if ((ret = m9206_write(d->udev, 0x22, 0xa8, 0xff55)) != 0) - return ret; - - if ((ret = m9206_write(d->udev, 0x22, 0x51, 0xff54)) != 0) - return ret; - } - return ret; -} - -static struct usb_device_id megasky_table [] = { - { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE (usb, megasky_table); - -static int set_filter(struct dvb_usb_device *d, int type, int idx, int pid) -{ - int ret = 0; - - if (pid >= 0x8000) - return -EINVAL; - - pid |= 0x8000; - - if ((ret = m9206_write(d->udev, 0x25, pid, (type << 8) | (idx * 4) )) != 0) - return ret; - - if ((ret = m9206_write(d->udev, 0x25, 0, (type << 8) | (idx * 4) )) != 0) - return ret; - - return ret; -} - -static int m9206_pid_filter_ctrl(struct dvb_usb_device *d, int onoff) -{ - int ret = 0; - - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - - deb_rc("filtering %s\n", onoff ? "on" : "off"); - if (onoff == 0) { - if ((ret = set_filter(d, 0x81, 1, 0x00)) != 0) - goto unlock; - - if ((ret = set_filter(d, 0x82, 0, 0x02f5)) != 0) - goto unlock; - } - unlock: - mutex_unlock(&d->i2c_mutex); - - return ret; -} - -static int m9206_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff) -{ - int ret = 0; - - if (pid == 8192) - return m9206_pid_filter_ctrl(d, !onoff); - - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) - return -EAGAIN; - - deb_rc("filter %d, pid %x, %s\n", index, pid, onoff ? "on" : "off"); - if (onoff == 0) - pid = 0; - - if ((ret = set_filter(d, 0x81, 1, 0x01)) != 0) - goto unlock; - - if ((ret = set_filter(d, 0x81, index + 2, pid)) != 0) - goto unlock; - - if ((ret = set_filter(d, 0x82, 0, 0x02f5)) != 0) - goto unlock; - - unlock: - mutex_unlock(&d->i2c_mutex); - - return ret; -} - -static int m9206_firmware_download(struct usb_device *udev, const struct firmware *fw) -{ - u16 value, index, size; - u8 read[4], *buff; - int i, pass, ret = 0; - - buff = kmalloc(65536, GFP_KERNEL); - - if ((ret = m9206_read(udev, 0x25, 0x0, 0x8000, read, 4)) != 0) - goto done; - deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]); - - if ((ret = m9206_read(udev, 0x30, 0x0, 0x0, read, 1)) != 0) - goto done; - deb_rc("%x\n", read[0]); - - for (pass = 0; pass < 2; pass++) { - for (i = 0; i + (sizeof(u16) * 3) < fw->size;) { - value = le16_to_cpu(*(u16 *)(fw->data + i)); - i += sizeof(u16); - - index = le16_to_cpu(*(u16 *)(fw->data + i)); - i += sizeof(u16); - - size = le16_to_cpu(*(u16 *)(fw->data + i)); - i += sizeof(u16); - - if (pass == 1) { - /* Will stall if using fw->data ... */ - memcpy(buff, fw->data + i, size); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), - 0x30, USB_TYPE_VENDOR | USB_DIR_OUT, - value, index, buff, size, 20); - if (ret != size) { - deb_rc("error while uploading fw!\n"); - ret = -EIO; - goto done; - } - msleep(3); - } - i += size; - } - if (i != fw->size) { - ret = -EINVAL; - goto done; - } - } - - msleep(36); - - /* m9206 will disconnect itself from the bus after this. */ - (void) m9206_write(udev, 0x22, 0x01, 0xff69); - deb_rc("firmware uploaded!\n"); - - done: - kfree(buff); - - return ret; -} - -static struct dvb_usb_properties megasky_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_HAS_PID_FILTER | - DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_NEED_PID_FILTERING, - .pid_filter_count = 8, - - .usb_ctrl = DEVICE_SPECIFIC, - .firmware = "dvb-usb-megasky-02.fw", - .download_firmware = m9206_firmware_download, - - .pid_filter = m9206_pid_filter, - .pid_filter_ctrl = m9206_pid_filter_ctrl, - .frontend_attach = megasky_frontend_attach, - - .rc_interval = 200, - .rc_key_map = megasky_rc_keys, - .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys), - .rc_query = m9206_rc_query, - - .size_of_priv = 0, - - .identify_state = megasky_identify_state, - .i2c_algo = &m9206_i2c_algo, - - .generic_bulk_ctrl_endpoint = 0x01, - .urb = { - .type = DVB_USB_BULK, - .count = 8, - .endpoint = 0x81, - .u = { - .bulk = { - .buffersize = 512, - } - } - }, - .num_device_descs = 1, - .devices = { - { "MSI Mega Sky 580 DVB-T USB2.0", - { &megasky_table[0], NULL }, - { NULL }, - }, - { NULL }, - } -}; - -static struct usb_driver megasky_driver = { -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) - .owner = THIS_MODULE, -#endif - .name = "dvb_usb_megasky", - .probe = megasky_probe, - .disconnect = dvb_usb_device_exit, - .id_table = megasky_table, -}; - -/* module stuff */ -static int __init megasky_module_init(void) -{ - int ret; - - if ((ret = usb_register(&megasky_driver))) { - err("usb_register failed. Error number %d", ret); - return ret; - } - - return 0; -} - -static void __exit megasky_module_exit(void) -{ - /* deregister this driver from the USB subsystem */ - usb_deregister(&megasky_driver); -} - -module_init (megasky_module_init); -module_exit (megasky_module_exit); - -MODULE_AUTHOR("Aapo Tahkola "); -MODULE_DESCRIPTION("Driver for MSI Mega Sky 580 DVB-T USB2.0"); -MODULE_VERSION("0.1"); -MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/dvb-usb/megasky.h b/linux/drivers/media/dvb/dvb-usb/megasky.h deleted file mode 100644 index 6f14ae74e..000000000 --- a/linux/drivers/media/dvb/dvb-usb/megasky.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _DVB_USB_MEGASKY_H_ -#define _DVB_USB_MEGASKY_H_ - -#define DVB_USB_LOG_PREFIX "megasky" -#include "dvb-usb.h" - -extern int dvb_usb_megasky_debug; -#define deb_rc(args...) dprintk(dvb_usb_megasky_debug,0x01,args) - -#endif -- cgit v1.2.3 From 060e944993ec36070b3f84e4f6f09bba076d01de Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 23 Sep 2006 19:01:29 -0400 Subject: m920x: cleanups after rename from megasky.[ch] From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/Kconfig | 4 +- linux/drivers/media/dvb/dvb-usb/Makefile | 2 +- linux/drivers/media/dvb/dvb-usb/m920x.c | 70 ++++++++++++++++---------------- linux/drivers/media/dvb/dvb-usb/m920x.h | 10 ++--- 4 files changed, 43 insertions(+), 43 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 5f2a0c1dc..e120d9871 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -109,8 +109,8 @@ config DVB_USB_CXUSB Medion MD95700 hybrid USB2.0 device. DViCO FusionHDTV (Bluebird) USB2.0 devices -config DVB_USB_MEGASKY - tristate "MSI Mega Sky 580 DVB-T USB2.0 support" +config DVB_USB_M920X + tristate "Uli m920x DVB-T USB2.0 support" depends on DVB_USB select DVB_MT352 help diff --git a/linux/drivers/media/dvb/dvb-usb/Makefile b/linux/drivers/media/dvb/dvb-usb/Makefile index e2eed102e..815e27898 100644 --- a/linux/drivers/media/dvb/dvb-usb/Makefile +++ b/linux/drivers/media/dvb/dvb-usb/Makefile @@ -31,7 +31,7 @@ dvb-usb-umt-010-objs = umt-010.o obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o dvb-usb-m920x-objs = m920x.o -obj-$(CONFIG_DVB_USB_MEGASKY) += dvb-usb-m920x.o +obj-$(CONFIG_DVB_USB_M920X) += dvb-usb-m920x.o dvb-usb-digitv-objs = digitv.o obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 915b6453a..4820fd07d 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -8,14 +8,15 @@ * * see Documentation/dvb/README.dvb-usb for more information */ + #include "m920x.h" #include "mt352.h" #include "mt352_priv.h" /* debug */ -int dvb_usb_megasky_debug; -module_param_named(debug,dvb_usb_megasky_debug, int, 0644); +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); static struct dvb_usb_rc_key megasky_rc_keys [] = { @@ -194,25 +195,25 @@ static int megasky_mt352_demod_init(struct dvb_frontend *fe) { int i; static u8 buf1[] = { - CONFIG, 0x3d, - CLOCK_CTL, 0x30, - RESET, 0x80, - ADC_CTL_1, 0x40, - AGC_TARGET, 0x1c, - AGC_CTL, 0x20, - 0x69, 0x00, - 0x6a, 0xff, - 0x6b, 0xff, - 0x6c, 0x40, - 0x6d, 0xff, - 0x6e, 0x00, - 0x6f, 0x40, - 0x70, 0x40, - 0x93, 0x1a, - 0xb5, 0x7a, - ACQ_CTL, 0x50, - INPUT_FREQ_1, 0x31, - INPUT_FREQ_0, 0x05, + CONFIG, 0x3d, + CLOCK_CTL, 0x30, + RESET, 0x80, + ADC_CTL_1, 0x40, + AGC_TARGET, 0x1c, + AGC_CTL, 0x20, + 0x69, 0x00, + 0x6a, 0xff, + 0x6b, 0xff, + 0x6c, 0x40, + 0x6d, 0xff, + 0x6e, 0x00, + 0x6f, 0x40, + 0x70, 0x40, + 0x93, 0x1a, + 0xb5, 0x7a, + ACQ_CTL, 0x50, + INPUT_FREQ_1, 0x31, + INPUT_FREQ_0, 0x05, }; for (i = 0; i < ARRAY_SIZE(buf1); i += 2) @@ -225,7 +226,6 @@ static int megasky_mt352_demod_init(struct dvb_frontend *fe) struct mt352_state; - #define W 0 #define R 1 /* Not actual hw limits. */ @@ -479,11 +479,11 @@ static int megasky_probe(struct usb_interface *intf, const struct usb_device_id return ret; } -static struct usb_device_id megasky_table [] = { +static struct usb_device_id m920x_table [] = { { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, megasky_table); +MODULE_DEVICE_TABLE (usb, m920x_table); static int set_filter(struct dvb_usb_device *d, int type, int idx, int pid) { @@ -651,29 +651,29 @@ static struct dvb_usb_properties megasky_properties = { .num_device_descs = 1, .devices = { { "MSI Mega Sky 580 DVB-T USB2.0", - { &megasky_table[0], NULL }, + { &m920x_table[0], NULL }, { NULL }, }, { NULL }, } }; -static struct usb_driver megasky_driver = { +static struct usb_driver m920x_driver = { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) .owner = THIS_MODULE, #endif - .name = "dvb_usb_megasky", + .name = "dvb_usb_m920x", .probe = megasky_probe, .disconnect = dvb_usb_device_exit, - .id_table = megasky_table, + .id_table = m920x_table, }; /* module stuff */ -static int __init megasky_module_init(void) +static int __init m920x_module_init(void) { int ret; - if ((ret = usb_register(&megasky_driver))) { + if ((ret = usb_register(&m920x_driver))) { err("usb_register failed. Error number %d", ret); return ret; } @@ -681,16 +681,16 @@ static int __init megasky_module_init(void) return 0; } -static void __exit megasky_module_exit(void) +static void __exit m920x_module_exit(void) { /* deregister this driver from the USB subsystem */ - usb_deregister(&megasky_driver); + usb_deregister(&m920x_driver); } -module_init (megasky_module_init); -module_exit (megasky_module_exit); +module_init (m920x_module_init); +module_exit (m920x_module_exit); MODULE_AUTHOR("Aapo Tahkola "); -MODULE_DESCRIPTION("Driver for MSI Mega Sky 580 DVB-T USB2.0"); +MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.h b/linux/drivers/media/dvb/dvb-usb/m920x.h index 6f14ae74e..fdb967aa3 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.h +++ b/linux/drivers/media/dvb/dvb-usb/m920x.h @@ -1,10 +1,10 @@ -#ifndef _DVB_USB_MEGASKY_H_ -#define _DVB_USB_MEGASKY_H_ +#ifndef _DVB_USB_M920X_H_ +#define _DVB_USB_M920X_H_ -#define DVB_USB_LOG_PREFIX "megasky" +#define DVB_USB_LOG_PREFIX "m920x" #include "dvb-usb.h" -extern int dvb_usb_megasky_debug; -#define deb_rc(args...) dprintk(dvb_usb_megasky_debug,0x01,args) +extern int dvb_usb_m920x_debug; +#define deb_rc(args...) dprintk(dvb_usb_m920x_debug,0x01,args) #endif -- cgit v1.2.3 From 64af2f151592da0ffb146d2867db3ebae0b66572 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 23 Sep 2006 19:01:29 -0400 Subject: m920x: update megasky driver for recent changes in the dvb tree From: Michael Krufky update code to use dvb_attach() update code to reflect recent changes to the dvb_usb framework Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/Kconfig | 2 +- linux/drivers/media/dvb/dvb-usb/m920x.c | 83 +++++++++++++++++---------------- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index e120d9871..e18eb7b3f 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -112,7 +112,7 @@ config DVB_USB_CXUSB config DVB_USB_M920X tristate "Uli m920x DVB-T USB2.0 support" depends on DVB_USB - select DVB_MT352 + select DVB_MT352 if !DVB_FE_CUSTOMISE help Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. Currently, only devices with a product id of diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 4820fd07d..aa53bc498 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -179,7 +179,7 @@ static struct i2c_algorithm m9206_i2c_algo = { /* Callbacks for DVB USB */ static int megasky_identify_state (struct usb_device *udev, - struct dvb_usb_properties *props, + struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, int *cold) { @@ -434,19 +434,19 @@ static struct mt352_config megasky_mt352_config = { .demod_init = megasky_mt352_demod_init, }; -static int megasky_frontend_attach(struct dvb_usb_device *d) +static int megasky_frontend_attach(struct dvb_usb_adapter *adap) { deb_rc("megasky_frontend_attach!\n"); - if ((d->fe = mt352_attach(&megasky_mt352_config, &d->i2c_adap)) != NULL) { - d->fe->ops.tuner_ops.calc_regs = qt1010_set_params; + if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) != NULL) { + adap->fe->ops.tuner_ops.calc_regs = qt1010_set_params; return 0; } return -EIO; } /* DVB USB Driver stuff */ -static struct dvb_usb_properties megasky_properties; +static struct dvb_usb_device_properties megasky_properties; static int megasky_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -485,7 +485,7 @@ static struct usb_device_id m920x_table [] = { }; MODULE_DEVICE_TABLE (usb, m920x_table); -static int set_filter(struct dvb_usb_device *d, int type, int idx, int pid) +static int set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid) { int ret = 0; @@ -494,61 +494,61 @@ static int set_filter(struct dvb_usb_device *d, int type, int idx, int pid) pid |= 0x8000; - if ((ret = m9206_write(d->udev, 0x25, pid, (type << 8) | (idx * 4) )) != 0) + if ((ret = m9206_write(adap->dev->udev, 0x25, pid, (type << 8) | (idx * 4) )) != 0) return ret; - if ((ret = m9206_write(d->udev, 0x25, 0, (type << 8) | (idx * 4) )) != 0) + if ((ret = m9206_write(adap->dev->udev, 0x25, 0, (type << 8) | (idx * 4) )) != 0) return ret; return ret; } -static int m9206_pid_filter_ctrl(struct dvb_usb_device *d, int onoff) +static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { int ret = 0; - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) return -EAGAIN; deb_rc("filtering %s\n", onoff ? "on" : "off"); if (onoff == 0) { - if ((ret = set_filter(d, 0x81, 1, 0x00)) != 0) + if ((ret = set_filter(adap, 0x81, 1, 0x00)) != 0) goto unlock; - if ((ret = set_filter(d, 0x82, 0, 0x02f5)) != 0) + if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0) goto unlock; } unlock: - mutex_unlock(&d->i2c_mutex); + mutex_unlock(&adap->dev->i2c_mutex); return ret; } -static int m9206_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff) +static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) { int ret = 0; if (pid == 8192) - return m9206_pid_filter_ctrl(d, !onoff); + return m9206_pid_filter_ctrl(adap, !onoff); - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) return -EAGAIN; deb_rc("filter %d, pid %x, %s\n", index, pid, onoff ? "on" : "off"); if (onoff == 0) pid = 0; - if ((ret = set_filter(d, 0x81, 1, 0x01)) != 0) + if ((ret = set_filter(adap, 0x81, 1, 0x01)) != 0) goto unlock; - if ((ret = set_filter(d, 0x81, index + 2, pid)) != 0) + if ((ret = set_filter(adap, 0x81, index + 2, pid)) != 0) goto unlock; - if ((ret = set_filter(d, 0x82, 0, 0x02f5)) != 0) + if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0) goto unlock; unlock: - mutex_unlock(&d->i2c_mutex); + mutex_unlock(&adap->dev->i2c_mutex); return ret; } @@ -614,19 +614,11 @@ static int m9206_firmware_download(struct usb_device *udev, const struct firmwar return ret; } -static struct dvb_usb_properties megasky_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_HAS_PID_FILTER | - DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_NEED_PID_FILTERING, - .pid_filter_count = 8, - +static struct dvb_usb_device_properties megasky_properties = { .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-megasky-02.fw", .download_firmware = m9206_firmware_download, - .pid_filter = m9206_pid_filter, - .pid_filter_ctrl = m9206_pid_filter_ctrl, - .frontend_attach = megasky_frontend_attach, - .rc_interval = 200, .rc_key_map = megasky_rc_keys, .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys), @@ -635,19 +627,32 @@ static struct dvb_usb_properties megasky_properties = { .size_of_priv = 0, .identify_state = megasky_identify_state, + .num_adapters = 1, + .adapter = {{ + .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | + DVB_USB_ADAP_NEED_PID_FILTERING, + .pid_filter_count = 8, + .pid_filter = m9206_pid_filter, + .pid_filter_ctrl = m9206_pid_filter_ctrl, + + .frontend_attach = megasky_frontend_attach, + + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, + }}, .i2c_algo = &m9206_i2c_algo, .generic_bulk_ctrl_endpoint = 0x01, - .urb = { - .type = DVB_USB_BULK, - .count = 8, - .endpoint = 0x81, - .u = { - .bulk = { - .buffersize = 512, - } - } - }, + .num_device_descs = 1, .devices = { { "MSI Mega Sky 580 DVB-T USB2.0", -- cgit v1.2.3 From f2f612b275408e919235c937e61c6992b71f6723 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 23 Sep 2006 19:13:12 -0400 Subject: m920x: trivial cleanups From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index aa53bc498..4213beda8 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -178,10 +178,10 @@ static struct i2c_algorithm m9206_i2c_algo = { }; /* Callbacks for DVB USB */ -static int megasky_identify_state (struct usb_device *udev, - struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, - int *cold) +static int megasky_identify_state(struct usb_device *udev, + struct dvb_usb_device_properties *props, + struct dvb_usb_device_description **desc, + int *cold) { struct usb_host_interface *alt; @@ -448,7 +448,7 @@ static int megasky_frontend_attach(struct dvb_usb_adapter *adap) /* DVB USB Driver stuff */ static struct dvb_usb_device_properties megasky_properties; -static int megasky_probe(struct usb_interface *intf, const struct usb_device_id *id) +static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct dvb_usb_device *d; struct usb_host_interface *alt; @@ -668,7 +668,7 @@ static struct usb_driver m920x_driver = { .owner = THIS_MODULE, #endif .name = "dvb_usb_m920x", - .probe = megasky_probe, + .probe = m920x_probe, .disconnect = dvb_usb_device_exit, .id_table = m920x_table, }; -- cgit v1.2.3 From 8d754c26a4d9b88654352d8600fd622c1f7060d2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 23 Sep 2006 19:40:20 -0400 Subject: m920x: break out qt1010 tuner code into a separate file From: Michael Krufky qt1010 is a tuner used in some other devices, so this code should be put into a separate file so that it could be reused by other drivers. Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 204 +------------------------- linux/drivers/media/dvb/frontends/qt1010.h | 221 +++++++++++++++++++++++++++++ 2 files changed, 222 insertions(+), 203 deletions(-) create mode 100644 linux/drivers/media/dvb/frontends/qt1010.h diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 4213beda8..2a7bb3808 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -13,6 +13,7 @@ #include "mt352.h" #include "mt352_priv.h" +#include "qt1010.h" /* debug */ int dvb_usb_m920x_debug; @@ -226,209 +227,6 @@ static int megasky_mt352_demod_init(struct dvb_frontend *fe) struct mt352_state; -#define W 0 -#define R 1 -/* Not actual hw limits. */ -#define QT1010_MIN_STEP 2000000 -#define QT1010_MIN_FREQ 48000000 - -int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) -{ - int i; - int div, mod; - struct { - u8 read, reg, value; - } rd[46] = { { W, 0x01, 0x80 }, - { W, 0x02, 0x3f }, - { W, 0x05, 0xff }, /* c */ - { W, 0x06, 0x44 }, - { W, 0x07, 0xff }, /* c */ - { W, 0x08, 0x08 }, - { W, 0x09, 0xff }, /* c */ - { W, 0x0a, 0xff }, /* c */ - { W, 0x0b, 0xff }, /* c */ - { W, 0x0c, 0xe1 }, - { W, 0x1a, 0xff }, /* 10 c */ - { W, 0x1b, 0x00 }, - { W, 0x1c, 0x89 }, - { W, 0x11, 0xff }, /* c */ - { W, 0x12, 0x91 }, - { W, 0x22, 0xff }, /* c */ - { W, 0x1e, 0x00 }, - { W, 0x1e, 0xd0 }, - { R, 0x22, 0xff }, /* c read */ - { W, 0x1e, 0x00 }, - { R, 0x05, 0xff }, /* 20 c read */ - { R, 0x22, 0xff }, /* c read */ - { W, 0x23, 0xd0 }, - { W, 0x1e, 0x00 }, - { W, 0x1e, 0xe0 }, - { R, 0x23, 0xff }, /* c read */ - { W, 0x1e, 0x00 }, - { W, 0x24, 0xd0 }, - { W, 0x1e, 0x00 }, - { W, 0x1e, 0xf0 }, - { R, 0x24, 0xff }, /* 30 c read */ - { W, 0x1e, 0x00 }, - { W, 0x14, 0x7f }, - { W, 0x15, 0x7f }, - { W, 0x05, 0xff }, /* c */ - { W, 0x06, 0x00 }, - { W, 0x15, 0x1f }, - { W, 0x16, 0xff }, - { W, 0x18, 0xff }, - { W, 0x1f, 0xff }, /* c */ - { W, 0x20, 0xff }, /* 40 c */ - { W, 0x21, 0x53 }, - { W, 0x25, 0xbd }, - { W, 0x26, 0x15 }, - { W, 0x02, 0x00 }, - { W, 0x01, 0x00 }, - }; - struct i2c_msg msg; - struct dvb_usb_device *d = fe->dvb->priv; - unsigned long freq = params->frequency; - - if (freq % QT1010_MIN_STEP) - deb_rc("frequency not supported.\n"); - - (void) buf; - (void) buf_len; - - div = (freq - QT1010_MIN_FREQ) / QT1010_MIN_STEP; - mod = (div + 16 - 9) % 16; - - /* 0x5 */ - if (div >= 377) - rd[2].value = 0x74; - else if (div >= 265) - rd[2].value = 0x54; - else if (div >= 121) - rd[2].value = 0x34; - else - rd[2].value = 0x14; - - /* 0x7 */ - rd[4].value = (((freq - QT1010_MIN_FREQ) / 1000000) * 9975 + 12960000) / 320000; - - /* 09 */ - if (mod < 4) - rd[6].value = 0x1d; - else - rd[6].value = 0x1c; - - /* 0a */ - if (mod < 2) - rd[7].value = 0x09; - else if (mod < 4) - rd[7].value = 0x08; - else if (mod < 6) - rd[7].value = 0x0f; - else if (mod < 8) - rd[7].value = 0x0e; - else if (mod < 10) - rd[7].value = 0x0d; - else if (mod < 12) - rd[7].value = 0x0c; - else if (mod < 14) - rd[7].value = 0x0b; - else - rd[7].value = 0x0a; - - /* 0b */ - if (div & 1) - rd[8].value = 0x45; - else - rd[8].value = 0x44; - - /* 1a */ - if (div & 1) - rd[10].value = 0x78; - else - rd[10].value = 0xf8; - - /* 11 */ - if (div >= 265) - rd[13].value = 0xf9; - else if (div >= 121) - rd[13].value = 0xfd; - else - rd[13].value = 0xf9; - - /* 22 */ - if (div < 201) - rd[15].value = 0xd0; - else if (div < 217) - rd[15].value = 0xd3; - else if (div < 233) - rd[15].value = 0xd6; - else if (div < 249) - rd[15].value = 0xd9; - else if (div < 265) - rd[15].value = 0xda; - else - rd[15].value = 0xd0; - - /* 05 */ - if (div >= 377) - rd[34].value = 0x70; - else if (div >= 265) - rd[34].value = 0x50; - else if (div >= 121) - rd[34].value = 0x30; - else - rd[34].value = 0x10; - - /* 1f */ - if (mod < 4) - rd[39].value = 0x64; - else if (mod < 6) - rd[39].value = 0x66; - else if (mod < 8) - rd[39].value = 0x67; - else if (mod < 12) - rd[39].value = 0x68; - else if (mod < 14) - rd[39].value = 0x69; - else - rd[39].value = 0x6a; - - /* 20 */ - if (mod < 4) - rd[40].value = 0x10; - else if (mod < 6) - rd[40].value = 0x11; - else if (mod < 10) - rd[40].value = 0x12; - else if (mod < 12) - rd[40].value = 0x13; - else if (mod < 14) - rd[40].value = 0x14; - else - rd[40].value = 0x15; - - deb_rc("Now tuning... "); - for (i = 0; i < sizeof(rd) / sizeof(*rd); i++) { - if (rd[i].read) - continue; - - msg.flags = 0; - msg.len = 2; - msg.addr = 0xc4; - msg.buf = &rd[i].reg; - - if (i2c_transfer(&d->i2c_adap, &msg, 1) != 1) { - deb_rc("tuner write failed\n"); - return -EIO; - } - } - deb_rc("done\n"); - - return 0; -} -#undef W -#undef R - static struct mt352_config megasky_mt352_config = { .demod_address = 0x1e, .demod_init = megasky_mt352_demod_init, diff --git a/linux/drivers/media/dvb/frontends/qt1010.h b/linux/drivers/media/dvb/frontends/qt1010.h new file mode 100644 index 000000000..e526e3c23 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/qt1010.h @@ -0,0 +1,221 @@ +/* + * qt1010.h - DVB-T Tuner support + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _QT1010_H_ +#define _QT1010_H_ + +#define QT1010_W 0 +#define QT1010_R 1 +/* Not actual hw limits. */ +#define QT1010_MIN_STEP 2000000 +#define QT1010_MIN_FREQ 48000000 + +static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) +{ + int i; + int div, mod; + struct { + u8 read, reg, value; + } rd[46] = { { QT1010_W, 0x01, 0x80 }, + { QT1010_W, 0x02, 0x3f }, + { QT1010_W, 0x05, 0xff }, /* c */ + { QT1010_W, 0x06, 0x44 }, + { QT1010_W, 0x07, 0xff }, /* c */ + { QT1010_W, 0x08, 0x08 }, + { QT1010_W, 0x09, 0xff }, /* c */ + { QT1010_W, 0x0a, 0xff }, /* c */ + { QT1010_W, 0x0b, 0xff }, /* c */ + { QT1010_W, 0x0c, 0xe1 }, + { QT1010_W, 0x1a, 0xff }, /* 10 c */ + { QT1010_W, 0x1b, 0x00 }, + { QT1010_W, 0x1c, 0x89 }, + { QT1010_W, 0x11, 0xff }, /* c */ + { QT1010_W, 0x12, 0x91 }, + { QT1010_W, 0x22, 0xff }, /* c */ + { QT1010_W, 0x1e, 0x00 }, + { QT1010_W, 0x1e, 0xd0 }, + { QT1010_R, 0x22, 0xff }, /* c read */ + { QT1010_W, 0x1e, 0x00 }, + { QT1010_R, 0x05, 0xff }, /* 20 c read */ + { QT1010_R, 0x22, 0xff }, /* c read */ + { QT1010_W, 0x23, 0xd0 }, + { QT1010_W, 0x1e, 0x00 }, + { QT1010_W, 0x1e, 0xe0 }, + { QT1010_R, 0x23, 0xff }, /* c read */ + { QT1010_W, 0x1e, 0x00 }, + { QT1010_W, 0x24, 0xd0 }, + { QT1010_W, 0x1e, 0x00 }, + { QT1010_W, 0x1e, 0xf0 }, + { QT1010_R, 0x24, 0xff }, /* 30 c read */ + { QT1010_W, 0x1e, 0x00 }, + { QT1010_W, 0x14, 0x7f }, + { QT1010_W, 0x15, 0x7f }, + { QT1010_W, 0x05, 0xff }, /* c */ + { QT1010_W, 0x06, 0x00 }, + { QT1010_W, 0x15, 0x1f }, + { QT1010_W, 0x16, 0xff }, + { QT1010_W, 0x18, 0xff }, + { QT1010_W, 0x1f, 0xff }, /* c */ + { QT1010_W, 0x20, 0xff }, /* 40 c */ + { QT1010_W, 0x21, 0x53 }, + { QT1010_W, 0x25, 0xbd }, + { QT1010_W, 0x26, 0x15 }, + { QT1010_W, 0x02, 0x00 }, + { QT1010_W, 0x01, 0x00 }, + }; + struct i2c_msg msg; + struct dvb_usb_device *d = fe->dvb->priv; + unsigned long freq = params->frequency; + + if (freq % QT1010_MIN_STEP) + printk("frequency not supported.\n"); + + (void) buf; + (void) buf_len; + + div = (freq - QT1010_MIN_FREQ) / QT1010_MIN_STEP; + mod = (div + 16 - 9) % 16; + + /* 0x5 */ + if (div >= 377) + rd[2].value = 0x74; + else if (div >= 265) + rd[2].value = 0x54; + else if (div >= 121) + rd[2].value = 0x34; + else + rd[2].value = 0x14; + + /* 0x7 */ + rd[4].value = (((freq - QT1010_MIN_FREQ) / 1000000) * 9975 + 12960000) / 320000; + + /* 09 */ + if (mod < 4) + rd[6].value = 0x1d; + else + rd[6].value = 0x1c; + + /* 0a */ + if (mod < 2) + rd[7].value = 0x09; + else if (mod < 4) + rd[7].value = 0x08; + else if (mod < 6) + rd[7].value = 0x0f; + else if (mod < 8) + rd[7].value = 0x0e; + else if (mod < 10) + rd[7].value = 0x0d; + else if (mod < 12) + rd[7].value = 0x0c; + else if (mod < 14) + rd[7].value = 0x0b; + else + rd[7].value = 0x0a; + + /* 0b */ + if (div & 1) + rd[8].value = 0x45; + else + rd[8].value = 0x44; + + /* 1a */ + if (div & 1) + rd[10].value = 0x78; + else + rd[10].value = 0xf8; + + /* 11 */ + if (div >= 265) + rd[13].value = 0xf9; + else if (div >= 121) + rd[13].value = 0xfd; + else + rd[13].value = 0xf9; + + /* 22 */ + if (div < 201) + rd[15].value = 0xd0; + else if (div < 217) + rd[15].value = 0xd3; + else if (div < 233) + rd[15].value = 0xd6; + else if (div < 249) + rd[15].value = 0xd9; + else if (div < 265) + rd[15].value = 0xda; + else + rd[15].value = 0xd0; + + /* 05 */ + if (div >= 377) + rd[34].value = 0x70; + else if (div >= 265) + rd[34].value = 0x50; + else if (div >= 121) + rd[34].value = 0x30; + else + rd[34].value = 0x10; + + /* 1f */ + if (mod < 4) + rd[39].value = 0x64; + else if (mod < 6) + rd[39].value = 0x66; + else if (mod < 8) + rd[39].value = 0x67; + else if (mod < 12) + rd[39].value = 0x68; + else if (mod < 14) + rd[39].value = 0x69; + else + rd[39].value = 0x6a; + + /* 20 */ + if (mod < 4) + rd[40].value = 0x10; + else if (mod < 6) + rd[40].value = 0x11; + else if (mod < 10) + rd[40].value = 0x12; + else if (mod < 12) + rd[40].value = 0x13; + else if (mod < 14) + rd[40].value = 0x14; + else + rd[40].value = 0x15; + + for (i = 0; i < sizeof(rd) / sizeof(*rd); i++) { + if (rd[i].read) + continue; + + msg.flags = 0; + msg.len = 2; + msg.addr = 0xc4; + msg.buf = &rd[i].reg; + + if (i2c_transfer(&d->i2c_adap, &msg, 1) != 1) { + printk("tuner write failed\n"); + return -EIO; + } + } + + return 0; +} + +#endif -- cgit v1.2.3 From e5609737e9b7d74fd2daec8a4a6f5c354ed7e29b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 27 Sep 2006 23:47:51 -0400 Subject: m920x: misc updates and fixes From: Aapo Tahkola - hardware pid filtering no longer enabled unless in usb 1.x mode - more responsive rc handling - some minor bug fixes and code refolding - m9206_write delay dropped (doesn't seem to be needed) Signed-off-by: Aapo Tahkola Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 213 +++++++++++++++++------------ linux/drivers/media/dvb/dvb-usb/m920x.h | 18 +++ linux/drivers/media/dvb/frontends/qt1010.h | 7 +- 3 files changed, 145 insertions(+), 93 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 2a7bb3808..3c7f639e6 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -62,23 +62,36 @@ static inline int m9206_write(struct usb_device *udev, u8 request, u16 value, u1 ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, USB_TYPE_VENDOR | USB_DIR_OUT, value, index, NULL, 0, 2000); - msleep(3); + return ret; +} + +static int m9206_rc_init(struct usb_device *udev) +{ + int ret = 0; + + /* Remote controller init. */ + if ((ret = m9206_write(udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0) + return ret; + + if ((ret = m9206_write(udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0) + return ret; return ret; } static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { + struct m9206_state *m = d->priv; int i, ret = 0; u8 rc_state[2]; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; - if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff51, rc_state, 1)) != 0) + if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) goto unlock; - if ((ret = m9206_read(d->udev, 0x22, 0x0, 0xff52, rc_state + 1, 1)) != 0) + if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) goto unlock; for (i = 0; i < ARRAY_SIZE(megasky_rc_keys); i++) @@ -92,11 +105,14 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) case 0x93: case 0x92: + m->rep_count = 0; *state = REMOTE_KEY_PRESSED; goto unlock; case 0x91: - *state = REMOTE_KEY_REPEAT; + /* For comfort. */ + if (++m->rep_count > 2) + *state = REMOTE_KEY_REPEAT; goto unlock; default: @@ -125,6 +141,12 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int nu int i; int ret = 0; + /* Need to access d->adapter[0] */ + if (d->num_adapters_initialized != 1) { + deb_rc("Impossible happened!\n"); + return -EINVAL; + } + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; @@ -134,22 +156,23 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int nu for (i = 0; i < num; i++) { u8 w_len; - if ((ret = m9206_write(d->udev, 0x23, msg[i].addr, 0x80)) != 0) + if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].addr, 0x80)) != 0) goto unlock; - if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[0], 0x0)) != 0) + if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[0], 0x0)) != 0) goto unlock; if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) { - if (msg[i].addr == 0x1e) - w_len = 0x1f; - else + /* Possibly device dependant */ + if (msg[i].addr == d->adapter[0].pll_addr) w_len = 0xc5; + else + w_len = 0x1f; - if ((ret = m9206_write(d->udev, 0x23, w_len, 0x80)) != 0) + if ((ret = m9206_write(d->udev, M9206_I2C, w_len, 0x80)) != 0) goto unlock; - if ((ret = m9206_read(d->udev, 0x23, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0) + if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0) goto unlock; i++; @@ -157,7 +180,7 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int nu if (msg[i].len != 2) return -EINVAL; - if ((ret = m9206_write(d->udev, 0x23, msg[i].buf[1], 0x40)) != 0) + if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[1], 0x40)) != 0) goto unlock; } } @@ -194,31 +217,23 @@ static int megasky_identify_state(struct usb_device *udev, static int megasky_mt352_demod_init(struct dvb_frontend *fe) { - int i; - static u8 buf1[] = { - CONFIG, 0x3d, - CLOCK_CTL, 0x30, - RESET, 0x80, - ADC_CTL_1, 0x40, - AGC_TARGET, 0x1c, - AGC_CTL, 0x20, - 0x69, 0x00, - 0x6a, 0xff, - 0x6b, 0xff, - 0x6c, 0x40, - 0x6d, 0xff, - 0x6e, 0x00, - 0x6f, 0x40, - 0x70, 0x40, - 0x93, 0x1a, - 0xb5, 0x7a, - ACQ_CTL, 0x50, - INPUT_FREQ_1, 0x31, - INPUT_FREQ_0, 0x05, - }; - - for (i = 0; i < ARRAY_SIZE(buf1); i += 2) - mt352_write(fe, &buf1[i], 2); + u8 config[] = { CONFIG, 0x3d }; + u8 clock[] = { CLOCK_CTL, 0x30 }; + u8 reset[] = { RESET, 0x80 }; + u8 adc_ctl[] = { ADC_CTL_1, 0x40 }; + u8 agc[] = { AGC_TARGET, 0x1c, 0x20 }; + u8 sec_agc[] = { 0x69, 0x00, 0xff, 0xff, 0x40, 0xff, 0x00, 0x40, 0x40 }; + u8 unk1[] = { 0x93, 0x1a }; + u8 unk2[] = { 0xb5, 0x7a }; + + mt352_write(fe, config, ARRAY_SIZE(config)); + mt352_write(fe, clock, ARRAY_SIZE(clock)); + mt352_write(fe, reset, ARRAY_SIZE(reset)); + mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl)); + mt352_write(fe, agc, ARRAY_SIZE(agc)); + mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc)); + mt352_write(fe, unk1, ARRAY_SIZE(unk1)); + mt352_write(fe, unk2, ARRAY_SIZE(unk2)); deb_rc("Demod init!\n"); @@ -229,6 +244,7 @@ struct mt352_state; static struct mt352_config megasky_mt352_config = { .demod_address = 0x1e, + .no_tuner = 1, .demod_init = megasky_mt352_demod_init, }; @@ -237,22 +253,39 @@ static int megasky_frontend_attach(struct dvb_usb_adapter *adap) deb_rc("megasky_frontend_attach!\n"); if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) != NULL) { - adap->fe->ops.tuner_ops.calc_regs = qt1010_set_params; return 0; } return -EIO; } +static int megasky_tuner_attach(struct dvb_usb_adapter *adap) +{ + adap->pll_addr = 0xc4; + adap->pll_desc = NULL; + adap->fe->ops.tuner_ops.set_params = qt1010_set_params; + + return 0; +} + /* DVB USB Driver stuff */ static struct dvb_usb_device_properties megasky_properties; static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *id) { + struct usb_device *udev = interface_to_usbdev(intf); struct dvb_usb_device *d; struct usb_host_interface *alt; + struct dvb_usb_device_properties props; int ret; - if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) { + memcpy(&props, &megasky_properties, sizeof(struct dvb_usb_device_properties)); + + /* Hardware pid filtering isn't quite perfect so dont use unless have to. */ + if (udev->speed == USB_SPEED_FULL) + props.caps |= DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF; + + if ((ret = dvb_usb_device_init(intf, &props, THIS_MODULE, &d)) == 0) { deb_rc("probed!\n"); alt = usb_altnum_to_altsetting(intf, 1); @@ -267,11 +300,7 @@ static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *i deb_rc("Changed to alternate setting!\n"); - /* Remote controller init. */ - if ((ret = m9206_write(d->udev, 0x22, 0xa8, 0xff55)) != 0) - return ret; - - if ((ret = m9206_write(d->udev, 0x22, 0x51, 0xff54)) != 0) + if ((ret = m9206_rc_init(d->udev)) != 0) return ret; } return ret; @@ -292,63 +321,71 @@ static int set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid) pid |= 0x8000; - if ((ret = m9206_write(adap->dev->udev, 0x25, pid, (type << 8) | (idx * 4) )) != 0) + if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0) return ret; - if ((ret = m9206_write(adap->dev->udev, 0x25, 0, (type << 8) | (idx * 4) )) != 0) + if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0) return ret; return ret; } -static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +static int m9206_update_filters(struct dvb_usb_adapter *adap) { - int ret = 0; + struct m9206_state *m = adap->dev->priv; + int enabled = m->filtering_enabled; + int i, ret = 0, filter = 0; - if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) - return -EAGAIN; + for (i = 0; i < M9206_MAX_FILTERS; i++) + if (m->filters[i] == 8192) + enabled = 0; - deb_rc("filtering %s\n", onoff ? "on" : "off"); - if (onoff == 0) { - if ((ret = set_filter(adap, 0x81, 1, 0x00)) != 0) - goto unlock; + /* Disable all filters */ + if ((ret = set_filter(adap, 0x81, 1, enabled)) != 0) + return ret; - if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0) - goto unlock; + for (i = 0; i < M9206_MAX_FILTERS; i++) + if ((ret = set_filter(adap, 0x81, i + 2, 0)) != 0) + return ret; + + if ((ret = set_filter(adap, 0x82, 0, 0x0)) != 0) + return ret; + + /* Set */ + if (enabled) { + for (i = 0; i < M9206_MAX_FILTERS; i++) { + if (m->filters[i] == 0) + continue; + + if ((ret = set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0) + return ret; + + filter++; + } } - unlock: - mutex_unlock(&adap->dev->i2c_mutex); + + if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0) + return ret; return ret; } -static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) +static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { - int ret = 0; - - if (pid == 8192) - return m9206_pid_filter_ctrl(adap, !onoff); - - if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) - return -EAGAIN; + struct m9206_state *m = adap->dev->priv; - deb_rc("filter %d, pid %x, %s\n", index, pid, onoff ? "on" : "off"); - if (onoff == 0) - pid = 0; + m->filtering_enabled = onoff ? 1 : 0; - if ((ret = set_filter(adap, 0x81, 1, 0x01)) != 0) - goto unlock; - - if ((ret = set_filter(adap, 0x81, index + 2, pid)) != 0) - goto unlock; + return m9206_update_filters(adap); +} - if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0) - goto unlock; +static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) +{ + struct m9206_state *m = adap->dev->priv; - unlock: - mutex_unlock(&adap->dev->i2c_mutex); + m->filters[index] = onoff ? pid : 0; - return ret; + return m9206_update_filters(adap); } static int m9206_firmware_download(struct usb_device *udev, const struct firmware *fw) @@ -359,11 +396,11 @@ static int m9206_firmware_download(struct usb_device *udev, const struct firmwar buff = kmalloc(65536, GFP_KERNEL); - if ((ret = m9206_read(udev, 0x25, 0x0, 0x8000, read, 4)) != 0) + if ((ret = m9206_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) goto done; deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]); - if ((ret = m9206_read(udev, 0x30, 0x0, 0x0, read, 1)) != 0) + if ((ret = m9206_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0) goto done; deb_rc("%x\n", read[0]); @@ -383,7 +420,8 @@ static int m9206_firmware_download(struct usb_device *udev, const struct firmwar memcpy(buff, fw->data + i, size); ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), - 0x30, USB_TYPE_VENDOR | USB_DIR_OUT, + M9206_FW, + USB_TYPE_VENDOR | USB_DIR_OUT, value, index, buff, size, 20); if (ret != size) { deb_rc("error while uploading fw!\n"); @@ -403,7 +441,7 @@ static int m9206_firmware_download(struct usb_device *udev, const struct firmwar msleep(36); /* m9206 will disconnect itself from the bus after this. */ - (void) m9206_write(udev, 0x22, 0x01, 0xff69); + (void) m9206_write(udev, M9206_CORE, 0x01, M9206_FW_GO); deb_rc("firmware uploaded!\n"); done: @@ -417,24 +455,23 @@ static struct dvb_usb_device_properties megasky_properties = { .firmware = "dvb-usb-megasky-02.fw", .download_firmware = m9206_firmware_download, - .rc_interval = 200, + .rc_interval = 100, .rc_key_map = megasky_rc_keys, .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys), .rc_query = m9206_rc_query, - .size_of_priv = 0, + .size_of_priv = sizeof(struct m9206_state), .identify_state = megasky_identify_state, .num_adapters = 1, .adapter = {{ - .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_ADAP_HAS_PID_FILTER | - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | - DVB_USB_ADAP_NEED_PID_FILTERING, + .caps = DVB_USB_IS_AN_I2C_ADAPTER, .pid_filter_count = 8, .pid_filter = m9206_pid_filter, .pid_filter_ctrl = m9206_pid_filter_ctrl, .frontend_attach = megasky_frontend_attach, + .tuner_attach = megasky_tuner_attach, .stream = { .type = USB_BULK, diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.h b/linux/drivers/media/dvb/dvb-usb/m920x.h index fdb967aa3..709b7d205 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.h +++ b/linux/drivers/media/dvb/dvb-usb/m920x.h @@ -7,4 +7,22 @@ extern int dvb_usb_m920x_debug; #define deb_rc(args...) dprintk(dvb_usb_m920x_debug,0x01,args) +#define M9206_CORE 0x22 +#define M9206_RC_STATE 0xff51 +#define M9206_RC_KEY 0xff52 +#define M9206_RC_INIT1 0xff54 +#define M9206_RC_INIT2 0xff55 +#define M9206_FW_GO 0xff69 + +#define M9206_I2C 0x23 +#define M9206_FILTER 0x25 +#define M9206_FW 0x30 + +#define M9206_MAX_FILTERS 8 +struct m9206_state { + u16 filters[M9206_MAX_FILTERS]; + int filtering_enabled; + int rep_count; +}; + #endif diff --git a/linux/drivers/media/dvb/frontends/qt1010.h b/linux/drivers/media/dvb/frontends/qt1010.h index e526e3c23..3a566085f 100644 --- a/linux/drivers/media/dvb/frontends/qt1010.h +++ b/linux/drivers/media/dvb/frontends/qt1010.h @@ -25,7 +25,7 @@ #define QT1010_MIN_STEP 2000000 #define QT1010_MIN_FREQ 48000000 -static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) +static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { int i; int div, mod; @@ -85,9 +85,6 @@ static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame if (freq % QT1010_MIN_STEP) printk("frequency not supported.\n"); - (void) buf; - (void) buf_len; - div = (freq - QT1010_MIN_FREQ) / QT1010_MIN_STEP; mod = (div + 16 - 9) % 16; @@ -206,7 +203,7 @@ static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame msg.flags = 0; msg.len = 2; - msg.addr = 0xc4; + msg.addr = d->adapter[0].pll_addr; msg.buf = &rd[i].reg; if (i2c_transfer(&d->i2c_adap, &msg, 1) != 1) { -- cgit v1.2.3 From 6640030077783c0cfa63707b7834cadbc2a752ec Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 28 Sep 2006 00:46:49 -0400 Subject: m920x: more cleanups From: Michael Krufky Some cleanups and suggestions from Patrick Boettcher. Dropped the mutex in m9206_rc_query using #if 0, because M9206_CORE, M9206_I2C, M9206_FILTER and M9206_FW can be accessed concurrently. Thanks to both Aapo Tahkola and Patrick Boettcher. Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 105 +++++++++++++++----------------- linux/drivers/media/dvb/dvb-usb/m920x.h | 12 ++-- 2 files changed, 55 insertions(+), 62 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 3c7f639e6..a7d42934d 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -16,7 +16,7 @@ #include "qt1010.h" /* debug */ -int dvb_usb_m920x_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); @@ -85,8 +85,10 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) int i, ret = 0; u8 rc_state[2]; +#if 0 if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; +#endif if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) goto unlock; @@ -128,7 +130,9 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) *state = REMOTE_NO_KEY_PRESSED; unlock: +#if 0 mutex_unlock(&d->i2c_mutex); +#endif return ret; } @@ -240,8 +244,6 @@ static int megasky_mt352_demod_init(struct dvb_frontend *fe) return 0; } -struct mt352_state; - static struct mt352_config megasky_mt352_config = { .demod_address = 0x1e, .no_tuner = 1, @@ -267,52 +269,7 @@ static int megasky_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -/* DVB USB Driver stuff */ -static struct dvb_usb_device_properties megasky_properties; - -static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct dvb_usb_device *d; - struct usb_host_interface *alt; - struct dvb_usb_device_properties props; - int ret; - - memcpy(&props, &megasky_properties, sizeof(struct dvb_usb_device_properties)); - - /* Hardware pid filtering isn't quite perfect so dont use unless have to. */ - if (udev->speed == USB_SPEED_FULL) - props.caps |= DVB_USB_ADAP_HAS_PID_FILTER | - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF; - - if ((ret = dvb_usb_device_init(intf, &props, THIS_MODULE, &d)) == 0) { - deb_rc("probed!\n"); - - alt = usb_altnum_to_altsetting(intf, 1); - if (alt == NULL) { - deb_rc("not alt found!\n"); - return -ENODEV; - } - - ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); - if (ret < 0) - return ret; - - deb_rc("Changed to alternate setting!\n"); - - if ((ret = m9206_rc_init(d->udev)) != 0) - return ret; - } - return ret; -} - -static struct usb_device_id m920x_table [] = { - { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE (usb, m920x_table); - -static int set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid) +static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid) { int ret = 0; @@ -341,14 +298,14 @@ static int m9206_update_filters(struct dvb_usb_adapter *adap) enabled = 0; /* Disable all filters */ - if ((ret = set_filter(adap, 0x81, 1, enabled)) != 0) + if ((ret = m9206_set_filter(adap, 0x81, 1, enabled)) != 0) return ret; for (i = 0; i < M9206_MAX_FILTERS; i++) - if ((ret = set_filter(adap, 0x81, i + 2, 0)) != 0) + if ((ret = m9206_set_filter(adap, 0x81, i + 2, 0)) != 0) return ret; - if ((ret = set_filter(adap, 0x82, 0, 0x0)) != 0) + if ((ret = m9206_set_filter(adap, 0x82, 0, 0x0)) != 0) return ret; /* Set */ @@ -357,14 +314,14 @@ static int m9206_update_filters(struct dvb_usb_adapter *adap) if (m->filters[i] == 0) continue; - if ((ret = set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0) + if ((ret = m9206_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0) return ret; filter++; } } - if ((ret = set_filter(adap, 0x82, 0, 0x02f5)) != 0) + if ((ret = m9206_set_filter(adap, 0x82, 0, 0x02f5)) != 0) return ret; return ret; @@ -450,6 +407,42 @@ static int m9206_firmware_download(struct usb_device *udev, const struct firmwar return ret; } +/* DVB USB Driver stuff */ +static struct dvb_usb_device_properties megasky_properties; + +static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct dvb_usb_device *d; + struct usb_host_interface *alt; + int ret; + + if ((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) { + deb_rc("probed!\n"); + + alt = usb_altnum_to_altsetting(intf, 1); + if (alt == NULL) { + deb_rc("not alt found!\n"); + return -ENODEV; + } + + ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); + if (ret < 0) + return ret; + + deb_rc("Changed to alternate setting!\n"); + + if ((ret = m9206_rc_init(d->udev)) != 0) + return ret; + } + return ret; +} + +static struct usb_device_id m920x_table [] = { + { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE (usb, m920x_table); + static struct dvb_usb_device_properties megasky_properties = { .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-megasky-02.fw", @@ -465,7 +458,9 @@ static struct dvb_usb_device_properties megasky_properties = { .identify_state = megasky_identify_state, .num_adapters = 1, .adapter = {{ - .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 8, .pid_filter = m9206_pid_filter, .pid_filter_ctrl = m9206_pid_filter_ctrl, diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.h b/linux/drivers/media/dvb/dvb-usb/m920x.h index 709b7d205..597df11e6 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.h +++ b/linux/drivers/media/dvb/dvb-usb/m920x.h @@ -4,15 +4,14 @@ #define DVB_USB_LOG_PREFIX "m920x" #include "dvb-usb.h" -extern int dvb_usb_m920x_debug; #define deb_rc(args...) dprintk(dvb_usb_m920x_debug,0x01,args) #define M9206_CORE 0x22 -#define M9206_RC_STATE 0xff51 -#define M9206_RC_KEY 0xff52 -#define M9206_RC_INIT1 0xff54 -#define M9206_RC_INIT2 0xff55 -#define M9206_FW_GO 0xff69 +#define M9206_RC_STATE 0xff51 +#define M9206_RC_KEY 0xff52 +#define M9206_RC_INIT1 0xff54 +#define M9206_RC_INIT2 0xff55 +#define M9206_FW_GO 0xff69 #define M9206_I2C 0x23 #define M9206_FILTER 0x25 @@ -24,5 +23,4 @@ struct m9206_state { int filtering_enabled; int rep_count; }; - #endif -- cgit v1.2.3 From c40096038d501a3afa1722d4290477ae37557964 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 28 Sep 2006 12:48:03 -0400 Subject: m920x: more trivial cleanups From: Patrick Boettcher - Removed some needless brances - Removed an unneeded check for adapter[0] - Removed unneeded declaration of .generic_bulk_ctrl_endpoint = 0x01 Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index a7d42934d..6fc71843b 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -145,12 +145,6 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int nu int i; int ret = 0; - /* Need to access d->adapter[0] */ - if (d->num_adapters_initialized != 1) { - deb_rc("Impossible happened!\n"); - return -EINVAL; - } - if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; @@ -254,9 +248,8 @@ static int megasky_frontend_attach(struct dvb_usb_adapter *adap) { deb_rc("megasky_frontend_attach!\n"); - if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) != NULL) { + if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) != NULL) return 0; - } return -EIO; } @@ -481,8 +474,6 @@ static struct dvb_usb_device_properties megasky_properties = { }}, .i2c_algo = &m9206_i2c_algo, - .generic_bulk_ctrl_endpoint = 0x01, - .num_device_descs = 1, .devices = { { "MSI Mega Sky 580 DVB-T USB2.0", -- cgit v1.2.3 From 1dbb128dceee78e8bcaada93e52d992c104737d0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 28 Sep 2006 13:47:21 -0400 Subject: m920x: move qt1010_tuner_attach function into qt1010.h From: Michael Krufky The megasky_tuner_attach function is not specific to this device. This patch renames it to qt1010_tuner_attach and moves it into the qt1010 header file. Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 11 +---------- linux/drivers/media/dvb/frontends/qt1010.h | 8 ++++++++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 6fc71843b..c10944a4f 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -253,15 +253,6 @@ static int megasky_frontend_attach(struct dvb_usb_adapter *adap) return -EIO; } -static int megasky_tuner_attach(struct dvb_usb_adapter *adap) -{ - adap->pll_addr = 0xc4; - adap->pll_desc = NULL; - adap->fe->ops.tuner_ops.set_params = qt1010_set_params; - - return 0; -} - static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid) { int ret = 0; @@ -459,7 +450,7 @@ static struct dvb_usb_device_properties megasky_properties = { .pid_filter_ctrl = m9206_pid_filter_ctrl, .frontend_attach = megasky_frontend_attach, - .tuner_attach = megasky_tuner_attach, + .tuner_attach = qt1010_tuner_attach, .stream = { .type = USB_BULK, diff --git a/linux/drivers/media/dvb/frontends/qt1010.h b/linux/drivers/media/dvb/frontends/qt1010.h index 3a566085f..59ee1cd03 100644 --- a/linux/drivers/media/dvb/frontends/qt1010.h +++ b/linux/drivers/media/dvb/frontends/qt1010.h @@ -215,4 +215,12 @@ static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame return 0; } +static int qt1010_tuner_attach(struct dvb_usb_adapter *adap) +{ + adap->pll_addr = 0xc4; + adap->pll_desc = NULL; + adap->fe->ops.tuner_ops.set_params = qt1010_set_params; + + return 0; +} #endif -- cgit v1.2.3 From 39f8c8cf4eedd31a816f6cc20e8f3f4f13199758 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 3 Oct 2006 15:46:33 -0400 Subject: m920x: fix build in hg tree / other trivial fixes From: Michael Krufky - removed extra newline - removed NULL entry - fixed versions.txt Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 2 -- v4l/versions.txt | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index c10944a4f..e44b52414 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -138,7 +138,6 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) } /* I2C */ - static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); @@ -471,7 +470,6 @@ static struct dvb_usb_device_properties megasky_properties = { { &m920x_table[0], NULL }, { NULL }, }, - { NULL }, } }; diff --git a/v4l/versions.txt b/v4l/versions.txt index 2d7ad4ee4..85bc48eef 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -111,7 +111,7 @@ DVB_USB_DIBUSB_MB_FAULTY DVB_USB_DIBUSB_MC DVB_USB_UMT_010 DVB_USB_CXUSB -DVB_USB_MEGASKY +DVB_USB_M920X DVB_USB_DIGITV DVB_USB_VP7045 DVB_USB_VP702X -- cgit v1.2.3 From 47b47d371e02c3585268e06325bf27bc3ec27dcc Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 7 Oct 2006 00:06:54 -0400 Subject: qt1010: correct hardlockup when an app access the DVB dongle From: Jan Nijs This patch changes qt1010.h to use dvb_usb_device struct instead of a dvb_usb_adapter for accessing the private area of the driver. Without this patch my PC hard locks when an application tries to access the DVB tuner. Signed-off-by: Jan Nijs Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/qt1010.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/qt1010.h b/linux/drivers/media/dvb/frontends/qt1010.h index 59ee1cd03..8196985e4 100644 --- a/linux/drivers/media/dvb/frontends/qt1010.h +++ b/linux/drivers/media/dvb/frontends/qt1010.h @@ -79,7 +79,7 @@ static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame { QT1010_W, 0x01, 0x00 }, }; struct i2c_msg msg; - struct dvb_usb_device *d = fe->dvb->priv; + struct dvb_usb_adapter *adap = fe->dvb->priv; unsigned long freq = params->frequency; if (freq % QT1010_MIN_STEP) @@ -203,10 +203,10 @@ static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame msg.flags = 0; msg.len = 2; - msg.addr = d->adapter[0].pll_addr; + msg.addr = adap->dev->adapter[0].pll_addr; msg.buf = &rd[i].reg; - if (i2c_transfer(&d->i2c_adap, &msg, 1) != 1) { + if (i2c_transfer(&adap->dev->i2c_adap, &msg, 1) != 1) { printk("tuner write failed\n"); return -EIO; } -- cgit v1.2.3 From 2198c7842c8114359ee495795d1fc624d8514321 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 7 Oct 2006 14:03:04 -0400 Subject: m920x: correct oops when loading module From: Michael Krufky move .caps from the adapter properties to the device properties. Thanks to Martin Schwier for confirming this fix. Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index e44b52414..911570387 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -427,6 +427,9 @@ static struct usb_device_id m920x_table [] = { MODULE_DEVICE_TABLE (usb, m920x_table); static struct dvb_usb_device_properties megasky_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-megasky-02.fw", .download_firmware = m9206_firmware_download, @@ -441,9 +444,6 @@ static struct dvb_usb_device_properties megasky_properties = { .identify_state = megasky_identify_state, .num_adapters = 1, .adapter = {{ - .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_ADAP_HAS_PID_FILTER | - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, - .pid_filter_count = 8, .pid_filter = m9206_pid_filter, .pid_filter_ctrl = m9206_pid_filter_ctrl, -- cgit v1.2.3 From a5cce0416f7fd557fa427893ee9cef207c33813a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Jan 2007 03:58:19 -0500 Subject: cx88: Add support for svideo/composite input of the Terratec Cinergy 1400 DVB-T From: Heiko Baums Adds support for the combined S-Video/Composite input of the Terratec Cinergy 1400 DVB-T. Signed-off-by: Heiko Baums Signed-off-by: Michael Krufky --- linux/drivers/media/video/cx88/cx88-cards.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 9a5aa0803..3a7131342 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -765,6 +765,12 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_DVB, .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 2, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, }}, .mpeg = CX88_MPEG_DVB, }, -- cgit v1.2.3 From 8eeef355ce44f48579df26ffb53f713e45f9169a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Jan 2007 13:56:10 -0500 Subject: dvb: add new qt1010 tuner module From: Antti Palosaari QT1010: - old qt1010-code totally rewritten and put in own kernel module - same enhancements as my earlier QT1010 125kHz patch - tuner initialization - register 1f calculation - register 20 calculation - register 25 calculation m920x: (MSI Megasky) - use new QT1010 module instead of old code Signed-off-by: Antti Palosaari Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 13 +- linux/drivers/media/dvb/frontends/Kconfig | 7 + linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/qt1010.c | 455 ++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/qt1010.h | 233 ++---------- linux/drivers/media/dvb/frontends/qt1010_priv.h | 105 ++++++ 6 files changed, 610 insertions(+), 204 deletions(-) create mode 100644 linux/drivers/media/dvb/frontends/qt1010.c create mode 100644 linux/drivers/media/dvb/frontends/qt1010_priv.h diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 911570387..108450ef0 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -390,6 +390,17 @@ static int m9206_firmware_download(struct usb_device *udev, const struct firmwar return ret; } +static struct qt1010_config megasky_qt1010_config = { + .i2c_address = 0xc4 +}; + +static int megasky_tuner_attach(struct dvb_usb_adapter *adap) +{ + return dvb_attach(qt1010_attach, + adap->fe, &adap->dev->i2c_adap, + &megasky_qt1010_config) == NULL ? -ENODEV : 0; +} + /* DVB USB Driver stuff */ static struct dvb_usb_device_properties megasky_properties; @@ -449,7 +460,7 @@ static struct dvb_usb_device_properties megasky_properties = { .pid_filter_ctrl = m9206_pid_filter_ctrl, .frontend_attach = megasky_frontend_attach, - .tuner_attach = qt1010_tuner_attach, + .tuner_attach = megasky_tuner_attach, .stream = { .type = USB_BULK, diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index af314bb1d..22c2cf2ce 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -290,6 +290,13 @@ config DVB_TDA826X help A DVB-S silicon tuner module. Say Y when you want to support this tuner. +config DVB_TUNER_QT1010 + tristate "Quantek QT1010 silicon tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A driver for the silicon tuner QT1010 from Quantek. + config DVB_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" depends on I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 3fa6e5d32..a646d9969 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -38,5 +38,6 @@ obj-$(CONFIG_DVB_ISL6421) += isl6421.o obj-$(CONFIG_DVB_TDA10086) += tda10086.o obj-$(CONFIG_DVB_TDA826X) += tda826x.o obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o +obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o obj-$(CONFIG_DVB_TUA6100) += tua6100.o obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o diff --git a/linux/drivers/media/dvb/frontends/qt1010.c b/linux/drivers/media/dvb/frontends/qt1010.c new file mode 100644 index 000000000..60931f83f --- /dev/null +++ b/linux/drivers/media/dvb/frontends/qt1010.c @@ -0,0 +1,455 @@ +/* + * Driver for Quantek QT1010 silicon tuner + * + * Copyright (C) 2006 Antti Palosaari + * Aapo Tahkola + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "qt1010.h" +#include "qt1010_priv.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); + +#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "QT1010: " args); printk("\n"); }} while (0) + +/* read single register */ +static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val) +{ + struct i2c_msg msg[2] = { + { .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, + { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 }, + }; + + if (i2c_transfer(priv->i2c, msg, 2) != 2) { + printk(KERN_WARNING "qt1010 I2C read failed\n"); + return -EREMOTEIO; + } + return 0; +} + +/* write single register */ +static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val) +{ + u8 buf[2] = { reg, val }; + struct i2c_msg msg = { + .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2 + }; + + if (i2c_transfer(priv->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "qt1010 I2C write failed\n"); + return -EREMOTEIO; + } + return 0; +} + +/* dump all registers */ +static void qt1010_dump_regs(struct qt1010_priv *priv) +{ + char buf[52], buf2[4]; + u8 reg, val; + + for (reg = 0; ; reg++) { + if (reg % 16 == 0) { + if (reg) + printk("%s\n", buf); + sprintf(buf, "%02x: ", reg); + } + if (qt1010_readreg(priv, reg, &val) == 0) + sprintf(buf2, "%02x ", val); + else + strcpy(buf2, "-- "); + strcat(buf, buf2); + if (reg == 0x2f) + break; + } + printk("%s\n", buf); +} + +static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct qt1010_priv *priv; + int err; + u32 freq, div, mod1, mod2; + u8 i, tmpval, reg05; + qt1010_i2c_oper_t rd[48] = { + { QT1010_WR, 0x01, 0x80 }, + { QT1010_WR, 0x02, 0x3f }, + { QT1010_WR, 0x05, 0xff }, /* 02 c write */ + { QT1010_WR, 0x06, 0x44 }, + { QT1010_WR, 0x07, 0xff }, /* 04 c write */ + { QT1010_WR, 0x08, 0x08 }, + { QT1010_WR, 0x09, 0xff }, /* 06 c write */ + { QT1010_WR, 0x0a, 0xff }, /* 07 c write */ + { QT1010_WR, 0x0b, 0xff }, /* 08 c write */ + { QT1010_WR, 0x0c, 0xe1 }, + { QT1010_WR, 0x1a, 0xff }, /* 10 c write */ + { QT1010_WR, 0x1b, 0x00 }, + { QT1010_WR, 0x1c, 0x89 }, + { QT1010_WR, 0x11, 0xff }, /* 13 c write */ + { QT1010_WR, 0x12, 0xff }, /* 14 c write */ + { QT1010_WR, 0x22, 0xff }, /* 15 c write */ + { QT1010_WR, 0x1e, 0x00 }, + { QT1010_WR, 0x1e, 0xd0 }, + { QT1010_RD, 0x22, 0xff }, /* 16 c read */ + { QT1010_WR, 0x1e, 0x00 }, + { QT1010_RD, 0x05, 0xff }, /* 20 c read */ + { QT1010_RD, 0x22, 0xff }, /* 21 c read */ + { QT1010_WR, 0x23, 0xd0 }, + { QT1010_WR, 0x1e, 0x00 }, + { QT1010_WR, 0x1e, 0xe0 }, + { QT1010_RD, 0x23, 0xff }, /* 25 c read */ + { QT1010_RD, 0x23, 0xff }, /* 26 c read */ + { QT1010_WR, 0x1e, 0x00 }, + { QT1010_WR, 0x24, 0xd0 }, + { QT1010_WR, 0x1e, 0x00 }, + { QT1010_WR, 0x1e, 0xf0 }, + { QT1010_RD, 0x24, 0xff }, /* 31 c read */ + { QT1010_WR, 0x1e, 0x00 }, + { QT1010_WR, 0x14, 0x7f }, + { QT1010_WR, 0x15, 0x7f }, + { QT1010_WR, 0x05, 0xff }, /* 35 c write */ + { QT1010_WR, 0x06, 0x00 }, + { QT1010_WR, 0x15, 0x1f }, + { QT1010_WR, 0x16, 0xff }, + { QT1010_WR, 0x18, 0xff }, + { QT1010_WR, 0x1f, 0xff }, /* 40 c write */ + { QT1010_WR, 0x20, 0xff }, /* 41 c write */ + { QT1010_WR, 0x21, 0x53 }, + { QT1010_WR, 0x25, 0xff }, /* 43 c write */ + { QT1010_WR, 0x26, 0x15 }, + { QT1010_WR, 0x00, 0xff }, /* 45 c write */ + { QT1010_WR, 0x02, 0x00 }, + { QT1010_WR, 0x01, 0x00 } + }; + +#define FREQ1 32000000 /* 32 MHz */ +#define FREQ2 4000000 /* 4 MHz Quartz oscillator in the stick? */ + + priv = fe->tuner_priv; + freq = params->frequency; + div = (freq + QT1010_OFFSET) / QT1010_STEP; + freq = (div * QT1010_STEP) - QT1010_OFFSET; + mod1 = (freq + QT1010_OFFSET) % FREQ1; + mod2 = (freq + QT1010_OFFSET) % FREQ2; + priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; + priv->frequency = freq; + + /* reg 05 base value */ + if (freq < 290000000) reg05 = 0x14; /* 290 MHz */ + else if (freq < 610000000) reg05 = 0x34; /* 610 MHz */ + else if (freq < 802000000) reg05 = 0x54; /* 802 MHz */ + else reg05 = 0x74; + + /* 0x5 */ + rd[2].val = reg05; + + /* 07 - set frequency: 32 MHz scale */ + rd[4].val = (freq + QT1010_OFFSET) / FREQ1; + + /* 09 - changes every 8/24 MHz */ + if (mod1 < 8000000) rd[6].val = 0x1d; + else rd[6].val = 0x1c; + + /* 0a - set frequency: 4 MHz scale (max 28 MHz) */ + if (mod1 < 1*FREQ2) rd[7].val = 0x09; /* +0 MHz */ + else if (mod1 < 2*FREQ2) rd[7].val = 0x08; /* +4 MHz */ + else if (mod1 < 3*FREQ2) rd[7].val = 0x0f; /* +8 MHz */ + else if (mod1 < 4*FREQ2) rd[7].val = 0x0e; /* +12 MHz */ + else if (mod1 < 5*FREQ2) rd[7].val = 0x0d; /* +16 MHz */ + else if (mod1 < 6*FREQ2) rd[7].val = 0x0c; /* +20 MHz */ + else if (mod1 < 7*FREQ2) rd[7].val = 0x0b; /* +24 MHz */ + else rd[7].val = 0x0a; /* +28 MHz */ + + /* 0b - changes every 2/2 MHz */ + if (mod2 < 2000000) rd[8].val = 0x45; + else rd[8].val = 0x44; + + /* 1a - set frequency: 125 kHz scale (max 3875 kHz)*/ + tmpval = 0x78; /* byte, overflows intentionally */ + rd[10].val = tmpval-((mod2/QT1010_STEP)*0x08); + + /* 11 */ + rd[13].val = 0xfd; /* TODO: correct value calculation */ + + /* 12 */ + rd[14].val = 0x91; /* TODO: correct value calculation */ + + /* 22 */ + if (freq < 450000000) rd[15].val = 0xd0; /* 450 MHz */ + else if (freq < 482000000) rd[15].val = 0xd1; /* 482 MHz */ + else if (freq < 514000000) rd[15].val = 0xd4; /* 514 MHz */ + else if (freq < 546000000) rd[15].val = 0xd7; /* 546 MHz */ + else if (freq < 610000000) rd[15].val = 0xda; /* 610 MHz */ + else rd[15].val = 0xd0; + + /* 05 */ + rd[35].val = (reg05 & 0xf0); + + /* 1f */ + if (mod1 < 8000000) tmpval = 0x00; + else if (mod1 < 12000000) tmpval = 0x01; + else if (mod1 < 16000000) tmpval = 0x02; + else if (mod1 < 24000000) tmpval = 0x03; + else if (mod1 < 28000000) tmpval = 0x04; + else tmpval = 0x05; + rd[40].val = (priv->reg1f_init_val + 0x0e + tmpval); + + /* 20 */ + if (mod1 < 8000000) tmpval = 0x00; + else if (mod1 < 12000000) tmpval = 0x01; + else if (mod1 < 20000000) tmpval = 0x02; + else if (mod1 < 24000000) tmpval = 0x03; + else if (mod1 < 28000000) tmpval = 0x04; + else tmpval = 0x05; + rd[41].val = (priv->reg20_init_val + 0x0d + tmpval); + + /* 25 */ + rd[43].val = priv->reg25_init_val; + + /* 00 */ + rd[45].val = 0x92; /* TODO: correct value calculation */ + + dprintk("freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x 1a:%02x 11:%02x " \ + "12:%02x 22:%02x 05:%02x 1f:%02x 20:%02x 25:%02x 00:%02x", \ + freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, rd[8].val, \ + rd[10].val, rd[13].val, rd[14].val, rd[15].val, rd[35].val, \ + rd[40].val, rd[41].val, rd[43].val, rd[45].val); + + for (i = 0; i < sizeof(rd) / sizeof(*rd); i++) { + if (rd[i].oper == QT1010_WR) { + err = qt1010_writereg(priv, rd[i].reg, rd[i].val); + } else { /* read is required to proper locking */ + err = qt1010_readreg(priv, rd[i].reg, &tmpval); + } + if (err) return err; + } + + if (debug) + qt1010_dump_regs(priv); + + return 0; +} + +static int qt1010_init_meas1(struct qt1010_priv *priv, u8 oper, u8 reg, u8 reg_init_val, u8 *retval) +{ + u8 i, val1, val2; + int err; + + qt1010_i2c_oper_t i2c_data[] = { + { QT1010_WR, reg, reg_init_val }, + { QT1010_WR, 0x1e, 0x00 }, + { QT1010_WR, 0x1e, oper }, + { QT1010_RD, reg, 0xff } + }; + + for (i = 0; i < sizeof(i2c_data) / sizeof(*i2c_data); i++) { + if (i2c_data[i].oper == QT1010_WR) { + err = qt1010_writereg(priv, i2c_data[i].reg, i2c_data[i].val); + } else { + err = qt1010_readreg(priv, i2c_data[i].reg, &val2); + } + if (err) return err; + } + + do { + val1 = val2; + err = qt1010_readreg(priv, reg, &val2); + if (err) return err; + dprintk("compare reg:%02x %02x %02x", reg, val1, val2); + } while (val1 != val2); + *retval = val1; + + return qt1010_writereg(priv, 0x1e, 0x00); +} + + +static u8 qt1010_init_meas2(struct qt1010_priv *priv, u8 reg_init_val, u8 *retval) +{ + u8 i, val; + int err; + qt1010_i2c_oper_t i2c_data[] = { + { QT1010_WR, 0x07, reg_init_val }, + { QT1010_WR, 0x22, 0xd0 }, + { QT1010_WR, 0x1e, 0x00 }, + { QT1010_WR, 0x1e, 0xd0 }, + { QT1010_RD, 0x22, 0xff }, + { QT1010_WR, 0x1e, 0x00 }, + { QT1010_WR, 0x22, 0xff } + }; + for (i = 0; i < sizeof(i2c_data) / sizeof(*i2c_data); i++) { + if (i2c_data[i].oper == QT1010_WR) { + err = qt1010_writereg(priv, i2c_data[i].reg, i2c_data[i].val); + } else { + err = qt1010_readreg(priv, i2c_data[i].reg, &val); + } + if (err) return err; + } + *retval = val; + return 0; +} + +static int qt1010_init(struct dvb_frontend *fe) +{ + struct qt1010_priv *priv = fe->tuner_priv; + struct dvb_frontend_parameters params; + int err; + u8 i, tmpval, *valptr = NULL; + + qt1010_i2c_oper_t i2c_data[] = { + { QT1010_WR, 0x01, 0x80 }, + { QT1010_WR, 0x0d, 0x84 }, + { QT1010_WR, 0x0e, 0xb7 }, + { QT1010_WR, 0x2a, 0x23 }, + { QT1010_WR, 0x2c, 0xdc }, + { QT1010_M1, 0x25, 0x40 }, /* get reg 25 init value */ + { QT1010_M1, 0x81, 0xff }, /* get reg 25 init value */ + { QT1010_WR, 0x2b, 0x70 }, + { QT1010_WR, 0x2a, 0x23 }, + { QT1010_M1, 0x26, 0x08 }, + { QT1010_M1, 0x82, 0xff }, + { QT1010_WR, 0x05, 0x14 }, + { QT1010_WR, 0x06, 0x44 }, + { QT1010_WR, 0x07, 0x28 }, + { QT1010_WR, 0x08, 0x0b }, + { QT1010_WR, 0x11, 0xfd }, + { QT1010_M1, 0x22, 0x0d }, + { QT1010_M1, 0xd0, 0xff }, + { QT1010_WR, 0x06, 0x40 }, + { QT1010_WR, 0x16, 0xf0 }, + { QT1010_WR, 0x02, 0x38 }, + { QT1010_WR, 0x03, 0x18 }, + { QT1010_WR, 0x20, 0xe0 }, + { QT1010_M1, 0x1f, 0x20 }, /* get reg 1f init value */ + { QT1010_M1, 0x84, 0xff }, /* get reg 1f init value */ + { QT1010_RD, 0x20, 0x20 }, /* get reg 20 init value */ + { QT1010_WR, 0x03, 0x19 }, + { QT1010_WR, 0x02, 0x3f }, + { QT1010_WR, 0x21, 0x53 }, + { QT1010_RD, 0x21, 0xff }, + { QT1010_WR, 0x11, 0xfd }, + { QT1010_WR, 0x05, 0x34 }, + { QT1010_WR, 0x06, 0x44 }, + { QT1010_WR, 0x08, 0x08 } + }; + + for (i = 0; i < sizeof(i2c_data) / sizeof(*i2c_data); i++) { + switch (i2c_data[i].oper) { + case QT1010_WR: + err = qt1010_writereg(priv, i2c_data[i].reg, i2c_data[i].val); + break; + case QT1010_RD: + if (i2c_data[i].val == 0x20) valptr = &priv->reg20_init_val; + else valptr = &tmpval; + err = qt1010_readreg(priv, i2c_data[i].reg, valptr); + break; + case QT1010_M1: + if (i2c_data[i].val == 0x25) valptr = &priv->reg25_init_val; + else if (i2c_data[i].val == 0x1f) valptr = &priv->reg1f_init_val; + else valptr = &tmpval; + err = qt1010_init_meas1(priv, i2c_data[i+1].reg, i2c_data[i].reg, + i2c_data[i].val, valptr); + i++; + break; + } + if (err) return err; + } + + for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */ + if ((err = qt1010_init_meas2(priv, i, &tmpval))) + return err; + + params.frequency = 545000000; /* Sigmatek DVB-110 545000000 */ + /* MSI Megasky 580 GL861 533000000 */ + return qt1010_set_params(fe, ¶ms); +} + +static int qt1010_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct qt1010_priv *priv = fe->tuner_priv; + *frequency = priv->frequency; + return 0; +} + +static int qt1010_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct qt1010_priv *priv = fe->tuner_priv; + *bandwidth = priv->bandwidth; + return 0; +} + +static const struct dvb_tuner_ops qt1010_tuner_ops = { + .info = { + .name = "Quantek QT1010", + .frequency_min = QT1010_MIN_FREQ, + .frequency_max = QT1010_MAX_FREQ, + .frequency_step = QT1010_STEP, + }, + + .release = qt1010_release, + .init = qt1010_init, + /* TODO: implement sleep */ + + .set_params = qt1010_set_params, + .get_frequency = qt1010_get_frequency, + .get_bandwidth = qt1010_get_bandwidth +}; + +struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct qt1010_config *cfg) +{ + struct qt1010_priv *priv = NULL; + u8 id; + + priv = kzalloc(sizeof(struct qt1010_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->cfg = cfg; + priv->i2c = i2c; + +#if 0 + qt1010_dump_regs(priv); +#endif + + /* Try to detect tuner chip. Probably this is not correct register. */ + if (qt1010_readreg(priv, 0x29, &id) != 0 || (id != 0x39)) { + kfree(priv); + return NULL; + } + + printk(KERN_INFO "Quantek QT1010 successfully identified.\n"); + memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops, sizeof(struct dvb_tuner_ops)); + + fe->tuner_priv = priv; + return fe; +} +EXPORT_SYMBOL(qt1010_attach); + +MODULE_DESCRIPTION("Quantek QT1010 silicon tuner driver"); +MODULE_AUTHOR("Antti Palosaari "); +MODULE_AUTHOR("Aapo Tahkola "); +MODULE_VERSION("0.1"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/qt1010.h b/linux/drivers/media/dvb/frontends/qt1010.h index 8196985e4..3ab4aa045 100644 --- a/linux/drivers/media/dvb/frontends/qt1010.h +++ b/linux/drivers/media/dvb/frontends/qt1010.h @@ -1,5 +1,8 @@ /* - * qt1010.h - DVB-T Tuner support + * Driver for Quantek QT1010 silicon tuner + * + * Copyright (C) 2006 Antti Palosaari + * Aapo Tahkola * * 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 @@ -16,211 +19,35 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _QT1010_H_ -#define _QT1010_H_ - -#define QT1010_W 0 -#define QT1010_R 1 -/* Not actual hw limits. */ -#define QT1010_MIN_STEP 2000000 -#define QT1010_MIN_FREQ 48000000 - -static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) -{ - int i; - int div, mod; - struct { - u8 read, reg, value; - } rd[46] = { { QT1010_W, 0x01, 0x80 }, - { QT1010_W, 0x02, 0x3f }, - { QT1010_W, 0x05, 0xff }, /* c */ - { QT1010_W, 0x06, 0x44 }, - { QT1010_W, 0x07, 0xff }, /* c */ - { QT1010_W, 0x08, 0x08 }, - { QT1010_W, 0x09, 0xff }, /* c */ - { QT1010_W, 0x0a, 0xff }, /* c */ - { QT1010_W, 0x0b, 0xff }, /* c */ - { QT1010_W, 0x0c, 0xe1 }, - { QT1010_W, 0x1a, 0xff }, /* 10 c */ - { QT1010_W, 0x1b, 0x00 }, - { QT1010_W, 0x1c, 0x89 }, - { QT1010_W, 0x11, 0xff }, /* c */ - { QT1010_W, 0x12, 0x91 }, - { QT1010_W, 0x22, 0xff }, /* c */ - { QT1010_W, 0x1e, 0x00 }, - { QT1010_W, 0x1e, 0xd0 }, - { QT1010_R, 0x22, 0xff }, /* c read */ - { QT1010_W, 0x1e, 0x00 }, - { QT1010_R, 0x05, 0xff }, /* 20 c read */ - { QT1010_R, 0x22, 0xff }, /* c read */ - { QT1010_W, 0x23, 0xd0 }, - { QT1010_W, 0x1e, 0x00 }, - { QT1010_W, 0x1e, 0xe0 }, - { QT1010_R, 0x23, 0xff }, /* c read */ - { QT1010_W, 0x1e, 0x00 }, - { QT1010_W, 0x24, 0xd0 }, - { QT1010_W, 0x1e, 0x00 }, - { QT1010_W, 0x1e, 0xf0 }, - { QT1010_R, 0x24, 0xff }, /* 30 c read */ - { QT1010_W, 0x1e, 0x00 }, - { QT1010_W, 0x14, 0x7f }, - { QT1010_W, 0x15, 0x7f }, - { QT1010_W, 0x05, 0xff }, /* c */ - { QT1010_W, 0x06, 0x00 }, - { QT1010_W, 0x15, 0x1f }, - { QT1010_W, 0x16, 0xff }, - { QT1010_W, 0x18, 0xff }, - { QT1010_W, 0x1f, 0xff }, /* c */ - { QT1010_W, 0x20, 0xff }, /* 40 c */ - { QT1010_W, 0x21, 0x53 }, - { QT1010_W, 0x25, 0xbd }, - { QT1010_W, 0x26, 0x15 }, - { QT1010_W, 0x02, 0x00 }, - { QT1010_W, 0x01, 0x00 }, - }; - struct i2c_msg msg; - struct dvb_usb_adapter *adap = fe->dvb->priv; - unsigned long freq = params->frequency; - - if (freq % QT1010_MIN_STEP) - printk("frequency not supported.\n"); - - div = (freq - QT1010_MIN_FREQ) / QT1010_MIN_STEP; - mod = (div + 16 - 9) % 16; - - /* 0x5 */ - if (div >= 377) - rd[2].value = 0x74; - else if (div >= 265) - rd[2].value = 0x54; - else if (div >= 121) - rd[2].value = 0x34; - else - rd[2].value = 0x14; - - /* 0x7 */ - rd[4].value = (((freq - QT1010_MIN_FREQ) / 1000000) * 9975 + 12960000) / 320000; - - /* 09 */ - if (mod < 4) - rd[6].value = 0x1d; - else - rd[6].value = 0x1c; - - /* 0a */ - if (mod < 2) - rd[7].value = 0x09; - else if (mod < 4) - rd[7].value = 0x08; - else if (mod < 6) - rd[7].value = 0x0f; - else if (mod < 8) - rd[7].value = 0x0e; - else if (mod < 10) - rd[7].value = 0x0d; - else if (mod < 12) - rd[7].value = 0x0c; - else if (mod < 14) - rd[7].value = 0x0b; - else - rd[7].value = 0x0a; - - /* 0b */ - if (div & 1) - rd[8].value = 0x45; - else - rd[8].value = 0x44; - - /* 1a */ - if (div & 1) - rd[10].value = 0x78; - else - rd[10].value = 0xf8; +#ifndef QT1010_H +#define QT1010_H - /* 11 */ - if (div >= 265) - rd[13].value = 0xf9; - else if (div >= 121) - rd[13].value = 0xfd; - else - rd[13].value = 0xf9; +#include "dvb_frontend.h" - /* 22 */ - if (div < 201) - rd[15].value = 0xd0; - else if (div < 217) - rd[15].value = 0xd3; - else if (div < 233) - rd[15].value = 0xd6; - else if (div < 249) - rd[15].value = 0xd9; - else if (div < 265) - rd[15].value = 0xda; - else - rd[15].value = 0xd0; +struct qt1010_config { + u8 i2c_address; +}; - /* 05 */ - if (div >= 377) - rd[34].value = 0x70; - else if (div >= 265) - rd[34].value = 0x50; - else if (div >= 121) - rd[34].value = 0x30; - else - rd[34].value = 0x10; - - /* 1f */ - if (mod < 4) - rd[39].value = 0x64; - else if (mod < 6) - rd[39].value = 0x66; - else if (mod < 8) - rd[39].value = 0x67; - else if (mod < 12) - rd[39].value = 0x68; - else if (mod < 14) - rd[39].value = 0x69; - else - rd[39].value = 0x6a; - - /* 20 */ - if (mod < 4) - rd[40].value = 0x10; - else if (mod < 6) - rd[40].value = 0x11; - else if (mod < 10) - rd[40].value = 0x12; - else if (mod < 12) - rd[40].value = 0x13; - else if (mod < 14) - rd[40].value = 0x14; - else - rd[40].value = 0x15; - - for (i = 0; i < sizeof(rd) / sizeof(*rd); i++) { - if (rd[i].read) - continue; - - msg.flags = 0; - msg.len = 2; - msg.addr = adap->dev->adapter[0].pll_addr; - msg.buf = &rd[i].reg; - - if (i2c_transfer(&adap->dev->i2c_adap, &msg, 1) != 1) { - printk("tuner write failed\n"); - return -EIO; - } - } - - return 0; -} - -static int qt1010_tuner_attach(struct dvb_usb_adapter *adap) +/** + * Attach a qt1010 tuner to the supplied frontend structure. + * + * @param fe frontend to attach to + * @param i2c i2c adapter to use + * @param cfg tuner hw based configuration + * @return fe pointer on success, NULL on failure + */ +#if defined(CONFIG_DVB_TUNER_QT1010) || (defined(CONFIG_DVB_TUNER_QT1010_MODULE) && defined(MODULE)) +extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct qt1010_config *cfg); +#else +static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct qt1010_config *cfg) { - adap->pll_addr = 0xc4; - adap->pll_desc = NULL; - adap->fe->ops.tuner_ops.set_params = qt1010_set_params; - - return 0; + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; } +#endif // CONFIG_DVB_TUNER_QT1010 + #endif diff --git a/linux/drivers/media/dvb/frontends/qt1010_priv.h b/linux/drivers/media/dvb/frontends/qt1010_priv.h new file mode 100644 index 000000000..090cf475f --- /dev/null +++ b/linux/drivers/media/dvb/frontends/qt1010_priv.h @@ -0,0 +1,105 @@ +/* + * Driver for Quantek QT1010 silicon tuner + * + * Copyright (C) 2006 Antti Palosaari + * Aapo Tahkola + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef QT1010_PRIV_H +#define QT1010_PRIV_H + +/* +reg def meaning +=== === ======= +00 00 ? +01 a0 ? operation start/stop; start=80, stop=00 +02 00 ? +03 19 ? +04 00 ? +05 00 ? maybe band selection +06 00 ? +07 2b set frequency: 32 MHz scale, n*32 MHz +08 0b ? +09 10 ? changes every 8/24 MHz; values 1d/1c +0a 08 set frequency: 4 MHz scale, n*4 MHz +0b 41 ? changes every 2/2 MHz; values 45/45 +0c e1 ? +0d 94 ? +0e b6 ? +0f 2c ? +10 10 ? +11 f1 ? maybe device specified adjustment +12 11 ? maybe device specified adjustment +13 3f ? +14 1f ? +15 3f ? +16 ff ? +17 ff ? +18 f7 ? +19 80 ? +1a d0 set frequency: 125 kHz scale, n*125 kHz +1b 00 ? +1c 89 ? +1d 00 ? +1e 00 ? looks like operation register; write cmd here, read result from 1f-26 +1f 20 ? chip initialization +20 e0 ? chip initialization +21 20 ? +22 d0 ? +23 d0 ? +24 d0 ? +25 40 ? chip initialization +26 08 ? +27 29 ? +28 55 ? +29 39 ? +2a 13 ? +2b 01 ? +2c ea ? +2d 00 ? +2e 00 ? not used? +2f 00 ? not used? +*/ + +#define QT1010_STEP 125000 /* 125 kHz used by Windows drivers, + hw could be more precise but we don't + know how to use */ +#define QT1010_MIN_FREQ 48000000 /* 48 MHz */ +#define QT1010_MAX_FREQ 860000000 /* 860 MHz */ +#define QT1010_OFFSET 1246000000 /* 1246 MHz */ + +#define QT1010_WR 0 +#define QT1010_RD 1 +#define QT1010_M1 3 + +typedef struct { + u8 oper, reg, val; +} qt1010_i2c_oper_t; + +struct qt1010_priv { + struct qt1010_config *cfg; + struct i2c_adapter *i2c; + + u8 reg1f_init_val; + u8 reg20_init_val; + u8 reg25_init_val; + + u32 frequency; + u32 bandwidth; +}; + +#endif -- cgit v1.2.3 From 2fdc02b3b8f76a1268956fad1c4e32facd5a61cf Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Jan 2007 13:56:46 -0500 Subject: kconfig: qt1010 should be selected by m920x From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index e18eb7b3f..861a02939 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -113,6 +113,7 @@ config DVB_USB_M920X tristate "Uli m920x DVB-T USB2.0 support" depends on DVB_USB select DVB_MT352 if !DVB_FE_CUSTOMISE + select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE help Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. Currently, only devices with a product id of -- cgit v1.2.3 From 22779dda1dcad43567d722ca5c412c07bbe2f67f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Jan 2007 13:57:20 -0500 Subject: m920x: Fix tuner identification bug with qt1010 module From: Aapo Tahkola Fixes qt1010 identification bug with megasky caused by the Quantek QT1010 tuner module patch. Signed-off-by: Aapo Tahkola Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 46 +++++++++++++++++++++++---------- linux/drivers/media/dvb/dvb-usb/m920x.h | 9 +++++++ 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 108450ef0..b65ba6ee1 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -141,6 +141,7 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); + struct m9206_state *m = d->priv; int i; int ret = 0; @@ -151,8 +152,6 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int nu return -EINVAL; for (i = 0; i < num; i++) { - u8 w_len; - if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].addr, 0x80)) != 0) goto unlock; @@ -160,13 +159,19 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int nu goto unlock; if (i + 1 < num && msg[i + 1].flags & I2C_M_RD) { - /* Possibly device dependant */ - if (msg[i].addr == d->adapter[0].pll_addr) - w_len = 0xc5; - else - w_len = 0x1f; + int i2c_i; + + for (i2c_i = 0; i2c_i < M9206_I2C_MAX; i2c_i++) + if (msg[i].addr == m->i2c_r[i2c_i].addr) + break; - if ((ret = m9206_write(d->udev, M9206_I2C, w_len, 0x80)) != 0) + if (i2c_i >= M9206_I2C_MAX) { + deb_rc("No magic for i2c addr!\n"); + ret = -EINVAL; + goto unlock; + } + + if ((ret = m9206_write(d->udev, M9206_I2C, m->i2c_r[i2c_i].magic, 0x80)) != 0) goto unlock; if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x60, msg[i + 1].buf, msg[i + 1].len)) != 0) @@ -245,11 +250,17 @@ static struct mt352_config megasky_mt352_config = { static int megasky_frontend_attach(struct dvb_usb_adapter *adap) { + struct m9206_state *m = adap->dev->priv; + deb_rc("megasky_frontend_attach!\n"); - if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) != NULL) - return 0; - return -EIO; + m->i2c_r[M9206_I2C_DEMOD].addr = megasky_mt352_config.demod_address; + m->i2c_r[M9206_I2C_DEMOD].magic = 0x1f; + + if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL) + return -EIO; + + return 0; } static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid) @@ -396,9 +407,16 @@ static struct qt1010_config megasky_qt1010_config = { static int megasky_tuner_attach(struct dvb_usb_adapter *adap) { - return dvb_attach(qt1010_attach, - adap->fe, &adap->dev->i2c_adap, - &megasky_qt1010_config) == NULL ? -ENODEV : 0; + struct m9206_state *m = adap->dev->priv; + + m->i2c_r[M9206_I2C_TUNER].addr = megasky_qt1010_config.i2c_address; + m->i2c_r[M9206_I2C_TUNER].magic = 0xc5; + + if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, + &megasky_qt1010_config) == NULL) + return -ENODEV; + + return 0; } /* DVB USB Driver stuff */ diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.h b/linux/drivers/media/dvb/dvb-usb/m920x.h index 597df11e6..c354196ff 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.h +++ b/linux/drivers/media/dvb/dvb-usb/m920x.h @@ -18,9 +18,18 @@ #define M9206_FW 0x30 #define M9206_MAX_FILTERS 8 + +#define M9206_I2C_TUNER 0 +#define M9206_I2C_DEMOD 1 +#define M9206_I2C_MAX 2 + struct m9206_state { u16 filters[M9206_MAX_FILTERS]; int filtering_enabled; int rep_count; + struct { + unsigned char addr; + unsigned char magic; + }i2c_r[M9206_I2C_MAX]; }; #endif -- cgit v1.2.3 From e9f51c1596685e652f88d6bbd9173bb0d0676ae0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Jan 2007 13:57:48 -0500 Subject: whitespace / 80-column cleanups From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index b65ba6ee1..495e92f4c 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -39,7 +39,8 @@ static struct dvb_usb_rc_key megasky_rc_keys [] = { { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ }; -static inline int m9206_read(struct usb_device *udev, u8 request, u16 value, u16 index, void *data, int size) +static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\ + u16 index, void *data, int size) { int ret; @@ -55,7 +56,8 @@ static inline int m9206_read(struct usb_device *udev, u8 request, u16 value, u16 return 0; } -static inline int m9206_write(struct usb_device *udev, u8 request, u16 value, u16 index) +static inline int m9206_write(struct usb_device *udev, u8 request, + u16 value, u16 index) { int ret; @@ -138,7 +140,8 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) } /* I2C */ -static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) +static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); struct m9206_state *m = d->priv; @@ -263,7 +266,8 @@ static int megasky_frontend_attach(struct dvb_usb_adapter *adap) return 0; } -static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid) +static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, + int pid) { int ret = 0; @@ -330,7 +334,8 @@ static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) return m9206_update_filters(adap); } -static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) +static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, + int onoff) { struct m9206_state *m = adap->dev->priv; @@ -339,7 +344,8 @@ static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, in return m9206_update_filters(adap); } -static int m9206_firmware_download(struct usb_device *udev, const struct firmware *fw) +static int m9206_firmware_download(struct usb_device *udev, + const struct firmware *fw) { u16 value, index, size; u8 read[4], *buff; @@ -422,7 +428,8 @@ static int megasky_tuner_attach(struct dvb_usb_adapter *adap) /* DVB USB Driver stuff */ static struct dvb_usb_device_properties megasky_properties; -static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *id) +static int m920x_probe(struct usb_interface *intf, + const struct usb_device_id *id) { struct dvb_usb_device *d; struct usb_host_interface *alt; @@ -437,7 +444,8 @@ static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *i return -ENODEV; } - ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, alt->desc.bAlternateSetting); + ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, + alt->desc.bAlternateSetting); if (ret < 0) return ret; -- cgit v1.2.3 From dd42b625bb11836e6b71aaa6a87faea6fa1e4df0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 21 Jan 2007 20:43:38 -0200 Subject: Adds video output routing From: Marco Schluessler Nexus CA needs to use a different routing on saa7115 module. Signed-off-by: Marco Schluessler Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7115.c | 24 ++++++++++++++++++------ linux/include/media/saa7115.h | 3 +++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 6b99a4624..462c5dd7f 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -82,6 +82,7 @@ I2C_CLIENT_INSMOD; struct saa711x_state { v4l2_std_id std; int input; + int output; int enable; int radio; int bright; @@ -1312,7 +1313,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar struct v4l2_routing *route = arg; route->input = state->input; - route->output = 0; + route->output = state->output; break; } @@ -1320,7 +1321,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar { struct v4l2_routing *route = arg; - v4l_dbg(1, debug, client, "decoder set input %d\n", route->input); + v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); /* saa7113 does not have these inputs */ if (state->ident == V4L2_IDENT_SAA7113 && (route->input == SAA7115_COMPOSITE4 || @@ -1329,10 +1330,12 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar } if (route->input > SAA7115_SVIDEO3) return -EINVAL; - if (state->input == route->input) + if (route->output > SAA7115_IPORT_ON) + return -EINVAL; + if (state->input == route->input && state->output == route->output) break; - v4l_dbg(1, debug, client, "now setting %s input\n", - (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite"); + v4l_dbg(1, debug, client, "now setting %s input %s output\n", + (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); state->input = route->input; /* select mode */ @@ -1344,6 +1347,14 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar saa711x_write(client, R_09_LUMA_CNTL, (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) | (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); + + state->output = route->output; + if (state->ident == V4L2_IDENT_SAA7114 || + state->ident == V4L2_IDENT_SAA7115) { + saa711x_write(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, + (saa711x_read(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) | + (state->output & 0x01)); + } break; } @@ -1511,6 +1522,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) return -ENOMEM; } state->input = -1; + state->output = SAA7115_IPORT_ON; state->enable = 1; state->radio = 0; state->bright = 128; @@ -1573,7 +1585,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) static int saa711x_probe(struct i2c_adapter *adapter) { #ifdef I2C_CLASS_TV_ANALOG - if (adapter->class & I2C_CLASS_TV_ANALOG) + if (adapter->class & I2C_CLASS_TV_ANALOG || adapter->class & I2C_CLASS_TV_DIGITAL) #else if (adapter->id == I2C_HW_B_BT848) #endif diff --git a/linux/include/media/saa7115.h b/linux/include/media/saa7115.h index 9f0e2285a..f677dfb9d 100644 --- a/linux/include/media/saa7115.h +++ b/linux/include/media/saa7115.h @@ -42,5 +42,8 @@ #define SAA7115_FREQ_FL_CGCDIV (1 << 1) /* SA 3A[6], CGCDIV, SAA7115 only */ #define SAA7115_FREQ_FL_APLL (1 << 2) /* SA 3A[3], APLL, SAA7114/5 only */ +#define SAA7115_IPORT_ON 1 +#define SAA7115_IPORT_OFF 0 + #endif -- cgit v1.2.3 From 7fd69e2ae5818df336926da320cba43774081e2b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 21 Jan 2007 23:02:35 -0200 Subject: Remove some warnings when compiling on x86_64 From: Mauro Carvalho Chehab pvrusb2-encoder.c: In function 'pvr2_encoder_cmd': pvrusb2-encoder.c:195: warning: format '%u' expects type 'unsigned int', but argument 3 has type 'long unsigned int' pvrusb2-encoder.c:205: warning: format '%u' expects type 'unsigned int', but argument 3 has type 'long unsigned int' pvrusb2-encoder.c: In function 'pvr2_encoder_vcmd': pvrusb2-encoder.c:303: warning: format '%u' expects type 'unsigned int', but argument 3 has type 'long unsigned int' CC: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c index b9ee07638..95e45be08 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -196,8 +196,8 @@ static int pvr2_encoder_cmd(void *ctxt, PVR2_TRACE_ERROR_LEGS, "Failed to write cx23416 command" " - too many input arguments" - " (was given %u limit %u)", - arg_cnt_send, ARRAY_SIZE(wrData) - 4); + " (was given %u limit %lu)", + arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4); return -EINVAL; } @@ -206,8 +206,8 @@ static int pvr2_encoder_cmd(void *ctxt, PVR2_TRACE_ERROR_LEGS, "Failed to write cx23416 command" " - too many return arguments" - " (was given %u limit %u)", - arg_cnt_recv, ARRAY_SIZE(rdData) - 4); + " (was given %u limit %lu)", + arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4); return -EINVAL; } @@ -304,8 +304,8 @@ static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd, PVR2_TRACE_ERROR_LEGS, "Failed to write cx23416 command" " - too many arguments" - " (was given %u limit %u)", - args, ARRAY_SIZE(data)); + " (was given %u limit %lu)", + args, (long unsigned) ARRAY_SIZE(data)); return -EINVAL; } -- cgit v1.2.3 From d8f7b2bfd824a45f93ffb0b3d78976d6e58b79c3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 21 Jan 2007 23:02:58 -0200 Subject: Fix: VIDIOC_G_TUNER were returning an endless number of tuners From: Mauro Carvalho Chehab pvrusb2 have only one tuner inside. However, as it were not handling index, a call to v4l-info were returning as if it were an infinite number of tuners: $ v4l-info|grep VIDIOC_G_TUNER |head -5 VIDIOC_G_TUNER(0) VIDIOC_G_TUNER(1) VIDIOC_G_TUNER(2) VIDIOC_G_TUNER(3) VIDIOC_G_TUNER(4) CC: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 13dc436f6..621a0dd31 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -366,6 +366,10 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_TUNER: { struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; + + if (vt->index != 0) + break; + pvr2_hdw_execute_tuner_poll(hdw); ret = pvr2_hdw_get_tuner_status(hdw,vt); break; -- cgit v1.2.3 From a4afacc02da0c558bd2e455a63d16a9c4301e862 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 21 Jan 2007 23:21:41 -0200 Subject: error check were wrong, since at userspace, error codes are positive vals From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/test/driver-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v4l2-apps/test/driver-test.c b/v4l2-apps/test/driver-test.c index eaa099fac..a2ac365a3 100644 --- a/v4l2-apps/test/driver-test.c +++ b/v4l2-apps/test/driver-test.c @@ -36,7 +36,7 @@ int main(void) perror("open /dev/video0"); return -1; } - if (v4l2_enum_stds (&drv)<0) { + if (v4l2_enum_stds (&drv)) { perror("enum_stds"); printf("Error! Driver is not reporting supported STD, frames/sec and number of lines!\n Trying to continue anyway...\n"); } else { -- cgit v1.2.3 From eeb2d15e79aeabf08344067463107020c173a427 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 21 Jan 2007 21:22:18 -0500 Subject: dvb-usb: Register the bus, vendor and product IDs for remote device From: Chris Rankin This patch writes the USB vendor and product IDs into the /sys/class/input/inputX/id/ files, so that udev can find them. A rule like this does the trick for me: KERNEL="event*", SYSFS{../id/vendor}=="2040", SYSFS{../id/product}=="9301", SYMLINK+="input/dvb-remote" Signed-off-by: Chris Rankin Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 1a86adbfa..1bee5dfad 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -125,6 +125,9 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) input_dev->keycodemax = KEY_MAX; input_dev->name = "IR-receiver inside an USB DVB receiver"; input_dev->phys = d->rc_phys; + input_dev->id.bustype = BUS_USB; + input_dev->id.vendor = d->udev->descriptor.idVendor; + input_dev->id.product = d->udev->descriptor.idProduct; usb_to_input_id(d->udev, &input_dev->id); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) input_dev->cdev.dev = &d->udev->dev; -- cgit v1.2.3 From e2ca83d37b31336371aca127f043b0a75d985ef0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 22 Jan 2007 22:27:47 +0100 Subject: Various cx2341x documentation updates/fixes. From: Hans Verkuil Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/cx2341x/fw-dma.txt | 16 +++++++++------- .../Documentation/video4linux/cx2341x/fw-encoder-api.txt | 10 ++++++---- linux/Documentation/video4linux/cx2341x/fw-memory.txt | 4 +++- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/linux/Documentation/video4linux/cx2341x/fw-dma.txt b/linux/Documentation/video4linux/cx2341x/fw-dma.txt index 8123e262d..be52b6fd1 100644 --- a/linux/Documentation/video4linux/cx2341x/fw-dma.txt +++ b/linux/Documentation/video4linux/cx2341x/fw-dma.txt @@ -22,6 +22,8 @@ urged to choose a smaller block size and learn the scatter-gather technique. Mailbox #10 is reserved for DMA transfer information. +Note: the hardware expects little-endian data ('intel format'). + Flow ==== @@ -64,7 +66,7 @@ addresses are the physical memory location of the target DMA buffer. Each S-G array element is a struct of three 32-bit words. The first word is the source address, the second is the destination address. Both take up the -entire 32 bits. The lowest 16 bits of the third word is the transfer byte +entire 32 bits. The lowest 18 bits of the third word is the transfer byte count. The high-bit of the third word is the "last" flag. The last-flag tells the card to raise the DMA_DONE interrupt. From hard personal experience, if you forget to set this bit, the card will still "work" but the stream will @@ -78,8 +80,8 @@ Array Element: - 32-bit Source Address - 32-bit Destination Address -- 16-bit reserved (high bit is the last flag) -- 16-bit byte count +- 14-bit reserved (high bit is the last flag) +- 18-bit byte count DMA Transfer Status =================== @@ -87,8 +89,8 @@ DMA Transfer Status Register 0x0004 holds the DMA Transfer Status: Bit -4 Scatter-Gather array error -3 DMA write error -2 DMA read error -1 write completed 0 read completed +1 write completed +2 DMA read error +3 DMA write error +4 Scatter-Gather array error diff --git a/linux/Documentation/video4linux/cx2341x/fw-encoder-api.txt b/linux/Documentation/video4linux/cx2341x/fw-encoder-api.txt index fe02bdb84..e499cc07f 100644 --- a/linux/Documentation/video4linux/cx2341x/fw-encoder-api.txt +++ b/linux/Documentation/video4linux/cx2341x/fw-encoder-api.txt @@ -498,12 +498,14 @@ Name CX2341X_ENC_GET_PREV_DMA_INFO_MB_9 Enum 203/0xCB Description Returns information on the previous DMA transfer in conjunction with - bit 27 of the interrupt mask. Uses mailbox 9. + bit 27 or 18 of the interrupt mask. Uses mailbox 9. Result[0] Status bits: - Bit 0 set indicates transfer complete - Bit 2 set indicates transfer error - Bit 4 set indicates linked list error + 0 read completed + 1 write completed + 2 DMA read error + 3 DMA write error + 4 Scatter-Gather array error Result[1] DMA type Result[2] diff --git a/linux/Documentation/video4linux/cx2341x/fw-memory.txt b/linux/Documentation/video4linux/cx2341x/fw-memory.txt index d445e457f..9d736fe8d 100644 --- a/linux/Documentation/video4linux/cx2341x/fw-memory.txt +++ b/linux/Documentation/video4linux/cx2341x/fw-memory.txt @@ -1,6 +1,8 @@ This document describes the cx2341x memory map and documents some of the register space. +Note: the memory long words are little-endian ('intel format'). + Warning! This information was figured out from searching through the memory and registers, this information may not be correct and is certainly not complete, and was not derived from anything more than searching through the memory space with @@ -67,7 +69,7 @@ DMA Registers 0x000-0xff: 0x84 - first write linked list reg, for pci memory addr 0x88 - first write linked list reg, for length of buffer in memory addr (|0x80000000 or this for last link) - 0x8c-0xcc - rest of write linked list reg, 8 sets of 3 total, DMA goes here + 0x8c-0xdc - rest of write linked list reg, 8 sets of 3 total, DMA goes here from linked list addr in reg 0x0c, firmware must push through or something. 0xe0 - first (and only) read linked list reg, for pci memory addr -- cgit v1.2.3 From 689e43512980c5225bd47090dbf7690a250ae8f0 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 22 Jan 2007 16:33:07 -0500 Subject: proper vendor/device ID for the CinergyT2 input device From: Tino Keitel I noticed that udev does not create a symlink for the CinergyT2 remote input device in /dev/input/by-id, which is required if I want to have a unique device name for lircd. The attached patch tries to achive this. However, udev still omits the input device for /dev/input/by-id symlinks. I think something is still not reported correctly. Signed-off-by: Tino Keitel Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/cinergyT2/cinergyT2.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c index 9c0eff865..0de98c3eb 100644 --- a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -864,6 +864,11 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) set_bit(rc_keys[i + 2], input_dev->keybit); input_dev->keycodesize = 0; input_dev->keycodemax = 0; + input_dev->id.bustype = BUS_USB; + input_dev->id.vendor = cinergyt2->udev->descriptor.idVendor; + input_dev->id.product = cinergyt2->udev->descriptor.idProduct; + input_dev->id.version = 1; + input_dev->cdev.dev = &cinergyt2->udev->dev; err = input_register_device(input_dev); if (err) { -- cgit v1.2.3 From 9896ec9a5dcc113b607c4649ca18dc05d2993928 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 23 Jan 2007 13:00:42 -0500 Subject: m920x: group tuner / demod callback functions together From: Michael Krufky Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 125 ++++++++++++++++---------------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 495e92f4c..1f0d21c7d 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -206,65 +206,6 @@ static struct i2c_algorithm m9206_i2c_algo = { .functionality = m9206_i2c_func, }; -/* Callbacks for DVB USB */ -static int megasky_identify_state(struct usb_device *udev, - struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, - int *cold) -{ - struct usb_host_interface *alt; - - alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1); - *cold = (alt == NULL) ? 1 : 0; - - return 0; -} - -static int megasky_mt352_demod_init(struct dvb_frontend *fe) -{ - u8 config[] = { CONFIG, 0x3d }; - u8 clock[] = { CLOCK_CTL, 0x30 }; - u8 reset[] = { RESET, 0x80 }; - u8 adc_ctl[] = { ADC_CTL_1, 0x40 }; - u8 agc[] = { AGC_TARGET, 0x1c, 0x20 }; - u8 sec_agc[] = { 0x69, 0x00, 0xff, 0xff, 0x40, 0xff, 0x00, 0x40, 0x40 }; - u8 unk1[] = { 0x93, 0x1a }; - u8 unk2[] = { 0xb5, 0x7a }; - - mt352_write(fe, config, ARRAY_SIZE(config)); - mt352_write(fe, clock, ARRAY_SIZE(clock)); - mt352_write(fe, reset, ARRAY_SIZE(reset)); - mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl)); - mt352_write(fe, agc, ARRAY_SIZE(agc)); - mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc)); - mt352_write(fe, unk1, ARRAY_SIZE(unk1)); - mt352_write(fe, unk2, ARRAY_SIZE(unk2)); - - deb_rc("Demod init!\n"); - - return 0; -} - -static struct mt352_config megasky_mt352_config = { - .demod_address = 0x1e, - .no_tuner = 1, - .demod_init = megasky_mt352_demod_init, -}; - -static int megasky_frontend_attach(struct dvb_usb_adapter *adap) -{ - struct m9206_state *m = adap->dev->priv; - - deb_rc("megasky_frontend_attach!\n"); - - m->i2c_r[M9206_I2C_DEMOD].addr = megasky_mt352_config.demod_address; - m->i2c_r[M9206_I2C_DEMOD].magic = 0x1f; - - if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL) - return -EIO; - - return 0; -} static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, int pid) @@ -407,11 +348,71 @@ static int m9206_firmware_download(struct usb_device *udev, return ret; } +/* Callbacks for DVB USB */ +static int megasky_identify_state(struct usb_device *udev, + struct dvb_usb_device_properties *props, + struct dvb_usb_device_description **desc, + int *cold) +{ + struct usb_host_interface *alt; + + alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1); + *cold = (alt == NULL) ? 1 : 0; + + return 0; +} + +static int megasky_mt352_demod_init(struct dvb_frontend *fe) +{ + u8 config[] = { CONFIG, 0x3d }; + u8 clock[] = { CLOCK_CTL, 0x30 }; + u8 reset[] = { RESET, 0x80 }; + u8 adc_ctl[] = { ADC_CTL_1, 0x40 }; + u8 agc[] = { AGC_TARGET, 0x1c, 0x20 }; + u8 sec_agc[] = { 0x69, 0x00, 0xff, 0xff, 0x40, 0xff, 0x00, 0x40, 0x40 }; + u8 unk1[] = { 0x93, 0x1a }; + u8 unk2[] = { 0xb5, 0x7a }; + + mt352_write(fe, config, ARRAY_SIZE(config)); + mt352_write(fe, clock, ARRAY_SIZE(clock)); + mt352_write(fe, reset, ARRAY_SIZE(reset)); + mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl)); + mt352_write(fe, agc, ARRAY_SIZE(agc)); + mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc)); + mt352_write(fe, unk1, ARRAY_SIZE(unk1)); + mt352_write(fe, unk2, ARRAY_SIZE(unk2)); + + deb_rc("Demod init!\n"); + + return 0; +} + +static struct mt352_config megasky_mt352_config = { + .demod_address = 0x1e, + .no_tuner = 1, + .demod_init = megasky_mt352_demod_init, +}; + +static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct m9206_state *m = adap->dev->priv; + + deb_rc("megasky_frontend_attach!\n"); + + m->i2c_r[M9206_I2C_DEMOD].addr = megasky_mt352_config.demod_address; + m->i2c_r[M9206_I2C_DEMOD].magic = 0x1f; + + if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL) + return -EIO; + + return 0; +} + static struct qt1010_config megasky_qt1010_config = { .i2c_address = 0xc4 }; -static int megasky_tuner_attach(struct dvb_usb_adapter *adap) +static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap) { struct m9206_state *m = adap->dev->priv; @@ -485,8 +486,8 @@ static struct dvb_usb_device_properties megasky_properties = { .pid_filter = m9206_pid_filter, .pid_filter_ctrl = m9206_pid_filter_ctrl, - .frontend_attach = megasky_frontend_attach, - .tuner_attach = megasky_tuner_attach, + .frontend_attach = megasky_mt352_frontend_attach, + .tuner_attach = megasky_qt1010_tuner_attach, .stream = { .type = USB_BULK, -- cgit v1.2.3 From 7f9be719c75fb28bd77aeeda2df201b14554a4fd Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 23 Jan 2007 13:34:10 -0500 Subject: m920x: move filter caps from device caps to adapter caps From: Michael Krufky Move filter caps from device caps to adapter caps for the megasky driver. This fixes usb1.1 operation. Signed-off-by: Aapo Tahkola Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/m920x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 1f0d21c7d..1a411316f 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -465,8 +465,7 @@ static struct usb_device_id m920x_table [] = { MODULE_DEVICE_TABLE (usb, m920x_table); static struct dvb_usb_device_properties megasky_properties = { - .caps = DVB_USB_IS_AN_I2C_ADAPTER | DVB_USB_ADAP_HAS_PID_FILTER | - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .caps = DVB_USB_IS_AN_I2C_ADAPTER, .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-megasky-02.fw", @@ -482,6 +481,9 @@ static struct dvb_usb_device_properties megasky_properties = { .identify_state = megasky_identify_state, .num_adapters = 1, .adapter = {{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 8, .pid_filter = m9206_pid_filter, .pid_filter_ctrl = m9206_pid_filter_ctrl, -- cgit v1.2.3 From fec39e8fa9bf392d8bd4efad9143535f3b8fdf39 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 23 Jan 2007 21:04:13 -0200 Subject: Buf_qbuf: fix: videobuf_queue->stream corruption and lockup From: Oleg Nesterov We are doing ->buf_prepare(buf) before adding buf to q->stream list. This means that videobuf_qbuf() should not try to re-add a STATE_PREPARED buffer. Signed-off-by: Oleg Nesterov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/video-buf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/drivers/media/video/video-buf.c b/linux/drivers/media/video/video-buf.c index 6d6a74c60..4e359bc33 100644 --- a/linux/drivers/media/video/video-buf.c +++ b/linux/drivers/media/video/video-buf.c @@ -706,6 +706,7 @@ videobuf_qbuf(struct videobuf_queue *q, goto done; } if (buf->state == STATE_QUEUED || + buf->state == STATE_PREPARED || buf->state == STATE_ACTIVE) { dprintk(1,"qbuf: buffer is already queued or active.\n"); goto done; -- cgit v1.2.3