Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 Aug 2011 06:48:22 +0000 (20:48 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 Aug 2011 06:48:22 +0000 (20:48 -1000)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: asihpi - Clarify adapter index validity check
  ALSA: asihpi - Don't leak firmware if mem alloc fails
  ALSA: rtctimer.c needs module.h
  ASoC: Fix txx9aclc.c build
  ALSA: hdspm - Add firmware revision 0xcc for RME MADI
  ALSA: hdspm - Fix reported external sample rate on RME MADI and MADIface
  ALSA: hdspm - Provide MADI speed mode selector on RME MADI and MADIface
  ALSA: sound/core/pcm_compat.c: adjust array index

sound/core/pcm_compat.c
sound/core/rtctimer.c
sound/pci/asihpi/hpidspcd.c
sound/pci/asihpi/hpioctl.c
sound/pci/rme9652/hdspm.c
sound/soc/txx9/txx9aclc.c

index 5fb2e28..91cdf94 100644 (file)
@@ -342,7 +342,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
                        kfree(bufs);
                        return -EFAULT;
                }
-               bufs[ch] = compat_ptr(ptr);
+               bufs[i] = compat_ptr(ptr);
                bufptr++;
        }
        if (dir == SNDRV_PCM_STREAM_PLAYBACK)
index 0851cd1..e85e72b 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
 #include <linux/log2.h>
 #include <sound/core.h>
 #include <sound/timer.h>
index 3a7afa3..71d32c8 100644 (file)
@@ -43,6 +43,7 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
        struct pci_dev *dev = os_data;
        struct code_header header;
        char fw_name[20];
+       short err_ret = HPI_ERROR_DSP_FILE_NOT_FOUND;
        int err;
 
        sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
@@ -85,8 +86,10 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
 
        HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
        dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL);
-       if (!dsp_code->pvt)
-               return HPI_ERROR_MEMORY_ALLOC;
+       if (!dsp_code->pvt) {
+               err_ret = HPI_ERROR_MEMORY_ALLOC;
+               goto error2;
+       }
 
        dsp_code->pvt->dev = dev;
        dsp_code->pvt->firmware = firmware;
@@ -99,7 +102,7 @@ error2:
        release_firmware(firmware);
 error1:
        dsp_code->block_length = 0;
-       return HPI_ERROR_DSP_FILE_NOT_FOUND;
+       return err_ret;
 }
 
 /*-------------------------------------------------------------------*/
index 9683f84..a32502e 100644 (file)
@@ -177,16 +177,21 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        } else {
                u16 __user *ptr = NULL;
                u32 size = 0;
-
+               u32 adapter_present;
                /* -1=no data 0=read from user mem, 1=write to user mem */
                int wrflag = -1;
-               u32 adapter = hm->h.adapter_index;
-               struct hpi_adapter *pa = &adapters[adapter];
+               struct hpi_adapter *pa;
+
+               if (hm->h.adapter_index < HPI_MAX_ADAPTERS) {
+                       pa = &adapters[hm->h.adapter_index];
+                       adapter_present = pa->type;
+               } else {
+                       adapter_present = 0;
+               }
 
-               if ((adapter >= HPI_MAX_ADAPTERS) || (!pa->type)) {
-                       hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER,
-                               HPI_ADAPTER_OPEN,
-                               HPI_ERROR_BAD_ADAPTER_NUMBER);
+               if (!adapter_present) {
+                       hpi_init_response(&hr->r0, hm->h.object,
+                               hm->h.function, HPI_ERROR_BAD_ADAPTER_NUMBER);
 
                        uncopied_bytes =
                                copy_to_user(puhr, hr, sizeof(hr->h));
index af130ee..6edc67c 100644 (file)
@@ -521,6 +521,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
 
 /* revisions >= 230 indicate AES32 card */
+#define HDSPM_MADI_ANCIENT_REV 204
 #define HDSPM_MADI_OLD_REV     207
 #define HDSPM_MADI_REV         210
 #define HDSPM_RAYDAT_REV       211
@@ -1217,6 +1218,22 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
                                rate = 0;
                                break;
                        }
+
+                       /* QS and DS rates normally can not be detected
+                        * automatically by the card. Only exception is MADI
+                        * in 96k frame mode.
+                        *
+                        * So if we read SS values (32 .. 48k), check for
+                        * user-provided DS/QS bits in the control register
+                        * and multiply the base frequency accordingly.
+                        */
+                       if (rate <= 48000) {
+                               if (hdspm->control_register & HDSPM_QuadSpeed)
+                                       rate *= 4;
+                               else if (hdspm->control_register &
+                                               HDSPM_DoubleSpeed)
+                                       rate *= 2;
+                       }
                }
                break;
        }
@@ -3415,6 +3432,91 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
        return change;
 }
 
+#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_madi_speedmode, \
+       .get = snd_hdspm_get_madi_speedmode, \
+       .put = snd_hdspm_put_madi_speedmode \
+}
+
+static int hdspm_madi_speedmode(struct hdspm *hdspm)
+{
+       if (hdspm->control_register & HDSPM_QuadSpeed)
+               return 2;
+       if (hdspm->control_register & HDSPM_DoubleSpeed)
+               return 1;
+       return 0;
+}
+
+static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
+{
+       hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
+       switch (mode) {
+       case 0:
+               break;
+       case 1:
+               hdspm->control_register |= HDSPM_DoubleSpeed;
+               break;
+       case 2:
+               hdspm->control_register |= HDSPM_QuadSpeed;
+               break;
+       }
+       hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+       return 0;
+}
+
+static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_info *uinfo)
+{
+       static char *texts[] = { "Single", "Double", "Quad" };
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 3;
+
+       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 snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+       spin_lock_irq(&hdspm->lock);
+       ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
+       spin_unlock_irq(&hdspm->lock);
+       return 0;
+}
+
+static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+       int change;
+       int val;
+
+       if (!snd_hdspm_use_is_exclusive(hdspm))
+               return -EBUSY;
+       val = ucontrol->value.integer.value[0];
+       if (val < 0)
+               val = 0;
+       if (val > 2)
+               val = 2;
+       spin_lock_irq(&hdspm->lock);
+       change = val != hdspm_madi_speedmode(hdspm);
+       hdspm_set_madi_speedmode(hdspm, val);
+       spin_unlock_irq(&hdspm->lock);
+       return change;
+}
 
 #define HDSPM_MIXER(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
@@ -4289,7 +4391,8 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
        HDSPM_TX_64("TX 64 channels mode", 0),
        HDSPM_C_TMS("Clear Track Marker", 0),
        HDSPM_SAFE_MODE("Safe Mode", 0),
-       HDSPM_INPUT_SELECT("Input Select", 0)
+       HDSPM_INPUT_SELECT("Input Select", 0),
+       HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
 };
 
 
@@ -4302,7 +4405,8 @@ static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
        HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
        HDSPM_TX_64("TX 64 channels mode", 0),
        HDSPM_C_TMS("Clear Track Marker", 0),
-       HDSPM_SAFE_MODE("Safe Mode", 0)
+       HDSPM_SAFE_MODE("Safe Mode", 0),
+       HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
 };
 
 static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
@@ -6381,6 +6485,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
        switch (hdspm->firmware_rev) {
        case HDSPM_MADI_REV:
        case HDSPM_MADI_OLD_REV:
+       case HDSPM_MADI_ANCIENT_REV:
                hdspm->io_type = MADI;
                hdspm->card_name = "RME MADI";
                hdspm->midiPorts = 3;
index 34aa972..3de99af 100644 (file)
@@ -290,6 +290,7 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static int txx9aclc_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_card *card = rtd->card->snd_card;
        struct snd_soc_dai *dai = rtd->cpu_dai;
        struct snd_pcm *pcm = rtd->pcm;
        struct platform_device *pdev = to_platform_device(dai->platform->dev);