root/sound/soc/intel/boards/bytcht_es8316.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. log_quirks
  2. byt_cht_es8316_speaker_power_event
  3. byt_cht_es8316_init
  4. byt_cht_es8316_codec_fixup
  5. byt_cht_es8316_aif1_startup
  6. byt_cht_es8316_suspend
  7. byt_cht_es8316_resume
  8. snd_byt_cht_es8316_mc_probe
  9. snd_byt_cht_es8316_mc_remove

   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/sst-dsp.h"
  32 #include "../common/soc-intel-quirks.h"
  33 
  34 /* jd-inv + terminating entry */
  35 #define MAX_NO_PROPS 2
  36 
  37 struct byt_cht_es8316_private {
  38         struct clk *mclk;
  39         struct snd_soc_jack jack;
  40         struct gpio_desc *speaker_en_gpio;
  41         bool speaker_en;
  42 };
  43 
  44 enum {
  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 
  54 static unsigned long quirk;
  55 
  56 static int quirk_override = -1;
  57 module_param_named(quirk, quirk_override, int, 0444);
  58 MODULE_PARM_DESC(quirk, "Board-specific quirk override");
  59 
  60 static 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 
  74 static 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 
  90 static 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 
 101 static 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 
 114 static const struct snd_soc_dapm_route byt_cht_es8316_intmic_in1_map[] = {
 115         {"MIC1", NULL, "Internal Mic"},
 116         {"MIC2", NULL, "Headset Mic"},
 117 };
 118 
 119 static const struct snd_soc_dapm_route byt_cht_es8316_intmic_in2_map[] = {
 120         {"MIC2", NULL, "Internal Mic"},
 121         {"MIC1", NULL, "Headset Mic"},
 122 };
 123 
 124 static 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 
 131 static 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 
 140 static 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 
 147 static 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 
 158 static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
 159 {
 160         struct snd_soc_component *codec = runtime->codec_dai->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(runtime->codec_dai, 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(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 
 237 static const struct snd_soc_pcm_stream byt_cht_es8316_dai_params = {
 238         .formats = SNDRV_PCM_FMTBIT_S24_LE,
 239         .rate_min = 48000,
 240         .rate_max = 48000,
 241         .channels_min = 2,
 242         .channels_max = 2,
 243 };
 244 
 245 static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
 246                             struct snd_pcm_hw_params *params)
 247 {
 248         struct snd_interval *rate = hw_param_interval(params,
 249                         SNDRV_PCM_HW_PARAM_RATE);
 250         struct snd_interval *channels = hw_param_interval(params,
 251                                                 SNDRV_PCM_HW_PARAM_CHANNELS);
 252         int ret, bits;
 253 
 254         /* The DSP will covert the FE rate to 48k, stereo */
 255         rate->min = rate->max = 48000;
 256         channels->min = channels->max = 2;
 257 
 258         if (quirk & BYT_CHT_ES8316_SSP0) {
 259                 /* set SSP0 to 16-bit */
 260                 params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
 261                 bits = 16;
 262         } else {
 263                 /* set SSP2 to 24-bit */
 264                 params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
 265                 bits = 24;
 266         }
 267 
 268         /*
 269          * Default mode for SSP configuration is TDM 4 slot, override config
 270          * with explicit setting to I2S 2ch 24-bit. The word length is set with
 271          * dai_set_tdm_slot() since there is no other API exposed
 272          */
 273         ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
 274                                 SND_SOC_DAIFMT_I2S     |
 275                                 SND_SOC_DAIFMT_NB_NF   |
 276                                 SND_SOC_DAIFMT_CBS_CFS
 277                 );
 278         if (ret < 0) {
 279                 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
 280                 return ret;
 281         }
 282 
 283         ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits);
 284         if (ret < 0) {
 285                 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
 286                 return ret;
 287         }
 288 
 289         return 0;
 290 }
 291 
 292 static int byt_cht_es8316_aif1_startup(struct snd_pcm_substream *substream)
 293 {
 294         return snd_pcm_hw_constraint_single(substream->runtime,
 295                         SNDRV_PCM_HW_PARAM_RATE, 48000);
 296 }
 297 
 298 static const struct snd_soc_ops byt_cht_es8316_aif1_ops = {
 299         .startup = byt_cht_es8316_aif1_startup,
 300 };
 301 
 302 SND_SOC_DAILINK_DEF(dummy,
 303         DAILINK_COMP_ARRAY(COMP_DUMMY()));
 304 
 305 SND_SOC_DAILINK_DEF(media,
 306         DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
 307 
 308 SND_SOC_DAILINK_DEF(deepbuffer,
 309         DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
 310 
 311 SND_SOC_DAILINK_DEF(ssp2_port,
 312         DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
 313 SND_SOC_DAILINK_DEF(ssp2_codec,
 314         DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8316:00", "ES8316 HiFi")));
 315 
 316 SND_SOC_DAILINK_DEF(platform,
 317         DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
 318 
 319 static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
 320         [MERR_DPCM_AUDIO] = {
 321                 .name = "Audio Port",
 322                 .stream_name = "Audio",
 323                 .nonatomic = true,
 324                 .dynamic = 1,
 325                 .dpcm_playback = 1,
 326                 .dpcm_capture = 1,
 327                 .ops = &byt_cht_es8316_aif1_ops,
 328                 SND_SOC_DAILINK_REG(media, dummy, platform),
 329         },
 330 
 331         [MERR_DPCM_DEEP_BUFFER] = {
 332                 .name = "Deep-Buffer Audio Port",
 333                 .stream_name = "Deep-Buffer Audio",
 334                 .nonatomic = true,
 335                 .dynamic = 1,
 336                 .dpcm_playback = 1,
 337                 .ops = &byt_cht_es8316_aif1_ops,
 338                 SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
 339         },
 340 
 341                 /* back ends */
 342         {
 343                 /* Only SSP2 has been tested here, so BYT-CR platforms that
 344                  * require SSP0 will not work.
 345                  */
 346                 .name = "SSP2-Codec",
 347                 .id = 0,
 348                 .no_pcm = 1,
 349                 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
 350                                                 | SND_SOC_DAIFMT_CBS_CFS,
 351                 .be_hw_params_fixup = byt_cht_es8316_codec_fixup,
 352                 .nonatomic = true,
 353                 .dpcm_playback = 1,
 354                 .dpcm_capture = 1,
 355                 .init = byt_cht_es8316_init,
 356                 SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
 357         },
 358 };
 359 
 360 
 361 /* SoC card */
 362 static char codec_name[SND_ACPI_I2C_ID_LEN];
 363 static char long_name[50]; /* = "bytcht-es8316-*-spk-*-mic" */
 364 
 365 static int byt_cht_es8316_suspend(struct snd_soc_card *card)
 366 {
 367         struct snd_soc_component *component;
 368 
 369         for_each_card_components(card, component) {
 370                 if (!strcmp(component->name, codec_name)) {
 371                         dev_dbg(component->dev, "disabling jack detect before suspend\n");
 372                         snd_soc_component_set_jack(component, NULL, NULL);
 373                         break;
 374                 }
 375         }
 376 
 377         return 0;
 378 }
 379 
 380 static int byt_cht_es8316_resume(struct snd_soc_card *card)
 381 {
 382         struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
 383         struct snd_soc_component *component;
 384 
 385         for_each_card_components(card, component) {
 386                 if (!strcmp(component->name, codec_name)) {
 387                         dev_dbg(component->dev, "re-enabling jack detect after resume\n");
 388                         snd_soc_component_set_jack(component, &priv->jack, NULL);
 389                         break;
 390                 }
 391         }
 392 
 393         /*
 394          * Some Cherry Trail boards with an ES8316 codec have a bug in their
 395          * ACPI tables where the MSSL1680 touchscreen's _PS0 and _PS3 methods
 396          * wrongly also set the speaker-enable GPIO to 1/0. Testing has shown
 397          * that this really is a bug and the GPIO has no influence on the
 398          * touchscreen at all.
 399          *
 400          * The silead.c touchscreen driver does not support runtime suspend, so
 401          * the GPIO can only be changed underneath us during a system suspend.
 402          * This resume() function runs from a pm complete() callback, and thus
 403          * is guaranteed to run after the touchscreen driver/ACPI-subsys has
 404          * brought the touchscreen back up again (and thus changed the GPIO).
 405          *
 406          * So to work around this we pass GPIOD_FLAGS_BIT_NONEXCLUSIVE when
 407          * requesting the GPIO and we set its value here to undo any changes
 408          * done by the touchscreen's broken _PS0 ACPI method.
 409          */
 410         gpiod_set_value_cansleep(priv->speaker_en_gpio, priv->speaker_en);
 411 
 412         return 0;
 413 }
 414 
 415 static struct snd_soc_card byt_cht_es8316_card = {
 416         .name = "bytcht-es8316",
 417         .owner = THIS_MODULE,
 418         .dai_link = byt_cht_es8316_dais,
 419         .num_links = ARRAY_SIZE(byt_cht_es8316_dais),
 420         .dapm_widgets = byt_cht_es8316_widgets,
 421         .num_dapm_widgets = ARRAY_SIZE(byt_cht_es8316_widgets),
 422         .dapm_routes = byt_cht_es8316_audio_map,
 423         .num_dapm_routes = ARRAY_SIZE(byt_cht_es8316_audio_map),
 424         .controls = byt_cht_es8316_controls,
 425         .num_controls = ARRAY_SIZE(byt_cht_es8316_controls),
 426         .fully_routed = true,
 427         .suspend_pre = byt_cht_es8316_suspend,
 428         .resume_post = byt_cht_es8316_resume,
 429 };
 430 
 431 static const struct acpi_gpio_params first_gpio = { 0, 0, false };
 432 
 433 static const struct acpi_gpio_mapping byt_cht_es8316_gpios[] = {
 434         { "speaker-enable-gpios", &first_gpio, 1 },
 435         { },
 436 };
 437 
 438 /* Please keep this list alphabetically sorted */
 439 static const struct dmi_system_id byt_cht_es8316_quirk_table[] = {
 440         {       /* Irbis NB41 */
 441                 .matches = {
 442                         DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"),
 443                         DMI_MATCH(DMI_PRODUCT_NAME, "NB41"),
 444                 },
 445                 .driver_data = (void *)(BYT_CHT_ES8316_SSP0
 446                                         | BYT_CHT_ES8316_INTMIC_IN2_MAP
 447                                         | BYT_CHT_ES8316_JD_INVERTED),
 448         },
 449         {       /* Teclast X98 Plus II */
 450                 .matches = {
 451                         DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
 452                         DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"),
 453                 },
 454                 .driver_data = (void *)(BYT_CHT_ES8316_INTMIC_IN1_MAP
 455                                         | BYT_CHT_ES8316_JD_INVERTED),
 456         },
 457         {}
 458 };
 459 
 460 static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
 461 {
 462         static const char * const mic_name[] = { "in1", "in2" };
 463         struct property_entry props[MAX_NO_PROPS] = {};
 464         struct byt_cht_es8316_private *priv;
 465         const struct dmi_system_id *dmi_id;
 466         struct device *dev = &pdev->dev;
 467         struct snd_soc_acpi_mach *mach;
 468         const char *platform_name;
 469         struct acpi_device *adev;
 470         struct device *codec_dev;
 471         unsigned int cnt = 0;
 472         int dai_index = 0;
 473         int i;
 474         int ret = 0;
 475 
 476         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 477         if (!priv)
 478                 return -ENOMEM;
 479 
 480         mach = dev->platform_data;
 481         /* fix index of codec dai */
 482         for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) {
 483                 if (!strcmp(byt_cht_es8316_dais[i].codecs->name,
 484                             "i2c-ESSX8316:00")) {
 485                         dai_index = i;
 486                         break;
 487                 }
 488         }
 489 
 490         /* fixup codec name based on HID */
 491         adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
 492         if (adev) {
 493                 snprintf(codec_name, sizeof(codec_name),
 494                          "i2c-%s", acpi_dev_name(adev));
 495                 put_device(&adev->dev);
 496                 byt_cht_es8316_dais[dai_index].codecs->name = codec_name;
 497         }
 498 
 499         /* override plaform name, if required */
 500         byt_cht_es8316_card.dev = dev;
 501         platform_name = mach->mach_params.platform;
 502 
 503         ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_es8316_card,
 504                                                     platform_name);
 505         if (ret)
 506                 return ret;
 507 
 508         /* Check for BYTCR or other platform and setup quirks */
 509         dmi_id = dmi_first_match(byt_cht_es8316_quirk_table);
 510         if (dmi_id) {
 511                 quirk = (unsigned long)dmi_id->driver_data;
 512         } else if (soc_intel_is_byt() &&
 513                    mach->mach_params.acpi_ipc_irq_index == 0) {
 514                 /* On BYTCR default to SSP0, internal-mic-in2-map, mono-spk */
 515                 quirk = BYT_CHT_ES8316_SSP0 | BYT_CHT_ES8316_INTMIC_IN2_MAP |
 516                         BYT_CHT_ES8316_MONO_SPEAKER;
 517         } else {
 518                 /* Others default to internal-mic-in1-map, mono-speaker */
 519                 quirk = BYT_CHT_ES8316_INTMIC_IN1_MAP |
 520                         BYT_CHT_ES8316_MONO_SPEAKER;
 521         }
 522         if (quirk_override != -1) {
 523                 dev_info(dev, "Overriding quirk 0x%x => 0x%x\n",
 524                          (unsigned int)quirk,
 525                          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                 ret = PTR_ERR(priv->mclk);
 537                 dev_err(dev, "clk_get pmc_plt_clk_3 failed: %d\n", ret);
 538                 return ret;
 539         }
 540 
 541         /* get speaker enable GPIO */
 542         codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name);
 543         if (!codec_dev)
 544                 return -EPROBE_DEFER;
 545 
 546         if (quirk & BYT_CHT_ES8316_JD_INVERTED)
 547                 props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted");
 548 
 549         if (cnt) {
 550                 ret = device_add_properties(codec_dev, props);
 551                 if (ret)
 552                         return ret;
 553         }
 554 
 555         devm_acpi_dev_add_driver_gpios(codec_dev, byt_cht_es8316_gpios);
 556         priv->speaker_en_gpio =
 557                 gpiod_get_index(codec_dev, "speaker-enable", 0,
 558                                 /* see comment in byt_cht_es8316_resume */
 559                                 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
 560         put_device(codec_dev);
 561 
 562         if (IS_ERR(priv->speaker_en_gpio)) {
 563                 ret = PTR_ERR(priv->speaker_en_gpio);
 564                 switch (ret) {
 565                 case -ENOENT:
 566                         priv->speaker_en_gpio = NULL;
 567                         break;
 568                 default:
 569                         dev_err(dev, "get speaker GPIO failed: %d\n", ret);
 570                         /* fall through */
 571                 case -EPROBE_DEFER:
 572                         return ret;
 573                 }
 574         }
 575 
 576         /* register the soc card */
 577         snprintf(long_name, sizeof(long_name), "bytcht-es8316-%s-spk-%s-mic",
 578                  (quirk & BYT_CHT_ES8316_MONO_SPEAKER) ? "mono" : "stereo",
 579                  mic_name[BYT_CHT_ES8316_MAP(quirk)]);
 580         byt_cht_es8316_card.long_name = long_name;
 581         snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv);
 582 
 583         ret = devm_snd_soc_register_card(dev, &byt_cht_es8316_card);
 584         if (ret) {
 585                 gpiod_put(priv->speaker_en_gpio);
 586                 dev_err(dev, "snd_soc_register_card failed: %d\n", ret);
 587                 return ret;
 588         }
 589         platform_set_drvdata(pdev, &byt_cht_es8316_card);
 590         return 0;
 591 }
 592 
 593 static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev)
 594 {
 595         struct snd_soc_card *card = platform_get_drvdata(pdev);
 596         struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
 597 
 598         gpiod_put(priv->speaker_en_gpio);
 599         return 0;
 600 }
 601 
 602 static struct platform_driver snd_byt_cht_es8316_mc_driver = {
 603         .driver = {
 604                 .name = "bytcht_es8316",
 605         },
 606         .probe = snd_byt_cht_es8316_mc_probe,
 607         .remove = snd_byt_cht_es8316_mc_remove,
 608 };
 609 
 610 module_platform_driver(snd_byt_cht_es8316_mc_driver);
 611 MODULE_DESCRIPTION("ASoC Intel(R) Baytrail/Cherrytrail Machine driver");
 612 MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");
 613 MODULE_LICENSE("GPL v2");
 614 MODULE_ALIAS("platform:bytcht_es8316");

/* [<][>][^][v][top][bottom][index][help] */