Commit 8ea08258 authored by Mark Brown's avatar Mark Brown

ASoC: Intel: bytcht_es8316: Determine

Merge series from Hans de Goede <hdegoede@redhat.com>:

This takes some of the work done to auto-configure quirks/routing
for ESS83xx codecs by getting the info from ACPI from:
https://github.com/thesofproject/linux/pull/4112

And then builds on top of this to add auto-configuration to
the bytcht_es8316 board driver.

Note compared to the pull-request, which deals with the ES8336, this
series deals with the ES8316 (for which I have several devices to test
on) and this moves handling of the _DSM from the codec driver to
the board driver since with the ES8316 the board driver takes
care of setting up various routes for things like the mic and
speakers.

After this series audio now works properly on a CHT Chuwi Hi12
tablet without needing to add an extra quirk for that model.

This has also been tested on the following devices, where things
are unchanged from before (the ACPI autoconfiguration gives the
same results as the old defaults) :

Onda V80 plus (CHT)
GP-electronic T701 (BYT)

I also tested this on a Nanote UMPC-01, here the _DSM result
for PLATFORM_SPK_TYPE_ARG wrongly returns 1 (mono) while
the device actually has 2 speakers, so this model needs to keep
its DMI quirk.

I don't have an IRBIS NB41 nor a TECLAST X98 Plus II,
so the DMI quirks for those are left in place too on
a better safe then sorry basis.
parents d0ae9dc4 7650862f
......@@ -1076,6 +1076,10 @@ config SND_SOC_ES7134
config SND_SOC_ES7241
tristate "Everest Semi ES7241 CODEC"
config SND_SOC_ES83XX_DSM_COMMON
depends on ACPI
tristate
config SND_SOC_ES8316
tristate "Everest Semi ES8316 CODEC"
depends on I2C
......
......@@ -116,6 +116,7 @@ snd-soc-da9055-objs := da9055.o
snd-soc-dmic-objs := dmic.o
snd-soc-es7134-objs := es7134.o
snd-soc-es7241-objs := es7241.o
snd-soc-es83xx-dsm-common-objs := es83xx-dsm-common.o
snd-soc-es8316-objs := es8316.o
snd-soc-es8326-objs := es8326.o
snd-soc-es8328-objs := es8328.o
......@@ -505,6 +506,7 @@ obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_ES7134) += snd-soc-es7134.o
obj-$(CONFIG_SND_SOC_ES7241) += snd-soc-es7241.o
obj-$(CONFIG_SND_SOC_ES83XX_DSM_COMMON) += snd-soc-es83xx-dsm-common.o
obj-$(CONFIG_SND_SOC_ES8316) += snd-soc-es8316.o
obj-$(CONFIG_SND_SOC_ES8326) += snd-soc-es8326.o
obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
......
// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright (c) Intel Corporation, 2022
// Copyright Everest Semiconductor Co.,Ltd
#include <linux/module.h>
#include <linux/acpi.h>
#include "es83xx-dsm-common.h"
/* UUID ("a9800c04-e016-343e-41f4-6bcce70f4332") */
static const guid_t es83xx_dsm_guid =
GUID_INIT(0xa9800c04, 0xe016, 0x343e,
0x41, 0xf4, 0x6b, 0xcc, 0xe7, 0x0f, 0x43, 0x32);
#define ES83xx_DSM_REVID 1
int es83xx_dsm(struct device *dev, int arg, int *value)
{
acpi_handle dhandle;
union acpi_object *obj;
int ret = 0;
dhandle = ACPI_HANDLE(dev);
if (!dhandle)
return -ENOENT;
obj = acpi_evaluate_dsm(dhandle, &es83xx_dsm_guid, ES83xx_DSM_REVID,
arg, NULL);
if (!obj) {
dev_err(dev, "%s: acpi_evaluate_dsm() failed\n", __func__);
ret = -EINVAL;
goto out;
}
if (obj->type != ACPI_TYPE_INTEGER) {
dev_err(dev, "%s: object is not ACPI_TYPE_INTEGER\n", __func__);
ret = -EINVAL;
goto err;
}
*value = obj->integer.value;
err:
ACPI_FREE(obj);
out:
return ret;
}
EXPORT_SYMBOL_GPL(es83xx_dsm);
int es83xx_dsm_dump(struct device *dev)
{
int value;
int ret;
ret = es83xx_dsm(dev, PLATFORM_MAINMIC_TYPE_ARG, &value);
if (ret < 0)
return ret;
dev_info(dev, "PLATFORM_MAINMIC_TYPE %#x\n", value);
ret = es83xx_dsm(dev, PLATFORM_HPMIC_TYPE_ARG, &value);
if (ret < 0)
return ret;
dev_info(dev, "PLATFORM_HPMIC_TYPE %#x\n", value);
ret = es83xx_dsm(dev, PLATFORM_SPK_TYPE_ARG, &value);
if (ret < 0)
return ret;
dev_info(dev, "PLATFORM_SPK_TYPE %#x\n", value);
ret = es83xx_dsm(dev, PLATFORM_HPDET_INV_ARG, &value);
if (ret < 0)
return ret;
dev_info(dev, "PLATFORM_HPDET_INV %#x\n", value);
ret = es83xx_dsm(dev, PLATFORM_PCM_TYPE_ARG, &value);
if (ret < 0)
return ret;
dev_info(dev, "PLATFORM_PCM_TYPE %#x\n", value);
ret = es83xx_dsm(dev, PLATFORM_MIC_DE_POP_ARG, &value);
if (ret < 0)
return ret;
dev_info(dev, "PLATFORM_MIC_DE_POP %#x\n", value);
return 0;
}
EXPORT_SYMBOL_GPL(es83xx_dsm_dump);
MODULE_DESCRIPTION("Everest Semi ES83xx DSM helpers");
MODULE_LICENSE("GPL");
This diff is collapsed.
......@@ -229,6 +229,7 @@ config SND_SOC_INTEL_BYT_CHT_ES8316_MACH
depends on GPIOLIB || COMPILE_TEST
select SND_SOC_ACPI
select SND_SOC_ES8316
select SND_SOC_ES83XX_DSM_COMMON
help
This adds support for ASoC machine driver for Intel(R) Baytrail &
Cherrytrail platforms with ES8316 audio codec.
......
......@@ -27,6 +27,7 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include "../../codecs/es83xx-dsm-common.h"
#include "../atom/sst-atom-controls.h"
#include "../common/soc-intel-quirks.h"
......@@ -461,6 +462,66 @@ static const struct dmi_system_id byt_cht_es8316_quirk_table[] = {
{}
};
static int byt_cht_es8316_get_quirks_from_dsm(struct byt_cht_es8316_private *priv,
bool is_bytcr)
{
int ret, val1, val2, dsm_quirk = 0;
if (is_bytcr)
dsm_quirk |= BYT_CHT_ES8316_SSP0;
ret = es83xx_dsm(priv->codec_dev, PLATFORM_MAINMIC_TYPE_ARG, &val1);
if (ret < 0)
return ret;
ret = es83xx_dsm(priv->codec_dev, PLATFORM_HPMIC_TYPE_ARG, &val2);
if (ret < 0)
return ret;
if (val1 == PLATFORM_MIC_AMIC_LIN1RIN1 && val2 == PLATFORM_MIC_AMIC_LIN2RIN2) {
dsm_quirk |= BYT_CHT_ES8316_INTMIC_IN1_MAP;
} else if (val1 == PLATFORM_MIC_AMIC_LIN2RIN2 && val2 == PLATFORM_MIC_AMIC_LIN1RIN1) {
dsm_quirk |= BYT_CHT_ES8316_INTMIC_IN2_MAP;
} else {
dev_warn(priv->codec_dev, "Unknown mic settings mainmic 0x%02x hpmic 0x%02x\n",
val1, val2);
return -EINVAL;
}
ret = es83xx_dsm(priv->codec_dev, PLATFORM_SPK_TYPE_ARG, &val1);
if (ret < 0)
return ret;
switch (val1) {
case PLATFORM_SPK_MONO:
dsm_quirk |= BYT_CHT_ES8316_MONO_SPEAKER;
break;
case PLATFORM_SPK_STEREO:
break;
default:
dev_warn(priv->codec_dev, "Unknown speaker setting 0x%02x\n", val1);
return -EINVAL;
}
ret = es83xx_dsm(priv->codec_dev, PLATFORM_HPDET_INV_ARG, &val1);
if (ret < 0)
return ret;
switch (val1) {
case PLATFORM_HPDET_NORMAL:
break;
case PLATFORM_HPDET_INVERTED:
dsm_quirk |= BYT_CHT_ES8316_JD_INVERTED;
break;
default:
dev_warn(priv->codec_dev, "Unknown hpdet-inv setting 0x%02x\n", val1);
return -EINVAL;
}
quirk = dsm_quirk;
return 0;
}
static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
......@@ -470,10 +531,10 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
struct byt_cht_es8316_private *priv;
const struct dmi_system_id *dmi_id;
struct fwnode_handle *fwnode;
bool sof_parent, is_bytcr;
const char *platform_name;
struct acpi_device *adev;
struct device *codec_dev;
bool sof_parent;
unsigned int cnt = 0;
int dai_index = 0;
int i;
......@@ -520,12 +581,16 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
return ret;
}
es83xx_dsm_dump(priv->codec_dev);
/* Check for BYTCR or other platform and setup quirks */
is_bytcr = soc_intel_is_byt() && mach->mach_params.acpi_ipc_irq_index == 0;
dmi_id = dmi_first_match(byt_cht_es8316_quirk_table);
if (dmi_id) {
quirk = (unsigned long)dmi_id->driver_data;
} else if (soc_intel_is_byt() &&
mach->mach_params.acpi_ipc_irq_index == 0) {
} else if (!byt_cht_es8316_get_quirks_from_dsm(priv, is_bytcr)) {
dev_info(dev, "Using ACPI DSM info for quirks\n");
} else if (is_bytcr) {
/* On BYTCR default to SSP0, internal-mic-in2-map, mono-spk */
quirk = BYT_CHT_ES8316_SSP0 | BYT_CHT_ES8316_INTMIC_IN2_MAP |
BYT_CHT_ES8316_MONO_SPEAKER;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment