Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  cht_bsw_rt5672.c - ASoc Machine driver for Intel Cherryview-based platforms
0004  *                     Cherrytrail and Braswell, with RT5672 codec.
0005  *
0006  *  Copyright (C) 2014 Intel Corp
0007  *  Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
0008  *          Mengdong Lin <mengdong.lin@intel.com>
0009  */
0010 
0011 #include <linux/gpio/consumer.h>
0012 #include <linux/input.h>
0013 #include <linux/module.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/slab.h>
0016 #include <linux/clk.h>
0017 #include <sound/pcm.h>
0018 #include <sound/pcm_params.h>
0019 #include <sound/soc.h>
0020 #include <sound/jack.h>
0021 #include <sound/soc-acpi.h>
0022 #include "../../codecs/rt5670.h"
0023 #include "../atom/sst-atom-controls.h"
0024 #include "../common/soc-intel-quirks.h"
0025 
0026 
0027 /* The platform clock #3 outputs 19.2Mhz clock to codec as I2S MCLK */
0028 #define CHT_PLAT_CLK_3_HZ   19200000
0029 #define CHT_CODEC_DAI   "rt5670-aif1"
0030 
0031 struct cht_mc_private {
0032     struct snd_soc_jack headset;
0033     char codec_name[SND_ACPI_I2C_ID_LEN];
0034     struct clk *mclk;
0035     bool use_ssp0;
0036 };
0037 
0038 /* Headset jack detection DAPM pins */
0039 static struct snd_soc_jack_pin cht_bsw_headset_pins[] = {
0040     {
0041         .pin = "Headset Mic",
0042         .mask = SND_JACK_MICROPHONE,
0043     },
0044     {
0045         .pin = "Headphone",
0046         .mask = SND_JACK_HEADPHONE,
0047     },
0048 };
0049 
0050 static int platform_clock_control(struct snd_soc_dapm_widget *w,
0051         struct snd_kcontrol *k, int  event)
0052 {
0053     struct snd_soc_dapm_context *dapm = w->dapm;
0054     struct snd_soc_card *card = dapm->card;
0055     struct snd_soc_dai *codec_dai;
0056     struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
0057     int ret;
0058 
0059     codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI);
0060     if (!codec_dai) {
0061         dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n");
0062         return -EIO;
0063     }
0064 
0065     if (SND_SOC_DAPM_EVENT_ON(event)) {
0066         if (ctx->mclk) {
0067             ret = clk_prepare_enable(ctx->mclk);
0068             if (ret < 0) {
0069                 dev_err(card->dev,
0070                     "could not configure MCLK state");
0071                 return ret;
0072             }
0073         }
0074 
0075         /* set codec PLL source to the 19.2MHz platform clock (MCLK) */
0076         ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK,
0077                 CHT_PLAT_CLK_3_HZ, 48000 * 512);
0078         if (ret < 0) {
0079             dev_err(card->dev, "can't set codec pll: %d\n", ret);
0080             return ret;
0081         }
0082 
0083         /* set codec sysclk source to PLL */
0084         ret = snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_PLL1,
0085             48000 * 512, SND_SOC_CLOCK_IN);
0086         if (ret < 0) {
0087             dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
0088             return ret;
0089         }
0090     } else {
0091         /* Set codec sysclk source to its internal clock because codec
0092          * PLL will be off when idle and MCLK will also be off by ACPI
0093          * when codec is runtime suspended. Codec needs clock for jack
0094          * detection and button press.
0095          */
0096         snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_RCCLK,
0097                        48000 * 512, SND_SOC_CLOCK_IN);
0098 
0099         if (ctx->mclk)
0100             clk_disable_unprepare(ctx->mclk);
0101     }
0102     return 0;
0103 }
0104 
0105 static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
0106     SND_SOC_DAPM_HP("Headphone", NULL),
0107     SND_SOC_DAPM_MIC("Headset Mic", NULL),
0108     SND_SOC_DAPM_MIC("Int Mic", NULL),
0109     SND_SOC_DAPM_SPK("Ext Spk", NULL),
0110     SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
0111             platform_clock_control, SND_SOC_DAPM_PRE_PMU |
0112             SND_SOC_DAPM_POST_PMD),
0113 };
0114 
0115 static const struct snd_soc_dapm_route cht_audio_map[] = {
0116     {"IN1P", NULL, "Headset Mic"},
0117     {"IN1N", NULL, "Headset Mic"},
0118     {"DMIC L1", NULL, "Int Mic"},
0119     {"DMIC R1", NULL, "Int Mic"},
0120     {"Headphone", NULL, "HPOL"},
0121     {"Headphone", NULL, "HPOR"},
0122     {"Ext Spk", NULL, "SPOLP"},
0123     {"Ext Spk", NULL, "SPOLN"},
0124     {"Ext Spk", NULL, "SPORP"},
0125     {"Ext Spk", NULL, "SPORN"},
0126     {"Headphone", NULL, "Platform Clock"},
0127     {"Headset Mic", NULL, "Platform Clock"},
0128     {"Int Mic", NULL, "Platform Clock"},
0129     {"Ext Spk", NULL, "Platform Clock"},
0130 };
0131 
0132 static const struct snd_soc_dapm_route cht_audio_ssp0_map[] = {
0133     {"AIF1 Playback", NULL, "ssp0 Tx"},
0134     {"ssp0 Tx", NULL, "modem_out"},
0135     {"modem_in", NULL, "ssp0 Rx"},
0136     {"ssp0 Rx", NULL, "AIF1 Capture"},
0137 };
0138 
0139 static const struct snd_soc_dapm_route cht_audio_ssp2_map[] = {
0140     {"AIF1 Playback", NULL, "ssp2 Tx"},
0141     {"ssp2 Tx", NULL, "codec_out0"},
0142     {"ssp2 Tx", NULL, "codec_out1"},
0143     {"codec_in0", NULL, "ssp2 Rx"},
0144     {"codec_in1", NULL, "ssp2 Rx"},
0145     {"ssp2 Rx", NULL, "AIF1 Capture"},
0146 };
0147 
0148 static const struct snd_kcontrol_new cht_mc_controls[] = {
0149     SOC_DAPM_PIN_SWITCH("Headphone"),
0150     SOC_DAPM_PIN_SWITCH("Headset Mic"),
0151     SOC_DAPM_PIN_SWITCH("Int Mic"),
0152     SOC_DAPM_PIN_SWITCH("Ext Spk"),
0153 };
0154 
0155 static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
0156                     struct snd_pcm_hw_params *params)
0157 {
0158     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0159     struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0160     int ret;
0161 
0162     /* set codec PLL source to the 19.2MHz platform clock (MCLK) */
0163     ret = snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_MCLK,
0164                   CHT_PLAT_CLK_3_HZ, params_rate(params) * 512);
0165     if (ret < 0) {
0166         dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
0167         return ret;
0168     }
0169 
0170     /* set codec sysclk source to PLL */
0171     ret = snd_soc_dai_set_sysclk(codec_dai, RT5670_SCLK_S_PLL1,
0172                      params_rate(params) * 512,
0173                      SND_SOC_CLOCK_IN);
0174     if (ret < 0) {
0175         dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
0176         return ret;
0177     }
0178     return 0;
0179 }
0180 
0181 static const struct acpi_gpio_params headset_gpios = { 0, 0, false };
0182 
0183 static const struct acpi_gpio_mapping cht_rt5672_gpios[] = {
0184     { "headset-gpios", &headset_gpios, 1 },
0185     {},
0186 };
0187 
0188 static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
0189 {
0190     int ret;
0191     struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0);
0192     struct snd_soc_component *component = codec_dai->component;
0193     struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card);
0194 
0195     if (devm_acpi_dev_add_driver_gpios(component->dev, cht_rt5672_gpios))
0196         dev_warn(runtime->dev, "Unable to add GPIO mapping table\n");
0197 
0198     /* Select codec ASRC clock source to track I2S1 clock, because codec
0199      * is in slave mode and 100fs I2S format (BCLK = 100 * LRCLK) cannot
0200      * be supported by RT5672. Otherwise, ASRC will be disabled and cause
0201      * noise.
0202      */
0203     rt5670_sel_asrc_clk_src(component,
0204                 RT5670_DA_STEREO_FILTER
0205                 | RT5670_DA_MONO_L_FILTER
0206                 | RT5670_DA_MONO_R_FILTER
0207                 | RT5670_AD_STEREO_FILTER
0208                 | RT5670_AD_MONO_L_FILTER
0209                 | RT5670_AD_MONO_R_FILTER,
0210                 RT5670_CLK_SEL_I2S1_ASRC);
0211 
0212     if (ctx->use_ssp0) {
0213         ret = snd_soc_dapm_add_routes(&runtime->card->dapm,
0214                           cht_audio_ssp0_map,
0215                           ARRAY_SIZE(cht_audio_ssp0_map));
0216     } else {
0217         ret = snd_soc_dapm_add_routes(&runtime->card->dapm,
0218                           cht_audio_ssp2_map,
0219                           ARRAY_SIZE(cht_audio_ssp2_map));
0220     }
0221     if (ret)
0222         return ret;
0223 
0224     ret = snd_soc_card_jack_new_pins(runtime->card, "Headset",
0225                      SND_JACK_HEADSET | SND_JACK_BTN_0 |
0226                      SND_JACK_BTN_1 | SND_JACK_BTN_2,
0227                      &ctx->headset,
0228                      cht_bsw_headset_pins,
0229                      ARRAY_SIZE(cht_bsw_headset_pins));
0230         if (ret)
0231                 return ret;
0232 
0233     snd_jack_set_key(ctx->headset.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
0234     snd_jack_set_key(ctx->headset.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
0235     snd_jack_set_key(ctx->headset.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
0236 
0237     rt5670_set_jack_detect(component, &ctx->headset);
0238     if (ctx->mclk) {
0239         /*
0240          * The firmware might enable the clock at
0241          * boot (this information may or may not
0242          * be reflected in the enable clock register).
0243          * To change the rate we must disable the clock
0244          * first to cover these cases. Due to common
0245          * clock framework restrictions that do not allow
0246          * to disable a clock that has not been enabled,
0247          * we need to enable the clock first.
0248          */
0249         ret = clk_prepare_enable(ctx->mclk);
0250         if (!ret)
0251             clk_disable_unprepare(ctx->mclk);
0252 
0253         ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
0254 
0255         if (ret) {
0256             dev_err(runtime->dev, "unable to set MCLK rate\n");
0257             return ret;
0258         }
0259     }
0260     return 0;
0261 }
0262 
0263 static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd,
0264                 struct snd_pcm_hw_params *params)
0265 {
0266     struct cht_mc_private *ctx = snd_soc_card_get_drvdata(rtd->card);
0267     struct snd_interval *rate = hw_param_interval(params,
0268             SNDRV_PCM_HW_PARAM_RATE);
0269     struct snd_interval *channels = hw_param_interval(params,
0270                         SNDRV_PCM_HW_PARAM_CHANNELS);
0271     int ret, bits;
0272 
0273     /* The DSP will covert the FE rate to 48k, stereo, 24bits */
0274     rate->min = rate->max = 48000;
0275     channels->min = channels->max = 2;
0276 
0277     if (ctx->use_ssp0) {
0278         /* set SSP0 to 16-bit */
0279         params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
0280         bits = 16;
0281     } else {
0282         /* set SSP2 to 24-bit */
0283         params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
0284         bits = 24;
0285     }
0286 
0287     /*
0288      * The default mode for the cpu-dai is TDM 4 slot. The default mode
0289      * for the codec-dai is I2S. So we need to either set the cpu-dai to
0290      * I2S mode to match the codec-dai, or set the codec-dai to TDM 4 slot
0291      * (or program both to yet another mode).
0292      * One board, the Lenovo Miix 2 10, uses not 1 but 2 codecs connected
0293      * to SSP2. The second piggy-backed, output-only codec is inside the
0294      * keyboard-dock (which has extra speakers). Unlike the main rt5672
0295      * codec, we cannot configure this codec, it is hard coded to use
0296      * 2 channel 24 bit I2S. For this to work we must use I2S mode on this
0297      * board. Since we only support 2 channels anyways, there is no need
0298      * for TDM on any cht-bsw-rt5672 designs. So we use I2S 2ch everywhere.
0299      */
0300     ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
0301                   SND_SOC_DAIFMT_I2S     |
0302                   SND_SOC_DAIFMT_NB_NF   |
0303                   SND_SOC_DAIFMT_BP_FP);
0304     if (ret < 0) {
0305         dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
0306         return ret;
0307     }
0308 
0309     ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits);
0310     if (ret < 0) {
0311         dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
0312         return ret;
0313     }
0314 
0315     return 0;
0316 }
0317 
0318 static int cht_aif1_startup(struct snd_pcm_substream *substream)
0319 {
0320     return snd_pcm_hw_constraint_single(substream->runtime,
0321             SNDRV_PCM_HW_PARAM_RATE, 48000);
0322 }
0323 
0324 static const struct snd_soc_ops cht_aif1_ops = {
0325     .startup = cht_aif1_startup,
0326 };
0327 
0328 static const struct snd_soc_ops cht_be_ssp2_ops = {
0329     .hw_params = cht_aif1_hw_params,
0330 };
0331 
0332 SND_SOC_DAILINK_DEF(dummy,
0333     DAILINK_COMP_ARRAY(COMP_DUMMY()));
0334 
0335 SND_SOC_DAILINK_DEF(media,
0336     DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
0337 
0338 SND_SOC_DAILINK_DEF(deepbuffer,
0339     DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
0340 
0341 SND_SOC_DAILINK_DEF(ssp2_port,
0342     DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
0343 SND_SOC_DAILINK_DEF(ssp2_codec,
0344     DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5670:00",
0345                       "rt5670-aif1")));
0346 
0347 SND_SOC_DAILINK_DEF(platform,
0348     DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
0349 
0350 static struct snd_soc_dai_link cht_dailink[] = {
0351     /* Front End DAI links */
0352     [MERR_DPCM_AUDIO] = {
0353         .name = "Audio Port",
0354         .stream_name = "Audio",
0355         .nonatomic = true,
0356         .dynamic = 1,
0357         .dpcm_playback = 1,
0358         .dpcm_capture = 1,
0359         .ops = &cht_aif1_ops,
0360         SND_SOC_DAILINK_REG(media, dummy, platform),
0361     },
0362     [MERR_DPCM_DEEP_BUFFER] = {
0363         .name = "Deep-Buffer Audio Port",
0364         .stream_name = "Deep-Buffer Audio",
0365         .nonatomic = true,
0366         .dynamic = 1,
0367         .dpcm_playback = 1,
0368         .ops = &cht_aif1_ops,
0369         SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
0370     },
0371 
0372     /* Back End DAI links */
0373     {
0374         /* SSP2 - Codec */
0375         .name = "SSP2-Codec",
0376         .id = 0,
0377         .no_pcm = 1,
0378         .init = cht_codec_init,
0379         .be_hw_params_fixup = cht_codec_fixup,
0380         .dpcm_playback = 1,
0381         .dpcm_capture = 1,
0382         .ops = &cht_be_ssp2_ops,
0383         SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
0384     },
0385 };
0386 
0387 static int cht_suspend_pre(struct snd_soc_card *card)
0388 {
0389     struct snd_soc_component *component;
0390     struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
0391 
0392     for_each_card_components(card, component) {
0393         if (!strncmp(component->name,
0394                  ctx->codec_name, sizeof(ctx->codec_name))) {
0395 
0396             dev_dbg(component->dev, "disabling jack detect before going to suspend.\n");
0397             rt5670_jack_suspend(component);
0398             break;
0399         }
0400     }
0401     return 0;
0402 }
0403 
0404 static int cht_resume_post(struct snd_soc_card *card)
0405 {
0406     struct snd_soc_component *component;
0407     struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
0408 
0409     for_each_card_components(card, component) {
0410         if (!strncmp(component->name,
0411                  ctx->codec_name, sizeof(ctx->codec_name))) {
0412 
0413             dev_dbg(component->dev, "enabling jack detect for resume.\n");
0414             rt5670_jack_resume(component);
0415             break;
0416         }
0417     }
0418 
0419     return 0;
0420 }
0421 
0422 /* use space before codec name to simplify card ID, and simplify driver name */
0423 #define SOF_CARD_NAME "bytcht rt5672" /* card name will be 'sof-bytcht rt5672' */
0424 #define SOF_DRIVER_NAME "SOF"
0425 
0426 #define CARD_NAME "cht-bsw-rt5672"
0427 #define DRIVER_NAME NULL /* card name will be used for driver name */
0428 
0429 /* SoC card */
0430 static struct snd_soc_card snd_soc_card_cht = {
0431     .owner = THIS_MODULE,
0432     .dai_link = cht_dailink,
0433     .num_links = ARRAY_SIZE(cht_dailink),
0434     .dapm_widgets = cht_dapm_widgets,
0435     .num_dapm_widgets = ARRAY_SIZE(cht_dapm_widgets),
0436     .dapm_routes = cht_audio_map,
0437     .num_dapm_routes = ARRAY_SIZE(cht_audio_map),
0438     .controls = cht_mc_controls,
0439     .num_controls = ARRAY_SIZE(cht_mc_controls),
0440     .suspend_pre = cht_suspend_pre,
0441     .resume_post = cht_resume_post,
0442 };
0443 
0444 #define RT5672_I2C_DEFAULT  "i2c-10EC5670:00"
0445 
0446 static int snd_cht_mc_probe(struct platform_device *pdev)
0447 {
0448     int ret_val = 0;
0449     struct cht_mc_private *drv;
0450     struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
0451     const char *platform_name;
0452     struct acpi_device *adev;
0453     bool sof_parent;
0454     int dai_index = 0;
0455     int i;
0456 
0457     drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
0458     if (!drv)
0459         return -ENOMEM;
0460 
0461     strcpy(drv->codec_name, RT5672_I2C_DEFAULT);
0462 
0463     /* find index of codec dai */
0464     for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) {
0465         if (!strcmp(cht_dailink[i].codecs->name, RT5672_I2C_DEFAULT)) {
0466             dai_index = i;
0467             break;
0468         }
0469     }
0470 
0471     /* fixup codec name based on HID */
0472     adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
0473     if (adev) {
0474         snprintf(drv->codec_name, sizeof(drv->codec_name),
0475              "i2c-%s", acpi_dev_name(adev));
0476         put_device(&adev->dev);
0477         cht_dailink[dai_index].codecs->name = drv->codec_name;
0478     }
0479 
0480     /* Use SSP0 on Bay Trail CR devices */
0481     if (soc_intel_is_byt() && mach->mach_params.acpi_ipc_irq_index == 0) {
0482         cht_dailink[dai_index].cpus->dai_name = "ssp0-port";
0483         drv->use_ssp0 = true;
0484     }
0485 
0486     /* override platform name, if required */
0487     snd_soc_card_cht.dev = &pdev->dev;
0488     platform_name = mach->mach_params.platform;
0489 
0490     ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht,
0491                             platform_name);
0492     if (ret_val)
0493         return ret_val;
0494 
0495     snd_soc_card_cht.components = rt5670_components();
0496 
0497     drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
0498     if (IS_ERR(drv->mclk)) {
0499         dev_err(&pdev->dev,
0500             "Failed to get MCLK from pmc_plt_clk_3: %ld\n",
0501             PTR_ERR(drv->mclk));
0502         return PTR_ERR(drv->mclk);
0503     }
0504     snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
0505 
0506     sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
0507 
0508     /* set card and driver name */
0509     if (sof_parent) {
0510         snd_soc_card_cht.name = SOF_CARD_NAME;
0511         snd_soc_card_cht.driver_name = SOF_DRIVER_NAME;
0512     } else {
0513         snd_soc_card_cht.name = CARD_NAME;
0514         snd_soc_card_cht.driver_name = DRIVER_NAME;
0515     }
0516 
0517     /* set pm ops */
0518     if (sof_parent)
0519         pdev->dev.driver->pm = &snd_soc_pm_ops;
0520 
0521     /* register the soc card */
0522     ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
0523     if (ret_val) {
0524         dev_err(&pdev->dev,
0525             "snd_soc_register_card failed %d\n", ret_val);
0526         return ret_val;
0527     }
0528     platform_set_drvdata(pdev, &snd_soc_card_cht);
0529     return ret_val;
0530 }
0531 
0532 static struct platform_driver snd_cht_mc_driver = {
0533     .driver = {
0534         .name = "cht-bsw-rt5672",
0535     },
0536     .probe = snd_cht_mc_probe,
0537 };
0538 
0539 module_platform_driver(snd_cht_mc_driver);
0540 
0541 MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");
0542 MODULE_AUTHOR("Subhransu S. Prusty, Mengdong Lin");
0543 MODULE_LICENSE("GPL v2");
0544 MODULE_ALIAS("platform:cht-bsw-rt5672");