aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/common/tuners/xc5000.c
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2012-08-06 21:47:09 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-09 19:56:45 -0400
commit22d5c6f585352566ab4161d9aa7936100f94af05 (patch)
treed7ebb3accc98a2fdd1d6bc719576f62d83c9df70 /drivers/media/common/tuners/xc5000.c
parentde49bc6ee9c38ac73abf41f3874918d930b2d985 (diff)
[media] xc5000: add support for firmware load check and init status
The xc5000c and newer versions of the xc5000a firmware need minor revisions to their initialization process. Add support for validating the firmware was properly loaded, as well as checking the init status after initialization. Based on advice from CrestaTech support as well as xc5000 datasheet v2.3. Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/common/tuners/xc5000.c')
-rw-r--r--drivers/media/common/tuners/xc5000.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index cd92b9e1ccdd..b488c0e1bcd7 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -63,6 +63,8 @@ struct xc5000_priv {
63 63
64 int chip_id; 64 int chip_id;
65 u16 pll_register_no; 65 u16 pll_register_no;
66 u8 init_status_supported;
67 u8 fw_checksum_supported;
66}; 68};
67 69
68/* Misc Defines */ 70/* Misc Defines */
@@ -113,6 +115,8 @@ struct xc5000_priv {
113#define XREG_BUSY 0x09 115#define XREG_BUSY 0x09
114#define XREG_BUILD 0x0D 116#define XREG_BUILD 0x0D
115#define XREG_TOTALGAIN 0x0F 117#define XREG_TOTALGAIN 0x0F
118#define XREG_FW_CHECKSUM 0x12
119#define XREG_INIT_STATUS 0x13
116 120
117/* 121/*
118 Basic firmware description. This will remain with 122 Basic firmware description. This will remain with
@@ -211,6 +215,8 @@ struct xc5000_fw_cfg {
211 char *name; 215 char *name;
212 u16 size; 216 u16 size;
213 u16 pll_reg; 217 u16 pll_reg;
218 u8 init_status_supported;
219 u8 fw_checksum_supported;
214}; 220};
215 221
216#define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" 222#define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw"
@@ -225,6 +231,8 @@ static const struct xc5000_fw_cfg xc5000c_41_024_5 = {
225 .name = XC5000C_FIRMWARE, 231 .name = XC5000C_FIRMWARE,
226 .size = 16497, 232 .size = 16497,
227 .pll_reg = 0x13, 233 .pll_reg = 0x13,
234 .init_status_supported = 1,
235 .fw_checksum_supported = 1,
228}; 236};
229 237
230static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) 238static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
@@ -624,6 +632,8 @@ static int xc5000_fwupload(struct dvb_frontend *fe)
624 const struct xc5000_fw_cfg *desired_fw = 632 const struct xc5000_fw_cfg *desired_fw =
625 xc5000_assign_firmware(priv->chip_id); 633 xc5000_assign_firmware(priv->chip_id);
626 priv->pll_register_no = desired_fw->pll_reg; 634 priv->pll_register_no = desired_fw->pll_reg;
635 priv->init_status_supported = desired_fw->init_status_supported;
636 priv->fw_checksum_supported = desired_fw->fw_checksum_supported;
627 637
628 /* request the firmware, this will block and timeout */ 638 /* request the firmware, this will block and timeout */
629 printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n", 639 printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
@@ -1090,6 +1100,7 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force)
1090 struct xc5000_priv *priv = fe->tuner_priv; 1100 struct xc5000_priv *priv = fe->tuner_priv;
1091 int ret = XC_RESULT_SUCCESS; 1101 int ret = XC_RESULT_SUCCESS;
1092 u16 pll_lock_status; 1102 u16 pll_lock_status;
1103 u16 fw_ck;
1093 1104
1094 if (force || xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { 1105 if (force || xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
1095 1106
@@ -1101,6 +1112,21 @@ fw_retry:
1101 1112
1102 msleep(20); 1113 msleep(20);
1103 1114
1115 if (priv->fw_checksum_supported) {
1116 if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)
1117 != XC_RESULT_SUCCESS) {
1118 dprintk(1, "%s() FW checksum reading failed.\n",
1119 __func__);
1120 goto fw_retry;
1121 }
1122
1123 if (fw_ck == 0) {
1124 dprintk(1, "%s() FW checksum failed = 0x%04x\n",
1125 __func__, fw_ck);
1126 goto fw_retry;
1127 }
1128 }
1129
1104 /* Start the tuner self-calibration process */ 1130 /* Start the tuner self-calibration process */
1105 ret |= xc_initialize(priv); 1131 ret |= xc_initialize(priv);
1106 1132
@@ -1114,6 +1140,19 @@ fw_retry:
1114 */ 1140 */
1115 xc_wait(100); 1141 xc_wait(100);
1116 1142
1143 if (priv->init_status_supported) {
1144 if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != XC_RESULT_SUCCESS) {
1145 dprintk(1, "%s() FW failed reading init status.\n",
1146 __func__);
1147 goto fw_retry;
1148 }
1149
1150 if (fw_ck == 0) {
1151 dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck);
1152 goto fw_retry;
1153 }
1154 }
1155
1117 if (priv->pll_register_no) { 1156 if (priv->pll_register_no) {
1118 xc5000_readreg(priv, priv->pll_register_no, 1157 xc5000_readreg(priv, priv->pll_register_no,
1119 &pll_lock_status); 1158 &pll_lock_status);