AnsweredAssumed Answered

Kernel-3.14.28 posting TLV320AIC23 sound card driver's issue

Question asked by haibo he on Jul 30, 2015
Latest reply on Aug 2, 2015 by igorpadykov

sound/soc/fsl/imx-tlv320aic23.c

#include <linux/module.h>

#include <linux/of.h>

#include <linux/of_platform.h>

#include <linux/i2c.h>

#include <linux/clk.h>

#include <sound/soc.h>

 

#include "../codecs/tlv320aic23.h"

#include "imx-audmux.h"

 

#define DAI_NAME_SIZE 32

struct imx_tlv320aic23_data {

  struct snd_soc_dai_link dai;

  struct snd_soc_card card;

  char codec_dai_name[DAI_NAME_SIZE];

  char platform_name[DAI_NAME_SIZE];

  struct clk *codec_clk;

  unsigned int clk_frequency;

};

 

static int imx_tlv320aic23_dai_init(struct snd_soc_pcm_runtime *rtd)

{

  struct imx_tlv320aic23_data *data = snd_soc_card_get_drvdata(rtd->card);

  struct device *dev = rtd->card->dev;

  int ret;

  ret = snd_soc_dai_set_sysclk(rtd->codec_dai, TLV320AIC23_SYSCLK,

      data->clk_frequency, SND_SOC_CLOCK_IN);

  if (ret) {

  dev_err(dev, "could not set codec driver clock params\n");

  return ret;

  }

  return 0;

}

 

static const struct snd_soc_dapm_widget imx_tlv320aic23_dapm_widgets[] = {

  SND_SOC_DAPM_MIC("Mic Jack", NULL),

  SND_SOC_DAPM_LINE("Line In Jack", NULL),

  SND_SOC_DAPM_HP("Headphone Jack", NULL),

  SND_SOC_DAPM_SPK("Line Out Jack", NULL),

  SND_SOC_DAPM_SPK("Ext Spk", NULL),

};

 

static int imx_tlv320aic23_audmux_config(struct platform_device *pdev)

{

  struct device_node *np = pdev->dev.of_node;

  int int_port, ext_port;

  int ret;

 

  ret = of_property_read_u32(np, "mux-int-port", &int_port);

  if (ret) {

  dev_err(&pdev->dev, "mux-int-port missing or invalid\n");

  return ret;

  }

  ret = of_property_read_u32(np, "mux-ext-port", &ext_port);

  if (ret) {

  dev_err(&pdev->dev, "mux-ext-port missing or invalid\n");

  return ret;

  }

 

  /*

  * The port numbering in the hardware manual starts at 1, while

  * the audmux API expects it starts at 0.

  */

  int_port--;

  ext_port--;

  ret = imx_audmux_v2_configure_port(int_port,

  IMX_AUDMUX_V2_PTCR_SYN |

  IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |

  IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |

  IMX_AUDMUX_V2_PTCR_TFSDIR |

  IMX_AUDMUX_V2_PTCR_TCLKDIR,

  IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port));

  if (ret) {

  dev_err(&pdev->dev, "audmux internal port setup failed\n");

  return ret;

  }

  ret = imx_audmux_v2_configure_port(ext_port,

  IMX_AUDMUX_V2_PTCR_SYN,

  IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));

  if (ret) {

  dev_err(&pdev->dev, "audmux external port setup failed\n");

  return ret;

  }

  return 0;

}

 

static int imx_tlv320aic23_probe(struct platform_device *pdev)

{

  struct device_node *cpu_np, *codec_np;

  struct platform_device *cpu_pdev;

  struct i2c_client *codec_dev;

  struct imx_tlv320aic23_data *data = NULL;

  int ret;

 

  cpu_np = of_parse_phandle(pdev->dev.of_node, "cpu-dai", 0);

  codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);

  if (!cpu_np || !codec_np) {

  dev_err(&pdev->dev, "phandle missing or invalid\n");

  ret = -EINVAL;

  goto fail;

  }

 

  if (strstr(cpu_np->name, "ssi")) {

  ret = imx_tlv320aic23_audmux_config(pdev);

  if (ret)

  goto fail;

  }

 

  cpu_pdev = of_find_device_by_node(cpu_np);

  if (!cpu_pdev) {

  dev_err(&pdev->dev, "failed to find SSI platform device\n");

  ret = -EPROBE_DEFER;

  goto fail;

  }

  codec_dev = of_find_i2c_device_by_node(codec_np);

  if (!codec_dev) {

  dev_err(&pdev->dev, "failed to find codec platform device\n");

  return -EPROBE_DEFER;

  }

 

  data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);

  if (!data) {

  ret = -ENOMEM;

  goto fail;

  }

 

  data->codec_clk = clk_get(&codec_dev->dev, NULL);

  if (IS_ERR(data->codec_clk)) {

  ret = PTR_ERR(data->codec_clk);

  goto fail;

  }

  data->clk_frequency = clk_get_rate(data->codec_clk);

  data->dai.name = "tlv320aic23";

  data->dai.stream_name = "TLV320AIC23";

  data->dai.codec_dai_name = "tlv320aic23-hifi";

  data->dai.codec_of_node = codec_np;

  data->dai.cpu_of_node = cpu_np;

  data->dai.platform_of_node = cpu_np;

  data->dai.init = &imx_tlv320aic23_dai_init;

  data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |

     SND_SOC_DAIFMT_CBM_CFM;

 

  data->card.dev = &pdev->dev;

  ret = snd_soc_of_parse_card_name(&data->card, "model");

  if (ret)

  goto fail;

  ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");

  if (ret)

  goto fail;

  data->card.num_links = 1;

  data->card.owner = THIS_MODULE;

  data->card.dai_link = &data->dai;

  data->card.dapm_widgets = imx_tlv320aic23_dapm_widgets;

  data->card.num_dapm_widgets = ARRAY_SIZE(imx_tlv320aic23_dapm_widgets);

 

  platform_set_drvdata(pdev, &data->card);

  snd_soc_card_set_drvdata(&data->card, data);

 

  ret = devm_snd_soc_register_card(&pdev->dev, &data->card);

  if (ret) {

  dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);

  goto fail;

  }

 

  of_node_put(cpu_np);

  of_node_put(codec_np);

 

  return 0;

 

fail:

  if (data && !IS_ERR(data->codec_clk))

  clk_put(data->codec_clk);

  if (cpu_np)

  of_node_put(cpu_np);

  if (codec_np)

  of_node_put(codec_np);

  return ret;

}

 

static int imx_tlv320aic23_remove(struct platform_device *pdev)

{

  struct snd_soc_card *card = platform_get_drvdata(pdev);

  struct imx_tlv320aic23_data *data = snd_soc_card_get_drvdata(card);

  clk_put(data->codec_clk);

  return 0;

}

 

static const struct of_device_id imx_tlv320aic23_dt_ids[] = {

  { .compatible = "fsl,imx-audio-tlv320aic23", },

  { /* sentinel */ }

};

MODULE_DEVICE_TABLE(of, imx_tlv320aic23_dt_ids);

 

 

static struct platform_driver imx_tlv320aic23_driver = {

  .driver = {

  .name = "imx-tlv320aic23",

  .owner = THIS_MODULE,

  .pm = &snd_soc_pm_ops,

  .of_match_table = imx_tlv320aic23_dt_ids,

  },

  .probe = imx_tlv320aic23_probe,

  .remove = imx_tlv320aic23_remove,

};

module_platform_driver(imx_tlv320aic23_driver);

 

 

MODULE_AUTHOR("Freescale Semiconductor, Inc.");

MODULE_DESCRIPTION("Freescale i.MX TLV320AIC23 ASoC machine driver");

MODULE_LICENSE("GPL v2");

MODULE_ALIAS("platform:imx-tlv320aic23");

 

arch/arm/boot/dts/imx6qdl-sabresd.dtsi

&i2c1 {

  clock-frequency = <100000>;

  pinctrl-names = "default";

  pinctrl-0 = <&pinctrl_i2c1>;

  status = "okay";

 

 

- codec: wm8962@1a {

- compatible = "wlf,wm8962";

+       codec: tlv320aic23@1a {

+             compatible = "fsl,tlv320aic23";

  reg = <0x1a>;

  clocks = <&clks 201>;

  DCVDD-supply = <&reg_audio>;

 

  sound {

- compatible = "fsl,imx6q-sabresd-wm8962",

-   "fsl,imx-audio-wm8962";

- model = "wm8962-audio"; 

+ compatible = "fsl,imx6q-sabresd-tlv320aic23",

+   "fsl,imx-audio-tlv320aic23";

+ model = "tlv320aic23-audio";

  cpu-dai = <&ssi2>;

  audio-codec = <&codec>;

  audio-routing =

- "Headphone Jack", "HPOUTL",

- "Headphone Jack", "HPOUTR"

- "Ext Spk", "SPKOUTL",

- "Ext Spk", "SPKOUTR",

- "MICBIAS", "AMIC",

- "IN3R", "MICBIAS",

- "DMIC", "MICBIAS",

- "DMICDAT", "DMIC"; 

+ "MICIN", "Mic Jack",

+                       "Headphone Jack", "LHPOUT",

+                       "Headphone Jack", "RHPOUT";

  mux-int-port = <2>;

  mux-ext-port = <3>;

  hp-det-gpios = <&gpio1 29 1>;

  mic-det-gpios = <&gpio3 20 1>;

  };

 

  reg_audio: regulator@2 {

  compatible = "regulator-fixed";

  reg = <2>;

- regulator-name = "wm8962-supply";

+ regulator-name = "tlv320aic23-supply";

  gpio = <&gpio4 10 0>;

  enable-active-high;

  };

 

 

issue is:

  Normal playback time of MP3 file is 3 minutes.

  Now playing time is 6 minutes.

  Sound not normal

                                          thanks

Outcomes