ALSA: snd-atmel-ac97c: do not overwrite OCA and ICA when assigning channels
This patch will take care not to overwrite OCA and ICA registers when assigning input and output channels. It will also make sure the registers are at a known state when enabling a channel and clean up properly in case of an error. Signed-off-by: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
d54bb9f0c5
commit
128ed6a926
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Driver for the Atmel AC97C controller
|
||||
* Driver for Atmel AC97C
|
||||
*
|
||||
* Copyright (C) 2005-2009 Atmel Corporation
|
||||
*
|
||||
|
@ -10,6 +10,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -297,9 +298,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
|
|||
{
|
||||
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
unsigned long word = 0;
|
||||
unsigned long word = ac97c_readl(chip, OCA);
|
||||
int retval;
|
||||
|
||||
word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
|
||||
|
||||
/* assign channels to AC97C channel A */
|
||||
switch (runtime->channels) {
|
||||
case 1:
|
||||
|
@ -323,9 +326,13 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
|
|||
word |= AC97C_CMR_CEM_LITTLE;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
|
||||
default:
|
||||
word &= ~(AC97C_CMR_CEM_LITTLE);
|
||||
break;
|
||||
default:
|
||||
word = ac97c_readl(chip, OCA);
|
||||
word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
|
||||
ac97c_writel(chip, OCA, word);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ac97c_writel(chip, CAMR, word);
|
||||
|
@ -358,9 +365,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
|
|||
{
|
||||
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
unsigned long word = 0;
|
||||
unsigned long word = ac97c_readl(chip, ICA);
|
||||
int retval;
|
||||
|
||||
word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
|
||||
|
||||
/* assign channels to AC97C channel A */
|
||||
switch (runtime->channels) {
|
||||
case 1:
|
||||
|
@ -384,9 +393,13 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
|
|||
word |= AC97C_CMR_CEM_LITTLE;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
|
||||
default:
|
||||
word &= ~(AC97C_CMR_CEM_LITTLE);
|
||||
break;
|
||||
default:
|
||||
word = ac97c_readl(chip, ICA);
|
||||
word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
|
||||
ac97c_writel(chip, ICA, word);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ac97c_writel(chip, CAMR, word);
|
||||
|
|
Loading…
Reference in New Issue