⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stv0297_cs2.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 2 页
字号:
	state->lastber = 0;	if (state->config->pll_init)		state->config->pll_init(fe);	return 0;}static void stv0297_set_initdemod(struct stv0297_state *state, s32 offset){	u16 initdemod = div64( (s64) (state->config->demodfreq - offset) << 16 , state->config->fclk);	u8 initdem[6];	deb_calc("demodfreq: %d, offset: %d, fclk: %d, initdemod: %d (%x)\n",			state->config->demodfreq, offset, state->config->fclk, initdemod, initdemod);	initdem[0] =  initdemod       & 0xff;	initdem[1] = (initdemod >> 8) & 0xff;	initdem[2] = 0x00;	initdem[3] = 0x00;	initdem[4] = 0x40;	initdem[5] = 0x88;	stv0297_writeregsI(state,INITDEM_0, initdem,6);}#define try(expr,num,sleep) \	for (i = 0; i < (num) && !(expr); i++) msleep(sleep);static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p){	struct stv0297_state *state = fe->demodulator_priv;	int i;	u8 equ_save[2];	fe_spectral_inversion_t inversion;	switch (p->inversion) {		case INVERSION_AUTO: /* fall through wanted */		case INVERSION_OFF:			inversion = state->invert ? INVERSION_ON : INVERSION_OFF;			break;		case INVERSION_ON:			inversion = state->invert ? INVERSION_OFF : INVERSION_ON;			break;		default:			return -EINVAL;	}	deb_info("spectrum inversion: %s\n",inversion == INVERSION_ON ? "on" : "off");	stv0297_reset(fe);	state->config->pll_set(fe, p);/* clear software interrupts */	stv0297_writeregI(state, CTRL_2, 0x00);/* set initial demodulation frequency */	stv0297_set_initdemod(state, 0);/* setup AGC */	stv0297_writeregI(state, WBAGC_3, 0x00);/* Wide Band AGC agc2sd initialisation: mid-range */	stv0297_writeregI(state, WBAGC_1, 0x00);//	stv0297_writereg_maskI(state, WBAGC_2, 0x03, 0x01);/* Wide Band AGC1&AGC2 nofreeze */	stv0297_writereg_maskI(state, DELAGC_6, 0x7f, 0x00);/* PMF AGC accumulator reset */	stv0297_writereg_maskI(state, PMFAGC_1, 0x80, 0x80);	stv0297_writeregI(state, PMFAGC_2, 0x00);	stv0297_writeregI(state, PMFAGC_3, 0x00);	stv0297_writereg_maskI(state, PMFAGC_4, 0x7f, 0x00);/* Force AGC ACQ low */	stv0297_writereg_maskI(state, WBAGC_3, 0x08, 0x00);/* Disable unlock forcing. */	stv0297_writereg_maskI(state, PMFAGC_1, 0x80, 0x00);/* setup STL * Phase clear */	stv0297_writereg_maskI(state, ST_LOOP10, 0x20, 0x20);/* STL integral path clear */	stv0297_writereg_maskI(state, ST_LOOP11, 0x02, 0x02);/* STL integral path clear release */	stv0297_writereg_maskI(state, ST_LOOP11, 0x02, 0x00);/* integral path enabled only */	stv0297_writereg_maskI(state, ST_LOOP11, 0x01, 0x00);/* direct path immediatly enabled */	stv0297_writereg_maskI(state, ST_LOOP10, 0x40, 0x40);/* disable frequency sweep */	stv0297_writereg_maskI(state, CRL_10, 0x01, 0x00);/* reset deinterleaver */	stv0297_writereg_maskI(state, CTRL_1, 0x01, 0x01);	stv0297_writereg_maskI(state, CTRL_1, 0x01, 0x00);/* ??? */	stv0297_writereg_maskI(state, CTRL_3, 0x20, 0x20);	stv0297_writereg_maskI(state, CTRL_3, 0x20, 0x00);/* Reed-Salomon clear */	stv0297_writereg_maskI(state, CTRL_3, 0x10, 0x10);	stv0297_writereg_maskI(state, CTRL_3, 0x10, 0x00);/* Equalizer values capture */	stv0297_readregsI(state, EQU_0, equ_save, 2);/* reset equalizer */	stv0297_writereg_maskI(state, CTRL_4, 0x01, 0x01);	stv0297_writereg_maskI(state, CTRL_4, 0x01, 0x00);/* Equalizer values restore */	stv0297_writeregsI(state, EQU_0, equ_save, 2);/* data comes from internal A/D */	stv0297_writereg_maskI(state, CTRL_7, 0x80, 0x00);/* set parameters */	stv0297_set_modulation(state, p->u.qam.modulation);	stv0297_set_symbolrate(state, p->u.qam.symbol_rate);	stv0297_set_crl(state, p, -130000);	stv0297_set_inversion(state, inversion);	stv0297_writereg_maskI(state, EQU_0, 0x0f, 0x09);	stv0297_writeregI(state, EQU_1, 0x69);/* only disable corner detection for QAM256 and QAM128, otherwise, enable it */	if (p->u.qam.modulation == QAM_256 ||		p->u.qam.modulation == QAM_128)		stv0297_writereg_maskI(state, CTRL_8, 0x08, 0x00);	else		stv0297_writereg_maskI(state, CTRL_8, 0x08, 0x08);/* Phase clear release */	stv0297_writereg_maskI(state, ST_LOOP10, 0x20, 0x00);/* Sweep Enable */	stv0297_writereg_maskI(state, CRL_10, 0x01, 0x01);	msleep(10);/*  Clear wide band AGC */	stv0297_writereg_maskI(state, WBAGC_3, 0x40, 0x40);/* enable wide band AGC */	stv0297_writereg_maskI(state, WBAGC_3, 0x10, WAGC_EN);	deb_info("initialized - waiting for the locks now\n");	/* wait for WBAGC lock */	deb_info("waiting for WBAGC lock\n");	try(stv0297_readregI(state, WBAGC_3) & 0x08, 200, 10);	if (i == 200)		goto timeout;	deb_info("WBAGC has lock\n");	msleep(20);	/* wait for equalizer 1 lock */	deb_info("waiting for equalizer 1 lock\n");	try(stv0297_readregI(state, CTRL_2) & 0x04, 400, 10);	if (i == 400)		goto timeout;	deb_info("equalizer 1 has lock\n");	/* wait for equalizer 2 lock and if it's stable */	deb_info("waiting for equalizer 2 lock\n");	try(stv0297_readregI(state, CTRL_2) & 0x08, 200, 10);	if (i == 200)		goto timeout;	deb_info("equalizer 2 has lock\n");	msleep(20);	if (!(stv0297_readregI(state, CTRL_2) & 0x08))		goto timeout;	deb_info("equalizer 2 is stable\n");	/* we have modulation, do we have data */	deb_info("waiting for data lock\n");	try(stv0297_readregI(state,RS_DESC_15) & 0x80,5,10);	if (i == 5) { /* try to invert the inversion during the next run */		deb_info("no data lock achieved, trying to invert the spectrum in the next run.\n");		state->invert = !state->invert;		goto timeout;	}	deb_info("we have data lock\n");/*  Turn off corner detection */	stv0297_writereg_maskI(state, CTRL_8,0x08, 0x00);	/* success!! */	state->base_freq = p->frequency;	return 0;timeout:	deb_info("timed out\n");	stv0297_writereg_maskI(state, CRL_10, 0x01, 0x00);	return 0;}static int stv0297_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p){	struct stv0297_state *state = fe->demodulator_priv;	int reg_00, reg_83;	reg_00 = stv0297_readregI(state, EQU_0);	reg_83 = stv0297_readregI(state, CTRL_3);	p->frequency = state->base_freq;	if (reg_83 & 0x08)		p->inversion = INVERSION_ON;	else		p->inversion = INVERSION_OFF;	p->u.qam.symbol_rate = stv0297_get_symbolrate(state);	p->u.qam.fec_inner = FEC_NONE;	switch (reg_00 & 0x70) {		case STV0297_QAM16:			p->u.qam.modulation = QAM_16;			break;		case STV0297_QAM32:			p->u.qam.modulation = QAM_32;			break;		case STV0297_QAM128:			p->u.qam.modulation = QAM_128;			break;		case STV0297_QAM256:			p->u.qam.modulation = QAM_256;			break;		case STV0297_QAM64:			p->u.qam.modulation = QAM_64;			break;	}	return 0;}static int stv0297_sleep(struct dvb_frontend *fe){	struct stv0297_state *state = fe->demodulator_priv;	deb_info("stv0297 is going to bed.\n");	stv0297_writereg_maskI(state, CTRL_0, 1, 1);	return 0;}static int stv0297_read_status(struct dvb_frontend *fe, fe_status_t * status){	struct stv0297_state *state = fe->demodulator_priv;	u8 ctrl_2 = stv0297_readregI(state, CTRL_2);	*status = 0;/* The following status assignments are only guesses, but we wanted to have a * kind of grade here */	if (stv0297_readregI(state, WBAGC_3) & 0x08)		*status |= FE_HAS_SIGNAL;	if (ctrl_2 & 0x04)		 *status |= FE_HAS_CARRIER;	if (ctrl_2 & 0x08)		*status |= FE_HAS_VITERBI;	if (stv0297_readregI(state, RS_DESC_15) & 0x80)		*status |= FE_HAS_SYNC | FE_HAS_LOCK;	return 0;}static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength){	struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;	u8 STRENGTH[2];	stv0297_readregsI(state, WBAGC_1, STRENGTH, 2);	*strength = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0];	return 0;}static int stv0297_read_snr(struct dvb_frontend *fe, u16 * snr){	struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;	u8 SNR[2];	stv0297_readregsI(state, EQU_7, SNR, 2);	*snr = SNR[1] << 8 | SNR[0];	return 0;}static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber){	struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;	u8 BER[3];	*ber = 0;	stv0297_readregsI(state, BERT_0, BER, 3);	if (!(BER[0] & 0x80)) {		state->lastber = (BER[0] & 0x07 << 16) | (BER[2] << 8) | BER[1];		/* reset the BER counter */		BER[0] |= 0x80;		BER[1] = BER[2] = 0x00;		stv0297_writeregsI(state, BERT_0, BER, 3);	}	*ber = state->lastber;	return 0;}static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks){	struct stv0297_state *state = fe->demodulator_priv;	u8 block_count[6];	stv0297_writeregI(state,RS_DESC_15,0x03); /* freeze the counters */	stv0297_readregsI(state,RS_DESC_0,block_count,6);	stv0297_writeregI(state,RS_DESC_15,0x02); /* clear the counters */	stv0297_writeregI(state,RS_DESC_15,0x01); /* re-enable the counters *//*	LastBlockCount          = (block_count[1] << 8) | block_count[0]; *//*	LastCorrectedBlockCount = (block_count[3] << 8) | block_count[2]; */	*ucblocks               = (block_count[5] << 8) | block_count[4];	return 0;}static void stv0297_release(struct dvb_frontend *fe){	struct stv0297_state *state = fe->demodulator_priv;	kfree(state);}static struct dvb_frontend_ops stv0297_ops;struct dvb_frontend *stv0297_cs2_attach(const struct stv0297_config *config,				    struct i2c_adapter *i2c){	struct stv0297_state *state = NULL;	/* allocate memory for the internal state */	state = kmalloc(sizeof(struct stv0297_state), GFP_KERNEL);	if (state == NULL)		goto error;	/* setup the state */	state->config = config;	state->i2c = i2c;	memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));	state->base_freq = 0;	/* check if the demod is there */	if ((stv0297_readregI(state, CTRL_0) & 0x70) != 0x20)		goto error;	/* create dvb_frontend */	state->frontend.ops = &state->ops;	state->frontend.demodulator_priv = state;	return &state->frontend;error:	kfree(state);	return NULL;}static struct dvb_frontend_ops stv0297_ops = {	.info = {		 .name = "ST STV0297 DVB-C",		 .type = FE_QAM,		 .frequency_min = 64000000,		 .frequency_max = 1300000000,		 .frequency_stepsize = 62500,		 .symbol_rate_min = 870000,		 .symbol_rate_max = 11700000,		 .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |		 FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO},	.release = stv0297_release,	.init = stv0297_init,	.sleep = stv0297_sleep,	.set_frontend = stv0297_set_frontend,	.get_frontend = stv0297_get_frontend,	.read_status = stv0297_read_status,	.read_ber = stv0297_read_ber,	.read_signal_strength = stv0297_read_signal_strength,	.read_snr = stv0297_read_snr,	.read_ucblocks = stv0297_read_ucblocks,};MODULE_DESCRIPTION("ST STV0297 DVB-C Demodulator driver");MODULE_AUTHOR("Dennis Noermann, Andrew de Quincey and Patrick Boettcher");MODULE_LICENSE("GPL");MODULE_VERSION("1.0");EXPORT_SYMBOL(stv0297_cs2_attach);EXPORT_SYMBOL(stv0297_cs2_enable_plli2c);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -