[alsa-devel] wm8974 and sam9g45 atmel

Sangilikumar sangilikumar.muniyandi at marudham.co.in
Fri Jul 11 08:01:41 CEST 2014


Mark Brown <broonie <at> opensource.wolfsonmicro.com> writes:

> 
> On Fri, Jun 17, 2011 at 05:03:01PM +0200, Michele Da Rold wrote:
> 
> > it's better to use wm8974 like master? because I have see that the
> > atmel ssc is not so good generating clocks....
> 
> Probably in your system, yes.  The most important thing from an audio
> performance point of view is that the clocks are all derived from the
> same clock source - if this is like other Atmel systems then you need to
> make the CODEC clock master on the audio bus as the MCLK output from the
> CPU is not synchronous with the audio clocks.
> 

Me too working with WM8974 codec and integrating with AM1808 processor but i 
while i'm playing i can't hear the sound from speaker.

Configured the WM8974 as slave and connected the MCLK with 24.5MHz crystal.
I can probe the signal at WCLK,BCLK and MCLK while playing audio but can't 
hear the sound from speaker.

My modified machine driver is 


#define AUDIO_FORMAT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 
SND_SOC_DAIFMT_CBS_CFS )

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;
	int ret = 0;
	unsigned sysclk;

	/* ASP1 on DM355 EVM is clocked by an external oscillator */
	if (machine_is_davinci_dm355_evm() || 
machine_is_davinci_dm6467_evm() ||
	    machine_is_davinci_dm365_evm())
		sysclk = 27000000;

	/* 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.
	 */
	if (machine_is_omapl138_lcdkboard())
	    sysclk = 24576000;
	else
		return -EINVAL;

	/* set codec DAI configuration */
	ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
	if (ret < 0)
		return ret;

	/* set cpu DAI configuration */
	ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
	if (ret < 0)
		return ret;

	
	ret = snd_soc_dai_set_pll(codec_dai, 0, 1, 24576000,0);
	if (ret) {
		printk( ">>>couldn't set pll: %d\n", ret);
		return ret;
	}
	
	return 0;
}

static int evm_spdif_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;

	/* set cpu DAI configuration */
	return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
}

/*
 * Since da850_sdi_shutdown() and da850_sdi_trigger() are invoked in 
interrupt 
 * context, they can't directly invoke da850_sdi_mute(), since 
da850_sdi_mute()
 * involves i2c communications (which is slow and can wait).  So, use the 
workqueue
 * mechanism to 'finish' processing.
 */
#ifdef CONFIG_MACH_DAVINCI_DA850_SDI
extern int da850_sdi_mute(int state);
static void muteTheOutputs( struct work_struct * work )
{
	da850_sdi_mute( 1 );
}
DECLARE_WORK( muteWorkElement, muteTheOutputs );

static void unmuteTheOutputs( struct work_struct * work )
{
	da850_sdi_mute( 0 );
}
DECLARE_WORK( unmuteWorkElement, unmuteTheOutputs );
 

static int da850_sdi_trigger(struct snd_pcm_substream *stream, int cmd)
{
    switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
	case SNDRV_PCM_TRIGGER_RESUME:
	    schedule_work( &unmuteWorkElement );
	    break;

	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	    schedule_work( &muteWorkElement );
	    break;
    }

    return 0;
}

static struct snd_soc_ops da850_sdi_ops = {
	.hw_params = evm_hw_params,
	.trigger = da850_sdi_trigger
};
#endif
static struct snd_soc_ops evm_ops = {
	.hw_params = evm_hw_params,
};

static struct snd_soc_ops evm_spdif_ops = {
	.hw_params = evm_spdif_hw_params,
};

static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
	SND_SOC_DAPM_MIC("Mic Jack", NULL),
	SND_SOC_DAPM_SPK("Ext Spk", NULL),
};
/* davinci-evm machine audio_mapnections to the codec pins */

static const struct snd_soc_dapm_route audio_map[] = {
	 
	/* Speaker output mixer */
 	{"Speaker Mixer", "PCM Playback Switch", "DAC"},
 	{"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
 	{"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"}, 
	/* speaker connected to SPKOUTP */ 
	{"SpkN Out", NULL, "Speaker Mixer"}, 
	{"SpkP Out", NULL, "Speaker Mixer"}, 
	{"SPKOUTN", NULL, "SpkN Out"}, 
	{"SPKOUTP", NULL, "SpkP Out"},  
	/* Input PGA */ 
	{"Input PGA", "Aux Switch", "Aux Input"}, 
	{"Input PGA", "MicN Switch", "MICN"}, 
	{"Input PGA", "MicP Switch", "MICP"}, 
};
/* Logic for a aic3x as connected on a davinci-evm */
static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_codec *codec = rtd->codec;
	struct snd_soc_dapm_context *dapm = &codec->dapm;

	/* Add davinci-evm specific widgets */
	snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
				  ARRAY_SIZE(aic3x_dapm_widgets));

	/* Set up davinci-evm specific audio path audio_map */
	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
	snd_soc_dapm_enable_pin(dapm, "Ext Spk");

	return 0;
}

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,
};

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 (machine_is_omapl138_lcdkboard()) {
		printk("LCDK HAWK board");
		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)
{
	platform_device_unregister(evm_snd_device);
}

module_init(evm_init);
module_exit(evm_exit);
root at omapl138-lcdk:~# amixer cset numid=61 1
numid=61,iface=MIXER,name='Speaker Mixer PCM Playback Switch'
  ; type=BOOLEAN,access=rw------,values=1
  : values=on
root at omapl138-lcdk:~# amixer cset numid=46,iface=MIXER,name='Speaker 
Playback Vo
lume' 63
numid=46,iface=MIXER,name='Speaker Playback Volume'
  ; type=INTEGER,access=rw---R--,values=1,min=0,max=63,step=0
  : values=63
  | dBscale-min=-57.00dB,step=1.00dB,mute=0

Please help me to solve this problem. 






More information about the Alsa-devel mailing list