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>
This commit is contained in:
Pierre-Louis Bossart 2016-11-12 18:07:45 -06:00 committed by Mark Brown
parent 3421894765
commit 64e84305cb
1 changed files with 51 additions and 2 deletions

View File

@ -689,6 +689,10 @@ static bool is_valleyview(void)
return true; 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) 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 i;
int dai_index; int dai_index;
struct byt_rt5640_private *priv; struct byt_rt5640_private *priv;
bool is_bytcr = false;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
if (!priv) 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; struct sst_platform_info *p_info = mach->pdata;
const struct sst_res_info *res_info = p_info->res_info; 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; byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
} }
} }