This source file includes following definitions.
- corgi_ext_control
- corgi_startup
- corgi_shutdown
- corgi_hw_params
- corgi_get_jack
- corgi_set_jack
- corgi_get_spk
- corgi_set_spk
- corgi_amp_event
- corgi_mic_event
- corgi_probe
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 #include <linux/module.h>
  13 #include <linux/moduleparam.h>
  14 #include <linux/timer.h>
  15 #include <linux/i2c.h>
  16 #include <linux/interrupt.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/gpio.h>
  19 #include <sound/core.h>
  20 #include <sound/pcm.h>
  21 #include <sound/soc.h>
  22 
  23 #include <asm/mach-types.h>
  24 #include <mach/corgi.h>
  25 #include <mach/audio.h>
  26 
  27 #include "../codecs/wm8731.h"
  28 #include "pxa2xx-i2s.h"
  29 
  30 #define CORGI_HP        0
  31 #define CORGI_MIC       1
  32 #define CORGI_LINE      2
  33 #define CORGI_HEADSET   3
  34 #define CORGI_HP_OFF    4
  35 #define CORGI_SPK_ON    0
  36 #define CORGI_SPK_OFF   1
  37 
  38  
  39 #define CORGI_AUDIO_CLOCK 12288000
  40 
  41 static int corgi_jack_func;
  42 static int corgi_spk_func;
  43 
  44 static void corgi_ext_control(struct snd_soc_dapm_context *dapm)
  45 {
  46         snd_soc_dapm_mutex_lock(dapm);
  47 
  48         
  49         switch (corgi_jack_func) {
  50         case CORGI_HP:
  51                 
  52                 gpio_set_value(CORGI_GPIO_MUTE_L, 1);
  53                 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
  54                 snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack");
  55                 snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack");
  56                 snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack");
  57                 snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
  58                 break;
  59         case CORGI_MIC:
  60                 
  61                 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
  62                 gpio_set_value(CORGI_GPIO_MUTE_R, 0);
  63                 snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack");
  64                 snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack");
  65                 snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
  66                 snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
  67                 break;
  68         case CORGI_LINE:
  69                 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
  70                 gpio_set_value(CORGI_GPIO_MUTE_R, 0);
  71                 snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack");
  72                 snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack");
  73                 snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
  74                 snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack");
  75                 break;
  76         case CORGI_HEADSET:
  77                 gpio_set_value(CORGI_GPIO_MUTE_L, 0);
  78                 gpio_set_value(CORGI_GPIO_MUTE_R, 1);
  79                 snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack");
  80                 snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack");
  81                 snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack");
  82                 snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack");
  83                 break;
  84         }
  85 
  86         if (corgi_spk_func == CORGI_SPK_ON)
  87                 snd_soc_dapm_enable_pin_unlocked(dapm, "Ext Spk");
  88         else
  89                 snd_soc_dapm_disable_pin_unlocked(dapm, "Ext Spk");
  90 
  91         
  92         snd_soc_dapm_sync_unlocked(dapm);
  93 
  94         snd_soc_dapm_mutex_unlock(dapm);
  95 }
  96 
  97 static int corgi_startup(struct snd_pcm_substream *substream)
  98 {
  99         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 100 
 101         
 102         corgi_ext_control(&rtd->card->dapm);
 103 
 104         return 0;
 105 }
 106 
 107 
 108 static void corgi_shutdown(struct snd_pcm_substream *substream)
 109 {
 110         
 111         gpio_set_value(CORGI_GPIO_MUTE_L, 1);
 112         gpio_set_value(CORGI_GPIO_MUTE_R, 1);
 113 }
 114 
 115 static int corgi_hw_params(struct snd_pcm_substream *substream,
 116         struct snd_pcm_hw_params *params)
 117 {
 118         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 119         struct snd_soc_dai *codec_dai = rtd->codec_dai;
 120         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 121         unsigned int clk = 0;
 122         int ret = 0;
 123 
 124         switch (params_rate(params)) {
 125         case 8000:
 126         case 16000:
 127         case 48000:
 128         case 96000:
 129                 clk = 12288000;
 130                 break;
 131         case 11025:
 132         case 22050:
 133         case 44100:
 134                 clk = 11289600;
 135                 break;
 136         }
 137 
 138         
 139         ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk,
 140                 SND_SOC_CLOCK_IN);
 141         if (ret < 0)
 142                 return ret;
 143 
 144         
 145         ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
 146                 SND_SOC_CLOCK_IN);
 147         if (ret < 0)
 148                 return ret;
 149 
 150         return 0;
 151 }
 152 
 153 static const struct snd_soc_ops corgi_ops = {
 154         .startup = corgi_startup,
 155         .hw_params = corgi_hw_params,
 156         .shutdown = corgi_shutdown,
 157 };
 158 
 159 static int corgi_get_jack(struct snd_kcontrol *kcontrol,
 160         struct snd_ctl_elem_value *ucontrol)
 161 {
 162         ucontrol->value.enumerated.item[0] = corgi_jack_func;
 163         return 0;
 164 }
 165 
 166 static int corgi_set_jack(struct snd_kcontrol *kcontrol,
 167         struct snd_ctl_elem_value *ucontrol)
 168 {
 169         struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 170 
 171         if (corgi_jack_func == ucontrol->value.enumerated.item[0])
 172                 return 0;
 173 
 174         corgi_jack_func = ucontrol->value.enumerated.item[0];
 175         corgi_ext_control(&card->dapm);
 176         return 1;
 177 }
 178 
 179 static int corgi_get_spk(struct snd_kcontrol *kcontrol,
 180         struct snd_ctl_elem_value *ucontrol)
 181 {
 182         ucontrol->value.enumerated.item[0] = corgi_spk_func;
 183         return 0;
 184 }
 185 
 186 static int corgi_set_spk(struct snd_kcontrol *kcontrol,
 187         struct snd_ctl_elem_value *ucontrol)
 188 {
 189         struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 190 
 191         if (corgi_spk_func == ucontrol->value.enumerated.item[0])
 192                 return 0;
 193 
 194         corgi_spk_func = ucontrol->value.enumerated.item[0];
 195         corgi_ext_control(&card->dapm);
 196         return 1;
 197 }
 198 
 199 static int corgi_amp_event(struct snd_soc_dapm_widget *w,
 200         struct snd_kcontrol *k, int event)
 201 {
 202         gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
 203         return 0;
 204 }
 205 
 206 static int corgi_mic_event(struct snd_soc_dapm_widget *w,
 207         struct snd_kcontrol *k, int event)
 208 {
 209         gpio_set_value(CORGI_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
 210         return 0;
 211 }
 212 
 213 
 214 static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
 215 SND_SOC_DAPM_HP("Headphone Jack", NULL),
 216 SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event),
 217 SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event),
 218 SND_SOC_DAPM_LINE("Line Jack", NULL),
 219 SND_SOC_DAPM_HP("Headset Jack", NULL),
 220 };
 221 
 222 
 223 static const struct snd_soc_dapm_route corgi_audio_map[] = {
 224 
 225         
 226         {"Headset Jack", NULL, "LHPOUT"},
 227 
 228         
 229         {"Headphone Jack", NULL, "LHPOUT"},
 230         {"Headphone Jack", NULL, "RHPOUT"},
 231 
 232         
 233         {"Ext Spk", NULL, "ROUT"},
 234         {"Ext Spk", NULL, "LOUT"},
 235 
 236         
 237         {"MICIN", NULL, "Mic Jack"},
 238 
 239         
 240         {"MICIN", NULL, "Line Jack"},
 241 };
 242 
 243 static const char * const jack_function[] = {"Headphone", "Mic", "Line",
 244         "Headset", "Off"};
 245 static const char * const spk_function[] = {"On", "Off"};
 246 static const struct soc_enum corgi_enum[] = {
 247         SOC_ENUM_SINGLE_EXT(5, jack_function),
 248         SOC_ENUM_SINGLE_EXT(2, spk_function),
 249 };
 250 
 251 static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
 252         SOC_ENUM_EXT("Jack Function", corgi_enum[0], corgi_get_jack,
 253                 corgi_set_jack),
 254         SOC_ENUM_EXT("Speaker Function", corgi_enum[1], corgi_get_spk,
 255                 corgi_set_spk),
 256 };
 257 
 258 
 259 SND_SOC_DAILINK_DEFS(wm8731,
 260         DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-i2s")),
 261         DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")),
 262         DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio")));
 263 
 264 static struct snd_soc_dai_link corgi_dai = {
 265         .name = "WM8731",
 266         .stream_name = "WM8731",
 267         .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 268                    SND_SOC_DAIFMT_CBS_CFS,
 269         .ops = &corgi_ops,
 270         SND_SOC_DAILINK_REG(wm8731),
 271 };
 272 
 273 
 274 static struct snd_soc_card corgi = {
 275         .name = "Corgi",
 276         .owner = THIS_MODULE,
 277         .dai_link = &corgi_dai,
 278         .num_links = 1,
 279 
 280         .controls = wm8731_corgi_controls,
 281         .num_controls = ARRAY_SIZE(wm8731_corgi_controls),
 282         .dapm_widgets = wm8731_dapm_widgets,
 283         .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
 284         .dapm_routes = corgi_audio_map,
 285         .num_dapm_routes = ARRAY_SIZE(corgi_audio_map),
 286         .fully_routed = true,
 287 };
 288 
 289 static int corgi_probe(struct platform_device *pdev)
 290 {
 291         struct snd_soc_card *card = &corgi;
 292         int ret;
 293 
 294         card->dev = &pdev->dev;
 295 
 296         ret = devm_snd_soc_register_card(&pdev->dev, card);
 297         if (ret)
 298                 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
 299                         ret);
 300         return ret;
 301 }
 302 
 303 static struct platform_driver corgi_driver = {
 304         .driver         = {
 305                 .name   = "corgi-audio",
 306                 .pm     = &snd_soc_pm_ops,
 307         },
 308         .probe          = corgi_probe,
 309 };
 310 
 311 module_platform_driver(corgi_driver);
 312 
 313 
 314 MODULE_AUTHOR("Richard Purdie");
 315 MODULE_DESCRIPTION("ALSA SoC Corgi");
 316 MODULE_LICENSE("GPL");
 317 MODULE_ALIAS("platform:corgi-audio");