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

📄 dib3000mc.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;	int search_state,auto_val;	u16 val;	if (tuner && state->config.pll_set) { /* initial call from dvb */		state->config.pll_set(fe,fep);		state->last_tuned_freq = fep->frequency;	//	if (!scanboost) {			dib3000mc_set_timing(state,0,ofdm->transmission_mode,ofdm->bandwidth);			dib3000mc_init_auto_scan(state, ofdm->bandwidth, 0);			state->last_tuned_bw = ofdm->bandwidth;			wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth);			wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_AGC);			wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF);			/* Default cfg isi offset adp */			wr_foreach(dib3000mc_reg_offset,dib3000mc_offset[0]);			wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT | DIB3000MC_ISI_INHIBIT);			dib3000mc_set_adp_cfg(state,ofdm->constellation);			wr(DIB3000MC_REG_UNK_133,DIB3000MC_UNK_133);			wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general);			/* power smoothing */			if (ofdm->bandwidth != BANDWIDTH_8_MHZ) {				wr_foreach(dib3000mc_reg_bw,dib3000mc_bw[0]);			} else {				wr_foreach(dib3000mc_reg_bw,dib3000mc_bw[3]);			}			auto_val = 0;			dib3000mc_set_general_cfg(state,fep,&auto_val);			dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth);			val = rd(DIB3000MC_REG_DEMOD_PARM);			wr(DIB3000MC_REG_DEMOD_PARM,val|DIB3000MC_DEMOD_RST_DEMOD_ON);			wr(DIB3000MC_REG_DEMOD_PARM,val);	//	}		msleep(70);		/* something has to be auto searched */		if (auto_val) {			int as_count=0;			deb_setf("autosearch enabled.\n");			val = rd(DIB3000MC_REG_DEMOD_PARM);			wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON);			wr(DIB3000MC_REG_DEMOD_PARM,val);			while ((search_state = dib3000_search_status(						rd(DIB3000MC_REG_AS_IRQ),1)) < 0 && as_count++ < 100)				msleep(10);			deb_info("search_state after autosearch %d after %d checks\n",search_state,as_count);			if (search_state == 1) {				struct dvb_frontend_parameters feps;				if (dib3000mc_get_frontend(fe, &feps) == 0) {					deb_setf("reading tuning data from frontend succeeded.\n");					return dib3000mc_set_frontend(fe, &feps, 0);				}			}		} else {			dib3000mc_set_impulse_noise(state,0,ofdm->transmission_mode,ofdm->bandwidth);			wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE);			dib3000mc_set_adp_cfg(state,ofdm->constellation);			/* set_offset_cfg */			wr_foreach(dib3000mc_reg_offset,					dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);		}	} else { /* second call, after autosearch (fka: set_WithKnownParams) *///		dib3000mc_set_timing(state,1,ofdm->transmission_mode,ofdm->bandwidth);		auto_val = 0;		dib3000mc_set_general_cfg(state,fep,&auto_val);		if (auto_val)			deb_info("auto_val is true, even though an auto search was already performed.\n");		dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth);		val = rd(DIB3000MC_REG_DEMOD_PARM);		wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON);		wr(DIB3000MC_REG_DEMOD_PARM,val);		msleep(30);		wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE);			dib3000mc_set_adp_cfg(state,ofdm->constellation);		wr_foreach(dib3000mc_reg_offset,				dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);	}	return 0;}static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode){	struct dib3000_state *state = fe->demodulator_priv;	deb_info("init start\n");	state->timing_offset = 0;	state->timing_offset_comp_done = 0;	wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_CONFIG);	wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF);	wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_UP);	wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_PUP_MOBILE);	wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_UP);	wr(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_INIT);	wr(DIB3000MC_REG_RST_UNC,DIB3000MC_RST_UNC_OFF);	wr(DIB3000MC_REG_UNK_19,DIB3000MC_UNK_19);	wr(33,5);	wr(36,81);	wr(DIB3000MC_REG_UNK_88,DIB3000MC_UNK_88);	wr(DIB3000MC_REG_UNK_99,DIB3000MC_UNK_99);	wr(DIB3000MC_REG_UNK_111,DIB3000MC_UNK_111_PH_N_MODE_0); /* phase noise algo off */	/* mobile mode - portable reception */	wr_foreach(dib3000mc_reg_mobile_mode,dib3000mc_mobile_mode[1]);/* TUNER_PANASONIC_ENV57H12D5: */	wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth);	wr_foreach(dib3000mc_reg_agc_bandwidth_general,dib3000mc_agc_bandwidth_general);	wr_foreach(dib3000mc_reg_agc,dib3000mc_agc_tuner[1]);	wr(DIB3000MC_REG_UNK_110,DIB3000MC_UNK_110);	wr(26,0x6680);	wr(DIB3000MC_REG_UNK_1,DIB3000MC_UNK_1);	wr(DIB3000MC_REG_UNK_2,DIB3000MC_UNK_2);	wr(DIB3000MC_REG_UNK_3,DIB3000MC_UNK_3);	wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS_DEFAULT);	wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz);	wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general);	wr(DIB3000MC_REG_UNK_4,DIB3000MC_UNK_4);	wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF);	wr(DIB3000MC_REG_SET_DDS_FREQ_LSB,DIB3000MC_DDS_FREQ_LSB);	dib3000mc_set_timing(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);//	wr_foreach(dib3000mc_reg_timing_freq,dib3000mc_timing_freq[3]);	wr(DIB3000MC_REG_UNK_120,DIB3000MC_UNK_120);	wr(DIB3000MC_REG_UNK_134,DIB3000MC_UNK_134);	wr(DIB3000MC_REG_FEC_CFG,DIB3000MC_FEC_CFG);	wr(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF);	dib3000mc_set_impulse_noise(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);/* output mode control, just the MPEG2_SLAVE *///	set_or(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_SLAVE);	wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_SLAVE);	wr(DIB3000MC_REG_SMO_MODE,DIB3000MC_SMO_MODE_SLAVE);	wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_SLAVE);	wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_SLAVE);/* MPEG2_PARALLEL_CONTINUOUS_CLOCK	wr(DIB3000MC_REG_OUTMODE,		DIB3000MC_SET_OUTMODE(DIB3000MC_OM_PAR_CONT_CLK,			rd(DIB3000MC_REG_OUTMODE)));	wr(DIB3000MC_REG_SMO_MODE,			DIB3000MC_SMO_MODE_DEFAULT |			DIB3000MC_SMO_MODE_188);	wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_DEFAULT);	wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON);*//* diversity */	wr(DIB3000MC_REG_DIVERSITY1,DIB3000MC_DIVERSITY1_DEFAULT);	wr(DIB3000MC_REG_DIVERSITY2,DIB3000MC_DIVERSITY2_DEFAULT);	set_and(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF);	set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);	if (state->config.pll_init)		state->config.pll_init(fe);	deb_info("init end\n");	return 0;}static int dib3000mc_read_status(struct dvb_frontend* fe, fe_status_t *stat){	struct dib3000_state* state = fe->demodulator_priv;	u16 lock = rd(DIB3000MC_REG_LOCKING);	*stat = 0;	if (DIB3000MC_AGC_LOCK(lock))		*stat |= FE_HAS_SIGNAL;	if (DIB3000MC_CARRIER_LOCK(lock))		*stat |= FE_HAS_CARRIER;	if (DIB3000MC_TPS_LOCK(lock))		*stat |= FE_HAS_VITERBI;	if (DIB3000MC_MPEG_SYNC_LOCK(lock))		*stat |= (FE_HAS_SYNC | FE_HAS_LOCK);	deb_stat("actual status is %2x fifo_level: %x,244: %x, 206: %x, 207: %x, 1040: %x\n",*stat,rd(510),rd(244),rd(206),rd(207),rd(1040));	return 0;}static int dib3000mc_read_ber(struct dvb_frontend* fe, u32 *ber){	struct dib3000_state* state = fe->demodulator_priv;	*ber = ((rd(DIB3000MC_REG_BER_MSB) << 16) | rd(DIB3000MC_REG_BER_LSB));	return 0;}static int dib3000mc_read_unc_blocks(struct dvb_frontend* fe, u32 *unc){	struct dib3000_state* state = fe->demodulator_priv;	*unc = rd(DIB3000MC_REG_PACKET_ERRORS);	return 0;}/* see dib3000mb.c for calculation comments */static int dib3000mc_read_signal_strength(struct dvb_frontend* fe, u16 *strength){	struct dib3000_state* state = fe->demodulator_priv;	u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB);	*strength = (((val >> 6) & 0xff) << 8) + (val & 0x3f);	deb_stat("signal: mantisse = %d, exponent = %d\n",(*strength >> 8) & 0xff, *strength & 0xff);	return 0;}/* see dib3000mb.c for calculation comments */static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr){	struct dib3000_state* state = fe->demodulator_priv;	u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB),		val2 = rd(DIB3000MC_REG_SIGNAL_NOISE_MSB);	u16 sig,noise;	sig =   (((val >> 6) & 0xff) << 8) + (val & 0x3f);	noise = (((val >> 4) & 0xff) << 8) + ((val & 0xf) << 2) + ((val2 >> 14) & 0x3);	if (noise == 0)		*snr = 0xffff;	else		*snr = (u16) sig/noise;	deb_stat("signal: mantisse = %d, exponent = %d\n",(sig >> 8) & 0xff, sig & 0xff);	deb_stat("noise:  mantisse = %d, exponent = %d\n",(noise >> 8) & 0xff, noise & 0xff);	deb_stat("snr: %d\n",*snr);	return 0;}static int dib3000mc_sleep(struct dvb_frontend* fe){	struct dib3000_state* state = fe->demodulator_priv;	set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_PWR_DOWN);	wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_DOWN);	wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_POWER_DOWN);	wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_DOWN);	return 0;}static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune){	tune->min_delay_ms = 1000;	return 0;}static int dib3000mc_fe_init_nonmobile(struct dvb_frontend* fe){	return dib3000mc_fe_init(fe, 0);}static int dib3000mc_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep){	return dib3000mc_set_frontend(fe, fep, 1);}static void dib3000mc_release(struct dvb_frontend* fe){	struct dib3000_state *state = fe->demodulator_priv;	kfree(state);}/* pid filter and transfer stuff */static int dib3000mc_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff){	struct dib3000_state *state = fe->demodulator_priv;	pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);	wr(index+DIB3000MC_REG_FIRST_PID,pid);	return 0;}static int dib3000mc_fifo_control(struct dvb_frontend *fe, int onoff){	struct dib3000_state *state = fe->demodulator_priv;	u16 tmp = rd(DIB3000MC_REG_SMO_MODE);	deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");	if (onoff) {		deb_xfer("%d %x\n",tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH);		wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH);	} else {		deb_xfer("%d %x\n",tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH,tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH);		wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH);	}	return 0;}static int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff){	struct dib3000_state *state = fe->demodulator_priv;	u16 tmp = rd(DIB3000MC_REG_SMO_MODE);	deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");	if (onoff) {		wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_PID_PARSE);	} else {		wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_NO_PID_PARSE);	}	return 0;}static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr){	struct dib3000_state *state = fe->demodulator_priv;	if (onoff) {		wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));	} else {		wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr));	}	return 0;}static int dib3000mc_demod_init(struct dib3000_state *state){	u16 default_addr = 0x0a;	/* first init */	if (state->config.demod_address != default_addr) {		deb_info("initializing the demod the first time. Setting demod addr to 0x%x\n",default_addr);		wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON);		wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_PAR_CONT_CLK);		wr(DIB3000MC_REG_RST_I2C_ADDR,			DIB3000MC_DEMOD_ADDR(default_addr) |			DIB3000MC_DEMOD_ADDR_ON);		state->config.demod_address = default_addr;		wr(DIB3000MC_REG_RST_I2C_ADDR,			DIB3000MC_DEMOD_ADDR(default_addr));	} else		deb_info("demod is already initialized. Demod addr: 0x%x\n",state->config.demod_address);	return 0;}static struct dvb_frontend_ops dib3000mc_ops;struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,				      struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops){	struct dib3000_state* state = NULL;	u16 devid;	/* allocate memory for the internal state */	state = kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);	if (state == NULL)		goto error;	memset(state,0,sizeof(struct dib3000_state));	/* setup the state */	state->i2c = i2c;	memcpy(&state->config,config,sizeof(struct dib3000_config));	memcpy(&state->ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));	/* check for the correct demod */	if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)		goto error;	devid = rd(DIB3000_REG_DEVICE_ID);	if (devid != DIB3000MC_DEVICE_ID && devid != DIB3000P_DEVICE_ID)		goto error;	switch (devid) {		case DIB3000MC_DEVICE_ID:			info("Found a DiBcom 3000M-C, interesting...");			break;		case DIB3000P_DEVICE_ID:			info("Found a DiBcom 3000P.");			break;	}	/* create dvb_frontend */	state->frontend.ops = &state->ops;	state->frontend.demodulator_priv = state;	/* set the xfer operations */	xfer_ops->pid_parse = dib3000mc_pid_parse;	xfer_ops->fifo_ctrl = dib3000mc_fifo_control;	xfer_ops->pid_ctrl = dib3000mc_pid_control;	xfer_ops->tuner_pass_ctrl = dib3000mc_tuner_pass_ctrl;	dib3000mc_demod_init(state);	return &state->frontend;error:	kfree(state);	return NULL;}static struct dvb_frontend_ops dib3000mc_ops = {	.info = {		.name			= "DiBcom 3000P/M-C DVB-T",		.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 = dib3000mc_release,	.init = dib3000mc_fe_init_nonmobile,	.sleep = dib3000mc_sleep,	.set_frontend = dib3000mc_set_frontend_and_tuner,	.get_frontend = dib3000mc_get_frontend,	.get_tune_settings = dib3000mc_fe_get_tune_settings,	.read_status = dib3000mc_read_status,	.read_ber = dib3000mc_read_ber,	.read_signal_strength = dib3000mc_read_signal_strength,	.read_snr = dib3000mc_read_snr,	.read_ucblocks = dib3000mc_read_unc_blocks,};MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");EXPORT_SYMBOL(dib3000mc_attach);

⌨️ 快捷键说明

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