diff options
author | Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> | 2008-03-07 19:57:18 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-24 13:07:49 -0400 |
commit | ad5f2e859d76dccb7eb1aa942171b1a32211efc2 (patch) | |
tree | 1716d5c82322d55886de36dddd9535b90dd57630 /drivers/media/video/mt9m001.c | |
parent | 1c659689fe9959c017bfaaa8301243f7d99f1a46 (diff) |
V4L/DVB (7336): soc-camera: streamline hardware parameter negotiation
Improve hardware parameter negotiation between the camera host driver and
camera drivers. Parameters like horizontal and vertical synchronisation,
pixel clock polarity shall be set depending on capabilities of the
parties.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/mt9m001.c')
-rw-r--r-- | drivers/media/video/mt9m001.c | 77 |
1 files changed, 48 insertions, 29 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 4ad834326fa8..acb5454b57eb 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c | |||
@@ -210,40 +210,64 @@ static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit) | |||
210 | #endif | 210 | #endif |
211 | } | 211 | } |
212 | 212 | ||
213 | static int mt9m001_set_capture_format(struct soc_camera_device *icd, | 213 | static int bus_switch_possible(struct mt9m001 *mt9m001) |
214 | __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) | 214 | { |
215 | #ifdef CONFIG_MT9M001_PCA9536_SWITCH | ||
216 | return gpio_is_valid(mt9m001->switch_gpio); | ||
217 | #else | ||
218 | return 0; | ||
219 | #endif | ||
220 | } | ||
221 | |||
222 | static int mt9m001_set_bus_param(struct soc_camera_device *icd, | ||
223 | unsigned long flags) | ||
215 | { | 224 | { |
216 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | 225 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); |
217 | unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | | 226 | unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; |
218 | IS_DATAWIDTH_8); | ||
219 | int ret; | 227 | int ret; |
220 | const u16 hblank = 9, vblank = 25; | ||
221 | 228 | ||
222 | /* MT9M001 has all capture_format parameters fixed */ | 229 | /* Flags validity verified in test_bus_param */ |
223 | if (!(flags & IS_MASTER) || | ||
224 | !(flags & IS_PCLK_SAMPLE_RISING) || | ||
225 | !(flags & IS_HSYNC_ACTIVE_HIGH) || | ||
226 | !(flags & IS_VSYNC_ACTIVE_HIGH)) | ||
227 | return -EINVAL; | ||
228 | |||
229 | /* Only one width bit may be set */ | ||
230 | if (!is_power_of_2(width_flag)) | ||
231 | return -EINVAL; | ||
232 | 230 | ||
233 | if ((mt9m001->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || | 231 | if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || |
234 | (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || | 232 | (mt9m001->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || |
235 | (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { | 233 | (mt9m001->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { |
236 | /* Well, we actually only can do 10 or 8 bits... */ | 234 | /* Well, we actually only can do 10 or 8 bits... */ |
237 | if (width_flag == IS_DATAWIDTH_9) | 235 | if (width_flag == SOCAM_DATAWIDTH_9) |
238 | return -EINVAL; | 236 | return -EINVAL; |
239 | ret = bus_switch_act(mt9m001, | 237 | ret = bus_switch_act(mt9m001, |
240 | width_flag == IS_DATAWIDTH_8); | 238 | width_flag == SOCAM_DATAWIDTH_8); |
241 | if (ret < 0) | 239 | if (ret < 0) |
242 | return ret; | 240 | return ret; |
243 | 241 | ||
244 | mt9m001->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; | 242 | mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; |
245 | } | 243 | } |
246 | 244 | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) | ||
249 | { | ||
250 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | ||
251 | unsigned int width_flag = SOCAM_DATAWIDTH_10; | ||
252 | |||
253 | if (bus_switch_possible(mt9m001)) | ||
254 | width_flag |= SOCAM_DATAWIDTH_8; | ||
255 | |||
256 | /* MT9M001 has all capture_format parameters fixed */ | ||
257 | return SOCAM_PCLK_SAMPLE_RISING | | ||
258 | SOCAM_HSYNC_ACTIVE_HIGH | | ||
259 | SOCAM_VSYNC_ACTIVE_HIGH | | ||
260 | SOCAM_MASTER | | ||
261 | width_flag; | ||
262 | } | ||
263 | |||
264 | static int mt9m001_set_fmt_cap(struct soc_camera_device *icd, | ||
265 | __u32 pixfmt, struct v4l2_rect *rect) | ||
266 | { | ||
267 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | ||
268 | int ret; | ||
269 | const u16 hblank = 9, vblank = 25; | ||
270 | |||
247 | /* Blanking and start values - default... */ | 271 | /* Blanking and start values - default... */ |
248 | ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); | 272 | ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank); |
249 | if (ret >= 0) | 273 | if (ret >= 0) |
@@ -348,12 +372,6 @@ static int mt9m001_set_register(struct soc_camera_device *icd, | |||
348 | } | 372 | } |
349 | #endif | 373 | #endif |
350 | 374 | ||
351 | static unsigned int mt9m001_get_datawidth(struct soc_camera_device *icd) | ||
352 | { | ||
353 | struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | ||
354 | return mt9m001->datawidth; | ||
355 | } | ||
356 | |||
357 | const struct v4l2_queryctrl mt9m001_controls[] = { | 375 | const struct v4l2_queryctrl mt9m001_controls[] = { |
358 | { | 376 | { |
359 | .id = V4L2_CID_VFLIP, | 377 | .id = V4L2_CID_VFLIP, |
@@ -401,11 +419,12 @@ static struct soc_camera_ops mt9m001_ops = { | |||
401 | .release = mt9m001_release, | 419 | .release = mt9m001_release, |
402 | .start_capture = mt9m001_start_capture, | 420 | .start_capture = mt9m001_start_capture, |
403 | .stop_capture = mt9m001_stop_capture, | 421 | .stop_capture = mt9m001_stop_capture, |
404 | .set_capture_format = mt9m001_set_capture_format, | 422 | .set_fmt_cap = mt9m001_set_fmt_cap, |
405 | .try_fmt_cap = mt9m001_try_fmt_cap, | 423 | .try_fmt_cap = mt9m001_try_fmt_cap, |
424 | .set_bus_param = mt9m001_set_bus_param, | ||
425 | .query_bus_param = mt9m001_query_bus_param, | ||
406 | .formats = NULL, /* Filled in later depending on the */ | 426 | .formats = NULL, /* Filled in later depending on the */ |
407 | .num_formats = 0, /* camera type and data widths */ | 427 | .num_formats = 0, /* camera type and data widths */ |
408 | .get_datawidth = mt9m001_get_datawidth, | ||
409 | .controls = mt9m001_controls, | 428 | .controls = mt9m001_controls, |
410 | .num_controls = ARRAY_SIZE(mt9m001_controls), | 429 | .num_controls = ARRAY_SIZE(mt9m001_controls), |
411 | .get_control = mt9m001_get_control, | 430 | .get_control = mt9m001_get_control, |