#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/pci.h>
+#include <linux/firmware.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */
static int line_outs_monitor[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0}; /* Send all inputs/playback to line outs */
-static int boot_devs;
-module_param_array(index, int, boot_devs, 0444);
+module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
-module_param_array(id, charp, boot_devs, 0444);
+module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
-module_param_array(enable, bool, boot_devs, 0444);
+module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-module_param_array(precise_ptr, bool, boot_devs, 0444);
+module_param_array(precise_ptr, bool, NULL, 0444);
MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably).");
-MODULE_PARM_SYNTAX(precise_ptr, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
-module_param_array(line_outs_monitor, bool, boot_devs, 0444);
+module_param_array(line_outs_monitor, bool, NULL, 0444);
MODULE_PARM_DESC(line_outs_monitor, "Send all input and playback streams to line outs by default.");
-MODULE_PARM_SYNTAX(line_outs_monitor, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
MODULE_DESCRIPTION("RME Hammerfall DSP");
MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{RME Hammerfall-DSP},"
+MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
"{RME HDSP-9652},"
"{RME HDSP-9632}}");
#define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES)
#define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024)
+/* use hotplug firmeare loader? */
+#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
+#ifndef HDSP_USE_HWDEP_LOADER
+#define HDSP_FW_LOADER
+#endif
+#endif
+
typedef struct _hdsp hdsp_t;
typedef struct _hdsp_midi hdsp_midi_t;
typedef struct _hdsp_9632_meters hdsp_9632_meters_t;
unsigned char qs_out_channels;
unsigned char ds_out_channels;
unsigned char ss_out_channels;
- void *capture_buffer_unaligned; /* original buffer addresses */
- void *playback_buffer_unaligned; /* original buffer addresses */
+
+ struct snd_dma_buffer capture_dma_buf;
+ struct snd_dma_buffer playback_dma_buf;
unsigned char *capture_buffer; /* suitably aligned address */
unsigned char *playback_buffer; /* suitably aligned address */
- dma_addr_t capture_buffer_addr;
- dma_addr_t playback_buffer_addr;
+
pid_t capture_pid;
pid_t playback_pid;
int running;
int dev;
int irq;
unsigned long port;
- struct resource *res_port;
- unsigned long iobase;
+ void __iomem *iobase;
snd_card_t *card;
snd_pcm_t *pcm;
snd_hwdep_t *hwdep;
-1, -1
};
-#define HDSP_PREALLOCATE_MEMORY /* via module snd-hdsp_mem */
-
-#ifdef HDSP_PREALLOCATE_MEMORY
-static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
{
- struct snd_dma_device pdev;
- struct snd_dma_buffer dmbuf;
-
- memset(&pdev, 0, sizeof(pdev));
- pdev.type = SNDRV_DMA_TYPE_DEV;
- pdev.dev = snd_dma_pci_data(pci);
- pdev.id = capture;
- dmbuf.bytes = 0;
- if (! snd_dma_get_reserved(&pdev, &dmbuf)) {
- if (snd_dma_alloc_pages(&pdev, size, &dmbuf) < 0)
- return NULL;
- snd_dma_set_reserved(&pdev, &dmbuf);
+ dmab->dev.type = SNDRV_DMA_TYPE_DEV;
+ dmab->dev.dev = snd_dma_pci_data(pci);
+ if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ size, dmab) < 0)
+ return -ENOMEM;
}
- *addrp = dmbuf.addr;
- return dmbuf.area;
-}
-
-static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
-{
- struct snd_dma_device pdev;
-
- memset(&pdev, 0, sizeof(pdev));
- pdev.type = SNDRV_DMA_TYPE_DEV;
- pdev.dev = snd_dma_pci_data(pci);
- pdev.id = capture;
- snd_dma_free_reserved(&pdev);
+ return 0;
}
-#else
-static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
{
- return snd_malloc_pci_pages(pci, size, addrp);
+ if (dmab->area)
+ snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
}
-static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
-{
- snd_free_pci_pages(pci, size, ptr, addr);
-}
-#endif
static struct pci_device_id snd_hdsp_ids[] = {
{
MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
/* prototypes */
-static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp);
-static int __devinit snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp);
-static inline int snd_hdsp_enable_io (hdsp_t *hdsp);
-static inline void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp);
-static inline void snd_hdsp_initialize_channels (hdsp_t *hdsp);
-static inline int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout);
+static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp);
+static int snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp);
+static int snd_hdsp_enable_io (hdsp_t *hdsp);
+static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp);
+static void snd_hdsp_initialize_channels (hdsp_t *hdsp);
+static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout);
static int hdsp_autosync_ref(hdsp_t *hdsp);
static int snd_hdsp_set_defaults(hdsp_t *hdsp);
-static inline void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp);
+static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp);
-static inline int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
+static int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
{
switch (hdsp->firmware_rev) {
case 0xa:
}
}
-static inline int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
+static int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
{
switch (hdsp->firmware_rev) {
case 0xa:
}
}
-static inline void hdsp_write(hdsp_t *hdsp, int reg, int val)
+static void hdsp_write(hdsp_t *hdsp, int reg, int val)
{
writel(val, hdsp->iobase + reg);
}
-static inline unsigned int hdsp_read(hdsp_t *hdsp, int reg)
+static unsigned int hdsp_read(hdsp_t *hdsp, int reg)
{
return readl (hdsp->iobase + reg);
}
-static inline int hdsp_check_for_iobox (hdsp_t *hdsp)
+static int hdsp_check_for_iobox (hdsp_t *hdsp)
{
if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
return 0;
}
-static inline int hdsp_get_iobox_version (hdsp_t *hdsp)
+static int hdsp_get_iobox_version (hdsp_t *hdsp)
{
int err;
}
-static inline int hdsp_check_for_firmware (hdsp_t *hdsp)
+static int hdsp_check_for_firmware (hdsp_t *hdsp)
{
if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
}
-static inline int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
+static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
{
int i;
return -1;
}
-static inline int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr)
+static int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr)
{
if (addr >= HDSP_MATRIX_MIXER_SIZE) {
return 0;
return hdsp->mixer_matrix[addr];
}
-static inline int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
+static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
{
unsigned int ad;
if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
- /* from martin björnsen:
+ /* from martin björnsen:
"You can only write dwords to the
mixer memory which contain two
return 0;
}
-static inline int snd_hdsp_use_is_exclusive(hdsp_t *hdsp)
+static int snd_hdsp_use_is_exclusive(hdsp_t *hdsp)
{
unsigned long flags;
int ret = 1;
return ret;
}
-static inline int hdsp_external_sample_rate (hdsp_t *hdsp)
+static int hdsp_external_sample_rate (hdsp_t *hdsp)
{
unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
}
}
-static inline int hdsp_spdif_sample_rate(hdsp_t *hdsp)
+static int hdsp_spdif_sample_rate(hdsp_t *hdsp)
{
unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
return 0;
}
-static inline void hdsp_compute_period_size(hdsp_t *hdsp)
+static void hdsp_compute_period_size(hdsp_t *hdsp)
{
hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
}
position &= HDSP_BufferPositionMask;
position /= 4;
- position -= 32;
- position &= (HDSP_CHANNEL_BUFFER_SAMPLES-1);
+ position &= (hdsp->period_bytes/2) - 1;
return position;
}
-static inline void hdsp_reset_hw_pointer(hdsp_t *hdsp)
+static void hdsp_reset_hw_pointer(hdsp_t *hdsp)
{
hdsp_write (hdsp, HDSP_resetPointer, 0);
}
-static inline void hdsp_start_audio(hdsp_t *s)
+static void hdsp_start_audio(hdsp_t *s)
{
s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
hdsp_write(s, HDSP_controlRegister, s->control_register);
}
-static inline void hdsp_stop_audio(hdsp_t *s)
+static void hdsp_stop_audio(hdsp_t *s)
{
s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
hdsp_write(s, HDSP_controlRegister, s->control_register);
}
-static inline void hdsp_silence_playback(hdsp_t *hdsp)
+static void hdsp_silence_playback(hdsp_t *hdsp)
{
memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
}
MIDI
----------------------------------------------------------------------------*/
-static inline unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id)
+static unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id)
{
/* the hardware already does the relevant bit-mask with 0xff */
if (id) {
}
}
-static inline void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val)
+static void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val)
{
/* the hardware already does the relevant bit-mask with 0xff */
if (id) {
}
}
-static inline int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id)
+static int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id)
{
if (id) {
return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
}
}
-static inline int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id)
+static int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id)
{
int fifo_bytes_used;
}
}
-static inline void snd_hdsp_flush_midi_input (hdsp_t *hdsp, int id)
+static void snd_hdsp_flush_midi_input (hdsp_t *hdsp, int id)
{
while (snd_hdsp_midi_input_available (hdsp, id)) {
snd_hdsp_midi_read_byte (hdsp, id);
static int snd_hdsp_midi_input_open(snd_rawmidi_substream_t * substream)
{
hdsp_midi_t *hmidi;
- unsigned long flags;
hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
- spin_lock_irqsave (&hmidi->lock, flags);
+ spin_lock_irq (&hmidi->lock);
snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
hmidi->input = substream;
- spin_unlock_irqrestore (&hmidi->lock, flags);
+ spin_unlock_irq (&hmidi->lock);
return 0;
}
static int snd_hdsp_midi_output_open(snd_rawmidi_substream_t * substream)
{
hdsp_midi_t *hmidi;
- unsigned long flags;
hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
- spin_lock_irqsave (&hmidi->lock, flags);
+ spin_lock_irq (&hmidi->lock);
hmidi->output = substream;
- spin_unlock_irqrestore (&hmidi->lock, flags);
+ spin_unlock_irq (&hmidi->lock);
return 0;
}
static int snd_hdsp_midi_input_close(snd_rawmidi_substream_t * substream)
{
hdsp_midi_t *hmidi;
- unsigned long flags;
snd_hdsp_midi_input_trigger (substream, 0);
hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
- spin_lock_irqsave (&hmidi->lock, flags);
+ spin_lock_irq (&hmidi->lock);
hmidi->input = NULL;
- spin_unlock_irqrestore (&hmidi->lock, flags);
+ spin_unlock_irq (&hmidi->lock);
return 0;
}
static int snd_hdsp_midi_output_close(snd_rawmidi_substream_t * substream)
{
hdsp_midi_t *hmidi;
- unsigned long flags;
snd_hdsp_midi_output_trigger (substream, 0);
hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
- spin_lock_irqsave (&hmidi->lock, flags);
+ spin_lock_irq (&hmidi->lock);
hmidi->output = NULL;
- spin_unlock_irqrestore (&hmidi->lock, flags);
+ spin_unlock_irq (&hmidi->lock);
return 0;
}
-snd_rawmidi_ops_t snd_hdsp_midi_output =
+static snd_rawmidi_ops_t snd_hdsp_midi_output =
{
.open = snd_hdsp_midi_output_open,
.close = snd_hdsp_midi_output_close,
.trigger = snd_hdsp_midi_output_trigger,
};
-snd_rawmidi_ops_t snd_hdsp_midi_input =
+static snd_rawmidi_ops_t snd_hdsp_midi_input =
{
.open = snd_hdsp_midi_input_open,
.close = snd_hdsp_midi_input_close,
static int snd_hdsp_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
return 0;
static int snd_hdsp_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
u32 val;
val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = val != hdsp->creg_spdif;
hdsp->creg_spdif = val;
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
return 0;
static int snd_hdsp_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
u32 val;
val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = val != hdsp->creg_spdif_stream;
hdsp->creg_spdif_stream = val;
hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"};
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
static int snd_hdsp_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
return 0;
static int snd_hdsp_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = val != hdsp_spdif_in(hdsp);
if (change)
hdsp_set_spdif_input(hdsp, val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp);
return 0;
static int snd_hdsp_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = (int)val != hdsp_spdif_out(hdsp);
hdsp_set_spdif_output(hdsp, val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp);
return 0;
static int snd_hdsp_put_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = (int)val != hdsp_spdif_professional(hdsp);
hdsp_set_spdif_professional(hdsp, val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp);
return 0;
static int snd_hdsp_put_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = (int)val != hdsp_spdif_emphasis(hdsp);
hdsp_set_spdif_emphasis(hdsp, val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp);
return 0;
static int snd_hdsp_put_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = (int)val != hdsp_spdif_nonaudio(hdsp);
hdsp_set_spdif_nonaudio(hdsp, val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_info_spdif_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
static int snd_hdsp_get_spdif_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
switch (hdsp_spdif_sample_rate(hdsp)) {
case 32000:
static int snd_hdsp_get_system_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
return 0;
static int snd_hdsp_info_autosync_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
static int snd_hdsp_get_autosync_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
switch (hdsp_external_sample_rate(hdsp)) {
case 32000:
static int snd_hdsp_get_system_clock_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
return 0;
static int snd_hdsp_info_clock_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
static char *texts[] = {"AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz", "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz", "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz", "Internal 192.0 KHz" };
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
static int snd_hdsp_get_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
return 0;
static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
} else {
if (val > 6) val = 6;
}
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
if (val != hdsp_clock_source(hdsp)) {
change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0;
} else {
change = 0;
}
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
return 0;
static int snd_hdsp_put_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
val = ucontrol->value.enumerated.item[0];
if (val < 0) val = 0;
if (val > 2) val = 2;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
if (val != hdsp_da_gain(hdsp)) {
change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0;
} else {
change = 0;
}
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
return 0;
static int snd_hdsp_put_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
val = ucontrol->value.enumerated.item[0];
if (val < 0) val = 0;
if (val > 2) val = 2;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
if (val != hdsp_ad_gain(hdsp)) {
change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0;
} else {
change = 0;
}
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
return 0;
static int snd_hdsp_put_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
val = ucontrol->value.enumerated.item[0];
if (val < 0) val = 0;
if (val > 2) val = 2;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
if (val != hdsp_phone_gain(hdsp)) {
change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0;
} else {
change = 0;
}
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp);
return 0;
static int snd_hdsp_put_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = (int)val != hdsp_xlr_breakout_cable(hdsp);
hdsp_set_xlr_breakout_cable(hdsp, val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp);
return 0;
static int snd_hdsp_put_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = (int)val != hdsp_aeb(hdsp);
hdsp_set_aeb(hdsp, val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_info_pref_sync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
static int snd_hdsp_get_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
return 0;
static int snd_hdsp_put_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change, max;
unsigned int val;
}
val = ucontrol->value.enumerated.item[0] % max;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = (int)val != hdsp_pref_sync_ref(hdsp);
hdsp_set_pref_sync_ref(hdsp, val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_autosync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
- ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
+ ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp);
return 0;
}
static int snd_hdsp_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
ucontrol->value.integer.value[0] = hdsp->passthru;
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return 0;
}
static int snd_hdsp_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
int err = 0;
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = (ucontrol->value.integer.value[0] != hdsp->passthru);
if (change)
err = hdsp_set_passthru(hdsp, val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return err ? err : change;
}
static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return 0;
}
static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = (int)val != hdsp_line_out(hdsp);
hdsp_set_line_output(hdsp, val);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int source;
int destination;
int addr;
addr = hdsp_input_to_output_key(hdsp,source, destination);
}
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return 0;
}
static int snd_hdsp_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int source;
int destination;
gain = ucontrol->value.integer.value[2];
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
change = gain != hdsp_read_gain(hdsp, addr);
if (change)
hdsp_write_gain(hdsp, addr, gain);
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return change;
}
static int snd_hdsp_get_wc_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
return 0;
static int snd_hdsp_get_spdif_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
return 0;
static int snd_hdsp_get_adatsync_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
return 0;
static int snd_hdsp_get_adat_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
int offset;
- hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
offset = ucontrol->id.index - 1;
snd_assert(offset >= 0);
HDSP_LINE_OUT("Line Out", 0),
};
-#define HDSP_CONTROLS (sizeof(snd_hdsp_controls)/sizeof(snd_kcontrol_new_t))
-
-#define HDSP_9632_CONTROLS (sizeof(snd_hdsp_9632_controls)/sizeof(snd_kcontrol_new_t))
-
static snd_kcontrol_new_t snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
static snd_kcontrol_new_t snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
-int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp)
+static int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp)
{
unsigned int idx;
int err;
snd_kcontrol_t *kctl;
- for (idx = 0; idx < HDSP_CONTROLS; idx++) {
+ 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) {
return err;
}
/* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
if (hdsp->io_type == H9632) {
- for (idx = 0; idx < HDSP_9632_CONTROLS; idx++) {
+ 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) {
return err;
}
snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
hdsp->capture_buffer, hdsp->playback_buffer);
snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
- hdsp->irq, hdsp->port, hdsp->iobase);
+ hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
snd_iprintf(buffer, "Control2 register: 0x%x\n", hdsp->control2_register);
snd_iprintf(buffer, "Status register: 0x%x\n", status);
static void snd_hdsp_free_buffers(hdsp_t *hdsp)
{
- if (hdsp->capture_buffer_unaligned) {
- snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES,
- hdsp->capture_buffer_unaligned,
- hdsp->capture_buffer_addr, 1);
- }
-
- if (hdsp->playback_buffer_unaligned) {
- snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES,
- hdsp->playback_buffer_unaligned,
- hdsp->playback_buffer_addr, 0);
- }
+ snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
+ snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
}
static int __devinit snd_hdsp_initialize_memory(hdsp_t *hdsp)
{
- void *pb, *cb;
- dma_addr_t pb_addr, cb_addr;
unsigned long pb_bus, cb_bus;
- cb = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, &cb_addr, 1);
- pb = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, &pb_addr, 0);
-
- if (cb == 0 || pb == 0) {
- if (cb) {
- snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, cb, cb_addr, 1);
- }
- if (pb) {
- snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, pb, pb_addr, 0);
- }
-
+ 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);
printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name);
return -ENOMEM;
}
- /* save raw addresses for use when freeing memory later */
-
- hdsp->capture_buffer_unaligned = cb;
- hdsp->playback_buffer_unaligned = pb;
- hdsp->capture_buffer_addr = cb_addr;
- hdsp->playback_buffer_addr = pb_addr;
-
/* Align to bus-space 64K boundary */
- cb_bus = (cb_addr + 0xFFFF) & ~0xFFFFl;
- pb_bus = (pb_addr + 0xFFFF) & ~0xFFFFl;
+ cb_bus = (hdsp->capture_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
+ pb_bus = (hdsp->playback_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
/* Tell the card where it is */
hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
- hdsp->capture_buffer = cb + (cb_bus - cb_addr);
- hdsp->playback_buffer = pb + (pb_bus - pb_addr);
+ 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);
return 0;
}
return 0;
}
-void hdsp_midi_tasklet(unsigned long arg)
+static void hdsp_midi_tasklet(unsigned long arg)
{
hdsp_t *hdsp = (hdsp_t *)arg;
static snd_pcm_uframes_t snd_hdsp_hw_pointer(snd_pcm_substream_t *substream)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
return hdsp_hw_pointer(hdsp);
}
static int snd_hdsp_playback_copy(snd_pcm_substream_t *substream, int channel,
snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
static int snd_hdsp_capture_copy(snd_pcm_substream_t *substream, int channel,
snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
static int snd_hdsp_hw_silence(snd_pcm_substream_t *substream, int channel,
snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
static int snd_hdsp_reset(snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
snd_pcm_substream_t *other;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
other = hdsp->capture_substream;
static int snd_hdsp_hw_params(snd_pcm_substream_t *substream,
snd_pcm_hw_params_t *params)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
int err;
pid_t this_pid;
pid_t other_pid;
static int snd_hdsp_channel_info(snd_pcm_substream_t *substream,
snd_pcm_channel_info_t *info)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
int mapped_channel;
snd_assert(info->channel < hdsp->max_channels, return -EINVAL);
static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
snd_pcm_substream_t *other;
int running;
static int snd_hdsp_prepare(snd_pcm_substream_t *substream)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
int result = 0;
if (hdsp_check_for_iobox (hdsp)) {
return -EIO;
}
- spin_lock(&hdsp->lock);
+ spin_lock_irq(&hdsp->lock);
if (!hdsp->running)
hdsp_reset_hw_pointer(hdsp);
- spin_unlock(&hdsp->lock);
+ spin_unlock_irq(&hdsp->lock);
return result;
}
static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
-#define HDSP_PERIOD_SIZES sizeof(hdsp_period_sizes) / sizeof(hdsp_period_sizes[0])
-
static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_period_sizes = {
- .count = HDSP_PERIOD_SIZES,
+ .count = ARRAY_SIZE(hdsp_period_sizes),
.list = hdsp_period_sizes,
.mask = 0
};
static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
-#define HDSP_9632_SAMPLE_RATES sizeof(hdsp_9632_sample_rates) / sizeof(hdsp_9632_sample_rates[0])
-
static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_9632_sample_rates = {
- .count = HDSP_9632_SAMPLE_RATES,
+ .count = ARRAY_SIZE(hdsp_9632_sample_rates),
.list = hdsp_9632_sample_rates,
.mask = 0
};
static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
- unsigned long flags;
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
if (hdsp_check_for_iobox (hdsp)) {
return -EIO;
}
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
snd_pcm_set_sync(substream);
hdsp->playback_pid = current->pid;
hdsp->playback_substream = substream;
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
static int snd_hdsp_playback_release(snd_pcm_substream_t *substream)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
- unsigned long flags;
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
hdsp->playback_pid = -1;
hdsp->playback_substream = NULL;
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
- unsigned long flags;
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
if (hdsp_check_for_iobox (hdsp)) {
return -EIO;
}
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
snd_pcm_set_sync(substream);
hdsp->capture_pid = current->pid;
hdsp->capture_substream = substream;
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
static int snd_hdsp_capture_release(snd_pcm_substream_t *substream)
{
- hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
- unsigned long flags;
+ hdsp_t *hdsp = snd_pcm_substream_chip(substream);
- spin_lock_irqsave(&hdsp->lock, flags);
+ spin_lock_irq(&hdsp->lock);
hdsp->capture_pid = -1;
hdsp->capture_substream = NULL;
- spin_unlock_irqrestore(&hdsp->lock, flags);
+ spin_unlock_irq(&hdsp->lock);
return 0;
}
}
+/* helper functions for copying meter values */
+static inline int copy_u32_le(void __user *dest, void __iomem *src)
+{
+ u32 val = readl(src);
+ return copy_to_user(dest, &val, 4);
+}
+
+static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
+{
+ u32 rms_low, rms_high;
+ u64 rms;
+ rms_low = readl(src_low);
+ rms_high = readl(src_high);
+ rms = ((u64)rms_high << 32) | rms_low;
+ return copy_to_user(dest, &rms, 8);
+}
+
+static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
+{
+ u32 rms_low, rms_high;
+ u64 rms;
+ rms_low = readl(src_low) & 0xffffff00;
+ rms_high = readl(src_high) & 0xffffff00;
+ rms = ((u64)rms_high << 32) | rms_low;
+ return copy_to_user(dest, &rms, 8);
+}
+
+static int hdsp_9652_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+{
+ int doublespeed = 0;
+ int i, j, channels, ofs;
+
+ if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
+ doublespeed = 1;
+ channels = doublespeed ? 14 : 26;
+ for (i = 0, j = 0; i < 26; ++i) {
+ if (doublespeed && (i & 4))
+ continue;
+ ofs = HDSP_9652_peakBase - j * 4;
+ if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs))
+ return -EFAULT;
+ ofs -= channels * 4;
+ if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs))
+ return -EFAULT;
+ ofs -= channels * 4;
+ if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs))
+ return -EFAULT;
+ ofs = HDSP_9652_rmsBase + j * 8;
+ if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs,
+ hdsp->iobase + ofs + 4))
+ return -EFAULT;
+ ofs += channels * 8;
+ if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs,
+ hdsp->iobase + ofs + 4))
+ return -EFAULT;
+ ofs += channels * 8;
+ if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs,
+ hdsp->iobase + ofs + 4))
+ return -EFAULT;
+ j++;
+ }
+ return 0;
+}
+
+static int hdsp_9632_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+{
+ int i, j;
+ hdsp_9632_meters_t __iomem *m;
+ int doublespeed = 0;
+
+ if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
+ doublespeed = 1;
+ m = (hdsp_9632_meters_t __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
+ for (i = 0, j = 0; i < 16; ++i, ++j) {
+ if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j]))
+ return -EFAULT;
+ if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j]))
+ return -EFAULT;
+ if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j]))
+ return -EFAULT;
+ if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j],
+ &m->input_rms_high[j]))
+ return -EFAULT;
+ if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j],
+ &m->playback_rms_high[j]))
+ return -EFAULT;
+ if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j],
+ &m->output_rms_high[j]))
+ return -EFAULT;
+ if (doublespeed && i == 3) i += 4;
+ }
+ return 0;
+}
+
+static int hdsp_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+{
+ int i;
+
+ for (i = 0; i < 26; i++) {
+ if (copy_u32_le(&peak_rms->playback_peaks[i],
+ hdsp->iobase + HDSP_playbackPeakLevel + i * 4))
+ return -EFAULT;
+ if (copy_u32_le(&peak_rms->input_peaks[i],
+ hdsp->iobase + HDSP_inputPeakLevel + i * 4))
+ return -EFAULT;
+ }
+ for (i = 0; i < 28; i++) {
+ if (copy_u32_le(&peak_rms->output_peaks[i],
+ hdsp->iobase + HDSP_outputPeakLevel + i * 4))
+ return -EFAULT;
+ }
+ for (i = 0; i < 26; ++i) {
+ if (copy_u64_le(&peak_rms->playback_rms[i],
+ hdsp->iobase + HDSP_playbackRmsLevel + i * 8,
+ hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4))
+ return -EFAULT;
+ if (copy_u64_le(&peak_rms->input_rms[i],
+ hdsp->iobase + HDSP_inputRmsLevel + i * 8,
+ hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4))
+ return -EFAULT;
+ }
+ return 0;
+}
+
static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int cmd, unsigned long arg)
{
hdsp_t *hdsp = (hdsp_t *)hw->private_data;
switch (cmd) {
case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
- hdsp_peak_rms_t __user *peak_rms;
- int i;
-
- if (hdsp->io_type == H9652) {
- unsigned long rms_low, rms_high;
- int doublespeed = 0;
- if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
- doublespeed = 1;
- peak_rms = (hdsp_peak_rms_t __user *)arg;
- for (i = 0; i < 26; ++i) {
- if (!(doublespeed && (i & 4))) {
- if (copy_to_user_fromio((void __user *)peak_rms->input_peaks+i*4, hdsp->iobase+HDSP_9652_peakBase-i*4, 4) != 0)
- return -EFAULT;
- if (copy_to_user_fromio((void __user *)peak_rms->playback_peaks+i*4, hdsp->iobase+HDSP_9652_peakBase-(doublespeed ? 14 : 26)*4-i*4, 4) != 0)
- return -EFAULT;
- if (copy_to_user_fromio((void __user *)peak_rms->output_peaks+i*4, hdsp->iobase+HDSP_9652_peakBase-2*(doublespeed ? 14 : 26)*4-i*4, 4) != 0)
- return -EFAULT;
- rms_low = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+i*8) & 0xFFFFFF00;
- rms_high = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+i*8+4) & 0xFFFFFF00;
- rms_high += (rms_low >> 24);
- rms_low <<= 8;
- if (copy_to_user((void __user *)peak_rms->input_rms+i*8, &rms_low, 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->input_rms+i*8+4, &rms_high, 4) != 0)
- return -EFAULT;
- rms_low = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+(doublespeed ? 14 : 26)*8+i*8) & 0xFFFFFF00;
- rms_high = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+(doublespeed ? 14 : 26)*8+i*8+4) & 0xFFFFFF00;
- rms_high += (rms_low >> 24);
- rms_low <<= 8;
- if (copy_to_user((void __user *)peak_rms->playback_rms+i*8, &rms_low, 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->playback_rms+i*8+4, &rms_high, 4) != 0)
- return -EFAULT;
- rms_low = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+2*(doublespeed ? 14 : 26)*8+i*8) & 0xFFFFFF00;
- rms_high = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+2*(doublespeed ? 14 : 26)*8+i*8+4) & 0xFFFFFF00;
- rms_high += (rms_low >> 24);
- rms_low <<= 8;
- if (copy_to_user((void __user *)peak_rms->output_rms+i*8, &rms_low, 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->output_rms+i*8+4, &rms_high, 4) != 0)
- return -EFAULT;
- }
- }
- return 0;
- }
- if (hdsp->io_type == H9632) {
- int j;
- hdsp_9632_meters_t *m;
- int doublespeed = 0;
- if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
- doublespeed = 1;
- m = (hdsp_9632_meters_t *)(hdsp->iobase+HDSP_9632_metersBase);
- peak_rms = (hdsp_peak_rms_t __user *)arg;
- for (i = 0, j = 0; i < 16; ++i, ++j) {
- if (copy_to_user((void __user *)peak_rms->input_peaks+i*4, &(m->input_peak[j]), 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->playback_peaks+i*4, &(m->playback_peak[j]), 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->output_peaks+i*4, &(m->output_peak[j]), 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->input_rms+i*8, &(m->input_rms_low[j]), 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->playback_rms+i*8, &(m->playback_rms_low[j]), 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->output_rms+i*8, &(m->output_rms_low[j]), 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->input_rms+i*8+4, &(m->input_rms_high[j]), 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->playback_rms+i*8+4, &(m->playback_rms_high[j]), 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->output_rms+i*8+4, &(m->output_rms_high[j]), 4) != 0)
- return -EFAULT;
- if (doublespeed && i == 3) i += 4;
- }
- return 0;
- }
+ hdsp_peak_rms_t __user *peak_rms = (hdsp_peak_rms_t __user *)arg;
+
if (!(hdsp->state & HDSP_FirmwareLoaded)) {
- snd_printk("firmware needs to be uploaded to the card.\n");
+ snd_printk(KERN_ERR "firmware needs to be uploaded to the card.\n");
return -EINVAL;
}
- peak_rms = (hdsp_peak_rms_t __user *)arg;
- for (i = 0; i < 26; ++i) {
- if (copy_to_user((void __user *)peak_rms->playback_peaks+i*4, (void *)hdsp->iobase+HDSP_playbackPeakLevel+i*4, 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->input_peaks+i*4, (void *)hdsp->iobase+HDSP_inputPeakLevel+i*4, 4) != 0)
- return -EFAULT;
- }
- for (i = 0; i < 26; ++i) {
- if (copy_to_user((void __user *)peak_rms->playback_rms+i*8+4, (void *)hdsp->iobase+HDSP_playbackRmsLevel+i*8, 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->playback_rms+i*8, (void *)hdsp->iobase+HDSP_playbackRmsLevel+i*8+4, 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->input_rms+i*8+4, (void *)hdsp->iobase+HDSP_inputRmsLevel+i*8, 4) != 0)
- return -EFAULT;
- if (copy_to_user((void __user *)peak_rms->input_rms+i*8, (void *)hdsp->iobase+HDSP_inputRmsLevel+i*8+4, 4) != 0)
- return -EFAULT;
- }
- for (i = 0; i < 28; ++i) {
- if (copy_to_user((void __user *)peak_rms->output_peaks+i*4, (void *)hdsp->iobase+HDSP_outputPeakLevel+i*4, 4) != 0)
- return -EFAULT;
+
+ switch (hdsp->io_type) {
+ case H9652:
+ return hdsp_9652_get_peak(hdsp, peak_rms);
+ case H9632:
+ return hdsp_9632_get_peak(hdsp, peak_rms);
+ default:
+ return hdsp_get_peak(hdsp, peak_rms);
}
- break;
}
case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
hdsp_config_info_t info;
}
break;
}
+#ifndef HDSP_FW_LOADER
case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
hdsp_firmware_t __user *firmware;
- unsigned long __user *firmware_data;
+ u32 __user *firmware_data;
int err;
if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
/* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */
if (hdsp->io_type == Undefined) return -EINVAL;
+ if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
+ return -EBUSY;
+
snd_printk("initializing firmware upload\n");
firmware = (hdsp_firmware_t __user *)argp;
return -EIO;
}
- if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(unsigned long)*24413) != 0) {
+ if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) {
return -EFAULT;
}
}
break;
}
+#endif
case SNDRV_HDSP_IOCTL_GET_MIXER: {
hdsp_mixer_t __user *mixer = (hdsp_mixer_t __user *)argp;
if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
return 0;
}
-static int __devinit snd_hdsp_create_pcm(snd_card_t *card,
- hdsp_t *hdsp)
+static int snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp)
{
snd_pcm_t *pcm;
int err;
return 0;
}
-static inline void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp)
+static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp)
{
hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
}
-static inline void snd_hdsp_9652_disable_mixer (hdsp_t *hdsp)
-{
- hdsp->control2_register &= ~HDSP_9652_ENABLE_MIXER;
- hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
-}
-
-static inline int snd_hdsp_enable_io (hdsp_t *hdsp)
+static int snd_hdsp_enable_io (hdsp_t *hdsp)
{
int i;
return 0;
}
-static inline void snd_hdsp_initialize_channels(hdsp_t *hdsp)
+static void snd_hdsp_initialize_channels(hdsp_t *hdsp)
{
int status, aebi_channels, aebo_channels;
}
}
-static inline void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp)
+static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp)
{
snd_hdsp_flush_midi_input (hdsp, 0);
snd_hdsp_flush_midi_input (hdsp, 1);
}
-static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
+static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
{
int err;
return 0;
}
+#ifdef HDSP_FW_LOADER
+/* load firmware via hotplug fw loader */
+static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
+{
+ const char *fwfile;
+ const struct firmware *fw;
+ int err;
+
+ if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
+ return 0;
+ if (hdsp->io_type == Undefined) {
+ if ((err = hdsp_get_iobox_version(hdsp)) < 0)
+ return err;
+ if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
+ return 0;
+ }
+ if (hdsp_check_for_iobox (hdsp))
+ return -EIO;
+
+ /* caution: max length of firmware filename is 30! */
+ switch (hdsp->io_type) {
+ case Multiface:
+ if (hdsp->firmware_rev == 0xa)
+ fwfile = "multiface_firmware.bin";
+ else
+ fwfile = "multiface_firmware_rev11.bin";
+ break;
+ case Digiface:
+ if (hdsp->firmware_rev == 0xa)
+ fwfile = "digiface_firmware.bin";
+ else
+ fwfile = "digiface_firmware_rev11.bin";
+ break;
+ default:
+ snd_printk(KERN_ERR "hdsp: invalid io_type %d\n", hdsp->io_type);
+ return -EINVAL;
+ }
+
+ if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
+ snd_printk(KERN_ERR "hdsp: cannot load firmware %s\n", fwfile);
+ return -ENOENT;
+ }
+ if (fw->size < sizeof(hdsp->firmware_cache)) {
+ snd_printk(KERN_ERR "hdsp: too short firmware size %d (expected %d)\n",
+ (int)fw->size, (int)sizeof(hdsp->firmware_cache));
+ release_firmware(fw);
+ return -EINVAL;
+ }
+#ifdef SNDRV_BIG_ENDIAN
+ {
+ int i;
+ u32 *src = (void *)fw->data;
+ for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++)
+ hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) |
+ ((*src & 0x0000ff00) << 8) |
+ ((*src & 0x00ff0000) >> 8) |
+ ((*src & 0xff000000) >> 16);
+ }
+#else
+ memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
+#endif
+ release_firmware(fw);
+
+ hdsp->state |= HDSP_FirmwareCached;
+
+ if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
+ return err;
+
+ if (!(hdsp->state & HDSP_InitializationComplete)) {
+ snd_hdsp_initialize_channels(hdsp);
+ snd_hdsp_initialize_midi_flush(hdsp);
+ if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
+ snd_printk("error creating alsa devices\n");
+ return err;
+ }
+ }
+ return 0;
+}
+#endif
+
static int __devinit snd_hdsp_create(snd_card_t *card,
hdsp_t *hdsp,
int precise_ptr)
hdsp->irq = -1;
hdsp->state = 0;
- hdsp->midi[0].rmidi = 0;
- hdsp->midi[1].rmidi = 0;
- hdsp->midi[0].input = 0;
- hdsp->midi[1].input = 0;
- hdsp->midi[0].output = 0;
- hdsp->midi[1].output = 0;
+ hdsp->midi[0].rmidi = NULL;
+ hdsp->midi[1].rmidi = NULL;
+ hdsp->midi[0].input = NULL;
+ hdsp->midi[1].input = NULL;
+ hdsp->midi[0].output = NULL;
+ hdsp->midi[1].output = NULL;
spin_lock_init(&hdsp->midi[0].lock);
spin_lock_init(&hdsp->midi[1].lock);
- hdsp->iobase = 0;
- hdsp->res_port = 0;
+ hdsp->iobase = NULL;
hdsp->control_register = 0;
hdsp->control2_register = 0;
hdsp->io_type = Undefined;
pci_set_master(hdsp->pci);
+ if ((err = pci_request_regions(pci, "hdsp")) < 0)
+ return err;
hdsp->port = pci_resource_start(pci, 0);
-
- if ((hdsp->res_port = request_mem_region(hdsp->port, HDSP_IO_EXTENT, "hdsp")) == NULL) {
- snd_printk("unable to grab memory region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
- return -EBUSY;
- }
-
- if ((hdsp->iobase = (unsigned long) ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == 0) {
+ if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
snd_printk("unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
return -EBUSY;
}
}
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
+#ifdef HDSP_FW_LOADER
+ if ((err = hdsp_request_fw_loader(hdsp)) < 0)
+ return err;
+#else
snd_printk("card initialization pending : waiting for firmware\n");
if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
return err;
}
return 0;
+#endif
}
snd_printk("Firmware already loaded, initializing card.\n");
static int snd_hdsp_free(hdsp_t *hdsp)
{
- if (hdsp->res_port) {
+ if (hdsp->port) {
/* stop the audio, and cancel all interrupts */
hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
snd_hdsp_free_buffers(hdsp);
if (hdsp->iobase)
- iounmap((void *) hdsp->iobase);
+ iounmap(hdsp->iobase);
- if (hdsp->res_port) {
- release_resource(hdsp->res_port);
- kfree_nocheck(hdsp->res_port);
- }
+ if (hdsp->port)
+ pci_release_regions(hdsp->pci);
+ pci_disable_device(hdsp->pci);
return 0;
}