diff options
author | Oder Chiou <oder_chiou@realtek.com> | 2014-09-15 23:37:39 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-09-16 12:16:12 -0400 |
commit | 44caf7648064502fd1d37d18443ae92c064ebadd (patch) | |
tree | eb012a83958e73cc0c82f396be745ae4fd0ec974 /sound/soc/codecs | |
parent | e5b2791d2a57e9da369bd75ae2a209bcce2ad4d3 (diff) |
ASoC: rt5677: Add the GPIO function
The patch adds the GPIO function.
Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/rt5677.c | 133 | ||||
-rw-r--r-- | sound/soc/codecs/rt5677.h | 112 |
2 files changed, 245 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 | } |
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index a334eb66cfc1..b61b72cfcbd7 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h | |||
@@ -1363,10 +1363,109 @@ | |||
1363 | #define RT5677_SEL_SRC_IB01 (0x1 << 0) | 1363 | #define RT5677_SEL_SRC_IB01 (0x1 << 0) |
1364 | #define RT5677_SEL_SRC_IB01_SFT 0 | 1364 | #define RT5677_SEL_SRC_IB01_SFT 0 |
1365 | 1365 | ||
1366 | /* GPIO status (0xbf) */ | ||
1367 | #define RT5677_GPIO6_STATUS_MASK (0x1 << 5) | ||
1368 | #define RT5677_GPIO6_STATUS_SFT 5 | ||
1369 | #define RT5677_GPIO5_STATUS_MASK (0x1 << 4) | ||
1370 | #define RT5677_GPIO5_STATUS_SFT 4 | ||
1371 | #define RT5677_GPIO4_STATUS_MASK (0x1 << 3) | ||
1372 | #define RT5677_GPIO4_STATUS_SFT 3 | ||
1373 | #define RT5677_GPIO3_STATUS_MASK (0x1 << 2) | ||
1374 | #define RT5677_GPIO3_STATUS_SFT 2 | ||
1375 | #define RT5677_GPIO2_STATUS_MASK (0x1 << 1) | ||
1376 | #define RT5677_GPIO2_STATUS_SFT 1 | ||
1377 | #define RT5677_GPIO1_STATUS_MASK (0x1 << 0) | ||
1378 | #define RT5677_GPIO1_STATUS_SFT 0 | ||
1379 | |||
1380 | /* GPIO Control 1 (0xc0) */ | ||
1381 | #define RT5677_GPIO1_PIN_MASK (0x1 << 15) | ||
1382 | #define RT5677_GPIO1_PIN_SFT 15 | ||
1383 | #define RT5677_GPIO1_PIN_GPIO1 (0x0 << 15) | ||
1384 | #define RT5677_GPIO1_PIN_IRQ (0x1 << 15) | ||
1385 | #define RT5677_IPTV_MODE_MASK (0x1 << 14) | ||
1386 | #define RT5677_IPTV_MODE_SFT 14 | ||
1387 | #define RT5677_IPTV_MODE_GPIO (0x0 << 14) | ||
1388 | #define RT5677_IPTV_MODE_IPTV (0x1 << 14) | ||
1389 | #define RT5677_FUNC_MODE_MASK (0x1 << 13) | ||
1390 | #define RT5677_FUNC_MODE_SFT 13 | ||
1391 | #define RT5677_FUNC_MODE_DMIC_GPIO (0x0 << 13) | ||
1392 | #define RT5677_FUNC_MODE_JTAG (0x1 << 13) | ||
1393 | |||
1366 | /* GPIO Control 2 (0xc1) */ | 1394 | /* GPIO Control 2 (0xc1) */ |
1367 | #define RT5677_GPIO5_DIR_MASK (0x1 << 14) | 1395 | #define RT5677_GPIO5_DIR_MASK (0x1 << 14) |
1396 | #define RT5677_GPIO5_DIR_SFT 14 | ||
1368 | #define RT5677_GPIO5_DIR_IN (0x0 << 14) | 1397 | #define RT5677_GPIO5_DIR_IN (0x0 << 14) |
1369 | #define RT5677_GPIO5_DIR_OUT (0x1 << 14) | 1398 | #define RT5677_GPIO5_DIR_OUT (0x1 << 14) |
1399 | #define RT5677_GPIO5_OUT_MASK (0x1 << 13) | ||
1400 | #define RT5677_GPIO5_OUT_SFT 13 | ||
1401 | #define RT5677_GPIO5_OUT_LO (0x0 << 13) | ||
1402 | #define RT5677_GPIO5_OUT_HI (0x1 << 13) | ||
1403 | #define RT5677_GPIO5_P_MASK (0x1 << 12) | ||
1404 | #define RT5677_GPIO5_P_SFT 12 | ||
1405 | #define RT5677_GPIO5_P_NOR (0x0 << 12) | ||
1406 | #define RT5677_GPIO5_P_INV (0x1 << 12) | ||
1407 | #define RT5677_GPIO4_DIR_MASK (0x1 << 11) | ||
1408 | #define RT5677_GPIO4_DIR_SFT 11 | ||
1409 | #define RT5677_GPIO4_DIR_IN (0x0 << 11) | ||
1410 | #define RT5677_GPIO4_DIR_OUT (0x1 << 11) | ||
1411 | #define RT5677_GPIO4_OUT_MASK (0x1 << 10) | ||
1412 | #define RT5677_GPIO4_OUT_SFT 10 | ||
1413 | #define RT5677_GPIO4_OUT_LO (0x0 << 10) | ||
1414 | #define RT5677_GPIO4_OUT_HI (0x1 << 10) | ||
1415 | #define RT5677_GPIO4_P_MASK (0x1 << 9) | ||
1416 | #define RT5677_GPIO4_P_SFT 9 | ||
1417 | #define RT5677_GPIO4_P_NOR (0x0 << 9) | ||
1418 | #define RT5677_GPIO4_P_INV (0x1 << 9) | ||
1419 | #define RT5677_GPIO3_DIR_MASK (0x1 << 8) | ||
1420 | #define RT5677_GPIO3_DIR_SFT 8 | ||
1421 | #define RT5677_GPIO3_DIR_IN (0x0 << 8) | ||
1422 | #define RT5677_GPIO3_DIR_OUT (0x1 << 8) | ||
1423 | #define RT5677_GPIO3_OUT_MASK (0x1 << 7) | ||
1424 | #define RT5677_GPIO3_OUT_SFT 7 | ||
1425 | #define RT5677_GPIO3_OUT_LO (0x0 << 7) | ||
1426 | #define RT5677_GPIO3_OUT_HI (0x1 << 7) | ||
1427 | #define RT5677_GPIO3_P_MASK (0x1 << 6) | ||
1428 | #define RT5677_GPIO3_P_SFT 6 | ||
1429 | #define RT5677_GPIO3_P_NOR (0x0 << 6) | ||
1430 | #define RT5677_GPIO3_P_INV (0x1 << 6) | ||
1431 | #define RT5677_GPIO2_DIR_MASK (0x1 << 5) | ||
1432 | #define RT5677_GPIO2_DIR_SFT 5 | ||
1433 | #define RT5677_GPIO2_DIR_IN (0x0 << 5) | ||
1434 | #define RT5677_GPIO2_DIR_OUT (0x1 << 5) | ||
1435 | #define RT5677_GPIO2_OUT_MASK (0x1 << 4) | ||
1436 | #define RT5677_GPIO2_OUT_SFT 4 | ||
1437 | #define RT5677_GPIO2_OUT_LO (0x0 << 4) | ||
1438 | #define RT5677_GPIO2_OUT_HI (0x1 << 4) | ||
1439 | #define RT5677_GPIO2_P_MASK (0x1 << 3) | ||
1440 | #define RT5677_GPIO2_P_SFT 3 | ||
1441 | #define RT5677_GPIO2_P_NOR (0x0 << 3) | ||
1442 | #define RT5677_GPIO2_P_INV (0x1 << 3) | ||
1443 | #define RT5677_GPIO1_DIR_MASK (0x1 << 2) | ||
1444 | #define RT5677_GPIO1_DIR_SFT 2 | ||
1445 | #define RT5677_GPIO1_DIR_IN (0x0 << 2) | ||
1446 | #define RT5677_GPIO1_DIR_OUT (0x1 << 2) | ||
1447 | #define RT5677_GPIO1_OUT_MASK (0x1 << 1) | ||
1448 | #define RT5677_GPIO1_OUT_SFT 1 | ||
1449 | #define RT5677_GPIO1_OUT_LO (0x0 << 1) | ||
1450 | #define RT5677_GPIO1_OUT_HI (0x1 << 1) | ||
1451 | #define RT5677_GPIO1_P_MASK (0x1 << 0) | ||
1452 | #define RT5677_GPIO1_P_SFT 0 | ||
1453 | #define RT5677_GPIO1_P_NOR (0x0 << 0) | ||
1454 | #define RT5677_GPIO1_P_INV (0x1 << 0) | ||
1455 | |||
1456 | /* GPIO Control 3 (0xc2) */ | ||
1457 | #define RT5677_GPIO6_DIR_MASK (0x1 << 2) | ||
1458 | #define RT5677_GPIO6_DIR_SFT 2 | ||
1459 | #define RT5677_GPIO6_DIR_IN (0x0 << 2) | ||
1460 | #define RT5677_GPIO6_DIR_OUT (0x1 << 2) | ||
1461 | #define RT5677_GPIO6_OUT_MASK (0x1 << 1) | ||
1462 | #define RT5677_GPIO6_OUT_SFT 1 | ||
1463 | #define RT5677_GPIO6_OUT_LO (0x0 << 1) | ||
1464 | #define RT5677_GPIO6_OUT_HI (0x1 << 1) | ||
1465 | #define RT5677_GPIO6_P_MASK (0x1 << 0) | ||
1466 | #define RT5677_GPIO6_P_SFT 0 | ||
1467 | #define RT5677_GPIO6_P_NOR (0x0 << 0) | ||
1468 | #define RT5677_GPIO6_P_INV (0x1 << 0) | ||
1370 | 1469 | ||
1371 | /* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */ | 1470 | /* Virtual DSP Mixer Control (0xf7 0xf8 0xf9) */ |
1372 | #define RT5677_DSP_IB_01_H (0x1 << 15) | 1471 | #define RT5677_DSP_IB_01_H (0x1 << 15) |
@@ -1428,6 +1527,16 @@ enum { | |||
1428 | RT5677_AIFS, | 1527 | RT5677_AIFS, |
1429 | }; | 1528 | }; |
1430 | 1529 | ||
1530 | enum { | ||
1531 | RT5677_GPIO1, | ||
1532 | RT5677_GPIO2, | ||
1533 | RT5677_GPIO3, | ||
1534 | RT5677_GPIO4, | ||
1535 | RT5677_GPIO5, | ||
1536 | RT5677_GPIO6, | ||
1537 | RT5677_GPIO_NUM, | ||
1538 | }; | ||
1539 | |||
1431 | struct rt5677_priv { | 1540 | struct rt5677_priv { |
1432 | struct snd_soc_codec *codec; | 1541 | struct snd_soc_codec *codec; |
1433 | struct rt5677_platform_data pdata; | 1542 | struct rt5677_platform_data pdata; |
@@ -1441,6 +1550,9 @@ struct rt5677_priv { | |||
1441 | int pll_src; | 1550 | int pll_src; |
1442 | int pll_in; | 1551 | int pll_in; |
1443 | int pll_out; | 1552 | int pll_out; |
1553 | #ifdef CONFIG_GPIOLIB | ||
1554 | struct gpio_chip gpio_chip; | ||
1555 | #endif | ||
1444 | }; | 1556 | }; |
1445 | 1557 | ||
1446 | #endif /* __RT5677_H__ */ | 1558 | #endif /* __RT5677_H__ */ |