* Fwd: WM8741 DAC with AT91SAM9G20
2013-06-20 21:40 WM8741 DAC with AT91SAM9G20 Michael Lathion
2013-06-21 10:25 ` Bo Shen
@ 2013-06-21 12:24 ` Michael Lathion
1 sibling, 0 replies; 3+ messages in thread
From: Michael Lathion @ 2013-06-21 12:24 UTC (permalink / raw)
To: alsa-devel
[-- Attachment #1: Type: text/plain, Size: 1737 bytes --]
I forgot tu my modified sam9g20_wm8741.c file, here is it...
---------- Forwarded message ----------
From: Michael Lathion <m.lathion@gmail.com>
Date: 2013/6/20
Subject: WM8741 DAC with AT91SAM9G20
To: alsa-devel@alsa-project.org
Hi all,
I'm trying to use a WM8742 dac instead of WM8731 on a custom board based on
AT91SAM9G20EK (developpment board from Atmel for AT91SAM9G20 soc) with
Linux Kernel 2.6.38.
I have the driver working in alsa (driver compiled, mixer up in alsa, ...)
but I can't have the ssc interface working. When trying to play sound with
aplay I get only the masterclock and bitclock but no frame clock (LRCLK),
see output below.
What I've done is modifying the /sound/soc/atmel/sam9g20_wm8731.c file but
it seems something is not configured as it should (probably related to
WM8742 being slave and the WM8731 used on original dev board was master for
clock distribution).
My modified sam9g20_wm8741.c is enclosed to this mail, i suspect something
is wrongly setup in CPU DAI configuration but can't find what.
I'm trying to set this up from some weeks now but can't find the right
config so if someone have any idea on what can has to be done it could be
great!
Thanks for help
Regards
Michael
Linux kernel 2.6.38
AT91SAM9G20 processor
WM8741 DAC
Kernel boot output :
ASoC: Mclk set to 22579200
wm8741-codec 0-001b: Successful registration
FOX_Board_wm8741 : PB1003A: wm8741__init() called
wm8741-codec 0-001b: wm8741_set_dai_sysclk info: freq=22579200
asoc: wm8741 <-> atmel-ssc-dai.0 mapping ok
ALSA device list:
#0: DAISY16
When trying play sound kernel driver print:
wm8741-codec 0-001b: wm8741_set_dai_fmt: Format=0, Clock Inv=0
wm8741-codec 0-001b: wm8741_hw_params: bit size param = 2
[-- Attachment #2: sam9g20_wm8741.c --]
[-- Type: text/x-csrc, Size: 7444 bytes --]
/*
* sam9g20_wm8741 -- SoC audio for AT91SAM9G20-based
* ATMEL AT91SAM9G20ek board.
*
* Copyright (C) 2005 SAN People
* Copyright (C) 2008 Atmel
*
* Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
*
* Based on ati_b1_wm8731.c by:
* Frank Mandarino <fmandarino@endrelia.com>
* Copyright 2006 Endrelia Technologies Inc.
* Based on corgi.c by:
* Copyright 2005 Wolfson Microelectronics PLC.
* Copyright 2005 Openedhand Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/atmel-ssc.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
#include "../codecs/wm8741.h"
#include "atmel-pcm.h"
#include "atmel_ssc_dai.h"
#define MCLK_RATE 22579200
static struct clk *mclk;
static int at91sam9g20ek_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;
/* set codec DAI configuration */
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
if (ret < 0)
return ret;
/* set cpu DAI configuration */
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
if (ret < 0)
return ret;
//---------- added cpu DAI ----------
// ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, 22579200);
// if (ret < 0)
// return ret;
ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, 3);
if (ret < 0)
return ret;
ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_TCMR_PERIOD, 7);
if (ret < 0)
return ret;
// ret = snd_soc_dai_set_sysclk(cpu_dai, ATMEL_SYSCLK_MCK, 1843200, 1);
// if (ret < 0)
// return ret;
//----------end CPU DAI add -------------------
return 0;
}
static struct snd_soc_ops at91sam9g20ek_ops = {
.hw_params = at91sam9g20ek_hw_params,
};
static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
enum snd_soc_bias_level level)
{
static int mclk_on;
int ret = 0;
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
if (!mclk_on)
ret = clk_enable(mclk);
if (ret == 0)
mclk_on = 1;
break;
case SND_SOC_BIAS_OFF:
case SND_SOC_BIAS_STANDBY:
if (mclk_on)
clk_disable(mclk);
mclk_on = 0;
break;
}
return ret;
}
static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
SND_SOC_DAPM_SPK("Ext Spk", NULL),
};
static const struct snd_soc_dapm_route intercon[] = {
/* speaker connected to VOUTL */
{"Ext Spk", NULL, "VOUTLP"},
{"Ext Spk", NULL, "VOUTLN"},
// {"Ext Spk", NULL, "VOUTRP"},
// {"Ext Spk", NULL, "VOUTRN"},
};
/*
* Logic for a wm8741 as connected on a at91sam9g20ek board.
*/
static int at91sam9g20ek_wm8741_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
printk(KERN_DEBUG
#if defined(CONFIG_MACH_ACMENETUSFOXG20)
"FOX_Board_wm8741 "
": PB1003A: wm8741__init() called\n");
#else
"at91sam9g20ek_wm8731 "
": at91sam9g20ek_wm8731_init() called\n");
#endif
ret = snd_soc_dai_set_sysclk(codec_dai, WM8741_SYSCLK,
MCLK_RATE, SND_SOC_CLOCK_IN);
if (ret < 0) {
printk(KERN_ERR "Failed to set WM8741 SYSCLK: %d\n", ret);
return ret;
}
/* Add specific widgets */
snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets,
ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
/* Set up specific audio path interconnects */
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
/* not connected */
/* always connected */
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
snd_soc_dapm_sync(dapm);
return 0;
}
static struct snd_soc_dai_link at91sam9g20ek_dai = {
.name = "WM8741",
.stream_name = "WM8741 PCM",
.cpu_dai_name = "atmel-ssc-dai.0",
.codec_dai_name = "wm8741",
.init = at91sam9g20ek_wm8741_init,
.platform_name = "atmel-pcm-audio",
.codec_name = "wm8741-codec.0-001b",
.ops = &at91sam9g20ek_ops,
};
static struct snd_soc_card snd_soc_at91sam9g20ek = {
#if defined(CONFIG_MACH_ACMENETUSFOXG20)
.name = "DAISY16",
#else
.name = "AT91SAMG20-EK",
#endif
.dai_link = &at91sam9g20ek_dai,
.num_links = 1,
.set_bias_level = at91sam9g20ek_set_bias_level,
};
static struct platform_device *at91sam9g20ek_snd_device;
static int __init at91sam9g20ek_init(void)
{
struct clk *pllb;
int ret;
if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc() || machine_is_acmenetusfoxg20()))
return -ENODEV;
ret = atmel_ssc_set_audio(0);
if (ret != 0) {
pr_err("Failed to set SSC 0 for audio: %d\n", ret);
return ret;
}
/*
* Codec MCLK is supplied by PCK0 - set it up.
*/
if (machine_is_acmenetusfoxg20())
mclk = clk_get(NULL, "pck1"); // Daisy16 Audio Codec MCLK is supplied by PCK1
else
mclk = clk_get(NULL, "pck0");
if (IS_ERR(mclk)) {
printk(KERN_ERR "ASoC: Failed to get MCLK\n");
ret = PTR_ERR(mclk);
goto err;
}
pllb = clk_get(NULL, "pllb");
if (IS_ERR(pllb)) {
printk(KERN_ERR "ASoC: Failed to get PLLB\n");
ret = PTR_ERR(pllb);
goto err_mclk;
}
ret = clk_set_parent(mclk, pllb);
clk_put(pllb);
if (ret != 0) {
printk(KERN_ERR "ASoC: Failed to set MCLK parent\n");
goto err_mclk;
}
clk_set_rate(mclk, MCLK_RATE);
printk(KERN_ERR "ASoC: Mclk set to %d\n",MCLK_RATE);
at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
if (!at91sam9g20ek_snd_device) {
printk(KERN_ERR "ASoC: Platform device allocation failed\n");
ret = -ENOMEM;
goto err_mclk;
}
platform_set_drvdata(at91sam9g20ek_snd_device,
&snd_soc_at91sam9g20ek);
ret = platform_device_add(at91sam9g20ek_snd_device);
if (ret) {
printk(KERN_ERR "ASoC: Platform device allocation failed\n");
goto err_device_add;
}
return ret;
err_device_add:
platform_device_put(at91sam9g20ek_snd_device);
err_mclk:
clk_put(mclk);
mclk = NULL;
err:
return ret;
}
static void __exit at91sam9g20ek_exit(void)
{
platform_device_unregister(at91sam9g20ek_snd_device);
at91sam9g20ek_snd_device = NULL;
clk_put(mclk);
mclk = NULL;
}
module_init(at91sam9g20ek_init);
module_exit(at91sam9g20ek_exit);
/* Module information */
MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
MODULE_LICENSE("GPL");
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread