1 /* 2 NxtWave Communications - NXT6000 demodulator driver 3 4 Copyright (C) 2002-2003 Florian Schirmer <jolt@tuxbox.org> 5 Copyright (C) 2003 Paul Andreassen <paul@andreassen.com.au> 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 23 24 #include <linux/init.h> 25 #include <linux/kernel.h> 26 #include <linux/module.h> 27 #include <linux/string.h> 28 #include <linux/slab.h> 29 30 #include <media/dvb_frontend.h> 31 #include "nxt6000_priv.h" 32 #include "nxt6000.h" 33 34 35 36 struct nxt6000_state { 37 struct i2c_adapter* i2c; 38 /* configuration settings */ 39 const struct nxt6000_config* config; 40 struct dvb_frontend frontend; 41 }; 42 43 static int debug; 44 #define dprintk(fmt, arg...) do { \ 45 if (debug) \ 46 printk(KERN_DEBUG pr_fmt("%s: " fmt), \ 47 __func__, ##arg); \ 48 } while (0) 49 50 static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data) 51 { 52 u8 buf[] = { reg, data }; 53 struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 }; 54 int ret; 55 56 if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) 57 dprintk("nxt6000: nxt6000_write error (reg: 0x%02X, data: 0x%02X, ret: %d)\n", reg, data, ret); 58 59 return (ret != 1) ? -EIO : 0; 60 } 61 62 static u8 nxt6000_readreg(struct nxt6000_state* state, u8 reg) 63 { 64 int ret; 65 u8 b0[] = { reg }; 66 u8 b1[] = { 0 }; 67 struct i2c_msg msgs[] = { 68 {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1}, 69 {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1} 70 }; 71 72 ret = i2c_transfer(state->i2c, msgs, 2); 73 74 if (ret != 2) 75 dprintk("nxt6000: nxt6000_read error (reg: 0x%02X, ret: %d)\n", reg, ret); 76 77 return b1[0]; 78 } 79 80 static void nxt6000_reset(struct nxt6000_state* state) 81 { 82 u8 val; 83 84 val = nxt6000_readreg(state, OFDM_COR_CTL); 85 86 nxt6000_writereg(state, OFDM_COR_CTL, val & ~COREACT); 87 nxt6000_writereg(state, OFDM_COR_CTL, val | COREACT); 88 } 89 90 static int nxt6000_set_bandwidth(struct nxt6000_state *state, u32 bandwidth) 91 { 92 u16 nominal_rate; 93 int result; 94 95 switch (bandwidth) { 96 case 6000000: 97 nominal_rate = 0x55B7; 98 break; 99 100 case 7000000: 101 nominal_rate = 0x6400; 102 break; 103 104 case 8000000: 105 nominal_rate = 0x7249; 106 break; 107 108 default: 109 return -EINVAL; 110 } 111 112 if ((result = nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0) 113 return result; 114 115 return nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF); 116 } 117 118 static int nxt6000_set_guard_interval(struct nxt6000_state *state, 119 enum fe_guard_interval guard_interval) 120 { 121 switch (guard_interval) { 122 123 case GUARD_INTERVAL_1_32: 124 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); 125 126 case GUARD_INTERVAL_1_16: 127 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); 128 129 case GUARD_INTERVAL_AUTO: 130 case GUARD_INTERVAL_1_8: 131 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); 132 133 case GUARD_INTERVAL_1_4: 134 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03)); 135 136 default: 137 return -EINVAL; 138 } 139 } 140 141 static int nxt6000_set_inversion(struct nxt6000_state *state, 142 enum fe_spectral_inversion inversion) 143 { 144 switch (inversion) { 145 146 case INVERSION_OFF: 147 return nxt6000_writereg(state, OFDM_ITB_CTL, 0x00); 148 149 case INVERSION_ON: 150 return nxt6000_writereg(state, OFDM_ITB_CTL, ITBINV); 151 152 default: 153 return -EINVAL; 154 155 } 156 } 157 158 static int 159 nxt6000_set_transmission_mode(struct nxt6000_state *state, 160 enum fe_transmit_mode transmission_mode) 161 { 162 int result; 163 164 switch (transmission_mode) { 165 166 case TRANSMISSION_MODE_2K: 167 if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0) 168 return result; 169 170 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04)); 171 172 case TRANSMISSION_MODE_8K: 173 case TRANSMISSION_MODE_AUTO: 174 if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0) 175 return result; 176 177 return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04)); 178 179 default: 180 return -EINVAL; 181 182 } 183 } 184 185 static void nxt6000_setup(struct dvb_frontend* fe) 186 { 187 struct nxt6000_state* state = fe->demodulator_priv; 188 189 nxt6000_writereg(state, RS_COR_SYNC_PARAM, SYNC_PARAM); 190 nxt6000_writereg(state, BER_CTRL, /*(1 << 2) | */ (0x01 << 1) | 0x01); 191 nxt6000_writereg(state, VIT_BERTIME_2, 0x00); // BER Timer = 0x000200 * 256 = 131072 bits 192 nxt6000_writereg(state, VIT_BERTIME_1, 0x02); // 193 nxt6000_writereg(state, VIT_BERTIME_0, 0x00); // 194 nxt6000_writereg(state, VIT_COR_INTEN, 0x98); // Enable BER interrupts 195 nxt6000_writereg(state, VIT_COR_CTL, 0x82); // Enable BER measurement 196 nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC | 0x02 ); 197 nxt6000_writereg(state, OFDM_COR_CTL, (0x01 << 5) | (nxt6000_readreg(state, OFDM_COR_CTL) & 0x0F)); 198 nxt6000_writereg(state, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02); 199 nxt6000_writereg(state, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW); 200 nxt6000_writereg(state, OFDM_ITB_FREQ_1, 0x06); 201 nxt6000_writereg(state, OFDM_ITB_FREQ_2, 0x31); 202 nxt6000_writereg(state, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04); 203 nxt6000_writereg(state, CAS_FREQ, 0xBB); /* CHECKME */ 204 nxt6000_writereg(state, OFDM_SYR_CTL, 1 << 2); 205 nxt6000_writereg(state, OFDM_PPM_CTL_1, PPM256); 206 nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, 0x49); 207 nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, 0x72); 208 nxt6000_writereg(state, ANALOG_CONTROL_0, 1 << 5); 209 nxt6000_writereg(state, EN_DMD_RACQ, (1 << 7) | (3 << 4) | 2); 210 nxt6000_writereg(state, DIAG_CONFIG, TB_SET); 211 212 if (state->config->clock_inversion) 213 nxt6000_writereg(state, SUB_DIAG_MODE_SEL, CLKINVERSION); 214 else 215 nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0); 216 217 nxt6000_writereg(state, TS_FORMAT, 0); 218 } 219 220 static void nxt6000_dump_status(struct nxt6000_state *state) 221 { 222 u8 val; 223 224 #if 0 225 pr_info("RS_COR_STAT: 0x%02X\n", 226 nxt6000_readreg(fe, RS_COR_STAT)); 227 pr_info("VIT_SYNC_STATUS: 0x%02X\n", 228 nxt6000_readreg(fe, VIT_SYNC_STATUS)); 229 pr_info("OFDM_COR_STAT: 0x%02X\n", 230 nxt6000_readreg(fe, OFDM_COR_STAT)); 231 pr_info("OFDM_SYR_STAT: 0x%02X\n", 232 nxt6000_readreg(fe, OFDM_SYR_STAT)); 233 pr_info("OFDM_TPS_RCVD_1: 0x%02X\n", 234 nxt6000_readreg(fe, OFDM_TPS_RCVD_1)); 235 pr_info("OFDM_TPS_RCVD_2: 0x%02X\n", 236 nxt6000_readreg(fe, OFDM_TPS_RCVD_2)); 237 pr_info("OFDM_TPS_RCVD_3: 0x%02X\n", 238 nxt6000_readreg(fe, OFDM_TPS_RCVD_3)); 239 pr_info("OFDM_TPS_RCVD_4: 0x%02X\n", 240 nxt6000_readreg(fe, OFDM_TPS_RCVD_4)); 241 pr_info("OFDM_TPS_RESERVED_1: 0x%02X\n", 242 nxt6000_readreg(fe, OFDM_TPS_RESERVED_1)); 243 pr_info("OFDM_TPS_RESERVED_2: 0x%02X\n", 244 nxt6000_readreg(fe, OFDM_TPS_RESERVED_2)); 245 #endif 246 pr_info("NXT6000 status:"); 247 248 val = nxt6000_readreg(state, RS_COR_STAT); 249 250 pr_cont(" DATA DESCR LOCK: %d,", val & 0x01); 251 pr_cont(" DATA SYNC LOCK: %d,", (val >> 1) & 0x01); 252 253 val = nxt6000_readreg(state, VIT_SYNC_STATUS); 254 255 pr_cont(" VITERBI LOCK: %d,", (val >> 7) & 0x01); 256 257 switch ((val >> 4) & 0x07) { 258 259 case 0x00: 260 pr_cont(" VITERBI CODERATE: 1/2,"); 261 break; 262 263 case 0x01: 264 pr_cont(" VITERBI CODERATE: 2/3,"); 265 break; 266 267 case 0x02: 268 pr_cont(" VITERBI CODERATE: 3/4,"); 269 break; 270 271 case 0x03: 272 pr_cont(" VITERBI CODERATE: 5/6,"); 273 break; 274 275 case 0x04: 276 pr_cont(" VITERBI CODERATE: 7/8,"); 277 break; 278 279 default: 280 pr_cont(" VITERBI CODERATE: Reserved,"); 281 282 } 283 284 val = nxt6000_readreg(state, OFDM_COR_STAT); 285 286 pr_cont(" CHCTrack: %d,", (val >> 7) & 0x01); 287 pr_cont(" TPSLock: %d,", (val >> 6) & 0x01); 288 pr_cont(" SYRLock: %d,", (val >> 5) & 0x01); 289 pr_cont(" AGCLock: %d,", (val >> 4) & 0x01); 290 291 switch (val & 0x0F) { 292 293 case 0x00: 294 pr_cont(" CoreState: IDLE,"); 295 break; 296 297 case 0x02: 298 pr_cont(" CoreState: WAIT_AGC,"); 299 break; 300 301 case 0x03: 302 pr_cont(" CoreState: WAIT_SYR,"); 303 break; 304 305 case 0x04: 306 pr_cont(" CoreState: WAIT_PPM,"); 307 break; 308 309 case 0x01: 310 pr_cont(" CoreState: WAIT_TRL,"); 311 break; 312 313 case 0x05: 314 pr_cont(" CoreState: WAIT_TPS,"); 315 break; 316 317 case 0x06: 318 pr_cont(" CoreState: MONITOR_TPS,"); 319 break; 320 321 default: 322 pr_cont(" CoreState: Reserved,"); 323 324 } 325 326 val = nxt6000_readreg(state, OFDM_SYR_STAT); 327 328 pr_cont(" SYRLock: %d,", (val >> 4) & 0x01); 329 pr_cont(" SYRMode: %s,", (val >> 2) & 0x01 ? "8K" : "2K"); 330 331 switch ((val >> 4) & 0x03) { 332 333 case 0x00: 334 pr_cont(" SYRGuard: 1/32,"); 335 break; 336 337 case 0x01: 338 pr_cont(" SYRGuard: 1/16,"); 339 break; 340 341 case 0x02: 342 pr_cont(" SYRGuard: 1/8,"); 343 break; 344 345 case 0x03: 346 pr_cont(" SYRGuard: 1/4,"); 347 break; 348 } 349 350 val = nxt6000_readreg(state, OFDM_TPS_RCVD_3); 351 352 switch ((val >> 4) & 0x07) { 353 354 case 0x00: 355 pr_cont(" TPSLP: 1/2,"); 356 break; 357 358 case 0x01: 359 pr_cont(" TPSLP: 2/3,"); 360 break; 361 362 case 0x02: 363 pr_cont(" TPSLP: 3/4,"); 364 break; 365 366 case 0x03: 367 pr_cont(" TPSLP: 5/6,"); 368 break; 369 370 case 0x04: 371 pr_cont(" TPSLP: 7/8,"); 372 break; 373 374 default: 375 pr_cont(" TPSLP: Reserved,"); 376 377 } 378 379 switch (val & 0x07) { 380 381 case 0x00: 382 pr_cont(" TPSHP: 1/2,"); 383 break; 384 385 case 0x01: 386 pr_cont(" TPSHP: 2/3,"); 387 break; 388 389 case 0x02: 390 pr_cont(" TPSHP: 3/4,"); 391 break; 392 393 case 0x03: 394 pr_cont(" TPSHP: 5/6,"); 395 break; 396 397 case 0x04: 398 pr_cont(" TPSHP: 7/8,"); 399 break; 400 401 default: 402 pr_cont(" TPSHP: Reserved,"); 403 404 } 405 406 val = nxt6000_readreg(state, OFDM_TPS_RCVD_4); 407 408 pr_cont(" TPSMode: %s,", val & 0x01 ? "8K" : "2K"); 409 410 switch ((val >> 4) & 0x03) { 411 412 case 0x00: 413 pr_cont(" TPSGuard: 1/32,"); 414 break; 415 416 case 0x01: 417 pr_cont(" TPSGuard: 1/16,"); 418 break; 419 420 case 0x02: 421 pr_cont(" TPSGuard: 1/8,"); 422 break; 423 424 case 0x03: 425 pr_cont(" TPSGuard: 1/4,"); 426 break; 427 428 } 429 430 /* Strange magic required to gain access to RF_AGC_STATUS */ 431 nxt6000_readreg(state, RF_AGC_VAL_1); 432 val = nxt6000_readreg(state, RF_AGC_STATUS); 433 val = nxt6000_readreg(state, RF_AGC_STATUS); 434 435 pr_cont(" RF AGC LOCK: %d,", (val >> 4) & 0x01); 436 pr_cont("\n"); 437 } 438 439 static int nxt6000_read_status(struct dvb_frontend *fe, enum fe_status *status) 440 { 441 u8 core_status; 442 struct nxt6000_state* state = fe->demodulator_priv; 443 444 *status = 0; 445 446 core_status = nxt6000_readreg(state, OFDM_COR_STAT); 447 448 if (core_status & AGCLOCKED) 449 *status |= FE_HAS_SIGNAL; 450 451 if (nxt6000_readreg(state, OFDM_SYR_STAT) & GI14_SYR_LOCK) 452 *status |= FE_HAS_CARRIER; 453 454 if (nxt6000_readreg(state, VIT_SYNC_STATUS) & VITINSYNC) 455 *status |= FE_HAS_VITERBI; 456 457 if (nxt6000_readreg(state, RS_COR_STAT) & RSCORESTATUS) 458 *status |= FE_HAS_SYNC; 459 460 if ((core_status & TPSLOCKED) && (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))) 461 *status |= FE_HAS_LOCK; 462 463 if (debug) 464 nxt6000_dump_status(state); 465 466 return 0; 467 } 468 469 static int nxt6000_init(struct dvb_frontend* fe) 470 { 471 struct nxt6000_state* state = fe->demodulator_priv; 472 473 nxt6000_reset(state); 474 nxt6000_setup(fe); 475 476 return 0; 477 } 478 479 static int nxt6000_set_frontend(struct dvb_frontend *fe) 480 { 481 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 482 struct nxt6000_state* state = fe->demodulator_priv; 483 int result; 484 485 if (fe->ops.tuner_ops.set_params) { 486 fe->ops.tuner_ops.set_params(fe); 487 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); 488 } 489 490 result = nxt6000_set_bandwidth(state, p->bandwidth_hz); 491 if (result < 0) 492 return result; 493 494 result = nxt6000_set_guard_interval(state, p->guard_interval); 495 if (result < 0) 496 return result; 497 498 result = nxt6000_set_transmission_mode(state, p->transmission_mode); 499 if (result < 0) 500 return result; 501 502 result = nxt6000_set_inversion(state, p->inversion); 503 if (result < 0) 504 return result; 505 506 msleep(500); 507 return 0; 508 } 509 510 static void nxt6000_release(struct dvb_frontend* fe) 511 { 512 struct nxt6000_state* state = fe->demodulator_priv; 513 kfree(state); 514 } 515 516 static int nxt6000_read_snr(struct dvb_frontend* fe, u16* snr) 517 { 518 struct nxt6000_state* state = fe->demodulator_priv; 519 520 *snr = nxt6000_readreg( state, OFDM_CHC_SNR) / 8; 521 522 return 0; 523 } 524 525 static int nxt6000_read_ber(struct dvb_frontend* fe, u32* ber) 526 { 527 struct nxt6000_state* state = fe->demodulator_priv; 528 529 nxt6000_writereg( state, VIT_COR_INTSTAT, 0x18 ); 530 531 *ber = (nxt6000_readreg( state, VIT_BER_1 ) << 8 ) | 532 nxt6000_readreg( state, VIT_BER_0 ); 533 534 nxt6000_writereg( state, VIT_COR_INTSTAT, 0x18); // Clear BER Done interrupts 535 536 return 0; 537 } 538 539 static int nxt6000_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength) 540 { 541 struct nxt6000_state* state = fe->demodulator_priv; 542 543 *signal_strength = (short) (511 - 544 (nxt6000_readreg(state, AGC_GAIN_1) + 545 ((nxt6000_readreg(state, AGC_GAIN_2) & 0x03) << 8))); 546 547 return 0; 548 } 549 550 static int nxt6000_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) 551 { 552 tune->min_delay_ms = 500; 553 return 0; 554 } 555 556 static int nxt6000_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) 557 { 558 struct nxt6000_state* state = fe->demodulator_priv; 559 560 if (enable) { 561 return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); 562 } else { 563 return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); 564 } 565 } 566 567 static const struct dvb_frontend_ops nxt6000_ops; 568 569 struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, 570 struct i2c_adapter* i2c) 571 { 572 struct nxt6000_state* state = NULL; 573 574 /* allocate memory for the internal state */ 575 state = kzalloc(sizeof(struct nxt6000_state), GFP_KERNEL); 576 if (state == NULL) goto error; 577 578 /* setup the state */ 579 state->config = config; 580 state->i2c = i2c; 581 582 /* check if the demod is there */ 583 if (nxt6000_readreg(state, OFDM_MSC_REV) != NXT6000ASICDEVICE) goto error; 584 585 /* create dvb_frontend */ 586 memcpy(&state->frontend.ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops)); 587 state->frontend.demodulator_priv = state; 588 return &state->frontend; 589 590 error: 591 kfree(state); 592 return NULL; 593 } 594 595 static const struct dvb_frontend_ops nxt6000_ops = { 596 .delsys = { SYS_DVBT }, 597 .info = { 598 .name = "NxtWave NXT6000 DVB-T", 599 .frequency_min_hz = 0, 600 .frequency_max_hz = 863250 * kHz, 601 .frequency_stepsize_hz = 62500, 602 /*.frequency_tolerance = *//* FIXME: 12% of SR */ 603 .symbol_rate_min = 0, /* FIXME */ 604 .symbol_rate_max = 9360000, /* FIXME */ 605 .symbol_rate_tolerance = 4000, 606 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 607 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | 608 FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | 609 FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 610 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | 611 FE_CAN_HIERARCHY_AUTO, 612 }, 613 614 .release = nxt6000_release, 615 616 .init = nxt6000_init, 617 .i2c_gate_ctrl = nxt6000_i2c_gate_ctrl, 618 619 .get_tune_settings = nxt6000_fe_get_tune_settings, 620 621 .set_frontend = nxt6000_set_frontend, 622 623 .read_status = nxt6000_read_status, 624 .read_ber = nxt6000_read_ber, 625 .read_signal_strength = nxt6000_read_signal_strength, 626 .read_snr = nxt6000_read_snr, 627 }; 628 629 module_param(debug, int, 0644); 630 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 631 632 MODULE_DESCRIPTION("NxtWave NXT6000 DVB-T demodulator driver"); 633 MODULE_AUTHOR("Florian Schirmer"); 634 MODULE_LICENSE("GPL"); 635 636 EXPORT_SYMBOL(nxt6000_attach); 637