aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/pxa_camera.c32
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c32
-rw-r--r--drivers/media/video/soc_camera.c58
-rw-r--r--include/media/soc_camera.h3
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)
907static int pxa_camera_set_fmt_cap(struct soc_camera_device *icd, 907static 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
913static int pxa_camera_try_fmt_cap(struct soc_camera_device *icd, 930static 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,
453static int sh_mobile_ceu_set_fmt_cap(struct soc_camera_device *icd, 453static 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
459static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd, 476static 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);
35static DEFINE_MUTEX(list_lock); 35static DEFINE_MUTEX(list_lock);
36static DEFINE_MUTEX(video_lock); 36static DEFINE_MUTEX(video_lock);
37 37
38const static struct soc_camera_data_format *format_by_fourcc( 38const 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}
48EXPORT_SYMBOL(soc_camera_format_by_fourcc);
48 49
49static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, 50static 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);
105extern int soc_camera_video_start(struct soc_camera_device *icd); 105extern int soc_camera_video_start(struct soc_camera_device *icd);
106extern void soc_camera_video_stop(struct soc_camera_device *icd); 106extern void soc_camera_video_stop(struct soc_camera_device *icd);
107 107
108extern const struct soc_camera_data_format *soc_camera_format_by_fourcc(
109 struct soc_camera_device *icd, unsigned int fourcc);
110
108struct soc_camera_data_format { 111struct soc_camera_data_format {
109 const char *name; 112 const char *name;
110 unsigned int depth; 113 unsigned int depth;