|
@@ -71,7 +71,7 @@ void tw686x_audio_irq(struct tw686x_dev *dev, unsigned long requests,
|
|
|
desc = &ac->dma_descs[pb];
|
|
|
if (desc->virt) {
|
|
|
memcpy(done->virt, desc->virt,
|
|
|
- desc->size);
|
|
|
+ dev->period_size);
|
|
|
} else {
|
|
|
u32 reg = pb ? ADMA_B_ADDR[ch] : ADMA_P_ADDR[ch];
|
|
|
reg_write(dev, reg, next->dma);
|
|
@@ -93,10 +93,11 @@ static int tw686x_pcm_hw_free(struct snd_pcm_substream *ss)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * The audio device rate is global and shared among all
|
|
|
+ * Audio parameters are global and shared among all
|
|
|
* capture channels. The driver makes no effort to prevent
|
|
|
- * rate modifications. User is free change the rate, but it
|
|
|
- * means changing the rate for all capture sub-devices.
|
|
|
+ * any modifications. User is free change the audio rate,
|
|
|
+ * or period size, thus changing parameters for all capture
|
|
|
+ * sub-devices.
|
|
|
*/
|
|
|
static const struct snd_pcm_hardware tw686x_capture_hw = {
|
|
|
.info = (SNDRV_PCM_INFO_MMAP |
|
|
@@ -109,9 +110,9 @@ static const struct snd_pcm_hardware tw686x_capture_hw = {
|
|
|
.rate_max = 48000,
|
|
|
.channels_min = 1,
|
|
|
.channels_max = 1,
|
|
|
- .buffer_bytes_max = TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ,
|
|
|
- .period_bytes_min = TW686X_AUDIO_PAGE_SZ,
|
|
|
- .period_bytes_max = TW686X_AUDIO_PAGE_SZ,
|
|
|
+ .buffer_bytes_max = TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX,
|
|
|
+ .period_bytes_min = AUDIO_DMA_SIZE_MIN,
|
|
|
+ .period_bytes_max = AUDIO_DMA_SIZE_MAX,
|
|
|
.periods_min = TW686X_AUDIO_PERIODS_MIN,
|
|
|
.periods_max = TW686X_AUDIO_PERIODS_MAX,
|
|
|
};
|
|
@@ -166,12 +167,21 @@ static int tw686x_pcm_prepare(struct snd_pcm_substream *ss)
|
|
|
reg_write(dev, AUDIO_CONTROL2, reg);
|
|
|
}
|
|
|
|
|
|
- if (period_size != TW686X_AUDIO_PAGE_SZ ||
|
|
|
- rt->periods < TW686X_AUDIO_PERIODS_MIN ||
|
|
|
- rt->periods > TW686X_AUDIO_PERIODS_MAX) {
|
|
|
- return -EINVAL;
|
|
|
+ if (dev->period_size != period_size) {
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ dev->period_size = period_size;
|
|
|
+ reg = reg_read(dev, AUDIO_CONTROL1);
|
|
|
+ reg &= ~(AUDIO_DMA_SIZE_MASK << AUDIO_DMA_SIZE_SHIFT);
|
|
|
+ reg |= period_size << AUDIO_DMA_SIZE_SHIFT;
|
|
|
+
|
|
|
+ reg_write(dev, AUDIO_CONTROL1, reg);
|
|
|
}
|
|
|
|
|
|
+ if (rt->periods < TW686X_AUDIO_PERIODS_MIN ||
|
|
|
+ rt->periods > TW686X_AUDIO_PERIODS_MAX)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
spin_lock_irqsave(&ac->lock, flags);
|
|
|
INIT_LIST_HEAD(&ac->buf_list);
|
|
|
|
|
@@ -282,8 +292,8 @@ static int tw686x_snd_pcm_init(struct tw686x_dev *dev)
|
|
|
return snd_pcm_lib_preallocate_pages_for_all(pcm,
|
|
|
SNDRV_DMA_TYPE_DEV,
|
|
|
snd_dma_pci_data(dev->pci_dev),
|
|
|
- TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ,
|
|
|
- TW686X_AUDIO_PAGE_MAX * TW686X_AUDIO_PAGE_SZ);
|
|
|
+ TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX,
|
|
|
+ TW686X_AUDIO_PAGE_MAX * AUDIO_DMA_SIZE_MAX);
|
|
|
}
|
|
|
|
|
|
static void tw686x_audio_dma_free(struct tw686x_dev *dev,
|
|
@@ -318,7 +328,7 @@ static int tw686x_audio_dma_alloc(struct tw686x_dev *dev,
|
|
|
u32 reg = pb ? ADMA_B_ADDR[ac->ch] : ADMA_P_ADDR[ac->ch];
|
|
|
void *virt;
|
|
|
|
|
|
- virt = pci_alloc_consistent(dev->pci_dev, TW686X_AUDIO_PAGE_SZ,
|
|
|
+ virt = pci_alloc_consistent(dev->pci_dev, AUDIO_DMA_SIZE_MAX,
|
|
|
&ac->dma_descs[pb].phys);
|
|
|
if (!virt) {
|
|
|
dev_err(&dev->pci_dev->dev,
|
|
@@ -327,7 +337,7 @@ static int tw686x_audio_dma_alloc(struct tw686x_dev *dev,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
ac->dma_descs[pb].virt = virt;
|
|
|
- ac->dma_descs[pb].size = TW686X_AUDIO_PAGE_SZ;
|
|
|
+ ac->dma_descs[pb].size = AUDIO_DMA_SIZE_MAX;
|
|
|
reg_write(dev, reg, ac->dma_descs[pb].phys);
|
|
|
}
|
|
|
return 0;
|
|
@@ -358,12 +368,8 @@ int tw686x_audio_init(struct tw686x_dev *dev)
|
|
|
struct snd_card *card;
|
|
|
int err, ch;
|
|
|
|
|
|
- /*
|
|
|
- * AUDIO_CONTROL1
|
|
|
- * DMA byte length [31:19] = 4096 (i.e. ALSA period)
|
|
|
- * External audio enable [0] = enabled
|
|
|
- */
|
|
|
- reg_write(dev, AUDIO_CONTROL1, 0x80000001);
|
|
|
+ /* Enable external audio */
|
|
|
+ reg_write(dev, AUDIO_CONTROL1, BIT(0));
|
|
|
|
|
|
err = snd_card_new(&pci_dev->dev, SNDRV_DEFAULT_IDX1,
|
|
|
SNDRV_DEFAULT_STR1,
|