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

📄 tda1004x.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
			fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;			break;		case 0x6e:			fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;			break;		case 0x80:			fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;			break;		}		break;	}	// FEC	fe_params->u.ofdm.code_rate_HP =	    tda1004x_decode_fec(tda1004x_read_byte(state, TDA1004X_OUT_CONF2) & 7);	fe_params->u.ofdm.code_rate_LP =	    tda1004x_decode_fec((tda1004x_read_byte(state, TDA1004X_OUT_CONF2) >> 3) & 7);	// constellation	switch (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 3) {	case 0:		fe_params->u.ofdm.constellation = QPSK;		break;	case 1:		fe_params->u.ofdm.constellation = QAM_16;		break;	case 2:		fe_params->u.ofdm.constellation = QAM_64;		break;	}	// transmission mode	fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;	if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10) {		fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;	}	// guard interval	switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) {	case 0:		fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;		break;	case 1:		fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;		break;	case 2:		fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;		break;	case 3:		fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;		break;	}	// hierarchy	switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x60) >> 5) {	case 0:		fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;		break;	case 1:		fe_params->u.ofdm.hierarchy_information = HIERARCHY_1;		break;	case 2:		fe_params->u.ofdm.hierarchy_information = HIERARCHY_2;		break;	case 3:		fe_params->u.ofdm.hierarchy_information = HIERARCHY_4;		break;	}	return 0;}static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status){	struct tda1004x_state* state = fe->demodulator_priv;	int status;	int cber;	int vber;	dprintk("%s\n", __FUNCTION__);	// read status	status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);	if (status == -1) {		return -EIO;	}	// decode	*fe_status = 0;	if (status & 4) *fe_status |= FE_HAS_SIGNAL;	if (status & 2) *fe_status |= FE_HAS_CARRIER;	if (status & 8) *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;	// if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi	// is getting anything valid	if (!(*fe_status & FE_HAS_VITERBI)) {		// read the CBER		cber = tda1004x_read_byte(state, TDA1004X_CBER_LSB);		if (cber == -1) return -EIO;		status = tda1004x_read_byte(state, TDA1004X_CBER_MSB);		if (status == -1) return -EIO;		cber |= (status << 8);		tda1004x_read_byte(state, TDA1004X_CBER_RESET);		if (cber != 65535) {			*fe_status |= FE_HAS_VITERBI;		}	}	// if we DO have some valid VITERBI output, but don't already have SYNC	// bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid.	if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) {		// read the VBER		vber = tda1004x_read_byte(state, TDA1004X_VBER_LSB);		if (vber == -1) return -EIO;		status = tda1004x_read_byte(state, TDA1004X_VBER_MID);		if (status == -1) return -EIO;		vber |= (status << 8);		status = tda1004x_read_byte(state, TDA1004X_VBER_MSB);		if (status == -1) return -EIO;		vber |= ((status << 16) & 0x0f);		tda1004x_read_byte(state, TDA1004X_CVBER_LUT);		// if RS has passed some valid TS packets, then we must be		// getting some SYNC bytes		if (vber < 16632) {			*fe_status |= FE_HAS_SYNC;		}	}	// success	dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status);	return 0;}static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal){	struct tda1004x_state* state = fe->demodulator_priv;	int tmp;	int reg = 0;	dprintk("%s\n", __FUNCTION__);	// determine the register to use	switch(state->demod_type) {	case TDA1004X_DEMOD_TDA10045:		reg = TDA10045H_S_AGC;		break;	case TDA1004X_DEMOD_TDA10046:		reg = TDA10046H_AGC_IF_LEVEL;		break;	}	// read it	tmp = tda1004x_read_byte(state, reg);	if (tmp < 0)		return -EIO;	*signal = (tmp << 8) | tmp;	dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal);	return 0;}static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr){	struct tda1004x_state* state = fe->demodulator_priv;	int tmp;	dprintk("%s\n", __FUNCTION__);	// read it	tmp = tda1004x_read_byte(state, TDA1004X_SNR);	if (tmp < 0)		return -EIO;	if (tmp) {		tmp = 255 - tmp;	}	*snr = ((tmp << 8) | tmp);	dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);	return 0;}static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks){	struct tda1004x_state* state = fe->demodulator_priv;	int tmp;	int tmp2;	int counter;	dprintk("%s\n", __FUNCTION__);	// read the UCBLOCKS and reset	counter = 0;	tmp = tda1004x_read_byte(state, TDA1004X_UNCOR);	if (tmp < 0)		return -EIO;	tmp &= 0x7f;	while (counter++ < 5) {		tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);		tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);		tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);		tmp2 = tda1004x_read_byte(state, TDA1004X_UNCOR);		if (tmp2 < 0)			return -EIO;		tmp2 &= 0x7f;		if ((tmp2 < tmp) || (tmp2 == 0))			break;	}	if (tmp != 0x7f) {		*ucblocks = tmp;	} else {		*ucblocks = 0xffffffff;	}	dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks);	return 0;}static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber){	struct tda1004x_state* state = fe->demodulator_priv;	int tmp;	dprintk("%s\n", __FUNCTION__);	// read it in	tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);	if (tmp < 0) return -EIO;	*ber = tmp << 1;	tmp = tda1004x_read_byte(state, TDA1004X_CBER_MSB);	if (tmp < 0) return -EIO;	*ber |= (tmp << 9);	tda1004x_read_byte(state, TDA1004X_CBER_RESET);	dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber);	return 0;}static int tda1004x_sleep(struct dvb_frontend* fe){	struct tda1004x_state* state = fe->demodulator_priv;	switch(state->demod_type) {	case TDA1004X_DEMOD_TDA10045:		tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0x10);			break;	case TDA1004X_DEMOD_TDA10046:		tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);			break;		}	state->initialised = 0;			return 0;		}static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)	{		fesettings->min_delay_ms = 800;		fesettings->step_size = 166667;		fesettings->max_drift = 166667*2;		return 0;	}static void tda1004x_release(struct dvb_frontend* fe){	struct tda1004x_state* state = (struct tda1004x_state*) fe->demodulator_priv;	kfree(state);	}static struct dvb_frontend_ops tda10045_ops;struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,				     struct i2c_adapter* i2c){	struct tda1004x_state* state = NULL;	/* allocate memory for the internal state */	state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);	if (state == NULL) goto error;	/* setup the state */	state->config = config;	state->i2c = i2c;	memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));	state->initialised = 0;	state->demod_type = TDA1004X_DEMOD_TDA10045;	/* check if the demod is there */	if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x25) goto error;	/* 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 tda10046_ops;struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,				     struct i2c_adapter* i2c){	struct tda1004x_state* state = NULL;	/* allocate memory for the internal state */	state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);	if (state == NULL) goto error;	/* setup the state */	state->config = config;	state->i2c = i2c;	memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));	state->initialised = 0;	state->demod_type = TDA1004X_DEMOD_TDA10046;	/* check if the demod is there */	if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) goto error;	/* 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 tda10045_ops = {	.info = {		.name = "Philips TDA10045H DVB-T",		.type = FE_OFDM,		.frequency_min = 51000000,		.frequency_max = 858000000,		.frequency_stepsize = 166667,		.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_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |		    FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO	},	.release = tda1004x_release,	.init = tda10045_init,	.sleep = tda1004x_sleep,	.set_frontend = tda1004x_set_fe,	.get_frontend = tda1004x_get_fe,	.get_tune_settings = tda1004x_get_tune_settings,	.read_status = tda1004x_read_status,	.read_ber = tda1004x_read_ber,	.read_signal_strength = tda1004x_read_signal_strength,	.read_snr = tda1004x_read_snr,	.read_ucblocks = tda1004x_read_ucblocks,};static struct dvb_frontend_ops tda10046_ops = {	.info = {		.name = "Philips TDA10046H DVB-T",		.type = FE_OFDM,		.frequency_min = 51000000,		.frequency_max = 858000000,		.frequency_stepsize = 166667,		.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_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |		    FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO	},	.release = tda1004x_release,	.init = tda10046_init,	.sleep = tda1004x_sleep,	.set_frontend = tda1004x_set_fe,	.get_frontend = tda1004x_get_fe,	.get_tune_settings = tda1004x_get_tune_settings,	.read_status = tda1004x_read_status,	.read_ber = tda1004x_read_ber,	.read_signal_strength = tda1004x_read_signal_strength,	.read_snr = tda1004x_read_snr,	.read_ucblocks = tda1004x_read_ucblocks,};module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");MODULE_DESCRIPTION("Philips TDA10045H & TDA10046H DVB-T Demodulator");MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach");MODULE_LICENSE("GPL");EXPORT_SYMBOL(tda10045_attach);EXPORT_SYMBOL(tda10046_attach);EXPORT_SYMBOL(tda1004x_write_byte);

⌨️ 快捷键说明

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