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