]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/tuner-xc2028.c
V4L/DVB (7538): Adds selectable adapter numbers as per module option
[linux-2.6-omap-h63xx.git] / drivers / media / video / tuner-xc2028.c
index f191f6a4807068869ef360d053325d08a7e3f14a..62b5de231e0dfa98435e04cb0753a5e0b415c17c 100644 (file)
@@ -23,8 +23,6 @@
 #include "dvb_frontend.h"
 
 
-#define PREFIX "xc2028"
-
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
@@ -43,6 +41,11 @@ MODULE_PARM_DESC(audio_std,
        "NICAM/A\n"
        "NICAM/B\n");
 
+static char firmware_name[FIRMWARE_NAME_MAX];
+module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
+MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
+                               "default firmware name\n");
+
 static LIST_HEAD(xc2028_list);
 static DEFINE_MUTEX(xc2028_list_mutex);
 
@@ -132,7 +135,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
        unsigned char buf[2];
        unsigned char ibuf[2];
 
-       tuner_dbg("%s %04x called\n", __FUNCTION__, reg);
+       tuner_dbg("%s %04x called\n", __func__, reg);
 
        buf[0] = reg >> 8;
        buf[1] = (unsigned char) reg;
@@ -145,7 +148,7 @@ static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
 }
 
 #define dump_firm_type(t)      dump_firm_type_and_int_freq(t, 0)
-void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
+static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
 {
         if (type & BASE)
                printk("BASE ");
@@ -255,19 +258,24 @@ static int load_all_firmwares(struct dvb_frontend *fe)
        int                   rc = 0;
        int                   n, n_array;
        char                  name[33];
+       char                  *fname;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
+
+       if (!firmware_name[0])
+               fname = priv->ctrl.fname;
+       else
+               fname = firmware_name;
 
-       tuner_dbg("Reading firmware %s\n", priv->ctrl.fname);
-       rc = request_firmware(&fw, priv->ctrl.fname,
-                             &priv->i2c_props.adap->dev);
+       tuner_dbg("Reading firmware %s\n", fname);
+       rc = request_firmware(&fw, fname, &priv->i2c_props.adap->dev);
        if (rc < 0) {
                if (rc == -ENOENT)
                        tuner_err("Error: firmware %s not found.\n",
-                                  priv->ctrl.fname);
+                                  fname);
                else
                        tuner_err("Error %d while requesting firmware %s \n",
-                                  rc, priv->ctrl.fname);
+                                  rc, fname);
 
                return rc;
        }
@@ -276,7 +284,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
 
        if (fw->size < sizeof(name) - 1 + 2 + 2) {
                tuner_err("Error: firmware file %s has invalid size!\n",
-                         priv->ctrl.fname);
+                         fname);
                goto corrupt;
        }
 
@@ -291,7 +299,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, priv->ctrl.fname, name,
+                  n_array, fname, name,
                   priv->firm_version >> 8, priv->firm_version & 0xff);
 
        priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
@@ -397,7 +405,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
        int                 i, best_i = -1, best_nr_matches = 0;
        unsigned int        ign_firm_type_mask = 0;
 
-       tuner_dbg("%s called, want type=", __FUNCTION__);
+       tuner_dbg("%s called, want type=", __func__);
        if (debug) {
                dump_firm_type(type);
                printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
@@ -483,7 +491,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
        int                pos, rc;
        unsigned char      *p, *endp, buf[priv->ctrl.max_len];
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        pos = seek_firmware(fe, type, id);
        if (pos < 0)
@@ -586,7 +594,7 @@ static int load_scode(struct dvb_frontend *fe, unsigned int type,
        int                pos, rc;
        unsigned char      *p;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (!int_freq) {
                pos = seek_firmware(fe, type, id);
@@ -650,7 +658,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
        u16                        version, hwmodel;
        v4l2_std_id                std0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (!priv->firm) {
                if (!priv->ctrl.fname) {
@@ -754,6 +762,9 @@ skip_std_specific:
                goto check_device;
        }
 
+       if (new_fw.type & FM)
+               goto check_device;
+
        /* Load SCODE firmware, if exists */
        tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr);
 
@@ -821,7 +832,7 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
        u16                 frq_lock, signal = 0;
        int                 rc;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&priv->lock);
 
@@ -858,7 +869,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
        unsigned char      buf[4];
        u32                div, offset = 0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&priv->lock);
 
@@ -903,9 +914,11 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
        if (rc < 0)
                goto ret;
 
-       rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
-       if (rc < 0)
-               goto ret;
+       /* Return code shouldn't be checked.
+          The reset CLK is needed only with tm6000.
+          Driver should work fine even if this fails.
+        */
+       priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
 
        msleep(10);
 
@@ -939,7 +952,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe,
        struct xc2028_data *priv = fe->tuner_priv;
        unsigned int       type=0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (p->mode == V4L2_TUNER_RADIO) {
                type |= FM;
@@ -972,7 +985,7 @@ static int xc2028_set_params(struct dvb_frontend *fe,
        fe_bandwidth_t     bw = BANDWIDTH_8_MHZ;
        u16                demod = 0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        if (priv->ctrl.d2633)
                type |= D2633;
@@ -1042,7 +1055,7 @@ static int xc2028_sleep(struct dvb_frontend *fe)
        struct xc2028_data *priv = fe->tuner_priv;
        int rc = 0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&priv->lock);
 
@@ -1063,7 +1076,7 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
 {
        struct xc2028_data *priv = fe->tuner_priv;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&xc2028_list_mutex);
 
@@ -1088,7 +1101,7 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
        struct xc2028_data *priv = fe->tuner_priv;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        *frequency = priv->frequency;
 
@@ -1101,7 +1114,7 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
        struct xc2028_ctrl *p    = priv_cfg;
        int                 rc   = 0;
 
-       tuner_dbg("%s called\n", __FUNCTION__);
+       tuner_dbg("%s called\n", __func__);
 
        mutex_lock(&priv->lock);
 
@@ -1150,23 +1163,29 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
        void               *video_dev;
 
        if (debug)
-               printk(KERN_DEBUG PREFIX ": Xcv2028/3028 init called!\n");
+               printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
 
-       if (NULL == cfg || NULL == cfg->video_dev)
+       if (NULL == cfg)
                return NULL;
 
        if (!fe) {
-               printk(KERN_ERR PREFIX ": No frontend!\n");
+               printk(KERN_ERR "xc2028: No frontend!\n");
                return NULL;
        }
 
-       video_dev = cfg->video_dev;
+       video_dev = cfg->i2c_adap->algo_data;
+
+       if (debug)
+               printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
 
        mutex_lock(&xc2028_list_mutex);
 
        list_for_each_entry(priv, &xc2028_list, xc2028_list) {
-               if (priv->video_dev == cfg->video_dev) {
+               if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
                        video_dev = NULL;
+                       if (debug)
+                               printk(KERN_DEBUG "xc2028: reusing device\n");
+
                        break;
                }
        }
@@ -1180,6 +1199,8 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
 
                priv->i2c_props.addr = cfg->i2c_addr;
                priv->i2c_props.adap = cfg->i2c_adap;
+               priv->i2c_props.name = "xc2028";
+
                priv->video_dev = video_dev;
                priv->tuner_callback = cfg->callback;
                priv->ctrl.max_len = 13;
@@ -1192,6 +1213,9 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
        fe->tuner_priv = priv;
        priv->count++;
 
+       if (debug)
+               printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count);
+
        memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
               sizeof(xc2028_dvb_tuner_ops));