162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * byt_cr_dpcm_rt5640.c - ASoc Machine driver for Intel Byt CR platform 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2014 Intel Corp 662306a36Sopenharmony_ci * Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com> 762306a36Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/i2c.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/moduleparam.h> 1662306a36Sopenharmony_ci#include <linux/platform_device.h> 1762306a36Sopenharmony_ci#include <linux/acpi.h> 1862306a36Sopenharmony_ci#include <linux/clk.h> 1962306a36Sopenharmony_ci#include <linux/device.h> 2062306a36Sopenharmony_ci#include <linux/dmi.h> 2162306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 2262306a36Sopenharmony_ci#include <linux/gpio/machine.h> 2362306a36Sopenharmony_ci#include <linux/input.h> 2462306a36Sopenharmony_ci#include <linux/slab.h> 2562306a36Sopenharmony_ci#include <sound/pcm.h> 2662306a36Sopenharmony_ci#include <sound/pcm_params.h> 2762306a36Sopenharmony_ci#include <sound/soc.h> 2862306a36Sopenharmony_ci#include <sound/jack.h> 2962306a36Sopenharmony_ci#include <sound/soc-acpi.h> 3062306a36Sopenharmony_ci#include <dt-bindings/sound/rt5640.h> 3162306a36Sopenharmony_ci#include "../../codecs/rt5640.h" 3262306a36Sopenharmony_ci#include "../atom/sst-atom-controls.h" 3362306a36Sopenharmony_ci#include "../common/soc-intel-quirks.h" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cienum { 3662306a36Sopenharmony_ci BYT_RT5640_DMIC1_MAP, 3762306a36Sopenharmony_ci BYT_RT5640_DMIC2_MAP, 3862306a36Sopenharmony_ci BYT_RT5640_IN1_MAP, 3962306a36Sopenharmony_ci BYT_RT5640_IN3_MAP, 4062306a36Sopenharmony_ci BYT_RT5640_NO_INTERNAL_MIC_MAP, 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define RT5640_JD_SRC_EXT_GPIO 0x0f 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cienum { 4662306a36Sopenharmony_ci BYT_RT5640_JD_SRC_GPIO1 = (RT5640_JD_SRC_GPIO1 << 4), 4762306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P = (RT5640_JD_SRC_JD1_IN4P << 4), 4862306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N = (RT5640_JD_SRC_JD2_IN4N << 4), 4962306a36Sopenharmony_ci BYT_RT5640_JD_SRC_GPIO2 = (RT5640_JD_SRC_GPIO2 << 4), 5062306a36Sopenharmony_ci BYT_RT5640_JD_SRC_GPIO3 = (RT5640_JD_SRC_GPIO3 << 4), 5162306a36Sopenharmony_ci BYT_RT5640_JD_SRC_GPIO4 = (RT5640_JD_SRC_GPIO4 << 4), 5262306a36Sopenharmony_ci BYT_RT5640_JD_SRC_EXT_GPIO = (RT5640_JD_SRC_EXT_GPIO << 4) 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cienum { 5662306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_600UA = (6 << 8), 5762306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA = (15 << 8), 5862306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA = (20 << 8), 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cienum { 6262306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P5 = (RT5640_OVCD_SF_0P5 << 13), 6362306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 = (RT5640_OVCD_SF_0P75 << 13), 6462306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_1P0 = (RT5640_OVCD_SF_1P0 << 13), 6562306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_1P5 = (RT5640_OVCD_SF_1P5 << 13), 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#define BYT_RT5640_MAP(quirk) ((quirk) & GENMASK(3, 0)) 6962306a36Sopenharmony_ci#define BYT_RT5640_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4) 7062306a36Sopenharmony_ci#define BYT_RT5640_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8) 7162306a36Sopenharmony_ci#define BYT_RT5640_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13) 7262306a36Sopenharmony_ci#define BYT_RT5640_JD_NOT_INV BIT(16) 7362306a36Sopenharmony_ci#define BYT_RT5640_MONO_SPEAKER BIT(17) 7462306a36Sopenharmony_ci#define BYT_RT5640_DIFF_MIC BIT(18) /* default is single-ended */ 7562306a36Sopenharmony_ci#define BYT_RT5640_SSP2_AIF2 BIT(19) /* default is using AIF1 */ 7662306a36Sopenharmony_ci#define BYT_RT5640_SSP0_AIF1 BIT(20) 7762306a36Sopenharmony_ci#define BYT_RT5640_SSP0_AIF2 BIT(21) 7862306a36Sopenharmony_ci#define BYT_RT5640_MCLK_EN BIT(22) 7962306a36Sopenharmony_ci#define BYT_RT5640_MCLK_25MHZ BIT(23) 8062306a36Sopenharmony_ci#define BYT_RT5640_NO_SPEAKERS BIT(24) 8162306a36Sopenharmony_ci#define BYT_RT5640_LINEOUT BIT(25) 8262306a36Sopenharmony_ci#define BYT_RT5640_LINEOUT_AS_HP2 BIT(26) 8362306a36Sopenharmony_ci#define BYT_RT5640_HSMIC2_ON_IN1 BIT(27) 8462306a36Sopenharmony_ci#define BYT_RT5640_JD_HP_ELITEP_1000G2 BIT(28) 8562306a36Sopenharmony_ci#define BYT_RT5640_USE_AMCR0F28 BIT(29) 8662306a36Sopenharmony_ci#define BYT_RT5640_SWAPPED_SPEAKERS BIT(30) 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define BYTCR_INPUT_DEFAULTS \ 8962306a36Sopenharmony_ci (BYT_RT5640_IN3_MAP | \ 9062306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | \ 9162306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | \ 9262306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | \ 9362306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC) 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci/* in-diff or dmic-pin + jdsrc + ovcd-th + -sf + jd-inv + terminating entry */ 9662306a36Sopenharmony_ci#define MAX_NO_PROPS 6 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistruct byt_rt5640_private { 9962306a36Sopenharmony_ci struct snd_soc_jack jack; 10062306a36Sopenharmony_ci struct snd_soc_jack jack2; 10162306a36Sopenharmony_ci struct rt5640_set_jack_data jack_data; 10262306a36Sopenharmony_ci struct gpio_desc *hsmic_detect; 10362306a36Sopenharmony_ci struct clk *mclk; 10462306a36Sopenharmony_ci struct device *codec_dev; 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_cistatic bool is_bytcr; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN; 10962306a36Sopenharmony_cistatic int quirk_override = -1; 11062306a36Sopenharmony_cimodule_param_named(quirk, quirk_override, int, 0444); 11162306a36Sopenharmony_ciMODULE_PARM_DESC(quirk, "Board-specific quirk override"); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic void log_quirks(struct device *dev) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci int map; 11662306a36Sopenharmony_ci bool has_mclk = false; 11762306a36Sopenharmony_ci bool has_ssp0 = false; 11862306a36Sopenharmony_ci bool has_ssp0_aif1 = false; 11962306a36Sopenharmony_ci bool has_ssp0_aif2 = false; 12062306a36Sopenharmony_ci bool has_ssp2_aif2 = false; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci map = BYT_RT5640_MAP(byt_rt5640_quirk); 12362306a36Sopenharmony_ci switch (map) { 12462306a36Sopenharmony_ci case BYT_RT5640_DMIC1_MAP: 12562306a36Sopenharmony_ci dev_info(dev, "quirk DMIC1_MAP enabled\n"); 12662306a36Sopenharmony_ci break; 12762306a36Sopenharmony_ci case BYT_RT5640_DMIC2_MAP: 12862306a36Sopenharmony_ci dev_info(dev, "quirk DMIC2_MAP enabled\n"); 12962306a36Sopenharmony_ci break; 13062306a36Sopenharmony_ci case BYT_RT5640_IN1_MAP: 13162306a36Sopenharmony_ci dev_info(dev, "quirk IN1_MAP enabled\n"); 13262306a36Sopenharmony_ci break; 13362306a36Sopenharmony_ci case BYT_RT5640_IN3_MAP: 13462306a36Sopenharmony_ci dev_info(dev, "quirk IN3_MAP enabled\n"); 13562306a36Sopenharmony_ci break; 13662306a36Sopenharmony_ci case BYT_RT5640_NO_INTERNAL_MIC_MAP: 13762306a36Sopenharmony_ci dev_info(dev, "quirk NO_INTERNAL_MIC_MAP enabled\n"); 13862306a36Sopenharmony_ci break; 13962306a36Sopenharmony_ci default: 14062306a36Sopenharmony_ci dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map); 14162306a36Sopenharmony_ci break; 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) 14462306a36Sopenharmony_ci dev_info(dev, "quirk HSMIC2_ON_IN1 enabled\n"); 14562306a36Sopenharmony_ci if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) { 14662306a36Sopenharmony_ci dev_info(dev, "quirk realtek,jack-detect-source %ld\n", 14762306a36Sopenharmony_ci BYT_RT5640_JDSRC(byt_rt5640_quirk)); 14862306a36Sopenharmony_ci dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n", 14962306a36Sopenharmony_ci BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100); 15062306a36Sopenharmony_ci dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n", 15162306a36Sopenharmony_ci BYT_RT5640_OVCD_SF(byt_rt5640_quirk)); 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV) 15462306a36Sopenharmony_ci dev_info(dev, "quirk JD_NOT_INV enabled\n"); 15562306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) 15662306a36Sopenharmony_ci dev_info(dev, "quirk JD_HP_ELITEPAD_1000G2 enabled\n"); 15762306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) 15862306a36Sopenharmony_ci dev_info(dev, "quirk MONO_SPEAKER enabled\n"); 15962306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) 16062306a36Sopenharmony_ci dev_info(dev, "quirk NO_SPEAKERS enabled\n"); 16162306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_SWAPPED_SPEAKERS) 16262306a36Sopenharmony_ci dev_info(dev, "quirk SWAPPED_SPEAKERS enabled\n"); 16362306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) 16462306a36Sopenharmony_ci dev_info(dev, "quirk LINEOUT enabled\n"); 16562306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2) 16662306a36Sopenharmony_ci dev_info(dev, "quirk LINEOUT_AS_HP2 enabled\n"); 16762306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) 16862306a36Sopenharmony_ci dev_info(dev, "quirk DIFF_MIC enabled\n"); 16962306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { 17062306a36Sopenharmony_ci dev_info(dev, "quirk SSP0_AIF1 enabled\n"); 17162306a36Sopenharmony_ci has_ssp0 = true; 17262306a36Sopenharmony_ci has_ssp0_aif1 = true; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) { 17562306a36Sopenharmony_ci dev_info(dev, "quirk SSP0_AIF2 enabled\n"); 17662306a36Sopenharmony_ci has_ssp0 = true; 17762306a36Sopenharmony_ci has_ssp0_aif2 = true; 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { 18062306a36Sopenharmony_ci dev_info(dev, "quirk SSP2_AIF2 enabled\n"); 18162306a36Sopenharmony_ci has_ssp2_aif2 = true; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci if (is_bytcr && !has_ssp0) 18462306a36Sopenharmony_ci dev_err(dev, "Invalid routing, bytcr detected but no SSP0-based quirk, audio cannot work with SSP2 on bytcr\n"); 18562306a36Sopenharmony_ci if (has_ssp0_aif1 && has_ssp0_aif2) 18662306a36Sopenharmony_ci dev_err(dev, "Invalid routing, SSP0 cannot be connected to both AIF1 and AIF2\n"); 18762306a36Sopenharmony_ci if (has_ssp0 && has_ssp2_aif2) 18862306a36Sopenharmony_ci dev_err(dev, "Invalid routing, cannot have both SSP0 and SSP2 connected to codec\n"); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { 19162306a36Sopenharmony_ci dev_info(dev, "quirk MCLK_EN enabled\n"); 19262306a36Sopenharmony_ci has_mclk = true; 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) { 19562306a36Sopenharmony_ci if (has_mclk) 19662306a36Sopenharmony_ci dev_info(dev, "quirk MCLK_25MHZ enabled\n"); 19762306a36Sopenharmony_ci else 19862306a36Sopenharmony_ci dev_err(dev, "quirk MCLK_25MHZ enabled but quirk MCLK not selected, will be ignored\n"); 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic int byt_rt5640_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai, 20362306a36Sopenharmony_ci int rate) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci int ret; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* Configure the PLL before selecting it */ 20862306a36Sopenharmony_ci if (!(byt_rt5640_quirk & BYT_RT5640_MCLK_EN)) { 20962306a36Sopenharmony_ci /* use bitclock as PLL input */ 21062306a36Sopenharmony_ci if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || 21162306a36Sopenharmony_ci (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { 21262306a36Sopenharmony_ci /* 2x16 bit slots on SSP0 */ 21362306a36Sopenharmony_ci ret = snd_soc_dai_set_pll(codec_dai, 0, 21462306a36Sopenharmony_ci RT5640_PLL1_S_BCLK1, 21562306a36Sopenharmony_ci rate * 32, rate * 512); 21662306a36Sopenharmony_ci } else { 21762306a36Sopenharmony_ci /* 2x15 bit slots on SSP2 */ 21862306a36Sopenharmony_ci ret = snd_soc_dai_set_pll(codec_dai, 0, 21962306a36Sopenharmony_ci RT5640_PLL1_S_BCLK1, 22062306a36Sopenharmony_ci rate * 50, rate * 512); 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci } else { 22362306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) { 22462306a36Sopenharmony_ci ret = snd_soc_dai_set_pll(codec_dai, 0, 22562306a36Sopenharmony_ci RT5640_PLL1_S_MCLK, 22662306a36Sopenharmony_ci 25000000, rate * 512); 22762306a36Sopenharmony_ci } else { 22862306a36Sopenharmony_ci ret = snd_soc_dai_set_pll(codec_dai, 0, 22962306a36Sopenharmony_ci RT5640_PLL1_S_MCLK, 23062306a36Sopenharmony_ci 19200000, rate * 512); 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (ret < 0) { 23562306a36Sopenharmony_ci dev_err(codec_dai->component->dev, "can't set pll: %d\n", ret); 23662306a36Sopenharmony_ci return ret; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, 24062306a36Sopenharmony_ci rate * 512, SND_SOC_CLOCK_IN); 24162306a36Sopenharmony_ci if (ret < 0) { 24262306a36Sopenharmony_ci dev_err(codec_dai->component->dev, "can't set clock %d\n", ret); 24362306a36Sopenharmony_ci return ret; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci return 0; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci#define BYT_CODEC_DAI1 "rt5640-aif1" 25062306a36Sopenharmony_ci#define BYT_CODEC_DAI2 "rt5640-aif2" 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic struct snd_soc_dai *byt_rt5640_get_codec_dai(struct snd_soc_dapm_context *dapm) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci struct snd_soc_card *card = dapm->card; 25562306a36Sopenharmony_ci struct snd_soc_dai *codec_dai; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1); 25862306a36Sopenharmony_ci if (!codec_dai) 25962306a36Sopenharmony_ci codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2); 26062306a36Sopenharmony_ci if (!codec_dai) 26162306a36Sopenharmony_ci dev_err(card->dev, "Error codec dai not found\n"); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci return codec_dai; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic int platform_clock_control(struct snd_soc_dapm_widget *w, 26762306a36Sopenharmony_ci struct snd_kcontrol *k, int event) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm = w->dapm; 27062306a36Sopenharmony_ci struct snd_soc_card *card = dapm->card; 27162306a36Sopenharmony_ci struct snd_soc_dai *codec_dai; 27262306a36Sopenharmony_ci struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 27362306a36Sopenharmony_ci int ret; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci codec_dai = byt_rt5640_get_codec_dai(dapm); 27662306a36Sopenharmony_ci if (!codec_dai) 27762306a36Sopenharmony_ci return -EIO; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci if (SND_SOC_DAPM_EVENT_ON(event)) { 28062306a36Sopenharmony_ci ret = clk_prepare_enable(priv->mclk); 28162306a36Sopenharmony_ci if (ret < 0) { 28262306a36Sopenharmony_ci dev_err(card->dev, "could not configure MCLK state\n"); 28362306a36Sopenharmony_ci return ret; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci ret = byt_rt5640_prepare_and_enable_pll1(codec_dai, 48000); 28662306a36Sopenharmony_ci } else { 28762306a36Sopenharmony_ci /* 28862306a36Sopenharmony_ci * Set codec clock source to internal clock before 28962306a36Sopenharmony_ci * turning off the platform clock. Codec needs clock 29062306a36Sopenharmony_ci * for Jack detection and button press 29162306a36Sopenharmony_ci */ 29262306a36Sopenharmony_ci ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK, 29362306a36Sopenharmony_ci 48000 * 512, 29462306a36Sopenharmony_ci SND_SOC_CLOCK_IN); 29562306a36Sopenharmony_ci if (!ret) 29662306a36Sopenharmony_ci clk_disable_unprepare(priv->mclk); 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci if (ret < 0) { 30062306a36Sopenharmony_ci dev_err(card->dev, "can't set codec sysclk: %d\n", ret); 30162306a36Sopenharmony_ci return ret; 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci return 0; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic int byt_rt5640_event_lineout(struct snd_soc_dapm_widget *w, 30862306a36Sopenharmony_ci struct snd_kcontrol *k, int event) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci unsigned int gpio_ctrl3_val = RT5640_GP1_PF_OUT; 31162306a36Sopenharmony_ci struct snd_soc_dai *codec_dai; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (!(byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)) 31462306a36Sopenharmony_ci return 0; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* 31762306a36Sopenharmony_ci * On devices which use line-out as a second headphones output, 31862306a36Sopenharmony_ci * the codec's GPIO1 pin is used to enable an external HP-amp. 31962306a36Sopenharmony_ci */ 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci codec_dai = byt_rt5640_get_codec_dai(w->dapm); 32262306a36Sopenharmony_ci if (!codec_dai) 32362306a36Sopenharmony_ci return -EIO; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (SND_SOC_DAPM_EVENT_ON(event)) 32662306a36Sopenharmony_ci gpio_ctrl3_val |= RT5640_GP1_OUT_HI; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci snd_soc_component_update_bits(codec_dai->component, RT5640_GPIO_CTRL3, 32962306a36Sopenharmony_ci RT5640_GP1_PF_MASK | RT5640_GP1_OUT_MASK, gpio_ctrl3_val); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci return 0; 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { 33562306a36Sopenharmony_ci SND_SOC_DAPM_HP("Headphone", NULL), 33662306a36Sopenharmony_ci SND_SOC_DAPM_MIC("Headset Mic", NULL), 33762306a36Sopenharmony_ci SND_SOC_DAPM_MIC("Headset Mic 2", NULL), 33862306a36Sopenharmony_ci SND_SOC_DAPM_MIC("Internal Mic", NULL), 33962306a36Sopenharmony_ci SND_SOC_DAPM_SPK("Speaker", NULL), 34062306a36Sopenharmony_ci SND_SOC_DAPM_LINE("Line Out", byt_rt5640_event_lineout), 34162306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, 34262306a36Sopenharmony_ci platform_clock_control, SND_SOC_DAPM_PRE_PMU | 34362306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMD), 34462306a36Sopenharmony_ci}; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { 34762306a36Sopenharmony_ci {"Headphone", NULL, "Platform Clock"}, 34862306a36Sopenharmony_ci {"Headset Mic", NULL, "Platform Clock"}, 34962306a36Sopenharmony_ci {"Headset Mic", NULL, "MICBIAS1"}, 35062306a36Sopenharmony_ci {"IN2P", NULL, "Headset Mic"}, 35162306a36Sopenharmony_ci {"Headphone", NULL, "HPOL"}, 35262306a36Sopenharmony_ci {"Headphone", NULL, "HPOR"}, 35362306a36Sopenharmony_ci}; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = { 35662306a36Sopenharmony_ci {"Internal Mic", NULL, "Platform Clock"}, 35762306a36Sopenharmony_ci {"DMIC1", NULL, "Internal Mic"}, 35862306a36Sopenharmony_ci}; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = { 36162306a36Sopenharmony_ci {"Internal Mic", NULL, "Platform Clock"}, 36262306a36Sopenharmony_ci {"DMIC2", NULL, "Internal Mic"}, 36362306a36Sopenharmony_ci}; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { 36662306a36Sopenharmony_ci {"Internal Mic", NULL, "Platform Clock"}, 36762306a36Sopenharmony_ci {"Internal Mic", NULL, "MICBIAS1"}, 36862306a36Sopenharmony_ci {"IN1P", NULL, "Internal Mic"}, 36962306a36Sopenharmony_ci}; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = { 37262306a36Sopenharmony_ci {"Internal Mic", NULL, "Platform Clock"}, 37362306a36Sopenharmony_ci {"Internal Mic", NULL, "MICBIAS1"}, 37462306a36Sopenharmony_ci {"IN3P", NULL, "Internal Mic"}, 37562306a36Sopenharmony_ci}; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_hsmic2_in1_map[] = { 37862306a36Sopenharmony_ci {"Headset Mic 2", NULL, "Platform Clock"}, 37962306a36Sopenharmony_ci {"Headset Mic 2", NULL, "MICBIAS1"}, 38062306a36Sopenharmony_ci {"IN1P", NULL, "Headset Mic 2"}, 38162306a36Sopenharmony_ci}; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = { 38462306a36Sopenharmony_ci {"ssp2 Tx", NULL, "codec_out0"}, 38562306a36Sopenharmony_ci {"ssp2 Tx", NULL, "codec_out1"}, 38662306a36Sopenharmony_ci {"codec_in0", NULL, "ssp2 Rx"}, 38762306a36Sopenharmony_ci {"codec_in1", NULL, "ssp2 Rx"}, 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci {"AIF1 Playback", NULL, "ssp2 Tx"}, 39062306a36Sopenharmony_ci {"ssp2 Rx", NULL, "AIF1 Capture"}, 39162306a36Sopenharmony_ci}; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_ssp2_aif2_map[] = { 39462306a36Sopenharmony_ci {"ssp2 Tx", NULL, "codec_out0"}, 39562306a36Sopenharmony_ci {"ssp2 Tx", NULL, "codec_out1"}, 39662306a36Sopenharmony_ci {"codec_in0", NULL, "ssp2 Rx"}, 39762306a36Sopenharmony_ci {"codec_in1", NULL, "ssp2 Rx"}, 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci {"AIF2 Playback", NULL, "ssp2 Tx"}, 40062306a36Sopenharmony_ci {"ssp2 Rx", NULL, "AIF2 Capture"}, 40162306a36Sopenharmony_ci}; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_ssp0_aif1_map[] = { 40462306a36Sopenharmony_ci {"ssp0 Tx", NULL, "modem_out"}, 40562306a36Sopenharmony_ci {"modem_in", NULL, "ssp0 Rx"}, 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci {"AIF1 Playback", NULL, "ssp0 Tx"}, 40862306a36Sopenharmony_ci {"ssp0 Rx", NULL, "AIF1 Capture"}, 40962306a36Sopenharmony_ci}; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = { 41262306a36Sopenharmony_ci {"ssp0 Tx", NULL, "modem_out"}, 41362306a36Sopenharmony_ci {"modem_in", NULL, "ssp0 Rx"}, 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci {"AIF2 Playback", NULL, "ssp0 Tx"}, 41662306a36Sopenharmony_ci {"ssp0 Rx", NULL, "AIF2 Capture"}, 41762306a36Sopenharmony_ci}; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = { 42062306a36Sopenharmony_ci {"Speaker", NULL, "Platform Clock"}, 42162306a36Sopenharmony_ci {"Speaker", NULL, "SPOLP"}, 42262306a36Sopenharmony_ci {"Speaker", NULL, "SPOLN"}, 42362306a36Sopenharmony_ci {"Speaker", NULL, "SPORP"}, 42462306a36Sopenharmony_ci {"Speaker", NULL, "SPORN"}, 42562306a36Sopenharmony_ci}; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = { 42862306a36Sopenharmony_ci {"Speaker", NULL, "Platform Clock"}, 42962306a36Sopenharmony_ci {"Speaker", NULL, "SPOLP"}, 43062306a36Sopenharmony_ci {"Speaker", NULL, "SPOLN"}, 43162306a36Sopenharmony_ci}; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic const struct snd_soc_dapm_route byt_rt5640_lineout_map[] = { 43462306a36Sopenharmony_ci {"Line Out", NULL, "Platform Clock"}, 43562306a36Sopenharmony_ci {"Line Out", NULL, "LOUTR"}, 43662306a36Sopenharmony_ci {"Line Out", NULL, "LOUTL"}, 43762306a36Sopenharmony_ci}; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic const struct snd_kcontrol_new byt_rt5640_controls[] = { 44062306a36Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Headphone"), 44162306a36Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Headset Mic"), 44262306a36Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Headset Mic 2"), 44362306a36Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Internal Mic"), 44462306a36Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Speaker"), 44562306a36Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Line Out"), 44662306a36Sopenharmony_ci}; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic struct snd_soc_jack_pin rt5640_pins[] = { 44962306a36Sopenharmony_ci { 45062306a36Sopenharmony_ci .pin = "Headphone", 45162306a36Sopenharmony_ci .mask = SND_JACK_HEADPHONE, 45262306a36Sopenharmony_ci }, 45362306a36Sopenharmony_ci { 45462306a36Sopenharmony_ci .pin = "Headset Mic", 45562306a36Sopenharmony_ci .mask = SND_JACK_MICROPHONE, 45662306a36Sopenharmony_ci }, 45762306a36Sopenharmony_ci}; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic struct snd_soc_jack_pin rt5640_pins2[] = { 46062306a36Sopenharmony_ci { 46162306a36Sopenharmony_ci /* The 2nd headset jack uses lineout with an external HP-amp */ 46262306a36Sopenharmony_ci .pin = "Line Out", 46362306a36Sopenharmony_ci .mask = SND_JACK_HEADPHONE, 46462306a36Sopenharmony_ci }, 46562306a36Sopenharmony_ci { 46662306a36Sopenharmony_ci .pin = "Headset Mic 2", 46762306a36Sopenharmony_ci .mask = SND_JACK_MICROPHONE, 46862306a36Sopenharmony_ci }, 46962306a36Sopenharmony_ci}; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic struct snd_soc_jack_gpio rt5640_jack_gpio = { 47262306a36Sopenharmony_ci .name = "hp-detect", 47362306a36Sopenharmony_ci .report = SND_JACK_HEADSET, 47462306a36Sopenharmony_ci .invert = true, 47562306a36Sopenharmony_ci .debounce_time = 200, 47662306a36Sopenharmony_ci}; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cistatic struct snd_soc_jack_gpio rt5640_jack2_gpio = { 47962306a36Sopenharmony_ci .name = "hp2-detect", 48062306a36Sopenharmony_ci .report = SND_JACK_HEADSET, 48162306a36Sopenharmony_ci .invert = true, 48262306a36Sopenharmony_ci .debounce_time = 200, 48362306a36Sopenharmony_ci}; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic const struct acpi_gpio_params acpi_gpio0 = { 0, 0, false }; 48662306a36Sopenharmony_cistatic const struct acpi_gpio_params acpi_gpio1 = { 1, 0, false }; 48762306a36Sopenharmony_cistatic const struct acpi_gpio_params acpi_gpio2 = { 2, 0, false }; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cistatic const struct acpi_gpio_mapping byt_rt5640_hp_elitepad_1000g2_gpios[] = { 49062306a36Sopenharmony_ci { "hp-detect-gpios", &acpi_gpio0, 1, }, 49162306a36Sopenharmony_ci { "headset-mic-detect-gpios", &acpi_gpio1, 1, }, 49262306a36Sopenharmony_ci { "hp2-detect-gpios", &acpi_gpio2, 1, }, 49362306a36Sopenharmony_ci { }, 49462306a36Sopenharmony_ci}; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_cistatic int byt_rt5640_hp_elitepad_1000g2_jack1_check(void *data) 49762306a36Sopenharmony_ci{ 49862306a36Sopenharmony_ci struct byt_rt5640_private *priv = data; 49962306a36Sopenharmony_ci int jack_status, mic_status; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci jack_status = gpiod_get_value_cansleep(rt5640_jack_gpio.desc); 50262306a36Sopenharmony_ci if (jack_status) 50362306a36Sopenharmony_ci return 0; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci mic_status = gpiod_get_value_cansleep(priv->hsmic_detect); 50662306a36Sopenharmony_ci if (mic_status) 50762306a36Sopenharmony_ci return SND_JACK_HEADPHONE; 50862306a36Sopenharmony_ci else 50962306a36Sopenharmony_ci return SND_JACK_HEADSET; 51062306a36Sopenharmony_ci} 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_cistatic int byt_rt5640_hp_elitepad_1000g2_jack2_check(void *data) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci struct snd_soc_component *component = data; 51562306a36Sopenharmony_ci int jack_status, report; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci jack_status = gpiod_get_value_cansleep(rt5640_jack2_gpio.desc); 51862306a36Sopenharmony_ci if (jack_status) 51962306a36Sopenharmony_ci return 0; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci rt5640_enable_micbias1_for_ovcd(component); 52262306a36Sopenharmony_ci report = rt5640_detect_headset(component, rt5640_jack2_gpio.desc); 52362306a36Sopenharmony_ci rt5640_disable_micbias1_for_ovcd(component); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci return report; 52662306a36Sopenharmony_ci} 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_cistatic int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, 52962306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 53262306a36Sopenharmony_ci struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params)); 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci/* Please keep this list alphabetically sorted */ 53862306a36Sopenharmony_cistatic const struct dmi_system_id byt_rt5640_quirk_table[] = { 53962306a36Sopenharmony_ci { /* Acer Iconia One 7 B1-750 */ 54062306a36Sopenharmony_ci .matches = { 54162306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), 54262306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "VESPA2"), 54362306a36Sopenharmony_ci }, 54462306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 54562306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | 54662306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 54762306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 54862306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 54962306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 55062306a36Sopenharmony_ci }, 55162306a36Sopenharmony_ci { /* Acer Iconia Tab 8 W1-810 */ 55262306a36Sopenharmony_ci .matches = { 55362306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"), 55462306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Iconia W1-810"), 55562306a36Sopenharmony_ci }, 55662306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 55762306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | 55862306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 55962306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 56062306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 56162306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 56262306a36Sopenharmony_ci }, 56362306a36Sopenharmony_ci { /* Acer One 10 S1002 */ 56462306a36Sopenharmony_ci .matches = { 56562306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 56662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "One S1002"), 56762306a36Sopenharmony_ci }, 56862306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 56962306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 57062306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 57162306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 57262306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 57362306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF2 | 57462306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 57562306a36Sopenharmony_ci }, 57662306a36Sopenharmony_ci { 57762306a36Sopenharmony_ci .matches = { 57862306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 57962306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"), 58062306a36Sopenharmony_ci }, 58162306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 58262306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 58362306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 58462306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 58562306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 58662306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 58762306a36Sopenharmony_ci }, 58862306a36Sopenharmony_ci { 58962306a36Sopenharmony_ci /* Advantech MICA-071 */ 59062306a36Sopenharmony_ci .matches = { 59162306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"), 59262306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"), 59362306a36Sopenharmony_ci }, 59462306a36Sopenharmony_ci /* OVCD Th = 1500uA to reliable detect head-phones vs -set */ 59562306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN3_MAP | 59662306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 59762306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 59862306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 59962306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 60062306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 60162306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 60262306a36Sopenharmony_ci }, 60362306a36Sopenharmony_ci { 60462306a36Sopenharmony_ci .matches = { 60562306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), 60662306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 80 Cesium"), 60762306a36Sopenharmony_ci }, 60862306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 60962306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 61062306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 61162306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 61262306a36Sopenharmony_ci }, 61362306a36Sopenharmony_ci { 61462306a36Sopenharmony_ci .matches = { 61562306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), 61662306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"), 61762306a36Sopenharmony_ci }, 61862306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 61962306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 62062306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 62162306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 62262306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 62362306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 62462306a36Sopenharmony_ci }, 62562306a36Sopenharmony_ci { 62662306a36Sopenharmony_ci .matches = { 62762306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 62862306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"), 62962306a36Sopenharmony_ci }, 63062306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 63162306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 63262306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 63362306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 63462306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 63562306a36Sopenharmony_ci BYT_RT5640_MCLK_EN | 63662306a36Sopenharmony_ci BYT_RT5640_USE_AMCR0F28), 63762306a36Sopenharmony_ci }, 63862306a36Sopenharmony_ci { 63962306a36Sopenharmony_ci .matches = { 64062306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 64162306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"), 64262306a36Sopenharmony_ci }, 64362306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 64462306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 64562306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 64662306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 64762306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 64862306a36Sopenharmony_ci }, 64962306a36Sopenharmony_ci { 65062306a36Sopenharmony_ci .matches = { 65162306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 65262306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), 65362306a36Sopenharmony_ci }, 65462306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 65562306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 65662306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 65762306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 65862306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 65962306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 66062306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF2 | 66162306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 66262306a36Sopenharmony_ci }, 66362306a36Sopenharmony_ci { 66462306a36Sopenharmony_ci .matches = { 66562306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 66662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"), 66762306a36Sopenharmony_ci }, 66862306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 66962306a36Sopenharmony_ci BYT_RT5640_JD_SRC_EXT_GPIO | 67062306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 67162306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 67262306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 67362306a36Sopenharmony_ci BYT_RT5640_MCLK_EN | 67462306a36Sopenharmony_ci BYT_RT5640_USE_AMCR0F28), 67562306a36Sopenharmony_ci }, 67662306a36Sopenharmony_ci { /* Chuwi Vi8 (CWI506) */ 67762306a36Sopenharmony_ci .matches = { 67862306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), 67962306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"), 68062306a36Sopenharmony_ci /* The above are too generic, also match BIOS info */ 68162306a36Sopenharmony_ci DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"), 68262306a36Sopenharmony_ci }, 68362306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 68462306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 68562306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 68662306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 68762306a36Sopenharmony_ci }, 68862306a36Sopenharmony_ci { /* Chuwi Vi8 dual-boot (CWI506) */ 68962306a36Sopenharmony_ci .matches = { 69062306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), 69162306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"), 69262306a36Sopenharmony_ci /* The above are too generic, also match BIOS info */ 69362306a36Sopenharmony_ci DMI_MATCH(DMI_BIOS_VERSION, "CHUWI2.D86JHBNR02"), 69462306a36Sopenharmony_ci }, 69562306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 69662306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 69762306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 69862306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 69962306a36Sopenharmony_ci }, 70062306a36Sopenharmony_ci { 70162306a36Sopenharmony_ci /* Chuwi Vi10 (CWI505) */ 70262306a36Sopenharmony_ci .matches = { 70362306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), 70462306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"), 70562306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "ilife"), 70662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "S165"), 70762306a36Sopenharmony_ci }, 70862306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 70962306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 71062306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 71162306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 71262306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 71362306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 71462306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 71562306a36Sopenharmony_ci }, 71662306a36Sopenharmony_ci { 71762306a36Sopenharmony_ci /* Chuwi Hi8 (CWI509) */ 71862306a36Sopenharmony_ci .matches = { 71962306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), 72062306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"), 72162306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "ilife"), 72262306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "S806"), 72362306a36Sopenharmony_ci }, 72462306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 72562306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 72662306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 72762306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 72862306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 72962306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 73062306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 73162306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 73262306a36Sopenharmony_ci }, 73362306a36Sopenharmony_ci { 73462306a36Sopenharmony_ci .matches = { 73562306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), 73662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"), 73762306a36Sopenharmony_ci }, 73862306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP), 73962306a36Sopenharmony_ci }, 74062306a36Sopenharmony_ci { /* Connect Tablet 9 */ 74162306a36Sopenharmony_ci .matches = { 74262306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Connect"), 74362306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Tablet 9"), 74462306a36Sopenharmony_ci }, 74562306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 74662306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 74762306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 74862306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 74962306a36Sopenharmony_ci }, 75062306a36Sopenharmony_ci { 75162306a36Sopenharmony_ci .matches = { 75262306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 75362306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"), 75462306a36Sopenharmony_ci }, 75562306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 75662306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 75762306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 75862306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 75962306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 76062306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 76162306a36Sopenharmony_ci }, 76262306a36Sopenharmony_ci { /* Estar Beauty HD MID 7316R */ 76362306a36Sopenharmony_ci .matches = { 76462306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Estar"), 76562306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"), 76662306a36Sopenharmony_ci }, 76762306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 76862306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 76962306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 77062306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 77162306a36Sopenharmony_ci }, 77262306a36Sopenharmony_ci { /* Glavey TM800A550L */ 77362306a36Sopenharmony_ci .matches = { 77462306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 77562306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 77662306a36Sopenharmony_ci /* Above strings are too generic, also match on BIOS version */ 77762306a36Sopenharmony_ci DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"), 77862306a36Sopenharmony_ci }, 77962306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 78062306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 78162306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 78262306a36Sopenharmony_ci }, 78362306a36Sopenharmony_ci { 78462306a36Sopenharmony_ci .matches = { 78562306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 78662306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"), 78762306a36Sopenharmony_ci }, 78862306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC2_MAP | 78962306a36Sopenharmony_ci BYT_RT5640_MCLK_EN | 79062306a36Sopenharmony_ci BYT_RT5640_LINEOUT | 79162306a36Sopenharmony_ci BYT_RT5640_LINEOUT_AS_HP2 | 79262306a36Sopenharmony_ci BYT_RT5640_HSMIC2_ON_IN1 | 79362306a36Sopenharmony_ci BYT_RT5640_JD_HP_ELITEP_1000G2), 79462306a36Sopenharmony_ci }, 79562306a36Sopenharmony_ci { /* HP Pavilion x2 10-k0XX, 10-n0XX */ 79662306a36Sopenharmony_ci .matches = { 79762306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 79862306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), 79962306a36Sopenharmony_ci }, 80062306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 80162306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 80262306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 80362306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 80462306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 80562306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 80662306a36Sopenharmony_ci }, 80762306a36Sopenharmony_ci { /* HP Pavilion x2 10-p0XX */ 80862306a36Sopenharmony_ci .matches = { 80962306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "HP"), 81062306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"), 81162306a36Sopenharmony_ci }, 81262306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 81362306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | 81462306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 81562306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 81662306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 81762306a36Sopenharmony_ci }, 81862306a36Sopenharmony_ci { /* HP Pro Tablet 408 */ 81962306a36Sopenharmony_ci .matches = { 82062306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 82162306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "HP Pro Tablet 408"), 82262306a36Sopenharmony_ci }, 82362306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 82462306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 82562306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 82662306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 82762306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 82862306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 82962306a36Sopenharmony_ci }, 83062306a36Sopenharmony_ci { /* HP Stream 7 */ 83162306a36Sopenharmony_ci .matches = { 83262306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 83362306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 7 Tablet"), 83462306a36Sopenharmony_ci }, 83562306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 83662306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 83762306a36Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 83862306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 83962306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 84062306a36Sopenharmony_ci }, 84162306a36Sopenharmony_ci { /* HP Stream 8 */ 84262306a36Sopenharmony_ci .matches = { 84362306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 84462306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 8 Tablet"), 84562306a36Sopenharmony_ci }, 84662306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 84762306a36Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 84862306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 84962306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 85062306a36Sopenharmony_ci }, 85162306a36Sopenharmony_ci { /* I.T.Works TW891 */ 85262306a36Sopenharmony_ci .matches = { 85362306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), 85462306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"), 85562306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), 85662306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"), 85762306a36Sopenharmony_ci }, 85862306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 85962306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 86062306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 86162306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 86262306a36Sopenharmony_ci }, 86362306a36Sopenharmony_ci { /* Lamina I8270 / T701BR.SE */ 86462306a36Sopenharmony_ci .matches = { 86562306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Lamina"), 86662306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "T701BR.SE"), 86762306a36Sopenharmony_ci }, 86862306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 86962306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 87062306a36Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 87162306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 87262306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 87362306a36Sopenharmony_ci }, 87462306a36Sopenharmony_ci { /* Lenovo Miix 2 8 */ 87562306a36Sopenharmony_ci .matches = { 87662306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), 87762306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "20326"), 87862306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Hiking"), 87962306a36Sopenharmony_ci }, 88062306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 88162306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 88262306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 88362306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 88462306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 88562306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 88662306a36Sopenharmony_ci }, 88762306a36Sopenharmony_ci { /* Lenovo Miix 3-830 */ 88862306a36Sopenharmony_ci .matches = { 88962306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), 89062306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 3-830"), 89162306a36Sopenharmony_ci }, 89262306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 89362306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 89462306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 89562306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 89662306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 89762306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 89862306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 89962306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 90062306a36Sopenharmony_ci }, 90162306a36Sopenharmony_ci { /* Linx Linx7 tablet */ 90262306a36Sopenharmony_ci .matches = { 90362306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LINX"), 90462306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LINX7"), 90562306a36Sopenharmony_ci }, 90662306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 90762306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 90862306a36Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 90962306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 91062306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 91162306a36Sopenharmony_ci }, 91262306a36Sopenharmony_ci { 91362306a36Sopenharmony_ci /* Medion Lifetab S10346 */ 91462306a36Sopenharmony_ci .matches = { 91562306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 91662306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 91762306a36Sopenharmony_ci /* Above strings are much too generic, also match on BIOS date */ 91862306a36Sopenharmony_ci DMI_MATCH(DMI_BIOS_DATE, "10/22/2015"), 91962306a36Sopenharmony_ci }, 92062306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 92162306a36Sopenharmony_ci BYT_RT5640_SWAPPED_SPEAKERS | 92262306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 92362306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 92462306a36Sopenharmony_ci }, 92562306a36Sopenharmony_ci { /* Mele PCG03 Mini PC */ 92662306a36Sopenharmony_ci .matches = { 92762306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"), 92862306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Mini PC"), 92962306a36Sopenharmony_ci }, 93062306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_NO_INTERNAL_MIC_MAP | 93162306a36Sopenharmony_ci BYT_RT5640_NO_SPEAKERS | 93262306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1), 93362306a36Sopenharmony_ci }, 93462306a36Sopenharmony_ci { /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */ 93562306a36Sopenharmony_ci .matches = { 93662306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"), 93762306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"), 93862306a36Sopenharmony_ci }, 93962306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 94062306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 94162306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 94262306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 94362306a36Sopenharmony_ci }, 94462306a36Sopenharmony_ci { 94562306a36Sopenharmony_ci /* MPMAN MPWIN895CL */ 94662306a36Sopenharmony_ci .matches = { 94762306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MPMAN"), 94862306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MPWIN8900CL"), 94962306a36Sopenharmony_ci }, 95062306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 95162306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 95262306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 95362306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 95462306a36Sopenharmony_ci }, 95562306a36Sopenharmony_ci { /* MSI S100 tablet */ 95662306a36Sopenharmony_ci .matches = { 95762306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."), 95862306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "S100"), 95962306a36Sopenharmony_ci }, 96062306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 96162306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 96262306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 96362306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 96462306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 96562306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 96662306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 96762306a36Sopenharmony_ci }, 96862306a36Sopenharmony_ci { /* Nuvison/TMax TM800W560 */ 96962306a36Sopenharmony_ci .matches = { 97062306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TMAX"), 97162306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TM800W560L"), 97262306a36Sopenharmony_ci }, 97362306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 97462306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 97562306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 97662306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 97762306a36Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 97862306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 97962306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 98062306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 98162306a36Sopenharmony_ci }, 98262306a36Sopenharmony_ci { /* Onda v975w */ 98362306a36Sopenharmony_ci .matches = { 98462306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 98562306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 98662306a36Sopenharmony_ci /* The above are too generic, also match BIOS info */ 98762306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_VERSION, "5.6.5"), 98862306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_DATE, "07/25/2014"), 98962306a36Sopenharmony_ci }, 99062306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 99162306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 99262306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 99362306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 99462306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 99562306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 99662306a36Sopenharmony_ci }, 99762306a36Sopenharmony_ci { /* Pipo W4 */ 99862306a36Sopenharmony_ci .matches = { 99962306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 100062306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 100162306a36Sopenharmony_ci /* The above are too generic, also match BIOS info */ 100262306a36Sopenharmony_ci DMI_MATCH(DMI_BIOS_VERSION, "V8L_WIN32_CHIPHD"), 100362306a36Sopenharmony_ci }, 100462306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 100562306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 100662306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 100762306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 100862306a36Sopenharmony_ci }, 100962306a36Sopenharmony_ci { /* Point of View Mobii TAB-P800W (V2.0) */ 101062306a36Sopenharmony_ci .matches = { 101162306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 101262306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 101362306a36Sopenharmony_ci /* The above are too generic, also match BIOS info */ 101462306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1014"), 101562306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_DATE, "10/24/2014"), 101662306a36Sopenharmony_ci }, 101762306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 101862306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 101962306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 102062306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 102162306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 102262306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 102362306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF2 | 102462306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 102562306a36Sopenharmony_ci }, 102662306a36Sopenharmony_ci { /* Point of View Mobii TAB-P800W (V2.1) */ 102762306a36Sopenharmony_ci .matches = { 102862306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 102962306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 103062306a36Sopenharmony_ci /* The above are too generic, also match BIOS info */ 103162306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1013"), 103262306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BIOS_DATE, "08/22/2014"), 103362306a36Sopenharmony_ci }, 103462306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 103562306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 103662306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 103762306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 103862306a36Sopenharmony_ci BYT_RT5640_MONO_SPEAKER | 103962306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 104062306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF2 | 104162306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 104262306a36Sopenharmony_ci }, 104362306a36Sopenharmony_ci { /* Point of View Mobii TAB-P1005W-232 (V2.0) */ 104462306a36Sopenharmony_ci .matches = { 104562306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "POV"), 104662306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_BOARD_NAME, "I102A"), 104762306a36Sopenharmony_ci }, 104862306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 104962306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 105062306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 105162306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 105262306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 105362306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 105462306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 105562306a36Sopenharmony_ci }, 105662306a36Sopenharmony_ci { 105762306a36Sopenharmony_ci /* Prowise PT301 */ 105862306a36Sopenharmony_ci .matches = { 105962306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Prowise"), 106062306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "PT301"), 106162306a36Sopenharmony_ci }, 106262306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 106362306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 106462306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 106562306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 106662306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 106762306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 106862306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 106962306a36Sopenharmony_ci }, 107062306a36Sopenharmony_ci { 107162306a36Sopenharmony_ci /* Teclast X89 */ 107262306a36Sopenharmony_ci .matches = { 107362306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), 107462306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "tPAD"), 107562306a36Sopenharmony_ci }, 107662306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN3_MAP | 107762306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | 107862306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 107962306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_1P0 | 108062306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 108162306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 108262306a36Sopenharmony_ci }, 108362306a36Sopenharmony_ci { /* Toshiba Satellite Click Mini L9W-B */ 108462306a36Sopenharmony_ci .matches = { 108562306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 108662306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"), 108762306a36Sopenharmony_ci }, 108862306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 108962306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 109062306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_1500UA | 109162306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 109262306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1 | 109362306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 109462306a36Sopenharmony_ci }, 109562306a36Sopenharmony_ci { /* Toshiba Encore WT8-A */ 109662306a36Sopenharmony_ci .matches = { 109762306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 109862306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT8-A"), 109962306a36Sopenharmony_ci }, 110062306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 110162306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 110262306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 110362306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 110462306a36Sopenharmony_ci BYT_RT5640_JD_NOT_INV | 110562306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 110662306a36Sopenharmony_ci }, 110762306a36Sopenharmony_ci { /* Toshiba Encore WT10-A */ 110862306a36Sopenharmony_ci .matches = { 110962306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 111062306a36Sopenharmony_ci DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT10-A-103"), 111162306a36Sopenharmony_ci }, 111262306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | 111362306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD1_IN4P | 111462306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 111562306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 111662306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF2 | 111762306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 111862306a36Sopenharmony_ci }, 111962306a36Sopenharmony_ci { /* Voyo Winpad A15 */ 112062306a36Sopenharmony_ci .matches = { 112162306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 112262306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 112362306a36Sopenharmony_ci /* Above strings are too generic, also match on BIOS date */ 112462306a36Sopenharmony_ci DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"), 112562306a36Sopenharmony_ci }, 112662306a36Sopenharmony_ci .driver_data = (void *)(BYT_RT5640_IN1_MAP | 112762306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 112862306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 112962306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75 | 113062306a36Sopenharmony_ci BYT_RT5640_DIFF_MIC | 113162306a36Sopenharmony_ci BYT_RT5640_MCLK_EN), 113262306a36Sopenharmony_ci }, 113362306a36Sopenharmony_ci { /* Catch-all for generic Insyde tablets, must be last */ 113462306a36Sopenharmony_ci .matches = { 113562306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 113662306a36Sopenharmony_ci }, 113762306a36Sopenharmony_ci .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | 113862306a36Sopenharmony_ci BYT_RT5640_MCLK_EN | 113962306a36Sopenharmony_ci BYT_RT5640_SSP0_AIF1), 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci }, 114262306a36Sopenharmony_ci {} 114362306a36Sopenharmony_ci}; 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci/* 114662306a36Sopenharmony_ci * Note this MUST be called before snd_soc_register_card(), so that the props 114762306a36Sopenharmony_ci * are in place before the codec component driver's probe function parses them. 114862306a36Sopenharmony_ci */ 114962306a36Sopenharmony_cistatic int byt_rt5640_add_codec_device_props(struct device *i2c_dev, 115062306a36Sopenharmony_ci struct byt_rt5640_private *priv) 115162306a36Sopenharmony_ci{ 115262306a36Sopenharmony_ci struct property_entry props[MAX_NO_PROPS] = {}; 115362306a36Sopenharmony_ci struct fwnode_handle *fwnode; 115462306a36Sopenharmony_ci int cnt = 0; 115562306a36Sopenharmony_ci int ret; 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { 115862306a36Sopenharmony_ci case BYT_RT5640_DMIC1_MAP: 115962306a36Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic1-data-pin", 116062306a36Sopenharmony_ci RT5640_DMIC1_DATA_PIN_IN1P); 116162306a36Sopenharmony_ci break; 116262306a36Sopenharmony_ci case BYT_RT5640_DMIC2_MAP: 116362306a36Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic2-data-pin", 116462306a36Sopenharmony_ci RT5640_DMIC2_DATA_PIN_IN1N); 116562306a36Sopenharmony_ci break; 116662306a36Sopenharmony_ci case BYT_RT5640_IN1_MAP: 116762306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) 116862306a36Sopenharmony_ci props[cnt++] = 116962306a36Sopenharmony_ci PROPERTY_ENTRY_BOOL("realtek,in1-differential"); 117062306a36Sopenharmony_ci break; 117162306a36Sopenharmony_ci case BYT_RT5640_IN3_MAP: 117262306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) 117362306a36Sopenharmony_ci props[cnt++] = 117462306a36Sopenharmony_ci PROPERTY_ENTRY_BOOL("realtek,in3-differential"); 117562306a36Sopenharmony_ci break; 117662306a36Sopenharmony_ci } 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) { 117962306a36Sopenharmony_ci if (BYT_RT5640_JDSRC(byt_rt5640_quirk) != RT5640_JD_SRC_EXT_GPIO) { 118062306a36Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_U32( 118162306a36Sopenharmony_ci "realtek,jack-detect-source", 118262306a36Sopenharmony_ci BYT_RT5640_JDSRC(byt_rt5640_quirk)); 118362306a36Sopenharmony_ci } 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_U32( 118662306a36Sopenharmony_ci "realtek,over-current-threshold-microamp", 118762306a36Sopenharmony_ci BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100); 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_U32( 119062306a36Sopenharmony_ci "realtek,over-current-scale-factor", 119162306a36Sopenharmony_ci BYT_RT5640_OVCD_SF(byt_rt5640_quirk)); 119262306a36Sopenharmony_ci } 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV) 119562306a36Sopenharmony_ci props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted"); 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci fwnode = fwnode_create_software_node(props, NULL); 119862306a36Sopenharmony_ci if (IS_ERR(fwnode)) { 119962306a36Sopenharmony_ci /* put_device() is handled in caller */ 120062306a36Sopenharmony_ci return PTR_ERR(fwnode); 120162306a36Sopenharmony_ci } 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci ret = device_add_software_node(i2c_dev, to_software_node(fwnode)); 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci fwnode_handle_put(fwnode); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci return ret; 120862306a36Sopenharmony_ci} 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci/* Some Android devs specify IRQs/GPIOS in a special AMCR0F28 ACPI device */ 121162306a36Sopenharmony_cistatic const struct acpi_gpio_params amcr0f28_jd_gpio = { 1, 0, false }; 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_cistatic const struct acpi_gpio_mapping amcr0f28_gpios[] = { 121462306a36Sopenharmony_ci { "rt5640-jd-gpios", &amcr0f28_jd_gpio, 1 }, 121562306a36Sopenharmony_ci { } 121662306a36Sopenharmony_ci}; 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_cistatic int byt_rt5640_get_amcr0f28_settings(struct snd_soc_card *card) 121962306a36Sopenharmony_ci{ 122062306a36Sopenharmony_ci struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 122162306a36Sopenharmony_ci struct rt5640_set_jack_data *data = &priv->jack_data; 122262306a36Sopenharmony_ci struct acpi_device *adev; 122362306a36Sopenharmony_ci int ret = 0; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci adev = acpi_dev_get_first_match_dev("AMCR0F28", "1", -1); 122662306a36Sopenharmony_ci if (!adev) { 122762306a36Sopenharmony_ci dev_err(card->dev, "error cannot find AMCR0F28 adev\n"); 122862306a36Sopenharmony_ci return -ENOENT; 122962306a36Sopenharmony_ci } 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci data->codec_irq_override = acpi_dev_gpio_irq_get(adev, 0); 123262306a36Sopenharmony_ci if (data->codec_irq_override < 0) { 123362306a36Sopenharmony_ci ret = data->codec_irq_override; 123462306a36Sopenharmony_ci dev_err(card->dev, "error %d getting codec IRQ\n", ret); 123562306a36Sopenharmony_ci goto put_adev; 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci if (BYT_RT5640_JDSRC(byt_rt5640_quirk) == RT5640_JD_SRC_EXT_GPIO) { 123962306a36Sopenharmony_ci acpi_dev_add_driver_gpios(adev, amcr0f28_gpios); 124062306a36Sopenharmony_ci data->jd_gpio = devm_fwnode_gpiod_get(card->dev, acpi_fwnode_handle(adev), 124162306a36Sopenharmony_ci "rt5640-jd", GPIOD_IN, "rt5640-jd"); 124262306a36Sopenharmony_ci acpi_dev_remove_driver_gpios(adev); 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci if (IS_ERR(data->jd_gpio)) { 124562306a36Sopenharmony_ci ret = PTR_ERR(data->jd_gpio); 124662306a36Sopenharmony_ci dev_err(card->dev, "error %d getting jd GPIO\n", ret); 124762306a36Sopenharmony_ci } 124862306a36Sopenharmony_ci } 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ciput_adev: 125162306a36Sopenharmony_ci acpi_dev_put(adev); 125262306a36Sopenharmony_ci return ret; 125362306a36Sopenharmony_ci} 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_cistatic int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) 125662306a36Sopenharmony_ci{ 125762306a36Sopenharmony_ci struct snd_soc_card *card = runtime->card; 125862306a36Sopenharmony_ci struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 125962306a36Sopenharmony_ci struct rt5640_set_jack_data *jack_data = &priv->jack_data; 126062306a36Sopenharmony_ci struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; 126162306a36Sopenharmony_ci const struct snd_soc_dapm_route *custom_map = NULL; 126262306a36Sopenharmony_ci int num_routes = 0; 126362306a36Sopenharmony_ci int ret; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci card->dapm.idle_bias_off = true; 126662306a36Sopenharmony_ci jack_data->use_platform_clock = true; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci /* Start with RC clk for jack-detect (we disable MCLK below) */ 126962306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) 127062306a36Sopenharmony_ci snd_soc_component_update_bits(component, RT5640_GLB_CLK, 127162306a36Sopenharmony_ci RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK); 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci rt5640_sel_asrc_clk_src(component, 127462306a36Sopenharmony_ci RT5640_DA_STEREO_FILTER | 127562306a36Sopenharmony_ci RT5640_DA_MONO_L_FILTER | 127662306a36Sopenharmony_ci RT5640_DA_MONO_R_FILTER | 127762306a36Sopenharmony_ci RT5640_AD_STEREO_FILTER | 127862306a36Sopenharmony_ci RT5640_AD_MONO_L_FILTER | 127962306a36Sopenharmony_ci RT5640_AD_MONO_R_FILTER, 128062306a36Sopenharmony_ci RT5640_CLK_SEL_ASRC); 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci ret = snd_soc_add_card_controls(card, byt_rt5640_controls, 128362306a36Sopenharmony_ci ARRAY_SIZE(byt_rt5640_controls)); 128462306a36Sopenharmony_ci if (ret) { 128562306a36Sopenharmony_ci dev_err(card->dev, "unable to add card controls\n"); 128662306a36Sopenharmony_ci return ret; 128762306a36Sopenharmony_ci } 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { 129062306a36Sopenharmony_ci case BYT_RT5640_IN1_MAP: 129162306a36Sopenharmony_ci custom_map = byt_rt5640_intmic_in1_map; 129262306a36Sopenharmony_ci num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map); 129362306a36Sopenharmony_ci break; 129462306a36Sopenharmony_ci case BYT_RT5640_IN3_MAP: 129562306a36Sopenharmony_ci custom_map = byt_rt5640_intmic_in3_map; 129662306a36Sopenharmony_ci num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map); 129762306a36Sopenharmony_ci break; 129862306a36Sopenharmony_ci case BYT_RT5640_DMIC1_MAP: 129962306a36Sopenharmony_ci custom_map = byt_rt5640_intmic_dmic1_map; 130062306a36Sopenharmony_ci num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); 130162306a36Sopenharmony_ci break; 130262306a36Sopenharmony_ci case BYT_RT5640_DMIC2_MAP: 130362306a36Sopenharmony_ci custom_map = byt_rt5640_intmic_dmic2_map; 130462306a36Sopenharmony_ci num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map); 130562306a36Sopenharmony_ci break; 130662306a36Sopenharmony_ci } 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); 130962306a36Sopenharmony_ci if (ret) 131062306a36Sopenharmony_ci return ret; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) { 131362306a36Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 131462306a36Sopenharmony_ci byt_rt5640_hsmic2_in1_map, 131562306a36Sopenharmony_ci ARRAY_SIZE(byt_rt5640_hsmic2_in1_map)); 131662306a36Sopenharmony_ci if (ret) 131762306a36Sopenharmony_ci return ret; 131862306a36Sopenharmony_ci } 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { 132162306a36Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 132262306a36Sopenharmony_ci byt_rt5640_ssp2_aif2_map, 132362306a36Sopenharmony_ci ARRAY_SIZE(byt_rt5640_ssp2_aif2_map)); 132462306a36Sopenharmony_ci } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { 132562306a36Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 132662306a36Sopenharmony_ci byt_rt5640_ssp0_aif1_map, 132762306a36Sopenharmony_ci ARRAY_SIZE(byt_rt5640_ssp0_aif1_map)); 132862306a36Sopenharmony_ci } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) { 132962306a36Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 133062306a36Sopenharmony_ci byt_rt5640_ssp0_aif2_map, 133162306a36Sopenharmony_ci ARRAY_SIZE(byt_rt5640_ssp0_aif2_map)); 133262306a36Sopenharmony_ci } else { 133362306a36Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 133462306a36Sopenharmony_ci byt_rt5640_ssp2_aif1_map, 133562306a36Sopenharmony_ci ARRAY_SIZE(byt_rt5640_ssp2_aif1_map)); 133662306a36Sopenharmony_ci } 133762306a36Sopenharmony_ci if (ret) 133862306a36Sopenharmony_ci return ret; 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { 134162306a36Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 134262306a36Sopenharmony_ci byt_rt5640_mono_spk_map, 134362306a36Sopenharmony_ci ARRAY_SIZE(byt_rt5640_mono_spk_map)); 134462306a36Sopenharmony_ci } else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) { 134562306a36Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 134662306a36Sopenharmony_ci byt_rt5640_stereo_spk_map, 134762306a36Sopenharmony_ci ARRAY_SIZE(byt_rt5640_stereo_spk_map)); 134862306a36Sopenharmony_ci } 134962306a36Sopenharmony_ci if (ret) 135062306a36Sopenharmony_ci return ret; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) { 135362306a36Sopenharmony_ci ret = snd_soc_dapm_add_routes(&card->dapm, 135462306a36Sopenharmony_ci byt_rt5640_lineout_map, 135562306a36Sopenharmony_ci ARRAY_SIZE(byt_rt5640_lineout_map)); 135662306a36Sopenharmony_ci if (ret) 135762306a36Sopenharmony_ci return ret; 135862306a36Sopenharmony_ci } 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci /* 136162306a36Sopenharmony_ci * The firmware might enable the clock at boot (this information 136262306a36Sopenharmony_ci * may or may not be reflected in the enable clock register). 136362306a36Sopenharmony_ci * To change the rate we must disable the clock first to cover 136462306a36Sopenharmony_ci * these cases. Due to common clock framework restrictions that 136562306a36Sopenharmony_ci * do not allow to disable a clock that has not been enabled, 136662306a36Sopenharmony_ci * we need to enable the clock first. 136762306a36Sopenharmony_ci */ 136862306a36Sopenharmony_ci ret = clk_prepare_enable(priv->mclk); 136962306a36Sopenharmony_ci if (!ret) 137062306a36Sopenharmony_ci clk_disable_unprepare(priv->mclk); 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) 137362306a36Sopenharmony_ci ret = clk_set_rate(priv->mclk, 25000000); 137462306a36Sopenharmony_ci else 137562306a36Sopenharmony_ci ret = clk_set_rate(priv->mclk, 19200000); 137662306a36Sopenharmony_ci if (ret) { 137762306a36Sopenharmony_ci dev_err(card->dev, "unable to set MCLK rate\n"); 137862306a36Sopenharmony_ci return ret; 137962306a36Sopenharmony_ci } 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) { 138262306a36Sopenharmony_ci ret = snd_soc_card_jack_new_pins(card, "Headset", 138362306a36Sopenharmony_ci SND_JACK_HEADSET | SND_JACK_BTN_0, 138462306a36Sopenharmony_ci &priv->jack, rt5640_pins, 138562306a36Sopenharmony_ci ARRAY_SIZE(rt5640_pins)); 138662306a36Sopenharmony_ci if (ret) { 138762306a36Sopenharmony_ci dev_err(card->dev, "Jack creation failed %d\n", ret); 138862306a36Sopenharmony_ci return ret; 138962306a36Sopenharmony_ci } 139062306a36Sopenharmony_ci snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, 139162306a36Sopenharmony_ci KEY_PLAYPAUSE); 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_USE_AMCR0F28) { 139462306a36Sopenharmony_ci ret = byt_rt5640_get_amcr0f28_settings(card); 139562306a36Sopenharmony_ci if (ret) 139662306a36Sopenharmony_ci return ret; 139762306a36Sopenharmony_ci } 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci snd_soc_component_set_jack(component, &priv->jack, &priv->jack_data); 140062306a36Sopenharmony_ci } 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) { 140362306a36Sopenharmony_ci ret = snd_soc_card_jack_new_pins(card, "Headset", 140462306a36Sopenharmony_ci SND_JACK_HEADSET, 140562306a36Sopenharmony_ci &priv->jack, rt5640_pins, 140662306a36Sopenharmony_ci ARRAY_SIZE(rt5640_pins)); 140762306a36Sopenharmony_ci if (ret) 140862306a36Sopenharmony_ci return ret; 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci ret = snd_soc_card_jack_new_pins(card, "Headset 2", 141162306a36Sopenharmony_ci SND_JACK_HEADSET, 141262306a36Sopenharmony_ci &priv->jack2, rt5640_pins2, 141362306a36Sopenharmony_ci ARRAY_SIZE(rt5640_pins2)); 141462306a36Sopenharmony_ci if (ret) 141562306a36Sopenharmony_ci return ret; 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci rt5640_jack_gpio.data = priv; 141862306a36Sopenharmony_ci rt5640_jack_gpio.gpiod_dev = priv->codec_dev; 141962306a36Sopenharmony_ci rt5640_jack_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack1_check; 142062306a36Sopenharmony_ci ret = snd_soc_jack_add_gpios(&priv->jack, 1, &rt5640_jack_gpio); 142162306a36Sopenharmony_ci if (ret) 142262306a36Sopenharmony_ci return ret; 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_ci rt5640_set_ovcd_params(component); 142562306a36Sopenharmony_ci rt5640_jack2_gpio.data = component; 142662306a36Sopenharmony_ci rt5640_jack2_gpio.gpiod_dev = priv->codec_dev; 142762306a36Sopenharmony_ci rt5640_jack2_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack2_check; 142862306a36Sopenharmony_ci ret = snd_soc_jack_add_gpios(&priv->jack2, 1, &rt5640_jack2_gpio); 142962306a36Sopenharmony_ci if (ret) { 143062306a36Sopenharmony_ci snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio); 143162306a36Sopenharmony_ci return ret; 143262306a36Sopenharmony_ci } 143362306a36Sopenharmony_ci } 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci return 0; 143662306a36Sopenharmony_ci} 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_cistatic void byt_rt5640_exit(struct snd_soc_pcm_runtime *runtime) 143962306a36Sopenharmony_ci{ 144062306a36Sopenharmony_ci struct snd_soc_card *card = runtime->card; 144162306a36Sopenharmony_ci struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) { 144462306a36Sopenharmony_ci snd_soc_jack_free_gpios(&priv->jack2, 1, &rt5640_jack2_gpio); 144562306a36Sopenharmony_ci snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio); 144662306a36Sopenharmony_ci } 144762306a36Sopenharmony_ci} 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_cistatic int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, 145062306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 145162306a36Sopenharmony_ci{ 145262306a36Sopenharmony_ci struct snd_interval *rate = hw_param_interval(params, 145362306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_RATE); 145462306a36Sopenharmony_ci struct snd_interval *channels = hw_param_interval(params, 145562306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_CHANNELS); 145662306a36Sopenharmony_ci int ret, bits; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci /* The DSP will convert the FE rate to 48k, stereo */ 145962306a36Sopenharmony_ci rate->min = rate->max = 48000; 146062306a36Sopenharmony_ci channels->min = channels->max = 2; 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || 146362306a36Sopenharmony_ci (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { 146462306a36Sopenharmony_ci /* set SSP0 to 16-bit */ 146562306a36Sopenharmony_ci params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); 146662306a36Sopenharmony_ci bits = 16; 146762306a36Sopenharmony_ci } else { 146862306a36Sopenharmony_ci /* set SSP2 to 24-bit */ 146962306a36Sopenharmony_ci params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); 147062306a36Sopenharmony_ci bits = 24; 147162306a36Sopenharmony_ci } 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci /* 147462306a36Sopenharmony_ci * Default mode for SSP configuration is TDM 4 slot, override config 147562306a36Sopenharmony_ci * with explicit setting to I2S 2ch. The word length is set with 147662306a36Sopenharmony_ci * dai_set_tdm_slot() since there is no other API exposed 147762306a36Sopenharmony_ci */ 147862306a36Sopenharmony_ci ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), 147962306a36Sopenharmony_ci SND_SOC_DAIFMT_I2S | 148062306a36Sopenharmony_ci SND_SOC_DAIFMT_NB_NF | 148162306a36Sopenharmony_ci SND_SOC_DAIFMT_BP_FP); 148262306a36Sopenharmony_ci if (ret < 0) { 148362306a36Sopenharmony_ci dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); 148462306a36Sopenharmony_ci return ret; 148562306a36Sopenharmony_ci } 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); 148862306a36Sopenharmony_ci if (ret < 0) { 148962306a36Sopenharmony_ci dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); 149062306a36Sopenharmony_ci return ret; 149162306a36Sopenharmony_ci } 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci return 0; 149462306a36Sopenharmony_ci} 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_cistatic int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream) 149762306a36Sopenharmony_ci{ 149862306a36Sopenharmony_ci return snd_pcm_hw_constraint_single(substream->runtime, 149962306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_RATE, 48000); 150062306a36Sopenharmony_ci} 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_cistatic const struct snd_soc_ops byt_rt5640_aif1_ops = { 150362306a36Sopenharmony_ci .startup = byt_rt5640_aif1_startup, 150462306a36Sopenharmony_ci}; 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_cistatic const struct snd_soc_ops byt_rt5640_be_ssp2_ops = { 150762306a36Sopenharmony_ci .hw_params = byt_rt5640_aif1_hw_params, 150862306a36Sopenharmony_ci}; 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ciSND_SOC_DAILINK_DEF(dummy, 151162306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY())); 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ciSND_SOC_DAILINK_DEF(media, 151462306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai"))); 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ciSND_SOC_DAILINK_DEF(deepbuffer, 151762306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai"))); 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ciSND_SOC_DAILINK_DEF(ssp2_port, 152062306a36Sopenharmony_ci /* overwritten for ssp0 routing */ 152162306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port"))); 152262306a36Sopenharmony_ciSND_SOC_DAILINK_DEF(ssp2_codec, 152362306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CODEC( 152462306a36Sopenharmony_ci /* overwritten with HID */ "i2c-10EC5640:00", 152562306a36Sopenharmony_ci /* changed w/ quirk */ "rt5640-aif1"))); 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ciSND_SOC_DAILINK_DEF(platform, 152862306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform"))); 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_cistatic struct snd_soc_dai_link byt_rt5640_dais[] = { 153162306a36Sopenharmony_ci [MERR_DPCM_AUDIO] = { 153262306a36Sopenharmony_ci .name = "Baytrail Audio Port", 153362306a36Sopenharmony_ci .stream_name = "Baytrail Audio", 153462306a36Sopenharmony_ci .nonatomic = true, 153562306a36Sopenharmony_ci .dynamic = 1, 153662306a36Sopenharmony_ci .dpcm_playback = 1, 153762306a36Sopenharmony_ci .dpcm_capture = 1, 153862306a36Sopenharmony_ci .ops = &byt_rt5640_aif1_ops, 153962306a36Sopenharmony_ci SND_SOC_DAILINK_REG(media, dummy, platform), 154062306a36Sopenharmony_ci }, 154162306a36Sopenharmony_ci [MERR_DPCM_DEEP_BUFFER] = { 154262306a36Sopenharmony_ci .name = "Deep-Buffer Audio Port", 154362306a36Sopenharmony_ci .stream_name = "Deep-Buffer Audio", 154462306a36Sopenharmony_ci .nonatomic = true, 154562306a36Sopenharmony_ci .dynamic = 1, 154662306a36Sopenharmony_ci .dpcm_playback = 1, 154762306a36Sopenharmony_ci .ops = &byt_rt5640_aif1_ops, 154862306a36Sopenharmony_ci SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), 154962306a36Sopenharmony_ci }, 155062306a36Sopenharmony_ci /* back ends */ 155162306a36Sopenharmony_ci { 155262306a36Sopenharmony_ci .name = "SSP2-Codec", 155362306a36Sopenharmony_ci .id = 0, 155462306a36Sopenharmony_ci .no_pcm = 1, 155562306a36Sopenharmony_ci .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 155662306a36Sopenharmony_ci | SND_SOC_DAIFMT_CBC_CFC, 155762306a36Sopenharmony_ci .be_hw_params_fixup = byt_rt5640_codec_fixup, 155862306a36Sopenharmony_ci .dpcm_playback = 1, 155962306a36Sopenharmony_ci .dpcm_capture = 1, 156062306a36Sopenharmony_ci .init = byt_rt5640_init, 156162306a36Sopenharmony_ci .exit = byt_rt5640_exit, 156262306a36Sopenharmony_ci .ops = &byt_rt5640_be_ssp2_ops, 156362306a36Sopenharmony_ci SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), 156462306a36Sopenharmony_ci }, 156562306a36Sopenharmony_ci}; 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci/* SoC card */ 156862306a36Sopenharmony_cistatic char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN]; 156962306a36Sopenharmony_ci#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) 157062306a36Sopenharmony_cistatic char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */ 157162306a36Sopenharmony_ci#endif 157262306a36Sopenharmony_cistatic char byt_rt5640_components[64]; /* = "cfg-spk:* cfg-mic:* ..." */ 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_cistatic int byt_rt5640_suspend(struct snd_soc_card *card) 157562306a36Sopenharmony_ci{ 157662306a36Sopenharmony_ci struct snd_soc_component *component; 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) 157962306a36Sopenharmony_ci return 0; 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci for_each_card_components(card, component) { 158262306a36Sopenharmony_ci if (!strcmp(component->name, byt_rt5640_codec_name)) { 158362306a36Sopenharmony_ci dev_dbg(component->dev, "disabling jack detect before suspend\n"); 158462306a36Sopenharmony_ci snd_soc_component_set_jack(component, NULL, NULL); 158562306a36Sopenharmony_ci break; 158662306a36Sopenharmony_ci } 158762306a36Sopenharmony_ci } 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci return 0; 159062306a36Sopenharmony_ci} 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_cistatic int byt_rt5640_resume(struct snd_soc_card *card) 159362306a36Sopenharmony_ci{ 159462306a36Sopenharmony_ci struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 159562306a36Sopenharmony_ci struct snd_soc_component *component; 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci if (!BYT_RT5640_JDSRC(byt_rt5640_quirk)) 159862306a36Sopenharmony_ci return 0; 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci for_each_card_components(card, component) { 160162306a36Sopenharmony_ci if (!strcmp(component->name, byt_rt5640_codec_name)) { 160262306a36Sopenharmony_ci dev_dbg(component->dev, "re-enabling jack detect after resume\n"); 160362306a36Sopenharmony_ci snd_soc_component_set_jack(component, &priv->jack, 160462306a36Sopenharmony_ci &priv->jack_data); 160562306a36Sopenharmony_ci break; 160662306a36Sopenharmony_ci } 160762306a36Sopenharmony_ci } 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci return 0; 161062306a36Sopenharmony_ci} 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci/* use space before codec name to simplify card ID, and simplify driver name */ 161362306a36Sopenharmony_ci#define SOF_CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */ 161462306a36Sopenharmony_ci#define SOF_DRIVER_NAME "SOF" 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci#define CARD_NAME "bytcr-rt5640" 161762306a36Sopenharmony_ci#define DRIVER_NAME NULL /* card name will be used for driver name */ 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_cistatic struct snd_soc_card byt_rt5640_card = { 162062306a36Sopenharmony_ci .owner = THIS_MODULE, 162162306a36Sopenharmony_ci .dai_link = byt_rt5640_dais, 162262306a36Sopenharmony_ci .num_links = ARRAY_SIZE(byt_rt5640_dais), 162362306a36Sopenharmony_ci .dapm_widgets = byt_rt5640_widgets, 162462306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets), 162562306a36Sopenharmony_ci .dapm_routes = byt_rt5640_audio_map, 162662306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map), 162762306a36Sopenharmony_ci .fully_routed = true, 162862306a36Sopenharmony_ci .suspend_pre = byt_rt5640_suspend, 162962306a36Sopenharmony_ci .resume_post = byt_rt5640_resume, 163062306a36Sopenharmony_ci}; 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_cistruct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ 163362306a36Sopenharmony_ci u64 aif_value; /* 1: AIF1, 2: AIF2 */ 163462306a36Sopenharmony_ci u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */ 163562306a36Sopenharmony_ci}; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_cistatic int snd_byt_rt5640_mc_probe(struct platform_device *pdev) 163862306a36Sopenharmony_ci{ 163962306a36Sopenharmony_ci struct device *dev = &pdev->dev; 164062306a36Sopenharmony_ci static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" }; 164162306a36Sopenharmony_ci struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); 164262306a36Sopenharmony_ci __maybe_unused const char *spk_type; 164362306a36Sopenharmony_ci const struct dmi_system_id *dmi_id; 164462306a36Sopenharmony_ci const char *headset2_string = ""; 164562306a36Sopenharmony_ci const char *lineout_string = ""; 164662306a36Sopenharmony_ci struct byt_rt5640_private *priv; 164762306a36Sopenharmony_ci const char *platform_name; 164862306a36Sopenharmony_ci struct acpi_device *adev; 164962306a36Sopenharmony_ci struct device *codec_dev; 165062306a36Sopenharmony_ci const char *cfg_spk; 165162306a36Sopenharmony_ci bool sof_parent; 165262306a36Sopenharmony_ci int ret_val = 0; 165362306a36Sopenharmony_ci int dai_index = 0; 165462306a36Sopenharmony_ci int i, aif; 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci is_bytcr = false; 165762306a36Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 165862306a36Sopenharmony_ci if (!priv) 165962306a36Sopenharmony_ci return -ENOMEM; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci /* register the soc card */ 166262306a36Sopenharmony_ci byt_rt5640_card.dev = dev; 166362306a36Sopenharmony_ci snd_soc_card_set_drvdata(&byt_rt5640_card, priv); 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_ci /* fix index of codec dai */ 166662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) { 166762306a36Sopenharmony_ci if (!strcmp(byt_rt5640_dais[i].codecs->name, 166862306a36Sopenharmony_ci "i2c-10EC5640:00")) { 166962306a36Sopenharmony_ci dai_index = i; 167062306a36Sopenharmony_ci break; 167162306a36Sopenharmony_ci } 167262306a36Sopenharmony_ci } 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci /* fixup codec name based on HID */ 167562306a36Sopenharmony_ci adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1); 167662306a36Sopenharmony_ci if (adev) { 167762306a36Sopenharmony_ci snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name), 167862306a36Sopenharmony_ci "i2c-%s", acpi_dev_name(adev)); 167962306a36Sopenharmony_ci byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name; 168062306a36Sopenharmony_ci } else { 168162306a36Sopenharmony_ci dev_err(dev, "Error cannot find '%s' dev\n", mach->id); 168262306a36Sopenharmony_ci return -ENXIO; 168362306a36Sopenharmony_ci } 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci codec_dev = acpi_get_first_physical_node(adev); 168662306a36Sopenharmony_ci acpi_dev_put(adev); 168762306a36Sopenharmony_ci if (!codec_dev) 168862306a36Sopenharmony_ci return -EPROBE_DEFER; 168962306a36Sopenharmony_ci priv->codec_dev = get_device(codec_dev); 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci /* 169262306a36Sopenharmony_ci * swap SSP0 if bytcr is detected 169362306a36Sopenharmony_ci * (will be overridden if DMI quirk is detected) 169462306a36Sopenharmony_ci */ 169562306a36Sopenharmony_ci if (soc_intel_is_byt()) { 169662306a36Sopenharmony_ci if (mach->mach_params.acpi_ipc_irq_index == 0) 169762306a36Sopenharmony_ci is_bytcr = true; 169862306a36Sopenharmony_ci } 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci if (is_bytcr) { 170162306a36Sopenharmony_ci /* 170262306a36Sopenharmony_ci * Baytrail CR platforms may have CHAN package in BIOS, try 170362306a36Sopenharmony_ci * to find relevant routing quirk based as done on Windows 170462306a36Sopenharmony_ci * platforms. We have to read the information directly from the 170562306a36Sopenharmony_ci * BIOS, at this stage the card is not created and the links 170662306a36Sopenharmony_ci * with the codec driver/pdata are non-existent 170762306a36Sopenharmony_ci */ 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci struct acpi_chan_package chan_package = { 0 }; 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci /* format specified: 2 64-bit integers */ 171262306a36Sopenharmony_ci struct acpi_buffer format = {sizeof("NN"), "NN"}; 171362306a36Sopenharmony_ci struct acpi_buffer state = {0, NULL}; 171462306a36Sopenharmony_ci struct snd_soc_acpi_package_context pkg_ctx; 171562306a36Sopenharmony_ci bool pkg_found = false; 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci state.length = sizeof(chan_package); 171862306a36Sopenharmony_ci state.pointer = &chan_package; 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci pkg_ctx.name = "CHAN"; 172162306a36Sopenharmony_ci pkg_ctx.length = 2; 172262306a36Sopenharmony_ci pkg_ctx.format = &format; 172362306a36Sopenharmony_ci pkg_ctx.state = &state; 172462306a36Sopenharmony_ci pkg_ctx.data_valid = false; 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci pkg_found = snd_soc_acpi_find_package_from_hid(mach->id, 172762306a36Sopenharmony_ci &pkg_ctx); 172862306a36Sopenharmony_ci if (pkg_found) { 172962306a36Sopenharmony_ci if (chan_package.aif_value == 1) { 173062306a36Sopenharmony_ci dev_info(dev, "BIOS Routing: AIF1 connected\n"); 173162306a36Sopenharmony_ci byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1; 173262306a36Sopenharmony_ci } else if (chan_package.aif_value == 2) { 173362306a36Sopenharmony_ci dev_info(dev, "BIOS Routing: AIF2 connected\n"); 173462306a36Sopenharmony_ci byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; 173562306a36Sopenharmony_ci } else { 173662306a36Sopenharmony_ci dev_info(dev, "BIOS Routing isn't valid, ignored\n"); 173762306a36Sopenharmony_ci pkg_found = false; 173862306a36Sopenharmony_ci } 173962306a36Sopenharmony_ci } 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci if (!pkg_found) { 174262306a36Sopenharmony_ci /* no BIOS indications, assume SSP0-AIF2 connection */ 174362306a36Sopenharmony_ci byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2; 174462306a36Sopenharmony_ci } 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci /* change defaults for Baytrail-CR capture */ 174762306a36Sopenharmony_ci byt_rt5640_quirk |= BYTCR_INPUT_DEFAULTS; 174862306a36Sopenharmony_ci } else { 174962306a36Sopenharmony_ci byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP | 175062306a36Sopenharmony_ci BYT_RT5640_JD_SRC_JD2_IN4N | 175162306a36Sopenharmony_ci BYT_RT5640_OVCD_TH_2000UA | 175262306a36Sopenharmony_ci BYT_RT5640_OVCD_SF_0P75; 175362306a36Sopenharmony_ci } 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_ci /* check quirks before creating card */ 175662306a36Sopenharmony_ci dmi_id = dmi_first_match(byt_rt5640_quirk_table); 175762306a36Sopenharmony_ci if (dmi_id) 175862306a36Sopenharmony_ci byt_rt5640_quirk = (unsigned long)dmi_id->driver_data; 175962306a36Sopenharmony_ci if (quirk_override != -1) { 176062306a36Sopenharmony_ci dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n", 176162306a36Sopenharmony_ci byt_rt5640_quirk, quirk_override); 176262306a36Sopenharmony_ci byt_rt5640_quirk = quirk_override; 176362306a36Sopenharmony_ci } 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) { 176662306a36Sopenharmony_ci acpi_dev_add_driver_gpios(ACPI_COMPANION(priv->codec_dev), 176762306a36Sopenharmony_ci byt_rt5640_hp_elitepad_1000g2_gpios); 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci priv->hsmic_detect = devm_fwnode_gpiod_get(dev, codec_dev->fwnode, 177062306a36Sopenharmony_ci "headset-mic-detect", GPIOD_IN, 177162306a36Sopenharmony_ci "headset-mic-detect"); 177262306a36Sopenharmony_ci if (IS_ERR(priv->hsmic_detect)) { 177362306a36Sopenharmony_ci ret_val = dev_err_probe(dev, PTR_ERR(priv->hsmic_detect), 177462306a36Sopenharmony_ci "getting hsmic-detect GPIO\n"); 177562306a36Sopenharmony_ci goto err_device; 177662306a36Sopenharmony_ci } 177762306a36Sopenharmony_ci } 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci /* Must be called before register_card, also see declaration comment. */ 178062306a36Sopenharmony_ci ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv); 178162306a36Sopenharmony_ci if (ret_val) 178262306a36Sopenharmony_ci goto err_remove_gpios; 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci log_quirks(dev); 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) || 178762306a36Sopenharmony_ci (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { 178862306a36Sopenharmony_ci byt_rt5640_dais[dai_index].codecs->dai_name = "rt5640-aif2"; 178962306a36Sopenharmony_ci aif = 2; 179062306a36Sopenharmony_ci } else { 179162306a36Sopenharmony_ci aif = 1; 179262306a36Sopenharmony_ci } 179362306a36Sopenharmony_ci 179462306a36Sopenharmony_ci if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || 179562306a36Sopenharmony_ci (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) 179662306a36Sopenharmony_ci byt_rt5640_dais[dai_index].cpus->dai_name = "ssp0-port"; 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { 179962306a36Sopenharmony_ci priv->mclk = devm_clk_get_optional(dev, "pmc_plt_clk_3"); 180062306a36Sopenharmony_ci if (IS_ERR(priv->mclk)) { 180162306a36Sopenharmony_ci ret_val = dev_err_probe(dev, PTR_ERR(priv->mclk), 180262306a36Sopenharmony_ci "Failed to get MCLK from pmc_plt_clk_3\n"); 180362306a36Sopenharmony_ci goto err; 180462306a36Sopenharmony_ci } 180562306a36Sopenharmony_ci /* 180662306a36Sopenharmony_ci * Fall back to bit clock usage when clock is not 180762306a36Sopenharmony_ci * available likely due to missing dependencies. 180862306a36Sopenharmony_ci */ 180962306a36Sopenharmony_ci if (!priv->mclk) 181062306a36Sopenharmony_ci byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN; 181162306a36Sopenharmony_ci } 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) { 181462306a36Sopenharmony_ci cfg_spk = "0"; 181562306a36Sopenharmony_ci spk_type = "none"; 181662306a36Sopenharmony_ci } else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { 181762306a36Sopenharmony_ci cfg_spk = "1"; 181862306a36Sopenharmony_ci spk_type = "mono"; 181962306a36Sopenharmony_ci } else if (byt_rt5640_quirk & BYT_RT5640_SWAPPED_SPEAKERS) { 182062306a36Sopenharmony_ci cfg_spk = "swapped"; 182162306a36Sopenharmony_ci spk_type = "swapped"; 182262306a36Sopenharmony_ci } else { 182362306a36Sopenharmony_ci cfg_spk = "2"; 182462306a36Sopenharmony_ci spk_type = "stereo"; 182562306a36Sopenharmony_ci } 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) { 182862306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2) 182962306a36Sopenharmony_ci lineout_string = " cfg-hp2:lineout"; 183062306a36Sopenharmony_ci else 183162306a36Sopenharmony_ci lineout_string = " cfg-lineout:2"; 183262306a36Sopenharmony_ci } 183362306a36Sopenharmony_ci 183462306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) 183562306a36Sopenharmony_ci headset2_string = " cfg-hs2:in1"; 183662306a36Sopenharmony_ci 183762306a36Sopenharmony_ci snprintf(byt_rt5640_components, sizeof(byt_rt5640_components), 183862306a36Sopenharmony_ci "cfg-spk:%s cfg-mic:%s aif:%d%s%s", cfg_spk, 183962306a36Sopenharmony_ci map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif, 184062306a36Sopenharmony_ci lineout_string, headset2_string); 184162306a36Sopenharmony_ci byt_rt5640_card.components = byt_rt5640_components; 184262306a36Sopenharmony_ci#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) 184362306a36Sopenharmony_ci snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name), 184462306a36Sopenharmony_ci "bytcr-rt5640-%s-spk-%s-mic", spk_type, 184562306a36Sopenharmony_ci map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); 184662306a36Sopenharmony_ci byt_rt5640_card.long_name = byt_rt5640_long_name; 184762306a36Sopenharmony_ci#endif 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci /* override platform name, if required */ 185062306a36Sopenharmony_ci platform_name = mach->mach_params.platform; 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card, 185362306a36Sopenharmony_ci platform_name); 185462306a36Sopenharmony_ci if (ret_val) 185562306a36Sopenharmony_ci goto err; 185662306a36Sopenharmony_ci 185762306a36Sopenharmony_ci sof_parent = snd_soc_acpi_sof_parent(dev); 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci /* set card and driver name */ 186062306a36Sopenharmony_ci if (sof_parent) { 186162306a36Sopenharmony_ci byt_rt5640_card.name = SOF_CARD_NAME; 186262306a36Sopenharmony_ci byt_rt5640_card.driver_name = SOF_DRIVER_NAME; 186362306a36Sopenharmony_ci } else { 186462306a36Sopenharmony_ci byt_rt5640_card.name = CARD_NAME; 186562306a36Sopenharmony_ci byt_rt5640_card.driver_name = DRIVER_NAME; 186662306a36Sopenharmony_ci } 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci /* set pm ops */ 186962306a36Sopenharmony_ci if (sof_parent) 187062306a36Sopenharmony_ci dev->driver->pm = &snd_soc_pm_ops; 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci ret_val = devm_snd_soc_register_card(dev, &byt_rt5640_card); 187362306a36Sopenharmony_ci if (ret_val) { 187462306a36Sopenharmony_ci dev_err(dev, "devm_snd_soc_register_card failed %d\n", ret_val); 187562306a36Sopenharmony_ci goto err; 187662306a36Sopenharmony_ci } 187762306a36Sopenharmony_ci platform_set_drvdata(pdev, &byt_rt5640_card); 187862306a36Sopenharmony_ci return ret_val; 187962306a36Sopenharmony_ci 188062306a36Sopenharmony_cierr: 188162306a36Sopenharmony_ci device_remove_software_node(priv->codec_dev); 188262306a36Sopenharmony_cierr_remove_gpios: 188362306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) 188462306a36Sopenharmony_ci acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev)); 188562306a36Sopenharmony_cierr_device: 188662306a36Sopenharmony_ci put_device(priv->codec_dev); 188762306a36Sopenharmony_ci return ret_val; 188862306a36Sopenharmony_ci} 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_cistatic void snd_byt_rt5640_mc_remove(struct platform_device *pdev) 189162306a36Sopenharmony_ci{ 189262306a36Sopenharmony_ci struct snd_soc_card *card = platform_get_drvdata(pdev); 189362306a36Sopenharmony_ci struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); 189462306a36Sopenharmony_ci 189562306a36Sopenharmony_ci if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) 189662306a36Sopenharmony_ci acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev)); 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_ci device_remove_software_node(priv->codec_dev); 189962306a36Sopenharmony_ci put_device(priv->codec_dev); 190062306a36Sopenharmony_ci} 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_cistatic struct platform_driver snd_byt_rt5640_mc_driver = { 190362306a36Sopenharmony_ci .driver = { 190462306a36Sopenharmony_ci .name = "bytcr_rt5640", 190562306a36Sopenharmony_ci }, 190662306a36Sopenharmony_ci .probe = snd_byt_rt5640_mc_probe, 190762306a36Sopenharmony_ci .remove_new = snd_byt_rt5640_mc_remove, 190862306a36Sopenharmony_ci}; 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_cimodule_platform_driver(snd_byt_rt5640_mc_driver); 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver"); 191362306a36Sopenharmony_ciMODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>"); 191462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 191562306a36Sopenharmony_ciMODULE_ALIAS("platform:bytcr_rt5640"); 1916