cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bytcht_es8316.c (19035B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  bytcht_es8316.c - ASoc Machine driver for Intel Baytrail/Cherrytrail
      4 *                    platforms with Everest ES8316 SoC
      5 *
      6 *  Copyright (C) 2017 Endless Mobile, Inc.
      7 *  Authors: David Yang <yangxiaohua@everest-semi.com>,
      8 *           Daniel Drake <drake@endlessm.com>
      9 *
     10 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     11 *
     12 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     13 */
     14#include <linux/acpi.h>
     15#include <linux/clk.h>
     16#include <linux/device.h>
     17#include <linux/dmi.h>
     18#include <linux/gpio/consumer.h>
     19#include <linux/i2c.h>
     20#include <linux/init.h>
     21#include <linux/input.h>
     22#include <linux/module.h>
     23#include <linux/platform_device.h>
     24#include <linux/slab.h>
     25#include <sound/jack.h>
     26#include <sound/pcm.h>
     27#include <sound/pcm_params.h>
     28#include <sound/soc.h>
     29#include <sound/soc-acpi.h>
     30#include "../atom/sst-atom-controls.h"
     31#include "../common/soc-intel-quirks.h"
     32
     33/* jd-inv + terminating entry */
     34#define MAX_NO_PROPS 2
     35
     36struct byt_cht_es8316_private {
     37	struct clk *mclk;
     38	struct snd_soc_jack jack;
     39	struct gpio_desc *speaker_en_gpio;
     40	struct device *codec_dev;
     41	bool speaker_en;
     42};
     43
     44enum {
     45	BYT_CHT_ES8316_INTMIC_IN1_MAP,
     46	BYT_CHT_ES8316_INTMIC_IN2_MAP,
     47};
     48
     49#define BYT_CHT_ES8316_MAP(quirk)		((quirk) & GENMASK(3, 0))
     50#define BYT_CHT_ES8316_SSP0			BIT(16)
     51#define BYT_CHT_ES8316_MONO_SPEAKER		BIT(17)
     52#define BYT_CHT_ES8316_JD_INVERTED		BIT(18)
     53
     54static unsigned long quirk;
     55
     56static int quirk_override = -1;
     57module_param_named(quirk, quirk_override, int, 0444);
     58MODULE_PARM_DESC(quirk, "Board-specific quirk override");
     59
     60static void log_quirks(struct device *dev)
     61{
     62	if (BYT_CHT_ES8316_MAP(quirk) == BYT_CHT_ES8316_INTMIC_IN1_MAP)
     63		dev_info(dev, "quirk IN1_MAP enabled");
     64	if (BYT_CHT_ES8316_MAP(quirk) == BYT_CHT_ES8316_INTMIC_IN2_MAP)
     65		dev_info(dev, "quirk IN2_MAP enabled");
     66	if (quirk & BYT_CHT_ES8316_SSP0)
     67		dev_info(dev, "quirk SSP0 enabled");
     68	if (quirk & BYT_CHT_ES8316_MONO_SPEAKER)
     69		dev_info(dev, "quirk MONO_SPEAKER enabled\n");
     70	if (quirk & BYT_CHT_ES8316_JD_INVERTED)
     71		dev_info(dev, "quirk JD_INVERTED enabled\n");
     72}
     73
     74static int byt_cht_es8316_speaker_power_event(struct snd_soc_dapm_widget *w,
     75	struct snd_kcontrol *kcontrol, int event)
     76{
     77	struct snd_soc_card *card = w->dapm->card;
     78	struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
     79
     80	if (SND_SOC_DAPM_EVENT_ON(event))
     81		priv->speaker_en = true;
     82	else
     83		priv->speaker_en = false;
     84
     85	gpiod_set_value_cansleep(priv->speaker_en_gpio, priv->speaker_en);
     86
     87	return 0;
     88}
     89
     90static const struct snd_soc_dapm_widget byt_cht_es8316_widgets[] = {
     91	SND_SOC_DAPM_SPK("Speaker", NULL),
     92	SND_SOC_DAPM_HP("Headphone", NULL),
     93	SND_SOC_DAPM_MIC("Headset Mic", NULL),
     94	SND_SOC_DAPM_MIC("Internal Mic", NULL),
     95
     96	SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0,
     97			    byt_cht_es8316_speaker_power_event,
     98			    SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
     99};
    100
    101static const struct snd_soc_dapm_route byt_cht_es8316_audio_map[] = {
    102	{"Headphone", NULL, "HPOL"},
    103	{"Headphone", NULL, "HPOR"},
    104
    105	/*
    106	 * There is no separate speaker output instead the speakers are muxed to
    107	 * the HP outputs. The mux is controlled by the "Speaker Power" supply.
    108	 */
    109	{"Speaker", NULL, "HPOL"},
    110	{"Speaker", NULL, "HPOR"},
    111	{"Speaker", NULL, "Speaker Power"},
    112};
    113
    114static const struct snd_soc_dapm_route byt_cht_es8316_intmic_in1_map[] = {
    115	{"MIC1", NULL, "Internal Mic"},
    116	{"MIC2", NULL, "Headset Mic"},
    117};
    118
    119static const struct snd_soc_dapm_route byt_cht_es8316_intmic_in2_map[] = {
    120	{"MIC2", NULL, "Internal Mic"},
    121	{"MIC1", NULL, "Headset Mic"},
    122};
    123
    124static const struct snd_soc_dapm_route byt_cht_es8316_ssp0_map[] = {
    125	{"Playback", NULL, "ssp0 Tx"},
    126	{"ssp0 Tx", NULL, "modem_out"},
    127	{"modem_in", NULL, "ssp0 Rx"},
    128	{"ssp0 Rx", NULL, "Capture"},
    129};
    130
    131static const struct snd_soc_dapm_route byt_cht_es8316_ssp2_map[] = {
    132	{"Playback", NULL, "ssp2 Tx"},
    133	{"ssp2 Tx", NULL, "codec_out0"},
    134	{"ssp2 Tx", NULL, "codec_out1"},
    135	{"codec_in0", NULL, "ssp2 Rx" },
    136	{"codec_in1", NULL, "ssp2 Rx" },
    137	{"ssp2 Rx", NULL, "Capture"},
    138};
    139
    140static const struct snd_kcontrol_new byt_cht_es8316_controls[] = {
    141	SOC_DAPM_PIN_SWITCH("Speaker"),
    142	SOC_DAPM_PIN_SWITCH("Headphone"),
    143	SOC_DAPM_PIN_SWITCH("Headset Mic"),
    144	SOC_DAPM_PIN_SWITCH("Internal Mic"),
    145};
    146
    147static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
    148	{
    149		.pin	= "Headphone",
    150		.mask	= SND_JACK_HEADPHONE,
    151	},
    152	{
    153		.pin	= "Headset Mic",
    154		.mask	= SND_JACK_MICROPHONE,
    155	},
    156};
    157
    158static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
    159{
    160	struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
    161	struct snd_soc_card *card = runtime->card;
    162	struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
    163	const struct snd_soc_dapm_route *custom_map;
    164	int num_routes;
    165	int ret;
    166
    167	card->dapm.idle_bias_off = true;
    168
    169	switch (BYT_CHT_ES8316_MAP(quirk)) {
    170	case BYT_CHT_ES8316_INTMIC_IN1_MAP:
    171	default:
    172		custom_map = byt_cht_es8316_intmic_in1_map;
    173		num_routes = ARRAY_SIZE(byt_cht_es8316_intmic_in1_map);
    174		break;
    175	case BYT_CHT_ES8316_INTMIC_IN2_MAP:
    176		custom_map = byt_cht_es8316_intmic_in2_map;
    177		num_routes = ARRAY_SIZE(byt_cht_es8316_intmic_in2_map);
    178		break;
    179	}
    180	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
    181	if (ret)
    182		return ret;
    183
    184	if (quirk & BYT_CHT_ES8316_SSP0) {
    185		custom_map = byt_cht_es8316_ssp0_map;
    186		num_routes = ARRAY_SIZE(byt_cht_es8316_ssp0_map);
    187	} else {
    188		custom_map = byt_cht_es8316_ssp2_map;
    189		num_routes = ARRAY_SIZE(byt_cht_es8316_ssp2_map);
    190	}
    191	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
    192	if (ret)
    193		return ret;
    194
    195	/*
    196	 * The firmware might enable the clock at boot (this information
    197	 * may or may not be reflected in the enable clock register).
    198	 * To change the rate we must disable the clock first to cover these
    199	 * cases. Due to common clock framework restrictions that do not allow
    200	 * to disable a clock that has not been enabled, we need to enable
    201	 * the clock first.
    202	 */
    203	ret = clk_prepare_enable(priv->mclk);
    204	if (!ret)
    205		clk_disable_unprepare(priv->mclk);
    206
    207	ret = clk_set_rate(priv->mclk, 19200000);
    208	if (ret)
    209		dev_err(card->dev, "unable to set MCLK rate\n");
    210
    211	ret = clk_prepare_enable(priv->mclk);
    212	if (ret)
    213		dev_err(card->dev, "unable to enable MCLK\n");
    214
    215	ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(runtime, 0), 0, 19200000,
    216				     SND_SOC_CLOCK_IN);
    217	if (ret < 0) {
    218		dev_err(card->dev, "can't set codec clock %d\n", ret);
    219		return ret;
    220	}
    221
    222	ret = snd_soc_card_jack_new_pins(card, "Headset",
    223					 SND_JACK_HEADSET | SND_JACK_BTN_0,
    224					 &priv->jack, byt_cht_es8316_jack_pins,
    225					 ARRAY_SIZE(byt_cht_es8316_jack_pins));
    226	if (ret) {
    227		dev_err(card->dev, "jack creation failed %d\n", ret);
    228		return ret;
    229	}
    230
    231	snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
    232	snd_soc_component_set_jack(codec, &priv->jack, NULL);
    233
    234	return 0;
    235}
    236
    237static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
    238			    struct snd_pcm_hw_params *params)
    239{
    240	struct snd_interval *rate = hw_param_interval(params,
    241			SNDRV_PCM_HW_PARAM_RATE);
    242	struct snd_interval *channels = hw_param_interval(params,
    243						SNDRV_PCM_HW_PARAM_CHANNELS);
    244	int ret, bits;
    245
    246	/* The DSP will covert the FE rate to 48k, stereo */
    247	rate->min = rate->max = 48000;
    248	channels->min = channels->max = 2;
    249
    250	if (quirk & BYT_CHT_ES8316_SSP0) {
    251		/* set SSP0 to 16-bit */
    252		params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
    253		bits = 16;
    254	} else {
    255		/* set SSP2 to 24-bit */
    256		params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
    257		bits = 24;
    258	}
    259
    260	/*
    261	 * Default mode for SSP configuration is TDM 4 slot, override config
    262	 * with explicit setting to I2S 2ch 24-bit. The word length is set with
    263	 * dai_set_tdm_slot() since there is no other API exposed
    264	 */
    265	ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
    266				SND_SOC_DAIFMT_I2S     |
    267				SND_SOC_DAIFMT_NB_NF   |
    268				SND_SOC_DAIFMT_CBC_CFC
    269		);
    270	if (ret < 0) {
    271		dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
    272		return ret;
    273	}
    274
    275	ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits);
    276	if (ret < 0) {
    277		dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
    278		return ret;
    279	}
    280
    281	return 0;
    282}
    283
    284static int byt_cht_es8316_aif1_startup(struct snd_pcm_substream *substream)
    285{
    286	return snd_pcm_hw_constraint_single(substream->runtime,
    287			SNDRV_PCM_HW_PARAM_RATE, 48000);
    288}
    289
    290static const struct snd_soc_ops byt_cht_es8316_aif1_ops = {
    291	.startup = byt_cht_es8316_aif1_startup,
    292};
    293
    294SND_SOC_DAILINK_DEF(dummy,
    295	DAILINK_COMP_ARRAY(COMP_DUMMY()));
    296
    297SND_SOC_DAILINK_DEF(media,
    298	DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
    299
    300SND_SOC_DAILINK_DEF(deepbuffer,
    301	DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
    302
    303SND_SOC_DAILINK_DEF(ssp2_port,
    304	DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
    305SND_SOC_DAILINK_DEF(ssp2_codec,
    306	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8316:00", "ES8316 HiFi")));
    307
    308SND_SOC_DAILINK_DEF(platform,
    309	DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
    310
    311static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
    312	[MERR_DPCM_AUDIO] = {
    313		.name = "Audio Port",
    314		.stream_name = "Audio",
    315		.nonatomic = true,
    316		.dynamic = 1,
    317		.dpcm_playback = 1,
    318		.dpcm_capture = 1,
    319		.ops = &byt_cht_es8316_aif1_ops,
    320		SND_SOC_DAILINK_REG(media, dummy, platform),
    321	},
    322
    323	[MERR_DPCM_DEEP_BUFFER] = {
    324		.name = "Deep-Buffer Audio Port",
    325		.stream_name = "Deep-Buffer Audio",
    326		.nonatomic = true,
    327		.dynamic = 1,
    328		.dpcm_playback = 1,
    329		.ops = &byt_cht_es8316_aif1_ops,
    330		SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
    331	},
    332
    333		/* back ends */
    334	{
    335		.name = "SSP2-Codec",
    336		.id = 0,
    337		.no_pcm = 1,
    338		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
    339						| SND_SOC_DAIFMT_CBC_CFC,
    340		.be_hw_params_fixup = byt_cht_es8316_codec_fixup,
    341		.dpcm_playback = 1,
    342		.dpcm_capture = 1,
    343		.init = byt_cht_es8316_init,
    344		SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
    345	},
    346};
    347
    348
    349/* SoC card */
    350static char codec_name[SND_ACPI_I2C_ID_LEN];
    351#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
    352static char long_name[50]; /* = "bytcht-es8316-*-spk-*-mic" */
    353#endif
    354static char components_string[32]; /* = "cfg-spk:* cfg-mic:* */
    355
    356static int byt_cht_es8316_suspend(struct snd_soc_card *card)
    357{
    358	struct snd_soc_component *component;
    359
    360	for_each_card_components(card, component) {
    361		if (!strcmp(component->name, codec_name)) {
    362			dev_dbg(component->dev, "disabling jack detect before suspend\n");
    363			snd_soc_component_set_jack(component, NULL, NULL);
    364			break;
    365		}
    366	}
    367
    368	return 0;
    369}
    370
    371static int byt_cht_es8316_resume(struct snd_soc_card *card)
    372{
    373	struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
    374	struct snd_soc_component *component;
    375
    376	for_each_card_components(card, component) {
    377		if (!strcmp(component->name, codec_name)) {
    378			dev_dbg(component->dev, "re-enabling jack detect after resume\n");
    379			snd_soc_component_set_jack(component, &priv->jack, NULL);
    380			break;
    381		}
    382	}
    383
    384	/*
    385	 * Some Cherry Trail boards with an ES8316 codec have a bug in their
    386	 * ACPI tables where the MSSL1680 touchscreen's _PS0 and _PS3 methods
    387	 * wrongly also set the speaker-enable GPIO to 1/0. Testing has shown
    388	 * that this really is a bug and the GPIO has no influence on the
    389	 * touchscreen at all.
    390	 *
    391	 * The silead.c touchscreen driver does not support runtime suspend, so
    392	 * the GPIO can only be changed underneath us during a system suspend.
    393	 * This resume() function runs from a pm complete() callback, and thus
    394	 * is guaranteed to run after the touchscreen driver/ACPI-subsys has
    395	 * brought the touchscreen back up again (and thus changed the GPIO).
    396	 *
    397	 * So to work around this we pass GPIOD_FLAGS_BIT_NONEXCLUSIVE when
    398	 * requesting the GPIO and we set its value here to undo any changes
    399	 * done by the touchscreen's broken _PS0 ACPI method.
    400	 */
    401	gpiod_set_value_cansleep(priv->speaker_en_gpio, priv->speaker_en);
    402
    403	return 0;
    404}
    405
    406/* use space before codec name to simplify card ID, and simplify driver name */
    407#define SOF_CARD_NAME "bytcht es8316" /* card name will be 'sof-bytcht es8316' */
    408#define SOF_DRIVER_NAME "SOF"
    409
    410#define CARD_NAME "bytcht-es8316"
    411#define DRIVER_NAME NULL /* card name will be used for driver name */
    412
    413static struct snd_soc_card byt_cht_es8316_card = {
    414	.owner = THIS_MODULE,
    415	.dai_link = byt_cht_es8316_dais,
    416	.num_links = ARRAY_SIZE(byt_cht_es8316_dais),
    417	.dapm_widgets = byt_cht_es8316_widgets,
    418	.num_dapm_widgets = ARRAY_SIZE(byt_cht_es8316_widgets),
    419	.dapm_routes = byt_cht_es8316_audio_map,
    420	.num_dapm_routes = ARRAY_SIZE(byt_cht_es8316_audio_map),
    421	.controls = byt_cht_es8316_controls,
    422	.num_controls = ARRAY_SIZE(byt_cht_es8316_controls),
    423	.fully_routed = true,
    424	.suspend_pre = byt_cht_es8316_suspend,
    425	.resume_post = byt_cht_es8316_resume,
    426};
    427
    428static const struct acpi_gpio_params first_gpio = { 0, 0, false };
    429
    430static const struct acpi_gpio_mapping byt_cht_es8316_gpios[] = {
    431	{ "speaker-enable-gpios", &first_gpio, 1 },
    432	{ },
    433};
    434
    435/* Please keep this list alphabetically sorted */
    436static const struct dmi_system_id byt_cht_es8316_quirk_table[] = {
    437	{	/* Irbis NB41 */
    438		.matches = {
    439			DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"),
    440			DMI_MATCH(DMI_PRODUCT_NAME, "NB41"),
    441		},
    442		.driver_data = (void *)(BYT_CHT_ES8316_SSP0
    443					| BYT_CHT_ES8316_INTMIC_IN2_MAP
    444					| BYT_CHT_ES8316_JD_INVERTED),
    445	},
    446	{	/* Teclast X98 Plus II */
    447		.matches = {
    448			DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
    449			DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"),
    450		},
    451		.driver_data = (void *)(BYT_CHT_ES8316_INTMIC_IN1_MAP
    452					| BYT_CHT_ES8316_JD_INVERTED),
    453	},
    454	{}
    455};
    456
    457static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
    458{
    459	struct device *dev = &pdev->dev;
    460	static const char * const mic_name[] = { "in1", "in2" };
    461	struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
    462	struct property_entry props[MAX_NO_PROPS] = {};
    463	struct byt_cht_es8316_private *priv;
    464	const struct dmi_system_id *dmi_id;
    465	struct fwnode_handle *fwnode;
    466	const char *platform_name;
    467	struct acpi_device *adev;
    468	struct device *codec_dev;
    469	bool sof_parent;
    470	unsigned int cnt = 0;
    471	int dai_index = 0;
    472	int i;
    473	int ret = 0;
    474
    475	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    476	if (!priv)
    477		return -ENOMEM;
    478
    479	/* fix index of codec dai */
    480	for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) {
    481		if (!strcmp(byt_cht_es8316_dais[i].codecs->name,
    482			    "i2c-ESSX8316:00")) {
    483			dai_index = i;
    484			break;
    485		}
    486	}
    487
    488	/* fixup codec name based on HID */
    489	adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
    490	if (adev) {
    491		snprintf(codec_name, sizeof(codec_name),
    492			 "i2c-%s", acpi_dev_name(adev));
    493		put_device(&adev->dev);
    494		byt_cht_es8316_dais[dai_index].codecs->name = codec_name;
    495	} else {
    496		dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
    497		return -ENXIO;
    498	}
    499
    500	/* override platform name, if required */
    501	byt_cht_es8316_card.dev = dev;
    502	platform_name = mach->mach_params.platform;
    503
    504	ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_es8316_card,
    505						    platform_name);
    506	if (ret)
    507		return ret;
    508
    509	/* Check for BYTCR or other platform and setup quirks */
    510	dmi_id = dmi_first_match(byt_cht_es8316_quirk_table);
    511	if (dmi_id) {
    512		quirk = (unsigned long)dmi_id->driver_data;
    513	} else if (soc_intel_is_byt() &&
    514		   mach->mach_params.acpi_ipc_irq_index == 0) {
    515		/* On BYTCR default to SSP0, internal-mic-in2-map, mono-spk */
    516		quirk = BYT_CHT_ES8316_SSP0 | BYT_CHT_ES8316_INTMIC_IN2_MAP |
    517			BYT_CHT_ES8316_MONO_SPEAKER;
    518	} else {
    519		/* Others default to internal-mic-in1-map, mono-speaker */
    520		quirk = BYT_CHT_ES8316_INTMIC_IN1_MAP |
    521			BYT_CHT_ES8316_MONO_SPEAKER;
    522	}
    523	if (quirk_override != -1) {
    524		dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n",
    525			 quirk, quirk_override);
    526		quirk = quirk_override;
    527	}
    528	log_quirks(dev);
    529
    530	if (quirk & BYT_CHT_ES8316_SSP0)
    531		byt_cht_es8316_dais[dai_index].cpus->dai_name = "ssp0-port";
    532
    533	/* get the clock */
    534	priv->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
    535	if (IS_ERR(priv->mclk))
    536		return dev_err_probe(dev, PTR_ERR(priv->mclk), "clk_get pmc_plt_clk_3 failed\n");
    537
    538	codec_dev = acpi_get_first_physical_node(adev);
    539	if (!codec_dev)
    540		return -EPROBE_DEFER;
    541	priv->codec_dev = get_device(codec_dev);
    542
    543	if (quirk & BYT_CHT_ES8316_JD_INVERTED)
    544		props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
    545
    546	if (cnt) {
    547		fwnode = fwnode_create_software_node(props, NULL);
    548		if (IS_ERR(fwnode)) {
    549			put_device(codec_dev);
    550			return PTR_ERR(fwnode);
    551		}
    552
    553		ret = device_add_software_node(codec_dev, to_software_node(fwnode));
    554
    555		fwnode_handle_put(fwnode);
    556
    557		if (ret) {
    558			put_device(codec_dev);
    559			return ret;
    560		}
    561	}
    562
    563	/* get speaker enable GPIO */
    564	devm_acpi_dev_add_driver_gpios(codec_dev, byt_cht_es8316_gpios);
    565	priv->speaker_en_gpio =
    566		gpiod_get_optional(codec_dev, "speaker-enable",
    567				   /* see comment in byt_cht_es8316_resume() */
    568				   GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
    569	if (IS_ERR(priv->speaker_en_gpio)) {
    570		ret = dev_err_probe(dev, PTR_ERR(priv->speaker_en_gpio),
    571				    "get speaker GPIO failed\n");
    572		goto err_put_codec;
    573	}
    574
    575	snprintf(components_string, sizeof(components_string),
    576		 "cfg-spk:%s cfg-mic:%s",
    577		 (quirk & BYT_CHT_ES8316_MONO_SPEAKER) ? "1" : "2",
    578		 mic_name[BYT_CHT_ES8316_MAP(quirk)]);
    579	byt_cht_es8316_card.components = components_string;
    580#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
    581	snprintf(long_name, sizeof(long_name), "bytcht-es8316-%s-spk-%s-mic",
    582		 (quirk & BYT_CHT_ES8316_MONO_SPEAKER) ? "mono" : "stereo",
    583		 mic_name[BYT_CHT_ES8316_MAP(quirk)]);
    584	byt_cht_es8316_card.long_name = long_name;
    585#endif
    586
    587	sof_parent = snd_soc_acpi_sof_parent(dev);
    588
    589	/* set card and driver name */
    590	if (sof_parent) {
    591		byt_cht_es8316_card.name = SOF_CARD_NAME;
    592		byt_cht_es8316_card.driver_name = SOF_DRIVER_NAME;
    593	} else {
    594		byt_cht_es8316_card.name = CARD_NAME;
    595		byt_cht_es8316_card.driver_name = DRIVER_NAME;
    596	}
    597
    598	/* set pm ops */
    599	if (sof_parent)
    600		dev->driver->pm = &snd_soc_pm_ops;
    601
    602	/* register the soc card */
    603	snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv);
    604
    605	ret = devm_snd_soc_register_card(dev, &byt_cht_es8316_card);
    606	if (ret) {
    607		gpiod_put(priv->speaker_en_gpio);
    608		dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
    609		goto err_put_codec;
    610	}
    611	platform_set_drvdata(pdev, &byt_cht_es8316_card);
    612	return 0;
    613
    614err_put_codec:
    615	device_remove_software_node(priv->codec_dev);
    616	put_device(priv->codec_dev);
    617	return ret;
    618}
    619
    620static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
    621{
    622	struct snd_soc_card *card = platform_get_drvdata(pdev);
    623	struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
    624
    625	gpiod_put(priv->speaker_en_gpio);
    626	device_remove_software_node(priv->codec_dev);
    627	put_device(priv->codec_dev);
    628	return 0;
    629}
    630
    631static struct platform_driver snd_byt_cht_es8316_mc_driver = {
    632	.driver = {
    633		.name = "bytcht_es8316",
    634	},
    635	.probe = snd_byt_cht_es8316_mc_probe,
    636	.remove = snd_byt_cht_es8316_mc_remove,
    637};
    638
    639module_platform_driver(snd_byt_cht_es8316_mc_driver);
    640MODULE_DESCRIPTION("ASoC Intel(R) Baytrail/Cherrytrail Machine driver");
    641MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");
    642MODULE_LICENSE("GPL v2");
    643MODULE_ALIAS("platform:bytcht_es8316");