Dear All,
I would like to using a WM8727 codec on my board, which has at Atmel AT91SAM9261 processor. I implemented the board specific part of the ASoC driver:
I'm trying to test it with: cat /dev/urandom > /dev/dsp I'm getting the following error message in dmesg: [ 7.140000] ASoC: SSC0 device request OK [ 7.140000] ASoC: wm8727 device allocation OK [ 7.160000] asoc: WM8727 <-> atmel-ssc0 mapping ok [ 7.160000] SoC IRF WM8727 init [ 7.220000] ASoC: wm8727 device registration OK [ 16.330000] atmel_ssc_startup: SSC_SR=0x204 [ 16.440000] SoC IRF WM8727 hw_params: cpu_dai [ 16.440000] SoC IRF WM8727 hw_params OK [ 16.440000] atmel_ssc_hw_params: RCMR=00010721 RFMR=0000008f TCMR=00010702 TFMR=0000008f [ 16.440000] atmel_ssc_dai: Starting clock [ 16.440000] atmel_ssc_dai,hw_params: SSC initialized [ 16.440000] transmit enabled SSC_SR=0x000104cf [ 210.850000] ALSA sound/core/pcm_lib.c:1758: playback write error (DMA or IRQ trouble?) [ 210.850000] ALSA sound/core/pcm_lib.c:1758: playback write error (DMA or IRQ trouble?) [ 220.850000] ALSA sound/core/pcm_native.c:1492: playback drain error (DMA or IRQ trouble?) [ 220.850000] atmel_ssc_shutdown: transmit disabled SSC_SR=0x000000c0 [ 220.850000] atmel_ssc_dau: Stopping clock
Did anybody used this codec before? What's missing from my code?
My source code:
static int soc_irf_wm8727_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->dai->cpu_dai; int ret;
printk("SoC IRF WM8727 hw_params: cpu_dai\n");
/* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret;
printk("SoC IRF WM8727 hw_params OK\n");
return 0; }
static struct snd_soc_ops soc_irf_wm8727_ops = { .hw_params = soc_irf_wm8727_hw_params, };
static int soc_irf_wm8727_init(struct snd_soc_codec *codec) { printk("SoC IRF WM8727 init\n");
return 0; }
static struct snd_soc_dai_link soc_irf_wm8727_dai[] = { { .name = "WM8727", .stream_name = "WM8727 PCM", .cpu_dai = &atmel_ssc_dai[0], .codec_dai = &wm8727_dai, .init = soc_irf_wm8727_init, .ops = &soc_irf_wm8727_ops, } };
static struct snd_soc_card snd_soc_wm8727_irf = { .name = "SOC_IRF_WM8727", .platform = &atmel_soc_platform, .dai_link = soc_irf_wm8727_dai, .num_links = ARRAY_SIZE(soc_irf_wm8727_dai), };
static struct snd_soc_device soc_irf_wm8727_snd_devdata = { .card = &snd_soc_wm8727_irf, .codec_dev = &soc_codec_dev_wm8727, };
static struct platform_device *soc_irf_wm8727_snd_device;
static int __init soc_irf_init(void) { struct atmel_ssc_info *ssc_p_wm8727 = soc_irf_wm8727_dai[0].cpu_dai->private_data; struct ssc_device *ssc = NULL; int ret;
/* Request SSC device */ ssc = ssc_request(0); if (IS_ERR(ssc)) { printk(KERN_ERR "ASoC: Failed to request SSC 0\n"); ret = PTR_ERR(ssc); ssc = NULL; goto err; } ssc_p_wm8727->ssc = ssc; printk("ASoC: SSC0 device request OK\n");
at91_set_B_periph(AT91_PIN_PA17, 1); at91_set_B_periph(AT91_PIN_PA18, 1); at91_set_B_periph(AT91_PIN_PA19, 1);
/* WM8727 codec */ soc_irf_wm8727_snd_device = platform_device_alloc("soc-audio", 1); if (!soc_irf_wm8727_snd_device) { printk(KERN_ERR "ASoC: Platform device allocation failed: wm8727\n"); ret = -ENOMEM; goto err_ssc; } printk("ASoC: wm8727 device allocation OK\n");
platform_set_drvdata(soc_irf_wm8727_snd_device, &soc_irf_wm8727_snd_devdata); soc_irf_wm8727_snd_devdata.dev = &soc_irf_wm8727_snd_device->dev;
ret = platform_device_add(soc_irf_wm8727_snd_device); if (ret) { printk(KERN_ERR "ASoC: Platform device allocation failed: wm8727\n"); ret = -ENODEV; goto err_wm8727; } printk("ASoC: wm8727 device registration OK\n");
return ret;
err_ssc: ssc_free(ssc); ssc_p_wm8727->ssc = NULL; err: return ret; }
static void __exit soc_irf_exit(void) { struct atmel_ssc_info *ssc_p_wm8727 = soc_irf_wm8727_dai[0].cpu_dai->private_data; struct ssc_device *ssc;
if (ssc_p_wm8727 != NULL) { ssc = ssc_p_wm8727->ssc; if (ssc != NULL) ssc_free(ssc); ssc_p_wm8727->ssc = NULL; }
platform_device_unregister(soc_irf_wm8727_snd_device); soc_irf_wm8727_snd_device = NULL; }
module_init(soc_irf_init); module_exit(soc_irf_exit);
Thank you for your help!
BR, András