diff options
Diffstat (limited to 'drivers/media/video/cx88/cx88-tvaudio.c')
-rw-r--r-- | drivers/media/video/cx88/cx88-tvaudio.c | 115 |
1 files changed, 86 insertions, 29 deletions
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 7dd506b987fe..e8316cf7f32f 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c | |||
@@ -163,6 +163,8 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) | |||
163 | /* unmute */ | 163 | /* unmute */ |
164 | volume = cx_sread(SHADOW_AUD_VOL_CTL); | 164 | volume = cx_sread(SHADOW_AUD_VOL_CTL); |
165 | cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume); | 165 | cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume); |
166 | |||
167 | core->last_change = jiffies; | ||
166 | } | 168 | } |
167 | 169 | ||
168 | /* ----------------------------------------------------------- */ | 170 | /* ----------------------------------------------------------- */ |
@@ -745,6 +747,7 @@ void cx88_set_tvaudio(struct cx88_core *core) | |||
745 | break; | 747 | break; |
746 | case WW_BG: | 748 | case WW_BG: |
747 | case WW_DK: | 749 | case WW_DK: |
750 | case WW_M: | ||
748 | case WW_I: | 751 | case WW_I: |
749 | case WW_L: | 752 | case WW_L: |
750 | /* prepare all dsp registers */ | 753 | /* prepare all dsp registers */ |
@@ -756,6 +759,7 @@ void cx88_set_tvaudio(struct cx88_core *core) | |||
756 | if (0 == cx88_detect_nicam(core)) { | 759 | if (0 == cx88_detect_nicam(core)) { |
757 | /* fall back to fm / am mono */ | 760 | /* fall back to fm / am mono */ |
758 | set_audio_standard_A2(core, EN_A2_FORCE_MONO1); | 761 | set_audio_standard_A2(core, EN_A2_FORCE_MONO1); |
762 | core->audiomode_current = V4L2_TUNER_MODE_MONO; | ||
759 | core->use_nicam = 0; | 763 | core->use_nicam = 0; |
760 | } else { | 764 | } else { |
761 | core->use_nicam = 1; | 765 | core->use_nicam = 1; |
@@ -787,6 +791,7 @@ void cx88_set_tvaudio(struct cx88_core *core) | |||
787 | void cx88_newstation(struct cx88_core *core) | 791 | void cx88_newstation(struct cx88_core *core) |
788 | { | 792 | { |
789 | core->audiomode_manual = UNSET; | 793 | core->audiomode_manual = UNSET; |
794 | core->last_change = jiffies; | ||
790 | } | 795 | } |
791 | 796 | ||
792 | void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) | 797 | void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) |
@@ -805,12 +810,50 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) | |||
805 | aud_ctl_names[cx_read(AUD_CTL) & 63]); | 810 | aud_ctl_names[cx_read(AUD_CTL) & 63]); |
806 | core->astat = reg; | 811 | core->astat = reg; |
807 | 812 | ||
808 | /* TODO | 813 | t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP | |
809 | Reading from AUD_STATUS is not enough | 814 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; |
810 | for auto-detecting sap/dual-fm/nicam. | 815 | t->rxsubchans = UNSET; |
811 | Add some code here later. | 816 | t->audmode = V4L2_TUNER_MODE_MONO; |
812 | */ | 817 | |
818 | switch (mode) { | ||
819 | case 0: | ||
820 | t->audmode = V4L2_TUNER_MODE_STEREO; | ||
821 | break; | ||
822 | case 1: | ||
823 | t->audmode = V4L2_TUNER_MODE_LANG2; | ||
824 | break; | ||
825 | case 2: | ||
826 | t->audmode = V4L2_TUNER_MODE_MONO; | ||
827 | break; | ||
828 | case 3: | ||
829 | t->audmode = V4L2_TUNER_MODE_SAP; | ||
830 | break; | ||
831 | } | ||
813 | 832 | ||
833 | switch (core->tvaudio) { | ||
834 | case WW_BTSC: | ||
835 | case WW_BG: | ||
836 | case WW_DK: | ||
837 | case WW_M: | ||
838 | case WW_EIAJ: | ||
839 | if (!core->use_nicam) { | ||
840 | t->rxsubchans = cx88_dsp_detect_stereo_sap(core); | ||
841 | break; | ||
842 | } | ||
843 | break; | ||
844 | default: | ||
845 | /* nothing */ | ||
846 | break; | ||
847 | } | ||
848 | |||
849 | /* If software stereo detection is not supported... */ | ||
850 | if (UNSET == t->rxsubchans) { | ||
851 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
852 | /* If the hardware itself detected stereo, also return | ||
853 | stereo as an available subchannel */ | ||
854 | if (V4L2_TUNER_MODE_STEREO == t->audmode) | ||
855 | t->rxsubchans |= V4L2_TUNER_SUB_STEREO; | ||
856 | } | ||
814 | return; | 857 | return; |
815 | } | 858 | } |
816 | 859 | ||
@@ -847,6 +890,7 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) | |||
847 | break; | 890 | break; |
848 | case WW_BG: | 891 | case WW_BG: |
849 | case WW_DK: | 892 | case WW_DK: |
893 | case WW_M: | ||
850 | case WW_I: | 894 | case WW_I: |
851 | case WW_L: | 895 | case WW_L: |
852 | if (1 == core->use_nicam) { | 896 | if (1 == core->use_nicam) { |
@@ -872,20 +916,18 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) | |||
872 | set_audio_standard_A2(core, EN_A2_FORCE_MONO1); | 916 | set_audio_standard_A2(core, EN_A2_FORCE_MONO1); |
873 | } else { | 917 | } else { |
874 | /* TODO: Add A2 autodection */ | 918 | /* TODO: Add A2 autodection */ |
919 | mask = 0x3f; | ||
875 | switch (mode) { | 920 | switch (mode) { |
876 | case V4L2_TUNER_MODE_MONO: | 921 | case V4L2_TUNER_MODE_MONO: |
877 | case V4L2_TUNER_MODE_LANG1: | 922 | case V4L2_TUNER_MODE_LANG1: |
878 | set_audio_standard_A2(core, | 923 | ctl = EN_A2_FORCE_MONO1; |
879 | EN_A2_FORCE_MONO1); | ||
880 | break; | 924 | break; |
881 | case V4L2_TUNER_MODE_LANG2: | 925 | case V4L2_TUNER_MODE_LANG2: |
882 | set_audio_standard_A2(core, | 926 | ctl = EN_A2_FORCE_MONO2; |
883 | EN_A2_FORCE_MONO2); | ||
884 | break; | 927 | break; |
885 | case V4L2_TUNER_MODE_STEREO: | 928 | case V4L2_TUNER_MODE_STEREO: |
886 | case V4L2_TUNER_MODE_LANG1_LANG2: | 929 | case V4L2_TUNER_MODE_LANG1_LANG2: |
887 | set_audio_standard_A2(core, | 930 | ctl = EN_A2_FORCE_STEREO; |
888 | EN_A2_FORCE_STEREO); | ||
889 | break; | 931 | break; |
890 | } | 932 | } |
891 | } | 933 | } |
@@ -932,24 +974,39 @@ int cx88_audio_thread(void *data) | |||
932 | break; | 974 | break; |
933 | try_to_freeze(); | 975 | try_to_freeze(); |
934 | 976 | ||
935 | /* just monitor the audio status for now ... */ | 977 | switch (core->tvaudio) { |
936 | memset(&t, 0, sizeof(t)); | 978 | case WW_BG: |
937 | cx88_get_stereo(core, &t); | 979 | case WW_DK: |
938 | 980 | case WW_M: | |
939 | if (UNSET != core->audiomode_manual) | 981 | case WW_I: |
940 | /* manually set, don't do anything. */ | 982 | case WW_L: |
941 | continue; | 983 | if (core->use_nicam) |
942 | 984 | goto hw_autodetect; | |
943 | /* monitor signal */ | 985 | |
944 | if (t.rxsubchans & V4L2_TUNER_SUB_STEREO) | 986 | /* just monitor the audio status for now ... */ |
945 | mode = V4L2_TUNER_MODE_STEREO; | 987 | memset(&t, 0, sizeof(t)); |
946 | else | 988 | cx88_get_stereo(core, &t); |
947 | mode = V4L2_TUNER_MODE_MONO; | 989 | |
948 | if (mode == core->audiomode_current) | 990 | if (UNSET != core->audiomode_manual) |
949 | continue; | 991 | /* manually set, don't do anything. */ |
950 | 992 | continue; | |
951 | /* automatically switch to best available mode */ | 993 | |
952 | cx88_set_stereo(core, mode, 0); | 994 | /* monitor signal and set stereo if available */ |
995 | if (t.rxsubchans & V4L2_TUNER_SUB_STEREO) | ||
996 | mode = V4L2_TUNER_MODE_STEREO; | ||
997 | else | ||
998 | mode = V4L2_TUNER_MODE_MONO; | ||
999 | if (mode == core->audiomode_current) | ||
1000 | continue; | ||
1001 | /* automatically switch to best available mode */ | ||
1002 | cx88_set_stereo(core, mode, 0); | ||
1003 | break; | ||
1004 | default: | ||
1005 | hw_autodetect: | ||
1006 | /* stereo autodetection is supported by hardware so | ||
1007 | we don't need to do it manually. Do nothing. */ | ||
1008 | break; | ||
1009 | } | ||
953 | } | 1010 | } |
954 | 1011 | ||
955 | dprintk("cx88: tvaudio thread exiting\n"); | 1012 | dprintk("cx88: tvaudio thread exiting\n"); |