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 { int chip_id; u16 pll_register_no; + u8 init_status_supported; + u8 fw_checksum_supported; }; /* Misc Defines */ @@ -113,6 +115,8 @@ struct xc5000_priv { #define XREG_BUSY 0x09 #define XREG_BUILD 0x0D #define XREG_TOTALGAIN 0x0F +#define XREG_FW_CHECKSUM 0x12 +#define XREG_INIT_STATUS 0x13 /* Basic firmware description. This will remain with @@ -211,6 +215,8 @@ struct xc5000_fw_cfg { char *name; u16 size; u16 pll_reg; + u8 init_status_supported; + u8 fw_checksum_supported; }; #define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw" @@ -225,6 +231,8 @@ static const struct xc5000_fw_cfg xc5000c_41_024_5 = { .name = XC5000C_FIRMWARE, .size = 16497, .pll_reg = 0x13, + .init_status_supported = 1, + .fw_checksum_supported = 1, }; static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id) @@ -624,6 +632,8 @@ static int xc5000_fwupload(struct dvb_frontend *fe) 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", @@ -1090,6 +1100,7 @@ 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; u16 pll_lock_status; + u16 fw_ck; if (force || xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { @@ -1101,6 +1112,21 @@ fw_retry: 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 (fw_ck == 0) { + dprintk(1, "%s() FW checksum failed = 0x%04x\n", + __func__, fw_ck); + goto fw_retry; + } + } + /* Start the tuner self-calibration process */ ret |= xc_initialize(priv); @@ -1114,6 +1140,19 @@ fw_retry: */ xc_wait(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 (fw_ck == 0) { + dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck); + goto fw_retry; + } + } + if (priv->pll_register_no) { xc5000_readreg(priv, priv->pll_register_no, &pll_lock_status);