]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - sound/soc/codecs/wm_adsp.c
Merge remote-tracking branches 'asoc/topic/adau17x1', 'asoc/topic/adsp', 'asoc/topic...
[mirror_ubuntu-bionic-kernel.git] / sound / soc / codecs / wm_adsp.c
index d72ccef9e238d39807657597d1c8496022718bb5..d151224ffcca411a5685b2076c43748fd2134790 100644 (file)
@@ -2473,7 +2473,7 @@ static void wm_adsp2_boot_work(struct work_struct *work)
 
        ret = wm_adsp2_ena(dsp);
        if (ret != 0)
-               goto err_mutex;
+               goto err_mem;
 
        ret = wm_adsp_load(dsp);
        if (ret != 0)
@@ -2492,14 +2492,14 @@ static void wm_adsp2_boot_work(struct work_struct *work)
        if (ret != 0)
                goto err_ena;
 
-       dsp->booted = true;
-
        /* Turn DSP back off until we are ready to run */
        ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
                                 ADSP2_SYS_ENA, 0);
        if (ret != 0)
                goto err_ena;
 
+       dsp->booted = true;
+
        mutex_unlock(&dsp->pwr_lock);
 
        return;
@@ -2507,6 +2507,9 @@ static void wm_adsp2_boot_work(struct work_struct *work)
 err_ena:
        regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
                           ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+err_mem:
+       regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                          ADSP2_MEM_ENA, 0);
 err_mutex:
        mutex_unlock(&dsp->pwr_lock);
 }
@@ -2523,6 +2526,43 @@ static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq)
                adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
 }
 
+int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+       struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = dsp->preloaded;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get);
+
+int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+       struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
+       struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       char preload[32];
+
+       snprintf(preload, ARRAY_SIZE(preload), "DSP%d Preload", mc->shift);
+
+       dsp->preloaded = ucontrol->value.integer.value[0];
+
+       if (ucontrol->value.integer.value[0])
+               snd_soc_dapm_force_enable_pin(dapm, preload);
+       else
+               snd_soc_dapm_disable_pin(dapm, preload);
+
+       snd_soc_dapm_sync(dapm);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);
+
 int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
                         struct snd_kcontrol *kcontrol, int event,
                         unsigned int freq)
@@ -2538,6 +2578,8 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
                queue_work(system_unbound_wq, &dsp->boot_work);
                break;
        case SND_SOC_DAPM_PRE_PMD:
+               mutex_lock(&dsp->pwr_lock);
+
                wm_adsp_debugfs_clear(dsp);
 
                dsp->fw_id = 0;
@@ -2553,6 +2595,8 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
 
                wm_adsp_free_alg_regions(dsp);
 
+               mutex_unlock(&dsp->pwr_lock);
+
                adsp_dbg(dsp, "Shutdown complete\n");
                break;
        default:
@@ -2575,8 +2619,12 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
        case SND_SOC_DAPM_POST_PMU:
                flush_work(&dsp->boot_work);
 
-               if (!dsp->booted)
-                       return -EIO;
+               mutex_lock(&dsp->pwr_lock);
+
+               if (!dsp->booted) {
+                       ret = -EIO;
+                       goto err;
+               }
 
                ret = wm_adsp2_ena(dsp);
                if (ret != 0)
@@ -2594,18 +2642,14 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                if (ret != 0)
                        goto err;
 
-               dsp->running = true;
-
-               mutex_lock(&dsp->pwr_lock);
-
                if (wm_adsp_fw[dsp->fw].num_caps != 0) {
                        ret = wm_adsp_buffer_init(dsp);
-                       if (ret < 0) {
-                               mutex_unlock(&dsp->pwr_lock);
+                       if (ret < 0)
                                goto err;
-                       }
                }
 
+               dsp->running = true;
+
                mutex_unlock(&dsp->pwr_lock);
 
                break;
@@ -2648,16 +2692,23 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 err:
        regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
                           ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+       mutex_unlock(&dsp->pwr_lock);
        return ret;
 }
 EXPORT_SYMBOL_GPL(wm_adsp2_event);
 
 int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec)
 {
-       dsp->codec = codec;
+       struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+       char preload[32];
+
+       snprintf(preload, ARRAY_SIZE(preload), "DSP%d Preload", dsp->num);
+       snd_soc_dapm_disable_pin(dapm, preload);
 
        wm_adsp2_init_debugfs(dsp, codec);
 
+       dsp->codec = codec;
+
        return snd_soc_add_codec_controls(codec,
                                          &wm_adsp_fw_controls[dsp->num - 1],
                                          1);