Skip to content

Commit dae191f

Browse files
povikbroonie
authored andcommitted
ASoC: tas2764: Add IRQ handling
Add an IRQ handler which logs detected faults (but doesn't do anything else). Signed-off-by: Martin Povišer <povik+lin@cutebit.org> Link: https://lore.kernel.org/r/20220825140241.53963-5-povik+lin@cutebit.org Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent f5ad67f commit dae191f

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

sound/soc/codecs/tas2764.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct tas2764_priv {
3131
struct gpio_desc *sdz_gpio;
3232
struct regmap *regmap;
3333
struct device *dev;
34+
int irq;
3435

3536
int v_sense_slot;
3637
int i_sense_slot;
@@ -39,6 +40,57 @@ struct tas2764_priv {
3940
bool unmuted;
4041
};
4142

43+
static const char *tas2764_int_ltch0_msgs[8] = {
44+
"fault: over temperature", /* INT_LTCH0 & BIT(0) */
45+
"fault: over current",
46+
"fault: bad TDM clock",
47+
"limiter active",
48+
"fault: PVDD below limiter inflection point",
49+
"fault: limiter max attenuation",
50+
"fault: BOP infinite hold",
51+
"fault: BOP mute", /* INT_LTCH0 & BIT(7) */
52+
};
53+
54+
static const unsigned int tas2764_int_readout_regs[6] = {
55+
TAS2764_INT_LTCH0,
56+
TAS2764_INT_LTCH1,
57+
TAS2764_INT_LTCH1_0,
58+
TAS2764_INT_LTCH2,
59+
TAS2764_INT_LTCH3,
60+
TAS2764_INT_LTCH4,
61+
};
62+
63+
static irqreturn_t tas2764_irq(int irq, void *data)
64+
{
65+
struct tas2764_priv *tas2764 = data;
66+
u8 latched[6] = {0, 0, 0, 0, 0, 0};
67+
int ret = IRQ_NONE;
68+
int i;
69+
70+
for (i = 0; i < ARRAY_SIZE(latched); i++)
71+
latched[i] = snd_soc_component_read(tas2764->component,
72+
tas2764_int_readout_regs[i]);
73+
74+
for (i = 0; i < 8; i++) {
75+
if (latched[0] & BIT(i)) {
76+
dev_crit_ratelimited(tas2764->dev, "%s\n",
77+
tas2764_int_ltch0_msgs[i]);
78+
ret = IRQ_HANDLED;
79+
}
80+
}
81+
82+
if (latched[0]) {
83+
dev_err_ratelimited(tas2764->dev, "other context to the fault: %02x,%02x,%02x,%02x,%02x",
84+
latched[1], latched[2], latched[3], latched[4], latched[5]);
85+
snd_soc_component_update_bits(tas2764->component,
86+
TAS2764_INT_CLK_CFG,
87+
TAS2764_INT_CLK_CFG_IRQZ_CLR,
88+
TAS2764_INT_CLK_CFG_IRQZ_CLR);
89+
}
90+
91+
return ret;
92+
}
93+
4294
static void tas2764_reset(struct tas2764_priv *tas2764)
4395
{
4496
if (tas2764->reset_gpio) {
@@ -497,6 +549,34 @@ static int tas2764_codec_probe(struct snd_soc_component *component)
497549

498550
tas2764_reset(tas2764);
499551

552+
if (tas2764->irq) {
553+
ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK0, 0xff);
554+
if (ret < 0)
555+
return ret;
556+
557+
ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK1, 0xff);
558+
if (ret < 0)
559+
return ret;
560+
561+
ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK2, 0xff);
562+
if (ret < 0)
563+
return ret;
564+
565+
ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK3, 0xff);
566+
if (ret < 0)
567+
return ret;
568+
569+
ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK4, 0xff);
570+
if (ret < 0)
571+
return ret;
572+
573+
ret = devm_request_threaded_irq(tas2764->dev, tas2764->irq, NULL, tas2764_irq,
574+
IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,
575+
"tas2764", tas2764);
576+
if (ret)
577+
dev_warn(tas2764->dev, "failed to request IRQ: %d\n", ret);
578+
}
579+
500580
ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG5,
501581
TAS2764_TDM_CFG5_VSNS_ENABLE, 0);
502582
if (ret < 0)
@@ -559,9 +639,21 @@ static const struct regmap_range_cfg tas2764_regmap_ranges[] = {
559639
},
560640
};
561641

642+
static bool tas2764_volatile_register(struct device *dev, unsigned int reg)
643+
{
644+
switch (reg) {
645+
case TAS2764_INT_LTCH0 ... TAS2764_INT_LTCH4:
646+
case TAS2764_INT_CLK_CFG:
647+
return true;
648+
default:
649+
return false;
650+
}
651+
}
652+
562653
static const struct regmap_config tas2764_i2c_regmap = {
563654
.reg_bits = 8,
564655
.val_bits = 8,
656+
.volatile_reg = tas2764_volatile_register,
565657
.reg_defaults = tas2764_reg_defaults,
566658
.num_reg_defaults = ARRAY_SIZE(tas2764_reg_defaults),
567659
.cache_type = REGCACHE_RBTREE,
@@ -615,6 +707,7 @@ static int tas2764_i2c_probe(struct i2c_client *client)
615707
return -ENOMEM;
616708

617709
tas2764->dev = &client->dev;
710+
tas2764->irq = client->irq;
618711
i2c_set_clientdata(client, tas2764);
619712
dev_set_drvdata(&client->dev, tas2764);
620713

sound/soc/codecs/tas2764.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,23 @@
8787
#define TAS2764_TDM_CFG6_ISNS_ENABLE BIT(6)
8888
#define TAS2764_TDM_CFG6_50_MASK GENMASK(5, 0)
8989

90+
/* Interrupt Masks */
91+
#define TAS2764_INT_MASK0 TAS2764_REG(0x0, 0x3b)
92+
#define TAS2764_INT_MASK1 TAS2764_REG(0x0, 0x3c)
93+
#define TAS2764_INT_MASK2 TAS2764_REG(0x0, 0x40)
94+
#define TAS2764_INT_MASK3 TAS2764_REG(0x0, 0x41)
95+
#define TAS2764_INT_MASK4 TAS2764_REG(0x0, 0x3d)
96+
97+
/* Latched Fault Registers */
98+
#define TAS2764_INT_LTCH0 TAS2764_REG(0x0, 0x49)
99+
#define TAS2764_INT_LTCH1 TAS2764_REG(0x0, 0x4a)
100+
#define TAS2764_INT_LTCH1_0 TAS2764_REG(0x0, 0x4b)
101+
#define TAS2764_INT_LTCH2 TAS2764_REG(0x0, 0x4f)
102+
#define TAS2764_INT_LTCH3 TAS2764_REG(0x0, 0x50)
103+
#define TAS2764_INT_LTCH4 TAS2764_REG(0x0, 0x51)
104+
105+
/* Clock/IRQ Settings */
106+
#define TAS2764_INT_CLK_CFG TAS2764_REG(0x0, 0x5c)
107+
#define TAS2764_INT_CLK_CFG_IRQZ_CLR BIT(2)
108+
90109
#endif /* __TAS2764__ */

0 commit comments

Comments
 (0)