Seungwhan Youn wrote: > Hi, > > On Tue, Jul 20, 2010 at 2:28 PM, Chanwoo Choi <cw00.choi@xxxxxxxxxxx> wrote: >> This patch add sound support for the Aquila board based on S5PC110. >> >> The Aquila board is based on Samsung SoC(S5PC110) and include >> WM8994 codec over I2S to support sound. This uses the I2Sv4 driver >> compatible with I2Sv5 to run sound. >> >> The kind of jack is below states : >> * SND_JACK_HEADPHONE >> * SND_JACK_HEADSET >> * SND_JACK_MECHANICAL >> : When TV-OUT cable is inserted on Aquila board, >> the TV-OUT cable isn't connected to television. >> * SND_JACK_AVOUT >> : When TV-OUT cable is inserted on Aquila board, >> the TV-OUT cable is connected to television. >> >> Signed-off-by: Chanwoo Choi <cw00.choi@xxxxxxxxxxx> >> Signed-off-by: Joonyoung Shim <jy0922.shim@xxxxxxxxxxx> >> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> >> --- >> sound/soc/s3c24xx/Kconfig | 9 + >> sound/soc/s3c24xx/Makefile | 2 + >> sound/soc/s3c24xx/aquila_wm8994.c | 300 +++++++++++++++++++++++++++++++++++++ >> 3 files changed, 311 insertions(+), 0 deletions(-) >> create mode 100644 sound/soc/s3c24xx/aquila_wm8994.c >> >> diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig >> index 213963a..c09b402 100644 >> --- a/sound/soc/s3c24xx/Kconfig >> +++ b/sound/soc/s3c24xx/Kconfig >> @@ -131,3 +131,12 @@ config SND_S3C64XX_SOC_SMARTQ >> depends on SND_S3C24XX_SOC && MACH_SMARTQ >> select SND_S3C64XX_SOC_I2S >> select SND_SOC_WM8750 >> + >> +config SND_S5PC110_SOC_AQUILA_WM8994 >> + tristate "SoC I2S Audio support for AQUILA - WM8994" >> + depends on SND_S3C24XX_SOC && MACH_AQUILA >> + select SND_S3C64XX_SOC_I2S_V4 >> + select SND_SOC_WM8994 >> + help >> + Say Y if you want to add support for SoC audio on aquila >> + with the WM8994. >> diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile >> index 50172c3..02dd12c 100644 >> --- a/sound/soc/s3c24xx/Makefile >> +++ b/sound/soc/s3c24xx/Makefile >> @@ -30,6 +30,7 @@ snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o >> snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o >> snd-soc-smdk-wm9713-objs := smdk_wm9713.o >> snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o >> +snd-soc-aquila-wm8994-objs := aquila_wm8994.o >> >> obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o >> obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o >> @@ -43,3 +44,4 @@ obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv32 >> obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o >> obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o >> obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o >> +obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o >> diff --git a/sound/soc/s3c24xx/aquila_wm8994.c b/sound/soc/s3c24xx/aquila_wm8994.c >> new file mode 100644 >> index 0000000..6ff5068 >> --- /dev/null >> +++ b/sound/soc/s3c24xx/aquila_wm8994.c >> @@ -0,0 +1,300 @@ >> +/* >> + * aquila_wm8994.c >> + * >> + * Copyright (C) 2010 Samsung Electronics Co.Ltd >> + * Author: Chanwoo Choi <cw00.choi@xxxxxxxxxxx> >> + * >> + * 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. >> + * >> + */ >> + >> +#include <linux/module.h> >> +#include <linux/moduleparam.h> >> +#include <linux/io.h> >> +#include <linux/platform_device.h> >> +#include <sound/soc.h> >> +#include <sound/soc-dapm.h> >> +#include <sound/jack.h> >> +#include <asm/mach-types.h> >> +#include <mach/gpio.h> >> +#include <mach/regs-clock.h> >> + >> +#include <linux/mfd/wm8994/core.h> >> +#include <linux/mfd/wm8994/registers.h> >> +#include "../codecs/wm8994.h" >> +#include "s3c-dma.h" >> +#include "s3c64xx-i2s.h" >> + >> +#define WM8994_DAI_HIFI 0 >> +#define WM8994_DAI_VOICE 1 >> + >> +static struct snd_soc_card aquila; >> +static struct platform_device *aquila_snd_device; >> + >> +/* 3.5 pie jack */ >> +static struct snd_soc_jack jack; >> + >> +/* 3.5 pie jack detection DAPM pins */ >> +static struct snd_soc_jack_pin jack_pins[] = { >> + { >> + .pin = "Headset Mic", >> + .mask = SND_JACK_MICROPHONE, >> + }, { >> + .pin = "Headset Stereophone", >> + .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL | >> + SND_JACK_AVOUT, >> + }, >> +}; >> + >> +/* 3.5 pie jack detection gpios */ >> +static struct snd_soc_jack_gpio jack_gpios[] = { >> + { >> + .gpio = S5PV210_GPH0(6), >> + .name = "DET_3.5", >> + .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL | >> + SND_JACK_AVOUT, >> + .debounce_time = 200, >> + }, >> +}; >> + >> +static const struct snd_soc_dapm_widget aquila_dapm_widgets[] = { >> + SND_SOC_DAPM_SPK("Ext Spk", NULL), >> + SND_SOC_DAPM_SPK("Ext Rcv", NULL), >> + SND_SOC_DAPM_HP("Headset Stereophone", NULL), >> + SND_SOC_DAPM_MIC("Headset Mic", NULL), >> + SND_SOC_DAPM_MIC("Main Mic", NULL), >> + SND_SOC_DAPM_MIC("2nd Mic", NULL), >> + SND_SOC_DAPM_LINE("Radio In", NULL), >> +}; >> + >> +static const struct snd_soc_dapm_route aquila_dapm_routes[] = { >> + {"Ext Spk", NULL, "SPKOUTLP"}, >> + {"Ext Spk", NULL, "SPKOUTLN"}, >> + >> + {"Ext Rcv", NULL, "HPOUT2N"}, >> + {"Ext Rcv", NULL, "HPOUT2P"}, >> + >> + {"Headset Stereophone", NULL, "HPOUT1L"}, >> + {"Headset Stereophone", NULL, "HPOUT1R"}, >> + >> + {"IN1RN", NULL, "Headset Mic"}, >> + {"IN1RP", NULL, "Headset Mic"}, >> + >> + {"IN1RN", NULL, "2nd Mic"}, >> + {"IN1RP", NULL, "2nd Mic"}, >> + >> + {"IN1LN", NULL, "Main Mic"}, >> + {"IN1LP", NULL, "Main Mic"}, >> + >> + {"IN2LN", NULL, "Radio In"}, >> + {"IN2RN", NULL, "Radio In"}, >> +}; >> + >> +static int aquila_wm8994_init(struct snd_soc_pcm_runtime *rtd) >> +{ >> + struct snd_soc_codec *codec = rtd->codec; >> + int ret; >> + >> + /* add aquila specific widgets */ >> + snd_soc_dapm_new_controls(codec, aquila_dapm_widgets, >> + ARRAY_SIZE(aquila_dapm_widgets)); >> + >> + /* set up aquila specific audio routes */ >> + snd_soc_dapm_add_routes(codec, aquila_dapm_routes, >> + ARRAY_SIZE(aquila_dapm_routes)); >> + >> + /* set endpoints to not connected */ >> + snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN"); >> + snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP"); >> + snd_soc_dapm_nc_pin(codec, "LINEOUT1N"); >> + snd_soc_dapm_nc_pin(codec, "LINEOUT1P"); >> + snd_soc_dapm_nc_pin(codec, "LINEOUT2N"); >> + snd_soc_dapm_nc_pin(codec, "LINEOUT2P"); >> + snd_soc_dapm_nc_pin(codec, "SPKOUTRN"); >> + snd_soc_dapm_nc_pin(codec, "SPKOUTRP"); >> + >> + snd_soc_dapm_sync(codec); >> + >> + /* Headset jack detection */ >> + ret = snd_soc_jack_new(&aquila, "Headset Jack", >> + SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT, >> + &jack); >> + if (ret) >> + return ret; >> + >> + ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins); >> + if (ret) >> + return ret; >> + >> + ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios); >> + if (ret) >> + return ret; >> + >> + return 0; >> +} >> + >> +static int aquila_hifi_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; >> + unsigned int pll_out = 24000000; >> + int ret = 0; >> + >> + /* set the 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; >> + >> + /* set the cpu system clock */ >> + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, 0); > > I think that this is not good to write hard-coded parameters. Ok, I will modify as below codes, - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, 0, 0); + ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK, + 0, SND_SOC_CLOCK_IN); > >> + if (ret < 0) >> + return 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_CBM_CFM); >> + if (ret < 0) >> + return ret; >> + >> + /* set the codec FLL */ >> + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out, >> + params_rate(params) * 256); >> + if (ret < 0) >> + return ret; >> + >> + /* set the codec system clock */ >> + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, >> + params_rate(params) * 256, SND_SOC_CLOCK_IN); >> + if (ret < 0) >> + return ret; >> + >> + return 0; >> +} >> + >> +static struct snd_soc_ops aquila_hifi_ops = { >> + .hw_params = aquila_hifi_hw_params, >> +}; >> + >> +static int aquila_voice_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; >> + unsigned int pll_out = 24000000; >> + int ret = 0; >> + >> + if (params_rate(params) != 8000) >> + return -EINVAL; >> + >> + /* set codec DAI configuration */ >> + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | >> + SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); >> + if (ret < 0) >> + return ret; >> + >> + /* set the codec FLL */ >> + ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out, >> + params_rate(params) * 256); >> + if (ret < 0) >> + return ret; >> + >> + /* set the codec system clock */ >> + ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, >> + params_rate(params) * 256, SND_SOC_CLOCK_IN); >> + if (ret < 0) >> + return ret; >> + >> + return 0; >> +} >> + >> +static struct snd_soc_dai_driver voice_dai = { >> + .name = "Voice", >> + .playback = { >> + .channels_min = 1, >> + .channels_max = 2, >> + .rates = SNDRV_PCM_RATE_8000, >> + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, >> + .capture = { >> + .channels_min = 1, >> + .channels_max = 2, >> + .rates = SNDRV_PCM_RATE_8000, >> + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, >> +}; >> + >> +static struct snd_soc_ops aquila_voice_ops = { >> + .hw_params = aquila_voice_hw_params, >> +}; >> + >> +static struct snd_soc_dai_link aquila_dai[] = { >> +{ >> + .name = "WM8994", >> + .stream_name = "WM8994 HiFi", >> + .cpu_dai_drv = &s3c64xx_i2s_v4_dai, >> + .codec_dai_drv = &wm8994_dai[WM8994_DAI_HIFI], >> + .codec_dai_id = WM8994_DAI_HIFI, >> + .platform_drv = &s3c24xx_soc_platform, >> + .codec_drv = &soc_codec_dev_wm8994, >> + .init = aquila_wm8994_init, >> + .ops = &aquila_hifi_ops, >> +}, { >> + .name = "WM8994 Voice", >> + .stream_name = "Voice", >> + .cpu_dai_drv = &voice_dai, >> + .codec_dai_drv = &wm8994_dai[WM8994_DAI_VOICE], >> + .codec_dai_id = WM8994_DAI_VOICE, >> + .platform_drv = &s3c24xx_soc_platform, >> + .codec_drv = &soc_codec_dev_wm8994, >> + .ops = &aquila_voice_ops, >> +}, >> +}; >> + >> +static struct snd_soc_card aquila = { >> + .name = "aquila", >> + .dai_link = aquila_dai, >> + .num_links = ARRAY_SIZE(aquila_dai), >> +}; >> + >> +static int __init aquila_init(void) >> +{ >> + int ret; >> + >> + if (!machine_is_aquila()) >> + return -ENODEV; >> + >> + aquila_snd_device = platform_device_alloc("soc-audio", 0); > > Really need this allocate as a '0' not "-1"? > Is there any reason for? No, there isn't special reason. I will modify id from '0' to '-1'. - aquila_snd_device = platform_device_alloc("soc-audio", 0); + aquila_snd_device = platform_device_alloc("soc-audio", -1); >> + if (!aquila_snd_device) >> + return -ENOMEM; >> + >> + /* register voice DAI here */ >> + ret = snd_soc_register_dai(&aquila_snd_device->dev, >> + 0, &voice_dai); >> + if (ret) >> + return ret; >> + >> + platform_set_drvdata(aquila_snd_device, &aquila); >> + ret = platform_device_add(aquila_snd_device); >> + >> + if (ret) >> + platform_device_put(aquila_snd_device); >> + >> + return ret; >> +} >> + >> +static void __exit aquila_exit(void) >> +{ >> + platform_device_unregister(aquila_snd_device); >> +} >> + >> +module_init(aquila_init); >> +module_exit(aquila_exit); >> + >> +/* Module information */ >> +MODULE_DESCRIPTION("ALSA SoC WM8994 Aquila(S5PC110)"); >> +MODULE_AUTHOR("Chanwoo Choi <cw00.choi@xxxxxxxxxxx>"); >> +MODULE_LICENSE("GPL"); >> -- >> 1.6.3.3 >> _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel