Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d7e92da authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents c027a474 9f3b2494
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -342,7 +342,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
			kfree(bufs);
			kfree(bufs);
			return -EFAULT;
			return -EFAULT;
		}
		}
		bufs[ch] = compat_ptr(ptr);
		bufs[i] = compat_ptr(ptr);
		bufptr++;
		bufptr++;
	}
	}
	if (dir == SNDRV_PCM_STREAM_PLAYBACK)
	if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+1 −1
Original line number Original line Diff line number Diff line
@@ -22,7 +22,7 @@


#include <linux/init.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/module.h>
#include <linux/log2.h>
#include <linux/log2.h>
#include <sound/core.h>
#include <sound/core.h>
#include <sound/timer.h>
#include <sound/timer.h>
+6 −3
Original line number Original line Diff line number Diff line
@@ -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 pci_dev *dev = os_data;
	struct code_header header;
	struct code_header header;
	char fw_name[20];
	char fw_name[20];
	short err_ret = HPI_ERROR_DSP_FILE_NOT_FOUND;
	int err;
	int err;


	sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
	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);
	HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
	dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL);
	dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL);
	if (!dsp_code->pvt)
	if (!dsp_code->pvt) {
		return HPI_ERROR_MEMORY_ALLOC;
		err_ret = HPI_ERROR_MEMORY_ALLOC;
		goto error2;
	}


	dsp_code->pvt->dev = dev;
	dsp_code->pvt->dev = dev;
	dsp_code->pvt->firmware = firmware;
	dsp_code->pvt->firmware = firmware;
@@ -99,7 +102,7 @@ error2:
	release_firmware(firmware);
	release_firmware(firmware);
error1:
error1:
	dsp_code->block_length = 0;
	dsp_code->block_length = 0;
	return HPI_ERROR_DSP_FILE_NOT_FOUND;
	return err_ret;
}
}


/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
+12 −7
Original line number Original line Diff line number Diff line
@@ -177,16 +177,21 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
	} else {
	} else {
		u16 __user *ptr = NULL;
		u16 __user *ptr = NULL;
		u32 size = 0;
		u32 size = 0;

		u32 adapter_present;
		/* -1=no data 0=read from user mem, 1=write to user mem */
		/* -1=no data 0=read from user mem, 1=write to user mem */
		int wrflag = -1;
		int wrflag = -1;
		u32 adapter = hm->h.adapter_index;
		struct hpi_adapter *pa;
		struct hpi_adapter *pa = &adapters[adapter];

		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)) {
		if (!adapter_present) {
			hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER,
			hpi_init_response(&hr->r0, hm->h.object,
				HPI_ADAPTER_OPEN,
				hm->h.function, HPI_ERROR_BAD_ADAPTER_NUMBER);
				HPI_ERROR_BAD_ADAPTER_NUMBER);


			uncopied_bytes =
			uncopied_bytes =
				copy_to_user(puhr, hr, sizeof(hr->h));
				copy_to_user(puhr, hr, sizeof(hr->h));
+107 −2
Original line number Original line Diff line number Diff line
@@ -521,6 +521,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)


/* revisions >= 230 indicate AES32 card */
/* revisions >= 230 indicate AES32 card */
#define HDSPM_MADI_ANCIENT_REV	204
#define HDSPM_MADI_OLD_REV	207
#define HDSPM_MADI_OLD_REV	207
#define HDSPM_MADI_REV		210
#define HDSPM_MADI_REV		210
#define HDSPM_RAYDAT_REV	211
#define HDSPM_RAYDAT_REV	211
@@ -1217,6 +1218,22 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
				rate = 0;
				rate = 0;
				break;
				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;
		break;
	}
	}
@@ -3415,6 +3432,91 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
	return change;
	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) \
#define HDSPM_MIXER(xname, xindex) \
{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
{ .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_TX_64("TX 64 channels mode", 0),
	HDSPM_C_TMS("Clear Track Marker", 0),
	HDSPM_C_TMS("Clear Track Marker", 0),
	HDSPM_SAFE_MODE("Safe Mode", 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_SYNC_CHECK("MADI SyncCheck", 0),
	HDSPM_TX_64("TX 64 channels mode", 0),
	HDSPM_TX_64("TX 64 channels mode", 0),
	HDSPM_C_TMS("Clear Track Marker", 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[] = {
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) {
	switch (hdspm->firmware_rev) {
	case HDSPM_MADI_REV:
	case HDSPM_MADI_REV:
	case HDSPM_MADI_OLD_REV:
	case HDSPM_MADI_OLD_REV:
	case HDSPM_MADI_ANCIENT_REV:
		hdspm->io_type = MADI;
		hdspm->io_type = MADI;
		hdspm->card_name = "RME MADI";
		hdspm->card_name = "RME MADI";
		hdspm->midiPorts = 3;
		hdspm->midiPorts = 3;
Loading