Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: tlv320aic32x4: Support for regulators

Support regulators to power up the codec. This patch also enables the
AVDD LDO if no AV regulator was found.

Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
Signed-off-by: Mark Brown <broonie@linaro.org>

authored by

Markus Pargmann and committed by
Mark Brown
239b669b 98b664e2

+133 -1
+8
Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
··· 5 5 Required properties: 6 6 - compatible: Should be "ti,tlv320aic32x4" 7 7 - reg: I2C slave address 8 + - supply-*: Required supply regulators are: 9 + "iov" - digital IO power supply 10 + "ldoin" - LDO power supply 11 + "dv" - Digital core power supply 12 + "av" - Analog core power supply 13 + If you supply ldoin, dv and av are optional. Otherwise they are required 14 + See regulator/regulator.txt for more information about the detailed binding 15 + format. 8 16 9 17 Optional properties: 10 18 - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
+125 -1
sound/soc/codecs/tlv320aic32x4.c
··· 34 34 #include <linux/cdev.h> 35 35 #include <linux/slab.h> 36 36 #include <linux/clk.h> 37 + #include <linux/regulator/consumer.h> 37 38 38 39 #include <sound/tlv320aic32x4.h> 39 40 #include <sound/core.h> ··· 70 69 bool swapdacs; 71 70 int rstn_gpio; 72 71 struct clk *mclk; 72 + 73 + struct regulator *supply_ldo; 74 + struct regulator *supply_iov; 75 + struct regulator *supply_dv; 76 + struct regulator *supply_av; 73 77 }; 74 78 75 79 /* 0dB min, 0.5dB steps */ ··· 701 695 return 0; 702 696 } 703 697 698 + static void aic32x4_disable_regulators(struct aic32x4_priv *aic32x4) 699 + { 700 + regulator_disable(aic32x4->supply_iov); 701 + 702 + if (!IS_ERR(aic32x4->supply_ldo)) 703 + regulator_disable(aic32x4->supply_ldo); 704 + 705 + if (!IS_ERR(aic32x4->supply_dv)) 706 + regulator_disable(aic32x4->supply_dv); 707 + 708 + if (!IS_ERR(aic32x4->supply_av)) 709 + regulator_disable(aic32x4->supply_av); 710 + } 711 + 712 + static int aic32x4_setup_regulators(struct device *dev, 713 + struct aic32x4_priv *aic32x4) 714 + { 715 + int ret = 0; 716 + 717 + aic32x4->supply_ldo = devm_regulator_get_optional(dev, "ldoin"); 718 + aic32x4->supply_iov = devm_regulator_get(dev, "iov"); 719 + aic32x4->supply_dv = devm_regulator_get_optional(dev, "dv"); 720 + aic32x4->supply_av = devm_regulator_get_optional(dev, "av"); 721 + 722 + /* Check if the regulator requirements are fulfilled */ 723 + 724 + if (IS_ERR(aic32x4->supply_iov)) { 725 + dev_err(dev, "Missing supply 'iov'\n"); 726 + return PTR_ERR(aic32x4->supply_iov); 727 + } 728 + 729 + if (IS_ERR(aic32x4->supply_ldo)) { 730 + if (PTR_ERR(aic32x4->supply_ldo) == -EPROBE_DEFER) 731 + return -EPROBE_DEFER; 732 + 733 + if (IS_ERR(aic32x4->supply_dv)) { 734 + dev_err(dev, "Missing supply 'dv' or 'ldoin'\n"); 735 + return PTR_ERR(aic32x4->supply_dv); 736 + } 737 + if (IS_ERR(aic32x4->supply_av)) { 738 + dev_err(dev, "Missing supply 'av' or 'ldoin'\n"); 739 + return PTR_ERR(aic32x4->supply_av); 740 + } 741 + } else { 742 + if (IS_ERR(aic32x4->supply_dv) && 743 + PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER) 744 + return -EPROBE_DEFER; 745 + if (IS_ERR(aic32x4->supply_av) && 746 + PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER) 747 + return -EPROBE_DEFER; 748 + } 749 + 750 + ret = regulator_enable(aic32x4->supply_iov); 751 + if (ret) { 752 + dev_err(dev, "Failed to enable regulator iov\n"); 753 + return ret; 754 + } 755 + 756 + if (!IS_ERR(aic32x4->supply_ldo)) { 757 + ret = regulator_enable(aic32x4->supply_ldo); 758 + if (ret) { 759 + dev_err(dev, "Failed to enable regulator ldo\n"); 760 + goto error_ldo; 761 + } 762 + } 763 + 764 + if (!IS_ERR(aic32x4->supply_dv)) { 765 + ret = regulator_enable(aic32x4->supply_dv); 766 + if (ret) { 767 + dev_err(dev, "Failed to enable regulator dv\n"); 768 + goto error_dv; 769 + } 770 + } 771 + 772 + if (!IS_ERR(aic32x4->supply_av)) { 773 + ret = regulator_enable(aic32x4->supply_av); 774 + if (ret) { 775 + dev_err(dev, "Failed to enable regulator av\n"); 776 + goto error_av; 777 + } 778 + } 779 + 780 + if (!IS_ERR(aic32x4->supply_ldo) && IS_ERR(aic32x4->supply_av)) 781 + aic32x4->power_cfg |= AIC32X4_PWR_AIC32X4_LDO_ENABLE; 782 + 783 + return 0; 784 + 785 + error_av: 786 + if (!IS_ERR(aic32x4->supply_dv)) 787 + regulator_disable(aic32x4->supply_dv); 788 + 789 + error_dv: 790 + if (!IS_ERR(aic32x4->supply_ldo)) 791 + regulator_disable(aic32x4->supply_ldo); 792 + 793 + error_ldo: 794 + regulator_disable(aic32x4->supply_iov); 795 + return ret; 796 + } 797 + 704 798 static int aic32x4_i2c_probe(struct i2c_client *i2c, 705 799 const struct i2c_device_id *id) 706 800 { ··· 851 745 return ret; 852 746 } 853 747 748 + ret = aic32x4_setup_regulators(&i2c->dev, aic32x4); 749 + if (ret) { 750 + dev_err(&i2c->dev, "Failed to setup regulators\n"); 751 + return ret; 752 + } 753 + 854 754 ret = snd_soc_register_codec(&i2c->dev, 855 755 &soc_codec_dev_aic32x4, &aic32x4_dai, 1); 856 - return ret; 756 + if (ret) { 757 + dev_err(&i2c->dev, "Failed to register codec\n"); 758 + aic32x4_disable_regulators(aic32x4); 759 + return ret; 760 + } 761 + 762 + i2c_set_clientdata(i2c, aic32x4); 763 + 764 + return 0; 857 765 } 858 766 859 767 static int aic32x4_i2c_remove(struct i2c_client *client) 860 768 { 769 + struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client); 770 + 771 + aic32x4_disable_regulators(aic32x4); 772 + 861 773 snd_soc_unregister_codec(&client->dev); 862 774 return 0; 863 775 }