1 // SPDX-License-Identifier: GPL-2.0-only
2 // This file incorporates work covered by the following copyright notice:
3 // Copyright (c) 2020 Intel Corporation
4 // Copyright (c) 2024 Advanced Micro Devices, Inc.
7 * soc_sdw_rt711 - Helpers to handle RT711 from generic machine driver
10 #include <linux/device.h>
11 #include <linux/errno.h>
12 #include <linux/input.h>
13 #include <linux/soundwire/sdw.h>
14 #include <linux/soundwire/sdw_type.h>
15 #include <sound/control.h>
16 #include <sound/soc.h>
17 #include <sound/soc-acpi.h>
18 #include <sound/soc-dapm.h>
19 #include <sound/jack.h>
20 #include <sound/soc_sdw_utils.h>
23 * Note this MUST be called before snd_soc_register_card(), so that the props
24 * are in place before the codec component driver's probe function parses them.
26 static int rt711_add_codec_device_props(struct device
*sdw_dev
, unsigned long quirk
)
28 struct property_entry props
[SOC_SDW_MAX_NO_PROPS
] = {};
29 struct fwnode_handle
*fwnode
;
32 if (!SOC_SDW_JACK_JDSRC(quirk
))
34 props
[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOC_SDW_JACK_JDSRC(quirk
));
36 fwnode
= fwnode_create_software_node(props
, NULL
);
38 return PTR_ERR(fwnode
);
40 ret
= device_add_software_node(sdw_dev
, to_software_node(fwnode
));
42 fwnode_handle_put(fwnode
);
47 static const struct snd_soc_dapm_route rt711_map
[] = {
49 { "Headphone", NULL
, "rt711 HP" },
50 { "rt711 MIC2", NULL
, "Headset Mic" },
53 static struct snd_soc_jack_pin rt711_jack_pins
[] = {
56 .mask
= SND_JACK_HEADPHONE
,
60 .mask
= SND_JACK_MICROPHONE
,
64 int asoc_sdw_rt711_rtd_init(struct snd_soc_pcm_runtime
*rtd
, struct snd_soc_dai
*dai
)
66 struct snd_soc_card
*card
= rtd
->card
;
67 struct asoc_sdw_mc_private
*ctx
= snd_soc_card_get_drvdata(card
);
68 struct snd_soc_component
*component
;
69 struct snd_soc_jack
*jack
;
72 component
= dai
->component
;
73 card
->components
= devm_kasprintf(card
->dev
, GFP_KERNEL
,
76 if (!card
->components
)
79 ret
= snd_soc_dapm_add_routes(&card
->dapm
, rt711_map
,
80 ARRAY_SIZE(rt711_map
));
83 dev_err(card
->dev
, "rt711 map addition failed: %d\n", ret
);
87 ret
= snd_soc_card_jack_new_pins(rtd
->card
, "Headset Jack",
88 SND_JACK_HEADSET
| SND_JACK_BTN_0
|
89 SND_JACK_BTN_1
| SND_JACK_BTN_2
|
93 ARRAY_SIZE(rt711_jack_pins
));
95 dev_err(rtd
->card
->dev
, "Headset Jack creation failed: %d\n",
100 jack
= &ctx
->sdw_headset
;
102 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_0
, KEY_PLAYPAUSE
);
103 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_1
, KEY_VOICECOMMAND
);
104 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_2
, KEY_VOLUMEUP
);
105 snd_jack_set_key(jack
->jack
, SND_JACK_BTN_3
, KEY_VOLUMEDOWN
);
107 ret
= snd_soc_component_set_jack(component
, jack
, NULL
);
110 dev_err(rtd
->card
->dev
, "Headset Jack call-back failed: %d\n",
115 EXPORT_SYMBOL_NS(asoc_sdw_rt711_rtd_init
, "SND_SOC_SDW_UTILS");
117 int asoc_sdw_rt711_exit(struct snd_soc_card
*card
, struct snd_soc_dai_link
*dai_link
)
119 struct asoc_sdw_mc_private
*ctx
= snd_soc_card_get_drvdata(card
);
121 if (!ctx
->headset_codec_dev
)
124 device_remove_software_node(ctx
->headset_codec_dev
);
125 put_device(ctx
->headset_codec_dev
);
129 EXPORT_SYMBOL_NS(asoc_sdw_rt711_exit
, "SND_SOC_SDW_UTILS");
131 int asoc_sdw_rt711_init(struct snd_soc_card
*card
,
132 struct snd_soc_dai_link
*dai_links
,
133 struct asoc_sdw_codec_info
*info
,
136 struct asoc_sdw_mc_private
*ctx
= snd_soc_card_get_drvdata(card
);
137 struct device
*sdw_dev
;
141 * headset should be initialized once.
142 * Do it with dai link for playback.
147 sdw_dev
= bus_find_device_by_name(&sdw_bus_type
, NULL
, dai_links
->codecs
[0].name
);
149 return -EPROBE_DEFER
;
151 ret
= rt711_add_codec_device_props(sdw_dev
, ctx
->mc_quirk
);
156 ctx
->headset_codec_dev
= sdw_dev
;
160 EXPORT_SYMBOL_NS(asoc_sdw_rt711_init
, "SND_SOC_SDW_UTILS");