1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 //
3 // This file is provided under a dual BSD/GPLv2 license. When using or
4 // redistributing this file, you may do so under either license.
5 //
6 // Copyright(c) 2021 Advanced Micro Devices, Inc.
7 //
8 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
9 //	    Vijendar Mukunda <Vijendar.Mukunda@amd.com>
10 //
11 
12 /*
13  * Machine Driver Interface for ACP HW block
14  */
15 
16 #include <sound/core.h>
17 #include <sound/jack.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc-dapm.h>
20 #include <sound/soc.h>
21 #include <linux/input.h>
22 #include <linux/module.h>
23 
24 #include "../../codecs/rt5682.h"
25 #include "../../codecs/rt1019.h"
26 #include "../../codecs/rt5682s.h"
27 #include "../../codecs/nau8825.h"
28 #include "acp-mach.h"
29 
30 #define PCO_PLAT_CLK 48000000
31 #define RT5682_PLL_FREQ (48000 * 512)
32 #define DUAL_CHANNEL	2
33 #define FOUR_CHANNEL	4
34 
35 static struct snd_soc_jack pco_jack;
36 
37 static const unsigned int channels[] = {
38 	DUAL_CHANNEL,
39 };
40 
41 static const unsigned int rates[] = {
42 	48000,
43 };
44 
45 static const struct snd_pcm_hw_constraint_list constraints_rates = {
46 	.count = ARRAY_SIZE(rates),
47 	.list  = rates,
48 	.mask = 0,
49 };
50 
51 static const struct snd_pcm_hw_constraint_list constraints_channels = {
52 	.count = ARRAY_SIZE(channels),
53 	.list = channels,
54 	.mask = 0,
55 };
56 
57 static int acp_clk_enable(struct acp_card_drvdata *drvdata,
58 			  unsigned int srate, unsigned int bclk_ratio)
59 {
60 	clk_set_rate(drvdata->wclk, srate);
61 	clk_set_rate(drvdata->bclk, srate * bclk_ratio);
62 
63 	return clk_prepare_enable(drvdata->wclk);
64 }
65 
66 /* Declare RT5682 codec components */
67 SND_SOC_DAILINK_DEF(rt5682,
68 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
69 
70 static const struct snd_soc_dapm_route rt5682_map[] = {
71 	{ "Headphone Jack", NULL, "HPOL" },
72 	{ "Headphone Jack", NULL, "HPOR" },
73 	{ "IN1P", NULL, "Headset Mic" },
74 };
75 
76 /* Define card ops for RT5682 CODEC */
77 static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
78 {
79 	struct snd_soc_card *card = rtd->card;
80 	struct acp_card_drvdata *drvdata = card->drvdata;
81 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
82 	struct snd_soc_component *component = codec_dai->component;
83 	int ret;
84 
85 	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
86 
87 	if (drvdata->hs_codec_id != RT5682)
88 		return -EINVAL;
89 
90 	drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
91 	drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
92 
93 	ret = snd_soc_card_jack_new(card, "Headset Jack",
94 				    SND_JACK_HEADSET | SND_JACK_LINEOUT |
95 				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
96 				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
97 				    &pco_jack);
98 	if (ret) {
99 		dev_err(card->dev, "HP jack creation failed %d\n", ret);
100 		return ret;
101 	}
102 
103 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
104 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
105 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
106 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
107 
108 	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
109 	if (ret) {
110 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
111 		return ret;
112 	}
113 
114 	return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
115 }
116 
117 static int acp_card_hs_startup(struct snd_pcm_substream *substream)
118 {
119 	struct snd_pcm_runtime *runtime = substream->runtime;
120 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
121 	struct snd_soc_card *card = rtd->card;
122 	struct acp_card_drvdata *drvdata = card->drvdata;
123 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
124 	int ret;
125 	unsigned int fmt;
126 
127 	if (drvdata->soc_mclk)
128 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
129 	else
130 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
131 
132 	ret =  snd_soc_dai_set_fmt(codec_dai, fmt);
133 	if (ret < 0) {
134 		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
135 		return ret;
136 	}
137 
138 	runtime->hw.channels_max = DUAL_CHANNEL;
139 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
140 				      &constraints_channels);
141 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
142 				      &constraints_rates);
143 
144 	return ret;
145 }
146 
147 static void acp_card_shutdown(struct snd_pcm_substream *substream)
148 {
149 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
150 	struct snd_soc_card *card = rtd->card;
151 	struct acp_card_drvdata *drvdata = card->drvdata;
152 
153 	if (!drvdata->soc_mclk)
154 		clk_disable_unprepare(drvdata->wclk);
155 }
156 
157 static int acp_card_rt5682_hw_params(struct snd_pcm_substream *substream,
158 				      struct snd_pcm_hw_params *params)
159 {
160 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
161 	struct snd_soc_card *card = rtd->card;
162 	struct acp_card_drvdata *drvdata = card->drvdata;
163 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
164 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
165 	int ret;
166 	unsigned int fmt, srate, ch, format;
167 
168 	srate = params_rate(params);
169 	ch = params_channels(params);
170 	format = 8 * params_format(params);
171 
172 	if (drvdata->soc_mclk)
173 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
174 	else
175 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
176 
177 	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
178 	if (ret && ret != -ENOTSUPP) {
179 		dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);
180 		return ret;
181 	}
182 
183 	ret =  snd_soc_dai_set_fmt(codec_dai, fmt);
184 	if (ret < 0) {
185 		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
186 		return ret;
187 	}
188 
189 	ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK,
190 				  PCO_PLAT_CLK, RT5682_PLL_FREQ);
191 	if (ret < 0) {
192 		dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
193 		return ret;
194 	}
195 
196 	ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2,
197 				     RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
198 	if (ret < 0) {
199 		dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
200 		return ret;
201 	}
202 
203 	/* Set tdm/i2s1 master bclk ratio */
204 	ret = snd_soc_dai_set_bclk_ratio(codec_dai, ch * format);
205 	if (ret < 0) {
206 		dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
207 		return ret;
208 	}
209 
210 	if (!drvdata->soc_mclk) {
211 		ret = acp_clk_enable(drvdata, srate, ch * format);
212 		if (ret < 0) {
213 			dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);
214 			return ret;
215 		}
216 	}
217 
218 	return 0;
219 }
220 
221 static const struct snd_soc_ops acp_card_rt5682_ops = {
222 	.startup = acp_card_hs_startup,
223 	.shutdown = acp_card_shutdown,
224 	.hw_params = acp_card_rt5682_hw_params,
225 };
226 
227 /* Define RT5682S CODEC component*/
228 SND_SOC_DAILINK_DEF(rt5682s,
229 		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1")));
230 
231 static const struct snd_soc_dapm_route rt5682s_map[] = {
232 	{ "Headphone Jack", NULL, "HPOL" },
233 	{ "Headphone Jack", NULL, "HPOR" },
234 	{ "IN1P", NULL, "Headset Mic" },
235 };
236 
237 static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
238 {
239 	struct snd_soc_card *card = rtd->card;
240 	struct acp_card_drvdata *drvdata = card->drvdata;
241 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
242 	struct snd_soc_component *component = codec_dai->component;
243 	int ret;
244 
245 	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
246 
247 	if (drvdata->hs_codec_id != RT5682S)
248 		return -EINVAL;
249 
250 	if (!drvdata->soc_mclk) {
251 		drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
252 		drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
253 	}
254 
255 	ret = snd_soc_card_jack_new(card, "Headset Jack",
256 				    SND_JACK_HEADSET | SND_JACK_LINEOUT |
257 				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
258 				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
259 				    &pco_jack);
260 	if (ret) {
261 		dev_err(card->dev, "HP jack creation failed %d\n", ret);
262 		return ret;
263 	}
264 
265 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
266 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
267 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
268 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
269 
270 	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
271 	if (ret) {
272 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
273 		return ret;
274 	}
275 
276 	return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682s_map, ARRAY_SIZE(rt5682s_map));
277 }
278 
279 static int acp_card_rt5682s_hw_params(struct snd_pcm_substream *substream,
280 				      struct snd_pcm_hw_params *params)
281 {
282 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
283 	struct snd_soc_card *card = rtd->card;
284 	struct acp_card_drvdata *drvdata = card->drvdata;
285 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
286 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
287 	int ret;
288 	unsigned int fmt, srate, ch, format;
289 
290 	srate = params_rate(params);
291 	ch = params_channels(params);
292 	format = 8 * params_format(params);
293 
294 	if (drvdata->soc_mclk)
295 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
296 	else
297 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
298 
299 	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
300 	if (ret && ret != -ENOTSUPP) {
301 		dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);
302 		return ret;
303 	}
304 
305 	ret =  snd_soc_dai_set_fmt(codec_dai, fmt);
306 	if (ret < 0) {
307 		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
308 		return ret;
309 	}
310 
311 	ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK,
312 				  PCO_PLAT_CLK, RT5682_PLL_FREQ);
313 	if (ret < 0) {
314 		dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
315 		return ret;
316 	}
317 
318 	ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2,
319 				     RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
320 	if (ret < 0) {
321 		dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
322 		return ret;
323 	}
324 
325 	/* Set tdm/i2s1 master bclk ratio */
326 	ret = snd_soc_dai_set_bclk_ratio(codec_dai, ch * format);
327 	if (ret < 0) {
328 		dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
329 		return ret;
330 	}
331 
332 	clk_set_rate(drvdata->wclk, srate);
333 	clk_set_rate(drvdata->bclk, srate * ch * format);
334 
335 	return 0;
336 }
337 
338 static const struct snd_soc_ops acp_card_rt5682s_ops = {
339 	.startup = acp_card_hs_startup,
340 	.hw_params = acp_card_rt5682s_hw_params,
341 };
342 
343 static const unsigned int dmic_channels[] = {
344 	DUAL_CHANNEL, FOUR_CHANNEL,
345 };
346 
347 static const struct snd_pcm_hw_constraint_list dmic_constraints_channels = {
348 	.count = ARRAY_SIZE(dmic_channels),
349 	.list = dmic_channels,
350 	.mask = 0,
351 };
352 
353 static int acp_card_dmic_startup(struct snd_pcm_substream *substream)
354 {
355 	struct snd_pcm_runtime *runtime = substream->runtime;
356 
357 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
358 				   &dmic_constraints_channels);
359 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
360 				   &constraints_rates);
361 
362 	return 0;
363 }
364 
365 static const struct snd_soc_ops acp_card_dmic_ops = {
366 	.startup = acp_card_dmic_startup,
367 };
368 
369 /* Declare RT1019 codec components */
370 SND_SOC_DAILINK_DEF(rt1019,
371 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"),
372 			  COMP_CODEC("i2c-10EC1019:01", "rt1019-aif")));
373 
374 static const struct snd_soc_dapm_route rt1019_map_lr[] = {
375 	{ "Left Spk", NULL, "Left SPO" },
376 	{ "Right Spk", NULL, "Right SPO" },
377 };
378 
379 static struct snd_soc_codec_conf rt1019_conf[] = {
380 	{
381 		 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),
382 		 .name_prefix = "Left",
383 	},
384 	{
385 		 .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"),
386 		 .name_prefix = "Right",
387 	},
388 };
389 
390 static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd)
391 {
392 	struct snd_soc_card *card = rtd->card;
393 	struct acp_card_drvdata *drvdata = card->drvdata;
394 
395 	if (drvdata->amp_codec_id != RT1019)
396 		return -EINVAL;
397 
398 	return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,
399 				       ARRAY_SIZE(rt1019_map_lr));
400 }
401 
402 static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
403 				     struct snd_pcm_hw_params *params)
404 {
405 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
406 	struct snd_soc_card *card = rtd->card;
407 	struct acp_card_drvdata *drvdata = card->drvdata;
408 	struct snd_soc_dai *codec_dai;
409 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
410 	int i, ret = 0;
411 	unsigned int fmt, srate, ch, format;
412 
413 	srate = params_rate(params);
414 	ch = params_channels(params);
415 	format = 8 * params_format(params);
416 
417 	if (drvdata->amp_codec_id != RT1019)
418 		return -EINVAL;
419 
420 	if (drvdata->soc_mclk)
421 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
422 	else
423 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
424 
425 	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
426 	if (ret && ret != -ENOTSUPP) {
427 		dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);
428 		return ret;
429 	}
430 
431 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
432 		if (strcmp(codec_dai->name, "rt1019-aif"))
433 			continue;
434 
435 		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
436 					  ch * format * srate, 256 * srate);
437 		if (ret < 0)
438 			return ret;
439 
440 		ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL,
441 					     256 * srate, SND_SOC_CLOCK_IN);
442 		if (ret < 0)
443 			return ret;
444 	}
445 
446 	if (!drvdata->soc_mclk) {
447 		ret = acp_clk_enable(drvdata, srate, ch * format);
448 		if (ret < 0) {
449 			dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
450 			return ret;
451 		}
452 	}
453 
454 	return 0;
455 }
456 
457 static int acp_card_amp_startup(struct snd_pcm_substream *substream)
458 {
459 	struct snd_pcm_runtime *runtime = substream->runtime;
460 
461 	runtime->hw.channels_max = DUAL_CHANNEL;
462 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
463 				      &constraints_channels);
464 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
465 				      &constraints_rates);
466 
467 	return 0;
468 }
469 
470 static const struct snd_soc_ops acp_card_rt1019_ops = {
471 	.startup = acp_card_amp_startup,
472 	.shutdown = acp_card_shutdown,
473 	.hw_params = acp_card_rt1019_hw_params,
474 };
475 
476 /* Declare Maxim codec components */
477 SND_SOC_DAILINK_DEF(max98360a,
478 	DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
479 
480 static const struct snd_soc_dapm_route max98360a_map[] = {
481 	{"Spk", NULL, "Speaker"},
482 };
483 
484 static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd)
485 {
486 	struct snd_soc_card *card = rtd->card;
487 	struct acp_card_drvdata *drvdata = card->drvdata;
488 
489 	if (drvdata->amp_codec_id != MAX98360A)
490 		return -EINVAL;
491 
492 	return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map,
493 				       ARRAY_SIZE(max98360a_map));
494 }
495 
496 static int acp_card_maxim_hw_params(struct snd_pcm_substream *substream,
497 				    struct snd_pcm_hw_params *params)
498 {
499 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
500 	struct snd_soc_card *card = rtd->card;
501 	struct acp_card_drvdata *drvdata = card->drvdata;
502 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
503 	unsigned int fmt, srate, ch, format;
504 	int ret;
505 
506 	srate = params_rate(params);
507 	ch = params_channels(params);
508 	format = 8 * params_format(params);
509 
510 	if (drvdata->soc_mclk)
511 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
512 	else
513 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
514 
515 	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
516 	if (ret && ret != -ENOTSUPP) {
517 		dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);
518 		return ret;
519 	}
520 
521 	if (!drvdata->soc_mclk) {
522 		ret = acp_clk_enable(drvdata, srate, ch * format);
523 		if (ret < 0) {
524 			dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
525 			return ret;
526 		}
527 	}
528 	return 0;
529 }
530 
531 static const struct snd_soc_ops acp_card_maxim_ops = {
532 	.startup = acp_card_amp_startup,
533 	.shutdown = acp_card_shutdown,
534 	.hw_params = acp_card_maxim_hw_params,
535 };
536 
537 /* Declare nau8825 codec components */
538 SND_SOC_DAILINK_DEF(nau8825,
539 		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", "nau8825-hifi")));
540 
541 static const struct snd_soc_dapm_route nau8825_map[] = {
542 	{ "Headphone Jack", NULL, "HPOL" },
543 	{ "Headphone Jack", NULL, "HPOR" },
544 };
545 
546 static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)
547 {
548 	struct snd_soc_card *card = rtd->card;
549 	struct acp_card_drvdata *drvdata = card->drvdata;
550 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
551 	struct snd_soc_component *component = codec_dai->component;
552 	int ret;
553 
554 	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
555 
556 	if (drvdata->hs_codec_id != NAU8825)
557 		return -EINVAL;
558 
559 	ret = snd_soc_card_jack_new(card, "Headset Jack",
560 					 SND_JACK_HEADSET | SND_JACK_LINEOUT |
561 					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
562 					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
563 					 &pco_jack);
564 	if (ret) {
565 		dev_err(card->dev, "HP jack creation failed %d\n", ret);
566 		return ret;
567 	}
568 
569 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
570 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
571 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
572 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
573 
574 	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
575 	if (ret) {
576 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
577 		return ret;
578 	}
579 
580 	return snd_soc_dapm_add_routes(&rtd->card->dapm, nau8825_map, ARRAY_SIZE(nau8825_map));
581 }
582 
583 static int acp_nau8825_hw_params(struct snd_pcm_substream *substream,
584 				 struct snd_pcm_hw_params *params)
585 {
586 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
587 	struct snd_soc_card *card = rtd->card;
588 	struct acp_card_drvdata *drvdata = card->drvdata;
589 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
590 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
591 	int ret;
592 	unsigned int fmt;
593 
594 	ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_FS,
595 				     (48000 * 256), SND_SOC_CLOCK_IN);
596 	if (ret < 0)
597 		dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
598 
599 	ret = snd_soc_dai_set_pll(codec_dai, 0, 0, params_rate(params),
600 				  params_rate(params) * 256);
601 	if (ret < 0) {
602 		dev_err(rtd->dev, "can't set FLL: %d\n", ret);
603 		return ret;
604 	}
605 
606 	if (drvdata->soc_mclk)
607 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
608 	else
609 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
610 
611 	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
612 	if (ret && ret != -ENOTSUPP) {
613 		dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);
614 		return ret;
615 	}
616 
617 	ret =  snd_soc_dai_set_fmt(codec_dai, fmt);
618 	if (ret < 0) {
619 		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
620 		return ret;
621 	}
622 
623 	return ret;
624 }
625 
626 static int acp_nau8825_startup(struct snd_pcm_substream *substream)
627 {
628 	struct snd_pcm_runtime *runtime = substream->runtime;
629 
630 	runtime->hw.channels_max = 2;
631 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
632 				   &constraints_channels);
633 
634 	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
635 	snd_pcm_hw_constraint_list(runtime, 0,
636 				   SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
637 	return 0;
638 }
639 
640 static const struct snd_soc_ops acp_card_nau8825_ops = {
641 	.startup =  acp_nau8825_startup,
642 	.hw_params = acp_nau8825_hw_params,
643 };
644 
645 /* Declare DMIC codec components */
646 SND_SOC_DAILINK_DEF(dmic_codec,
647 		DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
648 
649 /* Declare ACP CPU components */
650 static struct snd_soc_dai_link_component dummy_codec[] = {
651 	{
652 		.name = "snd-soc-dummy",
653 		.dai_name = "snd-soc-dummy-dai",
654 	}
655 };
656 
657 static struct snd_soc_dai_link_component platform_component[] = {
658 	{
659 		 .name = "acp_asoc_renoir.0",
660 	}
661 };
662 
663 static struct snd_soc_dai_link_component platform_rmb_component[] = {
664 	{
665 		.name = "acp_asoc_rembrandt.0",
666 	}
667 };
668 
669 static struct snd_soc_dai_link_component sof_component[] = {
670 	{
671 		 .name = "0000:04:00.5",
672 	}
673 };
674 
675 SND_SOC_DAILINK_DEF(i2s_sp,
676 	DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));
677 SND_SOC_DAILINK_DEF(i2s_hs,
678 		    DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-hs")));
679 SND_SOC_DAILINK_DEF(sof_sp,
680 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
681 SND_SOC_DAILINK_DEF(sof_sp_virtual,
682 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp-virtual")));
683 SND_SOC_DAILINK_DEF(sof_hs,
684 		    DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs")));
685 SND_SOC_DAILINK_DEF(sof_hs_virtual,
686 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs-virtual")));
687 SND_SOC_DAILINK_DEF(sof_dmic,
688 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
689 SND_SOC_DAILINK_DEF(pdm_dmic,
690 	DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic")));
691 
692 static int acp_rtk_set_bias_level(struct snd_soc_card *card,
693 				  struct snd_soc_dapm_context *dapm,
694 				  enum snd_soc_bias_level level)
695 {
696 	struct snd_soc_component *component = dapm->component;
697 	struct acp_card_drvdata *drvdata = card->drvdata;
698 	int ret = 0;
699 
700 	if (!component)
701 		return 0;
702 
703 	if (strncmp(component->name, "i2c-RTL5682", 11) &&
704 	    strncmp(component->name, "i2c-10EC1019", 12))
705 		return 0;
706 
707 	/*
708 	 * For Realtek's codec and amplifier components,
709 	 * the lrck and bclk must be enabled brfore their all dapms be powered on,
710 	 * and must be disabled after their all dapms be powered down
711 	 * to avoid any pop.
712 	 */
713 	switch (level) {
714 	case SND_SOC_BIAS_STANDBY:
715 		if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) {
716 
717 			/* Increase bclk's enable_count */
718 			ret = clk_prepare_enable(drvdata->bclk);
719 			if (ret < 0)
720 				dev_err(component->dev, "Failed to enable bclk %d\n", ret);
721 		} else {
722 			/*
723 			 * Decrease bclk's enable_count.
724 			 * While the enable_count is 0, the bclk would be closed.
725 			 */
726 			clk_disable_unprepare(drvdata->bclk);
727 		}
728 		break;
729 	default:
730 		break;
731 	}
732 
733 	return ret;
734 }
735 
736 int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
737 {
738 	struct snd_soc_dai_link *links;
739 	struct device *dev = card->dev;
740 	struct acp_card_drvdata *drv_data = card->drvdata;
741 	int i = 0, num_links = 0;
742 
743 	if (drv_data->hs_cpu_id)
744 		num_links++;
745 	if (drv_data->amp_cpu_id)
746 		num_links++;
747 	if (drv_data->dmic_cpu_id)
748 		num_links++;
749 
750 	links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL);
751 	if (!links)
752 		return -ENOMEM;
753 
754 	if (drv_data->hs_cpu_id == I2S_SP) {
755 		links[i].name = "acp-headset-codec";
756 		links[i].id = HEADSET_BE_ID;
757 		links[i].cpus = sof_sp;
758 		links[i].num_cpus = ARRAY_SIZE(sof_sp);
759 		links[i].platforms = sof_component;
760 		links[i].num_platforms = ARRAY_SIZE(sof_component);
761 		links[i].dpcm_playback = 1;
762 		links[i].dpcm_capture = 1;
763 		links[i].nonatomic = true;
764 		links[i].no_pcm = 1;
765 		if (!drv_data->hs_codec_id) {
766 			/* Use dummy codec if codec id not specified */
767 			links[i].codecs = dummy_codec;
768 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
769 		}
770 		if (drv_data->hs_codec_id == RT5682) {
771 			links[i].codecs = rt5682;
772 			links[i].num_codecs = ARRAY_SIZE(rt5682);
773 			links[i].init = acp_card_rt5682_init;
774 			links[i].ops = &acp_card_rt5682_ops;
775 		}
776 		if (drv_data->hs_codec_id == RT5682S) {
777 			links[i].codecs = rt5682s;
778 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
779 			links[i].init = acp_card_rt5682s_init;
780 			links[i].ops = &acp_card_rt5682s_ops;
781 		}
782 		i++;
783 	}
784 
785 	if (drv_data->hs_cpu_id == I2S_HS) {
786 		links[i].name = "acp-headset-codec";
787 		links[i].id = HEADSET_BE_ID;
788 		links[i].cpus = sof_hs;
789 		links[i].num_cpus = ARRAY_SIZE(sof_hs);
790 		links[i].platforms = sof_component;
791 		links[i].num_platforms = ARRAY_SIZE(sof_component);
792 		links[i].dpcm_playback = 1;
793 		links[i].dpcm_capture = 1;
794 		links[i].nonatomic = true;
795 		links[i].no_pcm = 1;
796 		if (!drv_data->hs_codec_id) {
797 			/* Use dummy codec if codec id not specified */
798 			links[i].codecs = dummy_codec;
799 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
800 		}
801 		if (drv_data->hs_codec_id == NAU8825) {
802 			links[i].codecs = nau8825;
803 			links[i].num_codecs = ARRAY_SIZE(nau8825);
804 			links[i].init = acp_card_nau8825_init;
805 			links[i].ops = &acp_card_nau8825_ops;
806 		}
807 		if (drv_data->hs_codec_id == RT5682S) {
808 			links[i].codecs = rt5682s;
809 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
810 			links[i].init = acp_card_rt5682s_init;
811 			links[i].ops = &acp_card_rt5682s_ops;
812 		}
813 		i++;
814 	}
815 
816 	if (drv_data->amp_cpu_id == I2S_SP) {
817 		links[i].name = "acp-amp-codec";
818 		links[i].id = AMP_BE_ID;
819 		links[i].cpus = sof_sp_virtual;
820 		links[i].num_cpus = ARRAY_SIZE(sof_sp_virtual);
821 		links[i].platforms = sof_component;
822 		links[i].num_platforms = ARRAY_SIZE(sof_component);
823 		links[i].dpcm_playback = 1;
824 		links[i].nonatomic = true;
825 		links[i].no_pcm = 1;
826 		if (!drv_data->amp_codec_id) {
827 			/* Use dummy codec if codec id not specified */
828 			links[i].codecs = dummy_codec;
829 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
830 		}
831 		if (drv_data->amp_codec_id == RT1019) {
832 			links[i].codecs = rt1019;
833 			links[i].num_codecs = ARRAY_SIZE(rt1019);
834 			links[i].ops = &acp_card_rt1019_ops;
835 			links[i].init = acp_card_rt1019_init;
836 			card->codec_conf = rt1019_conf;
837 			card->num_configs = ARRAY_SIZE(rt1019_conf);
838 		}
839 		if (drv_data->amp_codec_id == MAX98360A) {
840 			links[i].codecs = max98360a;
841 			links[i].num_codecs = ARRAY_SIZE(max98360a);
842 			links[i].ops = &acp_card_maxim_ops;
843 			links[i].init = acp_card_maxim_init;
844 		}
845 		i++;
846 	}
847 
848 	if (drv_data->amp_cpu_id == I2S_HS) {
849 		links[i].name = "acp-amp-codec";
850 		links[i].id = AMP_BE_ID;
851 		links[i].cpus = sof_hs_virtual;
852 		links[i].num_cpus = ARRAY_SIZE(sof_hs_virtual);
853 		links[i].platforms = sof_component;
854 		links[i].num_platforms = ARRAY_SIZE(sof_component);
855 		links[i].dpcm_playback = 1;
856 		links[i].nonatomic = true;
857 		links[i].no_pcm = 1;
858 		if (!drv_data->amp_codec_id) {
859 			/* Use dummy codec if codec id not specified */
860 			links[i].codecs = dummy_codec;
861 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
862 		}
863 		if (drv_data->amp_codec_id == MAX98360A) {
864 			links[i].codecs = max98360a;
865 			links[i].num_codecs = ARRAY_SIZE(max98360a);
866 			links[i].ops = &acp_card_maxim_ops;
867 			links[i].init = acp_card_maxim_init;
868 		}
869 		if (drv_data->amp_codec_id == RT1019) {
870 			links[i].codecs = rt1019;
871 			links[i].num_codecs = ARRAY_SIZE(rt1019);
872 			links[i].ops = &acp_card_rt1019_ops;
873 			links[i].init = acp_card_rt1019_init;
874 			card->codec_conf = rt1019_conf;
875 			card->num_configs = ARRAY_SIZE(rt1019_conf);
876 		}
877 		i++;
878 	}
879 
880 	if (drv_data->dmic_cpu_id == DMIC) {
881 		links[i].name = "acp-dmic-codec";
882 		links[i].id = DMIC_BE_ID;
883 		links[i].codecs = dmic_codec;
884 		links[i].num_codecs = ARRAY_SIZE(dmic_codec);
885 		links[i].cpus = sof_dmic;
886 		links[i].num_cpus = ARRAY_SIZE(sof_dmic);
887 		links[i].platforms = sof_component;
888 		links[i].num_platforms = ARRAY_SIZE(sof_component);
889 		links[i].dpcm_capture = 1;
890 		links[i].nonatomic = true;
891 		links[i].no_pcm = 1;
892 	}
893 
894 	card->dai_link = links;
895 	card->num_links = num_links;
896 	card->set_bias_level = acp_rtk_set_bias_level;
897 
898 	return 0;
899 }
900 EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);
901 
902 int acp_legacy_dai_links_create(struct snd_soc_card *card)
903 {
904 	struct snd_soc_dai_link *links;
905 	struct device *dev = card->dev;
906 	struct acp_card_drvdata *drv_data = card->drvdata;
907 	int i = 0, num_links = 0;
908 
909 	if (drv_data->hs_cpu_id)
910 		num_links++;
911 	if (drv_data->amp_cpu_id)
912 		num_links++;
913 	if (drv_data->dmic_cpu_id)
914 		num_links++;
915 
916 	links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL);
917 	if (!links)
918 		return -ENOMEM;
919 
920 	if (drv_data->hs_cpu_id == I2S_SP) {
921 		links[i].name = "acp-headset-codec";
922 		links[i].id = HEADSET_BE_ID;
923 		links[i].cpus = i2s_sp;
924 		links[i].num_cpus = ARRAY_SIZE(i2s_sp);
925 		links[i].platforms = platform_component;
926 		links[i].num_platforms = ARRAY_SIZE(platform_component);
927 		links[i].dpcm_playback = 1;
928 		links[i].dpcm_capture = 1;
929 		if (!drv_data->hs_codec_id) {
930 			/* Use dummy codec if codec id not specified */
931 			links[i].codecs = dummy_codec;
932 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
933 		}
934 		if (drv_data->hs_codec_id == RT5682) {
935 			links[i].codecs = rt5682;
936 			links[i].num_codecs = ARRAY_SIZE(rt5682);
937 			links[i].init = acp_card_rt5682_init;
938 			links[i].ops = &acp_card_rt5682_ops;
939 		}
940 		if (drv_data->hs_codec_id == RT5682S) {
941 			links[i].codecs = rt5682s;
942 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
943 			links[i].init = acp_card_rt5682s_init;
944 			links[i].ops = &acp_card_rt5682s_ops;
945 		}
946 		i++;
947 	}
948 
949 	if (drv_data->hs_cpu_id == I2S_HS) {
950 		links[i].name = "acp-headset-codec";
951 		links[i].id = HEADSET_BE_ID;
952 		links[i].cpus = i2s_hs;
953 		links[i].num_cpus = ARRAY_SIZE(i2s_hs);
954 		if (drv_data->platform == REMBRANDT) {
955 			links[i].platforms = platform_rmb_component;
956 			links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
957 		} else {
958 			links[i].platforms = platform_component;
959 			links[i].num_platforms = ARRAY_SIZE(platform_component);
960 		}
961 		links[i].dpcm_playback = 1;
962 		links[i].dpcm_capture = 1;
963 		if (!drv_data->hs_codec_id) {
964 			/* Use dummy codec if codec id not specified */
965 			links[i].codecs = dummy_codec;
966 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
967 		}
968 		if (drv_data->hs_codec_id == NAU8825) {
969 			links[i].codecs = nau8825;
970 			links[i].num_codecs = ARRAY_SIZE(nau8825);
971 			links[i].init = acp_card_nau8825_init;
972 			links[i].ops = &acp_card_nau8825_ops;
973 		}
974 		if (drv_data->hs_codec_id == RT5682S) {
975 			links[i].codecs = rt5682s;
976 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
977 			links[i].init = acp_card_rt5682s_init;
978 			links[i].ops = &acp_card_rt5682s_ops;
979 		}
980 		i++;
981 	}
982 
983 	if (drv_data->amp_cpu_id == I2S_SP) {
984 		links[i].name = "acp-amp-codec";
985 		links[i].id = AMP_BE_ID;
986 		links[i].cpus = i2s_sp;
987 		links[i].num_cpus = ARRAY_SIZE(i2s_sp);
988 		links[i].platforms = platform_component;
989 		links[i].num_platforms = ARRAY_SIZE(platform_component);
990 		links[i].dpcm_playback = 1;
991 		if (!drv_data->amp_codec_id) {
992 			/* Use dummy codec if codec id not specified */
993 			links[i].codecs = dummy_codec;
994 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
995 		}
996 		if (drv_data->amp_codec_id == RT1019) {
997 			links[i].codecs = rt1019;
998 			links[i].num_codecs = ARRAY_SIZE(rt1019);
999 			links[i].ops = &acp_card_rt1019_ops;
1000 			links[i].init = acp_card_rt1019_init;
1001 			card->codec_conf = rt1019_conf;
1002 			card->num_configs = ARRAY_SIZE(rt1019_conf);
1003 		}
1004 		if (drv_data->amp_codec_id == MAX98360A) {
1005 			links[i].codecs = max98360a;
1006 			links[i].num_codecs = ARRAY_SIZE(max98360a);
1007 			links[i].ops = &acp_card_maxim_ops;
1008 			links[i].init = acp_card_maxim_init;
1009 		}
1010 		i++;
1011 	}
1012 
1013 	if (drv_data->amp_cpu_id == I2S_HS) {
1014 		links[i].name = "acp-amp-codec";
1015 		links[i].id = AMP_BE_ID;
1016 		links[i].cpus = i2s_hs;
1017 		links[i].num_cpus = ARRAY_SIZE(i2s_hs);
1018 		if (drv_data->platform == REMBRANDT) {
1019 			links[i].platforms = platform_rmb_component;
1020 			links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
1021 		} else {
1022 			links[i].platforms = platform_component;
1023 			links[i].num_platforms = ARRAY_SIZE(platform_component);
1024 		}
1025 		links[i].dpcm_playback = 1;
1026 		if (!drv_data->amp_codec_id) {
1027 			/* Use dummy codec if codec id not specified */
1028 			links[i].codecs = dummy_codec;
1029 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
1030 		}
1031 		if (drv_data->amp_codec_id == MAX98360A) {
1032 			links[i].codecs = max98360a;
1033 			links[i].num_codecs = ARRAY_SIZE(max98360a);
1034 			links[i].ops = &acp_card_maxim_ops;
1035 			links[i].init = acp_card_maxim_init;
1036 		}
1037 		if (drv_data->amp_codec_id == RT1019) {
1038 			links[i].codecs = rt1019;
1039 			links[i].num_codecs = ARRAY_SIZE(rt1019);
1040 			links[i].ops = &acp_card_rt1019_ops;
1041 			links[i].init = acp_card_rt1019_init;
1042 			card->codec_conf = rt1019_conf;
1043 			card->num_configs = ARRAY_SIZE(rt1019_conf);
1044 		}
1045 		i++;
1046 	}
1047 
1048 	if (drv_data->dmic_cpu_id == DMIC) {
1049 		links[i].name = "acp-dmic-codec";
1050 		links[i].id = DMIC_BE_ID;
1051 		if (drv_data->dmic_codec_id == DMIC) {
1052 			links[i].codecs = dmic_codec;
1053 			links[i].num_codecs = ARRAY_SIZE(dmic_codec);
1054 		} else {
1055 			/* Use dummy codec if codec id not specified */
1056 			links[i].codecs = dummy_codec;
1057 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
1058 		}
1059 		links[i].cpus = pdm_dmic;
1060 		links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
1061 		if (drv_data->platform == REMBRANDT) {
1062 			links[i].platforms = platform_rmb_component;
1063 			links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
1064 		} else {
1065 			links[i].platforms = platform_component;
1066 			links[i].num_platforms = ARRAY_SIZE(platform_component);
1067 		}
1068 		links[i].ops = &acp_card_dmic_ops;
1069 		links[i].dpcm_capture = 1;
1070 	}
1071 
1072 	card->dai_link = links;
1073 	card->num_links = num_links;
1074 	card->set_bias_level = acp_rtk_set_bias_level;
1075 
1076 	return 0;
1077 }
1078 EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
1079 
1080 MODULE_LICENSE("GPL v2");
1081