Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 // Copyright (c) 2020 Intel Corporation
0003 
0004 /*
0005  *  sof_sdw_rt711 - Helpers to handle RT711 from generic machine driver
0006  */
0007 
0008 #include <linux/device.h>
0009 #include <linux/errno.h>
0010 #include <linux/input.h>
0011 #include <linux/soundwire/sdw.h>
0012 #include <linux/soundwire/sdw_type.h>
0013 #include <sound/control.h>
0014 #include <sound/soc.h>
0015 #include <sound/soc-acpi.h>
0016 #include <sound/soc-dapm.h>
0017 #include <sound/jack.h>
0018 #include "sof_sdw_common.h"
0019 
0020 /*
0021  * Note this MUST be called before snd_soc_register_card(), so that the props
0022  * are in place before the codec component driver's probe function parses them.
0023  */
0024 static int rt711_add_codec_device_props(struct device *sdw_dev)
0025 {
0026     struct property_entry props[MAX_NO_PROPS] = {};
0027     struct fwnode_handle *fwnode;
0028     int ret;
0029 
0030     if (!SOF_RT711_JDSRC(sof_sdw_quirk))
0031         return 0;
0032     props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk));
0033 
0034     fwnode = fwnode_create_software_node(props, NULL);
0035     if (IS_ERR(fwnode))
0036         return PTR_ERR(fwnode);
0037 
0038     ret = device_add_software_node(sdw_dev, to_software_node(fwnode));
0039 
0040     fwnode_handle_put(fwnode);
0041 
0042     return ret;
0043 }
0044 
0045 static const struct snd_soc_dapm_widget rt711_widgets[] = {
0046     SND_SOC_DAPM_HP("Headphone", NULL),
0047     SND_SOC_DAPM_MIC("Headset Mic", NULL),
0048 };
0049 
0050 static const struct snd_soc_dapm_route rt711_map[] = {
0051     /* Headphones */
0052     { "Headphone", NULL, "rt711 HP" },
0053     { "rt711 MIC2", NULL, "Headset Mic" },
0054 };
0055 
0056 static const struct snd_kcontrol_new rt711_controls[] = {
0057     SOC_DAPM_PIN_SWITCH("Headphone"),
0058     SOC_DAPM_PIN_SWITCH("Headset Mic"),
0059 };
0060 
0061 static struct snd_soc_jack_pin rt711_jack_pins[] = {
0062     {
0063         .pin    = "Headphone",
0064         .mask   = SND_JACK_HEADPHONE,
0065     },
0066     {
0067         .pin    = "Headset Mic",
0068         .mask   = SND_JACK_MICROPHONE,
0069     },
0070 };
0071 
0072 static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd)
0073 {
0074     struct snd_soc_card *card = rtd->card;
0075     struct mc_private *ctx = snd_soc_card_get_drvdata(card);
0076     struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0077     struct snd_soc_component *component = codec_dai->component;
0078     struct snd_soc_jack *jack;
0079     int ret;
0080 
0081     card->components = devm_kasprintf(card->dev, GFP_KERNEL,
0082                       "%s hs:rt711",
0083                       card->components);
0084     if (!card->components)
0085         return -ENOMEM;
0086 
0087     ret = snd_soc_add_card_controls(card, rt711_controls,
0088                     ARRAY_SIZE(rt711_controls));
0089     if (ret) {
0090         dev_err(card->dev, "rt711 controls addition failed: %d\n", ret);
0091         return ret;
0092     }
0093 
0094     ret = snd_soc_dapm_new_controls(&card->dapm, rt711_widgets,
0095                     ARRAY_SIZE(rt711_widgets));
0096     if (ret) {
0097         dev_err(card->dev, "rt711 widgets addition failed: %d\n", ret);
0098         return ret;
0099     }
0100 
0101     ret = snd_soc_dapm_add_routes(&card->dapm, rt711_map,
0102                       ARRAY_SIZE(rt711_map));
0103 
0104     if (ret) {
0105         dev_err(card->dev, "rt711 map addition failed: %d\n", ret);
0106         return ret;
0107     }
0108 
0109     ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
0110                      SND_JACK_HEADSET | SND_JACK_BTN_0 |
0111                      SND_JACK_BTN_1 | SND_JACK_BTN_2 |
0112                      SND_JACK_BTN_3,
0113                      &ctx->sdw_headset,
0114                      rt711_jack_pins,
0115                      ARRAY_SIZE(rt711_jack_pins));
0116     if (ret) {
0117         dev_err(rtd->card->dev, "Headset Jack creation failed: %d\n",
0118             ret);
0119         return ret;
0120     }
0121 
0122     jack = &ctx->sdw_headset;
0123 
0124     snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
0125     snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
0126     snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
0127     snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
0128 
0129     ret = snd_soc_component_set_jack(component, jack, NULL);
0130 
0131     if (ret)
0132         dev_err(rtd->card->dev, "Headset Jack call-back failed: %d\n",
0133             ret);
0134 
0135     return ret;
0136 }
0137 
0138 int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
0139 {
0140     struct mc_private *ctx = snd_soc_card_get_drvdata(card);
0141 
0142     if (!ctx->headset_codec_dev)
0143         return 0;
0144 
0145     device_remove_software_node(ctx->headset_codec_dev);
0146     put_device(ctx->headset_codec_dev);
0147 
0148     return 0;
0149 }
0150 
0151 int sof_sdw_rt711_init(struct snd_soc_card *card,
0152                const struct snd_soc_acpi_link_adr *link,
0153                struct snd_soc_dai_link *dai_links,
0154                struct sof_sdw_codec_info *info,
0155                bool playback)
0156 {
0157     struct mc_private *ctx = snd_soc_card_get_drvdata(card);
0158     struct device *sdw_dev;
0159     int ret;
0160 
0161     /*
0162      * headset should be initialized once.
0163      * Do it with dai link for playback.
0164      */
0165     if (!playback)
0166         return 0;
0167 
0168     sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name);
0169     if (!sdw_dev)
0170         return -EPROBE_DEFER;
0171 
0172     ret = rt711_add_codec_device_props(sdw_dev);
0173     if (ret < 0) {
0174         put_device(sdw_dev);
0175         return ret;
0176     }
0177     ctx->headset_codec_dev = sdw_dev;
0178 
0179     dai_links->init = rt711_rtd_init;
0180 
0181     return 0;
0182 }