File Index
Files and directories
Sign in
FILE

bytcr_rt5640.c

File preview with syntax highlighting.

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