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