cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mxl692.c (35370B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Driver for the MaxLinear MxL69x family of combo tuners/demods
      4 *
      5 * Copyright (C) 2020 Brad Love <brad@nextdimension.cc>
      6 *
      7 * based on code:
      8 * Copyright (c) 2016 MaxLinear, Inc. All rights reserved
      9 * which was released under GPL V2
     10 */
     11
     12#include <linux/mutex.h>
     13#include <linux/i2c-mux.h>
     14#include <linux/string.h>
     15#include <linux/firmware.h>
     16
     17#include "mxl692.h"
     18#include "mxl692_defs.h"
     19
     20static const struct dvb_frontend_ops mxl692_ops;
     21
     22struct mxl692_dev {
     23	struct dvb_frontend fe;
     24	struct i2c_client *i2c_client;
     25	struct mutex i2c_lock;		/* i2c command mutex */
     26	enum MXL_EAGLE_DEMOD_TYPE_E demod_type;
     27	enum MXL_EAGLE_POWER_MODE_E power_mode;
     28	u32 current_frequency;
     29	int device_type;
     30	int seqnum;
     31	int init_done;
     32};
     33
     34static int mxl692_i2c_write(struct mxl692_dev *dev, u8 *buffer, u16 buf_len)
     35{
     36	int ret = 0;
     37	struct i2c_msg msg = {
     38		.addr = dev->i2c_client->addr,
     39		.flags = 0,
     40		.buf = buffer,
     41		.len = buf_len
     42	};
     43
     44	ret = i2c_transfer(dev->i2c_client->adapter, &msg, 1);
     45	if (ret != 1)
     46		dev_dbg(&dev->i2c_client->dev, "i2c write error!\n");
     47
     48	return ret;
     49}
     50
     51static int mxl692_i2c_read(struct mxl692_dev *dev, u8 *buffer, u16 buf_len)
     52{
     53	int ret = 0;
     54	struct i2c_msg msg = {
     55		.addr = dev->i2c_client->addr,
     56		.flags = I2C_M_RD,
     57		.buf = buffer,
     58		.len = buf_len
     59	};
     60
     61	ret = i2c_transfer(dev->i2c_client->adapter, &msg, 1);
     62	if (ret != 1)
     63		dev_dbg(&dev->i2c_client->dev, "i2c read error!\n");
     64
     65	return ret;
     66}
     67
     68static int convert_endian(u32 size, u8 *d)
     69{
     70	u32 i;
     71
     72	for (i = 0; i < (size & ~3); i += 4) {
     73		d[i + 0] ^= d[i + 3];
     74		d[i + 3] ^= d[i + 0];
     75		d[i + 0] ^= d[i + 3];
     76
     77		d[i + 1] ^= d[i + 2];
     78		d[i + 2] ^= d[i + 1];
     79		d[i + 1] ^= d[i + 2];
     80	}
     81
     82	switch (size & 3) {
     83	case 0:
     84	case 1:
     85		/* do nothing */
     86		break;
     87	case 2:
     88		d[i + 0] ^= d[i + 1];
     89		d[i + 1] ^= d[i + 0];
     90		d[i + 0] ^= d[i + 1];
     91		break;
     92
     93	case 3:
     94		d[i + 0] ^= d[i + 2];
     95		d[i + 2] ^= d[i + 0];
     96		d[i + 0] ^= d[i + 2];
     97		break;
     98	}
     99	return size;
    100}
    101
    102static int convert_endian_n(int n, u32 size, u8 *d)
    103{
    104	int i, count = 0;
    105
    106	for (i = 0; i < n; i += size)
    107		count += convert_endian(size, d + i);
    108	return count;
    109}
    110
    111static void mxl692_tx_swap(enum MXL_EAGLE_OPCODE_E opcode, u8 *buffer)
    112{
    113#ifdef __BIG_ENDIAN
    114	return;
    115#endif
    116	buffer += MXL_EAGLE_HOST_MSG_HEADER_SIZE; /* skip API header */
    117
    118	switch (opcode) {
    119	case MXL_EAGLE_OPCODE_DEVICE_INTR_MASK_SET:
    120	case MXL_EAGLE_OPCODE_TUNER_CHANNEL_TUNE_SET:
    121	case MXL_EAGLE_OPCODE_SMA_TRANSMIT_SET:
    122		buffer += convert_endian(sizeof(u32), buffer);
    123		break;
    124	case MXL_EAGLE_OPCODE_QAM_PARAMS_SET:
    125		buffer += 5;
    126		buffer += convert_endian(2 * sizeof(u32), buffer);
    127		break;
    128	default:
    129		/* no swapping - all get opcodes */
    130		/* ATSC/OOB no swapping */
    131		break;
    132	}
    133}
    134
    135static void mxl692_rx_swap(enum MXL_EAGLE_OPCODE_E opcode, u8 *buffer)
    136{
    137#ifdef __BIG_ENDIAN
    138	return;
    139#endif
    140	buffer += MXL_EAGLE_HOST_MSG_HEADER_SIZE; /* skip API header */
    141
    142	switch (opcode) {
    143	case MXL_EAGLE_OPCODE_TUNER_AGC_STATUS_GET:
    144		buffer++;
    145		buffer += convert_endian(2 * sizeof(u16), buffer);
    146		break;
    147	case MXL_EAGLE_OPCODE_ATSC_STATUS_GET:
    148		buffer += convert_endian_n(2, sizeof(u16), buffer);
    149		buffer += convert_endian(sizeof(u32), buffer);
    150		break;
    151	case MXL_EAGLE_OPCODE_ATSC_ERROR_COUNTERS_GET:
    152		buffer += convert_endian(3 * sizeof(u32), buffer);
    153		break;
    154	case MXL_EAGLE_OPCODE_ATSC_EQUALIZER_FILTER_FFE_TAPS_GET:
    155		buffer += convert_endian_n(24, sizeof(u16), buffer);
    156		break;
    157	case MXL_EAGLE_OPCODE_QAM_STATUS_GET:
    158		buffer += 8;
    159		buffer += convert_endian_n(2, sizeof(u16), buffer);
    160		buffer += convert_endian(sizeof(u32), buffer);
    161		break;
    162	case MXL_EAGLE_OPCODE_QAM_ERROR_COUNTERS_GET:
    163		buffer += convert_endian(7 * sizeof(u32), buffer);
    164		break;
    165	case MXL_EAGLE_OPCODE_QAM_CONSTELLATION_VALUE_GET:
    166	case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_START_GET:
    167	case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_MIDDLE_GET:
    168	case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_END_GET:
    169	case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_SPUR_START_GET:
    170		buffer += convert_endian_n(24, sizeof(u16), buffer);
    171		break;
    172	case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_SPUR_END_GET:
    173		buffer += convert_endian_n(8, sizeof(u16), buffer);
    174		break;
    175	case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_FFE_GET:
    176		buffer += convert_endian_n(17, sizeof(u16), buffer);
    177		break;
    178	case MXL_EAGLE_OPCODE_OOB_ERROR_COUNTERS_GET:
    179		buffer += convert_endian(3 * sizeof(u32), buffer);
    180		break;
    181	case MXL_EAGLE_OPCODE_OOB_STATUS_GET:
    182		buffer += convert_endian_n(2, sizeof(u16), buffer);
    183		buffer += convert_endian(sizeof(u32), buffer);
    184		break;
    185	case MXL_EAGLE_OPCODE_SMA_RECEIVE_GET:
    186		buffer += convert_endian(sizeof(u32), buffer);
    187		break;
    188	default:
    189		/* no swapping - all set opcodes */
    190		break;
    191	}
    192}
    193
    194static u32 mxl692_checksum(u8 *buffer, u32 size)
    195{
    196	u32 ix, div_size;
    197	u32 cur_cksum = 0;
    198	__be32 *buf;
    199
    200	div_size = DIV_ROUND_UP(size, 4);
    201
    202	buf = (__be32 *)buffer;
    203	for (ix = 0; ix < div_size; ix++)
    204		cur_cksum += be32_to_cpu(buf[ix]);
    205
    206	cur_cksum ^= 0xDEADBEEF;
    207
    208	return cur_cksum;
    209}
    210
    211static int mxl692_validate_fw_header(struct mxl692_dev *dev,
    212				     const u8 *buffer, u32 buf_len)
    213{
    214	int status = 0;
    215	u32 ix, temp;
    216	__be32 *local_buf = NULL;
    217	u8 temp_cksum = 0;
    218	static const u8 fw_hdr[] = {
    219		0x4D, 0x31, 0x10, 0x02, 0x40, 0x00, 0x00, 0x80
    220	};
    221
    222	if (memcmp(buffer, fw_hdr, 8) != 0) {
    223		status = -EINVAL;
    224		goto err_finish;
    225	}
    226
    227	local_buf = (__be32 *)(buffer + 8);
    228	temp = be32_to_cpu(*local_buf);
    229
    230	if ((buf_len - 16) != temp >> 8) {
    231		status = -EINVAL;
    232		goto err_finish;
    233	}
    234
    235	for (ix = 16; ix < buf_len; ix++)
    236		temp_cksum += buffer[ix];
    237
    238	if (temp_cksum != buffer[11])
    239		status = -EINVAL;
    240
    241err_finish:
    242	if (status)
    243		dev_dbg(&dev->i2c_client->dev, "failed\n");
    244	return status;
    245}
    246
    247static int mxl692_write_fw_block(struct mxl692_dev *dev, const u8 *buffer,
    248				 u32 buf_len, u32 *index)
    249{
    250	int status = 0;
    251	u32 ix = 0, total_len = 0, addr = 0, chunk_len = 0, prevchunk_len = 0;
    252	u8 local_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {}, *plocal_buf = NULL;
    253	int payload_max = MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_MHEADER_SIZE;
    254
    255	ix = *index;
    256
    257	if (buffer[ix] == 0x53) {
    258		total_len = buffer[ix + 1] << 16 | buffer[ix + 2] << 8 | buffer[ix + 3];
    259		total_len = (total_len + 3) & ~3;
    260		addr      = buffer[ix + 4] << 24 | buffer[ix + 5] << 16 |
    261			    buffer[ix + 6] << 8 | buffer[ix + 7];
    262		ix       += MXL_EAGLE_FW_SEGMENT_HEADER_SIZE;
    263
    264		while ((total_len > 0) && (status == 0)) {
    265			plocal_buf = local_buf;
    266			chunk_len  = (total_len < payload_max) ? total_len : payload_max;
    267
    268			*plocal_buf++ = 0xFC;
    269			*plocal_buf++ = chunk_len + sizeof(u32);
    270
    271			*(u32 *)plocal_buf = addr + prevchunk_len;
    272#ifdef __BIG_ENDIAN
    273			convert_endian(sizeof(u32), plocal_buf);
    274#endif
    275			plocal_buf += sizeof(u32);
    276
    277			memcpy(plocal_buf, &buffer[ix], chunk_len);
    278			convert_endian(chunk_len, plocal_buf);
    279			if (mxl692_i2c_write(dev, local_buf,
    280					     (chunk_len + MXL_EAGLE_I2C_MHEADER_SIZE)) < 0) {
    281				status = -EREMOTEIO;
    282				break;
    283			}
    284
    285			prevchunk_len += chunk_len;
    286			total_len -= chunk_len;
    287			ix += chunk_len;
    288		}
    289		*index = ix;
    290	} else {
    291		status = -EINVAL;
    292	}
    293
    294	if (status)
    295		dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    296
    297	return status;
    298}
    299
    300static int mxl692_memwrite(struct mxl692_dev *dev, u32 addr,
    301			   u8 *buffer, u32 size)
    302{
    303	int status = 0, total_len = 0;
    304	u8 local_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {}, *plocal_buf = NULL;
    305
    306	total_len = size;
    307	total_len = (total_len + 3) & ~3;  /* 4 byte alignment */
    308
    309	if (total_len > (MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_MHEADER_SIZE))
    310		dev_dbg(&dev->i2c_client->dev, "hrmph?\n");
    311
    312	plocal_buf = local_buf;
    313
    314	*plocal_buf++ = 0xFC;
    315	*plocal_buf++ = total_len + sizeof(u32);
    316
    317	*(u32 *)plocal_buf = addr;
    318	plocal_buf += sizeof(u32);
    319
    320	memcpy(plocal_buf, buffer, total_len);
    321#ifdef __BIG_ENDIAN
    322	convert_endian(sizeof(u32) + total_len, local_buf + 2);
    323#endif
    324	if (mxl692_i2c_write(dev, local_buf,
    325			     (total_len + MXL_EAGLE_I2C_MHEADER_SIZE)) < 0) {
    326		status = -EREMOTEIO;
    327		goto err_finish;
    328	}
    329
    330	return status;
    331err_finish:
    332	dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    333	return status;
    334}
    335
    336static int mxl692_memread(struct mxl692_dev *dev, u32 addr,
    337			  u8 *buffer, u32 size)
    338{
    339	int status = 0;
    340	u8 local_buf[MXL_EAGLE_I2C_MHEADER_SIZE] = {}, *plocal_buf = NULL;
    341
    342	plocal_buf = local_buf;
    343
    344	*plocal_buf++ = 0xFB;
    345	*plocal_buf++ = sizeof(u32);
    346	*(u32 *)plocal_buf = addr;
    347#ifdef __BIG_ENDIAN
    348	convert_endian(sizeof(u32), plocal_buf);
    349#endif
    350	mutex_lock(&dev->i2c_lock);
    351
    352	if (mxl692_i2c_write(dev, local_buf, MXL_EAGLE_I2C_MHEADER_SIZE) > 0) {
    353		size = (size + 3) & ~3;  /* 4 byte alignment */
    354		status = mxl692_i2c_read(dev, buffer, (u16)size) < 0 ? -EREMOTEIO : 0;
    355#ifdef __BIG_ENDIAN
    356		if (status == 0)
    357			convert_endian(size, buffer);
    358#endif
    359	} else {
    360		status = -EREMOTEIO;
    361	}
    362
    363	mutex_unlock(&dev->i2c_lock);
    364
    365	if (status)
    366		dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    367
    368	return status;
    369}
    370
    371static const char *mxl692_opcode_string(u8 opcode)
    372{
    373	if (opcode <= MXL_EAGLE_OPCODE_INTERNAL)
    374		return MXL_EAGLE_OPCODE_STRING[opcode];
    375
    376	return "invalid opcode";
    377}
    378
    379static int mxl692_opwrite(struct mxl692_dev *dev, u8 *buffer,
    380			  u32 size)
    381{
    382	int status = 0, total_len = 0;
    383	u8 local_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {}, *plocal_buf = NULL;
    384	struct MXL_EAGLE_HOST_MSG_HEADER_T *tx_hdr = (struct MXL_EAGLE_HOST_MSG_HEADER_T *)buffer;
    385
    386	total_len = size;
    387	total_len = (total_len + 3) & ~3;  /* 4 byte alignment */
    388
    389	if (total_len > (MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_PHEADER_SIZE))
    390		dev_dbg(&dev->i2c_client->dev, "hrmph?\n");
    391
    392	plocal_buf = local_buf;
    393
    394	*plocal_buf++ = 0xFE;
    395	*plocal_buf++ = (u8)total_len;
    396
    397	memcpy(plocal_buf, buffer, total_len);
    398	convert_endian(total_len, plocal_buf);
    399
    400	if (mxl692_i2c_write(dev, local_buf,
    401			     (total_len + MXL_EAGLE_I2C_PHEADER_SIZE)) < 0) {
    402		status = -EREMOTEIO;
    403		goto err_finish;
    404	}
    405err_finish:
    406	if (status)
    407		dev_dbg(&dev->i2c_client->dev, "opcode %s  err %d\n",
    408			mxl692_opcode_string(tx_hdr->opcode), status);
    409	return status;
    410}
    411
    412static int mxl692_opread(struct mxl692_dev *dev, u8 *buffer,
    413			 u32 size)
    414{
    415	int status = 0;
    416	u32 ix = 0;
    417	u8 local_buf[MXL_EAGLE_I2C_PHEADER_SIZE] = {};
    418
    419	local_buf[0] = 0xFD;
    420	local_buf[1] = 0;
    421
    422	if (mxl692_i2c_write(dev, local_buf, MXL_EAGLE_I2C_PHEADER_SIZE) > 0) {
    423		size = (size + 3) & ~3;  /* 4 byte alignment */
    424
    425		/* Read in 4 byte chunks */
    426		for (ix = 0; ix < size; ix += 4) {
    427			if (mxl692_i2c_read(dev, buffer + ix, 4) < 0) {
    428				dev_dbg(&dev->i2c_client->dev, "ix=%d   size=%d\n", ix, size);
    429				status = -EREMOTEIO;
    430				goto err_finish;
    431			}
    432		}
    433		convert_endian(size, buffer);
    434	} else {
    435		status = -EREMOTEIO;
    436	}
    437err_finish:
    438	if (status)
    439		dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    440	return status;
    441}
    442
    443static int mxl692_i2c_writeread(struct mxl692_dev *dev,
    444				u8 opcode,
    445				u8 *tx_payload,
    446				u8 tx_payload_size,
    447				u8 *rx_payload,
    448				u8 rx_payload_expected)
    449{
    450	int status = 0, timeout = 40;
    451	u8 tx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
    452	u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
    453	u32 resp_checksum = 0, resp_checksum_tmp = 0;
    454	struct MXL_EAGLE_HOST_MSG_HEADER_T *tx_header;
    455	struct MXL_EAGLE_HOST_MSG_HEADER_T *rx_header;
    456
    457	mutex_lock(&dev->i2c_lock);
    458
    459	if ((tx_payload_size + MXL_EAGLE_HOST_MSG_HEADER_SIZE) >
    460	    (MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_PHEADER_SIZE)) {
    461		status = -EINVAL;
    462		goto err_finish;
    463	}
    464
    465	tx_header = (struct MXL_EAGLE_HOST_MSG_HEADER_T *)tx_buf;
    466	tx_header->opcode = opcode;
    467	tx_header->seqnum = dev->seqnum++;
    468	tx_header->payload_size = tx_payload_size;
    469	tx_header->checksum = 0;
    470
    471	if (dev->seqnum == 0)
    472		dev->seqnum = 1;
    473
    474	if (tx_payload && tx_payload_size > 0)
    475		memcpy(&tx_buf[MXL_EAGLE_HOST_MSG_HEADER_SIZE], tx_payload, tx_payload_size);
    476
    477	mxl692_tx_swap(opcode, tx_buf);
    478
    479	tx_header->checksum = 0;
    480	tx_header->checksum = mxl692_checksum(tx_buf,
    481					      MXL_EAGLE_HOST_MSG_HEADER_SIZE + tx_payload_size);
    482#ifdef __LITTLE_ENDIAN
    483	convert_endian(4, (u8 *)&tx_header->checksum); /* cksum is big endian */
    484#endif
    485	/* send Tx message */
    486	status = mxl692_opwrite(dev, tx_buf,
    487				tx_payload_size + MXL_EAGLE_HOST_MSG_HEADER_SIZE);
    488	if (status) {
    489		status = -EREMOTEIO;
    490		goto err_finish;
    491	}
    492
    493	/* receive Rx message (polling) */
    494	rx_header = (struct MXL_EAGLE_HOST_MSG_HEADER_T *)rx_buf;
    495
    496	do {
    497		status = mxl692_opread(dev, rx_buf,
    498				       rx_payload_expected + MXL_EAGLE_HOST_MSG_HEADER_SIZE);
    499		usleep_range(1000, 2000);
    500		timeout--;
    501	} while ((timeout > 0) && (status == 0) &&
    502		 (rx_header->seqnum == 0) &&
    503		 (rx_header->checksum == 0));
    504
    505	if (timeout == 0 || status) {
    506		dev_dbg(&dev->i2c_client->dev, "timeout=%d   status=%d\n",
    507			timeout, status);
    508		status = -ETIMEDOUT;
    509		goto err_finish;
    510	}
    511
    512	if (rx_header->status) {
    513		dev_dbg(&dev->i2c_client->dev, "rx header status code: %d\n", rx_header->status);
    514		status = -EREMOTEIO;
    515		goto err_finish;
    516	}
    517
    518	if (rx_header->seqnum != tx_header->seqnum ||
    519	    rx_header->opcode != tx_header->opcode ||
    520	    rx_header->payload_size != rx_payload_expected) {
    521		dev_dbg(&dev->i2c_client->dev, "Something failed seq=%s  opcode=%s  pSize=%s\n",
    522			rx_header->seqnum != tx_header->seqnum ? "X" : "0",
    523			rx_header->opcode != tx_header->opcode ? "X" : "0",
    524			rx_header->payload_size != rx_payload_expected ? "X" : "0");
    525		if (rx_header->payload_size != rx_payload_expected)
    526			dev_dbg(&dev->i2c_client->dev,
    527				"rx_header->payloadSize=%d   rx_payload_expected=%d\n",
    528				rx_header->payload_size, rx_payload_expected);
    529		status = -EREMOTEIO;
    530		goto err_finish;
    531	}
    532
    533	resp_checksum = rx_header->checksum;
    534	rx_header->checksum = 0;
    535
    536	resp_checksum_tmp = mxl692_checksum(rx_buf,
    537					    MXL_EAGLE_HOST_MSG_HEADER_SIZE + rx_header->payload_size);
    538#ifdef __LITTLE_ENDIAN
    539	convert_endian(4, (u8 *)&resp_checksum_tmp); /* cksum is big endian */
    540#endif
    541	if (resp_checksum != resp_checksum_tmp) {
    542		dev_dbg(&dev->i2c_client->dev, "rx checksum failure\n");
    543		status = -EREMOTEIO;
    544		goto err_finish;
    545	}
    546
    547	mxl692_rx_swap(rx_header->opcode, rx_buf);
    548
    549	if (rx_header->payload_size > 0) {
    550		if (!rx_payload) {
    551			dev_dbg(&dev->i2c_client->dev, "no rx payload?!?\n");
    552			status = -EREMOTEIO;
    553			goto err_finish;
    554		}
    555		memcpy(rx_payload, rx_buf + MXL_EAGLE_HOST_MSG_HEADER_SIZE,
    556		       rx_header->payload_size);
    557	}
    558err_finish:
    559	if (status)
    560		dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    561
    562	mutex_unlock(&dev->i2c_lock);
    563	return status;
    564}
    565
    566static int mxl692_fwdownload(struct mxl692_dev *dev,
    567			     const u8 *firmware_buf, u32 buf_len)
    568{
    569	int status = 0;
    570	u32 ix, reg_val = 0x1;
    571	u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
    572	struct MXL_EAGLE_DEV_STATUS_T *dev_status;
    573
    574	if (buf_len < MXL_EAGLE_FW_HEADER_SIZE ||
    575	    buf_len > MXL_EAGLE_FW_MAX_SIZE_IN_KB * 1000)
    576		return -EINVAL;
    577
    578	mutex_lock(&dev->i2c_lock);
    579
    580	dev_dbg(&dev->i2c_client->dev, "\n");
    581
    582	status = mxl692_validate_fw_header(dev, firmware_buf, buf_len);
    583	if (status)
    584		goto err_finish;
    585
    586	ix = 16;
    587	status = mxl692_write_fw_block(dev, firmware_buf, buf_len, &ix); /* DRAM */
    588	if (status)
    589		goto err_finish;
    590
    591	status = mxl692_write_fw_block(dev, firmware_buf, buf_len, &ix); /* IRAM */
    592	if (status)
    593		goto err_finish;
    594
    595	/* release CPU from reset */
    596	status = mxl692_memwrite(dev, 0x70000018, (u8 *)&reg_val, sizeof(u32));
    597	if (status)
    598		goto err_finish;
    599
    600	mutex_unlock(&dev->i2c_lock);
    601
    602	if (status == 0) {
    603		/* verify FW is alive */
    604		usleep_range(MXL_EAGLE_FW_LOAD_TIME * 1000, (MXL_EAGLE_FW_LOAD_TIME + 5) * 1000);
    605		dev_status = (struct MXL_EAGLE_DEV_STATUS_T *)&rx_buf;
    606		status = mxl692_i2c_writeread(dev,
    607					      MXL_EAGLE_OPCODE_DEVICE_STATUS_GET,
    608					      NULL,
    609					      0,
    610					      (u8 *)dev_status,
    611					      sizeof(struct MXL_EAGLE_DEV_STATUS_T));
    612	}
    613
    614	return status;
    615err_finish:
    616	mutex_unlock(&dev->i2c_lock);
    617	if (status)
    618		dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    619	return status;
    620}
    621
    622static int mxl692_get_versions(struct mxl692_dev *dev)
    623{
    624	int status = 0;
    625	struct MXL_EAGLE_DEV_VER_T dev_ver = {};
    626	static const char * const chip_id[] = {"N/A", "691", "248", "692"};
    627
    628	status = mxl692_i2c_writeread(dev, MXL_EAGLE_OPCODE_DEVICE_VERSION_GET,
    629				      NULL,
    630				      0,
    631				      (u8 *)&dev_ver,
    632				      sizeof(struct MXL_EAGLE_DEV_VER_T));
    633	if (status)
    634		return status;
    635
    636	dev_info(&dev->i2c_client->dev, "MxL692_DEMOD Chip ID: %s\n",
    637		 chip_id[dev_ver.chip_id]);
    638
    639	dev_info(&dev->i2c_client->dev,
    640		 "MxL692_DEMOD FW Version: %d.%d.%d.%d_RC%d\n",
    641		 dev_ver.firmware_ver[0],
    642		 dev_ver.firmware_ver[1],
    643		 dev_ver.firmware_ver[2],
    644		 dev_ver.firmware_ver[3],
    645		 dev_ver.firmware_ver[4]);
    646
    647	return status;
    648}
    649
    650static int mxl692_reset(struct mxl692_dev *dev)
    651{
    652	int status = 0;
    653	u32 dev_type = MXL_EAGLE_DEVICE_MAX, reg_val = 0x2;
    654
    655	dev_dbg(&dev->i2c_client->dev, "\n");
    656
    657	/* legacy i2c override */
    658	status = mxl692_memwrite(dev, 0x80000100, (u8 *)&reg_val, sizeof(u32));
    659	if (status)
    660		goto err_finish;
    661
    662	/* verify sku */
    663	status = mxl692_memread(dev, 0x70000188, (u8 *)&dev_type, sizeof(u32));
    664	if (status)
    665		goto err_finish;
    666
    667	if (dev_type != dev->device_type)
    668		goto err_finish;
    669
    670err_finish:
    671	if (status)
    672		dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    673	return status;
    674}
    675
    676static int mxl692_config_regulators(struct mxl692_dev *dev,
    677				    enum MXL_EAGLE_POWER_SUPPLY_SOURCE_E power_supply)
    678{
    679	int status = 0;
    680	u32 reg_val;
    681
    682	dev_dbg(&dev->i2c_client->dev, "\n");
    683
    684	/* configure main regulator according to the power supply source */
    685	status = mxl692_memread(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
    686	if (status)
    687		goto err_finish;
    688
    689	reg_val &= 0x00FFFFFF;
    690	reg_val |= (power_supply == MXL_EAGLE_POWER_SUPPLY_SOURCE_SINGLE) ?
    691					0x14000000 : 0x10000000;
    692
    693	status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
    694	if (status)
    695		goto err_finish;
    696
    697	/* configure digital regulator to high current mode */
    698	status = mxl692_memread(dev, 0x90000018, (u8 *)&reg_val, sizeof(u32));
    699	if (status)
    700		goto err_finish;
    701
    702	reg_val |= 0x800;
    703
    704	status = mxl692_memwrite(dev, 0x90000018, (u8 *)&reg_val, sizeof(u32));
    705
    706err_finish:
    707	if (status)
    708		dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    709	return status;
    710}
    711
    712static int mxl692_config_xtal(struct mxl692_dev *dev,
    713			      struct MXL_EAGLE_DEV_XTAL_T *dev_xtal)
    714{
    715	int status = 0;
    716	u32 reg_val, reg_val1;
    717
    718	dev_dbg(&dev->i2c_client->dev, "\n");
    719
    720	status = mxl692_memread(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
    721	if (status)
    722		goto err_finish;
    723
    724	/* set XTAL capacitance */
    725	reg_val &= 0xFFFFFFE0;
    726	reg_val |= dev_xtal->xtal_cap;
    727
    728	/* set CLK OUT */
    729	reg_val = dev_xtal->clk_out_enable ? (reg_val | 0x0100) : (reg_val & 0xFFFFFEFF);
    730
    731	status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
    732	if (status)
    733		goto err_finish;
    734
    735	/* set CLK OUT divider */
    736	reg_val = dev_xtal->clk_out_div_enable ? (reg_val | 0x0200) : (reg_val & 0xFFFFFDFF);
    737
    738	status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
    739	if (status)
    740		goto err_finish;
    741
    742	/* set XTAL sharing */
    743	reg_val = dev_xtal->xtal_sharing_enable ? (reg_val | 0x010400) : (reg_val & 0xFFFEFBFF);
    744
    745	status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
    746	if (status)
    747		goto err_finish;
    748
    749	/* enable/disable XTAL calibration, based on master/slave device */
    750	status = mxl692_memread(dev, 0x90000030, (u8 *)&reg_val1, sizeof(u32));
    751	if (status)
    752		goto err_finish;
    753
    754	if (dev_xtal->xtal_calibration_enable) {
    755		/* enable XTAL calibration and set XTAL amplitude to a higher value */
    756		reg_val1 &= 0xFFFFFFFD;
    757		reg_val1 |= 0x30;
    758
    759		status = mxl692_memwrite(dev, 0x90000030, (u8 *)&reg_val1, sizeof(u32));
    760		if (status)
    761			goto err_finish;
    762	} else {
    763		/* disable XTAL calibration */
    764		reg_val1 |= 0x2;
    765
    766		status = mxl692_memwrite(dev, 0x90000030, (u8 *)&reg_val1, sizeof(u32));
    767		if (status)
    768			goto err_finish;
    769
    770		/* set XTAL bias value */
    771		status = mxl692_memread(dev, 0x9000002c, (u8 *)&reg_val, sizeof(u32));
    772		if (status)
    773			goto err_finish;
    774
    775		reg_val &= 0xC0FFFFFF;
    776		reg_val |= 0xA000000;
    777
    778		status = mxl692_memwrite(dev, 0x9000002c, (u8 *)&reg_val, sizeof(u32));
    779		if (status)
    780			goto err_finish;
    781	}
    782
    783	/* start XTAL calibration */
    784	status = mxl692_memread(dev, 0x70000010, (u8 *)&reg_val, sizeof(u32));
    785	if (status)
    786		goto err_finish;
    787
    788	reg_val |= 0x8;
    789
    790	status = mxl692_memwrite(dev, 0x70000010, (u8 *)&reg_val, sizeof(u32));
    791	if (status)
    792		goto err_finish;
    793
    794	status = mxl692_memread(dev, 0x70000018, (u8 *)&reg_val, sizeof(u32));
    795	if (status)
    796		goto err_finish;
    797
    798	reg_val |= 0x10;
    799
    800	status = mxl692_memwrite(dev, 0x70000018, (u8 *)&reg_val, sizeof(u32));
    801	if (status)
    802		goto err_finish;
    803
    804	status = mxl692_memread(dev, 0x9001014c, (u8 *)&reg_val, sizeof(u32));
    805	if (status)
    806		goto err_finish;
    807
    808	reg_val &= 0xFFFFEFFF;
    809
    810	status = mxl692_memwrite(dev, 0x9001014c, (u8 *)&reg_val, sizeof(u32));
    811	if (status)
    812		goto err_finish;
    813
    814	reg_val |= 0x1000;
    815
    816	status = mxl692_memwrite(dev, 0x9001014c, (u8 *)&reg_val, sizeof(u32));
    817	if (status)
    818		goto err_finish;
    819
    820	usleep_range(45000, 55000);
    821
    822err_finish:
    823	if (status)
    824		dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    825	return status;
    826}
    827
    828static int mxl692_powermode(struct mxl692_dev *dev,
    829			    enum MXL_EAGLE_POWER_MODE_E power_mode)
    830{
    831	int status = 0;
    832	u8 mode = power_mode;
    833
    834	dev_dbg(&dev->i2c_client->dev, "%s\n",
    835		power_mode == MXL_EAGLE_POWER_MODE_SLEEP ? "sleep" : "active");
    836
    837	status = mxl692_i2c_writeread(dev,
    838				      MXL_EAGLE_OPCODE_DEVICE_POWERMODE_SET,
    839				      &mode,
    840				      sizeof(u8),
    841				      NULL,
    842				      0);
    843	if (status) {
    844		dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    845		return status;
    846	}
    847
    848	dev->power_mode = power_mode;
    849
    850	return status;
    851}
    852
    853static int mxl692_init(struct dvb_frontend *fe)
    854{
    855	struct mxl692_dev *dev = fe->demodulator_priv;
    856	struct i2c_client *client = dev->i2c_client;
    857	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
    858	int status = 0;
    859	const struct firmware *firmware;
    860	struct MXL_EAGLE_DEV_XTAL_T xtal_config = {};
    861
    862	dev_dbg(&dev->i2c_client->dev, "\n");
    863
    864	if (dev->init_done)
    865		goto warm;
    866
    867	dev->seqnum = 1;
    868
    869	status = mxl692_reset(dev);
    870	if (status)
    871		goto err;
    872
    873	usleep_range(50 * 1000, 60 * 1000); /* was 1000! */
    874
    875	status = mxl692_config_regulators(dev, MXL_EAGLE_POWER_SUPPLY_SOURCE_DUAL);
    876	if (status)
    877		goto err;
    878
    879	xtal_config.xtal_cap = 26;
    880	xtal_config.clk_out_div_enable = 0;
    881	xtal_config.clk_out_enable = 0;
    882	xtal_config.xtal_calibration_enable = 0;
    883	xtal_config.xtal_sharing_enable = 1;
    884	status = mxl692_config_xtal(dev, &xtal_config);
    885	if (status)
    886		goto err;
    887
    888	status = request_firmware(&firmware, MXL692_FIRMWARE, &client->dev);
    889	if (status) {
    890		dev_dbg(&dev->i2c_client->dev, "firmware missing? %s\n",
    891			MXL692_FIRMWARE);
    892		goto err;
    893	}
    894
    895	status = mxl692_fwdownload(dev, firmware->data, firmware->size);
    896	if (status)
    897		goto err_release_firmware;
    898
    899	release_firmware(firmware);
    900
    901	status = mxl692_get_versions(dev);
    902	if (status)
    903		goto err;
    904
    905	dev->power_mode = MXL_EAGLE_POWER_MODE_SLEEP;
    906warm:
    907	/* Config Device Power Mode */
    908	if (dev->power_mode != MXL_EAGLE_POWER_MODE_ACTIVE) {
    909		status = mxl692_powermode(dev, MXL_EAGLE_POWER_MODE_ACTIVE);
    910		if (status)
    911			goto err;
    912
    913		usleep_range(50 * 1000, 60 * 1000); /* was 500! */
    914	}
    915
    916	/* Init stats here to indicate which stats are supported */
    917	c->cnr.len = 1;
    918	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
    919	c->post_bit_error.len = 1;
    920	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
    921	c->post_bit_count.len = 1;
    922	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
    923	c->block_error.len = 1;
    924	c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
    925
    926	dev->init_done = 1;
    927	return 0;
    928err_release_firmware:
    929	release_firmware(firmware);
    930err:
    931	dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
    932	return status;
    933}
    934
    935static int mxl692_sleep(struct dvb_frontend *fe)
    936{
    937	struct mxl692_dev *dev = fe->demodulator_priv;
    938
    939	if (dev->power_mode != MXL_EAGLE_POWER_MODE_SLEEP)
    940		mxl692_powermode(dev, MXL_EAGLE_POWER_MODE_SLEEP);
    941
    942	return 0;
    943}
    944
    945static int mxl692_set_frontend(struct dvb_frontend *fe)
    946{
    947	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
    948	struct mxl692_dev *dev = fe->demodulator_priv;
    949
    950	int status = 0;
    951	enum MXL_EAGLE_DEMOD_TYPE_E demod_type;
    952	struct MXL_EAGLE_MPEGOUT_PARAMS_T mpeg_params = {};
    953	enum MXL_EAGLE_QAM_DEMOD_ANNEX_TYPE_E qam_annex = MXL_EAGLE_QAM_DEMOD_ANNEX_B;
    954	struct MXL_EAGLE_QAM_DEMOD_PARAMS_T qam_params = {};
    955	struct MXL_EAGLE_TUNER_CHANNEL_PARAMS_T tuner_params = {};
    956	u8 op_param = 0;
    957
    958	dev_dbg(&dev->i2c_client->dev, "\n");
    959
    960	switch (p->modulation) {
    961	case VSB_8:
    962		demod_type = MXL_EAGLE_DEMOD_TYPE_ATSC;
    963		break;
    964	case QAM_AUTO:
    965	case QAM_64:
    966	case QAM_128:
    967	case QAM_256:
    968		demod_type = MXL_EAGLE_DEMOD_TYPE_QAM;
    969		break;
    970	default:
    971		return -EINVAL;
    972	}
    973
    974	if (dev->current_frequency == p->frequency && dev->demod_type == demod_type) {
    975		dev_dbg(&dev->i2c_client->dev, "already set up\n");
    976		return 0;
    977	}
    978
    979	dev->current_frequency = -1;
    980	dev->demod_type = -1;
    981
    982	op_param = demod_type;
    983	status = mxl692_i2c_writeread(dev,
    984				      MXL_EAGLE_OPCODE_DEVICE_DEMODULATOR_TYPE_SET,
    985				      &op_param,
    986				      sizeof(u8),
    987				      NULL,
    988				      0);
    989	if (status) {
    990		dev_dbg(&dev->i2c_client->dev,
    991			"DEVICE_DEMODULATOR_TYPE_SET...FAIL  err 0x%x\n", status);
    992		goto err;
    993	}
    994
    995	usleep_range(20 * 1000, 30 * 1000); /* was 500! */
    996
    997	mpeg_params.mpeg_parallel = 0;
    998	mpeg_params.msb_first = MXL_EAGLE_DATA_SERIAL_MSB_1ST;
    999	mpeg_params.mpeg_sync_pulse_width = MXL_EAGLE_DATA_SYNC_WIDTH_BIT;
   1000	mpeg_params.mpeg_valid_pol = MXL_EAGLE_CLOCK_POSITIVE;
   1001	mpeg_params.mpeg_sync_pol = MXL_EAGLE_CLOCK_POSITIVE;
   1002	mpeg_params.mpeg_clk_pol = MXL_EAGLE_CLOCK_NEGATIVE;
   1003	mpeg_params.mpeg3wire_mode_enable = 0;
   1004	mpeg_params.mpeg_clk_freq = MXL_EAGLE_MPEG_CLOCK_27MHZ;
   1005
   1006	switch (demod_type) {
   1007	case MXL_EAGLE_DEMOD_TYPE_ATSC:
   1008		status = mxl692_i2c_writeread(dev,
   1009					      MXL_EAGLE_OPCODE_DEVICE_MPEG_OUT_PARAMS_SET,
   1010					      (u8 *)&mpeg_params,
   1011					      sizeof(struct MXL_EAGLE_MPEGOUT_PARAMS_T),
   1012					      NULL,
   1013					      0);
   1014		if (status)
   1015			goto err;
   1016		break;
   1017	case MXL_EAGLE_DEMOD_TYPE_QAM:
   1018		if (qam_annex == MXL_EAGLE_QAM_DEMOD_ANNEX_A)
   1019			mpeg_params.msb_first = MXL_EAGLE_DATA_SERIAL_LSB_1ST;
   1020		status = mxl692_i2c_writeread(dev,
   1021					      MXL_EAGLE_OPCODE_DEVICE_MPEG_OUT_PARAMS_SET,
   1022					      (u8 *)&mpeg_params,
   1023					      sizeof(struct MXL_EAGLE_MPEGOUT_PARAMS_T),
   1024					      NULL,
   1025					      0);
   1026		if (status)
   1027			goto err;
   1028
   1029		qam_params.annex_type = qam_annex;
   1030		qam_params.qam_type = MXL_EAGLE_QAM_DEMOD_AUTO;
   1031		qam_params.iq_flip = MXL_EAGLE_DEMOD_IQ_AUTO;
   1032		if (p->modulation == QAM_64)
   1033			qam_params.symbol_rate_hz = 5057000;
   1034		else
   1035			qam_params.symbol_rate_hz = 5361000;
   1036
   1037		qam_params.symbol_rate_256qam_hz = 5361000;
   1038
   1039		status = mxl692_i2c_writeread(dev,
   1040					      MXL_EAGLE_OPCODE_QAM_PARAMS_SET,
   1041					      (u8 *)&qam_params,
   1042					      sizeof(struct MXL_EAGLE_QAM_DEMOD_PARAMS_T),
   1043					      NULL, 0);
   1044		if (status)
   1045			goto err;
   1046
   1047		break;
   1048	default:
   1049		break;
   1050	}
   1051
   1052	usleep_range(20 * 1000, 30 * 1000); /* was 500! */
   1053
   1054	tuner_params.freq_hz = p->frequency;
   1055	tuner_params.bandwidth = MXL_EAGLE_TUNER_BW_6MHZ;
   1056	tuner_params.tune_mode = MXL_EAGLE_TUNER_CHANNEL_TUNE_MODE_VIEW;
   1057
   1058	dev_dbg(&dev->i2c_client->dev, " Tuning Freq: %d %s\n", tuner_params.freq_hz,
   1059		demod_type == MXL_EAGLE_DEMOD_TYPE_ATSC ? "ATSC" : "QAM");
   1060
   1061	status = mxl692_i2c_writeread(dev,
   1062				      MXL_EAGLE_OPCODE_TUNER_CHANNEL_TUNE_SET,
   1063				      (u8 *)&tuner_params,
   1064				      sizeof(struct MXL_EAGLE_TUNER_CHANNEL_PARAMS_T),
   1065				      NULL,
   1066				      0);
   1067	if (status)
   1068		goto err;
   1069
   1070	usleep_range(20 * 1000, 30 * 1000); /* was 500! */
   1071
   1072	switch (demod_type) {
   1073	case MXL_EAGLE_DEMOD_TYPE_ATSC:
   1074		status = mxl692_i2c_writeread(dev,
   1075					      MXL_EAGLE_OPCODE_ATSC_INIT_SET,
   1076					      NULL, 0, NULL, 0);
   1077		if (status)
   1078			goto err;
   1079		break;
   1080	case MXL_EAGLE_DEMOD_TYPE_QAM:
   1081		status = mxl692_i2c_writeread(dev,
   1082					      MXL_EAGLE_OPCODE_QAM_RESTART_SET,
   1083					      NULL, 0, NULL, 0);
   1084		if (status)
   1085			goto err;
   1086		break;
   1087	default:
   1088		break;
   1089	}
   1090
   1091	dev->demod_type = demod_type;
   1092	dev->current_frequency = p->frequency;
   1093
   1094	return 0;
   1095err:
   1096	dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
   1097	return status;
   1098}
   1099
   1100static int mxl692_get_frontend(struct dvb_frontend *fe,
   1101			       struct dtv_frontend_properties *p)
   1102{
   1103	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
   1104
   1105	p->modulation = c->modulation;
   1106	p->frequency = c->frequency;
   1107
   1108	return 0;
   1109}
   1110
   1111static int mxl692_read_snr(struct dvb_frontend *fe, u16 *snr)
   1112{
   1113	struct mxl692_dev *dev = fe->demodulator_priv;
   1114	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
   1115	u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
   1116	struct MXL_EAGLE_ATSC_DEMOD_STATUS_T *atsc_status;
   1117	struct MXL_EAGLE_QAM_DEMOD_STATUS_T *qam_status;
   1118	enum MXL_EAGLE_DEMOD_TYPE_E demod_type = dev->demod_type;
   1119	int mxl_status = 0;
   1120
   1121	*snr = 0;
   1122
   1123	dev_dbg(&dev->i2c_client->dev, "\n");
   1124
   1125	atsc_status = (struct MXL_EAGLE_ATSC_DEMOD_STATUS_T *)&rx_buf;
   1126	qam_status = (struct MXL_EAGLE_QAM_DEMOD_STATUS_T *)&rx_buf;
   1127
   1128	switch (demod_type) {
   1129	case MXL_EAGLE_DEMOD_TYPE_ATSC:
   1130		mxl_status = mxl692_i2c_writeread(dev,
   1131						  MXL_EAGLE_OPCODE_ATSC_STATUS_GET,
   1132						  NULL,
   1133						  0,
   1134						  rx_buf,
   1135						  sizeof(struct MXL_EAGLE_ATSC_DEMOD_STATUS_T));
   1136		if (!mxl_status) {
   1137			*snr = (u16)(atsc_status->snr_db_tenths / 10);
   1138			c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
   1139			c->cnr.stat[0].svalue = *snr;
   1140		}
   1141		break;
   1142	case MXL_EAGLE_DEMOD_TYPE_QAM:
   1143		mxl_status = mxl692_i2c_writeread(dev,
   1144						  MXL_EAGLE_OPCODE_QAM_STATUS_GET,
   1145						  NULL,
   1146						  0,
   1147						  rx_buf,
   1148						  sizeof(struct MXL_EAGLE_QAM_DEMOD_STATUS_T));
   1149		if (!mxl_status)
   1150			*snr = (u16)(qam_status->snr_db_tenths / 10);
   1151		break;
   1152	case MXL_EAGLE_DEMOD_TYPE_OOB:
   1153	default:
   1154		break;
   1155	}
   1156
   1157	if (mxl_status)
   1158		dev_dbg(&dev->i2c_client->dev, "err %d\n", mxl_status);
   1159	return mxl_status;
   1160}
   1161
   1162static int mxl692_read_ber_ucb(struct dvb_frontend *fe)
   1163{
   1164	struct mxl692_dev *dev = fe->demodulator_priv;
   1165	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
   1166	u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
   1167	struct MXL_EAGLE_ATSC_DEMOD_ERROR_COUNTERS_T *atsc_errors;
   1168	enum MXL_EAGLE_DEMOD_TYPE_E demod_type = dev->demod_type;
   1169	int mxl_status = 0;
   1170	u32 utmp;
   1171
   1172	dev_dbg(&dev->i2c_client->dev, "\n");
   1173
   1174	atsc_errors = (struct MXL_EAGLE_ATSC_DEMOD_ERROR_COUNTERS_T *)&rx_buf;
   1175
   1176	switch (demod_type) {
   1177	case MXL_EAGLE_DEMOD_TYPE_ATSC:
   1178		mxl_status = mxl692_i2c_writeread(dev,
   1179						  MXL_EAGLE_OPCODE_ATSC_ERROR_COUNTERS_GET,
   1180						  NULL,
   1181						  0,
   1182						  rx_buf,
   1183						  sizeof(struct MXL_EAGLE_ATSC_DEMOD_ERROR_COUNTERS_T));
   1184		if (!mxl_status) {
   1185			if (atsc_errors->error_packets == 0)
   1186				utmp = 0;
   1187			else
   1188				utmp = ((atsc_errors->error_bytes / atsc_errors->error_packets) *
   1189					atsc_errors->total_packets);
   1190			/* ber */
   1191			c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
   1192			c->post_bit_error.stat[0].uvalue += atsc_errors->error_bytes;
   1193			c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
   1194			c->post_bit_count.stat[0].uvalue += utmp;
   1195			/* ucb */
   1196			c->block_error.stat[0].scale = FE_SCALE_COUNTER;
   1197			c->block_error.stat[0].uvalue += atsc_errors->error_packets;
   1198
   1199			dev_dbg(&dev->i2c_client->dev, "%llu   %llu\n",
   1200				c->post_bit_count.stat[0].uvalue, c->block_error.stat[0].uvalue);
   1201		}
   1202		break;
   1203	case MXL_EAGLE_DEMOD_TYPE_QAM:
   1204	case MXL_EAGLE_DEMOD_TYPE_OOB:
   1205	default:
   1206		break;
   1207	}
   1208
   1209	if (mxl_status)
   1210		dev_dbg(&dev->i2c_client->dev, "err %d\n", mxl_status);
   1211
   1212	return mxl_status;
   1213}
   1214
   1215static int mxl692_read_status(struct dvb_frontend *fe,
   1216			      enum fe_status *status)
   1217{
   1218	struct mxl692_dev *dev = fe->demodulator_priv;
   1219	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
   1220	u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
   1221	struct MXL_EAGLE_ATSC_DEMOD_STATUS_T *atsc_status;
   1222	struct MXL_EAGLE_QAM_DEMOD_STATUS_T *qam_status;
   1223	enum MXL_EAGLE_DEMOD_TYPE_E demod_type = dev->demod_type;
   1224	int mxl_status = 0;
   1225	*status = 0;
   1226
   1227	dev_dbg(&dev->i2c_client->dev, "\n");
   1228
   1229	atsc_status = (struct MXL_EAGLE_ATSC_DEMOD_STATUS_T *)&rx_buf;
   1230	qam_status = (struct MXL_EAGLE_QAM_DEMOD_STATUS_T *)&rx_buf;
   1231
   1232	switch (demod_type) {
   1233	case MXL_EAGLE_DEMOD_TYPE_ATSC:
   1234		mxl_status = mxl692_i2c_writeread(dev,
   1235						  MXL_EAGLE_OPCODE_ATSC_STATUS_GET,
   1236						  NULL,
   1237						  0,
   1238						  rx_buf,
   1239						  sizeof(struct MXL_EAGLE_ATSC_DEMOD_STATUS_T));
   1240		if (!mxl_status && atsc_status->atsc_lock) {
   1241			*status |= FE_HAS_SIGNAL;
   1242			*status |= FE_HAS_CARRIER;
   1243			*status |= FE_HAS_VITERBI;
   1244			*status |= FE_HAS_SYNC;
   1245			*status |= FE_HAS_LOCK;
   1246
   1247			c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
   1248			c->cnr.stat[0].svalue = atsc_status->snr_db_tenths / 10;
   1249		}
   1250		break;
   1251	case MXL_EAGLE_DEMOD_TYPE_QAM:
   1252		mxl_status = mxl692_i2c_writeread(dev,
   1253						  MXL_EAGLE_OPCODE_QAM_STATUS_GET,
   1254						  NULL,
   1255						  0,
   1256						  rx_buf,
   1257						  sizeof(struct MXL_EAGLE_QAM_DEMOD_STATUS_T));
   1258		if (!mxl_status && qam_status->qam_locked) {
   1259			*status |= FE_HAS_SIGNAL;
   1260			*status |= FE_HAS_CARRIER;
   1261			*status |= FE_HAS_VITERBI;
   1262			*status |= FE_HAS_SYNC;
   1263			*status |= FE_HAS_LOCK;
   1264
   1265			c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
   1266			c->cnr.stat[0].svalue = qam_status->snr_db_tenths / 10;
   1267		}
   1268		break;
   1269	case MXL_EAGLE_DEMOD_TYPE_OOB:
   1270	default:
   1271		break;
   1272	}
   1273
   1274	if ((*status & FE_HAS_LOCK) == 0) {
   1275		/* No lock, reset all statistics */
   1276		c->cnr.len = 1;
   1277		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
   1278		c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
   1279		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
   1280		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
   1281		return 0;
   1282	}
   1283
   1284	if (mxl_status)
   1285		dev_dbg(&dev->i2c_client->dev, "err %d\n", mxl_status);
   1286	else
   1287		mxl_status = mxl692_read_ber_ucb(fe);
   1288
   1289	return mxl_status;
   1290}
   1291
   1292static const struct dvb_frontend_ops mxl692_ops = {
   1293	.delsys = { SYS_ATSC },
   1294	.info = {
   1295		.name = "MaxLinear MxL692 VSB tuner-demodulator",
   1296		.frequency_min_hz      = 54000000,
   1297		.frequency_max_hz      = 858000000,
   1298		.frequency_stepsize_hz = 62500,
   1299		.caps = FE_CAN_8VSB
   1300	},
   1301
   1302	.init         = mxl692_init,
   1303	.sleep        = mxl692_sleep,
   1304	.set_frontend = mxl692_set_frontend,
   1305	.get_frontend = mxl692_get_frontend,
   1306
   1307	.read_status          = mxl692_read_status,
   1308	.read_snr             = mxl692_read_snr,
   1309};
   1310
   1311static int mxl692_probe(struct i2c_client *client,
   1312			const struct i2c_device_id *id)
   1313{
   1314	struct mxl692_config *config = client->dev.platform_data;
   1315	struct mxl692_dev *dev;
   1316	int ret = 0;
   1317
   1318	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
   1319	if (!dev) {
   1320		ret = -ENOMEM;
   1321		dev_dbg(&client->dev, "kzalloc() failed\n");
   1322		goto err;
   1323	}
   1324
   1325	memcpy(&dev->fe.ops, &mxl692_ops, sizeof(struct dvb_frontend_ops));
   1326	dev->fe.demodulator_priv = dev;
   1327	dev->i2c_client = client;
   1328	*config->fe = &dev->fe;
   1329	mutex_init(&dev->i2c_lock);
   1330	i2c_set_clientdata(client, dev);
   1331
   1332	dev_info(&client->dev, "MaxLinear mxl692 successfully attached\n");
   1333
   1334	return 0;
   1335err:
   1336	dev_dbg(&client->dev, "failed %d\n", ret);
   1337	return -ENODEV;
   1338}
   1339
   1340static int mxl692_remove(struct i2c_client *client)
   1341{
   1342	struct mxl692_dev *dev = i2c_get_clientdata(client);
   1343
   1344	dev->fe.demodulator_priv = NULL;
   1345	i2c_set_clientdata(client, NULL);
   1346	kfree(dev);
   1347
   1348	return 0;
   1349}
   1350
   1351static const struct i2c_device_id mxl692_id_table[] = {
   1352	{"mxl692", 0},
   1353	{}
   1354};
   1355MODULE_DEVICE_TABLE(i2c, mxl692_id_table);
   1356
   1357static struct i2c_driver mxl692_driver = {
   1358	.driver = {
   1359		.name	= "mxl692",
   1360	},
   1361	.probe		= mxl692_probe,
   1362	.remove		= mxl692_remove,
   1363	.id_table	= mxl692_id_table,
   1364};
   1365
   1366module_i2c_driver(mxl692_driver);
   1367
   1368MODULE_AUTHOR("Brad Love <brad@nextdimension.cc>");
   1369MODULE_DESCRIPTION("MaxLinear MxL692 demodulator/tuner driver");
   1370MODULE_FIRMWARE(MXL692_FIRMWARE);
   1371MODULE_LICENSE("GPL");