• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/sound/soc/codecs/
1/*
2 * wm8750.c -- WM8750 ALSA SoC audio driver
3 *
4 * Copyright 2005 Openedhand Ltd.
5 *
6 * Author: Richard Purdie <richard@openedhand.com>
7 *
8 * Based on WM8753.c
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/platform_device.h>
22#include <linux/spi/spi.h>
23#include <linux/slab.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29#include <sound/initval.h>
30
31#include "wm8750.h"
32
33/*
34 * wm8750 register cache
35 * We can't read the WM8750 register space when we
36 * are using 2 wire for device control, so we cache them instead.
37 */
38static const u16 wm8750_reg[] = {
39	0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
40	0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
41	0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
42	0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
43	0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
44	0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
45	0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
46	0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
47	0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
48	0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
49	0x0079, 0x0079, 0x0079,          /* 40 */
50};
51
52/* codec private data */
53struct wm8750_priv {
54	unsigned int sysclk;
55	struct snd_soc_codec codec;
56	u16 reg_cache[ARRAY_SIZE(wm8750_reg)];
57};
58
59#define wm8750_reset(c)	snd_soc_write(c, WM8750_RESET, 0)
60
61/*
62 * WM8750 Controls
63 */
64static const char *wm8750_bass[] = {"Linear Control", "Adaptive Boost"};
65static const char *wm8750_bass_filter[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
66static const char *wm8750_treble[] = {"8kHz", "4kHz"};
67static const char *wm8750_3d_lc[] = {"200Hz", "500Hz"};
68static const char *wm8750_3d_uc[] = {"2.2kHz", "1.5kHz"};
69static const char *wm8750_3d_func[] = {"Capture", "Playback"};
70static const char *wm8750_alc_func[] = {"Off", "Right", "Left", "Stereo"};
71static const char *wm8750_ng_type[] = {"Constant PGA Gain",
72	"Mute ADC Output"};
73static const char *wm8750_line_mux[] = {"Line 1", "Line 2", "Line 3", "PGA",
74	"Differential"};
75static const char *wm8750_pga_sel[] = {"Line 1", "Line 2", "Line 3",
76	"Differential"};
77static const char *wm8750_out3[] = {"VREF", "ROUT1 + Vol", "MonoOut",
78	"ROUT1"};
79static const char *wm8750_diff_sel[] = {"Line 1", "Line 2"};
80static const char *wm8750_adcpol[] = {"Normal", "L Invert", "R Invert",
81	"L + R Invert"};
82static const char *wm8750_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
83static const char *wm8750_mono_mux[] = {"Stereo", "Mono (Left)",
84	"Mono (Right)", "Digital Mono"};
85
86static const struct soc_enum wm8750_enum[] = {
87SOC_ENUM_SINGLE(WM8750_BASS, 7, 2, wm8750_bass),
88SOC_ENUM_SINGLE(WM8750_BASS, 6, 2, wm8750_bass_filter),
89SOC_ENUM_SINGLE(WM8750_TREBLE, 6, 2, wm8750_treble),
90SOC_ENUM_SINGLE(WM8750_3D, 5, 2, wm8750_3d_lc),
91SOC_ENUM_SINGLE(WM8750_3D, 6, 2, wm8750_3d_uc),
92SOC_ENUM_SINGLE(WM8750_3D, 7, 2, wm8750_3d_func),
93SOC_ENUM_SINGLE(WM8750_ALC1, 7, 4, wm8750_alc_func),
94SOC_ENUM_SINGLE(WM8750_NGATE, 1, 2, wm8750_ng_type),
95SOC_ENUM_SINGLE(WM8750_LOUTM1, 0, 5, wm8750_line_mux),
96SOC_ENUM_SINGLE(WM8750_ROUTM1, 0, 5, wm8750_line_mux),
97SOC_ENUM_SINGLE(WM8750_LADCIN, 6, 4, wm8750_pga_sel), /* 10 */
98SOC_ENUM_SINGLE(WM8750_RADCIN, 6, 4, wm8750_pga_sel),
99SOC_ENUM_SINGLE(WM8750_ADCTL2, 7, 4, wm8750_out3),
100SOC_ENUM_SINGLE(WM8750_ADCIN, 8, 2, wm8750_diff_sel),
101SOC_ENUM_SINGLE(WM8750_ADCDAC, 5, 4, wm8750_adcpol),
102SOC_ENUM_SINGLE(WM8750_ADCDAC, 1, 4, wm8750_deemph),
103SOC_ENUM_SINGLE(WM8750_ADCIN, 6, 4, wm8750_mono_mux), /* 16 */
104
105};
106
107static const struct snd_kcontrol_new wm8750_snd_controls[] = {
108
109SOC_DOUBLE_R("Capture Volume", WM8750_LINVOL, WM8750_RINVOL, 0, 63, 0),
110SOC_DOUBLE_R("Capture ZC Switch", WM8750_LINVOL, WM8750_RINVOL, 6, 1, 0),
111SOC_DOUBLE_R("Capture Switch", WM8750_LINVOL, WM8750_RINVOL, 7, 1, 1),
112
113SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8750_LOUT1V,
114	WM8750_ROUT1V, 7, 1, 0),
115SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8750_LOUT2V,
116	WM8750_ROUT2V, 7, 1, 0),
117
118SOC_ENUM("Playback De-emphasis", wm8750_enum[15]),
119
120SOC_ENUM("Capture Polarity", wm8750_enum[14]),
121SOC_SINGLE("Playback 6dB Attenuate", WM8750_ADCDAC, 7, 1, 0),
122SOC_SINGLE("Capture 6dB Attenuate", WM8750_ADCDAC, 8, 1, 0),
123
124SOC_DOUBLE_R("PCM Volume", WM8750_LDAC, WM8750_RDAC, 0, 255, 0),
125
126SOC_ENUM("Bass Boost", wm8750_enum[0]),
127SOC_ENUM("Bass Filter", wm8750_enum[1]),
128SOC_SINGLE("Bass Volume", WM8750_BASS, 0, 15, 1),
129
130SOC_SINGLE("Treble Volume", WM8750_TREBLE, 0, 15, 1),
131SOC_ENUM("Treble Cut-off", wm8750_enum[2]),
132
133SOC_SINGLE("3D Switch", WM8750_3D, 0, 1, 0),
134SOC_SINGLE("3D Volume", WM8750_3D, 1, 15, 0),
135SOC_ENUM("3D Lower Cut-off", wm8750_enum[3]),
136SOC_ENUM("3D Upper Cut-off", wm8750_enum[4]),
137SOC_ENUM("3D Mode", wm8750_enum[5]),
138
139SOC_SINGLE("ALC Capture Target Volume", WM8750_ALC1, 0, 7, 0),
140SOC_SINGLE("ALC Capture Max Volume", WM8750_ALC1, 4, 7, 0),
141SOC_ENUM("ALC Capture Function", wm8750_enum[6]),
142SOC_SINGLE("ALC Capture ZC Switch", WM8750_ALC2, 7, 1, 0),
143SOC_SINGLE("ALC Capture Hold Time", WM8750_ALC2, 0, 15, 0),
144SOC_SINGLE("ALC Capture Decay Time", WM8750_ALC3, 4, 15, 0),
145SOC_SINGLE("ALC Capture Attack Time", WM8750_ALC3, 0, 15, 0),
146SOC_SINGLE("ALC Capture NG Threshold", WM8750_NGATE, 3, 31, 0),
147SOC_ENUM("ALC Capture NG Type", wm8750_enum[4]),
148SOC_SINGLE("ALC Capture NG Switch", WM8750_NGATE, 0, 1, 0),
149
150SOC_SINGLE("Left ADC Capture Volume", WM8750_LADC, 0, 255, 0),
151SOC_SINGLE("Right ADC Capture Volume", WM8750_RADC, 0, 255, 0),
152
153SOC_SINGLE("ZC Timeout Switch", WM8750_ADCTL1, 0, 1, 0),
154SOC_SINGLE("Playback Invert Switch", WM8750_ADCTL1, 1, 1, 0),
155
156SOC_SINGLE("Right Speaker Playback Invert Switch", WM8750_ADCTL2, 4, 1, 0),
157
158/* Unimplemented */
159/* ADCDAC Bit 0 - ADCHPD */
160/* ADCDAC Bit 4 - HPOR */
161/* ADCTL1 Bit 2,3 - DATSEL */
162/* ADCTL1 Bit 4,5 - DMONOMIX */
163/* ADCTL1 Bit 6,7 - VSEL */
164/* ADCTL2 Bit 2 - LRCM */
165/* ADCTL2 Bit 3 - TRI */
166/* ADCTL3 Bit 5 - HPFLREN */
167/* ADCTL3 Bit 6 - VROI */
168/* ADCTL3 Bit 7,8 - ADCLRM */
169/* ADCIN Bit 4 - LDCM */
170/* ADCIN Bit 5 - RDCM */
171
172SOC_DOUBLE_R("Mic Boost", WM8750_LADCIN, WM8750_RADCIN, 4, 3, 0),
173
174SOC_DOUBLE_R("Bypass Left Playback Volume", WM8750_LOUTM1,
175	WM8750_LOUTM2, 4, 7, 1),
176SOC_DOUBLE_R("Bypass Right Playback Volume", WM8750_ROUTM1,
177	WM8750_ROUTM2, 4, 7, 1),
178SOC_DOUBLE_R("Bypass Mono Playback Volume", WM8750_MOUTM1,
179	WM8750_MOUTM2, 4, 7, 1),
180
181SOC_SINGLE("Mono Playback ZC Switch", WM8750_MOUTV, 7, 1, 0),
182
183SOC_DOUBLE_R("Headphone Playback Volume", WM8750_LOUT1V, WM8750_ROUT1V,
184	0, 127, 0),
185SOC_DOUBLE_R("Speaker Playback Volume", WM8750_LOUT2V, WM8750_ROUT2V,
186	0, 127, 0),
187
188SOC_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0),
189
190};
191
192/*
193 * DAPM Controls
194 */
195
196/* Left Mixer */
197static const struct snd_kcontrol_new wm8750_left_mixer_controls[] = {
198SOC_DAPM_SINGLE("Playback Switch", WM8750_LOUTM1, 8, 1, 0),
199SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_LOUTM1, 7, 1, 0),
200SOC_DAPM_SINGLE("Right Playback Switch", WM8750_LOUTM2, 8, 1, 0),
201SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_LOUTM2, 7, 1, 0),
202};
203
204/* Right Mixer */
205static const struct snd_kcontrol_new wm8750_right_mixer_controls[] = {
206SOC_DAPM_SINGLE("Left Playback Switch", WM8750_ROUTM1, 8, 1, 0),
207SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_ROUTM1, 7, 1, 0),
208SOC_DAPM_SINGLE("Playback Switch", WM8750_ROUTM2, 8, 1, 0),
209SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_ROUTM2, 7, 1, 0),
210};
211
212/* Mono Mixer */
213static const struct snd_kcontrol_new wm8750_mono_mixer_controls[] = {
214SOC_DAPM_SINGLE("Left Playback Switch", WM8750_MOUTM1, 8, 1, 0),
215SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_MOUTM1, 7, 1, 0),
216SOC_DAPM_SINGLE("Right Playback Switch", WM8750_MOUTM2, 8, 1, 0),
217SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_MOUTM2, 7, 1, 0),
218};
219
220/* Left Line Mux */
221static const struct snd_kcontrol_new wm8750_left_line_controls =
222SOC_DAPM_ENUM("Route", wm8750_enum[8]);
223
224/* Right Line Mux */
225static const struct snd_kcontrol_new wm8750_right_line_controls =
226SOC_DAPM_ENUM("Route", wm8750_enum[9]);
227
228/* Left PGA Mux */
229static const struct snd_kcontrol_new wm8750_left_pga_controls =
230SOC_DAPM_ENUM("Route", wm8750_enum[10]);
231
232/* Right PGA Mux */
233static const struct snd_kcontrol_new wm8750_right_pga_controls =
234SOC_DAPM_ENUM("Route", wm8750_enum[11]);
235
236/* Out 3 Mux */
237static const struct snd_kcontrol_new wm8750_out3_controls =
238SOC_DAPM_ENUM("Route", wm8750_enum[12]);
239
240/* Differential Mux */
241static const struct snd_kcontrol_new wm8750_diffmux_controls =
242SOC_DAPM_ENUM("Route", wm8750_enum[13]);
243
244/* Mono ADC Mux */
245static const struct snd_kcontrol_new wm8750_monomux_controls =
246SOC_DAPM_ENUM("Route", wm8750_enum[16]);
247
248static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
249	SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
250		&wm8750_left_mixer_controls[0],
251		ARRAY_SIZE(wm8750_left_mixer_controls)),
252	SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
253		&wm8750_right_mixer_controls[0],
254		ARRAY_SIZE(wm8750_right_mixer_controls)),
255	SND_SOC_DAPM_MIXER("Mono Mixer", WM8750_PWR2, 2, 0,
256		&wm8750_mono_mixer_controls[0],
257		ARRAY_SIZE(wm8750_mono_mixer_controls)),
258
259	SND_SOC_DAPM_PGA("Right Out 2", WM8750_PWR2, 3, 0, NULL, 0),
260	SND_SOC_DAPM_PGA("Left Out 2", WM8750_PWR2, 4, 0, NULL, 0),
261	SND_SOC_DAPM_PGA("Right Out 1", WM8750_PWR2, 5, 0, NULL, 0),
262	SND_SOC_DAPM_PGA("Left Out 1", WM8750_PWR2, 6, 0, NULL, 0),
263	SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8750_PWR2, 7, 0),
264	SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8750_PWR2, 8, 0),
265
266	SND_SOC_DAPM_MICBIAS("Mic Bias", WM8750_PWR1, 1, 0),
267	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8750_PWR1, 2, 0),
268	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8750_PWR1, 3, 0),
269
270	SND_SOC_DAPM_MUX("Left PGA Mux", WM8750_PWR1, 5, 0,
271		&wm8750_left_pga_controls),
272	SND_SOC_DAPM_MUX("Right PGA Mux", WM8750_PWR1, 4, 0,
273		&wm8750_right_pga_controls),
274	SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
275		&wm8750_left_line_controls),
276	SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
277		&wm8750_right_line_controls),
278
279	SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &wm8750_out3_controls),
280	SND_SOC_DAPM_PGA("Out 3", WM8750_PWR2, 1, 0, NULL, 0),
281	SND_SOC_DAPM_PGA("Mono Out 1", WM8750_PWR2, 2, 0, NULL, 0),
282
283	SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
284		&wm8750_diffmux_controls),
285	SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
286		&wm8750_monomux_controls),
287	SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
288		&wm8750_monomux_controls),
289
290	SND_SOC_DAPM_OUTPUT("LOUT1"),
291	SND_SOC_DAPM_OUTPUT("ROUT1"),
292	SND_SOC_DAPM_OUTPUT("LOUT2"),
293	SND_SOC_DAPM_OUTPUT("ROUT2"),
294	SND_SOC_DAPM_OUTPUT("MONO1"),
295	SND_SOC_DAPM_OUTPUT("OUT3"),
296	SND_SOC_DAPM_OUTPUT("VREF"),
297
298	SND_SOC_DAPM_INPUT("LINPUT1"),
299	SND_SOC_DAPM_INPUT("LINPUT2"),
300	SND_SOC_DAPM_INPUT("LINPUT3"),
301	SND_SOC_DAPM_INPUT("RINPUT1"),
302	SND_SOC_DAPM_INPUT("RINPUT2"),
303	SND_SOC_DAPM_INPUT("RINPUT3"),
304};
305
306static const struct snd_soc_dapm_route audio_map[] = {
307	/* left mixer */
308	{"Left Mixer", "Playback Switch", "Left DAC"},
309	{"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
310	{"Left Mixer", "Right Playback Switch", "Right DAC"},
311	{"Left Mixer", "Right Bypass Switch", "Right Line Mux"},
312
313	/* right mixer */
314	{"Right Mixer", "Left Playback Switch", "Left DAC"},
315	{"Right Mixer", "Left Bypass Switch", "Left Line Mux"},
316	{"Right Mixer", "Playback Switch", "Right DAC"},
317	{"Right Mixer", "Right Bypass Switch", "Right Line Mux"},
318
319	/* left out 1 */
320	{"Left Out 1", NULL, "Left Mixer"},
321	{"LOUT1", NULL, "Left Out 1"},
322
323	/* left out 2 */
324	{"Left Out 2", NULL, "Left Mixer"},
325	{"LOUT2", NULL, "Left Out 2"},
326
327	/* right out 1 */
328	{"Right Out 1", NULL, "Right Mixer"},
329	{"ROUT1", NULL, "Right Out 1"},
330
331	/* right out 2 */
332	{"Right Out 2", NULL, "Right Mixer"},
333	{"ROUT2", NULL, "Right Out 2"},
334
335	/* mono mixer */
336	{"Mono Mixer", "Left Playback Switch", "Left DAC"},
337	{"Mono Mixer", "Left Bypass Switch", "Left Line Mux"},
338	{"Mono Mixer", "Right Playback Switch", "Right DAC"},
339	{"Mono Mixer", "Right Bypass Switch", "Right Line Mux"},
340
341	/* mono out */
342	{"Mono Out 1", NULL, "Mono Mixer"},
343	{"MONO1", NULL, "Mono Out 1"},
344
345	/* out 3 */
346	{"Out3 Mux", "VREF", "VREF"},
347	{"Out3 Mux", "ROUT1 + Vol", "ROUT1"},
348	{"Out3 Mux", "ROUT1", "Right Mixer"},
349	{"Out3 Mux", "MonoOut", "MONO1"},
350	{"Out 3", NULL, "Out3 Mux"},
351	{"OUT3", NULL, "Out 3"},
352
353	/* Left Line Mux */
354	{"Left Line Mux", "Line 1", "LINPUT1"},
355	{"Left Line Mux", "Line 2", "LINPUT2"},
356	{"Left Line Mux", "Line 3", "LINPUT3"},
357	{"Left Line Mux", "PGA", "Left PGA Mux"},
358	{"Left Line Mux", "Differential", "Differential Mux"},
359
360	/* Right Line Mux */
361	{"Right Line Mux", "Line 1", "RINPUT1"},
362	{"Right Line Mux", "Line 2", "RINPUT2"},
363	{"Right Line Mux", "Line 3", "RINPUT3"},
364	{"Right Line Mux", "PGA", "Right PGA Mux"},
365	{"Right Line Mux", "Differential", "Differential Mux"},
366
367	/* Left PGA Mux */
368	{"Left PGA Mux", "Line 1", "LINPUT1"},
369	{"Left PGA Mux", "Line 2", "LINPUT2"},
370	{"Left PGA Mux", "Line 3", "LINPUT3"},
371	{"Left PGA Mux", "Differential", "Differential Mux"},
372
373	/* Right PGA Mux */
374	{"Right PGA Mux", "Line 1", "RINPUT1"},
375	{"Right PGA Mux", "Line 2", "RINPUT2"},
376	{"Right PGA Mux", "Line 3", "RINPUT3"},
377	{"Right PGA Mux", "Differential", "Differential Mux"},
378
379	/* Differential Mux */
380	{"Differential Mux", "Line 1", "LINPUT1"},
381	{"Differential Mux", "Line 1", "RINPUT1"},
382	{"Differential Mux", "Line 2", "LINPUT2"},
383	{"Differential Mux", "Line 2", "RINPUT2"},
384
385	/* Left ADC Mux */
386	{"Left ADC Mux", "Stereo", "Left PGA Mux"},
387	{"Left ADC Mux", "Mono (Left)", "Left PGA Mux"},
388	{"Left ADC Mux", "Digital Mono", "Left PGA Mux"},
389
390	/* Right ADC Mux */
391	{"Right ADC Mux", "Stereo", "Right PGA Mux"},
392	{"Right ADC Mux", "Mono (Right)", "Right PGA Mux"},
393	{"Right ADC Mux", "Digital Mono", "Right PGA Mux"},
394
395	/* ADC */
396	{"Left ADC", NULL, "Left ADC Mux"},
397	{"Right ADC", NULL, "Right ADC Mux"},
398};
399
400static int wm8750_add_widgets(struct snd_soc_codec *codec)
401{
402	snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
403				  ARRAY_SIZE(wm8750_dapm_widgets));
404
405	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
406
407	return 0;
408}
409
410struct _coeff_div {
411	u32 mclk;
412	u32 rate;
413	u16 fs;
414	u8 sr:5;
415	u8 usb:1;
416};
417
418/* codec hifi mclk clock divider coefficients */
419static const struct _coeff_div coeff_div[] = {
420	/* 8k */
421	{12288000, 8000, 1536, 0x6, 0x0},
422	{11289600, 8000, 1408, 0x16, 0x0},
423	{18432000, 8000, 2304, 0x7, 0x0},
424	{16934400, 8000, 2112, 0x17, 0x0},
425	{12000000, 8000, 1500, 0x6, 0x1},
426
427	/* 11.025k */
428	{11289600, 11025, 1024, 0x18, 0x0},
429	{16934400, 11025, 1536, 0x19, 0x0},
430	{12000000, 11025, 1088, 0x19, 0x1},
431
432	/* 16k */
433	{12288000, 16000, 768, 0xa, 0x0},
434	{18432000, 16000, 1152, 0xb, 0x0},
435	{12000000, 16000, 750, 0xa, 0x1},
436
437	/* 22.05k */
438	{11289600, 22050, 512, 0x1a, 0x0},
439	{16934400, 22050, 768, 0x1b, 0x0},
440	{12000000, 22050, 544, 0x1b, 0x1},
441
442	/* 32k */
443	{12288000, 32000, 384, 0xc, 0x0},
444	{18432000, 32000, 576, 0xd, 0x0},
445	{12000000, 32000, 375, 0xa, 0x1},
446
447	/* 44.1k */
448	{11289600, 44100, 256, 0x10, 0x0},
449	{16934400, 44100, 384, 0x11, 0x0},
450	{12000000, 44100, 272, 0x11, 0x1},
451
452	/* 48k */
453	{12288000, 48000, 256, 0x0, 0x0},
454	{18432000, 48000, 384, 0x1, 0x0},
455	{12000000, 48000, 250, 0x0, 0x1},
456
457	/* 88.2k */
458	{11289600, 88200, 128, 0x1e, 0x0},
459	{16934400, 88200, 192, 0x1f, 0x0},
460	{12000000, 88200, 136, 0x1f, 0x1},
461
462	/* 96k */
463	{12288000, 96000, 128, 0xe, 0x0},
464	{18432000, 96000, 192, 0xf, 0x0},
465	{12000000, 96000, 125, 0xe, 0x1},
466};
467
468static inline int get_coeff(int mclk, int rate)
469{
470	int i;
471
472	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
473		if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
474			return i;
475	}
476
477	printk(KERN_ERR "wm8750: could not get coeff for mclk %d @ rate %d\n",
478		mclk, rate);
479	return -EINVAL;
480}
481
482static int wm8750_set_dai_sysclk(struct snd_soc_dai *codec_dai,
483		int clk_id, unsigned int freq, int dir)
484{
485	struct snd_soc_codec *codec = codec_dai->codec;
486	struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
487
488	switch (freq) {
489	case 11289600:
490	case 12000000:
491	case 12288000:
492	case 16934400:
493	case 18432000:
494		wm8750->sysclk = freq;
495		return 0;
496	}
497	return -EINVAL;
498}
499
500static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
501		unsigned int fmt)
502{
503	struct snd_soc_codec *codec = codec_dai->codec;
504	u16 iface = 0;
505
506	/* set master/slave audio interface */
507	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
508	case SND_SOC_DAIFMT_CBM_CFM:
509		iface = 0x0040;
510		break;
511	case SND_SOC_DAIFMT_CBS_CFS:
512		break;
513	default:
514		return -EINVAL;
515	}
516
517	/* interface format */
518	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
519	case SND_SOC_DAIFMT_I2S:
520		iface |= 0x0002;
521		break;
522	case SND_SOC_DAIFMT_RIGHT_J:
523		break;
524	case SND_SOC_DAIFMT_LEFT_J:
525		iface |= 0x0001;
526		break;
527	case SND_SOC_DAIFMT_DSP_A:
528		iface |= 0x0003;
529		break;
530	case SND_SOC_DAIFMT_DSP_B:
531		iface |= 0x0013;
532		break;
533	default:
534		return -EINVAL;
535	}
536
537	/* clock inversion */
538	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
539	case SND_SOC_DAIFMT_NB_NF:
540		break;
541	case SND_SOC_DAIFMT_IB_IF:
542		iface |= 0x0090;
543		break;
544	case SND_SOC_DAIFMT_IB_NF:
545		iface |= 0x0080;
546		break;
547	case SND_SOC_DAIFMT_NB_IF:
548		iface |= 0x0010;
549		break;
550	default:
551		return -EINVAL;
552	}
553
554	snd_soc_write(codec, WM8750_IFACE, iface);
555	return 0;
556}
557
558static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
559				struct snd_pcm_hw_params *params,
560				struct snd_soc_dai *dai)
561{
562	struct snd_soc_pcm_runtime *rtd = substream->private_data;
563	struct snd_soc_device *socdev = rtd->socdev;
564	struct snd_soc_codec *codec = socdev->card->codec;
565	struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
566	u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
567	u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
568	int coeff = get_coeff(wm8750->sysclk, params_rate(params));
569
570	/* bit size */
571	switch (params_format(params)) {
572	case SNDRV_PCM_FORMAT_S16_LE:
573		break;
574	case SNDRV_PCM_FORMAT_S20_3LE:
575		iface |= 0x0004;
576		break;
577	case SNDRV_PCM_FORMAT_S24_LE:
578		iface |= 0x0008;
579		break;
580	case SNDRV_PCM_FORMAT_S32_LE:
581		iface |= 0x000c;
582		break;
583	}
584
585	/* set iface & srate */
586	snd_soc_write(codec, WM8750_IFACE, iface);
587	if (coeff >= 0)
588		snd_soc_write(codec, WM8750_SRATE, srate |
589			(coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
590
591	return 0;
592}
593
594static int wm8750_mute(struct snd_soc_dai *dai, int mute)
595{
596	struct snd_soc_codec *codec = dai->codec;
597	u16 mute_reg = snd_soc_read(codec, WM8750_ADCDAC) & 0xfff7;
598
599	if (mute)
600		snd_soc_write(codec, WM8750_ADCDAC, mute_reg | 0x8);
601	else
602		snd_soc_write(codec, WM8750_ADCDAC, mute_reg);
603	return 0;
604}
605
606static int wm8750_set_bias_level(struct snd_soc_codec *codec,
607				 enum snd_soc_bias_level level)
608{
609	u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e;
610
611	switch (level) {
612	case SND_SOC_BIAS_ON:
613		/* set vmid to 50k and unmute dac */
614		snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
615		break;
616	case SND_SOC_BIAS_PREPARE:
617		break;
618	case SND_SOC_BIAS_STANDBY:
619		if (codec->bias_level == SND_SOC_BIAS_OFF) {
620			/* Set VMID to 5k */
621			snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
622
623			/* ...and ramp */
624			msleep(1000);
625		}
626
627		/* mute dac and set vmid to 500k, enable VREF */
628		snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
629		break;
630	case SND_SOC_BIAS_OFF:
631		snd_soc_write(codec, WM8750_PWR1, 0x0001);
632		break;
633	}
634	codec->bias_level = level;
635	return 0;
636}
637
638#define WM8750_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
639	SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
640	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
641
642#define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
643	SNDRV_PCM_FMTBIT_S24_LE)
644
645static struct snd_soc_dai_ops wm8750_dai_ops = {
646	.hw_params	= wm8750_pcm_hw_params,
647	.digital_mute	= wm8750_mute,
648	.set_fmt	= wm8750_set_dai_fmt,
649	.set_sysclk	= wm8750_set_dai_sysclk,
650};
651
652struct snd_soc_dai wm8750_dai = {
653	.name = "WM8750",
654	.playback = {
655		.stream_name = "Playback",
656		.channels_min = 1,
657		.channels_max = 2,
658		.rates = WM8750_RATES,
659		.formats = WM8750_FORMATS,},
660	.capture = {
661		.stream_name = "Capture",
662		.channels_min = 1,
663		.channels_max = 2,
664		.rates = WM8750_RATES,
665		.formats = WM8750_FORMATS,},
666	.ops = &wm8750_dai_ops,
667};
668EXPORT_SYMBOL_GPL(wm8750_dai);
669
670static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
671{
672	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
673	struct snd_soc_codec *codec = socdev->card->codec;
674
675	wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
676	return 0;
677}
678
679static int wm8750_resume(struct platform_device *pdev)
680{
681	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
682	struct snd_soc_codec *codec = socdev->card->codec;
683	int i;
684	u8 data[2];
685	u16 *cache = codec->reg_cache;
686
687	/* Sync reg_cache with the hardware */
688	for (i = 0; i < ARRAY_SIZE(wm8750_reg); i++) {
689		if (i == WM8750_RESET)
690			continue;
691		data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
692		data[1] = cache[i] & 0x00ff;
693		codec->hw_write(codec->control_data, data, 2);
694	}
695
696	wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
697
698	return 0;
699}
700
701static struct snd_soc_codec *wm8750_codec;
702
703static int wm8750_probe(struct platform_device *pdev)
704{
705	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
706	struct snd_soc_codec *codec;
707	int ret = 0;
708
709	if (!wm8750_codec) {
710		dev_err(&pdev->dev, "WM8750 codec not yet registered\n");
711		return -EINVAL;
712	}
713
714	socdev->card->codec = wm8750_codec;
715	codec = wm8750_codec;
716
717	/* register pcms */
718	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
719	if (ret < 0) {
720		printk(KERN_ERR "wm8750: failed to create pcms\n");
721		goto err;
722	}
723
724	snd_soc_add_controls(codec, wm8750_snd_controls,
725				ARRAY_SIZE(wm8750_snd_controls));
726	wm8750_add_widgets(codec);
727
728	return 0;
729
730err:
731	return ret;
732}
733
734/* power down chip */
735static int wm8750_remove(struct platform_device *pdev)
736{
737	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
738
739	snd_soc_free_pcms(socdev);
740	snd_soc_dapm_free(socdev);
741
742	return 0;
743}
744
745struct snd_soc_codec_device soc_codec_dev_wm8750 = {
746	.probe		= wm8750_probe,
747	.remove		= wm8750_remove,
748	.suspend	= wm8750_suspend,
749	.resume		= wm8750_resume,
750};
751EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
752
753/*
754 * initialise the WM8750 driver
755 * register the mixer and dsp interfaces with the kernel
756 */
757static int wm8750_register(struct wm8750_priv *wm8750,
758			enum snd_soc_control_type control)
759{
760	struct snd_soc_codec *codec = &wm8750->codec;
761	int reg, ret = 0;
762
763	if (wm8750_codec) {
764		dev_err(codec->dev, "Multiple WM8750 devices not supported\n");
765		ret = -EINVAL;
766		goto err;
767	}
768
769	mutex_init(&codec->mutex);
770	INIT_LIST_HEAD(&codec->dapm_widgets);
771	INIT_LIST_HEAD(&codec->dapm_paths);
772
773	codec->name = "WM8750";
774	codec->owner = THIS_MODULE;
775	codec->bias_level = SND_SOC_BIAS_STANDBY;
776	codec->set_bias_level = wm8750_set_bias_level;
777	codec->dai = &wm8750_dai;
778	codec->num_dai = 1;
779	codec->reg_cache_size = ARRAY_SIZE(wm8750->reg_cache) + 1;
780	codec->reg_cache = &wm8750->reg_cache;
781	snd_soc_codec_set_drvdata(codec, wm8750);
782
783	memcpy(codec->reg_cache, wm8750_reg, sizeof(wm8750->reg_cache));
784
785	ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
786	if (ret < 0) {
787		printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
788		goto err;
789	}
790
791	ret = wm8750_reset(codec);
792	if (ret < 0) {
793		printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
794		goto err;
795	}
796
797	/* charge output caps */
798	wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
799
800	/* set the update bits */
801	reg = snd_soc_read(codec, WM8750_LDAC);
802	snd_soc_write(codec, WM8750_LDAC, reg | 0x0100);
803	reg = snd_soc_read(codec, WM8750_RDAC);
804	snd_soc_write(codec, WM8750_RDAC, reg | 0x0100);
805	reg = snd_soc_read(codec, WM8750_LOUT1V);
806	snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100);
807	reg = snd_soc_read(codec, WM8750_ROUT1V);
808	snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100);
809	reg = snd_soc_read(codec, WM8750_LOUT2V);
810	snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100);
811	reg = snd_soc_read(codec, WM8750_ROUT2V);
812	snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100);
813	reg = snd_soc_read(codec, WM8750_LINVOL);
814	snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100);
815	reg = snd_soc_read(codec, WM8750_RINVOL);
816	snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
817
818	wm8750_codec = codec;
819
820	ret = snd_soc_register_codec(codec);
821	if (ret != 0) {
822		dev_err(codec->dev, "Failed to register codec: %d\n", ret);
823		goto err;
824	}
825
826	ret = snd_soc_register_dais(&wm8750_dai, 1);
827	if (ret != 0) {
828		dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
829		goto err_codec;
830	}
831
832	return 0;
833
834err_codec:
835	snd_soc_unregister_codec(codec);
836err:
837	kfree(wm8750);
838	return ret;
839}
840
841static void wm8750_unregister(struct wm8750_priv *wm8750)
842{
843	wm8750_set_bias_level(&wm8750->codec, SND_SOC_BIAS_OFF);
844	snd_soc_unregister_dais(&wm8750_dai, 1);
845	snd_soc_unregister_codec(&wm8750->codec);
846	kfree(wm8750);
847	wm8750_codec = NULL;
848}
849
850#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
851
852/*
853 * WM8750 2 wire address is determined by GPIO5
854 * state during powerup.
855 *    low  = 0x1a
856 *    high = 0x1b
857 */
858
859static int wm8750_i2c_probe(struct i2c_client *i2c,
860			    const struct i2c_device_id *id)
861{
862	struct snd_soc_codec *codec;
863	struct wm8750_priv *wm8750;
864
865	wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
866	if (wm8750 == NULL)
867		return -ENOMEM;
868
869	codec = &wm8750->codec;
870	codec->control_data = i2c;
871	i2c_set_clientdata(i2c, wm8750);
872
873	codec->dev = &i2c->dev;
874
875	return wm8750_register(wm8750, SND_SOC_I2C);
876}
877
878static int wm8750_i2c_remove(struct i2c_client *client)
879{
880	struct wm8750_priv *wm8750 = i2c_get_clientdata(client);
881	wm8750_unregister(wm8750);
882	return 0;
883}
884
885static const struct i2c_device_id wm8750_i2c_id[] = {
886	{ "wm8750", 0 },
887	{ "wm8987", 0 }, /* WM8987 is register compatible with WM8750 */
888	{ }
889};
890MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
891
892static struct i2c_driver wm8750_i2c_driver = {
893	.driver = {
894		.name = "WM8750 I2C Codec",
895		.owner = THIS_MODULE,
896	},
897	.probe =    wm8750_i2c_probe,
898	.remove =   wm8750_i2c_remove,
899	.id_table = wm8750_i2c_id,
900};
901#endif
902
903#if defined(CONFIG_SPI_MASTER)
904static int __devinit wm8750_spi_probe(struct spi_device *spi)
905{
906	struct snd_soc_codec *codec;
907	struct wm8750_priv *wm8750;
908
909	wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
910	if (wm8750 == NULL)
911		return -ENOMEM;
912
913	codec = &wm8750->codec;
914	codec->control_data = spi;
915	codec->dev = &spi->dev;
916
917	dev_set_drvdata(&spi->dev, wm8750);
918
919	return wm8750_register(wm8750, SND_SOC_SPI);
920}
921
922static int __devexit wm8750_spi_remove(struct spi_device *spi)
923{
924	struct wm8750_priv *wm8750 = dev_get_drvdata(&spi->dev);
925	wm8750_unregister(wm8750);
926	return 0;
927}
928
929static const struct spi_device_id wm8750_spi_id[] = {
930	{ "wm8750", 0 },
931	{ "wm8987", 0 },
932	{ }
933};
934MODULE_DEVICE_TABLE(spi, wm8750_spi_id);
935
936static struct spi_driver wm8750_spi_driver = {
937	.driver = {
938		.name	= "WM8750 SPI Codec",
939		.bus	= &spi_bus_type,
940		.owner	= THIS_MODULE,
941	},
942	.probe		= wm8750_spi_probe,
943	.remove		= __devexit_p(wm8750_spi_remove),
944	.id_table	= wm8750_spi_id,
945};
946#endif
947
948static int __init wm8750_modinit(void)
949{
950	int ret;
951#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
952	ret = i2c_add_driver(&wm8750_i2c_driver);
953	if (ret != 0)
954		pr_err("Failed to register WM8750 I2C driver: %d\n", ret);
955#endif
956#if defined(CONFIG_SPI_MASTER)
957	ret = spi_register_driver(&wm8750_spi_driver);
958	if (ret != 0)
959		pr_err("Failed to register WM8750 SPI driver: %d\n", ret);
960#endif
961	return 0;
962}
963module_init(wm8750_modinit);
964
965static void __exit wm8750_exit(void)
966{
967#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
968	i2c_del_driver(&wm8750_i2c_driver);
969#endif
970#if defined(CONFIG_SPI_MASTER)
971	spi_unregister_driver(&wm8750_spi_driver);
972#endif
973}
974module_exit(wm8750_exit);
975
976MODULE_DESCRIPTION("ASoC WM8750 driver");
977MODULE_AUTHOR("Liam Girdwood");
978MODULE_LICENSE("GPL");
979