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

Commit 58e8a474 authored by Russell King's avatar Russell King
Browse files

ALSA: AACI: fix channel mask selection



When double-rate mode was selected, we weren't setting the additional
two channel mask bits to allow double-rate to work.  Rearrange the
hw_params code to allow the correct channel mask to be selected.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent e831d80b
Loading
Loading
Loading
Loading
+20 −50
Original line number Diff line number Diff line
@@ -490,12 +490,21 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
	return 0;
}

/* Channel to slot mask */
static const u32 channels_to_slotmask[] = {
	[2] = CR_SL3 | CR_SL4,
	[4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
	[6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
};

static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
			      struct aaci_runtime *aacirun,
			      struct snd_pcm_hw_params *params)
{
	struct aaci_runtime *aacirun = substream->runtime->private_data;
	unsigned int channels = params_channels(params);
	unsigned int rate = params_rate(params);
	int dbl = rate > 48000;
	int err;
	struct aaci *aaci = substream->private_data;

	aaci_pcm_hw_free(substream);
	if (aacirun->pcm_open) {
@@ -503,18 +512,21 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
		aacirun->pcm_open = 0;
	}

	/* channels is already limited to 2, 4, or 6 by aaci_rule_channels */
	if (dbl && channels != 2)
		return -EINVAL;

	err = snd_pcm_lib_malloc_pages(substream,
				       params_buffer_bytes(params));
	if (err >= 0) {
		unsigned int rate = params_rate(params);
		int dbl = rate > 48000;
		struct aaci *aaci = substream->private_data;

		err = snd_ac97_pcm_open(aacirun->pcm, rate,
					params_channels(params),
		err = snd_ac97_pcm_open(aacirun->pcm, rate, channels,
					aacirun->pcm->r[dbl].slots);

		aacirun->pcm_open = err == 0;
		aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
		aacirun->cr |= channels_to_slotmask[channels + dbl * 2];
		aacirun->fifosz = aaci->fifosize * 4;

		if (aacirun->cr & CR_COMPACT)
@@ -551,34 +563,6 @@ static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream)
/*
 * Playback specific ALSA stuff
 */
static const u32 channels_to_txmask[] = {
	[2] = CR_SL3 | CR_SL4,
	[4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
	[6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
};

static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
				       struct snd_pcm_hw_params *params)
{
	struct aaci_runtime *aacirun = substream->runtime->private_data;
	unsigned int channels = params_channels(params);
	int ret;

	WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) ||
		!channels_to_txmask[channels]);

	ret = aaci_pcm_hw_params(substream, aacirun, params);

	/*
	 * Enable FIFO, compact mode, 16 bits per sample.
	 * FIXME: double rate slots?
	 */
	if (ret >= 0)
		aacirun->cr |= channels_to_txmask[channels];

	return ret;
}

static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
{
	u32 ie;
@@ -648,27 +632,13 @@ static struct snd_pcm_ops aaci_playback_ops = {
	.open		= aaci_pcm_open,
	.close		= aaci_pcm_close,
	.ioctl		= snd_pcm_lib_ioctl,
	.hw_params	= aaci_pcm_playback_hw_params,
	.hw_params	= aaci_pcm_hw_params,
	.hw_free	= aaci_pcm_hw_free,
	.prepare	= aaci_pcm_prepare,
	.trigger	= aaci_pcm_playback_trigger,
	.pointer	= aaci_pcm_pointer,
};

static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream,
				      struct snd_pcm_hw_params *params)
{
	struct aaci_runtime *aacirun = substream->runtime->private_data;
	int ret;

	ret = aaci_pcm_hw_params(substream, aacirun, params);
	if (ret >= 0)
		/* Line in record: slot 3 and 4 */
		aacirun->cr |= CR_SL3 | CR_SL4;

	return ret;
}

static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)
{
	u32 ie;
@@ -765,7 +735,7 @@ static struct snd_pcm_ops aaci_capture_ops = {
	.open		= aaci_pcm_open,
	.close		= aaci_pcm_close,
	.ioctl		= snd_pcm_lib_ioctl,
	.hw_params	= aaci_pcm_capture_hw_params,
	.hw_params	= aaci_pcm_hw_params,
	.hw_free	= aaci_pcm_hw_free,
	.prepare	= aaci_pcm_capture_prepare,
	.trigger	= aaci_pcm_capture_trigger,