^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (c) 2011 Samsung Electronics Co., Ltd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // http://www.samsung.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "../codecs/wm8994.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "pcm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Board Settings:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * o '1' means 'ON'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * o '0' means 'OFF'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * o 'X' means 'Don't care'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * SMDKC210, SMDKV310: CFG3- 1001, CFG5-1000, CFG7-111111
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Configure audio route as :-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * $ amixer sset 'DAC1' on,on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * $ amixer sset 'Right Headphone Mux' 'DAC'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * $ amixer sset 'Left Headphone Mux' 'DAC'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * $ amixer sset 'DAC1R Mixer AIF1.1' on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * $ amixer sset 'DAC1L Mixer AIF1.1' on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * $ amixer sset 'IN2L' on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * $ amixer sset 'IN2L PGA IN2LN' on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * $ amixer sset 'MIXINL IN2L' on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * $ amixer sset 'AIF1ADC1L Mixer ADC/DMIC' on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * $ amixer sset 'IN2R' on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * $ amixer sset 'IN2R PGA IN2RN' on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * $ amixer sset 'MIXINR IN2R' on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * $ amixer sset 'AIF1ADC1R Mixer ADC/DMIC' on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* SMDK has a 16.9344MHZ crystal attached to WM8994 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define SMDK_WM8994_FREQ 16934400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int smdk_wm8994_pcm_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) unsigned long mclk_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int rfs, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) switch(params_rate(params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) case 8000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) rfs = 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) dev_err(cpu_dai->dev, "%s:%d Sampling Rate %u not supported!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) __func__, __LINE__, params_rate(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) mclk_freq = params_rate(params) * rfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) mclk_freq, SND_SOC_CLOCK_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) SMDK_WM8994_FREQ, mclk_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Set PCM source clock on CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ret = snd_soc_dai_set_sysclk(cpu_dai, S3C_PCM_CLKSRC_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) mclk_freq, SND_SOC_CLOCK_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* Set SCLK_DIV for making bclk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_PCM_SCLK_PER_FS, rfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static struct snd_soc_ops smdk_wm8994_pcm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .hw_params = smdk_wm8994_pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) SND_SOC_DAILINK_DEFS(paif_pcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) DAILINK_COMP_ARRAY(COMP_CPU("samsung-pcm.0")),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) DAILINK_COMP_ARRAY(COMP_CODEC("wm8994-codec", "wm8994-aif1")),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-pcm.0")));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static struct snd_soc_dai_link smdk_dai[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .name = "WM8994 PAIF PCM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .stream_name = "Primary PCM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) SND_SOC_DAIFMT_CBS_CFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .ops = &smdk_wm8994_pcm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) SND_SOC_DAILINK_REG(paif_pcm),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static struct snd_soc_card smdk_pcm = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .name = "SMDK-PCM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .dai_link = smdk_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .num_links = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int snd_smdk_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) smdk_pcm.dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ret = devm_snd_soc_register_card(&pdev->dev, &smdk_pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (ret && ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static struct platform_driver snd_smdk_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .name = "samsung-smdk-pcm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .probe = snd_smdk_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) module_platform_driver(snd_smdk_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) MODULE_DESCRIPTION("ALSA SoC SMDK WM8994 for PCM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) MODULE_LICENSE("GPL");