1/*
2 * Machine driver for AMD ACP Audio engine using DA7219 & MAX98357 codec
3 *
4 * Copyright 2017 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25
26#include <sound/core.h>
27#include <sound/soc.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc-dapm.h>
31#include <sound/jack.h>
32#include <linux/clk.h>
33#include <linux/gpio.h>
34#include <linux/module.h>
35#include <linux/regulator/machine.h>
36#include <linux/regulator/driver.h>
37#include <linux/i2c.h>
38#include <linux/input.h>
39#include <linux/acpi.h>
40
41#include "acp.h"
42#include "../codecs/da7219.h"
43#include "../codecs/da7219-aad.h"
44
45#define CZ_PLAT_CLK 48000000
46#define DUAL_CHANNEL		2
47
48static struct snd_soc_jack cz_jack;
49static struct clk *da7219_dai_wclk;
50static struct clk *da7219_dai_bclk;
51extern bool bt_uart_enable;
52
53static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
54{
55	int ret;
56	struct snd_soc_card *card = rtd->card;
57	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
58	struct snd_soc_component *component = codec_dai->component;
59
60	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
61
62	ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK,
63				     CZ_PLAT_CLK, SND_SOC_CLOCK_IN);
64	if (ret < 0) {
65		dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
66		return ret;
67	}
68
69	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL,
70				  CZ_PLAT_CLK, DA7219_PLL_FREQ_OUT_98304);
71	if (ret < 0) {
72		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
73		return ret;
74	}
75
76	da7219_dai_wclk = devm_clk_get(component->dev, "da7219-dai-wclk");
77	if (IS_ERR(da7219_dai_wclk))
78		return PTR_ERR(da7219_dai_wclk);
79
80	da7219_dai_bclk = devm_clk_get(component->dev, "da7219-dai-bclk");
81	if (IS_ERR(da7219_dai_bclk))
82		return PTR_ERR(da7219_dai_bclk);
83
84	ret = snd_soc_card_jack_new(card, "Headset Jack",
85				SND_JACK_HEADSET | SND_JACK_LINEOUT |
86				SND_JACK_BTN_0 | SND_JACK_BTN_1 |
87				SND_JACK_BTN_2 | SND_JACK_BTN_3,
88				&cz_jack, NULL, 0);
89	if (ret) {
90		dev_err(card->dev, "HP jack creation failed %d\n", ret);
91		return ret;
92	}
93
94	snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
95	snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
96	snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
97	snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
98
99	da7219_aad_jack_det(component, &cz_jack);
100
101	return 0;
102}
103
104static int da7219_clk_enable(struct snd_pcm_substream *substream)
105{
106	int ret = 0;
107	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
108
109	/*
110	 * Set wclk to 48000 because the rate constraint of this driver is
111	 * 48000. ADAU7002 spec: "The ADAU7002 requires a BCLK rate that is
112	 * minimum of 64x the LRCLK sample rate." DA7219 is the only clk
113	 * source so for all codecs we have to limit bclk to 64X lrclk.
114	 */
115	clk_set_rate(da7219_dai_wclk, 48000);
116	clk_set_rate(da7219_dai_bclk, 48000 * 64);
117	ret = clk_prepare_enable(da7219_dai_bclk);
118	if (ret < 0) {
119		dev_err(rtd->dev, "can't enable master clock %d\n", ret);
120		return ret;
121	}
122
123	return ret;
124}
125
126static void da7219_clk_disable(void)
127{
128	clk_disable_unprepare(da7219_dai_bclk);
129}
130
131static const unsigned int channels[] = {
132	DUAL_CHANNEL,
133};
134
135static const unsigned int rates[] = {
136	48000,
137};
138
139static const struct snd_pcm_hw_constraint_list constraints_rates = {
140	.count = ARRAY_SIZE(rates),
141	.list  = rates,
142	.mask = 0,
143};
144
145static const struct snd_pcm_hw_constraint_list constraints_channels = {
146	.count = ARRAY_SIZE(channels),
147	.list = channels,
148	.mask = 0,
149};
150
151static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
152{
153	struct snd_pcm_runtime *runtime = substream->runtime;
154	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
155	struct snd_soc_card *card = rtd->card;
156	struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
157
158	/*
159	 * On this platform for PCM device we support stereo
160	 */
161
162	runtime->hw.channels_max = DUAL_CHANNEL;
163	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
164				   &constraints_channels);
165	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
166				   &constraints_rates);
167
168	machine->play_i2s_instance = I2S_SP_INSTANCE;
169	return da7219_clk_enable(substream);
170}
171
172static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
173{
174	struct snd_pcm_runtime *runtime = substream->runtime;
175	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
176	struct snd_soc_card *card = rtd->card;
177	struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
178
179	/*
180	 * On this platform for PCM device we support stereo
181	 */
182
183	runtime->hw.channels_max = DUAL_CHANNEL;
184	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
185				   &constraints_channels);
186	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
187				   &constraints_rates);
188
189	machine->cap_i2s_instance = I2S_SP_INSTANCE;
190	machine->capture_channel = CAP_CHANNEL1;
191	return da7219_clk_enable(substream);
192}
193
194static int cz_max_startup(struct snd_pcm_substream *substream)
195{
196	struct snd_pcm_runtime *runtime = substream->runtime;
197	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
198	struct snd_soc_card *card = rtd->card;
199	struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
200
201	/*
202	 * On this platform for PCM device we support stereo
203	 */
204
205	runtime->hw.channels_max = DUAL_CHANNEL;
206	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
207				   &constraints_channels);
208	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
209				   &constraints_rates);
210
211	machine->play_i2s_instance = I2S_BT_INSTANCE;
212	return da7219_clk_enable(substream);
213}
214
215static int cz_dmic0_startup(struct snd_pcm_substream *substream)
216{
217	struct snd_pcm_runtime *runtime = substream->runtime;
218	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
219	struct snd_soc_card *card = rtd->card;
220	struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
221
222	/*
223	 * On this platform for PCM device we support stereo
224	 */
225
226	runtime->hw.channels_max = DUAL_CHANNEL;
227	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
228				   &constraints_channels);
229	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
230				   &constraints_rates);
231
232	machine->cap_i2s_instance = I2S_BT_INSTANCE;
233	return da7219_clk_enable(substream);
234}
235
236static int cz_dmic1_startup(struct snd_pcm_substream *substream)
237{
238	struct snd_pcm_runtime *runtime = substream->runtime;
239	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
240	struct snd_soc_card *card = rtd->card;
241	struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
242
243	/*
244	 * On this platform for PCM device we support stereo
245	 */
246
247	runtime->hw.channels_max = DUAL_CHANNEL;
248	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
249				   &constraints_channels);
250	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
251				   &constraints_rates);
252
253	machine->cap_i2s_instance = I2S_SP_INSTANCE;
254	machine->capture_channel = CAP_CHANNEL0;
255	return da7219_clk_enable(substream);
256}
257
258static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
259{
260	da7219_clk_disable();
261}
262
263static const struct snd_soc_ops cz_da7219_play_ops = {
264	.startup = cz_da7219_play_startup,
265	.shutdown = cz_da7219_shutdown,
266};
267
268static const struct snd_soc_ops cz_da7219_cap_ops = {
269	.startup = cz_da7219_cap_startup,
270	.shutdown = cz_da7219_shutdown,
271};
272
273static const struct snd_soc_ops cz_max_play_ops = {
274	.startup = cz_max_startup,
275	.shutdown = cz_da7219_shutdown,
276};
277
278static const struct snd_soc_ops cz_dmic0_cap_ops = {
279	.startup = cz_dmic0_startup,
280	.shutdown = cz_da7219_shutdown,
281};
282
283static const struct snd_soc_ops cz_dmic1_cap_ops = {
284	.startup = cz_dmic1_startup,
285	.shutdown = cz_da7219_shutdown,
286};
287
288SND_SOC_DAILINK_DEF(designware1,
289	DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1.auto")));
290SND_SOC_DAILINK_DEF(designware2,
291	DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.2.auto")));
292SND_SOC_DAILINK_DEF(designware3,
293	DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.3.auto")));
294
295SND_SOC_DAILINK_DEF(dlgs,
296	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", "da7219-hifi")));
297SND_SOC_DAILINK_DEF(mx,
298	DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi")));
299SND_SOC_DAILINK_DEF(adau,
300	DAILINK_COMP_ARRAY(COMP_CODEC("ADAU7002:00", "adau7002-hifi")));
301
302SND_SOC_DAILINK_DEF(platform,
303	DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.0.auto")));
304
305static struct snd_soc_dai_link cz_dai_7219_98357[] = {
306	{
307		.name = "amd-da7219-play",
308		.stream_name = "Playback",
309		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
310				| SND_SOC_DAIFMT_CBM_CFM,
311		.init = cz_da7219_init,
312		.dpcm_playback = 1,
313		.ops = &cz_da7219_play_ops,
314		SND_SOC_DAILINK_REG(designware1, dlgs, platform),
315	},
316	{
317		.name = "amd-da7219-cap",
318		.stream_name = "Capture",
319		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
320				| SND_SOC_DAIFMT_CBM_CFM,
321		.dpcm_capture = 1,
322		.ops = &cz_da7219_cap_ops,
323		SND_SOC_DAILINK_REG(designware2, dlgs, platform),
324	},
325	{
326		.name = "amd-max98357-play",
327		.stream_name = "HiFi Playback",
328		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
329				| SND_SOC_DAIFMT_CBM_CFM,
330		.dpcm_playback = 1,
331		.ops = &cz_max_play_ops,
332		SND_SOC_DAILINK_REG(designware3, mx, platform),
333	},
334	{
335		/* C panel DMIC */
336		.name = "dmic0",
337		.stream_name = "DMIC0 Capture",
338		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
339				| SND_SOC_DAIFMT_CBM_CFM,
340		.dpcm_capture = 1,
341		.ops = &cz_dmic0_cap_ops,
342		SND_SOC_DAILINK_REG(designware3, adau, platform),
343	},
344	{
345		/* A/B panel DMIC */
346		.name = "dmic1",
347		.stream_name = "DMIC1 Capture",
348		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
349				| SND_SOC_DAIFMT_CBM_CFM,
350		.dpcm_capture = 1,
351		.ops = &cz_dmic1_cap_ops,
352		SND_SOC_DAILINK_REG(designware2, adau, platform),
353	},
354};
355
356static const struct snd_soc_dapm_widget cz_widgets[] = {
357	SND_SOC_DAPM_HP("Headphones", NULL),
358	SND_SOC_DAPM_SPK("Speakers", NULL),
359	SND_SOC_DAPM_MIC("Headset Mic", NULL),
360	SND_SOC_DAPM_MIC("Int Mic", NULL),
361};
362
363static const struct snd_soc_dapm_route cz_audio_route[] = {
364	{"Headphones", NULL, "HPL"},
365	{"Headphones", NULL, "HPR"},
366	{"MIC", NULL, "Headset Mic"},
367	{"Speakers", NULL, "Speaker"},
368	{"PDM_DAT", NULL, "Int Mic"},
369};
370
371static const struct snd_kcontrol_new cz_mc_controls[] = {
372	SOC_DAPM_PIN_SWITCH("Headphones"),
373	SOC_DAPM_PIN_SWITCH("Speakers"),
374	SOC_DAPM_PIN_SWITCH("Headset Mic"),
375	SOC_DAPM_PIN_SWITCH("Int Mic"),
376};
377
378static struct snd_soc_card cz_card = {
379	.name = "acpd7219m98357",
380	.owner = THIS_MODULE,
381	.dai_link = cz_dai_7219_98357,
382	.num_links = ARRAY_SIZE(cz_dai_7219_98357),
383	.dapm_widgets = cz_widgets,
384	.num_dapm_widgets = ARRAY_SIZE(cz_widgets),
385	.dapm_routes = cz_audio_route,
386	.num_dapm_routes = ARRAY_SIZE(cz_audio_route),
387	.controls = cz_mc_controls,
388	.num_controls = ARRAY_SIZE(cz_mc_controls),
389};
390
391static struct regulator_consumer_supply acp_da7219_supplies[] = {
392	REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"),
393	REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"),
394	REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"),
395	REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"),
396};
397
398static struct regulator_init_data acp_da7219_data = {
399	.constraints = {
400		.always_on = 1,
401	},
402	.num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies),
403	.consumer_supplies = acp_da7219_supplies,
404};
405
406static struct regulator_config acp_da7219_cfg = {
407	.init_data = &acp_da7219_data,
408};
409
410static struct regulator_ops acp_da7219_ops = {
411};
412
413static const struct regulator_desc acp_da7219_desc = {
414	.name = "reg-fixed-1.8V",
415	.type = REGULATOR_VOLTAGE,
416	.owner = THIS_MODULE,
417	.ops = &acp_da7219_ops,
418	.fixed_uV = 1800000, /* 1.8V */
419	.n_voltages = 1,
420};
421
422static int cz_probe(struct platform_device *pdev)
423{
424	int ret;
425	struct snd_soc_card *card;
426	struct acp_platform_info *machine;
427	struct regulator_dev *rdev;
428
429	acp_da7219_cfg.dev = &pdev->dev;
430	rdev = devm_regulator_register(&pdev->dev, &acp_da7219_desc,
431				       &acp_da7219_cfg);
432	if (IS_ERR(rdev)) {
433		dev_err(&pdev->dev, "Failed to register regulator: %d\n",
434			(int)PTR_ERR(rdev));
435		return -EINVAL;
436	}
437
438	machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info),
439			       GFP_KERNEL);
440	if (!machine)
441		return -ENOMEM;
442	card = &cz_card;
443	cz_card.dev = &pdev->dev;
444	platform_set_drvdata(pdev, card);
445	snd_soc_card_set_drvdata(card, machine);
446	ret = devm_snd_soc_register_card(&pdev->dev, &cz_card);
447	if (ret) {
448		dev_err(&pdev->dev,
449				"devm_snd_soc_register_card(%s) failed: %d\n",
450				cz_card.name, ret);
451		return ret;
452	}
453	bt_uart_enable = !device_property_read_bool(&pdev->dev,
454						    "bt-pad-enable");
455	return 0;
456}
457
458#ifdef CONFIG_ACPI
459static const struct acpi_device_id cz_audio_acpi_match[] = {
460	{ "AMD7219", 0 },
461	{},
462};
463MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match);
464#endif
465
466static struct platform_driver cz_pcm_driver = {
467	.driver = {
468		.name = "cz-da7219-max98357a",
469		.acpi_match_table = ACPI_PTR(cz_audio_acpi_match),
470		.pm = &snd_soc_pm_ops,
471	},
472	.probe = cz_probe,
473};
474
475module_platform_driver(cz_pcm_driver);
476
477MODULE_AUTHOR("akshu.agrawal@amd.com");
478MODULE_DESCRIPTION("DA7219 & MAX98357A audio support");
479MODULE_LICENSE("GPL v2");
480