Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 42 additions & 17 deletions sound/soc/codecs/tas2764.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ struct tas2764_priv {
struct regmap *regmap;
struct device *dev;
int irq;
/* Set while the component holds the fault IRQ */
bool irq_requested;
enum tas2764_devid devid;

int v_sense_slot;
Expand Down Expand Up @@ -937,39 +939,31 @@ static int tas2764_codec_probe(struct snd_soc_component *component)
if (tas2764->irq) {
ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK0, 0x00);
if (ret < 0)
return ret;
goto err_sdz;

ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK1, 0xff);
if (ret < 0)
return ret;
goto err_sdz;

ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK2, 0xff);
if (ret < 0)
return ret;
goto err_sdz;

ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK3, 0xff);
if (ret < 0)
return ret;
goto err_sdz;

ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK4, 0xff);
if (ret < 0)
return ret;

ret = devm_request_threaded_irq(tas2764->dev, tas2764->irq, NULL, tas2764_irq,
IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,
"tas2764", tas2764);
if (ret && tas2764->sdz_group)
return dev_err_probe(tas2764->dev, ret, "SDZ group needs its fault IRQ\n");
if (ret)
dev_warn(tas2764->dev, "failed to request IRQ: %d\n", ret);
goto err_sdz;
}

if (tas2764->i_sense_slot != -1 && tas2764->v_sense_slot != -1) {
ret = tas2764_set_ivsense_transmit(tas2764, tas2764->i_sense_slot,
tas2764->v_sense_slot);

if (ret < 0)
return ret;
goto err_sdz;
}

switch (tas2764->devid) {
Expand All @@ -978,35 +972,66 @@ static int tas2764_codec_probe(struct snd_soc_component *component)
TAS2764_PWR_CTRL_BOP_SRC,
TAS2764_PWR_CTRL_BOP_SRC);
if (ret < 0)
return ret;
goto err_sdz;

for (i = 0; i < ARRAY_SIZE(sn012776_bop_presets); i++) {
ret = snd_soc_component_write(component,
TAS2764_BOP_CFG0 + i,
sn012776_bop_presets[i]);

if (ret < 0)
return ret;
goto err_sdz;
}

/* Apply all enabled Apple quirks */
ret = tas2764_apply_init_quirks(tas2764);

if (ret < 0)
return ret;
goto err_sdz;

break;
default:
break;
}

/*
* Last, so that no failure leaves the handler behind: the IRQ belongs to the I2C
* device, which outlives the component, and the remove frees it.
*/
if (tas2764->irq) {
ret = devm_request_threaded_irq(tas2764->dev, tas2764->irq, NULL, tas2764_irq,
IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,
"tas2764", tas2764);
if (ret && tas2764->sdz_group) {
dev_err_probe(tas2764->dev, ret, "SDZ group needs its fault IRQ\n");
goto err_sdz;
}
if (ret)
dev_warn(tas2764->dev, "failed to request IRQ: %d\n", ret);
else
tas2764->irq_requested = true;
}

return 0;

err_sdz:
/* Undo the power-up: ASoC doesn't call the remove after a failed probe */
if (tas2764->sdz_gpio)
gpiod_set_value_cansleep(tas2764->sdz_gpio, 0);
if (!tas2764_group_failed(tas2764))
regulator_disable(tas2764->sdz_reg);
return ret;
}

static void tas2764_codec_remove(struct snd_soc_component *component)
{
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);

if (tas2764->irq_requested) {
devm_free_irq(tas2764->dev, tas2764->irq, tas2764);
tas2764->irq_requested = false;
}

/* A failed group's supply was forced off: there is no enable left to balance. */
if (tas2764_group_failed(tas2764))
return;
Expand Down