/* AF-9015 Bus Interface Unit driver Copyright (c) Manu Abraham Copyright (c) AFA Technologies 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 "dvb-usb.h" #include "af9015.h" #include "af9015_fw.h" #include "af9015_priv.h" #include "af901x_reg.h" #include "af901x_priv.h" #include "af9015_rom.h" static unsigned int verbose = 5; module_param(verbose, int, 0644); MODULE_PARM_DESC(verbose, "verbosity level"); u8 ucSN = 0; /** * NOTE! Currently we do bulk transfers for Control messages * not very sure, whether this is the best approach we should * take. Need to address this thought, once we have settled * with the basic functionality. */ int af9015_biu_read(struct usb_device *udev, struct af9015_biu_msg *msg) { int i, err, length; u8 buf[64]; /* EP 1 IN */ /** * TODO! Probably it might make more sense to replace * the hardcoded length of 255 with the length in the * sent message, ie, msg->len */ err = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, 255, &length, 1000); if (err == 0) { if (length == 0) { printk("%s: Transaction error! length=%d\n", __func__, length); goto exit; } if (buf[0] != (ucSN - 1)) { printk("%s: Sequence error! Seq RD=0x%02x, Expect=0x%02x\n", __func__, buf[0], ucSN); err = -EINVAL; goto exit; } if (buf[1] != 0) { printk("%s: Status check failed! Status=0x%02x\n", __func__, buf[1]); err = -EINVAL; goto exit; } } printk("%s: Data=[", __func__); for (i = 0; i < (msg->length + 2); i++) printk(" 0x%02x ", buf[i]); printk("]\n"); memcpy(msg->data, &buf[2], msg->length); // printk("%s: Data=[0x%02x]\n", __func__, msg->data[0]); return 0; exit: printk("%s: Read Error\n", __func__); return err; } /** * NOTE! Currently we do bulk transfers for Control messages. * not very sure, whether this is the best approach we should * take. Need to address this thought, once we have settled * with the basic functionality. */ int af9015_biu_write(struct usb_device *udev, struct af9015_biu_msg *msg) { int i, err, act_len; u8 biu_msg[64] = {0}; u8 length = 0; biu_msg[0] = msg->biu_cmd; biu_msg[1] = ucSN; biu_msg[2] = msg->addr; biu_msg[3] = msg->reg_addr_msb; /* Register Address (MSB) */ biu_msg[4] = msg->reg_addr_lsb; /* Register Address (LSB) */ biu_msg[5] = 0; /* what to do with MAILBOX[5] commands ? */ biu_msg[6] = msg->addr_length; /* Reg addr bytes = 3, means SLAVE, So what to do ? */ biu_msg[7] = msg->length; /* TODO! Checksum */ // printk("%s: Header = [ ", __func__); // for (i = 0; i < 8; i++) // printk("0x%02x ", biu_msg[i]); // printk("]\n"); switch (msg->biu_cmd) { case AF9015_REQ_FWDOWNLOAD: if (msg->length) /* There are cases with no data */ memcpy(&biu_msg[8], &msg->data[0], msg->length); /* Copy data */ length = 8 + msg->length; break; default: length = 8; break; } printk("%s: Message = [ ", __func__); for (i = 0; i < length; i++) printk("0x%02x ", biu_msg[i]); printk("]\n"); /* EP 2 OUT */ err = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), biu_msg, length, &act_len, 1000); ucSN += 1; return err; } /** * NOTE! This is the BIU protocol what we use. In fact this is not * the default hardware protocol that's defined by the vendor, We * try to make it look a bit nicer, by wrapping it around etc. * Since there is no other documentation other than this, it * is better to have it documented for reference purposes. * Such a rework has been done,such that SLAVE demodulators * are easily separable from Bus Interface Unit (BIU) integrated * demodulators, which brings code reusability, without duplication. * * struct af9015_biu_msg { * u16 addr; // Slave address * enum af9015_biu_cmd biu_cmd; // BIU Command * u16 flags; * #define BIU_RD 0x01 * u8 *data; // Data * u8 length; // Length of data * }; * * Where BIU Commands are defined thus: * * enum af9015_biu_cmd { * AF9015_REQ_CURCONFIG = 0x10, // 1a) Get current config * AF9015_REQ_FWDOWNLOAD = 0x11, // 2a) Download Firmware control messages * AF9015_REQ_CHKSUMCOMPUTE = 0x12, // 3a) Calculate Checksum control messages * AF9015_REQ_BOOTCONTROL = 0x13, // 4a) Boot control messages * AF9015_REQ_BIUMMIO_RD = 0x20, // 5a) USB Memory RD control messages * AF9015_REQ_BIUMMIO_WR = 0x21, // 6a) USB Memory WR control messages * AF9015_REQ_GENERIC_I2C = 0x22, // 7a) General I2C control messages * AF9015_REQ_FWCOPY = 0x23, // 8a) Copy Firmware control messages * AF9015_REQ_SWRESET = 0x25, // 9) Software reset control messages * AF9015_REQ_CMDCTL = 0x26, // 10a) Control unit command conrtol messages * }; * * Where Data is defined thus: * * Byte 0: Register Address (MSB) * Byte 1: Register Address (LSB) * Byte 2: Embedded MailBox Command * Byte 3:+ * --- | * --- | * Byte n:+ Data for internal Memory Mapped Registers */ int af9015_biu_xfer(struct usb_device *udev, struct af9015_biu_msg *msgs, int num) { int ret = 0, i; for (i = 0; i < num; i++) { // printk("%s: Msgs [%d of %d]\n", __func__, i, num); if (msgs[i].flags & BIU_RD) ret = af9015_biu_read(udev, &msgs[i]); else ret = af9015_biu_write(udev, &msgs[i]); if (ret < 0) { printk("%s: Transaction failure\n", __func__); return ret; } } return num; } static int af901x_fw_download(struct usb_device *udev, const struct firmware *fw) { int i, err; u8 config, *fw_array = packetArr; u32 length, blocks, remainder; struct af9015_biu_msg biu_config[] = { { .addr = 0x3a, .biu_cmd = AF9015_REQ_CURCONFIG, .reg_addr_msb = 0, .reg_addr_lsb = 0, .flags = 0, .data = NULL, .length = 0 },{ /* Current configuration */ .addr = 0x3a, .biu_cmd = AF9015_REQ_CURCONFIG, .flags = BIU_RD, .data = &config, .length = 1 } }; struct af9015_biu_msg fw_download = { /* Firmware download */ .addr = 0x3a, .biu_cmd = AF9015_REQ_FWDOWNLOAD, .flags = 0, }; struct af9015_biu_msg boot = { /* Boot demodulator */ .addr = 0x3a, .biu_cmd = AF9015_REQ_BOOTCONTROL, .flags = 0, .data = NULL, .length = 0 }; /* [STEP #1] Read current configuration */ printk("%s: Read current configuration\n", __func__); if ((err = af9015_biu_xfer(udev, biu_config, 2)) != 2) goto exit; if (biu_config[1].data[0] != 1) goto exit; length = sizeof (packetArr) / sizeof (u8); blocks = length / 63; remainder = length % 63; printk("%s: Array length=%d, Blocks=%d, Remainder=%d\n", __func__, length, blocks, remainder); /* [STEP #2] USB firmware download */ fw_download.reg_addr_msb = *(fw_array + 3); fw_download.reg_addr_lsb = *(fw_array + 4); fw_download.length = *(fw_array + 7); fw_download.data = fw_array + 8; for (i = 0; i < blocks; i++) { printk("%s: Transferring FW Blocks [%d of %d]\n", __func__, i, blocks); if ((err = af9015_biu_xfer(udev, &fw_download, 1)) != 1) goto exit; fw_array += 63; fw_download.reg_addr_msb = *(fw_array + 3); fw_download.reg_addr_lsb = *(fw_array + 4); fw_download.length = *(fw_array + 7); fw_download.data = fw_array + 8; } if (remainder) { fw_download.reg_addr_msb = *(fw_array + 3); fw_download.reg_addr_lsb = *(fw_array + 4); fw_download.length = *(fw_array + 7); fw_download.data = fw_array + 8; if ((err = af9015_biu_xfer(udev, &fw_download, 1)) != 1) goto exit; } /* [STEP #3] Boot */ printk("%s: Booting the DSP core\n", __func__); if ((err = af9015_biu_xfer(udev, &boot, 1)) != 1) goto exit; /* [STEP #4] Wait */ msleep(10); /* [STEP #5] Read current configuration */ printk("%s: Read current configuration\n", __func__); if ((err = af9015_biu_xfer(udev, biu_config, 2)) != 2) goto exit; if (biu_config[1].data[0] != 2) { if (biu_config[1].data[0] == 1) printk("%s: DSP Boot Code running still!, :-(\n", __func__); goto exit; } if (biu_config[1].data[0] == 2) printk("%s: DSP Firmware running, we made it through! :)\n", __func__); return 0; exit: printk("%s: ERROR=%d\n", __func__, err); return err; } #define MERC_EEPROM_I2C_ADDR 0x9A50 static int af9015_read_eeprom(struct usb_device *udev, u16 reg, u8 *data) { int err; u8 r_data, addr_len; u8 eeprom_reg[] = { ((reg >> 8) & 0xff), (reg & 0xff), 0x00 }; struct af9015_biu_msg mem_read[] = { { /* Memory read */ .addr = 0x2a, .biu_cmd = AF9015_REQ_BIUMMIO_RD, .reg_addr_msb = ((MERC_EEPROM_I2C_ADDR >> 8) & 0xff), .reg_addr_lsb = (MERC_EEPROM_I2C_ADDR & 0xff), .flags = 0, .data = NULL, .length = 1 },{ .flags = BIU_RD, .data = &r_data, .length = 1 } }; struct af9015_biu_msg eeprom_read[] = { { /* EEPROM read */ .addr = 0xa1, /* EEPROM = 0x50 */ .biu_cmd = AF9015_REQ_GENERIC_I2C, .reg_addr_msb = ((reg >> 8) & 0xff), .reg_addr_lsb = (reg & 0xff), .flags = 0, .data = NULL, .length = 1 },{ .flags = BIU_RD, .data = data, .length = 1 } }; /* [STEP #1] Issue Memory Read Request */ // printk("%s: Memory Read Request @ 0x%02x Reg(MSB)=0x%02x (LSB)=0x%02x\n", // __func__, // 0x2a, // ((MERC_EEPROM_I2C_ADDR >> 8) & 0xff), // (MERC_EEPROM_I2C_ADDR & 0xff)); if ((err = af9015_biu_xfer(udev, mem_read, 2)) != 2) { printk("%s: Memory Read request failed\n", __func__); goto exit; } if (r_data == 0) { printk("%s: Data=0, Unexpected\n", __func__); err = -EIO; goto exit; } if (r_data < 0xa8) { addr_len = 1; } else { addr_len = 2; } eeprom_read[0].addr_length = addr_len; /* [STEP #2] Issue Eeprom Read Request */ // printk("%s: EEPROM Read Request @ 0x%02x Reg (MSB)=0x%02x (LSB)=0x%02x\n", // __func__, eeprom_read[0].addr, ((reg >> 8) & 0xff), (reg & 0xff)); if ((err = af9015_biu_xfer(udev, eeprom_read, 2)) != 2) { printk("%s: EEPROM Read request failed\n", __func__); goto exit; } *data = data[0]; // printk("%s: Data=[0x%02x]\n", __func__, *data); return 0; exit: return err; } static int af9015_get_biu_config(struct af901x_biu *biu, struct af901x_config *dmd_config) { int err; u16 shift = 0; u8 slave = 0; u8 tmp[4]; struct af901x_biu_config *biu_config = &biu->biu_config; biu->dmd_config = dmd_config; #if 0 if (slave) shift = EEPROM_SHIFT; #endif /* IR Table download */ if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_IRMODE, tmp))) { biu_config->ir_mode = tmp[0]; switch (biu_config->ir_mode) { case AF9015_IRMODE_HID: case AF9015_IRMODE_RLC: case AF9015_IRMODE_RC6: if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_IRREMOTE, tmp))) { biu_config->ir_type = tmp[0]; switch (biu_config->ir_type) { case AF9015_IR_NEC: printk("%s: IR/HID Mode=(NEC)\n", __func__); break; case AF9015_IR_RC6: printk("%s: IR/HID Mode=(RC6)\n", __func__); break; default: printk("%s: Unknown IR mode\n", __func__); err = -EINVAL; } } break; case AF9015_IRMODE_DISABLED: default: printk("%s: IR mode disabled\n", __func__); break; } } /* Dual TS option */ if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_TSMODE, tmp))) { biu_config->ts_mode = tmp[0]; printk("%s: Dual TS Mode = 0x%02X\n", __func__, biu_config->ts_mode); } /* MPEG2 I2C addr */ if ((err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_2WIREADDR, tmp))) { biu_config->addr = AF901x_SLAVE_DEMOD_ADDR; printk("%s: EEPROM_2WIREADDR Fail\n", __func__); } biu_config->addr = tmp[0]; printk("%s: 2 wire address = 0x%02x\n", __func__, biu_config->addr); /* SAW filter bandwidth */ if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_SAWBW1, tmp))) { biu_config->saw_bw = tmp[0]; printk("%s: SAW filter bandwidth = %d Mhz\n", __func__, biu_config->saw_bw); } if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_XTALTYP1, tmp))) { biu_config->osc_type = tmp[0]; switch (biu_config->osc_type) { case 0: dmd_config->f_sample = AF901x_FSAMPLE_28800; break; case 1: dmd_config->f_sample = AF901x_FSAMPLE_20480; break; case 2: dmd_config->f_sample = AF901x_FSAMPLE_28000; break; case 3: dmd_config->f_sample = AF901x_FSAMPLE_25000; break; default: err = -EINVAL; }; printk("%s: Found Xtal Oscillator with freq = %d kHz,\n will use the same frequency for the sampling rate as well.\n", __func__, biu_config->osc_freq); } /* Tuner type */ if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_TUNERID1, tmp))) { biu_config->tuner = tmp[0]; printk("%s: Tuner type = 0x%02X\n", __func__, biu_config->tuner); switch (biu_config->tuner) { case AF9015_TUNER_MT2060D: printk("%s: Found a MT2060 digital tuner\n", __func__); break; case AF9015_TUNER_MXL5003D: printk("%s: Found a MXL5003 digital tuner\n", __func__); break; case AF9015_TUNER_MXL5005H: printk("%s: Found a MXL5005 Hybrid tuner\n", __func__); break; default: printk("%s: Unknown tuner %d, please report\n", __func__, biu_config->tuner); err = -EINVAL; } } /* IF0 */ if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_IF1H, tmp))) biu_config->i_freq_0 = tmp[0]; if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_IF1L, tmp))) { dmd_config->i_freq_0 <<= 8; dmd_config->i_freq_0 |= tmp[0]; printk("%s: IF0 = %d\n",__func__, dmd_config->i_freq_0); } /* IF1 */ if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_IF2H, tmp))) biu_config->i_freq_1 = tmp[0]; if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_IF2L, tmp))) { biu_config->i_freq_1 <<= 8; biu_config->i_freq_1 |= tmp[0]; printk("%s: IF1 = %d\n", __func__, biu_config->i_freq_1); } /* MT2060 IF0 */ if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_MT2060_IF1H, tmp))) biu_config->i_freq_0 = tmp[0]; if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_MT2060_IF1L, tmp))) { biu_config->i_freq_0 <<= 8; biu_config->i_freq_0 |= tmp[0]; printk("%s: MT2060 IF0 = %d\n",__func__, biu_config->i_freq_0); } /* MT2060 IF1 */ if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_MT2060_IF2H, tmp))) biu_config->i_freq_1 = tmp[0]; if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_MT2060_IF2L, tmp))) { biu_config->i_freq_1 <<= 8; biu_config->i_freq_1 |= tmp[0]; printk("%s: MT2060 IF1 = %d\n", __func__, biu_config->i_freq_1); } /* Spectral inversion */ if (!(err = af9015_read_eeprom(biu->udev->udev, AF9015_CONFIG_ROM_IQINV1, tmp))) { dmd_config->inversion = tmp[0]; printk("%s: Spectral Inversion = 0x%02X\n", __func__, tmp[0]); } return 0; exit: printk("%s: BIU EEPROM read failed err=%d\n", __func__, err); return err; } static int af9015_read(struct i2c_adapter *v_bus, u16 reg, u8 *data) { return 0; } static int af9015_write(struct i2c_adapter *v_bus, u16 reg, u8 data) { return 0; } /* Mode 15 + 13 init config mode */ static int af9015_epconfig_mode_15(struct af901x_biu *biu) { struct i2c_adapter *v_bus = biu->adapter; /* Adapter 0 */ u8 reg, dual = 0; /* TODO! Must move out end point configuration from in here */ // if (state->config->usb_11) { /** NOTE BIU config */ // /** // * We need to put frame sizes and packet sizes // * based on USB mode, ie 1.1/2.0 // */ // } /* TS init */ af9015_read(v_bus, AF901x_MP2IF_2, ®); AF901x_SETFIELD(MP2IF_2_SW_RESET, reg, 1); /* 0xd507 assert EP4 Reset */ af9015_write(v_bus, AF901x_MP2IF_2, reg); af9015_read(v_bus, AF901x_MP2IF_3, ®); AF901x_SETFIELD(MP2IF_3_SWRST, reg, 1); /* 0xd50b assert EP5 reset */ af9015_write(v_bus, AF901x_MP2IF_3, reg); af9015_read(v_bus, AF901x_TX_ENABLE, ®); AF901x_SETFIELD(TX_ENABLE_EP4, reg, 0); /* 0xdd11 disable EP4 */ af9015_write(v_bus, AF901x_TX_ENABLE, reg); af9015_read(v_bus, AF901x_TX_ENABLE, ®); AF901x_SETFIELD(TX_ENABLE_EP5, reg, 0); /* 0xdd11 disable EP5 */ af9015_write(v_bus, AF901x_TX_ENABLE, reg); af9015_read(v_bus, AF901x_TX_ENABLE, ®); AF901x_SETFIELD(TX_ENABLE_EP4, reg, 1); /* 0xdd11 enable EP4 */ af9015_write(v_bus, AF901x_TX_ENABLE, reg); if (dual) { af9015_read(v_bus, AF901x_TX_ENABLE, ®); AF901x_SETFIELD(TX_ENABLE_EP5, reg, 1); /* 0xdd11 enable EP5 */ af9015_write(v_bus, AF901x_TX_ENABLE, reg); }else { af9015_read(v_bus, AF901x_TX_ENABLE, ®); AF901x_SETFIELD(TX_ENABLE_EP5, reg, 0); /* 0xdd11 disable EP5 */ af9015_write(v_bus, AF901x_TX_ENABLE, reg); } af9015_read(v_bus, AF901x_TX_NAK, ®); AF901x_SETFIELD(TX_NAK_EP4, reg, 0); /* disable EP4 NAK */ if (dual) AF901x_SETFIELD(TX_NAK_EP5, reg, 0); /* disable EP5 NAK */ af9015_write(v_bus, AF901x_TX_NAK, reg); af9015_read(v_bus, AF901x_MP2IF_0, ®); /* 0xd500 */ AF901x_SETFIELD(MP2IF_0_MPEG_PARALLEL, reg, 0); /* disable Parallel mode */ AF901x_SETFIELD(MP2IF_0_MPEG_SERIAL, reg, 0); /* disable Serial mode */ af9015_write(v_bus, AF901x_MP2IF_0, reg); if (dual) { af9015_read(v_bus, AF901x_MP2IF_0, ®); AF901x_SETFIELD(MP2IF_0_MPEG_SERIAL, reg, 1); af9015_write(v_bus, AF901x_MP2IF_0, reg); } af9015_read(v_bus, AF901x_TX_LEN_EP4_LSB, ®); /* EP4 transfer length */ AF901x_SETFIELD(TX_LEN_EP4_LSB, reg, (BYTE0(TX_LEN_EP4_LSB, AF9015_DEFAULT_TS_FRAME_SIZE))); af9015_write(v_bus, AF901x_TX_LEN_EP4_LSB, reg); af9015_read(v_bus, AF901x_TX_LEN_EP4_MSB, ®); AF901x_SETFIELD(TX_LEN_EP4_MSB, reg, (BYTE1(TX_LEN_EP4_MSB, AF9015_DEFAULT_TS_FRAME_SIZE))); af9015_write(v_bus, AF901x_TX_LEN_EP4_MSB, reg); if (dual) { af9015_read(v_bus, AF901x_TX_LEN_EP5_LSB, ®); /* EP5 transfer length */ AF901x_SETFIELD(TX_LEN_EP5_LSB, reg, (BYTE0(TX_LEN_EP5_LSB, AF9015_DEFAULT_TS_FRAME_SIZE))); af9015_write(v_bus, AF901x_TX_LEN_EP5_LSB, reg); af9015_read(v_bus, AF901x_TX_LEN_EP5_MSB, ®); AF901x_SETFIELD(TX_LEN_EP4_MSB, reg, (BYTE1(TX_LEN_EP5_MSB, AF9015_DEFAULT_TS_FRAME_SIZE))); af9015_write(v_bus, AF901x_TX_LEN_EP5_MSB, reg); } af9015_read(v_bus, AF901x_MAX_PACKET_EP4, ®); AF901x_SETFIELD(MAX_PACKET_EP4, reg, AF9015_DEFAULT_TS_PACKT_LEN); af9015_write(v_bus, AF901x_MAX_PACKET_EP4, reg); if (dual) { af9015_read(v_bus, AF901x_MAX_PACKET_EP5, ®); AF901x_SETFIELD(MAX_PACKET_EP5, reg, AF9015_DEFAULT_TS_PACKT_LEN); af9015_write(v_bus, AF901x_MAX_PACKET_EP5, reg); } if (dual) { /* enable MP2IF */ af9015_read(v_bus, AF901x_MP2IF_3, ®); AF901x_SETFIELD(MP2IF_3_EN, reg, 1); /* enable MP2IF */ af9015_write(v_bus, AF901x_MP2IF_3, reg); } else { af9015_read(v_bus, AF901x_MP2IF_3, ®); AF901x_SETFIELD(MP2IF_3_EN, reg, 0); /* disable MP2IF */ af9015_write(v_bus, AF901x_MP2IF_3, reg); } af9015_read(v_bus, AF901x_MP2IF_2, ®); AF901x_SETFIELD(MP2IF_2_SW_RESET, reg, 0); /* negate EP4 reset */ af9015_write(v_bus, AF901x_MP2IF_2, reg); af9015_read(v_bus, AF901x_MP2IF_3, ®); AF901x_SETFIELD(MP2IF_3_SWRST, reg, 0); /* negate EP5 reset */ af9015_write(v_bus, AF901x_MP2IF_3, reg); if (dual) { /* Set Serial output pin of 13 (data7) */ af9015_read(v_bus, AF901x_MP2IF_USB20, ®); /* change output bit to Data 7, for the AF9013 */ if (!(AF901x_GETFIELD(MP2IF_USB20_MODE, reg))) { af9015_read(v_bus, AF901x_MP2IF_0, ®); AF901x_SETFIELD(MP2IF_0_MPEG_SERIAL7, reg, 1); af9015_write(v_bus, AF901x_MP2IF_0, reg); } /* Split 9015 PSB to 1.5k + 0.5k, enable Flow Control */ af9015_read(v_bus, AF901x_MP2IF_3, ®); AF901x_SETFIELD(MP2IF_3_HALF_PSB, reg, 1); af9015_write(v_bus, AF901x_MP2IF_3, reg); af9015_read(v_bus, AF901x_TSPARAM, ®); AF901x_SETFIELD(TSPARAM_STOP_EN, reg, 1); af9015_write(v_bus, AF901x_TSPARAM, reg); af9015_read(v_bus, AF901x_MPEG_FULL_SPEED, ®); AF901x_SETFIELD(MPEG_FULL_SPEED, reg, 1); af9015_write(v_bus, AF901x_MPEG_FULL_SPEED, reg); } return 0; } /** * NOTE! Mode 17 config * * We don't use this mode on any PC based devices * For a specific consumer handheld device with a * MPEG2 decoder */ static int af9015_epconfig_mode_17(struct af901x_biu *biu) { struct i2c_adapter *v_bus = biu->adapter; /* Adapter 0 */ u8 reg; // if (state->config->usb_11) { /** NOTE BIU config */ // /** // * We need to put frame sizes and packet sizes // * based on USB mode, ie 1.1/2.0 // */ // } af9015_read(v_bus, AF901x_MP2IF_3, ®); AF901x_SETFIELD(MP2IF_3_SWRST, reg, 1); /* 0xd50b assert EP5 reset */ af9015_write(v_bus, AF901x_MP2IF_3, reg); af9015_read(v_bus, AF901x_TX_ENABLE, ®); AF901x_SETFIELD(TX_ENABLE_EP5, reg, 0); /* 0xdd11 disable EP5 */ af9015_write(v_bus, AF901x_TX_ENABLE, reg); af9015_read(v_bus, AF901x_TX_ENABLE, ®); AF901x_SETFIELD(TX_ENABLE_EP5, reg, 1); /* 0xdd11 enable EP5 */ af9015_write(v_bus, AF901x_TX_ENABLE, reg); af9015_read(v_bus, AF901x_TX_NAK, ®); AF901x_SETFIELD(TX_NAK_EP5, reg, 0); /* disable EP5 NAK */ af9015_write(v_bus, AF901x_TX_NAK, reg); af9015_read(v_bus, AF901x_TX_LEN_EP5_LSB, ®); /* EP5 transfer length */ AF901x_SETFIELD(TX_LEN_EP5_LSB, reg, (BYTE0(TX_LEN_EP5_LSB, AF9015_DEFAULT_TS_FRAME_SIZE))); af9015_write(v_bus, AF901x_TX_LEN_EP5_LSB, reg); af9015_read(v_bus, AF901x_TX_LEN_EP5_MSB, ®); AF901x_SETFIELD(TX_LEN_EP4_MSB, reg, (BYTE1(TX_LEN_EP5_MSB, AF9015_DEFAULT_TS_FRAME_SIZE))); af9015_write(v_bus, AF901x_TX_LEN_EP5_MSB, reg); af9015_read(v_bus, AF901x_MAX_PACKET_EP5, ®); AF901x_SETFIELD(MAX_PACKET_EP5, reg, AF9015_DEFAULT_TS_PACKT_LEN); af9015_write(v_bus, AF901x_MAX_PACKET_EP5, reg); af9015_read(v_bus, AF901x_MP2IF_0, ®); /* 0xd500 */ AF901x_SETFIELD(MP2IF_0_MPEG_SERIAL, reg, 1); /* enable Serial mode */ af9015_write(v_bus, AF901x_MP2IF_0, reg); af9015_read(v_bus, AF901x_MP2IF_0, ®); /* 0xd500 */ AF901x_SETFIELD(MP2IF_0_MPEG_PARALLEL, reg, 0); /* disable Parallel mode */ af9015_write(v_bus, AF901x_MP2IF_0, reg); /* enable MP2IF */ af9015_read(v_bus, AF901x_MP2IF_3, ®); AF901x_SETFIELD(MP2IF_3_EN, reg, 1); /* enable MP2IF */ af9015_write(v_bus, AF901x_MP2IF_3, reg); af9015_read(v_bus, AF901x_MP2IF_3, ®); AF901x_SETFIELD(MP2IF_3_SWRST, reg, 0); /* negate EP5 reset */ af9015_write(v_bus, AF901x_MP2IF_3, reg); return 0; } extern struct dvb_frontend *af901x_attach(struct i2c_adapter *i2c_adapter, struct af901x_config *config); static int af9015_frontend_attach(struct dvb_usb_adapter *adap) { int err = 0; struct af901x_biu *biu = adap->dev->priv; struct i2c_adapter *i2c = biu->adapter; struct af901x_config demod_config; biu->udev = adap->dev; /** * TODO! Loading defaults, depends on the config * no hardcoded values please */ demod_config.bandwidth = BANDWIDTH_6_MHZ; /** * TODO! *Bloody Hell !* It sucks to do like this * Need to do it in a better way, this is _crap_ */ //------------------------ printk("%s: Initializing I2C\n", __func__); af9015_i2c_init(biu); printk("%s: Retrieving BIU config\n", __func__); af9015_get_biu_config(biu, &demod_config); //------------------------ printk("%s: Attaching Master demodulator\n", __func__); if (!(adap->fe = af901x_attach(i2c, &demod_config))) { printk("%s: AF9015 MASTER demodulator attach failed. :-(\n\n \ This is a very unlikely case, so surely there is a bug\n \ some place. All the singing happens on the\n \ Linux DVB Mailing List \n \ Please join the chorus at Linux DVB. ;-)\n", __func__); err = -EIO; goto exit; } printk("%s: AF9015 Master demodulator successfully attached\n", __func__); /** * TODO! How do we attach multiple frontends in our circumstance ? * A bit lost in thoughts, atm. Ever thought about circles ? */ return 0; exit: printk("%s: Quite nasty indeed!\n", __func__); return err; } static int af901x_frontend_attach(struct dvb_usb_adapter *adap) { int err = 0; struct af901x_biu *biu = adap->dev->priv; struct i2c_adapter *i2c = biu->adapter; struct af901x_config demod_config; i2c++; /* Virtual world 1 */ /** * We already initialized I2C and as well * read the BIU config. What to do now ? */ printk("%s: Attaching Slave demodulator\n", __func__); if (!(adap->fe = af901x_attach(i2c, &demod_config))) { printk("%s: AF9015 SLAVE demodulator attach failed.\n", __func__); err = -EIO; goto exit; } printk("%s: AF901x SLAVE demodulator successfully attached\n", __func__); return 0; exit: printk("%s: Quite nasty indeed!\n", __func__); return err; } static struct dvb_usb_device_properties af9015_properties; static struct af9015_biuconfig_mode af9015_ref_pcusb_dev = { .biu_mode = AF9015_BIU_MODE_15, .usb_mode = AF9015_USB_MODE_20 /* TODO! add in demod and tuner I2C addresses */ }; // static struct af9015_biuconfig_mode af9015_azurewave_vp704j = { // .biu_mode = AF9015_BIU_MODE_15, // .usb_mode = AF9015_USB_MODE_20 // /* TODO! add in demod and tuner I2C addresses */ // }; static int af9015_biu_epconfig(struct af901x_biu *biu) { int err = 0; struct af9015_biuconfig_mode *biuconfig_mode = &biu->config_mode; /* TODO! Need to do this conditionally for each device based on ID's */ memcpy(&biuconfig_mode, &af9015_ref_pcusb_dev, sizeof (struct af9015_biuconfig_mode)); switch (biuconfig_mode->biu_mode) { case AF9015_BIU_MODE_15: printk("%s: Using MODE 15\n", __func__); af9015_epconfig_mode_15(biu); break; case AF9015_BIU_MODE_17: printk("%s: Using MODE 17\n", __func__); af9015_epconfig_mode_17(biu); break; default: err = -EINVAL; break; } return err; } static int af9015_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { int err; struct dvb_usb_device *dev; struct af901x_biu *biu; printk("%s: probing for a AF9015\n", __func__); if ((err = dvb_usb_device_init(intf, &af9015_properties, THIS_MODULE, &dev))) printk("%s error %d\n", __FUNCTION__, err); dev = usb_get_intfdata(intf); // biu = dev->priv; // biu->udev = dev; // // printk("%s: Initializing I2C\n", __func__); // af9015_i2c_init(biu); // printk("%s: Retrieving BIU config\n", __func__); // af9015_get_biu_config(biu); // printk("%s: Initializing BIU\n", __func__); // af9015_biu_epconfig(biu); return err; } static void af9015_usb_device_exit(struct usb_interface *intf) { struct af901x_biu *biu; struct dvb_usb_device *dev = usb_get_intfdata(intf); biu = dev->priv; biu->udev = dev; af9015_i2c_exit(biu); dvb_usb_device_exit(intf); } static struct usb_device_id af9015_usb_table[] = { { USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015) }, { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_VP704J) }, { 0 }, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); static struct dvb_usb_device_properties af9015_properties = { .firmware = "dvb-usb-af9015.fw", .download_firmware = af901x_fw_download, .size_of_priv = sizeof (struct af901x_biu), .no_reconnect = 1, .num_adapters = 1, .adapter = { { .frontend_attach = af9015_frontend_attach, .stream = { .type = USB_BULK, .count = 4, .endpoint = 0x84, .u = { .bulk = { .buffersize = 4096, /* actual size seen is 3948 */ } } }, } }, .num_device_descs = 1, .devices = { { .name = "Afatech 9015 DVB-T", .cold_ids = { af9015_usb_table, NULL }, .warm_ids = { NULL }, },{ NULL }, } }; static struct usb_driver af9015_driver = { #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15) .owner = THIS_MODULE, #endif .name = "dvb-usb-af9015", .probe = af9015_usb_probe, .disconnect = af9015_usb_device_exit, .id_table = af9015_usb_table, }; static int __init af9015_init(void) { int result; printk("%s: Initializing AF9015\n", __func__); if ((result = usb_register(&af9015_driver))) { err("usb_register failed. (%d)", result); return result; } return 0; } static void __exit af9015_exit(void) { printk("%s: AF9015 exiting\n", __func__); usb_deregister(&af9015_driver); } module_init(af9015_init); module_exit(af9015_exit); MODULE_AUTHOR("Manu Abraham "); MODULE_DESCRIPTION("AF9015 DVB-T"); MODULE_LICENSE("GPL");