📄 nxt2002.c
字号:
buf[2] = 0x84 + (0x0E << 3); buf[3] = 0x08; } else { buf[2] = 0x84 + (0x0F << 3); buf[3] = 0x02; } /* write frequency information */ nxt2002_writetuner(state,buf); /* reset the agc now that tuning has been completed */ nxt2002_agc_reset(state); /* set target power level */ buf[0] = 0x70; i2c_writebytes(state,0x42,buf,1); /* configure sdm */ buf[0] = 0x87; i2c_writebytes(state,0x57,buf,1); /* write sdm1 input */ buf[0] = 0x10; buf[1] = 0x00; nxt2002_writereg_multibyte(state,0x58,buf,2); /* write sdmx input */ buf[0] = 0x60; buf[1] = 0x00; nxt2002_writereg_multibyte(state,0x5C,buf,2); /* write adc power lpf fc */ buf[0] = 0x05; i2c_writebytes(state,0x43,buf,1); /* write adc power lpf fc */ buf[0] = 0x05; i2c_writebytes(state,0x43,buf,1); /* write accumulator2 input */ buf[0] = 0x80; buf[1] = 0x00; nxt2002_writereg_multibyte(state,0x4B,buf,2); /* write kg1 */ buf[0] = 0x00; i2c_writebytes(state,0x4D,buf,1); /* write sdm12 lpf fc */ buf[0] = 0x44; i2c_writebytes(state,0x55,buf,1); /* write agc control reg */ buf[0] = 0x04; i2c_writebytes(state,0x41,buf,1); /* write agc ucgp0 */ buf[0] = 0x00; i2c_writebytes(state,0x30,buf,1); /* write agc control reg */ buf[0] = 0x00; i2c_writebytes(state,0x41,buf,1); /* write accumulator2 input */ buf[0] = 0x80; buf[1] = 0x00; nxt2002_writereg_multibyte(state,0x49,buf,2); nxt2002_writereg_multibyte(state,0x4B,buf,2); /* write agc control reg */ buf[0] = 0x04; i2c_writebytes(state,0x41,buf,1); nxt2002_microcontroller_start(state); /* adjacent channel detection should be done here, but I don't have any stations with this need so I cannot test it */ return 0;}static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status){ struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv; u8 lock; i2c_readbytes(state,0x31,&lock,1); *status = 0; if (lock & 0x20) { *status |= FE_HAS_SIGNAL; *status |= FE_HAS_CARRIER; *status |= FE_HAS_VITERBI; *status |= FE_HAS_SYNC; *status |= FE_HAS_LOCK; } return 0;}static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber){ struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv; u8 b[3]; nxt2002_readreg_multibyte(state,0xE6,b,3); *ber = ((b[0] << 8) + b[1]) * 8; return 0;}static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength){ struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv; u8 b[2]; u16 temp = 0; /* setup to read cluster variance */ b[0] = 0x00; i2c_writebytes(state,0xA1,b,1); /* get multreg val */ nxt2002_readreg_multibyte(state,0xA6,b,2); temp = (b[0] << 8) | b[1]; *strength = ((0x7FFF - temp) & 0x0FFF) * 16; return 0;}static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr){ struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv; u8 b[2]; u16 temp = 0, temp2; u32 snrdb = 0; /* setup to read cluster variance */ b[0] = 0x00; i2c_writebytes(state,0xA1,b,1); /* get multreg val from 0xA6 */ nxt2002_readreg_multibyte(state,0xA6,b,2); temp = (b[0] << 8) | b[1]; temp2 = 0x7FFF - temp; /* snr will be in db */ if (temp2 > 0x7F00) snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) ); else if (temp2 > 0x7EC0) snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) ); else if (temp2 > 0x7C00) snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) ); else snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) ); /* the value reported back from the frontend will be FFFF=32db 0000=0db */ *snr = snrdb * (0xFFFF/32000); return 0;}static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks){ struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv; u8 b[3]; nxt2002_readreg_multibyte(state,0xE6,b,3); *ucblocks = b[2]; return 0;}static int nxt2002_sleep(struct dvb_frontend* fe){ return 0;}static int nxt2002_init(struct dvb_frontend* fe){ struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv; const struct firmware *fw; int ret; u8 buf[2]; if (!state->initialised) { /* request the firmware, this will block until someone uploads it */ printk("nxt2002: Waiting for firmware upload...\n"); ret = state->config->request_firmware(fe, &fw, NXT2002_DEFAULT_FIRMWARE); printk("nxt2002: Waiting for firmware upload(2)...\n"); if (ret) { printk("nxt2002: no firmware upload (timeout or file not found?)\n"); return ret; } ret = nxt2002_load_firmware(fe, fw); if (ret) { printk("nxt2002: writing firmware to device failed\n"); release_firmware(fw); return ret; } /* Put the micro into reset */ nxt2002_microcontroller_stop(state); /* ensure transfer is complete */ buf[0]=0; i2c_writebytes(state,0x2B,buf,1); /* Put the micro into reset for real this time */ nxt2002_microcontroller_stop(state); /* soft reset everything (agc,frontend,eq,fec)*/ buf[0] = 0x0F; i2c_writebytes(state,0x08,buf,1); buf[0] = 0x00; i2c_writebytes(state,0x08,buf,1); /* write agc sdm configure */ buf[0] = 0xF1; i2c_writebytes(state,0x57,buf,1); /* write mod output format */ buf[0] = 0x20; i2c_writebytes(state,0x09,buf,1); /* write fec mpeg mode */ buf[0] = 0x7E; buf[1] = 0x00; i2c_writebytes(state,0xE9,buf,2); /* write mux selection */ buf[0] = 0x00; i2c_writebytes(state,0xCC,buf,1); state->initialised = 1; } return 0;}static int nxt2002_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings){ fesettings->min_delay_ms = 500; fesettings->step_size = 0; fesettings->max_drift = 0; return 0;}static void nxt2002_release(struct dvb_frontend* fe){ struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv; kfree(state);}static struct dvb_frontend_ops nxt2002_ops;struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config, struct i2c_adapter* i2c){ struct nxt2002_state* state = NULL; u8 buf [] = {0,0,0,0,0}; /* allocate memory for the internal state */ state = (struct nxt2002_state*) kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ state->config = config; state->i2c = i2c; memcpy(&state->ops, &nxt2002_ops, sizeof(struct dvb_frontend_ops)); state->initialised = 0; /* Check the first 5 registers to ensure this a revision we can handle */ i2c_readbytes(state, 0x00, buf, 5); if (buf[0] != 0x04) goto error; /* device id */ if (buf[1] != 0x02) goto error; /* fab id */ if (buf[2] != 0x11) goto error; /* month */ if (buf[3] != 0x20) goto error; /* year msb */ if (buf[4] != 0x00) goto error; /* year lsb */ /* create dvb_frontend */ state->frontend.ops = &state->ops; state->frontend.demodulator_priv = state; return &state->frontend;error: if (state) kfree(state); return NULL;}static struct dvb_frontend_ops nxt2002_ops = { .info = { .name = "Nextwave nxt2002 VSB/QAM frontend", .type = FE_ATSC, .frequency_min = 54000000, .frequency_max = 803000000, /* stepsize is just a guess */ .frequency_stepsize = 166666, .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_8VSB }, .release = nxt2002_release, .init = nxt2002_init, .sleep = nxt2002_sleep, .set_frontend = nxt2002_setup_frontend_parameters, .get_tune_settings = nxt2002_get_tune_settings, .read_status = nxt2002_read_status, .read_ber = nxt2002_read_ber, .read_signal_strength = nxt2002_read_signal_strength, .read_snr = nxt2002_read_snr, .read_ucblocks = nxt2002_read_ucblocks,};module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");MODULE_DESCRIPTION("NXT2002 ATSC (8VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");MODULE_AUTHOR("Taylor Jacob");MODULE_LICENSE("GPL");EXPORT_SYMBOL(nxt2002_attach);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -