ASoC: rt5677: add GPIO IRQ support
This allows to enable Mic Jack detection feature Signed-off-by: Oder Chiou <oder_chiou@realtek.com> Modified-by: Anatol Pomozov <anatol.pomozov@gmail.com> Signed-off-by: Anatol Pomozov <anatol.pomozov@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
ac884fc47b
commit
5e3363ad1b
4 changed files with 200 additions and 0 deletions
|
@ -33,6 +33,15 @@ Optional properties:
|
|||
1 - pull down
|
||||
2 - pull up
|
||||
|
||||
- realtek,jd1-gpio
|
||||
Configures GPIO Mic Jack detection 1.
|
||||
Select 0 ~ 3 as OFF, GPIO1, GPIO2 and GPIO3 respectively.
|
||||
|
||||
- realtek,jd2-gpio
|
||||
- realtek,jd3-gpio
|
||||
Configures GPIO Mic Jack detection 2 and 3.
|
||||
Select 0 ~ 3 as OFF, GPIO4, GPIO5 and GPIO6 respectively.
|
||||
|
||||
Pins on the device (for linking into audio routes):
|
||||
|
||||
* IN1P
|
||||
|
@ -63,4 +72,5 @@ rt5677 {
|
|||
<&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
|
||||
realtek,in1-differential = "true";
|
||||
realtek,gpio-config = /bits/ 8 <0 0 0 0 0 2>; /* pull up GPIO6 */
|
||||
realtek,jd2-gpio = <3>; /* Enables Jack detection for GPIO6 */
|
||||
};
|
||||
|
|
|
@ -30,6 +30,13 @@ struct rt5677_platform_data {
|
|||
|
||||
/* configures GPIO, 0 - floating, 1 - pulldown, 2 - pullup */
|
||||
u8 gpio_config[6];
|
||||
|
||||
/* jd1 can select 0 ~ 3 as OFF, GPIO1, GPIO2 and GPIO3 respectively */
|
||||
unsigned int jd1_gpio;
|
||||
/* jd2 and jd3 can select 0 ~ 3 as
|
||||
OFF, GPIO4, GPIO5 and GPIO6 respectively */
|
||||
unsigned int jd2_gpio;
|
||||
unsigned int jd3_gpio;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3614,6 +3614,46 @@ static void rt5677_gpio_config(struct rt5677_priv *rt5677, unsigned offset,
|
|||
}
|
||||
}
|
||||
|
||||
static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct rt5677_priv *rt5677 = gpio_to_rt5677(chip);
|
||||
struct regmap_irq_chip_data *data = rt5677->irq_data;
|
||||
int irq;
|
||||
|
||||
if (offset >= RT5677_GPIO1 && offset <= RT5677_GPIO3) {
|
||||
if ((rt5677->pdata.jd1_gpio == 1 && offset == RT5677_GPIO1) ||
|
||||
(rt5677->pdata.jd1_gpio == 2 &&
|
||||
offset == RT5677_GPIO2) ||
|
||||
(rt5677->pdata.jd1_gpio == 3 &&
|
||||
offset == RT5677_GPIO3)) {
|
||||
irq = RT5677_IRQ_JD1;
|
||||
} else {
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset >= RT5677_GPIO4 && offset <= RT5677_GPIO6) {
|
||||
if ((rt5677->pdata.jd2_gpio == 1 && offset == RT5677_GPIO4) ||
|
||||
(rt5677->pdata.jd2_gpio == 2 &&
|
||||
offset == RT5677_GPIO5) ||
|
||||
(rt5677->pdata.jd2_gpio == 3 &&
|
||||
offset == RT5677_GPIO6)) {
|
||||
irq = RT5677_IRQ_JD2;
|
||||
} else if ((rt5677->pdata.jd3_gpio == 1 &&
|
||||
offset == RT5677_GPIO4) ||
|
||||
(rt5677->pdata.jd3_gpio == 2 &&
|
||||
offset == RT5677_GPIO5) ||
|
||||
(rt5677->pdata.jd3_gpio == 3 &&
|
||||
offset == RT5677_GPIO6)) {
|
||||
irq = RT5677_IRQ_JD3;
|
||||
} else {
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
|
||||
return regmap_irq_get_virq(data, irq);
|
||||
}
|
||||
|
||||
static struct gpio_chip rt5677_template_chip = {
|
||||
.label = "rt5677",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -3621,6 +3661,7 @@ static struct gpio_chip rt5677_template_chip = {
|
|||
.set = rt5677_gpio_set,
|
||||
.direction_input = rt5677_gpio_direction_in,
|
||||
.get = rt5677_gpio_get,
|
||||
.to_irq = rt5677_to_irq,
|
||||
.can_sleep = 1,
|
||||
};
|
||||
|
||||
|
@ -3685,6 +3726,31 @@ static int rt5677_probe(struct snd_soc_codec *codec)
|
|||
for (i = 0; i < RT5677_GPIO_NUM; i++)
|
||||
rt5677_gpio_config(rt5677, i, rt5677->pdata.gpio_config[i]);
|
||||
|
||||
if (rt5677->irq_data) {
|
||||
regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL1, 0x8000,
|
||||
0x8000);
|
||||
regmap_update_bits(rt5677->regmap, RT5677_DIG_MISC, 0x0018,
|
||||
0x0008);
|
||||
|
||||
if (rt5677->pdata.jd1_gpio)
|
||||
regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1,
|
||||
RT5677_SEL_GPIO_JD1_MASK,
|
||||
rt5677->pdata.jd1_gpio <<
|
||||
RT5677_SEL_GPIO_JD1_SFT);
|
||||
|
||||
if (rt5677->pdata.jd2_gpio)
|
||||
regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1,
|
||||
RT5677_SEL_GPIO_JD2_MASK,
|
||||
rt5677->pdata.jd2_gpio <<
|
||||
RT5677_SEL_GPIO_JD2_SFT);
|
||||
|
||||
if (rt5677->pdata.jd3_gpio)
|
||||
regmap_update_bits(rt5677->regmap, RT5677_JD_CTRL1,
|
||||
RT5677_SEL_GPIO_JD3_MASK,
|
||||
rt5677->pdata.jd3_gpio <<
|
||||
RT5677_SEL_GPIO_JD3_SFT);
|
||||
}
|
||||
|
||||
mutex_init(&rt5677->dsp_cmd_lock);
|
||||
|
||||
return 0;
|
||||
|
@ -3915,9 +3981,74 @@ static int rt5677_parse_dt(struct rt5677_priv *rt5677, struct device_node *np)
|
|||
of_property_read_u8_array(np, "realtek,gpio-config",
|
||||
rt5677->pdata.gpio_config, RT5677_GPIO_NUM);
|
||||
|
||||
of_property_read_u32(np, "realtek,jd1-gpio", &rt5677->pdata.jd1_gpio);
|
||||
of_property_read_u32(np, "realtek,jd2-gpio", &rt5677->pdata.jd2_gpio);
|
||||
of_property_read_u32(np, "realtek,jd3-gpio", &rt5677->pdata.jd3_gpio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct regmap_irq rt5677_irqs[] = {
|
||||
[RT5677_IRQ_JD1] = {
|
||||
.reg_offset = 0,
|
||||
.mask = RT5677_EN_IRQ_GPIO_JD1,
|
||||
},
|
||||
[RT5677_IRQ_JD2] = {
|
||||
.reg_offset = 0,
|
||||
.mask = RT5677_EN_IRQ_GPIO_JD2,
|
||||
},
|
||||
[RT5677_IRQ_JD3] = {
|
||||
.reg_offset = 0,
|
||||
.mask = RT5677_EN_IRQ_GPIO_JD3,
|
||||
},
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip rt5677_irq_chip = {
|
||||
.name = "rt5677",
|
||||
.irqs = rt5677_irqs,
|
||||
.num_irqs = ARRAY_SIZE(rt5677_irqs),
|
||||
|
||||
.num_regs = 1,
|
||||
.status_base = RT5677_IRQ_CTRL1,
|
||||
.mask_base = RT5677_IRQ_CTRL1,
|
||||
.mask_invert = 1,
|
||||
};
|
||||
|
||||
int rt5677_irq_init(struct i2c_client *i2c)
|
||||
{
|
||||
int ret;
|
||||
struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c);
|
||||
|
||||
if (!rt5677->pdata.jd1_gpio &&
|
||||
!rt5677->pdata.jd2_gpio &&
|
||||
!rt5677->pdata.jd3_gpio)
|
||||
return 0;
|
||||
|
||||
if (!i2c->irq) {
|
||||
dev_err(&i2c->dev, "No interrupt specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_add_irq_chip(rt5677->regmap, i2c->irq,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0,
|
||||
&rt5677_irq_chip, &rt5677->irq_data);
|
||||
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to register IRQ chip: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rt5677_irq_exit(struct i2c_client *i2c)
|
||||
{
|
||||
struct rt5677_priv *rt5677 = i2c_get_clientdata(i2c);
|
||||
|
||||
if (rt5677->irq_data)
|
||||
regmap_del_irq_chip(i2c->irq, rt5677->irq_data);
|
||||
}
|
||||
|
||||
static int rt5677_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -4015,6 +4146,7 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
|
|||
}
|
||||
|
||||
rt5677_init_gpio(i2c);
|
||||
rt5677_irq_init(i2c);
|
||||
|
||||
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5677,
|
||||
rt5677_dai, ARRAY_SIZE(rt5677_dai));
|
||||
|
@ -4022,6 +4154,8 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
static int rt5677_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
rt5677_irq_exit(i2c);
|
||||
|
||||
snd_soc_unregister_codec(&i2c->dev);
|
||||
rt5677_free_gpio(i2c);
|
||||
|
||||
|
|
|
@ -1368,6 +1368,48 @@
|
|||
#define RT5677_SEL_SRC_IB01 (0x1 << 0)
|
||||
#define RT5677_SEL_SRC_IB01_SFT 0
|
||||
|
||||
/* Jack Detect Control 1 (0xb5) */
|
||||
#define RT5677_SEL_GPIO_JD1_MASK (0x3 << 14)
|
||||
#define RT5677_SEL_GPIO_JD1_SFT 14
|
||||
#define RT5677_SEL_GPIO_JD2_MASK (0x3 << 12)
|
||||
#define RT5677_SEL_GPIO_JD2_SFT 12
|
||||
#define RT5677_SEL_GPIO_JD3_MASK (0x3 << 10)
|
||||
#define RT5677_SEL_GPIO_JD3_SFT 10
|
||||
|
||||
/* IRQ Control 1 (0xbd) */
|
||||
#define RT5677_STA_GPIO_JD1 (0x1 << 15)
|
||||
#define RT5677_STA_GPIO_JD1_SFT 15
|
||||
#define RT5677_EN_IRQ_GPIO_JD1 (0x1 << 14)
|
||||
#define RT5677_EN_IRQ_GPIO_JD1_SFT 14
|
||||
#define RT5677_EN_GPIO_JD1_STICKY (0x1 << 13)
|
||||
#define RT5677_EN_GPIO_JD1_STICKY_SFT 13
|
||||
#define RT5677_INV_GPIO_JD1 (0x1 << 12)
|
||||
#define RT5677_INV_GPIO_JD1_SFT 12
|
||||
#define RT5677_STA_GPIO_JD2 (0x1 << 11)
|
||||
#define RT5677_STA_GPIO_JD2_SFT 11
|
||||
#define RT5677_EN_IRQ_GPIO_JD2 (0x1 << 10)
|
||||
#define RT5677_EN_IRQ_GPIO_JD2_SFT 10
|
||||
#define RT5677_EN_GPIO_JD2_STICKY (0x1 << 9)
|
||||
#define RT5677_EN_GPIO_JD2_STICKY_SFT 9
|
||||
#define RT5677_INV_GPIO_JD2 (0x1 << 8)
|
||||
#define RT5677_INV_GPIO_JD2_SFT 8
|
||||
#define RT5677_STA_MICBIAS1_OVCD (0x1 << 7)
|
||||
#define RT5677_STA_MICBIAS1_OVCD_SFT 7
|
||||
#define RT5677_EN_IRQ_MICBIAS1_OVCD (0x1 << 6)
|
||||
#define RT5677_EN_IRQ_MICBIAS1_OVCD_SFT 6
|
||||
#define RT5677_EN_MICBIAS1_OVCD_STICKY (0x1 << 5)
|
||||
#define RT5677_EN_MICBIAS1_OVCD_STICKY_SFT 5
|
||||
#define RT5677_INV_MICBIAS1_OVCD (0x1 << 4)
|
||||
#define RT5677_INV_MICBIAS1_OVCD_SFT 4
|
||||
#define RT5677_STA_GPIO_JD3 (0x1 << 3)
|
||||
#define RT5677_STA_GPIO_JD3_SFT 3
|
||||
#define RT5677_EN_IRQ_GPIO_JD3 (0x1 << 2)
|
||||
#define RT5677_EN_IRQ_GPIO_JD3_SFT 2
|
||||
#define RT5677_EN_GPIO_JD3_STICKY (0x1 << 1)
|
||||
#define RT5677_EN_GPIO_JD3_STICKY_SFT 1
|
||||
#define RT5677_INV_GPIO_JD3 (0x1 << 0)
|
||||
#define RT5677_INV_GPIO_JD3_SFT 0
|
||||
|
||||
/* GPIO status (0xbf) */
|
||||
#define RT5677_GPIO6_STATUS_MASK (0x1 << 5)
|
||||
#define RT5677_GPIO6_STATUS_SFT 5
|
||||
|
@ -1545,6 +1587,12 @@ enum {
|
|||
RT5677_GPIO_NUM,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT5677_IRQ_JD1,
|
||||
RT5677_IRQ_JD2,
|
||||
RT5677_IRQ_JD3,
|
||||
};
|
||||
|
||||
struct rt5677_priv {
|
||||
struct snd_soc_codec *codec;
|
||||
struct rt5677_platform_data pdata;
|
||||
|
@ -1565,6 +1613,7 @@ struct rt5677_priv {
|
|||
struct gpio_chip gpio_chip;
|
||||
#endif
|
||||
bool dsp_vad_en;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
};
|
||||
|
||||
#endif /* __RT5677_H__ */
|
||||
|
|
Loading…
Reference in a new issue