diff options
Diffstat (limited to 'drivers/media/video/soc_camera.c')
-rw-r--r-- | drivers/media/video/soc_camera.c | 156 |
1 files changed, 128 insertions, 28 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index a66811b43710..46284489e4eb 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <media/v4l2-ioctl.h> | 34 | #include <media/v4l2-ioctl.h> |
35 | #include <media/v4l2-dev.h> | 35 | #include <media/v4l2-dev.h> |
36 | #include <media/videobuf-core.h> | 36 | #include <media/videobuf-core.h> |
37 | #include <media/videobuf2-core.h> | ||
37 | #include <media/soc_mediabus.h> | 38 | #include <media/soc_mediabus.h> |
38 | 39 | ||
39 | /* Default to VGA resolution */ | 40 | /* Default to VGA resolution */ |
@@ -143,6 +144,10 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, | |||
143 | 144 | ||
144 | WARN_ON(priv != file->private_data); | 145 | WARN_ON(priv != file->private_data); |
145 | 146 | ||
147 | /* Only single-plane capture is supported so far */ | ||
148 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
149 | return -EINVAL; | ||
150 | |||
146 | /* limit format to hardware capabilities */ | 151 | /* limit format to hardware capabilities */ |
147 | return ici->ops->try_fmt(icd, f); | 152 | return ici->ops->try_fmt(icd, f); |
148 | } | 153 | } |
@@ -191,6 +196,15 @@ static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) | |||
191 | return v4l2_subdev_call(sd, core, s_std, *a); | 196 | return v4l2_subdev_call(sd, core, s_std, *a); |
192 | } | 197 | } |
193 | 198 | ||
199 | static int soc_camera_enum_fsizes(struct file *file, void *fh, | ||
200 | struct v4l2_frmsizeenum *fsize) | ||
201 | { | ||
202 | struct soc_camera_device *icd = file->private_data; | ||
203 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
204 | |||
205 | return ici->ops->enum_fsizes(icd, fsize); | ||
206 | } | ||
207 | |||
194 | static int soc_camera_reqbufs(struct file *file, void *priv, | 208 | static int soc_camera_reqbufs(struct file *file, void *priv, |
195 | struct v4l2_requestbuffers *p) | 209 | struct v4l2_requestbuffers *p) |
196 | { | 210 | { |
@@ -203,11 +217,16 @@ static int soc_camera_reqbufs(struct file *file, void *priv, | |||
203 | if (icd->streamer && icd->streamer != file) | 217 | if (icd->streamer && icd->streamer != file) |
204 | return -EBUSY; | 218 | return -EBUSY; |
205 | 219 | ||
206 | ret = videobuf_reqbufs(&icd->vb_vidq, p); | 220 | if (ici->ops->init_videobuf) { |
207 | if (ret < 0) | 221 | ret = videobuf_reqbufs(&icd->vb_vidq, p); |
208 | return ret; | 222 | if (ret < 0) |
223 | return ret; | ||
224 | |||
225 | ret = ici->ops->reqbufs(icd, p); | ||
226 | } else { | ||
227 | ret = vb2_reqbufs(&icd->vb2_vidq, p); | ||
228 | } | ||
209 | 229 | ||
210 | ret = ici->ops->reqbufs(icd, p); | ||
211 | if (!ret && !icd->streamer) | 230 | if (!ret && !icd->streamer) |
212 | icd->streamer = file; | 231 | icd->streamer = file; |
213 | 232 | ||
@@ -218,36 +237,48 @@ static int soc_camera_querybuf(struct file *file, void *priv, | |||
218 | struct v4l2_buffer *p) | 237 | struct v4l2_buffer *p) |
219 | { | 238 | { |
220 | struct soc_camera_device *icd = file->private_data; | 239 | struct soc_camera_device *icd = file->private_data; |
240 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
221 | 241 | ||
222 | WARN_ON(priv != file->private_data); | 242 | WARN_ON(priv != file->private_data); |
223 | 243 | ||
224 | return videobuf_querybuf(&icd->vb_vidq, p); | 244 | if (ici->ops->init_videobuf) |
245 | return videobuf_querybuf(&icd->vb_vidq, p); | ||
246 | else | ||
247 | return vb2_querybuf(&icd->vb2_vidq, p); | ||
225 | } | 248 | } |
226 | 249 | ||
227 | static int soc_camera_qbuf(struct file *file, void *priv, | 250 | static int soc_camera_qbuf(struct file *file, void *priv, |
228 | struct v4l2_buffer *p) | 251 | struct v4l2_buffer *p) |
229 | { | 252 | { |
230 | struct soc_camera_device *icd = file->private_data; | 253 | struct soc_camera_device *icd = file->private_data; |
254 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
231 | 255 | ||
232 | WARN_ON(priv != file->private_data); | 256 | WARN_ON(priv != file->private_data); |
233 | 257 | ||
234 | if (icd->streamer != file) | 258 | if (icd->streamer != file) |
235 | return -EBUSY; | 259 | return -EBUSY; |
236 | 260 | ||
237 | return videobuf_qbuf(&icd->vb_vidq, p); | 261 | if (ici->ops->init_videobuf) |
262 | return videobuf_qbuf(&icd->vb_vidq, p); | ||
263 | else | ||
264 | return vb2_qbuf(&icd->vb2_vidq, p); | ||
238 | } | 265 | } |
239 | 266 | ||
240 | static int soc_camera_dqbuf(struct file *file, void *priv, | 267 | static int soc_camera_dqbuf(struct file *file, void *priv, |
241 | struct v4l2_buffer *p) | 268 | struct v4l2_buffer *p) |
242 | { | 269 | { |
243 | struct soc_camera_device *icd = file->private_data; | 270 | struct soc_camera_device *icd = file->private_data; |
271 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
244 | 272 | ||
245 | WARN_ON(priv != file->private_data); | 273 | WARN_ON(priv != file->private_data); |
246 | 274 | ||
247 | if (icd->streamer != file) | 275 | if (icd->streamer != file) |
248 | return -EBUSY; | 276 | return -EBUSY; |
249 | 277 | ||
250 | return videobuf_dqbuf(&icd->vb_vidq, p, file->f_flags & O_NONBLOCK); | 278 | if (ici->ops->init_videobuf) |
279 | return videobuf_dqbuf(&icd->vb_vidq, p, file->f_flags & O_NONBLOCK); | ||
280 | else | ||
281 | return vb2_dqbuf(&icd->vb2_vidq, p, file->f_flags & O_NONBLOCK); | ||
251 | } | 282 | } |
252 | 283 | ||
253 | /* Always entered with .video_lock held */ | 284 | /* Always entered with .video_lock held */ |
@@ -362,13 +393,12 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd, | |||
362 | 393 | ||
363 | icd->user_width = pix->width; | 394 | icd->user_width = pix->width; |
364 | icd->user_height = pix->height; | 395 | icd->user_height = pix->height; |
396 | icd->bytesperline = pix->bytesperline; | ||
397 | icd->sizeimage = pix->sizeimage; | ||
365 | icd->colorspace = pix->colorspace; | 398 | icd->colorspace = pix->colorspace; |
366 | icd->vb_vidq.field = | 399 | icd->field = pix->field; |
367 | icd->field = pix->field; | 400 | if (ici->ops->init_videobuf) |
368 | 401 | icd->vb_vidq.field = pix->field; | |
369 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
370 | dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", | ||
371 | f->type); | ||
372 | 402 | ||
373 | dev_dbg(&icd->dev, "set width: %d height: %d\n", | 403 | dev_dbg(&icd->dev, "set width: %d height: %d\n", |
374 | icd->user_width, icd->user_height); | 404 | icd->user_width, icd->user_height); |
@@ -444,7 +474,13 @@ static int soc_camera_open(struct file *file) | |||
444 | if (ret < 0) | 474 | if (ret < 0) |
445 | goto esfmt; | 475 | goto esfmt; |
446 | 476 | ||
447 | ici->ops->init_videobuf(&icd->vb_vidq, icd); | 477 | if (ici->ops->init_videobuf) { |
478 | ici->ops->init_videobuf(&icd->vb_vidq, icd); | ||
479 | } else { | ||
480 | ret = ici->ops->init_videobuf2(&icd->vb2_vidq, icd); | ||
481 | if (ret < 0) | ||
482 | goto einitvb; | ||
483 | } | ||
448 | } | 484 | } |
449 | 485 | ||
450 | file->private_data = icd; | 486 | file->private_data = icd; |
@@ -456,6 +492,7 @@ static int soc_camera_open(struct file *file) | |||
456 | * First four errors are entered with the .video_lock held | 492 | * First four errors are entered with the .video_lock held |
457 | * and use_count == 1 | 493 | * and use_count == 1 |
458 | */ | 494 | */ |
495 | einitvb: | ||
459 | esfmt: | 496 | esfmt: |
460 | pm_runtime_disable(&icd->vdev->dev); | 497 | pm_runtime_disable(&icd->vdev->dev); |
461 | eresume: | 498 | eresume: |
@@ -482,6 +519,8 @@ static int soc_camera_close(struct file *file) | |||
482 | pm_runtime_disable(&icd->vdev->dev); | 519 | pm_runtime_disable(&icd->vdev->dev); |
483 | 520 | ||
484 | ici->ops->remove(icd); | 521 | ici->ops->remove(icd); |
522 | if (ici->ops->init_videobuf2) | ||
523 | vb2_queue_release(&icd->vb2_vidq); | ||
485 | 524 | ||
486 | soc_camera_power_set(icd, icl, 0); | 525 | soc_camera_power_set(icd, icl, 0); |
487 | } | 526 | } |
@@ -510,6 +549,7 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf, | |||
510 | static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) | 549 | static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) |
511 | { | 550 | { |
512 | struct soc_camera_device *icd = file->private_data; | 551 | struct soc_camera_device *icd = file->private_data; |
552 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
513 | int err; | 553 | int err; |
514 | 554 | ||
515 | dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma); | 555 | dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma); |
@@ -517,7 +557,10 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) | |||
517 | if (icd->streamer != file) | 557 | if (icd->streamer != file) |
518 | return -EBUSY; | 558 | return -EBUSY; |
519 | 559 | ||
520 | err = videobuf_mmap_mapper(&icd->vb_vidq, vma); | 560 | if (ici->ops->init_videobuf) |
561 | err = videobuf_mmap_mapper(&icd->vb_vidq, vma); | ||
562 | else | ||
563 | err = vb2_mmap(&icd->vb2_vidq, vma); | ||
521 | 564 | ||
522 | dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n", | 565 | dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n", |
523 | (unsigned long)vma->vm_start, | 566 | (unsigned long)vma->vm_start, |
@@ -535,7 +578,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) | |||
535 | if (icd->streamer != file) | 578 | if (icd->streamer != file) |
536 | return -EBUSY; | 579 | return -EBUSY; |
537 | 580 | ||
538 | if (list_empty(&icd->vb_vidq.stream)) { | 581 | if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream)) { |
539 | dev_err(&icd->dev, "Trying to poll with no queued buffers!\n"); | 582 | dev_err(&icd->dev, "Trying to poll with no queued buffers!\n"); |
540 | return POLLERR; | 583 | return POLLERR; |
541 | } | 584 | } |
@@ -543,6 +586,20 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) | |||
543 | return ici->ops->poll(file, pt); | 586 | return ici->ops->poll(file, pt); |
544 | } | 587 | } |
545 | 588 | ||
589 | void soc_camera_lock(struct vb2_queue *vq) | ||
590 | { | ||
591 | struct soc_camera_device *icd = vb2_get_drv_priv(vq); | ||
592 | mutex_lock(&icd->video_lock); | ||
593 | } | ||
594 | EXPORT_SYMBOL(soc_camera_lock); | ||
595 | |||
596 | void soc_camera_unlock(struct vb2_queue *vq) | ||
597 | { | ||
598 | struct soc_camera_device *icd = vb2_get_drv_priv(vq); | ||
599 | mutex_unlock(&icd->video_lock); | ||
600 | } | ||
601 | EXPORT_SYMBOL(soc_camera_unlock); | ||
602 | |||
546 | static struct v4l2_file_operations soc_camera_fops = { | 603 | static struct v4l2_file_operations soc_camera_fops = { |
547 | .owner = THIS_MODULE, | 604 | .owner = THIS_MODULE, |
548 | .open = soc_camera_open, | 605 | .open = soc_camera_open, |
@@ -561,6 +618,11 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, | |||
561 | 618 | ||
562 | WARN_ON(priv != file->private_data); | 619 | WARN_ON(priv != file->private_data); |
563 | 620 | ||
621 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
622 | dev_warn(&icd->dev, "Wrong buf-type %d\n", f->type); | ||
623 | return -EINVAL; | ||
624 | } | ||
625 | |||
564 | if (icd->streamer && icd->streamer != file) | 626 | if (icd->streamer && icd->streamer != file) |
565 | return -EBUSY; | 627 | return -EBUSY; |
566 | 628 | ||
@@ -604,16 +666,16 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, | |||
604 | 666 | ||
605 | WARN_ON(priv != file->private_data); | 667 | WARN_ON(priv != file->private_data); |
606 | 668 | ||
669 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
670 | return -EINVAL; | ||
671 | |||
607 | pix->width = icd->user_width; | 672 | pix->width = icd->user_width; |
608 | pix->height = icd->user_height; | 673 | pix->height = icd->user_height; |
609 | pix->field = icd->vb_vidq.field; | 674 | pix->bytesperline = icd->bytesperline; |
675 | pix->sizeimage = icd->sizeimage; | ||
676 | pix->field = icd->field; | ||
610 | pix->pixelformat = icd->current_fmt->host_fmt->fourcc; | 677 | pix->pixelformat = icd->current_fmt->host_fmt->fourcc; |
611 | pix->bytesperline = soc_mbus_bytes_per_line(pix->width, | ||
612 | icd->current_fmt->host_fmt); | ||
613 | pix->colorspace = icd->colorspace; | 678 | pix->colorspace = icd->colorspace; |
614 | if (pix->bytesperline < 0) | ||
615 | return pix->bytesperline; | ||
616 | pix->sizeimage = pix->height * pix->bytesperline; | ||
617 | dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", | 679 | dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", |
618 | icd->current_fmt->host_fmt->fourcc); | 680 | icd->current_fmt->host_fmt->fourcc); |
619 | return 0; | 681 | return 0; |
@@ -635,6 +697,7 @@ static int soc_camera_streamon(struct file *file, void *priv, | |||
635 | enum v4l2_buf_type i) | 697 | enum v4l2_buf_type i) |
636 | { | 698 | { |
637 | struct soc_camera_device *icd = file->private_data; | 699 | struct soc_camera_device *icd = file->private_data; |
700 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
638 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 701 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
639 | int ret; | 702 | int ret; |
640 | 703 | ||
@@ -646,10 +709,14 @@ static int soc_camera_streamon(struct file *file, void *priv, | |||
646 | if (icd->streamer != file) | 709 | if (icd->streamer != file) |
647 | return -EBUSY; | 710 | return -EBUSY; |
648 | 711 | ||
649 | v4l2_subdev_call(sd, video, s_stream, 1); | ||
650 | |||
651 | /* This calls buf_queue from host driver's videobuf_queue_ops */ | 712 | /* This calls buf_queue from host driver's videobuf_queue_ops */ |
652 | ret = videobuf_streamon(&icd->vb_vidq); | 713 | if (ici->ops->init_videobuf) |
714 | ret = videobuf_streamon(&icd->vb_vidq); | ||
715 | else | ||
716 | ret = vb2_streamon(&icd->vb2_vidq, i); | ||
717 | |||
718 | if (!ret) | ||
719 | v4l2_subdev_call(sd, video, s_stream, 1); | ||
653 | 720 | ||
654 | return ret; | 721 | return ret; |
655 | } | 722 | } |
@@ -659,6 +726,7 @@ static int soc_camera_streamoff(struct file *file, void *priv, | |||
659 | { | 726 | { |
660 | struct soc_camera_device *icd = file->private_data; | 727 | struct soc_camera_device *icd = file->private_data; |
661 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 728 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
729 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
662 | 730 | ||
663 | WARN_ON(priv != file->private_data); | 731 | WARN_ON(priv != file->private_data); |
664 | 732 | ||
@@ -672,7 +740,10 @@ static int soc_camera_streamoff(struct file *file, void *priv, | |||
672 | * This calls buf_release from host driver's videobuf_queue_ops for all | 740 | * This calls buf_release from host driver's videobuf_queue_ops for all |
673 | * remaining buffers. When the last buffer is freed, stop capture | 741 | * remaining buffers. When the last buffer is freed, stop capture |
674 | */ | 742 | */ |
675 | videobuf_streamoff(&icd->vb_vidq); | 743 | if (ici->ops->init_videobuf) |
744 | videobuf_streamoff(&icd->vb_vidq); | ||
745 | else | ||
746 | vb2_streamoff(&icd->vb2_vidq, i); | ||
676 | 747 | ||
677 | v4l2_subdev_call(sd, video, s_stream, 0); | 748 | v4l2_subdev_call(sd, video, s_stream, 0); |
678 | 749 | ||
@@ -1175,6 +1246,31 @@ static int default_s_parm(struct soc_camera_device *icd, | |||
1175 | return v4l2_subdev_call(sd, video, s_parm, parm); | 1246 | return v4l2_subdev_call(sd, video, s_parm, parm); |
1176 | } | 1247 | } |
1177 | 1248 | ||
1249 | static int default_enum_fsizes(struct soc_camera_device *icd, | ||
1250 | struct v4l2_frmsizeenum *fsize) | ||
1251 | { | ||
1252 | int ret; | ||
1253 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1254 | const struct soc_camera_format_xlate *xlate; | ||
1255 | __u32 pixfmt = fsize->pixel_format; | ||
1256 | struct v4l2_frmsizeenum fsize_mbus = *fsize; | ||
1257 | |||
1258 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | ||
1259 | if (!xlate) | ||
1260 | return -EINVAL; | ||
1261 | /* map xlate-code to pixel_format, sensor only handle xlate-code*/ | ||
1262 | fsize_mbus.pixel_format = xlate->code; | ||
1263 | |||
1264 | ret = v4l2_subdev_call(sd, video, enum_mbus_fsizes, &fsize_mbus); | ||
1265 | if (ret < 0) | ||
1266 | return ret; | ||
1267 | |||
1268 | *fsize = fsize_mbus; | ||
1269 | fsize->pixel_format = pixfmt; | ||
1270 | |||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1178 | static void soc_camera_device_init(struct device *dev, void *pdata) | 1274 | static void soc_camera_device_init(struct device *dev, void *pdata) |
1179 | { | 1275 | { |
1180 | dev->platform_data = pdata; | 1276 | dev->platform_data = pdata; |
@@ -1192,8 +1288,9 @@ int soc_camera_host_register(struct soc_camera_host *ici) | |||
1192 | !ici->ops->set_fmt || | 1288 | !ici->ops->set_fmt || |
1193 | !ici->ops->set_bus_param || | 1289 | !ici->ops->set_bus_param || |
1194 | !ici->ops->querycap || | 1290 | !ici->ops->querycap || |
1195 | !ici->ops->init_videobuf || | 1291 | ((!ici->ops->init_videobuf || |
1196 | !ici->ops->reqbufs || | 1292 | !ici->ops->reqbufs) && |
1293 | !ici->ops->init_videobuf2) || | ||
1197 | !ici->ops->add || | 1294 | !ici->ops->add || |
1198 | !ici->ops->remove || | 1295 | !ici->ops->remove || |
1199 | !ici->ops->poll || | 1296 | !ici->ops->poll || |
@@ -1210,6 +1307,8 @@ int soc_camera_host_register(struct soc_camera_host *ici) | |||
1210 | ici->ops->set_parm = default_s_parm; | 1307 | ici->ops->set_parm = default_s_parm; |
1211 | if (!ici->ops->get_parm) | 1308 | if (!ici->ops->get_parm) |
1212 | ici->ops->get_parm = default_g_parm; | 1309 | ici->ops->get_parm = default_g_parm; |
1310 | if (!ici->ops->enum_fsizes) | ||
1311 | ici->ops->enum_fsizes = default_enum_fsizes; | ||
1213 | 1312 | ||
1214 | mutex_lock(&list_lock); | 1313 | mutex_lock(&list_lock); |
1215 | list_for_each_entry(ix, &hosts, list) { | 1314 | list_for_each_entry(ix, &hosts, list) { |
@@ -1317,6 +1416,7 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { | |||
1317 | .vidioc_g_input = soc_camera_g_input, | 1416 | .vidioc_g_input = soc_camera_g_input, |
1318 | .vidioc_s_input = soc_camera_s_input, | 1417 | .vidioc_s_input = soc_camera_s_input, |
1319 | .vidioc_s_std = soc_camera_s_std, | 1418 | .vidioc_s_std = soc_camera_s_std, |
1419 | .vidioc_enum_framesizes = soc_camera_enum_fsizes, | ||
1320 | .vidioc_reqbufs = soc_camera_reqbufs, | 1420 | .vidioc_reqbufs = soc_camera_reqbufs, |
1321 | .vidioc_try_fmt_vid_cap = soc_camera_try_fmt_vid_cap, | 1421 | .vidioc_try_fmt_vid_cap = soc_camera_try_fmt_vid_cap, |
1322 | .vidioc_querybuf = soc_camera_querybuf, | 1422 | .vidioc_querybuf = soc_camera_querybuf, |