aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/common
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2012-08-06 21:47:08 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-09 19:55:55 -0400
commitde49bc6ee9c38ac73abf41f3874918d930b2d985 (patch)
tree3a767ad78e1b7edd5f236d232167971b45930187 /drivers/media/common
parentbaede40c4daf2157413ae218946d6fe3b3ed1292 (diff)
[media] xc5000: reset device if encountering PLL lock failure
It's possible for the xc5000 to enter an unknown state such that all subsequent tuning requests fail. The only way to recover is to reset the tuner and reload the firmware. This problem was detected after several days straight of issuing tuning requests every five seconds. Reset the firmware in the event that the PLL is in an unlocked state. This solution was provided by the engineer at CrestaTech (the company that acquired Xceive). Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/common')
-rw-r--r--drivers/media/common/tuners/xc5000.c58
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] = {
209struct xc5000_fw_cfg { 210struct 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"
215static const struct xc5000_fw_cfg xc5000a_1_6_114 = { 217static 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"
221static const struct xc5000_fw_cfg xc5000c_41_024_5 = { 224static 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
226static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) 230static 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
237static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); 241static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force);
238static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); 242static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
239static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val); 243static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val);
240static int xc5000_TunerReset(struct dvb_frontend *fe); 244static 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, &regval);
719 dprintk(1, "*** PLL lock status = 0x%04x\n", regval);
720 }
710} 721}
711 722
712static int xc5000_set_params(struct dvb_frontend *fe) 723static 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
1061static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) 1088static 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
1096fw_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 }