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

📄 dib3000mc.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Frontend driver for mobile DVB-T demodulator DiBcom 3000P/M-C * DiBcom (http://www.dibcom.fr/) * * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * * based on GPL code from DiBCom, which has * * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) * *	This program is free software; you can redistribute it and/or *	modify it under the terms of the GNU General Public License as *	published by the Free Software Foundation, version 2. * * Acknowledgements * *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver *  sources, on which this driver (and the dvb-dibusb) are based. * * see Documentation/dvb/README.dibusb for more information * */#include <linux/config.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/string.h>#include <linux/slab.h>#include "dib3000-common.h"#include "dib3000mc_priv.h"#include "dib3000.h"/* Version information */#define DRIVER_VERSION "0.1"#define DRIVER_DESC "DiBcom 3000M-C DVB-T demodulator"#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"#ifdef CONFIG_DVB_DIBCOM_DEBUGstatic int debug;module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe,16=stat (|-able)).");#endif#define deb_info(args...) dprintk(0x01,args)#define deb_xfer(args...) dprintk(0x02,args)#define deb_setf(args...) dprintk(0x04,args)#define deb_getf(args...) dprintk(0x08,args)#define deb_stat(args...) dprintk(0x10,args)static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode,	fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth){	switch (transmission_mode) {		case TRANSMISSION_MODE_2K:			wr_foreach(dib3000mc_reg_fft,dib3000mc_fft_modes[0]);			break;		case TRANSMISSION_MODE_8K:			wr_foreach(dib3000mc_reg_fft,dib3000mc_fft_modes[1]);			break;		default:			break;	}	switch (bandwidth) {/*		case BANDWIDTH_5_MHZ:			wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[0]);			break; */		case BANDWIDTH_6_MHZ:			wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[1]);			break;		case BANDWIDTH_7_MHZ:			wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[2]);			break;		case BANDWIDTH_8_MHZ:			wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[3]);			break;		default:			break;	}	switch (mode) {		case 0: /* no impulse */ /* fall through */			wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[0]);			break;		case 1: /* new algo */			wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[1]);			set_or(DIB3000MC_REG_IMP_NOISE_55,DIB3000MC_IMP_NEW_ALGO(0)); /* gives 1<<10 */			break;		default: /* old algo */			wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[3]);			break;	}	return 0;}static int dib3000mc_set_timing(struct dib3000_state *state, int upd_offset,		fe_transmit_mode_t fft, fe_bandwidth_t bw){	u16 timf_msb,timf_lsb;	s32 tim_offset,tim_sgn;	u64 comp1,comp2,comp=0;	switch (bw) {		case BANDWIDTH_8_MHZ: comp = DIB3000MC_CLOCK_REF*8; break;		case BANDWIDTH_7_MHZ: comp = DIB3000MC_CLOCK_REF*7; break;		case BANDWIDTH_6_MHZ: comp = DIB3000MC_CLOCK_REF*6; break;		default: err("unknown bandwidth (%d)",bw); break;	}	timf_msb = (comp >> 16) & 0xff;	timf_lsb = (comp & 0xffff);	// Update the timing offset ;	if (upd_offset > 0) {		if (!state->timing_offset_comp_done) {			msleep(200);			state->timing_offset_comp_done = 1;		}		tim_offset = rd(DIB3000MC_REG_TIMING_OFFS_MSB);		if ((tim_offset & 0x2000) == 0x2000)			tim_offset |= 0xC000;		if (fft == TRANSMISSION_MODE_2K)			tim_offset <<= 2;		state->timing_offset += tim_offset;	}	tim_offset = state->timing_offset;	if (tim_offset < 0) {		tim_sgn = 1;		tim_offset = -tim_offset;	} else		tim_sgn = 0;	comp1 =  (u32)tim_offset * (u32)timf_lsb ;	comp2 =  (u32)tim_offset * (u32)timf_msb ;	comp  = ((comp1 >> 16) + comp2) >> 7;	if (tim_sgn == 0)		comp = (u32)(timf_msb << 16) + (u32) timf_lsb + comp;	else		comp = (u32)(timf_msb << 16) + (u32) timf_lsb - comp ;	timf_msb = (comp >> 16) & 0xff;	timf_lsb = comp & 0xffff;	wr(DIB3000MC_REG_TIMING_FREQ_MSB,timf_msb);	wr(DIB3000MC_REG_TIMING_FREQ_LSB,timf_lsb);	return 0;}static int dib3000mc_init_auto_scan(struct dib3000_state *state, fe_bandwidth_t bw, int boost){	if (boost) {		wr(DIB3000MC_REG_SCAN_BOOST,DIB3000MC_SCAN_BOOST_ON);	} else {		wr(DIB3000MC_REG_SCAN_BOOST,DIB3000MC_SCAN_BOOST_OFF);	}	switch (bw) {		case BANDWIDTH_8_MHZ:			wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz);			break;		case BANDWIDTH_7_MHZ:			wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_7mhz);			break;		case BANDWIDTH_6_MHZ:			wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_6mhz);			break;/*		case BANDWIDTH_5_MHZ:			wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_5mhz);			break;*/		case BANDWIDTH_AUTO:			return -EOPNOTSUPP;		default:			err("unknown bandwidth value (%d).",bw);			return -EINVAL;	}	if (boost) {		u32 timeout = (rd(DIB3000MC_REG_BW_TIMOUT_MSB) << 16) +			rd(DIB3000MC_REG_BW_TIMOUT_LSB);		timeout *= 85; timeout >>= 7;		wr(DIB3000MC_REG_BW_TIMOUT_MSB,(timeout >> 16) & 0xffff);		wr(DIB3000MC_REG_BW_TIMOUT_LSB,timeout & 0xffff);	}	return 0;}static int dib3000mc_set_adp_cfg(struct dib3000_state *state, fe_modulation_t con){	switch (con) {		case QAM_64:			wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[2]);			break;		case QAM_16:			wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[1]);			break;		case QPSK:			wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[0]);			break;		case QAM_AUTO:			break;		default:			warn("unkown constellation.");			break;	}	return 0;}static int dib3000mc_set_general_cfg(struct dib3000_state *state, struct dvb_frontend_parameters *fep, int *auto_val){	struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;	fe_code_rate_t fe_cr = FEC_NONE;	u8 fft=0, guard=0, qam=0, alpha=0, sel_hp=0, cr=0, hrch=0;	int seq;	switch (ofdm->transmission_mode) {		case TRANSMISSION_MODE_2K: fft = DIB3000_TRANSMISSION_MODE_2K; break;		case TRANSMISSION_MODE_8K: fft = DIB3000_TRANSMISSION_MODE_8K; break;		case TRANSMISSION_MODE_AUTO: break;		default: return -EINVAL;	}	switch (ofdm->guard_interval) {		case GUARD_INTERVAL_1_32: guard = DIB3000_GUARD_TIME_1_32; break;		case GUARD_INTERVAL_1_16: guard = DIB3000_GUARD_TIME_1_16; break;		case GUARD_INTERVAL_1_8:  guard = DIB3000_GUARD_TIME_1_8; break;		case GUARD_INTERVAL_1_4:  guard = DIB3000_GUARD_TIME_1_4; break;		case GUARD_INTERVAL_AUTO: break;		default: return -EINVAL;	}	switch (ofdm->constellation) {		case QPSK:   qam = DIB3000_CONSTELLATION_QPSK; break;		case QAM_16: qam = DIB3000_CONSTELLATION_16QAM; break;		case QAM_64: qam = DIB3000_CONSTELLATION_64QAM; break;		case QAM_AUTO: break;		default: return -EINVAL;	}	switch (ofdm->hierarchy_information) {		case HIERARCHY_NONE: /* fall through */		case HIERARCHY_1: alpha = DIB3000_ALPHA_1; break;		case HIERARCHY_2: alpha = DIB3000_ALPHA_2; break;		case HIERARCHY_4: alpha = DIB3000_ALPHA_4; break;		case HIERARCHY_AUTO: break;		default: return -EINVAL;	}	if (ofdm->hierarchy_information == HIERARCHY_NONE) {		hrch   = DIB3000_HRCH_OFF;		sel_hp = DIB3000_SELECT_HP;		fe_cr  = ofdm->code_rate_HP;	} else if (ofdm->hierarchy_information != HIERARCHY_AUTO) {		hrch   = DIB3000_HRCH_ON;		sel_hp = DIB3000_SELECT_LP;		fe_cr  = ofdm->code_rate_LP;	}	switch (fe_cr) {		case FEC_1_2: cr = DIB3000_FEC_1_2; break;		case FEC_2_3: cr = DIB3000_FEC_2_3; break;		case FEC_3_4: cr = DIB3000_FEC_3_4; break;		case FEC_5_6: cr = DIB3000_FEC_5_6; break;		case FEC_7_8: cr = DIB3000_FEC_7_8; break;		case FEC_NONE: break;		case FEC_AUTO: break;		default: return -EINVAL;	}	wr(DIB3000MC_REG_DEMOD_PARM,DIB3000MC_DEMOD_PARM(alpha,qam,guard,fft));	wr(DIB3000MC_REG_HRCH_PARM,DIB3000MC_HRCH_PARM(sel_hp,cr,hrch));	switch (fep->inversion) {		case INVERSION_OFF:			wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF);			break;		case INVERSION_AUTO: /* fall through */		case INVERSION_ON:			wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_ON);			break;		default:			return -EINVAL;	}	seq = dib3000_seq		[ofdm->transmission_mode == TRANSMISSION_MODE_AUTO]		[ofdm->guard_interval == GUARD_INTERVAL_AUTO]		[fep->inversion == INVERSION_AUTO];	deb_setf("seq? %d\n", seq);	wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS(seq,1));	*auto_val = ofdm->constellation == QAM_AUTO ||			ofdm->hierarchy_information == HIERARCHY_AUTO ||			ofdm->guard_interval == GUARD_INTERVAL_AUTO ||			ofdm->transmission_mode == TRANSMISSION_MODE_AUTO ||			fe_cr == FEC_AUTO ||			fep->inversion == INVERSION_AUTO;	return 0;}static int dib3000mc_get_frontend(struct dvb_frontend* fe,				  struct dvb_frontend_parameters *fep){	struct dib3000_state* state = fe->demodulator_priv;	struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;	fe_code_rate_t *cr;	u16 tps_val,cr_val;	int inv_test1,inv_test2;	u32 dds_val, threshold = 0x1000000;	if (!(rd(DIB3000MC_REG_LOCK_507) & DIB3000MC_LOCK_507))		return 0;	dds_val = (rd(DIB3000MC_REG_DDS_FREQ_MSB) << 16) + rd(DIB3000MC_REG_DDS_FREQ_LSB);	deb_getf("DDS_FREQ: %6x\n",dds_val);	if (dds_val < threshold)		inv_test1 = 0;	else if (dds_val == threshold)		inv_test1 = 1;	else		inv_test1 = 2;	dds_val = (rd(DIB3000MC_REG_SET_DDS_FREQ_MSB) << 16) + rd(DIB3000MC_REG_SET_DDS_FREQ_LSB);	deb_getf("DDS_SET_FREQ: %6x\n",dds_val);	if (dds_val < threshold)		inv_test2 = 0;	else if (dds_val == threshold)		inv_test2 = 1;	else		inv_test2 = 2;	fep->inversion =		((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||		((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?		INVERSION_ON : INVERSION_OFF;	deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion);	fep->frequency = state->last_tuned_freq;	fep->u.ofdm.bandwidth= state->last_tuned_bw;	tps_val = rd(DIB3000MC_REG_TUNING_PARM);	switch (DIB3000MC_TP_QAM(tps_val)) {		case DIB3000_CONSTELLATION_QPSK:			deb_getf("QPSK ");			ofdm->constellation = QPSK;			break;		case DIB3000_CONSTELLATION_16QAM:			deb_getf("QAM16 ");			ofdm->constellation = QAM_16;			break;		case DIB3000_CONSTELLATION_64QAM:			deb_getf("QAM64 ");			ofdm->constellation = QAM_64;			break;		default:			err("Unexpected constellation returned by TPS (%d)", tps_val);			break;	}	if (DIB3000MC_TP_HRCH(tps_val)) {		deb_getf("HRCH ON ");		cr = &ofdm->code_rate_LP;		ofdm->code_rate_HP = FEC_NONE;		switch (DIB3000MC_TP_ALPHA(tps_val)) {			case DIB3000_ALPHA_0:				deb_getf("HIERARCHY_NONE ");				ofdm->hierarchy_information = HIERARCHY_NONE;				break;			case DIB3000_ALPHA_1:				deb_getf("HIERARCHY_1 ");				ofdm->hierarchy_information = HIERARCHY_1;				break;			case DIB3000_ALPHA_2:				deb_getf("HIERARCHY_2 ");				ofdm->hierarchy_information = HIERARCHY_2;				break;			case DIB3000_ALPHA_4:				deb_getf("HIERARCHY_4 ");				ofdm->hierarchy_information = HIERARCHY_4;				break;			default:				err("Unexpected ALPHA value returned by TPS (%d)", tps_val);				break;		}		cr_val = DIB3000MC_TP_FEC_CR_LP(tps_val);	} else {		deb_getf("HRCH OFF ");		cr = &ofdm->code_rate_HP;		ofdm->code_rate_LP = FEC_NONE;		ofdm->hierarchy_information = HIERARCHY_NONE;		cr_val = DIB3000MC_TP_FEC_CR_HP(tps_val);	}	switch (cr_val) {		case DIB3000_FEC_1_2:			deb_getf("FEC_1_2 ");			*cr = FEC_1_2;			break;		case DIB3000_FEC_2_3:			deb_getf("FEC_2_3 ");			*cr = FEC_2_3;			break;		case DIB3000_FEC_3_4:			deb_getf("FEC_3_4 ");			*cr = FEC_3_4;			break;		case DIB3000_FEC_5_6:			deb_getf("FEC_5_6 ");			*cr = FEC_4_5;			break;		case DIB3000_FEC_7_8:			deb_getf("FEC_7_8 ");			*cr = FEC_7_8;			break;		default:			err("Unexpected FEC returned by TPS (%d)", tps_val);			break;	}	switch (DIB3000MC_TP_GUARD(tps_val)) {		case DIB3000_GUARD_TIME_1_32:			deb_getf("GUARD_INTERVAL_1_32 ");			ofdm->guard_interval = GUARD_INTERVAL_1_32;			break;		case DIB3000_GUARD_TIME_1_16:			deb_getf("GUARD_INTERVAL_1_16 ");			ofdm->guard_interval = GUARD_INTERVAL_1_16;			break;		case DIB3000_GUARD_TIME_1_8:			deb_getf("GUARD_INTERVAL_1_8 ");			ofdm->guard_interval = GUARD_INTERVAL_1_8;			break;		case DIB3000_GUARD_TIME_1_4:			deb_getf("GUARD_INTERVAL_1_4 ");			ofdm->guard_interval = GUARD_INTERVAL_1_4;			break;		default:			err("Unexpected Guard Time returned by TPS (%d)", tps_val);			break;	}	switch (DIB3000MC_TP_FFT(tps_val)) {		case DIB3000_TRANSMISSION_MODE_2K:			deb_getf("TRANSMISSION_MODE_2K ");			ofdm->transmission_mode = TRANSMISSION_MODE_2K;			break;		case DIB3000_TRANSMISSION_MODE_8K:			deb_getf("TRANSMISSION_MODE_8K ");			ofdm->transmission_mode = TRANSMISSION_MODE_8K;			break;		default:			err("unexpected transmission mode return by TPS (%d)", tps_val);			break;	}	deb_getf("\n");	return 0;}static int dib3000mc_set_frontend(struct dvb_frontend* fe,				  struct dvb_frontend_parameters *fep, int tuner){	struct dib3000_state* state = fe->demodulator_priv;

⌨️ 快捷键说明

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