Commit 8c66a19d authored by Steven Toth's avatar Steven Toth Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (7868): mxl5005s: Cleanup #5



Cleanup #5

Signed-off-by: default avatarSteven Toth <stoth@hauppauge.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 85d220d0
Loading
Loading
Loading
Loading
+103 −201
Original line number Diff line number Diff line
@@ -24,10 +24,10 @@

#include "mxl5005s.h"

static int debug;
static int debug = 2;

#define dprintk(level, arg...) do {    \
	if (debug >= level)            \
	if (level <= debug)            \
		printk(arg);    \
	} while (0)

@@ -43,13 +43,6 @@ static int debug;
#define MXLCTRL_NUM             189
#define MASTER_CONTROL_ADDR     9

/* Enumeration of AGC Mode */
typedef enum
{
	MXL_DUAL_AGC = 0,
	MXL_SINGLE_AGC
} AGC_Mode;

/* Enumeration of Master Control Register State */
typedef enum
{
@@ -59,51 +52,6 @@ typedef enum
	MC_SEQ_OFF
} Master_Control_State;

/* Enumeration of MXL5005 Tuner Mode */
typedef enum
{
	MXL_ANALOG_MODE = 0,
	MXL_DIGITAL_MODE
} Tuner_Mode;

/* Enumeration of MXL5005 Tuner IF Mode */
typedef enum
{
	MXL_ZERO_IF = 0,
	MXL_LOW_IF
} Tuner_IF_Mode;

/* Enumeration of MXL5005 Tuner Clock Out Mode */
typedef enum
{
	MXL_CLOCK_OUT_DISABLE = 0,
	MXL_CLOCK_OUT_ENABLE
} Tuner_Clock_Out;

/* Enumeration of MXL5005 Tuner Div Out Mode */
typedef enum
{
	MXL_DIV_OUT_1 = 0,
	MXL_DIV_OUT_4

} Tuner_Div_Out;

/* Enumeration of MXL5005 Tuner Pull-up Cap Select Mode */
typedef enum
{
	MXL_CAP_SEL_DISABLE = 0,
	MXL_CAP_SEL_ENABLE

} Tuner_Cap_Select;

/* Enumeration of MXL5005 Tuner RSSI Mode */
typedef enum
{
	MXL_RSSI_DISABLE = 0,
	MXL_RSSI_ENABLE

} Tuner_RSSI;

/* Enumeration of MXL5005 Tuner Modulation Type */
typedef enum
{
@@ -115,22 +63,6 @@ typedef enum
	MXL_ANALOG_OTA
} Tuner_Modu_Type;

/* Enumeration of MXL5005 Tuner Tracking Filter Type */
typedef enum
{
	MXL_TF_DEFAULT = 0,
	MXL_TF_OFF,
	MXL_TF_C,
	MXL_TF_C_H,
	MXL_TF_D,
	MXL_TF_D_L,
	MXL_TF_E,
	MXL_TF_F,
	MXL_TF_E_2,
	MXL_TF_E_NA,
	MXL_TF_G
} Tuner_TF_Type;

/* MXL5005 Tuner Register Struct */
typedef struct _TunerReg_struct
{
@@ -261,33 +193,6 @@ enum
};
#define MXL5005S_BANDWIDTH_MODE_NUM		3

/* Top modes */
enum
{
	MXL5005S_TOP_5P5  =  55,
	MXL5005S_TOP_7P2  =  72,
	MXL5005S_TOP_9P2  =  92,
	MXL5005S_TOP_11P0 = 110,
	MXL5005S_TOP_12P9 = 129,
	MXL5005S_TOP_14P7 = 147,
	MXL5005S_TOP_16P8 = 168,
	MXL5005S_TOP_19P4 = 194,
	MXL5005S_TOP_21P2 = 212,
	MXL5005S_TOP_23P2 = 232,
	MXL5005S_TOP_25P2 = 252,
	MXL5005S_TOP_27P1 = 271,
	MXL5005S_TOP_29P2 = 292,
	MXL5005S_TOP_31P7 = 317,
	MXL5005S_TOP_34P9 = 349,
};

/* IF output load */
enum
{
	MXL5005S_IF_OUTPUT_LOAD_200_OHM = 200,
	MXL5005S_IF_OUTPUT_LOAD_300_OHM = 300,
};

/* MXL5005 Tuner Control Struct */
typedef struct _TunerControl_struct {
	u16 Ctrl_Num;	/* Control Number */
@@ -342,8 +247,7 @@ struct mxl5005s_state
		TunerRegs[TUNER_REGS_NUM];	/* Tuner Register Array Pointer */

	/* Linux driver framework specific */
	const struct mxl5005s_config *config;

	struct mxl5005s_config *config;
	struct dvb_frontend *frontend;
	struct i2c_adapter *i2c;
};
@@ -367,11 +271,11 @@ void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe);
u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count);
int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen);
u16 MXL_IFSynthInit(struct dvb_frontend *fe);
int mxl5005s_AssignTunerMode(struct dvb_frontend *fe);

int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)
{
	struct mxl5005s_state *state = fe->tuner_priv;
	u8 AgcMasterByte = state->config->AgcMasterByte;
	unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
	unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
	int TableLen;
@@ -402,13 +306,13 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)

	MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ;
	AddrTable[TableLen] = MASTER_CONTROL_ADDR ;
	ByteTable[TableLen] = MasterControlByte | AgcMasterByte;
	ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte;
	TableLen += 1;

	mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen);

	// Wait 30 ms.
	msleep(30);
	msleep(150);

	// Tuner RF frequency setting stage 2
	MXL_ControlWrite(fe, SEQ_FSM_PULSE, 1) ;
@@ -417,39 +321,56 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)

	MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ;
	AddrTable[TableLen] = MASTER_CONTROL_ADDR ;
	ByteTable[TableLen] = MasterControlByte | AgcMasterByte ;
	ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte ;
	TableLen += 1;

	mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen);

	msleep(100);

	return 0;
}

/* Write a single byte to a single reg */
static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val)
static int mxl5005s_reset(struct dvb_frontend *fe)
{
	struct mxl5005s_state *state = fe->tuner_priv;
	u8 buf[2] = { reg, val };
	int ret = 0;

	u8 buf[2] = { 0xff, 0x00 };
	struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
			       .buf = buf, .len = 2 };

	dprintk(2, "%s()\n", __func__);

	if (fe->ops.i2c_gate_ctrl)
		fe->ops.i2c_gate_ctrl(fe, 1);

	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
		printk(KERN_WARNING "mxl5005s I2C write failed\n");
		return -EREMOTEIO;
		printk(KERN_WARNING "mxl5005s I2C reset failed\n");
		ret = -EREMOTEIO;
	}
	return 0;

	if (fe->ops.i2c_gate_ctrl)
		fe->ops.i2c_gate_ctrl(fe, 0);

	return ret;
}

/* Write a word to a single reg */
static int mxl5005s_writereg16(struct dvb_frontend *fe, u8 reg, u16 val)
/* Write a single byte to a single reg */
static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch)
{
	struct mxl5005s_state *state = fe->tuner_priv;
	u8 buf[3] = { reg, val >> 8 , val & 0xff };
	u8 buf[3] = { reg, val, MXL5005S_LATCH_BYTE };
	struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
			       .buf = buf, .len = 3 };

	if(latch == 0)
		msg.len = 2;

	dprintk(2, "%s(reg = 0x%x val = 0x%x addr = 0x%x)\n", __func__, reg, val, msg.addr);

	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
		printk(KERN_WARNING "mxl5005s I2C write16 failed\n");
		printk(KERN_WARNING "mxl5005s I2C write failed\n");
		return -EREMOTEIO;
	}
	return 0;
@@ -457,20 +378,22 @@ static int mxl5005s_writereg16(struct dvb_frontend *fe, u8 reg, u16 val)

int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen)
{
	int	i, ret;
	u8	end_two_bytes_buf[]={ 0 , 0 };
	int	i, ret = 0;

	if (fe->ops.i2c_gate_ctrl)
		fe->ops.i2c_gate_ctrl(fe, 1);

	for( i = 0 ; i < TableLen - 1 ; i++)
	{
		ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i]);
		if (!ret)
			return ret;
		ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i], 0);
		if (ret < 0)
			break;
	}

	end_two_bytes_buf[0] = pByteTable[i];
	end_two_bytes_buf[1] = MXL5005S_LATCH_BYTE;
	ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i], 1);

	ret = mxl5005s_writereg16(fe, pAddrTable[i], (end_two_bytes_buf[0] << 8) | end_two_bytes_buf[1]);
	if (fe->ops.i2c_gate_ctrl)
		fe->ops.i2c_gate_ctrl(fe, 0);

	return ret;
}
@@ -509,6 +432,7 @@ int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe,
	return mxl5005s_SetRegsWithTable(fe, &RegAddr, &RegByte, 1);
}


// The following context is source code provided by MaxLinear.
// MaxLinear source code - MXL5005_Initialize.cpp
// DONE
@@ -2034,6 +1958,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe)
				status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 2);
				break;
			case 6000000:
				printk("%s() doing 6MHz digital\n", __func__);
				status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 3);
				break;
		}
@@ -2064,7 +1989,6 @@ u16 MXL_BlockInit(struct dvb_frontend *fe)
	else /*  Single AGC Mode Dig  Ana */
		status += MXL_ControlWrite(fe, AGC_RF, state->Mode ? 15 : 12);


	if (state->TOP == 55) /* TOP == 5.5 */
		status += MXL_ControlWrite(fe, AGC_IF, 0x0);

@@ -2294,6 +2218,8 @@ u16 MXL_BlockInit(struct dvb_frontend *fe)
			status += MXL_ControlWrite(fe, BB_IQSWAP, 0);
		else /* High IF */
			status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
		status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2);

	}
	if (state->Mod_Type == MXL_ANALOG_CABLE) {
		/* Analog Cable Mode */
@@ -2539,6 +2465,7 @@ u16 MXL_IFSynthInit(struct dvb_frontend *fe)
			Fref = 324000000UL ;
		}
		if (state->IF_LO == 5380000UL) {
			printk("%s() doing 5.38\n", __func__);
			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x07) ;
			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ;
			Fref = 322800000UL ;
@@ -3221,6 +3148,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)

	if (state->TF_Type == MXL_TF_C_H) // Tracking Filter type C-H for Hauppauge only
	{
		printk("%s() CH filter\n", __func__);
		status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ;

		if (state->RF_IN >= 43000000 && state->RF_IN < 150000000)
@@ -4534,63 +4462,59 @@ u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis)

/* Linux driver related functions */

int mxl5005s_init(struct dvb_frontend *fe)
{
	struct mxl5005s_state *state = fe->tuner_priv;

	u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
	u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
	int TableLen;

	dprintk(1, "%s()\n", __func__);

	mxl5005s_reset(fe);

	/* Tuner initialization stage 0 */
	MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET);
	AddrTable[0] = MASTER_CONTROL_ADDR;
	ByteTable[0] |= state->config->AgcMasterByte;

int mxl5005s_init2(struct dvb_frontend *fe)
	mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1);

	mxl5005s_AssignTunerMode(fe); // tunre_config

	/* Tuner initialization stage 1 */
	MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen);

	mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen);

	return 0;
}

int mxl5005s_AssignTunerMode(struct dvb_frontend *fe)
{
	int            MxlModMode;
	int            MxlIfMode;
	unsigned long  MxlBandwitdh;
	unsigned long  MxlIfFreqHz;
	unsigned long  MxlCrystalFreqHz;
	int            MxlAgcMode;
	unsigned short MxlTop;
	unsigned short MxlIfOutputLoad;
	int            MxlClockOut;
	int            MxlDivOut;
	int            MxlCapSel;
	int            MxlRssiOnOff;
	unsigned char  MxlStandard;
	unsigned char  MxlTfType;
	struct mxl5005s_state *state = fe->tuner_priv;
	struct mxl5005s_config *c = state->config;

	/* Set MxL5005S parameters. */
	MxlModMode       = MXL_DIGITAL_MODE;
	MxlIfMode        = MXL_ZERO_IF;
// steve
	//MxlBandwitdh     = MXL5005S_BANDWIDTH_8MHZ;
	//MxlIfFreqHz      = IF_FREQ_4570000HZ;
	MxlBandwitdh     = MXL5005S_BANDWIDTH_6MHZ; // config
	MxlIfFreqHz      = IF_FREQ_5380000HZ; // config
	MxlCrystalFreqHz = CRYSTAL_FREQ_16000000HZ; // config
	MxlAgcMode       = MXL_SINGLE_AGC;
	MxlTop           = MXL5005S_TOP_25P2;
	MxlIfOutputLoad  = MXL5005S_IF_OUTPUT_LOAD_200_OHM;
	MxlClockOut      = MXL_CLOCK_OUT_DISABLE;
	MxlDivOut        = MXL_DIV_OUT_4;
	MxlCapSel        = MXL_CAP_SEL_ENABLE;
	MxlRssiOnOff     = MXL_RSSI_ENABLE; // config
	MxlTfType        = MXL_TF_C_H; // config

	MxlStandard = MXL_ATSC; // config

	// TODO: this is bad, it trashes other configs
	// Set MxL5005S extra module.
	//pExtra->AgcMasterByte = (MxlAgcMode == MXL_DUAL_AGC) ? 0x4 : 0x0;
	InitTunerControls(fe);

	/* Set MxL5005S parameters. */
	MXL5005_TunerConfig(
		fe,
		(unsigned char)MxlModMode,
		(unsigned char)MxlIfMode,
		MxlBandwitdh,
		MxlIfFreqHz,
		MxlCrystalFreqHz,
		(unsigned char)MxlAgcMode,
		MxlTop,
		MxlIfOutputLoad,
		(unsigned char)MxlClockOut,
		(unsigned char)MxlDivOut,
		(unsigned char)MxlCapSel,
		(unsigned char)MxlRssiOnOff,
		MxlStandard, MxlTfType);
		c->mod_mode,
		c->if_mode,
		MXL5005S_BANDWIDTH_6MHZ,
		c->if_freq,
		c->xtal_freq,
		c->agc_mode,
		c->top,
		c->output_load,
		c->clock_out,
		c->div_out,
		c->cap_select,
		c->rssi_enable,
		MXL_QAM,
		c->tracking_filter);

	return 0;
}
@@ -4609,7 +4533,11 @@ static int mxl5005s_set_params(struct dvb_frontend *fe,
	freq = params->frequency; /* Hz */
	dprintk(1, "%s() freq=%d bw=%d\n", __func__, freq, bw);

	return mxl5005s_SetRfFreqHz(fe, freq);
	mxl5005s_SetRfFreqHz(fe, freq);

	msleep(350);

	return 0;
}

static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency)
@@ -4642,32 +4570,6 @@ static int mxl5005s_get_status(struct dvb_frontend *fe, u32 *status)
	return 0;
}

static int mxl5005s_init(struct dvb_frontend *fe)
{
	struct mxl5005s_state *state = fe->tuner_priv;
	u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
	u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
	int TableLen;

	dprintk(1, "%s()\n", __func__);

	/* Initialize MxL5005S tuner according to MxL5005S tuner example code. */

	/* Tuner initialization stage 0 */
	MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET);
	AddrTable[0] = MASTER_CONTROL_ADDR;
	ByteTable[0] |= state->config->AgcMasterByte;

	mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1);

	/* Tuner initialization stage 1 */
	MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen);

	mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen);

	return mxl5005s_init2(fe);
}

static int mxl5005s_release(struct dvb_frontend *fe)
{
	dprintk(1, "%s()\n", __func__);
+78 −21
Original line number Diff line number Diff line
@@ -26,31 +26,88 @@
#ifndef __MXL5005S_H
#define __MXL5005S_H

/* IF frequency */
enum IF_FREQ_HZ
{
	IF_FREQ_4570000HZ  =  4570000,                  ///<   IF frequency =   4.57 MHz
	IF_FREQ_4571429HZ  =  4571429,                  ///<   IF frequency =  4.571 MHz
	IF_FREQ_5380000HZ  =  5380000,                  ///<   IF frequency =   5.38 MHz
	IF_FREQ_36000000HZ = 36000000,                  ///<   IF frequency = 36.000 MHz
	IF_FREQ_36125000HZ = 36125000,                  ///<   IF frequency = 36.125 MHz
	IF_FREQ_36166667HZ = 36166667,                  ///<   IF frequency = 36.167 MHz
	IF_FREQ_44000000HZ = 44000000,                  ///<   IF frequency = 44.000 MHz
};

/* Crystal frequency */
enum CRYSTAL_FREQ_HZ
{
	CRYSTAL_FREQ_4000000HZ  =  4000000,                     ///<   Crystal frequency =  4.0 MHz
	CRYSTAL_FREQ_16000000HZ = 16000000,                     ///<   Crystal frequency = 16.0 MHz
	CRYSTAL_FREQ_25000000HZ = 25000000,                     ///<   Crystal frequency = 25.0 MHz
	CRYSTAL_FREQ_28800000HZ = 28800000,                     ///<   Crystal frequency = 28.8 MHz
};

struct mxl5005s_config
{
	/* 7 bit i2c address */
	u8 i2c_address;

#define IF_FREQ_4570000HZ    4570000
#define IF_FREQ_4571429HZ    4571429
#define IF_FREQ_5380000HZ    5380000
#define IF_FREQ_36000000HZ  36000000
#define IF_FREQ_36125000HZ  36125000
#define IF_FREQ_36166667HZ  36166667
#define IF_FREQ_44000000HZ  44000000
	u32 if_freq;

#define CRYSTAL_FREQ_4000000HZ    4000000
#define CRYSTAL_FREQ_16000000HZ  16000000
#define CRYSTAL_FREQ_25000000HZ  25000000
#define CRYSTAL_FREQ_28800000HZ  28800000
	u32 xtal_freq;

#define MXL_DUAL_AGC   0
#define MXL_SINGLE_AGC 1
	u8 agc_mode;

#define MXL_TF_DEFAULT	0
#define MXL_TF_OFF	1
#define MXL_TF_C	2
#define MXL_TF_C_H	3
#define MXL_TF_D	4
#define MXL_TF_D_L	5
#define MXL_TF_E	6
#define MXL_TF_F	7
#define MXL_TF_E_2	8
#define MXL_TF_E_NA	9
#define MXL_TF_G	10
	u8 tracking_filter;

#define MXL_RSSI_DISABLE	0
#define MXL_RSSI_ENABLE		1
	u8 rssi_enable;

#define MXL_CAP_SEL_DISABLE	0
#define MXL_CAP_SEL_ENABLE	1
	u8 cap_select;

#define MXL_DIV_OUT_1	0
#define MXL_DIV_OUT_4	1
	u8 div_out;

#define MXL_CLOCK_OUT_DISABLE	0
#define MXL_CLOCK_OUT_ENABLE	1
	u8 clock_out;

#define MXL5005S_IF_OUTPUT_LOAD_200_OHM 200
#define MXL5005S_IF_OUTPUT_LOAD_300_OHM 300
	u32 output_load;

#define MXL5005S_TOP_5P5   55
#define MXL5005S_TOP_7P2   72
#define MXL5005S_TOP_9P2   92
#define MXL5005S_TOP_11P0 110
#define MXL5005S_TOP_12P9 129
#define MXL5005S_TOP_14P7 147
#define MXL5005S_TOP_16P8 168
#define MXL5005S_TOP_19P4 194
#define MXL5005S_TOP_21P2 212
#define MXL5005S_TOP_23P2 232
#define MXL5005S_TOP_25P2 252
#define MXL5005S_TOP_27P1 271
#define MXL5005S_TOP_29P2 292
#define MXL5005S_TOP_31P7 317
#define MXL5005S_TOP_34P9 349
	u32 top;

#define MXL_ANALOG_MODE  0
#define MXL_DIGITAL_MODE 1
	u8 mod_mode;

#define MXL_ZERO_IF 0
#define MXL_LOW_IF  1
	u8 if_mode;

	/* Stuff I don't know what to do with */
	u8 AgcMasterByte;
};