diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2009-08-25 10:43:33 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-18 23:18:35 -0400 |
commit | 979ea1ddf80ac7383acdea03471355ca62702539 (patch) | |
tree | 2ee4c73eb672c1ee8167ed7e0906bac6f3b00e69 /drivers/media/video/tw9910.c | |
parent | 0bab829de1ab60d8c3cbf7e402192bb9446840b7 (diff) |
V4L/DVB (12510): soc-camera: (partially) convert to v4l2-(sub)dev API
Convert the soc-camera framework to use the v4l2-(sub)dev API. Start using
v4l2-subdev operations. Only a part of the interface between the
soc_camera core, soc_camera host drivers on one side and soc_camera device
drivers on the other side is replaced so far. The rest of the interface
will be replaced in incremental steps, and will require extensions and,
possibly, modifications to the v4l2-subdev code.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
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; |