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