stv0910: upstream changes and PLS support
Subsystems (2)
cover stv0910: upstream changes and PLS support
From: Daniel Scheller <[email protected]>
This series basically is meant to fully enable support for physical layer scrambling which is now supported by the DVB core. Though I decided to pick up the latest changes to the driver from the dddvb upstream and bring both drivers in sync. So, along with support for PLS, these patches apply some cosmetics and cleanups, adds macros to utilise the field definitions for which the offsets were added recently, and makes use of them while finally enabling PLS.
Daniel Scheller (4):
[media] dvb-frontends/stv0910: deduplicate writes in
enable_puncture_rate()
[media] dvb-frontends/stv0910: cleanup I2C access functions [media] dvb-frontends/stv0910: field and register access helpers [media] dvb-frontends/stv0910: cleanup init_search_param() and enable
PLS
drivers/media/dvb-frontends/stv0910.c | 195 ++++++++++++++++++---------------- 1 file changed, 103 insertions(+), 92 deletions(-)
Signature · 1 line
2.13.6
PATCH 1/4 dvb-frontends/stv0910: deduplicate writes in enable_puncture_rate()
From: Daniel Scheller <[email protected]>
For all code rates, the same write is performed, only with a differing value. Clean this up by putting that value into a variable instead and perform the write at the end with that value.
Picked up from the dddvb upstream.
--- drivers/media/dvb-frontends/stv0910.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-)
drivers/media/dvb-frontends/stv0910.c +16 -12
@@ -908,27 +908,31 @@ static int init_search_param(struct stv *state)static int enable_puncture_rate (struct stv *state,enum fe_code_rate rate) { +u8 val; +switch (rate) {case FEC_1_2 : -return write_reg (state, -RSTV0910_P2_PRVIT + state->regoff,0x01 ); + val =0x01 ; +break ;case FEC_2_3 : -return write_reg (state, -RSTV0910_P2_PRVIT + state->regoff,0x02 ); + val =0x02 ; +break ;case FEC_3_4 : -return write_reg (state, -RSTV0910_P2_PRVIT + state->regoff,0x04 ); + val =0x04 ; +break ;case FEC_5_6 : -return write_reg (state, -RSTV0910_P2_PRVIT + state->regoff,0x08 ); + val =0x08 ; +break ;case FEC_7_8 : -return write_reg (state, -RSTV0910_P2_PRVIT + state->regoff,0x20 ); + val =0x20 ; +break ;case FEC_NONE :default : -return write_reg (state, -RSTV0910_P2_PRVIT + state->regoff,0x2f ); + val =0x2f ; +break ; } + +return write_reg (state,RSTV0910_P2_PRVIT + state->regoff, val); }static int set_vth_default (struct stv *state)
Signature · 1 line
2.13.6
PATCH 2/4 dvb-frontends/stv0910: cleanup I2C access functions
In reply to Daniel SchellerFrom: Daniel Scheller <[email protected]>
write_reg() and i2c_write_reg16() only act as a proxy to i2c_write(), which isn't called from anywhere else throughout the driver. Clean this up by moving the message setup and the i2c_transfer() into write_reg() so it becomes the only I2C write function. While touching those parts, fix the error codes from EREMOTEIO to EIO.
The I2C cleanup is picked from the upstream dddvb.
--- drivers/media/dvb-frontends/stv0910.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-)
drivers/media/dvb-frontends/stv0910.c +8 -20
@@ -137,33 +137,21 @@ struct slookup {u32 reg_value; }; -static inline int i2c_write (struct i2c_adapter *adap,u8 adr, -u8 *data,int len) +static int write_reg (struct stv *state,u16 reg,u8 val) { -struct i2c_msg msg = {.addr = adr, .flags =0 , - .buf = data, .len = len}; +struct i2c_adapter *adap = state->base->i2c; +u8 data[3 ] = {reg >>8 , reg &0xff , val}; +struct i2c_msg msg = {.addr = state->base->adr, .flags =0 , + .buf = data, .len =3 };if (i2c_transfer (adap, &msg,1 ) !=1 ) {dev_warn (&adap->dev,"i2c write error ([%02x] %04x: %02x)\n" , - adr, (data[0 ] <<8 ) | data[1 ], - (len >2 ? data[2 ] :0 )); -return -EREMOTEIO ; + state->base->adr, reg, val); +return -EIO ; }return 0 ; } -static int i2c_write_reg16 (struct i2c_adapter *adap,u8 adr,u16 reg,u8 val) -{ -u8 msg[3 ] = {reg >>8 , reg &0xff , val}; - -return i2c_write (adap, adr, msg,3 ); -} - -static int write_reg (struct stv *state,u16 reg,u8 val) -{ -return i2c_write_reg16 (state->base->i2c, state->base->adr, reg, val); -} -static inline int i2c_read_regs16 (struct i2c_adapter *adapter,u8 adr,u16 reg,u8 *val,int count) {
@@ -176,7 +164,7 @@ static inline int i2c_read_regs16(struct i2c_adapter *adapter, u8 adr,if (i2c_transfer (adapter, msgs,2 ) !=2 ) {dev_warn (&adapter->dev,"i2c read error ([%02x] %04x)\n" , adr, reg); -return -EREMOTEIO ; +return -EIO ; }return 0 ; }
Signature · 1 line
2.13.6
PATCH 3/4 dvb-frontends/stv0910: field and register access helpers
In reply to Daniel SchellerFrom: Daniel Scheller <[email protected]>
Add a write_field() function that acts as helper to update specific bits specified in the field defines (FSTV0910_*) in stv0910_regs.h, which was recently updated to carry the missing offset values. With that, add the SET_FIELD(), SET_REG() and GET_REG() macros that wrap the write_field(), write_reg() and read_reg() functions to allow for making all demod access code cleaner.
The write_field() function is annotated with __maybe_unused temporarily to silence eventual compile warnings.
Picked up from the dddvb upstream, with the macro names made uppercase so they are distinguishable as such.
--- drivers/media/dvb-frontends/stv0910.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
drivers/media/dvb-frontends/stv0910.c +28 -0
@@ -194,6 +194,34 @@ static int write_shared_reg(struct stv *state, u16 reg, u8 mask, u8 val)return status; } +static int __maybe_unused write_field (struct stv *state,u32 field,u8 val) +{ +int status; +u8 shift, mask, old, new; + + status =read_reg (state, field >>16 , &old); +if (status) +return status; + mask = field &0xff ; + shift = (field >>12 ) &0xf ; + new = ((val << shift) & mask) | (old & ~mask); +if (new == old) +return 0 ; +return write_reg (state, field >>16 , new); +} + +#define SET_FIELD (_reg, _val) \ + write_field(state, state->nr ? FSTV0910_P2_##_reg : \ + FSTV0910_P1_##_reg, _val) + +#define SET_REG (_reg, _val) \ + write_reg(state, state->nr ? RSTV0910_P2_##_reg : \ + RSTV0910_P1_##_reg, _val) + +#define GET_REG (_reg, _val) \ + read_reg(state, state->nr ? RSTV0910_P2_##_reg : \ + RSTV0910_P1_##_reg, _val) +static const struct slookup s1_sn_lookup[] = { {0 ,9242 },/* C/N= 0dB */ {5 ,9105 },/* C/N= 0.5dB */
Signature · 1 line
2.13.6
Daniel Scheller
AppliedPATCH 4/4 dvb-frontends/stv0910: cleanup init_search_param() and enable PLS
In reply to Daniel SchellerFrom: Daniel Scheller <[email protected]>
Cleanup the mess in init_search_param() by utilising the new register access macros and functions. And while at it, move the ISI and PLS setup into separate functions, and pass the new scrambling_sequence_index (aka. physical layer scrambling) value to set_pls.
Picked up from the dddvb upstream, adapted to the different naming of the pls property (pls vs. scrambling_sequence_index).
--- drivers/media/dvb-frontends/stv0910.c | 113 ++++++++++++++++------------------ 1 file changed, 52 insertions(+), 61 deletions(-)
drivers/media/dvb-frontends/stv0910.c +52 -61
@@ -194,7 +194,7 @@ static int write_shared_reg(struct stv *state, u16 reg, u8 mask, u8 val)return status; } -static int __maybe_unused write_field (struct stv *state,u32 field,u8 val) +static int write_field (struct stv *state,u32 field,u8 val) {int status;u8 shift, mask, old, new;
@@ -880,45 +880,60 @@ static int stop(struct stv *state)return 0 ; } -static int init_search_param (struct stv *state) +static void set_pls (struct stv *state,u32 pls_code) { -u8 tmp; - -read_reg (state,RSTV0910_P2_PDELCTRL1 + state->regoff, &tmp); - tmp |=0x20 ;/* Filter_en (no effect if SIS=non-MIS */ -write_reg (state,RSTV0910_P2_PDELCTRL1 + state->regoff, tmp); - -read_reg (state,RSTV0910_P2_PDELCTRL2 + state->regoff, &tmp); - tmp &= ~0x02 ;/* frame mode = 0 */ -write_reg (state,RSTV0910_P2_PDELCTRL2 + state->regoff, tmp); - -write_reg (state,RSTV0910_P2_UPLCCST0 + state->regoff,0xe0 ); -write_reg (state,RSTV0910_P2_ISIBITENA + state->regoff,0x00 ); - -read_reg (state,RSTV0910_P2_TSSTATEM + state->regoff, &tmp); - tmp &= ~0x01 ;/* nosync = 0, in case next signal is standard TS */ -write_reg (state,RSTV0910_P2_TSSTATEM + state->regoff, tmp); - -read_reg (state,RSTV0910_P2_TSCFGL + state->regoff, &tmp); - tmp &= ~0x04 ;/* embindvb = 0 */ -write_reg (state,RSTV0910_P2_TSCFGL + state->regoff, tmp); - -read_reg (state,RSTV0910_P2_TSINSDELH + state->regoff, &tmp); - tmp &= ~0x80 ;/* syncbyte = 0 */ -write_reg (state,RSTV0910_P2_TSINSDELH + state->regoff, tmp); - -read_reg (state,RSTV0910_P2_TSINSDELM + state->regoff, &tmp); - tmp &= ~0x08 ;/* token = 0 */ -write_reg (state,RSTV0910_P2_TSINSDELM + state->regoff, tmp); +if (pls_code == state->cur_scrambling_code) +return ; + +/* PLROOT2 bit 2 = gold code */ +write_reg (state,RSTV0910_P2_PLROOT0 + state->regoff, + pls_code &0xff ); +write_reg (state,RSTV0910_P2_PLROOT1 + state->regoff, + (pls_code >>8 ) &0xff ); +write_reg (state,RSTV0910_P2_PLROOT2 + state->regoff, +0x04 | ((pls_code >>16 ) &0x03 )); + state->cur_scrambling_code = pls_code; +} -read_reg (state,RSTV0910_P2_TSDLYSET2 + state->regoff, &tmp); - tmp &= ~0x30 ;/* hysteresis threshold = 0 */ -write_reg (state,RSTV0910_P2_TSDLYSET2 + state->regoff, tmp); +static void set_isi (struct stv *state,u32 isi) +{ +if (isi ==NO_STREAM_ID_FILTER ) +return ; +if (isi ==0x80000000 ) { +SET_FIELD (FORCE_CONTINUOUS ,1 ); +SET_FIELD (TSOUT_NOSYNC ,1 ); + }else { +SET_FIELD (FILTER_EN ,1 ); +write_reg (state,RSTV0910_P2_ISIENTRY + state->regoff, + isi &0xff ); +write_reg (state,RSTV0910_P2_ISIBITENA + state->regoff,0xff ); + } +SET_FIELD (ALGOSWRST ,1 ); +SET_FIELD (ALGOSWRST ,0 ); +} -read_reg (state,RSTV0910_P2_PDELCTRL0 + state->regoff, &tmp); - tmp = (tmp & ~0x30 ) |0x10 ;/* isi obs mode = 1, observe min ISI */ -write_reg (state,RSTV0910_P2_PDELCTRL0 + state->regoff, tmp); +static void set_stream_modes (struct stv *state, +struct dtv_frontend_properties *p) +{ +set_isi (state, p->stream_id); +set_pls (state, p->scrambling_sequence_index); +} +static int init_search_param (struct stv *state, +struct dtv_frontend_properties *p) +{ +SET_FIELD (FORCE_CONTINUOUS ,0 ); +SET_FIELD (FRAME_MODE ,0 ); +SET_FIELD (FILTER_EN ,0 ); +SET_FIELD (TSOUT_NOSYNC ,0 ); +SET_FIELD (TSFIFO_EMBINDVB ,0 ); +SET_FIELD (TSDEL_SYNCBYTE ,0 ); +SET_REG (UPLCCST0 ,0xe0 ); +SET_FIELD (TSINS_TOKEN ,0 ); +SET_FIELD (HYSTERESIS_THRESHOLD ,0 ); +SET_FIELD (ISIOBS_MODE ,1 ); + +set_stream_modes (state, p);return 0 ; }
@@ -1005,7 +1020,6 @@ 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 ;
@@ -1017,30 +1031,7 @@ static int start(struct stv *state, struct dtv_frontend_properties *p)if (state->started)write_reg (state,RSTV0910_P2_DMDISTATE + state->regoff,0x5C ); -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 ) &0x0f ); - state->cur_scrambling_code = scrambling_code; - } +init_search_param (state, p);if (p->symbol_rate <=1000000 ) {/* SR <=1Msps */ state->demod_timeout =3000 ;
Signature · 1 line
2.13.6