summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkihiro Tsukada <tskd08@gmail.com>2019-01-10 04:56:23 -0500
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2019-03-04 06:17:02 -0500
commit15d90a6ae98e6d2c68497b44a491cb9efbb98ab1 (patch)
treed6bfba0ebc361a937d5bf0045fe24057c21998d7
parentc310d1f97c94f68eb4b3860933b2e977c6b0cf5b (diff)
media: dvb/earth-pt1: fix wrong initialization for demod blocks
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(). Fixes: b732539efdba ("media: dvb: earth-pt1: decompose pt1 driver into sub drivers") Signed-off-by: Akihiro Tsukada <tskd08@gmail.com> Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r--drivers/media/pci/pt1/pt1.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c
index f4b8030e2369..393f4c596819 100644
--- a/drivers/media/pci/pt1/pt1.c
+++ b/drivers/media/pci/pt1/pt1.c
@@ -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);