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