diff options
author | Nicolin Chen <nicoleotsuka@gmail.com> | 2016-06-21 19:50:13 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-06-23 06:35:52 -0400 |
commit | 05f33bc5d6df03426e631cea5d1a8568d43ab07f (patch) | |
tree | e1f0294d8420d74f0b9f053d368081cd10958b6e | |
parent | b0e71c0ddda4e1540b38658cac705222a648c756 (diff) |
ASoC: cs53l30: Add MUTE pin control support via GPIO
The codec chip has a physical MUTE pin to let users control it via
GPIO. So this patch add a mute control support to the driver.
Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
Acked-by: Paul Handrigan <Paul.Handrigan@cirrus.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | Documentation/devicetree/bindings/sound/cs53l30.txt | 4 | ||||
-rw-r--r-- | sound/soc/codecs/cs53l30.c | 30 | ||||
-rw-r--r-- | sound/soc/codecs/cs53l30.h | 1 |
3 files changed, 35 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/cs53l30.txt b/Documentation/devicetree/bindings/sound/cs53l30.txt index 18d6b99e0a2d..4dbfb8274cd9 100644 --- a/Documentation/devicetree/bindings/sound/cs53l30.txt +++ b/Documentation/devicetree/bindings/sound/cs53l30.txt | |||
@@ -13,6 +13,10 @@ Optional properties: | |||
13 | 13 | ||
14 | - reset-gpios : a GPIO spec for the reset pin. | 14 | - reset-gpios : a GPIO spec for the reset pin. |
15 | 15 | ||
16 | - mute-gpios : a GPIO spec for the MUTE pin. The active state can be either | ||
17 | GPIO_ACTIVE_HIGH or GPIO_ACTIVE_LOW, which would be handled | ||
18 | by the driver automatically. | ||
19 | |||
16 | - cirrus,micbias-lvl : Set the output voltage level on the MICBIAS Pin. | 20 | - cirrus,micbias-lvl : Set the output voltage level on the MICBIAS Pin. |
17 | 0 = Hi-Z | 21 | 0 = Hi-Z |
18 | 1 = 1.80 V | 22 | 1 = 1.80 V |
diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index b0a64a19a045..5988b5c672fe 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c | |||
@@ -35,6 +35,7 @@ struct cs53l30_private { | |||
35 | struct regulator_bulk_data supplies[CS53L30_NUM_SUPPLIES]; | 35 | struct regulator_bulk_data supplies[CS53L30_NUM_SUPPLIES]; |
36 | struct regmap *regmap; | 36 | struct regmap *regmap; |
37 | struct gpio_desc *reset_gpio; | 37 | struct gpio_desc *reset_gpio; |
38 | struct gpio_desc *mute_gpio; | ||
38 | struct clk *mclk; | 39 | struct clk *mclk; |
39 | bool use_sdout2; | 40 | bool use_sdout2; |
40 | u32 mclk_rate; | 41 | u32 mclk_rate; |
@@ -833,6 +834,16 @@ static int cs53l30_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
833 | return 0; | 834 | return 0; |
834 | } | 835 | } |
835 | 836 | ||
837 | static int cs53l30_mute_stream(struct snd_soc_dai *dai, int mute, int stream) | ||
838 | { | ||
839 | struct cs53l30_private *priv = snd_soc_codec_get_drvdata(dai->codec); | ||
840 | |||
841 | if (priv->mute_gpio) | ||
842 | gpiod_set_value_cansleep(priv->mute_gpio, mute); | ||
843 | |||
844 | return 0; | ||
845 | } | ||
846 | |||
836 | /* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */ | 847 | /* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */ |
837 | #define CS53L30_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT) | 848 | #define CS53L30_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT) |
838 | 849 | ||
@@ -846,6 +857,7 @@ static const struct snd_soc_dai_ops cs53l30_ops = { | |||
846 | .set_sysclk = cs53l30_set_sysclk, | 857 | .set_sysclk = cs53l30_set_sysclk, |
847 | .set_tristate = cs53l30_set_tristate, | 858 | .set_tristate = cs53l30_set_tristate, |
848 | .set_tdm_slot = cs53l30_set_dai_tdm_slot, | 859 | .set_tdm_slot = cs53l30_set_dai_tdm_slot, |
860 | .mute_stream = cs53l30_mute_stream, | ||
849 | }; | 861 | }; |
850 | 862 | ||
851 | static struct snd_soc_dai_driver cs53l30_dai = { | 863 | static struct snd_soc_dai_driver cs53l30_dai = { |
@@ -991,6 +1003,24 @@ static int cs53l30_i2c_probe(struct i2c_client *client, | |||
991 | cs53l30->mclk = NULL; | 1003 | cs53l30->mclk = NULL; |
992 | } | 1004 | } |
993 | 1005 | ||
1006 | /* Fetch the MUTE control */ | ||
1007 | cs53l30->mute_gpio = devm_gpiod_get_optional(dev, "mute", | ||
1008 | GPIOD_OUT_HIGH); | ||
1009 | if (IS_ERR(cs53l30->mute_gpio)) { | ||
1010 | ret = PTR_ERR(cs53l30->mute_gpio); | ||
1011 | goto error; | ||
1012 | } | ||
1013 | |||
1014 | if (cs53l30->mute_gpio) { | ||
1015 | /* Enable MUTE controls via MUTE pin */ | ||
1016 | regmap_write(cs53l30->regmap, CS53L30_MUTEP_CTL1, | ||
1017 | CS53L30_MUTEP_CTL1_MUTEALL); | ||
1018 | /* Flip the polarity of MUTE pin */ | ||
1019 | if (gpiod_is_active_low(cs53l30->mute_gpio)) | ||
1020 | regmap_update_bits(cs53l30->regmap, CS53L30_MUTEP_CTL2, | ||
1021 | CS53L30_MUTE_PIN_POLARITY, 0); | ||
1022 | } | ||
1023 | |||
994 | if (!of_property_read_u8(np, "cirrus,micbias-lvl", &val)) | 1024 | if (!of_property_read_u8(np, "cirrus,micbias-lvl", &val)) |
995 | regmap_update_bits(cs53l30->regmap, CS53L30_MICBIAS_CTL, | 1025 | regmap_update_bits(cs53l30->regmap, CS53L30_MICBIAS_CTL, |
996 | CS53L30_MIC_BIAS_CTRL_MASK, val); | 1026 | CS53L30_MIC_BIAS_CTRL_MASK, val); |
diff --git a/sound/soc/codecs/cs53l30.h b/sound/soc/codecs/cs53l30.h index 0dd4afbb5c64..5e39da568749 100644 --- a/sound/soc/codecs/cs53l30.h +++ b/sound/soc/codecs/cs53l30.h | |||
@@ -253,6 +253,7 @@ | |||
253 | #define CS53L30_MUTE_MB_ALL_PDN_MASK (1 << CS53L30_MUTE_MB_ALL_PDN_SHIFT) | 253 | #define CS53L30_MUTE_MB_ALL_PDN_MASK (1 << CS53L30_MUTE_MB_ALL_PDN_SHIFT) |
254 | #define CS53L30_MUTE_MB_ALL_PDN (1 << CS53L30_MUTE_MB_ALL_PDN_SHIFT) | 254 | #define CS53L30_MUTE_MB_ALL_PDN (1 << CS53L30_MUTE_MB_ALL_PDN_SHIFT) |
255 | 255 | ||
256 | #define CS53L30_MUTEP_CTL1_MUTEALL (0xdf) | ||
256 | #define CS53L30_MUTEP_CTL1_DEFAULT (0) | 257 | #define CS53L30_MUTEP_CTL1_DEFAULT (0) |
257 | 258 | ||
258 | /* R32 (0x20) CS53L30_MUTEP_CTL2 - MUTE Pin Control 2 */ | 259 | /* R32 (0x20) CS53L30_MUTEP_CTL2 - MUTE Pin Control 2 */ |