Skip to content

Commit

Permalink
V4L/DVB (11033): mt9v022: allow setting of bus width from board code
Browse files Browse the repository at this point in the history
This patch removes the phytec specific setting of the bus width
and switches to the more generic query_bus_param/set_bus_param
hooks

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Sascha Hauer authored and Mauro Carvalho Chehab committed Mar 30, 2009
1 parent 36034dc commit e958e27
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 106 deletions.
7 changes: 0 additions & 7 deletions drivers/media/video/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -726,13 +726,6 @@ config SOC_CAMERA_MT9V022
help
This driver supports MT9V022 cameras from Micron

config MT9V022_PCA9536_SWITCH
bool "pca9536 datawidth switch for mt9v022"
depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO
help
Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
extender to switch between 8 and 10 bit datawidth modes

config SOC_CAMERA_TW9910
tristate "tw9910 support"
depends on SOC_CAMERA && I2C
Expand Down
141 changes: 42 additions & 99 deletions drivers/media/video/mt9v022.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/log2.h>
#include <linux/gpio.h>

#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
Expand Down Expand Up @@ -89,9 +88,7 @@ struct mt9v022 {
struct i2c_client *client;
struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
int switch_gpio;
u16 chip_control;
unsigned char datawidth;
};

static int reg_read(struct soc_camera_device *icd, const u8 reg)
Expand Down Expand Up @@ -209,66 +206,6 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
return 0;
}

static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl)
{
#ifdef CONFIG_MT9V022_PCA9536_SWITCH
int ret;
unsigned int gpio = icl->gpio;

if (gpio_is_valid(gpio)) {
/* We have a data bus switch. */
ret = gpio_request(gpio, "mt9v022");
if (ret < 0) {
dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio);
return ret;
}

ret = gpio_direction_output(gpio, 0);
if (ret < 0) {
dev_err(&mt9v022->client->dev,
"Cannot set GPIO %u to output\n", gpio);
gpio_free(gpio);
return ret;
}
}

mt9v022->switch_gpio = gpio;
#else
mt9v022->switch_gpio = -EINVAL;
#endif
return 0;
}

static void bus_switch_release(struct mt9v022 *mt9v022)
{
#ifdef CONFIG_MT9V022_PCA9536_SWITCH
if (gpio_is_valid(mt9v022->switch_gpio))
gpio_free(mt9v022->switch_gpio);
#endif
}

static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit)
{
#ifdef CONFIG_MT9V022_PCA9536_SWITCH
if (!gpio_is_valid(mt9v022->switch_gpio))
return -ENODEV;

gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit);
return 0;
#else
return -ENODEV;
#endif
}

static int bus_switch_possible(struct mt9v022 *mt9v022)
{
#ifdef CONFIG_MT9V022_PCA9536_SWITCH
return gpio_is_valid(mt9v022->switch_gpio);
#else
return 0;
#endif
}

static int mt9v022_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
Expand All @@ -282,19 +219,17 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
if (!is_power_of_2(width_flag))
return -EINVAL;

if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
(mt9v022->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) ||
(mt9v022->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) {
/* Well, we actually only can do 10 or 8 bits... */
if (width_flag == SOCAM_DATAWIDTH_9)
return -EINVAL;

ret = bus_switch_act(mt9v022,
width_flag == SOCAM_DATAWIDTH_8);
if (ret < 0)
if (icl->set_bus_param) {
ret = icl->set_bus_param(icl, width_flag);
if (ret)
return ret;

mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
} else {
/*
* Without board specific bus width settings we only support the
* sensors native bus width
*/
if (width_flag != SOCAM_DATAWIDTH_10)
return -EINVAL;
}

flags = soc_camera_apply_sensor_flags(icl, flags);
Expand Down Expand Up @@ -328,10 +263,14 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
{
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
unsigned int width_flag = SOCAM_DATAWIDTH_10;
struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
unsigned int width_flag;

if (bus_switch_possible(mt9v022))
width_flag |= SOCAM_DATAWIDTH_8;
if (icl->query_bus_param)
width_flag = icl->query_bus_param(icl) &
SOCAM_DATAWIDTH_MASK;
else
width_flag = SOCAM_DATAWIDTH_10;

return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
Expand Down Expand Up @@ -715,6 +654,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
s32 data;
int ret;
unsigned long flags;

if (!icd->dev.parent ||
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
Expand Down Expand Up @@ -748,22 +688,36 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
icd->formats = mt9v022_colour_formats;
if (gpio_is_valid(icl->gpio))
icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats);
else
icd->num_formats = 1;
} else {
ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11);
mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
icd->formats = mt9v022_monochrome_formats;
if (gpio_is_valid(icl->gpio))
icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats);
else
icd->num_formats = 1;
}

if (!ret)
ret = soc_camera_video_start(icd);
if (ret < 0)
goto eisis;

icd->num_formats = 0;

/*
* This is a 10bit sensor, so by default we only allow 10bit.
* The platform may support different bus widths due to
* different routing of the data lines.
*/
if (icl->query_bus_param)
flags = icl->query_bus_param(icl);
else
flags = SOCAM_DATAWIDTH_10;

if (flags & SOCAM_DATAWIDTH_10)
icd->num_formats++;
else
icd->formats++;

if (flags & SOCAM_DATAWIDTH_8)
icd->num_formats++;

ret = soc_camera_video_start(icd);
if (ret < 0)
goto eisis;

Expand Down Expand Up @@ -828,14 +782,6 @@ static int mt9v022_probe(struct i2c_client *client,
icd->height_max = 480;
icd->y_skip_top = 1;
icd->iface = icl->bus_id;
/* Default datawidth - this is the only width this camera (normally)
* supports. It is only with extra logic that it can support
* other widths. Therefore it seems to be a sensible default. */
mt9v022->datawidth = 10;

ret = bus_switch_request(mt9v022, icl);
if (ret)
goto eswinit;

ret = soc_camera_device_register(icd);
if (ret)
Expand All @@ -844,8 +790,6 @@ static int mt9v022_probe(struct i2c_client *client,
return 0;

eisdr:
bus_switch_release(mt9v022);
eswinit:
kfree(mt9v022);
return ret;
}
Expand All @@ -855,7 +799,6 @@ static int mt9v022_remove(struct i2c_client *client)
struct mt9v022 *mt9v022 = i2c_get_clientdata(client);

soc_camera_device_unregister(&mt9v022->icd);
bus_switch_release(mt9v022);
kfree(mt9v022);

return 0;
Expand Down

0 comments on commit e958e27

Please sign in to comment.