aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/rt5677.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/rt5677.c')
-rw-r--r--sound/soc/codecs/rt5677.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index f0b751bf1d6c..02bc8bd7caeb 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -19,6 +19,7 @@
19#include <linux/i2c.h> 19#include <linux/i2c.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/spi/spi.h> 21#include <linux/spi/spi.h>
22#include <linux/gpio.h>
22#include <sound/core.h> 23#include <sound/core.h>
23#include <sound/pcm.h> 24#include <sound/pcm.h>
24#include <sound/pcm_params.h> 25#include <sound/pcm_params.h>
@@ -3160,6 +3161,135 @@ static int rt5677_set_bias_level(struct snd_soc_codec *codec,
3160 return 0; 3161 return 0;
3161} 3162}
3162 3163
3164#ifdef CONFIG_GPIOLIB
3165static inline struct rt5677_priv *gpio_to_rt5677(struct gpio_chip *chip)
3166{
3167 return container_of(chip, struct rt5677_priv, gpio_chip);
3168}
3169
3170static void rt5677_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
3171{
3172 struct rt5677_priv *rt5677 = gpio_to_rt5677(chip);
3173
3174 switch (offset) {
3175 case RT5677_GPIO1 ... RT5677_GPIO5:
3176 regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
3177 0x1 << (offset * 3 + 1), !!value << (offset * 3 + 1));
3178 break;
3179
3180 case RT5677_GPIO6:
3181 regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3,
3182 RT5677_GPIO6_OUT_MASK, !!value << RT5677_GPIO6_OUT_SFT);
3183 break;
3184
3185 default:
3186 break;
3187 }
3188}
3189
3190static int rt5677_gpio_direction_out(struct gpio_chip *chip,
3191 unsigned offset, int value)
3192{
3193 struct rt5677_priv *rt5677 = gpio_to_rt5677(chip);
3194
3195 switch (offset) {
3196 case RT5677_GPIO1 ... RT5677_GPIO5:
3197 regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
3198 0x3 << (offset * 3 + 1),
3199 (0x2 | !!value) << (offset * 3 + 1));
3200 break;
3201
3202 case RT5677_GPIO6:
3203 regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3,
3204 RT5677_GPIO6_DIR_MASK | RT5677_GPIO6_OUT_MASK,
3205 RT5677_GPIO6_DIR_OUT | !!value << RT5677_GPIO6_OUT_SFT);
3206 break;
3207
3208 default:
3209 break;
3210 }
3211
3212 return 0;
3213}
3214
3215static int rt5677_gpio_get(struct gpio_chip *chip, unsigned offset)
3216{
3217 struct rt5677_priv *rt5677 = gpio_to_rt5677(chip);
3218 int value, ret;
3219
3220 ret = regmap_read(rt5677->regmap, RT5677_GPIO_ST, &value);
3221 if (ret < 0)
3222 return ret;
3223
3224 return (value & (0x1 << offset)) >> offset;
3225}
3226
3227static int rt5677_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
3228{
3229 struct rt5677_priv *rt5677 = gpio_to_rt5677(chip);
3230
3231 switch (offset) {
3232 case RT5677_GPIO1 ... RT5677_GPIO5:
3233 regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
3234 0x1 << (offset * 3 + 2), 0x0);
3235 break;
3236
3237 case RT5677_GPIO6:
3238 regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3,
3239 RT5677_GPIO6_DIR_MASK, RT5677_GPIO6_DIR_IN);
3240 break;
3241
3242 default:
3243 break;
3244 }
3245
3246 return 0;
3247}
3248
3249static struct gpio_chip rt5677_template_chip = {
3250 .label = "rt5677",
3251 .owner = THIS_MODULE,
3252 .direction_output = rt5677_gpio_direction_out,
3253 .set = rt5677_gpio_set,
3254 .direction_input = rt5677_gpio_direction_in,
3255 .get = rt5677_gpio_get,
3256 .can_sleep = 1,
3257};
3258
3259static void rt5677_init_gpio(struct i2c_client *i2c)
3260{
3261 struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c);
3262 int ret;
3263
3264 rt5677->gpio_chip = rt5677_template_chip;
3265 rt5677->gpio_chip.ngpio = RT5677_GPIO_NUM;
3266 rt5677->gpio_chip.dev = &i2c->dev;
3267 rt5677->gpio_chip.base = -1;
3268
3269 ret = gpiochip_add(&rt5677->gpio_chip);
3270 if (ret != 0)
3271 dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret);
3272}
3273
3274static void rt5677_free_gpio(struct i2c_client *i2c)
3275{
3276 struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c);
3277 int ret;
3278
3279 ret = gpiochip_remove(&rt5677->gpio_chip);
3280 if (ret != 0)
3281 dev_err(&i2c->dev, "Failed to remove GPIOs: %d\n", ret);
3282}
3283#else
3284static void rt5677_init_gpio(struct i2c_client *i2c)
3285{
3286}
3287
3288static void rt5677_free_gpio(struct i2c_client *i2c)
3289{
3290}
3291#endif
3292
3163static int rt5677_probe(struct snd_soc_codec *codec) 3293static int rt5677_probe(struct snd_soc_codec *codec)
3164{ 3294{
3165 struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec); 3295 struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
@@ -3422,6 +3552,8 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
3422 RT5677_GPIO5_DIR_OUT); 3552 RT5677_GPIO5_DIR_OUT);
3423 } 3553 }
3424 3554
3555 rt5677_init_gpio(i2c);
3556
3425 return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, 3557 return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677,
3426 rt5677_dai, ARRAY_SIZE(rt5677_dai)); 3558 rt5677_dai, ARRAY_SIZE(rt5677_dai));
3427} 3559}
@@ -3429,6 +3561,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
3429static int rt5677_i2c_remove(struct i2c_client *i2c) 3561static int rt5677_i2c_remove(struct i2c_client *i2c)
3430{ 3562{
3431 snd_soc_unregister_codec(&i2c->dev); 3563 snd_soc_unregister_codec(&i2c->dev);
3564 rt5677_free_gpio(i2c);
3432 3565
3433 return 0; 3566 return 0;
3434} 3567}