Commit afd17e6d authored by Simon Trimmer's avatar Simon Trimmer Committed by Takashi Iwai

ASoC: cs35l56: Add support for CS35L54 and CS35L57

The CS35L54 and CS35L57 are Boosted Smart Amplifiers. The CS35L54 has
I2C/SPI control and I2S/TDM audio. The CS35L57 also has SoundWire
control and audio.

The hardware differences between L54, L56 and L57 do not affect the
driver control interface so they can all be handled by the same driver.
Signed-off-by: default avatarSimon Trimmer <simont@opensource.cirrus.com>
Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
Acked-by: default avatarMark Brown <broonie@kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Message-ID: <20240308135900.603192-2-rf@opensource.cirrus.com>
parent 85b4f2a6
...@@ -257,6 +257,7 @@ struct cs35l56_base { ...@@ -257,6 +257,7 @@ struct cs35l56_base {
struct regmap *regmap; struct regmap *regmap;
int irq; int irq;
struct mutex irq_lock; struct mutex irq_lock;
u8 type;
u8 rev; u8 rev;
bool init_done; bool init_done;
bool fw_patched; bool fw_patched;
......
...@@ -366,7 +366,7 @@ static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, ...@@ -366,7 +366,7 @@ static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral,
dev_dbg(cs35l56->base.dev, "%s: sclk=%u c=%u r=%u\n", dev_dbg(cs35l56->base.dev, "%s: sclk=%u c=%u r=%u\n",
__func__, sclk, params->col, params->row); __func__, sclk, params->col, params->row);
if (cs35l56->base.rev < 0xb0) if ((cs35l56->base.type == 0x56) && (cs35l56->base.rev < 0xb0))
return cs35l56_a1_kick_divider(cs35l56, peripheral); return cs35l56_a1_kick_divider(cs35l56, peripheral);
return 0; return 0;
...@@ -543,6 +543,7 @@ static const struct dev_pm_ops cs35l56_sdw_pm = { ...@@ -543,6 +543,7 @@ static const struct dev_pm_ops cs35l56_sdw_pm = {
static const struct sdw_device_id cs35l56_sdw_id[] = { static const struct sdw_device_id cs35l56_sdw_id[] = {
SDW_SLAVE_ENTRY(0x01FA, 0x3556, 0), SDW_SLAVE_ENTRY(0x01FA, 0x3556, 0),
SDW_SLAVE_ENTRY(0x01FA, 0x3557, 0),
{}, {},
}; };
MODULE_DEVICE_TABLE(sdw, cs35l56_sdw_id); MODULE_DEVICE_TABLE(sdw, cs35l56_sdw_id);
......
...@@ -692,13 +692,17 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) ...@@ -692,13 +692,17 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
devid &= CS35L56_DEVID_MASK; devid &= CS35L56_DEVID_MASK;
switch (devid) { switch (devid) {
case 0x35A54:
case 0x35A56: case 0x35A56:
case 0x35A57:
break; break;
default: default:
dev_err(cs35l56_base->dev, "Unknown device %x\n", devid); dev_err(cs35l56_base->dev, "Unknown device %x\n", devid);
return ret; return ret;
} }
cs35l56_base->type = devid & 0xFF;
ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured); ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured);
if (ret) { if (ret) {
dev_err(cs35l56_base->dev, "Get Secure status failed\n"); dev_err(cs35l56_base->dev, "Get Secure status failed\n");
...@@ -719,8 +723,8 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base) ...@@ -719,8 +723,8 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
if (ret) if (ret)
return ret; return ret;
dev_info(cs35l56_base->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d fw:%d.%d.%d (patched=%u)\n", dev_info(cs35l56_base->dev, "Cirrus Logic CS35L%02X%s Rev %02X OTP%d fw:%d.%d.%d (patched=%u)\n",
cs35l56_base->secured ? "s" : "", cs35l56_base->rev, otpid, cs35l56_base->type, cs35l56_base->secured ? "s" : "", cs35l56_base->rev, otpid,
fw_ver >> 16, (fw_ver >> 8) & 0xff, fw_ver & 0xff, !fw_missing); fw_ver >> 16, (fw_ver >> 8) & 0xff, fw_ver & 0xff, !fw_missing);
/* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */ /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */
......
...@@ -972,6 +972,10 @@ static int cs35l56_component_probe(struct snd_soc_component *component) ...@@ -972,6 +972,10 @@ static int cs35l56_component_probe(struct snd_soc_component *component)
return -ENODEV; return -ENODEV;
} }
cs35l56->dsp.part = kasprintf(GFP_KERNEL, "cs35l%02x", cs35l56->base.type);
if (!cs35l56->dsp.part)
return -ENOMEM;
cs35l56->component = component; cs35l56->component = component;
wm_adsp2_component_probe(&cs35l56->dsp, component); wm_adsp2_component_probe(&cs35l56->dsp, component);
...@@ -1002,6 +1006,9 @@ static void cs35l56_component_remove(struct snd_soc_component *component) ...@@ -1002,6 +1006,9 @@ static void cs35l56_component_remove(struct snd_soc_component *component)
wm_adsp2_component_remove(&cs35l56->dsp, component); wm_adsp2_component_remove(&cs35l56->dsp, component);
kfree(cs35l56->dsp.part);
cs35l56->dsp.part = NULL;
kfree(cs35l56->dsp.fwf_name); kfree(cs35l56->dsp.fwf_name);
cs35l56->dsp.fwf_name = NULL; cs35l56->dsp.fwf_name = NULL;
...@@ -1221,7 +1228,12 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56) ...@@ -1221,7 +1228,12 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56)
dsp = &cs35l56->dsp; dsp = &cs35l56->dsp;
cs35l56_init_cs_dsp(&cs35l56->base, &dsp->cs_dsp); cs35l56_init_cs_dsp(&cs35l56->base, &dsp->cs_dsp);
dsp->part = "cs35l56";
/*
* dsp->part is filled in later as it is based on the DEVID. In a
* SoundWire system that cannot be read until enumeration has occurred
* and the device has attached.
*/
dsp->fw = 12; dsp->fw = 12;
dsp->wmfw_optional = true; dsp->wmfw_optional = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment