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.

Clock drift issue in ti sdk 8 BSP's for audio

Dear Ti E2E community

Am facing the clock drift issue when I run the below attached app, it says that sound card is facing clock drifts, but I don't see this issue in ti sdk 7, could you please try to reproduce this issue from your end & let me know why this issue is seen, is this the codec driver, or platform driver or machine driver problem or alsa related issue??

logs:

M E N U :
---------
0: Tests
00: Run test wizard
01: Device Test
02: Play Tone
03: Play WAV File1
04: Play WAV File2
05: Record Audio
06: Latency Test
07: AEC/AES Test

09: Exit
1: Options
10: View Devices
11: View Settings

Enter the menu number: 01

Audio Device Test
Here are the audio statistics:
Rec : interval (min/max/avg/dev)=
0/41/20/13 (ms)
max burst=3
Play: interval (min/max/avg/dev)=
19/22/20/0 (ms)
burst=2
There could be 1 problem(s) with the sound device:
1: Clock drifts detected. Capture is 16 samples/sec faster than the playback device

1:OK

Kindly do the needful as early as possible,

Many Thanks in advance again,

(Please remove the .txt extension & run the below app)

pjsystest-arm-unknown-linux-gnueabihf.txt

  • Forwarding this to the SW team.
  • Thanks a lot Biser,

    Could anybody please reproduce the above issue from SW team, in ti sdk 8 BSP's & let me know whether you are facing the same issue or not, so that I can isolate the issue whether it is in codec or platform or machine driver


    Kindly do the needful as early as possible,

    Many Thanks in advance again,
  • Hi Srini,

    Do I need to do any modifications to the kernel, or just run ./pjsystest-arm-unknown-linux-gnueabihf on my beaglebone?

    Best Regards,
    Yordan
  • Sorry, BBB is not the correct platform to test this.

    I ran the app on starter kit running SDK01 & SDK8. On both TI SDKs the log is:

       

    M E N U :
    ---------
    0: Tests
    00: Run test wizard
    01: Device Test
    02: Play Tone
    03: Play WAV File1
    04: Play WAV File2
    05: Record Audio
    06: Latency Test
    07: AEC/AES Test

    09: Exit
    1: Options
    10: View Devices
    11: View Settings

    Enter the menu number: 01
    Audio Device Test
    This will run an automated test for about ten seconds or so, and display some statistics about your sound device. Please don't do anything .
    1:OK 9:Cancel
    1
    15:10:16.025 systest.c Running Audio Device Test
    15:10:16.240 audiotest.c Please wait while test is in progress (~11 secs)..
    15:10:16.260 os_core_unix.c Info: possibly re-registering existing thread
    15:10:27.374 pjsua_aud.c Set sound device: capture=-1, playback=-2
    15:10:27.374 pjsua_aud.c .Opening sound device PCM@8000/1/20ms
    Audio Device Test
    Here are the audio statistics:
    Rec : interval (min/max/avg/dev)=
    20/20/20/0 (ms)
    max burst=1
    Play: interval (min/max/avg/dev)=
    20/20/20/0 (ms)
    burst=1

    The sound device seems to be okay!
    1:OK

    Best Regards, 

    Yordan

  • Many Thanks a lot Yordan for carrying out this test

    Could you please let me know the name of the rootfs you have tried in ti sdk 8 & ti sdk 01, as I find many rootfs in filesystem folder of ti sdk 8

    Could you please provide any guidance or suggestions, why I'm facing this issue

    Hope Platform & Machine driver is correct now, am I right???, should I do any changes in the codec driver??? inorder to resolve this issue??

    Could you please help me out in this for debugging ???

    Kindly do the needful as early as possible

    As am stuck with this from past 5  days

    Many Thanks Yordan & would really appreciate for your support w.r.t this thread

  • I've used the tisdk-rootfs-image-am335x-evm.

    Srini said:
    Hope Platform & Machine driver is correct now, am I right???, should I do any changes in the codec driver??? inorder to resolve this issue??

     

    Are you able to hear any sound (i.e. from a headset), when playing audio file?

     

  • Could you please retry on other rootfs's also ie., argo-base rootfs   (ie, which is minimal in size roughly around 100 MB)

    No problem I hear audio when playing a audio file.. using aplay & am able to record using arecord, but still is this a codec driver problem??? Now platform & machine driver is correct is my understanding is correct??

    But when I run voip call(ie., network call) by running PJSIP, the call fails twice out of ten times (ie., ten times passes & 2 times fails) , what could be the issue?? is this a codec driver prolem?

    e2e.ti.com/.../1567870

    I see master underflow


    Kindly do the needful as early as possible

    Many Thanks in advance again

  • Dear Yordan,

    Could you please retry on arago-base-tisdk-image-am335x-evm.tar.gz  on ti sdk 8 & sdk 01

    I have here by attached the driver files modified to get working in ti sdk 8 (davinci-evm.c & uda134x.c ie., same modifications for these two files as I did in ti sdk 7), could you please cross check once & let me know, if there is any discrepancies  leading to this clock drift issue or should I take care anything specific to sdk 8???

    And more point I would like to add is, in hw_params() there is no bclk divider is being used in davinci-evm.c of ti sdk 8, is this being takecare by default in sdk 8??

     

     

    uda134x.c
    /*
    iifndef CONFIG_TUNSTALL_CADB
     * uda134x.c  --  UDA1345TS ALSA SoC Codec driver
     *
     * Modifications for UDA1345TS done by Srinivasan S <srinivasan.s@tataelxsi.co.in>
     *
     * Modifications by Christian Pellegrin <chripell@evolware.org>
     *
     * Copyright 2007 Dension Audio Systems Ltd.
     * Author: Zoltan Devai
     *
     * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie
     *
     * 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/delay.h>
    #include <linux/slab.h>
    #include <sound/pcm.h>
    #include <sound/pcm_params.h>
    #include <sound/soc.h>
    #include <sound/initval.h>
    
    #include <sound/uda134x.h>
    #include <sound/l3.h>
    
    #include <linux/of.h> 
    #include <linux/kernel.h>
    #include <linux/platform_device.h>
    #include <linux/slab.h>
    #include <linux/of_gpio.h>
    #include <linux/of_device.h>
    #include <linux/of_platform.h>
    #include <linux/regmap.h>
    #include <linux/pinctrl/consumer.h>
    #include "uda134x.h"
    
    
    
    /*Lines used for Configuring the codec - L3 Protocol */
    #define L3_DATA        8   	// MP4 -- GPIO0_8
    #define L3_MODE      81  	// MP2 -- GPIO2_17
    #define L3_CLOCK     10  	// MP3 -- GPIO0_10
    
    
    #define UDA134X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |SNDRV_PCM_RATE_32000 | \
    	SNDRV_PCM_RATE_44100 |SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 |SNDRV_PCM_RATE_96000)
    	
    #define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
    		SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
    
    struct uda134x_priv {
    	int sysclk;
    	int dai_fmt;
    
    	struct snd_pcm_substream *master_substream;
    	struct snd_pcm_substream *slave_substream;
    };
    
    /* In-data addresses are hard-coded into the reg-cache values */
    static const char uda134x_reg[UDA134X_REGS_NUM] = {
    	/* Extended address registers */
    	0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
    	/* Status, data regs */
    	0x00, 0x83, 0x00, 0x40, 0x80, 0xC0, 0x00, // STATUS0, NOT USED, UDA134X_DATA000 - A, UDA134X_DATA001 -B,  UDA134X_DATA010 -C, UDA134X_DATA011 - D
    
    };
    static void setdat(int v)
    {
    	gpio_set_value(L3_DATA, v > 0);
    }
    
    static void setclk(int v)
    {
    	gpio_set_value(L3_CLOCK, v > 0);
    }
    
    static void setmode(int v)
    {
    	gpio_set_value(L3_MODE, v > 0);
    }
    
    /*
     * The codec has no support for reading its registers except for peak level...
     */
    static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec,
    	unsigned int reg)
    {
    	u8 *cache = codec->reg_cache;
    
    	if (reg >= UDA134X_REGS_NUM)
    		return -1;
    	return cache[reg];
    }
    
    /*
     * Write the register cache
     */
    static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec,
    	u8 reg, unsigned int value)
    {
    	u8 *cache = codec->reg_cache;
    
    	if (reg >= UDA134X_REGS_NUM)
    		return;
    	cache[reg] = value;
    }
    
    /*
     * Write to the uda134x registers
     *
     */
    static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
    	unsigned int value)
    {
    	int ret;
    	u8 addr;
    	u8 data = value;
    	struct uda134x_platform_data *pd = codec->control_data;
    
    	if (reg >= UDA134X_REGS_NUM) {
    		printk(KERN_ERR "uda134x_write %s unknown register: reg: %u",
    		       __func__, reg);
    		return -EINVAL;
    	}
    
    	uda134x_write_reg_cache(codec, reg, value);
    
    	switch (reg) {
    	case UDA134X_STATUS0: // SYSTEM CLOCK FREQ, DATA I/P FORMAT, DC -FILTER
    	case UDA134X_STATUS1:
    		addr = UDA134X_STATUS_ADDR;
    		break;
    	case UDA134X_DATA000: // VOLUME CONTROL
    	dev_dbg(codec->dev, "Uda134x:uda134x_write L3 PROTOCOL VOLUME CONTROL  %s reg: %02X, data:%02X, value:%02X\n", __func__, reg, data, value);
    	case UDA134X_DATA001: // NOT USED FOR UDA1345TS
    	case UDA134X_DATA010: // MUTE & DE-EMPHASIS
    	case UDA134X_DATA011: // POWER CONTROL
    		addr = UDA134X_DATA0_ADDR;
    		break;
    	case UDA134X_DATA1:
    		addr = UDA134X_DATA1_ADDR;
    		break;
    	default:
    		/* It's an extended address register */
    		addr =  (reg | UDA134X_EXTADDR_PREFIX);
    
    		ret = l3_write(&pd->l3,
    			       UDA134X_DATA0_ADDR, &addr, 1);
    		if (ret != 1)
    			return -EIO;
    
    		addr = UDA134X_DATA0_ADDR;
    		data = (value | UDA134X_EXTDATA_PREFIX);
    		break;
    	}
    
    	ret = l3_write(&pd->l3,
    		       addr, &data, 1);
    	if (ret != 1)
    	{
    		return -EIO;
    	}
    
    	return 0;
    }
    
    static inline void uda134x_reset(struct snd_soc_codec *codec)
    {
    	u8 reset_reg = 0;
    	dev_dbg(codec->dev, "Uda134x:uda134x_reset ENTERED in uda134x_reset\n");
    	reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
    	uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6));
    	msleep(1);
    	uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6));
    
    }
    
    static int uda134x_mute(struct snd_soc_dai *dai, int mute)
    {
    	struct snd_soc_codec *codec = dai->codec;
    	u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010);
    
    	if (mute)
    	{
    		dev_dbg(codec->dev, "Uda134x:uda134x_mute %s mute: %d\n", __func__, mute);
    		mute_reg |= (1<<2);
    	}	
    	else
    	{
    		dev_dbg(codec->dev, "Uda134x:uda134x_mute %s unmute: %d\n", __func__, mute);
    		mute_reg &= ~(1<<2);
    	}	
    
    	uda134x_write(codec, UDA134X_DATA010, mute_reg);
    
    	return 0;
    }
    
    static int uda134x_startup(struct snd_pcm_substream *substream,
    	struct snd_soc_dai *dai)
    {
    	struct snd_soc_codec *codec = dai->codec;
    	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
    	struct snd_pcm_runtime *master_runtime;
    
    	if (uda134x->master_substream) {
    		master_runtime = uda134x->master_substream->runtime;
    
    		dev_dbg(codec->dev, "Uda134x:uda134x_startup %s constraining to %d bits at %d\n", __func__,
    			 master_runtime->sample_bits,
    			 master_runtime->rate);
    
    		snd_pcm_hw_constraint_minmax(substream->runtime,
    					     SNDRV_PCM_HW_PARAM_RATE,
    					     master_runtime->rate,
    					     master_runtime->rate);
    
    		snd_pcm_hw_constraint_minmax(substream->runtime,
    					     SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
    					     master_runtime->sample_bits,
    					     master_runtime->sample_bits);
    
    		uda134x->slave_substream = substream;
    	} else
    		uda134x->master_substream = substream;
    
    	return 0;
    }
    
    static void uda134x_shutdown(struct snd_pcm_substream *substream,
    	struct snd_soc_dai *dai)
    {
    	struct snd_soc_codec *codec = dai->codec;
    	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
    
    	dev_dbg(codec->dev, "Uda134x:uda134x_shutdown Entered uda134x_shutdown\n");
    
    	if (uda134x->master_substream == substream)
    		uda134x->master_substream = uda134x->slave_substream;
    
    	uda134x->slave_substream = NULL;
    }
    
    static int uda134x_hw_params(struct snd_pcm_substream *substream,
    	struct snd_pcm_hw_params *params,
    	struct snd_soc_dai *dai)
    {
    	struct snd_soc_pcm_runtime *rtd = substream->private_data;
    	struct snd_soc_codec *codec = rtd->codec;
    	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
    	u8 hw_params;
    
    	if (substream == uda134x->slave_substream) {
    		pr_debug("%s ignoring hw_params for slave substream\n",
    			 __func__);
    		return 0;
    	}
    
    	hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
    	hw_params &= STATUS0_SYSCLK_MASK; // 001111
    	hw_params &= STATUS0_DAIFMT_MASK; //    0001
    
    	dev_dbg(codec->dev, "Uda134x:uda134x_hw_params FORMATS %s dai_fmt: %d, params_format:%d\n", __func__,
    		 uda134x->dai_fmt, params_format(params));
    
    	dev_dbg(codec->dev, "Uda134x:uda134x_hw_params CLOCKS %s , SAMPLING RATE :%d\n", __func__, params_rate(params));
    
    	/*UDA1345TS system clock configured for 256*FS */
    	hw_params |= (1<<5); // 100000
    
    	dev_dbg(codec->dev, "%s dai_fmt: %d, params_format:%d\n", __func__,
    		 uda134x->dai_fmt, params_format(params));
    
    	/* set DAI format and word length */
    	switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    	case SND_SOC_DAIFMT_I2S:
    		printk(KERN_ERR "Uda134x:uda134x_hw_params UDA1345TS FORMAT SND_SOC_DAIFMT_I2S\n");
    		break;
    	case SND_SOC_DAIFMT_RIGHT_J:
    		switch (params_format(params)) {
    		case SNDRV_PCM_FORMAT_S16_LE:
    			hw_params |= (1<<1);
    			break;
    		case SNDRV_PCM_FORMAT_S18_3LE:
    			hw_params |= (1<<2);
    			break;
    		case SNDRV_PCM_FORMAT_S20_3LE:
    			hw_params |= ((1<<2) | (1<<1));
    			break;
    		default:
    			printk(KERN_ERR "%s unsupported format (right)\n",
    			       __func__);
    			return -EINVAL;
    		}
    		break;
    	case SND_SOC_DAIFMT_LEFT_J:
    		hw_params |= (1<<3);
    		break;
    	default:
    		printk(KERN_ERR "%s unsupported format\n", __func__);
    		return -EINVAL;
    	}
    
    	uda134x_write(codec, UDA134X_STATUS0, hw_params);
    
    	return 0;
    }
    
    static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
    				  int clk_id, unsigned int freq, int dir)
    {
    	struct snd_soc_codec *codec = codec_dai->codec;
    	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
    
    	/* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
    	   because the codec is slave. Of course limitations of the clock
    	   master (the IIS controller) apply.
    	   We'll error out on set_hw_params if it's not OK */
    	if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
    		uda134x->sysclk = freq;
    		return 0;
    	}
    
    	printk(KERN_ERR "%s unsupported sysclk\n", __func__);
    	return -EINVAL;
    }
    
    static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
    			       unsigned int fmt)
    {
    	struct snd_soc_codec *codec = codec_dai->codec;
    	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
    
    	/* codec supports only full slave mode */
    	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
    		printk(KERN_ERR "%s unsupported slave mode\n", __func__);
    		return -EINVAL;
    	}
    
    	/* no support for clock inversion */
    	if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
    		printk(KERN_ERR "%s unsupported clock inversion\n", __func__);
    		return -EINVAL;
    	}
    
    	/* We can't setup DAI format here as it depends on the word bit num */
    	/* so let's just store the value for later */
    	uda134x->dai_fmt = fmt;
    
    	return 0;
    }
    
    static int uda134x_set_bias_level(struct snd_soc_codec *codec,
    				  enum snd_soc_bias_level level)
    {
    	
    	int i;
    	u8 *cache = codec->reg_cache;
    
    	switch (level) {
    	case SND_SOC_BIAS_ON:
    		break;
    	case SND_SOC_BIAS_PREPARE:
    		/* power on */
    		uda134x_write(codec, UDA134X_DATA011, 0xc3);
    		/* Sync reg_cache with the hardware */
    			for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
    				codec->driver->write(codec, i, *cache++);
    
    		break;
    	case SND_SOC_BIAS_STANDBY:
    		break;
    	case SND_SOC_BIAS_OFF:
    		/* power off */
    		uda134x_write(codec, UDA134X_DATA011, 0xc0);
    		break;
    	}
    	codec->dapm.bias_level = level;
    
    	return 0;
    }
    
    static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1",
    					    "Minimum2", "Maximum"};
    static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
    static const char *uda134x_mixmode[] = {"Differential", "Analog1",
    					"Analog2", "Both"};
    
    static const struct soc_enum uda134x_mixer_enum[] = {
    SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting),
    SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph),
    SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode),
    };
    
    static const struct snd_kcontrol_new uda1341_snd_controls[] = {
    SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
    SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0),
    SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1),
    SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1),
    
    SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0),
    SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0),
    
    SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
    SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
    
    SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
    SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
    SOC_ENUM("Input Mux", uda134x_mixer_enum[2]),
    
    SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0),
    SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1),
    SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0),
    
    SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0),
    SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0),
    SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0),
    SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0),
    SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0),
    SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
    };
    
    static const struct snd_kcontrol_new uda1340_snd_controls[] = {
    SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
    
    SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
    SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
    
    SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
    SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
    
    SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
    };
    
    static const struct snd_kcontrol_new uda1345_snd_controls[] = {
    SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
    
    SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
    
    SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
    };
    
    /* UDA1341 has the DAC/ADC power down in STATUS1 */
    static const struct snd_soc_dapm_widget uda1341_dapm_widgets[] = {
    	SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_STATUS1, 0, 0),
    	SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_STATUS1, 1, 0),
    };
    
    /* UDA1340/4/5 has the DAC/ADC pwoer down in DATA0 11 */
    static const struct snd_soc_dapm_widget uda1345_dapm_widgets[] = {
    	SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_DATA011, 0, 0),
    	SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_DATA011, 1, 0),
    };
    
    /* Common DAPM widgets */
    static const struct snd_soc_dapm_widget uda134x_dapm_widgets[] = {
    	
    	SND_SOC_DAPM_INPUT("VINL"), 
    	SND_SOC_DAPM_INPUT("VINR"), 
    	SND_SOC_DAPM_OUTPUT("VOUTL"),
    	SND_SOC_DAPM_OUTPUT("VOUTR"),
    
    };
    
    static const struct snd_soc_dapm_route uda134x_dapm_routes[] = {
    
    	{ "ADC", NULL, "VINL" }, 
    	{ "ADC", NULL, "VINR" }, 
    
    	{ "VOUTL", NULL, "DAC" },
    	{ "VOUTR", NULL, "DAC" },
    
    
    };
    
    static const struct snd_soc_dai_ops uda134x_dai_ops = {
    	.startup	= uda134x_startup,
    	.shutdown	= uda134x_shutdown,
    	.hw_params	= uda134x_hw_params,
    	.digital_mute	= uda134x_mute,
    	.set_sysclk	= uda134x_set_dai_sysclk,
    	.set_fmt	= uda134x_set_dai_fmt,
    };
    
    static struct snd_soc_dai_driver uda134x_dai = {
    	.name = "uda134x-hifi",
    	/* playback capabilities */
    	.playback = {
    		.stream_name = "Playback",
    		.channels_min = 1,
    		.channels_max = 2,
    		.rates = UDA134X_RATES,
    		.formats = UDA134X_FORMATS,
    	},
    	/* capture capabilities */
    	.capture = {
    		.stream_name = "Capture",
    		.channels_min = 1,
    		.channels_max = 2,
    		.rates = UDA134X_RATES,
    		.formats = UDA134X_FORMATS,
    	},
    	/* pcm operations */
    	.ops = &uda134x_dai_ops,
    };
    
    static int uda134x_soc_probe(struct snd_soc_codec *codec)
    {
    	static struct uda134x_platform_data pdata = {
    		.l3 = {
    			.setdat = setdat,
    			.setclk = setclk,
    			.setmode = setmode,
    			.data_hold = 1,
    			.data_setup = 1,
    			.clock_high = 1,
    			.mode_hold = 1,
    			.mode = 1,
    			.mode_setup = 1,
    		},
    	};
    
    
    	struct uda134x_platform_data *pd = &pdata;
    	struct uda134x_priv *uda134x;
    	const struct snd_soc_dapm_widget *widgets;
    	unsigned num_widgets;
    
    	int ret;
    
    	dev_dbg(codec->dev, "Uda134x:uda134x_soc_probe UDA1345TS SoC Stereo Codec probe...!\n");
    
    	uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
    	if (uda134x == NULL)
    		return -ENOMEM;
    	snd_soc_codec_set_drvdata(codec, uda134x);
    
    	codec->control_data = pd;
    
    	uda134x_reset(codec);
    
    	uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
    
    	widgets = uda1345_dapm_widgets;
    	num_widgets = ARRAY_SIZE(uda1345_dapm_widgets);
    
    	ret = snd_soc_dapm_new_controls(&codec->dapm, widgets, num_widgets);
    	if (ret) {
    		printk(KERN_ERR "%s failed to register dapm controls: %d",
    			__func__, ret);
    		kfree(uda134x);
    		return ret;
    	}
    
    	dev_dbg(codec->dev, "Uda134x:uda134x_soc_probe Switching to uda1345_snd_controls\n");
    	ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls,
    					ARRAY_SIZE(uda1345_snd_controls));
    
    	if (ret < 0) {
    		printk(KERN_ERR "Uda134x:uda134x_soc_probe UDA1345TS: failed to register controls\n");
    		kfree(uda134x);
    		return ret;
    	}
    
    	return 0;
    }
    
    /* power down chip */
    static int uda134x_soc_remove(struct snd_soc_codec *codec)
    {
    	struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
    
    	uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
    	uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
    
    	kfree(uda134x);
    	return 0;
    }
    
    #if defined(CONFIG_PM)
    static int uda134x_soc_suspend(struct snd_soc_codec *codec)
    {
    	uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
    	uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
    	return 0;
    }
    
    static int uda134x_soc_resume(struct snd_soc_codec *codec)
    {
    	uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
    	uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
    	return 0;
    }
    #else
    #define uda134x_soc_suspend NULL
    #define uda134x_soc_resume NULL
    #endif /* CONFIG_PM */
    
    static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
    	.probe =        uda134x_soc_probe,
    	.remove =       uda134x_soc_remove,
    	.suspend =      uda134x_soc_suspend,
    	.resume =       uda134x_soc_resume,
    	.reg_cache_size = sizeof(uda134x_reg),
    	.reg_word_size = sizeof(u8),
    	.reg_cache_default = uda134x_reg,
    	.reg_cache_step = 1,
    	.read = uda134x_read_reg_cache,
    	.write = uda134x_write,
    	.set_bias_level = uda134x_set_bias_level,
    	.dapm_widgets = uda134x_dapm_widgets,
    	.num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets),
    	.dapm_routes = uda134x_dapm_routes,
    	.num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes),
    };
    
    static int am335x_uda134x_setup_pin(int pin, char *fun)
    {
    	if (gpio_request(pin, "am335x_uda134x") < 0) {
    		printk(KERN_ERR "AM335X_UDA134X SoC Audio: "
    		       "l3 %s pin already in use", fun);
    		return -EBUSY;
    	}
    	gpio_direction_output(pin, 1); 
    	return 0;
    }
    static int uda134x_codec_probe(struct platform_device *pdev)
    {
       
    	if (am335x_uda134x_setup_pin(L3_DATA,  "data") < 0)
    		return -EBUSY;
    	if (am335x_uda134x_setup_pin(L3_CLOCK, "clk") < 0) {
    		gpio_free(L3_DATA);
    		return -EBUSY;
    	}
    	if (am335x_uda134x_setup_pin(L3_MODE, "mode") < 0) {
    		gpio_free(L3_DATA);
    		gpio_free(L3_CLOCK);
    		return -EBUSY;
    	}
    	return snd_soc_register_codec(&pdev->dev,
    			&soc_codec_dev_uda134x, &uda134x_dai, 1);
    }
    
    static int uda134x_codec_remove(struct platform_device *pdev)
    {
    	snd_soc_unregister_codec(&pdev->dev);
    	gpio_free(L3_DATA);
    	gpio_free(L3_CLOCK); 
    	gpio_free(L3_MODE); 
    	return 0;
    }
    
    #if defined(CONFIG_OF)
    static const struct of_device_id uda134x_dt_ids[] = {
    	{ .compatible = "ti,uda134x" },
    	{ }
    };
    MODULE_DEVICE_TABLE(of, uda134x_dt_ids);
    #endif
    static struct platform_driver uda134x_codec_driver = {
    	.driver = {
    		.name = "uda134x-codec",
    		.owner = THIS_MODULE,
    		.of_match_table = of_match_ptr(uda134x_dt_ids),
    	},
    	.probe = uda134x_codec_probe,
    	.remove = uda134x_codec_remove,
    };
    
    module_platform_driver(uda134x_codec_driver);
    
    MODULE_DESCRIPTION("UDA1345TS ALSA soc codec driver");
    MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>, Srinivasan S (srinivasan.s@tataelxsi.co.in)");
    MODULE_LICENSE("GPL");
    
    davinci-evm.c
    /*
     * ASoC driver for TI DAVINCI EVM platform
     *
     * Author:      Vladimir Barinov, <vbarinov@embeddedalley.com>
     * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.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/module.h>
    #include <linux/moduleparam.h>
    #include <linux/timer.h>
    #include <linux/interrupt.h>
    #include <linux/platform_device.h>
    #include <linux/platform_data/edma.h>
    #include <linux/i2c.h>
    #include <linux/of_platform.h>
    #include <linux/clk.h>
    #include <sound/core.h>
    #include <sound/pcm.h>
    #include <sound/soc.h>
    #include <sound/pcm_params.h>
    
    
    #include <asm/dma.h>
    #include <asm/mach-types.h>
    
    #include <linux/edma.h>
    
    #include "davinci-pcm.h"
    #include "davinci-i2s.h"
    
    #include <linux/gpio.h>
    #include <linux/kernel.h>
    #include <linux/platform_device.h>
    #include <linux/slab.h>
    #include <linux/of.h>
    #include <linux/of_gpio.h>
    #include <linux/of_device.h>
    #include <linux/of_platform.h>
    #include <linux/regmap.h>
    #include <linux/pinctrl/consumer.h>
    #include <sound/uda134x.h>
    #include <sound/l3.h>
    #include "uda134x.h"
    
    
    /* Common DAPM widgets */
    static const struct snd_soc_dapm_widget uda134x_dapm_widgets[] = {
    
    	SND_SOC_DAPM_INPUT("VINL"), 
    	SND_SOC_DAPM_INPUT("VINR"), 
    	
    	SND_SOC_DAPM_OUTPUT("VOUTL"),
    	SND_SOC_DAPM_OUTPUT("VOUTR"),
    
    };
    
    static const struct snd_soc_dapm_route uda134x_dapm_routes[] = {
    
    	{ "ADC", NULL, "VINL" },
    	{ "ADC", NULL, "VINR" }, 
    	
    	{ "VOUTL", NULL, "DAC" },
    	{ "VOUTR", NULL, "DAC" },
    
    };
    
    struct snd_soc_card_drvdata_davinci {
    	struct clk *mclk;
    	unsigned sysclk;
    };
    
    static unsigned int evm_get_bclk(struct snd_pcm_hw_params *params)
    {
    	int sample_size = snd_pcm_format_width(params_format(params));
    	int rate = params_rate(params);
    	int channels = params_channels(params);
    
    	return sample_size * channels * rate;
    }
    
    static int evm_startup(struct snd_pcm_substream *substream)
    {
    	struct snd_soc_pcm_runtime *rtd = substream->private_data;
    	struct snd_soc_card *soc_card = rtd->card;
    	struct snd_soc_card_drvdata_davinci *drvdata =
    		snd_soc_card_get_drvdata(soc_card);
    
    	if (drvdata->mclk)
    	{
    		dev_dbg(soc_card->dev, "davinci-evm:evm_startup MCLK: %d", clk_prepare_enable(drvdata->mclk));
    		return clk_prepare_enable(drvdata->mclk);
        }
    
    	return 0;
    }
    
    static int dra7xx_evm_startup(struct snd_pcm_substream *substream)
    {
    	snd_pcm_hw_constraint_minmax(substream->runtime,
    				     SNDRV_PCM_HW_PARAM_RATE, 44100, 44100);
    
    	return evm_startup(substream);
    }
    
    static int dra7xx_evm_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 snd_soc_card *soc_card = rtd->card;
    	struct snd_soc_card_drvdata_davinci *drvdata =
    		snd_soc_card_get_drvdata(soc_card);
    	int ret;
    
    	/* Set MCLK as clock source for tlv320aic3106 */
    	ret = snd_soc_dai_set_sysclk(codec_dai, 0, drvdata->sysclk,
    				     SND_SOC_CLOCK_IN);
    	if (ret < 0)
    		return ret;
    
    	/* Set McASP sysclk from AHCLKX sourced from ATL */
    	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, drvdata->sysclk,
    				     SND_SOC_CLOCK_IN);
    	return ret;
    }
    
    static void evm_shutdown(struct snd_pcm_substream *substream)
    {
    	struct snd_soc_pcm_runtime *rtd = substream->private_data;
    	struct snd_soc_card *soc_card = rtd->card;
    	struct snd_soc_card_drvdata_davinci *drvdata =
    		snd_soc_card_get_drvdata(soc_card);
    
    	dev_dbg(soc_card->dev, "davinci-evm:evm_shutdown ENETERED \n");
    	if (drvdata->mclk)
    		clk_disable_unprepare(drvdata->mclk);
    }
    
    static int evm_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 snd_soc_card *soc_card = rtd->card;
    	int ret = 0;
    	unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
    			   snd_soc_card_get_drvdata(soc_card))->sysclk;
    
    	/* set the codec system clock */
    	ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
    	if (ret < 0)
    		return ret;
    
    	/* set the CPU system clock */
    	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
    	if (ret < 0)
    		return ret;
    
    	return 0;
    }
    
    static int evm_uda134x_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 snd_soc_card *soc_card = rtd->card;
    	int ret = 0;
    	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 rate = params_rate(params) ;
    
    	/* set SYSCLK / fs ratio */
    	switch (params_rate(params)) {
    	case 8000:
    		dev_dbg(soc_card->dev, "davinci-evm:evm_uda134x_hw_params SCALING MASTER CLOCK FOR 8000HZ\n");
    		ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 0xc);  // 24Mhz/2048000 (256*8Khz) = 11.71875 =12 ( in dec)
    		sysclk = 2048000; /*(256*8Khz)*/
    		break;
    	case 16000:
    		dev_dbg(soc_card->dev, "davinci-evm:evm_uda134x_hw_params SCALING MASTER CLOCK FOR 16000HZ\n");
    		ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 0x6);  // 24Mhz/(256*16Khz) = 5.859375 = 6
    		sysclk = 4096000; /*(256*16Khz)*/
    		break;
    	case 32000:
    		dev_dbg(soc_card->dev, "davinci-evm:evm_uda134x_hw_params SCALING MASTER CLOCK FOR 32000HZ\n");
    		ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 0x3);  // 24Mhz/(256*32Khz) = 2.9296 = 3
    		sysclk = 8192000; /*(256*16Khz)*/
    		break;
    	case 44100:
    		dev_dbg(soc_card->dev, "davinci-evm:evm_uda134x_hw_params  SCALING MASTER CLOCK FOR 44100HZ\n");
    		ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 0x2);  // 24000000hz/(256*44100hz) = 240000/112896 = 2.12585 = 2
    		sysclk = 11289600;
    		break;
    	case 48000:
    		dev_dbg(soc_card->dev, "davinci-evm:evm_uda134x_hw_params SCALING MASTER CLOCK FOR 48000HZ\n");
    		ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 2); 
    		sysclk = 12288000;
    		break;
    	default:
    		dev_dbg(soc_card->dev, "davinci-evm:evm_uda134x_hw_params unsupported MASTER CLOCK\n");
    		return -EINVAL;
    	}
    
    	dev_dbg(soc_card->dev, "davinci-evm:evm_uda134x_hw_params SAMPLING RATE=%d\n", rate);
    	dev_dbg(soc_card->dev, "davinci-evm:evm_uda134x_hw_params SYSCLK=%d\n", sysclk);
    	dev_dbg(soc_card->dev, "davinci-evm:evm_uda134x_hw_params BCLK FREQ=%d\n", bclk_freq);
    	dev_dbg(soc_card->dev, "davinci-evm:evm_uda134x_hw_params SYSCLK/BCLK_FREQ =%d\n", sysclk/bclk_freq);
    
    	ret = snd_soc_dai_set_clkdiv(cpu_dai, 1, sysclk/bclk_freq);  
    	if (ret < 0) {
    		dev_err(soc_card->dev, "davinci-evm:evm_uda134x_hw_params BCLK can't set CPU DAI clock divider %d\n",
    			ret);
    		return ret;
    	}
    
    		/* set the CPU system clock */
    	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
    	if (ret < 0)
    		dev_err(soc_card->dev, "can't set CPU DAI sysclk %d\n", ret);
    
    
    	/* Set MCLK as clock source for UDA1345TS ie., set the codec system clock */
    	ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT); 
    	if (ret < 0)
    		return ret;
    
    	return 0;
    
    }
    /* If changing sample format the tda998x configuration (REG_CTS_N) needs
       to be changed. */
    #define TDA998X_SAMPLE_FORMAT SNDRV_PCM_FORMAT_S32_LE
    static int evm_tda998x_startup(struct snd_pcm_substream *substream)
    {
    	struct snd_pcm_runtime *runtime = substream->runtime;
    	struct snd_mask *fmt = constrs_mask(&runtime->hw_constraints,
    					    SNDRV_PCM_HW_PARAM_FORMAT);
    	snd_mask_none(fmt);
    	snd_mask_set(fmt, TDA998X_SAMPLE_FORMAT);
    
    	return evm_startup(substream);
    }
    
    static int evm_tda998x_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_card *soc_card = rtd->card;
    	struct snd_soc_card_drvdata_davinci *drvdata =
    		snd_soc_card_get_drvdata(soc_card);
    
    	return snd_soc_dai_set_sysclk(cpu_dai, 0, drvdata->sysclk,
    				      SND_SOC_CLOCK_IN);
    }
    
    static struct snd_soc_ops evm_ops = {
    	.startup = evm_startup,
    	.shutdown = evm_shutdown,
    	.hw_params = evm_hw_params,
    };
    
    static struct snd_soc_ops uda134x_ops = {
    	.startup = evm_startup,
    	.shutdown = evm_shutdown,
    	.hw_params = evm_uda134x_hw_params,
    };
    
    static struct snd_soc_ops evm_tda998x_ops = {
    	.startup = evm_tda998x_startup,
    	.shutdown = evm_shutdown,
    	.hw_params = evm_tda998x_hw_params,
    };
    
    static struct snd_soc_ops dra7xx_ops = {
    	.startup = dra7xx_evm_startup,
    	.shutdown = evm_shutdown,
    	.hw_params = dra7xx_evm_hw_params,
    };
    
    /* davinci-evm machine dapm widgets */
    static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
    	SND_SOC_DAPM_HP("Headphone Jack", NULL),
    	SND_SOC_DAPM_LINE("Line Out", NULL),
    	SND_SOC_DAPM_MIC("Mic Jack", NULL),
    	SND_SOC_DAPM_LINE("Line In", NULL),
    };
    
    /* davinci-evm machine audio_mapnections to the codec pins */
    static const struct snd_soc_dapm_route audio_map[] = {
    	/* Headphone connected to HPLOUT, HPROUT */
    	{"Headphone Jack", NULL, "HPLOUT"},
    	{"Headphone Jack", NULL, "HPROUT"},
    
    	/* Line Out connected to LLOUT, RLOUT */
    	{"Line Out", NULL, "LLOUT"},
    	{"Line Out", NULL, "RLOUT"},
    
    	/* Mic connected to (MIC3L | MIC3R) */
    	{"MIC3L", NULL, "Mic Bias"},
    	{"MIC3R", NULL, "Mic Bias"},
    	{"Mic Bias", NULL, "Mic Jack"},
    
    	/* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
    	{"LINE1L", NULL, "Line In"},
    	{"LINE2L", NULL, "Line In"},
    	{"LINE1R", NULL, "Line In"},
    	{"LINE2R", NULL, "Line In"},
    };
    
    /* Logic for a aic3x as connected on a davinci-evm */
    static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
    {
    	struct snd_soc_card *card = rtd->card;
    	struct snd_soc_codec *codec = rtd->codec;
    	struct device_node *np = card->dev->of_node;
    	int ret;
    
    	/* Add davinci-evm specific widgets */
    	snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets,
    				  ARRAY_SIZE(aic3x_dapm_widgets));
    
    	if (np) {
    		ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing");
    		if (ret)
    			return ret;
    	} else {
    		/* Set up davinci-evm specific audio path audio_map */
    		snd_soc_dapm_add_routes(&card->dapm, audio_map,
    					ARRAY_SIZE(audio_map));
    	}
    
    	/* not connected */
    	snd_soc_dapm_nc_pin(&codec->dapm, "MONO_LOUT");
    	snd_soc_dapm_nc_pin(&codec->dapm, "HPLCOM");
    	snd_soc_dapm_nc_pin(&codec->dapm, "HPRCOM");
    
    	return 0;
    }
    
    static int evm_uda134x_init(struct snd_soc_pcm_runtime *rtd)
    {
    
    	struct snd_soc_card *card = rtd->card;
    	struct snd_soc_codec *codec = rtd->codec;
    	struct device_node *np = card->dev->of_node;
    	int ret;
    
    	snd_soc_dapm_new_controls(&card->dapm, uda134x_dapm_widgets,
    				  ARRAY_SIZE(uda134x_dapm_widgets));
    
    	if (np) {
    		
    		ret = snd_soc_of_parse_audio_routing(card,
    						     "ti,audio-routing");
    		if (ret)
    		{
    			dev_err(card->dev, "davinci-evm:evm_uda134x_init DAPM ROUTING BASED ON DTS IS FAILURE\n");
    			return ret;
    		}
    
    	} 
    
    	snd_soc_dapm_enable_pin(&codec->dapm, "VINL"),
    	snd_soc_dapm_enable_pin(&codec->dapm, "VINR"),
    
    	snd_soc_dapm_enable_pin(&codec->dapm, "VOUTL");
    	snd_soc_dapm_enable_pin(&codec->dapm, "VOUTR");
    	
    
    	return 0;
    }
    
    static const struct snd_soc_dapm_widget tda998x_dapm_widgets[] = {
    	SND_SOC_DAPM_OUTPUT("HDMI Out"),
    };
    
    
    
    static int evm_tda998x_init(struct snd_soc_pcm_runtime *rtd)
    {
    	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
    	struct snd_soc_dapm_context *dapm = &rtd->codec->dapm;
    	struct snd_soc_card *soc_card = rtd->card;
    	int ret;
    
    	ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 1);
    	if (ret < 0)
    		return ret;
    
    	snd_soc_dapm_new_controls(dapm, tda998x_dapm_widgets,
    				  ARRAY_SIZE(tda998x_dapm_widgets));
    
    	ret = snd_soc_of_parse_audio_routing(soc_card, "ti,audio-routing");
    
    	/* not connected */
    	snd_soc_dapm_disable_pin(dapm, "RX");
    
    	/* always connected */
    	snd_soc_dapm_enable_pin(dapm, "HDMI Out");
    
    	return 0;
    }
    /* davinci-evm digital audio interface glue - connects codec <--> CPU */
    static struct snd_soc_dai_link dm6446_evm_dai = {
    	.name = "TLV320AIC3X",
    	.stream_name = "AIC3X",
    	.cpu_dai_name = "davinci-mcbsp",
    	.codec_dai_name = "tlv320aic3x-hifi",
    	.codec_name = "tlv320aic3x-codec.1-001b",
    	.platform_name = "davinci-mcbsp",
    	.init = evm_aic3x_init,
    	.ops = &evm_ops,
    	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
    		   SND_SOC_DAIFMT_IB_NF,
    };
    
    static struct snd_soc_dai_link dm355_evm_dai = {
    	.name = "TLV320AIC3X",
    	.stream_name = "AIC3X",
    	.cpu_dai_name = "davinci-mcbsp.1",
    	.codec_dai_name = "tlv320aic3x-hifi",
    	.codec_name = "tlv320aic3x-codec.1-001b",
    	.platform_name = "davinci-mcbsp.1",
    	.init = evm_aic3x_init,
    	.ops = &evm_ops,
    	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
    		   SND_SOC_DAIFMT_IB_NF,
    };
    
    static struct snd_soc_dai_link dm365_evm_dai = {
    #ifdef CONFIG_SND_DM365_AIC3X_CODEC
    	.name = "TLV320AIC3X",
    	.stream_name = "AIC3X",
    	.cpu_dai_name = "davinci-mcbsp",
    	.codec_dai_name = "tlv320aic3x-hifi",
    	.codec_name = "tlv320aic3x-codec.1-0018",
    	.platform_name = "davinci-mcbsp",
    	.init = evm_aic3x_init,
    	.ops = &evm_ops,
    	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
    		   SND_SOC_DAIFMT_IB_NF,
    #elif defined(CONFIG_SND_DM365_VOICE_CODEC)
    	.name = "Voice Codec - CQ93VC",
    	.stream_name = "CQ93",
    	.cpu_dai_name = "davinci-vcif",
    	.codec_dai_name = "cq93vc-hifi",
    	.codec_name = "cq93vc-codec",
    	.platform_name = "davinci-vcif",
    #endif
    };
    
    static struct snd_soc_dai_link dm6467_evm_dai[] = {
    	{
    		.name = "TLV320AIC3X",
    		.stream_name = "AIC3X",
    		.cpu_dai_name= "davinci-mcasp.0",
    		.codec_dai_name = "tlv320aic3x-hifi",
    		.platform_name = "davinci-mcasp.0",
    		.codec_name = "tlv320aic3x-codec.0-001a",
    		.init = evm_aic3x_init,
    		.ops = &evm_ops,
    		.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
    			   SND_SOC_DAIFMT_IB_NF,
    	},
    	{
    		.name = "McASP",
    		.stream_name = "spdif",
    		.cpu_dai_name= "davinci-mcasp.1",
    		.codec_dai_name = "dit-hifi",
    		.codec_name = "spdif_dit",
    		.platform_name = "davinci-mcasp.1",
    		.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
    			   SND_SOC_DAIFMT_IB_NF,
    	},
    };
    
    static struct snd_soc_dai_link da830_evm_dai = {
    	.name = "TLV320AIC3X",
    	.stream_name = "AIC3X",
    	.cpu_dai_name = "davinci-mcasp.1",
    	.codec_dai_name = "tlv320aic3x-hifi",
    	.codec_name = "tlv320aic3x-codec.1-0018",
    	.platform_name = "davinci-mcasp.1",
    	.init = evm_aic3x_init,
    	.ops = &evm_ops,
    	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
    		   SND_SOC_DAIFMT_IB_NF,
    };
    
    static struct snd_soc_dai_link da850_evm_dai = {
    	.name = "TLV320AIC3X",
    	.stream_name = "AIC3X",
    	.cpu_dai_name= "davinci-mcasp.0",
    	.codec_dai_name = "tlv320aic3x-hifi",
    	.codec_name = "tlv320aic3x-codec.1-0018",
    	.platform_name = "davinci-mcasp.0",
    	.init = evm_aic3x_init,
    	.ops = &evm_ops,
    	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
    		   SND_SOC_DAIFMT_IB_NF,
    };
    
    /* davinci dm6446 evm audio machine driver */
    /*
     * ASP0 in DM6446 EVM is clocked by U55, as configured by
     * board-dm644x-evm.c using GPIOs from U18.  There are six
     * options; here we "know" we use a 48 KHz sample rate.
     */
    static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = {
    	.sysclk = 12288000,
    };
    
    static struct snd_soc_card dm6446_snd_soc_card_evm = {
    	.name = "DaVinci DM6446 EVM",
    	.owner = THIS_MODULE,
    	.dai_link = &dm6446_evm_dai,
    	.num_links = 1,
    	.drvdata = &dm6446_snd_soc_card_drvdata,
    };
    
    /* davinci dm355 evm audio machine driver */
    /* ASP1 on DM355 EVM is clocked by an external oscillator */
    static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = {
    	.sysclk = 27000000,
    };
    
    static struct snd_soc_card dm355_snd_soc_card_evm = {
    	.name = "DaVinci DM355 EVM",
    	.owner = THIS_MODULE,
    	.dai_link = &dm355_evm_dai,
    	.num_links = 1,
    	.drvdata = &dm355_snd_soc_card_drvdata,
    };
    
    /* davinci dm365 evm audio machine driver */
    static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = {
    	.sysclk = 27000000,
    };
    
    static struct snd_soc_card dm365_snd_soc_card_evm = {
    	.name = "DaVinci DM365 EVM",
    	.owner = THIS_MODULE,
    	.dai_link = &dm365_evm_dai,
    	.num_links = 1,
    	.drvdata = &dm365_snd_soc_card_drvdata,
    };
    
    /* davinci dm6467 evm audio machine driver */
    static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = {
    	.sysclk = 27000000,
    };
    
    static struct snd_soc_card dm6467_snd_soc_card_evm = {
    	.name = "DaVinci DM6467 EVM",
    	.owner = THIS_MODULE,
    	.dai_link = dm6467_evm_dai,
    	.num_links = ARRAY_SIZE(dm6467_evm_dai),
    	.drvdata = &dm6467_snd_soc_card_drvdata,
    };
    
    static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = {
    	.sysclk = 24576000,
    };
    
    static struct snd_soc_card da830_snd_soc_card = {
    	.name = "DA830/OMAP-L137 EVM",
    	.owner = THIS_MODULE,
    	.dai_link = &da830_evm_dai,
    	.num_links = 1,
    	.drvdata = &da830_snd_soc_card_drvdata,
    };
    
    static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = {
    	.sysclk = 24576000,
    };
    
    static struct snd_soc_card da850_snd_soc_card = {
    	.name = "DA850/OMAP-L138 EVM",
    	.owner = THIS_MODULE,
    	.dai_link = &da850_evm_dai,
    	.num_links = 1,
    	.drvdata = &da850_snd_soc_card_drvdata,
    };
    
    #if defined(CONFIG_OF)
    
    /*
     * 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_tlv320aic3x = {
    	.name		= "TLV320AIC3X",
    	.stream_name	= "AIC3X",
    	.codec_dai_name	= "tlv320aic3x-hifi",
    	.ops            = &evm_ops,
    	.init           = evm_aic3x_init,
    	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
    		   SND_SOC_DAIFMT_IB_NF,
    };
    
    static struct snd_soc_dai_link evm_dai_tda998x_hdmi = {
    	.name		= "NXP TDA998x HDMI Chip",
    	.stream_name	= "HDMI",
    	.codec_dai_name	= "hdmi-hifi",
    	.ops		= &evm_tda998x_ops,
    	.init           = evm_tda998x_init,
    	.dai_fmt	= (SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S |
    			   SND_SOC_DAIFMT_IB_NF),
    };
    
    static struct snd_soc_dai_link dra7xx_evm_link = {
    	.name		= "TLV320AIC3X",
    	.stream_name	= "AIC3X",
    	.codec_dai_name	= "tlv320aic3x-hifi",
    	.ops            = &dra7xx_ops,
    	.init           = evm_aic3x_init,
    	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS |
    		   SND_SOC_DAIFMT_IB_NF,
    };
    
    static struct snd_soc_dai_link evm_dai_uda134x = {
    	.name		= "UDA134x",
    	.stream_name	= "UDA134x",
    	.codec_dai_name	= "uda134x-hifi",
    	.ops = &uda134x_ops,
    	.init		= evm_uda134x_init,
    	.dai_fmt	= (SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S |
    			   SND_SOC_DAIFMT_NB_NF),
    };
    
    static const struct of_device_id davinci_evm_dt_ids[] = {
    
    	{
    		.compatible = "ti,uda134x-audio-codec",
    		.data = &evm_dai_uda134x,
    	},
    	{
    		.compatible = "ti,da830-evm-audio",
    		.data = &evm_dai_tlv320aic3x,
    	},
    	{
    		.compatible = "ti,beaglebone-black-audio",
    		.data = &evm_dai_tda998x_hdmi,
    	},
    	{
    		.compatible = "ti,dra7xx-evm-audio",
    		.data = (void *) &dra7xx_evm_link,
    	},
    	{ /* sentinel */ }
    };
    MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);
    
    /* davinci evm audio machine driver */
    static struct snd_soc_card evm_soc_card = {
    	.owner = THIS_MODULE,
    	.num_links = 1,
    };
    
    static int davinci_evm_probe(struct platform_device *pdev)
    {
    	struct device_node *np = pdev->dev.of_node;
    	const struct of_device_id *match =
    		of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
    	struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data;
    	struct snd_soc_card_drvdata_davinci *drvdata = NULL;
    	struct clk *mclk;
    	int ret = 0;
    
    	evm_soc_card.dai_link = dai;
    
    	dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0);
    	if (!dai->codec_of_node)
    	{
    		dev_err(&pdev->dev, "davinci-evm:davinci_evm_probe EVM PROBE IS FAILUREEE ti,audio-codec \n");
    		return -EINVAL;
    
    	}
    
    	dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0);
    	if (!dai->cpu_of_node)
    	{
    		dev_err(&pdev->dev, "davinci-evm:davinci_evm_probe IS FAILURE ti,mcasp-controller\n");
    		return -EINVAL;
    	}
    
    	/* Only set the platform_of_node if the platform_name is not set */
    	if (!dai->platform_name)
    		dai->platform_of_node = dai->cpu_of_node;
    
    	evm_soc_card.dev = &pdev->dev;
    	ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
    	if (ret)
    	{
    		dev_err(&pdev->dev, "davinci-evm:davinci_evm_probe  ti,model is failure\n");
    		return ret;
    
    	}
    
    	mclk = devm_clk_get(&pdev->dev, "mclk");
    	if (PTR_ERR(mclk) == -EPROBE_DEFER) {
    		return -EPROBE_DEFER;
    	} else if (IS_ERR(mclk)) {
    		dev_dbg(&pdev->dev, "mclk not found.\n");
    		mclk = NULL;
    	}
    
    	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
    	if (!drvdata)
    	{
    		dev_err(&pdev->dev, "davinci-evm:davinci_evm_probe codec drvdata failure\n");
    		return -ENOMEM;
    	}	
    
    	drvdata->mclk = mclk;
    
    	ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk);
    
    	if (ret < 0) {
    		if (!drvdata->mclk) {
    			dev_err(&pdev->dev,
    				"No clock or clock rate defined.\n");
    			return -EINVAL;
    		}
    		drvdata->sysclk = clk_get_rate(drvdata->mclk);
    	} else if (drvdata->mclk) {
    		unsigned int requestd_rate = drvdata->sysclk;
    		clk_set_rate(drvdata->mclk, drvdata->sysclk);
    		drvdata->sysclk = clk_get_rate(drvdata->mclk);
    		if (drvdata->sysclk != requestd_rate)
    			dev_warn(&pdev->dev,
    				 "Could not get requested rate %u using %u.\n",
    				 requestd_rate, drvdata->sysclk);
    	}
    
    	snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
    	ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);
    
    	if (ret)
    		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
    
    	return ret;
    }
    
    static int davinci_evm_remove(struct platform_device *pdev)
    {
    	struct snd_soc_card *card = platform_get_drvdata(pdev);
    
    	snd_soc_unregister_card(card);
    
    	return 0;
    }
    
    static struct platform_driver davinci_evm_driver = {
    	.probe		= davinci_evm_probe,
    	.remove		= davinci_evm_remove,
    	.driver		= {
    		.name	= "davinci_evm",
    		.owner	= THIS_MODULE,
    		.pm	= &snd_soc_pm_ops,
    		.of_match_table = of_match_ptr(davinci_evm_dt_ids),
    	},
    };
    #endif
    
    static struct platform_device *evm_snd_device;
    
    static int __init evm_init(void)
    {
    	struct snd_soc_card *evm_snd_dev_data;
    	int index;
    	int ret;
    
    	/*
    	 * If dtb is there, the devices will be created dynamically.
    	 * Only register platfrom driver structure.
    	 */
    #if defined(CONFIG_OF)
    	if (of_have_populated_dt())
    		return platform_driver_register(&davinci_evm_driver);
    #endif
    
    	if (machine_is_davinci_evm()) {
    		evm_snd_dev_data = &dm6446_snd_soc_card_evm;
    		index = 0;
    	} else if (machine_is_davinci_dm355_evm()) {
    		evm_snd_dev_data = &dm355_snd_soc_card_evm;
    		index = 1;
    	} else if (machine_is_davinci_dm365_evm()) {
    		evm_snd_dev_data = &dm365_snd_soc_card_evm;
    		index = 0;
    	} else if (machine_is_davinci_dm6467_evm()) {
    		evm_snd_dev_data = &dm6467_snd_soc_card_evm;
    		index = 0;
    	} else if (machine_is_davinci_da830_evm()) {
    		evm_snd_dev_data = &da830_snd_soc_card;
    		index = 1;
    	} else if (machine_is_davinci_da850_evm()) {
    		evm_snd_dev_data = &da850_snd_soc_card;
    		index = 0;
    	} else
    		return -EINVAL;
    
    	evm_snd_device = platform_device_alloc("soc-audio", index);
    	if (!evm_snd_device)
    		return -ENOMEM;
    
    	platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
    	ret = platform_device_add(evm_snd_device);
    	if (ret)
    		platform_device_put(evm_snd_device);
    
    	return ret;
    }
    
    static void __exit evm_exit(void)
    {
    #if defined(CONFIG_OF)
    	if (of_have_populated_dt()) {
    		platform_driver_unregister(&davinci_evm_driver);
    		return;
    	}
    #endif
    
    	platform_device_unregister(evm_snd_device);
    }
    
    module_init(evm_init);
    module_exit(evm_exit);
    
    MODULE_AUTHOR("Vladimir Barinov, Srinivasan S");
    MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
    MODULE_LICENSE("GPL");
    

    Kindly do the needful as early as possible,

    Many Thanks in advance

  • Dear Yordan,

    Could you please provide any inputs w.r.t the above query

    Kindly do the needful

    Thanks in advance
  • could you pls provide any inputs w.r.t this issue, am awaiting for your replies