aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2008-12-23 03:54:45 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:40:17 -0500
commitbd73b36f0c41b0c02ef4b10a307db1c43537e006 (patch)
tree5dabc2aadde5e873d4d1cba136376ae55826f273
parent5ca11fa3e0025864df930d6d97470b87c35919ed (diff)
V4L/DVB (10072): soc-camera: Add signal inversion flags to be used by camera drivers
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> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/mt9m001.c15
-rw-r--r--drivers/media/video/mt9m111.c6
-rw-r--r--drivers/media/video/mt9v022.c3
-rw-r--r--drivers/media/video/ov772x.c10
-rw-r--r--drivers/media/video/soc_camera.c34
-rw-r--r--include/media/soc_camera.h11
6 files changed, 65 insertions, 14 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index a7f0e6971fe1..b58f0f85e30f 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -272,17 +272,16 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd,
272static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) 272static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
273{ 273{
274 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); 274 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
275 unsigned int width_flag = SOCAM_DATAWIDTH_10; 275 struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
276 /* MT9M001 has all capture_format parameters fixed */
277 unsigned long flags = SOCAM_DATAWIDTH_10 | SOCAM_PCLK_SAMPLE_RISING |
278 SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
279 SOCAM_MASTER;
276 280
277 if (bus_switch_possible(mt9m001)) 281 if (bus_switch_possible(mt9m001))
278 width_flag |= SOCAM_DATAWIDTH_8; 282 flags |= SOCAM_DATAWIDTH_8;
279 283
280 /* MT9M001 has all capture_format parameters fixed */ 284 return soc_camera_apply_sensor_flags(icl, flags);
281 return SOCAM_PCLK_SAMPLE_RISING |
282 SOCAM_HSYNC_ACTIVE_HIGH |
283 SOCAM_VSYNC_ACTIVE_HIGH |
284 SOCAM_MASTER |
285 width_flag;
286} 285}
287 286
288static int mt9m001_set_fmt(struct soc_camera_device *icd, 287static int mt9m001_set_fmt(struct soc_camera_device *icd,
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index b4a238f49600..b0e6046ea967 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -415,9 +415,13 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd)
415 415
416static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) 416static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
417{ 417{
418 return SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | 418 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
419 struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
420 unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
419 SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | 421 SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
420 SOCAM_DATAWIDTH_8; 422 SOCAM_DATAWIDTH_8;
423
424 return soc_camera_apply_sensor_flags(icl, flags);
421} 425}
422 426
423static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) 427static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 82e1a3381a7a..3b3a6a027b1d 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -273,6 +273,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
273 unsigned long flags) 273 unsigned long flags)
274{ 274{
275 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 275 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
276 struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
276 unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; 277 unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
277 int ret; 278 int ret;
278 u16 pixclk = 0; 279 u16 pixclk = 0;
@@ -296,6 +297,8 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
296 mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; 297 mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
297 } 298 }
298 299
300 flags = soc_camera_apply_sensor_flags(icl, flags);
301
299 if (flags & SOCAM_PCLK_SAMPLE_RISING) 302 if (flags & SOCAM_PCLK_SAMPLE_RISING)
300 pixclk |= 0x10; 303 pixclk |= 0x10;
301 304
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index 99dd943aacf3..110cb9be09d6 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -716,12 +716,12 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd,
716static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) 716static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
717{ 717{
718 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 718 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
719 719 struct soc_camera_link *icl = priv->client->dev.platform_data;
720 return SOCAM_PCLK_SAMPLE_RISING | 720 unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
721 SOCAM_HSYNC_ACTIVE_HIGH | 721 SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
722 SOCAM_VSYNC_ACTIVE_HIGH |
723 SOCAM_MASTER |
724 priv->info->buswidth; 722 priv->info->buswidth;
723
724 return soc_camera_apply_sensor_flags(icl, flags);
725} 725}
726 726
727static int ov772x_get_chip_id(struct soc_camera_device *icd, 727static int ov772x_get_chip_id(struct soc_camera_device *icd,
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 5e48c2cc1a44..176017501055 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -59,6 +59,40 @@ const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
59} 59}
60EXPORT_SYMBOL(soc_camera_xlate_by_fourcc); 60EXPORT_SYMBOL(soc_camera_xlate_by_fourcc);
61 61
62/**
63 * soc_camera_apply_sensor_flags() - apply platform SOCAM_SENSOR_INVERT_* flags
64 * @icl: camera platform parameters
65 * @flags: flags to be inverted according to platform configuration
66 * @return: resulting flags
67 */
68unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
69 unsigned long flags)
70{
71 unsigned long f;
72
73 /* If only one of the two polarities is supported, switch to the opposite */
74 if (icl->flags & SOCAM_SENSOR_INVERT_HSYNC) {
75 f = flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
76 if (f == SOCAM_HSYNC_ACTIVE_HIGH || f == SOCAM_HSYNC_ACTIVE_LOW)
77 flags ^= SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW;
78 }
79
80 if (icl->flags & SOCAM_SENSOR_INVERT_VSYNC) {
81 f = flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
82 if (f == SOCAM_VSYNC_ACTIVE_HIGH || f == SOCAM_VSYNC_ACTIVE_LOW)
83 flags ^= SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW;
84 }
85
86 if (icl->flags & SOCAM_SENSOR_INVERT_PCLK) {
87 f = flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
88 if (f == SOCAM_PCLK_SAMPLE_RISING || f == SOCAM_PCLK_SAMPLE_FALLING)
89 flags ^= SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING;
90 }
91
92 return flags;
93}
94EXPORT_SYMBOL(soc_camera_apply_sensor_flags);
95
62static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, 96static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
63 struct v4l2_format *f) 97 struct v4l2_format *f)
64{ 98{
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index da57ffdaec4d..e6ed0d94ac1b 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -81,11 +81,19 @@ struct soc_camera_host_ops {
81 unsigned int (*poll)(struct file *, poll_table *); 81 unsigned int (*poll)(struct file *, poll_table *);
82}; 82};
83 83
84#define SOCAM_SENSOR_INVERT_PCLK (1 << 0)
85#define SOCAM_SENSOR_INVERT_MCLK (1 << 1)
86#define SOCAM_SENSOR_INVERT_HSYNC (1 << 2)
87#define SOCAM_SENSOR_INVERT_VSYNC (1 << 3)
88#define SOCAM_SENSOR_INVERT_DATA (1 << 4)
89
84struct soc_camera_link { 90struct soc_camera_link {
85 /* Camera bus id, used to match a camera and a bus */ 91 /* Camera bus id, used to match a camera and a bus */
86 int bus_id; 92 int bus_id;
87 /* GPIO number to switch between 8 and 10 bit modes */ 93 /* GPIO number to switch between 8 and 10 bit modes */
88 unsigned int gpio; 94 unsigned int gpio;
95 /* Per camera SOCAM_SENSOR_* bus flags */
96 unsigned long flags;
89 /* Optional callbacks to power on or off and reset the sensor */ 97 /* Optional callbacks to power on or off and reset the sensor */
90 int (*power)(struct device *, int); 98 int (*power)(struct device *, int);
91 int (*reset)(struct device *); 99 int (*reset)(struct device *);
@@ -206,4 +214,7 @@ static inline unsigned long soc_camera_bus_param_compatible(
206 return (!hsync || !vsync || !pclk) ? 0 : common_flags; 214 return (!hsync || !vsync || !pclk) ? 0 : common_flags;
207} 215}
208 216
217extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
218 unsigned long flags);
219
209#endif 220#endif