]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/media/dvb/frontends/tda1004x.c
V4L/DVB (5369): Fixed 1 byte too short buffer in tda827x.c
[karo-tx-linux.git] / drivers / media / dvb / frontends / tda1004x.c
index 11e0dca9a2d7307de9e1a6648eedd4311844f9f1..f4882457d0213e50d2cc8fee52e6e9ecc42d906f 100644 (file)
 #include "dvb_frontend.h"
 #include "tda1004x.h"
 
-enum tda1004x_demod {
-       TDA1004X_DEMOD_TDA10045,
-       TDA1004X_DEMOD_TDA10046,
-};
-
-struct tda1004x_state {
-       struct i2c_adapter* i2c;
-       const struct tda1004x_config* config;
-       struct dvb_frontend frontend;
-
-       /* private demod data */
-       enum tda1004x_demod demod_type;
-};
-
 static int debug;
 #define dprintk(args...) \
        do { \
@@ -507,12 +493,25 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
                tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80);
        }
        tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
+       /* set GPIO 1 and 3 */
+       if (state->config->gpio_config != TDA10046_GPTRI) {
+               tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0x33);
+               tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, state->config->gpio_config &0x0f);
+       }
        /* let the clocks recover from sleep */
-       msleep(5);
+       msleep(10);
 
        /* The PLLs need to be reprogrammed after sleep */
        tda10046_init_plls(fe);
+       tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0);
 
+       /* don't re-upload unless necessary */
+       if (tda1004x_check_upload_ok(state) == 0)
+               return 0;
+
+       printk(KERN_INFO "tda1004x: trying to boot from eeprom\n");
+       tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4);
+       msleep(300);
        /* don't re-upload unless necessary */
        if (tda1004x_check_upload_ok(state) == 0)
                return 0;
@@ -522,20 +521,23 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
                printk(KERN_INFO "tda1004x: waiting for firmware upload...\n");
                ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE);
                if (ret) {
-                       printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
-                       return ret;
+                       /* remain compatible to old bug: try to load with tda10045 image name */
+                       ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
+                       if (ret) {
+                               printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
+                               return ret;
+                       } else {
+                               printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n",
+                                                 TDA10046_DEFAULT_FIRMWARE);
+                       }
                }
-               tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST
-               ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN);
-               release_firmware(fw);
-               if (ret)
-                       return ret;
        } else {
-               /* boot from firmware eeprom */
-               printk(KERN_INFO "tda1004x: booting from eeprom\n");
-               tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4);
-               msleep(300);
+               printk(KERN_ERR "tda1004x: no request function defined, can't upload from file\n");
+               return -EIO;
        }
+       tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST
+       ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN);
+       release_firmware(fw);
        return tda1004x_check_upload_ok(state);
 }
 
@@ -579,7 +581,7 @@ static int tda1004x_decode_fec(int tdafec)
        return -1;
 }
 
-int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len)
+static int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len)
 {
        struct tda1004x_state* state = fe->demodulator_priv;
 
@@ -638,31 +640,25 @@ static int tda10046_init(struct dvb_frontend* fe)
        switch (state->config->agc_config) {
        case TDA10046_AGC_DEFAULT:
                tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup
-               tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
+               tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60);  // set AGC polarities
                break;
        case TDA10046_AGC_IFO_AUTO_NEG:
                tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
-               tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
+               tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60);  // set AGC polarities
                break;
        case TDA10046_AGC_IFO_AUTO_POS:
                tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
-               tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities
+               tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x00);  // set AGC polarities
                break;
        case TDA10046_AGC_TDA827X:
                tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02);   // AGC setup
                tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70);    // AGC Threshold
                tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
-               tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities
-               break;
-       case TDA10046_AGC_TDA827X_GPL:
-               tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02);   // AGC setup
-               tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70);    // AGC Threshold
-               tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
-               tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
+               tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60);  // set AGC polarities
                break;
        }
        tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
-       tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
+       tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x79); // Turn IF AGC output on
        tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0);    // }
        tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values
        tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0);     // }
@@ -699,7 +695,8 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
        // set frequency
        if (fe->ops.tuner_ops.set_params) {
                fe->ops.tuner_ops.set_params(fe, fe_params);
-               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
        // Hardcoded to use auto as much as possible on the TDA10045 as it
@@ -1159,6 +1156,7 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
 static int tda1004x_sleep(struct dvb_frontend* fe)
 {
        struct tda1004x_state* state = fe->demodulator_priv;
+       int gpio_conf;
 
        switch (state->demod_type) {
        case TDA1004X_DEMOD_TDA10045:
@@ -1168,6 +1166,13 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
        case TDA1004X_DEMOD_TDA10046:
                /* set outputs to tristate */
                tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff);
+               /* invert GPIO 1 and 3 if desired*/
+               gpio_conf = state->config->gpio_config;
+               if (gpio_conf >= TDA10046_GP00_I)
+                       tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f,
+                                                       (gpio_conf & 0x0f) ^ 0x0a);
+
+               tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0xc0);
                tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
                break;
        }