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