diff options
-rw-r--r-- | drivers/media/video/pxa_camera.c | 32 | ||||
-rw-r--r-- | drivers/media/video/sh_mobile_ceu_camera.c | 32 | ||||
-rw-r--r-- | drivers/media/video/soc_camera.c | 58 | ||||
-rw-r--r-- | include/media/soc_camera.h | 3 |
4 files changed, 87 insertions, 38 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 2a811f8584b5..a375872b1342 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -907,17 +907,43 @@ static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
907 | static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd, | 907 | static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd, |
908 | __u32 pixfmt, struct v4l2_rect *rect) | 908 | __u32 pixfmt, struct v4l2_rect *rect) |
909 | { | 909 | { |
910 | return icd->ops->set_fmt_cap(icd, pixfmt, rect); | 910 | const struct soc_camera_data_format *cam_fmt; |
911 | int ret; | ||
912 | |||
913 | /* | ||
914 | * TODO: find a suitable supported by the SoC output format, check | ||
915 | * whether the sensor supports one of acceptable input formats. | ||
916 | */ | ||
917 | if (pixfmt) { | ||
918 | cam_fmt = soc_camera_format_by_fourcc(icd, pixfmt); | ||
919 | if (!cam_fmt) | ||
920 | return -EINVAL; | ||
921 | } | ||
922 | |||
923 | ret = icd->ops->set_fmt_cap(icd, pixfmt, rect); | ||
924 | if (pixfmt && !ret) | ||
925 | icd->current_fmt = cam_fmt; | ||
926 | |||
927 | return ret; | ||
911 | } | 928 | } |
912 | 929 | ||
913 | static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, | 930 | static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, |
914 | struct v4l2_format *f) | 931 | struct v4l2_format *f) |
915 | { | 932 | { |
933 | const struct soc_camera_data_format *cam_fmt; | ||
916 | int ret = pxa_camera_try_bus_param(icd, f->fmt.pix.pixelformat); | 934 | int ret = pxa_camera_try_bus_param(icd, f->fmt.pix.pixelformat); |
917 | 935 | ||
918 | if (ret < 0) | 936 | if (ret < 0) |
919 | return ret; | 937 | return ret; |
920 | 938 | ||
939 | /* | ||
940 | * TODO: find a suitable supported by the SoC output format, check | ||
941 | * whether the sensor supports one of acceptable input formats. | ||
942 | */ | ||
943 | cam_fmt = soc_camera_format_by_fourcc(icd, f->fmt.pix.pixelformat); | ||
944 | if (!cam_fmt) | ||
945 | return -EINVAL; | ||
946 | |||
921 | /* limit to pxa hardware capabilities */ | 947 | /* limit to pxa hardware capabilities */ |
922 | if (f->fmt.pix.height < 32) | 948 | if (f->fmt.pix.height < 32) |
923 | f->fmt.pix.height = 32; | 949 | f->fmt.pix.height = 32; |
@@ -929,6 +955,10 @@ static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, | |||
929 | f->fmt.pix.width = 2048; | 955 | f->fmt.pix.width = 2048; |
930 | f->fmt.pix.width &= ~0x01; | 956 | f->fmt.pix.width &= ~0x01; |
931 | 957 | ||
958 | f->fmt.pix.bytesperline = f->fmt.pix.width * | ||
959 | DIV_ROUND_UP(cam_fmt->depth, 8); | ||
960 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
961 | |||
932 | /* limit to sensor capabilities */ | 962 | /* limit to sensor capabilities */ |
933 | return icd->ops->try_fmt_cap(icd, f); | 963 | return icd->ops->try_fmt_cap(icd, f); |
934 | } | 964 | } |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 87d0f3075811..02f846d1908b 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -453,17 +453,43 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd, | |||
453 | static int sh_mobile_ceu_set_fmt_cap(struct soc_camera_device *icd, | 453 | static int sh_mobile_ceu_set_fmt_cap(struct soc_camera_device *icd, |
454 | __u32 pixfmt, struct v4l2_rect *rect) | 454 | __u32 pixfmt, struct v4l2_rect *rect) |
455 | { | 455 | { |
456 | return icd->ops->set_fmt_cap(icd, pixfmt, rect); | 456 | const struct soc_camera_data_format *cam_fmt; |
457 | int ret; | ||
458 | |||
459 | /* | ||
460 | * TODO: find a suitable supported by the SoC output format, check | ||
461 | * whether the sensor supports one of acceptable input formats. | ||
462 | */ | ||
463 | if (pixfmt) { | ||
464 | cam_fmt = soc_camera_format_by_fourcc(icd, pixfmt); | ||
465 | if (!cam_fmt) | ||
466 | return -EINVAL; | ||
467 | } | ||
468 | |||
469 | ret = icd->ops->set_fmt_cap(icd, pixfmt, rect); | ||
470 | if (pixfmt && !ret) | ||
471 | icd->current_fmt = cam_fmt; | ||
472 | |||
473 | return ret; | ||
457 | } | 474 | } |
458 | 475 | ||
459 | static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd, | 476 | static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd, |
460 | struct v4l2_format *f) | 477 | struct v4l2_format *f) |
461 | { | 478 | { |
479 | const struct soc_camera_data_format *cam_fmt; | ||
462 | int ret = sh_mobile_ceu_try_bus_param(icd, f->fmt.pix.pixelformat); | 480 | int ret = sh_mobile_ceu_try_bus_param(icd, f->fmt.pix.pixelformat); |
463 | 481 | ||
464 | if (ret < 0) | 482 | if (ret < 0) |
465 | return ret; | 483 | return ret; |
466 | 484 | ||
485 | /* | ||
486 | * TODO: find a suitable supported by the SoC output format, check | ||
487 | * whether the sensor supports one of acceptable input formats. | ||
488 | */ | ||
489 | cam_fmt = soc_camera_format_by_fourcc(icd, f->fmt.pix.pixelformat); | ||
490 | if (!cam_fmt) | ||
491 | return -EINVAL; | ||
492 | |||
467 | /* FIXME: calculate using depth and bus width */ | 493 | /* FIXME: calculate using depth and bus width */ |
468 | 494 | ||
469 | if (f->fmt.pix.height < 4) | 495 | if (f->fmt.pix.height < 4) |
@@ -477,6 +503,10 @@ static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd, | |||
477 | f->fmt.pix.width &= ~0x01; | 503 | f->fmt.pix.width &= ~0x01; |
478 | f->fmt.pix.height &= ~0x03; | 504 | f->fmt.pix.height &= ~0x03; |
479 | 505 | ||
506 | f->fmt.pix.bytesperline = f->fmt.pix.width * | ||
507 | DIV_ROUND_UP(cam_fmt->depth, 8); | ||
508 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
509 | |||
480 | /* limit to sensor capabilities */ | 510 | /* limit to sensor capabilities */ |
481 | return icd->ops->try_fmt_cap(icd, f); | 511 | return icd->ops->try_fmt_cap(icd, f); |
482 | } | 512 | } |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 7217de21e76b..01c33841d1c6 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -35,7 +35,7 @@ static LIST_HEAD(devices); | |||
35 | static DEFINE_MUTEX(list_lock); | 35 | static DEFINE_MUTEX(list_lock); |
36 | static DEFINE_MUTEX(video_lock); | 36 | static DEFINE_MUTEX(video_lock); |
37 | 37 | ||
38 | const static struct soc_camera_data_format *format_by_fourcc( | 38 | const struct soc_camera_data_format *soc_camera_format_by_fourcc( |
39 | struct soc_camera_device *icd, unsigned int fourcc) | 39 | struct soc_camera_device *icd, unsigned int fourcc) |
40 | { | 40 | { |
41 | unsigned int i; | 41 | unsigned int i; |
@@ -45,6 +45,7 @@ const static struct soc_camera_data_format *format_by_fourcc( | |||
45 | return icd->formats + i; | 45 | return icd->formats + i; |
46 | return NULL; | 46 | return NULL; |
47 | } | 47 | } |
48 | EXPORT_SYMBOL(soc_camera_format_by_fourcc); | ||
48 | 49 | ||
49 | static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, | 50 | static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, |
50 | struct v4l2_format *f) | 51 | struct v4l2_format *f) |
@@ -54,25 +55,19 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, | |||
54 | struct soc_camera_host *ici = | 55 | struct soc_camera_host *ici = |
55 | to_soc_camera_host(icd->dev.parent); | 56 | to_soc_camera_host(icd->dev.parent); |
56 | enum v4l2_field field; | 57 | enum v4l2_field field; |
57 | const struct soc_camera_data_format *fmt; | ||
58 | int ret; | 58 | int ret; |
59 | 59 | ||
60 | WARN_ON(priv != file->private_data); | 60 | WARN_ON(priv != file->private_data); |
61 | 61 | ||
62 | fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); | 62 | /* |
63 | if (!fmt) { | 63 | * TODO: this might also have to migrate to host-drivers, if anyone |
64 | dev_dbg(&icd->dev, "invalid format 0x%08x\n", | 64 | * wishes to support other fields |
65 | f->fmt.pix.pixelformat); | 65 | */ |
66 | return -EINVAL; | ||
67 | } | ||
68 | |||
69 | dev_dbg(&icd->dev, "fmt: 0x%08x\n", fmt->fourcc); | ||
70 | |||
71 | field = f->fmt.pix.field; | 66 | field = f->fmt.pix.field; |
72 | 67 | ||
73 | if (field == V4L2_FIELD_ANY) { | 68 | if (field == V4L2_FIELD_ANY) { |
74 | field = V4L2_FIELD_NONE; | 69 | f->fmt.pix.field = V4L2_FIELD_NONE; |
75 | } else if (V4L2_FIELD_NONE != field) { | 70 | } else if (field != V4L2_FIELD_NONE) { |
76 | dev_err(&icd->dev, "Field type invalid.\n"); | 71 | dev_err(&icd->dev, "Field type invalid.\n"); |
77 | return -EINVAL; | 72 | return -EINVAL; |
78 | } | 73 | } |
@@ -80,13 +75,6 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, | |||
80 | /* limit format to hardware capabilities */ | 75 | /* limit format to hardware capabilities */ |
81 | ret = ici->ops->try_fmt_cap(icd, f); | 76 | ret = ici->ops->try_fmt_cap(icd, f); |
82 | 77 | ||
83 | /* calculate missing fields */ | ||
84 | f->fmt.pix.field = field; | ||
85 | f->fmt.pix.bytesperline = | ||
86 | (f->fmt.pix.width * fmt->depth) >> 3; | ||
87 | f->fmt.pix.sizeimage = | ||
88 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
89 | |||
90 | return ret; | 78 | return ret; |
91 | } | 79 | } |
92 | 80 | ||
@@ -325,18 +313,10 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, | |||
325 | to_soc_camera_host(icd->dev.parent); | 313 | to_soc_camera_host(icd->dev.parent); |
326 | int ret; | 314 | int ret; |
327 | struct v4l2_rect rect; | 315 | struct v4l2_rect rect; |
328 | const static struct soc_camera_data_format *data_fmt; | ||
329 | 316 | ||
330 | WARN_ON(priv != file->private_data); | 317 | WARN_ON(priv != file->private_data); |
331 | 318 | ||
332 | data_fmt = format_by_fourcc(icd, f->fmt.pix.pixelformat); | 319 | ret = soc_camera_try_fmt_vid_cap(file, priv, f); |
333 | if (!data_fmt) | ||
334 | return -EINVAL; | ||
335 | |||
336 | /* buswidth may be further adjusted by the ici */ | ||
337 | icd->buswidth = data_fmt->depth; | ||
338 | |||
339 | ret = soc_camera_try_fmt_vid_cap(file, icf, f); | ||
340 | if (ret < 0) | 320 | if (ret < 0) |
341 | return ret; | 321 | return ret; |
342 | 322 | ||
@@ -345,14 +325,21 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, | |||
345 | rect.width = f->fmt.pix.width; | 325 | rect.width = f->fmt.pix.width; |
346 | rect.height = f->fmt.pix.height; | 326 | rect.height = f->fmt.pix.height; |
347 | ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); | 327 | ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); |
348 | if (ret < 0) | 328 | if (ret < 0) { |
349 | return ret; | 329 | return ret; |
330 | } else if (!icd->current_fmt || | ||
331 | icd->current_fmt->fourcc != f->fmt.pix.pixelformat) { | ||
332 | dev_err(&ici->dev, "Host driver hasn't set up current " | ||
333 | "format correctly!\n"); | ||
334 | return -EINVAL; | ||
335 | } | ||
350 | 336 | ||
351 | icd->current_fmt = data_fmt; | 337 | /* buswidth may be further adjusted by the ici */ |
338 | icd->buswidth = icd->current_fmt->depth; | ||
352 | icd->width = rect.width; | 339 | icd->width = rect.width; |
353 | icd->height = rect.height; | 340 | icd->height = rect.height; |
354 | icf->vb_vidq.field = f->fmt.pix.field; | 341 | icf->vb_vidq.field = f->fmt.pix.field; |
355 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) | 342 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
356 | dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", | 343 | dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", |
357 | f->type); | 344 | f->type); |
358 | 345 | ||
@@ -394,10 +381,9 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, | |||
394 | f->fmt.pix.height = icd->height; | 381 | f->fmt.pix.height = icd->height; |
395 | f->fmt.pix.field = icf->vb_vidq.field; | 382 | f->fmt.pix.field = icf->vb_vidq.field; |
396 | f->fmt.pix.pixelformat = icd->current_fmt->fourcc; | 383 | f->fmt.pix.pixelformat = icd->current_fmt->fourcc; |
397 | f->fmt.pix.bytesperline = | 384 | f->fmt.pix.bytesperline = f->fmt.pix.width * |
398 | (f->fmt.pix.width * icd->current_fmt->depth) >> 3; | 385 | DIV_ROUND_UP(icd->current_fmt->depth, 8); |
399 | f->fmt.pix.sizeimage = | 386 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
400 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
401 | dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", | 387 | dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", |
402 | icd->current_fmt->fourcc); | 388 | icd->current_fmt->fourcc); |
403 | return 0; | 389 | return 0; |
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index ee0e6b4bed33..8e8fcb75dacb 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h | |||
@@ -105,6 +105,9 @@ extern void soc_camera_device_unregister(struct soc_camera_device *icd); | |||
105 | extern int soc_camera_video_start(struct soc_camera_device *icd); | 105 | extern int soc_camera_video_start(struct soc_camera_device *icd); |
106 | extern void soc_camera_video_stop(struct soc_camera_device *icd); | 106 | extern void soc_camera_video_stop(struct soc_camera_device *icd); |
107 | 107 | ||
108 | extern const struct soc_camera_data_format *soc_camera_format_by_fourcc( | ||
109 | struct soc_camera_device *icd, unsigned int fourcc); | ||
110 | |||
108 | struct soc_camera_data_format { | 111 | struct soc_camera_data_format { |
109 | const char *name; | 112 | const char *name; |
110 | unsigned int depth; | 113 | unsigned int depth; |