media: dvb/earth-pt1: fix wrong initialization for demod blocks
Subsystems (2)
[email protected]
maintainerPATCH 1/1 media: dvb/earth-pt1: fix wrong initialization for demod blocks
From: Akihiro Tsukada <[email protected]>
earth-pt1 driver was decomposed/restructured by the commit: b732539efdba ("media: dvb: earth-pt1: decompose pt1 driver into sub drivers"), but it introduced a problem regarding concurrent streaming:
Opening a new terrestial stream stops the reception of an existing, already-opened satellite stream.
The demod IC in earth-pt1 boards contains 2 pairs of terr. and sat. blocks, supporting 4 concurrent demodulations, and the above problem was because the config of a terr. block contained whole reset/init of the pair blocks, thus each open() of a terrestrial frontend wrongly cleared the config of its peer satellite block of the demod.
This whole/pair reset should be executed earlier and not on each open().
--- drivers/media/pci/pt1/pt1.c | 54 ++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-)
drivers/media/pci/pt1/pt1.c +48 -6
@@ -200,16 +200,10 @@ static const u8 va1j5jf8007t_25mhz_configs[][2] = {static int config_demod (struct i2c_client *cl,enum pt1_fe_clk clk) {int ret; -u8 buf[2 ] = {0x01 ,0x80 };bool is_sat;const u8 (*cfg_data)[2 ];int i, len; - ret =i2c_master_send (cl, buf,2 ); -if (ret <0 ) -return ret; -usleep_range (30000 ,50000 ); - is_sat = !strncmp (cl->name,TC90522_I2C_DEV_SAT ,strlen (TC90522_I2C_DEV_SAT ));if (is_sat) {
@@ -260,6 +254,46 @@ static int config_demod(struct i2c_client *cl, enum pt1_fe_clk clk)return 0 ; } +/* +* Init registers for (each pair of) terrestrial/satellite block in demod. +* Note that resetting terr. block also resets its peer sat. block as well. +* This function must be called before configuring any demod block +* (before pt1_wakeup(), fe->ops.init()). +*/ +static int pt1_demod_block_init (struct pt1 *pt1) +{ +struct i2c_client *cl; +u8 buf[2 ] = {0x01 ,0x80 }; +int ret; +int i; + +/* reset all terr. & sat. pairs first */ +for (i =0 ; i <PT1_NR_ADAPS ; i++) { + cl = pt1->adaps[i]->demod_i2c_client; +if (strncmp (cl->name,TC90522_I2C_DEV_TER , +strlen (TC90522_I2C_DEV_TER ))) +continue ; + + ret =i2c_master_send (cl, buf,2 ); +if (ret <0 ) +return ret; +usleep_range (30000 ,50000 ); + } + +for (i =0 ; i <PT1_NR_ADAPS ; i++) { + cl = pt1->adaps[i]->demod_i2c_client; +if (strncmp (cl->name,TC90522_I2C_DEV_SAT , +strlen (TC90522_I2C_DEV_SAT ))) +continue ; + + ret =i2c_master_send (cl, buf,2 ); +if (ret <0 ) +return ret; +usleep_range (30000 ,50000 ); + } +return 0 ; +} +static void pt1_write_reg (struct pt1 *pt1,int reg,u32 data) {writel (data, pt1->regs + reg *4 );
@@ -987,6 +1021,10 @@ static int pt1_init_frontends(struct pt1 *pt1) goto tuner_release; } + ret =pt1_demod_block_init (pt1); +if (ret <0 ) + goto fe_unregister; +return 0 ; tuner_release:
@@ -1245,6 +1283,10 @@ static int pt1_resume(struct device *dev)pt1_update_power (pt1);usleep_range (1000 ,2000 ); + ret =pt1_demod_block_init (pt1); +if (ret <0 ) + goto resume_err; +for (i =0 ; i <PT1_NR_ADAPS ; i++)dvb_frontend_reinitialise (pt1->adaps[i]->fe);
Signature · 1 line
2.20.1
Hello,
Thank you for your patch.
Quoted 73 lines · On Thu, Jan 10, 2019 at 06:56:23PM +0900, [email protected] wrote:
From: Akihiro Tsukada <[email protected]>
earth-pt1 driver was decomposed/restructured by the commit:
b732539efdba("media: dvb: earth-pt1: decompose pt1 driver into sub drivers"), but it introduced a problem regarding concurrent streaming:
Opening a new terrestial stream stops the reception of an existing, already-opened satellite stream.The demod IC in earth-pt1 boards contains 2 pairs of terr. and sat. blocks, supporting 4 concurrent demodulations, and the above problem was because the config of a terr. block contained whole reset/init of the pair blocks, thus each
open()of a terrestrial frontend wrongly cleared the config of its peer satellite block of the demod.
This whole/pair reset should be executed earlier and not on eachopen().Fixes b732539efdba ("media: dvb: earth-pt1: decompose pt1 driver into sub drivers")Signed-off-by Akihiro Tsukada <[email protected]>--- drivers/media/pci/pt1/pt1.c | 54 ++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-)drivers/media/pci/pt1/pt1.c +27
-6@@ -200,16 +200,10 @@ static const u8 va1j5jf8007t_25mhz_configs[][2] = {static int config_demod (struct i2c_client *cl,enum pt1_fe_clk clk) {int ret; -u8 buf[2 ] = {0x01 ,0x80 };bool is_sat;const u8 (*cfg_data)[2 ];int i, len; - ret =i2c_master_send (cl, buf,2 ); -if (ret <0 ) -return ret; -usleep_range (30000 ,50000 ); - is_sat = !strncmp (cl->name,TC90522_I2C_DEV_SAT ,strlen (TC90522_I2C_DEV_SAT ));if (is_sat) {@@ -260,6 +254,46 @@ static int config_demod(struct i2c_client *cl, enum pt1_fe_clk clk)return 0 ; } +/* +* Init registers for (each pair of) terrestrial/satellite block in demod. +* Note that resetting terr. block also resets its peer sat. block as well. +* This function must be called before configuring any demod block +* (before pt1_wakeup(), fe->ops.init()). +*/ +static int pt1_demod_block_init (struct pt1 *pt1) +{ +struct i2c_client *cl; +u8 buf[2 ] = {0x01 ,0x80 }; +int ret; +int i; + +/* reset all terr. & sat. pairs first */ +for (i =0 ; i <PT1_NR_ADAPS ; i++) { + cl = pt1->adaps[i]->demod_i2c_client; +if (strncmp (cl->name,TC90522_I2C_DEV_TER , +strlen (TC90522_I2C_DEV_TER ))) +continue ; + + ret =i2c_master_send (cl, buf,2 ); +if (ret <0 ) +return ret; +usleep_range (30000 ,50000 ); + } + +for (i =0 ; i <PT1_NR_ADAPS ; i++) {
drivers/media/pci/pt1/pt1.c static int config_demod(struct i2c_client *cl, enum pt1_fe_clk clk) · line 293
Quoted 10 lines
drivers/media/pci/pt1/pt1.c +10
-0+ cl = pt1->adaps[i]->demod_i2c_client; +if (strncmp (cl->name,TC90522_I2C_DEV_SAT , +strlen (TC90522_I2C_DEV_SAT ))) +continue ; + + ret =i2c_master_send (cl, buf,2 ); +if (ret <0 ) +return ret; +usleep_range (30000 ,50000 ); + }
It might be possible to simplify the code a little by using strcmp() and making it into one loop, like so:
for (i = 0; i < PT1_NR_ADAPS; i++) {
cl = pt1->adaps[i]->demod_i2c_client;
if (strcmp(cl->name, TC90522_I2C_DEV_SAT) &&
strcmp(cl->name, TC90522_I2C_DEV_TER))
continue;
ret = i2c_master_send(cl, buf, 2);
if (ret < 0)
return ret;
usleep_range(30000, 50000);
}Quoted 30 lines
drivers/media/pci/pt1/pt1.c +11
-0+return 0 ; +} +static void pt1_write_reg (struct pt1 *pt1,int reg,u32 data) {writel (data, pt1->regs + reg *4 );@@ -987,6 +1021,10 @@ static int pt1_init_frontends(struct pt1 *pt1) goto tuner_release; } + ret =pt1_demod_block_init (pt1); +if (ret <0 ) + goto fe_unregister; +return 0 ; tuner_release:@@ -1245,6 +1283,10 @@ static int pt1_resume(struct device *dev)pt1_update_power (pt1);usleep_range (1000 ,2000 ); + ret =pt1_demod_block_init (pt1); +if (ret <0 ) + goto resume_err; +for (i =0 ; i <PT1_NR_ADAPS ; i++)dvb_frontend_reinitialise (pt1->adaps[i]->fe);Signature · 1 line
2.20.1
Many thanks,
Sean