diff options
Diffstat (limited to 'drivers/media/video/tw9910.c')
-rw-r--r-- | drivers/media/video/tw9910.c | 151 |
1 files changed, 63 insertions, 88 deletions
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index d780a509faa9..a006df1d28ec 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/videodev2.h> | 25 | #include <linux/videodev2.h> |
26 | #include <media/v4l2-chip-ident.h> | 26 | #include <media/v4l2-chip-ident.h> |
27 | #include <media/v4l2-common.h> | 27 | #include <media/v4l2-subdev.h> |
28 | #include <media/soc_camera.h> | 28 | #include <media/soc_camera.h> |
29 | #include <media/tw9910.h> | 29 | #include <media/tw9910.h> |
30 | 30 | ||
@@ -223,6 +223,7 @@ struct tw9910_hsync_ctrl { | |||
223 | }; | 223 | }; |
224 | 224 | ||
225 | struct tw9910_priv { | 225 | struct tw9910_priv { |
226 | struct v4l2_subdev subdev; | ||
226 | struct tw9910_video_info *info; | 227 | struct tw9910_video_info *info; |
227 | const struct tw9910_scale_ctrl *scale; | 228 | const struct tw9910_scale_ctrl *scale; |
228 | }; | 229 | }; |
@@ -354,6 +355,11 @@ static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = { | |||
354 | /* | 355 | /* |
355 | * general function | 356 | * general function |
356 | */ | 357 | */ |
358 | static struct tw9910_priv *to_tw9910(const struct i2c_client *client) | ||
359 | { | ||
360 | return container_of(i2c_get_clientdata(client), struct tw9910_priv, subdev); | ||
361 | } | ||
362 | |||
357 | static int tw9910_set_scale(struct i2c_client *client, | 363 | static int tw9910_set_scale(struct i2c_client *client, |
358 | const struct tw9910_scale_ctrl *scale) | 364 | const struct tw9910_scale_ctrl *scale) |
359 | { | 365 | { |
@@ -507,47 +513,20 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height) | |||
507 | /* | 513 | /* |
508 | * soc_camera_ops function | 514 | * soc_camera_ops function |
509 | */ | 515 | */ |
510 | static int tw9910_init(struct soc_camera_device *icd) | 516 | static int tw9910_s_stream(struct v4l2_subdev *sd, int enable) |
511 | { | 517 | { |
512 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 518 | struct i2c_client *client = sd->priv; |
513 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 519 | struct tw9910_priv *priv = to_tw9910(client); |
514 | int ret = 0; | ||
515 | 520 | ||
516 | if (icl->power) { | 521 | if (!enable) |
517 | ret = icl->power(&client->dev, 1); | 522 | return 0; |
518 | if (ret < 0) | ||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | if (icl->reset) | ||
523 | ret = icl->reset(&client->dev); | ||
524 | |||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | static int tw9910_release(struct soc_camera_device *icd) | ||
529 | { | ||
530 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
531 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
532 | int ret = 0; | ||
533 | |||
534 | if (icl->power) | ||
535 | ret = icl->power(&client->dev, 0); | ||
536 | |||
537 | return ret; | ||
538 | } | ||
539 | |||
540 | static int tw9910_start_capture(struct soc_camera_device *icd) | ||
541 | { | ||
542 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
543 | struct tw9910_priv *priv = i2c_get_clientdata(client); | ||
544 | 523 | ||
545 | if (!priv->scale) { | 524 | if (!priv->scale) { |
546 | dev_err(&icd->dev, "norm select error\n"); | 525 | dev_err(&client->dev, "norm select error\n"); |
547 | return -EPERM; | 526 | return -EPERM; |
548 | } | 527 | } |
549 | 528 | ||
550 | dev_dbg(&icd->dev, "%s %dx%d\n", | 529 | dev_dbg(&client->dev, "%s %dx%d\n", |
551 | priv->scale->name, | 530 | priv->scale->name, |
552 | priv->scale->width, | 531 | priv->scale->width, |
553 | priv->scale->height); | 532 | priv->scale->height); |
@@ -555,11 +534,6 @@ static int tw9910_start_capture(struct soc_camera_device *icd) | |||
555 | return 0; | 534 | return 0; |
556 | } | 535 | } |
557 | 536 | ||
558 | static int tw9910_stop_capture(struct soc_camera_device *icd) | ||
559 | { | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static int tw9910_set_bus_param(struct soc_camera_device *icd, | 537 | static int tw9910_set_bus_param(struct soc_camera_device *icd, |
564 | unsigned long flags) | 538 | unsigned long flags) |
565 | { | 539 | { |
@@ -569,7 +543,7 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd, | |||
569 | static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) | 543 | static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) |
570 | { | 544 | { |
571 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 545 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
572 | struct tw9910_priv *priv = i2c_get_clientdata(client); | 546 | struct tw9910_priv *priv = to_tw9910(client); |
573 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 547 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
574 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | | 548 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | |
575 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | | 549 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | |
@@ -578,21 +552,11 @@ static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) | |||
578 | return soc_camera_apply_sensor_flags(icl, flags); | 552 | return soc_camera_apply_sensor_flags(icl, flags); |
579 | } | 553 | } |
580 | 554 | ||
581 | static int tw9910_get_chip_id(struct soc_camera_device *icd, | 555 | static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) |
582 | struct v4l2_dbg_chip_ident *id) | ||
583 | { | ||
584 | id->ident = V4L2_IDENT_TW9910; | ||
585 | id->revision = 0; | ||
586 | |||
587 | return 0; | ||
588 | } | ||
589 | |||
590 | static int tw9910_set_std(struct soc_camera_device *icd, | ||
591 | v4l2_std_id *a) | ||
592 | { | 556 | { |
593 | int ret = -EINVAL; | 557 | int ret = -EINVAL; |
594 | 558 | ||
595 | if (*a & (V4L2_STD_NTSC | V4L2_STD_PAL)) | 559 | if (norm & (V4L2_STD_NTSC | V4L2_STD_PAL)) |
596 | ret = 0; | 560 | ret = 0; |
597 | 561 | ||
598 | return ret; | 562 | return ret; |
@@ -608,11 +572,20 @@ static int tw9910_enum_input(struct soc_camera_device *icd, | |||
608 | return 0; | 572 | return 0; |
609 | } | 573 | } |
610 | 574 | ||
575 | static int tw9910_g_chip_ident(struct v4l2_subdev *sd, | ||
576 | struct v4l2_dbg_chip_ident *id) | ||
577 | { | ||
578 | id->ident = V4L2_IDENT_TW9910; | ||
579 | id->revision = 0; | ||
580 | |||
581 | return 0; | ||
582 | } | ||
583 | |||
611 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 584 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
612 | static int tw9910_get_register(struct soc_camera_device *icd, | 585 | static int tw9910_g_register(struct v4l2_subdev *sd, |
613 | struct v4l2_dbg_register *reg) | 586 | struct v4l2_dbg_register *reg) |
614 | { | 587 | { |
615 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 588 | struct i2c_client *client = sd->priv; |
616 | int ret; | 589 | int ret; |
617 | 590 | ||
618 | if (reg->reg > 0xff) | 591 | if (reg->reg > 0xff) |
@@ -630,10 +603,10 @@ static int tw9910_get_register(struct soc_camera_device *icd, | |||
630 | return 0; | 603 | return 0; |
631 | } | 604 | } |
632 | 605 | ||
633 | static int tw9910_set_register(struct soc_camera_device *icd, | 606 | static int tw9910_s_register(struct v4l2_subdev *sd, |
634 | struct v4l2_dbg_register *reg) | 607 | struct v4l2_dbg_register *reg) |
635 | { | 608 | { |
636 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 609 | struct i2c_client *client = sd->priv; |
637 | 610 | ||
638 | if (reg->reg > 0xff || | 611 | if (reg->reg > 0xff || |
639 | reg->val > 0xff) | 612 | reg->val > 0xff) |
@@ -647,7 +620,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, | |||
647 | struct v4l2_rect *rect) | 620 | struct v4l2_rect *rect) |
648 | { | 621 | { |
649 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | 622 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
650 | struct tw9910_priv *priv = i2c_get_clientdata(client); | 623 | struct tw9910_priv *priv = to_tw9910(client); |
651 | int ret = -EINVAL; | 624 | int ret = -EINVAL; |
652 | u8 val; | 625 | u8 val; |
653 | 626 | ||
@@ -736,9 +709,10 @@ tw9910_set_fmt_error: | |||
736 | return ret; | 709 | return ret; |
737 | } | 710 | } |
738 | 711 | ||
739 | static int tw9910_set_fmt(struct soc_camera_device *icd, | 712 | static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) |
740 | struct v4l2_format *f) | ||
741 | { | 713 | { |
714 | struct i2c_client *client = sd->priv; | ||
715 | struct soc_camera_device *icd = client->dev.platform_data; | ||
742 | struct v4l2_pix_format *pix = &f->fmt.pix; | 716 | struct v4l2_pix_format *pix = &f->fmt.pix; |
743 | struct v4l2_rect rect = { | 717 | struct v4l2_rect rect = { |
744 | .left = icd->x_current, | 718 | .left = icd->x_current, |
@@ -761,16 +735,17 @@ static int tw9910_set_fmt(struct soc_camera_device *icd, | |||
761 | return tw9910_set_crop(icd, &rect); | 735 | return tw9910_set_crop(icd, &rect); |
762 | } | 736 | } |
763 | 737 | ||
764 | static int tw9910_try_fmt(struct soc_camera_device *icd, | 738 | static int tw9910_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) |
765 | struct v4l2_format *f) | ||
766 | { | 739 | { |
740 | struct i2c_client *client = sd->priv; | ||
741 | struct soc_camera_device *icd = client->dev.platform_data; | ||
767 | struct v4l2_pix_format *pix = &f->fmt.pix; | 742 | struct v4l2_pix_format *pix = &f->fmt.pix; |
768 | const struct tw9910_scale_ctrl *scale; | 743 | const struct tw9910_scale_ctrl *scale; |
769 | 744 | ||
770 | if (V4L2_FIELD_ANY == pix->field) { | 745 | if (V4L2_FIELD_ANY == pix->field) { |
771 | pix->field = V4L2_FIELD_INTERLACED; | 746 | pix->field = V4L2_FIELD_INTERLACED; |
772 | } else if (V4L2_FIELD_INTERLACED != pix->field) { | 747 | } else if (V4L2_FIELD_INTERLACED != pix->field) { |
773 | dev_err(&icd->dev, "Field type invalid.\n"); | 748 | dev_err(&client->dev, "Field type invalid.\n"); |
774 | return -EINVAL; | 749 | return -EINVAL; |
775 | } | 750 | } |
776 | 751 | ||
@@ -790,9 +765,8 @@ static int tw9910_try_fmt(struct soc_camera_device *icd, | |||
790 | static int tw9910_video_probe(struct soc_camera_device *icd, | 765 | static int tw9910_video_probe(struct soc_camera_device *icd, |
791 | struct i2c_client *client) | 766 | struct i2c_client *client) |
792 | { | 767 | { |
793 | struct tw9910_priv *priv = i2c_get_clientdata(client); | 768 | struct tw9910_priv *priv = to_tw9910(client); |
794 | s32 val; | 769 | s32 val; |
795 | int ret; | ||
796 | 770 | ||
797 | /* | 771 | /* |
798 | * We must have a parent by now. And it cannot be a wrong one. | 772 | * We must have a parent by now. And it cannot be a wrong one. |
@@ -814,18 +788,11 @@ static int tw9910_video_probe(struct soc_camera_device *icd, | |||
814 | icd->formats = tw9910_color_fmt; | 788 | icd->formats = tw9910_color_fmt; |
815 | icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); | 789 | icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); |
816 | 790 | ||
817 | /* Switch master clock on */ | ||
818 | ret = soc_camera_video_start(icd, &client->dev); | ||
819 | if (ret) | ||
820 | return ret; | ||
821 | |||
822 | /* | 791 | /* |
823 | * check and show Product ID | 792 | * check and show Product ID |
824 | */ | 793 | */ |
825 | val = i2c_smbus_read_byte_data(client, ID); | 794 | val = i2c_smbus_read_byte_data(client, ID); |
826 | 795 | ||
827 | soc_camera_video_stop(icd); | ||
828 | |||
829 | if (0x0B != GET_ID(val) || | 796 | if (0x0B != GET_ID(val) || |
830 | 0x00 != GET_ReV(val)) { | 797 | 0x00 != GET_ReV(val)) { |
831 | dev_err(&icd->dev, | 798 | dev_err(&icd->dev, |
@@ -839,29 +806,36 @@ static int tw9910_video_probe(struct soc_camera_device *icd, | |||
839 | icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; | 806 | icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; |
840 | icd->vdev->current_norm = V4L2_STD_NTSC; | 807 | icd->vdev->current_norm = V4L2_STD_NTSC; |
841 | 808 | ||
842 | return ret; | 809 | return 0; |
843 | } | 810 | } |
844 | 811 | ||
845 | static struct soc_camera_ops tw9910_ops = { | 812 | static struct soc_camera_ops tw9910_ops = { |
846 | .owner = THIS_MODULE, | ||
847 | .init = tw9910_init, | ||
848 | .release = tw9910_release, | ||
849 | .start_capture = tw9910_start_capture, | ||
850 | .stop_capture = tw9910_stop_capture, | ||
851 | .set_crop = tw9910_set_crop, | 813 | .set_crop = tw9910_set_crop, |
852 | .set_fmt = tw9910_set_fmt, | ||
853 | .try_fmt = tw9910_try_fmt, | ||
854 | .set_bus_param = tw9910_set_bus_param, | 814 | .set_bus_param = tw9910_set_bus_param, |
855 | .query_bus_param = tw9910_query_bus_param, | 815 | .query_bus_param = tw9910_query_bus_param, |
856 | .get_chip_id = tw9910_get_chip_id, | ||
857 | .set_std = tw9910_set_std, | ||
858 | .enum_input = tw9910_enum_input, | 816 | .enum_input = tw9910_enum_input, |
817 | }; | ||
818 | |||
819 | static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { | ||
820 | .g_chip_ident = tw9910_g_chip_ident, | ||
821 | .s_std = tw9910_s_std, | ||
859 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 822 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
860 | .get_register = tw9910_get_register, | 823 | .g_register = tw9910_g_register, |
861 | .set_register = tw9910_set_register, | 824 | .s_register = tw9910_s_register, |
862 | #endif | 825 | #endif |
863 | }; | 826 | }; |
864 | 827 | ||
828 | static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { | ||
829 | .s_stream = tw9910_s_stream, | ||
830 | .s_fmt = tw9910_s_fmt, | ||
831 | .try_fmt = tw9910_try_fmt, | ||
832 | }; | ||
833 | |||
834 | static struct v4l2_subdev_ops tw9910_subdev_ops = { | ||
835 | .core = &tw9910_subdev_core_ops, | ||
836 | .video = &tw9910_subdev_video_ops, | ||
837 | }; | ||
838 | |||
865 | /* | 839 | /* |
866 | * i2c_driver function | 840 | * i2c_driver function |
867 | */ | 841 | */ |
@@ -902,7 +876,8 @@ static int tw9910_probe(struct i2c_client *client, | |||
902 | return -ENOMEM; | 876 | return -ENOMEM; |
903 | 877 | ||
904 | priv->info = info; | 878 | priv->info = info; |
905 | i2c_set_clientdata(client, priv); | 879 | |
880 | v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); | ||
906 | 881 | ||
907 | icd->ops = &tw9910_ops; | 882 | icd->ops = &tw9910_ops; |
908 | icd->iface = info->link.bus_id; | 883 | icd->iface = info->link.bus_id; |
@@ -942,7 +917,7 @@ static int tw9910_probe(struct i2c_client *client, | |||
942 | 917 | ||
943 | static int tw9910_remove(struct i2c_client *client) | 918 | static int tw9910_remove(struct i2c_client *client) |
944 | { | 919 | { |
945 | struct tw9910_priv *priv = i2c_get_clientdata(client); | 920 | struct tw9910_priv *priv = to_tw9910(client); |
946 | struct soc_camera_device *icd = client->dev.platform_data; | 921 | struct soc_camera_device *icd = client->dev.platform_data; |
947 | 922 | ||
948 | icd->ops = NULL; | 923 | icd->ops = NULL; |