diff options
Diffstat (limited to 'sound/pci/rme9652/hdsp.c')
-rw-r--r-- | sound/pci/rme9652/hdsp.c | 427 |
1 files changed, 238 insertions, 189 deletions
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index dda56ecfd33b..e7d1b43471a2 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -44,9 +44,6 @@ MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards."); MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>"); MODULE_DESCRIPTION("RME Hammerfall DSP"); MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," - "{RME HDSP-9652}," - "{RME HDSP-9632}}"); MODULE_FIRMWARE("rpm_firmware.bin"); MODULE_FIRMWARE("multiface_firmware.bin"); MODULE_FIRMWARE("multiface_firmware_rev11.bin"); @@ -292,7 +289,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); return 104857600000000 / rate; // 100 MHz return 110100480000000 / rate; // 105 MHz */ -#define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */ +#define DDS_NUMERATOR 104857600000000ULL /* = 2^20 * 10^8 */ #define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask) #define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1) @@ -436,7 +433,7 @@ struct hdsp_midi { struct snd_rawmidi *rmidi; struct snd_rawmidi_substream *input; struct snd_rawmidi_substream *output; - char istimer; /* timer in use */ + signed char istimer; /* timer in use */ struct timer_list timer; spinlock_t lock; int pending; @@ -447,8 +444,8 @@ struct hdsp { struct snd_pcm_substream *capture_substream; struct snd_pcm_substream *playback_substream; struct hdsp_midi midi[2]; - struct tasklet_struct midi_tasklet; - int use_midi_tasklet; + struct work_struct midi_work; + int use_midi_work; int precise_ptr; u32 control_register; /* cached value */ u32 control2_register; /* cached value */ @@ -469,7 +466,11 @@ struct hdsp { unsigned char qs_out_channels; unsigned char ds_out_channels; unsigned char ss_out_channels; + u32 io_loopback; /* output loopback channel states*/ + /* DMA buffers; those are copied instances from the original snd_dma_buf + * objects (which are managed via devres) for the address alignments + */ struct snd_dma_buffer capture_dma_buf; struct snd_dma_buffer playback_dma_buf; unsigned char *capture_buffer; /* suitably aligned address */ @@ -479,7 +480,7 @@ struct hdsp { pid_t playback_pid; int running; int system_sample_rate; - const char *channel_map; + const signed char *channel_map; int dev; int irq; unsigned long port; @@ -501,7 +502,7 @@ struct hdsp { where the data for that channel can be read/written from/to. */ -static const char channel_map_df_ss[HDSP_MAX_CHANNELS] = { +static const signed char channel_map_df_ss[HDSP_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, 24, 25 }; @@ -516,7 +517,7 @@ static const char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */ -1, -1, -1, -1, -1, -1, -1, -1 }; -static const char channel_map_ds[HDSP_MAX_CHANNELS] = { +static const signed char channel_map_ds[HDSP_MAX_CHANNELS] = { /* ADAT channels are remapped */ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, /* channels 12 and 13 are S/PDIF */ @@ -525,7 +526,7 @@ static const char channel_map_ds[HDSP_MAX_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; -static const char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = { +static const signed char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = { /* ADAT channels */ 0, 1, 2, 3, 4, 5, 6, 7, /* SPDIF */ @@ -539,7 +540,7 @@ static const char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = { -1, -1 }; -static const char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = { +static const signed char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = { /* ADAT */ 1, 3, 5, 7, /* SPDIF */ @@ -553,7 +554,7 @@ static const char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = { -1, -1, -1, -1, -1, -1 }; -static const char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = { +static const signed char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = { /* ADAT is disabled in this mode */ /* SPDIF */ 8, 9, @@ -567,18 +568,12 @@ static const char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = { -1, -1 }; -static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size) -{ - return snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, size, dmab); -} - -static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) +static struct snd_dma_buffer * +snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size) { - if (dmab->area) - snd_dma_free_pages(dmab); + return snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, size); } - static const struct pci_device_id snd_hdsp_ids[] = { { .vendor = PCI_VENDOR_ID_XILINX, @@ -1320,11 +1315,13 @@ static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) spin_lock_irqsave (&hmidi->lock, flags); if (hmidi->output) { if (!snd_rawmidi_transmit_empty (hmidi->output)) { - if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) { + n_pending = snd_hdsp_midi_output_possible(hmidi->hdsp, hmidi->id); + if (n_pending > 0) { if (n_pending > (int)sizeof (buf)) n_pending = sizeof (buf); - if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { + to_write = snd_rawmidi_transmit(hmidi->output, buf, n_pending); + if (to_write > 0) { for (i = 0; i < to_write; ++i) snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]); } @@ -1343,7 +1340,8 @@ static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi) int i; spin_lock_irqsave (&hmidi->lock, flags); - if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) { + n_pending = snd_hdsp_midi_input_available(hmidi->hdsp, hmidi->id); + if (n_pending > 0) { if (hmidi->input) { if (n_pending > (int)sizeof (buf)) n_pending = sizeof (buf); @@ -1385,7 +1383,6 @@ static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, } } else { hdsp->control_register &= ~ie; - tasklet_kill(&hdsp->midi_tasklet); } hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); @@ -2542,37 +2539,37 @@ static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct sn return change; } -#define HDSP_USE_MIDI_TASKLET(xname, xindex) \ +#define HDSP_USE_MIDI_WORK(xname, xindex) \ { .iface = SNDRV_CTL_ELEM_IFACE_CARD, \ .name = xname, \ .index = xindex, \ - .info = snd_hdsp_info_use_midi_tasklet, \ - .get = snd_hdsp_get_use_midi_tasklet, \ - .put = snd_hdsp_put_use_midi_tasklet \ + .info = snd_hdsp_info_use_midi_work, \ + .get = snd_hdsp_get_use_midi_work, \ + .put = snd_hdsp_put_use_midi_work \ } -static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet) +static int hdsp_set_use_midi_work(struct hdsp *hdsp, int use_work) { - if (use_tasklet) - hdsp->use_midi_tasklet = 1; + if (use_work) + hdsp->use_midi_work = 1; else - hdsp->use_midi_tasklet = 0; + hdsp->use_midi_work = 0; return 0; } -#define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info +#define snd_hdsp_info_use_midi_work snd_ctl_boolean_mono_info -static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hdsp_get_use_midi_work(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); spin_lock_irq(&hdsp->lock); - ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet; + ucontrol->value.integer.value[0] = hdsp->use_midi_work; spin_unlock_irq(&hdsp->lock); return 0; } -static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hdsp_put_use_midi_work(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); int change; @@ -2582,8 +2579,8 @@ static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct s return -EBUSY; val = ucontrol->value.integer.value[0] & 1; spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp->use_midi_tasklet; - hdsp_set_use_midi_tasklet(hdsp, val); + change = (int)val != hdsp->use_midi_work; + hdsp_set_use_midi_work(hdsp, val); spin_unlock_irq(&hdsp->lock); return change; } @@ -2950,7 +2947,7 @@ HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0), HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0), HDSP_TOGGLE_SETTING("Line Out", HDSP_LineOut), HDSP_PRECISE_POINTER("Precise Pointer", 0), -HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0), +HDSP_USE_MIDI_WORK("Use Midi Tasklet", 0), }; @@ -3254,6 +3251,60 @@ static const struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AnalogExtensionBoard); static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK; + +static bool hdsp_loopback_get(struct hdsp *const hdsp, const u8 channel) +{ + return hdsp->io_loopback & (1 << channel); +} + +static int hdsp_loopback_set(struct hdsp *const hdsp, const u8 channel, const bool enable) +{ + if (hdsp_loopback_get(hdsp, channel) == enable) + return 0; + + hdsp->io_loopback ^= (1 << channel); + + hdsp_write(hdsp, HDSP_inputEnable + (4 * (hdsp->max_channels + channel)), enable); + + return 1; +} + +static int snd_hdsp_loopback_get(struct snd_kcontrol *const kcontrol, + struct snd_ctl_elem_value *const ucontrol) +{ + struct hdsp *const hdsp = snd_kcontrol_chip(kcontrol); + const u8 channel = snd_ctl_get_ioff(kcontrol, &ucontrol->id); + + if (channel >= hdsp->max_channels) + return -ENOENT; + + ucontrol->value.integer.value[0] = hdsp_loopback_get(hdsp, channel); + + return 0; +} + +static int snd_hdsp_loopback_put(struct snd_kcontrol *const kcontrol, + struct snd_ctl_elem_value *const ucontrol) +{ + struct hdsp *const hdsp = snd_kcontrol_chip(kcontrol); + const u8 channel = snd_ctl_get_ioff(kcontrol, &ucontrol->id); + const bool enable = ucontrol->value.integer.value[0] & 1; + + if (channel >= hdsp->max_channels) + return -ENOENT; + + return hdsp_loopback_set(hdsp, channel, enable); +} + +static struct snd_kcontrol_new snd_hdsp_loopback_control = { + .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, + .name = "Output Loopback", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_ctl_boolean_mono_info, + .get = snd_hdsp_loopback_get, + .put = snd_hdsp_loopback_put +}; + static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) { unsigned int idx; @@ -3263,7 +3314,7 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) if (hdsp->io_type == RPM) { /* RPM Bypass, Disconnect and Input switches */ for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_rpm_controls); idx++) { - err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_rpm_controls[idx], hdsp)); + err = snd_ctl_add(card, snd_ctl_new1(&snd_hdsp_rpm_controls[idx], hdsp)); if (err < 0) return err; } @@ -3271,7 +3322,9 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) } for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) + kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; if (idx == 1) /* IEC958 (S/PDIF) Stream */ hdsp->spdif_ctl = kctl; @@ -3280,12 +3333,16 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) /* ADAT SyncCheck status */ snd_hdsp_adat_sync_check.name = "ADAT Lock Status"; snd_hdsp_adat_sync_check.index = 1; - if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) + kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { for (idx = 1; idx < 3; ++idx) { snd_hdsp_adat_sync_check.index = idx+1; - if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) + kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; } } @@ -3293,15 +3350,30 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */ if (hdsp->io_type == H9632) { for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0) + kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; } } + /* Output loopback controls for H9632 cards */ + if (hdsp->io_type == H9632) { + snd_hdsp_loopback_control.count = hdsp->max_channels; + kctl = snd_ctl_new1(&snd_hdsp_loopback_control, hdsp); + if (kctl == NULL) + return -ENOMEM; + err = snd_ctl_add(card, kctl); + if (err < 0) + return err; + } + /* AEB control for H96xx card */ if (hdsp->io_type == H9632 || hdsp->io_type == H9652) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0) - return err; + kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp); + err = snd_ctl_add(card, kctl); + if (err < 0) + return err; } return 0; @@ -3370,7 +3442,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0)); snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1)); snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1)); - snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off"); + snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_work ? "on" : "off"); snd_iprintf(buffer, "\n"); @@ -3693,37 +3765,34 @@ static void snd_hdsp_proc_init(struct hdsp *hdsp) snd_card_ro_proc_new(hdsp->card, "hdsp", hdsp, snd_hdsp_proc_read); } -static void snd_hdsp_free_buffers(struct hdsp *hdsp) -{ - snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci); - snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci); -} - static int snd_hdsp_initialize_memory(struct hdsp *hdsp) { - unsigned long pb_bus, cb_bus; + struct snd_dma_buffer *capture_dma, *playback_dma; - if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 || - snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) { - if (hdsp->capture_dma_buf.area) - snd_dma_free_pages(&hdsp->capture_dma_buf); + capture_dma = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES); + playback_dma = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES); + if (!capture_dma || !playback_dma) { dev_err(hdsp->card->dev, "%s: no buffers available\n", hdsp->card_name); return -ENOMEM; } - /* Align to bus-space 64K boundary */ + /* copy to the own data for alignment */ + hdsp->capture_dma_buf = *capture_dma; + hdsp->playback_dma_buf = *playback_dma; - cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul); - pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul); + /* Align to bus-space 64K boundary */ + hdsp->capture_dma_buf.addr = ALIGN(capture_dma->addr, 0x10000ul); + hdsp->playback_dma_buf.addr = ALIGN(playback_dma->addr, 0x10000ul); /* Tell the card where it is */ + hdsp_write(hdsp, HDSP_inputBufferAddress, hdsp->capture_dma_buf.addr); + hdsp_write(hdsp, HDSP_outputBufferAddress, hdsp->playback_dma_buf.addr); - hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus); - hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus); - - hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr); - hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr); + hdsp->capture_dma_buf.area += hdsp->capture_dma_buf.addr - capture_dma->addr; + hdsp->playback_dma_buf.area += hdsp->playback_dma_buf.addr - playback_dma->addr; + hdsp->capture_buffer = hdsp->capture_dma_buf.area; + hdsp->playback_buffer = hdsp->playback_dma_buf.area; return 0; } @@ -3791,9 +3860,9 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp) return 0; } -static void hdsp_midi_tasklet(struct tasklet_struct *t) +static void hdsp_midi_work(struct work_struct *work) { - struct hdsp *hdsp = from_tasklet(hdsp, t, midi_tasklet); + struct hdsp *hdsp = container_of(work, struct hdsp, midi_work); if (hdsp->midi[0].pending) snd_hdsp_midi_input_read (&hdsp->midi[0]); @@ -3838,7 +3907,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id) } if (midi0 && midi0status) { - if (hdsp->use_midi_tasklet) { + if (hdsp->use_midi_work) { /* we disable interrupts for this input until processing is done */ hdsp->control_register &= ~HDSP_Midi0InterruptEnable; hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); @@ -3849,7 +3918,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id) } } if (hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632 && midi1 && midi1status) { - if (hdsp->use_midi_tasklet) { + if (hdsp->use_midi_work) { /* we disable interrupts for this input until processing is done */ hdsp->control_register &= ~HDSP_Midi1InterruptEnable; hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); @@ -3859,8 +3928,8 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id) snd_hdsp_midi_input_read (&hdsp->midi[1]); } } - if (hdsp->use_midi_tasklet && schedule) - tasklet_schedule(&hdsp->midi_tasklet); + if (hdsp->use_midi_work && schedule) + queue_work(system_highpri_wq, &hdsp->midi_work); return IRQ_HANDLED; } @@ -3870,7 +3939,7 @@ static snd_pcm_uframes_t snd_hdsp_hw_pointer(struct snd_pcm_substream *substream return hdsp_hw_pointer(hdsp); } -static char *hdsp_channel_buffer_location(struct hdsp *hdsp, +static signed char *hdsp_channel_buffer_location(struct hdsp *hdsp, int stream, int channel) @@ -3880,7 +3949,8 @@ static char *hdsp_channel_buffer_location(struct hdsp *hdsp, if (snd_BUG_ON(channel < 0 || channel >= hdsp->max_channels)) return NULL; - if ((mapped_channel = hdsp->channel_map[channel]) < 0) + mapped_channel = hdsp->channel_map[channel]; + if (mapped_channel < 0) return NULL; if (stream == SNDRV_PCM_STREAM_CAPTURE) @@ -3891,10 +3961,10 @@ static char *hdsp_channel_buffer_location(struct hdsp *hdsp, static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel, unsigned long pos, - void __user *src, unsigned long count) + struct iov_iter *src, unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf; if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES)) return -EINVAL; @@ -3902,31 +3972,17 @@ static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - if (copy_from_user(channel_buf + pos, src, count)) + if (copy_from_iter(channel_buf + pos, count, src) != count) return -EFAULT; return 0; } -static int snd_hdsp_playback_copy_kernel(struct snd_pcm_substream *substream, - int channel, unsigned long pos, - void *src, unsigned long count) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; - - channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel); - if (snd_BUG_ON(!channel_buf)) - return -EIO; - memcpy(channel_buf + pos, src, count); - return 0; -} - static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel, unsigned long pos, - void __user *dst, unsigned long count) + struct iov_iter *dst, unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf; if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES)) return -EINVAL; @@ -3934,31 +3990,17 @@ static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - if (copy_to_user(dst, channel_buf + pos, count)) + if (copy_to_iter(channel_buf + pos, count, dst) != count) return -EFAULT; return 0; } -static int snd_hdsp_capture_copy_kernel(struct snd_pcm_substream *substream, - int channel, unsigned long pos, - void *dst, unsigned long count) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; - - channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel); - if (snd_BUG_ON(!channel_buf)) - return -EIO; - memcpy(dst, channel_buf + pos, count); - return 0; -} - static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel, unsigned long pos, unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; + signed char *channel_buf; channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) @@ -4052,7 +4094,8 @@ static int snd_hdsp_hw_params(struct snd_pcm_substream *substream, spin_lock_irq(&hdsp->lock); if (! hdsp->clock_source_locked) { - if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) { + err = hdsp_set_rate(hdsp, params_rate(params), 0); + if (err < 0) { spin_unlock_irq(&hdsp->lock); _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); return err; @@ -4060,7 +4103,8 @@ static int snd_hdsp_hw_params(struct snd_pcm_substream *substream, } spin_unlock_irq(&hdsp->lock); - if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) { + err = hdsp_set_interrupt_interval(hdsp, params_period_size(params)); + if (err < 0) { _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); return err; } @@ -4440,8 +4484,7 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); runtime->hw = snd_hdsp_playback_subinfo; - runtime->dma_area = hdsp->playback_buffer; - runtime->dma_bytes = HDSP_DMA_AREA_BYTES; + snd_pcm_set_runtime_buffer(substream, &hdsp->playback_dma_buf); hdsp->playback_pid = current->pid; hdsp->playback_substream = substream; @@ -4517,8 +4560,7 @@ static int snd_hdsp_capture_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); runtime->hw = snd_hdsp_capture_subinfo; - runtime->dma_area = hdsp->capture_buffer; - runtime->dma_bytes = HDSP_DMA_AREA_BYTES; + snd_pcm_set_runtime_buffer(substream, &hdsp->capture_dma_buf); hdsp->capture_pid = current->pid; hdsp->capture_substream = substream; @@ -4792,14 +4834,15 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; if (hdsp->io_type == Undefined) { - if ((err = hdsp_get_iobox_version(hdsp)) < 0) + err = hdsp_get_iobox_version(hdsp); + if (err < 0) return err; } memset(&hdsp_version, 0, sizeof(hdsp_version)); hdsp_version.io_type = hdsp->io_type; hdsp_version.firmware_rev = hdsp->firmware_rev; - if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version)))) - return -EFAULT; + if (copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))) + return -EFAULT; break; } case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: { @@ -4838,17 +4881,20 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne hdsp->state |= HDSP_FirmwareCached; - if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) + err = snd_hdsp_load_firmware_from_cache(hdsp); + if (err < 0) return err; if (!(hdsp->state & HDSP_InitializationComplete)) { - if ((err = snd_hdsp_enable_io(hdsp)) < 0) + err = snd_hdsp_enable_io(hdsp); + if (err < 0) return err; snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); - if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { + err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp); + if (err < 0) { dev_err(hdsp->card->dev, "error creating alsa devices\n"); return err; @@ -4876,8 +4922,7 @@ static const struct snd_pcm_ops snd_hdsp_playback_ops = { .prepare = snd_hdsp_prepare, .trigger = snd_hdsp_trigger, .pointer = snd_hdsp_hw_pointer, - .copy_user = snd_hdsp_playback_copy, - .copy_kernel = snd_hdsp_playback_copy_kernel, + .copy = snd_hdsp_playback_copy, .fill_silence = snd_hdsp_hw_silence, }; @@ -4889,8 +4934,7 @@ static const struct snd_pcm_ops snd_hdsp_capture_ops = { .prepare = snd_hdsp_prepare, .trigger = snd_hdsp_trigger, .pointer = snd_hdsp_hw_pointer, - .copy_user = snd_hdsp_capture_copy, - .copy_kernel = snd_hdsp_capture_copy_kernel, + .copy = snd_hdsp_capture_copy, }; static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp) @@ -4898,7 +4942,8 @@ static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp) struct snd_hwdep *hw; int err; - if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0) + err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw); + if (err < 0) return err; hdsp->hwdep = hw; @@ -4916,7 +4961,8 @@ static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0) + err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm); + if (err < 0) return err; hdsp->pcm = pcm; @@ -4957,7 +5003,7 @@ static int snd_hdsp_enable_io (struct hdsp *hdsp) static void snd_hdsp_initialize_channels(struct hdsp *hdsp) { - int status, aebi_channels, aebo_channels; + int status, aebi_channels, aebo_channels, i; switch (hdsp->io_type) { case Digiface: @@ -4984,6 +5030,12 @@ static void snd_hdsp_initialize_channels(struct hdsp *hdsp) hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels; hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels; hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels; + /* Disable loopback of output channels, as the set function + * only sets on a change we fake all bits (channels) as enabled. + */ + hdsp->io_loopback = 0xffffffff; + for (i = 0; i < hdsp->max_channels; ++i) + hdsp_loopback_set(hdsp, i, false); break; case Multiface: @@ -5016,28 +5068,32 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp { int err; - if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) { + err = snd_hdsp_create_pcm(card, hdsp); + if (err < 0) { dev_err(card->dev, "Error creating pcm interface\n"); return err; } - if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { + err = snd_hdsp_create_midi(card, hdsp, 0); + if (err < 0) { dev_err(card->dev, "Error creating first midi interface\n"); return err; } if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { - if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) { + err = snd_hdsp_create_midi(card, hdsp, 1); + if (err < 0) { dev_err(card->dev, "Error creating second midi interface\n"); return err; } } - if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) { + err = snd_hdsp_create_controls(card, hdsp); + if (err < 0) { dev_err(card->dev, "Error creating ctl interface\n"); return err; @@ -5051,7 +5107,8 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp hdsp->capture_substream = NULL; hdsp->playback_substream = NULL; - if ((err = snd_hdsp_set_defaults(hdsp)) < 0) { + err = snd_hdsp_set_defaults(hdsp); + if (err < 0) { dev_err(card->dev, "Error setting default values\n"); return err; @@ -5062,7 +5119,8 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, hdsp->port, hdsp->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { dev_err(card->dev, "error registering card\n"); return err; @@ -5083,7 +5141,8 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; if (hdsp->io_type == Undefined) { - if ((err = hdsp_get_iobox_version(hdsp)) < 0) + err = hdsp_get_iobox_version(hdsp); + if (err < 0) return err; if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; @@ -5129,21 +5188,25 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) hdsp->state |= HDSP_FirmwareCached; - if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) + err = snd_hdsp_load_firmware_from_cache(hdsp); + if (err < 0) return err; if (!(hdsp->state & HDSP_InitializationComplete)) { - if ((err = snd_hdsp_enable_io(hdsp)) < 0) + err = snd_hdsp_enable_io(hdsp); + if (err < 0) return err; - if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) { + err = snd_hdsp_create_hwdep(hdsp->card, hdsp); + if (err < 0) { dev_err(hdsp->card->dev, "error creating hwdep device\n"); return err; } snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); - if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { + err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp); + if (err < 0) { dev_err(hdsp->card->dev, "error creating alsa devices\n"); return err; @@ -5182,7 +5245,7 @@ static int snd_hdsp_create(struct snd_card *card, spin_lock_init(&hdsp->lock); - tasklet_setup(&hdsp->midi_tasklet, hdsp_midi_tasklet); + INIT_WORK(&hdsp->midi_work, hdsp_midi_work); pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev); hdsp->firmware_rev &= 0xff; @@ -5212,22 +5275,25 @@ static int snd_hdsp_create(struct snd_card *card, is_9632 = 1; } - if ((err = pci_enable_device(pci)) < 0) + err = pcim_enable_device(pci); + if (err < 0) return err; pci_set_master(hdsp->pci); - if ((err = pci_request_regions(pci, "hdsp")) < 0) + err = pci_request_regions(pci, "hdsp"); + if (err < 0) return err; hdsp->port = pci_resource_start(pci, 0); - if ((hdsp->iobase = ioremap(hdsp->port, HDSP_IO_EXTENT)) == NULL) { + hdsp->iobase = devm_ioremap(&pci->dev, hdsp->port, HDSP_IO_EXTENT); + if (!hdsp->iobase) { dev_err(hdsp->card->dev, "unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); return -EBUSY; } - if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED, - KBUILD_MODNAME, hdsp)) { + if (devm_request_irq(&pci->dev, pci->irq, snd_hdsp_interrupt, + IRQF_SHARED, KBUILD_MODNAME, hdsp)) { dev_err(hdsp->card->dev, "unable to use IRQ %d\n", pci->irq); return -EBUSY; } @@ -5235,10 +5301,11 @@ static int snd_hdsp_create(struct snd_card *card, hdsp->irq = pci->irq; card->sync_irq = hdsp->irq; hdsp->precise_ptr = 0; - hdsp->use_midi_tasklet = 1; + hdsp->use_midi_work = 1; hdsp->dds_value = 0; - if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) + err = snd_hdsp_initialize_memory(hdsp); + if (err < 0) return err; if (!is_9652 && !is_9632) { @@ -5250,7 +5317,8 @@ static int snd_hdsp_create(struct snd_card *card, return err; if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - if ((err = hdsp_request_fw_loader(hdsp)) < 0) + err = hdsp_request_fw_loader(hdsp); + if (err < 0) /* we don't fail as this can happen if userspace is not ready for firmware upload @@ -5263,7 +5331,8 @@ static int snd_hdsp_create(struct snd_card *card, /* we defer initialization */ dev_info(hdsp->card->dev, "card initialization pending : waiting for firmware\n"); - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) + err = snd_hdsp_create_hwdep(card, hdsp); + if (err < 0) return err; return 0; } else { @@ -5278,7 +5347,8 @@ static int snd_hdsp_create(struct snd_card *card, } } - if ((err = snd_hdsp_enable_io(hdsp)) != 0) + err = snd_hdsp_enable_io(hdsp); + if (err) return err; if (is_9652) @@ -5287,7 +5357,8 @@ static int snd_hdsp_create(struct snd_card *card, if (is_9632) hdsp->io_type = H9632; - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) + err = snd_hdsp_create_hwdep(card, hdsp); + if (err < 0) return err; snd_hdsp_initialize_channels(hdsp); @@ -5295,43 +5366,26 @@ static int snd_hdsp_create(struct snd_card *card, hdsp->state |= HDSP_FirmwareLoaded; - if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0) + err = snd_hdsp_create_alsa_devices(card, hdsp); + if (err < 0) return err; return 0; } -static int snd_hdsp_free(struct hdsp *hdsp) +static void snd_hdsp_card_free(struct snd_card *card) { + struct hdsp *hdsp = card->private_data; + if (hdsp->port) { /* stop the audio, and cancel all interrupts */ - tasklet_kill(&hdsp->midi_tasklet); + cancel_work_sync(&hdsp->midi_work); hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable); hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register); } - if (hdsp->irq >= 0) - free_irq(hdsp->irq, (void *)hdsp); - - snd_hdsp_free_buffers(hdsp); - release_firmware(hdsp->firmware); vfree(hdsp->fw_uploaded); - iounmap(hdsp->iobase); - - if (hdsp->port) - pci_release_regions(hdsp->pci); - - pci_disable_device(hdsp->pci); - return 0; -} - -static void snd_hdsp_card_free(struct snd_card *card) -{ - struct hdsp *hdsp = card->private_data; - - if (hdsp) - snd_hdsp_free(hdsp); } static int snd_hdsp_probe(struct pci_dev *pci, @@ -5349,8 +5403,8 @@ static int snd_hdsp_probe(struct pci_dev *pci, return -ENOENT; } - err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, - sizeof(struct hdsp), &card); + err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct hdsp), &card); if (err < 0) return err; @@ -5360,32 +5414,27 @@ static int snd_hdsp_probe(struct pci_dev *pci, hdsp->pci = pci; err = snd_hdsp_create(card, hdsp); if (err) - goto free_card; + goto error; strcpy(card->shortname, "Hammerfall DSP"); sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, hdsp->port, hdsp->irq); err = snd_card_register(card); - if (err) { -free_card: - snd_card_free(card); - return err; - } + if (err) + goto error; pci_set_drvdata(pci, card); dev++; return 0; -} -static void snd_hdsp_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); + error: + snd_card_free(card); + return err; } static struct pci_driver hdsp_driver = { .name = KBUILD_MODNAME, .id_table = snd_hdsp_ids, .probe = snd_hdsp_probe, - .remove = snd_hdsp_remove, }; module_pci_driver(hdsp_driver); |