.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);
 
        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);
 
 #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>
        }
 };
 
+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)
                          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:
 
        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);
        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;
 
 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");