diff options
Diffstat (limited to 'sound/soc/codecs/wm8996.c')
-rw-r--r-- | sound/soc/codecs/wm8996.c | 587 |
1 files changed, 215 insertions, 372 deletions
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index dc9b42b7fc4d..00f183dfa454 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8996.c - WM8996 audio codec interface | 2 | * wm8996.c - WM8996 audio codec interface |
3 | * | 3 | * |
4 | * Copyright 2011 Wolfson Microelectronics PLC. | 4 | * Copyright 2011-2 Wolfson Microelectronics PLC. |
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
@@ -296,184 +296,6 @@ static struct reg_default wm8996_reg[] = { | |||
296 | { WM8996_RIGHT_PDM_SPEAKER, 0x1 }, | 296 | { WM8996_RIGHT_PDM_SPEAKER, 0x1 }, |
297 | { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 }, | 297 | { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 }, |
298 | { WM8996_PDM_SPEAKER_VOLUME, 0x66 }, | 298 | { WM8996_PDM_SPEAKER_VOLUME, 0x66 }, |
299 | { WM8996_WRITE_SEQUENCER_0, 0x1 }, | ||
300 | { WM8996_WRITE_SEQUENCER_1, 0x1 }, | ||
301 | { WM8996_WRITE_SEQUENCER_3, 0x6 }, | ||
302 | { WM8996_WRITE_SEQUENCER_4, 0x40 }, | ||
303 | { WM8996_WRITE_SEQUENCER_5, 0x1 }, | ||
304 | { WM8996_WRITE_SEQUENCER_6, 0xf }, | ||
305 | { WM8996_WRITE_SEQUENCER_7, 0x6 }, | ||
306 | { WM8996_WRITE_SEQUENCER_8, 0x1 }, | ||
307 | { WM8996_WRITE_SEQUENCER_9, 0x3 }, | ||
308 | { WM8996_WRITE_SEQUENCER_10, 0x104 }, | ||
309 | { WM8996_WRITE_SEQUENCER_12, 0x60 }, | ||
310 | { WM8996_WRITE_SEQUENCER_13, 0x11 }, | ||
311 | { WM8996_WRITE_SEQUENCER_14, 0x401 }, | ||
312 | { WM8996_WRITE_SEQUENCER_16, 0x50 }, | ||
313 | { WM8996_WRITE_SEQUENCER_17, 0x3 }, | ||
314 | { WM8996_WRITE_SEQUENCER_18, 0x100 }, | ||
315 | { WM8996_WRITE_SEQUENCER_20, 0x51 }, | ||
316 | { WM8996_WRITE_SEQUENCER_21, 0x3 }, | ||
317 | { WM8996_WRITE_SEQUENCER_22, 0x104 }, | ||
318 | { WM8996_WRITE_SEQUENCER_23, 0xa }, | ||
319 | { WM8996_WRITE_SEQUENCER_24, 0x60 }, | ||
320 | { WM8996_WRITE_SEQUENCER_25, 0x3b }, | ||
321 | { WM8996_WRITE_SEQUENCER_26, 0x502 }, | ||
322 | { WM8996_WRITE_SEQUENCER_27, 0x100 }, | ||
323 | { WM8996_WRITE_SEQUENCER_28, 0x2fff }, | ||
324 | { WM8996_WRITE_SEQUENCER_32, 0x2fff }, | ||
325 | { WM8996_WRITE_SEQUENCER_36, 0x2fff }, | ||
326 | { WM8996_WRITE_SEQUENCER_40, 0x2fff }, | ||
327 | { WM8996_WRITE_SEQUENCER_44, 0x2fff }, | ||
328 | { WM8996_WRITE_SEQUENCER_48, 0x2fff }, | ||
329 | { WM8996_WRITE_SEQUENCER_52, 0x2fff }, | ||
330 | { WM8996_WRITE_SEQUENCER_56, 0x2fff }, | ||
331 | { WM8996_WRITE_SEQUENCER_60, 0x2fff }, | ||
332 | { WM8996_WRITE_SEQUENCER_64, 0x1 }, | ||
333 | { WM8996_WRITE_SEQUENCER_65, 0x1 }, | ||
334 | { WM8996_WRITE_SEQUENCER_67, 0x6 }, | ||
335 | { WM8996_WRITE_SEQUENCER_68, 0x40 }, | ||
336 | { WM8996_WRITE_SEQUENCER_69, 0x1 }, | ||
337 | { WM8996_WRITE_SEQUENCER_70, 0xf }, | ||
338 | { WM8996_WRITE_SEQUENCER_71, 0x6 }, | ||
339 | { WM8996_WRITE_SEQUENCER_72, 0x1 }, | ||
340 | { WM8996_WRITE_SEQUENCER_73, 0x3 }, | ||
341 | { WM8996_WRITE_SEQUENCER_74, 0x104 }, | ||
342 | { WM8996_WRITE_SEQUENCER_76, 0x60 }, | ||
343 | { WM8996_WRITE_SEQUENCER_77, 0x11 }, | ||
344 | { WM8996_WRITE_SEQUENCER_78, 0x401 }, | ||
345 | { WM8996_WRITE_SEQUENCER_80, 0x50 }, | ||
346 | { WM8996_WRITE_SEQUENCER_81, 0x3 }, | ||
347 | { WM8996_WRITE_SEQUENCER_82, 0x100 }, | ||
348 | { WM8996_WRITE_SEQUENCER_84, 0x60 }, | ||
349 | { WM8996_WRITE_SEQUENCER_85, 0x3b }, | ||
350 | { WM8996_WRITE_SEQUENCER_86, 0x502 }, | ||
351 | { WM8996_WRITE_SEQUENCER_87, 0x100 }, | ||
352 | { WM8996_WRITE_SEQUENCER_88, 0x2fff }, | ||
353 | { WM8996_WRITE_SEQUENCER_92, 0x2fff }, | ||
354 | { WM8996_WRITE_SEQUENCER_96, 0x2fff }, | ||
355 | { WM8996_WRITE_SEQUENCER_100, 0x2fff }, | ||
356 | { WM8996_WRITE_SEQUENCER_104, 0x2fff }, | ||
357 | { WM8996_WRITE_SEQUENCER_108, 0x2fff }, | ||
358 | { WM8996_WRITE_SEQUENCER_112, 0x2fff }, | ||
359 | { WM8996_WRITE_SEQUENCER_116, 0x2fff }, | ||
360 | { WM8996_WRITE_SEQUENCER_120, 0x2fff }, | ||
361 | { WM8996_WRITE_SEQUENCER_124, 0x2fff }, | ||
362 | { WM8996_WRITE_SEQUENCER_128, 0x1 }, | ||
363 | { WM8996_WRITE_SEQUENCER_129, 0x1 }, | ||
364 | { WM8996_WRITE_SEQUENCER_131, 0x6 }, | ||
365 | { WM8996_WRITE_SEQUENCER_132, 0x40 }, | ||
366 | { WM8996_WRITE_SEQUENCER_133, 0x1 }, | ||
367 | { WM8996_WRITE_SEQUENCER_134, 0xf }, | ||
368 | { WM8996_WRITE_SEQUENCER_135, 0x6 }, | ||
369 | { WM8996_WRITE_SEQUENCER_136, 0x1 }, | ||
370 | { WM8996_WRITE_SEQUENCER_137, 0x3 }, | ||
371 | { WM8996_WRITE_SEQUENCER_138, 0x106 }, | ||
372 | { WM8996_WRITE_SEQUENCER_140, 0x61 }, | ||
373 | { WM8996_WRITE_SEQUENCER_141, 0x11 }, | ||
374 | { WM8996_WRITE_SEQUENCER_142, 0x401 }, | ||
375 | { WM8996_WRITE_SEQUENCER_144, 0x50 }, | ||
376 | { WM8996_WRITE_SEQUENCER_145, 0x3 }, | ||
377 | { WM8996_WRITE_SEQUENCER_146, 0x102 }, | ||
378 | { WM8996_WRITE_SEQUENCER_148, 0x51 }, | ||
379 | { WM8996_WRITE_SEQUENCER_149, 0x3 }, | ||
380 | { WM8996_WRITE_SEQUENCER_150, 0x106 }, | ||
381 | { WM8996_WRITE_SEQUENCER_151, 0xa }, | ||
382 | { WM8996_WRITE_SEQUENCER_152, 0x61 }, | ||
383 | { WM8996_WRITE_SEQUENCER_153, 0x3b }, | ||
384 | { WM8996_WRITE_SEQUENCER_154, 0x502 }, | ||
385 | { WM8996_WRITE_SEQUENCER_155, 0x100 }, | ||
386 | { WM8996_WRITE_SEQUENCER_156, 0x2fff }, | ||
387 | { WM8996_WRITE_SEQUENCER_160, 0x2fff }, | ||
388 | { WM8996_WRITE_SEQUENCER_164, 0x2fff }, | ||
389 | { WM8996_WRITE_SEQUENCER_168, 0x2fff }, | ||
390 | { WM8996_WRITE_SEQUENCER_172, 0x2fff }, | ||
391 | { WM8996_WRITE_SEQUENCER_176, 0x2fff }, | ||
392 | { WM8996_WRITE_SEQUENCER_180, 0x2fff }, | ||
393 | { WM8996_WRITE_SEQUENCER_184, 0x2fff }, | ||
394 | { WM8996_WRITE_SEQUENCER_188, 0x2fff }, | ||
395 | { WM8996_WRITE_SEQUENCER_192, 0x1 }, | ||
396 | { WM8996_WRITE_SEQUENCER_193, 0x1 }, | ||
397 | { WM8996_WRITE_SEQUENCER_195, 0x6 }, | ||
398 | { WM8996_WRITE_SEQUENCER_196, 0x40 }, | ||
399 | { WM8996_WRITE_SEQUENCER_197, 0x1 }, | ||
400 | { WM8996_WRITE_SEQUENCER_198, 0xf }, | ||
401 | { WM8996_WRITE_SEQUENCER_199, 0x6 }, | ||
402 | { WM8996_WRITE_SEQUENCER_200, 0x1 }, | ||
403 | { WM8996_WRITE_SEQUENCER_201, 0x3 }, | ||
404 | { WM8996_WRITE_SEQUENCER_202, 0x106 }, | ||
405 | { WM8996_WRITE_SEQUENCER_204, 0x61 }, | ||
406 | { WM8996_WRITE_SEQUENCER_205, 0x11 }, | ||
407 | { WM8996_WRITE_SEQUENCER_206, 0x401 }, | ||
408 | { WM8996_WRITE_SEQUENCER_208, 0x50 }, | ||
409 | { WM8996_WRITE_SEQUENCER_209, 0x3 }, | ||
410 | { WM8996_WRITE_SEQUENCER_210, 0x102 }, | ||
411 | { WM8996_WRITE_SEQUENCER_212, 0x61 }, | ||
412 | { WM8996_WRITE_SEQUENCER_213, 0x3b }, | ||
413 | { WM8996_WRITE_SEQUENCER_214, 0x502 }, | ||
414 | { WM8996_WRITE_SEQUENCER_215, 0x100 }, | ||
415 | { WM8996_WRITE_SEQUENCER_216, 0x2fff }, | ||
416 | { WM8996_WRITE_SEQUENCER_220, 0x2fff }, | ||
417 | { WM8996_WRITE_SEQUENCER_224, 0x2fff }, | ||
418 | { WM8996_WRITE_SEQUENCER_228, 0x2fff }, | ||
419 | { WM8996_WRITE_SEQUENCER_232, 0x2fff }, | ||
420 | { WM8996_WRITE_SEQUENCER_236, 0x2fff }, | ||
421 | { WM8996_WRITE_SEQUENCER_240, 0x2fff }, | ||
422 | { WM8996_WRITE_SEQUENCER_244, 0x2fff }, | ||
423 | { WM8996_WRITE_SEQUENCER_248, 0x2fff }, | ||
424 | { WM8996_WRITE_SEQUENCER_252, 0x2fff }, | ||
425 | { WM8996_WRITE_SEQUENCER_256, 0x60 }, | ||
426 | { WM8996_WRITE_SEQUENCER_258, 0x601 }, | ||
427 | { WM8996_WRITE_SEQUENCER_260, 0x50 }, | ||
428 | { WM8996_WRITE_SEQUENCER_262, 0x100 }, | ||
429 | { WM8996_WRITE_SEQUENCER_264, 0x1 }, | ||
430 | { WM8996_WRITE_SEQUENCER_266, 0x104 }, | ||
431 | { WM8996_WRITE_SEQUENCER_267, 0x100 }, | ||
432 | { WM8996_WRITE_SEQUENCER_268, 0x2fff }, | ||
433 | { WM8996_WRITE_SEQUENCER_272, 0x2fff }, | ||
434 | { WM8996_WRITE_SEQUENCER_276, 0x2fff }, | ||
435 | { WM8996_WRITE_SEQUENCER_280, 0x2fff }, | ||
436 | { WM8996_WRITE_SEQUENCER_284, 0x2fff }, | ||
437 | { WM8996_WRITE_SEQUENCER_288, 0x2fff }, | ||
438 | { WM8996_WRITE_SEQUENCER_292, 0x2fff }, | ||
439 | { WM8996_WRITE_SEQUENCER_296, 0x2fff }, | ||
440 | { WM8996_WRITE_SEQUENCER_300, 0x2fff }, | ||
441 | { WM8996_WRITE_SEQUENCER_304, 0x2fff }, | ||
442 | { WM8996_WRITE_SEQUENCER_308, 0x2fff }, | ||
443 | { WM8996_WRITE_SEQUENCER_312, 0x2fff }, | ||
444 | { WM8996_WRITE_SEQUENCER_316, 0x2fff }, | ||
445 | { WM8996_WRITE_SEQUENCER_320, 0x61 }, | ||
446 | { WM8996_WRITE_SEQUENCER_322, 0x601 }, | ||
447 | { WM8996_WRITE_SEQUENCER_324, 0x50 }, | ||
448 | { WM8996_WRITE_SEQUENCER_326, 0x102 }, | ||
449 | { WM8996_WRITE_SEQUENCER_328, 0x1 }, | ||
450 | { WM8996_WRITE_SEQUENCER_330, 0x106 }, | ||
451 | { WM8996_WRITE_SEQUENCER_331, 0x100 }, | ||
452 | { WM8996_WRITE_SEQUENCER_332, 0x2fff }, | ||
453 | { WM8996_WRITE_SEQUENCER_336, 0x2fff }, | ||
454 | { WM8996_WRITE_SEQUENCER_340, 0x2fff }, | ||
455 | { WM8996_WRITE_SEQUENCER_344, 0x2fff }, | ||
456 | { WM8996_WRITE_SEQUENCER_348, 0x2fff }, | ||
457 | { WM8996_WRITE_SEQUENCER_352, 0x2fff }, | ||
458 | { WM8996_WRITE_SEQUENCER_356, 0x2fff }, | ||
459 | { WM8996_WRITE_SEQUENCER_360, 0x2fff }, | ||
460 | { WM8996_WRITE_SEQUENCER_364, 0x2fff }, | ||
461 | { WM8996_WRITE_SEQUENCER_368, 0x2fff }, | ||
462 | { WM8996_WRITE_SEQUENCER_372, 0x2fff }, | ||
463 | { WM8996_WRITE_SEQUENCER_376, 0x2fff }, | ||
464 | { WM8996_WRITE_SEQUENCER_380, 0x2fff }, | ||
465 | { WM8996_WRITE_SEQUENCER_384, 0x60 }, | ||
466 | { WM8996_WRITE_SEQUENCER_386, 0x601 }, | ||
467 | { WM8996_WRITE_SEQUENCER_388, 0x61 }, | ||
468 | { WM8996_WRITE_SEQUENCER_390, 0x601 }, | ||
469 | { WM8996_WRITE_SEQUENCER_392, 0x50 }, | ||
470 | { WM8996_WRITE_SEQUENCER_394, 0x300 }, | ||
471 | { WM8996_WRITE_SEQUENCER_396, 0x1 }, | ||
472 | { WM8996_WRITE_SEQUENCER_398, 0x304 }, | ||
473 | { WM8996_WRITE_SEQUENCER_400, 0x40 }, | ||
474 | { WM8996_WRITE_SEQUENCER_402, 0xf }, | ||
475 | { WM8996_WRITE_SEQUENCER_404, 0x1 }, | ||
476 | { WM8996_WRITE_SEQUENCER_407, 0x100 }, | ||
477 | }; | 299 | }; |
478 | 300 | ||
479 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0); | 301 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0); |
@@ -1706,18 +1528,6 @@ static bool wm8996_volatile_register(struct device *dev, unsigned int reg) | |||
1706 | } | 1528 | } |
1707 | } | 1529 | } |
1708 | 1530 | ||
1709 | static int wm8996_reset(struct wm8996_priv *wm8996) | ||
1710 | { | ||
1711 | if (wm8996->pdata.ldo_ena > 0) { | ||
1712 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | ||
1713 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1); | ||
1714 | return 0; | ||
1715 | } else { | ||
1716 | return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET, | ||
1717 | 0x8915); | ||
1718 | } | ||
1719 | } | ||
1720 | |||
1721 | static const int bclk_divs[] = { | 1531 | static const int bclk_divs[] = { |
1722 | 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 | 1532 | 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 |
1723 | }; | 1533 | }; |
@@ -1809,8 +1619,10 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, | |||
1809 | 1619 | ||
1810 | case SND_SOC_BIAS_OFF: | 1620 | case SND_SOC_BIAS_OFF: |
1811 | regcache_cache_only(codec->control_data, true); | 1621 | regcache_cache_only(codec->control_data, true); |
1812 | if (wm8996->pdata.ldo_ena >= 0) | 1622 | if (wm8996->pdata.ldo_ena >= 0) { |
1813 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 1623 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
1624 | regcache_cache_only(codec->control_data, true); | ||
1625 | } | ||
1814 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), | 1626 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), |
1815 | wm8996->supplies); | 1627 | wm8996->supplies); |
1816 | break; | 1628 | break; |
@@ -2807,7 +2619,7 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2807 | int ret; | 2619 | int ret; |
2808 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 2620 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
2809 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 2621 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
2810 | int i, irq_flags; | 2622 | int irq_flags; |
2811 | 2623 | ||
2812 | wm8996->codec = codec; | 2624 | wm8996->codec = codec; |
2813 | 2625 | ||
@@ -2822,177 +2634,12 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2822 | goto err; | 2634 | goto err; |
2823 | } | 2635 | } |
2824 | 2636 | ||
2825 | wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; | ||
2826 | wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; | ||
2827 | wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; | ||
2828 | |||
2829 | /* This should really be moved into the regulator core */ | ||
2830 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { | ||
2831 | ret = regulator_register_notifier(wm8996->supplies[i].consumer, | ||
2832 | &wm8996->disable_nb[i]); | ||
2833 | if (ret != 0) { | ||
2834 | dev_err(codec->dev, | ||
2835 | "Failed to register regulator notifier: %d\n", | ||
2836 | ret); | ||
2837 | } | ||
2838 | } | ||
2839 | |||
2840 | /* Apply platform data settings */ | ||
2841 | snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL, | ||
2842 | WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK, | ||
2843 | wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT | | ||
2844 | wm8996->pdata.inr_mode); | ||
2845 | |||
2846 | for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) { | ||
2847 | if (!wm8996->pdata.gpio_default[i]) | ||
2848 | continue; | ||
2849 | |||
2850 | snd_soc_write(codec, WM8996_GPIO_1 + i, | ||
2851 | wm8996->pdata.gpio_default[i] & 0xffff); | ||
2852 | } | ||
2853 | |||
2854 | if (wm8996->pdata.spkmute_seq) | ||
2855 | snd_soc_update_bits(codec, WM8996_PDM_SPEAKER_MUTE_SEQUENCE, | ||
2856 | WM8996_SPK_MUTE_ENDIAN | | ||
2857 | WM8996_SPK_MUTE_SEQ1_MASK, | ||
2858 | wm8996->pdata.spkmute_seq); | ||
2859 | |||
2860 | snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_2, | ||
2861 | WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC | | ||
2862 | WM8996_MICD_SRC, wm8996->pdata.micdet_def); | ||
2863 | |||
2864 | /* Latch volume update bits */ | ||
2865 | snd_soc_update_bits(codec, WM8996_LEFT_LINE_INPUT_VOLUME, | ||
2866 | WM8996_IN1_VU, WM8996_IN1_VU); | ||
2867 | snd_soc_update_bits(codec, WM8996_RIGHT_LINE_INPUT_VOLUME, | ||
2868 | WM8996_IN1_VU, WM8996_IN1_VU); | ||
2869 | |||
2870 | snd_soc_update_bits(codec, WM8996_DAC1_LEFT_VOLUME, | ||
2871 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2872 | snd_soc_update_bits(codec, WM8996_DAC1_RIGHT_VOLUME, | ||
2873 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2874 | snd_soc_update_bits(codec, WM8996_DAC2_LEFT_VOLUME, | ||
2875 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2876 | snd_soc_update_bits(codec, WM8996_DAC2_RIGHT_VOLUME, | ||
2877 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2878 | |||
2879 | snd_soc_update_bits(codec, WM8996_OUTPUT1_LEFT_VOLUME, | ||
2880 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2881 | snd_soc_update_bits(codec, WM8996_OUTPUT1_RIGHT_VOLUME, | ||
2882 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2883 | snd_soc_update_bits(codec, WM8996_OUTPUT2_LEFT_VOLUME, | ||
2884 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2885 | snd_soc_update_bits(codec, WM8996_OUTPUT2_RIGHT_VOLUME, | ||
2886 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2887 | |||
2888 | snd_soc_update_bits(codec, WM8996_DSP1_TX_LEFT_VOLUME, | ||
2889 | WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | ||
2890 | snd_soc_update_bits(codec, WM8996_DSP1_TX_RIGHT_VOLUME, | ||
2891 | WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | ||
2892 | snd_soc_update_bits(codec, WM8996_DSP2_TX_LEFT_VOLUME, | ||
2893 | WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | ||
2894 | snd_soc_update_bits(codec, WM8996_DSP2_TX_RIGHT_VOLUME, | ||
2895 | WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | ||
2896 | |||
2897 | snd_soc_update_bits(codec, WM8996_DSP1_RX_LEFT_VOLUME, | ||
2898 | WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | ||
2899 | snd_soc_update_bits(codec, WM8996_DSP1_RX_RIGHT_VOLUME, | ||
2900 | WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | ||
2901 | snd_soc_update_bits(codec, WM8996_DSP2_RX_LEFT_VOLUME, | ||
2902 | WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | ||
2903 | snd_soc_update_bits(codec, WM8996_DSP2_RX_RIGHT_VOLUME, | ||
2904 | WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | ||
2905 | |||
2906 | /* No support currently for the underclocked TDM modes and | ||
2907 | * pick a default TDM layout with each channel pair working with | ||
2908 | * slots 0 and 1. */ | ||
2909 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, | ||
2910 | WM8996_AIF1RX_CHAN0_SLOTS_MASK | | ||
2911 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2912 | 1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0); | ||
2913 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, | ||
2914 | WM8996_AIF1RX_CHAN1_SLOTS_MASK | | ||
2915 | WM8996_AIF1RX_CHAN1_START_SLOT_MASK, | ||
2916 | 1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1); | ||
2917 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, | ||
2918 | WM8996_AIF1RX_CHAN2_SLOTS_MASK | | ||
2919 | WM8996_AIF1RX_CHAN2_START_SLOT_MASK, | ||
2920 | 1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0); | ||
2921 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, | ||
2922 | WM8996_AIF1RX_CHAN3_SLOTS_MASK | | ||
2923 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2924 | 1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1); | ||
2925 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, | ||
2926 | WM8996_AIF1RX_CHAN4_SLOTS_MASK | | ||
2927 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2928 | 1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0); | ||
2929 | snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, | ||
2930 | WM8996_AIF1RX_CHAN5_SLOTS_MASK | | ||
2931 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2932 | 1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1); | ||
2933 | |||
2934 | snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, | ||
2935 | WM8996_AIF2RX_CHAN0_SLOTS_MASK | | ||
2936 | WM8996_AIF2RX_CHAN0_START_SLOT_MASK, | ||
2937 | 1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0); | ||
2938 | snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, | ||
2939 | WM8996_AIF2RX_CHAN1_SLOTS_MASK | | ||
2940 | WM8996_AIF2RX_CHAN1_START_SLOT_MASK, | ||
2941 | 1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1); | ||
2942 | |||
2943 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, | ||
2944 | WM8996_AIF1TX_CHAN0_SLOTS_MASK | | ||
2945 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2946 | 1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0); | ||
2947 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | ||
2948 | WM8996_AIF1TX_CHAN1_SLOTS_MASK | | ||
2949 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2950 | 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | ||
2951 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, | ||
2952 | WM8996_AIF1TX_CHAN2_SLOTS_MASK | | ||
2953 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2954 | 1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0); | ||
2955 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, | ||
2956 | WM8996_AIF1TX_CHAN3_SLOTS_MASK | | ||
2957 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2958 | 1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1); | ||
2959 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, | ||
2960 | WM8996_AIF1TX_CHAN4_SLOTS_MASK | | ||
2961 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2962 | 1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0); | ||
2963 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, | ||
2964 | WM8996_AIF1TX_CHAN5_SLOTS_MASK | | ||
2965 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2966 | 1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1); | ||
2967 | |||
2968 | snd_soc_update_bits(codec, WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, | ||
2969 | WM8996_AIF2TX_CHAN0_SLOTS_MASK | | ||
2970 | WM8996_AIF2TX_CHAN0_START_SLOT_MASK, | ||
2971 | 1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0); | ||
2972 | snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | ||
2973 | WM8996_AIF2TX_CHAN1_SLOTS_MASK | | ||
2974 | WM8996_AIF2TX_CHAN1_START_SLOT_MASK, | ||
2975 | 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | ||
2976 | |||
2977 | if (wm8996->pdata.num_retune_mobile_cfgs) | 2637 | if (wm8996->pdata.num_retune_mobile_cfgs) |
2978 | wm8996_retune_mobile_pdata(codec); | 2638 | wm8996_retune_mobile_pdata(codec); |
2979 | else | 2639 | else |
2980 | snd_soc_add_codec_controls(codec, wm8996_eq_controls, | 2640 | snd_soc_add_codec_controls(codec, wm8996_eq_controls, |
2981 | ARRAY_SIZE(wm8996_eq_controls)); | 2641 | ARRAY_SIZE(wm8996_eq_controls)); |
2982 | 2642 | ||
2983 | /* If the TX LRCLK pins are not in LRCLK mode configure the | ||
2984 | * AIFs to source their clocks from the RX LRCLKs. | ||
2985 | */ | ||
2986 | if ((snd_soc_read(codec, WM8996_GPIO_1))) | ||
2987 | snd_soc_update_bits(codec, WM8996_AIF1_TX_LRCLK_2, | ||
2988 | WM8996_AIF1TX_LRCLK_MODE, | ||
2989 | WM8996_AIF1TX_LRCLK_MODE); | ||
2990 | |||
2991 | if ((snd_soc_read(codec, WM8996_GPIO_2))) | ||
2992 | snd_soc_update_bits(codec, WM8996_AIF2_TX_LRCLK_2, | ||
2993 | WM8996_AIF2TX_LRCLK_MODE, | ||
2994 | WM8996_AIF2TX_LRCLK_MODE); | ||
2995 | |||
2996 | if (i2c->irq) { | 2643 | if (i2c->irq) { |
2997 | if (wm8996->pdata.irq_flags) | 2644 | if (wm8996->pdata.irq_flags) |
2998 | irq_flags = wm8996->pdata.irq_flags; | 2645 | irq_flags = wm8996->pdata.irq_flags; |
@@ -3036,9 +2683,7 @@ err: | |||
3036 | 2683 | ||
3037 | static int wm8996_remove(struct snd_soc_codec *codec) | 2684 | static int wm8996_remove(struct snd_soc_codec *codec) |
3038 | { | 2685 | { |
3039 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
3040 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 2686 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
3041 | int i; | ||
3042 | 2687 | ||
3043 | snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL, | 2688 | snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL, |
3044 | WM8996_IM_IRQ, WM8996_IM_IRQ); | 2689 | WM8996_IM_IRQ, WM8996_IM_IRQ); |
@@ -3046,10 +2691,6 @@ static int wm8996_remove(struct snd_soc_codec *codec) | |||
3046 | if (i2c->irq) | 2691 | if (i2c->irq) |
3047 | free_irq(i2c->irq, codec); | 2692 | free_irq(i2c->irq, codec); |
3048 | 2693 | ||
3049 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) | ||
3050 | regulator_unregister_notifier(wm8996->supplies[i].consumer, | ||
3051 | &wm8996->disable_nb[i]); | ||
3052 | |||
3053 | return 0; | 2694 | return 0; |
3054 | } | 2695 | } |
3055 | 2696 | ||
@@ -3163,6 +2804,21 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, | |||
3163 | goto err_gpio; | 2804 | goto err_gpio; |
3164 | } | 2805 | } |
3165 | 2806 | ||
2807 | wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; | ||
2808 | wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; | ||
2809 | wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; | ||
2810 | |||
2811 | /* This should really be moved into the regulator core */ | ||
2812 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { | ||
2813 | ret = regulator_register_notifier(wm8996->supplies[i].consumer, | ||
2814 | &wm8996->disable_nb[i]); | ||
2815 | if (ret != 0) { | ||
2816 | dev_err(&i2c->dev, | ||
2817 | "Failed to register regulator notifier: %d\n", | ||
2818 | ret); | ||
2819 | } | ||
2820 | } | ||
2821 | |||
3166 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), | 2822 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), |
3167 | wm8996->supplies); | 2823 | wm8996->supplies); |
3168 | if (ret != 0) { | 2824 | if (ret != 0) { |
@@ -3175,7 +2831,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, | |||
3175 | msleep(5); | 2831 | msleep(5); |
3176 | } | 2832 | } |
3177 | 2833 | ||
3178 | wm8996->regmap = regmap_init_i2c(i2c, &wm8996_regmap); | 2834 | wm8996->regmap = devm_regmap_init_i2c(i2c, &wm8996_regmap); |
3179 | if (IS_ERR(wm8996->regmap)) { | 2835 | if (IS_ERR(wm8996->regmap)) { |
3180 | ret = PTR_ERR(wm8996->regmap); | 2836 | ret = PTR_ERR(wm8996->regmap); |
3181 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); | 2837 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); |
@@ -3203,15 +2859,199 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, | |||
3203 | dev_info(&i2c->dev, "revision %c\n", | 2859 | dev_info(&i2c->dev, "revision %c\n", |
3204 | (reg & WM8996_CHIP_REV_MASK) + 'A'); | 2860 | (reg & WM8996_CHIP_REV_MASK) + 'A'); |
3205 | 2861 | ||
3206 | ret = wm8996_reset(wm8996); | 2862 | if (wm8996->pdata.ldo_ena > 0) { |
3207 | if (ret < 0) { | 2863 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
3208 | dev_err(&i2c->dev, "Failed to issue reset\n"); | 2864 | regcache_cache_only(wm8996->regmap, true); |
3209 | goto err_regmap; | 2865 | } else { |
2866 | ret = regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET, | ||
2867 | 0x8915); | ||
2868 | if (ret != 0) { | ||
2869 | dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | ||
2870 | goto err_regmap; | ||
2871 | } | ||
3210 | } | 2872 | } |
3211 | 2873 | ||
3212 | regcache_cache_only(wm8996->regmap, true); | ||
3213 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | 2874 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
3214 | 2875 | ||
2876 | /* Apply platform data settings */ | ||
2877 | regmap_update_bits(wm8996->regmap, WM8996_LINE_INPUT_CONTROL, | ||
2878 | WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK, | ||
2879 | wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT | | ||
2880 | wm8996->pdata.inr_mode); | ||
2881 | |||
2882 | for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) { | ||
2883 | if (!wm8996->pdata.gpio_default[i]) | ||
2884 | continue; | ||
2885 | |||
2886 | regmap_write(wm8996->regmap, WM8996_GPIO_1 + i, | ||
2887 | wm8996->pdata.gpio_default[i] & 0xffff); | ||
2888 | } | ||
2889 | |||
2890 | if (wm8996->pdata.spkmute_seq) | ||
2891 | regmap_update_bits(wm8996->regmap, | ||
2892 | WM8996_PDM_SPEAKER_MUTE_SEQUENCE, | ||
2893 | WM8996_SPK_MUTE_ENDIAN | | ||
2894 | WM8996_SPK_MUTE_SEQ1_MASK, | ||
2895 | wm8996->pdata.spkmute_seq); | ||
2896 | |||
2897 | regmap_update_bits(wm8996->regmap, WM8996_ACCESSORY_DETECT_MODE_2, | ||
2898 | WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC | | ||
2899 | WM8996_MICD_SRC, wm8996->pdata.micdet_def); | ||
2900 | |||
2901 | /* Latch volume update bits */ | ||
2902 | regmap_update_bits(wm8996->regmap, WM8996_LEFT_LINE_INPUT_VOLUME, | ||
2903 | WM8996_IN1_VU, WM8996_IN1_VU); | ||
2904 | regmap_update_bits(wm8996->regmap, WM8996_RIGHT_LINE_INPUT_VOLUME, | ||
2905 | WM8996_IN1_VU, WM8996_IN1_VU); | ||
2906 | |||
2907 | regmap_update_bits(wm8996->regmap, WM8996_DAC1_LEFT_VOLUME, | ||
2908 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2909 | regmap_update_bits(wm8996->regmap, WM8996_DAC1_RIGHT_VOLUME, | ||
2910 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2911 | regmap_update_bits(wm8996->regmap, WM8996_DAC2_LEFT_VOLUME, | ||
2912 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2913 | regmap_update_bits(wm8996->regmap, WM8996_DAC2_RIGHT_VOLUME, | ||
2914 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2915 | |||
2916 | regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_LEFT_VOLUME, | ||
2917 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2918 | regmap_update_bits(wm8996->regmap, WM8996_OUTPUT1_RIGHT_VOLUME, | ||
2919 | WM8996_DAC1_VU, WM8996_DAC1_VU); | ||
2920 | regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_LEFT_VOLUME, | ||
2921 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2922 | regmap_update_bits(wm8996->regmap, WM8996_OUTPUT2_RIGHT_VOLUME, | ||
2923 | WM8996_DAC2_VU, WM8996_DAC2_VU); | ||
2924 | |||
2925 | regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_LEFT_VOLUME, | ||
2926 | WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | ||
2927 | regmap_update_bits(wm8996->regmap, WM8996_DSP1_TX_RIGHT_VOLUME, | ||
2928 | WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); | ||
2929 | regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_LEFT_VOLUME, | ||
2930 | WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | ||
2931 | regmap_update_bits(wm8996->regmap, WM8996_DSP2_TX_RIGHT_VOLUME, | ||
2932 | WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); | ||
2933 | |||
2934 | regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_LEFT_VOLUME, | ||
2935 | WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | ||
2936 | regmap_update_bits(wm8996->regmap, WM8996_DSP1_RX_RIGHT_VOLUME, | ||
2937 | WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); | ||
2938 | regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_LEFT_VOLUME, | ||
2939 | WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | ||
2940 | regmap_update_bits(wm8996->regmap, WM8996_DSP2_RX_RIGHT_VOLUME, | ||
2941 | WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); | ||
2942 | |||
2943 | /* No support currently for the underclocked TDM modes and | ||
2944 | * pick a default TDM layout with each channel pair working with | ||
2945 | * slots 0 and 1. */ | ||
2946 | regmap_update_bits(wm8996->regmap, | ||
2947 | WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, | ||
2948 | WM8996_AIF1RX_CHAN0_SLOTS_MASK | | ||
2949 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2950 | 1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0); | ||
2951 | regmap_update_bits(wm8996->regmap, | ||
2952 | WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, | ||
2953 | WM8996_AIF1RX_CHAN1_SLOTS_MASK | | ||
2954 | WM8996_AIF1RX_CHAN1_START_SLOT_MASK, | ||
2955 | 1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1); | ||
2956 | regmap_update_bits(wm8996->regmap, | ||
2957 | WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, | ||
2958 | WM8996_AIF1RX_CHAN2_SLOTS_MASK | | ||
2959 | WM8996_AIF1RX_CHAN2_START_SLOT_MASK, | ||
2960 | 1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0); | ||
2961 | regmap_update_bits(wm8996->regmap, | ||
2962 | WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, | ||
2963 | WM8996_AIF1RX_CHAN3_SLOTS_MASK | | ||
2964 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2965 | 1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1); | ||
2966 | regmap_update_bits(wm8996->regmap, | ||
2967 | WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, | ||
2968 | WM8996_AIF1RX_CHAN4_SLOTS_MASK | | ||
2969 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2970 | 1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0); | ||
2971 | regmap_update_bits(wm8996->regmap, | ||
2972 | WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, | ||
2973 | WM8996_AIF1RX_CHAN5_SLOTS_MASK | | ||
2974 | WM8996_AIF1RX_CHAN0_START_SLOT_MASK, | ||
2975 | 1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1); | ||
2976 | |||
2977 | regmap_update_bits(wm8996->regmap, | ||
2978 | WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, | ||
2979 | WM8996_AIF2RX_CHAN0_SLOTS_MASK | | ||
2980 | WM8996_AIF2RX_CHAN0_START_SLOT_MASK, | ||
2981 | 1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0); | ||
2982 | regmap_update_bits(wm8996->regmap, | ||
2983 | WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, | ||
2984 | WM8996_AIF2RX_CHAN1_SLOTS_MASK | | ||
2985 | WM8996_AIF2RX_CHAN1_START_SLOT_MASK, | ||
2986 | 1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1); | ||
2987 | |||
2988 | regmap_update_bits(wm8996->regmap, | ||
2989 | WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, | ||
2990 | WM8996_AIF1TX_CHAN0_SLOTS_MASK | | ||
2991 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2992 | 1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0); | ||
2993 | regmap_update_bits(wm8996->regmap, | ||
2994 | WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | ||
2995 | WM8996_AIF1TX_CHAN1_SLOTS_MASK | | ||
2996 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
2997 | 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | ||
2998 | regmap_update_bits(wm8996->regmap, | ||
2999 | WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, | ||
3000 | WM8996_AIF1TX_CHAN2_SLOTS_MASK | | ||
3001 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
3002 | 1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0); | ||
3003 | regmap_update_bits(wm8996->regmap, | ||
3004 | WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, | ||
3005 | WM8996_AIF1TX_CHAN3_SLOTS_MASK | | ||
3006 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
3007 | 1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1); | ||
3008 | regmap_update_bits(wm8996->regmap, | ||
3009 | WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, | ||
3010 | WM8996_AIF1TX_CHAN4_SLOTS_MASK | | ||
3011 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
3012 | 1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0); | ||
3013 | regmap_update_bits(wm8996->regmap, | ||
3014 | WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, | ||
3015 | WM8996_AIF1TX_CHAN5_SLOTS_MASK | | ||
3016 | WM8996_AIF1TX_CHAN0_START_SLOT_MASK, | ||
3017 | 1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1); | ||
3018 | |||
3019 | regmap_update_bits(wm8996->regmap, | ||
3020 | WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, | ||
3021 | WM8996_AIF2TX_CHAN0_SLOTS_MASK | | ||
3022 | WM8996_AIF2TX_CHAN0_START_SLOT_MASK, | ||
3023 | 1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0); | ||
3024 | regmap_update_bits(wm8996->regmap, | ||
3025 | WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, | ||
3026 | WM8996_AIF2TX_CHAN1_SLOTS_MASK | | ||
3027 | WM8996_AIF2TX_CHAN1_START_SLOT_MASK, | ||
3028 | 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); | ||
3029 | |||
3030 | /* If the TX LRCLK pins are not in LRCLK mode configure the | ||
3031 | * AIFs to source their clocks from the RX LRCLKs. | ||
3032 | */ | ||
3033 | ret = regmap_read(wm8996->regmap, WM8996_GPIO_1, ®); | ||
3034 | if (ret != 0) { | ||
3035 | dev_err(&i2c->dev, "Failed to read GPIO1: %d\n", ret); | ||
3036 | goto err_regmap; | ||
3037 | } | ||
3038 | |||
3039 | if (reg & WM8996_GP1_FN_MASK) | ||
3040 | regmap_update_bits(wm8996->regmap, WM8996_AIF1_TX_LRCLK_2, | ||
3041 | WM8996_AIF1TX_LRCLK_MODE, | ||
3042 | WM8996_AIF1TX_LRCLK_MODE); | ||
3043 | |||
3044 | ret = regmap_read(wm8996->regmap, WM8996_GPIO_2, ®); | ||
3045 | if (ret != 0) { | ||
3046 | dev_err(&i2c->dev, "Failed to read GPIO2: %d\n", ret); | ||
3047 | goto err_regmap; | ||
3048 | } | ||
3049 | |||
3050 | if (reg & WM8996_GP2_FN_MASK) | ||
3051 | regmap_update_bits(wm8996->regmap, WM8996_AIF2_TX_LRCLK_2, | ||
3052 | WM8996_AIF2TX_LRCLK_MODE, | ||
3053 | WM8996_AIF2TX_LRCLK_MODE); | ||
3054 | |||
3215 | wm8996_init_gpio(wm8996); | 3055 | wm8996_init_gpio(wm8996); |
3216 | 3056 | ||
3217 | ret = snd_soc_register_codec(&i2c->dev, | 3057 | ret = snd_soc_register_codec(&i2c->dev, |
@@ -3225,7 +3065,6 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, | |||
3225 | err_gpiolib: | 3065 | err_gpiolib: |
3226 | wm8996_free_gpio(wm8996); | 3066 | wm8996_free_gpio(wm8996); |
3227 | err_regmap: | 3067 | err_regmap: |
3228 | regmap_exit(wm8996->regmap); | ||
3229 | err_enable: | 3068 | err_enable: |
3230 | if (wm8996->pdata.ldo_ena > 0) | 3069 | if (wm8996->pdata.ldo_ena > 0) |
3231 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 3070 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
@@ -3241,14 +3080,18 @@ err: | |||
3241 | static __devexit int wm8996_i2c_remove(struct i2c_client *client) | 3080 | static __devexit int wm8996_i2c_remove(struct i2c_client *client) |
3242 | { | 3081 | { |
3243 | struct wm8996_priv *wm8996 = i2c_get_clientdata(client); | 3082 | struct wm8996_priv *wm8996 = i2c_get_clientdata(client); |
3083 | int i; | ||
3244 | 3084 | ||
3245 | snd_soc_unregister_codec(&client->dev); | 3085 | snd_soc_unregister_codec(&client->dev); |
3246 | wm8996_free_gpio(wm8996); | 3086 | wm8996_free_gpio(wm8996); |
3247 | regmap_exit(wm8996->regmap); | ||
3248 | if (wm8996->pdata.ldo_ena > 0) { | 3087 | if (wm8996->pdata.ldo_ena > 0) { |
3249 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 3088 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
3250 | gpio_free(wm8996->pdata.ldo_ena); | 3089 | gpio_free(wm8996->pdata.ldo_ena); |
3251 | } | 3090 | } |
3091 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) | ||
3092 | regulator_unregister_notifier(wm8996->supplies[i].consumer, | ||
3093 | &wm8996->disable_nb[i]); | ||
3094 | |||
3252 | return 0; | 3095 | return 0; |
3253 | } | 3096 | } |
3254 | 3097 | ||