diff options
Diffstat (limited to 'sound/soc/davinci')
-rw-r--r-- | sound/soc/davinci/Kconfig | 106 | ||||
-rw-r--r-- | sound/soc/davinci/Makefile | 16 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-evm.c | 511 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-i2s.c | 782 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-i2s.h | 20 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-mcasp.c | 2212 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-mcasp.h | 306 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-vcif.c | 259 | ||||
-rw-r--r-- | sound/soc/davinci/edma-pcm.c | 59 | ||||
-rw-r--r-- | sound/soc/davinci/edma-pcm.h | 32 |
10 files changed, 0 insertions, 4303 deletions
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig deleted file mode 100644 index 778faff28e0e..000000000000 --- a/sound/soc/davinci/Kconfig +++ /dev/null @@ -1,106 +0,0 @@ -config SND_DAVINCI_SOC - tristate - depends on ARCH_DAVINCI - select SND_EDMA_SOC - -config SND_EDMA_SOC - tristate "SoC Audio for Texas Instruments chips using eDMA" - depends on TI_EDMA - select SND_SOC_GENERIC_DMAENGINE_PCM - help - Say Y or M here if you want audio support for TI SoC which uses eDMA. - The following line of SoCs are supported by this platform driver: - - daVinci devices - - AM335x - - AM437x/AM438x - - DRA7xx family - -config SND_DAVINCI_SOC_I2S - tristate "DaVinci Multichannel Buffered Serial Port (McBSP) support" - depends on SND_EDMA_SOC - help - Say Y or M here if you want to have support for McBSP IP found in - Texas Instruments DaVinci DA850 SoCs. - -config SND_DAVINCI_SOC_MCASP - tristate "Multichannel Audio Serial Port (McASP) support" - depends on SND_SDMA_SOC || SND_EDMA_SOC - help - Say Y or M here if you want to have support for McASP IP found in - various Texas Instruments SoCs like: - - daVinci devices - - Sitara line of SoCs (AM335x, AM438x, etc) - - DRA7x devices - -config SND_DAVINCI_SOC_VCIF - tristate - -config SND_DAVINCI_SOC_GENERIC_EVM - tristate - select SND_SOC_TLV320AIC3X - select SND_DAVINCI_SOC_MCASP - -config SND_AM33XX_SOC_EVM - tristate "SoC Audio for the AM33XX chip based boards" - depends on SND_EDMA_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 - boards using McASP and TLV320AIC3X codec. For example AM335X-EVM, - AM335X-EVMSK, and BeagelBone with AudioCape boards have this - setup. - -config SND_DAVINCI_SOC_EVM - tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" - depends on SND_EDMA_SOC && I2C - depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM - select SND_DAVINCI_SOC_GENERIC_EVM - help - Say Y if you want to add support for SoC audio on TI - DaVinci DM6446, DM355 or DM365 EVM platforms. - -choice - prompt "DM365 codec select" - depends on SND_DAVINCI_SOC_EVM - depends on MACH_DAVINCI_DM365_EVM - -config SND_DM365_AIC3X_CODEC - tristate "Audio Codec - AIC3101" - help - Say Y if you want to add support for AIC3101 audio codec - -config SND_DM365_VOICE_CODEC - tristate "Voice Codec - CQ93VC" - select MFD_DAVINCI_VOICECODEC - select SND_DAVINCI_SOC_VCIF - select SND_SOC_CQ0093VC - help - Say Y if you want to add support for SoC On-chip voice codec -endchoice - -config SND_DM6467_SOC_EVM - tristate "SoC Audio support for DaVinci DM6467 EVM" - depends on SND_EDMA_SOC && MACH_DAVINCI_DM6467_EVM && I2C - select SND_DAVINCI_SOC_GENERIC_EVM - select SND_SOC_SPDIF - - help - Say Y if you want to add support for SoC audio on TI - -config SND_DA830_SOC_EVM - tristate "SoC Audio support for DA830/OMAP-L137 EVM" - depends on SND_EDMA_SOC && MACH_DAVINCI_DA830_EVM && I2C - select SND_DAVINCI_SOC_GENERIC_EVM - - help - Say Y if you want to add support for SoC audio on TI - DA830/OMAP-L137 EVM - -config SND_DA850_SOC_EVM - tristate "SoC Audio support for DA850/OMAP-L138 EVM" - depends on SND_EDMA_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 - DA850/OMAP-L138 EVM - diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile deleted file mode 100644 index 23c6592eb31a..000000000000 --- a/sound/soc/davinci/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# DAVINCI Platform Support -snd-soc-edma-objs := edma-pcm.o -snd-soc-davinci-i2s-objs := davinci-i2s.o -snd-soc-davinci-mcasp-objs:= davinci-mcasp.o -snd-soc-davinci-vcif-objs:= davinci-vcif.o - -obj-$(CONFIG_SND_EDMA_SOC) += snd-soc-edma.o -obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o -obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o -obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o - -# Generic DAVINCI/AM33xx Machine Support -snd-soc-evm-objs := davinci-evm.o - -obj-$(CONFIG_SND_DAVINCI_SOC_GENERIC_EVM) += snd-soc-evm.o diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c deleted file mode 100644 index 7a369e0f2093..000000000000 --- a/sound/soc/davinci/davinci-evm.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * ASoC driver for TI DAVINCI EVM platform - * - * Author: Vladimir Barinov, <vbarinov@embeddedalley.com> - * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/of_platform.h> -#include <linux/clk.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/soc.h> - -#include <asm/dma.h> -#include <asm/mach-types.h> - -struct snd_soc_card_drvdata_davinci { - struct clk *mclk; - unsigned sysclk; -}; - -static int evm_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_card *soc_card = rtd->card; - struct snd_soc_card_drvdata_davinci *drvdata = - snd_soc_card_get_drvdata(soc_card); - - if (drvdata->mclk) - return clk_prepare_enable(drvdata->mclk); - - return 0; -} - -static void evm_shutdown(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_card *soc_card = rtd->card; - struct snd_soc_card_drvdata_davinci *drvdata = - snd_soc_card_get_drvdata(soc_card); - - if (drvdata->mclk) - clk_disable_unprepare(drvdata->mclk); -} - -static int evm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_card *soc_card = rtd->card; - int ret = 0; - unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) - snd_soc_card_get_drvdata(soc_card))->sysclk; - - /* set the codec system clock */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT); - if (ret < 0) - return ret; - - /* set the CPU system clock */ - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT); - if (ret < 0) - return ret; - - return 0; -} - -static struct snd_soc_ops evm_ops = { - .startup = evm_startup, - .shutdown = evm_shutdown, - .hw_params = evm_hw_params, -}; - -/* davinci-evm machine dapm widgets */ -static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), -}; - -/* davinci-evm machine audio_mapnections to the codec pins */ -static const struct snd_soc_dapm_route audio_map[] = { - /* Headphone connected to HPLOUT, HPROUT */ - {"Headphone Jack", NULL, "HPLOUT"}, - {"Headphone Jack", NULL, "HPROUT"}, - - /* Line Out connected to LLOUT, RLOUT */ - {"Line Out", NULL, "LLOUT"}, - {"Line Out", NULL, "RLOUT"}, - - /* Mic connected to (MIC3L | MIC3R) */ - {"MIC3L", NULL, "Mic Bias"}, - {"MIC3R", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Mic Jack"}, - - /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */ - {"LINE1L", NULL, "Line In"}, - {"LINE2L", NULL, "Line In"}, - {"LINE1R", NULL, "Line In"}, - {"LINE2R", NULL, "Line In"}, -}; - -/* Logic for a aic3x as connected on a davinci-evm */ -static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - struct device_node *np = card->dev->of_node; - int ret; - - /* Add davinci-evm specific widgets */ - snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets, - ARRAY_SIZE(aic3x_dapm_widgets)); - - if (np) { - ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing"); - if (ret) - return ret; - } else { - /* Set up davinci-evm specific audio path audio_map */ - snd_soc_dapm_add_routes(&card->dapm, audio_map, - ARRAY_SIZE(audio_map)); - } - - /* not connected */ - snd_soc_dapm_nc_pin(&card->dapm, "MONO_LOUT"); - snd_soc_dapm_nc_pin(&card->dapm, "HPLCOM"); - snd_soc_dapm_nc_pin(&card->dapm, "HPRCOM"); - - return 0; -} - -/* davinci-evm digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link dm6446_evm_dai = { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcbsp", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-001b", - .platform_name = "davinci-mcbsp", - .init = evm_aic3x_init, - .ops = &evm_ops, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_IB_NF, -}; - -static struct snd_soc_dai_link dm355_evm_dai = { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcbsp.1", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-001b", - .platform_name = "davinci-mcbsp.1", - .init = evm_aic3x_init, - .ops = &evm_ops, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_IB_NF, -}; - -static struct snd_soc_dai_link dm365_evm_dai = { -#ifdef CONFIG_SND_DM365_AIC3X_CODEC - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcbsp", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-mcbsp", - .init = evm_aic3x_init, - .ops = &evm_ops, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_IB_NF, -#elif defined(CONFIG_SND_DM365_VOICE_CODEC) - .name = "Voice Codec - CQ93VC", - .stream_name = "CQ93", - .cpu_dai_name = "davinci-vcif", - .codec_dai_name = "cq93vc-hifi", - .codec_name = "cq93vc-codec", - .platform_name = "davinci-vcif", -#endif -}; - -static struct snd_soc_dai_link dm6467_evm_dai[] = { - { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name= "davinci-mcasp.0", - .codec_dai_name = "tlv320aic3x-hifi", - .platform_name = "davinci-mcasp.0", - .codec_name = "tlv320aic3x-codec.0-001a", - .init = evm_aic3x_init, - .ops = &evm_ops, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_IB_NF, - }, - { - .name = "McASP", - .stream_name = "spdif", - .cpu_dai_name= "davinci-mcasp.1", - .codec_dai_name = "dit-hifi", - .codec_name = "spdif_dit", - .platform_name = "davinci-mcasp.1", - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_IB_NF, - }, -}; - -static struct snd_soc_dai_link da830_evm_dai = { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcasp.1", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-mcasp.1", - .init = evm_aic3x_init, - .ops = &evm_ops, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_IB_NF, -}; - -static struct snd_soc_dai_link da850_evm_dai = { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name= "davinci-mcasp.0", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-mcasp.0", - .init = evm_aic3x_init, - .ops = &evm_ops, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_IB_NF, -}; - -/* davinci dm6446 evm audio machine driver */ -/* - * ASP0 in DM6446 EVM is clocked by U55, as configured by - * board-dm644x-evm.c using GPIOs from U18. There are six - * options; here we "know" we use a 48 KHz sample rate. - */ -static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = { - .sysclk = 12288000, -}; - -static struct snd_soc_card dm6446_snd_soc_card_evm = { - .name = "DaVinci DM6446 EVM", - .owner = THIS_MODULE, - .dai_link = &dm6446_evm_dai, - .num_links = 1, - .drvdata = &dm6446_snd_soc_card_drvdata, -}; - -/* davinci dm355 evm audio machine driver */ -/* ASP1 on DM355 EVM is clocked by an external oscillator */ -static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = { - .sysclk = 27000000, -}; - -static struct snd_soc_card dm355_snd_soc_card_evm = { - .name = "DaVinci DM355 EVM", - .owner = THIS_MODULE, - .dai_link = &dm355_evm_dai, - .num_links = 1, - .drvdata = &dm355_snd_soc_card_drvdata, -}; - -/* davinci dm365 evm audio machine driver */ -static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = { - .sysclk = 27000000, -}; - -static struct snd_soc_card dm365_snd_soc_card_evm = { - .name = "DaVinci DM365 EVM", - .owner = THIS_MODULE, - .dai_link = &dm365_evm_dai, - .num_links = 1, - .drvdata = &dm365_snd_soc_card_drvdata, -}; - -/* davinci dm6467 evm audio machine driver */ -static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = { - .sysclk = 27000000, -}; - -static struct snd_soc_card dm6467_snd_soc_card_evm = { - .name = "DaVinci DM6467 EVM", - .owner = THIS_MODULE, - .dai_link = dm6467_evm_dai, - .num_links = ARRAY_SIZE(dm6467_evm_dai), - .drvdata = &dm6467_snd_soc_card_drvdata, -}; - -static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = { - .sysclk = 24576000, -}; - -static struct snd_soc_card da830_snd_soc_card = { - .name = "DA830/OMAP-L137 EVM", - .owner = THIS_MODULE, - .dai_link = &da830_evm_dai, - .num_links = 1, - .drvdata = &da830_snd_soc_card_drvdata, -}; - -static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = { - .sysclk = 24576000, -}; - -static struct snd_soc_card da850_snd_soc_card = { - .name = "DA850/OMAP-L138 EVM", - .owner = THIS_MODULE, - .dai_link = &da850_evm_dai, - .num_links = 1, - .drvdata = &da850_snd_soc_card_drvdata, -}; - -#if defined(CONFIG_OF) - -/* - * The struct is used as place holder. It will be completely - * filled with data from dt node. - */ -static struct snd_soc_dai_link evm_dai_tlv320aic3x = { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .codec_dai_name = "tlv320aic3x-hifi", - .ops = &evm_ops, - .init = evm_aic3x_init, - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM | - SND_SOC_DAIFMT_IB_NF, -}; - -static const struct of_device_id davinci_evm_dt_ids[] = { - { - .compatible = "ti,da830-evm-audio", - .data = (void *) &evm_dai_tlv320aic3x, - }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids); - -/* davinci evm audio machine driver */ -static struct snd_soc_card evm_soc_card = { - .owner = THIS_MODULE, - .num_links = 1, -}; - -static int davinci_evm_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - const struct of_device_id *match; - struct snd_soc_dai_link *dai; - struct snd_soc_card_drvdata_davinci *drvdata = NULL; - struct clk *mclk; - int ret = 0; - - match = of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); - if (!match) { - dev_err(&pdev->dev, "Error: No device match found\n"); - return -ENODEV; - } - - dai = (struct snd_soc_dai_link *) match->data; - - evm_soc_card.dai_link = dai; - - dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0); - if (!dai->codec_of_node) - return -EINVAL; - - dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0); - if (!dai->cpu_of_node) - return -EINVAL; - - dai->platform_of_node = dai->cpu_of_node; - - evm_soc_card.dev = &pdev->dev; - ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model"); - if (ret) - return ret; - - mclk = devm_clk_get(&pdev->dev, "mclk"); - if (PTR_ERR(mclk) == -EPROBE_DEFER) { - return -EPROBE_DEFER; - } else if (IS_ERR(mclk)) { - dev_dbg(&pdev->dev, "mclk not found.\n"); - mclk = NULL; - } - - drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); - if (!drvdata) - return -ENOMEM; - - drvdata->mclk = mclk; - - ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk); - - if (ret < 0) { - if (!drvdata->mclk) { - dev_err(&pdev->dev, - "No clock or clock rate defined.\n"); - return -EINVAL; - } - drvdata->sysclk = clk_get_rate(drvdata->mclk); - } else if (drvdata->mclk) { - unsigned int requestd_rate = drvdata->sysclk; - clk_set_rate(drvdata->mclk, drvdata->sysclk); - drvdata->sysclk = clk_get_rate(drvdata->mclk); - if (drvdata->sysclk != requestd_rate) - dev_warn(&pdev->dev, - "Could not get requested rate %u using %u.\n", - requestd_rate, drvdata->sysclk); - } - - snd_soc_card_set_drvdata(&evm_soc_card, drvdata); - ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card); - - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - - return ret; -} - -static struct platform_driver davinci_evm_driver = { - .probe = davinci_evm_probe, - .driver = { - .name = "davinci_evm", - .pm = &snd_soc_pm_ops, - .of_match_table = of_match_ptr(davinci_evm_dt_ids), - }, -}; -#endif - -static struct platform_device *evm_snd_device; - -static int __init evm_init(void) -{ - struct snd_soc_card *evm_snd_dev_data; - int index; - int ret; - - /* - * If dtb is there, the devices will be created dynamically. - * Only register platfrom driver structure. - */ -#if defined(CONFIG_OF) - if (of_have_populated_dt()) - return platform_driver_register(&davinci_evm_driver); -#endif - - if (machine_is_davinci_evm()) { - evm_snd_dev_data = &dm6446_snd_soc_card_evm; - index = 0; - } else if (machine_is_davinci_dm355_evm()) { - evm_snd_dev_data = &dm355_snd_soc_card_evm; - index = 1; - } else if (machine_is_davinci_dm365_evm()) { - evm_snd_dev_data = &dm365_snd_soc_card_evm; - index = 0; - } else if (machine_is_davinci_dm6467_evm()) { - evm_snd_dev_data = &dm6467_snd_soc_card_evm; - index = 0; - } else if (machine_is_davinci_da830_evm()) { - evm_snd_dev_data = &da830_snd_soc_card; - index = 1; - } else if (machine_is_davinci_da850_evm()) { - evm_snd_dev_data = &da850_snd_soc_card; - index = 0; - } else - return -EINVAL; - - evm_snd_device = platform_device_alloc("soc-audio", index); - if (!evm_snd_device) - return -ENOMEM; - - platform_set_drvdata(evm_snd_device, evm_snd_dev_data); - ret = platform_device_add(evm_snd_device); - if (ret) - platform_device_put(evm_snd_device); - - return ret; -} - -static void __exit evm_exit(void) -{ -#if defined(CONFIG_OF) - if (of_have_populated_dt()) { - platform_driver_unregister(&davinci_evm_driver); - return; - } -#endif - - platform_device_unregister(evm_snd_device); -} - -module_init(evm_init); -module_exit(evm_exit); - -MODULE_AUTHOR("Vladimir Barinov"); -MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c deleted file mode 100644 index a3206e65e5e5..000000000000 --- a/sound/soc/davinci/davinci-i2s.c +++ /dev/null @@ -1,782 +0,0 @@ -/* - * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor - * - * Author: Vladimir Barinov, <vbarinov@embeddedalley.com> - * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> - * - * DT support (c) 2016 Petr Kulhavy, Barix AG <petr@barix.com> - * based on davinci-mcasp.c DT support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO: - * on DA850 implement HW FIFOs instead of DMA into DXR and DRR registers - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/platform_data/davinci_asp.h> - -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/initval.h> -#include <sound/soc.h> -#include <sound/dmaengine_pcm.h> - -#include "edma-pcm.h" -#include "davinci-i2s.h" - -#define DRV_NAME "davinci-i2s" - -/* - * NOTE: terminology here is confusing. - * - * - This driver supports the "Audio Serial Port" (ASP), - * found on dm6446, dm355, and other DaVinci chips. - * - * - But it labels it a "Multi-channel Buffered Serial Port" - * (McBSP) as on older chips like the dm642 ... which was - * backward-compatible, possibly explaining that confusion. - * - * - OMAP chips have a controller called McBSP, which is - * incompatible with the DaVinci flavor of McBSP. - * - * - Newer DaVinci chips have a controller called McASP, - * incompatible with ASP and with either McBSP. - * - * In short: this uses ASP to implement I2S, not McBSP. - * And it won't be the only DaVinci implemention of I2S. - */ -#define DAVINCI_MCBSP_DRR_REG 0x00 -#define DAVINCI_MCBSP_DXR_REG 0x04 -#define DAVINCI_MCBSP_SPCR_REG 0x08 -#define DAVINCI_MCBSP_RCR_REG 0x0c -#define DAVINCI_MCBSP_XCR_REG 0x10 -#define DAVINCI_MCBSP_SRGR_REG 0x14 -#define DAVINCI_MCBSP_PCR_REG 0x24 - -#define DAVINCI_MCBSP_SPCR_RRST (1 << 0) -#define DAVINCI_MCBSP_SPCR_RINTM(v) ((v) << 4) -#define DAVINCI_MCBSP_SPCR_XRST (1 << 16) -#define DAVINCI_MCBSP_SPCR_XINTM(v) ((v) << 20) -#define DAVINCI_MCBSP_SPCR_GRST (1 << 22) -#define DAVINCI_MCBSP_SPCR_FRST (1 << 23) -#define DAVINCI_MCBSP_SPCR_FREE (1 << 25) - -#define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5) -#define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8) -#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16) -#define DAVINCI_MCBSP_RCR_RFIG (1 << 18) -#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21) -#define DAVINCI_MCBSP_RCR_RFRLEN2(v) ((v) << 24) -#define DAVINCI_MCBSP_RCR_RPHASE BIT(31) - -#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5) -#define DAVINCI_MCBSP_XCR_XFRLEN1(v) ((v) << 8) -#define DAVINCI_MCBSP_XCR_XDATDLY(v) ((v) << 16) -#define DAVINCI_MCBSP_XCR_XFIG (1 << 18) -#define DAVINCI_MCBSP_XCR_XWDLEN2(v) ((v) << 21) -#define DAVINCI_MCBSP_XCR_XFRLEN2(v) ((v) << 24) -#define DAVINCI_MCBSP_XCR_XPHASE BIT(31) - -#define DAVINCI_MCBSP_SRGR_FWID(v) ((v) << 8) -#define DAVINCI_MCBSP_SRGR_FPER(v) ((v) << 16) -#define DAVINCI_MCBSP_SRGR_FSGM (1 << 28) -#define DAVINCI_MCBSP_SRGR_CLKSM BIT(29) - -#define DAVINCI_MCBSP_PCR_CLKRP (1 << 0) -#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1) -#define DAVINCI_MCBSP_PCR_FSRP (1 << 2) -#define DAVINCI_MCBSP_PCR_FSXP (1 << 3) -#define DAVINCI_MCBSP_PCR_SCLKME (1 << 7) -#define DAVINCI_MCBSP_PCR_CLKRM (1 << 8) -#define DAVINCI_MCBSP_PCR_CLKXM (1 << 9) -#define DAVINCI_MCBSP_PCR_FSRM (1 << 10) -#define DAVINCI_MCBSP_PCR_FSXM (1 << 11) - -enum { - DAVINCI_MCBSP_WORD_8 = 0, - DAVINCI_MCBSP_WORD_12, - DAVINCI_MCBSP_WORD_16, - DAVINCI_MCBSP_WORD_20, - DAVINCI_MCBSP_WORD_24, - DAVINCI_MCBSP_WORD_32, -}; - -static const unsigned char data_type[SNDRV_PCM_FORMAT_S32_LE + 1] = { - [SNDRV_PCM_FORMAT_S8] = 1, - [SNDRV_PCM_FORMAT_S16_LE] = 2, - [SNDRV_PCM_FORMAT_S32_LE] = 4, -}; - -static const unsigned char asp_word_length[SNDRV_PCM_FORMAT_S32_LE + 1] = { - [SNDRV_PCM_FORMAT_S8] = DAVINCI_MCBSP_WORD_8, - [SNDRV_PCM_FORMAT_S16_LE] = DAVINCI_MCBSP_WORD_16, - [SNDRV_PCM_FORMAT_S32_LE] = DAVINCI_MCBSP_WORD_32, -}; - -static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = { - [SNDRV_PCM_FORMAT_S8] = SNDRV_PCM_FORMAT_S16_LE, - [SNDRV_PCM_FORMAT_S16_LE] = SNDRV_PCM_FORMAT_S32_LE, -}; - -struct davinci_mcbsp_dev { - struct device *dev; - struct snd_dmaengine_dai_dma_data dma_data[2]; - int dma_request[2]; - void __iomem *base; -#define MOD_DSP_A 0 -#define MOD_DSP_B 1 - int mode; - u32 pcr; - struct clk *clk; - /* - * Combining both channels into 1 element will at least double the - * amount of time between servicing the dma channel, increase - * effiency, and reduce the chance of overrun/underrun. But, - * it will result in the left & right channels being swapped. - * - * If relabeling the left and right channels is not possible, - * you may want to let the codec know to swap them back. - * - * It may allow x10 the amount of time to service dma requests, - * if the codec is master and is using an unnecessarily fast bit clock - * (ie. tlvaic23b), independent of the sample rate. So, having an - * entire frame at once means it can be serviced at the sample rate - * instead of the bit clock rate. - * - * In the now unlikely case that an underrun still - * occurs, both the left and right samples will be repeated - * so that no pops are heard, and the left and right channels - * won't end up being swapped because of the underrun. - */ - unsigned enable_channel_combine:1; - - 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, - int reg, u32 val) -{ - __raw_writel(val, dev->base + reg); -} - -static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg) -{ - return __raw_readl(dev->base + reg); -} - -static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback) -{ - u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP; - /* The clock needs to toggle to complete reset. - * So, fake it by toggling the clk polarity. - */ - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m); - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr); -} - -static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, - struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - u32 spcr; - u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - if (spcr & mask) { - /* start off disabled */ - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, - spcr & ~mask); - toggle_clock(dev, playback); - } - if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | - DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) { - /* Start the sample generator */ - spcr |= DAVINCI_MCBSP_SPCR_GRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - } - - if (playback) { - /* Stop the DMA to avoid data loss */ - /* while the transmitter is out of reset to handle XSYNCERR */ - if (component->driver->ops->trigger) { - int ret = component->driver->ops->trigger(substream, - SNDRV_PCM_TRIGGER_STOP); - if (ret < 0) - printk(KERN_DEBUG "Playback DMA stop failed\n"); - } - - /* Enable the transmitter */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr |= DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - - /* wait for any unexpected frame sync error to occur */ - udelay(100); - - /* Disable the transmitter to clear any outstanding XSYNCERR */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr &= ~DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - toggle_clock(dev, playback); - - /* Restart the DMA */ - if (component->driver->ops->trigger) { - int ret = component->driver->ops->trigger(substream, - SNDRV_PCM_TRIGGER_START); - if (ret < 0) - printk(KERN_DEBUG "Playback DMA start failed\n"); - } - } - - /* Enable transmitter or receiver */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr |= mask; - - if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) { - /* Start frame sync */ - spcr |= DAVINCI_MCBSP_SPCR_FRST; - } - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); -} - -static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback) -{ - u32 spcr; - - /* Reset transmitter/receiver and sample rate/frame sync generators */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST); - spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - toggle_clock(dev, playback); -} - -#define DEFAULT_BITPERSAMPLE 16 - -static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - unsigned int pcr; - unsigned int srgr; - bool inv_fs = false; - /* Attention srgr is updated by hw_params! */ - srgr = DAVINCI_MCBSP_SRGR_FSGM | - DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | - DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); - - dev->fmt = fmt; - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* cpu is master */ - pcr = DAVINCI_MCBSP_PCR_FSXM | - DAVINCI_MCBSP_PCR_FSRM | - DAVINCI_MCBSP_PCR_CLKXM | - DAVINCI_MCBSP_PCR_CLKRM; - break; - case SND_SOC_DAIFMT_CBM_CFS: - 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 */ - pcr = 0; - break; - default: - printk(KERN_ERR "%s:bad master\n", __func__); - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - /* Davinci doesn't support TRUE I2S, but some codecs will have - * the left and right channels contiguous. This allows - * dsp_a mode to be used with an inverted normal frame clk. - * If your codec is master and does not have contiguous - * channels, then you will have sound on only one channel. - * Try using a different mode, or codec as slave. - * - * The TLV320AIC33 is an example of a codec where this works. - * It has a variable bit clock frequency allowing it to have - * valid data on every bit clock. - * - * The TLV320AIC23 is an example of a codec where this does not - * work. It has a fixed bit clock frequency with progressively - * more empty bit clock slots between channels as the sample - * rate is lowered. - */ - inv_fs = true; - /* fall through */ - case SND_SOC_DAIFMT_DSP_A: - dev->mode = MOD_DSP_A; - break; - case SND_SOC_DAIFMT_DSP_B: - dev->mode = MOD_DSP_B; - break; - default: - printk(KERN_ERR "%s:bad format\n", __func__); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - /* CLKRP Receive clock polarity, - * 1 - sampled on rising edge of CLKR - * valid on rising edge - * CLKXP Transmit clock polarity, - * 1 - clocked on falling edge of CLKX - * valid on rising edge - * FSRP Receive frame sync pol, 0 - active high - * FSXP Transmit frame sync pol, 0 - active high - */ - pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP); - break; - case SND_SOC_DAIFMT_IB_IF: - /* CLKRP Receive clock polarity, - * 0 - sampled on falling edge of CLKR - * valid on falling edge - * CLKXP Transmit clock polarity, - * 0 - clocked on rising edge of CLKX - * valid on falling edge - * FSRP Receive frame sync pol, 1 - active low - * FSXP Transmit frame sync pol, 1 - active low - */ - pcr |= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP); - break; - case SND_SOC_DAIFMT_NB_IF: - /* CLKRP Receive clock polarity, - * 1 - sampled on rising edge of CLKR - * valid on rising edge - * CLKXP Transmit clock polarity, - * 1 - clocked on falling edge of CLKX - * valid on rising edge - * FSRP Receive frame sync pol, 1 - active low - * FSXP Transmit frame sync pol, 1 - active low - */ - pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP | - DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP); - break; - case SND_SOC_DAIFMT_IB_NF: - /* CLKRP Receive clock polarity, - * 0 - sampled on falling edge of CLKR - * valid on falling edge - * CLKXP Transmit clock polarity, - * 0 - clocked on rising edge of CLKX - * valid on falling edge - * FSRP Receive frame sync pol, 0 - active high - * FSXP Transmit frame sync pol, 0 - active high - */ - break; - default: - return -EINVAL; - } - if (inv_fs == true) - pcr ^= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP); - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); - dev->pcr = pcr; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr); - return 0; -} - -static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, - int div_id, int div) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - - if (div_id != DAVINCI_MCBSP_CLKGDV) - return -ENODEV; - - dev->clk_div = div; - return 0; -} - -static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); - struct snd_interval *i = NULL; - int mcbsp_word_length, master; - unsigned int rcr, xcr, srgr, clk_div, freq, framesize; - u32 spcr; - snd_pcm_format_t fmt; - unsigned element_cnt = 1; - - /* general line settings */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - } else { - spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - } - - master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; - fmt = params_format(params); - mcbsp_word_length = asp_word_length[fmt]; - - switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: - freq = clk_get_rate(dev->clk); - srgr = DAVINCI_MCBSP_SRGR_FSGM | - DAVINCI_MCBSP_SRGR_CLKSM; - srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * - 8 - 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; - case SND_SOC_DAIFMT_CBM_CFS: - srgr = DAVINCI_MCBSP_SRGR_FSGM; - clk_div = dev->clk_div - 1; - srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1); - srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1); - clk_div &= 0xFF; - srgr |= clk_div; - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* Clock and frame sync given from external sources */ - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); - srgr = DAVINCI_MCBSP_SRGR_FSGM; - srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); - pr_debug("%s - %d FWID set: re-read srgr = %X\n", - __func__, __LINE__, snd_interval_value(i) - 1); - - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); - srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); - break; - default: - return -EINVAL; - } - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); - - rcr = DAVINCI_MCBSP_RCR_RFIG; - xcr = DAVINCI_MCBSP_XCR_XFIG; - if (dev->mode == MOD_DSP_B) { - rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0); - xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0); - } else { - rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); - xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); - } - /* Determine xfer data type */ - fmt = params_format(params); - if ((fmt > SNDRV_PCM_FORMAT_S32_LE) || !data_type[fmt]) { - printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n"); - return -EINVAL; - } - - if (params_channels(params) == 2) { - element_cnt = 2; - if (double_fmt[fmt] && dev->enable_channel_combine) { - element_cnt = 1; - fmt = double_fmt[fmt]; - } - switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBS_CFM: - rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0); - rcr |= DAVINCI_MCBSP_RCR_RPHASE; - xcr |= DAVINCI_MCBSP_XCR_XPHASE; - break; - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1); - break; - default: - return -EINVAL; - } - } - mcbsp_word_length = asp_word_length[fmt]; - - switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBS_CFM: - rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0); - break; - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1); - break; - default: - return -EINVAL; - } - - rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | - DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); - xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | - DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); - else - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); - - pr_debug("%s - %d srgr=%X\n", __func__, __LINE__, srgr); - pr_debug("%s - %d xcr=%X\n", __func__, __LINE__, xcr); - pr_debug("%s - %d rcr=%X\n", __func__, __LINE__, rcr); - return 0; -} - -static int davinci_i2s_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - davinci_mcbsp_stop(dev, playback); - return 0; -} - -static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); - int ret = 0; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - davinci_mcbsp_start(dev, substream); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_mcbsp_stop(dev, playback); - break; - default: - ret = -EINVAL; - } - return ret; -} - -static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - davinci_mcbsp_stop(dev, playback); -} - -#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 - -static const struct snd_soc_dai_ops davinci_i2s_dai_ops = { - .shutdown = davinci_i2s_shutdown, - .prepare = davinci_i2s_prepare, - .trigger = davinci_i2s_trigger, - .hw_params = davinci_i2s_hw_params, - .set_fmt = davinci_i2s_set_dai_fmt, - .set_clkdiv = davinci_i2s_dai_set_clkdiv, - -}; - -static int davinci_i2s_dai_probe(struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); - - dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; - dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; - - return 0; -} - -static struct snd_soc_dai_driver davinci_i2s_dai = { - .probe = davinci_i2s_dai_probe, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &davinci_i2s_dai_ops, - -}; - -static const struct snd_soc_component_driver davinci_i2s_component = { - .name = DRV_NAME, -}; - -static int davinci_i2s_probe(struct platform_device *pdev) -{ - struct snd_dmaengine_dai_dma_data *dma_data; - struct davinci_mcbsp_dev *dev; - struct resource *mem, *res; - void __iomem *io_base; - int *dma; - int ret; - - mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); - if (!mem) { - dev_warn(&pdev->dev, - "\"mpu\" mem resource not found, using index 0\n"); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -ENODEV; - } - } - - io_base = devm_ioremap_resource(&pdev->dev, mem); - if (IS_ERR(io_base)) - return PTR_ERR(io_base); - - dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcbsp_dev), - GFP_KERNEL); - if (!dev) - return -ENOMEM; - - dev->base = io_base; - - /* setup DMA, first TX, then RX */ - dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; - dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); - - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (res) { - dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK]; - *dma = res->start; - dma_data->filter_data = dma; - } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { - dma_data->filter_data = "tx"; - } else { - dev_err(&pdev->dev, "Missing DMA tx resource\n"); - return -ENODEV; - } - - dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; - dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG); - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (res) { - dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE]; - *dma = res->start; - dma_data->filter_data = dma; - } else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { - dma_data->filter_data = "rx"; - } else { - dev_err(&pdev->dev, "Missing DMA rx resource\n"); - return -ENODEV; - } - - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) - return -ENODEV; - clk_enable(dev->clk); - - dev->dev = &pdev->dev; - dev_set_drvdata(&pdev->dev, dev); - - ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component, - &davinci_i2s_dai, 1); - if (ret != 0) - goto err_release_clk; - - ret = edma_pcm_platform_register(&pdev->dev); - if (ret) { - dev_err(&pdev->dev, "register PCM failed: %d\n", ret); - goto err_unregister_component; - } - - return 0; - -err_unregister_component: - snd_soc_unregister_component(&pdev->dev); -err_release_clk: - clk_disable(dev->clk); - clk_put(dev->clk); - return ret; -} - -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); - - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; - - return 0; -} - -static const struct of_device_id davinci_i2s_match[] = { - { .compatible = "ti,da850-mcbsp" }, - {}, -}; -MODULE_DEVICE_TABLE(of, davinci_i2s_match); - -static struct platform_driver davinci_mcbsp_driver = { - .probe = davinci_i2s_probe, - .remove = davinci_i2s_remove, - .driver = { - .name = "davinci-mcbsp", - .of_match_table = of_match_ptr(davinci_i2s_match), - }, -}; - -module_platform_driver(davinci_mcbsp_driver); - -MODULE_AUTHOR("Vladimir Barinov"); -MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h deleted file mode 100644 index 48dac3e2521a..000000000000 --- a/sound/soc/davinci/davinci-i2s.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor - * - * Author: Vladimir Barinov, <vbarinov@embeddedalley.com> - * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _DAVINCI_I2S_H -#define _DAVINCI_I2S_H - -/* McBSP dividers */ -enum davinci_mcbsp_div { - DAVINCI_MCBSP_CLKGDV, /* Sample rate generator divider */ -}; - -#endif diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c deleted file mode 100644 index 40d3a916fb74..000000000000 --- a/sound/soc/davinci/davinci-mcasp.c +++ /dev/null @@ -1,2212 +0,0 @@ -/* - * ALSA SoC McASP Audio Layer for TI DAVINCI processor - * - * Multi-channel Audio Serial Port Driver - * - * Author: Nirmal Pandey <n-pandey@ti.com>, - * Suresh Rajashekara <suresh.r@ti.com> - * Steve Chen <schen@.mvista.com> - * - * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com> - * Copyright: (C) 2009 Texas Instruments, India - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/pm_runtime.h> -#include <linux/of.h> -#include <linux/of_platform.h> -#include <linux/of_device.h> -#include <linux/platform_data/davinci_asp.h> -#include <linux/math64.h> -#include <linux/bitmap.h> - -#include <sound/asoundef.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/initval.h> -#include <sound/soc.h> -#include <sound/dmaengine_pcm.h> - -#include "edma-pcm.h" -#include "../omap/sdma-pcm.h" -#include "davinci-mcasp.h" - -#define MCASP_MAX_AFIFO_DEPTH 64 - -static u32 context_regs[] = { - DAVINCI_MCASP_TXFMCTL_REG, - DAVINCI_MCASP_RXFMCTL_REG, - DAVINCI_MCASP_TXFMT_REG, - DAVINCI_MCASP_RXFMT_REG, - DAVINCI_MCASP_ACLKXCTL_REG, - DAVINCI_MCASP_ACLKRCTL_REG, - DAVINCI_MCASP_AHCLKXCTL_REG, - DAVINCI_MCASP_AHCLKRCTL_REG, - DAVINCI_MCASP_PDIR_REG, - DAVINCI_MCASP_RXMASK_REG, - DAVINCI_MCASP_TXMASK_REG, - DAVINCI_MCASP_RXTDM_REG, - DAVINCI_MCASP_TXTDM_REG, -}; - -struct davinci_mcasp_context { - u32 config_regs[ARRAY_SIZE(context_regs)]; - u32 afifo_regs[2]; /* for read/write fifo control registers */ - u32 *xrsr_regs; /* for serializer configuration */ - bool pm_state; -}; - -struct davinci_mcasp_ruledata { - struct davinci_mcasp *mcasp; - int serializers; -}; - -struct davinci_mcasp { - struct snd_dmaengine_dai_dma_data dma_data[2]; - void __iomem *base; - u32 fifo_base; - struct device *dev; - struct snd_pcm_substream *substreams[2]; - unsigned int dai_fmt; - - /* McASP specific data */ - int tdm_slots; - u32 tdm_mask[2]; - int slot_width; - u8 op_mode; - u8 dismod; - u8 num_serializer; - u8 *serial_dir; - u8 version; - u8 bclk_div; - int streams; - u32 irq_request[2]; - int dma_request[2]; - - int sysclk_freq; - bool bclk_master; - - unsigned long pdir; /* Pin direction bitfield */ - - /* McASP FIFO related */ - u8 txnumevt; - u8 rxnumevt; - - bool dat_port; - - /* Used for comstraint setting on the second stream */ - u32 channels; - -#ifdef CONFIG_PM_SLEEP - struct davinci_mcasp_context context; -#endif - - struct davinci_mcasp_ruledata ruledata[2]; - struct snd_pcm_hw_constraint_list chconstr[2]; -}; - -static inline void mcasp_set_bits(struct davinci_mcasp *mcasp, u32 offset, - u32 val) -{ - void __iomem *reg = mcasp->base + offset; - __raw_writel(__raw_readl(reg) | val, reg); -} - -static inline void mcasp_clr_bits(struct davinci_mcasp *mcasp, u32 offset, - u32 val) -{ - void __iomem *reg = mcasp->base + offset; - __raw_writel((__raw_readl(reg) & ~(val)), reg); -} - -static inline void mcasp_mod_bits(struct davinci_mcasp *mcasp, u32 offset, - u32 val, u32 mask) -{ - void __iomem *reg = mcasp->base + offset; - __raw_writel((__raw_readl(reg) & ~mask) | val, reg); -} - -static inline void mcasp_set_reg(struct davinci_mcasp *mcasp, u32 offset, - u32 val) -{ - __raw_writel(val, mcasp->base + offset); -} - -static inline u32 mcasp_get_reg(struct davinci_mcasp *mcasp, u32 offset) -{ - return (u32)__raw_readl(mcasp->base + offset); -} - -static void mcasp_set_ctl_reg(struct davinci_mcasp *mcasp, u32 ctl_reg, u32 val) -{ - int i = 0; - - mcasp_set_bits(mcasp, ctl_reg, val); - - /* programming GBLCTL needs to read back from GBLCTL and verfiy */ - /* loop count is to avoid the lock-up */ - for (i = 0; i < 1000; i++) { - if ((mcasp_get_reg(mcasp, ctl_reg) & val) == val) - break; - } - - if (i == 1000 && ((mcasp_get_reg(mcasp, ctl_reg) & val) != val)) - printk(KERN_ERR "GBLCTL write error\n"); -} - -static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp) -{ - u32 rxfmctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG); - u32 aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG); - - return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE; -} - -static inline void mcasp_set_clk_pdir(struct davinci_mcasp *mcasp, bool enable) -{ - u32 bit = PIN_BIT_AMUTE; - - for_each_set_bit_from(bit, &mcasp->pdir, PIN_BIT_AFSR + 1) { - if (enable) - mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); - else - mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); - } -} - -static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable) -{ - u32 bit; - - for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AFSR) { - if (enable) - mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); - else - mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); - } -} - -static void mcasp_start_rx(struct davinci_mcasp *mcasp) -{ - if (mcasp->rxnumevt) { /* enable FIFO */ - u32 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; - - mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); - mcasp_set_bits(mcasp, reg, FIFO_ENABLE); - } - - /* Start clocks */ - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); - /* - * When ASYNC == 0 the transmit and receive sections operate - * synchronously from the transmit clock and frame sync. We need to make - * sure that the TX signlas are enabled when starting reception. - */ - if (mcasp_is_synchronous(mcasp)) { - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); - } - - /* Activate serializer(s) */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); - /* Release RX state machine */ - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); - /* Release Frame Sync generator */ - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); - if (mcasp_is_synchronous(mcasp)) - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); - - /* enable receive IRQs */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLR_REG, - mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE]); -} - -static void mcasp_start_tx(struct davinci_mcasp *mcasp) -{ - u32 cnt; - - if (mcasp->txnumevt) { /* enable FIFO */ - u32 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; - - mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); - mcasp_set_bits(mcasp, reg, FIFO_ENABLE); - } - - /* Start clocks */ - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); - mcasp_set_clk_pdir(mcasp, true); - - /* Activate serializer(s) */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); - - /* wait for XDATA to be cleared */ - cnt = 0; - while ((mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG) & XRDATA) && - (cnt < 100000)) - cnt++; - - mcasp_set_axr_pdir(mcasp, true); - - /* Release TX state machine */ - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); - /* Release Frame Sync generator */ - mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); - - /* enable transmit IRQs */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG, - mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]); -} - -static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream) -{ - mcasp->streams++; - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - mcasp_start_tx(mcasp); - else - mcasp_start_rx(mcasp); -} - -static void mcasp_stop_rx(struct davinci_mcasp *mcasp) -{ - /* disable IRQ sources */ - mcasp_clr_bits(mcasp, DAVINCI_MCASP_EVTCTLR_REG, - mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE]); - - /* - * In synchronous mode stop the TX clocks if no other stream is - * running - */ - if (mcasp_is_synchronous(mcasp) && !mcasp->streams) { - mcasp_set_clk_pdir(mcasp, false); - mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0); - } - - mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); - - if (mcasp->rxnumevt) { /* disable FIFO */ - u32 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; - - mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); - } -} - -static void mcasp_stop_tx(struct davinci_mcasp *mcasp) -{ - u32 val = 0; - - /* disable IRQ sources */ - mcasp_clr_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG, - mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]); - - /* - * In synchronous mode keep TX clocks running if the capture stream is - * still running. - */ - if (mcasp_is_synchronous(mcasp) && mcasp->streams) - val = TXHCLKRST | TXCLKRST | TXFSRST; - else - mcasp_set_clk_pdir(mcasp, false); - - - mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val); - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); - - if (mcasp->txnumevt) { /* disable FIFO */ - u32 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; - - mcasp_clr_bits(mcasp, reg, FIFO_ENABLE); - } - - mcasp_set_axr_pdir(mcasp, false); -} - -static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream) -{ - mcasp->streams--; - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - mcasp_stop_tx(mcasp); - else - mcasp_stop_rx(mcasp); -} - -static irqreturn_t davinci_mcasp_tx_irq_handler(int irq, void *data) -{ - struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data; - struct snd_pcm_substream *substream; - u32 irq_mask = mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]; - u32 handled_mask = 0; - u32 stat; - - stat = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG); - if (stat & XUNDRN & irq_mask) { - dev_warn(mcasp->dev, "Transmit buffer underflow\n"); - handled_mask |= XUNDRN; - - substream = mcasp->substreams[SNDRV_PCM_STREAM_PLAYBACK]; - if (substream) - snd_pcm_stop_xrun(substream); - } - - if (!handled_mask) - dev_warn(mcasp->dev, "unhandled tx event. txstat: 0x%08x\n", - stat); - - if (stat & XRERR) - handled_mask |= XRERR; - - /* Ack the handled event only */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, handled_mask); - - return IRQ_RETVAL(handled_mask); -} - -static irqreturn_t davinci_mcasp_rx_irq_handler(int irq, void *data) -{ - struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data; - struct snd_pcm_substream *substream; - u32 irq_mask = mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE]; - u32 handled_mask = 0; - u32 stat; - - stat = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG); - if (stat & ROVRN & irq_mask) { - dev_warn(mcasp->dev, "Receive buffer overflow\n"); - handled_mask |= ROVRN; - - substream = mcasp->substreams[SNDRV_PCM_STREAM_CAPTURE]; - if (substream) - snd_pcm_stop_xrun(substream); - } - - if (!handled_mask) - dev_warn(mcasp->dev, "unhandled rx event. rxstat: 0x%08x\n", - stat); - - if (stat & XRERR) - handled_mask |= XRERR; - - /* Ack the handled event only */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, handled_mask); - - return IRQ_RETVAL(handled_mask); -} - -static irqreturn_t davinci_mcasp_common_irq_handler(int irq, void *data) -{ - struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data; - irqreturn_t ret = IRQ_NONE; - - if (mcasp->substreams[SNDRV_PCM_STREAM_PLAYBACK]) - ret = davinci_mcasp_tx_irq_handler(irq, data); - - if (mcasp->substreams[SNDRV_PCM_STREAM_CAPTURE]) - ret |= davinci_mcasp_rx_irq_handler(irq, data); - - return ret; -} - -static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - 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; - - if (!fmt) - return 0; - - 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; - 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); - /* 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 */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - /* BCLK */ - set_bit(PIN_BIT_ACLKX, &mcasp->pdir); - set_bit(PIN_BIT_ACLKR, &mcasp->pdir); - /* Frame Sync */ - set_bit(PIN_BIT_AFSX, &mcasp->pdir); - set_bit(PIN_BIT_AFSR, &mcasp->pdir); - - mcasp->bclk_master = 1; - break; - case SND_SOC_DAIFMT_CBS_CFM: - /* codec is clock slave and frame master */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - /* BCLK */ - set_bit(PIN_BIT_ACLKX, &mcasp->pdir); - set_bit(PIN_BIT_ACLKR, &mcasp->pdir); - /* Frame Sync */ - clear_bit(PIN_BIT_AFSX, &mcasp->pdir); - clear_bit(PIN_BIT_AFSR, &mcasp->pdir); - - mcasp->bclk_master = 1; - break; - case SND_SOC_DAIFMT_CBM_CFS: - /* codec is clock master and frame slave */ - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - /* BCLK */ - clear_bit(PIN_BIT_ACLKX, &mcasp->pdir); - clear_bit(PIN_BIT_ACLKR, &mcasp->pdir); - /* Frame Sync */ - set_bit(PIN_BIT_AFSX, &mcasp->pdir); - set_bit(PIN_BIT_AFSR, &mcasp->pdir); - - mcasp->bclk_master = 0; - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* codec is clock and frame master */ - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - /* BCLK */ - clear_bit(PIN_BIT_ACLKX, &mcasp->pdir); - clear_bit(PIN_BIT_ACLKR, &mcasp->pdir); - /* Frame Sync */ - clear_bit(PIN_BIT_AFSX, &mcasp->pdir); - clear_bit(PIN_BIT_AFSR, &mcasp->pdir); - - mcasp->bclk_master = 0; - break; - default: - ret = -EINVAL; - goto out; - } - - 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_ACLKRCTL_REG, ACLKRPOL); - 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_ACLKRCTL_REG, ACLKRPOL); - fs_pol_rising = false; - break; - case SND_SOC_DAIFMT_IB_IF: - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - fs_pol_rising = false; - break; - case SND_SOC_DAIFMT_NB_NF: - mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - fs_pol_rising = true; - break; - default: - ret = -EINVAL; - 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); - } - - mcasp->dai_fmt = fmt; -out: - pm_runtime_put(mcasp->dev); - return ret; -} - -static int __davinci_mcasp_set_clkdiv(struct davinci_mcasp *mcasp, int div_id, - int div, bool explicit) -{ - pm_runtime_get_sync(mcasp->dev); - switch (div_id) { - case MCASP_CLKDIV_AUXCLK: /* MCLK divider */ - mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, - AHCLKXDIV(div - 1), AHCLKXDIV_MASK); - mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, - AHCLKRDIV(div - 1), AHCLKRDIV_MASK); - break; - - case MCASP_CLKDIV_BCLK: /* BCLK divider */ - mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, - ACLKXDIV(div - 1), ACLKXDIV_MASK); - mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, - ACLKRDIV(div - 1), ACLKRDIV_MASK); - if (explicit) - mcasp->bclk_div = div; - break; - - case MCASP_CLKDIV_BCLK_FS_RATIO: - /* - * BCLK/LRCLK ratio descries how many bit-clock cycles - * fit into one frame. The clock ratio is given for a - * full period of data (for I2S format both left and - * right channels), so it has to be divided by number - * of tdm-slots (for I2S - divided by 2). - * Instead of storing this ratio, we calculate a new - * tdm_slot width by dividing the the ratio by the - * number of configured tdm slots. - */ - mcasp->slot_width = div / mcasp->tdm_slots; - if (div % mcasp->tdm_slots) - dev_warn(mcasp->dev, - "%s(): BCLK/LRCLK %d is not divisible by %d tdm slots", - __func__, div, mcasp->tdm_slots); - break; - - default: - return -EINVAL; - } - - pm_runtime_put(mcasp->dev); - return 0; -} - -static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, - int div) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - - return __davinci_mcasp_set_clkdiv(mcasp, div_id, div, 1); -} - -static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, int dir) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - - pm_runtime_get_sync(mcasp->dev); - if (dir == SND_SOC_CLOCK_OUT) { - mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); - mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE); - set_bit(PIN_BIT_AHCLKX, &mcasp->pdir); - } else { - mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE); - clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir); - } - - mcasp->sysclk_freq = freq; - - pm_runtime_put(mcasp->dev); - return 0; -} - -/* All serializers must have equal number of channels */ -static int davinci_mcasp_ch_constraint(struct davinci_mcasp *mcasp, int stream, - int serializers) -{ - struct snd_pcm_hw_constraint_list *cl = &mcasp->chconstr[stream]; - unsigned int *list = (unsigned int *) cl->list; - int slots = mcasp->tdm_slots; - int i, count = 0; - - if (mcasp->tdm_mask[stream]) - slots = hweight32(mcasp->tdm_mask[stream]); - - for (i = 1; i <= slots; i++) - list[count++] = i; - - for (i = 2; i <= serializers; i++) - list[count++] = i*slots; - - cl->count = count; - - return 0; -} - -static int davinci_mcasp_set_ch_constraints(struct davinci_mcasp *mcasp) -{ - int rx_serializers = 0, tx_serializers = 0, ret, i; - - for (i = 0; i < mcasp->num_serializer; i++) - if (mcasp->serial_dir[i] == TX_MODE) - tx_serializers++; - else if (mcasp->serial_dir[i] == RX_MODE) - rx_serializers++; - - ret = davinci_mcasp_ch_constraint(mcasp, SNDRV_PCM_STREAM_PLAYBACK, - tx_serializers); - if (ret) - return ret; - - ret = davinci_mcasp_ch_constraint(mcasp, SNDRV_PCM_STREAM_CAPTURE, - rx_serializers); - - return ret; -} - - -static int davinci_mcasp_set_tdm_slot(struct snd_soc_dai *dai, - unsigned int tx_mask, - unsigned int rx_mask, - int slots, int slot_width) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - - dev_dbg(mcasp->dev, - "%s() tx_mask 0x%08x rx_mask 0x%08x slots %d width %d\n", - __func__, tx_mask, rx_mask, slots, slot_width); - - if (tx_mask >= (1<<slots) || rx_mask >= (1<<slots)) { - dev_err(mcasp->dev, - "Bad tdm mask tx: 0x%08x rx: 0x%08x slots %d\n", - tx_mask, rx_mask, slots); - return -EINVAL; - } - - if (slot_width && - (slot_width < 8 || slot_width > 32 || slot_width % 4 != 0)) { - dev_err(mcasp->dev, "%s: Unsupported slot_width %d\n", - __func__, slot_width); - return -EINVAL; - } - - mcasp->tdm_slots = slots; - mcasp->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask; - mcasp->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask; - mcasp->slot_width = slot_width; - - return davinci_mcasp_set_ch_constraints(mcasp); -} - -static int davinci_config_channel_size(struct davinci_mcasp *mcasp, - int sample_width) -{ - u32 fmt; - u32 tx_rotate = (sample_width / 4) & 0x7; - u32 mask = (1ULL << sample_width) - 1; - u32 slot_width = sample_width; - - /* - * For captured data we should not rotate, inversion and masking is - * enoguh to get the data to the right position: - * Format data from bus after reverse (XRBUF) - * S16_LE: |LSB|MSB|xxx|xxx| |xxx|xxx|MSB|LSB| - * S24_3LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| - * S24_LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| - * S32_LE: |LSB|DAT|DAT|MSB| |MSB|DAT|DAT|LSB| - */ - u32 rx_rotate = 0; - - /* - * Setting the tdm slot width either with set_clkdiv() or - * set_tdm_slot() allows us to for example send 32 bits per - * channel to the codec, while only 16 of them carry audio - * payload. - */ - if (mcasp->slot_width) { - /* - * When we have more bclk then it is needed for the - * data, we need to use the rotation to move the - * received samples to have correct alignment. - */ - slot_width = mcasp->slot_width; - rx_rotate = (slot_width - sample_width) / 4; - } - - /* mapping of the XSSZ bit-field as described in the datasheet */ - fmt = (slot_width >> 1) - 1; - - if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) { - mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt), - RXSSZ(0x0F)); - mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt), - TXSSZ(0x0F)); - mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate), - TXROT(7)); - mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate), - RXROT(7)); - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask); - } - - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); - - return 0; -} - -static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, - int period_words, int channels) -{ - struct snd_dmaengine_dai_dma_data *dma_data = &mcasp->dma_data[stream]; - int i; - u8 tx_ser = 0; - u8 rx_ser = 0; - u8 slots = mcasp->tdm_slots; - u8 max_active_serializers = (channels + slots - 1) / slots; - int active_serializers, numevt; - u32 reg; - /* Default configuration */ - if (mcasp->version < MCASP_VERSION_3) - mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); - - /* All PINS as McASP */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); - } else { - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); - mcasp_clr_bits(mcasp, DAVINCI_MCASP_REVTCTL_REG, RXDATADMADIS); - } - - for (i = 0; i < mcasp->num_serializer; i++) { - mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), - mcasp->serial_dir[i]); - if (mcasp->serial_dir[i] == TX_MODE && - tx_ser < max_active_serializers) { - mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), - mcasp->dismod, DISMOD_MASK); - set_bit(PIN_BIT_AXR(i), &mcasp->pdir); - tx_ser++; - } else if (mcasp->serial_dir[i] == RX_MODE && - rx_ser < max_active_serializers) { - clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); - rx_ser++; - } else if (mcasp->serial_dir[i] == INACTIVE_MODE) { - mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), - SRMOD_INACTIVE, SRMOD_MASK); - clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); - } else if (mcasp->serial_dir[i] == TX_MODE) { - /* Unused TX pins, clear PDIR */ - mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), - mcasp->dismod, DISMOD_MASK); - clear_bit(PIN_BIT_AXR(i), &mcasp->pdir); - } - } - - 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 (active_serializers < max_active_serializers) { - dev_warn(mcasp->dev, "stream has more channels (%d) than are " - "enabled in mcasp (%d)\n", channels, - active_serializers * slots); - return -EINVAL; - } - - /* 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_data->maxburst = active_serializers; - } else { - dma_data->maxburst = 0; - } - return 0; - } - - 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. - */ - numevt = (numevt / active_serializers) * active_serializers; - - 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_data->maxburst = numevt; - - return 0; -} - -static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream, - int channels) -{ - int i, active_slots; - int total_slots; - int active_serializers; - u32 mask = 0; - u32 busel = 0; - - total_slots = mcasp->tdm_slots; - - /* - * If more than one serializer is needed, then use them with - * all the specified tdm_slots. Otherwise, one serializer can - * cope with the transaction using just as many slots as there - * are channels in the stream. - */ - if (mcasp->tdm_mask[stream]) { - active_slots = hweight32(mcasp->tdm_mask[stream]); - active_serializers = (channels + active_slots - 1) / - active_slots; - if (active_serializers == 1) { - active_slots = channels; - for (i = 0; i < total_slots; i++) { - if ((1 << i) & mcasp->tdm_mask[stream]) { - mask |= (1 << i); - if (--active_slots <= 0) - break; - } - } - } - } else { - active_serializers = (channels + total_slots - 1) / total_slots; - if (active_serializers == 1) - active_slots = channels; - else - active_slots = total_slots; - - for (i = 0; i < active_slots; i++) - mask |= (1 << i); - } - mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); - - if (!mcasp->dat_port) - busel = TXSEL; - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask); - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD); - mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, - FSXMOD(total_slots), FSXMOD(0x1FF)); - } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { - mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask); - mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD); - mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, - FSRMOD(total_slots), FSRMOD(0x1FF)); - /* - * If McASP is set to be TX/RX synchronous and the playback is - * not running already we need to configure the TX slots in - * order to have correct FSX on the bus - */ - if (mcasp_is_synchronous(mcasp) && !mcasp->channels) - mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, - FSXMOD(total_slots), FSXMOD(0x1FF)); - } - - return 0; -} - -/* S/PDIF */ -static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, - unsigned int rate) -{ - u32 cs_value = 0; - u8 *cs_bytes = (u8*) &cs_value; - - /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 - and LSB first */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15)); - - /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE | FSXMOD(0x180)); - - /* Set the TX tdm : for all the slots */ - mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF); - - /* Set the TX clock controls : div = 1 and internal */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | TX_ASYNC); - - mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); - - /* Only 44100 and 48000 are valid, both have the same setting */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3)); - - /* Enable the DIT */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); - - /* Set S/PDIF channel status bits */ - cs_bytes[0] = IEC958_AES0_CON_NOT_COPYRIGHT; - cs_bytes[1] = IEC958_AES1_CON_PCM_CODER; - - switch (rate) { - case 22050: - cs_bytes[3] |= IEC958_AES3_CON_FS_22050; - break; - case 24000: - cs_bytes[3] |= IEC958_AES3_CON_FS_24000; - break; - case 32000: - cs_bytes[3] |= IEC958_AES3_CON_FS_32000; - break; - case 44100: - cs_bytes[3] |= IEC958_AES3_CON_FS_44100; - break; - case 48000: - cs_bytes[3] |= IEC958_AES3_CON_FS_48000; - break; - case 88200: - cs_bytes[3] |= IEC958_AES3_CON_FS_88200; - break; - case 96000: - cs_bytes[3] |= IEC958_AES3_CON_FS_96000; - break; - case 176400: - cs_bytes[3] |= IEC958_AES3_CON_FS_176400; - break; - case 192000: - cs_bytes[3] |= IEC958_AES3_CON_FS_192000; - break; - default: - printk(KERN_WARNING "unsupported sampling rate: %d\n", rate); - return -EINVAL; - } - - mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, cs_value); - mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, cs_value); - - return 0; -} - -static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp, - unsigned int bclk_freq, bool set) -{ - int error_ppm; - unsigned int sysclk_freq = mcasp->sysclk_freq; - u32 reg = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG); - int div = sysclk_freq / bclk_freq; - int rem = sysclk_freq % bclk_freq; - int aux_div = 1; - - if (div > (ACLKXDIV_MASK + 1)) { - if (reg & AHCLKXE) { - aux_div = div / (ACLKXDIV_MASK + 1); - if (div % (ACLKXDIV_MASK + 1)) - aux_div++; - - sysclk_freq /= aux_div; - div = sysclk_freq / bclk_freq; - rem = sysclk_freq % bclk_freq; - } else if (set) { - dev_warn(mcasp->dev, "Too fast reference clock (%u)\n", - sysclk_freq); - } - } - - if (rem != 0) { - if (div == 0 || - ((sysclk_freq / div) - bclk_freq) > - (bclk_freq - (sysclk_freq / (div+1)))) { - div++; - rem = rem - bclk_freq; - } - } - error_ppm = (div*1000000 + (int)div64_long(1000000LL*rem, - (int)bclk_freq)) / div - 1000000; - - if (set) { - if (error_ppm) - dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n", - error_ppm); - - __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_BCLK, div, 0); - if (reg & AHCLKXE) - __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_AUXCLK, - aux_div, 0); - } - - return error_ppm; -} - -static inline u32 davinci_mcasp_tx_delay(struct davinci_mcasp *mcasp) -{ - if (!mcasp->txnumevt) - return 0; - - return mcasp_get_reg(mcasp, mcasp->fifo_base + MCASP_WFIFOSTS_OFFSET); -} - -static inline u32 davinci_mcasp_rx_delay(struct davinci_mcasp *mcasp) -{ - if (!mcasp->rxnumevt) - return 0; - - return mcasp_get_reg(mcasp, mcasp->fifo_base + MCASP_RFIFOSTS_OFFSET); -} - -static snd_pcm_sframes_t davinci_mcasp_delay( - struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); - u32 fifo_use; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - fifo_use = davinci_mcasp_tx_delay(mcasp); - else - fifo_use = davinci_mcasp_rx_delay(mcasp); - - /* - * Divide the used locations with the channel count to get the - * FIFO usage in samples (don't care about partial samples in the - * buffer). - */ - return fifo_use / substream->runtime->channels; -} - -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_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); - int word_length; - int channels = params_channels(params); - int period_size = params_period_size(params); - int ret; - - ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt); - if (ret) - return ret; - - /* - * If mcasp is BCLK master, and a BCLK divider was not provided by - * the machine driver, we need to calculate the ratio. - */ - if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { - int slots = mcasp->tdm_slots; - int rate = params_rate(params); - int sbits = params_width(params); - - if (mcasp->slot_width) - sbits = mcasp->slot_width; - - davinci_mcasp_calc_clk_div(mcasp, rate * sbits * slots, true); - } - - ret = mcasp_common_hw_param(mcasp, substream->stream, - period_size * channels, channels); - if (ret) - return ret; - - if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) - ret = mcasp_dit_hw_param(mcasp, params_rate(params)); - else - ret = mcasp_i2s_hw_param(mcasp, substream->stream, - channels); - - if (ret) - return ret; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_U8: - case SNDRV_PCM_FORMAT_S8: - word_length = 8; - break; - - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_S16_LE: - word_length = 16; - break; - - case SNDRV_PCM_FORMAT_U24_3LE: - case SNDRV_PCM_FORMAT_S24_3LE: - word_length = 24; - break; - - case SNDRV_PCM_FORMAT_U24_LE: - case SNDRV_PCM_FORMAT_S24_LE: - word_length = 24; - break; - - case SNDRV_PCM_FORMAT_U32_LE: - case SNDRV_PCM_FORMAT_S32_LE: - word_length = 32; - break; - - default: - printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); - return -EINVAL; - } - - davinci_config_channel_size(mcasp, word_length); - - if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) - mcasp->channels = channels; - - return 0; -} - -static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *cpu_dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - davinci_mcasp_start(mcasp, substream->stream); - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_mcasp_stop(mcasp, substream->stream); - break; - - default: - ret = -EINVAL; - } - - return ret; -} - -static const unsigned int davinci_mcasp_dai_rates[] = { - 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, - 88200, 96000, 176400, 192000, -}; - -#define DAVINCI_MAX_RATE_ERROR_PPM 1000 - -static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct davinci_mcasp_ruledata *rd = rule->private; - struct snd_interval *ri = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - int sbits = params_width(params); - int slots = rd->mcasp->tdm_slots; - struct snd_interval range; - int i; - - if (rd->mcasp->slot_width) - sbits = rd->mcasp->slot_width; - - snd_interval_any(&range); - range.empty = 1; - - for (i = 0; i < ARRAY_SIZE(davinci_mcasp_dai_rates); i++) { - if (snd_interval_test(ri, davinci_mcasp_dai_rates[i])) { - uint bclk_freq = sbits*slots* - davinci_mcasp_dai_rates[i]; - int ppm; - - ppm = davinci_mcasp_calc_clk_div(rd->mcasp, bclk_freq, - false); - if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { - if (range.empty) { - range.min = davinci_mcasp_dai_rates[i]; - range.empty = 0; - } - range.max = davinci_mcasp_dai_rates[i]; - } - } - } - - dev_dbg(rd->mcasp->dev, - "Frequencies %d-%d -> %d-%d for %d sbits and %d tdm slots\n", - ri->min, ri->max, range.min, range.max, sbits, slots); - - return snd_interval_refine(hw_param_interval(params, rule->var), - &range); -} - -static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct davinci_mcasp_ruledata *rd = rule->private; - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_mask nfmt; - int rate = params_rate(params); - int slots = rd->mcasp->tdm_slots; - int i, count = 0; - - snd_mask_none(&nfmt); - - for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { - if (snd_mask_test(fmt, i)) { - uint sbits = snd_pcm_format_width(i); - int ppm; - - if (rd->mcasp->slot_width) - sbits = rd->mcasp->slot_width; - - ppm = davinci_mcasp_calc_clk_div(rd->mcasp, - sbits * slots * rate, - false); - if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) { - snd_mask_set(&nfmt, i); - count++; - } - } - } - dev_dbg(rd->mcasp->dev, - "%d possible sample format for %d Hz and %d tdm slots\n", - count, rate, slots); - - return snd_mask_refine(fmt, &nfmt); -} - -static int davinci_mcasp_hw_rule_min_periodsize( - struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *period_size = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - struct snd_interval frames; - - snd_interval_any(&frames); - frames.min = 64; - frames.integer = 1; - - return snd_interval_refine(period_size, &frames); -} - -static int davinci_mcasp_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); - struct davinci_mcasp_ruledata *ruledata = - &mcasp->ruledata[substream->stream]; - u32 max_channels = 0; - int i, dir; - int tdm_slots = mcasp->tdm_slots; - - /* Do not allow more then one stream per direction */ - if (mcasp->substreams[substream->stream]) - return -EBUSY; - - mcasp->substreams[substream->stream] = substream; - - if (mcasp->tdm_mask[substream->stream]) - tdm_slots = hweight32(mcasp->tdm_mask[substream->stream]); - - if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) - return 0; - - /* - * Limit the maximum allowed channels for the first stream: - * number of serializers for the direction * tdm slots per serializer - */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dir = TX_MODE; - else - dir = RX_MODE; - - for (i = 0; i < mcasp->num_serializer; i++) { - if (mcasp->serial_dir[i] == dir) - max_channels++; - } - ruledata->serializers = max_channels; - max_channels *= tdm_slots; - /* - * If the already active stream has less channels than the calculated - * limnit based on the seirializers * tdm_slots, we need to use that as - * a constraint for the second stream. - * Otherwise (first stream or less allowed channels) we use the - * calculated constraint. - */ - if (mcasp->channels && mcasp->channels < max_channels) - max_channels = mcasp->channels; - /* - * But we can always allow channels upto the amount of - * the available tdm_slots. - */ - if (max_channels < tdm_slots) - max_channels = tdm_slots; - - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_CHANNELS, - 0, max_channels); - - snd_pcm_hw_constraint_list(substream->runtime, - 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &mcasp->chconstr[substream->stream]); - - if (mcasp->slot_width) - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - 8, mcasp->slot_width); - - /* - * If we rely on implicit BCLK divider setting we should - * set constraints based on what we can provide. - */ - if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { - int ret; - - ruledata->mcasp = mcasp; - - ret = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - davinci_mcasp_hw_rule_rate, - ruledata, - SNDRV_PCM_HW_PARAM_FORMAT, -1); - if (ret) - return ret; - ret = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - davinci_mcasp_hw_rule_format, - ruledata, - SNDRV_PCM_HW_PARAM_RATE, -1); - if (ret) - return ret; - } - - snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - davinci_mcasp_hw_rule_min_periodsize, NULL, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); - - return 0; -} - -static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); - - mcasp->substreams[substream->stream] = NULL; - - if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) - return; - - if (!cpu_dai->active) - mcasp->channels = 0; -} - -static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { - .startup = davinci_mcasp_startup, - .shutdown = davinci_mcasp_shutdown, - .trigger = davinci_mcasp_trigger, - .delay = davinci_mcasp_delay, - .hw_params = davinci_mcasp_hw_params, - .set_fmt = davinci_mcasp_set_dai_fmt, - .set_clkdiv = davinci_mcasp_set_clkdiv, - .set_sysclk = davinci_mcasp_set_sysclk, - .set_tdm_slot = davinci_mcasp_set_tdm_slot, -}; - -static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - - dai->playback_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; - dai->capture_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int davinci_mcasp_suspend(struct snd_soc_dai *dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - struct davinci_mcasp_context *context = &mcasp->context; - u32 reg; - int i; - - context->pm_state = pm_runtime_active(mcasp->dev); - if (!context->pm_state) - pm_runtime_get_sync(mcasp->dev); - - for (i = 0; i < ARRAY_SIZE(context_regs); i++) - context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]); - - if (mcasp->txnumevt) { - reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; - context->afifo_regs[0] = mcasp_get_reg(mcasp, reg); - } - if (mcasp->rxnumevt) { - reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; - context->afifo_regs[1] = mcasp_get_reg(mcasp, reg); - } - - for (i = 0; i < mcasp->num_serializer; i++) - context->xrsr_regs[i] = mcasp_get_reg(mcasp, - DAVINCI_MCASP_XRSRCTL_REG(i)); - - pm_runtime_put_sync(mcasp->dev); - - return 0; -} - -static int davinci_mcasp_resume(struct snd_soc_dai *dai) -{ - struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); - struct davinci_mcasp_context *context = &mcasp->context; - u32 reg; - int i; - - pm_runtime_get_sync(mcasp->dev); - - for (i = 0; i < ARRAY_SIZE(context_regs); i++) - mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]); - - if (mcasp->txnumevt) { - reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET; - mcasp_set_reg(mcasp, reg, context->afifo_regs[0]); - } - if (mcasp->rxnumevt) { - reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET; - mcasp_set_reg(mcasp, reg, context->afifo_regs[1]); - } - - for (i = 0; i < mcasp->num_serializer; i++) - mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), - context->xrsr_regs[i]); - - if (!context->pm_state) - pm_runtime_put_sync(mcasp->dev); - - return 0; -} -#else -#define davinci_mcasp_suspend NULL -#define davinci_mcasp_resume NULL -#endif - -#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_192000 - -#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ - SNDRV_PCM_FMTBIT_U8 | \ - SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_U16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_U24_LE | \ - SNDRV_PCM_FMTBIT_S24_3LE | \ - SNDRV_PCM_FMTBIT_U24_3LE | \ - SNDRV_PCM_FMTBIT_S32_LE | \ - SNDRV_PCM_FMTBIT_U32_LE) - -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 = { - .channels_min = 1, - .channels_max = 32 * 16, - .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, - }, - .capture = { - .channels_min = 1, - .channels_max = 32 * 16, - .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, - }, - .ops = &davinci_mcasp_dai_ops, - - .symmetric_samplebits = 1, - .symmetric_rates = 1, - }, - { - .name = "davinci-mcasp.1", - .probe = davinci_mcasp_dai_probe, - .playback = { - .channels_min = 1, - .channels_max = 384, - .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, - }, - .ops = &davinci_mcasp_dai_ops, - }, - -}; - -static const struct snd_soc_component_driver davinci_mcasp_component = { - .name = "davinci-mcasp", -}; - -/* Some HW specific values and defaults. The rest is filled in from DT. */ -static struct davinci_mcasp_pdata dm646x_mcasp_pdata = { - .tx_dma_offset = 0x400, - .rx_dma_offset = 0x400, - .version = MCASP_VERSION_1, -}; - -static struct davinci_mcasp_pdata da830_mcasp_pdata = { - .tx_dma_offset = 0x2000, - .rx_dma_offset = 0x2000, - .version = MCASP_VERSION_2, -}; - -static struct davinci_mcasp_pdata am33xx_mcasp_pdata = { - .tx_dma_offset = 0, - .rx_dma_offset = 0, - .version = MCASP_VERSION_3, -}; - -static struct davinci_mcasp_pdata dra7_mcasp_pdata = { - /* The CFG port offset will be calculated if it is needed */ - .tx_dma_offset = 0, - .rx_dma_offset = 0, - .version = MCASP_VERSION_4, -}; - -static const struct of_device_id mcasp_dt_ids[] = { - { - .compatible = "ti,dm646x-mcasp-audio", - .data = &dm646x_mcasp_pdata, - }, - { - .compatible = "ti,da830-mcasp-audio", - .data = &da830_mcasp_pdata, - }, - { - .compatible = "ti,am33xx-mcasp-audio", - .data = &am33xx_mcasp_pdata, - }, - { - .compatible = "ti,dra7-mcasp-audio", - .data = &dra7_mcasp_pdata, - }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, mcasp_dt_ids); - -static int mcasp_reparent_fck(struct platform_device *pdev) -{ - struct device_node *node = pdev->dev.of_node; - struct clk *gfclk, *parent_clk; - const char *parent_name; - int ret; - - if (!node) - return 0; - - parent_name = of_get_property(node, "fck_parent", NULL); - if (!parent_name) - return 0; - - dev_warn(&pdev->dev, "Update the bindings to use assigned-clocks!\n"); - - gfclk = clk_get(&pdev->dev, "fck"); - if (IS_ERR(gfclk)) { - dev_err(&pdev->dev, "failed to get fck\n"); - return PTR_ERR(gfclk); - } - - parent_clk = clk_get(NULL, parent_name); - if (IS_ERR(parent_clk)) { - dev_err(&pdev->dev, "failed to get parent clock\n"); - ret = PTR_ERR(parent_clk); - goto err1; - } - - ret = clk_set_parent(gfclk, parent_clk); - if (ret) { - dev_err(&pdev->dev, "failed to reparent fck\n"); - goto err2; - } - -err2: - clk_put(parent_clk); -err1: - clk_put(gfclk); - return ret; -} - -static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of( - struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct davinci_mcasp_pdata *pdata = NULL; - const struct of_device_id *match = - of_match_device(mcasp_dt_ids, &pdev->dev); - struct of_phandle_args dma_spec; - - const u32 *of_serial_dir32; - u32 val; - int i, ret = 0; - - if (pdev->dev.platform_data) { - pdata = pdev->dev.platform_data; - pdata->dismod = DISMOD_LOW; - return pdata; - } else if (match) { - pdata = devm_kmemdup(&pdev->dev, match->data, sizeof(*pdata), - GFP_KERNEL); - if (!pdata) { - ret = -ENOMEM; - return pdata; - } - } else { - /* control shouldn't reach here. something is wrong */ - ret = -EINVAL; - goto nodata; - } - - ret = of_property_read_u32(np, "op-mode", &val); - if (ret >= 0) - pdata->op_mode = val; - - ret = of_property_read_u32(np, "tdm-slots", &val); - if (ret >= 0) { - if (val < 2 || val > 32) { - dev_err(&pdev->dev, - "tdm-slots must be in rage [2-32]\n"); - ret = -EINVAL; - goto nodata; - } - - pdata->tdm_slots = val; - } - - of_serial_dir32 = of_get_property(np, "serial-dir", &val); - val /= sizeof(u32); - if (of_serial_dir32) { - u8 *of_serial_dir = devm_kzalloc(&pdev->dev, - (sizeof(*of_serial_dir) * val), - GFP_KERNEL); - if (!of_serial_dir) { - ret = -ENOMEM; - goto nodata; - } - - for (i = 0; i < val; i++) - of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); - - pdata->num_serializer = val; - pdata->serial_dir = of_serial_dir; - } - - ret = of_property_match_string(np, "dma-names", "tx"); - if (ret < 0) - goto nodata; - - ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret, - &dma_spec); - if (ret < 0) - goto nodata; - - pdata->tx_dma_channel = dma_spec.args[0]; - - /* RX is not valid in DIT mode */ - if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE) { - ret = of_property_match_string(np, "dma-names", "rx"); - if (ret < 0) - goto nodata; - - ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret, - &dma_spec); - if (ret < 0) - goto nodata; - - pdata->rx_dma_channel = dma_spec.args[0]; - } - - ret = of_property_read_u32(np, "tx-num-evt", &val); - if (ret >= 0) - pdata->txnumevt = val; - - ret = of_property_read_u32(np, "rx-num-evt", &val); - if (ret >= 0) - pdata->rxnumevt = val; - - ret = of_property_read_u32(np, "sram-size-playback", &val); - if (ret >= 0) - pdata->sram_size_playback = val; - - ret = of_property_read_u32(np, "sram-size-capture", &val); - if (ret >= 0) - pdata->sram_size_capture = val; - - ret = of_property_read_u32(np, "dismod", &val); - if (ret >= 0) { - if (val == 0 || val == 2 || val == 3) { - pdata->dismod = DISMOD_VAL(val); - } else { - dev_warn(&pdev->dev, "Invalid dismod value: %u\n", val); - pdata->dismod = DISMOD_LOW; - } - } else { - pdata->dismod = DISMOD_LOW; - } - - return pdata; - -nodata: - if (ret < 0) { - dev_err(&pdev->dev, "Error populating platform data, err %d\n", - ret); - pdata = NULL; - } - return pdata; -} - -enum { - PCM_EDMA, - PCM_SDMA, -}; -static const char *sdma_prefix = "ti,omap"; - -static int davinci_mcasp_get_dma_type(struct davinci_mcasp *mcasp) -{ - struct dma_chan *chan; - const char *tmp; - int ret = PCM_EDMA; - - if (!mcasp->dev->of_node) - return PCM_EDMA; - - tmp = mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data; - chan = dma_request_slave_channel_reason(mcasp->dev, tmp); - if (IS_ERR(chan)) { - if (PTR_ERR(chan) != -EPROBE_DEFER) - dev_err(mcasp->dev, - "Can't verify DMA configuration (%ld)\n", - PTR_ERR(chan)); - return PTR_ERR(chan); - } - if (WARN_ON(!chan->device || !chan->device->dev)) - return -EINVAL; - - if (chan->device->dev->of_node) - ret = of_property_read_string(chan->device->dev->of_node, - "compatible", &tmp); - else - dev_dbg(mcasp->dev, "DMA controller has no of-node\n"); - - dma_release_channel(chan); - if (ret) - return ret; - - dev_dbg(mcasp->dev, "DMA controller compatible = \"%s\"\n", tmp); - if (!strncmp(tmp, sdma_prefix, strlen(sdma_prefix))) - return PCM_SDMA; - - return PCM_EDMA; -} - -static u32 davinci_mcasp_txdma_offset(struct davinci_mcasp_pdata *pdata) -{ - int i; - u32 offset = 0; - - if (pdata->version != MCASP_VERSION_4) - return pdata->tx_dma_offset; - - for (i = 0; i < pdata->num_serializer; i++) { - if (pdata->serial_dir[i] == TX_MODE) { - if (!offset) { - offset = DAVINCI_MCASP_TXBUF_REG(i); - } else { - pr_err("%s: Only one serializer allowed!\n", - __func__); - break; - } - } - } - - return offset; -} - -static u32 davinci_mcasp_rxdma_offset(struct davinci_mcasp_pdata *pdata) -{ - int i; - u32 offset = 0; - - if (pdata->version != MCASP_VERSION_4) - return pdata->rx_dma_offset; - - for (i = 0; i < pdata->num_serializer; i++) { - if (pdata->serial_dir[i] == RX_MODE) { - if (!offset) { - offset = DAVINCI_MCASP_RXBUF_REG(i); - } else { - pr_err("%s: Only one serializer allowed!\n", - __func__); - break; - } - } - } - - return offset; -} - -static int davinci_mcasp_probe(struct platform_device *pdev) -{ - struct snd_dmaengine_dai_dma_data *dma_data; - struct resource *mem, *res, *dat; - struct davinci_mcasp_pdata *pdata; - struct davinci_mcasp *mcasp; - char *irq_name; - int *dma; - int irq; - int ret; - - if (!pdev->dev.platform_data && !pdev->dev.of_node) { - dev_err(&pdev->dev, "No platform data supplied\n"); - return -EINVAL; - } - - mcasp = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcasp), - GFP_KERNEL); - if (!mcasp) - return -ENOMEM; - - pdata = davinci_mcasp_set_pdata_from_of(pdev); - if (!pdata) { - dev_err(&pdev->dev, "no platform data\n"); - return -EINVAL; - } - - mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); - if (!mem) { - dev_warn(mcasp->dev, - "\"mpu\" mem resource not found, using index 0\n"); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -ENODEV; - } - } - - mcasp->base = devm_ioremap_resource(&pdev->dev, mem); - if (IS_ERR(mcasp->base)) - return PTR_ERR(mcasp->base); - - pm_runtime_enable(&pdev->dev); - - mcasp->op_mode = pdata->op_mode; - /* sanity check for tdm slots parameter */ - if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) { - if (pdata->tdm_slots < 2) { - dev_err(&pdev->dev, "invalid tdm slots: %d\n", - pdata->tdm_slots); - mcasp->tdm_slots = 2; - } else if (pdata->tdm_slots > 32) { - dev_err(&pdev->dev, "invalid tdm slots: %d\n", - pdata->tdm_slots); - mcasp->tdm_slots = 32; - } else { - mcasp->tdm_slots = pdata->tdm_slots; - } - } - - mcasp->num_serializer = pdata->num_serializer; -#ifdef CONFIG_PM_SLEEP - mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev, - mcasp->num_serializer, sizeof(u32), - GFP_KERNEL); - if (!mcasp->context.xrsr_regs) { - ret = -ENOMEM; - goto err; - } -#endif - mcasp->serial_dir = pdata->serial_dir; - mcasp->version = pdata->version; - mcasp->txnumevt = pdata->txnumevt; - mcasp->rxnumevt = pdata->rxnumevt; - mcasp->dismod = pdata->dismod; - - mcasp->dev = &pdev->dev; - - irq = platform_get_irq_byname(pdev, "common"); - if (irq >= 0) { - irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_common", - dev_name(&pdev->dev)); - if (!irq_name) { - ret = -ENOMEM; - goto err; - } - ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, - davinci_mcasp_common_irq_handler, - IRQF_ONESHOT | IRQF_SHARED, - irq_name, mcasp); - if (ret) { - dev_err(&pdev->dev, "common IRQ request failed\n"); - goto err; - } - - mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN; - mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN; - } - - irq = platform_get_irq_byname(pdev, "rx"); - if (irq >= 0) { - irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_rx", - dev_name(&pdev->dev)); - if (!irq_name) { - ret = -ENOMEM; - goto err; - } - ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, - davinci_mcasp_rx_irq_handler, - IRQF_ONESHOT, irq_name, mcasp); - if (ret) { - dev_err(&pdev->dev, "RX IRQ request failed\n"); - goto err; - } - - mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN; - } - - irq = platform_get_irq_byname(pdev, "tx"); - if (irq >= 0) { - irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_tx", - dev_name(&pdev->dev)); - if (!irq_name) { - ret = -ENOMEM; - goto err; - } - ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, - davinci_mcasp_tx_irq_handler, - IRQF_ONESHOT, irq_name, mcasp); - if (ret) { - dev_err(&pdev->dev, "TX IRQ request failed\n"); - goto err; - } - - mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN; - } - - dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat"); - if (dat) - mcasp->dat_port = true; - - dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; - if (dat) - dma_data->addr = dat->start; - else - dma_data->addr = mem->start + davinci_mcasp_txdma_offset(pdata); - - dma = &mcasp->dma_request[SNDRV_PCM_STREAM_PLAYBACK]; - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (res) - *dma = res->start; - else - *dma = pdata->tx_dma_channel; - - /* dmaengine filter data for DT and non-DT boot */ - if (pdev->dev.of_node) - dma_data->filter_data = "tx"; - else - dma_data->filter_data = dma; - - /* RX is not valid in DIT mode */ - if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) { - dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; - if (dat) - dma_data->addr = dat->start; - else - dma_data->addr = - mem->start + davinci_mcasp_rxdma_offset(pdata); - - dma = &mcasp->dma_request[SNDRV_PCM_STREAM_CAPTURE]; - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (res) - *dma = res->start; - else - *dma = pdata->rx_dma_channel; - - /* dmaengine filter data for DT and non-DT boot */ - if (pdev->dev.of_node) - dma_data->filter_data = "rx"; - else - dma_data->filter_data = dma; - } - - if (mcasp->version < MCASP_VERSION_3) { - mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE; - /* dma_params->dma_addr is pointing to the data port address */ - mcasp->dat_port = true; - } else { - mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE; - } - - /* Allocate memory for long enough list for all possible - * scenarios. Maximum number tdm slots is 32 and there cannot - * be more serializers than given in the configuration. The - * serializer directions could be taken into account, but it - * would make code much more complex and save only couple of - * bytes. - */ - mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list = - devm_kcalloc(mcasp->dev, - 32 + mcasp->num_serializer - 1, - sizeof(unsigned int), - GFP_KERNEL); - - mcasp->chconstr[SNDRV_PCM_STREAM_CAPTURE].list = - devm_kcalloc(mcasp->dev, - 32 + mcasp->num_serializer - 1, - sizeof(unsigned int), - GFP_KERNEL); - - if (!mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list || - !mcasp->chconstr[SNDRV_PCM_STREAM_CAPTURE].list) { - ret = -ENOMEM; - goto err; - } - - ret = davinci_mcasp_set_ch_constraints(mcasp); - if (ret) - goto err; - - dev_set_drvdata(&pdev->dev, mcasp); - - mcasp_reparent_fck(pdev); - - ret = devm_snd_soc_register_component(&pdev->dev, - &davinci_mcasp_component, - &davinci_mcasp_dai[pdata->op_mode], 1); - - if (ret != 0) - goto err; - - ret = davinci_mcasp_get_dma_type(mcasp); - switch (ret) { - case PCM_EDMA: -#if IS_BUILTIN(CONFIG_SND_EDMA_SOC) || \ - (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ - IS_MODULE(CONFIG_SND_EDMA_SOC)) - ret = edma_pcm_platform_register(&pdev->dev); -#else - dev_err(&pdev->dev, "Missing SND_EDMA_SOC\n"); - ret = -EINVAL; - goto err; -#endif - break; - case PCM_SDMA: -#if IS_BUILTIN(CONFIG_SND_SDMA_SOC) || \ - (IS_MODULE(CONFIG_SND_DAVINCI_SOC_MCASP) && \ - IS_MODULE(CONFIG_SND_SDMA_SOC)) - ret = sdma_pcm_platform_register(&pdev->dev, NULL, NULL); -#else - dev_err(&pdev->dev, "Missing SND_SDMA_SOC\n"); - ret = -EINVAL; - goto err; -#endif - break; - default: - dev_err(&pdev->dev, "No DMA controller found (%d)\n", ret); - case -EPROBE_DEFER: - goto err; - break; - } - - if (ret) { - dev_err(&pdev->dev, "register PCM failed: %d\n", ret); - goto err; - } - - return 0; - -err: - pm_runtime_disable(&pdev->dev); - return ret; -} - -static int davinci_mcasp_remove(struct platform_device *pdev) -{ - pm_runtime_disable(&pdev->dev); - - return 0; -} - -static struct platform_driver davinci_mcasp_driver = { - .probe = davinci_mcasp_probe, - .remove = davinci_mcasp_remove, - .driver = { - .name = "davinci-mcasp", - .of_match_table = mcasp_dt_ids, - }, -}; - -module_platform_driver(davinci_mcasp_driver); - -MODULE_AUTHOR("Steve Chen"); -MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h deleted file mode 100644 index 5e4060d8fe56..000000000000 --- a/sound/soc/davinci/davinci-mcasp.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * ALSA SoC McASP Audio Layer for TI DAVINCI processor - * - * MCASP related definitions - * - * Author: Nirmal Pandey <n-pandey@ti.com>, - * Suresh Rajashekara <suresh.r@ti.com> - * Steve Chen <schen@.mvista.com> - * - * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com> - * Copyright: (C) 2009 Texas Instruments, India - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef DAVINCI_MCASP_H -#define DAVINCI_MCASP_H - -/* - * McASP register definitions - */ -#define DAVINCI_MCASP_PID_REG 0x00 -#define DAVINCI_MCASP_PWREMUMGT_REG 0x04 - -#define DAVINCI_MCASP_PFUNC_REG 0x10 -#define DAVINCI_MCASP_PDIR_REG 0x14 -#define DAVINCI_MCASP_PDOUT_REG 0x18 -#define DAVINCI_MCASP_PDSET_REG 0x1c - -#define DAVINCI_MCASP_PDCLR_REG 0x20 - -#define DAVINCI_MCASP_TLGC_REG 0x30 -#define DAVINCI_MCASP_TLMR_REG 0x34 - -#define DAVINCI_MCASP_GBLCTL_REG 0x44 -#define DAVINCI_MCASP_AMUTE_REG 0x48 -#define DAVINCI_MCASP_LBCTL_REG 0x4c - -#define DAVINCI_MCASP_TXDITCTL_REG 0x50 - -#define DAVINCI_MCASP_GBLCTLR_REG 0x60 -#define DAVINCI_MCASP_RXMASK_REG 0x64 -#define DAVINCI_MCASP_RXFMT_REG 0x68 -#define DAVINCI_MCASP_RXFMCTL_REG 0x6c - -#define DAVINCI_MCASP_ACLKRCTL_REG 0x70 -#define DAVINCI_MCASP_AHCLKRCTL_REG 0x74 -#define DAVINCI_MCASP_RXTDM_REG 0x78 -#define DAVINCI_MCASP_EVTCTLR_REG 0x7c - -#define DAVINCI_MCASP_RXSTAT_REG 0x80 -#define DAVINCI_MCASP_RXTDMSLOT_REG 0x84 -#define DAVINCI_MCASP_RXCLKCHK_REG 0x88 -#define DAVINCI_MCASP_REVTCTL_REG 0x8c - -#define DAVINCI_MCASP_GBLCTLX_REG 0xa0 -#define DAVINCI_MCASP_TXMASK_REG 0xa4 -#define DAVINCI_MCASP_TXFMT_REG 0xa8 -#define DAVINCI_MCASP_TXFMCTL_REG 0xac - -#define DAVINCI_MCASP_ACLKXCTL_REG 0xb0 -#define DAVINCI_MCASP_AHCLKXCTL_REG 0xb4 -#define DAVINCI_MCASP_TXTDM_REG 0xb8 -#define DAVINCI_MCASP_EVTCTLX_REG 0xbc - -#define DAVINCI_MCASP_TXSTAT_REG 0xc0 -#define DAVINCI_MCASP_TXTDMSLOT_REG 0xc4 -#define DAVINCI_MCASP_TXCLKCHK_REG 0xc8 -#define DAVINCI_MCASP_XEVTCTL_REG 0xcc - -/* Left(even TDM Slot) Channel Status Register File */ -#define DAVINCI_MCASP_DITCSRA_REG 0x100 -/* Right(odd TDM slot) Channel Status Register File */ -#define DAVINCI_MCASP_DITCSRB_REG 0x118 -/* Left(even TDM slot) User Data Register File */ -#define DAVINCI_MCASP_DITUDRA_REG 0x130 -/* Right(odd TDM Slot) User Data Register File */ -#define DAVINCI_MCASP_DITUDRB_REG 0x148 - -/* Serializer n Control Register */ -#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180 -#define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \ - (n << 2)) - -/* Transmit Buffer for Serializer n */ -#define DAVINCI_MCASP_TXBUF_REG(n) (0x200 + (n << 2)) -/* Receive Buffer for Serializer n */ -#define DAVINCI_MCASP_RXBUF_REG(n) (0x280 + (n << 2)) - -/* McASP FIFO Registers */ -#define DAVINCI_MCASP_V2_AFIFO_BASE (0x1010) -#define DAVINCI_MCASP_V3_AFIFO_BASE (0x1000) - -/* FIFO register offsets from AFIFO base */ -#define MCASP_WFIFOCTL_OFFSET (0x0) -#define MCASP_WFIFOSTS_OFFSET (0x4) -#define MCASP_RFIFOCTL_OFFSET (0x8) -#define MCASP_RFIFOSTS_OFFSET (0xc) - -/* - * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management - * Register Bits - */ -#define MCASP_FREE BIT(0) -#define MCASP_SOFT BIT(1) - -/* - * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits - * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits - * DAVINCI_MCASP_PDOUT_REG - Pin output in GPIO mode - * DAVINCI_MCASP_PDSET_REG - Pin input in GPIO mode - */ -#define PIN_BIT_AXR(n) (n) -#define PIN_BIT_AMUTE 25 -#define PIN_BIT_ACLKX 26 -#define PIN_BIT_AHCLKX 27 -#define PIN_BIT_AFSX 28 -#define PIN_BIT_ACLKR 29 -#define PIN_BIT_AHCLKR 30 -#define PIN_BIT_AFSR 31 - -/* - * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits - */ -#define DITEN BIT(0) /* Transmit DIT mode enable/disable */ -#define VA BIT(2) -#define VB BIT(3) - -/* - * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits - */ -#define TXROT(val) (val) -#define TXSEL BIT(3) -#define TXSSZ(val) (val<<4) -#define TXPBIT(val) (val<<8) -#define TXPAD(val) (val<<13) -#define TXORD BIT(15) -#define FSXDLY(val) (val<<16) - -/* - * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits - */ -#define RXROT(val) (val) -#define RXSEL BIT(3) -#define RXSSZ(val) (val<<4) -#define RXPBIT(val) (val<<8) -#define RXPAD(val) (val<<13) -#define RXORD BIT(15) -#define FSRDLY(val) (val<<16) - -/* - * DAVINCI_MCASP_TXFMCTL_REG - Transmit Frame Control Register Bits - */ -#define FSXPOL BIT(0) -#define AFSXE BIT(1) -#define FSXDUR BIT(4) -#define FSXMOD(val) (val<<7) - -/* - * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits - */ -#define FSRPOL BIT(0) -#define AFSRE BIT(1) -#define FSRDUR BIT(4) -#define FSRMOD(val) (val<<7) - -/* - * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits - */ -#define ACLKXDIV(val) (val) -#define ACLKXE BIT(5) -#define TX_ASYNC BIT(6) -#define ACLKXPOL BIT(7) -#define ACLKXDIV_MASK 0x1f - -/* - * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits - */ -#define ACLKRDIV(val) (val) -#define ACLKRE BIT(5) -#define RX_ASYNC BIT(6) -#define ACLKRPOL BIT(7) -#define ACLKRDIV_MASK 0x1f - -/* - * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control - * Register Bits - */ -#define AHCLKXDIV(val) (val) -#define AHCLKXPOL BIT(14) -#define AHCLKXE BIT(15) -#define AHCLKXDIV_MASK 0xfff - -/* - * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control - * Register Bits - */ -#define AHCLKRDIV(val) (val) -#define AHCLKRPOL BIT(14) -#define AHCLKRE BIT(15) -#define AHCLKRDIV_MASK 0xfff - -/* - * DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits - */ -#define MODE(val) (val) -#define DISMOD_3STATE (0x0) -#define DISMOD_LOW (0x2 << 2) -#define DISMOD_HIGH (0x3 << 2) -#define DISMOD_VAL(x) ((x) << 2) -#define DISMOD_MASK DISMOD_HIGH -#define TXSTATE BIT(4) -#define RXSTATE BIT(5) -#define SRMOD_MASK 3 -#define SRMOD_INACTIVE 0 - -/* - * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits - */ -#define LBEN BIT(0) -#define LBORD BIT(1) -#define LBGENMODE(val) (val<<2) - -/* - * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration - */ -#define TXTDMS(n) (1<<n) - -/* - * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration - */ -#define RXTDMS(n) (1<<n) - -/* - * DAVINCI_MCASP_GBLCTL_REG - Global Control Register Bits - */ -#define RXCLKRST BIT(0) /* Receiver Clock Divider Reset */ -#define RXHCLKRST BIT(1) /* Receiver High Frequency Clock Divider */ -#define RXSERCLR BIT(2) /* Receiver Serializer Clear */ -#define RXSMRST BIT(3) /* Receiver State Machine Reset */ -#define RXFSRST BIT(4) /* Frame Sync Generator Reset */ -#define TXCLKRST BIT(8) /* Transmitter Clock Divider Reset */ -#define TXHCLKRST BIT(9) /* Transmitter High Frequency Clock Divider*/ -#define TXSERCLR BIT(10) /* Transmit Serializer Clear */ -#define TXSMRST BIT(11) /* Transmitter State Machine Reset */ -#define TXFSRST BIT(12) /* Frame Sync Generator Reset */ - -/* - * DAVINCI_MCASP_TXSTAT_REG - Transmitter Status Register Bits - * DAVINCI_MCASP_RXSTAT_REG - Receiver Status Register Bits - */ -#define XRERR BIT(8) /* Transmit/Receive error */ -#define XRDATA BIT(5) /* Transmit/Receive data ready */ - -/* - * DAVINCI_MCASP_AMUTE_REG - Mute Control Register Bits - */ -#define MUTENA(val) (val) -#define MUTEINPOL BIT(2) -#define MUTEINENA BIT(3) -#define MUTEIN BIT(4) -#define MUTER BIT(5) -#define MUTEX BIT(6) -#define MUTEFSR BIT(7) -#define MUTEFSX BIT(8) -#define MUTEBADCLKR BIT(9) -#define MUTEBADCLKX BIT(10) -#define MUTERXDMAERR BIT(11) -#define MUTETXDMAERR BIT(12) - -/* - * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits - */ -#define RXDATADMADIS BIT(0) - -/* - * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits - */ -#define TXDATADMADIS BIT(0) - -/* - * DAVINCI_MCASP_EVTCTLR_REG - Receiver Interrupt Control Register Bits - */ -#define ROVRN BIT(0) - -/* - * DAVINCI_MCASP_EVTCTLX_REG - Transmitter Interrupt Control Register Bits - */ -#define XUNDRN BIT(0) - -/* - * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits - */ -#define FIFO_ENABLE BIT(16) -#define NUMEVT_MASK (0xFF << 8) -#define NUMEVT(x) (((x) & 0xFF) << 8) -#define NUMDMA_MASK (0xFF) - -/* clock divider IDs */ -#define MCASP_CLKDIV_AUXCLK 0 /* HCLK divider from AUXCLK */ -#define MCASP_CLKDIV_BCLK 1 /* BCLK divider from HCLK */ -#define MCASP_CLKDIV_BCLK_FS_RATIO 2 /* to set BCLK FS ration */ - -#endif /* DAVINCI_MCASP_H */ diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c deleted file mode 100644 index 5415b72393fa..000000000000 --- a/sound/soc/davinci/davinci-vcif.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * ALSA SoC Voice Codec Interface for TI DAVINCI processor - * - * Copyright (C) 2010 Texas Instruments. - * - * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/mfd/davinci_voicecodec.h> - -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/initval.h> -#include <sound/soc.h> -#include <sound/dmaengine_pcm.h> - -#include "edma-pcm.h" -#include "davinci-i2s.h" - -#define MOD_REG_BIT(val, mask, set) do { \ - if (set) { \ - val |= mask; \ - } else { \ - val &= ~mask; \ - } \ -} while (0) - -struct davinci_vcif_dev { - struct davinci_vc *davinci_vc; - struct snd_dmaengine_dai_dma_data dma_data[2]; - int dma_request[2]; -}; - -static void davinci_vcif_start(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct davinci_vcif_dev *davinci_vcif_dev = - snd_soc_dai_get_drvdata(rtd->cpu_dai); - struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; - u32 w; - - /* Start the sample generator and enable transmitter/receiver */ - w = readl(davinci_vc->base + DAVINCI_VC_CTRL); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0); - else - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0); - - writel(w, davinci_vc->base + DAVINCI_VC_CTRL); -} - -static void davinci_vcif_stop(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct davinci_vcif_dev *davinci_vcif_dev = - snd_soc_dai_get_drvdata(rtd->cpu_dai); - struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; - u32 w; - - /* Reset transmitter/receiver and sample rate/frame sync generators */ - w = readl(davinci_vc->base + DAVINCI_VC_CTRL); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1); - else - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1); - - writel(w, davinci_vc->base + DAVINCI_VC_CTRL); -} - -static int davinci_vcif_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(dai); - struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; - u32 w; - - /* Restart the codec before setup */ - davinci_vcif_stop(substream); - davinci_vcif_start(substream); - - /* General line settings */ - writel(DAVINCI_VC_CTRL_MASK, davinci_vc->base + DAVINCI_VC_CTRL); - - writel(DAVINCI_VC_INT_MASK, davinci_vc->base + DAVINCI_VC_INTCLR); - - writel(DAVINCI_VC_INT_MASK, davinci_vc->base + DAVINCI_VC_INTEN); - - w = readl(davinci_vc->base + DAVINCI_VC_CTRL); - - /* Determine xfer data type */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_U8: - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 | - DAVINCI_VC_CTRL_RD_UNSIGNED | - DAVINCI_VC_CTRL_WD_BITS_8 | - DAVINCI_VC_CTRL_WD_UNSIGNED, 1); - break; - case SNDRV_PCM_FORMAT_S8: - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 | - DAVINCI_VC_CTRL_WD_BITS_8, 1); - - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_UNSIGNED | - DAVINCI_VC_CTRL_WD_UNSIGNED, 0); - break; - case SNDRV_PCM_FORMAT_S16_LE: - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 | - DAVINCI_VC_CTRL_RD_UNSIGNED | - DAVINCI_VC_CTRL_WD_BITS_8 | - DAVINCI_VC_CTRL_WD_UNSIGNED, 0); - break; - default: - printk(KERN_WARNING "davinci-vcif: unsupported PCM format"); - return -EINVAL; - } - - writel(w, davinci_vc->base + DAVINCI_VC_CTRL); - - return 0; -} - -static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - davinci_vcif_start(substream); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_vcif_stop(substream); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -#define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000 - -static const struct snd_soc_dai_ops davinci_vcif_dai_ops = { - .trigger = davinci_vcif_trigger, - .hw_params = davinci_vcif_hw_params, -}; - -static int davinci_vcif_dai_probe(struct snd_soc_dai *dai) -{ - struct davinci_vcif_dev *dev = snd_soc_dai_get_drvdata(dai); - - dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; - dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; - - return 0; -} - -static struct snd_soc_dai_driver davinci_vcif_dai = { - .probe = davinci_vcif_dai_probe, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = DAVINCI_VCIF_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = DAVINCI_VCIF_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &davinci_vcif_dai_ops, - -}; - -static const struct snd_soc_component_driver davinci_vcif_component = { - .name = "davinci-vcif", -}; - -static int davinci_vcif_probe(struct platform_device *pdev) -{ - struct davinci_vc *davinci_vc = pdev->dev.platform_data; - struct davinci_vcif_dev *davinci_vcif_dev; - int ret; - - davinci_vcif_dev = devm_kzalloc(&pdev->dev, - sizeof(struct davinci_vcif_dev), - GFP_KERNEL); - if (!davinci_vcif_dev) - return -ENOMEM; - - /* DMA tx params */ - davinci_vcif_dev->davinci_vc = davinci_vc; - davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = - &davinci_vc->davinci_vcif.dma_tx_channel; - davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = - davinci_vc->davinci_vcif.dma_tx_addr; - - /* DMA rx params */ - davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = - &davinci_vc->davinci_vcif.dma_rx_channel; - davinci_vcif_dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = - davinci_vc->davinci_vcif.dma_rx_addr; - - dev_set_drvdata(&pdev->dev, davinci_vcif_dev); - - ret = devm_snd_soc_register_component(&pdev->dev, - &davinci_vcif_component, - &davinci_vcif_dai, 1); - if (ret != 0) { - dev_err(&pdev->dev, "could not register dai\n"); - return ret; - } - - ret = edma_pcm_platform_register(&pdev->dev); - if (ret) { - dev_err(&pdev->dev, "register PCM failed: %d\n", ret); - return ret; - } - - return 0; -} - -static struct platform_driver davinci_vcif_driver = { - .probe = davinci_vcif_probe, - .driver = { - .name = "davinci-vcif", - }, -}; - -module_platform_driver(davinci_vcif_driver); - -MODULE_AUTHOR("Miguel Aguilar"); -MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC Voice Codec Interface"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/davinci/edma-pcm.c b/sound/soc/davinci/edma-pcm.c deleted file mode 100644 index 59e588abe54b..000000000000 --- a/sound/soc/davinci/edma-pcm.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * edma-pcm.c - eDMA PCM driver using dmaengine for AM3xxx, AM4xxx - * - * Copyright (C) 2014 Texas Instruments, Inc. - * - * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> - * - * Based on: sound/soc/tegra/tegra_pcm.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include <linux/module.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h> -#include <sound/dmaengine_pcm.h> -#include <linux/edma.h> - -#include "edma-pcm.h" - -static const struct snd_pcm_hardware edma_pcm_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP | - SNDRV_PCM_INFO_INTERLEAVED, - .buffer_bytes_max = 128 * 1024, - .period_bytes_min = 32, - .period_bytes_max = 64 * 1024, - .periods_min = 2, - .periods_max = 19, /* Limit by edma dmaengine driver */ -}; - -static const struct snd_dmaengine_pcm_config edma_dmaengine_pcm_config = { - .pcm_hardware = &edma_pcm_hardware, - .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, - .compat_filter_fn = edma_filter_fn, - .prealloc_buffer_size = 128 * 1024, -}; - -int edma_pcm_platform_register(struct device *dev) -{ - return devm_snd_dmaengine_pcm_register(dev, &edma_dmaengine_pcm_config, - SND_DMAENGINE_PCM_FLAG_COMPAT); -} -EXPORT_SYMBOL_GPL(edma_pcm_platform_register); - -MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); -MODULE_DESCRIPTION("eDMA PCM ASoC platform driver"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/davinci/edma-pcm.h b/sound/soc/davinci/edma-pcm.h deleted file mode 100644 index b0957744851c..000000000000 --- a/sound/soc/davinci/edma-pcm.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * edma-pcm.h - eDMA PCM driver using dmaengine for AM3xxx, AM4xxx - * - * Copyright (C) 2014 Texas Instruments, Inc. - * - * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> - * - * Based on: sound/soc/tegra/tegra_pcm.h - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#ifndef __EDMA_PCM_H__ -#define __EDMA_PCM_H__ - -#if IS_ENABLED(CONFIG_SND_EDMA_SOC) -int edma_pcm_platform_register(struct device *dev); -#else -static inline int edma_pcm_platform_register(struct device *dev) -{ - return 0; -} -#endif /* CONFIG_SND_EDMA_SOC */ - -#endif /* __EDMA_PCM_H__ */ |