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

📄 dvb-dibusb-fe-i2c.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * dvb-dibusb-fe-i2c.c is part of the driver for mobile USB Budget DVB-T devices  * based on reference design made by DiBcom (http://www.dibcom.fr/) * * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * * see dvb-dibusb-core.c for more copyright details. * * This file contains functions for attaching, initializing of an appropriate * demodulator/frontend. I2C-stuff is also located here. *  */#include "dvb-dibusb.h"#include <linux/usb.h>int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr, 		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen){	u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */	/* write only ? */	int wo = (rbuf == NULL || rlen == 0), 		len = 2 + wlen + (wo ? 0 : 2);		sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;	sndbuf[1] = (addr << 1) | (wo ? 0 : 1);	memcpy(&sndbuf[2],wbuf,wlen);		if (!wo) {		sndbuf[wlen+2] = (rlen >> 8) & 0xff;		sndbuf[wlen+3] = rlen & 0xff;	}		return dibusb_readwrite_usb(dib,sndbuf,len,rbuf,rlen);}/* * I2C master xfer function */static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num){	struct usb_dibusb *dib = i2c_get_adapdata(adap);	int i;	if (down_interruptible(&dib->i2c_sem) < 0) 		return -EAGAIN;	if (num > 2)		warn("more than 2 i2c messages at a time is not handled yet. TODO.");		for (i = 0; i < num; i++) {		/* write/read request */		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {			if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,						msg[i+1].buf,msg[i+1].len) < 0)				break;			i++;		} else 			if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)				break;	}		up(&dib->i2c_sem);	return i;	}static u32 dibusb_i2c_func(struct i2c_adapter *adapter){	return I2C_FUNC_I2C;}static struct i2c_algorithm dibusb_algo = {	.name			= "DiBcom USB i2c algorithm",	.id				= I2C_ALGO_BIT,	.master_xfer	= dibusb_i2c_xfer,	.functionality	= dibusb_i2c_func,};static int dibusb_general_demod_init(struct dvb_frontend *fe);static u8 dibusb_general_pll_addr(struct dvb_frontend *fe);static int dibusb_general_pll_init(struct dvb_frontend *fe, u8 pll_buf[5]);static int dibusb_general_pll_set(struct dvb_frontend *fe, 		struct dvb_frontend_parameters* params, u8 pll_buf[5]);static struct mt352_config mt352_hanftek_umt_010_config = {	.demod_address = 0x1e,	.demod_init = dibusb_general_demod_init,   	.pll_set = dibusb_general_pll_set,};static int dibusb_tuner_quirk(struct usb_dibusb *dib) {	switch (dib->dibdev->dev_cl->id) {		case DIBUSB1_1: /* some these device have the ENV77H11D5 and some the THOMSON CABLE */		case DIBUSB1_1_AN2235: { /* actually its this device, but in warm state they are indistinguishable */			struct dibusb_tuner *t;			u8 b[2] = { 0,0 } ,b2[1];			struct i2c_msg msg[2] = {				{ .flags = 0, .buf = b, .len = 2 },				{ .flags = I2C_M_RD, .buf = b2, .len = 1},			};						t = &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5];						msg[0].addr = msg[1].addr = t->pll_addr;					if (dib->xfer_ops.tuner_pass_ctrl != NULL)				dib->xfer_ops.tuner_pass_ctrl(dib->fe,1,t->pll_addr);			dibusb_i2c_xfer(&dib->i2c_adap,msg,2);			if (dib->xfer_ops.tuner_pass_ctrl != NULL)				dib->xfer_ops.tuner_pass_ctrl(dib->fe,0,t->pll_addr);			if (b2[0] == 0xfe)				info("this device has the Thomson Cable onboard. Which is default.");			else {				dib->tuner = t;				info("this device has the Panasonic ENV77H11D5 onboard.");			}			break;			}		default:			break;	}	return 0;}/* there is a ugly pid_filter in the firmware of the umt devices, it is accessible  * by i2c address 0x8. Don't know how to deactivate it and how many rows it has. */static int dibusb_umt_pid_control(struct dvb_frontend *fe, int index, int pid, int onoff){	struct usb_dibusb *dib = fe->dvb->priv;	u8 b[3];	b[0] = index;	if (onoff) {		b[1] = (pid >> 8) & 0xff;		b[2] = pid & 0xff;	} else {		b[1] = 0;		b[2] = 0;	}	dibusb_i2c_msg(dib, 0x8, b, 3, NULL,0);	dibusb_set_streaming_mode(dib,0);	dibusb_set_streaming_mode(dib,1);	return 0;}int dibusb_fe_init(struct usb_dibusb* dib){	struct dib3000_config demod_cfg;	int i;		if (dib->init_state & DIBUSB_STATE_I2C) { 		for (i = 0; i < sizeof(dib->dibdev->dev_cl->demod->i2c_addrs) / sizeof(unsigned char) && 				dib->dibdev->dev_cl->demod->i2c_addrs[i] != 0; i++) {			demod_cfg.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];			demod_cfg.pll_addr = dibusb_general_pll_addr;			demod_cfg.pll_set = dibusb_general_pll_set;			demod_cfg.pll_init = dibusb_general_pll_init;			switch (dib->dibdev->dev_cl->demod->id) {				case DIBUSB_DIB3000MB:					dib->fe = dib3000mb_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);				break;				case DIBUSB_DIB3000MC:					dib->fe = dib3000mc_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);				break;				case DIBUSB_MT352:					mt352_hanftek_umt_010_config.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];					dib->fe = mt352_attach(&mt352_hanftek_umt_010_config, &dib->i2c_adap);					dib->xfer_ops.pid_ctrl = dibusb_umt_pid_control;				break;			}			if (dib->fe != NULL) {				info("found demodulator at i2c address 0x%x",dib->dibdev->dev_cl->demod->i2c_addrs[i]);				break;			}		}		if (dib->fe->ops->sleep != NULL)			dib->fe_sleep = dib->fe->ops->sleep;		dib->fe->ops->sleep = dibusb_hw_sleep;		if (dib->fe->ops->init != NULL ) 			dib->fe_init = dib->fe->ops->init;		dib->fe->ops->init = dibusb_hw_wakeup;			/* setting the default tuner */ 		dib->tuner = dib->dibdev->dev_cl->tuner;		/* check which tuner is mounted on this device, in case this is unsure */		dibusb_tuner_quirk(dib);	}	if (dib->fe == NULL) {		err("A frontend driver was not found for device '%s'.",		       dib->dibdev->name);		return -ENODEV;	} else {		if (dvb_register_frontend(dib->adapter, dib->fe)) {			err("Frontend registration failed.");			if (dib->fe->ops->release)				dib->fe->ops->release(dib->fe);			dib->fe = NULL;			return -ENODEV;		}	}	return 0;}int dibusb_fe_exit(struct usb_dibusb *dib){	if (dib->fe != NULL)		dvb_unregister_frontend(dib->fe);	return 0;}int dibusb_i2c_init(struct usb_dibusb *dib){	int ret = 0;	dib->adapter->priv = dib;	strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE);#ifdef I2C_ADAP_CLASS_TV_DIGITAL	dib->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,#else	dib->i2c_adap.class = I2C_CLASS_TV_DIGITAL,#endif	dib->i2c_adap.algo 		= &dibusb_algo;	dib->i2c_adap.algo_data = NULL;	dib->i2c_adap.id		= I2C_ALGO_BIT;		i2c_set_adapdata(&dib->i2c_adap, dib);		if ((ret = i2c_add_adapter(&dib->i2c_adap)) < 0)		err("could not add i2c adapter");		dib->init_state |= DIBUSB_STATE_I2C;	return ret;}int dibusb_i2c_exit(struct usb_dibusb *dib){	if (dib->init_state & DIBUSB_STATE_I2C)		i2c_del_adapter(&dib->i2c_adap);	dib->init_state &= ~DIBUSB_STATE_I2C;	return 0;}/* pll stuff, maybe removed soon (thx to Gerd/Andrew in advance) */static int thomson_cable_eu_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4]){	u32 tfreq = (fep->frequency + 36125000) / 62500;	int vu,p0,p1,p2;	if (fep->frequency > 403250000)		vu = 1, p2 = 1, p1 = 0, p0 = 1;	else if (fep->frequency > 115750000)		vu = 0, p2 = 1, p1 = 1, p0 = 0;	else if (fep->frequency > 44250000)		vu = 0, p2 = 0, p1 = 1, p0 = 1;	else		return -EINVAL;	pllbuf[0] = (tfreq >> 8) & 0x7f;	pllbuf[1] = tfreq & 0xff;   	pllbuf[2] = 0x8e;   	pllbuf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0;	return 0;}static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4]){	u32 freq = fep->frequency;	u32 tfreq = ((freq + 36125000)*6 + 500000) / 1000000;	u8 TA, T210, R210, ctrl1, cp210, p4321;	if (freq > 858000000) {		err("frequency cannot be larger than 858 MHz.");		return -EINVAL;	}		// contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0	TA = 1;	T210 = 0;	R210 = 0x2;	ctrl1 = (1 << 7) | (TA << 6) | (T210 << 3) | R210;// ********    CHARGE PUMP CONFIG vs RF FREQUENCIES     *****************	if (freq < 470000000) 		cp210 = 2;  // VHF Low and High band ch E12 to E4 to E12	else if (freq < 526000000) 		cp210 = 4;  // UHF band Ch E21 to E27	else // if (freq < 862000000) 		cp210 = 5;  // UHF band ch E28 to E69//*********************    BW select  *******************************	if (freq < 153000000) 

⌨️ 快捷键说明

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