This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TAS2552 imx6 i2s no audio out.

Other Parts Discussed in Thread: TAS2552

Hey guys;

 

I am trying to bring up a board with two audio codecs on it.  

 

Chip 1: SGTL5000 in master mode connected to which works AUD3 and ssi1, this works fine.

Chip 2: Texas Instruments TAS2552 ClassD amplifier connected to AUD4 and SSI2 that we want to use in slave mode.

 

Here is the datasheet to the TAS2552: http://www.ti.com/lit/ds/symlink/tas2552.pdf 

 

I understand we need our own imx6 specific codec driver for the TAS2552, and as such I have created one, it will be attached at the bottom.

 

Here is our issue:

 

Running speaker-test I am able to confirm that MCLK, WCLK (TXFS), BCLK (TXC), and DIN (TXD), are all being produced, but DOUT (RXD) is not being produced and therefor I am not able to get static.

 

I have poured over all the registers and am able to determine that they are all supposedly setup correctly, so perhaps this is a driver issue?  I am not sure, and that is why I am asking for help from the experts.  

 

Below is the schematic for this particular section:

As you can see, mclk0 is tied into mclk1, the sgtl is using mclk0 and it works perfectly fine with speaker-test.

 

Below is what I am using for my DTSI file:

#ifdef SGTL5000
sound-sgtl5500 {
   compatible     = "fsl,imx-audio-sgtl5000";
   model             = "imx-sgtl5500";
   ssi-controller  = <&ssi1>;
   audio-codec  = <&sgtl5000>;
   audio-routing =
      "MIC_IN", "Mic Jack",
      "LINE_IN", "Line In Jack",
      "Headphone Jack", "HP_OUT"; 
   mux-int-port = <1>;
   mux-ext-port = <3>;
};
#endif

 

#ifdef TAS2552
sound-tas2552 {
   compatible = "fsl,imx-audio-tas2552";
   model = "ti-tas2550";
   ssi-controller = <&ssi2>;
   audio-codec = <&tas2552>;
   audio-routing =
      "In", "DAC",
      "Ext Spk", "OUT"; 
   mux-int-port = <2>;
   mux-ext-port = <4>;
};
#endif

 

 

#ifdef SGTL5000
sgtl5000: sgtl5000@0a {
   compatible =       "fsl,sgtl5000";
   reg =                    <0x0a>;
   clocks =               <&clksIMX6QDL_CLK_CKO>; 
   VDDA-supply =   <&sw4_reg>;
   VDDIO-supply = <&vgen4_reg>;
};

#endif

 

#ifdef TAS2552
tas2552: tas2552@41 {
   compatible =    "ti,tas2552";
   reg =                  <0x41>;
   avdd-supply =   <&vgen4_reg>;
   iovdd-supply =  <&sw4_reg>;
   vbat-supply =    <&reg_4p2v>;
   clocks =            <&clks IMX6QDL_CLK_CKO>;
   enable-gpio =   <&gpio1 11 GPIO_ACTIVE_HIGH>;
};

#endif

 

&ssi1 {
   status = "okay";
};

 

&ssi2 {
   fsl,mode = "i2s-master";
   status = "okay";
};

 

&audmux {
   pinctrl-names = "default";
   pinctrl-0 = <&pinctrl_audmux>;
   status = "okay";
};

 

 

pinctrl_audmux: audmuxgrp1 {
   fsl,pins = <
   #ifdef SGTL5000
      MX6QDL_PAD_CSI0_DAT4__AUD3_TXC    0x130b0
      MX6QDL_PAD_CSI0_DAT5__AUD3_TXD    0x110b0
      MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS  0x130b0
      MX6QDL_PAD_CSI0_DAT7__AUD3_RXD    0x130b0
   #endif

 

   #ifdef TAS2552
      MX6QDL_PAD_SD2_DAT0__AUD4_RXD    0x130b0
      MX6QDL_PAD_SD2_DAT1__AUD4_TXFS  0x130b0
      MX6QDL_PAD_SD2_DAT2__AUD4_TXD    0x110b0
      MX6QDL_PAD_SD2_DAT3__AUD4_TXC    0x130b0
   #endif
   >;
};

Here is my dmesg output:

[ 3.685819] Adding route DAC IN -> direct -> DAC
[ 3.689151] Adding route DAC -> Digital -> Input selection
[ 3.693345] Adding route IN -> Analog -> Input selection
[ 3.697415] Adding route Input selection -> direct -> ClassD
[ 3.701779] Adding route ClassD -> direct -> OUT
[ 3.705141] Adding route PLL -> direct -> ClassD
[ 3.708502] ASoC: probe ti-tas2550 dai link 0 late -2
[ 3.712259] ASoC: probe ti-tas2550 dai link 0 late -1
[ 3.716086] ASoC: probe ti-tas2550 dai link 0 late 0
[ 3.719756] ASoC: probe ti-tas2550 dai link 0 late 1
[ 3.723422] ASoC: probe ti-tas2550 dai link 0 late 2
[ 3.750046] imx-tas2552 sound-tas2552: tas2552-amplifier <-> 202c000.ssi mapping ok
[ 3.756505] Adding route OUT -> direct -> Ext Spk
...
[ 3.824546] ALSA device list:
[ 3.826227] #0: ti-tas2550

# speaker-test

speaker-test 1.1.2

Playback device is default
Stream parameters are 48000Hz, S16_LE, 1 channels
Using 16 octaves of pink noise
Rate set to 48000Hz (requested 48000Hz)

 

##### tas2552_hw_params #####

#####  tas2552_setup_pll  #####
Pll_clk == 24576000
pll_clkin == 24000000

 

Buffer size range from 64 to 16384
Period size range from 32 to 8192

Using max buffer size 16384

Periods = 4

 


##### tas2552_prepare #####


##### tas2552_mute #####
Register 0x1 set to 0x10
Register 0x2 set to 0xee
Register 0x3 set to 0x5d
Register 0x4 set to 0x0
Register 0x5 set to 0x0
Register 0x6 set to 0x0
Register 0x7 set to 0xc8
Register 0x8 set to 0x20
Register 0x9 set to 0x0
Register 0xa set to 0x0
Register 0xb set to 0x8f
Register 0xc set to 0x80
Register 0xe set to 0x28
Register 0xf set to 0x4
Register 0x10 set to 0x0
Register 0x11 set to 0x1
Register 0x12 set to 0x16
Register 0x13 set to 0x40
Register 0x14 set to 0x3
Register 0x16 set to 0x8
Register 0x19 set to 0x0
Register 0x0 set to 0x0
was set period_size = 4096
was set buffer_size = 16384
0 - Front Left
Time per period = 2.657305
0 - Front Left

Still no output from the speaker.

 

Any thoughts?

imx-tas2552.c
/*
 * Copyright 2012 Freescale Semiconductor, Inc.
 * Copyright 2012 Linaro Ltd.
 *
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

#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 <linux/delay.h>
#include "../codecs/tas2552.h"
#include "imx-audmux.h"
#include <dt-bindings/sound/tas2552.h>

#define DAI_NAME_SIZE	32

struct imx_tas2552_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_audmux_config(int slave, int master)
{
	unsigned int ptcr, pdcr;
	slave = slave - 1;
	master = master - 1;

	ptcr = IMX_AUDMUX_V2_PTCR_SYN |
		IMX_AUDMUX_V2_PTCR_TFSDIR |
		IMX_AUDMUX_V2_PTCR_TFSEL(slave) |
		IMX_AUDMUX_V2_PTCR_TCLKDIR |
		IMX_AUDMUX_V2_PTCR_TCSEL(slave);
	pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(slave);
	imx_audmux_v2_configure_port(master, ptcr, pdcr);

	/*
	 * According to RM, RCLKDIR and SYN should not be changed at same time.
	 * So separate to two step for configuring this port.
	 */
	ptcr |= IMX_AUDMUX_V2_PTCR_RFSDIR |
		IMX_AUDMUX_V2_PTCR_RFSEL(slave) |
		IMX_AUDMUX_V2_PTCR_RCLKDIR |
		IMX_AUDMUX_V2_PTCR_RCSEL(slave);
	imx_audmux_v2_configure_port(master, ptcr, pdcr);

	ptcr = IMX_AUDMUX_V2_PTCR_SYN;
	pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(master);
	imx_audmux_v2_configure_port(slave, ptcr, pdcr);

	return 0;
}


static int imx_tas2552_dai_init(struct snd_soc_pcm_runtime *rtd)
{
	struct imx_tas2552_data *data = snd_soc_card_get_drvdata(rtd->card);
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct snd_soc_codec *codec = codec_dai->codec;

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



	ret = snd_soc_dai_set_sysclk(rtd->codec_dai, TAS2552_PLL_CLKIN_MCLK,
		data->clk_frequency, SND_SOC_CLOCK_OUT);
	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_tas2552_dapm_widgets[] = {
	SND_SOC_DAPM_SPK("Ext Spk", NULL),
};

static int imx_tas2552_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct device_node *ssi_np, *codec_np;
	struct platform_device *ssi_pdev;
	struct i2c_client *codec_dev;
	struct imx_tas2552_data *data = NULL;
	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;
	}

	imx_audmux_config(int_port, ext_port);

	ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0);
	codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
	if (!ssi_np || !codec_np) {
		dev_err(&pdev->dev, "phandle missing or invalid\n");
		ret = -EINVAL;
		goto fail;
	}

	ssi_pdev = of_find_device_by_node(ssi_np);
	if (!ssi_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)) {
		printk("Unable to get clock!\n");
		ret = PTR_ERR(data->codec_clk);
		goto fail;
	}

	data->clk_frequency = clk_get_rate(data->codec_clk);
	data->dai.name = "HiFi";
	data->dai.stream_name = "HiFi";
	data->dai.codec_dai_name = "tas2552-amplifier";
	data->dai.codec_of_node = codec_np;
	data->dai.cpu_of_node = ssi_np;
	data->dai.platform_of_node = ssi_np;
	data->dai.init = &imx_tas2552_dai_init;
	data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |  SND_SOC_DAIFMT_CBS_CFS;

	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_tas2552_dapm_widgets;
	data->card.num_dapm_widgets = ARRAY_SIZE(imx_tas2552_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(ssi_np);
	of_node_put(codec_np);

	return 0;

fail:
	if (data && !IS_ERR(data->codec_clk))
		clk_put(data->codec_clk);
	of_node_put(ssi_np);
	of_node_put(codec_np);

	return ret;
}

static int imx_tas2552_remove(struct platform_device *pdev)
{
	struct snd_soc_card *card = platform_get_drvdata(pdev);
	struct imx_tas2552_data *data = snd_soc_card_get_drvdata(card);

	clk_put(data->codec_clk);

	return 0;
}

static const struct of_device_id imx_tas2552_dt_ids[] = {
	{ .compatible = "fsl,imx-audio-tas2552", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_tas2552_dt_ids);

static struct platform_driver imx_tas2552_driver = {
	.driver = {
		.name = "imx-tas2552",
		.pm = &snd_soc_pm_ops,
		.of_match_table = imx_tas2552_dt_ids,
	},
	.probe = imx_tas2552_probe,
	.remove = imx_tas2552_remove,
};
module_platform_driver(imx_tas2552_driver);

MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
MODULE_DESCRIPTION("Freescale i.MX tas2552 ASoC machine driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:imx-tas2552");