Path: blob/master/sound/soc/intel/boards/bytcr_rt5640.c
26493 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* byt_cr_dpcm_rt5640.c - ASoc Machine driver for Intel Byt CR platform3*4* Copyright (C) 2014 Intel Corp5* Author: Subhransu S. Prusty <[email protected]>6* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~7*8* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~9*/1011#include <linux/i2c.h>12#include <linux/init.h>13#include <linux/module.h>14#include <linux/moduleparam.h>15#include <linux/platform_device.h>16#include <linux/acpi.h>17#include <linux/clk.h>18#include <linux/device.h>19#include <linux/device/bus.h>20#include <linux/dmi.h>21#include <linux/gpio/consumer.h>22#include <linux/gpio/machine.h>23#include <linux/input.h>24#include <linux/slab.h>25#include <sound/pcm.h>26#include <sound/pcm_params.h>27#include <sound/soc.h>28#include <sound/jack.h>29#include <sound/soc-acpi.h>30#include <dt-bindings/sound/rt5640.h>31#include "../../codecs/rt5640.h"32#include "../atom/sst-atom-controls.h"33#include "../common/soc-intel-quirks.h"3435#define BYT_RT5640_FALLBACK_CODEC_DEV_NAME "i2c-rt5640"3637enum {38BYT_RT5640_DMIC1_MAP,39BYT_RT5640_DMIC2_MAP,40BYT_RT5640_IN1_MAP,41BYT_RT5640_IN3_MAP,42BYT_RT5640_NO_INTERNAL_MIC_MAP,43};4445#define RT5640_JD_SRC_EXT_GPIO 0x0f4647enum {48BYT_RT5640_JD_SRC_GPIO1 = (RT5640_JD_SRC_GPIO1 << 4),49BYT_RT5640_JD_SRC_JD1_IN4P = (RT5640_JD_SRC_JD1_IN4P << 4),50BYT_RT5640_JD_SRC_JD2_IN4N = (RT5640_JD_SRC_JD2_IN4N << 4),51BYT_RT5640_JD_SRC_GPIO2 = (RT5640_JD_SRC_GPIO2 << 4),52BYT_RT5640_JD_SRC_GPIO3 = (RT5640_JD_SRC_GPIO3 << 4),53BYT_RT5640_JD_SRC_GPIO4 = (RT5640_JD_SRC_GPIO4 << 4),54BYT_RT5640_JD_SRC_EXT_GPIO = (RT5640_JD_SRC_EXT_GPIO << 4)55};5657enum {58BYT_RT5640_OVCD_TH_600UA = (6 << 8),59BYT_RT5640_OVCD_TH_1500UA = (15 << 8),60BYT_RT5640_OVCD_TH_2000UA = (20 << 8),61};6263enum {64BYT_RT5640_OVCD_SF_0P5 = (RT5640_OVCD_SF_0P5 << 13),65BYT_RT5640_OVCD_SF_0P75 = (RT5640_OVCD_SF_0P75 << 13),66BYT_RT5640_OVCD_SF_1P0 = (RT5640_OVCD_SF_1P0 << 13),67BYT_RT5640_OVCD_SF_1P5 = (RT5640_OVCD_SF_1P5 << 13),68};6970#define BYT_RT5640_MAP(quirk) ((quirk) & GENMASK(3, 0))71#define BYT_RT5640_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4)72#define BYT_RT5640_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8)73#define BYT_RT5640_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13)74#define BYT_RT5640_JD_NOT_INV BIT(16)75#define BYT_RT5640_MONO_SPEAKER BIT(17)76#define BYT_RT5640_DIFF_MIC BIT(18) /* default is single-ended */77#define BYT_RT5640_SSP2_AIF2 BIT(19) /* default is using AIF1 */78#define BYT_RT5640_SSP0_AIF1 BIT(20)79#define BYT_RT5640_SSP0_AIF2 BIT(21)80#define BYT_RT5640_MCLK_EN BIT(22)81#define BYT_RT5640_MCLK_25MHZ BIT(23)82#define BYT_RT5640_NO_SPEAKERS BIT(24)83#define BYT_RT5640_LINEOUT BIT(25)84#define BYT_RT5640_LINEOUT_AS_HP2 BIT(26)85#define BYT_RT5640_HSMIC2_ON_IN1 BIT(27)86#define BYT_RT5640_JD_HP_ELITEP_1000G2 BIT(28)87#define BYT_RT5640_USE_AMCR0F28 BIT(29)88#define BYT_RT5640_SWAPPED_SPEAKERS BIT(30)8990#define BYTCR_INPUT_DEFAULTS \91(BYT_RT5640_IN3_MAP | \92BYT_RT5640_JD_SRC_JD1_IN4P | \93BYT_RT5640_OVCD_TH_2000UA | \94BYT_RT5640_OVCD_SF_0P75 | \95BYT_RT5640_DIFF_MIC)9697/* in-diff or dmic-pin + jdsrc + ovcd-th + -sf + jd-inv + terminating entry */98#define MAX_NO_PROPS 699100struct byt_rt5640_private {101struct snd_soc_jack jack;102struct snd_soc_jack jack2;103struct rt5640_set_jack_data jack_data;104struct gpio_desc *hsmic_detect;105struct clk *mclk;106struct device *codec_dev;107};108static bool is_bytcr;109110static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;111static int quirk_override = -1;112module_param_named(quirk, quirk_override, int, 0444);113MODULE_PARM_DESC(quirk, "Board-specific quirk override");114115static void log_quirks(struct device *dev)116{117int map;118bool has_mclk = false;119bool has_ssp0 = false;120bool has_ssp0_aif1 = false;121bool has_ssp0_aif2 = false;122bool has_ssp2_aif2 = false;123124map = BYT_RT5640_MAP(byt_rt5640_quirk);125switch (map) {126case BYT_RT5640_DMIC1_MAP:127dev_info(dev, "quirk DMIC1_MAP enabled\n");128break;129case BYT_RT5640_DMIC2_MAP:130dev_info(dev, "quirk DMIC2_MAP enabled\n");131break;132case BYT_RT5640_IN1_MAP:133dev_info(dev, "quirk IN1_MAP enabled\n");134break;135case BYT_RT5640_IN3_MAP:136dev_info(dev, "quirk IN3_MAP enabled\n");137break;138case BYT_RT5640_NO_INTERNAL_MIC_MAP:139dev_info(dev, "quirk NO_INTERNAL_MIC_MAP enabled\n");140break;141default:142dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map);143break;144}145if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)146dev_info(dev, "quirk HSMIC2_ON_IN1 enabled\n");147if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {148dev_info(dev, "quirk realtek,jack-detect-source %ld\n",149BYT_RT5640_JDSRC(byt_rt5640_quirk));150dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n",151BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100);152dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n",153BYT_RT5640_OVCD_SF(byt_rt5640_quirk));154}155if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)156dev_info(dev, "quirk JD_NOT_INV enabled\n");157if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)158dev_info(dev, "quirk JD_HP_ELITEPAD_1000G2 enabled\n");159if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)160dev_info(dev, "quirk MONO_SPEAKER enabled\n");161if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)162dev_info(dev, "quirk NO_SPEAKERS enabled\n");163if (byt_rt5640_quirk & BYT_RT5640_SWAPPED_SPEAKERS)164dev_info(dev, "quirk SWAPPED_SPEAKERS enabled\n");165if (byt_rt5640_quirk & BYT_RT5640_LINEOUT)166dev_info(dev, "quirk LINEOUT enabled\n");167if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)168dev_info(dev, "quirk LINEOUT_AS_HP2 enabled\n");169if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)170dev_info(dev, "quirk DIFF_MIC enabled\n");171if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {172dev_info(dev, "quirk SSP0_AIF1 enabled\n");173has_ssp0 = true;174has_ssp0_aif1 = true;175}176if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {177dev_info(dev, "quirk SSP0_AIF2 enabled\n");178has_ssp0 = true;179has_ssp0_aif2 = true;180}181if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {182dev_info(dev, "quirk SSP2_AIF2 enabled\n");183has_ssp2_aif2 = true;184}185if (is_bytcr && !has_ssp0)186dev_err(dev, "Invalid routing, bytcr detected but no SSP0-based quirk, audio cannot work with SSP2 on bytcr\n");187if (has_ssp0_aif1 && has_ssp0_aif2)188dev_err(dev, "Invalid routing, SSP0 cannot be connected to both AIF1 and AIF2\n");189if (has_ssp0 && has_ssp2_aif2)190dev_err(dev, "Invalid routing, cannot have both SSP0 and SSP2 connected to codec\n");191192if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {193dev_info(dev, "quirk MCLK_EN enabled\n");194has_mclk = true;195}196if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) {197if (has_mclk)198dev_info(dev, "quirk MCLK_25MHZ enabled\n");199else200dev_err(dev, "quirk MCLK_25MHZ enabled but quirk MCLK not selected, will be ignored\n");201}202}203204static int byt_rt5640_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,205int rate)206{207int ret;208209/* Configure the PLL before selecting it */210if (!(byt_rt5640_quirk & BYT_RT5640_MCLK_EN)) {211/* use bitclock as PLL input */212if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||213(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {214/* 2x16 bit slots on SSP0 */215ret = snd_soc_dai_set_pll(codec_dai, 0,216RT5640_PLL1_S_BCLK1,217rate * 32, rate * 512);218} else {219/* 2x15 bit slots on SSP2 */220ret = snd_soc_dai_set_pll(codec_dai, 0,221RT5640_PLL1_S_BCLK1,222rate * 50, rate * 512);223}224} else {225if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) {226ret = snd_soc_dai_set_pll(codec_dai, 0,227RT5640_PLL1_S_MCLK,22825000000, rate * 512);229} else {230ret = snd_soc_dai_set_pll(codec_dai, 0,231RT5640_PLL1_S_MCLK,23219200000, rate * 512);233}234}235236if (ret < 0) {237dev_err(codec_dai->component->dev, "can't set pll: %d\n", ret);238return ret;239}240241ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1,242rate * 512, SND_SOC_CLOCK_IN);243if (ret < 0) {244dev_err(codec_dai->component->dev, "can't set clock %d\n", ret);245return ret;246}247248return 0;249}250251#define BYT_CODEC_DAI1 "rt5640-aif1"252#define BYT_CODEC_DAI2 "rt5640-aif2"253254static struct snd_soc_dai *byt_rt5640_get_codec_dai(struct snd_soc_dapm_context *dapm)255{256struct snd_soc_card *card = dapm->card;257struct snd_soc_dai *codec_dai;258259codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);260if (!codec_dai)261codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);262if (!codec_dai)263dev_err(card->dev, "Error codec dai not found\n");264265return codec_dai;266}267268static int platform_clock_control(struct snd_soc_dapm_widget *w,269struct snd_kcontrol *k, int event)270{271struct snd_soc_dapm_context *dapm = w->dapm;272struct snd_soc_card *card = dapm->card;273struct snd_soc_dai *codec_dai;274struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);275int ret;276277codec_dai = byt_rt5640_get_codec_dai(dapm);278if (!codec_dai)279return -EIO;280281if (SND_SOC_DAPM_EVENT_ON(event)) {282ret = clk_prepare_enable(priv->mclk);283if (ret < 0) {284dev_err(card->dev, "could not configure MCLK state\n");285return ret;286}287ret = byt_rt5640_prepare_and_enable_pll1(codec_dai, 48000);288} else {289/*290* Set codec clock source to internal clock before291* turning off the platform clock. Codec needs clock292* for Jack detection and button press293*/294ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK,29548000 * 512,296SND_SOC_CLOCK_IN);297if (!ret)298clk_disable_unprepare(priv->mclk);299}300301if (ret < 0) {302dev_err(card->dev, "can't set codec sysclk: %d\n", ret);303return ret;304}305306return 0;307}308309static int byt_rt5640_event_lineout(struct snd_soc_dapm_widget *w,310struct snd_kcontrol *k, int event)311{312unsigned int gpio_ctrl3_val = RT5640_GP1_PF_OUT;313struct snd_soc_dai *codec_dai;314315if (!(byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2))316return 0;317318/*319* On devices which use line-out as a second headphones output,320* the codec's GPIO1 pin is used to enable an external HP-amp.321*/322323codec_dai = byt_rt5640_get_codec_dai(w->dapm);324if (!codec_dai)325return -EIO;326327if (SND_SOC_DAPM_EVENT_ON(event))328gpio_ctrl3_val |= RT5640_GP1_OUT_HI;329330snd_soc_component_update_bits(codec_dai->component, RT5640_GPIO_CTRL3,331RT5640_GP1_PF_MASK | RT5640_GP1_OUT_MASK, gpio_ctrl3_val);332333return 0;334}335336static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {337SND_SOC_DAPM_HP("Headphone", NULL),338SND_SOC_DAPM_MIC("Headset Mic", NULL),339SND_SOC_DAPM_MIC("Headset Mic 2", NULL),340SND_SOC_DAPM_MIC("Internal Mic", NULL),341SND_SOC_DAPM_SPK("Speaker", NULL),342SND_SOC_DAPM_LINE("Line Out", byt_rt5640_event_lineout),343SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,344platform_clock_control, SND_SOC_DAPM_PRE_PMU |345SND_SOC_DAPM_POST_PMD),346};347348static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {349{"Headphone", NULL, "Platform Clock"},350{"Headset Mic", NULL, "Platform Clock"},351{"Headset Mic", NULL, "MICBIAS1"},352{"IN2P", NULL, "Headset Mic"},353{"Headphone", NULL, "HPOL"},354{"Headphone", NULL, "HPOR"},355};356357static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {358{"Internal Mic", NULL, "Platform Clock"},359{"DMIC1", NULL, "Internal Mic"},360};361362static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {363{"Internal Mic", NULL, "Platform Clock"},364{"DMIC2", NULL, "Internal Mic"},365};366367static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {368{"Internal Mic", NULL, "Platform Clock"},369{"Internal Mic", NULL, "MICBIAS1"},370{"IN1P", NULL, "Internal Mic"},371};372373static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = {374{"Internal Mic", NULL, "Platform Clock"},375{"Internal Mic", NULL, "MICBIAS1"},376{"IN3P", NULL, "Internal Mic"},377};378379static const struct snd_soc_dapm_route byt_rt5640_hsmic2_in1_map[] = {380{"Headset Mic 2", NULL, "Platform Clock"},381{"Headset Mic 2", NULL, "MICBIAS1"},382{"IN1P", NULL, "Headset Mic 2"},383};384385static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = {386{"ssp2 Tx", NULL, "codec_out0"},387{"ssp2 Tx", NULL, "codec_out1"},388{"codec_in0", NULL, "ssp2 Rx"},389{"codec_in1", NULL, "ssp2 Rx"},390391{"AIF1 Playback", NULL, "ssp2 Tx"},392{"ssp2 Rx", NULL, "AIF1 Capture"},393};394395static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif2_map[] = {396{"ssp2 Tx", NULL, "codec_out0"},397{"ssp2 Tx", NULL, "codec_out1"},398{"codec_in0", NULL, "ssp2 Rx"},399{"codec_in1", NULL, "ssp2 Rx"},400401{"AIF2 Playback", NULL, "ssp2 Tx"},402{"ssp2 Rx", NULL, "AIF2 Capture"},403};404405static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif1_map[] = {406{"ssp0 Tx", NULL, "modem_out"},407{"modem_in", NULL, "ssp0 Rx"},408409{"AIF1 Playback", NULL, "ssp0 Tx"},410{"ssp0 Rx", NULL, "AIF1 Capture"},411};412413static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = {414{"ssp0 Tx", NULL, "modem_out"},415{"modem_in", NULL, "ssp0 Rx"},416417{"AIF2 Playback", NULL, "ssp0 Tx"},418{"ssp0 Rx", NULL, "AIF2 Capture"},419};420421static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {422{"Speaker", NULL, "Platform Clock"},423{"Speaker", NULL, "SPOLP"},424{"Speaker", NULL, "SPOLN"},425{"Speaker", NULL, "SPORP"},426{"Speaker", NULL, "SPORN"},427};428429static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = {430{"Speaker", NULL, "Platform Clock"},431{"Speaker", NULL, "SPOLP"},432{"Speaker", NULL, "SPOLN"},433};434435static const struct snd_soc_dapm_route byt_rt5640_lineout_map[] = {436{"Line Out", NULL, "Platform Clock"},437{"Line Out", NULL, "LOUTR"},438{"Line Out", NULL, "LOUTL"},439};440441static const struct snd_kcontrol_new byt_rt5640_controls[] = {442SOC_DAPM_PIN_SWITCH("Headphone"),443SOC_DAPM_PIN_SWITCH("Headset Mic"),444SOC_DAPM_PIN_SWITCH("Headset Mic 2"),445SOC_DAPM_PIN_SWITCH("Internal Mic"),446SOC_DAPM_PIN_SWITCH("Speaker"),447SOC_DAPM_PIN_SWITCH("Line Out"),448};449450static struct snd_soc_jack_pin rt5640_pins[] = {451{452.pin = "Headphone",453.mask = SND_JACK_HEADPHONE,454},455{456.pin = "Headset Mic",457.mask = SND_JACK_MICROPHONE,458},459};460461static struct snd_soc_jack_pin rt5640_pins2[] = {462{463/* The 2nd headset jack uses lineout with an external HP-amp */464.pin = "Line Out",465.mask = SND_JACK_HEADPHONE,466},467{468.pin = "Headset Mic 2",469.mask = SND_JACK_MICROPHONE,470},471};472473static struct snd_soc_jack_gpio rt5640_jack_gpio = {474.name = "hp-detect",475.report = SND_JACK_HEADSET,476.invert = true,477.debounce_time = 200,478};479480static struct snd_soc_jack_gpio rt5640_jack2_gpio = {481.name = "hp2-detect",482.report = SND_JACK_HEADSET,483.invert = true,484.debounce_time = 200,485};486487static const struct acpi_gpio_params acpi_gpio0 = { 0, 0, false };488static const struct acpi_gpio_params acpi_gpio1 = { 1, 0, false };489static const struct acpi_gpio_params acpi_gpio2 = { 2, 0, false };490491static const struct acpi_gpio_mapping byt_rt5640_hp_elitepad_1000g2_gpios[] = {492{ "hp-detect-gpios", &acpi_gpio0, 1, },493{ "headset-mic-detect-gpios", &acpi_gpio1, 1, },494{ "hp2-detect-gpios", &acpi_gpio2, 1, },495{ },496};497498static int byt_rt5640_hp_elitepad_1000g2_jack1_check(void *data)499{500struct byt_rt5640_private *priv = data;501int jack_status, mic_status;502503jack_status = gpiod_get_value_cansleep(rt5640_jack_gpio.desc);504if (jack_status)505return 0;506507mic_status = gpiod_get_value_cansleep(priv->hsmic_detect);508if (mic_status)509return SND_JACK_HEADPHONE;510else511return SND_JACK_HEADSET;512}513514static int byt_rt5640_hp_elitepad_1000g2_jack2_check(void *data)515{516struct snd_soc_component *component = data;517int jack_status, report;518519jack_status = gpiod_get_value_cansleep(rt5640_jack2_gpio.desc);520if (jack_status)521return 0;522523rt5640_enable_micbias1_for_ovcd(component);524report = rt5640_detect_headset(component, rt5640_jack2_gpio.desc);525rt5640_disable_micbias1_for_ovcd(component);526527return report;528}529530static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,531struct snd_pcm_hw_params *params)532{533struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);534struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);535536return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params));537}538539/* Please keep this list alphabetically sorted */540static const struct dmi_system_id byt_rt5640_quirk_table[] = {541{ /* Acer Iconia One 7 B1-750 */542.matches = {543DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),544DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "VESPA2"),545},546.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |547BYT_RT5640_JD_SRC_JD1_IN4P |548BYT_RT5640_OVCD_TH_1500UA |549BYT_RT5640_OVCD_SF_0P75 |550BYT_RT5640_SSP0_AIF1 |551BYT_RT5640_MCLK_EN),552},553{ /* Acer Iconia Tab 8 W1-810 */554.matches = {555DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),556DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Iconia W1-810"),557},558.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |559BYT_RT5640_JD_SRC_JD1_IN4P |560BYT_RT5640_OVCD_TH_1500UA |561BYT_RT5640_OVCD_SF_0P75 |562BYT_RT5640_SSP0_AIF1 |563BYT_RT5640_MCLK_EN),564},565{ /* Acer One 10 S1002 */566.matches = {567DMI_MATCH(DMI_SYS_VENDOR, "Acer"),568DMI_MATCH(DMI_PRODUCT_NAME, "One S1002"),569},570.driver_data = (void *)(BYT_RT5640_IN1_MAP |571BYT_RT5640_JD_SRC_JD2_IN4N |572BYT_RT5640_OVCD_TH_2000UA |573BYT_RT5640_OVCD_SF_0P75 |574BYT_RT5640_DIFF_MIC |575BYT_RT5640_SSP0_AIF2 |576BYT_RT5640_MCLK_EN),577},578{ /* Acer Aspire SW3-013 */579.matches = {580DMI_MATCH(DMI_SYS_VENDOR, "Acer"),581DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW3-013"),582},583.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |584BYT_RT5640_JD_SRC_JD2_IN4N |585BYT_RT5640_OVCD_TH_2000UA |586BYT_RT5640_OVCD_SF_0P75 |587BYT_RT5640_DIFF_MIC |588BYT_RT5640_SSP0_AIF1 |589BYT_RT5640_MCLK_EN),590},591{592.matches = {593DMI_MATCH(DMI_SYS_VENDOR, "Acer"),594DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),595},596.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |597BYT_RT5640_JD_SRC_JD2_IN4N |598BYT_RT5640_OVCD_TH_2000UA |599BYT_RT5640_OVCD_SF_0P75 |600BYT_RT5640_SSP0_AIF1 |601BYT_RT5640_MCLK_EN),602},603{604/* Advantech MICA-071 */605.matches = {606DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"),607DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"),608},609/* OVCD Th = 1500uA to reliable detect head-phones vs -set */610.driver_data = (void *)(BYT_RT5640_IN3_MAP |611BYT_RT5640_JD_SRC_JD2_IN4N |612BYT_RT5640_OVCD_TH_1500UA |613BYT_RT5640_OVCD_SF_0P75 |614BYT_RT5640_MONO_SPEAKER |615BYT_RT5640_DIFF_MIC |616BYT_RT5640_MCLK_EN),617},618{619.matches = {620DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),621DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 80 Cesium"),622},623.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |624BYT_RT5640_MONO_SPEAKER |625BYT_RT5640_SSP0_AIF1 |626BYT_RT5640_MCLK_EN),627},628{629.matches = {630DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),631DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 CESIUM"),632},633.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |634BYT_RT5640_JD_NOT_INV |635BYT_RT5640_DIFF_MIC |636BYT_RT5640_SSP0_AIF1 |637BYT_RT5640_MCLK_EN),638},639{640.matches = {641DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),642DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"),643},644.driver_data = (void *)(BYT_RT5640_IN1_MAP |645BYT_RT5640_JD_SRC_JD2_IN4N |646BYT_RT5640_OVCD_TH_2000UA |647BYT_RT5640_OVCD_SF_0P75 |648BYT_RT5640_SSP0_AIF1 |649BYT_RT5640_MCLK_EN),650},651{652.matches = {653DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),654DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),655},656.driver_data = (void *)(BYT_RT5640_IN1_MAP |657BYT_RT5640_JD_SRC_JD2_IN4N |658BYT_RT5640_OVCD_TH_2000UA |659BYT_RT5640_OVCD_SF_0P75 |660BYT_RT5640_SSP0_AIF1 |661BYT_RT5640_MCLK_EN |662BYT_RT5640_USE_AMCR0F28),663},664{665/* Asus T100TAF, unlike other T100TA* models this one has a mono speaker */666.matches = {667DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),668DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),669},670.driver_data = (void *)(BYT_RT5640_IN1_MAP |671BYT_RT5640_JD_SRC_JD2_IN4N |672BYT_RT5640_OVCD_TH_2000UA |673BYT_RT5640_OVCD_SF_0P75 |674BYT_RT5640_MONO_SPEAKER |675BYT_RT5640_DIFF_MIC |676BYT_RT5640_SSP0_AIF2 |677BYT_RT5640_MCLK_EN),678},679{680/* Asus T100TA and T100TAM, must come after T100TAF (mono spk) match */681.matches = {682DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),683DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"),684},685.driver_data = (void *)(BYT_RT5640_IN1_MAP |686BYT_RT5640_JD_SRC_JD2_IN4N |687BYT_RT5640_OVCD_TH_2000UA |688BYT_RT5640_OVCD_SF_0P75 |689BYT_RT5640_MCLK_EN),690},691{692.matches = {693DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),694DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),695},696.driver_data = (void *)(BYT_RT5640_IN1_MAP |697BYT_RT5640_JD_SRC_EXT_GPIO |698BYT_RT5640_OVCD_TH_2000UA |699BYT_RT5640_OVCD_SF_0P75 |700BYT_RT5640_SSP0_AIF1 |701BYT_RT5640_MCLK_EN |702BYT_RT5640_USE_AMCR0F28),703},704{ /* Chuwi Vi8 (CWI506) */705.matches = {706DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),707DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"),708/* The above are too generic, also match BIOS info */709DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),710},711.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |712BYT_RT5640_MONO_SPEAKER |713BYT_RT5640_SSP0_AIF1 |714BYT_RT5640_MCLK_EN),715},716{ /* Chuwi Vi8 dual-boot (CWI506) */717.matches = {718DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),719DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"),720/* The above are too generic, also match BIOS info */721DMI_MATCH(DMI_BIOS_VERSION, "CHUWI2.D86JHBNR02"),722},723.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |724BYT_RT5640_MONO_SPEAKER |725BYT_RT5640_SSP0_AIF1 |726BYT_RT5640_MCLK_EN),727},728{729/* Chuwi Vi10 (CWI505) */730.matches = {731DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),732DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"),733DMI_MATCH(DMI_SYS_VENDOR, "ilife"),734DMI_MATCH(DMI_PRODUCT_NAME, "S165"),735},736.driver_data = (void *)(BYT_RT5640_IN1_MAP |737BYT_RT5640_JD_SRC_JD2_IN4N |738BYT_RT5640_OVCD_TH_2000UA |739BYT_RT5640_OVCD_SF_0P75 |740BYT_RT5640_DIFF_MIC |741BYT_RT5640_SSP0_AIF1 |742BYT_RT5640_MCLK_EN),743},744{745/* Chuwi Hi8 (CWI509) */746.matches = {747DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),748DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"),749DMI_MATCH(DMI_SYS_VENDOR, "ilife"),750DMI_MATCH(DMI_PRODUCT_NAME, "S806"),751},752.driver_data = (void *)(BYT_RT5640_IN1_MAP |753BYT_RT5640_JD_SRC_JD2_IN4N |754BYT_RT5640_OVCD_TH_2000UA |755BYT_RT5640_OVCD_SF_0P75 |756BYT_RT5640_MONO_SPEAKER |757BYT_RT5640_DIFF_MIC |758BYT_RT5640_SSP0_AIF1 |759BYT_RT5640_MCLK_EN),760},761{762.matches = {763DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),764DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),765},766.driver_data = (void *)(BYT_RT5640_DMIC1_MAP),767},768{ /* Connect Tablet 9 */769.matches = {770DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Connect"),771DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Tablet 9"),772},773.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |774BYT_RT5640_MONO_SPEAKER |775BYT_RT5640_SSP0_AIF1 |776BYT_RT5640_MCLK_EN),777},778{779.matches = {780DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),781DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"),782},783.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |784BYT_RT5640_JD_SRC_JD2_IN4N |785BYT_RT5640_OVCD_TH_2000UA |786BYT_RT5640_OVCD_SF_0P75 |787BYT_RT5640_MONO_SPEAKER |788BYT_RT5640_MCLK_EN),789},790{ /* Estar Beauty HD MID 7316R */791.matches = {792DMI_MATCH(DMI_SYS_VENDOR, "Estar"),793DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"),794},795.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |796BYT_RT5640_MONO_SPEAKER |797BYT_RT5640_SSP0_AIF1 |798BYT_RT5640_MCLK_EN),799},800{ /* Glavey TM800A550L */801.matches = {802DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),803DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),804/* Above strings are too generic, also match on BIOS version */805DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),806},807.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |808BYT_RT5640_SSP0_AIF1 |809BYT_RT5640_MCLK_EN),810},811{812.matches = {813DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),814DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),815},816.driver_data = (void *)(BYT_RT5640_DMIC2_MAP |817BYT_RT5640_MCLK_EN |818BYT_RT5640_LINEOUT |819BYT_RT5640_LINEOUT_AS_HP2 |820BYT_RT5640_HSMIC2_ON_IN1 |821BYT_RT5640_JD_HP_ELITEP_1000G2),822},823{ /* HP Pavilion x2 10-k0XX, 10-n0XX */824.matches = {825DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),826DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),827},828.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |829BYT_RT5640_JD_SRC_JD2_IN4N |830BYT_RT5640_OVCD_TH_1500UA |831BYT_RT5640_OVCD_SF_0P75 |832BYT_RT5640_SSP0_AIF1 |833BYT_RT5640_MCLK_EN),834},835{ /* HP Pavilion x2 10-p0XX */836.matches = {837DMI_MATCH(DMI_SYS_VENDOR, "HP"),838DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),839},840.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |841BYT_RT5640_JD_SRC_JD1_IN4P |842BYT_RT5640_OVCD_TH_2000UA |843BYT_RT5640_OVCD_SF_0P75 |844BYT_RT5640_MCLK_EN),845},846{ /* HP Pro Tablet 408 */847.matches = {848DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),849DMI_MATCH(DMI_PRODUCT_NAME, "HP Pro Tablet 408"),850},851.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |852BYT_RT5640_JD_SRC_JD2_IN4N |853BYT_RT5640_OVCD_TH_1500UA |854BYT_RT5640_OVCD_SF_0P75 |855BYT_RT5640_SSP0_AIF1 |856BYT_RT5640_MCLK_EN),857},858{ /* HP Stream 7 */859.matches = {860DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),861DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 7 Tablet"),862},863.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |864BYT_RT5640_MONO_SPEAKER |865BYT_RT5640_JD_NOT_INV |866BYT_RT5640_SSP0_AIF1 |867BYT_RT5640_MCLK_EN),868},869{ /* HP Stream 8 */870.matches = {871DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),872DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 8 Tablet"),873},874.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |875BYT_RT5640_JD_NOT_INV |876BYT_RT5640_SSP0_AIF1 |877BYT_RT5640_MCLK_EN),878},879{ /* I.T.Works TW891 */880.matches = {881DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),882DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"),883DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),884DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),885},886.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |887BYT_RT5640_MONO_SPEAKER |888BYT_RT5640_SSP0_AIF1 |889BYT_RT5640_MCLK_EN),890},891{ /* Lamina I8270 / T701BR.SE */892.matches = {893DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Lamina"),894DMI_EXACT_MATCH(DMI_BOARD_NAME, "T701BR.SE"),895},896.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |897BYT_RT5640_MONO_SPEAKER |898BYT_RT5640_JD_NOT_INV |899BYT_RT5640_SSP0_AIF1 |900BYT_RT5640_MCLK_EN),901},902{ /* Lenovo Miix 2 8 */903.matches = {904DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),905DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "20326"),906DMI_EXACT_MATCH(DMI_BOARD_NAME, "Hiking"),907},908.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |909BYT_RT5640_JD_SRC_JD2_IN4N |910BYT_RT5640_OVCD_TH_2000UA |911BYT_RT5640_OVCD_SF_0P75 |912BYT_RT5640_MONO_SPEAKER |913BYT_RT5640_MCLK_EN),914},915{ /* Lenovo Miix 3-830 */916.matches = {917DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),918DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 3-830"),919},920.driver_data = (void *)(BYT_RT5640_IN1_MAP |921BYT_RT5640_JD_SRC_JD2_IN4N |922BYT_RT5640_OVCD_TH_2000UA |923BYT_RT5640_OVCD_SF_0P75 |924BYT_RT5640_MONO_SPEAKER |925BYT_RT5640_DIFF_MIC |926BYT_RT5640_SSP0_AIF1 |927BYT_RT5640_MCLK_EN),928},929{ /* Linx Linx7 tablet */930.matches = {931DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LINX"),932DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LINX7"),933},934.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |935BYT_RT5640_MONO_SPEAKER |936BYT_RT5640_JD_NOT_INV |937BYT_RT5640_SSP0_AIF1 |938BYT_RT5640_MCLK_EN),939},940{941/* Medion Lifetab S10346 */942.matches = {943DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),944DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),945/* Above strings are much too generic, also match on BIOS date */946DMI_MATCH(DMI_BIOS_DATE, "10/22/2015"),947},948.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |949BYT_RT5640_SWAPPED_SPEAKERS |950BYT_RT5640_SSP0_AIF1 |951BYT_RT5640_MCLK_EN),952},953{ /* Mele PCG03 Mini PC */954.matches = {955DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"),956DMI_EXACT_MATCH(DMI_BOARD_NAME, "Mini PC"),957},958.driver_data = (void *)(BYT_RT5640_NO_INTERNAL_MIC_MAP |959BYT_RT5640_NO_SPEAKERS |960BYT_RT5640_SSP0_AIF1),961},962{ /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */963.matches = {964DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),965DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"),966},967.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |968BYT_RT5640_MONO_SPEAKER |969BYT_RT5640_SSP0_AIF1 |970BYT_RT5640_MCLK_EN),971},972{973/* MPMAN MPWIN895CL */974.matches = {975DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MPMAN"),976DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MPWIN8900CL"),977},978.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |979BYT_RT5640_MONO_SPEAKER |980BYT_RT5640_SSP0_AIF1 |981BYT_RT5640_MCLK_EN),982},983{ /* MSI S100 tablet */984.matches = {985DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),986DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "S100"),987},988.driver_data = (void *)(BYT_RT5640_IN1_MAP |989BYT_RT5640_JD_SRC_JD2_IN4N |990BYT_RT5640_OVCD_TH_2000UA |991BYT_RT5640_OVCD_SF_0P75 |992BYT_RT5640_MONO_SPEAKER |993BYT_RT5640_DIFF_MIC |994BYT_RT5640_MCLK_EN),995},996{ /* Nuvison/TMax TM800W560 */997.matches = {998DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TMAX"),999DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TM800W560L"),1000},1001.driver_data = (void *)(BYT_RT5640_IN1_MAP |1002BYT_RT5640_JD_SRC_JD2_IN4N |1003BYT_RT5640_OVCD_TH_2000UA |1004BYT_RT5640_OVCD_SF_0P75 |1005BYT_RT5640_JD_NOT_INV |1006BYT_RT5640_DIFF_MIC |1007BYT_RT5640_SSP0_AIF1 |1008BYT_RT5640_MCLK_EN),1009},1010{ /* Onda v975w */1011.matches = {1012DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1013DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1014/* The above are too generic, also match BIOS info */1015DMI_EXACT_MATCH(DMI_BIOS_VERSION, "5.6.5"),1016DMI_EXACT_MATCH(DMI_BIOS_DATE, "07/25/2014"),1017},1018.driver_data = (void *)(BYT_RT5640_IN1_MAP |1019BYT_RT5640_JD_SRC_JD2_IN4N |1020BYT_RT5640_OVCD_TH_2000UA |1021BYT_RT5640_OVCD_SF_0P75 |1022BYT_RT5640_DIFF_MIC |1023BYT_RT5640_MCLK_EN),1024},1025{ /* Pipo W4 */1026.matches = {1027DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1028DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1029/* The above are too generic, also match BIOS info */1030DMI_MATCH(DMI_BIOS_VERSION, "V8L_WIN32_CHIPHD"),1031},1032.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |1033BYT_RT5640_MONO_SPEAKER |1034BYT_RT5640_SSP0_AIF1 |1035BYT_RT5640_MCLK_EN),1036},1037{ /* Point of View Mobii TAB-P800W (V2.0) */1038.matches = {1039DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1040DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1041/* The above are too generic, also match BIOS info */1042DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),1043DMI_EXACT_MATCH(DMI_BIOS_DATE, "10/24/2014"),1044},1045.driver_data = (void *)(BYT_RT5640_IN1_MAP |1046BYT_RT5640_JD_SRC_JD2_IN4N |1047BYT_RT5640_OVCD_TH_2000UA |1048BYT_RT5640_OVCD_SF_0P75 |1049BYT_RT5640_MONO_SPEAKER |1050BYT_RT5640_DIFF_MIC |1051BYT_RT5640_SSP0_AIF2 |1052BYT_RT5640_MCLK_EN),1053},1054{ /* Point of View Mobii TAB-P800W (V2.1) */1055.matches = {1056DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1057DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1058/* The above are too generic, also match BIOS info */1059DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),1060DMI_EXACT_MATCH(DMI_BIOS_DATE, "08/22/2014"),1061},1062.driver_data = (void *)(BYT_RT5640_IN1_MAP |1063BYT_RT5640_JD_SRC_JD2_IN4N |1064BYT_RT5640_OVCD_TH_2000UA |1065BYT_RT5640_OVCD_SF_0P75 |1066BYT_RT5640_MONO_SPEAKER |1067BYT_RT5640_DIFF_MIC |1068BYT_RT5640_SSP0_AIF2 |1069BYT_RT5640_MCLK_EN),1070},1071{ /* Point of View Mobii TAB-P1005W-232 (V2.0) */1072.matches = {1073DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "POV"),1074DMI_EXACT_MATCH(DMI_BOARD_NAME, "I102A"),1075},1076.driver_data = (void *)(BYT_RT5640_IN1_MAP |1077BYT_RT5640_JD_SRC_JD2_IN4N |1078BYT_RT5640_OVCD_TH_2000UA |1079BYT_RT5640_OVCD_SF_0P75 |1080BYT_RT5640_DIFF_MIC |1081BYT_RT5640_SSP0_AIF1 |1082BYT_RT5640_MCLK_EN),1083},1084{1085/* Prowise PT301 */1086.matches = {1087DMI_MATCH(DMI_SYS_VENDOR, "Prowise"),1088DMI_MATCH(DMI_PRODUCT_NAME, "PT301"),1089},1090.driver_data = (void *)(BYT_RT5640_IN1_MAP |1091BYT_RT5640_JD_SRC_JD2_IN4N |1092BYT_RT5640_OVCD_TH_2000UA |1093BYT_RT5640_OVCD_SF_0P75 |1094BYT_RT5640_DIFF_MIC |1095BYT_RT5640_SSP0_AIF1 |1096BYT_RT5640_MCLK_EN),1097},1098{1099/* Teclast X89 */1100.matches = {1101DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),1102DMI_MATCH(DMI_BOARD_NAME, "tPAD"),1103},1104.driver_data = (void *)(BYT_RT5640_IN3_MAP |1105BYT_RT5640_JD_SRC_JD1_IN4P |1106BYT_RT5640_OVCD_TH_2000UA |1107BYT_RT5640_OVCD_SF_1P0 |1108BYT_RT5640_SSP0_AIF1 |1109BYT_RT5640_MCLK_EN),1110},1111{ /* Toshiba Satellite Click Mini L9W-B */1112.matches = {1113DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),1114DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"),1115},1116.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |1117BYT_RT5640_JD_SRC_JD2_IN4N |1118BYT_RT5640_OVCD_TH_1500UA |1119BYT_RT5640_OVCD_SF_0P75 |1120BYT_RT5640_SSP0_AIF1 |1121BYT_RT5640_MCLK_EN),1122},1123{ /* Toshiba Encore WT8-A */1124.matches = {1125DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),1126DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT8-A"),1127},1128.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |1129BYT_RT5640_JD_SRC_JD2_IN4N |1130BYT_RT5640_OVCD_TH_2000UA |1131BYT_RT5640_OVCD_SF_0P75 |1132BYT_RT5640_JD_NOT_INV |1133BYT_RT5640_MCLK_EN),1134},1135{ /* Toshiba Encore WT10-A */1136.matches = {1137DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),1138DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT10-A-103"),1139},1140.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |1141BYT_RT5640_JD_SRC_JD1_IN4P |1142BYT_RT5640_OVCD_TH_2000UA |1143BYT_RT5640_OVCD_SF_0P75 |1144BYT_RT5640_SSP0_AIF2 |1145BYT_RT5640_MCLK_EN),1146},1147{1148/* Vexia Edu Atla 10 tablet 5V version */1149.matches = {1150/* Having all 3 of these not set is somewhat unique */1151DMI_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),1152DMI_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."),1153DMI_MATCH(DMI_BOARD_NAME, "To be filled by O.E.M."),1154/* Above strings are too generic, also match on BIOS date */1155DMI_MATCH(DMI_BIOS_DATE, "05/14/2015"),1156},1157.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |1158BYT_RT5640_JD_NOT_INV |1159BYT_RT5640_SSP0_AIF1 |1160BYT_RT5640_MCLK_EN),1161},1162{ /* Vexia Edu Atla 10 tablet 9V version */1163.matches = {1164DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1165DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1166/* Above strings are too generic, also match on BIOS date */1167DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),1168},1169.driver_data = (void *)(BYT_RT5640_IN1_MAP |1170BYT_RT5640_JD_SRC_JD2_IN4N |1171BYT_RT5640_OVCD_TH_2000UA |1172BYT_RT5640_OVCD_SF_0P75 |1173BYT_RT5640_DIFF_MIC |1174BYT_RT5640_SSP0_AIF2 |1175BYT_RT5640_MCLK_EN),1176},1177{ /* Voyo Winpad A15 */1178.matches = {1179DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1180DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1181/* Above strings are too generic, also match on BIOS date */1182DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"),1183},1184.driver_data = (void *)(BYT_RT5640_IN1_MAP |1185BYT_RT5640_JD_SRC_JD2_IN4N |1186BYT_RT5640_OVCD_TH_2000UA |1187BYT_RT5640_OVCD_SF_0P75 |1188BYT_RT5640_DIFF_MIC |1189BYT_RT5640_MCLK_EN),1190},1191{ /* Catch-all for generic Insyde tablets, must be last */1192.matches = {1193DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),1194},1195.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |1196BYT_RT5640_MCLK_EN |1197BYT_RT5640_SSP0_AIF1),11981199},1200{}1201};12021203/*1204* Note this MUST be called before snd_soc_register_card(), so that the props1205* are in place before the codec component driver's probe function parses them.1206*/1207static int byt_rt5640_add_codec_device_props(struct device *i2c_dev,1208struct byt_rt5640_private *priv)1209{1210struct property_entry props[MAX_NO_PROPS] = {};1211struct fwnode_handle *fwnode;1212int cnt = 0;1213int ret;12141215switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {1216case BYT_RT5640_DMIC1_MAP:1217props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic1-data-pin",1218RT5640_DMIC1_DATA_PIN_IN1P);1219break;1220case BYT_RT5640_DMIC2_MAP:1221props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic2-data-pin",1222RT5640_DMIC2_DATA_PIN_IN1N);1223break;1224case BYT_RT5640_IN1_MAP:1225if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)1226props[cnt++] =1227PROPERTY_ENTRY_BOOL("realtek,in1-differential");1228break;1229case BYT_RT5640_IN3_MAP:1230if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)1231props[cnt++] =1232PROPERTY_ENTRY_BOOL("realtek,in3-differential");1233break;1234}12351236if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {1237if (BYT_RT5640_JDSRC(byt_rt5640_quirk) != RT5640_JD_SRC_EXT_GPIO) {1238props[cnt++] = PROPERTY_ENTRY_U32(1239"realtek,jack-detect-source",1240BYT_RT5640_JDSRC(byt_rt5640_quirk));1241}12421243props[cnt++] = PROPERTY_ENTRY_U32(1244"realtek,over-current-threshold-microamp",1245BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100);12461247props[cnt++] = PROPERTY_ENTRY_U32(1248"realtek,over-current-scale-factor",1249BYT_RT5640_OVCD_SF(byt_rt5640_quirk));1250}12511252if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)1253props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");12541255fwnode = fwnode_create_software_node(props, NULL);1256if (IS_ERR(fwnode)) {1257/* put_device() is handled in caller */1258return PTR_ERR(fwnode);1259}12601261ret = device_add_software_node(i2c_dev, to_software_node(fwnode));12621263fwnode_handle_put(fwnode);12641265return ret;1266}12671268/* Some Android devs specify IRQs/GPIOS in a special AMCR0F28 ACPI device */1269static const struct acpi_gpio_params amcr0f28_jd_gpio = { 1, 0, false };12701271static const struct acpi_gpio_mapping amcr0f28_gpios[] = {1272{ "rt5640-jd-gpios", &amcr0f28_jd_gpio, 1 },1273{ }1274};12751276static int byt_rt5640_get_amcr0f28_settings(struct snd_soc_card *card)1277{1278struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);1279struct rt5640_set_jack_data *data = &priv->jack_data;1280struct acpi_device *adev;1281int ret = 0;12821283adev = acpi_dev_get_first_match_dev("AMCR0F28", "1", -1);1284if (!adev) {1285dev_err(card->dev, "error cannot find AMCR0F28 adev\n");1286return -ENOENT;1287}12881289data->codec_irq_override = acpi_dev_gpio_irq_get(adev, 0);1290if (data->codec_irq_override < 0) {1291ret = data->codec_irq_override;1292dev_err(card->dev, "error %d getting codec IRQ\n", ret);1293goto put_adev;1294}12951296if (BYT_RT5640_JDSRC(byt_rt5640_quirk) == RT5640_JD_SRC_EXT_GPIO) {1297acpi_dev_add_driver_gpios(adev, amcr0f28_gpios);1298data->jd_gpio = devm_fwnode_gpiod_get(card->dev, acpi_fwnode_handle(adev),1299"rt5640-jd", GPIOD_IN, "rt5640-jd");1300acpi_dev_remove_driver_gpios(adev);13011302if (IS_ERR(data->jd_gpio)) {1303ret = PTR_ERR(data->jd_gpio);1304dev_err(card->dev, "error %d getting jd GPIO\n", ret);1305}1306}13071308put_adev:1309acpi_dev_put(adev);1310return ret;1311}13121313static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)1314{1315struct snd_soc_card *card = runtime->card;1316struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);1317struct rt5640_set_jack_data *jack_data = &priv->jack_data;1318struct snd_soc_component *component = snd_soc_rtd_to_codec(runtime, 0)->component;1319const struct snd_soc_dapm_route *custom_map = NULL;1320int num_routes = 0;1321int ret;13221323card->dapm.idle_bias_off = true;1324jack_data->use_platform_clock = true;13251326/* Start with RC clk for jack-detect (we disable MCLK below) */1327if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)1328snd_soc_component_update_bits(component, RT5640_GLB_CLK,1329RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK);13301331rt5640_sel_asrc_clk_src(component,1332RT5640_DA_STEREO_FILTER |1333RT5640_DA_MONO_L_FILTER |1334RT5640_DA_MONO_R_FILTER |1335RT5640_AD_STEREO_FILTER |1336RT5640_AD_MONO_L_FILTER |1337RT5640_AD_MONO_R_FILTER,1338RT5640_CLK_SEL_ASRC);13391340ret = snd_soc_add_card_controls(card, byt_rt5640_controls,1341ARRAY_SIZE(byt_rt5640_controls));1342if (ret) {1343dev_err(card->dev, "unable to add card controls\n");1344return ret;1345}13461347switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {1348case BYT_RT5640_IN1_MAP:1349custom_map = byt_rt5640_intmic_in1_map;1350num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map);1351break;1352case BYT_RT5640_IN3_MAP:1353custom_map = byt_rt5640_intmic_in3_map;1354num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map);1355break;1356case BYT_RT5640_DMIC1_MAP:1357custom_map = byt_rt5640_intmic_dmic1_map;1358num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);1359break;1360case BYT_RT5640_DMIC2_MAP:1361custom_map = byt_rt5640_intmic_dmic2_map;1362num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);1363break;1364}13651366ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);1367if (ret)1368return ret;13691370if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) {1371ret = snd_soc_dapm_add_routes(&card->dapm,1372byt_rt5640_hsmic2_in1_map,1373ARRAY_SIZE(byt_rt5640_hsmic2_in1_map));1374if (ret)1375return ret;1376}13771378if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {1379ret = snd_soc_dapm_add_routes(&card->dapm,1380byt_rt5640_ssp2_aif2_map,1381ARRAY_SIZE(byt_rt5640_ssp2_aif2_map));1382} else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {1383ret = snd_soc_dapm_add_routes(&card->dapm,1384byt_rt5640_ssp0_aif1_map,1385ARRAY_SIZE(byt_rt5640_ssp0_aif1_map));1386} else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {1387ret = snd_soc_dapm_add_routes(&card->dapm,1388byt_rt5640_ssp0_aif2_map,1389ARRAY_SIZE(byt_rt5640_ssp0_aif2_map));1390} else {1391ret = snd_soc_dapm_add_routes(&card->dapm,1392byt_rt5640_ssp2_aif1_map,1393ARRAY_SIZE(byt_rt5640_ssp2_aif1_map));1394}1395if (ret)1396return ret;13971398if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {1399ret = snd_soc_dapm_add_routes(&card->dapm,1400byt_rt5640_mono_spk_map,1401ARRAY_SIZE(byt_rt5640_mono_spk_map));1402} else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) {1403ret = snd_soc_dapm_add_routes(&card->dapm,1404byt_rt5640_stereo_spk_map,1405ARRAY_SIZE(byt_rt5640_stereo_spk_map));1406}1407if (ret)1408return ret;14091410if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {1411ret = snd_soc_dapm_add_routes(&card->dapm,1412byt_rt5640_lineout_map,1413ARRAY_SIZE(byt_rt5640_lineout_map));1414if (ret)1415return ret;1416}14171418/*1419* The firmware might enable the clock at boot (this information1420* may or may not be reflected in the enable clock register).1421* To change the rate we must disable the clock first to cover1422* these cases. Due to common clock framework restrictions that1423* do not allow to disable a clock that has not been enabled,1424* we need to enable the clock first.1425*/1426ret = clk_prepare_enable(priv->mclk);1427if (!ret)1428clk_disable_unprepare(priv->mclk);14291430if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ)1431ret = clk_set_rate(priv->mclk, 25000000);1432else1433ret = clk_set_rate(priv->mclk, 19200000);1434if (ret) {1435dev_err(card->dev, "unable to set MCLK rate\n");1436return ret;1437}14381439if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {1440ret = snd_soc_card_jack_new_pins(card, "Headset",1441SND_JACK_HEADSET | SND_JACK_BTN_0,1442&priv->jack, rt5640_pins,1443ARRAY_SIZE(rt5640_pins));1444if (ret) {1445dev_err(card->dev, "Jack creation failed %d\n", ret);1446return ret;1447}1448snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,1449KEY_PLAYPAUSE);14501451if (byt_rt5640_quirk & BYT_RT5640_USE_AMCR0F28) {1452ret = byt_rt5640_get_amcr0f28_settings(card);1453if (ret)1454return ret;1455}14561457snd_soc_component_set_jack(component, &priv->jack, &priv->jack_data);1458}14591460if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {1461ret = snd_soc_card_jack_new_pins(card, "Headset",1462SND_JACK_HEADSET,1463&priv->jack, rt5640_pins,1464ARRAY_SIZE(rt5640_pins));1465if (ret)1466return ret;14671468ret = snd_soc_card_jack_new_pins(card, "Headset 2",1469SND_JACK_HEADSET,1470&priv->jack2, rt5640_pins2,1471ARRAY_SIZE(rt5640_pins2));1472if (ret)1473return ret;14741475rt5640_jack_gpio.data = priv;1476rt5640_jack_gpio.gpiod_dev = priv->codec_dev;1477rt5640_jack_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack1_check;1478ret = snd_soc_jack_add_gpios(&priv->jack, 1, &rt5640_jack_gpio);1479if (ret)1480return ret;14811482rt5640_set_ovcd_params(component);1483rt5640_jack2_gpio.data = component;1484rt5640_jack2_gpio.gpiod_dev = priv->codec_dev;1485rt5640_jack2_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack2_check;1486ret = snd_soc_jack_add_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);1487if (ret) {1488snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);1489return ret;1490}1491}14921493return 0;1494}14951496static void byt_rt5640_exit(struct snd_soc_pcm_runtime *runtime)1497{1498struct snd_soc_card *card = runtime->card;1499struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);15001501if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {1502snd_soc_jack_free_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);1503snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);1504}1505}15061507static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,1508struct snd_pcm_hw_params *params)1509{1510struct snd_interval *rate = hw_param_interval(params,1511SNDRV_PCM_HW_PARAM_RATE);1512struct snd_interval *channels = hw_param_interval(params,1513SNDRV_PCM_HW_PARAM_CHANNELS);1514int ret, bits;15151516/* The DSP will convert the FE rate to 48k, stereo */1517rate->min = rate->max = 48000;1518channels->min = channels->max = 2;15191520if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||1521(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {1522/* set SSP0 to 16-bit */1523params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);1524bits = 16;1525} else {1526/* set SSP2 to 24-bit */1527params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);1528bits = 24;1529}15301531/*1532* Default mode for SSP configuration is TDM 4 slot, override config1533* with explicit setting to I2S 2ch. The word length is set with1534* dai_set_tdm_slot() since there is no other API exposed1535*/1536ret = snd_soc_dai_set_fmt(snd_soc_rtd_to_cpu(rtd, 0),1537SND_SOC_DAIFMT_I2S |1538SND_SOC_DAIFMT_NB_NF |1539SND_SOC_DAIFMT_BP_FP);1540if (ret < 0) {1541dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);1542return ret;1543}15441545ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits);1546if (ret < 0) {1547dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);1548return ret;1549}15501551return 0;1552}15531554static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream)1555{1556return snd_pcm_hw_constraint_single(substream->runtime,1557SNDRV_PCM_HW_PARAM_RATE, 48000);1558}15591560static const struct snd_soc_ops byt_rt5640_aif1_ops = {1561.startup = byt_rt5640_aif1_startup,1562};15631564static const struct snd_soc_ops byt_rt5640_be_ssp2_ops = {1565.hw_params = byt_rt5640_aif1_hw_params,1566};15671568SND_SOC_DAILINK_DEF(dummy,1569DAILINK_COMP_ARRAY(COMP_DUMMY()));15701571SND_SOC_DAILINK_DEF(media,1572DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));15731574SND_SOC_DAILINK_DEF(deepbuffer,1575DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));15761577SND_SOC_DAILINK_DEF(ssp2_port,1578/* overwritten for ssp0 routing */1579DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));1580SND_SOC_DAILINK_DEF(ssp2_codec,1581DAILINK_COMP_ARRAY(COMP_CODEC(1582/* overwritten with HID */ "i2c-10EC5640:00",1583/* changed w/ quirk */ "rt5640-aif1")));15841585SND_SOC_DAILINK_DEF(platform,1586DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));15871588static struct snd_soc_dai_link byt_rt5640_dais[] = {1589[MERR_DPCM_AUDIO] = {1590.name = "Baytrail Audio Port",1591.stream_name = "Baytrail Audio",1592.nonatomic = true,1593.dynamic = 1,1594.ops = &byt_rt5640_aif1_ops,1595SND_SOC_DAILINK_REG(media, dummy, platform),1596},1597[MERR_DPCM_DEEP_BUFFER] = {1598.name = "Deep-Buffer Audio Port",1599.stream_name = "Deep-Buffer Audio",1600.nonatomic = true,1601.dynamic = 1,1602.playback_only = 1,1603.ops = &byt_rt5640_aif1_ops,1604SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),1605},1606/* back ends */1607{1608.name = "SSP2-Codec",1609.id = 0,1610.no_pcm = 1,1611.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF1612| SND_SOC_DAIFMT_CBC_CFC,1613.be_hw_params_fixup = byt_rt5640_codec_fixup,1614.init = byt_rt5640_init,1615.exit = byt_rt5640_exit,1616.ops = &byt_rt5640_be_ssp2_ops,1617SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),1618},1619};16201621/* SoC card */1622static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];1623#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)1624static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */1625#endif1626static char byt_rt5640_components[64]; /* = "cfg-spk:* cfg-mic:* ..." */16271628static int byt_rt5640_suspend(struct snd_soc_card *card)1629{1630struct snd_soc_component *component;16311632if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))1633return 0;16341635for_each_card_components(card, component) {1636if (!strcmp(component->name, byt_rt5640_codec_name)) {1637dev_dbg(component->dev, "disabling jack detect before suspend\n");1638snd_soc_component_set_jack(component, NULL, NULL);1639break;1640}1641}16421643return 0;1644}16451646static int byt_rt5640_resume(struct snd_soc_card *card)1647{1648struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);1649struct snd_soc_component *component;16501651if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))1652return 0;16531654for_each_card_components(card, component) {1655if (!strcmp(component->name, byt_rt5640_codec_name)) {1656dev_dbg(component->dev, "re-enabling jack detect after resume\n");1657snd_soc_component_set_jack(component, &priv->jack,1658&priv->jack_data);1659break;1660}1661}16621663return 0;1664}16651666/* use space before codec name to simplify card ID, and simplify driver name */1667#define SOF_CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */1668#define SOF_DRIVER_NAME "SOF"16691670#define CARD_NAME "bytcr-rt5640"1671#define DRIVER_NAME NULL /* card name will be used for driver name */16721673static struct snd_soc_card byt_rt5640_card = {1674.owner = THIS_MODULE,1675.dai_link = byt_rt5640_dais,1676.num_links = ARRAY_SIZE(byt_rt5640_dais),1677.dapm_widgets = byt_rt5640_widgets,1678.num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets),1679.dapm_routes = byt_rt5640_audio_map,1680.num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map),1681.fully_routed = true,1682.suspend_pre = byt_rt5640_suspend,1683.resume_post = byt_rt5640_resume,1684};16851686struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */1687u64 aif_value; /* 1: AIF1, 2: AIF2 */1688u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */1689};16901691static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)1692{1693struct device *dev = &pdev->dev;1694static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" };1695struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);1696__maybe_unused const char *spk_type;1697const struct dmi_system_id *dmi_id;1698const char *headset2_string = "";1699const char *lineout_string = "";1700struct byt_rt5640_private *priv;1701const char *platform_name;1702struct acpi_device *adev;1703struct device *codec_dev;1704const char *cfg_spk;1705bool sof_parent;1706int ret_val = 0;1707int dai_index = 0;1708int i, aif;17091710is_bytcr = false;1711priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);1712if (!priv)1713return -ENOMEM;17141715/* register the soc card */1716byt_rt5640_card.dev = dev;1717snd_soc_card_set_drvdata(&byt_rt5640_card, priv);17181719/* fix index of codec dai */1720for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {1721if (byt_rt5640_dais[i].num_codecs &&1722!strcmp(byt_rt5640_dais[i].codecs->name,1723"i2c-10EC5640:00")) {1724dai_index = i;1725break;1726}1727}17281729/* fixup codec name based on HID */1730adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);1731if (adev) {1732snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),1733"i2c-%s", acpi_dev_name(adev));1734byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;1735} else {1736dev_err(dev, "Error cannot find '%s' dev\n", mach->id);1737return -ENOENT;1738}17391740codec_dev = acpi_get_first_physical_node(adev);1741acpi_dev_put(adev);17421743if (codec_dev) {1744priv->codec_dev = get_device(codec_dev);1745} else {1746/*1747* Special case for Android tablets where the codec i2c_client1748* has been manually instantiated by x86_android_tablets.ko due1749* to a broken DSDT.1750*/1751codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,1752BYT_RT5640_FALLBACK_CODEC_DEV_NAME);1753if (!codec_dev)1754return -EPROBE_DEFER;17551756if (!i2c_verify_client(codec_dev)) {1757dev_err(dev, "Error '%s' is not an i2c_client\n",1758BYT_RT5640_FALLBACK_CODEC_DEV_NAME);1759put_device(codec_dev);1760}17611762/* fixup codec name */1763strscpy(byt_rt5640_codec_name, BYT_RT5640_FALLBACK_CODEC_DEV_NAME,1764sizeof(byt_rt5640_codec_name));17651766/* bus_find_device() returns a reference no need to get() */1767priv->codec_dev = codec_dev;1768}17691770/*1771* swap SSP0 if bytcr is detected1772* (will be overridden if DMI quirk is detected)1773*/1774if (soc_intel_is_byt()) {1775if (mach->mach_params.acpi_ipc_irq_index == 0)1776is_bytcr = true;1777}17781779if (is_bytcr) {1780/*1781* Baytrail CR platforms may have CHAN package in BIOS, try1782* to find relevant routing quirk based as done on Windows1783* platforms. We have to read the information directly from the1784* BIOS, at this stage the card is not created and the links1785* with the codec driver/pdata are non-existent1786*/17871788struct acpi_chan_package chan_package = { 0 };17891790/* format specified: 2 64-bit integers */1791struct acpi_buffer format = {sizeof("NN"), "NN"};1792struct acpi_buffer state = {0, NULL};1793struct snd_soc_acpi_package_context pkg_ctx;1794bool pkg_found = false;17951796state.length = sizeof(chan_package);1797state.pointer = &chan_package;17981799pkg_ctx.name = "CHAN";1800pkg_ctx.length = 2;1801pkg_ctx.format = &format;1802pkg_ctx.state = &state;1803pkg_ctx.data_valid = false;18041805pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,1806&pkg_ctx);1807if (pkg_found) {1808if (chan_package.aif_value == 1) {1809dev_info(dev, "BIOS Routing: AIF1 connected\n");1810byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1;1811} else if (chan_package.aif_value == 2) {1812dev_info(dev, "BIOS Routing: AIF2 connected\n");1813byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;1814} else {1815dev_info(dev, "BIOS Routing isn't valid, ignored\n");1816pkg_found = false;1817}1818}18191820if (!pkg_found) {1821/* no BIOS indications, assume SSP0-AIF2 connection */1822byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;1823}18241825/* change defaults for Baytrail-CR capture */1826byt_rt5640_quirk |= BYTCR_INPUT_DEFAULTS;1827} else {1828byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP |1829BYT_RT5640_JD_SRC_JD2_IN4N |1830BYT_RT5640_OVCD_TH_2000UA |1831BYT_RT5640_OVCD_SF_0P75;1832}18331834/* check quirks before creating card */1835dmi_id = dmi_first_match(byt_rt5640_quirk_table);1836if (dmi_id)1837byt_rt5640_quirk = (unsigned long)dmi_id->driver_data;1838if (quirk_override != -1) {1839dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n",1840byt_rt5640_quirk, quirk_override);1841byt_rt5640_quirk = quirk_override;1842}18431844if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {1845acpi_dev_add_driver_gpios(ACPI_COMPANION(priv->codec_dev),1846byt_rt5640_hp_elitepad_1000g2_gpios);18471848priv->hsmic_detect = devm_fwnode_gpiod_get(dev, codec_dev->fwnode,1849"headset-mic-detect", GPIOD_IN,1850"headset-mic-detect");1851if (IS_ERR(priv->hsmic_detect)) {1852ret_val = dev_err_probe(dev, PTR_ERR(priv->hsmic_detect),1853"getting hsmic-detect GPIO\n");1854goto err_device;1855}1856}18571858/* Must be called before register_card, also see declaration comment. */1859ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv);1860if (ret_val)1861goto err_remove_gpios;18621863log_quirks(dev);18641865if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) ||1866(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {1867byt_rt5640_dais[dai_index].codecs->dai_name = "rt5640-aif2";1868aif = 2;1869} else {1870aif = 1;1871}18721873if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||1874(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2))1875byt_rt5640_dais[dai_index].cpus->dai_name = "ssp0-port";18761877if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {1878priv->mclk = devm_clk_get_optional(dev, "pmc_plt_clk_3");1879if (IS_ERR(priv->mclk)) {1880ret_val = dev_err_probe(dev, PTR_ERR(priv->mclk),1881"Failed to get MCLK from pmc_plt_clk_3\n");1882goto err;1883}1884/*1885* Fall back to bit clock usage when clock is not1886* available likely due to missing dependencies.1887*/1888if (!priv->mclk)1889byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;1890}18911892if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) {1893cfg_spk = "0";1894spk_type = "none";1895} else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {1896cfg_spk = "1";1897spk_type = "mono";1898} else if (byt_rt5640_quirk & BYT_RT5640_SWAPPED_SPEAKERS) {1899cfg_spk = "swapped";1900spk_type = "swapped";1901} else {1902cfg_spk = "2";1903spk_type = "stereo";1904}19051906if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {1907if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)1908lineout_string = " cfg-hp2:lineout";1909else1910lineout_string = " cfg-lineout:2";1911}19121913if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)1914headset2_string = " cfg-hs2:in1";19151916snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),1917"cfg-spk:%s cfg-mic:%s aif:%d%s%s", cfg_spk,1918map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif,1919lineout_string, headset2_string);1920byt_rt5640_card.components = byt_rt5640_components;1921#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)1922snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),1923"bytcr-rt5640-%s-spk-%s-mic", spk_type,1924map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);1925byt_rt5640_card.long_name = byt_rt5640_long_name;1926#endif19271928/* override platform name, if required */1929platform_name = mach->mach_params.platform;19301931ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card,1932platform_name);1933if (ret_val)1934goto err;19351936sof_parent = snd_soc_acpi_sof_parent(dev);19371938/* set card and driver name */1939if (sof_parent) {1940byt_rt5640_card.name = SOF_CARD_NAME;1941byt_rt5640_card.driver_name = SOF_DRIVER_NAME;1942} else {1943byt_rt5640_card.name = CARD_NAME;1944byt_rt5640_card.driver_name = DRIVER_NAME;1945}19461947/* set pm ops */1948if (sof_parent)1949dev->driver->pm = &snd_soc_pm_ops;19501951ret_val = devm_snd_soc_register_card(dev, &byt_rt5640_card);1952if (ret_val) {1953dev_err(dev, "devm_snd_soc_register_card failed %d\n", ret_val);1954goto err;1955}1956platform_set_drvdata(pdev, &byt_rt5640_card);1957return ret_val;19581959err:1960device_remove_software_node(priv->codec_dev);1961err_remove_gpios:1962if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)1963acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));1964err_device:1965put_device(priv->codec_dev);1966return ret_val;1967}19681969static void snd_byt_rt5640_mc_remove(struct platform_device *pdev)1970{1971struct snd_soc_card *card = platform_get_drvdata(pdev);1972struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);19731974if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)1975acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));19761977device_remove_software_node(priv->codec_dev);1978put_device(priv->codec_dev);1979}19801981static struct platform_driver snd_byt_rt5640_mc_driver = {1982.driver = {1983.name = "bytcr_rt5640",1984},1985.probe = snd_byt_rt5640_mc_probe,1986.remove = snd_byt_rt5640_mc_remove,1987};19881989module_platform_driver(snd_byt_rt5640_mc_driver);19901991MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");1992MODULE_AUTHOR("Subhransu S. Prusty <[email protected]>");1993MODULE_LICENSE("GPL v2");1994MODULE_ALIAS("platform:bytcr_rt5640");199519961997