18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * byt_cr_dpcm_rt5640.c - ASoc Machine driver for Intel Byt CR platform 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2014 Intel Corp 68c2ecf20Sopenharmony_ci * Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com> 78c2ecf20Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/i2c.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 168c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 178c2ecf20Sopenharmony_ci#include <linux/acpi.h> 188c2ecf20Sopenharmony_ci#include <linux/clk.h> 198c2ecf20Sopenharmony_ci#include <linux/device.h> 208c2ecf20Sopenharmony_ci#include <linux/dmi.h> 218c2ecf20Sopenharmony_ci#include <linux/input.h> 228c2ecf20Sopenharmony_ci#include <linux/slab.h> 238c2ecf20Sopenharmony_ci#include <sound/pcm.h> 248c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 258c2ecf20Sopenharmony_ci#include <sound/soc.h> 268c2ecf20Sopenharmony_ci#include <sound/jack.h> 278c2ecf20Sopenharmony_ci#include <sound/soc-acpi.h> 288c2ecf20Sopenharmony_ci#include <dt-bindings/sound/rt5640.h> 298c2ecf20Sopenharmony_ci#include "../../codecs/rt5640.h" 308c2ecf20Sopenharmony_ci#include "../atom/sst-atom-controls.h" 318c2ecf20Sopenharmony_ci#include "../common/soc-intel-quirks.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cienum { 348c2ecf20Sopenharmony_ci BYT_RT5640_DMIC1_MAP, 358c2ecf20Sopenharmony_ci BYT_RT5640_DMIC2_MAP, 368c2ecf20Sopenharmony_ci BYT_RT5640_IN1_MAP, 378c2ecf20Sopenharmony_ci BYT_RT5640_IN3_MAP, 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cienum { 418c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_GPIO1 = (RT5640_JD_SRC_GPIO1 << 4), 428c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P = (RT5640_JD_SRC_JD1_IN4P << 4), 438c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N = (RT5640_JD_SRC_JD2_IN4N << 4), 448c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_GPIO2 = (RT5640_JD_SRC_GPIO2 << 4), 458c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_GPIO3 = (RT5640_JD_SRC_GPIO3 << 4), 468c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_GPIO4 = (RT5640_JD_SRC_GPIO4 << 4), 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cienum { 508c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_600UA = (6 << 8), 518c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA = (15 << 8), 528c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA = (20 << 8), 538c2ecf20Sopenharmony_ci}; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cienum { 568c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P5 = (RT5640_OVCD_SF_0P5 << 13), 578c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 = (RT5640_OVCD_SF_0P75 << 13), 588c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_1P0 = (RT5640_OVCD_SF_1P0 << 13), 598c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_1P5 = (RT5640_OVCD_SF_1P5 << 13), 608c2ecf20Sopenharmony_ci}; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define BYT_RT5640_MAP(quirk) ((quirk) & GENMASK(3, 0)) 638c2ecf20Sopenharmony_ci#define BYT_RT5640_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4) 648c2ecf20Sopenharmony_ci#define BYT_RT5640_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8) 658c2ecf20Sopenharmony_ci#define BYT_RT5640_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13) 668c2ecf20Sopenharmony_ci#define BYT_RT5640_JD_NOT_INV BIT(16) 678c2ecf20Sopenharmony_ci#define BYT_RT5640_MONO_SPEAKER BIT(17) 688c2ecf20Sopenharmony_ci#define BYT_RT5640_DIFF_MIC BIT(18) /* default is single-ended */ 698c2ecf20Sopenharmony_ci#define BYT_RT5640_SSP2_AIF2 BIT(19) /* default is using AIF1 */ 708c2ecf20Sopenharmony_ci#define BYT_RT5640_SSP0_AIF1 BIT(20) 718c2ecf20Sopenharmony_ci#define BYT_RT5640_SSP0_AIF2 BIT(21) 728c2ecf20Sopenharmony_ci#define BYT_RT5640_MCLK_EN BIT(22) 738c2ecf20Sopenharmony_ci#define BYT_RT5640_MCLK_25MHZ BIT(23) 748c2ecf20Sopenharmony_ci#define BYT_RT5640_NO_SPEAKERS BIT(24) 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#define BYTCR_INPUT_DEFAULTS \ 778c2ecf20Sopenharmony_ci (BYT_RT5640_IN3_MAP | \ 788c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | \ 798c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | \ 808c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | \ 818c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* in-diff or dmic-pin + jdsrc + ovcd-th + -sf + jd-inv + terminating entry */ 848c2ecf20Sopenharmony_ci#define MAX_NO_PROPS 6 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistruct byt_rt5640_private { 878c2ecf20Sopenharmony_ci struct snd_soc_jack jack; 888c2ecf20Sopenharmony_ci struct clk *mclk; 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_cistatic bool is_bytcr; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN; 938c2ecf20Sopenharmony_cistatic int quirk_override = -1; 948c2ecf20Sopenharmony_cimodule_param_named(quirk, quirk_override, int, 0444); 958c2ecf20Sopenharmony_ciMODULE_PARM_DESC(quirk, "Board-specific quirk override"); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic void log_quirks(struct device *dev) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci int map; 1008c2ecf20Sopenharmony_ci bool has_mclk = false; 1018c2ecf20Sopenharmony_ci bool has_ssp0 = false; 1028c2ecf20Sopenharmony_ci bool has_ssp0_aif1 = false; 1038c2ecf20Sopenharmony_ci bool has_ssp0_aif2 = false; 1048c2ecf20Sopenharmony_ci bool has_ssp2_aif2 = false; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci map = BYT_RT5640_MAP(byt_rt5640_quirk); 1078c2ecf20Sopenharmony_ci switch (map) { 1088c2ecf20Sopenharmony_ci case BYT_RT5640_DMIC1_MAP: 1098c2ecf20Sopenharmony_ci dev_info(dev, "quirk DMIC1_MAP enabled\n"); 1108c2ecf20Sopenharmony_ci break; 1118c2ecf20Sopenharmony_ci case BYT_RT5640_DMIC2_MAP: 1128c2ecf20Sopenharmony_ci dev_info(dev, "quirk DMIC2_MAP enabled\n"); 1138c2ecf20Sopenharmony_ci break; 1148c2ecf20Sopenharmony_ci case BYT_RT5640_IN1_MAP: 1158c2ecf20Sopenharmony_ci dev_info(dev, "quirk IN1_MAP enabled\n"); 1168c2ecf20Sopenharmony_ci break; 1178c2ecf20Sopenharmony_ci case BYT_RT5640_IN3_MAP: 1188c2ecf20Sopenharmony_ci dev_info(dev, "quirk IN3_MAP enabled\n"); 1198c2ecf20Sopenharmony_ci break; 1208c2ecf20Sopenharmony_ci default: 1218c2ecf20Sopenharmony_ci dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map); 1228c2ecf20Sopenharmony_ci break; 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) { 1258c2ecf20Sopenharmony_ci dev_info(dev, "quirk realtek,jack-detect-source %ld\n", 1268c2ecf20Sopenharmony_ci BYT_RT5640_JDSRC(byt_rt5640_quirk)); 1278c2ecf20Sopenharmony_ci dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n", 1288c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100); 1298c2ecf20Sopenharmony_ci dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n", 1308c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF(byt_rt5640_quirk)); 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV) 1338c2ecf20Sopenharmony_ci dev_info(dev, "quirk JD_NOT_INV enabled\n"); 1348c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) 1358c2ecf20Sopenharmony_ci dev_info(dev, "quirk MONO_SPEAKER enabled\n"); 1368c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) 1378c2ecf20Sopenharmony_ci dev_info(dev, "quirk NO_SPEAKERS enabled\n"); 1388c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) 1398c2ecf20Sopenharmony_ci dev_info(dev, "quirk DIFF_MIC enabled\n"); 1408c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { 1418c2ecf20Sopenharmony_ci dev_info(dev, "quirk SSP0_AIF1 enabled\n"); 1428c2ecf20Sopenharmony_ci has_ssp0 = true; 1438c2ecf20Sopenharmony_ci has_ssp0_aif1 = true; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) { 1468c2ecf20Sopenharmony_ci dev_info(dev, "quirk SSP0_AIF2 enabled\n"); 1478c2ecf20Sopenharmony_ci has_ssp0 = true; 1488c2ecf20Sopenharmony_ci has_ssp0_aif2 = true; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { 1518c2ecf20Sopenharmony_ci dev_info(dev, "quirk SSP2_AIF2 enabled\n"); 1528c2ecf20Sopenharmony_ci has_ssp2_aif2 = true; 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci if (is_bytcr && !has_ssp0) 1558c2ecf20Sopenharmony_ci dev_err(dev, "Invalid routing, bytcr detected but no SSP0-based quirk, audio cannot work with SSP2 on bytcr\n"); 1568c2ecf20Sopenharmony_ci if (has_ssp0_aif1 && has_ssp0_aif2) 1578c2ecf20Sopenharmony_ci dev_err(dev, "Invalid routing, SSP0 cannot be connected to both AIF1 and AIF2\n"); 1588c2ecf20Sopenharmony_ci if (has_ssp0 && has_ssp2_aif2) 1598c2ecf20Sopenharmony_ci dev_err(dev, "Invalid routing, cannot have both SSP0 and SSP2 connected to codec\n"); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { 1628c2ecf20Sopenharmony_ci dev_info(dev, "quirk MCLK_EN enabled\n"); 1638c2ecf20Sopenharmony_ci has_mclk = true; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) { 1668c2ecf20Sopenharmony_ci if (has_mclk) 1678c2ecf20Sopenharmony_ci dev_info(dev, "quirk MCLK_25MHZ enabled\n"); 1688c2ecf20Sopenharmony_ci else 1698c2ecf20Sopenharmony_ci dev_err(dev, "quirk MCLK_25MHZ enabled but quirk MCLK not selected, will be ignored\n"); 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic int byt_rt5640_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai, 1748c2ecf20Sopenharmony_ci int rate) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci int ret; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /* Configure the PLL before selecting it */ 1798c2ecf20Sopenharmony_ci if (!(byt_rt5640_quirk & BYT_RT5640_MCLK_EN)) { 1808c2ecf20Sopenharmony_ci /* use bitclock as PLL input */ 1818c2ecf20Sopenharmony_ci if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || 1828c2ecf20Sopenharmony_ci (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { 1838c2ecf20Sopenharmony_ci /* 2x16 bit slots on SSP0 */ 1848c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_pll(codec_dai, 0, 1858c2ecf20Sopenharmony_ci RT5640_PLL1_S_BCLK1, 1868c2ecf20Sopenharmony_ci rate * 32, rate * 512); 1878c2ecf20Sopenharmony_ci } else { 1888c2ecf20Sopenharmony_ci /* 2x15 bit slots on SSP2 */ 1898c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_pll(codec_dai, 0, 1908c2ecf20Sopenharmony_ci RT5640_PLL1_S_BCLK1, 1918c2ecf20Sopenharmony_ci rate * 50, rate * 512); 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci } else { 1948c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) { 1958c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_pll(codec_dai, 0, 1968c2ecf20Sopenharmony_ci RT5640_PLL1_S_MCLK, 1978c2ecf20Sopenharmony_ci 25000000, rate * 512); 1988c2ecf20Sopenharmony_ci } else { 1998c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_pll(codec_dai, 0, 2008c2ecf20Sopenharmony_ci RT5640_PLL1_S_MCLK, 2018c2ecf20Sopenharmony_ci 19200000, rate * 512); 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci if (ret < 0) { 2068c2ecf20Sopenharmony_ci dev_err(codec_dai->component->dev, "can't set pll: %d\n", ret); 2078c2ecf20Sopenharmony_ci return ret; 2088c2ecf20Sopenharmony_ci } 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, 2118c2ecf20Sopenharmony_ci rate * 512, SND_SOC_CLOCK_IN); 2128c2ecf20Sopenharmony_ci if (ret < 0) { 2138c2ecf20Sopenharmony_ci dev_err(codec_dai->component->dev, "can't set clock %d\n", ret); 2148c2ecf20Sopenharmony_ci return ret; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci return 0; 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci#define BYT_CODEC_DAI1 "rt5640-aif1" 2218c2ecf20Sopenharmony_ci#define BYT_CODEC_DAI2 "rt5640-aif2" 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic int platform_clock_control(struct snd_soc_dapm_widget *w, 2248c2ecf20Sopenharmony_ci struct snd_kcontrol *k, int event) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci struct snd_soc_dapm_context *dapm = w->dapm; 2278c2ecf20Sopenharmony_ci struct snd_soc_card *card = dapm->card; 2288c2ecf20Sopenharmony_ci struct snd_soc_dai *codec_dai; 2298c2ecf20Sopenharmony_ci struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 2308c2ecf20Sopenharmony_ci int ret; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1); 2338c2ecf20Sopenharmony_ci if (!codec_dai) 2348c2ecf20Sopenharmony_ci codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci if (!codec_dai) { 2378c2ecf20Sopenharmony_ci dev_err(card->dev, 2388c2ecf20Sopenharmony_ci "Codec dai not found; Unable to set platform clock\n"); 2398c2ecf20Sopenharmony_ci return -EIO; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (SND_SOC_DAPM_EVENT_ON(event)) { 2438c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { 2448c2ecf20Sopenharmony_ci ret = clk_prepare_enable(priv->mclk); 2458c2ecf20Sopenharmony_ci if (ret < 0) { 2468c2ecf20Sopenharmony_ci dev_err(card->dev, 2478c2ecf20Sopenharmony_ci "could not configure MCLK state\n"); 2488c2ecf20Sopenharmony_ci return ret; 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci ret = byt_rt5640_prepare_and_enable_pll1(codec_dai, 48000); 2528c2ecf20Sopenharmony_ci } else { 2538c2ecf20Sopenharmony_ci /* 2548c2ecf20Sopenharmony_ci * Set codec clock source to internal clock before 2558c2ecf20Sopenharmony_ci * turning off the platform clock. Codec needs clock 2568c2ecf20Sopenharmony_ci * for Jack detection and button press 2578c2ecf20Sopenharmony_ci */ 2588c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK, 2598c2ecf20Sopenharmony_ci 48000 * 512, 2608c2ecf20Sopenharmony_ci SND_SOC_CLOCK_IN); 2618c2ecf20Sopenharmony_ci if (!ret) { 2628c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) 2638c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->mclk); 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci if (ret < 0) { 2688c2ecf20Sopenharmony_ci dev_err(card->dev, "can't set codec sysclk: %d\n", ret); 2698c2ecf20Sopenharmony_ci return ret; 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci return 0; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { 2768c2ecf20Sopenharmony_ci SND_SOC_DAPM_HP("Headphone", NULL), 2778c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIC("Headset Mic", NULL), 2788c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIC("Internal Mic", NULL), 2798c2ecf20Sopenharmony_ci SND_SOC_DAPM_SPK("Speaker", NULL), 2808c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, 2818c2ecf20Sopenharmony_ci platform_clock_control, SND_SOC_DAPM_PRE_PMU | 2828c2ecf20Sopenharmony_ci SND_SOC_DAPM_POST_PMD), 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci}; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { 2878c2ecf20Sopenharmony_ci {"Headphone", NULL, "Platform Clock"}, 2888c2ecf20Sopenharmony_ci {"Headset Mic", NULL, "Platform Clock"}, 2898c2ecf20Sopenharmony_ci {"Headset Mic", NULL, "MICBIAS1"}, 2908c2ecf20Sopenharmony_ci {"IN2P", NULL, "Headset Mic"}, 2918c2ecf20Sopenharmony_ci {"Headphone", NULL, "HPOL"}, 2928c2ecf20Sopenharmony_ci {"Headphone", NULL, "HPOR"}, 2938c2ecf20Sopenharmony_ci}; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = { 2968c2ecf20Sopenharmony_ci {"Internal Mic", NULL, "Platform Clock"}, 2978c2ecf20Sopenharmony_ci {"DMIC1", NULL, "Internal Mic"}, 2988c2ecf20Sopenharmony_ci}; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = { 3018c2ecf20Sopenharmony_ci {"Internal Mic", NULL, "Platform Clock"}, 3028c2ecf20Sopenharmony_ci {"DMIC2", NULL, "Internal Mic"}, 3038c2ecf20Sopenharmony_ci}; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { 3068c2ecf20Sopenharmony_ci {"Internal Mic", NULL, "Platform Clock"}, 3078c2ecf20Sopenharmony_ci {"Internal Mic", NULL, "MICBIAS1"}, 3088c2ecf20Sopenharmony_ci {"IN1P", NULL, "Internal Mic"}, 3098c2ecf20Sopenharmony_ci}; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = { 3128c2ecf20Sopenharmony_ci {"Internal Mic", NULL, "Platform Clock"}, 3138c2ecf20Sopenharmony_ci {"Internal Mic", NULL, "MICBIAS1"}, 3148c2ecf20Sopenharmony_ci {"IN3P", NULL, "Internal Mic"}, 3158c2ecf20Sopenharmony_ci}; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = { 3188c2ecf20Sopenharmony_ci {"ssp2 Tx", NULL, "codec_out0"}, 3198c2ecf20Sopenharmony_ci {"ssp2 Tx", NULL, "codec_out1"}, 3208c2ecf20Sopenharmony_ci {"codec_in0", NULL, "ssp2 Rx"}, 3218c2ecf20Sopenharmony_ci {"codec_in1", NULL, "ssp2 Rx"}, 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci {"AIF1 Playback", NULL, "ssp2 Tx"}, 3248c2ecf20Sopenharmony_ci {"ssp2 Rx", NULL, "AIF1 Capture"}, 3258c2ecf20Sopenharmony_ci}; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_ssp2_aif2_map[] = { 3288c2ecf20Sopenharmony_ci {"ssp2 Tx", NULL, "codec_out0"}, 3298c2ecf20Sopenharmony_ci {"ssp2 Tx", NULL, "codec_out1"}, 3308c2ecf20Sopenharmony_ci {"codec_in0", NULL, "ssp2 Rx"}, 3318c2ecf20Sopenharmony_ci {"codec_in1", NULL, "ssp2 Rx"}, 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci {"AIF2 Playback", NULL, "ssp2 Tx"}, 3348c2ecf20Sopenharmony_ci {"ssp2 Rx", NULL, "AIF2 Capture"}, 3358c2ecf20Sopenharmony_ci}; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_ssp0_aif1_map[] = { 3388c2ecf20Sopenharmony_ci {"ssp0 Tx", NULL, "modem_out"}, 3398c2ecf20Sopenharmony_ci {"modem_in", NULL, "ssp0 Rx"}, 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci {"AIF1 Playback", NULL, "ssp0 Tx"}, 3428c2ecf20Sopenharmony_ci {"ssp0 Rx", NULL, "AIF1 Capture"}, 3438c2ecf20Sopenharmony_ci}; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = { 3468c2ecf20Sopenharmony_ci {"ssp0 Tx", NULL, "modem_out"}, 3478c2ecf20Sopenharmony_ci {"modem_in", NULL, "ssp0 Rx"}, 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci {"AIF2 Playback", NULL, "ssp0 Tx"}, 3508c2ecf20Sopenharmony_ci {"ssp0 Rx", NULL, "AIF2 Capture"}, 3518c2ecf20Sopenharmony_ci}; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = { 3548c2ecf20Sopenharmony_ci {"Speaker", NULL, "Platform Clock"}, 3558c2ecf20Sopenharmony_ci {"Speaker", NULL, "SPOLP"}, 3568c2ecf20Sopenharmony_ci {"Speaker", NULL, "SPOLN"}, 3578c2ecf20Sopenharmony_ci {"Speaker", NULL, "SPORP"}, 3588c2ecf20Sopenharmony_ci {"Speaker", NULL, "SPORN"}, 3598c2ecf20Sopenharmony_ci}; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = { 3628c2ecf20Sopenharmony_ci {"Speaker", NULL, "Platform Clock"}, 3638c2ecf20Sopenharmony_ci {"Speaker", NULL, "SPOLP"}, 3648c2ecf20Sopenharmony_ci {"Speaker", NULL, "SPOLN"}, 3658c2ecf20Sopenharmony_ci}; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new byt_rt5640_controls[] = { 3688c2ecf20Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Headphone"), 3698c2ecf20Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Headset Mic"), 3708c2ecf20Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Internal Mic"), 3718c2ecf20Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Speaker"), 3728c2ecf20Sopenharmony_ci}; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic struct snd_soc_jack_pin rt5640_pins[] = { 3758c2ecf20Sopenharmony_ci { 3768c2ecf20Sopenharmony_ci .pin = "Headphone", 3778c2ecf20Sopenharmony_ci .mask = SND_JACK_HEADPHONE, 3788c2ecf20Sopenharmony_ci }, 3798c2ecf20Sopenharmony_ci { 3808c2ecf20Sopenharmony_ci .pin = "Headset Mic", 3818c2ecf20Sopenharmony_ci .mask = SND_JACK_MICROPHONE, 3828c2ecf20Sopenharmony_ci }, 3838c2ecf20Sopenharmony_ci}; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cistatic int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, 3868c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 3898c2ecf20Sopenharmony_ci struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params)); 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci/* Please keep this list alphabetically sorted */ 3958c2ecf20Sopenharmony_cistatic const struct dmi_system_id byt_rt5640_quirk_table[] = { 3968c2ecf20Sopenharmony_ci { /* Acer Iconia One 7 B1-750 */ 3978c2ecf20Sopenharmony_ci .matches = { 3988c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), 3998c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "VESPA2"), 4008c2ecf20Sopenharmony_ci }, 4018c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 4028c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | 4038c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 4048c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 4058c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 4068c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 4078c2ecf20Sopenharmony_ci }, 4088c2ecf20Sopenharmony_ci { /* Acer Iconia Tab 8 W1-810 */ 4098c2ecf20Sopenharmony_ci .matches = { 4108c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"), 4118c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Iconia W1-810"), 4128c2ecf20Sopenharmony_ci }, 4138c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 4148c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | 4158c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 4168c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 4178c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 4188c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 4198c2ecf20Sopenharmony_ci }, 4208c2ecf20Sopenharmony_ci { /* Acer One 10 S1002 */ 4218c2ecf20Sopenharmony_ci .matches = { 4228c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 4238c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "One S1002"), 4248c2ecf20Sopenharmony_ci }, 4258c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 4268c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 4278c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 4288c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 4298c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 4308c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF2 | 4318c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 4328c2ecf20Sopenharmony_ci }, 4338c2ecf20Sopenharmony_ci { 4348c2ecf20Sopenharmony_ci .matches = { 4358c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 4368c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"), 4378c2ecf20Sopenharmony_ci }, 4388c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 4398c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 4408c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 4418c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 4428c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 4438c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 4448c2ecf20Sopenharmony_ci }, 4458c2ecf20Sopenharmony_ci { 4468c2ecf20Sopenharmony_ci /* Advantech MICA-071 */ 4478c2ecf20Sopenharmony_ci .matches = { 4488c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"), 4498c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"), 4508c2ecf20Sopenharmony_ci }, 4518c2ecf20Sopenharmony_ci /* OVCD Th = 1500uA to reliable detect head-phones vs -set */ 4528c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN3_MAP | 4538c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 4548c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 4558c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 4568c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 4578c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 4588c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 4598c2ecf20Sopenharmony_ci }, 4608c2ecf20Sopenharmony_ci { 4618c2ecf20Sopenharmony_ci .matches = { 4628c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), 4638c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 80 Cesium"), 4648c2ecf20Sopenharmony_ci }, 4658c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 4668c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 4678c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 4688c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 4698c2ecf20Sopenharmony_ci }, 4708c2ecf20Sopenharmony_ci { 4718c2ecf20Sopenharmony_ci .matches = { 4728c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), 4738c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"), 4748c2ecf20Sopenharmony_ci }, 4758c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 4768c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 4778c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 4788c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 4798c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 4808c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 4818c2ecf20Sopenharmony_ci }, 4828c2ecf20Sopenharmony_ci { 4838c2ecf20Sopenharmony_ci .matches = { 4848c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 4858c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"), 4868c2ecf20Sopenharmony_ci }, 4878c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 4888c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 4898c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 4908c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 4918c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 4928c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 4938c2ecf20Sopenharmony_ci }, 4948c2ecf20Sopenharmony_ci { 4958c2ecf20Sopenharmony_ci .matches = { 4968c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 4978c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), 4988c2ecf20Sopenharmony_ci }, 4998c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 5008c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 5018c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 5028c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 5038c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 5048c2ecf20Sopenharmony_ci }, 5058c2ecf20Sopenharmony_ci { 5068c2ecf20Sopenharmony_ci .matches = { 5078c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 5088c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), 5098c2ecf20Sopenharmony_ci }, 5108c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 5118c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 5128c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 5138c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 5148c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 5158c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 5168c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF2 | 5178c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 5188c2ecf20Sopenharmony_ci }, 5198c2ecf20Sopenharmony_ci { /* Chuwi Vi8 (CWI506) */ 5208c2ecf20Sopenharmony_ci .matches = { 5218c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), 5228c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"), 5238c2ecf20Sopenharmony_ci /* The above are too generic, also match BIOS info */ 5248c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"), 5258c2ecf20Sopenharmony_ci }, 5268c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 5278c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 5288c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 5298c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 5308c2ecf20Sopenharmony_ci }, 5318c2ecf20Sopenharmony_ci { 5328c2ecf20Sopenharmony_ci /* Chuwi Vi10 (CWI505) */ 5338c2ecf20Sopenharmony_ci .matches = { 5348c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), 5358c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"), 5368c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "ilife"), 5378c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "S165"), 5388c2ecf20Sopenharmony_ci }, 5398c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 5408c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 5418c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 5428c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 5438c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 5448c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 5458c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 5468c2ecf20Sopenharmony_ci }, 5478c2ecf20Sopenharmony_ci { 5488c2ecf20Sopenharmony_ci /* Chuwi Hi8 (CWI509) */ 5498c2ecf20Sopenharmony_ci .matches = { 5508c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), 5518c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"), 5528c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "ilife"), 5538c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "S806"), 5548c2ecf20Sopenharmony_ci }, 5558c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 5568c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 5578c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 5588c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 5598c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 5608c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 5618c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 5628c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 5638c2ecf20Sopenharmony_ci }, 5648c2ecf20Sopenharmony_ci { 5658c2ecf20Sopenharmony_ci .matches = { 5668c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), 5678c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"), 5688c2ecf20Sopenharmony_ci }, 5698c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP), 5708c2ecf20Sopenharmony_ci }, 5718c2ecf20Sopenharmony_ci { /* Connect Tablet 9 */ 5728c2ecf20Sopenharmony_ci .matches = { 5738c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Connect"), 5748c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Tablet 9"), 5758c2ecf20Sopenharmony_ci }, 5768c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 5778c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 5788c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 5798c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 5808c2ecf20Sopenharmony_ci }, 5818c2ecf20Sopenharmony_ci { 5828c2ecf20Sopenharmony_ci .matches = { 5838c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 5848c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"), 5858c2ecf20Sopenharmony_ci }, 5868c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 5878c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 5888c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 5898c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 5908c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 5918c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 5928c2ecf20Sopenharmony_ci }, 5938c2ecf20Sopenharmony_ci { /* Estar Beauty HD MID 7316R */ 5948c2ecf20Sopenharmony_ci .matches = { 5958c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Estar"), 5968c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"), 5978c2ecf20Sopenharmony_ci }, 5988c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 5998c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 6008c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 6018c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 6028c2ecf20Sopenharmony_ci }, 6038c2ecf20Sopenharmony_ci { /* Glavey TM800A550L */ 6048c2ecf20Sopenharmony_ci .matches = { 6058c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 6068c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 6078c2ecf20Sopenharmony_ci /* Above strings are too generic, also match on BIOS version */ 6088c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"), 6098c2ecf20Sopenharmony_ci }, 6108c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 6118c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 6128c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 6138c2ecf20Sopenharmony_ci }, 6148c2ecf20Sopenharmony_ci { 6158c2ecf20Sopenharmony_ci .matches = { 6168c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 6178c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"), 6188c2ecf20Sopenharmony_ci }, 6198c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 6208c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 6218c2ecf20Sopenharmony_ci }, 6228c2ecf20Sopenharmony_ci { /* HP Pavilion x2 10-k0XX, 10-n0XX */ 6238c2ecf20Sopenharmony_ci .matches = { 6248c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 6258c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), 6268c2ecf20Sopenharmony_ci }, 6278c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 6288c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 6298c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 6308c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 6318c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 6328c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 6338c2ecf20Sopenharmony_ci }, 6348c2ecf20Sopenharmony_ci { /* HP Pavilion x2 10-p0XX */ 6358c2ecf20Sopenharmony_ci .matches = { 6368c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "HP"), 6378c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"), 6388c2ecf20Sopenharmony_ci }, 6398c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 6408c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | 6418c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 6428c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 6438c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 6448c2ecf20Sopenharmony_ci }, 6458c2ecf20Sopenharmony_ci { /* HP Pro Tablet 408 */ 6468c2ecf20Sopenharmony_ci .matches = { 6478c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 6488c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "HP Pro Tablet 408"), 6498c2ecf20Sopenharmony_ci }, 6508c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 6518c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 6528c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 6538c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 6548c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 6558c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 6568c2ecf20Sopenharmony_ci }, 6578c2ecf20Sopenharmony_ci { /* HP Stream 7 */ 6588c2ecf20Sopenharmony_ci .matches = { 6598c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 6608c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 7 Tablet"), 6618c2ecf20Sopenharmony_ci }, 6628c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 6638c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 6648c2ecf20Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 6658c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 6668c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 6678c2ecf20Sopenharmony_ci }, 6688c2ecf20Sopenharmony_ci { /* I.T.Works TW891 */ 6698c2ecf20Sopenharmony_ci .matches = { 6708c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), 6718c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"), 6728c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), 6738c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"), 6748c2ecf20Sopenharmony_ci }, 6758c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 6768c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 6778c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 6788c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 6798c2ecf20Sopenharmony_ci }, 6808c2ecf20Sopenharmony_ci { /* Lamina I8270 / T701BR.SE */ 6818c2ecf20Sopenharmony_ci .matches = { 6828c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Lamina"), 6838c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "T701BR.SE"), 6848c2ecf20Sopenharmony_ci }, 6858c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 6868c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 6878c2ecf20Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 6888c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 6898c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 6908c2ecf20Sopenharmony_ci }, 6918c2ecf20Sopenharmony_ci { /* Lenovo Miix 2 8 */ 6928c2ecf20Sopenharmony_ci .matches = { 6938c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), 6948c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "20326"), 6958c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Hiking"), 6968c2ecf20Sopenharmony_ci }, 6978c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 6988c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 6998c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 7008c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 7018c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 7028c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 7038c2ecf20Sopenharmony_ci }, 7048c2ecf20Sopenharmony_ci { /* Lenovo Miix 3-830 */ 7058c2ecf20Sopenharmony_ci .matches = { 7068c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), 7078c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 3-830"), 7088c2ecf20Sopenharmony_ci }, 7098c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 7108c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 7118c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 7128c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 7138c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 7148c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 7158c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 7168c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 7178c2ecf20Sopenharmony_ci }, 7188c2ecf20Sopenharmony_ci { /* Linx Linx7 tablet */ 7198c2ecf20Sopenharmony_ci .matches = { 7208c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LINX"), 7218c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LINX7"), 7228c2ecf20Sopenharmony_ci }, 7238c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 7248c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 7258c2ecf20Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 7268c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 7278c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 7288c2ecf20Sopenharmony_ci }, 7298c2ecf20Sopenharmony_ci { /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */ 7308c2ecf20Sopenharmony_ci .matches = { 7318c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"), 7328c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"), 7338c2ecf20Sopenharmony_ci }, 7348c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 7358c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 7368c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 7378c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 7388c2ecf20Sopenharmony_ci }, 7398c2ecf20Sopenharmony_ci { 7408c2ecf20Sopenharmony_ci /* MPMAN MPWIN895CL */ 7418c2ecf20Sopenharmony_ci .matches = { 7428c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MPMAN"), 7438c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MPWIN8900CL"), 7448c2ecf20Sopenharmony_ci }, 7458c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 7468c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 7478c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 7488c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 7498c2ecf20Sopenharmony_ci }, 7508c2ecf20Sopenharmony_ci { /* MSI S100 tablet */ 7518c2ecf20Sopenharmony_ci .matches = { 7528c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."), 7538c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "S100"), 7548c2ecf20Sopenharmony_ci }, 7558c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 7568c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 7578c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 7588c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 7598c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 7608c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 7618c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 7628c2ecf20Sopenharmony_ci }, 7638c2ecf20Sopenharmony_ci { /* Nuvison/TMax TM800W560 */ 7648c2ecf20Sopenharmony_ci .matches = { 7658c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TMAX"), 7668c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TM800W560L"), 7678c2ecf20Sopenharmony_ci }, 7688c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 7698c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 7708c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 7718c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 7728c2ecf20Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 7738c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 7748c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 7758c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 7768c2ecf20Sopenharmony_ci }, 7778c2ecf20Sopenharmony_ci { /* Onda v975w */ 7788c2ecf20Sopenharmony_ci .matches = { 7798c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 7808c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 7818c2ecf20Sopenharmony_ci /* The above are too generic, also match BIOS info */ 7828c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_VERSION, "5.6.5"), 7838c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_DATE, "07/25/2014"), 7848c2ecf20Sopenharmony_ci }, 7858c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 7868c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 7878c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 7888c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 7898c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 7908c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 7918c2ecf20Sopenharmony_ci }, 7928c2ecf20Sopenharmony_ci { /* Pipo W4 */ 7938c2ecf20Sopenharmony_ci .matches = { 7948c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 7958c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 7968c2ecf20Sopenharmony_ci /* The above are too generic, also match BIOS info */ 7978c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BIOS_VERSION, "V8L_WIN32_CHIPHD"), 7988c2ecf20Sopenharmony_ci }, 7998c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 8008c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 8018c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 8028c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 8038c2ecf20Sopenharmony_ci }, 8048c2ecf20Sopenharmony_ci { /* Point of View Mobii TAB-P800W (V2.0) */ 8058c2ecf20Sopenharmony_ci .matches = { 8068c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 8078c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 8088c2ecf20Sopenharmony_ci /* The above are too generic, also match BIOS info */ 8098c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1014"), 8108c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_DATE, "10/24/2014"), 8118c2ecf20Sopenharmony_ci }, 8128c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 8138c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 8148c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 8158c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 8168c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 8178c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 8188c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF2 | 8198c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 8208c2ecf20Sopenharmony_ci }, 8218c2ecf20Sopenharmony_ci { /* Point of View Mobii TAB-P800W (V2.1) */ 8228c2ecf20Sopenharmony_ci .matches = { 8238c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 8248c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 8258c2ecf20Sopenharmony_ci /* The above are too generic, also match BIOS info */ 8268c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1013"), 8278c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_DATE, "08/22/2014"), 8288c2ecf20Sopenharmony_ci }, 8298c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 8308c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 8318c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 8328c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 8338c2ecf20Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 8348c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 8358c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF2 | 8368c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 8378c2ecf20Sopenharmony_ci }, 8388c2ecf20Sopenharmony_ci { /* Point of View Mobii TAB-P1005W-232 (V2.0) */ 8398c2ecf20Sopenharmony_ci .matches = { 8408c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "POV"), 8418c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "I102A"), 8428c2ecf20Sopenharmony_ci }, 8438c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 8448c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 8458c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 8468c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 8478c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 8488c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 8498c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 8508c2ecf20Sopenharmony_ci }, 8518c2ecf20Sopenharmony_ci { 8528c2ecf20Sopenharmony_ci /* Prowise PT301 */ 8538c2ecf20Sopenharmony_ci .matches = { 8548c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Prowise"), 8558c2ecf20Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "PT301"), 8568c2ecf20Sopenharmony_ci }, 8578c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 8588c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 8598c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 8608c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 8618c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 8628c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 8638c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 8648c2ecf20Sopenharmony_ci }, 8658c2ecf20Sopenharmony_ci { 8668c2ecf20Sopenharmony_ci /* Teclast X89 */ 8678c2ecf20Sopenharmony_ci .matches = { 8688c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), 8698c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "tPAD"), 8708c2ecf20Sopenharmony_ci }, 8718c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN3_MAP | 8728c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | 8738c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 8748c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_1P0 | 8758c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 8768c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 8778c2ecf20Sopenharmony_ci }, 8788c2ecf20Sopenharmony_ci { /* Toshiba Satellite Click Mini L9W-B */ 8798c2ecf20Sopenharmony_ci .matches = { 8808c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 8818c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"), 8828c2ecf20Sopenharmony_ci }, 8838c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 8848c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 8858c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 8868c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 8878c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 8888c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 8898c2ecf20Sopenharmony_ci }, 8908c2ecf20Sopenharmony_ci { /* Toshiba Encore WT8-A */ 8918c2ecf20Sopenharmony_ci .matches = { 8928c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 8938c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT8-A"), 8948c2ecf20Sopenharmony_ci }, 8958c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 8968c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 8978c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 8988c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 8998c2ecf20Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 9008c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 9018c2ecf20Sopenharmony_ci }, 9028c2ecf20Sopenharmony_ci { /* Toshiba Encore WT10-A */ 9038c2ecf20Sopenharmony_ci .matches = { 9048c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 9058c2ecf20Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT10-A-103"), 9068c2ecf20Sopenharmony_ci }, 9078c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 9088c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | 9098c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 9108c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 9118c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF2 | 9128c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 9138c2ecf20Sopenharmony_ci }, 9148c2ecf20Sopenharmony_ci { /* Voyo Winpad A15 */ 9158c2ecf20Sopenharmony_ci .matches = { 9168c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 9178c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 9188c2ecf20Sopenharmony_ci /* Above strings are too generic, also match on BIOS date */ 9198c2ecf20Sopenharmony_ci DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"), 9208c2ecf20Sopenharmony_ci }, 9218c2ecf20Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 9228c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 9238c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 9248c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 9258c2ecf20Sopenharmony_ci BYT_RT5640_DIFF_MIC | 9268c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN), 9278c2ecf20Sopenharmony_ci }, 9288c2ecf20Sopenharmony_ci { /* Catch-all for generic Insyde tablets, must be last */ 9298c2ecf20Sopenharmony_ci .matches = { 9308c2ecf20Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 9318c2ecf20Sopenharmony_ci }, 9328c2ecf20Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 9338c2ecf20Sopenharmony_ci BYT_RT5640_MCLK_EN | 9348c2ecf20Sopenharmony_ci BYT_RT5640_SSP0_AIF1), 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci }, 9378c2ecf20Sopenharmony_ci {} 9388c2ecf20Sopenharmony_ci}; 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci/* 9418c2ecf20Sopenharmony_ci * Note this MUST be called before snd_soc_register_card(), so that the props 9428c2ecf20Sopenharmony_ci * are in place before the codec component driver's probe function parses them. 9438c2ecf20Sopenharmony_ci */ 9448c2ecf20Sopenharmony_cistatic int byt_rt5640_add_codec_device_props(const char *i2c_dev_name) 9458c2ecf20Sopenharmony_ci{ 9468c2ecf20Sopenharmony_ci struct property_entry props[MAX_NO_PROPS] = {}; 9478c2ecf20Sopenharmony_ci struct device *i2c_dev; 9488c2ecf20Sopenharmony_ci int ret, cnt = 0; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name); 9518c2ecf20Sopenharmony_ci if (!i2c_dev) 9528c2ecf20Sopenharmony_ci return -EPROBE_DEFER; 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { 9558c2ecf20Sopenharmony_ci case BYT_RT5640_DMIC1_MAP: 9568c2ecf20Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic1-data-pin", 9578c2ecf20Sopenharmony_ci RT5640_DMIC1_DATA_PIN_IN1P); 9588c2ecf20Sopenharmony_ci break; 9598c2ecf20Sopenharmony_ci case BYT_RT5640_DMIC2_MAP: 9608c2ecf20Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic2-data-pin", 9618c2ecf20Sopenharmony_ci RT5640_DMIC2_DATA_PIN_IN1N); 9628c2ecf20Sopenharmony_ci break; 9638c2ecf20Sopenharmony_ci case BYT_RT5640_IN1_MAP: 9648c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) 9658c2ecf20Sopenharmony_ci props[cnt++] = 9668c2ecf20Sopenharmony_ci PROPERTY_ENTRY_BOOL("realtek,in1-differential"); 9678c2ecf20Sopenharmony_ci break; 9688c2ecf20Sopenharmony_ci case BYT_RT5640_IN3_MAP: 9698c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) 9708c2ecf20Sopenharmony_ci props[cnt++] = 9718c2ecf20Sopenharmony_ci PROPERTY_ENTRY_BOOL("realtek,in3-differential"); 9728c2ecf20Sopenharmony_ci break; 9738c2ecf20Sopenharmony_ci } 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) { 9768c2ecf20Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_U32( 9778c2ecf20Sopenharmony_ci "realtek,jack-detect-source", 9788c2ecf20Sopenharmony_ci BYT_RT5640_JDSRC(byt_rt5640_quirk)); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_U32( 9818c2ecf20Sopenharmony_ci "realtek,over-current-threshold-microamp", 9828c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100); 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_U32( 9858c2ecf20Sopenharmony_ci "realtek,over-current-scale-factor", 9868c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF(byt_rt5640_quirk)); 9878c2ecf20Sopenharmony_ci } 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV) 9908c2ecf20Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted"); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci ret = device_add_properties(i2c_dev, props); 9938c2ecf20Sopenharmony_ci put_device(i2c_dev); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci return ret; 9968c2ecf20Sopenharmony_ci} 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_cistatic int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) 9998c2ecf20Sopenharmony_ci{ 10008c2ecf20Sopenharmony_ci struct snd_soc_card *card = runtime->card; 10018c2ecf20Sopenharmony_ci struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 10028c2ecf20Sopenharmony_ci struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; 10038c2ecf20Sopenharmony_ci const struct snd_soc_dapm_route *custom_map; 10048c2ecf20Sopenharmony_ci int num_routes; 10058c2ecf20Sopenharmony_ci int ret; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci card->dapm.idle_bias_off = true; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci /* Start with RC clk for jack-detect (we disable MCLK below) */ 10108c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) 10118c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT5640_GLB_CLK, 10128c2ecf20Sopenharmony_ci RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK); 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci rt5640_sel_asrc_clk_src(component, 10158c2ecf20Sopenharmony_ci RT5640_DA_STEREO_FILTER | 10168c2ecf20Sopenharmony_ci RT5640_DA_MONO_L_FILTER | 10178c2ecf20Sopenharmony_ci RT5640_DA_MONO_R_FILTER | 10188c2ecf20Sopenharmony_ci RT5640_AD_STEREO_FILTER | 10198c2ecf20Sopenharmony_ci RT5640_AD_MONO_L_FILTER | 10208c2ecf20Sopenharmony_ci RT5640_AD_MONO_R_FILTER, 10218c2ecf20Sopenharmony_ci RT5640_CLK_SEL_ASRC); 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci ret = snd_soc_add_card_controls(card, byt_rt5640_controls, 10248c2ecf20Sopenharmony_ci ARRAY_SIZE(byt_rt5640_controls)); 10258c2ecf20Sopenharmony_ci if (ret) { 10268c2ecf20Sopenharmony_ci dev_err(card->dev, "unable to add card controls\n"); 10278c2ecf20Sopenharmony_ci return ret; 10288c2ecf20Sopenharmony_ci } 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { 10318c2ecf20Sopenharmony_ci case BYT_RT5640_IN1_MAP: 10328c2ecf20Sopenharmony_ci custom_map = byt_rt5640_intmic_in1_map; 10338c2ecf20Sopenharmony_ci num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map); 10348c2ecf20Sopenharmony_ci break; 10358c2ecf20Sopenharmony_ci case BYT_RT5640_IN3_MAP: 10368c2ecf20Sopenharmony_ci custom_map = byt_rt5640_intmic_in3_map; 10378c2ecf20Sopenharmony_ci num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map); 10388c2ecf20Sopenharmony_ci break; 10398c2ecf20Sopenharmony_ci case BYT_RT5640_DMIC2_MAP: 10408c2ecf20Sopenharmony_ci custom_map = byt_rt5640_intmic_dmic2_map; 10418c2ecf20Sopenharmony_ci num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map); 10428c2ecf20Sopenharmony_ci break; 10438c2ecf20Sopenharmony_ci default: 10448c2ecf20Sopenharmony_ci custom_map = byt_rt5640_intmic_dmic1_map; 10458c2ecf20Sopenharmony_ci num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); 10498c2ecf20Sopenharmony_ci if (ret) 10508c2ecf20Sopenharmony_ci return ret; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { 10538c2ecf20Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 10548c2ecf20Sopenharmony_ci byt_rt5640_ssp2_aif2_map, 10558c2ecf20Sopenharmony_ci ARRAY_SIZE(byt_rt5640_ssp2_aif2_map)); 10568c2ecf20Sopenharmony_ci } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { 10578c2ecf20Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 10588c2ecf20Sopenharmony_ci byt_rt5640_ssp0_aif1_map, 10598c2ecf20Sopenharmony_ci ARRAY_SIZE(byt_rt5640_ssp0_aif1_map)); 10608c2ecf20Sopenharmony_ci } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) { 10618c2ecf20Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 10628c2ecf20Sopenharmony_ci byt_rt5640_ssp0_aif2_map, 10638c2ecf20Sopenharmony_ci ARRAY_SIZE(byt_rt5640_ssp0_aif2_map)); 10648c2ecf20Sopenharmony_ci } else { 10658c2ecf20Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 10668c2ecf20Sopenharmony_ci byt_rt5640_ssp2_aif1_map, 10678c2ecf20Sopenharmony_ci ARRAY_SIZE(byt_rt5640_ssp2_aif1_map)); 10688c2ecf20Sopenharmony_ci } 10698c2ecf20Sopenharmony_ci if (ret) 10708c2ecf20Sopenharmony_ci return ret; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { 10738c2ecf20Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 10748c2ecf20Sopenharmony_ci byt_rt5640_mono_spk_map, 10758c2ecf20Sopenharmony_ci ARRAY_SIZE(byt_rt5640_mono_spk_map)); 10768c2ecf20Sopenharmony_ci } else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) { 10778c2ecf20Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 10788c2ecf20Sopenharmony_ci byt_rt5640_stereo_spk_map, 10798c2ecf20Sopenharmony_ci ARRAY_SIZE(byt_rt5640_stereo_spk_map)); 10808c2ecf20Sopenharmony_ci } 10818c2ecf20Sopenharmony_ci if (ret) 10828c2ecf20Sopenharmony_ci return ret; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { 10858c2ecf20Sopenharmony_ci /* 10868c2ecf20Sopenharmony_ci * The firmware might enable the clock at 10878c2ecf20Sopenharmony_ci * boot (this information may or may not 10888c2ecf20Sopenharmony_ci * be reflected in the enable clock register). 10898c2ecf20Sopenharmony_ci * To change the rate we must disable the clock 10908c2ecf20Sopenharmony_ci * first to cover these cases. Due to common 10918c2ecf20Sopenharmony_ci * clock framework restrictions that do not allow 10928c2ecf20Sopenharmony_ci * to disable a clock that has not been enabled, 10938c2ecf20Sopenharmony_ci * we need to enable the clock first. 10948c2ecf20Sopenharmony_ci */ 10958c2ecf20Sopenharmony_ci ret = clk_prepare_enable(priv->mclk); 10968c2ecf20Sopenharmony_ci if (!ret) 10978c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->mclk); 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) 11008c2ecf20Sopenharmony_ci ret = clk_set_rate(priv->mclk, 25000000); 11018c2ecf20Sopenharmony_ci else 11028c2ecf20Sopenharmony_ci ret = clk_set_rate(priv->mclk, 19200000); 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci if (ret) { 11058c2ecf20Sopenharmony_ci dev_err(card->dev, "unable to set MCLK rate\n"); 11068c2ecf20Sopenharmony_ci return ret; 11078c2ecf20Sopenharmony_ci } 11088c2ecf20Sopenharmony_ci } 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) { 11118c2ecf20Sopenharmony_ci ret = snd_soc_card_jack_new(card, "Headset", 11128c2ecf20Sopenharmony_ci SND_JACK_HEADSET | SND_JACK_BTN_0, 11138c2ecf20Sopenharmony_ci &priv->jack, rt5640_pins, 11148c2ecf20Sopenharmony_ci ARRAY_SIZE(rt5640_pins)); 11158c2ecf20Sopenharmony_ci if (ret) { 11168c2ecf20Sopenharmony_ci dev_err(card->dev, "Jack creation failed %d\n", ret); 11178c2ecf20Sopenharmony_ci return ret; 11188c2ecf20Sopenharmony_ci } 11198c2ecf20Sopenharmony_ci snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, 11208c2ecf20Sopenharmony_ci KEY_PLAYPAUSE); 11218c2ecf20Sopenharmony_ci snd_soc_component_set_jack(component, &priv->jack, NULL); 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci return 0; 11258c2ecf20Sopenharmony_ci} 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_cistatic int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, 11288c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params) 11298c2ecf20Sopenharmony_ci{ 11308c2ecf20Sopenharmony_ci struct snd_interval *rate = hw_param_interval(params, 11318c2ecf20Sopenharmony_ci SNDRV_PCM_HW_PARAM_RATE); 11328c2ecf20Sopenharmony_ci struct snd_interval *channels = hw_param_interval(params, 11338c2ecf20Sopenharmony_ci SNDRV_PCM_HW_PARAM_CHANNELS); 11348c2ecf20Sopenharmony_ci int ret, bits; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci /* The DSP will covert the FE rate to 48k, stereo */ 11378c2ecf20Sopenharmony_ci rate->min = rate->max = 48000; 11388c2ecf20Sopenharmony_ci channels->min = channels->max = 2; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || 11418c2ecf20Sopenharmony_ci (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { 11428c2ecf20Sopenharmony_ci /* set SSP0 to 16-bit */ 11438c2ecf20Sopenharmony_ci params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); 11448c2ecf20Sopenharmony_ci bits = 16; 11458c2ecf20Sopenharmony_ci } else { 11468c2ecf20Sopenharmony_ci /* set SSP2 to 24-bit */ 11478c2ecf20Sopenharmony_ci params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); 11488c2ecf20Sopenharmony_ci bits = 24; 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci /* 11528c2ecf20Sopenharmony_ci * Default mode for SSP configuration is TDM 4 slot, override config 11538c2ecf20Sopenharmony_ci * with explicit setting to I2S 2ch. The word length is set with 11548c2ecf20Sopenharmony_ci * dai_set_tdm_slot() since there is no other API exposed 11558c2ecf20Sopenharmony_ci */ 11568c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), 11578c2ecf20Sopenharmony_ci SND_SOC_DAIFMT_I2S | 11588c2ecf20Sopenharmony_ci SND_SOC_DAIFMT_NB_NF | 11598c2ecf20Sopenharmony_ci SND_SOC_DAIFMT_CBS_CFS); 11608c2ecf20Sopenharmony_ci if (ret < 0) { 11618c2ecf20Sopenharmony_ci dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); 11628c2ecf20Sopenharmony_ci return ret; 11638c2ecf20Sopenharmony_ci } 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); 11668c2ecf20Sopenharmony_ci if (ret < 0) { 11678c2ecf20Sopenharmony_ci dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); 11688c2ecf20Sopenharmony_ci return ret; 11698c2ecf20Sopenharmony_ci } 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci return 0; 11728c2ecf20Sopenharmony_ci} 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_cistatic int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream) 11758c2ecf20Sopenharmony_ci{ 11768c2ecf20Sopenharmony_ci return snd_pcm_hw_constraint_single(substream->runtime, 11778c2ecf20Sopenharmony_ci SNDRV_PCM_HW_PARAM_RATE, 48000); 11788c2ecf20Sopenharmony_ci} 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_cistatic const struct snd_soc_ops byt_rt5640_aif1_ops = { 11818c2ecf20Sopenharmony_ci .startup = byt_rt5640_aif1_startup, 11828c2ecf20Sopenharmony_ci}; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_cistatic const struct snd_soc_ops byt_rt5640_be_ssp2_ops = { 11858c2ecf20Sopenharmony_ci .hw_params = byt_rt5640_aif1_hw_params, 11868c2ecf20Sopenharmony_ci}; 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(dummy, 11898c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY())); 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(media, 11928c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(deepbuffer, 11958c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(ssp2_port, 11988c2ecf20Sopenharmony_ci /* overwritten for ssp0 routing */ 11998c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); 12008c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(ssp2_codec, 12018c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CODEC( 12028c2ecf20Sopenharmony_ci /* overwritten with HID */ "i2c-10EC5640:00", 12038c2ecf20Sopenharmony_ci /* changed w/ quirk */ "rt5640-aif1"))); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(platform, 12068c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_cistatic struct snd_soc_dai_link byt_rt5640_dais[] = { 12098c2ecf20Sopenharmony_ci [MERR_DPCM_AUDIO] = { 12108c2ecf20Sopenharmony_ci .name = "Baytrail Audio Port", 12118c2ecf20Sopenharmony_ci .stream_name = "Baytrail Audio", 12128c2ecf20Sopenharmony_ci .nonatomic = true, 12138c2ecf20Sopenharmony_ci .dynamic = 1, 12148c2ecf20Sopenharmony_ci .dpcm_playback = 1, 12158c2ecf20Sopenharmony_ci .dpcm_capture = 1, 12168c2ecf20Sopenharmony_ci .ops = &byt_rt5640_aif1_ops, 12178c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(media, dummy, platform), 12188c2ecf20Sopenharmony_ci }, 12198c2ecf20Sopenharmony_ci [MERR_DPCM_DEEP_BUFFER] = { 12208c2ecf20Sopenharmony_ci .name = "Deep-Buffer Audio Port", 12218c2ecf20Sopenharmony_ci .stream_name = "Deep-Buffer Audio", 12228c2ecf20Sopenharmony_ci .nonatomic = true, 12238c2ecf20Sopenharmony_ci .dynamic = 1, 12248c2ecf20Sopenharmony_ci .dpcm_playback = 1, 12258c2ecf20Sopenharmony_ci .ops = &byt_rt5640_aif1_ops, 12268c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), 12278c2ecf20Sopenharmony_ci }, 12288c2ecf20Sopenharmony_ci /* back ends */ 12298c2ecf20Sopenharmony_ci { 12308c2ecf20Sopenharmony_ci .name = "SSP2-Codec", 12318c2ecf20Sopenharmony_ci .id = 0, 12328c2ecf20Sopenharmony_ci .no_pcm = 1, 12338c2ecf20Sopenharmony_ci .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 12348c2ecf20Sopenharmony_ci | SND_SOC_DAIFMT_CBS_CFS, 12358c2ecf20Sopenharmony_ci .be_hw_params_fixup = byt_rt5640_codec_fixup, 12368c2ecf20Sopenharmony_ci .nonatomic = true, 12378c2ecf20Sopenharmony_ci .dpcm_playback = 1, 12388c2ecf20Sopenharmony_ci .dpcm_capture = 1, 12398c2ecf20Sopenharmony_ci .init = byt_rt5640_init, 12408c2ecf20Sopenharmony_ci .ops = &byt_rt5640_be_ssp2_ops, 12418c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), 12428c2ecf20Sopenharmony_ci }, 12438c2ecf20Sopenharmony_ci}; 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci/* SoC card */ 12468c2ecf20Sopenharmony_cistatic char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN]; 12478c2ecf20Sopenharmony_ci#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) 12488c2ecf20Sopenharmony_cistatic char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */ 12498c2ecf20Sopenharmony_ci#endif 12508c2ecf20Sopenharmony_cistatic char byt_rt5640_components[32]; /* = "cfg-spk:* cfg-mic:*" */ 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_cistatic int byt_rt5640_suspend(struct snd_soc_card *card) 12538c2ecf20Sopenharmony_ci{ 12548c2ecf20Sopenharmony_ci struct snd_soc_component *component; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) 12578c2ecf20Sopenharmony_ci return 0; 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci for_each_card_components(card, component) { 12608c2ecf20Sopenharmony_ci if (!strcmp(component->name, byt_rt5640_codec_name)) { 12618c2ecf20Sopenharmony_ci dev_dbg(component->dev, "disabling jack detect before suspend\n"); 12628c2ecf20Sopenharmony_ci snd_soc_component_set_jack(component, NULL, NULL); 12638c2ecf20Sopenharmony_ci break; 12648c2ecf20Sopenharmony_ci } 12658c2ecf20Sopenharmony_ci } 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci return 0; 12688c2ecf20Sopenharmony_ci} 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_cistatic int byt_rt5640_resume(struct snd_soc_card *card) 12718c2ecf20Sopenharmony_ci{ 12728c2ecf20Sopenharmony_ci struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 12738c2ecf20Sopenharmony_ci struct snd_soc_component *component; 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) 12768c2ecf20Sopenharmony_ci return 0; 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci for_each_card_components(card, component) { 12798c2ecf20Sopenharmony_ci if (!strcmp(component->name, byt_rt5640_codec_name)) { 12808c2ecf20Sopenharmony_ci dev_dbg(component->dev, "re-enabling jack detect after resume\n"); 12818c2ecf20Sopenharmony_ci snd_soc_component_set_jack(component, &priv->jack, NULL); 12828c2ecf20Sopenharmony_ci break; 12838c2ecf20Sopenharmony_ci } 12848c2ecf20Sopenharmony_ci } 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci return 0; 12878c2ecf20Sopenharmony_ci} 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) 12908c2ecf20Sopenharmony_ci/* use space before codec name to simplify card ID, and simplify driver name */ 12918c2ecf20Sopenharmony_ci#define CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */ 12928c2ecf20Sopenharmony_ci#define DRIVER_NAME "SOF" 12938c2ecf20Sopenharmony_ci#else 12948c2ecf20Sopenharmony_ci#define CARD_NAME "bytcr-rt5640" 12958c2ecf20Sopenharmony_ci#define DRIVER_NAME NULL /* card name will be used for driver name */ 12968c2ecf20Sopenharmony_ci#endif 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_cistatic struct snd_soc_card byt_rt5640_card = { 12998c2ecf20Sopenharmony_ci .name = CARD_NAME, 13008c2ecf20Sopenharmony_ci .driver_name = DRIVER_NAME, 13018c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 13028c2ecf20Sopenharmony_ci .dai_link = byt_rt5640_dais, 13038c2ecf20Sopenharmony_ci .num_links = ARRAY_SIZE(byt_rt5640_dais), 13048c2ecf20Sopenharmony_ci .dapm_widgets = byt_rt5640_widgets, 13058c2ecf20Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets), 13068c2ecf20Sopenharmony_ci .dapm_routes = byt_rt5640_audio_map, 13078c2ecf20Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map), 13088c2ecf20Sopenharmony_ci .fully_routed = true, 13098c2ecf20Sopenharmony_ci .suspend_pre = byt_rt5640_suspend, 13108c2ecf20Sopenharmony_ci .resume_post = byt_rt5640_resume, 13118c2ecf20Sopenharmony_ci}; 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_cistruct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ 13148c2ecf20Sopenharmony_ci u64 aif_value; /* 1: AIF1, 2: AIF2 */ 13158c2ecf20Sopenharmony_ci u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */ 13168c2ecf20Sopenharmony_ci}; 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_cistatic int snd_byt_rt5640_mc_probe(struct platform_device *pdev) 13198c2ecf20Sopenharmony_ci{ 13208c2ecf20Sopenharmony_ci static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" }; 13218c2ecf20Sopenharmony_ci __maybe_unused const char *spk_type; 13228c2ecf20Sopenharmony_ci const struct dmi_system_id *dmi_id; 13238c2ecf20Sopenharmony_ci struct byt_rt5640_private *priv; 13248c2ecf20Sopenharmony_ci struct snd_soc_acpi_mach *mach; 13258c2ecf20Sopenharmony_ci const char *platform_name; 13268c2ecf20Sopenharmony_ci struct acpi_device *adev; 13278c2ecf20Sopenharmony_ci int ret_val = 0; 13288c2ecf20Sopenharmony_ci int dai_index = 0; 13298c2ecf20Sopenharmony_ci int i, cfg_spk; 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci is_bytcr = false; 13328c2ecf20Sopenharmony_ci priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 13338c2ecf20Sopenharmony_ci if (!priv) 13348c2ecf20Sopenharmony_ci return -ENOMEM; 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci /* register the soc card */ 13378c2ecf20Sopenharmony_ci byt_rt5640_card.dev = &pdev->dev; 13388c2ecf20Sopenharmony_ci mach = byt_rt5640_card.dev->platform_data; 13398c2ecf20Sopenharmony_ci snd_soc_card_set_drvdata(&byt_rt5640_card, priv); 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci /* fix index of codec dai */ 13428c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) { 13438c2ecf20Sopenharmony_ci if (!strcmp(byt_rt5640_dais[i].codecs->name, 13448c2ecf20Sopenharmony_ci "i2c-10EC5640:00")) { 13458c2ecf20Sopenharmony_ci dai_index = i; 13468c2ecf20Sopenharmony_ci break; 13478c2ecf20Sopenharmony_ci } 13488c2ecf20Sopenharmony_ci } 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci /* fixup codec name based on HID */ 13518c2ecf20Sopenharmony_ci adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1); 13528c2ecf20Sopenharmony_ci if (adev) { 13538c2ecf20Sopenharmony_ci snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name), 13548c2ecf20Sopenharmony_ci "i2c-%s", acpi_dev_name(adev)); 13558c2ecf20Sopenharmony_ci put_device(&adev->dev); 13568c2ecf20Sopenharmony_ci byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name; 13578c2ecf20Sopenharmony_ci } 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci /* 13608c2ecf20Sopenharmony_ci * swap SSP0 if bytcr is detected 13618c2ecf20Sopenharmony_ci * (will be overridden if DMI quirk is detected) 13628c2ecf20Sopenharmony_ci */ 13638c2ecf20Sopenharmony_ci if (soc_intel_is_byt()) { 13648c2ecf20Sopenharmony_ci if (mach->mach_params.acpi_ipc_irq_index == 0) 13658c2ecf20Sopenharmony_ci is_bytcr = true; 13668c2ecf20Sopenharmony_ci } 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci if (is_bytcr) { 13698c2ecf20Sopenharmony_ci /* 13708c2ecf20Sopenharmony_ci * Baytrail CR platforms may have CHAN package in BIOS, try 13718c2ecf20Sopenharmony_ci * to find relevant routing quirk based as done on Windows 13728c2ecf20Sopenharmony_ci * platforms. We have to read the information directly from the 13738c2ecf20Sopenharmony_ci * BIOS, at this stage the card is not created and the links 13748c2ecf20Sopenharmony_ci * with the codec driver/pdata are non-existent 13758c2ecf20Sopenharmony_ci */ 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci struct acpi_chan_package chan_package; 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci /* format specified: 2 64-bit integers */ 13808c2ecf20Sopenharmony_ci struct acpi_buffer format = {sizeof("NN"), "NN"}; 13818c2ecf20Sopenharmony_ci struct acpi_buffer state = {0, NULL}; 13828c2ecf20Sopenharmony_ci struct snd_soc_acpi_package_context pkg_ctx; 13838c2ecf20Sopenharmony_ci bool pkg_found = false; 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci state.length = sizeof(chan_package); 13868c2ecf20Sopenharmony_ci state.pointer = &chan_package; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci pkg_ctx.name = "CHAN"; 13898c2ecf20Sopenharmony_ci pkg_ctx.length = 2; 13908c2ecf20Sopenharmony_ci pkg_ctx.format = &format; 13918c2ecf20Sopenharmony_ci pkg_ctx.state = &state; 13928c2ecf20Sopenharmony_ci pkg_ctx.data_valid = false; 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci pkg_found = snd_soc_acpi_find_package_from_hid(mach->id, 13958c2ecf20Sopenharmony_ci &pkg_ctx); 13968c2ecf20Sopenharmony_ci if (pkg_found) { 13978c2ecf20Sopenharmony_ci if (chan_package.aif_value == 1) { 13988c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n"); 13998c2ecf20Sopenharmony_ci byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1; 14008c2ecf20Sopenharmony_ci } else if (chan_package.aif_value == 2) { 14018c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n"); 14028c2ecf20Sopenharmony_ci byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; 14038c2ecf20Sopenharmony_ci } else { 14048c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n"); 14058c2ecf20Sopenharmony_ci pkg_found = false; 14068c2ecf20Sopenharmony_ci } 14078c2ecf20Sopenharmony_ci } 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci if (!pkg_found) { 14108c2ecf20Sopenharmony_ci /* no BIOS indications, assume SSP0-AIF2 connection */ 14118c2ecf20Sopenharmony_ci byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; 14128c2ecf20Sopenharmony_ci } 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci /* change defaults for Baytrail-CR capture */ 14158c2ecf20Sopenharmony_ci byt_rt5640_quirk |= BYTCR_INPUT_DEFAULTS; 14168c2ecf20Sopenharmony_ci } else { 14178c2ecf20Sopenharmony_ci byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP | 14188c2ecf20Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 14198c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 14208c2ecf20Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75; 14218c2ecf20Sopenharmony_ci } 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci /* check quirks before creating card */ 14248c2ecf20Sopenharmony_ci dmi_id = dmi_first_match(byt_rt5640_quirk_table); 14258c2ecf20Sopenharmony_ci if (dmi_id) 14268c2ecf20Sopenharmony_ci byt_rt5640_quirk = (unsigned long)dmi_id->driver_data; 14278c2ecf20Sopenharmony_ci if (quirk_override != -1) { 14288c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n", 14298c2ecf20Sopenharmony_ci byt_rt5640_quirk, quirk_override); 14308c2ecf20Sopenharmony_ci byt_rt5640_quirk = quirk_override; 14318c2ecf20Sopenharmony_ci } 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci /* Must be called before register_card, also see declaration comment. */ 14348c2ecf20Sopenharmony_ci ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name); 14358c2ecf20Sopenharmony_ci if (ret_val) 14368c2ecf20Sopenharmony_ci return ret_val; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci log_quirks(&pdev->dev); 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) || 14418c2ecf20Sopenharmony_ci (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) 14428c2ecf20Sopenharmony_ci byt_rt5640_dais[dai_index].codecs->dai_name = "rt5640-aif2"; 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || 14458c2ecf20Sopenharmony_ci (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) 14468c2ecf20Sopenharmony_ci byt_rt5640_dais[dai_index].cpus->dai_name = "ssp0-port"; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { 14498c2ecf20Sopenharmony_ci priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); 14508c2ecf20Sopenharmony_ci if (IS_ERR(priv->mclk)) { 14518c2ecf20Sopenharmony_ci ret_val = PTR_ERR(priv->mclk); 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 14548c2ecf20Sopenharmony_ci "Failed to get MCLK from pmc_plt_clk_3: %d\n", 14558c2ecf20Sopenharmony_ci ret_val); 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci /* 14588c2ecf20Sopenharmony_ci * Fall back to bit clock usage for -ENOENT (clock not 14598c2ecf20Sopenharmony_ci * available likely due to missing dependencies), bail 14608c2ecf20Sopenharmony_ci * for all other errors, including -EPROBE_DEFER 14618c2ecf20Sopenharmony_ci */ 14628c2ecf20Sopenharmony_ci if (ret_val != -ENOENT) 14638c2ecf20Sopenharmony_ci return ret_val; 14648c2ecf20Sopenharmony_ci byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN; 14658c2ecf20Sopenharmony_ci } 14668c2ecf20Sopenharmony_ci } 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) { 14698c2ecf20Sopenharmony_ci cfg_spk = 0; 14708c2ecf20Sopenharmony_ci spk_type = "none"; 14718c2ecf20Sopenharmony_ci } else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { 14728c2ecf20Sopenharmony_ci cfg_spk = 1; 14738c2ecf20Sopenharmony_ci spk_type = "mono"; 14748c2ecf20Sopenharmony_ci } else { 14758c2ecf20Sopenharmony_ci cfg_spk = 2; 14768c2ecf20Sopenharmony_ci spk_type = "stereo"; 14778c2ecf20Sopenharmony_ci } 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci snprintf(byt_rt5640_components, sizeof(byt_rt5640_components), 14808c2ecf20Sopenharmony_ci "cfg-spk:%d cfg-mic:%s", cfg_spk, 14818c2ecf20Sopenharmony_ci map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); 14828c2ecf20Sopenharmony_ci byt_rt5640_card.components = byt_rt5640_components; 14838c2ecf20Sopenharmony_ci#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) 14848c2ecf20Sopenharmony_ci snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name), 14858c2ecf20Sopenharmony_ci "bytcr-rt5640-%s-spk-%s-mic", spk_type, 14868c2ecf20Sopenharmony_ci map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); 14878c2ecf20Sopenharmony_ci byt_rt5640_card.long_name = byt_rt5640_long_name; 14888c2ecf20Sopenharmony_ci#endif 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci /* override plaform name, if required */ 14918c2ecf20Sopenharmony_ci platform_name = mach->mach_params.platform; 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card, 14948c2ecf20Sopenharmony_ci platform_name); 14958c2ecf20Sopenharmony_ci if (ret_val) 14968c2ecf20Sopenharmony_ci return ret_val; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card); 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci if (ret_val) { 15018c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n", 15028c2ecf20Sopenharmony_ci ret_val); 15038c2ecf20Sopenharmony_ci return ret_val; 15048c2ecf20Sopenharmony_ci } 15058c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, &byt_rt5640_card); 15068c2ecf20Sopenharmony_ci return ret_val; 15078c2ecf20Sopenharmony_ci} 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_cistatic struct platform_driver snd_byt_rt5640_mc_driver = { 15108c2ecf20Sopenharmony_ci .driver = { 15118c2ecf20Sopenharmony_ci .name = "bytcr_rt5640", 15128c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL) 15138c2ecf20Sopenharmony_ci .pm = &snd_soc_pm_ops, 15148c2ecf20Sopenharmony_ci#endif 15158c2ecf20Sopenharmony_ci }, 15168c2ecf20Sopenharmony_ci .probe = snd_byt_rt5640_mc_probe, 15178c2ecf20Sopenharmony_ci}; 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_cimodule_platform_driver(snd_byt_rt5640_mc_driver); 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver"); 15228c2ecf20Sopenharmony_ciMODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>"); 15238c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 15248c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:bytcr_rt5640"); 1525