1
2
3
4
5#include <linux/device.h>
6#include <linux/kernel.h>
7#include <sound/pcm.h>
8#include <sound/pcm_params.h>
9#include <sound/soc.h>
10#include <sound/soc-acpi.h>
11#include <sound/soc-dai.h>
12#include <sound/soc-dapm.h>
13#include <uapi/sound/asound.h>
14#include "../../codecs/rt1011.h"
15#include "sof_realtek_common.h"
16
17
18
19
20static const struct snd_soc_dapm_route rt1011_dapm_routes[] = {
21
22 { "Left Spk", NULL, "Left SPO" },
23 { "Right Spk", NULL, "Right SPO" },
24};
25
26
27
28
29
30
31
32
33
34
35static struct snd_soc_codec_conf rt1011_codec_confs[] = {
36 {
37 .dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME),
38 .name_prefix = "Left",
39 },
40 {
41 .dlc = COMP_CODEC_CONF(RT1011_DEV1_NAME),
42 .name_prefix = "Right",
43 },
44};
45
46static struct snd_soc_dai_link_component rt1011_dai_link_components[] = {
47 {
48 .name = RT1011_DEV0_NAME,
49 .dai_name = RT1011_CODEC_DAI,
50 },
51 {
52 .name = RT1011_DEV1_NAME,
53 .dai_name = RT1011_CODEC_DAI,
54 },
55};
56
57static const struct {
58 unsigned int tx;
59 unsigned int rx;
60} rt1011_tdm_mask[] = {
61 {.tx = 0x4, .rx = 0x1},
62 {.tx = 0x8, .rx = 0x2},
63};
64
65static int rt1011_hw_params(struct snd_pcm_substream *substream,
66 struct snd_pcm_hw_params *params)
67{
68 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
69 struct snd_soc_dai *codec_dai;
70 int srate, i, ret = 0;
71
72 srate = params_rate(params);
73
74 for_each_rtd_codec_dais(rtd, i, codec_dai) {
75
76 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK,
77 100 * srate, 256 * srate);
78 if (ret < 0) {
79 dev_err(codec_dai->dev, "fail to set pll, ret %d\n",
80 ret);
81 return ret;
82 }
83
84 ret = snd_soc_dai_set_sysclk(codec_dai, RT1011_FS_SYS_PRE_S_PLL1,
85 256 * srate, SND_SOC_CLOCK_IN);
86 if (ret < 0) {
87 dev_err(codec_dai->dev, "fail to set sysclk, ret %d\n",
88 ret);
89 return ret;
90 }
91
92 if (i >= ARRAY_SIZE(rt1011_tdm_mask)) {
93 dev_err(codec_dai->dev, "invalid codec index %d\n",
94 i);
95 return -ENODEV;
96 }
97
98 ret = snd_soc_dai_set_tdm_slot(codec_dai, rt1011_tdm_mask[i].tx,
99 rt1011_tdm_mask[i].rx, 4,
100 params_width(params));
101 if (ret < 0) {
102 dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n",
103 ret);
104 return ret;
105 }
106 }
107
108 return 0;
109}
110
111static const struct snd_soc_ops rt1011_ops = {
112 .hw_params = rt1011_hw_params,
113};
114
115static int rt1011_init(struct snd_soc_pcm_runtime *rtd)
116{
117 struct snd_soc_card *card = rtd->card;
118 int ret;
119
120 ret = snd_soc_dapm_add_routes(&card->dapm, rt1011_dapm_routes,
121 ARRAY_SIZE(rt1011_dapm_routes));
122 if (ret)
123 dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
124 return ret;
125}
126
127void sof_rt1011_dai_link(struct snd_soc_dai_link *link)
128{
129 link->codecs = rt1011_dai_link_components;
130 link->num_codecs = ARRAY_SIZE(rt1011_dai_link_components);
131 link->init = rt1011_init;
132 link->ops = &rt1011_ops;
133}
134
135void sof_rt1011_codec_conf(struct snd_soc_card *card)
136{
137 card->codec_conf = rt1011_codec_confs;
138 card->num_configs = ARRAY_SIZE(rt1011_codec_confs);
139}
140
141
142
143
144
145
146
147
148
149
150
151static const struct snd_soc_dapm_route rt1015p_1dev_dapm_routes[] = {
152
153 { "Left Spk", NULL, "Speaker" },
154 { "Right Spk", NULL, "Speaker" },
155};
156
157static const struct snd_soc_dapm_route rt1015p_2dev_dapm_routes[] = {
158
159 { "Left Spk", NULL, "Left Speaker" },
160 { "Right Spk", NULL, "Right Speaker" },
161};
162
163static struct snd_soc_codec_conf rt1015p_codec_confs[] = {
164 {
165 .dlc = COMP_CODEC_CONF(RT1015P_DEV0_NAME),
166 .name_prefix = "Left",
167 },
168 {
169 .dlc = COMP_CODEC_CONF(RT1015P_DEV1_NAME),
170 .name_prefix = "Right",
171 },
172};
173
174static struct snd_soc_dai_link_component rt1015p_dai_link_components[] = {
175 {
176 .name = RT1015P_DEV0_NAME,
177 .dai_name = RT1015P_CODEC_DAI,
178 },
179 {
180 .name = RT1015P_DEV1_NAME,
181 .dai_name = RT1015P_CODEC_DAI,
182 },
183};
184
185static int rt1015p_get_num_codecs(void)
186{
187 static int dev_num;
188
189 if (dev_num)
190 return dev_num;
191
192 if (!acpi_dev_present("RTL1015", "1", -1))
193 dev_num = 1;
194 else
195 dev_num = 2;
196
197 return dev_num;
198}
199
200static int rt1015p_hw_params(struct snd_pcm_substream *substream,
201 struct snd_pcm_hw_params *params)
202{
203
204
205 return 0;
206}
207
208static const struct snd_soc_ops rt1015p_ops = {
209 .hw_params = rt1015p_hw_params,
210};
211
212static int rt1015p_init(struct snd_soc_pcm_runtime *rtd)
213{
214 struct snd_soc_card *card = rtd->card;
215 int ret;
216
217 if (rt1015p_get_num_codecs() == 1)
218 ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_1dev_dapm_routes,
219 ARRAY_SIZE(rt1015p_1dev_dapm_routes));
220 else
221 ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_2dev_dapm_routes,
222 ARRAY_SIZE(rt1015p_2dev_dapm_routes));
223 if (ret)
224 dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
225 return ret;
226}
227
228void sof_rt1015p_dai_link(struct snd_soc_dai_link *link)
229{
230 link->codecs = rt1015p_dai_link_components;
231 link->num_codecs = rt1015p_get_num_codecs();
232 link->init = rt1015p_init;
233 link->ops = &rt1015p_ops;
234}
235
236void sof_rt1015p_codec_conf(struct snd_soc_card *card)
237{
238 if (rt1015p_get_num_codecs() == 1)
239 return;
240
241 card->codec_conf = rt1015p_codec_confs;
242 card->num_configs = ARRAY_SIZE(rt1015p_codec_confs);
243}
244