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