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