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

📄 tda80xx.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		state->code_rate = fec_tab[val & 0x07];		if (state->status & (FE_HAS_SYNC | FE_HAS_LOCK))			state->spectral_inversion = inv_tab[(val >> 7) & 0x01];		else			state->spectral_inversion = INVERSION_AUTO;	}	else {		state->code_rate = FEC_AUTO;	}}static void tda80xx_worklet(void *priv){	struct tda80xx_state *state = priv;	tda80xx_writereg(state, 0x00, 0x04);	enable_irq(state->config->irq);	tda80xx_read_status_int(state);}static void tda80xx_wait_diseqc_fifo(struct tda80xx_state* state){	size_t i;	for (i = 0; i < 100; i++) {		if (tda80xx_readreg(state, 0x02) & 0x80)			break;		msleep(10);	}}static int tda8044_init(struct dvb_frontend* fe){	struct tda80xx_state* state = fe->demodulator_priv;	int ret;	/*	 * this function is a mess...	 */	if ((ret = tda80xx_write(state, 0x00, tda8044_inittab_pre, sizeof(tda8044_inittab_pre))))		return ret;	tda80xx_writereg(state, 0x0f, 0x50);#if 1	tda80xx_writereg(state, 0x20, 0x8F);		/* FIXME */	tda80xx_writereg(state, 0x20, state->config->volt18setting);	/* FIXME */	//tda80xx_writereg(state, 0x00, 0x04);	tda80xx_writereg(state, 0x00, 0x0C);#endif	//tda80xx_writereg(state, 0x00, 0x08); /* Reset AFC1 loop filter */	tda80xx_write(state, 0x00, tda8044_inittab_post, sizeof(tda8044_inittab_post));	if (state->config->pll_init) {		tda80xx_writereg(state, 0x1c, 0x80);		state->config->pll_init(fe);		tda80xx_writereg(state, 0x1c, 0x00);	}	return 0;}static int tda8083_init(struct dvb_frontend* fe){	struct tda80xx_state* state = fe->demodulator_priv;	tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab));	if (state->config->pll_init) {		tda80xx_writereg(state, 0x1c, 0x80);		state->config->pll_init(fe);		tda80xx_writereg(state, 0x1c, 0x00);	}	return 0;}static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage){	struct tda80xx_state* state = fe->demodulator_priv;	switch (voltage) {	case SEC_VOLTAGE_13:		return tda80xx_writereg(state, 0x20, state->config->volt13setting);	case SEC_VOLTAGE_18:		return tda80xx_writereg(state, 0x20, state->config->volt18setting);	case SEC_VOLTAGE_OFF:		return tda80xx_writereg(state, 0x20, 0);	default:		return -EINVAL;	}}static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone){	struct tda80xx_state* state = fe->demodulator_priv;	switch (tone) {	case SEC_TONE_OFF:		return tda80xx_writereg(state, 0x29, 0x00);	case SEC_TONE_ON:		return tda80xx_writereg(state, 0x29, 0x80);	default:		return -EINVAL;	}}static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd){	struct tda80xx_state* state = fe->demodulator_priv;	if (cmd->msg_len > 6)		return -EINVAL;	tda80xx_writereg(state, 0x29, 0x08 | (cmd->msg_len - 3));	tda80xx_write(state, 0x23, cmd->msg, cmd->msg_len);	tda80xx_writereg(state, 0x29, 0x0c | (cmd->msg_len - 3));	tda80xx_wait_diseqc_fifo(state);	return 0;}static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t cmd){	struct tda80xx_state* state = fe->demodulator_priv;	switch (cmd) {	case SEC_MINI_A:		tda80xx_writereg(state, 0x29, 0x14);		break;	case SEC_MINI_B:		tda80xx_writereg(state, 0x29, 0x1c);		break;	default:		return -EINVAL;	}	tda80xx_wait_diseqc_fifo(state);	return 0;}static int tda80xx_sleep(struct dvb_frontend* fe){	struct tda80xx_state* state = fe->demodulator_priv;	tda80xx_writereg(state, 0x00, 0x02);	/* enter standby */	return 0;}static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p){	struct tda80xx_state* state = fe->demodulator_priv;	tda80xx_writereg(state, 0x1c, 0x80);	state->config->pll_set(fe, p);	tda80xx_writereg(state, 0x1c, 0x00);	tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner);	tda80xx_set_clk(state);	//tda80xx_set_scpc_freq_offset(state);	state->afc_loop = 1;	return 0;}static int tda80xx_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p){	struct tda80xx_state* state = fe->demodulator_priv;	if (!state->config->irq)		tda80xx_read_status_int(state);	p->inversion = state->spectral_inversion;	p->u.qpsk.fec_inner = state->code_rate;	return 0;}static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status){	struct tda80xx_state* state = fe->demodulator_priv;	if (!state->config->irq)		tda80xx_read_status_int(state);	*status = state->status;	return 0;}static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber){	struct tda80xx_state* state = fe->demodulator_priv;	int ret;	u8 buf[3];	if ((ret = tda80xx_read(state, 0x0b, buf, sizeof(buf))))		return ret;	*ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];	return 0;}static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength){	struct tda80xx_state* state = fe->demodulator_priv;	u8 gain = ~tda80xx_readreg(state, 0x01);	*strength = (gain << 8) | gain;	return 0;}static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr){	struct tda80xx_state* state = fe->demodulator_priv;	u8 quality = tda80xx_readreg(state, 0x08);	*snr = (quality << 8) | quality;	return 0;}static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks){	struct tda80xx_state* state = fe->demodulator_priv;	*ucblocks = tda80xx_readreg(state, 0x0f);	if (*ucblocks == 0xff)		*ucblocks = 0xffffffff;	return 0;}static int tda80xx_init(struct dvb_frontend* fe){	struct tda80xx_state* state = fe->demodulator_priv;	switch(state->id) {	case ID_TDA8044:		return tda8044_init(fe);	case ID_TDA8083:		return tda8083_init(fe);	}	return 0;}static void tda80xx_release(struct dvb_frontend* fe){	struct tda80xx_state* state = fe->demodulator_priv;	if (state->config->irq)		free_irq(state->config->irq, &state->worklet);	kfree(state);}static struct dvb_frontend_ops tda80xx_ops;struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,				    struct i2c_adapter* i2c){	struct tda80xx_state* state = NULL;	int ret;	/* allocate memory for the internal state */	state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL);	if (state == NULL) goto error;	/* setup the state */	state->config = config;	state->i2c = i2c;	memcpy(&state->ops, &tda80xx_ops, sizeof(struct dvb_frontend_ops));	state->spectral_inversion = INVERSION_AUTO;	state->code_rate = FEC_AUTO;	state->status = 0;	state->afc_loop = 0;	/* check if the demod is there */	if (tda80xx_writereg(state, 0x89, 0x00) < 0) goto error;	state->id = tda80xx_readreg(state, 0x00);	switch (state->id) {	case ID_TDA8044:		state->clk = 96000000;		printk("tda80xx: Detected tda8044\n");		break;	case ID_TDA8083:		state->clk = 64000000;		printk("tda80xx: Detected tda8083\n");		break;	default:		goto error;	}	/* setup IRQ */	if (state->config->irq) {		INIT_WORK(&state->worklet, tda80xx_worklet, state);		if ((ret = request_irq(state->config->irq, tda80xx_irq, SA_ONESHOT, "tda80xx", &state->worklet)) < 0) {			printk(KERN_ERR "tda80xx: request_irq failed (%d)\n", ret);			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 tda80xx_ops = {	.info = {		.name = "Philips TDA80xx DVB-S",		.type = FE_QPSK,		.frequency_min = 500000,		.frequency_max = 2700000,		.frequency_stepsize = 125,		.symbol_rate_min = 4500000,		.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_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |			FE_CAN_QPSK |			FE_CAN_MUTE_TS	},	.release = tda80xx_release,	.init = tda80xx_init,	.sleep = tda80xx_sleep,	.set_frontend = tda80xx_set_frontend,	.get_frontend = tda80xx_get_frontend,	.read_status = tda80xx_read_status,	.read_ber = tda80xx_read_ber,	.read_signal_strength = tda80xx_read_signal_strength,	.read_snr = tda80xx_read_snr,	.read_ucblocks = tda80xx_read_ucblocks,	.diseqc_send_master_cmd = tda80xx_send_diseqc_msg,	.diseqc_send_burst = tda80xx_send_diseqc_burst,	.set_tone = tda80xx_set_tone,	.set_voltage = tda80xx_set_voltage,};module_param(debug, int, 0644);MODULE_DESCRIPTION("Philips TDA8044 / TDA8083 DVB-S Demodulator driver");MODULE_AUTHOR("Felix Domke, Andreas Oberritter");MODULE_LICENSE("GPL");EXPORT_SYMBOL(tda80xx_attach);

⌨️ 快捷键说明

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