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

📄 tda10086.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	case FEC_6_7:		fecval = 0x05;		break;	case FEC_7_8:		fecval = 0x06;		break;	case FEC_8_9:		fecval = 0x07;		break;	case FEC_AUTO:		fecval = 0x08;		break;	default:		return -1;	}	tda10086_write_byte(state, 0x0d, fecval);	return 0;}static int tda10086_set_frontend(struct dvb_frontend* fe,				 struct dvb_frontend_parameters *fe_params){	struct tda10086_state *state = fe->demodulator_priv;	int ret;	u32 freq = 0;	int freqoff;	dprintk ("%s\n", __FUNCTION__);	// modify parameters for tuning	tda10086_write_byte(state, 0x02, 0x35);	state->has_lock = false;	// set params	if (fe->ops.tuner_ops.set_params) {		fe->ops.tuner_ops.set_params(fe, fe_params);		if (fe->ops.i2c_gate_ctrl)			fe->ops.i2c_gate_ctrl(fe, 0);		if (fe->ops.tuner_ops.get_frequency)			fe->ops.tuner_ops.get_frequency(fe, &freq);		if (fe->ops.i2c_gate_ctrl)			fe->ops.i2c_gate_ctrl(fe, 0);	}	// calcluate the frequency offset (in *Hz* not kHz)	freqoff = fe_params->frequency - freq;	freqoff = ((1<<16) * freqoff) / (SACLK/1000);	tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));	tda10086_write_byte(state, 0x3e, freqoff);	if ((ret = tda10086_set_inversion(state, fe_params)) < 0)		return ret;	if ((ret = tda10086_set_symbol_rate(state, fe_params)) < 0)		return ret;	if ((ret = tda10086_set_fec(state, fe_params)) < 0)		return ret;	// soft reset + disable TS output until lock	tda10086_write_mask(state, 0x10, 0x40, 0x40);	tda10086_write_mask(state, 0x00, 0x01, 0x00);	state->symbol_rate = fe_params->u.qpsk.symbol_rate;	state->frequency = fe_params->frequency;	return 0;}static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params){	struct tda10086_state* state = fe->demodulator_priv;	u8 val;	int tmp;	u64 tmp64;	dprintk ("%s\n", __FUNCTION__);	// check for invalid symbol rate	if (fe_params->u.qpsk.symbol_rate < 500000)		return -EINVAL;	// calculate the updated frequency (note: we convert from Hz->kHz)	tmp64 = tda10086_read_byte(state, 0x52);	tmp64 |= (tda10086_read_byte(state, 0x51) << 8);	if (tmp64 & 0x8000)		tmp64 |= 0xffffffffffff0000ULL;	tmp64 = (tmp64 * (SACLK/1000ULL));	do_div(tmp64, (1ULL<<15) * (1ULL<<1));	fe_params->frequency = (int) state->frequency + (int) tmp64;	// the inversion	val = tda10086_read_byte(state, 0x0c);	if (val & 0x80) {		switch(val & 0x40) {		case 0x00:			fe_params->inversion = INVERSION_OFF;			if (state->config->invert)				fe_params->inversion = INVERSION_ON;			break;		default:			fe_params->inversion = INVERSION_ON;			if (state->config->invert)				fe_params->inversion = INVERSION_OFF;			break;		}	} else {		tda10086_read_byte(state, 0x0f);		switch(val & 0x02) {		case 0x00:			fe_params->inversion = INVERSION_OFF;			if (state->config->invert)				fe_params->inversion = INVERSION_ON;			break;		default:			fe_params->inversion = INVERSION_ON;			if (state->config->invert)				fe_params->inversion = INVERSION_OFF;			break;		}	}	// calculate the updated symbol rate	tmp = tda10086_read_byte(state, 0x1d);	if (tmp & 0x80)		tmp |= 0xffffff00;	tmp = (tmp * 480 * (1<<1)) / 128;	tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);	fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;	// the FEC	val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;	switch(val) {	case 0x00:		fe_params->u.qpsk.fec_inner = FEC_1_2;		break;	case 0x01:		fe_params->u.qpsk.fec_inner = FEC_2_3;		break;	case 0x02:		fe_params->u.qpsk.fec_inner = FEC_3_4;		break;	case 0x03:		fe_params->u.qpsk.fec_inner = FEC_4_5;		break;	case 0x04:		fe_params->u.qpsk.fec_inner = FEC_5_6;		break;	case 0x05:		fe_params->u.qpsk.fec_inner = FEC_6_7;		break;	case 0x06:		fe_params->u.qpsk.fec_inner = FEC_7_8;		break;	case 0x07:		fe_params->u.qpsk.fec_inner = FEC_8_9;		break;	}	return 0;}static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status){	struct tda10086_state* state = fe->demodulator_priv;	u8 val;	dprintk ("%s\n", __FUNCTION__);	val = tda10086_read_byte(state, 0x0e);	*fe_status = 0;	if (val & 0x01)		*fe_status |= FE_HAS_SIGNAL;	if (val & 0x02)		*fe_status |= FE_HAS_CARRIER;	if (val & 0x04)		*fe_status |= FE_HAS_VITERBI;	if (val & 0x08)		*fe_status |= FE_HAS_SYNC;	if (val & 0x10) {		*fe_status |= FE_HAS_LOCK;		if (!state->has_lock) {			state->has_lock = true;			// modify parameters for stable reception			tda10086_write_byte(state, 0x02, 0x00);		}	}	return 0;}static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal){	struct tda10086_state* state = fe->demodulator_priv;	u8 _str;	dprintk ("%s\n", __FUNCTION__);	_str = 0xff - tda10086_read_byte(state, 0x43);	*signal = (_str << 8) | _str;	return 0;}static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr){	struct tda10086_state* state = fe->demodulator_priv;	u8 _snr;	dprintk ("%s\n", __FUNCTION__);	_snr = 0xff - tda10086_read_byte(state, 0x1c);	*snr = (_snr << 8) | _snr;	return 0;}static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks){	struct tda10086_state* state = fe->demodulator_priv;	dprintk ("%s\n", __FUNCTION__);	// read it	*ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;	// reset counter	tda10086_write_byte(state, 0x18, 0x00);	tda10086_write_byte(state, 0x18, 0x80);	return 0;}static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber){	struct tda10086_state* state = fe->demodulator_priv;	dprintk ("%s\n", __FUNCTION__);	// read it	*ber = 0;	*ber |= tda10086_read_byte(state, 0x15);	*ber |= tda10086_read_byte(state, 0x16) << 8;	*ber |= (tda10086_read_byte(state, 0x17) & 0xf) << 16;	return 0;}static int tda10086_sleep(struct dvb_frontend* fe){	struct tda10086_state* state = fe->demodulator_priv;	dprintk ("%s\n", __FUNCTION__);	tda10086_write_mask(state, 0x00, 0x08, 0x08);	return 0;}static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable){	struct tda10086_state* state = fe->demodulator_priv;	dprintk ("%s\n", __FUNCTION__);	if (enable) {		tda10086_write_mask(state, 0x00, 0x10, 0x10);	} else {		tda10086_write_mask(state, 0x00, 0x10, 0x00);	}	return 0;}static int tda10086_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings){	if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {		fesettings->min_delay_ms = 50;		fesettings->step_size = 2000;		fesettings->max_drift = 8000;	} else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {		fesettings->min_delay_ms = 100;		fesettings->step_size = 1500;		fesettings->max_drift = 9000;	} else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {		fesettings->min_delay_ms = 100;		fesettings->step_size = 1000;		fesettings->max_drift = 8000;	} else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {		fesettings->min_delay_ms = 100;		fesettings->step_size = 500;		fesettings->max_drift = 7000;	} else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {		fesettings->min_delay_ms = 200;		fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);		fesettings->max_drift = 14 * fesettings->step_size;	} else {		fesettings->min_delay_ms = 200;		fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);		fesettings->max_drift = 18 * fesettings->step_size;	}	return 0;}static void tda10086_release(struct dvb_frontend* fe){	struct tda10086_state *state = fe->demodulator_priv;	tda10086_sleep(fe);	kfree(state);}static struct dvb_frontend_ops tda10086_ops = {	.info = {		.name     = "Philips TDA10086 DVB-S",		.type     = FE_QPSK,		.frequency_min    = 950000,		.frequency_max    = 2150000,		.frequency_stepsize = 125,     /* kHz for QPSK frontends */		.symbol_rate_min  = 1000000,		.symbol_rate_max  = 45000000,		.caps = FE_CAN_INVERSION_AUTO |			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |			FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |			FE_CAN_QPSK	},	.release = tda10086_release,	.init = tda10086_init,	.sleep = tda10086_sleep,	.i2c_gate_ctrl = tda10086_i2c_gate_ctrl,	.set_frontend = tda10086_set_frontend,	.get_frontend = tda10086_get_frontend,	.get_tune_settings = tda10086_get_tune_settings,	.read_status = tda10086_read_status,	.read_ber = tda10086_read_ber,	.read_signal_strength = tda10086_read_signal_strength,	.read_snr = tda10086_read_snr,	.read_ucblocks = tda10086_read_ucblocks,	.diseqc_send_master_cmd = tda10086_send_master_cmd,	.diseqc_send_burst = tda10086_send_burst,	.set_tone = tda10086_set_tone,};struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,				     struct i2c_adapter* i2c){	struct tda10086_state *state;	dprintk ("%s\n", __FUNCTION__);	/* allocate memory for the internal state */	state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);	if (!state)		return NULL;	/* setup the state */	state->config = config;	state->i2c = i2c;	/* check if the demod is there */	if (tda10086_read_byte(state, 0x1e) != 0xe1) {		kfree(state);		return NULL;	}	/* create dvb_frontend */	memcpy(&state->frontend.ops, &tda10086_ops, sizeof(struct dvb_frontend_ops));	state->frontend.demodulator_priv = state;	return &state->frontend;}module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");MODULE_DESCRIPTION("Philips TDA10086 DVB-S Demodulator");MODULE_AUTHOR("Andrew de Quincey");MODULE_LICENSE("GPL");EXPORT_SYMBOL(tda10086_attach);

⌨️ 快捷键说明

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