aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-11 19:43:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-11 19:43:27 -0400
commitc15000b40d46c0affa4c142c4ecb7beee4ce03f3 (patch)
tree14fe31249f9f8c882fecc63542821d6b431630c6
parent9ddf7f5058c4f4badd38dba8d5896a5dbd7e716f (diff)
parentddc6ff31cc22720c46c1547a5310ea260a968ae9 (diff)
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: [media] msp3400: fill in v4l2_tuner based on vt->type field [media] tuner-core.c: don't change type field in g_tuner or g_frequency [media] cx18/ivtv: fix g_tuner support [media] tuner-core: power up tuner when called with s_power(1) [media] v4l2-ioctl.c: check for valid tuner type in S_HW_FREQ_SEEK [media] tuner-core: simplify the standard fixup [media] tuner-core/v4l2-subdev: document that the type field has to be filled in [media] v4l2-subdev.h: remove unused s_mode tuner op [media] feature-removal-schedule: change in how radio device nodes are handled [media] bttv: fix s_tuner for radio [media] pvrusb2: fix g/s_tuner support [media] v4l2-ioctl.c: prefill tuner type for g_frequency and g/s_tuner [media] tuner-core: fix tuner_resume: use t->mode instead of t->type [media] tuner-core: fix s_std and s_tuner
-rw-r--r--Documentation/feature-removal-schedule.txt22
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c2
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c8
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c8
-rw-r--r--drivers/media/video/msp3400-driver.c12
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c4
-rw-r--r--drivers/media/video/tuner-core.c229
-rw-r--r--drivers/media/video/v4l2-ioctl.c18
-rw-r--r--include/media/v4l2-subdev.h10
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.
583Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com> 583Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
584 584
585---------------------------- 585----------------------------
586
587What: For VIDIOC_S_FREQUENCY the type field must match the device node's type.
588 If not, return -EINVAL.
589When: 3.2
590Why: 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.
594Who: Hans Verkuil <hans.verkuil@cisco.com>
595
596----------------------------
597
598What: Opening a radio device node will no longer automatically switch the
599 tuner mode from tv to radio.
600When: 3.3
601Why: 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.
605Who: 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 */
738static int set_mode_freq(struct i2c_client *client, struct tuner *t, 735static 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 */
759static 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 */
830static int tuner_fixup_std(struct tuner *t) 837static 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)
1058static int tuner_s_radio(struct v4l2_subdev *sd) 1026static 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 */
1077static int tuner_s_power(struct v4l2_subdev *sd, int on) 1044static 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)
1093static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std) 1064static 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
1107static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) 1078static 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 */
1118static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) 1097static 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 */
1140static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) 1128static 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 */
1180static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) 1178static 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 */
184struct v4l2_subdev_tuner_ops { 189struct 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);