--- zzzz-none-000/linux-3.10.107/drivers/media/tuners/xc5000.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/media/tuners/xc5000.c 2021-02-04 17:41:59.000000000 +0000 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -58,33 +59,36 @@ u32 freq_hz, freq_offset; u32 bandwidth; u8 video_standard; + unsigned int mode; u8 rf_mode; u8 radio_input; + u16 output_amp; int chip_id; u16 pll_register_no; u8 init_status_supported; u8 fw_checksum_supported; + + struct dvb_frontend *fe; + struct delayed_work timer_sleep; + + const struct firmware *firmware; }; /* Misc Defines */ #define MAX_TV_STANDARD 24 #define XC_MAX_I2C_WRITE_LENGTH 64 +/* Time to suspend after the .sleep callback is called */ +#define XC5000_SLEEP_TIME 5000 /* ms */ + /* Signal Types */ #define XC_RF_MODE_AIR 0 #define XC_RF_MODE_CABLE 1 -/* Result codes */ -#define XC_RESULT_SUCCESS 0 -#define XC_RESULT_RESET_FAILURE 1 -#define XC_RESULT_I2C_WRITE_FAILURE 2 -#define XC_RESULT_I2C_READ_FAILURE 3 -#define XC_RESULT_OUT_OF_RANGE 5 - /* Product id */ #define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000 -#define XC_PRODUCT_ID_FW_LOADED 0x1388 +#define XC_PRODUCT_ID_FW_LOADED 0x1388 /* Registers */ #define XREG_INIT 0x00 @@ -152,16 +156,16 @@ */ struct XC_TV_STANDARD { - char *Name; - u16 AudioMode; - u16 VideoMode; + char *name; + u16 audio_mode; + u16 video_mode; }; /* Tuner standards */ #define MN_NTSC_PAL_BTSC 0 #define MN_NTSC_PAL_A2 1 #define MN_NTSC_PAL_EIAJ 2 -#define MN_NTSC_PAL_Mono 3 +#define MN_NTSC_PAL_MONO 3 #define BG_PAL_A2 4 #define BG_PAL_NICAM 5 #define BG_PAL_MONO 6 @@ -171,19 +175,19 @@ #define DK_PAL_NICAM 10 #define DK_PAL_MONO 11 #define DK_SECAM_A2DK1 12 -#define DK_SECAM_A2LDK3 13 -#define DK_SECAM_A2MONO 14 +#define DK_SECAM_A2LDK3 13 +#define DK_SECAM_A2MONO 14 #define L_SECAM_NICAM 15 #define LC_SECAM_NICAM 16 #define DTV6 17 #define DTV8 18 #define DTV7_8 19 #define DTV7 20 -#define FM_Radio_INPUT2 21 -#define FM_Radio_INPUT1 22 -#define FM_Radio_INPUT1_MONO 23 +#define FM_RADIO_INPUT2 21 +#define FM_RADIO_INPUT1 22 +#define FM_RADIO_INPUT1_MONO 23 -static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { +static struct XC_TV_STANDARD xc5000_standard[MAX_TV_STANDARD] = { {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020}, {"M/N-NTSC/PAL-A2", 0x0600, 0x8020}, {"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020}, @@ -249,7 +253,7 @@ 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); +static int xc5000_tuner_reset(struct dvb_frontend *fe); static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len) { @@ -258,9 +262,9 @@ if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", len); - return XC_RESULT_I2C_WRITE_FAILURE; + return -EREMOTEIO; } - return XC_RESULT_SUCCESS; + return 0; } #if 0 @@ -297,15 +301,10 @@ } *val = (bval[0] << 8) | bval[1]; - return XC_RESULT_SUCCESS; -} - -static void xc_wait(int wait_ms) -{ - msleep(wait_ms); + return 0; } -static int xc5000_TunerReset(struct dvb_frontend *fe) +static int xc5000_tuner_reset(struct dvb_frontend *fe) { struct xc5000_priv *priv = fe->tuner_priv; int ret; @@ -320,43 +319,43 @@ XC5000_TUNER_RESET, 0); if (ret) { printk(KERN_ERR "xc5000: reset failed\n"); - return XC_RESULT_RESET_FAILURE; + return ret; } } else { printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n"); - return XC_RESULT_RESET_FAILURE; + return -EINVAL; } - return XC_RESULT_SUCCESS; + return 0; } -static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData) +static int xc_write_reg(struct xc5000_priv *priv, u16 reg_addr, u16 i2c_data) { u8 buf[4]; - int WatchDogTimer = 100; + int watch_dog_timer = 100; int result; - buf[0] = (regAddr >> 8) & 0xFF; - buf[1] = regAddr & 0xFF; - buf[2] = (i2cData >> 8) & 0xFF; - buf[3] = i2cData & 0xFF; + buf[0] = (reg_addr >> 8) & 0xFF; + buf[1] = reg_addr & 0xFF; + buf[2] = (i2c_data >> 8) & 0xFF; + buf[3] = i2c_data & 0xFF; result = xc_send_i2c_data(priv, buf, 4); - if (result == XC_RESULT_SUCCESS) { + if (result == 0) { /* wait for busy flag to clear */ - while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) { + while ((watch_dog_timer > 0) && (result == 0)) { result = xc5000_readreg(priv, XREG_BUSY, (u16 *)buf); - if (result == XC_RESULT_SUCCESS) { + if (result == 0) { if ((buf[0] == 0) && (buf[1] == 0)) { /* busy flag cleared */ break; } else { - xc_wait(5); /* wait 5 ms */ - WatchDogTimer--; + msleep(5); /* wait 5 ms */ + watch_dog_timer--; } } } } - if (WatchDogTimer <= 0) - result = XC_RESULT_I2C_WRITE_FAILURE; + if (watch_dog_timer <= 0) + result = -EREMOTEIO; return result; } @@ -375,13 +374,13 @@ len = i2c_sequence[index] * 256 + i2c_sequence[index+1]; if (len == 0x0000) { /* RESET command */ - result = xc5000_TunerReset(fe); + result = xc5000_tuner_reset(fe); index += 2; - if (result != XC_RESULT_SUCCESS) + if (result != 0) return result; } else if (len & 0x8000) { /* WAIT command */ - xc_wait(len & 0x7FFF); + msleep(len & 0x7FFF); index += 2; } else { /* Send i2c data whilst ensuring individual transactions @@ -404,7 +403,7 @@ result = xc_send_i2c_data(priv, buf, nbytes_to_send); - if (result != XC_RESULT_SUCCESS) + if (result != 0) return result; pos += nbytes_to_send - 2; @@ -412,7 +411,7 @@ index += len; } } - return XC_RESULT_SUCCESS; + return 0; } static int xc_initialize(struct xc5000_priv *priv) @@ -421,29 +420,29 @@ return xc_write_reg(priv, XREG_INIT, 0); } -static int xc_SetTVStandard(struct xc5000_priv *priv, - u16 VideoMode, u16 AudioMode, u8 RadioMode) +static int xc_set_tv_standard(struct xc5000_priv *priv, + u16 video_mode, u16 audio_mode, u8 radio_mode) { int ret; - dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode); - if (RadioMode) { + dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, video_mode, audio_mode); + if (radio_mode) { dprintk(1, "%s() Standard = %s\n", __func__, - XC5000_Standard[RadioMode].Name); + xc5000_standard[radio_mode].name); } else { dprintk(1, "%s() Standard = %s\n", __func__, - XC5000_Standard[priv->video_standard].Name); + xc5000_standard[priv->video_standard].name); } - ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode); - if (ret == XC_RESULT_SUCCESS) - ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode); + ret = xc_write_reg(priv, XREG_VIDEO_MODE, video_mode); + if (ret == 0) + ret = xc_write_reg(priv, XREG_AUDIO_MODE, audio_mode); return ret; } -static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode) +static int xc_set_signal_source(struct xc5000_priv *priv, u16 rf_mode) { dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode, rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE"); @@ -459,7 +458,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops; -static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz) +static int xc_set_rf_frequency(struct xc5000_priv *priv, u32 freq_hz) { u16 freq_code; @@ -467,7 +466,7 @@ if ((freq_hz > xc5000_tuner_ops.info.frequency_max) || (freq_hz < xc5000_tuner_ops.info.frequency_min)) - return XC_RESULT_OUT_OF_RANGE; + return -EINVAL; freq_code = (u16)(freq_hz / 15625); @@ -488,7 +487,7 @@ } -static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope) +static int xc_get_adc_envelope(struct xc5000_priv *priv, u16 *adc_envelope) { return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope); } @@ -496,14 +495,14 @@ static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz) { int result; - u16 regData; + u16 reg_data; u32 tmp; - result = xc5000_readreg(priv, XREG_FREQ_ERROR, ®Data); - if (result != XC_RESULT_SUCCESS) + result = xc5000_readreg(priv, XREG_FREQ_ERROR, ®_data); + if (result != 0) return result; - tmp = (u32)regData; + tmp = (u32)reg_data; (*freq_error_hz) = (tmp * 15625) / 1000; return result; } @@ -521,7 +520,7 @@ int result; result = xc5000_readreg(priv, XREG_VERSION, &data); - if (result != XC_RESULT_SUCCESS) + if (result != 0) return result; (*hw_majorversion) = (data >> 12) & 0x0F; @@ -539,14 +538,14 @@ static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz) { - u16 regData; + u16 reg_data; int result; - result = xc5000_readreg(priv, XREG_HSYNC_FREQ, ®Data); - if (result != XC_RESULT_SUCCESS) + result = xc5000_readreg(priv, XREG_HSYNC_FREQ, ®_data); + if (result != 0) return result; - (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100; + (*hsync_freq_hz) = ((reg_data & 0x0fff) * 763)/100; return result; } @@ -570,19 +569,19 @@ return xc5000_readreg(priv, XREG_TOTALGAIN, totalgain); } -static u16 WaitForLock(struct xc5000_priv *priv) +static u16 wait_for_lock(struct xc5000_priv *priv) { - u16 lockState = 0; - int watchDogCount = 40; + u16 lock_state = 0; + int watch_dog_count = 40; - while ((lockState == 0) && (watchDogCount > 0)) { - xc_get_lock_status(priv, &lockState); - if (lockState != 1) { - xc_wait(5); - watchDogCount--; + while ((lock_state == 0) && (watch_dog_count > 0)) { + xc_get_lock_status(priv, &lock_state); + if (lock_state != 1) { + msleep(5); + watch_dog_count--; } } - return lockState; + return lock_state; } #define XC_TUNE_ANALOG 0 @@ -593,11 +592,11 @@ dprintk(1, "%s(%u)\n", __func__, freq_hz); - if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) + if (xc_set_rf_frequency(priv, freq_hz) != 0) return 0; if (mode == XC_TUNE_ANALOG) { - if (WaitForLock(priv) == 1) + if (wait_for_lock(priv) == 1) found = 1; } @@ -607,7 +606,7 @@ static int xc_set_xtal(struct dvb_frontend *fe) { struct xc5000_priv *priv = fe->tuner_priv; - int ret = XC_RESULT_SUCCESS; + int ret = 0; switch (priv->chip_id) { default: @@ -630,49 +629,30 @@ return ret; } -static int xc5000_fwupload(struct dvb_frontend *fe) +static int xc5000_fwupload(struct dvb_frontend *fe, + const struct xc5000_fw_cfg *desired_fw, + const struct firmware *fw) { struct xc5000_priv *priv = fe->tuner_priv; - const struct firmware *fw; int ret; - const struct xc5000_fw_cfg *desired_fw = - xc5000_assign_firmware(priv->chip_id); - priv->pll_register_no = desired_fw->pll_reg; - priv->init_status_supported = desired_fw->init_status_supported; - priv->fw_checksum_supported = desired_fw->fw_checksum_supported; /* request the firmware, this will block and timeout */ - printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", + dprintk(1, "waiting for firmware upload (%s)...\n", desired_fw->name); - ret = request_firmware(&fw, desired_fw->name, - priv->i2c_props.adap->dev.parent); - if (ret) { - printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n"); - ret = XC_RESULT_RESET_FAILURE; - goto out; - } else { - printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n", - fw->size); - ret = XC_RESULT_SUCCESS; - } + priv->pll_register_no = desired_fw->pll_reg; + priv->init_status_supported = desired_fw->init_status_supported; + priv->fw_checksum_supported = desired_fw->fw_checksum_supported; - if (fw->size != desired_fw->size) { - printk(KERN_ERR "xc5000: firmware incorrect size\n"); - ret = XC_RESULT_RESET_FAILURE; - } else { - printk(KERN_INFO "xc5000: firmware uploading...\n"); - ret = xc_load_i2c_sequence(fe, fw->data); - if (XC_RESULT_SUCCESS == ret) - ret = xc_set_xtal(fe); - if (XC_RESULT_SUCCESS == ret) - printk(KERN_INFO "xc5000: firmware upload complete...\n"); - else - printk(KERN_ERR "xc5000: firmware upload failed...\n"); - } -out: - release_firmware(fw); + dprintk(1, "firmware uploading...\n"); + ret = xc_load_i2c_sequence(fe, fw->data); + if (!ret) { + ret = xc_set_xtal(fe); + dprintk(1, "Firmware upload complete...\n"); + } else + printk(KERN_ERR "xc5000: firmware upload failed...\n"); + return ret; } @@ -695,9 +675,9 @@ * Frame Lines needs two frame times after initial lock * before it is valid. */ - xc_wait(100); + msleep(100); - xc_get_ADC_Envelope(priv, &adc_envelope); + xc_get_adc_envelope(priv, &adc_envelope); dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope); xc_get_frequency_error(priv, &freq_error_hz); @@ -736,15 +716,58 @@ } } -static int xc5000_set_params(struct dvb_frontend *fe) +static int xc5000_tune_digital(struct dvb_frontend *fe) +{ + struct xc5000_priv *priv = fe->tuner_priv; + int ret; + u32 bw = fe->dtv_property_cache.bandwidth_hz; + + ret = xc_set_signal_source(priv, priv->rf_mode); + if (ret != 0) { + printk(KERN_ERR + "xc5000: xc_set_signal_source(%d) failed\n", + priv->rf_mode); + return -EREMOTEIO; + } + + ret = xc_set_tv_standard(priv, + xc5000_standard[priv->video_standard].video_mode, + xc5000_standard[priv->video_standard].audio_mode, 0); + if (ret != 0) { + printk(KERN_ERR "xc5000: xc_set_tv_standard failed\n"); + return -EREMOTEIO; + } + + ret = xc_set_IF_frequency(priv, priv->if_khz); + if (ret != 0) { + printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n", + priv->if_khz); + return -EIO; + } + + dprintk(1, "%s() setting OUTPUT_AMP to 0x%x\n", + __func__, priv->output_amp); + xc_write_reg(priv, XREG_OUTPUT_AMP, priv->output_amp); + + xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL); + + if (debug) + xc_debug_dump(priv); + + priv->bandwidth = bw; + + return 0; +} + +static int xc5000_set_digital_params(struct dvb_frontend *fe) { - int ret, b; + int b; struct xc5000_priv *priv = fe->tuner_priv; u32 bw = fe->dtv_property_cache.bandwidth_hz; u32 freq = fe->dtv_property_cache.frequency; u32 delsys = fe->dtv_property_cache.delivery_system; - if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { + if (xc_load_fw_and_init_tuner(fe, 0) != 0) { dprintk(1, "Unable to load firmware and init tuner\n"); return -EINVAL; } @@ -818,43 +841,12 @@ } priv->freq_hz = freq - priv->freq_offset; + priv->mode = V4L2_TUNER_DIGITAL_TV; dprintk(1, "%s() frequency=%d (compensated to %d)\n", __func__, freq, priv->freq_hz); - ret = xc_SetSignalSource(priv, priv->rf_mode); - if (ret != XC_RESULT_SUCCESS) { - printk(KERN_ERR - "xc5000: xc_SetSignalSource(%d) failed\n", - priv->rf_mode); - return -EREMOTEIO; - } - - ret = xc_SetTVStandard(priv, - XC5000_Standard[priv->video_standard].VideoMode, - XC5000_Standard[priv->video_standard].AudioMode, 0); - if (ret != XC_RESULT_SUCCESS) { - printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); - return -EREMOTEIO; - } - - ret = xc_set_IF_frequency(priv, priv->if_khz); - if (ret != XC_RESULT_SUCCESS) { - printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n", - priv->if_khz); - return -EIO; - } - - xc_write_reg(priv, XREG_OUTPUT_AMP, 0x8a); - - xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL); - - if (debug) - xc_debug_dump(priv); - - priv->bandwidth = bw; - - return 0; + return xc5000_tune_digital(fe); } static int xc5000_is_firmware_loaded(struct dvb_frontend *fe) @@ -864,24 +856,22 @@ u16 id; ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id); - if (ret == XC_RESULT_SUCCESS) { + if (ret == 0) { if (id == XC_PRODUCT_ID_FW_NOT_LOADED) - ret = XC_RESULT_RESET_FAILURE; + ret = -ENOENT; else - ret = XC_RESULT_SUCCESS; + ret = 0; } dprintk(1, "%s() returns %s id = 0x%x\n", __func__, - ret == XC_RESULT_SUCCESS ? "True" : "False", id); + ret == 0 ? "True" : "False", id); return ret; } -static int xc5000_set_tv_freq(struct dvb_frontend *fe, - struct analog_parameters *params) +static void xc5000_config_tv(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", __func__, params->frequency); @@ -900,57 +890,64 @@ if (params->std & V4L2_STD_MN) { /* default to BTSC audio standard */ priv->video_standard = MN_NTSC_PAL_BTSC; - goto tune_channel; + return; } if (params->std & V4L2_STD_PAL_BG) { /* default to NICAM audio standard */ priv->video_standard = BG_PAL_NICAM; - goto tune_channel; + return; } if (params->std & V4L2_STD_PAL_I) { /* default to NICAM audio standard */ priv->video_standard = I_PAL_NICAM; - goto tune_channel; + return; } if (params->std & V4L2_STD_PAL_DK) { /* default to NICAM audio standard */ priv->video_standard = DK_PAL_NICAM; - goto tune_channel; + return; } if (params->std & V4L2_STD_SECAM_DK) { /* default to A2 DK1 audio standard */ priv->video_standard = DK_SECAM_A2DK1; - goto tune_channel; + return; } if (params->std & V4L2_STD_SECAM_L) { priv->video_standard = L_SECAM_NICAM; - goto tune_channel; + return; } if (params->std & V4L2_STD_SECAM_LC) { priv->video_standard = LC_SECAM_NICAM; - goto tune_channel; + return; } +} + +static int xc5000_set_tv_freq(struct dvb_frontend *fe) +{ + struct xc5000_priv *priv = fe->tuner_priv; + u16 pll_lock_status; + int ret; tune_channel: - ret = xc_SetSignalSource(priv, priv->rf_mode); - if (ret != XC_RESULT_SUCCESS) { + ret = xc_set_signal_source(priv, priv->rf_mode); + if (ret != 0) { printk(KERN_ERR - "xc5000: xc_SetSignalSource(%d) failed\n", + "xc5000: xc_set_signal_source(%d) failed\n", priv->rf_mode); return -EREMOTEIO; } - ret = xc_SetTVStandard(priv, - XC5000_Standard[priv->video_standard].VideoMode, - XC5000_Standard[priv->video_standard].AudioMode, 0); - if (ret != XC_RESULT_SUCCESS) { - printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); + ret = xc_set_tv_standard(priv, + xc5000_standard[priv->video_standard].video_mode, + xc5000_standard[priv->video_standard].audio_mode, 0); + if (ret != 0) { + printk(KERN_ERR "xc5000: xc_set_tv_standard failed\n"); return -EREMOTEIO; } @@ -968,7 +965,7 @@ /* 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) { + if (xc_load_fw_and_init_tuner(fe, 1) != 0) { printk(KERN_ERR "xc5000: Unable to reload fw\n"); return -EREMOTEIO; } @@ -979,12 +976,11 @@ return 0; } -static int xc5000_set_radio_freq(struct dvb_frontend *fe, - struct analog_parameters *params) +static int xc5000_config_radio(struct dvb_frontend *fe, + struct analog_parameters *params) + { struct xc5000_priv *priv = fe->tuner_priv; - int ret = -EINVAL; - u8 radio_input; dprintk(1, "%s() frequency=%d (in units of khz)\n", __func__, params->frequency); @@ -994,34 +990,42 @@ return -EINVAL; } + priv->freq_hz = params->frequency * 125 / 2; + priv->rf_mode = XC_RF_MODE_AIR; + + return 0; +} + +static int xc5000_set_radio_freq(struct dvb_frontend *fe) +{ + struct xc5000_priv *priv = fe->tuner_priv; + int ret; + u8 radio_input; + if (priv->radio_input == XC5000_RADIO_FM1) - radio_input = FM_Radio_INPUT1; + radio_input = FM_RADIO_INPUT1; else if (priv->radio_input == XC5000_RADIO_FM2) - radio_input = FM_Radio_INPUT2; + radio_input = FM_RADIO_INPUT2; else if (priv->radio_input == XC5000_RADIO_FM1_MONO) - radio_input = FM_Radio_INPUT1_MONO; + radio_input = FM_RADIO_INPUT1_MONO; else { dprintk(1, "%s() unknown radio input %d\n", __func__, priv->radio_input); return -EINVAL; } - priv->freq_hz = params->frequency * 125 / 2; + ret = xc_set_tv_standard(priv, xc5000_standard[radio_input].video_mode, + xc5000_standard[radio_input].audio_mode, radio_input); - priv->rf_mode = XC_RF_MODE_AIR; - - ret = xc_SetTVStandard(priv, XC5000_Standard[radio_input].VideoMode, - XC5000_Standard[radio_input].AudioMode, radio_input); - - if (ret != XC_RESULT_SUCCESS) { - printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n"); + if (ret != 0) { + printk(KERN_ERR "xc5000: xc_set_tv_standard failed\n"); return -EREMOTEIO; } - ret = xc_SetSignalSource(priv, priv->rf_mode); - if (ret != XC_RESULT_SUCCESS) { + ret = xc_set_signal_source(priv, priv->rf_mode); + if (ret != 0) { printk(KERN_ERR - "xc5000: xc_SetSignalSource(%d) failed\n", + "xc5000: xc_set_signal_source(%d) failed\n", priv->rf_mode); return -EREMOTEIO; } @@ -1037,34 +1041,53 @@ return 0; } +static int xc5000_set_params(struct dvb_frontend *fe) +{ + struct xc5000_priv *priv = fe->tuner_priv; + + if (xc_load_fw_and_init_tuner(fe, 0) != 0) { + dprintk(1, "Unable to load firmware and init tuner\n"); + return -EINVAL; + } + + switch (priv->mode) { + case V4L2_TUNER_RADIO: + return xc5000_set_radio_freq(fe); + case V4L2_TUNER_ANALOG_TV: + return xc5000_set_tv_freq(fe); + case V4L2_TUNER_DIGITAL_TV: + return xc5000_tune_digital(fe); + } + + return 0; +} + static int xc5000_set_analog_params(struct dvb_frontend *fe, struct analog_parameters *params) { struct xc5000_priv *priv = fe->tuner_priv; - int ret = -EINVAL; + int ret; if (priv->i2c_props.adap == NULL) return -EINVAL; - if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { - dprintk(1, "Unable to load firmware and init tuner\n"); - return -EINVAL; - } - switch (params->mode) { case V4L2_TUNER_RADIO: - ret = xc5000_set_radio_freq(fe, params); + ret = xc5000_config_radio(fe, params); + if (ret) + return ret; break; case V4L2_TUNER_ANALOG_TV: - case V4L2_TUNER_DIGITAL_TV: - ret = xc5000_set_tv_freq(fe, params); + xc5000_config_tv(fe, params); + break; + default: break; } + priv->mode = params->mode; - return ret; + return xc5000_set_params(fe); } - static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq) { struct xc5000_priv *priv = fe->tuner_priv; @@ -1107,58 +1130,88 @@ 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; + const struct xc5000_fw_cfg *desired_fw = xc5000_assign_firmware(priv->chip_id); + const struct firmware *fw; + int ret, i; u16 pll_lock_status; u16 fw_ck; - if (force || xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { + cancel_delayed_work(&priv->timer_sleep); -fw_retry: + if (!force && xc5000_is_firmware_loaded(fe) == 0) + return 0; - ret = xc5000_fwupload(fe); - if (ret != XC_RESULT_SUCCESS) + if (!priv->firmware) { + ret = request_firmware(&fw, desired_fw->name, + priv->i2c_props.adap->dev.parent); + if (ret) { + pr_err("xc5000: Upload failed. rc %d\n", ret); return ret; + } + dprintk(1, "firmware read %Zu bytes.\n", fw->size); + + if (fw->size != desired_fw->size) { + pr_err("xc5000: Firmware file with incorrect size\n"); + release_firmware(fw); + return -EINVAL; + } + priv->firmware = fw; + } else + fw = priv->firmware; + + /* Try up to 5 times to load firmware */ + for (i = 0; i < 5; i++) { + if (i) + printk(KERN_CONT " - retrying to upload firmware.\n"); + + ret = xc5000_fwupload(fe, desired_fw, fw); + if (ret != 0) + goto err; msleep(20); if (priv->fw_checksum_supported) { - if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck) - != XC_RESULT_SUCCESS) { - dprintk(1, "%s() FW checksum reading failed.\n", - __func__); - goto fw_retry; + if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)) { + printk(KERN_ERR + "xc5000: FW checksum reading failed."); + continue; } - if (fw_ck == 0) { - dprintk(1, "%s() FW checksum failed = 0x%04x\n", - __func__, fw_ck); - goto fw_retry; + if (!fw_ck) { + printk(KERN_ERR + "xc5000: FW checksum failed = 0x%04x.", + fw_ck); + continue; } } /* Start the tuner self-calibration process */ - ret |= xc_initialize(priv); - - if (ret != XC_RESULT_SUCCESS) - goto fw_retry; + ret = xc_initialize(priv); + if (ret) { + printk(KERN_ERR + "xc5000: Can't request Self-callibration."); + continue; + } /* 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); + msleep(100); if (priv->init_status_supported) { - if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != XC_RESULT_SUCCESS) { - dprintk(1, "%s() FW failed reading init status.\n", - __func__); - goto fw_retry; + if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck)) { + printk(KERN_ERR + "xc5000: FW failed reading init status."); + continue; } - if (fw_ck == 0) { - dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck); - goto fw_retry; + if (!fw_ck) { + printk(KERN_ERR + "xc5000: FW init status failed = 0x%04x.", + fw_ck); + continue; } } @@ -1167,39 +1220,94 @@ &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; + printk(KERN_ERR + "xc5000: PLL not running after fwload."); + continue; } } /* Default to "CABLE" mode */ - ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); + ret = xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); + if (!ret) + break; + printk(KERN_ERR "xc5000: can't set to cable mode."); } +err: + if (!ret) + printk(KERN_INFO "xc5000: Firmware %s loaded and running.\n", + desired_fw->name); + else + printk(KERN_CONT " - too many retries. Giving up\n"); + return ret; } -static int xc5000_sleep(struct dvb_frontend *fe) +static void xc5000_do_timer_sleep(struct work_struct *timer_sleep) { + struct xc5000_priv *priv =container_of(timer_sleep, struct xc5000_priv, + timer_sleep.work); + struct dvb_frontend *fe = priv->fe; int ret; dprintk(1, "%s()\n", __func__); + /* 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 = xc5000_tuner_reset(fe); + if (ret != 0) + printk(KERN_ERR + "xc5000: %s() unable to shutdown tuner\n", + __func__); +} + +static int xc5000_sleep(struct dvb_frontend *fe) +{ + struct xc5000_priv *priv = fe->tuner_priv; + + 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 = xc5000_TunerReset(fe); - if (ret != XC_RESULT_SUCCESS) { + schedule_delayed_work(&priv->timer_sleep, + msecs_to_jiffies(XC5000_SLEEP_TIME)); + + return 0; +} + +static int xc5000_suspend(struct dvb_frontend *fe) +{ + struct xc5000_priv *priv = fe->tuner_priv; + int ret; + + dprintk(1, "%s()\n", __func__); + + cancel_delayed_work(&priv->timer_sleep); + + ret = xc5000_tuner_reset(fe); + if (ret != 0) printk(KERN_ERR "xc5000: %s() unable to shutdown tuner\n", __func__); - return -EREMOTEIO; - } else - return XC_RESULT_SUCCESS; + + return 0; +} + +static int xc5000_resume(struct dvb_frontend *fe) +{ + struct xc5000_priv *priv = fe->tuner_priv; + + dprintk(1, "%s()\n", __func__); + + /* suspended before firmware is loaded. + Avoid firmware load in resume path. */ + if (!priv->firmware) + return 0; + + return xc5000_set_params(fe); } static int xc5000_init(struct dvb_frontend *fe) @@ -1207,7 +1315,7 @@ struct xc5000_priv *priv = fe->tuner_priv; dprintk(1, "%s()\n", __func__); - if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { + if (xc_load_fw_and_init_tuner(fe, 0) != 0) { printk(KERN_ERR "xc5000: Unable to initialise tuner\n"); return -EREMOTEIO; } @@ -1226,8 +1334,14 @@ mutex_lock(&xc5000_list_mutex); - if (priv) + if (priv) { + cancel_delayed_work(&priv->timer_sleep); + if (priv->firmware) { + release_firmware(priv->firmware); + priv->firmware = NULL; + } hybrid_tuner_release_state(priv); + } mutex_unlock(&xc5000_list_mutex); @@ -1249,6 +1363,9 @@ if (p->radio_input) priv->radio_input = p->radio_input; + if (p->output_amp) + priv->output_amp = p->output_amp; + return 0; } @@ -1264,9 +1381,11 @@ .release = xc5000_release, .init = xc5000_init, .sleep = xc5000_sleep, + .suspend = xc5000_suspend, + .resume = xc5000_resume, .set_config = xc5000_set_config, - .set_params = xc5000_set_params, + .set_params = xc5000_set_digital_params, .set_analog_params = xc5000_set_analog_params, .get_frequency = xc5000_get_frequency, .get_if_frequency = xc5000_get_if_frequency, @@ -1294,11 +1413,12 @@ switch (instance) { case 0: goto fail; - break; case 1: /* new tuner instance */ priv->bandwidth = 6000000; fe->tuner_priv = priv; + priv->fe = fe; + INIT_DELAYED_WORK(&priv->timer_sleep, xc5000_do_timer_sleep); break; default: /* existing tuner instance */ @@ -1326,10 +1446,16 @@ it can be overridden if this is a hybrid driver */ priv->chip_id = (cfg->chip_id) ? cfg->chip_id : 0; + /* don't override output_amp if it's already been set + unless explicitly specified */ + if ((priv->output_amp == 0) || (cfg->output_amp)) + /* use default output_amp value if none specified */ + priv->output_amp = (cfg->output_amp) ? cfg->output_amp : 0x8a; + /* Check if firmware has been loaded. It is possible that another instance of the driver has loaded the firmware. */ - if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS) + if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) goto fail; switch (id) {