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

📄 dib3000mc.c~

📁 asus U3100 DMBTH 電視棒反釋源碼
💻 C~
字号:
/* * Driver for DiBcom DiB3000MC/P-demodulator. * * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/) * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * * This code is partially based on the previous dib3000mc.c . * * 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. */#include <linux/kernel.h>#include <linux/i2c.h>//#include <linux/init.h>//#include <linux/delay.h>//#include <linux/string.h>//#include <linux/slab.h>#include "dvb_frontend.h"#include "dib3000mc.h"static int debug;module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0)struct dib3000mc_state {	struct dvb_frontend demod;	struct dib3000mc_config *cfg;	u8 i2c_addr;	struct i2c_adapter *i2c_adap;	struct dibx000_i2c_master i2c_master;	u32 timf;	fe_bandwidth_t current_bandwidth;	u16 dev_id;};unsigned int lg8934lock;void ComputeSectionAddress(unsigned char reg, unsigned char *result_reg) {	unsigned int tmp;	if(reg < 0xc0)		tmp = 0xffffffff;	else		tmp = 0;	*result_reg = (tmp & 0xfc) + 0x36;}EXPORT_SYMBOL(ComputeSectionAddress);static int dib3000mc_init(struct dvb_frontend *demod){	return 0;}static int dib3000mc_sleep(struct dvb_frontend *demod){    return 0;}static int dib3000mc_get_frontend(struct dvb_frontend* fe,				struct dvb_frontend_parameters *fep){	return 0;}static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber){	return 0;}static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc){	return 0;}static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength){	return 0;}static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr){	*snr = 0x0000;	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;}int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff){	return 0;}EXPORT_SYMBOL(dib3000mc_pid_control);int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff){	return 0;}EXPORT_SYMBOL(dib3000mc_pid_parse);void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg){	struct dib3000mc_state *state = fe->demodulator_priv;	state->cfg = cfg;}EXPORT_SYMBOL(dib3000mc_set_config);int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[]){	return 0;}EXPORT_SYMBOL(dib3000mc_i2c_enumeration);static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat){	unsigned int lock;	lock = lg8934lock;	dprintk("lock status %d\n", lock);	if(lg8934lock < 1)		lock = 0xffffffff;	else		lock = 0;	lock = ~lock;	lock = lock &  0x1f;	*stat = lock;	return 0;}static int dib3000mc_write_byte(struct dib3000mc_state *state, unsigned char reg, unsigned char val){	struct i2c_msg msg;	unsigned char wb[2];	unsigned char seg_reg;	wb[0] = reg;	wb[1] = val;	ComputeSectionAddress(reg, &seg_reg);	msg.addr = state->i2c_addr = (seg_reg>>1);	msg.flags = 0;	msg.len = 2;	msg.buf = wb;	return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;}int lgs8934_SetManualParameters(struct dib3000mc_state *state, unsigned char val) {	int result;	result = dib3000mc_write_byte(state, 0x7d, val|0x40);	if(result != 0)		return 1;	result = dib3000mc_write_byte(state, 0xc0, val|0x40);	if(result != 0)		return 1;	return 0;}EXPORT_SYMBOL(lgs8934_SetManualParameters);static int dib3000mc_read_byte(struct dib3000mc_state *state, u8 reg, unsigned char *i2c_read_result){	struct i2c_msg msg[2];	unsigned char wb[2];	unsigned char rb[2];	unsigned char seg_reg;	wb[0] = reg;	wb[1] = reg;	ComputeSectionAddress(reg, &seg_reg);	msg[0].addr = msg[1].addr = state->i2c_addr = (seg_reg >> 1);	msg[0].buf = wb;	msg[0].flags = 0;	msg[0].len = 2;	msg[1].flags = I2C_M_RD;	msg[1].len = 2;	msg[1].buf = rb;	if (i2c_transfer(state->i2c_adap, msg, 2) !=2) {		printk("i2c read error on %d\n",reg);		return 1;	}	*i2c_read_result = rb[0];	return 0;}void IsLgs8934Lock(struct dib3000mc_state *state, unsigned char *result) {	unsigned char i2c_read_result;	i2c_read_result = 0;	dib3000mc_read_byte(state, 0x4b, &i2c_read_result);	i2c_read_result &= 0xc0;	printk("LGS8934 Lock (%d)!!", (*result = (i2c_read_result == 0xc0 ? 1 : 0)));}EXPORT_SYMBOL(IsLgs8934Lock);void lgs8934_SetManualMode(struct dib3000mc_state *state) {	unsigned char i2c_read_result;	if(dib3000mc_read_byte(state, 0x7e, &i2c_read_result) != 0) {		printk("SetMaualMode Failed\n");		return;	}	i2c_read_result &= 0xfe;	if(dib3000mc_write_byte(state, 0x7e, i2c_read_result) != 0) {		printk("SetMaualMode Failed\n");		return;	}	if(dib3000mc_read_byte(state, 0x7e, &i2c_read_result) != 0) {		printk("SetMaualMode Failed\n");		return;	}	if(dib3000mc_read_byte(state, 0xc1, &i2c_read_result) != 0) {		printk("SetMaualMode Failed\n");		return;	}	i2c_read_result &= 0xfe;	if(dib3000mc_write_byte(state, 0xc1, i2c_read_result) != 0) {		printk("SetMaualMode Failed\n");	}}EXPORT_SYMBOL(lgs8934_SetManualMode);void DumpConfigedReg(struct dib3000mc_state *state) {	unsigned char i2c_read_result;	if(dib3000mc_read_byte(state, 0x04, &i2c_read_result) != 0) {		printk("DumpConfigedReg Failed\n");		return;	}	if(dib3000mc_read_byte(state, 0x7d, &i2c_read_result) != 0) {		printk("DumpConfigedReg Failed\n");		return;	}	if(dib3000mc_read_byte(state, 0xc8, &i2c_read_result) != 0) {		printk("DumpConfigedReg Failed\n");		return;	}	if(dib3000mc_read_byte(state, 0x37, &i2c_read_result) != 0) {		printk("DumpConfigedReg Failed\n");		return;	}	if(dib3000mc_read_byte(state, 0xc2, &i2c_read_result) != 0) {		printk("DumpConfigedReg Failed\n");		return;	}	if(dib3000mc_read_byte(state, 0x7c, &i2c_read_result) != 0) {		printk("DumpConfigedReg Failed\n");		return;	}}EXPORT_SYMBOL(DumpConfigedReg);void lgs8934_SetAutoMode(struct dib3000mc_state *state) {	unsigned char i2c_read_result;	printk("lgs8934_SetAutoMode! \n");	if(dib3000mc_read_byte(state, 0x4b, &i2c_read_result))		goto FAILED;	if(dib3000mc_read_byte(state, 0xc2, &i2c_read_result))		goto FAILED;	if(dib3000mc_write_byte(state, 0xc2, 0x0a))		goto FAILED;	if(dib3000mc_write_byte(state, 0x7c, 0x07))		goto FAILED;	if(dib3000mc_write_byte(state, 0x07, 0x9f))		goto FAILED;	if(dib3000mc_write_byte(state, 0x09, 0x00))		goto FAILED;	if(dib3000mc_write_byte(state, 0x0a, 0x00))		goto FAILED;	if(dib3000mc_write_byte(state, 0x0b, 0x00))		goto FAILED;	if(dib3000mc_write_byte(state, 0x0c, 0x00))		goto FAILED;	if(dib3000mc_write_byte(state, 0xc5, 0x00))		goto FAILED;	if(dib3000mc_write_byte(state, 0x03, 0x00))		goto FAILED;	if(dib3000mc_write_byte(state, 0x7e, 0x01))		goto FAILED;	if(dib3000mc_write_byte(state, 0xc1, 0x01))		goto FAILED;	if(dib3000mc_write_byte(state, 0x2d, 0x00))		goto FAILED;	dib3000mc_write_byte(state, 0x2e, 0x62);FAILED:	printk("lgs8934_SetAutoMode Failed");}EXPORT_SYMBOL(lgs8934_SetAutoMode);int lgs8934_WaitForLock(struct dib3000mc_state *state, unsigned char reg, unsigned char mask, unsigned char target, int sleep_amount, unsigned char *error_code, int retries){	int tries;	unsigned char i2c_read_result;	if(retries <= 0)		goto FAILED; /* please forgive me to write goto statements, or else the code won't look alike (though it's equivalent) */	tries = 0;	do{		msleep(sleep_amount);		if(dib3000mc_read_byte(state, reg, &i2c_read_result))			*error_code = i2c_read_result;		if((i2c_read_result & mask) == target) {			lg8934lock = 1;			printk("LGS8934 Locked!!");			return 1;		}		tries++;	} while(tries != retries);FAILED:	return 0;}EXPORT_SYMBOL(lgs8934_WaitForLock);static int lgs8934_softreset(struct dib3000mc_state *state) {	unsigned char i2c_read_result;	if(dib3000mc_read_byte(state, 0x02, &i2c_read_result))		goto FAILED;	i2c_read_result &= 0xfe;	if(dib3000mc_write_byte(state, 0x02, i2c_read_result))		goto FAILED;	msleep(100);	i2c_read_result |= 0x01;	if(dib3000mc_write_byte(state, 0x02, i2c_read_result))		goto FAILED;	msleep(500);	return 0;FAILED:	return 1;}void CloseEcho(struct dib3000mc_state *state){	unsigned char i2c_read_result;	if(dib3000mc_read_byte(state, 0x01, &i2c_read_result))		goto FAILED;	if(dib3000mc_write_byte(state, 0x01, i2c_read_result & 0x7f))		goto FAILED;	lgs8934_softreset(state);FAILED:	printk("\t CloseEcho is failed!");}EXPORT_SYMBOL(CloseEcho);void OpenEcho(struct dib3000mc_state *state, unsigned char val) {	val = (val >> 1) | 0x80;	if(dib3000mc_write_byte(state, 0x01, val))		goto FAILED;	lgs8934_softreset(state);FAILED:	printk("\t OpenEcho is failed!");}EXPORT_SYMBOL(OpenEcho);void lgs8934_auto_detect(struct dib3000mc_state *state, unsigned int *unused) {	unsigned char i2c_write_data;	int tries;	tries = 0;	printk("lgs8934_auto_detect! \n");	do {/*		if((tries & 1) == 0)			i2c_write_data = 0;		else if(((tries & 1)-1) == 0)			i2c_write_data = 2;		else			i2c_write_data = 0;*//* oh well, no matter how i'm rewriting this, it's just not the same...  seems my code is more optimized? */		if(!(tries & 1))			i2c_write_data = 0;		else			i2c_write_data = 2;		if(dib3000mc_write_byte(state, 0x04, i2c_write_data))			goto RETRY;		lgs8934_softreset(state);		msleep(200);		if(lgs8934_WaitForLock(state, 0x4b, 0xc0, 0xc0, 500, &i2c_write_data, 2) == 0)			goto RETRY;		if(dib3000mc_read_byte(state, 0xa2, &i2c_write_data))			goto RETRY;		if(lgs8934_SetManualParameters(state, i2c_write_data))			goto RETRY;		break;RETRY:		tries++;	} while (tries != 2);}EXPORT_SYMBOL(lgs8934_auto_detect);static int dib3000mc_set_frontend(struct dvb_frontend* fe,				struct dvb_frontend_parameters *fep){	struct dib3000mc_state *state;	fe->ops.tuner_ops.set_params(fe, fep);	state = fe->demodulator_priv;	lg8934lock = 0;	lgs8934_SetAutoMode(state);	lgs8934_auto_detect(state, &lg8934lock);	lgs8934_SetManualMode(state);	lgs8934_softreset(state);	DumpConfigedReg(state);	printk("lgs8934_auto_detect, lock %d\n", lg8934lock);	return 0;}static void dib3000mc_release(struct dvb_frontend *fe){	struct dib3000mc_state *state = fe->demodulator_priv;	dibx000_exit_i2c_master(&state->i2c_master);	kfree(state);}static struct dvb_frontend_ops dib3000mc_ops;struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg){	struct dvb_frontend *demod;	struct dib3000mc_state *st;	unsigned char i2c_read_data;	st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);	if (st == NULL)		return NULL;	st->cfg = cfg;	st->i2c_adap = i2c_adap;	st->i2c_addr = i2c_addr;	demod                   = &st->demod;	demod->demodulator_priv = st;	memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));		i2c_read_data = 0xff;	dib3000mc_read_byte(st, 0, &i2c_read_data);	if(i2c_read_data == 0x0c) {		printk("Found LGS8934 version=%x\n", 0x0c);	} else {		printk("Cannot find LGS8934\n");	}	st->dev_id = 	dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);	return demod;}EXPORT_SYMBOL(dib3000mc_attach);struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating){	struct dib3000mc_state *st = demod->demodulator_priv;	return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);}EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);static struct dvb_frontend_ops dib3000mc_ops = {	.info = {		.name = "Legend Slilicon 8934",		.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_init,	.sleep                = dib3000mc_sleep,	.set_frontend         = dib3000mc_set_frontend,	.get_tune_settings    = dib3000mc_fe_get_tune_settings,	.get_frontend         = dib3000mc_get_frontend,	.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("JHA <jha.hsiao@gmail.com>");MODULE_DESCRIPTION("Driver for the Legend 8934 demodulator");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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