1e149ca29SPierre-Louis Bossart // SPDX-License-Identifier: GPL-2.0-only
2798313f2SNaveen Manohar // Copyright (c) 2020 Intel Corporation
3798313f2SNaveen Manohar 
4798313f2SNaveen Manohar /*
5798313f2SNaveen Manohar  *  sof_sdw_rt5682 - Helpers to handle RT5682 from generic machine driver
6798313f2SNaveen Manohar  */
7798313f2SNaveen Manohar 
8798313f2SNaveen Manohar #include <linux/device.h>
9798313f2SNaveen Manohar #include <linux/errno.h>
10798313f2SNaveen Manohar #include <linux/input.h>
11798313f2SNaveen Manohar #include <linux/soundwire/sdw.h>
12798313f2SNaveen Manohar #include <linux/soundwire/sdw_type.h>
133f2c6564SBard Liao #include <sound/control.h>
14798313f2SNaveen Manohar #include <sound/soc.h>
15798313f2SNaveen Manohar #include <sound/soc-acpi.h>
163f2c6564SBard Liao #include <sound/soc-dapm.h>
17798313f2SNaveen Manohar #include <sound/jack.h>
18798313f2SNaveen Manohar #include "sof_sdw_common.h"
19798313f2SNaveen Manohar 
20798313f2SNaveen Manohar static const struct snd_soc_dapm_widget rt5682_widgets[] = {
21798313f2SNaveen Manohar 	SND_SOC_DAPM_HP("Headphone", NULL),
22798313f2SNaveen Manohar 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
23798313f2SNaveen Manohar };
24798313f2SNaveen Manohar 
25798313f2SNaveen Manohar static const struct snd_soc_dapm_route rt5682_map[] = {
26798313f2SNaveen Manohar 	/*Headphones*/
27798313f2SNaveen Manohar 	{ "Headphone", NULL, "rt5682 HPOL" },
28798313f2SNaveen Manohar 	{ "Headphone", NULL, "rt5682 HPOR" },
29798313f2SNaveen Manohar 	{ "rt5682 IN1P", NULL, "Headset Mic" },
30798313f2SNaveen Manohar };
31798313f2SNaveen Manohar 
32798313f2SNaveen Manohar static const struct snd_kcontrol_new rt5682_controls[] = {
33798313f2SNaveen Manohar 	SOC_DAPM_PIN_SWITCH("Headphone"),
34798313f2SNaveen Manohar 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
35798313f2SNaveen Manohar };
36798313f2SNaveen Manohar 
37798313f2SNaveen Manohar static struct snd_soc_jack_pin rt5682_jack_pins[] = {
38798313f2SNaveen Manohar 	{
39798313f2SNaveen Manohar 		.pin    = "Headphone",
40798313f2SNaveen Manohar 		.mask   = SND_JACK_HEADPHONE,
41798313f2SNaveen Manohar 	},
42798313f2SNaveen Manohar 	{
43798313f2SNaveen Manohar 		.pin    = "Headset Mic",
44798313f2SNaveen Manohar 		.mask   = SND_JACK_MICROPHONE,
45798313f2SNaveen Manohar 	},
46798313f2SNaveen Manohar };
47798313f2SNaveen Manohar 
rt5682_rtd_init(struct snd_soc_pcm_runtime * rtd)48798313f2SNaveen Manohar static int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd)
49798313f2SNaveen Manohar {
50798313f2SNaveen Manohar 	struct snd_soc_card *card = rtd->card;
51798313f2SNaveen Manohar 	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
52f11633daSPierre-Louis Bossart 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
53f11633daSPierre-Louis Bossart 	struct snd_soc_component *component = codec_dai->component;
54798313f2SNaveen Manohar 	struct snd_soc_jack *jack;
55798313f2SNaveen Manohar 	int ret;
56798313f2SNaveen Manohar 
57798313f2SNaveen Manohar 	card->components = devm_kasprintf(card->dev, GFP_KERNEL,
58798313f2SNaveen Manohar 					  "%s hs:rt5682",
59798313f2SNaveen Manohar 					  card->components);
60798313f2SNaveen Manohar 	if (!card->components)
61798313f2SNaveen Manohar 		return -ENOMEM;
62798313f2SNaveen Manohar 
63798313f2SNaveen Manohar 	ret = snd_soc_add_card_controls(card, rt5682_controls,
64798313f2SNaveen Manohar 					ARRAY_SIZE(rt5682_controls));
65798313f2SNaveen Manohar 	if (ret) {
66798313f2SNaveen Manohar 		dev_err(card->dev, "rt5682 control addition failed: %d\n", ret);
67798313f2SNaveen Manohar 		return ret;
68798313f2SNaveen Manohar 	}
69798313f2SNaveen Manohar 
70798313f2SNaveen Manohar 	ret = snd_soc_dapm_new_controls(&card->dapm, rt5682_widgets,
71798313f2SNaveen Manohar 					ARRAY_SIZE(rt5682_widgets));
72798313f2SNaveen Manohar 	if (ret) {
73798313f2SNaveen Manohar 		dev_err(card->dev, "rt5682 widgets addition failed: %d\n", ret);
74798313f2SNaveen Manohar 		return ret;
75798313f2SNaveen Manohar 	}
76798313f2SNaveen Manohar 
77798313f2SNaveen Manohar 	ret = snd_soc_dapm_add_routes(&card->dapm, rt5682_map,
78798313f2SNaveen Manohar 				      ARRAY_SIZE(rt5682_map));
79798313f2SNaveen Manohar 
80798313f2SNaveen Manohar 	if (ret) {
81798313f2SNaveen Manohar 		dev_err(card->dev, "rt5682 map addition failed: %d\n", ret);
82798313f2SNaveen Manohar 		return ret;
83798313f2SNaveen Manohar 	}
84798313f2SNaveen Manohar 
85*19aed2d6SAkihiko Odaki 	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
86798313f2SNaveen Manohar 					 SND_JACK_HEADSET | SND_JACK_BTN_0 |
87798313f2SNaveen Manohar 					 SND_JACK_BTN_1 | SND_JACK_BTN_2 |
88798313f2SNaveen Manohar 					 SND_JACK_BTN_3,
89798313f2SNaveen Manohar 					 &ctx->sdw_headset,
90798313f2SNaveen Manohar 					 rt5682_jack_pins,
91798313f2SNaveen Manohar 					 ARRAY_SIZE(rt5682_jack_pins));
92798313f2SNaveen Manohar 	if (ret) {
93798313f2SNaveen Manohar 		dev_err(rtd->card->dev, "Headset Jack creation failed: %d\n",
94798313f2SNaveen Manohar 			ret);
95798313f2SNaveen Manohar 		return ret;
96798313f2SNaveen Manohar 	}
97798313f2SNaveen Manohar 
98798313f2SNaveen Manohar 	jack = &ctx->sdw_headset;
99798313f2SNaveen Manohar 
100798313f2SNaveen Manohar 	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
101798313f2SNaveen Manohar 	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
102798313f2SNaveen Manohar 	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
103798313f2SNaveen Manohar 	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
104798313f2SNaveen Manohar 
105798313f2SNaveen Manohar 	ret = snd_soc_component_set_jack(component, jack, NULL);
106798313f2SNaveen Manohar 
107798313f2SNaveen Manohar 	if (ret)
108798313f2SNaveen Manohar 		dev_err(rtd->card->dev, "Headset Jack call-back failed: %d\n",
109798313f2SNaveen Manohar 			ret);
110798313f2SNaveen Manohar 
111798313f2SNaveen Manohar 	return ret;
112798313f2SNaveen Manohar }
113798313f2SNaveen Manohar 
sof_sdw_rt5682_init(struct snd_soc_card * card,const struct snd_soc_acpi_link_adr * link,struct snd_soc_dai_link * dai_links,struct sof_sdw_codec_info * info,bool playback)114cdf99c9aSPierre-Louis Bossart int sof_sdw_rt5682_init(struct snd_soc_card *card,
115cdf99c9aSPierre-Louis Bossart 			const struct snd_soc_acpi_link_adr *link,
116798313f2SNaveen Manohar 			struct snd_soc_dai_link *dai_links,
117798313f2SNaveen Manohar 			struct sof_sdw_codec_info *info,
118798313f2SNaveen Manohar 			bool playback)
119798313f2SNaveen Manohar {
120798313f2SNaveen Manohar 	/*
121798313f2SNaveen Manohar 	 * headset should be initialized once.
122798313f2SNaveen Manohar 	 * Do it with dai link for playback.
123798313f2SNaveen Manohar 	 */
124798313f2SNaveen Manohar 	if (!playback)
125798313f2SNaveen Manohar 		return 0;
126798313f2SNaveen Manohar 
127798313f2SNaveen Manohar 	dai_links->init = rt5682_rtd_init;
128798313f2SNaveen Manohar 
129798313f2SNaveen Manohar 	return 0;
130798313f2SNaveen Manohar }
131