static int mxs_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; struct mxs_runtime_data *prtd = substream->runtime->private_data; int ret = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: if ((prtd->params->dma_ch == MXS_DMA_CHANNEL_AHB_APBX_SPDIF) && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) && (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) && ((prtd->format == SNDRV_PCM_FORMAT_S24_LE) || (prtd->format == SNDRV_PCM_FORMAT_S20_3LE))) { prtd->appl_ptr_bytes = frames_to_bytes(runtime, runtime->control->appl_ptr); memmove(runtime->dma_area + 1, runtime->dma_area, prtd->appl_ptr_bytes - 1); } mxs_dma_enable(prtd->dma_ch); break; case SNDRV_PCM_TRIGGER_STOP: mxs_pcm_stop(substream); break; case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: mxs_dma_unfreeze(prtd->dma_ch); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: mxs_dma_freeze(prtd->dma_ch); break; default: ret = -EINVAL; break; } return ret; }
int submit_request(struct mxs_hsadc_data* pdx, unsigned long count) { unsigned long sample_count; memset(pdx->buf, 0, count); pdx->desc->cmd.cmd.bits.bytes = count; pdx->desc->cmd.cmd.bits.pio_words = 0; pdx->desc->cmd.cmd.bits.wait4end = 1; pdx->desc->cmd.cmd.bits.dec_sem = 1; pdx->desc->cmd.cmd.bits.irq = 1; pdx->desc->cmd.cmd.bits.command = DMA_WRITE; pdx->desc->cmd.address = pdx->buf_phy; if(mxs_dma_desc_append(pdx->dma_ch, pdx->desc)) { return -EINVAL; } // // byte(s) to sample count // sample_count = adc_sample_percision == 8 ? count : (count >> 1); // 10-bit & 12-bit mode a sample word is two bytes size writel(sample_count, pdx->hsadc_base + HSADC_SEQUENCE_SAMPLES_NUM); writel(1, pdx->hsadc_base + HSADC_SEQUENCE_NUM); writel(1<<31 | 1<<30 | 1<<29, pdx->hsadc_base + HSADC_CTRL1); // enable irq mxs_dma_reset(pdx->dma_ch); mxs_dma_ack_irq(pdx->dma_ch); mxs_dma_enable_irq(pdx->dma_ch, 1); if(mxs_dma_enable(pdx->dma_ch)) { return -EINVAL; } writel(RUN, pdx->hsadc_base + HSADC_CTRL0_SET); writel(SOFT_TRIGGER, pdx->hsadc_base + HSADC_CTRL0_SET); return 0; }