diff options
Diffstat (limited to 'sound/soc/codecs/rt5677.c')
-rw-r--r-- | sound/soc/codecs/rt5677.c | 133 |
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 | ||
3165 | static inline struct rt5677_priv *gpio_to_rt5677(struct gpio_chip *chip) | ||
3166 | { | ||
3167 | return container_of(chip, struct rt5677_priv, gpio_chip); | ||
3168 | } | ||
3169 | |||
3170 | static 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 | |||
3190 | static 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 | |||
3215 | static 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 | |||
3227 | static 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 | |||
3249 | static 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 | |||
3259 | static 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 | |||
3274 | static 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 | ||
3284 | static void rt5677_init_gpio(struct i2c_client *i2c) | ||
3285 | { | ||
3286 | } | ||
3287 | |||
3288 | static void rt5677_free_gpio(struct i2c_client *i2c) | ||
3289 | { | ||
3290 | } | ||
3291 | #endif | ||
3292 | |||
3163 | static int rt5677_probe(struct snd_soc_codec *codec) | 3293 | static 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, | |||
3429 | static int rt5677_i2c_remove(struct i2c_client *i2c) | 3561 | static 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 | } |