root/sound/soc/samsung/neo1973_wm8753.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. neo1973_hifi_hw_params
  2. neo1973_hifi_hw_free
  3. neo1973_voice_hw_params
  4. neo1973_voice_hw_free
  5. lm4853_set_spk
  6. lm4853_get_spk
  7. lm4853_event
  8. neo1973_wm8753_init
  9. neo1973_init
  10. neo1973_exit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 //
   3 // neo1973_wm8753.c - SoC audio for Openmoko Neo1973 and Freerunner devices
   4 //
   5 // Copyright 2007 Openmoko Inc
   6 // Author: Graeme Gregory <graeme@openmoko.org>
   7 // Copyright 2007 Wolfson Microelectronics PLC.
   8 // Author: Graeme Gregory
   9 //         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
  10 // Copyright 2009 Wolfson Microelectronics
  11 
  12 #include <linux/module.h>
  13 #include <linux/platform_device.h>
  14 #include <linux/gpio.h>
  15 
  16 #include <sound/soc.h>
  17 
  18 #include <mach/gpio-samsung.h>
  19 #include <asm/mach-types.h>
  20 #include "regs-iis.h"
  21 
  22 #include "../codecs/wm8753.h"
  23 #include "s3c24xx-i2s.h"
  24 
  25 static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
  26         struct snd_pcm_hw_params *params)
  27 {
  28         struct snd_soc_pcm_runtime *rtd = substream->private_data;
  29         struct snd_soc_dai *codec_dai = rtd->codec_dai;
  30         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  31         unsigned int pll_out = 0, bclk = 0;
  32         int ret = 0;
  33         unsigned long iis_clkrate;
  34 
  35         iis_clkrate = s3c24xx_i2s_get_clockrate();
  36 
  37         switch (params_rate(params)) {
  38         case 8000:
  39         case 16000:
  40                 pll_out = 12288000;
  41                 break;
  42         case 48000:
  43                 bclk = WM8753_BCLK_DIV_4;
  44                 pll_out = 12288000;
  45                 break;
  46         case 96000:
  47                 bclk = WM8753_BCLK_DIV_2;
  48                 pll_out = 12288000;
  49                 break;
  50         case 11025:
  51                 bclk = WM8753_BCLK_DIV_16;
  52                 pll_out = 11289600;
  53                 break;
  54         case 22050:
  55                 bclk = WM8753_BCLK_DIV_8;
  56                 pll_out = 11289600;
  57                 break;
  58         case 44100:
  59                 bclk = WM8753_BCLK_DIV_4;
  60                 pll_out = 11289600;
  61                 break;
  62         case 88200:
  63                 bclk = WM8753_BCLK_DIV_2;
  64                 pll_out = 11289600;
  65                 break;
  66         }
  67 
  68         /* set the codec system clock for DAC and ADC */
  69         ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
  70                 SND_SOC_CLOCK_IN);
  71         if (ret < 0)
  72                 return ret;
  73 
  74         /* set MCLK division for sample rate */
  75         ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
  76                 S3C2410_IISMOD_32FS);
  77         if (ret < 0)
  78                 return ret;
  79 
  80         /* set codec BCLK division for sample rate */
  81         ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
  82         if (ret < 0)
  83                 return ret;
  84 
  85         /* set prescaler division for sample rate */
  86         ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
  87                 S3C24XX_PRESCALE(4, 4));
  88         if (ret < 0)
  89                 return ret;
  90 
  91         /* codec PLL input is PCLK/4 */
  92         ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
  93                 iis_clkrate / 4, pll_out);
  94         if (ret < 0)
  95                 return ret;
  96 
  97         return 0;
  98 }
  99 
 100 static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
 101 {
 102         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 103         struct snd_soc_dai *codec_dai = rtd->codec_dai;
 104 
 105         /* disable the PLL */
 106         return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
 107 }
 108 
 109 /*
 110  * Neo1973 WM8753 HiFi DAI opserations.
 111  */
 112 static struct snd_soc_ops neo1973_hifi_ops = {
 113         .hw_params = neo1973_hifi_hw_params,
 114         .hw_free = neo1973_hifi_hw_free,
 115 };
 116 
 117 static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
 118         struct snd_pcm_hw_params *params)
 119 {
 120         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 121         struct snd_soc_dai *codec_dai = rtd->codec_dai;
 122         unsigned int pcmdiv = 0;
 123         int ret = 0;
 124         unsigned long iis_clkrate;
 125 
 126         iis_clkrate = s3c24xx_i2s_get_clockrate();
 127 
 128         if (params_rate(params) != 8000)
 129                 return -EINVAL;
 130         if (params_channels(params) != 1)
 131                 return -EINVAL;
 132 
 133         pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
 134 
 135         /* set the codec system clock for DAC and ADC */
 136         ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,
 137                 SND_SOC_CLOCK_IN);
 138         if (ret < 0)
 139                 return ret;
 140 
 141         /* set codec PCM division for sample rate */
 142         ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
 143         if (ret < 0)
 144                 return ret;
 145 
 146         /* configure and enable PLL for 12.288MHz output */
 147         ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
 148                 iis_clkrate / 4, 12288000);
 149         if (ret < 0)
 150                 return ret;
 151 
 152         return 0;
 153 }
 154 
 155 static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
 156 {
 157         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 158         struct snd_soc_dai *codec_dai = rtd->codec_dai;
 159 
 160         /* disable the PLL */
 161         return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
 162 }
 163 
 164 static struct snd_soc_ops neo1973_voice_ops = {
 165         .hw_params = neo1973_voice_hw_params,
 166         .hw_free = neo1973_voice_hw_free,
 167 };
 168 
 169 static int gta02_speaker_enabled;
 170 
 171 static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
 172         struct snd_ctl_elem_value *ucontrol)
 173 {
 174         gta02_speaker_enabled = ucontrol->value.integer.value[0];
 175 
 176         gpio_set_value(S3C2410_GPJ(2), !gta02_speaker_enabled);
 177 
 178         return 0;
 179 }
 180 
 181 static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
 182         struct snd_ctl_elem_value *ucontrol)
 183 {
 184         ucontrol->value.integer.value[0] = gta02_speaker_enabled;
 185         return 0;
 186 }
 187 
 188 static int lm4853_event(struct snd_soc_dapm_widget *w,
 189                         struct snd_kcontrol *k, int event)
 190 {
 191         gpio_set_value(S3C2410_GPJ(1), SND_SOC_DAPM_EVENT_OFF(event));
 192 
 193         return 0;
 194 }
 195 
 196 static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = {
 197         SND_SOC_DAPM_LINE("GSM Line Out", NULL),
 198         SND_SOC_DAPM_LINE("GSM Line In", NULL),
 199         SND_SOC_DAPM_MIC("Headset Mic", NULL),
 200         SND_SOC_DAPM_MIC("Handset Mic", NULL),
 201         SND_SOC_DAPM_SPK("Handset Spk", NULL),
 202         SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
 203 };
 204 
 205 static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = {
 206         /* Connections to the GSM Module */
 207         {"GSM Line Out", NULL, "MONO1"},
 208         {"GSM Line Out", NULL, "MONO2"},
 209         {"RXP", NULL, "GSM Line In"},
 210         {"RXN", NULL, "GSM Line In"},
 211 
 212         /* Connections to Headset */
 213         {"MIC1", NULL, "Mic Bias"},
 214         {"Mic Bias", NULL, "Headset Mic"},
 215 
 216         /* Call Mic */
 217         {"MIC2", NULL, "Mic Bias"},
 218         {"MIC2N", NULL, "Mic Bias"},
 219         {"Mic Bias", NULL, "Handset Mic"},
 220 
 221         /* Connect the ALC pins */
 222         {"ACIN", NULL, "ACOP"},
 223 
 224         /* Connections to the amp */
 225         {"Stereo Out", NULL, "LOUT1"},
 226         {"Stereo Out", NULL, "ROUT1"},
 227 
 228         /* Call Speaker */
 229         {"Handset Spk", NULL, "LOUT2"},
 230         {"Handset Spk", NULL, "ROUT2"},
 231 };
 232 
 233 static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
 234         SOC_DAPM_PIN_SWITCH("GSM Line Out"),
 235         SOC_DAPM_PIN_SWITCH("GSM Line In"),
 236         SOC_DAPM_PIN_SWITCH("Headset Mic"),
 237         SOC_DAPM_PIN_SWITCH("Handset Mic"),
 238         SOC_DAPM_PIN_SWITCH("Handset Spk"),
 239         SOC_DAPM_PIN_SWITCH("Stereo Out"),
 240 
 241         SOC_SINGLE_BOOL_EXT("Amp Spk Switch", 0,
 242                 lm4853_get_spk,
 243                 lm4853_set_spk),
 244 };
 245 
 246 static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
 247 {
 248         struct snd_soc_card *card = rtd->card;
 249 
 250         /* set endpoints to default off mode */
 251         snd_soc_dapm_disable_pin(&card->dapm, "GSM Line Out");
 252         snd_soc_dapm_disable_pin(&card->dapm, "GSM Line In");
 253         snd_soc_dapm_disable_pin(&card->dapm, "Headset Mic");
 254         snd_soc_dapm_disable_pin(&card->dapm, "Handset Mic");
 255         snd_soc_dapm_disable_pin(&card->dapm, "Stereo Out");
 256         snd_soc_dapm_disable_pin(&card->dapm, "Handset Spk");
 257 
 258         /* allow audio paths from the GSM modem to run during suspend */
 259         snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line Out");
 260         snd_soc_dapm_ignore_suspend(&card->dapm, "GSM Line In");
 261         snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic");
 262         snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Mic");
 263         snd_soc_dapm_ignore_suspend(&card->dapm, "Stereo Out");
 264         snd_soc_dapm_ignore_suspend(&card->dapm, "Handset Spk");
 265 
 266         return 0;
 267 }
 268 
 269 SND_SOC_DAILINK_DEFS(wm8753,
 270         DAILINK_COMP_ARRAY(COMP_CPU("s3c24xx-iis")),
 271         DAILINK_COMP_ARRAY(COMP_CODEC("wm8753.0-001a", "wm8753-hifi")),
 272         DAILINK_COMP_ARRAY(COMP_PLATFORM("s3c24xx-iis")));
 273 
 274 SND_SOC_DAILINK_DEFS(bluetooth,
 275         DAILINK_COMP_ARRAY(COMP_CPU("bt-sco-pcm")),
 276         DAILINK_COMP_ARRAY(COMP_CODEC("wm8753.0-001a", "wm8753-voice")));
 277 
 278 static struct snd_soc_dai_link neo1973_dai[] = {
 279 { /* Hifi Playback - for similatious use with voice below */
 280         .name = "WM8753",
 281         .stream_name = "WM8753 HiFi",
 282         .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 283                    SND_SOC_DAIFMT_CBM_CFM,
 284         .init = neo1973_wm8753_init,
 285         .ops = &neo1973_hifi_ops,
 286         SND_SOC_DAILINK_REG(wm8753),
 287 },
 288 { /* Voice via BT */
 289         .name = "Bluetooth",
 290         .stream_name = "Voice",
 291         .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
 292                    SND_SOC_DAIFMT_CBS_CFS,
 293         .ops = &neo1973_voice_ops,
 294         SND_SOC_DAILINK_REG(bluetooth),
 295 },
 296 };
 297 
 298 static struct snd_soc_aux_dev neo1973_aux_devs[] = {
 299         {
 300                 .dlc = COMP_AUX("dfbmcs320.0"),
 301         },
 302 };
 303 
 304 static struct snd_soc_codec_conf neo1973_codec_conf[] = {
 305         {
 306                 .dev_name = "lm4857.0-007c",
 307                 .name_prefix = "Amp",
 308         },
 309 };
 310 
 311 static const struct gpio neo1973_gta02_gpios[] = {
 312         { S3C2410_GPJ(2), GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
 313         { S3C2410_GPJ(1), GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
 314 };
 315 
 316 static struct snd_soc_card neo1973 = {
 317         .name = "neo1973",
 318         .owner = THIS_MODULE,
 319         .dai_link = neo1973_dai,
 320         .num_links = ARRAY_SIZE(neo1973_dai),
 321         .aux_dev = neo1973_aux_devs,
 322         .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs),
 323         .codec_conf = neo1973_codec_conf,
 324         .num_configs = ARRAY_SIZE(neo1973_codec_conf),
 325 
 326         .controls = neo1973_wm8753_controls,
 327         .num_controls = ARRAY_SIZE(neo1973_wm8753_controls),
 328         .dapm_widgets = neo1973_wm8753_dapm_widgets,
 329         .num_dapm_widgets = ARRAY_SIZE(neo1973_wm8753_dapm_widgets),
 330         .dapm_routes = neo1973_wm8753_routes,
 331         .num_dapm_routes = ARRAY_SIZE(neo1973_wm8753_routes),
 332         .fully_routed = true,
 333 };
 334 
 335 static struct platform_device *neo1973_snd_device;
 336 
 337 static int __init neo1973_init(void)
 338 {
 339         int ret;
 340 
 341         if (!machine_is_neo1973_gta02())
 342                 return -ENODEV;
 343 
 344         if (machine_is_neo1973_gta02()) {
 345                 neo1973.name = "neo1973gta02";
 346                 neo1973.num_aux_devs = 1;
 347 
 348                 ret = gpio_request_array(neo1973_gta02_gpios,
 349                                 ARRAY_SIZE(neo1973_gta02_gpios));
 350                 if (ret)
 351                         return ret;
 352         }
 353 
 354         neo1973_snd_device = platform_device_alloc("soc-audio", -1);
 355         if (!neo1973_snd_device) {
 356                 ret = -ENOMEM;
 357                 goto err_gpio_free;
 358         }
 359 
 360         platform_set_drvdata(neo1973_snd_device, &neo1973);
 361         ret = platform_device_add(neo1973_snd_device);
 362 
 363         if (ret)
 364                 goto err_put_device;
 365 
 366         return 0;
 367 
 368 err_put_device:
 369         platform_device_put(neo1973_snd_device);
 370 err_gpio_free:
 371         if (machine_is_neo1973_gta02()) {
 372                 gpio_free_array(neo1973_gta02_gpios,
 373                                 ARRAY_SIZE(neo1973_gta02_gpios));
 374         }
 375         return ret;
 376 }
 377 module_init(neo1973_init);
 378 
 379 static void __exit neo1973_exit(void)
 380 {
 381         platform_device_unregister(neo1973_snd_device);
 382 
 383         if (machine_is_neo1973_gta02()) {
 384                 gpio_free_array(neo1973_gta02_gpios,
 385                                 ARRAY_SIZE(neo1973_gta02_gpios));
 386         }
 387 }
 388 module_exit(neo1973_exit);
 389 
 390 /* Module information */
 391 MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org");
 392 MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner");
 393 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */