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(adap: dev->i2c_client->adapter, msgs: &msg, num: 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(adap: dev->i2c_client->adapter, msgs: &msg, num: 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: 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(size: sizeof(u32), d: buffer);
123 break;
124 case MXL_EAGLE_OPCODE_QAM_PARAMS_SET:
125 buffer += 5;
126 buffer += convert_endian(size: 2 * sizeof(u32), d: 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(size: 2 * sizeof(u16), d: buffer);
146 break;
147 case MXL_EAGLE_OPCODE_ATSC_STATUS_GET:
148 buffer += convert_endian_n(n: 2, size: sizeof(u16), d: buffer);
149 buffer += convert_endian(size: sizeof(u32), d: buffer);
150 break;
151 case MXL_EAGLE_OPCODE_ATSC_ERROR_COUNTERS_GET:
152 buffer += convert_endian(size: 3 * sizeof(u32), d: buffer);
153 break;
154 case MXL_EAGLE_OPCODE_ATSC_EQUALIZER_FILTER_FFE_TAPS_GET:
155 buffer += convert_endian_n(n: 24, size: sizeof(u16), d: buffer);
156 break;
157 case MXL_EAGLE_OPCODE_QAM_STATUS_GET:
158 buffer += 8;
159 buffer += convert_endian_n(n: 2, size: sizeof(u16), d: buffer);
160 buffer += convert_endian(size: sizeof(u32), d: buffer);
161 break;
162 case MXL_EAGLE_OPCODE_QAM_ERROR_COUNTERS_GET:
163 buffer += convert_endian(size: 7 * sizeof(u32), d: 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(n: 24, size: sizeof(u16), d: buffer);
171 break;
172 case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_SPUR_END_GET:
173 buffer += convert_endian_n(n: 8, size: sizeof(u16), d: buffer);
174 break;
175 case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_FFE_GET:
176 buffer += convert_endian_n(n: 17, size: sizeof(u16), d: buffer);
177 break;
178 case MXL_EAGLE_OPCODE_OOB_ERROR_COUNTERS_GET:
179 buffer += convert_endian(size: 3 * sizeof(u32), d: buffer);
180 break;
181 case MXL_EAGLE_OPCODE_OOB_STATUS_GET:
182 buffer += convert_endian_n(n: 2, size: sizeof(u16), d: buffer);
183 buffer += convert_endian(size: sizeof(u32), d: buffer);
184 break;
185 case MXL_EAGLE_OPCODE_SMA_RECEIVE_GET:
186 buffer += convert_endian(size: sizeof(u32), d: 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(p: buffer, q: fw_hdr, size: 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(size: chunk_len, d: plocal_buf);
279 if (mxl692_i2c_write(dev, buffer: local_buf,
280 buf_len: (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, buffer: local_buf,
325 buf_len: (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, buffer: local_buf, MXL_EAGLE_I2C_MHEADER_SIZE) > 0) {
353 size = (size + 3) & ~3; /* 4 byte alignment */
354 status = mxl692_i2c_read(dev, buffer, buf_len: (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(lock: &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(size: total_len, d: plocal_buf);
399
400 if (mxl692_i2c_write(dev, buffer: local_buf,
401 buf_len: (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, buffer: 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: buffer + ix, buf_len: 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, d: 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, buffer: tx_buf);
478
479 tx_header->checksum = 0;
480 tx_header->checksum = mxl692_checksum(buffer: tx_buf,
481 MXL_EAGLE_HOST_MSG_HEADER_SIZE + tx_payload_size);
482#ifdef __LITTLE_ENDIAN
483 convert_endian(size: 4, d: (u8 *)&tx_header->checksum); /* cksum is big endian */
484#endif
485 /* send Tx message */
486 status = mxl692_opwrite(dev, buffer: tx_buf,
487 size: 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, buffer: rx_buf,
498 size: rx_payload_expected + MXL_EAGLE_HOST_MSG_HEADER_SIZE);
499 usleep_range(min: 1000, max: 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(buffer: rx_buf,
537 MXL_EAGLE_HOST_MSG_HEADER_SIZE + rx_header->payload_size);
538#ifdef __LITTLE_ENDIAN
539 convert_endian(size: 4, d: (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(opcode: rx_header->opcode, buffer: 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(lock: &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, buffer: firmware_buf, buf_len);
583 if (status)
584 goto err_finish;
585
586 ix = 16;
587 status = mxl692_write_fw_block(dev, buffer: firmware_buf, buf_len, index: &ix); /* DRAM */
588 if (status)
589 goto err_finish;
590
591 status = mxl692_write_fw_block(dev, buffer: firmware_buf, buf_len, index: &ix); /* IRAM */
592 if (status)
593 goto err_finish;
594
595 /* release CPU from reset */
596 status = mxl692_memwrite(dev, addr: 0x70000018, buffer: (u8 *)&reg_val, size: sizeof(u32));
597 if (status)
598 goto err_finish;
599
600 mutex_unlock(lock: &dev->i2c_lock);
601
602 if (status == 0) {
603 /* verify FW is alive */
604 usleep_range(MXL_EAGLE_FW_LOAD_TIME * 1000, max: (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 opcode: MXL_EAGLE_OPCODE_DEVICE_STATUS_GET,
608 NULL,
609 tx_payload_size: 0,
610 rx_payload: (u8 *)dev_status,
611 rx_payload_expected: sizeof(struct MXL_EAGLE_DEV_STATUS_T));
612 }
613
614 return status;
615err_finish:
616 mutex_unlock(lock: &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, opcode: MXL_EAGLE_OPCODE_DEVICE_VERSION_GET,
629 NULL,
630 tx_payload_size: 0,
631 rx_payload: (u8 *)&dev_ver,
632 rx_payload_expected: 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, addr: 0x80000100, buffer: (u8 *)&reg_val, size: sizeof(u32));
659 if (status)
660 goto err_finish;
661
662 /* verify sku */
663 status = mxl692_memread(dev, addr: 0x70000188, buffer: (u8 *)&dev_type, size: 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, addr: 0x90000000, buffer: (u8 *)&reg_val, size: 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, addr: 0x90000000, buffer: (u8 *)&reg_val, size: sizeof(u32));
694 if (status)
695 goto err_finish;
696
697 /* configure digital regulator to high current mode */
698 status = mxl692_memread(dev, addr: 0x90000018, buffer: (u8 *)&reg_val, size: sizeof(u32));
699 if (status)
700 goto err_finish;
701
702 reg_val |= 0x800;
703
704 status = mxl692_memwrite(dev, addr: 0x90000018, buffer: (u8 *)&reg_val, size: 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, addr: 0x90000000, buffer: (u8 *)&reg_val, size: 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, addr: 0x90000000, buffer: (u8 *)&reg_val, size: 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, addr: 0x90000000, buffer: (u8 *)&reg_val, size: 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, addr: 0x90000000, buffer: (u8 *)&reg_val, size: 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, addr: 0x90000030, buffer: (u8 *)&reg_val1, size: 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, addr: 0x90000030, buffer: (u8 *)&reg_val1, size: 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, addr: 0x90000030, buffer: (u8 *)&reg_val1, size: sizeof(u32));
767 if (status)
768 goto err_finish;
769
770 /* set XTAL bias value */
771 status = mxl692_memread(dev, addr: 0x9000002c, buffer: (u8 *)&reg_val, size: sizeof(u32));
772 if (status)
773 goto err_finish;
774
775 reg_val &= 0xC0FFFFFF;
776 reg_val |= 0xA000000;
777
778 status = mxl692_memwrite(dev, addr: 0x9000002c, buffer: (u8 *)&reg_val, size: sizeof(u32));
779 if (status)
780 goto err_finish;
781 }
782
783 /* start XTAL calibration */
784 status = mxl692_memread(dev, addr: 0x70000010, buffer: (u8 *)&reg_val, size: sizeof(u32));
785 if (status)
786 goto err_finish;
787
788 reg_val |= 0x8;
789
790 status = mxl692_memwrite(dev, addr: 0x70000010, buffer: (u8 *)&reg_val, size: sizeof(u32));
791 if (status)
792 goto err_finish;
793
794 status = mxl692_memread(dev, addr: 0x70000018, buffer: (u8 *)&reg_val, size: sizeof(u32));
795 if (status)
796 goto err_finish;
797
798 reg_val |= 0x10;
799
800 status = mxl692_memwrite(dev, addr: 0x70000018, buffer: (u8 *)&reg_val, size: sizeof(u32));
801 if (status)
802 goto err_finish;
803
804 status = mxl692_memread(dev, addr: 0x9001014c, buffer: (u8 *)&reg_val, size: sizeof(u32));
805 if (status)
806 goto err_finish;
807
808 reg_val &= 0xFFFFEFFF;
809
810 status = mxl692_memwrite(dev, addr: 0x9001014c, buffer: (u8 *)&reg_val, size: sizeof(u32));
811 if (status)
812 goto err_finish;
813
814 reg_val |= 0x1000;
815
816 status = mxl692_memwrite(dev, addr: 0x9001014c, buffer: (u8 *)&reg_val, size: sizeof(u32));
817 if (status)
818 goto err_finish;
819
820 usleep_range(min: 45000, max: 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 opcode: MXL_EAGLE_OPCODE_DEVICE_POWERMODE_SET,
839 tx_payload: &mode,
840 tx_payload_size: sizeof(u8),
841 NULL,
842 rx_payload_expected: 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(min: 50 * 1000, max: 60 * 1000); /* was 1000! */
874
875 status = mxl692_config_regulators(dev, power_supply: 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, dev_xtal: &xtal_config);
885 if (status)
886 goto err;
887
888 status = request_firmware(fw: &firmware, MXL692_FIRMWARE, device: &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_buf: firmware->data, buf_len: firmware->size);
896 if (status)
897 goto err_release_firmware;
898
899 release_firmware(fw: 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, power_mode: MXL_EAGLE_POWER_MODE_ACTIVE);
910 if (status)
911 goto err;
912
913 usleep_range(min: 50 * 1000, max: 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(fw: 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, power_mode: 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 opcode: MXL_EAGLE_OPCODE_DEVICE_DEMODULATOR_TYPE_SET,
985 tx_payload: &op_param,
986 tx_payload_size: sizeof(u8),
987 NULL,
988 rx_payload_expected: 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(min: 20 * 1000, max: 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 opcode: MXL_EAGLE_OPCODE_DEVICE_MPEG_OUT_PARAMS_SET,
1010 tx_payload: (u8 *)&mpeg_params,
1011 tx_payload_size: sizeof(struct MXL_EAGLE_MPEGOUT_PARAMS_T),
1012 NULL,
1013 rx_payload_expected: 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 opcode: MXL_EAGLE_OPCODE_DEVICE_MPEG_OUT_PARAMS_SET,
1022 tx_payload: (u8 *)&mpeg_params,
1023 tx_payload_size: sizeof(struct MXL_EAGLE_MPEGOUT_PARAMS_T),
1024 NULL,
1025 rx_payload_expected: 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 opcode: MXL_EAGLE_OPCODE_QAM_PARAMS_SET,
1041 tx_payload: (u8 *)&qam_params,
1042 tx_payload_size: sizeof(struct MXL_EAGLE_QAM_DEMOD_PARAMS_T),
1043 NULL, rx_payload_expected: 0);
1044 if (status)
1045 goto err;
1046
1047 break;
1048 default:
1049 break;
1050 }
1051
1052 usleep_range(min: 20 * 1000, max: 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 opcode: MXL_EAGLE_OPCODE_TUNER_CHANNEL_TUNE_SET,
1063 tx_payload: (u8 *)&tuner_params,
1064 tx_payload_size: sizeof(struct MXL_EAGLE_TUNER_CHANNEL_PARAMS_T),
1065 NULL,
1066 rx_payload_expected: 0);
1067 if (status)
1068 goto err;
1069
1070 usleep_range(min: 20 * 1000, max: 30 * 1000); /* was 500! */
1071
1072 switch (demod_type) {
1073 case MXL_EAGLE_DEMOD_TYPE_ATSC:
1074 status = mxl692_i2c_writeread(dev,
1075 opcode: MXL_EAGLE_OPCODE_ATSC_INIT_SET,
1076 NULL, tx_payload_size: 0, NULL, rx_payload_expected: 0);
1077 if (status)
1078 goto err;
1079 break;
1080 case MXL_EAGLE_DEMOD_TYPE_QAM:
1081 status = mxl692_i2c_writeread(dev,
1082 opcode: MXL_EAGLE_OPCODE_QAM_RESTART_SET,
1083 NULL, tx_payload_size: 0, NULL, rx_payload_expected: 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 opcode: MXL_EAGLE_OPCODE_ATSC_STATUS_GET,
1132 NULL,
1133 tx_payload_size: 0,
1134 rx_payload: rx_buf,
1135 rx_payload_expected: 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 opcode: MXL_EAGLE_OPCODE_QAM_STATUS_GET,
1145 NULL,
1146 tx_payload_size: 0,
1147 rx_payload: rx_buf,
1148 rx_payload_expected: 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 opcode: MXL_EAGLE_OPCODE_ATSC_ERROR_COUNTERS_GET,
1180 NULL,
1181 tx_payload_size: 0,
1182 rx_payload: rx_buf,
1183 rx_payload_expected: 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 opcode: MXL_EAGLE_OPCODE_ATSC_STATUS_GET,
1236 NULL,
1237 tx_payload_size: 0,
1238 rx_payload: rx_buf,
1239 rx_payload_expected: 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 opcode: MXL_EAGLE_OPCODE_QAM_STATUS_GET,
1254 NULL,
1255 tx_payload_size: 0,
1256 rx_payload: rx_buf,
1257 rx_payload_expected: 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(size: 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, data: 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(objp: 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

source code of linux/drivers/media/dvb-frontends/mxl692.c