diff options
Diffstat (limited to 'sound/soc/codecs/cs35l41-lib.c')
-rw-r--r-- | sound/soc/codecs/cs35l41-lib.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c index 491616c7c5c7..451d3be37157 100644 --- a/sound/soc/codecs/cs35l41-lib.c +++ b/sound/soc/codecs/cs35l41-lib.c @@ -1206,6 +1206,63 @@ int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg) } EXPORT_SYMBOL_GPL(cs35l41_gpio_config); +static bool cs35l41_check_cspl_mbox_sts(enum cs35l41_cspl_mbox_cmd cmd, + enum cs35l41_cspl_mbox_status sts) +{ + switch (cmd) { + case CSPL_MBOX_CMD_NONE: + case CSPL_MBOX_CMD_UNKNOWN_CMD: + return true; + case CSPL_MBOX_CMD_PAUSE: + case CSPL_MBOX_CMD_OUT_OF_HIBERNATE: + return (sts == CSPL_MBOX_STS_PAUSED); + case CSPL_MBOX_CMD_RESUME: + return (sts == CSPL_MBOX_STS_RUNNING); + case CSPL_MBOX_CMD_REINIT: + return (sts == CSPL_MBOX_STS_RUNNING); + case CSPL_MBOX_CMD_STOP_PRE_REINIT: + return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT); + default: + return false; + } +} + +int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap, + enum cs35l41_cspl_mbox_cmd cmd) +{ + unsigned int sts = 0, i; + int ret; + + // Set mailbox cmd + ret = regmap_write(regmap, CS35L41_DSP_VIRT1_MBOX_1, cmd); + if (ret < 0) { + if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) + dev_err(dev, "Failed to write MBOX: %d\n", ret); + return ret; + } + + // Read mailbox status and verify it is appropriate for the given cmd + for (i = 0; i < 5; i++) { + usleep_range(1000, 1100); + + ret = regmap_read(regmap, CS35L41_DSP_MBOX_2, &sts); + if (ret < 0) { + dev_err(dev, "Failed to read MBOX STS: %d\n", ret); + continue; + } + + if (!cs35l41_check_cspl_mbox_sts(cmd, sts)) + dev_dbg(dev, "[%u] cmd %u returned invalid sts %u", i, cmd, sts); + else + return 0; + } + + dev_err(dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts); + + return -ENOMSG; +} +EXPORT_SYMBOL_GPL(cs35l41_set_cspl_mbox_cmd); + MODULE_DESCRIPTION("CS35L41 library"); MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>"); MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>"); |