drx397xd.c

来自「trident tm5600的linux驱动」· C语言 代码 · 共 1,600 行 · 第 1/3 页

C
1,600
字号
				     (u64)ebx) - 0x800000;		EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff));		EXIT_RC(WR16(s, 0x0c50011, ebx >> 16));		/* drx397xD oscillator calibration */		ebx = div64_u64(((u64) (s->config.f_if + df_tuner) << 28) +				     (s->f_osc >> 1), (u64)s->f_osc);	}	ebx &= 0xfffffff;	if (fep->inversion == INVERSION_ON)		ebx = 0x10000000 - ebx;	EXIT_RC(WR16(s, 0x0c30010, ebx & 0xffff));	EXIT_RC(WR16(s, 0x0c30011, ebx >> 16));	EXIT_RC(WR16(s, 0x0800000, 1));	EXIT_RC(RD16(s, 0x0800000));#if 0	rc = WR16(s, 0x0810000, 1);	if (rc < 0)		goto exit_rc;#endif	EXIT_RC(SC_WaitForReady(s));	EXIT_RC(WR16(s, 0x0820042, 0));	EXIT_RC(WR16(s, 0x0820041, v22));	EXIT_RC(WR16(s, 0x0820040, edi));	EXIT_RC(SC_SendCommand(s, 3));	rc = RD16(s, 0x0800000);	SC_WaitForReady(s);	WR16(s, 0x0820042, 0);	WR16(s, 0x0820041, 1);	WR16(s, 0x0820040, 1);	SC_SendCommand(s, 1);#if 0	rc = WR16(s, 0x2150000, 1);	if (rc < 0)		goto exit_rc;#endif	rc = WR16(s, 0x2150000, 2);	rc = WR16(s, 0x2150016, a);	rc = WR16(s, 0x2150010, 4);	rc = WR16(s, 0x2150036, 0);	rc = WR16(s, 0x2150000, 1);	s->config.d60 = 2;exit_rc:	return rc;}/******************************************************************************* * DVB interface ******************************************************************************/static int drx397x_init(struct dvb_frontend *fe){	struct drx397xD_state *s = fe->demodulator_priv;	int rc;	pr_debug("%s\n", __func__);	s->config.rfagc.d00 = 2;	/* 0x7c */	s->config.rfagc.w04 = 0;	s->config.rfagc.w06 = 0x3ff;	s->config.ifagc.d00 = 0;	/* 0x68 */	s->config.ifagc.w04 = 0;	s->config.ifagc.w06 = 140;	s->config.ifagc.w08 = 0;	s->config.ifagc.w0A = 0x3ff;	s->config.ifagc.w0C = 0x388;	/* for signal strenght calculations */	s->config.ss76 = 820;	s->config.ss78 = 2200;	s->config.ss7A = 150;	/* HI_CfgCommand */	s->config.w50 = 4;	s->config.w52 = 9;	s->config.f_if = 42800000;	/* d14: intermediate frequency [Hz] */	s->config.f_osc = 48000;	/* s66 : oscillator frequency [kHz] */	s->config.w92 = 12000;	s->config.w9C = 0x000e;	s->config.w9E = 0x0000;	/* ConfigureMPEGOutput params */	s->config.wA0 = 4;	s->config.w98 = 1;	s->config.w9A = 1;	/* get chip revision */	rc = RD16(s, 0x2410019);	if (rc < 0)		return -ENODEV;	if (rc == 0) {		printk(KERN_INFO "%s: chip revision A2\n", mod_name);		rc = drx_load_fw(s, DRXD_FW_A2);	} else {		rc = (rc >> 12) - 3;		switch (rc) {		case 1:			s->flags |= F_SET_0D4h;		case 0:		case 4:			s->flags |= F_SET_0D0h;			break;		case 2:		case 5:			break;		case 3:			s->flags |= F_SET_0D4h;			break;		default:			return -ENODEV;		};		printk(KERN_INFO "%s: chip revision B1.%d\n", mod_name, rc);		rc = drx_load_fw(s, DRXD_FW_B1);	}	if (rc < 0)		goto error;	rc = WR16(s, 0x0420033, 0x3973);	if (rc < 0)		goto error;	rc = HI_Command(s, 2);	msleep(1);	if (s->chip_rev == DRXD_FW_A2) {		rc = WR16(s, 0x043012d, 0x47F);		if (rc < 0)			goto error;	}	rc = WR16_E0(s, 0x0400000, 0);	if (rc < 0)		goto error;	if (s->config.w92 > 20000 || s->config.w92 % 4000) {		printk(KERN_ERR "%s: invalid osc frequency\n", mod_name);		rc = -1;		goto error;	}	rc = WR16(s, 0x2410010, 1);	if (rc < 0)		goto error;	rc = WR16(s, 0x2410011, 0x15);	if (rc < 0)		goto error;	rc = WR16(s, 0x2410012, s->config.w92 / 4000);	if (rc < 0)		goto error;#ifdef ORIG_FW	rc = WR16(s, 0x2410015, 2);	if (rc < 0)		goto error;#endif	rc = WR16(s, 0x2410017, 0x3973);	if (rc < 0)		goto error;	s->f_osc = s->config.f_osc * 1000;	/* initial estimator */#if 0	{		int deviation, val, edi;		/* osc_deviation(struct state *x, int deviation, int io)		 *		 * io == 0      : read_deviation from eeprom		 * io != 0      : write deviation to eeprom		 */		s->config.w64 = x->osc_deviation(x, 0, 0);		val = s->config.w64 * s->config.w66;		deviation = val / 1000000;		edi = 2;		if (val <= 0)			edi = -2;		val = val % 1000000;		if (edi * val > 1000000)			deviation += edi >> 1;		s->clk_if_corrected += deviation;	}#endif	s->config.w56 = 1;	rc = HI_CfgCommand(s);	if (rc < 0)		goto error;	rc = write_fw(s, DRXD_InitAtomicRead);	if (rc < 0)		goto error;	if (s->chip_rev == DRXD_FW_A2) {		rc = WR16(s, 0x2150013, 0);		if (rc < 0)			goto error;	}	rc = WR16_E0(s, 0x0400002, 0);	if (rc < 0)		goto error;	rc = WR16(s, 0x0400002, 0);	if (rc < 0)		goto error;	if (s->chip_rev == DRXD_FW_A2) {		rc = write_fw(s, DRXD_ResetCEFR);		if (rc < 0)			goto error;	}	rc = write_fw(s, DRXD_microcode);	if (rc < 0)		goto error;	s->config.w9C = 0x0e;	if (s->flags & F_SET_0D0h) {		s->config.w9C = 0;		rc = RD16(s, 0x0c20010);		if (rc < 0)			goto write_DRXD_InitFE_1;		rc &= ~0x1000;		rc = WR16(s, 0x0c20010, rc);		if (rc < 0)			goto write_DRXD_InitFE_1;		rc = RD16(s, 0x0c20011);		if (rc < 0)			goto write_DRXD_InitFE_1;		rc &= ~0x8;		rc = WR16(s, 0x0c20011, rc);		if (rc < 0)			goto write_DRXD_InitFE_1;		rc = WR16(s, 0x0c20012, 1);	}write_DRXD_InitFE_1:	rc = write_fw(s, DRXD_InitFE_1);	if (rc < 0)		goto error;	rc = 1;	if (s->chip_rev == DRXD_FW_B1) {		if (s->flags & F_SET_0D0h)			rc = 0;	} else {		if (s->flags & F_SET_0D0h)			rc = 4;	}	rc = WR16(s, 0x0C20012, rc);	if (rc < 0)		goto error;	rc = WR16(s, 0x0C20013, s->config.w9E);	if (rc < 0)		goto error;	rc = WR16(s, 0x0C20015, s->config.w9C);	if (rc < 0)		goto error;	rc = write_fw(s, DRXD_InitFE_2);	if (rc < 0)		goto error;	rc = write_fw(s, DRXD_InitFT);	if (rc < 0)		goto error;	rc = write_fw(s, DRXD_InitCP);	if (rc < 0)		goto error;	rc = write_fw(s, DRXD_InitCE);	if (rc < 0)		goto error;	rc = write_fw(s, DRXD_InitEQ);	if (rc < 0)		goto error;	rc = write_fw(s, DRXD_InitEC);	if (rc < 0)		goto error;	rc = write_fw(s, DRXD_InitSC);	if (rc < 0)		goto error;	rc = SetCfgIfAgc(s, &s->config.ifagc);	if (rc < 0)		goto error;	rc = SetCfgRfAgc(s, &s->config.rfagc);	if (rc < 0)		goto error;#if 1	rc = ConfigureMPEGOutput(s, 1);	rc = WR16(s, 0x08201fe, 0x0017);	rc = WR16(s, 0x08201ff, 0x0101);	s->config.d5C = 0;#else	s->config.d5C = 0;	rc = CorrectSysClockDeviation(s);	if (rc < 0)		goto error;// rc = ConfigureWR16(s, 0x0420033, 0x200);	rc = WR16(s, 0x0800000, 0);	if (rc < 0)		goto error;	rc = WR16(s, 0x2800000, 0);#endif	s->config.d60 = 1;	s->config.d48 = 1;error:	return rc;}static int drx397x_get_frontend(struct dvb_frontend *fe,				struct dvb_frontend_parameters *params){	return 0;}static int drx397x_set_frontend(struct dvb_frontend *fe,				struct dvb_frontend_parameters *params){	struct drx397xD_state *s = fe->demodulator_priv;	s->config.s20d24 = 1;	return drx_tune(s, params);}static int drx397x_get_tune_settings(struct dvb_frontend *fe,				     struct dvb_frontend_tune_settings				     *fe_tune_settings){	fe_tune_settings->min_delay_ms = 10000;	fe_tune_settings->step_size = 0;	fe_tune_settings->max_drift = 0;	return 0;}static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t *status){	struct drx397xD_state *s = fe->demodulator_priv;	int lockstat;	GetLockStatus(s, &lockstat);#if 0	/* TODO */	if (lockstat & 1)		CorrectSysClockDeviation(s);#endif	*status = 0;	if (lockstat & 2) {		CorrectSysClockDeviation(s);		ConfigureMPEGOutput(s, 1);		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;	}	if (lockstat & 4)		*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;	return 0;}static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber){	*ber = 0;	return 0;}static int drx397x_read_snr(struct dvb_frontend *fe, u16 *snr){	*snr = 0;	return 0;}static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 *strength){	struct drx397xD_state *s = fe->demodulator_priv;	int rc;	if (s->config.ifagc.d00 == 2) {		*strength = 0xffff;		return 0;	}	rc = RD16(s, 0x0c20035);	if (rc < 0) {		*strength = 0;		return 0;	}	rc &= 0x3ff;	/* Signal strength is calculated using the following formula:	 *	 * a = 2200 * 150 / (2200 + 150);	 * a = a * 3300 /  (a + 820);	 * b = 2200 * 3300 / (2200 + 820);	 * c = (((b-a) * rc) >> 10  + a) << 4;	 * strength = ~c & 0xffff;	 *	 * The following does the same but with less rounding errors:	 */	*strength = ~(7720 + (rc * 30744 >> 10));	return 0;}static int drx397x_read_ucblocks(struct dvb_frontend *fe,				 unsigned int *ucblocks){	*ucblocks = 0;	return 0;}static int drx397x_sleep(struct dvb_frontend *fe){	return 0;}static void drx397x_release(struct dvb_frontend *fe){	struct drx397xD_state *s = fe->demodulator_priv;	printk(KERN_INFO "%s: release demodulator\n", mod_name);	if (s) {		drx_release_fw(s);		kfree(s);	}}static struct dvb_frontend_ops drx397x_ops = {	.info = {		 .name			= "Micronas DRX397xD DVB-T Frontend",		 .type			= FE_OFDM,		 .frequency_min		= 47125000,		 .frequency_max		= 855250000,		 .frequency_stepsize	= 166667,		 .frequency_tolerance	= 0,		 .caps =				  /* 0x0C01B2EAE */			 FE_CAN_FEC_1_2			| /* = 0x2, */			 FE_CAN_FEC_2_3			| /* = 0x4, */			 FE_CAN_FEC_3_4			| /* = 0x8, */			 FE_CAN_FEC_5_6			| /* = 0x20, */			 FE_CAN_FEC_7_8			| /* = 0x80, */			 FE_CAN_FEC_AUTO		| /* = 0x200, */			 FE_CAN_QPSK			| /* = 0x400, */			 FE_CAN_QAM_16			| /* = 0x800, */			 FE_CAN_QAM_64			| /* = 0x2000, */			 FE_CAN_QAM_AUTO		| /* = 0x10000, */			 FE_CAN_TRANSMISSION_MODE_AUTO	| /* = 0x20000, */			 FE_CAN_GUARD_INTERVAL_AUTO	| /* = 0x80000, */			 FE_CAN_HIERARCHY_AUTO		| /* = 0x100000, */			 FE_CAN_RECOVER			| /* = 0x40000000, */			 FE_CAN_MUTE_TS			  /* = 0x80000000 */	 },	.release = drx397x_release,	.init = drx397x_init,	.sleep = drx397x_sleep,	.set_frontend = drx397x_set_frontend,	.get_tune_settings = drx397x_get_tune_settings,	.get_frontend = drx397x_get_frontend,	.read_status = drx397x_read_status,	.read_snr = drx397x_read_snr,	.read_signal_strength = drx397x_read_signal_strength,	.read_ber = drx397x_read_ber,	.read_ucblocks = drx397x_read_ucblocks,};struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config,				     struct i2c_adapter *i2c){	struct drx397xD_state *state;	/* allocate memory for the internal state */	state = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);	if (!state)		goto error;	/* setup the state */	state->i2c = i2c;	memcpy(&state->config, config, sizeof(struct drx397xD_config));	/* check if the demod is there */	if (RD16(state, 0x2410019) < 0)		goto error;	/* create dvb_frontend */	memcpy(&state->frontend.ops, &drx397x_ops,			sizeof(struct dvb_frontend_ops));	state->frontend.demodulator_priv = state;	return &state->frontend;error:	kfree(state);	return NULL;}EXPORT_SYMBOL(drx397xD_attach);MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend");MODULE_AUTHOR("Henk Vergonet");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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