diff mbox series

[v2,7/7,media] tvp5150: add s_power callback

Message ID 20180813092508.1334-8-m.felsch@pengutronix.de (mailing list archive)
State New, archived
Headers show
Series TVP5150 fixes and new features | expand

Commit Message

Marco Felsch Aug. 13, 2018, 9:25 a.m. UTC
Don't en-/disable the interrupts during s_stream because someone can
disable the stream but wants to get informed if the stream is locked
again. So keep the interrupts enabled the whole time the pipeline is
opened.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/media/i2c/tvp5150.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

Comments

Sakari Ailus Sept. 14, 2018, 1:23 p.m. UTC | #1
Hi Marco,

On Mon, Aug 13, 2018 at 11:25:08AM +0200, Marco Felsch wrote:
> Don't en-/disable the interrupts during s_stream because someone can
> disable the stream but wants to get informed if the stream is locked
> again. So keep the interrupts enabled the whole time the pipeline is
> opened.
> 
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
>  drivers/media/i2c/tvp5150.c | 23 +++++++++++++++++------
>  1 file changed, 17 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> index e736f609fecd..e296f5bfae21 100644
> --- a/drivers/media/i2c/tvp5150.c
> +++ b/drivers/media/i2c/tvp5150.c
> @@ -1389,11 +1389,26 @@ static const struct media_entity_operations tvp5150_sd_media_ops = {
>  /****************************************************************************
>  			I2C Command
>   ****************************************************************************/
> +static int tvp5150_s_power(struct  v4l2_subdev *sd, int on)
> +{
> +	struct tvp5150 *decoder = to_tvp5150(sd);
> +	unsigned int val = 0;
> +
> +	if (on)
> +		val = TVP5150_INT_A_LOCK;
> +
> +	if (decoder->irq)
> +		/* Enable / Disable lock interrupt */
> +		regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
> +				   TVP5150_INT_A_LOCK, val);

Could you use runtime PM instead?

For an example, the dw9714 driver does this: drivers/media/i2c/dw9714.c .

> +
> +	return 0;
> +}
>  
>  static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
>  {
>  	struct tvp5150 *decoder = to_tvp5150(sd);
> -	unsigned int mask, val = 0, int_val = 0;
> +	unsigned int mask, val = 0;
>  
>  	mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
>  	       TVP5150_MISC_CTL_CLOCK_OE;
> @@ -1406,15 +1421,10 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
>  			val = decoder->lock ? decoder->oe : 0;
>  		else
>  			val = decoder->oe;
> -		int_val = TVP5150_INT_A_LOCK;
>  		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
>  	}
>  
>  	regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val);
> -	if (decoder->irq)
> -		/* Enable / Disable lock interrupt */
> -		regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
> -				   TVP5150_INT_A_LOCK, int_val);
>  
>  	return 0;
>  }
> @@ -1616,6 +1626,7 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = {
>  	.g_register = tvp5150_g_register,
>  	.s_register = tvp5150_s_register,
>  #endif
> +	.s_power = tvp5150_s_power,
>  };
>  
>  static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
Marco Felsch Sept. 14, 2018, 6:20 p.m. UTC | #2
Hi Sakari,

On 18-09-14 16:23, Sakari Ailus wrote:
> Hi Marco,
> 
> On Mon, Aug 13, 2018 at 11:25:08AM +0200, Marco Felsch wrote:
> > Don't en-/disable the interrupts during s_stream because someone can
> > disable the stream but wants to get informed if the stream is locked
> > again. So keep the interrupts enabled the whole time the pipeline is
> > opened.
> > 
> > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > ---
> >  drivers/media/i2c/tvp5150.c | 23 +++++++++++++++++------
> >  1 file changed, 17 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > index e736f609fecd..e296f5bfae21 100644
> > --- a/drivers/media/i2c/tvp5150.c
> > +++ b/drivers/media/i2c/tvp5150.c
> > @@ -1389,11 +1389,26 @@ static const struct media_entity_operations tvp5150_sd_media_ops = {
> >  /****************************************************************************
> >  			I2C Command
> >   ****************************************************************************/
> > +static int tvp5150_s_power(struct  v4l2_subdev *sd, int on)
> > +{
> > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > +	unsigned int val = 0;
> > +
> > +	if (on)
> > +		val = TVP5150_INT_A_LOCK;
> > +
> > +	if (decoder->irq)
> > +		/* Enable / Disable lock interrupt */
> > +		regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
> > +				   TVP5150_INT_A_LOCK, val);
> 
> Could you use runtime PM instead?

I will test it next monday. What's the different between s_power and
runtime PM?

> 
> For an example, the dw9714 driver does this: drivers/media/i2c/dw9714.c .

Hopefully I got you right, should I use the
v4l2_subdev_internal_ops.open/close and call the pm_runtime_put/get
there or did you mean the driver.pm callbacks? I'm not that familiar
with the pm ops at the moment, sorry.

Regards,
Marco

> > +
> > +	return 0;
> > +}
> >  
> >  static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> >  {
> >  	struct tvp5150 *decoder = to_tvp5150(sd);
> > -	unsigned int mask, val = 0, int_val = 0;
> > +	unsigned int mask, val = 0;
> >  
> >  	mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
> >  	       TVP5150_MISC_CTL_CLOCK_OE;
> > @@ -1406,15 +1421,10 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
> >  			val = decoder->lock ? decoder->oe : 0;
> >  		else
> >  			val = decoder->oe;
> > -		int_val = TVP5150_INT_A_LOCK;
> >  		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
> >  	}
> >  
> >  	regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val);
> > -	if (decoder->irq)
> > -		/* Enable / Disable lock interrupt */
> > -		regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
> > -				   TVP5150_INT_A_LOCK, int_val);
> >  
> >  	return 0;
> >  }
> > @@ -1616,6 +1626,7 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = {
> >  	.g_register = tvp5150_g_register,
> >  	.s_register = tvp5150_s_register,
> >  #endif
> > +	.s_power = tvp5150_s_power,
> >  };
> >  
> >  static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
> 
> -- 
> Kind regards,
> 
> Sakari Ailus
> sakari.ailus@linux.intel.com
>
Mauro Carvalho Chehab Sept. 14, 2018, 6:57 p.m. UTC | #3
Em Fri, 14 Sep 2018 20:20:46 +0200
Marco Felsch <m.felsch@pengutronix.de> escreveu:

> Hi Sakari,
> 
> On 18-09-14 16:23, Sakari Ailus wrote:
> > Hi Marco,
> > 
> > On Mon, Aug 13, 2018 at 11:25:08AM +0200, Marco Felsch wrote:  
> > > Don't en-/disable the interrupts during s_stream because someone can
> > > disable the stream but wants to get informed if the stream is locked
> > > again. So keep the interrupts enabled the whole time the pipeline is
> > > opened.
> > > 
> > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > ---
> > >  drivers/media/i2c/tvp5150.c | 23 +++++++++++++++++------
> > >  1 file changed, 17 insertions(+), 6 deletions(-)
> > > 
> > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > index e736f609fecd..e296f5bfae21 100644
> > > --- a/drivers/media/i2c/tvp5150.c
> > > +++ b/drivers/media/i2c/tvp5150.c
> > > @@ -1389,11 +1389,26 @@ static const struct media_entity_operations tvp5150_sd_media_ops = {
> > >  /****************************************************************************
> > >  			I2C Command
> > >   ****************************************************************************/
> > > +static int tvp5150_s_power(struct  v4l2_subdev *sd, int on)
> > > +{
> > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > +	unsigned int val = 0;
> > > +
> > > +	if (on)
> > > +		val = TVP5150_INT_A_LOCK;
> > > +
> > > +	if (decoder->irq)
> > > +		/* Enable / Disable lock interrupt */
> > > +		regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
> > > +				   TVP5150_INT_A_LOCK, val);  
> > 
> > Could you use runtime PM instead?  
> 
> I will test it next monday. What's the different between s_power and
> runtime PM?
> 
> > 
> > For an example, the dw9714 driver does this: drivers/media/i2c/dw9714.c .  
> 
> Hopefully I got you right, should I use the
> v4l2_subdev_internal_ops.open/close and call the pm_runtime_put/get
> there or did you mean the driver.pm callbacks? I'm not that familiar
> with the pm ops at the moment, sorry.

I guess the main issue here is: will this work if the bridge
driver is em28xx?

Whatever change we do, tvp5150 should still fully work with em28xx,
as several devices use this demod there.

Changing em28xx to cope with runtime PM would be *very* complex,
as there are lots of other drivers that can work with it, and
touching those will affect lots of other drivers. At the end, it
will very likely affect all PCI/PCIe V4L2 drivers, and several
USB ones.

If it can be done without affecting PM with em28xx, let's do it.
Otherwise, let's stick with s_power on this series, and let 
the mass PM rework on non-platform drivers to happen on some
separate patchset.

Thanks,
Mauro
Marco Felsch Sept. 18, 2018, 9:51 a.m. UTC | #4
Hi,

On 18-09-14 15:57, Mauro Carvalho Chehab wrote:
> Em Fri, 14 Sep 2018 20:20:46 +0200
> Marco Felsch <m.felsch@pengutronix.de> escreveu:
> 
> > Hi Sakari,
> > 
> > On 18-09-14 16:23, Sakari Ailus wrote:
> > > Hi Marco,
> > > 
> > > On Mon, Aug 13, 2018 at 11:25:08AM +0200, Marco Felsch wrote:  
> > > > Don't en-/disable the interrupts during s_stream because someone can
> > > > disable the stream but wants to get informed if the stream is locked
> > > > again. So keep the interrupts enabled the whole time the pipeline is
> > > > opened.
> > > > 
> > > > Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> > > > ---
> > > >  drivers/media/i2c/tvp5150.c | 23 +++++++++++++++++------
> > > >  1 file changed, 17 insertions(+), 6 deletions(-)
> > > > 
> > > > diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
> > > > index e736f609fecd..e296f5bfae21 100644
> > > > --- a/drivers/media/i2c/tvp5150.c
> > > > +++ b/drivers/media/i2c/tvp5150.c
> > > > @@ -1389,11 +1389,26 @@ static const struct media_entity_operations tvp5150_sd_media_ops = {
> > > >  /****************************************************************************
> > > >  			I2C Command
> > > >   ****************************************************************************/
> > > > +static int tvp5150_s_power(struct  v4l2_subdev *sd, int on)
> > > > +{
> > > > +	struct tvp5150 *decoder = to_tvp5150(sd);
> > > > +	unsigned int val = 0;
> > > > +
> > > > +	if (on)
> > > > +		val = TVP5150_INT_A_LOCK;
> > > > +
> > > > +	if (decoder->irq)
> > > > +		/* Enable / Disable lock interrupt */
> > > > +		regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
> > > > +				   TVP5150_INT_A_LOCK, val);  
> > > 
> > > Could you use runtime PM instead?  
> > 
> > I will test it next monday. What's the different between s_power and
> > runtime PM?
> > 
> > > 
> > > For an example, the dw9714 driver does this: drivers/media/i2c/dw9714.c .  
> > 
> > Hopefully I got you right, should I use the
> > v4l2_subdev_internal_ops.open/close and call the pm_runtime_put/get
> > there or did you mean the driver.pm callbacks? I'm not that familiar
> > with the pm ops at the moment, sorry.

I did some tests with the PM runtime ops. I used the suspend() callback
to disbale the IRQ and the resume() callback to enable it. But this
won't work with my IRQ-driven setup because if the signal is not locked
(maybe lost due to no input stream) the tvp went into suspend. In this
mode the IRQ is disabled and I have no chance to enable the chip again.

As Mauro pointed out below, there maybe some other issues I can't test
at the moment. I'm with Mauro to keep the .s_power() callback for this
series. There should be another patchset which covers the PM rework for
all devices using the TVP5150.

> 
> I guess the main issue here is: will this work if the bridge
> driver is em28xx?
> 
> Whatever change we do, tvp5150 should still fully work with em28xx,
> as several devices use this demod there.
> 
> Changing em28xx to cope with runtime PM would be *very* complex,
> as there are lots of other drivers that can work with it, and
> touching those will affect lots of other drivers. At the end, it
> will very likely affect all PCI/PCIe V4L2 drivers, and several
> USB ones.
> 
> If it can be done without affecting PM with em28xx, let's do it.
> Otherwise, let's stick with s_power on this series, and let 
> the mass PM rework on non-platform drivers to happen on some
> separate patchset.
> 
> Thanks,
> Mauro
> 

Kind regards,
Marco
diff mbox series

Patch

diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index e736f609fecd..e296f5bfae21 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -1389,11 +1389,26 @@  static const struct media_entity_operations tvp5150_sd_media_ops = {
 /****************************************************************************
 			I2C Command
  ****************************************************************************/
+static int tvp5150_s_power(struct  v4l2_subdev *sd, int on)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	unsigned int val = 0;
+
+	if (on)
+		val = TVP5150_INT_A_LOCK;
+
+	if (decoder->irq)
+		/* Enable / Disable lock interrupt */
+		regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
+				   TVP5150_INT_A_LOCK, val);
+
+	return 0;
+}
 
 static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
-	unsigned int mask, val = 0, int_val = 0;
+	unsigned int mask, val = 0;
 
 	mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
 	       TVP5150_MISC_CTL_CLOCK_OE;
@@ -1406,15 +1421,10 @@  static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 			val = decoder->lock ? decoder->oe : 0;
 		else
 			val = decoder->oe;
-		int_val = TVP5150_INT_A_LOCK;
 		v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt);
 	}
 
 	regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val);
-	if (decoder->irq)
-		/* Enable / Disable lock interrupt */
-		regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
-				   TVP5150_INT_A_LOCK, int_val);
 
 	return 0;
 }
@@ -1616,6 +1626,7 @@  static const struct v4l2_subdev_core_ops tvp5150_core_ops = {
 	.g_register = tvp5150_g_register,
 	.s_register = tvp5150_s_register,
 #endif
+	.s_power = tvp5150_s_power,
 };
 
 static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {