blob: 4517453b33b6cb5e0e5a9e29eb94d49816f64aa1 [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>
Mark Brown29fdf4f2012-09-10 10:59:56 +080027#include <linux/regmap.h>
Johannes Stezenbachc034abf2011-06-22 14:59:24 +020028#include <linux/regulator/consumer.h>
29#include <linux/slab.h>
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +010030#include <linux/workqueue.h>
Johannes Stezenbachc034abf2011-06-22 14:59:24 +020031#include <sound/core.h>
32#include <sound/pcm.h>
33#include <sound/pcm_params.h>
34#include <sound/soc.h>
35#include <sound/soc-dapm.h>
36#include <sound/initval.h>
37#include <sound/tlv.h>
38
Johannes Stezenbache012ba22011-11-14 17:23:17 +010039#include <sound/sta32x.h>
Johannes Stezenbachc034abf2011-06-22 14:59:24 +020040#include "sta32x.h"
41
42#define STA32X_RATES (SNDRV_PCM_RATE_32000 | \
43 SNDRV_PCM_RATE_44100 | \
44 SNDRV_PCM_RATE_48000 | \
45 SNDRV_PCM_RATE_88200 | \
46 SNDRV_PCM_RATE_96000 | \
47 SNDRV_PCM_RATE_176400 | \
48 SNDRV_PCM_RATE_192000)
49
50#define STA32X_FORMATS \
51 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
52 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
53 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
54 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
55 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \
56 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
57
58/* Power-up register defaults */
Mark Brown29fdf4f2012-09-10 10:59:56 +080059static const struct reg_default sta32x_regs[] = {
60 { 0x0, 0x63 },
61 { 0x1, 0x80 },
62 { 0x2, 0xc2 },
63 { 0x3, 0x40 },
64 { 0x4, 0xc2 },
65 { 0x5, 0x5c },
66 { 0x6, 0x10 },
67 { 0x7, 0xff },
68 { 0x8, 0x60 },
69 { 0x9, 0x60 },
70 { 0xa, 0x60 },
71 { 0xb, 0x80 },
72 { 0xc, 0x00 },
73 { 0xd, 0x00 },
74 { 0xe, 0x00 },
75 { 0xf, 0x40 },
76 { 0x10, 0x80 },
77 { 0x11, 0x77 },
78 { 0x12, 0x6a },
79 { 0x13, 0x69 },
80 { 0x14, 0x6a },
81 { 0x15, 0x69 },
82 { 0x16, 0x00 },
83 { 0x17, 0x00 },
84 { 0x18, 0x00 },
85 { 0x19, 0x00 },
86 { 0x1a, 0x00 },
87 { 0x1b, 0x00 },
88 { 0x1c, 0x00 },
89 { 0x1d, 0x00 },
90 { 0x1e, 0x00 },
91 { 0x1f, 0x00 },
92 { 0x20, 0x00 },
93 { 0x21, 0x00 },
94 { 0x22, 0x00 },
95 { 0x23, 0x00 },
96 { 0x24, 0x00 },
97 { 0x25, 0x00 },
98 { 0x26, 0x00 },
99 { 0x27, 0x2d },
100 { 0x28, 0xc0 },
101 { 0x2b, 0x00 },
102 { 0x2c, 0x0c },
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200103};
104
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100105static const struct regmap_range sta32x_write_regs_range[] = {
106 regmap_reg_range(STA32X_CONFA, STA32X_AUTO2),
107 regmap_reg_range(STA32X_C1CFG, STA32X_FDRC2),
108};
109
110static const struct regmap_range sta32x_read_regs_range[] = {
111 regmap_reg_range(STA32X_CONFA, STA32X_AUTO2),
112 regmap_reg_range(STA32X_C1CFG, STA32X_FDRC2),
113};
114
115static const struct regmap_range sta32x_volatile_regs_range[] = {
116 regmap_reg_range(STA32X_CFADDR2, STA32X_CFUD),
117};
118
119static const struct regmap_access_table sta32x_write_regs = {
120 .yes_ranges = sta32x_write_regs_range,
121 .n_yes_ranges = ARRAY_SIZE(sta32x_write_regs_range),
122};
123
124static const struct regmap_access_table sta32x_read_regs = {
125 .yes_ranges = sta32x_read_regs_range,
126 .n_yes_ranges = ARRAY_SIZE(sta32x_read_regs_range),
127};
128
129static const struct regmap_access_table sta32x_volatile_regs = {
130 .yes_ranges = sta32x_volatile_regs_range,
131 .n_yes_ranges = ARRAY_SIZE(sta32x_volatile_regs_range),
132};
133
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200134/* regulator power supply names */
135static const char *sta32x_supply_names[] = {
136 "Vdda", /* analog supply, 3.3VV */
137 "Vdd3", /* digital supply, 3.3V */
138 "Vcc" /* power amp spply, 10V - 36V */
139};
140
141/* codec private data */
142struct sta32x_priv {
Mark Brown29fdf4f2012-09-10 10:59:56 +0800143 struct regmap *regmap;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200144 struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)];
145 struct snd_soc_codec *codec;
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100146 struct sta32x_platform_data *pdata;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200147
148 unsigned int mclk;
149 unsigned int format;
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100150
151 u32 coef_shadow[STA32X_COEF_COUNT];
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100152 struct delayed_work watchdog_work;
153 int shutdown;
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100154 struct mutex coeff_lock;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200155};
156
157static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
158static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
159static const DECLARE_TLV_DB_SCALE(tone_tlv, -120, 200, 0);
160
161static const char *sta32x_drc_ac[] = {
162 "Anti-Clipping", "Dynamic Range Compression" };
163static const char *sta32x_auto_eq_mode[] = {
164 "User", "Preset", "Loudness" };
165static const char *sta32x_auto_gc_mode[] = {
166 "User", "AC no clipping", "AC limited clipping (10%)",
167 "DRC nighttime listening mode" };
168static const char *sta32x_auto_xo_mode[] = {
169 "User", "80Hz", "100Hz", "120Hz", "140Hz", "160Hz", "180Hz", "200Hz",
170 "220Hz", "240Hz", "260Hz", "280Hz", "300Hz", "320Hz", "340Hz", "360Hz" };
171static const char *sta32x_preset_eq_mode[] = {
172 "Flat", "Rock", "Soft Rock", "Jazz", "Classical", "Dance", "Pop", "Soft",
173 "Hard", "Party", "Vocal", "Hip-Hop", "Dialog", "Bass-boost #1",
174 "Bass-boost #2", "Bass-boost #3", "Loudness 1", "Loudness 2",
175 "Loudness 3", "Loudness 4", "Loudness 5", "Loudness 6", "Loudness 7",
176 "Loudness 8", "Loudness 9", "Loudness 10", "Loudness 11", "Loudness 12",
177 "Loudness 13", "Loudness 14", "Loudness 15", "Loudness 16" };
178static const char *sta32x_limiter_select[] = {
179 "Limiter Disabled", "Limiter #1", "Limiter #2" };
180static const char *sta32x_limiter_attack_rate[] = {
181 "3.1584", "2.7072", "2.2560", "1.8048", "1.3536", "0.9024",
182 "0.4512", "0.2256", "0.1504", "0.1123", "0.0902", "0.0752",
183 "0.0645", "0.0564", "0.0501", "0.0451" };
184static const char *sta32x_limiter_release_rate[] = {
185 "0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299",
186 "0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137",
187 "0.0134", "0.0117", "0.0110", "0.0104" };
188
189static const unsigned int sta32x_limiter_ac_attack_tlv[] = {
190 TLV_DB_RANGE_HEAD(2),
191 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),
192 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0),
193};
194
195static const unsigned int sta32x_limiter_ac_release_tlv[] = {
196 TLV_DB_RANGE_HEAD(5),
197 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
198 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),
199 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),
200 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),
201 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),
202};
203
204static const unsigned int sta32x_limiter_drc_attack_tlv[] = {
205 TLV_DB_RANGE_HEAD(3),
206 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),
207 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),
208 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),
209};
210
211static const unsigned int sta32x_limiter_drc_release_tlv[] = {
212 TLV_DB_RANGE_HEAD(5),
213 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
214 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),
215 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),
216 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),
217 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
218};
219
Takashi Iwai025c3fa2014-02-18 09:24:12 +0100220static SOC_ENUM_SINGLE_DECL(sta32x_drc_ac_enum,
221 STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
222 sta32x_drc_ac);
223static SOC_ENUM_SINGLE_DECL(sta32x_auto_eq_enum,
224 STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
225 sta32x_auto_eq_mode);
226static SOC_ENUM_SINGLE_DECL(sta32x_auto_gc_enum,
227 STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
228 sta32x_auto_gc_mode);
229static SOC_ENUM_SINGLE_DECL(sta32x_auto_xo_enum,
230 STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
231 sta32x_auto_xo_mode);
232static SOC_ENUM_SINGLE_DECL(sta32x_preset_eq_enum,
233 STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
234 sta32x_preset_eq_mode);
235static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch1_enum,
236 STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
237 sta32x_limiter_select);
238static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch2_enum,
239 STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
240 sta32x_limiter_select);
241static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch3_enum,
242 STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
243 sta32x_limiter_select);
244static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_attack_rate_enum,
245 STA32X_L1AR, STA32X_LxA_SHIFT,
246 sta32x_limiter_attack_rate);
247static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_attack_rate_enum,
248 STA32X_L2AR, STA32X_LxA_SHIFT,
249 sta32x_limiter_attack_rate);
250static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_release_rate_enum,
251 STA32X_L1AR, STA32X_LxR_SHIFT,
252 sta32x_limiter_release_rate);
253static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_release_rate_enum,
254 STA32X_L2AR, STA32X_LxR_SHIFT,
255 sta32x_limiter_release_rate);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200256
257/* byte array controls for setting biquad, mixer, scaling coefficients;
258 * for biquads all five coefficients need to be set in one go,
259 * mixer and pre/postscale coefs can be set individually;
260 * each coef is 24bit, the bytes are ordered in the same way
261 * as given in the STA32x data sheet (big endian; b1, b2, a1, a2, b0)
262 */
263
264static int sta32x_coefficient_info(struct snd_kcontrol *kcontrol,
265 struct snd_ctl_elem_info *uinfo)
266{
267 int numcoef = kcontrol->private_value >> 16;
268 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
269 uinfo->count = 3 * numcoef;
270 return 0;
271}
272
273static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol,
274 struct snd_ctl_elem_value *ucontrol)
275{
Lars-Peter Clausenea53bf72014-03-18 09:02:04 +0100276 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100277 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200278 int numcoef = kcontrol->private_value >> 16;
279 int index = kcontrol->private_value & 0xffff;
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100280 unsigned int cfud, val;
281 int i, ret = 0;
282
283 mutex_lock(&sta32x->coeff_lock);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200284
285 /* preserve reserved bits in STA32X_CFUD */
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100286 regmap_read(sta32x->regmap, STA32X_CFUD, &cfud);
287 cfud &= 0xf0;
288 /*
289 * chip documentation does not say if the bits are self clearing,
290 * so do it explicitly
291 */
292 regmap_write(sta32x->regmap, STA32X_CFUD, cfud);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200293
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100294 regmap_write(sta32x->regmap, STA32X_CFADDR2, index);
295 if (numcoef == 1) {
296 regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x04);
297 } else if (numcoef == 5) {
298 regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x08);
299 } else {
300 ret = -EINVAL;
301 goto exit_unlock;
302 }
Johannes Stezenbach79688432011-07-11 17:01:23 +0200303
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100304 for (i = 0; i < 3 * numcoef; i++) {
305 regmap_read(sta32x->regmap, STA32X_B1CF1 + i, &val);
306 ucontrol->value.bytes.data[i] = val;
307 }
308
309exit_unlock:
310 mutex_unlock(&sta32x->coeff_lock);
311
312 return ret;
Johannes Stezenbach79688432011-07-11 17:01:23 +0200313}
314
315static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
316 struct snd_ctl_elem_value *ucontrol)
317{
Lars-Peter Clausenea53bf72014-03-18 09:02:04 +0100318 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100319 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200320 int numcoef = kcontrol->private_value >> 16;
321 int index = kcontrol->private_value & 0xffff;
322 unsigned int cfud;
323 int i;
324
325 /* preserve reserved bits in STA32X_CFUD */
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100326 regmap_read(sta32x->regmap, STA32X_CFUD, &cfud);
327 cfud &= 0xf0;
328 /*
329 * chip documentation does not say if the bits are self clearing,
330 * so do it explicitly
331 */
332 regmap_write(sta32x->regmap, STA32X_CFUD, cfud);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200333
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100334 regmap_write(sta32x->regmap, STA32X_CFADDR2, index);
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100335 for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++)
336 sta32x->coef_shadow[index + i] =
337 (ucontrol->value.bytes.data[3 * i] << 16)
338 | (ucontrol->value.bytes.data[3 * i + 1] << 8)
339 | (ucontrol->value.bytes.data[3 * i + 2]);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200340 for (i = 0; i < 3 * numcoef; i++)
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100341 regmap_write(sta32x->regmap, STA32X_B1CF1 + i,
342 ucontrol->value.bytes.data[i]);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200343 if (numcoef == 1)
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100344 regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x01);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200345 else if (numcoef == 5)
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100346 regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x02);
Johannes Stezenbach79688432011-07-11 17:01:23 +0200347 else
348 return -EINVAL;
349
350 return 0;
351}
352
Mark Brown878042d2011-11-24 17:31:12 +0000353static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100354{
355 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
356 unsigned int cfud;
357 int i;
358
359 /* preserve reserved bits in STA32X_CFUD */
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100360 regmap_read(sta32x->regmap, STA32X_CFUD, &cfud);
361 cfud &= 0xf0;
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100362
363 for (i = 0; i < STA32X_COEF_COUNT; i++) {
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100364 regmap_write(sta32x->regmap, STA32X_CFADDR2, i);
365 regmap_write(sta32x->regmap, STA32X_B1CF1,
366 (sta32x->coef_shadow[i] >> 16) & 0xff);
367 regmap_write(sta32x->regmap, STA32X_B1CF2,
368 (sta32x->coef_shadow[i] >> 8) & 0xff);
369 regmap_write(sta32x->regmap, STA32X_B1CF3,
370 (sta32x->coef_shadow[i]) & 0xff);
371 /*
372 * chip documentation does not say if the bits are
373 * self-clearing, so do it explicitly
374 */
375 regmap_write(sta32x->regmap, STA32X_CFUD, cfud);
376 regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x01);
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100377 }
378 return 0;
379}
380
Mark Brown878042d2011-11-24 17:31:12 +0000381static int sta32x_cache_sync(struct snd_soc_codec *codec)
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100382{
Lars-Peter Clausen70ff00f2014-02-22 18:27:17 +0100383 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100384 unsigned int mute;
385 int rc;
386
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100387 /* mute during register sync */
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100388 regmap_read(sta32x->regmap, STA32X_MMUTE, &mute);
389 regmap_write(sta32x->regmap, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE);
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100390 sta32x_sync_coef_shadow(codec);
Mark Brown29fdf4f2012-09-10 10:59:56 +0800391 rc = regcache_sync(sta32x->regmap);
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100392 regmap_write(sta32x->regmap, STA32X_MMUTE, mute);
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100393 return rc;
394}
395
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100396/* work around ESD issue where sta32x resets and loses all configuration */
397static void sta32x_watchdog(struct work_struct *work)
398{
399 struct sta32x_priv *sta32x = container_of(work, struct sta32x_priv,
400 watchdog_work.work);
401 struct snd_soc_codec *codec = sta32x->codec;
402 unsigned int confa, confa_cached;
403
404 /* check if sta32x has reset itself */
405 confa_cached = snd_soc_read(codec, STA32X_CONFA);
Mark Brown29fdf4f2012-09-10 10:59:56 +0800406 regcache_cache_bypass(sta32x->regmap, true);
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100407 confa = snd_soc_read(codec, STA32X_CONFA);
Mark Brown29fdf4f2012-09-10 10:59:56 +0800408 regcache_cache_bypass(sta32x->regmap, false);
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100409 if (confa != confa_cached) {
Mark Brown29fdf4f2012-09-10 10:59:56 +0800410 regcache_mark_dirty(sta32x->regmap);
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100411 sta32x_cache_sync(codec);
412 }
413
414 if (!sta32x->shutdown)
Mark Browna14d9822013-07-18 22:43:19 +0100415 queue_delayed_work(system_power_efficient_wq,
416 &sta32x->watchdog_work,
417 round_jiffies_relative(HZ));
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100418}
419
420static void sta32x_watchdog_start(struct sta32x_priv *sta32x)
421{
422 if (sta32x->pdata->needs_esd_watchdog) {
423 sta32x->shutdown = 0;
Mark Browna14d9822013-07-18 22:43:19 +0100424 queue_delayed_work(system_power_efficient_wq,
425 &sta32x->watchdog_work,
426 round_jiffies_relative(HZ));
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100427 }
428}
429
430static void sta32x_watchdog_stop(struct sta32x_priv *sta32x)
431{
432 if (sta32x->pdata->needs_esd_watchdog) {
433 sta32x->shutdown = 1;
434 cancel_delayed_work_sync(&sta32x->watchdog_work);
435 }
436}
437
Johannes Stezenbach79688432011-07-11 17:01:23 +0200438#define SINGLE_COEF(xname, index) \
439{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
440 .info = sta32x_coefficient_info, \
441 .get = sta32x_coefficient_get,\
442 .put = sta32x_coefficient_put, \
443 .private_value = index | (1 << 16) }
444
445#define BIQUAD_COEFS(xname, index) \
446{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
447 .info = sta32x_coefficient_info, \
448 .get = sta32x_coefficient_get,\
449 .put = sta32x_coefficient_put, \
450 .private_value = index | (5 << 16) }
451
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200452static const struct snd_kcontrol_new sta32x_snd_controls[] = {
453SOC_SINGLE_TLV("Master Volume", STA32X_MVOL, 0, 0xff, 1, mvol_tlv),
454SOC_SINGLE("Master Switch", STA32X_MMUTE, 0, 1, 1),
455SOC_SINGLE("Ch1 Switch", STA32X_MMUTE, 1, 1, 1),
456SOC_SINGLE("Ch2 Switch", STA32X_MMUTE, 2, 1, 1),
457SOC_SINGLE("Ch3 Switch", STA32X_MMUTE, 3, 1, 1),
458SOC_SINGLE_TLV("Ch1 Volume", STA32X_C1VOL, 0, 0xff, 1, chvol_tlv),
459SOC_SINGLE_TLV("Ch2 Volume", STA32X_C2VOL, 0, 0xff, 1, chvol_tlv),
460SOC_SINGLE_TLV("Ch3 Volume", STA32X_C3VOL, 0, 0xff, 1, chvol_tlv),
461SOC_SINGLE("De-emphasis Filter Switch", STA32X_CONFD, STA32X_CONFD_DEMP_SHIFT, 1, 0),
462SOC_ENUM("Compressor/Limiter Switch", sta32x_drc_ac_enum),
463SOC_SINGLE("Miami Mode Switch", STA32X_CONFD, STA32X_CONFD_MME_SHIFT, 1, 0),
464SOC_SINGLE("Zero Cross Switch", STA32X_CONFE, STA32X_CONFE_ZCE_SHIFT, 1, 0),
465SOC_SINGLE("Soft Ramp Switch", STA32X_CONFE, STA32X_CONFE_SVE_SHIFT, 1, 0),
466SOC_SINGLE("Auto-Mute Switch", STA32X_CONFF, STA32X_CONFF_IDE_SHIFT, 1, 0),
467SOC_ENUM("Automode EQ", sta32x_auto_eq_enum),
468SOC_ENUM("Automode GC", sta32x_auto_gc_enum),
469SOC_ENUM("Automode XO", sta32x_auto_xo_enum),
470SOC_ENUM("Preset EQ", sta32x_preset_eq_enum),
471SOC_SINGLE("Ch1 Tone Control Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0),
472SOC_SINGLE("Ch2 Tone Control Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0),
473SOC_SINGLE("Ch1 EQ Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0),
474SOC_SINGLE("Ch2 EQ Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0),
475SOC_SINGLE("Ch1 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
476SOC_SINGLE("Ch2 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
477SOC_SINGLE("Ch3 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
478SOC_ENUM("Ch1 Limiter Select", sta32x_limiter_ch1_enum),
479SOC_ENUM("Ch2 Limiter Select", sta32x_limiter_ch2_enum),
480SOC_ENUM("Ch3 Limiter Select", sta32x_limiter_ch3_enum),
481SOC_SINGLE_TLV("Bass Tone Control", STA32X_TONE, STA32X_TONE_BTC_SHIFT, 15, 0, tone_tlv),
482SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0, tone_tlv),
483SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum),
484SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum),
485SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
Takashi Iwaib3619b22014-02-27 07:41:32 +0100486SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter2_release_rate_enum),
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200487
488/* depending on mode, the attack/release thresholds have
489 * two different enum definitions; provide both
490 */
491SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT,
492 16, 0, sta32x_limiter_ac_attack_tlv),
493SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT,
494 16, 0, sta32x_limiter_ac_attack_tlv),
495SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT,
496 16, 0, sta32x_limiter_ac_release_tlv),
497SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT,
498 16, 0, sta32x_limiter_ac_release_tlv),
499SOC_SINGLE_TLV("Limiter1 Attack Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT,
500 16, 0, sta32x_limiter_drc_attack_tlv),
501SOC_SINGLE_TLV("Limiter2 Attack Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT,
502 16, 0, sta32x_limiter_drc_attack_tlv),
503SOC_SINGLE_TLV("Limiter1 Release Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT,
504 16, 0, sta32x_limiter_drc_release_tlv),
505SOC_SINGLE_TLV("Limiter2 Release Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT,
506 16, 0, sta32x_limiter_drc_release_tlv),
Johannes Stezenbach79688432011-07-11 17:01:23 +0200507
508BIQUAD_COEFS("Ch1 - Biquad 1", 0),
509BIQUAD_COEFS("Ch1 - Biquad 2", 5),
510BIQUAD_COEFS("Ch1 - Biquad 3", 10),
511BIQUAD_COEFS("Ch1 - Biquad 4", 15),
512BIQUAD_COEFS("Ch2 - Biquad 1", 20),
513BIQUAD_COEFS("Ch2 - Biquad 2", 25),
514BIQUAD_COEFS("Ch2 - Biquad 3", 30),
515BIQUAD_COEFS("Ch2 - Biquad 4", 35),
516BIQUAD_COEFS("High-pass", 40),
517BIQUAD_COEFS("Low-pass", 45),
518SINGLE_COEF("Ch1 - Prescale", 50),
519SINGLE_COEF("Ch2 - Prescale", 51),
520SINGLE_COEF("Ch1 - Postscale", 52),
521SINGLE_COEF("Ch2 - Postscale", 53),
522SINGLE_COEF("Ch3 - Postscale", 54),
523SINGLE_COEF("Thermal warning - Postscale", 55),
524SINGLE_COEF("Ch1 - Mix 1", 56),
525SINGLE_COEF("Ch1 - Mix 2", 57),
526SINGLE_COEF("Ch2 - Mix 1", 58),
527SINGLE_COEF("Ch2 - Mix 2", 59),
528SINGLE_COEF("Ch3 - Mix 1", 60),
529SINGLE_COEF("Ch3 - Mix 2", 61),
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200530};
531
532static const struct snd_soc_dapm_widget sta32x_dapm_widgets[] = {
533SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
534SND_SOC_DAPM_OUTPUT("LEFT"),
535SND_SOC_DAPM_OUTPUT("RIGHT"),
536SND_SOC_DAPM_OUTPUT("SUB"),
537};
538
539static const struct snd_soc_dapm_route sta32x_dapm_routes[] = {
540 { "LEFT", NULL, "DAC" },
541 { "RIGHT", NULL, "DAC" },
542 { "SUB", NULL, "DAC" },
543};
544
545/* MCLK interpolation ratio per fs */
546static struct {
547 int fs;
548 int ir;
549} interpolation_ratios[] = {
550 { 32000, 0 },
551 { 44100, 0 },
552 { 48000, 0 },
553 { 88200, 1 },
554 { 96000, 1 },
555 { 176400, 2 },
556 { 192000, 2 },
557};
558
559/* MCLK to fs clock ratios */
560static struct {
561 int ratio;
562 int mcs;
563} mclk_ratios[3][7] = {
564 { { 768, 0 }, { 512, 1 }, { 384, 2 }, { 256, 3 },
565 { 128, 4 }, { 576, 5 }, { 0, 0 } },
566 { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } },
567 { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } },
568};
569
570
571/**
572 * sta32x_set_dai_sysclk - configure MCLK
573 * @codec_dai: the codec DAI
574 * @clk_id: the clock ID (ignored)
575 * @freq: the MCLK input frequency
576 * @dir: the clock direction (ignored)
577 *
578 * The value of MCLK is used to determine which sample rates are supported
579 * by the STA32X, based on the mclk_ratios table.
580 *
581 * This function must be called by the machine driver's 'startup' function,
582 * otherwise the list of supported sample rates will not be available in
583 * time for ALSA.
584 *
585 * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause
586 * theoretically possible sample rates to be enabled. Call it again with a
587 * proper value set one the external clock is set (most probably you would do
588 * that from a machine's driver 'hw_param' hook.
589 */
590static int sta32x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
591 int clk_id, unsigned int freq, int dir)
592{
593 struct snd_soc_codec *codec = codec_dai->codec;
594 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
595 int i, j, ir, fs;
596 unsigned int rates = 0;
597 unsigned int rate_min = -1;
598 unsigned int rate_max = 0;
599
600 pr_debug("mclk=%u\n", freq);
601 sta32x->mclk = freq;
602
603 if (sta32x->mclk) {
604 for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) {
605 ir = interpolation_ratios[i].ir;
606 fs = interpolation_ratios[i].fs;
607 for (j = 0; mclk_ratios[ir][j].ratio; j++) {
608 if (mclk_ratios[ir][j].ratio * fs == freq) {
609 rates |= snd_pcm_rate_to_rate_bit(fs);
610 if (fs < rate_min)
611 rate_min = fs;
612 if (fs > rate_max)
613 rate_max = fs;
Axel Lin7a748e42012-01-01 18:36:14 +0800614 break;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200615 }
616 }
617 }
618 /* FIXME: soc should support a rate list */
619 rates &= ~SNDRV_PCM_RATE_KNOT;
620
621 if (!rates) {
622 dev_err(codec->dev, "could not find a valid sample rate\n");
623 return -EINVAL;
624 }
625 } else {
626 /* enable all possible rates */
627 rates = STA32X_RATES;
628 rate_min = 32000;
629 rate_max = 192000;
630 }
631
632 codec_dai->driver->playback.rates = rates;
633 codec_dai->driver->playback.rate_min = rate_min;
634 codec_dai->driver->playback.rate_max = rate_max;
635 return 0;
636}
637
638/**
639 * sta32x_set_dai_fmt - configure the codec for the selected audio format
640 * @codec_dai: the codec DAI
641 * @fmt: a SND_SOC_DAIFMT_x value indicating the data format
642 *
643 * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
644 * codec accordingly.
645 */
646static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai,
647 unsigned int fmt)
648{
649 struct snd_soc_codec *codec = codec_dai->codec;
650 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100651 u8 confb = 0;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200652
653 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
654 case SND_SOC_DAIFMT_CBS_CFS:
655 break;
656 default:
657 return -EINVAL;
658 }
659
660 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
661 case SND_SOC_DAIFMT_I2S:
662 case SND_SOC_DAIFMT_RIGHT_J:
663 case SND_SOC_DAIFMT_LEFT_J:
664 sta32x->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
665 break;
666 default:
667 return -EINVAL;
668 }
669
670 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
671 case SND_SOC_DAIFMT_NB_NF:
672 confb |= STA32X_CONFB_C2IM;
673 break;
674 case SND_SOC_DAIFMT_NB_IF:
675 confb |= STA32X_CONFB_C1IM;
676 break;
677 default:
678 return -EINVAL;
679 }
680
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100681 return regmap_update_bits(sta32x->regmap, STA32X_CONFB,
682 STA32X_CONFB_C1IM | STA32X_CONFB_C2IM, confb);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200683}
684
685/**
686 * sta32x_hw_params - program the STA32X with the given hardware parameters.
687 * @substream: the audio stream
688 * @params: the hardware parameters to set
689 * @dai: the SOC DAI (ignored)
690 *
691 * This function programs the hardware with the values provided.
692 * Specifically, the sample rate and the data format.
693 */
694static int sta32x_hw_params(struct snd_pcm_substream *substream,
695 struct snd_pcm_hw_params *params,
696 struct snd_soc_dai *dai)
697{
Mark Browne6968a12012-04-04 15:58:16 +0100698 struct snd_soc_codec *codec = dai->codec;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200699 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
700 unsigned int rate;
701 int i, mcs = -1, ir = -1;
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100702 unsigned int confa, confb;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200703
704 rate = params_rate(params);
705 pr_debug("rate: %u\n", rate);
706 for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++)
Axel Lina5952382011-08-14 11:31:04 +0800707 if (interpolation_ratios[i].fs == rate) {
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200708 ir = interpolation_ratios[i].ir;
Axel Lina5952382011-08-14 11:31:04 +0800709 break;
710 }
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200711 if (ir < 0)
712 return -EINVAL;
713 for (i = 0; mclk_ratios[ir][i].ratio; i++)
Axel Lina5952382011-08-14 11:31:04 +0800714 if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) {
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200715 mcs = mclk_ratios[ir][i].mcs;
Axel Lina5952382011-08-14 11:31:04 +0800716 break;
717 }
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200718 if (mcs < 0)
719 return -EINVAL;
720
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100721 confa = (ir << STA32X_CONFA_IR_SHIFT) |
722 (mcs << STA32X_CONFA_MCS_SHIFT);
723 confb = 0;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200724
Mark Brown737e0f82014-07-31 12:47:24 +0100725 switch (params_width(params)) {
726 case 24:
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200727 pr_debug("24bit\n");
728 /* fall through */
Mark Brown737e0f82014-07-31 12:47:24 +0100729 case 32:
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200730 pr_debug("24bit or 32bit\n");
731 switch (sta32x->format) {
732 case SND_SOC_DAIFMT_I2S:
733 confb |= 0x0;
734 break;
735 case SND_SOC_DAIFMT_LEFT_J:
736 confb |= 0x1;
737 break;
738 case SND_SOC_DAIFMT_RIGHT_J:
739 confb |= 0x2;
740 break;
741 }
742
743 break;
Mark Brown737e0f82014-07-31 12:47:24 +0100744 case 20:
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200745 pr_debug("20bit\n");
746 switch (sta32x->format) {
747 case SND_SOC_DAIFMT_I2S:
748 confb |= 0x4;
749 break;
750 case SND_SOC_DAIFMT_LEFT_J:
751 confb |= 0x5;
752 break;
753 case SND_SOC_DAIFMT_RIGHT_J:
754 confb |= 0x6;
755 break;
756 }
757
758 break;
Mark Brown737e0f82014-07-31 12:47:24 +0100759 case 18:
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200760 pr_debug("18bit\n");
761 switch (sta32x->format) {
762 case SND_SOC_DAIFMT_I2S:
763 confb |= 0x8;
764 break;
765 case SND_SOC_DAIFMT_LEFT_J:
766 confb |= 0x9;
767 break;
768 case SND_SOC_DAIFMT_RIGHT_J:
769 confb |= 0xa;
770 break;
771 }
772
773 break;
Mark Brown737e0f82014-07-31 12:47:24 +0100774 case 16:
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200775 pr_debug("16bit\n");
776 switch (sta32x->format) {
777 case SND_SOC_DAIFMT_I2S:
778 confb |= 0x0;
779 break;
780 case SND_SOC_DAIFMT_LEFT_J:
781 confb |= 0xd;
782 break;
783 case SND_SOC_DAIFMT_RIGHT_J:
784 confb |= 0xe;
785 break;
786 }
787
788 break;
789 default:
790 return -EINVAL;
791 }
792
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100793 ret = regmap_update_bits(sta32x->regmap, STA32X_CONFA,
794 STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK,
795 confa);
796 if (ret < 0)
797 return ret;
798
799 ret = regmap_update_bits(sta32x->regmap, STA32X_CONFB,
800 STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB,
801 confb);
802 if (ret < 0)
803 return ret;
804
805 return 0;
806}
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200807 return 0;
808}
809
810/**
811 * sta32x_set_bias_level - DAPM callback
812 * @codec: the codec device
813 * @level: DAPM power level
814 *
815 * This is called by ALSA to put the codec into low power mode
816 * or to wake it up. If the codec is powered off completely
817 * all registers must be restored after power on.
818 */
819static int sta32x_set_bias_level(struct snd_soc_codec *codec,
820 enum snd_soc_bias_level level)
821{
822 int ret;
823 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
824
825 pr_debug("level = %d\n", level);
826 switch (level) {
827 case SND_SOC_BIAS_ON:
828 break;
829
830 case SND_SOC_BIAS_PREPARE:
831 /* Full power on */
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100832 regmap_update_bits(sta32x->regmap, STA32X_CONFF,
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200833 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
834 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD);
835 break;
836
837 case SND_SOC_BIAS_STANDBY:
838 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
839 ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
840 sta32x->supplies);
841 if (ret != 0) {
842 dev_err(codec->dev,
843 "Failed to enable supplies: %d\n", ret);
844 return ret;
845 }
846
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100847 sta32x_cache_sync(codec);
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100848 sta32x_watchdog_start(sta32x);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200849 }
850
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100851 /* Power down */
852 regmap_update_bits(sta32x->regmap, STA32X_CONFF,
853 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
854 0);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200855
856 break;
857
858 case SND_SOC_BIAS_OFF:
859 /* The chip runs through the power down sequence for us. */
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100860 regmap_update_bits(sta32x->regmap, STA32X_CONFF,
861 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, 0);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200862 msleep(300);
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100863 sta32x_watchdog_stop(sta32x);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200864 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies),
865 sta32x->supplies);
866 break;
867 }
868 codec->dapm.bias_level = level;
869 return 0;
870}
871
Lars-Peter Clausen85e76522011-11-23 11:40:40 +0100872static const struct snd_soc_dai_ops sta32x_dai_ops = {
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200873 .hw_params = sta32x_hw_params,
874 .set_sysclk = sta32x_set_dai_sysclk,
875 .set_fmt = sta32x_set_dai_fmt,
876};
877
878static struct snd_soc_dai_driver sta32x_dai = {
879 .name = "STA32X",
880 .playback = {
881 .stream_name = "Playback",
882 .channels_min = 2,
883 .channels_max = 2,
884 .rates = STA32X_RATES,
885 .formats = STA32X_FORMATS,
886 },
887 .ops = &sta32x_dai_ops,
888};
889
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200890static int sta32x_probe(struct snd_soc_codec *codec)
891{
892 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100893 struct sta32x_platform_data *pdata = sta32x->pdata;
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100894 int i, ret = 0, thermal = 0;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200895 ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
896 sta32x->supplies);
897 if (ret != 0) {
898 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
Mark Brownaff041a2012-09-10 10:59:51 +0800899 return ret;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200900 }
901
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100902 /* set thermal warning adjustment and recovery */
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100903 if (!pdata->thermal_warning_recovery)
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100904 thermal |= STA32X_CONFA_TWAB;
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100905 if (!pdata->thermal_warning_adjustment)
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100906 thermal |= STA32X_CONFA_TWRB;
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100907 regmap_update_bits(sta32x->regmap, STA32X_CONFA,
908 STA32X_CONFA_TWAB | STA32X_CONFA_TWRB,
909 thermal);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200910
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100911 /* select output configuration */
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100912 regmap_update_bits(sta32x->regmap, STA32X_CONFF,
913 STA32X_CONFF_OCFG_MASK,
914 pdata->output_conf
915 << STA32X_CONFF_OCFG_SHIFT);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200916
Johannes Stezenbache012ba22011-11-14 17:23:17 +0100917 /* channel to output mapping */
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100918 regmap_update_bits(sta32x->regmap, STA32X_C1CFG,
919 STA32X_CxCFG_OM_MASK,
920 pdata->ch1_output_mapping
921 << STA32X_CxCFG_OM_SHIFT);
922 regmap_update_bits(sta32x->regmap, STA32X_C2CFG,
923 STA32X_CxCFG_OM_MASK,
924 pdata->ch2_output_mapping
925 << STA32X_CxCFG_OM_SHIFT);
926 regmap_update_bits(sta32x->regmap, STA32X_C3CFG,
927 STA32X_CxCFG_OM_MASK,
928 pdata->ch3_output_mapping
929 << STA32X_CxCFG_OM_SHIFT);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200930
Johannes Stezenbach54dc6ca2011-11-14 17:23:16 +0100931 /* initialize coefficient shadow RAM with reset values */
932 for (i = 4; i <= 49; i += 5)
933 sta32x->coef_shadow[i] = 0x400000;
934 for (i = 50; i <= 54; i++)
935 sta32x->coef_shadow[i] = 0x7fffff;
936 sta32x->coef_shadow[55] = 0x5a9df7;
937 sta32x->coef_shadow[56] = 0x7fffff;
938 sta32x->coef_shadow[59] = 0x7fffff;
939 sta32x->coef_shadow[60] = 0x400000;
940 sta32x->coef_shadow[61] = 0x400000;
941
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100942 if (sta32x->pdata->needs_esd_watchdog)
943 INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog);
944
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200945 sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
946 /* Bias level configuration will have done an extra enable */
947 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
948
949 return 0;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200950}
951
952static int sta32x_remove(struct snd_soc_codec *codec)
953{
954 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
955
Johannes Stezenbach3fb5eac2011-11-14 17:23:18 +0100956 sta32x_watchdog_stop(sta32x);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200957 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200958
959 return 0;
960}
961
962static const struct snd_soc_codec_driver sta32x_codec = {
963 .probe = sta32x_probe,
964 .remove = sta32x_remove,
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200965 .set_bias_level = sta32x_set_bias_level,
Lars-Peter Clausen815b7762014-10-20 10:56:36 +0200966 .suspend_bias_off = true,
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200967 .controls = sta32x_snd_controls,
968 .num_controls = ARRAY_SIZE(sta32x_snd_controls),
969 .dapm_widgets = sta32x_dapm_widgets,
970 .num_dapm_widgets = ARRAY_SIZE(sta32x_dapm_widgets),
971 .dapm_routes = sta32x_dapm_routes,
972 .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes),
973};
974
Mark Brown29fdf4f2012-09-10 10:59:56 +0800975static const struct regmap_config sta32x_regmap = {
976 .reg_bits = 8,
977 .val_bits = 8,
978 .max_register = STA32X_FDRC2,
979 .reg_defaults = sta32x_regs,
980 .num_reg_defaults = ARRAY_SIZE(sta32x_regs),
981 .cache_type = REGCACHE_RBTREE,
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100982 .wr_table = &sta32x_write_regs,
983 .rd_table = &sta32x_read_regs,
984 .volatile_table = &sta32x_volatile_regs,
985};
Mark Brown29fdf4f2012-09-10 10:59:56 +0800986};
987
Bill Pemberton7a79e942012-12-07 09:26:37 -0500988static int sta32x_i2c_probe(struct i2c_client *i2c,
989 const struct i2c_device_id *id)
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200990{
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +0100991 struct device *dev = &i2c->dev;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200992 struct sta32x_priv *sta32x;
Mark Brownaff041a2012-09-10 10:59:51 +0800993 int ret, i;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200994
Axel Lind999c022011-12-29 12:06:39 +0800995 sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv),
996 GFP_KERNEL);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +0200997 if (!sta32x)
998 return -ENOMEM;
999
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +01001000 mutex_init(&sta32x->coeff_lock);
1001 sta32x->pdata = dev_get_platdata(dev);
Mark Brownaff041a2012-09-10 10:59:51 +08001002 /* regulators */
1003 for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++)
1004 sta32x->supplies[i].supply = sta32x_supply_names[i];
1005
1006 ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(sta32x->supplies),
1007 sta32x->supplies);
1008 if (ret != 0) {
1009 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
1010 return ret;
1011 }
1012
Mark Brown29fdf4f2012-09-10 10:59:56 +08001013 sta32x->regmap = devm_regmap_init_i2c(i2c, &sta32x_regmap);
1014 if (IS_ERR(sta32x->regmap)) {
1015 ret = PTR_ERR(sta32x->regmap);
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +01001016 dev_err(dev, "Failed to init regmap: %d\n", ret);
Mark Brown29fdf4f2012-09-10 10:59:56 +08001017 return ret;
1018 }
1019
Johannes Stezenbachc034abf2011-06-22 14:59:24 +02001020 i2c_set_clientdata(i2c, sta32x);
1021
Thomas Niederprüma1be4cea2015-01-22 00:01:53 +01001022 ret = snd_soc_register_codec(dev, &sta32x_codec, &sta32x_dai, 1);
1023 if (ret < 0)
1024 dev_err(dev, "Failed to register codec (%d)\n", ret);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +02001025
Axel Lind999c022011-12-29 12:06:39 +08001026 return ret;
Johannes Stezenbachc034abf2011-06-22 14:59:24 +02001027}
1028
Bill Pemberton7a79e942012-12-07 09:26:37 -05001029static int sta32x_i2c_remove(struct i2c_client *client)
Johannes Stezenbachc034abf2011-06-22 14:59:24 +02001030{
Axel Line3d73c12011-08-18 15:31:04 +08001031 snd_soc_unregister_codec(&client->dev);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +02001032 return 0;
1033}
1034
1035static const struct i2c_device_id sta32x_i2c_id[] = {
1036 { "sta326", 0 },
1037 { "sta328", 0 },
1038 { "sta329", 0 },
1039 { }
1040};
1041MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id);
1042
1043static struct i2c_driver sta32x_i2c_driver = {
1044 .driver = {
1045 .name = "sta32x",
1046 .owner = THIS_MODULE,
1047 },
1048 .probe = sta32x_i2c_probe,
Bill Pemberton7a79e942012-12-07 09:26:37 -05001049 .remove = sta32x_i2c_remove,
Johannes Stezenbachc034abf2011-06-22 14:59:24 +02001050 .id_table = sta32x_i2c_id,
1051};
1052
Sachin Kamat0ead1132012-08-06 17:25:43 +05301053module_i2c_driver(sta32x_i2c_driver);
Johannes Stezenbachc034abf2011-06-22 14:59:24 +02001054
1055MODULE_DESCRIPTION("ASoC STA32X driver");
1056MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>");
1057MODULE_LICENSE("GPL");