diff mbox

[2/5] pcm990 baseboard: add camera bus width switch setting

Message ID 20090312141819.GN425@pengutronix.de (mailing list archive)
State RFC
Headers show

Commit Message

Sascha Hauer March 12, 2009, 2:18 p.m. UTC
On Thu, Mar 12, 2009 at 02:12:09PM +0100, Guennadi Liakhovetski wrote:
> On Thu, 12 Mar 2009, Sascha Hauer wrote:
> 
> > Some Phytec cameras have a I2C GPIO expander which allows it to
> > switch between different sensor bus widths. This was previously
> > handled in the camera driver. Since handling of this switch
> > varies on several boards the cameras are used on, the board
> > support seems a better place to handle the switch
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm/mach-pxa/pcm990-baseboard.c |   49 +++++++++++++++++++++++++++------
> >  1 files changed, 40 insertions(+), 9 deletions(-)
> > 
> > diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
> > index 34841c7..8b01565 100644
> > --- a/arch/arm/mach-pxa/pcm990-baseboard.c
> > +++ b/arch/arm/mach-pxa/pcm990-baseboard.c
> > @@ -381,14 +381,45 @@ static struct pca953x_platform_data pca9536_data = {
> >  	.gpio_base	= NR_BUILTIN_GPIO + 1,
> >  };
> >  
> > -static struct soc_camera_link iclink[] = {
> > -	{
> > -		.bus_id	= 0, /* Must match with the camera ID above */
> > -		.gpio	= NR_BUILTIN_GPIO + 1,
> > -	}, {
> > -		.bus_id	= 0, /* Must match with the camera ID above */
> > -		.gpio	= -ENXIO,
> > +static int gpio_bus_switch;
> > +
> > +static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
> > +		unsigned long flags)
> > +{
> > +	if (gpio_bus_switch <= 0)
> > +		return 0;
> 
> Are you really sure you don't want to return an error here? In 
> query_bus_param() below, if you fail to get the GPIO, you set 
> gpio_bus_switch to -EINVAL and return only 10 bit. Now if a buggy host 
> driver still requests 8 bits, mt9m001 will call ->set_bus_param and you 
> will happily return 0...
> 

Of course there are no buggy host drivers ;)

Ok, changed it to support only ten bit without gpio switch and return
-EINVAL for any other width.

Sasche


From 58485f136579273d4da41d65974ce6ed02ba877a Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Tue, 10 Mar 2009 16:45:58 +0100
Subject: [PATCH 2/5] pcm990 baseboard: add camera bus width switch setting

Some Phytec cameras have a I2C GPIO expander which allows it to
switch between different sensor bus widths. This was previously
handled in the camera driver. Since handling of this switch
varies on several boards the cameras are used on, the board
support seems a better place to handle the switch

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-pxa/pcm990-baseboard.c |   53 ++++++++++++++++++++++++++++------
 1 files changed, 44 insertions(+), 9 deletions(-)

Comments

Guennadi Liakhovetski April 9, 2009, 9:44 p.m. UTC | #1
Hi Sascha,

something, that skipped both of us:

On Thu, 12 Mar 2009, Sascha Hauer wrote:

> Some Phytec cameras have a I2C GPIO expander which allows it to
> switch between different sensor bus widths. This was previously
> handled in the camera driver. Since handling of this switch
> varies on several boards the cameras are used on, the board
> support seems a better place to handle the switch
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm/mach-pxa/pcm990-baseboard.c |   53 ++++++++++++++++++++++++++++------
>  1 files changed, 44 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
> index 34841c7..fd8f786 100644
> --- a/arch/arm/mach-pxa/pcm990-baseboard.c
> +++ b/arch/arm/mach-pxa/pcm990-baseboard.c
> @@ -381,14 +381,49 @@ static struct pca953x_platform_data pca9536_data = {
>  	.gpio_base	= NR_BUILTIN_GPIO + 1,
>  };
>  
> -static struct soc_camera_link iclink[] = {
> -	{
> -		.bus_id	= 0, /* Must match with the camera ID above */
> -		.gpio	= NR_BUILTIN_GPIO + 1,
> -	}, {
> -		.bus_id	= 0, /* Must match with the camera ID above */
> -		.gpio	= -ENXIO,
> +static int gpio_bus_switch;
> +
> +static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
> +		unsigned long flags)
> +{
> +	if (gpio_bus_switch <= 0) {
> +		if (flags == SOCAM_DATAWIDTH_10)
> +			return 0;
> +		else
> +			return -EINVAL;
> +	}
> +
> +	if (flags & SOCAM_DATAWIDTH_8)
> +		gpio_set_value(gpio_bus_switch, 1);
> +	else
> +		gpio_set_value(gpio_bus_switch, 0);
> +
> +	return 0;
> +}
> +
> +static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
> +{
> +	int ret;
> +
> +	if (!gpio_bus_switch) {
> +		ret = gpio_request(NR_BUILTIN_GPIO + 1, "camera");

There's no gpio_free() now... So, for example, you cannot unload the 
extender driver any more, unloading i2c adapter driver (i2c-pxa) produces 
ugly stuff like

pca953x 0-0041: gpiochip_remove() failed, -16

So, we either have to request and free the GPIO in each query / set, or we 
need an explicit .free_bus() call in soc_camera_link. None of the two 
really pleases me, but maybe the latter is slightly less ugly, what do you 
think?

Thanks
Guennadi

> +		if (!ret) {
> +			gpio_bus_switch = NR_BUILTIN_GPIO + 1;
> +			gpio_direction_output(gpio_bus_switch, 0);
> +		} else
> +			gpio_bus_switch = -EINVAL;
>  	}
> +
> +	if (gpio_bus_switch > 0)
> +		return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
> +	else
> +		return SOCAM_DATAWIDTH_10;
> +}
> +
> +static struct soc_camera_link iclink = {
> +	.bus_id	= 0, /* Must match with the camera ID above */
> +	.query_bus_param = pcm990_camera_query_bus_param,
> +	.set_bus_param = pcm990_camera_set_bus_param,
>  };
>  
>  /* Board I2C devices. */
> @@ -399,10 +434,10 @@ static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
>  		.platform_data = &pca9536_data,
>  	}, {
>  		I2C_BOARD_INFO("mt9v022", 0x48),
> -		.platform_data = &iclink[0], /* With extender */
> +		.platform_data = &iclink, /* With extender */
>  	}, {
>  		I2C_BOARD_INFO("mt9m001", 0x5d),
> -		.platform_data = &iclink[0], /* With extender */
> +		.platform_data = &iclink, /* With extender */
>  	},
>  };
>  #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
> -- 
> 1.5.6.5
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Guennadi Liakhovetski April 14, 2009, 8:57 a.m. UTC | #2
On Thu, 9 Apr 2009, Guennadi Liakhovetski wrote:

> Hi Sascha,
> 
> something, that skipped both of us:

...and one more:

> On Thu, 12 Mar 2009, Sascha Hauer wrote:
> 
> > Some Phytec cameras have a I2C GPIO expander which allows it to
> > switch between different sensor bus widths. This was previously
> > handled in the camera driver. Since handling of this switch
> > varies on several boards the cameras are used on, the board
> > support seems a better place to handle the switch
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm/mach-pxa/pcm990-baseboard.c |   53 ++++++++++++++++++++++++++++------
> >  1 files changed, 44 insertions(+), 9 deletions(-)
> > 
> > diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
> > index 34841c7..fd8f786 100644
> > --- a/arch/arm/mach-pxa/pcm990-baseboard.c
> > +++ b/arch/arm/mach-pxa/pcm990-baseboard.c
> > @@ -381,14 +381,49 @@ static struct pca953x_platform_data pca9536_data = {
> >  	.gpio_base	= NR_BUILTIN_GPIO + 1,
> >  };
> >  
> > -static struct soc_camera_link iclink[] = {
> > -	{
> > -		.bus_id	= 0, /* Must match with the camera ID above */
> > -		.gpio	= NR_BUILTIN_GPIO + 1,
> > -	}, {
> > -		.bus_id	= 0, /* Must match with the camera ID above */
> > -		.gpio	= -ENXIO,
> > +static int gpio_bus_switch;
> > +
> > +static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
> > +		unsigned long flags)
> > +{
> > +	if (gpio_bus_switch <= 0) {
> > +		if (flags == SOCAM_DATAWIDTH_10)
> > +			return 0;
> > +		else
> > +			return -EINVAL;
> > +	}
> > +
> > +	if (flags & SOCAM_DATAWIDTH_8)
> > +		gpio_set_value(gpio_bus_switch, 1);
> > +	else
> > +		gpio_set_value(gpio_bus_switch, 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
> > +{
> > +	int ret;
> > +
> > +	if (!gpio_bus_switch) {
> > +		ret = gpio_request(NR_BUILTIN_GPIO + 1, "camera");
> 
> There's no gpio_free() now... So, for example, you cannot unload the 
> extender driver any more, unloading i2c adapter driver (i2c-pxa) produces 
> ugly stuff like
> 
> pca953x 0-0041: gpiochip_remove() failed, -16
> 
> So, we either have to request and free the GPIO in each query / set, or we 
> need an explicit .free_bus() call in soc_camera_link. None of the two 
> really pleases me, but maybe the latter is slightly less ugly, what do you 
> think?
> 
> Thanks
> Guennadi
> 
> > +		if (!ret) {
> > +			gpio_bus_switch = NR_BUILTIN_GPIO + 1;
> > +			gpio_direction_output(gpio_bus_switch, 0);
> > +		} else
> > +			gpio_bus_switch = -EINVAL;
> >  	}

If you first do not load pca953x and try to start capture, thus calling 
pcm990_camera_query_bus_param(), gpio_request() will fail and you get 
gpio_bus_switch < 0. Then if you load pca953x it doesn't help any more - 
by testing for "if (!gpio_bus_switch)" you do not retry after the first 
error.

Thanks
Guennadi

> > +
> > +	if (gpio_bus_switch > 0)
> > +		return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
> > +	else
> > +		return SOCAM_DATAWIDTH_10;
> > +}
> > +
> > +static struct soc_camera_link iclink = {
> > +	.bus_id	= 0, /* Must match with the camera ID above */
> > +	.query_bus_param = pcm990_camera_query_bus_param,
> > +	.set_bus_param = pcm990_camera_set_bus_param,
> >  };
> >  
> >  /* Board I2C devices. */
> > @@ -399,10 +434,10 @@ static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
> >  		.platform_data = &pca9536_data,
> >  	}, {
> >  		I2C_BOARD_INFO("mt9v022", 0x48),
> > -		.platform_data = &iclink[0], /* With extender */
> > +		.platform_data = &iclink, /* With extender */
> >  	}, {
> >  		I2C_BOARD_INFO("mt9m001", 0x5d),
> > -		.platform_data = &iclink[0], /* With extender */
> > +		.platform_data = &iclink, /* With extender */
> >  	},
> >  };
> >  #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
> > -- 
> > 1.5.6.5
> > 
> > -- 
> > Pengutronix e.K.                           |                             |
> > Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> > Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> > Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> > 
> 
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sascha Hauer April 14, 2009, 9:10 a.m. UTC | #3
On Tue, Apr 14, 2009 at 10:57:32AM +0200, Guennadi Liakhovetski wrote:
> On Thu, 9 Apr 2009, Guennadi Liakhovetski wrote:
> 
> > Hi Sascha,
> > 
> > something, that skipped both of us:
> 
> ...and one more:
> 
> > On Thu, 12 Mar 2009, Sascha Hauer wrote:
> > 
> > > Some Phytec cameras have a I2C GPIO expander which allows it to
> > > switch between different sensor bus widths. This was previously
> > > handled in the camera driver. Since handling of this switch
> > > varies on several boards the cameras are used on, the board
> > > support seems a better place to handle the switch
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  arch/arm/mach-pxa/pcm990-baseboard.c |   53 ++++++++++++++++++++++++++++------
> > >  1 files changed, 44 insertions(+), 9 deletions(-)
> > > 
> > > diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
> > > index 34841c7..fd8f786 100644
> > > --- a/arch/arm/mach-pxa/pcm990-baseboard.c
> > > +++ b/arch/arm/mach-pxa/pcm990-baseboard.c
> > > @@ -381,14 +381,49 @@ static struct pca953x_platform_data pca9536_data = {
> > >  	.gpio_base	= NR_BUILTIN_GPIO + 1,
> > >  };
> > >  
> > > -static struct soc_camera_link iclink[] = {
> > > -	{
> > > -		.bus_id	= 0, /* Must match with the camera ID above */
> > > -		.gpio	= NR_BUILTIN_GPIO + 1,
> > > -	}, {
> > > -		.bus_id	= 0, /* Must match with the camera ID above */
> > > -		.gpio	= -ENXIO,
> > > +static int gpio_bus_switch;
> > > +
> > > +static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
> > > +		unsigned long flags)
> > > +{
> > > +	if (gpio_bus_switch <= 0) {
> > > +		if (flags == SOCAM_DATAWIDTH_10)
> > > +			return 0;
> > > +		else
> > > +			return -EINVAL;
> > > +	}
> > > +
> > > +	if (flags & SOCAM_DATAWIDTH_8)
> > > +		gpio_set_value(gpio_bus_switch, 1);
> > > +	else
> > > +		gpio_set_value(gpio_bus_switch, 0);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
> > > +{
> > > +	int ret;
> > > +
> > > +	if (!gpio_bus_switch) {
> > > +		ret = gpio_request(NR_BUILTIN_GPIO + 1, "camera");
> > 
> > There's no gpio_free() now... So, for example, you cannot unload the 
> > extender driver any more, unloading i2c adapter driver (i2c-pxa) produces 
> > ugly stuff like
> > 
> > pca953x 0-0041: gpiochip_remove() failed, -16
> > 
> > So, we either have to request and free the GPIO in each query / set, or we 
> > need an explicit .free_bus() call in soc_camera_link. None of the two 
> > really pleases me, but maybe the latter is slightly less ugly, what do you 
> > think?
> > 
> > Thanks
> > Guennadi
> > 
> > > +		if (!ret) {
> > > +			gpio_bus_switch = NR_BUILTIN_GPIO + 1;
> > > +			gpio_direction_output(gpio_bus_switch, 0);
> > > +		} else
> > > +			gpio_bus_switch = -EINVAL;
> > >  	}
> 
> If you first do not load pca953x and try to start capture, thus calling 
> pcm990_camera_query_bus_param(), gpio_request() will fail and you get 
> gpio_bus_switch < 0. Then if you load pca953x it doesn't help any more - 
> by testing for "if (!gpio_bus_switch)" you do not retry after the first 
> error.

So how do we proceed? Add init/exit functions for the bus?

Sascha

> 
> Thanks
> Guennadi
> 
> > > +
> > > +	if (gpio_bus_switch > 0)
> > > +		return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
> > > +	else
> > > +		return SOCAM_DATAWIDTH_10;
> > > +}
> > > +
> > > +static struct soc_camera_link iclink = {
> > > +	.bus_id	= 0, /* Must match with the camera ID above */
> > > +	.query_bus_param = pcm990_camera_query_bus_param,
> > > +	.set_bus_param = pcm990_camera_set_bus_param,
> > >  };
> > >  
> > >  /* Board I2C devices. */
> > > @@ -399,10 +434,10 @@ static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
> > >  		.platform_data = &pca9536_data,
> > >  	}, {
> > >  		I2C_BOARD_INFO("mt9v022", 0x48),
> > > -		.platform_data = &iclink[0], /* With extender */
> > > +		.platform_data = &iclink, /* With extender */
> > >  	}, {
> > >  		I2C_BOARD_INFO("mt9m001", 0x5d),
> > > -		.platform_data = &iclink[0], /* With extender */
> > > +		.platform_data = &iclink, /* With extender */
> > >  	},
> > >  };
> > >  #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
> > > -- 
> > > 1.5.6.5
> > > 
> > > -- 
> > > Pengutronix e.K.                           |                             |
> > > Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> > > Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> > > Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> > > 
> > 
> > ---
> > Guennadi Liakhovetski, Ph.D.
> > Freelance Open-Source Software Developer
> > 
> 
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
>
Guennadi Liakhovetski April 14, 2009, 9:20 a.m. UTC | #4
On Tue, 14 Apr 2009, Sascha Hauer wrote:

> On Tue, Apr 14, 2009 at 10:57:32AM +0200, Guennadi Liakhovetski wrote:
> > On Thu, 9 Apr 2009, Guennadi Liakhovetski wrote:

[snip]

> > > > +static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
> > > > +{
> > > > +	int ret;
> > > > +
> > > > +	if (!gpio_bus_switch) {
> > > > +		ret = gpio_request(NR_BUILTIN_GPIO + 1, "camera");
> > > 
> > > There's no gpio_free() now... So, for example, you cannot unload the 
> > > extender driver any more, unloading i2c adapter driver (i2c-pxa) produces 
> > > ugly stuff like
> > > 
> > > pca953x 0-0041: gpiochip_remove() failed, -16
> > > 
> > > So, we either have to request and free the GPIO in each query / set, or we 
> > > need an explicit .free_bus() call in soc_camera_link. None of the two 
> > > really pleases me, but maybe the latter is slightly less ugly, what do you 
> > > think?
> > > 
> > > Thanks
> > > Guennadi
> > > 
> > > > +		if (!ret) {
> > > > +			gpio_bus_switch = NR_BUILTIN_GPIO + 1;
> > > > +			gpio_direction_output(gpio_bus_switch, 0);
> > > > +		} else
> > > > +			gpio_bus_switch = -EINVAL;
> > > >  	}
> > 
> > If you first do not load pca953x and try to start capture, thus calling 
> > pcm990_camera_query_bus_param(), gpio_request() will fail and you get 
> > gpio_bus_switch < 0. Then if you load pca953x it doesn't help any more - 
> > by testing for "if (!gpio_bus_switch)" you do not retry after the first 
> > error.
> 
> So how do we proceed? Add init/exit functions for the bus?

If you don't object, I'll just add a .free_bus method to soc_camera_link, 
and switch pcm990 to only use two values: a negative value for a 
non-allocated gpio - either before the first attempt or after an error, 
thus re-trying every time if gpio is negative, in case a driver has been 
loaded in the meantime.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sascha Hauer April 14, 2009, 9:38 a.m. UTC | #5
On Tue, Apr 14, 2009 at 11:20:03AM +0200, Guennadi Liakhovetski wrote:
> On Tue, 14 Apr 2009, Sascha Hauer wrote:
> 
> > On Tue, Apr 14, 2009 at 10:57:32AM +0200, Guennadi Liakhovetski wrote:
> > > On Thu, 9 Apr 2009, Guennadi Liakhovetski wrote:
> 
> [snip]
> 
> > > > > +static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
> > > > > +{
> > > > > +	int ret;
> > > > > +
> > > > > +	if (!gpio_bus_switch) {
> > > > > +		ret = gpio_request(NR_BUILTIN_GPIO + 1, "camera");
> > > > 
> > > > There's no gpio_free() now... So, for example, you cannot unload the 
> > > > extender driver any more, unloading i2c adapter driver (i2c-pxa) produces 
> > > > ugly stuff like
> > > > 
> > > > pca953x 0-0041: gpiochip_remove() failed, -16
> > > > 
> > > > So, we either have to request and free the GPIO in each query / set, or we 
> > > > need an explicit .free_bus() call in soc_camera_link. None of the two 
> > > > really pleases me, but maybe the latter is slightly less ugly, what do you 
> > > > think?
> > > > 
> > > > Thanks
> > > > Guennadi
> > > > 
> > > > > +		if (!ret) {
> > > > > +			gpio_bus_switch = NR_BUILTIN_GPIO + 1;
> > > > > +			gpio_direction_output(gpio_bus_switch, 0);
> > > > > +		} else
> > > > > +			gpio_bus_switch = -EINVAL;
> > > > >  	}
> > > 
> > > If you first do not load pca953x and try to start capture, thus calling 
> > > pcm990_camera_query_bus_param(), gpio_request() will fail and you get 
> > > gpio_bus_switch < 0. Then if you load pca953x it doesn't help any more - 
> > > by testing for "if (!gpio_bus_switch)" you do not retry after the first 
> > > error.
> > 
> > So how do we proceed? Add init/exit functions for the bus?
> 
> If you don't object, I'll just add a .free_bus method to soc_camera_link, 
> and switch pcm990 to only use two values: a negative value for a 
> non-allocated gpio - either before the first attempt or after an error, 
> thus re-trying every time if gpio is negative, in case a driver has been 
> loaded in the meantime.

For the sake of symmetry, shouldn't we have an init function aswell?

Sascha
Guennadi Liakhovetski April 14, 2009, 9:53 a.m. UTC | #6
On Tue, 14 Apr 2009, Sascha Hauer wrote:

> On Tue, Apr 14, 2009 at 11:20:03AM +0200, Guennadi Liakhovetski wrote:
> > 
> > If you don't object, I'll just add a .free_bus method to soc_camera_link, 
> > and switch pcm990 to only use two values: a negative value for a 
> > non-allocated gpio - either before the first attempt or after an error, 
> > thus re-trying every time if gpio is negative, in case a driver has been 
> > loaded in the meantime.
> 
> For the sake of symmetry, shouldn't we have an init function aswell?

Well, for the sake of symmetry - yes, but I'm not sure we want to bloat 
this simple API further just to make it symmetric... You think it's worth 
it? Or do you have any "practical" reasons for that? Of course, we could 
also add a void *bus_resource to soc_camera_link and get rid of the static 
gpio_bus_switch and allocate it dynamically in .bus_init and free it in 
.bus_release, but...

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sascha Hauer April 14, 2009, 9:59 a.m. UTC | #7
On Tue, Apr 14, 2009 at 11:53:54AM +0200, Guennadi Liakhovetski wrote:
> On Tue, 14 Apr 2009, Sascha Hauer wrote:
> 
> > On Tue, Apr 14, 2009 at 11:20:03AM +0200, Guennadi Liakhovetski wrote:
> > > 
> > > If you don't object, I'll just add a .free_bus method to soc_camera_link, 
> > > and switch pcm990 to only use two values: a negative value for a 
> > > non-allocated gpio - either before the first attempt or after an error, 
> > > thus re-trying every time if gpio is negative, in case a driver has been 
> > > loaded in the meantime.
> > 
> > For the sake of symmetry, shouldn't we have an init function aswell?
> 
> Well, for the sake of symmetry - yes, but I'm not sure we want to bloat 
> this simple API further just to make it symmetric... You think it's worth 
> it? Or do you have any "practical" reasons for that? Of course, we could 
> also add a void *bus_resource to soc_camera_link and get rid of the static 
> gpio_bus_switch and allocate it dynamically in .bus_init and free it in 
> .bus_release, but...

No, I have no practical use for it at the moment. My feeling says it's
better to add it, but just follow your feelings instead of mine ;)

Sascha
diff mbox

Patch

diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 34841c7..fd8f786 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -381,14 +381,49 @@  static struct pca953x_platform_data pca9536_data = {
 	.gpio_base	= NR_BUILTIN_GPIO + 1,
 };
 
-static struct soc_camera_link iclink[] = {
-	{
-		.bus_id	= 0, /* Must match with the camera ID above */
-		.gpio	= NR_BUILTIN_GPIO + 1,
-	}, {
-		.bus_id	= 0, /* Must match with the camera ID above */
-		.gpio	= -ENXIO,
+static int gpio_bus_switch;
+
+static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
+		unsigned long flags)
+{
+	if (gpio_bus_switch <= 0) {
+		if (flags == SOCAM_DATAWIDTH_10)
+			return 0;
+		else
+			return -EINVAL;
+	}
+
+	if (flags & SOCAM_DATAWIDTH_8)
+		gpio_set_value(gpio_bus_switch, 1);
+	else
+		gpio_set_value(gpio_bus_switch, 0);
+
+	return 0;
+}
+
+static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
+{
+	int ret;
+
+	if (!gpio_bus_switch) {
+		ret = gpio_request(NR_BUILTIN_GPIO + 1, "camera");
+		if (!ret) {
+			gpio_bus_switch = NR_BUILTIN_GPIO + 1;
+			gpio_direction_output(gpio_bus_switch, 0);
+		} else
+			gpio_bus_switch = -EINVAL;
 	}
+
+	if (gpio_bus_switch > 0)
+		return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
+	else
+		return SOCAM_DATAWIDTH_10;
+}
+
+static struct soc_camera_link iclink = {
+	.bus_id	= 0, /* Must match with the camera ID above */
+	.query_bus_param = pcm990_camera_query_bus_param,
+	.set_bus_param = pcm990_camera_set_bus_param,
 };
 
 /* Board I2C devices. */
@@ -399,10 +434,10 @@  static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
 		.platform_data = &pca9536_data,
 	}, {
 		I2C_BOARD_INFO("mt9v022", 0x48),
-		.platform_data = &iclink[0], /* With extender */
+		.platform_data = &iclink, /* With extender */
 	}, {
 		I2C_BOARD_INFO("mt9m001", 0x5d),
-		.platform_data = &iclink[0], /* With extender */
+		.platform_data = &iclink, /* With extender */
 	},
 };
 #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */