aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm5100.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-11-09 11:12:04 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-11-09 11:33:26 -0500
commit588ac5e0b63da9cdef8b1b1d71dbcd95a8a94131 (patch)
tree7b22f818e41a45e246d147b965235a76c0371099 /sound/soc/codecs/wm5100.c
parentd926b5a3d921decc0fc537ba8a5ad53350c78f82 (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.c263
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
208static int wm5100_reset(struct snd_soc_codec *codec) 208static 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);
2671err_reset:
2672 if (wm5100->pdata.reset) {
2673 gpio_set_value_cansleep(wm5100->pdata.reset, 1);
2674 gpio_free(wm5100->pdata.reset);
2675 }
2676err_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 }
2681err_enable:
2682 regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
2683 wm5100->core_supplies);
2684err_dbvdd3:
2685 regulator_put(wm5100->dbvdd3);
2686err_dbvdd2:
2687 regulator_put(wm5100->dbvdd2);
2688err_cpvdd:
2689 regulator_put(wm5100->cpvdd);
2690err_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, &reg);
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, &reg);
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
2756err_reset:
2757 if (wm5100->pdata.reset) {
2758 gpio_set_value_cansleep(wm5100->pdata.reset, 1);
2759 gpio_free(wm5100->pdata.reset);
2760 }
2761err_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 }
2766err_enable:
2767 regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
2768 wm5100->core_supplies);
2769err_dbvdd3:
2770 regulator_put(wm5100->dbvdd3);
2771err_dbvdd2:
2772 regulator_put(wm5100->dbvdd2);
2773err_cpvdd:
2774 regulator_put(wm5100->cpvdd);
2775err_core:
2776 regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
2777 wm5100->core_supplies);
2792err_regmap: 2778err_regmap:
2793 regmap_exit(wm5100->regmap); 2779 regmap_exit(wm5100->regmap);
2794err_alloc: 2780err_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