diff options
Diffstat (limited to 'sound/soc/intel/boards/bytcr_rt5640.c')
-rw-r--r-- | sound/soc/intel/boards/bytcr_rt5640.c | 64 |
1 files changed, 59 insertions, 5 deletions
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index bff77a1f27fc..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) { @@ -689,6 +687,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 +700,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,10 +737,61 @@ 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; } + + /* 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 */ |