diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2008-12-23 09:54:45 +0100 |
---|---|---|
committer | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2008-12-23 09:54:45 +0100 |
commit | d3918ffc89527a22f0ba31095387201cee5aff10 (patch) | |
tree | d80c74c840c5fd14e60a285109b6b97e82e1507c /linux/drivers/media | |
parent | 4d71e0f99bbbad2f387a34daed239ce1c45f5ef6 (diff) | |
download | mediapointer-dvb-s2-d3918ffc89527a22f0ba31095387201cee5aff10.tar.gz mediapointer-dvb-s2-d3918ffc89527a22f0ba31095387201cee5aff10.tar.bz2 |
soc-camera: Add signal inversion flags to be used by camera drivers
From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
As reported by Antonio Ospite <ospite@studenti.unina.it> two platforms with a
mt9m111 camera require opposite pixel clock polarity, which means one of them
inverts it. This patch adds support for inversion flags and switches all
available camera drivers to using them.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/media/video/mt9m001.c | 15 +++++++--------
drivers/media/video/mt9m111.c | 6 +++++-
drivers/media/video/mt9v022.c | 3 +++
drivers/media/video/ov772x.c | 10 +++++-----
drivers/media/video/soc_camera.c | 34 ++++++++++++++++++++++++++++++++++
include/media/soc_camera.h | 11 +++++++++++
6 files changed, 65 insertions(+), 14 deletions(-)
Diffstat (limited to 'linux/drivers/media')
-rw-r--r-- | linux/drivers/media/video/mt9m001.c | 15 | ||||
-rw-r--r-- | linux/drivers/media/video/mt9m111.c | 6 | ||||
-rw-r--r-- | linux/drivers/media/video/mt9v022.c | 3 | ||||
-rw-r--r-- | linux/drivers/media/video/ov772x.c | 10 | ||||
-rw-r--r-- | linux/drivers/media/video/soc_camera.c | 34 |
5 files changed, 54 insertions, 14 deletions
diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index a489f239f..ed8a02269 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -272,17 +272,16 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd, static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) { struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - unsigned int width_flag = SOCAM_DATAWIDTH_10; + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + /* MT9M001 has all capture_format parameters fixed */ + unsigned long flags = SOCAM_DATAWIDTH_10 | SOCAM_PCLK_SAMPLE_RISING | + SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | + SOCAM_MASTER; if (bus_switch_possible(mt9m001)) - width_flag |= SOCAM_DATAWIDTH_8; + flags |= SOCAM_DATAWIDTH_8; - /* MT9M001 has all capture_format parameters fixed */ - return SOCAM_PCLK_SAMPLE_RISING | - SOCAM_HSYNC_ACTIVE_HIGH | - SOCAM_VSYNC_ACTIVE_HIGH | - SOCAM_MASTER | - width_flag; + return soc_camera_apply_sensor_flags(icl, flags); } static int mt9m001_set_fmt(struct soc_camera_device *icd, diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index dc3a913da..2241b916e 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -415,9 +415,13 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd) static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) { - return SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | + struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct soc_camera_link *icl = mt9m111->client->dev.platform_data; + unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; + + return soc_camera_apply_sensor_flags(icl, flags); } static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 88380e05f..419cbe61f 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -273,6 +273,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; u16 pixclk = 0; @@ -296,6 +297,8 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; } + flags = soc_camera_apply_sensor_flags(icl, flags); + if (flags & SOCAM_PCLK_SAMPLE_RISING) pixclk |= 0x10; diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 89cacadad..bed830aed 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -716,12 +716,12 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd, static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) { struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - - return SOCAM_PCLK_SAMPLE_RISING | - SOCAM_HSYNC_ACTIVE_HIGH | - SOCAM_VSYNC_ACTIVE_HIGH | - SOCAM_MASTER | + struct soc_camera_link *icl = priv->client->dev.platform_data; + unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | priv->info->buswidth; + + return soc_camera_apply_sensor_flags(icl, flags); } static int ov772x_get_chip_id(struct soc_camera_device *icd, diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 4a9c52c37..d512cede8 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -60,6 +60,40 @@ const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( } EXPORT_SYMBOL(soc_camera_xlate_by_fourcc); +/** + * soc_camera_apply_sensor_flags() - apply platform SOCAM_SENSOR_INVERT_* flags + * @icl: camera platform parameters + * @flags: flags to be inverted according to platform configuration + * @return: resulting flags + */ +unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl, + unsigned long flags) +{ + unsigned long f; + + /* If only one of the two polarities is supported, switch to the opposite */ + if (icl->flags & SOCAM_SENSOR_INVERT_HSYNC) { + f = flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW); + if (f == SOCAM_HSYNC_ACTIVE_HIGH || f == SOCAM_HSYNC_ACTIVE_LOW) + flags ^= SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW; + } + + if (icl->flags & SOCAM_SENSOR_INVERT_VSYNC) { + f = flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW); + if (f == SOCAM_VSYNC_ACTIVE_HIGH || f == SOCAM_VSYNC_ACTIVE_LOW) + flags ^= SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW; + } + + if (icl->flags & SOCAM_SENSOR_INVERT_PCLK) { + f = flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING); + if (f == SOCAM_PCLK_SAMPLE_RISING || f == SOCAM_PCLK_SAMPLE_FALLING) + flags ^= SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING; + } + + return flags; +} +EXPORT_SYMBOL(soc_camera_apply_sensor_flags); + static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { |