ASoC: cs35l41: Move cs35l41_set_cspl_mbox_cmd to shared code

This function is used to control the DSP Firmware for cs35l41,
and will be needed by the cs35l41 hda driver, when firmware
support is added.

Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20220509214703.4482-7-vitalyr@opensource.cirrus.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Stefan Binding 2022-05-09 22:46:43 +01:00 коммит произвёл Takashi Iwai
Родитель de8cab7b38
Коммит caf7c1f1de
4 изменённых файлов: 82 добавлений и 82 удалений

Просмотреть файл

@ -801,6 +801,24 @@ struct cs35l41_otp_map_element_t {
u32 word_offset;
};
enum cs35l41_cspl_mbox_status {
CSPL_MBOX_STS_RUNNING = 0,
CSPL_MBOX_STS_PAUSED = 1,
CSPL_MBOX_STS_RDY_FOR_REINIT = 2,
};
enum cs35l41_cspl_mbox_cmd {
CSPL_MBOX_CMD_NONE = 0,
CSPL_MBOX_CMD_PAUSE = 1,
CSPL_MBOX_CMD_RESUME = 2,
CSPL_MBOX_CMD_REINIT = 3,
CSPL_MBOX_CMD_STOP_PRE_REINIT = 4,
CSPL_MBOX_CMD_HIBERNATE = 5,
CSPL_MBOX_CMD_OUT_OF_HIBERNATE = 6,
CSPL_MBOX_CMD_UNKNOWN_CMD = -1,
CSPL_MBOX_CMD_INVALID_SEQUENCE = -2,
};
/*
* IRQs
*/
@ -859,6 +877,8 @@ int cs35l41_set_channels(struct device *dev, struct regmap *reg,
unsigned int tx_num, unsigned int *tx_slot,
unsigned int rx_num, unsigned int *rx_slot);
int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg);
int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap,
enum cs35l41_cspl_mbox_cmd cmd);
int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
struct cs35l41_hw_cfg *hw_cfg);
bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type);

Просмотреть файл

@ -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>");

Просмотреть файл

@ -208,67 +208,6 @@ static int cs35l41_dsp_preload_ev(struct snd_soc_dapm_widget *w,
}
}
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;
}
}
static int cs35l41_set_cspl_mbox_cmd(struct cs35l41_private *cs35l41,
enum cs35l41_cspl_mbox_cmd cmd)
{
unsigned int sts = 0, i;
int ret;
// Set mailbox cmd
ret = regmap_write(cs35l41->regmap, CS35L41_DSP_VIRT1_MBOX_1, cmd);
if (ret < 0) {
if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE)
dev_err(cs35l41->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(cs35l41->regmap, CS35L41_DSP_MBOX_2, &sts);
if (ret < 0) {
dev_err(cs35l41->dev, "Failed to read MBOX STS: %d\n", ret);
continue;
}
if (!cs35l41_check_cspl_mbox_sts(cmd, sts)) {
dev_dbg(cs35l41->dev,
"[%u] cmd %u returned invalid sts %u",
i, cmd, sts);
} else {
return 0;
}
}
dev_err(cs35l41->dev,
"Failed to set mailbox cmd %u (status %u)\n",
cmd, sts);
return -ENOMSG;
}
static int cs35l41_dsp_audio_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@ -299,9 +238,11 @@ static int cs35l41_dsp_audio_ev(struct snd_soc_dapm_widget *w,
return -EINVAL;
}
return cs35l41_set_cspl_mbox_cmd(cs35l41, CSPL_MBOX_CMD_RESUME);
return cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap,
CSPL_MBOX_CMD_RESUME);
case SND_SOC_DAPM_PRE_PMD:
return cs35l41_set_cspl_mbox_cmd(cs35l41, CSPL_MBOX_CMD_PAUSE);
return cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap,
CSPL_MBOX_CMD_PAUSE);
default:
return 0;
}
@ -1475,7 +1416,7 @@ static int cs35l41_exit_hibernate(struct cs35l41_private *cs35l41)
dev_dbg(cs35l41->dev, "Exit hibernate\n");
for (j = 0; j < wake_retries; j++) {
ret = cs35l41_set_cspl_mbox_cmd(cs35l41,
ret = cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap,
CSPL_MBOX_CMD_OUT_OF_HIBERNATE);
if (!ret)
break;

Просмотреть файл

@ -23,24 +23,6 @@
extern const struct dev_pm_ops cs35l41_pm_ops;
enum cs35l41_cspl_mbox_status {
CSPL_MBOX_STS_RUNNING = 0,
CSPL_MBOX_STS_PAUSED = 1,
CSPL_MBOX_STS_RDY_FOR_REINIT = 2,
};
enum cs35l41_cspl_mbox_cmd {
CSPL_MBOX_CMD_NONE = 0,
CSPL_MBOX_CMD_PAUSE = 1,
CSPL_MBOX_CMD_RESUME = 2,
CSPL_MBOX_CMD_REINIT = 3,
CSPL_MBOX_CMD_STOP_PRE_REINIT = 4,
CSPL_MBOX_CMD_HIBERNATE = 5,
CSPL_MBOX_CMD_OUT_OF_HIBERNATE = 6,
CSPL_MBOX_CMD_UNKNOWN_CMD = -1,
CSPL_MBOX_CMD_INVALID_SEQUENCE = -2,
};
struct cs35l41_private {
struct wm_adsp dsp; /* needs to be first member */
struct snd_soc_codec *codec;