1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * n810.c -- SoC audio for Nokia N810 4 * 5 * Copyright (C) 2008 Nokia Corporation 6 * 7 * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com> 8 */ 9 10 #include <linux/clk.h> 11 #include <linux/i2c.h> 12 #include <linux/platform_device.h> 13 #include <sound/core.h> 14 #include <sound/pcm.h> 15 #include <sound/soc.h> 16 17 #include <asm/mach-types.h> 18 #include <linux/gpio.h> 19 #include <linux/module.h> 20 #include <linux/platform_data/asoc-ti-mcbsp.h> 21 22 #include "omap-mcbsp.h" 23 24 #define N810_HEADSET_AMP_GPIO 10 25 #define N810_SPEAKER_AMP_GPIO 101 26 27 enum { 28 N810_JACK_DISABLED, 29 N810_JACK_HP, 30 N810_JACK_HS, 31 N810_JACK_MIC, 32 }; 33 34 static struct clk *sys_clkout2; 35 static struct clk *sys_clkout2_src; 36 static struct clk *func96m_clk; 37 38 static int n810_spk_func; 39 static int n810_jack_func; 40 static int n810_dmic_func; 41 42 static void n810_ext_control(struct snd_soc_dapm_context *dapm) 43 { 44 int hp = 0, line1l = 0; 45 46 switch (n810_jack_func) { 47 case N810_JACK_HS: 48 line1l = 1; 49 case N810_JACK_HP: 50 hp = 1; 51 break; 52 case N810_JACK_MIC: 53 line1l = 1; 54 break; 55 } 56 57 snd_soc_dapm_mutex_lock(dapm); 58 59 if (n810_spk_func) 60 snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk"); 61 else 62 snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk"); 63 64 if (hp) 65 snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); 66 else 67 snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); 68 if (line1l) 69 snd_soc_dapm_enable_pin_unlocked(dapm, "HS Mic"); 70 else 71 snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic"); 72 73 if (n810_dmic_func) 74 snd_soc_dapm_enable_pin_unlocked(dapm, "DMic"); 75 else 76 snd_soc_dapm_disable_pin_unlocked(dapm, "DMic"); 77 78 snd_soc_dapm_sync_unlocked(dapm); 79 80 snd_soc_dapm_mutex_unlock(dapm); 81 } 82 83 static int n810_startup(struct snd_pcm_substream *substream) 84 { 85 struct snd_pcm_runtime *runtime = substream->runtime; 86 struct snd_soc_pcm_runtime *rtd = substream->private_data; 87 88 snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2); 89 90 n810_ext_control(&rtd->card->dapm); 91 return clk_prepare_enable(sys_clkout2); 92 } 93 94 static void n810_shutdown(struct snd_pcm_substream *substream) 95 { 96 clk_disable_unprepare(sys_clkout2); 97 } 98 99 static int n810_hw_params(struct snd_pcm_substream *substream, 100 struct snd_pcm_hw_params *params) 101 { 102 struct snd_soc_pcm_runtime *rtd = substream->private_data; 103 struct snd_soc_dai *codec_dai = rtd->codec_dai; 104 int err; 105 106 /* Set the codec system clock for DAC and ADC */ 107 err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000, 108 SND_SOC_CLOCK_IN); 109 110 return err; 111 } 112 113 static const struct snd_soc_ops n810_ops = { 114 .startup = n810_startup, 115 .hw_params = n810_hw_params, 116 .shutdown = n810_shutdown, 117 }; 118 119 static int n810_get_spk(struct snd_kcontrol *kcontrol, 120 struct snd_ctl_elem_value *ucontrol) 121 { 122 ucontrol->value.enumerated.item[0] = n810_spk_func; 123 124 return 0; 125 } 126 127 static int n810_set_spk(struct snd_kcontrol *kcontrol, 128 struct snd_ctl_elem_value *ucontrol) 129 { 130 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); 131 132 if (n810_spk_func == ucontrol->value.enumerated.item[0]) 133 return 0; 134 135 n810_spk_func = ucontrol->value.enumerated.item[0]; 136 n810_ext_control(&card->dapm); 137 138 return 1; 139 } 140 141 static int n810_get_jack(struct snd_kcontrol *kcontrol, 142 struct snd_ctl_elem_value *ucontrol) 143 { 144 ucontrol->value.enumerated.item[0] = n810_jack_func; 145 146 return 0; 147 } 148 149 static int n810_set_jack(struct snd_kcontrol *kcontrol, 150 struct snd_ctl_elem_value *ucontrol) 151 { 152 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); 153 154 if (n810_jack_func == ucontrol->value.enumerated.item[0]) 155 return 0; 156 157 n810_jack_func = ucontrol->value.enumerated.item[0]; 158 n810_ext_control(&card->dapm); 159 160 return 1; 161 } 162 163 static int n810_get_input(struct snd_kcontrol *kcontrol, 164 struct snd_ctl_elem_value *ucontrol) 165 { 166 ucontrol->value.enumerated.item[0] = n810_dmic_func; 167 168 return 0; 169 } 170 171 static int n810_set_input(struct snd_kcontrol *kcontrol, 172 struct snd_ctl_elem_value *ucontrol) 173 { 174 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); 175 176 if (n810_dmic_func == ucontrol->value.enumerated.item[0]) 177 return 0; 178 179 n810_dmic_func = ucontrol->value.enumerated.item[0]; 180 n810_ext_control(&card->dapm); 181 182 return 1; 183 } 184 185 static int n810_spk_event(struct snd_soc_dapm_widget *w, 186 struct snd_kcontrol *k, int event) 187 { 188 if (SND_SOC_DAPM_EVENT_ON(event)) 189 gpio_set_value(N810_SPEAKER_AMP_GPIO, 1); 190 else 191 gpio_set_value(N810_SPEAKER_AMP_GPIO, 0); 192 193 return 0; 194 } 195 196 static int n810_jack_event(struct snd_soc_dapm_widget *w, 197 struct snd_kcontrol *k, int event) 198 { 199 if (SND_SOC_DAPM_EVENT_ON(event)) 200 gpio_set_value(N810_HEADSET_AMP_GPIO, 1); 201 else 202 gpio_set_value(N810_HEADSET_AMP_GPIO, 0); 203 204 return 0; 205 } 206 207 static const struct snd_soc_dapm_widget aic33_dapm_widgets[] = { 208 SND_SOC_DAPM_SPK("Ext Spk", n810_spk_event), 209 SND_SOC_DAPM_HP("Headphone Jack", n810_jack_event), 210 SND_SOC_DAPM_MIC("DMic", NULL), 211 SND_SOC_DAPM_MIC("HS Mic", NULL), 212 }; 213 214 static const struct snd_soc_dapm_route audio_map[] = { 215 {"Headphone Jack", NULL, "HPLOUT"}, 216 {"Headphone Jack", NULL, "HPROUT"}, 217 218 {"Ext Spk", NULL, "LLOUT"}, 219 {"Ext Spk", NULL, "RLOUT"}, 220 221 {"DMic Rate 64", NULL, "DMic"}, 222 {"DMic", NULL, "Mic Bias"}, 223 224 /* 225 * Note that the mic bias is coming from Retu/Vilma and we don't have 226 * control over it atm. The analog HS mic is not working. <- TODO 227 */ 228 {"LINE1L", NULL, "HS Mic"}, 229 }; 230 231 static const char *spk_function[] = {"Off", "On"}; 232 static const char *jack_function[] = {"Off", "Headphone", "Headset", "Mic"}; 233 static const char *input_function[] = {"ADC", "Digital Mic"}; 234 static const struct soc_enum n810_enum[] = { 235 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), 236 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function), 237 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function), 238 }; 239 240 static const struct snd_kcontrol_new aic33_n810_controls[] = { 241 SOC_ENUM_EXT("Speaker Function", n810_enum[0], 242 n810_get_spk, n810_set_spk), 243 SOC_ENUM_EXT("Jack Function", n810_enum[1], 244 n810_get_jack, n810_set_jack), 245 SOC_ENUM_EXT("Input Select", n810_enum[2], 246 n810_get_input, n810_set_input), 247 }; 248 249 /* Digital audio interface glue - connects codec <--> CPU */ 250 static struct snd_soc_dai_link n810_dai = { 251 .name = "TLV320AIC33", 252 .stream_name = "AIC33", 253 .cpu_dai_name = "48076000.mcbsp", 254 .platform_name = "48076000.mcbsp", 255 .codec_name = "tlv320aic3x-codec.1-0018", 256 .codec_dai_name = "tlv320aic3x-hifi", 257 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 258 SND_SOC_DAIFMT_CBM_CFM, 259 .ops = &n810_ops, 260 }; 261 262 /* Audio machine driver */ 263 static struct snd_soc_card snd_soc_n810 = { 264 .name = "N810", 265 .owner = THIS_MODULE, 266 .dai_link = &n810_dai, 267 .num_links = 1, 268 269 .controls = aic33_n810_controls, 270 .num_controls = ARRAY_SIZE(aic33_n810_controls), 271 .dapm_widgets = aic33_dapm_widgets, 272 .num_dapm_widgets = ARRAY_SIZE(aic33_dapm_widgets), 273 .dapm_routes = audio_map, 274 .num_dapm_routes = ARRAY_SIZE(audio_map), 275 .fully_routed = true, 276 }; 277 278 static struct platform_device *n810_snd_device; 279 280 static int __init n810_soc_init(void) 281 { 282 int err; 283 struct device *dev; 284 285 if (!of_have_populated_dt() || 286 (!of_machine_is_compatible("nokia,n810") && 287 !of_machine_is_compatible("nokia,n810-wimax"))) 288 return -ENODEV; 289 290 n810_snd_device = platform_device_alloc("soc-audio", -1); 291 if (!n810_snd_device) 292 return -ENOMEM; 293 294 platform_set_drvdata(n810_snd_device, &snd_soc_n810); 295 err = platform_device_add(n810_snd_device); 296 if (err) 297 goto err1; 298 299 dev = &n810_snd_device->dev; 300 301 sys_clkout2_src = clk_get(dev, "sys_clkout2_src"); 302 if (IS_ERR(sys_clkout2_src)) { 303 dev_err(dev, "Could not get sys_clkout2_src clock\n"); 304 err = PTR_ERR(sys_clkout2_src); 305 goto err2; 306 } 307 sys_clkout2 = clk_get(dev, "sys_clkout2"); 308 if (IS_ERR(sys_clkout2)) { 309 dev_err(dev, "Could not get sys_clkout2\n"); 310 err = PTR_ERR(sys_clkout2); 311 goto err3; 312 } 313 /* 314 * Configure 12 MHz output on SYS_CLKOUT2. Therefore we must use 315 * 96 MHz as its parent in order to get 12 MHz 316 */ 317 func96m_clk = clk_get(dev, "func_96m_ck"); 318 if (IS_ERR(func96m_clk)) { 319 dev_err(dev, "Could not get func 96M clock\n"); 320 err = PTR_ERR(func96m_clk); 321 goto err4; 322 } 323 clk_set_parent(sys_clkout2_src, func96m_clk); 324 clk_set_rate(sys_clkout2, 12000000); 325 326 if (WARN_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) || 327 (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0))) { 328 err = -EINVAL; 329 goto err4; 330 } 331 332 gpio_direction_output(N810_HEADSET_AMP_GPIO, 0); 333 gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0); 334 335 return 0; 336 err4: 337 clk_put(sys_clkout2); 338 err3: 339 clk_put(sys_clkout2_src); 340 err2: 341 platform_device_del(n810_snd_device); 342 err1: 343 platform_device_put(n810_snd_device); 344 345 return err; 346 } 347 348 static void __exit n810_soc_exit(void) 349 { 350 gpio_free(N810_SPEAKER_AMP_GPIO); 351 gpio_free(N810_HEADSET_AMP_GPIO); 352 clk_put(sys_clkout2_src); 353 clk_put(sys_clkout2); 354 clk_put(func96m_clk); 355 356 platform_device_unregister(n810_snd_device); 357 } 358 359 module_init(n810_soc_init); 360 module_exit(n810_soc_exit); 361 362 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>"); 363 MODULE_DESCRIPTION("ALSA SoC Nokia N810"); 364 MODULE_LICENSE("GPL"); 365