aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/soc_camera.c100
1 files changed, 68 insertions, 32 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 9939b045cb4c..fcd6b2ce9c19 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -30,6 +30,10 @@
30#include <media/videobuf-core.h> 30#include <media/videobuf-core.h>
31#include <media/soc_camera.h> 31#include <media/soc_camera.h>
32 32
33/* Default to VGA resolution */
34#define DEFAULT_WIDTH 640
35#define DEFAULT_HEIGHT 480
36
33static LIST_HEAD(hosts); 37static LIST_HEAD(hosts);
34static LIST_HEAD(devices); 38static LIST_HEAD(devices);
35static DEFINE_MUTEX(list_lock); 39static DEFINE_MUTEX(list_lock);
@@ -256,6 +260,44 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd)
256 vfree(icd->user_formats); 260 vfree(icd->user_formats);
257} 261}
258 262
263/* Called with .vb_lock held */
264static int soc_camera_set_fmt(struct soc_camera_file *icf,
265 struct v4l2_format *f)
266{
267 struct soc_camera_device *icd = icf->icd;
268 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
269 struct v4l2_pix_format *pix = &f->fmt.pix;
270 int ret;
271
272 /* We always call try_fmt() before set_fmt() or set_crop() */
273 ret = ici->ops->try_fmt(icd, f);
274 if (ret < 0)
275 return ret;
276
277 ret = ici->ops->set_fmt(icd, f);
278 if (ret < 0) {
279 return ret;
280 } else if (!icd->current_fmt ||
281 icd->current_fmt->fourcc != pix->pixelformat) {
282 dev_err(&ici->dev,
283 "Host driver hasn't set up current format correctly!\n");
284 return -EINVAL;
285 }
286
287 icd->width = pix->width;
288 icd->height = pix->height;
289 icf->vb_vidq.field = pix->field;
290 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
291 dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
292 f->type);
293
294 dev_dbg(&icd->dev, "set width: %d height: %d\n",
295 icd->width, icd->height);
296
297 /* set physical bus parameters */
298 return ici->ops->set_bus_param(icd, pix->pixelformat);
299}
300
259static int soc_camera_open(struct file *file) 301static int soc_camera_open(struct file *file)
260{ 302{
261 struct video_device *vdev; 303 struct video_device *vdev;
@@ -297,6 +339,15 @@ static int soc_camera_open(struct file *file)
297 339
298 /* Now we really have to activate the camera */ 340 /* Now we really have to activate the camera */
299 if (icd->use_count == 1) { 341 if (icd->use_count == 1) {
342 struct v4l2_format f = {
343 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
344 .fmt.pix = {
345 .width = DEFAULT_WIDTH,
346 .height = DEFAULT_HEIGHT,
347 .field = V4L2_FIELD_ANY,
348 },
349 };
350
300 ret = soc_camera_init_user_formats(icd); 351 ret = soc_camera_init_user_formats(icd);
301 if (ret < 0) 352 if (ret < 0)
302 goto eiufmt; 353 goto eiufmt;
@@ -305,6 +356,14 @@ static int soc_camera_open(struct file *file)
305 dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); 356 dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
306 goto eiciadd; 357 goto eiciadd;
307 } 358 }
359
360 f.fmt.pix.pixelformat = icd->current_fmt->fourcc;
361 f.fmt.pix.colorspace = icd->current_fmt->colorspace;
362
363 /* Try to configure with default parameters */
364 ret = soc_camera_set_fmt(icf, &f);
365 if (ret < 0)
366 goto esfmt;
308 } 367 }
309 368
310 mutex_unlock(&icd->video_lock); 369 mutex_unlock(&icd->video_lock);
@@ -316,7 +375,12 @@ static int soc_camera_open(struct file *file)
316 375
317 return 0; 376 return 0;
318 377
319 /* First two errors are entered with the .video_lock held */ 378 /*
379 * First three errors are entered with the .video_lock held
380 * and use_count == 1
381 */
382esfmt:
383 ici->ops->remove(icd);
320eiciadd: 384eiciadd:
321 soc_camera_free_user_formats(icd); 385 soc_camera_free_user_formats(icd);
322eiufmt: 386eiufmt:
@@ -415,16 +479,10 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
415{ 479{
416 struct soc_camera_file *icf = file->private_data; 480 struct soc_camera_file *icf = file->private_data;
417 struct soc_camera_device *icd = icf->icd; 481 struct soc_camera_device *icd = icf->icd;
418 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
419 struct v4l2_pix_format *pix = &f->fmt.pix;
420 int ret; 482 int ret;
421 483
422 WARN_ON(priv != file->private_data); 484 WARN_ON(priv != file->private_data);
423 485
424 ret = soc_camera_try_fmt_vid_cap(file, priv, f);
425 if (ret < 0)
426 return ret;
427
428 mutex_lock(&icf->vb_vidq.vb_lock); 486 mutex_lock(&icf->vb_vidq.vb_lock);
429 487
430 if (videobuf_queue_is_busy(&icf->vb_vidq)) { 488 if (videobuf_queue_is_busy(&icf->vb_vidq)) {
@@ -433,29 +491,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
433 goto unlock; 491 goto unlock;
434 } 492 }
435 493
436 ret = ici->ops->set_fmt(icd, f); 494 ret = soc_camera_set_fmt(icf, f);
437 if (ret < 0) {
438 goto unlock;
439 } else if (!icd->current_fmt ||
440 icd->current_fmt->fourcc != pix->pixelformat) {
441 dev_err(&ici->dev,
442 "Host driver hasn't set up current format correctly!\n");
443 ret = -EINVAL;
444 goto unlock;
445 }
446
447 icd->width = f->fmt.pix.width;
448 icd->height = f->fmt.pix.height;
449 icf->vb_vidq.field = pix->field;
450 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
451 dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
452 f->type);
453
454 dev_dbg(&icd->dev, "set width: %d height: %d\n",
455 icd->width, icd->height);
456
457 /* set physical bus parameters */
458 ret = ici->ops->set_bus_param(icd, pix->pixelformat);
459 495
460unlock: 496unlock:
461 mutex_unlock(&icf->vb_vidq.vb_lock); 497 mutex_unlock(&icf->vb_vidq.vb_lock);
@@ -642,8 +678,8 @@ static int soc_camera_cropcap(struct file *file, void *fh,
642 a->bounds.height = icd->height_max; 678 a->bounds.height = icd->height_max;
643 a->defrect.left = icd->x_min; 679 a->defrect.left = icd->x_min;
644 a->defrect.top = icd->y_min; 680 a->defrect.top = icd->y_min;
645 a->defrect.width = 640; 681 a->defrect.width = DEFAULT_WIDTH;
646 a->defrect.height = 480; 682 a->defrect.height = DEFAULT_HEIGHT;
647 a->pixelaspect.numerator = 1; 683 a->pixelaspect.numerator = 1;
648 a->pixelaspect.denominator = 1; 684 a->pixelaspect.denominator = 1;
649 685