1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2020 Intel Corporation. All rights reserved.
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 * Current only 2-amp configuration is supported for rt1011
19 */
20 static const struct snd_soc_dapm_route rt1011_dapm_routes[] = {
21 /* speaker */
22 { "Left Spk", NULL, "Left SPO" },
23 { "Right Spk", NULL, "Right SPO" },
24 };
25
26 /*
27 * Make sure device's Unique ID follows this configuration:
28 *
29 * Two speakers:
30 * 0: left, 1: right
31 * Four speakers:
32 * 0: Woofer left, 1: Woofer right
33 * 2: Tweeter left, 3: Tweeter right
34 */
35 static 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
46 static 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
57 static 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
rt1011_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)65 static 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 /* 100 Fs to drive 24 bit data */
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
111 static const struct snd_soc_ops rt1011_ops = {
112 .hw_params = rt1011_hw_params,
113 };
114
rt1011_init(struct snd_soc_pcm_runtime * rtd)115 static 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
sof_rt1011_dai_link(struct snd_soc_dai_link * link)127 void 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
sof_rt1011_codec_conf(struct snd_soc_card * card)135 void 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 * rt1015: i2c mode driver for ALC1015 and ALC1015Q
143 * rt1015p: auto-mode driver for ALC1015, ALC1015Q, and ALC1015Q-VB
144 *
145 * For stereo output, there are always two amplifiers on the board.
146 * However, the ACPI implements only one device instance (UID=0) if they
147 * are sharing the same enable pin. The code will detect the number of
148 * device instance and use corresponding DAPM structures for
149 * initialization.
150 */
151 static const struct snd_soc_dapm_route rt1015p_1dev_dapm_routes[] = {
152 /* speaker */
153 { "Left Spk", NULL, "Speaker" },
154 { "Right Spk", NULL, "Speaker" },
155 };
156
157 static const struct snd_soc_dapm_route rt1015p_2dev_dapm_routes[] = {
158 /* speaker */
159 { "Left Spk", NULL, "Left Speaker" },
160 { "Right Spk", NULL, "Right Speaker" },
161 };
162
163 static 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
174 static 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
rt1015p_get_num_codecs(void)185 static 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
rt1015p_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)200 static int rt1015p_hw_params(struct snd_pcm_substream *substream,
201 struct snd_pcm_hw_params *params)
202 {
203 /* reserved for debugging purpose */
204
205 return 0;
206 }
207
208 static const struct snd_soc_ops rt1015p_ops = {
209 .hw_params = rt1015p_hw_params,
210 };
211
rt1015p_init(struct snd_soc_pcm_runtime * rtd)212 static 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
sof_rt1015p_dai_link(struct snd_soc_dai_link * link)228 void 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
sof_rt1015p_codec_conf(struct snd_soc_card * card)236 void 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