diff options
Diffstat (limited to 'drivers/media/video/soc_camera.c')
-rw-r--r-- | drivers/media/video/soc_camera.c | 250 |
1 files changed, 148 insertions, 102 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 20ef5c773fae..0a1cb40bfbf6 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -170,8 +170,6 @@ static int soc_camera_reqbufs(struct file *file, void *priv, | |||
170 | 170 | ||
171 | WARN_ON(priv != file->private_data); | 171 | WARN_ON(priv != file->private_data); |
172 | 172 | ||
173 | dev_dbg(&icd->dev, "%s: %d\n", __func__, p->memory); | ||
174 | |||
175 | ret = videobuf_reqbufs(&icf->vb_vidq, p); | 173 | ret = videobuf_reqbufs(&icf->vb_vidq, p); |
176 | if (ret < 0) | 174 | if (ret < 0) |
177 | return ret; | 175 | return ret; |
@@ -285,7 +283,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, | |||
285 | return ret; | 283 | return ret; |
286 | } else if (!icd->current_fmt || | 284 | } else if (!icd->current_fmt || |
287 | icd->current_fmt->fourcc != pix->pixelformat) { | 285 | icd->current_fmt->fourcc != pix->pixelformat) { |
288 | dev_err(ici->dev, | 286 | dev_err(ici->v4l2_dev.dev, |
289 | "Host driver hasn't set up current format correctly!\n"); | 287 | "Host driver hasn't set up current format correctly!\n"); |
290 | return -EINVAL; | 288 | return -EINVAL; |
291 | } | 289 | } |
@@ -308,20 +306,13 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, | |||
308 | 306 | ||
309 | static int soc_camera_open(struct file *file) | 307 | static int soc_camera_open(struct file *file) |
310 | { | 308 | { |
311 | struct video_device *vdev; | 309 | struct video_device *vdev = video_devdata(file); |
312 | struct soc_camera_device *icd; | 310 | struct soc_camera_device *icd = container_of(vdev->parent, struct soc_camera_device, dev); |
311 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
313 | struct soc_camera_host *ici; | 312 | struct soc_camera_host *ici; |
314 | struct soc_camera_file *icf; | 313 | struct soc_camera_file *icf; |
315 | int ret; | 314 | int ret; |
316 | 315 | ||
317 | /* | ||
318 | * It is safe to dereference these pointers now as long as a user has | ||
319 | * the video device open - we are protected by the held cdev reference. | ||
320 | */ | ||
321 | |||
322 | vdev = video_devdata(file); | ||
323 | icd = container_of(vdev->parent, struct soc_camera_device, dev); | ||
324 | |||
325 | if (!icd->ops) | 316 | if (!icd->ops) |
326 | /* No device driver attached */ | 317 | /* No device driver attached */ |
327 | return -ENODEV; | 318 | return -ENODEV; |
@@ -332,12 +323,6 @@ static int soc_camera_open(struct file *file) | |||
332 | if (!icf) | 323 | if (!icf) |
333 | return -ENOMEM; | 324 | return -ENOMEM; |
334 | 325 | ||
335 | if (!try_module_get(icd->ops->owner)) { | ||
336 | dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); | ||
337 | ret = -EINVAL; | ||
338 | goto emgd; | ||
339 | } | ||
340 | |||
341 | if (!try_module_get(ici->ops->owner)) { | 326 | if (!try_module_get(ici->ops->owner)) { |
342 | dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); | 327 | dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); |
343 | ret = -EINVAL; | 328 | ret = -EINVAL; |
@@ -366,47 +351,65 @@ static int soc_camera_open(struct file *file) | |||
366 | if (ret < 0) | 351 | if (ret < 0) |
367 | goto eiufmt; | 352 | goto eiufmt; |
368 | 353 | ||
369 | dev_dbg(&icd->dev, "Using fmt %x\n", icd->current_fmt->fourcc); | ||
370 | |||
371 | f.fmt.pix.pixelformat = icd->current_fmt->fourcc; | 354 | f.fmt.pix.pixelformat = icd->current_fmt->fourcc; |
372 | f.fmt.pix.colorspace = icd->current_fmt->colorspace; | 355 | f.fmt.pix.colorspace = icd->current_fmt->colorspace; |
373 | 356 | ||
357 | if (icl->power) { | ||
358 | ret = icl->power(icd->pdev, 1); | ||
359 | if (ret < 0) | ||
360 | goto epower; | ||
361 | } | ||
362 | |||
363 | /* The camera could have been already on, try to reset */ | ||
364 | if (icl->reset) | ||
365 | icl->reset(icd->pdev); | ||
366 | |||
374 | ret = ici->ops->add(icd); | 367 | ret = ici->ops->add(icd); |
375 | if (ret < 0) { | 368 | if (ret < 0) { |
376 | dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); | 369 | dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); |
377 | goto eiciadd; | 370 | goto eiciadd; |
378 | } | 371 | } |
379 | 372 | ||
373 | if (icd->ops->init) { | ||
374 | ret = icd->ops->init(icd); | ||
375 | if (ret < 0) | ||
376 | goto einit; | ||
377 | } | ||
378 | |||
380 | /* Try to configure with default parameters */ | 379 | /* Try to configure with default parameters */ |
381 | ret = soc_camera_set_fmt(icf, &f); | 380 | ret = soc_camera_set_fmt(icf, &f); |
382 | if (ret < 0) | 381 | if (ret < 0) |
383 | goto esfmt; | 382 | goto esfmt; |
384 | } | 383 | } |
385 | 384 | ||
386 | mutex_unlock(&icd->video_lock); | ||
387 | |||
388 | file->private_data = icf; | 385 | file->private_data = icf; |
389 | dev_dbg(&icd->dev, "camera device open\n"); | 386 | dev_dbg(&icd->dev, "camera device open\n"); |
390 | 387 | ||
391 | ici->ops->init_videobuf(&icf->vb_vidq, icd); | 388 | ici->ops->init_videobuf(&icf->vb_vidq, icd); |
392 | 389 | ||
390 | mutex_unlock(&icd->video_lock); | ||
391 | |||
393 | return 0; | 392 | return 0; |
394 | 393 | ||
395 | /* | 394 | /* |
396 | * First three errors are entered with the .video_lock held | 395 | * First five errors are entered with the .video_lock held |
397 | * and use_count == 1 | 396 | * and use_count == 1 |
398 | */ | 397 | */ |
399 | esfmt: | 398 | esfmt: |
399 | if (icd->ops->release) | ||
400 | icd->ops->release(icd); | ||
401 | einit: | ||
400 | ici->ops->remove(icd); | 402 | ici->ops->remove(icd); |
401 | eiciadd: | 403 | eiciadd: |
404 | if (icl->power) | ||
405 | icl->power(icd->pdev, 0); | ||
406 | epower: | ||
402 | soc_camera_free_user_formats(icd); | 407 | soc_camera_free_user_formats(icd); |
403 | eiufmt: | 408 | eiufmt: |
404 | icd->use_count--; | 409 | icd->use_count--; |
405 | mutex_unlock(&icd->video_lock); | 410 | mutex_unlock(&icd->video_lock); |
406 | module_put(ici->ops->owner); | 411 | module_put(ici->ops->owner); |
407 | emgi: | 412 | emgi: |
408 | module_put(icd->ops->owner); | ||
409 | emgd: | ||
410 | vfree(icf); | 413 | vfree(icf); |
411 | return ret; | 414 | return ret; |
412 | } | 415 | } |
@@ -421,13 +424,18 @@ static int soc_camera_close(struct file *file) | |||
421 | mutex_lock(&icd->video_lock); | 424 | mutex_lock(&icd->video_lock); |
422 | icd->use_count--; | 425 | icd->use_count--; |
423 | if (!icd->use_count) { | 426 | if (!icd->use_count) { |
427 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
428 | |||
429 | if (icd->ops->release) | ||
430 | icd->ops->release(icd); | ||
424 | ici->ops->remove(icd); | 431 | ici->ops->remove(icd); |
432 | if (icl->power) | ||
433 | icl->power(icd->pdev, 0); | ||
425 | soc_camera_free_user_formats(icd); | 434 | soc_camera_free_user_formats(icd); |
426 | } | 435 | } |
427 | 436 | ||
428 | mutex_unlock(&icd->video_lock); | 437 | mutex_unlock(&icd->video_lock); |
429 | 438 | ||
430 | module_put(icd->ops->owner); | ||
431 | module_put(ici->ops->owner); | 439 | module_put(ici->ops->owner); |
432 | 440 | ||
433 | vfree(icf); | 441 | vfree(icf); |
@@ -575,18 +583,17 @@ static int soc_camera_streamon(struct file *file, void *priv, | |||
575 | { | 583 | { |
576 | struct soc_camera_file *icf = file->private_data; | 584 | struct soc_camera_file *icf = file->private_data; |
577 | struct soc_camera_device *icd = icf->icd; | 585 | struct soc_camera_device *icd = icf->icd; |
586 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
578 | int ret; | 587 | int ret; |
579 | 588 | ||
580 | WARN_ON(priv != file->private_data); | 589 | WARN_ON(priv != file->private_data); |
581 | 590 | ||
582 | dev_dbg(&icd->dev, "%s\n", __func__); | ||
583 | |||
584 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 591 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
585 | return -EINVAL; | 592 | return -EINVAL; |
586 | 593 | ||
587 | mutex_lock(&icd->video_lock); | 594 | mutex_lock(&icd->video_lock); |
588 | 595 | ||
589 | icd->ops->start_capture(icd); | 596 | v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_stream, 1); |
590 | 597 | ||
591 | /* This calls buf_queue from host driver's videobuf_queue_ops */ | 598 | /* This calls buf_queue from host driver's videobuf_queue_ops */ |
592 | ret = videobuf_streamon(&icf->vb_vidq); | 599 | ret = videobuf_streamon(&icf->vb_vidq); |
@@ -601,11 +608,10 @@ static int soc_camera_streamoff(struct file *file, void *priv, | |||
601 | { | 608 | { |
602 | struct soc_camera_file *icf = file->private_data; | 609 | struct soc_camera_file *icf = file->private_data; |
603 | struct soc_camera_device *icd = icf->icd; | 610 | struct soc_camera_device *icd = icf->icd; |
611 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
604 | 612 | ||
605 | WARN_ON(priv != file->private_data); | 613 | WARN_ON(priv != file->private_data); |
606 | 614 | ||
607 | dev_dbg(&icd->dev, "%s\n", __func__); | ||
608 | |||
609 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 615 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
610 | return -EINVAL; | 616 | return -EINVAL; |
611 | 617 | ||
@@ -615,7 +621,7 @@ static int soc_camera_streamoff(struct file *file, void *priv, | |||
615 | * remaining buffers. When the last buffer is freed, stop capture */ | 621 | * remaining buffers. When the last buffer is freed, stop capture */ |
616 | videobuf_streamoff(&icf->vb_vidq); | 622 | videobuf_streamoff(&icf->vb_vidq); |
617 | 623 | ||
618 | icd->ops->stop_capture(icd); | 624 | v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_stream, 0); |
619 | 625 | ||
620 | mutex_unlock(&icd->video_lock); | 626 | mutex_unlock(&icd->video_lock); |
621 | 627 | ||
@@ -649,6 +655,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, | |||
649 | { | 655 | { |
650 | struct soc_camera_file *icf = file->private_data; | 656 | struct soc_camera_file *icf = file->private_data; |
651 | struct soc_camera_device *icd = icf->icd; | 657 | struct soc_camera_device *icd = icf->icd; |
658 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
652 | 659 | ||
653 | WARN_ON(priv != file->private_data); | 660 | WARN_ON(priv != file->private_data); |
654 | 661 | ||
@@ -665,9 +672,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, | |||
665 | return 0; | 672 | return 0; |
666 | } | 673 | } |
667 | 674 | ||
668 | if (icd->ops->get_control) | 675 | return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_ctrl, ctrl); |
669 | return icd->ops->get_control(icd, ctrl); | ||
670 | return -EINVAL; | ||
671 | } | 676 | } |
672 | 677 | ||
673 | static int soc_camera_s_ctrl(struct file *file, void *priv, | 678 | static int soc_camera_s_ctrl(struct file *file, void *priv, |
@@ -675,12 +680,11 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, | |||
675 | { | 680 | { |
676 | struct soc_camera_file *icf = file->private_data; | 681 | struct soc_camera_file *icf = file->private_data; |
677 | struct soc_camera_device *icd = icf->icd; | 682 | struct soc_camera_device *icd = icf->icd; |
683 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
678 | 684 | ||
679 | WARN_ON(priv != file->private_data); | 685 | WARN_ON(priv != file->private_data); |
680 | 686 | ||
681 | if (icd->ops->set_control) | 687 | return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_ctrl, ctrl); |
682 | return icd->ops->set_control(icd, ctrl); | ||
683 | return -EINVAL; | ||
684 | } | 688 | } |
685 | 689 | ||
686 | static int soc_camera_cropcap(struct file *file, void *fh, | 690 | static int soc_camera_cropcap(struct file *file, void *fh, |
@@ -751,11 +755,9 @@ static int soc_camera_g_chip_ident(struct file *file, void *fh, | |||
751 | { | 755 | { |
752 | struct soc_camera_file *icf = file->private_data; | 756 | struct soc_camera_file *icf = file->private_data; |
753 | struct soc_camera_device *icd = icf->icd; | 757 | struct soc_camera_device *icd = icf->icd; |
758 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
754 | 759 | ||
755 | if (!icd->ops->get_chip_id) | 760 | return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_chip_ident, id); |
756 | return -EINVAL; | ||
757 | |||
758 | return icd->ops->get_chip_id(icd, id); | ||
759 | } | 761 | } |
760 | 762 | ||
761 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 763 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -764,11 +766,9 @@ static int soc_camera_g_register(struct file *file, void *fh, | |||
764 | { | 766 | { |
765 | struct soc_camera_file *icf = file->private_data; | 767 | struct soc_camera_file *icf = file->private_data; |
766 | struct soc_camera_device *icd = icf->icd; | 768 | struct soc_camera_device *icd = icf->icd; |
769 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
767 | 770 | ||
768 | if (!icd->ops->get_register) | 771 | return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_register, reg); |
769 | return -EINVAL; | ||
770 | |||
771 | return icd->ops->get_register(icd, reg); | ||
772 | } | 772 | } |
773 | 773 | ||
774 | static int soc_camera_s_register(struct file *file, void *fh, | 774 | static int soc_camera_s_register(struct file *file, void *fh, |
@@ -776,11 +776,9 @@ static int soc_camera_s_register(struct file *file, void *fh, | |||
776 | { | 776 | { |
777 | struct soc_camera_file *icf = file->private_data; | 777 | struct soc_camera_file *icf = file->private_data; |
778 | struct soc_camera_device *icd = icf->icd; | 778 | struct soc_camera_device *icd = icf->icd; |
779 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
779 | 780 | ||
780 | if (!icd->ops->set_register) | 781 | return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_register, reg); |
781 | return -EINVAL; | ||
782 | |||
783 | return icd->ops->set_register(icd, reg); | ||
784 | } | 782 | } |
785 | #endif | 783 | #endif |
786 | 784 | ||
@@ -794,7 +792,7 @@ static void scan_add_host(struct soc_camera_host *ici) | |||
794 | list_for_each_entry(icd, &devices, list) { | 792 | list_for_each_entry(icd, &devices, list) { |
795 | if (icd->iface == ici->nr) { | 793 | if (icd->iface == ici->nr) { |
796 | int ret; | 794 | int ret; |
797 | icd->dev.parent = ici->dev; | 795 | icd->dev.parent = ici->v4l2_dev.dev; |
798 | dev_set_name(&icd->dev, "%u-%u", icd->iface, | 796 | dev_set_name(&icd->dev, "%u-%u", icd->iface, |
799 | icd->devnum); | 797 | icd->devnum); |
800 | ret = device_register(&icd->dev); | 798 | ret = device_register(&icd->dev); |
@@ -814,7 +812,9 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
814 | struct soc_camera_link *icl) | 812 | struct soc_camera_link *icl) |
815 | { | 813 | { |
816 | struct i2c_client *client; | 814 | struct i2c_client *client; |
815 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
817 | struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); | 816 | struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); |
817 | struct v4l2_subdev *subdev; | ||
818 | int ret; | 818 | int ret; |
819 | 819 | ||
820 | if (!adap) { | 820 | if (!adap) { |
@@ -826,17 +826,16 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
826 | 826 | ||
827 | icl->board_info->platform_data = icd; | 827 | icl->board_info->platform_data = icd; |
828 | 828 | ||
829 | client = i2c_new_device(adap, icl->board_info); | 829 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, |
830 | if (!client) { | 830 | icl->module_name, icl->board_info, NULL); |
831 | if (!subdev) { | ||
831 | ret = -ENOMEM; | 832 | ret = -ENOMEM; |
832 | goto ei2cnd; | 833 | goto ei2cnd; |
833 | } | 834 | } |
834 | 835 | ||
835 | /* | 836 | subdev->grp_id = (__u32)icd; |
836 | * We set icd drvdata at two locations - here and in | 837 | client = subdev->priv; |
837 | * soc_camera_video_start(). Depending on the module loading / | 838 | |
838 | * initialisation order one of these locations will be entered first | ||
839 | */ | ||
840 | /* Use to_i2c_client(dev) to recover the i2c client */ | 839 | /* Use to_i2c_client(dev) to recover the i2c client */ |
841 | dev_set_drvdata(&icd->dev, &client->dev); | 840 | dev_set_drvdata(&icd->dev, &client->dev); |
842 | 841 | ||
@@ -852,6 +851,7 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd) | |||
852 | struct i2c_client *client = | 851 | struct i2c_client *client = |
853 | to_i2c_client(to_soc_camera_control(icd)); | 852 | to_i2c_client(to_soc_camera_control(icd)); |
854 | dev_set_drvdata(&icd->dev, NULL); | 853 | dev_set_drvdata(&icd->dev, NULL); |
854 | v4l2_device_unregister_subdev(i2c_get_clientdata(client)); | ||
855 | i2c_unregister_device(client); | 855 | i2c_unregister_device(client); |
856 | i2c_put_adapter(client->adapter); | 856 | i2c_put_adapter(client->adapter); |
857 | } | 857 | } |
@@ -860,16 +860,37 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd) | |||
860 | #define soc_camera_free_i2c(icd) do {} while (0) | 860 | #define soc_camera_free_i2c(icd) do {} while (0) |
861 | #endif | 861 | #endif |
862 | 862 | ||
863 | static int soc_camera_video_start(struct soc_camera_device *icd); | ||
863 | static int video_dev_create(struct soc_camera_device *icd); | 864 | static int video_dev_create(struct soc_camera_device *icd); |
864 | /* Called during host-driver probe */ | 865 | /* Called during host-driver probe */ |
865 | static int soc_camera_probe(struct device *dev) | 866 | static int soc_camera_probe(struct device *dev) |
866 | { | 867 | { |
867 | struct soc_camera_device *icd = to_soc_camera_dev(dev); | 868 | struct soc_camera_device *icd = to_soc_camera_dev(dev); |
869 | struct soc_camera_host *ici = to_soc_camera_host(dev->parent); | ||
868 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 870 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
871 | struct device *control = NULL; | ||
869 | int ret; | 872 | int ret; |
870 | 873 | ||
871 | dev_info(dev, "Probing %s\n", dev_name(dev)); | 874 | dev_info(dev, "Probing %s\n", dev_name(dev)); |
872 | 875 | ||
876 | if (icl->power) { | ||
877 | ret = icl->power(icd->pdev, 1); | ||
878 | if (ret < 0) { | ||
879 | dev_err(dev, | ||
880 | "Platform failed to power-on the camera.\n"); | ||
881 | goto epower; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | /* The camera could have been already on, try to reset */ | ||
886 | if (icl->reset) | ||
887 | icl->reset(icd->pdev); | ||
888 | |||
889 | ret = ici->ops->add(icd); | ||
890 | if (ret < 0) | ||
891 | goto eadd; | ||
892 | |||
893 | /* Must have icd->vdev before registering the device */ | ||
873 | ret = video_dev_create(icd); | 894 | ret = video_dev_create(icd); |
874 | if (ret < 0) | 895 | if (ret < 0) |
875 | goto evdc; | 896 | goto evdc; |
@@ -883,34 +904,61 @@ static int soc_camera_probe(struct device *dev) | |||
883 | ret = -EINVAL; | 904 | ret = -EINVAL; |
884 | goto eadddev; | 905 | goto eadddev; |
885 | } else { | 906 | } else { |
907 | if (icl->module_name) | ||
908 | ret = request_module(icl->module_name); | ||
909 | |||
886 | ret = icl->add_device(icl, &icd->dev); | 910 | ret = icl->add_device(icl, &icd->dev); |
887 | if (ret < 0) | 911 | if (ret < 0) |
888 | goto eadddev; | 912 | goto eadddev; |
889 | } | ||
890 | 913 | ||
891 | ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, icd->vdev->minor); | 914 | /* FIXME: this is racy, have to use driver-binding notification */ |
892 | if (ret < 0) { | 915 | control = to_soc_camera_control(icd); |
893 | dev_err(&icd->dev, "video_register_device failed: %d\n", ret); | 916 | if (!control || !control->driver || |
894 | goto evidregd; | 917 | !try_module_get(control->driver->owner)) { |
918 | icl->del_device(icl); | ||
919 | goto enodrv; | ||
920 | } | ||
895 | } | 921 | } |
896 | 922 | ||
923 | /* ..._video_start() will create a device node, so we have to protect */ | ||
924 | mutex_lock(&icd->video_lock); | ||
925 | |||
926 | ret = soc_camera_video_start(icd); | ||
927 | if (ret < 0) | ||
928 | goto evidstart; | ||
929 | |||
897 | /* Do we have to sysfs_remove_link() before device_unregister()? */ | 930 | /* Do we have to sysfs_remove_link() before device_unregister()? */ |
898 | if (to_soc_camera_control(icd) && | 931 | if (to_soc_camera_control(icd) && |
899 | sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, | 932 | sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, |
900 | "control")) | 933 | "control")) |
901 | dev_warn(&icd->dev, "Failed creating the control symlink\n"); | 934 | dev_warn(&icd->dev, "Failed creating the control symlink\n"); |
902 | 935 | ||
936 | ici->ops->remove(icd); | ||
937 | |||
938 | if (icl->power) | ||
939 | icl->power(icd->pdev, 0); | ||
940 | |||
941 | mutex_unlock(&icd->video_lock); | ||
903 | 942 | ||
904 | return 0; | 943 | return 0; |
905 | 944 | ||
906 | evidregd: | 945 | evidstart: |
907 | if (icl->board_info) | 946 | mutex_unlock(&icd->video_lock); |
947 | if (icl->board_info) { | ||
908 | soc_camera_free_i2c(icd); | 948 | soc_camera_free_i2c(icd); |
909 | else | 949 | } else { |
910 | icl->del_device(icl); | 950 | icl->del_device(icl); |
951 | module_put(control->driver->owner); | ||
952 | } | ||
953 | enodrv: | ||
911 | eadddev: | 954 | eadddev: |
912 | video_device_release(icd->vdev); | 955 | video_device_release(icd->vdev); |
913 | evdc: | 956 | evdc: |
957 | ici->ops->remove(icd); | ||
958 | eadd: | ||
959 | if (icl->power) | ||
960 | icl->power(icd->pdev, 0); | ||
961 | epower: | ||
914 | return ret; | 962 | return ret; |
915 | } | 963 | } |
916 | 964 | ||
@@ -931,10 +979,16 @@ static int soc_camera_remove(struct device *dev) | |||
931 | mutex_unlock(&icd->video_lock); | 979 | mutex_unlock(&icd->video_lock); |
932 | } | 980 | } |
933 | 981 | ||
934 | if (icl->board_info) | 982 | if (icl->board_info) { |
935 | soc_camera_free_i2c(icd); | 983 | soc_camera_free_i2c(icd); |
936 | else | 984 | } else { |
937 | icl->del_device(icl); | 985 | struct device_driver *drv = to_soc_camera_control(icd) ? |
986 | to_soc_camera_control(icd)->driver : NULL; | ||
987 | if (drv) { | ||
988 | icl->del_device(icl); | ||
989 | module_put(drv->owner); | ||
990 | } | ||
991 | } | ||
938 | 992 | ||
939 | return 0; | 993 | return 0; |
940 | } | 994 | } |
@@ -984,6 +1038,7 @@ static void dummy_release(struct device *dev) | |||
984 | int soc_camera_host_register(struct soc_camera_host *ici) | 1038 | int soc_camera_host_register(struct soc_camera_host *ici) |
985 | { | 1039 | { |
986 | struct soc_camera_host *ix; | 1040 | struct soc_camera_host *ix; |
1041 | int ret; | ||
987 | 1042 | ||
988 | if (!ici || !ici->ops || | 1043 | if (!ici || !ici->ops || |
989 | !ici->ops->try_fmt || | 1044 | !ici->ops->try_fmt || |
@@ -996,18 +1051,20 @@ int soc_camera_host_register(struct soc_camera_host *ici) | |||
996 | !ici->ops->add || | 1051 | !ici->ops->add || |
997 | !ici->ops->remove || | 1052 | !ici->ops->remove || |
998 | !ici->ops->poll || | 1053 | !ici->ops->poll || |
999 | !ici->dev) | 1054 | !ici->v4l2_dev.dev) |
1000 | return -EINVAL; | 1055 | return -EINVAL; |
1001 | 1056 | ||
1002 | mutex_lock(&list_lock); | 1057 | mutex_lock(&list_lock); |
1003 | list_for_each_entry(ix, &hosts, list) { | 1058 | list_for_each_entry(ix, &hosts, list) { |
1004 | if (ix->nr == ici->nr) { | 1059 | if (ix->nr == ici->nr) { |
1005 | mutex_unlock(&list_lock); | 1060 | ret = -EBUSY; |
1006 | return -EBUSY; | 1061 | goto edevreg; |
1007 | } | 1062 | } |
1008 | } | 1063 | } |
1009 | 1064 | ||
1010 | dev_set_drvdata(ici->dev, ici); | 1065 | ret = v4l2_device_register(ici->v4l2_dev.dev, &ici->v4l2_dev); |
1066 | if (ret < 0) | ||
1067 | goto edevreg; | ||
1011 | 1068 | ||
1012 | list_add_tail(&ici->list, &hosts); | 1069 | list_add_tail(&ici->list, &hosts); |
1013 | mutex_unlock(&list_lock); | 1070 | mutex_unlock(&list_lock); |
@@ -1015,6 +1072,10 @@ int soc_camera_host_register(struct soc_camera_host *ici) | |||
1015 | scan_add_host(ici); | 1072 | scan_add_host(ici); |
1016 | 1073 | ||
1017 | return 0; | 1074 | return 0; |
1075 | |||
1076 | edevreg: | ||
1077 | mutex_unlock(&list_lock); | ||
1078 | return ret; | ||
1018 | } | 1079 | } |
1019 | EXPORT_SYMBOL(soc_camera_host_register); | 1080 | EXPORT_SYMBOL(soc_camera_host_register); |
1020 | 1081 | ||
@@ -1028,7 +1089,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) | |||
1028 | list_del(&ici->list); | 1089 | list_del(&ici->list); |
1029 | 1090 | ||
1030 | list_for_each_entry(icd, &devices, list) { | 1091 | list_for_each_entry(icd, &devices, list) { |
1031 | if (icd->dev.parent == ici->dev) { | 1092 | if (icd->iface == ici->nr) { |
1032 | /* The bus->remove will be called */ | 1093 | /* The bus->remove will be called */ |
1033 | device_unregister(&icd->dev); | 1094 | device_unregister(&icd->dev); |
1034 | /* Not before device_unregister(), .remove | 1095 | /* Not before device_unregister(), .remove |
@@ -1043,7 +1104,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) | |||
1043 | 1104 | ||
1044 | mutex_unlock(&list_lock); | 1105 | mutex_unlock(&list_lock); |
1045 | 1106 | ||
1046 | dev_set_drvdata(ici->dev, NULL); | 1107 | v4l2_device_unregister(&ici->v4l2_dev); |
1047 | } | 1108 | } |
1048 | EXPORT_SYMBOL(soc_camera_host_unregister); | 1109 | EXPORT_SYMBOL(soc_camera_host_unregister); |
1049 | 1110 | ||
@@ -1123,7 +1184,6 @@ static int video_dev_create(struct soc_camera_device *icd) | |||
1123 | 1184 | ||
1124 | if (!vdev) | 1185 | if (!vdev) |
1125 | return -ENOMEM; | 1186 | return -ENOMEM; |
1126 | dev_dbg(ici->dev, "Allocated video_device %p\n", vdev); | ||
1127 | 1187 | ||
1128 | strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); | 1188 | strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); |
1129 | 1189 | ||
@@ -1141,50 +1201,35 @@ static int video_dev_create(struct soc_camera_device *icd) | |||
1141 | } | 1201 | } |
1142 | 1202 | ||
1143 | /* | 1203 | /* |
1144 | * Usually called from the struct soc_camera_ops .probe() method, i.e., from | 1204 | * Called from soc_camera_probe() above (with .video_lock held???) |
1145 | * soc_camera_probe() above with .video_lock held | ||
1146 | */ | 1205 | */ |
1147 | int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev) | 1206 | static int soc_camera_video_start(struct soc_camera_device *icd) |
1148 | { | 1207 | { |
1149 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
1150 | const struct v4l2_queryctrl *qctrl; | 1208 | const struct v4l2_queryctrl *qctrl; |
1209 | int ret; | ||
1151 | 1210 | ||
1152 | if (!icd->dev.parent) | 1211 | if (!icd->dev.parent) |
1153 | return -ENODEV; | 1212 | return -ENODEV; |
1154 | 1213 | ||
1155 | if (!icd->ops || | 1214 | if (!icd->ops || |
1156 | !icd->ops->init || | ||
1157 | !icd->ops->release || | ||
1158 | !icd->ops->start_capture || | ||
1159 | !icd->ops->stop_capture || | ||
1160 | !icd->ops->set_fmt || | ||
1161 | !icd->ops->try_fmt || | ||
1162 | !icd->ops->query_bus_param || | 1215 | !icd->ops->query_bus_param || |
1163 | !icd->ops->set_bus_param) | 1216 | !icd->ops->set_bus_param) |
1164 | return -EINVAL; | 1217 | return -EINVAL; |
1165 | 1218 | ||
1166 | /* See comment in soc_camera_probe() */ | 1219 | ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, |
1167 | dev_set_drvdata(&icd->dev, dev); | 1220 | icd->vdev->minor); |
1221 | if (ret < 0) { | ||
1222 | dev_err(&icd->dev, "video_register_device failed: %d\n", ret); | ||
1223 | return ret; | ||
1224 | } | ||
1168 | 1225 | ||
1169 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); | 1226 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); |
1170 | icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; | 1227 | icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; |
1171 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); | 1228 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); |
1172 | icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; | 1229 | icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; |
1173 | 1230 | ||
1174 | return ici->ops->add(icd); | 1231 | return 0; |
1175 | } | ||
1176 | EXPORT_SYMBOL(soc_camera_video_start); | ||
1177 | |||
1178 | /* Called from client .remove() methods with .video_lock held */ | ||
1179 | void soc_camera_video_stop(struct soc_camera_device *icd) | ||
1180 | { | ||
1181 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
1182 | |||
1183 | dev_dbg(&icd->dev, "%s\n", __func__); | ||
1184 | |||
1185 | ici->ops->remove(icd); | ||
1186 | } | 1232 | } |
1187 | EXPORT_SYMBOL(soc_camera_video_stop); | ||
1188 | 1233 | ||
1189 | static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) | 1234 | static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) |
1190 | { | 1235 | { |
@@ -1200,6 +1245,7 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) | |||
1200 | return -ENOMEM; | 1245 | return -ENOMEM; |
1201 | 1246 | ||
1202 | icd->iface = icl->bus_id; | 1247 | icd->iface = icl->bus_id; |
1248 | icd->pdev = &pdev->dev; | ||
1203 | platform_set_drvdata(pdev, icd); | 1249 | platform_set_drvdata(pdev, icd); |
1204 | icd->dev.platform_data = icl; | 1250 | icd->dev.platform_data = icl; |
1205 | 1251 | ||