1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2020 Intel Corporation
5 * sof_sdw_rt711_sdca - Helpers to handle RT711-SDCA from generic machine driver
8 #include <linux/device.h>
9 #include <linux/errno.h>
10 #include <linux/input.h>
11 #include <linux/soundwire/sdw.h>
12 #include <linux/soundwire/sdw_type.h>
13 #include <sound/control.h>
14 #include <sound/soc.h>
15 #include <sound/soc-acpi.h>
16 #include <sound/soc-dapm.h>
17 #include <sound/jack.h>
18 #include "sof_sdw_common.h"
21 * Note this MUST be called before snd_soc_register_card(), so that the props
22 * are in place before the codec component driver's probe function parses them.
24 static int rt711_sdca_add_codec_device_props(const char *sdw_dev_name
)
26 struct property_entry props
[MAX_NO_PROPS
] = {};
27 struct device
*sdw_dev
;
30 sdw_dev
= bus_find_device_by_name(&sdw_bus_type
, NULL
, sdw_dev_name
);
34 if (SOF_RT711_JDSRC(sof_sdw_quirk
)) {
35 props
[0] = PROPERTY_ENTRY_U32("realtek,jd-src",
36 SOF_RT711_JDSRC(sof_sdw_quirk
));
39 ret
= device_add_properties(sdw_dev
, props
);
45 static const struct snd_soc_dapm_widget rt711_sdca_widgets
[] = {
46 SND_SOC_DAPM_HP("Headphone", NULL
),
47 SND_SOC_DAPM_MIC("Headset Mic", NULL
),
50 static const struct snd_soc_dapm_route rt711_sdca_map
[] = {
52 { "Headphone", NULL
, "rt711 HP" },
53 { "rt711 MIC2", NULL
, "Headset Mic" },
56 static const struct snd_kcontrol_new rt711_sdca_controls
[] = {
57 SOC_DAPM_PIN_SWITCH("Headphone"),
58 SOC_DAPM_PIN_SWITCH("Headset Mic"),
61 static struct snd_soc_jack_pin rt711_sdca_jack_pins
[] = {
64 .mask
= SND_JACK_HEADPHONE
,
68 .mask
= SND_JACK_MICROPHONE
,
72 static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime
*rtd
)
74 struct snd_soc_card
*card
= rtd
->card
;
75 struct mc_private
*ctx
= snd_soc_card_get_drvdata(card
);
76 struct snd_soc_dai
*codec_dai
= asoc_rtd_to_codec(rtd
, 0);
77 struct snd_soc_component
*component
= codec_dai
->component
;
78 struct snd_soc_jack
*jack
;
81 card
->components
= devm_kasprintf(card
->dev
, GFP_KERNEL
,
84 if (!card
->components
)
87 ret
= snd_soc_add_card_controls(card
, rt711_sdca_controls
,
88 ARRAY_SIZE(rt711_sdca_controls
));
90 dev_err(card
->dev
, "rt711-sdca controls addition failed: %d\n", ret
);
94 ret
= snd_soc_dapm_new_controls(&card
->dapm
, rt711_sdca_widgets
,
95 ARRAY_SIZE(rt711_sdca_widgets
));
97 dev_err(card
->dev
, "rt711-sdca widgets addition failed: %d\n", ret
);
101 ret
= snd_soc_dapm_add_routes(&card
->dapm
, rt711_sdca_map
,
102 ARRAY_SIZE(rt711_sdca_map
));
105 dev_err(card
->dev
, "rt711-sdca map addition failed: %d\n", ret
);
109 ret
= snd_soc_card_jack_new(rtd
->card
, "Headset Jack",
110 SND_JACK_HEADSET
| SND_JACK_BTN_0
|
111 SND_JACK_BTN_1
| SND_JACK_BTN_2
|
114 rt711_sdca_jack_pins
,
115 ARRAY_SIZE(rt711_sdca_jack_pins
));
117 dev_err(rtd
->card
->dev
, "Headset Jack creation failed: %d\n",
122 jack
= &ctx
->sdw_headset
;
124 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_0
, KEY_PLAYPAUSE
);
125 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_1
, KEY_VOICECOMMAND
);
126 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_2
, KEY_VOLUMEUP
);
127 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_3
, KEY_VOLUMEDOWN
);
129 ret
= snd_soc_component_set_jack(component
, jack
, NULL
);
132 dev_err(rtd
->card
->dev
, "Headset Jack call-back failed: %d\n",
138 int sof_sdw_rt711_sdca_exit(struct device
*dev
, struct snd_soc_dai_link
*dai_link
)
140 struct device
*sdw_dev
;
142 sdw_dev
= bus_find_device_by_name(&sdw_bus_type
, NULL
,
143 dai_link
->codecs
[0].name
);
147 device_remove_properties(sdw_dev
);
153 int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr
*link
,
154 struct snd_soc_dai_link
*dai_links
,
155 struct sof_sdw_codec_info
*info
,
161 * headset should be initialized once.
162 * Do it with dai link for playback.
167 ret
= rt711_sdca_add_codec_device_props(dai_links
->codecs
[0].name
);
171 dai_links
->init
= rt711_sdca_rtd_init
;