diff options
Diffstat (limited to 'drivers/media/common/tuners/xc5000.c')
-rw-r--r-- | drivers/media/common/tuners/xc5000.c | 58 |
1 files changed, 52 insertions, 6 deletions
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index 06f66fedfff3..cd92b9e1ccdd 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c | |||
@@ -62,6 +62,7 @@ struct xc5000_priv { | |||
62 | u8 radio_input; | 62 | u8 radio_input; |
63 | 63 | ||
64 | int chip_id; | 64 | int chip_id; |
65 | u16 pll_register_no; | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | /* Misc Defines */ | 68 | /* Misc Defines */ |
@@ -209,18 +210,21 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { | |||
209 | struct xc5000_fw_cfg { | 210 | struct xc5000_fw_cfg { |
210 | char *name; | 211 | char *name; |
211 | u16 size; | 212 | u16 size; |
213 | u16 pll_reg; | ||
212 | }; | 214 | }; |
213 | 215 | ||
214 | #define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" | 216 | #define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" |
215 | static const struct xc5000_fw_cfg xc5000a_1_6_114 = { | 217 | static const struct xc5000_fw_cfg xc5000a_1_6_114 = { |
216 | .name = XC5000A_FIRMWARE, | 218 | .name = XC5000A_FIRMWARE, |
217 | .size = 12401, | 219 | .size = 12401, |
220 | .pll_reg = 0x806c, | ||
218 | }; | 221 | }; |
219 | 222 | ||
220 | #define XC5000C_FIRMWARE "dvb-fe-xc5000c-41.024.5.fw" | 223 | #define XC5000C_FIRMWARE "dvb-fe-xc5000c-41.024.5.fw" |
221 | static const struct xc5000_fw_cfg xc5000c_41_024_5 = { | 224 | static const struct xc5000_fw_cfg xc5000c_41_024_5 = { |
222 | .name = XC5000C_FIRMWARE, | 225 | .name = XC5000C_FIRMWARE, |
223 | .size = 16497, | 226 | .size = 16497, |
227 | .pll_reg = 0x13, | ||
224 | }; | 228 | }; |
225 | 229 | ||
226 | static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) | 230 | static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) |
@@ -234,7 +238,7 @@ static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) | |||
234 | } | 238 | } |
235 | } | 239 | } |
236 | 240 | ||
237 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); | 241 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force); |
238 | static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); | 242 | static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); |
239 | static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); | 243 | static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); |
240 | static int xc5000_TunerReset(struct dvb_frontend *fe); | 244 | static int xc5000_TunerReset(struct dvb_frontend *fe); |
@@ -619,6 +623,7 @@ static int xc5000_fwupload(struct dvb_frontend *fe) | |||
619 | int ret; | 623 | int ret; |
620 | const struct xc5000_fw_cfg *desired_fw = | 624 | const struct xc5000_fw_cfg *desired_fw = |
621 | xc5000_assign_firmware(priv->chip_id); | 625 | xc5000_assign_firmware(priv->chip_id); |
626 | priv->pll_register_no = desired_fw->pll_reg; | ||
622 | 627 | ||
623 | /* request the firmware, this will block and timeout */ | 628 | /* request the firmware, this will block and timeout */ |
624 | printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", | 629 | printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", |
@@ -668,6 +673,7 @@ static void xc_debug_dump(struct xc5000_priv *priv) | |||
668 | u8 hw_majorversion = 0, hw_minorversion = 0; | 673 | u8 hw_majorversion = 0, hw_minorversion = 0; |
669 | u8 fw_majorversion = 0, fw_minorversion = 0; | 674 | u8 fw_majorversion = 0, fw_minorversion = 0; |
670 | u16 fw_buildversion = 0; | 675 | u16 fw_buildversion = 0; |
676 | u16 regval; | ||
671 | 677 | ||
672 | /* Wait for stats to stabilize. | 678 | /* Wait for stats to stabilize. |
673 | * Frame Lines needs two frame times after initial lock | 679 | * Frame Lines needs two frame times after initial lock |
@@ -707,6 +713,11 @@ static void xc_debug_dump(struct xc5000_priv *priv) | |||
707 | xc_get_totalgain(priv, &totalgain); | 713 | xc_get_totalgain(priv, &totalgain); |
708 | dprintk(1, "*** Total gain = %d.%d dB\n", totalgain / 256, | 714 | dprintk(1, "*** Total gain = %d.%d dB\n", totalgain / 256, |
709 | (totalgain % 256) * 100 / 256); | 715 | (totalgain % 256) * 100 / 256); |
716 | |||
717 | if (priv->pll_register_no) { | ||
718 | xc5000_readreg(priv, priv->pll_register_no, ®val); | ||
719 | dprintk(1, "*** PLL lock status = 0x%04x\n", regval); | ||
720 | } | ||
710 | } | 721 | } |
711 | 722 | ||
712 | static int xc5000_set_params(struct dvb_frontend *fe) | 723 | static int xc5000_set_params(struct dvb_frontend *fe) |
@@ -717,7 +728,7 @@ static int xc5000_set_params(struct dvb_frontend *fe) | |||
717 | u32 freq = fe->dtv_property_cache.frequency; | 728 | u32 freq = fe->dtv_property_cache.frequency; |
718 | u32 delsys = fe->dtv_property_cache.delivery_system; | 729 | u32 delsys = fe->dtv_property_cache.delivery_system; |
719 | 730 | ||
720 | if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { | 731 | if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { |
721 | dprintk(1, "Unable to load firmware and init tuner\n"); | 732 | dprintk(1, "Unable to load firmware and init tuner\n"); |
722 | return -EINVAL; | 733 | return -EINVAL; |
723 | } | 734 | } |
@@ -850,6 +861,7 @@ static int xc5000_set_tv_freq(struct dvb_frontend *fe, | |||
850 | struct analog_parameters *params) | 861 | struct analog_parameters *params) |
851 | { | 862 | { |
852 | struct xc5000_priv *priv = fe->tuner_priv; | 863 | struct xc5000_priv *priv = fe->tuner_priv; |
864 | u16 pll_lock_status; | ||
853 | int ret; | 865 | int ret; |
854 | 866 | ||
855 | dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", | 867 | dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", |
@@ -930,6 +942,21 @@ tune_channel: | |||
930 | if (debug) | 942 | if (debug) |
931 | xc_debug_dump(priv); | 943 | xc_debug_dump(priv); |
932 | 944 | ||
945 | if (priv->pll_register_no != 0) { | ||
946 | msleep(20); | ||
947 | xc5000_readreg(priv, priv->pll_register_no, &pll_lock_status); | ||
948 | if (pll_lock_status > 63) { | ||
949 | /* PLL is unlocked, force reload of the firmware */ | ||
950 | dprintk(1, "xc5000: PLL not locked (0x%x). Reloading...\n", | ||
951 | pll_lock_status); | ||
952 | if (xc_load_fw_and_init_tuner(fe, 1) != XC_RESULT_SUCCESS) { | ||
953 | printk(KERN_ERR "xc5000: Unable to reload fw\n"); | ||
954 | return -EREMOTEIO; | ||
955 | } | ||
956 | goto tune_channel; | ||
957 | } | ||
958 | } | ||
959 | |||
933 | return 0; | 960 | return 0; |
934 | } | 961 | } |
935 | 962 | ||
@@ -1000,7 +1027,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, | |||
1000 | if (priv->i2c_props.adap == NULL) | 1027 | if (priv->i2c_props.adap == NULL) |
1001 | return -EINVAL; | 1028 | return -EINVAL; |
1002 | 1029 | ||
1003 | if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { | 1030 | if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { |
1004 | dprintk(1, "Unable to load firmware and init tuner\n"); | 1031 | dprintk(1, "Unable to load firmware and init tuner\n"); |
1005 | return -EINVAL; | 1032 | return -EINVAL; |
1006 | } | 1033 | } |
@@ -1058,19 +1085,28 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status) | |||
1058 | return 0; | 1085 | return 0; |
1059 | } | 1086 | } |
1060 | 1087 | ||
1061 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) | 1088 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force) |
1062 | { | 1089 | { |
1063 | struct xc5000_priv *priv = fe->tuner_priv; | 1090 | struct xc5000_priv *priv = fe->tuner_priv; |
1064 | int ret = XC_RESULT_SUCCESS; | 1091 | int ret = XC_RESULT_SUCCESS; |
1092 | u16 pll_lock_status; | ||
1093 | |||
1094 | if (force || xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { | ||
1095 | |||
1096 | fw_retry: | ||
1065 | 1097 | ||
1066 | if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { | ||
1067 | ret = xc5000_fwupload(fe); | 1098 | ret = xc5000_fwupload(fe); |
1068 | if (ret != XC_RESULT_SUCCESS) | 1099 | if (ret != XC_RESULT_SUCCESS) |
1069 | return ret; | 1100 | return ret; |
1070 | 1101 | ||
1102 | msleep(20); | ||
1103 | |||
1071 | /* Start the tuner self-calibration process */ | 1104 | /* Start the tuner self-calibration process */ |
1072 | ret |= xc_initialize(priv); | 1105 | ret |= xc_initialize(priv); |
1073 | 1106 | ||
1107 | if (ret != XC_RESULT_SUCCESS) | ||
1108 | goto fw_retry; | ||
1109 | |||
1074 | /* Wait for calibration to complete. | 1110 | /* Wait for calibration to complete. |
1075 | * We could continue but XC5000 will clock stretch subsequent | 1111 | * We could continue but XC5000 will clock stretch subsequent |
1076 | * I2C transactions until calibration is complete. This way we | 1112 | * I2C transactions until calibration is complete. This way we |
@@ -1078,6 +1114,16 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) | |||
1078 | */ | 1114 | */ |
1079 | xc_wait(100); | 1115 | xc_wait(100); |
1080 | 1116 | ||
1117 | if (priv->pll_register_no) { | ||
1118 | xc5000_readreg(priv, priv->pll_register_no, | ||
1119 | &pll_lock_status); | ||
1120 | if (pll_lock_status > 63) { | ||
1121 | /* PLL is unlocked, force reload of the firmware */ | ||
1122 | printk(KERN_ERR "xc5000: PLL not running after fwload.\n"); | ||
1123 | goto fw_retry; | ||
1124 | } | ||
1125 | } | ||
1126 | |||
1081 | /* Default to "CABLE" mode */ | 1127 | /* Default to "CABLE" mode */ |
1082 | ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); | 1128 | ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE); |
1083 | } | 1129 | } |
@@ -1113,7 +1159,7 @@ static int xc5000_init(struct dvb_frontend *fe) | |||
1113 | struct xc5000_priv *priv = fe->tuner_priv; | 1159 | struct xc5000_priv *priv = fe->tuner_priv; |
1114 | dprintk(1, "%s()\n", __func__); | 1160 | dprintk(1, "%s()\n", __func__); |
1115 | 1161 | ||
1116 | if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { | 1162 | if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) { |
1117 | printk(KERN_ERR "xc5000: Unable to initialise tuner\n"); | 1163 | printk(KERN_ERR "xc5000: Unable to initialise tuner\n"); |
1118 | return -EREMOTEIO; | 1164 | return -EREMOTEIO; |
1119 | } | 1165 | } |