[media] xc4000: continued cleanup of the firmware loading routine
Properly setup the standard firmware loading and scode loading, as well as getting rid of a ton of dead code. Note that I am getting a single i2c error when the standard firmware sets the video standard, but everything else seems to be loading properly now. Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
d0962382cf
commit
ee4c3cd67b
1 changed files with 44 additions and 136 deletions
|
@ -108,23 +108,21 @@ struct xc4000_priv {
|
|||
|
||||
/* Product id */
|
||||
#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000
|
||||
#define XC_PRODUCT_ID_FW_LOADED 0x0FA0 /* WAS: 0x1388*/
|
||||
#define XC_PRODUCT_ID_FW_LOADED 0x0FA0
|
||||
|
||||
/* Registers */
|
||||
/* Registers (Write-only) */
|
||||
#define XREG_INIT 0x00
|
||||
#define XREG_VIDEO_MODE 0x01
|
||||
#define XREG_AUDIO_MODE 0x02
|
||||
#define XREG_RF_FREQ 0x03
|
||||
#define XREG_D_CODE 0x04
|
||||
#define XREG_IF_OUT 0x05 /* ?? */
|
||||
#define XREG_SEEK_MODE 0x07 /* WAS: 0x06 */
|
||||
#define XREG_POWER_DOWN 0x08 /* WAS: 0x0A Obsolete */
|
||||
#define XREG_SIGNALSOURCE 0x0A /* WAS: 0x0D 0=Air, 1=Cable */
|
||||
//#define XREG_SMOOTHEDCVBS 0x0E
|
||||
//#define XREG_XTALFREQ 0x0F
|
||||
//#define XREG_FINERFREQ 0x10
|
||||
//#define XREG_DDIMODE 0x11
|
||||
#define XREG_DIRECTSITTING_MODE 0x05
|
||||
#define XREG_SEEK_MODE 0x06
|
||||
#define XREG_POWER_DOWN 0x08
|
||||
#define XREG_SIGNALSOURCE 0x0A
|
||||
#define XREG_AMPLITUDE 0x10
|
||||
|
||||
/* Registers (Read-only) */
|
||||
#define XREG_ADC_ENV 0x00
|
||||
#define XREG_QUALITY 0x01
|
||||
#define XREG_FRAME_LINES 0x02
|
||||
|
@ -134,7 +132,6 @@ struct xc4000_priv {
|
|||
#define XREG_SNR 0x06
|
||||
#define XREG_VERSION 0x07
|
||||
#define XREG_PRODUCT_ID 0x08
|
||||
//#define XREG_BUILD 0x0D
|
||||
|
||||
/*
|
||||
Basic firmware description. This will remain with
|
||||
|
@ -249,7 +246,6 @@ static struct XC_TV_STANDARD XC4000_Standard[MAX_TV_STANDARD] = {
|
|||
{"FM Radio-INPUT1", 0x0008, 0x9000}
|
||||
};
|
||||
|
||||
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
|
||||
static int xc4000_is_firmware_loaded(struct dvb_frontend *fe);
|
||||
static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val);
|
||||
static int xc4000_TunerReset(struct dvb_frontend *fe);
|
||||
|
@ -258,7 +254,6 @@ static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
|
|||
{
|
||||
struct i2c_msg msg = { .addr = priv->i2c_props.addr,
|
||||
.flags = 0, .buf = buf, .len = len };
|
||||
|
||||
if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
|
||||
printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n", len);
|
||||
return XC_RESULT_I2C_WRITE_FAILURE;
|
||||
|
@ -269,17 +264,6 @@ static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
|
|||
/* This routine is never used because the only time we read data from the
|
||||
i2c bus is when we read registers, and we want that to be an atomic i2c
|
||||
transaction in case we are on a multi-master bus */
|
||||
static int xc_read_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
|
||||
{
|
||||
struct i2c_msg msg = { .addr = priv->i2c_props.addr,
|
||||
.flags = I2C_M_RD, .buf = buf, .len = len };
|
||||
|
||||
if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
|
||||
printk(KERN_ERR "xc4000 I2C read failed (len=%i)\n", len);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xc_wait(int wait_ms)
|
||||
{
|
||||
|
@ -378,12 +362,6 @@ static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
|
|||
return XC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int xc_initialize(struct xc4000_priv *priv)
|
||||
{
|
||||
dprintk(1, "%s()\n", __func__);
|
||||
return xc_write_reg(priv, XREG_INIT, 0);
|
||||
}
|
||||
|
||||
static int xc_SetTVStandard(struct xc4000_priv *priv,
|
||||
u16 VideoMode, u16 AudioMode)
|
||||
{
|
||||
|
@ -435,16 +413,6 @@ static int xc_set_RF_frequency(struct xc4000_priv *priv, u32 freq_hz)
|
|||
}
|
||||
|
||||
|
||||
static int xc_set_IF_frequency(struct xc4000_priv *priv, u32 freq_khz)
|
||||
{
|
||||
u32 freq_code = (freq_khz * 1024)/1000;
|
||||
dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
|
||||
__func__, freq_khz, freq_code);
|
||||
|
||||
return xc_write_reg(priv, XREG_IF_OUT, freq_code);
|
||||
}
|
||||
|
||||
|
||||
static int xc_get_ADC_Envelope(struct xc4000_priv *priv, u16 *adc_envelope)
|
||||
{
|
||||
return xc4000_readreg(priv, XREG_ADC_ENV, adc_envelope);
|
||||
|
@ -751,6 +719,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
|
|||
(unsigned long long)*id);
|
||||
|
||||
p = priv->firm[pos].ptr;
|
||||
printk("firmware length = %d\n", priv->firm[pos].size);
|
||||
|
||||
rc = xc_load_i2c_sequence(fe, p);
|
||||
|
||||
|
@ -911,7 +880,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
|
|||
struct xc4000_priv *priv = fe->tuner_priv;
|
||||
int pos, rc;
|
||||
unsigned char *p;
|
||||
u8 direct_mode[4];
|
||||
u8 scode_buf[13];
|
||||
u8 indirect_mode[5];
|
||||
|
||||
dprintk(1, "%s called\n", __func__);
|
||||
|
@ -951,24 +920,28 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
|
|||
printk("(%x), id %016llx.\n", priv->firm[pos].type,
|
||||
(unsigned long long)*id);
|
||||
|
||||
scode_buf[0] = 0x00;
|
||||
memcpy(&scode_buf[1], p, 12);
|
||||
|
||||
/* Enter direct-mode */
|
||||
memset(direct_mode, 0, sizeof(direct_mode));
|
||||
direct_mode[1] = 0x05;
|
||||
rc = xc_send_i2c_data(priv, direct_mode, sizeof(direct_mode));
|
||||
if (rc < 0)
|
||||
rc = xc_write_reg(priv, XREG_DIRECTSITTING_MODE, 0);
|
||||
if (rc < 0) {
|
||||
printk("failed to put device into direct mode!\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = xc_send_i2c_data(priv, p, 12);
|
||||
if (rc != XC_RESULT_SUCCESS)
|
||||
return -EIO;
|
||||
rc = xc_send_i2c_data(priv, scode_buf, 13);
|
||||
if (rc != XC_RESULT_SUCCESS) {
|
||||
/* Even if the send failed, make sure we set back to indirect
|
||||
mode */
|
||||
printk("Failed to set scode %d\n", rc);
|
||||
}
|
||||
|
||||
/* Switch back to indirect-mode */
|
||||
memset(indirect_mode, 0, sizeof(indirect_mode));
|
||||
indirect_mode[4] = 0x88;
|
||||
rc = xc_send_i2c_data(priv, indirect_mode, sizeof(indirect_mode));
|
||||
if (rc < 0)
|
||||
return -EIO;
|
||||
xc_send_i2c_data(priv, indirect_mode, sizeof(indirect_mode));
|
||||
msleep(10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1057,6 +1030,8 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
printk("Done with init1\n");
|
||||
|
||||
skip_base:
|
||||
/*
|
||||
* No need to reload standard specific firmware if base firmware
|
||||
|
@ -1071,9 +1046,8 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
|
|||
/* Reloading std-specific firmware forces a SCODE update */
|
||||
priv->cur_fw.scode_table = 0;
|
||||
|
||||
/* Load the standard firmware */
|
||||
rc = load_firmware(fe, new_fw.type, &new_fw.id);
|
||||
if (rc == -ENOENT)
|
||||
rc = load_firmware(fe, new_fw.type & ~F8MHZ, &new_fw.id);
|
||||
|
||||
if (rc < 0)
|
||||
goto fail;
|
||||
|
@ -1089,10 +1063,10 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
|
|||
goto check_device;
|
||||
|
||||
/* Load SCODE firmware, if exists */
|
||||
dprintk(1, "Trying to load scode %d\n", new_fw.scode_nr);
|
||||
|
||||
rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
|
||||
new_fw.int_freq, new_fw.scode_nr);
|
||||
if (rc != XC_RESULT_SUCCESS)
|
||||
dprintk(1, "load scode failed %d\n", rc);
|
||||
|
||||
check_device:
|
||||
rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel);
|
||||
|
@ -1209,11 +1183,13 @@ static int xc4000_set_params(struct dvb_frontend *fe,
|
|||
struct xc4000_priv *priv = fe->tuner_priv;
|
||||
int ret;
|
||||
|
||||
if (xc4000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
|
||||
xc_load_fw_and_init_tuner(fe);
|
||||
|
||||
dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
|
||||
|
||||
/* FIXME: setup proper parameters */
|
||||
if (check_firmware(fe, DTV8, 0, 5400) != XC_RESULT_SUCCESS) {
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
if (fe->ops.info.type == FE_ATSC) {
|
||||
dprintk(1, "%s() ATSC\n", __func__);
|
||||
switch (params->u.vsb.modulation) {
|
||||
|
@ -1281,14 +1257,14 @@ static int xc4000_set_params(struct dvb_frontend *fe,
|
|||
printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
#ifdef DJH_DEBUG
|
||||
ret = xc_set_IF_frequency(priv, priv->if_khz);
|
||||
if (ret != XC_RESULT_SUCCESS) {
|
||||
printk(KERN_ERR "xc4000: xc_Set_IF_frequency(%d) failed\n",
|
||||
priv->if_khz);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#endif
|
||||
xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
|
||||
|
||||
if (debug)
|
||||
|
@ -1322,12 +1298,14 @@ static int xc4000_set_analog_params(struct dvb_frontend *fe,
|
|||
struct xc4000_priv *priv = fe->tuner_priv;
|
||||
int ret;
|
||||
|
||||
if (xc4000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
|
||||
xc_load_fw_and_init_tuner(fe);
|
||||
|
||||
dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
|
||||
__func__, params->frequency);
|
||||
|
||||
/* FIXME: setup proper parameters */
|
||||
if (check_firmware(fe, DTV8, 0, 5400) != XC_RESULT_SUCCESS) {
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
/* Fix me: it could be air. */
|
||||
priv->rf_mode = params->mode;
|
||||
if (params->mode > XC_RF_MODE_CABLE)
|
||||
|
@ -1435,54 +1413,10 @@ static int xc4000_get_status(struct dvb_frontend *fe, u32 *status)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
|
||||
{
|
||||
struct xc4000_priv *priv = fe->tuner_priv;
|
||||
int ret = 0;
|
||||
|
||||
if (xc4000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
|
||||
ret = xc4000_fwupload(fe);
|
||||
if (ret != XC_RESULT_SUCCESS)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Start the tuner self-calibration process */
|
||||
ret |= xc_initialize(priv);
|
||||
|
||||
/* Wait for calibration to complete.
|
||||
* We could continue but XC4000 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);
|
||||
|
||||
/* Default to "CABLE" mode */
|
||||
ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int xc4000_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dprintk(1, "%s()\n", __func__);
|
||||
|
||||
/* Avoid firmware reload on slow devices */
|
||||
if (no_poweroff)
|
||||
return 0;
|
||||
|
||||
/* According to Xceive technical support, the "powerdown" register
|
||||
was removed in newer versions of the firmware. The "supported"
|
||||
way to sleep the tuner is to pull the reset pin low for 10ms */
|
||||
ret = xc4000_TunerReset(fe);
|
||||
if (ret != XC_RESULT_SUCCESS) {
|
||||
printk(KERN_ERR
|
||||
"xc4000: %s() unable to shutdown tuner\n",
|
||||
__func__);
|
||||
return -EREMOTEIO;
|
||||
} else
|
||||
return XC_RESULT_SUCCESS;
|
||||
/* FIXME: djh disable this for now... */
|
||||
return XC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int xc4000_init(struct dvb_frontend *fe)
|
||||
|
@ -1490,7 +1424,7 @@ static int xc4000_init(struct dvb_frontend *fe)
|
|||
struct xc4000_priv *priv = fe->tuner_priv;
|
||||
dprintk(1, "%s()\n", __func__);
|
||||
|
||||
if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
|
||||
if (check_firmware(fe, DTV8, 0, 5400) != XC_RESULT_SUCCESS) {
|
||||
printk(KERN_ERR "xc4000: Unable to initialise tuner\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
@ -1544,9 +1478,7 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
|
|||
{
|
||||
struct xc4000_priv *priv = NULL;
|
||||
int instance;
|
||||
v4l2_std_id std0;
|
||||
u16 id = 0;
|
||||
int rc;
|
||||
|
||||
dprintk(1, "%s(%d-%04x)\n", __func__,
|
||||
i2c ? i2c_adapter_id(i2c) : -1,
|
||||
|
@ -1615,32 +1547,8 @@ struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
|
|||
|
||||
/* FIXME: For now, load the firmware at startup. We will remove this
|
||||
before the code goes to production... */
|
||||
#ifdef DJH_DEBUG
|
||||
xc4000_fwupload(fe);
|
||||
printk("xc4000_fwupload done\n");
|
||||
|
||||
std0 = 0;
|
||||
// rc = load_firmware(fe, BASE | new_fw.type, &std0);
|
||||
rc = load_firmware(fe, BASE, &std0);
|
||||
if (rc != XC_RESULT_SUCCESS) {
|
||||
tuner_err("Error %d while loading base firmware\n",
|
||||
rc);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Load INIT1, if needed */
|
||||
dprintk("Load init1 firmware, if exists\n");
|
||||
|
||||
// rc = load_firmware(fe, BASE | INIT1 | new_fw.type, &std0);
|
||||
rc = load_firmware(fe, BASE | INIT1, &std0);
|
||||
printk("init1 load result %x\n", rc);
|
||||
#endif
|
||||
check_firmware(fe, DTV8, 0, 5400);
|
||||
|
||||
if (xc4000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS)
|
||||
goto fail;
|
||||
printk("djh id is now %x\n", id);
|
||||
|
||||
return fe;
|
||||
fail:
|
||||
mutex_unlock(&xc4000_list_mutex);
|
||||
|
|
Loading…
Reference in a new issue