root/sound/soc/intel/boards/byt-rt5640.c

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

DEFINITIONS

This source file includes following definitions.
  1. byt_rt5640_hw_params
  2. byt_rt5640_quirk_cb
  3. byt_rt5640_init
  4. byt_rt5640_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Intel Baytrail SST RT5640 machine driver
   4  * Copyright (c) 2014, Intel Corporation.
   5  */
   6 
   7 #include <linux/init.h>
   8 #include <linux/module.h>
   9 #include <linux/platform_device.h>
  10 #include <linux/acpi.h>
  11 #include <linux/device.h>
  12 #include <linux/dmi.h>
  13 #include <linux/slab.h>
  14 #include <sound/pcm.h>
  15 #include <sound/pcm_params.h>
  16 #include <sound/soc.h>
  17 #include <sound/jack.h>
  18 #include "../../codecs/rt5640.h"
  19 
  20 #include "../common/sst-dsp.h"
  21 
  22 static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
  23         SND_SOC_DAPM_HP("Headphone", NULL),
  24         SND_SOC_DAPM_MIC("Headset Mic", NULL),
  25         SND_SOC_DAPM_MIC("Internal Mic", NULL),
  26         SND_SOC_DAPM_SPK("Speaker", NULL),
  27 };
  28 
  29 static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
  30         {"Headset Mic", NULL, "MICBIAS1"},
  31         {"IN2P", NULL, "Headset Mic"},
  32         {"Headphone", NULL, "HPOL"},
  33         {"Headphone", NULL, "HPOR"},
  34         {"Speaker", NULL, "SPOLP"},
  35         {"Speaker", NULL, "SPOLN"},
  36         {"Speaker", NULL, "SPORP"},
  37         {"Speaker", NULL, "SPORN"},
  38 };
  39 
  40 static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {
  41         {"DMIC1", NULL, "Internal Mic"},
  42 };
  43 
  44 static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {
  45         {"DMIC2", NULL, "Internal Mic"},
  46 };
  47 
  48 static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
  49         {"Internal Mic", NULL, "MICBIAS1"},
  50         {"IN1P", NULL, "Internal Mic"},
  51 };
  52 
  53 enum {
  54         BYT_RT5640_DMIC1_MAP,
  55         BYT_RT5640_DMIC2_MAP,
  56         BYT_RT5640_IN1_MAP,
  57 };
  58 
  59 #define BYT_RT5640_MAP(quirk)   ((quirk) & 0xff)
  60 #define BYT_RT5640_DMIC_EN      BIT(16)
  61 
  62 static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP |
  63                                         BYT_RT5640_DMIC_EN;
  64 
  65 static const struct snd_kcontrol_new byt_rt5640_controls[] = {
  66         SOC_DAPM_PIN_SWITCH("Headphone"),
  67         SOC_DAPM_PIN_SWITCH("Headset Mic"),
  68         SOC_DAPM_PIN_SWITCH("Internal Mic"),
  69         SOC_DAPM_PIN_SWITCH("Speaker"),
  70 };
  71 
  72 static int byt_rt5640_hw_params(struct snd_pcm_substream *substream,
  73                                 struct snd_pcm_hw_params *params)
  74 {
  75         struct snd_soc_pcm_runtime *rtd = substream->private_data;
  76         struct snd_soc_dai *codec_dai = rtd->codec_dai;
  77         int ret;
  78 
  79         ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1,
  80                                      params_rate(params) * 256,
  81                                      SND_SOC_CLOCK_IN);
  82         if (ret < 0) {
  83                 dev_err(codec_dai->dev, "can't set codec clock %d\n", ret);
  84                 return ret;
  85         }
  86         ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1,
  87                                   params_rate(params) * 64,
  88                                   params_rate(params) * 256);
  89         if (ret < 0) {
  90                 dev_err(codec_dai->dev, "can't set codec pll: %d\n", ret);
  91                 return ret;
  92         }
  93         return 0;
  94 }
  95 
  96 static int byt_rt5640_quirk_cb(const struct dmi_system_id *id)
  97 {
  98         byt_rt5640_quirk = (unsigned long)id->driver_data;
  99         return 1;
 100 }
 101 
 102 static const struct dmi_system_id byt_rt5640_quirk_table[] = {
 103         {
 104                 .callback = byt_rt5640_quirk_cb,
 105                 .matches = {
 106                         DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 107                         DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"),
 108                 },
 109                 .driver_data = (unsigned long *)BYT_RT5640_IN1_MAP,
 110         },
 111         {
 112                 .callback = byt_rt5640_quirk_cb,
 113                 .matches = {
 114                         DMI_MATCH(DMI_SYS_VENDOR, "DellInc."),
 115                         DMI_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"),
 116                 },
 117                 .driver_data = (unsigned long *)(BYT_RT5640_DMIC2_MAP |
 118                                                  BYT_RT5640_DMIC_EN),
 119         },
 120         {}
 121 };
 122 
 123 static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
 124 {
 125         int ret;
 126         struct snd_soc_component *component = runtime->codec_dai->component;
 127         struct snd_soc_card *card = runtime->card;
 128         const struct snd_soc_dapm_route *custom_map;
 129         int num_routes;
 130 
 131         card->dapm.idle_bias_off = true;
 132 
 133         ret = snd_soc_add_card_controls(card, byt_rt5640_controls,
 134                                         ARRAY_SIZE(byt_rt5640_controls));
 135         if (ret) {
 136                 dev_err(card->dev, "unable to add card controls\n");
 137                 return ret;
 138         }
 139 
 140         dmi_check_system(byt_rt5640_quirk_table);
 141         switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
 142         case BYT_RT5640_IN1_MAP:
 143                 custom_map = byt_rt5640_intmic_in1_map;
 144                 num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map);
 145                 break;
 146         case BYT_RT5640_DMIC2_MAP:
 147                 custom_map = byt_rt5640_intmic_dmic2_map;
 148                 num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);
 149                 break;
 150         default:
 151                 custom_map = byt_rt5640_intmic_dmic1_map;
 152                 num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
 153         }
 154 
 155         ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
 156         if (ret)
 157                 return ret;
 158 
 159         if (byt_rt5640_quirk & BYT_RT5640_DMIC_EN) {
 160                 ret = rt5640_dmic_enable(component, 0, 0);
 161                 if (ret)
 162                         return ret;
 163         }
 164 
 165         snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
 166         snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
 167 
 168         return ret;
 169 }
 170 
 171 static struct snd_soc_ops byt_rt5640_ops = {
 172         .hw_params = byt_rt5640_hw_params,
 173 };
 174 
 175 SND_SOC_DAILINK_DEFS(audio,
 176         DAILINK_COMP_ARRAY(COMP_CPU("baytrail-pcm-audio")),
 177         DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5640:00", "rt5640-aif1")),
 178         DAILINK_COMP_ARRAY(COMP_PLATFORM("baytrail-pcm-audio")));
 179 
 180 static struct snd_soc_dai_link byt_rt5640_dais[] = {
 181         {
 182                 .name = "Baytrail Audio",
 183                 .stream_name = "Audio",
 184                 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 185                            SND_SOC_DAIFMT_CBS_CFS,
 186                 .init = byt_rt5640_init,
 187                 .ops = &byt_rt5640_ops,
 188                 SND_SOC_DAILINK_REG(audio),
 189         },
 190 };
 191 
 192 static struct snd_soc_card byt_rt5640_card = {
 193         .name = "byt-rt5640",
 194         .owner = THIS_MODULE,
 195         .dai_link = byt_rt5640_dais,
 196         .num_links = ARRAY_SIZE(byt_rt5640_dais),
 197         .dapm_widgets = byt_rt5640_widgets,
 198         .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets),
 199         .dapm_routes = byt_rt5640_audio_map,
 200         .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map),
 201         .fully_routed = true,
 202 };
 203 
 204 static int byt_rt5640_probe(struct platform_device *pdev)
 205 {
 206         struct snd_soc_card *card = &byt_rt5640_card;
 207 
 208         card->dev = &pdev->dev;
 209         return devm_snd_soc_register_card(&pdev->dev, card);
 210 }
 211 
 212 static struct platform_driver byt_rt5640_audio = {
 213         .probe = byt_rt5640_probe,
 214         .driver = {
 215                 .name = "byt-rt5640",
 216                 .pm = &snd_soc_pm_ops,
 217         },
 218 };
 219 module_platform_driver(byt_rt5640_audio)
 220 
 221 MODULE_DESCRIPTION("ASoC Intel(R) Baytrail Machine driver");
 222 MODULE_AUTHOR("Omair Md Abdullah, Jarkko Nikula");
 223 MODULE_LICENSE("GPL v2");
 224 MODULE_ALIAS("platform:byt-rt5640");

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