On Sat, Dec 29, 2018 at 11:51:16AM -0600, Brad Love wrote: > Some software reports no signal found on a frequency due to immediately > checking for lock as soon as set_params returns. This waits up 40ms for > tuning operation, then from 30-150ms (dig/analog) for signal lock before > returning from set_params and set_analog_params. > > Tuning typically completes in 20-30ms. Digital tuning will additionally > wait depending on signal characteristics. Analog tuning will wait the > full timeout in case of no signal. This looks like a workaround for broken userspace. Very possibly this is software was tested on a different frontend which does wait for tuning to complete. This is a change in uapi and will have to be done for all frontends, and documented. However I doubt such a change is acceptable. What software are you refering to? Sean > > Signed-off-by: Brad Love <brad@xxxxxxxxxxxxxxxx> > --- > drivers/media/tuners/si2157.c | 87 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 87 insertions(+) > > diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c > index ff462ba..1737007 100644 > --- a/drivers/media/tuners/si2157.c > +++ b/drivers/media/tuners/si2157.c > @@ -318,6 +318,89 @@ static int si2157_sleep(struct dvb_frontend *fe) > return ret; > } > > +static int si2157_tune_wait(struct i2c_client *client, u8 is_digital) > +{ > +#define TUN_TIMEOUT 40 > +#define DIG_TIMEOUT 30 > +#define ANALOG_TIMEOUT 150 > + struct si2157_dev *dev = i2c_get_clientdata(client); > + int ret; > + unsigned long timeout; > + unsigned long start_time; > + u8 wait_status; > + u8 tune_lock_mask; > + > + if (is_digital) > + tune_lock_mask = 0x04; > + else > + tune_lock_mask = 0x02; > + > + mutex_lock(&dev->i2c_mutex); > + > + /* wait tuner command complete */ > + start_time = jiffies; > + timeout = start_time + msecs_to_jiffies(TUN_TIMEOUT); > + while (!time_after(jiffies, timeout)) { > + ret = i2c_master_recv(client, &wait_status, > + sizeof(wait_status)); > + if (ret < 0) { > + goto err_mutex_unlock; > + } else if (ret != sizeof(wait_status)) { > + ret = -EREMOTEIO; > + goto err_mutex_unlock; > + } > + > + /* tuner done? */ > + if ((wait_status & 0x81) == 0x81) > + break; > + usleep_range(5000, 10000); > + } > + > + dev_dbg(&client->dev, "tuning took %d ms, status=0x%x\n", > + jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time), > + wait_status); > + > + /* if we tuned ok, wait a bit for tuner lock */ > + if ((wait_status & 0x81) == 0x81) { > + if (is_digital) > + timeout = jiffies + msecs_to_jiffies(DIG_TIMEOUT); > + else > + timeout = jiffies + msecs_to_jiffies(ANALOG_TIMEOUT); > + while (!time_after(jiffies, timeout)) { > + ret = i2c_master_recv(client, &wait_status, > + sizeof(wait_status)); > + if (ret < 0) { > + goto err_mutex_unlock; > + } else if (ret != sizeof(wait_status)) { > + ret = -EREMOTEIO; > + goto err_mutex_unlock; > + } > + > + /* tuner locked? */ > + if (wait_status & tune_lock_mask) > + break; > + usleep_range(5000, 10000); > + } > + } > + > + dev_dbg(&client->dev, "tuning+lock took %d ms, status=0x%x\n", > + jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time), > + wait_status); > + > + if ((wait_status & 0xc0) != 0x80) { > + ret = -ETIMEDOUT; > + goto err_mutex_unlock; > + } > + > + mutex_unlock(&dev->i2c_mutex); > + return 0; > + > +err_mutex_unlock: > + mutex_unlock(&dev->i2c_mutex); > + dev_dbg(&client->dev, "failed=%d\n", ret); > + return ret; > +} > + > static int si2157_set_params(struct dvb_frontend *fe) > { > struct i2c_client *client = fe->tuner_priv; > @@ -417,6 +500,8 @@ static int si2157_set_params(struct dvb_frontend *fe) > dev->bandwidth = bandwidth; > dev->frequency = c->frequency; > > + si2157_tune_wait(client, 1); /* wait to complete, ignore any errors */ > + > return 0; > err: > dev->bandwidth = 0; > @@ -626,6 +711,8 @@ static int si2157_set_analog_params(struct dvb_frontend *fe, > #endif > dev->bandwidth = bandwidth; > > + si2157_tune_wait(client, 0); /* wait to complete, ignore any errors */ > + > return 0; > err: > dev->bandwidth = 0; > -- > 2.7.4