diff options
-rw-r--r-- | Documentation/feature-removal-schedule.txt | 22 | ||||
-rw-r--r-- | drivers/media/video/bt8xx/bttv-driver.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-ioctl.c | 8 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 8 | ||||
-rw-r--r-- | drivers/media/video/msp3400-driver.c | 12 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.c | 4 | ||||
-rw-r--r-- | drivers/media/video/tuner-core.c | 229 | ||||
-rw-r--r-- | drivers/media/video/v4l2-ioctl.c | 18 | ||||
-rw-r--r-- | include/media/v4l2-subdev.h | 10 |
9 files changed, 174 insertions, 139 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 72e238465b0b..b1c921c27519 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -583,3 +583,25 @@ Why: Superseded by the UVCIOC_CTRL_QUERY ioctl. | |||
583 | Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 583 | Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
584 | 584 | ||
585 | ---------------------------- | 585 | ---------------------------- |
586 | |||
587 | What: For VIDIOC_S_FREQUENCY the type field must match the device node's type. | ||
588 | If not, return -EINVAL. | ||
589 | When: 3.2 | ||
590 | Why: It makes no sense to switch the tuner to radio mode by calling | ||
591 | VIDIOC_S_FREQUENCY on a video node, or to switch the tuner to tv mode by | ||
592 | calling VIDIOC_S_FREQUENCY on a radio node. This is the first step of a | ||
593 | move to more consistent handling of tv and radio tuners. | ||
594 | Who: Hans Verkuil <hans.verkuil@cisco.com> | ||
595 | |||
596 | ---------------------------- | ||
597 | |||
598 | What: Opening a radio device node will no longer automatically switch the | ||
599 | tuner mode from tv to radio. | ||
600 | When: 3.3 | ||
601 | Why: Just opening a V4L device should not change the state of the hardware | ||
602 | like that. It's very unexpected and against the V4L spec. Instead, you | ||
603 | switch to radio mode by calling VIDIOC_S_FREQUENCY. This is the second | ||
604 | and last step of the move to consistent handling of tv and radio tuners. | ||
605 | Who: Hans Verkuil <hans.verkuil@cisco.com> | ||
606 | |||
607 | ---------------------------- | ||
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index a97cf2750bd9..834a48394bce 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -3474,7 +3474,7 @@ static int radio_s_tuner(struct file *file, void *priv, | |||
3474 | if (0 != t->index) | 3474 | if (0 != t->index) |
3475 | return -EINVAL; | 3475 | return -EINVAL; |
3476 | 3476 | ||
3477 | bttv_call_all(btv, tuner, g_tuner, t); | 3477 | bttv_call_all(btv, tuner, s_tuner, t); |
3478 | return 0; | 3478 | return 0; |
3479 | } | 3479 | } |
3480 | 3480 | ||
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 1933d4d11bf2..e80134f52ef5 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -695,14 +695,10 @@ static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) | |||
695 | 695 | ||
696 | cx18_call_all(cx, tuner, g_tuner, vt); | 696 | cx18_call_all(cx, tuner, g_tuner, vt); |
697 | 697 | ||
698 | if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { | 698 | if (vt->type == V4L2_TUNER_RADIO) |
699 | strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name)); | 699 | strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name)); |
700 | vt->type = V4L2_TUNER_RADIO; | 700 | else |
701 | } else { | ||
702 | strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name)); | 701 | strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name)); |
703 | vt->type = V4L2_TUNER_ANALOG_TV; | ||
704 | } | ||
705 | |||
706 | return 0; | 702 | return 0; |
707 | } | 703 | } |
708 | 704 | ||
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index f9e347dae739..120c7d8e0895 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -1184,14 +1184,10 @@ static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) | |||
1184 | 1184 | ||
1185 | ivtv_call_all(itv, tuner, g_tuner, vt); | 1185 | ivtv_call_all(itv, tuner, g_tuner, vt); |
1186 | 1186 | ||
1187 | if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { | 1187 | if (vt->type == V4L2_TUNER_RADIO) |
1188 | strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name)); | 1188 | strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name)); |
1189 | vt->type = V4L2_TUNER_RADIO; | 1189 | else |
1190 | } else { | ||
1191 | strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name)); | 1190 | strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name)); |
1192 | vt->type = V4L2_TUNER_ANALOG_TV; | ||
1193 | } | ||
1194 | |||
1195 | return 0; | 1191 | return 0; |
1196 | } | 1192 | } |
1197 | 1193 | ||
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index de5d481b0328..c43c81f5f978 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c | |||
@@ -480,12 +480,14 @@ static int msp_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | |||
480 | struct msp_state *state = to_state(sd); | 480 | struct msp_state *state = to_state(sd); |
481 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 481 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
482 | 482 | ||
483 | if (state->radio) | 483 | if (vt->type != V4L2_TUNER_ANALOG_TV) |
484 | return 0; | 484 | return 0; |
485 | if (state->opmode == OPMODE_AUTOSELECT) | 485 | if (!state->radio) { |
486 | msp_detect_stereo(client); | 486 | if (state->opmode == OPMODE_AUTOSELECT) |
487 | vt->audmode = state->audmode; | 487 | msp_detect_stereo(client); |
488 | vt->rxsubchans = state->rxsubchans; | 488 | vt->rxsubchans = state->rxsubchans; |
489 | } | ||
490 | vt->audmode = state->audmode; | ||
489 | vt->capability |= V4L2_TUNER_CAP_STEREO | | 491 | vt->capability |= V4L2_TUNER_CAP_STEREO | |
490 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; | 492 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; |
491 | return 0; | 493 | return 0; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 9d0dd08f57f8..e98d38212791 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -3046,6 +3046,8 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) | |||
3046 | if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) { | 3046 | if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) { |
3047 | struct v4l2_tuner vt; | 3047 | struct v4l2_tuner vt; |
3048 | memset(&vt, 0, sizeof(vt)); | 3048 | memset(&vt, 0, sizeof(vt)); |
3049 | vt.type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ? | ||
3050 | V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | ||
3049 | vt.audmode = hdw->audiomode_val; | 3051 | vt.audmode = hdw->audiomode_val; |
3050 | v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt); | 3052 | v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt); |
3051 | } | 3053 | } |
@@ -5171,6 +5173,8 @@ void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) | |||
5171 | { | 5173 | { |
5172 | struct v4l2_tuner *vtp = &hdw->tuner_signal_info; | 5174 | struct v4l2_tuner *vtp = &hdw->tuner_signal_info; |
5173 | memset(vtp, 0, sizeof(*vtp)); | 5175 | memset(vtp, 0, sizeof(*vtp)); |
5176 | vtp->type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ? | ||
5177 | V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | ||
5174 | hdw->tuner_signal_stale = 0; | 5178 | hdw->tuner_signal_stale = 0; |
5175 | /* Note: There apparently is no replacement for VIDIOC_CROPCAP | 5179 | /* Note: There apparently is no replacement for VIDIOC_CROPCAP |
5176 | using v4l2-subdev - therefore we can't support that AT ALL right | 5180 | using v4l2-subdev - therefore we can't support that AT ALL right |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 9363ed91a4cb..cfa9f7efe93d 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -724,19 +724,15 @@ static inline int check_mode(struct tuner *t, enum v4l2_tuner_type mode) | |||
724 | } | 724 | } |
725 | 725 | ||
726 | /** | 726 | /** |
727 | * set_mode_freq - Switch tuner to other mode. | 727 | * set_mode - Switch tuner to other mode. |
728 | * @client: struct i2c_client pointer | ||
729 | * @t: a pointer to the module's internal struct_tuner | 728 | * @t: a pointer to the module's internal struct_tuner |
730 | * @mode: enum v4l2_type (radio or TV) | 729 | * @mode: enum v4l2_type (radio or TV) |
731 | * @freq: frequency to set (0 means to use the previous one) | ||
732 | * | 730 | * |
733 | * If tuner doesn't support the needed mode (radio or TV), prints a | 731 | * If tuner doesn't support the needed mode (radio or TV), prints a |
734 | * debug message and returns -EINVAL, changing its state to standby. | 732 | * debug message and returns -EINVAL, changing its state to standby. |
735 | * Otherwise, changes the state and sets frequency to the last value, if | 733 | * Otherwise, changes the mode and returns 0. |
736 | * the tuner can sleep or if it supports both Radio and TV. | ||
737 | */ | 734 | */ |
738 | static int set_mode_freq(struct i2c_client *client, struct tuner *t, | 735 | static int set_mode(struct tuner *t, enum v4l2_tuner_type mode) |
739 | enum v4l2_tuner_type mode, unsigned int freq) | ||
740 | { | 736 | { |
741 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; | 737 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; |
742 | 738 | ||
@@ -752,17 +748,27 @@ static int set_mode_freq(struct i2c_client *client, struct tuner *t, | |||
752 | t->mode = mode; | 748 | t->mode = mode; |
753 | tuner_dbg("Changing to mode %d\n", mode); | 749 | tuner_dbg("Changing to mode %d\n", mode); |
754 | } | 750 | } |
751 | return 0; | ||
752 | } | ||
753 | |||
754 | /** | ||
755 | * set_freq - Set the tuner to the desired frequency. | ||
756 | * @t: a pointer to the module's internal struct_tuner | ||
757 | * @freq: frequency to set (0 means to use the current frequency) | ||
758 | */ | ||
759 | static void set_freq(struct tuner *t, unsigned int freq) | ||
760 | { | ||
761 | struct i2c_client *client = v4l2_get_subdevdata(&t->sd); | ||
762 | |||
755 | if (t->mode == V4L2_TUNER_RADIO) { | 763 | if (t->mode == V4L2_TUNER_RADIO) { |
756 | if (freq) | 764 | if (!freq) |
757 | t->radio_freq = freq; | 765 | freq = t->radio_freq; |
758 | set_radio_freq(client, t->radio_freq); | 766 | set_radio_freq(client, freq); |
759 | } else { | 767 | } else { |
760 | if (freq) | 768 | if (!freq) |
761 | t->tv_freq = freq; | 769 | freq = t->tv_freq; |
762 | set_tv_freq(client, t->tv_freq); | 770 | set_tv_freq(client, freq); |
763 | } | 771 | } |
764 | |||
765 | return 0; | ||
766 | } | 772 | } |
767 | 773 | ||
768 | /* | 774 | /* |
@@ -817,7 +823,8 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
817 | /** | 823 | /** |
818 | * tuner_fixup_std - force a given video standard variant | 824 | * tuner_fixup_std - force a given video standard variant |
819 | * | 825 | * |
820 | * @t: tuner internal struct | 826 | * @t: tuner internal struct |
827 | * @std: TV standard | ||
821 | * | 828 | * |
822 | * A few devices or drivers have problem to detect some standard variations. | 829 | * A few devices or drivers have problem to detect some standard variations. |
823 | * On other operational systems, the drivers generally have a per-country | 830 | * On other operational systems, the drivers generally have a per-country |
@@ -827,57 +834,39 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq) | |||
827 | * to distinguish all video standard variations, a modprobe parameter can | 834 | * to distinguish all video standard variations, a modprobe parameter can |
828 | * be used to force a video standard match. | 835 | * be used to force a video standard match. |
829 | */ | 836 | */ |
830 | static int tuner_fixup_std(struct tuner *t) | 837 | static v4l2_std_id tuner_fixup_std(struct tuner *t, v4l2_std_id std) |
831 | { | 838 | { |
832 | if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) { | 839 | if (pal[0] != '-' && (std & V4L2_STD_PAL) == V4L2_STD_PAL) { |
833 | switch (pal[0]) { | 840 | switch (pal[0]) { |
834 | case '6': | 841 | case '6': |
835 | tuner_dbg("insmod fixup: PAL => PAL-60\n"); | 842 | return V4L2_STD_PAL_60; |
836 | t->std = V4L2_STD_PAL_60; | ||
837 | break; | ||
838 | case 'b': | 843 | case 'b': |
839 | case 'B': | 844 | case 'B': |
840 | case 'g': | 845 | case 'g': |
841 | case 'G': | 846 | case 'G': |
842 | tuner_dbg("insmod fixup: PAL => PAL-BG\n"); | 847 | return V4L2_STD_PAL_BG; |
843 | t->std = V4L2_STD_PAL_BG; | ||
844 | break; | ||
845 | case 'i': | 848 | case 'i': |
846 | case 'I': | 849 | case 'I': |
847 | tuner_dbg("insmod fixup: PAL => PAL-I\n"); | 850 | return V4L2_STD_PAL_I; |
848 | t->std = V4L2_STD_PAL_I; | ||
849 | break; | ||
850 | case 'd': | 851 | case 'd': |
851 | case 'D': | 852 | case 'D': |
852 | case 'k': | 853 | case 'k': |
853 | case 'K': | 854 | case 'K': |
854 | tuner_dbg("insmod fixup: PAL => PAL-DK\n"); | 855 | return V4L2_STD_PAL_DK; |
855 | t->std = V4L2_STD_PAL_DK; | ||
856 | break; | ||
857 | case 'M': | 856 | case 'M': |
858 | case 'm': | 857 | case 'm': |
859 | tuner_dbg("insmod fixup: PAL => PAL-M\n"); | 858 | return V4L2_STD_PAL_M; |
860 | t->std = V4L2_STD_PAL_M; | ||
861 | break; | ||
862 | case 'N': | 859 | case 'N': |
863 | case 'n': | 860 | case 'n': |
864 | if (pal[1] == 'c' || pal[1] == 'C') { | 861 | if (pal[1] == 'c' || pal[1] == 'C') |
865 | tuner_dbg("insmod fixup: PAL => PAL-Nc\n"); | 862 | return V4L2_STD_PAL_Nc; |
866 | t->std = V4L2_STD_PAL_Nc; | 863 | return V4L2_STD_PAL_N; |
867 | } else { | ||
868 | tuner_dbg("insmod fixup: PAL => PAL-N\n"); | ||
869 | t->std = V4L2_STD_PAL_N; | ||
870 | } | ||
871 | break; | ||
872 | case '-': | ||
873 | /* default parameter, do nothing */ | ||
874 | break; | ||
875 | default: | 864 | default: |
876 | tuner_warn("pal= argument not recognised\n"); | 865 | tuner_warn("pal= argument not recognised\n"); |
877 | break; | 866 | break; |
878 | } | 867 | } |
879 | } | 868 | } |
880 | if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { | 869 | if (secam[0] != '-' && (std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { |
881 | switch (secam[0]) { | 870 | switch (secam[0]) { |
882 | case 'b': | 871 | case 'b': |
883 | case 'B': | 872 | case 'B': |
@@ -885,63 +874,42 @@ static int tuner_fixup_std(struct tuner *t) | |||
885 | case 'G': | 874 | case 'G': |
886 | case 'h': | 875 | case 'h': |
887 | case 'H': | 876 | case 'H': |
888 | tuner_dbg("insmod fixup: SECAM => SECAM-BGH\n"); | 877 | return V4L2_STD_SECAM_B | |
889 | t->std = V4L2_STD_SECAM_B | | 878 | V4L2_STD_SECAM_G | |
890 | V4L2_STD_SECAM_G | | 879 | V4L2_STD_SECAM_H; |
891 | V4L2_STD_SECAM_H; | ||
892 | break; | ||
893 | case 'd': | 880 | case 'd': |
894 | case 'D': | 881 | case 'D': |
895 | case 'k': | 882 | case 'k': |
896 | case 'K': | 883 | case 'K': |
897 | tuner_dbg("insmod fixup: SECAM => SECAM-DK\n"); | 884 | return V4L2_STD_SECAM_DK; |
898 | t->std = V4L2_STD_SECAM_DK; | ||
899 | break; | ||
900 | case 'l': | 885 | case 'l': |
901 | case 'L': | 886 | case 'L': |
902 | if ((secam[1] == 'C') || (secam[1] == 'c')) { | 887 | if ((secam[1] == 'C') || (secam[1] == 'c')) |
903 | tuner_dbg("insmod fixup: SECAM => SECAM-L'\n"); | 888 | return V4L2_STD_SECAM_LC; |
904 | t->std = V4L2_STD_SECAM_LC; | 889 | return V4L2_STD_SECAM_L; |
905 | } else { | ||
906 | tuner_dbg("insmod fixup: SECAM => SECAM-L\n"); | ||
907 | t->std = V4L2_STD_SECAM_L; | ||
908 | } | ||
909 | break; | ||
910 | case '-': | ||
911 | /* default parameter, do nothing */ | ||
912 | break; | ||
913 | default: | 890 | default: |
914 | tuner_warn("secam= argument not recognised\n"); | 891 | tuner_warn("secam= argument not recognised\n"); |
915 | break; | 892 | break; |
916 | } | 893 | } |
917 | } | 894 | } |
918 | 895 | ||
919 | if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) { | 896 | if (ntsc[0] != '-' && (std & V4L2_STD_NTSC) == V4L2_STD_NTSC) { |
920 | switch (ntsc[0]) { | 897 | switch (ntsc[0]) { |
921 | case 'm': | 898 | case 'm': |
922 | case 'M': | 899 | case 'M': |
923 | tuner_dbg("insmod fixup: NTSC => NTSC-M\n"); | 900 | return V4L2_STD_NTSC_M; |
924 | t->std = V4L2_STD_NTSC_M; | ||
925 | break; | ||
926 | case 'j': | 901 | case 'j': |
927 | case 'J': | 902 | case 'J': |
928 | tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); | 903 | return V4L2_STD_NTSC_M_JP; |
929 | t->std = V4L2_STD_NTSC_M_JP; | ||
930 | break; | ||
931 | case 'k': | 904 | case 'k': |
932 | case 'K': | 905 | case 'K': |
933 | tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n"); | 906 | return V4L2_STD_NTSC_M_KR; |
934 | t->std = V4L2_STD_NTSC_M_KR; | ||
935 | break; | ||
936 | case '-': | ||
937 | /* default parameter, do nothing */ | ||
938 | break; | ||
939 | default: | 907 | default: |
940 | tuner_info("ntsc= argument not recognised\n"); | 908 | tuner_info("ntsc= argument not recognised\n"); |
941 | break; | 909 | break; |
942 | } | 910 | } |
943 | } | 911 | } |
944 | return 0; | 912 | return std; |
945 | } | 913 | } |
946 | 914 | ||
947 | /* | 915 | /* |
@@ -1058,10 +1026,9 @@ static void tuner_status(struct dvb_frontend *fe) | |||
1058 | static int tuner_s_radio(struct v4l2_subdev *sd) | 1026 | static int tuner_s_radio(struct v4l2_subdev *sd) |
1059 | { | 1027 | { |
1060 | struct tuner *t = to_tuner(sd); | 1028 | struct tuner *t = to_tuner(sd); |
1061 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1062 | 1029 | ||
1063 | if (set_mode_freq(client, t, V4L2_TUNER_RADIO, 0) == -EINVAL) | 1030 | if (set_mode(t, V4L2_TUNER_RADIO) == 0) |
1064 | return 0; | 1031 | set_freq(t, 0); |
1065 | return 0; | 1032 | return 0; |
1066 | } | 1033 | } |
1067 | 1034 | ||
@@ -1072,16 +1039,20 @@ static int tuner_s_radio(struct v4l2_subdev *sd) | |||
1072 | /** | 1039 | /** |
1073 | * tuner_s_power - controls the power state of the tuner | 1040 | * tuner_s_power - controls the power state of the tuner |
1074 | * @sd: pointer to struct v4l2_subdev | 1041 | * @sd: pointer to struct v4l2_subdev |
1075 | * @on: a zero value puts the tuner to sleep | 1042 | * @on: a zero value puts the tuner to sleep, non-zero wakes it up |
1076 | */ | 1043 | */ |
1077 | static int tuner_s_power(struct v4l2_subdev *sd, int on) | 1044 | static int tuner_s_power(struct v4l2_subdev *sd, int on) |
1078 | { | 1045 | { |
1079 | struct tuner *t = to_tuner(sd); | 1046 | struct tuner *t = to_tuner(sd); |
1080 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; | 1047 | struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; |
1081 | 1048 | ||
1082 | /* FIXME: Why this function don't wake the tuner if on != 0 ? */ | 1049 | if (on) { |
1083 | if (on) | 1050 | if (t->standby && set_mode(t, t->mode) == 0) { |
1051 | tuner_dbg("Waking up tuner\n"); | ||
1052 | set_freq(t, 0); | ||
1053 | } | ||
1084 | return 0; | 1054 | return 0; |
1055 | } | ||
1085 | 1056 | ||
1086 | tuner_dbg("Putting tuner to sleep\n"); | 1057 | tuner_dbg("Putting tuner to sleep\n"); |
1087 | t->standby = true; | 1058 | t->standby = true; |
@@ -1093,28 +1064,36 @@ static int tuner_s_power(struct v4l2_subdev *sd, int on) | |||
1093 | static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | 1064 | static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std) |
1094 | { | 1065 | { |
1095 | struct tuner *t = to_tuner(sd); | 1066 | struct tuner *t = to_tuner(sd); |
1096 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1097 | 1067 | ||
1098 | if (set_mode_freq(client, t, V4L2_TUNER_ANALOG_TV, 0) == -EINVAL) | 1068 | if (set_mode(t, V4L2_TUNER_ANALOG_TV)) |
1099 | return 0; | 1069 | return 0; |
1100 | 1070 | ||
1101 | t->std = std; | 1071 | t->std = tuner_fixup_std(t, std); |
1102 | tuner_fixup_std(t); | 1072 | if (t->std != std) |
1103 | 1073 | tuner_dbg("Fixup standard %llx to %llx\n", std, t->std); | |
1074 | set_freq(t, 0); | ||
1104 | return 0; | 1075 | return 0; |
1105 | } | 1076 | } |
1106 | 1077 | ||
1107 | static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) | 1078 | static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) |
1108 | { | 1079 | { |
1109 | struct tuner *t = to_tuner(sd); | 1080 | struct tuner *t = to_tuner(sd); |
1110 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1111 | |||
1112 | if (set_mode_freq(client, t, f->type, f->frequency) == -EINVAL) | ||
1113 | return 0; | ||
1114 | 1081 | ||
1082 | if (set_mode(t, f->type) == 0) | ||
1083 | set_freq(t, f->frequency); | ||
1115 | return 0; | 1084 | return 0; |
1116 | } | 1085 | } |
1117 | 1086 | ||
1087 | /** | ||
1088 | * tuner_g_frequency - Get the tuned frequency for the tuner | ||
1089 | * @sd: pointer to struct v4l2_subdev | ||
1090 | * @f: pointer to struct v4l2_frequency | ||
1091 | * | ||
1092 | * At return, the structure f will be filled with tuner frequency | ||
1093 | * if the tuner matches the f->type. | ||
1094 | * Note: f->type should be initialized before calling it. | ||
1095 | * This is done by either video_ioctl2 or by the bridge driver. | ||
1096 | */ | ||
1118 | static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) | 1097 | static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) |
1119 | { | 1098 | { |
1120 | struct tuner *t = to_tuner(sd); | 1099 | struct tuner *t = to_tuner(sd); |
@@ -1122,8 +1101,7 @@ static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) | |||
1122 | 1101 | ||
1123 | if (check_mode(t, f->type) == -EINVAL) | 1102 | if (check_mode(t, f->type) == -EINVAL) |
1124 | return 0; | 1103 | return 0; |
1125 | f->type = t->mode; | 1104 | if (f->type == t->mode && fe_tuner_ops->get_frequency && !t->standby) { |
1126 | if (fe_tuner_ops->get_frequency && !t->standby) { | ||
1127 | u32 abs_freq; | 1105 | u32 abs_freq; |
1128 | 1106 | ||
1129 | fe_tuner_ops->get_frequency(&t->fe, &abs_freq); | 1107 | fe_tuner_ops->get_frequency(&t->fe, &abs_freq); |
@@ -1131,12 +1109,22 @@ static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) | |||
1131 | DIV_ROUND_CLOSEST(abs_freq * 2, 125) : | 1109 | DIV_ROUND_CLOSEST(abs_freq * 2, 125) : |
1132 | DIV_ROUND_CLOSEST(abs_freq, 62500); | 1110 | DIV_ROUND_CLOSEST(abs_freq, 62500); |
1133 | } else { | 1111 | } else { |
1134 | f->frequency = (V4L2_TUNER_RADIO == t->mode) ? | 1112 | f->frequency = (V4L2_TUNER_RADIO == f->type) ? |
1135 | t->radio_freq : t->tv_freq; | 1113 | t->radio_freq : t->tv_freq; |
1136 | } | 1114 | } |
1137 | return 0; | 1115 | return 0; |
1138 | } | 1116 | } |
1139 | 1117 | ||
1118 | /** | ||
1119 | * tuner_g_tuner - Fill in tuner information | ||
1120 | * @sd: pointer to struct v4l2_subdev | ||
1121 | * @vt: pointer to struct v4l2_tuner | ||
1122 | * | ||
1123 | * At return, the structure vt will be filled with tuner information | ||
1124 | * if the tuner matches vt->type. | ||
1125 | * Note: vt->type should be initialized before calling it. | ||
1126 | * This is done by either video_ioctl2 or by the bridge driver. | ||
1127 | */ | ||
1140 | static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | 1128 | static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) |
1141 | { | 1129 | { |
1142 | struct tuner *t = to_tuner(sd); | 1130 | struct tuner *t = to_tuner(sd); |
@@ -1145,48 +1133,58 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | |||
1145 | 1133 | ||
1146 | if (check_mode(t, vt->type) == -EINVAL) | 1134 | if (check_mode(t, vt->type) == -EINVAL) |
1147 | return 0; | 1135 | return 0; |
1148 | vt->type = t->mode; | 1136 | if (vt->type == t->mode && analog_ops->get_afc) |
1149 | if (analog_ops->get_afc) | ||
1150 | vt->afc = analog_ops->get_afc(&t->fe); | 1137 | vt->afc = analog_ops->get_afc(&t->fe); |
1151 | if (t->mode == V4L2_TUNER_ANALOG_TV) | 1138 | if (vt->type == V4L2_TUNER_ANALOG_TV) |
1152 | vt->capability |= V4L2_TUNER_CAP_NORM; | 1139 | vt->capability |= V4L2_TUNER_CAP_NORM; |
1153 | if (t->mode != V4L2_TUNER_RADIO) { | 1140 | if (vt->type != V4L2_TUNER_RADIO) { |
1154 | vt->rangelow = tv_range[0] * 16; | 1141 | vt->rangelow = tv_range[0] * 16; |
1155 | vt->rangehigh = tv_range[1] * 16; | 1142 | vt->rangehigh = tv_range[1] * 16; |
1156 | return 0; | 1143 | return 0; |
1157 | } | 1144 | } |
1158 | 1145 | ||
1159 | /* radio mode */ | 1146 | /* radio mode */ |
1160 | vt->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | 1147 | if (vt->type == t->mode) { |
1161 | if (fe_tuner_ops->get_status) { | 1148 | vt->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; |
1162 | u32 tuner_status; | 1149 | if (fe_tuner_ops->get_status) { |
1163 | 1150 | u32 tuner_status; | |
1164 | fe_tuner_ops->get_status(&t->fe, &tuner_status); | 1151 | |
1165 | vt->rxsubchans = | 1152 | fe_tuner_ops->get_status(&t->fe, &tuner_status); |
1166 | (tuner_status & TUNER_STATUS_STEREO) ? | 1153 | vt->rxsubchans = |
1167 | V4L2_TUNER_SUB_STEREO : | 1154 | (tuner_status & TUNER_STATUS_STEREO) ? |
1168 | V4L2_TUNER_SUB_MONO; | 1155 | V4L2_TUNER_SUB_STEREO : |
1156 | V4L2_TUNER_SUB_MONO; | ||
1157 | } | ||
1158 | if (analog_ops->has_signal) | ||
1159 | vt->signal = analog_ops->has_signal(&t->fe); | ||
1160 | vt->audmode = t->audmode; | ||
1169 | } | 1161 | } |
1170 | if (analog_ops->has_signal) | ||
1171 | vt->signal = analog_ops->has_signal(&t->fe); | ||
1172 | vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; | 1162 | vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; |
1173 | vt->audmode = t->audmode; | ||
1174 | vt->rangelow = radio_range[0] * 16000; | 1163 | vt->rangelow = radio_range[0] * 16000; |
1175 | vt->rangehigh = radio_range[1] * 16000; | 1164 | vt->rangehigh = radio_range[1] * 16000; |
1176 | 1165 | ||
1177 | return 0; | 1166 | return 0; |
1178 | } | 1167 | } |
1179 | 1168 | ||
1169 | /** | ||
1170 | * tuner_s_tuner - Set the tuner's audio mode | ||
1171 | * @sd: pointer to struct v4l2_subdev | ||
1172 | * @vt: pointer to struct v4l2_tuner | ||
1173 | * | ||
1174 | * Sets the audio mode if the tuner matches vt->type. | ||
1175 | * Note: vt->type should be initialized before calling it. | ||
1176 | * This is done by either video_ioctl2 or by the bridge driver. | ||
1177 | */ | ||
1180 | static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) | 1178 | static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) |
1181 | { | 1179 | { |
1182 | struct tuner *t = to_tuner(sd); | 1180 | struct tuner *t = to_tuner(sd); |
1183 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1184 | 1181 | ||
1185 | if (set_mode_freq(client, t, vt->type, 0) == -EINVAL) | 1182 | if (set_mode(t, vt->type)) |
1186 | return 0; | 1183 | return 0; |
1187 | 1184 | ||
1188 | if (t->mode == V4L2_TUNER_RADIO) | 1185 | if (t->mode == V4L2_TUNER_RADIO) |
1189 | t->audmode = vt->audmode; | 1186 | t->audmode = vt->audmode; |
1187 | set_freq(t, 0); | ||
1190 | 1188 | ||
1191 | return 0; | 1189 | return 0; |
1192 | } | 1190 | } |
@@ -1221,7 +1219,8 @@ static int tuner_resume(struct i2c_client *c) | |||
1221 | tuner_dbg("resume\n"); | 1219 | tuner_dbg("resume\n"); |
1222 | 1220 | ||
1223 | if (!t->standby) | 1221 | if (!t->standby) |
1224 | set_mode_freq(c, t, t->type, 0); | 1222 | if (set_mode(t, t->mode) == 0) |
1223 | set_freq(t, 0); | ||
1225 | 1224 | ||
1226 | return 0; | 1225 | return 0; |
1227 | } | 1226 | } |
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 506edcc2ddeb..69e8c6ffcc49 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c | |||
@@ -1822,6 +1822,8 @@ static long __video_do_ioctl(struct file *file, | |||
1822 | if (!ops->vidioc_g_tuner) | 1822 | if (!ops->vidioc_g_tuner) |
1823 | break; | 1823 | break; |
1824 | 1824 | ||
1825 | p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? | ||
1826 | V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | ||
1825 | ret = ops->vidioc_g_tuner(file, fh, p); | 1827 | ret = ops->vidioc_g_tuner(file, fh, p); |
1826 | if (!ret) | 1828 | if (!ret) |
1827 | dbgarg(cmd, "index=%d, name=%s, type=%d, " | 1829 | dbgarg(cmd, "index=%d, name=%s, type=%d, " |
@@ -1840,6 +1842,8 @@ static long __video_do_ioctl(struct file *file, | |||
1840 | 1842 | ||
1841 | if (!ops->vidioc_s_tuner) | 1843 | if (!ops->vidioc_s_tuner) |
1842 | break; | 1844 | break; |
1845 | p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? | ||
1846 | V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | ||
1843 | dbgarg(cmd, "index=%d, name=%s, type=%d, " | 1847 | dbgarg(cmd, "index=%d, name=%s, type=%d, " |
1844 | "capability=0x%x, rangelow=%d, " | 1848 | "capability=0x%x, rangelow=%d, " |
1845 | "rangehigh=%d, signal=%d, afc=%d, " | 1849 | "rangehigh=%d, signal=%d, afc=%d, " |
@@ -1858,6 +1862,8 @@ static long __video_do_ioctl(struct file *file, | |||
1858 | if (!ops->vidioc_g_frequency) | 1862 | if (!ops->vidioc_g_frequency) |
1859 | break; | 1863 | break; |
1860 | 1864 | ||
1865 | p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? | ||
1866 | V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | ||
1861 | ret = ops->vidioc_g_frequency(file, fh, p); | 1867 | ret = ops->vidioc_g_frequency(file, fh, p); |
1862 | if (!ret) | 1868 | if (!ret) |
1863 | dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n", | 1869 | dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n", |
@@ -1940,13 +1946,19 @@ static long __video_do_ioctl(struct file *file, | |||
1940 | case VIDIOC_S_HW_FREQ_SEEK: | 1946 | case VIDIOC_S_HW_FREQ_SEEK: |
1941 | { | 1947 | { |
1942 | struct v4l2_hw_freq_seek *p = arg; | 1948 | struct v4l2_hw_freq_seek *p = arg; |
1949 | enum v4l2_tuner_type type; | ||
1943 | 1950 | ||
1944 | if (!ops->vidioc_s_hw_freq_seek) | 1951 | if (!ops->vidioc_s_hw_freq_seek) |
1945 | break; | 1952 | break; |
1953 | type = (vfd->vfl_type == VFL_TYPE_RADIO) ? | ||
1954 | V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | ||
1946 | dbgarg(cmd, | 1955 | dbgarg(cmd, |
1947 | "tuner=%d, type=%d, seek_upward=%d, wrap_around=%d\n", | 1956 | "tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n", |
1948 | p->tuner, p->type, p->seek_upward, p->wrap_around); | 1957 | p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing); |
1949 | ret = ops->vidioc_s_hw_freq_seek(file, fh, p); | 1958 | if (p->type != type) |
1959 | ret = -EINVAL; | ||
1960 | else | ||
1961 | ret = ops->vidioc_s_hw_freq_seek(file, fh, p); | ||
1950 | break; | 1962 | break; |
1951 | } | 1963 | } |
1952 | case VIDIOC_ENUM_FRAMESIZES: | 1964 | case VIDIOC_ENUM_FRAMESIZES: |
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 1562c4ff3a65..2884e3e69cb1 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h | |||
@@ -173,16 +173,20 @@ struct v4l2_subdev_core_ops { | |||
173 | struct v4l2_event_subscription *sub); | 173 | struct v4l2_event_subscription *sub); |
174 | }; | 174 | }; |
175 | 175 | ||
176 | /* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio. | 176 | /* s_radio: v4l device was opened in radio mode. |
177 | 177 | ||
178 | s_radio: v4l device was opened in Radio mode, to be replaced by s_mode. | 178 | g_frequency: freq->type must be filled in. Normally done by video_ioctl2 |
179 | or the bridge driver. | ||
180 | |||
181 | g_tuner: | ||
182 | s_tuner: vt->type must be filled in. Normally done by video_ioctl2 or the | ||
183 | bridge driver. | ||
179 | 184 | ||
180 | s_type_addr: sets tuner type and its I2C addr. | 185 | s_type_addr: sets tuner type and its I2C addr. |
181 | 186 | ||
182 | s_config: sets tda9887 specific stuff, like port1, port2 and qss | 187 | s_config: sets tda9887 specific stuff, like port1, port2 and qss |
183 | */ | 188 | */ |
184 | struct v4l2_subdev_tuner_ops { | 189 | struct v4l2_subdev_tuner_ops { |
185 | int (*s_mode)(struct v4l2_subdev *sd, enum v4l2_tuner_type); | ||
186 | int (*s_radio)(struct v4l2_subdev *sd); | 190 | int (*s_radio)(struct v4l2_subdev *sd); |
187 | int (*s_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq); | 191 | int (*s_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq); |
188 | int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq); | 192 | int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq); |