2
* wm8737.c -- WM8737 ALSA SoC Audio driver
4
* Copyright 2010 Wolfson Microelectronics plc
6
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2 as
10
* published by the Free Software Foundation.
13
#include <linux/module.h>
14
#include <linux/moduleparam.h>
15
#include <linux/init.h>
16
#include <linux/delay.h>
18
#include <linux/i2c.h>
19
#include <linux/platform_device.h>
20
#include <linux/regulator/consumer.h>
21
#include <linux/spi/spi.h>
22
#include <linux/slab.h>
23
#include <sound/core.h>
24
#include <sound/pcm.h>
25
#include <sound/pcm_params.h>
26
#include <sound/soc.h>
27
#include <sound/soc-dapm.h>
28
#include <sound/initval.h>
29
#include <sound/tlv.h>
33
#define WM8737_NUM_SUPPLIES 4
34
static const char *wm8737_supply_names[WM8737_NUM_SUPPLIES] = {
41
/* codec private data */
43
enum snd_soc_control_type control_type;
44
struct regulator_bulk_data supplies[WM8737_NUM_SUPPLIES];
48
static const u16 wm8737_reg[WM8737_REGISTER_COUNT] = {
49
0x00C3, /* R0 - Left PGA volume */
50
0x00C3, /* R1 - Right PGA volume */
51
0x0007, /* R2 - AUDIO path L */
52
0x0007, /* R3 - AUDIO path R */
53
0x0000, /* R4 - 3D Enhance */
54
0x0000, /* R5 - ADC Control */
55
0x0000, /* R6 - Power Management */
56
0x000A, /* R7 - Audio Format */
57
0x0000, /* R8 - Clocking */
58
0x000F, /* R9 - MIC Preamp Control */
59
0x0003, /* R10 - Misc Bias Control */
60
0x0000, /* R11 - Noise Gate */
61
0x007C, /* R12 - ALC1 */
62
0x0000, /* R13 - ALC2 */
63
0x0032, /* R14 - ALC3 */
66
static int wm8737_reset(struct snd_soc_codec *codec)
68
return snd_soc_write(codec, WM8737_RESET, 0);
71
static const unsigned int micboost_tlv[] = {
73
0, 0, TLV_DB_SCALE_ITEM(1300, 0, 0),
74
1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0),
75
2, 2, TLV_DB_SCALE_ITEM(2800, 0, 0),
76
3, 3, TLV_DB_SCALE_ITEM(3300, 0, 0),
78
static const DECLARE_TLV_DB_SCALE(pga_tlv, -9750, 50, 1);
79
static const DECLARE_TLV_DB_SCALE(adc_tlv, -600, 600, 0);
80
static const DECLARE_TLV_DB_SCALE(ng_tlv, -7800, 600, 0);
81
static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -1200, 600, 0);
82
static const DECLARE_TLV_DB_SCALE(alc_target_tlv, -1800, 100, 0);
84
static const char *micbias_enum_text[] = {
91
static const struct soc_enum micbias_enum =
92
SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 0, 4, micbias_enum_text);
94
static const char *low_cutoff_text[] = {
98
static const struct soc_enum low_3d =
99
SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 6, 2, low_cutoff_text);
101
static const char *high_cutoff_text[] = {
105
static const struct soc_enum high_3d =
106
SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 5, 2, high_cutoff_text);
108
static const char *alc_fn_text[] = {
109
"Disabled", "Right", "Left", "Stereo"
112
static const struct soc_enum alc_fn =
113
SOC_ENUM_SINGLE(WM8737_ALC1, 7, 4, alc_fn_text);
115
static const char *alc_hold_text[] = {
116
"0", "2.67ms", "5.33ms", "10.66ms", "21.32ms", "42.64ms", "85.28ms",
117
"170.56ms", "341.12ms", "682.24ms", "1.364s", "2.728s", "5.458s",
118
"10.916s", "21.832s", "43.691s"
121
static const struct soc_enum alc_hold =
122
SOC_ENUM_SINGLE(WM8737_ALC2, 0, 16, alc_hold_text);
124
static const char *alc_atk_text[] = {
125
"8.4ms", "16.8ms", "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms",
126
"1.075s", "2.15s", "4.3s", "8.6s"
129
static const struct soc_enum alc_atk =
130
SOC_ENUM_SINGLE(WM8737_ALC3, 0, 11, alc_atk_text);
132
static const char *alc_dcy_text[] = {
133
"33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s",
134
"4.3s", "8.6s", "17.2s", "34.41s"
137
static const struct soc_enum alc_dcy =
138
SOC_ENUM_SINGLE(WM8737_ALC3, 4, 11, alc_dcy_text);
140
static const struct snd_kcontrol_new wm8737_snd_controls[] = {
141
SOC_DOUBLE_R_TLV("Mic Boost Volume", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
142
6, 3, 0, micboost_tlv),
143
SOC_DOUBLE_R("Mic Boost Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
145
SOC_DOUBLE("Mic ZC Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
148
SOC_DOUBLE_R_TLV("Capture Volume", WM8737_LEFT_PGA_VOLUME,
149
WM8737_RIGHT_PGA_VOLUME, 0, 255, 0, pga_tlv),
150
SOC_DOUBLE("Capture ZC Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R,
153
SOC_DOUBLE("INPUT1 DC Bias Switch", WM8737_MISC_BIAS_CONTROL, 0, 1, 1, 0),
155
SOC_ENUM("Mic PGA Bias", micbias_enum),
156
SOC_SINGLE("ADC Low Power Switch", WM8737_ADC_CONTROL, 2, 1, 0),
157
SOC_SINGLE("High Pass Filter Switch", WM8737_ADC_CONTROL, 0, 1, 1),
158
SOC_DOUBLE("Polarity Invert Switch", WM8737_ADC_CONTROL, 5, 6, 1, 0),
160
SOC_SINGLE("3D Switch", WM8737_3D_ENHANCE, 0, 1, 0),
161
SOC_SINGLE("3D Depth", WM8737_3D_ENHANCE, 1, 15, 0),
162
SOC_ENUM("3D Low Cut-off", low_3d),
163
SOC_ENUM("3D High Cut-off", low_3d),
164
SOC_SINGLE_TLV("3D ADC Volume", WM8737_3D_ENHANCE, 7, 1, 1, adc_tlv),
166
SOC_SINGLE("Noise Gate Switch", WM8737_NOISE_GATE, 0, 1, 0),
167
SOC_SINGLE_TLV("Noise Gate Threshold Volume", WM8737_NOISE_GATE, 2, 7, 0,
170
SOC_ENUM("ALC", alc_fn),
171
SOC_SINGLE_TLV("ALC Max Gain Volume", WM8737_ALC1, 4, 7, 0, alc_max_tlv),
172
SOC_SINGLE_TLV("ALC Target Volume", WM8737_ALC1, 0, 15, 0, alc_target_tlv),
173
SOC_ENUM("ALC Hold Time", alc_hold),
174
SOC_SINGLE("ALC ZC Switch", WM8737_ALC2, 4, 1, 0),
175
SOC_ENUM("ALC Attack Time", alc_atk),
176
SOC_ENUM("ALC Decay Time", alc_dcy),
179
static const char *linsel_text[] = {
180
"LINPUT1", "LINPUT2", "LINPUT3", "LINPUT1 DC",
183
static const struct soc_enum linsel_enum =
184
SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_L, 7, 4, linsel_text);
186
static const struct snd_kcontrol_new linsel_mux =
187
SOC_DAPM_ENUM("LINSEL", linsel_enum);
190
static const char *rinsel_text[] = {
191
"RINPUT1", "RINPUT2", "RINPUT3", "RINPUT1 DC",
194
static const struct soc_enum rinsel_enum =
195
SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_R, 7, 4, rinsel_text);
197
static const struct snd_kcontrol_new rinsel_mux =
198
SOC_DAPM_ENUM("RINSEL", rinsel_enum);
200
static const char *bypass_text[] = {
204
static const struct soc_enum lbypass_enum =
205
SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 2, 2, bypass_text);
207
static const struct snd_kcontrol_new lbypass_mux =
208
SOC_DAPM_ENUM("Left Bypass", lbypass_enum);
211
static const struct soc_enum rbypass_enum =
212
SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 3, 2, bypass_text);
214
static const struct snd_kcontrol_new rbypass_mux =
215
SOC_DAPM_ENUM("Left Bypass", rbypass_enum);
217
static const struct snd_soc_dapm_widget wm8737_dapm_widgets[] = {
218
SND_SOC_DAPM_INPUT("LINPUT1"),
219
SND_SOC_DAPM_INPUT("LINPUT2"),
220
SND_SOC_DAPM_INPUT("LINPUT3"),
221
SND_SOC_DAPM_INPUT("RINPUT1"),
222
SND_SOC_DAPM_INPUT("RINPUT2"),
223
SND_SOC_DAPM_INPUT("RINPUT3"),
224
SND_SOC_DAPM_INPUT("LACIN"),
225
SND_SOC_DAPM_INPUT("RACIN"),
227
SND_SOC_DAPM_MUX("LINSEL", SND_SOC_NOPM, 0, 0, &linsel_mux),
228
SND_SOC_DAPM_MUX("RINSEL", SND_SOC_NOPM, 0, 0, &rinsel_mux),
230
SND_SOC_DAPM_MUX("Left Preamp Mux", SND_SOC_NOPM, 0, 0, &lbypass_mux),
231
SND_SOC_DAPM_MUX("Right Preamp Mux", SND_SOC_NOPM, 0, 0, &rbypass_mux),
233
SND_SOC_DAPM_PGA("PGAL", WM8737_POWER_MANAGEMENT, 5, 0, NULL, 0),
234
SND_SOC_DAPM_PGA("PGAR", WM8737_POWER_MANAGEMENT, 4, 0, NULL, 0),
236
SND_SOC_DAPM_DAC("ADCL", NULL, WM8737_POWER_MANAGEMENT, 3, 0),
237
SND_SOC_DAPM_DAC("ADCR", NULL, WM8737_POWER_MANAGEMENT, 2, 0),
239
SND_SOC_DAPM_AIF_OUT("AIF", "Capture", 0, WM8737_POWER_MANAGEMENT, 6, 0),
242
static const struct snd_soc_dapm_route intercon[] = {
243
{ "LINSEL", "LINPUT1", "LINPUT1" },
244
{ "LINSEL", "LINPUT2", "LINPUT2" },
245
{ "LINSEL", "LINPUT3", "LINPUT3" },
246
{ "LINSEL", "LINPUT1 DC", "LINPUT1" },
248
{ "RINSEL", "RINPUT1", "RINPUT1" },
249
{ "RINSEL", "RINPUT2", "RINPUT2" },
250
{ "RINSEL", "RINPUT3", "RINPUT3" },
251
{ "RINSEL", "RINPUT1 DC", "RINPUT1" },
253
{ "Left Preamp Mux", "Preamp", "LINSEL" },
254
{ "Left Preamp Mux", "Direct", "LACIN" },
256
{ "Right Preamp Mux", "Preamp", "RINSEL" },
257
{ "Right Preamp Mux", "Direct", "RACIN" },
259
{ "PGAL", NULL, "Left Preamp Mux" },
260
{ "PGAR", NULL, "Right Preamp Mux" },
262
{ "ADCL", NULL, "PGAL" },
263
{ "ADCR", NULL, "PGAR" },
265
{ "AIF", NULL, "ADCL" },
266
{ "AIF", NULL, "ADCR" },
269
static int wm8737_add_widgets(struct snd_soc_codec *codec)
271
struct snd_soc_dapm_context *dapm = &codec->dapm;
273
snd_soc_dapm_new_controls(dapm, wm8737_dapm_widgets,
274
ARRAY_SIZE(wm8737_dapm_widgets));
275
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
280
/* codec mclk clock divider coefficients */
281
static const struct {
287
{ 12288000, 8000, 0, 0x4 },
288
{ 12288000, 12000, 0, 0x8 },
289
{ 12288000, 16000, 0, 0xa },
290
{ 12288000, 24000, 0, 0x1c },
291
{ 12288000, 32000, 0, 0xc },
292
{ 12288000, 48000, 0, 0 },
293
{ 12288000, 96000, 0, 0xe },
295
{ 11289600, 8000, 0, 0x14 },
296
{ 11289600, 11025, 0, 0x18 },
297
{ 11289600, 22050, 0, 0x1a },
298
{ 11289600, 44100, 0, 0x10 },
299
{ 11289600, 88200, 0, 0x1e },
301
{ 18432000, 8000, 0, 0x5 },
302
{ 18432000, 12000, 0, 0x9 },
303
{ 18432000, 16000, 0, 0xb },
304
{ 18432000, 24000, 0, 0x1b },
305
{ 18432000, 32000, 0, 0xd },
306
{ 18432000, 48000, 0, 0x1 },
307
{ 18432000, 96000, 0, 0x1f },
309
{ 16934400, 8000, 0, 0x15 },
310
{ 16934400, 11025, 0, 0x19 },
311
{ 16934400, 22050, 0, 0x1b },
312
{ 16934400, 44100, 0, 0x11 },
313
{ 16934400, 88200, 0, 0x1f },
315
{ 12000000, 8000, 1, 0x4 },
316
{ 12000000, 11025, 1, 0x19 },
317
{ 12000000, 12000, 1, 0x8 },
318
{ 12000000, 16000, 1, 0xa },
319
{ 12000000, 22050, 1, 0x1b },
320
{ 12000000, 24000, 1, 0x1c },
321
{ 12000000, 32000, 1, 0xc },
322
{ 12000000, 44100, 1, 0x11 },
323
{ 12000000, 48000, 1, 0x0 },
324
{ 12000000, 88200, 1, 0x1f },
325
{ 12000000, 96000, 1, 0xe },
328
static int wm8737_hw_params(struct snd_pcm_substream *substream,
329
struct snd_pcm_hw_params *params,
330
struct snd_soc_dai *dai)
332
struct snd_soc_pcm_runtime *rtd = substream->private_data;
333
struct snd_soc_codec *codec = rtd->codec;
334
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
339
for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
340
if (coeff_div[i].rate != params_rate(params))
343
if (coeff_div[i].mclk == wm8737->mclk)
346
if (coeff_div[i].mclk == wm8737->mclk * 2) {
347
clocking |= WM8737_CLKDIV2;
352
if (i == ARRAY_SIZE(coeff_div)) {
353
dev_err(codec->dev, "%dHz MCLK can't support %dHz\n",
354
wm8737->mclk, params_rate(params));
358
clocking |= coeff_div[i].usb | (coeff_div[i].sr << WM8737_SR_SHIFT);
360
switch (params_format(params)) {
361
case SNDRV_PCM_FORMAT_S16_LE:
363
case SNDRV_PCM_FORMAT_S20_3LE:
366
case SNDRV_PCM_FORMAT_S24_LE:
369
case SNDRV_PCM_FORMAT_S32_LE:
376
snd_soc_update_bits(codec, WM8737_AUDIO_FORMAT, WM8737_WL_MASK, af);
377
snd_soc_update_bits(codec, WM8737_CLOCKING,
378
WM8737_USB_MODE | WM8737_CLKDIV2 | WM8737_SR_MASK,
384
static int wm8737_set_dai_sysclk(struct snd_soc_dai *codec_dai,
385
int clk_id, unsigned int freq, int dir)
387
struct snd_soc_codec *codec = codec_dai->codec;
388
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
391
for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
392
if (freq == coeff_div[i].mclk ||
393
freq == coeff_div[i].mclk * 2) {
399
dev_err(codec->dev, "MCLK rate %dHz not supported\n", freq);
405
static int wm8737_set_dai_fmt(struct snd_soc_dai *codec_dai,
408
struct snd_soc_codec *codec = codec_dai->codec;
411
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
412
case SND_SOC_DAIFMT_CBM_CFM:
415
case SND_SOC_DAIFMT_CBS_CFS:
421
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
422
case SND_SOC_DAIFMT_I2S:
425
case SND_SOC_DAIFMT_RIGHT_J:
427
case SND_SOC_DAIFMT_LEFT_J:
430
case SND_SOC_DAIFMT_DSP_A:
433
case SND_SOC_DAIFMT_DSP_B:
440
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
441
case SND_SOC_DAIFMT_NB_NF:
443
case SND_SOC_DAIFMT_NB_IF:
450
snd_soc_update_bits(codec, WM8737_AUDIO_FORMAT,
451
WM8737_FORMAT_MASK | WM8737_LRP | WM8737_MS, af);
456
static int wm8737_set_bias_level(struct snd_soc_codec *codec,
457
enum snd_soc_bias_level level)
459
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
463
case SND_SOC_BIAS_ON:
466
case SND_SOC_BIAS_PREPARE:
468
snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL,
469
WM8737_VMIDSEL_MASK, 0);
472
case SND_SOC_BIAS_STANDBY:
473
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
474
ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies),
478
"Failed to enable supplies: %d\n",
483
snd_soc_cache_sync(codec);
485
/* Fast VMID ramp at 2*2.5k */
486
snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL,
487
WM8737_VMIDSEL_MASK, 0x4);
490
snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT,
500
snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL,
501
WM8737_VMIDSEL_MASK, 2);
505
case SND_SOC_BIAS_OFF:
506
snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT,
507
WM8737_VMID_MASK | WM8737_VREF_MASK, 0);
509
regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies),
514
codec->dapm.bias_level = level;
518
#define WM8737_RATES SNDRV_PCM_RATE_8000_96000
520
#define WM8737_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
521
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
523
static struct snd_soc_dai_ops wm8737_dai_ops = {
524
.hw_params = wm8737_hw_params,
525
.set_sysclk = wm8737_set_dai_sysclk,
526
.set_fmt = wm8737_set_dai_fmt,
529
static struct snd_soc_dai_driver wm8737_dai = {
532
.stream_name = "Capture",
533
.channels_min = 2, /* Mono modes not yet supported */
535
.rates = WM8737_RATES,
536
.formats = WM8737_FORMATS,
538
.ops = &wm8737_dai_ops,
542
static int wm8737_suspend(struct snd_soc_codec *codec, pm_message_t state)
544
wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF);
548
static int wm8737_resume(struct snd_soc_codec *codec)
550
wm8737_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
554
#define wm8737_suspend NULL
555
#define wm8737_resume NULL
558
static int wm8737_probe(struct snd_soc_codec *codec)
560
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
563
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8737->control_type);
565
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
569
for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++)
570
wm8737->supplies[i].supply = wm8737_supply_names[i];
572
ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8737->supplies),
575
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
579
ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies),
582
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
586
ret = wm8737_reset(codec);
588
dev_err(codec->dev, "Failed to issue reset\n");
592
snd_soc_update_bits(codec, WM8737_LEFT_PGA_VOLUME, WM8737_LVU,
594
snd_soc_update_bits(codec, WM8737_RIGHT_PGA_VOLUME, WM8737_RVU,
597
wm8737_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
599
/* Bias level configuration will have done an extra enable */
600
regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
602
snd_soc_add_controls(codec, wm8737_snd_controls,
603
ARRAY_SIZE(wm8737_snd_controls));
604
wm8737_add_widgets(codec);
609
regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
611
regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
616
static int wm8737_remove(struct snd_soc_codec *codec)
618
struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec);
620
wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF);
621
regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
625
static struct snd_soc_codec_driver soc_codec_dev_wm8737 = {
626
.probe = wm8737_probe,
627
.remove = wm8737_remove,
628
.suspend = wm8737_suspend,
629
.resume = wm8737_resume,
630
.set_bias_level = wm8737_set_bias_level,
632
.reg_cache_size = WM8737_REGISTER_COUNT - 1, /* Skip reset */
633
.reg_word_size = sizeof(u16),
634
.reg_cache_default = wm8737_reg,
637
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
638
static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
639
const struct i2c_device_id *id)
641
struct wm8737_priv *wm8737;
644
wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL);
648
i2c_set_clientdata(i2c, wm8737);
649
wm8737->control_type = SND_SOC_I2C;
651
ret = snd_soc_register_codec(&i2c->dev,
652
&soc_codec_dev_wm8737, &wm8737_dai, 1);
659
static __devexit int wm8737_i2c_remove(struct i2c_client *client)
661
snd_soc_unregister_codec(&client->dev);
662
kfree(i2c_get_clientdata(client));
666
static const struct i2c_device_id wm8737_i2c_id[] = {
670
MODULE_DEVICE_TABLE(i2c, wm8737_i2c_id);
672
static struct i2c_driver wm8737_i2c_driver = {
675
.owner = THIS_MODULE,
677
.probe = wm8737_i2c_probe,
678
.remove = __devexit_p(wm8737_i2c_remove),
679
.id_table = wm8737_i2c_id,
683
#if defined(CONFIG_SPI_MASTER)
684
static int __devinit wm8737_spi_probe(struct spi_device *spi)
686
struct wm8737_priv *wm8737;
689
wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL);
693
wm8737->control_type = SND_SOC_SPI;
694
spi_set_drvdata(spi, wm8737);
696
ret = snd_soc_register_codec(&spi->dev,
697
&soc_codec_dev_wm8737, &wm8737_dai, 1);
703
static int __devexit wm8737_spi_remove(struct spi_device *spi)
705
snd_soc_unregister_codec(&spi->dev);
706
kfree(spi_get_drvdata(spi));
710
static struct spi_driver wm8737_spi_driver = {
713
.owner = THIS_MODULE,
715
.probe = wm8737_spi_probe,
716
.remove = __devexit_p(wm8737_spi_remove),
718
#endif /* CONFIG_SPI_MASTER */
720
static int __init wm8737_modinit(void)
723
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
724
ret = i2c_add_driver(&wm8737_i2c_driver);
726
printk(KERN_ERR "Failed to register WM8737 I2C driver: %d\n",
730
#if defined(CONFIG_SPI_MASTER)
731
ret = spi_register_driver(&wm8737_spi_driver);
733
printk(KERN_ERR "Failed to register WM8737 SPI driver: %d\n",
739
module_init(wm8737_modinit);
741
static void __exit wm8737_exit(void)
743
#if defined(CONFIG_SPI_MASTER)
744
spi_unregister_driver(&wm8737_spi_driver);
746
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
747
i2c_del_driver(&wm8737_i2c_driver);
750
module_exit(wm8737_exit);
752
MODULE_DESCRIPTION("ASoC WM8737 driver");
753
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
754
MODULE_LICENSE("GPL");