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{
1313	struct mxl692_config *config = client->dev.platform_data;
1314	struct mxl692_dev *dev;
1315	int ret = 0;
1316
1317	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1318	if (!dev) {
1319		ret = -ENOMEM;
1320		dev_dbg(&client->dev, "kzalloc() failed\n");
1321		goto err;
1322	}
1323
1324	memcpy(&dev->fe.ops, &mxl692_ops, sizeof(struct dvb_frontend_ops));
1325	dev->fe.demodulator_priv = dev;
1326	dev->i2c_client = client;
1327	*config->fe = &dev->fe;
1328	mutex_init(&dev->i2c_lock);
1329	i2c_set_clientdata(client, dev);
1330
1331	dev_info(&client->dev, "MaxLinear mxl692 successfully attached\n");
1332
1333	return 0;
1334err:
1335	dev_dbg(&client->dev, "failed %d\n", ret);
1336	return -ENODEV;
1337}
1338
1339static void mxl692_remove(struct i2c_client *client)
1340{
1341	struct mxl692_dev *dev = i2c_get_clientdata(client);
1342
1343	dev->fe.demodulator_priv = NULL;
1344	i2c_set_clientdata(client, NULL);
1345	kfree(dev);
1346}
1347
1348static const struct i2c_device_id mxl692_id_table[] = {
1349	{"mxl692", 0},
1350	{}
1351};
1352MODULE_DEVICE_TABLE(i2c, mxl692_id_table);
1353
1354static struct i2c_driver mxl692_driver = {
1355	.driver = {
1356		.name	= "mxl692",
1357	},
1358	.probe		= mxl692_probe,
1359	.remove		= mxl692_remove,
1360	.id_table	= mxl692_id_table,
1361};
1362
1363module_i2c_driver(mxl692_driver);
1364
1365MODULE_AUTHOR("Brad Love <brad@nextdimension.cc>");
1366MODULE_DESCRIPTION("MaxLinear MxL692 demodulator/tuner driver");
1367MODULE_FIRMWARE(MXL692_FIRMWARE);
1368MODULE_LICENSE("GPL");
1369