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

📄 af9005-fe.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Frontend part of the Linux driver for the Afatech 9005 * USB1.1 DVB-T receiver. * * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org) * * Thanks to Afatech who kindly provided information. * * 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; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * see Documentation/dvb/README.dvb-usb for more information */#include "af9005.h"#include "af9005-script.h"#include "mt2060.h"#include "qt1010.h"#include <asm/div64.h>struct af9005_fe_state {	struct dvb_usb_device *d;	fe_status_t stat;	/* retraining parameters */	u32 original_fcw;	u16 original_rf_top;	u16 original_if_top;	u16 original_if_min;	u16 original_aci0_if_top;	u16 original_aci1_if_top;	u16 original_aci0_if_min;	u8 original_if_unplug_th;	u8 original_rf_unplug_th;	u8 original_dtop_if_unplug_th;	u8 original_dtop_rf_unplug_th;	/* statistics */	u32 pre_vit_error_count;	u32 pre_vit_bit_count;	u32 ber;	u32 post_vit_error_count;	u32 post_vit_bit_count;	u32 unc;	u16 abort_count;	int opened;	int strong;	unsigned long next_status_check;	struct dvb_frontend frontend;};static int af9005_write_word_agc(struct dvb_usb_device *d, u16 reghi,				 u16 reglo, u8 pos, u8 len, u16 value){	int ret;	u8 temp;	if ((ret = af9005_write_ofdm_register(d, reglo, (u8) (value & 0xff))))		return ret;	temp = (u8) ((value & 0x0300) >> 8);	return af9005_write_register_bits(d, reghi, pos, len,					  (u8) ((value & 0x300) >> 8));}static int af9005_read_word_agc(struct dvb_usb_device *d, u16 reghi,				u16 reglo, u8 pos, u8 len, u16 * value){	int ret;	u8 temp0, temp1;	if ((ret = af9005_read_ofdm_register(d, reglo, &temp0)))		return ret;	if ((ret = af9005_read_ofdm_register(d, reghi, &temp1)))		return ret;	switch (pos) {	case 0:		*value = ((u16) (temp1 & 0x03) << 8) + (u16) temp0;		break;	case 2:		*value = ((u16) (temp1 & 0x0C) << 6) + (u16) temp0;		break;	case 4:		*value = ((u16) (temp1 & 0x30) << 4) + (u16) temp0;		break;	case 6:		*value = ((u16) (temp1 & 0xC0) << 2) + (u16) temp0;		break;	default:		err("invalid pos in read word agc");		return -EINVAL;	}	return 0;}static int af9005_is_fecmon_available(struct dvb_frontend *fe, int *available){	struct af9005_fe_state *state = fe->demodulator_priv;	int ret;	u8 temp;	*available = false;	ret = af9005_read_register_bits(state->d, xd_p_fec_vtb_rsd_mon_en,					fec_vtb_rsd_mon_en_pos,					fec_vtb_rsd_mon_en_len, &temp);	if (ret)		return ret;	if (temp & 1) {		ret =		    af9005_read_register_bits(state->d,					      xd_p_reg_ofsm_read_rbc_en,					      reg_ofsm_read_rbc_en_pos,					      reg_ofsm_read_rbc_en_len, &temp);		if (ret)			return ret;		if ((temp & 1) == 0)			*available = true;	}	return 0;}static int af9005_get_post_vit_err_cw_count(struct dvb_frontend *fe,					    u32 * post_err_count,					    u32 * post_cw_count,					    u16 * abort_count){	struct af9005_fe_state *state = fe->demodulator_priv;	int ret;	u32 err_count;	u32 cw_count;	u8 temp, temp0, temp1, temp2;	u16 loc_abort_count;	*post_err_count = 0;	*post_cw_count = 0;	/* check if error bit count is ready */	ret =	    af9005_read_register_bits(state->d, xd_r_fec_rsd_ber_rdy,				      fec_rsd_ber_rdy_pos, fec_rsd_ber_rdy_len,				      &temp);	if (ret)		return ret;	if (!temp) {		deb_info("rsd counter not ready\n");		return 100;	}	/* get abort count */	ret =	    af9005_read_ofdm_register(state->d,				      xd_r_fec_rsd_abort_packet_cnt_7_0,				      &temp0);	if (ret)		return ret;	ret =	    af9005_read_ofdm_register(state->d,				      xd_r_fec_rsd_abort_packet_cnt_15_8,				      &temp1);	if (ret)		return ret;	loc_abort_count = ((u16) temp1 << 8) + temp0;	/* get error count */	ret =	    af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_7_0,				      &temp0);	if (ret)		return ret;	ret =	    af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_15_8,				      &temp1);	if (ret)		return ret;	ret =	    af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_23_16,				      &temp2);	if (ret)		return ret;	err_count = ((u32) temp2 << 16) + ((u32) temp1 << 8) + temp0;	*post_err_count = err_count - (u32) loc_abort_count *8 * 8;	/* get RSD packet number */	ret =	    af9005_read_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_7_0,				      &temp0);	if (ret)		return ret;	ret =	    af9005_read_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_15_8,				      &temp1);	if (ret)		return ret;	cw_count = ((u32) temp1 << 8) + temp0;	if (cw_count == 0) {		err("wrong RSD packet count");		return -EIO;	}	deb_info("POST abort count %d err count %d rsd packets %d\n",		 loc_abort_count, err_count, cw_count);	*post_cw_count = cw_count - (u32) loc_abort_count;	*abort_count = loc_abort_count;	return 0;}static int af9005_get_post_vit_ber(struct dvb_frontend *fe,				   u32 * post_err_count, u32 * post_cw_count,				   u16 * abort_count){	u32 loc_cw_count = 0, loc_err_count;	u16 loc_abort_count;	int ret;	ret =	    af9005_get_post_vit_err_cw_count(fe, &loc_err_count, &loc_cw_count,					     &loc_abort_count);	if (ret)		return ret;	*post_err_count = loc_err_count;	*post_cw_count = loc_cw_count * 204 * 8;	*abort_count = loc_abort_count;	return 0;}static int af9005_get_pre_vit_err_bit_count(struct dvb_frontend *fe,					    u32 * pre_err_count,					    u32 * pre_bit_count){	struct af9005_fe_state *state = fe->demodulator_priv;	u8 temp, temp0, temp1, temp2;	u32 super_frame_count, x, bits;	int ret;	ret =	    af9005_read_register_bits(state->d, xd_r_fec_vtb_ber_rdy,				      fec_vtb_ber_rdy_pos, fec_vtb_ber_rdy_len,				      &temp);	if (ret)		return ret;	if (!temp) {		deb_info("viterbi counter not ready\n");		return 101;	/* ERR_APO_VTB_COUNTER_NOT_READY; */	}	ret =	    af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_7_0,				      &temp0);	if (ret)		return ret;	ret =	    af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_15_8,				      &temp1);	if (ret)		return ret;	ret =	    af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_23_16,				      &temp2);	if (ret)		return ret;	*pre_err_count = ((u32) temp2 << 16) + ((u32) temp1 << 8) + temp0;	ret =	    af9005_read_ofdm_register(state->d, xd_p_fec_super_frm_unit_7_0,				      &temp0);	if (ret)		return ret;	ret =	    af9005_read_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8,				      &temp1);	if (ret)		return ret;	super_frame_count = ((u32) temp1 << 8) + temp0;	if (super_frame_count == 0) {		deb_info("super frame count 0\n");		return 102;	}	/* read fft mode */	ret =	    af9005_read_register_bits(state->d, xd_g_reg_tpsd_txmod,				      reg_tpsd_txmod_pos, reg_tpsd_txmod_len,				      &temp);	if (ret)		return ret;	if (temp == 0) {		/* 2K */		x = 1512;	} else if (temp == 1) {		/* 8k */		x = 6048;	} else {		err("Invalid fft mode");		return -EINVAL;	}	/* read constellation mode */	ret =	    af9005_read_register_bits(state->d, xd_g_reg_tpsd_const,				      reg_tpsd_const_pos, reg_tpsd_const_len,				      &temp);	if (ret)		return ret;	switch (temp) {	case 0:		/* QPSK */		bits = 2;		break;	case 1:		/* QAM_16 */		bits = 4;		break;	case 2:		/* QAM_64 */		bits = 6;		break;	default:		err("invalid constellation mode");		return -EINVAL;	}	*pre_bit_count = super_frame_count * 68 * 4 * x * bits;	deb_info("PRE err count %d frame count %d bit count %d\n",		 *pre_err_count, super_frame_count, *pre_bit_count);	return 0;}static int af9005_reset_pre_viterbi(struct dvb_frontend *fe){	struct af9005_fe_state *state = fe->demodulator_priv;	int ret;	/* set super frame count to 1 */	ret =	    af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_7_0,				       1 & 0xff);	if (ret)		return ret;	ret = af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8,					 1 >> 8);	if (ret)		return ret;	/* reset pre viterbi error count */	ret =	    af9005_write_register_bits(state->d, xd_p_fec_vtb_ber_rst,				       fec_vtb_ber_rst_pos, fec_vtb_ber_rst_len,				       1);	return ret;}static int af9005_reset_post_viterbi(struct dvb_frontend *fe){	struct af9005_fe_state *state = fe->demodulator_priv;	int ret;	/* set packet unit */	ret =	    af9005_write_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_7_0,				       10000 & 0xff);	if (ret)		return ret;	ret =	    af9005_write_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_15_8,				       10000 >> 8);	if (ret)		return ret;	/* reset post viterbi error count */	ret =	    af9005_write_register_bits(state->d, xd_p_fec_rsd_ber_rst,				       fec_rsd_ber_rst_pos, fec_rsd_ber_rst_len,				       1);	return ret;}static int af9005_get_statistic(struct dvb_frontend *fe){	struct af9005_fe_state *state = fe->demodulator_priv;	int ret, fecavailable;	u64 numerator, denominator;	deb_info("GET STATISTIC\n");	ret = af9005_is_fecmon_available(fe, &fecavailable);	if (ret)		return ret;	if (!fecavailable) {		deb_info("fecmon not available\n");		return 0;	}	ret = af9005_get_pre_vit_err_bit_count(fe, &state->pre_vit_error_count,					       &state->pre_vit_bit_count);	if (ret == 0) {		af9005_reset_pre_viterbi(fe);		if (state->pre_vit_bit_count > 0) {			/* according to v 0.0.4 of the dvb api ber should be a multiple			   of 10E-9 so we have to multiply the error count by			   10E9=1000000000 */			numerator =			    (u64) state->pre_vit_error_count * (u64) 1000000000;			denominator = (u64) state->pre_vit_bit_count;			state->ber = do_div(numerator, denominator);		} else {			state->ber = 0xffffffff;		}	}	ret = af9005_get_post_vit_ber(fe, &state->post_vit_error_count,				      &state->post_vit_bit_count,				      &state->abort_count);	if (ret == 0) {		ret = af9005_reset_post_viterbi(fe);		state->unc += state->abort_count;		if (ret)			return ret;	}	return 0;}static int af9005_fe_refresh_state(struct dvb_frontend *fe){	struct af9005_fe_state *state = fe->demodulator_priv;	if (time_after(jiffies, state->next_status_check)) {		deb_info("REFRESH STATE\n");		/* statistics */		if (af9005_get_statistic(fe))			err("get_statistic_failed");		state->next_status_check = jiffies + 250 * HZ / 1000;	}	return 0;}static int af9005_fe_read_status(struct dvb_frontend *fe, fe_status_t * stat){	struct af9005_fe_state *state = fe->demodulator_priv;	u8 temp;#if 0	/* adjust mt2060 for strong signal (test) */	u8 buf[2];	struct i2c_msg msg = {		.addr = 0xc0,.flags = 0,.buf = buf,.len = 2	};#endif	int ret;	if (fe->ops.tuner_ops.release == NULL)		return -ENODEV;	*stat = 0;	ret = af9005_read_register_bits(state->d, xd_p_agc_lock,					agc_lock_pos, agc_lock_len, &temp);	if (ret)		return ret;	if (temp)		*stat |= FE_HAS_SIGNAL;	ret = af9005_read_register_bits(state->d, xd_p_fd_tpsd_lock,					fd_tpsd_lock_pos, fd_tpsd_lock_len,					&temp);	if (ret)		return ret;	if (temp)		*stat |= FE_HAS_CARRIER;	ret = af9005_read_register_bits(state->d,					xd_r_mp2if_sync_byte_locked,					mp2if_sync_byte_locked_pos,					mp2if_sync_byte_locked_pos, &temp);	if (ret)		return ret;	if (temp)		*stat |= FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_LOCK;	if (state->opened)		af9005_led_control(state->d, *stat & FE_HAS_LOCK);	ret =	    af9005_read_register_bits(state->d, xd_p_reg_strong_sginal_detected,				      reg_strong_sginal_detected_pos,				      reg_strong_sginal_detected_len, &temp);	if (ret)		return ret;	if (temp != state->strong) {		deb_info("adjust for strong signal %d\n", temp);#if 0		/* adjust mt2060 for strong signal (test) */		buf[0] = 0x0b;		if (temp) {			buf[1] = 0x30;		} else {			buf[1] = 0x33;		}		if (i2c_transfer(&state->d->i2c_adap, &msg, 1) != 1) {			err("aiaiaia");		} else#endif			state->strong = temp;	}	return 0;}static int af9005_fe_read_ber(struct dvb_frontend *fe, u32 * ber){	struct af9005_fe_state *state = fe->demodulator_priv;	if (fe->ops.tuner_ops.release  == NULL)		return -ENODEV;	af9005_fe_refresh_state(fe);	*ber = state->ber;	return 0;}static int af9005_fe_read_unc_blocks(struct dvb_frontend *fe, u32 * unc){	struct af9005_fe_state *state = fe->demodulator_priv;	if (fe->ops.tuner_ops.release == NULL)		return -ENODEV;	af9005_fe_refresh_state(fe);	*unc = state->unc;	return 0;}static int af9005_fe_read_signal_strength(struct dvb_frontend *fe,					  u16 * strength){	struct af9005_fe_state *state = fe->demodulator_priv;	int ret;	u8 if_gain, rf_gain;	if (fe->ops.tuner_ops.release == NULL)		return -ENODEV;	ret =	    af9005_read_ofdm_register(state->d, xd_r_reg_aagc_rf_gain,				      &rf_gain);	if (ret)		return ret;	ret =

⌨️ 快捷键说明

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