blob: 6648af6656c8469b67dab098502be136651ea0e0 [file] [log] [blame]
Johannes Stezenbachc034abf2011-06-22 14:59:24 +02001/*
2 * Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system
3 *
4 * Copyright: 2011 Raumfeld GmbH
5 * Author: Johannes Stezenbach <js@sig21.net>
6 *
7 * based on code from:
8 * Wolfson Microelectronics PLC.
9 * Mark Brown <broonie@opensource.wolfsonmicro.com>
10 * Freescale Semiconductor, Inc.
11 * Timur Tabi <timur@freescale.com>
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__
20
21#include <linux/module.h>
22#include <linux/moduleparam.h>
23#include <linux/init.h>
24#include <linux/delay.h>
25#include <linux/pm.h>
26#include <linux/i2c.h>
Johannes Stezenbachc034abf2011-06-22 14:59:24 +020027#include <linux/regulator/consumer.h>
28#include <linux/slab.h>
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +010029#include <linux/workqueue.h>
Johannes Stezenbachc034abf2011-06-22 14:59:24 +020030#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/pcm_params.h>
33#include <sound/soc.h>
34#include <sound/soc-dapm.h>
35#include <sound/initval.h>
36#include <sound/tlv.h>
37
Johannes Stezenbache012ba22011-11-14 17:23:17 +010038#include <sound/sta32x.h>
Johannes Stezenbachc034abf2011-06-22 14:59:24 +020039#include "sta32x.h"
40
41#define STA32X_RATES (SNDRV_PCM_RATE_32000 | \
42 SNDRV_PCM_RATE_44100 | \
43 SNDRV_PCM_RATE_48000 | \
44 SNDRV_PCM_RATE_88200 | \
45 SNDRV_PCM_RATE_96000 | \
46 SNDRV_PCM_RATE_176400 | \
47 SNDRV_PCM_RATE_192000)
48
49#define STA32X_FORMATS \
50 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
51 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
52 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
53 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
54 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \
55 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
56
57/* Power-up register defaults */
58static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = {
59 0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60,
60 0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69,
61 0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
63 0xc0, 0xf3, 0x33, 0x00, 0x0c,
64};
65
66/* regulator power supply names */
67static const char *sta32x_supply_names[] = {
68 "Vdda", /* analog supply, 3.3VV */
69 "Vdd3", /* digital supply, 3.3V */
70 "Vcc" /* power amp spply, 10V - 36V */
71};
72
73/* codec private data */
74struct sta32x_priv {
75 struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)];
76 struct snd_soc_codec *codec;
Johannes Stezenbache012ba22011-11-14 17:23:17 +010077 struct sta32x_platform_data *pdata;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +020078
79 unsigned int mclk;
80 unsigned int format;
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +010081
82 u32 coef_shadow[STA32X_COEF_COUNT];
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +010083 struct delayed_work watchdog_work;
84 int shutdown;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +020085};
86
87static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
88static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
89static const DECLARE_TLV_DB_SCALE(tone_tlv, -120, 200, 0);
90
91static const char *sta32x_drc_ac[] = {
92 "Anti-Clipping", "Dynamic Range Compression" };
93static const char *sta32x_auto_eq_mode[] = {
94 "User", "Preset", "Loudness" };
95static const char *sta32x_auto_gc_mode[] = {
96 "User", "AC no clipping", "AC limited clipping (10%)",
97 "DRC nighttime listening mode" };
98static const char *sta32x_auto_xo_mode[] = {
99 "User", "80Hz", "100Hz", "120Hz", "140Hz", "160Hz", "180Hz", "200Hz",
100 "220Hz", "240Hz", "260Hz", "280Hz", "300Hz", "320Hz", "340Hz", "360Hz" };
101static const char *sta32x_preset_eq_mode[] = {
102 "Flat", "Rock", "Soft Rock", "Jazz", "Classical", "Dance", "Pop", "Soft",
103 "Hard", "Party", "Vocal", "Hip-Hop", "Dialog", "Bass-boost #1",
104 "Bass-boost #2", "Bass-boost #3", "Loudness 1", "Loudness 2",
105 "Loudness 3", "Loudness 4", "Loudness 5", "Loudness 6", "Loudness 7",
106 "Loudness 8", "Loudness 9", "Loudness 10", "Loudness 11", "Loudness 12",
107 "Loudness 13", "Loudness 14", "Loudness 15", "Loudness 16" };
108static const char *sta32x_limiter_select[] = {
109 "Limiter Disabled", "Limiter #1", "Limiter #2" };
110static const char *sta32x_limiter_attack_rate[] = {
111 "3.1584", "2.7072", "2.2560", "1.8048", "1.3536", "0.9024",
112 "0.4512", "0.2256", "0.1504", "0.1123", "0.0902", "0.0752",
113 "0.0645", "0.0564", "0.0501", "0.0451" };
114static const char *sta32x_limiter_release_rate[] = {
115 "0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299",
116 "0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137",
117 "0.0134", "0.0117", "0.0110", "0.0104" };
118
119static const unsigned int sta32x_limiter_ac_attack_tlv[] = {
120 TLV_DB_RANGE_HEAD(2),
121 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),
122 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0),
123};
124
125static const unsigned int sta32x_limiter_ac_release_tlv[] = {
126 TLV_DB_RANGE_HEAD(5),
127 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
128 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),
129 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),
130 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),
131 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),
132};
133
134static const unsigned int sta32x_limiter_drc_attack_tlv[] = {
135 TLV_DB_RANGE_HEAD(3),
136 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),
137 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),
138 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),
139};
140
141static const unsigned int sta32x_limiter_drc_release_tlv[] = {
142 TLV_DB_RANGE_HEAD(5),
143 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
144 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),
145 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),
146 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),
147 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
148};
149
150static const struct soc_enum sta32x_drc_ac_enum =
151 SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
152 2, sta32x_drc_ac);
153static const struct soc_enum sta32x_auto_eq_enum =
154 SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
155 3, sta32x_auto_eq_mode);
156static const struct soc_enum sta32x_auto_gc_enum =
157 SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
158 4, sta32x_auto_gc_mode);
159static const struct soc_enum sta32x_auto_xo_enum =
160 SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
161 16, sta32x_auto_xo_mode);
162static const struct soc_enum sta32x_preset_eq_enum =
163 SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
164 32, sta32x_preset_eq_mode);
165static const struct soc_enum sta32x_limiter_ch1_enum =
166 SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
167 3, sta32x_limiter_select);
168static const struct soc_enum sta32x_limiter_ch2_enum =
169 SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
170 3, sta32x_limiter_select);
171static const struct soc_enum sta32x_limiter_ch3_enum =
172 SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
173 3, sta32x_limiter_select);
174static const struct soc_enum sta32x_limiter1_attack_rate_enum =
175 SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT,
176 16, sta32x_limiter_attack_rate);
177static const struct soc_enum sta32x_limiter2_attack_rate_enum =
178 SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT,
179 16, sta32x_limiter_attack_rate);
180static const struct soc_enum sta32x_limiter1_release_rate_enum =
181 SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT,
182 16, sta32x_limiter_release_rate);
183static const struct soc_enum sta32x_limiter2_release_rate_enum =
184 SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT,
185 16, sta32x_limiter_release_rate);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200186
187/* byte array controls for setting biquad, mixer, scaling coefficients;
188 * for biquads all five coefficients need to be set in one go,
189 * mixer and pre/postscale coefs can be set individually;
190 * each coef is 24bit, the bytes are ordered in the same way
191 * as given in the STA32x data sheet (big endian; b1, b2, a1, a2, b0)
192 */
193
194static int sta32x_coefficient_info(struct snd_kcontrol *kcontrol,
195 struct snd_ctl_elem_info *uinfo)
196{
197 int numcoef = kcontrol->private_value >> 16;
198 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
199 uinfo->count = 3 * numcoef;
200 return 0;
201}
202
203static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol,
204 struct snd_ctl_elem_value *ucontrol)
205{
206 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
207 int numcoef = kcontrol->private_value >> 16;
208 int index = kcontrol->private_value & 0xffff;
209 unsigned int cfud;
210 int i;
211
212 /* preserve reserved bits in STA32X_CFUD */
213 cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
214 /* chip documentation does not say if the bits are self clearing,
215 * so do it explicitly */
216 snd_soc_write(codec, STA32X_CFUD, cfud);
217
218 snd_soc_write(codec, STA32X_CFADDR2, index);
219 if (numcoef == 1)
220 snd_soc_write(codec, STA32X_CFUD, cfud | 0x04);
221 else if (numcoef == 5)
222 snd_soc_write(codec, STA32X_CFUD, cfud | 0x08);
223 else
224 return -EINVAL;
225 for (i = 0; i < 3 * numcoef; i++)
226 ucontrol->value.bytes.data[i] =
227 snd_soc_read(codec, STA32X_B1CF1 + i);
228
229 return 0;
230}
231
232static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
233 struct snd_ctl_elem_value *ucontrol)
234{
235 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100236 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200237 int numcoef = kcontrol->private_value >> 16;
238 int index = kcontrol->private_value & 0xffff;
239 unsigned int cfud;
240 int i;
241
242 /* preserve reserved bits in STA32X_CFUD */
243 cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
244 /* chip documentation does not say if the bits are self clearing,
245 * so do it explicitly */
246 snd_soc_write(codec, STA32X_CFUD, cfud);
247
248 snd_soc_write(codec, STA32X_CFADDR2, index);
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100249 for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++)
250 sta32x->coef_shadow[index + i] =
251 (ucontrol->value.bytes.data[3 * i] << 16)
252 | (ucontrol->value.bytes.data[3 * i + 1] << 8)
253 | (ucontrol->value.bytes.data[3 * i + 2]);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200254 for (i = 0; i < 3 * numcoef; i++)
255 snd_soc_write(codec, STA32X_B1CF1 + i,
256 ucontrol->value.bytes.data[i]);
257 if (numcoef == 1)
258 snd_soc_write(codec, STA32X_CFUD, cfud | 0x01);
259 else if (numcoef == 5)
260 snd_soc_write(codec, STA32X_CFUD, cfud | 0x02);
261 else
262 return -EINVAL;
263
264 return 0;
265}
266
Mark Brown878042d2011-11-24 17:31:12 +0000267static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100268{
269 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
270 unsigned int cfud;
271 int i;
272
273 /* preserve reserved bits in STA32X_CFUD */
274 cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
275
276 for (i = 0; i < STA32X_COEF_COUNT; i++) {
277 snd_soc_write(codec, STA32X_CFADDR2, i);
278 snd_soc_write(codec, STA32X_B1CF1,
279 (sta32x->coef_shadow[i] >> 16) & 0xff);
280 snd_soc_write(codec, STA32X_B1CF2,
281 (sta32x->coef_shadow[i] >> 8) & 0xff);
282 snd_soc_write(codec, STA32X_B1CF3,
283 (sta32x->coef_shadow[i]) & 0xff);
284 /* chip documentation does not say if the bits are
285 * self-clearing, so do it explicitly */
286 snd_soc_write(codec, STA32X_CFUD, cfud);
287 snd_soc_write(codec, STA32X_CFUD, cfud | 0x01);
288 }
289 return 0;
290}
291
Mark Brown878042d2011-11-24 17:31:12 +0000292static int sta32x_cache_sync(struct snd_soc_codec *codec)
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100293{
294 unsigned int mute;
295 int rc;
296
297 if (!codec->cache_sync)
298 return 0;
299
300 /* mute during register sync */
301 mute = snd_soc_read(codec, STA32X_MMUTE);
302 snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE);
303 sta32x_sync_coef_shadow(codec);
304 rc = snd_soc_cache_sync(codec);
305 snd_soc_write(codec, STA32X_MMUTE, mute);
306 return rc;
307}
308
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100309/* work around ESD issue where sta32x resets and loses all configuration */
310static void sta32x_watchdog(struct work_struct *work)
311{
312 struct sta32x_priv *sta32x = container_of(work, struct sta32x_priv,
313 watchdog_work.work);
314 struct snd_soc_codec *codec = sta32x->codec;
315 unsigned int confa, confa_cached;
316
317 /* check if sta32x has reset itself */
318 confa_cached = snd_soc_read(codec, STA32X_CONFA);
319 codec->cache_bypass = 1;
320 confa = snd_soc_read(codec, STA32X_CONFA);
321 codec->cache_bypass = 0;
322 if (confa != confa_cached) {
323 codec->cache_sync = 1;
324 sta32x_cache_sync(codec);
325 }
326
327 if (!sta32x->shutdown)
328 schedule_delayed_work(&sta32x->watchdog_work,
329 round_jiffies_relative(HZ));
330}
331
332static void sta32x_watchdog_start(struct sta32x_priv *sta32x)
333{
334 if (sta32x->pdata->needs_esd_watchdog) {
335 sta32x->shutdown = 0;
336 schedule_delayed_work(&sta32x->watchdog_work,
337 round_jiffies_relative(HZ));
338 }
339}
340
341static void sta32x_watchdog_stop(struct sta32x_priv *sta32x)
342{
343 if (sta32x->pdata->needs_esd_watchdog) {
344 sta32x->shutdown = 1;
345 cancel_delayed_work_sync(&sta32x->watchdog_work);
346 }
347}
348
Johannes Stezenbach79688432011-07-11 17:01:23 +0200349#define SINGLE_COEF(xname, index) \
350{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
351 .info = sta32x_coefficient_info, \
352 .get = sta32x_coefficient_get,\
353 .put = sta32x_coefficient_put, \
354 .private_value = index | (1 << 16) }
355
356#define BIQUAD_COEFS(xname, index) \
357{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
358 .info = sta32x_coefficient_info, \
359 .get = sta32x_coefficient_get,\
360 .put = sta32x_coefficient_put, \
361 .private_value = index | (5 << 16) }
362
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200363static const struct snd_kcontrol_new sta32x_snd_controls[] = {
364SOC_SINGLE_TLV("Master Volume", STA32X_MVOL, 0, 0xff, 1, mvol_tlv),
365SOC_SINGLE("Master Switch", STA32X_MMUTE, 0, 1, 1),
366SOC_SINGLE("Ch1 Switch", STA32X_MMUTE, 1, 1, 1),
367SOC_SINGLE("Ch2 Switch", STA32X_MMUTE, 2, 1, 1),
368SOC_SINGLE("Ch3 Switch", STA32X_MMUTE, 3, 1, 1),
369SOC_SINGLE_TLV("Ch1 Volume", STA32X_C1VOL, 0, 0xff, 1, chvol_tlv),
370SOC_SINGLE_TLV("Ch2 Volume", STA32X_C2VOL, 0, 0xff, 1, chvol_tlv),
371SOC_SINGLE_TLV("Ch3 Volume", STA32X_C3VOL, 0, 0xff, 1, chvol_tlv),
372SOC_SINGLE("De-emphasis Filter Switch", STA32X_CONFD, STA32X_CONFD_DEMP_SHIFT, 1, 0),
373SOC_ENUM("Compressor/Limiter Switch", sta32x_drc_ac_enum),
374SOC_SINGLE("Miami Mode Switch", STA32X_CONFD, STA32X_CONFD_MME_SHIFT, 1, 0),
375SOC_SINGLE("Zero Cross Switch", STA32X_CONFE, STA32X_CONFE_ZCE_SHIFT, 1, 0),
376SOC_SINGLE("Soft Ramp Switch", STA32X_CONFE, STA32X_CONFE_SVE_SHIFT, 1, 0),
377SOC_SINGLE("Auto-Mute Switch", STA32X_CONFF, STA32X_CONFF_IDE_SHIFT, 1, 0),
378SOC_ENUM("Automode EQ", sta32x_auto_eq_enum),
379SOC_ENUM("Automode GC", sta32x_auto_gc_enum),
380SOC_ENUM("Automode XO", sta32x_auto_xo_enum),
381SOC_ENUM("Preset EQ", sta32x_preset_eq_enum),
382SOC_SINGLE("Ch1 Tone Control Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0),
383SOC_SINGLE("Ch2 Tone Control Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0),
384SOC_SINGLE("Ch1 EQ Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0),
385SOC_SINGLE("Ch2 EQ Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0),
386SOC_SINGLE("Ch1 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
387SOC_SINGLE("Ch2 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
388SOC_SINGLE("Ch3 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
389SOC_ENUM("Ch1 Limiter Select", sta32x_limiter_ch1_enum),
390SOC_ENUM("Ch2 Limiter Select", sta32x_limiter_ch2_enum),
391SOC_ENUM("Ch3 Limiter Select", sta32x_limiter_ch3_enum),
392SOC_SINGLE_TLV("Bass Tone Control", STA32X_TONE, STA32X_TONE_BTC_SHIFT, 15, 0, tone_tlv),
393SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0, tone_tlv),
394SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum),
395SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum),
396SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
397SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
398
399/* depending on mode, the attack/release thresholds have
400 * two different enum definitions; provide both
401 */
402SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT,
403 16, 0, sta32x_limiter_ac_attack_tlv),
404SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT,
405 16, 0, sta32x_limiter_ac_attack_tlv),
406SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT,
407 16, 0, sta32x_limiter_ac_release_tlv),
408SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT,
409 16, 0, sta32x_limiter_ac_release_tlv),
410SOC_SINGLE_TLV("Limiter1 Attack Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT,
411 16, 0, sta32x_limiter_drc_attack_tlv),
412SOC_SINGLE_TLV("Limiter2 Attack Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT,
413 16, 0, sta32x_limiter_drc_attack_tlv),
414SOC_SINGLE_TLV("Limiter1 Release Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT,
415 16, 0, sta32x_limiter_drc_release_tlv),
416SOC_SINGLE_TLV("Limiter2 Release Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT,
417 16, 0, sta32x_limiter_drc_release_tlv),
Johannes Stezenbach79688432011-07-11 17:01:23 +0200418
419BIQUAD_COEFS("Ch1 - Biquad 1", 0),
420BIQUAD_COEFS("Ch1 - Biquad 2", 5),
421BIQUAD_COEFS("Ch1 - Biquad 3", 10),
422BIQUAD_COEFS("Ch1 - Biquad 4", 15),
423BIQUAD_COEFS("Ch2 - Biquad 1", 20),
424BIQUAD_COEFS("Ch2 - Biquad 2", 25),
425BIQUAD_COEFS("Ch2 - Biquad 3", 30),
426BIQUAD_COEFS("Ch2 - Biquad 4", 35),
427BIQUAD_COEFS("High-pass", 40),
428BIQUAD_COEFS("Low-pass", 45),
429SINGLE_COEF("Ch1 - Prescale", 50),
430SINGLE_COEF("Ch2 - Prescale", 51),
431SINGLE_COEF("Ch1 - Postscale", 52),
432SINGLE_COEF("Ch2 - Postscale", 53),
433SINGLE_COEF("Ch3 - Postscale", 54),
434SINGLE_COEF("Thermal warning - Postscale", 55),
435SINGLE_COEF("Ch1 - Mix 1", 56),
436SINGLE_COEF("Ch1 - Mix 2", 57),
437SINGLE_COEF("Ch2 - Mix 1", 58),
438SINGLE_COEF("Ch2 - Mix 2", 59),
439SINGLE_COEF("Ch3 - Mix 1", 60),
440SINGLE_COEF("Ch3 - Mix 2", 61),
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200441};
442
443static const struct snd_soc_dapm_widget sta32x_dapm_widgets[] = {
444SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
445SND_SOC_DAPM_OUTPUT("LEFT"),
446SND_SOC_DAPM_OUTPUT("RIGHT"),
447SND_SOC_DAPM_OUTPUT("SUB"),
448};
449
450static const struct snd_soc_dapm_route sta32x_dapm_routes[] = {
451 { "LEFT", NULL, "DAC" },
452 { "RIGHT", NULL, "DAC" },
453 { "SUB", NULL, "DAC" },
454};
455
456/* MCLK interpolation ratio per fs */
457static struct {
458 int fs;
459 int ir;
460} interpolation_ratios[] = {
461 { 32000, 0 },
462 { 44100, 0 },
463 { 48000, 0 },
464 { 88200, 1 },
465 { 96000, 1 },
466 { 176400, 2 },
467 { 192000, 2 },
468};
469
470/* MCLK to fs clock ratios */
471static struct {
472 int ratio;
473 int mcs;
474} mclk_ratios[3][7] = {
475 { { 768, 0 }, { 512, 1 }, { 384, 2 }, { 256, 3 },
476 { 128, 4 }, { 576, 5 }, { 0, 0 } },
477 { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } },
478 { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } },
479};
480
481
482/**
483 * sta32x_set_dai_sysclk - configure MCLK
484 * @codec_dai: the codec DAI
485 * @clk_id: the clock ID (ignored)
486 * @freq: the MCLK input frequency
487 * @dir: the clock direction (ignored)
488 *
489 * The value of MCLK is used to determine which sample rates are supported
490 * by the STA32X, based on the mclk_ratios table.
491 *
492 * This function must be called by the machine driver's 'startup' function,
493 * otherwise the list of supported sample rates will not be available in
494 * time for ALSA.
495 *
496 * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause
497 * theoretically possible sample rates to be enabled. Call it again with a
498 * proper value set one the external clock is set (most probably you would do
499 * that from a machine's driver 'hw_param' hook.
500 */
501static int sta32x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
502 int clk_id, unsigned int freq, int dir)
503{
504 struct snd_soc_codec *codec = codec_dai->codec;
505 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
506 int i, j, ir, fs;
507 unsigned int rates = 0;
508 unsigned int rate_min = -1;
509 unsigned int rate_max = 0;
510
511 pr_debug("mclk=%u\n", freq);
512 sta32x->mclk = freq;
513
514 if (sta32x->mclk) {
515 for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) {
516 ir = interpolation_ratios[i].ir;
517 fs = interpolation_ratios[i].fs;
518 for (j = 0; mclk_ratios[ir][j].ratio; j++) {
519 if (mclk_ratios[ir][j].ratio * fs == freq) {
520 rates |= snd_pcm_rate_to_rate_bit(fs);
521 if (fs < rate_min)
522 rate_min = fs;
523 if (fs > rate_max)
524 rate_max = fs;
525 }
526 }
527 }
528 /* FIXME: soc should support a rate list */
529 rates &= ~SNDRV_PCM_RATE_KNOT;
530
531 if (!rates) {
532 dev_err(codec->dev, "could not find a valid sample rate\n");
533 return -EINVAL;
534 }
535 } else {
536 /* enable all possible rates */
537 rates = STA32X_RATES;
538 rate_min = 32000;
539 rate_max = 192000;
540 }
541
542 codec_dai->driver->playback.rates = rates;
543 codec_dai->driver->playback.rate_min = rate_min;
544 codec_dai->driver->playback.rate_max = rate_max;
545 return 0;
546}
547
548/**
549 * sta32x_set_dai_fmt - configure the codec for the selected audio format
550 * @codec_dai: the codec DAI
551 * @fmt: a SND_SOC_DAIFMT_x value indicating the data format
552 *
553 * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
554 * codec accordingly.
555 */
556static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai,
557 unsigned int fmt)
558{
559 struct snd_soc_codec *codec = codec_dai->codec;
560 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
561 u8 confb = snd_soc_read(codec, STA32X_CONFB);
562
563 pr_debug("\n");
564 confb &= ~(STA32X_CONFB_C1IM | STA32X_CONFB_C2IM);
565
566 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
567 case SND_SOC_DAIFMT_CBS_CFS:
568 break;
569 default:
570 return -EINVAL;
571 }
572
573 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
574 case SND_SOC_DAIFMT_I2S:
575 case SND_SOC_DAIFMT_RIGHT_J:
576 case SND_SOC_DAIFMT_LEFT_J:
577 sta32x->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
578 break;
579 default:
580 return -EINVAL;
581 }
582
583 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
584 case SND_SOC_DAIFMT_NB_NF:
585 confb |= STA32X_CONFB_C2IM;
586 break;
587 case SND_SOC_DAIFMT_NB_IF:
588 confb |= STA32X_CONFB_C1IM;
589 break;
590 default:
591 return -EINVAL;
592 }
593
594 snd_soc_write(codec, STA32X_CONFB, confb);
595 return 0;
596}
597
598/**
599 * sta32x_hw_params - program the STA32X with the given hardware parameters.
600 * @substream: the audio stream
601 * @params: the hardware parameters to set
602 * @dai: the SOC DAI (ignored)
603 *
604 * This function programs the hardware with the values provided.
605 * Specifically, the sample rate and the data format.
606 */
607static int sta32x_hw_params(struct snd_pcm_substream *substream,
608 struct snd_pcm_hw_params *params,
609 struct snd_soc_dai *dai)
610{
611 struct snd_soc_pcm_runtime *rtd = substream->private_data;
612 struct snd_soc_codec *codec = rtd->codec;
613 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
614 unsigned int rate;
615 int i, mcs = -1, ir = -1;
616 u8 confa, confb;
617
618 rate = params_rate(params);
619 pr_debug("rate: %u\n", rate);
620 for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++)
Axel Lina5952382011-08-14 11:31:04 +0800621 if (interpolation_ratios[i].fs == rate) {
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200622 ir = interpolation_ratios[i].ir;
Axel Lina5952382011-08-14 11:31:04 +0800623 break;
624 }
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200625 if (ir < 0)
626 return -EINVAL;
627 for (i = 0; mclk_ratios[ir][i].ratio; i++)
Axel Lina5952382011-08-14 11:31:04 +0800628 if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) {
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200629 mcs = mclk_ratios[ir][i].mcs;
Axel Lina5952382011-08-14 11:31:04 +0800630 break;
631 }
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200632 if (mcs < 0)
633 return -EINVAL;
634
635 confa = snd_soc_read(codec, STA32X_CONFA);
636 confa &= ~(STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK);
637 confa |= (ir << STA32X_CONFA_IR_SHIFT) | (mcs << STA32X_CONFA_MCS_SHIFT);
638
639 confb = snd_soc_read(codec, STA32X_CONFB);
640 confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB);
641 switch (params_format(params)) {
642 case SNDRV_PCM_FORMAT_S24_LE:
643 case SNDRV_PCM_FORMAT_S24_BE:
644 case SNDRV_PCM_FORMAT_S24_3LE:
645 case SNDRV_PCM_FORMAT_S24_3BE:
646 pr_debug("24bit\n");
647 /* fall through */
648 case SNDRV_PCM_FORMAT_S32_LE:
649 case SNDRV_PCM_FORMAT_S32_BE:
650 pr_debug("24bit or 32bit\n");
651 switch (sta32x->format) {
652 case SND_SOC_DAIFMT_I2S:
653 confb |= 0x0;
654 break;
655 case SND_SOC_DAIFMT_LEFT_J:
656 confb |= 0x1;
657 break;
658 case SND_SOC_DAIFMT_RIGHT_J:
659 confb |= 0x2;
660 break;
661 }
662
663 break;
664 case SNDRV_PCM_FORMAT_S20_3LE:
665 case SNDRV_PCM_FORMAT_S20_3BE:
666 pr_debug("20bit\n");
667 switch (sta32x->format) {
668 case SND_SOC_DAIFMT_I2S:
669 confb |= 0x4;
670 break;
671 case SND_SOC_DAIFMT_LEFT_J:
672 confb |= 0x5;
673 break;
674 case SND_SOC_DAIFMT_RIGHT_J:
675 confb |= 0x6;
676 break;
677 }
678
679 break;
680 case SNDRV_PCM_FORMAT_S18_3LE:
681 case SNDRV_PCM_FORMAT_S18_3BE:
682 pr_debug("18bit\n");
683 switch (sta32x->format) {
684 case SND_SOC_DAIFMT_I2S:
685 confb |= 0x8;
686 break;
687 case SND_SOC_DAIFMT_LEFT_J:
688 confb |= 0x9;
689 break;
690 case SND_SOC_DAIFMT_RIGHT_J:
691 confb |= 0xa;
692 break;
693 }
694
695 break;
696 case SNDRV_PCM_FORMAT_S16_LE:
697 case SNDRV_PCM_FORMAT_S16_BE:
698 pr_debug("16bit\n");
699 switch (sta32x->format) {
700 case SND_SOC_DAIFMT_I2S:
701 confb |= 0x0;
702 break;
703 case SND_SOC_DAIFMT_LEFT_J:
704 confb |= 0xd;
705 break;
706 case SND_SOC_DAIFMT_RIGHT_J:
707 confb |= 0xe;
708 break;
709 }
710
711 break;
712 default:
713 return -EINVAL;
714 }
715
716 snd_soc_write(codec, STA32X_CONFA, confa);
717 snd_soc_write(codec, STA32X_CONFB, confb);
718 return 0;
719}
720
721/**
722 * sta32x_set_bias_level - DAPM callback
723 * @codec: the codec device
724 * @level: DAPM power level
725 *
726 * This is called by ALSA to put the codec into low power mode
727 * or to wake it up. If the codec is powered off completely
728 * all registers must be restored after power on.
729 */
730static int sta32x_set_bias_level(struct snd_soc_codec *codec,
731 enum snd_soc_bias_level level)
732{
733 int ret;
734 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
735
736 pr_debug("level = %d\n", level);
737 switch (level) {
738 case SND_SOC_BIAS_ON:
739 break;
740
741 case SND_SOC_BIAS_PREPARE:
742 /* Full power on */
743 snd_soc_update_bits(codec, STA32X_CONFF,
744 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
745 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD);
746 break;
747
748 case SND_SOC_BIAS_STANDBY:
749 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
750 ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
751 sta32x->supplies);
752 if (ret != 0) {
753 dev_err(codec->dev,
754 "Failed to enable supplies: %d\n", ret);
755 return ret;
756 }
757
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100758 sta32x_cache_sync(codec);
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100759 sta32x_watchdog_start(sta32x);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200760 }
761
762 /* Power up to mute */
763 /* FIXME */
764 snd_soc_update_bits(codec, STA32X_CONFF,
765 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
766 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD);
767
768 break;
769
770 case SND_SOC_BIAS_OFF:
771 /* The chip runs through the power down sequence for us. */
772 snd_soc_update_bits(codec, STA32X_CONFF,
773 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
774 STA32X_CONFF_PWDN);
775 msleep(300);
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100776 sta32x_watchdog_stop(sta32x);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200777 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies),
778 sta32x->supplies);
779 break;
780 }
781 codec->dapm.bias_level = level;
782 return 0;
783}
784
Lars-Peter Clausen85e76522011-11-23 11:40:40 +0100785static const struct snd_soc_dai_ops sta32x_dai_ops = {
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200786 .hw_params = sta32x_hw_params,
787 .set_sysclk = sta32x_set_dai_sysclk,
788 .set_fmt = sta32x_set_dai_fmt,
789};
790
791static struct snd_soc_dai_driver sta32x_dai = {
792 .name = "STA32X",
793 .playback = {
794 .stream_name = "Playback",
795 .channels_min = 2,
796 .channels_max = 2,
797 .rates = STA32X_RATES,
798 .formats = STA32X_FORMATS,
799 },
800 .ops = &sta32x_dai_ops,
801};
802
803#ifdef CONFIG_PM
Lars-Peter Clausen84b315e2011-12-02 10:18:28 +0100804static int sta32x_suspend(struct snd_soc_codec *codec)
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200805{
806 sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
807 return 0;
808}
809
810static int sta32x_resume(struct snd_soc_codec *codec)
811{
812 sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
813 return 0;
814}
815#else
816#define sta32x_suspend NULL
817#define sta32x_resume NULL
818#endif
819
820static int sta32x_probe(struct snd_soc_codec *codec)
821{
822 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100823 int i, ret = 0, thermal = 0;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200824
825 sta32x->codec = codec;
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100826 sta32x->pdata = dev_get_platdata(codec->dev);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200827
828 /* regulators */
829 for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++)
830 sta32x->supplies[i].supply = sta32x_supply_names[i];
831
832 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies),
833 sta32x->supplies);
834 if (ret != 0) {
835 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
836 goto err;
837 }
838
839 ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
840 sta32x->supplies);
841 if (ret != 0) {
842 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
843 goto err_get;
844 }
845
846 /* Tell ASoC what kind of I/O to use to read the registers. ASoC will
847 * then do the I2C transactions itself.
848 */
849 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
850 if (ret < 0) {
851 dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret);
852 return ret;
853 }
854
Axel Linedf413f2011-10-13 14:57:31 +0800855 /* Chip documentation explicitly requires that the reset values
856 * of reserved register bits are left untouched.
857 * Write the register default value to cache for reserved registers,
858 * so the write to the these registers are suppressed by the cache
859 * restore code when it skips writes of default registers.
860 */
861 snd_soc_cache_write(codec, STA32X_CONFC, 0xc2);
862 snd_soc_cache_write(codec, STA32X_CONFE, 0xc2);
863 snd_soc_cache_write(codec, STA32X_CONFF, 0x5c);
864 snd_soc_cache_write(codec, STA32X_MMUTE, 0x10);
865 snd_soc_cache_write(codec, STA32X_AUTO1, 0x60);
866 snd_soc_cache_write(codec, STA32X_AUTO3, 0x00);
867 snd_soc_cache_write(codec, STA32X_C3CFG, 0x40);
Johannes Stezenbach889ebae2011-07-11 17:01:24 +0200868
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100869 /* set thermal warning adjustment and recovery */
870 if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE))
871 thermal |= STA32X_CONFA_TWAB;
872 if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_RECOVERY_ENABLE))
873 thermal |= STA32X_CONFA_TWRB;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200874 snd_soc_update_bits(codec, STA32X_CONFA,
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100875 STA32X_CONFA_TWAB | STA32X_CONFA_TWRB,
876 thermal);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200877
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100878 /* select output configuration */
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200879 snd_soc_update_bits(codec, STA32X_CONFF,
880 STA32X_CONFF_OCFG_MASK,
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100881 sta32x->pdata->output_conf
882 << STA32X_CONFF_OCFG_SHIFT);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200883
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100884 /* channel to output mapping */
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200885 snd_soc_update_bits(codec, STA32X_C1CFG,
886 STA32X_CxCFG_OM_MASK,
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100887 sta32x->pdata->ch1_output_mapping
888 << STA32X_CxCFG_OM_SHIFT);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200889 snd_soc_update_bits(codec, STA32X_C2CFG,
890 STA32X_CxCFG_OM_MASK,
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100891 sta32x->pdata->ch2_output_mapping
892 << STA32X_CxCFG_OM_SHIFT);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200893 snd_soc_update_bits(codec, STA32X_C3CFG,
894 STA32X_CxCFG_OM_MASK,
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100895 sta32x->pdata->ch3_output_mapping
896 << STA32X_CxCFG_OM_SHIFT);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200897
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100898 /* initialize coefficient shadow RAM with reset values */
899 for (i = 4; i <= 49; i += 5)
900 sta32x->coef_shadow[i] = 0x400000;
901 for (i = 50; i <= 54; i++)
902 sta32x->coef_shadow[i] = 0x7fffff;
903 sta32x->coef_shadow[55] = 0x5a9df7;
904 sta32x->coef_shadow[56] = 0x7fffff;
905 sta32x->coef_shadow[59] = 0x7fffff;
906 sta32x->coef_shadow[60] = 0x400000;
907 sta32x->coef_shadow[61] = 0x400000;
908
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100909 if (sta32x->pdata->needs_esd_watchdog)
910 INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog);
911
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200912 sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
913 /* Bias level configuration will have done an extra enable */
914 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
915
916 return 0;
917
918err_get:
919 regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
920err:
921 return ret;
922}
923
924static int sta32x_remove(struct snd_soc_codec *codec)
925{
926 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
927
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100928 sta32x_watchdog_stop(sta32x);
Axel Line3d73c12011-08-18 15:31:04 +0800929 sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200930 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
931 regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
932
933 return 0;
934}
935
Johannes Stezenbach79688432011-07-11 17:01:23 +0200936static int sta32x_reg_is_volatile(struct snd_soc_codec *codec,
937 unsigned int reg)
938{
939 switch (reg) {
940 case STA32X_CONFA ... STA32X_L2ATRT:
941 case STA32X_MPCC1 ... STA32X_FDRC2:
942 return 0;
943 }
944 return 1;
945}
946
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200947static const struct snd_soc_codec_driver sta32x_codec = {
948 .probe = sta32x_probe,
949 .remove = sta32x_remove,
950 .suspend = sta32x_suspend,
951 .resume = sta32x_resume,
952 .reg_cache_size = STA32X_REGISTER_COUNT,
953 .reg_word_size = sizeof(u8),
Axel Linf0bbc2b2011-10-13 14:40:08 +0800954 .reg_cache_default = sta32x_regs,
Johannes Stezenbach79688432011-07-11 17:01:23 +0200955 .volatile_register = sta32x_reg_is_volatile,
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200956 .set_bias_level = sta32x_set_bias_level,
957 .controls = sta32x_snd_controls,
958 .num_controls = ARRAY_SIZE(sta32x_snd_controls),
959 .dapm_widgets = sta32x_dapm_widgets,
960 .num_dapm_widgets = ARRAY_SIZE(sta32x_dapm_widgets),
961 .dapm_routes = sta32x_dapm_routes,
962 .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes),
963};
964
965static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
966 const struct i2c_device_id *id)
967{
968 struct sta32x_priv *sta32x;
969 int ret;
970
971 sta32x = kzalloc(sizeof(struct sta32x_priv), GFP_KERNEL);
972 if (!sta32x)
973 return -ENOMEM;
974
975 i2c_set_clientdata(i2c, sta32x);
976
977 ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1);
978 if (ret != 0) {
979 dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret);
Axel Lin161d55c2011-08-13 11:33:08 +0800980 kfree(sta32x);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200981 return ret;
982 }
983
984 return 0;
985}
986
987static __devexit int sta32x_i2c_remove(struct i2c_client *client)
988{
989 struct sta32x_priv *sta32x = i2c_get_clientdata(client);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200990
Axel Line3d73c12011-08-18 15:31:04 +0800991 snd_soc_unregister_codec(&client->dev);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200992 kfree(sta32x);
993 return 0;
994}
995
996static const struct i2c_device_id sta32x_i2c_id[] = {
997 { "sta326", 0 },
998 { "sta328", 0 },
999 { "sta329", 0 },
1000 { }
1001};
1002MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id);
1003
1004static struct i2c_driver sta32x_i2c_driver = {
1005 .driver = {
1006 .name = "sta32x",
1007 .owner = THIS_MODULE,
1008 },
1009 .probe = sta32x_i2c_probe,
1010 .remove = __devexit_p(sta32x_i2c_remove),
1011 .id_table = sta32x_i2c_id,
1012};
1013
1014static int __init sta32x_init(void)
1015{
1016 return i2c_add_driver(&sta32x_i2c_driver);
1017}
1018module_init(sta32x_init);
1019
1020static void __exit sta32x_exit(void)
1021{
1022 i2c_del_driver(&sta32x_i2c_driver);
1023}
1024module_exit(sta32x_exit);
1025
1026MODULE_DESCRIPTION("ASoC STA32X driver");
1027MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>");
1028MODULE_LICENSE("GPL");