aboutsummaryrefslogtreecommitdiffstats
path: root/sound/atmel
diff options
context:
space:
mode:
authorHans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>2009-04-02 02:21:12 -0400
committerTakashi Iwai <tiwai@suse.de>2009-04-05 21:55:08 -0400
commit128ed6a9266daac5d7b0e082339742e16caf7caa (patch)
treef6e1fa1fd74437933a6c16d553aff6b304b896bc /sound/atmel
parentd54bb9f0c57e39a9a7c8ba523f2c0c1a955d8efb (diff)
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>
Diffstat (limited to 'sound/atmel')
-rw-r--r--sound/atmel/ac97c.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 21be9c9fbd53..4e8f66d40812 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Driver for the Atmel AC97C controller 2 * Driver for Atmel AC97C
3 * 3 *
4 * Copyright (C) 2005-2009 Atmel Corporation 4 * Copyright (C) 2005-2009 Atmel Corporation
5 * 5 *
@@ -10,6 +10,7 @@
10#include <linux/clk.h> 10#include <linux/clk.h>
11#include <linux/delay.h> 11#include <linux/delay.h>
12#include <linux/bitmap.h> 12#include <linux/bitmap.h>
13#include <linux/device.h>
13#include <linux/dmaengine.h> 14#include <linux/dmaengine.h>
14#include <linux/dma-mapping.h> 15#include <linux/dma-mapping.h>
15#include <linux/init.h> 16#include <linux/init.h>
@@ -297,9 +298,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
297{ 298{
298 struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 299 struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
299 struct snd_pcm_runtime *runtime = substream->runtime; 300 struct snd_pcm_runtime *runtime = substream->runtime;
300 unsigned long word = 0; 301 unsigned long word = ac97c_readl(chip, OCA);
301 int retval; 302 int retval;
302 303
304 word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
305
303 /* assign channels to AC97C channel A */ 306 /* assign channels to AC97C channel A */
304 switch (runtime->channels) { 307 switch (runtime->channels) {
305 case 1: 308 case 1:
@@ -323,9 +326,13 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
323 word |= AC97C_CMR_CEM_LITTLE; 326 word |= AC97C_CMR_CEM_LITTLE;
324 break; 327 break;
325 case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ 328 case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
326 default:
327 word &= ~(AC97C_CMR_CEM_LITTLE); 329 word &= ~(AC97C_CMR_CEM_LITTLE);
328 break; 330 break;
331 default:
332 word = ac97c_readl(chip, OCA);
333 word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
334 ac97c_writel(chip, OCA, word);
335 return -EINVAL;
329 } 336 }
330 337
331 ac97c_writel(chip, CAMR, word); 338 ac97c_writel(chip, CAMR, word);
@@ -358,9 +365,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
358{ 365{
359 struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); 366 struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
360 struct snd_pcm_runtime *runtime = substream->runtime; 367 struct snd_pcm_runtime *runtime = substream->runtime;
361 unsigned long word = 0; 368 unsigned long word = ac97c_readl(chip, ICA);
362 int retval; 369 int retval;
363 370
371 word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
372
364 /* assign channels to AC97C channel A */ 373 /* assign channels to AC97C channel A */
365 switch (runtime->channels) { 374 switch (runtime->channels) {
366 case 1: 375 case 1:
@@ -384,9 +393,13 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
384 word |= AC97C_CMR_CEM_LITTLE; 393 word |= AC97C_CMR_CEM_LITTLE;
385 break; 394 break;
386 case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ 395 case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
387 default:
388 word &= ~(AC97C_CMR_CEM_LITTLE); 396 word &= ~(AC97C_CMR_CEM_LITTLE);
389 break; 397 break;
398 default:
399 word = ac97c_readl(chip, ICA);
400 word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
401 ac97c_writel(chip, ICA, word);
402 return -EINVAL;
390 } 403 }
391 404
392 ac97c_writel(chip, CAMR, word); 405 ac97c_writel(chip, CAMR, word);