|
@@ -1,69 +1,40 @@
|
|
|
/*
|
|
|
- MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
|
|
|
-
|
|
|
- Copyright (C) 2008 MaxLinear
|
|
|
- Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
|
|
|
- Functions:
|
|
|
- mxl5005s_reset()
|
|
|
- mxl5005s_writereg()
|
|
|
- mxl5005s_writeregs()
|
|
|
- mxl5005s_init()
|
|
|
- mxl5005s_reconfigure()
|
|
|
- mxl5005s_AssignTunerMode()
|
|
|
- mxl5005s_set_params()
|
|
|
- mxl5005s_get_frequency()
|
|
|
- mxl5005s_get_bandwidth()
|
|
|
- mxl5005s_release()
|
|
|
- mxl5005s_attach()
|
|
|
-
|
|
|
- Copyright (c) 2008 Realtek
|
|
|
- Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper
|
|
|
- Functions:
|
|
|
- mxl5005s_SetRfFreqHz()
|
|
|
-
|
|
|
- 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.
|
|
|
-
|
|
|
-*/
|
|
|
-
|
|
|
-/*
|
|
|
- History of this driver (Steven Toth):
|
|
|
- I was given a public release of a linux driver that included
|
|
|
- support for the MaxLinear MXL5005S silicon tuner. Analysis of
|
|
|
- the tuner driver showed clearly three things.
|
|
|
-
|
|
|
- 1. The tuner driver didn't support the LinuxTV tuner API
|
|
|
- so the code Realtek added had to be removed.
|
|
|
-
|
|
|
- 2. A significant amount of the driver is reference driver code
|
|
|
- from MaxLinear, I felt it was important to identify and
|
|
|
- preserve this.
|
|
|
-
|
|
|
- 3. New code has to be added to interface correctly with the
|
|
|
- LinuxTV API, as a regular kernel module.
|
|
|
-
|
|
|
- Other than the reference driver enum's, I've clearly marked
|
|
|
- sections of the code and retained the copyright of the
|
|
|
- respective owners.
|
|
|
-*/
|
|
|
+ * For the Realtek RTL chip RTL2831U
|
|
|
+ * Realtek Release Date: 2008-03-14, ver 080314
|
|
|
+ * Realtek version RTL2831 Linux driver version 080314
|
|
|
+ * ver 080314
|
|
|
+ *
|
|
|
+ * for linux kernel version 2.6.21.4 - 2.6.22-14
|
|
|
+ * support MXL5005s and MT2060 tuners (support tuner auto-detecting)
|
|
|
+ * support two IR types -- RC5 and NEC
|
|
|
+ *
|
|
|
+ * Known boards with Realtek RTL chip RTL2821U
|
|
|
+ * Freecom USB stick 14aa:0160 (version 4)
|
|
|
+ * Conceptronic CTVDIGRCU
|
|
|
+ *
|
|
|
+ * Copyright (c) 2008 Realtek
|
|
|
+ * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper
|
|
|
+ * This code is placed under the terms of the GNU General Public License
|
|
|
+ *
|
|
|
+ * Released by Realtek under GPLv2.
|
|
|
+ * Thanks to Realtek for a lot of support we received !
|
|
|
+ *
|
|
|
+ * Revision: 080314 - original version
|
|
|
+ */
|
|
|
|
|
|
+#include <linux/kernel.h>
|
|
|
+#include <linux/init.h>
|
|
|
+#include <linux/module.h>
|
|
|
+#include <linux/string.h>
|
|
|
+#include <linux/slab.h>
|
|
|
+#include <linux/delay.h>
|
|
|
+#include "dvb_frontend.h"
|
|
|
#include "mxl5005s.h"
|
|
|
|
|
|
-static int debug = 2;
|
|
|
+static int debug;
|
|
|
|
|
|
#define dprintk(level, arg...) do { \
|
|
|
- if (level <= debug) \
|
|
|
+ if (debug >= level) \
|
|
|
printk(arg); \
|
|
|
} while (0)
|
|
|
|
|
@@ -79,6 +50,13 @@ static int debug = 2;
|
|
|
#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
|
|
|
{
|
|
@@ -88,6 +66,51 @@ 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
|
|
|
{
|
|
@@ -99,6 +122,22 @@ 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
|
|
|
{
|
|
@@ -229,6 +268,33 @@ 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 */
|
|
@@ -283,15 +349,13 @@ struct mxl5005s_state
|
|
|
TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */
|
|
|
|
|
|
/* Linux driver framework specific */
|
|
|
- struct mxl5005s_config *config;
|
|
|
+ const struct mxl5005s_config *config;
|
|
|
+
|
|
|
struct dvb_frontend *frontend;
|
|
|
struct i2c_adapter *i2c;
|
|
|
-
|
|
|
- /* Cache values */
|
|
|
- u32 current_mode;
|
|
|
-
|
|
|
};
|
|
|
|
|
|
+// funcs
|
|
|
u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value);
|
|
|
u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value);
|
|
|
u16 MXL_GetMasterControl(u8 *MasterReg, int state);
|
|
@@ -308,26 +372,14 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq);
|
|
|
void MXL_SynthIFLO_Calc(struct dvb_frontend *fe);
|
|
|
void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe);
|
|
|
u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count);
|
|
|
-int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len);
|
|
|
+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, u32 mod_type, u32 bandwidth);
|
|
|
-int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth);
|
|
|
-
|
|
|
-/* ----------------------------------------------------------------
|
|
|
- * Begin: Custom code salvaged from the Realtek driver.
|
|
|
- * Copyright (c) 2008 Realtek
|
|
|
- * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper
|
|
|
- * This code is placed under the terms of the GNU General Public License
|
|
|
- *
|
|
|
- * Released by Realtek under GPLv2.
|
|
|
- * Thanks to Realtek for a lot of support we received !
|
|
|
- *
|
|
|
- * Revision: 080314 - original version
|
|
|
- */
|
|
|
+static int mxl5005s_init2(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;
|
|
@@ -344,7 +396,7 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)
|
|
|
AddrTable[0] = MASTER_CONTROL_ADDR;
|
|
|
ByteTable[0] |= state->config->AgcMasterByte;
|
|
|
|
|
|
- mxl5005s_writeregs(fe, AddrTable, ByteTable, 1);
|
|
|
+ mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1);
|
|
|
|
|
|
// Tuner RF frequency setting stage 1
|
|
|
MXL_TuneRF(fe, RfFreqHz);
|
|
@@ -358,13 +410,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 | state->config->AgcMasterByte;
|
|
|
+ ByteTable[TableLen] = MasterControlByte | AgcMasterByte;
|
|
|
TableLen += 1;
|
|
|
|
|
|
- mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
|
|
|
+ mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen);
|
|
|
|
|
|
// Wait 30 ms.
|
|
|
- msleep(150);
|
|
|
+ msleep(30);
|
|
|
|
|
|
// Tuner RF frequency setting stage 2
|
|
|
MXL_ControlWrite(fe, SEQ_FSM_PULSE, 1) ;
|
|
@@ -373,21 +425,101 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)
|
|
|
|
|
|
MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ;
|
|
|
AddrTable[TableLen] = MASTER_CONTROL_ADDR ;
|
|
|
- ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte ;
|
|
|
+ ByteTable[TableLen] = MasterControlByte | AgcMasterByte ;
|
|
|
TableLen += 1;
|
|
|
|
|
|
- mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
|
|
|
+ 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)
|
|
|
+{
|
|
|
+ struct mxl5005s_state *state = fe->tuner_priv;
|
|
|
+ u8 buf[2] = { reg, val };
|
|
|
+ struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
|
|
|
+ .buf = buf, .len = 2 };
|
|
|
+
|
|
|
+ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
|
|
+ printk(KERN_WARNING "mxl5005s I2C write failed\n");
|
|
|
+ return -EREMOTEIO;
|
|
|
+ }
|
|
|
return 0;
|
|
|
}
|
|
|
-/* End: Custom code taken from the Realtek driver */
|
|
|
|
|
|
-/* ----------------------------------------------------------------
|
|
|
- * Begin: Reference driver code found in the Realtek driver.
|
|
|
- * Copyright (c) 2008 MaxLinear
|
|
|
- */
|
|
|
+/* Write a word to a single reg */
|
|
|
+static int mxl5005s_writereg16(struct dvb_frontend *fe, u8 reg, u16 val)
|
|
|
+{
|
|
|
+ struct mxl5005s_state *state = fe->tuner_priv;
|
|
|
+ u8 buf[3] = { reg, val >> 8 , val & 0xff };
|
|
|
+ struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
|
|
|
+ .buf = buf, .len = 3 };
|
|
|
+
|
|
|
+ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
|
|
+ printk(KERN_WARNING "mxl5005s I2C write16 failed\n");
|
|
|
+ return -EREMOTEIO;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen)
|
|
|
+{
|
|
|
+ int i, ret;
|
|
|
+ u8 end_two_bytes_buf[]={ 0 , 0 };
|
|
|
+
|
|
|
+ for( i = 0 ; i < TableLen - 1 ; i++)
|
|
|
+ {
|
|
|
+ ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i]);
|
|
|
+ if (!ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ end_two_bytes_buf[0] = pByteTable[i];
|
|
|
+ end_two_bytes_buf[1] = MXL5005S_LATCH_BYTE;
|
|
|
+
|
|
|
+ ret = mxl5005s_writereg16(fe, pAddrTable[i], (end_two_bytes_buf[0] << 8) | end_two_bytes_buf[1]);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe,
|
|
|
+ unsigned char RegAddr,
|
|
|
+ unsigned char Msb,
|
|
|
+ unsigned char Lsb,
|
|
|
+ const unsigned char WritingValue
|
|
|
+ )
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ unsigned char Mask;
|
|
|
+ unsigned char Shift;
|
|
|
+ unsigned char RegByte;
|
|
|
+
|
|
|
+ /* Generate mask and shift according to MSB and LSB. */
|
|
|
+ Mask = 0;
|
|
|
+ for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
|
|
|
+ Mask |= 0x1 << i;
|
|
|
+
|
|
|
+ Shift = Lsb;
|
|
|
+
|
|
|
+ /* Get tuner register byte according to register adddress. */
|
|
|
+ MXL_RegRead(fe, RegAddr, &RegByte);
|
|
|
+
|
|
|
+ /* Reserve register byte unmask bit with mask and inlay writing value into it. */
|
|
|
+ RegByte &= ~Mask;
|
|
|
+ RegByte |= (WritingValue << Shift) & Mask;
|
|
|
+
|
|
|
+ /* Update tuner register byte table. */
|
|
|
+ MXL_RegWrite(fe, RegAddr, RegByte);
|
|
|
+
|
|
|
+ /* Write tuner register byte with writing byte. */
|
|
|
+ return mxl5005s_SetRegsWithTable(fe, &RegAddr, &RegByte, 1);
|
|
|
+}
|
|
|
+
|
|
|
+// The following context is source code provided by MaxLinear.
|
|
|
+// MaxLinear source code - MXL5005_Initialize.cpp
|
|
|
+// DONE
|
|
|
u16 MXL5005_RegisterInit(struct dvb_frontend *fe)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -709,6 +841,7 @@ u16 MXL5005_RegisterInit(struct dvb_frontend *fe)
|
|
|
return 0 ;
|
|
|
}
|
|
|
|
|
|
+// DONE
|
|
|
u16 MXL5005_ControlInit(struct dvb_frontend *fe)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -1652,6 +1785,7 @@ u16 MXL5005_ControlInit(struct dvb_frontend *fe)
|
|
|
// MaxLinear source code - MXL5005_c.cpp
|
|
|
// MXL5005.cpp : Defines the initialization routines for the DLL.
|
|
|
// 2.6.12
|
|
|
+// DONE
|
|
|
void InitTunerControls(struct dvb_frontend *fe)
|
|
|
{
|
|
|
MXL5005_RegisterInit(fe);
|
|
@@ -1694,6 +1828,7 @@ void InitTunerControls(struct dvb_frontend *fe)
|
|
|
// > 0 : Failed //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
u16 MXL5005_TunerConfig(struct dvb_frontend *fe,
|
|
|
u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */
|
|
|
u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */
|
|
@@ -1763,6 +1898,7 @@ u16 MXL5005_TunerConfig(struct dvb_frontend *fe,
|
|
|
// > 0 : Failed //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
void MXL_SynthIFLO_Calc(struct dvb_frontend *fe)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -1801,6 +1937,7 @@ void MXL_SynthIFLO_Calc(struct dvb_frontend *fe)
|
|
|
// > 0 : Failed //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -1839,6 +1976,7 @@ void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe)
|
|
|
// > 0 : Failed //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
u16 MXL_OverwriteICDefault(struct dvb_frontend *fe)
|
|
|
{
|
|
|
u16 status = 0;
|
|
@@ -1876,6 +2014,7 @@ u16 MXL_OverwriteICDefault(struct dvb_frontend *fe)
|
|
|
// > 0 : Failed //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
u16 MXL_BlockInit(struct dvb_frontend *fe)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -1903,7 +2042,6 @@ 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;
|
|
|
}
|
|
@@ -1934,6 +2072,7 @@ 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);
|
|
|
|
|
@@ -2163,8 +2302,6 @@ 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 */
|
|
@@ -2201,7 +2338,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe)
|
|
|
}
|
|
|
|
|
|
/* RSSI disable */
|
|
|
- if(state->EN_RSSI == 0) {
|
|
|
+ if(state->EN_RSSI==0) {
|
|
|
status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
|
|
|
status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
|
|
|
status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0);
|
|
@@ -2410,7 +2547,6 @@ 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 ;
|
|
@@ -3093,7 +3229,6 @@ 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)
|
|
@@ -3632,6 +3767,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
|
|
|
return status ;
|
|
|
}
|
|
|
|
|
|
+// DONE
|
|
|
u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val)
|
|
|
{
|
|
|
u16 status = 0;
|
|
@@ -3698,6 +3834,7 @@ u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val)
|
|
|
// >0 : Value exceed maximum allowed for control number //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value)
|
|
|
{
|
|
|
u16 status = 0;
|
|
@@ -3738,6 +3875,7 @@ u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value)
|
|
|
// 2 : Control name not found //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -3844,6 +3982,7 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u
|
|
|
// -1 : Invalid Register Address //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -3883,6 +4022,7 @@ u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal)
|
|
|
// -1 : Invalid Register Address //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -3919,6 +4059,7 @@ u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal)
|
|
|
// -1 : Invalid control name //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -3990,6 +4131,7 @@ u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value)
|
|
|
// -1 : Invalid control name //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int * count)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -4095,6 +4237,7 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int
|
|
|
// NONE //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -4142,6 +4285,7 @@ void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal)
|
|
|
// Computed value //
|
|
|
// //
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
+// DONE
|
|
|
u32 MXL_Ceiling(u32 value, u32 resolution)
|
|
|
{
|
|
|
return (value/resolution + (value % resolution > 0 ? 1 : 0));
|
|
@@ -4150,6 +4294,7 @@ u32 MXL_Ceiling(u32 value, u32 resolution)
|
|
|
//
|
|
|
// Retrieve the Initialzation Registers
|
|
|
//
|
|
|
+// DONE
|
|
|
u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count)
|
|
|
{
|
|
|
u16 status = 0;
|
|
@@ -4172,6 +4317,7 @@ u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *c
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+// DONE
|
|
|
u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count)
|
|
|
{
|
|
|
u16 status = 0;
|
|
@@ -4199,6 +4345,7 @@ u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *cou
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+// DONE
|
|
|
u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count)
|
|
|
{
|
|
|
u16 status = 0;
|
|
@@ -4216,6 +4363,7 @@ u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, i
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+// DONE
|
|
|
u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count)
|
|
|
{
|
|
|
u16 status = 0;
|
|
@@ -4233,6 +4381,7 @@ u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, in
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+// DONE
|
|
|
u16 MXL_GetMasterControl(u8 *MasterReg, int state)
|
|
|
{
|
|
|
if (state == 1) /* Load_Start */
|
|
@@ -4377,6 +4526,7 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range)
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+// DONE
|
|
|
u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
@@ -4387,224 +4537,141 @@ u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis)
|
|
|
|
|
|
return status;
|
|
|
}
|
|
|
+
|
|
|
#endif
|
|
|
-/* End: Reference driver code found in the Realtek driver that
|
|
|
- * is copyright MaxLinear */
|
|
|
|
|
|
-/* ----------------------------------------------------------------
|
|
|
- * Begin: Everything after here is new code to adapt the
|
|
|
- * proprietary Realtek driver into a Linux API tuner.
|
|
|
- * Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
|
|
|
- */
|
|
|
-static int mxl5005s_reset(struct dvb_frontend *fe)
|
|
|
+/* Linux driver related functions */
|
|
|
+
|
|
|
+
|
|
|
+int mxl5005s_init(struct dvb_frontend *fe)
|
|
|
{
|
|
|
- struct mxl5005s_state *state = fe->tuner_priv;
|
|
|
- int ret = 0;
|
|
|
+ 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;
|
|
|
|
|
|
- u8 buf[2] = { 0xff, 0x00 };
|
|
|
- struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
|
|
|
- .buf = buf, .len = 2 };
|
|
|
+ /* 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;
|
|
|
|
|
|
- dprintk(2, "%s()\n", __func__);
|
|
|
+ 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);
|
|
|
+
|
|
|
+ return mxl5005s_init2(fe);
|
|
|
+}
|
|
|
|
|
|
- if (fe->ops.i2c_gate_ctrl)
|
|
|
- fe->ops.i2c_gate_ctrl(fe, 1);
|
|
|
+static int mxl5005s_set_params(struct dvb_frontend *fe,
|
|
|
+ struct dvb_frontend_parameters *params)
|
|
|
+{
|
|
|
+ u32 freq;
|
|
|
+ u32 bw;
|
|
|
|
|
|
- if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
|
|
- printk(KERN_WARNING "mxl5005s I2C reset failed\n");
|
|
|
- ret = -EREMOTEIO;
|
|
|
- }
|
|
|
+ if (fe->ops.info.type == FE_OFDM)
|
|
|
+ bw = params->u.ofdm.bandwidth;
|
|
|
+ else
|
|
|
+ bw = MXL5005S_BANDWIDTH_6MHZ;
|
|
|
|
|
|
- if (fe->ops.i2c_gate_ctrl)
|
|
|
- fe->ops.i2c_gate_ctrl(fe, 0);
|
|
|
+ freq = params->frequency; /* Hz */
|
|
|
+ dprintk(1, "%s() freq=%d bw=%d\n", __func__, freq, bw);
|
|
|
|
|
|
- return ret;
|
|
|
+ return mxl5005s_SetRfFreqHz(fe, freq);
|
|
|
}
|
|
|
|
|
|
-/* Write a single byte to a single reg, latch the value if required by
|
|
|
- * following the transaction with the latch byte.
|
|
|
- */
|
|
|
-static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch)
|
|
|
+static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
|
|
{
|
|
|
struct mxl5005s_state *state = fe->tuner_priv;
|
|
|
- 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(1, "%s()\n", __func__);
|
|
|
|
|
|
- dprintk(2, "%s(reg = 0x%x val = 0x%x addr = 0x%x)\n", __func__, reg, val, msg.addr);
|
|
|
+ *frequency = state->RF_IN;
|
|
|
|
|
|
- if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
|
|
- printk(KERN_WARNING "mxl5005s I2C write failed\n");
|
|
|
- return -EREMOTEIO;
|
|
|
- }
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len)
|
|
|
+static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
|
|
{
|
|
|
- int ret = 0, i;
|
|
|
-
|
|
|
- if (fe->ops.i2c_gate_ctrl)
|
|
|
- fe->ops.i2c_gate_ctrl(fe, 1);
|
|
|
-
|
|
|
- for (i = 0 ; i < len-1; i++) {
|
|
|
- ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 0);
|
|
|
- if (ret < 0)
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 1);
|
|
|
+ struct mxl5005s_state *state = fe->tuner_priv;
|
|
|
+ dprintk(1, "%s()\n", __func__);
|
|
|
|
|
|
- if (fe->ops.i2c_gate_ctrl)
|
|
|
- fe->ops.i2c_gate_ctrl(fe, 0);
|
|
|
+ *bandwidth = state->Chan_Bandwidth;
|
|
|
|
|
|
- return ret;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-int mxl5005s_init(struct dvb_frontend *fe)
|
|
|
+static int mxl5005s_get_status(struct dvb_frontend *fe, u32 *status)
|
|
|
{
|
|
|
dprintk(1, "%s()\n", __func__);
|
|
|
- return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ);
|
|
|
+
|
|
|
+ *status = 0;
|
|
|
+ // *status = TUNER_STATUS_LOCKED;
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth)
|
|
|
+static int mxl5005s_init2(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(type=%d, bw=%d)\n", __func__, mod_type, bandwidth);
|
|
|
+ dprintk(1, "%s()\n", __func__);
|
|
|
|
|
|
- mxl5005s_reset(fe);
|
|
|
+ /* 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_writeregs(fe, AddrTable, ByteTable, 1);
|
|
|
-
|
|
|
- mxl5005s_AssignTunerMode(fe, mod_type, bandwidth);
|
|
|
+ mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1);
|
|
|
|
|
|
/* Tuner initialization stage 1 */
|
|
|
MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen);
|
|
|
|
|
|
- mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth)
|
|
|
-{
|
|
|
- struct mxl5005s_state *state = fe->tuner_priv;
|
|
|
- struct mxl5005s_config *c = state->config;
|
|
|
-
|
|
|
- InitTunerControls(fe);
|
|
|
-
|
|
|
- /* Set MxL5005S parameters. */
|
|
|
- MXL5005_TunerConfig(
|
|
|
- fe,
|
|
|
- c->mod_mode,
|
|
|
- c->if_mode,
|
|
|
- bandwidth,
|
|
|
- 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,
|
|
|
- mod_type,
|
|
|
- c->tracking_filter);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int mxl5005s_set_params(struct dvb_frontend *fe,
|
|
|
- struct dvb_frontend_parameters *params)
|
|
|
-{
|
|
|
- struct mxl5005s_state *state = fe->tuner_priv;
|
|
|
- u32 req_mode, req_bw = 0;
|
|
|
- int ret;
|
|
|
-
|
|
|
- dprintk(1, "%s()\n", __func__);
|
|
|
-
|
|
|
- if (fe->ops.info.type == FE_ATSC) {
|
|
|
- switch (params->u.vsb.modulation) {
|
|
|
- case VSB_8:
|
|
|
- req_mode = MXL_ATSC; break;
|
|
|
- default:
|
|
|
- case QAM_64:
|
|
|
- case QAM_256:
|
|
|
- case QAM_AUTO:
|
|
|
- req_mode = MXL_QAM; break;
|
|
|
- }
|
|
|
- }
|
|
|
- else req_mode = MXL_DVBT;
|
|
|
-
|
|
|
- /* Change tuner for new modulation type if reqd */
|
|
|
- if (req_mode != state->current_mode) {
|
|
|
- switch (req_mode) {
|
|
|
- case VSB_8:
|
|
|
- case QAM_64:
|
|
|
- case QAM_256:
|
|
|
- case QAM_AUTO:
|
|
|
- req_bw = MXL5005S_BANDWIDTH_6MHZ;
|
|
|
- break;
|
|
|
- default:
|
|
|
- /* Assume DVB-T */
|
|
|
- switch (params->u.ofdm.bandwidth) {
|
|
|
- case BANDWIDTH_6_MHZ:
|
|
|
- req_bw = MXL5005S_BANDWIDTH_6MHZ;
|
|
|
- break;
|
|
|
- case BANDWIDTH_7_MHZ:
|
|
|
- req_bw = MXL5005S_BANDWIDTH_7MHZ;
|
|
|
- break;
|
|
|
- case BANDWIDTH_AUTO:
|
|
|
- case BANDWIDTH_8_MHZ:
|
|
|
- req_bw = MXL5005S_BANDWIDTH_8MHZ;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- state->current_mode = req_mode;
|
|
|
- ret = mxl5005s_reconfigure(fe, req_mode, req_bw);
|
|
|
-
|
|
|
- } else
|
|
|
- ret = 0;
|
|
|
-
|
|
|
- if (ret == 0) {
|
|
|
- dprintk(1, "%s() freq=%d\n", __func__, params->frequency);
|
|
|
- ret = mxl5005s_SetRfFreqHz(fe, params->frequency);
|
|
|
- }
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
|
|
-{
|
|
|
- struct mxl5005s_state *state = fe->tuner_priv;
|
|
|
- dprintk(1, "%s()\n", __func__);
|
|
|
-
|
|
|
- *frequency = state->RF_IN;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
|
|
-{
|
|
|
- struct mxl5005s_state *state = fe->tuner_priv;
|
|
|
- dprintk(1, "%s()\n", __func__);
|
|
|
-
|
|
|
- *bandwidth = state->Chan_Bandwidth;
|
|
|
+ mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -4631,6 +4698,7 @@ static const struct dvb_tuner_ops mxl5005s_tuner_ops = {
|
|
|
.set_params = mxl5005s_set_params,
|
|
|
.get_frequency = mxl5005s_get_frequency,
|
|
|
.get_bandwidth = mxl5005s_get_bandwidth,
|
|
|
+ .get_status = mxl5005s_get_status
|
|
|
};
|
|
|
|
|
|
struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
|
|
@@ -4647,7 +4715,6 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
|
|
|
state->frontend = fe;
|
|
|
state->config = config;
|
|
|
state->i2c = i2c;
|
|
|
- state->current_mode = MXL_QAM;
|
|
|
|
|
|
printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n", config->i2c_address);
|
|
|
|
|
@@ -4659,5 +4726,8 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
|
|
|
EXPORT_SYMBOL(mxl5005s_attach);
|
|
|
|
|
|
MODULE_DESCRIPTION("MaxLinear MXL5005S silicon tuner driver");
|
|
|
+MODULE_AUTHOR("Jan Hoogenraad");
|
|
|
+MODULE_AUTHOR("Barnaby Shearer");
|
|
|
+MODULE_AUTHOR("Andy Hasper");
|
|
|
MODULE_AUTHOR("Steven Toth");
|
|
|
MODULE_LICENSE("GPL");
|