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