Lines Matching +full:fw +full:- +full:cfg

1 // SPDX-License-Identifier: GPL-2.0-only
3 * wm8958-dsp2.c -- WM8958 DSP2 support
42 const struct firmware *fw, bool check) in wm8958_dsp2_fw() argument
53 if (wm8994->cur_fw == fw) in wm8958_dsp2_fw()
56 if (fw->size < 32) { in wm8958_dsp2_fw()
57 dev_err(component->dev, "%s: firmware too short (%zd bytes)\n", in wm8958_dsp2_fw()
58 name, fw->size); in wm8958_dsp2_fw()
62 if (memcmp(fw->data, "WMFW", 4) != 0) { in wm8958_dsp2_fw()
63 data32 = get_unaligned_be32(fw->data); in wm8958_dsp2_fw()
64 dev_err(component->dev, "%s: firmware has bad file magic %08x\n", in wm8958_dsp2_fw()
69 len = get_unaligned_be32(fw->data + 4); in wm8958_dsp2_fw()
70 data32 = get_unaligned_be32(fw->data + 8); in wm8958_dsp2_fw()
73 dev_err(component->dev, "%s: unsupported firmware version %d\n", in wm8958_dsp2_fw()
78 dev_err(component->dev, "%s: unsupported target device %d\n", in wm8958_dsp2_fw()
83 dev_err(component->dev, "%s: unsupported target core %d\n", in wm8958_dsp2_fw()
89 data64 = get_unaligned_be64(fw->data + 24); in wm8958_dsp2_fw()
90 dev_info(component->dev, "%s timestamp %llx\n", name, data64); in wm8958_dsp2_fw()
96 data = fw->data + len; in wm8958_dsp2_fw()
97 len = fw->size - len; in wm8958_dsp2_fw()
100 dev_err(component->dev, "%s short data block of %zd\n", in wm8958_dsp2_fw()
107 dev_err(component->dev, "%zd byte block longer than file\n", in wm8958_dsp2_fw()
112 dev_err(component->dev, "Zero length block\n"); in wm8958_dsp2_fw()
127 dev_info(component->dev, "%s: %s\n", name, str); in wm8958_dsp2_fw()
130 dev_err(component->dev, "Out of memory\n"); in wm8958_dsp2_fw()
140 dev_dbg(component->dev, "%s: %zd bytes of %x@%x\n", name, in wm8958_dsp2_fw()
149 wm8994_bulk_write(wm8994->wm8994, in wm8958_dsp2_fw()
156 dev_warn(component->dev, "%s: unknown block type %d\n", in wm8958_dsp2_fw()
165 len -= block_len + 8; in wm8958_dsp2_fw()
169 dev_dbg(component->dev, "%s: download done\n", name); in wm8958_dsp2_fw()
170 wm8994->cur_fw = fw; in wm8958_dsp2_fw()
172 dev_info(component->dev, "%s: got firmware\n", name); in wm8958_dsp2_fw()
178 ret = -EINVAL; in wm8958_dsp2_fw()
191 struct wm8994 *control = wm8994->wm8994; in wm8958_dsp_start_mbc()
199 if (wm8994->mbc) in wm8958_dsp_start_mbc()
200 wm8958_dsp2_fw(component, "MBC", wm8994->mbc, false); in wm8958_dsp_start_mbc()
206 if (control->pdata.num_mbc_cfgs) { in wm8958_dsp_start_mbc()
207 struct wm8958_mbc_cfg *cfg in wm8958_dsp_start_mbc() local
208 = &control->pdata.mbc_cfgs[wm8994->mbc_cfg]; in wm8958_dsp_start_mbc()
210 for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++) in wm8958_dsp_start_mbc()
212 cfg->coeff_regs[i]); in wm8958_dsp_start_mbc()
214 for (i = 0; i < ARRAY_SIZE(cfg->cutoff_regs); i++) in wm8958_dsp_start_mbc()
217 cfg->cutoff_regs[i]); in wm8958_dsp_start_mbc()
235 struct wm8994 *control = wm8994->wm8994; in wm8958_dsp_start_vss()
238 if (wm8994->mbc_vss) in wm8958_dsp_start_vss()
239 wm8958_dsp2_fw(component, "MBC+VSS", wm8994->mbc_vss, false); in wm8958_dsp_start_vss()
245 if (control->pdata.num_mbc_cfgs) { in wm8958_dsp_start_vss()
246 struct wm8958_mbc_cfg *cfg in wm8958_dsp_start_vss() local
247 = &control->pdata.mbc_cfgs[wm8994->mbc_cfg]; in wm8958_dsp_start_vss()
249 for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++) in wm8958_dsp_start_vss()
251 cfg->combined_regs[i]); in wm8958_dsp_start_vss()
254 if (control->pdata.num_vss_cfgs) { in wm8958_dsp_start_vss()
255 struct wm8958_vss_cfg *cfg in wm8958_dsp_start_vss() local
256 = &control->pdata.vss_cfgs[wm8994->vss_cfg]; in wm8958_dsp_start_vss()
258 for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) in wm8958_dsp_start_vss()
259 snd_soc_component_write(component, i + 0x2600, cfg->regs[i]); in wm8958_dsp_start_vss()
262 if (control->pdata.num_vss_hpf_cfgs) { in wm8958_dsp_start_vss()
263 struct wm8958_vss_hpf_cfg *cfg in wm8958_dsp_start_vss() local
264 = &control->pdata.vss_hpf_cfgs[wm8994->vss_hpf_cfg]; in wm8958_dsp_start_vss()
266 for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) in wm8958_dsp_start_vss()
267 snd_soc_component_write(component, i + 0x2400, cfg->regs[i]); in wm8958_dsp_start_vss()
276 if (wm8994->mbc_ena[path]) in wm8958_dsp_start_vss()
278 if (wm8994->hpf2_ena[path]) in wm8958_dsp_start_vss()
280 if (wm8994->hpf1_ena[path]) in wm8958_dsp_start_vss()
282 if (wm8994->vss_ena[path]) in wm8958_dsp_start_vss()
296 struct wm8994 *control = wm8994->wm8994; in wm8958_dsp_start_enh_eq()
299 wm8958_dsp2_fw(component, "ENH_EQ", wm8994->enh_eq, false); in wm8958_dsp_start_enh_eq()
305 if (control->pdata.num_enh_eq_cfgs) { in wm8958_dsp_start_enh_eq()
306 struct wm8958_enh_eq_cfg *cfg in wm8958_dsp_start_enh_eq() local
307 = &control->pdata.enh_eq_cfgs[wm8994->enh_eq_cfg]; in wm8958_dsp_start_enh_eq()
309 for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) in wm8958_dsp_start_enh_eq()
311 cfg->regs[i]); in wm8958_dsp_start_enh_eq()
349 ena = wm8994->mbc_ena[path] || wm8994->vss_ena[path] || in wm8958_dsp_apply()
350 wm8994->hpf1_ena[path] || wm8994->hpf2_ena[path] || in wm8958_dsp_apply()
351 wm8994->enh_eq_ena[path]; in wm8958_dsp_apply()
357 dev_dbg(component->dev, "DSP path %d %d startup: %d, power: %x, DSP: %x\n", in wm8958_dsp_apply()
358 path, wm8994->dsp_active, start, pwr_reg, reg); in wm8958_dsp_apply()
378 if (wm8994->enh_eq_ena[path]) in wm8958_dsp_apply()
380 else if (wm8994->vss_ena[path] || wm8994->hpf1_ena[path] || in wm8958_dsp_apply()
381 wm8994->hpf2_ena[path]) in wm8958_dsp_apply()
383 else if (wm8994->mbc_ena[path]) in wm8958_dsp_apply()
386 wm8994->dsp_active = path; in wm8958_dsp_apply()
388 dev_dbg(component->dev, "DSP running in path %d\n", path); in wm8958_dsp_apply()
391 if (!start && wm8994->dsp_active == path) { in wm8958_dsp_apply()
405 wm8994->dsp_active = -1; in wm8958_dsp_apply()
407 dev_dbg(component->dev, "DSP stopped\n"); in wm8958_dsp_apply()
414 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); in wm8958_aif_ev()
415 struct wm8994 *control = dev_get_drvdata(component->dev->parent); in wm8958_aif_ev()
418 if (control->type != WM8958) in wm8958_aif_ev()
442 for (i = 0; i < ARRAY_SIZE(wm8994->mbc_ena); i++) { in wm8958_dsp2_busy()
445 if (wm8994->mbc_ena[i] || wm8994->vss_ena[i] || in wm8958_dsp2_busy()
446 wm8994->hpf1_ena[i] || wm8994->hpf2_ena[i]) in wm8958_dsp2_busy()
458 struct wm8994 *control = wm8994->wm8994; in wm8958_put_mbc_enum()
459 int value = ucontrol->value.enumerated.item[0]; in wm8958_put_mbc_enum()
465 return -EBUSY; in wm8958_put_mbc_enum()
467 if (value >= control->pdata.num_mbc_cfgs) in wm8958_put_mbc_enum()
468 return -EINVAL; in wm8958_put_mbc_enum()
470 wm8994->mbc_cfg = value; in wm8958_put_mbc_enum()
481 ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg; in wm8958_get_mbc_enum()
489 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; in wm8958_mbc_info()
490 uinfo->count = 1; in wm8958_mbc_info()
491 uinfo->value.integer.min = 0; in wm8958_mbc_info()
492 uinfo->value.integer.max = 1; in wm8958_mbc_info()
499 int mbc = kcontrol->private_value; in wm8958_mbc_get()
503 ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc]; in wm8958_mbc_get()
511 int mbc = kcontrol->private_value; in wm8958_mbc_put()
515 if (wm8994->mbc_ena[mbc] == ucontrol->value.integer.value[0]) in wm8958_mbc_put()
518 if (ucontrol->value.integer.value[0] > 1) in wm8958_mbc_put()
519 return -EINVAL; in wm8958_mbc_put()
522 dev_dbg(component->dev, "DSP2 active on %d already\n", mbc); in wm8958_mbc_put()
523 return -EBUSY; in wm8958_mbc_put()
526 if (wm8994->enh_eq_ena[mbc]) in wm8958_mbc_put()
527 return -EBUSY; in wm8958_mbc_put()
529 wm8994->mbc_ena[mbc] = ucontrol->value.integer.value[0]; in wm8958_mbc_put()
531 wm8958_dsp_apply(component, mbc, wm8994->mbc_ena[mbc]); in wm8958_mbc_put()
548 struct wm8994 *control = wm8994->wm8994; in wm8958_put_vss_enum()
549 int value = ucontrol->value.enumerated.item[0]; in wm8958_put_vss_enum()
555 return -EBUSY; in wm8958_put_vss_enum()
557 if (value >= control->pdata.num_vss_cfgs) in wm8958_put_vss_enum()
558 return -EINVAL; in wm8958_put_vss_enum()
560 wm8994->vss_cfg = value; in wm8958_put_vss_enum()
571 ucontrol->value.enumerated.item[0] = wm8994->vss_cfg; in wm8958_get_vss_enum()
581 struct wm8994 *control = wm8994->wm8994; in wm8958_put_vss_hpf_enum()
582 int value = ucontrol->value.enumerated.item[0]; in wm8958_put_vss_hpf_enum()
588 return -EBUSY; in wm8958_put_vss_hpf_enum()
590 if (value >= control->pdata.num_vss_hpf_cfgs) in wm8958_put_vss_hpf_enum()
591 return -EINVAL; in wm8958_put_vss_hpf_enum()
593 wm8994->vss_hpf_cfg = value; in wm8958_put_vss_hpf_enum()
604 ucontrol->value.enumerated.item[0] = wm8994->vss_hpf_cfg; in wm8958_get_vss_hpf_enum()
612 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; in wm8958_vss_info()
613 uinfo->count = 1; in wm8958_vss_info()
614 uinfo->value.integer.min = 0; in wm8958_vss_info()
615 uinfo->value.integer.max = 1; in wm8958_vss_info()
622 int vss = kcontrol->private_value; in wm8958_vss_get()
626 ucontrol->value.integer.value[0] = wm8994->vss_ena[vss]; in wm8958_vss_get()
634 int vss = kcontrol->private_value; in wm8958_vss_put()
638 if (wm8994->vss_ena[vss] == ucontrol->value.integer.value[0]) in wm8958_vss_put()
641 if (ucontrol->value.integer.value[0] > 1) in wm8958_vss_put()
642 return -EINVAL; in wm8958_vss_put()
644 if (!wm8994->mbc_vss) in wm8958_vss_put()
645 return -ENODEV; in wm8958_vss_put()
648 dev_dbg(component->dev, "DSP2 active on %d already\n", vss); in wm8958_vss_put()
649 return -EBUSY; in wm8958_vss_put()
652 if (wm8994->enh_eq_ena[vss]) in wm8958_vss_put()
653 return -EBUSY; in wm8958_vss_put()
655 wm8994->vss_ena[vss] = ucontrol->value.integer.value[0]; in wm8958_vss_put()
657 wm8958_dsp_apply(component, vss, wm8994->vss_ena[vss]); in wm8958_vss_put()
673 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; in wm8958_hpf_info()
674 uinfo->count = 1; in wm8958_hpf_info()
675 uinfo->value.integer.min = 0; in wm8958_hpf_info()
676 uinfo->value.integer.max = 1; in wm8958_hpf_info()
683 int hpf = kcontrol->private_value; in wm8958_hpf_get()
688 ucontrol->value.integer.value[0] = wm8994->hpf1_ena[hpf % 3]; in wm8958_hpf_get()
690 ucontrol->value.integer.value[0] = wm8994->hpf2_ena[hpf % 3]; in wm8958_hpf_get()
698 int hpf = kcontrol->private_value; in wm8958_hpf_put()
703 if (wm8994->hpf1_ena[hpf % 3] == in wm8958_hpf_put()
704 ucontrol->value.integer.value[0]) in wm8958_hpf_put()
707 if (wm8994->hpf2_ena[hpf % 3] == in wm8958_hpf_put()
708 ucontrol->value.integer.value[0]) in wm8958_hpf_put()
712 if (ucontrol->value.integer.value[0] > 1) in wm8958_hpf_put()
713 return -EINVAL; in wm8958_hpf_put()
715 if (!wm8994->mbc_vss) in wm8958_hpf_put()
716 return -ENODEV; in wm8958_hpf_put()
719 dev_dbg(component->dev, "DSP2 active on %d already\n", hpf); in wm8958_hpf_put()
720 return -EBUSY; in wm8958_hpf_put()
723 if (wm8994->enh_eq_ena[hpf % 3]) in wm8958_hpf_put()
724 return -EBUSY; in wm8958_hpf_put()
727 wm8994->hpf1_ena[hpf % 3] = ucontrol->value.integer.value[0]; in wm8958_hpf_put()
729 wm8994->hpf2_ena[hpf % 3] = ucontrol->value.integer.value[0]; in wm8958_hpf_put()
731 wm8958_dsp_apply(component, hpf % 3, ucontrol->value.integer.value[0]); in wm8958_hpf_put()
748 struct wm8994 *control = wm8994->wm8994; in wm8958_put_enh_eq_enum()
749 int value = ucontrol->value.enumerated.item[0]; in wm8958_put_enh_eq_enum()
755 return -EBUSY; in wm8958_put_enh_eq_enum()
757 if (value >= control->pdata.num_enh_eq_cfgs) in wm8958_put_enh_eq_enum()
758 return -EINVAL; in wm8958_put_enh_eq_enum()
760 wm8994->enh_eq_cfg = value; in wm8958_put_enh_eq_enum()
771 ucontrol->value.enumerated.item[0] = wm8994->enh_eq_cfg; in wm8958_get_enh_eq_enum()
779 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; in wm8958_enh_eq_info()
780 uinfo->count = 1; in wm8958_enh_eq_info()
781 uinfo->value.integer.min = 0; in wm8958_enh_eq_info()
782 uinfo->value.integer.max = 1; in wm8958_enh_eq_info()
789 int eq = kcontrol->private_value; in wm8958_enh_eq_get()
793 ucontrol->value.integer.value[0] = wm8994->enh_eq_ena[eq]; in wm8958_enh_eq_get()
801 int eq = kcontrol->private_value; in wm8958_enh_eq_put()
805 if (wm8994->enh_eq_ena[eq] == ucontrol->value.integer.value[0]) in wm8958_enh_eq_put()
808 if (ucontrol->value.integer.value[0] > 1) in wm8958_enh_eq_put()
809 return -EINVAL; in wm8958_enh_eq_put()
811 if (!wm8994->enh_eq) in wm8958_enh_eq_put()
812 return -ENODEV; in wm8958_enh_eq_put()
815 dev_dbg(component->dev, "DSP2 active on %d already\n", eq); in wm8958_enh_eq_put()
816 return -EBUSY; in wm8958_enh_eq_put()
819 if (wm8994->mbc_ena[eq] || wm8994->vss_ena[eq] || in wm8958_enh_eq_put()
820 wm8994->hpf1_ena[eq] || wm8994->hpf2_ena[eq]) in wm8958_enh_eq_put()
821 return -EBUSY; in wm8958_enh_eq_put()
823 wm8994->enh_eq_ena[eq] = ucontrol->value.integer.value[0]; in wm8958_enh_eq_put()
825 wm8958_dsp_apply(component, eq, ucontrol->value.integer.value[0]); in wm8958_enh_eq_put()
861 static void wm8958_enh_eq_loaded(const struct firmware *fw, void *context) in wm8958_enh_eq_loaded() argument
866 if (fw && (wm8958_dsp2_fw(component, "ENH_EQ", fw, true) == 0)) { in wm8958_enh_eq_loaded()
867 mutex_lock(&wm8994->fw_lock); in wm8958_enh_eq_loaded()
868 wm8994->enh_eq = fw; in wm8958_enh_eq_loaded()
869 mutex_unlock(&wm8994->fw_lock); in wm8958_enh_eq_loaded()
873 static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context) in wm8958_mbc_vss_loaded() argument
878 if (fw && (wm8958_dsp2_fw(component, "MBC+VSS", fw, true) == 0)) { in wm8958_mbc_vss_loaded()
879 mutex_lock(&wm8994->fw_lock); in wm8958_mbc_vss_loaded()
880 wm8994->mbc_vss = fw; in wm8958_mbc_vss_loaded()
881 mutex_unlock(&wm8994->fw_lock); in wm8958_mbc_vss_loaded()
885 static void wm8958_mbc_loaded(const struct firmware *fw, void *context) in wm8958_mbc_loaded() argument
890 if (fw && (wm8958_dsp2_fw(component, "MBC", fw, true) == 0)) { in wm8958_mbc_loaded()
891 mutex_lock(&wm8994->fw_lock); in wm8958_mbc_loaded()
892 wm8994->mbc = fw; in wm8958_mbc_loaded()
893 mutex_unlock(&wm8994->fw_lock); in wm8958_mbc_loaded()
900 struct wm8994 *control = wm8994->wm8994; in wm8958_dsp2_init()
901 struct wm8994_pdata *pdata = &control->pdata; in wm8958_dsp2_init()
904 wm8994->dsp_active = -1; in wm8958_dsp2_init()
916 "wm8958_mbc.wfw", component->dev, GFP_KERNEL, in wm8958_dsp2_init()
919 "wm8958_mbc_vss.wfw", component->dev, GFP_KERNEL, in wm8958_dsp2_init()
922 "wm8958_enh_eq.wfw", component->dev, GFP_KERNEL, in wm8958_dsp2_init()
925 if (pdata->num_mbc_cfgs) { in wm8958_dsp2_init()
927 SOC_ENUM_EXT("MBC Mode", wm8994->mbc_enum, in wm8958_dsp2_init()
932 wm8994->mbc_texts = kmalloc_array(pdata->num_mbc_cfgs, in wm8958_dsp2_init()
935 if (!wm8994->mbc_texts) in wm8958_dsp2_init()
938 for (i = 0; i < pdata->num_mbc_cfgs; i++) in wm8958_dsp2_init()
939 wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; in wm8958_dsp2_init()
941 wm8994->mbc_enum.items = pdata->num_mbc_cfgs; in wm8958_dsp2_init()
942 wm8994->mbc_enum.texts = wm8994->mbc_texts; in wm8958_dsp2_init()
944 ret = snd_soc_add_component_controls(wm8994->hubs.component, in wm8958_dsp2_init()
947 dev_err(wm8994->hubs.component->dev, in wm8958_dsp2_init()
951 if (pdata->num_vss_cfgs) { in wm8958_dsp2_init()
953 SOC_ENUM_EXT("VSS Mode", wm8994->vss_enum, in wm8958_dsp2_init()
958 wm8994->vss_texts = kmalloc_array(pdata->num_vss_cfgs, in wm8958_dsp2_init()
961 if (!wm8994->vss_texts) in wm8958_dsp2_init()
964 for (i = 0; i < pdata->num_vss_cfgs; i++) in wm8958_dsp2_init()
965 wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; in wm8958_dsp2_init()
967 wm8994->vss_enum.items = pdata->num_vss_cfgs; in wm8958_dsp2_init()
968 wm8994->vss_enum.texts = wm8994->vss_texts; in wm8958_dsp2_init()
970 ret = snd_soc_add_component_controls(wm8994->hubs.component, in wm8958_dsp2_init()
973 dev_err(wm8994->hubs.component->dev, in wm8958_dsp2_init()
977 if (pdata->num_vss_hpf_cfgs) { in wm8958_dsp2_init()
979 SOC_ENUM_EXT("VSS HPF Mode", wm8994->vss_hpf_enum, in wm8958_dsp2_init()
985 wm8994->vss_hpf_texts = kmalloc_array(pdata->num_vss_hpf_cfgs, in wm8958_dsp2_init()
988 if (!wm8994->vss_hpf_texts) in wm8958_dsp2_init()
991 for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) in wm8958_dsp2_init()
992 wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; in wm8958_dsp2_init()
994 wm8994->vss_hpf_enum.items = pdata->num_vss_hpf_cfgs; in wm8958_dsp2_init()
995 wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; in wm8958_dsp2_init()
997 ret = snd_soc_add_component_controls(wm8994->hubs.component, in wm8958_dsp2_init()
1000 dev_err(wm8994->hubs.component->dev, in wm8958_dsp2_init()
1005 if (pdata->num_enh_eq_cfgs) { in wm8958_dsp2_init()
1007 SOC_ENUM_EXT("Enhanced EQ Mode", wm8994->enh_eq_enum, in wm8958_dsp2_init()
1013 wm8994->enh_eq_texts = kmalloc_array(pdata->num_enh_eq_cfgs, in wm8958_dsp2_init()
1016 if (!wm8994->enh_eq_texts) in wm8958_dsp2_init()
1019 for (i = 0; i < pdata->num_enh_eq_cfgs; i++) in wm8958_dsp2_init()
1020 wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; in wm8958_dsp2_init()
1022 wm8994->enh_eq_enum.items = pdata->num_enh_eq_cfgs; in wm8958_dsp2_init()
1023 wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; in wm8958_dsp2_init()
1025 ret = snd_soc_add_component_controls(wm8994->hubs.component, in wm8958_dsp2_init()
1028 dev_err(wm8994->hubs.component->dev, in wm8958_dsp2_init()