]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/dvb/frontends/lgdt330x.c
V4L/DVB (4176): Bug-fix: Fix memory overflow
[linux-2.6-omap-h63xx.git] / drivers / media / dvb / frontends / lgdt330x.c
index 7852b83b82d44737413cd013ff657b8afc0cfc7c..6e8ad176e1a1468f0bbb3bf197232e850361f0d6 100644 (file)
  *   DViCO FusionHDTV 3 Gold-Q
  *   DViCO FusionHDTV 3 Gold-T
  *   DViCO FusionHDTV 5 Gold
+ *   DViCO FusionHDTV 5 Lite
+ *   DViCO FusionHDTV 5 USB Gold
+ *   Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
+ *   pcHDTV HD5500
  *
  * TODO:
  * signal strength always returns 0.
@@ -56,7 +60,6 @@ if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
 struct lgdt330x_state
 {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
 
        /* Configuration settings */
        const struct lgdt330x_config* config;
@@ -222,6 +225,11 @@ static int lgdt330x_init(struct dvb_frontend* fe)
                0x4c, 0x14
        };
 
+       static u8 flip_lgdt3303_init_data[] = {
+               0x4c, 0x14,
+               0x87, 0xf3
+       };
+
        struct lgdt330x_state* state = fe->demodulator_priv;
        char  *chip_name;
        int    err;
@@ -234,8 +242,13 @@ static int lgdt330x_init(struct dvb_frontend* fe)
                break;
        case LGDT3303:
                chip_name = "LGDT3303";
-               err = i2c_write_demod_bytes(state, lgdt3303_init_data,
-                                           sizeof(lgdt3303_init_data));
+               if (state->config->clock_polarity_flip) {
+                       err = i2c_write_demod_bytes(state, flip_lgdt3303_init_data,
+                                                   sizeof(flip_lgdt3303_init_data));
+               } else {
+                       err = i2c_write_demod_bytes(state, lgdt3303_init_data,
+                                                   sizeof(lgdt3303_init_data));
+               }
                break;
        default:
                chip_name = "undefined";
@@ -289,10 +302,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
        static u8 lgdt3303_8vsb_44_data[] = {
                0x04, 0x00,
                0x0d, 0x40,
-        0x0e, 0x87,
-        0x0f, 0x8e,
-        0x10, 0x01,
-        0x47, 0x8b };
+       0x0e, 0x87,
+       0x0f, 0x8e,
+       0x10, 0x01,
+       0x47, 0x8b };
 
        /*
         * Array of byte pairs <address, value>
@@ -386,10 +399,14 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
        }
 
        /* Tune to the specified frequency */
-       if (state->config->pll_set)
-               state->config->pll_set(fe, param);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, param);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
        /* Keep track of the new frequency */
+       /* FIXME this is the wrong way to do this...           */
+       /* The tuner is shared with the video4linux analog API */
        state->current_frequency = param->frequency;
 
        lgdt330x_SwReset(state);
@@ -657,6 +674,7 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
 
        if (state->current_modulation == VSB_8) {
 
+               i2c_read_demod_bytes(state, 0x6e, buf, 5);
                /* Phase Tracker Mean-Square Error Register for VSB */
                noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
        } else {
@@ -699,24 +717,26 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
        u8 buf[1];
 
        /* Allocate memory for the internal state */
-       state = (struct lgdt330x_state*) kmalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
-       memset(state,0,sizeof(*state));
 
        /* Setup the state */
        state->config = config;
        state->i2c = i2c;
+
+       /* Create dvb_frontend */
        switch (config->demod_chip) {
        case LGDT3302:
-               memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
+               memcpy(&state->frontend.ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
                break;
        case LGDT3303:
-               memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
+               memcpy(&state->frontend.ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
                break;
        default:
                goto error;
        }
+       state->frontend.demodulator_priv = state;
 
        /* Verify communication with demod chip */
        if (i2c_read_demod_bytes(state, 2, buf, 1))
@@ -725,9 +745,6 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
        state->current_frequency = -1;
        state->current_modulation = -1;
 
-       /* Create dvb_frontend */
-       state->frontend.ops = &state->ops;
-       state->frontend.demodulator_priv = state;
        return &state->frontend;
 
 error:
@@ -743,9 +760,8 @@ static struct dvb_frontend_ops lgdt3302_ops = {
                .frequency_min= 54000000,
                .frequency_max= 858000000,
                .frequency_stepsize= 62500,
-               /* Symbol rate is for all VSB modes need to check QAM */
-               .symbol_rate_min    = 10762000,
-               .symbol_rate_max    = 10762000,
+               .symbol_rate_min    = 5056941,  /* QAM 64 */
+               .symbol_rate_max    = 10762000, /* VSB 8  */
                .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
        },
        .init                 = lgdt330x_init,
@@ -767,9 +783,8 @@ static struct dvb_frontend_ops lgdt3303_ops = {
                .frequency_min= 54000000,
                .frequency_max= 858000000,
                .frequency_stepsize= 62500,
-               /* Symbol rate is for all VSB modes need to check QAM */
-               .symbol_rate_min    = 10762000,
-               .symbol_rate_max    = 10762000,
+               .symbol_rate_min    = 5056941,  /* QAM 64 */
+               .symbol_rate_max    = 10762000, /* VSB 8  */
                .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
        },
        .init                 = lgdt330x_init,