aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/soc_camera.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2008-12-01 07:45:27 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:38:24 -0500
commitc2786ad27104c558b92343e8816e18654aae1759 (patch)
tree45d36ef3dd9f8182477a6386c5063aa3f4177dbb /drivers/media/video/soc_camera.c
parentd2e3dce083bc96b3bfb71603eaa1726181f7184b (diff)
V4L/DVB (9790): soc-camera: pixel format negotiation - core support
Allocate and fill a list of formats, supported by this specific camera-host combination. Use it for format enumeration. Take care to stay backwards-compatible. Camera hosts rely on sensor formats available, as well as host specific translations. We add a structure so that hosts can define a translation table and use it for format check and setup. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> 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.c93
1 files changed, 81 insertions, 12 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 9db66a4fd1a3..5e48c2cc1a44 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -47,6 +47,18 @@ const struct soc_camera_data_format *soc_camera_format_by_fourcc(
47} 47}
48EXPORT_SYMBOL(soc_camera_format_by_fourcc); 48EXPORT_SYMBOL(soc_camera_format_by_fourcc);
49 49
50const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
51 struct soc_camera_device *icd, unsigned int fourcc)
52{
53 unsigned int i;
54
55 for (i = 0; i < icd->num_user_formats; i++)
56 if (icd->user_formats[i].host_fmt->fourcc == fourcc)
57 return icd->user_formats + i;
58 return NULL;
59}
60EXPORT_SYMBOL(soc_camera_xlate_by_fourcc);
61
50static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, 62static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
51 struct v4l2_format *f) 63 struct v4l2_format *f)
52{ 64{
@@ -161,6 +173,59 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
161 return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); 173 return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
162} 174}
163 175
176static int soc_camera_init_user_formats(struct soc_camera_device *icd)
177{
178 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
179 int i, fmts = 0;
180
181 if (!ici->ops->get_formats)
182 /*
183 * Fallback mode - the host will have to serve all
184 * sensor-provided formats one-to-one to the user
185 */
186 fmts = icd->num_formats;
187 else
188 /*
189 * First pass - only count formats this host-sensor
190 * configuration can provide
191 */
192 for (i = 0; i < icd->num_formats; i++)
193 fmts += ici->ops->get_formats(icd, i, NULL);
194
195 if (!fmts)
196 return -ENXIO;
197
198 icd->user_formats =
199 vmalloc(fmts * sizeof(struct soc_camera_format_xlate));
200 if (!icd->user_formats)
201 return -ENOMEM;
202
203 icd->num_user_formats = fmts;
204 fmts = 0;
205
206 dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts);
207
208 /* Second pass - actually fill data formats */
209 for (i = 0; i < icd->num_formats; i++)
210 if (!ici->ops->get_formats) {
211 icd->user_formats[i].host_fmt = icd->formats + i;
212 icd->user_formats[i].cam_fmt = icd->formats + i;
213 icd->user_formats[i].buswidth = icd->formats[i].depth;
214 } else {
215 fmts += ici->ops->get_formats(icd, i,
216 &icd->user_formats[fmts]);
217 }
218
219 icd->current_fmt = icd->user_formats[0].host_fmt;
220
221 return 0;
222}
223
224static void soc_camera_free_user_formats(struct soc_camera_device *icd)
225{
226 vfree(icd->user_formats);
227}
228
164static int soc_camera_open(struct inode *inode, struct file *file) 229static int soc_camera_open(struct inode *inode, struct file *file)
165{ 230{
166 struct video_device *vdev; 231 struct video_device *vdev;
@@ -197,10 +262,12 @@ static int soc_camera_open(struct inode *inode, struct file *file)
197 262
198 /* Now we really have to activate the camera */ 263 /* Now we really have to activate the camera */
199 if (icd->use_count == 1) { 264 if (icd->use_count == 1) {
265 ret = soc_camera_init_user_formats(icd);
266 if (ret < 0)
267 goto eiufmt;
200 ret = ici->ops->add(icd); 268 ret = ici->ops->add(icd);
201 if (ret < 0) { 269 if (ret < 0) {
202 dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); 270 dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
203 icd->use_count--;
204 goto eiciadd; 271 goto eiciadd;
205 } 272 }
206 } 273 }
@@ -216,6 +283,9 @@ static int soc_camera_open(struct inode *inode, struct file *file)
216 283
217 /* All errors are entered with the video_lock held */ 284 /* All errors are entered with the video_lock held */
218eiciadd: 285eiciadd:
286 soc_camera_free_user_formats(icd);
287eiufmt:
288 icd->use_count--;
219 module_put(ici->ops->owner); 289 module_put(ici->ops->owner);
220emgi: 290emgi:
221 module_put(icd->ops->owner); 291 module_put(icd->ops->owner);
@@ -234,8 +304,10 @@ static int soc_camera_close(struct inode *inode, struct file *file)
234 304
235 mutex_lock(&video_lock); 305 mutex_lock(&video_lock);
236 icd->use_count--; 306 icd->use_count--;
237 if (!icd->use_count) 307 if (!icd->use_count) {
238 ici->ops->remove(icd); 308 ici->ops->remove(icd);
309 soc_camera_free_user_formats(icd);
310 }
239 module_put(icd->ops->owner); 311 module_put(icd->ops->owner);
240 module_put(ici->ops->owner); 312 module_put(ici->ops->owner);
241 mutex_unlock(&video_lock); 313 mutex_unlock(&video_lock);
@@ -311,6 +383,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
311 struct soc_camera_device *icd = icf->icd; 383 struct soc_camera_device *icd = icf->icd;
312 struct soc_camera_host *ici = 384 struct soc_camera_host *ici =
313 to_soc_camera_host(icd->dev.parent); 385 to_soc_camera_host(icd->dev.parent);
386 __u32 pixfmt = f->fmt.pix.pixelformat;
314 int ret; 387 int ret;
315 struct v4l2_rect rect; 388 struct v4l2_rect rect;
316 389
@@ -328,14 +401,12 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
328 if (ret < 0) { 401 if (ret < 0) {
329 return ret; 402 return ret;
330 } else if (!icd->current_fmt || 403 } else if (!icd->current_fmt ||
331 icd->current_fmt->fourcc != f->fmt.pix.pixelformat) { 404 icd->current_fmt->fourcc != pixfmt) {
332 dev_err(&ici->dev, "Host driver hasn't set up current " 405 dev_err(&ici->dev,
333 "format correctly!\n"); 406 "Host driver hasn't set up current format correctly!\n");
334 return -EINVAL; 407 return -EINVAL;
335 } 408 }
336 409
337 /* buswidth may be further adjusted by the ici */
338 icd->buswidth = icd->current_fmt->depth;
339 icd->width = rect.width; 410 icd->width = rect.width;
340 icd->height = rect.height; 411 icd->height = rect.height;
341 icf->vb_vidq.field = f->fmt.pix.field; 412 icf->vb_vidq.field = f->fmt.pix.field;
@@ -347,7 +418,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
347 icd->width, icd->height); 418 icd->width, icd->height);
348 419
349 /* set physical bus parameters */ 420 /* set physical bus parameters */
350 return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat); 421 return ici->ops->set_bus_param(icd, pixfmt);
351} 422}
352 423
353static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, 424static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
@@ -359,10 +430,10 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
359 430
360 WARN_ON(priv != file->private_data); 431 WARN_ON(priv != file->private_data);
361 432
362 if (f->index >= icd->num_formats) 433 if (f->index >= icd->num_user_formats)
363 return -EINVAL; 434 return -EINVAL;
364 435
365 format = &icd->formats[f->index]; 436 format = icd->user_formats[f->index].host_fmt;
366 437
367 strlcpy(f->description, format->name, sizeof(f->description)); 438 strlcpy(f->description, format->name, sizeof(f->description));
368 f->pixelformat = format->fourcc; 439 f->pixelformat = format->fourcc;
@@ -919,8 +990,6 @@ int soc_camera_video_start(struct soc_camera_device *icd)
919 vdev->minor = -1; 990 vdev->minor = -1;
920 vdev->tvnorms = V4L2_STD_UNKNOWN, 991 vdev->tvnorms = V4L2_STD_UNKNOWN,
921 992
922 icd->current_fmt = &icd->formats[0];
923
924 err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); 993 err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
925 if (err < 0) { 994 if (err < 0) {
926 dev_err(vdev->parent, "video_register_device failed\n"); 995 dev_err(vdev->parent, "video_register_device failed\n");