1/* 2 * neo1973_gta02_wm8753.c -- SoC audio for Openmoko Freerunner(GTA02) 3 * 4 * Copyright 2007 Openmoko Inc 5 * Author: Graeme Gregory <graeme@openmoko.org> 6 * Copyright 2007 Wolfson Microelectronics PLC. 7 * Author: Graeme Gregory <linux@wolfsonmicro.com> 8 * Copyright 2009 Wolfson Microelectronics 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the 12 * Free Software Foundation; either version 2 of the License, or (at your 13 * option) any later version. 14 */ 15 16#include <linux/module.h> 17#include <linux/moduleparam.h> 18#include <linux/timer.h> 19#include <linux/interrupt.h> 20#include <linux/platform_device.h> 21#include <linux/gpio.h> 22#include <sound/core.h> 23#include <sound/pcm.h> 24#include <sound/soc.h> 25#include <sound/soc-dapm.h> 26 27#include <asm/mach-types.h> 28 29#include <plat/regs-iis.h> 30 31#include <mach/regs-clock.h> 32#include <asm/io.h> 33#include <mach/gta02.h> 34#include "../codecs/wm8753.h" 35#include "s3c-dma.h" 36#include "s3c24xx-i2s.h" 37 38static struct snd_soc_card neo1973_gta02; 39 40static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, 41 struct snd_pcm_hw_params *params) 42{ 43 struct snd_soc_pcm_runtime *rtd = substream->private_data; 44 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 45 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 46 unsigned int pll_out = 0, bclk = 0; 47 int ret = 0; 48 unsigned long iis_clkrate; 49 50 iis_clkrate = s3c24xx_i2s_get_clockrate(); 51 52 switch (params_rate(params)) { 53 case 8000: 54 case 16000: 55 pll_out = 12288000; 56 break; 57 case 48000: 58 bclk = WM8753_BCLK_DIV_4; 59 pll_out = 12288000; 60 break; 61 case 96000: 62 bclk = WM8753_BCLK_DIV_2; 63 pll_out = 12288000; 64 break; 65 case 11025: 66 bclk = WM8753_BCLK_DIV_16; 67 pll_out = 11289600; 68 break; 69 case 22050: 70 bclk = WM8753_BCLK_DIV_8; 71 pll_out = 11289600; 72 break; 73 case 44100: 74 bclk = WM8753_BCLK_DIV_4; 75 pll_out = 11289600; 76 break; 77 case 88200: 78 bclk = WM8753_BCLK_DIV_2; 79 pll_out = 11289600; 80 break; 81 } 82 83 /* set codec DAI configuration */ 84 ret = snd_soc_dai_set_fmt(codec_dai, 85 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 86 SND_SOC_DAIFMT_CBM_CFM); 87 if (ret < 0) 88 return ret; 89 90 /* set cpu DAI configuration */ 91 ret = snd_soc_dai_set_fmt(cpu_dai, 92 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 93 SND_SOC_DAIFMT_CBM_CFM); 94 if (ret < 0) 95 return ret; 96 97 /* set the codec system clock for DAC and ADC */ 98 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out, 99 SND_SOC_CLOCK_IN); 100 if (ret < 0) 101 return ret; 102 103 /* set MCLK division for sample rate */ 104 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, 105 S3C2410_IISMOD_32FS); 106 if (ret < 0) 107 return ret; 108 109 /* set codec BCLK division for sample rate */ 110 ret = snd_soc_dai_set_clkdiv(codec_dai, 111 WM8753_BCLKDIV, bclk); 112 if (ret < 0) 113 return ret; 114 115 /* set prescaler division for sample rate */ 116 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, 117 S3C24XX_PRESCALE(4, 4)); 118 if (ret < 0) 119 return ret; 120 121 /* codec PLL input is PCLK/4 */ 122 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 123 iis_clkrate / 4, pll_out); 124 if (ret < 0) 125 return ret; 126 127 return 0; 128} 129 130static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) 131{ 132 struct snd_soc_pcm_runtime *rtd = substream->private_data; 133 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 134 135 /* disable the PLL */ 136 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); 137} 138 139/* 140 * Neo1973 WM8753 HiFi DAI opserations. 141 */ 142static struct snd_soc_ops neo1973_gta02_hifi_ops = { 143 .hw_params = neo1973_gta02_hifi_hw_params, 144 .hw_free = neo1973_gta02_hifi_hw_free, 145}; 146 147static int neo1973_gta02_voice_hw_params( 148 struct snd_pcm_substream *substream, 149 struct snd_pcm_hw_params *params) 150{ 151 struct snd_soc_pcm_runtime *rtd = substream->private_data; 152 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 153 unsigned int pcmdiv = 0; 154 int ret = 0; 155 unsigned long iis_clkrate; 156 157 iis_clkrate = s3c24xx_i2s_get_clockrate(); 158 159 if (params_rate(params) != 8000) 160 return -EINVAL; 161 if (params_channels(params) != 1) 162 return -EINVAL; 163 164 pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */ 165 166 /* todo: gg check mode (DSP_B) against CSR datasheet */ 167 /* set codec DAI configuration */ 168 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | 169 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); 170 if (ret < 0) 171 return ret; 172 173 /* set the codec system clock for DAC and ADC */ 174 ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 175 12288000, SND_SOC_CLOCK_IN); 176 if (ret < 0) 177 return ret; 178 179 /* set codec PCM division for sample rate */ 180 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, 181 pcmdiv); 182 if (ret < 0) 183 return ret; 184 185 /* configue and enable PLL for 12.288MHz output */ 186 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 187 iis_clkrate / 4, 12288000); 188 if (ret < 0) 189 return ret; 190 191 return 0; 192} 193 194static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) 195{ 196 struct snd_soc_pcm_runtime *rtd = substream->private_data; 197 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 198 199 /* disable the PLL */ 200 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); 201} 202 203static struct snd_soc_ops neo1973_gta02_voice_ops = { 204 .hw_params = neo1973_gta02_voice_hw_params, 205 .hw_free = neo1973_gta02_voice_hw_free, 206}; 207 208#define LM4853_AMP 1 209#define LM4853_SPK 2 210 211static u8 lm4853_state; 212 213/* This has no effect, it exists only to maintain compatibility with 214 * existing ALSA state files. 215 */ 216static int lm4853_set_state(struct snd_kcontrol *kcontrol, 217 struct snd_ctl_elem_value *ucontrol) 218{ 219 int val = ucontrol->value.integer.value[0]; 220 221 if (val) 222 lm4853_state |= LM4853_AMP; 223 else 224 lm4853_state &= ~LM4853_AMP; 225 226 return 0; 227} 228 229static int lm4853_get_state(struct snd_kcontrol *kcontrol, 230 struct snd_ctl_elem_value *ucontrol) 231{ 232 ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP; 233 234 return 0; 235} 236 237static int lm4853_set_spk(struct snd_kcontrol *kcontrol, 238 struct snd_ctl_elem_value *ucontrol) 239{ 240 int val = ucontrol->value.integer.value[0]; 241 242 if (val) { 243 lm4853_state |= LM4853_SPK; 244 gpio_set_value(GTA02_GPIO_HP_IN, 0); 245 } else { 246 lm4853_state &= ~LM4853_SPK; 247 gpio_set_value(GTA02_GPIO_HP_IN, 1); 248 } 249 250 return 0; 251} 252 253static int lm4853_get_spk(struct snd_kcontrol *kcontrol, 254 struct snd_ctl_elem_value *ucontrol) 255{ 256 ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1; 257 258 return 0; 259} 260 261static int lm4853_event(struct snd_soc_dapm_widget *w, 262 struct snd_kcontrol *k, 263 int event) 264{ 265 gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value)); 266 267 return 0; 268} 269 270static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { 271 SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), 272 SND_SOC_DAPM_LINE("GSM Line Out", NULL), 273 SND_SOC_DAPM_LINE("GSM Line In", NULL), 274 SND_SOC_DAPM_MIC("Headset Mic", NULL), 275 SND_SOC_DAPM_MIC("Handset Mic", NULL), 276 SND_SOC_DAPM_SPK("Handset Spk", NULL), 277}; 278 279 280/* example machine audio_mapnections */ 281static const struct snd_soc_dapm_route audio_map[] = { 282 283 /* Connections to the lm4853 amp */ 284 {"Stereo Out", NULL, "LOUT1"}, 285 {"Stereo Out", NULL, "ROUT1"}, 286 287 /* Connections to the GSM Module */ 288 {"GSM Line Out", NULL, "MONO1"}, 289 {"GSM Line Out", NULL, "MONO2"}, 290 {"RXP", NULL, "GSM Line In"}, 291 {"RXN", NULL, "GSM Line In"}, 292 293 /* Connections to Headset */ 294 {"MIC1", NULL, "Mic Bias"}, 295 {"Mic Bias", NULL, "Headset Mic"}, 296 297 /* Call Mic */ 298 {"MIC2", NULL, "Mic Bias"}, 299 {"MIC2N", NULL, "Mic Bias"}, 300 {"Mic Bias", NULL, "Handset Mic"}, 301 302 /* Call Speaker */ 303 {"Handset Spk", NULL, "LOUT2"}, 304 {"Handset Spk", NULL, "ROUT2"}, 305 306 /* Connect the ALC pins */ 307 {"ACIN", NULL, "ACOP"}, 308}; 309 310static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = { 311 SOC_DAPM_PIN_SWITCH("Stereo Out"), 312 SOC_DAPM_PIN_SWITCH("GSM Line Out"), 313 SOC_DAPM_PIN_SWITCH("GSM Line In"), 314 SOC_DAPM_PIN_SWITCH("Headset Mic"), 315 SOC_DAPM_PIN_SWITCH("Handset Mic"), 316 SOC_DAPM_PIN_SWITCH("Handset Spk"), 317 318 /* This has no effect, it exists only to maintain compatibility with 319 * existing ALSA state files. 320 */ 321 SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0, 322 lm4853_get_state, 323 lm4853_set_state), 324 SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0, 325 lm4853_get_spk, 326 lm4853_set_spk), 327}; 328 329/* 330 * This is an example machine initialisation for a wm8753 connected to a 331 * neo1973 GTA02. 332 */ 333static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) 334{ 335 int err; 336 337 /* set up NC codec pins */ 338 snd_soc_dapm_nc_pin(codec, "OUT3"); 339 snd_soc_dapm_nc_pin(codec, "OUT4"); 340 snd_soc_dapm_nc_pin(codec, "LINE1"); 341 snd_soc_dapm_nc_pin(codec, "LINE2"); 342 343 /* Add neo1973 gta02 specific widgets */ 344 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets, 345 ARRAY_SIZE(wm8753_dapm_widgets)); 346 347 /* add neo1973 gta02 specific controls */ 348 err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls, 349 ARRAY_SIZE(wm8753_neo1973_gta02_controls)); 350 351 if (err < 0) 352 return err; 353 354 /* set up neo1973 gta02 specific audio path audio_map */ 355 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 356 357 /* set endpoints to default off mode */ 358 snd_soc_dapm_disable_pin(codec, "Stereo Out"); 359 snd_soc_dapm_disable_pin(codec, "GSM Line Out"); 360 snd_soc_dapm_disable_pin(codec, "GSM Line In"); 361 snd_soc_dapm_disable_pin(codec, "Headset Mic"); 362 snd_soc_dapm_disable_pin(codec, "Handset Mic"); 363 snd_soc_dapm_disable_pin(codec, "Handset Spk"); 364 365 /* allow audio paths from the GSM modem to run during suspend */ 366 snd_soc_dapm_ignore_suspend(codec, "Stereo Out"); 367 snd_soc_dapm_ignore_suspend(codec, "GSM Line Out"); 368 snd_soc_dapm_ignore_suspend(codec, "GSM Line In"); 369 snd_soc_dapm_ignore_suspend(codec, "Headset Mic"); 370 snd_soc_dapm_ignore_suspend(codec, "Handset Mic"); 371 snd_soc_dapm_ignore_suspend(codec, "Handset Spk"); 372 373 snd_soc_dapm_sync(codec); 374 375 return 0; 376} 377 378/* 379 * BT Codec DAI 380 */ 381static struct snd_soc_dai bt_dai = { 382 .name = "Bluetooth", 383 .id = 0, 384 .playback = { 385 .channels_min = 1, 386 .channels_max = 1, 387 .rates = SNDRV_PCM_RATE_8000, 388 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 389 .capture = { 390 .channels_min = 1, 391 .channels_max = 1, 392 .rates = SNDRV_PCM_RATE_8000, 393 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 394}; 395 396static struct snd_soc_dai_link neo1973_gta02_dai[] = { 397{ /* Hifi Playback - for similatious use with voice below */ 398 .name = "WM8753", 399 .stream_name = "WM8753 HiFi", 400 .cpu_dai = &s3c24xx_i2s_dai, 401 .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], 402 .init = neo1973_gta02_wm8753_init, 403 .ops = &neo1973_gta02_hifi_ops, 404}, 405{ /* Voice via BT */ 406 .name = "Bluetooth", 407 .stream_name = "Voice", 408 .cpu_dai = &bt_dai, 409 .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], 410 .ops = &neo1973_gta02_voice_ops, 411}, 412}; 413 414static struct snd_soc_card neo1973_gta02 = { 415 .name = "neo1973-gta02", 416 .platform = &s3c24xx_soc_platform, 417 .dai_link = neo1973_gta02_dai, 418 .num_links = ARRAY_SIZE(neo1973_gta02_dai), 419}; 420 421static struct snd_soc_device neo1973_gta02_snd_devdata = { 422 .card = &neo1973_gta02, 423 .codec_dev = &soc_codec_dev_wm8753, 424}; 425 426static struct platform_device *neo1973_gta02_snd_device; 427 428static int __init neo1973_gta02_init(void) 429{ 430 int ret; 431 432 if (!machine_is_neo1973_gta02()) { 433 printk(KERN_INFO 434 "Only GTA02 is supported by this ASoC driver\n"); 435 return -ENODEV; 436 } 437 438 /* register bluetooth DAI here */ 439 ret = snd_soc_register_dai(&bt_dai); 440 if (ret) 441 return ret; 442 443 neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); 444 if (!neo1973_gta02_snd_device) 445 return -ENOMEM; 446 447 platform_set_drvdata(neo1973_gta02_snd_device, 448 &neo1973_gta02_snd_devdata); 449 neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev; 450 ret = platform_device_add(neo1973_gta02_snd_device); 451 452 if (ret) { 453 platform_device_put(neo1973_gta02_snd_device); 454 return ret; 455 } 456 457 /* Initialise GPIOs used by amp */ 458 ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN"); 459 if (ret) { 460 pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN); 461 goto err_unregister_device; 462 } 463 464 ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1); 465 if (ret) { 466 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); 467 goto err_free_gpio_hp_in; 468 } 469 470 ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT"); 471 if (ret) { 472 pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT); 473 goto err_free_gpio_hp_in; 474 } 475 476 ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1); 477 if (ret) { 478 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT); 479 goto err_free_gpio_amp_shut; 480 } 481 482 return 0; 483 484err_free_gpio_amp_shut: 485 gpio_free(GTA02_GPIO_AMP_SHUT); 486err_free_gpio_hp_in: 487 gpio_free(GTA02_GPIO_HP_IN); 488err_unregister_device: 489 platform_device_unregister(neo1973_gta02_snd_device); 490 return ret; 491} 492module_init(neo1973_gta02_init); 493 494static void __exit neo1973_gta02_exit(void) 495{ 496 snd_soc_unregister_dai(&bt_dai); 497 platform_device_unregister(neo1973_gta02_snd_device); 498 gpio_free(GTA02_GPIO_HP_IN); 499 gpio_free(GTA02_GPIO_AMP_SHUT); 500} 501module_exit(neo1973_gta02_exit); 502 503/* Module information */ 504MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org"); 505MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02"); 506MODULE_LICENSE("GPL"); 507