aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/soc_camera.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <lyakh@axis700.grange>2008-12-01 07:44:59 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:38:22 -0500
commit25c4d74ea6f07f2aaa3df537619680ba967043f5 (patch)
tree58a33458a15e9720adc027ef443828550ba1f0eb /drivers/media/video/soc_camera.c
parentabe4c4710386a4859dae9193bfc9a1f0e3c60db4 (diff)
V4L/DVB (9787): soc-camera: let camera host drivers decide upon pixel format
Pixel format requested by the user is not necessarily the same, as what a sensor driver provides. There are situations, when a camera host driver provides the required format, but requires a different format from the sensor. Further, the list of formats, supported by sensors is pretty static and can be pretty good described with a constant list of structures. Whereas decisions, made by camera host drivers to support requested formats can be quite complex, therefore it is better to let the host driver do the work. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/soc_camera.c')
-rw-r--r--drivers/media/video/soc_camera.c58
1 files changed, 22 insertions, 36 deletions
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;