0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/moduleparam.h>
0013 #include <linux/timer.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/gpio/consumer.h>
0017
0018 #include <sound/core.h>
0019 #include <sound/pcm.h>
0020 #include <sound/soc.h>
0021 #include <sound/jack.h>
0022
0023 #include <asm/mach-types.h>
0024 #include <linux/platform_data/asoc-pxa.h>
0025
0026 #include "../codecs/wm8750.h"
0027 #include "pxa2xx-i2s.h"
0028
0029 static struct snd_soc_card snd_soc_z2;
0030
0031 static int z2_hw_params(struct snd_pcm_substream *substream,
0032 struct snd_pcm_hw_params *params)
0033 {
0034 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0035 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0036 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0037 unsigned int clk = 0;
0038 int ret = 0;
0039
0040 switch (params_rate(params)) {
0041 case 8000:
0042 case 16000:
0043 case 48000:
0044 case 96000:
0045 clk = 12288000;
0046 break;
0047 case 11025:
0048 case 22050:
0049 case 44100:
0050 clk = 11289600;
0051 break;
0052 }
0053
0054
0055 ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
0056 SND_SOC_CLOCK_IN);
0057 if (ret < 0)
0058 return ret;
0059
0060
0061 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
0062 SND_SOC_CLOCK_IN);
0063 if (ret < 0)
0064 return ret;
0065
0066 return 0;
0067 }
0068
0069 static struct snd_soc_jack hs_jack;
0070
0071
0072 static struct snd_soc_jack_pin hs_jack_pins[] = {
0073 {
0074 .pin = "Mic Jack",
0075 .mask = SND_JACK_MICROPHONE,
0076 },
0077 {
0078 .pin = "Headphone Jack",
0079 .mask = SND_JACK_HEADPHONE,
0080 },
0081 {
0082 .pin = "Ext Spk",
0083 .mask = SND_JACK_HEADPHONE,
0084 .invert = 1
0085 },
0086 };
0087
0088
0089 static struct snd_soc_jack_gpio hs_jack_gpios[] = {
0090 {
0091 .name = "hsdet-gpio",
0092 .report = SND_JACK_HEADSET,
0093 .debounce_time = 200,
0094 .invert = 1,
0095 },
0096 };
0097
0098
0099 static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
0100 SND_SOC_DAPM_HP("Headphone Jack", NULL),
0101 SND_SOC_DAPM_MIC("Mic Jack", NULL),
0102 SND_SOC_DAPM_SPK("Ext Spk", NULL),
0103
0104
0105 SND_SOC_DAPM_HP("Headset Jack", NULL),
0106 };
0107
0108
0109 static const struct snd_soc_dapm_route z2_audio_map[] = {
0110
0111
0112 {"Headphone Jack", NULL, "LOUT1"},
0113 {"Headphone Jack", NULL, "ROUT1"},
0114
0115
0116 {"Ext Spk", NULL, "ROUT2"},
0117 {"Ext Spk", NULL, "LOUT2"},
0118
0119
0120 {"RINPUT2", NULL, "Mic Bias"},
0121 {"Mic Bias", NULL, "Mic Jack"},
0122 };
0123
0124
0125
0126
0127 static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
0128 {
0129 int ret;
0130
0131
0132 ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
0133 SND_JACK_HEADSET, &hs_jack,
0134 hs_jack_pins,
0135 ARRAY_SIZE(hs_jack_pins));
0136 if (ret)
0137 goto err;
0138
0139 ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios),
0140 hs_jack_gpios);
0141 if (ret)
0142 goto err;
0143
0144 return 0;
0145
0146 err:
0147 return ret;
0148 }
0149
0150 static const struct snd_soc_ops z2_ops = {
0151 .hw_params = z2_hw_params,
0152 };
0153
0154
0155 SND_SOC_DAILINK_DEFS(wm8750,
0156 DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-i2s")),
0157 DAILINK_COMP_ARRAY(COMP_CODEC("wm8750.0-001b", "wm8750-hifi")),
0158 DAILINK_COMP_ARRAY(COMP_PLATFORM("pxa-pcm-audio")));
0159
0160 static struct snd_soc_dai_link z2_dai = {
0161 .name = "wm8750",
0162 .stream_name = "WM8750",
0163 .init = z2_wm8750_init,
0164 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0165 SND_SOC_DAIFMT_CBS_CFS,
0166 .ops = &z2_ops,
0167 SND_SOC_DAILINK_REG(wm8750),
0168 };
0169
0170
0171 static struct snd_soc_card snd_soc_z2 = {
0172 .name = "Z2",
0173 .owner = THIS_MODULE,
0174 .dai_link = &z2_dai,
0175 .num_links = 1,
0176
0177 .dapm_widgets = wm8750_dapm_widgets,
0178 .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
0179 .dapm_routes = z2_audio_map,
0180 .num_dapm_routes = ARRAY_SIZE(z2_audio_map),
0181 .fully_routed = true,
0182 };
0183
0184 static struct platform_device *z2_snd_device;
0185
0186 static int __init z2_init(void)
0187 {
0188 int ret;
0189
0190 if (!machine_is_zipit2())
0191 return -ENODEV;
0192
0193 z2_snd_device = platform_device_alloc("soc-audio", -1);
0194 if (!z2_snd_device)
0195 return -ENOMEM;
0196
0197 hs_jack_gpios[0].gpiod_dev = &z2_snd_device->dev;
0198 platform_set_drvdata(z2_snd_device, &snd_soc_z2);
0199 ret = platform_device_add(z2_snd_device);
0200
0201 if (ret)
0202 platform_device_put(z2_snd_device);
0203
0204 return ret;
0205 }
0206
0207 static void __exit z2_exit(void)
0208 {
0209 platform_device_unregister(z2_snd_device);
0210 }
0211
0212 module_init(z2_init);
0213 module_exit(z2_exit);
0214
0215 MODULE_AUTHOR("Ken McGuire <kenm@desertweyr.com>, "
0216 "Marek Vasut <marek.vasut@gmail.com>");
0217 MODULE_DESCRIPTION("ALSA SoC ZipitZ2");
0218 MODULE_LICENSE("GPL");