Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * n810.c  --  SoC audio for Nokia N810
0004  *
0005  * Copyright (C) 2008 Nokia Corporation
0006  *
0007  * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
0008  */
0009 
0010 #include <linux/clk.h>
0011 #include <linux/i2c.h>
0012 #include <linux/platform_device.h>
0013 #include <sound/core.h>
0014 #include <sound/pcm.h>
0015 #include <sound/soc.h>
0016 
0017 #include <asm/mach-types.h>
0018 #include <linux/gpio.h>
0019 #include <linux/module.h>
0020 #include <linux/platform_data/asoc-ti-mcbsp.h>
0021 
0022 #include "omap-mcbsp.h"
0023 
0024 #define N810_HEADSET_AMP_GPIO   10
0025 #define N810_SPEAKER_AMP_GPIO   101
0026 
0027 enum {
0028     N810_JACK_DISABLED,
0029     N810_JACK_HP,
0030     N810_JACK_HS,
0031     N810_JACK_MIC,
0032 };
0033 
0034 static struct clk *sys_clkout2;
0035 static struct clk *sys_clkout2_src;
0036 static struct clk *func96m_clk;
0037 
0038 static int n810_spk_func;
0039 static int n810_jack_func;
0040 static int n810_dmic_func;
0041 
0042 static void n810_ext_control(struct snd_soc_dapm_context *dapm)
0043 {
0044     int hp = 0, line1l = 0;
0045 
0046     switch (n810_jack_func) {
0047     case N810_JACK_HS:
0048         line1l = 1;
0049         fallthrough;
0050     case N810_JACK_HP:
0051         hp = 1;
0052         break;
0053     case N810_JACK_MIC:
0054         line1l = 1;
0055         break;
0056     }
0057 
0058     snd_soc_dapm_mutex_lock(dapm);
0059 
0060     if (n810_spk_func)
0061         snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk");
0062     else
0063         snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk");
0064 
0065     if (hp)
0066         snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack");
0067     else
0068         snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
0069     if (line1l)
0070         snd_soc_dapm_enable_pin_unlocked(dapm, "HS Mic");
0071     else
0072         snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic");
0073 
0074     if (n810_dmic_func)
0075         snd_soc_dapm_enable_pin_unlocked(dapm, "DMic");
0076     else
0077         snd_soc_dapm_disable_pin_unlocked(dapm, "DMic");
0078 
0079     snd_soc_dapm_sync_unlocked(dapm);
0080 
0081     snd_soc_dapm_mutex_unlock(dapm);
0082 }
0083 
0084 static int n810_startup(struct snd_pcm_substream *substream)
0085 {
0086     struct snd_pcm_runtime *runtime = substream->runtime;
0087     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0088 
0089     snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2);
0090 
0091     n810_ext_control(&rtd->card->dapm);
0092     return clk_prepare_enable(sys_clkout2);
0093 }
0094 
0095 static void n810_shutdown(struct snd_pcm_substream *substream)
0096 {
0097     clk_disable_unprepare(sys_clkout2);
0098 }
0099 
0100 static int n810_hw_params(struct snd_pcm_substream *substream,
0101     struct snd_pcm_hw_params *params)
0102 {
0103     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0104     struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0105     int err;
0106 
0107     /* Set the codec system clock for DAC and ADC */
0108     err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000,
0109                         SND_SOC_CLOCK_IN);
0110 
0111     return err;
0112 }
0113 
0114 static const struct snd_soc_ops n810_ops = {
0115     .startup = n810_startup,
0116     .hw_params = n810_hw_params,
0117     .shutdown = n810_shutdown,
0118 };
0119 
0120 static int n810_get_spk(struct snd_kcontrol *kcontrol,
0121             struct snd_ctl_elem_value *ucontrol)
0122 {
0123     ucontrol->value.enumerated.item[0] = n810_spk_func;
0124 
0125     return 0;
0126 }
0127 
0128 static int n810_set_spk(struct snd_kcontrol *kcontrol,
0129             struct snd_ctl_elem_value *ucontrol)
0130 {
0131     struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
0132 
0133     if (n810_spk_func == ucontrol->value.enumerated.item[0])
0134         return 0;
0135 
0136     n810_spk_func = ucontrol->value.enumerated.item[0];
0137     n810_ext_control(&card->dapm);
0138 
0139     return 1;
0140 }
0141 
0142 static int n810_get_jack(struct snd_kcontrol *kcontrol,
0143              struct snd_ctl_elem_value *ucontrol)
0144 {
0145     ucontrol->value.enumerated.item[0] = n810_jack_func;
0146 
0147     return 0;
0148 }
0149 
0150 static int n810_set_jack(struct snd_kcontrol *kcontrol,
0151              struct snd_ctl_elem_value *ucontrol)
0152 {
0153     struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
0154 
0155     if (n810_jack_func == ucontrol->value.enumerated.item[0])
0156         return 0;
0157 
0158     n810_jack_func = ucontrol->value.enumerated.item[0];
0159     n810_ext_control(&card->dapm);
0160 
0161     return 1;
0162 }
0163 
0164 static int n810_get_input(struct snd_kcontrol *kcontrol,
0165               struct snd_ctl_elem_value *ucontrol)
0166 {
0167     ucontrol->value.enumerated.item[0] = n810_dmic_func;
0168 
0169     return 0;
0170 }
0171 
0172 static int n810_set_input(struct snd_kcontrol *kcontrol,
0173               struct snd_ctl_elem_value *ucontrol)
0174 {
0175     struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
0176 
0177     if (n810_dmic_func == ucontrol->value.enumerated.item[0])
0178         return 0;
0179 
0180     n810_dmic_func = ucontrol->value.enumerated.item[0];
0181     n810_ext_control(&card->dapm);
0182 
0183     return 1;
0184 }
0185 
0186 static int n810_spk_event(struct snd_soc_dapm_widget *w,
0187               struct snd_kcontrol *k, int event)
0188 {
0189     if (SND_SOC_DAPM_EVENT_ON(event))
0190         gpio_set_value(N810_SPEAKER_AMP_GPIO, 1);
0191     else
0192         gpio_set_value(N810_SPEAKER_AMP_GPIO, 0);
0193 
0194     return 0;
0195 }
0196 
0197 static int n810_jack_event(struct snd_soc_dapm_widget *w,
0198                struct snd_kcontrol *k, int event)
0199 {
0200     if (SND_SOC_DAPM_EVENT_ON(event))
0201         gpio_set_value(N810_HEADSET_AMP_GPIO, 1);
0202     else
0203         gpio_set_value(N810_HEADSET_AMP_GPIO, 0);
0204 
0205     return 0;
0206 }
0207 
0208 static const struct snd_soc_dapm_widget aic33_dapm_widgets[] = {
0209     SND_SOC_DAPM_SPK("Ext Spk", n810_spk_event),
0210     SND_SOC_DAPM_HP("Headphone Jack", n810_jack_event),
0211     SND_SOC_DAPM_MIC("DMic", NULL),
0212     SND_SOC_DAPM_MIC("HS Mic", NULL),
0213 };
0214 
0215 static const struct snd_soc_dapm_route audio_map[] = {
0216     {"Headphone Jack", NULL, "HPLOUT"},
0217     {"Headphone Jack", NULL, "HPROUT"},
0218 
0219     {"Ext Spk", NULL, "LLOUT"},
0220     {"Ext Spk", NULL, "RLOUT"},
0221 
0222     {"DMic Rate 64", NULL, "DMic"},
0223     {"DMic", NULL, "Mic Bias"},
0224 
0225     /*
0226      * Note that the mic bias is coming from Retu/Vilma and we don't have
0227      * control over it atm. The analog HS mic is not working. <- TODO
0228      */
0229     {"LINE1L", NULL, "HS Mic"},
0230 };
0231 
0232 static const char *spk_function[] = {"Off", "On"};
0233 static const char *jack_function[] = {"Off", "Headphone", "Headset", "Mic"};
0234 static const char *input_function[] = {"ADC", "Digital Mic"};
0235 static const struct soc_enum n810_enum[] = {
0236     SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
0237     SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
0238     SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
0239 };
0240 
0241 static const struct snd_kcontrol_new aic33_n810_controls[] = {
0242     SOC_ENUM_EXT("Speaker Function", n810_enum[0],
0243              n810_get_spk, n810_set_spk),
0244     SOC_ENUM_EXT("Jack Function", n810_enum[1],
0245              n810_get_jack, n810_set_jack),
0246     SOC_ENUM_EXT("Input Select",  n810_enum[2],
0247              n810_get_input, n810_set_input),
0248 };
0249 
0250 /* Digital audio interface glue - connects codec <--> CPU */
0251 SND_SOC_DAILINK_DEFS(aic33,
0252     DAILINK_COMP_ARRAY(COMP_CPU("48076000.mcbsp")),
0253     DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018",
0254                       "tlv320aic3x-hifi")),
0255     DAILINK_COMP_ARRAY(COMP_PLATFORM("48076000.mcbsp")));
0256 
0257 static struct snd_soc_dai_link n810_dai = {
0258     .name = "TLV320AIC33",
0259     .stream_name = "AIC33",
0260     .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0261            SND_SOC_DAIFMT_CBM_CFM,
0262     .ops = &n810_ops,
0263     SND_SOC_DAILINK_REG(aic33),
0264 };
0265 
0266 /* Audio machine driver */
0267 static struct snd_soc_card snd_soc_n810 = {
0268     .name = "N810",
0269     .owner = THIS_MODULE,
0270     .dai_link = &n810_dai,
0271     .num_links = 1,
0272 
0273     .controls = aic33_n810_controls,
0274     .num_controls = ARRAY_SIZE(aic33_n810_controls),
0275     .dapm_widgets = aic33_dapm_widgets,
0276     .num_dapm_widgets = ARRAY_SIZE(aic33_dapm_widgets),
0277     .dapm_routes = audio_map,
0278     .num_dapm_routes = ARRAY_SIZE(audio_map),
0279     .fully_routed = true,
0280 };
0281 
0282 static struct platform_device *n810_snd_device;
0283 
0284 static int __init n810_soc_init(void)
0285 {
0286     int err;
0287     struct device *dev;
0288 
0289     if (!of_have_populated_dt() ||
0290         (!of_machine_is_compatible("nokia,n810") &&
0291          !of_machine_is_compatible("nokia,n810-wimax")))
0292         return -ENODEV;
0293 
0294     n810_snd_device = platform_device_alloc("soc-audio", -1);
0295     if (!n810_snd_device)
0296         return -ENOMEM;
0297 
0298     platform_set_drvdata(n810_snd_device, &snd_soc_n810);
0299     err = platform_device_add(n810_snd_device);
0300     if (err)
0301         goto err1;
0302 
0303     dev = &n810_snd_device->dev;
0304 
0305     sys_clkout2_src = clk_get(dev, "sys_clkout2_src");
0306     if (IS_ERR(sys_clkout2_src)) {
0307         dev_err(dev, "Could not get sys_clkout2_src clock\n");
0308         err = PTR_ERR(sys_clkout2_src);
0309         goto err2;
0310     }
0311     sys_clkout2 = clk_get(dev, "sys_clkout2");
0312     if (IS_ERR(sys_clkout2)) {
0313         dev_err(dev, "Could not get sys_clkout2\n");
0314         err = PTR_ERR(sys_clkout2);
0315         goto err3;
0316     }
0317     /*
0318      * Configure 12 MHz output on SYS_CLKOUT2. Therefore we must use
0319      * 96 MHz as its parent in order to get 12 MHz
0320      */
0321     func96m_clk = clk_get(dev, "func_96m_ck");
0322     if (IS_ERR(func96m_clk)) {
0323         dev_err(dev, "Could not get func 96M clock\n");
0324         err = PTR_ERR(func96m_clk);
0325         goto err4;
0326     }
0327     clk_set_parent(sys_clkout2_src, func96m_clk);
0328     clk_set_rate(sys_clkout2, 12000000);
0329 
0330     if (WARN_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) ||
0331             (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0))) {
0332         err = -EINVAL;
0333         goto err4;
0334     }
0335 
0336     gpio_direction_output(N810_HEADSET_AMP_GPIO, 0);
0337     gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0);
0338 
0339     return 0;
0340 err4:
0341     clk_put(sys_clkout2);
0342 err3:
0343     clk_put(sys_clkout2_src);
0344 err2:
0345     platform_device_del(n810_snd_device);
0346 err1:
0347     platform_device_put(n810_snd_device);
0348 
0349     return err;
0350 }
0351 
0352 static void __exit n810_soc_exit(void)
0353 {
0354     gpio_free(N810_SPEAKER_AMP_GPIO);
0355     gpio_free(N810_HEADSET_AMP_GPIO);
0356     clk_put(sys_clkout2_src);
0357     clk_put(sys_clkout2);
0358     clk_put(func96m_clk);
0359 
0360     platform_device_unregister(n810_snd_device);
0361 }
0362 
0363 module_init(n810_soc_init);
0364 module_exit(n810_soc_exit);
0365 
0366 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
0367 MODULE_DESCRIPTION("ALSA SoC Nokia N810");
0368 MODULE_LICENSE("GPL");