};
struct davinci_mcbsp_dev {
+ struct device *dev;
struct davinci_pcm_dma_params dma_params[2];
void __iomem *base;
#define MOD_DSP_A 0
unsigned int fmt;
int clk_div;
+ int clk_input_pin;
+ bool i2s_accurate_sck;
};
static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
DAVINCI_MCBSP_PCR_CLKRM;
break;
case SND_SOC_DAIFMT_CBM_CFS:
- /* McBSP CLKR pin is the input for the Sample Rate Generator.
- * McBSP FSR and FSX are driven by the Sample Rate Generator. */
- pcr = DAVINCI_MCBSP_PCR_SCLKME |
- DAVINCI_MCBSP_PCR_FSXM |
- DAVINCI_MCBSP_PCR_FSRM;
+ pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM;
+ /*
+ * Selection of the clock input pin that is the
+ * input for the Sample Rate Generator.
+ * McBSP FSR and FSX are driven by the Sample Rate
+ * Generator.
+ */
+ switch (dev->clk_input_pin) {
+ case MCBSP_CLKS:
+ pcr |= DAVINCI_MCBSP_PCR_CLKXM |
+ DAVINCI_MCBSP_PCR_CLKRM;
+ break;
+ case MCBSP_CLKR:
+ pcr |= DAVINCI_MCBSP_PCR_SCLKME;
+ break;
+ default:
+ dev_err(dev->dev, "bad clk_input_pin\n");
+ return -EINVAL;
+ }
+
break;
case SND_SOC_DAIFMT_CBM_CFM:
/* codec is master */
DAVINCI_MCBSP_SRGR_CLKSM;
srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length *
8 - 1);
- /* symmetric waveforms */
- clk_div = freq / (mcbsp_word_length * 16) /
- params->rate_num * params->rate_den;
- srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length *
- 16 - 1);
+ if (dev->i2s_accurate_sck) {
+ clk_div = 256;
+ do {
+ framesize = (freq / (--clk_div)) /
+ params->rate_num *
+ params->rate_den;
+ } while (((framesize < 33) || (framesize > 4095)) &&
+ (clk_div));
+ clk_div--;
+ srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1);
+ } else {
+ /* symmetric waveforms */
+ clk_div = freq / (mcbsp_word_length * 16) /
+ params->rate_num * params->rate_den;
+ srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length *
+ 16 - 1);
+ }
clk_div &= 0xFF;
srgr |= clk_div;
break;
struct snd_platform_data *pdata = pdev->dev.platform_data;
struct davinci_mcbsp_dev *dev;
struct resource *mem, *ioarea, *res;
+ enum dma_event_q asp_chan_q = EVENTQ_0;
+ enum dma_event_q ram_chan_q = EVENTQ_1;
int ret;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pdata->sram_size_playback;
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size =
pdata->sram_size_capture;
+ dev->clk_input_pin = pdata->clk_input_pin;
+ dev->i2s_accurate_sck = pdata->i2s_accurate_sck;
+ asp_chan_q = pdata->asp_chan_q;
+ ram_chan_q = pdata->ram_chan_q;
}
+
+ dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].asp_chan_q = asp_chan_q;
+ dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].ram_chan_q = ram_chan_q;
+ dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].asp_chan_q = asp_chan_q;
+ dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].ram_chan_q = ram_chan_q;
+
dev->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk)) {
ret = -ENODEV;
goto err_free_mem;
}
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
+ dev->dev = &pdev->dev;
davinci_i2s_dai.private_data = dev;
davinci_i2s_dai.capture.dma_data = dev->dma_params;