diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-11-09 11:12:04 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-11-09 11:33:26 -0500 |
commit | 588ac5e0b63da9cdef8b1b1d71dbcd95a8a94131 (patch) | |
tree | 7b22f818e41a45e246d147b965235a76c0371099 /sound/soc/codecs/wm5100.c | |
parent | d926b5a3d921decc0fc537ba8a5ad53350c78f82 (diff) |
ASoC: Move most WM5100 resource allocation to I2C probe
More standard Linuxish.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm5100.c')
-rw-r--r-- | sound/soc/codecs/wm5100.c | 263 |
1 files changed, 131 insertions, 132 deletions
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 340ffe20b53b..08bf073ce19f 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -205,17 +205,15 @@ static void wm5100_free_sr(struct snd_soc_codec *codec, int rate) | |||
205 | } | 205 | } |
206 | } | 206 | } |
207 | 207 | ||
208 | static int wm5100_reset(struct snd_soc_codec *codec) | 208 | static int wm5100_reset(struct wm5100_priv *wm5100) |
209 | { | 209 | { |
210 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | ||
211 | |||
212 | if (wm5100->pdata.reset) { | 210 | if (wm5100->pdata.reset) { |
213 | gpio_set_value_cansleep(wm5100->pdata.reset, 0); | 211 | gpio_set_value_cansleep(wm5100->pdata.reset, 0); |
214 | gpio_set_value_cansleep(wm5100->pdata.reset, 1); | 212 | gpio_set_value_cansleep(wm5100->pdata.reset, 1); |
215 | 213 | ||
216 | return 0; | 214 | return 0; |
217 | } else { | 215 | } else { |
218 | return snd_soc_write(codec, WM5100_SOFTWARE_RESET, 0); | 216 | return regmap_write(wm5100->regmap, WM5100_SOFTWARE_RESET, 0); |
219 | } | 217 | } |
220 | } | 218 | } |
221 | 219 | ||
@@ -2465,98 +2463,6 @@ static int wm5100_probe(struct snd_soc_codec *codec) | |||
2465 | return ret; | 2463 | return ret; |
2466 | } | 2464 | } |
2467 | 2465 | ||
2468 | for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++) | ||
2469 | wm5100->core_supplies[i].supply = wm5100_core_supply_names[i]; | ||
2470 | |||
2471 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies), | ||
2472 | wm5100->core_supplies); | ||
2473 | if (ret != 0) { | ||
2474 | dev_err(codec->dev, "Failed to request core supplies: %d\n", | ||
2475 | ret); | ||
2476 | return ret; | ||
2477 | } | ||
2478 | |||
2479 | wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD"); | ||
2480 | if (IS_ERR(wm5100->cpvdd)) { | ||
2481 | ret = PTR_ERR(wm5100->cpvdd); | ||
2482 | dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret); | ||
2483 | goto err_core; | ||
2484 | } | ||
2485 | |||
2486 | wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2"); | ||
2487 | if (IS_ERR(wm5100->dbvdd2)) { | ||
2488 | ret = PTR_ERR(wm5100->dbvdd2); | ||
2489 | dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret); | ||
2490 | goto err_cpvdd; | ||
2491 | } | ||
2492 | |||
2493 | wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3"); | ||
2494 | if (IS_ERR(wm5100->dbvdd3)) { | ||
2495 | ret = PTR_ERR(wm5100->dbvdd3); | ||
2496 | dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret); | ||
2497 | goto err_dbvdd2; | ||
2498 | } | ||
2499 | |||
2500 | ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies), | ||
2501 | wm5100->core_supplies); | ||
2502 | if (ret != 0) { | ||
2503 | dev_err(codec->dev, "Failed to enable core supplies: %d\n", | ||
2504 | ret); | ||
2505 | goto err_dbvdd3; | ||
2506 | } | ||
2507 | |||
2508 | if (wm5100->pdata.ldo_ena) { | ||
2509 | ret = gpio_request_one(wm5100->pdata.ldo_ena, | ||
2510 | GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA"); | ||
2511 | if (ret < 0) { | ||
2512 | dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n", | ||
2513 | wm5100->pdata.ldo_ena, ret); | ||
2514 | goto err_enable; | ||
2515 | } | ||
2516 | msleep(2); | ||
2517 | } | ||
2518 | |||
2519 | if (wm5100->pdata.reset) { | ||
2520 | ret = gpio_request_one(wm5100->pdata.reset, | ||
2521 | GPIOF_OUT_INIT_HIGH, "WM5100 /RESET"); | ||
2522 | if (ret < 0) { | ||
2523 | dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n", | ||
2524 | wm5100->pdata.reset, ret); | ||
2525 | goto err_ldo; | ||
2526 | } | ||
2527 | } | ||
2528 | |||
2529 | ret = snd_soc_read(codec, WM5100_SOFTWARE_RESET); | ||
2530 | if (ret < 0) { | ||
2531 | dev_err(codec->dev, "Failed to read ID register\n"); | ||
2532 | goto err_reset; | ||
2533 | } | ||
2534 | switch (ret) { | ||
2535 | case 0x8997: | ||
2536 | case 0x5100: | ||
2537 | break; | ||
2538 | |||
2539 | default: | ||
2540 | dev_err(codec->dev, "Device is not a WM5100, ID is %x\n", ret); | ||
2541 | ret = -EINVAL; | ||
2542 | goto err_reset; | ||
2543 | } | ||
2544 | |||
2545 | ret = snd_soc_read(codec, WM5100_DEVICE_REVISION); | ||
2546 | if (ret < 0) { | ||
2547 | dev_err(codec->dev, "Failed to read revision register\n"); | ||
2548 | goto err_reset; | ||
2549 | } | ||
2550 | wm5100->rev = ret & WM5100_DEVICE_REVISION_MASK; | ||
2551 | |||
2552 | dev_info(codec->dev, "revision %c\n", wm5100->rev + 'A'); | ||
2553 | |||
2554 | ret = wm5100_reset(codec); | ||
2555 | if (ret < 0) { | ||
2556 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
2557 | goto err_reset; | ||
2558 | } | ||
2559 | |||
2560 | regcache_cache_only(wm5100->regmap, true); | 2466 | regcache_cache_only(wm5100->regmap, true); |
2561 | 2467 | ||
2562 | wm5100_init_gpio(codec); | 2468 | wm5100_init_gpio(codec); |
@@ -2668,28 +2574,6 @@ err_gpio: | |||
2668 | if (i2c->irq) | 2574 | if (i2c->irq) |
2669 | free_irq(i2c->irq, codec); | 2575 | free_irq(i2c->irq, codec); |
2670 | wm5100_free_gpio(codec); | 2576 | wm5100_free_gpio(codec); |
2671 | err_reset: | ||
2672 | if (wm5100->pdata.reset) { | ||
2673 | gpio_set_value_cansleep(wm5100->pdata.reset, 1); | ||
2674 | gpio_free(wm5100->pdata.reset); | ||
2675 | } | ||
2676 | err_ldo: | ||
2677 | if (wm5100->pdata.ldo_ena) { | ||
2678 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); | ||
2679 | gpio_free(wm5100->pdata.ldo_ena); | ||
2680 | } | ||
2681 | err_enable: | ||
2682 | regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), | ||
2683 | wm5100->core_supplies); | ||
2684 | err_dbvdd3: | ||
2685 | regulator_put(wm5100->dbvdd3); | ||
2686 | err_dbvdd2: | ||
2687 | regulator_put(wm5100->dbvdd2); | ||
2688 | err_cpvdd: | ||
2689 | regulator_put(wm5100->cpvdd); | ||
2690 | err_core: | ||
2691 | regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies), | ||
2692 | wm5100->core_supplies); | ||
2693 | 2577 | ||
2694 | return ret; | 2578 | return ret; |
2695 | } | 2579 | } |
@@ -2706,19 +2590,6 @@ static int wm5100_remove(struct snd_soc_codec *codec) | |||
2706 | if (i2c->irq) | 2590 | if (i2c->irq) |
2707 | free_irq(i2c->irq, codec); | 2591 | free_irq(i2c->irq, codec); |
2708 | wm5100_free_gpio(codec); | 2592 | wm5100_free_gpio(codec); |
2709 | if (wm5100->pdata.reset) { | ||
2710 | gpio_set_value_cansleep(wm5100->pdata.reset, 1); | ||
2711 | gpio_free(wm5100->pdata.reset); | ||
2712 | } | ||
2713 | if (wm5100->pdata.ldo_ena) { | ||
2714 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); | ||
2715 | gpio_free(wm5100->pdata.ldo_ena); | ||
2716 | } | ||
2717 | regulator_put(wm5100->dbvdd3); | ||
2718 | regulator_put(wm5100->dbvdd2); | ||
2719 | regulator_put(wm5100->cpvdd); | ||
2720 | regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies), | ||
2721 | wm5100->core_supplies); | ||
2722 | return 0; | 2593 | return 0; |
2723 | } | 2594 | } |
2724 | 2595 | ||
@@ -2757,6 +2628,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, | |||
2757 | { | 2628 | { |
2758 | struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev); | 2629 | struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev); |
2759 | struct wm5100_priv *wm5100; | 2630 | struct wm5100_priv *wm5100; |
2631 | unsigned int reg; | ||
2760 | int ret, i; | 2632 | int ret, i; |
2761 | 2633 | ||
2762 | wm5100 = kzalloc(sizeof(struct wm5100_priv), GFP_KERNEL); | 2634 | wm5100 = kzalloc(sizeof(struct wm5100_priv), GFP_KERNEL); |
@@ -2779,16 +2651,130 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, | |||
2779 | 2651 | ||
2780 | i2c_set_clientdata(i2c, wm5100); | 2652 | i2c_set_clientdata(i2c, wm5100); |
2781 | 2653 | ||
2654 | for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++) | ||
2655 | wm5100->core_supplies[i].supply = wm5100_core_supply_names[i]; | ||
2656 | |||
2657 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies), | ||
2658 | wm5100->core_supplies); | ||
2659 | if (ret != 0) { | ||
2660 | dev_err(&i2c->dev, "Failed to request core supplies: %d\n", | ||
2661 | ret); | ||
2662 | goto err_regmap; | ||
2663 | } | ||
2664 | |||
2665 | wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD"); | ||
2666 | if (IS_ERR(wm5100->cpvdd)) { | ||
2667 | ret = PTR_ERR(wm5100->cpvdd); | ||
2668 | dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret); | ||
2669 | goto err_core; | ||
2670 | } | ||
2671 | |||
2672 | wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2"); | ||
2673 | if (IS_ERR(wm5100->dbvdd2)) { | ||
2674 | ret = PTR_ERR(wm5100->dbvdd2); | ||
2675 | dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret); | ||
2676 | goto err_cpvdd; | ||
2677 | } | ||
2678 | |||
2679 | wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3"); | ||
2680 | if (IS_ERR(wm5100->dbvdd3)) { | ||
2681 | ret = PTR_ERR(wm5100->dbvdd3); | ||
2682 | dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret); | ||
2683 | goto err_dbvdd2; | ||
2684 | } | ||
2685 | |||
2686 | ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies), | ||
2687 | wm5100->core_supplies); | ||
2688 | if (ret != 0) { | ||
2689 | dev_err(&i2c->dev, "Failed to enable core supplies: %d\n", | ||
2690 | ret); | ||
2691 | goto err_dbvdd3; | ||
2692 | } | ||
2693 | |||
2694 | if (wm5100->pdata.ldo_ena) { | ||
2695 | ret = gpio_request_one(wm5100->pdata.ldo_ena, | ||
2696 | GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA"); | ||
2697 | if (ret < 0) { | ||
2698 | dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n", | ||
2699 | wm5100->pdata.ldo_ena, ret); | ||
2700 | goto err_enable; | ||
2701 | } | ||
2702 | msleep(2); | ||
2703 | } | ||
2704 | |||
2705 | if (wm5100->pdata.reset) { | ||
2706 | ret = gpio_request_one(wm5100->pdata.reset, | ||
2707 | GPIOF_OUT_INIT_HIGH, "WM5100 /RESET"); | ||
2708 | if (ret < 0) { | ||
2709 | dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n", | ||
2710 | wm5100->pdata.reset, ret); | ||
2711 | goto err_ldo; | ||
2712 | } | ||
2713 | } | ||
2714 | |||
2715 | ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, ®); | ||
2716 | if (ret < 0) { | ||
2717 | dev_err(&i2c->dev, "Failed to read ID register\n"); | ||
2718 | goto err_reset; | ||
2719 | } | ||
2720 | switch (reg) { | ||
2721 | case 0x8997: | ||
2722 | case 0x5100: | ||
2723 | break; | ||
2724 | |||
2725 | default: | ||
2726 | dev_err(&i2c->dev, "Device is not a WM5100, ID is %x\n", reg); | ||
2727 | ret = -EINVAL; | ||
2728 | goto err_reset; | ||
2729 | } | ||
2730 | |||
2731 | ret = regmap_read(wm5100->regmap, WM5100_DEVICE_REVISION, ®); | ||
2732 | if (ret < 0) { | ||
2733 | dev_err(&i2c->dev, "Failed to read revision register\n"); | ||
2734 | goto err_reset; | ||
2735 | } | ||
2736 | wm5100->rev = reg & WM5100_DEVICE_REVISION_MASK; | ||
2737 | |||
2738 | dev_info(&i2c->dev, "revision %c\n", wm5100->rev + 'A'); | ||
2739 | |||
2740 | ret = wm5100_reset(wm5100); | ||
2741 | if (ret < 0) { | ||
2742 | dev_err(&i2c->dev, "Failed to issue reset\n"); | ||
2743 | goto err_reset; | ||
2744 | } | ||
2745 | |||
2782 | ret = snd_soc_register_codec(&i2c->dev, | 2746 | ret = snd_soc_register_codec(&i2c->dev, |
2783 | &soc_codec_dev_wm5100, wm5100_dai, | 2747 | &soc_codec_dev_wm5100, wm5100_dai, |
2784 | ARRAY_SIZE(wm5100_dai)); | 2748 | ARRAY_SIZE(wm5100_dai)); |
2785 | if (ret < 0) { | 2749 | if (ret < 0) { |
2786 | dev_err(&i2c->dev, "Failed to register WM5100: %d\n", ret); | 2750 | dev_err(&i2c->dev, "Failed to register WM5100: %d\n", ret); |
2787 | goto err_regmap; | 2751 | goto err_reset; |
2788 | } | 2752 | } |
2789 | 2753 | ||
2790 | return ret; | 2754 | return ret; |
2791 | 2755 | ||
2756 | err_reset: | ||
2757 | if (wm5100->pdata.reset) { | ||
2758 | gpio_set_value_cansleep(wm5100->pdata.reset, 1); | ||
2759 | gpio_free(wm5100->pdata.reset); | ||
2760 | } | ||
2761 | err_ldo: | ||
2762 | if (wm5100->pdata.ldo_ena) { | ||
2763 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); | ||
2764 | gpio_free(wm5100->pdata.ldo_ena); | ||
2765 | } | ||
2766 | err_enable: | ||
2767 | regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), | ||
2768 | wm5100->core_supplies); | ||
2769 | err_dbvdd3: | ||
2770 | regulator_put(wm5100->dbvdd3); | ||
2771 | err_dbvdd2: | ||
2772 | regulator_put(wm5100->dbvdd2); | ||
2773 | err_cpvdd: | ||
2774 | regulator_put(wm5100->cpvdd); | ||
2775 | err_core: | ||
2776 | regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies), | ||
2777 | wm5100->core_supplies); | ||
2792 | err_regmap: | 2778 | err_regmap: |
2793 | regmap_exit(wm5100->regmap); | 2779 | regmap_exit(wm5100->regmap); |
2794 | err_alloc: | 2780 | err_alloc: |
@@ -2801,6 +2787,19 @@ static __devexit int wm5100_i2c_remove(struct i2c_client *client) | |||
2801 | struct wm5100_priv *wm5100 = i2c_get_clientdata(client); | 2787 | struct wm5100_priv *wm5100 = i2c_get_clientdata(client); |
2802 | 2788 | ||
2803 | snd_soc_unregister_codec(&client->dev); | 2789 | snd_soc_unregister_codec(&client->dev); |
2790 | if (wm5100->pdata.reset) { | ||
2791 | gpio_set_value_cansleep(wm5100->pdata.reset, 1); | ||
2792 | gpio_free(wm5100->pdata.reset); | ||
2793 | } | ||
2794 | if (wm5100->pdata.ldo_ena) { | ||
2795 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); | ||
2796 | gpio_free(wm5100->pdata.ldo_ena); | ||
2797 | } | ||
2798 | regulator_put(wm5100->dbvdd3); | ||
2799 | regulator_put(wm5100->dbvdd2); | ||
2800 | regulator_put(wm5100->cpvdd); | ||
2801 | regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies), | ||
2802 | wm5100->core_supplies); | ||
2804 | regmap_exit(wm5100->regmap); | 2803 | regmap_exit(wm5100->regmap); |
2805 | kfree(wm5100); | 2804 | kfree(wm5100); |
2806 | 2805 | ||