~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/boards/byt-rt5640.c

Version: ~ [ linux-5.10-rc5 ] ~ [ linux-5.9.10 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.79 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.159 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.208 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.245 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.245 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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");
225 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp