13c4e0415SDaniel Scheller /* 23c4e0415SDaniel Scheller * Driver for the MaxLinear MxL5xx family of tuners/demods 33c4e0415SDaniel Scheller * 43c4e0415SDaniel Scheller * Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de> 53c4e0415SDaniel Scheller * Marcus Metzler <mocm@metzlerbros.de> 63c4e0415SDaniel Scheller * developed for Digital Devices GmbH 73c4e0415SDaniel Scheller * 83c4e0415SDaniel Scheller * based on code: 93c4e0415SDaniel Scheller * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved 103c4e0415SDaniel Scheller * which was released under GPL V2 113c4e0415SDaniel Scheller * 123c4e0415SDaniel Scheller * This program is free software; you can redistribute it and/or 133c4e0415SDaniel Scheller * modify it under the terms of the GNU General Public License 143c4e0415SDaniel Scheller * version 2, as published by the Free Software Foundation. 153c4e0415SDaniel Scheller * 163c4e0415SDaniel Scheller * This program is distributed in the hope that it will be useful, 173c4e0415SDaniel Scheller * but WITHOUT ANY WARRANTY; without even the implied warranty of 183c4e0415SDaniel Scheller * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 193c4e0415SDaniel Scheller * GNU General Public License for more details. 203c4e0415SDaniel Scheller * 213c4e0415SDaniel Scheller */ 223c4e0415SDaniel Scheller 233c4e0415SDaniel Scheller #include <linux/kernel.h> 243c4e0415SDaniel Scheller #include <linux/module.h> 253c4e0415SDaniel Scheller #include <linux/moduleparam.h> 263c4e0415SDaniel Scheller #include <linux/init.h> 273c4e0415SDaniel Scheller #include <linux/delay.h> 283c4e0415SDaniel Scheller #include <linux/firmware.h> 293c4e0415SDaniel Scheller #include <linux/i2c.h> 303c4e0415SDaniel Scheller #include <linux/version.h> 313c4e0415SDaniel Scheller #include <linux/mutex.h> 323c4e0415SDaniel Scheller #include <linux/vmalloc.h> 333c4e0415SDaniel Scheller #include <asm/div64.h> 343c4e0415SDaniel Scheller #include <asm/unaligned.h> 353c4e0415SDaniel Scheller 36fada1935SMauro Carvalho Chehab #include <media/dvb_frontend.h> 373c4e0415SDaniel Scheller #include "mxl5xx.h" 383c4e0415SDaniel Scheller #include "mxl5xx_regs.h" 393c4e0415SDaniel Scheller #include "mxl5xx_defs.h" 403c4e0415SDaniel Scheller 413c4e0415SDaniel Scheller #define BYTE0(v) ((v >> 0) & 0xff) 423c4e0415SDaniel Scheller #define BYTE1(v) ((v >> 8) & 0xff) 433c4e0415SDaniel Scheller #define BYTE2(v) ((v >> 16) & 0xff) 443c4e0415SDaniel Scheller #define BYTE3(v) ((v >> 24) & 0xff) 453c4e0415SDaniel Scheller 46f71c4306SDaniel Scheller static LIST_HEAD(mxllist); 473c4e0415SDaniel Scheller 483c4e0415SDaniel Scheller struct mxl_base { 493c4e0415SDaniel Scheller struct list_head mxllist; 503c4e0415SDaniel Scheller struct list_head mxls; 513c4e0415SDaniel Scheller 523c4e0415SDaniel Scheller u8 adr; 533c4e0415SDaniel Scheller struct i2c_adapter *i2c; 543c4e0415SDaniel Scheller 553c4e0415SDaniel Scheller u32 count; 563c4e0415SDaniel Scheller u32 type; 573c4e0415SDaniel Scheller u32 sku_type; 583c4e0415SDaniel Scheller u32 chipversion; 593c4e0415SDaniel Scheller u32 clock; 603c4e0415SDaniel Scheller u32 fwversion; 613c4e0415SDaniel Scheller 623c4e0415SDaniel Scheller u8 *ts_map; 633c4e0415SDaniel Scheller u8 can_clkout; 643c4e0415SDaniel Scheller u8 chan_bond; 653c4e0415SDaniel Scheller u8 demod_num; 663c4e0415SDaniel Scheller u8 tuner_num; 673c4e0415SDaniel Scheller 683c4e0415SDaniel Scheller unsigned long next_tune; 693c4e0415SDaniel Scheller 703c4e0415SDaniel Scheller struct mutex i2c_lock; 713c4e0415SDaniel Scheller struct mutex status_lock; 723c4e0415SDaniel Scheller struct mutex tune_lock; 733c4e0415SDaniel Scheller 743c4e0415SDaniel Scheller u8 buf[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; 753c4e0415SDaniel Scheller 763c4e0415SDaniel Scheller u32 cmd_size; 773c4e0415SDaniel Scheller u8 cmd_data[MAX_CMD_DATA]; 783c4e0415SDaniel Scheller }; 793c4e0415SDaniel Scheller 803c4e0415SDaniel Scheller struct mxl { 813c4e0415SDaniel Scheller struct list_head mxl; 823c4e0415SDaniel Scheller 833c4e0415SDaniel Scheller struct mxl_base *base; 843c4e0415SDaniel Scheller struct dvb_frontend fe; 853c4e0415SDaniel Scheller struct device *i2cdev; 863c4e0415SDaniel Scheller u32 demod; 873c4e0415SDaniel Scheller u32 tuner; 883c4e0415SDaniel Scheller u32 tuner_in_use; 893c4e0415SDaniel Scheller u8 xbar[3]; 903c4e0415SDaniel Scheller 913c4e0415SDaniel Scheller unsigned long tune_time; 923c4e0415SDaniel Scheller }; 933c4e0415SDaniel Scheller 943c4e0415SDaniel Scheller static void convert_endian(u8 flag, u32 size, u8 *d) 953c4e0415SDaniel Scheller { 963c4e0415SDaniel Scheller u32 i; 973c4e0415SDaniel Scheller 983c4e0415SDaniel Scheller if (!flag) 993c4e0415SDaniel Scheller return; 1003c4e0415SDaniel Scheller for (i = 0; i < (size & ~3); i += 4) { 1013c4e0415SDaniel Scheller d[i + 0] ^= d[i + 3]; 1023c4e0415SDaniel Scheller d[i + 3] ^= d[i + 0]; 1033c4e0415SDaniel Scheller d[i + 0] ^= d[i + 3]; 1043c4e0415SDaniel Scheller 1053c4e0415SDaniel Scheller d[i + 1] ^= d[i + 2]; 1063c4e0415SDaniel Scheller d[i + 2] ^= d[i + 1]; 1073c4e0415SDaniel Scheller d[i + 1] ^= d[i + 2]; 1083c4e0415SDaniel Scheller } 1093c4e0415SDaniel Scheller 1103c4e0415SDaniel Scheller switch (size & 3) { 1113c4e0415SDaniel Scheller case 0: 1123c4e0415SDaniel Scheller case 1: 1133c4e0415SDaniel Scheller /* do nothing */ 1143c4e0415SDaniel Scheller break; 1153c4e0415SDaniel Scheller case 2: 1163c4e0415SDaniel Scheller d[i + 0] ^= d[i + 1]; 1173c4e0415SDaniel Scheller d[i + 1] ^= d[i + 0]; 1183c4e0415SDaniel Scheller d[i + 0] ^= d[i + 1]; 1193c4e0415SDaniel Scheller break; 1203c4e0415SDaniel Scheller 1213c4e0415SDaniel Scheller case 3: 1223c4e0415SDaniel Scheller d[i + 0] ^= d[i + 2]; 1233c4e0415SDaniel Scheller d[i + 2] ^= d[i + 0]; 1243c4e0415SDaniel Scheller d[i + 0] ^= d[i + 2]; 1253c4e0415SDaniel Scheller break; 1263c4e0415SDaniel Scheller } 1273c4e0415SDaniel Scheller 1283c4e0415SDaniel Scheller } 1293c4e0415SDaniel Scheller 1303c4e0415SDaniel Scheller static int i2c_write(struct i2c_adapter *adap, u8 adr, 1313c4e0415SDaniel Scheller u8 *data, u32 len) 1323c4e0415SDaniel Scheller { 1333c4e0415SDaniel Scheller struct i2c_msg msg = {.addr = adr, .flags = 0, 1343c4e0415SDaniel Scheller .buf = data, .len = len}; 1353c4e0415SDaniel Scheller 1363c4e0415SDaniel Scheller return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; 1373c4e0415SDaniel Scheller } 1383c4e0415SDaniel Scheller 1393c4e0415SDaniel Scheller static int i2c_read(struct i2c_adapter *adap, u8 adr, 1403c4e0415SDaniel Scheller u8 *data, u32 len) 1413c4e0415SDaniel Scheller { 1423c4e0415SDaniel Scheller struct i2c_msg msg = {.addr = adr, .flags = I2C_M_RD, 1433c4e0415SDaniel Scheller .buf = data, .len = len}; 1443c4e0415SDaniel Scheller 1453c4e0415SDaniel Scheller return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; 1463c4e0415SDaniel Scheller } 1473c4e0415SDaniel Scheller 1483c4e0415SDaniel Scheller static int i2cread(struct mxl *state, u8 *data, int len) 1493c4e0415SDaniel Scheller { 1503c4e0415SDaniel Scheller return i2c_read(state->base->i2c, state->base->adr, data, len); 1513c4e0415SDaniel Scheller } 1523c4e0415SDaniel Scheller 1533c4e0415SDaniel Scheller static int i2cwrite(struct mxl *state, u8 *data, int len) 1543c4e0415SDaniel Scheller { 1553c4e0415SDaniel Scheller return i2c_write(state->base->i2c, state->base->adr, data, len); 1563c4e0415SDaniel Scheller } 1573c4e0415SDaniel Scheller 1583c4e0415SDaniel Scheller static int read_register_unlocked(struct mxl *state, u32 reg, u32 *val) 1593c4e0415SDaniel Scheller { 1603c4e0415SDaniel Scheller int stat; 1613c4e0415SDaniel Scheller u8 data[MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE] = { 1623c4e0415SDaniel Scheller MXL_HYDRA_PLID_REG_READ, 0x04, 1633c4e0415SDaniel Scheller GET_BYTE(reg, 0), GET_BYTE(reg, 1), 1643c4e0415SDaniel Scheller GET_BYTE(reg, 2), GET_BYTE(reg, 3), 1653c4e0415SDaniel Scheller }; 1663c4e0415SDaniel Scheller 1673c4e0415SDaniel Scheller stat = i2cwrite(state, data, 1683c4e0415SDaniel Scheller MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE); 1693c4e0415SDaniel Scheller if (stat) 1703c4e0415SDaniel Scheller dev_err(state->i2cdev, "i2c read error 1\n"); 1713c4e0415SDaniel Scheller if (!stat) 1723c4e0415SDaniel Scheller stat = i2cread(state, (u8 *) val, 1733c4e0415SDaniel Scheller MXL_HYDRA_REG_SIZE_IN_BYTES); 1743c4e0415SDaniel Scheller le32_to_cpus(val); 1753c4e0415SDaniel Scheller if (stat) 1763c4e0415SDaniel Scheller dev_err(state->i2cdev, "i2c read error 2\n"); 1773c4e0415SDaniel Scheller return stat; 1783c4e0415SDaniel Scheller } 1793c4e0415SDaniel Scheller 1803c4e0415SDaniel Scheller #define DMA_I2C_INTERRUPT_ADDR 0x8000011C 1813c4e0415SDaniel Scheller #define DMA_INTR_PROT_WR_CMP 0x08 1823c4e0415SDaniel Scheller 1833c4e0415SDaniel Scheller static int send_command(struct mxl *state, u32 size, u8 *buf) 1843c4e0415SDaniel Scheller { 1853c4e0415SDaniel Scheller int stat; 1863c4e0415SDaniel Scheller u32 val, count = 10; 1873c4e0415SDaniel Scheller 1883c4e0415SDaniel Scheller mutex_lock(&state->base->i2c_lock); 1893c4e0415SDaniel Scheller if (state->base->fwversion > 0x02010109) { 1903c4e0415SDaniel Scheller read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR, &val); 1913c4e0415SDaniel Scheller if (DMA_INTR_PROT_WR_CMP & val) 1923c4e0415SDaniel Scheller dev_info(state->i2cdev, "%s busy\n", __func__); 1933c4e0415SDaniel Scheller while ((DMA_INTR_PROT_WR_CMP & val) && --count) { 1943c4e0415SDaniel Scheller mutex_unlock(&state->base->i2c_lock); 1953c4e0415SDaniel Scheller usleep_range(1000, 2000); 1963c4e0415SDaniel Scheller mutex_lock(&state->base->i2c_lock); 1973c4e0415SDaniel Scheller read_register_unlocked(state, DMA_I2C_INTERRUPT_ADDR, 1983c4e0415SDaniel Scheller &val); 1993c4e0415SDaniel Scheller } 2003c4e0415SDaniel Scheller if (!count) { 2013c4e0415SDaniel Scheller dev_info(state->i2cdev, "%s busy\n", __func__); 2023c4e0415SDaniel Scheller mutex_unlock(&state->base->i2c_lock); 2033c4e0415SDaniel Scheller return -EBUSY; 2043c4e0415SDaniel Scheller } 2053c4e0415SDaniel Scheller } 2063c4e0415SDaniel Scheller stat = i2cwrite(state, buf, size); 2073c4e0415SDaniel Scheller mutex_unlock(&state->base->i2c_lock); 2083c4e0415SDaniel Scheller return stat; 2093c4e0415SDaniel Scheller } 2103c4e0415SDaniel Scheller 2113c4e0415SDaniel Scheller static int write_register(struct mxl *state, u32 reg, u32 val) 2123c4e0415SDaniel Scheller { 2133c4e0415SDaniel Scheller int stat; 2143c4e0415SDaniel Scheller u8 data[MXL_HYDRA_REG_WRITE_LEN] = { 2153c4e0415SDaniel Scheller MXL_HYDRA_PLID_REG_WRITE, 0x08, 2163c4e0415SDaniel Scheller BYTE0(reg), BYTE1(reg), BYTE2(reg), BYTE3(reg), 2173c4e0415SDaniel Scheller BYTE0(val), BYTE1(val), BYTE2(val), BYTE3(val), 2183c4e0415SDaniel Scheller }; 2193c4e0415SDaniel Scheller mutex_lock(&state->base->i2c_lock); 2203c4e0415SDaniel Scheller stat = i2cwrite(state, data, sizeof(data)); 2213c4e0415SDaniel Scheller mutex_unlock(&state->base->i2c_lock); 2223c4e0415SDaniel Scheller if (stat) 2233c4e0415SDaniel Scheller dev_err(state->i2cdev, "i2c write error\n"); 2243c4e0415SDaniel Scheller return stat; 2253c4e0415SDaniel Scheller } 2263c4e0415SDaniel Scheller 2273c4e0415SDaniel Scheller static int write_firmware_block(struct mxl *state, 2283c4e0415SDaniel Scheller u32 reg, u32 size, u8 *reg_data_ptr) 2293c4e0415SDaniel Scheller { 2303c4e0415SDaniel Scheller int stat; 2313c4e0415SDaniel Scheller u8 *buf = state->base->buf; 2323c4e0415SDaniel Scheller 2333c4e0415SDaniel Scheller mutex_lock(&state->base->i2c_lock); 2343c4e0415SDaniel Scheller buf[0] = MXL_HYDRA_PLID_REG_WRITE; 2353c4e0415SDaniel Scheller buf[1] = size + 4; 2363c4e0415SDaniel Scheller buf[2] = GET_BYTE(reg, 0); 2373c4e0415SDaniel Scheller buf[3] = GET_BYTE(reg, 1); 2383c4e0415SDaniel Scheller buf[4] = GET_BYTE(reg, 2); 2393c4e0415SDaniel Scheller buf[5] = GET_BYTE(reg, 3); 2403c4e0415SDaniel Scheller memcpy(&buf[6], reg_data_ptr, size); 2413c4e0415SDaniel Scheller stat = i2cwrite(state, buf, 2423c4e0415SDaniel Scheller MXL_HYDRA_I2C_HDR_SIZE + 2433c4e0415SDaniel Scheller MXL_HYDRA_REG_SIZE_IN_BYTES + size); 2443c4e0415SDaniel Scheller mutex_unlock(&state->base->i2c_lock); 2453c4e0415SDaniel Scheller if (stat) 2463c4e0415SDaniel Scheller dev_err(state->i2cdev, "fw block write failed\n"); 2473c4e0415SDaniel Scheller return stat; 2483c4e0415SDaniel Scheller } 2493c4e0415SDaniel Scheller 2503c4e0415SDaniel Scheller static int read_register(struct mxl *state, u32 reg, u32 *val) 2513c4e0415SDaniel Scheller { 2523c4e0415SDaniel Scheller int stat; 2533c4e0415SDaniel Scheller u8 data[MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE] = { 2543c4e0415SDaniel Scheller MXL_HYDRA_PLID_REG_READ, 0x04, 2553c4e0415SDaniel Scheller GET_BYTE(reg, 0), GET_BYTE(reg, 1), 2563c4e0415SDaniel Scheller GET_BYTE(reg, 2), GET_BYTE(reg, 3), 2573c4e0415SDaniel Scheller }; 2583c4e0415SDaniel Scheller 2593c4e0415SDaniel Scheller mutex_lock(&state->base->i2c_lock); 2603c4e0415SDaniel Scheller stat = i2cwrite(state, data, 2613c4e0415SDaniel Scheller MXL_HYDRA_REG_SIZE_IN_BYTES + MXL_HYDRA_I2C_HDR_SIZE); 2623c4e0415SDaniel Scheller if (stat) 2633c4e0415SDaniel Scheller dev_err(state->i2cdev, "i2c read error 1\n"); 2643c4e0415SDaniel Scheller if (!stat) 2653c4e0415SDaniel Scheller stat = i2cread(state, (u8 *) val, 2663c4e0415SDaniel Scheller MXL_HYDRA_REG_SIZE_IN_BYTES); 2673c4e0415SDaniel Scheller mutex_unlock(&state->base->i2c_lock); 2683c4e0415SDaniel Scheller le32_to_cpus(val); 2693c4e0415SDaniel Scheller if (stat) 2703c4e0415SDaniel Scheller dev_err(state->i2cdev, "i2c read error 2\n"); 2713c4e0415SDaniel Scheller return stat; 2723c4e0415SDaniel Scheller } 2733c4e0415SDaniel Scheller 2743c4e0415SDaniel Scheller static int read_register_block(struct mxl *state, u32 reg, u32 size, u8 *data) 2753c4e0415SDaniel Scheller { 2763c4e0415SDaniel Scheller int stat; 2773c4e0415SDaniel Scheller u8 *buf = state->base->buf; 2783c4e0415SDaniel Scheller 2793c4e0415SDaniel Scheller mutex_lock(&state->base->i2c_lock); 2803c4e0415SDaniel Scheller 2813c4e0415SDaniel Scheller buf[0] = MXL_HYDRA_PLID_REG_READ; 2823c4e0415SDaniel Scheller buf[1] = size + 4; 2833c4e0415SDaniel Scheller buf[2] = GET_BYTE(reg, 0); 2843c4e0415SDaniel Scheller buf[3] = GET_BYTE(reg, 1); 2853c4e0415SDaniel Scheller buf[4] = GET_BYTE(reg, 2); 2863c4e0415SDaniel Scheller buf[5] = GET_BYTE(reg, 3); 2873c4e0415SDaniel Scheller stat = i2cwrite(state, buf, 2883c4e0415SDaniel Scheller MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES); 2893c4e0415SDaniel Scheller if (!stat) { 2903c4e0415SDaniel Scheller stat = i2cread(state, data, size); 2913c4e0415SDaniel Scheller convert_endian(MXL_ENABLE_BIG_ENDIAN, size, data); 2923c4e0415SDaniel Scheller } 2933c4e0415SDaniel Scheller mutex_unlock(&state->base->i2c_lock); 2943c4e0415SDaniel Scheller return stat; 2953c4e0415SDaniel Scheller } 2963c4e0415SDaniel Scheller 2973c4e0415SDaniel Scheller static int read_by_mnemonic(struct mxl *state, 2983c4e0415SDaniel Scheller u32 reg, u8 lsbloc, u8 numofbits, u32 *val) 2993c4e0415SDaniel Scheller { 3003c4e0415SDaniel Scheller u32 data = 0, mask = 0; 3013c4e0415SDaniel Scheller int stat; 3023c4e0415SDaniel Scheller 3033c4e0415SDaniel Scheller stat = read_register(state, reg, &data); 3043c4e0415SDaniel Scheller if (stat) 3053c4e0415SDaniel Scheller return stat; 3063c4e0415SDaniel Scheller mask = MXL_GET_REG_MASK_32(lsbloc, numofbits); 3073c4e0415SDaniel Scheller data &= mask; 3083c4e0415SDaniel Scheller data >>= lsbloc; 3093c4e0415SDaniel Scheller *val = data; 3103c4e0415SDaniel Scheller return 0; 3113c4e0415SDaniel Scheller } 3123c4e0415SDaniel Scheller 3133c4e0415SDaniel Scheller 3143c4e0415SDaniel Scheller static int update_by_mnemonic(struct mxl *state, 3153c4e0415SDaniel Scheller u32 reg, u8 lsbloc, u8 numofbits, u32 val) 3163c4e0415SDaniel Scheller { 3173c4e0415SDaniel Scheller u32 data, mask; 3183c4e0415SDaniel Scheller int stat; 3193c4e0415SDaniel Scheller 3203c4e0415SDaniel Scheller stat = read_register(state, reg, &data); 3213c4e0415SDaniel Scheller if (stat) 3223c4e0415SDaniel Scheller return stat; 3233c4e0415SDaniel Scheller mask = MXL_GET_REG_MASK_32(lsbloc, numofbits); 3243c4e0415SDaniel Scheller data = (data & ~mask) | ((val << lsbloc) & mask); 3253c4e0415SDaniel Scheller stat = write_register(state, reg, data); 3263c4e0415SDaniel Scheller return stat; 3273c4e0415SDaniel Scheller } 3283c4e0415SDaniel Scheller 3293c4e0415SDaniel Scheller static int firmware_is_alive(struct mxl *state) 3303c4e0415SDaniel Scheller { 3313c4e0415SDaniel Scheller u32 hb0, hb1; 3323c4e0415SDaniel Scheller 3333c4e0415SDaniel Scheller if (read_register(state, HYDRA_HEAR_BEAT, &hb0)) 3343c4e0415SDaniel Scheller return 0; 3353c4e0415SDaniel Scheller msleep(20); 3363c4e0415SDaniel Scheller if (read_register(state, HYDRA_HEAR_BEAT, &hb1)) 3373c4e0415SDaniel Scheller return 0; 3383c4e0415SDaniel Scheller if (hb1 == hb0) 3393c4e0415SDaniel Scheller return 0; 3403c4e0415SDaniel Scheller return 1; 3413c4e0415SDaniel Scheller } 3423c4e0415SDaniel Scheller 3433c4e0415SDaniel Scheller static int init(struct dvb_frontend *fe) 3443c4e0415SDaniel Scheller { 3453c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 3463c4e0415SDaniel Scheller 3473c4e0415SDaniel Scheller /* init fe stats */ 3483c4e0415SDaniel Scheller p->strength.len = 1; 3493c4e0415SDaniel Scheller p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3503c4e0415SDaniel Scheller p->cnr.len = 1; 3513c4e0415SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3523c4e0415SDaniel Scheller p->pre_bit_error.len = 1; 3533c4e0415SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3543c4e0415SDaniel Scheller p->pre_bit_count.len = 1; 3553c4e0415SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3563c4e0415SDaniel Scheller p->post_bit_error.len = 1; 3573c4e0415SDaniel Scheller p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3583c4e0415SDaniel Scheller p->post_bit_count.len = 1; 3593c4e0415SDaniel Scheller p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 3603c4e0415SDaniel Scheller 3613c4e0415SDaniel Scheller return 0; 3623c4e0415SDaniel Scheller } 3633c4e0415SDaniel Scheller 3643c4e0415SDaniel Scheller static void release(struct dvb_frontend *fe) 3653c4e0415SDaniel Scheller { 3663c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 3673c4e0415SDaniel Scheller 3683c4e0415SDaniel Scheller list_del(&state->mxl); 3693c4e0415SDaniel Scheller /* Release one frontend, two more shall take its place! */ 3703c4e0415SDaniel Scheller state->base->count--; 3713c4e0415SDaniel Scheller if (state->base->count == 0) { 3723c4e0415SDaniel Scheller list_del(&state->base->mxllist); 3733c4e0415SDaniel Scheller kfree(state->base); 3743c4e0415SDaniel Scheller } 3753c4e0415SDaniel Scheller kfree(state); 3763c4e0415SDaniel Scheller } 3773c4e0415SDaniel Scheller 378*8d718e53SLuc Van Oostenryck static enum dvbfe_algo get_algo(struct dvb_frontend *fe) 3793c4e0415SDaniel Scheller { 3803c4e0415SDaniel Scheller return DVBFE_ALGO_HW; 3813c4e0415SDaniel Scheller } 3823c4e0415SDaniel Scheller 38362474660SDaniel Scheller static u32 gold2root(u32 gold) 38462474660SDaniel Scheller { 38562474660SDaniel Scheller u32 x, g, tmp = gold; 38662474660SDaniel Scheller 38762474660SDaniel Scheller if (tmp >= 0x3ffff) 38862474660SDaniel Scheller tmp = 0; 38962474660SDaniel Scheller for (g = 0, x = 1; g < tmp; g++) 39062474660SDaniel Scheller x = (((x ^ (x >> 7)) & 1) << 17) | (x >> 1); 39162474660SDaniel Scheller return x; 39262474660SDaniel Scheller } 39362474660SDaniel Scheller 39462474660SDaniel Scheller static int cfg_scrambler(struct mxl *state, u32 gold) 39562474660SDaniel Scheller { 39662474660SDaniel Scheller u32 root; 39762474660SDaniel Scheller u8 buf[26] = { 39862474660SDaniel Scheller MXL_HYDRA_PLID_CMD_WRITE, 24, 39962474660SDaniel Scheller 0, MXL_HYDRA_DEMOD_SCRAMBLE_CODE_CMD, 0, 0, 40062474660SDaniel Scheller state->demod, 0, 0, 0, 40162474660SDaniel Scheller 0, 0, 0, 0, 0, 0, 0, 0, 40262474660SDaniel Scheller 0, 0, 0, 0, 1, 0, 0, 0, 40362474660SDaniel Scheller }; 40462474660SDaniel Scheller 40562474660SDaniel Scheller root = gold2root(gold); 40662474660SDaniel Scheller 40762474660SDaniel Scheller buf[25] = (root >> 24) & 0xff; 40862474660SDaniel Scheller buf[24] = (root >> 16) & 0xff; 40962474660SDaniel Scheller buf[23] = (root >> 8) & 0xff; 41062474660SDaniel Scheller buf[22] = root & 0xff; 41162474660SDaniel Scheller 41262474660SDaniel Scheller return send_command(state, sizeof(buf), buf); 41362474660SDaniel Scheller } 41462474660SDaniel Scheller 4153c4e0415SDaniel Scheller static int cfg_demod_abort_tune(struct mxl *state) 4163c4e0415SDaniel Scheller { 4173c4e0415SDaniel Scheller struct MXL_HYDRA_DEMOD_ABORT_TUNE_T abort_tune_cmd; 4183c4e0415SDaniel Scheller u8 cmd_size = sizeof(abort_tune_cmd); 4193c4e0415SDaniel Scheller u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; 4203c4e0415SDaniel Scheller 4213c4e0415SDaniel Scheller abort_tune_cmd.demod_id = state->demod; 4223c4e0415SDaniel Scheller BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE, 4233c4e0415SDaniel Scheller cmd_size, &abort_tune_cmd, cmd_buff); 4243c4e0415SDaniel Scheller return send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, 4253c4e0415SDaniel Scheller &cmd_buff[0]); 4263c4e0415SDaniel Scheller } 4273c4e0415SDaniel Scheller 4283c4e0415SDaniel Scheller static int send_master_cmd(struct dvb_frontend *fe, 4293c4e0415SDaniel Scheller struct dvb_diseqc_master_cmd *cmd) 4303c4e0415SDaniel Scheller { 4313c4e0415SDaniel Scheller /*struct mxl *state = fe->demodulator_priv;*/ 4323c4e0415SDaniel Scheller 4333c4e0415SDaniel Scheller return 0; /*CfgDemodAbortTune(state);*/ 4343c4e0415SDaniel Scheller } 4353c4e0415SDaniel Scheller 4363c4e0415SDaniel Scheller static int set_parameters(struct dvb_frontend *fe) 4373c4e0415SDaniel Scheller { 4383c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 4393c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 4403c4e0415SDaniel Scheller struct MXL_HYDRA_DEMOD_PARAM_T demod_chan_cfg; 4413c4e0415SDaniel Scheller u8 cmd_size = sizeof(demod_chan_cfg); 4423c4e0415SDaniel Scheller u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; 4433c4e0415SDaniel Scheller u32 srange = 10; 4443c4e0415SDaniel Scheller int stat; 4453c4e0415SDaniel Scheller 4463c4e0415SDaniel Scheller if (p->frequency < 950000 || p->frequency > 2150000) 4473c4e0415SDaniel Scheller return -EINVAL; 4483c4e0415SDaniel Scheller if (p->symbol_rate < 1000000 || p->symbol_rate > 45000000) 4493c4e0415SDaniel Scheller return -EINVAL; 4503c4e0415SDaniel Scheller 4513c4e0415SDaniel Scheller /* CfgDemodAbortTune(state); */ 4523c4e0415SDaniel Scheller 4533c4e0415SDaniel Scheller switch (p->delivery_system) { 4543c4e0415SDaniel Scheller case SYS_DSS: 4553c4e0415SDaniel Scheller demod_chan_cfg.standard = MXL_HYDRA_DSS; 4563c4e0415SDaniel Scheller demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_AUTO; 4573c4e0415SDaniel Scheller break; 4583c4e0415SDaniel Scheller case SYS_DVBS: 4593c4e0415SDaniel Scheller srange = p->symbol_rate / 1000000; 4603c4e0415SDaniel Scheller if (srange > 10) 4613c4e0415SDaniel Scheller srange = 10; 4623c4e0415SDaniel Scheller demod_chan_cfg.standard = MXL_HYDRA_DVBS; 4633c4e0415SDaniel Scheller demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_0_35; 4643c4e0415SDaniel Scheller demod_chan_cfg.modulation_scheme = MXL_HYDRA_MOD_QPSK; 4653c4e0415SDaniel Scheller demod_chan_cfg.pilots = MXL_HYDRA_PILOTS_OFF; 4663c4e0415SDaniel Scheller break; 4673c4e0415SDaniel Scheller case SYS_DVBS2: 4683c4e0415SDaniel Scheller demod_chan_cfg.standard = MXL_HYDRA_DVBS2; 4693c4e0415SDaniel Scheller demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_AUTO; 4703c4e0415SDaniel Scheller demod_chan_cfg.modulation_scheme = MXL_HYDRA_MOD_AUTO; 4713c4e0415SDaniel Scheller demod_chan_cfg.pilots = MXL_HYDRA_PILOTS_AUTO; 47262474660SDaniel Scheller cfg_scrambler(state, p->scrambling_sequence_index); 4733c4e0415SDaniel Scheller break; 4743c4e0415SDaniel Scheller default: 4753c4e0415SDaniel Scheller return -EINVAL; 4763c4e0415SDaniel Scheller } 4773c4e0415SDaniel Scheller demod_chan_cfg.tuner_index = state->tuner; 4783c4e0415SDaniel Scheller demod_chan_cfg.demod_index = state->demod; 4793c4e0415SDaniel Scheller demod_chan_cfg.frequency_in_hz = p->frequency * 1000; 4803c4e0415SDaniel Scheller demod_chan_cfg.symbol_rate_in_hz = p->symbol_rate; 4813c4e0415SDaniel Scheller demod_chan_cfg.max_carrier_offset_in_mhz = srange; 4823c4e0415SDaniel Scheller demod_chan_cfg.spectrum_inversion = MXL_HYDRA_SPECTRUM_AUTO; 4833c4e0415SDaniel Scheller demod_chan_cfg.fec_code_rate = MXL_HYDRA_FEC_AUTO; 4843c4e0415SDaniel Scheller 4853c4e0415SDaniel Scheller mutex_lock(&state->base->tune_lock); 4863c4e0415SDaniel Scheller if (time_after(jiffies + msecs_to_jiffies(200), 4873c4e0415SDaniel Scheller state->base->next_tune)) 4883c4e0415SDaniel Scheller while (time_before(jiffies, state->base->next_tune)) 4893c4e0415SDaniel Scheller usleep_range(10000, 11000); 4903c4e0415SDaniel Scheller state->base->next_tune = jiffies + msecs_to_jiffies(100); 4913c4e0415SDaniel Scheller state->tuner_in_use = state->tuner; 4923c4e0415SDaniel Scheller BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_SET_PARAM_CMD, MXL_CMD_WRITE, 4933c4e0415SDaniel Scheller cmd_size, &demod_chan_cfg, cmd_buff); 4943c4e0415SDaniel Scheller stat = send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, 4953c4e0415SDaniel Scheller &cmd_buff[0]); 4963c4e0415SDaniel Scheller mutex_unlock(&state->base->tune_lock); 4973c4e0415SDaniel Scheller return stat; 4983c4e0415SDaniel Scheller } 4993c4e0415SDaniel Scheller 5003c4e0415SDaniel Scheller static int enable_tuner(struct mxl *state, u32 tuner, u32 enable); 5013c4e0415SDaniel Scheller 5023c4e0415SDaniel Scheller static int sleep(struct dvb_frontend *fe) 5033c4e0415SDaniel Scheller { 5043c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 5053c4e0415SDaniel Scheller struct mxl *p; 5063c4e0415SDaniel Scheller 5073c4e0415SDaniel Scheller cfg_demod_abort_tune(state); 5083c4e0415SDaniel Scheller if (state->tuner_in_use != 0xffffffff) { 5093c4e0415SDaniel Scheller mutex_lock(&state->base->tune_lock); 5103c4e0415SDaniel Scheller state->tuner_in_use = 0xffffffff; 5113c4e0415SDaniel Scheller list_for_each_entry(p, &state->base->mxls, mxl) { 5123c4e0415SDaniel Scheller if (p->tuner_in_use == state->tuner) 5133c4e0415SDaniel Scheller break; 5143c4e0415SDaniel Scheller } 5153c4e0415SDaniel Scheller if (&p->mxl == &state->base->mxls) 5163c4e0415SDaniel Scheller enable_tuner(state, state->tuner, 0); 5173c4e0415SDaniel Scheller mutex_unlock(&state->base->tune_lock); 5183c4e0415SDaniel Scheller } 5193c4e0415SDaniel Scheller return 0; 5203c4e0415SDaniel Scheller } 5213c4e0415SDaniel Scheller 5223c4e0415SDaniel Scheller static int read_snr(struct dvb_frontend *fe) 5233c4e0415SDaniel Scheller { 5243c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 5253c4e0415SDaniel Scheller int stat; 5263c4e0415SDaniel Scheller u32 reg_data = 0; 5273c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 5283c4e0415SDaniel Scheller 5293c4e0415SDaniel Scheller mutex_lock(&state->base->status_lock); 5303c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_LOCK(state, state->demod); 5313c4e0415SDaniel Scheller stat = read_register(state, (HYDRA_DMD_SNR_ADDR_OFFSET + 5323c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 5333c4e0415SDaniel Scheller ®_data); 5343c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); 5353c4e0415SDaniel Scheller mutex_unlock(&state->base->status_lock); 5363c4e0415SDaniel Scheller 5373c4e0415SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_DECIBEL; 5383c4e0415SDaniel Scheller p->cnr.stat[0].svalue = (s16)reg_data * 10; 5393c4e0415SDaniel Scheller 5403c4e0415SDaniel Scheller return stat; 5413c4e0415SDaniel Scheller } 5423c4e0415SDaniel Scheller 5433c4e0415SDaniel Scheller static int read_ber(struct dvb_frontend *fe) 5443c4e0415SDaniel Scheller { 5453c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 5463c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 5473c4e0415SDaniel Scheller u32 reg[8]; 5483c4e0415SDaniel Scheller 5493c4e0415SDaniel Scheller mutex_lock(&state->base->status_lock); 5503c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_LOCK(state, state->demod); 5513c4e0415SDaniel Scheller read_register_block(state, 5523c4e0415SDaniel Scheller (HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET + 5533c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 5543c4e0415SDaniel Scheller (4 * sizeof(u32)), 5553c4e0415SDaniel Scheller (u8 *) ®[0]); 5563c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); 5573c4e0415SDaniel Scheller 5583c4e0415SDaniel Scheller switch (p->delivery_system) { 5593c4e0415SDaniel Scheller case SYS_DSS: 5603c4e0415SDaniel Scheller case SYS_DVBS: 5613c4e0415SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; 5623c4e0415SDaniel Scheller p->pre_bit_error.stat[0].uvalue = reg[2]; 5633c4e0415SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; 5643c4e0415SDaniel Scheller p->pre_bit_count.stat[0].uvalue = reg[3]; 5653c4e0415SDaniel Scheller break; 5663c4e0415SDaniel Scheller default: 5673c4e0415SDaniel Scheller break; 5683c4e0415SDaniel Scheller } 5693c4e0415SDaniel Scheller 5703c4e0415SDaniel Scheller read_register_block(state, 5713c4e0415SDaniel Scheller (HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET + 5723c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 5733c4e0415SDaniel Scheller (7 * sizeof(u32)), 5743c4e0415SDaniel Scheller (u8 *) ®[0]); 5753c4e0415SDaniel Scheller 5763c4e0415SDaniel Scheller switch (p->delivery_system) { 5773c4e0415SDaniel Scheller case SYS_DSS: 5783c4e0415SDaniel Scheller case SYS_DVBS: 5793c4e0415SDaniel Scheller p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 5803c4e0415SDaniel Scheller p->post_bit_error.stat[0].uvalue = reg[5]; 5813c4e0415SDaniel Scheller p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 5823c4e0415SDaniel Scheller p->post_bit_count.stat[0].uvalue = reg[6]; 5833c4e0415SDaniel Scheller break; 5843c4e0415SDaniel Scheller case SYS_DVBS2: 5853c4e0415SDaniel Scheller p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 5863c4e0415SDaniel Scheller p->post_bit_error.stat[0].uvalue = reg[1]; 5873c4e0415SDaniel Scheller p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 5883c4e0415SDaniel Scheller p->post_bit_count.stat[0].uvalue = reg[2]; 5893c4e0415SDaniel Scheller break; 5903c4e0415SDaniel Scheller default: 5913c4e0415SDaniel Scheller break; 5923c4e0415SDaniel Scheller } 5933c4e0415SDaniel Scheller 5943c4e0415SDaniel Scheller mutex_unlock(&state->base->status_lock); 5953c4e0415SDaniel Scheller 5963c4e0415SDaniel Scheller return 0; 5973c4e0415SDaniel Scheller } 5983c4e0415SDaniel Scheller 5993c4e0415SDaniel Scheller static int read_signal_strength(struct dvb_frontend *fe) 6003c4e0415SDaniel Scheller { 6013c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 6023c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 6033c4e0415SDaniel Scheller int stat; 6043c4e0415SDaniel Scheller u32 reg_data = 0; 6053c4e0415SDaniel Scheller 6063c4e0415SDaniel Scheller mutex_lock(&state->base->status_lock); 6073c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_LOCK(state, state->demod); 6083c4e0415SDaniel Scheller stat = read_register(state, (HYDRA_DMD_STATUS_INPUT_POWER_ADDR + 6093c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 6103c4e0415SDaniel Scheller ®_data); 6113c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); 6123c4e0415SDaniel Scheller mutex_unlock(&state->base->status_lock); 6133c4e0415SDaniel Scheller 6143c4e0415SDaniel Scheller p->strength.stat[0].scale = FE_SCALE_DECIBEL; 6153c4e0415SDaniel Scheller p->strength.stat[0].svalue = (s16) reg_data * 10; /* fix scale */ 6163c4e0415SDaniel Scheller 6173c4e0415SDaniel Scheller return stat; 6183c4e0415SDaniel Scheller } 6193c4e0415SDaniel Scheller 6203c4e0415SDaniel Scheller static int read_status(struct dvb_frontend *fe, enum fe_status *status) 6213c4e0415SDaniel Scheller { 6223c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 6233c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 6243c4e0415SDaniel Scheller u32 reg_data = 0; 6253c4e0415SDaniel Scheller 6263c4e0415SDaniel Scheller mutex_lock(&state->base->status_lock); 6273c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_LOCK(state, state->demod); 6283c4e0415SDaniel Scheller read_register(state, (HYDRA_DMD_LOCK_STATUS_ADDR_OFFSET + 6293c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 6303c4e0415SDaniel Scheller ®_data); 6313c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); 6323c4e0415SDaniel Scheller mutex_unlock(&state->base->status_lock); 6333c4e0415SDaniel Scheller 6343c4e0415SDaniel Scheller *status = (reg_data == 1) ? 0x1f : 0; 6353c4e0415SDaniel Scheller 6363c4e0415SDaniel Scheller /* signal statistics */ 6373c4e0415SDaniel Scheller 6383c4e0415SDaniel Scheller /* signal strength is always available */ 6393c4e0415SDaniel Scheller read_signal_strength(fe); 6403c4e0415SDaniel Scheller 6413c4e0415SDaniel Scheller if (*status & FE_HAS_CARRIER) 6423c4e0415SDaniel Scheller read_snr(fe); 6433c4e0415SDaniel Scheller else 6443c4e0415SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6453c4e0415SDaniel Scheller 6463c4e0415SDaniel Scheller if (*status & FE_HAS_SYNC) 6473c4e0415SDaniel Scheller read_ber(fe); 6483c4e0415SDaniel Scheller else { 6493c4e0415SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6503c4e0415SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6513c4e0415SDaniel Scheller p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6523c4e0415SDaniel Scheller p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6533c4e0415SDaniel Scheller } 6543c4e0415SDaniel Scheller 6553c4e0415SDaniel Scheller return 0; 6563c4e0415SDaniel Scheller } 6573c4e0415SDaniel Scheller 6583c4e0415SDaniel Scheller static int tune(struct dvb_frontend *fe, bool re_tune, 6593c4e0415SDaniel Scheller unsigned int mode_flags, 6603c4e0415SDaniel Scheller unsigned int *delay, enum fe_status *status) 6613c4e0415SDaniel Scheller { 6623c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 6633c4e0415SDaniel Scheller int r = 0; 6643c4e0415SDaniel Scheller 6653c4e0415SDaniel Scheller *delay = HZ / 2; 6663c4e0415SDaniel Scheller if (re_tune) { 6673c4e0415SDaniel Scheller r = set_parameters(fe); 6683c4e0415SDaniel Scheller if (r) 6693c4e0415SDaniel Scheller return r; 6703c4e0415SDaniel Scheller state->tune_time = jiffies; 6713c4e0415SDaniel Scheller } 6723c4e0415SDaniel Scheller 6732919d12dSMauro Carvalho Chehab return read_status(fe, status); 6743c4e0415SDaniel Scheller } 6753c4e0415SDaniel Scheller 6763c4e0415SDaniel Scheller static enum fe_code_rate conv_fec(enum MXL_HYDRA_FEC_E fec) 6773c4e0415SDaniel Scheller { 6783c4e0415SDaniel Scheller enum fe_code_rate fec2fec[11] = { 6793c4e0415SDaniel Scheller FEC_NONE, FEC_1_2, FEC_3_5, FEC_2_3, 6803c4e0415SDaniel Scheller FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, 6813c4e0415SDaniel Scheller FEC_7_8, FEC_8_9, FEC_9_10 6823c4e0415SDaniel Scheller }; 6833c4e0415SDaniel Scheller 6843c4e0415SDaniel Scheller if (fec > MXL_HYDRA_FEC_9_10) 6853c4e0415SDaniel Scheller return FEC_NONE; 6863c4e0415SDaniel Scheller return fec2fec[fec]; 6873c4e0415SDaniel Scheller } 6883c4e0415SDaniel Scheller 6893c4e0415SDaniel Scheller static int get_frontend(struct dvb_frontend *fe, 6903c4e0415SDaniel Scheller struct dtv_frontend_properties *p) 6913c4e0415SDaniel Scheller { 6923c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 6933c4e0415SDaniel Scheller u32 reg_data[MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE]; 6943c4e0415SDaniel Scheller u32 freq; 6953c4e0415SDaniel Scheller 6963c4e0415SDaniel Scheller mutex_lock(&state->base->status_lock); 6973c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_LOCK(state, state->demod); 6983c4e0415SDaniel Scheller read_register_block(state, 6993c4e0415SDaniel Scheller (HYDRA_DMD_STANDARD_ADDR_OFFSET + 7003c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 7013c4e0415SDaniel Scheller (MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE * 4), /* 25 * 4 bytes */ 7023c4e0415SDaniel Scheller (u8 *) ®_data[0]); 7033c4e0415SDaniel Scheller /* read demod channel parameters */ 7043c4e0415SDaniel Scheller read_register_block(state, 7053c4e0415SDaniel Scheller (HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR + 7063c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 7073c4e0415SDaniel Scheller (4), /* 4 bytes */ 7083c4e0415SDaniel Scheller (u8 *) &freq); 7093c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); 7103c4e0415SDaniel Scheller mutex_unlock(&state->base->status_lock); 7113c4e0415SDaniel Scheller 7123c4e0415SDaniel Scheller dev_dbg(state->i2cdev, "freq=%u delsys=%u srate=%u\n", 7133c4e0415SDaniel Scheller freq * 1000, reg_data[DMD_STANDARD_ADDR], 7143c4e0415SDaniel Scheller reg_data[DMD_SYMBOL_RATE_ADDR]); 7153c4e0415SDaniel Scheller p->symbol_rate = reg_data[DMD_SYMBOL_RATE_ADDR]; 7163c4e0415SDaniel Scheller p->frequency = freq; 7173c4e0415SDaniel Scheller /* 7183c4e0415SDaniel Scheller * p->delivery_system = 7193c4e0415SDaniel Scheller * (MXL_HYDRA_BCAST_STD_E) regData[DMD_STANDARD_ADDR]; 7203c4e0415SDaniel Scheller * p->inversion = 7213c4e0415SDaniel Scheller * (MXL_HYDRA_SPECTRUM_E) regData[DMD_SPECTRUM_INVERSION_ADDR]; 7223c4e0415SDaniel Scheller * freqSearchRangeKHz = 7233c4e0415SDaniel Scheller * (regData[DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR]); 7243c4e0415SDaniel Scheller */ 7253c4e0415SDaniel Scheller 7263c4e0415SDaniel Scheller p->fec_inner = conv_fec(reg_data[DMD_FEC_CODE_RATE_ADDR]); 7273c4e0415SDaniel Scheller switch (p->delivery_system) { 7283c4e0415SDaniel Scheller case SYS_DSS: 7293c4e0415SDaniel Scheller break; 7303c4e0415SDaniel Scheller case SYS_DVBS2: 7313c4e0415SDaniel Scheller switch ((enum MXL_HYDRA_PILOTS_E) 7323c4e0415SDaniel Scheller reg_data[DMD_DVBS2_PILOT_ON_OFF_ADDR]) { 7333c4e0415SDaniel Scheller case MXL_HYDRA_PILOTS_OFF: 7343c4e0415SDaniel Scheller p->pilot = PILOT_OFF; 7353c4e0415SDaniel Scheller break; 7363c4e0415SDaniel Scheller case MXL_HYDRA_PILOTS_ON: 7373c4e0415SDaniel Scheller p->pilot = PILOT_ON; 7383c4e0415SDaniel Scheller break; 7393c4e0415SDaniel Scheller default: 7403c4e0415SDaniel Scheller break; 7413c4e0415SDaniel Scheller } 7423c4e0415SDaniel Scheller case SYS_DVBS: 7433c4e0415SDaniel Scheller switch ((enum MXL_HYDRA_MODULATION_E) 7443c4e0415SDaniel Scheller reg_data[DMD_MODULATION_SCHEME_ADDR]) { 7453c4e0415SDaniel Scheller case MXL_HYDRA_MOD_QPSK: 7463c4e0415SDaniel Scheller p->modulation = QPSK; 7473c4e0415SDaniel Scheller break; 7483c4e0415SDaniel Scheller case MXL_HYDRA_MOD_8PSK: 7493c4e0415SDaniel Scheller p->modulation = PSK_8; 7503c4e0415SDaniel Scheller break; 7513c4e0415SDaniel Scheller default: 7523c4e0415SDaniel Scheller break; 7533c4e0415SDaniel Scheller } 7543c4e0415SDaniel Scheller switch ((enum MXL_HYDRA_ROLLOFF_E) 7553c4e0415SDaniel Scheller reg_data[DMD_SPECTRUM_ROLL_OFF_ADDR]) { 7563c4e0415SDaniel Scheller case MXL_HYDRA_ROLLOFF_0_20: 7573c4e0415SDaniel Scheller p->rolloff = ROLLOFF_20; 7583c4e0415SDaniel Scheller break; 7593c4e0415SDaniel Scheller case MXL_HYDRA_ROLLOFF_0_35: 7603c4e0415SDaniel Scheller p->rolloff = ROLLOFF_35; 7613c4e0415SDaniel Scheller break; 7623c4e0415SDaniel Scheller case MXL_HYDRA_ROLLOFF_0_25: 7633c4e0415SDaniel Scheller p->rolloff = ROLLOFF_25; 7643c4e0415SDaniel Scheller break; 7653c4e0415SDaniel Scheller default: 7663c4e0415SDaniel Scheller break; 7673c4e0415SDaniel Scheller } 7683c4e0415SDaniel Scheller break; 7693c4e0415SDaniel Scheller default: 7703c4e0415SDaniel Scheller return -EINVAL; 7713c4e0415SDaniel Scheller } 7723c4e0415SDaniel Scheller return 0; 7733c4e0415SDaniel Scheller } 7743c4e0415SDaniel Scheller 7753c4e0415SDaniel Scheller static int set_input(struct dvb_frontend *fe, int input) 7763c4e0415SDaniel Scheller { 7773c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 7783c4e0415SDaniel Scheller 7793c4e0415SDaniel Scheller state->tuner = input; 7803c4e0415SDaniel Scheller return 0; 7813c4e0415SDaniel Scheller } 7823c4e0415SDaniel Scheller 7833c4e0415SDaniel Scheller static struct dvb_frontend_ops mxl_ops = { 7843c4e0415SDaniel Scheller .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, 7853c4e0415SDaniel Scheller .info = { 7863c4e0415SDaniel Scheller .name = "MaxLinear MxL5xx DVB-S/S2 tuner-demodulator", 7873c4e0415SDaniel Scheller .frequency_min = 300000, 7883c4e0415SDaniel Scheller .frequency_max = 2350000, 7893c4e0415SDaniel Scheller .frequency_stepsize = 0, 7903c4e0415SDaniel Scheller .frequency_tolerance = 0, 7913c4e0415SDaniel Scheller .symbol_rate_min = 1000000, 7923c4e0415SDaniel Scheller .symbol_rate_max = 45000000, 7933c4e0415SDaniel Scheller .caps = FE_CAN_INVERSION_AUTO | 7943c4e0415SDaniel Scheller FE_CAN_FEC_AUTO | 7953c4e0415SDaniel Scheller FE_CAN_QPSK | 7963c4e0415SDaniel Scheller FE_CAN_2G_MODULATION 7973c4e0415SDaniel Scheller }, 7983c4e0415SDaniel Scheller .init = init, 7993c4e0415SDaniel Scheller .release = release, 8003c4e0415SDaniel Scheller .get_frontend_algo = get_algo, 8013c4e0415SDaniel Scheller .tune = tune, 8023c4e0415SDaniel Scheller .read_status = read_status, 8033c4e0415SDaniel Scheller .sleep = sleep, 8043c4e0415SDaniel Scheller .get_frontend = get_frontend, 8053c4e0415SDaniel Scheller .diseqc_send_master_cmd = send_master_cmd, 8063c4e0415SDaniel Scheller }; 8073c4e0415SDaniel Scheller 8083c4e0415SDaniel Scheller static struct mxl_base *match_base(struct i2c_adapter *i2c, u8 adr) 8093c4e0415SDaniel Scheller { 8103c4e0415SDaniel Scheller struct mxl_base *p; 8113c4e0415SDaniel Scheller 8123c4e0415SDaniel Scheller list_for_each_entry(p, &mxllist, mxllist) 8133c4e0415SDaniel Scheller if (p->i2c == i2c && p->adr == adr) 8143c4e0415SDaniel Scheller return p; 8153c4e0415SDaniel Scheller return NULL; 8163c4e0415SDaniel Scheller } 8173c4e0415SDaniel Scheller 8183c4e0415SDaniel Scheller static void cfg_dev_xtal(struct mxl *state, u32 freq, u32 cap, u32 enable) 8193c4e0415SDaniel Scheller { 8203c4e0415SDaniel Scheller if (state->base->can_clkout || !enable) 8213c4e0415SDaniel Scheller update_by_mnemonic(state, 0x90200054, 23, 1, enable); 8223c4e0415SDaniel Scheller 8233c4e0415SDaniel Scheller if (freq == 24000000) 8243c4e0415SDaniel Scheller write_register(state, HYDRA_CRYSTAL_SETTING, 0); 8253c4e0415SDaniel Scheller else 8263c4e0415SDaniel Scheller write_register(state, HYDRA_CRYSTAL_SETTING, 1); 8273c4e0415SDaniel Scheller 8283c4e0415SDaniel Scheller write_register(state, HYDRA_CRYSTAL_CAP, cap); 8293c4e0415SDaniel Scheller } 8303c4e0415SDaniel Scheller 8313c4e0415SDaniel Scheller static u32 get_big_endian(u8 num_of_bits, const u8 buf[]) 8323c4e0415SDaniel Scheller { 8333c4e0415SDaniel Scheller u32 ret_value = 0; 8343c4e0415SDaniel Scheller 8353c4e0415SDaniel Scheller switch (num_of_bits) { 8363c4e0415SDaniel Scheller case 24: 8373c4e0415SDaniel Scheller ret_value = (((u32) buf[0]) << 16) | 8383c4e0415SDaniel Scheller (((u32) buf[1]) << 8) | buf[2]; 8393c4e0415SDaniel Scheller break; 8403c4e0415SDaniel Scheller case 32: 8413c4e0415SDaniel Scheller ret_value = (((u32) buf[0]) << 24) | 8423c4e0415SDaniel Scheller (((u32) buf[1]) << 16) | 8433c4e0415SDaniel Scheller (((u32) buf[2]) << 8) | buf[3]; 8443c4e0415SDaniel Scheller break; 8453c4e0415SDaniel Scheller default: 8463c4e0415SDaniel Scheller break; 8473c4e0415SDaniel Scheller } 8483c4e0415SDaniel Scheller 8493c4e0415SDaniel Scheller return ret_value; 8503c4e0415SDaniel Scheller } 8513c4e0415SDaniel Scheller 8523c4e0415SDaniel Scheller static int write_fw_segment(struct mxl *state, 8533c4e0415SDaniel Scheller u32 mem_addr, u32 total_size, u8 *data_ptr) 8543c4e0415SDaniel Scheller { 8553c4e0415SDaniel Scheller int status; 8563c4e0415SDaniel Scheller u32 data_count = 0; 8573c4e0415SDaniel Scheller u32 size = 0; 8583c4e0415SDaniel Scheller u32 orig_size = 0; 8593c4e0415SDaniel Scheller u8 *w_buf_ptr = NULL; 8603c4e0415SDaniel Scheller u32 block_size = ((MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH - 8613c4e0415SDaniel Scheller (MXL_HYDRA_I2C_HDR_SIZE + 8623c4e0415SDaniel Scheller MXL_HYDRA_REG_SIZE_IN_BYTES)) / 4) * 4; 8633c4e0415SDaniel Scheller u8 w_msg_buffer[MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH - 8643c4e0415SDaniel Scheller (MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES)]; 8653c4e0415SDaniel Scheller 8663c4e0415SDaniel Scheller do { 8673c4e0415SDaniel Scheller size = orig_size = (((u32)(data_count + block_size)) > total_size) ? 8683c4e0415SDaniel Scheller (total_size - data_count) : block_size; 8693c4e0415SDaniel Scheller 8703c4e0415SDaniel Scheller if (orig_size & 3) 8713c4e0415SDaniel Scheller size = (orig_size + 4) & ~3; 8723c4e0415SDaniel Scheller w_buf_ptr = &w_msg_buffer[0]; 8733c4e0415SDaniel Scheller memset((void *) w_buf_ptr, 0, size); 8743c4e0415SDaniel Scheller memcpy((void *) w_buf_ptr, (void *) data_ptr, orig_size); 8753c4e0415SDaniel Scheller convert_endian(1, size, w_buf_ptr); 8763c4e0415SDaniel Scheller status = write_firmware_block(state, mem_addr, size, w_buf_ptr); 8773c4e0415SDaniel Scheller if (status) 8783c4e0415SDaniel Scheller return status; 8793c4e0415SDaniel Scheller data_count += size; 8803c4e0415SDaniel Scheller mem_addr += size; 8813c4e0415SDaniel Scheller data_ptr += size; 8823c4e0415SDaniel Scheller } while (data_count < total_size); 8833c4e0415SDaniel Scheller 8843c4e0415SDaniel Scheller return status; 8853c4e0415SDaniel Scheller } 8863c4e0415SDaniel Scheller 8873c4e0415SDaniel Scheller static int do_firmware_download(struct mxl *state, u8 *mbin_buffer_ptr, 8883c4e0415SDaniel Scheller u32 mbin_buffer_size) 8893c4e0415SDaniel Scheller 8903c4e0415SDaniel Scheller { 8913c4e0415SDaniel Scheller int status; 8923c4e0415SDaniel Scheller u32 index = 0; 8933c4e0415SDaniel Scheller u32 seg_length = 0; 8943c4e0415SDaniel Scheller u32 seg_address = 0; 8953c4e0415SDaniel Scheller struct MBIN_FILE_T *mbin_ptr = (struct MBIN_FILE_T *)mbin_buffer_ptr; 8963c4e0415SDaniel Scheller struct MBIN_SEGMENT_T *segment_ptr; 8973c4e0415SDaniel Scheller enum MXL_BOOL_E xcpu_fw_flag = MXL_FALSE; 8983c4e0415SDaniel Scheller 8993c4e0415SDaniel Scheller if (mbin_ptr->header.id != MBIN_FILE_HEADER_ID) { 9003c4e0415SDaniel Scheller dev_err(state->i2cdev, "%s: Invalid file header ID (%c)\n", 9013c4e0415SDaniel Scheller __func__, mbin_ptr->header.id); 9023c4e0415SDaniel Scheller return -EINVAL; 9033c4e0415SDaniel Scheller } 9043c4e0415SDaniel Scheller status = write_register(state, FW_DL_SIGN_ADDR, 0); 9053c4e0415SDaniel Scheller if (status) 9063c4e0415SDaniel Scheller return status; 9073c4e0415SDaniel Scheller segment_ptr = (struct MBIN_SEGMENT_T *) (&mbin_ptr->data[0]); 9083c4e0415SDaniel Scheller for (index = 0; index < mbin_ptr->header.num_segments; index++) { 9093c4e0415SDaniel Scheller if (segment_ptr->header.id != MBIN_SEGMENT_HEADER_ID) { 9103c4e0415SDaniel Scheller dev_err(state->i2cdev, "%s: Invalid segment header ID (%c)\n", 9113c4e0415SDaniel Scheller __func__, segment_ptr->header.id); 9123c4e0415SDaniel Scheller return -EINVAL; 9133c4e0415SDaniel Scheller } 9143c4e0415SDaniel Scheller seg_length = get_big_endian(24, 9153c4e0415SDaniel Scheller &(segment_ptr->header.len24[0])); 9163c4e0415SDaniel Scheller seg_address = get_big_endian(32, 9173c4e0415SDaniel Scheller &(segment_ptr->header.address[0])); 9183c4e0415SDaniel Scheller 9193c4e0415SDaniel Scheller if (state->base->type == MXL_HYDRA_DEVICE_568) { 9203c4e0415SDaniel Scheller if ((((seg_address & 0x90760000) == 0x90760000) || 9213c4e0415SDaniel Scheller ((seg_address & 0x90740000) == 0x90740000)) && 9223c4e0415SDaniel Scheller (xcpu_fw_flag == MXL_FALSE)) { 9233c4e0415SDaniel Scheller update_by_mnemonic(state, 0x8003003C, 0, 1, 1); 9243c4e0415SDaniel Scheller msleep(200); 9253c4e0415SDaniel Scheller write_register(state, 0x90720000, 0); 9263c4e0415SDaniel Scheller usleep_range(10000, 11000); 9273c4e0415SDaniel Scheller xcpu_fw_flag = MXL_TRUE; 9283c4e0415SDaniel Scheller } 9293c4e0415SDaniel Scheller status = write_fw_segment(state, seg_address, 9303c4e0415SDaniel Scheller seg_length, 9313c4e0415SDaniel Scheller (u8 *) segment_ptr->data); 9323c4e0415SDaniel Scheller } else { 9333c4e0415SDaniel Scheller if (((seg_address & 0x90760000) != 0x90760000) && 9343c4e0415SDaniel Scheller ((seg_address & 0x90740000) != 0x90740000)) 9353c4e0415SDaniel Scheller status = write_fw_segment(state, seg_address, 9363c4e0415SDaniel Scheller seg_length, (u8 *) segment_ptr->data); 9373c4e0415SDaniel Scheller } 9383c4e0415SDaniel Scheller if (status) 9393c4e0415SDaniel Scheller return status; 9403c4e0415SDaniel Scheller segment_ptr = (struct MBIN_SEGMENT_T *) 9413c4e0415SDaniel Scheller &(segment_ptr->data[((seg_length + 3) / 4) * 4]); 9423c4e0415SDaniel Scheller } 9433c4e0415SDaniel Scheller return status; 9443c4e0415SDaniel Scheller } 9453c4e0415SDaniel Scheller 9463c4e0415SDaniel Scheller static int check_fw(struct mxl *state, u8 *mbin, u32 mbin_len) 9473c4e0415SDaniel Scheller { 9483c4e0415SDaniel Scheller struct MBIN_FILE_HEADER_T *fh = (struct MBIN_FILE_HEADER_T *) mbin; 9493c4e0415SDaniel Scheller u32 flen = (fh->image_size24[0] << 16) | 9503c4e0415SDaniel Scheller (fh->image_size24[1] << 8) | fh->image_size24[2]; 9513c4e0415SDaniel Scheller u8 *fw, cs = 0; 9523c4e0415SDaniel Scheller u32 i; 9533c4e0415SDaniel Scheller 9543c4e0415SDaniel Scheller if (fh->id != 'M' || fh->fmt_version != '1' || flen > 0x3FFF0) { 9553c4e0415SDaniel Scheller dev_info(state->i2cdev, "Invalid FW Header\n"); 9563c4e0415SDaniel Scheller return -1; 9573c4e0415SDaniel Scheller } 9583c4e0415SDaniel Scheller fw = mbin + sizeof(struct MBIN_FILE_HEADER_T); 9593c4e0415SDaniel Scheller for (i = 0; i < flen; i += 1) 9603c4e0415SDaniel Scheller cs += fw[i]; 9613c4e0415SDaniel Scheller if (cs != fh->image_checksum) { 9623c4e0415SDaniel Scheller dev_info(state->i2cdev, "Invalid FW Checksum\n"); 9633c4e0415SDaniel Scheller return -1; 9643c4e0415SDaniel Scheller } 9653c4e0415SDaniel Scheller return 0; 9663c4e0415SDaniel Scheller } 9673c4e0415SDaniel Scheller 9683c4e0415SDaniel Scheller static int firmware_download(struct mxl *state, u8 *mbin, u32 mbin_len) 9693c4e0415SDaniel Scheller { 9703c4e0415SDaniel Scheller int status; 9713c4e0415SDaniel Scheller u32 reg_data = 0; 9723c4e0415SDaniel Scheller struct MXL_HYDRA_SKU_COMMAND_T dev_sku_cfg; 9733c4e0415SDaniel Scheller u8 cmd_size = sizeof(struct MXL_HYDRA_SKU_COMMAND_T); 9743c4e0415SDaniel Scheller u8 cmd_buff[sizeof(struct MXL_HYDRA_SKU_COMMAND_T) + 6]; 9753c4e0415SDaniel Scheller 9763c4e0415SDaniel Scheller if (check_fw(state, mbin, mbin_len)) 9773c4e0415SDaniel Scheller return -1; 9783c4e0415SDaniel Scheller 9793c4e0415SDaniel Scheller /* put CPU into reset */ 9803c4e0415SDaniel Scheller status = update_by_mnemonic(state, 0x8003003C, 0, 1, 0); 9813c4e0415SDaniel Scheller if (status) 9823c4e0415SDaniel Scheller return status; 9833c4e0415SDaniel Scheller usleep_range(1000, 2000); 9843c4e0415SDaniel Scheller 9853c4e0415SDaniel Scheller /* Reset TX FIFO's, BBAND, XBAR */ 9863c4e0415SDaniel Scheller status = write_register(state, HYDRA_RESET_TRANSPORT_FIFO_REG, 9873c4e0415SDaniel Scheller HYDRA_RESET_TRANSPORT_FIFO_DATA); 9883c4e0415SDaniel Scheller if (status) 9893c4e0415SDaniel Scheller return status; 9903c4e0415SDaniel Scheller status = write_register(state, HYDRA_RESET_BBAND_REG, 9913c4e0415SDaniel Scheller HYDRA_RESET_BBAND_DATA); 9923c4e0415SDaniel Scheller if (status) 9933c4e0415SDaniel Scheller return status; 9943c4e0415SDaniel Scheller status = write_register(state, HYDRA_RESET_XBAR_REG, 9953c4e0415SDaniel Scheller HYDRA_RESET_XBAR_DATA); 9963c4e0415SDaniel Scheller if (status) 9973c4e0415SDaniel Scheller return status; 9983c4e0415SDaniel Scheller 9993c4e0415SDaniel Scheller /* Disable clock to Baseband, Wideband, SerDes, 10003c4e0415SDaniel Scheller * Alias ext & Transport modules 10013c4e0415SDaniel Scheller */ 10023c4e0415SDaniel Scheller status = write_register(state, HYDRA_MODULES_CLK_2_REG, 10033c4e0415SDaniel Scheller HYDRA_DISABLE_CLK_2); 10043c4e0415SDaniel Scheller if (status) 10053c4e0415SDaniel Scheller return status; 10063c4e0415SDaniel Scheller /* Clear Software & Host interrupt status - (Clear on read) */ 10073c4e0415SDaniel Scheller status = read_register(state, HYDRA_PRCM_ROOT_CLK_REG, ®_data); 10083c4e0415SDaniel Scheller if (status) 10093c4e0415SDaniel Scheller return status; 10103c4e0415SDaniel Scheller status = do_firmware_download(state, mbin, mbin_len); 10113c4e0415SDaniel Scheller if (status) 10123c4e0415SDaniel Scheller return status; 10133c4e0415SDaniel Scheller 10143c4e0415SDaniel Scheller if (state->base->type == MXL_HYDRA_DEVICE_568) { 10153c4e0415SDaniel Scheller usleep_range(10000, 11000); 10163c4e0415SDaniel Scheller 10173c4e0415SDaniel Scheller /* bring XCPU out of reset */ 10183c4e0415SDaniel Scheller status = write_register(state, 0x90720000, 1); 10193c4e0415SDaniel Scheller if (status) 10203c4e0415SDaniel Scheller return status; 10213c4e0415SDaniel Scheller msleep(500); 10223c4e0415SDaniel Scheller 10233c4e0415SDaniel Scheller /* Enable XCPU UART message processing in MCPU */ 10243c4e0415SDaniel Scheller status = write_register(state, 0x9076B510, 1); 10253c4e0415SDaniel Scheller if (status) 10263c4e0415SDaniel Scheller return status; 10273c4e0415SDaniel Scheller } else { 10283c4e0415SDaniel Scheller /* Bring CPU out of reset */ 10293c4e0415SDaniel Scheller status = update_by_mnemonic(state, 0x8003003C, 0, 1, 1); 10303c4e0415SDaniel Scheller if (status) 10313c4e0415SDaniel Scheller return status; 10323c4e0415SDaniel Scheller /* Wait until FW boots */ 10333c4e0415SDaniel Scheller msleep(150); 10343c4e0415SDaniel Scheller } 10353c4e0415SDaniel Scheller 10363c4e0415SDaniel Scheller /* Initialize XPT XBAR */ 10373c4e0415SDaniel Scheller status = write_register(state, XPT_DMD0_BASEADDR, 0x76543210); 10383c4e0415SDaniel Scheller if (status) 10393c4e0415SDaniel Scheller return status; 10403c4e0415SDaniel Scheller 10413c4e0415SDaniel Scheller if (!firmware_is_alive(state)) 10423c4e0415SDaniel Scheller return -1; 10433c4e0415SDaniel Scheller 10443c4e0415SDaniel Scheller dev_info(state->i2cdev, "Hydra FW alive. Hail!\n"); 10453c4e0415SDaniel Scheller 10463c4e0415SDaniel Scheller /* sometimes register values are wrong shortly 10473c4e0415SDaniel Scheller * after first heart beats 10483c4e0415SDaniel Scheller */ 10493c4e0415SDaniel Scheller msleep(50); 10503c4e0415SDaniel Scheller 10513c4e0415SDaniel Scheller dev_sku_cfg.sku_type = state->base->sku_type; 10523c4e0415SDaniel Scheller BUILD_HYDRA_CMD(MXL_HYDRA_DEV_CFG_SKU_CMD, MXL_CMD_WRITE, 10533c4e0415SDaniel Scheller cmd_size, &dev_sku_cfg, cmd_buff); 10543c4e0415SDaniel Scheller status = send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, 10553c4e0415SDaniel Scheller &cmd_buff[0]); 10563c4e0415SDaniel Scheller 10573c4e0415SDaniel Scheller return status; 10583c4e0415SDaniel Scheller } 10593c4e0415SDaniel Scheller 10603c4e0415SDaniel Scheller static int cfg_ts_pad_mux(struct mxl *state, enum MXL_BOOL_E enable_serial_ts) 10613c4e0415SDaniel Scheller { 10623c4e0415SDaniel Scheller int status = 0; 10633c4e0415SDaniel Scheller u32 pad_mux_value = 0; 10643c4e0415SDaniel Scheller 10653c4e0415SDaniel Scheller if (enable_serial_ts == MXL_TRUE) { 10663c4e0415SDaniel Scheller pad_mux_value = 0; 10673c4e0415SDaniel Scheller if ((state->base->type == MXL_HYDRA_DEVICE_541) || 10683c4e0415SDaniel Scheller (state->base->type == MXL_HYDRA_DEVICE_541S)) 10693c4e0415SDaniel Scheller pad_mux_value = 2; 10703c4e0415SDaniel Scheller } else { 10713c4e0415SDaniel Scheller if ((state->base->type == MXL_HYDRA_DEVICE_581) || 10723c4e0415SDaniel Scheller (state->base->type == MXL_HYDRA_DEVICE_581S)) 10733c4e0415SDaniel Scheller pad_mux_value = 2; 10743c4e0415SDaniel Scheller else 10753c4e0415SDaniel Scheller pad_mux_value = 3; 10763c4e0415SDaniel Scheller } 10773c4e0415SDaniel Scheller 10783c4e0415SDaniel Scheller switch (state->base->type) { 10793c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_561: 10803c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_581: 10813c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_541: 10823c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_541S: 10833c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_561S: 10843c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_581S: 10853c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000170, 24, 3, 10863c4e0415SDaniel Scheller pad_mux_value); 10873c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000170, 28, 3, 10883c4e0415SDaniel Scheller pad_mux_value); 10893c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 0, 3, 10903c4e0415SDaniel Scheller pad_mux_value); 10913c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 4, 3, 10923c4e0415SDaniel Scheller pad_mux_value); 10933c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 8, 3, 10943c4e0415SDaniel Scheller pad_mux_value); 10953c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 12, 3, 10963c4e0415SDaniel Scheller pad_mux_value); 10973c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 16, 3, 10983c4e0415SDaniel Scheller pad_mux_value); 10993c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 20, 3, 11003c4e0415SDaniel Scheller pad_mux_value); 11013c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 24, 3, 11023c4e0415SDaniel Scheller pad_mux_value); 11033c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 28, 3, 11043c4e0415SDaniel Scheller pad_mux_value); 11053c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 0, 3, 11063c4e0415SDaniel Scheller pad_mux_value); 11073c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 4, 3, 11083c4e0415SDaniel Scheller pad_mux_value); 11093c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 8, 3, 11103c4e0415SDaniel Scheller pad_mux_value); 11113c4e0415SDaniel Scheller break; 11123c4e0415SDaniel Scheller 11133c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_544: 11143c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_542: 11153c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000016C, 4, 3, 1); 11163c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000016C, 8, 3, 0); 11173c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000016C, 12, 3, 0); 11183c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000016C, 16, 3, 0); 11193c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000170, 0, 3, 0); 11203c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 12, 3, 1); 11213c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 16, 3, 1); 11223c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 20, 3, 1); 11233c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 24, 3, 1); 11243c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000017C, 0, 3, 1); 11253c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000017C, 4, 3, 1); 11263c4e0415SDaniel Scheller if (enable_serial_ts == MXL_ENABLE) { 11273c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11283c4e0415SDaniel Scheller 0x90000170, 4, 3, 0); 11293c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11303c4e0415SDaniel Scheller 0x90000170, 8, 3, 0); 11313c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11323c4e0415SDaniel Scheller 0x90000170, 12, 3, 0); 11333c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11343c4e0415SDaniel Scheller 0x90000170, 16, 3, 0); 11353c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11363c4e0415SDaniel Scheller 0x90000170, 20, 3, 1); 11373c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11383c4e0415SDaniel Scheller 0x90000170, 24, 3, 1); 11393c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11403c4e0415SDaniel Scheller 0x90000170, 28, 3, 2); 11413c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11423c4e0415SDaniel Scheller 0x90000174, 0, 3, 2); 11433c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11443c4e0415SDaniel Scheller 0x90000174, 4, 3, 2); 11453c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11463c4e0415SDaniel Scheller 0x90000174, 8, 3, 2); 11473c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11483c4e0415SDaniel Scheller 0x90000174, 12, 3, 2); 11493c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11503c4e0415SDaniel Scheller 0x90000174, 16, 3, 2); 11513c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11523c4e0415SDaniel Scheller 0x90000174, 20, 3, 2); 11533c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11543c4e0415SDaniel Scheller 0x90000174, 24, 3, 2); 11553c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11563c4e0415SDaniel Scheller 0x90000174, 28, 3, 2); 11573c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11583c4e0415SDaniel Scheller 0x90000178, 0, 3, 2); 11593c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11603c4e0415SDaniel Scheller 0x90000178, 4, 3, 2); 11613c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11623c4e0415SDaniel Scheller 0x90000178, 8, 3, 2); 11633c4e0415SDaniel Scheller } else { 11643c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11653c4e0415SDaniel Scheller 0x90000170, 4, 3, 3); 11663c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11673c4e0415SDaniel Scheller 0x90000170, 8, 3, 3); 11683c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11693c4e0415SDaniel Scheller 0x90000170, 12, 3, 3); 11703c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11713c4e0415SDaniel Scheller 0x90000170, 16, 3, 3); 11723c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11733c4e0415SDaniel Scheller 0x90000170, 20, 3, 3); 11743c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11753c4e0415SDaniel Scheller 0x90000170, 24, 3, 3); 11763c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11773c4e0415SDaniel Scheller 0x90000170, 28, 3, 3); 11783c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11793c4e0415SDaniel Scheller 0x90000174, 0, 3, 3); 11803c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11813c4e0415SDaniel Scheller 0x90000174, 4, 3, 3); 11823c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11833c4e0415SDaniel Scheller 0x90000174, 8, 3, 3); 11843c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11853c4e0415SDaniel Scheller 0x90000174, 12, 3, 3); 11863c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11873c4e0415SDaniel Scheller 0x90000174, 16, 3, 3); 11883c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11893c4e0415SDaniel Scheller 0x90000174, 20, 3, 1); 11903c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11913c4e0415SDaniel Scheller 0x90000174, 24, 3, 1); 11923c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11933c4e0415SDaniel Scheller 0x90000174, 28, 3, 1); 11943c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11953c4e0415SDaniel Scheller 0x90000178, 0, 3, 1); 11963c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11973c4e0415SDaniel Scheller 0x90000178, 4, 3, 1); 11983c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11993c4e0415SDaniel Scheller 0x90000178, 8, 3, 1); 12003c4e0415SDaniel Scheller } 12013c4e0415SDaniel Scheller break; 12023c4e0415SDaniel Scheller 12033c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_568: 12043c4e0415SDaniel Scheller if (enable_serial_ts == MXL_FALSE) { 12053c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12063c4e0415SDaniel Scheller 0x9000016C, 8, 3, 5); 12073c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12083c4e0415SDaniel Scheller 0x9000016C, 12, 3, 5); 12093c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12103c4e0415SDaniel Scheller 0x9000016C, 16, 3, 5); 12113c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12123c4e0415SDaniel Scheller 0x9000016C, 20, 3, 5); 12133c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12143c4e0415SDaniel Scheller 0x9000016C, 24, 3, 5); 12153c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12163c4e0415SDaniel Scheller 0x9000016C, 28, 3, 5); 12173c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12183c4e0415SDaniel Scheller 0x90000170, 0, 3, 5); 12193c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12203c4e0415SDaniel Scheller 0x90000170, 4, 3, 5); 12213c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12223c4e0415SDaniel Scheller 0x90000170, 8, 3, 5); 12233c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12243c4e0415SDaniel Scheller 0x90000170, 12, 3, 5); 12253c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12263c4e0415SDaniel Scheller 0x90000170, 16, 3, 5); 12273c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12283c4e0415SDaniel Scheller 0x90000170, 20, 3, 5); 12293c4e0415SDaniel Scheller 12303c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12313c4e0415SDaniel Scheller 0x90000170, 24, 3, pad_mux_value); 12323c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12333c4e0415SDaniel Scheller 0x90000174, 0, 3, pad_mux_value); 12343c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12353c4e0415SDaniel Scheller 0x90000174, 4, 3, pad_mux_value); 12363c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12373c4e0415SDaniel Scheller 0x90000174, 8, 3, pad_mux_value); 12383c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12393c4e0415SDaniel Scheller 0x90000174, 12, 3, pad_mux_value); 12403c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12413c4e0415SDaniel Scheller 0x90000174, 16, 3, pad_mux_value); 12423c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12433c4e0415SDaniel Scheller 0x90000174, 20, 3, pad_mux_value); 12443c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12453c4e0415SDaniel Scheller 0x90000174, 24, 3, pad_mux_value); 12463c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12473c4e0415SDaniel Scheller 0x90000174, 28, 3, pad_mux_value); 12483c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12493c4e0415SDaniel Scheller 0x90000178, 0, 3, pad_mux_value); 12503c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12513c4e0415SDaniel Scheller 0x90000178, 4, 3, pad_mux_value); 12523c4e0415SDaniel Scheller 12533c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12543c4e0415SDaniel Scheller 0x90000178, 8, 3, 5); 12553c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12563c4e0415SDaniel Scheller 0x90000178, 12, 3, 5); 12573c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12583c4e0415SDaniel Scheller 0x90000178, 16, 3, 5); 12593c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12603c4e0415SDaniel Scheller 0x90000178, 20, 3, 5); 12613c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12623c4e0415SDaniel Scheller 0x90000178, 24, 3, 5); 12633c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12643c4e0415SDaniel Scheller 0x90000178, 28, 3, 5); 12653c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12663c4e0415SDaniel Scheller 0x9000017C, 0, 3, 5); 12673c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12683c4e0415SDaniel Scheller 0x9000017C, 4, 3, 5); 12693c4e0415SDaniel Scheller } else { 12703c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12713c4e0415SDaniel Scheller 0x90000170, 4, 3, pad_mux_value); 12723c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12733c4e0415SDaniel Scheller 0x90000170, 8, 3, pad_mux_value); 12743c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12753c4e0415SDaniel Scheller 0x90000170, 12, 3, pad_mux_value); 12763c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12773c4e0415SDaniel Scheller 0x90000170, 16, 3, pad_mux_value); 12783c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12793c4e0415SDaniel Scheller 0x90000170, 20, 3, pad_mux_value); 12803c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12813c4e0415SDaniel Scheller 0x90000170, 24, 3, pad_mux_value); 12823c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12833c4e0415SDaniel Scheller 0x90000170, 28, 3, pad_mux_value); 12843c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12853c4e0415SDaniel Scheller 0x90000174, 0, 3, pad_mux_value); 12863c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12873c4e0415SDaniel Scheller 0x90000174, 4, 3, pad_mux_value); 12883c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12893c4e0415SDaniel Scheller 0x90000174, 8, 3, pad_mux_value); 12903c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12913c4e0415SDaniel Scheller 0x90000174, 12, 3, pad_mux_value); 12923c4e0415SDaniel Scheller } 12933c4e0415SDaniel Scheller break; 12943c4e0415SDaniel Scheller 12953c4e0415SDaniel Scheller 12963c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_584: 12973c4e0415SDaniel Scheller default: 12983c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12993c4e0415SDaniel Scheller 0x90000170, 4, 3, pad_mux_value); 13003c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 13013c4e0415SDaniel Scheller 0x90000170, 8, 3, pad_mux_value); 13023c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 13033c4e0415SDaniel Scheller 0x90000170, 12, 3, pad_mux_value); 13043c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 13053c4e0415SDaniel Scheller 0x90000170, 16, 3, pad_mux_value); 13063c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 13073c4e0415SDaniel Scheller 0x90000170, 20, 3, pad_mux_value); 13083c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 13093c4e0415SDaniel Scheller 0x90000170, 24, 3, pad_mux_value); 13103c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 13113c4e0415SDaniel Scheller 0x90000170, 28, 3, pad_mux_value); 13123c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 13133c4e0415SDaniel Scheller 0x90000174, 0, 3, pad_mux_value); 13143c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 13153c4e0415SDaniel Scheller 0x90000174, 4, 3, pad_mux_value); 13163c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 13173c4e0415SDaniel Scheller 0x90000174, 8, 3, pad_mux_value); 13183c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 13193c4e0415SDaniel Scheller 0x90000174, 12, 3, pad_mux_value); 13203c4e0415SDaniel Scheller break; 13213c4e0415SDaniel Scheller } 13223c4e0415SDaniel Scheller return status; 13233c4e0415SDaniel Scheller } 13243c4e0415SDaniel Scheller 13253c4e0415SDaniel Scheller static int set_drive_strength(struct mxl *state, 13263c4e0415SDaniel Scheller enum MXL_HYDRA_TS_DRIVE_STRENGTH_E ts_drive_strength) 13273c4e0415SDaniel Scheller { 13283c4e0415SDaniel Scheller int stat = 0; 13293c4e0415SDaniel Scheller u32 val; 13303c4e0415SDaniel Scheller 13313c4e0415SDaniel Scheller read_register(state, 0x90000194, &val); 13323c4e0415SDaniel Scheller dev_info(state->i2cdev, "DIGIO = %08x\n", val); 13333c4e0415SDaniel Scheller dev_info(state->i2cdev, "set drive_strength = %u\n", ts_drive_strength); 13343c4e0415SDaniel Scheller 13353c4e0415SDaniel Scheller 13363c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000194, 0, 3, ts_drive_strength); 13373c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000194, 20, 3, ts_drive_strength); 13383c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000194, 24, 3, ts_drive_strength); 13393c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000198, 12, 3, ts_drive_strength); 13403c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000198, 16, 3, ts_drive_strength); 13413c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000198, 20, 3, ts_drive_strength); 13423c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000198, 24, 3, ts_drive_strength); 13433c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x9000019C, 0, 3, ts_drive_strength); 13443c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x9000019C, 4, 3, ts_drive_strength); 13453c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x9000019C, 8, 3, ts_drive_strength); 13463c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x9000019C, 24, 3, ts_drive_strength); 13473c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x9000019C, 28, 3, ts_drive_strength); 13483c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x900001A0, 0, 3, ts_drive_strength); 13493c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x900001A0, 4, 3, ts_drive_strength); 13503c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x900001A0, 20, 3, ts_drive_strength); 13513c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x900001A0, 24, 3, ts_drive_strength); 13523c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x900001A0, 28, 3, ts_drive_strength); 13533c4e0415SDaniel Scheller 13543c4e0415SDaniel Scheller return stat; 13553c4e0415SDaniel Scheller } 13563c4e0415SDaniel Scheller 13573c4e0415SDaniel Scheller static int enable_tuner(struct mxl *state, u32 tuner, u32 enable) 13583c4e0415SDaniel Scheller { 13593c4e0415SDaniel Scheller int stat = 0; 13603c4e0415SDaniel Scheller struct MXL_HYDRA_TUNER_CMD ctrl_tuner_cmd; 13613c4e0415SDaniel Scheller u8 cmd_size = sizeof(ctrl_tuner_cmd); 13623c4e0415SDaniel Scheller u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; 13633c4e0415SDaniel Scheller u32 val, count = 10; 13643c4e0415SDaniel Scheller 13653c4e0415SDaniel Scheller ctrl_tuner_cmd.tuner_id = tuner; 13663c4e0415SDaniel Scheller ctrl_tuner_cmd.enable = enable; 13673c4e0415SDaniel Scheller BUILD_HYDRA_CMD(MXL_HYDRA_TUNER_ACTIVATE_CMD, MXL_CMD_WRITE, 13683c4e0415SDaniel Scheller cmd_size, &ctrl_tuner_cmd, cmd_buff); 13693c4e0415SDaniel Scheller stat = send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, 13703c4e0415SDaniel Scheller &cmd_buff[0]); 13713c4e0415SDaniel Scheller if (stat) 13723c4e0415SDaniel Scheller return stat; 13733c4e0415SDaniel Scheller read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val); 13743c4e0415SDaniel Scheller while (--count && ((val >> tuner) & 1) != enable) { 13753c4e0415SDaniel Scheller msleep(20); 13763c4e0415SDaniel Scheller read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val); 13773c4e0415SDaniel Scheller } 13783c4e0415SDaniel Scheller if (!count) 13793c4e0415SDaniel Scheller return -1; 13803c4e0415SDaniel Scheller read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val); 13813c4e0415SDaniel Scheller dev_dbg(state->i2cdev, "tuner %u ready = %u\n", 13823c4e0415SDaniel Scheller tuner, (val >> tuner) & 1); 13833c4e0415SDaniel Scheller 13843c4e0415SDaniel Scheller return 0; 13853c4e0415SDaniel Scheller } 13863c4e0415SDaniel Scheller 13873c4e0415SDaniel Scheller 13883c4e0415SDaniel Scheller static int config_ts(struct mxl *state, enum MXL_HYDRA_DEMOD_ID_E demod_id, 13893c4e0415SDaniel Scheller struct MXL_HYDRA_MPEGOUT_PARAM_T *mpeg_out_param_ptr) 13903c4e0415SDaniel Scheller { 13913c4e0415SDaniel Scheller int status = 0; 13923c4e0415SDaniel Scheller u32 nco_count_min = 0; 13933c4e0415SDaniel Scheller u32 clk_type = 0; 13943c4e0415SDaniel Scheller 13953c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_sync_polarity[MXL_HYDRA_DEMOD_MAX] = { 13963c4e0415SDaniel Scheller {0x90700010, 8, 1}, {0x90700010, 9, 1}, 13973c4e0415SDaniel Scheller {0x90700010, 10, 1}, {0x90700010, 11, 1}, 13983c4e0415SDaniel Scheller {0x90700010, 12, 1}, {0x90700010, 13, 1}, 13993c4e0415SDaniel Scheller {0x90700010, 14, 1}, {0x90700010, 15, 1} }; 14003c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_clock_polarity[MXL_HYDRA_DEMOD_MAX] = { 14013c4e0415SDaniel Scheller {0x90700010, 16, 1}, {0x90700010, 17, 1}, 14023c4e0415SDaniel Scheller {0x90700010, 18, 1}, {0x90700010, 19, 1}, 14033c4e0415SDaniel Scheller {0x90700010, 20, 1}, {0x90700010, 21, 1}, 14043c4e0415SDaniel Scheller {0x90700010, 22, 1}, {0x90700010, 23, 1} }; 14053c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_valid_polarity[MXL_HYDRA_DEMOD_MAX] = { 14063c4e0415SDaniel Scheller {0x90700014, 0, 1}, {0x90700014, 1, 1}, 14073c4e0415SDaniel Scheller {0x90700014, 2, 1}, {0x90700014, 3, 1}, 14083c4e0415SDaniel Scheller {0x90700014, 4, 1}, {0x90700014, 5, 1}, 14093c4e0415SDaniel Scheller {0x90700014, 6, 1}, {0x90700014, 7, 1} }; 14103c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_ts_clock_phase[MXL_HYDRA_DEMOD_MAX] = { 14113c4e0415SDaniel Scheller {0x90700018, 0, 3}, {0x90700018, 4, 3}, 14123c4e0415SDaniel Scheller {0x90700018, 8, 3}, {0x90700018, 12, 3}, 14133c4e0415SDaniel Scheller {0x90700018, 16, 3}, {0x90700018, 20, 3}, 14143c4e0415SDaniel Scheller {0x90700018, 24, 3}, {0x90700018, 28, 3} }; 14153c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_lsb_first[MXL_HYDRA_DEMOD_MAX] = { 14163c4e0415SDaniel Scheller {0x9070000C, 16, 1}, {0x9070000C, 17, 1}, 14173c4e0415SDaniel Scheller {0x9070000C, 18, 1}, {0x9070000C, 19, 1}, 14183c4e0415SDaniel Scheller {0x9070000C, 20, 1}, {0x9070000C, 21, 1}, 14193c4e0415SDaniel Scheller {0x9070000C, 22, 1}, {0x9070000C, 23, 1} }; 14203c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_sync_byte[MXL_HYDRA_DEMOD_MAX] = { 14213c4e0415SDaniel Scheller {0x90700010, 0, 1}, {0x90700010, 1, 1}, 14223c4e0415SDaniel Scheller {0x90700010, 2, 1}, {0x90700010, 3, 1}, 14233c4e0415SDaniel Scheller {0x90700010, 4, 1}, {0x90700010, 5, 1}, 14243c4e0415SDaniel Scheller {0x90700010, 6, 1}, {0x90700010, 7, 1} }; 14253c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_enable_output[MXL_HYDRA_DEMOD_MAX] = { 14263c4e0415SDaniel Scheller {0x9070000C, 0, 1}, {0x9070000C, 1, 1}, 14273c4e0415SDaniel Scheller {0x9070000C, 2, 1}, {0x9070000C, 3, 1}, 14283c4e0415SDaniel Scheller {0x9070000C, 4, 1}, {0x9070000C, 5, 1}, 14293c4e0415SDaniel Scheller {0x9070000C, 6, 1}, {0x9070000C, 7, 1} }; 14303c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_err_replace_sync[MXL_HYDRA_DEMOD_MAX] = { 14313c4e0415SDaniel Scheller {0x9070000C, 24, 1}, {0x9070000C, 25, 1}, 14323c4e0415SDaniel Scheller {0x9070000C, 26, 1}, {0x9070000C, 27, 1}, 14333c4e0415SDaniel Scheller {0x9070000C, 28, 1}, {0x9070000C, 29, 1}, 14343c4e0415SDaniel Scheller {0x9070000C, 30, 1}, {0x9070000C, 31, 1} }; 14353c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_err_replace_valid[MXL_HYDRA_DEMOD_MAX] = { 14363c4e0415SDaniel Scheller {0x90700014, 8, 1}, {0x90700014, 9, 1}, 14373c4e0415SDaniel Scheller {0x90700014, 10, 1}, {0x90700014, 11, 1}, 14383c4e0415SDaniel Scheller {0x90700014, 12, 1}, {0x90700014, 13, 1}, 14393c4e0415SDaniel Scheller {0x90700014, 14, 1}, {0x90700014, 15, 1} }; 14403c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_continuous_clock[MXL_HYDRA_DEMOD_MAX] = { 14413c4e0415SDaniel Scheller {0x907001D4, 0, 1}, {0x907001D4, 1, 1}, 14423c4e0415SDaniel Scheller {0x907001D4, 2, 1}, {0x907001D4, 3, 1}, 14433c4e0415SDaniel Scheller {0x907001D4, 4, 1}, {0x907001D4, 5, 1}, 14443c4e0415SDaniel Scheller {0x907001D4, 6, 1}, {0x907001D4, 7, 1} }; 14453c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_nco_clock_rate[MXL_HYDRA_DEMOD_MAX] = { 14463c4e0415SDaniel Scheller {0x90700044, 16, 80}, {0x90700044, 16, 81}, 14473c4e0415SDaniel Scheller {0x90700044, 16, 82}, {0x90700044, 16, 83}, 14483c4e0415SDaniel Scheller {0x90700044, 16, 84}, {0x90700044, 16, 85}, 14493c4e0415SDaniel Scheller {0x90700044, 16, 86}, {0x90700044, 16, 87} }; 14503c4e0415SDaniel Scheller 14513c4e0415SDaniel Scheller demod_id = state->base->ts_map[demod_id]; 14523c4e0415SDaniel Scheller 14533c4e0415SDaniel Scheller if (mpeg_out_param_ptr->enable == MXL_ENABLE) { 14543c4e0415SDaniel Scheller if (mpeg_out_param_ptr->mpeg_mode == 14553c4e0415SDaniel Scheller MXL_HYDRA_MPEG_MODE_PARALLEL) { 14563c4e0415SDaniel Scheller } else { 14573c4e0415SDaniel Scheller cfg_ts_pad_mux(state, MXL_TRUE); 14583c4e0415SDaniel Scheller update_by_mnemonic(state, 14593c4e0415SDaniel Scheller 0x90700010, 27, 1, MXL_FALSE); 14603c4e0415SDaniel Scheller } 14613c4e0415SDaniel Scheller } 14623c4e0415SDaniel Scheller 14633c4e0415SDaniel Scheller nco_count_min = 14643c4e0415SDaniel Scheller (u32)(MXL_HYDRA_NCO_CLK / mpeg_out_param_ptr->max_mpeg_clk_rate); 14653c4e0415SDaniel Scheller 14663c4e0415SDaniel Scheller if (state->base->chipversion >= 2) { 14673c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14683c4e0415SDaniel Scheller xpt_nco_clock_rate[demod_id].reg_addr, /* Reg Addr */ 14693c4e0415SDaniel Scheller xpt_nco_clock_rate[demod_id].lsb_pos, /* LSB pos */ 14703c4e0415SDaniel Scheller xpt_nco_clock_rate[demod_id].num_of_bits, /* Num of bits */ 14713c4e0415SDaniel Scheller nco_count_min); /* Data */ 14723c4e0415SDaniel Scheller } else 14733c4e0415SDaniel Scheller update_by_mnemonic(state, 0x90700044, 16, 8, nco_count_min); 14743c4e0415SDaniel Scheller 14753c4e0415SDaniel Scheller if (mpeg_out_param_ptr->mpeg_clk_type == MXL_HYDRA_MPEG_CLK_CONTINUOUS) 14763c4e0415SDaniel Scheller clk_type = 1; 14773c4e0415SDaniel Scheller 14783c4e0415SDaniel Scheller if (mpeg_out_param_ptr->mpeg_mode < MXL_HYDRA_MPEG_MODE_PARALLEL) { 14793c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14803c4e0415SDaniel Scheller xpt_continuous_clock[demod_id].reg_addr, 14813c4e0415SDaniel Scheller xpt_continuous_clock[demod_id].lsb_pos, 14823c4e0415SDaniel Scheller xpt_continuous_clock[demod_id].num_of_bits, 14833c4e0415SDaniel Scheller clk_type); 14843c4e0415SDaniel Scheller } else 14853c4e0415SDaniel Scheller update_by_mnemonic(state, 0x907001D4, 8, 1, clk_type); 14863c4e0415SDaniel Scheller 14873c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14883c4e0415SDaniel Scheller xpt_sync_polarity[demod_id].reg_addr, 14893c4e0415SDaniel Scheller xpt_sync_polarity[demod_id].lsb_pos, 14903c4e0415SDaniel Scheller xpt_sync_polarity[demod_id].num_of_bits, 14913c4e0415SDaniel Scheller mpeg_out_param_ptr->mpeg_sync_pol); 14923c4e0415SDaniel Scheller 14933c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14943c4e0415SDaniel Scheller xpt_valid_polarity[demod_id].reg_addr, 14953c4e0415SDaniel Scheller xpt_valid_polarity[demod_id].lsb_pos, 14963c4e0415SDaniel Scheller xpt_valid_polarity[demod_id].num_of_bits, 14973c4e0415SDaniel Scheller mpeg_out_param_ptr->mpeg_valid_pol); 14983c4e0415SDaniel Scheller 14993c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15003c4e0415SDaniel Scheller xpt_clock_polarity[demod_id].reg_addr, 15013c4e0415SDaniel Scheller xpt_clock_polarity[demod_id].lsb_pos, 15023c4e0415SDaniel Scheller xpt_clock_polarity[demod_id].num_of_bits, 15033c4e0415SDaniel Scheller mpeg_out_param_ptr->mpeg_clk_pol); 15043c4e0415SDaniel Scheller 15053c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15063c4e0415SDaniel Scheller xpt_sync_byte[demod_id].reg_addr, 15073c4e0415SDaniel Scheller xpt_sync_byte[demod_id].lsb_pos, 15083c4e0415SDaniel Scheller xpt_sync_byte[demod_id].num_of_bits, 15093c4e0415SDaniel Scheller mpeg_out_param_ptr->mpeg_sync_pulse_width); 15103c4e0415SDaniel Scheller 15113c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15123c4e0415SDaniel Scheller xpt_ts_clock_phase[demod_id].reg_addr, 15133c4e0415SDaniel Scheller xpt_ts_clock_phase[demod_id].lsb_pos, 15143c4e0415SDaniel Scheller xpt_ts_clock_phase[demod_id].num_of_bits, 15153c4e0415SDaniel Scheller mpeg_out_param_ptr->mpeg_clk_phase); 15163c4e0415SDaniel Scheller 15173c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15183c4e0415SDaniel Scheller xpt_lsb_first[demod_id].reg_addr, 15193c4e0415SDaniel Scheller xpt_lsb_first[demod_id].lsb_pos, 15203c4e0415SDaniel Scheller xpt_lsb_first[demod_id].num_of_bits, 15213c4e0415SDaniel Scheller mpeg_out_param_ptr->lsb_or_msb_first); 15223c4e0415SDaniel Scheller 15233c4e0415SDaniel Scheller switch (mpeg_out_param_ptr->mpeg_error_indication) { 15243c4e0415SDaniel Scheller case MXL_HYDRA_MPEG_ERR_REPLACE_SYNC: 15253c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15263c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].reg_addr, 15273c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].lsb_pos, 15283c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].num_of_bits, 15293c4e0415SDaniel Scheller MXL_TRUE); 15303c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15313c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].reg_addr, 15323c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].lsb_pos, 15333c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].num_of_bits, 15343c4e0415SDaniel Scheller MXL_FALSE); 15353c4e0415SDaniel Scheller break; 15363c4e0415SDaniel Scheller 15373c4e0415SDaniel Scheller case MXL_HYDRA_MPEG_ERR_REPLACE_VALID: 15383c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15393c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].reg_addr, 15403c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].lsb_pos, 15413c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].num_of_bits, 15423c4e0415SDaniel Scheller MXL_FALSE); 15433c4e0415SDaniel Scheller 15443c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15453c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].reg_addr, 15463c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].lsb_pos, 15473c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].num_of_bits, 15483c4e0415SDaniel Scheller MXL_TRUE); 15493c4e0415SDaniel Scheller break; 15503c4e0415SDaniel Scheller 15513c4e0415SDaniel Scheller case MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED: 15523c4e0415SDaniel Scheller default: 15533c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15543c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].reg_addr, 15553c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].lsb_pos, 15563c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].num_of_bits, 15573c4e0415SDaniel Scheller MXL_FALSE); 15583c4e0415SDaniel Scheller 15593c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15603c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].reg_addr, 15613c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].lsb_pos, 15623c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].num_of_bits, 15633c4e0415SDaniel Scheller MXL_FALSE); 15643c4e0415SDaniel Scheller 15653c4e0415SDaniel Scheller break; 15663c4e0415SDaniel Scheller 15673c4e0415SDaniel Scheller } 15683c4e0415SDaniel Scheller 15693c4e0415SDaniel Scheller if (mpeg_out_param_ptr->mpeg_mode != MXL_HYDRA_MPEG_MODE_PARALLEL) { 15703c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15713c4e0415SDaniel Scheller xpt_enable_output[demod_id].reg_addr, 15723c4e0415SDaniel Scheller xpt_enable_output[demod_id].lsb_pos, 15733c4e0415SDaniel Scheller xpt_enable_output[demod_id].num_of_bits, 15743c4e0415SDaniel Scheller mpeg_out_param_ptr->enable); 15753c4e0415SDaniel Scheller } 15763c4e0415SDaniel Scheller return status; 15773c4e0415SDaniel Scheller } 15783c4e0415SDaniel Scheller 15793c4e0415SDaniel Scheller static int config_mux(struct mxl *state) 15803c4e0415SDaniel Scheller { 15813c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 0, 1, 0); 15823c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 1, 1, 0); 15833c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 2, 1, 0); 15843c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 3, 1, 0); 15853c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 4, 1, 0); 15863c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 5, 1, 0); 15873c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 6, 1, 0); 15883c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 7, 1, 0); 15893c4e0415SDaniel Scheller update_by_mnemonic(state, 0x90700008, 0, 2, 1); 15903c4e0415SDaniel Scheller update_by_mnemonic(state, 0x90700008, 2, 2, 1); 15913c4e0415SDaniel Scheller return 0; 15923c4e0415SDaniel Scheller } 15933c4e0415SDaniel Scheller 15943c4e0415SDaniel Scheller static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg) 15953c4e0415SDaniel Scheller { 15963c4e0415SDaniel Scheller int stat = 0; 15973c4e0415SDaniel Scheller u8 *buf; 15983c4e0415SDaniel Scheller 15993c4e0415SDaniel Scheller if (cfg->fw) 16003c4e0415SDaniel Scheller return firmware_download(state, cfg->fw, cfg->fw_len); 16013c4e0415SDaniel Scheller 16023c4e0415SDaniel Scheller if (!cfg->fw_read) 16033c4e0415SDaniel Scheller return -1; 16043c4e0415SDaniel Scheller 16053c4e0415SDaniel Scheller buf = vmalloc(0x40000); 16063c4e0415SDaniel Scheller if (!buf) 16073c4e0415SDaniel Scheller return -ENOMEM; 16083c4e0415SDaniel Scheller 16093c4e0415SDaniel Scheller cfg->fw_read(cfg->fw_priv, buf, 0x40000); 16103c4e0415SDaniel Scheller stat = firmware_download(state, buf, 0x40000); 16113c4e0415SDaniel Scheller vfree(buf); 16123c4e0415SDaniel Scheller 16133c4e0415SDaniel Scheller return stat; 16143c4e0415SDaniel Scheller } 16153c4e0415SDaniel Scheller 16163c4e0415SDaniel Scheller static int validate_sku(struct mxl *state) 16173c4e0415SDaniel Scheller { 16183c4e0415SDaniel Scheller u32 pad_mux_bond = 0, prcm_chip_id = 0, prcm_so_cid = 0; 16193c4e0415SDaniel Scheller int status; 16203c4e0415SDaniel Scheller u32 type = state->base->type; 16213c4e0415SDaniel Scheller 16223c4e0415SDaniel Scheller status = read_by_mnemonic(state, 0x90000190, 0, 3, &pad_mux_bond); 16233c4e0415SDaniel Scheller status |= read_by_mnemonic(state, 0x80030000, 0, 12, &prcm_chip_id); 16243c4e0415SDaniel Scheller status |= read_by_mnemonic(state, 0x80030004, 24, 8, &prcm_so_cid); 16253c4e0415SDaniel Scheller if (status) 16263c4e0415SDaniel Scheller return -1; 16273c4e0415SDaniel Scheller 16283c4e0415SDaniel Scheller dev_info(state->i2cdev, "padMuxBond=%08x, prcmChipId=%08x, prcmSoCId=%08x\n", 16293c4e0415SDaniel Scheller pad_mux_bond, prcm_chip_id, prcm_so_cid); 16303c4e0415SDaniel Scheller 16313c4e0415SDaniel Scheller if (prcm_chip_id != 0x560) { 16323c4e0415SDaniel Scheller switch (pad_mux_bond) { 16333c4e0415SDaniel Scheller case MXL_HYDRA_SKU_ID_581: 16343c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_581) 16353c4e0415SDaniel Scheller return 0; 16363c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_581S) { 16373c4e0415SDaniel Scheller state->base->type = MXL_HYDRA_DEVICE_581; 16383c4e0415SDaniel Scheller return 0; 16393c4e0415SDaniel Scheller } 16403c4e0415SDaniel Scheller break; 16413c4e0415SDaniel Scheller case MXL_HYDRA_SKU_ID_584: 16423c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_584) 16433c4e0415SDaniel Scheller return 0; 16443c4e0415SDaniel Scheller break; 16453c4e0415SDaniel Scheller case MXL_HYDRA_SKU_ID_544: 16463c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_544) 16473c4e0415SDaniel Scheller return 0; 16483c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_542) 16493c4e0415SDaniel Scheller return 0; 16503c4e0415SDaniel Scheller break; 16513c4e0415SDaniel Scheller case MXL_HYDRA_SKU_ID_582: 16523c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_582) 16533c4e0415SDaniel Scheller return 0; 16543c4e0415SDaniel Scheller break; 16553c4e0415SDaniel Scheller default: 16563c4e0415SDaniel Scheller return -1; 16573c4e0415SDaniel Scheller } 16583c4e0415SDaniel Scheller } else { 16593c4e0415SDaniel Scheller 16603c4e0415SDaniel Scheller } 16613c4e0415SDaniel Scheller return -1; 16623c4e0415SDaniel Scheller } 16633c4e0415SDaniel Scheller 16643c4e0415SDaniel Scheller static int get_fwinfo(struct mxl *state) 16653c4e0415SDaniel Scheller { 16663c4e0415SDaniel Scheller int status; 16673c4e0415SDaniel Scheller u32 val = 0; 16683c4e0415SDaniel Scheller 16693c4e0415SDaniel Scheller status = read_by_mnemonic(state, 0x90000190, 0, 3, &val); 16703c4e0415SDaniel Scheller if (status) 16713c4e0415SDaniel Scheller return status; 16723c4e0415SDaniel Scheller dev_info(state->i2cdev, "chipID=%08x\n", val); 16733c4e0415SDaniel Scheller 16743c4e0415SDaniel Scheller status = read_by_mnemonic(state, 0x80030004, 8, 8, &val); 16753c4e0415SDaniel Scheller if (status) 16763c4e0415SDaniel Scheller return status; 16773c4e0415SDaniel Scheller dev_info(state->i2cdev, "chipVer=%08x\n", val); 16783c4e0415SDaniel Scheller 16793c4e0415SDaniel Scheller status = read_register(state, HYDRA_FIRMWARE_VERSION, &val); 16803c4e0415SDaniel Scheller if (status) 16813c4e0415SDaniel Scheller return status; 16823c4e0415SDaniel Scheller dev_info(state->i2cdev, "FWVer=%08x\n", val); 16833c4e0415SDaniel Scheller 16843c4e0415SDaniel Scheller state->base->fwversion = val; 16853c4e0415SDaniel Scheller return status; 16863c4e0415SDaniel Scheller } 16873c4e0415SDaniel Scheller 16883c4e0415SDaniel Scheller 16893c4e0415SDaniel Scheller static u8 ts_map1_to_1[MXL_HYDRA_DEMOD_MAX] = { 16903c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_0, 16913c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_1, 16923c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_2, 16933c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_3, 16943c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_4, 16953c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_5, 16963c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_6, 16973c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_7, 16983c4e0415SDaniel Scheller }; 16993c4e0415SDaniel Scheller 17003c4e0415SDaniel Scheller static u8 ts_map54x[MXL_HYDRA_DEMOD_MAX] = { 17013c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_2, 17023c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_3, 17033c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_4, 17043c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_5, 17053c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_MAX, 17063c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_MAX, 17073c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_MAX, 17083c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_MAX, 17093c4e0415SDaniel Scheller }; 17103c4e0415SDaniel Scheller 17113c4e0415SDaniel Scheller static int probe(struct mxl *state, struct mxl5xx_cfg *cfg) 17123c4e0415SDaniel Scheller { 17133c4e0415SDaniel Scheller u32 chipver; 17143c4e0415SDaniel Scheller int fw, status, j; 17153c4e0415SDaniel Scheller struct MXL_HYDRA_MPEGOUT_PARAM_T mpeg_interface_cfg; 17163c4e0415SDaniel Scheller 17173c4e0415SDaniel Scheller state->base->ts_map = ts_map1_to_1; 17183c4e0415SDaniel Scheller 17193c4e0415SDaniel Scheller switch (state->base->type) { 17203c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_581: 17213c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_581S: 17223c4e0415SDaniel Scheller state->base->can_clkout = 1; 17233c4e0415SDaniel Scheller state->base->demod_num = 8; 17243c4e0415SDaniel Scheller state->base->tuner_num = 1; 17253c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_581; 17263c4e0415SDaniel Scheller break; 17273c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_582: 17283c4e0415SDaniel Scheller state->base->can_clkout = 1; 17293c4e0415SDaniel Scheller state->base->demod_num = 8; 17303c4e0415SDaniel Scheller state->base->tuner_num = 3; 17313c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_582; 17323c4e0415SDaniel Scheller break; 17333c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_585: 17343c4e0415SDaniel Scheller state->base->can_clkout = 0; 17353c4e0415SDaniel Scheller state->base->demod_num = 8; 17363c4e0415SDaniel Scheller state->base->tuner_num = 4; 17373c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_585; 17383c4e0415SDaniel Scheller break; 17393c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_544: 17403c4e0415SDaniel Scheller state->base->can_clkout = 0; 17413c4e0415SDaniel Scheller state->base->demod_num = 4; 17423c4e0415SDaniel Scheller state->base->tuner_num = 4; 17433c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_544; 17443c4e0415SDaniel Scheller state->base->ts_map = ts_map54x; 17453c4e0415SDaniel Scheller break; 17463c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_541: 17473c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_541S: 17483c4e0415SDaniel Scheller state->base->can_clkout = 0; 17493c4e0415SDaniel Scheller state->base->demod_num = 4; 17503c4e0415SDaniel Scheller state->base->tuner_num = 1; 17513c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_541; 17523c4e0415SDaniel Scheller state->base->ts_map = ts_map54x; 17533c4e0415SDaniel Scheller break; 17543c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_561: 17553c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_561S: 17563c4e0415SDaniel Scheller state->base->can_clkout = 0; 17573c4e0415SDaniel Scheller state->base->demod_num = 6; 17583c4e0415SDaniel Scheller state->base->tuner_num = 1; 17593c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_561; 17603c4e0415SDaniel Scheller break; 17613c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_568: 17623c4e0415SDaniel Scheller state->base->can_clkout = 0; 17633c4e0415SDaniel Scheller state->base->demod_num = 8; 17643c4e0415SDaniel Scheller state->base->tuner_num = 1; 17653c4e0415SDaniel Scheller state->base->chan_bond = 1; 17663c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_568; 17673c4e0415SDaniel Scheller break; 17683c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_542: 17693c4e0415SDaniel Scheller state->base->can_clkout = 1; 17703c4e0415SDaniel Scheller state->base->demod_num = 4; 17713c4e0415SDaniel Scheller state->base->tuner_num = 3; 17723c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_542; 17733c4e0415SDaniel Scheller state->base->ts_map = ts_map54x; 17743c4e0415SDaniel Scheller break; 17753c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_TEST: 17763c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_584: 17773c4e0415SDaniel Scheller default: 17783c4e0415SDaniel Scheller state->base->can_clkout = 0; 17793c4e0415SDaniel Scheller state->base->demod_num = 8; 17803c4e0415SDaniel Scheller state->base->tuner_num = 4; 17813c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_584; 17823c4e0415SDaniel Scheller break; 17833c4e0415SDaniel Scheller } 17843c4e0415SDaniel Scheller 17853c4e0415SDaniel Scheller status = validate_sku(state); 17863c4e0415SDaniel Scheller if (status) 17873c4e0415SDaniel Scheller return status; 17883c4e0415SDaniel Scheller 17893c4e0415SDaniel Scheller update_by_mnemonic(state, 0x80030014, 9, 1, 1); 17903c4e0415SDaniel Scheller update_by_mnemonic(state, 0x8003003C, 12, 1, 1); 17913c4e0415SDaniel Scheller status = read_by_mnemonic(state, 0x80030000, 12, 4, &chipver); 17923c4e0415SDaniel Scheller if (status) 17933c4e0415SDaniel Scheller state->base->chipversion = 0; 17943c4e0415SDaniel Scheller else 17953c4e0415SDaniel Scheller state->base->chipversion = (chipver == 2) ? 2 : 1; 17963c4e0415SDaniel Scheller dev_info(state->i2cdev, "Hydra chip version %u\n", 17973c4e0415SDaniel Scheller state->base->chipversion); 17983c4e0415SDaniel Scheller 17993c4e0415SDaniel Scheller cfg_dev_xtal(state, cfg->clk, cfg->cap, 0); 18003c4e0415SDaniel Scheller 18013c4e0415SDaniel Scheller fw = firmware_is_alive(state); 18023c4e0415SDaniel Scheller if (!fw) { 18033c4e0415SDaniel Scheller status = load_fw(state, cfg); 18043c4e0415SDaniel Scheller if (status) 18053c4e0415SDaniel Scheller return status; 18063c4e0415SDaniel Scheller } 18073c4e0415SDaniel Scheller get_fwinfo(state); 18083c4e0415SDaniel Scheller 18093c4e0415SDaniel Scheller config_mux(state); 18103c4e0415SDaniel Scheller mpeg_interface_cfg.enable = MXL_ENABLE; 18113c4e0415SDaniel Scheller mpeg_interface_cfg.lsb_or_msb_first = MXL_HYDRA_MPEG_SERIAL_MSB_1ST; 18123c4e0415SDaniel Scheller /* supports only (0-104&139)MHz */ 18133c4e0415SDaniel Scheller if (cfg->ts_clk) 18143c4e0415SDaniel Scheller mpeg_interface_cfg.max_mpeg_clk_rate = cfg->ts_clk; 18153c4e0415SDaniel Scheller else 18163c4e0415SDaniel Scheller mpeg_interface_cfg.max_mpeg_clk_rate = 69; /* 139; */ 18173c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_clk_phase = MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_0_DEG; 18183c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_clk_pol = MXL_HYDRA_MPEG_CLK_IN_PHASE; 18193c4e0415SDaniel Scheller /* MXL_HYDRA_MPEG_CLK_GAPPED; */ 18203c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_clk_type = MXL_HYDRA_MPEG_CLK_CONTINUOUS; 18213c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_error_indication = 18223c4e0415SDaniel Scheller MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED; 18233c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_mode = MXL_HYDRA_MPEG_MODE_SERIAL_3_WIRE; 18243c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_sync_pol = MXL_HYDRA_MPEG_ACTIVE_HIGH; 18253c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_sync_pulse_width = MXL_HYDRA_MPEG_SYNC_WIDTH_BIT; 18263c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_valid_pol = MXL_HYDRA_MPEG_ACTIVE_HIGH; 18273c4e0415SDaniel Scheller 18283c4e0415SDaniel Scheller for (j = 0; j < state->base->demod_num; j++) { 18293c4e0415SDaniel Scheller status = config_ts(state, (enum MXL_HYDRA_DEMOD_ID_E) j, 18303c4e0415SDaniel Scheller &mpeg_interface_cfg); 18313c4e0415SDaniel Scheller if (status) 18323c4e0415SDaniel Scheller return status; 18333c4e0415SDaniel Scheller } 18343c4e0415SDaniel Scheller set_drive_strength(state, 1); 18353c4e0415SDaniel Scheller return 0; 18363c4e0415SDaniel Scheller } 18373c4e0415SDaniel Scheller 18383c4e0415SDaniel Scheller struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, 18393c4e0415SDaniel Scheller struct mxl5xx_cfg *cfg, u32 demod, u32 tuner, 18403c4e0415SDaniel Scheller int (**fn_set_input)(struct dvb_frontend *, int)) 18413c4e0415SDaniel Scheller { 18423c4e0415SDaniel Scheller struct mxl *state; 18433c4e0415SDaniel Scheller struct mxl_base *base; 18443c4e0415SDaniel Scheller 18453c4e0415SDaniel Scheller state = kzalloc(sizeof(struct mxl), GFP_KERNEL); 18463c4e0415SDaniel Scheller if (!state) 18473c4e0415SDaniel Scheller return NULL; 18483c4e0415SDaniel Scheller 18493c4e0415SDaniel Scheller state->demod = demod; 18503c4e0415SDaniel Scheller state->tuner = tuner; 18513c4e0415SDaniel Scheller state->tuner_in_use = 0xffffffff; 18523c4e0415SDaniel Scheller state->i2cdev = &i2c->dev; 18533c4e0415SDaniel Scheller 18543c4e0415SDaniel Scheller base = match_base(i2c, cfg->adr); 18553c4e0415SDaniel Scheller if (base) { 18563c4e0415SDaniel Scheller base->count++; 18573c4e0415SDaniel Scheller if (base->count > base->demod_num) 18583c4e0415SDaniel Scheller goto fail; 18593c4e0415SDaniel Scheller state->base = base; 18603c4e0415SDaniel Scheller } else { 18613c4e0415SDaniel Scheller base = kzalloc(sizeof(struct mxl_base), GFP_KERNEL); 18623c4e0415SDaniel Scheller if (!base) 18633c4e0415SDaniel Scheller goto fail; 18643c4e0415SDaniel Scheller base->i2c = i2c; 18653c4e0415SDaniel Scheller base->adr = cfg->adr; 18663c4e0415SDaniel Scheller base->type = cfg->type; 18673c4e0415SDaniel Scheller base->count = 1; 18683c4e0415SDaniel Scheller mutex_init(&base->i2c_lock); 18693c4e0415SDaniel Scheller mutex_init(&base->status_lock); 18703c4e0415SDaniel Scheller mutex_init(&base->tune_lock); 18713c4e0415SDaniel Scheller INIT_LIST_HEAD(&base->mxls); 18723c4e0415SDaniel Scheller 18733c4e0415SDaniel Scheller state->base = base; 18743c4e0415SDaniel Scheller if (probe(state, cfg) < 0) { 18753c4e0415SDaniel Scheller kfree(base); 18763c4e0415SDaniel Scheller goto fail; 18773c4e0415SDaniel Scheller } 18783c4e0415SDaniel Scheller list_add(&base->mxllist, &mxllist); 18793c4e0415SDaniel Scheller } 18803c4e0415SDaniel Scheller state->fe.ops = mxl_ops; 18813c4e0415SDaniel Scheller state->xbar[0] = 4; 18823c4e0415SDaniel Scheller state->xbar[1] = demod; 18833c4e0415SDaniel Scheller state->xbar[2] = 8; 18843c4e0415SDaniel Scheller state->fe.demodulator_priv = state; 18853c4e0415SDaniel Scheller *fn_set_input = set_input; 18863c4e0415SDaniel Scheller 18873c4e0415SDaniel Scheller list_add(&state->mxl, &base->mxls); 18883c4e0415SDaniel Scheller return &state->fe; 18893c4e0415SDaniel Scheller 18903c4e0415SDaniel Scheller fail: 18913c4e0415SDaniel Scheller kfree(state); 18923c4e0415SDaniel Scheller return NULL; 18933c4e0415SDaniel Scheller } 18943c4e0415SDaniel Scheller EXPORT_SYMBOL_GPL(mxl5xx_attach); 18953c4e0415SDaniel Scheller 18963c4e0415SDaniel Scheller MODULE_DESCRIPTION("MaxLinear MxL5xx DVB-S/S2 tuner-demodulator driver"); 18973c4e0415SDaniel Scheller MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR"); 18983c4e0415SDaniel Scheller MODULE_LICENSE("GPL"); 1899