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

📄 dib7000p.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
		} else if (pha == 768) {			coef_re[k] = 0;			coef_im[k] = -256;		} else {			coef_re[k] = sine[pha&0xff];			coef_im[k] = -sine[256 - (pha&0xff)];		}		coef_re[k] *= notch[k];		coef_re[k] += (1<<14);		if (coef_re[k] >= (1<<24))			coef_re[k]  = (1<<24) - 1;		coef_re[k] /= (1<<15);		coef_im[k] *= notch[k];		coef_im[k] += (1<<14);		if (coef_im[k] >= (1<<24))			coef_im[k]  = (1<<24)-1;		coef_im[k] /= (1<<15);		dprintk( "PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);		dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));		dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);		dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));	}	dib7000p_write_word(state,143 ,0);}static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch){	struct dib7000p_state *state = demod->demodulator_priv;	u16 tmp = 0;	if (ch != NULL)		dib7000p_set_channel(state, ch, 0);	else		return -EINVAL;	// restart demod	dib7000p_write_word(state, 770, 0x4000);	dib7000p_write_word(state, 770, 0x0000);	msleep(45);	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */	tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);	if (state->sfn_workaround_active) {		dprintk( "SFN workaround is active");		tmp |= (1 << 9);		dib7000p_write_word(state, 166, 0x4000); // P_pha3_force_pha_shift	} else {		dib7000p_write_word(state, 166, 0x0000); // P_pha3_force_pha_shift	}	dib7000p_write_word(state, 29, tmp);	// never achieved a lock with that bandwidth so far - wait for osc-freq to update	if (state->timf == 0)		msleep(200);	/* offset loop parameters */	/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */	tmp = (6 << 8) | 0x80;	switch (ch->u.ofdm.transmission_mode) {		case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break;		case /* 4K MODE */ 255: tmp |= (8 << 12); break;		default:		case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break;	}	dib7000p_write_word(state, 26, tmp);  /* timf_a(6xxx) */	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */	tmp = (0 << 4);	switch (ch->u.ofdm.transmission_mode) {		case TRANSMISSION_MODE_2K: tmp |= 0x6; break;		case /* 4K MODE */ 255: tmp |= 0x7; break;		default:		case TRANSMISSION_MODE_8K: tmp |= 0x8; break;	}	dib7000p_write_word(state, 32,  tmp);	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */	tmp = (0 << 4);	switch (ch->u.ofdm.transmission_mode) {		case TRANSMISSION_MODE_2K: tmp |= 0x6; break;		case /* 4K MODE */ 255: tmp |= 0x7; break;		default:		case TRANSMISSION_MODE_8K: tmp |= 0x8; break;	}	dib7000p_write_word(state, 33,  tmp);	tmp = dib7000p_read_word(state,509);	if (!((tmp >> 6) & 0x1)) {		/* restart the fec */		tmp = dib7000p_read_word(state,771);		dib7000p_write_word(state, 771, tmp | (1 << 1));		dib7000p_write_word(state, 771, tmp);		msleep(10);		tmp = dib7000p_read_word(state,509);	}	// we achieved a lock - it's time to update the osc freq	if ((tmp >> 6) & 0x1)		dib7000p_update_timf(state);	if (state->cfg.spur_protect)		dib7000p_spur_protect(state, ch->frequency/1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));    dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));	return 0;}static int dib7000p_wakeup(struct dvb_frontend *demod){	struct dib7000p_state *state = demod->demodulator_priv;	dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);	return 0;}static int dib7000p_sleep(struct dvb_frontend *demod){	struct dib7000p_state *state = demod->demodulator_priv;	return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);}static int dib7000p_identify(struct dib7000p_state *st){	u16 value;	dprintk( "checking demod on I2C address: %d (%x)",		st->i2c_addr, st->i2c_addr);	if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {		dprintk( "wrong Vendor ID (read=0x%x)",value);		return -EREMOTEIO;	}	if ((value = dib7000p_read_word(st, 769)) != 0x4000) {		dprintk( "wrong Device ID (%x)",value);		return -EREMOTEIO;	}	return 0;}static int dib7000p_get_frontend(struct dvb_frontend* fe,				struct dvb_frontend_parameters *fep){	struct dib7000p_state *state = fe->demodulator_priv;	u16 tps = dib7000p_read_word(state,463);	fep->inversion = INVERSION_AUTO;	fep->u.ofdm.bandwidth = BANDWIDTH_TO_INDEX(state->current_bandwidth);	switch ((tps >> 8) & 0x3) {		case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;		case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;		/* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */	}	switch (tps & 0x3) {		case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;		case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;		case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;		case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;	}	switch ((tps >> 14) & 0x3) {		case 0: fep->u.ofdm.constellation = QPSK; break;		case 1: fep->u.ofdm.constellation = QAM_16; break;		case 2:		default: fep->u.ofdm.constellation = QAM_64; break;	}	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */	/* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */	fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;	switch ((tps >> 5) & 0x7) {		case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;		case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;		case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;		case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;		case 7:		default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;	}	switch ((tps >> 2) & 0x7) {		case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;		case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;		case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;		case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;		case 7:		default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;	}	/* native interleaver: (dib7000p_read_word(state, 464) >>  5) & 0x1 */	return 0;}static int dib7000p_set_frontend(struct dvb_frontend* fe,				struct dvb_frontend_parameters *fep){	struct dib7000p_state *state = fe->demodulator_priv;	int time, ret;	dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);    /* maybe the parameter has been changed */	state->sfn_workaround_active = buggy_sfn_workaround;	if (fe->ops.tuner_ops.set_params)		fe->ops.tuner_ops.set_params(fe, fep);	/* start up the AGC */	state->agc_state = 0;	do {		time = dib7000p_agc_startup(fe, fep);		if (time != -1)			msleep(time);	} while (time != -1);	if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||		fep->u.ofdm.guard_interval    == GUARD_INTERVAL_AUTO ||		fep->u.ofdm.constellation     == QAM_AUTO ||		fep->u.ofdm.code_rate_HP      == FEC_AUTO) {		int i = 800, found;		dib7000p_autosearch_start(fe, fep);		do {			msleep(1);			found = dib7000p_autosearch_is_irq(fe);		} while (found == 0 && i--);		dprintk("autosearch returns: %d",found);		if (found == 0 || found == 1)			return 0; // no channel found		dib7000p_get_frontend(fe, fep);	}	ret = dib7000p_tune(fe, fep);	/* make this a config parameter */	dib7000p_set_output_mode(state, state->cfg.output_mode);    return ret;}static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat){	struct dib7000p_state *state = fe->demodulator_priv;	u16 lock = dib7000p_read_word(state, 509);	*stat = 0;	if (lock & 0x8000)		*stat |= FE_HAS_SIGNAL;	if (lock & 0x3000)		*stat |= FE_HAS_CARRIER;	if (lock & 0x0100)		*stat |= FE_HAS_VITERBI;	if (lock & 0x0010)		*stat |= FE_HAS_SYNC;	if (lock & 0x0008)		*stat |= FE_HAS_LOCK;	return 0;}static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber){	struct dib7000p_state *state = fe->demodulator_priv;	*ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);	return 0;}static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc){	struct dib7000p_state *state = fe->demodulator_priv;	*unc = dib7000p_read_word(state, 506);	return 0;}static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength){	struct dib7000p_state *state = fe->demodulator_priv;	u16 val = dib7000p_read_word(state, 394);	*strength = 65535 - val;	return 0;}static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr){	*snr = 0x0000;	return 0;}static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune){	tune->min_delay_ms = 1000;	return 0;}static void dib7000p_release(struct dvb_frontend *demod){	struct dib7000p_state *st = demod->demodulator_priv;	dibx000_exit_i2c_master(&st->i2c_master);	kfree(st);}int dib7000pc_detection(struct i2c_adapter *i2c_adap){	u8 tx[2], rx[2];	struct i2c_msg msg[2] = {		{ .addr = 18 >> 1, .flags = 0,        .buf = tx, .len = 2 },		{ .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 },	};	tx[0] = 0x03;	tx[1] = 0x00;	if (i2c_transfer(i2c_adap, msg, 2) == 2)		if (rx[0] == 0x01 && rx[1] == 0xb3) {			dprintk("-D-  DiB7000PC detected");			return 1;		}	msg[0].addr = msg[1].addr = 0x40;	if (i2c_transfer(i2c_adap, msg, 2) == 2)		if (rx[0] == 0x01 && rx[1] == 0xb3) {			dprintk("-D-  DiB7000PC detected");			return 1;		}	dprintk("-D-  DiB7000PC not detected");	return 0;}EXPORT_SYMBOL(dib7000pc_detection);struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating){	struct dib7000p_state *st = demod->demodulator_priv;	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);}EXPORT_SYMBOL(dib7000p_get_i2c_master);int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]){	struct dib7000p_state st = { .i2c_adap = i2c };	int k = 0;	u8 new_addr = 0;	for (k = no_of_demods-1; k >= 0; k--) {		st.cfg = cfg[k];		/* designated i2c address */		new_addr          = (0x40 + k) << 1;		st.i2c_addr = new_addr;		if (dib7000p_identify(&st) != 0) {			st.i2c_addr = default_addr;			if (dib7000p_identify(&st) != 0) {				dprintk("DiB7000P #%d: not identified\n", k);				return -EIO;			}		}		/* start diversity to pull_down div_str - just for i2c-enumeration */		dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY);		/* set new i2c address and force divstart */		dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2);		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);	}	for (k = 0; k < no_of_demods; k++) {		st.cfg = cfg[k];		st.i2c_addr = (0x40 + k) << 1;		// unforce divstr		dib7000p_write_word(&st, 1285, st.i2c_addr << 2);		/* deactivate div - it was just for i2c-enumeration */		dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z);	}	return 0;}EXPORT_SYMBOL(dib7000p_i2c_enumeration);static struct dvb_frontend_ops dib7000p_ops;struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg){	struct dvb_frontend *demod;	struct dib7000p_state *st;	st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);	if (st == NULL)		return NULL;	memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));	st->i2c_adap = i2c_adap;	st->i2c_addr = i2c_addr;	st->gpio_val = cfg->gpio_val;	st->gpio_dir = cfg->gpio_dir;	/* Ensure the output mode remains at the previous default if it's	 * not specifically set by the caller.	 */	if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) &&	    (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))		st->cfg.output_mode = OUTMODE_MPEG2_FIFO;	demod                   = &st->demod;	demod->demodulator_priv = st;	memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));	if (dib7000p_identify(st) != 0)		goto error;	dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);	dib7000p_demod_reset(st);	return demod;error:	kfree(st);	return NULL;}EXPORT_SYMBOL(dib7000p_attach);static struct dvb_frontend_ops dib7000p_ops = {	.info = {		.name = "DiBcom 7000PC",		.type = FE_OFDM,		.frequency_min      = 44250000,		.frequency_max      = 867250000,		.frequency_stepsize = 62500,		.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_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 |			FE_CAN_RECOVER |			FE_CAN_HIERARCHY_AUTO,	},	.release              = dib7000p_release,	.init                 = dib7000p_wakeup,	.sleep                = dib7000p_sleep,	.set_frontend         = dib7000p_set_frontend,	.get_tune_settings    = dib7000p_fe_get_tune_settings,	.get_frontend         = dib7000p_get_frontend,	.read_status          = dib7000p_read_status,	.read_ber             = dib7000p_read_ber,	.read_signal_strength = dib7000p_read_signal_strength,	.read_snr             = dib7000p_read_snr,	.read_ucblocks        = dib7000p_read_unc_blocks,};MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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