aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Stezenbach <js@sig21.net>2011-06-22 08:59:24 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-22 14:10:59 -0400
commitc034abf6e5039cbbe691de37903c514c1033bf75 (patch)
treeb544e78a4d0b7529c5d8391a04340defe2fbd296
parentbab3b59d531bb4dd04d2996dd553ab6e38ec8972 (diff)
ASoC: add STA32X codec driver
Signed-off-by: Johannes Stezenbach <js@sig21.net> [zonque@gmail.com: transform to new ASoC structure] Signed-off-by: Daniel Mack <zonque@gmail.com> Acked-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/sta32x.c777
-rw-r--r--sound/soc/codecs/sta32x.h210
4 files changed, 993 insertions, 0 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 7a2e4269b255..6d32346ac7ce 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -42,6 +42,7 @@ config SND_SOC_ALL_CODECS
42 select SND_SOC_SN95031 if INTEL_SCU_IPC 42 select SND_SOC_SN95031 if INTEL_SCU_IPC
43 select SND_SOC_SPDIF 43 select SND_SOC_SPDIF
44 select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI 44 select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
45 select SND_SOC_STA32X if I2C
45 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS 46 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
46 select SND_SOC_TLV320AIC23 if I2C 47 select SND_SOC_TLV320AIC23 if I2C
47 select SND_SOC_TLV320AIC26 if SPI_MASTER 48 select SND_SOC_TLV320AIC26 if SPI_MASTER
@@ -220,6 +221,9 @@ config SND_SOC_SPDIF
220config SND_SOC_SSM2602 221config SND_SOC_SSM2602
221 tristate 222 tristate
222 223
224config SND_SOC_STA32X
225 tristate
226
223config SND_SOC_STAC9766 227config SND_SOC_STAC9766
224 tristate 228 tristate
225 229
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 30a4c631aef4..600102eb6010 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -29,6 +29,7 @@ snd-soc-alc5623-objs := alc5623.o
29snd-soc-sn95031-objs := sn95031.o 29snd-soc-sn95031-objs := sn95031.o
30snd-soc-spdif-objs := spdif_transciever.o 30snd-soc-spdif-objs := spdif_transciever.o
31snd-soc-ssm2602-objs := ssm2602.o 31snd-soc-ssm2602-objs := ssm2602.o
32snd-soc-sta32x-objs := sta32x.o
32snd-soc-stac9766-objs := stac9766.o 33snd-soc-stac9766-objs := stac9766.o
33snd-soc-tlv320aic23-objs := tlv320aic23.o 34snd-soc-tlv320aic23-objs := tlv320aic23.o
34snd-soc-tlv320aic26-objs := tlv320aic26.o 35snd-soc-tlv320aic26-objs := tlv320aic26.o
@@ -122,6 +123,7 @@ obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
122obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o 123obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
123obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o 124obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
124obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 125obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
126obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o
125obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o 127obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
126obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 128obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
127obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 129obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
new file mode 100644
index 000000000000..486628a144b4
--- /dev/null
+++ b/sound/soc/codecs/sta32x.c
@@ -0,0 +1,777 @@
1/*
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>
27#include <linux/platform_device.h>
28#include <linux/regulator/consumer.h>
29#include <linux/slab.h>
30#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
38#include "sta32x.h"
39
40#define STA32X_RATES (SNDRV_PCM_RATE_32000 | \
41 SNDRV_PCM_RATE_44100 | \
42 SNDRV_PCM_RATE_48000 | \
43 SNDRV_PCM_RATE_88200 | \
44 SNDRV_PCM_RATE_96000 | \
45 SNDRV_PCM_RATE_176400 | \
46 SNDRV_PCM_RATE_192000)
47
48#define STA32X_FORMATS \
49 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
50 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
51 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
52 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \
53 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \
54 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
55
56/* Power-up register defaults */
57static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = {
58 0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60,
59 0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69,
60 0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
62 0xc0, 0xf3, 0x33, 0x00, 0x0c,
63};
64
65/* regulator power supply names */
66static const char *sta32x_supply_names[] = {
67 "Vdda", /* analog supply, 3.3VV */
68 "Vdd3", /* digital supply, 3.3V */
69 "Vcc" /* power amp spply, 10V - 36V */
70};
71
72/* codec private data */
73struct sta32x_priv {
74 struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)];
75 struct snd_soc_codec *codec;
76
77 unsigned int mclk;
78 unsigned int format;
79};
80
81static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
82static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
83static const DECLARE_TLV_DB_SCALE(tone_tlv, -120, 200, 0);
84
85static const char *sta32x_drc_ac[] = {
86 "Anti-Clipping", "Dynamic Range Compression" };
87static const char *sta32x_auto_eq_mode[] = {
88 "User", "Preset", "Loudness" };
89static const char *sta32x_auto_gc_mode[] = {
90 "User", "AC no clipping", "AC limited clipping (10%)",
91 "DRC nighttime listening mode" };
92static const char *sta32x_auto_xo_mode[] = {
93 "User", "80Hz", "100Hz", "120Hz", "140Hz", "160Hz", "180Hz", "200Hz",
94 "220Hz", "240Hz", "260Hz", "280Hz", "300Hz", "320Hz", "340Hz", "360Hz" };
95static const char *sta32x_preset_eq_mode[] = {
96 "Flat", "Rock", "Soft Rock", "Jazz", "Classical", "Dance", "Pop", "Soft",
97 "Hard", "Party", "Vocal", "Hip-Hop", "Dialog", "Bass-boost #1",
98 "Bass-boost #2", "Bass-boost #3", "Loudness 1", "Loudness 2",
99 "Loudness 3", "Loudness 4", "Loudness 5", "Loudness 6", "Loudness 7",
100 "Loudness 8", "Loudness 9", "Loudness 10", "Loudness 11", "Loudness 12",
101 "Loudness 13", "Loudness 14", "Loudness 15", "Loudness 16" };
102static const char *sta32x_limiter_select[] = {
103 "Limiter Disabled", "Limiter #1", "Limiter #2" };
104static const char *sta32x_limiter_attack_rate[] = {
105 "3.1584", "2.7072", "2.2560", "1.8048", "1.3536", "0.9024",
106 "0.4512", "0.2256", "0.1504", "0.1123", "0.0902", "0.0752",
107 "0.0645", "0.0564", "0.0501", "0.0451" };
108static const char *sta32x_limiter_release_rate[] = {
109 "0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299",
110 "0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137",
111 "0.0134", "0.0117", "0.0110", "0.0104" };
112
113static const unsigned int sta32x_limiter_ac_attack_tlv[] = {
114 TLV_DB_RANGE_HEAD(2),
115 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),
116 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0),
117};
118
119static const unsigned int sta32x_limiter_ac_release_tlv[] = {
120 TLV_DB_RANGE_HEAD(5),
121 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
122 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),
123 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),
124 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),
125 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),
126};
127
128static const unsigned int sta32x_limiter_drc_attack_tlv[] = {
129 TLV_DB_RANGE_HEAD(3),
130 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),
131 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),
132 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),
133};
134
135static const unsigned int sta32x_limiter_drc_release_tlv[] = {
136 TLV_DB_RANGE_HEAD(5),
137 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
138 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),
139 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),
140 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),
141 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
142};
143
144static const struct soc_enum sta32x_drc_ac_enum =
145 SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
146 2, sta32x_drc_ac);
147static const struct soc_enum sta32x_auto_eq_enum =
148 SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
149 3, sta32x_auto_eq_mode);
150static const struct soc_enum sta32x_auto_gc_enum =
151 SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
152 4, sta32x_auto_gc_mode);
153static const struct soc_enum sta32x_auto_xo_enum =
154 SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
155 16, sta32x_auto_xo_mode);
156static const struct soc_enum sta32x_preset_eq_enum =
157 SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
158 32, sta32x_preset_eq_mode);
159static const struct soc_enum sta32x_limiter_ch1_enum =
160 SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
161 3, sta32x_limiter_select);
162static const struct soc_enum sta32x_limiter_ch2_enum =
163 SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
164 3, sta32x_limiter_select);
165static const struct soc_enum sta32x_limiter_ch3_enum =
166 SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
167 3, sta32x_limiter_select);
168static const struct soc_enum sta32x_limiter1_attack_rate_enum =
169 SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT,
170 16, sta32x_limiter_attack_rate);
171static const struct soc_enum sta32x_limiter2_attack_rate_enum =
172 SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT,
173 16, sta32x_limiter_attack_rate);
174static const struct soc_enum sta32x_limiter1_release_rate_enum =
175 SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT,
176 16, sta32x_limiter_release_rate);
177static const struct soc_enum sta32x_limiter2_release_rate_enum =
178 SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT,
179 16, sta32x_limiter_release_rate);
180static const struct snd_kcontrol_new sta32x_snd_controls[] = {
181SOC_SINGLE_TLV("Master Volume", STA32X_MVOL, 0, 0xff, 1, mvol_tlv),
182SOC_SINGLE("Master Switch", STA32X_MMUTE, 0, 1, 1),
183SOC_SINGLE("Ch1 Switch", STA32X_MMUTE, 1, 1, 1),
184SOC_SINGLE("Ch2 Switch", STA32X_MMUTE, 2, 1, 1),
185SOC_SINGLE("Ch3 Switch", STA32X_MMUTE, 3, 1, 1),
186SOC_SINGLE_TLV("Ch1 Volume", STA32X_C1VOL, 0, 0xff, 1, chvol_tlv),
187SOC_SINGLE_TLV("Ch2 Volume", STA32X_C2VOL, 0, 0xff, 1, chvol_tlv),
188SOC_SINGLE_TLV("Ch3 Volume", STA32X_C3VOL, 0, 0xff, 1, chvol_tlv),
189SOC_SINGLE("De-emphasis Filter Switch", STA32X_CONFD, STA32X_CONFD_DEMP_SHIFT, 1, 0),
190SOC_ENUM("Compressor/Limiter Switch", sta32x_drc_ac_enum),
191SOC_SINGLE("Miami Mode Switch", STA32X_CONFD, STA32X_CONFD_MME_SHIFT, 1, 0),
192SOC_SINGLE("Zero Cross Switch", STA32X_CONFE, STA32X_CONFE_ZCE_SHIFT, 1, 0),
193SOC_SINGLE("Soft Ramp Switch", STA32X_CONFE, STA32X_CONFE_SVE_SHIFT, 1, 0),
194SOC_SINGLE("Auto-Mute Switch", STA32X_CONFF, STA32X_CONFF_IDE_SHIFT, 1, 0),
195SOC_ENUM("Automode EQ", sta32x_auto_eq_enum),
196SOC_ENUM("Automode GC", sta32x_auto_gc_enum),
197SOC_ENUM("Automode XO", sta32x_auto_xo_enum),
198SOC_ENUM("Preset EQ", sta32x_preset_eq_enum),
199SOC_SINGLE("Ch1 Tone Control Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0),
200SOC_SINGLE("Ch2 Tone Control Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0),
201SOC_SINGLE("Ch1 EQ Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0),
202SOC_SINGLE("Ch2 EQ Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0),
203SOC_SINGLE("Ch1 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
204SOC_SINGLE("Ch2 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
205SOC_SINGLE("Ch3 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0),
206SOC_ENUM("Ch1 Limiter Select", sta32x_limiter_ch1_enum),
207SOC_ENUM("Ch2 Limiter Select", sta32x_limiter_ch2_enum),
208SOC_ENUM("Ch3 Limiter Select", sta32x_limiter_ch3_enum),
209SOC_SINGLE_TLV("Bass Tone Control", STA32X_TONE, STA32X_TONE_BTC_SHIFT, 15, 0, tone_tlv),
210SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0, tone_tlv),
211SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum),
212SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum),
213SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
214SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
215
216/* depending on mode, the attack/release thresholds have
217 * two different enum definitions; provide both
218 */
219SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT,
220 16, 0, sta32x_limiter_ac_attack_tlv),
221SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT,
222 16, 0, sta32x_limiter_ac_attack_tlv),
223SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT,
224 16, 0, sta32x_limiter_ac_release_tlv),
225SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT,
226 16, 0, sta32x_limiter_ac_release_tlv),
227SOC_SINGLE_TLV("Limiter1 Attack Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT,
228 16, 0, sta32x_limiter_drc_attack_tlv),
229SOC_SINGLE_TLV("Limiter2 Attack Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT,
230 16, 0, sta32x_limiter_drc_attack_tlv),
231SOC_SINGLE_TLV("Limiter1 Release Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT,
232 16, 0, sta32x_limiter_drc_release_tlv),
233SOC_SINGLE_TLV("Limiter2 Release Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT,
234 16, 0, sta32x_limiter_drc_release_tlv),
235};
236
237static const struct snd_soc_dapm_widget sta32x_dapm_widgets[] = {
238SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
239SND_SOC_DAPM_OUTPUT("LEFT"),
240SND_SOC_DAPM_OUTPUT("RIGHT"),
241SND_SOC_DAPM_OUTPUT("SUB"),
242};
243
244static const struct snd_soc_dapm_route sta32x_dapm_routes[] = {
245 { "LEFT", NULL, "DAC" },
246 { "RIGHT", NULL, "DAC" },
247 { "SUB", NULL, "DAC" },
248};
249
250/* MCLK interpolation ratio per fs */
251static struct {
252 int fs;
253 int ir;
254} interpolation_ratios[] = {
255 { 32000, 0 },
256 { 44100, 0 },
257 { 48000, 0 },
258 { 88200, 1 },
259 { 96000, 1 },
260 { 176400, 2 },
261 { 192000, 2 },
262};
263
264/* MCLK to fs clock ratios */
265static struct {
266 int ratio;
267 int mcs;
268} mclk_ratios[3][7] = {
269 { { 768, 0 }, { 512, 1 }, { 384, 2 }, { 256, 3 },
270 { 128, 4 }, { 576, 5 }, { 0, 0 } },
271 { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } },
272 { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } },
273};
274
275
276/**
277 * sta32x_set_dai_sysclk - configure MCLK
278 * @codec_dai: the codec DAI
279 * @clk_id: the clock ID (ignored)
280 * @freq: the MCLK input frequency
281 * @dir: the clock direction (ignored)
282 *
283 * The value of MCLK is used to determine which sample rates are supported
284 * by the STA32X, based on the mclk_ratios table.
285 *
286 * This function must be called by the machine driver's 'startup' function,
287 * otherwise the list of supported sample rates will not be available in
288 * time for ALSA.
289 *
290 * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause
291 * theoretically possible sample rates to be enabled. Call it again with a
292 * proper value set one the external clock is set (most probably you would do
293 * that from a machine's driver 'hw_param' hook.
294 */
295static int sta32x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
296 int clk_id, unsigned int freq, int dir)
297{
298 struct snd_soc_codec *codec = codec_dai->codec;
299 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
300 int i, j, ir, fs;
301 unsigned int rates = 0;
302 unsigned int rate_min = -1;
303 unsigned int rate_max = 0;
304
305 pr_debug("mclk=%u\n", freq);
306 sta32x->mclk = freq;
307
308 if (sta32x->mclk) {
309 for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) {
310 ir = interpolation_ratios[i].ir;
311 fs = interpolation_ratios[i].fs;
312 for (j = 0; mclk_ratios[ir][j].ratio; j++) {
313 if (mclk_ratios[ir][j].ratio * fs == freq) {
314 rates |= snd_pcm_rate_to_rate_bit(fs);
315 if (fs < rate_min)
316 rate_min = fs;
317 if (fs > rate_max)
318 rate_max = fs;
319 }
320 }
321 }
322 /* FIXME: soc should support a rate list */
323 rates &= ~SNDRV_PCM_RATE_KNOT;
324
325 if (!rates) {
326 dev_err(codec->dev, "could not find a valid sample rate\n");
327 return -EINVAL;
328 }
329 } else {
330 /* enable all possible rates */
331 rates = STA32X_RATES;
332 rate_min = 32000;
333 rate_max = 192000;
334 }
335
336 codec_dai->driver->playback.rates = rates;
337 codec_dai->driver->playback.rate_min = rate_min;
338 codec_dai->driver->playback.rate_max = rate_max;
339 return 0;
340}
341
342/**
343 * sta32x_set_dai_fmt - configure the codec for the selected audio format
344 * @codec_dai: the codec DAI
345 * @fmt: a SND_SOC_DAIFMT_x value indicating the data format
346 *
347 * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the
348 * codec accordingly.
349 */
350static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai,
351 unsigned int fmt)
352{
353 struct snd_soc_codec *codec = codec_dai->codec;
354 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
355 u8 confb = snd_soc_read(codec, STA32X_CONFB);
356
357 pr_debug("\n");
358 confb &= ~(STA32X_CONFB_C1IM | STA32X_CONFB_C2IM);
359
360 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
361 case SND_SOC_DAIFMT_CBS_CFS:
362 break;
363 default:
364 return -EINVAL;
365 }
366
367 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
368 case SND_SOC_DAIFMT_I2S:
369 case SND_SOC_DAIFMT_RIGHT_J:
370 case SND_SOC_DAIFMT_LEFT_J:
371 sta32x->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
372 break;
373 default:
374 return -EINVAL;
375 }
376
377 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
378 case SND_SOC_DAIFMT_NB_NF:
379 confb |= STA32X_CONFB_C2IM;
380 break;
381 case SND_SOC_DAIFMT_NB_IF:
382 confb |= STA32X_CONFB_C1IM;
383 break;
384 default:
385 return -EINVAL;
386 }
387
388 snd_soc_write(codec, STA32X_CONFB, confb);
389 return 0;
390}
391
392/**
393 * sta32x_hw_params - program the STA32X with the given hardware parameters.
394 * @substream: the audio stream
395 * @params: the hardware parameters to set
396 * @dai: the SOC DAI (ignored)
397 *
398 * This function programs the hardware with the values provided.
399 * Specifically, the sample rate and the data format.
400 */
401static int sta32x_hw_params(struct snd_pcm_substream *substream,
402 struct snd_pcm_hw_params *params,
403 struct snd_soc_dai *dai)
404{
405 struct snd_soc_pcm_runtime *rtd = substream->private_data;
406 struct snd_soc_codec *codec = rtd->codec;
407 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
408 unsigned int rate;
409 int i, mcs = -1, ir = -1;
410 u8 confa, confb;
411
412 rate = params_rate(params);
413 pr_debug("rate: %u\n", rate);
414 for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++)
415 if (interpolation_ratios[i].fs == rate)
416 ir = interpolation_ratios[i].ir;
417 if (ir < 0)
418 return -EINVAL;
419 for (i = 0; mclk_ratios[ir][i].ratio; i++)
420 if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk)
421 mcs = mclk_ratios[ir][i].mcs;
422 if (mcs < 0)
423 return -EINVAL;
424
425 confa = snd_soc_read(codec, STA32X_CONFA);
426 confa &= ~(STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK);
427 confa |= (ir << STA32X_CONFA_IR_SHIFT) | (mcs << STA32X_CONFA_MCS_SHIFT);
428
429 confb = snd_soc_read(codec, STA32X_CONFB);
430 confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB);
431 switch (params_format(params)) {
432 case SNDRV_PCM_FORMAT_S24_LE:
433 case SNDRV_PCM_FORMAT_S24_BE:
434 case SNDRV_PCM_FORMAT_S24_3LE:
435 case SNDRV_PCM_FORMAT_S24_3BE:
436 pr_debug("24bit\n");
437 /* fall through */
438 case SNDRV_PCM_FORMAT_S32_LE:
439 case SNDRV_PCM_FORMAT_S32_BE:
440 pr_debug("24bit or 32bit\n");
441 switch (sta32x->format) {
442 case SND_SOC_DAIFMT_I2S:
443 confb |= 0x0;
444 break;
445 case SND_SOC_DAIFMT_LEFT_J:
446 confb |= 0x1;
447 break;
448 case SND_SOC_DAIFMT_RIGHT_J:
449 confb |= 0x2;
450 break;
451 }
452
453 break;
454 case SNDRV_PCM_FORMAT_S20_3LE:
455 case SNDRV_PCM_FORMAT_S20_3BE:
456 pr_debug("20bit\n");
457 switch (sta32x->format) {
458 case SND_SOC_DAIFMT_I2S:
459 confb |= 0x4;
460 break;
461 case SND_SOC_DAIFMT_LEFT_J:
462 confb |= 0x5;
463 break;
464 case SND_SOC_DAIFMT_RIGHT_J:
465 confb |= 0x6;
466 break;
467 }
468
469 break;
470 case SNDRV_PCM_FORMAT_S18_3LE:
471 case SNDRV_PCM_FORMAT_S18_3BE:
472 pr_debug("18bit\n");
473 switch (sta32x->format) {
474 case SND_SOC_DAIFMT_I2S:
475 confb |= 0x8;
476 break;
477 case SND_SOC_DAIFMT_LEFT_J:
478 confb |= 0x9;
479 break;
480 case SND_SOC_DAIFMT_RIGHT_J:
481 confb |= 0xa;
482 break;
483 }
484
485 break;
486 case SNDRV_PCM_FORMAT_S16_LE:
487 case SNDRV_PCM_FORMAT_S16_BE:
488 pr_debug("16bit\n");
489 switch (sta32x->format) {
490 case SND_SOC_DAIFMT_I2S:
491 confb |= 0x0;
492 break;
493 case SND_SOC_DAIFMT_LEFT_J:
494 confb |= 0xd;
495 break;
496 case SND_SOC_DAIFMT_RIGHT_J:
497 confb |= 0xe;
498 break;
499 }
500
501 break;
502 default:
503 return -EINVAL;
504 }
505
506 snd_soc_write(codec, STA32X_CONFA, confa);
507 snd_soc_write(codec, STA32X_CONFB, confb);
508 return 0;
509}
510
511/**
512 * sta32x_set_bias_level - DAPM callback
513 * @codec: the codec device
514 * @level: DAPM power level
515 *
516 * This is called by ALSA to put the codec into low power mode
517 * or to wake it up. If the codec is powered off completely
518 * all registers must be restored after power on.
519 */
520static int sta32x_set_bias_level(struct snd_soc_codec *codec,
521 enum snd_soc_bias_level level)
522{
523 int ret;
524 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
525
526 pr_debug("level = %d\n", level);
527 switch (level) {
528 case SND_SOC_BIAS_ON:
529 break;
530
531 case SND_SOC_BIAS_PREPARE:
532 /* Full power on */
533 snd_soc_update_bits(codec, STA32X_CONFF,
534 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
535 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD);
536 break;
537
538 case SND_SOC_BIAS_STANDBY:
539 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
540 ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
541 sta32x->supplies);
542 if (ret != 0) {
543 dev_err(codec->dev,
544 "Failed to enable supplies: %d\n", ret);
545 return ret;
546 }
547
548 snd_soc_cache_sync(codec);
549 }
550
551 /* Power up to mute */
552 /* FIXME */
553 snd_soc_update_bits(codec, STA32X_CONFF,
554 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
555 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD);
556
557 break;
558
559 case SND_SOC_BIAS_OFF:
560 /* The chip runs through the power down sequence for us. */
561 snd_soc_update_bits(codec, STA32X_CONFF,
562 STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
563 STA32X_CONFF_PWDN);
564 msleep(300);
565
566 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies),
567 sta32x->supplies);
568 break;
569 }
570 codec->dapm.bias_level = level;
571 return 0;
572}
573
574static struct snd_soc_dai_ops sta32x_dai_ops = {
575 .hw_params = sta32x_hw_params,
576 .set_sysclk = sta32x_set_dai_sysclk,
577 .set_fmt = sta32x_set_dai_fmt,
578};
579
580static struct snd_soc_dai_driver sta32x_dai = {
581 .name = "STA32X",
582 .playback = {
583 .stream_name = "Playback",
584 .channels_min = 2,
585 .channels_max = 2,
586 .rates = STA32X_RATES,
587 .formats = STA32X_FORMATS,
588 },
589 .ops = &sta32x_dai_ops,
590};
591
592#ifdef CONFIG_PM
593static int sta32x_suspend(struct snd_soc_codec *codec, pm_message_t state)
594{
595 sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
596 return 0;
597}
598
599static int sta32x_resume(struct snd_soc_codec *codec)
600{
601 sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
602 return 0;
603}
604#else
605#define sta32x_suspend NULL
606#define sta32x_resume NULL
607#endif
608
609static int sta32x_probe(struct snd_soc_codec *codec)
610{
611 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
612 int i, ret = 0;
613
614 sta32x->codec = codec;
615
616 /* regulators */
617 for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++)
618 sta32x->supplies[i].supply = sta32x_supply_names[i];
619
620 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies),
621 sta32x->supplies);
622 if (ret != 0) {
623 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
624 goto err;
625 }
626
627 ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
628 sta32x->supplies);
629 if (ret != 0) {
630 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
631 goto err_get;
632 }
633
634 /* Tell ASoC what kind of I/O to use to read the registers. ASoC will
635 * then do the I2C transactions itself.
636 */
637 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
638 if (ret < 0) {
639 dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret);
640 return ret;
641 }
642
643 /* read reg reset values into cache */
644 for (i = 0; i < STA32X_REGISTER_COUNT; i++)
645 snd_soc_cache_write(codec, i, sta32x_regs[i]);
646
647 /* FIXME enable thermal warning adjustment and recovery */
648 snd_soc_update_bits(codec, STA32X_CONFA,
649 STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, 0);
650
651 /* FIXME select 2.1 mode */
652 snd_soc_update_bits(codec, STA32X_CONFF,
653 STA32X_CONFF_OCFG_MASK,
654 1 << STA32X_CONFF_OCFG_SHIFT);
655
656 /* FIXME channel to output mapping */
657 snd_soc_update_bits(codec, STA32X_C1CFG,
658 STA32X_CxCFG_OM_MASK,
659 0 << STA32X_CxCFG_OM_SHIFT);
660 snd_soc_update_bits(codec, STA32X_C2CFG,
661 STA32X_CxCFG_OM_MASK,
662 1 << STA32X_CxCFG_OM_SHIFT);
663 snd_soc_update_bits(codec, STA32X_C3CFG,
664 STA32X_CxCFG_OM_MASK,
665 2 << STA32X_CxCFG_OM_SHIFT);
666
667 sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
668 /* Bias level configuration will have done an extra enable */
669 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
670
671 return 0;
672
673err_get:
674 regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
675err:
676 return ret;
677}
678
679static int sta32x_remove(struct snd_soc_codec *codec)
680{
681 struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
682
683 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
684 regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
685
686 return 0;
687}
688
689static const struct snd_soc_codec_driver sta32x_codec = {
690 .probe = sta32x_probe,
691 .remove = sta32x_remove,
692 .suspend = sta32x_suspend,
693 .resume = sta32x_resume,
694 .reg_cache_size = STA32X_REGISTER_COUNT,
695 .reg_word_size = sizeof(u8),
696 .set_bias_level = sta32x_set_bias_level,
697 .controls = sta32x_snd_controls,
698 .num_controls = ARRAY_SIZE(sta32x_snd_controls),
699 .dapm_widgets = sta32x_dapm_widgets,
700 .num_dapm_widgets = ARRAY_SIZE(sta32x_dapm_widgets),
701 .dapm_routes = sta32x_dapm_routes,
702 .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes),
703};
704
705static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
706 const struct i2c_device_id *id)
707{
708 struct sta32x_priv *sta32x;
709 int ret;
710
711 sta32x = kzalloc(sizeof(struct sta32x_priv), GFP_KERNEL);
712 if (!sta32x)
713 return -ENOMEM;
714
715 i2c_set_clientdata(i2c, sta32x);
716
717 ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1);
718 if (ret != 0) {
719 dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret);
720 return ret;
721 }
722
723 return 0;
724}
725
726static __devexit int sta32x_i2c_remove(struct i2c_client *client)
727{
728 struct sta32x_priv *sta32x = i2c_get_clientdata(client);
729 struct snd_soc_codec *codec = sta32x->codec;
730
731 if (codec)
732 sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
733
734 regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
735
736 if (codec) {
737 snd_soc_unregister_codec(&client->dev);
738 snd_soc_codec_set_drvdata(codec, NULL);
739 }
740
741 kfree(sta32x);
742 return 0;
743}
744
745static const struct i2c_device_id sta32x_i2c_id[] = {
746 { "sta326", 0 },
747 { "sta328", 0 },
748 { "sta329", 0 },
749 { }
750};
751MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id);
752
753static struct i2c_driver sta32x_i2c_driver = {
754 .driver = {
755 .name = "sta32x",
756 .owner = THIS_MODULE,
757 },
758 .probe = sta32x_i2c_probe,
759 .remove = __devexit_p(sta32x_i2c_remove),
760 .id_table = sta32x_i2c_id,
761};
762
763static int __init sta32x_init(void)
764{
765 return i2c_add_driver(&sta32x_i2c_driver);
766}
767module_init(sta32x_init);
768
769static void __exit sta32x_exit(void)
770{
771 i2c_del_driver(&sta32x_i2c_driver);
772}
773module_exit(sta32x_exit);
774
775MODULE_DESCRIPTION("ASoC STA32X driver");
776MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>");
777MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sta32x.h b/sound/soc/codecs/sta32x.h
new file mode 100644
index 000000000000..b97ee5a75667
--- /dev/null
+++ b/sound/soc/codecs/sta32x.h
@@ -0,0 +1,210 @@
1/*
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 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16#ifndef _ASOC_STA_32X_H
17#define _ASOC_STA_32X_H
18
19/* STA326 register addresses */
20
21#define STA32X_REGISTER_COUNT 0x2d
22
23#define STA32X_CONFA 0x00
24#define STA32X_CONFB 0x01
25#define STA32X_CONFC 0x02
26#define STA32X_CONFD 0x03
27#define STA32X_CONFE 0x04
28#define STA32X_CONFF 0x05
29#define STA32X_MMUTE 0x06
30#define STA32X_MVOL 0x07
31#define STA32X_C1VOL 0x08
32#define STA32X_C2VOL 0x09
33#define STA32X_C3VOL 0x0a
34#define STA32X_AUTO1 0x0b
35#define STA32X_AUTO2 0x0c
36#define STA32X_AUTO3 0x0d
37#define STA32X_C1CFG 0x0e
38#define STA32X_C2CFG 0x0f
39#define STA32X_C3CFG 0x10
40#define STA32X_TONE 0x11
41#define STA32X_L1AR 0x12
42#define STA32X_L1ATRT 0x13
43#define STA32X_L2AR 0x14
44#define STA32X_L2ATRT 0x15
45#define STA32X_CFADDR2 0x16
46#define STA32X_B1CF1 0x17
47#define STA32X_B1CF2 0x18
48#define STA32X_B1CF3 0x19
49#define STA32X_B2CF1 0x1a
50#define STA32X_B2CF2 0x1b
51#define STA32X_B2CF3 0x1c
52#define STA32X_A1CF1 0x1d
53#define STA32X_A1CF2 0x1e
54#define STA32X_A1CF3 0x1f
55#define STA32X_A2CF1 0x20
56#define STA32X_A2CF2 0x21
57#define STA32X_A2CF3 0x22
58#define STA32X_B0CF1 0x23
59#define STA32X_B0CF2 0x24
60#define STA32X_B0CF3 0x25
61#define STA32X_CFUD 0x26
62#define STA32X_MPCC1 0x27
63#define STA32X_MPCC2 0x28
64/* Reserved 0x29 */
65/* Reserved 0x2a */
66#define STA32X_Reserved 0x2a
67#define STA32X_FDRC1 0x2b
68#define STA32X_FDRC2 0x2c
69/* Reserved 0x2d */
70
71
72/* STA326 register field definitions */
73
74/* 0x00 CONFA */
75#define STA32X_CONFA_MCS_MASK 0x03
76#define STA32X_CONFA_MCS_SHIFT 0
77#define STA32X_CONFA_IR_MASK 0x18
78#define STA32X_CONFA_IR_SHIFT 3
79#define STA32X_CONFA_TWRB 0x20
80#define STA32X_CONFA_TWAB 0x40
81#define STA32X_CONFA_FDRB 0x80
82
83/* 0x01 CONFB */
84#define STA32X_CONFB_SAI_MASK 0x0f
85#define STA32X_CONFB_SAI_SHIFT 0
86#define STA32X_CONFB_SAIFB 0x10
87#define STA32X_CONFB_DSCKE 0x20
88#define STA32X_CONFB_C1IM 0x40
89#define STA32X_CONFB_C2IM 0x80
90
91/* 0x02 CONFC */
92#define STA32X_CONFC_OM_MASK 0x03
93#define STA32X_CONFC_OM_SHIFT 0
94#define STA32X_CONFC_CSZ_MASK 0x7c
95#define STA32X_CONFC_CSZ_SHIFT 2
96
97/* 0x03 CONFD */
98#define STA32X_CONFD_HPB 0x01
99#define STA32X_CONFD_HPB_SHIFT 0
100#define STA32X_CONFD_DEMP 0x02
101#define STA32X_CONFD_DEMP_SHIFT 1
102#define STA32X_CONFD_DSPB 0x04
103#define STA32X_CONFD_DSPB_SHIFT 2
104#define STA32X_CONFD_PSL 0x08
105#define STA32X_CONFD_PSL_SHIFT 3
106#define STA32X_CONFD_BQL 0x10
107#define STA32X_CONFD_BQL_SHIFT 4
108#define STA32X_CONFD_DRC 0x20
109#define STA32X_CONFD_DRC_SHIFT 5
110#define STA32X_CONFD_ZDE 0x40
111#define STA32X_CONFD_ZDE_SHIFT 6
112#define STA32X_CONFD_MME 0x80
113#define STA32X_CONFD_MME_SHIFT 7
114
115/* 0x04 CONFE */
116#define STA32X_CONFE_MPCV 0x01
117#define STA32X_CONFE_MPCV_SHIFT 0
118#define STA32X_CONFE_MPC 0x02
119#define STA32X_CONFE_MPC_SHIFT 1
120#define STA32X_CONFE_AME 0x08
121#define STA32X_CONFE_AME_SHIFT 3
122#define STA32X_CONFE_PWMS 0x10
123#define STA32X_CONFE_PWMS_SHIFT 4
124#define STA32X_CONFE_ZCE 0x40
125#define STA32X_CONFE_ZCE_SHIFT 6
126#define STA32X_CONFE_SVE 0x80
127#define STA32X_CONFE_SVE_SHIFT 7
128
129/* 0x05 CONFF */
130#define STA32X_CONFF_OCFG_MASK 0x03
131#define STA32X_CONFF_OCFG_SHIFT 0
132#define STA32X_CONFF_IDE 0x04
133#define STA32X_CONFF_IDE_SHIFT 3
134#define STA32X_CONFF_BCLE 0x08
135#define STA32X_CONFF_ECLE 0x20
136#define STA32X_CONFF_PWDN 0x40
137#define STA32X_CONFF_EAPD 0x80
138
139/* 0x06 MMUTE */
140#define STA32X_MMUTE_MMUTE 0x01
141
142/* 0x0b AUTO1 */
143#define STA32X_AUTO1_AMEQ_MASK 0x03
144#define STA32X_AUTO1_AMEQ_SHIFT 0
145#define STA32X_AUTO1_AMV_MASK 0xc0
146#define STA32X_AUTO1_AMV_SHIFT 2
147#define STA32X_AUTO1_AMGC_MASK 0x30
148#define STA32X_AUTO1_AMGC_SHIFT 4
149#define STA32X_AUTO1_AMPS 0x80
150
151/* 0x0c AUTO2 */
152#define STA32X_AUTO2_AMAME 0x01
153#define STA32X_AUTO2_AMAM_MASK 0x0e
154#define STA32X_AUTO2_AMAM_SHIFT 1
155#define STA32X_AUTO2_XO_MASK 0xf0
156#define STA32X_AUTO2_XO_SHIFT 4
157
158/* 0x0d AUTO3 */
159#define STA32X_AUTO3_PEQ_MASK 0x1f
160#define STA32X_AUTO3_PEQ_SHIFT 0
161
162/* 0x0e 0x0f 0x10 CxCFG */
163#define STA32X_CxCFG_TCB 0x01 /* only C1 and C2 */
164#define STA32X_CxCFG_TCB_SHIFT 0
165#define STA32X_CxCFG_EQBP 0x02 /* only C1 and C2 */
166#define STA32X_CxCFG_EQBP_SHIFT 1
167#define STA32X_CxCFG_VBP 0x03
168#define STA32X_CxCFG_VBP_SHIFT 2
169#define STA32X_CxCFG_BO 0x04
170#define STA32X_CxCFG_LS_MASK 0x30
171#define STA32X_CxCFG_LS_SHIFT 4
172#define STA32X_CxCFG_OM_MASK 0xc0
173#define STA32X_CxCFG_OM_SHIFT 6
174
175/* 0x11 TONE */
176#define STA32X_TONE_BTC_SHIFT 0
177#define STA32X_TONE_TTC_SHIFT 4
178
179/* 0x12 0x13 0x14 0x15 limiter attack/release */
180#define STA32X_LxA_SHIFT 0
181#define STA32X_LxR_SHIFT 4
182
183/* 0x26 CFUD */
184#define STA32X_CFUD_W1 0x01
185#define STA32X_CFUD_WA 0x02
186#define STA32X_CFUD_R1 0x04
187#define STA32X_CFUD_RA 0x08
188
189
190/* biquad filter coefficient table offsets */
191#define STA32X_C1_BQ_BASE 0
192#define STA32X_C2_BQ_BASE 20
193#define STA32X_CH_BQ_NUM 4
194#define STA32X_BQ_NUM_COEF 5
195#define STA32X_XO_HP_BQ_BASE 40
196#define STA32X_XO_LP_BQ_BASE 45
197#define STA32X_C1_PRESCALE 50
198#define STA32X_C2_PRESCALE 51
199#define STA32X_C1_POSTSCALE 52
200#define STA32X_C2_POSTSCALE 53
201#define STA32X_C3_POSTSCALE 54
202#define STA32X_TW_POSTSCALE 55
203#define STA32X_C1_MIX1 56
204#define STA32X_C1_MIX2 57
205#define STA32X_C2_MIX1 58
206#define STA32X_C2_MIX2 59
207#define STA32X_C3_MIX1 60
208#define STA32X_C3_MIX2 61
209
210#endif /* _ASOC_STA_32X_H */