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

📄 sp887x.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	switch (p->u.ofdm.constellation) {	case QPSK:		break;	case QAM_16:		*reg0xc05 |= (1 << 10);		break;	case QAM_64:		*reg0xc05 |= (2 << 10);		break;	case QAM_AUTO:		known_parameters = 0;		break;	default:		return -EINVAL;	};	switch (p->u.ofdm.hierarchy_information) {	case HIERARCHY_NONE:		break;	case HIERARCHY_1:		*reg0xc05 |= (1 << 7);		break;	case HIERARCHY_2:		*reg0xc05 |= (2 << 7);		break;	case HIERARCHY_4:		*reg0xc05 |= (3 << 7);		break;	case HIERARCHY_AUTO:		known_parameters = 0;		break;	default:		return -EINVAL;	};	switch (p->u.ofdm.code_rate_HP) {	case FEC_1_2:		break;	case FEC_2_3:		*reg0xc05 |= (1 << 3);		break;	case FEC_3_4:		*reg0xc05 |= (2 << 3);		break;	case FEC_5_6:		*reg0xc05 |= (3 << 3);		break;	case FEC_7_8:		*reg0xc05 |= (4 << 3);		break;	case FEC_AUTO:		known_parameters = 0;		break;	default:		return -EINVAL;	};	if (known_parameters)		*reg0xc05 |= (2 << 1);	/* use specified parameters */	else		*reg0xc05 |= (1 << 1);	/* enable autoprobing */	return 0;}/** *  estimates division of two 24bit numbers, *  derived from the ves1820/stv0299 driver code */staticvoid divide (int n, int d, int *quotient_i, int *quotient_f){	unsigned int q, r;	r = (n % d) << 8;	q = (r / d);	if (quotient_i)		*quotient_i = q;	if (quotient_f) {		r = (r % d) << 8;		q = (q << 8) | (r / d);		r = (r % d) << 8;		*quotient_f = (q << 8) | (r / d);	}}staticvoid sp887x_correct_offsets (struct dvb_frontend *fe,			     struct dvb_frontend_parameters *p,			     int actual_freq){	static const u32 srate_correction [] = { 1879617, 4544878, 8098561 };	int bw_index = p->u.ofdm.bandwidth - BANDWIDTH_8_MHZ;	int freq_offset = actual_freq - p->frequency;	int sysclock = 61003; //[kHz]	int ifreq = 36000000;	int freq;	int frequency_shift;	if (p->inversion == INVERSION_ON)		freq = ifreq - freq_offset;	else		freq = ifreq + freq_offset;	divide(freq / 333, sysclock, NULL, &frequency_shift);	if (p->inversion == INVERSION_ON)		frequency_shift = -frequency_shift;	/* sample rate correction */	sp887x_writereg(fe, 0x319, srate_correction[bw_index] >> 12);	sp887x_writereg(fe, 0x31a, srate_correction[bw_index] & 0xfff);	/* carrier offset correction */	sp887x_writereg(fe, 0x309, frequency_shift >> 12);	sp887x_writereg(fe, 0x30a, frequency_shift & 0xfff);}staticint sp887x_setup_frontend_parameters (struct dvb_frontend *fe,				      struct dvb_frontend_parameters *p){	int actual_freq, err;	u16 val, reg0xc05;	if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ &&	    p->u.ofdm.bandwidth != BANDWIDTH_7_MHZ &&	    p->u.ofdm.bandwidth != BANDWIDTH_6_MHZ)		return -EINVAL;		if ((err = configure_reg0xc05(p, &reg0xc05)))		return err;	sp887x_microcontroller_stop(fe);	actual_freq = tsa5060_setup_pll(fe, p->frequency);	/* read status reg in order to clear pending irqs */	sp887x_readreg(fe, 0x200);	sp887x_correct_offsets(fe, p, actual_freq);	/* filter for 6/7/8 Mhz channel */	if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)		val = 2;	else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)		val = 1;	else		val = 0;	sp887x_writereg(fe, 0x311, val);	/* scan order: 2k first = 0, 8k first = 1 */	if (p->u.ofdm.transmission_mode == TRANSMISSION_MODE_2K)		sp887x_writereg(fe, 0x338, 0x000);	else		sp887x_writereg(fe, 0x338, 0x001);	sp887x_writereg(fe, 0xc05, reg0xc05);	if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)		val = 2 << 3;	else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)		val = 3 << 3;	else		val = 0 << 3;	/* enable OFDM and SAW bits as lock indicators in sync register 0xf17,	 * optimize algorithm for given bandwidth...	 */	sp887x_writereg(fe, 0xf14, 0x160 | val);	sp887x_writereg(fe, 0xf15, 0x000);	sp887x_microcontroller_start(fe);	return 0;}staticint sp887x_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg){        switch (cmd) {        case FE_GET_INFO:		memcpy (arg, &sp887x_info, sizeof(struct dvb_frontend_info));		break;        case FE_READ_STATUS:	{		u16 snr12 = sp887x_readreg(fe, 0xf16);		u16 sync0x200 = sp887x_readreg(fe, 0x200);		u16 sync0xf17 = sp887x_readreg(fe, 0xf17);		fe_status_t *status = arg;		*status = 0;		if (snr12 > 0x00f)			*status |= FE_HAS_SIGNAL;		//if (sync0x200 & 0x004)		//	*status |= FE_HAS_SYNC | FE_HAS_CARRIER;		//if (sync0x200 & 0x008)		//	*status |= FE_HAS_VITERBI;		if ((sync0xf17 & 0x00f) == 0x002) {			*status |= FE_HAS_LOCK;			*status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_CARRIER;		}		if (sync0x200 & 0x001) {	/* tuner adjustment requested...*/			int steps = (sync0x200 >> 4) & 0x00f;			if (steps & 0x008)				steps = -steps;			dprintk("sp887x: implement tuner adjustment (%+i steps)!!\n",			       steps);		}		break;	}        case FE_READ_BER:	{		u32* ber = arg;		*ber = (sp887x_readreg(fe, 0xc08) & 0x3f) |		       (sp887x_readreg(fe, 0xc07) << 6);		sp887x_writereg(fe, 0xc08, 0x000);		sp887x_writereg(fe, 0xc07, 0x000);		if (*ber >= 0x3fff0)			*ber = ~0;		break;	}        case FE_READ_SIGNAL_STRENGTH:		// FIXME: correct registers ?	{		u16 snr12 = sp887x_readreg(fe, 0xf16);		u32 signal = 3 * (snr12 << 4);		*((u16*) arg) = (signal < 0xffff) ? signal : 0xffff;		break;	}        case FE_READ_SNR:	{		u16 snr12 = sp887x_readreg(fe, 0xf16);		*(u16*) arg = (snr12 << 4) | (snr12 >> 8);		break;	}	case FE_READ_UNCORRECTED_BLOCKS:	{		u32 *ublocks = (u32 *) arg;		*ublocks = sp887x_readreg(fe, 0xc0c);		if (*ublocks == 0xfff)			*ublocks = ~0;		break;	}        case FE_SET_FRONTEND:		return sp887x_setup_frontend_parameters(fe, arg);	case FE_GET_FRONTEND:  // FIXME: read known values back from Hardware...		break;        case FE_SLEEP:		/* tristate TS output and disable interface pins */		sp887x_writereg(fe, 0xc18, 0x000);		break;        case FE_INIT:		if (fe->data == NULL) {	  /* first time initialisation... */			fe->data = (void*) ~0;			sp887x_initial_setup (fe);		}		/* enable TS output and interface pins */		sp887x_writereg(fe, 0xc18, 0x00d);		break;	case FE_GET_TUNE_SETTINGS:	{	        struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;	        fesettings->min_delay_ms = 50;	        fesettings->step_size = 0;	        fesettings->max_drift = 0;	        return 0;	}	    	default:		return -EOPNOTSUPP;        };        return 0;}staticint sp887x_attach (struct dvb_i2c_bus *i2c, void **data){	struct i2c_msg msg = {.addr = 0x70, .flags = 0, .buf = NULL, .len = 0 };	dprintk ("%s\n", __FUNCTION__);	if (i2c->xfer (i2c, &msg, 1) != 1)                return -ENODEV;	return dvb_register_frontend (sp887x_ioctl, i2c, NULL, &sp887x_info);}staticvoid sp887x_detach (struct dvb_i2c_bus *i2c, void *data){	dprintk ("%s\n", __FUNCTION__);	dvb_unregister_frontend (sp887x_ioctl, i2c);}staticint __init init_sp887x (void){	dprintk ("%s\n", __FUNCTION__);	return dvb_register_i2c_device (NULL, sp887x_attach, sp887x_detach);}staticvoid __exit exit_sp887x (void){	dprintk ("%s\n", __FUNCTION__);	dvb_unregister_i2c_device (sp887x_attach);}module_init(init_sp887x);module_exit(exit_sp887x);MODULE_DESCRIPTION("sp887x DVB-T demodulator driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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