| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * ALSA driver for RME Hammerfall DSP MADI audio interface(s) |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 23 | 24 | * |
|---|
| 24 | 25 | * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth |
|---|
| 25 | 26 | * |
|---|
| 26 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 27 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 28 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 29 | | - * (at your option) any later version. |
|---|
| 30 | | - * |
|---|
| 31 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 32 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 33 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 34 | | - * GNU General Public License for more details. |
|---|
| 35 | | - * |
|---|
| 36 | | - * You should have received a copy of the GNU General Public License |
|---|
| 37 | | - * along with this program; if not, write to the Free Software |
|---|
| 38 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 39 | | - * |
|---|
| 27 | + * Modified 2019-05-23 fix AIO single speed ADAT capture and playback |
|---|
| 28 | + * by Philippe.Bekaert@uhasselt.be |
|---|
| 40 | 29 | */ |
|---|
| 41 | 30 | |
|---|
| 42 | 31 | /* ************* Register Documentation ******************************************************* |
|---|
| .. | .. |
|---|
| 648 | 637 | #define HDSPM_SPEED_QUAD 2 |
|---|
| 649 | 638 | |
|---|
| 650 | 639 | /* names for speed modes */ |
|---|
| 651 | | -static char *hdspm_speed_names[] = { "single", "double", "quad" }; |
|---|
| 640 | +static const char * const hdspm_speed_names[] = { "single", "double", "quad" }; |
|---|
| 652 | 641 | |
|---|
| 653 | 642 | static const char *const texts_autosync_aes_tco[] = { "Word Clock", |
|---|
| 654 | 643 | "AES1", "AES2", "AES3", "AES4", |
|---|
| .. | .. |
|---|
| 695 | 684 | "192 kHz" |
|---|
| 696 | 685 | }; |
|---|
| 697 | 686 | |
|---|
| 698 | | -static char *texts_ports_madi[] = { |
|---|
| 687 | +static const char * const texts_ports_madi[] = { |
|---|
| 699 | 688 | "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6", |
|---|
| 700 | 689 | "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12", |
|---|
| 701 | 690 | "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18", |
|---|
| .. | .. |
|---|
| 710 | 699 | }; |
|---|
| 711 | 700 | |
|---|
| 712 | 701 | |
|---|
| 713 | | -static char *texts_ports_raydat_ss[] = { |
|---|
| 702 | +static const char * const texts_ports_raydat_ss[] = { |
|---|
| 714 | 703 | "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6", |
|---|
| 715 | 704 | "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4", |
|---|
| 716 | 705 | "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2", |
|---|
| .. | .. |
|---|
| 721 | 710 | "SPDIF.L", "SPDIF.R" |
|---|
| 722 | 711 | }; |
|---|
| 723 | 712 | |
|---|
| 724 | | -static char *texts_ports_raydat_ds[] = { |
|---|
| 713 | +static const char * const texts_ports_raydat_ds[] = { |
|---|
| 725 | 714 | "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", |
|---|
| 726 | 715 | "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4", |
|---|
| 727 | 716 | "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4", |
|---|
| .. | .. |
|---|
| 730 | 719 | "SPDIF.L", "SPDIF.R" |
|---|
| 731 | 720 | }; |
|---|
| 732 | 721 | |
|---|
| 733 | | -static char *texts_ports_raydat_qs[] = { |
|---|
| 722 | +static const char * const texts_ports_raydat_qs[] = { |
|---|
| 734 | 723 | "ADAT1.1", "ADAT1.2", |
|---|
| 735 | 724 | "ADAT2.1", "ADAT2.2", |
|---|
| 736 | 725 | "ADAT3.1", "ADAT3.2", |
|---|
| .. | .. |
|---|
| 740 | 729 | }; |
|---|
| 741 | 730 | |
|---|
| 742 | 731 | |
|---|
| 743 | | -static char *texts_ports_aio_in_ss[] = { |
|---|
| 732 | +static const char * const texts_ports_aio_in_ss[] = { |
|---|
| 744 | 733 | "Analogue.L", "Analogue.R", |
|---|
| 745 | 734 | "AES.L", "AES.R", |
|---|
| 746 | 735 | "SPDIF.L", "SPDIF.R", |
|---|
| .. | .. |
|---|
| 749 | 738 | "AEB.1", "AEB.2", "AEB.3", "AEB.4" |
|---|
| 750 | 739 | }; |
|---|
| 751 | 740 | |
|---|
| 752 | | -static char *texts_ports_aio_out_ss[] = { |
|---|
| 741 | +static const char * const texts_ports_aio_out_ss[] = { |
|---|
| 753 | 742 | "Analogue.L", "Analogue.R", |
|---|
| 754 | 743 | "AES.L", "AES.R", |
|---|
| 755 | 744 | "SPDIF.L", "SPDIF.R", |
|---|
| .. | .. |
|---|
| 759 | 748 | "AEB.1", "AEB.2", "AEB.3", "AEB.4" |
|---|
| 760 | 749 | }; |
|---|
| 761 | 750 | |
|---|
| 762 | | -static char *texts_ports_aio_in_ds[] = { |
|---|
| 751 | +static const char * const texts_ports_aio_in_ds[] = { |
|---|
| 763 | 752 | "Analogue.L", "Analogue.R", |
|---|
| 764 | 753 | "AES.L", "AES.R", |
|---|
| 765 | 754 | "SPDIF.L", "SPDIF.R", |
|---|
| .. | .. |
|---|
| 767 | 756 | "AEB.1", "AEB.2", "AEB.3", "AEB.4" |
|---|
| 768 | 757 | }; |
|---|
| 769 | 758 | |
|---|
| 770 | | -static char *texts_ports_aio_out_ds[] = { |
|---|
| 759 | +static const char * const texts_ports_aio_out_ds[] = { |
|---|
| 771 | 760 | "Analogue.L", "Analogue.R", |
|---|
| 772 | 761 | "AES.L", "AES.R", |
|---|
| 773 | 762 | "SPDIF.L", "SPDIF.R", |
|---|
| .. | .. |
|---|
| 776 | 765 | "AEB.1", "AEB.2", "AEB.3", "AEB.4" |
|---|
| 777 | 766 | }; |
|---|
| 778 | 767 | |
|---|
| 779 | | -static char *texts_ports_aio_in_qs[] = { |
|---|
| 768 | +static const char * const texts_ports_aio_in_qs[] = { |
|---|
| 780 | 769 | "Analogue.L", "Analogue.R", |
|---|
| 781 | 770 | "AES.L", "AES.R", |
|---|
| 782 | 771 | "SPDIF.L", "SPDIF.R", |
|---|
| .. | .. |
|---|
| 784 | 773 | "AEB.1", "AEB.2", "AEB.3", "AEB.4" |
|---|
| 785 | 774 | }; |
|---|
| 786 | 775 | |
|---|
| 787 | | -static char *texts_ports_aio_out_qs[] = { |
|---|
| 776 | +static const char * const texts_ports_aio_out_qs[] = { |
|---|
| 788 | 777 | "Analogue.L", "Analogue.R", |
|---|
| 789 | 778 | "AES.L", "AES.R", |
|---|
| 790 | 779 | "SPDIF.L", "SPDIF.R", |
|---|
| .. | .. |
|---|
| 793 | 782 | "AEB.1", "AEB.2", "AEB.3", "AEB.4" |
|---|
| 794 | 783 | }; |
|---|
| 795 | 784 | |
|---|
| 796 | | -static char *texts_ports_aes32[] = { |
|---|
| 785 | +static const char * const texts_ports_aes32[] = { |
|---|
| 797 | 786 | "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7", |
|---|
| 798 | 787 | "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14", |
|---|
| 799 | 788 | "AES.15", "AES.16" |
|---|
| .. | .. |
|---|
| 807 | 796 | where the data for that channel can be read/written from/to. |
|---|
| 808 | 797 | */ |
|---|
| 809 | 798 | |
|---|
| 810 | | -static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = { |
|---|
| 799 | +static const char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = { |
|---|
| 811 | 800 | 0, 1, 2, 3, 4, 5, 6, 7, |
|---|
| 812 | 801 | 8, 9, 10, 11, 12, 13, 14, 15, |
|---|
| 813 | 802 | 16, 17, 18, 19, 20, 21, 22, 23, |
|---|
| .. | .. |
|---|
| 818 | 807 | 56, 57, 58, 59, 60, 61, 62, 63 |
|---|
| 819 | 808 | }; |
|---|
| 820 | 809 | |
|---|
| 821 | | -static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = { |
|---|
| 810 | +static const char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = { |
|---|
| 822 | 811 | 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */ |
|---|
| 823 | 812 | 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */ |
|---|
| 824 | 813 | 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */ |
|---|
| .. | .. |
|---|
| 831 | 820 | -1, -1, -1, -1, -1, -1, -1, -1, |
|---|
| 832 | 821 | }; |
|---|
| 833 | 822 | |
|---|
| 834 | | -static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = { |
|---|
| 823 | +static const char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = { |
|---|
| 835 | 824 | 4, 5, 6, 7, /* ADAT 1 */ |
|---|
| 836 | 825 | 8, 9, 10, 11, /* ADAT 2 */ |
|---|
| 837 | 826 | 12, 13, 14, 15, /* ADAT 3 */ |
|---|
| .. | .. |
|---|
| 846 | 835 | -1, -1, -1, -1, -1, -1, -1, -1, |
|---|
| 847 | 836 | }; |
|---|
| 848 | 837 | |
|---|
| 849 | | -static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = { |
|---|
| 838 | +static const char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = { |
|---|
| 850 | 839 | 4, 5, /* ADAT 1 */ |
|---|
| 851 | 840 | 6, 7, /* ADAT 2 */ |
|---|
| 852 | 841 | 8, 9, /* ADAT 3 */ |
|---|
| .. | .. |
|---|
| 862 | 851 | -1, -1, -1, -1, -1, -1, -1, -1, |
|---|
| 863 | 852 | }; |
|---|
| 864 | 853 | |
|---|
| 865 | | -static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = { |
|---|
| 854 | +static const char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = { |
|---|
| 866 | 855 | 0, 1, /* line in */ |
|---|
| 867 | 856 | 8, 9, /* aes in, */ |
|---|
| 868 | 857 | 10, 11, /* spdif in */ |
|---|
| .. | .. |
|---|
| 876 | 865 | -1, -1, -1, -1, -1, -1, -1, -1, |
|---|
| 877 | 866 | }; |
|---|
| 878 | 867 | |
|---|
| 879 | | -static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = { |
|---|
| 868 | +static const char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = { |
|---|
| 880 | 869 | 0, 1, /* line out */ |
|---|
| 881 | 870 | 8, 9, /* aes out */ |
|---|
| 882 | 871 | 10, 11, /* spdif out */ |
|---|
| .. | .. |
|---|
| 891 | 880 | -1, -1, -1, -1, -1, -1, -1, -1, |
|---|
| 892 | 881 | }; |
|---|
| 893 | 882 | |
|---|
| 894 | | -static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = { |
|---|
| 883 | +static const char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = { |
|---|
| 895 | 884 | 0, 1, /* line in */ |
|---|
| 896 | 885 | 8, 9, /* aes in */ |
|---|
| 897 | 886 | 10, 11, /* spdif in */ |
|---|
| .. | .. |
|---|
| 906 | 895 | -1, -1, -1, -1, -1, -1, -1, -1 |
|---|
| 907 | 896 | }; |
|---|
| 908 | 897 | |
|---|
| 909 | | -static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = { |
|---|
| 898 | +static const char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = { |
|---|
| 910 | 899 | 0, 1, /* line out */ |
|---|
| 911 | 900 | 8, 9, /* aes out */ |
|---|
| 912 | 901 | 10, 11, /* spdif out */ |
|---|
| .. | .. |
|---|
| 921 | 910 | -1, -1, -1, -1, -1, -1, -1, -1 |
|---|
| 922 | 911 | }; |
|---|
| 923 | 912 | |
|---|
| 924 | | -static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = { |
|---|
| 913 | +static const char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = { |
|---|
| 925 | 914 | 0, 1, /* line in */ |
|---|
| 926 | 915 | 8, 9, /* aes in */ |
|---|
| 927 | 916 | 10, 11, /* spdif in */ |
|---|
| .. | .. |
|---|
| 936 | 925 | -1, -1, -1, -1, -1, -1, -1, -1 |
|---|
| 937 | 926 | }; |
|---|
| 938 | 927 | |
|---|
| 939 | | -static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = { |
|---|
| 928 | +static const char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = { |
|---|
| 940 | 929 | 0, 1, /* line out */ |
|---|
| 941 | 930 | 8, 9, /* aes out */ |
|---|
| 942 | 931 | 10, 11, /* spdif out */ |
|---|
| .. | .. |
|---|
| 952 | 941 | -1, -1, -1, -1, -1, -1, -1, -1 |
|---|
| 953 | 942 | }; |
|---|
| 954 | 943 | |
|---|
| 955 | | -static char channel_map_aes32[HDSPM_MAX_CHANNELS] = { |
|---|
| 944 | +static const char channel_map_aes32[HDSPM_MAX_CHANNELS] = { |
|---|
| 956 | 945 | 0, 1, 2, 3, 4, 5, 6, 7, |
|---|
| 957 | 946 | 8, 9, 10, 11, 12, 13, 14, 15, |
|---|
| 958 | 947 | -1, -1, -1, -1, -1, -1, -1, -1, |
|---|
| .. | .. |
|---|
| 1008 | 997 | u32 settings_register; /* cached value for AIO / RayDat (sync reference, master/slave) */ |
|---|
| 1009 | 998 | |
|---|
| 1010 | 999 | struct hdspm_midi midi[4]; |
|---|
| 1011 | | - struct tasklet_struct midi_tasklet; |
|---|
| 1000 | + struct work_struct midi_work; |
|---|
| 1012 | 1001 | |
|---|
| 1013 | 1002 | size_t period_bytes; |
|---|
| 1014 | 1003 | unsigned char ss_in_channels; |
|---|
| .. | .. |
|---|
| 1021 | 1010 | unsigned char max_channels_in; |
|---|
| 1022 | 1011 | unsigned char max_channels_out; |
|---|
| 1023 | 1012 | |
|---|
| 1024 | | - signed char *channel_map_in; |
|---|
| 1025 | | - signed char *channel_map_out; |
|---|
| 1013 | + const signed char *channel_map_in; |
|---|
| 1014 | + const signed char *channel_map_out; |
|---|
| 1026 | 1015 | |
|---|
| 1027 | | - signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; |
|---|
| 1028 | | - signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; |
|---|
| 1016 | + const signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; |
|---|
| 1017 | + const signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; |
|---|
| 1029 | 1018 | |
|---|
| 1030 | | - char **port_names_in; |
|---|
| 1031 | | - char **port_names_out; |
|---|
| 1019 | + const char * const *port_names_in; |
|---|
| 1020 | + const char * const *port_names_out; |
|---|
| 1032 | 1021 | |
|---|
| 1033 | | - char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs; |
|---|
| 1034 | | - char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs; |
|---|
| 1022 | + const char * const *port_names_in_ss; |
|---|
| 1023 | + const char * const *port_names_in_ds; |
|---|
| 1024 | + const char * const *port_names_in_qs; |
|---|
| 1025 | + const char * const *port_names_out_ss; |
|---|
| 1026 | + const char * const *port_names_out_ds; |
|---|
| 1027 | + const char * const *port_names_out_qs; |
|---|
| 1035 | 1028 | |
|---|
| 1036 | 1029 | unsigned char *playback_buffer; /* suitably aligned address */ |
|---|
| 1037 | 1030 | unsigned char *capture_buffer; /* suitably aligned address */ |
|---|
| .. | .. |
|---|
| 1105 | 1098 | static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out); |
|---|
| 1106 | 1099 | static int snd_hdspm_set_defaults(struct hdspm *hdspm); |
|---|
| 1107 | 1100 | static int hdspm_system_clock_mode(struct hdspm *hdspm); |
|---|
| 1108 | | -static void hdspm_set_sgbuf(struct hdspm *hdspm, |
|---|
| 1109 | | - struct snd_pcm_substream *substream, |
|---|
| 1110 | | - unsigned int reg, int channels); |
|---|
| 1101 | +static void hdspm_set_channel_dma_addr(struct hdspm *hdspm, |
|---|
| 1102 | + struct snd_pcm_substream *substream, |
|---|
| 1103 | + unsigned int reg, int channels); |
|---|
| 1111 | 1104 | |
|---|
| 1112 | 1105 | static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx); |
|---|
| 1113 | 1106 | static int hdspm_wc_sync_check(struct hdspm *hdspm); |
|---|
| .. | .. |
|---|
| 1224 | 1217 | return ret; |
|---|
| 1225 | 1218 | } |
|---|
| 1226 | 1219 | |
|---|
| 1227 | | -/* round arbitary sample rates to commonly known rates */ |
|---|
| 1220 | +/* round arbitrary sample rates to commonly known rates */ |
|---|
| 1228 | 1221 | static int hdspm_round_frequency(int rate) |
|---|
| 1229 | 1222 | { |
|---|
| 1230 | 1223 | if (rate < 38050) |
|---|
| .. | .. |
|---|
| 2176 | 2169 | } |
|---|
| 2177 | 2170 | |
|---|
| 2178 | 2171 | |
|---|
| 2179 | | -static void hdspm_midi_tasklet(unsigned long arg) |
|---|
| 2172 | +static void hdspm_midi_work(struct work_struct *work) |
|---|
| 2180 | 2173 | { |
|---|
| 2181 | | - struct hdspm *hdspm = (struct hdspm *)arg; |
|---|
| 2174 | + struct hdspm *hdspm = container_of(work, struct hdspm, midi_work); |
|---|
| 2182 | 2175 | int i = 0; |
|---|
| 2183 | 2176 | |
|---|
| 2184 | 2177 | while (i < hdspm->midiPorts) { |
|---|
| .. | .. |
|---|
| 3034 | 3027 | |
|---|
| 3035 | 3028 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); |
|---|
| 3036 | 3029 | unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF; |
|---|
| 3037 | | - if ((syncref >= HDSPM_AES32_AUTOSYNC_FROM_WORD) && |
|---|
| 3038 | | - (syncref <= HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN)) { |
|---|
| 3030 | + /* syncref >= HDSPM_AES32_AUTOSYNC_FROM_WORD is always true */ |
|---|
| 3031 | + if (syncref <= HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN) { |
|---|
| 3039 | 3032 | return syncref; |
|---|
| 3040 | 3033 | } |
|---|
| 3041 | 3034 | return HDSPM_AES32_AUTOSYNC_FROM_NONE; |
|---|
| .. | .. |
|---|
| 4489 | 4482 | |
|---|
| 4490 | 4483 | |
|---|
| 4491 | 4484 | |
|---|
| 4492 | | -static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { |
|---|
| 4485 | +static const struct snd_kcontrol_new snd_hdspm_controls_madi[] = { |
|---|
| 4493 | 4486 | HDSPM_MIXER("Mixer", 0), |
|---|
| 4494 | 4487 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), |
|---|
| 4495 | 4488 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
|---|
| .. | .. |
|---|
| 4511 | 4504 | }; |
|---|
| 4512 | 4505 | |
|---|
| 4513 | 4506 | |
|---|
| 4514 | | -static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = { |
|---|
| 4507 | +static const struct snd_kcontrol_new snd_hdspm_controls_madiface[] = { |
|---|
| 4515 | 4508 | HDSPM_MIXER("Mixer", 0), |
|---|
| 4516 | 4509 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), |
|---|
| 4517 | 4510 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
|---|
| .. | .. |
|---|
| 4524 | 4517 | HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0) |
|---|
| 4525 | 4518 | }; |
|---|
| 4526 | 4519 | |
|---|
| 4527 | | -static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { |
|---|
| 4520 | +static const struct snd_kcontrol_new snd_hdspm_controls_aio[] = { |
|---|
| 4528 | 4521 | HDSPM_MIXER("Mixer", 0), |
|---|
| 4529 | 4522 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), |
|---|
| 4530 | 4523 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
|---|
| .. | .. |
|---|
| 4565 | 4558 | */ |
|---|
| 4566 | 4559 | }; |
|---|
| 4567 | 4560 | |
|---|
| 4568 | | -static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = { |
|---|
| 4561 | +static const struct snd_kcontrol_new snd_hdspm_controls_raydat[] = { |
|---|
| 4569 | 4562 | HDSPM_MIXER("Mixer", 0), |
|---|
| 4570 | 4563 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), |
|---|
| 4571 | 4564 | HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0), |
|---|
| .. | .. |
|---|
| 4593 | 4586 | HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48) |
|---|
| 4594 | 4587 | }; |
|---|
| 4595 | 4588 | |
|---|
| 4596 | | -static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { |
|---|
| 4589 | +static const struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { |
|---|
| 4597 | 4590 | HDSPM_MIXER("Mixer", 0), |
|---|
| 4598 | 4591 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), |
|---|
| 4599 | 4592 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
|---|
| .. | .. |
|---|
| 4635 | 4628 | |
|---|
| 4636 | 4629 | |
|---|
| 4637 | 4630 | /* Control elements for the optional TCO module */ |
|---|
| 4638 | | -static struct snd_kcontrol_new snd_hdspm_controls_tco[] = { |
|---|
| 4631 | +static const struct snd_kcontrol_new snd_hdspm_controls_tco[] = { |
|---|
| 4639 | 4632 | HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0), |
|---|
| 4640 | 4633 | HDSPM_TCO_PULL("TCO Pull", 0), |
|---|
| 4641 | 4634 | HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0), |
|---|
| .. | .. |
|---|
| 4682 | 4675 | unsigned int idx, limit; |
|---|
| 4683 | 4676 | int err; |
|---|
| 4684 | 4677 | struct snd_kcontrol *kctl; |
|---|
| 4685 | | - struct snd_kcontrol_new *list = NULL; |
|---|
| 4678 | + const struct snd_kcontrol_new *list = NULL; |
|---|
| 4686 | 4679 | |
|---|
| 4687 | 4680 | switch (hdspm->io_type) { |
|---|
| 4688 | 4681 | case MADI: |
|---|
| .. | .. |
|---|
| 5287 | 5280 | |
|---|
| 5288 | 5281 | static void snd_hdspm_proc_init(struct hdspm *hdspm) |
|---|
| 5289 | 5282 | { |
|---|
| 5290 | | - struct snd_info_entry *entry; |
|---|
| 5283 | + void (*read)(struct snd_info_entry *, struct snd_info_buffer *) = NULL; |
|---|
| 5291 | 5284 | |
|---|
| 5292 | | - if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) { |
|---|
| 5293 | | - switch (hdspm->io_type) { |
|---|
| 5294 | | - case AES32: |
|---|
| 5295 | | - snd_info_set_text_ops(entry, hdspm, |
|---|
| 5296 | | - snd_hdspm_proc_read_aes32); |
|---|
| 5297 | | - break; |
|---|
| 5298 | | - case MADI: |
|---|
| 5299 | | - snd_info_set_text_ops(entry, hdspm, |
|---|
| 5300 | | - snd_hdspm_proc_read_madi); |
|---|
| 5301 | | - break; |
|---|
| 5302 | | - case MADIface: |
|---|
| 5303 | | - /* snd_info_set_text_ops(entry, hdspm, |
|---|
| 5304 | | - snd_hdspm_proc_read_madiface); */ |
|---|
| 5305 | | - break; |
|---|
| 5306 | | - case RayDAT: |
|---|
| 5307 | | - snd_info_set_text_ops(entry, hdspm, |
|---|
| 5308 | | - snd_hdspm_proc_read_raydat); |
|---|
| 5309 | | - break; |
|---|
| 5310 | | - case AIO: |
|---|
| 5311 | | - break; |
|---|
| 5312 | | - } |
|---|
| 5285 | + switch (hdspm->io_type) { |
|---|
| 5286 | + case AES32: |
|---|
| 5287 | + read = snd_hdspm_proc_read_aes32; |
|---|
| 5288 | + break; |
|---|
| 5289 | + case MADI: |
|---|
| 5290 | + read = snd_hdspm_proc_read_madi; |
|---|
| 5291 | + break; |
|---|
| 5292 | + case MADIface: |
|---|
| 5293 | + /* read = snd_hdspm_proc_read_madiface; */ |
|---|
| 5294 | + break; |
|---|
| 5295 | + case RayDAT: |
|---|
| 5296 | + read = snd_hdspm_proc_read_raydat; |
|---|
| 5297 | + break; |
|---|
| 5298 | + case AIO: |
|---|
| 5299 | + break; |
|---|
| 5313 | 5300 | } |
|---|
| 5314 | 5301 | |
|---|
| 5315 | | - if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) { |
|---|
| 5316 | | - snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in); |
|---|
| 5317 | | - } |
|---|
| 5318 | | - |
|---|
| 5319 | | - if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) { |
|---|
| 5320 | | - snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out); |
|---|
| 5321 | | - } |
|---|
| 5302 | + snd_card_ro_proc_new(hdspm->card, "hdspm", hdspm, read); |
|---|
| 5303 | + snd_card_ro_proc_new(hdspm->card, "ports.in", hdspm, |
|---|
| 5304 | + snd_hdspm_proc_ports_in); |
|---|
| 5305 | + snd_card_ro_proc_new(hdspm->card, "ports.out", hdspm, |
|---|
| 5306 | + snd_hdspm_proc_ports_out); |
|---|
| 5322 | 5307 | |
|---|
| 5323 | 5308 | #ifdef CONFIG_SND_DEBUG |
|---|
| 5324 | 5309 | /* debug file to read all hdspm registers */ |
|---|
| 5325 | | - if (!snd_card_proc_new(hdspm->card, "debug", &entry)) |
|---|
| 5326 | | - snd_info_set_text_ops(entry, hdspm, |
|---|
| 5327 | | - snd_hdspm_proc_read_debug); |
|---|
| 5310 | + snd_card_ro_proc_new(hdspm->card, "debug", hdspm, |
|---|
| 5311 | + snd_hdspm_proc_read_debug); |
|---|
| 5328 | 5312 | #endif |
|---|
| 5329 | 5313 | } |
|---|
| 5330 | 5314 | |
|---|
| .. | .. |
|---|
| 5465 | 5449 | } |
|---|
| 5466 | 5450 | |
|---|
| 5467 | 5451 | if (schedule) |
|---|
| 5468 | | - tasklet_hi_schedule(&hdspm->midi_tasklet); |
|---|
| 5452 | + queue_work(system_highpri_wq, &hdspm->midi_work); |
|---|
| 5469 | 5453 | } |
|---|
| 5470 | 5454 | |
|---|
| 5471 | 5455 | return IRQ_HANDLED; |
|---|
| .. | .. |
|---|
| 5597 | 5581 | |
|---|
| 5598 | 5582 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
|---|
| 5599 | 5583 | |
|---|
| 5600 | | - hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut, |
|---|
| 5601 | | - params_channels(params)); |
|---|
| 5584 | + for (i = 0; i < params_channels(params); ++i) { |
|---|
| 5585 | + int c = hdspm->channel_map_out[i]; |
|---|
| 5602 | 5586 | |
|---|
| 5603 | | - for (i = 0; i < params_channels(params); ++i) |
|---|
| 5604 | | - snd_hdspm_enable_out(hdspm, i, 1); |
|---|
| 5587 | + if (c < 0) |
|---|
| 5588 | + continue; /* just make sure */ |
|---|
| 5589 | + hdspm_set_channel_dma_addr(hdspm, substream, |
|---|
| 5590 | + HDSPM_pageAddressBufferOut, |
|---|
| 5591 | + c); |
|---|
| 5592 | + snd_hdspm_enable_out(hdspm, c, 1); |
|---|
| 5593 | + } |
|---|
| 5605 | 5594 | |
|---|
| 5606 | 5595 | hdspm->playback_buffer = |
|---|
| 5607 | 5596 | (unsigned char *) substream->runtime->dma_area; |
|---|
| .. | .. |
|---|
| 5609 | 5598 | "Allocated sample buffer for playback at %p\n", |
|---|
| 5610 | 5599 | hdspm->playback_buffer); |
|---|
| 5611 | 5600 | } else { |
|---|
| 5612 | | - hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn, |
|---|
| 5613 | | - params_channels(params)); |
|---|
| 5601 | + for (i = 0; i < params_channels(params); ++i) { |
|---|
| 5602 | + int c = hdspm->channel_map_in[i]; |
|---|
| 5614 | 5603 | |
|---|
| 5615 | | - for (i = 0; i < params_channels(params); ++i) |
|---|
| 5616 | | - snd_hdspm_enable_in(hdspm, i, 1); |
|---|
| 5604 | + if (c < 0) |
|---|
| 5605 | + continue; |
|---|
| 5606 | + hdspm_set_channel_dma_addr(hdspm, substream, |
|---|
| 5607 | + HDSPM_pageAddressBufferIn, |
|---|
| 5608 | + c); |
|---|
| 5609 | + snd_hdspm_enable_in(hdspm, c, 1); |
|---|
| 5610 | + } |
|---|
| 5617 | 5611 | |
|---|
| 5618 | 5612 | hdspm->capture_buffer = |
|---|
| 5619 | 5613 | (unsigned char *) substream->runtime->dma_area; |
|---|
| .. | .. |
|---|
| 5674 | 5668 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); |
|---|
| 5675 | 5669 | |
|---|
| 5676 | 5670 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
|---|
| 5677 | | - |
|---|
| 5678 | | - /* params_channels(params) should be enough, |
|---|
| 5679 | | - but to get sure in case of error */ |
|---|
| 5680 | | - for (i = 0; i < hdspm->max_channels_out; ++i) |
|---|
| 5671 | + /* Just disable all channels. The saving when disabling a */ |
|---|
| 5672 | + /* smaller set is not worth the trouble. */ |
|---|
| 5673 | + for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) |
|---|
| 5681 | 5674 | snd_hdspm_enable_out(hdspm, i, 0); |
|---|
| 5682 | 5675 | |
|---|
| 5683 | 5676 | hdspm->playback_buffer = NULL; |
|---|
| 5684 | 5677 | } else { |
|---|
| 5685 | | - for (i = 0; i < hdspm->max_channels_in; ++i) |
|---|
| 5678 | + for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) |
|---|
| 5686 | 5679 | snd_hdspm_enable_in(hdspm, i, 0); |
|---|
| 5687 | 5680 | |
|---|
| 5688 | 5681 | hdspm->capture_buffer = NULL; |
|---|
| 5689 | | - |
|---|
| 5690 | 5682 | } |
|---|
| 5691 | 5683 | |
|---|
| 5692 | 5684 | snd_pcm_lib_free_pages(substream); |
|---|
| .. | .. |
|---|
| 5832 | 5824 | return 0; |
|---|
| 5833 | 5825 | } |
|---|
| 5834 | 5826 | |
|---|
| 5835 | | -static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { |
|---|
| 5827 | +static const struct snd_pcm_hardware snd_hdspm_playback_subinfo = { |
|---|
| 5836 | 5828 | .info = (SNDRV_PCM_INFO_MMAP | |
|---|
| 5837 | 5829 | SNDRV_PCM_INFO_MMAP_VALID | |
|---|
| 5838 | 5830 | SNDRV_PCM_INFO_NONINTERLEAVED | |
|---|
| .. | .. |
|---|
| 5857 | 5849 | .fifo_size = 0 |
|---|
| 5858 | 5850 | }; |
|---|
| 5859 | 5851 | |
|---|
| 5860 | | -static struct snd_pcm_hardware snd_hdspm_capture_subinfo = { |
|---|
| 5852 | +static const struct snd_pcm_hardware snd_hdspm_capture_subinfo = { |
|---|
| 5861 | 5853 | .info = (SNDRV_PCM_INFO_MMAP | |
|---|
| 5862 | 5854 | SNDRV_PCM_INFO_MMAP_VALID | |
|---|
| 5863 | 5855 | SNDRV_PCM_INFO_NONINTERLEAVED | |
|---|
| .. | .. |
|---|
| 6380 | 6372 | .prepare = snd_hdspm_prepare, |
|---|
| 6381 | 6373 | .trigger = snd_hdspm_trigger, |
|---|
| 6382 | 6374 | .pointer = snd_hdspm_hw_pointer, |
|---|
| 6383 | | - .page = snd_pcm_sgbuf_ops_page, |
|---|
| 6384 | 6375 | }; |
|---|
| 6385 | 6376 | |
|---|
| 6386 | 6377 | static int snd_hdspm_create_hwdep(struct snd_card *card, |
|---|
| .. | .. |
|---|
| 6411 | 6402 | ------------------------------------------------------------*/ |
|---|
| 6412 | 6403 | static int snd_hdspm_preallocate_memory(struct hdspm *hdspm) |
|---|
| 6413 | 6404 | { |
|---|
| 6414 | | - int err; |
|---|
| 6415 | 6405 | struct snd_pcm *pcm; |
|---|
| 6416 | 6406 | size_t wanted; |
|---|
| 6417 | 6407 | |
|---|
| .. | .. |
|---|
| 6419 | 6409 | |
|---|
| 6420 | 6410 | wanted = HDSPM_DMA_AREA_BYTES; |
|---|
| 6421 | 6411 | |
|---|
| 6422 | | - err = |
|---|
| 6423 | | - snd_pcm_lib_preallocate_pages_for_all(pcm, |
|---|
| 6424 | | - SNDRV_DMA_TYPE_DEV_SG, |
|---|
| 6425 | | - snd_dma_pci_data(hdspm->pci), |
|---|
| 6426 | | - wanted, |
|---|
| 6427 | | - wanted); |
|---|
| 6428 | | - if (err < 0) { |
|---|
| 6429 | | - dev_dbg(hdspm->card->dev, |
|---|
| 6430 | | - "Could not preallocate %zd Bytes\n", wanted); |
|---|
| 6431 | | - |
|---|
| 6432 | | - return err; |
|---|
| 6433 | | - } else |
|---|
| 6434 | | - dev_dbg(hdspm->card->dev, |
|---|
| 6435 | | - " Preallocated %zd Bytes\n", wanted); |
|---|
| 6436 | | - |
|---|
| 6412 | + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
|---|
| 6413 | + &hdspm->pci->dev, |
|---|
| 6414 | + wanted, wanted); |
|---|
| 6415 | + dev_dbg(hdspm->card->dev, " Preallocated %zd Bytes\n", wanted); |
|---|
| 6437 | 6416 | return 0; |
|---|
| 6438 | 6417 | } |
|---|
| 6439 | 6418 | |
|---|
| 6440 | | - |
|---|
| 6441 | | -static void hdspm_set_sgbuf(struct hdspm *hdspm, |
|---|
| 6442 | | - struct snd_pcm_substream *substream, |
|---|
| 6443 | | - unsigned int reg, int channels) |
|---|
| 6419 | +/* Inform the card what DMA addresses to use for the indicated channel. */ |
|---|
| 6420 | +/* Each channel got 16 4K pages allocated for DMA transfers. */ |
|---|
| 6421 | +static void hdspm_set_channel_dma_addr(struct hdspm *hdspm, |
|---|
| 6422 | + struct snd_pcm_substream *substream, |
|---|
| 6423 | + unsigned int reg, int channel) |
|---|
| 6444 | 6424 | { |
|---|
| 6445 | 6425 | int i; |
|---|
| 6446 | 6426 | |
|---|
| 6447 | | - /* continuous memory segment */ |
|---|
| 6448 | | - for (i = 0; i < (channels * 16); i++) |
|---|
| 6427 | + for (i = channel * 16; i < channel * 16 + 16; i++) |
|---|
| 6449 | 6428 | hdspm_write(hdspm, reg + 4 * i, |
|---|
| 6450 | | - snd_pcm_sgbuf_get_addr(substream, 4096 * i)); |
|---|
| 6429 | + snd_pcm_sgbuf_get_addr(substream, 4096 * i)); |
|---|
| 6451 | 6430 | } |
|---|
| 6452 | 6431 | |
|---|
| 6453 | 6432 | |
|---|
| .. | .. |
|---|
| 6534 | 6513 | dev_dbg(card->dev, "Update mixer controls...\n"); |
|---|
| 6535 | 6514 | hdspm_update_simple_mixer_controls(hdspm); |
|---|
| 6536 | 6515 | |
|---|
| 6537 | | - dev_dbg(card->dev, "Initializeing complete ???\n"); |
|---|
| 6516 | + dev_dbg(card->dev, "Initializing complete?\n"); |
|---|
| 6538 | 6517 | |
|---|
| 6539 | 6518 | err = snd_card_register(card); |
|---|
| 6540 | 6519 | if (err < 0) { |
|---|
| .. | .. |
|---|
| 6559 | 6538 | hdspm->card = card; |
|---|
| 6560 | 6539 | |
|---|
| 6561 | 6540 | spin_lock_init(&hdspm->lock); |
|---|
| 6541 | + INIT_WORK(&hdspm->midi_work, hdspm_midi_work); |
|---|
| 6562 | 6542 | |
|---|
| 6563 | 6543 | pci_read_config_word(hdspm->pci, |
|---|
| 6564 | 6544 | PCI_CLASS_REVISION, &hdspm->firmware_rev); |
|---|
| .. | .. |
|---|
| 6619 | 6599 | dev_dbg(card->dev, "grabbed memory region 0x%lx-0x%lx\n", |
|---|
| 6620 | 6600 | hdspm->port, hdspm->port + io_extent - 1); |
|---|
| 6621 | 6601 | |
|---|
| 6622 | | - hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); |
|---|
| 6602 | + hdspm->iobase = ioremap(hdspm->port, io_extent); |
|---|
| 6623 | 6603 | if (!hdspm->iobase) { |
|---|
| 6624 | 6604 | dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n", |
|---|
| 6625 | 6605 | hdspm->port, hdspm->port + io_extent - 1); |
|---|
| .. | .. |
|---|
| 6638 | 6618 | dev_dbg(card->dev, "use IRQ %d\n", pci->irq); |
|---|
| 6639 | 6619 | |
|---|
| 6640 | 6620 | hdspm->irq = pci->irq; |
|---|
| 6621 | + card->sync_irq = hdspm->irq; |
|---|
| 6641 | 6622 | |
|---|
| 6642 | 6623 | dev_dbg(card->dev, "kmalloc Mixer memory of %zd Bytes\n", |
|---|
| 6643 | 6624 | sizeof(*hdspm->mixer)); |
|---|
| .. | .. |
|---|
| 6856 | 6837 | |
|---|
| 6857 | 6838 | } |
|---|
| 6858 | 6839 | |
|---|
| 6859 | | - tasklet_init(&hdspm->midi_tasklet, |
|---|
| 6860 | | - hdspm_midi_tasklet, (unsigned long) hdspm); |
|---|
| 6861 | | - |
|---|
| 6862 | | - |
|---|
| 6863 | 6840 | if (hdspm->io_type != MADIface) { |
|---|
| 6864 | 6841 | hdspm->serial = (hdspm_read(hdspm, |
|---|
| 6865 | 6842 | HDSPM_midiStatusIn0)>>8) & 0xFFFFFF; |
|---|
| .. | .. |
|---|
| 6894 | 6871 | { |
|---|
| 6895 | 6872 | |
|---|
| 6896 | 6873 | if (hdspm->port) { |
|---|
| 6874 | + cancel_work_sync(&hdspm->midi_work); |
|---|
| 6897 | 6875 | |
|---|
| 6898 | 6876 | /* stop th audio, and cancel all interrupts */ |
|---|
| 6899 | 6877 | hdspm->control_register &= |
|---|