summaryrefslogtreecommitdiffstats
path: root/drivers/media/common
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-09-07 15:07:55 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-09-07 15:07:55 -0400
commitfac805f8c198092de9a2842efd7f5022e2937b18 (patch)
tree7557809c373f97a343c427d8fded0696060394ce /drivers/media/common
parent2461c7d60f9f3821274e4acf9019cba8b82c94b5 (diff)
parentf10723841e624c0726c70356b31d91befed01dd6 (diff)
downloadlinux-fac805f8c198092de9a2842efd7f5022e2937b18.tar.gz
linux-fac805f8c198092de9a2842efd7f5022e2937b18.tar.bz2
linux-fac805f8c198092de9a2842efd7f5022e2937b18.zip
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Diffstat (limited to 'drivers/media/common')
-rw-r--r--drivers/media/common/tuners/Kconfig64
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.c249
-rw-r--r--drivers/media/common/tuners/xc5000.c14
3 files changed, 236 insertions, 91 deletions
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
index bbf4945149a9..94c6ff7a5da3 100644
--- a/drivers/media/common/tuners/Kconfig
+++ b/drivers/media/common/tuners/Kconfig
@@ -1,7 +1,8 @@
config MEDIA_ATTACH
bool "Load and attach frontend and tuner driver modules as needed"
- depends on VIDEO_MEDIA
+ depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
depends on MODULES
+ default y if !EXPERT
help
Remove the static dependency of DVB card drivers on all
frontend modules for all possible card variants. Instead,
@@ -19,15 +20,15 @@ config MEDIA_ATTACH
config MEDIA_TUNER
tristate
- default VIDEO_MEDIA && I2C
- depends on VIDEO_MEDIA && I2C
+ depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT) && I2C
+ default y
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
- select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && EXPERIMENTAL
- select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE
+ select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT && EXPERIMENTAL
+ select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
@@ -47,10 +48,11 @@ config MEDIA_TUNER_CUSTOMISE
menu "Customize TV tuners"
visible if MEDIA_TUNER_CUSTOMISE
+ depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
config MEDIA_TUNER_SIMPLE
tristate "Simple tuner support"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
select MEDIA_TUNER_TDA9887
default m if MEDIA_TUNER_CUSTOMISE
help
@@ -58,7 +60,7 @@ config MEDIA_TUNER_SIMPLE
config MEDIA_TUNER_TDA8290
tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
select MEDIA_TUNER_TDA827X
select MEDIA_TUNER_TDA18271
default m if MEDIA_TUNER_CUSTOMISE
@@ -67,21 +69,21 @@ config MEDIA_TUNER_TDA8290
config MEDIA_TUNER_TDA827X
tristate "Philips TDA827X silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A DVB-T silicon tuner module. Say Y when you want to support this tuner.
config MEDIA_TUNER_TDA18271
tristate "NXP TDA18271 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A silicon tuner module. Say Y when you want to support this tuner.
config MEDIA_TUNER_TDA9887
tristate "TDA 9885/6/7 analog IF demodulator"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
Say Y here to include support for Philips TDA9885/6/7
@@ -89,7 +91,7 @@ config MEDIA_TUNER_TDA9887
config MEDIA_TUNER_TEA5761
tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
depends on EXPERIMENTAL
default m if MEDIA_TUNER_CUSTOMISE
help
@@ -97,63 +99,63 @@ config MEDIA_TUNER_TEA5761
config MEDIA_TUNER_TEA5767
tristate "TEA 5767 radio tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
Say Y here to include support for the Philips TEA5767 radio tuner.
config MEDIA_TUNER_MT20XX
tristate "Microtune 2032 / 2050 tuners"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
Say Y here to include support for the MT2032 / MT2050 tuner.
config MEDIA_TUNER_MT2060
tristate "Microtune MT2060 silicon IF tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A driver for the silicon IF tuner MT2060 from Microtune.
config MEDIA_TUNER_MT2063
tristate "Microtune MT2063 silicon IF tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A driver for the silicon IF tuner MT2063 from Microtune.
config MEDIA_TUNER_MT2266
tristate "Microtune MT2266 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A driver for the silicon baseband tuner MT2266 from Microtune.
config MEDIA_TUNER_MT2131
tristate "Microtune MT2131 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A driver for the silicon baseband tuner MT2131 from Microtune.
config MEDIA_TUNER_QT1010
tristate "Quantek QT1010 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A driver for the silicon tuner QT1010 from Quantek.
config MEDIA_TUNER_XC2028
tristate "XCeive xc2028/xc3028 tuners"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
Say Y here to include support for the xc2028/xc3028 tuners.
config MEDIA_TUNER_XC5000
tristate "Xceive XC5000 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A driver for the silicon tuner XC5000 from Xceive.
@@ -162,7 +164,7 @@ config MEDIA_TUNER_XC5000
config MEDIA_TUNER_XC4000
tristate "Xceive XC4000 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A driver for the silicon tuner XC4000 from Xceive.
@@ -171,70 +173,70 @@ config MEDIA_TUNER_XC4000
config MEDIA_TUNER_MXL5005S
tristate "MaxLinear MSL5005S silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A driver for the silicon tuner MXL5005S from MaxLinear.
config MEDIA_TUNER_MXL5007T
tristate "MaxLinear MxL5007T silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A driver for the silicon tuner MxL5007T from MaxLinear.
config MEDIA_TUNER_MC44S803
tristate "Freescale MC44S803 Low Power CMOS Broadband tuners"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
Say Y here to support the Freescale MC44S803 based tuners
config MEDIA_TUNER_MAX2165
tristate "Maxim MAX2165 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
A driver for the silicon tuner MAX2165 from Maxim.
config MEDIA_TUNER_TDA18218
tristate "NXP TDA18218 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
NXP TDA18218 silicon tuner driver.
config MEDIA_TUNER_FC0011
tristate "Fitipower FC0011 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
Fitipower FC0011 silicon tuner driver.
config MEDIA_TUNER_FC0012
tristate "Fitipower FC0012 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
Fitipower FC0012 silicon tuner driver.
config MEDIA_TUNER_FC0013
tristate "Fitipower FC0013 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
Fitipower FC0013 silicon tuner driver.
config MEDIA_TUNER_TDA18212
tristate "NXP TDA18212 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
NXP TDA18212 silicon tuner driver.
config MEDIA_TUNER_TUA9001
tristate "Infineon TUA 9001 silicon tuner"
- depends on VIDEO_MEDIA && I2C
+ depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
Infineon TUA 9001 silicon tuner driver.
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
index b5ee3ebfcfca..ea0550eafe7d 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -90,11 +90,22 @@ struct firmware_properties {
int scode_nr;
};
+enum xc2028_state {
+ XC2028_NO_FIRMWARE = 0,
+ XC2028_WAITING_FIRMWARE,
+ XC2028_ACTIVE,
+ XC2028_SLEEP,
+ XC2028_NODEV,
+};
+
struct xc2028_data {
struct list_head hybrid_tuner_instance_list;
struct tuner_i2c_props i2c_props;
__u32 frequency;
+ enum xc2028_state state;
+ const char *fname;
+
struct firmware_description *firm;
int firm_size;
__u16 firm_version;
@@ -255,6 +266,21 @@ static v4l2_std_id parse_audio_std_option(void)
return 0;
}
+static int check_device_status(struct xc2028_data *priv)
+{
+ switch (priv->state) {
+ case XC2028_NO_FIRMWARE:
+ case XC2028_WAITING_FIRMWARE:
+ return -EAGAIN;
+ case XC2028_ACTIVE:
+ case XC2028_SLEEP:
+ return 0;
+ case XC2028_NODEV:
+ return -ENODEV;
+ }
+ return 0;
+}
+
static void free_firmware(struct xc2028_data *priv)
{
int i;
@@ -270,45 +296,28 @@ static void free_firmware(struct xc2028_data *priv)
priv->firm = NULL;
priv->firm_size = 0;
+ priv->state = XC2028_NO_FIRMWARE;
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
}
-static int load_all_firmwares(struct dvb_frontend *fe)
+static int load_all_firmwares(struct dvb_frontend *fe,
+ const struct firmware *fw)
{
struct xc2028_data *priv = fe->tuner_priv;
- const struct firmware *fw = NULL;
const unsigned char *p, *endp;
int rc = 0;
int n, n_array;
char name[33];
- char *fname;
tuner_dbg("%s called\n", __func__);
- if (!firmware_name[0])
- fname = priv->ctrl.fname;
- else
- fname = firmware_name;
-
- tuner_dbg("Reading firmware %s\n", fname);
- rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
- if (rc < 0) {
- if (rc == -ENOENT)
- tuner_err("Error: firmware %s not found.\n",
- fname);
- else
- tuner_err("Error %d while requesting firmware %s \n",
- rc, fname);
-
- return rc;
- }
p = fw->data;
endp = p + fw->size;
if (fw->size < sizeof(name) - 1 + 2 + 2) {
tuner_err("Error: firmware file %s has invalid size!\n",
- fname);
+ priv->fname);
goto corrupt;
}
@@ -323,7 +332,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
p += 2;
tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
- n_array, fname, name,
+ n_array, priv->fname, name,
priv->firm_version >> 8, priv->firm_version & 0xff);
priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
@@ -417,9 +426,10 @@ err:
free_firmware(priv);
done:
- release_firmware(fw);
if (rc == 0)
tuner_dbg("Firmware files loaded.\n");
+ else
+ priv->state = XC2028_NODEV;
return rc;
}
@@ -707,22 +717,15 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
{
struct xc2028_data *priv = fe->tuner_priv;
struct firmware_properties new_fw;
- int rc = 0, retry_count = 0;
+ int rc, retry_count = 0;
u16 version, hwmodel;
v4l2_std_id std0;
tuner_dbg("%s called\n", __func__);
- if (!priv->firm) {
- if (!priv->ctrl.fname) {
- tuner_info("xc2028/3028 firmware name not set!\n");
- return -EINVAL;
- }
-
- rc = load_all_firmwares(fe);
- if (rc < 0)
- return rc;
- }
+ rc = check_device_status(priv);
+ if (rc < 0)
+ return rc;
if (priv->ctrl.mts && !(type & FM))
type |= MTS;
@@ -749,9 +752,13 @@ retry:
printk("scode_nr %d\n", new_fw.scode_nr);
}
- /* No need to reload base firmware if it matches */
- if (((BASE | new_fw.type) & BASE_TYPES) ==
- (priv->cur_fw.type & BASE_TYPES)) {
+ /*
+ * No need to reload base firmware if it matches and if the tuner
+ * is not at sleep mode
+ */
+ if ((priv->state == XC2028_ACTIVE) &&
+ (((BASE | new_fw.type) & BASE_TYPES) ==
+ (priv->cur_fw.type & BASE_TYPES))) {
tuner_dbg("BASE firmware not changed.\n");
goto skip_base;
}
@@ -872,10 +879,13 @@ read_not_reliable:
* 2. Tell whether BASE firmware was just changed the next time through.
*/
priv->cur_fw.type |= BASE;
+ priv->state = XC2028_ACTIVE;
return 0;
fail:
+ priv->state = XC2028_SLEEP;
+
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
if (retry_count < 8) {
msleep(50);
@@ -893,28 +903,39 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
{
struct xc2028_data *priv = fe->tuner_priv;
u16 frq_lock, signal = 0;
- int rc;
+ int rc, i;
tuner_dbg("%s called\n", __func__);
+ rc = check_device_status(priv);
+ if (rc < 0)
+ return rc;
+
mutex_lock(&priv->lock);
/* Sync Lock Indicator */
- rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
- if (rc < 0)
- goto ret;
+ for (i = 0; i < 3; i++) {
+ rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
+ if (rc < 0)
+ goto ret;
- /* Frequency is locked */
- if (frq_lock == 1)
- signal = 1 << 11;
+ if (frq_lock)
+ break;
+ msleep(6);
+ }
+
+ /* Frequency didn't lock */
+ if (frq_lock == 2)
+ goto ret;
/* Get SNR of the video signal */
rc = xc2028_get_reg(priv, XREG_SNR, &signal);
if (rc < 0)
goto ret;
- /* Use both frq_lock and signal to generate the result */
- signal = signal || ((signal & 0x07) << 12);
+ /* Signal level is 3 bits only */
+
+ signal = ((1 << 12) - 1) | ((signal & 0x07) << 12);
ret:
mutex_unlock(&priv->lock);
@@ -926,6 +947,49 @@ ret:
return rc;
}
+static int xc2028_get_afc(struct dvb_frontend *fe, s32 *afc)
+{
+ struct xc2028_data *priv = fe->tuner_priv;
+ int i, rc;
+ u16 frq_lock = 0;
+ s16 afc_reg = 0;
+
+ rc = check_device_status(priv);
+ if (rc < 0)
+ return rc;
+
+ mutex_lock(&priv->lock);
+
+ /* Sync Lock Indicator */
+ for (i = 0; i < 3; i++) {
+ rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
+ if (rc < 0)
+ goto ret;
+
+ if (frq_lock)
+ break;
+ msleep(6);
+ }
+
+ /* Frequency didn't lock */
+ if (frq_lock == 2)
+ goto ret;
+
+ /* Get AFC */
+ rc = xc2028_get_reg(priv, XREG_FREQ_ERROR, &afc_reg);
+ if (rc < 0)
+ goto ret;
+
+ *afc = afc_reg * 15625; /* Hz */
+
+ tuner_dbg("AFC is %d Hz\n", *afc);
+
+ret:
+ mutex_unlock(&priv->lock);
+
+ return rc;
+}
+
#define DIV 15625
static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
@@ -1111,11 +1175,16 @@ static int xc2028_set_params(struct dvb_frontend *fe)
u32 delsys = c->delivery_system;
u32 bw = c->bandwidth_hz;
struct xc2028_data *priv = fe->tuner_priv;
- unsigned int type=0;
+ int rc;
+ unsigned int type = 0;
u16 demod = 0;
tuner_dbg("%s called\n", __func__);
+ rc = check_device_status(priv);
+ if (rc < 0)
+ return rc;
+
switch (delsys) {
case SYS_DVBT:
case SYS_DVBT2:
@@ -1201,7 +1270,11 @@ static int xc2028_set_params(struct dvb_frontend *fe)
static int xc2028_sleep(struct dvb_frontend *fe)
{
struct xc2028_data *priv = fe->tuner_priv;
- int rc = 0;
+ int rc;
+
+ rc = check_device_status(priv);
+ if (rc < 0)
+ return rc;
/* Avoid firmware reload on slow devices or if PM disabled */
if (no_poweroff || priv->ctrl.disable_power_mgmt)
@@ -1220,7 +1293,7 @@ static int xc2028_sleep(struct dvb_frontend *fe)
else
rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00});
- priv->cur_fw.type = 0; /* need firmware reload */
+ priv->state = XC2028_SLEEP;
mutex_unlock(&priv->lock);
@@ -1237,8 +1310,9 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
/* only perform final cleanup if this is the last instance */
if (hybrid_tuner_report_instance_count(priv) == 1) {
- kfree(priv->ctrl.fname);
free_firmware(priv);
+ kfree(priv->ctrl.fname);
+ priv->ctrl.fname = NULL;
}
if (priv)
@@ -1254,14 +1328,42 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct xc2028_data *priv = fe->tuner_priv;
+ int rc;
tuner_dbg("%s called\n", __func__);
+ rc = check_device_status(priv);
+ if (rc < 0)
+ return rc;
+
*frequency = priv->frequency;
return 0;
}
+static void load_firmware_cb(const struct firmware *fw,
+ void *context)
+{
+ struct dvb_frontend *fe = context;
+ struct xc2028_data *priv = fe->tuner_priv;
+ int rc;
+
+ tuner_dbg("request_firmware_nowait(): %s\n", fw ? "OK" : "error");
+ if (!fw) {
+ tuner_err("Could not load firmware %s.\n", priv->fname);
+ priv->state = XC2028_NODEV;
+ return;
+ }
+
+ rc = load_all_firmwares(fe, fw);
+
+ release_firmware(fw);
+
+ if (rc < 0)
+ return;
+ priv->state = XC2028_SLEEP;
+}
+
static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
{
struct xc2028_data *priv = fe->tuner_priv;
@@ -1272,21 +1374,49 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
mutex_lock(&priv->lock);
+ /*
+ * Copy the config data.
+ * For the firmware name, keep a local copy of the string,
+ * in order to avoid troubles during device release.
+ */
+ if (priv->ctrl.fname)
+ kfree(priv->ctrl.fname);
memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
- if (priv->ctrl.max_len < 9)
- priv->ctrl.max_len = 13;
-
if (p->fname) {
- if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) {
- kfree(priv->ctrl.fname);
- free_firmware(priv);
- }
-
priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
if (priv->ctrl.fname == NULL)
rc = -ENOMEM;
}
+ /*
+ * If firmware name changed, frees firmware. As free_firmware will
+ * reset the status to NO_FIRMWARE, this forces a new request_firmware
+ */
+ if (!firmware_name[0] && p->fname &&
+ priv->fname && strcmp(p->fname, priv->fname))
+ free_firmware(priv);
+
+ if (priv->ctrl.max_len < 9)
+ priv->ctrl.max_len = 13;
+
+ if (priv->state == XC2028_NO_FIRMWARE) {
+ if (!firmware_name[0])
+ priv->fname = priv->ctrl.fname;
+ else
+ priv->fname = firmware_name;
+
+ rc = request_firmware_nowait(THIS_MODULE, 1,
+ priv->fname,
+ priv->i2c_props.adap->dev.parent,
+ GFP_KERNEL,
+ fe, load_firmware_cb);
+ if (rc < 0) {
+ tuner_err("Failed to request firmware %s\n",
+ priv->fname);
+ priv->state = XC2028_NODEV;
+ }
+ priv->state = XC2028_WAITING_FIRMWARE;
+ }
mutex_unlock(&priv->lock);
return rc;
@@ -1305,6 +1435,7 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
.release = xc2028_dvb_release,
.get_frequency = xc2028_get_frequency,
.get_rf_strength = xc2028_signal,
+ .get_afc = xc2028_get_afc,
.set_params = xc2028_set_params,
.sleep = xc2028_sleep,
};
@@ -1375,3 +1506,5 @@ MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver");
MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE);
+MODULE_FIRMWARE(XC3028L_DEFAULT_FIRMWARE);
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index dcca42ca57be..362a8d7c9738 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -210,13 +210,15 @@ struct xc5000_fw_cfg {
u16 size;
};
+#define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw"
static const struct xc5000_fw_cfg xc5000a_1_6_114 = {
- .name = "dvb-fe-xc5000-1.6.114.fw",
+ .name = XC5000A_FIRMWARE,
.size = 12401,
};
+#define XC5000C_FIRMWARE "dvb-fe-xc5000c-41.024.5.fw"
static const struct xc5000_fw_cfg xc5000c_41_024_5 = {
- .name = "dvb-fe-xc5000c-41.024.5.fw",
+ .name = XC5000C_FIRMWARE,
.size = 16497,
};
@@ -717,6 +719,12 @@ static int xc5000_set_params(struct dvb_frontend *fe)
priv->freq_hz = freq - 1750000;
priv->video_standard = DTV6;
break;
+ case SYS_ISDBT:
+ /* All ISDB-T are currently for 6 MHz bw */
+ if (!bw)
+ bw = 6000000;
+ /* fall to OFDM handling */
+ case SYS_DMBTH:
case SYS_DVBT:
case SYS_DVBT2:
dprintk(1, "%s() OFDM\n", __func__);
@@ -1253,3 +1261,5 @@ EXPORT_SYMBOL(xc5000_attach);
MODULE_AUTHOR("Steven Toth");
MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(XC5000A_FIRMWARE);
+MODULE_FIRMWARE(XC5000C_FIRMWARE);