#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sun7i-i2s.h" #include "sun7i-i2sdma.h" #define AUDIO_FORMAT (SND_SOC_DAIFMT_I2S | \ SND_SOC_DAIFMT_CBS_CFS |SND_SOC_DAIFMT_NB_NF) #define AUDIO_CODEC_FORMAT (SND_SOC_DAIFMT_I2S | \ SND_SOC_DAIFMT_CBM_CFM |SND_SOC_DAIFMT_NB_NF) static int rx51_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 long sample_rate =41000; ret = snd_soc_dai_set_sysclk(cpu_dai, 0 , 22579200, SND_SOC_CLOCK_OUT); if (ret < 0) { return ret; } /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_CODEC_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_clkdiv(cpu_dai, 0, sample_rate); if (ret < 0) { return ret; } /* Set the codec system clock for DAC and ADC */ return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000, SND_SOC_CLOCK_IN); } static struct snd_soc_ops rx51_ops = { .hw_params = rx51_hw_params, }; static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), }; static const struct snd_soc_dapm_route audio_map[] = { {"Speaker", NULL, "SPL"}, {"Speaker", NULL, "SPR"}, /* Headphone connected to HPLOUT, HPROUT */ {"Headphone Jack", NULL, "HPL"}, {"Headphone Jack", NULL, "HPR"}, }; static const struct snd_kcontrol_new aic34_rx51_controls[] = { SOC_ENUM_EXT("Speaker Function", rx51_enum[0], rx51_get_spk, rx51_set_spk), SOC_ENUM_EXT("Input Select", rx51_enum[1], rx51_get_input, rx51_set_input), SOC_ENUM_EXT("Jack Function", rx51_enum[2], rx51_get_jack, rx51_set_jack), SOC_DAPM_PIN_SWITCH("FM Transmitter"), }; static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; int err; /* Add RX-51 specific widgets */ snd_soc_dapm_new_controls(dapm, aic34_dapm_widgets, ARRAY_SIZE(aic34_dapm_widgets)); /* Set up RX-51 specific audio path audio_map */ snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); snd_soc_dapm_nc_pin(dapm, "MIC3L"); snd_soc_dapm_nc_pin(dapm, "MIC3R"); snd_soc_dapm_nc_pin(dapm, "LINE1R"); snd_soc_dapm_nc_pin(dapm, "MONO_LOUT"); snd_soc_dapm_enable_pin(dapm, "HPL"); snd_soc_dapm_enable_pin(dapm, "HPR"); snd_soc_dapm_enable_pin(dapm, "HPLCOM"); snd_soc_dapm_enable_pin(dapm, "HPRCOM"); /* always connected */ snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_nc_pin(dapm, "Line Out"); snd_soc_dapm_nc_pin(dapm, "Mic Jack"); snd_soc_dapm_nc_pin(dapm, "Line In"); return 0; } /* Digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link rx51_dai[] = { { .name = "TLV320AIC34", .stream_name = "AIC34", .cpu_dai_name = "sun7i-i2s.0", .codec_dai_name = "tlv320aic31xx-dai", .init = rx51_aic34_init, .platform_name = "sun7i-i2s-pcm-audio.0", .codec_name = "tlv320aic31xx-codec.2-0018", .ops = &rx51_ops, }, }; /* Audio card */ static struct snd_soc_card rx51_sound_card = { .name = "RX-51", .owner = THIS_MODULE, .dai_link = &rx51_dai, .num_links = 1, }; static struct platform_device *rx51_snd_device; static int __init rx51_soc_init(void) { int err; rx51_snd_device = platform_device_alloc("soc-audio", 3); if (!rx51_snd_device) { err = -ENOMEM; return err; } platform_set_drvdata(rx51_snd_device, &rx51_sound_card); err = platform_device_add(rx51_snd_device); if (err) { platform_device_put(rx51_snd_device); } return err; } static void __exit rx51_soc_exit(void) { platform_device_unregister(rx51_snd_device); } module_init(rx51_soc_init); module_exit(rx51_soc_exit); MODULE_AUTHOR("Nokia Corporation"); MODULE_DESCRIPTION("ALSA SoC Nokia RX-51"); MODULE_LICENSE("GPL");