cx88-tvaudio.c (7b61ba8ff838dbee422d428fbd882ab83db4b2d9) cx88-tvaudio.c (399426cadf5b0539a5b2a4d805257ce8acc6aba2)
1/*
2 * cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
3 *
4 * (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
5 * (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
6 * (c) 2003 Gerd Knorr <kraxel@bytesex.org>
7 *
8 * -----------------------------------------------------------------------

--- 43 unchanged lines hidden (view full) ---

52MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
53
54static unsigned int always_analog;
55module_param(always_analog, int, 0644);
56MODULE_PARM_DESC(always_analog, "force analog audio out");
57
58static unsigned int radio_deemphasis;
59module_param(radio_deemphasis, int, 0644);
1/*
2 * cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
3 *
4 * (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
5 * (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
6 * (c) 2003 Gerd Knorr <kraxel@bytesex.org>
7 *
8 * -----------------------------------------------------------------------

--- 43 unchanged lines hidden (view full) ---

52MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
53
54static unsigned int always_analog;
55module_param(always_analog, int, 0644);
56MODULE_PARM_DESC(always_analog, "force analog audio out");
57
58static unsigned int radio_deemphasis;
59module_param(radio_deemphasis, int, 0644);
60MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, 0=None, 1=50us (elsewhere), 2=75us (USA)");
60MODULE_PARM_DESC(radio_deemphasis,
61 "Radio deemphasis time constant, 0=None, 1=50us (elsewhere), 2=75us (USA)");
61
62#define dprintk(fmt, arg...) do { \
63 if (audio_debug) \
64 printk(KERN_DEBUG pr_fmt("%s: tvaudio:" fmt), \
65 __func__, ##arg); \
66} while (0)
67/* ----------------------------------------------------------- */
68

--- 67 unchanged lines hidden (view full) ---

136 /* restart dma; This avoids buzz in NICAM and is good in others */
137 cx88_stop_audio_dma(core);
138 cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
139 cx88_start_audio_dma(core);
140
141 if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
142 cx_write(AUD_I2SINPUTCNTL, 4);
143 cx_write(AUD_BAUDRATE, 1);
62
63#define dprintk(fmt, arg...) do { \
64 if (audio_debug) \
65 printk(KERN_DEBUG pr_fmt("%s: tvaudio:" fmt), \
66 __func__, ##arg); \
67} while (0)
68/* ----------------------------------------------------------- */
69

--- 67 unchanged lines hidden (view full) ---

137 /* restart dma; This avoids buzz in NICAM and is good in others */
138 cx88_stop_audio_dma(core);
139 cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
140 cx88_start_audio_dma(core);
141
142 if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
143 cx_write(AUD_I2SINPUTCNTL, 4);
144 cx_write(AUD_BAUDRATE, 1);
144 /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
145 /*
146 * 'pass-thru mode': this enables the i2s
147 * output to the mpeg encoder
148 */
145 cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
146 cx_write(AUD_I2SOUTPUTCNTL, 1);
147 cx_write(AUD_I2SCNTL, 0);
148 /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
149 }
150 if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
151 ctl |= EN_DAC_ENABLE;
152 cx_write(AUD_CTL, ctl);

--- 476 unchanged lines hidden (view full) ---

629 case WW_BTSC:
630 case WW_EIAJ:
631 case WW_I2SPT:
632 case WW_FM:
633 case WW_I2SADC:
634 case WW_M:
635 dprintk("%s Warning: wrong value\n", __func__);
636 return;
149 cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
150 cx_write(AUD_I2SOUTPUTCNTL, 1);
151 cx_write(AUD_I2SCNTL, 0);
152 /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
153 }
154 if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
155 ctl |= EN_DAC_ENABLE;
156 cx_write(AUD_CTL, ctl);

--- 476 unchanged lines hidden (view full) ---

633 case WW_BTSC:
634 case WW_EIAJ:
635 case WW_I2SPT:
636 case WW_FM:
637 case WW_I2SADC:
638 case WW_M:
639 dprintk("%s Warning: wrong value\n", __func__);
640 return;
637 break;
638 }
639
640 mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
641 set_audio_finish(core, mode);
642}
643
644static void set_audio_standard_EIAJ(struct cx88_core *core)
645{

--- 40 unchanged lines hidden (view full) ---

686 {AUD_DEEMPH1_B0, 0x11EC},
687 {AUD_DEEMPH1_A1, 0x3FC66},
688 {AUD_DEEMPH1_B1, 0x399A},
689
690 {AUD_POLYPH80SCALEFAC, 0x0003},
691 { /* end of list */ },
692 };
693
641 }
642
643 mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
644 set_audio_finish(core, mode);
645}
646
647static void set_audio_standard_EIAJ(struct cx88_core *core)
648{

--- 40 unchanged lines hidden (view full) ---

689 {AUD_DEEMPH1_B0, 0x11EC},
690 {AUD_DEEMPH1_A1, 0x3FC66},
691 {AUD_DEEMPH1_B1, 0x399A},
692
693 {AUD_POLYPH80SCALEFAC, 0x0003},
694 { /* end of list */ },
695 };
696
694 /* It is enough to leave default values? */
695 /* No, it's not! The deemphasis registers are reset to the 75us
697 /*
698 * It is enough to leave default values?
699 *
700 * No, it's not! The deemphasis registers are reset to the 75us
696 * values by default. Analyzing the spectrum of the decoded audio
697 * reveals that "no deemphasis" is the same as 75 us, while the 50 us
701 * values by default. Analyzing the spectrum of the decoded audio
702 * reveals that "no deemphasis" is the same as 75 us, while the 50 us
698 * setting results in less deemphasis. */
703 * setting results in less deemphasis.
704 */
699 static const struct rlist fm_no_deemph[] = {
705 static const struct rlist fm_no_deemph[] = {
700
701 {AUD_POLYPH80SCALEFAC, 0x0003},
702 { /* end of list */ },
703 };
704
705 dprintk("%s (status: unknown)\n", __func__);
706 set_audio_start(core, SEL_FMRADIO);
707
708 switch (deemph) {

--- 27 unchanged lines hidden (view full) ---

736 j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
737
738 if (j == 1) {
739 dprintk("nicam is detected.\n");
740 return 1;
741 }
742
743 /* wait a little bit for next reading status */
706 {AUD_POLYPH80SCALEFAC, 0x0003},
707 { /* end of list */ },
708 };
709
710 dprintk("%s (status: unknown)\n", __func__);
711 set_audio_start(core, SEL_FMRADIO);
712
713 switch (deemph) {

--- 27 unchanged lines hidden (view full) ---

741 j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
742
743 if (j == 1) {
744 dprintk("nicam is detected.\n");
745 return 1;
746 }
747
748 /* wait a little bit for next reading status */
744 msleep(10);
749 usleep_range(10000, 20000);
745 }
746
747 dprintk("nicam is not detected.\n");
748 return 0;
749}
750
751void cx88_set_tvaudio(struct cx88_core *core)
752{

--- 4 unchanged lines hidden (view full) ---

757 case WW_BG:
758 case WW_DK:
759 case WW_M:
760 case WW_I:
761 case WW_L:
762 /* prepare all dsp registers */
763 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
764
750 }
751
752 dprintk("nicam is not detected.\n");
753 return 0;
754}
755
756void cx88_set_tvaudio(struct cx88_core *core)
757{

--- 4 unchanged lines hidden (view full) ---

762 case WW_BG:
763 case WW_DK:
764 case WW_M:
765 case WW_I:
766 case WW_L:
767 /* prepare all dsp registers */
768 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
769
765 /* set nicam mode - otherwise
766 AUD_NICAM_STATUS2 contains wrong values */
770 /*
771 * set nicam mode - otherwise
772 * AUD_NICAM_STATUS2 contains wrong values
773 */
767 set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
768 if (cx88_detect_nicam(core) == 0) {
769 /* fall back to fm / am mono */
770 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
771 core->audiomode_current = V4L2_TUNER_MODE_MONO;
772 core->use_nicam = 0;
773 } else {
774 core->use_nicam = 1;

--- 17 unchanged lines hidden (view full) ---

792 cx_write(AUD_I2SCNTL, 0x1);
793 set_audio_finish(core, EN_I2SIN_ENABLE);
794 break;
795 case WW_NONE:
796 case WW_I2SPT:
797 pr_info("unknown tv audio mode [%d]\n", core->tvaudio);
798 break;
799 }
774 set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
775 if (cx88_detect_nicam(core) == 0) {
776 /* fall back to fm / am mono */
777 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
778 core->audiomode_current = V4L2_TUNER_MODE_MONO;
779 core->use_nicam = 0;
780 } else {
781 core->use_nicam = 1;

--- 17 unchanged lines hidden (view full) ---

799 cx_write(AUD_I2SCNTL, 0x1);
800 set_audio_finish(core, EN_I2SIN_ENABLE);
801 break;
802 case WW_NONE:
803 case WW_I2SPT:
804 pr_info("unknown tv audio mode [%d]\n", core->tvaudio);
805 break;
806 }
800 return;
801}
807}
808EXPORT_SYMBOL(cx88_set_tvaudio);
802
803void cx88_newstation(struct cx88_core *core)
804{
805 core->audiomode_manual = UNSET;
806 core->last_change = jiffies;
807}
809
810void cx88_newstation(struct cx88_core *core)
811{
812 core->audiomode_manual = UNSET;
813 core->last_change = jiffies;
814}
815EXPORT_SYMBOL(cx88_newstation);
808
809void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
810{
816
817void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
818{
811 static const char * const m[] = { "stereo", "dual mono", "mono", "sap" };
812 static const char * const p[] = { "no pilot", "pilot c1", "pilot c2", "?" };
819 static const char * const m[] = { "stereo", "dual mono",
820 "mono", "sap" };
821 static const char * const p[] = { "no pilot", "pilot c1",
822 "pilot c2", "?" };
813 u32 reg, mode, pilot;
814
815 reg = cx_read(AUD_STATUS);
816 mode = reg & 0x03;
817 pilot = (reg >> 2) & 0x03;
818
819 if (core->astat != reg)
820 dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",

--- 40 unchanged lines hidden (view full) ---

861 case WW_I2SADC:
862 /* nothing */
863 break;
864 }
865
866 /* If software stereo detection is not supported... */
867 if (t->rxsubchans == UNSET) {
868 t->rxsubchans = V4L2_TUNER_SUB_MONO;
823 u32 reg, mode, pilot;
824
825 reg = cx_read(AUD_STATUS);
826 mode = reg & 0x03;
827 pilot = (reg >> 2) & 0x03;
828
829 if (core->astat != reg)
830 dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",

--- 40 unchanged lines hidden (view full) ---

871 case WW_I2SADC:
872 /* nothing */
873 break;
874 }
875
876 /* If software stereo detection is not supported... */
877 if (t->rxsubchans == UNSET) {
878 t->rxsubchans = V4L2_TUNER_SUB_MONO;
869 /* If the hardware itself detected stereo, also return
870 stereo as an available subchannel */
879 /*
880 * If the hardware itself detected stereo, also return
881 * stereo as an available subchannel
882 */
871 if (t->audmode == V4L2_TUNER_MODE_STEREO)
872 t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
873 }
883 if (t->audmode == V4L2_TUNER_MODE_STEREO)
884 t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
885 }
874 return;
875}
886}
887EXPORT_SYMBOL(cx88_get_stereo);
876
888
889
877void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
878{
879 u32 ctl = UNSET;
880 u32 mask = UNSET;
881
882 if (manual) {
883 core->audiomode_manual = mode;
884 } else {

--- 38 unchanged lines hidden (view full) ---

923 break;
924 case V4L2_TUNER_MODE_STEREO:
925 case V4L2_TUNER_MODE_LANG1_LANG2:
926 set_audio_standard_NICAM(core,
927 EN_NICAM_FORCE_STEREO);
928 break;
929 }
930 } else {
890void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
891{
892 u32 ctl = UNSET;
893 u32 mask = UNSET;
894
895 if (manual) {
896 core->audiomode_manual = mode;
897 } else {

--- 38 unchanged lines hidden (view full) ---

936 break;
937 case V4L2_TUNER_MODE_STEREO:
938 case V4L2_TUNER_MODE_LANG1_LANG2:
939 set_audio_standard_NICAM(core,
940 EN_NICAM_FORCE_STEREO);
941 break;
942 }
943 } else {
931 if ((core->tvaudio == WW_I) || (core->tvaudio == WW_L)) {
944 if ((core->tvaudio == WW_I) ||
945 (core->tvaudio == WW_L)) {
932 /* fall back to fm / am mono */
933 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
934 } else {
935 /* TODO: Add A2 autodection */
936 mask = 0x3f;
937 switch (mode) {
938 case V4L2_TUNER_MODE_MONO:
939 case V4L2_TUNER_MODE_LANG1:

--- 31 unchanged lines hidden (view full) ---

971 }
972
973 if (ctl != UNSET) {
974 dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x [status=0x%x,ctl=0x%x,vol=0x%x]\n",
975 mask, ctl, cx_read(AUD_STATUS),
976 cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
977 cx_andor(AUD_CTL, mask, ctl);
978 }
946 /* fall back to fm / am mono */
947 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
948 } else {
949 /* TODO: Add A2 autodection */
950 mask = 0x3f;
951 switch (mode) {
952 case V4L2_TUNER_MODE_MONO:
953 case V4L2_TUNER_MODE_LANG1:

--- 31 unchanged lines hidden (view full) ---

985 }
986
987 if (ctl != UNSET) {
988 dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x [status=0x%x,ctl=0x%x,vol=0x%x]\n",
989 mask, ctl, cx_read(AUD_STATUS),
990 cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
991 cx_andor(AUD_CTL, mask, ctl);
992 }
979 return;
980}
993}
994EXPORT_SYMBOL(cx88_set_stereo);
981
982int cx88_audio_thread(void *data)
983{
984 struct cx88_core *core = data;
985 struct v4l2_tuner t;
986 u32 mode = 0;
987
988 dprintk("cx88: tvaudio thread started\n");

--- 33 unchanged lines hidden (view full) ---

1022 break;
1023 case WW_NONE:
1024 case WW_BTSC:
1025 case WW_EIAJ:
1026 case WW_I2SPT:
1027 case WW_FM:
1028 case WW_I2SADC:
1029hw_autodetect:
995
996int cx88_audio_thread(void *data)
997{
998 struct cx88_core *core = data;
999 struct v4l2_tuner t;
1000 u32 mode = 0;
1001
1002 dprintk("cx88: tvaudio thread started\n");

--- 33 unchanged lines hidden (view full) ---

1036 break;
1037 case WW_NONE:
1038 case WW_BTSC:
1039 case WW_EIAJ:
1040 case WW_I2SPT:
1041 case WW_FM:
1042 case WW_I2SADC:
1043hw_autodetect:
1030 /* stereo autodetection is supported by hardware so
1031 we don't need to do it manually. Do nothing. */
1044 /*
1045 * stereo autodetection is supported by hardware so
1046 * we don't need to do it manually. Do nothing.
1047 */
1032 break;
1033 }
1034 }
1035
1036 dprintk("cx88: tvaudio thread exiting\n");
1037 return 0;
1038}
1048 break;
1049 }
1050 }
1051
1052 dprintk("cx88: tvaudio thread exiting\n");
1053 return 0;
1054}
1039
1040/* ----------------------------------------------------------- */
1041
1042EXPORT_SYMBOL(cx88_set_tvaudio);
1043EXPORT_SYMBOL(cx88_newstation);
1044EXPORT_SYMBOL(cx88_set_stereo);
1045EXPORT_SYMBOL(cx88_get_stereo);
1046EXPORT_SYMBOL(cx88_audio_thread);
1055EXPORT_SYMBOL(cx88_audio_thread);