Skip to content

Commit 1326444

Browse files
rfvirgilbroonie
authored andcommitted
ASoC: cs35l56: Apply amp calibration from EFI data
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent e1830f6 commit 1326444

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

sound/soc/codecs/cs35l56-sdw.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,33 @@ static const struct regmap_bus cs35l56_regmap_bus_sdw = {
161161
.val_format_endian_default = REGMAP_ENDIAN_BIG,
162162
};
163163

164+
static int cs35l56_sdw_set_cal_index(struct cs35l56_private *cs35l56)
165+
{
166+
int ret;
167+
168+
/* SoundWire UniqueId is used to index the calibration array */
169+
ret = sdw_read_no_pm(cs35l56->sdw_peripheral, SDW_SCP_DEVID_0);
170+
if (ret < 0)
171+
return ret;
172+
173+
cs35l56->base.cal_index = ret & 0xf;
174+
175+
return 0;
176+
}
177+
164178
static void cs35l56_sdw_init(struct sdw_slave *peripheral)
165179
{
166180
struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);
167181
int ret;
168182

169183
pm_runtime_get_noresume(cs35l56->base.dev);
170184

185+
if (cs35l56->base.cal_index < 0) {
186+
ret = cs35l56_sdw_set_cal_index(cs35l56);
187+
if (ret < 0)
188+
goto out;
189+
}
190+
171191
regcache_cache_only(cs35l56->base.regmap, false);
172192

173193
ret = cs35l56_init(cs35l56);

sound/soc/codecs/cs35l56.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <linux/soundwire/sdw.h>
2424
#include <linux/types.h>
2525
#include <linux/workqueue.h>
26+
#include <sound/cs-amp-lib.h>
2627
#include <sound/pcm.h>
2728
#include <sound/pcm_params.h>
2829
#include <sound/soc.h>
@@ -802,16 +803,44 @@ static struct snd_soc_dai_driver cs35l56_dai[] = {
802803
}
803804
};
804805

806+
static int cs35l56_write_cal(struct cs35l56_private *cs35l56)
807+
{
808+
int ret;
809+
810+
if (cs35l56->base.secured || !cs35l56->base.cal_data_valid)
811+
return -ENODATA;
812+
813+
ret = wm_adsp_run(&cs35l56->dsp);
814+
if (ret)
815+
return ret;
816+
817+
ret = cs_amp_write_cal_coeffs(&cs35l56->dsp.cs_dsp,
818+
&cs35l56_calibration_controls,
819+
&cs35l56->base.cal_data);
820+
821+
wm_adsp_stop(&cs35l56->dsp);
822+
823+
if (ret == 0)
824+
dev_info(cs35l56->base.dev, "Calibration applied\n");
825+
826+
return ret;
827+
}
828+
805829
static void cs35l56_reinit_patch(struct cs35l56_private *cs35l56)
806830
{
807831
int ret;
808832

809833
/* Use wm_adsp to load and apply the firmware patch and coefficient files */
810834
ret = wm_adsp_power_up(&cs35l56->dsp, true);
811-
if (ret)
835+
if (ret) {
812836
dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
813-
else
814-
cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);
837+
return;
838+
}
839+
840+
cs35l56_write_cal(cs35l56);
841+
842+
/* Always REINIT after applying patch or coefficients */
843+
cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);
815844
}
816845

817846
static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing)
@@ -874,6 +903,9 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing
874903
CS35L56_FIRMWARE_MISSING);
875904
cs35l56->base.fw_patched = true;
876905

906+
if (cs35l56_write_cal(cs35l56) == 0)
907+
cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);
908+
877909
err_unlock:
878910
mutex_unlock(&cs35l56->base.irq_lock);
879911
err:
@@ -1356,6 +1388,7 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
13561388

13571389
init_completion(&cs35l56->init_completion);
13581390
mutex_init(&cs35l56->base.irq_lock);
1391+
cs35l56->base.cal_index = -1;
13591392
cs35l56->speaker_id = -ENOENT;
13601393

13611394
dev_set_drvdata(cs35l56->base.dev, cs35l56);
@@ -1457,6 +1490,10 @@ int cs35l56_init(struct cs35l56_private *cs35l56)
14571490
if (ret)
14581491
return ret;
14591492

1493+
ret = cs35l56_get_calibration(&cs35l56->base);
1494+
if (ret)
1495+
return ret;
1496+
14601497
if (!cs35l56->base.reset_gpio) {
14611498
dev_dbg(cs35l56->base.dev, "No reset gpio: using soft reset\n");
14621499
cs35l56->soft_resetting = true;
@@ -1541,6 +1578,7 @@ EXPORT_NS_GPL_DEV_PM_OPS(cs35l56_pm_ops_i2c_spi, SND_SOC_CS35L56_CORE) = {
15411578

15421579
MODULE_DESCRIPTION("ASoC CS35L56 driver");
15431580
MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
1581+
MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);
15441582
MODULE_AUTHOR("Richard Fitzgerald <[email protected]>");
15451583
MODULE_AUTHOR("Simon Trimmer <[email protected]>");
15461584
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)