mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 08:14:15 +08:00
ASoC: cs35l45: IRQ support
Adds IRQ handlers Signed-off-by: Vlad Karpovich <vkarpovi@opensource.cirrus.com> Link: https://lore.kernel.org/r/167933510218.26.11092784685990338045@mailman-core.alsa-project.org Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
c6cec088ab
commit
6085f9e6dc
@ -32,6 +32,7 @@ static int cs35l45_i2c_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
cs35l45->dev = dev;
|
||||
cs35l45->irq = client->irq;
|
||||
|
||||
return cs35l45_probe(cs35l45);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ static int cs35l45_spi_probe(struct spi_device *spi)
|
||||
}
|
||||
|
||||
cs35l45->dev = dev;
|
||||
cs35l45->irq = spi->irq;
|
||||
|
||||
return cs35l45_probe(cs35l45);
|
||||
}
|
||||
|
@ -64,6 +64,25 @@ static const struct reg_default cs35l45_defaults[] = {
|
||||
{ CS35L45_ASPTX4_INPUT, 0x00000028 },
|
||||
{ CS35L45_ASPTX5_INPUT, 0x00000048 },
|
||||
{ CS35L45_AMP_PCM_CONTROL, 0x00100000 },
|
||||
{ CS35L45_IRQ1_CFG, 0x00000000 },
|
||||
{ CS35L45_IRQ1_MASK_1, 0xBFEFFFBF },
|
||||
{ CS35L45_IRQ1_MASK_2, 0xFFFFFFFF },
|
||||
{ CS35L45_IRQ1_MASK_3, 0xFFFF87FF },
|
||||
{ CS35L45_IRQ1_MASK_4, 0xF8FFFFFF },
|
||||
{ CS35L45_IRQ1_MASK_5, 0x0EF80000 },
|
||||
{ CS35L45_IRQ1_MASK_6, 0x00000000 },
|
||||
{ CS35L45_IRQ1_MASK_7, 0xFFFFFF78 },
|
||||
{ CS35L45_IRQ1_MASK_8, 0x00003FFF },
|
||||
{ CS35L45_IRQ1_MASK_9, 0x00000000 },
|
||||
{ CS35L45_IRQ1_MASK_10, 0x00000000 },
|
||||
{ CS35L45_IRQ1_MASK_11, 0x00000000 },
|
||||
{ CS35L45_IRQ1_MASK_12, 0x00000000 },
|
||||
{ CS35L45_IRQ1_MASK_13, 0x00000000 },
|
||||
{ CS35L45_IRQ1_MASK_14, 0x00000001 },
|
||||
{ CS35L45_IRQ1_MASK_15, 0x00000000 },
|
||||
{ CS35L45_IRQ1_MASK_16, 0x00000000 },
|
||||
{ CS35L45_IRQ1_MASK_17, 0x00000000 },
|
||||
{ CS35L45_IRQ1_MASK_18, 0x3FE5D0FF },
|
||||
{ CS35L45_GPIO1_CTRL1, 0x81000001 },
|
||||
{ CS35L45_GPIO2_CTRL1, 0x81000001 },
|
||||
{ CS35L45_GPIO3_CTRL1, 0x81000001 },
|
||||
@ -100,7 +119,11 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg)
|
||||
case CS35L45_ASPTX5_INPUT:
|
||||
case CS35L45_AMP_PCM_CONTROL:
|
||||
case CS35L45_AMP_PCM_HPF_TST:
|
||||
case CS35L45_IRQ1_EINT_4:
|
||||
case CS35L45_IRQ1_CFG:
|
||||
case CS35L45_IRQ1_STATUS:
|
||||
case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18:
|
||||
case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18:
|
||||
case CS35L45_IRQ1_MASK_1 ... CS35L45_IRQ1_MASK_18:
|
||||
case CS35L45_GPIO_STATUS1:
|
||||
case CS35L45_GPIO1_CTRL1:
|
||||
case CS35L45_GPIO2_CTRL1:
|
||||
@ -119,7 +142,9 @@ static bool cs35l45_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case CS35L45_GLOBAL_ENABLES:
|
||||
case CS35L45_ERROR_RELEASE:
|
||||
case CS35L45_AMP_PCM_HPF_TST: /* not cachable */
|
||||
case CS35L45_IRQ1_EINT_4:
|
||||
case CS35L45_IRQ1_STATUS:
|
||||
case CS35L45_IRQ1_EINT_1 ... CS35L45_IRQ1_EINT_18:
|
||||
case CS35L45_IRQ1_STS_1 ... CS35L45_IRQ1_STS_18:
|
||||
case CS35L45_GPIO_STATUS1:
|
||||
return true;
|
||||
default:
|
||||
|
@ -586,10 +586,13 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45)
|
||||
val << CS35L45_GPIO_CTRL_SHIFT);
|
||||
|
||||
ret = of_property_read_u32(child, "gpio-invert", &val);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
regmap_update_bits(cs35l45->regmap, pad_regs[i],
|
||||
CS35L45_GPIO_INVERT_MASK,
|
||||
val << CS35L45_GPIO_INVERT_SHIFT);
|
||||
if (i == 1)
|
||||
cs35l45->irq_invert = val;
|
||||
}
|
||||
|
||||
of_node_put(child);
|
||||
}
|
||||
@ -604,6 +607,78 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t cs35l45_pll_unlock(int irq, void *data)
|
||||
{
|
||||
struct cs35l45_private *cs35l45 = data;
|
||||
|
||||
dev_dbg(cs35l45->dev, "PLL unlock detected!");
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t cs35l45_pll_lock(int irq, void *data)
|
||||
{
|
||||
struct cs35l45_private *cs35l45 = data;
|
||||
|
||||
dev_dbg(cs35l45->dev, "PLL lock detected!");
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t cs35l45_spk_safe_err(int irq, void *data);
|
||||
|
||||
static const struct cs35l45_irq cs35l45_irqs[] = {
|
||||
CS35L45_IRQ(AMP_SHORT_ERR, "Amplifier short error", cs35l45_spk_safe_err),
|
||||
CS35L45_IRQ(UVLO_VDDBATT_ERR, "VDDBATT undervoltage error", cs35l45_spk_safe_err),
|
||||
CS35L45_IRQ(BST_SHORT_ERR, "Boost inductor error", cs35l45_spk_safe_err),
|
||||
CS35L45_IRQ(BST_UVP_ERR, "Boost undervoltage error", cs35l45_spk_safe_err),
|
||||
CS35L45_IRQ(TEMP_ERR, "Overtemperature error", cs35l45_spk_safe_err),
|
||||
CS35L45_IRQ(AMP_CAL_ERR, "Amplifier calibration error", cs35l45_spk_safe_err),
|
||||
CS35L45_IRQ(UVLO_VDDLV_ERR, "LV threshold detector error", cs35l45_spk_safe_err),
|
||||
CS35L45_IRQ(GLOBAL_ERROR, "Global error", cs35l45_spk_safe_err),
|
||||
CS35L45_IRQ(DSP_WDT_EXPIRE, "DSP Watchdog Timer", cs35l45_spk_safe_err),
|
||||
CS35L45_IRQ(PLL_UNLOCK_FLAG_RISE, "PLL unlock", cs35l45_pll_unlock),
|
||||
CS35L45_IRQ(PLL_LOCK_FLAG, "PLL lock", cs35l45_pll_lock),
|
||||
};
|
||||
|
||||
static irqreturn_t cs35l45_spk_safe_err(int irq, void *data)
|
||||
{
|
||||
struct cs35l45_private *cs35l45 = data;
|
||||
int i;
|
||||
|
||||
i = irq - regmap_irq_get_virq(cs35l45->irq_data, 0);
|
||||
|
||||
dev_err(cs35l45->dev, "%s condition detected!\n", cs35l45_irqs[i].name);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct regmap_irq cs35l45_reg_irqs[] = {
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_1, AMP_SHORT_ERR),
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_1, UVLO_VDDBATT_ERR),
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_1, BST_SHORT_ERR),
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_1, BST_UVP_ERR),
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_1, TEMP_ERR),
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_3, AMP_CAL_ERR),
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_18, UVLO_VDDLV_ERR),
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_18, GLOBAL_ERROR),
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_WDT_EXPIRE),
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_UNLOCK_FLAG_RISE),
|
||||
CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_LOCK_FLAG),
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip cs35l45_regmap_irq_chip = {
|
||||
.name = "cs35l45 IRQ1 Controller",
|
||||
.main_status = CS35L45_IRQ1_STATUS,
|
||||
.status_base = CS35L45_IRQ1_EINT_1,
|
||||
.mask_base = CS35L45_IRQ1_MASK_1,
|
||||
.ack_base = CS35L45_IRQ1_EINT_1,
|
||||
.num_regs = 18,
|
||||
.irqs = cs35l45_reg_irqs,
|
||||
.num_irqs = ARRAY_SIZE(cs35l45_reg_irqs),
|
||||
.runtime_pm = true,
|
||||
};
|
||||
|
||||
static int cs35l45_initialize(struct cs35l45_private *cs35l45)
|
||||
{
|
||||
struct device *dev = cs35l45->dev;
|
||||
@ -660,7 +735,8 @@ static int cs35l45_initialize(struct cs35l45_private *cs35l45)
|
||||
int cs35l45_probe(struct cs35l45_private *cs35l45)
|
||||
{
|
||||
struct device *dev = cs35l45->dev;
|
||||
int ret;
|
||||
unsigned long irq_pol = IRQF_ONESHOT | IRQF_SHARED;
|
||||
int ret, i, irq;
|
||||
|
||||
cs35l45->vdd_batt = devm_regulator_get(dev, "vdd-batt");
|
||||
if (IS_ERR(cs35l45->vdd_batt))
|
||||
@ -705,6 +781,37 @@ int cs35l45_probe(struct cs35l45_private *cs35l45)
|
||||
if (ret < 0)
|
||||
goto err_reset;
|
||||
|
||||
if (cs35l45->irq) {
|
||||
if (cs35l45->irq_invert)
|
||||
irq_pol |= IRQF_TRIGGER_HIGH;
|
||||
else
|
||||
irq_pol |= IRQF_TRIGGER_LOW;
|
||||
|
||||
ret = devm_regmap_add_irq_chip(dev, cs35l45->regmap, cs35l45->irq, irq_pol, 0,
|
||||
&cs35l45_regmap_irq_chip, &cs35l45->irq_data);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register IRQ chip: %d\n", ret);
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cs35l45_irqs); i++) {
|
||||
irq = regmap_irq_get_virq(cs35l45->irq_data, cs35l45_irqs[i].irq);
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "Failed to get %s\n", cs35l45_irqs[i].name);
|
||||
ret = irq;
|
||||
goto err_reset;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL, cs35l45_irqs[i].handler,
|
||||
irq_pol, cs35l45_irqs[i].name, cs35l45);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to request IRQ %s: %d\n",
|
||||
cs35l45_irqs[i].name, ret);
|
||||
goto err_reset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_component(dev, &cs35l45_component,
|
||||
cs35l45_dai,
|
||||
ARRAY_SIZE(cs35l45_dai));
|
||||
|
@ -51,7 +51,42 @@
|
||||
#define CS35L45_LDPM_CONFIG 0x00006404
|
||||
#define CS35L45_AMP_PCM_CONTROL 0x00007000
|
||||
#define CS35L45_AMP_PCM_HPF_TST 0x00007004
|
||||
#define CS35L45_IRQ1_CFG 0x0000E000
|
||||
#define CS35L45_IRQ1_STATUS 0x0000E004
|
||||
#define CS35L45_IRQ1_EINT_1 0x0000E010
|
||||
#define CS35L45_IRQ1_EINT_2 0x0000E014
|
||||
#define CS35L45_IRQ1_EINT_3 0x0000E018
|
||||
#define CS35L45_IRQ1_EINT_4 0x0000E01C
|
||||
#define CS35L45_IRQ1_EINT_5 0x0000E020
|
||||
#define CS35L45_IRQ1_EINT_7 0x0000E028
|
||||
#define CS35L45_IRQ1_EINT_8 0x0000E02C
|
||||
#define CS35L45_IRQ1_EINT_18 0x0000E054
|
||||
#define CS35L45_IRQ1_STS_1 0x0000E090
|
||||
#define CS35L45_IRQ1_STS_2 0x0000E094
|
||||
#define CS35L45_IRQ1_STS_3 0x0000E098
|
||||
#define CS35L45_IRQ1_STS_4 0x0000E09C
|
||||
#define CS35L45_IRQ1_STS_5 0x0000E0A0
|
||||
#define CS35L45_IRQ1_STS_7 0x0000E0A8
|
||||
#define CS35L45_IRQ1_STS_8 0x0000E0AC
|
||||
#define CS35L45_IRQ1_STS_18 0x0000E0D4
|
||||
#define CS35L45_IRQ1_MASK_1 0x0000E110
|
||||
#define CS35L45_IRQ1_MASK_2 0x0000E114
|
||||
#define CS35L45_IRQ1_MASK_3 0x0000E118
|
||||
#define CS35L45_IRQ1_MASK_4 0x0000E11C
|
||||
#define CS35L45_IRQ1_MASK_5 0x0000E120
|
||||
#define CS35L45_IRQ1_MASK_6 0x0000E124
|
||||
#define CS35L45_IRQ1_MASK_7 0x0000E128
|
||||
#define CS35L45_IRQ1_MASK_8 0x0000E12C
|
||||
#define CS35L45_IRQ1_MASK_9 0x0000E130
|
||||
#define CS35L45_IRQ1_MASK_10 0x0000E134
|
||||
#define CS35L45_IRQ1_MASK_11 0x0000E138
|
||||
#define CS35L45_IRQ1_MASK_12 0x0000E13C
|
||||
#define CS35L45_IRQ1_MASK_13 0x0000E140
|
||||
#define CS35L45_IRQ1_MASK_14 0x0000E144
|
||||
#define CS35L45_IRQ1_MASK_15 0x0000E148
|
||||
#define CS35L45_IRQ1_MASK_16 0x0000E14C
|
||||
#define CS35L45_IRQ1_MASK_17 0x0000E150
|
||||
#define CS35L45_IRQ1_MASK_18 0x0000E154
|
||||
#define CS35L45_GPIO_STATUS1 0x0000F000
|
||||
#define CS35L45_GPIO1_CTRL1 0x0000F008
|
||||
#define CS35L45_GPIO2_CTRL1 0x0000F00C
|
||||
@ -188,6 +223,38 @@
|
||||
#define CS35L45_GPIO_INVERT_SHIFT 19
|
||||
#define CS35L45_GPIO_INVERT_MASK BIT(19)
|
||||
|
||||
/* CS35L45_IRQ1_EINT_1 */
|
||||
#define CS35L45_BST_UVP_ERR_SHIFT 7
|
||||
#define CS35L45_BST_UVP_ERR_MASK BIT(7)
|
||||
#define CS35L45_BST_SHORT_ERR_SHIFT 8
|
||||
#define CS35L45_BST_SHORT_ERR_MASK BIT(8)
|
||||
#define CS35L45_TEMP_ERR_SHIFT 17
|
||||
#define CS35L45_TEMP_ERR_MASK BIT(17)
|
||||
#define CS35L45_MSM_GLOBAL_EN_ASSERT_SHIFT 22
|
||||
#define CS35L45_MSM_GLOBAL_EN_ASSERT_MASK BIT(22)
|
||||
#define CS35L45_UVLO_VDDBATT_ERR_SHIFT 29
|
||||
#define CS35L45_UVLO_VDDBATT_ERR_MASK BIT(29)
|
||||
#define CS35L45_AMP_SHORT_ERR_SHIFT 31
|
||||
#define CS35L45_AMP_SHORT_ERR_MASK BIT(31)
|
||||
|
||||
/* CS35L45_IRQ1_EINT_2 */
|
||||
#define CS35L45_DSP_WDT_EXPIRE_SHIFT 4
|
||||
#define CS35L45_DSP_WDT_EXPIRE_MASK BIT(4)
|
||||
|
||||
/* CS35L45_IRQ1_EINT_3 */
|
||||
#define CS35L45_PLL_LOCK_FLAG_SHIFT 1
|
||||
#define CS35L45_PLL_LOCK_FLAG_MASK BIT(1)
|
||||
#define CS35L45_PLL_UNLOCK_FLAG_RISE_SHIFT 4
|
||||
#define CS35L45_PLL_UNLOCK_FLAG_RISE_MASK BIT(4)
|
||||
#define CS35L45_AMP_CAL_ERR_SHIFT 25
|
||||
#define CS35L45_AMP_CAL_ERR_MASK BIT(25)
|
||||
|
||||
/* CS35L45_IRQ1_EINT_18 */
|
||||
#define CS35L45_GLOBAL_ERROR_SHIFT 15
|
||||
#define CS35L45_GLOBAL_ERROR_MASK BIT(15)
|
||||
#define CS35L45_UVLO_VDDLV_ERR_SHIFT 16
|
||||
#define CS35L45_UVLO_VDDLV_ERR_MASK BIT(16)
|
||||
|
||||
/* Mixer sources */
|
||||
#define CS35L45_PCM_SRC_MASK 0x7F
|
||||
#define CS35L45_PCM_SRC_ZERO 0x00
|
||||
@ -217,6 +284,43 @@
|
||||
SNDRV_PCM_RATE_88200 | \
|
||||
SNDRV_PCM_RATE_96000)
|
||||
|
||||
/*
|
||||
* IRQs
|
||||
*/
|
||||
#define CS35L45_IRQ(_irq, _name, _hand) \
|
||||
{ \
|
||||
.irq = CS35L45_ ## _irq ## _IRQ,\
|
||||
.name = _name, \
|
||||
.handler = _hand, \
|
||||
}
|
||||
|
||||
struct cs35l45_irq {
|
||||
int irq;
|
||||
const char *name;
|
||||
irqreturn_t (*handler)(int irq, void *data);
|
||||
};
|
||||
|
||||
#define CS35L45_REG_IRQ(_reg, _irq) \
|
||||
[CS35L45_ ## _irq ## _IRQ] = { \
|
||||
.reg_offset = (CS35L45_ ## _reg) - CS35L45_IRQ1_EINT_1, \
|
||||
.mask = CS35L45_ ## _irq ## _MASK \
|
||||
}
|
||||
|
||||
enum cs35l45_irq_list {
|
||||
CS35L45_AMP_SHORT_ERR_IRQ,
|
||||
CS35L45_UVLO_VDDBATT_ERR_IRQ,
|
||||
CS35L45_BST_SHORT_ERR_IRQ,
|
||||
CS35L45_BST_UVP_ERR_IRQ,
|
||||
CS35L45_TEMP_ERR_IRQ,
|
||||
CS35L45_AMP_CAL_ERR_IRQ,
|
||||
CS35L45_UVLO_VDDLV_ERR_IRQ,
|
||||
CS35L45_GLOBAL_ERROR_IRQ,
|
||||
CS35L45_DSP_WDT_EXPIRE_IRQ,
|
||||
CS35L45_PLL_UNLOCK_FLAG_RISE_IRQ,
|
||||
CS35L45_PLL_LOCK_FLAG_IRQ,
|
||||
CS35L45_NUM_IRQ
|
||||
};
|
||||
|
||||
struct cs35l45_private {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
@ -227,6 +331,9 @@ struct cs35l45_private {
|
||||
bool sysclk_set;
|
||||
u8 slot_width;
|
||||
u8 slot_count;
|
||||
int irq_invert;
|
||||
int irq;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
};
|
||||
|
||||
extern const struct dev_pm_ops cs35l45_pm_ops;
|
||||
|
Loading…
Reference in New Issue
Block a user