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 363c4e0415SDaniel Scheller #include "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 3783c4e0415SDaniel Scheller static int get_algo(struct dvb_frontend *fe) 3793c4e0415SDaniel Scheller { 3803c4e0415SDaniel Scheller return DVBFE_ALGO_HW; 3813c4e0415SDaniel Scheller } 3823c4e0415SDaniel Scheller 3833c4e0415SDaniel Scheller static int cfg_demod_abort_tune(struct mxl *state) 3843c4e0415SDaniel Scheller { 3853c4e0415SDaniel Scheller struct MXL_HYDRA_DEMOD_ABORT_TUNE_T abort_tune_cmd; 3863c4e0415SDaniel Scheller u8 cmd_size = sizeof(abort_tune_cmd); 3873c4e0415SDaniel Scheller u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; 3883c4e0415SDaniel Scheller 3893c4e0415SDaniel Scheller abort_tune_cmd.demod_id = state->demod; 3903c4e0415SDaniel Scheller BUILD_HYDRA_CMD(MXL_HYDRA_ABORT_TUNE_CMD, MXL_CMD_WRITE, 3913c4e0415SDaniel Scheller cmd_size, &abort_tune_cmd, cmd_buff); 3923c4e0415SDaniel Scheller return send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, 3933c4e0415SDaniel Scheller &cmd_buff[0]); 3943c4e0415SDaniel Scheller } 3953c4e0415SDaniel Scheller 3963c4e0415SDaniel Scheller static int send_master_cmd(struct dvb_frontend *fe, 3973c4e0415SDaniel Scheller struct dvb_diseqc_master_cmd *cmd) 3983c4e0415SDaniel Scheller { 3993c4e0415SDaniel Scheller /*struct mxl *state = fe->demodulator_priv;*/ 4003c4e0415SDaniel Scheller 4013c4e0415SDaniel Scheller return 0; /*CfgDemodAbortTune(state);*/ 4023c4e0415SDaniel Scheller } 4033c4e0415SDaniel Scheller 4043c4e0415SDaniel Scheller static int set_parameters(struct dvb_frontend *fe) 4053c4e0415SDaniel Scheller { 4063c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 4073c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 4083c4e0415SDaniel Scheller struct MXL_HYDRA_DEMOD_PARAM_T demod_chan_cfg; 4093c4e0415SDaniel Scheller u8 cmd_size = sizeof(demod_chan_cfg); 4103c4e0415SDaniel Scheller u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; 4113c4e0415SDaniel Scheller u32 srange = 10; 4123c4e0415SDaniel Scheller int stat; 4133c4e0415SDaniel Scheller 4143c4e0415SDaniel Scheller if (p->frequency < 950000 || p->frequency > 2150000) 4153c4e0415SDaniel Scheller return -EINVAL; 4163c4e0415SDaniel Scheller if (p->symbol_rate < 1000000 || p->symbol_rate > 45000000) 4173c4e0415SDaniel Scheller return -EINVAL; 4183c4e0415SDaniel Scheller 4193c4e0415SDaniel Scheller /* CfgDemodAbortTune(state); */ 4203c4e0415SDaniel Scheller 4213c4e0415SDaniel Scheller switch (p->delivery_system) { 4223c4e0415SDaniel Scheller case SYS_DSS: 4233c4e0415SDaniel Scheller demod_chan_cfg.standard = MXL_HYDRA_DSS; 4243c4e0415SDaniel Scheller demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_AUTO; 4253c4e0415SDaniel Scheller break; 4263c4e0415SDaniel Scheller case SYS_DVBS: 4273c4e0415SDaniel Scheller srange = p->symbol_rate / 1000000; 4283c4e0415SDaniel Scheller if (srange > 10) 4293c4e0415SDaniel Scheller srange = 10; 4303c4e0415SDaniel Scheller demod_chan_cfg.standard = MXL_HYDRA_DVBS; 4313c4e0415SDaniel Scheller demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_0_35; 4323c4e0415SDaniel Scheller demod_chan_cfg.modulation_scheme = MXL_HYDRA_MOD_QPSK; 4333c4e0415SDaniel Scheller demod_chan_cfg.pilots = MXL_HYDRA_PILOTS_OFF; 4343c4e0415SDaniel Scheller break; 4353c4e0415SDaniel Scheller case SYS_DVBS2: 4363c4e0415SDaniel Scheller demod_chan_cfg.standard = MXL_HYDRA_DVBS2; 4373c4e0415SDaniel Scheller demod_chan_cfg.roll_off = MXL_HYDRA_ROLLOFF_AUTO; 4383c4e0415SDaniel Scheller demod_chan_cfg.modulation_scheme = MXL_HYDRA_MOD_AUTO; 4393c4e0415SDaniel Scheller demod_chan_cfg.pilots = MXL_HYDRA_PILOTS_AUTO; 4403c4e0415SDaniel Scheller /* cfg_scrambler(state); */ 4413c4e0415SDaniel Scheller break; 4423c4e0415SDaniel Scheller default: 4433c4e0415SDaniel Scheller return -EINVAL; 4443c4e0415SDaniel Scheller } 4453c4e0415SDaniel Scheller demod_chan_cfg.tuner_index = state->tuner; 4463c4e0415SDaniel Scheller demod_chan_cfg.demod_index = state->demod; 4473c4e0415SDaniel Scheller demod_chan_cfg.frequency_in_hz = p->frequency * 1000; 4483c4e0415SDaniel Scheller demod_chan_cfg.symbol_rate_in_hz = p->symbol_rate; 4493c4e0415SDaniel Scheller demod_chan_cfg.max_carrier_offset_in_mhz = srange; 4503c4e0415SDaniel Scheller demod_chan_cfg.spectrum_inversion = MXL_HYDRA_SPECTRUM_AUTO; 4513c4e0415SDaniel Scheller demod_chan_cfg.fec_code_rate = MXL_HYDRA_FEC_AUTO; 4523c4e0415SDaniel Scheller 4533c4e0415SDaniel Scheller mutex_lock(&state->base->tune_lock); 4543c4e0415SDaniel Scheller if (time_after(jiffies + msecs_to_jiffies(200), 4553c4e0415SDaniel Scheller state->base->next_tune)) 4563c4e0415SDaniel Scheller while (time_before(jiffies, state->base->next_tune)) 4573c4e0415SDaniel Scheller usleep_range(10000, 11000); 4583c4e0415SDaniel Scheller state->base->next_tune = jiffies + msecs_to_jiffies(100); 4593c4e0415SDaniel Scheller state->tuner_in_use = state->tuner; 4603c4e0415SDaniel Scheller BUILD_HYDRA_CMD(MXL_HYDRA_DEMOD_SET_PARAM_CMD, MXL_CMD_WRITE, 4613c4e0415SDaniel Scheller cmd_size, &demod_chan_cfg, cmd_buff); 4623c4e0415SDaniel Scheller stat = send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, 4633c4e0415SDaniel Scheller &cmd_buff[0]); 4643c4e0415SDaniel Scheller mutex_unlock(&state->base->tune_lock); 4653c4e0415SDaniel Scheller return stat; 4663c4e0415SDaniel Scheller } 4673c4e0415SDaniel Scheller 4683c4e0415SDaniel Scheller static int enable_tuner(struct mxl *state, u32 tuner, u32 enable); 4693c4e0415SDaniel Scheller 4703c4e0415SDaniel Scheller static int sleep(struct dvb_frontend *fe) 4713c4e0415SDaniel Scheller { 4723c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 4733c4e0415SDaniel Scheller struct mxl *p; 4743c4e0415SDaniel Scheller 4753c4e0415SDaniel Scheller cfg_demod_abort_tune(state); 4763c4e0415SDaniel Scheller if (state->tuner_in_use != 0xffffffff) { 4773c4e0415SDaniel Scheller mutex_lock(&state->base->tune_lock); 4783c4e0415SDaniel Scheller state->tuner_in_use = 0xffffffff; 4793c4e0415SDaniel Scheller list_for_each_entry(p, &state->base->mxls, mxl) { 4803c4e0415SDaniel Scheller if (p->tuner_in_use == state->tuner) 4813c4e0415SDaniel Scheller break; 4823c4e0415SDaniel Scheller } 4833c4e0415SDaniel Scheller if (&p->mxl == &state->base->mxls) 4843c4e0415SDaniel Scheller enable_tuner(state, state->tuner, 0); 4853c4e0415SDaniel Scheller mutex_unlock(&state->base->tune_lock); 4863c4e0415SDaniel Scheller } 4873c4e0415SDaniel Scheller return 0; 4883c4e0415SDaniel Scheller } 4893c4e0415SDaniel Scheller 4903c4e0415SDaniel Scheller static int read_snr(struct dvb_frontend *fe) 4913c4e0415SDaniel Scheller { 4923c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 4933c4e0415SDaniel Scheller int stat; 4943c4e0415SDaniel Scheller u32 reg_data = 0; 4953c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 4963c4e0415SDaniel Scheller 4973c4e0415SDaniel Scheller mutex_lock(&state->base->status_lock); 4983c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_LOCK(state, state->demod); 4993c4e0415SDaniel Scheller stat = read_register(state, (HYDRA_DMD_SNR_ADDR_OFFSET + 5003c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 5013c4e0415SDaniel Scheller ®_data); 5023c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); 5033c4e0415SDaniel Scheller mutex_unlock(&state->base->status_lock); 5043c4e0415SDaniel Scheller 5053c4e0415SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_DECIBEL; 5063c4e0415SDaniel Scheller p->cnr.stat[0].svalue = (s16)reg_data * 10; 5073c4e0415SDaniel Scheller 5083c4e0415SDaniel Scheller return stat; 5093c4e0415SDaniel Scheller } 5103c4e0415SDaniel Scheller 5113c4e0415SDaniel Scheller static int read_ber(struct dvb_frontend *fe) 5123c4e0415SDaniel Scheller { 5133c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 5143c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 5153c4e0415SDaniel Scheller u32 reg[8]; 5163c4e0415SDaniel Scheller 5173c4e0415SDaniel Scheller mutex_lock(&state->base->status_lock); 5183c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_LOCK(state, state->demod); 5193c4e0415SDaniel Scheller read_register_block(state, 5203c4e0415SDaniel Scheller (HYDRA_DMD_DVBS_1ST_CORR_RS_ERRORS_ADDR_OFFSET + 5213c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 5223c4e0415SDaniel Scheller (4 * sizeof(u32)), 5233c4e0415SDaniel Scheller (u8 *) ®[0]); 5243c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); 5253c4e0415SDaniel Scheller 5263c4e0415SDaniel Scheller switch (p->delivery_system) { 5273c4e0415SDaniel Scheller case SYS_DSS: 5283c4e0415SDaniel Scheller case SYS_DVBS: 5293c4e0415SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; 5303c4e0415SDaniel Scheller p->pre_bit_error.stat[0].uvalue = reg[2]; 5313c4e0415SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; 5323c4e0415SDaniel Scheller p->pre_bit_count.stat[0].uvalue = reg[3]; 5333c4e0415SDaniel Scheller break; 5343c4e0415SDaniel Scheller default: 5353c4e0415SDaniel Scheller break; 5363c4e0415SDaniel Scheller } 5373c4e0415SDaniel Scheller 5383c4e0415SDaniel Scheller read_register_block(state, 5393c4e0415SDaniel Scheller (HYDRA_DMD_DVBS2_CRC_ERRORS_ADDR_OFFSET + 5403c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 5413c4e0415SDaniel Scheller (7 * sizeof(u32)), 5423c4e0415SDaniel Scheller (u8 *) ®[0]); 5433c4e0415SDaniel Scheller 5443c4e0415SDaniel Scheller switch (p->delivery_system) { 5453c4e0415SDaniel Scheller case SYS_DSS: 5463c4e0415SDaniel Scheller case SYS_DVBS: 5473c4e0415SDaniel Scheller p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 5483c4e0415SDaniel Scheller p->post_bit_error.stat[0].uvalue = reg[5]; 5493c4e0415SDaniel Scheller p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 5503c4e0415SDaniel Scheller p->post_bit_count.stat[0].uvalue = reg[6]; 5513c4e0415SDaniel Scheller break; 5523c4e0415SDaniel Scheller case SYS_DVBS2: 5533c4e0415SDaniel Scheller p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; 5543c4e0415SDaniel Scheller p->post_bit_error.stat[0].uvalue = reg[1]; 5553c4e0415SDaniel Scheller p->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; 5563c4e0415SDaniel Scheller p->post_bit_count.stat[0].uvalue = reg[2]; 5573c4e0415SDaniel Scheller break; 5583c4e0415SDaniel Scheller default: 5593c4e0415SDaniel Scheller break; 5603c4e0415SDaniel Scheller } 5613c4e0415SDaniel Scheller 5623c4e0415SDaniel Scheller mutex_unlock(&state->base->status_lock); 5633c4e0415SDaniel Scheller 5643c4e0415SDaniel Scheller return 0; 5653c4e0415SDaniel Scheller } 5663c4e0415SDaniel Scheller 5673c4e0415SDaniel Scheller static int read_signal_strength(struct dvb_frontend *fe) 5683c4e0415SDaniel Scheller { 5693c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 5703c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 5713c4e0415SDaniel Scheller int stat; 5723c4e0415SDaniel Scheller u32 reg_data = 0; 5733c4e0415SDaniel Scheller 5743c4e0415SDaniel Scheller mutex_lock(&state->base->status_lock); 5753c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_LOCK(state, state->demod); 5763c4e0415SDaniel Scheller stat = read_register(state, (HYDRA_DMD_STATUS_INPUT_POWER_ADDR + 5773c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 5783c4e0415SDaniel Scheller ®_data); 5793c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); 5803c4e0415SDaniel Scheller mutex_unlock(&state->base->status_lock); 5813c4e0415SDaniel Scheller 5823c4e0415SDaniel Scheller p->strength.stat[0].scale = FE_SCALE_DECIBEL; 5833c4e0415SDaniel Scheller p->strength.stat[0].svalue = (s16) reg_data * 10; /* fix scale */ 5843c4e0415SDaniel Scheller 5853c4e0415SDaniel Scheller return stat; 5863c4e0415SDaniel Scheller } 5873c4e0415SDaniel Scheller 5883c4e0415SDaniel Scheller static int read_status(struct dvb_frontend *fe, enum fe_status *status) 5893c4e0415SDaniel Scheller { 5903c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 5913c4e0415SDaniel Scheller struct dtv_frontend_properties *p = &fe->dtv_property_cache; 5923c4e0415SDaniel Scheller u32 reg_data = 0; 5933c4e0415SDaniel Scheller 5943c4e0415SDaniel Scheller mutex_lock(&state->base->status_lock); 5953c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_LOCK(state, state->demod); 5963c4e0415SDaniel Scheller read_register(state, (HYDRA_DMD_LOCK_STATUS_ADDR_OFFSET + 5973c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 5983c4e0415SDaniel Scheller ®_data); 5993c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); 6003c4e0415SDaniel Scheller mutex_unlock(&state->base->status_lock); 6013c4e0415SDaniel Scheller 6023c4e0415SDaniel Scheller *status = (reg_data == 1) ? 0x1f : 0; 6033c4e0415SDaniel Scheller 6043c4e0415SDaniel Scheller /* signal statistics */ 6053c4e0415SDaniel Scheller 6063c4e0415SDaniel Scheller /* signal strength is always available */ 6073c4e0415SDaniel Scheller read_signal_strength(fe); 6083c4e0415SDaniel Scheller 6093c4e0415SDaniel Scheller if (*status & FE_HAS_CARRIER) 6103c4e0415SDaniel Scheller read_snr(fe); 6113c4e0415SDaniel Scheller else 6123c4e0415SDaniel Scheller p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6133c4e0415SDaniel Scheller 6143c4e0415SDaniel Scheller if (*status & FE_HAS_SYNC) 6153c4e0415SDaniel Scheller read_ber(fe); 6163c4e0415SDaniel Scheller else { 6173c4e0415SDaniel Scheller p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6183c4e0415SDaniel Scheller p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6193c4e0415SDaniel Scheller p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6203c4e0415SDaniel Scheller p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; 6213c4e0415SDaniel Scheller } 6223c4e0415SDaniel Scheller 6233c4e0415SDaniel Scheller return 0; 6243c4e0415SDaniel Scheller } 6253c4e0415SDaniel Scheller 6263c4e0415SDaniel Scheller static int tune(struct dvb_frontend *fe, bool re_tune, 6273c4e0415SDaniel Scheller unsigned int mode_flags, 6283c4e0415SDaniel Scheller unsigned int *delay, enum fe_status *status) 6293c4e0415SDaniel Scheller { 6303c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 6313c4e0415SDaniel Scheller int r = 0; 6323c4e0415SDaniel Scheller 6333c4e0415SDaniel Scheller *delay = HZ / 2; 6343c4e0415SDaniel Scheller if (re_tune) { 6353c4e0415SDaniel Scheller r = set_parameters(fe); 6363c4e0415SDaniel Scheller if (r) 6373c4e0415SDaniel Scheller return r; 6383c4e0415SDaniel Scheller state->tune_time = jiffies; 6393c4e0415SDaniel Scheller } 6403c4e0415SDaniel Scheller 641*2919d12dSMauro Carvalho Chehab return read_status(fe, status); 6423c4e0415SDaniel Scheller } 6433c4e0415SDaniel Scheller 6443c4e0415SDaniel Scheller static enum fe_code_rate conv_fec(enum MXL_HYDRA_FEC_E fec) 6453c4e0415SDaniel Scheller { 6463c4e0415SDaniel Scheller enum fe_code_rate fec2fec[11] = { 6473c4e0415SDaniel Scheller FEC_NONE, FEC_1_2, FEC_3_5, FEC_2_3, 6483c4e0415SDaniel Scheller FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, 6493c4e0415SDaniel Scheller FEC_7_8, FEC_8_9, FEC_9_10 6503c4e0415SDaniel Scheller }; 6513c4e0415SDaniel Scheller 6523c4e0415SDaniel Scheller if (fec > MXL_HYDRA_FEC_9_10) 6533c4e0415SDaniel Scheller return FEC_NONE; 6543c4e0415SDaniel Scheller return fec2fec[fec]; 6553c4e0415SDaniel Scheller } 6563c4e0415SDaniel Scheller 6573c4e0415SDaniel Scheller static int get_frontend(struct dvb_frontend *fe, 6583c4e0415SDaniel Scheller struct dtv_frontend_properties *p) 6593c4e0415SDaniel Scheller { 6603c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 6613c4e0415SDaniel Scheller u32 reg_data[MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE]; 6623c4e0415SDaniel Scheller u32 freq; 6633c4e0415SDaniel Scheller 6643c4e0415SDaniel Scheller mutex_lock(&state->base->status_lock); 6653c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_LOCK(state, state->demod); 6663c4e0415SDaniel Scheller read_register_block(state, 6673c4e0415SDaniel Scheller (HYDRA_DMD_STANDARD_ADDR_OFFSET + 6683c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 6693c4e0415SDaniel Scheller (MXL_DEMOD_CHAN_PARAMS_BUFF_SIZE * 4), /* 25 * 4 bytes */ 6703c4e0415SDaniel Scheller (u8 *) ®_data[0]); 6713c4e0415SDaniel Scheller /* read demod channel parameters */ 6723c4e0415SDaniel Scheller read_register_block(state, 6733c4e0415SDaniel Scheller (HYDRA_DMD_STATUS_CENTER_FREQ_IN_KHZ_ADDR + 6743c4e0415SDaniel Scheller HYDRA_DMD_STATUS_OFFSET(state->demod)), 6753c4e0415SDaniel Scheller (4), /* 4 bytes */ 6763c4e0415SDaniel Scheller (u8 *) &freq); 6773c4e0415SDaniel Scheller HYDRA_DEMOD_STATUS_UNLOCK(state, state->demod); 6783c4e0415SDaniel Scheller mutex_unlock(&state->base->status_lock); 6793c4e0415SDaniel Scheller 6803c4e0415SDaniel Scheller dev_dbg(state->i2cdev, "freq=%u delsys=%u srate=%u\n", 6813c4e0415SDaniel Scheller freq * 1000, reg_data[DMD_STANDARD_ADDR], 6823c4e0415SDaniel Scheller reg_data[DMD_SYMBOL_RATE_ADDR]); 6833c4e0415SDaniel Scheller p->symbol_rate = reg_data[DMD_SYMBOL_RATE_ADDR]; 6843c4e0415SDaniel Scheller p->frequency = freq; 6853c4e0415SDaniel Scheller /* 6863c4e0415SDaniel Scheller * p->delivery_system = 6873c4e0415SDaniel Scheller * (MXL_HYDRA_BCAST_STD_E) regData[DMD_STANDARD_ADDR]; 6883c4e0415SDaniel Scheller * p->inversion = 6893c4e0415SDaniel Scheller * (MXL_HYDRA_SPECTRUM_E) regData[DMD_SPECTRUM_INVERSION_ADDR]; 6903c4e0415SDaniel Scheller * freqSearchRangeKHz = 6913c4e0415SDaniel Scheller * (regData[DMD_FREQ_SEARCH_RANGE_IN_KHZ_ADDR]); 6923c4e0415SDaniel Scheller */ 6933c4e0415SDaniel Scheller 6943c4e0415SDaniel Scheller p->fec_inner = conv_fec(reg_data[DMD_FEC_CODE_RATE_ADDR]); 6953c4e0415SDaniel Scheller switch (p->delivery_system) { 6963c4e0415SDaniel Scheller case SYS_DSS: 6973c4e0415SDaniel Scheller break; 6983c4e0415SDaniel Scheller case SYS_DVBS2: 6993c4e0415SDaniel Scheller switch ((enum MXL_HYDRA_PILOTS_E) 7003c4e0415SDaniel Scheller reg_data[DMD_DVBS2_PILOT_ON_OFF_ADDR]) { 7013c4e0415SDaniel Scheller case MXL_HYDRA_PILOTS_OFF: 7023c4e0415SDaniel Scheller p->pilot = PILOT_OFF; 7033c4e0415SDaniel Scheller break; 7043c4e0415SDaniel Scheller case MXL_HYDRA_PILOTS_ON: 7053c4e0415SDaniel Scheller p->pilot = PILOT_ON; 7063c4e0415SDaniel Scheller break; 7073c4e0415SDaniel Scheller default: 7083c4e0415SDaniel Scheller break; 7093c4e0415SDaniel Scheller } 7103c4e0415SDaniel Scheller case SYS_DVBS: 7113c4e0415SDaniel Scheller switch ((enum MXL_HYDRA_MODULATION_E) 7123c4e0415SDaniel Scheller reg_data[DMD_MODULATION_SCHEME_ADDR]) { 7133c4e0415SDaniel Scheller case MXL_HYDRA_MOD_QPSK: 7143c4e0415SDaniel Scheller p->modulation = QPSK; 7153c4e0415SDaniel Scheller break; 7163c4e0415SDaniel Scheller case MXL_HYDRA_MOD_8PSK: 7173c4e0415SDaniel Scheller p->modulation = PSK_8; 7183c4e0415SDaniel Scheller break; 7193c4e0415SDaniel Scheller default: 7203c4e0415SDaniel Scheller break; 7213c4e0415SDaniel Scheller } 7223c4e0415SDaniel Scheller switch ((enum MXL_HYDRA_ROLLOFF_E) 7233c4e0415SDaniel Scheller reg_data[DMD_SPECTRUM_ROLL_OFF_ADDR]) { 7243c4e0415SDaniel Scheller case MXL_HYDRA_ROLLOFF_0_20: 7253c4e0415SDaniel Scheller p->rolloff = ROLLOFF_20; 7263c4e0415SDaniel Scheller break; 7273c4e0415SDaniel Scheller case MXL_HYDRA_ROLLOFF_0_35: 7283c4e0415SDaniel Scheller p->rolloff = ROLLOFF_35; 7293c4e0415SDaniel Scheller break; 7303c4e0415SDaniel Scheller case MXL_HYDRA_ROLLOFF_0_25: 7313c4e0415SDaniel Scheller p->rolloff = ROLLOFF_25; 7323c4e0415SDaniel Scheller break; 7333c4e0415SDaniel Scheller default: 7343c4e0415SDaniel Scheller break; 7353c4e0415SDaniel Scheller } 7363c4e0415SDaniel Scheller break; 7373c4e0415SDaniel Scheller default: 7383c4e0415SDaniel Scheller return -EINVAL; 7393c4e0415SDaniel Scheller } 7403c4e0415SDaniel Scheller return 0; 7413c4e0415SDaniel Scheller } 7423c4e0415SDaniel Scheller 7433c4e0415SDaniel Scheller static int set_input(struct dvb_frontend *fe, int input) 7443c4e0415SDaniel Scheller { 7453c4e0415SDaniel Scheller struct mxl *state = fe->demodulator_priv; 7463c4e0415SDaniel Scheller 7473c4e0415SDaniel Scheller state->tuner = input; 7483c4e0415SDaniel Scheller return 0; 7493c4e0415SDaniel Scheller } 7503c4e0415SDaniel Scheller 7513c4e0415SDaniel Scheller static struct dvb_frontend_ops mxl_ops = { 7523c4e0415SDaniel Scheller .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, 7533c4e0415SDaniel Scheller .info = { 7543c4e0415SDaniel Scheller .name = "MaxLinear MxL5xx DVB-S/S2 tuner-demodulator", 7553c4e0415SDaniel Scheller .frequency_min = 300000, 7563c4e0415SDaniel Scheller .frequency_max = 2350000, 7573c4e0415SDaniel Scheller .frequency_stepsize = 0, 7583c4e0415SDaniel Scheller .frequency_tolerance = 0, 7593c4e0415SDaniel Scheller .symbol_rate_min = 1000000, 7603c4e0415SDaniel Scheller .symbol_rate_max = 45000000, 7613c4e0415SDaniel Scheller .caps = FE_CAN_INVERSION_AUTO | 7623c4e0415SDaniel Scheller FE_CAN_FEC_AUTO | 7633c4e0415SDaniel Scheller FE_CAN_QPSK | 7643c4e0415SDaniel Scheller FE_CAN_2G_MODULATION 7653c4e0415SDaniel Scheller }, 7663c4e0415SDaniel Scheller .init = init, 7673c4e0415SDaniel Scheller .release = release, 7683c4e0415SDaniel Scheller .get_frontend_algo = get_algo, 7693c4e0415SDaniel Scheller .tune = tune, 7703c4e0415SDaniel Scheller .read_status = read_status, 7713c4e0415SDaniel Scheller .sleep = sleep, 7723c4e0415SDaniel Scheller .get_frontend = get_frontend, 7733c4e0415SDaniel Scheller .diseqc_send_master_cmd = send_master_cmd, 7743c4e0415SDaniel Scheller }; 7753c4e0415SDaniel Scheller 7763c4e0415SDaniel Scheller static struct mxl_base *match_base(struct i2c_adapter *i2c, u8 adr) 7773c4e0415SDaniel Scheller { 7783c4e0415SDaniel Scheller struct mxl_base *p; 7793c4e0415SDaniel Scheller 7803c4e0415SDaniel Scheller list_for_each_entry(p, &mxllist, mxllist) 7813c4e0415SDaniel Scheller if (p->i2c == i2c && p->adr == adr) 7823c4e0415SDaniel Scheller return p; 7833c4e0415SDaniel Scheller return NULL; 7843c4e0415SDaniel Scheller } 7853c4e0415SDaniel Scheller 7863c4e0415SDaniel Scheller static void cfg_dev_xtal(struct mxl *state, u32 freq, u32 cap, u32 enable) 7873c4e0415SDaniel Scheller { 7883c4e0415SDaniel Scheller if (state->base->can_clkout || !enable) 7893c4e0415SDaniel Scheller update_by_mnemonic(state, 0x90200054, 23, 1, enable); 7903c4e0415SDaniel Scheller 7913c4e0415SDaniel Scheller if (freq == 24000000) 7923c4e0415SDaniel Scheller write_register(state, HYDRA_CRYSTAL_SETTING, 0); 7933c4e0415SDaniel Scheller else 7943c4e0415SDaniel Scheller write_register(state, HYDRA_CRYSTAL_SETTING, 1); 7953c4e0415SDaniel Scheller 7963c4e0415SDaniel Scheller write_register(state, HYDRA_CRYSTAL_CAP, cap); 7973c4e0415SDaniel Scheller } 7983c4e0415SDaniel Scheller 7993c4e0415SDaniel Scheller static u32 get_big_endian(u8 num_of_bits, const u8 buf[]) 8003c4e0415SDaniel Scheller { 8013c4e0415SDaniel Scheller u32 ret_value = 0; 8023c4e0415SDaniel Scheller 8033c4e0415SDaniel Scheller switch (num_of_bits) { 8043c4e0415SDaniel Scheller case 24: 8053c4e0415SDaniel Scheller ret_value = (((u32) buf[0]) << 16) | 8063c4e0415SDaniel Scheller (((u32) buf[1]) << 8) | buf[2]; 8073c4e0415SDaniel Scheller break; 8083c4e0415SDaniel Scheller case 32: 8093c4e0415SDaniel Scheller ret_value = (((u32) buf[0]) << 24) | 8103c4e0415SDaniel Scheller (((u32) buf[1]) << 16) | 8113c4e0415SDaniel Scheller (((u32) buf[2]) << 8) | buf[3]; 8123c4e0415SDaniel Scheller break; 8133c4e0415SDaniel Scheller default: 8143c4e0415SDaniel Scheller break; 8153c4e0415SDaniel Scheller } 8163c4e0415SDaniel Scheller 8173c4e0415SDaniel Scheller return ret_value; 8183c4e0415SDaniel Scheller } 8193c4e0415SDaniel Scheller 8203c4e0415SDaniel Scheller static int write_fw_segment(struct mxl *state, 8213c4e0415SDaniel Scheller u32 mem_addr, u32 total_size, u8 *data_ptr) 8223c4e0415SDaniel Scheller { 8233c4e0415SDaniel Scheller int status; 8243c4e0415SDaniel Scheller u32 data_count = 0; 8253c4e0415SDaniel Scheller u32 size = 0; 8263c4e0415SDaniel Scheller u32 orig_size = 0; 8273c4e0415SDaniel Scheller u8 *w_buf_ptr = NULL; 8283c4e0415SDaniel Scheller u32 block_size = ((MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH - 8293c4e0415SDaniel Scheller (MXL_HYDRA_I2C_HDR_SIZE + 8303c4e0415SDaniel Scheller MXL_HYDRA_REG_SIZE_IN_BYTES)) / 4) * 4; 8313c4e0415SDaniel Scheller u8 w_msg_buffer[MXL_HYDRA_OEM_MAX_BLOCK_WRITE_LENGTH - 8323c4e0415SDaniel Scheller (MXL_HYDRA_I2C_HDR_SIZE + MXL_HYDRA_REG_SIZE_IN_BYTES)]; 8333c4e0415SDaniel Scheller 8343c4e0415SDaniel Scheller do { 8353c4e0415SDaniel Scheller size = orig_size = (((u32)(data_count + block_size)) > total_size) ? 8363c4e0415SDaniel Scheller (total_size - data_count) : block_size; 8373c4e0415SDaniel Scheller 8383c4e0415SDaniel Scheller if (orig_size & 3) 8393c4e0415SDaniel Scheller size = (orig_size + 4) & ~3; 8403c4e0415SDaniel Scheller w_buf_ptr = &w_msg_buffer[0]; 8413c4e0415SDaniel Scheller memset((void *) w_buf_ptr, 0, size); 8423c4e0415SDaniel Scheller memcpy((void *) w_buf_ptr, (void *) data_ptr, orig_size); 8433c4e0415SDaniel Scheller convert_endian(1, size, w_buf_ptr); 8443c4e0415SDaniel Scheller status = write_firmware_block(state, mem_addr, size, w_buf_ptr); 8453c4e0415SDaniel Scheller if (status) 8463c4e0415SDaniel Scheller return status; 8473c4e0415SDaniel Scheller data_count += size; 8483c4e0415SDaniel Scheller mem_addr += size; 8493c4e0415SDaniel Scheller data_ptr += size; 8503c4e0415SDaniel Scheller } while (data_count < total_size); 8513c4e0415SDaniel Scheller 8523c4e0415SDaniel Scheller return status; 8533c4e0415SDaniel Scheller } 8543c4e0415SDaniel Scheller 8553c4e0415SDaniel Scheller static int do_firmware_download(struct mxl *state, u8 *mbin_buffer_ptr, 8563c4e0415SDaniel Scheller u32 mbin_buffer_size) 8573c4e0415SDaniel Scheller 8583c4e0415SDaniel Scheller { 8593c4e0415SDaniel Scheller int status; 8603c4e0415SDaniel Scheller u32 index = 0; 8613c4e0415SDaniel Scheller u32 seg_length = 0; 8623c4e0415SDaniel Scheller u32 seg_address = 0; 8633c4e0415SDaniel Scheller struct MBIN_FILE_T *mbin_ptr = (struct MBIN_FILE_T *)mbin_buffer_ptr; 8643c4e0415SDaniel Scheller struct MBIN_SEGMENT_T *segment_ptr; 8653c4e0415SDaniel Scheller enum MXL_BOOL_E xcpu_fw_flag = MXL_FALSE; 8663c4e0415SDaniel Scheller 8673c4e0415SDaniel Scheller if (mbin_ptr->header.id != MBIN_FILE_HEADER_ID) { 8683c4e0415SDaniel Scheller dev_err(state->i2cdev, "%s: Invalid file header ID (%c)\n", 8693c4e0415SDaniel Scheller __func__, mbin_ptr->header.id); 8703c4e0415SDaniel Scheller return -EINVAL; 8713c4e0415SDaniel Scheller } 8723c4e0415SDaniel Scheller status = write_register(state, FW_DL_SIGN_ADDR, 0); 8733c4e0415SDaniel Scheller if (status) 8743c4e0415SDaniel Scheller return status; 8753c4e0415SDaniel Scheller segment_ptr = (struct MBIN_SEGMENT_T *) (&mbin_ptr->data[0]); 8763c4e0415SDaniel Scheller for (index = 0; index < mbin_ptr->header.num_segments; index++) { 8773c4e0415SDaniel Scheller if (segment_ptr->header.id != MBIN_SEGMENT_HEADER_ID) { 8783c4e0415SDaniel Scheller dev_err(state->i2cdev, "%s: Invalid segment header ID (%c)\n", 8793c4e0415SDaniel Scheller __func__, segment_ptr->header.id); 8803c4e0415SDaniel Scheller return -EINVAL; 8813c4e0415SDaniel Scheller } 8823c4e0415SDaniel Scheller seg_length = get_big_endian(24, 8833c4e0415SDaniel Scheller &(segment_ptr->header.len24[0])); 8843c4e0415SDaniel Scheller seg_address = get_big_endian(32, 8853c4e0415SDaniel Scheller &(segment_ptr->header.address[0])); 8863c4e0415SDaniel Scheller 8873c4e0415SDaniel Scheller if (state->base->type == MXL_HYDRA_DEVICE_568) { 8883c4e0415SDaniel Scheller if ((((seg_address & 0x90760000) == 0x90760000) || 8893c4e0415SDaniel Scheller ((seg_address & 0x90740000) == 0x90740000)) && 8903c4e0415SDaniel Scheller (xcpu_fw_flag == MXL_FALSE)) { 8913c4e0415SDaniel Scheller update_by_mnemonic(state, 0x8003003C, 0, 1, 1); 8923c4e0415SDaniel Scheller msleep(200); 8933c4e0415SDaniel Scheller write_register(state, 0x90720000, 0); 8943c4e0415SDaniel Scheller usleep_range(10000, 11000); 8953c4e0415SDaniel Scheller xcpu_fw_flag = MXL_TRUE; 8963c4e0415SDaniel Scheller } 8973c4e0415SDaniel Scheller status = write_fw_segment(state, seg_address, 8983c4e0415SDaniel Scheller seg_length, 8993c4e0415SDaniel Scheller (u8 *) segment_ptr->data); 9003c4e0415SDaniel Scheller } else { 9013c4e0415SDaniel Scheller if (((seg_address & 0x90760000) != 0x90760000) && 9023c4e0415SDaniel Scheller ((seg_address & 0x90740000) != 0x90740000)) 9033c4e0415SDaniel Scheller status = write_fw_segment(state, seg_address, 9043c4e0415SDaniel Scheller seg_length, (u8 *) segment_ptr->data); 9053c4e0415SDaniel Scheller } 9063c4e0415SDaniel Scheller if (status) 9073c4e0415SDaniel Scheller return status; 9083c4e0415SDaniel Scheller segment_ptr = (struct MBIN_SEGMENT_T *) 9093c4e0415SDaniel Scheller &(segment_ptr->data[((seg_length + 3) / 4) * 4]); 9103c4e0415SDaniel Scheller } 9113c4e0415SDaniel Scheller return status; 9123c4e0415SDaniel Scheller } 9133c4e0415SDaniel Scheller 9143c4e0415SDaniel Scheller static int check_fw(struct mxl *state, u8 *mbin, u32 mbin_len) 9153c4e0415SDaniel Scheller { 9163c4e0415SDaniel Scheller struct MBIN_FILE_HEADER_T *fh = (struct MBIN_FILE_HEADER_T *) mbin; 9173c4e0415SDaniel Scheller u32 flen = (fh->image_size24[0] << 16) | 9183c4e0415SDaniel Scheller (fh->image_size24[1] << 8) | fh->image_size24[2]; 9193c4e0415SDaniel Scheller u8 *fw, cs = 0; 9203c4e0415SDaniel Scheller u32 i; 9213c4e0415SDaniel Scheller 9223c4e0415SDaniel Scheller if (fh->id != 'M' || fh->fmt_version != '1' || flen > 0x3FFF0) { 9233c4e0415SDaniel Scheller dev_info(state->i2cdev, "Invalid FW Header\n"); 9243c4e0415SDaniel Scheller return -1; 9253c4e0415SDaniel Scheller } 9263c4e0415SDaniel Scheller fw = mbin + sizeof(struct MBIN_FILE_HEADER_T); 9273c4e0415SDaniel Scheller for (i = 0; i < flen; i += 1) 9283c4e0415SDaniel Scheller cs += fw[i]; 9293c4e0415SDaniel Scheller if (cs != fh->image_checksum) { 9303c4e0415SDaniel Scheller dev_info(state->i2cdev, "Invalid FW Checksum\n"); 9313c4e0415SDaniel Scheller return -1; 9323c4e0415SDaniel Scheller } 9333c4e0415SDaniel Scheller return 0; 9343c4e0415SDaniel Scheller } 9353c4e0415SDaniel Scheller 9363c4e0415SDaniel Scheller static int firmware_download(struct mxl *state, u8 *mbin, u32 mbin_len) 9373c4e0415SDaniel Scheller { 9383c4e0415SDaniel Scheller int status; 9393c4e0415SDaniel Scheller u32 reg_data = 0; 9403c4e0415SDaniel Scheller struct MXL_HYDRA_SKU_COMMAND_T dev_sku_cfg; 9413c4e0415SDaniel Scheller u8 cmd_size = sizeof(struct MXL_HYDRA_SKU_COMMAND_T); 9423c4e0415SDaniel Scheller u8 cmd_buff[sizeof(struct MXL_HYDRA_SKU_COMMAND_T) + 6]; 9433c4e0415SDaniel Scheller 9443c4e0415SDaniel Scheller if (check_fw(state, mbin, mbin_len)) 9453c4e0415SDaniel Scheller return -1; 9463c4e0415SDaniel Scheller 9473c4e0415SDaniel Scheller /* put CPU into reset */ 9483c4e0415SDaniel Scheller status = update_by_mnemonic(state, 0x8003003C, 0, 1, 0); 9493c4e0415SDaniel Scheller if (status) 9503c4e0415SDaniel Scheller return status; 9513c4e0415SDaniel Scheller usleep_range(1000, 2000); 9523c4e0415SDaniel Scheller 9533c4e0415SDaniel Scheller /* Reset TX FIFO's, BBAND, XBAR */ 9543c4e0415SDaniel Scheller status = write_register(state, HYDRA_RESET_TRANSPORT_FIFO_REG, 9553c4e0415SDaniel Scheller HYDRA_RESET_TRANSPORT_FIFO_DATA); 9563c4e0415SDaniel Scheller if (status) 9573c4e0415SDaniel Scheller return status; 9583c4e0415SDaniel Scheller status = write_register(state, HYDRA_RESET_BBAND_REG, 9593c4e0415SDaniel Scheller HYDRA_RESET_BBAND_DATA); 9603c4e0415SDaniel Scheller if (status) 9613c4e0415SDaniel Scheller return status; 9623c4e0415SDaniel Scheller status = write_register(state, HYDRA_RESET_XBAR_REG, 9633c4e0415SDaniel Scheller HYDRA_RESET_XBAR_DATA); 9643c4e0415SDaniel Scheller if (status) 9653c4e0415SDaniel Scheller return status; 9663c4e0415SDaniel Scheller 9673c4e0415SDaniel Scheller /* Disable clock to Baseband, Wideband, SerDes, 9683c4e0415SDaniel Scheller * Alias ext & Transport modules 9693c4e0415SDaniel Scheller */ 9703c4e0415SDaniel Scheller status = write_register(state, HYDRA_MODULES_CLK_2_REG, 9713c4e0415SDaniel Scheller HYDRA_DISABLE_CLK_2); 9723c4e0415SDaniel Scheller if (status) 9733c4e0415SDaniel Scheller return status; 9743c4e0415SDaniel Scheller /* Clear Software & Host interrupt status - (Clear on read) */ 9753c4e0415SDaniel Scheller status = read_register(state, HYDRA_PRCM_ROOT_CLK_REG, ®_data); 9763c4e0415SDaniel Scheller if (status) 9773c4e0415SDaniel Scheller return status; 9783c4e0415SDaniel Scheller status = do_firmware_download(state, mbin, mbin_len); 9793c4e0415SDaniel Scheller if (status) 9803c4e0415SDaniel Scheller return status; 9813c4e0415SDaniel Scheller 9823c4e0415SDaniel Scheller if (state->base->type == MXL_HYDRA_DEVICE_568) { 9833c4e0415SDaniel Scheller usleep_range(10000, 11000); 9843c4e0415SDaniel Scheller 9853c4e0415SDaniel Scheller /* bring XCPU out of reset */ 9863c4e0415SDaniel Scheller status = write_register(state, 0x90720000, 1); 9873c4e0415SDaniel Scheller if (status) 9883c4e0415SDaniel Scheller return status; 9893c4e0415SDaniel Scheller msleep(500); 9903c4e0415SDaniel Scheller 9913c4e0415SDaniel Scheller /* Enable XCPU UART message processing in MCPU */ 9923c4e0415SDaniel Scheller status = write_register(state, 0x9076B510, 1); 9933c4e0415SDaniel Scheller if (status) 9943c4e0415SDaniel Scheller return status; 9953c4e0415SDaniel Scheller } else { 9963c4e0415SDaniel Scheller /* Bring CPU out of reset */ 9973c4e0415SDaniel Scheller status = update_by_mnemonic(state, 0x8003003C, 0, 1, 1); 9983c4e0415SDaniel Scheller if (status) 9993c4e0415SDaniel Scheller return status; 10003c4e0415SDaniel Scheller /* Wait until FW boots */ 10013c4e0415SDaniel Scheller msleep(150); 10023c4e0415SDaniel Scheller } 10033c4e0415SDaniel Scheller 10043c4e0415SDaniel Scheller /* Initialize XPT XBAR */ 10053c4e0415SDaniel Scheller status = write_register(state, XPT_DMD0_BASEADDR, 0x76543210); 10063c4e0415SDaniel Scheller if (status) 10073c4e0415SDaniel Scheller return status; 10083c4e0415SDaniel Scheller 10093c4e0415SDaniel Scheller if (!firmware_is_alive(state)) 10103c4e0415SDaniel Scheller return -1; 10113c4e0415SDaniel Scheller 10123c4e0415SDaniel Scheller dev_info(state->i2cdev, "Hydra FW alive. Hail!\n"); 10133c4e0415SDaniel Scheller 10143c4e0415SDaniel Scheller /* sometimes register values are wrong shortly 10153c4e0415SDaniel Scheller * after first heart beats 10163c4e0415SDaniel Scheller */ 10173c4e0415SDaniel Scheller msleep(50); 10183c4e0415SDaniel Scheller 10193c4e0415SDaniel Scheller dev_sku_cfg.sku_type = state->base->sku_type; 10203c4e0415SDaniel Scheller BUILD_HYDRA_CMD(MXL_HYDRA_DEV_CFG_SKU_CMD, MXL_CMD_WRITE, 10213c4e0415SDaniel Scheller cmd_size, &dev_sku_cfg, cmd_buff); 10223c4e0415SDaniel Scheller status = send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, 10233c4e0415SDaniel Scheller &cmd_buff[0]); 10243c4e0415SDaniel Scheller 10253c4e0415SDaniel Scheller return status; 10263c4e0415SDaniel Scheller } 10273c4e0415SDaniel Scheller 10283c4e0415SDaniel Scheller static int cfg_ts_pad_mux(struct mxl *state, enum MXL_BOOL_E enable_serial_ts) 10293c4e0415SDaniel Scheller { 10303c4e0415SDaniel Scheller int status = 0; 10313c4e0415SDaniel Scheller u32 pad_mux_value = 0; 10323c4e0415SDaniel Scheller 10333c4e0415SDaniel Scheller if (enable_serial_ts == MXL_TRUE) { 10343c4e0415SDaniel Scheller pad_mux_value = 0; 10353c4e0415SDaniel Scheller if ((state->base->type == MXL_HYDRA_DEVICE_541) || 10363c4e0415SDaniel Scheller (state->base->type == MXL_HYDRA_DEVICE_541S)) 10373c4e0415SDaniel Scheller pad_mux_value = 2; 10383c4e0415SDaniel Scheller } else { 10393c4e0415SDaniel Scheller if ((state->base->type == MXL_HYDRA_DEVICE_581) || 10403c4e0415SDaniel Scheller (state->base->type == MXL_HYDRA_DEVICE_581S)) 10413c4e0415SDaniel Scheller pad_mux_value = 2; 10423c4e0415SDaniel Scheller else 10433c4e0415SDaniel Scheller pad_mux_value = 3; 10443c4e0415SDaniel Scheller } 10453c4e0415SDaniel Scheller 10463c4e0415SDaniel Scheller switch (state->base->type) { 10473c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_561: 10483c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_581: 10493c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_541: 10503c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_541S: 10513c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_561S: 10523c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_581S: 10533c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000170, 24, 3, 10543c4e0415SDaniel Scheller pad_mux_value); 10553c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000170, 28, 3, 10563c4e0415SDaniel Scheller pad_mux_value); 10573c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 0, 3, 10583c4e0415SDaniel Scheller pad_mux_value); 10593c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 4, 3, 10603c4e0415SDaniel Scheller pad_mux_value); 10613c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 8, 3, 10623c4e0415SDaniel Scheller pad_mux_value); 10633c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 12, 3, 10643c4e0415SDaniel Scheller pad_mux_value); 10653c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 16, 3, 10663c4e0415SDaniel Scheller pad_mux_value); 10673c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 20, 3, 10683c4e0415SDaniel Scheller pad_mux_value); 10693c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 24, 3, 10703c4e0415SDaniel Scheller pad_mux_value); 10713c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000174, 28, 3, 10723c4e0415SDaniel Scheller pad_mux_value); 10733c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 0, 3, 10743c4e0415SDaniel Scheller pad_mux_value); 10753c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 4, 3, 10763c4e0415SDaniel Scheller pad_mux_value); 10773c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 8, 3, 10783c4e0415SDaniel Scheller pad_mux_value); 10793c4e0415SDaniel Scheller break; 10803c4e0415SDaniel Scheller 10813c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_544: 10823c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_542: 10833c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000016C, 4, 3, 1); 10843c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000016C, 8, 3, 0); 10853c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000016C, 12, 3, 0); 10863c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000016C, 16, 3, 0); 10873c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000170, 0, 3, 0); 10883c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 12, 3, 1); 10893c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 16, 3, 1); 10903c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 20, 3, 1); 10913c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x90000178, 24, 3, 1); 10923c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000017C, 0, 3, 1); 10933c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 0x9000017C, 4, 3, 1); 10943c4e0415SDaniel Scheller if (enable_serial_ts == MXL_ENABLE) { 10953c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 10963c4e0415SDaniel Scheller 0x90000170, 4, 3, 0); 10973c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 10983c4e0415SDaniel Scheller 0x90000170, 8, 3, 0); 10993c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11003c4e0415SDaniel Scheller 0x90000170, 12, 3, 0); 11013c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11023c4e0415SDaniel Scheller 0x90000170, 16, 3, 0); 11033c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11043c4e0415SDaniel Scheller 0x90000170, 20, 3, 1); 11053c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11063c4e0415SDaniel Scheller 0x90000170, 24, 3, 1); 11073c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11083c4e0415SDaniel Scheller 0x90000170, 28, 3, 2); 11093c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11103c4e0415SDaniel Scheller 0x90000174, 0, 3, 2); 11113c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11123c4e0415SDaniel Scheller 0x90000174, 4, 3, 2); 11133c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11143c4e0415SDaniel Scheller 0x90000174, 8, 3, 2); 11153c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11163c4e0415SDaniel Scheller 0x90000174, 12, 3, 2); 11173c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11183c4e0415SDaniel Scheller 0x90000174, 16, 3, 2); 11193c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11203c4e0415SDaniel Scheller 0x90000174, 20, 3, 2); 11213c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11223c4e0415SDaniel Scheller 0x90000174, 24, 3, 2); 11233c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11243c4e0415SDaniel Scheller 0x90000174, 28, 3, 2); 11253c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11263c4e0415SDaniel Scheller 0x90000178, 0, 3, 2); 11273c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11283c4e0415SDaniel Scheller 0x90000178, 4, 3, 2); 11293c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11303c4e0415SDaniel Scheller 0x90000178, 8, 3, 2); 11313c4e0415SDaniel Scheller } else { 11323c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11333c4e0415SDaniel Scheller 0x90000170, 4, 3, 3); 11343c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11353c4e0415SDaniel Scheller 0x90000170, 8, 3, 3); 11363c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11373c4e0415SDaniel Scheller 0x90000170, 12, 3, 3); 11383c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11393c4e0415SDaniel Scheller 0x90000170, 16, 3, 3); 11403c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11413c4e0415SDaniel Scheller 0x90000170, 20, 3, 3); 11423c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11433c4e0415SDaniel Scheller 0x90000170, 24, 3, 3); 11443c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11453c4e0415SDaniel Scheller 0x90000170, 28, 3, 3); 11463c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11473c4e0415SDaniel Scheller 0x90000174, 0, 3, 3); 11483c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11493c4e0415SDaniel Scheller 0x90000174, 4, 3, 3); 11503c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11513c4e0415SDaniel Scheller 0x90000174, 8, 3, 3); 11523c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11533c4e0415SDaniel Scheller 0x90000174, 12, 3, 3); 11543c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11553c4e0415SDaniel Scheller 0x90000174, 16, 3, 3); 11563c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11573c4e0415SDaniel Scheller 0x90000174, 20, 3, 1); 11583c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11593c4e0415SDaniel Scheller 0x90000174, 24, 3, 1); 11603c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11613c4e0415SDaniel Scheller 0x90000174, 28, 3, 1); 11623c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11633c4e0415SDaniel Scheller 0x90000178, 0, 3, 1); 11643c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11653c4e0415SDaniel Scheller 0x90000178, 4, 3, 1); 11663c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11673c4e0415SDaniel Scheller 0x90000178, 8, 3, 1); 11683c4e0415SDaniel Scheller } 11693c4e0415SDaniel Scheller break; 11703c4e0415SDaniel Scheller 11713c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_568: 11723c4e0415SDaniel Scheller if (enable_serial_ts == MXL_FALSE) { 11733c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11743c4e0415SDaniel Scheller 0x9000016C, 8, 3, 5); 11753c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11763c4e0415SDaniel Scheller 0x9000016C, 12, 3, 5); 11773c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11783c4e0415SDaniel Scheller 0x9000016C, 16, 3, 5); 11793c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11803c4e0415SDaniel Scheller 0x9000016C, 20, 3, 5); 11813c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11823c4e0415SDaniel Scheller 0x9000016C, 24, 3, 5); 11833c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11843c4e0415SDaniel Scheller 0x9000016C, 28, 3, 5); 11853c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11863c4e0415SDaniel Scheller 0x90000170, 0, 3, 5); 11873c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11883c4e0415SDaniel Scheller 0x90000170, 4, 3, 5); 11893c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11903c4e0415SDaniel Scheller 0x90000170, 8, 3, 5); 11913c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11923c4e0415SDaniel Scheller 0x90000170, 12, 3, 5); 11933c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11943c4e0415SDaniel Scheller 0x90000170, 16, 3, 5); 11953c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11963c4e0415SDaniel Scheller 0x90000170, 20, 3, 5); 11973c4e0415SDaniel Scheller 11983c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 11993c4e0415SDaniel Scheller 0x90000170, 24, 3, pad_mux_value); 12003c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12013c4e0415SDaniel Scheller 0x90000174, 0, 3, pad_mux_value); 12023c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12033c4e0415SDaniel Scheller 0x90000174, 4, 3, pad_mux_value); 12043c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12053c4e0415SDaniel Scheller 0x90000174, 8, 3, pad_mux_value); 12063c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12073c4e0415SDaniel Scheller 0x90000174, 12, 3, pad_mux_value); 12083c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12093c4e0415SDaniel Scheller 0x90000174, 16, 3, pad_mux_value); 12103c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12113c4e0415SDaniel Scheller 0x90000174, 20, 3, pad_mux_value); 12123c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12133c4e0415SDaniel Scheller 0x90000174, 24, 3, pad_mux_value); 12143c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12153c4e0415SDaniel Scheller 0x90000174, 28, 3, pad_mux_value); 12163c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12173c4e0415SDaniel Scheller 0x90000178, 0, 3, pad_mux_value); 12183c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12193c4e0415SDaniel Scheller 0x90000178, 4, 3, pad_mux_value); 12203c4e0415SDaniel Scheller 12213c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12223c4e0415SDaniel Scheller 0x90000178, 8, 3, 5); 12233c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12243c4e0415SDaniel Scheller 0x90000178, 12, 3, 5); 12253c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12263c4e0415SDaniel Scheller 0x90000178, 16, 3, 5); 12273c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12283c4e0415SDaniel Scheller 0x90000178, 20, 3, 5); 12293c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12303c4e0415SDaniel Scheller 0x90000178, 24, 3, 5); 12313c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12323c4e0415SDaniel Scheller 0x90000178, 28, 3, 5); 12333c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12343c4e0415SDaniel Scheller 0x9000017C, 0, 3, 5); 12353c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12363c4e0415SDaniel Scheller 0x9000017C, 4, 3, 5); 12373c4e0415SDaniel Scheller } else { 12383c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12393c4e0415SDaniel Scheller 0x90000170, 4, 3, pad_mux_value); 12403c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12413c4e0415SDaniel Scheller 0x90000170, 8, 3, pad_mux_value); 12423c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12433c4e0415SDaniel Scheller 0x90000170, 12, 3, pad_mux_value); 12443c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12453c4e0415SDaniel Scheller 0x90000170, 16, 3, pad_mux_value); 12463c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12473c4e0415SDaniel Scheller 0x90000170, 20, 3, pad_mux_value); 12483c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12493c4e0415SDaniel Scheller 0x90000170, 24, 3, pad_mux_value); 12503c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12513c4e0415SDaniel Scheller 0x90000170, 28, 3, pad_mux_value); 12523c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12533c4e0415SDaniel Scheller 0x90000174, 0, 3, pad_mux_value); 12543c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12553c4e0415SDaniel Scheller 0x90000174, 4, 3, pad_mux_value); 12563c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12573c4e0415SDaniel Scheller 0x90000174, 8, 3, pad_mux_value); 12583c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12593c4e0415SDaniel Scheller 0x90000174, 12, 3, pad_mux_value); 12603c4e0415SDaniel Scheller } 12613c4e0415SDaniel Scheller break; 12623c4e0415SDaniel Scheller 12633c4e0415SDaniel Scheller 12643c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_584: 12653c4e0415SDaniel Scheller default: 12663c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12673c4e0415SDaniel Scheller 0x90000170, 4, 3, pad_mux_value); 12683c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12693c4e0415SDaniel Scheller 0x90000170, 8, 3, pad_mux_value); 12703c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12713c4e0415SDaniel Scheller 0x90000170, 12, 3, pad_mux_value); 12723c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12733c4e0415SDaniel Scheller 0x90000170, 16, 3, pad_mux_value); 12743c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12753c4e0415SDaniel Scheller 0x90000170, 20, 3, pad_mux_value); 12763c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12773c4e0415SDaniel Scheller 0x90000170, 24, 3, pad_mux_value); 12783c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12793c4e0415SDaniel Scheller 0x90000170, 28, 3, pad_mux_value); 12803c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12813c4e0415SDaniel Scheller 0x90000174, 0, 3, pad_mux_value); 12823c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12833c4e0415SDaniel Scheller 0x90000174, 4, 3, pad_mux_value); 12843c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12853c4e0415SDaniel Scheller 0x90000174, 8, 3, pad_mux_value); 12863c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 12873c4e0415SDaniel Scheller 0x90000174, 12, 3, pad_mux_value); 12883c4e0415SDaniel Scheller break; 12893c4e0415SDaniel Scheller } 12903c4e0415SDaniel Scheller return status; 12913c4e0415SDaniel Scheller } 12923c4e0415SDaniel Scheller 12933c4e0415SDaniel Scheller static int set_drive_strength(struct mxl *state, 12943c4e0415SDaniel Scheller enum MXL_HYDRA_TS_DRIVE_STRENGTH_E ts_drive_strength) 12953c4e0415SDaniel Scheller { 12963c4e0415SDaniel Scheller int stat = 0; 12973c4e0415SDaniel Scheller u32 val; 12983c4e0415SDaniel Scheller 12993c4e0415SDaniel Scheller read_register(state, 0x90000194, &val); 13003c4e0415SDaniel Scheller dev_info(state->i2cdev, "DIGIO = %08x\n", val); 13013c4e0415SDaniel Scheller dev_info(state->i2cdev, "set drive_strength = %u\n", ts_drive_strength); 13023c4e0415SDaniel Scheller 13033c4e0415SDaniel Scheller 13043c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000194, 0, 3, ts_drive_strength); 13053c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000194, 20, 3, ts_drive_strength); 13063c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000194, 24, 3, ts_drive_strength); 13073c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000198, 12, 3, ts_drive_strength); 13083c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000198, 16, 3, ts_drive_strength); 13093c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000198, 20, 3, ts_drive_strength); 13103c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x90000198, 24, 3, ts_drive_strength); 13113c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x9000019C, 0, 3, ts_drive_strength); 13123c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x9000019C, 4, 3, ts_drive_strength); 13133c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x9000019C, 8, 3, ts_drive_strength); 13143c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x9000019C, 24, 3, ts_drive_strength); 13153c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x9000019C, 28, 3, ts_drive_strength); 13163c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x900001A0, 0, 3, ts_drive_strength); 13173c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x900001A0, 4, 3, ts_drive_strength); 13183c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x900001A0, 20, 3, ts_drive_strength); 13193c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x900001A0, 24, 3, ts_drive_strength); 13203c4e0415SDaniel Scheller stat |= update_by_mnemonic(state, 0x900001A0, 28, 3, ts_drive_strength); 13213c4e0415SDaniel Scheller 13223c4e0415SDaniel Scheller return stat; 13233c4e0415SDaniel Scheller } 13243c4e0415SDaniel Scheller 13253c4e0415SDaniel Scheller static int enable_tuner(struct mxl *state, u32 tuner, u32 enable) 13263c4e0415SDaniel Scheller { 13273c4e0415SDaniel Scheller int stat = 0; 13283c4e0415SDaniel Scheller struct MXL_HYDRA_TUNER_CMD ctrl_tuner_cmd; 13293c4e0415SDaniel Scheller u8 cmd_size = sizeof(ctrl_tuner_cmd); 13303c4e0415SDaniel Scheller u8 cmd_buff[MXL_HYDRA_OEM_MAX_CMD_BUFF_LEN]; 13313c4e0415SDaniel Scheller u32 val, count = 10; 13323c4e0415SDaniel Scheller 13333c4e0415SDaniel Scheller ctrl_tuner_cmd.tuner_id = tuner; 13343c4e0415SDaniel Scheller ctrl_tuner_cmd.enable = enable; 13353c4e0415SDaniel Scheller BUILD_HYDRA_CMD(MXL_HYDRA_TUNER_ACTIVATE_CMD, MXL_CMD_WRITE, 13363c4e0415SDaniel Scheller cmd_size, &ctrl_tuner_cmd, cmd_buff); 13373c4e0415SDaniel Scheller stat = send_command(state, cmd_size + MXL_HYDRA_CMD_HEADER_SIZE, 13383c4e0415SDaniel Scheller &cmd_buff[0]); 13393c4e0415SDaniel Scheller if (stat) 13403c4e0415SDaniel Scheller return stat; 13413c4e0415SDaniel Scheller read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val); 13423c4e0415SDaniel Scheller while (--count && ((val >> tuner) & 1) != enable) { 13433c4e0415SDaniel Scheller msleep(20); 13443c4e0415SDaniel Scheller read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val); 13453c4e0415SDaniel Scheller } 13463c4e0415SDaniel Scheller if (!count) 13473c4e0415SDaniel Scheller return -1; 13483c4e0415SDaniel Scheller read_register(state, HYDRA_TUNER_ENABLE_COMPLETE, &val); 13493c4e0415SDaniel Scheller dev_dbg(state->i2cdev, "tuner %u ready = %u\n", 13503c4e0415SDaniel Scheller tuner, (val >> tuner) & 1); 13513c4e0415SDaniel Scheller 13523c4e0415SDaniel Scheller return 0; 13533c4e0415SDaniel Scheller } 13543c4e0415SDaniel Scheller 13553c4e0415SDaniel Scheller 13563c4e0415SDaniel Scheller static int config_ts(struct mxl *state, enum MXL_HYDRA_DEMOD_ID_E demod_id, 13573c4e0415SDaniel Scheller struct MXL_HYDRA_MPEGOUT_PARAM_T *mpeg_out_param_ptr) 13583c4e0415SDaniel Scheller { 13593c4e0415SDaniel Scheller int status = 0; 13603c4e0415SDaniel Scheller u32 nco_count_min = 0; 13613c4e0415SDaniel Scheller u32 clk_type = 0; 13623c4e0415SDaniel Scheller 13633c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_sync_polarity[MXL_HYDRA_DEMOD_MAX] = { 13643c4e0415SDaniel Scheller {0x90700010, 8, 1}, {0x90700010, 9, 1}, 13653c4e0415SDaniel Scheller {0x90700010, 10, 1}, {0x90700010, 11, 1}, 13663c4e0415SDaniel Scheller {0x90700010, 12, 1}, {0x90700010, 13, 1}, 13673c4e0415SDaniel Scheller {0x90700010, 14, 1}, {0x90700010, 15, 1} }; 13683c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_clock_polarity[MXL_HYDRA_DEMOD_MAX] = { 13693c4e0415SDaniel Scheller {0x90700010, 16, 1}, {0x90700010, 17, 1}, 13703c4e0415SDaniel Scheller {0x90700010, 18, 1}, {0x90700010, 19, 1}, 13713c4e0415SDaniel Scheller {0x90700010, 20, 1}, {0x90700010, 21, 1}, 13723c4e0415SDaniel Scheller {0x90700010, 22, 1}, {0x90700010, 23, 1} }; 13733c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_valid_polarity[MXL_HYDRA_DEMOD_MAX] = { 13743c4e0415SDaniel Scheller {0x90700014, 0, 1}, {0x90700014, 1, 1}, 13753c4e0415SDaniel Scheller {0x90700014, 2, 1}, {0x90700014, 3, 1}, 13763c4e0415SDaniel Scheller {0x90700014, 4, 1}, {0x90700014, 5, 1}, 13773c4e0415SDaniel Scheller {0x90700014, 6, 1}, {0x90700014, 7, 1} }; 13783c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_ts_clock_phase[MXL_HYDRA_DEMOD_MAX] = { 13793c4e0415SDaniel Scheller {0x90700018, 0, 3}, {0x90700018, 4, 3}, 13803c4e0415SDaniel Scheller {0x90700018, 8, 3}, {0x90700018, 12, 3}, 13813c4e0415SDaniel Scheller {0x90700018, 16, 3}, {0x90700018, 20, 3}, 13823c4e0415SDaniel Scheller {0x90700018, 24, 3}, {0x90700018, 28, 3} }; 13833c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_lsb_first[MXL_HYDRA_DEMOD_MAX] = { 13843c4e0415SDaniel Scheller {0x9070000C, 16, 1}, {0x9070000C, 17, 1}, 13853c4e0415SDaniel Scheller {0x9070000C, 18, 1}, {0x9070000C, 19, 1}, 13863c4e0415SDaniel Scheller {0x9070000C, 20, 1}, {0x9070000C, 21, 1}, 13873c4e0415SDaniel Scheller {0x9070000C, 22, 1}, {0x9070000C, 23, 1} }; 13883c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_sync_byte[MXL_HYDRA_DEMOD_MAX] = { 13893c4e0415SDaniel Scheller {0x90700010, 0, 1}, {0x90700010, 1, 1}, 13903c4e0415SDaniel Scheller {0x90700010, 2, 1}, {0x90700010, 3, 1}, 13913c4e0415SDaniel Scheller {0x90700010, 4, 1}, {0x90700010, 5, 1}, 13923c4e0415SDaniel Scheller {0x90700010, 6, 1}, {0x90700010, 7, 1} }; 13933c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_enable_output[MXL_HYDRA_DEMOD_MAX] = { 13943c4e0415SDaniel Scheller {0x9070000C, 0, 1}, {0x9070000C, 1, 1}, 13953c4e0415SDaniel Scheller {0x9070000C, 2, 1}, {0x9070000C, 3, 1}, 13963c4e0415SDaniel Scheller {0x9070000C, 4, 1}, {0x9070000C, 5, 1}, 13973c4e0415SDaniel Scheller {0x9070000C, 6, 1}, {0x9070000C, 7, 1} }; 13983c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_err_replace_sync[MXL_HYDRA_DEMOD_MAX] = { 13993c4e0415SDaniel Scheller {0x9070000C, 24, 1}, {0x9070000C, 25, 1}, 14003c4e0415SDaniel Scheller {0x9070000C, 26, 1}, {0x9070000C, 27, 1}, 14013c4e0415SDaniel Scheller {0x9070000C, 28, 1}, {0x9070000C, 29, 1}, 14023c4e0415SDaniel Scheller {0x9070000C, 30, 1}, {0x9070000C, 31, 1} }; 14033c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_err_replace_valid[MXL_HYDRA_DEMOD_MAX] = { 14043c4e0415SDaniel Scheller {0x90700014, 8, 1}, {0x90700014, 9, 1}, 14053c4e0415SDaniel Scheller {0x90700014, 10, 1}, {0x90700014, 11, 1}, 14063c4e0415SDaniel Scheller {0x90700014, 12, 1}, {0x90700014, 13, 1}, 14073c4e0415SDaniel Scheller {0x90700014, 14, 1}, {0x90700014, 15, 1} }; 14083c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_continuous_clock[MXL_HYDRA_DEMOD_MAX] = { 14093c4e0415SDaniel Scheller {0x907001D4, 0, 1}, {0x907001D4, 1, 1}, 14103c4e0415SDaniel Scheller {0x907001D4, 2, 1}, {0x907001D4, 3, 1}, 14113c4e0415SDaniel Scheller {0x907001D4, 4, 1}, {0x907001D4, 5, 1}, 14123c4e0415SDaniel Scheller {0x907001D4, 6, 1}, {0x907001D4, 7, 1} }; 14133c4e0415SDaniel Scheller struct MXL_REG_FIELD_T xpt_nco_clock_rate[MXL_HYDRA_DEMOD_MAX] = { 14143c4e0415SDaniel Scheller {0x90700044, 16, 80}, {0x90700044, 16, 81}, 14153c4e0415SDaniel Scheller {0x90700044, 16, 82}, {0x90700044, 16, 83}, 14163c4e0415SDaniel Scheller {0x90700044, 16, 84}, {0x90700044, 16, 85}, 14173c4e0415SDaniel Scheller {0x90700044, 16, 86}, {0x90700044, 16, 87} }; 14183c4e0415SDaniel Scheller 14193c4e0415SDaniel Scheller demod_id = state->base->ts_map[demod_id]; 14203c4e0415SDaniel Scheller 14213c4e0415SDaniel Scheller if (mpeg_out_param_ptr->enable == MXL_ENABLE) { 14223c4e0415SDaniel Scheller if (mpeg_out_param_ptr->mpeg_mode == 14233c4e0415SDaniel Scheller MXL_HYDRA_MPEG_MODE_PARALLEL) { 14243c4e0415SDaniel Scheller } else { 14253c4e0415SDaniel Scheller cfg_ts_pad_mux(state, MXL_TRUE); 14263c4e0415SDaniel Scheller update_by_mnemonic(state, 14273c4e0415SDaniel Scheller 0x90700010, 27, 1, MXL_FALSE); 14283c4e0415SDaniel Scheller } 14293c4e0415SDaniel Scheller } 14303c4e0415SDaniel Scheller 14313c4e0415SDaniel Scheller nco_count_min = 14323c4e0415SDaniel Scheller (u32)(MXL_HYDRA_NCO_CLK / mpeg_out_param_ptr->max_mpeg_clk_rate); 14333c4e0415SDaniel Scheller 14343c4e0415SDaniel Scheller if (state->base->chipversion >= 2) { 14353c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14363c4e0415SDaniel Scheller xpt_nco_clock_rate[demod_id].reg_addr, /* Reg Addr */ 14373c4e0415SDaniel Scheller xpt_nco_clock_rate[demod_id].lsb_pos, /* LSB pos */ 14383c4e0415SDaniel Scheller xpt_nco_clock_rate[demod_id].num_of_bits, /* Num of bits */ 14393c4e0415SDaniel Scheller nco_count_min); /* Data */ 14403c4e0415SDaniel Scheller } else 14413c4e0415SDaniel Scheller update_by_mnemonic(state, 0x90700044, 16, 8, nco_count_min); 14423c4e0415SDaniel Scheller 14433c4e0415SDaniel Scheller if (mpeg_out_param_ptr->mpeg_clk_type == MXL_HYDRA_MPEG_CLK_CONTINUOUS) 14443c4e0415SDaniel Scheller clk_type = 1; 14453c4e0415SDaniel Scheller 14463c4e0415SDaniel Scheller if (mpeg_out_param_ptr->mpeg_mode < MXL_HYDRA_MPEG_MODE_PARALLEL) { 14473c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14483c4e0415SDaniel Scheller xpt_continuous_clock[demod_id].reg_addr, 14493c4e0415SDaniel Scheller xpt_continuous_clock[demod_id].lsb_pos, 14503c4e0415SDaniel Scheller xpt_continuous_clock[demod_id].num_of_bits, 14513c4e0415SDaniel Scheller clk_type); 14523c4e0415SDaniel Scheller } else 14533c4e0415SDaniel Scheller update_by_mnemonic(state, 0x907001D4, 8, 1, clk_type); 14543c4e0415SDaniel Scheller 14553c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14563c4e0415SDaniel Scheller xpt_sync_polarity[demod_id].reg_addr, 14573c4e0415SDaniel Scheller xpt_sync_polarity[demod_id].lsb_pos, 14583c4e0415SDaniel Scheller xpt_sync_polarity[demod_id].num_of_bits, 14593c4e0415SDaniel Scheller mpeg_out_param_ptr->mpeg_sync_pol); 14603c4e0415SDaniel Scheller 14613c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14623c4e0415SDaniel Scheller xpt_valid_polarity[demod_id].reg_addr, 14633c4e0415SDaniel Scheller xpt_valid_polarity[demod_id].lsb_pos, 14643c4e0415SDaniel Scheller xpt_valid_polarity[demod_id].num_of_bits, 14653c4e0415SDaniel Scheller mpeg_out_param_ptr->mpeg_valid_pol); 14663c4e0415SDaniel Scheller 14673c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14683c4e0415SDaniel Scheller xpt_clock_polarity[demod_id].reg_addr, 14693c4e0415SDaniel Scheller xpt_clock_polarity[demod_id].lsb_pos, 14703c4e0415SDaniel Scheller xpt_clock_polarity[demod_id].num_of_bits, 14713c4e0415SDaniel Scheller mpeg_out_param_ptr->mpeg_clk_pol); 14723c4e0415SDaniel Scheller 14733c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14743c4e0415SDaniel Scheller xpt_sync_byte[demod_id].reg_addr, 14753c4e0415SDaniel Scheller xpt_sync_byte[demod_id].lsb_pos, 14763c4e0415SDaniel Scheller xpt_sync_byte[demod_id].num_of_bits, 14773c4e0415SDaniel Scheller mpeg_out_param_ptr->mpeg_sync_pulse_width); 14783c4e0415SDaniel Scheller 14793c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14803c4e0415SDaniel Scheller xpt_ts_clock_phase[demod_id].reg_addr, 14813c4e0415SDaniel Scheller xpt_ts_clock_phase[demod_id].lsb_pos, 14823c4e0415SDaniel Scheller xpt_ts_clock_phase[demod_id].num_of_bits, 14833c4e0415SDaniel Scheller mpeg_out_param_ptr->mpeg_clk_phase); 14843c4e0415SDaniel Scheller 14853c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14863c4e0415SDaniel Scheller xpt_lsb_first[demod_id].reg_addr, 14873c4e0415SDaniel Scheller xpt_lsb_first[demod_id].lsb_pos, 14883c4e0415SDaniel Scheller xpt_lsb_first[demod_id].num_of_bits, 14893c4e0415SDaniel Scheller mpeg_out_param_ptr->lsb_or_msb_first); 14903c4e0415SDaniel Scheller 14913c4e0415SDaniel Scheller switch (mpeg_out_param_ptr->mpeg_error_indication) { 14923c4e0415SDaniel Scheller case MXL_HYDRA_MPEG_ERR_REPLACE_SYNC: 14933c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14943c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].reg_addr, 14953c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].lsb_pos, 14963c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].num_of_bits, 14973c4e0415SDaniel Scheller MXL_TRUE); 14983c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 14993c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].reg_addr, 15003c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].lsb_pos, 15013c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].num_of_bits, 15023c4e0415SDaniel Scheller MXL_FALSE); 15033c4e0415SDaniel Scheller break; 15043c4e0415SDaniel Scheller 15053c4e0415SDaniel Scheller case MXL_HYDRA_MPEG_ERR_REPLACE_VALID: 15063c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15073c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].reg_addr, 15083c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].lsb_pos, 15093c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].num_of_bits, 15103c4e0415SDaniel Scheller MXL_FALSE); 15113c4e0415SDaniel Scheller 15123c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15133c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].reg_addr, 15143c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].lsb_pos, 15153c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].num_of_bits, 15163c4e0415SDaniel Scheller MXL_TRUE); 15173c4e0415SDaniel Scheller break; 15183c4e0415SDaniel Scheller 15193c4e0415SDaniel Scheller case MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED: 15203c4e0415SDaniel Scheller default: 15213c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15223c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].reg_addr, 15233c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].lsb_pos, 15243c4e0415SDaniel Scheller xpt_err_replace_sync[demod_id].num_of_bits, 15253c4e0415SDaniel Scheller MXL_FALSE); 15263c4e0415SDaniel Scheller 15273c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15283c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].reg_addr, 15293c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].lsb_pos, 15303c4e0415SDaniel Scheller xpt_err_replace_valid[demod_id].num_of_bits, 15313c4e0415SDaniel Scheller MXL_FALSE); 15323c4e0415SDaniel Scheller 15333c4e0415SDaniel Scheller break; 15343c4e0415SDaniel Scheller 15353c4e0415SDaniel Scheller } 15363c4e0415SDaniel Scheller 15373c4e0415SDaniel Scheller if (mpeg_out_param_ptr->mpeg_mode != MXL_HYDRA_MPEG_MODE_PARALLEL) { 15383c4e0415SDaniel Scheller status |= update_by_mnemonic(state, 15393c4e0415SDaniel Scheller xpt_enable_output[demod_id].reg_addr, 15403c4e0415SDaniel Scheller xpt_enable_output[demod_id].lsb_pos, 15413c4e0415SDaniel Scheller xpt_enable_output[demod_id].num_of_bits, 15423c4e0415SDaniel Scheller mpeg_out_param_ptr->enable); 15433c4e0415SDaniel Scheller } 15443c4e0415SDaniel Scheller return status; 15453c4e0415SDaniel Scheller } 15463c4e0415SDaniel Scheller 15473c4e0415SDaniel Scheller static int config_mux(struct mxl *state) 15483c4e0415SDaniel Scheller { 15493c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 0, 1, 0); 15503c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 1, 1, 0); 15513c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 2, 1, 0); 15523c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 3, 1, 0); 15533c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 4, 1, 0); 15543c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 5, 1, 0); 15553c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 6, 1, 0); 15563c4e0415SDaniel Scheller update_by_mnemonic(state, 0x9070000C, 7, 1, 0); 15573c4e0415SDaniel Scheller update_by_mnemonic(state, 0x90700008, 0, 2, 1); 15583c4e0415SDaniel Scheller update_by_mnemonic(state, 0x90700008, 2, 2, 1); 15593c4e0415SDaniel Scheller return 0; 15603c4e0415SDaniel Scheller } 15613c4e0415SDaniel Scheller 15623c4e0415SDaniel Scheller static int load_fw(struct mxl *state, struct mxl5xx_cfg *cfg) 15633c4e0415SDaniel Scheller { 15643c4e0415SDaniel Scheller int stat = 0; 15653c4e0415SDaniel Scheller u8 *buf; 15663c4e0415SDaniel Scheller 15673c4e0415SDaniel Scheller if (cfg->fw) 15683c4e0415SDaniel Scheller return firmware_download(state, cfg->fw, cfg->fw_len); 15693c4e0415SDaniel Scheller 15703c4e0415SDaniel Scheller if (!cfg->fw_read) 15713c4e0415SDaniel Scheller return -1; 15723c4e0415SDaniel Scheller 15733c4e0415SDaniel Scheller buf = vmalloc(0x40000); 15743c4e0415SDaniel Scheller if (!buf) 15753c4e0415SDaniel Scheller return -ENOMEM; 15763c4e0415SDaniel Scheller 15773c4e0415SDaniel Scheller cfg->fw_read(cfg->fw_priv, buf, 0x40000); 15783c4e0415SDaniel Scheller stat = firmware_download(state, buf, 0x40000); 15793c4e0415SDaniel Scheller vfree(buf); 15803c4e0415SDaniel Scheller 15813c4e0415SDaniel Scheller return stat; 15823c4e0415SDaniel Scheller } 15833c4e0415SDaniel Scheller 15843c4e0415SDaniel Scheller static int validate_sku(struct mxl *state) 15853c4e0415SDaniel Scheller { 15863c4e0415SDaniel Scheller u32 pad_mux_bond = 0, prcm_chip_id = 0, prcm_so_cid = 0; 15873c4e0415SDaniel Scheller int status; 15883c4e0415SDaniel Scheller u32 type = state->base->type; 15893c4e0415SDaniel Scheller 15903c4e0415SDaniel Scheller status = read_by_mnemonic(state, 0x90000190, 0, 3, &pad_mux_bond); 15913c4e0415SDaniel Scheller status |= read_by_mnemonic(state, 0x80030000, 0, 12, &prcm_chip_id); 15923c4e0415SDaniel Scheller status |= read_by_mnemonic(state, 0x80030004, 24, 8, &prcm_so_cid); 15933c4e0415SDaniel Scheller if (status) 15943c4e0415SDaniel Scheller return -1; 15953c4e0415SDaniel Scheller 15963c4e0415SDaniel Scheller dev_info(state->i2cdev, "padMuxBond=%08x, prcmChipId=%08x, prcmSoCId=%08x\n", 15973c4e0415SDaniel Scheller pad_mux_bond, prcm_chip_id, prcm_so_cid); 15983c4e0415SDaniel Scheller 15993c4e0415SDaniel Scheller if (prcm_chip_id != 0x560) { 16003c4e0415SDaniel Scheller switch (pad_mux_bond) { 16013c4e0415SDaniel Scheller case MXL_HYDRA_SKU_ID_581: 16023c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_581) 16033c4e0415SDaniel Scheller return 0; 16043c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_581S) { 16053c4e0415SDaniel Scheller state->base->type = MXL_HYDRA_DEVICE_581; 16063c4e0415SDaniel Scheller return 0; 16073c4e0415SDaniel Scheller } 16083c4e0415SDaniel Scheller break; 16093c4e0415SDaniel Scheller case MXL_HYDRA_SKU_ID_584: 16103c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_584) 16113c4e0415SDaniel Scheller return 0; 16123c4e0415SDaniel Scheller break; 16133c4e0415SDaniel Scheller case MXL_HYDRA_SKU_ID_544: 16143c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_544) 16153c4e0415SDaniel Scheller return 0; 16163c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_542) 16173c4e0415SDaniel Scheller return 0; 16183c4e0415SDaniel Scheller break; 16193c4e0415SDaniel Scheller case MXL_HYDRA_SKU_ID_582: 16203c4e0415SDaniel Scheller if (type == MXL_HYDRA_DEVICE_582) 16213c4e0415SDaniel Scheller return 0; 16223c4e0415SDaniel Scheller break; 16233c4e0415SDaniel Scheller default: 16243c4e0415SDaniel Scheller return -1; 16253c4e0415SDaniel Scheller } 16263c4e0415SDaniel Scheller } else { 16273c4e0415SDaniel Scheller 16283c4e0415SDaniel Scheller } 16293c4e0415SDaniel Scheller return -1; 16303c4e0415SDaniel Scheller } 16313c4e0415SDaniel Scheller 16323c4e0415SDaniel Scheller static int get_fwinfo(struct mxl *state) 16333c4e0415SDaniel Scheller { 16343c4e0415SDaniel Scheller int status; 16353c4e0415SDaniel Scheller u32 val = 0; 16363c4e0415SDaniel Scheller 16373c4e0415SDaniel Scheller status = read_by_mnemonic(state, 0x90000190, 0, 3, &val); 16383c4e0415SDaniel Scheller if (status) 16393c4e0415SDaniel Scheller return status; 16403c4e0415SDaniel Scheller dev_info(state->i2cdev, "chipID=%08x\n", val); 16413c4e0415SDaniel Scheller 16423c4e0415SDaniel Scheller status = read_by_mnemonic(state, 0x80030004, 8, 8, &val); 16433c4e0415SDaniel Scheller if (status) 16443c4e0415SDaniel Scheller return status; 16453c4e0415SDaniel Scheller dev_info(state->i2cdev, "chipVer=%08x\n", val); 16463c4e0415SDaniel Scheller 16473c4e0415SDaniel Scheller status = read_register(state, HYDRA_FIRMWARE_VERSION, &val); 16483c4e0415SDaniel Scheller if (status) 16493c4e0415SDaniel Scheller return status; 16503c4e0415SDaniel Scheller dev_info(state->i2cdev, "FWVer=%08x\n", val); 16513c4e0415SDaniel Scheller 16523c4e0415SDaniel Scheller state->base->fwversion = val; 16533c4e0415SDaniel Scheller return status; 16543c4e0415SDaniel Scheller } 16553c4e0415SDaniel Scheller 16563c4e0415SDaniel Scheller 16573c4e0415SDaniel Scheller static u8 ts_map1_to_1[MXL_HYDRA_DEMOD_MAX] = { 16583c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_0, 16593c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_1, 16603c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_2, 16613c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_3, 16623c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_4, 16633c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_5, 16643c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_6, 16653c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_7, 16663c4e0415SDaniel Scheller }; 16673c4e0415SDaniel Scheller 16683c4e0415SDaniel Scheller static u8 ts_map54x[MXL_HYDRA_DEMOD_MAX] = { 16693c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_2, 16703c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_3, 16713c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_4, 16723c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_ID_5, 16733c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_MAX, 16743c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_MAX, 16753c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_MAX, 16763c4e0415SDaniel Scheller MXL_HYDRA_DEMOD_MAX, 16773c4e0415SDaniel Scheller }; 16783c4e0415SDaniel Scheller 16793c4e0415SDaniel Scheller static int probe(struct mxl *state, struct mxl5xx_cfg *cfg) 16803c4e0415SDaniel Scheller { 16813c4e0415SDaniel Scheller u32 chipver; 16823c4e0415SDaniel Scheller int fw, status, j; 16833c4e0415SDaniel Scheller struct MXL_HYDRA_MPEGOUT_PARAM_T mpeg_interface_cfg; 16843c4e0415SDaniel Scheller 16853c4e0415SDaniel Scheller state->base->ts_map = ts_map1_to_1; 16863c4e0415SDaniel Scheller 16873c4e0415SDaniel Scheller switch (state->base->type) { 16883c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_581: 16893c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_581S: 16903c4e0415SDaniel Scheller state->base->can_clkout = 1; 16913c4e0415SDaniel Scheller state->base->demod_num = 8; 16923c4e0415SDaniel Scheller state->base->tuner_num = 1; 16933c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_581; 16943c4e0415SDaniel Scheller break; 16953c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_582: 16963c4e0415SDaniel Scheller state->base->can_clkout = 1; 16973c4e0415SDaniel Scheller state->base->demod_num = 8; 16983c4e0415SDaniel Scheller state->base->tuner_num = 3; 16993c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_582; 17003c4e0415SDaniel Scheller break; 17013c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_585: 17023c4e0415SDaniel Scheller state->base->can_clkout = 0; 17033c4e0415SDaniel Scheller state->base->demod_num = 8; 17043c4e0415SDaniel Scheller state->base->tuner_num = 4; 17053c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_585; 17063c4e0415SDaniel Scheller break; 17073c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_544: 17083c4e0415SDaniel Scheller state->base->can_clkout = 0; 17093c4e0415SDaniel Scheller state->base->demod_num = 4; 17103c4e0415SDaniel Scheller state->base->tuner_num = 4; 17113c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_544; 17123c4e0415SDaniel Scheller state->base->ts_map = ts_map54x; 17133c4e0415SDaniel Scheller break; 17143c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_541: 17153c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_541S: 17163c4e0415SDaniel Scheller state->base->can_clkout = 0; 17173c4e0415SDaniel Scheller state->base->demod_num = 4; 17183c4e0415SDaniel Scheller state->base->tuner_num = 1; 17193c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_541; 17203c4e0415SDaniel Scheller state->base->ts_map = ts_map54x; 17213c4e0415SDaniel Scheller break; 17223c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_561: 17233c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_561S: 17243c4e0415SDaniel Scheller state->base->can_clkout = 0; 17253c4e0415SDaniel Scheller state->base->demod_num = 6; 17263c4e0415SDaniel Scheller state->base->tuner_num = 1; 17273c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_561; 17283c4e0415SDaniel Scheller break; 17293c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_568: 17303c4e0415SDaniel Scheller state->base->can_clkout = 0; 17313c4e0415SDaniel Scheller state->base->demod_num = 8; 17323c4e0415SDaniel Scheller state->base->tuner_num = 1; 17333c4e0415SDaniel Scheller state->base->chan_bond = 1; 17343c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_568; 17353c4e0415SDaniel Scheller break; 17363c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_542: 17373c4e0415SDaniel Scheller state->base->can_clkout = 1; 17383c4e0415SDaniel Scheller state->base->demod_num = 4; 17393c4e0415SDaniel Scheller state->base->tuner_num = 3; 17403c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_542; 17413c4e0415SDaniel Scheller state->base->ts_map = ts_map54x; 17423c4e0415SDaniel Scheller break; 17433c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_TEST: 17443c4e0415SDaniel Scheller case MXL_HYDRA_DEVICE_584: 17453c4e0415SDaniel Scheller default: 17463c4e0415SDaniel Scheller state->base->can_clkout = 0; 17473c4e0415SDaniel Scheller state->base->demod_num = 8; 17483c4e0415SDaniel Scheller state->base->tuner_num = 4; 17493c4e0415SDaniel Scheller state->base->sku_type = MXL_HYDRA_SKU_TYPE_584; 17503c4e0415SDaniel Scheller break; 17513c4e0415SDaniel Scheller } 17523c4e0415SDaniel Scheller 17533c4e0415SDaniel Scheller status = validate_sku(state); 17543c4e0415SDaniel Scheller if (status) 17553c4e0415SDaniel Scheller return status; 17563c4e0415SDaniel Scheller 17573c4e0415SDaniel Scheller update_by_mnemonic(state, 0x80030014, 9, 1, 1); 17583c4e0415SDaniel Scheller update_by_mnemonic(state, 0x8003003C, 12, 1, 1); 17593c4e0415SDaniel Scheller status = read_by_mnemonic(state, 0x80030000, 12, 4, &chipver); 17603c4e0415SDaniel Scheller if (status) 17613c4e0415SDaniel Scheller state->base->chipversion = 0; 17623c4e0415SDaniel Scheller else 17633c4e0415SDaniel Scheller state->base->chipversion = (chipver == 2) ? 2 : 1; 17643c4e0415SDaniel Scheller dev_info(state->i2cdev, "Hydra chip version %u\n", 17653c4e0415SDaniel Scheller state->base->chipversion); 17663c4e0415SDaniel Scheller 17673c4e0415SDaniel Scheller cfg_dev_xtal(state, cfg->clk, cfg->cap, 0); 17683c4e0415SDaniel Scheller 17693c4e0415SDaniel Scheller fw = firmware_is_alive(state); 17703c4e0415SDaniel Scheller if (!fw) { 17713c4e0415SDaniel Scheller status = load_fw(state, cfg); 17723c4e0415SDaniel Scheller if (status) 17733c4e0415SDaniel Scheller return status; 17743c4e0415SDaniel Scheller } 17753c4e0415SDaniel Scheller get_fwinfo(state); 17763c4e0415SDaniel Scheller 17773c4e0415SDaniel Scheller config_mux(state); 17783c4e0415SDaniel Scheller mpeg_interface_cfg.enable = MXL_ENABLE; 17793c4e0415SDaniel Scheller mpeg_interface_cfg.lsb_or_msb_first = MXL_HYDRA_MPEG_SERIAL_MSB_1ST; 17803c4e0415SDaniel Scheller /* supports only (0-104&139)MHz */ 17813c4e0415SDaniel Scheller if (cfg->ts_clk) 17823c4e0415SDaniel Scheller mpeg_interface_cfg.max_mpeg_clk_rate = cfg->ts_clk; 17833c4e0415SDaniel Scheller else 17843c4e0415SDaniel Scheller mpeg_interface_cfg.max_mpeg_clk_rate = 69; /* 139; */ 17853c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_clk_phase = MXL_HYDRA_MPEG_CLK_PHASE_SHIFT_0_DEG; 17863c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_clk_pol = MXL_HYDRA_MPEG_CLK_IN_PHASE; 17873c4e0415SDaniel Scheller /* MXL_HYDRA_MPEG_CLK_GAPPED; */ 17883c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_clk_type = MXL_HYDRA_MPEG_CLK_CONTINUOUS; 17893c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_error_indication = 17903c4e0415SDaniel Scheller MXL_HYDRA_MPEG_ERR_INDICATION_DISABLED; 17913c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_mode = MXL_HYDRA_MPEG_MODE_SERIAL_3_WIRE; 17923c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_sync_pol = MXL_HYDRA_MPEG_ACTIVE_HIGH; 17933c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_sync_pulse_width = MXL_HYDRA_MPEG_SYNC_WIDTH_BIT; 17943c4e0415SDaniel Scheller mpeg_interface_cfg.mpeg_valid_pol = MXL_HYDRA_MPEG_ACTIVE_HIGH; 17953c4e0415SDaniel Scheller 17963c4e0415SDaniel Scheller for (j = 0; j < state->base->demod_num; j++) { 17973c4e0415SDaniel Scheller status = config_ts(state, (enum MXL_HYDRA_DEMOD_ID_E) j, 17983c4e0415SDaniel Scheller &mpeg_interface_cfg); 17993c4e0415SDaniel Scheller if (status) 18003c4e0415SDaniel Scheller return status; 18013c4e0415SDaniel Scheller } 18023c4e0415SDaniel Scheller set_drive_strength(state, 1); 18033c4e0415SDaniel Scheller return 0; 18043c4e0415SDaniel Scheller } 18053c4e0415SDaniel Scheller 18063c4e0415SDaniel Scheller struct dvb_frontend *mxl5xx_attach(struct i2c_adapter *i2c, 18073c4e0415SDaniel Scheller struct mxl5xx_cfg *cfg, u32 demod, u32 tuner, 18083c4e0415SDaniel Scheller int (**fn_set_input)(struct dvb_frontend *, int)) 18093c4e0415SDaniel Scheller { 18103c4e0415SDaniel Scheller struct mxl *state; 18113c4e0415SDaniel Scheller struct mxl_base *base; 18123c4e0415SDaniel Scheller 18133c4e0415SDaniel Scheller state = kzalloc(sizeof(struct mxl), GFP_KERNEL); 18143c4e0415SDaniel Scheller if (!state) 18153c4e0415SDaniel Scheller return NULL; 18163c4e0415SDaniel Scheller 18173c4e0415SDaniel Scheller state->demod = demod; 18183c4e0415SDaniel Scheller state->tuner = tuner; 18193c4e0415SDaniel Scheller state->tuner_in_use = 0xffffffff; 18203c4e0415SDaniel Scheller state->i2cdev = &i2c->dev; 18213c4e0415SDaniel Scheller 18223c4e0415SDaniel Scheller base = match_base(i2c, cfg->adr); 18233c4e0415SDaniel Scheller if (base) { 18243c4e0415SDaniel Scheller base->count++; 18253c4e0415SDaniel Scheller if (base->count > base->demod_num) 18263c4e0415SDaniel Scheller goto fail; 18273c4e0415SDaniel Scheller state->base = base; 18283c4e0415SDaniel Scheller } else { 18293c4e0415SDaniel Scheller base = kzalloc(sizeof(struct mxl_base), GFP_KERNEL); 18303c4e0415SDaniel Scheller if (!base) 18313c4e0415SDaniel Scheller goto fail; 18323c4e0415SDaniel Scheller base->i2c = i2c; 18333c4e0415SDaniel Scheller base->adr = cfg->adr; 18343c4e0415SDaniel Scheller base->type = cfg->type; 18353c4e0415SDaniel Scheller base->count = 1; 18363c4e0415SDaniel Scheller mutex_init(&base->i2c_lock); 18373c4e0415SDaniel Scheller mutex_init(&base->status_lock); 18383c4e0415SDaniel Scheller mutex_init(&base->tune_lock); 18393c4e0415SDaniel Scheller INIT_LIST_HEAD(&base->mxls); 18403c4e0415SDaniel Scheller 18413c4e0415SDaniel Scheller state->base = base; 18423c4e0415SDaniel Scheller if (probe(state, cfg) < 0) { 18433c4e0415SDaniel Scheller kfree(base); 18443c4e0415SDaniel Scheller goto fail; 18453c4e0415SDaniel Scheller } 18463c4e0415SDaniel Scheller list_add(&base->mxllist, &mxllist); 18473c4e0415SDaniel Scheller } 18483c4e0415SDaniel Scheller state->fe.ops = mxl_ops; 18493c4e0415SDaniel Scheller state->xbar[0] = 4; 18503c4e0415SDaniel Scheller state->xbar[1] = demod; 18513c4e0415SDaniel Scheller state->xbar[2] = 8; 18523c4e0415SDaniel Scheller state->fe.demodulator_priv = state; 18533c4e0415SDaniel Scheller *fn_set_input = set_input; 18543c4e0415SDaniel Scheller 18553c4e0415SDaniel Scheller list_add(&state->mxl, &base->mxls); 18563c4e0415SDaniel Scheller return &state->fe; 18573c4e0415SDaniel Scheller 18583c4e0415SDaniel Scheller fail: 18593c4e0415SDaniel Scheller kfree(state); 18603c4e0415SDaniel Scheller return NULL; 18613c4e0415SDaniel Scheller } 18623c4e0415SDaniel Scheller EXPORT_SYMBOL_GPL(mxl5xx_attach); 18633c4e0415SDaniel Scheller 18643c4e0415SDaniel Scheller MODULE_DESCRIPTION("MaxLinear MxL5xx DVB-S/S2 tuner-demodulator driver"); 18653c4e0415SDaniel Scheller MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR"); 18663c4e0415SDaniel Scheller MODULE_LICENSE("GPL"); 1867