summaryrefslogtreecommitdiff
path: root/linux/drivers/media/common/tuners
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/common/tuners')
-rw-r--r--linux/drivers/media/common/tuners/Kconfig2
-rw-r--r--linux/drivers/media/common/tuners/mt20xx.c3
-rw-r--r--linux/drivers/media/common/tuners/tda18271-common.c14
-rw-r--r--linux/drivers/media/common/tuners/tda18271-fe.c53
-rw-r--r--linux/drivers/media/common/tuners/tda18271-maps.c2
-rw-r--r--linux/drivers/media/common/tuners/tda827x.c4
-rw-r--r--linux/drivers/media/common/tuners/tda8290.c3
-rw-r--r--linux/drivers/media/common/tuners/tda9887.c10
-rw-r--r--linux/drivers/media/common/tuners/tea5767.c3
-rw-r--r--linux/drivers/media/common/tuners/tuner-simple.c7
-rw-r--r--linux/drivers/media/common/tuners/tuner-xc2028.c28
-rw-r--r--linux/drivers/media/common/tuners/xc5000.c37
-rw-r--r--linux/drivers/media/common/tuners/xc5000_priv.h1
13 files changed, 94 insertions, 73 deletions
diff --git a/linux/drivers/media/common/tuners/Kconfig b/linux/drivers/media/common/tuners/Kconfig
index d62065404..850d5689b 100644
--- a/linux/drivers/media/common/tuners/Kconfig
+++ b/linux/drivers/media/common/tuners/Kconfig
@@ -21,6 +21,7 @@ config MEDIA_TUNER
tristate
default VIDEO_MEDIA && I2C
depends on VIDEO_MEDIA && I2C
+ select FW_LOADER if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE
@@ -33,6 +34,7 @@ config MEDIA_TUNER
menuconfig MEDIA_TUNER_CUSTOMIZE
bool "Customize analog and hybrid tuner modules to build"
depends on MEDIA_TUNER
+ default n
help
This allows the user to deselect tuner drivers unnecessary
for their hardware from the build. Use this option with care
diff --git a/linux/drivers/media/common/tuners/mt20xx.c b/linux/drivers/media/common/tuners/mt20xx.c
index d2c281aeb..9d9f1cf11 100644
--- a/linux/drivers/media/common/tuners/mt20xx.c
+++ b/linux/drivers/media/common/tuners/mt20xx.c
@@ -10,9 +10,6 @@
#include <linux/videodev.h>
#include "tuner-i2c.h"
#include "mt20xx.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "i2c-compat.h"
-#endif
static int debug;
module_param(debug, int, 0644);
diff --git a/linux/drivers/media/common/tuners/tda18271-common.c b/linux/drivers/media/common/tuners/tda18271-common.c
index 5bdab8181..a8fb96698 100644
--- a/linux/drivers/media/common/tuners/tda18271-common.c
+++ b/linux/drivers/media/common/tuners/tda18271-common.c
@@ -716,11 +716,19 @@ int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
unsigned char *regs = priv->tda18271_regs;
u8 val;
- tda18271_lookup_map(fe, RF_CAL, freq, &val);
+ int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val);
+ /* The TDA18271HD/C1 rf_cal map lookup is expected to go out of range
+ * for frequencies above 61.1 MHz. In these cases, the internal RF
+ * tracking filters calibration mechanism is used.
+ *
+ * There is no need to warn the user about this.
+ */
+ if (ret < 0)
+ goto fail;
regs[R_EB14] = val;
-
- return 0;
+fail:
+ return ret;
}
/*
diff --git a/linux/drivers/media/common/tuners/tda18271-fe.c b/linux/drivers/media/common/tuners/tda18271-fe.c
index f9e2957bb..68167b5ad 100644
--- a/linux/drivers/media/common/tuners/tda18271-fe.c
+++ b/linux/drivers/media/common/tuners/tda18271-fe.c
@@ -46,6 +46,21 @@ static inline int charge_pump_source(struct dvb_frontend *fe, int force)
TDA18271_MAIN_PLL, force);
}
+static inline void tda18271_set_if_notch(struct dvb_frontend *fe)
+{
+ struct tda18271_priv *priv = fe->tuner_priv;
+ unsigned char *regs = priv->tda18271_regs;
+
+ switch (priv->mode) {
+ case TDA18271_ANALOG:
+ regs[R_MPD] &= ~0x80; /* IF notch = 0 */
+ break;
+ case TDA18271_DIGITAL:
+ regs[R_MPD] |= 0x80; /* IF notch = 1 */
+ break;
+ }
+}
+
static int tda18271_channel_configuration(struct dvb_frontend *fe,
struct tda18271_std_map_item *map,
u32 freq, u32 bw)
@@ -61,25 +76,18 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
regs[R_EP3] &= ~0x1f; /* clear std bits */
regs[R_EP3] |= (map->agc_mode << 3) | map->std;
- /* set rfagc to high speed mode */
- regs[R_EP3] &= ~0x04;
+ if (priv->id == TDA18271HDC2) {
+ /* set rfagc to high speed mode */
+ regs[R_EP3] &= ~0x04;
+ }
/* set cal mode to normal */
regs[R_EP4] &= ~0x03;
- /* update IF output level & IF notch frequency */
+ /* update IF output level */
regs[R_EP4] &= ~0x1c; /* clear if level bits */
regs[R_EP4] |= (map->if_lvl << 2);
- switch (priv->mode) {
- case TDA18271_ANALOG:
- regs[R_MPD] &= ~0x80; /* IF notch = 0 */
- break;
- case TDA18271_DIGITAL:
- regs[R_MPD] |= 0x80; /* IF notch = 1 */
- break;
- }
-
/* update FM_RFn */
regs[R_EP4] &= ~0x80;
regs[R_EP4] |= map->fm_rfn << 7;
@@ -96,6 +104,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
/* disable Power Level Indicator */
regs[R_EP1] |= 0x40;
+ /* make sure thermometer is off */
+ regs[R_TM] &= ~0x10;
+
/* frequency dependent parameters */
tda18271_calc_ir_measure(fe, &freq);
@@ -136,6 +147,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
switch (priv->role) {
case TDA18271_MASTER:
tda18271_calc_main_pll(fe, N);
+ tda18271_set_if_notch(fe);
tda18271_write_regs(fe, R_MPD, 4);
break;
case TDA18271_SLAVE:
@@ -143,6 +155,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
tda18271_write_regs(fe, R_CPD, 4);
regs[R_MPD] = regs[R_CPD] & 0x7f;
+ tda18271_set_if_notch(fe);
tda18271_write_regs(fe, R_MPD, 1);
break;
}
@@ -161,12 +174,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
msleep(20);
- /* set rfagc to normal speed mode */
- if (map->fm_rfn)
- regs[R_EP3] &= ~0x04;
- else
- regs[R_EP3] |= 0x04;
- ret = tda18271_write_regs(fe, R_EP3, 1);
+ if (priv->id == TDA18271HDC2) {
+ /* set rfagc to normal speed mode */
+ if (map->fm_rfn)
+ regs[R_EP3] &= ~0x04;
+ else
+ regs[R_EP3] |= 0x04;
+ ret = tda18271_write_regs(fe, R_EP3, 1);
+ }
fail:
return ret;
}
@@ -508,7 +523,7 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe)
/* set cal mode to normal */
regs[R_EP4] &= ~0x03;
- /* update IF output level & IF notch frequency */
+ /* update IF output level */
regs[R_EP4] &= ~0x1c; /* clear if level bits */
ret = tda18271_write_regs(fe, R_EP3, 2);
diff --git a/linux/drivers/media/common/tuners/tda18271-maps.c b/linux/drivers/media/common/tuners/tda18271-maps.c
index 83e756196..ab14ceb9e 100644
--- a/linux/drivers/media/common/tuners/tda18271-maps.c
+++ b/linux/drivers/media/common/tuners/tda18271-maps.c
@@ -1,5 +1,5 @@
/*
- tda18271-tables.c - driver for the Philips / NXP TDA18271 silicon tuner
+ tda18271-maps.c - driver for the Philips / NXP TDA18271 silicon tuner
Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
diff --git a/linux/drivers/media/common/tuners/tda827x.c b/linux/drivers/media/common/tuners/tda827x.c
index 2d39f9be5..763b0dd95 100644
--- a/linux/drivers/media/common/tuners/tda827x.c
+++ b/linux/drivers/media/common/tuners/tda827x.c
@@ -419,13 +419,13 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
unsigned char buf[] = {0x22, 0x01};
int arg;
int gp_func;
- struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0,
- .buf = buf, .len = sizeof(buf) };
+ struct i2c_msg msg = { .flags = 0, .buf = buf, .len = sizeof(buf) };
if (NULL == priv->cfg) {
dprintk("tda827x_config not defined, cannot set LNA gain!\n");
return;
}
+ msg.addr = priv->cfg->switch_addr;
if (priv->cfg->config) {
if (high)
dprintk("setting LNA to high gain\n");
diff --git a/linux/drivers/media/common/tuners/tda8290.c b/linux/drivers/media/common/tuners/tda8290.c
index 9bda53be5..751845554 100644
--- a/linux/drivers/media/common/tuners/tda8290.c
+++ b/linux/drivers/media/common/tuners/tda8290.c
@@ -28,9 +28,6 @@
#include "tda8290.h"
#include "tda827x.h"
#include "tda18271.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "i2c-compat.h"
-#endif
static int debug;
module_param(debug, int, 0644);
diff --git a/linux/drivers/media/common/tuners/tda9887.c b/linux/drivers/media/common/tuners/tda9887.c
index e98de7d40..61a56026d 100644
--- a/linux/drivers/media/common/tuners/tda9887.c
+++ b/linux/drivers/media/common/tuners/tda9887.c
@@ -8,9 +8,6 @@
#include <linux/delay.h>
#include "compat.h"
#include <linux/videodev.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "i2c-compat.h"
-#endif
#include <media/v4l2-common.h>
#include <media/tuner.h>
#include "tuner-i2c.h"
@@ -438,17 +435,10 @@ static unsigned int port2 = UNSET;
static unsigned int qss = UNSET;
static unsigned int adjust = UNSET;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-MODULE_PARM(port1, "i");
-MODULE_PARM(port2, "i");
-MODULE_PARM(qss, "i");
-MODULE_PARM(adjust, "i");
-#else
module_param(port1, int, 0644);
module_param(port2, int, 0644);
module_param(qss, int, 0644);
module_param(adjust, int, 0644);
-#endif
static int tda9887_set_insmod(struct dvb_frontend *fe)
{
diff --git a/linux/drivers/media/common/tuners/tea5767.c b/linux/drivers/media/common/tuners/tea5767.c
index 5990a63ef..c56ff2dc1 100644
--- a/linux/drivers/media/common/tuners/tea5767.c
+++ b/linux/drivers/media/common/tuners/tea5767.c
@@ -16,9 +16,6 @@
#include <linux/videodev.h>
#include "tuner-i2c.h"
#include "tea5767.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "i2c-compat.h"
-#endif
static int debug;
module_param(debug, int, 0644);
diff --git a/linux/drivers/media/common/tuners/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c
index c9d70e4b2..a029cf8f5 100644
--- a/linux/drivers/media/common/tuners/tuner-simple.c
+++ b/linux/drivers/media/common/tuners/tuner-simple.c
@@ -11,9 +11,6 @@
#include <media/tuner.h>
#include <media/v4l2-common.h>
#include <media/tuner-types.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "i2c-compat.h"
-#endif
#include "tuner-i2c.h"
#include "tuner-simple.h"
@@ -25,11 +22,7 @@ MODULE_PARM_DESC(debug, "enable verbose debug messages");
static unsigned int simple_devcount;
static int offset;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-MODULE_PARM(offset, "i");
-#else
module_param(offset, int, 0664);
-#endif
MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");
static unsigned int atv_input[TUNER_SIMPLE_MAX] = \
diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.c b/linux/drivers/media/common/tuners/tuner-xc2028.c
index 6a9742552..9d3f397e3 100644
--- a/linux/drivers/media/common/tuners/tuner-xc2028.c
+++ b/linux/drivers/media/common/tuners/tuner-xc2028.c
@@ -20,10 +20,8 @@
#include <asm/semaphore.h>
#endif
#include "compat.h"
+#include <asm/unaligned.h>
#include "tuner-i2c.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
-#include "i2c-compat.h"
-#endif
#include "tuner-xc2028.h"
#include "tuner-xc2028-types.h"
@@ -307,10 +305,10 @@ static int load_all_firmwares(struct dvb_frontend *fe)
name[sizeof(name) - 1] = 0;
p += sizeof(name) - 1;
- priv->firm_version = le16_to_cpu(*(__u16 *) p);
+ priv->firm_version = get_unaligned_le16(p);
p += 2;
- n_array = le16_to_cpu(*(__u16 *) p);
+ n_array = get_unaligned_le16(p);
p += 2;
tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
@@ -339,26 +337,26 @@ static int load_all_firmwares(struct dvb_frontend *fe)
}
/* Checks if there's enough bytes to read */
- if (p + sizeof(type) + sizeof(id) + sizeof(size) > endp) {
- tuner_err("Firmware header is incomplete!\n");
- goto corrupt;
- }
+ if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
+ goto header;
- type = le32_to_cpu(*(__u32 *) p);
+ type = get_unaligned_le32(p);
p += sizeof(type);
- id = le64_to_cpu(*(v4l2_std_id *) p);
+ id = get_unaligned_le64(p);
p += sizeof(id);
if (type & HAS_IF) {
- int_freq = le16_to_cpu(*(__u16 *) p);
+ int_freq = get_unaligned_le16(p);
p += sizeof(int_freq);
+ if (endp - p < sizeof(size))
+ goto header;
}
- size = le32_to_cpu(*(__u32 *) p);
+ size = get_unaligned_le32(p);
p += sizeof(size);
- if ((!size) || (size + p > endp)) {
+ if (!size || size > endp - p) {
tuner_err("Firmware type ");
dump_firm_type(type);
printk("(%x), id %llx is corrupted "
@@ -397,6 +395,8 @@ static int load_all_firmwares(struct dvb_frontend *fe)
goto done;
+header:
+ tuner_err("Firmware header is incomplete!\n");
corrupt:
rc = -EINVAL;
tuner_err("Error: firmware file is corrupted!\n");
diff --git a/linux/drivers/media/common/tuners/xc5000.c b/linux/drivers/media/common/tuners/xc5000.c
index b35640824..63b4dba44 100644
--- a/linux/drivers/media/common/tuners/xc5000.c
+++ b/linux/drivers/media/common/tuners/xc5000.c
@@ -36,6 +36,10 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+static int xc5000_load_fw_on_attach;
+module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644);
+MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
+
#define dprintk(level,fmt, arg...) if (debug >= level) \
printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
@@ -177,6 +181,7 @@ static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
{"FM Radio-INPUT1", 0x0208, 0x9002}
};
+static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len);
static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len);
static void xc5000_TunerReset(struct dvb_frontend *fe);
@@ -352,7 +357,7 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
static int xc_shutdown(struct xc5000_priv *priv)
{
- return 0;
+ return XC_RESULT_SUCCESS;
/* Fixme: cannot bring tuner back alive once shutdown
* without reloading the driver modules.
* return xc_write_reg(priv, XREG_POWER_DOWN, 0);
@@ -704,6 +709,25 @@ static int xc5000_set_params(struct dvb_frontend *fe,
return 0;
}
+static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
+{
+ struct xc5000_priv *priv = fe->tuner_priv;
+ int ret;
+ u16 id;
+
+ ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id);
+ if (ret == XC_RESULT_SUCCESS) {
+ if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
+ ret = XC_RESULT_RESET_FAILURE;
+ else
+ ret = XC_RESULT_SUCCESS;
+ }
+
+ dprintk(1, "%s() returns %s id = 0x%x\n", __func__,
+ ret == XC_RESULT_SUCCESS ? "True" : "False", id);
+ return ret;
+}
+
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
static int xc5000_set_analog_params(struct dvb_frontend *fe,
@@ -712,7 +736,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
struct xc5000_priv *priv = fe->tuner_priv;
int ret;
- if(priv->fwloaded == 0)
+ if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
xc_load_fw_and_init_tuner(fe);
dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
@@ -827,11 +851,10 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
struct xc5000_priv *priv = fe->tuner_priv;
int ret = 0;
- if (priv->fwloaded == 0) {
+ if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
ret = xc5000_fwupload(fe);
if (ret != XC_RESULT_SUCCESS)
return ret;
- priv->fwloaded = 1;
}
/* Start the tuner self-calibration process */
@@ -871,7 +894,6 @@ static int xc5000_sleep(struct dvb_frontend *fe)
return -EREMOTEIO;
}
else {
- /* priv->fwloaded = 0; */
return XC_RESULT_SUCCESS;
}
}
@@ -952,7 +974,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
cfg->i2c_address);
printk(KERN_INFO
"xc5000: Firmware has been loaded previously\n");
- priv->fwloaded = 1;
break;
case XC_PRODUCT_ID_FW_NOT_LOADED:
printk(KERN_INFO
@@ -960,7 +981,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
cfg->i2c_address);
printk(KERN_INFO
"xc5000: Firmware has not been loaded previously\n");
- priv->fwloaded = 0;
break;
default:
printk(KERN_ERR
@@ -975,6 +995,9 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
fe->tuner_priv = priv;
+ if (xc5000_load_fw_on_attach)
+ xc5000_init(fe);
+
return fe;
}
EXPORT_SYMBOL(xc5000_attach);
diff --git a/linux/drivers/media/common/tuners/xc5000_priv.h b/linux/drivers/media/common/tuners/xc5000_priv.h
index ecebfe474..a72a9887f 100644
--- a/linux/drivers/media/common/tuners/xc5000_priv.h
+++ b/linux/drivers/media/common/tuners/xc5000_priv.h
@@ -30,7 +30,6 @@ struct xc5000_priv {
u32 bandwidth;
u8 video_standard;
u8 rf_mode;
- u8 fwloaded;
void *devptr;
};