Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Driver for the MaxLinear MxL69x family of combo tuners/demods
0004  *
0005  * Copyright (C) 2020 Brad Love <brad@nextdimension.cc>
0006  *
0007  * based on code:
0008  * Copyright (c) 2016 MaxLinear, Inc. All rights reserved
0009  * which was released under GPL V2
0010  */
0011 
0012 #include <linux/mutex.h>
0013 #include <linux/i2c-mux.h>
0014 #include <linux/string.h>
0015 #include <linux/firmware.h>
0016 
0017 #include "mxl692.h"
0018 #include "mxl692_defs.h"
0019 
0020 static const struct dvb_frontend_ops mxl692_ops;
0021 
0022 struct mxl692_dev {
0023     struct dvb_frontend fe;
0024     struct i2c_client *i2c_client;
0025     struct mutex i2c_lock;      /* i2c command mutex */
0026     enum MXL_EAGLE_DEMOD_TYPE_E demod_type;
0027     enum MXL_EAGLE_POWER_MODE_E power_mode;
0028     u32 current_frequency;
0029     int device_type;
0030     int seqnum;
0031     int init_done;
0032 };
0033 
0034 static int mxl692_i2c_write(struct mxl692_dev *dev, u8 *buffer, u16 buf_len)
0035 {
0036     int ret = 0;
0037     struct i2c_msg msg = {
0038         .addr = dev->i2c_client->addr,
0039         .flags = 0,
0040         .buf = buffer,
0041         .len = buf_len
0042     };
0043 
0044     ret = i2c_transfer(dev->i2c_client->adapter, &msg, 1);
0045     if (ret != 1)
0046         dev_dbg(&dev->i2c_client->dev, "i2c write error!\n");
0047 
0048     return ret;
0049 }
0050 
0051 static int mxl692_i2c_read(struct mxl692_dev *dev, u8 *buffer, u16 buf_len)
0052 {
0053     int ret = 0;
0054     struct i2c_msg msg = {
0055         .addr = dev->i2c_client->addr,
0056         .flags = I2C_M_RD,
0057         .buf = buffer,
0058         .len = buf_len
0059     };
0060 
0061     ret = i2c_transfer(dev->i2c_client->adapter, &msg, 1);
0062     if (ret != 1)
0063         dev_dbg(&dev->i2c_client->dev, "i2c read error!\n");
0064 
0065     return ret;
0066 }
0067 
0068 static int convert_endian(u32 size, u8 *d)
0069 {
0070     u32 i;
0071 
0072     for (i = 0; i < (size & ~3); i += 4) {
0073         d[i + 0] ^= d[i + 3];
0074         d[i + 3] ^= d[i + 0];
0075         d[i + 0] ^= d[i + 3];
0076 
0077         d[i + 1] ^= d[i + 2];
0078         d[i + 2] ^= d[i + 1];
0079         d[i + 1] ^= d[i + 2];
0080     }
0081 
0082     switch (size & 3) {
0083     case 0:
0084     case 1:
0085         /* do nothing */
0086         break;
0087     case 2:
0088         d[i + 0] ^= d[i + 1];
0089         d[i + 1] ^= d[i + 0];
0090         d[i + 0] ^= d[i + 1];
0091         break;
0092 
0093     case 3:
0094         d[i + 0] ^= d[i + 2];
0095         d[i + 2] ^= d[i + 0];
0096         d[i + 0] ^= d[i + 2];
0097         break;
0098     }
0099     return size;
0100 }
0101 
0102 static int convert_endian_n(int n, u32 size, u8 *d)
0103 {
0104     int i, count = 0;
0105 
0106     for (i = 0; i < n; i += size)
0107         count += convert_endian(size, d + i);
0108     return count;
0109 }
0110 
0111 static void mxl692_tx_swap(enum MXL_EAGLE_OPCODE_E opcode, u8 *buffer)
0112 {
0113 #ifdef __BIG_ENDIAN
0114     return;
0115 #endif
0116     buffer += MXL_EAGLE_HOST_MSG_HEADER_SIZE; /* skip API header */
0117 
0118     switch (opcode) {
0119     case MXL_EAGLE_OPCODE_DEVICE_INTR_MASK_SET:
0120     case MXL_EAGLE_OPCODE_TUNER_CHANNEL_TUNE_SET:
0121     case MXL_EAGLE_OPCODE_SMA_TRANSMIT_SET:
0122         buffer += convert_endian(sizeof(u32), buffer);
0123         break;
0124     case MXL_EAGLE_OPCODE_QAM_PARAMS_SET:
0125         buffer += 5;
0126         buffer += convert_endian(2 * sizeof(u32), buffer);
0127         break;
0128     default:
0129         /* no swapping - all get opcodes */
0130         /* ATSC/OOB no swapping */
0131         break;
0132     }
0133 }
0134 
0135 static void mxl692_rx_swap(enum MXL_EAGLE_OPCODE_E opcode, u8 *buffer)
0136 {
0137 #ifdef __BIG_ENDIAN
0138     return;
0139 #endif
0140     buffer += MXL_EAGLE_HOST_MSG_HEADER_SIZE; /* skip API header */
0141 
0142     switch (opcode) {
0143     case MXL_EAGLE_OPCODE_TUNER_AGC_STATUS_GET:
0144         buffer++;
0145         buffer += convert_endian(2 * sizeof(u16), buffer);
0146         break;
0147     case MXL_EAGLE_OPCODE_ATSC_STATUS_GET:
0148         buffer += convert_endian_n(2, sizeof(u16), buffer);
0149         buffer += convert_endian(sizeof(u32), buffer);
0150         break;
0151     case MXL_EAGLE_OPCODE_ATSC_ERROR_COUNTERS_GET:
0152         buffer += convert_endian(3 * sizeof(u32), buffer);
0153         break;
0154     case MXL_EAGLE_OPCODE_ATSC_EQUALIZER_FILTER_FFE_TAPS_GET:
0155         buffer += convert_endian_n(24, sizeof(u16), buffer);
0156         break;
0157     case MXL_EAGLE_OPCODE_QAM_STATUS_GET:
0158         buffer += 8;
0159         buffer += convert_endian_n(2, sizeof(u16), buffer);
0160         buffer += convert_endian(sizeof(u32), buffer);
0161         break;
0162     case MXL_EAGLE_OPCODE_QAM_ERROR_COUNTERS_GET:
0163         buffer += convert_endian(7 * sizeof(u32), buffer);
0164         break;
0165     case MXL_EAGLE_OPCODE_QAM_CONSTELLATION_VALUE_GET:
0166     case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_START_GET:
0167     case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_MIDDLE_GET:
0168     case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_END_GET:
0169     case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_SPUR_START_GET:
0170         buffer += convert_endian_n(24, sizeof(u16), buffer);
0171         break;
0172     case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_SPUR_END_GET:
0173         buffer += convert_endian_n(8, sizeof(u16), buffer);
0174         break;
0175     case MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_FFE_GET:
0176         buffer += convert_endian_n(17, sizeof(u16), buffer);
0177         break;
0178     case MXL_EAGLE_OPCODE_OOB_ERROR_COUNTERS_GET:
0179         buffer += convert_endian(3 * sizeof(u32), buffer);
0180         break;
0181     case MXL_EAGLE_OPCODE_OOB_STATUS_GET:
0182         buffer += convert_endian_n(2, sizeof(u16), buffer);
0183         buffer += convert_endian(sizeof(u32), buffer);
0184         break;
0185     case MXL_EAGLE_OPCODE_SMA_RECEIVE_GET:
0186         buffer += convert_endian(sizeof(u32), buffer);
0187         break;
0188     default:
0189         /* no swapping - all set opcodes */
0190         break;
0191     }
0192 }
0193 
0194 static u32 mxl692_checksum(u8 *buffer, u32 size)
0195 {
0196     u32 ix, div_size;
0197     u32 cur_cksum = 0;
0198     __be32 *buf;
0199 
0200     div_size = DIV_ROUND_UP(size, 4);
0201 
0202     buf = (__be32 *)buffer;
0203     for (ix = 0; ix < div_size; ix++)
0204         cur_cksum += be32_to_cpu(buf[ix]);
0205 
0206     cur_cksum ^= 0xDEADBEEF;
0207 
0208     return cur_cksum;
0209 }
0210 
0211 static int mxl692_validate_fw_header(struct mxl692_dev *dev,
0212                      const u8 *buffer, u32 buf_len)
0213 {
0214     int status = 0;
0215     u32 ix, temp;
0216     __be32 *local_buf = NULL;
0217     u8 temp_cksum = 0;
0218     static const u8 fw_hdr[] = {
0219         0x4D, 0x31, 0x10, 0x02, 0x40, 0x00, 0x00, 0x80
0220     };
0221 
0222     if (memcmp(buffer, fw_hdr, 8) != 0) {
0223         status = -EINVAL;
0224         goto err_finish;
0225     }
0226 
0227     local_buf = (__be32 *)(buffer + 8);
0228     temp = be32_to_cpu(*local_buf);
0229 
0230     if ((buf_len - 16) != temp >> 8) {
0231         status = -EINVAL;
0232         goto err_finish;
0233     }
0234 
0235     for (ix = 16; ix < buf_len; ix++)
0236         temp_cksum += buffer[ix];
0237 
0238     if (temp_cksum != buffer[11])
0239         status = -EINVAL;
0240 
0241 err_finish:
0242     if (status)
0243         dev_dbg(&dev->i2c_client->dev, "failed\n");
0244     return status;
0245 }
0246 
0247 static int mxl692_write_fw_block(struct mxl692_dev *dev, const u8 *buffer,
0248                  u32 buf_len, u32 *index)
0249 {
0250     int status = 0;
0251     u32 ix = 0, total_len = 0, addr = 0, chunk_len = 0, prevchunk_len = 0;
0252     u8 local_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {}, *plocal_buf = NULL;
0253     int payload_max = MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_MHEADER_SIZE;
0254 
0255     ix = *index;
0256 
0257     if (buffer[ix] == 0x53) {
0258         total_len = buffer[ix + 1] << 16 | buffer[ix + 2] << 8 | buffer[ix + 3];
0259         total_len = (total_len + 3) & ~3;
0260         addr      = buffer[ix + 4] << 24 | buffer[ix + 5] << 16 |
0261                 buffer[ix + 6] << 8 | buffer[ix + 7];
0262         ix       += MXL_EAGLE_FW_SEGMENT_HEADER_SIZE;
0263 
0264         while ((total_len > 0) && (status == 0)) {
0265             plocal_buf = local_buf;
0266             chunk_len  = (total_len < payload_max) ? total_len : payload_max;
0267 
0268             *plocal_buf++ = 0xFC;
0269             *plocal_buf++ = chunk_len + sizeof(u32);
0270 
0271             *(u32 *)plocal_buf = addr + prevchunk_len;
0272 #ifdef __BIG_ENDIAN
0273             convert_endian(sizeof(u32), plocal_buf);
0274 #endif
0275             plocal_buf += sizeof(u32);
0276 
0277             memcpy(plocal_buf, &buffer[ix], chunk_len);
0278             convert_endian(chunk_len, plocal_buf);
0279             if (mxl692_i2c_write(dev, local_buf,
0280                          (chunk_len + MXL_EAGLE_I2C_MHEADER_SIZE)) < 0) {
0281                 status = -EREMOTEIO;
0282                 break;
0283             }
0284 
0285             prevchunk_len += chunk_len;
0286             total_len -= chunk_len;
0287             ix += chunk_len;
0288         }
0289         *index = ix;
0290     } else {
0291         status = -EINVAL;
0292     }
0293 
0294     if (status)
0295         dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0296 
0297     return status;
0298 }
0299 
0300 static int mxl692_memwrite(struct mxl692_dev *dev, u32 addr,
0301                u8 *buffer, u32 size)
0302 {
0303     int status = 0, total_len = 0;
0304     u8 local_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {}, *plocal_buf = NULL;
0305 
0306     total_len = size;
0307     total_len = (total_len + 3) & ~3;  /* 4 byte alignment */
0308 
0309     if (total_len > (MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_MHEADER_SIZE))
0310         dev_dbg(&dev->i2c_client->dev, "hrmph?\n");
0311 
0312     plocal_buf = local_buf;
0313 
0314     *plocal_buf++ = 0xFC;
0315     *plocal_buf++ = total_len + sizeof(u32);
0316 
0317     *(u32 *)plocal_buf = addr;
0318     plocal_buf += sizeof(u32);
0319 
0320     memcpy(plocal_buf, buffer, total_len);
0321 #ifdef __BIG_ENDIAN
0322     convert_endian(sizeof(u32) + total_len, local_buf + 2);
0323 #endif
0324     if (mxl692_i2c_write(dev, local_buf,
0325                  (total_len + MXL_EAGLE_I2C_MHEADER_SIZE)) < 0) {
0326         status = -EREMOTEIO;
0327         goto err_finish;
0328     }
0329 
0330     return status;
0331 err_finish:
0332     dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0333     return status;
0334 }
0335 
0336 static int mxl692_memread(struct mxl692_dev *dev, u32 addr,
0337               u8 *buffer, u32 size)
0338 {
0339     int status = 0;
0340     u8 local_buf[MXL_EAGLE_I2C_MHEADER_SIZE] = {}, *plocal_buf = NULL;
0341 
0342     plocal_buf = local_buf;
0343 
0344     *plocal_buf++ = 0xFB;
0345     *plocal_buf++ = sizeof(u32);
0346     *(u32 *)plocal_buf = addr;
0347 #ifdef __BIG_ENDIAN
0348     convert_endian(sizeof(u32), plocal_buf);
0349 #endif
0350     mutex_lock(&dev->i2c_lock);
0351 
0352     if (mxl692_i2c_write(dev, local_buf, MXL_EAGLE_I2C_MHEADER_SIZE) > 0) {
0353         size = (size + 3) & ~3;  /* 4 byte alignment */
0354         status = mxl692_i2c_read(dev, buffer, (u16)size) < 0 ? -EREMOTEIO : 0;
0355 #ifdef __BIG_ENDIAN
0356         if (status == 0)
0357             convert_endian(size, buffer);
0358 #endif
0359     } else {
0360         status = -EREMOTEIO;
0361     }
0362 
0363     mutex_unlock(&dev->i2c_lock);
0364 
0365     if (status)
0366         dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0367 
0368     return status;
0369 }
0370 
0371 static const char *mxl692_opcode_string(u8 opcode)
0372 {
0373     if (opcode <= MXL_EAGLE_OPCODE_INTERNAL)
0374         return MXL_EAGLE_OPCODE_STRING[opcode];
0375 
0376     return "invalid opcode";
0377 }
0378 
0379 static int mxl692_opwrite(struct mxl692_dev *dev, u8 *buffer,
0380               u32 size)
0381 {
0382     int status = 0, total_len = 0;
0383     u8 local_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {}, *plocal_buf = NULL;
0384     struct MXL_EAGLE_HOST_MSG_HEADER_T *tx_hdr = (struct MXL_EAGLE_HOST_MSG_HEADER_T *)buffer;
0385 
0386     total_len = size;
0387     total_len = (total_len + 3) & ~3;  /* 4 byte alignment */
0388 
0389     if (total_len > (MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_PHEADER_SIZE))
0390         dev_dbg(&dev->i2c_client->dev, "hrmph?\n");
0391 
0392     plocal_buf = local_buf;
0393 
0394     *plocal_buf++ = 0xFE;
0395     *plocal_buf++ = (u8)total_len;
0396 
0397     memcpy(plocal_buf, buffer, total_len);
0398     convert_endian(total_len, plocal_buf);
0399 
0400     if (mxl692_i2c_write(dev, local_buf,
0401                  (total_len + MXL_EAGLE_I2C_PHEADER_SIZE)) < 0) {
0402         status = -EREMOTEIO;
0403         goto err_finish;
0404     }
0405 err_finish:
0406     if (status)
0407         dev_dbg(&dev->i2c_client->dev, "opcode %s  err %d\n",
0408             mxl692_opcode_string(tx_hdr->opcode), status);
0409     return status;
0410 }
0411 
0412 static int mxl692_opread(struct mxl692_dev *dev, u8 *buffer,
0413              u32 size)
0414 {
0415     int status = 0;
0416     u32 ix = 0;
0417     u8 local_buf[MXL_EAGLE_I2C_PHEADER_SIZE] = {};
0418 
0419     local_buf[0] = 0xFD;
0420     local_buf[1] = 0;
0421 
0422     if (mxl692_i2c_write(dev, local_buf, MXL_EAGLE_I2C_PHEADER_SIZE) > 0) {
0423         size = (size + 3) & ~3;  /* 4 byte alignment */
0424 
0425         /* Read in 4 byte chunks */
0426         for (ix = 0; ix < size; ix += 4) {
0427             if (mxl692_i2c_read(dev, buffer + ix, 4) < 0) {
0428                 dev_dbg(&dev->i2c_client->dev, "ix=%d   size=%d\n", ix, size);
0429                 status = -EREMOTEIO;
0430                 goto err_finish;
0431             }
0432         }
0433         convert_endian(size, buffer);
0434     } else {
0435         status = -EREMOTEIO;
0436     }
0437 err_finish:
0438     if (status)
0439         dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0440     return status;
0441 }
0442 
0443 static int mxl692_i2c_writeread(struct mxl692_dev *dev,
0444                 u8 opcode,
0445                 u8 *tx_payload,
0446                 u8 tx_payload_size,
0447                 u8 *rx_payload,
0448                 u8 rx_payload_expected)
0449 {
0450     int status = 0, timeout = 40;
0451     u8 tx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
0452     u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
0453     u32 resp_checksum = 0, resp_checksum_tmp = 0;
0454     struct MXL_EAGLE_HOST_MSG_HEADER_T *tx_header;
0455     struct MXL_EAGLE_HOST_MSG_HEADER_T *rx_header;
0456 
0457     mutex_lock(&dev->i2c_lock);
0458 
0459     if ((tx_payload_size + MXL_EAGLE_HOST_MSG_HEADER_SIZE) >
0460         (MXL_EAGLE_MAX_I2C_PACKET_SIZE - MXL_EAGLE_I2C_PHEADER_SIZE)) {
0461         status = -EINVAL;
0462         goto err_finish;
0463     }
0464 
0465     tx_header = (struct MXL_EAGLE_HOST_MSG_HEADER_T *)tx_buf;
0466     tx_header->opcode = opcode;
0467     tx_header->seqnum = dev->seqnum++;
0468     tx_header->payload_size = tx_payload_size;
0469     tx_header->checksum = 0;
0470 
0471     if (dev->seqnum == 0)
0472         dev->seqnum = 1;
0473 
0474     if (tx_payload && tx_payload_size > 0)
0475         memcpy(&tx_buf[MXL_EAGLE_HOST_MSG_HEADER_SIZE], tx_payload, tx_payload_size);
0476 
0477     mxl692_tx_swap(opcode, tx_buf);
0478 
0479     tx_header->checksum = 0;
0480     tx_header->checksum = mxl692_checksum(tx_buf,
0481                           MXL_EAGLE_HOST_MSG_HEADER_SIZE + tx_payload_size);
0482 #ifdef __LITTLE_ENDIAN
0483     convert_endian(4, (u8 *)&tx_header->checksum); /* cksum is big endian */
0484 #endif
0485     /* send Tx message */
0486     status = mxl692_opwrite(dev, tx_buf,
0487                 tx_payload_size + MXL_EAGLE_HOST_MSG_HEADER_SIZE);
0488     if (status) {
0489         status = -EREMOTEIO;
0490         goto err_finish;
0491     }
0492 
0493     /* receive Rx message (polling) */
0494     rx_header = (struct MXL_EAGLE_HOST_MSG_HEADER_T *)rx_buf;
0495 
0496     do {
0497         status = mxl692_opread(dev, rx_buf,
0498                        rx_payload_expected + MXL_EAGLE_HOST_MSG_HEADER_SIZE);
0499         usleep_range(1000, 2000);
0500         timeout--;
0501     } while ((timeout > 0) && (status == 0) &&
0502          (rx_header->seqnum == 0) &&
0503          (rx_header->checksum == 0));
0504 
0505     if (timeout == 0 || status) {
0506         dev_dbg(&dev->i2c_client->dev, "timeout=%d   status=%d\n",
0507             timeout, status);
0508         status = -ETIMEDOUT;
0509         goto err_finish;
0510     }
0511 
0512     if (rx_header->status) {
0513         dev_dbg(&dev->i2c_client->dev, "rx header status code: %d\n", rx_header->status);
0514         status = -EREMOTEIO;
0515         goto err_finish;
0516     }
0517 
0518     if (rx_header->seqnum != tx_header->seqnum ||
0519         rx_header->opcode != tx_header->opcode ||
0520         rx_header->payload_size != rx_payload_expected) {
0521         dev_dbg(&dev->i2c_client->dev, "Something failed seq=%s  opcode=%s  pSize=%s\n",
0522             rx_header->seqnum != tx_header->seqnum ? "X" : "0",
0523             rx_header->opcode != tx_header->opcode ? "X" : "0",
0524             rx_header->payload_size != rx_payload_expected ? "X" : "0");
0525         if (rx_header->payload_size != rx_payload_expected)
0526             dev_dbg(&dev->i2c_client->dev,
0527                 "rx_header->payloadSize=%d   rx_payload_expected=%d\n",
0528                 rx_header->payload_size, rx_payload_expected);
0529         status = -EREMOTEIO;
0530         goto err_finish;
0531     }
0532 
0533     resp_checksum = rx_header->checksum;
0534     rx_header->checksum = 0;
0535 
0536     resp_checksum_tmp = mxl692_checksum(rx_buf,
0537                         MXL_EAGLE_HOST_MSG_HEADER_SIZE + rx_header->payload_size);
0538 #ifdef __LITTLE_ENDIAN
0539     convert_endian(4, (u8 *)&resp_checksum_tmp); /* cksum is big endian */
0540 #endif
0541     if (resp_checksum != resp_checksum_tmp) {
0542         dev_dbg(&dev->i2c_client->dev, "rx checksum failure\n");
0543         status = -EREMOTEIO;
0544         goto err_finish;
0545     }
0546 
0547     mxl692_rx_swap(rx_header->opcode, rx_buf);
0548 
0549     if (rx_header->payload_size > 0) {
0550         if (!rx_payload) {
0551             dev_dbg(&dev->i2c_client->dev, "no rx payload?!?\n");
0552             status = -EREMOTEIO;
0553             goto err_finish;
0554         }
0555         memcpy(rx_payload, rx_buf + MXL_EAGLE_HOST_MSG_HEADER_SIZE,
0556                rx_header->payload_size);
0557     }
0558 err_finish:
0559     if (status)
0560         dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0561 
0562     mutex_unlock(&dev->i2c_lock);
0563     return status;
0564 }
0565 
0566 static int mxl692_fwdownload(struct mxl692_dev *dev,
0567                  const u8 *firmware_buf, u32 buf_len)
0568 {
0569     int status = 0;
0570     u32 ix, reg_val = 0x1;
0571     u8 rx_buf[MXL_EAGLE_MAX_I2C_PACKET_SIZE] = {};
0572     struct MXL_EAGLE_DEV_STATUS_T *dev_status;
0573 
0574     if (buf_len < MXL_EAGLE_FW_HEADER_SIZE ||
0575         buf_len > MXL_EAGLE_FW_MAX_SIZE_IN_KB * 1000)
0576         return -EINVAL;
0577 
0578     mutex_lock(&dev->i2c_lock);
0579 
0580     dev_dbg(&dev->i2c_client->dev, "\n");
0581 
0582     status = mxl692_validate_fw_header(dev, firmware_buf, buf_len);
0583     if (status)
0584         goto err_finish;
0585 
0586     ix = 16;
0587     status = mxl692_write_fw_block(dev, firmware_buf, buf_len, &ix); /* DRAM */
0588     if (status)
0589         goto err_finish;
0590 
0591     status = mxl692_write_fw_block(dev, firmware_buf, buf_len, &ix); /* IRAM */
0592     if (status)
0593         goto err_finish;
0594 
0595     /* release CPU from reset */
0596     status = mxl692_memwrite(dev, 0x70000018, (u8 *)&reg_val, sizeof(u32));
0597     if (status)
0598         goto err_finish;
0599 
0600     mutex_unlock(&dev->i2c_lock);
0601 
0602     if (status == 0) {
0603         /* verify FW is alive */
0604         usleep_range(MXL_EAGLE_FW_LOAD_TIME * 1000, (MXL_EAGLE_FW_LOAD_TIME + 5) * 1000);
0605         dev_status = (struct MXL_EAGLE_DEV_STATUS_T *)&rx_buf;
0606         status = mxl692_i2c_writeread(dev,
0607                           MXL_EAGLE_OPCODE_DEVICE_STATUS_GET,
0608                           NULL,
0609                           0,
0610                           (u8 *)dev_status,
0611                           sizeof(struct MXL_EAGLE_DEV_STATUS_T));
0612     }
0613 
0614     return status;
0615 err_finish:
0616     mutex_unlock(&dev->i2c_lock);
0617     if (status)
0618         dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0619     return status;
0620 }
0621 
0622 static int mxl692_get_versions(struct mxl692_dev *dev)
0623 {
0624     int status = 0;
0625     struct MXL_EAGLE_DEV_VER_T dev_ver = {};
0626     static const char * const chip_id[] = {"N/A", "691", "248", "692"};
0627 
0628     status = mxl692_i2c_writeread(dev, MXL_EAGLE_OPCODE_DEVICE_VERSION_GET,
0629                       NULL,
0630                       0,
0631                       (u8 *)&dev_ver,
0632                       sizeof(struct MXL_EAGLE_DEV_VER_T));
0633     if (status)
0634         return status;
0635 
0636     dev_info(&dev->i2c_client->dev, "MxL692_DEMOD Chip ID: %s\n",
0637          chip_id[dev_ver.chip_id]);
0638 
0639     dev_info(&dev->i2c_client->dev,
0640          "MxL692_DEMOD FW Version: %d.%d.%d.%d_RC%d\n",
0641          dev_ver.firmware_ver[0],
0642          dev_ver.firmware_ver[1],
0643          dev_ver.firmware_ver[2],
0644          dev_ver.firmware_ver[3],
0645          dev_ver.firmware_ver[4]);
0646 
0647     return status;
0648 }
0649 
0650 static int mxl692_reset(struct mxl692_dev *dev)
0651 {
0652     int status = 0;
0653     u32 dev_type = MXL_EAGLE_DEVICE_MAX, reg_val = 0x2;
0654 
0655     dev_dbg(&dev->i2c_client->dev, "\n");
0656 
0657     /* legacy i2c override */
0658     status = mxl692_memwrite(dev, 0x80000100, (u8 *)&reg_val, sizeof(u32));
0659     if (status)
0660         goto err_finish;
0661 
0662     /* verify sku */
0663     status = mxl692_memread(dev, 0x70000188, (u8 *)&dev_type, sizeof(u32));
0664     if (status)
0665         goto err_finish;
0666 
0667     if (dev_type != dev->device_type)
0668         goto err_finish;
0669 
0670 err_finish:
0671     if (status)
0672         dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0673     return status;
0674 }
0675 
0676 static int mxl692_config_regulators(struct mxl692_dev *dev,
0677                     enum MXL_EAGLE_POWER_SUPPLY_SOURCE_E power_supply)
0678 {
0679     int status = 0;
0680     u32 reg_val;
0681 
0682     dev_dbg(&dev->i2c_client->dev, "\n");
0683 
0684     /* configure main regulator according to the power supply source */
0685     status = mxl692_memread(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
0686     if (status)
0687         goto err_finish;
0688 
0689     reg_val &= 0x00FFFFFF;
0690     reg_val |= (power_supply == MXL_EAGLE_POWER_SUPPLY_SOURCE_SINGLE) ?
0691                     0x14000000 : 0x10000000;
0692 
0693     status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
0694     if (status)
0695         goto err_finish;
0696 
0697     /* configure digital regulator to high current mode */
0698     status = mxl692_memread(dev, 0x90000018, (u8 *)&reg_val, sizeof(u32));
0699     if (status)
0700         goto err_finish;
0701 
0702     reg_val |= 0x800;
0703 
0704     status = mxl692_memwrite(dev, 0x90000018, (u8 *)&reg_val, sizeof(u32));
0705 
0706 err_finish:
0707     if (status)
0708         dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0709     return status;
0710 }
0711 
0712 static int mxl692_config_xtal(struct mxl692_dev *dev,
0713                   struct MXL_EAGLE_DEV_XTAL_T *dev_xtal)
0714 {
0715     int status = 0;
0716     u32 reg_val, reg_val1;
0717 
0718     dev_dbg(&dev->i2c_client->dev, "\n");
0719 
0720     status = mxl692_memread(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
0721     if (status)
0722         goto err_finish;
0723 
0724     /* set XTAL capacitance */
0725     reg_val &= 0xFFFFFFE0;
0726     reg_val |= dev_xtal->xtal_cap;
0727 
0728     /* set CLK OUT */
0729     reg_val = dev_xtal->clk_out_enable ? (reg_val | 0x0100) : (reg_val & 0xFFFFFEFF);
0730 
0731     status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
0732     if (status)
0733         goto err_finish;
0734 
0735     /* set CLK OUT divider */
0736     reg_val = dev_xtal->clk_out_div_enable ? (reg_val | 0x0200) : (reg_val & 0xFFFFFDFF);
0737 
0738     status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
0739     if (status)
0740         goto err_finish;
0741 
0742     /* set XTAL sharing */
0743     reg_val = dev_xtal->xtal_sharing_enable ? (reg_val | 0x010400) : (reg_val & 0xFFFEFBFF);
0744 
0745     status = mxl692_memwrite(dev, 0x90000000, (u8 *)&reg_val, sizeof(u32));
0746     if (status)
0747         goto err_finish;
0748 
0749     /* enable/disable XTAL calibration, based on master/slave device */
0750     status = mxl692_memread(dev, 0x90000030, (u8 *)&reg_val1, sizeof(u32));
0751     if (status)
0752         goto err_finish;
0753 
0754     if (dev_xtal->xtal_calibration_enable) {
0755         /* enable XTAL calibration and set XTAL amplitude to a higher value */
0756         reg_val1 &= 0xFFFFFFFD;
0757         reg_val1 |= 0x30;
0758 
0759         status = mxl692_memwrite(dev, 0x90000030, (u8 *)&reg_val1, sizeof(u32));
0760         if (status)
0761             goto err_finish;
0762     } else {
0763         /* disable XTAL calibration */
0764         reg_val1 |= 0x2;
0765 
0766         status = mxl692_memwrite(dev, 0x90000030, (u8 *)&reg_val1, sizeof(u32));
0767         if (status)
0768             goto err_finish;
0769 
0770         /* set XTAL bias value */
0771         status = mxl692_memread(dev, 0x9000002c, (u8 *)&reg_val, sizeof(u32));
0772         if (status)
0773             goto err_finish;
0774 
0775         reg_val &= 0xC0FFFFFF;
0776         reg_val |= 0xA000000;
0777 
0778         status = mxl692_memwrite(dev, 0x9000002c, (u8 *)&reg_val, sizeof(u32));
0779         if (status)
0780             goto err_finish;
0781     }
0782 
0783     /* start XTAL calibration */
0784     status = mxl692_memread(dev, 0x70000010, (u8 *)&reg_val, sizeof(u32));
0785     if (status)
0786         goto err_finish;
0787 
0788     reg_val |= 0x8;
0789 
0790     status = mxl692_memwrite(dev, 0x70000010, (u8 *)&reg_val, sizeof(u32));
0791     if (status)
0792         goto err_finish;
0793 
0794     status = mxl692_memread(dev, 0x70000018, (u8 *)&reg_val, sizeof(u32));
0795     if (status)
0796         goto err_finish;
0797 
0798     reg_val |= 0x10;
0799 
0800     status = mxl692_memwrite(dev, 0x70000018, (u8 *)&reg_val, sizeof(u32));
0801     if (status)
0802         goto err_finish;
0803 
0804     status = mxl692_memread(dev, 0x9001014c, (u8 *)&reg_val, sizeof(u32));
0805     if (status)
0806         goto err_finish;
0807 
0808     reg_val &= 0xFFFFEFFF;
0809 
0810     status = mxl692_memwrite(dev, 0x9001014c, (u8 *)&reg_val, sizeof(u32));
0811     if (status)
0812         goto err_finish;
0813 
0814     reg_val |= 0x1000;
0815 
0816     status = mxl692_memwrite(dev, 0x9001014c, (u8 *)&reg_val, sizeof(u32));
0817     if (status)
0818         goto err_finish;
0819 
0820     usleep_range(45000, 55000);
0821 
0822 err_finish:
0823     if (status)
0824         dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0825     return status;
0826 }
0827 
0828 static int mxl692_powermode(struct mxl692_dev *dev,
0829                 enum MXL_EAGLE_POWER_MODE_E power_mode)
0830 {
0831     int status = 0;
0832     u8 mode = power_mode;
0833 
0834     dev_dbg(&dev->i2c_client->dev, "%s\n",
0835         power_mode == MXL_EAGLE_POWER_MODE_SLEEP ? "sleep" : "active");
0836 
0837     status = mxl692_i2c_writeread(dev,
0838                       MXL_EAGLE_OPCODE_DEVICE_POWERMODE_SET,
0839                       &mode,
0840                       sizeof(u8),
0841                       NULL,
0842                       0);
0843     if (status) {
0844         dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0845         return status;
0846     }
0847 
0848     dev->power_mode = power_mode;
0849 
0850     return status;
0851 }
0852 
0853 static int mxl692_init(struct dvb_frontend *fe)
0854 {
0855     struct mxl692_dev *dev = fe->demodulator_priv;
0856     struct i2c_client *client = dev->i2c_client;
0857     struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0858     int status = 0;
0859     const struct firmware *firmware;
0860     struct MXL_EAGLE_DEV_XTAL_T xtal_config = {};
0861 
0862     dev_dbg(&dev->i2c_client->dev, "\n");
0863 
0864     if (dev->init_done)
0865         goto warm;
0866 
0867     dev->seqnum = 1;
0868 
0869     status = mxl692_reset(dev);
0870     if (status)
0871         goto err;
0872 
0873     usleep_range(50 * 1000, 60 * 1000); /* was 1000! */
0874 
0875     status = mxl692_config_regulators(dev, MXL_EAGLE_POWER_SUPPLY_SOURCE_DUAL);
0876     if (status)
0877         goto err;
0878 
0879     xtal_config.xtal_cap = 26;
0880     xtal_config.clk_out_div_enable = 0;
0881     xtal_config.clk_out_enable = 0;
0882     xtal_config.xtal_calibration_enable = 0;
0883     xtal_config.xtal_sharing_enable = 1;
0884     status = mxl692_config_xtal(dev, &xtal_config);
0885     if (status)
0886         goto err;
0887 
0888     status = request_firmware(&firmware, MXL692_FIRMWARE, &client->dev);
0889     if (status) {
0890         dev_dbg(&dev->i2c_client->dev, "firmware missing? %s\n",
0891             MXL692_FIRMWARE);
0892         goto err;
0893     }
0894 
0895     status = mxl692_fwdownload(dev, firmware->data, firmware->size);
0896     if (status)
0897         goto err_release_firmware;
0898 
0899     release_firmware(firmware);
0900 
0901     status = mxl692_get_versions(dev);
0902     if (status)
0903         goto err;
0904 
0905     dev->power_mode = MXL_EAGLE_POWER_MODE_SLEEP;
0906 warm:
0907     /* Config Device Power Mode */
0908     if (dev->power_mode != MXL_EAGLE_POWER_MODE_ACTIVE) {
0909         status = mxl692_powermode(dev, MXL_EAGLE_POWER_MODE_ACTIVE);
0910         if (status)
0911             goto err;
0912 
0913         usleep_range(50 * 1000, 60 * 1000); /* was 500! */
0914     }
0915 
0916     /* Init stats here to indicate which stats are supported */
0917     c->cnr.len = 1;
0918     c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
0919     c->post_bit_error.len = 1;
0920     c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
0921     c->post_bit_count.len = 1;
0922     c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
0923     c->block_error.len = 1;
0924     c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
0925 
0926     dev->init_done = 1;
0927     return 0;
0928 err_release_firmware:
0929     release_firmware(firmware);
0930 err:
0931     dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
0932     return status;
0933 }
0934 
0935 static int mxl692_sleep(struct dvb_frontend *fe)
0936 {
0937     struct mxl692_dev *dev = fe->demodulator_priv;
0938 
0939     if (dev->power_mode != MXL_EAGLE_POWER_MODE_SLEEP)
0940         mxl692_powermode(dev, MXL_EAGLE_POWER_MODE_SLEEP);
0941 
0942     return 0;
0943 }
0944 
0945 static int mxl692_set_frontend(struct dvb_frontend *fe)
0946 {
0947     struct dtv_frontend_properties *p = &fe->dtv_property_cache;
0948     struct mxl692_dev *dev = fe->demodulator_priv;
0949 
0950     int status = 0;
0951     enum MXL_EAGLE_DEMOD_TYPE_E demod_type;
0952     struct MXL_EAGLE_MPEGOUT_PARAMS_T mpeg_params = {};
0953     enum MXL_EAGLE_QAM_DEMOD_ANNEX_TYPE_E qam_annex = MXL_EAGLE_QAM_DEMOD_ANNEX_B;
0954     struct MXL_EAGLE_QAM_DEMOD_PARAMS_T qam_params = {};
0955     struct MXL_EAGLE_TUNER_CHANNEL_PARAMS_T tuner_params = {};
0956     u8 op_param = 0;
0957 
0958     dev_dbg(&dev->i2c_client->dev, "\n");
0959 
0960     switch (p->modulation) {
0961     case VSB_8:
0962         demod_type = MXL_EAGLE_DEMOD_TYPE_ATSC;
0963         break;
0964     case QAM_AUTO:
0965     case QAM_64:
0966     case QAM_128:
0967     case QAM_256:
0968         demod_type = MXL_EAGLE_DEMOD_TYPE_QAM;
0969         break;
0970     default:
0971         return -EINVAL;
0972     }
0973 
0974     if (dev->current_frequency == p->frequency && dev->demod_type == demod_type) {
0975         dev_dbg(&dev->i2c_client->dev, "already set up\n");
0976         return 0;
0977     }
0978 
0979     dev->current_frequency = -1;
0980     dev->demod_type = -1;
0981 
0982     op_param = demod_type;
0983     status = mxl692_i2c_writeread(dev,
0984                       MXL_EAGLE_OPCODE_DEVICE_DEMODULATOR_TYPE_SET,
0985                       &op_param,
0986                       sizeof(u8),
0987                       NULL,
0988                       0);
0989     if (status) {
0990         dev_dbg(&dev->i2c_client->dev,
0991             "DEVICE_DEMODULATOR_TYPE_SET...FAIL  err 0x%x\n", status);
0992         goto err;
0993     }
0994 
0995     usleep_range(20 * 1000, 30 * 1000); /* was 500! */
0996 
0997     mpeg_params.mpeg_parallel = 0;
0998     mpeg_params.msb_first = MXL_EAGLE_DATA_SERIAL_MSB_1ST;
0999     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;
1095 err:
1096     dev_dbg(&dev->i2c_client->dev, "err %d\n", status);
1097     return status;
1098 }
1099 
1100 static 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 
1111 static 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 
1162 static 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 
1215 static 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 
1292 static 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 
1311 static 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;
1335 err:
1336     dev_dbg(&client->dev, "failed %d\n", ret);
1337     return -ENODEV;
1338 }
1339 
1340 static 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 
1351 static const struct i2c_device_id mxl692_id_table[] = {
1352     {"mxl692", 0},
1353     {}
1354 };
1355 MODULE_DEVICE_TABLE(i2c, mxl692_id_table);
1356 
1357 static 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 
1366 module_i2c_driver(mxl692_driver);
1367 
1368 MODULE_AUTHOR("Brad Love <brad@nextdimension.cc>");
1369 MODULE_DESCRIPTION("MaxLinear MxL692 demodulator/tuner driver");
1370 MODULE_FIRMWARE(MXL692_FIRMWARE);
1371 MODULE_LICENSE("GPL");