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.

AM5708: Linux: McASP5 audio not working

Part Number: AM5708
Other Parts Discussed in Thread: AM5728, DRA722, TSC2007

Hi,

We have developed a custom board with AM5708 processor using ti-processor-sdk-linux-am57xx-evm-05.03.00.07.
We are having McASP5 interface in the board and for MCLK we have connected to H5 ball of AM5708 processor.
Could you help us to make the sound work?

Pinmux in uboot we set
    {GPMC_ADVN_ALE, (M2 | PIN_OUTPUT)}, /* gpmc_advn_ale.clkout2 *//* audio_master_clk */
    {XREF_CLK0, (M4 | PIN_OUTPUT)}, /* xref_clk0.mcasp5_ahclkx */
    {MCASP5_ACLKX, (M0 | PIN_OUTPUT)}, /* mcasp5_aclkx.mcasp5_aclkx */
    {MCASP5_FSX, (M0 | PIN_OUTPUT)}, /* mcasp5_fsx.mcasp5_fsx */
    {MCASP5_AXR0, (M0 | PIN_OUTPUT)}, /* mcasp5_axr0.mcasp5_axr0 */

am571x-idk.dts we add

sound0: sound@0 {
    compatible = "simple-audio-card";
    simple-audio-card,name = "DRA7xx-EVM";
    simple-audio-card,widgets =
        "Headphone", "Headphone Jack",
        "Line", "Line Out",
        "Microphone", "Mic Jack",
        "Line", "Line In";
    simple-audio-card,routing =
        "Headphone Jack", "DAC to AOUT";
    simple-audio-card,format = "i2s";
    simple-audio-card,bitclock-master = <&sound0_master>;
    simple-audio-card,frame-master = <&sound0_master>;
    simple-audio-card,bitclock-inversion;

    sound0_master: simple-audio-card,cpu {
        sound-dai = <&mcasp5>;
        system-clock-frequency = <24576000>;
    };

    simple-audio-card,codec {
        sound-dai = <&audio>;
        clocks = <&clkout2_clk>;
    };
};

&i2c2 {
    status = "okay";
    clock-frequency = <400000>;

    audio: audio-codec@19 {
        #sound-dai-cells = <0>;
        compatible = "akm,ak4432";
        reg = <0x19>;
    };
};

&mcasp5 {
    #sound-dai-cells = <0>;
    assigned-clocks = <&mcasp5_ahclkx_mux>;
    assigned-clock-parents = <&sys_clkin2>;

    status = "okay";

    op-mode = <0>; /* MCASP_IIS_MODE */
    tdm-slots = <2>;
    /* 4 serializers */
    serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
    1 0 0 0
    >;
    tx-num-evt = <32>;
    rx-num-evt = <32>;
};

The kernle log is 

[ 3.614856] [AK4432] ak4432_probe(668)
[ 3.618711] Read PDN pin from device tree
[ 3.646825] ak4432 pdn pin(4294967294) is invalid(642)
[ 3.652035] ak4432 mute pin(4294967294) is invalid(652)
[ 3.657282] [AK4432] ak4432_set_bias_level(494)
[ 3.662065] [AK4432] ak4432_init_reg(604)
[ 3.666385] [AK4432] ak4432_write_register (01, 01)
[ 3.671525] [AK4432] ak4432_init_reg ACKS bit = 1
[ 3.676337] [AK4432] ak4432_init_reg(611)
[ 3.680450] [AK4432] ak4432_probe(691) return 0
[ 3.685182] [AK4432] ak4432_set_dai_sysclk(329)
[ 3.690096] [AK4432] ak4432_set_dai_fmt(344) addr 02H = 06
[ 3.695711] [AK4432] ak4432_set_dai_fmt(371) addr 02H = 07
[ 3.701517] [AK4432] ak4432_write_register (02, 07)
[ 3.706682] ===>>> SND_SOC_DAIFMT_I2S
[ 3.710361] ===>>> SND_SOC_DAIFMT_CBS_CFS
[ 3.714402] ===>>> SND_SOC_DAIFMT_IB_NF
[ 3.718545] asoc-simple-card sound@0: ak4432-aif <-> 48470000.mcasp mapping ok
[ 3.725828] asoc-simple-card sound@0: ASoC: no DMI vendor name!
[ 3.732323] [AK4432] ak4432_write_register (00, 00)
[ 3.748367] ALSA device list:
[ 3.751393] #0: DRA7xx-EVM

In userspace with aplay -Dplughw:0,0 alarm.mp3

# aplay -Dplughw:0,0 alarm.mp3
Playing raw data 'alarm.mp3' : [ 7.763355] [AK4432] ak4432_hw_params(268)
Unsigned 8 bit, Rate 8000 Hz, Mono
[ 7.768479] [AK4432] ak4432_write_register (02, 03)
[ 7.776696] ===>>> SND_SOC_DAIFMT_I2S
[ 7.780398] ===>>> SND_SOC_DAIFMT_CBS_CFS
[ 7.784479] ===>>> SND_SOC_DAIFMT_IB_NF
[ 7.788359] davinci-mcasp 48470000.mcasp: Too fast reference clock (24576000)
[ 7.795954] [AK4432] ak4432_set_dai_mute mute[OFF] nfs[8000]
[ 7.801742] [AK4432] ak4432_set_dai_mute External Mute = OFF
[ 7.934723] [AK4432] ak4432_set_dai_mute(550) mdelay(127 ms)
[ 7.940494] [AK4432] ak4432_set_dai_mute(552) ret[0]
[ 7.945758] [AK4432] ak4432_trigger(482)
[ 11.961221] [AK4432] ak4432_trigger(482)
[ 11.965583] [AK4432] ak4432_set_dai_mute mute[ON] nfs[8000]
[ 11.971501] [AK4432] ak4432_write_register (03, 03)
[ 12.103644] [AK4432] ak4432_set_dai_mute(541) mdelay(127 ms)
[ 12.109416] [AK4432] ak4432_set_dai_mute External Mute = ON
[ 12.115111] [AK4432] ak4432_set_dai_mute(552) ret[1]
#
# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: DRA7xxEVM [DRA7xx-EVM], device 0: davinci-mcasp.0-ak4432-aif ak4432-aif-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
#

But still no sound with these settings.

  • Hi Scott,

    You can skip devmem 0x484700B4 w 0x00008005 & devmem2 0x484700B0 w 0x1F steps on the fly.

    Please do send devmem2 dumps for all the registers that I mentioned like before for test 1 , test 2 and test 3. 

    Also would request you to add logs in file sound/soc/ti/davinci-mcasp.c in kernel and in function 

    static int davinci_mcasp_calc_clk_div() just before return as below:

    printk("div is %d aux_div is %d bclk freq is %d and sys clk is %d set %d\n", div, aux_div, bclk_freq, sysclk_freq, set);
    return error_ppm;

  • Hi Scott,

    In file sound/soc/generic/simple-card.c, in function asoc_simple_set_clk_rate(), can you please add prints like below:

    static int asoc_simple_set_clk_rate(struct asoc_simple_dai *simple_dai,
    unsigned long rate)
    {
    + printk("name %s rate %d simple_dai->clk %p\n", simple_dai->name, rate, simple_dai->clk);
    if (!simple_dai->clk)
    return 0;
    + printk("Clock name is %s\n",__clk_get_name(simple_dai->clk));
    if (clk_get_rate(simple_dai->clk) == rate)
    return 0;

    + printk("Setting clock rate for %s is %d\n",__clk_get_name(simple_dai->clk, rate);
    return clk_set_rate(simple_dai->clk, rate);
    }

    In file sound/soc/generic/simple-card.c, in function asoc_simple_card_hw_params(), can you please add print like below:

    if (priv->mclk_fs)
    mclk_fs = priv->mclk_fs;
    else if (dai_props->mclk_fs)
    mclk_fs = dai_props->mclk_fs;
    + printk("mclk fs is %d params rate is %d\n", mclk_fs, params_rate(params));
    if (mclk_fs) {

    In file sound/soc/generic/simple-card-utils.c, in function asoc_simple_card_parse_clk(), prints like below:

    clk = devm_get_clk_from_child(dev, node, NULL);
    if (!IS_ERR(clk)) {
    simple_dai->sysclk = clk_get_rate(clk);
    + printk("Clock name is %s\n",__clk_get_name(clk));
    asoc_simple_card_clk_register(simple_dai, clk);
    } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
    simple_dai->sysclk = val;
    } else {
    clk = devm_get_clk_from_child(dev, dai_of_node, NULL);
    if (!IS_ERR(clk)) + {
    simple_dai->sysclk = clk_get_rate(clk);
    + printk("child: Clock name is %s\n",__clk_get_name(clk));
    + }
    }

    ...

    ...

    + printk("%s : sysclk-%d = %d, direction %d\n", name, simple_dai->sysclk_id, simple_dai->sysclk, simple_dai->clk_direction);

    return 0;

    Please take prints of the above and do please send me for all tests.

    Also please perform only 1 test with removing clocks field and adding back system-clock-frequency

        sound0_master: simple-audio-card,cpu {
            sound-dai = <&mcasp5>;
            clocks = <&mcasp5_aux_gfclk_mux>; or clocks = <&dpll_abe_ck>; or clock = <&dpll_abe_m2_ck>

    system-clock-frequency = <24576000>;

            system-clock-direction-out;
        };

  • Hi Dwarakesh R.

    I can NOT find function asoc_simple_set_clk_rate() in file sound/soc/generic/simple-card.c. attached is from linux 4.14.79 

    simple-card.c
    /*
     * ASoC simple sound card support
     *
     * Copyright (C) 2012 Renesas Solutions Corp.
     * Kuninori Morimoto <kuninori.morimoto.gx@renesas.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/clk.h>
    #include <linux/device.h>
    #include <linux/gpio.h>
    #include <linux/module.h>
    #include <linux/of.h>
    #include <linux/of_gpio.h>
    #include <linux/platform_device.h>
    #include <linux/string.h>
    #include <sound/jack.h>
    #include <sound/simple_card.h>
    #include <sound/soc-dai.h>
    #include <sound/soc.h>
    
    struct asoc_simple_jack {
    	struct snd_soc_jack jack;
    	struct snd_soc_jack_pin pin;
    	struct snd_soc_jack_gpio gpio;
    };
    
    struct simple_card_data {
    	struct snd_soc_card snd_card;
    	struct simple_dai_props {
    		struct asoc_simple_dai cpu_dai;
    		struct asoc_simple_dai codec_dai;
    		unsigned int mclk_fs;
    	} *dai_props;
    	unsigned int mclk_fs;
    	struct asoc_simple_jack hp_jack;
    	struct asoc_simple_jack mic_jack;
    	struct snd_soc_dai_link *dai_link;
    };
    
    #define simple_priv_to_card(priv) (&(priv)->snd_card)
    #define simple_priv_to_props(priv, i) ((priv)->dai_props + (i))
    #define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev)
    #define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i))
    
    #define DAI	"sound-dai"
    #define CELL	"#sound-dai-cells"
    #define PREFIX	"simple-audio-card,"
    
    #define asoc_simple_card_init_hp(card, sjack, prefix)\
    	asoc_simple_card_init_jack(card, sjack, 1, prefix)
    #define asoc_simple_card_init_mic(card, sjack, prefix)\
    	asoc_simple_card_init_jack(card, sjack, 0, prefix)
    static int asoc_simple_card_init_jack(struct snd_soc_card *card,
    				      struct asoc_simple_jack *sjack,
    				      int is_hp, char *prefix)
    {
    	struct device *dev = card->dev;
    	enum of_gpio_flags flags;
    	char prop[128];
    	char *pin_name;
    	char *gpio_name;
    	int mask;
    	int det;
    
    	sjack->gpio.gpio = -ENOENT;
    
    	if (is_hp) {
    		snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
    		pin_name	= "Headphones";
    		gpio_name	= "Headphone detection";
    		mask		= SND_JACK_HEADPHONE;
    	} else {
    		snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
    		pin_name	= "Mic Jack";
    		gpio_name	= "Mic detection";
    		mask		= SND_JACK_MICROPHONE;
    	}
    
    	det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
    	if (det == -EPROBE_DEFER)
    		return -EPROBE_DEFER;
    
    	if (gpio_is_valid(det)) {
    		sjack->pin.pin		= pin_name;
    		sjack->pin.mask		= mask;
    
    		sjack->gpio.name	= gpio_name;
    		sjack->gpio.report	= mask;
    		sjack->gpio.gpio	= det;
    		sjack->gpio.invert	= !!(flags & OF_GPIO_ACTIVE_LOW);
    		sjack->gpio.debounce_time = 150;
    
    		snd_soc_card_jack_new(card, pin_name, mask,
    				      &sjack->jack,
    				      &sjack->pin, 1);
    
    		snd_soc_jack_add_gpios(&sjack->jack, 1,
    				       &sjack->gpio);
    	}
    
    	return 0;
    }
    
    static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
    {
    	struct snd_soc_pcm_runtime *rtd = substream->private_data;
    	struct simple_card_data *priv =	snd_soc_card_get_drvdata(rtd->card);
    	struct simple_dai_props *dai_props =
    		simple_priv_to_props(priv, rtd->num);
    	int ret;
    
    	ret = asoc_simple_card_clk_enable(&dai_props->cpu_dai);
    	if (ret)
    		return ret;
    
    	ret = asoc_simple_card_clk_enable(&dai_props->codec_dai);
    	if (ret)
    		asoc_simple_card_clk_disable(&dai_props->cpu_dai);
    
    	return ret;
    }
    
    static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream)
    {
    	struct snd_soc_pcm_runtime *rtd = substream->private_data;
    	struct simple_card_data *priv =	snd_soc_card_get_drvdata(rtd->card);
    	struct simple_dai_props *dai_props =
    		simple_priv_to_props(priv, rtd->num);
    
    	asoc_simple_card_clk_disable(&dai_props->cpu_dai);
    
    	asoc_simple_card_clk_disable(&dai_props->codec_dai);
    }
    
    static int asoc_simple_card_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 simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
    	struct simple_dai_props *dai_props =
    		simple_priv_to_props(priv, rtd->num);
    	unsigned int mclk, mclk_fs = 0;
    	int ret = 0;
    
    	if (priv->mclk_fs)
    		mclk_fs = priv->mclk_fs;
    	else if (dai_props->mclk_fs)
    		mclk_fs = dai_props->mclk_fs;
    
    	printk("===>>> mclk fs is %d params rate is %d\n", mclk_fs, params_rate(params));
    	if (mclk_fs) {
    		mclk = params_rate(params) * mclk_fs;
    		ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
    					     SND_SOC_CLOCK_IN);
    		if (ret && ret != -ENOTSUPP)
    			goto err;
    
    		ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
    					     SND_SOC_CLOCK_OUT);
    		if (ret && ret != -ENOTSUPP)
    			goto err;
    	}
    	return 0;
    err:
    	return ret;
    }
    
    static const struct snd_soc_ops asoc_simple_card_ops = {
    	.startup = asoc_simple_card_startup,
    	.shutdown = asoc_simple_card_shutdown,
    	.hw_params = asoc_simple_card_hw_params,
    };
    
    static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
    {
    	struct simple_card_data *priv =	snd_soc_card_get_drvdata(rtd->card);
    	struct snd_soc_dai *codec = rtd->codec_dai;
    	struct snd_soc_dai *cpu = rtd->cpu_dai;
    	struct simple_dai_props *dai_props =
    		simple_priv_to_props(priv, rtd->num);
    	int ret;
    
    	ret = asoc_simple_card_init_dai(codec, &dai_props->codec_dai);
    	if (ret < 0)
    		return ret;
    
    	ret = asoc_simple_card_init_dai(cpu, &dai_props->cpu_dai);
    	if (ret < 0)
    		return ret;
    
    	ret = asoc_simple_card_init_hp(rtd->card, &priv->hp_jack, PREFIX);
    	if (ret < 0)
    		return ret;
    
    	ret = asoc_simple_card_init_mic(rtd->card, &priv->mic_jack, PREFIX);
    	if (ret < 0)
    		return ret;
    
    	return 0;
    }
    
    static int asoc_simple_card_dai_link_of(struct device_node *node,
    					struct simple_card_data *priv,
    					int idx,
    					bool is_top_level_node)
    {
    	struct device *dev = simple_priv_to_dev(priv);
    	struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
    	struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
    	struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
    	struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
    	struct device_node *cpu = NULL;
    	struct device_node *plat = NULL;
    	struct device_node *codec = NULL;
    	char prop[128];
    	char *prefix = "";
    	int ret, single_cpu;
    
    	/* For single DAI link & old style of DT node */
    	if (is_top_level_node)
    		prefix = PREFIX;
    
    	snprintf(prop, sizeof(prop), "%scpu", prefix);
    	cpu = of_get_child_by_name(node, prop);
    
    	if (!cpu) {
    		ret = -EINVAL;
    		dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
    		goto dai_link_of_err;
    	}
    
    	snprintf(prop, sizeof(prop), "%splat", prefix);
    	plat = of_get_child_by_name(node, prop);
    
    	snprintf(prop, sizeof(prop), "%scodec", prefix);
    	codec = of_get_child_by_name(node, prop);
    
    	if (!codec) {
    		ret = -EINVAL;
    		dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
    		goto dai_link_of_err;
    	}
    
    	ret = asoc_simple_card_parse_daifmt(dev, node, codec,
    					    prefix, &dai_link->dai_fmt);
    	if (ret < 0)
    		goto dai_link_of_err;
    
    	of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs);
    
    	ret = asoc_simple_card_parse_cpu(cpu, dai_link,
    					 DAI, CELL, &single_cpu);
    	if (ret < 0)
    		goto dai_link_of_err;
    
    	ret = asoc_simple_card_parse_codec(codec, dai_link, DAI, CELL);
    	if (ret < 0)
    		goto dai_link_of_err;
    
    	ret = asoc_simple_card_parse_platform(plat, dai_link, DAI, CELL);
    	if (ret < 0)
    		goto dai_link_of_err;
    
    	ret = asoc_simple_card_of_parse_tdm(cpu, cpu_dai);
    	if (ret < 0)
    		goto dai_link_of_err;
    
    	ret = asoc_simple_card_of_parse_tdm(codec, codec_dai);
    	if (ret < 0)
    		goto dai_link_of_err;
    
    	ret = asoc_simple_card_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
    	if (ret < 0)
    		goto dai_link_of_err;
    
    	ret = asoc_simple_card_parse_clk_codec(dev, codec, dai_link, codec_dai);
    	if (ret < 0)
    		goto dai_link_of_err;
    
    	ret = asoc_simple_card_canonicalize_dailink(dai_link);
    	if (ret < 0)
    		goto dai_link_of_err;
    
    	ret = asoc_simple_card_set_dailink_name(dev, dai_link,
    						"%s-%s",
    						dai_link->cpu_dai_name,
    						dai_link->codec_dai_name);
    	if (ret < 0)
    		goto dai_link_of_err;
    
    	dai_link->ops = &asoc_simple_card_ops;
    	dai_link->init = asoc_simple_card_dai_init;
    
    	asoc_simple_card_canonicalize_cpu(dai_link, single_cpu);
    
    dai_link_of_err:
    	of_node_put(cpu);
    	of_node_put(codec);
    
    	return ret;
    }
    
    static int asoc_simple_card_parse_aux_devs(struct device_node *node,
    					   struct simple_card_data *priv)
    {
    	struct device *dev = simple_priv_to_dev(priv);
    	struct device_node *aux_node;
    	struct snd_soc_card *card = simple_priv_to_card(priv);
    	int i, n, len;
    
    	if (!of_find_property(node, PREFIX "aux-devs", &len))
    		return 0;		/* Ok to have no aux-devs */
    
    	n = len / sizeof(__be32);
    	if (n <= 0)
    		return -EINVAL;
    
    	card->aux_dev = devm_kzalloc(dev,
    			n * sizeof(*card->aux_dev), GFP_KERNEL);
    	if (!card->aux_dev)
    		return -ENOMEM;
    
    	for (i = 0; i < n; i++) {
    		aux_node = of_parse_phandle(node, PREFIX "aux-devs", i);
    		if (!aux_node)
    			return -EINVAL;
    		card->aux_dev[i].codec_of_node = aux_node;
    	}
    
    	card->num_aux_devs = n;
    	return 0;
    }
    
    static int asoc_simple_card_parse_of(struct simple_card_data *priv)
    {
    	struct device *dev = simple_priv_to_dev(priv);
    	struct snd_soc_card *card = simple_priv_to_card(priv);
    	struct device_node *dai_link;
    	struct device_node *node = dev->of_node;
    	int ret;
    
    	if (!node)
    		return -EINVAL;
    
    	dai_link = of_get_child_by_name(node, PREFIX "dai-link");
    
    	ret = asoc_simple_card_of_parse_widgets(card, PREFIX);
    	if (ret < 0)
    		goto card_parse_end;
    
    	ret = asoc_simple_card_of_parse_routing(card, PREFIX, 1);
    	if (ret < 0)
    		goto card_parse_end;
    
    	/* Factor to mclk, used in hw_params() */
    	of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs);
    
    	/* Single/Muti DAI link(s) & New style of DT node */
    	if (dai_link) {
    		struct device_node *np = NULL;
    		int i = 0;
    
    		for_each_child_of_node(node, np) {
    			dev_dbg(dev, "\tlink %d:\n", i);
    			ret = asoc_simple_card_dai_link_of(np, priv,
    							   i, false);
    			if (ret < 0) {
    				of_node_put(np);
    				goto card_parse_end;
    			}
    			i++;
    		}
    	} else {
    		/* For single DAI link & old style of DT node */
    		ret = asoc_simple_card_dai_link_of(node, priv, 0, true);
    		if (ret < 0)
    			goto card_parse_end;
    	}
    
    	ret = asoc_simple_card_parse_card_name(card, PREFIX);
    	if (ret < 0)
    		goto card_parse_end;
    
    	ret = asoc_simple_card_parse_aux_devs(node, priv);
    
    card_parse_end:
    	of_node_put(dai_link);
    
    	return ret;
    }
    
    static int asoc_simple_card_probe(struct platform_device *pdev)
    {
    	struct simple_card_data *priv;
    	struct snd_soc_dai_link *dai_link;
    	struct simple_dai_props *dai_props;
    	struct device *dev = &pdev->dev;
    	struct device_node *np = dev->of_node;
    	struct snd_soc_card *card;
    	int num, ret;
    
    	/* Get the number of DAI links */
    	if (np && of_get_child_by_name(np, PREFIX "dai-link"))
    		num = of_get_child_count(np);
    	else
    		num = 1;
    
    	/* Allocate the private data and the DAI link array */
    	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    	if (!priv)
    		return -ENOMEM;
    
    	dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
    	dai_link  = devm_kzalloc(dev, sizeof(*dai_link)  * num, GFP_KERNEL);
    	if (!dai_props || !dai_link)
    		return -ENOMEM;
    
    	priv->dai_props			= dai_props;
    	priv->dai_link			= dai_link;
    
    	/* Init snd_soc_card */
    	card = simple_priv_to_card(priv);
    	card->owner		= THIS_MODULE;
    	card->dev		= dev;
    	card->dai_link		= priv->dai_link;
    	card->num_links		= num;
    
    	if (np && of_device_is_available(np)) {
    
    		ret = asoc_simple_card_parse_of(priv);
    		if (ret < 0) {
    			if (ret != -EPROBE_DEFER)
    				dev_err(dev, "parse error %d\n", ret);
    			goto err;
    		}
    
    	} else {
    		struct asoc_simple_card_info *cinfo;
    
    		cinfo = dev->platform_data;
    		if (!cinfo) {
    			dev_err(dev, "no info for asoc-simple-card\n");
    			return -EINVAL;
    		}
    
    		if (!cinfo->name ||
    		    !cinfo->codec_dai.name ||
    		    !cinfo->codec ||
    		    !cinfo->platform ||
    		    !cinfo->cpu_dai.name) {
    			dev_err(dev, "insufficient asoc_simple_card_info settings\n");
    			return -EINVAL;
    		}
    
    		card->name		= (cinfo->card) ? cinfo->card : cinfo->name;
    		dai_link->name		= cinfo->name;
    		dai_link->stream_name	= cinfo->name;
    		dai_link->platform_name	= cinfo->platform;
    		dai_link->codec_name	= cinfo->codec;
    		dai_link->cpu_dai_name	= cinfo->cpu_dai.name;
    		dai_link->codec_dai_name = cinfo->codec_dai.name;
    		dai_link->dai_fmt	= cinfo->daifmt;
    		dai_link->init		= asoc_simple_card_dai_init;
    		memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai,
    					sizeof(priv->dai_props->cpu_dai));
    		memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai,
    					sizeof(priv->dai_props->codec_dai));
    	}
    
    	snd_soc_card_set_drvdata(card, priv);
    
    	ret = devm_snd_soc_register_card(dev, card);
    	if (ret < 0)
    		goto err;
    
    	return 0;
    err:
    	asoc_simple_card_clean_reference(card);
    
    	return ret;
    }
    
    static int asoc_simple_card_remove(struct platform_device *pdev)
    {
    	struct snd_soc_card *card = platform_get_drvdata(pdev);
    
    	return asoc_simple_card_clean_reference(card);
    }
    
    static const struct of_device_id asoc_simple_of_match[] = {
    	{ .compatible = "simple-audio-card", },
    	{},
    };
    MODULE_DEVICE_TABLE(of, asoc_simple_of_match);
    
    static struct platform_driver asoc_simple_card = {
    	.driver = {
    		.name = "asoc-simple-card",
    		.pm = &snd_soc_pm_ops,
    		.of_match_table = asoc_simple_of_match,
    	},
    	.probe = asoc_simple_card_probe,
    	.remove = asoc_simple_card_remove,
    };
    
    module_platform_driver(asoc_simple_card);
    
    MODULE_ALIAS("platform:asoc-simple-card");
    MODULE_LICENSE("GPL v2");
    MODULE_DESCRIPTION("ASoC Simple Sound Card");
    MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
    

    => Please take prints of the above and do please send me for all tests.

    You mean test 1, test 2 and test 3. right?

    and also test 4 with removing clocks field and adding back system-clock-frequency in DTS file, right?

    Regards,

    Scott

  • Hi Scott,

    Can you please check in file simple-card-utils.c and see if the function is there.

    You mean test 1, test 2 and test 3. right? : Yes

    and also test 4 with removing clocks field and adding back system-clock-frequency in DTS file, right? : Yes

  • Hi Dwarakesh R.

    Checked, there is no function similar to set_clk_rate 

    simple-card-utils.c
    /*
     * simple-card-utils.c
     *
     * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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/clk.h>
    #include <linux/module.h>
    #include <linux/of.h>
    #include <linux/of_graph.h>
    #include <sound/simple_card_utils.h>
    
    void asoc_simple_card_convert_fixup(struct asoc_simple_card_data *data,
    				    struct snd_pcm_hw_params *params)
    {
    	struct snd_interval *rate = hw_param_interval(params,
    						SNDRV_PCM_HW_PARAM_RATE);
    	struct snd_interval *channels = hw_param_interval(params,
    						SNDRV_PCM_HW_PARAM_CHANNELS);
    
    	if (data->convert_rate)
    		rate->min =
    		rate->max = data->convert_rate;
    
    	if (data->convert_channels)
    		channels->min =
    		channels->max = data->convert_channels;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_convert_fixup);
    
    void asoc_simple_card_parse_convert(struct device *dev, char *prefix,
    				    struct asoc_simple_card_data *data)
    {
    	struct device_node *np = dev->of_node;
    	char prop[128];
    
    	if (!prefix)
    		prefix = "";
    
    	/* sampling rate convert */
    	snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-rate");
    	of_property_read_u32(np, prop, &data->convert_rate);
    
    	/* channels transfer */
    	snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-channels");
    	of_property_read_u32(np, prop, &data->convert_channels);
    
    	dev_dbg(dev, "convert_rate     %d\n", data->convert_rate);
    	dev_dbg(dev, "convert_channels %d\n", data->convert_channels);
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_parse_convert);
    
    int asoc_simple_card_parse_daifmt(struct device *dev,
    				  struct device_node *node,
    				  struct device_node *codec,
    				  char *prefix,
    				  unsigned int *retfmt)
    {
    	struct device_node *bitclkmaster = NULL;
    	struct device_node *framemaster = NULL;
    	unsigned int daifmt;
    
    	daifmt = snd_soc_of_parse_daifmt(node, prefix,
    					 &bitclkmaster, &framemaster);
    	daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
    
    	if (!bitclkmaster && !framemaster) {
    		/*
    		 * No dai-link level and master setting was not found from
    		 * sound node level, revert back to legacy DT parsing and
    		 * take the settings from codec node.
    		 */
    		dev_dbg(dev, "Revert to legacy daifmt parsing\n");
    
    		daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
    			(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
    	} else {
    		if (codec == bitclkmaster)
    			daifmt |= (codec == framemaster) ?
    				SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
    		else
    			daifmt |= (codec == framemaster) ?
    				SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
    	}
    
    	of_node_put(bitclkmaster);
    	of_node_put(framemaster);
    
    	*retfmt = daifmt;
    
    	dev_dbg(dev, "format : %04x\n", daifmt);
    
    	return 0;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_parse_daifmt);
    
    int asoc_simple_card_set_dailink_name(struct device *dev,
    				      struct snd_soc_dai_link *dai_link,
    				      const char *fmt, ...)
    {
    	va_list ap;
    	char *name = NULL;
    	int ret = -ENOMEM;
    
    	va_start(ap, fmt);
    	name = devm_kvasprintf(dev, GFP_KERNEL, fmt, ap);
    	va_end(ap);
    
    	if (name) {
    		ret = 0;
    
    		dai_link->name		= name;
    		dai_link->stream_name	= name;
    
    		dev_dbg(dev, "name : %s\n", name);
    	}
    
    	return ret;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_set_dailink_name);
    
    int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
    				     char *prefix)
    {
    	int ret;
    
    	if (!prefix)
    		prefix = "";
    
    	/* Parse the card name from DT */
    	ret = snd_soc_of_parse_card_name(card, "label");
    	if (ret < 0 || !card->name) {
    		char prop[128];
    
    		snprintf(prop, sizeof(prop), "%sname", prefix);
    		ret = snd_soc_of_parse_card_name(card, prop);
    		if (ret < 0)
    			return ret;
    	}
    
    	if (!card->name && card->dai_link)
    		card->name = card->dai_link->name;
    
    	dev_dbg(card->dev, "Card Name: %s\n", card->name ? card->name : "");
    
    	return 0;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name);
    
    static void asoc_simple_card_clk_register(struct asoc_simple_dai *dai,
    					  struct clk *clk)
    {
    	dai->clk = clk;
    }
    
    int asoc_simple_card_clk_enable(struct asoc_simple_dai *dai)
    {
    	return clk_prepare_enable(dai->clk);
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_clk_enable);
    
    void asoc_simple_card_clk_disable(struct asoc_simple_dai *dai)
    {
    	clk_disable_unprepare(dai->clk);
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_clk_disable);
    
    int asoc_simple_card_parse_clk(struct device *dev,
    			       struct device_node *node,
    			       struct device_node *dai_of_node,
    			       struct asoc_simple_dai *simple_dai,
    			       const char *name)
    {
    	struct clk *clk;
    	u32 val;
    
    	/*
    	 * Parse dai->sysclk come from "clocks = <&xxx>"
    	 * (if system has common clock)
    	 *  or "system-clock-frequency = <xxx>"
    	 *  or device's module clock.
    	 */
    	clk = devm_get_clk_from_child(dev, node, NULL);
    	if (!IS_ERR(clk)) {
    		simple_dai->sysclk = clk_get_rate(clk);
    		printk("===>>> Clock name is %s\n",__clk_get_name(clk));
    		asoc_simple_card_clk_register(simple_dai, clk);
    	} else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
    		simple_dai->sysclk = val;
    	} else {
    		clk = devm_get_clk_from_child(dev, dai_of_node, NULL);
    		if (!IS_ERR(clk)) {
    			simple_dai->sysclk = clk_get_rate(clk);
    			printk("===>>> child: Clock name is %s\n",__clk_get_name(clk));
    		}
    	}
    
    	if (of_property_read_bool(node, "system-clock-direction-out"))
    		simple_dai->clk_direction = SND_SOC_CLOCK_OUT;
    
    	if (!of_property_read_u32(node, "system-clock-id", &val))
    		simple_dai->sysclk_id = val;
    
    	dev_dbg(dev, "%s : sysclk-%d-%s = %d\n", name, simple_dai->sysclk_id,
    		simple_dai->clk_direction == SND_SOC_CLOCK_IN ? "in" : "out",
    		simple_dai->sysclk);
    
    	printk("===>>> %s : sysclk-%d = %d, direction %d\n", name, simple_dai->sysclk_id, simple_dai->sysclk, simple_dai->clk_direction);
    	return 0;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk);
    
    int asoc_simple_card_parse_dai(struct device_node *node,
    				    struct device_node **dai_of_node,
    				    const char **dai_name,
    				    const char *list_name,
    				    const char *cells_name,
    				    int *is_single_link)
    {
    	struct of_phandle_args args;
    	int ret;
    
    	if (!node)
    		return 0;
    
    	/*
    	 * Get node via "sound-dai = <&phandle port>"
    	 * it will be used as xxx_of_node on soc_bind_dai_link()
    	 */
    	ret = of_parse_phandle_with_args(node, list_name, cells_name, 0, &args);
    	if (ret)
    		return ret;
    
    	/* Get dai->name */
    	if (dai_name) {
    		ret = snd_soc_of_get_dai_name(node, dai_name);
    		if (ret < 0)
    			return ret;
    	}
    
    	*dai_of_node = args.np;
    
    	if (is_single_link)
    		*is_single_link = !args.args_count;
    
    	return 0;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai);
    
    static int asoc_simple_card_get_dai_id(struct device_node *ep)
    {
    	struct device_node *node;
    	struct device_node *endpoint;
    	int i, id;
    	int ret;
    
    	ret = snd_soc_get_dai_id(ep);
    	if (ret != -ENOTSUPP)
    		return ret;
    
    	node = of_graph_get_port_parent(ep);
    
    	/*
    	 * Non HDMI sound case, counting port/endpoint on its DT
    	 * is enough. Let's count it.
    	 */
    	i = 0;
    	id = -1;
    	for_each_endpoint_of_node(node, endpoint) {
    		if (endpoint == ep)
    			id = i;
    		i++;
    	}
    
    	of_node_put(node);
    
    	if (id < 0)
    		return -ENODEV;
    
    	return id;
    }
    
    int asoc_simple_card_parse_graph_dai(struct device_node *ep,
    				     struct device_node **dai_of_node,
    				     const char **dai_name)
    {
    	struct device_node *node;
    	struct of_phandle_args args;
    	int ret;
    
    	if (!ep)
    		return 0;
    	if (!dai_name)
    		return 0;
    
    	node = of_graph_get_port_parent(ep);
    
    	/* Get dai->name */
    	args.np		= node;
    	args.args[0]	= asoc_simple_card_get_dai_id(ep);
    	args.args_count	= (of_graph_get_endpoint_count(node) > 1);
    
    	ret = snd_soc_get_dai_name(&args, dai_name);
    	if (ret < 0)
    		return ret;
    
    	*dai_of_node = node;
    
    	return 0;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_parse_graph_dai);
    
    int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
    			      struct asoc_simple_dai *simple_dai)
    {
    	int ret;
    
    	if (simple_dai->sysclk) {
    		ret = snd_soc_dai_set_sysclk(dai, simple_dai->sysclk_id,
    					     simple_dai->sysclk,
    					     simple_dai->clk_direction);
    		if (ret && ret != -ENOTSUPP) {
    			dev_err(dai->dev, "simple-card: set_sysclk error\n");
    			return ret;
    		}
    	}
    
    	if (simple_dai->slots) {
    		ret = snd_soc_dai_set_tdm_slot(dai,
    					       simple_dai->tx_slot_mask,
    					       simple_dai->rx_slot_mask,
    					       simple_dai->slots,
    					       simple_dai->slot_width);
    		if (ret && ret != -ENOTSUPP) {
    			dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
    			return ret;
    		}
    	}
    
    	return 0;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai);
    
    int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link)
    {
    	/* Assumes platform == cpu */
    	if (!dai_link->platform_of_node)
    		dai_link->platform_of_node = dai_link->cpu_of_node;
    
    	return 0;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink);
    
    void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
    				       int is_single_links)
    {
    	/*
    	 * In soc_bind_dai_link() will check cpu name after
    	 * of_node matching if dai_link has cpu_dai_name.
    	 * but, it will never match if name was created by
    	 * fmt_single_name() remove cpu_dai_name if cpu_args
    	 * was 0. See:
    	 *	fmt_single_name()
    	 *	fmt_multiple_name()
    	 */
    	if (is_single_links)
    		dai_link->cpu_dai_name = NULL;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu);
    
    int asoc_simple_card_clean_reference(struct snd_soc_card *card)
    {
    	struct snd_soc_dai_link *dai_link;
    	int num_links;
    
    	for (num_links = 0, dai_link = card->dai_link;
    	     num_links < card->num_links;
    	     num_links++, dai_link++) {
    		of_node_put(dai_link->cpu_of_node);
    		of_node_put(dai_link->codec_of_node);
    	}
    	return 0;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference);
    
    int asoc_simple_card_of_parse_routing(struct snd_soc_card *card,
    				      char *prefix,
    				      int optional)
    {
    	struct device_node *node = card->dev->of_node;
    	char prop[128];
    
    	if (!prefix)
    		prefix = "";
    
    	snprintf(prop, sizeof(prop), "%s%s", prefix, "routing");
    
    	if (!of_property_read_bool(node, prop)) {
    		if (optional)
    			return 0;
    		return -EINVAL;
    	}
    
    	return snd_soc_of_parse_audio_routing(card, prop);
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_routing);
    
    int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card,
    				      char *prefix)
    {
    	struct device_node *node = card->dev->of_node;
    	char prop[128];
    
    	if (!prefix)
    		prefix = "";
    
    	snprintf(prop, sizeof(prop), "%s%s", prefix, "widgets");
    
    	if (of_property_read_bool(node, prop))
    		return snd_soc_of_parse_audio_simple_widgets(card, prop);
    
    	/* no widgets is not error */
    	return 0;
    }
    EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_widgets);
    
    /* Module information */
    MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
    MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
    MODULE_LICENSE("GPL v2");
    

  • Hi Scott,

    Oh that explains why clock did not change for 8KHz and 48KHz, when we tried using mclk_fs=512. Can you please try to patch up your code as below:

    In function asoc_simple_card_hw_params() :

    if (mclk_fs) {
    mclk = params_rate(params) * mclk_fs;

    + ret = asoc_simple_set_clk_rate(&dai_props->codec_dai, mclk);
    + if (ret < 0)
    + return ret;

    + ret = asoc_simple_set_clk_rate(&dai_props->cpu_dai, mclk);
    + if (ret < 0)
    + return ret;

    ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
    SND_SOC_CLOCK_IN);
    if (ret && ret != -ENOTSUPP)
    goto err;

    ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
    SND_SOC_CLOCK_OUT);
    if (ret && ret != -ENOTSUPP)
    goto err;
    }

    And then above asoc_simple_card_hw_params() function define the below function:

    + static int asoc_simple_set_clk_rate(struct asoc_simple_dai *simple_dai,
    + unsigned long rate)
    + {
    + printk("name %s rate %d simple_dai->clk %p\n", simple_dai->name, rate, simple_dai->clk);
    + if (!simple_dai->clk)
    + return 0;
    + printk("Clock name is %s\n",__clk_get_name(simple_dai->clk);
    + if (clk_get_rate(simple_dai->clk) == rate)
    + return 0;

    + printk("Setting clock rate for %s\n",__clk_get_name(simple_dai->clk));
    + return clk_set_rate(simple_dai->clk, rate);
    + }

  • Hi Scott,

    Please do take the devmem2 dumps and also please measure clock for all the 4 tests

  • Hi Dwarakesh R.

    The results are listed here and attached logs. audio_debug_log_with_patch.rar

    Test1 Test 2 Test 3 Test 4 all same 

    ACLKX = 1.535MHz

    FSX = 48KHz

    AHCLK = 24.576MHz

    Clockout2 = null

    Regards,

    Scott

  • Hi Scott,

    Can you please try below dts file and send the logs, devmem dump and clock probing:

    sound0: sound@0 {
        compatible = "simple-audio-card";
        simple-audio-card,name = "DRA7xx-EVM";

        simple-audio-card,mclk-fs = <512>;

        simple-audio-card,widgets =
        "Headphone", "Headphone Jack",
        "Line", "Line Out",
        "Microphone", "Mic Jack",
        "Line", "Line In";
        simple-audio-card,routing =
        "Headphone Jack", "DAC to AOUT";
        simple-audio-card,format = "i2s";
        simple-audio-card,bitclock-master = <&sound0_master>;
        simple-audio-card,frame-master = <&sound0_master>;
        simple-audio-card,bitclock-inversion;

        sound0_master: simple-audio-card,cpu {
            sound-dai = <&mcasp5>;
            clocks = <&dpll_abe_m2_ck>

            system-clock-direction-out;
        };

        simple-audio-card,codec {
            sound-dai = <&audio>;
        };
    };

    audio: audio-codec@19 {
        #sound-dai-cells = <0>;
        compatible = "akm,ak4432";
        reg = <0x19>;
    };

    &mcasp5 {
        #sound-dai-cells = <0>;
        assigned-clocks = <&abe_dpll_sys_clk_mux>, <&dpll_abe_ck>, <&dpll_abe_m2_ck>;
        assigned-clock-parents = <&sys_clkin2>;

        assigned-clock-rates  = <0>, <24576000>, <24576000>;

        status = "okay";

        op-mode = <0>; /* MCASP_IIS_MODE */
        tdm-slots = <2>;
        /* 4 serializers */
        serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
            1 0 0 0
        >;
        tx-num-evt = <32>;
        rx-num-evt = <32>;

        auxclk-fs-ratio = <512>;
    };

  • Hi Dwarakesh R.

    By using DTS below = test 5

    	sound0: sound@0 {
    		compatible = "simple-audio-card";
    		simple-audio-card,name = "DRA7xx-EVM";
    		simple-audio-card,mclk-fs = <512>;
    		simple-audio-card,widgets =
    			"Headphone", "Headphone Jack",
    			"Line", "Line Out",
    			"Microphone", "Mic Jack",
    			"Line", "Line In";
    		simple-audio-card,routing =
    			"Headphone Jack",       "DAC to AOUT";
    		simple-audio-card,format = "i2s";
    		simple-audio-card,bitclock-master = <&sound0_master>;
    		simple-audio-card,frame-master = <&sound0_master>;
    		simple-audio-card,bitclock-inversion;
    
    		sound0_master: simple-audio-card,cpu {
    			sound-dai = <&mcasp5>;
    			clocks = <&dpll_abe_m2_ck>;
    			system-clock-direction-out;
    		};
    
    		simple-audio-card,codec {
    			sound-dai = <&audio>;
    		};
    	};
    
    	audio: audio-codec@19 {
    		#sound-dai-cells = <0>;
    		compatible = "akm,ak4432";
    		reg = <0x19>;
    	};
    
    &mcasp5 {
    	#sound-dai-cells = <0>;
    	assigned-clocks = <&abe_dpll_sys_clk_mux>, <&dpll_abe_ck>, <&dpll_abe_m2_ck>;
    	assigned-clock-parents = <&sys_clkin2>;
    	assigned-clock-rates  = <0>, <24576000>, <24576000>;
    
    	status = "okay";
    
    	op-mode = <0>;	/* MCASP_IIS_MODE */
    	tdm-slots = <2>;
    	/* 4 serializers */
    	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
    		1 0 0 0
    	>;
    	tx-num-evt = <32>;
    	rx-num-evt = <32>;
    
    	auxclk-fs-ratio = <512>;
    };

    The frequency are same

    ACLKX = 1.535MHz

    FSX = 48KHz

    AHCLK = 24.576MHz

    Clockout2 = null

    The log with devmem attached test_5_with_patch.rar

  • Hi Scott,

    Are you sure it is still 24.576 ? I see there is division of 6 as below:

    Read at address  0x4A0051F0 (0xb6f6f1f0): 0x00000A06

     

    24.57MHz 6 /6 = 4.096 MHz

    4.096 MHz clock goes to MCASP and gets divided by 1 for AHCLKX and divided by 16 fir ACLKX(bit clk)

    Read at address  0x484700B0 (0xb6ff50b0): 0x0000002F(16)

    Read at address  0x484700B4 (0xb6fa90b4): 0x00008000(1)

    4.096MHz/16 = 256KHz

    16-bits*2 slots*8Khz = 256 KHz 

    Just play the 8KHz after boot up and check

  • Hi Dwarakesh R.

    We double checked the frequency, attach MOV file FYR  

    ACLKX = 1.535MHz

    FSX = 48KHz

    AHCLK = 24.576MHz

  • Hi Scott,

    I am really not sure why it is not changing. Can you play same 8KHz audio for second time after it played for the first time completely. Second time also you can take dump. Entire clock settings are configured for 4.096MHz and it should have output the same. Let me see if there is any more that I have missed out.

  • Hi Dwarakesh R.

    => Can you play same 8KHz audio for second time after it played for the first time completely. Second time also you can take dump.

    Attached is the log please check test_5_with_patch_play_twice_mp3.rar

  • Hi Scott,

    Meanwhile to confirm if 8KHz audio is playing, you can change clock as below and check if audio is playing

    assigned-clock-rates  = <0>, <4096000>, <4096000>;


    Also in case required in dra7xx-clocks.dtsi

    dpll_abe_ck: dpll_abe_ck@1e0 {
    #clock-cells = <0>;
    compatible = "ti,omap4-dpll-m4xen-clock";
    clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
    reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
    assigned-clocks = <&dpll_abe_ck>;
    assigned-clock-rates = <3333333>;
    };

  • Hi Dwarakesh R.

    SDK-05.03.00.07\linux-4.14.79\arch\arm\boot\dts\am571x-idk.dts
    	sound0: sound@0 {
    		compatible = "simple-audio-card";
    		simple-audio-card,name = "DRA7xx-EVM";
    		simple-audio-card,mclk-fs = <512>;
    		simple-audio-card,widgets =
    			"Headphone", "Headphone Jack",
    			"Line", "Line Out",
    			"Microphone", "Mic Jack",
    			"Line", "Line In";
    		simple-audio-card,routing =
    			"Headphone Jack",       "DAC to AOUT";
    		simple-audio-card,format = "i2s";
    		simple-audio-card,bitclock-master = <&sound0_master>;
    		simple-audio-card,frame-master = <&sound0_master>;
    		simple-audio-card,bitclock-inversion;
    
    		sound0_master: simple-audio-card,cpu {
    			sound-dai = <&mcasp5>;
    			clocks = <&dpll_abe_m2_ck>;
    			system-clock-direction-out;
    		};
    
    		simple-audio-card,codec {
    			sound-dai = <&audio>;
    		};
    	};
    
    &i2c3 {
    	status = "okay";
    	clock-frequency = <400000>;
    	audio: audio-codec@19 {
    		#sound-dai-cells = <0>;
    		compatible = "akm,ak4432";
    		reg = <0x19>;
    	};
    };
    
    &mcasp5 {
    	#sound-dai-cells = <0>;
    	assigned-clocks = <&abe_dpll_sys_clk_mux>, <&dpll_abe_ck>, <&dpll_abe_m2_ck>;
    	assigned-clock-parents = <&sys_clkin2>;
    	assigned-clock-rates  = <0>, <4096000>, <4096000>;
    
    	status = "okay";
    
    	op-mode = <0>;	/* MCASP_IIS_MODE */
    	tdm-slots = <2>;
    	/* 4 serializers */
    	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
    		1 0 0 0
    	>;
    	tx-num-evt = <32>;
    	rx-num-evt = <32>;
    
    	auxclk-fs-ratio = <512>;
    };
    
    SDK-05.03.00.07\linux-4.14.79\arch\arm\boot\dts\dra7xx-clocks.dtsi
    	sys_clkin2: sys_clkin2 {
    		#clock-cells = <0>;
    		compatible = "fixed-clock";
    		clock-frequency = <24576000>;
    	};
    
    	dpll_abe_ck: dpll_abe_ck@1e0 {
    		#clock-cells = <0>;
    		compatible = "ti,omap4-dpll-m4xen-clock";
    		clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
    		reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
    		assigned-clocks = <&dpll_abe_ck>;
    		assigned-clock-rates = <3333333>;
    	};
    
    

    the log seems crash @ dmesg boot test_6_with_patch_crash_dmesg.rar

    and both files could not be played  (test.mp3 & sample06.wav)

    Another test is 

    same SDK-05.03.00.07\linux-4.14.79\arch\arm\boot\dts\am571x-idk.dts
    only change back SDK-05.03.00.07\linux-4.14.79\arch\arm\boot\dts\dra7xx-clocks.dtsi
    
    	sys_clkin2: sys_clkin2 {
    		#clock-cells = <0>;
    		compatible = "fixed-clock";
    		clock-frequency = <24576000>;
    	};
    
    	dpll_abe_ck: dpll_abe_ck@1e0 {
    		#clock-cells = <0>;
    		compatible = "ti,omap4-dpll-m4xen-clock";
    		clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
    		reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
    		assigned-clocks = <&dpll_abe_ck>;
    		assigned-clock-rates = <24576000>;
    	};

    both files could not be played  (test.mp3 & sample06.wav) and kernel still crash. test_7_with_patch_crash_dmesg.rar

  • Hi Dwarakesh R.

    Is there anything we can test ?

    Regards,

    Scott

  • Hi Scott,

    For some reason touching DPLL_ABE is causing the crash. Can you please try like below and check if 8 KHz audio is playing. also please probe and let me know the clocks.

    Revert back abe_dpll clock to 24.576 MHz

    assigned-clock-rates = <0>, <24576000>, <4096000>;

    Also in case required in dra7xx-clocks.dtsi

    
    

    dpll_abe_ck: dpll_abe_ck@1e0 {
    #clock-cells = <0>;
    compatible = "ti,omap4-dpll-m4xen-clock";
    clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
    reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
    assigned-clocks = <&dpll_abe_ck>;
    assigned-clock-rates = <20000000>;
    };

    Also please include the following devmem dump along with the previous devmem dumps you take

    # devmem2 0x4A0051E0

    # devmem2 0x4A0051E4

    # devmem2 0x4A0051E8

  • Hi Scott,

    Can you please check if any mcasp is enabled in uboot and if so please disable and check if the crash is there as above. Is your code based on AM57xx IDK or AM57xx EVM ?

    Also can you please dump stopping at autoboot in uboot and all the devmem2 commands as follows

    e.g. # devmem2 0x4A0051E8 as below in uboot

    # md.w 0x4A0051E8 1

  • Hi Dwarakesh R

    I was confused with several tests, Is this what you want us to try by applying below DTS? and you need additional register value with address 0x4A0051E0 0x4A0051E4 0x4A0051E8

    SDK-05.03.00.07\linux-4.14.79\arch\arm\boot\dts\am571x-idk.dts
    	sound0: sound@0 {
    		compatible = "simple-audio-card";
    		simple-audio-card,name = "DRA7xx-EVM";
    		simple-audio-card,mclk-fs = <512>;
    		simple-audio-card,widgets =
    			"Headphone", "Headphone Jack",
    			"Line", "Line Out",
    			"Microphone", "Mic Jack",
    			"Line", "Line In";
    		simple-audio-card,routing =
    			"Headphone Jack",       "DAC to AOUT";
    		simple-audio-card,format = "i2s";
    		simple-audio-card,bitclock-master = <&sound0_master>;
    		simple-audio-card,frame-master = <&sound0_master>;
    		simple-audio-card,bitclock-inversion;
    
    		sound0_master: simple-audio-card,cpu {
    			sound-dai = <&mcasp5>;
    			clocks = <&dpll_abe_m2_ck>;
    			system-clock-direction-out;
    		};
    
    		simple-audio-card,codec {
    			sound-dai = <&audio>;
    		};
    	};
    
    &i2c3 {
    	status = "okay";
    	clock-frequency = <400000>;
    	audio: audio-codec@19 {
    		#sound-dai-cells = <0>;
    		compatible = "akm,ak4432";
    		reg = <0x19>;
    	};
    };
    
    &mcasp5 {
    	#sound-dai-cells = <0>;
    	assigned-clocks = <&abe_dpll_sys_clk_mux>, <&dpll_abe_ck>, <&dpll_abe_m2_ck>;
    	assigned-clock-parents = <&sys_clkin2>;
    	assigned-clock-rates  = <0>, <24576000>, <4096000>;
    
    	status = "okay";
    
    	op-mode = <0>;	/* MCASP_IIS_MODE */
    	tdm-slots = <2>;
    	/* 4 serializers */
    	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
    		1 0 0 0
    	>;
    	tx-num-evt = <32>;
    	rx-num-evt = <32>;
    
    	auxclk-fs-ratio = <512>;
    };
    
    SDK-05.03.00.07\linux-4.14.79\arch\arm\boot\dts\dra7xx-clocks.dtsi
    	sys_clkin2: sys_clkin2 {
    		#clock-cells = <0>;
    		compatible = "fixed-clock";
    		clock-frequency = <24576000>;
    	};
    
    	dpll_abe_ck: dpll_abe_ck@1e0 {
    		#clock-cells = <0>;
    		compatible = "ti,omap4-dpll-m4xen-clock";
    		clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
    		reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
    		assigned-clocks = <&dpll_abe_ck>;
    		assigned-clock-rates = <20000000>;
    	};

  • Hi Scott,

    Sorry for not being clear. Yes the above dts for checking if 8KHz audio is getting played, along with the additional dumps.

    Below is another experiment:

    Only when DPLL_ABE(0x4A0051EC) is modified(and not what is sysclkin2 which is 24.576 MHz) say example with the following, we are seeing a crash e.g.

    assigned-clock-rates  = <0>, <4096000>, <4096000>; or


    dpll_abe_ck: dpll_abe_ck@1e0 {
    #clock-cells = <0>;
    compatible = "ti,omap4-dpll-m4xen-clock";
    clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
    reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
    assigned-clocks = <&dpll_abe_ck>;
    assigned-clock-rates = <3333333>;
    };

    To investigate this crash issue with the above configuration(when DPLL_ABE is changed), I would want you to disable mcasp(if enabled) in uboot dts(not kernel dts. uboot dts will be in arch/arm/dts folder in uboot code) and check. Also to confirm if the clocks are gated or enabled, I would like you to dump the same registers(which you used in userspace with devmem2 ) in uboot(uboot would have a autoboot at booting time. Stop autoboot and give following commands) as follows:

    # md.w 0x4ae06118 1

    .

    .

    .

    .

    # md.w 0x484700B4 1

    Is this clear ?

  • Hi Dwarakesh R.

    For checking if 8KHz audio is getting played I applied the DTS

    SDK-05.03.00.07\linux-4.14.79\arch\arm\boot\dts\am571x-idk.dts
    	sound0: sound@0 {
    		compatible = "simple-audio-card";
    		simple-audio-card,name = "DRA7xx-EVM";
    		simple-audio-card,mclk-fs = <512>;
    		simple-audio-card,widgets =
    			"Headphone", "Headphone Jack",
    			"Line", "Line Out",
    			"Microphone", "Mic Jack",
    			"Line", "Line In";
    		simple-audio-card,routing =
    			"Headphone Jack",       "DAC to AOUT";
    		simple-audio-card,format = "i2s";
    		simple-audio-card,bitclock-master = <&sound0_master>;
    		simple-audio-card,frame-master = <&sound0_master>;
    		simple-audio-card,bitclock-inversion;
    
    		sound0_master: simple-audio-card,cpu {
    			sound-dai = <&mcasp5>;
    			clocks = <&dpll_abe_m2_ck>;
    			system-clock-direction-out;
    		};
    
    		simple-audio-card,codec {
    			sound-dai = <&audio>;
    		};
    	};
    
    &i2c3 {
    	status = "okay";
    	clock-frequency = <400000>;
    	audio: audio-codec@19 {
    		#sound-dai-cells = <0>;
    		compatible = "akm,ak4432";
    		reg = <0x19>;
    	};
    };
    
    &mcasp5 {
    	#sound-dai-cells = <0>;
    	assigned-clocks = <&abe_dpll_sys_clk_mux>, <&dpll_abe_ck>, <&dpll_abe_m2_ck>;
    	assigned-clock-parents = <&sys_clkin2>;
    	assigned-clock-rates  = <0>, <24576000>, <4096000>;
    
    	status = "okay";
    
    	op-mode = <0>;	/* MCASP_IIS_MODE */
    	tdm-slots = <2>;
    	/* 4 serializers */
    	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
    		1 0 0 0
    	>;
    	tx-num-evt = <32>;
    	rx-num-evt = <32>;
    
    	auxclk-fs-ratio = <512>;
    };
    
    SDK-05.03.00.07\linux-4.14.79\arch\arm\boot\dts\dra7xx-clocks.dtsi
    	sys_clkin2: sys_clkin2 {
    		#clock-cells = <0>;
    		compatible = "fixed-clock";
    		clock-frequency = <24576000>;
    	};
    
    	dpll_abe_ck: dpll_abe_ck@1e0 {
    		#clock-cells = <0>;
    		compatible = "ti,omap4-dpll-m4xen-clock";
    		clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
    		reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
    		assigned-clocks = <&dpll_abe_ck>;
    		assigned-clock-rates = <20000000>;
    	};

    The log is attached test_8_612_with_patch_dmesg.rar and the clocks are 

    ACLKX = 1.535MHz

    FSX = 48KHz

    AHCLK = 24.576MHz

    -----------------------------------------------------------------------------------------

    For another experiment with the crash issue

    I applied the linux DTS below

    SDK-05.03.00.07\linux-4.14.79\arch\arm\boot\dts\am571x-idk.dts
    
    	sound0: sound@0 {
    		compatible = "simple-audio-card";
    		simple-audio-card,name = "DRA7xx-EVM";
    		simple-audio-card,mclk-fs = <512>;
    		simple-audio-card,widgets =
    			"Headphone", "Headphone Jack",
    			"Line", "Line Out",
    			"Microphone", "Mic Jack",
    			"Line", "Line In";
    		simple-audio-card,routing =
    			"Headphone Jack",       "DAC to AOUT";
    		simple-audio-card,format = "i2s";
    		simple-audio-card,bitclock-master = <&sound0_master>;
    		simple-audio-card,frame-master = <&sound0_master>;
    		simple-audio-card,bitclock-inversion;
    
    		sound0_master: simple-audio-card,cpu {
    			sound-dai = <&mcasp5>;
    			clocks = <&dpll_abe_m2_ck>;
    			system-clock-direction-out;
    		};
    
    		simple-audio-card,codec {
    			sound-dai = <&audio>;
    		};
    	};
    &i2c3 {
    	status = "okay";
    	clock-frequency = <400000>;
    
    	audio: audio-codec@19 {
    		#sound-dai-cells = <0>;
    		compatible = "akm,ak4432";
    		reg = <0x19>;
    	};
    };
    &mcasp5 {
    	#sound-dai-cells = <0>;
    	assigned-clocks = <&abe_dpll_sys_clk_mux>, <&dpll_abe_ck>, <&dpll_abe_m2_ck>;
    	assigned-clock-parents = <&sys_clkin2>;
    	assigned-clock-rates  = <0>, <4096000>, <4096000>;
    
    	status = "okay";
    
    	op-mode = <0>;	/* MCASP_IIS_MODE */
    	tdm-slots = <2>;
    	/* 4 serializers */
    	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
    		1 0 0 0
    	>;
    	tx-num-evt = <32>;
    	rx-num-evt = <32>;
    
    	auxclk-fs-ratio = <512>;
    };
    
    SDK-05.03.00.07\linux-4.14.79\arch\arm\boot\dts\dra7xx-clocks.dtsi
    	sys_clkin2: sys_clkin2 {
    		#clock-cells = <0>;
    		compatible = "fixed-clock";
    		clock-frequency = <24576000>;
    	};
    	dpll_abe_ck: dpll_abe_ck@1e0 {
    		#clock-cells = <0>;
    		compatible = "ti,omap4-dpll-m4xen-clock";
    		clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
    		reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
    		assigned-clocks = <&dpll_abe_ck>;
    		assigned-clock-rates = <3333333>;
    	};
    

    and remove sound and mcasp in uboot DTS which we added in the SDK-05.03.00.07\u-boot-2018.01\arch\arm\dts\am571x-idk.dts

    the uboot and linux crash log is attached, test_9_612_with_patch_dmesg_crash.rar 

  • Hi Scott,

    Can you please dump these registers too for the second experiment : 

    # md.w 0x4A0051E0 4

    # md.w 0x4A0051E4 4

    # md.w 0x4A0051E8 4

    Please also take for the remaining registers using md.w and 4 as above

  • Hi Dwarakesh R.

    For experiment, attached the log by using md.w and 4 test_9_612_with_patch_dmesg_crash_2.rar

    Regards,

    Scott

  • Hi Dwarakesh R.

    Does it mean we can't support both 48KHz and 8KHz simultaneously?

    Scott

  • Hi Scott,

    In theory I dont see a reason why it cant be supported. It should be possible. But we need to check why it is crashing above. Let me check. Meanwhile you can try different clock values for dpll_abe_ck(highlighted below) instead of 4096000 like 245760000,128800000, 24576000,12880000, 184320000, 18432000

    assigned-clocks = <&abe_dpll_sys_clk_mux>, <&dpll_abe_ck>, <&dpll_abe_m2_ck>;

    assigned-clock-parents = <&sys_clkin2>;

    assigned-clock-rates = <0>, <4096000>, <4096000>;