Skip to content

Commit

Permalink
ASoC: cs35l56: Apply amp calibration from EFI data
Browse files Browse the repository at this point in the history
If there are factory calibration settings in EFI, extract the
settings and write them to the firmware calibration controls.

This must be done after any firmware or coefficients have been
downloaded to the amp.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20240223153910.2063698-5-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Richard Fitzgerald authored and Mark Brown committed Feb 23, 2024
1 parent e1830f6 commit 1326444
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 3 deletions.
20 changes: 20 additions & 0 deletions sound/soc/codecs/cs35l56-sdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,33 @@ static const struct regmap_bus cs35l56_regmap_bus_sdw = {
.val_format_endian_default = REGMAP_ENDIAN_BIG,
};

static int cs35l56_sdw_set_cal_index(struct cs35l56_private *cs35l56)
{
int ret;

/* SoundWire UniqueId is used to index the calibration array */
ret = sdw_read_no_pm(cs35l56->sdw_peripheral, SDW_SCP_DEVID_0);
if (ret < 0)
return ret;

cs35l56->base.cal_index = ret & 0xf;

return 0;
}

static void cs35l56_sdw_init(struct sdw_slave *peripheral)
{
struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);
int ret;

pm_runtime_get_noresume(cs35l56->base.dev);

if (cs35l56->base.cal_index < 0) {
ret = cs35l56_sdw_set_cal_index(cs35l56);
if (ret < 0)
goto out;
}

regcache_cache_only(cs35l56->base.regmap, false);

ret = cs35l56_init(cs35l56);
Expand Down
44 changes: 41 additions & 3 deletions sound/soc/codecs/cs35l56.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/soundwire/sdw.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#include <sound/cs-amp-lib.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
Expand Down Expand Up @@ -802,16 +803,44 @@ static struct snd_soc_dai_driver cs35l56_dai[] = {
}
};

static int cs35l56_write_cal(struct cs35l56_private *cs35l56)
{
int ret;

if (cs35l56->base.secured || !cs35l56->base.cal_data_valid)
return -ENODATA;

ret = wm_adsp_run(&cs35l56->dsp);
if (ret)
return ret;

ret = cs_amp_write_cal_coeffs(&cs35l56->dsp.cs_dsp,
&cs35l56_calibration_controls,
&cs35l56->base.cal_data);

wm_adsp_stop(&cs35l56->dsp);

if (ret == 0)
dev_info(cs35l56->base.dev, "Calibration applied\n");

return ret;
}

static void cs35l56_reinit_patch(struct cs35l56_private *cs35l56)
{
int ret;

/* Use wm_adsp to load and apply the firmware patch and coefficient files */
ret = wm_adsp_power_up(&cs35l56->dsp, true);
if (ret)
if (ret) {
dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
else
cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);
return;
}

cs35l56_write_cal(cs35l56);

/* Always REINIT after applying patch or coefficients */
cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);
}

static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing)
Expand Down Expand Up @@ -874,6 +903,9 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing
CS35L56_FIRMWARE_MISSING);
cs35l56->base.fw_patched = true;

if (cs35l56_write_cal(cs35l56) == 0)
cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);

err_unlock:
mutex_unlock(&cs35l56->base.irq_lock);
err:
Expand Down Expand Up @@ -1356,6 +1388,7 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)

init_completion(&cs35l56->init_completion);
mutex_init(&cs35l56->base.irq_lock);
cs35l56->base.cal_index = -1;
cs35l56->speaker_id = -ENOENT;

dev_set_drvdata(cs35l56->base.dev, cs35l56);
Expand Down Expand Up @@ -1457,6 +1490,10 @@ int cs35l56_init(struct cs35l56_private *cs35l56)
if (ret)
return ret;

ret = cs35l56_get_calibration(&cs35l56->base);
if (ret)
return ret;

if (!cs35l56->base.reset_gpio) {
dev_dbg(cs35l56->base.dev, "No reset gpio: using soft reset\n");
cs35l56->soft_resetting = true;
Expand Down Expand Up @@ -1541,6 +1578,7 @@ EXPORT_NS_GPL_DEV_PM_OPS(cs35l56_pm_ops_i2c_spi, SND_SOC_CS35L56_CORE) = {

MODULE_DESCRIPTION("ASoC CS35L56 driver");
MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
MODULE_LICENSE("GPL");

0 comments on commit 1326444

Please sign in to comment.