0001
0002
0003
0004
0005
0006 #include <linux/module.h>
0007 #include <sound/soc.h>
0008 #include <sound/pcm_params.h>
0009
0010 #include "../codecs/wm8580.h"
0011 #include "i2s.h"
0012
0013
0014
0015
0016
0017
0018
0019
0020 #define SMDK_WM8580_FREQ 12000000
0021
0022 static int smdk_hw_params(struct snd_pcm_substream *substream,
0023 struct snd_pcm_hw_params *params)
0024 {
0025 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0026 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0027 unsigned int pll_out;
0028 int rfs, ret;
0029
0030 switch (params_width(params)) {
0031 case 8:
0032 case 16:
0033 break;
0034 default:
0035 return -EINVAL;
0036 }
0037
0038
0039
0040
0041
0042
0043
0044
0045 switch (params_rate(params)) {
0046 case 16000:
0047 case 22050:
0048 case 32000:
0049 case 44100:
0050 case 48000:
0051 case 88200:
0052 case 96000:
0053 rfs = 256;
0054 break;
0055 case 64000:
0056 rfs = 384;
0057 break;
0058 case 8000:
0059 case 11025:
0060 rfs = 512;
0061 break;
0062 default:
0063 return -EINVAL;
0064 }
0065 pll_out = params_rate(params) * rfs;
0066
0067
0068 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK,
0069 WM8580_CLKSRC_PLLA);
0070 if (ret < 0)
0071 return ret;
0072
0073 ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0,
0074 SMDK_WM8580_FREQ, pll_out);
0075 if (ret < 0)
0076 return ret;
0077
0078 ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA,
0079 pll_out, SND_SOC_CLOCK_IN);
0080 if (ret < 0)
0081 return ret;
0082
0083 return 0;
0084 }
0085
0086
0087
0088
0089 static const struct snd_soc_ops smdk_ops = {
0090 .hw_params = smdk_hw_params,
0091 };
0092
0093
0094 static const struct snd_soc_dapm_widget smdk_wm8580_dapm_widgets[] = {
0095 SND_SOC_DAPM_HP("Front", NULL),
0096 SND_SOC_DAPM_HP("Center+Sub", NULL),
0097 SND_SOC_DAPM_HP("Rear", NULL),
0098
0099 SND_SOC_DAPM_MIC("MicIn", NULL),
0100 SND_SOC_DAPM_LINE("LineIn", NULL),
0101 };
0102
0103
0104 static const struct snd_soc_dapm_route smdk_wm8580_audio_map[] = {
0105
0106 {"AINL", NULL, "MicIn"},
0107
0108
0109 {"AINL", NULL, "LineIn"},
0110 {"AINR", NULL, "LineIn"},
0111
0112
0113 {"Front", NULL, "VOUT1L"},
0114 {"Front", NULL, "VOUT1R"},
0115
0116
0117 {"Center+Sub", NULL, "VOUT2L"},
0118 {"Center+Sub", NULL, "VOUT2R"},
0119
0120
0121 {"Rear", NULL, "VOUT3L"},
0122 {"Rear", NULL, "VOUT3R"},
0123 };
0124
0125 static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)
0126 {
0127
0128
0129
0130 snd_soc_dapm_disable_pin(&rtd->card->dapm, "MicIn");
0131
0132 return 0;
0133 }
0134
0135 enum {
0136 PRI_PLAYBACK = 0,
0137 PRI_CAPTURE,
0138 };
0139
0140 #define SMDK_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \
0141 SND_SOC_DAIFMT_CBM_CFM)
0142
0143 SND_SOC_DAILINK_DEFS(paif_rx,
0144 DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.2")),
0145 DAILINK_COMP_ARRAY(COMP_CODEC("wm8580.0-001b", "wm8580-hifi-playback")),
0146 DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
0147
0148 SND_SOC_DAILINK_DEFS(paif_tx,
0149 DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.2")),
0150 DAILINK_COMP_ARRAY(COMP_CODEC("wm8580.0-001b", "wm8580-hifi-capture")),
0151 DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
0152
0153 static struct snd_soc_dai_link smdk_dai[] = {
0154 [PRI_PLAYBACK] = {
0155 .name = "WM8580 PAIF RX",
0156 .stream_name = "Playback",
0157 .dai_fmt = SMDK_DAI_FMT,
0158 .ops = &smdk_ops,
0159 SND_SOC_DAILINK_REG(paif_rx),
0160 },
0161 [PRI_CAPTURE] = {
0162 .name = "WM8580 PAIF TX",
0163 .stream_name = "Capture",
0164 .dai_fmt = SMDK_DAI_FMT,
0165 .init = smdk_wm8580_init_paiftx,
0166 .ops = &smdk_ops,
0167 SND_SOC_DAILINK_REG(paif_tx),
0168 },
0169 };
0170
0171 static struct snd_soc_card smdk = {
0172 .name = "SMDK-I2S",
0173 .owner = THIS_MODULE,
0174 .dai_link = smdk_dai,
0175 .num_links = ARRAY_SIZE(smdk_dai),
0176
0177 .dapm_widgets = smdk_wm8580_dapm_widgets,
0178 .num_dapm_widgets = ARRAY_SIZE(smdk_wm8580_dapm_widgets),
0179 .dapm_routes = smdk_wm8580_audio_map,
0180 .num_dapm_routes = ARRAY_SIZE(smdk_wm8580_audio_map),
0181 };
0182
0183 static struct platform_device *smdk_snd_device;
0184
0185 static int __init smdk_audio_init(void)
0186 {
0187 int ret;
0188
0189 smdk_snd_device = platform_device_alloc("soc-audio", -1);
0190 if (!smdk_snd_device)
0191 return -ENOMEM;
0192
0193 platform_set_drvdata(smdk_snd_device, &smdk);
0194 ret = platform_device_add(smdk_snd_device);
0195
0196 if (ret)
0197 platform_device_put(smdk_snd_device);
0198
0199 return ret;
0200 }
0201 module_init(smdk_audio_init);
0202
0203 static void __exit smdk_audio_exit(void)
0204 {
0205 platform_device_unregister(smdk_snd_device);
0206 }
0207 module_exit(smdk_audio_exit);
0208
0209 MODULE_AUTHOR("Jaswinder Singh, jassisinghbrar@gmail.com");
0210 MODULE_DESCRIPTION("ALSA SoC SMDK WM8580");
0211 MODULE_LICENSE("GPL");