1/* $NetBSD: zl10353.c,v 1.2 2011/08/29 11:16:35 jruoho Exp $ */ 2 3/*- 4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jukka Ruohonen. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: zl10353.c,v 1.2 2011/08/29 11:16:35 jruoho Exp $"); 34 35#include <sys/param.h> 36#include <sys/kmem.h> 37#include <sys/module.h> 38 39#include <dev/dtv/dtvif.h> 40 41#include <dev/i2c/i2cvar.h> 42#include <dev/i2c/zl10353reg.h> 43#include <dev/i2c/zl10353var.h> 44 45/* 46 * Zarlink ZL10353 demodulator (now known as Intel CE623x). 47 * 48 * An incomplete datasheet: 49 * 50 * Intel Corporation: CE6230 - COFDM demodulator with 51 * USB interface for PC-TV. Data Sheet, Revision 1.1. 52 * March 29, 2007. 53 */ 54 55static int zl10353_probe(struct zl10353 *); 56static int zl10353_read(struct zl10353 *, uint8_t, uint8_t *); 57static int zl10353_write(struct zl10353 *, uint8_t, uint8_t); 58static int zl10353_reset(struct zl10353 *, bool); 59static int zl10353_set_agc(struct zl10353 *, 60 const struct dvb_frontend_parameters *); 61static int zl10353_set_bw(struct zl10353 *, fe_bandwidth_t); 62static int zl10353_set_rate(struct zl10353 *); 63static int zl10353_set_freq(struct zl10353 *); 64static int zl10353_set_tps(struct zl10353 *, 65 const struct dvb_frontend_parameters *); 66static int zl10353_get_guard(fe_guard_interval_t, uint16_t *); 67static int zl10353_get_mode(fe_transmit_mode_t, uint16_t *); 68static int zl10353_get_fec(fe_code_rate_t, bool, uint16_t *); 69static int zl10353_get_modulation(fe_modulation_t, uint16_t *); 70static int zl10353_get_hier(fe_hierarchy_t, uint16_t *); 71 72struct zl10353 * 73zl10353_open(device_t parent, i2c_tag_t i2c, i2c_addr_t addr) 74{ 75 struct zl10353 *zl; 76 77 zl = kmem_zalloc(sizeof(*zl), KM_SLEEP); 78 79 if (zl == NULL) 80 return NULL; 81 82 zl->zl_i2c = i2c; 83 zl->zl_i2c_addr = addr; 84 zl->zl_parent = parent; 85 86 zl->zl_freq = ZL10353_DEFAULT_INPUT_FREQ; 87 zl->zl_clock = ZL10353_DEFAULT_CLOCK_MHZ; 88 89 if (zl10353_reset(zl, true) != 0) { 90 zl10353_close(zl); 91 return NULL; 92 } 93 94 if (zl10353_probe(zl) != 0) { 95 zl10353_close(zl); 96 return NULL; 97 } 98 99 return zl; 100} 101 102void 103zl10353_close(struct zl10353 *zl) 104{ 105 kmem_free(zl, sizeof(*zl)); 106} 107 108static int 109zl10353_probe(struct zl10353 *zl) 110{ 111 uint8_t val; 112 int rv; 113 114 if ((rv = zl10353_read(zl, ZL10353_REG_ID, &val)) != 0) 115 return rv; 116 117 switch (val) { 118 119 case ZL10353_ID_CE6230: 120 zl->zl_name = "Intel CE6230"; 121 break; 122 123 case ZL10353_ID_CE6231: 124 zl->zl_name = "Intel CE6231"; 125 break; 126 127 case ZL10353_ID_ZL10353: 128 zl->zl_name = "Zarlink ZL10353"; 129 break; 130 131 default: 132 aprint_error_dev(zl->zl_parent, "unknown chip 0x%02x\n", val); 133 return ENOTSUP; 134 } 135 136 aprint_verbose_dev(zl->zl_parent, "found %s at i2c " 137 "addr 0x%02x\n", zl->zl_name, zl->zl_i2c_addr); 138 139 return 0; 140} 141 142static int 143zl10353_read(struct zl10353 *zl, uint8_t reg, uint8_t *valp) 144{ 145 static const i2c_op_t op = I2C_OP_READ; 146 int rv; 147 148 if ((rv = iic_acquire_bus(zl->zl_i2c, 0)) != 0) 149 return rv; 150 151 rv = iic_exec(zl->zl_i2c, op, zl->zl_i2c_addr, ®, 1, valp, 1, 0); 152 iic_release_bus(zl->zl_i2c, 0); 153 154 return rv; 155} 156 157static int 158zl10353_write(struct zl10353 *zl, uint8_t reg, uint8_t val) 159{ 160 static const i2c_op_t op = I2C_OP_WRITE; 161 const uint8_t cmd[2] = { reg, val }; 162 int rv; 163 164 if ((rv = iic_acquire_bus(zl->zl_i2c, 0)) != 0) 165 return rv; 166 167 rv = iic_exec(zl->zl_i2c, op, zl->zl_i2c_addr, cmd, 2, NULL, 0, 0); 168 iic_release_bus(zl->zl_i2c, 0); 169 170 return rv; 171} 172 173static int 174zl10353_reset(struct zl10353 *zl, bool hard) 175{ 176 size_t i = 0, len = 5; 177 int rv; 178 179 static const struct { 180 uint8_t reg; 181 uint8_t val; 182 } reset[] = { 183 { 0x50, 0x03 }, /* Hard */ 184 { 0x03, 0x44 }, 185 { 0x44, 0x46 }, 186 { 0x46, 0x15 }, 187 { 0x15, 0x0f }, 188 { 0x55, 0x80 }, /* Soft */ 189 { 0xea, 0x01 }, 190 { 0xea, 0x00 }, 191 }; 192 193 if (hard != true) { 194 len = __arraycount(reset); 195 i = 5; 196 } 197 198 while (i < len) { 199 200 if ((rv = zl10353_write(zl, reset[i].reg, reset[i].val)) != 0) 201 return rv; 202 else { 203 delay(100); 204 } 205 206 i++; 207 208 } 209 210 return 0; 211} 212 213void 214zl10353_get_devinfo(struct dvb_frontend_info *fi) 215{ 216 217 fi->type = FE_OFDM; 218 219 fi->frequency_min = 174000000; 220 fi->frequency_max = 862000000; 221 222 fi->frequency_tolerance = 0; 223 fi->frequency_stepsize = 166667; 224 225 fi->caps |= FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 226 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_QPSK | 227 FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_RECOVER | 228 FE_CAN_MUTE_TS; 229 230 fi->caps |= FE_CAN_FEC_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | 231 FE_CAN_QAM_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | 232 FE_CAN_HIERARCHY_AUTO; 233} 234 235int 236zl10353_set_params(struct zl10353 *zl,const struct dvb_frontend_parameters *fp) 237{ 238 int rv; 239 240 /* 1. Soft reset. */ 241 if ((rv = zl10353_reset(zl, false)) != 0) 242 return rv; 243 244 /* 2. Set AGC. */ 245 if ((rv = zl10353_set_agc(zl, fp)) != 0) 246 return rv; 247 248 /* 3. Set bandwidth. */ 249 if ((rv = zl10353_set_bw(zl, fp->u.ofdm.bandwidth)) != 0) 250 return rv; 251 252 /* 4. Set nominal rate. */ 253 if ((rv = zl10353_set_rate(zl)) != 0) 254 return rv; 255 256 /* 5. Set input frequency. */ 257 if ((rv = zl10353_set_freq(zl)) != 0) 258 return rv; 259 260 /* 6. Set TPS parameters. */ 261 if ((rv = zl10353_set_tps(zl, fp)) != 0) 262 return rv; 263 264 return 0; 265} 266 267int 268zl10353_set_fsm(struct zl10353 *zl) 269{ 270 return zl10353_write(zl, ZL10353_REG_FSM, ZL10353_FSM_START); 271} 272 273int 274zl10353_set_gate(void *aux, bool enable) 275{ 276 uint8_t val = ZL10353_GATE_DISABLE; 277 278 if (enable != false) 279 val = ZL10353_GATE_ENABLE; 280 281 return zl10353_write(aux, ZL10353_REG_GATE, val); 282} 283 284static int 285zl10353_set_agc(struct zl10353 *zl, const struct dvb_frontend_parameters *fp) 286{ 287 const struct dvb_ofdm_parameters *ofdm = &fp->u.ofdm; 288 uint8_t val = ZL10353_AGC_TARGET_DEFAULT; 289 int rv; 290 291 if ((rv = zl10353_write(zl, ZL10353_REG_AGC_TARGET, val)) != 0) 292 return rv; 293 else { 294 val = 0; 295 } 296 297 if (ofdm->guard_interval != GUARD_INTERVAL_AUTO) 298 val |= ZL10353_AGC_CTRL_GUARD_NONAUTO; 299 300 if (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO) 301 val |= ZL10353_AGC_CTRL_MODE_NONAUTO; 302 303 return zl10353_write(zl, ZL10353_REG_AGC_CTRL, val); 304} 305 306static int 307zl10353_set_bw(struct zl10353 *zl, fe_bandwidth_t bw) 308{ 309 uint8_t val[3]; 310 int rv; 311 312 switch (bw) { 313 314 case BANDWIDTH_6_MHZ: 315 val[0] = ZL10353_BW_1_6_MHZ; 316 val[1] = ZL10353_BW_2_6_MHZ; 317 val[2] = ZL10353_BW_3_6_MHZ; 318 zl->zl_bw = 6; 319 break; 320 321 case BANDWIDTH_7_MHZ: 322 val[0] = ZL10353_BW_1_7_MHZ; 323 val[1] = ZL10353_BW_2_7_MHZ; 324 val[2] = ZL10353_BW_3_7_MHZ; 325 zl->zl_bw = 7; 326 break; 327 328 case BANDWIDTH_8_MHZ: 329 val[0] = ZL10353_BW_1_8_MHZ; 330 val[1] = ZL10353_BW_2_8_MHZ; 331 val[2] = ZL10353_BW_3_8_MHZ; 332 zl->zl_bw = 8; 333 break; 334 335 default: 336 zl->zl_bw = 0; 337 return EINVAL; 338 } 339 340 if ((rv = zl10353_write(zl, ZL10353_REG_BW_1, val[0])) != 0) 341 return rv; 342 343 if ((rv = zl10353_write(zl, ZL10353_REG_BW_2, val[1])) != 0) 344 return rv; 345 346 if ((rv = zl10353_write(zl, ZL10353_REG_BW_3, val[2])) != 0) 347 return rv; 348 349 return 0; 350} 351 352static int 353zl10353_set_rate(struct zl10353 *zl) 354{ 355 static const uint64_t c = 1497965625; 356 uint64_t val; 357 int rv; 358 359 KASSERT(zl->zl_bw >= 6 && zl->zl_bw <= 8); 360 KASSERT(zl->zl_clock > 0 && zl->zl_freq > 0); 361 362 val = zl->zl_bw * c; 363 val += zl->zl_clock >> 1; 364 val /= zl->zl_clock; 365 val = val & 0xffff; 366 367 if ((rv = zl10353_write(zl, ZL10353_REG_RATE_1, val >> 8)) != 0) 368 return rv; 369 370 return zl10353_write(zl, ZL10353_REG_RATE_2, val & 0xff); 371} 372 373static int 374zl10353_set_freq(struct zl10353 *zl) 375{ 376 const uint16_t val = zl->zl_freq; 377 int rv; 378 379 if ((rv = zl10353_write(zl, ZL10353_REG_FREQ_1, val >> 8)) != 0) 380 return rv; 381 382 return zl10353_write(zl, ZL10353_REG_FREQ_2, val & 0xff); 383} 384 385static int 386zl10353_set_tps(struct zl10353 *zl, const struct dvb_frontend_parameters *fp) 387{ 388 const struct dvb_ofdm_parameters *ofdm = &fp->u.ofdm; 389 uint16_t val = 0; 390 int rv; 391 392 if ((rv = zl10353_get_guard(ofdm->guard_interval, &val)) != 0) 393 goto fail; 394 395 if ((rv = zl10353_get_mode(ofdm->transmission_mode, &val)) != 0) 396 goto fail; 397 398 if ((rv = zl10353_get_fec(ofdm->code_rate_HP, true, &val)) != 0) 399 goto fail; 400 401 if ((rv = zl10353_get_fec(ofdm->code_rate_LP, false, &val)) != 0) 402 goto fail; 403 404 if ((rv = zl10353_get_modulation(ofdm->constellation, &val)) != 0) 405 goto fail; 406 407 if ((rv = zl10353_get_hier(ofdm->hierarchy_information, &val)) != 0) 408 goto fail; 409 410 if ((rv = zl10353_write(zl, ZL10353_REG_TPS_1, val >> 8)) != 0) 411 goto fail; 412 413 if ((rv = zl10353_write(zl, ZL10353_REG_TPS_2, val & 0xff)) != 0) 414 goto fail; 415 416 return 0; 417 418fail: 419 aprint_error_dev(zl->zl_parent, "failed to set " 420 "tps for %s (err %d)\n", zl->zl_name, rv); 421 422 return rv; 423} 424 425static int 426zl10353_get_guard(fe_guard_interval_t fg, uint16_t *valp) 427{ 428 429 switch (fg) { 430 431 case GUARD_INTERVAL_1_4: 432 *valp |= ZL10353_TPS_GUARD_1_4; 433 break; 434 435 case GUARD_INTERVAL_1_8: 436 *valp |= ZL10353_TPS_GUARD_1_8; 437 break; 438 439 case GUARD_INTERVAL_1_16: 440 *valp |= ZL10353_TPS_GUARD_1_16; 441 break; 442 443 case GUARD_INTERVAL_1_32: 444 *valp |= ZL10353_TPS_GUARD_1_32; 445 break; 446 447 case GUARD_INTERVAL_AUTO: 448 *valp |= ZL10353_TPS_GUARD_AUTO; 449 break; 450 451 default: 452 return EINVAL; 453 } 454 455 return 0; 456} 457 458static int 459zl10353_get_mode(fe_transmit_mode_t fm, uint16_t *valp) 460{ 461 462 switch (fm) { 463 464 case TRANSMISSION_MODE_2K: 465 *valp |= ZL10353_TPS_MODE_2K; 466 break; 467 468 case TRANSMISSION_MODE_8K: 469 *valp |= ZL10353_TPS_MODE_8K; 470 break; 471 472 case TRANSMISSION_MODE_AUTO: 473 *valp |= ZL10353_TPS_MODE_AUTO; 474 break; 475 476 default: 477 return EINVAL; 478 } 479 480 return 0; 481} 482 483static int 484zl10353_get_fec(fe_code_rate_t fc, bool hp, uint16_t *valp) 485{ 486 uint16_t hpval = 0, lpval = 0; 487 488 switch (fc) { 489 490 case FEC_1_2: 491 hpval = ZL10353_TPS_HP_FEC_1_2; 492 lpval = ZL10353_TPS_LP_FEC_1_2; 493 break; 494 495 case FEC_2_3: 496 hpval = ZL10353_TPS_HP_FEC_2_3; 497 lpval = ZL10353_TPS_LP_FEC_2_3; 498 break; 499 500 case FEC_3_4: 501 hpval = ZL10353_TPS_HP_FEC_3_4; 502 lpval = ZL10353_TPS_LP_FEC_3_4; 503 break; 504 505 case FEC_5_6: 506 hpval = ZL10353_TPS_HP_FEC_5_6; 507 lpval = ZL10353_TPS_LP_FEC_5_6; 508 break; 509 510 case FEC_7_8: 511 hpval = ZL10353_TPS_HP_FEC_7_8; 512 lpval = ZL10353_TPS_LP_FEC_7_8; 513 break; 514 515 case FEC_AUTO: 516 hpval = ZL10353_TPS_HP_FEC_AUTO; 517 lpval = ZL10353_TPS_LP_FEC_AUTO; 518 break; 519 520 case FEC_NONE: 521 return EOPNOTSUPP; 522 523 default: 524 return EINVAL; 525 } 526 527 *valp |= (hp != false) ? hpval : lpval; 528 529 return 0; 530} 531 532static int 533zl10353_get_modulation(fe_modulation_t fm, uint16_t *valp) 534{ 535 536 switch (fm) { 537 538 case QPSK: 539 *valp |= ZL10353_TPS_MODULATION_QPSK; 540 break; 541 542 case QAM_16: 543 *valp |= ZL10353_TPS_MODULATION_QAM_16; 544 break; 545 546 case QAM_64: 547 *valp |= ZL10353_TPS_MODULATION_QAM_64; 548 break; 549 550 case QAM_AUTO: 551 *valp |= ZL10353_TPS_MODULATION_QAM_AUTO; 552 break; 553 554 default: 555 return EINVAL; 556 } 557 558 return 0; 559} 560 561static int 562zl10353_get_hier(fe_hierarchy_t fh, uint16_t *valp) 563{ 564 565 switch (fh) { 566 567 case HIERARCHY_1: 568 *valp |= ZL10353_TPS_HIERARCHY_1; 569 break; 570 571 case HIERARCHY_2: 572 *valp |= ZL10353_TPS_HIERARCHY_2; 573 break; 574 575 case HIERARCHY_4: 576 *valp |= ZL10353_TPS_HIERARCHY_4; 577 break; 578 579 case HIERARCHY_NONE: 580 *valp |= ZL10353_TPS_HIERARCHY_NONE; 581 break; 582 583 case HIERARCHY_AUTO: 584 *valp |= ZL10353_TPS_HIERARCHY_AUTO; 585 break; 586 587 default: 588 return EINVAL; 589 } 590 591 return 0; 592} 593 594fe_status_t 595zl10353_get_status(struct zl10353 *zl) 596{ 597 const uint8_t lock = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC; 598 fe_status_t fs = 0; 599 uint8_t val; 600 601 if (zl10353_read(zl, ZL10353_REG_STATUS_LOCK, &val) == 0) { 602 603 if ((val & ZL10353_STATUS_LOCK_ON) != 0) 604 fs |= FE_HAS_LOCK; 605 606 if ((val & ZL10353_STATUS_LOCK_CARRIER) != 0) 607 fs |= FE_HAS_CARRIER; 608 609 if ((val & ZL10353_STATUS_LOCK_VITERBI) != 0) 610 fs |= FE_HAS_VITERBI; 611 } 612 613 if (zl10353_read(zl, ZL10353_REG_STATUS_SYNC, &val) == 0) { 614 615 if ((val & ZL10353_STATUS_SYNC_ON) != 0) 616 fs |= FE_HAS_SYNC; 617 } 618 619 if (zl10353_read(zl, ZL10353_REG_STATUS_SIGNAL, &val) == 0) { 620 621 if ((val & ZL10353_STATUS_SIGNAL_ON) != 0) 622 fs |= FE_HAS_SIGNAL; 623 } 624 625 return ((fs & lock) != lock) ? fs & ~FE_HAS_LOCK : fs; 626}; 627 628uint16_t 629zl10353_get_signal_strength(struct zl10353 *zl) 630{ 631 uint8_t val1, val2; 632 633 if (zl10353_read(zl, ZL10353_REG_SIGSTR_1, &val1) != 0) 634 return 0; 635 636 if (zl10353_read(zl, ZL10353_REG_SIGSTR_2, &val2) != 0) 637 return 0; 638 639 return val1 << 10 | val2 << 2 | 0x03; 640} 641 642uint16_t 643zl10353_get_snr(struct zl10353 *zl) 644{ 645 uint8_t val; 646 647 if (zl10353_read(zl, ZL10353_REG_SNR, &val) != 0) 648 return 0; 649 650 return (val << 8) | val; 651} 652 653MODULE(MODULE_CLASS_DRIVER, zl10353, "iic"); 654 655static int 656zl10353_modcmd(modcmd_t cmd, void *aux) 657{ 658 659 if (cmd != MODULE_CMD_INIT && cmd != MODULE_CMD_FINI) 660 return ENOTTY; 661 662 return 0; 663} 664