AM3358 >> C/C++
移植PCM5102A音效驅動程式
參考資訊:
1. Sitara_Linux_Audio_DAC_Example
arch/arm/boot/dts/am335x-bonegreen-wireless.dts
am33xx_pinmux: pinmux@44e10800 { ... mcasp0_pins: mcasp0_pins { pinctrl-single,pins = < 0x190 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx */ 0x194 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_fsx*/ 0x198 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_axr0 */ >; };
diff
From 1250f7b96688bdc5cdc4bc9def37ba669efeb9c1 Mon Sep 17 00:00:00 2001 From: Josh Elliott <jelliott@ti.com> Date: Fri, 16 May 2014 05:12:56 -0500 Subject: [PATCH] pcm5102a complete --- arch/arm/boot/dts/am335x-bone.dts | 40 +++++++++++++++++++ sound/soc/codecs/Kconfig | 4 ++ sound/soc/codecs/Makefile | 2 + sound/soc/codecs/pcm5102a.c | 80 +++++++++++++++++++++++++++++++++++++ sound/soc/davinci/Kconfig | 8 ++++ sound/soc/davinci/davinci-evm.c | 54 +++++++++++++++++++++++++ 6 files changed, 188 insertions(+) create mode 100644 sound/soc/codecs/pcm5102a.c diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts index 0d63348..6c83e25 100644 --- a/arch/arm/boot/dts/am335x-bone.dts +++ b/arch/arm/boot/dts/am335x-bone.dts @@ -19,3 +19,43 @@ &mmc1 { vmmc-supply = <&ldo3_reg>; }; + +&am33xx_pinmux { + mcasp0_pins: mcasp0_pins { + pinctrl-single,pins = < + 0x190 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx */ + 0x194 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_fsx*/ + 0x198 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_axr0 */ + >; + }; +}; + +&mcasp0 { + pinctrl-names = "default"; + pinctrl-0 = <&mcasp0_pins>; + status = "okay"; + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + /* 16 serializer */ + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 1 0 0 0 + >; + tx-num-evt = <32>; + rx-num-evt = <32>; +}; + +/ { + + pcm5102a: pcm5102a { + compatible = "ti,pcm5102a"; + }; + + sound { + compatible = "ti,pcm5102a-evm-audio"; + ti,model = "TI PCM5102A"; + ti,audio-codec = <&pcm5102a>; + ti,mcasp-controller = <&mcasp0>; + ti,codec-clock-rate = <24000000>; + }; + +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 590cf10..73cd8d0 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -59,6 +59,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM1681 if I2C select SND_SOC_PCM1792A if SPI_MASTER select SND_SOC_PCM3008 + select SND_SOC_PCM5102A select SND_SOC_RT5631 if I2C select SND_SOC_RT5640 if I2C select SND_SOC_SGTL5000 if I2C @@ -312,6 +313,9 @@ config SND_SOC_PCM1792A config SND_SOC_PCM3008 tristate +config SND_SOC_PCM5102A + tristate + config SND_SOC_RT5631 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 23f8042..461050f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -46,6 +46,7 @@ snd-soc-hdmi-codec-objs := hdmi.o snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm1792a-codec-objs := pcm1792a.o snd-soc-pcm3008-objs := pcm3008.o +snd-soc-pcm5102a-objs := pcm5102a.o snd-soc-rt5631-objs := rt5631.o snd-soc-rt5640-objs := rt5640.o snd-soc-sgtl5000-objs := sgtl5000.o @@ -180,6 +181,7 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o +obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c new file mode 100644 index 0000000..9a2059b --- /dev/null +++ b/sound/soc/codecs/pcm5102a.c @@ -0,0 +1,80 @@ +/* + * ALSA SoC PCM5102a driver + * + * Author: Josh Elliott, <jelliott@ti.com> + * Copyright: Copyright: (C) 2014 Texas Instruments + * + * Based on sound/soc/codecs/spdif_transmitter.c by Steve Chen + * + * 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/slab.h> +#include <sound/soc.h> +#include <sound/pcm.h> +#include <sound/initval.h> +#include <linux/of.h> + +#define DRV_NAME "pcm5102a" + +#define RATES SNDRV_PCM_RATE_8000_96000 +#define FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_codec_driver soc_codec_pcm5102a = { + +}; + +static struct snd_soc_dai_driver pcm5102a_dai = { + .name = "pcm5102a-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RATES, + .formats = FORMATS, + }, +}; + +static int pcm5102a_probe(struct platform_device *pdev) +{ + printk("PCM5102a probe...\n"); + + return snd_soc_register_codec(&pdev->dev, &soc_codec_pcm5102a, + &pcm5102a_dai, 1); +} + +static int pcm5102a_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id pcm5102a_dt_ids[] = { + { .compatible = "ti,pcm5102a", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm5102a_dt_ids); +#endif + +static struct platform_driver pcm5102a_driver = { + .probe = pcm5102a_probe, + .remove = pcm5102a_remove, + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(pcm5102a_dt_ids), + }, +}; + +module_platform_driver(pcm5102a_driver); + +MODULE_AUTHOR("Josh Elliott <jelliott@ti.com>"); +MODULE_DESCRIPTION("PCM5102A dummy codec driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index c2153cf..3e11da5 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig @@ -26,6 +26,14 @@ config SND_AM33XX_SOC_EVM AM335X-EVMSK, AM43XX-GP-EVM, and BeagelBone with AudioCape boards have this setup. +config SND_AM33XX_SOC_PCM5102A + tristate "SoC Audio support for PCM5102A on BeagleBoneBlack" + depends on SND_DAVINCI_SOC && SOC_AM33XX + select SND_SOC_PCM5102A + help + Say Y or M if you want to add support for SoC audio on AM33XX + BeagleBoneBlack board using McASP and PCM5102A. + config SND_AM43XX_SOC_EPOS_EVM tristate "SoC Audio for the AM43XX and TLV320AIC3111 based board" depends on SND_DAVINCI_SOC && SOC_AM43XX diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 14f4049..2deafac 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -57,7 +57,9 @@ static int evm_startup(struct snd_pcm_substream *substream) struct snd_soc_card *soc_card = rtd->codec->card; struct clk *mclk = ((struct snd_soc_card_drvdata_davinci *) snd_soc_card_get_drvdata(soc_card))->mclk; + if (mclk) + printk("MCLK: %d", clk_prepare_enable(mclk)); return clk_prepare_enable(mclk); return 0; @@ -93,6 +95,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream, unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) snd_soc_card_get_drvdata(soc_card))->sysclk; + printk("EVM HW PARAMS\n"); + /* set the codec system clock */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT); if (ret < 0) @@ -159,6 +163,36 @@ static int evm_tda998x_hw_params(struct snd_pcm_substream *substream, return ret; } +static int pcm5102a_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 *cpu_dai = rtd->cpu_dai; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_card *soc_card = codec->card; + struct platform_device *pdev = to_platform_device(soc_card->dev); + unsigned int bclk_freq = evm_get_bclk(params); + unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) + snd_soc_card_get_drvdata(soc_card))->sysclk; + int ret; + + ret = snd_soc_dai_set_clkdiv(cpu_dai, 1, sysclk/bclk_freq); + if (ret < 0) { + dev_err(&pdev->dev, "can't set CPU DAI clock divider %d\n", + ret); + return ret; + } + + printk("PCM5102a hw params\n"); + printk("sysclk=%d\n", sysclk); + printk("bclk_freq=%d\n", bclk_freq); + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT); + if (ret < 0) + return ret; + + return ret; +} + static int evm_slave_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -214,6 +248,13 @@ static struct snd_soc_ops dra7xx_ops = { .hw_params = evm_slave_codec_hw_params, }; +static struct snd_soc_ops pcm5102a_ops = { + .startup = evm_startup, + .shutdown = evm_shutdown, + .hw_params = pcm5102a_hw_params, +}; + + /* davinci-evm machine dapm widgets */ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), @@ -584,6 +625,15 @@ static struct snd_soc_card da850_snd_soc_card = { * The structs are used as place holders. They will be completely * filled with data from dt node. */ +static struct snd_soc_dai_link evm_dai_pcm5102a = { + .name = "PCM5102A", + .stream_name = "Playback", + .codec_dai_name = "pcm5102a-hifi", + .ops = &pcm5102a_ops, + .dai_fmt = (SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_IB_NF), +}; + static struct snd_soc_dai_link evm_dai_tlv320aic3x = { .name = "TLV320AIC3X", .stream_name = "AIC3X", @@ -627,6 +677,10 @@ static struct snd_soc_dai_link evm_dai_tlv320aic3111 = { static const struct of_device_id davinci_evm_dt_ids[] = { { + .compatible = "ti,pcm5102a-evm-audio", + .data = &evm_dai_pcm5102a, + }, + { .compatible = "ti,da830-evm-audio", .data = &evm_dai_tlv320aic3x, }, -- 1.7.9.5
腳位
BBGW | PCM5102A |
---|---|
P9.32(SPI1_SCLK, MCASP0_ACLKX) | BCK |
P9.29(SPI1_D0, MCASP0_FSX) | LRCK |
P9.30(SPI1_D1, MCASP0_AXR0) | DIN |
menuconfig
dmesg
完成