diff options
Diffstat (limited to 'sound/pci/rme9652/hdsp.c')
| -rw-r--r-- | sound/pci/rme9652/hdsp.c | 2072 |
1 files changed, 1210 insertions, 862 deletions
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index d3e07de433b..4c6f5d1c988 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -21,14 +21,14 @@ * */ -#include <sound/driver.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/interrupt.h> -#include <linux/slab.h> #include <linux/pci.h> #include <linux/firmware.h> -#include <linux/moduleparam.h> +#include <linux/module.h> +#include <linux/math64.h> +#include <linux/vmalloc.h> #include <sound/core.h> #include <sound/control.h> @@ -46,7 +46,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ +static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface."); @@ -60,6 +60,11 @@ 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"); +MODULE_FIRMWARE("digiface_firmware.bin"); +MODULE_FIRMWARE("digiface_firmware_rev11.bin"); #define HDSP_MAX_CHANNELS 26 #define HDSP_MAX_DS_CHANNELS 14 @@ -76,10 +81,12 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define H9632_SS_CHANNELS 12 #define H9632_DS_CHANNELS 8 #define H9632_QS_CHANNELS 4 +#define RPM_CHANNELS 6 /* Write registers. These are defined as byte-offsets from the iobase value. */ #define HDSP_resetPointer 0 +#define HDSP_freqReg 0 #define HDSP_outputBufferAddress 32 #define HDSP_inputBufferAddress 36 #define HDSP_controlRegister 64 @@ -97,8 +104,6 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define HDSP_statusRegister 0 #define HDSP_timecode 128 #define HDSP_status2Register 192 -#define HDSP_midiDataOut0 352 -#define HDSP_midiDataOut1 356 #define HDSP_midiDataIn0 360 #define HDSP_midiDataIn1 364 #define HDSP_midiStatusOut0 384 @@ -109,7 +114,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," /* the meters are regular i/o-mapped registers, but offset considerably from the rest. the peak registers are reset - when read; the least-significant 4 bits are full-scale counters; + when read; the least-significant 4 bits are full-scale counters; the actual peak value is in the most-significant 24 bits. */ @@ -127,7 +132,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," 26*3 values are read in ss mode 14*3 in ds mode, with no gap between values */ -#define HDSP_9652_peakBase 7164 +#define HDSP_9652_peakBase 7164 #define HDSP_9652_rmsBase 4096 /* c.f. the hdsp_9632_meters_t struct */ @@ -145,14 +150,17 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define HDSP_PROGRAM 0x020 #define HDSP_CONFIG_MODE_0 0x040 #define HDSP_CONFIG_MODE_1 0x080 -#define HDSP_VERSION_BIT 0x100 +#define HDSP_VERSION_BIT (0x100 | HDSP_S_LOAD) #define HDSP_BIGENDIAN_MODE 0x200 #define HDSP_RD_MULTIPLE 0x400 #define HDSP_9652_ENABLE_MIXER 0x800 +#define HDSP_S200 0x800 +#define HDSP_S300 (0x100 | HDSP_S200) /* dummy, purpose of 0x100 unknown */ +#define HDSP_CYCLIC_MODE 0x1000 #define HDSP_TDO 0x10000000 -#define HDSP_S_PROGRAM (HDSP_PROGRAM|HDSP_CONFIG_MODE_0) -#define HDSP_S_LOAD (HDSP_PROGRAM|HDSP_CONFIG_MODE_1) +#define HDSP_S_PROGRAM (HDSP_CYCLIC_MODE|HDSP_PROGRAM|HDSP_CONFIG_MODE_0) +#define HDSP_S_LOAD (HDSP_CYCLIC_MODE|HDSP_PROGRAM|HDSP_CONFIG_MODE_1) /* Control Register bits */ @@ -169,12 +177,12 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */ #define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */ #define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */ -#define HDSP_SyncRef2 (1<<13) -#define HDSP_SPDIFInputSelect0 (1<<14) -#define HDSP_SPDIFInputSelect1 (1<<15) -#define HDSP_SyncRef0 (1<<16) +#define HDSP_SyncRef2 (1<<13) +#define HDSP_SPDIFInputSelect0 (1<<14) +#define HDSP_SPDIFInputSelect1 (1<<15) +#define HDSP_SyncRef0 (1<<16) #define HDSP_SyncRef1 (1<<17) -#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */ +#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */ #define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */ #define HDSP_Midi0InterruptEnable (1<<22) #define HDSP_Midi1InterruptEnable (1<<23) @@ -187,6 +195,25 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define HDSP_PhoneGain1 (1<<30) #define HDSP_QuadSpeed (1<<31) +/* RPM uses some of the registers for special purposes */ +#define HDSP_RPM_Inp12 0x04A00 +#define HDSP_RPM_Inp12_Phon_6dB 0x00800 /* Dolby */ +#define HDSP_RPM_Inp12_Phon_0dB 0x00000 /* .. */ +#define HDSP_RPM_Inp12_Phon_n6dB 0x04000 /* inp_0 */ +#define HDSP_RPM_Inp12_Line_0dB 0x04200 /* Dolby+PRO */ +#define HDSP_RPM_Inp12_Line_n6dB 0x00200 /* PRO */ + +#define HDSP_RPM_Inp34 0x32000 +#define HDSP_RPM_Inp34_Phon_6dB 0x20000 /* SyncRef1 */ +#define HDSP_RPM_Inp34_Phon_0dB 0x00000 /* .. */ +#define HDSP_RPM_Inp34_Phon_n6dB 0x02000 /* SyncRef2 */ +#define HDSP_RPM_Inp34_Line_0dB 0x30000 /* SyncRef1+SyncRef0 */ +#define HDSP_RPM_Inp34_Line_n6dB 0x10000 /* SyncRef0 */ + +#define HDSP_RPM_Bypass 0x01000 + +#define HDSP_RPM_Disconnect 0x00001 + #define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1) #define HDSP_ADGainMinus10dBV HDSP_ADGainMask #define HDSP_ADGainPlus4dBu (HDSP_ADGain0) @@ -274,6 +301,11 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0) #define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1) #define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0) +/* RME says n = 104857600000000, but in the windows MADI driver, I see: + return 104857600000000 / rate; // 100 MHz + return 110100480000000 / rate; // 105 MHz +*/ +#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) @@ -305,10 +337,14 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define HDSP_TimecodeSync (1<<27) #define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */ #define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */ -#define HDSP_midi0IRQPending (1<<30) +#define HDSP_midi0IRQPending (1<<30) #define HDSP_midi1IRQPending (1<<31) #define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2) +#define HDSP_spdifFrequencyMask_9632 (HDSP_spdifFrequency0|\ + HDSP_spdifFrequency1|\ + HDSP_spdifFrequency2|\ + HDSP_spdifFrequency3) #define HDSP_spdifFrequency32KHz (HDSP_spdifFrequency0) #define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1) @@ -319,7 +355,9 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define HDSP_spdifFrequency96KHz (HDSP_spdifFrequency2|HDSP_spdifFrequency1) /* This is for H9632 cards */ -#define HDSP_spdifFrequency128KHz HDSP_spdifFrequencyMask +#define HDSP_spdifFrequency128KHz (HDSP_spdifFrequency0|\ + HDSP_spdifFrequency1|\ + HDSP_spdifFrequency2) #define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3 #define HDSP_spdifFrequency192KHz (HDSP_spdifFrequency3|HDSP_spdifFrequency0) @@ -376,7 +414,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_CHANNEL_BUFFER_SAMPLES) /* the size of the area we need to allocate for DMA transfers. the - size is the same regardless of the number of channels - the + size is the same regardless of the number of channels - the Multiface still uses the same memory area. Note that we allocate 1 more channel than is apparently needed @@ -387,12 +425,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," #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) -#if !defined(HDSP_USE_HWDEP_LOADER) && !defined(CONFIG_SND_HDSP) -#define HDSP_FW_LOADER -#endif -#endif +#define HDSP_FIRMWARE_SIZE (24413 * 4) struct hdsp_9632_meters { u32 input_peak[16]; @@ -435,17 +468,18 @@ struct hdsp { u32 creg_spdif; u32 creg_spdif_stream; int clock_source_locked; - char *card_name; /* digiface/multiface */ + char *card_name; /* digiface/multiface/rpm */ enum HDSP_IO_Type io_type; /* ditto, but for code use */ unsigned short firmware_rev; unsigned short state; /* stores state bits */ - u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */ + const struct firmware *firmware; + u32 *fw_uploaded; size_t period_bytes; /* guess what this is */ unsigned char max_channels; unsigned char qs_in_channels; /* quad speed mode for H9632 */ unsigned char ds_in_channels; unsigned char ss_in_channels; /* different for multiface/digiface */ - unsigned char qs_out_channels; + unsigned char qs_out_channels; unsigned char ds_out_channels; unsigned char ss_out_channels; @@ -469,6 +503,7 @@ struct hdsp { struct pci_dev *pci; struct snd_kcontrol *spdif_ctl; unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE]; + unsigned int dds_value; /* last value written to freq register */ }; /* These tables map the ALSA channels 1..N to the channels that we @@ -486,9 +521,9 @@ static char channel_map_df_ss[HDSP_MAX_CHANNELS] = { static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */ /* Analog */ - 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, /* ADAT 2 */ - 16, 17, 18, 19, 20, 21, 22, 23, + 16, 17, 18, 19, 20, 21, 22, 23, /* SPDIF */ 24, 25, -1, -1, -1, -1, -1, -1, -1, -1 @@ -509,11 +544,11 @@ static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = { /* SPDIF */ 8, 9, /* Analog */ - 10, 11, + 10, 11, /* AO4S-192 and AI4S-192 extension boards */ 12, 13, 14, 15, /* others don't exist */ - -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; @@ -523,7 +558,7 @@ static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = { /* SPDIF */ 8, 9, /* Analog */ - 10, 11, + 10, 11, /* AO4S-192 and AI4S-192 extension boards */ 12, 13, 14, 15, /* others don't exist */ @@ -549,10 +584,6 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer { 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 (dmab->bytes >= size) - return 0; - } if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), size, dmab) < 0) return -ENOMEM; @@ -561,17 +592,15 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) { - if (dmab->area) { - dmab->dev.dev = NULL; /* make it anonymous */ - snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci)); - } + if (dmab->area) + snd_dma_free_pages(dmab); } -static struct pci_device_id snd_hdsp_ids[] = { +static DEFINE_PCI_DEVICE_TABLE(snd_hdsp_ids) = { { .vendor = PCI_VENDOR_ID_XILINX, - .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, + .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, /* RME Hammerfall-DSP */ @@ -593,26 +622,36 @@ static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp); static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out) { - switch (hdsp->firmware_rev) { - case 0xa: - return (64 * out) + (32 + (in)); - case 0x96: - case 0x97: - return (32 * out) + (16 + (in)); + switch (hdsp->io_type) { + case Multiface: + case Digiface: + case RPM: default: + if (hdsp->firmware_rev == 0xa) + return (64 * out) + (32 + (in)); + else + return (52 * out) + (26 + (in)); + case H9632: + return (32 * out) + (16 + (in)); + case H9652: return (52 * out) + (26 + (in)); } } static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out) { - switch (hdsp->firmware_rev) { - case 0xa: - return (64 * out) + in; - case 0x96: - case 0x97: - return (32 * out) + in; + switch (hdsp->io_type) { + case Multiface: + case Digiface: + case RPM: default: + if (hdsp->firmware_rev == 0xa) + return (64 * out) + in; + else + return (52 * out) + in; + case H9632: + return (32 * out) + in; + case H9652: return (52 * out) + in; } } @@ -629,67 +668,112 @@ static unsigned int hdsp_read(struct hdsp *hdsp, int reg) static int hdsp_check_for_iobox (struct hdsp *hdsp) { + int i; if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; - if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) { - snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n"); - hdsp->state &= ~HDSP_FirmwareLoaded; - return -EIO; + for (i = 0; i < 500; i++) { + if (0 == (hdsp_read(hdsp, HDSP_statusRegister) & + HDSP_ConfigError)) { + if (i) { + dev_dbg(hdsp->card->dev, + "IO box found after %d ms\n", + (20 * i)); + } + return 0; + } + msleep(20); } - return 0; + dev_err(hdsp->card->dev, "no IO box connected!\n"); + hdsp->state &= ~HDSP_FirmwareLoaded; + return -EIO; +} +static int hdsp_wait_for_iobox(struct hdsp *hdsp, unsigned int loops, + unsigned int delay) +{ + unsigned int i; + + if (hdsp->io_type == H9652 || hdsp->io_type == H9632) + return 0; + + for (i = 0; i != loops; ++i) { + if (hdsp_read(hdsp, HDSP_statusRegister) & HDSP_ConfigError) + msleep(delay); + else { + dev_dbg(hdsp->card->dev, "iobox found after %ums!\n", + i * delay); + return 0; + } + } + + dev_info(hdsp->card->dev, "no IO box connected!\n"); + hdsp->state &= ~HDSP_FirmwareLoaded; + return -EIO; } static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { int i; unsigned long flags; + const u32 *cache; + + if (hdsp->fw_uploaded) + cache = hdsp->fw_uploaded; + else { + if (!hdsp->firmware) + return -ENODEV; + cache = (u32 *)hdsp->firmware->data; + if (!cache) + return -ENODEV; + } if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - - snd_printk ("Hammerfall-DSP: loading firmware\n"); + + dev_info(hdsp->card->dev, "loading firmware\n"); hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM); hdsp_write (hdsp, HDSP_fifoData, 0); - + if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { - snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n"); + dev_info(hdsp->card->dev, + "timeout waiting for download preparation\n"); + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200); return -EIO; } - + hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); - - for (i = 0; i < 24413; ++i) { - hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]); + + for (i = 0; i < HDSP_FIRMWARE_SIZE / 4; ++i) { + hdsp_write(hdsp, HDSP_fifoData, cache[i]); if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { - snd_printk ("Hammerfall-DSP: timeout during firmware loading\n"); + dev_info(hdsp->card->dev, + "timeout during firmware loading\n"); + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200); return -EIO; } } - ssleep(3); - - if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { - snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n"); - return -EIO; - } + hdsp_fifo_wait(hdsp, 3, HDSP_LONG_WAIT); + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200); + ssleep(3); #ifdef SNDRV_BIG_ENDIAN hdsp->control2_register = HDSP_BIGENDIAN_MODE; #else hdsp->control2_register = 0; #endif hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); - snd_printk ("Hammerfall-DSP: finished firmware loading\n"); - + dev_info(hdsp->card->dev, "finished firmware loading\n"); + } if (hdsp->state & HDSP_InitializationComplete) { - snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n"); + dev_info(hdsp->card->dev, + "firmware loaded from cache, restoring defaults\n"); spin_lock_irqsave(&hdsp->lock, flags); snd_hdsp_set_defaults(hdsp); - spin_unlock_irqrestore(&hdsp->lock, flags); + spin_unlock_irqrestore(&hdsp->lock, flags); } - + hdsp->state |= HDSP_FirmwareLoaded; return 0; @@ -698,26 +782,57 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { static int hdsp_get_iobox_version (struct hdsp *hdsp) { if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - - hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM); - hdsp_write (hdsp, HDSP_fifoData, 0); - if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) - return -EIO; - hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); - hdsp_write (hdsp, HDSP_fifoData, 0); + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); + hdsp_write(hdsp, HDSP_fifoData, 0); + + if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) { + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300); + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); + } - if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) { + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200 | HDSP_PROGRAM); + hdsp_write (hdsp, HDSP_fifoData, 0); + if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) { hdsp->io_type = Multiface; - hdsp_write (hdsp, HDSP_control2Reg, HDSP_VERSION_BIT); - hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); - hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT); - } else { + dev_info(hdsp->card->dev, "Multiface found\n"); + return 0; + } + + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); + hdsp_write(hdsp, HDSP_fifoData, 0); + if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) { hdsp->io_type = Digiface; - } + dev_info(hdsp->card->dev, "Digiface found\n"); + return 0; + } + + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300); + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); + hdsp_write(hdsp, HDSP_fifoData, 0); + if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) { + hdsp->io_type = Multiface; + dev_info(hdsp->card->dev, "Multiface found\n"); + return 0; + } + + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300); + hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); + hdsp_write(hdsp, HDSP_fifoData, 0); + if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) { + hdsp->io_type = Multiface; + dev_info(hdsp->card->dev, "Multiface found\n"); + return 0; + } + + hdsp->io_type = RPM; + dev_info(hdsp->card->dev, "RPM found\n"); + return 0; } else { /* firmware was already loaded, get iobox type */ - if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) + if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2) + hdsp->io_type = RPM; + else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) hdsp->io_type = Multiface; else hdsp->io_type = Digiface; @@ -726,9 +841,7 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) } -#ifdef HDSP_FW_LOADER -static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp); -#endif +static int hdsp_request_fw_loader(struct hdsp *hdsp); static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) { @@ -738,22 +851,18 @@ static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) hdsp->state &= ~HDSP_FirmwareLoaded; if (! load_on_demand) return -EIO; - snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); + dev_err(hdsp->card->dev, "firmware not present.\n"); /* try to load firmware */ if (! (hdsp->state & HDSP_FirmwareCached)) { -#ifdef HDSP_FW_LOADER if (! hdsp_request_fw_loader(hdsp)) return 0; -#endif - snd_printk(KERN_ERR - "Hammerfall-DSP: No firmware loaded nor " - "cached, please upload firmware.\n"); + dev_err(hdsp->card->dev, + "No firmware loaded nor cached, please upload firmware.\n"); return -EIO; } if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk(KERN_ERR - "Hammerfall-DSP: Firmware loading from " - "cache failed, please upload manually.\n"); + dev_err(hdsp->card->dev, + "Firmware loading from cache failed, please upload manually.\n"); return -EIO; } } @@ -762,13 +871,13 @@ static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout) -{ +{ int i; /* the fifoStatus registers reports on how many words are available in the command FIFO. */ - + for (i = 0; i < timeout; i++) { if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count) @@ -781,7 +890,8 @@ static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout) udelay (100); } - snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n", + dev_warn(hdsp->card->dev, + "wait for FIFO status <= %d failed after %d iterations\n", count, timeout); return -1; } @@ -800,11 +910,11 @@ static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short if (addr >= HDSP_MATRIX_MIXER_SIZE) return -1; - + if (hdsp->io_type == H9652 || hdsp->io_type == H9632) { /* from martin bjornsen: - + "You can only write dwords to the mixer memory which contain two mixer values in the low and high @@ -823,7 +933,7 @@ static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short hdsp->mixer_matrix[addr] = data; - + /* `addr' addresses a 16-bit wide address, but the address space accessed via hdsp_write uses byte offsets. put another way, addr @@ -832,17 +942,17 @@ static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short to access 0 to 2703 ... */ ad = addr/2; - - hdsp_write (hdsp, 4096 + (ad*4), - (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) + + + hdsp_write (hdsp, 4096 + (ad*4), + (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) + hdsp->mixer_matrix[addr&0x7fe]); - + return 0; } else { ad = (addr << 16) + data; - + if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) return -1; @@ -867,31 +977,18 @@ static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp) return ret; } -static int hdsp_external_sample_rate (struct hdsp *hdsp) -{ - unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register); - unsigned int rate_bits = status2 & HDSP_systemFrequencyMask; - - switch (rate_bits) { - case HDSP_systemFrequency32: return 32000; - case HDSP_systemFrequency44_1: return 44100; - case HDSP_systemFrequency48: return 48000; - case HDSP_systemFrequency64: return 64000; - case HDSP_systemFrequency88_2: return 88200; - case HDSP_systemFrequency96: return 96000; - default: - return 0; - } -} - static int hdsp_spdif_sample_rate(struct hdsp *hdsp) { unsigned int status = hdsp_read(hdsp, HDSP_statusRegister); unsigned int rate_bits = (status & HDSP_spdifFrequencyMask); + /* For the 9632, the mask is different */ + if (hdsp->io_type == H9632) + rate_bits = (status & HDSP_spdifFrequencyMask_9632); + if (status & HDSP_SPDIFErrorFlag) return 0; - + switch (rate_bits) { case HDSP_spdifFrequency32KHz: return 32000; case HDSP_spdifFrequency44_1KHz: return 44100; @@ -899,22 +996,49 @@ static int hdsp_spdif_sample_rate(struct hdsp *hdsp) case HDSP_spdifFrequency64KHz: return 64000; case HDSP_spdifFrequency88_2KHz: return 88200; case HDSP_spdifFrequency96KHz: return 96000; - case HDSP_spdifFrequency128KHz: + case HDSP_spdifFrequency128KHz: if (hdsp->io_type == H9632) return 128000; break; - case HDSP_spdifFrequency176_4KHz: + case HDSP_spdifFrequency176_4KHz: if (hdsp->io_type == H9632) return 176400; break; - case HDSP_spdifFrequency192KHz: + case HDSP_spdifFrequency192KHz: if (hdsp->io_type == H9632) return 192000; break; default: break; } - snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status); + dev_warn(hdsp->card->dev, + "unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", + rate_bits, status); return 0; } +static int hdsp_external_sample_rate(struct hdsp *hdsp) +{ + unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register); + unsigned int rate_bits = status2 & HDSP_systemFrequencyMask; + + /* For the 9632 card, there seems to be no bit for indicating external + * sample rate greater than 96kHz. The card reports the corresponding + * single speed. So the best means seems to get spdif rate when + * autosync reference is spdif */ + if (hdsp->io_type == H9632 && + hdsp_autosync_ref(hdsp) == HDSP_AUTOSYNC_FROM_SPDIF) + return hdsp_spdif_sample_rate(hdsp); + + switch (rate_bits) { + case HDSP_systemFrequency32: return 32000; + case HDSP_systemFrequency44_1: return 44100; + case HDSP_systemFrequency48: return 48000; + case HDSP_systemFrequency64: return 64000; + case HDSP_systemFrequency88_2: return 88200; + case HDSP_systemFrequency96: return 96000; + default: + return 0; + } +} + static void hdsp_compute_period_size(struct hdsp *hdsp) { hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8)); @@ -938,6 +1062,11 @@ static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp) static void hdsp_reset_hw_pointer(struct hdsp *hdsp) { hdsp_write (hdsp, HDSP_resetPointer, 0); + if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152) + /* HDSP_resetPointer = HDSP_freqReg, which is strange and + * requires (?) to write again DDS value after a reset pointer + * (at least, it works like this) */ + hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value); } static void hdsp_start_audio(struct hdsp *s) @@ -982,6 +1111,25 @@ static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames) return 0; } +static void hdsp_set_dds_value(struct hdsp *hdsp, int rate) +{ + u64 n; + + if (rate >= 112000) + rate /= 4; + else if (rate >= 56000) + rate /= 2; + + n = DDS_NUMERATOR; + n = div_u64(n, rate); + /* n should be less than 2^32 for being written to FREQ register */ + snd_BUG_ON(n >> 32); + /* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS + value to write it after a reset */ + hdsp->dds_value = n; + hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value); +} + static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) { int reject_if_open = 0; @@ -992,35 +1140,39 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) there is no need for it (e.g. during module initialization). */ - - if (!(hdsp->control_register & HDSP_ClockModeMaster)) { + + if (!(hdsp->control_register & HDSP_ClockModeMaster)) { if (called_internally) { /* request from ctl or card initialization */ - snd_printk(KERN_ERR "Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n"); + dev_err(hdsp->card->dev, + "device is not running as a clock master: cannot set sample rate.\n"); return -1; - } else { + } else { /* hw_param request while in AutoSync mode */ int external_freq = hdsp_external_sample_rate(hdsp); int spdif_freq = hdsp_spdif_sample_rate(hdsp); - + if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) - snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n"); + dev_info(hdsp->card->dev, + "Detected ADAT in double speed mode\n"); else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) - snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n"); + dev_info(hdsp->card->dev, + "Detected ADAT in quad speed mode\n"); else if (rate != external_freq) { - snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n"); + dev_info(hdsp->card->dev, + "No AutoSync source for requested rate\n"); return -1; - } - } + } + } } current_rate = hdsp->system_sample_rate; /* Changing from a "single speed" to a "double speed" rate is not allowed if any substreams are open. This is because - such a change causes a shift in the location of + such a change causes a shift in the location of the DMA buffers and a reduction in the number of available - buffers. + buffers. Note that a similar but essentially insoluble problem exists for externally-driven rate changes. All we can do @@ -1028,7 +1180,7 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) if (rate > 96000 && hdsp->io_type != H9632) return -EINVAL; - + switch (rate) { case 32000: if (current_rate > 48000) @@ -1080,7 +1232,8 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) } if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) { - snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n", + dev_warn(hdsp->card->dev, + "cannot change speed mode (capture PID = %d, playback PID = %d)\n", hdsp->capture_pid, hdsp->playback_pid); return -EBUSY; @@ -1090,6 +1243,10 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) hdsp->control_register |= rate_bits; hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + /* For HDSP9632 rev 152, need to set DDS value in FREQ register */ + if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152) + hdsp_set_dds_value(hdsp, rate); + if (rate >= 128000) { hdsp->channel_map = channel_map_H9632_qs; } else if (rate > 48000) { @@ -1099,6 +1256,7 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) hdsp->channel_map = channel_map_ds; } else { switch (hdsp->io_type) { + case RPM: case Multiface: hdsp->channel_map = channel_map_mf_ss; break; @@ -1114,7 +1272,7 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) break; } } - + hdsp->system_sample_rate = rate; return 0; @@ -1180,16 +1338,16 @@ static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) unsigned char buf[128]; /* Output is not interrupt driven */ - + 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) { if (n_pending > (int)sizeof (buf)) n_pending = sizeof (buf); - + if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { - for (i = 0; i < to_write; ++i) + for (i = 0; i < to_write; ++i) snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]); } } @@ -1260,14 +1418,14 @@ static void snd_hdsp_midi_output_timer(unsigned long data) { struct hdsp_midi *hmidi = (struct hdsp_midi *) data; unsigned long flags; - + snd_hdsp_midi_output_write(hmidi); spin_lock_irqsave (&hmidi->lock, flags); /* this does not bump hmidi->istimer, because the kernel automatically removed the timer when it expired, and we are now adding it back, thus - leaving istimer wherever it was set before. + leaving istimer wherever it was set before. */ if (hmidi->istimer) { @@ -1387,7 +1545,7 @@ static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int i if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0) return -1; - sprintf (hdsp->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1); + sprintf(hdsp->midi[id].rmidi->name, "HDSP MIDI %d", id+1); hdsp->midi[id].rmidi->private_data = &hdsp->midi[id]; snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output); @@ -1436,7 +1594,7 @@ static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif); return 0; } @@ -1446,7 +1604,7 @@ static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); int change; u32 val; - + val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); spin_lock_irq(&hdsp->lock); change = val != hdsp->creg_spdif; @@ -1465,7 +1623,7 @@ static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, str static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream); return 0; } @@ -1475,7 +1633,7 @@ static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, stru struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); int change; u32 val; - + val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); spin_lock_irq(&hdsp->lock); change = val != hdsp->creg_spdif_stream; @@ -1537,7 +1695,7 @@ static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp); return 0; } @@ -1547,7 +1705,7 @@ static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_e struct hdsp *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); @@ -1559,187 +1717,60 @@ static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_e return change; } -#define HDSP_SPDIF_OUT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_hdsp_info_spdif_bits, \ - .get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out } +#define HDSP_TOGGLE_SETTING(xname, xindex) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .private_value = xindex, \ + .info = snd_hdsp_info_toggle_setting, \ + .get = snd_hdsp_get_toggle_setting, \ + .put = snd_hdsp_put_toggle_setting \ +} -static int hdsp_spdif_out(struct hdsp *hdsp) +static int hdsp_toggle_setting(struct hdsp *hdsp, u32 regmask) { - return (hdsp->control_register & HDSP_SPDIFOpticalOut) ? 1 : 0; + return (hdsp->control_register & regmask) ? 1 : 0; } -static int hdsp_set_spdif_output(struct hdsp *hdsp, int out) +static int hdsp_set_toggle_setting(struct hdsp *hdsp, u32 regmask, int out) { if (out) - hdsp->control_register |= HDSP_SPDIFOpticalOut; + hdsp->control_register |= regmask; else - hdsp->control_register &= ~HDSP_SPDIFOpticalOut; + hdsp->control_register &= ~regmask; hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} -static int snd_hdsp_info_spdif_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; return 0; } -static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp); - return 0; -} +#define snd_hdsp_info_toggle_setting snd_ctl_boolean_mono_info -static int snd_hdsp_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hdsp_get_toggle_setting(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hdsp *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_irq(&hdsp->lock); - change = (int)val != hdsp_spdif_out(hdsp); - hdsp_set_spdif_output(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} + u32 regmask = kcontrol->private_value; -#define HDSP_SPDIF_PROFESSIONAL(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_hdsp_info_spdif_bits, \ - .get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional } - -static int hdsp_spdif_professional(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_SPDIFProfessional) ? 1 : 0; -} - -static int hdsp_set_spdif_professional(struct hdsp *hdsp, int val) -{ - if (val) - hdsp->control_register |= HDSP_SPDIFProfessional; - else - hdsp->control_register &= ~HDSP_SPDIFProfessional; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp); - return 0; -} - -static int snd_hdsp_put_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *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_irq(&hdsp->lock); - change = (int)val != hdsp_spdif_professional(hdsp); - hdsp_set_spdif_professional(hdsp, val); + ucontrol->value.integer.value[0] = hdsp_toggle_setting(hdsp, regmask); spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_SPDIF_EMPHASIS(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_hdsp_info_spdif_bits, \ - .get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis } - -static int hdsp_spdif_emphasis(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_SPDIFEmphasis) ? 1 : 0; -} - -static int hdsp_set_spdif_emphasis(struct hdsp *hdsp, int val) -{ - if (val) - hdsp->control_register |= HDSP_SPDIFEmphasis; - else - hdsp->control_register &= ~HDSP_SPDIFEmphasis; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } -static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp); - return 0; -} - -static int snd_hdsp_put_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +static int snd_hdsp_put_toggle_setting(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + u32 regmask = kcontrol->private_value; int change; unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_spdif_emphasis(hdsp); - hdsp_set_spdif_emphasis(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_SPDIF_NON_AUDIO(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_hdsp_info_spdif_bits, \ - .get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio } - -static int hdsp_spdif_nonaudio(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_SPDIFNonAudio) ? 1 : 0; -} - -static int hdsp_set_spdif_nonaudio(struct hdsp *hdsp, int val) -{ - if (val) - hdsp->control_register |= HDSP_SPDIFNonAudio; - else - hdsp->control_register &= ~HDSP_SPDIFNonAudio; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} -static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp); - return 0; -} - -static int snd_hdsp_put_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *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_irq(&hdsp->lock); - change = (int)val != hdsp_spdif_nonaudio(hdsp); - hdsp_set_spdif_nonaudio(hdsp, val); + change = (int) val != hdsp_toggle_setting(hdsp, regmask); + if (change) + hdsp_set_toggle_setting(hdsp, regmask, val); spin_unlock_irq(&hdsp->lock); return change; } @@ -1770,7 +1801,7 @@ static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + switch (hdsp_spdif_sample_rate(hdsp)) { case 32000: ucontrol->value.enumerated.item[0] = 0; @@ -1800,7 +1831,7 @@ static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct ucontrol->value.enumerated.item[0] = 9; break; default: - ucontrol->value.enumerated.item[0] = 6; + ucontrol->value.enumerated.item[0] = 6; } return 0; } @@ -1824,7 +1855,7 @@ static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struc static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate; return 0; } @@ -1841,7 +1872,7 @@ static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"}; + static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"}; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ; @@ -1854,7 +1885,7 @@ static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, str static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + switch (hdsp_external_sample_rate(hdsp)) { case 32000: ucontrol->value.enumerated.item[0] = 0; @@ -1882,9 +1913,9 @@ static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, stru break; case 192000: ucontrol->value.enumerated.item[0] = 9; - break; + break; default: - ucontrol->value.enumerated.item[0] = 6; + ucontrol->value.enumerated.item[0] = 6; } return 0; } @@ -1910,7 +1941,7 @@ static int hdsp_system_clock_mode(struct hdsp *hdsp) static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = {"Master", "Slave" }; - + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 2; @@ -1923,7 +1954,7 @@ static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp); return 0; } @@ -1960,7 +1991,7 @@ static int hdsp_clock_source(struct hdsp *hdsp) case 192000: return 9; default: - return 3; + return 3; } } else { return 0; @@ -1974,7 +2005,7 @@ static int hdsp_set_clock_source(struct hdsp *hdsp, int mode) case HDSP_CLOCK_SOURCE_AUTOSYNC: if (hdsp_external_sample_rate(hdsp) != 0) { if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) { - hdsp->control_register &= ~HDSP_ClockModeMaster; + hdsp->control_register &= ~HDSP_ClockModeMaster; hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); return 0; } @@ -1985,7 +2016,7 @@ static int hdsp_set_clock_source(struct hdsp *hdsp, int mode) break; case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ: rate = 44100; - break; + break; case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ: rate = 48000; break; @@ -2020,13 +2051,13 @@ static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ { 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" }; struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; if (hdsp->io_type == H9632) uinfo->value.enumerated.items = 10; else - uinfo->value.enumerated.items = 7; + uinfo->value.enumerated.items = 7; if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); @@ -2036,7 +2067,7 @@ static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp); return 0; } @@ -2046,7 +2077,7 @@ static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_c struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); int change; int val; - + if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.enumerated.item[0]; @@ -2067,19 +2098,12 @@ static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_c return change; } -static int snd_hdsp_info_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} +#define snd_hdsp_info_clock_source_lock snd_ctl_boolean_mono_info static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + ucontrol->value.integer.value[0] = hdsp->clock_source_locked; return 0; } @@ -2091,7 +2115,7 @@ static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked; if (change) - hdsp->clock_source_locked = ucontrol->value.integer.value[0]; + hdsp->clock_source_locked = !!ucontrol->value.integer.value[0]; return change; } @@ -2114,7 +2138,7 @@ static int hdsp_da_gain(struct hdsp *hdsp) case HDSP_DAGainMinus10dBV: return 2; default: - return 1; + return 1; } } @@ -2129,8 +2153,8 @@ static int hdsp_set_da_gain(struct hdsp *hdsp, int mode) hdsp->control_register |= HDSP_DAGainPlus4dBu; break; case 2: - hdsp->control_register |= HDSP_DAGainMinus10dBV; - break; + hdsp->control_register |= HDSP_DAGainMinus10dBV; + break; default: return -1; @@ -2142,7 +2166,7 @@ static int hdsp_set_da_gain(struct hdsp *hdsp, int mode) static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"}; - + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 3; @@ -2155,7 +2179,7 @@ static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp); return 0; } @@ -2165,7 +2189,7 @@ static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_el struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); int change; int val; - + if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.enumerated.item[0]; @@ -2199,7 +2223,7 @@ static int hdsp_ad_gain(struct hdsp *hdsp) case HDSP_ADGainLowGain: return 2; default: - return 1; + return 1; } } @@ -2211,11 +2235,11 @@ static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode) hdsp->control_register |= HDSP_ADGainMinus10dBV; break; case 1: - hdsp->control_register |= HDSP_ADGainPlus4dBu; + hdsp->control_register |= HDSP_ADGainPlus4dBu; break; case 2: - hdsp->control_register |= HDSP_ADGainLowGain; - break; + hdsp->control_register |= HDSP_ADGainLowGain; + break; default: return -1; @@ -2227,7 +2251,7 @@ static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode) static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"}; - + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 3; @@ -2240,7 +2264,7 @@ static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_e static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp); return 0; } @@ -2250,7 +2274,7 @@ static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_el struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); int change; int val; - + if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.enumerated.item[0]; @@ -2284,7 +2308,7 @@ static int hdsp_phone_gain(struct hdsp *hdsp) case HDSP_PhoneGainMinus12dB: return 2; default: - return 0; + return 0; } } @@ -2296,11 +2320,11 @@ static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode) hdsp->control_register |= HDSP_PhoneGain0dB; break; case 1: - hdsp->control_register |= HDSP_PhoneGainMinus6dB; + hdsp->control_register |= HDSP_PhoneGainMinus6dB; break; case 2: - hdsp->control_register |= HDSP_PhoneGainMinus12dB; - break; + hdsp->control_register |= HDSP_PhoneGainMinus12dB; + break; default: return -1; @@ -2312,7 +2336,7 @@ static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode) static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = {"0 dB", "-6 dB", "-12 dB"}; - + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 3; @@ -2325,7 +2349,7 @@ static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ct static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp); return 0; } @@ -2335,7 +2359,7 @@ static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); int change; int val; - + if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; val = ucontrol->value.enumerated.item[0]; @@ -2350,128 +2374,6 @@ static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl return change; } -#define HDSP_XLR_BREAKOUT_CABLE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_xlr_breakout_cable, \ - .get = snd_hdsp_get_xlr_breakout_cable, \ - .put = snd_hdsp_put_xlr_breakout_cable \ -} - -static int hdsp_xlr_breakout_cable(struct hdsp *hdsp) -{ - if (hdsp->control_register & HDSP_XLRBreakoutCable) - return 1; - return 0; -} - -static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode) -{ - if (mode) - hdsp->control_register |= HDSP_XLRBreakoutCable; - else - hdsp->control_register &= ~HDSP_XLRBreakoutCable; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_info_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *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(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *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_irq(&hdsp->lock); - change = (int)val != hdsp_xlr_breakout_cable(hdsp); - hdsp_set_xlr_breakout_cable(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -/* (De)activates old RME Analog Extension Board - These are connected to the internal ADAT connector - Switching this on desactivates external ADAT -*/ -#define HDSP_AEB(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_aeb, \ - .get = snd_hdsp_get_aeb, \ - .put = snd_hdsp_put_aeb \ -} - -static int hdsp_aeb(struct hdsp *hdsp) -{ - if (hdsp->control_register & HDSP_AnalogExtensionBoard) - return 1; - return 0; -} - -static int hdsp_set_aeb(struct hdsp *hdsp, int mode) -{ - if (mode) - hdsp->control_register |= HDSP_AnalogExtensionBoard; - else - hdsp->control_register &= ~HDSP_AnalogExtensionBoard; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_info_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp); - return 0; -} - -static int snd_hdsp_put_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *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_irq(&hdsp->lock); - change = (int)val != hdsp_aeb(hdsp); - hdsp_set_aeb(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - #define HDSP_PREF_SYNC_REF(xname, xindex) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ @@ -2539,7 +2441,7 @@ static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd { static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" }; struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; @@ -2555,10 +2457,9 @@ static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd uinfo->value.enumerated.items = 3; break; default: - uinfo->value.enumerated.items = 0; - break; + return -EINVAL; } - + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); @@ -2568,7 +2469,7 @@ static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - + ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp); return 0; } @@ -2578,7 +2479,7 @@ static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); int change, max; unsigned int val; - + if (!snd_hdsp_use_is_exclusive(hdsp)) return -EBUSY; @@ -2627,7 +2528,7 @@ static int hdsp_autosync_ref(struct hdsp *hdsp) case HDSP_SelSyncRef_SPDIF: return HDSP_AUTOSYNC_FROM_SPDIF; case HDSP_SelSyncRefMask: - return HDSP_AUTOSYNC_FROM_NONE; + return HDSP_AUTOSYNC_FROM_NONE; case HDSP_SelSyncRef_ADAT1: return HDSP_AUTOSYNC_FROM_ADAT1; case HDSP_SelSyncRef_ADAT2: @@ -2643,7 +2544,7 @@ static int hdsp_autosync_ref(struct hdsp *hdsp) static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" }; - + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 7; @@ -2656,70 +2557,11 @@ static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp); - return 0; -} -#define HDSP_LINE_OUT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_line_out, \ - .get = snd_hdsp_get_line_out, \ - .put = snd_hdsp_put_line_out \ -} - -static int hdsp_line_out(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_LineOut) ? 1 : 0; -} - -static int hdsp_set_line_output(struct hdsp *hdsp, int out) -{ - if (out) - hdsp->control_register |= HDSP_LineOut; - else - hdsp->control_register &= ~HDSP_LineOut; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_info_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_hdsp_get_line_out(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_line_out(hdsp); - spin_unlock_irq(&hdsp->lock); + ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp); return 0; } -static int snd_hdsp_put_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *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_irq(&hdsp->lock); - change = (int)val != hdsp_line_out(hdsp); - hdsp_set_line_output(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - #define HDSP_PRECISE_POINTER(xname, xindex) \ { .iface = SNDRV_CTL_ELEM_IFACE_CARD, \ .name = xname, \ @@ -2738,19 +2580,12 @@ static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise) return 0; } -static int snd_hdsp_info_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} +#define snd_hdsp_info_precise_pointer snd_ctl_boolean_mono_info static int snd_hdsp_get_precise_pointer(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->precise_ptr; spin_unlock_irq(&hdsp->lock); @@ -2762,7 +2597,7 @@ static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct sn struct hdsp *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; @@ -2791,19 +2626,12 @@ static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet) return 0; } -static int snd_hdsp_info_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} +#define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info static int snd_hdsp_get_use_midi_tasklet(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; spin_unlock_irq(&hdsp->lock); @@ -2815,7 +2643,7 @@ static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct s struct hdsp *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; @@ -2857,12 +2685,12 @@ static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem source = ucontrol->value.integer.value[0]; destination = ucontrol->value.integer.value[1]; - + if (source >= hdsp->max_channels) addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination); else addr = hdsp_input_to_output_key(hdsp,source, destination); - + spin_lock_irq(&hdsp->lock); ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr); spin_unlock_irq(&hdsp->lock); @@ -2910,7 +2738,7 @@ static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - static char *texts[] = {"No Lock", "Lock", "Sync" }; + static char *texts[] = {"No Lock", "Lock", "Sync" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 3; @@ -2955,7 +2783,7 @@ static int hdsp_spdif_sync_check(struct hdsp *hdsp) int status = hdsp_read(hdsp, HDSP_statusRegister); if (status & HDSP_SPDIFErrorFlag) return 0; - else { + else { if (status & HDSP_SPDIFSync) return 2; else @@ -2991,7 +2819,7 @@ static int hdsp_adatsync_sync_check(struct hdsp *hdsp) return 1; } else return 0; -} +} static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -3009,17 +2837,17 @@ static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struc } static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx) -{ +{ int status = hdsp_read(hdsp, HDSP_statusRegister); - + if (status & (HDSP_Lock0>>idx)) { if (status & (HDSP_Sync0>>idx)) return 2; else - return 1; + return 1; } else return 0; -} +} static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -3027,7 +2855,7 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); offset = ucontrol->id.index - 1; - snd_assert(offset >= 0); + snd_BUG_ON(offset < 0); switch (hdsp->io_type) { case Digiface: @@ -3037,7 +2865,7 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn break; case Multiface: case H9632: - if (offset >= 1) + if (offset >= 1) return -EINVAL; break; default: @@ -3048,11 +2876,85 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn return 0; } +#define HDSP_DDS_OFFSET(xname, xindex) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdsp_info_dds_offset, \ + .get = snd_hdsp_get_dds_offset, \ + .put = snd_hdsp_put_dds_offset \ +} + +static int hdsp_dds_offset(struct hdsp *hdsp) +{ + u64 n; + unsigned int dds_value = hdsp->dds_value; + int system_sample_rate = hdsp->system_sample_rate; + + if (!dds_value) + return 0; + + n = DDS_NUMERATOR; + /* + * dds_value = n / rate + * rate = n / dds_value + */ + n = div_u64(n, dds_value); + if (system_sample_rate >= 112000) + n *= 4; + else if (system_sample_rate >= 56000) + n *= 2; + return ((int)n) - system_sample_rate; +} + +static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz) +{ + int rate = hdsp->system_sample_rate + offset_hz; + hdsp_set_dds_value(hdsp, rate); + return 0; +} + +static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = -5000; + uinfo->value.integer.max = 5000; + return 0; +} + +static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + + ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp); + return 0; +} + +static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + int change; + int val; + + if (!snd_hdsp_use_is_exclusive(hdsp)) + return -EBUSY; + val = ucontrol->value.enumerated.item[0]; + spin_lock_irq(&hdsp->lock); + if (val != hdsp_dds_offset(hdsp)) + change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0; + else + change = 0; + spin_unlock_irq(&hdsp->lock); + return change; +} + static struct snd_kcontrol_new snd_hdsp_9632_controls[] = { HDSP_DA_GAIN("DA Gain", 0), HDSP_AD_GAIN("AD Gain", 0), HDSP_PHONE_GAIN("Phones Gain", 0), -HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0) +HDSP_TOGGLE_SETTING("XLR Breakout Cable", HDSP_XLRBreakoutCable), +HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0) }; static struct snd_kcontrol_new snd_hdsp_controls[] = { @@ -3079,7 +2981,7 @@ static struct snd_kcontrol_new snd_hdsp_controls[] = { .get = snd_hdsp_control_spdif_mask_get, .private_value = IEC958_AES0_NONAUDIO | IEC958_AES0_PROFESSIONAL | - IEC958_AES0_CON_EMPHASIS, + IEC958_AES0_CON_EMPHASIS, }, { .access = SNDRV_CTL_ELEM_ACCESS_READ, @@ -3093,11 +2995,11 @@ static struct snd_kcontrol_new snd_hdsp_controls[] = { }, HDSP_MIXER("Mixer", 0), HDSP_SPDIF_IN("IEC958 Input Connector", 0), -HDSP_SPDIF_OUT("IEC958 Output also on ADAT1", 0), -HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0), -HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0), -HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0), -/* 'Sample Clock Source' complies with the alsa control naming scheme */ +HDSP_TOGGLE_SETTING("IEC958 Output also on ADAT1", HDSP_SPDIFOpticalOut), +HDSP_TOGGLE_SETTING("IEC958 Professional Bit", HDSP_SPDIFProfessional), +HDSP_TOGGLE_SETTING("IEC958 Emphasis Bit", HDSP_SPDIFEmphasis), +HDSP_TOGGLE_SETTING("IEC958 Non-audio Bit", HDSP_SPDIFNonAudio), +/* 'Sample Clock Source' complies with the alsa control naming scheme */ HDSP_CLOCK_SOURCE("Sample Clock Source", 0), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -3116,12 +3018,326 @@ HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0), HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0), HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0), HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0), -HDSP_LINE_OUT("Line Out", 0), +HDSP_TOGGLE_SETTING("Line Out", HDSP_LineOut), HDSP_PRECISE_POINTER("Precise Pointer", 0), HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0), }; -static struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0); + +static int hdsp_rpm_input12(struct hdsp *hdsp) +{ + switch (hdsp->control_register & HDSP_RPM_Inp12) { + case HDSP_RPM_Inp12_Phon_6dB: + return 0; + case HDSP_RPM_Inp12_Phon_n6dB: + return 2; + case HDSP_RPM_Inp12_Line_0dB: + return 3; + case HDSP_RPM_Inp12_Line_n6dB: + return 4; + } + return 1; +} + + +static int snd_hdsp_get_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + + ucontrol->value.enumerated.item[0] = hdsp_rpm_input12(hdsp); + return 0; +} + + +static int hdsp_set_rpm_input12(struct hdsp *hdsp, int mode) +{ + hdsp->control_register &= ~HDSP_RPM_Inp12; + switch (mode) { + case 0: + hdsp->control_register |= HDSP_RPM_Inp12_Phon_6dB; + break; + case 1: + break; + case 2: + hdsp->control_register |= HDSP_RPM_Inp12_Phon_n6dB; + break; + case 3: + hdsp->control_register |= HDSP_RPM_Inp12_Line_0dB; + break; + case 4: + hdsp->control_register |= HDSP_RPM_Inp12_Line_n6dB; + break; + default: + return -1; + } + + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + return 0; +} + + +static int snd_hdsp_put_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + int change; + int val; + + if (!snd_hdsp_use_is_exclusive(hdsp)) + return -EBUSY; + val = ucontrol->value.enumerated.item[0]; + if (val < 0) + val = 0; + if (val > 4) + val = 4; + spin_lock_irq(&hdsp->lock); + if (val != hdsp_rpm_input12(hdsp)) + change = (hdsp_set_rpm_input12(hdsp, val) == 0) ? 1 : 0; + else + change = 0; + spin_unlock_irq(&hdsp->lock); + return change; +} + + +static int snd_hdsp_info_rpm_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + static char *texts[] = {"Phono +6dB", "Phono 0dB", "Phono -6dB", "Line 0dB", "Line -6dB"}; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 5; + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) + uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + + +static int hdsp_rpm_input34(struct hdsp *hdsp) +{ + switch (hdsp->control_register & HDSP_RPM_Inp34) { + case HDSP_RPM_Inp34_Phon_6dB: + return 0; + case HDSP_RPM_Inp34_Phon_n6dB: + return 2; + case HDSP_RPM_Inp34_Line_0dB: + return 3; + case HDSP_RPM_Inp34_Line_n6dB: + return 4; + } + return 1; +} + + +static int snd_hdsp_get_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + + ucontrol->value.enumerated.item[0] = hdsp_rpm_input34(hdsp); + return 0; +} + + +static int hdsp_set_rpm_input34(struct hdsp *hdsp, int mode) +{ + hdsp->control_register &= ~HDSP_RPM_Inp34; + switch (mode) { + case 0: + hdsp->control_register |= HDSP_RPM_Inp34_Phon_6dB; + break; + case 1: + break; + case 2: + hdsp->control_register |= HDSP_RPM_Inp34_Phon_n6dB; + break; + case 3: + hdsp->control_register |= HDSP_RPM_Inp34_Line_0dB; + break; + case 4: + hdsp->control_register |= HDSP_RPM_Inp34_Line_n6dB; + break; + default: + return -1; + } + + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + return 0; +} + + +static int snd_hdsp_put_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + int change; + int val; + + if (!snd_hdsp_use_is_exclusive(hdsp)) + return -EBUSY; + val = ucontrol->value.enumerated.item[0]; + if (val < 0) + val = 0; + if (val > 4) + val = 4; + spin_lock_irq(&hdsp->lock); + if (val != hdsp_rpm_input34(hdsp)) + change = (hdsp_set_rpm_input34(hdsp, val) == 0) ? 1 : 0; + else + change = 0; + spin_unlock_irq(&hdsp->lock); + return change; +} + + +/* RPM Bypass switch */ +static int hdsp_rpm_bypass(struct hdsp *hdsp) +{ + return (hdsp->control_register & HDSP_RPM_Bypass) ? 1 : 0; +} + + +static int snd_hdsp_get_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = hdsp_rpm_bypass(hdsp); + return 0; +} + + +static int hdsp_set_rpm_bypass(struct hdsp *hdsp, int on) +{ + if (on) + hdsp->control_register |= HDSP_RPM_Bypass; + else + hdsp->control_register &= ~HDSP_RPM_Bypass; + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + return 0; +} + + +static int snd_hdsp_put_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *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_irq(&hdsp->lock); + change = (int)val != hdsp_rpm_bypass(hdsp); + hdsp_set_rpm_bypass(hdsp, val); + spin_unlock_irq(&hdsp->lock); + return change; +} + + +static int snd_hdsp_info_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + static char *texts[] = {"On", "Off"}; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 2; + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) + uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + + +/* RPM Disconnect switch */ +static int hdsp_rpm_disconnect(struct hdsp *hdsp) +{ + return (hdsp->control_register & HDSP_RPM_Disconnect) ? 1 : 0; +} + + +static int snd_hdsp_get_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = hdsp_rpm_disconnect(hdsp); + return 0; +} + + +static int hdsp_set_rpm_disconnect(struct hdsp *hdsp, int on) +{ + if (on) + hdsp->control_register |= HDSP_RPM_Disconnect; + else + hdsp->control_register &= ~HDSP_RPM_Disconnect; + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); + return 0; +} + + +static int snd_hdsp_put_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct hdsp *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_irq(&hdsp->lock); + change = (int)val != hdsp_rpm_disconnect(hdsp); + hdsp_set_rpm_disconnect(hdsp, val); + spin_unlock_irq(&hdsp->lock); + return change; +} + +static int snd_hdsp_info_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + static char *texts[] = {"On", "Off"}; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 2; + if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) + uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + +static struct snd_kcontrol_new snd_hdsp_rpm_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "RPM Bypass", + .get = snd_hdsp_get_rpm_bypass, + .put = snd_hdsp_put_rpm_bypass, + .info = snd_hdsp_info_rpm_bypass + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "RPM Disconnect", + .get = snd_hdsp_get_rpm_disconnect, + .put = snd_hdsp_put_rpm_disconnect, + .info = snd_hdsp_info_rpm_disconnect + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Input 1/2", + .get = snd_hdsp_get_rpm_input12, + .put = snd_hdsp_put_rpm_input12, + .info = snd_hdsp_info_rpm_input + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Input 3/4", + .get = snd_hdsp_get_rpm_input34, + .put = snd_hdsp_put_rpm_input34, + .info = snd_hdsp_info_rpm_input + }, + HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), + HDSP_MIXER("Mixer", 0) +}; + +static struct snd_kcontrol_new snd_hdsp_96xx_aeb = + HDSP_TOGGLE_SETTING("Analog Extension Board", + HDSP_AnalogExtensionBoard); static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK; static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) @@ -3130,6 +3346,16 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) int err; struct snd_kcontrol *kctl; + 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)); + if (err < 0) + return err; + } + return 0; + } + 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; @@ -3149,7 +3375,7 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) return err; } } - + /* 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++) { @@ -3168,13 +3394,13 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) } /*------------------------------------------------------------ - /proc interface + /proc interface ------------------------------------------------------------*/ static void snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { - struct hdsp *hdsp = (struct hdsp *) entry->private_data; + struct hdsp *hdsp = entry->private_data; unsigned int status; unsigned int status2; char *pref_sync_ref; @@ -3183,22 +3409,38 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) char *clock_source; int x; - if (hdsp_check_for_iobox (hdsp)) { - snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n"); + status = hdsp_read(hdsp, HDSP_statusRegister); + status2 = hdsp_read(hdsp, HDSP_status2Register); + + snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name, + hdsp->card->number + 1); + 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, (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); + snd_iprintf(buffer, "Status2 register: 0x%x\n", status2); + + if (hdsp_check_for_iobox(hdsp)) { + snd_iprintf(buffer, "No I/O box connected.\n" + "Please connect one and upload firmware.\n"); return; - } + } if (hdsp_check_for_firmware(hdsp, 0)) { if (hdsp->state & HDSP_FirmwareCached) { if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_iprintf(buffer, "Firmware loading from cache failed, please upload manually.\n"); + snd_iprintf(buffer, "Firmware loading from " + "cache failed, " + "please upload manually.\n"); return; } } else { int err = -EINVAL; -#ifdef HDSP_FW_LOADER err = hdsp_request_fw_loader(hdsp); -#endif if (err < 0) { snd_iprintf(buffer, "No firmware loaded nor cached, " @@ -3207,19 +3449,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) } } } - - status = hdsp_read(hdsp, HDSP_statusRegister); - status2 = hdsp_read(hdsp, HDSP_status2Register); - snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name, hdsp->card->number + 1); - 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, (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); - snd_iprintf(buffer, "Status2 register: 0x%x\n", status2); snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff); snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0)); snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0)); @@ -3240,7 +3470,6 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) snd_iprintf(buffer, "\n"); - switch (hdsp_clock_source(hdsp)) { case HDSP_CLOCK_SOURCE_AUTOSYNC: clock_source = "AutoSync"; @@ -3271,17 +3500,17 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) break; case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ: clock_source = "Internal 192 kHz"; - break; + break; default: - clock_source = "Error"; + clock_source = "Error"; } snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source); - + if (hdsp_system_clock_mode(hdsp)) system_clock_mode = "Slave"; else system_clock_mode = "Master"; - + switch (hdsp_pref_sync_ref (hdsp)) { case HDSP_SYNC_FROM_WORD: pref_sync_ref = "Word Clock"; @@ -3306,7 +3535,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) break; } snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref); - + switch (hdsp_autosync_ref (hdsp)) { case HDSP_AUTOSYNC_FROM_WORD: autosync_ref = "Word Clock"; @@ -3319,7 +3548,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) break; case HDSP_AUTOSYNC_FROM_NONE: autosync_ref = "None"; - break; + break; case HDSP_AUTOSYNC_FROM_ADAT1: autosync_ref = "ADAT1"; break; @@ -3334,58 +3563,112 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) break; } snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref); - + snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp)); - + snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode); snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate); snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No"); - + snd_iprintf(buffer, "\n"); - switch (hdsp_spdif_in(hdsp)) { - case HDSP_SPDIFIN_OPTICAL: - snd_iprintf(buffer, "IEC958 input: Optical\n"); - break; - case HDSP_SPDIFIN_COAXIAL: - snd_iprintf(buffer, "IEC958 input: Coaxial\n"); - break; - case HDSP_SPDIFIN_INTERNAL: - snd_iprintf(buffer, "IEC958 input: Internal\n"); - break; - case HDSP_SPDIFIN_AES: - snd_iprintf(buffer, "IEC958 input: AES\n"); - break; - default: - snd_iprintf(buffer, "IEC958 input: ???\n"); - break; + if (hdsp->io_type != RPM) { + switch (hdsp_spdif_in(hdsp)) { + case HDSP_SPDIFIN_OPTICAL: + snd_iprintf(buffer, "IEC958 input: Optical\n"); + break; + case HDSP_SPDIFIN_COAXIAL: + snd_iprintf(buffer, "IEC958 input: Coaxial\n"); + break; + case HDSP_SPDIFIN_INTERNAL: + snd_iprintf(buffer, "IEC958 input: Internal\n"); + break; + case HDSP_SPDIFIN_AES: + snd_iprintf(buffer, "IEC958 input: AES\n"); + break; + default: + snd_iprintf(buffer, "IEC958 input: ???\n"); + break; + } } - - if (hdsp->control_register & HDSP_SPDIFOpticalOut) - snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); - else - snd_iprintf(buffer, "IEC958 output: Coaxial only\n"); - if (hdsp->control_register & HDSP_SPDIFProfessional) - snd_iprintf(buffer, "IEC958 quality: Professional\n"); - else - snd_iprintf(buffer, "IEC958 quality: Consumer\n"); + if (RPM == hdsp->io_type) { + if (hdsp->control_register & HDSP_RPM_Bypass) + snd_iprintf(buffer, "RPM Bypass: disabled\n"); + else + snd_iprintf(buffer, "RPM Bypass: enabled\n"); + if (hdsp->control_register & HDSP_RPM_Disconnect) + snd_iprintf(buffer, "RPM disconnected\n"); + else + snd_iprintf(buffer, "RPM connected\n"); - if (hdsp->control_register & HDSP_SPDIFEmphasis) - snd_iprintf(buffer, "IEC958 emphasis: on\n"); - else - snd_iprintf(buffer, "IEC958 emphasis: off\n"); + switch (hdsp->control_register & HDSP_RPM_Inp12) { + case HDSP_RPM_Inp12_Phon_6dB: + snd_iprintf(buffer, "Input 1/2: Phono, 6dB\n"); + break; + case HDSP_RPM_Inp12_Phon_0dB: + snd_iprintf(buffer, "Input 1/2: Phono, 0dB\n"); + break; + case HDSP_RPM_Inp12_Phon_n6dB: + snd_iprintf(buffer, "Input 1/2: Phono, -6dB\n"); + break; + case HDSP_RPM_Inp12_Line_0dB: + snd_iprintf(buffer, "Input 1/2: Line, 0dB\n"); + break; + case HDSP_RPM_Inp12_Line_n6dB: + snd_iprintf(buffer, "Input 1/2: Line, -6dB\n"); + break; + default: + snd_iprintf(buffer, "Input 1/2: ???\n"); + } - if (hdsp->control_register & HDSP_SPDIFNonAudio) - snd_iprintf(buffer, "IEC958 NonAudio: on\n"); - else - snd_iprintf(buffer, "IEC958 NonAudio: off\n"); - if ((x = hdsp_spdif_sample_rate (hdsp)) != 0) - snd_iprintf (buffer, "IEC958 sample rate: %d\n", x); - else - snd_iprintf (buffer, "IEC958 sample rate: Error flag set\n"); + switch (hdsp->control_register & HDSP_RPM_Inp34) { + case HDSP_RPM_Inp34_Phon_6dB: + snd_iprintf(buffer, "Input 3/4: Phono, 6dB\n"); + break; + case HDSP_RPM_Inp34_Phon_0dB: + snd_iprintf(buffer, "Input 3/4: Phono, 0dB\n"); + break; + case HDSP_RPM_Inp34_Phon_n6dB: + snd_iprintf(buffer, "Input 3/4: Phono, -6dB\n"); + break; + case HDSP_RPM_Inp34_Line_0dB: + snd_iprintf(buffer, "Input 3/4: Line, 0dB\n"); + break; + case HDSP_RPM_Inp34_Line_n6dB: + snd_iprintf(buffer, "Input 3/4: Line, -6dB\n"); + break; + default: + snd_iprintf(buffer, "Input 3/4: ???\n"); + } + + } else { + if (hdsp->control_register & HDSP_SPDIFOpticalOut) + snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); + else + snd_iprintf(buffer, "IEC958 output: Coaxial only\n"); + + if (hdsp->control_register & HDSP_SPDIFProfessional) + snd_iprintf(buffer, "IEC958 quality: Professional\n"); + else + snd_iprintf(buffer, "IEC958 quality: Consumer\n"); + if (hdsp->control_register & HDSP_SPDIFEmphasis) + snd_iprintf(buffer, "IEC958 emphasis: on\n"); + else + snd_iprintf(buffer, "IEC958 emphasis: off\n"); + + if (hdsp->control_register & HDSP_SPDIFNonAudio) + snd_iprintf(buffer, "IEC958 NonAudio: on\n"); + else + snd_iprintf(buffer, "IEC958 NonAudio: off\n"); + x = hdsp_spdif_sample_rate(hdsp); + if (x != 0) + snd_iprintf(buffer, "IEC958 sample rate: %d\n", x); + else + snd_iprintf(buffer, "IEC958 sample rate: Error flag set\n"); + } snd_iprintf(buffer, "\n"); /* Sync Check */ @@ -3419,13 +3702,13 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) snd_iprintf (buffer, "SPDIF: No Lock\n"); else snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock"); - + x = status2 & HDSP_wc_sync; if (status2 & HDSP_wc_lock) snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock"); else snd_iprintf (buffer, "Word Clock: No Lock\n"); - + x = status & HDSP_TimecodeSync; if (status & HDSP_TimecodeLock) snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock"); @@ -3433,11 +3716,11 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) snd_iprintf(buffer, "ADAT Sync: No Lock\n"); snd_iprintf(buffer, "\n"); - + /* Informations about H9632 specific controls */ if (hdsp->io_type == H9632) { char *tmp; - + switch (hdsp_ad_gain(hdsp)) { case 0: tmp = "-10 dBV"; @@ -3463,7 +3746,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) break; } snd_iprintf(buffer, "DA Gain : %s\n", tmp); - + switch (hdsp_phone_gain(hdsp)) { case 0: tmp = "0 dB"; @@ -3477,8 +3760,10 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) } snd_iprintf(buffer, "Phones Gain : %s\n", tmp); - snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no"); - + snd_iprintf(buffer, "XLR Breakout Cable : %s\n", + hdsp_toggle_setting(hdsp, HDSP_XLRBreakoutCable) ? + "yes" : "no"); + if (hdsp->control_register & HDSP_AnalogExtensionBoard) snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n"); else @@ -3488,7 +3773,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) } -static void __devinit snd_hdsp_proc_init(struct hdsp *hdsp) +static void snd_hdsp_proc_init(struct hdsp *hdsp) { struct snd_info_entry *entry; @@ -3502,7 +3787,7 @@ static void snd_hdsp_free_buffers(struct hdsp *hdsp) snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci); } -static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp) +static int snd_hdsp_initialize_memory(struct hdsp *hdsp) { unsigned long pb_bus, cb_bus; @@ -3510,14 +3795,15 @@ static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp) 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); + dev_err(hdsp->card->dev, + "%s: no buffers available\n", hdsp->card_name); return -ENOMEM; } /* Align to bus-space 64K boundary */ - cb_bus = (hdsp->capture_dma_buf.addr + 0xFFFF) & ~0xFFFFl; - pb_bus = (hdsp->playback_dma_buf.addr + 0xFFFF) & ~0xFFFFl; + cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul); + pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul); /* Tell the card where it is */ @@ -3536,23 +3822,23 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp) /* ASSUMPTION: hdsp->lock is either held, or there is no need to hold it (e.g. during module - initalization). + initialization). */ /* set defaults: - SPDIF Input via Coax + SPDIF Input via Coax Master clock mode maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer, which implies 2 4096 sample, 32Kbyte periods). - Enable line out. + Enable line out. */ - hdsp->control_register = HDSP_ClockModeMaster | - HDSP_SPDIFInputCoaxial | - hdsp_encode_latency(7) | + hdsp->control_register = HDSP_ClockModeMaster | + HDSP_SPDIFInputCoaxial | + hdsp_encode_latency(7) | HDSP_LineOut; - + hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); @@ -3570,7 +3856,7 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp) hdsp_compute_period_size(hdsp); /* silence everything */ - + for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i) hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN; @@ -3578,7 +3864,7 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp) if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN)) return -EIO; } - + /* H9632 specific defaults */ if (hdsp->io_type == H9632) { hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB); @@ -3596,14 +3882,14 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp) static void hdsp_midi_tasklet(unsigned long arg) { struct hdsp *hdsp = (struct hdsp *)arg; - + if (hdsp->midi[0].pending) snd_hdsp_midi_input_read (&hdsp->midi[0]); if (hdsp->midi[1].pending) snd_hdsp_midi_input_read (&hdsp->midi[1]); -} +} -static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id) { struct hdsp *hdsp = (struct hdsp *) dev_id; unsigned int status; @@ -3613,7 +3899,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg unsigned int midi0status; unsigned int midi1status; int schedule = 0; - + status = hdsp_read(hdsp, HDSP_statusRegister); audio = status & HDSP_audioIRQPending; @@ -3627,15 +3913,18 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff; midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff; - + + if (!(hdsp->state & HDSP_InitializationComplete)) + return IRQ_HANDLED; + if (audio) { if (hdsp->capture_substream) snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); - + if (hdsp->playback_substream) snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream); } - + if (midi0 && midi0status) { if (hdsp->use_midi_tasklet) { /* we disable interrupts for this input until processing is done */ @@ -3647,7 +3936,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg snd_hdsp_midi_input_read (&hdsp->midi[0]); } } - if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) { + if (hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632 && midi1 && midi1status) { if (hdsp->use_midi_tasklet) { /* we disable interrupts for this input until processing is done */ hdsp->control_register &= ~HDSP_Midi1InterruptEnable; @@ -3659,7 +3948,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg } } if (hdsp->use_midi_tasklet && schedule) - tasklet_hi_schedule(&hdsp->midi_tasklet); + tasklet_schedule(&hdsp->midi_tasklet); return IRQ_HANDLED; } @@ -3676,11 +3965,12 @@ static char *hdsp_channel_buffer_location(struct hdsp *hdsp, { int mapped_channel; - snd_assert(channel >= 0 && channel < hdsp->max_channels, return NULL); - + if (snd_BUG_ON(channel < 0 || channel >= hdsp->max_channels)) + return NULL; + if ((mapped_channel = hdsp->channel_map[channel]) < 0) return NULL; - + if (stream == SNDRV_PCM_STREAM_CAPTURE) return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); else @@ -3693,10 +3983,12 @@ static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int chann struct hdsp *hdsp = snd_pcm_substream_chip(substream); char *channel_buf; - snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL); + if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4)) + return -EINVAL; channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; if (copy_from_user(channel_buf + pos * 4, src, count * 4)) return -EFAULT; return count; @@ -3708,10 +4000,12 @@ static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channe struct hdsp *hdsp = snd_pcm_substream_chip(substream); char *channel_buf; - snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL); + if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4)) + return -EINVAL; channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) return -EFAULT; return count; @@ -3724,7 +4018,8 @@ static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel, char *channel_buf; channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); - snd_assert(channel_buf != NULL, return -EIO); + if (snd_BUG_ON(!channel_buf)) + return -EIO; memset(channel_buf + pos * 4, 0, count * 4); return count; } @@ -3743,11 +4038,9 @@ static int snd_hdsp_reset(struct snd_pcm_substream *substream) else runtime->status->hw_ptr = 0; if (other) { - struct list_head *pos; struct snd_pcm_substream *s; struct snd_pcm_runtime *oruntime = other->runtime; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == other) { oruntime->status->hw_ptr = runtime->status->hw_ptr; break; @@ -3838,7 +4131,8 @@ static int snd_hdsp_channel_info(struct snd_pcm_substream *substream, struct hdsp *hdsp = snd_pcm_substream_chip(substream); int mapped_channel; - snd_assert(info->channel < hdsp->max_channels, return -EINVAL); + if (snd_BUG_ON(info->channel >= hdsp->max_channels)) + return -EINVAL; if ((mapped_channel = hdsp->channel_map[info->channel]) < 0) return -EINVAL; @@ -3869,7 +4163,7 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) struct hdsp *hdsp = snd_pcm_substream_chip(substream); struct snd_pcm_substream *other; int running; - + if (hdsp_check_for_iobox (hdsp)) return -EIO; @@ -3896,10 +4190,8 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) other = hdsp->playback_substream; if (other) { - struct list_head *pos; struct snd_pcm_substream *s; - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); + snd_pcm_group_for_each_entry(s, substream) { if (s == other) { snd_pcm_trigger_done(s, substream); if (cmd == SNDRV_PCM_TRIGGER_START) @@ -3965,14 +4257,14 @@ static struct snd_pcm_hardware snd_hdsp_playback_subinfo = .formats = SNDRV_PCM_FMTBIT_S32_LE, #endif .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_64000 | + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), .rate_min = 32000, .rate_max = 96000, - .channels_min = 14, + .channels_min = 6, .channels_max = HDSP_MAX_CHANNELS, .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS, .period_bytes_min = (64 * 4) * 10, @@ -3994,14 +4286,14 @@ static struct snd_pcm_hardware snd_hdsp_capture_subinfo = .formats = SNDRV_PCM_FMTBIT_S32_LE, #endif .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_64000 | + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), .rate_min = 32000, .rate_max = 96000, - .channels_min = 14, + .channels_min = 5, .channels_max = HDSP_MAX_CHANNELS, .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS, .period_bytes_min = (64 * 4) * 10, @@ -4076,7 +4368,7 @@ static int snd_hdsp_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params, .max = hdsp->qs_in_channels, .integer = 1, }; - return snd_interval_refine(c, &t); + return snd_interval_refine(c, &t); } else if (r->min > 48000 && r->max <= 96000) { struct snd_interval t = { .min = hdsp->ds_in_channels, @@ -4107,7 +4399,7 @@ static int snd_hdsp_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params, .max = hdsp->qs_out_channels, .integer = 1, }; - return snd_interval_refine(c, &t); + return snd_interval_refine(c, &t); } else if (r->min > 48000 && r->max <= 96000) { struct snd_interval t = { .min = hdsp->ds_out_channels, @@ -4224,8 +4516,8 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream) if (hdsp->io_type == H9632) { runtime->hw.channels_min = hdsp->qs_out_channels; runtime->hw.channels_max = hdsp->ss_out_channels; - } - + } + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, snd_hdsp_hw_rule_out_channels, hdsp, SNDRV_PCM_HW_PARAM_CHANNELS, -1); @@ -4236,10 +4528,12 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream) snd_hdsp_hw_rule_rate_out_channels, hdsp, SNDRV_PCM_HW_PARAM_CHANNELS, -1); - hdsp->creg_spdif_stream = hdsp->creg_spdif; - hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); + if (RPM != hdsp->io_type) { + hdsp->creg_spdif_stream = hdsp->creg_spdif; + hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; + snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | + SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); + } return 0; } @@ -4254,9 +4548,11 @@ static int snd_hdsp_playback_release(struct snd_pcm_substream *substream) 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 | - SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); + if (RPM != hdsp->io_type) { + hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; + snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | + SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); + } return 0; } @@ -4319,13 +4615,6 @@ static int snd_hdsp_capture_release(struct snd_pcm_substream *substream) return 0; } -static int snd_hdsp_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file) -{ - /* we have nothing to initialize but the call is required */ - return 0; -} - - /* helper functions for copying meter values */ static inline int copy_u32_le(void __user *dest, void __iomem *src) { @@ -4442,7 +4731,7 @@ static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rm hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4, hdsp->iobase + HDSP_playbackRmsLevel + i * 8)) return -EFAULT; - if (copy_u64_le(&peak_rms->input_rms[i], + if (copy_u64_le(&peak_rms->input_rms[i], hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4, hdsp->iobase + HDSP_inputRmsLevel + i * 8)) return -EFAULT; @@ -4452,15 +4741,25 @@ static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rm static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) { - struct hdsp *hdsp = (struct hdsp *)hw->private_data; + struct hdsp *hdsp = hw->private_data; void __user *argp = (void __user *)arg; + int err; switch (cmd) { case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: { struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg; + err = hdsp_check_for_iobox(hdsp); + if (err < 0) + return err; + + err = hdsp_check_for_firmware(hdsp, 1); + if (err < 0) + return err; + if (!(hdsp->state & HDSP_FirmwareLoaded)) { - snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n"); + dev_err(hdsp->card->dev, + "firmware needs to be uploaded to the card.\n"); return -EINVAL; } @@ -4477,40 +4776,57 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne struct hdsp_config_info info; unsigned long flags; int i; - - if (!(hdsp->state & HDSP_FirmwareLoaded)) { - snd_printk(KERN_ERR "Hammerfall-DSP: Firmware needs to be uploaded to the card.\n"); - return -EINVAL; - } + + err = hdsp_check_for_iobox(hdsp); + if (err < 0) + return err; + + err = hdsp_check_for_firmware(hdsp, 1); + if (err < 0) + return err; + + memset(&info, 0, sizeof(info)); spin_lock_irqsave(&hdsp->lock, flags); info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp); info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp); if (hdsp->io_type != H9632) info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp); info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp); - for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != H9632) ? 3 : 1); ++i) + for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632) ? 3 : 1); ++i) info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i); info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp); - info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp); - info.spdif_professional = (unsigned char)hdsp_spdif_professional(hdsp); - info.spdif_emphasis = (unsigned char)hdsp_spdif_emphasis(hdsp); - info.spdif_nonaudio = (unsigned char)hdsp_spdif_nonaudio(hdsp); + info.spdif_out = (unsigned char)hdsp_toggle_setting(hdsp, + HDSP_SPDIFOpticalOut); + info.spdif_professional = (unsigned char) + hdsp_toggle_setting(hdsp, HDSP_SPDIFProfessional); + info.spdif_emphasis = (unsigned char) + hdsp_toggle_setting(hdsp, HDSP_SPDIFEmphasis); + info.spdif_nonaudio = (unsigned char) + hdsp_toggle_setting(hdsp, HDSP_SPDIFNonAudio); info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp); info.system_sample_rate = hdsp->system_sample_rate; info.autosync_sample_rate = hdsp_external_sample_rate(hdsp); info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp); info.clock_source = (unsigned char)hdsp_clock_source(hdsp); info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp); - info.line_out = (unsigned char)hdsp_line_out(hdsp); + info.line_out = (unsigned char) + hdsp_toggle_setting(hdsp, HDSP_LineOut); if (hdsp->io_type == H9632) { info.da_gain = (unsigned char)hdsp_da_gain(hdsp); info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp); info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp); - info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp); - + info.xlr_breakout_cable = + (unsigned char)hdsp_toggle_setting(hdsp, + HDSP_XLRBreakoutCable); + + } else if (hdsp->io_type == RPM) { + info.da_gain = (unsigned char) hdsp_rpm_input12(hdsp); + info.ad_gain = (unsigned char) hdsp_rpm_input34(hdsp); } if (hdsp->io_type == H9632 || hdsp->io_type == H9652) - info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp); + info.analog_extension_board = + (unsigned char)hdsp_toggle_setting(hdsp, + HDSP_AnalogExtensionBoard); spin_unlock_irqrestore(&hdsp->lock, flags); if (copy_to_user(argp, &info, sizeof(info))) return -EFAULT; @@ -4518,7 +4834,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne } case SNDRV_HDSP_IOCTL_GET_9632_AEB: { struct hdsp_9632_aeb h9632_aeb; - + if (hdsp->io_type != H9632) return -EINVAL; h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS; h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS; @@ -4529,12 +4845,13 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne case SNDRV_HDSP_IOCTL_GET_VERSION: { struct hdsp_version hdsp_version; int err; - + if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; if (hdsp->io_type == Undefined) { if ((err = hdsp_get_iobox_version(hdsp)) < 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)))) @@ -4545,7 +4862,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne struct hdsp_firmware __user *firmware; 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; @@ -4553,32 +4870,44 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded)) return -EBUSY; - snd_printk(KERN_INFO "Hammerfall-DSP: initializing firmware upload\n"); + dev_info(hdsp->card->dev, + "initializing firmware upload\n"); firmware = (struct hdsp_firmware __user *)argp; if (get_user(firmware_data, &firmware->firmware_data)) return -EFAULT; - + if (hdsp_check_for_iobox (hdsp)) return -EIO; - if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) + if (!hdsp->fw_uploaded) { + hdsp->fw_uploaded = vmalloc(HDSP_FIRMWARE_SIZE); + if (!hdsp->fw_uploaded) + return -ENOMEM; + } + + if (copy_from_user(hdsp->fw_uploaded, firmware_data, + HDSP_FIRMWARE_SIZE)) { + vfree(hdsp->fw_uploaded); + hdsp->fw_uploaded = NULL; return -EFAULT; - + } + hdsp->state |= HDSP_FirmwareCached; if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) return err; - + if (!(hdsp->state & HDSP_InitializationComplete)) { if ((err = snd_hdsp_enable_io(hdsp)) < 0) return err; - - snd_hdsp_initialize_channels(hdsp); + + snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); - + if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n"); + dev_err(hdsp->card->dev, + "error creating alsa devices\n"); return err; } } @@ -4619,23 +4948,21 @@ static struct snd_pcm_ops snd_hdsp_capture_ops = { .copy = snd_hdsp_capture_copy, }; -static int __devinit snd_hdsp_create_hwdep(struct snd_card *card, - struct hdsp *hdsp) +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) return err; - + hdsp->hwdep = hw; hw->private_data = hdsp; strcpy(hw->name, "HDSP hwdep interface"); - hw->ops.open = snd_hdsp_hwdep_dummy_op; hw->ops.ioctl = snd_hdsp_hwdep_ioctl; - hw->ops.release = snd_hdsp_hwdep_dummy_op; - + hw->ops.ioctl_compat = snd_hdsp_hwdep_ioctl; + return 0; } @@ -4668,24 +4995,25 @@ static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp) static int snd_hdsp_enable_io (struct hdsp *hdsp) { int i; - + if (hdsp_fifo_wait (hdsp, 0, 100)) { - snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n"); + dev_err(hdsp->card->dev, + "enable_io fifo_wait failed\n"); return -EIO; } - + for (i = 0; i < hdsp->max_channels; ++i) { hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1); hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1); } - + return 0; } static void snd_hdsp_initialize_channels(struct hdsp *hdsp) { int status, aebi_channels, aebo_channels; - + switch (hdsp->io_type) { case Digiface: hdsp->card_name = "RME Hammerfall DSP + Digiface"; @@ -4698,7 +5026,7 @@ static void snd_hdsp_initialize_channels(struct hdsp *hdsp) hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS; hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS; break; - + case H9632: status = hdsp_read(hdsp, HDSP_statusRegister); /* HDSP_AEBx bits are low when AEB are connected */ @@ -4718,7 +5046,15 @@ static void snd_hdsp_initialize_channels(struct hdsp *hdsp) hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS; hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS; break; - + + case RPM: + hdsp->card_name = "RME Hammerfall DSP + RPM"; + hdsp->ss_in_channels = RPM_CHANNELS-1; + hdsp->ss_out_channels = RPM_CHANNELS; + hdsp->ds_in_channels = RPM_CHANNELS-1; + hdsp->ds_out_channels = RPM_CHANNELS; + break; + default: /* should never get here */ break; @@ -4734,27 +5070,31 @@ static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp) 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) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n"); + dev_err(card->dev, + "Error creating pcm interface\n"); return err; } - + if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n"); + 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) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating second midi interface\n"); + dev_err(card->dev, + "Error creating second midi interface\n"); return err; } } if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating ctl interface\n"); + dev_err(card->dev, + "Error creating ctl interface\n"); return err; } @@ -4767,33 +5107,34 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp hdsp->playback_substream = NULL; if ((err = snd_hdsp_set_defaults(hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n"); + dev_err(card->dev, + "Error setting default values\n"); return err; } - + if (!(hdsp->state & HDSP_InitializationComplete)) { strcpy(card->shortname, "Hammerfall DSP"); - sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, + sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, hdsp->port, hdsp->irq); - + if ((err = snd_card_register(card)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n"); + dev_err(card->dev, + "error registering card\n"); return err; } hdsp->state |= HDSP_InitializationComplete; } - + return 0; } -#ifdef HDSP_FW_LOADER /* load firmware via hotplug fw loader */ -static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp) +static int hdsp_request_fw_loader(struct hdsp *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) { @@ -4802,9 +5143,12 @@ static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp) if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; } - + /* caution: max length of firmware filename is 30! */ switch (hdsp->io_type) { + case RPM: + fwfile = "rpm_firmware.bin"; + break; case Multiface: if (hdsp->firmware_rev == 0xa) fwfile = "multiface_firmware.bin"; @@ -4818,51 +5162,52 @@ static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp) fwfile = "digiface_firmware_rev11.bin"; break; default: - snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type); + dev_err(hdsp->card->dev, + "invalid io_type %d\n", hdsp->io_type); return -EINVAL; } if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) { - snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile); + dev_err(hdsp->card->dev, + "cannot load firmware %s\n", fwfile); return -ENOENT; } - if (fw->size < sizeof(hdsp->firmware_cache)) { - snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n", - (int)fw->size, (int)sizeof(hdsp->firmware_cache)); - release_firmware(fw); + if (fw->size < HDSP_FIRMWARE_SIZE) { + dev_err(hdsp->card->dev, + "too short firmware size %d (expected %d)\n", + (int)fw->size, HDSP_FIRMWARE_SIZE); return -EINVAL; } - memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); + hdsp->firmware = fw; - release_firmware(fw); - hdsp->state |= HDSP_FirmwareCached; if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) return err; - + if (!(hdsp->state & HDSP_InitializationComplete)) { if ((err = snd_hdsp_enable_io(hdsp)) < 0) return err; if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error creating hwdep device\n"); + 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) { - snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n"); + dev_err(hdsp->card->dev, + "error creating alsa devices\n"); return err; } } return 0; } -#endif -static int __devinit snd_hdsp_create(struct snd_card *card, - struct hdsp *hdsp) +static int snd_hdsp_create(struct snd_card *card, + struct hdsp *hdsp) { struct pci_dev *pci = hdsp->pci; int err; @@ -4888,14 +5233,14 @@ static int __devinit snd_hdsp_create(struct snd_card *card, hdsp->max_channels = 26; hdsp->card = card; - + spin_lock_init(&hdsp->lock); tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp); - + pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev); hdsp->firmware_rev &= 0xff; - + /* From Martin Bjoernsen : "It is important that the card's latency timer register in the PCI configuration space is set to a value much larger @@ -4904,7 +5249,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, to its maximum 255 to avoid problems with some computers." */ pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF); - + strcpy(card->driver, "H-DSP"); strcpy(card->mixername, "Xilinx FPGA"); @@ -4918,7 +5263,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, } else { hdsp->card_name = "RME HDSP 9632"; hdsp->max_channels = 16; - is_9632 = 1; + is_9632 = 1; } if ((err = pci_enable_device(pci)) < 0) @@ -4930,73 +5275,83 @@ static int __devinit snd_hdsp_create(struct snd_card *card, return err; hdsp->port = pci_resource_start(pci, 0); if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) { - snd_printk(KERN_ERR "Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); + 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_DISABLED|IRQF_SHARED, "hdsp", (void *)hdsp)) { - snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); + if (request_irq(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; } hdsp->irq = pci->irq; - hdsp->precise_ptr = 1; + hdsp->precise_ptr = 0; hdsp->use_midi_tasklet = 1; + hdsp->dds_value = 0; if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) return err; - + if (!is_9652 && !is_9632) { - /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ - ssleep(2); + /* we wait a maximum of 10 seconds to let freshly + * inserted cardbus cards do their hardware init */ + err = hdsp_wait_for_iobox(hdsp, 1000, 10); + + if (err < 0) + return err; if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { -#ifdef HDSP_FW_LOADER if ((err = hdsp_request_fw_loader(hdsp)) < 0) /* we don't fail as this can happen if userspace is not ready for firmware upload */ - snd_printk(KERN_ERR "Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n"); + dev_err(hdsp->card->dev, + "couldn't get firmware from userspace. try using hdsploader\n"); else /* init is complete, we return */ return 0; -#endif - /* no iobox connected, we defer initialization */ - snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n"); + /* we defer initialization */ + dev_info(hdsp->card->dev, + "card initialization pending : waiting for firmware\n"); if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) return err; return 0; } else { - snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n"); - if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) + dev_info(hdsp->card->dev, + "Firmware already present, initializing card.\n"); + if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2) + hdsp->io_type = RPM; + else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) hdsp->io_type = Multiface; - else + else hdsp->io_type = Digiface; } } - + if ((err = snd_hdsp_enable_io(hdsp)) != 0) return err; - + if (is_9652) hdsp->io_type = H9652; - + if (is_9632) hdsp->io_type = H9632; if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) return err; - + snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); - hdsp->state |= HDSP_FirmwareLoaded; + hdsp->state |= HDSP_FirmwareLoaded; if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0) return err; - return 0; + return 0; } static int snd_hdsp_free(struct hdsp *hdsp) @@ -5012,27 +5367,31 @@ static int snd_hdsp_free(struct hdsp *hdsp) free_irq(hdsp->irq, (void *)hdsp); snd_hdsp_free_buffers(hdsp); - + + if (hdsp->firmware) + release_firmware(hdsp->firmware); + vfree(hdsp->fw_uploaded); + if (hdsp->iobase) 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 = (struct hdsp *) card->private_data; + struct hdsp *hdsp = card->private_data; if (hdsp) snd_hdsp_free(hdsp); } -static int __devinit snd_hdsp_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) +static int snd_hdsp_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) { static int dev; struct hdsp *hdsp; @@ -5046,14 +5405,15 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci, return -ENOENT; } - if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp)))) - return -ENOMEM; + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, + sizeof(struct hdsp), &card); + if (err < 0) + return err; - hdsp = (struct hdsp *) card->private_data; + hdsp = card->private_data; card->private_free = snd_hdsp_card_free; hdsp->dev = dev; hdsp->pci = pci; - snd_card_set_dev(card, &pci->dev); if ((err = snd_hdsp_create(card, hdsp)) < 0) { snd_card_free(card); @@ -5061,7 +5421,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci, } strcpy(card->shortname, "Hammerfall DSP"); - sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, + sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, hdsp->port, hdsp->irq); if ((err = snd_card_register(card)) < 0) { @@ -5073,28 +5433,16 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci, return 0; } -static void __devexit snd_hdsp_remove(struct pci_dev *pci) +static void snd_hdsp_remove(struct pci_dev *pci) { snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); } -static struct pci_driver driver = { - .name = "RME Hammerfall DSP", +static struct pci_driver hdsp_driver = { + .name = KBUILD_MODNAME, .id_table = snd_hdsp_ids, .probe = snd_hdsp_probe, - .remove = __devexit_p(snd_hdsp_remove), + .remove = snd_hdsp_remove, }; -static int __init alsa_card_hdsp_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_hdsp_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_hdsp_init) -module_exit(alsa_card_hdsp_exit) +module_pci_driver(hdsp_driver); |
