media: dvb-frontends/stv0910: add multistream (ISI) and PLS capabilities
authorDaniel Scheller <d.scheller@gmx.net>
Mon, 3 Jul 2017 17:20:56 +0000 (13:20 -0400)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Thu, 20 Jul 2017 16:59:03 +0000 (12:59 -0400)
Implements stream_id filter and scrambling code setup in start() and also
sets FE_CAN_MULTISTREAM in frontend_ops. This enables the driver to
properly receive and handle multistream transponders, functionality has
been reported working fine by testers with access to such streams, in
conjunction with VDR on the userspace side.

The code snippet originates from the original vendor's dddvb driver
package and has been made working properly with the current in-kernel
DVB core API.

Signed-off-by: Daniel Scheller <d.scheller@gmx.net>
Tested-by: Richard Scobie <r.scobie@clear.net.nz>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/media/dvb-frontends/stv0910.c

index 85439d3b725e3a8ab21afec9ce6340d5618d4d3d..dc848ebe1a44f1f29736ff167a38f4d1559363a3 100644 (file)
@@ -119,6 +119,8 @@ struct stv {
        int   is_standard_broadcast;
        int   is_vcm;
 
+       u32   cur_scrambling_code;
+
        u32   last_bernumerator;
        u32   last_berdenominator;
        u8    berscale;
@@ -965,6 +967,7 @@ static int start(struct stv *state, struct dtv_frontend_properties *p)
        s32 freq;
        u8  reg_dmdcfgmd;
        u16 symb;
+       u32 scrambling_code = 1;
 
        if (p->symbol_rate < 100000 || p->symbol_rate > 70000000)
                return -EINVAL;
@@ -978,6 +981,28 @@ static int start(struct stv *state, struct dtv_frontend_properties *p)
 
        init_search_param(state);
 
+       if (p->stream_id != NO_STREAM_ID_FILTER) {
+               /* Backwards compatibility to "crazy" API.
+                * PRBS X root cannot be 0, so this should always work.
+                */
+               if (p->stream_id & 0xffffff00)
+                       scrambling_code = p->stream_id >> 8;
+               write_reg(state, RSTV0910_P2_ISIENTRY + state->regoff,
+                         p->stream_id & 0xff);
+               write_reg(state, RSTV0910_P2_ISIBITENA + state->regoff,
+                         0xff);
+       }
+
+       if (scrambling_code != state->cur_scrambling_code) {
+               write_reg(state, RSTV0910_P2_PLROOT0 + state->regoff,
+                         scrambling_code & 0xff);
+               write_reg(state, RSTV0910_P2_PLROOT1 + state->regoff,
+                         (scrambling_code >> 8) & 0xff);
+               write_reg(state, RSTV0910_P2_PLROOT2 + state->regoff,
+                         (scrambling_code >> 16) & 0x07);
+               state->cur_scrambling_code = scrambling_code;
+       }
+
        if (p->symbol_rate <= 1000000) {  /* SR <=1Msps */
                state->demod_timeout = 3000;
                state->fec_timeout = 2000;
@@ -1597,7 +1622,8 @@ static struct dvb_frontend_ops stv0910_ops = {
                .caps                   = FE_CAN_INVERSION_AUTO |
                                          FE_CAN_FEC_AUTO       |
                                          FE_CAN_QPSK           |
-                                         FE_CAN_2G_MODULATION
+                                         FE_CAN_2G_MODULATION  |
+                                         FE_CAN_MULTISTREAM
        },
        .sleep                          = sleep,
        .release                        = release,
@@ -1655,6 +1681,7 @@ struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c,
        state->search_range = 16000000;
        state->demod_bits = 0x10;     /* Inversion : Auto with reset to 0 */
        state->receive_mode   = RCVMODE_NONE;
+       state->cur_scrambling_code = (~0U);
        state->single = cfg->single ? 1 : 0;
 
        base = match_base(i2c, cfg->adr);