From cf4ce59b3b70238352c7f1729f0f7223214828ad Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 20 Sep 2024 01:46:19 +0000 Subject: [PATCH] rtl88x2CE_WiFi_linux add concurrent mode --- kernel/sound/pci/rme9652/hdspm.c | 258 +++++++++++++++++++++++---------------------------- 1 files changed, 118 insertions(+), 140 deletions(-) diff --git a/kernel/sound/pci/rme9652/hdspm.c b/kernel/sound/pci/rme9652/hdspm.c index 5dfddad..51c3c6a 100644 --- a/kernel/sound/pci/rme9652/hdspm.c +++ b/kernel/sound/pci/rme9652/hdspm.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * ALSA driver for RME Hammerfall DSP MADI audio interface(s) * @@ -23,20 +24,8 @@ * * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * Modified 2019-05-23 fix AIO single speed ADAT capture and playback + * by Philippe.Bekaert@uhasselt.be */ /* ************* Register Documentation ******************************************************* @@ -648,7 +637,7 @@ #define HDSPM_SPEED_QUAD 2 /* names for speed modes */ -static char *hdspm_speed_names[] = { "single", "double", "quad" }; +static const char * const hdspm_speed_names[] = { "single", "double", "quad" }; static const char *const texts_autosync_aes_tco[] = { "Word Clock", "AES1", "AES2", "AES3", "AES4", @@ -695,7 +684,7 @@ "192 kHz" }; -static char *texts_ports_madi[] = { +static const char * const texts_ports_madi[] = { "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6", "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12", "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18", @@ -710,7 +699,7 @@ }; -static char *texts_ports_raydat_ss[] = { +static const char * const texts_ports_raydat_ss[] = { "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6", "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4", "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2", @@ -721,7 +710,7 @@ "SPDIF.L", "SPDIF.R" }; -static char *texts_ports_raydat_ds[] = { +static const char * const texts_ports_raydat_ds[] = { "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4", "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4", @@ -730,7 +719,7 @@ "SPDIF.L", "SPDIF.R" }; -static char *texts_ports_raydat_qs[] = { +static const char * const texts_ports_raydat_qs[] = { "ADAT1.1", "ADAT1.2", "ADAT2.1", "ADAT2.2", "ADAT3.1", "ADAT3.2", @@ -740,7 +729,7 @@ }; -static char *texts_ports_aio_in_ss[] = { +static const char * const texts_ports_aio_in_ss[] = { "Analogue.L", "Analogue.R", "AES.L", "AES.R", "SPDIF.L", "SPDIF.R", @@ -749,7 +738,7 @@ "AEB.1", "AEB.2", "AEB.3", "AEB.4" }; -static char *texts_ports_aio_out_ss[] = { +static const char * const texts_ports_aio_out_ss[] = { "Analogue.L", "Analogue.R", "AES.L", "AES.R", "SPDIF.L", "SPDIF.R", @@ -759,7 +748,7 @@ "AEB.1", "AEB.2", "AEB.3", "AEB.4" }; -static char *texts_ports_aio_in_ds[] = { +static const char * const texts_ports_aio_in_ds[] = { "Analogue.L", "Analogue.R", "AES.L", "AES.R", "SPDIF.L", "SPDIF.R", @@ -767,7 +756,7 @@ "AEB.1", "AEB.2", "AEB.3", "AEB.4" }; -static char *texts_ports_aio_out_ds[] = { +static const char * const texts_ports_aio_out_ds[] = { "Analogue.L", "Analogue.R", "AES.L", "AES.R", "SPDIF.L", "SPDIF.R", @@ -776,7 +765,7 @@ "AEB.1", "AEB.2", "AEB.3", "AEB.4" }; -static char *texts_ports_aio_in_qs[] = { +static const char * const texts_ports_aio_in_qs[] = { "Analogue.L", "Analogue.R", "AES.L", "AES.R", "SPDIF.L", "SPDIF.R", @@ -784,7 +773,7 @@ "AEB.1", "AEB.2", "AEB.3", "AEB.4" }; -static char *texts_ports_aio_out_qs[] = { +static const char * const texts_ports_aio_out_qs[] = { "Analogue.L", "Analogue.R", "AES.L", "AES.R", "SPDIF.L", "SPDIF.R", @@ -793,7 +782,7 @@ "AEB.1", "AEB.2", "AEB.3", "AEB.4" }; -static char *texts_ports_aes32[] = { +static const char * const texts_ports_aes32[] = { "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7", "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14", "AES.15", "AES.16" @@ -807,7 +796,7 @@ where the data for that channel can be read/written from/to. */ -static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = { +static const char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, @@ -818,7 +807,7 @@ 56, 57, 58, 59, 60, 61, 62, 63 }; -static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = { +static const char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = { 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */ 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */ 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */ @@ -831,7 +820,7 @@ -1, -1, -1, -1, -1, -1, -1, -1, }; -static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = { +static const char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = { 4, 5, 6, 7, /* ADAT 1 */ 8, 9, 10, 11, /* ADAT 2 */ 12, 13, 14, 15, /* ADAT 3 */ @@ -846,7 +835,7 @@ -1, -1, -1, -1, -1, -1, -1, -1, }; -static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = { +static const char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = { 4, 5, /* ADAT 1 */ 6, 7, /* ADAT 2 */ 8, 9, /* ADAT 3 */ @@ -862,7 +851,7 @@ -1, -1, -1, -1, -1, -1, -1, -1, }; -static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = { +static const char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = { 0, 1, /* line in */ 8, 9, /* aes in, */ 10, 11, /* spdif in */ @@ -876,7 +865,7 @@ -1, -1, -1, -1, -1, -1, -1, -1, }; -static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = { +static const char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = { 0, 1, /* line out */ 8, 9, /* aes out */ 10, 11, /* spdif out */ @@ -891,7 +880,7 @@ -1, -1, -1, -1, -1, -1, -1, -1, }; -static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = { +static const char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = { 0, 1, /* line in */ 8, 9, /* aes in */ 10, 11, /* spdif in */ @@ -906,7 +895,7 @@ -1, -1, -1, -1, -1, -1, -1, -1 }; -static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = { +static const char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = { 0, 1, /* line out */ 8, 9, /* aes out */ 10, 11, /* spdif out */ @@ -921,7 +910,7 @@ -1, -1, -1, -1, -1, -1, -1, -1 }; -static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = { +static const char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = { 0, 1, /* line in */ 8, 9, /* aes in */ 10, 11, /* spdif in */ @@ -936,7 +925,7 @@ -1, -1, -1, -1, -1, -1, -1, -1 }; -static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = { +static const char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = { 0, 1, /* line out */ 8, 9, /* aes out */ 10, 11, /* spdif out */ @@ -952,7 +941,7 @@ -1, -1, -1, -1, -1, -1, -1, -1 }; -static char channel_map_aes32[HDSPM_MAX_CHANNELS] = { +static const char channel_map_aes32[HDSPM_MAX_CHANNELS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, @@ -1008,7 +997,7 @@ u32 settings_register; /* cached value for AIO / RayDat (sync reference, master/slave) */ struct hdspm_midi midi[4]; - struct tasklet_struct midi_tasklet; + struct work_struct midi_work; size_t period_bytes; unsigned char ss_in_channels; @@ -1021,17 +1010,21 @@ unsigned char max_channels_in; unsigned char max_channels_out; - signed char *channel_map_in; - signed char *channel_map_out; + const signed char *channel_map_in; + const signed char *channel_map_out; - signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; - signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; + const signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; + const signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; - char **port_names_in; - char **port_names_out; + const char * const *port_names_in; + const char * const *port_names_out; - char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs; - char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs; + const char * const *port_names_in_ss; + const char * const *port_names_in_ds; + const char * const *port_names_in_qs; + const char * const *port_names_out_ss; + const char * const *port_names_out_ds; + const char * const *port_names_out_qs; unsigned char *playback_buffer; /* suitably aligned address */ unsigned char *capture_buffer; /* suitably aligned address */ @@ -1105,9 +1098,9 @@ static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out); static int snd_hdspm_set_defaults(struct hdspm *hdspm); static int hdspm_system_clock_mode(struct hdspm *hdspm); -static void hdspm_set_sgbuf(struct hdspm *hdspm, - struct snd_pcm_substream *substream, - unsigned int reg, int channels); +static void hdspm_set_channel_dma_addr(struct hdspm *hdspm, + struct snd_pcm_substream *substream, + unsigned int reg, int channels); static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx); static int hdspm_wc_sync_check(struct hdspm *hdspm); @@ -1224,7 +1217,7 @@ return ret; } -/* round arbitary sample rates to commonly known rates */ +/* round arbitrary sample rates to commonly known rates */ static int hdspm_round_frequency(int rate) { if (rate < 38050) @@ -2176,9 +2169,9 @@ } -static void hdspm_midi_tasklet(unsigned long arg) +static void hdspm_midi_work(struct work_struct *work) { - struct hdspm *hdspm = (struct hdspm *)arg; + struct hdspm *hdspm = container_of(work, struct hdspm, midi_work); int i = 0; while (i < hdspm->midiPorts) { @@ -3034,8 +3027,8 @@ unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF; - if ((syncref >= HDSPM_AES32_AUTOSYNC_FROM_WORD) && - (syncref <= HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN)) { + /* syncref >= HDSPM_AES32_AUTOSYNC_FROM_WORD is always true */ + if (syncref <= HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN) { return syncref; } return HDSPM_AES32_AUTOSYNC_FROM_NONE; @@ -4489,7 +4482,7 @@ -static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { +static const struct snd_kcontrol_new snd_hdspm_controls_madi[] = { HDSPM_MIXER("Mixer", 0), HDSPM_INTERNAL_CLOCK("Internal Clock", 0), HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), @@ -4511,7 +4504,7 @@ }; -static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = { +static const struct snd_kcontrol_new snd_hdspm_controls_madiface[] = { HDSPM_MIXER("Mixer", 0), HDSPM_INTERNAL_CLOCK("Internal Clock", 0), HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), @@ -4524,7 +4517,7 @@ HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0) }; -static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { +static const struct snd_kcontrol_new snd_hdspm_controls_aio[] = { HDSPM_MIXER("Mixer", 0), HDSPM_INTERNAL_CLOCK("Internal Clock", 0), HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), @@ -4565,7 +4558,7 @@ */ }; -static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = { +static const struct snd_kcontrol_new snd_hdspm_controls_raydat[] = { HDSPM_MIXER("Mixer", 0), HDSPM_INTERNAL_CLOCK("Internal Clock", 0), HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0), @@ -4593,7 +4586,7 @@ HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48) }; -static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { +static const struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { HDSPM_MIXER("Mixer", 0), HDSPM_INTERNAL_CLOCK("Internal Clock", 0), HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), @@ -4635,7 +4628,7 @@ /* Control elements for the optional TCO module */ -static struct snd_kcontrol_new snd_hdspm_controls_tco[] = { +static const struct snd_kcontrol_new snd_hdspm_controls_tco[] = { HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0), HDSPM_TCO_PULL("TCO Pull", 0), HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0), @@ -4682,7 +4675,7 @@ unsigned int idx, limit; int err; struct snd_kcontrol *kctl; - struct snd_kcontrol_new *list = NULL; + const struct snd_kcontrol_new *list = NULL; switch (hdspm->io_type) { case MADI: @@ -5287,44 +5280,35 @@ static void snd_hdspm_proc_init(struct hdspm *hdspm) { - struct snd_info_entry *entry; + void (*read)(struct snd_info_entry *, struct snd_info_buffer *) = NULL; - if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) { - switch (hdspm->io_type) { - case AES32: - snd_info_set_text_ops(entry, hdspm, - snd_hdspm_proc_read_aes32); - break; - case MADI: - snd_info_set_text_ops(entry, hdspm, - snd_hdspm_proc_read_madi); - break; - case MADIface: - /* snd_info_set_text_ops(entry, hdspm, - snd_hdspm_proc_read_madiface); */ - break; - case RayDAT: - snd_info_set_text_ops(entry, hdspm, - snd_hdspm_proc_read_raydat); - break; - case AIO: - break; - } + switch (hdspm->io_type) { + case AES32: + read = snd_hdspm_proc_read_aes32; + break; + case MADI: + read = snd_hdspm_proc_read_madi; + break; + case MADIface: + /* read = snd_hdspm_proc_read_madiface; */ + break; + case RayDAT: + read = snd_hdspm_proc_read_raydat; + break; + case AIO: + break; } - if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) { - snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in); - } - - if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) { - snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out); - } + snd_card_ro_proc_new(hdspm->card, "hdspm", hdspm, read); + snd_card_ro_proc_new(hdspm->card, "ports.in", hdspm, + snd_hdspm_proc_ports_in); + snd_card_ro_proc_new(hdspm->card, "ports.out", hdspm, + snd_hdspm_proc_ports_out); #ifdef CONFIG_SND_DEBUG /* debug file to read all hdspm registers */ - if (!snd_card_proc_new(hdspm->card, "debug", &entry)) - snd_info_set_text_ops(entry, hdspm, - snd_hdspm_proc_read_debug); + snd_card_ro_proc_new(hdspm->card, "debug", hdspm, + snd_hdspm_proc_read_debug); #endif } @@ -5465,7 +5449,7 @@ } if (schedule) - tasklet_hi_schedule(&hdspm->midi_tasklet); + queue_work(system_highpri_wq, &hdspm->midi_work); } return IRQ_HANDLED; @@ -5597,11 +5581,16 @@ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut, - params_channels(params)); + for (i = 0; i < params_channels(params); ++i) { + int c = hdspm->channel_map_out[i]; - for (i = 0; i < params_channels(params); ++i) - snd_hdspm_enable_out(hdspm, i, 1); + if (c < 0) + continue; /* just make sure */ + hdspm_set_channel_dma_addr(hdspm, substream, + HDSPM_pageAddressBufferOut, + c); + snd_hdspm_enable_out(hdspm, c, 1); + } hdspm->playback_buffer = (unsigned char *) substream->runtime->dma_area; @@ -5609,11 +5598,16 @@ "Allocated sample buffer for playback at %p\n", hdspm->playback_buffer); } else { - hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn, - params_channels(params)); + for (i = 0; i < params_channels(params); ++i) { + int c = hdspm->channel_map_in[i]; - for (i = 0; i < params_channels(params); ++i) - snd_hdspm_enable_in(hdspm, i, 1); + if (c < 0) + continue; + hdspm_set_channel_dma_addr(hdspm, substream, + HDSPM_pageAddressBufferIn, + c); + snd_hdspm_enable_in(hdspm, c, 1); + } hdspm->capture_buffer = (unsigned char *) substream->runtime->dma_area; @@ -5674,19 +5668,17 @@ struct hdspm *hdspm = snd_pcm_substream_chip(substream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - - /* params_channels(params) should be enough, - but to get sure in case of error */ - for (i = 0; i < hdspm->max_channels_out; ++i) + /* Just disable all channels. The saving when disabling a */ + /* smaller set is not worth the trouble. */ + for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) snd_hdspm_enable_out(hdspm, i, 0); hdspm->playback_buffer = NULL; } else { - for (i = 0; i < hdspm->max_channels_in; ++i) + for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) snd_hdspm_enable_in(hdspm, i, 0); hdspm->capture_buffer = NULL; - } snd_pcm_lib_free_pages(substream); @@ -5832,7 +5824,7 @@ return 0; } -static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { +static const struct snd_pcm_hardware snd_hdspm_playback_subinfo = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_NONINTERLEAVED | @@ -5857,7 +5849,7 @@ .fifo_size = 0 }; -static struct snd_pcm_hardware snd_hdspm_capture_subinfo = { +static const struct snd_pcm_hardware snd_hdspm_capture_subinfo = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_NONINTERLEAVED | @@ -6380,7 +6372,6 @@ .prepare = snd_hdspm_prepare, .trigger = snd_hdspm_trigger, .pointer = snd_hdspm_hw_pointer, - .page = snd_pcm_sgbuf_ops_page, }; static int snd_hdspm_create_hwdep(struct snd_card *card, @@ -6411,7 +6402,6 @@ ------------------------------------------------------------*/ static int snd_hdspm_preallocate_memory(struct hdspm *hdspm) { - int err; struct snd_pcm *pcm; size_t wanted; @@ -6419,35 +6409,24 @@ wanted = HDSPM_DMA_AREA_BYTES; - err = - snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(hdspm->pci), - wanted, - wanted); - if (err < 0) { - dev_dbg(hdspm->card->dev, - "Could not preallocate %zd Bytes\n", wanted); - - return err; - } else - dev_dbg(hdspm->card->dev, - " Preallocated %zd Bytes\n", wanted); - + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, + &hdspm->pci->dev, + wanted, wanted); + dev_dbg(hdspm->card->dev, " Preallocated %zd Bytes\n", wanted); return 0; } - -static void hdspm_set_sgbuf(struct hdspm *hdspm, - struct snd_pcm_substream *substream, - unsigned int reg, int channels) +/* Inform the card what DMA addresses to use for the indicated channel. */ +/* Each channel got 16 4K pages allocated for DMA transfers. */ +static void hdspm_set_channel_dma_addr(struct hdspm *hdspm, + struct snd_pcm_substream *substream, + unsigned int reg, int channel) { int i; - /* continuous memory segment */ - for (i = 0; i < (channels * 16); i++) + for (i = channel * 16; i < channel * 16 + 16; i++) hdspm_write(hdspm, reg + 4 * i, - snd_pcm_sgbuf_get_addr(substream, 4096 * i)); + snd_pcm_sgbuf_get_addr(substream, 4096 * i)); } @@ -6534,7 +6513,7 @@ dev_dbg(card->dev, "Update mixer controls...\n"); hdspm_update_simple_mixer_controls(hdspm); - dev_dbg(card->dev, "Initializeing complete ???\n"); + dev_dbg(card->dev, "Initializing complete?\n"); err = snd_card_register(card); if (err < 0) { @@ -6559,6 +6538,7 @@ hdspm->card = card; spin_lock_init(&hdspm->lock); + INIT_WORK(&hdspm->midi_work, hdspm_midi_work); pci_read_config_word(hdspm->pci, PCI_CLASS_REVISION, &hdspm->firmware_rev); @@ -6619,7 +6599,7 @@ dev_dbg(card->dev, "grabbed memory region 0x%lx-0x%lx\n", hdspm->port, hdspm->port + io_extent - 1); - hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); + hdspm->iobase = ioremap(hdspm->port, io_extent); if (!hdspm->iobase) { dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n", hdspm->port, hdspm->port + io_extent - 1); @@ -6638,6 +6618,7 @@ dev_dbg(card->dev, "use IRQ %d\n", pci->irq); hdspm->irq = pci->irq; + card->sync_irq = hdspm->irq; dev_dbg(card->dev, "kmalloc Mixer memory of %zd Bytes\n", sizeof(*hdspm->mixer)); @@ -6856,10 +6837,6 @@ } - tasklet_init(&hdspm->midi_tasklet, - hdspm_midi_tasklet, (unsigned long) hdspm); - - if (hdspm->io_type != MADIface) { hdspm->serial = (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF; @@ -6894,6 +6871,7 @@ { if (hdspm->port) { + cancel_work_sync(&hdspm->midi_work); /* stop th audio, and cancel all interrupts */ hdspm->control_register &= -- Gitblit v1.6.2