From 8acacc32551854816a4d0a68424fb63f0375e78e Mon Sep 17 00:00:00 2001 From: Misael Lopez Cruz Date: Tue, 23 Apr 2013 00:28:07 -0500 Subject: ASoC: davinci-mcasp: HACK: Add MCASP_VERSION_4 support McASP IP found in DRA7xx devices is similar to the one described by VERSION_3 (TI81xx, AM33xx), except that a different DMA mechanism is used. A new version is introduced to use DMA4 instead (OMAP's). Long term plan is to keep McASP driver totally agnostic of the DMA module (sDMA or eDMA). Change-Id: I47a2fd117b3647a5ed6562cbaa00211cb95dea3a Signed-off-by: Misael Lopez Cruz --- .../bindings/sound/davinci-mcasp-audio.txt | 1 + include/linux/platform_data/davinci_asp.h | 1 + sound/soc/davinci/davinci-mcasp.c | 178 +++++++++++++++------ sound/soc/davinci/davinci-mcasp.h | 2 +- sound/soc/davinci/davinci-pcm.h | 15 ++ 5 files changed, 145 insertions(+), 52 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt index 6f269f3aca70..9bac63e73eb1 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt @@ -5,6 +5,7 @@ Required properties: "ti,dm646x-mcasp-audio" : for DM646x platforms "ti,da830-mcasp-audio" : for both DA830 & DA850 platforms "ti,omap2-mcasp-audio" : for OMAP2 platforms (TI81xx, AM33xx) + "ti,dra7-mcasp-audio" : for DRA7xx platforms - reg : Should contain McASP registers offset and length - interrupts : Interrupt number for McASP diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index a78d0b0762b1..416c1d2abe63 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -92,6 +92,7 @@ enum { MCASP_VERSION_1 = 0, /* DM646x */ MCASP_VERSION_2, /* DA8xx/OMAPL1x */ MCASP_VERSION_3, /* TI81xx/AM33xx */ + MCASP_VERSION_4, /* DRA7xxx */ }; enum mcbsp_clk_input_pin { diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 5d9af6c7ddfa..3f569fc2b763 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -34,6 +34,7 @@ #include "davinci-pcm.h" #include "davinci-mcasp.h" +#include "../omap/omap-pcm.h" /* * McASP register definitions @@ -104,7 +105,7 @@ /* Transmit Buffer for Serializer n */ #define DAVINCI_MCASP_TXBUF_REG 0x200 /* Receive Buffer for Serializer n */ -#define DAVINCI_MCASP_RXBUF_REG 0x280 +#define DAVINCI_MCASP_RXBUF_REG 0x284 /* McASP FIFO Registers */ #define DAVINCI_MCASP_WFIFOCTL (0x1010) @@ -425,6 +426,7 @@ static int davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) if (dev->txnumevt) { /* enable FIFO */ switch (dev->version) { case MCASP_VERSION_3: + case MCASP_VERSION_4: mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, FIFO_ENABLE); mcasp_set_bits(dev->base + MCASP_VER3_WFIFOCTL, @@ -460,6 +462,7 @@ static int davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) if (dev->rxnumevt) { /* enable FIFO */ switch (dev->version) { case MCASP_VERSION_3: + case MCASP_VERSION_4: mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, FIFO_ENABLE); mcasp_set_bits(dev->base + MCASP_VER3_RFIFOCTL, @@ -511,6 +514,7 @@ static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) if (dev->txnumevt) { /* disable FIFO */ switch (dev->version) { case MCASP_VERSION_3: + case MCASP_VERSION_4: mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, FIFO_ENABLE); break; @@ -524,6 +528,7 @@ static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) if (dev->rxnumevt) { /* disable FIFO */ switch (dev->version) { case MCASP_VERSION_3: + case MCASP_VERSION_4: mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, FIFO_ENABLE); break; @@ -747,7 +752,9 @@ static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream, u8 slots = dev->tdm_slots; u8 max_active_serializers = (channels + slots - 1) / slots; /* Default configuration */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); + if (dev->version != MCASP_VERSION_4) + mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, + MCASP_SOFT); /* All PINS as McASP */ mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000); @@ -804,6 +811,7 @@ static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream, switch (dev->version) { case MCASP_VERSION_3: + case MCASP_VERSION_4: mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, tx_ser, NUMDMA_MASK); mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, @@ -822,6 +830,7 @@ static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream, dev->rxnumevt = 1; switch (dev->version) { case MCASP_VERSION_3: + case MCASP_VERSION_4: mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, rx_ser, NUMDMA_MASK); mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, @@ -845,6 +854,7 @@ static int davinci_hw_param(struct davinci_audio_dev *dev, int stream, int total_slots = dev->tdm_slots; int active_serializers; u32 mask = 0; + u32 busel = 0; if ((total_slots < 2) || (total_slots > 32)) { dev_err(dev->dev, "tdm slot count %d not supported\n", @@ -871,15 +881,18 @@ static int davinci_hw_param(struct davinci_audio_dev *dev, int stream, mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); + if (dev->version == MCASP_VERSION_4) + busel = TXSEL; + /* bit stream is MSB first with no delay */ /* DSP_B mode */ mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask); - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD); + mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, busel | TXORD); mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXMOD(total_slots), FSXMOD(0x1FF)); mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask); - mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD); + mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, busel | RXORD); mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRMOD(total_slots), FSRMOD(0x1FF)); @@ -916,13 +929,34 @@ static int davinci_hw_dit_param(struct davinci_audio_dev *dev) return 0; } +static void davinci_mcasp_set_dma_params(struct snd_pcm_substream *substream, + struct davinci_audio_dev *dev, + int word_length, u8 fifo_level) +{ + if (dev->version == MCASP_VERSION_4) { + struct omap_pcm_dma_data *dma_data = + dev->dma_params[substream->stream]; + + dma_data->packet_size = fifo_level; + } else { + struct davinci_pcm_dma_params *dma_params = + dev->dma_params[substream->stream]; + + dma_params->data_type = word_length >> 3; + dma_params->fifo_level = fifo_level; + + if (dev->version == MCASP_VERSION_2 && !fifo_level) + dma_params->acnt = 4; + else + dma_params->acnt = dma_params->data_type; + } +} + static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - struct davinci_pcm_dma_params *dma_params = - &dev->dma_params[substream->stream]; int word_length; u8 fifo_level; u8 slots = dev->tdm_slots; @@ -950,19 +984,16 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_U8: case SNDRV_PCM_FORMAT_S8: - dma_params->data_type = 1; word_length = 8; break; case SNDRV_PCM_FORMAT_U16_LE: case SNDRV_PCM_FORMAT_S16_LE: - dma_params->data_type = 2; word_length = 16; break; case SNDRV_PCM_FORMAT_U24_3LE: case SNDRV_PCM_FORMAT_S24_3LE: - dma_params->data_type = 3; word_length = 24; break; @@ -970,7 +1001,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_U32_LE: case SNDRV_PCM_FORMAT_S32_LE: - dma_params->data_type = 4; word_length = 32; break; @@ -979,14 +1009,8 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - if (dev->version == MCASP_VERSION_2 && !fifo_level) - dma_params->acnt = 4; - else - dma_params->acnt = dma_params->data_type; - - dma_params->fifo_level = fifo_level; - dev->sample_bits = word_length; + davinci_mcasp_set_dma_params(substream, dev, word_length, fifo_level); davinci_config_channel_size(dev, word_length); return 0; @@ -1023,7 +1047,11 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, { struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai); - snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); + if (dev->version == MCASP_VERSION_4) + snd_soc_dai_set_dma_data(dai, substream, + dev->dma_params[substream->stream]); + else + snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); /* Apply channels symmetry, needed when using a single serializer */ if (dev->channels) @@ -1121,6 +1149,10 @@ static const struct of_device_id mcasp_dt_ids[] = { .compatible = "ti,omap2-mcasp-audio", .data = (void *)MCASP_VERSION_3, }, + { + .compatible = "ti,dra7-mcasp-audio", + .data = (void *)MCASP_VERSION_4, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mcasp_dt_ids); @@ -1247,8 +1279,8 @@ nodata: static int davinci_mcasp_probe(struct platform_device *pdev) { - struct davinci_pcm_dma_params *dma_data; - struct resource *mem, *ioarea, *res; + struct resource *mem, *ioarea; + struct resource *tx_res, *rx_res; struct snd_platform_data *pdata; struct davinci_audio_dev *dev; int ret; @@ -1302,50 +1334,91 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dev->rx_dismod = pdata->rx_dismod; dev->dev = &pdev->dev; - dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_pool = pdata->sram_pool; - dma_data->sram_size = pdata->sram_size_playback; - dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + - mem->start); - /* first TX, then RX */ - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { + tx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!tx_res) { dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENODEV; - goto err_release_clk; + return -ENODEV; + } + + rx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (!rx_res) { + dev_err(&pdev->dev, "no DMA resource\n"); + return -ENODEV; } - dma_data->channel = res->start; + if (dev->version == MCASP_VERSION_4) { + struct omap_pcm_dma_data *dma_data; - dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_pool = pdata->sram_pool; - dma_data->sram_size = pdata->sram_size_capture; - dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + - mem->start); + dma_data = devm_kzalloc(&pdev->dev, sizeof(*dma_data), + GFP_KERNEL); + if (!dma_data) { + ret = -ENOMEM; + goto err_release_clk; + } - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENODEV; - goto err_release_clk; + dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = dma_data; + dma_data->port_addr = mem->start + DAVINCI_MCASP_TXBUF_REG; + dma_data->dma_req = tx_res->start; + + dma_data = devm_kzalloc(&pdev->dev, sizeof(*dma_data), + GFP_KERNEL); + if (!dma_data) { + ret = -ENOMEM; + goto err_release_clk; + } + + dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = dma_data; + dma_data->port_addr = mem->start + DAVINCI_MCASP_RXBUF_REG; + dma_data->dma_req = rx_res->start; + } else { + struct davinci_pcm_dma_params *dma_data; + + dma_data = devm_kzalloc(&pdev->dev, sizeof(*dma_data), + GFP_KERNEL); + if (!dma_data) { + ret = -ENOMEM; + goto err_release_clk; + } + + dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = dma_data; + dma_data->asp_chan_q = pdata->asp_chan_q; + dma_data->ram_chan_q = pdata->ram_chan_q; + dma_data->sram_pool = pdata->sram_pool; + dma_data->sram_size = pdata->sram_size_playback; + dma_data->channel = tx_res->start; + dma_data->dma_addr = (dma_addr_t)(pdata->tx_dma_offset + + mem->start); + + dma_data = devm_kzalloc(&pdev->dev, sizeof(*dma_data), + GFP_KERNEL); + if (!dma_data) { + ret = -ENOMEM; + goto err_release_clk; + } + + dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = dma_data; + dma_data->asp_chan_q = pdata->asp_chan_q; + dma_data->ram_chan_q = pdata->ram_chan_q; + dma_data->sram_pool = pdata->sram_pool; + dma_data->sram_size = pdata->sram_size_capture; + dma_data->channel = rx_res->start; + dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + + mem->start); } - dma_data->channel = res->start; dev_set_drvdata(&pdev->dev, dev); ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]); if (ret != 0) goto err_release_clk; - ret = davinci_soc_platform_register(&pdev->dev); - if (ret) { - dev_err(&pdev->dev, "register PCM failed: %d\n", ret); - goto err_unregister_dai; + if (dev->version != MCASP_VERSION_4) { + ret = davinci_soc_platform_register(&pdev->dev); + if (ret) { + dev_err(&pdev->dev, "register PCM failed: %d\n", ret); + goto err_unregister_dai; + } } return 0; @@ -1359,9 +1432,12 @@ err_release_clk: static int davinci_mcasp_remove(struct platform_device *pdev) { + struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); snd_soc_unregister_dai(&pdev->dev); - davinci_soc_platform_unregister(&pdev->dev); + + if (dev->version != MCASP_VERSION_4) + davinci_soc_platform_unregister(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 8b98ed16b8ed..38a205ea338d 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h @@ -28,7 +28,7 @@ #define DAVINCI_MCASP_DIT_DAI 1 struct davinci_audio_dev { - struct davinci_pcm_dma_params dma_params[2]; + void *dma_params[2]; void __iomem *base; struct device *dev; diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index fbb710c76c08..436722c27dc9 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h @@ -29,7 +29,22 @@ struct davinci_pcm_dma_params { unsigned int fifo_level; }; +#ifdef CONFIG_SND_DAVINCI_SOC + int davinci_soc_platform_register(struct device *dev); void davinci_soc_platform_unregister(struct device *dev); +#else + +static inline int davinci_soc_platform_register(struct device *dev) +{ + return 0; +} + +static inline void davinci_soc_platform_unregister(struct device *dev) +{ +} + +#endif + #endif -- cgit v1.2.3-54-g00ecf