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

腳位

BBGWPCM5102A
P9.32(SPI1_SCLK, MCASP0_ACLKX)BCK
P9.29(SPI1_D0, MCASP0_FSX)LRCK
P9.30(SPI1_D1, MCASP0_AXR0)DIN



menuconfig


dmesg


完成


返回上一頁