Loading sound/soc/davinci/Kconfig +5 −5 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ config SND_DAVINCI_SOC_GENERIC_EVM config SND_AM33XX_SOC_EVM tristate "SoC Audio for the AM33XX chip based boards" depends on SND_DAVINCI_SOC && SOC_AM33XX depends on SND_DAVINCI_SOC && SOC_AM33XX && I2C select SND_DAVINCI_SOC_GENERIC_EVM help Say Y or M if you want to add support for SoC audio on AM33XX Loading @@ -28,7 +28,7 @@ config SND_AM33XX_SOC_EVM config SND_DAVINCI_SOC_EVM tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" depends on SND_DAVINCI_SOC depends on SND_DAVINCI_SOC && I2C depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM select SND_DAVINCI_SOC_GENERIC_EVM help Loading Loading @@ -56,7 +56,7 @@ endchoice config SND_DM6467_SOC_EVM tristate "SoC Audio support for DaVinci DM6467 EVM" depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM && I2C select SND_DAVINCI_SOC_GENERIC_EVM select SND_SOC_SPDIF Loading @@ -65,7 +65,7 @@ config SND_DM6467_SOC_EVM config SND_DA830_SOC_EVM tristate "SoC Audio support for DA830/OMAP-L137 EVM" depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM && I2C select SND_DAVINCI_SOC_GENERIC_EVM help Loading @@ -74,7 +74,7 @@ config SND_DA830_SOC_EVM config SND_DA850_SOC_EVM tristate "SoC Audio support for DA850/OMAP-L138 EVM" depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM && I2C select SND_DAVINCI_SOC_GENERIC_EVM help Say Y if you want to add support for SoC audio on TI Loading sound/soc/davinci/davinci-i2s.c +0 −1 Original line number Diff line number Diff line Loading @@ -757,7 +757,6 @@ static int davinci_i2s_remove(struct platform_device *pdev) struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); snd_soc_unregister_component(&pdev->dev); davinci_soc_platform_unregister(&pdev->dev); clk_disable(dev->clk); clk_put(dev->clk); Loading sound/soc/davinci/davinci-mcasp.c +161 −99 Original line number Diff line number Diff line Loading @@ -36,6 +36,9 @@ #include "davinci-pcm.h" #include "davinci-mcasp.h" #include "../omap/omap-pcm.h" #define MCASP_MAX_AFIFO_DEPTH 64 struct davinci_mcasp_context { u32 txfmtctl; Loading Loading @@ -269,25 +272,51 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); int ret = 0; u32 data_delay; bool fs_pol_rising; bool inv_fs = false; pm_runtime_get_sync(mcasp->dev); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); /* 1st data bit occur one ACLK cycle after the frame sync */ data_delay = 1; break; case SND_SOC_DAIFMT_DSP_B: case SND_SOC_DAIFMT_AC97: mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); /* No delay after FS */ data_delay = 0; break; default: case SND_SOC_DAIFMT_I2S: /* configure a full-word SYNC pulse (LRCLK) */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); /* make 1st data bit occur one ACLK cycle after the frame sync */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(1)); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(1)); /* 1st data bit occur one ACLK cycle after the frame sync */ data_delay = 1; /* FS need to be inverted */ inv_fs = true; break; case SND_SOC_DAIFMT_LEFT_J: /* configure a full-word SYNC pulse (LRCLK) */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); /* No delay after FS */ data_delay = 0; break; default: ret = -EINVAL; goto out; } mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(data_delay), FSXDLY(3)); mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(data_delay), FSRDLY(3)); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* codec is clock and frame slave */ Loading Loading @@ -325,7 +354,6 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); mcasp->bclk_master = 0; break; default: ret = -EINVAL; goto out; Loading @@ -334,39 +362,38 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_IB_NF: mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); fs_pol_rising = true; break; case SND_SOC_DAIFMT_NB_IF: mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); fs_pol_rising = false; break; case SND_SOC_DAIFMT_IB_IF: mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); fs_pol_rising = false; break; case SND_SOC_DAIFMT_NB_NF: mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); fs_pol_rising = true; break; default: ret = -EINVAL; break; goto out; } if (inv_fs) fs_pol_rising = !fs_pol_rising; if (fs_pol_rising) { mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); } else { mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); } out: pm_runtime_put_sync(mcasp->dev); Loading Loading @@ -464,17 +491,19 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, } static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, int channels) int period_words, int channels) { struct davinci_pcm_dma_params *dma_params = &mcasp->dma_params[stream]; struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[stream]; int i; u8 tx_ser = 0; u8 rx_ser = 0; u8 ser; u8 slots = mcasp->tdm_slots; u8 max_active_serializers = (channels + slots - 1) / slots; int active_serializers, numevt, n; u32 reg; /* Default configuration */ if (mcasp->version != MCASP_VERSION_4) if (mcasp->version < MCASP_VERSION_3) mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); /* All PINS as McASP */ Loading Loading @@ -505,37 +534,71 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, } } if (stream == SNDRV_PCM_STREAM_PLAYBACK) ser = tx_ser; else ser = rx_ser; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { active_serializers = tx_ser; numevt = mcasp->txnumevt; reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; } else { active_serializers = rx_ser; numevt = mcasp->rxnumevt; reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; } if (ser < max_active_serializers) { if (active_serializers < max_active_serializers) { dev_warn(mcasp->dev, "stream has more channels (%d) than are " "enabled in mcasp (%d)\n", channels, ser * slots); "enabled in mcasp (%d)\n", channels, active_serializers * slots); return -EINVAL; } if (mcasp->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { if (mcasp->txnumevt * tx_ser > 64) mcasp->txnumevt = 1; reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; mcasp_mod_bits(mcasp, reg, tx_ser, NUMDMA_MASK); mcasp_mod_bits(mcasp, reg, ((mcasp->txnumevt * tx_ser) << 8), NUMEVT_MASK); /* AFIFO is not in use */ if (!numevt) { /* Configure the burst size for platform drivers */ if (active_serializers > 1) { /* * If more than one serializers are in use we have one * DMA request to provide data for all serializers. * For example if three serializers are enabled the DMA * need to transfer three words per DMA request. */ dma_params->fifo_level = active_serializers; dma_data->maxburst = active_serializers; } else { dma_params->fifo_level = 0; dma_data->maxburst = 0; } return 0; } if (mcasp->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { if (mcasp->rxnumevt * rx_ser > 64) mcasp->rxnumevt = 1; reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; mcasp_mod_bits(mcasp, reg, rx_ser, NUMDMA_MASK); mcasp_mod_bits(mcasp, reg, ((mcasp->rxnumevt * rx_ser) << 8), NUMEVT_MASK); if (period_words % active_serializers) { dev_err(mcasp->dev, "Invalid combination of period words and " "active serializers: %d, %d\n", period_words, active_serializers); return -EINVAL; } /* * Calculate the optimal AFIFO depth for platform side: * The number of words for numevt need to be in steps of active * serializers. */ n = numevt % active_serializers; if (n) numevt += (active_serializers - n); while (period_words % numevt && numevt > 0) numevt -= active_serializers; if (numevt <= 0) numevt = active_serializers; mcasp_mod_bits(mcasp, reg, active_serializers, NUMDMA_MASK); mcasp_mod_bits(mcasp, reg, NUMEVT(numevt), NUMEVT_MASK); /* Configure the burst size for platform drivers */ if (numevt == 1) numevt = 0; dma_params->fifo_level = numevt; dma_data->maxburst = numevt; return 0; } Loading Loading @@ -607,27 +670,24 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); struct davinci_pcm_dma_params *dma_params = &mcasp->dma_params[substream->stream]; struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[substream->stream]; int word_length; u8 fifo_level; u8 slots = mcasp->tdm_slots; u8 active_serializers; int channels = params_channels(params); int period_size = params_period_size(params); int ret; /* If mcasp is BCLK master we need to set BCLK divider */ if (mcasp->bclk_master) { unsigned int bclk_freq = snd_soc_params_to_bclk(params); if (mcasp->sysclk_freq % bclk_freq != 0) { dev_err(mcasp->dev, "Can't produce requred BCLK\n"); dev_err(mcasp->dev, "Can't produce required BCLK\n"); return -EINVAL; } davinci_mcasp_set_clkdiv( cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); } ret = mcasp_common_hw_param(mcasp, substream->stream, channels); ret = mcasp_common_hw_param(mcasp, substream->stream, period_size * channels, channels); if (ret) return ret; Loading Loading @@ -671,21 +731,11 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } /* Calculate FIFO level */ active_serializers = (channels + slots - 1) / slots; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) fifo_level = mcasp->txnumevt * active_serializers; else fifo_level = mcasp->rxnumevt * active_serializers; if (mcasp->version == MCASP_VERSION_2 && !fifo_level) if (mcasp->version == MCASP_VERSION_2 && !dma_params->fifo_level) dma_params->acnt = 4; else dma_params->acnt = dma_params->data_type; dma_params->fifo_level = fifo_level; dma_data->maxburst = fifo_level; davinci_config_channel_size(mcasp, word_length); return 0; Loading Loading @@ -716,22 +766,7 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, return ret; } static int davinci_mcasp_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); if (mcasp->version == MCASP_VERSION_4) snd_soc_dai_set_dma_data(dai, substream, &mcasp->dma_data[substream->stream]); else snd_soc_dai_set_dma_data(dai, substream, mcasp->dma_params); return 0; } static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .startup = davinci_mcasp_startup, .trigger = davinci_mcasp_trigger, .hw_params = davinci_mcasp_hw_params, .set_fmt = davinci_mcasp_set_dai_fmt, Loading @@ -739,6 +774,25 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .set_sysclk = davinci_mcasp_set_sysclk, }; static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); if (mcasp->version == MCASP_VERSION_4) { /* Using dmaengine PCM */ dai->playback_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; dai->capture_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; } else { /* Using davinci-pcm */ dai->playback_dma_data = mcasp->dma_params; dai->capture_dma_data = mcasp->dma_params; } return 0; } #ifdef CONFIG_PM_SLEEP static int davinci_mcasp_suspend(struct snd_soc_dai *dai) { Loading Loading @@ -792,6 +846,7 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai) static struct snd_soc_dai_driver davinci_mcasp_dai[] = { { .name = "davinci-mcasp.0", .probe = davinci_mcasp_dai_probe, .suspend = davinci_mcasp_suspend, .resume = davinci_mcasp_resume, .playback = { Loading @@ -811,6 +866,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { }, { .name = "davinci-mcasp.1", .probe = davinci_mcasp_dai_probe, .playback = { .channels_min = 1, .channels_max = 384, Loading Loading @@ -1078,7 +1134,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) if (!mcasp->base) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; goto err_release_clk; goto err; } mcasp->op_mode = pdata->op_mode; Loading Loading @@ -1159,25 +1215,37 @@ static int davinci_mcasp_probe(struct platform_device *pdev) mcasp_reparent_fck(pdev); ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, &davinci_mcasp_dai[pdata->op_mode], 1); if (ret != 0) goto err_release_clk; goto err; if (mcasp->version != MCASP_VERSION_4) { switch (mcasp->version) { case MCASP_VERSION_1: case MCASP_VERSION_2: case MCASP_VERSION_3: ret = davinci_soc_platform_register(&pdev->dev); break; case MCASP_VERSION_4: ret = omap_pcm_platform_register(&pdev->dev); break; default: dev_err(&pdev->dev, "Invalid McASP version: %d\n", mcasp->version); ret = -EINVAL; break; } if (ret) { dev_err(&pdev->dev, "register PCM failed: %d\n", ret); goto err_unregister_component; } goto err; } return 0; err_unregister_component: snd_soc_unregister_component(&pdev->dev); err_release_clk: err: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); return ret; Loading @@ -1185,12 +1253,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev) static int davinci_mcasp_remove(struct platform_device *pdev) { struct davinci_mcasp *mcasp = dev_get_drvdata(&pdev->dev); snd_soc_unregister_component(&pdev->dev); if (mcasp->version != MCASP_VERSION_4) davinci_soc_platform_unregister(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); Loading sound/soc/davinci/davinci-mcasp.h +1 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,7 @@ */ #define FIFO_ENABLE BIT(16) #define NUMEVT_MASK (0xFF << 8) #define NUMEVT(x) (((x) & 0xFF) << 8) #define NUMDMA_MASK (0xFF) #endif /* DAVINCI_MCASP_H */ sound/soc/davinci/davinci-pcm.c +1 −7 Original line number Diff line number Diff line Loading @@ -852,16 +852,10 @@ static struct snd_soc_platform_driver davinci_soc_platform = { int davinci_soc_platform_register(struct device *dev) { return snd_soc_register_platform(dev, &davinci_soc_platform); return devm_snd_soc_register_platform(dev, &davinci_soc_platform); } EXPORT_SYMBOL_GPL(davinci_soc_platform_register); void davinci_soc_platform_unregister(struct device *dev) { snd_soc_unregister_platform(dev); } EXPORT_SYMBOL_GPL(davinci_soc_platform_unregister); MODULE_AUTHOR("Vladimir Barinov"); MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); MODULE_LICENSE("GPL"); Loading
sound/soc/davinci/Kconfig +5 −5 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ config SND_DAVINCI_SOC_GENERIC_EVM config SND_AM33XX_SOC_EVM tristate "SoC Audio for the AM33XX chip based boards" depends on SND_DAVINCI_SOC && SOC_AM33XX depends on SND_DAVINCI_SOC && SOC_AM33XX && I2C select SND_DAVINCI_SOC_GENERIC_EVM help Say Y or M if you want to add support for SoC audio on AM33XX Loading @@ -28,7 +28,7 @@ config SND_AM33XX_SOC_EVM config SND_DAVINCI_SOC_EVM tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" depends on SND_DAVINCI_SOC depends on SND_DAVINCI_SOC && I2C depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM select SND_DAVINCI_SOC_GENERIC_EVM help Loading Loading @@ -56,7 +56,7 @@ endchoice config SND_DM6467_SOC_EVM tristate "SoC Audio support for DaVinci DM6467 EVM" depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM && I2C select SND_DAVINCI_SOC_GENERIC_EVM select SND_SOC_SPDIF Loading @@ -65,7 +65,7 @@ config SND_DM6467_SOC_EVM config SND_DA830_SOC_EVM tristate "SoC Audio support for DA830/OMAP-L137 EVM" depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM && I2C select SND_DAVINCI_SOC_GENERIC_EVM help Loading @@ -74,7 +74,7 @@ config SND_DA830_SOC_EVM config SND_DA850_SOC_EVM tristate "SoC Audio support for DA850/OMAP-L138 EVM" depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM && I2C select SND_DAVINCI_SOC_GENERIC_EVM help Say Y if you want to add support for SoC audio on TI Loading
sound/soc/davinci/davinci-i2s.c +0 −1 Original line number Diff line number Diff line Loading @@ -757,7 +757,6 @@ static int davinci_i2s_remove(struct platform_device *pdev) struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); snd_soc_unregister_component(&pdev->dev); davinci_soc_platform_unregister(&pdev->dev); clk_disable(dev->clk); clk_put(dev->clk); Loading
sound/soc/davinci/davinci-mcasp.c +161 −99 Original line number Diff line number Diff line Loading @@ -36,6 +36,9 @@ #include "davinci-pcm.h" #include "davinci-mcasp.h" #include "../omap/omap-pcm.h" #define MCASP_MAX_AFIFO_DEPTH 64 struct davinci_mcasp_context { u32 txfmtctl; Loading Loading @@ -269,25 +272,51 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); int ret = 0; u32 data_delay; bool fs_pol_rising; bool inv_fs = false; pm_runtime_get_sync(mcasp->dev); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); /* 1st data bit occur one ACLK cycle after the frame sync */ data_delay = 1; break; case SND_SOC_DAIFMT_DSP_B: case SND_SOC_DAIFMT_AC97: mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); /* No delay after FS */ data_delay = 0; break; default: case SND_SOC_DAIFMT_I2S: /* configure a full-word SYNC pulse (LRCLK) */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); /* make 1st data bit occur one ACLK cycle after the frame sync */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(1)); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(1)); /* 1st data bit occur one ACLK cycle after the frame sync */ data_delay = 1; /* FS need to be inverted */ inv_fs = true; break; case SND_SOC_DAIFMT_LEFT_J: /* configure a full-word SYNC pulse (LRCLK) */ mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); /* No delay after FS */ data_delay = 0; break; default: ret = -EINVAL; goto out; } mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(data_delay), FSXDLY(3)); mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(data_delay), FSRDLY(3)); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* codec is clock and frame slave */ Loading Loading @@ -325,7 +354,6 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); mcasp->bclk_master = 0; break; default: ret = -EINVAL; goto out; Loading @@ -334,39 +362,38 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_IB_NF: mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); fs_pol_rising = true; break; case SND_SOC_DAIFMT_NB_IF: mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); fs_pol_rising = false; break; case SND_SOC_DAIFMT_IB_IF: mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); fs_pol_rising = false; break; case SND_SOC_DAIFMT_NB_NF: mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); fs_pol_rising = true; break; default: ret = -EINVAL; break; goto out; } if (inv_fs) fs_pol_rising = !fs_pol_rising; if (fs_pol_rising) { mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); } else { mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); } out: pm_runtime_put_sync(mcasp->dev); Loading Loading @@ -464,17 +491,19 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, } static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, int channels) int period_words, int channels) { struct davinci_pcm_dma_params *dma_params = &mcasp->dma_params[stream]; struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[stream]; int i; u8 tx_ser = 0; u8 rx_ser = 0; u8 ser; u8 slots = mcasp->tdm_slots; u8 max_active_serializers = (channels + slots - 1) / slots; int active_serializers, numevt, n; u32 reg; /* Default configuration */ if (mcasp->version != MCASP_VERSION_4) if (mcasp->version < MCASP_VERSION_3) mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); /* All PINS as McASP */ Loading Loading @@ -505,37 +534,71 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, } } if (stream == SNDRV_PCM_STREAM_PLAYBACK) ser = tx_ser; else ser = rx_ser; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { active_serializers = tx_ser; numevt = mcasp->txnumevt; reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; } else { active_serializers = rx_ser; numevt = mcasp->rxnumevt; reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; } if (ser < max_active_serializers) { if (active_serializers < max_active_serializers) { dev_warn(mcasp->dev, "stream has more channels (%d) than are " "enabled in mcasp (%d)\n", channels, ser * slots); "enabled in mcasp (%d)\n", channels, active_serializers * slots); return -EINVAL; } if (mcasp->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { if (mcasp->txnumevt * tx_ser > 64) mcasp->txnumevt = 1; reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; mcasp_mod_bits(mcasp, reg, tx_ser, NUMDMA_MASK); mcasp_mod_bits(mcasp, reg, ((mcasp->txnumevt * tx_ser) << 8), NUMEVT_MASK); /* AFIFO is not in use */ if (!numevt) { /* Configure the burst size for platform drivers */ if (active_serializers > 1) { /* * If more than one serializers are in use we have one * DMA request to provide data for all serializers. * For example if three serializers are enabled the DMA * need to transfer three words per DMA request. */ dma_params->fifo_level = active_serializers; dma_data->maxburst = active_serializers; } else { dma_params->fifo_level = 0; dma_data->maxburst = 0; } return 0; } if (mcasp->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { if (mcasp->rxnumevt * rx_ser > 64) mcasp->rxnumevt = 1; reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; mcasp_mod_bits(mcasp, reg, rx_ser, NUMDMA_MASK); mcasp_mod_bits(mcasp, reg, ((mcasp->rxnumevt * rx_ser) << 8), NUMEVT_MASK); if (period_words % active_serializers) { dev_err(mcasp->dev, "Invalid combination of period words and " "active serializers: %d, %d\n", period_words, active_serializers); return -EINVAL; } /* * Calculate the optimal AFIFO depth for platform side: * The number of words for numevt need to be in steps of active * serializers. */ n = numevt % active_serializers; if (n) numevt += (active_serializers - n); while (period_words % numevt && numevt > 0) numevt -= active_serializers; if (numevt <= 0) numevt = active_serializers; mcasp_mod_bits(mcasp, reg, active_serializers, NUMDMA_MASK); mcasp_mod_bits(mcasp, reg, NUMEVT(numevt), NUMEVT_MASK); /* Configure the burst size for platform drivers */ if (numevt == 1) numevt = 0; dma_params->fifo_level = numevt; dma_data->maxburst = numevt; return 0; } Loading Loading @@ -607,27 +670,24 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); struct davinci_pcm_dma_params *dma_params = &mcasp->dma_params[substream->stream]; struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[substream->stream]; int word_length; u8 fifo_level; u8 slots = mcasp->tdm_slots; u8 active_serializers; int channels = params_channels(params); int period_size = params_period_size(params); int ret; /* If mcasp is BCLK master we need to set BCLK divider */ if (mcasp->bclk_master) { unsigned int bclk_freq = snd_soc_params_to_bclk(params); if (mcasp->sysclk_freq % bclk_freq != 0) { dev_err(mcasp->dev, "Can't produce requred BCLK\n"); dev_err(mcasp->dev, "Can't produce required BCLK\n"); return -EINVAL; } davinci_mcasp_set_clkdiv( cpu_dai, 1, mcasp->sysclk_freq / bclk_freq); } ret = mcasp_common_hw_param(mcasp, substream->stream, channels); ret = mcasp_common_hw_param(mcasp, substream->stream, period_size * channels, channels); if (ret) return ret; Loading Loading @@ -671,21 +731,11 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } /* Calculate FIFO level */ active_serializers = (channels + slots - 1) / slots; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) fifo_level = mcasp->txnumevt * active_serializers; else fifo_level = mcasp->rxnumevt * active_serializers; if (mcasp->version == MCASP_VERSION_2 && !fifo_level) if (mcasp->version == MCASP_VERSION_2 && !dma_params->fifo_level) dma_params->acnt = 4; else dma_params->acnt = dma_params->data_type; dma_params->fifo_level = fifo_level; dma_data->maxburst = fifo_level; davinci_config_channel_size(mcasp, word_length); return 0; Loading Loading @@ -716,22 +766,7 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, return ret; } static int davinci_mcasp_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); if (mcasp->version == MCASP_VERSION_4) snd_soc_dai_set_dma_data(dai, substream, &mcasp->dma_data[substream->stream]); else snd_soc_dai_set_dma_data(dai, substream, mcasp->dma_params); return 0; } static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .startup = davinci_mcasp_startup, .trigger = davinci_mcasp_trigger, .hw_params = davinci_mcasp_hw_params, .set_fmt = davinci_mcasp_set_dai_fmt, Loading @@ -739,6 +774,25 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .set_sysclk = davinci_mcasp_set_sysclk, }; static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); if (mcasp->version == MCASP_VERSION_4) { /* Using dmaengine PCM */ dai->playback_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; dai->capture_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; } else { /* Using davinci-pcm */ dai->playback_dma_data = mcasp->dma_params; dai->capture_dma_data = mcasp->dma_params; } return 0; } #ifdef CONFIG_PM_SLEEP static int davinci_mcasp_suspend(struct snd_soc_dai *dai) { Loading Loading @@ -792,6 +846,7 @@ static int davinci_mcasp_resume(struct snd_soc_dai *dai) static struct snd_soc_dai_driver davinci_mcasp_dai[] = { { .name = "davinci-mcasp.0", .probe = davinci_mcasp_dai_probe, .suspend = davinci_mcasp_suspend, .resume = davinci_mcasp_resume, .playback = { Loading @@ -811,6 +866,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { }, { .name = "davinci-mcasp.1", .probe = davinci_mcasp_dai_probe, .playback = { .channels_min = 1, .channels_max = 384, Loading Loading @@ -1078,7 +1134,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) if (!mcasp->base) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; goto err_release_clk; goto err; } mcasp->op_mode = pdata->op_mode; Loading Loading @@ -1159,25 +1215,37 @@ static int davinci_mcasp_probe(struct platform_device *pdev) mcasp_reparent_fck(pdev); ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, &davinci_mcasp_dai[pdata->op_mode], 1); if (ret != 0) goto err_release_clk; goto err; if (mcasp->version != MCASP_VERSION_4) { switch (mcasp->version) { case MCASP_VERSION_1: case MCASP_VERSION_2: case MCASP_VERSION_3: ret = davinci_soc_platform_register(&pdev->dev); break; case MCASP_VERSION_4: ret = omap_pcm_platform_register(&pdev->dev); break; default: dev_err(&pdev->dev, "Invalid McASP version: %d\n", mcasp->version); ret = -EINVAL; break; } if (ret) { dev_err(&pdev->dev, "register PCM failed: %d\n", ret); goto err_unregister_component; } goto err; } return 0; err_unregister_component: snd_soc_unregister_component(&pdev->dev); err_release_clk: err: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); return ret; Loading @@ -1185,12 +1253,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev) static int davinci_mcasp_remove(struct platform_device *pdev) { struct davinci_mcasp *mcasp = dev_get_drvdata(&pdev->dev); snd_soc_unregister_component(&pdev->dev); if (mcasp->version != MCASP_VERSION_4) davinci_soc_platform_unregister(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); Loading
sound/soc/davinci/davinci-mcasp.h +1 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,7 @@ */ #define FIFO_ENABLE BIT(16) #define NUMEVT_MASK (0xFF << 8) #define NUMEVT(x) (((x) & 0xFF) << 8) #define NUMDMA_MASK (0xFF) #endif /* DAVINCI_MCASP_H */
sound/soc/davinci/davinci-pcm.c +1 −7 Original line number Diff line number Diff line Loading @@ -852,16 +852,10 @@ static struct snd_soc_platform_driver davinci_soc_platform = { int davinci_soc_platform_register(struct device *dev) { return snd_soc_register_platform(dev, &davinci_soc_platform); return devm_snd_soc_register_platform(dev, &davinci_soc_platform); } EXPORT_SYMBOL_GPL(davinci_soc_platform_register); void davinci_soc_platform_unregister(struct device *dev) { snd_soc_unregister_platform(dev); } EXPORT_SYMBOL_GPL(davinci_soc_platform_unregister); MODULE_AUTHOR("Vladimir Barinov"); MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); MODULE_LICENSE("GPL");