From e3a91813a659447bd20de014902fc5b1d95272aa Mon Sep 17 00:00:00 2001 From: Graeme Gregory Date: Mon, 26 Mar 2007 15:47:09 +0100 Subject: [PATCH] Add smdk2443 s3c2443-ac97 and wm9710 support This is the machine driver for smdk2443 with wm9710 Also the s3c2443-ac97 driver for use with the above machine driver. Signed-off-by: Graeme Gregory --- sound/soc/s3c24xx/Kconfig | 15 ++ sound/soc/s3c24xx/Makefile | 5 +- sound/soc/s3c24xx/s3c2443-ac97.c | 438 +++++++++++++++++++++++++++++++++++ sound/soc/s3c24xx/s3c24xx-ac97.h | 25 ++ sound/soc/s3c24xx/smdk2443_wm9710.c | 162 +++++++++++++ 5 files changed, 644 insertions(+), 1 deletions(-) create mode 100644 sound/soc/s3c24xx/s3c2443-ac97.c create mode 100644 sound/soc/s3c24xx/s3c24xx-ac97.h create mode 100644 sound/soc/s3c24xx/smdk2443_wm9710.c diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index 2b4bd21..c41ac49 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig @@ -12,6 +12,12 @@ config SND_S3C24XX_SOC config SND_S3C24XX_SOC_I2S tristate +config SND_S3C2443_SOC_AC97 + tristate + select AC97_BUS + select SND_AC97_CODEC + select SND_SOC_AC97_BUS + config SND_S3C24XX_SOC_NEO1973_WM8753 tristate "SoC I2S Audio support for NEO1973 - WM8753" depends on SND_S3C24XX_SOC && MACH_GTA01 @@ -37,5 +43,14 @@ config SND_S3C24XX_SOC_SMDK2440_WM8956 Say Y if you want to add support for SoC audio on SMDK2440 with WM8956. +config SND_S3C24XX_SOC_SMDK2443_WM9710 + tristate "SoC I2S Audio support for SMDK2443 - WM9710" + depends on SND_S3C24XX_SOC && MACH_SMDK2443 + select SND_S3C2443_SOC_AC97 + select SND_SOC_AC97_CODEC + help + Say Y if you want to add support for SoC audio on smdk2443 + with the WM9710. + endmenu diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 2759e88..3594155 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile @@ -1,16 +1,19 @@ # S3c24XX Platform Support snd-soc-s3c24xx-objs := s3c24xx-pcm.o snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o +snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o +obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o # S3C24XX Machine Support snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o snd-soc-smdk2440-objs := smdk2440.o snd-soc-smdk2440-wm8956-objs := smdk2440-wm8956.o +snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2440) += snd-soc-smdk2440.o obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2440_WM8956) += snd-soc-smdk2440-wm8956.o - +obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c new file mode 100644 index 0000000..db5996b --- /dev/null +++ b/sound/soc/s3c24xx/s3c2443-ac97.c @@ -0,0 +1,438 @@ +/* + * s3c24xx-i2s.c -- ALSA Soc Audio Layer + * + * (c) 2006 Wolfson Microelectronics PLC. + * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com + * + * Copyright (C) 2005, Sean Choi + * All rights reserved. + * + * 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. + * + * Revision history + * 21st Mar 2007 Initial Version + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "s3c24xx-pcm.h" +#include "s3c24xx-ac97.h" + +#define S3C2443_I2S_DEBUG 1 +#if S3C2443_I2S_DEBUG +#define DBG(x...) printk(KERN_DEBUG x) +#else +#define DBG(x...) +#endif + +struct s3c24xx_ac97_info { + void __iomem *regs; + struct clk *ac97_clk; +}; +static struct s3c24xx_ac97_info s3c24xx_ac97; + +static struct completion CAR_completion; +static u32 waitingForMask; +static DECLARE_MUTEX(CAR_mutex); + +static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97, + unsigned short reg) +{ + u32 ac_glbctrl; + u32 ac_codec_cmd; + u32 stat, addr, data; + + DBG("Entered %s\n",__FUNCTION__); + + down(&CAR_mutex); + + // Initialise the completion used in ISR + init_completion(&CAR_completion); + + waitingForMask = S3C_AC97_GLBSTAT_CODECREADY; + ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); + ac_codec_cmd = S3C_AC97_CODEC_CMD_READ | AC_CMD_ADDR(reg); + writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); + + udelay(50); + + ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + + wait_for_completion(&CAR_completion); + + stat = readl(s3c24xx_ac97.regs + S3C_AC97_STAT); + addr = (stat >> 16) & 0x7f; + data = (stat & 0xffff); + + DBG("AC97 Read %x %x\n", addr, data); + + if (addr != reg) { + printk("req addr = %02x, rep addr = %02x\n", reg, addr); + } + + up(&CAR_mutex); + + return (unsigned short)data; +} + +static void s3c2443_ac97_write(struct snd_ac97 *ac97, unsigned short reg, + unsigned short val) +{ + u32 ac_glbctrl; + u32 ac_codec_cmd; + + DBG("Entered %s\n",__FUNCTION__); + + down(&CAR_mutex); + + DBG("AC97 Write %x:%x\n", reg,val); + + init_completion(&CAR_completion); + + waitingForMask = S3C_AC97_GLBSTAT_CODECREADY; + ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); + ac_codec_cmd = AC_CMD_ADDR(reg) | AC_CMD_DATA(val); + writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); + + udelay(50); + + ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + + wait_for_completion(&CAR_completion); + + ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); + ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ; + writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); + + up(&CAR_mutex); + +} + +static void s3c2443_ac97_warm_reset(struct snd_ac97 *ac97) +{ + u32 ac_glbctrl; + + DBG("Entered %s\n", __FUNCTION__); + + ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + ac_glbctrl = S3C_AC97_GLBCTRL_WARMRESET; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + udelay(1000); + + ac_glbctrl = 0; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + udelay(1000); +} + +static void s3c2443_ac97_cold_reset(struct snd_ac97 *ac97) +{ + u32 ac_glbctrl; + + DBG("Entered %s\n", __FUNCTION__); + + ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + ac_glbctrl = S3C_AC97_GLBCTRL_COLDRESET; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + udelay(1000); + + ac_glbctrl = 0; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + udelay(1000); + + ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + ac_glbctrl = S3C_AC97_GLBCTRL_ACLINKON; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + udelay(1000); + + ac_glbctrl |= S3C_AC97_GLBCTRL_TRANSFERDATAENABLE; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + udelay(1000); + + ac_glbctrl |= S3C_AC97_GLBCTRL_PCMOUTTM_DMA | S3C_AC97_GLBCTRL_PCMINTM_DMA | + S3C_AC97_GLBCTRL_MICINTM_DMA; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + +} + +static irqreturn_t s3c2443_ac97_irq(int irq, void *dev_id) +{ + int gsr; + u32 ac_glbctrl; + + gsr = readl(s3c24xx_ac97.regs + S3C_AC97_GLBSTAT) & waitingForMask; + + if (gsr) { + ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + ac_glbctrl &= ~S3C_AC97_GLBCTRL_CODECREADYIE; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + complete(&CAR_completion); + } + return IRQ_HANDLED; +} + +struct snd_ac97_bus_ops soc_ac97_ops = { + .read = s3c2443_ac97_read, + .write = s3c2443_ac97_write, + .warm_reset = s3c2443_ac97_warm_reset, + .reset = s3c2443_ac97_cold_reset, +}; + +static struct s3c2410_dma_client s3c2443_dma_client_out = { + .name = "AC97 PCM Stereo out" +}; + +static struct s3c2410_dma_client s3c2443_dma_client_in = { + .name = "AC97 PCM Stereo in" +}; + +static struct s3c2410_dma_client s3c2443_dma_client_micin = { + .name = "AC97 Mic Mono in" +}; + +static struct s3c24xx_pcm_dma_params s3c2443_ac97_pcm_stereo_out = { + .client = &s3c2443_dma_client_out, + .channel = DMACH_PCM_OUT, + .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA, + .dma_size = 4, +}; + +static struct s3c24xx_pcm_dma_params s3c2443_ac97_pcm_stereo_in = { + .client = &s3c2443_dma_client_in, + .channel = DMACH_PCM_IN, + .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA, + .dma_size = 4, +}; + +static struct s3c24xx_pcm_dma_params s3c2443_ac97_mic_mono_in = { + .client = &s3c2443_dma_client_micin, + .channel = DMACH_MIC_IN, + .dma_addr = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA, + .dma_size = 4, +}; + +#ifdef CONFIG_PM +static int s3c2443_ac97_suspend(struct platform_device *pdev, + struct snd_soc_cpu_dai *dai) +{ + + return 0; +} + +static int s3c2443_ac97_resume(struct platform_device *pdev, + struct snd_soc_cpu_dai *dai) +{ + return 0; +} + +#else +#define s3c2443_ac97_suspend NULL +#define s3c2443_ac97_resume NULL +#endif + +static int s3c2443_ac97_probe(struct platform_device *pdev) +{ + int ret; + u32 ac_glbctrl; + + s3c24xx_ac97.regs = ioremap(S3C2440_PA_AC97, 0x100); + if (s3c24xx_ac97.regs == NULL) + return -ENXIO; + + s3c24xx_ac97.ac97_clk=clk_get(&pdev->dev, "ac97"); + if (s3c24xx_ac97.ac97_clk == NULL) { + DBG("failed to get ac97_clock\n"); + return -ENODEV; + } + clk_enable(s3c24xx_ac97.ac97_clk); + + s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2443_GPE0_AC_nRESET); + s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2443_GPE1_AC_SYNC); + s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2443_GPE2_AC_BITCLK); + s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2443_GPE3_AC_SDI); + s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2443_GPE4_AC_SDO); + + ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + ac_glbctrl = S3C_AC97_GLBCTRL_COLDRESET; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + udelay(1000); + + ac_glbctrl = 0; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + udelay(1000); + + ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + ac_glbctrl = S3C_AC97_GLBCTRL_ACLINKON; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + udelay(1000); + + ac_glbctrl |= S3C_AC97_GLBCTRL_TRANSFERDATAENABLE; + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + + ret = request_irq(IRQ_S3C2443_AC97, s3c2443_ac97_irq, SA_INTERRUPT, "AC97", NULL); + if (ret) + printk("Interrupt request failed.\n"); + + return ret; +} + +static void s3c2443_ac97_remove(struct platform_device *pdev) +{ + +} + +static int s3c2443_ac97_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_cpu_dai *cpu_dai = rtd->dai->cpu_dai; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + cpu_dai->dma_data = &s3c2443_ac97_pcm_stereo_out; + else + cpu_dai->dma_data = &s3c2443_ac97_pcm_stereo_in; + + return 0; +} + +static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd) +{ + u32 ac_glbctrl; + + ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + switch(cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + ac_glbctrl |= S3C_AC97_GLBCTRL_PCMINTM_DMA; + else + ac_glbctrl |= S3C_AC97_GLBCTRL_PCMOUTTM_DMA; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMINTM_MASK; + else + ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMOUTTM_MASK; + break; + } + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + + return 0; +} + +static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return -ENODEV; + else + cpu_dai->dma_data = &s3c2443_ac97_mic_mono_in; + + return 0; +} + +static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, int cmd) +{ + u32 ac_glbctrl; + + ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + switch(cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ac_glbctrl |= S3C_AC97_GLBCTRL_PCMINTM_DMA; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMINTM_MASK; + } + writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); + + return 0; +} + +#define s3c2443_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) + +struct snd_soc_cpu_dai s3c2443_ac97_dai[] = { +{ + .name = "s3c2443-ac97", + .id = 0, + .type = SND_SOC_DAI_AC97, + .probe = s3c2443_ac97_probe, + .remove = s3c2443_ac97_remove, + .suspend = s3c2443_ac97_suspend, + .resume = s3c2443_ac97_resume, + .playback = { + .stream_name = "AC97 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = s3c2443_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .stream_name = "AC97 Capture", + .channels_min = 2, + .channels_max = 2, + .rates = s3c2443_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .hw_params = s3c2443_ac97_hw_params, + .trigger = s3c2443_ac97_trigger}, +}, +{ + .name = "pxa2xx-ac97-mic", + .id = 1, + .type = SND_SOC_DAI_AC97, + .capture = { + .stream_name = "AC97 Mic Capture", + .channels_min = 1, + .channels_max = 1, + .rates = s3c2443_AC97_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = { + .hw_params = s3c2443_ac97_hw_mic_params, + .trigger = s3c2443_ac97_mic_trigger,}, +}, +}; + +EXPORT_SYMBOL_GPL(s3c2443_ac97_dai); +EXPORT_SYMBOL_GPL(soc_ac97_ops); + +MODULE_AUTHOR("Graeme Gregory"); +MODULE_DESCRIPTION("AC97 driver for the Samsung s3c2443 chip"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/s3c24xx/s3c24xx-ac97.h b/sound/soc/s3c24xx/s3c24xx-ac97.h new file mode 100644 index 0000000..afddff0 --- /dev/null +++ b/sound/soc/s3c24xx/s3c24xx-ac97.h @@ -0,0 +1,25 @@ +/* + * s3c24xx-i2s.c -- ALSA Soc Audio Layer + * + * Copyright 2005 Wolfson Microelectronics PLC. + * Author: Graeme Gregory + * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com + * + * 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. + * + * Revision history + * 10th Nov 2006 Initial version. + */ + +#ifndef S3C24XXAC97_H_ +#define S3C24XXAC97_H_ + +#define AC_CMD_ADDR(x) (x<<16) +#define AC_CMD_DATA(x) (x&0xffff) + +extern struct snd_soc_cpu_dai s3c2443_ac97_dai[]; + +#endif /*S3C24XXI2S_H_*/ diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c new file mode 100644 index 0000000..66c13cf --- /dev/null +++ b/sound/soc/s3c24xx/smdk2443_wm9710.c @@ -0,0 +1,162 @@ +/* + * smdk2443_wm9710.c -- SoC audio for smdk2443 + * + * Copyright 2007 Wolfson Microelectronics PLC. + * Author: Graeme Gregory + * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com + * + * 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. + * + * Revision history + * 8th Mar 2007 Initial version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../codecs/ac97.h" +#include "s3c24xx-pcm.h" +#include "s3c24xx-ac97.h" + +#define SMDK2443_DEBUG 1 +#if SMDK2443_DEBUG +#define DBG(x...) printk(KERN_DEBUG x) +#else +#define DBG(x...) +#endif + +static struct snd_soc_machine smdk2443; + +static int smdk2443_suspend(struct platform_device *pdev, pm_message_t state) +{ + return 0; +} + +static int smdk2443_resume(struct platform_device *pdev) +{ + return 0; +} + +static int smdk2443_probe(struct platform_device *pdev) +{ + return 0; +} + +static int smdk2443_remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct snd_soc_dapm_widget smdk2443_dapm_widgets[] = { + SND_SOC_DAPM_MIC("Mic (Internal)", NULL), +}; + +/* example machine interconnections */ +static const char* intercon[][3] = { + + /* mic is connected to mic1 - with bias */ + {"MIC1", NULL, "Mic Bias"}, + {"Mic Bias", NULL, "Mic (Internal)"}, + + {NULL, NULL, NULL}, +}; + +static int smdk2443_wm9710_init(struct snd_soc_codec *codec) +{ + int i; + + /* set up smdk2443 NC codec pins */ + snd_soc_dapm_set_endpoint(codec, "RXP", 0); + snd_soc_dapm_set_endpoint(codec, "RXN", 0); + + /* Add smdk2443 specific widgets */ + for(i = 0; i < ARRAY_SIZE(smdk2443_dapm_widgets); i++) { + snd_soc_dapm_new_control(codec, &smdk2443_dapm_widgets[i]); + } + + /* set up smdk2443 specific audio path interconnects */ + for(i = 0; intercon[i][0] != NULL; i++) { + snd_soc_dapm_connect_input(codec, intercon[i][0], intercon[i][1], intercon[i][2]); + } + + snd_soc_dapm_sync_endpoints(codec); + return 0; +} + +static struct snd_soc_dai_link smdk2443_dai[] = { +{ + .name = "AC97", + .stream_name = "AC97 HiFi", + .cpu_dai = &s3c2443_ac97_dai[0], + .codec_dai = &ac97_dai, + .init = smdk2443_wm9710_init, +}, +}; + +static struct snd_soc_machine smdk2443 = { + .name = "SMDK2443", + .probe = smdk2443_probe, + .remove = smdk2443_remove, + .suspend_pre = smdk2443_suspend, + .resume_post = smdk2443_resume, + .dai_link = smdk2443_dai, + .num_links = ARRAY_SIZE(smdk2443_dai), +}; + +static struct snd_soc_device smdk2443_snd_ac97_devdata = { + .machine = &smdk2443, + .platform = &s3c24xx_soc_platform, + .codec_dev = &soc_codec_dev_ac97, +}; + +static struct platform_device *smdk2443_snd_ac97_device; + +static int __init smdk2443_init(void) +{ + int ret; + + smdk2443_snd_ac97_device = platform_device_alloc("soc-audio", -1); + if (!smdk2443_snd_ac97_device) + return -ENOMEM; + + platform_set_drvdata(smdk2443_snd_ac97_device, &smdk2443_snd_ac97_devdata); + smdk2443_snd_ac97_devdata.dev = &smdk2443_snd_ac97_device->dev; + + if((ret = platform_device_add(smdk2443_snd_ac97_device)) != 0) + platform_device_put(smdk2443_snd_ac97_device); + + return ret; +} + +static void __exit smdk2443_exit(void) +{ + platform_device_unregister(smdk2443_snd_ac97_device); +} + +module_init(smdk2443_init); +module_exit(smdk2443_exit); + +/* Module information */ +MODULE_AUTHOR("Graeme Gregory, graeme.gregory@wolfsonmicro.com, www.wolfsonmicro.com"); +MODULE_DESCRIPTION("ALSA SoC WM9710 SMDK2443"); +MODULE_LICENSE("GPL"); -- 1.5.0.3