aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
diff options
context:
space:
mode:
authorOder Chiou <oder_chiou@realtek.com>2014-09-15 23:37:39 -0400
committerMark Brown <broonie@kernel.org>2014-09-16 12:16:12 -0400
commit44caf7648064502fd1d37d18443ae92c064ebadd (patch)
treeeb012a83958e73cc0c82f396be745ae4fd0ec974 /sound/soc/codecs
parente5b2791d2a57e9da369bd75ae2a209bcce2ad4d3 (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.c133
-rw-r--r--sound/soc/codecs/rt5677.h112
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
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}
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
1530enum {
1531 RT5677_GPIO1,
1532 RT5677_GPIO2,
1533 RT5677_GPIO3,
1534 RT5677_GPIO4,
1535 RT5677_GPIO5,
1536 RT5677_GPIO6,
1537 RT5677_GPIO_NUM,
1538};
1539
1431struct rt5677_priv { 1540struct 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__ */