diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/rt5677.txt | 10 | ||||
-rw-r--r-- | include/sound/rt5677.h | 7 | ||||
-rw-r--r-- | sound/soc/codecs/rt5677.c | 134 | ||||
-rw-r--r-- | sound/soc/codecs/rt5677.h | 49 |
4 files changed, 200 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/rt5677.txt b/Documentation/devicetree/bindings/sound/rt5677.txt index f82f0e906cd9..740ff771aa8b 100644 --- a/Documentation/devicetree/bindings/sound/rt5677.txt +++ b/Documentation/devicetree/bindings/sound/rt5677.txt | |||
@@ -33,6 +33,15 @@ Optional properties: | |||
33 | 1 - pull down | 33 | 1 - pull down |
34 | 2 - pull up | 34 | 2 - pull up |
35 | 35 | ||
36 | - realtek,jd1-gpio | ||
37 | Configures GPIO Mic Jack detection 1. | ||
38 | Select 0 ~ 3 as OFF, GPIO1, GPIO2 and GPIO3 respectively. | ||
39 | |||
40 | - realtek,jd2-gpio | ||
41 | - realtek,jd3-gpio | ||
42 | Configures GPIO Mic Jack detection 2 and 3. | ||
43 | Select 0 ~ 3 as OFF, GPIO4, GPIO5 and GPIO6 respectively. | ||
44 | |||
36 | Pins on the device (for linking into audio routes): | 45 | Pins on the device (for linking into audio routes): |
37 | 46 | ||
38 | * IN1P | 47 | * IN1P |
@@ -63,4 +72,5 @@ rt5677 { | |||
63 | <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; | 72 | <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; |
64 | realtek,in1-differential = "true"; | 73 | realtek,in1-differential = "true"; |
65 | realtek,gpio-config = /bits/ 8 <0 0 0 0 0 2>; /* pull up GPIO6 */ | 74 | realtek,gpio-config = /bits/ 8 <0 0 0 0 0 2>; /* pull up GPIO6 */ |
75 | realtek,jd2-gpio = <3>; /* Enables Jack detection for GPIO6 */ | ||
66 | }; | 76 | }; |
diff --git a/include/sound/rt5677.h b/include/sound/rt5677.h index a56b429a1dbc..d9eb7d861cd0 100644 --- a/include/sound/rt5677.h +++ b/include/sound/rt5677.h | |||
@@ -30,6 +30,13 @@ struct rt5677_platform_data { | |||
30 | 30 | ||
31 | /* configures GPIO, 0 - floating, 1 - pulldown, 2 - pullup */ | 31 | /* configures GPIO, 0 - floating, 1 - pulldown, 2 - pullup */ |
32 | u8 gpio_config[6]; | 32 | u8 gpio_config[6]; |
33 | |||
34 | /* jd1 can select 0 ~ 3 as OFF, GPIO1, GPIO2 and GPIO3 respectively */ | ||
35 | unsigned int jd1_gpio; | ||
36 | /* jd2 and jd3 can select 0 ~ 3 as | ||
37 | OFF, GPIO4, GPIO5 and GPIO6 respectively */ | ||
38 | unsigned int jd2_gpio; | ||
39 | unsigned int jd3_gpio; | ||
33 | }; | 40 | }; |
34 | 41 | ||
35 | #endif | 42 | #endif |
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index d17d079fdcf3..6c73dfd22a0c 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c | |||
@@ -3614,6 +3614,46 @@ static void rt5677_gpio_config(struct rt5677_priv *rt5677, unsigned offset, | |||
3614 | } | 3614 | } |
3615 | } | 3615 | } |
3616 | 3616 | ||
3617 | static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset) | ||
3618 | { | ||
3619 | struct rt5677_priv *rt5677 = gpio_to_rt5677(chip); | ||
3620 | struct regmap_irq_chip_data *data = rt5677->irq_data; | ||
3621 | int irq; | ||
3622 | |||
3623 | if (offset >= RT5677_GPIO1 && offset <= RT5677_GPIO3) { | ||
3624 | if ((rt5677->pdata.jd1_gpio == 1 && offset == RT5677_GPIO1) || | ||
3625 | (rt5677->pdata.jd1_gpio == 2 && | ||
3626 | offset == RT5677_GPIO2) || | ||
3627 | (rt5677->pdata.jd1_gpio == 3 && | ||
3628 | offset == RT5677_GPIO3)) { | ||
3629 | irq = RT5677_IRQ_JD1; | ||
3630 | } else { | ||
3631 | return -ENXIO; | ||
3632 | } | ||
3633 | } | ||
3634 | |||
3635 | if (offset >= RT5677_GPIO4 && offset <= RT5677_GPIO6) { | ||
3636 | if ((rt5677->pdata.jd2_gpio == 1 && offset == RT5677_GPIO4) || | ||
3637 | (rt5677->pdata.jd2_gpio == 2 && | ||
3638 | offset == RT5677_GPIO5) || | ||
3639 | (rt5677->pdata.jd2_gpio == 3 && | ||
3640 | offset == RT5677_GPIO6)) { | ||
3641 | irq = RT5677_IRQ_JD2; | ||
3642 | } else if ((rt5677->pdata.jd3_gpio == 1 && | ||
3643 | offset == RT5677_GPIO4) || | ||
3644 | (rt5677->pdata.jd3_gpio == 2 && | ||
3645 | offset == RT5677_GPIO5) || | ||
3646 | (rt5677->pdata.jd3_gpio == 3 && | ||
3647 | offset == RT5677_GPIO6)) { | ||
3648 | irq = RT5677_IRQ_JD3; | ||
3649 | } else { | ||
3650 | return -ENXIO; | ||
3651 | } | ||
3652 | } | ||
3653 | |||
3654 | return regmap_irq_get_virq(data, irq); | ||
3655 | } | ||
3656 | |||
3617 | static struct gpio_chip rt5677_template_chip = { | 3657 | static struct gpio_chip rt5677_template_chip = { |
3618 | .label = "rt5677", | 3658 | .label = "rt5677", |
3619 | .owner = THIS_MODULE, | 3659 | .owner = THIS_MODULE, |
@@ -3621,6 +3661,7 @@ static struct gpio_chip rt5677_template_chip = { | |||
3621 | .set = rt5677_gpio_set, | 3661 | .set = rt5677_gpio_set, |
3622 | .direction_input = rt5677_gpio_direction_in, | 3662 | .direction_input = rt5677_gpio_direction_in, |
3623 | .get = rt5677_gpio_get, | 3663 | .get = rt5677_gpio_get, |
3664 | .to_irq = rt5677_to_irq, | ||
3624 | .can_sleep = 1, | 3665 | .can_sleep = 1, |
3625 | }; | 3666 | }; |
3626 | 3667 | ||
@@ -3685,6 +3726,31 @@ static int rt5677_probe(struct snd_soc_codec *codec) | |||
3685 | for (i = 0; i < RT5677_GPIO_NUM; i++) | 3726 | for (i = 0; i < RT5677_GPIO_NUM; i++) |
3686 | rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]); | 3727 | rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]); |
3687 | 3728 | ||
3729 | if (rt5677->irq_data) { | ||
3730 | regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL1, 0x8000, | ||
3731 | 0x8000); | ||
3732 | regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x0018, | ||
3733 | 0x0008); | ||
3734 | |||
3735 | if (rt5677->pdata.jd1_gpio) | ||
3736 | regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, | ||
3737 | RT5677_SEL_GPIO_JD1_MASK, | ||
3738 | rt5677->pdata.jd1_gpio << | ||
3739 | RT5677_SEL_GPIO_JD1_SFT); | ||
3740 | |||
3741 | if (rt5677->pdata.jd2_gpio) | ||
3742 | regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, | ||
3743 | RT5677_SEL_GPIO_JD2_MASK, | ||
3744 | rt5677->pdata.jd2_gpio << | ||
3745 | RT5677_SEL_GPIO_JD2_SFT); | ||
3746 | |||
3747 | if (rt5677->pdata.jd3_gpio) | ||
3748 | regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1, | ||
3749 | RT5677_SEL_GPIO_JD3_MASK, | ||
3750 | rt5677->pdata.jd3_gpio << | ||
3751 | RT5677_SEL_GPIO_JD3_SFT); | ||
3752 | } | ||
3753 | |||
3688 | mutex_init(&rt5677->dsp_cmd_lock); | 3754 | mutex_init(&rt5677->dsp_cmd_lock); |
3689 | 3755 | ||
3690 | return 0; | 3756 | return 0; |
@@ -3915,9 +3981,74 @@ static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np) | |||
3915 | of_property_read_u8_array(np, "realtek,gpio-config", | 3981 | of_property_read_u8_array(np, "realtek,gpio-config", |
3916 | rt5677->pdata.gpio_config, RT5677_GPIO_NUM); | 3982 | rt5677->pdata.gpio_config, RT5677_GPIO_NUM); |
3917 | 3983 | ||
3984 | of_property_read_u32(np, "realtek,jd1-gpio", &rt5677->pdata.jd1_gpio); | ||
3985 | of_property_read_u32(np, "realtek,jd2-gpio", &rt5677->pdata.jd2_gpio); | ||
3986 | of_property_read_u32(np, "realtek,jd3-gpio", &rt5677->pdata.jd3_gpio); | ||
3987 | |||
3918 | return 0; | 3988 | return 0; |
3919 | } | 3989 | } |
3920 | 3990 | ||
3991 | static struct regmap_irq rt5677_irqs[] = { | ||
3992 | [RT5677_IRQ_JD1] = { | ||
3993 | .reg_offset = 0, | ||
3994 | .mask = RT5677_EN_IRQ_GPIO_JD1, | ||
3995 | }, | ||
3996 | [RT5677_IRQ_JD2] = { | ||
3997 | .reg_offset = 0, | ||
3998 | .mask = RT5677_EN_IRQ_GPIO_JD2, | ||
3999 | }, | ||
4000 | [RT5677_IRQ_JD3] = { | ||
4001 | .reg_offset = 0, | ||
4002 | .mask = RT5677_EN_IRQ_GPIO_JD3, | ||
4003 | }, | ||
4004 | }; | ||
4005 | |||
4006 | static struct regmap_irq_chip rt5677_irq_chip = { | ||
4007 | .name = "rt5677", | ||
4008 | .irqs = rt5677_irqs, | ||
4009 | .num_irqs = ARRAY_SIZE(rt5677_irqs), | ||
4010 | |||
4011 | .num_regs = 1, | ||
4012 | .status_base = RT5677_IRQ_CTRL1, | ||
4013 | .mask_base = RT5677_IRQ_CTRL1, | ||
4014 | .mask_invert = 1, | ||
4015 | }; | ||
4016 | |||
4017 | int rt5677_irq_init(struct i2c_client *i2c) | ||
4018 | { | ||
4019 | int ret; | ||
4020 | struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c); | ||
4021 | |||
4022 | if (!rt5677->pdata.jd1_gpio && | ||
4023 | !rt5677->pdata.jd2_gpio && | ||
4024 | !rt5677->pdata.jd3_gpio) | ||
4025 | return 0; | ||
4026 | |||
4027 | if (!i2c->irq) { | ||
4028 | dev_err(&i2c->dev, "No interrupt specified\n"); | ||
4029 | return -EINVAL; | ||
4030 | } | ||
4031 | |||
4032 | ret = regmap_add_irq_chip(rt5677->regmap, i2c->irq, | ||
4033 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0, | ||
4034 | &rt5677_irq_chip, &rt5677->irq_data); | ||
4035 | |||
4036 | if (ret != 0) { | ||
4037 | dev_err(&i2c->dev, "Failed to register IRQ chip: %d\n", ret); | ||
4038 | return ret; | ||
4039 | } | ||
4040 | |||
4041 | return 0; | ||
4042 | } | ||
4043 | |||
4044 | void rt5677_irq_exit(struct i2c_client *i2c) | ||
4045 | { | ||
4046 | struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c); | ||
4047 | |||
4048 | if (rt5677->irq_data) | ||
4049 | regmap_del_irq_chip(i2c->irq, rt5677->irq_data); | ||
4050 | } | ||
4051 | |||
3921 | static int rt5677_i2c_probe(struct i2c_client *i2c, | 4052 | static int rt5677_i2c_probe(struct i2c_client *i2c, |
3922 | const struct i2c_device_id *id) | 4053 | const struct i2c_device_id *id) |
3923 | { | 4054 | { |
@@ -4015,6 +4146,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
4015 | } | 4146 | } |
4016 | 4147 | ||
4017 | rt5677_init_gpio(i2c); | 4148 | rt5677_init_gpio(i2c); |
4149 | rt5677_irq_init(i2c); | ||
4018 | 4150 | ||
4019 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, | 4151 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677, |
4020 | rt5677_dai, ARRAY_SIZE(rt5677_dai)); | 4152 | rt5677_dai, ARRAY_SIZE(rt5677_dai)); |
@@ -4022,6 +4154,8 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, | |||
4022 | 4154 | ||
4023 | static int rt5677_i2c_remove(struct i2c_client *i2c) | 4155 | static int rt5677_i2c_remove(struct i2c_client *i2c) |
4024 | { | 4156 | { |
4157 | rt5677_irq_exit(i2c); | ||
4158 | |||
4025 | snd_soc_unregister_codec(&i2c->dev); | 4159 | snd_soc_unregister_codec(&i2c->dev); |
4026 | rt5677_free_gpio(i2c); | 4160 | rt5677_free_gpio(i2c); |
4027 | 4161 | ||
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h index 20efa4a4c82c..d2c743c255a1 100644 --- a/sound/soc/codecs/rt5677.h +++ b/sound/soc/codecs/rt5677.h | |||
@@ -1368,6 +1368,48 @@ | |||
1368 | #define RT5677_SEL_SRC_IB01 (0x1 << 0) | 1368 | #define RT5677_SEL_SRC_IB01 (0x1 << 0) |
1369 | #define RT5677_SEL_SRC_IB01_SFT 0 | 1369 | #define RT5677_SEL_SRC_IB01_SFT 0 |
1370 | 1370 | ||
1371 | /* Jack Detect Control 1 (0xb5) */ | ||
1372 | #define RT5677_SEL_GPIO_JD1_MASK (0x3 << 14) | ||
1373 | #define RT5677_SEL_GPIO_JD1_SFT 14 | ||
1374 | #define RT5677_SEL_GPIO_JD2_MASK (0x3 << 12) | ||
1375 | #define RT5677_SEL_GPIO_JD2_SFT 12 | ||
1376 | #define RT5677_SEL_GPIO_JD3_MASK (0x3 << 10) | ||
1377 | #define RT5677_SEL_GPIO_JD3_SFT 10 | ||
1378 | |||
1379 | /* IRQ Control 1 (0xbd) */ | ||
1380 | #define RT5677_STA_GPIO_JD1 (0x1 << 15) | ||
1381 | #define RT5677_STA_GPIO_JD1_SFT 15 | ||
1382 | #define RT5677_EN_IRQ_GPIO_JD1 (0x1 << 14) | ||
1383 | #define RT5677_EN_IRQ_GPIO_JD1_SFT 14 | ||
1384 | #define RT5677_EN_GPIO_JD1_STICKY (0x1 << 13) | ||
1385 | #define RT5677_EN_GPIO_JD1_STICKY_SFT 13 | ||
1386 | #define RT5677_INV_GPIO_JD1 (0x1 << 12) | ||
1387 | #define RT5677_INV_GPIO_JD1_SFT 12 | ||
1388 | #define RT5677_STA_GPIO_JD2 (0x1 << 11) | ||
1389 | #define RT5677_STA_GPIO_JD2_SFT 11 | ||
1390 | #define RT5677_EN_IRQ_GPIO_JD2 (0x1 << 10) | ||
1391 | #define RT5677_EN_IRQ_GPIO_JD2_SFT 10 | ||
1392 | #define RT5677_EN_GPIO_JD2_STICKY (0x1 << 9) | ||
1393 | #define RT5677_EN_GPIO_JD2_STICKY_SFT 9 | ||
1394 | #define RT5677_INV_GPIO_JD2 (0x1 << 8) | ||
1395 | #define RT5677_INV_GPIO_JD2_SFT 8 | ||
1396 | #define RT5677_STA_MICBIAS1_OVCD (0x1 << 7) | ||
1397 | #define RT5677_STA_MICBIAS1_OVCD_SFT 7 | ||
1398 | #define RT5677_EN_IRQ_MICBIAS1_OVCD (0x1 << 6) | ||
1399 | #define RT5677_EN_IRQ_MICBIAS1_OVCD_SFT 6 | ||
1400 | #define RT5677_EN_MICBIAS1_OVCD_STICKY (0x1 << 5) | ||
1401 | #define RT5677_EN_MICBIAS1_OVCD_STICKY_SFT 5 | ||
1402 | #define RT5677_INV_MICBIAS1_OVCD (0x1 << 4) | ||
1403 | #define RT5677_INV_MICBIAS1_OVCD_SFT 4 | ||
1404 | #define RT5677_STA_GPIO_JD3 (0x1 << 3) | ||
1405 | #define RT5677_STA_GPIO_JD3_SFT 3 | ||
1406 | #define RT5677_EN_IRQ_GPIO_JD3 (0x1 << 2) | ||
1407 | #define RT5677_EN_IRQ_GPIO_JD3_SFT 2 | ||
1408 | #define RT5677_EN_GPIO_JD3_STICKY (0x1 << 1) | ||
1409 | #define RT5677_EN_GPIO_JD3_STICKY_SFT 1 | ||
1410 | #define RT5677_INV_GPIO_JD3 (0x1 << 0) | ||
1411 | #define RT5677_INV_GPIO_JD3_SFT 0 | ||
1412 | |||
1371 | /* GPIO status (0xbf) */ | 1413 | /* GPIO status (0xbf) */ |
1372 | #define RT5677_GPIO6_STATUS_MASK (0x1 << 5) | 1414 | #define RT5677_GPIO6_STATUS_MASK (0x1 << 5) |
1373 | #define RT5677_GPIO6_STATUS_SFT 5 | 1415 | #define RT5677_GPIO6_STATUS_SFT 5 |
@@ -1545,6 +1587,12 @@ enum { | |||
1545 | RT5677_GPIO_NUM, | 1587 | RT5677_GPIO_NUM, |
1546 | }; | 1588 | }; |
1547 | 1589 | ||
1590 | enum { | ||
1591 | RT5677_IRQ_JD1, | ||
1592 | RT5677_IRQ_JD2, | ||
1593 | RT5677_IRQ_JD3, | ||
1594 | }; | ||
1595 | |||
1548 | struct rt5677_priv { | 1596 | struct rt5677_priv { |
1549 | struct snd_soc_codec *codec; | 1597 | struct snd_soc_codec *codec; |
1550 | struct rt5677_platform_data pdata; | 1598 | struct rt5677_platform_data pdata; |
@@ -1565,6 +1613,7 @@ struct rt5677_priv { | |||
1565 | struct gpio_chip gpio_chip; | 1613 | struct gpio_chip gpio_chip; |
1566 | #endif | 1614 | #endif |
1567 | bool dsp_vad_en; | 1615 | bool dsp_vad_en; |
1616 | struct regmap_irq_chip_data *irq_data; | ||
1568 | }; | 1617 | }; |
1569 | 1618 | ||
1570 | #endif /* __RT5677_H__ */ | 1619 | #endif /* __RT5677_H__ */ |