diff options
-rw-r--r-- | drivers/media/video/mt9m001.c | 77 | ||||
-rw-r--r-- | drivers/media/video/mt9v022.c | 129 | ||||
-rw-r--r-- | drivers/media/video/pxa_camera.c | 156 | ||||
-rw-r--r-- | drivers/media/video/soc_camera.c | 49 | ||||
-rw-r--r-- | include/media/soc_camera.h | 52 |
5 files changed, 301 insertions, 162 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, |
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index d677344d233d..a2f161dcc72d 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -241,19 +241,89 @@ static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit) | |||
241 | #endif | 241 | #endif |
242 | } | 242 | } |
243 | 243 | ||
244 | static int mt9v022_set_capture_format(struct soc_camera_device *icd, | 244 | static int bus_switch_possible(struct mt9v022 *mt9v022) |
245 | __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags) | 245 | { |
246 | #ifdef CONFIG_MT9V022_PCA9536_SWITCH | ||
247 | return gpio_is_valid(mt9v022->switch_gpio); | ||
248 | #else | ||
249 | return 0; | ||
250 | #endif | ||
251 | } | ||
252 | |||
253 | static int mt9v022_set_bus_param(struct soc_camera_device *icd, | ||
254 | unsigned long flags) | ||
246 | { | 255 | { |
247 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | 256 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); |
248 | unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 | | 257 | unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; |
249 | IS_DATAWIDTH_8); | ||
250 | u16 pixclk = 0; | ||
251 | int ret; | 258 | int ret; |
259 | u16 pixclk = 0; | ||
252 | 260 | ||
253 | /* Only one width bit may be set */ | 261 | /* Only one width bit may be set */ |
254 | if (!is_power_of_2(width_flag)) | 262 | if (!is_power_of_2(width_flag)) |
255 | return -EINVAL; | 263 | return -EINVAL; |
256 | 264 | ||
265 | if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) || | ||
266 | (mt9v022->datawidth != 9 && (width_flag == SOCAM_DATAWIDTH_9)) || | ||
267 | (mt9v022->datawidth != 8 && (width_flag == SOCAM_DATAWIDTH_8))) { | ||
268 | /* Well, we actually only can do 10 or 8 bits... */ | ||
269 | if (width_flag == SOCAM_DATAWIDTH_9) | ||
270 | return -EINVAL; | ||
271 | |||
272 | ret = bus_switch_act(mt9v022, | ||
273 | width_flag == SOCAM_DATAWIDTH_8); | ||
274 | if (ret < 0) | ||
275 | return ret; | ||
276 | |||
277 | mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10; | ||
278 | } | ||
279 | |||
280 | if (flags & SOCAM_PCLK_SAMPLE_RISING) | ||
281 | pixclk |= 0x10; | ||
282 | |||
283 | if (!(flags & SOCAM_HSYNC_ACTIVE_HIGH)) | ||
284 | pixclk |= 0x1; | ||
285 | |||
286 | if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH)) | ||
287 | pixclk |= 0x2; | ||
288 | |||
289 | ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); | ||
290 | if (ret < 0) | ||
291 | return ret; | ||
292 | |||
293 | if (!(flags & SOCAM_MASTER)) | ||
294 | mt9v022->chip_control &= ~0x8; | ||
295 | |||
296 | ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); | ||
297 | if (ret < 0) | ||
298 | return ret; | ||
299 | |||
300 | dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", | ||
301 | pixclk, mt9v022->chip_control); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) | ||
307 | { | ||
308 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | ||
309 | unsigned int width_flag = SOCAM_DATAWIDTH_10; | ||
310 | |||
311 | if (bus_switch_possible(mt9v022)) | ||
312 | width_flag |= SOCAM_DATAWIDTH_8; | ||
313 | |||
314 | return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | | ||
315 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | | ||
316 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | | ||
317 | SOCAM_MASTER | SOCAM_SLAVE | | ||
318 | width_flag; | ||
319 | } | ||
320 | |||
321 | static int mt9v022_set_fmt_cap(struct soc_camera_device *icd, | ||
322 | __u32 pixfmt, struct v4l2_rect *rect) | ||
323 | { | ||
324 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | ||
325 | int ret; | ||
326 | |||
257 | /* The caller provides a supported format, as verified per call to | 327 | /* The caller provides a supported format, as verified per call to |
258 | * icd->try_fmt_cap(), datawidth is from our supported format list */ | 328 | * icd->try_fmt_cap(), datawidth is from our supported format list */ |
259 | switch (pixfmt) { | 329 | switch (pixfmt) { |
@@ -308,44 +378,6 @@ static int mt9v022_set_capture_format(struct soc_camera_device *icd, | |||
308 | 378 | ||
309 | dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height); | 379 | dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height); |
310 | 380 | ||
311 | if ((mt9v022->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) || | ||
312 | (mt9v022->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) || | ||
313 | (mt9v022->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) { | ||
314 | /* Well, we actually only can do 10 or 8 bits... */ | ||
315 | if (width_flag == IS_DATAWIDTH_9) | ||
316 | return -EINVAL; | ||
317 | |||
318 | ret = bus_switch_act(mt9v022, | ||
319 | width_flag == IS_DATAWIDTH_8); | ||
320 | if (ret < 0) | ||
321 | return ret; | ||
322 | |||
323 | mt9v022->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10; | ||
324 | } | ||
325 | |||
326 | if (flags & IS_PCLK_SAMPLE_RISING) | ||
327 | pixclk |= 0x10; | ||
328 | |||
329 | if (!(flags & IS_HSYNC_ACTIVE_HIGH)) | ||
330 | pixclk |= 0x1; | ||
331 | |||
332 | if (!(flags & IS_VSYNC_ACTIVE_HIGH)) | ||
333 | pixclk |= 0x2; | ||
334 | |||
335 | ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk); | ||
336 | if (ret < 0) | ||
337 | return ret; | ||
338 | |||
339 | if (!(flags & IS_MASTER)) | ||
340 | mt9v022->chip_control &= ~0x8; | ||
341 | |||
342 | ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control); | ||
343 | if (ret < 0) | ||
344 | return ret; | ||
345 | |||
346 | dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", | ||
347 | pixclk, mt9v022->chip_control); | ||
348 | |||
349 | return 0; | 381 | return 0; |
350 | } | 382 | } |
351 | 383 | ||
@@ -420,12 +452,6 @@ static int mt9v022_set_register(struct soc_camera_device *icd, | |||
420 | } | 452 | } |
421 | #endif | 453 | #endif |
422 | 454 | ||
423 | static unsigned int mt9v022_get_datawidth(struct soc_camera_device *icd) | ||
424 | { | ||
425 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | ||
426 | return mt9v022->datawidth; | ||
427 | } | ||
428 | |||
429 | const struct v4l2_queryctrl mt9v022_controls[] = { | 455 | const struct v4l2_queryctrl mt9v022_controls[] = { |
430 | { | 456 | { |
431 | .id = V4L2_CID_VFLIP, | 457 | .id = V4L2_CID_VFLIP, |
@@ -491,11 +517,12 @@ static struct soc_camera_ops mt9v022_ops = { | |||
491 | .release = mt9v022_release, | 517 | .release = mt9v022_release, |
492 | .start_capture = mt9v022_start_capture, | 518 | .start_capture = mt9v022_start_capture, |
493 | .stop_capture = mt9v022_stop_capture, | 519 | .stop_capture = mt9v022_stop_capture, |
494 | .set_capture_format = mt9v022_set_capture_format, | 520 | .set_fmt_cap = mt9v022_set_fmt_cap, |
495 | .try_fmt_cap = mt9v022_try_fmt_cap, | 521 | .try_fmt_cap = mt9v022_try_fmt_cap, |
522 | .set_bus_param = mt9v022_set_bus_param, | ||
523 | .query_bus_param = mt9v022_query_bus_param, | ||
496 | .formats = NULL, /* Filled in later depending on the */ | 524 | .formats = NULL, /* Filled in later depending on the */ |
497 | .num_formats = 0, /* sensor type and data widths */ | 525 | .num_formats = 0, /* sensor type and data widths */ |
498 | .get_datawidth = mt9v022_get_datawidth, | ||
499 | .controls = mt9v022_controls, | 526 | .controls = mt9v022_controls, |
500 | .num_controls = ARRAY_SIZE(mt9v022_controls), | 527 | .num_controls = ARRAY_SIZE(mt9v022_controls), |
501 | .get_control = mt9v022_get_control, | 528 | .get_control = mt9v022_get_control, |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index a34a193249f6..4756699d16aa 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -581,64 +581,109 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) | |||
581 | pcdev->icd = NULL; | 581 | pcdev->icd = NULL; |
582 | } | 582 | } |
583 | 583 | ||
584 | static int pxa_camera_set_capture_format(struct soc_camera_device *icd, | 584 | static int test_platform_param(struct pxa_camera_dev *pcdev, |
585 | __u32 pixfmt, struct v4l2_rect *rect) | 585 | unsigned char buswidth, unsigned long *flags) |
586 | { | 586 | { |
587 | struct soc_camera_host *ici = | 587 | /* |
588 | to_soc_camera_host(icd->dev.parent); | 588 | * Platform specified synchronization and pixel clock polarities are |
589 | struct pxa_camera_dev *pcdev = ici->priv; | 589 | * only a recommendation and are only used during probing. The PXA270 |
590 | unsigned int datawidth = 0, dw, bpp; | 590 | * quick capture interface supports both. |
591 | u32 cicr0, cicr4 = 0; | 591 | */ |
592 | int ret; | 592 | *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ? |
593 | SOCAM_MASTER : SOCAM_SLAVE) | | ||
594 | SOCAM_HSYNC_ACTIVE_HIGH | | ||
595 | SOCAM_HSYNC_ACTIVE_LOW | | ||
596 | SOCAM_VSYNC_ACTIVE_HIGH | | ||
597 | SOCAM_VSYNC_ACTIVE_LOW | | ||
598 | SOCAM_PCLK_SAMPLE_RISING | | ||
599 | SOCAM_PCLK_SAMPLE_FALLING; | ||
593 | 600 | ||
594 | /* If requested data width is supported by the platform, use it */ | 601 | /* If requested data width is supported by the platform, use it */ |
595 | switch (icd->cached_datawidth) { | 602 | switch (buswidth) { |
596 | case 10: | 603 | case 10: |
597 | if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10) | 604 | if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10)) |
598 | datawidth = IS_DATAWIDTH_10; | 605 | return -EINVAL; |
606 | *flags |= SOCAM_DATAWIDTH_10; | ||
599 | break; | 607 | break; |
600 | case 9: | 608 | case 9: |
601 | if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9) | 609 | if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9)) |
602 | datawidth = IS_DATAWIDTH_9; | 610 | return -EINVAL; |
611 | *flags |= SOCAM_DATAWIDTH_9; | ||
603 | break; | 612 | break; |
604 | case 8: | 613 | case 8: |
605 | if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8) | 614 | if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8)) |
606 | datawidth = IS_DATAWIDTH_8; | 615 | return -EINVAL; |
616 | *flags |= SOCAM_DATAWIDTH_8; | ||
607 | } | 617 | } |
608 | if (!datawidth) | 618 | |
619 | return 0; | ||
620 | } | ||
621 | |||
622 | static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | ||
623 | { | ||
624 | struct soc_camera_host *ici = | ||
625 | to_soc_camera_host(icd->dev.parent); | ||
626 | struct pxa_camera_dev *pcdev = ici->priv; | ||
627 | unsigned long dw, bpp, bus_flags, camera_flags, common_flags; | ||
628 | u32 cicr0, cicr4 = 0; | ||
629 | int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); | ||
630 | |||
631 | if (ret < 0) | ||
632 | return ret; | ||
633 | |||
634 | camera_flags = icd->ops->query_bus_param(icd); | ||
635 | |||
636 | common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); | ||
637 | if (!common_flags) | ||
609 | return -EINVAL; | 638 | return -EINVAL; |
610 | 639 | ||
611 | ret = icd->ops->set_capture_format(icd, pixfmt, rect, | 640 | /* Make choises, based on platform preferences */ |
612 | datawidth | | 641 | if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && |
613 | (pcdev->platform_flags & PXA_CAMERA_MASTER ? | 642 | (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { |
614 | IS_MASTER : 0) | | 643 | if (pcdev->platform_flags & PXA_CAMERA_HSP) |
615 | (pcdev->platform_flags & PXA_CAMERA_HSP ? | 644 | common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; |
616 | 0 : IS_HSYNC_ACTIVE_HIGH) | | 645 | else |
617 | (pcdev->platform_flags & PXA_CAMERA_VSP ? | 646 | common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; |
618 | 0 : IS_VSYNC_ACTIVE_HIGH) | | 647 | } |
619 | (pcdev->platform_flags & PXA_CAMERA_PCP ? | 648 | |
620 | 0 : IS_PCLK_SAMPLE_RISING)); | 649 | if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && |
650 | (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { | ||
651 | if (pcdev->platform_flags & PXA_CAMERA_VSP) | ||
652 | common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; | ||
653 | else | ||
654 | common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; | ||
655 | } | ||
656 | |||
657 | if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && | ||
658 | (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { | ||
659 | if (pcdev->platform_flags & PXA_CAMERA_PCP) | ||
660 | common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; | ||
661 | else | ||
662 | common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; | ||
663 | } | ||
664 | |||
665 | ret = icd->ops->set_bus_param(icd, common_flags); | ||
621 | if (ret < 0) | 666 | if (ret < 0) |
622 | return ret; | 667 | return ret; |
623 | 668 | ||
624 | /* Datawidth is now guaranteed to be equal to one of the three values. | 669 | /* Datawidth is now guaranteed to be equal to one of the three values. |
625 | * We fix bit-per-pixel equal to data-width... */ | 670 | * We fix bit-per-pixel equal to data-width... */ |
626 | switch (datawidth) { | 671 | switch (common_flags & SOCAM_DATAWIDTH_MASK) { |
627 | case IS_DATAWIDTH_10: | 672 | case SOCAM_DATAWIDTH_10: |
628 | icd->cached_datawidth = 10; | 673 | icd->buswidth = 10; |
629 | dw = 4; | 674 | dw = 4; |
630 | bpp = 0x40; | 675 | bpp = 0x40; |
631 | break; | 676 | break; |
632 | case IS_DATAWIDTH_9: | 677 | case SOCAM_DATAWIDTH_9: |
633 | icd->cached_datawidth = 9; | 678 | icd->buswidth = 9; |
634 | dw = 3; | 679 | dw = 3; |
635 | bpp = 0x20; | 680 | bpp = 0x20; |
636 | break; | 681 | break; |
637 | default: | 682 | default: |
638 | /* Actually it can only be 8 now, | 683 | /* Actually it can only be 8 now, |
639 | * default is just to silence compiler warnings */ | 684 | * default is just to silence compiler warnings */ |
640 | case IS_DATAWIDTH_8: | 685 | case SOCAM_DATAWIDTH_8: |
641 | icd->cached_datawidth = 8; | 686 | icd->buswidth = 8; |
642 | dw = 2; | 687 | dw = 2; |
643 | bpp = 0; | 688 | bpp = 0; |
644 | } | 689 | } |
@@ -647,19 +692,19 @@ static int pxa_camera_set_capture_format(struct soc_camera_device *icd, | |||
647 | cicr4 |= CICR4_PCLK_EN; | 692 | cicr4 |= CICR4_PCLK_EN; |
648 | if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) | 693 | if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) |
649 | cicr4 |= CICR4_MCLK_EN; | 694 | cicr4 |= CICR4_MCLK_EN; |
650 | if (pcdev->platform_flags & PXA_CAMERA_PCP) | 695 | if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) |
651 | cicr4 |= CICR4_PCP; | 696 | cicr4 |= CICR4_PCP; |
652 | if (pcdev->platform_flags & PXA_CAMERA_HSP) | 697 | if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) |
653 | cicr4 |= CICR4_HSP; | 698 | cicr4 |= CICR4_HSP; |
654 | if (pcdev->platform_flags & PXA_CAMERA_VSP) | 699 | if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) |
655 | cicr4 |= CICR4_VSP; | 700 | cicr4 |= CICR4_VSP; |
656 | 701 | ||
657 | cicr0 = CICR0; | 702 | cicr0 = CICR0; |
658 | if (cicr0 & CICR0_ENB) | 703 | if (cicr0 & CICR0_ENB) |
659 | CICR0 = cicr0 & ~CICR0_ENB; | 704 | CICR0 = cicr0 & ~CICR0_ENB; |
660 | CICR1 = CICR1_PPL_VAL(rect->width - 1) | bpp | dw; | 705 | CICR1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw; |
661 | CICR2 = 0; | 706 | CICR2 = 0; |
662 | CICR3 = CICR3_LPF_VAL(rect->height - 1) | | 707 | CICR3 = CICR3_LPF_VAL(icd->height - 1) | |
663 | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); | 708 | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); |
664 | CICR4 = mclk_get_divisor(pcdev) | cicr4; | 709 | CICR4 = mclk_get_divisor(pcdev) | cicr4; |
665 | 710 | ||
@@ -671,7 +716,29 @@ static int pxa_camera_set_capture_format(struct soc_camera_device *icd, | |||
671 | return 0; | 716 | return 0; |
672 | } | 717 | } |
673 | 718 | ||
674 | static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici, | 719 | static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt) |
720 | { | ||
721 | struct soc_camera_host *ici = | ||
722 | to_soc_camera_host(icd->dev.parent); | ||
723 | struct pxa_camera_dev *pcdev = ici->priv; | ||
724 | unsigned long bus_flags, camera_flags; | ||
725 | int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); | ||
726 | |||
727 | if (ret < 0) | ||
728 | return ret; | ||
729 | |||
730 | camera_flags = icd->ops->query_bus_param(icd); | ||
731 | |||
732 | return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; | ||
733 | } | ||
734 | |||
735 | static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd, | ||
736 | __u32 pixfmt, struct v4l2_rect *rect) | ||
737 | { | ||
738 | return icd->ops->set_fmt_cap(icd, pixfmt, rect); | ||
739 | } | ||
740 | |||
741 | static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, | ||
675 | struct v4l2_format *f) | 742 | struct v4l2_format *f) |
676 | { | 743 | { |
677 | /* limit to pxa hardware capabilities */ | 744 | /* limit to pxa hardware capabilities */ |
@@ -685,7 +752,8 @@ static int pxa_camera_try_fmt_cap(struct soc_camera_host *ici, | |||
685 | f->fmt.pix.width = 2048; | 752 | f->fmt.pix.width = 2048; |
686 | f->fmt.pix.width &= ~0x01; | 753 | f->fmt.pix.width &= ~0x01; |
687 | 754 | ||
688 | return 0; | 755 | /* limit to sensor capabilities */ |
756 | return icd->ops->try_fmt_cap(icd, f); | ||
689 | } | 757 | } |
690 | 758 | ||
691 | static int pxa_camera_reqbufs(struct soc_camera_file *icf, | 759 | static int pxa_camera_reqbufs(struct soc_camera_file *icf, |
@@ -742,11 +810,13 @@ static struct soc_camera_host pxa_soc_camera_host = { | |||
742 | .add = pxa_camera_add_device, | 810 | .add = pxa_camera_add_device, |
743 | .remove = pxa_camera_remove_device, | 811 | .remove = pxa_camera_remove_device, |
744 | .msize = sizeof(struct pxa_buffer), | 812 | .msize = sizeof(struct pxa_buffer), |
745 | .set_capture_format = pxa_camera_set_capture_format, | 813 | .set_fmt_cap = pxa_camera_set_fmt_cap, |
746 | .try_fmt_cap = pxa_camera_try_fmt_cap, | 814 | .try_fmt_cap = pxa_camera_try_fmt_cap, |
747 | .reqbufs = pxa_camera_reqbufs, | 815 | .reqbufs = pxa_camera_reqbufs, |
748 | .poll = pxa_camera_poll, | 816 | .poll = pxa_camera_poll, |
749 | .querycap = pxa_camera_querycap, | 817 | .querycap = pxa_camera_querycap, |
818 | .try_bus_param = pxa_camera_try_bus_param, | ||
819 | .set_bus_param = pxa_camera_set_bus_param, | ||
750 | }; | 820 | }; |
751 | 821 | ||
752 | static int pxa_camera_probe(struct platform_device *pdev) | 822 | static int pxa_camera_probe(struct platform_device *pdev) |
@@ -782,8 +852,8 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
782 | 852 | ||
783 | pcdev->pdata = pdev->dev.platform_data; | 853 | pcdev->pdata = pdev->dev.platform_data; |
784 | pcdev->platform_flags = pcdev->pdata->flags; | 854 | pcdev->platform_flags = pcdev->pdata->flags; |
785 | if (!pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | | 855 | if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | |
786 | PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10)) { | 856 | PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) { |
787 | /* Platform hasn't set available data widths. This is bad. | 857 | /* Platform hasn't set available data widths. This is bad. |
788 | * Warn and use a default. */ | 858 | * Warn and use a default. */ |
789 | dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " | 859 | dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 322f837bcfea..bd8677cb1cab 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -75,12 +75,13 @@ static int soc_camera_try_fmt_cap(struct file *file, void *priv, | |||
75 | return -EINVAL; | 75 | return -EINVAL; |
76 | } | 76 | } |
77 | 77 | ||
78 | /* limit to host capabilities */ | 78 | /* test physical bus parameters */ |
79 | ret = ici->try_fmt_cap(ici, f); | 79 | ret = ici->try_bus_param(icd, f->fmt.pix.pixelformat); |
80 | if (ret) | ||
81 | return ret; | ||
80 | 82 | ||
81 | /* limit to sensor capabilities */ | 83 | /* limit format to hardware capabilities */ |
82 | if (!ret) | 84 | ret = ici->try_fmt_cap(icd, f); |
83 | ret = icd->ops->try_fmt_cap(icd, f); | ||
84 | 85 | ||
85 | /* calculate missing fields */ | 86 | /* calculate missing fields */ |
86 | f->fmt.pix.field = field; | 87 | f->fmt.pix.field = field; |
@@ -344,8 +345,8 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, | |||
344 | if (!data_fmt) | 345 | if (!data_fmt) |
345 | return -EINVAL; | 346 | return -EINVAL; |
346 | 347 | ||
347 | /* cached_datawidth may be further adjusted by the ici */ | 348 | /* buswidth may be further adjusted by the ici */ |
348 | icd->cached_datawidth = data_fmt->depth; | 349 | icd->buswidth = data_fmt->depth; |
349 | 350 | ||
350 | ret = soc_camera_try_fmt_cap(file, icf, f); | 351 | ret = soc_camera_try_fmt_cap(file, icf, f); |
351 | if (ret < 0) | 352 | if (ret < 0) |
@@ -355,22 +356,23 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, | |||
355 | rect.top = icd->y_current; | 356 | rect.top = icd->y_current; |
356 | rect.width = f->fmt.pix.width; | 357 | rect.width = f->fmt.pix.width; |
357 | rect.height = f->fmt.pix.height; | 358 | rect.height = f->fmt.pix.height; |
358 | ret = ici->set_capture_format(icd, f->fmt.pix.pixelformat, &rect); | 359 | ret = ici->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); |
360 | if (ret < 0) | ||
361 | return ret; | ||
359 | 362 | ||
360 | if (!ret) { | 363 | icd->current_fmt = data_fmt; |
361 | icd->current_fmt = data_fmt; | 364 | icd->width = rect.width; |
362 | icd->width = rect.width; | 365 | icd->height = rect.height; |
363 | icd->height = rect.height; | 366 | icf->vb_vidq.field = f->fmt.pix.field; |
364 | icf->vb_vidq.field = f->fmt.pix.field; | 367 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) |
365 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) | 368 | dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", |
366 | dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", | 369 | f->type); |
367 | f->type); | ||
368 | |||
369 | dev_dbg(&icd->dev, "set width: %d height: %d\n", | ||
370 | icd->width, icd->height); | ||
371 | } | ||
372 | 370 | ||
373 | return ret; | 371 | dev_dbg(&icd->dev, "set width: %d height: %d\n", |
372 | icd->width, icd->height); | ||
373 | |||
374 | /* set physical bus parameters */ | ||
375 | return ici->set_bus_param(icd, f->fmt.pix.pixelformat); | ||
374 | } | 376 | } |
375 | 377 | ||
376 | static int soc_camera_enum_fmt_cap(struct file *file, void *priv, | 378 | static int soc_camera_enum_fmt_cap(struct file *file, void *priv, |
@@ -577,7 +579,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, | |||
577 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 579 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
578 | return -EINVAL; | 580 | return -EINVAL; |
579 | 581 | ||
580 | ret = ici->set_capture_format(icd, 0, &a->c); | 582 | ret = ici->set_fmt_cap(icd, 0, &a->c); |
581 | if (!ret) { | 583 | if (!ret) { |
582 | icd->width = a->c.width; | 584 | icd->width = a->c.width; |
583 | icd->height = a->c.height; | 585 | icd->height = a->c.height; |
@@ -860,9 +862,6 @@ int soc_camera_device_register(struct soc_camera_device *icd) | |||
860 | 862 | ||
861 | icd->dev.release = dummy_release; | 863 | icd->dev.release = dummy_release; |
862 | 864 | ||
863 | if (icd->ops->get_datawidth) | ||
864 | icd->cached_datawidth = icd->ops->get_datawidth(icd); | ||
865 | |||
866 | return scan_add_device(icd); | 865 | return scan_add_device(icd); |
867 | } | 866 | } |
868 | EXPORT_SYMBOL(soc_camera_device_register); | 867 | EXPORT_SYMBOL(soc_camera_device_register); |
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index c886b1e64872..3e48e435b21a 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h | |||
@@ -34,7 +34,7 @@ struct soc_camera_device { | |||
34 | unsigned short exposure; | 34 | unsigned short exposure; |
35 | unsigned char iface; /* Host number */ | 35 | unsigned char iface; /* Host number */ |
36 | unsigned char devnum; /* Device number per host */ | 36 | unsigned char devnum; /* Device number per host */ |
37 | unsigned char cached_datawidth; /* See comment in .c */ | 37 | unsigned char buswidth; /* See comment in .c */ |
38 | struct soc_camera_ops *ops; | 38 | struct soc_camera_ops *ops; |
39 | struct video_device *vdev; | 39 | struct video_device *vdev; |
40 | const struct soc_camera_data_format *current_fmt; | 40 | const struct soc_camera_data_format *current_fmt; |
@@ -61,11 +61,13 @@ struct soc_camera_host { | |||
61 | char *drv_name; | 61 | char *drv_name; |
62 | int (*add)(struct soc_camera_device *); | 62 | int (*add)(struct soc_camera_device *); |
63 | void (*remove)(struct soc_camera_device *); | 63 | void (*remove)(struct soc_camera_device *); |
64 | int (*set_capture_format)(struct soc_camera_device *, __u32, | 64 | int (*set_fmt_cap)(struct soc_camera_device *, __u32, |
65 | struct v4l2_rect *); | 65 | struct v4l2_rect *); |
66 | int (*try_fmt_cap)(struct soc_camera_host *, struct v4l2_format *); | 66 | int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); |
67 | int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); | 67 | int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); |
68 | int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); | 68 | int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); |
69 | int (*try_bus_param)(struct soc_camera_device *, __u32); | ||
70 | int (*set_bus_param)(struct soc_camera_device *, __u32); | ||
69 | unsigned int (*poll)(struct file *, poll_table *); | 71 | unsigned int (*poll)(struct file *, poll_table *); |
70 | }; | 72 | }; |
71 | 73 | ||
@@ -108,9 +110,11 @@ struct soc_camera_ops { | |||
108 | int (*release)(struct soc_camera_device *); | 110 | int (*release)(struct soc_camera_device *); |
109 | int (*start_capture)(struct soc_camera_device *); | 111 | int (*start_capture)(struct soc_camera_device *); |
110 | int (*stop_capture)(struct soc_camera_device *); | 112 | int (*stop_capture)(struct soc_camera_device *); |
111 | int (*set_capture_format)(struct soc_camera_device *, __u32, | 113 | int (*set_fmt_cap)(struct soc_camera_device *, __u32, |
112 | struct v4l2_rect *, unsigned int); | 114 | struct v4l2_rect *); |
113 | int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); | 115 | int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); |
116 | unsigned long (*query_bus_param)(struct soc_camera_device *); | ||
117 | int (*set_bus_param)(struct soc_camera_device *, unsigned long); | ||
114 | int (*get_chip_id)(struct soc_camera_device *, | 118 | int (*get_chip_id)(struct soc_camera_device *, |
115 | struct v4l2_chip_ident *); | 119 | struct v4l2_chip_ident *); |
116 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 120 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -123,7 +127,6 @@ struct soc_camera_ops { | |||
123 | int (*set_control)(struct soc_camera_device *, struct v4l2_control *); | 127 | int (*set_control)(struct soc_camera_device *, struct v4l2_control *); |
124 | const struct v4l2_queryctrl *controls; | 128 | const struct v4l2_queryctrl *controls; |
125 | int num_controls; | 129 | int num_controls; |
126 | unsigned int(*get_datawidth)(struct soc_camera_device *icd); | ||
127 | }; | 130 | }; |
128 | 131 | ||
129 | static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( | 132 | static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( |
@@ -138,12 +141,33 @@ static inline struct v4l2_queryctrl const *soc_camera_find_qctrl( | |||
138 | return NULL; | 141 | return NULL; |
139 | } | 142 | } |
140 | 143 | ||
141 | #define IS_MASTER (1<<0) | 144 | #define SOCAM_MASTER (1 << 0) |
142 | #define IS_HSYNC_ACTIVE_HIGH (1<<1) | 145 | #define SOCAM_SLAVE (1 << 1) |
143 | #define IS_VSYNC_ACTIVE_HIGH (1<<2) | 146 | #define SOCAM_HSYNC_ACTIVE_HIGH (1 << 2) |
144 | #define IS_DATAWIDTH_8 (1<<3) | 147 | #define SOCAM_HSYNC_ACTIVE_LOW (1 << 3) |
145 | #define IS_DATAWIDTH_9 (1<<4) | 148 | #define SOCAM_VSYNC_ACTIVE_HIGH (1 << 4) |
146 | #define IS_DATAWIDTH_10 (1<<5) | 149 | #define SOCAM_VSYNC_ACTIVE_LOW (1 << 5) |
147 | #define IS_PCLK_SAMPLE_RISING (1<<6) | 150 | #define SOCAM_DATAWIDTH_8 (1 << 6) |
151 | #define SOCAM_DATAWIDTH_9 (1 << 7) | ||
152 | #define SOCAM_DATAWIDTH_10 (1 << 8) | ||
153 | #define SOCAM_PCLK_SAMPLE_RISING (1 << 9) | ||
154 | #define SOCAM_PCLK_SAMPLE_FALLING (1 << 10) | ||
155 | |||
156 | #define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \ | ||
157 | SOCAM_DATAWIDTH_10) | ||
158 | |||
159 | static inline unsigned long soc_camera_bus_param_compatible( | ||
160 | unsigned long camera_flags, unsigned long bus_flags) | ||
161 | { | ||
162 | unsigned long common_flags, hsync, vsync, pclk; | ||
163 | |||
164 | common_flags = camera_flags & bus_flags; | ||
165 | |||
166 | hsync = common_flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW); | ||
167 | vsync = common_flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW); | ||
168 | pclk = common_flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING); | ||
169 | |||
170 | return (!hsync || !vsync || !pclk) ? 0 : common_flags; | ||
171 | } | ||
148 | 172 | ||
149 | #endif | 173 | #endif |