aboutsummaryrefslogtreecommitdiff
path: root/sound/pci/cs5535audio/cs5535audio_pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/cs5535audio/cs5535audio_pcm.c')
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pcm.c45
1 files changed, 29 insertions, 16 deletions
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
index 5450a9e8f13..9c2dc911d8d 100644
--- a/sound/pci/cs5535audio/cs5535audio_pcm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
@@ -23,9 +23,7 @@
*/
#include <linux/init.h>
-#include <linux/slab.h>
#include <linux/pci.h>
-#include <sound/driver.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/initval.h>
@@ -43,7 +41,6 @@ static struct snd_pcm_hardware snd_cs5535audio_playback =
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_SYNC_START |
SNDRV_PCM_INFO_RESUME
),
.formats = (
@@ -71,8 +68,7 @@ static struct snd_pcm_hardware snd_cs5535audio_capture =
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_SYNC_START
+ SNDRV_PCM_INFO_MMAP_VALID
),
.formats = (
SNDRV_PCM_FMTBIT_S16_LE
@@ -100,9 +96,10 @@ static int snd_cs5535audio_playback_open(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw = snd_cs5535audio_playback;
+ runtime->hw.rates = cs5535au->ac97->rates[AC97_RATES_FRONT_DAC];
+ snd_pcm_limit_hw_rates(runtime);
cs5535au->playback_substream = substream;
runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK]);
- snd_pcm_set_sync(substream);
if ((err = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
@@ -151,8 +148,8 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au,
struct cs5535audio_dma_desc *desc =
&((struct cs5535audio_dma_desc *) dma->desc_buf.area)[i];
desc->addr = cpu_to_le32(addr);
- desc->size = cpu_to_le32(period_bytes);
- desc->ctlreserved = cpu_to_le32(PRD_EOP);
+ desc->size = cpu_to_le16(period_bytes);
+ desc->ctlreserved = cpu_to_le16(PRD_EOP);
desc_addr += sizeof(struct cs5535audio_dma_desc);
addr += period_bytes;
}
@@ -160,10 +157,11 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au,
lastdesc = &((struct cs5535audio_dma_desc *) dma->desc_buf.area)[periods];
lastdesc->addr = cpu_to_le32((u32) dma->desc_buf.addr);
lastdesc->size = 0;
- lastdesc->ctlreserved = cpu_to_le32(PRD_JMP);
+ lastdesc->ctlreserved = cpu_to_le16(PRD_JMP);
jmpprd_addr = cpu_to_le32(lastdesc->addr +
(sizeof(struct cs5535audio_dma_desc)*periods));
+ dma->substream = substream;
dma->period_bytes = period_bytes;
dma->periods = periods;
spin_lock_irq(&cs5535au->reg_lock);
@@ -241,6 +239,7 @@ static void cs5535audio_clear_dma_packets(struct cs5535audio *cs5535au,
{
snd_dma_free_pages(&dma->desc_buf);
dma->desc_buf.area = NULL;
+ dma->substream = NULL;
}
static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream,
@@ -260,6 +259,9 @@ static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream,
err = cs5535audio_build_dma_packets(cs5535au, dma, substream,
params_periods(hw_params),
params_period_bytes(hw_params));
+ if (!err)
+ dma->pcm_open_flag = 1;
+
return err;
}
@@ -268,6 +270,15 @@ static int snd_cs5535audio_hw_free(struct snd_pcm_substream *substream)
struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
struct cs5535audio_dma *dma = substream->runtime->private_data;
+ if (dma->pcm_open_flag) {
+ if (substream == cs5535au->playback_substream)
+ snd_ac97_update_power(cs5535au->ac97,
+ AC97_PCM_FRONT_DAC_RATE, 0);
+ else
+ snd_ac97_update_power(cs5535au->ac97,
+ AC97_PCM_LR_ADC_RATE, 0);
+ dma->pcm_open_flag = 0;
+ }
cs5535audio_clear_dma_packets(cs5535au, dma, substream);
return snd_pcm_lib_free_pages(substream);
}
@@ -298,17 +309,15 @@ static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd)
break;
case SNDRV_PCM_TRIGGER_RESUME:
dma->ops->enable_dma(cs5535au);
- dma->suspended = 0;
break;
case SNDRV_PCM_TRIGGER_STOP:
dma->ops->disable_dma(cs5535au);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
dma->ops->disable_dma(cs5535au);
- dma->suspended = 1;
break;
default:
- snd_printk(KERN_ERR "unhandled trigger\n");
+ dev_err(cs5535au->card->dev, "unhandled trigger\n");
err = -EINVAL;
break;
}
@@ -326,13 +335,13 @@ static snd_pcm_uframes_t snd_cs5535audio_pcm_pointer(struct snd_pcm_substream
dma = substream->runtime->private_data;
curdma = dma->ops->read_dma_pntr(cs5535au);
if (curdma < dma->buf_addr) {
- snd_printk(KERN_ERR "curdma=%x < %x bufaddr.\n",
+ dev_err(cs5535au->card->dev, "curdma=%x < %x bufaddr.\n",
curdma, dma->buf_addr);
return 0;
}
curdma -= dma->buf_addr;
if (curdma >= dma->buf_bytes) {
- snd_printk(KERN_ERR "diff=%x >= %x buf_bytes.\n",
+ dev_err(cs5535au->card->dev, "diff=%x >= %x buf_bytes.\n",
curdma, dma->buf_bytes);
return 0;
}
@@ -346,17 +355,21 @@ static int snd_cs5535audio_capture_open(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw = snd_cs5535audio_capture;
+ runtime->hw.rates = cs5535au->ac97->rates[AC97_RATES_ADC];
+ snd_pcm_limit_hw_rates(runtime);
cs5535au->capture_substream = substream;
runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE]);
- snd_pcm_set_sync(substream);
if ((err = snd_pcm_hw_constraint_integer(runtime,
SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
+ olpc_capture_open(cs5535au->ac97);
return 0;
}
static int snd_cs5535audio_capture_close(struct snd_pcm_substream *substream)
{
+ struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
+ olpc_capture_close(cs5535au->ac97);
return 0;
}
@@ -409,7 +422,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = {
.read_dma_pntr = cs5535audio_capture_read_dma_pntr,
};
-int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
+int snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
{
struct snd_pcm *pcm;
int err;