[alsa-devel] [PATCH 0/3] More Baytrail improvements
this patchset introduces an auto-detect mechanism to avoid adding quirks over and over. The BIOS provides information on AIF1/AIF2 connection and we set the microphone settings differently on baytrail-CR. This was tested on a variety of platforms and most people should have sound without quirks.
Pierre-Louis Bossart (3): ASoC: Intel: common: add ACPI package extraction utility ASoC: Intel: detect audio routing with CHAN package ASoC: Intel: bytct_rt5640: change default capture settings
sound/soc/intel/boards/bytcr_rt5640.c | 64 ++++++++++++++++++++++++++++++--- sound/soc/intel/common/sst-acpi.h | 17 ++++++++- sound/soc/intel/common/sst-match-acpi.c | 57 +++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 6 deletions(-)
Add a new common routine to extract a package exposed by a device indexed with the HID value. The functionality is implemented without assumptions on the package type or structure to allow for reuse. The caller is responsible for defining the name and allocating structures to store the results, ACPICA will complain in case of type mismatches or buffer size issues.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/intel/common/sst-acpi.h | 17 +++++++++- sound/soc/intel/common/sst-match-acpi.c | 57 +++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/common/sst-acpi.h b/sound/soc/intel/common/sst-acpi.h index 0127422..214e000 100644 --- a/sound/soc/intel/common/sst-acpi.h +++ b/sound/soc/intel/common/sst-acpi.h @@ -15,14 +15,29 @@ #include <linux/stddef.h> #include <linux/acpi.h>
-/* translation fron HID to I2C name, needed for DAI codec_name */ +struct sst_acpi_package_context { + char *name; /* package name */ + int length; /* number of elements */ + struct acpi_buffer *format; + struct acpi_buffer *state; + bool data_valid; +}; + #if IS_ENABLED(CONFIG_ACPI) +/* translation fron HID to I2C name, needed for DAI codec_name */ const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]); +bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], + struct sst_acpi_package_context *ctx); #else static inline const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]) { return NULL; } +static inline bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], + struct sst_acpi_package_context *ctx) +{ + return false; +} #endif
/* acpi match */ diff --git a/sound/soc/intel/common/sst-match-acpi.c b/sound/soc/intel/common/sst-match-acpi.c index 7898433..1070f3a 100644 --- a/sound/soc/intel/common/sst-match-acpi.c +++ b/sound/soc/intel/common/sst-match-acpi.c @@ -77,5 +77,62 @@ struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines) } EXPORT_SYMBOL_GPL(sst_acpi_find_machine);
+static acpi_status sst_acpi_find_package(acpi_handle handle, u32 level, + void *context, void **ret) +{ + struct acpi_device *adev; + acpi_status status = AE_OK; + struct sst_acpi_package_context *pkg_ctx = context; + + pkg_ctx->data_valid = false; + + if (acpi_bus_get_device(handle, &adev)) + return AE_OK; + + if (adev->status.present && adev->status.functional) { + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *myobj = NULL; + + status = acpi_evaluate_object_typed(handle, pkg_ctx->name, + NULL, &buffer, + ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(status)) + return AE_OK; + + myobj = buffer.pointer; + if (!myobj || myobj->package.count != pkg_ctx->length) { + kfree(buffer.pointer); + return AE_OK; + } + + status = acpi_extract_package(myobj, + pkg_ctx->format, pkg_ctx->state); + if (ACPI_FAILURE(status)) { + kfree(buffer.pointer); + return AE_OK; + } + + kfree(buffer.pointer); + pkg_ctx->data_valid = true; + return AE_CTRL_TERMINATE; + } + + return AE_OK; +} + +bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], + struct sst_acpi_package_context *ctx) +{ + acpi_status status; + + status = acpi_get_devices(hid, sst_acpi_find_package, ctx, NULL); + + if (ACPI_FAILURE(status) || !ctx->data_valid) + return false; + + return true; +} +EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid); + MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Intel Common ACPI Match module");
The patch
ASoC: Intel: common: add ACPI package extraction utility
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 3421894765a345c6919b22cdda606c2ba1aab2eb Mon Sep 17 00:00:00 2001
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Date: Sat, 12 Nov 2016 18:07:44 -0600 Subject: [PATCH] ASoC: Intel: common: add ACPI package extraction utility
Add a new common routine to extract a package exposed by a device indexed with the HID value. The functionality is implemented without assumptions on the package type or structure to allow for reuse. The caller is responsible for defining the name and allocating structures to store the results, ACPICA will complain in case of type mismatches or buffer size issues.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/common/sst-acpi.h | 17 +++++++++- sound/soc/intel/common/sst-match-acpi.c | 57 +++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/common/sst-acpi.h b/sound/soc/intel/common/sst-acpi.h index 012742299dd5..214e000667ae 100644 --- a/sound/soc/intel/common/sst-acpi.h +++ b/sound/soc/intel/common/sst-acpi.h @@ -15,14 +15,29 @@ #include <linux/stddef.h> #include <linux/acpi.h>
-/* translation fron HID to I2C name, needed for DAI codec_name */ +struct sst_acpi_package_context { + char *name; /* package name */ + int length; /* number of elements */ + struct acpi_buffer *format; + struct acpi_buffer *state; + bool data_valid; +}; + #if IS_ENABLED(CONFIG_ACPI) +/* translation fron HID to I2C name, needed for DAI codec_name */ const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]); +bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], + struct sst_acpi_package_context *ctx); #else static inline const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]) { return NULL; } +static inline bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], + struct sst_acpi_package_context *ctx) +{ + return false; +} #endif
/* acpi match */ diff --git a/sound/soc/intel/common/sst-match-acpi.c b/sound/soc/intel/common/sst-match-acpi.c index 789843307a49..1070f3ad23e5 100644 --- a/sound/soc/intel/common/sst-match-acpi.c +++ b/sound/soc/intel/common/sst-match-acpi.c @@ -77,5 +77,62 @@ struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines) } EXPORT_SYMBOL_GPL(sst_acpi_find_machine);
+static acpi_status sst_acpi_find_package(acpi_handle handle, u32 level, + void *context, void **ret) +{ + struct acpi_device *adev; + acpi_status status = AE_OK; + struct sst_acpi_package_context *pkg_ctx = context; + + pkg_ctx->data_valid = false; + + if (acpi_bus_get_device(handle, &adev)) + return AE_OK; + + if (adev->status.present && adev->status.functional) { + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *myobj = NULL; + + status = acpi_evaluate_object_typed(handle, pkg_ctx->name, + NULL, &buffer, + ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(status)) + return AE_OK; + + myobj = buffer.pointer; + if (!myobj || myobj->package.count != pkg_ctx->length) { + kfree(buffer.pointer); + return AE_OK; + } + + status = acpi_extract_package(myobj, + pkg_ctx->format, pkg_ctx->state); + if (ACPI_FAILURE(status)) { + kfree(buffer.pointer); + return AE_OK; + } + + kfree(buffer.pointer); + pkg_ctx->data_valid = true; + return AE_CTRL_TERMINATE; + } + + return AE_OK; +} + +bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], + struct sst_acpi_package_context *ctx) +{ + acpi_status status; + + status = acpi_get_devices(hid, sst_acpi_find_package, ctx, NULL); + + if (ACPI_FAILURE(status) || !ctx->data_valid) + return false; + + return true; +} +EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid); + MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Intel Common ACPI Match module");
Baytrail-CR devices usually expose information in the DSDT which can be used to auto-detect AIF1/AIF2 connections. The CHAN package contains two integers, the first one describes the AIF number (1: AIF1, 2: AIF2) and the second the MCLK value (ignored in this patch)
For example the following information is found in Lenovo 100s:
Device (RTEK) { [...] Name (CHAN, Package (0x02) { One, 0x017D7840 })
While on Asus T100TAF the package values are:
Name (CHAN, Package (0x02) { 0x02, 0x017D7840 })
This patch relies on the new common routine to extract a package exposed by a device indexed with the HID value. The CHAN package contents are queried from the machine driver and stored in a structure.
If this auto-detection fails (missing or bad package in the BIOS), the routing falls back to SSP0-AIF2.
Note that quirks may still be needed to support mono speakers or microphone, but this should reduce the number of issues with Baytrail significantly.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/intel/boards/bytcr_rt5640.c | 53 +++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 751e009..63a7993 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -689,6 +689,10 @@ static bool is_valleyview(void) return true; }
+struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ + u64 aif_value; /* 1: AIF1, 2: AIF2 */ + u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */ +};
static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) { @@ -698,6 +702,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) int i; int dai_index; struct byt_rt5640_private *priv; + bool is_bytcr = false;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); if (!priv) @@ -734,8 +739,52 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) struct sst_platform_info *p_info = mach->pdata; const struct sst_res_info *res_info = p_info->res_info;
- /* TODO: use CHAN package info from BIOS to detect AIF1/AIF2 */ - if (res_info->acpi_ipc_irq_index == 0) { + if (res_info->acpi_ipc_irq_index == 0) + is_bytcr = true; + } + + if (is_bytcr) { + /* + * Baytrail CR platforms may have CHAN package in BIOS, try + * to find relevant routing quirk based as done on Windows + * platforms. We have to read the information directly from the + * BIOS, at this stage the card is not created and the links + * with the codec driver/pdata are non-existent + */ + + struct acpi_chan_package chan_package; + + /* format specified: 2 64-bit integers */ + struct acpi_buffer format = {sizeof("NN"), "NN"}; + struct acpi_buffer state = {0, NULL}; + struct sst_acpi_package_context pkg_ctx; + bool pkg_found = false; + + state.length = sizeof(chan_package); + state.pointer = &chan_package; + + pkg_ctx.name = "CHAN"; + pkg_ctx.length = 2; + pkg_ctx.format = &format; + pkg_ctx.state = &state; + pkg_ctx.data_valid = false; + + pkg_found = sst_acpi_find_package_from_hid(mach->id, &pkg_ctx); + if (pkg_found) { + if (chan_package.aif_value == 1) { + dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n"); + byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1; + } else if (chan_package.aif_value == 2) { + dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n"); + byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; + } else { + dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n"); + pkg_found = false; + } + } + + if (!pkg_found) { + /* no BIOS indications, assume SSP0-AIF2 connection */ byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; } }
The patch
ASoC: Intel: detect audio routing with CHAN package
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 64e84305cb936024a9862c48f61539fdad649a22 Mon Sep 17 00:00:00 2001
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Date: Sat, 12 Nov 2016 18:07:45 -0600 Subject: [PATCH] ASoC: Intel: detect audio routing with CHAN package
Baytrail-CR devices usually expose information in the DSDT which can be used to auto-detect AIF1/AIF2 connections. The CHAN package contains two integers, the first one describes the AIF number (1: AIF1, 2: AIF2) and the second the MCLK value (ignored in this patch)
For example the following information is found in Lenovo 100s:
Device (RTEK) { [...] Name (CHAN, Package (0x02) { One, 0x017D7840 })
While on Asus T100TAF the package values are:
Name (CHAN, Package (0x02) { 0x02, 0x017D7840 })
This patch relies on the new common routine to extract a package exposed by a device indexed with the HID value. The CHAN package contents are queried from the machine driver and stored in a structure.
If this auto-detection fails (missing or bad package in the BIOS), the routing falls back to SSP0-AIF2.
Note that quirks may still be needed to support mono speakers or microphone, but this should reduce the number of issues with Baytrail significantly.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/boards/bytcr_rt5640.c | 53 +++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index bff77a1f27fc..32aeffc352ee 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -689,6 +689,10 @@ static bool is_valleyview(void) return true; }
+struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ + u64 aif_value; /* 1: AIF1, 2: AIF2 */ + u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */ +};
static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) { @@ -698,6 +702,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) int i; int dai_index; struct byt_rt5640_private *priv; + bool is_bytcr = false;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); if (!priv) @@ -734,8 +739,52 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) struct sst_platform_info *p_info = mach->pdata; const struct sst_res_info *res_info = p_info->res_info;
- /* TODO: use CHAN package info from BIOS to detect AIF1/AIF2 */ - if (res_info->acpi_ipc_irq_index == 0) { + if (res_info->acpi_ipc_irq_index == 0) + is_bytcr = true; + } + + if (is_bytcr) { + /* + * Baytrail CR platforms may have CHAN package in BIOS, try + * to find relevant routing quirk based as done on Windows + * platforms. We have to read the information directly from the + * BIOS, at this stage the card is not created and the links + * with the codec driver/pdata are non-existent + */ + + struct acpi_chan_package chan_package; + + /* format specified: 2 64-bit integers */ + struct acpi_buffer format = {sizeof("NN"), "NN"}; + struct acpi_buffer state = {0, NULL}; + struct sst_acpi_package_context pkg_ctx; + bool pkg_found = false; + + state.length = sizeof(chan_package); + state.pointer = &chan_package; + + pkg_ctx.name = "CHAN"; + pkg_ctx.length = 2; + pkg_ctx.format = &format; + pkg_ctx.state = &state; + pkg_ctx.data_valid = false; + + pkg_found = sst_acpi_find_package_from_hid(mach->id, &pkg_ctx); + if (pkg_found) { + if (chan_package.aif_value == 1) { + dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n"); + byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1; + } else if (chan_package.aif_value == 2) { + dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n"); + byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; + } else { + dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n"); + pkg_found = false; + } + } + + if (!pkg_found) { + /* no BIOS indications, assume SSP0-AIF2 connection */ byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; } }
Most Baytrail-CR devices use analog differential microphones, modify capture default to avoid DMI quirks. Keep digital mics for all other configurations.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com --- sound/soc/intel/boards/bytcr_rt5640.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 63a7993..507a86a 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -57,9 +57,7 @@ struct byt_rt5640_private { struct clk *mclk; };
-static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | - BYT_RT5640_DMIC_EN | - BYT_RT5640_MCLK_EN; +static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;
static void log_quirks(struct device *dev) { @@ -787,6 +785,13 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) /* no BIOS indications, assume SSP0-AIF2 connection */ byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; } + + /* change defaults for Baytrail-CR capture */ + byt_rt5640_quirk |= BYT_RT5640_IN1_MAP; + byt_rt5640_quirk |= BYT_RT5640_DIFF_MIC; + } else { + byt_rt5640_quirk |= (BYT_RT5640_DMIC1_MAP | + BYT_RT5640_DMIC_EN); }
/* check quirks before creating card */
The patch
ASoC: Intel: bytct_rt5640: change default capture settings
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From bf46241bee7bc3ec28703796f4fbd56085055fca Mon Sep 17 00:00:00 2001
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Date: Sat, 12 Nov 2016 18:07:46 -0600 Subject: [PATCH] ASoC: Intel: bytct_rt5640: change default capture settings
Most Baytrail-CR devices use analog differential microphones, modify capture default to avoid DMI quirks. Keep digital mics for all other configurations.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/intel/boards/bytcr_rt5640.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 32aeffc352ee..f9d73b55d2f7 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -57,9 +57,7 @@ struct byt_rt5640_private { struct clk *mclk; };
-static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP | - BYT_RT5640_DMIC_EN | - BYT_RT5640_MCLK_EN; +static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;
static void log_quirks(struct device *dev) { @@ -787,6 +785,13 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) /* no BIOS indications, assume SSP0-AIF2 connection */ byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; } + + /* change defaults for Baytrail-CR capture */ + byt_rt5640_quirk |= BYT_RT5640_IN1_MAP; + byt_rt5640_quirk |= BYT_RT5640_DIFF_MIC; + } else { + byt_rt5640_quirk |= (BYT_RT5640_DMIC1_MAP | + BYT_RT5640_DMIC_EN); }
/* check quirks before creating card */
participants (2)
-
Mark Brown
-
Pierre-Louis Bossart