aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@gmail.com>2015-02-22 11:43:22 -0500
committerMark Brown <broonie@kernel.org>2015-03-04 20:05:54 -0500
commit6f2c9348095ae1a489abafe2ab3db7deca406e49 (patch)
treed530b26416c2d43387f24a09a403ba3834a93467
parentbbed297d373471c8e4c3183bf67472a768576664 (diff)
ASoC: wm8804: Merge CODEC probe and bus probe
All of the things in the CODEC probe, such as getting the regulators and verifying the chip ID, are better done in bus probe. It is better to fail during bus probe if this is the wrong chip and all resource allocation should be done in the bus probe anyway. This patch merges the CODEC probe into bus probe. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/wm8804.c180
1 files changed, 82 insertions, 98 deletions
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index b5a04fc5060f..1bd4ace29594 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -182,9 +182,9 @@ static bool wm8804_volatile(struct device *dev, unsigned int reg)
182 } 182 }
183} 183}
184 184
185static int wm8804_reset(struct snd_soc_codec *codec) 185static int wm8804_reset(struct wm8804_priv *wm8804)
186{ 186{
187 return snd_soc_write(codec, WM8804_RST_DEVID1, 0x0); 187 return regmap_write(wm8804->regmap, WM8804_RST_DEVID1, 0x0);
188} 188}
189 189
190static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 190static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
@@ -515,100 +515,6 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec,
515 return 0; 515 return 0;
516} 516}
517 517
518static int wm8804_codec_remove(struct snd_soc_codec *codec)
519{
520 struct wm8804_priv *wm8804;
521 int i;
522
523 wm8804 = snd_soc_codec_get_drvdata(codec);
524
525 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
526 regulator_unregister_notifier(wm8804->supplies[i].consumer,
527 &wm8804->disable_nb[i]);
528 return 0;
529}
530
531static int wm8804_codec_probe(struct snd_soc_codec *codec)
532{
533 struct wm8804_priv *wm8804;
534 int i, id1, id2, ret;
535
536 wm8804 = snd_soc_codec_get_drvdata(codec);
537
538 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
539 wm8804->supplies[i].supply = wm8804_supply_names[i];
540
541 ret = devm_regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
542 wm8804->supplies);
543 if (ret) {
544 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
545 return ret;
546 }
547
548 wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
549 wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
550
551 /* This should really be moved into the regulator core */
552 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
553 ret = regulator_register_notifier(wm8804->supplies[i].consumer,
554 &wm8804->disable_nb[i]);
555 if (ret != 0) {
556 dev_err(codec->dev,
557 "Failed to register regulator notifier: %d\n",
558 ret);
559 }
560 }
561
562 ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
563 wm8804->supplies);
564 if (ret) {
565 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
566 return ret;
567 }
568
569 id1 = snd_soc_read(codec, WM8804_RST_DEVID1);
570 if (id1 < 0) {
571 dev_err(codec->dev, "Failed to read device ID: %d\n", id1);
572 ret = id1;
573 goto err_reg_enable;
574 }
575
576 id2 = snd_soc_read(codec, WM8804_DEVID2);
577 if (id2 < 0) {
578 dev_err(codec->dev, "Failed to read device ID: %d\n", id2);
579 ret = id2;
580 goto err_reg_enable;
581 }
582
583 id2 = (id2 << 8) | id1;
584
585 if (id2 != 0x8805) {
586 dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
587 ret = -EINVAL;
588 goto err_reg_enable;
589 }
590
591 ret = snd_soc_read(codec, WM8804_DEVREV);
592 if (ret < 0) {
593 dev_err(codec->dev, "Failed to read device revision: %d\n",
594 ret);
595 goto err_reg_enable;
596 }
597 dev_info(codec->dev, "revision %c\n", ret + 'A');
598
599 ret = wm8804_reset(codec);
600 if (ret < 0) {
601 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
602 goto err_reg_enable;
603 }
604
605 return 0;
606
607err_reg_enable:
608 regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
609 return ret;
610}
611
612static const struct snd_soc_dai_ops wm8804_dai_ops = { 518static const struct snd_soc_dai_ops wm8804_dai_ops = {
613 .hw_params = wm8804_hw_params, 519 .hw_params = wm8804_hw_params,
614 .set_fmt = wm8804_set_fmt, 520 .set_fmt = wm8804_set_fmt,
@@ -646,8 +552,6 @@ static struct snd_soc_dai_driver wm8804_dai = {
646}; 552};
647 553
648static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { 554static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
649 .probe = wm8804_codec_probe,
650 .remove = wm8804_codec_remove,
651 .set_bias_level = wm8804_set_bias_level, 555 .set_bias_level = wm8804_set_bias_level,
652 .idle_bias_off = true, 556 .idle_bias_off = true,
653 557
@@ -671,6 +575,8 @@ EXPORT_SYMBOL_GPL(wm8804_regmap_config);
671int wm8804_probe(struct device *dev, struct regmap *regmap) 575int wm8804_probe(struct device *dev, struct regmap *regmap)
672{ 576{
673 struct wm8804_priv *wm8804; 577 struct wm8804_priv *wm8804;
578 unsigned int id1, id2;
579 int i, ret;
674 580
675 wm8804 = devm_kzalloc(dev, sizeof(*wm8804), GFP_KERNEL); 581 wm8804 = devm_kzalloc(dev, sizeof(*wm8804), GFP_KERNEL);
676 if (!wm8804) 582 if (!wm8804)
@@ -680,13 +586,91 @@ int wm8804_probe(struct device *dev, struct regmap *regmap)
680 586
681 wm8804->regmap = regmap; 587 wm8804->regmap = regmap;
682 588
589 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
590 wm8804->supplies[i].supply = wm8804_supply_names[i];
591
592 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(wm8804->supplies),
593 wm8804->supplies);
594 if (ret) {
595 dev_err(dev, "Failed to request supplies: %d\n", ret);
596 return ret;
597 }
598
599 wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
600 wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
601
602 /* This should really be moved into the regulator core */
603 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
604 ret = regulator_register_notifier(wm8804->supplies[i].consumer,
605 &wm8804->disable_nb[i]);
606 if (ret != 0) {
607 dev_err(dev,
608 "Failed to register regulator notifier: %d\n",
609 ret);
610 }
611 }
612
613 ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
614 wm8804->supplies);
615 if (ret) {
616 dev_err(dev, "Failed to enable supplies: %d\n", ret);
617 goto err_reg_enable;
618 }
619
620 ret = regmap_read(regmap, WM8804_RST_DEVID1, &id1);
621 if (ret < 0) {
622 dev_err(dev, "Failed to read device ID: %d\n", ret);
623 goto err_reg_enable;
624 }
625
626 ret = regmap_read(regmap, WM8804_DEVID2, &id2);
627 if (ret < 0) {
628 dev_err(dev, "Failed to read device ID: %d\n", ret);
629 goto err_reg_enable;
630 }
631
632 id2 = (id2 << 8) | id1;
633
634 if (id2 != 0x8805) {
635 dev_err(dev, "Invalid device ID: %#x\n", id2);
636 ret = -EINVAL;
637 goto err_reg_enable;
638 }
639
640 ret = regmap_read(regmap, WM8804_DEVREV, &id1);
641 if (ret < 0) {
642 dev_err(dev, "Failed to read device revision: %d\n",
643 ret);
644 goto err_reg_enable;
645 }
646 dev_info(dev, "revision %c\n", id1 + 'A');
647
648 ret = wm8804_reset(wm8804);
649 if (ret < 0) {
650 dev_err(dev, "Failed to issue reset: %d\n", ret);
651 goto err_reg_enable;
652 }
653
683 return snd_soc_register_codec(dev, &soc_codec_dev_wm8804, 654 return snd_soc_register_codec(dev, &soc_codec_dev_wm8804,
684 &wm8804_dai, 1); 655 &wm8804_dai, 1);
656
657err_reg_enable:
658 regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
659 return ret;
685} 660}
686EXPORT_SYMBOL_GPL(wm8804_probe); 661EXPORT_SYMBOL_GPL(wm8804_probe);
687 662
688void wm8804_remove(struct device *dev) 663void wm8804_remove(struct device *dev)
689{ 664{
665 struct wm8804_priv *wm8804;
666 int i;
667
668 wm8804 = dev_get_drvdata(dev);
669
670 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
671 regulator_unregister_notifier(wm8804->supplies[i].consumer,
672 &wm8804->disable_nb[i]);
673
690 snd_soc_unregister_codec(dev); 674 snd_soc_unregister_codec(dev);
691} 675}
692EXPORT_SYMBOL_GPL(wm8804_remove); 676EXPORT_SYMBOL_GPL(wm8804_remove);