Merge tag 'asoc-v6.9' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[linux-2.6-microblaze.git] / sound / soc / codecs / cs35l56.c
index 450a163..8d2f021 100644 (file)
@@ -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>
@@ -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)
@@ -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:
@@ -1368,6 +1400,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);
@@ -1469,6 +1502,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;
@@ -1553,6 +1590,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");