blob: 00b481183d456f154fceeb23f6b94286fc67a032 [file] [log] [blame]
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001/*
2 * wm8753.c -- WM8753 ALSA Soc Audio driver
3 *
4 * Copyright 2003 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Notes:
14 * The WM8753 is a low power, high quality stereo codec with integrated PCM
15 * codec designed for portable digital telephony applications.
16 *
17 * Dual DAI:-
18 *
19 * This driver support 2 DAI PCM's. This makes the default PCM available for
20 * HiFi audio (e.g. MP3, ogg) playback/capture and the other PCM available for
21 * voice.
22 *
23 * Please note that the voice PCM can be connected directly to a Bluetooth
24 * codec or GSM modem and thus cannot be read or written to, although it is
25 * available to be configured with snd_hw_params(), etc and kcontrols in the
26 * normal alsa manner.
27 *
28 * Fast DAI switching:-
29 *
30 * The driver can now fast switch between the DAI configurations via a
31 * an alsa kcontrol. This allows the PCM to remain open.
32 *
33 */
34
35#include <linux/module.h>
36#include <linux/moduleparam.h>
37#include <linux/version.h>
38#include <linux/kernel.h>
39#include <linux/init.h>
40#include <linux/delay.h>
41#include <linux/pm.h>
42#include <linux/i2c.h>
43#include <linux/platform_device.h>
Liam Girdwood1f53aee2007-04-16 19:17:44 +020044#include <sound/core.h>
45#include <sound/pcm.h>
46#include <sound/pcm_params.h>
47#include <sound/soc.h>
48#include <sound/soc-dapm.h>
49#include <sound/initval.h>
Liam Girdwood2d6a4ac2008-01-10 14:43:48 +010050#include <sound/tlv.h>
Liam Girdwood1f53aee2007-04-16 19:17:44 +020051#include <asm/div64.h>
52
53#include "wm8753.h"
54
55#define AUDIO_NAME "wm8753"
56#define WM8753_VERSION "0.16"
57
58/*
59 * Debug
60 */
61
62#define WM8753_DEBUG 0
63
64#ifdef WM8753_DEBUG
65#define dbg(format, arg...) \
66 printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
67#else
68#define dbg(format, arg...) do {} while (0)
69#endif
70#define err(format, arg...) \
71 printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
72#define info(format, arg...) \
73 printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
74#define warn(format, arg...) \
75 printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
76
77static int caps_charge = 2000;
78module_param(caps_charge, int, 0);
79MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
80
81static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
82 unsigned int mode);
83
84/* codec private data */
85struct wm8753_priv {
86 unsigned int sysclk;
87 unsigned int pcmclk;
88};
89
90/*
91 * wm8753 register cache
92 * We can't read the WM8753 register space when we
93 * are using 2 wire for device control, so we cache them instead.
94 */
95static const u16 wm8753_reg[] = {
96 0x0008, 0x0000, 0x000a, 0x000a,
97 0x0033, 0x0000, 0x0007, 0x00ff,
98 0x00ff, 0x000f, 0x000f, 0x007b,
99 0x0000, 0x0032, 0x0000, 0x00c3,
100 0x00c3, 0x00c0, 0x0000, 0x0000,
101 0x0000, 0x0000, 0x0000, 0x0000,
102 0x0000, 0x0000, 0x0000, 0x0000,
103 0x0000, 0x0000, 0x0000, 0x0055,
104 0x0005, 0x0050, 0x0055, 0x0050,
105 0x0055, 0x0050, 0x0055, 0x0079,
106 0x0079, 0x0079, 0x0079, 0x0079,
107 0x0000, 0x0000, 0x0000, 0x0000,
108 0x0097, 0x0097, 0x0000, 0x0004,
109 0x0000, 0x0083, 0x0024, 0x01ba,
110 0x0000, 0x0083, 0x0024, 0x01ba,
111 0x0000, 0x0000
112};
113
114/*
115 * read wm8753 register cache
116 */
117static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec,
118 unsigned int reg)
119{
120 u16 *cache = codec->reg_cache;
121 if (reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1))
122 return -1;
123 return cache[reg - 1];
124}
125
126/*
127 * write wm8753 register cache
128 */
129static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec,
130 unsigned int reg, unsigned int value)
131{
132 u16 *cache = codec->reg_cache;
133 if (reg < 1 || reg > 0x3f)
134 return;
135 cache[reg - 1] = value;
136}
137
138/*
139 * write to the WM8753 register space
140 */
141static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg,
142 unsigned int value)
143{
144 u8 data[2];
145
146 /* data is
147 * D15..D9 WM8753 register offset
148 * D8...D0 register data
149 */
150 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
151 data[1] = value & 0x00ff;
152
Mark Brown60fc6842008-04-30 17:18:43 +0200153 wm8753_write_reg_cache(codec, reg, value);
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200154 if (codec->hw_write(codec->control_data, data, 2) == 2)
155 return 0;
156 else
157 return -EIO;
158}
159
160#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0)
161
162/*
163 * WM8753 Controls
164 */
165static const char *wm8753_base[] = {"Linear Control", "Adaptive Boost"};
166static const char *wm8753_base_filter[] =
167 {"130Hz @ 48kHz", "200Hz @ 48kHz", "100Hz @ 16kHz", "400Hz @ 48kHz",
168 "100Hz @ 8kHz", "200Hz @ 8kHz"};
169static const char *wm8753_treble[] = {"8kHz", "4kHz"};
170static const char *wm8753_alc_func[] = {"Off", "Right", "Left", "Stereo"};
171static const char *wm8753_ng_type[] = {"Constant PGA Gain", "Mute ADC Output"};
172static const char *wm8753_3d_func[] = {"Capture", "Playback"};
173static const char *wm8753_3d_uc[] = {"2.2kHz", "1.5kHz"};
174static const char *wm8753_3d_lc[] = {"200Hz", "500Hz"};
175static const char *wm8753_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz"};
176static const char *wm8753_mono_mix[] = {"Stereo", "Left", "Right", "Mono"};
177static const char *wm8753_dac_phase[] = {"Non Inverted", "Inverted"};
178static const char *wm8753_line_mix[] = {"Line 1 + 2", "Line 1 - 2",
179 "Line 1", "Line 2"};
180static const char *wm8753_mono_mux[] = {"Line Mix", "Rx Mix"};
181static const char *wm8753_right_mux[] = {"Line 2", "Rx Mix"};
182static const char *wm8753_left_mux[] = {"Line 1", "Rx Mix"};
183static const char *wm8753_rxmsel[] = {"RXP - RXN", "RXP + RXN", "RXP", "RXN"};
184static const char *wm8753_sidetone_mux[] = {"Left PGA", "Mic 1", "Mic 2",
185 "Right PGA"};
186static const char *wm8753_mono2_src[] = {"Inverted Mono 1", "Left", "Right",
187 "Left + Right"};
188static const char *wm8753_out3[] = {"VREF", "ROUT2", "Left + Right"};
189static const char *wm8753_out4[] = {"VREF", "Capture ST", "LOUT2"};
190static const char *wm8753_radcsel[] = {"PGA", "Line or RXP-RXN", "Sidetone"};
191static const char *wm8753_ladcsel[] = {"PGA", "Line or RXP-RXN", "Line"};
192static const char *wm8753_mono_adc[] = {"Stereo", "Analogue Mix Left",
193 "Analogue Mix Right", "Digital Mono Mix"};
194static const char *wm8753_adc_hp[] = {"3.4Hz @ 48kHz", "82Hz @ 16k",
195 "82Hz @ 8kHz", "170Hz @ 8kHz"};
196static const char *wm8753_adc_filter[] = {"HiFi", "Voice"};
197static const char *wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"};
198static const char *wm8753_dai_mode[] = {"DAI 0", "DAI 1", "DAI 2", "DAI 3"};
199static const char *wm8753_dat_sel[] = {"Stereo", "Left ADC", "Right ADC",
200 "Channel Swap"};
Graeme Gregoryae092c92008-03-03 17:19:45 +0100201static const char *wm8753_rout2_phase[] = {"Non Inverted", "Inverted"};
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200202
203static const struct soc_enum wm8753_enum[] = {
204SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base),
205SOC_ENUM_SINGLE(WM8753_BASS, 4, 6, wm8753_base_filter),
206SOC_ENUM_SINGLE(WM8753_TREBLE, 6, 2, wm8753_treble),
207SOC_ENUM_SINGLE(WM8753_ALC1, 7, 4, wm8753_alc_func),
208SOC_ENUM_SINGLE(WM8753_NGATE, 1, 2, wm8753_ng_type),
209SOC_ENUM_SINGLE(WM8753_3D, 7, 2, wm8753_3d_func),
210SOC_ENUM_SINGLE(WM8753_3D, 6, 2, wm8753_3d_uc),
211SOC_ENUM_SINGLE(WM8753_3D, 5, 2, wm8753_3d_lc),
212SOC_ENUM_SINGLE(WM8753_DAC, 1, 4, wm8753_deemp),
213SOC_ENUM_SINGLE(WM8753_DAC, 4, 4, wm8753_mono_mix),
214SOC_ENUM_SINGLE(WM8753_DAC, 6, 2, wm8753_dac_phase),
215SOC_ENUM_SINGLE(WM8753_INCTL1, 3, 4, wm8753_line_mix),
216SOC_ENUM_SINGLE(WM8753_INCTL1, 2, 2, wm8753_mono_mux),
217SOC_ENUM_SINGLE(WM8753_INCTL1, 1, 2, wm8753_right_mux),
218SOC_ENUM_SINGLE(WM8753_INCTL1, 0, 2, wm8753_left_mux),
219SOC_ENUM_SINGLE(WM8753_INCTL2, 6, 4, wm8753_rxmsel),
220SOC_ENUM_SINGLE(WM8753_INCTL2, 4, 4, wm8753_sidetone_mux),
221SOC_ENUM_SINGLE(WM8753_OUTCTL, 7, 4, wm8753_mono2_src),
222SOC_ENUM_SINGLE(WM8753_OUTCTL, 0, 3, wm8753_out3),
223SOC_ENUM_SINGLE(WM8753_ADCTL2, 7, 3, wm8753_out4),
224SOC_ENUM_SINGLE(WM8753_ADCIN, 2, 3, wm8753_radcsel),
225SOC_ENUM_SINGLE(WM8753_ADCIN, 0, 3, wm8753_ladcsel),
226SOC_ENUM_SINGLE(WM8753_ADCIN, 4, 4, wm8753_mono_adc),
227SOC_ENUM_SINGLE(WM8753_ADC, 2, 4, wm8753_adc_hp),
228SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter),
229SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel),
230SOC_ENUM_SINGLE(WM8753_IOCTL, 2, 4, wm8753_dai_mode),
231SOC_ENUM_SINGLE(WM8753_ADC, 7, 4, wm8753_dat_sel),
Graeme Gregoryae092c92008-03-03 17:19:45 +0100232SOC_ENUM_SINGLE(WM8753_OUTCTL, 2, 2, wm8753_rout2_phase),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200233};
234
235
236static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
237 struct snd_ctl_elem_value *ucontrol)
238{
239 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
240 int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
241
242 ucontrol->value.integer.value[0] = (mode & 0xc) >> 2;
243 return 0;
244}
245
246static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
247 struct snd_ctl_elem_value *ucontrol)
248{
249 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
250 int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
251
Mark Brown60fc6842008-04-30 17:18:43 +0200252 if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200253 return 0;
254
255 mode &= 0xfff3;
256 mode |= (ucontrol->value.integer.value[0] << 2);
257
258 wm8753_write(codec, WM8753_IOCTL, mode);
259 wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]);
260 return 1;
261}
262
Mike Montour2cc8c602008-06-11 13:47:12 +0100263static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 300, 0);
264static const DECLARE_TLV_DB_SCALE(mic_preamp_tlv, 1200, 600, 0);
265static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
266static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
267static const unsigned int out_tlv[] = {
268 TLV_DB_RANGE_HEAD(2),
269 /* 0000000 - 0101111 = "Analogue mute" */
270 0, 48, TLV_DB_SCALE_ITEM(-25500, 0, 0),
271 48, 127, TLV_DB_SCALE_ITEM(-7300, 100, 0),
272};
273static const DECLARE_TLV_DB_SCALE(mix_tlv, -1500, 300, 0);
274static const DECLARE_TLV_DB_SCALE(voice_mix_tlv, -1200, 300, 0);
275static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);
Liam Girdwood2d6a4ac2008-01-10 14:43:48 +0100276
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200277static const struct snd_kcontrol_new wm8753_snd_controls[] = {
Mike Montour2cc8c602008-06-11 13:47:12 +0100278SOC_DOUBLE_R_TLV("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0, dac_tlv),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200279
Mike Montour2cc8c602008-06-11 13:47:12 +0100280SOC_DOUBLE_R_TLV("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 255, 0,
281 adc_tlv),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200282
Mike Montour2cc8c602008-06-11 13:47:12 +0100283SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8753_LOUT1V, WM8753_ROUT1V,
284 0, 127, 0, out_tlv),
285SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8753_LOUT2V, WM8753_ROUT2V, 0,
286 127, 0, out_tlv),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200287
Mike Montour2cc8c602008-06-11 13:47:12 +0100288SOC_SINGLE_TLV("Mono Playback Volume", WM8753_MOUTV, 0, 127, 0, out_tlv),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200289
Mike Montour2cc8c602008-06-11 13:47:12 +0100290SOC_DOUBLE_R_TLV("Bypass Playback Volume", WM8753_LOUTM1, WM8753_ROUTM1, 4, 7,
291 1, mix_tlv),
292SOC_DOUBLE_R_TLV("Sidetone Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 4,
293 7, 1, mix_tlv),
294SOC_DOUBLE_R_TLV("Voice Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 0, 7,
295 1, voice_mix_tlv),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200296
Mike Montour2cc8c602008-06-11 13:47:12 +0100297SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8753_LOUT1V, WM8753_ROUT1V, 7,
298 1, 0),
299SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7,
300 1, 0),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200301
Mike Montour2cc8c602008-06-11 13:47:12 +0100302SOC_SINGLE_TLV("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1, mix_tlv),
303SOC_SINGLE_TLV("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1,
304 mix_tlv),
305SOC_SINGLE_TLV("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1,
306 voice_mix_tlv),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200307SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0),
308
309SOC_ENUM("Bass Boost", wm8753_enum[0]),
310SOC_ENUM("Bass Filter", wm8753_enum[1]),
311SOC_SINGLE("Bass Volume", WM8753_BASS, 0, 15, 1),
312
313SOC_SINGLE("Treble Volume", WM8753_TREBLE, 0, 15, 1),
314SOC_ENUM("Treble Cut-off", wm8753_enum[2]),
315
Mike Montour2cc8c602008-06-11 13:47:12 +0100316SOC_DOUBLE_TLV("Sidetone Capture Volume", WM8753_RECMIX1, 0, 4, 7, 1,
317 rec_mix_tlv),
318SOC_SINGLE_TLV("Voice Sidetone Capture Volume", WM8753_RECMIX2, 0, 7, 1,
319 rec_mix_tlv),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200320
Mike Montour2cc8c602008-06-11 13:47:12 +0100321SOC_DOUBLE_R_TLV("Capture Volume", WM8753_LINVOL, WM8753_RINVOL, 0, 63, 0,
322 pga_tlv),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200323SOC_DOUBLE_R("Capture ZC Switch", WM8753_LINVOL, WM8753_RINVOL, 6, 1, 0),
324SOC_DOUBLE_R("Capture Switch", WM8753_LINVOL, WM8753_RINVOL, 7, 1, 1),
325
326SOC_ENUM("Capture Filter Select", wm8753_enum[23]),
327SOC_ENUM("Capture Filter Cut-off", wm8753_enum[24]),
328SOC_SINGLE("Capture Filter Switch", WM8753_ADC, 0, 1, 1),
329
330SOC_SINGLE("ALC Capture Target Volume", WM8753_ALC1, 0, 7, 0),
331SOC_SINGLE("ALC Capture Max Volume", WM8753_ALC1, 4, 7, 0),
332SOC_ENUM("ALC Capture Function", wm8753_enum[3]),
333SOC_SINGLE("ALC Capture ZC Switch", WM8753_ALC2, 8, 1, 0),
334SOC_SINGLE("ALC Capture Hold Time", WM8753_ALC2, 0, 15, 1),
335SOC_SINGLE("ALC Capture Decay Time", WM8753_ALC3, 4, 15, 1),
336SOC_SINGLE("ALC Capture Attack Time", WM8753_ALC3, 0, 15, 0),
337SOC_SINGLE("ALC Capture NG Threshold", WM8753_NGATE, 3, 31, 0),
338SOC_ENUM("ALC Capture NG Type", wm8753_enum[4]),
339SOC_SINGLE("ALC Capture NG Switch", WM8753_NGATE, 0, 1, 0),
340
341SOC_ENUM("3D Function", wm8753_enum[5]),
342SOC_ENUM("3D Upper Cut-off", wm8753_enum[6]),
343SOC_ENUM("3D Lower Cut-off", wm8753_enum[7]),
344SOC_SINGLE("3D Volume", WM8753_3D, 1, 15, 0),
345SOC_SINGLE("3D Switch", WM8753_3D, 0, 1, 0),
346
347SOC_SINGLE("Capture 6dB Attenuate", WM8753_ADCTL1, 2, 1, 0),
348SOC_SINGLE("Playback 6dB Attenuate", WM8753_ADCTL1, 1, 1, 0),
349
350SOC_ENUM("De-emphasis", wm8753_enum[8]),
351SOC_ENUM("Playback Mono Mix", wm8753_enum[9]),
352SOC_ENUM("Playback Phase", wm8753_enum[10]),
353
Mike Montour2cc8c602008-06-11 13:47:12 +0100354SOC_SINGLE_TLV("Mic2 Capture Volume", WM8753_INCTL1, 7, 3, 0, mic_preamp_tlv),
355SOC_SINGLE_TLV("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0, mic_preamp_tlv),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200356
357SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai),
358
359SOC_ENUM("ADC Data Select", wm8753_enum[27]),
Graeme Gregoryae092c92008-03-03 17:19:45 +0100360SOC_ENUM("ROUT2 Phase", wm8753_enum[28]),
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200361};
362
363/* add non dapm controls */
364static int wm8753_add_controls(struct snd_soc_codec *codec)
365{
366 int err, i;
367
368 for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) {
369 err = snd_ctl_add(codec->card,
Mark Brown60fc6842008-04-30 17:18:43 +0200370 snd_soc_cnew(&wm8753_snd_controls[i],
371 codec, NULL));
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200372 if (err < 0)
373 return err;
374 }
375 return 0;
376}
377
378/*
379 * _DAPM_ Controls
380 */
381
382/* Left Mixer */
383static const struct snd_kcontrol_new wm8753_left_mixer_controls[] = {
384SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_LOUTM2, 8, 1, 0),
385SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_LOUTM2, 7, 1, 0),
386SOC_DAPM_SINGLE("Left Playback Switch", WM8753_LOUTM1, 8, 1, 0),
387SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_LOUTM1, 7, 1, 0),
388};
389
390/* Right mixer */
391static const struct snd_kcontrol_new wm8753_right_mixer_controls[] = {
392SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_ROUTM2, 8, 1, 0),
393SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_ROUTM2, 7, 1, 0),
394SOC_DAPM_SINGLE("Right Playback Switch", WM8753_ROUTM1, 8, 1, 0),
395SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_ROUTM1, 7, 1, 0),
396};
397
398/* Mono mixer */
399static const struct snd_kcontrol_new wm8753_mono_mixer_controls[] = {
400SOC_DAPM_SINGLE("Left Playback Switch", WM8753_MOUTM1, 8, 1, 0),
401SOC_DAPM_SINGLE("Right Playback Switch", WM8753_MOUTM2, 8, 1, 0),
402SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_MOUTM2, 3, 1, 0),
403SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_MOUTM2, 7, 1, 0),
404SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_MOUTM1, 7, 1, 0),
405};
406
407/* Mono 2 Mux */
408static const struct snd_kcontrol_new wm8753_mono2_controls =
409SOC_DAPM_ENUM("Route", wm8753_enum[17]);
410
411/* Out 3 Mux */
412static const struct snd_kcontrol_new wm8753_out3_controls =
413SOC_DAPM_ENUM("Route", wm8753_enum[18]);
414
415/* Out 4 Mux */
416static const struct snd_kcontrol_new wm8753_out4_controls =
417SOC_DAPM_ENUM("Route", wm8753_enum[19]);
418
419/* ADC Mono Mix */
420static const struct snd_kcontrol_new wm8753_adc_mono_controls =
421SOC_DAPM_ENUM("Route", wm8753_enum[22]);
422
423/* Record mixer */
424static const struct snd_kcontrol_new wm8753_record_mixer_controls[] = {
425SOC_DAPM_SINGLE("Voice Capture Switch", WM8753_RECMIX2, 3, 1, 0),
426SOC_DAPM_SINGLE("Left Capture Switch", WM8753_RECMIX1, 3, 1, 0),
427SOC_DAPM_SINGLE("Right Capture Switch", WM8753_RECMIX1, 7, 1, 0),
428};
429
430/* Left ADC mux */
431static const struct snd_kcontrol_new wm8753_adc_left_controls =
432SOC_DAPM_ENUM("Route", wm8753_enum[21]);
433
434/* Right ADC mux */
435static const struct snd_kcontrol_new wm8753_adc_right_controls =
436SOC_DAPM_ENUM("Route", wm8753_enum[20]);
437
438/* MIC mux */
439static const struct snd_kcontrol_new wm8753_mic_mux_controls =
440SOC_DAPM_ENUM("Route", wm8753_enum[16]);
441
442/* ALC mixer */
443static const struct snd_kcontrol_new wm8753_alc_mixer_controls[] = {
444SOC_DAPM_SINGLE("Line Capture Switch", WM8753_INCTL2, 3, 1, 0),
445SOC_DAPM_SINGLE("Mic2 Capture Switch", WM8753_INCTL2, 2, 1, 0),
446SOC_DAPM_SINGLE("Mic1 Capture Switch", WM8753_INCTL2, 1, 1, 0),
447SOC_DAPM_SINGLE("Rx Capture Switch", WM8753_INCTL2, 0, 1, 0),
448};
449
450/* Left Line mux */
451static const struct snd_kcontrol_new wm8753_line_left_controls =
452SOC_DAPM_ENUM("Route", wm8753_enum[14]);
453
454/* Right Line mux */
455static const struct snd_kcontrol_new wm8753_line_right_controls =
456SOC_DAPM_ENUM("Route", wm8753_enum[13]);
457
458/* Mono Line mux */
459static const struct snd_kcontrol_new wm8753_line_mono_controls =
460SOC_DAPM_ENUM("Route", wm8753_enum[12]);
461
462/* Line mux and mixer */
463static const struct snd_kcontrol_new wm8753_line_mux_mix_controls =
464SOC_DAPM_ENUM("Route", wm8753_enum[11]);
465
466/* Rx mux and mixer */
467static const struct snd_kcontrol_new wm8753_rx_mux_mix_controls =
468SOC_DAPM_ENUM("Route", wm8753_enum[15]);
469
470/* Mic Selector Mux */
471static const struct snd_kcontrol_new wm8753_mic_sel_mux_controls =
472SOC_DAPM_ENUM("Route", wm8753_enum[25]);
473
474static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
475SND_SOC_DAPM_MICBIAS("Mic Bias", WM8753_PWR1, 5, 0),
476SND_SOC_DAPM_MIXER("Left Mixer", WM8753_PWR4, 0, 0,
477 &wm8753_left_mixer_controls[0], ARRAY_SIZE(wm8753_left_mixer_controls)),
478SND_SOC_DAPM_PGA("Left Out 1", WM8753_PWR3, 8, 0, NULL, 0),
479SND_SOC_DAPM_PGA("Left Out 2", WM8753_PWR3, 6, 0, NULL, 0),
480SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", WM8753_PWR1, 3, 0),
481SND_SOC_DAPM_OUTPUT("LOUT1"),
482SND_SOC_DAPM_OUTPUT("LOUT2"),
483SND_SOC_DAPM_MIXER("Right Mixer", WM8753_PWR4, 1, 0,
484 &wm8753_right_mixer_controls[0], ARRAY_SIZE(wm8753_right_mixer_controls)),
485SND_SOC_DAPM_PGA("Right Out 1", WM8753_PWR3, 7, 0, NULL, 0),
486SND_SOC_DAPM_PGA("Right Out 2", WM8753_PWR3, 5, 0, NULL, 0),
487SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", WM8753_PWR1, 2, 0),
488SND_SOC_DAPM_OUTPUT("ROUT1"),
489SND_SOC_DAPM_OUTPUT("ROUT2"),
490SND_SOC_DAPM_MIXER("Mono Mixer", WM8753_PWR4, 2, 0,
491 &wm8753_mono_mixer_controls[0], ARRAY_SIZE(wm8753_mono_mixer_controls)),
492SND_SOC_DAPM_PGA("Mono Out 1", WM8753_PWR3, 2, 0, NULL, 0),
493SND_SOC_DAPM_PGA("Mono Out 2", WM8753_PWR3, 1, 0, NULL, 0),
494SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", WM8753_PWR1, 4, 0),
495SND_SOC_DAPM_OUTPUT("MONO1"),
496SND_SOC_DAPM_MUX("Mono 2 Mux", SND_SOC_NOPM, 0, 0, &wm8753_mono2_controls),
497SND_SOC_DAPM_OUTPUT("MONO2"),
498SND_SOC_DAPM_MIXER("Out3 Left + Right", -1, 0, 0, NULL, 0),
499SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &wm8753_out3_controls),
500SND_SOC_DAPM_PGA("Out 3", WM8753_PWR3, 4, 0, NULL, 0),
501SND_SOC_DAPM_OUTPUT("OUT3"),
502SND_SOC_DAPM_MUX("Out4 Mux", SND_SOC_NOPM, 0, 0, &wm8753_out4_controls),
503SND_SOC_DAPM_PGA("Out 4", WM8753_PWR3, 3, 0, NULL, 0),
504SND_SOC_DAPM_OUTPUT("OUT4"),
505SND_SOC_DAPM_MIXER("Playback Mixer", WM8753_PWR4, 3, 0,
506 &wm8753_record_mixer_controls[0],
507 ARRAY_SIZE(wm8753_record_mixer_controls)),
508SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8753_PWR2, 3, 0),
509SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8753_PWR2, 2, 0),
510SND_SOC_DAPM_MUX("Capture Left Mixer", SND_SOC_NOPM, 0, 0,
511 &wm8753_adc_mono_controls),
512SND_SOC_DAPM_MUX("Capture Right Mixer", SND_SOC_NOPM, 0, 0,
513 &wm8753_adc_mono_controls),
514SND_SOC_DAPM_MUX("Capture Left Mux", SND_SOC_NOPM, 0, 0,
515 &wm8753_adc_left_controls),
516SND_SOC_DAPM_MUX("Capture Right Mux", SND_SOC_NOPM, 0, 0,
517 &wm8753_adc_right_controls),
518SND_SOC_DAPM_MUX("Mic Sidetone Mux", SND_SOC_NOPM, 0, 0,
519 &wm8753_mic_mux_controls),
520SND_SOC_DAPM_PGA("Left Capture Volume", WM8753_PWR2, 5, 0, NULL, 0),
521SND_SOC_DAPM_PGA("Right Capture Volume", WM8753_PWR2, 4, 0, NULL, 0),
522SND_SOC_DAPM_MIXER("ALC Mixer", WM8753_PWR2, 6, 0,
523 &wm8753_alc_mixer_controls[0], ARRAY_SIZE(wm8753_alc_mixer_controls)),
524SND_SOC_DAPM_MUX("Line Left Mux", SND_SOC_NOPM, 0, 0,
525 &wm8753_line_left_controls),
526SND_SOC_DAPM_MUX("Line Right Mux", SND_SOC_NOPM, 0, 0,
527 &wm8753_line_right_controls),
528SND_SOC_DAPM_MUX("Line Mono Mux", SND_SOC_NOPM, 0, 0,
529 &wm8753_line_mono_controls),
530SND_SOC_DAPM_MUX("Line Mixer", WM8753_PWR2, 0, 0,
531 &wm8753_line_mux_mix_controls),
532SND_SOC_DAPM_MUX("Rx Mixer", WM8753_PWR2, 1, 0,
533 &wm8753_rx_mux_mix_controls),
534SND_SOC_DAPM_PGA("Mic 1 Volume", WM8753_PWR2, 8, 0, NULL, 0),
535SND_SOC_DAPM_PGA("Mic 2 Volume", WM8753_PWR2, 7, 0, NULL, 0),
536SND_SOC_DAPM_MUX("Mic Selection Mux", SND_SOC_NOPM, 0, 0,
537 &wm8753_mic_sel_mux_controls),
538SND_SOC_DAPM_INPUT("LINE1"),
539SND_SOC_DAPM_INPUT("LINE2"),
540SND_SOC_DAPM_INPUT("RXP"),
541SND_SOC_DAPM_INPUT("RXN"),
542SND_SOC_DAPM_INPUT("ACIN"),
543SND_SOC_DAPM_OUTPUT("ACOP"),
544SND_SOC_DAPM_INPUT("MIC1N"),
545SND_SOC_DAPM_INPUT("MIC1"),
546SND_SOC_DAPM_INPUT("MIC2N"),
547SND_SOC_DAPM_INPUT("MIC2"),
548SND_SOC_DAPM_VMID("VREF"),
549};
550
Mark Browna65f0562008-05-13 14:54:43 +0200551static const struct snd_soc_dapm_route audio_map[] = {
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200552 /* left mixer */
553 {"Left Mixer", "Left Playback Switch", "Left DAC"},
554 {"Left Mixer", "Voice Playback Switch", "Voice DAC"},
555 {"Left Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"},
556 {"Left Mixer", "Bypass Playback Switch", "Line Left Mux"},
557
558 /* right mixer */
559 {"Right Mixer", "Right Playback Switch", "Right DAC"},
560 {"Right Mixer", "Voice Playback Switch", "Voice DAC"},
561 {"Right Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"},
562 {"Right Mixer", "Bypass Playback Switch", "Line Right Mux"},
563
564 /* mono mixer */
565 {"Mono Mixer", "Voice Playback Switch", "Voice DAC"},
566 {"Mono Mixer", "Left Playback Switch", "Left DAC"},
567 {"Mono Mixer", "Right Playback Switch", "Right DAC"},
568 {"Mono Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"},
569 {"Mono Mixer", "Bypass Playback Switch", "Line Mono Mux"},
570
571 /* left out */
572 {"Left Out 1", NULL, "Left Mixer"},
573 {"Left Out 2", NULL, "Left Mixer"},
574 {"LOUT1", NULL, "Left Out 1"},
575 {"LOUT2", NULL, "Left Out 2"},
576
577 /* right out */
578 {"Right Out 1", NULL, "Right Mixer"},
579 {"Right Out 2", NULL, "Right Mixer"},
580 {"ROUT1", NULL, "Right Out 1"},
581 {"ROUT2", NULL, "Right Out 2"},
582
583 /* mono 1 out */
584 {"Mono Out 1", NULL, "Mono Mixer"},
585 {"MONO1", NULL, "Mono Out 1"},
586
587 /* mono 2 out */
588 {"Mono 2 Mux", "Left + Right", "Out3 Left + Right"},
589 {"Mono 2 Mux", "Inverted Mono 1", "MONO1"},
590 {"Mono 2 Mux", "Left", "Left Mixer"},
591 {"Mono 2 Mux", "Right", "Right Mixer"},
592 {"Mono Out 2", NULL, "Mono 2 Mux"},
593 {"MONO2", NULL, "Mono Out 2"},
594
595 /* out 3 */
596 {"Out3 Left + Right", NULL, "Left Mixer"},
597 {"Out3 Left + Right", NULL, "Right Mixer"},
598 {"Out3 Mux", "VREF", "VREF"},
599 {"Out3 Mux", "Left + Right", "Out3 Left + Right"},
600 {"Out3 Mux", "ROUT2", "ROUT2"},
601 {"Out 3", NULL, "Out3 Mux"},
602 {"OUT3", NULL, "Out 3"},
603
604 /* out 4 */
605 {"Out4 Mux", "VREF", "VREF"},
606 {"Out4 Mux", "Capture ST", "Capture ST Mixer"},
607 {"Out4 Mux", "LOUT2", "LOUT2"},
608 {"Out 4", NULL, "Out4 Mux"},
609 {"OUT4", NULL, "Out 4"},
610
611 /* record mixer */
612 {"Playback Mixer", "Left Capture Switch", "Left Mixer"},
613 {"Playback Mixer", "Voice Capture Switch", "Mono Mixer"},
614 {"Playback Mixer", "Right Capture Switch", "Right Mixer"},
615
616 /* Mic/SideTone Mux */
617 {"Mic Sidetone Mux", "Left PGA", "Left Capture Volume"},
618 {"Mic Sidetone Mux", "Right PGA", "Right Capture Volume"},
619 {"Mic Sidetone Mux", "Mic 1", "Mic 1 Volume"},
620 {"Mic Sidetone Mux", "Mic 2", "Mic 2 Volume"},
621
622 /* Capture Left Mux */
623 {"Capture Left Mux", "PGA", "Left Capture Volume"},
624 {"Capture Left Mux", "Line or RXP-RXN", "Line Left Mux"},
625 {"Capture Left Mux", "Line", "LINE1"},
626
627 /* Capture Right Mux */
628 {"Capture Right Mux", "PGA", "Right Capture Volume"},
629 {"Capture Right Mux", "Line or RXP-RXN", "Line Right Mux"},
630 {"Capture Right Mux", "Sidetone", "Capture ST Mixer"},
631
632 /* Mono Capture mixer-mux */
633 {"Capture Right Mixer", "Stereo", "Capture Right Mux"},
634 {"Capture Left Mixer", "Analogue Mix Left", "Capture Left Mux"},
635 {"Capture Left Mixer", "Analogue Mix Left", "Capture Right Mux"},
636 {"Capture Right Mixer", "Analogue Mix Right", "Capture Left Mux"},
637 {"Capture Right Mixer", "Analogue Mix Right", "Capture Right Mux"},
638 {"Capture Left Mixer", "Digital Mono Mix", "Capture Left Mux"},
639 {"Capture Left Mixer", "Digital Mono Mix", "Capture Right Mux"},
640 {"Capture Right Mixer", "Digital Mono Mix", "Capture Left Mux"},
641 {"Capture Right Mixer", "Digital Mono Mix", "Capture Right Mux"},
642
643 /* ADC */
644 {"Left ADC", NULL, "Capture Left Mixer"},
645 {"Right ADC", NULL, "Capture Right Mixer"},
646
647 /* Left Capture Volume */
648 {"Left Capture Volume", NULL, "ACIN"},
649
650 /* Right Capture Volume */
651 {"Right Capture Volume", NULL, "Mic 2 Volume"},
652
653 /* ALC Mixer */
654 {"ALC Mixer", "Line Capture Switch", "Line Mixer"},
655 {"ALC Mixer", "Mic2 Capture Switch", "Mic 2 Volume"},
656 {"ALC Mixer", "Mic1 Capture Switch", "Mic 1 Volume"},
657 {"ALC Mixer", "Rx Capture Switch", "Rx Mixer"},
658
659 /* Line Left Mux */
660 {"Line Left Mux", "Line 1", "LINE1"},
661 {"Line Left Mux", "Rx Mix", "Rx Mixer"},
662
663 /* Line Right Mux */
664 {"Line Right Mux", "Line 2", "LINE2"},
665 {"Line Right Mux", "Rx Mix", "Rx Mixer"},
666
667 /* Line Mono Mux */
668 {"Line Mono Mux", "Line Mix", "Line Mixer"},
669 {"Line Mono Mux", "Rx Mix", "Rx Mixer"},
670
671 /* Line Mixer/Mux */
672 {"Line Mixer", "Line 1 + 2", "LINE1"},
673 {"Line Mixer", "Line 1 - 2", "LINE1"},
674 {"Line Mixer", "Line 1 + 2", "LINE2"},
675 {"Line Mixer", "Line 1 - 2", "LINE2"},
676 {"Line Mixer", "Line 1", "LINE1"},
677 {"Line Mixer", "Line 2", "LINE2"},
678
679 /* Rx Mixer/Mux */
680 {"Rx Mixer", "RXP - RXN", "RXP"},
681 {"Rx Mixer", "RXP + RXN", "RXP"},
682 {"Rx Mixer", "RXP - RXN", "RXN"},
683 {"Rx Mixer", "RXP + RXN", "RXN"},
684 {"Rx Mixer", "RXP", "RXP"},
685 {"Rx Mixer", "RXN", "RXN"},
686
687 /* Mic 1 Volume */
688 {"Mic 1 Volume", NULL, "MIC1N"},
689 {"Mic 1 Volume", NULL, "Mic Selection Mux"},
690
691 /* Mic 2 Volume */
692 {"Mic 2 Volume", NULL, "MIC2N"},
693 {"Mic 2 Volume", NULL, "MIC2"},
694
695 /* Mic Selector Mux */
696 {"Mic Selection Mux", "Mic 1", "MIC1"},
697 {"Mic Selection Mux", "Mic 2", "MIC2N"},
698 {"Mic Selection Mux", "Mic 3", "MIC2"},
699
700 /* ACOP */
701 {"ACOP", NULL, "ALC Mixer"},
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200702};
703
704static int wm8753_add_widgets(struct snd_soc_codec *codec)
705{
Mark Browna65f0562008-05-13 14:54:43 +0200706 snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
707 ARRAY_SIZE(wm8753_dapm_widgets));
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200708
Mark Browna65f0562008-05-13 14:54:43 +0200709 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200710
711 snd_soc_dapm_new_widgets(codec);
712 return 0;
713}
714
715/* PLL divisors */
716struct _pll_div {
717 u32 div2:1;
718 u32 n:4;
719 u32 k:24;
720};
721
722/* The size in bits of the pll divide multiplied by 10
723 * to allow rounding later */
724#define FIXED_PLL_SIZE ((1 << 22) * 10)
725
726static void pll_factors(struct _pll_div *pll_div, unsigned int target,
727 unsigned int source)
728{
729 u64 Kpart;
730 unsigned int K, Ndiv, Nmod;
731
732 Ndiv = target / source;
733 if (Ndiv < 6) {
734 source >>= 1;
735 pll_div->div2 = 1;
736 Ndiv = target / source;
737 } else
738 pll_div->div2 = 0;
739
740 if ((Ndiv < 6) || (Ndiv > 12))
741 printk(KERN_WARNING
Mark Brown60fc6842008-04-30 17:18:43 +0200742 "wm8753: unsupported N = %d\n", Ndiv);
Liam Girdwood1f53aee2007-04-16 19:17:44 +0200743
744 pll_div->n = Ndiv;
745 Nmod = target % source;
746 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
747
748 do_div(Kpart, source);
749
750 K = Kpart & 0xFFFFFFFF;
751
752 /* Check if we need to round */
753 if ((K % 10) >= 5)
754 K += 5;
755
756 /* Move down to proper range now rounding is done */
757 K /= 10;
758
759 pll_div->k = K;
760}
761
762static int wm8753_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
763 int pll_id, unsigned int freq_in, unsigned int freq_out)
764{
765 u16 reg, enable;
766 int offset;
767 struct snd_soc_codec *codec = codec_dai->codec;
768
769 if (pll_id < WM8753_PLL1 || pll_id > WM8753_PLL2)
770 return -ENODEV;
771
772 if (pll_id == WM8753_PLL1) {
773 offset = 0;
774 enable = 0x10;
775 reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef;
776 } else {
777 offset = 4;
778 enable = 0x8;
779 reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7;
780 }
781
782 if (!freq_in || !freq_out) {
783 /* disable PLL */
784 wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026);
785 wm8753_write(codec, WM8753_CLOCK, reg);
786 return 0;
787 } else {
788 u16 value = 0;
789 struct _pll_div pll_div;
790
791 pll_factors(&pll_div, freq_out * 8, freq_in);
792
793 /* set up N and K PLL divisor ratios */
794 /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
795 value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18);
796 wm8753_write(codec, WM8753_PLL1CTL2 + offset, value);
797
798 /* bits 8:0 = PLL_K[17:9] */
799 value = (pll_div.k & 0x03fe00) >> 9;
800 wm8753_write(codec, WM8753_PLL1CTL3 + offset, value);
801
802 /* bits 8:0 = PLL_K[8:0] */
803 value = pll_div.k & 0x0001ff;
804 wm8753_write(codec, WM8753_PLL1CTL4 + offset, value);
805
806 /* set PLL as input and enable */
807 wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |
808 (pll_div.div2 << 3));
809 wm8753_write(codec, WM8753_CLOCK, reg | enable);
810 }
811 return 0;
812}
813
814struct _coeff_div {
815 u32 mclk;
816 u32 rate;
817 u8 sr:5;
818 u8 usb:1;
819};
820
821/* codec hifi mclk (after PLL) clock divider coefficients */
822static const struct _coeff_div coeff_div[] = {
823 /* 8k */
824 {12288000, 8000, 0x6, 0x0},
825 {11289600, 8000, 0x16, 0x0},
826 {18432000, 8000, 0x7, 0x0},
827 {16934400, 8000, 0x17, 0x0},
828 {12000000, 8000, 0x6, 0x1},
829
830 /* 11.025k */
831 {11289600, 11025, 0x18, 0x0},
832 {16934400, 11025, 0x19, 0x0},
833 {12000000, 11025, 0x19, 0x1},
834
835 /* 16k */
836 {12288000, 16000, 0xa, 0x0},
837 {18432000, 16000, 0xb, 0x0},
838 {12000000, 16000, 0xa, 0x1},
839
840 /* 22.05k */
841 {11289600, 22050, 0x1a, 0x0},
842 {16934400, 22050, 0x1b, 0x0},
843 {12000000, 22050, 0x1b, 0x1},
844
845 /* 32k */
846 {12288000, 32000, 0xc, 0x0},
847 {18432000, 32000, 0xd, 0x0},
848 {12000000, 32000, 0xa, 0x1},
849
850 /* 44.1k */
851 {11289600, 44100, 0x10, 0x0},
852 {16934400, 44100, 0x11, 0x0},
853 {12000000, 44100, 0x11, 0x1},
854
855 /* 48k */
856 {12288000, 48000, 0x0, 0x0},
857 {18432000, 48000, 0x1, 0x0},
858 {12000000, 48000, 0x0, 0x1},
859
860 /* 88.2k */
861 {11289600, 88200, 0x1e, 0x0},
862 {16934400, 88200, 0x1f, 0x0},
863 {12000000, 88200, 0x1f, 0x1},
864
865 /* 96k */
866 {12288000, 96000, 0xe, 0x0},
867 {18432000, 96000, 0xf, 0x0},
868 {12000000, 96000, 0xe, 0x1},
869};
870
871static int get_coeff(int mclk, int rate)
872{
873 int i;
874
875 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
876 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
877 return i;
878 }
879 return -EINVAL;
880}
881
882/*
883 * Clock after PLL and dividers
884 */
885static int wm8753_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
886 int clk_id, unsigned int freq, int dir)
887{
888 struct snd_soc_codec *codec = codec_dai->codec;
889 struct wm8753_priv *wm8753 = codec->private_data;
890
891 switch (freq) {
892 case 11289600:
893 case 12000000:
894 case 12288000:
895 case 16934400:
896 case 18432000:
897 if (clk_id == WM8753_MCLK) {
898 wm8753->sysclk = freq;
899 return 0;
900 } else if (clk_id == WM8753_PCMCLK) {
901 wm8753->pcmclk = freq;
902 return 0;
903 }
904 break;
905 }
906 return -EINVAL;
907}
908
909/*
910 * Set's ADC and Voice DAC format.
911 */
912static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
913 unsigned int fmt)
914{
915 struct snd_soc_codec *codec = codec_dai->codec;
916 u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec;
917
918 /* interface format */
919 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
920 case SND_SOC_DAIFMT_I2S:
921 voice |= 0x0002;
922 break;
923 case SND_SOC_DAIFMT_RIGHT_J:
924 break;
925 case SND_SOC_DAIFMT_LEFT_J:
926 voice |= 0x0001;
927 break;
928 case SND_SOC_DAIFMT_DSP_A:
929 voice |= 0x0003;
930 break;
931 case SND_SOC_DAIFMT_DSP_B:
932 voice |= 0x0013;
933 break;
934 default:
935 return -EINVAL;
936 }
937
938 wm8753_write(codec, WM8753_PCM, voice);
939 return 0;
940}
941
942/*
943 * Set PCM DAI bit size and sample rate.
944 */
945static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
946 struct snd_pcm_hw_params *params)
947{
948 struct snd_soc_pcm_runtime *rtd = substream->private_data;
949 struct snd_soc_device *socdev = rtd->socdev;
950 struct snd_soc_codec *codec = socdev->codec;
951 struct wm8753_priv *wm8753 = codec->private_data;
952 u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3;
953 u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
954
955 /* bit size */
956 switch (params_format(params)) {
957 case SNDRV_PCM_FORMAT_S16_LE:
958 break;
959 case SNDRV_PCM_FORMAT_S20_3LE:
960 voice |= 0x0004;
961 break;
962 case SNDRV_PCM_FORMAT_S24_LE:
963 voice |= 0x0008;
964 break;
965 case SNDRV_PCM_FORMAT_S32_LE:
966 voice |= 0x000c;
967 break;
968 }
969
970 /* sample rate */
971 if (params_rate(params) * 384 == wm8753->pcmclk)
972 srate |= 0x80;
973 wm8753_write(codec, WM8753_SRATE1, srate);
974
975 wm8753_write(codec, WM8753_PCM, voice);
976 return 0;
977}
978
979/*
980 * Set's PCM dai fmt and BCLK.
981 */
982static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
983 unsigned int fmt)
984{
985 struct snd_soc_codec *codec = codec_dai->codec;
986 u16 voice, ioctl;
987
988 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f;
989 ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d;
990
991 /* set master/slave audio interface */
992 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
993 case SND_SOC_DAIFMT_CBS_CFS:
994 break;
995 case SND_SOC_DAIFMT_CBM_CFM:
996 ioctl |= 0x2;
997 case SND_SOC_DAIFMT_CBM_CFS:
998 voice |= 0x0040;
999 break;
1000 default:
1001 return -EINVAL;
1002 }
1003
1004 /* clock inversion */
1005 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1006 case SND_SOC_DAIFMT_DSP_A:
1007 case SND_SOC_DAIFMT_DSP_B:
1008 /* frame inversion not valid for DSP modes */
1009 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1010 case SND_SOC_DAIFMT_NB_NF:
1011 break;
1012 case SND_SOC_DAIFMT_IB_NF:
1013 voice |= 0x0080;
1014 break;
1015 default:
1016 return -EINVAL;
1017 }
1018 break;
1019 case SND_SOC_DAIFMT_I2S:
1020 case SND_SOC_DAIFMT_RIGHT_J:
1021 case SND_SOC_DAIFMT_LEFT_J:
1022 voice &= ~0x0010;
1023 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1024 case SND_SOC_DAIFMT_NB_NF:
1025 break;
1026 case SND_SOC_DAIFMT_IB_IF:
1027 voice |= 0x0090;
1028 break;
1029 case SND_SOC_DAIFMT_IB_NF:
1030 voice |= 0x0080;
1031 break;
1032 case SND_SOC_DAIFMT_NB_IF:
1033 voice |= 0x0010;
1034 break;
1035 default:
1036 return -EINVAL;
1037 }
1038 break;
1039 default:
1040 return -EINVAL;
1041 }
1042
1043 wm8753_write(codec, WM8753_PCM, voice);
1044 wm8753_write(codec, WM8753_IOCTL, ioctl);
1045 return 0;
1046}
1047
1048static int wm8753_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
1049 int div_id, int div)
1050{
1051 struct snd_soc_codec *codec = codec_dai->codec;
1052 u16 reg;
1053
1054 switch (div_id) {
1055 case WM8753_PCMDIV:
1056 reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f;
1057 wm8753_write(codec, WM8753_CLOCK, reg | div);
1058 break;
1059 case WM8753_BCLKDIV:
1060 reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7;
1061 wm8753_write(codec, WM8753_SRATE2, reg | div);
1062 break;
1063 case WM8753_VXCLKDIV:
1064 reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f;
1065 wm8753_write(codec, WM8753_SRATE2, reg | div);
1066 break;
1067 default:
1068 return -EINVAL;
1069 }
1070 return 0;
1071}
1072
1073/*
1074 * Set's HiFi DAC format.
1075 */
1076static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1077 unsigned int fmt)
1078{
1079 struct snd_soc_codec *codec = codec_dai->codec;
1080 u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0;
1081
1082 /* interface format */
1083 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1084 case SND_SOC_DAIFMT_I2S:
1085 hifi |= 0x0002;
1086 break;
1087 case SND_SOC_DAIFMT_RIGHT_J:
1088 break;
1089 case SND_SOC_DAIFMT_LEFT_J:
1090 hifi |= 0x0001;
1091 break;
1092 case SND_SOC_DAIFMT_DSP_A:
1093 hifi |= 0x0003;
1094 break;
1095 case SND_SOC_DAIFMT_DSP_B:
1096 hifi |= 0x0013;
1097 break;
1098 default:
1099 return -EINVAL;
1100 }
1101
1102 wm8753_write(codec, WM8753_HIFI, hifi);
1103 return 0;
1104}
1105
1106/*
1107 * Set's I2S DAI format.
1108 */
1109static int wm8753_i2s_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1110 unsigned int fmt)
1111{
1112 struct snd_soc_codec *codec = codec_dai->codec;
1113 u16 ioctl, hifi;
1114
1115 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f;
1116 ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae;
1117
1118 /* set master/slave audio interface */
1119 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1120 case SND_SOC_DAIFMT_CBS_CFS:
1121 break;
1122 case SND_SOC_DAIFMT_CBM_CFM:
1123 ioctl |= 0x1;
1124 case SND_SOC_DAIFMT_CBM_CFS:
1125 hifi |= 0x0040;
1126 break;
1127 default:
1128 return -EINVAL;
1129 }
1130
1131 /* clock inversion */
1132 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1133 case SND_SOC_DAIFMT_DSP_A:
1134 case SND_SOC_DAIFMT_DSP_B:
1135 /* frame inversion not valid for DSP modes */
1136 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1137 case SND_SOC_DAIFMT_NB_NF:
1138 break;
1139 case SND_SOC_DAIFMT_IB_NF:
1140 hifi |= 0x0080;
1141 break;
1142 default:
1143 return -EINVAL;
1144 }
1145 break;
1146 case SND_SOC_DAIFMT_I2S:
1147 case SND_SOC_DAIFMT_RIGHT_J:
1148 case SND_SOC_DAIFMT_LEFT_J:
1149 hifi &= ~0x0010;
1150 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1151 case SND_SOC_DAIFMT_NB_NF:
1152 break;
1153 case SND_SOC_DAIFMT_IB_IF:
1154 hifi |= 0x0090;
1155 break;
1156 case SND_SOC_DAIFMT_IB_NF:
1157 hifi |= 0x0080;
1158 break;
1159 case SND_SOC_DAIFMT_NB_IF:
1160 hifi |= 0x0010;
1161 break;
1162 default:
1163 return -EINVAL;
1164 }
1165 break;
1166 default:
1167 return -EINVAL;
1168 }
1169
1170 wm8753_write(codec, WM8753_HIFI, hifi);
1171 wm8753_write(codec, WM8753_IOCTL, ioctl);
1172 return 0;
1173}
1174
1175/*
1176 * Set PCM DAI bit size and sample rate.
1177 */
1178static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
1179 struct snd_pcm_hw_params *params)
1180{
1181 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1182 struct snd_soc_device *socdev = rtd->socdev;
1183 struct snd_soc_codec *codec = socdev->codec;
1184 struct wm8753_priv *wm8753 = codec->private_data;
1185 u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;
1186 u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3;
1187 int coeff;
1188
1189 /* is digital filter coefficient valid ? */
1190 coeff = get_coeff(wm8753->sysclk, params_rate(params));
1191 if (coeff < 0) {
1192 printk(KERN_ERR "wm8753 invalid MCLK or rate\n");
1193 return coeff;
1194 }
1195 wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
1196 coeff_div[coeff].usb);
1197
1198 /* bit size */
1199 switch (params_format(params)) {
1200 case SNDRV_PCM_FORMAT_S16_LE:
1201 break;
1202 case SNDRV_PCM_FORMAT_S20_3LE:
1203 hifi |= 0x0004;
1204 break;
1205 case SNDRV_PCM_FORMAT_S24_LE:
1206 hifi |= 0x0008;
1207 break;
1208 case SNDRV_PCM_FORMAT_S32_LE:
1209 hifi |= 0x000c;
1210 break;
1211 }
1212
1213 wm8753_write(codec, WM8753_HIFI, hifi);
1214 return 0;
1215}
1216
1217static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1218 unsigned int fmt)
1219{
1220 struct snd_soc_codec *codec = codec_dai->codec;
1221 u16 clock;
1222
1223 /* set clk source as pcmclk */
1224 clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
1225 wm8753_write(codec, WM8753_CLOCK, clock);
1226
1227 if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
1228 return -EINVAL;
1229 return wm8753_pcm_set_dai_fmt(codec_dai, fmt);
1230}
1231
1232static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1233 unsigned int fmt)
1234{
1235 if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
1236 return -EINVAL;
1237 return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
1238}
1239
1240static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1241 unsigned int fmt)
1242{
1243 struct snd_soc_codec *codec = codec_dai->codec;
1244 u16 clock;
1245
1246 /* set clk source as pcmclk */
1247 clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
1248 wm8753_write(codec, WM8753_CLOCK, clock);
1249
1250 if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
1251 return -EINVAL;
1252 return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
1253}
1254
1255static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
1256 unsigned int fmt)
1257{
1258 struct snd_soc_codec *codec = codec_dai->codec;
1259 u16 clock;
1260
1261 /* set clk source as mclk */
1262 clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
1263 wm8753_write(codec, WM8753_CLOCK, clock | 0x4);
1264
1265 if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
1266 return -EINVAL;
1267 if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
1268 return -EINVAL;
1269 return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
1270}
1271
1272static int wm8753_mute(struct snd_soc_codec_dai *dai, int mute)
1273{
1274 struct snd_soc_codec *codec = dai->codec;
1275 u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
1276
1277 /* the digital mute covers the HiFi and Voice DAC's on the WM8753.
1278 * make sure we check if they are not both active when we mute */
1279 if (mute && dai->id == 1) {
1280 if (!wm8753_dai[WM8753_DAI_VOICE].playback.active ||
1281 !wm8753_dai[WM8753_DAI_HIFI].playback.active)
1282 wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
1283 } else {
1284 if (mute)
1285 wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
1286 else
1287 wm8753_write(codec, WM8753_DAC, mute_reg);
1288 }
1289
1290 return 0;
1291}
1292
Mark Brown0be98982008-05-19 12:31:28 +02001293static int wm8753_set_bias_level(struct snd_soc_codec *codec,
1294 enum snd_soc_bias_level level)
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001295{
1296 u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e;
1297
Mark Brown0be98982008-05-19 12:31:28 +02001298 switch (level) {
1299 case SND_SOC_BIAS_ON:
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001300 /* set vmid to 50k and unmute dac */
1301 wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
1302 break;
Mark Brown0be98982008-05-19 12:31:28 +02001303 case SND_SOC_BIAS_PREPARE:
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001304 /* set vmid to 5k for quick power up */
1305 wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
1306 break;
Mark Brown0be98982008-05-19 12:31:28 +02001307 case SND_SOC_BIAS_STANDBY:
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001308 /* mute dac and set vmid to 500k, enable VREF */
1309 wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
1310 break;
Mark Brown0be98982008-05-19 12:31:28 +02001311 case SND_SOC_BIAS_OFF:
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001312 wm8753_write(codec, WM8753_PWR1, 0x0001);
1313 break;
1314 }
Mark Brown0be98982008-05-19 12:31:28 +02001315 codec->bias_level = level;
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001316 return 0;
1317}
1318
1319#define WM8753_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
Mark Brown60fc6842008-04-30 17:18:43 +02001320 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
1321 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
1322 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001323
1324#define WM8753_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1325 SNDRV_PCM_FMTBIT_S24_LE)
1326
1327/*
1328 * The WM8753 supports upto 4 different and mutually exclusive DAI
1329 * configurations. This gives 2 PCM's available for use, hifi and voice.
1330 * NOTE: The Voice PCM cannot play or capture audio to the CPU as it's DAI
1331 * is connected between the wm8753 and a BT codec or GSM modem.
1332 *
1333 * 1. Voice over PCM DAI - HIFI DAC over HIFI DAI
1334 * 2. Voice over HIFI DAI - HIFI disabled
1335 * 3. Voice disabled - HIFI over HIFI
1336 * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
1337 */
1338static const struct snd_soc_codec_dai wm8753_all_dai[] = {
1339/* DAI HiFi mode 1 */
1340{ .name = "WM8753 HiFi",
1341 .id = 1,
1342 .playback = {
1343 .stream_name = "HiFi Playback",
1344 .channels_min = 1,
1345 .channels_max = 2,
1346 .rates = WM8753_RATES,
1347 .formats = WM8753_FORMATS,},
1348 .capture = { /* dummy for fast DAI switching */
1349 .stream_name = "Capture",
1350 .channels_min = 1,
1351 .channels_max = 2,
1352 .rates = WM8753_RATES,
1353 .formats = WM8753_FORMATS,},
1354 .ops = {
1355 .hw_params = wm8753_i2s_hw_params,},
1356 .dai_ops = {
1357 .digital_mute = wm8753_mute,
1358 .set_fmt = wm8753_mode1h_set_dai_fmt,
1359 .set_clkdiv = wm8753_set_dai_clkdiv,
1360 .set_pll = wm8753_set_dai_pll,
1361 .set_sysclk = wm8753_set_dai_sysclk,
1362 },
1363},
1364/* DAI Voice mode 1 */
1365{ .name = "WM8753 Voice",
1366 .id = 1,
1367 .playback = {
1368 .stream_name = "Voice Playback",
1369 .channels_min = 1,
1370 .channels_max = 1,
1371 .rates = WM8753_RATES,
1372 .formats = WM8753_FORMATS,},
1373 .capture = {
1374 .stream_name = "Capture",
1375 .channels_min = 1,
1376 .channels_max = 2,
1377 .rates = WM8753_RATES,
1378 .formats = WM8753_FORMATS,},
1379 .ops = {
1380 .hw_params = wm8753_pcm_hw_params,},
1381 .dai_ops = {
1382 .digital_mute = wm8753_mute,
1383 .set_fmt = wm8753_mode1v_set_dai_fmt,
1384 .set_clkdiv = wm8753_set_dai_clkdiv,
1385 .set_pll = wm8753_set_dai_pll,
1386 .set_sysclk = wm8753_set_dai_sysclk,
1387 },
1388},
1389/* DAI HiFi mode 2 - dummy */
1390{ .name = "WM8753 HiFi",
1391 .id = 2,
1392},
1393/* DAI Voice mode 2 */
1394{ .name = "WM8753 Voice",
1395 .id = 2,
1396 .playback = {
1397 .stream_name = "Voice Playback",
1398 .channels_min = 1,
1399 .channels_max = 1,
1400 .rates = WM8753_RATES,
1401 .formats = WM8753_FORMATS,},
1402 .capture = {
1403 .stream_name = "Capture",
1404 .channels_min = 1,
1405 .channels_max = 2,
1406 .rates = WM8753_RATES,
1407 .formats = WM8753_FORMATS,},
1408 .ops = {
1409 .hw_params = wm8753_pcm_hw_params,},
1410 .dai_ops = {
1411 .digital_mute = wm8753_mute,
1412 .set_fmt = wm8753_mode2_set_dai_fmt,
1413 .set_clkdiv = wm8753_set_dai_clkdiv,
1414 .set_pll = wm8753_set_dai_pll,
1415 .set_sysclk = wm8753_set_dai_sysclk,
1416 },
1417},
1418/* DAI HiFi mode 3 */
1419{ .name = "WM8753 HiFi",
1420 .id = 3,
1421 .playback = {
1422 .stream_name = "HiFi Playback",
1423 .channels_min = 1,
1424 .channels_max = 2,
1425 .rates = WM8753_RATES,
1426 .formats = WM8753_FORMATS,},
1427 .capture = {
1428 .stream_name = "Capture",
1429 .channels_min = 1,
1430 .channels_max = 2,
1431 .rates = WM8753_RATES,
1432 .formats = WM8753_FORMATS,},
1433 .ops = {
1434 .hw_params = wm8753_i2s_hw_params,},
1435 .dai_ops = {
1436 .digital_mute = wm8753_mute,
1437 .set_fmt = wm8753_mode3_4_set_dai_fmt,
1438 .set_clkdiv = wm8753_set_dai_clkdiv,
1439 .set_pll = wm8753_set_dai_pll,
1440 .set_sysclk = wm8753_set_dai_sysclk,
1441 },
1442},
1443/* DAI Voice mode 3 - dummy */
1444{ .name = "WM8753 Voice",
1445 .id = 3,
1446},
1447/* DAI HiFi mode 4 */
1448{ .name = "WM8753 HiFi",
1449 .id = 4,
1450 .playback = {
1451 .stream_name = "HiFi Playback",
1452 .channels_min = 1,
1453 .channels_max = 2,
1454 .rates = WM8753_RATES,
1455 .formats = WM8753_FORMATS,},
1456 .capture = {
1457 .stream_name = "Capture",
1458 .channels_min = 1,
1459 .channels_max = 2,
1460 .rates = WM8753_RATES,
1461 .formats = WM8753_FORMATS,},
1462 .ops = {
1463 .hw_params = wm8753_i2s_hw_params,},
1464 .dai_ops = {
1465 .digital_mute = wm8753_mute,
1466 .set_fmt = wm8753_mode3_4_set_dai_fmt,
1467 .set_clkdiv = wm8753_set_dai_clkdiv,
1468 .set_pll = wm8753_set_dai_pll,
1469 .set_sysclk = wm8753_set_dai_sysclk,
1470 },
1471},
1472/* DAI Voice mode 4 - dummy */
1473{ .name = "WM8753 Voice",
1474 .id = 4,
1475},
1476};
1477
1478struct snd_soc_codec_dai wm8753_dai[2];
1479EXPORT_SYMBOL_GPL(wm8753_dai);
1480
1481static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode)
1482{
1483 if (mode < 4) {
1484 int playback_active, capture_active, codec_active, pop_wait;
1485 void *private_data;
1486
1487 playback_active = wm8753_dai[0].playback.active;
1488 capture_active = wm8753_dai[0].capture.active;
1489 codec_active = wm8753_dai[0].active;
1490 private_data = wm8753_dai[0].private_data;
1491 pop_wait = wm8753_dai[0].pop_wait;
1492 wm8753_dai[0] = wm8753_all_dai[mode << 1];
1493 wm8753_dai[0].playback.active = playback_active;
1494 wm8753_dai[0].capture.active = capture_active;
1495 wm8753_dai[0].active = codec_active;
1496 wm8753_dai[0].private_data = private_data;
1497 wm8753_dai[0].pop_wait = pop_wait;
1498
1499 playback_active = wm8753_dai[1].playback.active;
1500 capture_active = wm8753_dai[1].capture.active;
1501 codec_active = wm8753_dai[1].active;
1502 private_data = wm8753_dai[1].private_data;
1503 pop_wait = wm8753_dai[1].pop_wait;
1504 wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1];
1505 wm8753_dai[1].playback.active = playback_active;
1506 wm8753_dai[1].capture.active = capture_active;
1507 wm8753_dai[1].active = codec_active;
1508 wm8753_dai[1].private_data = private_data;
1509 wm8753_dai[1].pop_wait = pop_wait;
1510 }
1511 wm8753_dai[0].codec = codec;
1512 wm8753_dai[1].codec = codec;
1513}
1514
1515static void wm8753_work(struct work_struct *work)
1516{
1517 struct snd_soc_codec *codec =
1518 container_of(work, struct snd_soc_codec, delayed_work.work);
Mark Brown0be98982008-05-19 12:31:28 +02001519 wm8753_set_bias_level(codec, codec->bias_level);
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001520}
1521
1522static int wm8753_suspend(struct platform_device *pdev, pm_message_t state)
1523{
1524 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1525 struct snd_soc_codec *codec = socdev->codec;
1526
1527 /* we only need to suspend if we are a valid card */
Mark Brown60fc6842008-04-30 17:18:43 +02001528 if (!codec->card)
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001529 return 0;
Mark Brown60fc6842008-04-30 17:18:43 +02001530
Mark Brown0be98982008-05-19 12:31:28 +02001531 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001532 return 0;
1533}
1534
1535static int wm8753_resume(struct platform_device *pdev)
1536{
1537 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1538 struct snd_soc_codec *codec = socdev->codec;
1539 int i;
1540 u8 data[2];
1541 u16 *cache = codec->reg_cache;
1542
1543 /* we only need to resume if we are a valid card */
Mark Brown60fc6842008-04-30 17:18:43 +02001544 if (!codec->card)
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001545 return 0;
1546
1547 /* Sync reg_cache with the hardware */
1548 for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) {
1549 if (i + 1 == WM8753_RESET)
1550 continue;
1551 data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
1552 data[1] = cache[i] & 0x00ff;
1553 codec->hw_write(codec->control_data, data, 2);
1554 }
1555
Mark Brown0be98982008-05-19 12:31:28 +02001556 wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001557
1558 /* charge wm8753 caps */
Mark Brown0be98982008-05-19 12:31:28 +02001559 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
1560 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
1561 codec->bias_level = SND_SOC_BIAS_ON;
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001562 schedule_delayed_work(&codec->delayed_work,
1563 msecs_to_jiffies(caps_charge));
1564 }
1565
1566 return 0;
1567}
1568
1569/*
1570 * initialise the WM8753 driver
1571 * register the mixer and dsp interfaces with the kernel
1572 */
1573static int wm8753_init(struct snd_soc_device *socdev)
1574{
1575 struct snd_soc_codec *codec = socdev->codec;
1576 int reg, ret = 0;
1577
1578 codec->name = "WM8753";
1579 codec->owner = THIS_MODULE;
1580 codec->read = wm8753_read_reg_cache;
1581 codec->write = wm8753_write;
Mark Brown0be98982008-05-19 12:31:28 +02001582 codec->set_bias_level = wm8753_set_bias_level;
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001583 codec->dai = wm8753_dai;
1584 codec->num_dai = 2;
Mark Brownd751b232008-06-11 13:47:06 +01001585 codec->reg_cache_size = ARRAY_SIZE(wm8753_reg);
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001586 codec->reg_cache = kmemdup(wm8753_reg, sizeof(wm8753_reg), GFP_KERNEL);
1587
1588 if (codec->reg_cache == NULL)
1589 return -ENOMEM;
1590
1591 wm8753_set_dai_mode(codec, 0);
1592
1593 wm8753_reset(codec);
1594
1595 /* register pcms */
1596 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1597 if (ret < 0) {
1598 printk(KERN_ERR "wm8753: failed to create pcms\n");
1599 goto pcm_err;
1600 }
1601
1602 /* charge output caps */
Mark Brown0be98982008-05-19 12:31:28 +02001603 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
1604 codec->bias_level = SND_SOC_BIAS_STANDBY;
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001605 schedule_delayed_work(&codec->delayed_work,
1606 msecs_to_jiffies(caps_charge));
1607
1608 /* set the update bits */
1609 reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
1610 wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
1611 reg = wm8753_read_reg_cache(codec, WM8753_RDAC);
1612 wm8753_write(codec, WM8753_RDAC, reg | 0x0100);
1613 reg = wm8753_read_reg_cache(codec, WM8753_LADC);
1614 wm8753_write(codec, WM8753_LADC, reg | 0x0100);
1615 reg = wm8753_read_reg_cache(codec, WM8753_RADC);
1616 wm8753_write(codec, WM8753_RADC, reg | 0x0100);
1617 reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V);
1618 wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100);
1619 reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
1620 wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
1621 reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
1622 wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
1623 reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
1624 wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
1625 reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
1626 wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
1627 reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
1628 wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
1629
1630 wm8753_add_controls(codec);
1631 wm8753_add_widgets(codec);
1632 ret = snd_soc_register_card(socdev);
1633 if (ret < 0) {
Mark Brown60fc6842008-04-30 17:18:43 +02001634 printk(KERN_ERR "wm8753: failed to register card\n");
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001635 goto card_err;
Mark Brown60fc6842008-04-30 17:18:43 +02001636 }
1637
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001638 return ret;
1639
1640card_err:
1641 snd_soc_free_pcms(socdev);
1642 snd_soc_dapm_free(socdev);
1643pcm_err:
1644 kfree(codec->reg_cache);
1645 return ret;
1646}
1647
1648/* If the i2c layer weren't so broken, we could pass this kind of data
1649 around */
1650static struct snd_soc_device *wm8753_socdev;
1651
Mark Brown60fc6842008-04-30 17:18:43 +02001652#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001653
1654/*
1655 * WM8753 2 wire address is determined by GPIO5
1656 * state during powerup.
1657 * low = 0x1a
1658 * high = 0x1b
1659 */
1660static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
1661
1662/* Magic definition of all other variables and things */
1663I2C_CLIENT_INSMOD;
1664
1665static struct i2c_driver wm8753_i2c_driver;
1666static struct i2c_client client_template;
1667
1668static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
1669{
1670 struct snd_soc_device *socdev = wm8753_socdev;
1671 struct wm8753_setup_data *setup = socdev->codec_data;
1672 struct snd_soc_codec *codec = socdev->codec;
1673 struct i2c_client *i2c;
1674 int ret;
1675
1676 if (addr != setup->i2c_address)
1677 return -ENODEV;
1678
1679 client_template.adapter = adap;
1680 client_template.addr = addr;
1681
1682 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
Mark Brown60fc6842008-04-30 17:18:43 +02001683 if (!i2c) {
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001684 kfree(codec);
1685 return -ENOMEM;
1686 }
1687 i2c_set_clientdata(i2c, codec);
1688 codec->control_data = i2c;
1689
1690 ret = i2c_attach_client(i2c);
1691 if (ret < 0) {
1692 err("failed to attach codec at addr %x\n", addr);
1693 goto err;
1694 }
1695
1696 ret = wm8753_init(socdev);
1697 if (ret < 0) {
1698 err("failed to initialise WM8753\n");
1699 goto err;
1700 }
1701
1702 return ret;
1703
1704err:
1705 kfree(codec);
1706 kfree(i2c);
1707 return ret;
1708}
1709
1710static int wm8753_i2c_detach(struct i2c_client *client)
1711{
1712 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1713 i2c_detach_client(client);
1714 kfree(codec->reg_cache);
1715 kfree(client);
1716 return 0;
1717}
1718
1719static int wm8753_i2c_attach(struct i2c_adapter *adap)
1720{
1721 return i2c_probe(adap, &addr_data, wm8753_codec_probe);
1722}
1723
1724/* corgi i2c codec control layer */
1725static struct i2c_driver wm8753_i2c_driver = {
1726 .driver = {
1727 .name = "WM8753 I2C Codec",
1728 .owner = THIS_MODULE,
1729 },
1730 .id = I2C_DRIVERID_WM8753,
1731 .attach_adapter = wm8753_i2c_attach,
1732 .detach_client = wm8753_i2c_detach,
1733 .command = NULL,
1734};
1735
1736static struct i2c_client client_template = {
1737 .name = "WM8753",
1738 .driver = &wm8753_i2c_driver,
1739};
1740#endif
1741
1742static int wm8753_probe(struct platform_device *pdev)
1743{
1744 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1745 struct wm8753_setup_data *setup;
1746 struct snd_soc_codec *codec;
1747 struct wm8753_priv *wm8753;
1748 int ret = 0;
1749
1750 info("WM8753 Audio Codec %s", WM8753_VERSION);
1751
1752 setup = socdev->codec_data;
1753 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1754 if (codec == NULL)
1755 return -ENOMEM;
1756
1757 wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
1758 if (wm8753 == NULL) {
1759 kfree(codec);
1760 return -ENOMEM;
1761 }
1762
1763 codec->private_data = wm8753;
1764 socdev->codec = codec;
1765 mutex_init(&codec->mutex);
1766 INIT_LIST_HEAD(&codec->dapm_widgets);
1767 INIT_LIST_HEAD(&codec->dapm_paths);
1768 wm8753_socdev = socdev;
1769 INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
1770
Mark Brown60fc6842008-04-30 17:18:43 +02001771#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001772 if (setup->i2c_address) {
1773 normal_i2c[0] = setup->i2c_address;
1774 codec->hw_write = (hw_write_t)i2c_master_send;
1775 ret = i2c_add_driver(&wm8753_i2c_driver);
1776 if (ret != 0)
1777 printk(KERN_ERR "can't add i2c driver");
1778 }
1779#else
1780 /* Add other interfaces here */
1781#endif
1782 return ret;
1783}
1784
1785/*
1786 * This function forces any delayed work to be queued and run.
1787 */
1788static int run_delayed_work(struct delayed_work *dwork)
1789{
1790 int ret;
1791
1792 /* cancel any work waiting to be queued. */
1793 ret = cancel_delayed_work(dwork);
1794
1795 /* if there was any work waiting then we run it now and
1796 * wait for it's completion */
1797 if (ret) {
1798 schedule_delayed_work(dwork, 0);
1799 flush_scheduled_work();
1800 }
1801 return ret;
1802}
1803
1804/* power down chip */
1805static int wm8753_remove(struct platform_device *pdev)
1806{
1807 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1808 struct snd_soc_codec *codec = socdev->codec;
1809
1810 if (codec->control_data)
Mark Brown0be98982008-05-19 12:31:28 +02001811 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001812 run_delayed_work(&codec->delayed_work);
1813 snd_soc_free_pcms(socdev);
1814 snd_soc_dapm_free(socdev);
Mark Brown60fc6842008-04-30 17:18:43 +02001815#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001816 i2c_del_driver(&wm8753_i2c_driver);
1817#endif
1818 kfree(codec->private_data);
1819 kfree(codec);
1820
1821 return 0;
1822}
1823
1824struct snd_soc_codec_device soc_codec_dev_wm8753 = {
1825 .probe = wm8753_probe,
1826 .remove = wm8753_remove,
1827 .suspend = wm8753_suspend,
1828 .resume = wm8753_resume,
1829};
Liam Girdwood1f53aee2007-04-16 19:17:44 +02001830EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
1831
1832MODULE_DESCRIPTION("ASoC WM8753 driver");
1833MODULE_AUTHOR("Liam Girdwood");
1834MODULE_LICENSE("GPL");