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

cht_bsw_max98090_ti.c (16773B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  cht-bsw-max98090.c - ASoc Machine driver for Intel Cherryview-based
      4 *  platforms Cherrytrail and Braswell, with max98090 & TI codec.
      5 *
      6 *  Copyright (C) 2015 Intel Corp
      7 *  Author: Fang, Yang A <yang.a.fang@intel.com>
      8 *  This file is modified from cht_bsw_rt5645.c
      9 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     10 *
     11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     12 */
     13
     14#include <linux/dmi.h>
     15#include <linux/gpio/consumer.h>
     16#include <linux/module.h>
     17#include <linux/platform_device.h>
     18#include <linux/slab.h>
     19#include <linux/acpi.h>
     20#include <linux/clk.h>
     21#include <sound/pcm.h>
     22#include <sound/pcm_params.h>
     23#include <sound/soc.h>
     24#include <sound/soc-acpi.h>
     25#include <sound/jack.h>
     26#include "../../codecs/max98090.h"
     27#include "../atom/sst-atom-controls.h"
     28#include "../../codecs/ts3a227e.h"
     29
     30#define CHT_PLAT_CLK_3_HZ	19200000
     31#define CHT_CODEC_DAI	"HiFi"
     32
     33#define QUIRK_PMC_PLT_CLK_0				0x01
     34
     35struct cht_mc_private {
     36	struct clk *mclk;
     37	struct snd_soc_jack jack;
     38	bool ts3a227e_present;
     39	int quirks;
     40};
     41
     42static int platform_clock_control(struct snd_soc_dapm_widget *w,
     43					  struct snd_kcontrol *k, int  event)
     44{
     45	struct snd_soc_dapm_context *dapm = w->dapm;
     46	struct snd_soc_card *card = dapm->card;
     47	struct snd_soc_dai *codec_dai;
     48	struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
     49	int ret;
     50
     51	/* See the comment in snd_cht_mc_probe() */
     52	if (ctx->quirks & QUIRK_PMC_PLT_CLK_0)
     53		return 0;
     54
     55	codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI);
     56	if (!codec_dai) {
     57		dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n");
     58		return -EIO;
     59	}
     60
     61	if (SND_SOC_DAPM_EVENT_ON(event)) {
     62		ret = clk_prepare_enable(ctx->mclk);
     63		if (ret < 0) {
     64			dev_err(card->dev,
     65				"could not configure MCLK state");
     66			return ret;
     67		}
     68	} else {
     69		clk_disable_unprepare(ctx->mclk);
     70	}
     71
     72	return 0;
     73}
     74
     75static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
     76	SND_SOC_DAPM_HP("Headphone", NULL),
     77	SND_SOC_DAPM_MIC("Headset Mic", NULL),
     78	SND_SOC_DAPM_MIC("Int Mic", NULL),
     79	SND_SOC_DAPM_SPK("Ext Spk", NULL),
     80	SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
     81			    platform_clock_control, SND_SOC_DAPM_PRE_PMU |
     82			    SND_SOC_DAPM_POST_PMD),
     83};
     84
     85static const struct snd_soc_dapm_route cht_audio_map[] = {
     86	{"IN34", NULL, "Headset Mic"},
     87	{"Headset Mic", NULL, "MICBIAS"},
     88	{"DMICL", NULL, "Int Mic"},
     89	{"Headphone", NULL, "HPL"},
     90	{"Headphone", NULL, "HPR"},
     91	{"Ext Spk", NULL, "SPKL"},
     92	{"Ext Spk", NULL, "SPKR"},
     93	{"HiFi Playback", NULL, "ssp2 Tx"},
     94	{"ssp2 Tx", NULL, "codec_out0"},
     95	{"ssp2 Tx", NULL, "codec_out1"},
     96	{"codec_in0", NULL, "ssp2 Rx" },
     97	{"codec_in1", NULL, "ssp2 Rx" },
     98	{"ssp2 Rx", NULL, "HiFi Capture"},
     99	{"Headphone", NULL, "Platform Clock"},
    100	{"Headset Mic", NULL, "Platform Clock"},
    101	{"Int Mic", NULL, "Platform Clock"},
    102	{"Ext Spk", NULL, "Platform Clock"},
    103};
    104
    105static const struct snd_kcontrol_new cht_mc_controls[] = {
    106	SOC_DAPM_PIN_SWITCH("Headphone"),
    107	SOC_DAPM_PIN_SWITCH("Headset Mic"),
    108	SOC_DAPM_PIN_SWITCH("Int Mic"),
    109	SOC_DAPM_PIN_SWITCH("Ext Spk"),
    110};
    111
    112static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
    113			     struct snd_pcm_hw_params *params)
    114{
    115	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
    116	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
    117	int ret;
    118
    119	ret = snd_soc_dai_set_sysclk(codec_dai, M98090_REG_SYSTEM_CLOCK,
    120				     CHT_PLAT_CLK_3_HZ, SND_SOC_CLOCK_IN);
    121	if (ret < 0) {
    122		dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
    123		return ret;
    124	}
    125
    126	return 0;
    127}
    128
    129static int cht_ti_jack_event(struct notifier_block *nb,
    130		unsigned long event, void *data)
    131{
    132	struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
    133	struct snd_soc_dapm_context *dapm = &jack->card->dapm;
    134
    135	if (event & SND_JACK_MICROPHONE) {
    136		snd_soc_dapm_force_enable_pin(dapm, "SHDN");
    137		snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
    138		snd_soc_dapm_sync(dapm);
    139	} else {
    140		snd_soc_dapm_disable_pin(dapm, "MICBIAS");
    141		snd_soc_dapm_disable_pin(dapm, "SHDN");
    142		snd_soc_dapm_sync(dapm);
    143	}
    144
    145	return 0;
    146}
    147
    148static struct notifier_block cht_jack_nb = {
    149	.notifier_call = cht_ti_jack_event,
    150};
    151
    152static struct snd_soc_jack_pin hs_jack_pins[] = {
    153	{
    154		.pin	= "Headphone",
    155		.mask	= SND_JACK_HEADPHONE,
    156	},
    157	{
    158		.pin	= "Headset Mic",
    159		.mask	= SND_JACK_MICROPHONE,
    160	},
    161};
    162
    163static struct snd_soc_jack_gpio hs_jack_gpios[] = {
    164	{
    165		.name		= "hp",
    166		.report		= SND_JACK_HEADPHONE | SND_JACK_LINEOUT,
    167		.debounce_time	= 200,
    168	},
    169	{
    170		.name		= "mic",
    171		.invert		= 1,
    172		.report		= SND_JACK_MICROPHONE,
    173		.debounce_time	= 200,
    174	},
    175};
    176
    177static const struct acpi_gpio_params hp_gpios = { 0, 0, false };
    178static const struct acpi_gpio_params mic_gpios = { 1, 0, false };
    179
    180static const struct acpi_gpio_mapping acpi_max98090_gpios[] = {
    181	{ "hp-gpios", &hp_gpios, 1 },
    182	{ "mic-gpios", &mic_gpios, 1 },
    183	{},
    184};
    185
    186static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
    187{
    188	int ret;
    189	int jack_type;
    190	struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card);
    191	struct snd_soc_jack *jack = &ctx->jack;
    192
    193	if (ctx->ts3a227e_present) {
    194		/*
    195		 * The jack has already been created in the
    196		 * cht_max98090_headset_init() function.
    197		 */
    198		snd_soc_jack_notifier_register(jack, &cht_jack_nb);
    199		return 0;
    200	}
    201
    202	jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE;
    203
    204	ret = snd_soc_card_jack_new_pins(runtime->card, "Headset Jack",
    205					 jack_type, jack,
    206					 hs_jack_pins,
    207					 ARRAY_SIZE(hs_jack_pins));
    208	if (ret) {
    209		dev_err(runtime->dev, "Headset Jack creation failed %d\n", ret);
    210		return ret;
    211	}
    212
    213	ret = snd_soc_jack_add_gpiods(runtime->card->dev->parent, jack,
    214				      ARRAY_SIZE(hs_jack_gpios),
    215				      hs_jack_gpios);
    216	if (ret) {
    217		/*
    218		 * flag error but don't bail if jack detect is broken
    219		 * due to platform issues or bad BIOS/configuration
    220		 */
    221		dev_err(runtime->dev,
    222			"jack detection gpios not added, error %d\n", ret);
    223	}
    224
    225	/* See the comment in snd_cht_mc_probe() */
    226	if (ctx->quirks & QUIRK_PMC_PLT_CLK_0)
    227		return 0;
    228
    229	/*
    230	 * The firmware might enable the clock at
    231	 * boot (this information may or may not
    232	 * be reflected in the enable clock register).
    233	 * To change the rate we must disable the clock
    234	 * first to cover these cases. Due to common
    235	 * clock framework restrictions that do not allow
    236	 * to disable a clock that has not been enabled,
    237	 * we need to enable the clock first.
    238	 */
    239	ret = clk_prepare_enable(ctx->mclk);
    240	if (!ret)
    241		clk_disable_unprepare(ctx->mclk);
    242
    243	ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
    244
    245	if (ret)
    246		dev_err(runtime->dev, "unable to set MCLK rate\n");
    247
    248	return ret;
    249}
    250
    251static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
    252			    struct snd_pcm_hw_params *params)
    253{
    254	struct snd_interval *rate = hw_param_interval(params,
    255			SNDRV_PCM_HW_PARAM_RATE);
    256	struct snd_interval *channels = hw_param_interval(params,
    257						SNDRV_PCM_HW_PARAM_CHANNELS);
    258	int ret = 0;
    259	unsigned int fmt = 0;
    260
    261	ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 16);
    262	if (ret < 0) {
    263		dev_err(rtd->dev, "can't set cpu_dai slot fmt: %d\n", ret);
    264		return ret;
    265	}
    266
    267	fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
    268				| SND_SOC_DAIFMT_CBC_CFC;
    269
    270	ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), fmt);
    271	if (ret < 0) {
    272		dev_err(rtd->dev, "can't set cpu_dai set fmt: %d\n", ret);
    273		return ret;
    274	}
    275
    276	/* The DSP will covert the FE rate to 48k, stereo, 24bits */
    277	rate->min = rate->max = 48000;
    278	channels->min = channels->max = 2;
    279
    280	/* set SSP2 to 16-bit */
    281	params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
    282	return 0;
    283}
    284
    285static int cht_aif1_startup(struct snd_pcm_substream *substream)
    286{
    287	return snd_pcm_hw_constraint_single(substream->runtime,
    288			SNDRV_PCM_HW_PARAM_RATE, 48000);
    289}
    290
    291static int cht_max98090_headset_init(struct snd_soc_component *component)
    292{
    293	struct snd_soc_card *card = component->card;
    294	struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
    295	struct snd_soc_jack *jack = &ctx->jack;
    296	int jack_type;
    297	int ret;
    298
    299	/*
    300	 * TI supports 4 buttons headset detection
    301	 * KEY_MEDIA
    302	 * KEY_VOICECOMMAND
    303	 * KEY_VOLUMEUP
    304	 * KEY_VOLUMEDOWN
    305	 */
    306	jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
    307		    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
    308		    SND_JACK_BTN_2 | SND_JACK_BTN_3;
    309
    310	ret = snd_soc_card_jack_new(card, "Headset Jack", jack_type, jack);
    311	if (ret) {
    312		dev_err(card->dev, "Headset Jack creation failed %d\n", ret);
    313		return ret;
    314	}
    315
    316	return ts3a227e_enable_jack_detect(component, jack);
    317}
    318
    319static const struct snd_soc_ops cht_aif1_ops = {
    320	.startup = cht_aif1_startup,
    321};
    322
    323static const struct snd_soc_ops cht_be_ssp2_ops = {
    324	.hw_params = cht_aif1_hw_params,
    325};
    326
    327static struct snd_soc_aux_dev cht_max98090_headset_dev = {
    328	.dlc = COMP_AUX("i2c-104C227E:00"),
    329	.init = cht_max98090_headset_init,
    330};
    331
    332SND_SOC_DAILINK_DEF(dummy,
    333	DAILINK_COMP_ARRAY(COMP_DUMMY()));
    334
    335SND_SOC_DAILINK_DEF(media,
    336	DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
    337
    338SND_SOC_DAILINK_DEF(deepbuffer,
    339	DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
    340
    341SND_SOC_DAILINK_DEF(ssp2_port,
    342	DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
    343SND_SOC_DAILINK_DEF(ssp2_codec,
    344	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-193C9890:00", "HiFi")));
    345
    346SND_SOC_DAILINK_DEF(platform,
    347	DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
    348
    349static struct snd_soc_dai_link cht_dailink[] = {
    350	[MERR_DPCM_AUDIO] = {
    351		.name = "Audio Port",
    352		.stream_name = "Audio",
    353		.nonatomic = true,
    354		.dynamic = 1,
    355		.dpcm_playback = 1,
    356		.dpcm_capture = 1,
    357		.ops = &cht_aif1_ops,
    358		SND_SOC_DAILINK_REG(media, dummy, platform),
    359	},
    360	[MERR_DPCM_DEEP_BUFFER] = {
    361		.name = "Deep-Buffer Audio Port",
    362		.stream_name = "Deep-Buffer Audio",
    363		.nonatomic = true,
    364		.dynamic = 1,
    365		.dpcm_playback = 1,
    366		.ops = &cht_aif1_ops,
    367		SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
    368	},
    369	/* back ends */
    370	{
    371		.name = "SSP2-Codec",
    372		.id = 0,
    373		.no_pcm = 1,
    374		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
    375					| SND_SOC_DAIFMT_CBC_CFC,
    376		.init = cht_codec_init,
    377		.be_hw_params_fixup = cht_codec_fixup,
    378		.dpcm_playback = 1,
    379		.dpcm_capture = 1,
    380		.ops = &cht_be_ssp2_ops,
    381		SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
    382	},
    383};
    384
    385/* use space before codec name to simplify card ID, and simplify driver name */
    386#define SOF_CARD_NAME "bytcht max98090" /* card name will be 'sof-bytcht max98090 */
    387#define SOF_DRIVER_NAME "SOF"
    388
    389#define CARD_NAME "chtmax98090"
    390#define DRIVER_NAME NULL /* card name will be used for driver name */
    391
    392/* SoC card */
    393static struct snd_soc_card snd_soc_card_cht = {
    394	.owner = THIS_MODULE,
    395	.dai_link = cht_dailink,
    396	.num_links = ARRAY_SIZE(cht_dailink),
    397	.aux_dev = &cht_max98090_headset_dev,
    398	.num_aux_devs = 1,
    399	.dapm_widgets = cht_dapm_widgets,
    400	.num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets),
    401	.dapm_routes = cht_audio_map,
    402	.num_dapm_routes = ARRAY_SIZE(cht_audio_map),
    403	.controls = cht_mc_controls,
    404	.num_controls = ARRAY_SIZE(cht_mc_controls),
    405};
    406
    407static const struct dmi_system_id cht_max98090_quirk_table[] = {
    408	{
    409		/* Banjo model Chromebook */
    410		.matches = {
    411			DMI_MATCH(DMI_PRODUCT_NAME, "Banjo"),
    412		},
    413		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    414	},
    415	{
    416		/* Candy model Chromebook */
    417		.matches = {
    418			DMI_MATCH(DMI_PRODUCT_NAME, "Candy"),
    419		},
    420		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    421	},
    422	{
    423		/* Clapper model Chromebook */
    424		.matches = {
    425			DMI_MATCH(DMI_PRODUCT_NAME, "Clapper"),
    426		},
    427		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    428	},
    429	{
    430		/* Cyan model Chromebook */
    431		.matches = {
    432			DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"),
    433		},
    434		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    435	},
    436	{
    437		/* Enguarde model Chromebook */
    438		.matches = {
    439			DMI_MATCH(DMI_PRODUCT_NAME, "Enguarde"),
    440		},
    441		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    442	},
    443	{
    444		/* Glimmer model Chromebook */
    445		.matches = {
    446			DMI_MATCH(DMI_PRODUCT_NAME, "Glimmer"),
    447		},
    448		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    449	},
    450	{
    451		/* Gnawty model Chromebook (Acer Chromebook CB3-111) */
    452		.matches = {
    453			DMI_MATCH(DMI_PRODUCT_NAME, "Gnawty"),
    454		},
    455		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    456	},
    457	{
    458		/* Heli model Chromebook */
    459		.matches = {
    460			DMI_MATCH(DMI_PRODUCT_NAME, "Heli"),
    461		},
    462		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    463	},
    464	{
    465		/* Kip model Chromebook */
    466		.matches = {
    467			DMI_MATCH(DMI_PRODUCT_NAME, "Kip"),
    468		},
    469		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    470	},
    471	{
    472		/* Ninja model Chromebook */
    473		.matches = {
    474			DMI_MATCH(DMI_PRODUCT_NAME, "Ninja"),
    475		},
    476		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    477	},
    478	{
    479		/* Orco model Chromebook */
    480		.matches = {
    481			DMI_MATCH(DMI_PRODUCT_NAME, "Orco"),
    482		},
    483		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    484	},
    485	{
    486		/* Quawks model Chromebook */
    487		.matches = {
    488			DMI_MATCH(DMI_PRODUCT_NAME, "Quawks"),
    489		},
    490		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    491	},
    492	{
    493		/* Rambi model Chromebook */
    494		.matches = {
    495			DMI_MATCH(DMI_PRODUCT_NAME, "Rambi"),
    496		},
    497		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    498	},
    499	{
    500		/* Squawks model Chromebook */
    501		.matches = {
    502			DMI_MATCH(DMI_PRODUCT_NAME, "Squawks"),
    503		},
    504		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    505	},
    506	{
    507		/* Sumo model Chromebook */
    508		.matches = {
    509			DMI_MATCH(DMI_PRODUCT_NAME, "Sumo"),
    510		},
    511		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    512	},
    513	{
    514		/* Swanky model Chromebook (Toshiba Chromebook 2) */
    515		.matches = {
    516			DMI_MATCH(DMI_PRODUCT_NAME, "Swanky"),
    517		},
    518		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    519	},
    520	{
    521		/* Winky model Chromebook */
    522		.matches = {
    523			DMI_MATCH(DMI_PRODUCT_NAME, "Winky"),
    524		},
    525		.driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
    526	},
    527	{}
    528};
    529
    530static int snd_cht_mc_probe(struct platform_device *pdev)
    531{
    532	const struct dmi_system_id *dmi_id;
    533	struct device *dev = &pdev->dev;
    534	int ret_val = 0;
    535	struct cht_mc_private *drv;
    536	const char *mclk_name;
    537	struct snd_soc_acpi_mach *mach;
    538	const char *platform_name;
    539	bool sof_parent;
    540
    541	drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
    542	if (!drv)
    543		return -ENOMEM;
    544
    545	dmi_id = dmi_first_match(cht_max98090_quirk_table);
    546	if (dmi_id)
    547		drv->quirks = (unsigned long)dmi_id->driver_data;
    548
    549	drv->ts3a227e_present = acpi_dev_found("104C227E");
    550	if (!drv->ts3a227e_present) {
    551		/* no need probe TI jack detection chip */
    552		snd_soc_card_cht.aux_dev = NULL;
    553		snd_soc_card_cht.num_aux_devs = 0;
    554
    555		ret_val = devm_acpi_dev_add_driver_gpios(dev->parent,
    556							 acpi_max98090_gpios);
    557		if (ret_val)
    558			dev_dbg(dev, "Unable to add GPIO mapping table\n");
    559	}
    560
    561	/* override platform name, if required */
    562	snd_soc_card_cht.dev = dev;
    563	mach = dev->platform_data;
    564	platform_name = mach->mach_params.platform;
    565
    566	ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht,
    567							platform_name);
    568	if (ret_val)
    569		return ret_val;
    570
    571	/* register the soc card */
    572	snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
    573
    574	if (drv->quirks & QUIRK_PMC_PLT_CLK_0)
    575		mclk_name = "pmc_plt_clk_0";
    576	else
    577		mclk_name = "pmc_plt_clk_3";
    578
    579	drv->mclk = devm_clk_get(dev, mclk_name);
    580	if (IS_ERR(drv->mclk)) {
    581		dev_err(dev,
    582			"Failed to get MCLK from %s: %ld\n",
    583			mclk_name, PTR_ERR(drv->mclk));
    584		return PTR_ERR(drv->mclk);
    585	}
    586
    587	/*
    588	 * Boards which have the MAX98090's clk connected to clk_0 do not seem
    589	 * to like it if we muck with the clock. If we disable the clock when
    590	 * it is unused we get "max98090 i2c-193C9890:00: PLL unlocked" errors
    591	 * and the PLL never seems to lock again.
    592	 * So for these boards we enable it here once and leave it at that.
    593	 */
    594	if (drv->quirks & QUIRK_PMC_PLT_CLK_0) {
    595		ret_val = clk_prepare_enable(drv->mclk);
    596		if (ret_val < 0) {
    597			dev_err(dev, "MCLK enable error: %d\n", ret_val);
    598			return ret_val;
    599		}
    600	}
    601
    602	sof_parent = snd_soc_acpi_sof_parent(dev);
    603
    604	/* set card and driver name */
    605	if (sof_parent) {
    606		snd_soc_card_cht.name = SOF_CARD_NAME;
    607		snd_soc_card_cht.driver_name = SOF_DRIVER_NAME;
    608	} else {
    609		snd_soc_card_cht.name = CARD_NAME;
    610		snd_soc_card_cht.driver_name = DRIVER_NAME;
    611	}
    612
    613	/* set pm ops */
    614	if (sof_parent)
    615		dev->driver->pm = &snd_soc_pm_ops;
    616
    617	ret_val = devm_snd_soc_register_card(dev, &snd_soc_card_cht);
    618	if (ret_val) {
    619		dev_err(dev,
    620			"snd_soc_register_card failed %d\n", ret_val);
    621		return ret_val;
    622	}
    623	platform_set_drvdata(pdev, &snd_soc_card_cht);
    624	return ret_val;
    625}
    626
    627static int snd_cht_mc_remove(struct platform_device *pdev)
    628{
    629	struct snd_soc_card *card = platform_get_drvdata(pdev);
    630	struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
    631
    632	if (ctx->quirks & QUIRK_PMC_PLT_CLK_0)
    633		clk_disable_unprepare(ctx->mclk);
    634
    635	return 0;
    636}
    637
    638static struct platform_driver snd_cht_mc_driver = {
    639	.driver = {
    640		.name = "cht-bsw-max98090",
    641	},
    642	.probe = snd_cht_mc_probe,
    643	.remove = snd_cht_mc_remove,
    644};
    645
    646module_platform_driver(snd_cht_mc_driver)
    647
    648MODULE_DESCRIPTION("ASoC Intel(R) Braswell Machine driver");
    649MODULE_AUTHOR("Fang, Yang A <yang.a.fang@intel.com>");
    650MODULE_LICENSE("GPL v2");
    651MODULE_ALIAS("platform:cht-bsw-max98090");