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); |