diff options
Diffstat (limited to 'sound/soc/codecs/wm8903.c')
-rw-r--r-- | sound/soc/codecs/wm8903.c | 641 |
1 files changed, 459 insertions, 182 deletions
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 017d99ceb42e..ae1cadfae84c 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * wm8903.c -- WM8903 ALSA SoC Audio driver | 2 | * wm8903.c -- WM8903 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2008 Wolfson Microelectronics | 4 | * Copyright 2008 Wolfson Microelectronics |
5 | * Copyright 2011 NVIDIA, Inc. | ||
5 | * | 6 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 7 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 8 | * |
@@ -19,6 +20,7 @@ | |||
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/completion.h> | 21 | #include <linux/completion.h> |
21 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/gpio.h> | ||
22 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
23 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
24 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
@@ -213,6 +215,7 @@ static u16 wm8903_reg_defaults[] = { | |||
213 | }; | 215 | }; |
214 | 216 | ||
215 | struct wm8903_priv { | 217 | struct wm8903_priv { |
218 | struct snd_soc_codec *codec; | ||
216 | 219 | ||
217 | int sysclk; | 220 | int sysclk; |
218 | int irq; | 221 | int irq; |
@@ -220,25 +223,36 @@ struct wm8903_priv { | |||
220 | int fs; | 223 | int fs; |
221 | int deemph; | 224 | int deemph; |
222 | 225 | ||
226 | int dcs_pending; | ||
227 | int dcs_cache[4]; | ||
228 | |||
223 | /* Reference count */ | 229 | /* Reference count */ |
224 | int class_w_users; | 230 | int class_w_users; |
225 | 231 | ||
226 | struct completion wseq; | ||
227 | |||
228 | struct snd_soc_jack *mic_jack; | 232 | struct snd_soc_jack *mic_jack; |
229 | int mic_det; | 233 | int mic_det; |
230 | int mic_short; | 234 | int mic_short; |
231 | int mic_last_report; | 235 | int mic_last_report; |
232 | int mic_delay; | 236 | int mic_delay; |
237 | |||
238 | #ifdef CONFIG_GPIOLIB | ||
239 | struct gpio_chip gpio_chip; | ||
240 | #endif | ||
233 | }; | 241 | }; |
234 | 242 | ||
235 | static int wm8903_volatile_register(unsigned int reg) | 243 | static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
236 | { | 244 | { |
237 | switch (reg) { | 245 | switch (reg) { |
238 | case WM8903_SW_RESET_AND_ID: | 246 | case WM8903_SW_RESET_AND_ID: |
239 | case WM8903_REVISION_NUMBER: | 247 | case WM8903_REVISION_NUMBER: |
240 | case WM8903_INTERRUPT_STATUS_1: | 248 | case WM8903_INTERRUPT_STATUS_1: |
241 | case WM8903_WRITE_SEQUENCER_4: | 249 | case WM8903_WRITE_SEQUENCER_4: |
250 | case WM8903_POWER_MANAGEMENT_3: | ||
251 | case WM8903_POWER_MANAGEMENT_2: | ||
252 | case WM8903_DC_SERVO_READBACK_1: | ||
253 | case WM8903_DC_SERVO_READBACK_2: | ||
254 | case WM8903_DC_SERVO_READBACK_3: | ||
255 | case WM8903_DC_SERVO_READBACK_4: | ||
242 | return 1; | 256 | return 1; |
243 | 257 | ||
244 | default: | 258 | default: |
@@ -246,50 +260,6 @@ static int wm8903_volatile_register(unsigned int reg) | |||
246 | } | 260 | } |
247 | } | 261 | } |
248 | 262 | ||
249 | static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | ||
250 | { | ||
251 | u16 reg[5]; | ||
252 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
253 | |||
254 | BUG_ON(start > 48); | ||
255 | |||
256 | /* Enable the sequencer if it's not already on */ | ||
257 | reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0); | ||
258 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, | ||
259 | reg[0] | WM8903_WSEQ_ENA); | ||
260 | |||
261 | dev_dbg(codec->dev, "Starting sequence at %d\n", start); | ||
262 | |||
263 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3, | ||
264 | start | WM8903_WSEQ_START); | ||
265 | |||
266 | /* Wait for it to complete. If we have the interrupt wired up then | ||
267 | * that will break us out of the poll early. | ||
268 | */ | ||
269 | do { | ||
270 | wait_for_completion_timeout(&wm8903->wseq, | ||
271 | msecs_to_jiffies(10)); | ||
272 | |||
273 | reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); | ||
274 | } while (reg[4] & WM8903_WSEQ_BUSY); | ||
275 | |||
276 | dev_dbg(codec->dev, "Sequence complete\n"); | ||
277 | |||
278 | /* Disable the sequencer again if we enabled it */ | ||
279 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache) | ||
285 | { | ||
286 | int i; | ||
287 | |||
288 | /* There really ought to be something better we can do here :/ */ | ||
289 | for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++) | ||
290 | cache[i] = codec->hw_read(codec, i); | ||
291 | } | ||
292 | |||
293 | static void wm8903_reset(struct snd_soc_codec *codec) | 263 | static void wm8903_reset(struct snd_soc_codec *codec) |
294 | { | 264 | { |
295 | snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0); | 265 | snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0); |
@@ -297,11 +267,6 @@ static void wm8903_reset(struct snd_soc_codec *codec) | |||
297 | sizeof(wm8903_reg_defaults)); | 267 | sizeof(wm8903_reg_defaults)); |
298 | } | 268 | } |
299 | 269 | ||
300 | #define WM8903_OUTPUT_SHORT 0x8 | ||
301 | #define WM8903_OUTPUT_OUT 0x4 | ||
302 | #define WM8903_OUTPUT_INT 0x2 | ||
303 | #define WM8903_OUTPUT_IN 0x1 | ||
304 | |||
305 | static int wm8903_cp_event(struct snd_soc_dapm_widget *w, | 270 | static int wm8903_cp_event(struct snd_soc_dapm_widget *w, |
306 | struct snd_kcontrol *kcontrol, int event) | 271 | struct snd_kcontrol *kcontrol, int event) |
307 | { | 272 | { |
@@ -311,97 +276,101 @@ static int wm8903_cp_event(struct snd_soc_dapm_widget *w, | |||
311 | return 0; | 276 | return 0; |
312 | } | 277 | } |
313 | 278 | ||
314 | /* | 279 | static int wm8903_dcs_event(struct snd_soc_dapm_widget *w, |
315 | * Event for headphone and line out amplifier power changes. Special | 280 | struct snd_kcontrol *kcontrol, int event) |
316 | * power up/down sequences are required in order to maximise pop/click | ||
317 | * performance. | ||
318 | */ | ||
319 | static int wm8903_output_event(struct snd_soc_dapm_widget *w, | ||
320 | struct snd_kcontrol *kcontrol, int event) | ||
321 | { | 281 | { |
322 | struct snd_soc_codec *codec = w->codec; | 282 | struct snd_soc_codec *codec = w->codec; |
323 | u16 val; | 283 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
324 | u16 reg; | ||
325 | u16 dcs_reg; | ||
326 | u16 dcs_bit; | ||
327 | int shift; | ||
328 | 284 | ||
329 | switch (w->reg) { | 285 | switch (event) { |
330 | case WM8903_POWER_MANAGEMENT_2: | 286 | case SND_SOC_DAPM_POST_PMU: |
331 | reg = WM8903_ANALOGUE_HP_0; | 287 | wm8903->dcs_pending |= 1 << w->shift; |
332 | dcs_bit = 0 + w->shift; | ||
333 | break; | 288 | break; |
334 | case WM8903_POWER_MANAGEMENT_3: | 289 | case SND_SOC_DAPM_PRE_PMD: |
335 | reg = WM8903_ANALOGUE_LINEOUT_0; | 290 | snd_soc_update_bits(codec, WM8903_DC_SERVO_0, |
336 | dcs_bit = 2 + w->shift; | 291 | 1 << w->shift, 0); |
337 | break; | 292 | break; |
338 | default: | ||
339 | BUG(); | ||
340 | return -EINVAL; /* Spurious warning from some compilers */ | ||
341 | } | 293 | } |
342 | 294 | ||
343 | switch (w->shift) { | 295 | return 0; |
344 | case 0: | 296 | } |
345 | shift = 0; | ||
346 | break; | ||
347 | case 1: | ||
348 | shift = 4; | ||
349 | break; | ||
350 | default: | ||
351 | BUG(); | ||
352 | return -EINVAL; /* Spurious warning from some compilers */ | ||
353 | } | ||
354 | 297 | ||
355 | if (event & SND_SOC_DAPM_PRE_PMU) { | 298 | #define WM8903_DCS_MODE_WRITE_STOP 0 |
356 | val = snd_soc_read(codec, reg); | 299 | #define WM8903_DCS_MODE_START_STOP 2 |
357 | 300 | ||
358 | /* Short the output */ | 301 | static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, |
359 | val &= ~(WM8903_OUTPUT_SHORT << shift); | 302 | enum snd_soc_dapm_type event, int subseq) |
360 | snd_soc_write(codec, reg, val); | 303 | { |
361 | } | 304 | struct snd_soc_codec *codec = container_of(dapm, |
305 | struct snd_soc_codec, dapm); | ||
306 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
307 | int dcs_mode = WM8903_DCS_MODE_WRITE_STOP; | ||
308 | int i, val; | ||
362 | 309 | ||
363 | if (event & SND_SOC_DAPM_POST_PMU) { | 310 | /* Complete any pending DC servo starts */ |
364 | val = snd_soc_read(codec, reg); | 311 | if (wm8903->dcs_pending) { |
312 | dev_dbg(codec->dev, "Starting DC servo for %x\n", | ||
313 | wm8903->dcs_pending); | ||
365 | 314 | ||
366 | val |= (WM8903_OUTPUT_IN << shift); | 315 | /* If we've no cached values then we need to do startup */ |
367 | snd_soc_write(codec, reg, val); | 316 | for (i = 0; i < ARRAY_SIZE(wm8903->dcs_cache); i++) { |
317 | if (!(wm8903->dcs_pending & (1 << i))) | ||
318 | continue; | ||
368 | 319 | ||
369 | val |= (WM8903_OUTPUT_INT << shift); | 320 | if (wm8903->dcs_cache[i]) { |
370 | snd_soc_write(codec, reg, val); | 321 | dev_dbg(codec->dev, |
322 | "Restore DC servo %d value %x\n", | ||
323 | 3 - i, wm8903->dcs_cache[i]); | ||
324 | |||
325 | snd_soc_write(codec, WM8903_DC_SERVO_4 + i, | ||
326 | wm8903->dcs_cache[i] & 0xff); | ||
327 | } else { | ||
328 | dev_dbg(codec->dev, | ||
329 | "Calibrate DC servo %d\n", 3 - i); | ||
330 | dcs_mode = WM8903_DCS_MODE_START_STOP; | ||
331 | } | ||
332 | } | ||
371 | 333 | ||
372 | /* Turn on the output ENA_OUTP */ | 334 | /* Don't trust the cache for analogue */ |
373 | val |= (WM8903_OUTPUT_OUT << shift); | 335 | if (wm8903->class_w_users) |
374 | snd_soc_write(codec, reg, val); | 336 | dcs_mode = WM8903_DCS_MODE_START_STOP; |
375 | 337 | ||
376 | /* Enable the DC servo */ | 338 | snd_soc_update_bits(codec, WM8903_DC_SERVO_2, |
377 | dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0); | 339 | WM8903_DCS_MODE_MASK, dcs_mode); |
378 | dcs_reg |= dcs_bit; | ||
379 | snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg); | ||
380 | 340 | ||
381 | /* Remove the short */ | 341 | snd_soc_update_bits(codec, WM8903_DC_SERVO_0, |
382 | val |= (WM8903_OUTPUT_SHORT << shift); | 342 | WM8903_DCS_ENA_MASK, wm8903->dcs_pending); |
383 | snd_soc_write(codec, reg, val); | ||
384 | } | ||
385 | 343 | ||
386 | if (event & SND_SOC_DAPM_PRE_PMD) { | 344 | switch (dcs_mode) { |
387 | val = snd_soc_read(codec, reg); | 345 | case WM8903_DCS_MODE_WRITE_STOP: |
346 | break; | ||
388 | 347 | ||
389 | /* Short the output */ | 348 | case WM8903_DCS_MODE_START_STOP: |
390 | val &= ~(WM8903_OUTPUT_SHORT << shift); | 349 | msleep(270); |
391 | snd_soc_write(codec, reg, val); | ||
392 | 350 | ||
393 | /* Disable the DC servo */ | 351 | /* Cache the measured offsets for digital */ |
394 | dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0); | 352 | if (wm8903->class_w_users) |
395 | dcs_reg &= ~dcs_bit; | 353 | break; |
396 | snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg); | ||
397 | 354 | ||
398 | /* Then disable the intermediate and output stages */ | 355 | for (i = 0; i < ARRAY_SIZE(wm8903->dcs_cache); i++) { |
399 | val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT | | 356 | if (!(wm8903->dcs_pending & (1 << i))) |
400 | WM8903_OUTPUT_IN) << shift); | 357 | continue; |
401 | snd_soc_write(codec, reg, val); | ||
402 | } | ||
403 | 358 | ||
404 | return 0; | 359 | val = snd_soc_read(codec, |
360 | WM8903_DC_SERVO_READBACK_1 + i); | ||
361 | dev_dbg(codec->dev, "DC servo %d: %x\n", | ||
362 | 3 - i, val); | ||
363 | wm8903->dcs_cache[i] = val; | ||
364 | } | ||
365 | break; | ||
366 | |||
367 | default: | ||
368 | pr_warn("DCS mode %d delay not set\n", dcs_mode); | ||
369 | break; | ||
370 | } | ||
371 | |||
372 | wm8903->dcs_pending = 0; | ||
373 | } | ||
405 | } | 374 | } |
406 | 375 | ||
407 | /* | 376 | /* |
@@ -667,6 +636,22 @@ static const struct soc_enum lsidetone_enum = | |||
667 | static const struct soc_enum rsidetone_enum = | 636 | static const struct soc_enum rsidetone_enum = |
668 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); | 637 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); |
669 | 638 | ||
639 | static const char *aif_text[] = { | ||
640 | "Left", "Right" | ||
641 | }; | ||
642 | |||
643 | static const struct soc_enum lcapture_enum = | ||
644 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 7, 2, aif_text); | ||
645 | |||
646 | static const struct soc_enum rcapture_enum = | ||
647 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 6, 2, aif_text); | ||
648 | |||
649 | static const struct soc_enum lplay_enum = | ||
650 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 5, 2, aif_text); | ||
651 | |||
652 | static const struct soc_enum rplay_enum = | ||
653 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 4, 2, aif_text); | ||
654 | |||
670 | static const struct snd_kcontrol_new wm8903_snd_controls[] = { | 655 | static const struct snd_kcontrol_new wm8903_snd_controls[] = { |
671 | 656 | ||
672 | /* Input PGAs - No TLV since the scale depends on PGA mode */ | 657 | /* Input PGAs - No TLV since the scale depends on PGA mode */ |
@@ -784,6 +769,18 @@ static const struct snd_kcontrol_new lsidetone_mux = | |||
784 | static const struct snd_kcontrol_new rsidetone_mux = | 769 | static const struct snd_kcontrol_new rsidetone_mux = |
785 | SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum); | 770 | SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum); |
786 | 771 | ||
772 | static const struct snd_kcontrol_new lcapture_mux = | ||
773 | SOC_DAPM_ENUM("Left Capture Mux", lcapture_enum); | ||
774 | |||
775 | static const struct snd_kcontrol_new rcapture_mux = | ||
776 | SOC_DAPM_ENUM("Right Capture Mux", rcapture_enum); | ||
777 | |||
778 | static const struct snd_kcontrol_new lplay_mux = | ||
779 | SOC_DAPM_ENUM("Left Playback Mux", lplay_enum); | ||
780 | |||
781 | static const struct snd_kcontrol_new rplay_mux = | ||
782 | SOC_DAPM_ENUM("Right Playback Mux", rplay_enum); | ||
783 | |||
787 | static const struct snd_kcontrol_new left_output_mixer[] = { | 784 | static const struct snd_kcontrol_new left_output_mixer[] = { |
788 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), | 785 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), |
789 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), | 786 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), |
@@ -847,14 +844,26 @@ SND_SOC_DAPM_MUX("Right Input Mode Mux", SND_SOC_NOPM, 0, 0, &rinput_mode_mux), | |||
847 | SND_SOC_DAPM_PGA("Left Input PGA", WM8903_POWER_MANAGEMENT_0, 1, 0, NULL, 0), | 844 | SND_SOC_DAPM_PGA("Left Input PGA", WM8903_POWER_MANAGEMENT_0, 1, 0, NULL, 0), |
848 | SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0), | 845 | SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0), |
849 | 846 | ||
850 | SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8903_POWER_MANAGEMENT_6, 1, 0), | 847 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8903_POWER_MANAGEMENT_6, 1, 0), |
851 | SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0), | 848 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8903_POWER_MANAGEMENT_6, 0, 0), |
849 | |||
850 | SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lcapture_mux), | ||
851 | SND_SOC_DAPM_MUX("Right Capture Mux", SND_SOC_NOPM, 0, 0, &rcapture_mux), | ||
852 | |||
853 | SND_SOC_DAPM_AIF_OUT("AIFTXL", "Left HiFi Capture", 0, SND_SOC_NOPM, 0, 0), | ||
854 | SND_SOC_DAPM_AIF_OUT("AIFTXR", "Right HiFi Capture", 0, SND_SOC_NOPM, 0, 0), | ||
852 | 855 | ||
853 | SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &lsidetone_mux), | 856 | SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &lsidetone_mux), |
854 | SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &rsidetone_mux), | 857 | SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &rsidetone_mux), |
855 | 858 | ||
856 | SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0), | 859 | SND_SOC_DAPM_AIF_IN("AIFRXL", "Left Playback", 0, SND_SOC_NOPM, 0, 0), |
857 | SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0), | 860 | SND_SOC_DAPM_AIF_IN("AIFRXR", "Right Playback", 0, SND_SOC_NOPM, 0, 0), |
861 | |||
862 | SND_SOC_DAPM_MUX("Left Playback Mux", SND_SOC_NOPM, 0, 0, &lplay_mux), | ||
863 | SND_SOC_DAPM_MUX("Right Playback Mux", SND_SOC_NOPM, 0, 0, &rplay_mux), | ||
864 | |||
865 | SND_SOC_DAPM_DAC("DACL", NULL, WM8903_POWER_MANAGEMENT_6, 3, 0), | ||
866 | SND_SOC_DAPM_DAC("DACR", NULL, WM8903_POWER_MANAGEMENT_6, 2, 0), | ||
858 | 867 | ||
859 | SND_SOC_DAPM_MIXER("Left Output Mixer", WM8903_POWER_MANAGEMENT_1, 1, 0, | 868 | SND_SOC_DAPM_MIXER("Left Output Mixer", WM8903_POWER_MANAGEMENT_1, 1, 0, |
860 | left_output_mixer, ARRAY_SIZE(left_output_mixer)), | 869 | left_output_mixer, ARRAY_SIZE(left_output_mixer)), |
@@ -866,23 +875,45 @@ SND_SOC_DAPM_MIXER("Left Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 1, 0, | |||
866 | SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0, | 875 | SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0, |
867 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), | 876 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), |
868 | 877 | ||
869 | SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, | 878 | SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0, |
870 | 1, 0, NULL, 0, wm8903_output_event, | 879 | 4, 0, NULL, 0), |
871 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 880 | SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0, |
872 | SND_SOC_DAPM_PRE_PMD), | 881 | 0, 0, NULL, 0), |
873 | SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, | 882 | |
874 | 0, 0, NULL, 0, wm8903_output_event, | 883 | SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 4, 0, |
875 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 884 | NULL, 0), |
876 | SND_SOC_DAPM_PRE_PMD), | 885 | SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 0, 0, |
877 | 886 | NULL, 0), | |
878 | SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0, | 887 | |
879 | NULL, 0, wm8903_output_event, | 888 | SND_SOC_DAPM_PGA_S("HPL_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 7, 0, NULL, 0), |
880 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 889 | SND_SOC_DAPM_PGA_S("HPL_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 6, 0, NULL, 0), |
881 | SND_SOC_DAPM_PRE_PMD), | 890 | SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0), |
882 | SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0, | 891 | SND_SOC_DAPM_PGA_S("HPR_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 3, 0, NULL, 0), |
883 | NULL, 0, wm8903_output_event, | 892 | SND_SOC_DAPM_PGA_S("HPR_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 2, 0, NULL, 0), |
884 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 893 | SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0), |
885 | SND_SOC_DAPM_PRE_PMD), | 894 | |
895 | SND_SOC_DAPM_PGA_S("LINEOUTL_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 7, 0, | ||
896 | NULL, 0), | ||
897 | SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 6, 0, | ||
898 | NULL, 0), | ||
899 | SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 5, 0, | ||
900 | NULL, 0), | ||
901 | SND_SOC_DAPM_PGA_S("LINEOUTR_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 3, 0, | ||
902 | NULL, 0), | ||
903 | SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 2, 0, | ||
904 | NULL, 0), | ||
905 | SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 1, 0, | ||
906 | NULL, 0), | ||
907 | |||
908 | SND_SOC_DAPM_SUPPLY("DCS Master", WM8903_DC_SERVO_0, 4, 0, NULL, 0), | ||
909 | SND_SOC_DAPM_PGA_S("HPL_DCS", 3, SND_SOC_NOPM, 3, 0, wm8903_dcs_event, | ||
910 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
911 | SND_SOC_DAPM_PGA_S("HPR_DCS", 3, SND_SOC_NOPM, 2, 0, wm8903_dcs_event, | ||
912 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
913 | SND_SOC_DAPM_PGA_S("LINEOUTL_DCS", 3, SND_SOC_NOPM, 1, 0, wm8903_dcs_event, | ||
914 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
915 | SND_SOC_DAPM_PGA_S("LINEOUTR_DCS", 3, SND_SOC_NOPM, 0, 0, wm8903_dcs_event, | ||
916 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
886 | 917 | ||
887 | SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0, | 918 | SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0, |
888 | NULL, 0), | 919 | NULL, 0), |
@@ -892,10 +923,18 @@ SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0, | |||
892 | SND_SOC_DAPM_SUPPLY("Charge Pump", WM8903_CHARGE_PUMP_0, 0, 0, | 923 | SND_SOC_DAPM_SUPPLY("Charge Pump", WM8903_CHARGE_PUMP_0, 0, 0, |
893 | wm8903_cp_event, SND_SOC_DAPM_POST_PMU), | 924 | wm8903_cp_event, SND_SOC_DAPM_POST_PMU), |
894 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0), | 925 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0), |
926 | SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0), | ||
895 | }; | 927 | }; |
896 | 928 | ||
897 | static const struct snd_soc_dapm_route intercon[] = { | 929 | static const struct snd_soc_dapm_route intercon[] = { |
898 | 930 | ||
931 | { "CLK_DSP", NULL, "CLK_SYS" }, | ||
932 | { "Mic Bias", NULL, "CLK_SYS" }, | ||
933 | { "HPL_DCS", NULL, "CLK_SYS" }, | ||
934 | { "HPR_DCS", NULL, "CLK_SYS" }, | ||
935 | { "LINEOUTL_DCS", NULL, "CLK_SYS" }, | ||
936 | { "LINEOUTR_DCS", NULL, "CLK_SYS" }, | ||
937 | |||
899 | { "Left Input Mux", "IN1L", "IN1L" }, | 938 | { "Left Input Mux", "IN1L", "IN1L" }, |
900 | { "Left Input Mux", "IN2L", "IN2L" }, | 939 | { "Left Input Mux", "IN2L", "IN2L" }, |
901 | { "Left Input Mux", "IN3L", "IN3L" }, | 940 | { "Left Input Mux", "IN3L", "IN3L" }, |
@@ -936,18 +975,36 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
936 | { "Left Input PGA", NULL, "Left Input Mode Mux" }, | 975 | { "Left Input PGA", NULL, "Left Input Mode Mux" }, |
937 | { "Right Input PGA", NULL, "Right Input Mode Mux" }, | 976 | { "Right Input PGA", NULL, "Right Input Mode Mux" }, |
938 | 977 | ||
978 | { "Left Capture Mux", "Left", "ADCL" }, | ||
979 | { "Left Capture Mux", "Right", "ADCR" }, | ||
980 | |||
981 | { "Right Capture Mux", "Left", "ADCL" }, | ||
982 | { "Right Capture Mux", "Right", "ADCR" }, | ||
983 | |||
984 | { "AIFTXL", NULL, "Left Capture Mux" }, | ||
985 | { "AIFTXR", NULL, "Right Capture Mux" }, | ||
986 | |||
939 | { "ADCL", NULL, "Left Input PGA" }, | 987 | { "ADCL", NULL, "Left Input PGA" }, |
940 | { "ADCL", NULL, "CLK_DSP" }, | 988 | { "ADCL", NULL, "CLK_DSP" }, |
941 | { "ADCR", NULL, "Right Input PGA" }, | 989 | { "ADCR", NULL, "Right Input PGA" }, |
942 | { "ADCR", NULL, "CLK_DSP" }, | 990 | { "ADCR", NULL, "CLK_DSP" }, |
943 | 991 | ||
992 | { "Left Playback Mux", "Left", "AIFRXL" }, | ||
993 | { "Left Playback Mux", "Right", "AIFRXR" }, | ||
994 | |||
995 | { "Right Playback Mux", "Left", "AIFRXL" }, | ||
996 | { "Right Playback Mux", "Right", "AIFRXR" }, | ||
997 | |||
944 | { "DACL Sidetone", "Left", "ADCL" }, | 998 | { "DACL Sidetone", "Left", "ADCL" }, |
945 | { "DACL Sidetone", "Right", "ADCR" }, | 999 | { "DACL Sidetone", "Right", "ADCR" }, |
946 | { "DACR Sidetone", "Left", "ADCL" }, | 1000 | { "DACR Sidetone", "Left", "ADCL" }, |
947 | { "DACR Sidetone", "Right", "ADCR" }, | 1001 | { "DACR Sidetone", "Right", "ADCR" }, |
948 | 1002 | ||
1003 | { "DACL", NULL, "Left Playback Mux" }, | ||
949 | { "DACL", NULL, "DACL Sidetone" }, | 1004 | { "DACL", NULL, "DACL Sidetone" }, |
950 | { "DACL", NULL, "CLK_DSP" }, | 1005 | { "DACL", NULL, "CLK_DSP" }, |
1006 | |||
1007 | { "DACR", NULL, "Right Playback Mux" }, | ||
951 | { "DACR", NULL, "DACR Sidetone" }, | 1008 | { "DACR", NULL, "DACR Sidetone" }, |
952 | { "DACR", NULL, "CLK_DSP" }, | 1009 | { "DACR", NULL, "CLK_DSP" }, |
953 | 1010 | ||
@@ -980,11 +1037,35 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
980 | { "Left Speaker PGA", NULL, "Left Speaker Mixer" }, | 1037 | { "Left Speaker PGA", NULL, "Left Speaker Mixer" }, |
981 | { "Right Speaker PGA", NULL, "Right Speaker Mixer" }, | 1038 | { "Right Speaker PGA", NULL, "Right Speaker Mixer" }, |
982 | 1039 | ||
983 | { "HPOUTL", NULL, "Left Headphone Output PGA" }, | 1040 | { "HPL_ENA_DLY", NULL, "Left Headphone Output PGA" }, |
984 | { "HPOUTR", NULL, "Right Headphone Output PGA" }, | 1041 | { "HPR_ENA_DLY", NULL, "Right Headphone Output PGA" }, |
1042 | { "LINEOUTL_ENA_DLY", NULL, "Left Line Output PGA" }, | ||
1043 | { "LINEOUTR_ENA_DLY", NULL, "Right Line Output PGA" }, | ||
1044 | |||
1045 | { "HPL_DCS", NULL, "DCS Master" }, | ||
1046 | { "HPR_DCS", NULL, "DCS Master" }, | ||
1047 | { "LINEOUTL_DCS", NULL, "DCS Master" }, | ||
1048 | { "LINEOUTR_DCS", NULL, "DCS Master" }, | ||
1049 | |||
1050 | { "HPL_DCS", NULL, "HPL_ENA_DLY" }, | ||
1051 | { "HPR_DCS", NULL, "HPR_ENA_DLY" }, | ||
1052 | { "LINEOUTL_DCS", NULL, "LINEOUTL_ENA_DLY" }, | ||
1053 | { "LINEOUTR_DCS", NULL, "LINEOUTR_ENA_DLY" }, | ||
985 | 1054 | ||
986 | { "LINEOUTL", NULL, "Left Line Output PGA" }, | 1055 | { "HPL_ENA_OUTP", NULL, "HPL_DCS" }, |
987 | { "LINEOUTR", NULL, "Right Line Output PGA" }, | 1056 | { "HPR_ENA_OUTP", NULL, "HPR_DCS" }, |
1057 | { "LINEOUTL_ENA_OUTP", NULL, "LINEOUTL_DCS" }, | ||
1058 | { "LINEOUTR_ENA_OUTP", NULL, "LINEOUTR_DCS" }, | ||
1059 | |||
1060 | { "HPL_RMV_SHORT", NULL, "HPL_ENA_OUTP" }, | ||
1061 | { "HPR_RMV_SHORT", NULL, "HPR_ENA_OUTP" }, | ||
1062 | { "LINEOUTL_RMV_SHORT", NULL, "LINEOUTL_ENA_OUTP" }, | ||
1063 | { "LINEOUTR_RMV_SHORT", NULL, "LINEOUTR_ENA_OUTP" }, | ||
1064 | |||
1065 | { "HPOUTL", NULL, "HPL_RMV_SHORT" }, | ||
1066 | { "HPOUTR", NULL, "HPR_RMV_SHORT" }, | ||
1067 | { "LINEOUTL", NULL, "LINEOUTL_RMV_SHORT" }, | ||
1068 | { "LINEOUTR", NULL, "LINEOUTR_RMV_SHORT" }, | ||
988 | 1069 | ||
989 | { "LOP", NULL, "Left Speaker PGA" }, | 1070 | { "LOP", NULL, "Left Speaker PGA" }, |
990 | { "LON", NULL, "Left Speaker PGA" }, | 1071 | { "LON", NULL, "Left Speaker PGA" }, |
@@ -1012,29 +1093,71 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec) | |||
1012 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, | 1093 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, |
1013 | enum snd_soc_bias_level level) | 1094 | enum snd_soc_bias_level level) |
1014 | { | 1095 | { |
1015 | u16 reg; | ||
1016 | |||
1017 | switch (level) { | 1096 | switch (level) { |
1018 | case SND_SOC_BIAS_ON: | 1097 | case SND_SOC_BIAS_ON: |
1098 | break; | ||
1099 | |||
1019 | case SND_SOC_BIAS_PREPARE: | 1100 | case SND_SOC_BIAS_PREPARE: |
1020 | reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0); | 1101 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, |
1021 | reg &= ~(WM8903_VMID_RES_MASK); | 1102 | WM8903_VMID_RES_MASK, |
1022 | reg |= WM8903_VMID_RES_50K; | 1103 | WM8903_VMID_RES_50K); |
1023 | snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg); | ||
1024 | break; | 1104 | break; |
1025 | 1105 | ||
1026 | case SND_SOC_BIAS_STANDBY: | 1106 | case SND_SOC_BIAS_STANDBY: |
1027 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1107 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
1028 | snd_soc_write(codec, WM8903_CLOCK_RATES_2, | 1108 | snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, |
1029 | WM8903_CLK_SYS_ENA); | 1109 | WM8903_POBCTRL | WM8903_ISEL_MASK | |
1030 | 1110 | WM8903_STARTUP_BIAS_ENA | | |
1031 | /* Change DC servo dither level in startup sequence */ | 1111 | WM8903_BIAS_ENA, |
1032 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11); | 1112 | WM8903_POBCTRL | |
1033 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257); | 1113 | (2 << WM8903_ISEL_SHIFT) | |
1034 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2); | 1114 | WM8903_STARTUP_BIAS_ENA); |
1035 | 1115 | ||
1036 | wm8903_run_sequence(codec, 0); | 1116 | snd_soc_update_bits(codec, |
1037 | wm8903_sync_reg_cache(codec, codec->reg_cache); | 1117 | WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0, |
1118 | WM8903_SPK_DISCHARGE, | ||
1119 | WM8903_SPK_DISCHARGE); | ||
1120 | |||
1121 | msleep(33); | ||
1122 | |||
1123 | snd_soc_update_bits(codec, WM8903_POWER_MANAGEMENT_5, | ||
1124 | WM8903_SPKL_ENA | WM8903_SPKR_ENA, | ||
1125 | WM8903_SPKL_ENA | WM8903_SPKR_ENA); | ||
1126 | |||
1127 | snd_soc_update_bits(codec, | ||
1128 | WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0, | ||
1129 | WM8903_SPK_DISCHARGE, 0); | ||
1130 | |||
1131 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, | ||
1132 | WM8903_VMID_TIE_ENA | | ||
1133 | WM8903_BUFIO_ENA | | ||
1134 | WM8903_VMID_IO_ENA | | ||
1135 | WM8903_VMID_SOFT_MASK | | ||
1136 | WM8903_VMID_RES_MASK | | ||
1137 | WM8903_VMID_BUF_ENA, | ||
1138 | WM8903_VMID_TIE_ENA | | ||
1139 | WM8903_BUFIO_ENA | | ||
1140 | WM8903_VMID_IO_ENA | | ||
1141 | (2 << WM8903_VMID_SOFT_SHIFT) | | ||
1142 | WM8903_VMID_RES_250K | | ||
1143 | WM8903_VMID_BUF_ENA); | ||
1144 | |||
1145 | msleep(129); | ||
1146 | |||
1147 | snd_soc_update_bits(codec, WM8903_POWER_MANAGEMENT_5, | ||
1148 | WM8903_SPKL_ENA | WM8903_SPKR_ENA, | ||
1149 | 0); | ||
1150 | |||
1151 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, | ||
1152 | WM8903_VMID_SOFT_MASK, 0); | ||
1153 | |||
1154 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, | ||
1155 | WM8903_VMID_RES_MASK, | ||
1156 | WM8903_VMID_RES_50K); | ||
1157 | |||
1158 | snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, | ||
1159 | WM8903_BIAS_ENA | WM8903_POBCTRL, | ||
1160 | WM8903_BIAS_ENA); | ||
1038 | 1161 | ||
1039 | /* By default no bypass paths are enabled so | 1162 | /* By default no bypass paths are enabled so |
1040 | * enable Class W support. | 1163 | * enable Class W support. |
@@ -1047,17 +1170,32 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, | |||
1047 | WM8903_CP_DYN_V); | 1170 | WM8903_CP_DYN_V); |
1048 | } | 1171 | } |
1049 | 1172 | ||
1050 | reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0); | 1173 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, |
1051 | reg &= ~(WM8903_VMID_RES_MASK); | 1174 | WM8903_VMID_RES_MASK, |
1052 | reg |= WM8903_VMID_RES_250K; | 1175 | WM8903_VMID_RES_250K); |
1053 | snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg); | ||
1054 | break; | 1176 | break; |
1055 | 1177 | ||
1056 | case SND_SOC_BIAS_OFF: | 1178 | case SND_SOC_BIAS_OFF: |
1057 | wm8903_run_sequence(codec, 32); | 1179 | snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, |
1058 | reg = snd_soc_read(codec, WM8903_CLOCK_RATES_2); | 1180 | WM8903_BIAS_ENA, 0); |
1059 | reg &= ~WM8903_CLK_SYS_ENA; | 1181 | |
1060 | snd_soc_write(codec, WM8903_CLOCK_RATES_2, reg); | 1182 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, |
1183 | WM8903_VMID_SOFT_MASK, | ||
1184 | 2 << WM8903_VMID_SOFT_SHIFT); | ||
1185 | |||
1186 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, | ||
1187 | WM8903_VMID_BUF_ENA, 0); | ||
1188 | |||
1189 | msleep(290); | ||
1190 | |||
1191 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, | ||
1192 | WM8903_VMID_TIE_ENA | WM8903_BUFIO_ENA | | ||
1193 | WM8903_VMID_IO_ENA | WM8903_VMID_RES_MASK | | ||
1194 | WM8903_VMID_SOFT_MASK | | ||
1195 | WM8903_VMID_BUF_ENA, 0); | ||
1196 | |||
1197 | snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, | ||
1198 | WM8903_STARTUP_BIAS_ENA, 0); | ||
1061 | break; | 1199 | break; |
1062 | } | 1200 | } |
1063 | 1201 | ||
@@ -1510,8 +1648,7 @@ static irqreturn_t wm8903_irq(int irq, void *data) | |||
1510 | int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask; | 1648 | int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask; |
1511 | 1649 | ||
1512 | if (int_val & WM8903_WSEQ_BUSY_EINT) { | 1650 | if (int_val & WM8903_WSEQ_BUSY_EINT) { |
1513 | dev_dbg(codec->dev, "Write sequencer done\n"); | 1651 | dev_warn(codec->dev, "Write sequencer done\n"); |
1514 | complete(&wm8903->wseq); | ||
1515 | } | 1652 | } |
1516 | 1653 | ||
1517 | /* | 1654 | /* |
@@ -1635,6 +1772,120 @@ static int wm8903_resume(struct snd_soc_codec *codec) | |||
1635 | return 0; | 1772 | return 0; |
1636 | } | 1773 | } |
1637 | 1774 | ||
1775 | #ifdef CONFIG_GPIOLIB | ||
1776 | static inline struct wm8903_priv *gpio_to_wm8903(struct gpio_chip *chip) | ||
1777 | { | ||
1778 | return container_of(chip, struct wm8903_priv, gpio_chip); | ||
1779 | } | ||
1780 | |||
1781 | static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
1782 | { | ||
1783 | if (offset >= WM8903_NUM_GPIO) | ||
1784 | return -EINVAL; | ||
1785 | |||
1786 | return 0; | ||
1787 | } | ||
1788 | |||
1789 | static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | ||
1790 | { | ||
1791 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | ||
1792 | struct snd_soc_codec *codec = wm8903->codec; | ||
1793 | unsigned int mask, val; | ||
1794 | |||
1795 | mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK; | ||
1796 | val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) | | ||
1797 | WM8903_GP1_DIR; | ||
1798 | |||
1799 | return snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | ||
1800 | mask, val); | ||
1801 | } | ||
1802 | |||
1803 | static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
1804 | { | ||
1805 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | ||
1806 | struct snd_soc_codec *codec = wm8903->codec; | ||
1807 | int reg; | ||
1808 | |||
1809 | reg = snd_soc_read(codec, WM8903_GPIO_CONTROL_1 + offset); | ||
1810 | |||
1811 | return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT; | ||
1812 | } | ||
1813 | |||
1814 | static int wm8903_gpio_direction_out(struct gpio_chip *chip, | ||
1815 | unsigned offset, int value) | ||
1816 | { | ||
1817 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | ||
1818 | struct snd_soc_codec *codec = wm8903->codec; | ||
1819 | unsigned int mask, val; | ||
1820 | |||
1821 | mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK | WM8903_GP1_LVL_MASK; | ||
1822 | val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) | | ||
1823 | (value << WM8903_GP2_LVL_SHIFT); | ||
1824 | |||
1825 | return snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | ||
1826 | mask, val); | ||
1827 | } | ||
1828 | |||
1829 | static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
1830 | { | ||
1831 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | ||
1832 | struct snd_soc_codec *codec = wm8903->codec; | ||
1833 | |||
1834 | snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | ||
1835 | WM8903_GP1_LVL_MASK, | ||
1836 | !!value << WM8903_GP1_LVL_SHIFT); | ||
1837 | } | ||
1838 | |||
1839 | static struct gpio_chip wm8903_template_chip = { | ||
1840 | .label = "wm8903", | ||
1841 | .owner = THIS_MODULE, | ||
1842 | .request = wm8903_gpio_request, | ||
1843 | .direction_input = wm8903_gpio_direction_in, | ||
1844 | .get = wm8903_gpio_get, | ||
1845 | .direction_output = wm8903_gpio_direction_out, | ||
1846 | .set = wm8903_gpio_set, | ||
1847 | .can_sleep = 1, | ||
1848 | }; | ||
1849 | |||
1850 | static void wm8903_init_gpio(struct snd_soc_codec *codec) | ||
1851 | { | ||
1852 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1853 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); | ||
1854 | int ret; | ||
1855 | |||
1856 | wm8903->gpio_chip = wm8903_template_chip; | ||
1857 | wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO; | ||
1858 | wm8903->gpio_chip.dev = codec->dev; | ||
1859 | |||
1860 | if (pdata && pdata->gpio_base) | ||
1861 | wm8903->gpio_chip.base = pdata->gpio_base; | ||
1862 | else | ||
1863 | wm8903->gpio_chip.base = -1; | ||
1864 | |||
1865 | ret = gpiochip_add(&wm8903->gpio_chip); | ||
1866 | if (ret != 0) | ||
1867 | dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); | ||
1868 | } | ||
1869 | |||
1870 | static void wm8903_free_gpio(struct snd_soc_codec *codec) | ||
1871 | { | ||
1872 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1873 | int ret; | ||
1874 | |||
1875 | ret = gpiochip_remove(&wm8903->gpio_chip); | ||
1876 | if (ret != 0) | ||
1877 | dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); | ||
1878 | } | ||
1879 | #else | ||
1880 | static void wm8903_init_gpio(struct snd_soc_codec *codec) | ||
1881 | { | ||
1882 | } | ||
1883 | |||
1884 | static void wm8903_free_gpio(struct snd_soc_codec *codec) | ||
1885 | { | ||
1886 | } | ||
1887 | #endif | ||
1888 | |||
1638 | static int wm8903_probe(struct snd_soc_codec *codec) | 1889 | static int wm8903_probe(struct snd_soc_codec *codec) |
1639 | { | 1890 | { |
1640 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); | 1891 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); |
@@ -1643,7 +1894,7 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1643 | int trigger, irq_pol; | 1894 | int trigger, irq_pol; |
1644 | u16 val; | 1895 | u16 val; |
1645 | 1896 | ||
1646 | init_completion(&wm8903->wseq); | 1897 | wm8903->codec = codec; |
1647 | 1898 | ||
1648 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1899 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1649 | if (ret != 0) { | 1900 | if (ret != 0) { |
@@ -1659,19 +1910,33 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1659 | } | 1910 | } |
1660 | 1911 | ||
1661 | val = snd_soc_read(codec, WM8903_REVISION_NUMBER); | 1912 | val = snd_soc_read(codec, WM8903_REVISION_NUMBER); |
1662 | dev_info(codec->dev, "WM8903 revision %d\n", | 1913 | dev_info(codec->dev, "WM8903 revision %c\n", |
1663 | val & WM8903_CHIP_REV_MASK); | 1914 | (val & WM8903_CHIP_REV_MASK) + 'A'); |
1664 | 1915 | ||
1665 | wm8903_reset(codec); | 1916 | wm8903_reset(codec); |
1666 | 1917 | ||
1667 | /* Set up GPIOs and microphone detection */ | 1918 | /* Set up GPIOs and microphone detection */ |
1668 | if (pdata) { | 1919 | if (pdata) { |
1920 | bool mic_gpio = false; | ||
1921 | |||
1669 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { | 1922 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { |
1670 | if (!pdata->gpio_cfg[i]) | 1923 | if (pdata->gpio_cfg[i] == WM8903_GPIO_NO_CONFIG) |
1671 | continue; | 1924 | continue; |
1672 | 1925 | ||
1673 | snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, | 1926 | snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, |
1674 | pdata->gpio_cfg[i] & 0xffff); | 1927 | pdata->gpio_cfg[i] & 0xffff); |
1928 | |||
1929 | val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK) | ||
1930 | >> WM8903_GP1_FN_SHIFT; | ||
1931 | |||
1932 | switch (val) { | ||
1933 | case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT: | ||
1934 | case WM8903_GPn_FN_MICBIAS_SHORT_DETECT: | ||
1935 | mic_gpio = true; | ||
1936 | break; | ||
1937 | default: | ||
1938 | break; | ||
1939 | } | ||
1675 | } | 1940 | } |
1676 | 1941 | ||
1677 | snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, | 1942 | snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, |
@@ -1682,6 +1947,14 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1682 | snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, | 1947 | snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, |
1683 | WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); | 1948 | WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); |
1684 | 1949 | ||
1950 | /* If microphone detection is enabled by pdata but | ||
1951 | * detected via IRQ then interrupts can be lost before | ||
1952 | * the machine driver has set up microphone detection | ||
1953 | * IRQs as the IRQs are clear on read. The detection | ||
1954 | * will be enabled when the machine driver configures. | ||
1955 | */ | ||
1956 | WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA)); | ||
1957 | |||
1685 | wm8903->mic_delay = pdata->micdet_delay; | 1958 | wm8903->mic_delay = pdata->micdet_delay; |
1686 | } | 1959 | } |
1687 | 1960 | ||
@@ -1741,20 +2014,23 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1741 | snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); | 2014 | snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); |
1742 | 2015 | ||
1743 | /* Enable DAC soft mute by default */ | 2016 | /* Enable DAC soft mute by default */ |
1744 | val = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); | 2017 | snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1, |
1745 | val |= WM8903_DAC_MUTEMODE; | 2018 | WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, |
1746 | snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val); | 2019 | WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); |
1747 | 2020 | ||
1748 | snd_soc_add_controls(codec, wm8903_snd_controls, | 2021 | snd_soc_add_controls(codec, wm8903_snd_controls, |
1749 | ARRAY_SIZE(wm8903_snd_controls)); | 2022 | ARRAY_SIZE(wm8903_snd_controls)); |
1750 | wm8903_add_widgets(codec); | 2023 | wm8903_add_widgets(codec); |
1751 | 2024 | ||
2025 | wm8903_init_gpio(codec); | ||
2026 | |||
1752 | return ret; | 2027 | return ret; |
1753 | } | 2028 | } |
1754 | 2029 | ||
1755 | /* power down chip */ | 2030 | /* power down chip */ |
1756 | static int wm8903_remove(struct snd_soc_codec *codec) | 2031 | static int wm8903_remove(struct snd_soc_codec *codec) |
1757 | { | 2032 | { |
2033 | wm8903_free_gpio(codec); | ||
1758 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2034 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1759 | return 0; | 2035 | return 0; |
1760 | } | 2036 | } |
@@ -1769,6 +2045,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { | |||
1769 | .reg_word_size = sizeof(u16), | 2045 | .reg_word_size = sizeof(u16), |
1770 | .reg_cache_default = wm8903_reg_defaults, | 2046 | .reg_cache_default = wm8903_reg_defaults, |
1771 | .volatile_register = wm8903_volatile_register, | 2047 | .volatile_register = wm8903_volatile_register, |
2048 | .seq_notifier = wm8903_seq_notifier, | ||
1772 | }; | 2049 | }; |
1773 | 2050 | ||
1774 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 2051 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
@@ -1807,7 +2084,7 @@ MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); | |||
1807 | 2084 | ||
1808 | static struct i2c_driver wm8903_i2c_driver = { | 2085 | static struct i2c_driver wm8903_i2c_driver = { |
1809 | .driver = { | 2086 | .driver = { |
1810 | .name = "wm8903-codec", | 2087 | .name = "wm8903", |
1811 | .owner = THIS_MODULE, | 2088 | .owner = THIS_MODULE, |
1812 | }, | 2089 | }, |
1813 | .probe = wm8903_i2c_probe, | 2090 | .probe = wm8903_i2c_probe, |