diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-11 19:43:27 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-11 19:43:27 -0400 |
| commit | c15000b40d46c0affa4c142c4ecb7beee4ce03f3 (patch) | |
| tree | 14fe31249f9f8c882fecc63542821d6b431630c6 | |
| parent | 9ddf7f5058c4f4badd38dba8d5896a5dbd7e716f (diff) | |
| parent | ddc6ff31cc22720c46c1547a5310ea260a968ae9 (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.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); |
