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 SND_SOC_DAILINK_DEFS(aic33, 251 DAILINK_COMP_ARRAY(COMP_CPU("48076000.mcbsp")), 252 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018", 253 "tlv320aic3x-hifi")), 254 DAILINK_COMP_ARRAY(COMP_PLATFORM("48076000.mcbsp"))); 255 256 static struct snd_soc_dai_link n810_dai = { 257 .name = "TLV320AIC33", 258 .stream_name = "AIC33", 259 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 260 SND_SOC_DAIFMT_CBM_CFM, 261 .ops = &n810_ops, 262 SND_SOC_DAILINK_REG(aic33), 263 }; 264 265 /* Audio machine driver */ 266 static struct snd_soc_card snd_soc_n810 = { 267 .name = "N810", 268 .owner = THIS_MODULE, 269 .dai_link = &n810_dai, 270 .num_links = 1, 271 272 .controls = aic33_n810_controls, 273 .num_controls = ARRAY_SIZE(aic33_n810_controls), 274 .dapm_widgets = aic33_dapm_widgets, 275 .num_dapm_widgets = ARRAY_SIZE(aic33_dapm_widgets), 276 .dapm_routes = audio_map, 277 .num_dapm_routes = ARRAY_SIZE(audio_map), 278 .fully_routed = true, 279 }; 280 281 static struct platform_device *n810_snd_device; 282 283 static int __init n810_soc_init(void) 284 { 285 int err; 286 struct device *dev; 287 288 if (!of_have_populated_dt() || 289 (!of_machine_is_compatible("nokia,n810") && 290 !of_machine_is_compatible("nokia,n810-wimax"))) 291 return -ENODEV; 292 293 n810_snd_device = platform_device_alloc("soc-audio", -1); 294 if (!n810_snd_device) 295 return -ENOMEM; 296 297 platform_set_drvdata(n810_snd_device, &snd_soc_n810); 298 err = platform_device_add(n810_snd_device); 299 if (err) 300 goto err1; 301 302 dev = &n810_snd_device->dev; 303 304 sys_clkout2_src = clk_get(dev, "sys_clkout2_src"); 305 if (IS_ERR(sys_clkout2_src)) { 306 dev_err(dev, "Could not get sys_clkout2_src clock\n"); 307 err = PTR_ERR(sys_clkout2_src); 308 goto err2; 309 } 310 sys_clkout2 = clk_get(dev, "sys_clkout2"); 311 if (IS_ERR(sys_clkout2)) { 312 dev_err(dev, "Could not get sys_clkout2\n"); 313 err = PTR_ERR(sys_clkout2); 314 goto err3; 315 } 316 /* 317 * Configure 12 MHz output on SYS_CLKOUT2. Therefore we must use 318 * 96 MHz as its parent in order to get 12 MHz 319 */ 320 func96m_clk = clk_get(dev, "func_96m_ck"); 321 if (IS_ERR(func96m_clk)) { 322 dev_err(dev, "Could not get func 96M clock\n"); 323 err = PTR_ERR(func96m_clk); 324 goto err4; 325 } 326 clk_set_parent(sys_clkout2_src, func96m_clk); 327 clk_set_rate(sys_clkout2, 12000000); 328 329 if (WARN_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) || 330 (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0))) { 331 err = -EINVAL; 332 goto err4; 333 } 334 335 gpio_direction_output(N810_HEADSET_AMP_GPIO, 0); 336 gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0); 337 338 return 0; 339 err4: 340 clk_put(sys_clkout2); 341 err3: 342 clk_put(sys_clkout2_src); 343 err2: 344 platform_device_del(n810_snd_device); 345 err1: 346 platform_device_put(n810_snd_device); 347 348 return err; 349 } 350 351 static void __exit n810_soc_exit(void) 352 { 353 gpio_free(N810_SPEAKER_AMP_GPIO); 354 gpio_free(N810_HEADSET_AMP_GPIO); 355 clk_put(sys_clkout2_src); 356 clk_put(sys_clkout2); 357 clk_put(func96m_clk); 358 359 platform_device_unregister(n810_snd_device); 360 } 361 362 module_init(n810_soc_init); 363 module_exit(n810_soc_exit); 364 365 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>"); 366 MODULE_DESCRIPTION("ALSA SoC Nokia N810"); 367 MODULE_LICENSE("GPL"); 368