| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Maintained by Jaroslav Kysela <perex@perex.cz> |
|---|
| 3 | 4 | * Originated by audio@tridentmicro.com |
|---|
| .. | .. |
|---|
| 8 | 9 | * |
|---|
| 9 | 10 | * TODO: |
|---|
| 10 | 11 | * --- |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 13 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 14 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 15 | | - * (at your option) any later version. |
|---|
| 16 | | - * |
|---|
| 17 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 18 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 19 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 20 | | - * GNU General Public License for more details. |
|---|
| 21 | | - * |
|---|
| 22 | | - * You should have received a copy of the GNU General Public License |
|---|
| 23 | | - * along with this program; if not, write to the Free Software |
|---|
| 24 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 25 | | - * |
|---|
| 26 | 12 | * |
|---|
| 27 | 13 | * SiS7018 S/PDIF support by Thomas Winischhofer <thomas@winischhofer.net> |
|---|
| 28 | 14 | */ |
|---|
| .. | .. |
|---|
| 782 | 768 | */ |
|---|
| 783 | 769 | |
|---|
| 784 | 770 | /*--------------------------------------------------------------------------- |
|---|
| 785 | | - snd_trident_ioctl |
|---|
| 786 | | - |
|---|
| 787 | | - Description: Device I/O control handler for playback/capture parameters. |
|---|
| 788 | | - |
|---|
| 789 | | - Parameters: substream - PCM substream class |
|---|
| 790 | | - cmd - what ioctl message to process |
|---|
| 791 | | - arg - additional message infoarg |
|---|
| 792 | | - |
|---|
| 793 | | - Returns: Error status |
|---|
| 794 | | - |
|---|
| 795 | | - ---------------------------------------------------------------------------*/ |
|---|
| 796 | | - |
|---|
| 797 | | -static int snd_trident_ioctl(struct snd_pcm_substream *substream, |
|---|
| 798 | | - unsigned int cmd, |
|---|
| 799 | | - void *arg) |
|---|
| 800 | | -{ |
|---|
| 801 | | - /* FIXME: it seems that with small periods the behaviour of |
|---|
| 802 | | - trident hardware is unpredictable and interrupt generator |
|---|
| 803 | | - is broken */ |
|---|
| 804 | | - return snd_pcm_lib_ioctl(substream, cmd, arg); |
|---|
| 805 | | -} |
|---|
| 806 | | - |
|---|
| 807 | | -/*--------------------------------------------------------------------------- |
|---|
| 808 | 771 | snd_trident_allocate_pcm_mem |
|---|
| 809 | 772 | |
|---|
| 810 | 773 | Description: Allocate PCM ring buffer for given substream |
|---|
| .. | .. |
|---|
| 822 | 785 | struct snd_trident *trident = snd_pcm_substream_chip(substream); |
|---|
| 823 | 786 | struct snd_pcm_runtime *runtime = substream->runtime; |
|---|
| 824 | 787 | struct snd_trident_voice *voice = runtime->private_data; |
|---|
| 825 | | - int err; |
|---|
| 826 | 788 | |
|---|
| 827 | | - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) |
|---|
| 828 | | - return err; |
|---|
| 829 | 789 | if (trident->tlb.entries) { |
|---|
| 830 | | - if (err > 0) { /* change */ |
|---|
| 790 | + if (runtime->buffer_changed) { |
|---|
| 831 | 791 | if (voice->memblk) |
|---|
| 832 | 792 | snd_trident_free_pages(trident, voice->memblk); |
|---|
| 833 | 793 | voice->memblk = snd_trident_alloc_pages(trident, substream); |
|---|
| .. | .. |
|---|
| 925 | 885 | voice->memblk = NULL; |
|---|
| 926 | 886 | } |
|---|
| 927 | 887 | } |
|---|
| 928 | | - snd_pcm_lib_free_pages(substream); |
|---|
| 929 | 888 | if (evoice != NULL) { |
|---|
| 930 | 889 | snd_trident_free_voice(trident, evoice); |
|---|
| 931 | 890 | voice->extra = NULL; |
|---|
| .. | .. |
|---|
| 1142 | 1101 | static int snd_trident_si7018_capture_hw_params(struct snd_pcm_substream *substream, |
|---|
| 1143 | 1102 | struct snd_pcm_hw_params *hw_params) |
|---|
| 1144 | 1103 | { |
|---|
| 1145 | | - int err; |
|---|
| 1146 | | - |
|---|
| 1147 | | - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) |
|---|
| 1148 | | - return err; |
|---|
| 1149 | | - |
|---|
| 1150 | 1104 | return snd_trident_allocate_evoice(substream, hw_params); |
|---|
| 1151 | 1105 | } |
|---|
| 1152 | 1106 | |
|---|
| .. | .. |
|---|
| 1168 | 1122 | struct snd_trident_voice *voice = runtime->private_data; |
|---|
| 1169 | 1123 | struct snd_trident_voice *evoice = voice ? voice->extra : NULL; |
|---|
| 1170 | 1124 | |
|---|
| 1171 | | - snd_pcm_lib_free_pages(substream); |
|---|
| 1172 | 1125 | if (evoice != NULL) { |
|---|
| 1173 | 1126 | snd_trident_free_voice(trident, evoice); |
|---|
| 1174 | 1127 | voice->extra = NULL; |
|---|
| .. | .. |
|---|
| 2073 | 2026 | static const struct snd_pcm_ops snd_trident_playback_ops = { |
|---|
| 2074 | 2027 | .open = snd_trident_playback_open, |
|---|
| 2075 | 2028 | .close = snd_trident_playback_close, |
|---|
| 2076 | | - .ioctl = snd_trident_ioctl, |
|---|
| 2077 | 2029 | .hw_params = snd_trident_hw_params, |
|---|
| 2078 | 2030 | .hw_free = snd_trident_hw_free, |
|---|
| 2079 | 2031 | .prepare = snd_trident_playback_prepare, |
|---|
| .. | .. |
|---|
| 2084 | 2036 | static const struct snd_pcm_ops snd_trident_nx_playback_ops = { |
|---|
| 2085 | 2037 | .open = snd_trident_playback_open, |
|---|
| 2086 | 2038 | .close = snd_trident_playback_close, |
|---|
| 2087 | | - .ioctl = snd_trident_ioctl, |
|---|
| 2088 | 2039 | .hw_params = snd_trident_hw_params, |
|---|
| 2089 | 2040 | .hw_free = snd_trident_hw_free, |
|---|
| 2090 | 2041 | .prepare = snd_trident_playback_prepare, |
|---|
| 2091 | 2042 | .trigger = snd_trident_trigger, |
|---|
| 2092 | 2043 | .pointer = snd_trident_playback_pointer, |
|---|
| 2093 | | - .page = snd_pcm_sgbuf_ops_page, |
|---|
| 2094 | 2044 | }; |
|---|
| 2095 | 2045 | |
|---|
| 2096 | 2046 | static const struct snd_pcm_ops snd_trident_capture_ops = { |
|---|
| 2097 | 2047 | .open = snd_trident_capture_open, |
|---|
| 2098 | 2048 | .close = snd_trident_capture_close, |
|---|
| 2099 | | - .ioctl = snd_trident_ioctl, |
|---|
| 2100 | 2049 | .hw_params = snd_trident_capture_hw_params, |
|---|
| 2101 | 2050 | .hw_free = snd_trident_hw_free, |
|---|
| 2102 | 2051 | .prepare = snd_trident_capture_prepare, |
|---|
| .. | .. |
|---|
| 2107 | 2056 | static const struct snd_pcm_ops snd_trident_si7018_capture_ops = { |
|---|
| 2108 | 2057 | .open = snd_trident_capture_open, |
|---|
| 2109 | 2058 | .close = snd_trident_capture_close, |
|---|
| 2110 | | - .ioctl = snd_trident_ioctl, |
|---|
| 2111 | 2059 | .hw_params = snd_trident_si7018_capture_hw_params, |
|---|
| 2112 | 2060 | .hw_free = snd_trident_si7018_capture_hw_free, |
|---|
| 2113 | 2061 | .prepare = snd_trident_si7018_capture_prepare, |
|---|
| .. | .. |
|---|
| 2118 | 2066 | static const struct snd_pcm_ops snd_trident_foldback_ops = { |
|---|
| 2119 | 2067 | .open = snd_trident_foldback_open, |
|---|
| 2120 | 2068 | .close = snd_trident_foldback_close, |
|---|
| 2121 | | - .ioctl = snd_trident_ioctl, |
|---|
| 2122 | 2069 | .hw_params = snd_trident_hw_params, |
|---|
| 2123 | 2070 | .hw_free = snd_trident_hw_free, |
|---|
| 2124 | 2071 | .prepare = snd_trident_foldback_prepare, |
|---|
| .. | .. |
|---|
| 2129 | 2076 | static const struct snd_pcm_ops snd_trident_nx_foldback_ops = { |
|---|
| 2130 | 2077 | .open = snd_trident_foldback_open, |
|---|
| 2131 | 2078 | .close = snd_trident_foldback_close, |
|---|
| 2132 | | - .ioctl = snd_trident_ioctl, |
|---|
| 2133 | 2079 | .hw_params = snd_trident_hw_params, |
|---|
| 2134 | 2080 | .hw_free = snd_trident_hw_free, |
|---|
| 2135 | 2081 | .prepare = snd_trident_foldback_prepare, |
|---|
| 2136 | 2082 | .trigger = snd_trident_trigger, |
|---|
| 2137 | 2083 | .pointer = snd_trident_playback_pointer, |
|---|
| 2138 | | - .page = snd_pcm_sgbuf_ops_page, |
|---|
| 2139 | 2084 | }; |
|---|
| 2140 | 2085 | |
|---|
| 2141 | 2086 | static const struct snd_pcm_ops snd_trident_spdif_ops = { |
|---|
| 2142 | 2087 | .open = snd_trident_spdif_open, |
|---|
| 2143 | 2088 | .close = snd_trident_spdif_close, |
|---|
| 2144 | | - .ioctl = snd_trident_ioctl, |
|---|
| 2145 | 2089 | .hw_params = snd_trident_spdif_hw_params, |
|---|
| 2146 | 2090 | .hw_free = snd_trident_hw_free, |
|---|
| 2147 | 2091 | .prepare = snd_trident_spdif_prepare, |
|---|
| .. | .. |
|---|
| 2152 | 2096 | static const struct snd_pcm_ops snd_trident_spdif_7018_ops = { |
|---|
| 2153 | 2097 | .open = snd_trident_spdif_open, |
|---|
| 2154 | 2098 | .close = snd_trident_spdif_close, |
|---|
| 2155 | | - .ioctl = snd_trident_ioctl, |
|---|
| 2156 | 2099 | .hw_params = snd_trident_spdif_hw_params, |
|---|
| 2157 | 2100 | .hw_free = snd_trident_hw_free, |
|---|
| 2158 | 2101 | .prepare = snd_trident_spdif_prepare, |
|---|
| .. | .. |
|---|
| 2199 | 2142 | if (trident->tlb.entries) { |
|---|
| 2200 | 2143 | struct snd_pcm_substream *substream; |
|---|
| 2201 | 2144 | for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) |
|---|
| 2202 | | - snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, |
|---|
| 2203 | | - snd_dma_pci_data(trident->pci), |
|---|
| 2204 | | - 64*1024, 128*1024); |
|---|
| 2205 | | - snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, |
|---|
| 2206 | | - SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), |
|---|
| 2207 | | - 64*1024, 128*1024); |
|---|
| 2145 | + snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV_SG, |
|---|
| 2146 | + &trident->pci->dev, |
|---|
| 2147 | + 64*1024, 128*1024); |
|---|
| 2148 | + snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, |
|---|
| 2149 | + SNDRV_DMA_TYPE_DEV, |
|---|
| 2150 | + &trident->pci->dev, |
|---|
| 2151 | + 64*1024, 128*1024); |
|---|
| 2208 | 2152 | } else { |
|---|
| 2209 | | - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
|---|
| 2210 | | - snd_dma_pci_data(trident->pci), 64*1024, 128*1024); |
|---|
| 2153 | + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, |
|---|
| 2154 | + &trident->pci->dev, |
|---|
| 2155 | + 64*1024, 128*1024); |
|---|
| 2211 | 2156 | } |
|---|
| 2212 | 2157 | |
|---|
| 2213 | 2158 | return 0; |
|---|
| .. | .. |
|---|
| 2256 | 2201 | trident->foldback = foldback; |
|---|
| 2257 | 2202 | |
|---|
| 2258 | 2203 | if (trident->tlb.entries) |
|---|
| 2259 | | - snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV_SG, |
|---|
| 2260 | | - snd_dma_pci_data(trident->pci), 0, 128*1024); |
|---|
| 2204 | + snd_pcm_set_managed_buffer_all(foldback, SNDRV_DMA_TYPE_DEV_SG, |
|---|
| 2205 | + &trident->pci->dev, |
|---|
| 2206 | + 0, 128*1024); |
|---|
| 2261 | 2207 | else |
|---|
| 2262 | | - snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV, |
|---|
| 2263 | | - snd_dma_pci_data(trident->pci), 64*1024, 128*1024); |
|---|
| 2208 | + snd_pcm_set_managed_buffer_all(foldback, SNDRV_DMA_TYPE_DEV, |
|---|
| 2209 | + &trident->pci->dev, |
|---|
| 2210 | + 64*1024, 128*1024); |
|---|
| 2264 | 2211 | |
|---|
| 2265 | 2212 | return 0; |
|---|
| 2266 | 2213 | } |
|---|
| .. | .. |
|---|
| 2294 | 2241 | strcpy(spdif->name, "Trident 4DWave IEC958"); |
|---|
| 2295 | 2242 | trident->spdif = spdif; |
|---|
| 2296 | 2243 | |
|---|
| 2297 | | - snd_pcm_lib_preallocate_pages_for_all(spdif, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), 64*1024, 128*1024); |
|---|
| 2244 | + snd_pcm_set_managed_buffer_all(spdif, SNDRV_DMA_TYPE_DEV, |
|---|
| 2245 | + &trident->pci->dev, 64*1024, 128*1024); |
|---|
| 2298 | 2246 | |
|---|
| 2299 | 2247 | return 0; |
|---|
| 2300 | 2248 | } |
|---|
| .. | .. |
|---|
| 2964 | 2912 | struct snd_kcontrol *kctl; |
|---|
| 2965 | 2913 | struct snd_ctl_elem_value *uctl; |
|---|
| 2966 | 2914 | int idx, err, retries = 2; |
|---|
| 2967 | | - static struct snd_ac97_bus_ops ops = { |
|---|
| 2915 | + static const struct snd_ac97_bus_ops ops = { |
|---|
| 2968 | 2916 | .write = snd_trident_codec_write, |
|---|
| 2969 | 2917 | .read = snd_trident_codec_read, |
|---|
| 2970 | 2918 | }; |
|---|
| .. | .. |
|---|
| 3320 | 3268 | |
|---|
| 3321 | 3269 | static void snd_trident_proc_init(struct snd_trident *trident) |
|---|
| 3322 | 3270 | { |
|---|
| 3323 | | - struct snd_info_entry *entry; |
|---|
| 3324 | 3271 | const char *s = "trident"; |
|---|
| 3325 | 3272 | |
|---|
| 3326 | 3273 | if (trident->device == TRIDENT_DEVICE_ID_SI7018) |
|---|
| 3327 | 3274 | s = "sis7018"; |
|---|
| 3328 | | - if (! snd_card_proc_new(trident->card, s, &entry)) |
|---|
| 3329 | | - snd_info_set_text_ops(entry, trident, snd_trident_proc_read); |
|---|
| 3275 | + snd_card_ro_proc_new(trident->card, s, trident, snd_trident_proc_read); |
|---|
| 3330 | 3276 | } |
|---|
| 3331 | 3277 | |
|---|
| 3332 | 3278 | static int snd_trident_dev_free(struct snd_device *device) |
|---|
| .. | .. |
|---|
| 3354 | 3300 | /* TLB array must be aligned to 16kB !!! so we allocate |
|---|
| 3355 | 3301 | 32kB region and correct offset when necessary */ |
|---|
| 3356 | 3302 | |
|---|
| 3357 | | - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), |
|---|
| 3303 | + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev, |
|---|
| 3358 | 3304 | 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) { |
|---|
| 3359 | 3305 | dev_err(trident->card->dev, "unable to allocate TLB buffer\n"); |
|---|
| 3360 | 3306 | return -ENOMEM; |
|---|
| .. | .. |
|---|
| 3369 | 3315 | return -ENOMEM; |
|---|
| 3370 | 3316 | |
|---|
| 3371 | 3317 | /* allocate and setup silent page and initialise TLB entries */ |
|---|
| 3372 | | - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), |
|---|
| 3318 | + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev, |
|---|
| 3373 | 3319 | SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) { |
|---|
| 3374 | 3320 | dev_err(trident->card->dev, "unable to allocate silent page\n"); |
|---|
| 3375 | 3321 | return -ENOMEM; |
|---|
| .. | .. |
|---|
| 3541 | 3487 | int i, err; |
|---|
| 3542 | 3488 | struct snd_trident_voice *voice; |
|---|
| 3543 | 3489 | struct snd_trident_pcm_mixer *tmix; |
|---|
| 3544 | | - static struct snd_device_ops ops = { |
|---|
| 3490 | + static const struct snd_device_ops ops = { |
|---|
| 3545 | 3491 | .dev_free = snd_trident_dev_free, |
|---|
| 3546 | 3492 | }; |
|---|
| 3547 | 3493 | |
|---|
| .. | .. |
|---|
| 3597 | 3543 | return -EBUSY; |
|---|
| 3598 | 3544 | } |
|---|
| 3599 | 3545 | trident->irq = pci->irq; |
|---|
| 3546 | + card->sync_irq = trident->irq; |
|---|
| 3600 | 3547 | |
|---|
| 3601 | 3548 | /* allocate 16k-aligned TLB for NX cards */ |
|---|
| 3602 | 3549 | trident->tlb.entries = NULL; |
|---|
| .. | .. |
|---|
| 3915 | 3862 | |
|---|
| 3916 | 3863 | trident->in_suspend = 1; |
|---|
| 3917 | 3864 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
|---|
| 3918 | | - snd_pcm_suspend_all(trident->pcm); |
|---|
| 3919 | | - snd_pcm_suspend_all(trident->foldback); |
|---|
| 3920 | | - snd_pcm_suspend_all(trident->spdif); |
|---|
| 3921 | | - |
|---|
| 3922 | 3865 | snd_ac97_suspend(trident->ac97); |
|---|
| 3923 | 3866 | snd_ac97_suspend(trident->ac97_sec); |
|---|
| 3924 | 3867 | return 0; |
|---|