OSDN Git Service

ASoC: amd: acp: Power on/off the speaker enable gpio pin based on DAPM callback.
authorV sujith kumar Reddy <vsujithkumar.reddy@amd.com>
Fri, 24 Dec 2021 15:00:43 +0000 (20:30 +0530)
committerMark Brown <broonie@kernel.org>
Fri, 24 Dec 2021 14:06:59 +0000 (14:06 +0000)
Configure the speaker gpio pin based on power sequence of the DAPM
speaker events.
Enable speaker after widget power up and Disable before widget  powerdown.

Signed-off-by: V sujith kumar Reddy <vsujithkumar.reddy@amd.com>
Link: https://lore.kernel.org/r/20211224150058.2444776-1-vsujithkumar.reddy@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/amd/acp/Kconfig
sound/soc/amd/acp/acp-legacy-mach.c
sound/soc/amd/acp/acp-mach-common.c
sound/soc/amd/acp/acp-mach.h
sound/soc/amd/acp/acp-sof-mach.c

index 154be5e..d5838df 100644 (file)
@@ -32,7 +32,7 @@ config SND_AMD_ASOC_RENOIR
 
 config SND_SOC_AMD_MACH_COMMON
        tristate
-       depends on X86 && PCI && I2C
+       depends on X86 && PCI && I2C && GPIOLIB
        select CLK_FIXED_FCH
        select SND_SOC_RT5682_I2C
        select SND_SOC_DMIC
@@ -44,14 +44,14 @@ config SND_SOC_AMD_MACH_COMMON
 
 config SND_SOC_AMD_LEGACY_MACH
        tristate "AMD Legacy Machine Driver Support"
-       depends on X86 && PCI && I2C
+       depends on X86 && PCI && I2C && GPIOLIB
        select SND_SOC_AMD_MACH_COMMON
        help
          This option enables legacy sound card support for ACP audio.
 
 config SND_SOC_AMD_SOF_MACH
        tristate "AMD SOF Machine Driver Support"
-       depends on X86 && PCI && I2C
+       depends on X86 && PCI && I2C && GPIOLIB
        select SND_SOC_AMD_MACH_COMMON
        help
          This option enables SOF sound card support for ACP audio.
index de0f802..0ad1cf4 100644 (file)
@@ -27,6 +27,7 @@ static struct acp_card_drvdata rt5682_rt1019_data = {
        .hs_codec_id = RT5682,
        .amp_codec_id = RT1019,
        .dmic_codec_id = NONE,
+       .gpio_spkr_en = EN_SPKR_GPIO_GB,
 };
 
 static const struct snd_kcontrol_new acp_controls[] = {
@@ -41,15 +42,16 @@ static const struct snd_kcontrol_new acp_controls[] = {
 static const struct snd_soc_dapm_widget acp_widgets[] = {
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
-       SND_SOC_DAPM_SPK("Spk", NULL),
-       SND_SOC_DAPM_SPK("Left Spk", NULL),
-       SND_SOC_DAPM_SPK("Right Spk", NULL),
+       SND_SOC_DAPM_SPK("Spk", event_spkr_handler),
+       SND_SOC_DAPM_SPK("Left Spk", event_spkr_handler),
+       SND_SOC_DAPM_SPK("Right Spk", event_spkr_handler),
 };
 
 static int acp_asoc_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = NULL;
        struct device *dev = &pdev->dev;
+       unsigned int spkr_gpio;
        int ret;
 
        if (!pdev->id_entry)
@@ -67,9 +69,20 @@ static int acp_asoc_probe(struct platform_device *pdev)
        card->controls = acp_controls;
        card->num_controls = ARRAY_SIZE(acp_controls);
        card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
+       spkr_gpio = ((struct acp_card_drvdata *)(card->drvdata))->gpio_spkr_en;
 
        acp_legacy_dai_links_create(card);
 
+       if (gpio_is_valid(spkr_gpio)) {
+               ret = devm_gpio_request(dev, spkr_gpio, "spkren");
+               if (ret) {
+                       dev_err(dev, "(%s) gpio request failed: %d\n",
+                               __func__, ret);
+                       return ret;
+               }
+               gpio_direction_output(spkr_gpio, 0);
+       }
+
        ret = devm_snd_soc_register_card(&pdev->dev, card);
        if (ret) {
                dev_err(&pdev->dev,
index 7785f12..03d8d1a 100644 (file)
@@ -71,6 +71,31 @@ static const struct snd_soc_dapm_route rt5682_map[] = {
        { "IN1P", NULL, "Headset Mic" },
 };
 
+int event_spkr_handler(struct snd_soc_dapm_widget *w,
+                       struct snd_kcontrol *k, int event)
+{
+       struct snd_soc_dapm_context *dapm = w->dapm;
+       struct snd_soc_card *card = dapm->card;
+       struct acp_card_drvdata *drvdata = snd_soc_card_get_drvdata(card);
+
+       if (!gpio_is_valid(drvdata->gpio_spkr_en))
+               return 0;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               gpio_set_value(drvdata->gpio_spkr_en, 1);
+               break;
+       case SND_SOC_DAPM_PRE_PMD:
+               gpio_set_value(drvdata->gpio_spkr_en, 0);
+               break;
+       default:
+               dev_warn(card->dev, "%s invalid setting\n", __func__);
+               break;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_NS_GPL(event_spkr_handler, SND_SOC_AMD_MACH);
+
 /* Define card ops for RT5682 CODEC */
 static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
 {
index 5dc47cf..fd62998 100644 (file)
 #include <linux/input.h>
 #include <linux/module.h>
 #include <sound/soc.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+
+#define EN_SPKR_GPIO_GB                0x11F
+#define EN_SPKR_GPIO_NK                0x146
+#define EN_SPKR_GPIO_NONE      -EINVAL
 
 enum be_id {
        HEADSET_BE_ID = 0,
@@ -49,9 +55,11 @@ struct acp_card_drvdata {
        unsigned int dai_fmt;
        struct clk *wclk;
        struct clk *bclk;
+       unsigned int gpio_spkr_en;
 };
 
 int acp_sofdsp_dai_links_create(struct snd_soc_card *card);
 int acp_legacy_dai_links_create(struct snd_soc_card *card);
-
+int event_spkr_handler(struct snd_soc_dapm_widget *w,
+                       struct snd_kcontrol *k, int event);
 #endif
index 854eb72..07de461 100644 (file)
@@ -27,6 +27,7 @@ static struct acp_card_drvdata sof_rt5682_rt1019_data = {
        .hs_codec_id = RT5682,
        .amp_codec_id = RT1019,
        .dmic_codec_id = DMIC,
+       .gpio_spkr_en = EN_SPKR_GPIO_GB,
 };
 
 static struct acp_card_drvdata sof_rt5682_max_data = {
@@ -36,6 +37,7 @@ static struct acp_card_drvdata sof_rt5682_max_data = {
        .hs_codec_id = RT5682,
        .amp_codec_id = MAX98360A,
        .dmic_codec_id = DMIC,
+       .gpio_spkr_en = EN_SPKR_GPIO_NK,
 };
 
 static struct acp_card_drvdata sof_rt5682s_max_data = {
@@ -45,6 +47,7 @@ static struct acp_card_drvdata sof_rt5682s_max_data = {
        .hs_codec_id = RT5682S,
        .amp_codec_id = MAX98360A,
        .dmic_codec_id = DMIC,
+       .gpio_spkr_en = EN_SPKR_GPIO_NK,
 };
 
 static const struct snd_kcontrol_new acp_controls[] = {
@@ -58,15 +61,16 @@ static const struct snd_kcontrol_new acp_controls[] = {
 static const struct snd_soc_dapm_widget acp_widgets[] = {
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
-       SND_SOC_DAPM_SPK("Spk", NULL),
-       SND_SOC_DAPM_SPK("Left Spk", NULL),
-       SND_SOC_DAPM_SPK("Right Spk", NULL),
+       SND_SOC_DAPM_SPK("Spk", event_spkr_handler),
+       SND_SOC_DAPM_SPK("Left Spk", event_spkr_handler),
+       SND_SOC_DAPM_SPK("Right Spk", event_spkr_handler),
 };
 
 static int acp_sof_probe(struct platform_device *pdev)
 {
        struct snd_soc_card *card = NULL;
        struct device *dev = &pdev->dev;
+       unsigned int spkr_gpio;
        int ret;
 
        if (!pdev->id_entry)
@@ -84,9 +88,20 @@ static int acp_sof_probe(struct platform_device *pdev)
        card->controls = acp_controls;
        card->num_controls = ARRAY_SIZE(acp_controls);
        card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
+       spkr_gpio = ((struct acp_card_drvdata *)(card->drvdata))->gpio_spkr_en;
 
        acp_sofdsp_dai_links_create(card);
 
+       if (gpio_is_valid(spkr_gpio)) {
+               ret = devm_gpio_request(dev, spkr_gpio, "spkren");
+               if (ret) {
+                       dev_err(dev, "(%s) gpio request failed: %d\n",
+                               __func__, ret);
+                       return ret;
+               }
+               gpio_direction_output(spkr_gpio, 0);
+       }
+
        ret = devm_snd_soc_register_card(&pdev->dev, card);
        if (ret) {
                dev_err(&pdev->dev,