Skip to content

Commit

Permalink
ALSA: snd-atmel-ac97c: do not overwrite OCA and ICA when assigning ch…
Browse files Browse the repository at this point in the history
…annels

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>
  • Loading branch information
Hans-Christian Egtvedt authored and Takashi Iwai committed Apr 6, 2009
1 parent d54bb9f commit 128ed6a
Showing 1 changed file with 18 additions and 5 deletions.
23 changes: 18 additions & 5 deletions sound/atmel/ac97c.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Driver for the Atmel AC97C controller
* Driver for Atmel AC97C
*
* Copyright (C) 2005-2009 Atmel Corporation
*
Expand All @@ -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>
Expand Down Expand Up @@ -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:
Expand All @@ -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);
Expand Down Expand Up @@ -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:
Expand All @@ -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);
Expand Down

0 comments on commit 128ed6a

Please sign in to comment.