aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/tlv320aic32x4.txt4
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c21
2 files changed, 25 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
index db0551088cc4..352be7b1f7e2 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
@@ -8,6 +8,8 @@ Required properties:
8 8
9Optional properties: 9Optional properties:
10 - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt 10 - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
11 - clocks/clock-names: Clock named 'mclk' for the master clock of the codec.
12 See clock/clock-bindings.txt for information about the detailed format.
11 13
12 14
13Example: 15Example:
@@ -15,4 +17,6 @@ Example:
15codec: tlv320aic32x4@18 { 17codec: tlv320aic32x4@18 {
16 compatible = "ti,tlv320aic32x4"; 18 compatible = "ti,tlv320aic32x4";
17 reg = <0x18>; 19 reg = <0x18>;
20 clocks = <&clks 201>;
21 clock-names = "mclk";
18}; 22};
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 1dd50e48934c..643fa53beaab 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -33,6 +33,7 @@
33#include <linux/i2c.h> 33#include <linux/i2c.h>
34#include <linux/cdev.h> 34#include <linux/cdev.h>
35#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/clk.h>
36 37
37#include <sound/tlv320aic32x4.h> 38#include <sound/tlv320aic32x4.h>
38#include <sound/core.h> 39#include <sound/core.h>
@@ -67,6 +68,7 @@ struct aic32x4_priv {
67 u32 micpga_routing; 68 u32 micpga_routing;
68 bool swapdacs; 69 bool swapdacs;
69 int rstn_gpio; 70 int rstn_gpio;
71 struct clk *mclk;
70}; 72};
71 73
72/* 0dB min, 0.5dB steps */ 74/* 0dB min, 0.5dB steps */
@@ -487,8 +489,18 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute)
487static int aic32x4_set_bias_level(struct snd_soc_codec *codec, 489static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
488 enum snd_soc_bias_level level) 490 enum snd_soc_bias_level level)
489{ 491{
492 struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
493 int ret;
494
490 switch (level) { 495 switch (level) {
491 case SND_SOC_BIAS_ON: 496 case SND_SOC_BIAS_ON:
497 /* Switch on master clock */
498 ret = clk_prepare_enable(aic32x4->mclk);
499 if (ret) {
500 dev_err(codec->dev, "Failed to enable master clock\n");
501 return ret;
502 }
503
492 /* Switch on PLL */ 504 /* Switch on PLL */
493 snd_soc_update_bits(codec, AIC32X4_PLLPR, 505 snd_soc_update_bits(codec, AIC32X4_PLLPR,
494 AIC32X4_PLLEN, AIC32X4_PLLEN); 506 AIC32X4_PLLEN, AIC32X4_PLLEN);
@@ -539,6 +551,9 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
539 /* Switch off BCLK_N Divider */ 551 /* Switch off BCLK_N Divider */
540 snd_soc_update_bits(codec, AIC32X4_BCLKN, 552 snd_soc_update_bits(codec, AIC32X4_BCLKN,
541 AIC32X4_BCLKEN, 0); 553 AIC32X4_BCLKEN, 0);
554
555 /* Switch off master clock */
556 clk_disable_unprepare(aic32x4->mclk);
542 break; 557 break;
543 case SND_SOC_BIAS_OFF: 558 case SND_SOC_BIAS_OFF:
544 break; 559 break;
@@ -717,6 +732,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
717 aic32x4->rstn_gpio = -1; 732 aic32x4->rstn_gpio = -1;
718 } 733 }
719 734
735 aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk");
736 if (IS_ERR(aic32x4->mclk)) {
737 dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n");
738 return PTR_ERR(aic32x4->mclk);
739 }
740
720 if (gpio_is_valid(aic32x4->rstn_gpio)) { 741 if (gpio_is_valid(aic32x4->rstn_gpio)) {
721 ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, 742 ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio,
722 GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); 743 GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");