blob: b7fd96adac643043a3e4bfe0b45c984112bdbc77 [file] [log] [blame]
Mark Brown0e0e16a2008-08-04 12:06:45 +01001/*
2 * wm8900.c -- WM8900 ALSA Soc Audio driver
3 *
4 * Copyright 2007, 2008 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
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.
11 *
12 * TODO:
13 * - Tristating.
14 * - TDM.
15 * - Jack detect.
16 * - FLL source configuration, currently only MCLK is supported.
17 */
18
19#include <linux/module.h>
20#include <linux/moduleparam.h>
Mark Brown0e0e16a2008-08-04 12:06:45 +010021#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/delay.h>
24#include <linux/pm.h>
25#include <linux/i2c.h>
26#include <linux/platform_device.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090027#include <linux/slab.h>
Mark Brown0e0e16a2008-08-04 12:06:45 +010028#include <sound/core.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/soc.h>
32#include <sound/soc-dapm.h>
33#include <sound/initval.h>
34#include <sound/tlv.h>
35
36#include "wm8900.h"
37
38/* WM8900 register space */
39#define WM8900_REG_RESET 0x0
40#define WM8900_REG_ID 0x0
41#define WM8900_REG_POWER1 0x1
42#define WM8900_REG_POWER2 0x2
43#define WM8900_REG_POWER3 0x3
44#define WM8900_REG_AUDIO1 0x4
45#define WM8900_REG_AUDIO2 0x5
46#define WM8900_REG_CLOCKING1 0x6
47#define WM8900_REG_CLOCKING2 0x7
48#define WM8900_REG_AUDIO3 0x8
49#define WM8900_REG_AUDIO4 0x9
50#define WM8900_REG_DACCTRL 0xa
51#define WM8900_REG_LDAC_DV 0xb
52#define WM8900_REG_RDAC_DV 0xc
53#define WM8900_REG_SIDETONE 0xd
54#define WM8900_REG_ADCCTRL 0xe
55#define WM8900_REG_LADC_DV 0xf
56#define WM8900_REG_RADC_DV 0x10
57#define WM8900_REG_GPIO 0x12
58#define WM8900_REG_INCTL 0x15
59#define WM8900_REG_LINVOL 0x16
60#define WM8900_REG_RINVOL 0x17
61#define WM8900_REG_INBOOSTMIX1 0x18
62#define WM8900_REG_INBOOSTMIX2 0x19
63#define WM8900_REG_ADCPATH 0x1a
64#define WM8900_REG_AUXBOOST 0x1b
65#define WM8900_REG_ADDCTL 0x1e
66#define WM8900_REG_FLLCTL1 0x24
67#define WM8900_REG_FLLCTL2 0x25
68#define WM8900_REG_FLLCTL3 0x26
69#define WM8900_REG_FLLCTL4 0x27
70#define WM8900_REG_FLLCTL5 0x28
71#define WM8900_REG_FLLCTL6 0x29
72#define WM8900_REG_LOUTMIXCTL1 0x2c
73#define WM8900_REG_ROUTMIXCTL1 0x2d
74#define WM8900_REG_BYPASS1 0x2e
75#define WM8900_REG_BYPASS2 0x2f
76#define WM8900_REG_AUXOUT_CTL 0x30
77#define WM8900_REG_LOUT1CTL 0x33
78#define WM8900_REG_ROUT1CTL 0x34
79#define WM8900_REG_LOUT2CTL 0x35
80#define WM8900_REG_ROUT2CTL 0x36
81#define WM8900_REG_HPCTL1 0x3a
82#define WM8900_REG_OUTBIASCTL 0x73
83
84#define WM8900_MAXREG 0x80
85
86#define WM8900_REG_ADDCTL_OUT1_DIS 0x80
87#define WM8900_REG_ADDCTL_OUT2_DIS 0x40
88#define WM8900_REG_ADDCTL_VMID_DIS 0x20
89#define WM8900_REG_ADDCTL_BIAS_SRC 0x10
90#define WM8900_REG_ADDCTL_VMID_SOFTST 0x04
91#define WM8900_REG_ADDCTL_TEMP_SD 0x02
92
93#define WM8900_REG_GPIO_TEMP_ENA 0x2
94
95#define WM8900_REG_POWER1_STARTUP_BIAS_ENA 0x0100
96#define WM8900_REG_POWER1_BIAS_ENA 0x0008
97#define WM8900_REG_POWER1_VMID_BUF_ENA 0x0004
98#define WM8900_REG_POWER1_FLL_ENA 0x0040
99
100#define WM8900_REG_POWER2_SYSCLK_ENA 0x8000
101#define WM8900_REG_POWER2_ADCL_ENA 0x0002
102#define WM8900_REG_POWER2_ADCR_ENA 0x0001
103
104#define WM8900_REG_POWER3_DACL_ENA 0x0002
105#define WM8900_REG_POWER3_DACR_ENA 0x0001
106
107#define WM8900_REG_AUDIO1_AIF_FMT_MASK 0x0018
108#define WM8900_REG_AUDIO1_LRCLK_INV 0x0080
109#define WM8900_REG_AUDIO1_BCLK_INV 0x0100
110
111#define WM8900_REG_CLOCKING1_BCLK_DIR 0x1
112#define WM8900_REG_CLOCKING1_MCLK_SRC 0x100
113#define WM8900_REG_CLOCKING1_BCLK_MASK (~0x01e)
114#define WM8900_REG_CLOCKING1_OPCLK_MASK (~0x7000)
115
116#define WM8900_REG_CLOCKING2_ADC_CLKDIV 0xe0
117#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
118
119#define WM8900_REG_DACCTRL_MUTE 0x004
Mark Brown21002e22009-06-12 17:27:52 +0100120#define WM8900_REG_DACCTRL_DAC_SB_FILT 0x100
Mark Brown0e0e16a2008-08-04 12:06:45 +0100121#define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400
122
123#define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800
124
125#define WM8900_REG_AUDIO4_DACLRC_DIR 0x0800
126
127#define WM8900_REG_FLLCTL1_OSC_ENA 0x100
128
129#define WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF 0x100
130
131#define WM8900_REG_HPCTL1_HP_IPSTAGE_ENA 0x80
132#define WM8900_REG_HPCTL1_HP_OPSTAGE_ENA 0x40
133#define WM8900_REG_HPCTL1_HP_CLAMP_IP 0x20
134#define WM8900_REG_HPCTL1_HP_CLAMP_OP 0x10
135#define WM8900_REG_HPCTL1_HP_SHORT 0x08
136#define WM8900_REG_HPCTL1_HP_SHORT2 0x04
137
138#define WM8900_LRC_MASK 0xfc00
139
140struct snd_soc_codec_device soc_codec_dev_wm8900;
141
142struct wm8900_priv {
Mark Brown78e19a32008-12-10 15:38:36 +0000143 struct snd_soc_codec codec;
144
145 u16 reg_cache[WM8900_MAXREG];
146
Mark Brown0e0e16a2008-08-04 12:06:45 +0100147 u32 fll_in; /* FLL input frequency */
148 u32 fll_out; /* FLL output frequency */
149};
150
151/*
152 * wm8900 register cache. We can't read the entire register space and we
153 * have slow control buses so we cache the registers.
154 */
155static const u16 wm8900_reg_defaults[WM8900_MAXREG] = {
156 0x8900, 0x0000,
157 0xc000, 0x0000,
158 0x4050, 0x4000,
159 0x0008, 0x0000,
160 0x0040, 0x0040,
161 0x1004, 0x00c0,
162 0x00c0, 0x0000,
163 0x0100, 0x00c0,
164 0x00c0, 0x0000,
165 0xb001, 0x0000,
166 0x0000, 0x0044,
167 0x004c, 0x004c,
168 0x0044, 0x0044,
169 0x0000, 0x0044,
170 0x0000, 0x0000,
171 0x0002, 0x0000,
172 0x0000, 0x0000,
173 0x0000, 0x0000,
174 0x0008, 0x0000,
175 0x0000, 0x0008,
176 0x0097, 0x0100,
177 0x0000, 0x0000,
178 0x0050, 0x0050,
179 0x0055, 0x0055,
180 0x0055, 0x0000,
181 0x0000, 0x0079,
182 0x0079, 0x0079,
183 0x0079, 0x0000,
184 /* Remaining registers all zero */
185};
186
Mark Brown8d50e442009-07-10 23:12:01 +0100187static int wm8900_volatile_register(unsigned int reg)
Mark Brown0e0e16a2008-08-04 12:06:45 +0100188{
189 switch (reg) {
190 case WM8900_REG_ID:
Mark Brown8d50e442009-07-10 23:12:01 +0100191 case WM8900_REG_POWER1:
192 return 1;
Mark Brown0e0e16a2008-08-04 12:06:45 +0100193 default:
Mark Brown8d50e442009-07-10 23:12:01 +0100194 return 0;
Mark Brown0e0e16a2008-08-04 12:06:45 +0100195 }
196}
197
198static void wm8900_reset(struct snd_soc_codec *codec)
199{
Mark Brown8d50e442009-07-10 23:12:01 +0100200 snd_soc_write(codec, WM8900_REG_RESET, 0);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100201
202 memcpy(codec->reg_cache, wm8900_reg_defaults,
Julia Lawallbc258002009-12-13 12:43:15 +0100203 sizeof(wm8900_reg_defaults));
Mark Brown0e0e16a2008-08-04 12:06:45 +0100204}
205
206static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
207 struct snd_kcontrol *kcontrol, int event)
208{
209 struct snd_soc_codec *codec = w->codec;
Mark Brown8d50e442009-07-10 23:12:01 +0100210 u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100211
212 switch (event) {
213 case SND_SOC_DAPM_PRE_PMU:
214 /* Clamp headphone outputs */
215 hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP |
216 WM8900_REG_HPCTL1_HP_CLAMP_OP;
Mark Brown8d50e442009-07-10 23:12:01 +0100217 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100218 break;
219
220 case SND_SOC_DAPM_POST_PMU:
221 /* Enable the input stage */
222 hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_IP;
223 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT |
224 WM8900_REG_HPCTL1_HP_SHORT2 |
225 WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
Mark Brown8d50e442009-07-10 23:12:01 +0100226 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100227
228 msleep(400);
229
230 /* Enable the output stage */
231 hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP;
232 hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
Mark Brown8d50e442009-07-10 23:12:01 +0100233 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100234
235 /* Remove the shorts */
236 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2;
Mark Brown8d50e442009-07-10 23:12:01 +0100237 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100238 hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT;
Mark Brown8d50e442009-07-10 23:12:01 +0100239 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100240 break;
241
242 case SND_SOC_DAPM_PRE_PMD:
243 /* Short the output */
244 hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT;
Mark Brown8d50e442009-07-10 23:12:01 +0100245 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100246
247 /* Disable the output stage */
248 hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
Mark Brown8d50e442009-07-10 23:12:01 +0100249 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100250
251 /* Clamp the outputs and power down input */
252 hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP |
253 WM8900_REG_HPCTL1_HP_CLAMP_OP;
254 hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
Mark Brown8d50e442009-07-10 23:12:01 +0100255 snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100256 break;
257
258 case SND_SOC_DAPM_POST_PMD:
259 /* Disable everything */
Mark Brown8d50e442009-07-10 23:12:01 +0100260 snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100261 break;
262
263 default:
264 BUG();
265 }
266
267 return 0;
268}
269
270static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -5700, 100, 0);
271
272static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 0);
273
274static const DECLARE_TLV_DB_SCALE(in_boost_tlv, -1200, 600, 0);
275
276static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1200, 100, 0);
277
278static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0);
279
280static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1);
281
282static const DECLARE_TLV_DB_SCALE(adc_svol_tlv, -3600, 300, 0);
283
284static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
285
286static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" };
287
288static const struct soc_enum mic_bias_level =
289SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt);
290
291static const char *dac_mute_rate_txt[] = { "Fast", "Slow" };
292
293static const struct soc_enum dac_mute_rate =
294SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt);
295
296static const char *dac_deemphasis_txt[] = {
297 "Disabled", "32kHz", "44.1kHz", "48kHz"
298};
299
300static const struct soc_enum dac_deemphasis =
301SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt);
302
303static const char *adc_hpf_cut_txt[] = {
304 "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"
305};
306
307static const struct soc_enum adc_hpf_cut =
308SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt);
309
310static const char *lr_txt[] = {
311 "Left", "Right"
312};
313
314static const struct soc_enum aifl_src =
315SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt);
316
317static const struct soc_enum aifr_src =
318SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt);
319
320static const struct soc_enum dacl_src =
321SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt);
322
323static const struct soc_enum dacr_src =
324SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt);
325
326static const char *sidetone_txt[] = {
327 "Disabled", "Left ADC", "Right ADC"
328};
329
330static const struct soc_enum dacl_sidetone =
331SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt);
332
333static const struct soc_enum dacr_sidetone =
334SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt);
335
336static const struct snd_kcontrol_new wm8900_snd_controls[] = {
337SOC_ENUM("Mic Bias Level", mic_bias_level),
338
339SOC_SINGLE_TLV("Left Input PGA Volume", WM8900_REG_LINVOL, 0, 31, 0,
340 in_pga_tlv),
341SOC_SINGLE("Left Input PGA Switch", WM8900_REG_LINVOL, 6, 1, 1),
342SOC_SINGLE("Left Input PGA ZC Switch", WM8900_REG_LINVOL, 7, 1, 0),
343
344SOC_SINGLE_TLV("Right Input PGA Volume", WM8900_REG_RINVOL, 0, 31, 0,
345 in_pga_tlv),
346SOC_SINGLE("Right Input PGA Switch", WM8900_REG_RINVOL, 6, 1, 1),
347SOC_SINGLE("Right Input PGA ZC Switch", WM8900_REG_RINVOL, 7, 1, 0),
348
349SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1),
350SOC_ENUM("DAC Mute Rate", dac_mute_rate),
351SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0),
352SOC_ENUM("DAC Deemphasis", dac_deemphasis),
Mark Brown0e0e16a2008-08-04 12:06:45 +0100353SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL,
354 12, 1, 0),
355
356SOC_SINGLE("ADC HPF Switch", WM8900_REG_ADCCTRL, 8, 1, 0),
357SOC_ENUM("ADC HPF Cut-Off", adc_hpf_cut),
358SOC_DOUBLE("ADC Invert Switch", WM8900_REG_ADCCTRL, 1, 0, 1, 0),
359SOC_SINGLE_TLV("Left ADC Sidetone Volume", WM8900_REG_SIDETONE, 9, 12, 0,
360 adc_svol_tlv),
361SOC_SINGLE_TLV("Right ADC Sidetone Volume", WM8900_REG_SIDETONE, 5, 12, 0,
362 adc_svol_tlv),
363SOC_ENUM("Left Digital Audio Source", aifl_src),
364SOC_ENUM("Right Digital Audio Source", aifr_src),
365
366SOC_SINGLE_TLV("DAC Input Boost Volume", WM8900_REG_AUDIO2, 10, 4, 0,
367 dac_boost_tlv),
368SOC_ENUM("Left DAC Source", dacl_src),
369SOC_ENUM("Right DAC Source", dacr_src),
370SOC_ENUM("Left DAC Sidetone", dacl_sidetone),
371SOC_ENUM("Right DAC Sidetone", dacr_sidetone),
372SOC_DOUBLE("DAC Invert Switch", WM8900_REG_DACCTRL, 1, 0, 1, 0),
373
374SOC_DOUBLE_R_TLV("Digital Playback Volume",
375 WM8900_REG_LDAC_DV, WM8900_REG_RDAC_DV,
376 1, 96, 0, dac_tlv),
377SOC_DOUBLE_R_TLV("Digital Capture Volume",
378 WM8900_REG_LADC_DV, WM8900_REG_RADC_DV, 1, 119, 0, adc_tlv),
379
380SOC_SINGLE_TLV("LINPUT3 Bypass Volume", WM8900_REG_LOUTMIXCTL1, 4, 7, 0,
381 out_mix_tlv),
382SOC_SINGLE_TLV("RINPUT3 Bypass Volume", WM8900_REG_ROUTMIXCTL1, 4, 7, 0,
383 out_mix_tlv),
384SOC_SINGLE_TLV("Left AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 4, 7, 0,
385 out_mix_tlv),
386SOC_SINGLE_TLV("Right AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 0, 7, 0,
387 out_mix_tlv),
388
389SOC_SINGLE_TLV("LeftIn to RightOut Mixer Volume", WM8900_REG_BYPASS1, 0, 7, 0,
390 out_mix_tlv),
391SOC_SINGLE_TLV("LeftIn to LeftOut Mixer Volume", WM8900_REG_BYPASS1, 4, 7, 0,
392 out_mix_tlv),
393SOC_SINGLE_TLV("RightIn to LeftOut Mixer Volume", WM8900_REG_BYPASS2, 0, 7, 0,
394 out_mix_tlv),
395SOC_SINGLE_TLV("RightIn to RightOut Mixer Volume", WM8900_REG_BYPASS2, 4, 7, 0,
396 out_mix_tlv),
397
398SOC_SINGLE_TLV("IN2L Boost Volume", WM8900_REG_INBOOSTMIX1, 0, 3, 0,
399 in_boost_tlv),
400SOC_SINGLE_TLV("IN3L Boost Volume", WM8900_REG_INBOOSTMIX1, 4, 3, 0,
401 in_boost_tlv),
402SOC_SINGLE_TLV("IN2R Boost Volume", WM8900_REG_INBOOSTMIX2, 0, 3, 0,
403 in_boost_tlv),
404SOC_SINGLE_TLV("IN3R Boost Volume", WM8900_REG_INBOOSTMIX2, 4, 3, 0,
405 in_boost_tlv),
406SOC_SINGLE_TLV("Left AUX Boost Volume", WM8900_REG_AUXBOOST, 4, 3, 0,
407 in_boost_tlv),
408SOC_SINGLE_TLV("Right AUX Boost Volume", WM8900_REG_AUXBOOST, 0, 3, 0,
409 in_boost_tlv),
410
411SOC_DOUBLE_R_TLV("LINEOUT1 Volume", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
412 0, 63, 0, out_pga_tlv),
413SOC_DOUBLE_R("LINEOUT1 Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
414 6, 1, 1),
415SOC_DOUBLE_R("LINEOUT1 ZC Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
416 7, 1, 0),
417
418SOC_DOUBLE_R_TLV("LINEOUT2 Volume",
419 WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL,
420 0, 63, 0, out_pga_tlv),
421SOC_DOUBLE_R("LINEOUT2 Switch",
422 WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 6, 1, 1),
423SOC_DOUBLE_R("LINEOUT2 ZC Switch",
424 WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 7, 1, 0),
425SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1,
426 0, 1, 1),
427
428};
429
Mark Brown0e0e16a2008-08-04 12:06:45 +0100430static const struct snd_kcontrol_new wm8900_dapm_loutput2_control =
431SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0);
432
433static const struct snd_kcontrol_new wm8900_dapm_routput2_control =
434SOC_DAPM_SINGLE("LINEOUT2R Switch", WM8900_REG_POWER3, 5, 1, 0);
435
436static const struct snd_kcontrol_new wm8900_loutmix_controls[] = {
437SOC_DAPM_SINGLE("LINPUT3 Bypass Switch", WM8900_REG_LOUTMIXCTL1, 7, 1, 0),
438SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 7, 1, 0),
439SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 7, 1, 0),
440SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 3, 1, 0),
441SOC_DAPM_SINGLE("DACL Switch", WM8900_REG_LOUTMIXCTL1, 8, 1, 0),
442};
443
444static const struct snd_kcontrol_new wm8900_routmix_controls[] = {
445SOC_DAPM_SINGLE("RINPUT3 Bypass Switch", WM8900_REG_ROUTMIXCTL1, 7, 1, 0),
446SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 3, 1, 0),
447SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 3, 1, 0),
448SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 7, 1, 0),
449SOC_DAPM_SINGLE("DACR Switch", WM8900_REG_ROUTMIXCTL1, 8, 1, 0),
450};
451
452static const struct snd_kcontrol_new wm8900_linmix_controls[] = {
453SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INBOOSTMIX1, 2, 1, 1),
454SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INBOOSTMIX1, 6, 1, 1),
455SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 6, 1, 1),
456SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 6, 1, 0),
457};
458
459static const struct snd_kcontrol_new wm8900_rinmix_controls[] = {
460SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INBOOSTMIX2, 2, 1, 1),
461SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INBOOSTMIX2, 6, 1, 1),
462SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 2, 1, 1),
463SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 2, 1, 0),
464};
465
466static const struct snd_kcontrol_new wm8900_linpga_controls[] = {
467SOC_DAPM_SINGLE("LINPUT1 Switch", WM8900_REG_INCTL, 6, 1, 0),
468SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INCTL, 5, 1, 0),
469SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INCTL, 4, 1, 0),
470};
471
472static const struct snd_kcontrol_new wm8900_rinpga_controls[] = {
473SOC_DAPM_SINGLE("RINPUT1 Switch", WM8900_REG_INCTL, 2, 1, 0),
474SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INCTL, 1, 1, 0),
475SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0),
476};
477
478static const char *wm9700_lp_mux[] = { "Disabled", "Enabled" };
479
480static const struct soc_enum wm8900_lineout2_lp_mux =
481SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm9700_lp_mux);
482
483static const struct snd_kcontrol_new wm8900_lineout2_lp =
484SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux);
485
486static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = {
487
488/* Externally visible pins */
489SND_SOC_DAPM_OUTPUT("LINEOUT1L"),
490SND_SOC_DAPM_OUTPUT("LINEOUT1R"),
491SND_SOC_DAPM_OUTPUT("LINEOUT2L"),
492SND_SOC_DAPM_OUTPUT("LINEOUT2R"),
493SND_SOC_DAPM_OUTPUT("HP_L"),
494SND_SOC_DAPM_OUTPUT("HP_R"),
495
496SND_SOC_DAPM_INPUT("RINPUT1"),
497SND_SOC_DAPM_INPUT("LINPUT1"),
498SND_SOC_DAPM_INPUT("RINPUT2"),
499SND_SOC_DAPM_INPUT("LINPUT2"),
500SND_SOC_DAPM_INPUT("RINPUT3"),
501SND_SOC_DAPM_INPUT("LINPUT3"),
502SND_SOC_DAPM_INPUT("AUX"),
503
504SND_SOC_DAPM_VMID("VMID"),
505
506/* Input */
507SND_SOC_DAPM_MIXER("Left Input PGA", WM8900_REG_POWER2, 3, 0,
508 wm8900_linpga_controls,
509 ARRAY_SIZE(wm8900_linpga_controls)),
510SND_SOC_DAPM_MIXER("Right Input PGA", WM8900_REG_POWER2, 2, 0,
511 wm8900_rinpga_controls,
512 ARRAY_SIZE(wm8900_rinpga_controls)),
513
514SND_SOC_DAPM_MIXER("Left Input Mixer", WM8900_REG_POWER2, 5, 0,
515 wm8900_linmix_controls,
516 ARRAY_SIZE(wm8900_linmix_controls)),
517SND_SOC_DAPM_MIXER("Right Input Mixer", WM8900_REG_POWER2, 4, 0,
518 wm8900_rinmix_controls,
519 ARRAY_SIZE(wm8900_rinmix_controls)),
520
521SND_SOC_DAPM_MICBIAS("Mic Bias", WM8900_REG_POWER1, 4, 0),
522
523SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8900_REG_POWER2, 1, 0),
524SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8900_REG_POWER2, 0, 0),
525
526/* Output */
527SND_SOC_DAPM_DAC("DACL", "Left HiFi Playback", WM8900_REG_POWER3, 1, 0),
528SND_SOC_DAPM_DAC("DACR", "Right HiFi Playback", WM8900_REG_POWER3, 0, 0),
529
530SND_SOC_DAPM_PGA_E("Headphone Amplifier", WM8900_REG_POWER3, 7, 0, NULL, 0,
531 wm8900_hp_event,
532 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
533 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
534
535SND_SOC_DAPM_PGA("LINEOUT1L PGA", WM8900_REG_POWER2, 8, 0, NULL, 0),
536SND_SOC_DAPM_PGA("LINEOUT1R PGA", WM8900_REG_POWER2, 7, 0, NULL, 0),
537
538SND_SOC_DAPM_MUX("LINEOUT2 LP", SND_SOC_NOPM, 0, 0, &wm8900_lineout2_lp),
539SND_SOC_DAPM_PGA("LINEOUT2L PGA", WM8900_REG_POWER3, 6, 0, NULL, 0),
540SND_SOC_DAPM_PGA("LINEOUT2R PGA", WM8900_REG_POWER3, 5, 0, NULL, 0),
541
542SND_SOC_DAPM_MIXER("Left Output Mixer", WM8900_REG_POWER3, 3, 0,
543 wm8900_loutmix_controls,
544 ARRAY_SIZE(wm8900_loutmix_controls)),
545SND_SOC_DAPM_MIXER("Right Output Mixer", WM8900_REG_POWER3, 2, 0,
546 wm8900_routmix_controls,
547 ARRAY_SIZE(wm8900_routmix_controls)),
548};
549
550/* Target, Path, Source */
551static const struct snd_soc_dapm_route audio_map[] = {
552/* Inputs */
553{"Left Input PGA", "LINPUT1 Switch", "LINPUT1"},
554{"Left Input PGA", "LINPUT2 Switch", "LINPUT2"},
555{"Left Input PGA", "LINPUT3 Switch", "LINPUT3"},
556
557{"Right Input PGA", "RINPUT1 Switch", "RINPUT1"},
558{"Right Input PGA", "RINPUT2 Switch", "RINPUT2"},
559{"Right Input PGA", "RINPUT3 Switch", "RINPUT3"},
560
561{"Left Input Mixer", "LINPUT2 Switch", "LINPUT2"},
562{"Left Input Mixer", "LINPUT3 Switch", "LINPUT3"},
563{"Left Input Mixer", "AUX Switch", "AUX"},
564{"Left Input Mixer", "Input PGA Switch", "Left Input PGA"},
565
566{"Right Input Mixer", "RINPUT2 Switch", "RINPUT2"},
567{"Right Input Mixer", "RINPUT3 Switch", "RINPUT3"},
568{"Right Input Mixer", "AUX Switch", "AUX"},
569{"Right Input Mixer", "Input PGA Switch", "Right Input PGA"},
570
571{"ADCL", NULL, "Left Input Mixer"},
572{"ADCR", NULL, "Right Input Mixer"},
573
574/* Outputs */
575{"LINEOUT1L", NULL, "LINEOUT1L PGA"},
576{"LINEOUT1L PGA", NULL, "Left Output Mixer"},
577{"LINEOUT1R", NULL, "LINEOUT1R PGA"},
578{"LINEOUT1R PGA", NULL, "Right Output Mixer"},
579
580{"LINEOUT2L PGA", NULL, "Left Output Mixer"},
581{"LINEOUT2 LP", "Disabled", "LINEOUT2L PGA"},
582{"LINEOUT2 LP", "Enabled", "Left Output Mixer"},
583{"LINEOUT2L", NULL, "LINEOUT2 LP"},
584
585{"LINEOUT2R PGA", NULL, "Right Output Mixer"},
586{"LINEOUT2 LP", "Disabled", "LINEOUT2R PGA"},
587{"LINEOUT2 LP", "Enabled", "Right Output Mixer"},
588{"LINEOUT2R", NULL, "LINEOUT2 LP"},
589
590{"Left Output Mixer", "LINPUT3 Bypass Switch", "LINPUT3"},
591{"Left Output Mixer", "AUX Bypass Switch", "AUX"},
592{"Left Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"},
593{"Left Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"},
594{"Left Output Mixer", "DACL Switch", "DACL"},
595
596{"Right Output Mixer", "RINPUT3 Bypass Switch", "RINPUT3"},
597{"Right Output Mixer", "AUX Bypass Switch", "AUX"},
598{"Right Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"},
599{"Right Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"},
600{"Right Output Mixer", "DACR Switch", "DACR"},
601
602/* Note that the headphone output stage needs to be connected
603 * externally to LINEOUT2 via DC blocking capacitors. Other
604 * configurations are not supported.
605 *
606 * Note also that left and right headphone paths are treated as a
607 * mono path.
608 */
609{"Headphone Amplifier", NULL, "LINEOUT2 LP"},
610{"Headphone Amplifier", NULL, "LINEOUT2 LP"},
611{"HP_L", NULL, "Headphone Amplifier"},
612{"HP_R", NULL, "Headphone Amplifier"},
613};
614
615static int wm8900_add_widgets(struct snd_soc_codec *codec)
616{
617 snd_soc_dapm_new_controls(codec, wm8900_dapm_widgets,
618 ARRAY_SIZE(wm8900_dapm_widgets));
619
620 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
621
Mark Brown0e0e16a2008-08-04 12:06:45 +0100622 return 0;
623}
624
625static int wm8900_hw_params(struct snd_pcm_substream *substream,
Mark Browndee89c42008-11-18 22:11:38 +0000626 struct snd_pcm_hw_params *params,
627 struct snd_soc_dai *dai)
Mark Brown0e0e16a2008-08-04 12:06:45 +0100628{
629 struct snd_soc_pcm_runtime *rtd = substream->private_data;
630 struct snd_soc_device *socdev = rtd->socdev;
Mark Brown6627a652009-01-23 22:55:23 +0000631 struct snd_soc_codec *codec = socdev->card->codec;
Mark Brown0e0e16a2008-08-04 12:06:45 +0100632 u16 reg;
633
Mark Brown8d50e442009-07-10 23:12:01 +0100634 reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60;
Mark Brown0e0e16a2008-08-04 12:06:45 +0100635
636 switch (params_format(params)) {
637 case SNDRV_PCM_FORMAT_S16_LE:
638 break;
639 case SNDRV_PCM_FORMAT_S20_3LE:
640 reg |= 0x20;
641 break;
642 case SNDRV_PCM_FORMAT_S24_LE:
643 reg |= 0x40;
644 break;
645 case SNDRV_PCM_FORMAT_S32_LE:
646 reg |= 0x60;
647 break;
648 default:
649 return -EINVAL;
650 }
651
Mark Brown8d50e442009-07-10 23:12:01 +0100652 snd_soc_write(codec, WM8900_REG_AUDIO1, reg);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100653
Mark Brown21002e22009-06-12 17:27:52 +0100654 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Mark Brown8d50e442009-07-10 23:12:01 +0100655 reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
Mark Brown21002e22009-06-12 17:27:52 +0100656
657 if (params_rate(params) <= 24000)
658 reg |= WM8900_REG_DACCTRL_DAC_SB_FILT;
659 else
660 reg &= ~WM8900_REG_DACCTRL_DAC_SB_FILT;
661
Mark Brown8d50e442009-07-10 23:12:01 +0100662 snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
Mark Brown21002e22009-06-12 17:27:52 +0100663 }
664
Mark Brown0e0e16a2008-08-04 12:06:45 +0100665 return 0;
666}
667
668/* FLL divisors */
669struct _fll_div {
670 u16 fll_ratio;
671 u16 fllclk_div;
672 u16 fll_slow_lock_ref;
673 u16 n;
674 u16 k;
675};
676
677/* The size in bits of the FLL divide multiplied by 10
678 * to allow rounding later */
679#define FIXED_FLL_SIZE ((1 << 16) * 10)
680
681static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
682 unsigned int Fout)
683{
684 u64 Kpart;
685 unsigned int K, Ndiv, Nmod, target;
686 unsigned int div;
687
688 BUG_ON(!Fout);
689
690 /* The FLL must run at 90-100MHz which is then scaled down to
691 * the output value by FLLCLK_DIV. */
692 target = Fout;
693 div = 1;
694 while (target < 90000000) {
695 div *= 2;
696 target *= 2;
697 }
698
699 if (target > 100000000)
Roel Kluin449bd542009-05-27 17:08:39 -0700700 printk(KERN_WARNING "wm8900: FLL rate %u out of range, Fref=%u"
701 " Fout=%u\n", target, Fref, Fout);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100702 if (div > 32) {
703 printk(KERN_ERR "wm8900: Invalid FLL division rate %u, "
Roel Kluin449bd542009-05-27 17:08:39 -0700704 "Fref=%u, Fout=%u, target=%u\n",
Mark Brown0e0e16a2008-08-04 12:06:45 +0100705 div, Fref, Fout, target);
706 return -EINVAL;
707 }
708
709 fll_div->fllclk_div = div >> 2;
710
711 if (Fref < 48000)
712 fll_div->fll_slow_lock_ref = 1;
713 else
714 fll_div->fll_slow_lock_ref = 0;
715
716 Ndiv = target / Fref;
717
718 if (Fref < 1000000)
719 fll_div->fll_ratio = 8;
720 else
721 fll_div->fll_ratio = 1;
722
723 fll_div->n = Ndiv / fll_div->fll_ratio;
724 Nmod = (target / fll_div->fll_ratio) % Fref;
725
726 /* Calculate fractional part - scale up so we can round. */
727 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
728
729 do_div(Kpart, Fref);
730
731 K = Kpart & 0xFFFFFFFF;
732
733 if ((K % 10) >= 5)
734 K += 5;
735
736 /* Move down to proper range now rounding is done */
737 fll_div->k = K / 10;
738
739 BUG_ON(target != Fout * (fll_div->fllclk_div << 2));
740 BUG_ON(!K && target != Fref * fll_div->fll_ratio * fll_div->n);
741
742 return 0;
743}
744
745static int wm8900_set_fll(struct snd_soc_codec *codec,
746 int fll_id, unsigned int freq_in, unsigned int freq_out)
747{
748 struct wm8900_priv *wm8900 = codec->private_data;
749 struct _fll_div fll_div;
750 unsigned int reg;
751
752 if (wm8900->fll_in == freq_in && wm8900->fll_out == freq_out)
753 return 0;
754
755 /* The digital side should be disabled during any change. */
Mark Brown8d50e442009-07-10 23:12:01 +0100756 reg = snd_soc_read(codec, WM8900_REG_POWER1);
757 snd_soc_write(codec, WM8900_REG_POWER1,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100758 reg & (~WM8900_REG_POWER1_FLL_ENA));
759
760 /* Disable the FLL? */
761 if (!freq_in || !freq_out) {
Mark Brown8d50e442009-07-10 23:12:01 +0100762 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
763 snd_soc_write(codec, WM8900_REG_CLOCKING1,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100764 reg & (~WM8900_REG_CLOCKING1_MCLK_SRC));
765
Mark Brown8d50e442009-07-10 23:12:01 +0100766 reg = snd_soc_read(codec, WM8900_REG_FLLCTL1);
767 snd_soc_write(codec, WM8900_REG_FLLCTL1,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100768 reg & (~WM8900_REG_FLLCTL1_OSC_ENA));
769
770 wm8900->fll_in = freq_in;
771 wm8900->fll_out = freq_out;
772
773 return 0;
774 }
775
776 if (fll_factors(&fll_div, freq_in, freq_out) != 0)
777 goto reenable;
778
779 wm8900->fll_in = freq_in;
780 wm8900->fll_out = freq_out;
781
782 /* The osclilator *MUST* be enabled before we enable the
783 * digital circuit. */
Mark Brown8d50e442009-07-10 23:12:01 +0100784 snd_soc_write(codec, WM8900_REG_FLLCTL1,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100785 fll_div.fll_ratio | WM8900_REG_FLLCTL1_OSC_ENA);
786
Mark Brown8d50e442009-07-10 23:12:01 +0100787 snd_soc_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5);
788 snd_soc_write(codec, WM8900_REG_FLLCTL5,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100789 (fll_div.fllclk_div << 6) | (fll_div.n & 0x1f));
790
791 if (fll_div.k) {
Mark Brown8d50e442009-07-10 23:12:01 +0100792 snd_soc_write(codec, WM8900_REG_FLLCTL2,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100793 (fll_div.k >> 8) | 0x100);
Mark Brown8d50e442009-07-10 23:12:01 +0100794 snd_soc_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100795 } else
Mark Brown8d50e442009-07-10 23:12:01 +0100796 snd_soc_write(codec, WM8900_REG_FLLCTL2, 0);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100797
798 if (fll_div.fll_slow_lock_ref)
Mark Brown8d50e442009-07-10 23:12:01 +0100799 snd_soc_write(codec, WM8900_REG_FLLCTL6,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100800 WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF);
801 else
Mark Brown8d50e442009-07-10 23:12:01 +0100802 snd_soc_write(codec, WM8900_REG_FLLCTL6, 0);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100803
Mark Brown8d50e442009-07-10 23:12:01 +0100804 reg = snd_soc_read(codec, WM8900_REG_POWER1);
805 snd_soc_write(codec, WM8900_REG_POWER1,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100806 reg | WM8900_REG_POWER1_FLL_ENA);
807
808reenable:
Mark Brown8d50e442009-07-10 23:12:01 +0100809 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
810 snd_soc_write(codec, WM8900_REG_CLOCKING1,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100811 reg | WM8900_REG_CLOCKING1_MCLK_SRC);
812
813 return 0;
814}
815
Mark Brown85488032009-09-05 18:52:16 +0100816static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
817 int source, unsigned int freq_in, unsigned int freq_out)
Mark Brown0e0e16a2008-08-04 12:06:45 +0100818{
819 return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out);
820}
821
822static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
823 int div_id, int div)
824{
825 struct snd_soc_codec *codec = codec_dai->codec;
826 unsigned int reg;
827
828 switch (div_id) {
829 case WM8900_BCLK_DIV:
Mark Brown8d50e442009-07-10 23:12:01 +0100830 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
831 snd_soc_write(codec, WM8900_REG_CLOCKING1,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100832 div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK));
833 break;
834 case WM8900_OPCLK_DIV:
Mark Brown8d50e442009-07-10 23:12:01 +0100835 reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
836 snd_soc_write(codec, WM8900_REG_CLOCKING1,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100837 div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK));
838 break;
839 case WM8900_DAC_LRCLK:
Mark Brown8d50e442009-07-10 23:12:01 +0100840 reg = snd_soc_read(codec, WM8900_REG_AUDIO4);
841 snd_soc_write(codec, WM8900_REG_AUDIO4,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100842 div | (reg & WM8900_LRC_MASK));
843 break;
844 case WM8900_ADC_LRCLK:
Mark Brown8d50e442009-07-10 23:12:01 +0100845 reg = snd_soc_read(codec, WM8900_REG_AUDIO3);
846 snd_soc_write(codec, WM8900_REG_AUDIO3,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100847 div | (reg & WM8900_LRC_MASK));
848 break;
849 case WM8900_DAC_CLKDIV:
Mark Brown8d50e442009-07-10 23:12:01 +0100850 reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
851 snd_soc_write(codec, WM8900_REG_CLOCKING2,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100852 div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV));
853 break;
854 case WM8900_ADC_CLKDIV:
Mark Brown8d50e442009-07-10 23:12:01 +0100855 reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
856 snd_soc_write(codec, WM8900_REG_CLOCKING2,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100857 div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV));
858 break;
859 case WM8900_LRCLK_MODE:
Mark Brown8d50e442009-07-10 23:12:01 +0100860 reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
861 snd_soc_write(codec, WM8900_REG_DACCTRL,
Mark Brown0e0e16a2008-08-04 12:06:45 +0100862 div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE));
863 break;
864 default:
865 return -EINVAL;
866 }
867
868 return 0;
869}
870
871
872static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
873 unsigned int fmt)
874{
875 struct snd_soc_codec *codec = codec_dai->codec;
876 unsigned int clocking1, aif1, aif3, aif4;
877
Mark Brown8d50e442009-07-10 23:12:01 +0100878 clocking1 = snd_soc_read(codec, WM8900_REG_CLOCKING1);
879 aif1 = snd_soc_read(codec, WM8900_REG_AUDIO1);
880 aif3 = snd_soc_read(codec, WM8900_REG_AUDIO3);
881 aif4 = snd_soc_read(codec, WM8900_REG_AUDIO4);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100882
883 /* set master/slave audio interface */
884 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
885 case SND_SOC_DAIFMT_CBS_CFS:
886 clocking1 &= ~WM8900_REG_CLOCKING1_BCLK_DIR;
887 aif3 &= ~WM8900_REG_AUDIO3_ADCLRC_DIR;
888 aif4 &= ~WM8900_REG_AUDIO4_DACLRC_DIR;
889 break;
890 case SND_SOC_DAIFMT_CBS_CFM:
891 clocking1 &= ~WM8900_REG_CLOCKING1_BCLK_DIR;
892 aif3 |= WM8900_REG_AUDIO3_ADCLRC_DIR;
893 aif4 |= WM8900_REG_AUDIO4_DACLRC_DIR;
894 break;
895 case SND_SOC_DAIFMT_CBM_CFM:
896 clocking1 |= WM8900_REG_CLOCKING1_BCLK_DIR;
897 aif3 |= WM8900_REG_AUDIO3_ADCLRC_DIR;
898 aif4 |= WM8900_REG_AUDIO4_DACLRC_DIR;
899 break;
900 case SND_SOC_DAIFMT_CBM_CFS:
901 clocking1 |= WM8900_REG_CLOCKING1_BCLK_DIR;
902 aif3 &= ~WM8900_REG_AUDIO3_ADCLRC_DIR;
903 aif4 &= ~WM8900_REG_AUDIO4_DACLRC_DIR;
904 break;
905 default:
906 return -EINVAL;
907 }
908
909 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
910 case SND_SOC_DAIFMT_DSP_A:
911 aif1 |= WM8900_REG_AUDIO1_AIF_FMT_MASK;
912 aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV;
913 break;
914 case SND_SOC_DAIFMT_DSP_B:
915 aif1 |= WM8900_REG_AUDIO1_AIF_FMT_MASK;
916 aif1 |= WM8900_REG_AUDIO1_LRCLK_INV;
917 break;
918 case SND_SOC_DAIFMT_I2S:
919 aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK;
920 aif1 |= 0x10;
921 break;
922 case SND_SOC_DAIFMT_RIGHT_J:
923 aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK;
924 break;
925 case SND_SOC_DAIFMT_LEFT_J:
926 aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK;
927 aif1 |= 0x8;
928 break;
929 default:
930 return -EINVAL;
931 }
932
933 /* Clock inversion */
934 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
935 case SND_SOC_DAIFMT_DSP_A:
936 case SND_SOC_DAIFMT_DSP_B:
937 /* frame inversion not valid for DSP modes */
938 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
939 case SND_SOC_DAIFMT_NB_NF:
940 aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV;
941 break;
942 case SND_SOC_DAIFMT_IB_NF:
943 aif1 |= WM8900_REG_AUDIO1_BCLK_INV;
944 break;
945 default:
946 return -EINVAL;
947 }
948 break;
949 case SND_SOC_DAIFMT_I2S:
950 case SND_SOC_DAIFMT_RIGHT_J:
951 case SND_SOC_DAIFMT_LEFT_J:
952 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
953 case SND_SOC_DAIFMT_NB_NF:
954 aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV;
955 aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV;
956 break;
957 case SND_SOC_DAIFMT_IB_IF:
958 aif1 |= WM8900_REG_AUDIO1_BCLK_INV;
959 aif1 |= WM8900_REG_AUDIO1_LRCLK_INV;
960 break;
961 case SND_SOC_DAIFMT_IB_NF:
962 aif1 |= WM8900_REG_AUDIO1_BCLK_INV;
963 aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV;
964 break;
965 case SND_SOC_DAIFMT_NB_IF:
966 aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV;
967 aif1 |= WM8900_REG_AUDIO1_LRCLK_INV;
968 break;
969 default:
970 return -EINVAL;
971 }
972 break;
973 default:
974 return -EINVAL;
975 }
976
Mark Brown8d50e442009-07-10 23:12:01 +0100977 snd_soc_write(codec, WM8900_REG_CLOCKING1, clocking1);
978 snd_soc_write(codec, WM8900_REG_AUDIO1, aif1);
979 snd_soc_write(codec, WM8900_REG_AUDIO3, aif3);
980 snd_soc_write(codec, WM8900_REG_AUDIO4, aif4);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100981
982 return 0;
983}
984
985static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute)
986{
987 struct snd_soc_codec *codec = codec_dai->codec;
988 u16 reg;
989
Mark Brown8d50e442009-07-10 23:12:01 +0100990 reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100991
992 if (mute)
993 reg |= WM8900_REG_DACCTRL_MUTE;
994 else
995 reg &= ~WM8900_REG_DACCTRL_MUTE;
996
Mark Brown8d50e442009-07-10 23:12:01 +0100997 snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
Mark Brown0e0e16a2008-08-04 12:06:45 +0100998
999 return 0;
1000}
1001
1002#define WM8900_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
1003 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
1004 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
1005
1006#define WM8900_PCM_FORMATS \
1007 (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
1008 SNDRV_PCM_FORMAT_S24_LE)
1009
Eric Miao6335d052009-03-03 09:41:00 +08001010static struct snd_soc_dai_ops wm8900_dai_ops = {
1011 .hw_params = wm8900_hw_params,
1012 .set_clkdiv = wm8900_set_dai_clkdiv,
1013 .set_pll = wm8900_set_dai_pll,
1014 .set_fmt = wm8900_set_dai_fmt,
1015 .digital_mute = wm8900_digital_mute,
1016};
1017
Mark Brown0e0e16a2008-08-04 12:06:45 +01001018struct snd_soc_dai wm8900_dai = {
1019 .name = "WM8900 HiFi",
1020 .playback = {
1021 .stream_name = "HiFi Playback",
1022 .channels_min = 1,
1023 .channels_max = 2,
1024 .rates = WM8900_RATES,
1025 .formats = WM8900_PCM_FORMATS,
1026 },
1027 .capture = {
1028 .stream_name = "HiFi Capture",
1029 .channels_min = 1,
1030 .channels_max = 2,
1031 .rates = WM8900_RATES,
1032 .formats = WM8900_PCM_FORMATS,
1033 },
Eric Miao6335d052009-03-03 09:41:00 +08001034 .ops = &wm8900_dai_ops,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001035};
1036EXPORT_SYMBOL_GPL(wm8900_dai);
1037
1038static int wm8900_set_bias_level(struct snd_soc_codec *codec,
1039 enum snd_soc_bias_level level)
1040{
1041 u16 reg;
1042
1043 switch (level) {
1044 case SND_SOC_BIAS_ON:
1045 /* Enable thermal shutdown */
Mark Brown8d50e442009-07-10 23:12:01 +01001046 reg = snd_soc_read(codec, WM8900_REG_GPIO);
1047 snd_soc_write(codec, WM8900_REG_GPIO,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001048 reg | WM8900_REG_GPIO_TEMP_ENA);
Mark Brown8d50e442009-07-10 23:12:01 +01001049 reg = snd_soc_read(codec, WM8900_REG_ADDCTL);
1050 snd_soc_write(codec, WM8900_REG_ADDCTL,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001051 reg | WM8900_REG_ADDCTL_TEMP_SD);
1052 break;
1053
1054 case SND_SOC_BIAS_PREPARE:
1055 break;
1056
1057 case SND_SOC_BIAS_STANDBY:
1058 /* Charge capacitors if initial power up */
1059 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1060 /* STARTUP_BIAS_ENA on */
Mark Brown8d50e442009-07-10 23:12:01 +01001061 snd_soc_write(codec, WM8900_REG_POWER1,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001062 WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1063
1064 /* Startup bias mode */
Mark Brown8d50e442009-07-10 23:12:01 +01001065 snd_soc_write(codec, WM8900_REG_ADDCTL,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001066 WM8900_REG_ADDCTL_BIAS_SRC |
1067 WM8900_REG_ADDCTL_VMID_SOFTST);
1068
1069 /* VMID 2x50k */
Mark Brown8d50e442009-07-10 23:12:01 +01001070 snd_soc_write(codec, WM8900_REG_POWER1,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001071 WM8900_REG_POWER1_STARTUP_BIAS_ENA | 0x1);
1072
1073 /* Allow capacitors to charge */
1074 schedule_timeout_interruptible(msecs_to_jiffies(400));
1075
1076 /* Enable bias */
Mark Brown8d50e442009-07-10 23:12:01 +01001077 snd_soc_write(codec, WM8900_REG_POWER1,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001078 WM8900_REG_POWER1_STARTUP_BIAS_ENA |
1079 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1080
Mark Brown8d50e442009-07-10 23:12:01 +01001081 snd_soc_write(codec, WM8900_REG_ADDCTL, 0);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001082
Mark Brown8d50e442009-07-10 23:12:01 +01001083 snd_soc_write(codec, WM8900_REG_POWER1,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001084 WM8900_REG_POWER1_BIAS_ENA | 0x1);
1085 }
1086
Mark Brown8d50e442009-07-10 23:12:01 +01001087 reg = snd_soc_read(codec, WM8900_REG_POWER1);
1088 snd_soc_write(codec, WM8900_REG_POWER1,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001089 (reg & WM8900_REG_POWER1_FLL_ENA) |
1090 WM8900_REG_POWER1_BIAS_ENA | 0x1);
Mark Brown8d50e442009-07-10 23:12:01 +01001091 snd_soc_write(codec, WM8900_REG_POWER2,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001092 WM8900_REG_POWER2_SYSCLK_ENA);
Mark Brown8d50e442009-07-10 23:12:01 +01001093 snd_soc_write(codec, WM8900_REG_POWER3, 0);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001094 break;
1095
1096 case SND_SOC_BIAS_OFF:
1097 /* Startup bias enable */
Mark Brown8d50e442009-07-10 23:12:01 +01001098 reg = snd_soc_read(codec, WM8900_REG_POWER1);
1099 snd_soc_write(codec, WM8900_REG_POWER1,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001100 reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA);
Mark Brown8d50e442009-07-10 23:12:01 +01001101 snd_soc_write(codec, WM8900_REG_ADDCTL,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001102 WM8900_REG_ADDCTL_BIAS_SRC |
1103 WM8900_REG_ADDCTL_VMID_SOFTST);
1104
1105 /* Discharge caps */
Mark Brown8d50e442009-07-10 23:12:01 +01001106 snd_soc_write(codec, WM8900_REG_POWER1,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001107 WM8900_REG_POWER1_STARTUP_BIAS_ENA);
1108 schedule_timeout_interruptible(msecs_to_jiffies(500));
1109
1110 /* Remove clamp */
Mark Brown8d50e442009-07-10 23:12:01 +01001111 snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001112
1113 /* Power down */
Mark Brown8d50e442009-07-10 23:12:01 +01001114 snd_soc_write(codec, WM8900_REG_ADDCTL, 0);
1115 snd_soc_write(codec, WM8900_REG_POWER1, 0);
1116 snd_soc_write(codec, WM8900_REG_POWER2, 0);
1117 snd_soc_write(codec, WM8900_REG_POWER3, 0);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001118
1119 /* Need to let things settle before stopping the clock
1120 * to ensure that restart works, see "Stopping the
1121 * master clock" in the datasheet. */
1122 schedule_timeout_interruptible(msecs_to_jiffies(1));
Mark Brown8d50e442009-07-10 23:12:01 +01001123 snd_soc_write(codec, WM8900_REG_POWER2,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001124 WM8900_REG_POWER2_SYSCLK_ENA);
1125 break;
1126 }
1127 codec->bias_level = level;
1128 return 0;
1129}
1130
1131static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)
1132{
1133 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
Mark Brown6627a652009-01-23 22:55:23 +00001134 struct snd_soc_codec *codec = socdev->card->codec;
Mark Brown0e0e16a2008-08-04 12:06:45 +01001135 struct wm8900_priv *wm8900 = codec->private_data;
1136 int fll_out = wm8900->fll_out;
1137 int fll_in = wm8900->fll_in;
1138 int ret;
1139
1140 /* Stop the FLL in an orderly fashion */
1141 ret = wm8900_set_fll(codec, 0, 0, 0);
1142 if (ret != 0) {
1143 dev_err(&pdev->dev, "Failed to stop FLL\n");
1144 return ret;
1145 }
1146
1147 wm8900->fll_out = fll_out;
1148 wm8900->fll_in = fll_in;
1149
1150 wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF);
1151
1152 return 0;
1153}
1154
1155static int wm8900_resume(struct platform_device *pdev)
1156{
1157 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
Mark Brown6627a652009-01-23 22:55:23 +00001158 struct snd_soc_codec *codec = socdev->card->codec;
Mark Brown0e0e16a2008-08-04 12:06:45 +01001159 struct wm8900_priv *wm8900 = codec->private_data;
1160 u16 *cache;
1161 int i, ret;
1162
1163 cache = kmemdup(codec->reg_cache, sizeof(wm8900_reg_defaults),
1164 GFP_KERNEL);
1165
1166 wm8900_reset(codec);
1167 wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1168
1169 /* Restart the FLL? */
1170 if (wm8900->fll_out) {
1171 int fll_out = wm8900->fll_out;
1172 int fll_in = wm8900->fll_in;
1173
1174 wm8900->fll_in = 0;
1175 wm8900->fll_out = 0;
1176
1177 ret = wm8900_set_fll(codec, 0, fll_in, fll_out);
1178 if (ret != 0) {
1179 dev_err(&pdev->dev, "Failed to restart FLL\n");
1180 return ret;
1181 }
1182 }
1183
1184 if (cache) {
1185 for (i = 0; i < WM8900_MAXREG; i++)
Mark Brown8d50e442009-07-10 23:12:01 +01001186 snd_soc_write(codec, i, cache[i]);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001187 kfree(cache);
1188 } else
1189 dev_err(&pdev->dev, "Unable to allocate register cache\n");
1190
1191 return 0;
1192}
1193
Mark Brown78e19a32008-12-10 15:38:36 +00001194static struct snd_soc_codec *wm8900_codec;
1195
Mark Brownc6f29812009-02-18 21:25:40 +00001196static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
1197 const struct i2c_device_id *id)
Mark Brown0e0e16a2008-08-04 12:06:45 +01001198{
Mark Brown78e19a32008-12-10 15:38:36 +00001199 struct wm8900_priv *wm8900;
1200 struct snd_soc_codec *codec;
Mark Brown0e0e16a2008-08-04 12:06:45 +01001201 unsigned int reg;
Mark Brown78e19a32008-12-10 15:38:36 +00001202 int ret;
1203
1204 wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
1205 if (wm8900 == NULL)
1206 return -ENOMEM;
1207
1208 codec = &wm8900->codec;
1209 codec->private_data = wm8900;
1210 codec->reg_cache = &wm8900->reg_cache[0];
1211 codec->reg_cache_size = WM8900_MAXREG;
1212
1213 mutex_init(&codec->mutex);
1214 INIT_LIST_HEAD(&codec->dapm_widgets);
1215 INIT_LIST_HEAD(&codec->dapm_paths);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001216
1217 codec->name = "WM8900";
1218 codec->owner = THIS_MODULE;
Mark Brown0e0e16a2008-08-04 12:06:45 +01001219 codec->dai = &wm8900_dai;
1220 codec->num_dai = 1;
Mark Brown78e19a32008-12-10 15:38:36 +00001221 codec->control_data = i2c;
1222 codec->set_bias_level = wm8900_set_bias_level;
Mark Brown8d50e442009-07-10 23:12:01 +01001223 codec->volatile_register = wm8900_volatile_register;
Mark Brown78e19a32008-12-10 15:38:36 +00001224 codec->dev = &i2c->dev;
Mark Brown0e0e16a2008-08-04 12:06:45 +01001225
Mark Brown8d50e442009-07-10 23:12:01 +01001226 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1227 if (ret != 0) {
1228 dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
1229 goto err;
1230 }
1231
1232 reg = snd_soc_read(codec, WM8900_REG_ID);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001233 if (reg != 0x8900) {
Mark Brown78e19a32008-12-10 15:38:36 +00001234 dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg);
1235 ret = -ENODEV;
1236 goto err;
Mark Brown0e0e16a2008-08-04 12:06:45 +01001237 }
1238
1239 /* Read back from the chip */
Mark Brown8d50e442009-07-10 23:12:01 +01001240 reg = snd_soc_read(codec, WM8900_REG_POWER1);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001241 reg = (reg >> 12) & 0xf;
Mark Brown78e19a32008-12-10 15:38:36 +00001242 dev_info(&i2c->dev, "WM8900 revision %d\n", reg);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001243
1244 wm8900_reset(codec);
1245
Mark Brown78e19a32008-12-10 15:38:36 +00001246 /* Turn the chip on */
1247 wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1248
Mark Brown0e0e16a2008-08-04 12:06:45 +01001249 /* Latch the volume update bits */
Mark Brown8d50e442009-07-10 23:12:01 +01001250 snd_soc_write(codec, WM8900_REG_LINVOL,
1251 snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100);
1252 snd_soc_write(codec, WM8900_REG_RINVOL,
1253 snd_soc_read(codec, WM8900_REG_RINVOL) | 0x100);
1254 snd_soc_write(codec, WM8900_REG_LOUT1CTL,
1255 snd_soc_read(codec, WM8900_REG_LOUT1CTL) | 0x100);
1256 snd_soc_write(codec, WM8900_REG_ROUT1CTL,
1257 snd_soc_read(codec, WM8900_REG_ROUT1CTL) | 0x100);
1258 snd_soc_write(codec, WM8900_REG_LOUT2CTL,
1259 snd_soc_read(codec, WM8900_REG_LOUT2CTL) | 0x100);
1260 snd_soc_write(codec, WM8900_REG_ROUT2CTL,
1261 snd_soc_read(codec, WM8900_REG_ROUT2CTL) | 0x100);
1262 snd_soc_write(codec, WM8900_REG_LDAC_DV,
1263 snd_soc_read(codec, WM8900_REG_LDAC_DV) | 0x100);
1264 snd_soc_write(codec, WM8900_REG_RDAC_DV,
1265 snd_soc_read(codec, WM8900_REG_RDAC_DV) | 0x100);
1266 snd_soc_write(codec, WM8900_REG_LADC_DV,
1267 snd_soc_read(codec, WM8900_REG_LADC_DV) | 0x100);
1268 snd_soc_write(codec, WM8900_REG_RADC_DV,
1269 snd_soc_read(codec, WM8900_REG_RADC_DV) | 0x100);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001270
1271 /* Set the DAC and mixer output bias */
Mark Brown8d50e442009-07-10 23:12:01 +01001272 snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001273
Mark Brownf0752332008-12-09 12:51:56 +00001274 wm8900_dai.dev = &i2c->dev;
Mark Brown78e19a32008-12-10 15:38:36 +00001275
1276 wm8900_codec = codec;
1277
1278 ret = snd_soc_register_codec(codec);
1279 if (ret != 0) {
1280 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
1281 goto err;
1282 }
1283
1284 ret = snd_soc_register_dai(&wm8900_dai);
1285 if (ret != 0) {
1286 dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
1287 goto err_codec;
1288 }
1289
1290 return ret;
1291
1292err_codec:
1293 snd_soc_unregister_codec(codec);
1294err:
1295 kfree(wm8900);
1296 wm8900_codec = NULL;
1297 return ret;
Mark Brown0e0e16a2008-08-04 12:06:45 +01001298}
1299
Mark Brownc6f29812009-02-18 21:25:40 +00001300static __devexit int wm8900_i2c_remove(struct i2c_client *client)
Mark Brown0e0e16a2008-08-04 12:06:45 +01001301{
Mark Brownf0752332008-12-09 12:51:56 +00001302 snd_soc_unregister_dai(&wm8900_dai);
Mark Brown78e19a32008-12-10 15:38:36 +00001303 snd_soc_unregister_codec(wm8900_codec);
1304
1305 wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF);
1306
Mark Brownf0752332008-12-09 12:51:56 +00001307 wm8900_dai.dev = NULL;
Mark Brown78e19a32008-12-10 15:38:36 +00001308 kfree(wm8900_codec->private_data);
1309 wm8900_codec = NULL;
1310
Mark Brown0e0e16a2008-08-04 12:06:45 +01001311 return 0;
1312}
1313
Jean Delvare8ae6a552008-10-15 19:58:12 +02001314static const struct i2c_device_id wm8900_i2c_id[] = {
1315 { "wm8900", 0 },
1316 { }
1317};
1318MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001319
Mark Brown0e0e16a2008-08-04 12:06:45 +01001320static struct i2c_driver wm8900_i2c_driver = {
1321 .driver = {
Mark Brown78e19a32008-12-10 15:38:36 +00001322 .name = "WM8900",
Mark Brown0e0e16a2008-08-04 12:06:45 +01001323 .owner = THIS_MODULE,
1324 },
Jean Delvare8ae6a552008-10-15 19:58:12 +02001325 .probe = wm8900_i2c_probe,
Mark Brownc6f29812009-02-18 21:25:40 +00001326 .remove = __devexit_p(wm8900_i2c_remove),
Jean Delvare8ae6a552008-10-15 19:58:12 +02001327 .id_table = wm8900_i2c_id,
Mark Brown0e0e16a2008-08-04 12:06:45 +01001328};
1329
Mark Brown0e0e16a2008-08-04 12:06:45 +01001330static int wm8900_probe(struct platform_device *pdev)
1331{
1332 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001333 struct snd_soc_codec *codec;
1334 int ret = 0;
1335
Mark Brown78e19a32008-12-10 15:38:36 +00001336 if (!wm8900_codec) {
Mark Brownf0752332008-12-09 12:51:56 +00001337 dev_err(&pdev->dev, "I2C client not yet instantiated\n");
1338 return -ENODEV;
1339 }
Mark Brown0e0e16a2008-08-04 12:06:45 +01001340
Mark Brown78e19a32008-12-10 15:38:36 +00001341 codec = wm8900_codec;
Mark Brown6627a652009-01-23 22:55:23 +00001342 socdev->card->codec = codec;
Mark Brown0e0e16a2008-08-04 12:06:45 +01001343
Mark Brown78e19a32008-12-10 15:38:36 +00001344 /* Register pcms */
1345 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1346 if (ret < 0) {
1347 dev_err(&pdev->dev, "Failed to register new PCMs\n");
1348 goto pcm_err;
1349 }
Mark Brown0e0e16a2008-08-04 12:06:45 +01001350
Ian Molton3e8e1952009-01-09 00:23:21 +00001351 snd_soc_add_controls(codec, wm8900_snd_controls,
1352 ARRAY_SIZE(wm8900_snd_controls));
Mark Brown78e19a32008-12-10 15:38:36 +00001353 wm8900_add_widgets(codec);
Mark Brownf0752332008-12-09 12:51:56 +00001354
Mark Brown78e19a32008-12-10 15:38:36 +00001355pcm_err:
1356 return ret;
Mark Brown0e0e16a2008-08-04 12:06:45 +01001357}
1358
1359/* power down chip */
1360static int wm8900_remove(struct platform_device *pdev)
1361{
1362 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001363
1364 snd_soc_free_pcms(socdev);
1365 snd_soc_dapm_free(socdev);
Mark Brown0e0e16a2008-08-04 12:06:45 +01001366
1367 return 0;
1368}
1369
1370struct snd_soc_codec_device soc_codec_dev_wm8900 = {
1371 .probe = wm8900_probe,
1372 .remove = wm8900_remove,
1373 .suspend = wm8900_suspend,
1374 .resume = wm8900_resume,
1375};
1376EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900);
1377
Takashi Iwaic9b3a402008-12-10 07:47:22 +01001378static int __init wm8900_modinit(void)
Mark Brown64089b82008-12-08 19:17:58 +00001379{
Mark Brownf0752332008-12-09 12:51:56 +00001380 return i2c_add_driver(&wm8900_i2c_driver);
Mark Brown64089b82008-12-08 19:17:58 +00001381}
1382module_init(wm8900_modinit);
1383
1384static void __exit wm8900_exit(void)
1385{
Mark Brownf0752332008-12-09 12:51:56 +00001386 i2c_del_driver(&wm8900_i2c_driver);
Mark Brown64089b82008-12-08 19:17:58 +00001387}
1388module_exit(wm8900_exit);
1389
Mark Brown0e0e16a2008-08-04 12:06:45 +01001390MODULE_DESCRIPTION("ASoC WM8900 driver");
1391MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>");
1392MODULE_LICENSE("GPL");