brintos

brintos / linux-shallow public Read only

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