Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 330724
b: refs/heads/master
c: de49bc6
h: refs/heads/master
v: v3
  • Loading branch information
Devin Heitmueller authored and Mauro Carvalho Chehab committed Aug 9, 2012
1 parent 48e38ca commit d91a327
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: baede40c4daf2157413ae218946d6fe3b3ed1292
refs/heads/master: de49bc6ee9c38ac73abf41f3874918d930b2d985
58 changes: 52 additions & 6 deletions trunk/drivers/media/common/tuners/xc5000.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct xc5000_priv {
u8 radio_input;

int chip_id;
u16 pll_register_no;
};

/* Misc Defines */
Expand Down Expand Up @@ -209,18 +210,21 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
struct xc5000_fw_cfg {
char *name;
u16 size;
u16 pll_reg;
};

#define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw"
static const struct xc5000_fw_cfg xc5000a_1_6_114 = {
.name = XC5000A_FIRMWARE,
.size = 12401,
.pll_reg = 0x806c,
};

#define XC5000C_FIRMWARE "dvb-fe-xc5000c-41.024.5.fw"
static const struct xc5000_fw_cfg xc5000c_41_024_5 = {
.name = XC5000C_FIRMWARE,
.size = 16497,
.pll_reg = 0x13,
};

static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
Expand All @@ -234,7 +238,7 @@ static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
}
}

static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force);
static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val);
static int xc5000_TunerReset(struct dvb_frontend *fe);
Expand Down Expand Up @@ -619,6 +623,7 @@ static int xc5000_fwupload(struct dvb_frontend *fe)
int ret;
const struct xc5000_fw_cfg *desired_fw =
xc5000_assign_firmware(priv->chip_id);
priv->pll_register_no = desired_fw->pll_reg;

/* request the firmware, this will block and timeout */
printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
Expand Down Expand Up @@ -668,6 +673,7 @@ static void xc_debug_dump(struct xc5000_priv *priv)
u8 hw_majorversion = 0, hw_minorversion = 0;
u8 fw_majorversion = 0, fw_minorversion = 0;
u16 fw_buildversion = 0;
u16 regval;

/* Wait for stats to stabilize.
* Frame Lines needs two frame times after initial lock
Expand Down Expand Up @@ -707,6 +713,11 @@ static void xc_debug_dump(struct xc5000_priv *priv)
xc_get_totalgain(priv, &totalgain);
dprintk(1, "*** Total gain = %d.%d dB\n", totalgain / 256,
(totalgain % 256) * 100 / 256);

if (priv->pll_register_no) {
xc5000_readreg(priv, priv->pll_register_no, &regval);
dprintk(1, "*** PLL lock status = 0x%04x\n", regval);
}
}

static int xc5000_set_params(struct dvb_frontend *fe)
Expand All @@ -717,7 +728,7 @@ static int xc5000_set_params(struct dvb_frontend *fe)
u32 freq = fe->dtv_property_cache.frequency;
u32 delsys = fe->dtv_property_cache.delivery_system;

if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) {
dprintk(1, "Unable to load firmware and init tuner\n");
return -EINVAL;
}
Expand Down Expand Up @@ -850,6 +861,7 @@ static int xc5000_set_tv_freq(struct dvb_frontend *fe,
struct analog_parameters *params)
{
struct xc5000_priv *priv = fe->tuner_priv;
u16 pll_lock_status;
int ret;

dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
Expand Down Expand Up @@ -930,6 +942,21 @@ static int xc5000_set_tv_freq(struct dvb_frontend *fe,
if (debug)
xc_debug_dump(priv);

if (priv->pll_register_no != 0) {
msleep(20);
xc5000_readreg(priv, priv->pll_register_no, &pll_lock_status);
if (pll_lock_status > 63) {
/* PLL is unlocked, force reload of the firmware */
dprintk(1, "xc5000: PLL not locked (0x%x). Reloading...\n",
pll_lock_status);
if (xc_load_fw_and_init_tuner(fe, 1) != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc5000: Unable to reload fw\n");
return -EREMOTEIO;
}
goto tune_channel;
}
}

return 0;
}

Expand Down Expand Up @@ -1000,7 +1027,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
if (priv->i2c_props.adap == NULL)
return -EINVAL;

if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) {
dprintk(1, "Unable to load firmware and init tuner\n");
return -EINVAL;
}
Expand Down Expand Up @@ -1058,26 +1085,45 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
return 0;
}

static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force)
{
struct xc5000_priv *priv = fe->tuner_priv;
int ret = XC_RESULT_SUCCESS;
u16 pll_lock_status;

if (force || xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {

fw_retry:

if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
ret = xc5000_fwupload(fe);
if (ret != XC_RESULT_SUCCESS)
return ret;

msleep(20);

/* Start the tuner self-calibration process */
ret |= xc_initialize(priv);

if (ret != XC_RESULT_SUCCESS)
goto fw_retry;

/* Wait for calibration to complete.
* We could continue but XC5000 will clock stretch subsequent
* I2C transactions until calibration is complete. This way we
* don't have to rely on clock stretching working.
*/
xc_wait(100);

if (priv->pll_register_no) {
xc5000_readreg(priv, priv->pll_register_no,
&pll_lock_status);
if (pll_lock_status > 63) {
/* PLL is unlocked, force reload of the firmware */
printk(KERN_ERR "xc5000: PLL not running after fwload.\n");
goto fw_retry;
}
}

/* Default to "CABLE" mode */
ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
}
Expand Down Expand Up @@ -1113,7 +1159,7 @@ static int xc5000_init(struct dvb_frontend *fe)
struct xc5000_priv *priv = fe->tuner_priv;
dprintk(1, "%s()\n", __func__);

if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
return -EREMOTEIO;
}
Expand Down

0 comments on commit d91a327

Please sign in to comment.