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
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.
.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[] = {
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)
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,
{ "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)
{
#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,
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
.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 = {
.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 = {
.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[] = {
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)
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,