#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
+#include <sound/cs-amp-lib.h>
 #include <sound/hda_codec.h>
 #include <sound/tlv.h>
 #include "cirrus_scodec.h"
        hda_cs_dsp_add_controls(&cs35l56->cs_dsp, &info);
 }
 
+static void cs35l56_hda_apply_calibration(struct cs35l56_hda *cs35l56)
+{
+       int ret;
+
+       if (!cs35l56->base.cal_data_valid || cs35l56->base.secured)
+               return;
+
+       ret = cs_amp_write_cal_coeffs(&cs35l56->cs_dsp,
+                                     &cs35l56_calibration_controls,
+                                     &cs35l56->base.cal_data);
+       if (ret < 0)
+               dev_warn(cs35l56->base.dev, "Failed to write calibration: %d\n", ret);
+       else
+               dev_info(cs35l56->base.dev, "Calibration applied\n");
+}
+
 static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
 {
        const struct firmware *coeff_firmware = NULL;
        if (coeff_filename)
                dev_dbg(cs35l56->base.dev, "Loaded Coefficients: %s\n", coeff_filename);
 
-       if (!firmware_missing) {
-               ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);
-               if (ret)
-                       goto err_powered_up;
-       } else if (wmfw_firmware || coeff_firmware) {
-               /* If we downloaded firmware, reset the device and wait for it to boot */
+       /* If we downloaded firmware, reset the device and wait for it to boot */
+       if (firmware_missing && (wmfw_firmware || coeff_firmware)) {
                cs35l56_system_reset(&cs35l56->base, false);
                regcache_mark_dirty(cs35l56->base.regmap);
                ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);
        if (ret)
                dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret);
 
+       cs35l56_hda_apply_calibration(cs35l56);
+       ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);
+       if (ret)
+               cs_dsp_stop(&cs35l56->cs_dsp);
+
 err_powered_up:
        if (!cs35l56->base.fw_patched)
                cs_dsp_power_down(&cs35l56->cs_dsp);
                goto err;
        }
 
+       cs35l56->base.cal_index = cs35l56->index;
+
        cs35l56_init_cs_dsp(&cs35l56->base, &cs35l56->cs_dsp);
        cs35l56->cs_dsp.client_ops = &cs35l56_hda_client_ops;
 
        if (ret)
                goto err;
 
+       ret = cs35l56_get_calibration(&cs35l56->base);
+       if (ret)
+               goto err;
+
        ret = cs_dsp_halo_init(&cs35l56->cs_dsp);
        if (ret) {
                dev_err_probe(cs35l56->base.dev, ret, "cs_dsp_halo_init failed\n");
 EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56);
 
 MODULE_DESCRIPTION("CS35L56 HDA Driver");
+MODULE_IMPORT_NS(FW_CS_DSP);
 MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);
 MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS);
 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");
-MODULE_IMPORT_NS(FW_CS_DSP);