[media] m88ds3103: implement BER
authorAntti Palosaari <crope@iki.fi>
Thu, 10 Jul 2014 11:17:59 +0000 (08:17 -0300)
committerMauro Carvalho Chehab <m.chehab@samsung.com>
Wed, 23 Jul 2014 00:30:58 +0000 (21:30 -0300)
Implement read_ber for BER estimate.

Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/dvb-frontends/m88ds3103.c
drivers/media/dvb-frontends/m88ds3103_priv.h

index 4176edf623a87b8d0949e452984da3473cc21f4e..dfe0c2f7f1efc749b7b409cbc7bb00262e9eca37 100644 (file)
@@ -926,6 +926,86 @@ err:
        return ret;
 }
 
+static int m88ds3103_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct m88ds3103_priv *priv = fe->demodulator_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       int ret;
+       unsigned int utmp;
+       u8 buf[3], u8tmp;
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       switch (c->delivery_system) {
+       case SYS_DVBS:
+               ret = m88ds3103_wr_reg(priv, 0xf9, 0x04);
+               if (ret)
+                       goto err;
+
+               ret = m88ds3103_rd_reg(priv, 0xf8, &u8tmp);
+               if (ret)
+                       goto err;
+
+               if (!(u8tmp & 0x10)) {
+                       u8tmp |= 0x10;
+
+                       ret = m88ds3103_rd_regs(priv, 0xf6, buf, 2);
+                       if (ret)
+                               goto err;
+
+                       priv->ber = (buf[1] << 8) | (buf[0] << 0);
+
+                       /* restart counters */
+                       ret = m88ds3103_wr_reg(priv, 0xf8, u8tmp);
+                       if (ret)
+                               goto err;
+               }
+               break;
+       case SYS_DVBS2:
+               ret = m88ds3103_rd_regs(priv, 0xd5, buf, 3);
+               if (ret)
+                       goto err;
+
+               utmp = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0);
+
+               if (utmp > 3000) {
+                       ret = m88ds3103_rd_regs(priv, 0xf7, buf, 2);
+                       if (ret)
+                               goto err;
+
+                       priv->ber = (buf[1] << 8) | (buf[0] << 0);
+
+                       /* restart counters */
+                       ret = m88ds3103_wr_reg(priv, 0xd1, 0x01);
+                       if (ret)
+                               goto err;
+
+                       ret = m88ds3103_wr_reg(priv, 0xf9, 0x01);
+                       if (ret)
+                               goto err;
+
+                       ret = m88ds3103_wr_reg(priv, 0xf9, 0x00);
+                       if (ret)
+                               goto err;
+
+                       ret = m88ds3103_wr_reg(priv, 0xd1, 0x00);
+                       if (ret)
+                               goto err;
+               }
+               break;
+       default:
+               dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
+                               __func__);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       *ber = priv->ber;
+
+       return 0;
+err:
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
 
 static int m88ds3103_set_tone(struct dvb_frontend *fe,
        fe_sec_tone_mode_t fe_sec_tone_mode)
@@ -1284,6 +1364,7 @@ static struct dvb_frontend_ops m88ds3103_ops = {
 
        .read_status = m88ds3103_read_status,
        .read_snr = m88ds3103_read_snr,
+       .read_ber = m88ds3103_read_ber,
 
        .diseqc_send_master_cmd = m88ds3103_diseqc_send_master_cmd,
        .diseqc_send_burst = m88ds3103_diseqc_send_burst,
index e73db5ccdc7473bc4264f11fdf61cb85f559e45a..9169fdd143cfdd1973d38324ba4e2863696f245d 100644 (file)
@@ -35,6 +35,7 @@ struct m88ds3103_priv {
        struct dvb_frontend fe;
        fe_delivery_system_t delivery_system;
        fe_status_t fe_status;
+       u32 ber;
        bool warm; /* FW running */
        struct i2c_adapter *i2c_adapter;
 };