Regarding m88rc2000 i2c gate operation, SNR, BER and others
PATCH 1/1 Regarding m88rc2000 i2c gate operation, SNR, BER and others
Malcolm,
I made SNR, BER, UCB and signal level code for m88rc2000, but my cards show them correctly only if I made changes in m88rs2000_tuner_read function. Analyzing USB logs I found that register 0x81 never set to 0x85 value. It is always set to 0x84 regardless of read or write operation to tuner. I was wondering is this my hardware specific? Can you test you cards with attached patch?
Igor
drivers/media/dvb/frontends/m88rs2000.c +59 -11
@@ -143,7 +143,7 @@ static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg)static u8 m88rs2000_tuner_read (struct m88rs2000_state *state,u8 reg) { -m88rs2000_demod_write (state,0x81 ,0x85 ); +m88rs2000_demod_write (state,0x81 ,0x84 );udelay (10 );return m88rs2000_readreg (state,0 , reg); }
@@ -492,33 +492,81 @@ static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status)return 0 ; } -/* Extact code for these unknown but lmedm04 driver uses interupt callbacks */ -static int m88rs2000_read_ber (struct dvb_frontend *fe,u32 *ber) { -deb_info ("m88rs2000_read_ber %d\n" , *ber); - *ber =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; +u8 tmp0, tmp1; + +m88rs2000_demod_write (state,0x9a ,0x30 ); + tmp0 =m88rs2000_demod_read (state,0xd8 ); +if ((tmp0 &0x10 ) !=0 ) { +m88rs2000_demod_write (state,0x9a ,0xb0 ); + *ber =0xffffffff ; +return 0 ; + } + + *ber = (m88rs2000_demod_read (state,0xd7 ) <<8 ) | +m88rs2000_demod_read (state,0xd6 ); + + tmp1 =m88rs2000_demod_read (state,0xd9 ); +m88rs2000_demod_write (state,0xd9 , (tmp1 & ~7 ) |4 ); +/* needs twice */ +m88rs2000_demod_write (state,0xd8 , (tmp0 & ~8 ) |0x30 ); +m88rs2000_demod_write (state,0xd8 , (tmp0 & ~8 ) |0x30 ); +m88rs2000_demod_write (state,0x9a ,0xb0 ); +return 0 ; }static int m88rs2000_read_signal_strength (struct dvb_frontend *fe, -u16 *strength) +u16 *signal_strength) { - *strength =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; +u8 rfg, bbg, gain, strength; + + rfg =m88rs2000_tuner_read (state,0x3d ) &0x1f ; + bbg =m88rs2000_tuner_read (state,0x21 ) &0x1f ; + gain = rfg *2 + bbg *3 ; + +if (gain >80 ) + strength =0 ; +else if (gain >65 ) + strength =4 * (80 - gain); +else if (gain >50 ) + strength =65 +4 * (65 - gain) /3 ; +else + strength =85 +2 * (50 - gain) /3 ; + + *signal_strength = strength *655 ; + +deb_info ("%s: rfg, bbg / gain = %d, %d, %d\n" , + __func__, rfg, bbg, gain); +return 0 ; }static int m88rs2000_read_snr (struct dvb_frontend *fe,u16 *snr) { -deb_info ("m88rs2000_read_snr %d\n" , *snr); - *snr =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; + + *snr =512 *m88rs2000_demod_read (state,0x65 ); +return 0 ; }static int m88rs2000_read_ucblocks (struct dvb_frontend *fe,u32 *ucblocks) { -deb_info ("m88rs2000_read_ber %d\n" , *ucblocks); - *ucblocks =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; +u8 tmp; + + *ucblocks = (m88rs2000_demod_read (state,0xd5 ) <<8 ) | +m88rs2000_demod_read (state,0xd4 ); + tmp =m88rs2000_demod_read (state,0xd8 ); +m88rs2000_demod_write (state,0xd8 , tmp & ~0x20 ); +/* needs two times */ +m88rs2000_demod_write (state,0xd8 , tmp |0x20 ); +m88rs2000_demod_write (state,0xd8 , tmp |0x20 ); +return 0 ; }
Quoted 10 lines · Igor M. Liplianin
Malcolm,
I made SNR, BER, UCB and signal level code for m88rc2000, but my cards show them correctly only if I made changes in
m88rs2000_tuner_readfunction. Analyzing USB logs I found that register0x81never set to0x85value. It is always set to0x84regardless of read or write operation to tuner. I was wondering is this my hardware specific? Can you test you cards with attached patch?Igor
Hi Igor
I have been testing the patch this evening and have found no problems.
I just need to create in lmedm04 callbacks for m88rs2000_read_snr and m88rs2000_read_ber as these cannot be called while the device is streaming. It looks like they are present in the interrupt callback.
Register 0x81 works with either 0x84 or 0x85 on read. What I did notice if 0x85 is used on writes the device becomes completely unresponsive and needs to be replugged. So it is safer to use 0x84.
I will try and get the patch for lmedm04 ready in the next few days.
Regards
Malcolm
Quoted 106 lines
differences between files attachment (snrber.patch)
drivers/media/dvb/frontends/m88rs2000.c +59
-11@@ -143,7 +143,7 @@ static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg)static u8 m88rs2000_tuner_read (struct m88rs2000_state *state,u8 reg) { -m88rs2000_demod_write (state,0x81 ,0x85 ); +m88rs2000_demod_write (state,0x81 ,0x84 );udelay (10 );return m88rs2000_readreg (state,0 , reg); }@@ -492,33 +492,81 @@ static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status)return 0 ; } -/* Extact code for these unknown but lmedm04 driver uses interupt callbacks */ -static int m88rs2000_read_ber (struct dvb_frontend *fe,u32 *ber) { -deb_info ("m88rs2000_read_ber %d\n" , *ber); - *ber =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; +u8 tmp0, tmp1; + +m88rs2000_demod_write (state,0x9a ,0x30 ); + tmp0 =m88rs2000_demod_read (state,0xd8 ); +if ((tmp0 &0x10 ) !=0 ) { +m88rs2000_demod_write (state,0x9a ,0xb0 ); + *ber =0xffffffff ; +return 0 ; + } + + *ber = (m88rs2000_demod_read (state,0xd7 ) <<8 ) | +m88rs2000_demod_read (state,0xd6 ); + + tmp1 =m88rs2000_demod_read (state,0xd9 ); +m88rs2000_demod_write (state,0xd9 , (tmp1 & ~7 ) |4 ); +/* needs twice */ +m88rs2000_demod_write (state,0xd8 , (tmp0 & ~8 ) |0x30 ); +m88rs2000_demod_write (state,0xd8 , (tmp0 & ~8 ) |0x30 ); +m88rs2000_demod_write (state,0x9a ,0xb0 ); +return 0 ; }static int m88rs2000_read_signal_strength (struct dvb_frontend *fe, -u16 *strength) +u16 *signal_strength) { - *strength =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; +u8 rfg, bbg, gain, strength; + + rfg =m88rs2000_tuner_read (state,0x3d ) &0x1f ; + bbg =m88rs2000_tuner_read (state,0x21 ) &0x1f ; + gain = rfg *2 + bbg *3 ; + +if (gain >80 ) + strength =0 ; +else if (gain >65 ) + strength =4 * (80 - gain); +else if (gain >50 ) + strength =65 +4 * (65 - gain) /3 ; +else + strength =85 +2 * (50 - gain) /3 ; + + *signal_strength = strength *655 ; + +deb_info ("%s: rfg, bbg / gain = %d, %d, %d\n" , + __func__, rfg, bbg, gain); +return 0 ; }static int m88rs2000_read_snr (struct dvb_frontend *fe,u16 *snr) { -deb_info ("m88rs2000_read_snr %d\n" , *snr); - *snr =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; + + *snr =512 *m88rs2000_demod_read (state,0x65 ); +return 0 ; }static int m88rs2000_read_ucblocks (struct dvb_frontend *fe,u32 *ucblocks) { -deb_info ("m88rs2000_read_ber %d\n" , *ucblocks); - *ucblocks =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; +u8 tmp; + + *ucblocks = (m88rs2000_demod_read (state,0xd5 ) <<8 ) | +m88rs2000_demod_read (state,0xd4 ); + tmp =m88rs2000_demod_read (state,0xd8 ); +m88rs2000_demod_write (state,0xd8 , tmp & ~0x20 ); +/* needs two times */ +m88rs2000_demod_write (state,0xd8 , tmp |0x20 ); +m88rs2000_demod_write (state,0xd8 , tmp |0x20 ); +return 0 ; }
PATCH 1/1 lmedm04 ver 2.00 - changes for [TEST] Regarding m88rc2000 i2c gate operation, SNR, BER and others
Re: [PATCH] [TEST] Regarding m88rc2000 i2c gate operation, SNR, BER and others
This patch restores more less as before, except;
Corrected snr/signal strength are swapped.
m88rs2000_set_voltage is now called inside dm04_lme2510_set_voltage this seems to stop intermittent loss of device during channel change/scan.
Unfortunately, lmedm04 cannot support ucblocks or ber, neither are returned in the interrupt callback. I am working on a patch to map them back in when streaming is off.
--- drivers/media/dvb/dvb-usb/lmedm04.c | 46 ++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 9 deletions(-)
drivers/media/dvb/dvb-usb/lmedm04.c +37 -9
@@ -136,7 +136,7 @@ struct lme2510_state {void *buffer;struct urb *lme_urb;void *usb_buffer; - +int (*fe_set_voltage)(struct dvb_frontend *,fe_sec_voltage_t ); }; static int lme2510_bulk_write(struct usb_device *dev,
@@ -313,12 +313,12 @@ static void lme2510_int_response(struct urb *lme_urb) }break ;case TUNER_RS2000 : -if (ibuf[2 ] >0 ) +if (ibuf[1 ] ==0x3 && ibuf[6 ] ==0xff ) st->signal_lock =0xff ;else - st->signal_lock =0xf0 ; - st->signal_level = ibuf[4 ]; - st->signal_sn = ibuf[5 ]; + st->signal_lock =0x00 ; + st->signal_level = ibuf[5 ]; + st->signal_sn = ibuf[4 ]; st->time_key = ibuf[7 ];default :break ;
@@ -973,6 +973,7 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) {struct dvb_usb_adapter *adap = fe->dvb->priv; +struct lme2510_state *st = adap->dev->priv;static u8 voltage_low[] =LME_VOLTAGE_L ;static u8 voltage_high[] =LME_VOLTAGE_H ;static u8 rbuf[1 ];
@@ -993,9 +994,13 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, voltage_low, len, rbuf, rlen);break ; } -mutex_unlock (&adap->dev->i2c_mutex); +if (st->tuner_config ==TUNER_RS2000 ) +if (st->fe_set_voltage) + st->fe_set_voltage (fe, voltage); + +return (ret <0 ) ? -ENODEV :0 ; }
@@ -1005,7 +1010,8 @@ static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe,struct dvb_usb_adapter *adap = fe->dvb->priv;struct lme2510_state *st = adap->dev->priv; - *strength = (u16)((u32 )st->signal_level *0xffff /0x7f ); + *strength = (u16)((u32 )st->signal_level *0xffff /0xff ); +return 0 ; }
@@ -1014,7 +1020,22 @@ static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr)struct dvb_usb_adapter *adap = fe->dvb->priv;struct lme2510_state *st = adap->dev->priv; - *snr = (u16)((u32 )st->signal_sn *0xffff /0xff ); + *snr = (u16)((u32 )st->signal_sn *0xffff /0x7f ); + +return 0 ; +} + +static int dm04_read_ber (struct dvb_frontend *fe,u32 *ber) +{ + *ber =0 ; + +return 0 ; +} + +static int dm04_read_ucblocks (struct dvb_frontend *fe,u32 *ucblocks) +{ + *ucblocks =0 ; +return 0 ; }
@@ -1101,10 +1122,17 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) st->i2c_tuner_gate_r =5 ; st->i2c_tuner_addr =0xc0 ; st->tuner_config =TUNER_RS2000 ; + st->fe_set_voltage = + adap->fe_adap[0 ].fe->ops.set_voltage; + adap->fe_adap[0 ].fe->ops.read_signal_strength = dm04_rs2000_read_signal_strength; adap->fe_adap[0 ].fe->ops.read_snr = dm04_rs2000_read_snr; + adap->fe_adap[0 ].fe->ops.read_ber = + dm04_read_ber; + adap->fe_adap[0 ].fe->ops.read_ucblocks = + dm04_read_ucblocks; }break ; }
@@ -1404,5 +1432,5 @@ module_usb_driver(lme2510_driver);MODULE_AUTHOR ("Malcolm Priestley <[email protected]>" );MODULE_DESCRIPTION ("LME2510(C) DVB-S USB2.0" ); -MODULE_VERSION ("1.99" ); +MODULE_VERSION ("2.00" );MODULE_LICENSE ("GPL" );
Signature · 1 line
1.7.9.5
Re: [PATCH] [TEST] Regarding m88rs2000 i2c gate operation, SNR, BER and others
In reply to Igor M. LiplianinQuoted 10 lines · Igor M. Liplianin
Malcolm,
I made SNR, BER, UCB and signal level code for m88rc2000, but my cards show them correctly only if I made changes in
m88rs2000_tuner_readfunction. Analyzing USB logs I found that register0x81never set to0x85value. It is always set to0x84regardless of read or write operation to tuner. I was wondering is this my hardware specific? Can you test you cards with attached patch?Igor
Hi Igor
I have no problems with patch, please could you add your signoff
I you and me have followed a typo error with m88rc2000 for m88rs2000 in the title.
This patch and patch
http://patchwork.linuxtv.org/patch/11235/
can go upstream
Regards
Malcolm
Quoted 106 lines
differences between files attachment (snrber.patch)
drivers/media/dvb/frontends/m88rs2000.c +59
-11@@ -143,7 +143,7 @@ static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg)static u8 m88rs2000_tuner_read (struct m88rs2000_state *state,u8 reg) { -m88rs2000_demod_write (state,0x81 ,0x85 ); +m88rs2000_demod_write (state,0x81 ,0x84 );udelay (10 );return m88rs2000_readreg (state,0 , reg); }@@ -492,33 +492,81 @@ static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status)return 0 ; } -/* Extact code for these unknown but lmedm04 driver uses interupt callbacks */ -static int m88rs2000_read_ber (struct dvb_frontend *fe,u32 *ber) { -deb_info ("m88rs2000_read_ber %d\n" , *ber); - *ber =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; +u8 tmp0, tmp1; + +m88rs2000_demod_write (state,0x9a ,0x30 ); + tmp0 =m88rs2000_demod_read (state,0xd8 ); +if ((tmp0 &0x10 ) !=0 ) { +m88rs2000_demod_write (state,0x9a ,0xb0 ); + *ber =0xffffffff ; +return 0 ; + } + + *ber = (m88rs2000_demod_read (state,0xd7 ) <<8 ) | +m88rs2000_demod_read (state,0xd6 ); + + tmp1 =m88rs2000_demod_read (state,0xd9 ); +m88rs2000_demod_write (state,0xd9 , (tmp1 & ~7 ) |4 ); +/* needs twice */ +m88rs2000_demod_write (state,0xd8 , (tmp0 & ~8 ) |0x30 ); +m88rs2000_demod_write (state,0xd8 , (tmp0 & ~8 ) |0x30 ); +m88rs2000_demod_write (state,0x9a ,0xb0 ); +return 0 ; }static int m88rs2000_read_signal_strength (struct dvb_frontend *fe, -u16 *strength) +u16 *signal_strength) { - *strength =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; +u8 rfg, bbg, gain, strength; + + rfg =m88rs2000_tuner_read (state,0x3d ) &0x1f ; + bbg =m88rs2000_tuner_read (state,0x21 ) &0x1f ; + gain = rfg *2 + bbg *3 ; + +if (gain >80 ) + strength =0 ; +else if (gain >65 ) + strength =4 * (80 - gain); +else if (gain >50 ) + strength =65 +4 * (65 - gain) /3 ; +else + strength =85 +2 * (50 - gain) /3 ; + + *signal_strength = strength *655 ; + +deb_info ("%s: rfg, bbg / gain = %d, %d, %d\n" , + __func__, rfg, bbg, gain); +return 0 ; }static int m88rs2000_read_snr (struct dvb_frontend *fe,u16 *snr) { -deb_info ("m88rs2000_read_snr %d\n" , *snr); - *snr =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; + + *snr =512 *m88rs2000_demod_read (state,0x65 ); +return 0 ; }static int m88rs2000_read_ucblocks (struct dvb_frontend *fe,u32 *ucblocks) { -deb_info ("m88rs2000_read_ber %d\n" , *ucblocks); - *ucblocks =0 ; +struct m88rs2000_state *state = fe->demodulator_priv; +u8 tmp; + + *ucblocks = (m88rs2000_demod_read (state,0xd5 ) <<8 ) | +m88rs2000_demod_read (state,0xd4 ); + tmp =m88rs2000_demod_read (state,0xd8 ); +m88rs2000_demod_write (state,0xd8 , tmp & ~0x20 ); +/* needs two times */ +m88rs2000_demod_write (state,0xd8 , tmp |0x20 ); +m88rs2000_demod_write (state,0xd8 , tmp |0x20 ); +return 0 ; }