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

📄 mxl5007t.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  mxl5007t.c - driver for the MaxLinear MxL5007T silicon tuner * *  Copyright (C) 2008 Michael Krufky <mkrufky@linuxtv.org> * *  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. */#include <linux/i2c.h>#include <linux/types.h>#include "compat.h"#include <linux/videodev2.h>#include "tuner-i2c.h"#include "mxl5007t.h"static DEFINE_MUTEX(mxl5007t_list_mutex);static LIST_HEAD(hybrid_tuner_instance_list);static int mxl5007t_debug;module_param_named(debug, mxl5007t_debug, int, 0644);MODULE_PARM_DESC(debug, "set debug level");/* ------------------------------------------------------------------------- */#define mxl_printk(kern, fmt, arg...) \	printk(kern "%s: " fmt "\n", __func__, ##arg)#define mxl_err(fmt, arg...) \	mxl_printk(KERN_ERR, "%d: " fmt, __LINE__, ##arg)#define mxl_warn(fmt, arg...) \	mxl_printk(KERN_WARNING, fmt, ##arg)#define mxl_info(fmt, arg...) \	mxl_printk(KERN_INFO, fmt, ##arg)#define mxl_debug(fmt, arg...)				\({							\	if (mxl5007t_debug)				\		mxl_printk(KERN_DEBUG, fmt, ##arg);	\})#define mxl_fail(ret)							\({									\	int __ret;							\	__ret = (ret < 0);						\	if (__ret)							\		mxl_printk(KERN_ERR, "error %d on line %d",		\			   ret, __LINE__);				\	__ret;								\})/* ------------------------------------------------------------------------- */#define MHz 1000000enum mxl5007t_mode {	MxL_MODE_OTA_DVBT_ATSC        =    0,	MxL_MODE_OTA_NTSC_PAL_GH      =    1,	MxL_MODE_OTA_PAL_IB           =    2,	MxL_MODE_OTA_PAL_D_SECAM_KL   =    3,	MxL_MODE_OTA_ISDBT            =    4,	MxL_MODE_CABLE_DIGITAL        = 0x10,	MxL_MODE_CABLE_NTSC_PAL_GH    = 0x11,	MxL_MODE_CABLE_PAL_IB         = 0x12,	MxL_MODE_CABLE_PAL_D_SECAM_KL = 0x13,	MxL_MODE_CABLE_SCTE40         = 0x14,};enum mxl5007t_chip_version {	MxL_UNKNOWN_ID     = 0x00,	MxL_5007_V1_F1     = 0x11,	MxL_5007_V1_F2     = 0x12,	MxL_5007_V2_100_F1 = 0x21,	MxL_5007_V2_100_F2 = 0x22,	MxL_5007_V2_200_F1 = 0x23,	MxL_5007_V2_200_F2 = 0x24,};struct reg_pair_t {	u8 reg;	u8 val;};/* ------------------------------------------------------------------------- */static struct reg_pair_t init_tab[] = {	{ 0x0b, 0x44 }, /* XTAL */	{ 0x0c, 0x60 }, /* IF */	{ 0x10, 0x00 }, /* MISC */	{ 0x12, 0xca }, /* IDAC */	{ 0x16, 0x90 }, /* MODE */	{ 0x32, 0x38 }, /* MODE Analog/Digital */	{ 0xd8, 0x18 }, /* CLK_OUT_ENABLE */	{ 0x2c, 0x34 }, /* OVERRIDE */	{ 0x4d, 0x40 }, /* OVERRIDE */	{ 0x7f, 0x02 }, /* OVERRIDE */	{ 0x9a, 0x52 }, /* OVERRIDE */	{ 0x48, 0x5a }, /* OVERRIDE */	{ 0x76, 0x1a }, /* OVERRIDE */	{ 0x6a, 0x48 }, /* OVERRIDE */	{ 0x64, 0x28 }, /* OVERRIDE */	{ 0x66, 0xe6 }, /* OVERRIDE */	{ 0x35, 0x0e }, /* OVERRIDE */	{ 0x7e, 0x01 }, /* OVERRIDE */	{ 0x83, 0x00 }, /* OVERRIDE */	{ 0x04, 0x0b }, /* OVERRIDE */	{ 0x05, 0x01 }, /* TOP_MASTER_ENABLE */	{ 0, 0 }};static struct reg_pair_t init_tab_cable[] = {	{ 0x0b, 0x44 }, /* XTAL */	{ 0x0c, 0x60 }, /* IF */	{ 0x10, 0x00 }, /* MISC */	{ 0x12, 0xca }, /* IDAC */	{ 0x16, 0x90 }, /* MODE */	{ 0x32, 0x38 }, /* MODE A/D */	{ 0x71, 0x3f }, /* TOP1 */	{ 0x72, 0x3f }, /* TOP2 */	{ 0x74, 0x3f }, /* TOP3 */	{ 0xd8, 0x18 }, /* CLK_OUT_ENABLE */	{ 0x2c, 0x34 }, /* OVERRIDE */	{ 0x4d, 0x40 }, /* OVERRIDE */	{ 0x7f, 0x02 }, /* OVERRIDE */	{ 0x9a, 0x52 }, /* OVERRIDE */	{ 0x48, 0x5a }, /* OVERRIDE */	{ 0x76, 0x1a }, /* OVERRIDE */	{ 0x6a, 0x48 }, /* OVERRIDE */	{ 0x64, 0x28 }, /* OVERRIDE */	{ 0x66, 0xe6 }, /* OVERRIDE */	{ 0x35, 0x0e }, /* OVERRIDE */	{ 0x7e, 0x01 }, /* OVERRIDE */	{ 0x04, 0x0b }, /* OVERRIDE */	{ 0x68, 0xb4 }, /* OVERRIDE */	{ 0x36, 0x00 }, /* OVERRIDE */	{ 0x05, 0x01 }, /* TOP_MASTER_ENABLE */	{ 0, 0 }};/* ------------------------------------------------------------------------- */static struct reg_pair_t reg_pair_rftune[] = {	{ 0x11, 0x00 }, /* abort tune */	{ 0x13, 0x15 },	{ 0x14, 0x40 },	{ 0x15, 0x0e },	{ 0x11, 0x02 }, /* start tune */	{ 0, 0 }};/* ------------------------------------------------------------------------- */struct mxl5007t_state {	struct list_head hybrid_tuner_instance_list;	struct tuner_i2c_props i2c_props;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)	struct mutex lock;#else	struct semaphore lock;#endif	struct mxl5007t_config *config;	enum mxl5007t_chip_version chip_id;	struct reg_pair_t tab_init[ARRAY_SIZE(init_tab)];	struct reg_pair_t tab_init_cable[ARRAY_SIZE(init_tab_cable)];	struct reg_pair_t tab_rftune[ARRAY_SIZE(reg_pair_rftune)];	u32 frequency;	u32 bandwidth;};/* ------------------------------------------------------------------------- *//* called by _init and _rftun to manipulate the register arrays */static void set_reg_bits(struct reg_pair_t *reg_pair, u8 reg, u8 mask, u8 val){	unsigned int i = 0;	while (reg_pair[i].reg || reg_pair[i].val) {		if (reg_pair[i].reg == reg) {			reg_pair[i].val &= ~mask;			reg_pair[i].val |= val;		}		i++;	}	return;}static void copy_reg_bits(struct reg_pair_t *reg_pair1,			  struct reg_pair_t *reg_pair2){	unsigned int i, j;	i = j = 0;	while (reg_pair1[i].reg || reg_pair1[i].val) {		while (reg_pair2[j].reg || reg_pair2[j].reg) {			if (reg_pair1[i].reg != reg_pair2[j].reg) {				j++;				continue;			}			reg_pair2[j].val = reg_pair1[i].val;			break;		}		i++;	}	return;}/* ------------------------------------------------------------------------- */static void mxl5007t_set_mode_bits(struct mxl5007t_state *state,				   enum mxl5007t_mode mode,				   s32 if_diff_out_level){	switch (mode) {	case MxL_MODE_OTA_DVBT_ATSC:		set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06);		set_reg_bits(state->tab_init, 0x35, 0xff, 0x0e);		break;	case MxL_MODE_OTA_ISDBT:		set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06);		set_reg_bits(state->tab_init, 0x35, 0xff, 0x12);		break;	case MxL_MODE_OTA_NTSC_PAL_GH:		set_reg_bits(state->tab_init, 0x16, 0x70, 0x00);		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);		break;	case MxL_MODE_OTA_PAL_IB:		set_reg_bits(state->tab_init, 0x16, 0x70, 0x10);		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);		break;	case MxL_MODE_OTA_PAL_D_SECAM_KL:		set_reg_bits(state->tab_init, 0x16, 0x70, 0x20);		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);		break;	case MxL_MODE_CABLE_DIGITAL:		set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);		set_reg_bits(state->tab_init_cable, 0x72, 0xff,			     8 - if_diff_out_level);		set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);		break;	case MxL_MODE_CABLE_NTSC_PAL_GH:		set_reg_bits(state->tab_init, 0x16, 0x70, 0x00);		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);		set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);		set_reg_bits(state->tab_init_cable, 0x72, 0xff,			     8 - if_diff_out_level);		set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);		break;	case MxL_MODE_CABLE_PAL_IB:		set_reg_bits(state->tab_init, 0x16, 0x70, 0x10);		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);		set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);		set_reg_bits(state->tab_init_cable, 0x72, 0xff,			     8 - if_diff_out_level);		set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);		break;	case MxL_MODE_CABLE_PAL_D_SECAM_KL:		set_reg_bits(state->tab_init, 0x16, 0x70, 0x20);		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);		set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);		set_reg_bits(state->tab_init_cable, 0x72, 0xff,			     8 - if_diff_out_level);		set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);		break;	case MxL_MODE_CABLE_SCTE40:		set_reg_bits(state->tab_init_cable, 0x36, 0xff, 0x08);		set_reg_bits(state->tab_init_cable, 0x68, 0xff, 0xbc);		set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);		set_reg_bits(state->tab_init_cable, 0x72, 0xff,			     8 - if_diff_out_level);		set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);		break;	default:		mxl_fail(-EINVAL);	}	return;}static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,				      enum mxl5007t_if_freq if_freq,				      int invert_if){	u8 val;	switch (if_freq) {	case MxL_IF_4_MHZ:		val = 0x00;		break;	case MxL_IF_4_5_MHZ:		val = 0x20;		break;	case MxL_IF_4_57_MHZ:		val = 0x30;		break;	case MxL_IF_5_MHZ:		val = 0x40;		break;	case MxL_IF_5_38_MHZ:		val = 0x50;		break;	case MxL_IF_6_MHZ:		val = 0x60;		break;	case MxL_IF_6_28_MHZ:		val = 0x70;		break;	case MxL_IF_9_1915_MHZ:		val = 0x80;		break;	case MxL_IF_35_25_MHZ:		val = 0x90;		break;	case MxL_IF_36_15_MHZ:		val = 0xa0;		break;	case MxL_IF_44_MHZ:		val = 0xb0;		break;	default:		mxl_fail(-EINVAL);		return;	}	set_reg_bits(state->tab_init, 0x0c, 0xf0, val);	/* set inverted IF or normal IF */	set_reg_bits(state->tab_init, 0x0c, 0x08, invert_if ? 0x08 : 0x00);	return;}static void mxl5007t_set_xtal_freq_bits(struct mxl5007t_state *state,					enum mxl5007t_xtal_freq xtal_freq){	u8 val;	switch (xtal_freq) {	case MxL_XTAL_16_MHZ:		val = 0x00; /* select xtal freq & Ref Freq */		break;	case MxL_XTAL_20_MHZ:		val = 0x11;		break;	case MxL_XTAL_20_25_MHZ:		val = 0x22;		break;	case MxL_XTAL_20_48_MHZ:		val = 0x33;		break;	case MxL_XTAL_24_MHZ:		val = 0x44;		break;	case MxL_XTAL_25_MHZ:		val = 0x55;		break;	case MxL_XTAL_25_14_MHZ:		val = 0x66;		break;	case MxL_XTAL_27_MHZ:		val = 0x77;		break;	case MxL_XTAL_28_8_MHZ:		val = 0x88;		break;	case MxL_XTAL_32_MHZ:		val = 0x99;		break;	case MxL_XTAL_40_MHZ:		val = 0xaa;		break;	case MxL_XTAL_44_MHZ:		val = 0xbb;		break;	case MxL_XTAL_48_MHZ:		val = 0xcc;		break;	case MxL_XTAL_49_3811_MHZ:		val = 0xdd;		break;	default:		mxl_fail(-EINVAL);		return;	}	set_reg_bits(state->tab_init, 0x0b, 0xff, val);	return;}static struct reg_pair_t *mxl5007t_calc_init_regs(struct mxl5007t_state *state,						  enum mxl5007t_mode mode){	struct mxl5007t_config *cfg = state->config;	memcpy(&state->tab_init, &init_tab, sizeof(init_tab));	memcpy(&state->tab_init_cable, &init_tab_cable, sizeof(init_tab_cable));	mxl5007t_set_mode_bits(state, mode, cfg->if_diff_out_level);	mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if);	mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz);	set_reg_bits(state->tab_init, 0x10, 0x40, cfg->loop_thru_enable << 6);	set_reg_bits(state->tab_init, 0xd8, 0x08, cfg->clk_out_enable << 3);	set_reg_bits(state->tab_init, 0x10, 0x07, cfg->clk_out_amp);	/* set IDAC to automatic mode control by AGC */	set_reg_bits(state->tab_init, 0x12, 0x80, 0x00);	if (mode >= MxL_MODE_CABLE_DIGITAL) {		copy_reg_bits(state->tab_init, state->tab_init_cable);		return state->tab_init_cable;	} else		return state->tab_init;}/* ------------------------------------------------------------------------- */enum mxl5007t_bw_mhz {	MxL_BW_6MHz = 6,	MxL_BW_7MHz = 7,	MxL_BW_8MHz = 8,};static void mxl5007t_set_bw_bits(struct mxl5007t_state *state,				 enum mxl5007t_bw_mhz bw){	u8 val;	switch (bw) {	case MxL_BW_6MHz:		val = 0x15; /* set DIG_MODEINDEX, DIG_MODEINDEX_A,			     * and DIG_MODEINDEX_CSF */		break;	case MxL_BW_7MHz:		val = 0x21;		break;	case MxL_BW_8MHz:		val = 0x3f;		break;	default:		mxl_fail(-EINVAL);		return;	}	set_reg_bits(state->tab_rftune, 0x13, 0x3f, val);	return;}static structreg_pair_t *mxl5007t_calc_rf_tune_regs(struct mxl5007t_state *state,				       u32 rf_freq, enum mxl5007t_bw_mhz bw){	u32 dig_rf_freq = 0;	u32 temp;	u32 frac_divider = 1000000;	unsigned int i;	memcpy(&state->tab_rftune, &reg_pair_rftune, sizeof(reg_pair_rftune));	mxl5007t_set_bw_bits(state, bw);	/* Convert RF frequency into 16 bits =>	 * 10 bit integer (MHz) + 6 bit fraction */	dig_rf_freq = rf_freq / MHz;	temp = rf_freq % MHz;	for (i = 0; i < 6; i++) {		dig_rf_freq <<= 1;		frac_divider /= 2;		if (temp > frac_divider) {			temp -= frac_divider;			dig_rf_freq++;		}	}	/* add to have shift center point by 7.8124 kHz */	if (temp > 7812)		dig_rf_freq++;	set_reg_bits(state->tab_rftune, 0x14, 0xff, (u8)dig_rf_freq);	set_reg_bits(state->tab_rftune, 0x15, 0xff, (u8)(dig_rf_freq >> 8));	return state->tab_rftune;}/* ------------------------------------------------------------------------- */static int mxl5007t_write_reg(struct mxl5007t_state *state, u8 reg, u8 val){	u8 buf[] = { reg, val };	struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,			       .buf = buf, .len = 2 };	int ret;	ret = i2c_transfer(state->i2c_props.adap, &msg, 1);	if (ret != 1) {		mxl_err("failed!");		return -EREMOTEIO;	}	return 0;}static int mxl5007t_write_regs(struct mxl5007t_state *state,			       struct reg_pair_t *reg_pair){

⌨️ 快捷键说明

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